diff --git a/CMakeLists.txt b/CMakeLists.txt
index 31597f399..f9364fdd2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.0)
project(SRB2
- VERSION 2.1.17
+ VERSION 2.1.19
LANGUAGES C)
if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR})
diff --git a/SRB2.cbp b/SRB2.cbp
index 88dc400fe..2a1eb87b8 100644
--- a/SRB2.cbp
+++ b/SRB2.cbp
@@ -1174,6 +1174,39 @@ HW3SOUND for 3D hardware sound support
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/appveyor.yml b/appveyor.yml
index b0544a90b..23b9b6281 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,4 +1,4 @@
-version: 2.1.17.{branch}-{build}
+version: 2.1.19.{branch}-{build}
os: MinGW
environment:
@@ -47,7 +47,7 @@ before_build:
- upx -V
- ccache -V
- ccache -s
-- set SRB2_MFLAGS=-C src MINGW=1 WARNINGMODE=1 GCC63=1 CCACHE=1
+- set SRB2_MFLAGS=-C src MINGW=1 WARNINGMODE=1 GCC63=1 CCACHE=1 NOOBJDUMP=1
build_script:
- cmd: mingw32-make.exe %SRB2_MFLAGS% %CONFIGURATION%=1 clean
@@ -58,26 +58,29 @@ after_build:
- cmd: git rev-parse --short %APPVEYOR_REPO_COMMIT%>%TMP%/gitshort.txt
- cmd: set /P GITSHORT=<%TMP%/gitshort.txt
- set BUILD_ARCHIVE=%APPVEYOR_REPO_BRANCH%-%GITSHORT%-%CONFIGURATION%.7z
+- set BUILDSARCHIVE=%APPVEYOR_REPO_BRANCH%-%CONFIGURATION%.7z
- cmd: 7z a %BUILD_ARCHIVE% bin\Mingw\Release -xr!.gitignore
- appveyor PushArtifact %BUILD_ARCHIVE%
+- cmd: copy %BUILD_ARCHIVE% %BUILDSARCHIVE%
+- appveyor PushArtifact %BUILDSARCHIVE%
test: off
-deploy:
- - provider: FTP
- protocol: ftps
- host:
- secure: NsLJEPIBvmwCOj8Tg8RoRQ==
- username:
- secure: ejxi5mvk7oLYu7QtbYojajEPigMy0mokaKhuEVuDZcA=
- password:
- secure: Hbn6Uy3lT0YZ88yFJ3aW4w==
- folder: appveyor
- application:
- active_mode: false
- on:
- branch: master
- appveyor_repo_tag: true
+#deploy:
+# - provider: FTP
+# protocol: ftps
+# host:
+# secure: NsLJEPIBvmwCOj8Tg8RoRQ==
+# username:
+# secure: ejxi5mvk7oLYu7QtbYojajEPigMy0mokaKhuEVuDZcA=
+# password:
+# secure: Hbn6Uy3lT0YZ88yFJ3aW4w==
+# folder: appveyor
+# application:
+# active_mode: false
+# on:
+# branch: master
+# appveyor_repo_tag: true
on_finish:
diff --git a/bin/Mingw/Debug/.gitignore b/bin/Mingw/Debug/.gitignore
index e431dca5d..834f313e3 100644
--- a/bin/Mingw/Debug/.gitignore
+++ b/bin/Mingw/Debug/.gitignore
@@ -1,3 +1,3 @@
-/srb2sdl.exe
-/srb2win.exe
-/r_opengl.dll
+*.exe
+*.mo
+r_opengl.dll
diff --git a/bin/Mingw/Release/.gitignore b/bin/Mingw/Release/.gitignore
index e431dca5d..834f313e3 100644
--- a/bin/Mingw/Release/.gitignore
+++ b/bin/Mingw/Release/.gitignore
@@ -1,3 +1,3 @@
-/srb2sdl.exe
-/srb2win.exe
-/r_opengl.dll
+*.exe
+*.mo
+r_opengl.dll
diff --git a/objs/.gitignore b/objs/.gitignore
new file mode 100644
index 000000000..35ecd6def
--- /dev/null
+++ b/objs/.gitignore
@@ -0,0 +1,8 @@
+#All folders
+SRB2.res
+depend.dep
+depend.ped
+*.o
+#VC9 folder only
+/VC9/Win32
+/VC9/x64
diff --git a/objs/DC/SDL/Debug/.gitignore b/objs/DC/SDL/Debug/.gitignore
index 867fcb4e0..42c6dc2c6 100644
--- a/objs/DC/SDL/Debug/.gitignore
+++ b/objs/DC/SDL/Debug/.gitignore
@@ -1 +1,2 @@
-/depend.dep
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/DC/SDL/Release/.gitignore b/objs/DC/SDL/Release/.gitignore
index 867fcb4e0..42c6dc2c6 100644
--- a/objs/DC/SDL/Release/.gitignore
+++ b/objs/DC/SDL/Release/.gitignore
@@ -1 +1,2 @@
-/depend.dep
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/Linux/SDL/Debug/.gitignore b/objs/Linux/SDL/Debug/.gitignore
index 8f6d0bdcd..42c6dc2c6 100644
--- a/objs/Linux/SDL/Debug/.gitignore
+++ b/objs/Linux/SDL/Debug/.gitignore
@@ -1,2 +1,2 @@
-/depend.dep
-/*.o
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/Linux/SDL/Release/.gitignore b/objs/Linux/SDL/Release/.gitignore
index 8f6d0bdcd..42c6dc2c6 100644
--- a/objs/Linux/SDL/Release/.gitignore
+++ b/objs/Linux/SDL/Release/.gitignore
@@ -1,2 +1,2 @@
-/depend.dep
-/*.o
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/Linux64/SDL/Debug/.gitignore b/objs/Linux64/SDL/Debug/.gitignore
index 8f6d0bdcd..42c6dc2c6 100644
--- a/objs/Linux64/SDL/Debug/.gitignore
+++ b/objs/Linux64/SDL/Debug/.gitignore
@@ -1,2 +1,2 @@
-/depend.dep
-/*.o
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/Linux64/SDL/Release/.gitignore b/objs/Linux64/SDL/Release/.gitignore
index 8f6d0bdcd..42c6dc2c6 100644
--- a/objs/Linux64/SDL/Release/.gitignore
+++ b/objs/Linux64/SDL/Release/.gitignore
@@ -1,2 +1,2 @@
-/depend.dep
-/*.o
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/Mingw/Debug/.gitignore b/objs/Mingw/Debug/.gitignore
index da4b3e912..42c6dc2c6 100644
--- a/objs/Mingw/Debug/.gitignore
+++ b/objs/Mingw/Debug/.gitignore
@@ -1,3 +1,2 @@
-/SRB2.res
-/depend.dep
-/*.o
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/Mingw/Release/.gitignore b/objs/Mingw/Release/.gitignore
index da4b3e912..42c6dc2c6 100644
--- a/objs/Mingw/Release/.gitignore
+++ b/objs/Mingw/Release/.gitignore
@@ -1,3 +1,2 @@
-/SRB2.res
-/depend.dep
-/*.o
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/Mingw/SDL/Debug/.gitignore b/objs/Mingw/SDL/Debug/.gitignore
index da4b3e912..42c6dc2c6 100644
--- a/objs/Mingw/SDL/Debug/.gitignore
+++ b/objs/Mingw/SDL/Debug/.gitignore
@@ -1,3 +1,2 @@
-/SRB2.res
-/depend.dep
-/*.o
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/Mingw/SDL/Release/.gitignore b/objs/Mingw/SDL/Release/.gitignore
index da4b3e912..42c6dc2c6 100644
--- a/objs/Mingw/SDL/Release/.gitignore
+++ b/objs/Mingw/SDL/Release/.gitignore
@@ -1,3 +1,2 @@
-/SRB2.res
-/depend.dep
-/*.o
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/Mingw64/Debug/.gitignore b/objs/Mingw64/Debug/.gitignore
index da4b3e912..42c6dc2c6 100644
--- a/objs/Mingw64/Debug/.gitignore
+++ b/objs/Mingw64/Debug/.gitignore
@@ -1,3 +1,2 @@
-/SRB2.res
-/depend.dep
-/*.o
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/Mingw64/Release/.gitignore b/objs/Mingw64/Release/.gitignore
index da4b3e912..42c6dc2c6 100644
--- a/objs/Mingw64/Release/.gitignore
+++ b/objs/Mingw64/Release/.gitignore
@@ -1,3 +1,2 @@
-/SRB2.res
-/depend.dep
-/*.o
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/Mingw64/SDL/Debug/.gitignore b/objs/Mingw64/SDL/Debug/.gitignore
index da4b3e912..42c6dc2c6 100644
--- a/objs/Mingw64/SDL/Debug/.gitignore
+++ b/objs/Mingw64/SDL/Debug/.gitignore
@@ -1,3 +1,2 @@
-/SRB2.res
-/depend.dep
-/*.o
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/Mingw64/SDL/Release/.gitignore b/objs/Mingw64/SDL/Release/.gitignore
index da4b3e912..42c6dc2c6 100644
--- a/objs/Mingw64/SDL/Release/.gitignore
+++ b/objs/Mingw64/SDL/Release/.gitignore
@@ -1,3 +1,2 @@
-/SRB2.res
-/depend.dep
-/*.o
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/PS3/SDL/Debug/.gitignore b/objs/PS3/SDL/Debug/.gitignore
index 8f6d0bdcd..42c6dc2c6 100644
--- a/objs/PS3/SDL/Debug/.gitignore
+++ b/objs/PS3/SDL/Debug/.gitignore
@@ -1,2 +1,2 @@
-/depend.dep
-/*.o
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/PS3/SDL/Release/.gitignore b/objs/PS3/SDL/Release/.gitignore
index 8f6d0bdcd..42c6dc2c6 100644
--- a/objs/PS3/SDL/Release/.gitignore
+++ b/objs/PS3/SDL/Release/.gitignore
@@ -1,2 +1,2 @@
-/depend.dep
-/*.o
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/PSP/SDL/Release/.gitignore b/objs/PSP/SDL/Release/.gitignore
index 867fcb4e0..42c6dc2c6 100644
--- a/objs/PSP/SDL/Release/.gitignore
+++ b/objs/PSP/SDL/Release/.gitignore
@@ -1 +1,2 @@
-/depend.dep
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/SDL/Release/.gitignore b/objs/SDL/Release/.gitignore
index 4a262f94f..42c6dc2c6 100644
--- a/objs/SDL/Release/.gitignore
+++ b/objs/SDL/Release/.gitignore
@@ -1 +1,2 @@
-/depend.ped
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/VC/.gitignore b/objs/VC/.gitignore
index e69de29bb..42c6dc2c6 100644
--- a/objs/VC/.gitignore
+++ b/objs/VC/.gitignore
@@ -0,0 +1,2 @@
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/VC9/.gitignore b/objs/VC9/.gitignore
index 205fe45de..42c6dc2c6 100644
--- a/objs/VC9/.gitignore
+++ b/objs/VC9/.gitignore
@@ -1,2 +1,2 @@
-/Win32
-/x64
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/Wii/SDL/Debug/.gitignore b/objs/Wii/SDL/Debug/.gitignore
index 8f6d0bdcd..42c6dc2c6 100644
--- a/objs/Wii/SDL/Debug/.gitignore
+++ b/objs/Wii/SDL/Debug/.gitignore
@@ -1,2 +1,2 @@
-/depend.dep
-/*.o
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/Wii/SDL/Release/.gitignore b/objs/Wii/SDL/Release/.gitignore
index 8f6d0bdcd..42c6dc2c6 100644
--- a/objs/Wii/SDL/Release/.gitignore
+++ b/objs/Wii/SDL/Release/.gitignore
@@ -1,2 +1,2 @@
-/depend.dep
-/*.o
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/WinCE/SDL/Release/.gitignore b/objs/WinCE/SDL/Release/.gitignore
index 867fcb4e0..42c6dc2c6 100644
--- a/objs/WinCE/SDL/Release/.gitignore
+++ b/objs/WinCE/SDL/Release/.gitignore
@@ -1 +1,2 @@
-/depend.dep
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/djgppdos/Debug/.gitignore b/objs/djgppdos/Debug/.gitignore
index 867fcb4e0..42c6dc2c6 100644
--- a/objs/djgppdos/Debug/.gitignore
+++ b/objs/djgppdos/Debug/.gitignore
@@ -1 +1,2 @@
-/depend.dep
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/djgppdos/Release/.gitignore b/objs/djgppdos/Release/.gitignore
index 867fcb4e0..42c6dc2c6 100644
--- a/objs/djgppdos/Release/.gitignore
+++ b/objs/djgppdos/Release/.gitignore
@@ -1 +1,2 @@
-/depend.dep
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/nds/Debug/.gitignore b/objs/nds/Debug/.gitignore
index 8f6d0bdcd..42c6dc2c6 100644
--- a/objs/nds/Debug/.gitignore
+++ b/objs/nds/Debug/.gitignore
@@ -1,2 +1,2 @@
-/depend.dep
-/*.o
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/objs/nds/Release/.gitignore b/objs/nds/Release/.gitignore
index 8f6d0bdcd..42c6dc2c6 100644
--- a/objs/nds/Release/.gitignore
+++ b/objs/nds/Release/.gitignore
@@ -1,2 +1,2 @@
-/depend.dep
-/*.o
+# DON'T REMOVE
+# This keeps the folder from disappearing
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index da8438a59..6a8b7e3f1 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -351,6 +351,7 @@ if(${SRB2_CONFIG_HWRENDER})
set(SRB2_HWRENDER_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_bsp.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_cache.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_draw.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.c
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.c
@@ -359,6 +360,7 @@ if(${SRB2_CONFIG_HWRENDER})
)
set (SRB2_HWRENDER_HEADERS
+ ${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_clip.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_data.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_defs.h
${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_dll.h
diff --git a/src/Makefile b/src/Makefile
index 76f013c52..27569b36c 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -259,7 +259,7 @@ ifndef DC
endif
OPTS+=-DHWRENDER
OBJS+=$(OBJDIR)/hw_bsp.o $(OBJDIR)/hw_draw.o $(OBJDIR)/hw_light.o \
- $(OBJDIR)/hw_main.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o
+ $(OBJDIR)/hw_main.o $(OBJDIR)/hw_clip.o $(OBJDIR)/hw_md2.o $(OBJDIR)/hw_cache.o $(OBJDIR)/hw_trick.o
endif
ifdef NOHS
@@ -511,13 +511,11 @@ OBJS:=$(i_main_o) \
# For reference, this is the command I use to build a srb2.pot file from the source code.
# (The listed source files are the ones containing translated strings).
# FILES=""; for file in `find ./ | grep "\.c" | grep -v svn`; do [ "`grep "M_GetText(" $file`" ] && FILES="$FILES $file"; done; xgettext -d srb2 -o locale/srb2.pot -kM_GetText -F --no-wrap $FILES
-ifndef NOGETTEXT
ifdef GETTEXT
POS:=$(BIN)/en.mo
OPTS+=-DGETTEXT
endif
-endif
ifdef DJGPPDOS
all: pre-build $(BIN)/$(EXENAME)
@@ -705,7 +703,7 @@ ifdef MINGW
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
- hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
+ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -c $< -o $@
@@ -713,7 +711,7 @@ else
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
- hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
+ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -I/usr/X11R6/include -c $< -o $@
@@ -866,7 +864,7 @@ ifndef NOHW
$(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
- hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
+ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
@@ -874,7 +872,7 @@ $(OBJDIR)/r_opengl.o: hardware/r_opengl/r_opengl.c hardware/r_opengl/r_opengl.h
$(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
- hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
+ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
@@ -882,7 +880,7 @@ $(OBJDIR)/ogl_win.o: hardware/r_opengl/ogl_win.c hardware/r_opengl/r_opengl.h \
$(OBJDIR)/r_minigl.o: hardware/r_minigl/r_minigl.c hardware/r_opengl/r_opengl.h \
doomdef.h doomtype.h g_state.h m_swap.h hardware/hw_drv.h screen.h \
command.h hardware/hw_data.h hardware/hw_glide.h hardware/hw_defs.h \
- hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h am_map.h \
+ hardware/hw_md2.h hardware/hw_glob.h hardware/hw_main.h hardware/hw_clip.h am_map.h \
d_event.h d_player.h p_pspr.h m_fixed.h tables.h info.h d_think.h \
p_mobj.h doomdata.h d_ticcmd.h r_defs.h hardware/hw_dll.h
$(CC) $(CFLAGS) $(WFLAGS) -D_WINDOWS -mwindows -c $< -o $@
diff --git a/src/Makefile.cfg b/src/Makefile.cfg
index 80d018c4b..5bf7f247d 100644
--- a/src/Makefile.cfg
+++ b/src/Makefile.cfg
@@ -283,9 +283,6 @@ else
ifdef LINUX
NASMFORMAT=elf -DLINUX
SDL=1
-ifndef NOGETTEXT
- GETTEXT=1
-endif
ifdef LINUX64
OBJDIR:=$(OBJDIR)/Linux64
BIN:=$(BIN)/Linux64
@@ -321,9 +318,6 @@ else
ifdef MINGW64
INTERFACE=win32
#NASMFORMAT=win64
-ifndef NOGETTEXT
- #GETTEXT=1
-endif
OBJDIR:=$(OBJDIR)/Mingw64
BIN:=$(BIN)/Mingw64
else
@@ -354,9 +348,6 @@ else
ifdef MINGW
INTERFACE=win32
NASMFORMAT=win32
-ifndef NOGETTEXT
- GETTEXT=1
-endif
OBJDIR:=$(OBJDIR)/Mingw
BIN:=$(BIN)/Mingw
else
diff --git a/src/console.c b/src/console.c
index 3702dd560..54fde7af7 100644
--- a/src/console.c
+++ b/src/console.c
@@ -33,6 +33,7 @@
#include "i_system.h"
#include "d_main.h"
#include "m_menu.h"
+#include "filesrch.h"
#ifdef _WINDOWS
#include "win32/win_main.h"
@@ -1275,12 +1276,15 @@ void CONS_Alert(alerttype_t level, const char *fmt, ...)
switch (level)
{
case CONS_NOTICE:
+ // no notice for notices, hehe
CONS_Printf("\x83" "%s" "\x80 ", M_GetText("NOTICE:"));
break;
case CONS_WARNING:
+ refreshdirmenu |= REFRESHDIR_WARNING;
CONS_Printf("\x82" "%s" "\x80 ", M_GetText("WARNING:"));
break;
case CONS_ERROR:
+ refreshdirmenu |= REFRESHDIR_ERROR;
CONS_Printf("\x85" "%s" "\x80 ", M_GetText("ERROR:"));
break;
}
@@ -1394,32 +1398,32 @@ static void CON_DrawInput(void)
if (input_sel < c)
V_DrawFill(x, y, charwidth*3, (10 * con_scalefactor), 77 | V_NOSCALESTART);
for (i = 0; i < 3; ++i, x += charwidth)
- V_DrawCharacter(x, y, '.' | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, !cv_allcaps.value);
+ V_DrawCharacter(x, y, '.' | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, true);
}
else
- V_DrawCharacter(x-charwidth, y, CON_PROMPTCHAR | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, !cv_allcaps.value);
+ V_DrawCharacter(x-charwidth, y, CON_PROMPTCHAR | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, true);
for (cend = c + clen; c < cend; ++c, x += charwidth)
{
if ((input_sel > c && input_cur <= c) || (input_sel <= c && input_cur > c))
{
V_DrawFill(x, y, charwidth, (10 * con_scalefactor), 77 | V_NOSCALESTART);
- V_DrawCharacter(x, y, p[c] | cv_constextsize.value | V_YELLOWMAP | V_NOSCALESTART, !cv_allcaps.value);
+ V_DrawCharacter(x, y, p[c] | cv_constextsize.value | V_YELLOWMAP | V_NOSCALESTART, true);
}
else
- V_DrawCharacter(x, y, p[c] | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
+ V_DrawCharacter(x, y, p[c] | cv_constextsize.value | V_NOSCALESTART, true);
if (c == input_cur && con_tick >= 4)
- V_DrawCharacter(x, y + (con_scalefactor*2), '_' | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
+ V_DrawCharacter(x, y + (con_scalefactor*2), '_' | cv_constextsize.value | V_NOSCALESTART, true);
}
if (cend == input_cur && con_tick >= 4)
- V_DrawCharacter(x, y + (con_scalefactor*2), '_' | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
+ V_DrawCharacter(x, y + (con_scalefactor*2), '_' | cv_constextsize.value | V_NOSCALESTART, true);
if (rellip)
{
if (input_sel > cend)
V_DrawFill(x, y, charwidth*3, (10 * con_scalefactor), 77 | V_NOSCALESTART);
for (i = 0; i < 3; ++i, x += charwidth)
- V_DrawCharacter(x, y, '.' | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, !cv_allcaps.value);
+ V_DrawCharacter(x, y, '.' | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, true);
}
}
@@ -1465,11 +1469,11 @@ static void CON_DrawHudlines(void)
else
{
//charwidth = SHORT(hu_font['A'-HU_FONTSTART]->width) * con_scalefactor;
- V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
+ V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, true);
}
}
- //V_DrawCharacter(x, y, (p[c]&0xff) | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
+ //V_DrawCharacter(x, y, (p[c]&0xff) | cv_constextsize.value | V_NOSCALESTART, true);
y += charheight;
}
@@ -1607,7 +1611,7 @@ static void CON_DrawConsole(void)
charflags = (*p & 0x7f) << V_CHARCOLORSHIFT;
p++;
}
- V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
+ V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, true);
}
}
diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index 2db27a693..3878d8795 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -768,8 +768,16 @@ static void resynch_read_player(resynch_pak *rsp)
players[i].mo->scalespeed = LONG(rsp->scalespeed);
// And finally, SET THE MOBJ SKIN damn it.
- players[i].mo->skin = &skins[players[i].skin];
- players[i].mo->color = players[i].skincolor;
+ if ((players[i].powers[pw_carry] == CR_NIGHTSMODE) && (skins[players[i].skin].sprites[SPR2_NGT0].numframes == 0))
+ {
+ players[i].mo->skin = &skins[DEFAULTNIGHTSSKIN];
+ players[i].mo->color = skins[DEFAULTNIGHTSSKIN].prefcolor; // this will be corrected by thinker to super flash
+ }
+ else
+ {
+ players[i].mo->skin = &skins[players[i].skin];
+ players[i].mo->color = players[i].skincolor; // this will be corrected by thinker to super flash/mario star
+ }
P_SetThingPosition(players[i].mo);
}
@@ -883,6 +891,7 @@ static inline void resynch_write_others(resynchend_pak *rst)
UINT8 i;
rst->ingame = 0;
+ rst->outofcoop = 0;
for (i = 0; i < MAXPLAYERS; ++i)
{
@@ -899,6 +908,8 @@ static inline void resynch_write_others(resynchend_pak *rst)
if (!players[i].spectator)
rst->ingame |= (1<outofcoop |= (1<ctfteam[i] = (INT32)LONG(players[i].ctfteam);
rst->score[i] = (UINT32)LONG(players[i].score);
rst->numboxes[i] = SHORT(players[i].numboxes);
@@ -915,11 +926,13 @@ static inline void resynch_read_others(resynchend_pak *p)
{
UINT8 i;
UINT32 loc_ingame = (UINT32)LONG(p->ingame);
+ UINT32 loc_outofcoop = (UINT32)LONG(p->outofcoop);
for (i = 0; i < MAXPLAYERS; ++i)
{
// We don't care if they're in the game or not, just write all the data.
players[i].spectator = !(loc_ingame & (1<ctfteam[i]); // no, 0 does not mean spectator, at least not in Match
players[i].score = (UINT32)LONG(p->score[i]);
players[i].numboxes = SHORT(p->numboxes[i]);
@@ -1319,7 +1332,7 @@ static void SV_SendPlayerInfo(INT32 node)
netbuffer->u.playerinfo[i].skin = (UINT8)players[i].skin;
// Extra data
- netbuffer->u.playerinfo[i].data = players[i].skincolor;
+ netbuffer->u.playerinfo[i].data = 0; //players[i].skincolor;
if (players[i].pflags & PF_TAGIT)
netbuffer->u.playerinfo[i].data |= 0x20;
@@ -1563,8 +1576,6 @@ static void CL_LoadReceivedSavegame(void)
automapactive = false;
// load a base level
- playerdeadview = false;
-
if (P_LoadNetGame())
{
const INT32 actnum = mapheaderinfo[gamemap-1]->actnum;
@@ -1742,9 +1753,7 @@ static boolean CL_ServerConnectionSearchTicker(boolean viams, tic_t *asksent)
{
#ifndef NONET
INT32 i;
-#endif
-#ifndef NONET
// serverlist is updated by GetPacket function
if (serverlistcount > 0)
{
@@ -1778,7 +1787,20 @@ static boolean CL_ServerConnectionSearchTicker(boolean viams, tic_t *asksent)
serverlist[i].info.fileneeded);
CONS_Printf(M_GetText("Checking files...\n"));
i = CL_CheckFiles();
- if (i == 2) // cannot join for some reason
+ if (i == 3) // too many files
+ {
+ D_QuitNetGame();
+ CL_Reset();
+ D_StartTitle();
+ M_StartMessage(M_GetText(
+ "You have too many WAD files loaded\n"
+ "to add ones the server is using.\n"
+ "Please restart SRB2 before connecting.\n\n"
+ "Press ESC\n"
+ ), NULL, MM_NOTHING);
+ return false;
+ }
+ else if (i == 2) // cannot join for some reason
{
D_QuitNetGame();
CL_Reset();
@@ -2518,12 +2540,18 @@ static void Command_Nodes(void)
static void Command_Ban(void)
{
- if (COM_Argc() == 1)
+ if (COM_Argc() < 2)
{
CONS_Printf(M_GetText("Ban : ban and kick a player\n"));
return;
}
+ if (!netgame) // Don't kick Tails in splitscreen!
+ {
+ CONS_Printf(M_GetText("This only works in a netgame.\n"));
+ return;
+ }
+
if (server || adminplayer == consoleplayer)
{
XBOXSTATIC UINT8 buf[3 + MAX_REASONLENGTH];
@@ -2533,9 +2561,10 @@ static void Command_Ban(void)
if (pn == -1 || pn == 0)
return;
- else
- WRITEUINT8(p, pn);
- if (I_Ban && !I_Ban(node))
+
+ WRITEUINT8(p, pn);
+
+ if (server && I_Ban && !I_Ban(node)) // only the server is allowed to do this right now
{
CONS_Alert(CONS_WARNING, M_GetText("Too many bans! Geez, that's a lot of people you're excluding...\n"));
WRITEUINT8(p, KICK_MSG_GO_AWAY);
@@ -2543,7 +2572,8 @@ static void Command_Ban(void)
}
else
{
- Ban_Add(COM_Argv(2));
+ if (server) // only the server is allowed to do this right now
+ Ban_Add(COM_Argv(2));
if (COM_Argc() == 2)
{
@@ -2576,21 +2606,27 @@ static void Command_Ban(void)
static void Command_Kick(void)
{
- XBOXSTATIC UINT8 buf[3 + MAX_REASONLENGTH];
- UINT8 *p = buf;
-
- if (COM_Argc() == 1)
+ if (COM_Argc() < 2)
{
CONS_Printf(M_GetText("kick : kick a player\n"));
return;
}
+ if (!netgame) // Don't kick Tails in splitscreen!
+ {
+ CONS_Printf(M_GetText("This only works in a netgame.\n"));
+ return;
+ }
+
if (server || adminplayer == consoleplayer)
{
+ XBOXSTATIC UINT8 buf[3 + MAX_REASONLENGTH];
+ UINT8 *p = buf;
const SINT8 pn = nametonum(COM_Argv(1));
- WRITESINT8(p, pn);
+
if (pn == -1 || pn == 0)
return;
+
// Special case if we are trying to kick a player who is downloading the game state:
// trigger a timeout instead of kicking them, because a kick would only
// take effect after they have finished downloading
@@ -2599,6 +2635,9 @@ static void Command_Kick(void)
Net_ConnectionTimeout(playernode[pn]);
return;
}
+
+ WRITESINT8(p, pn);
+
if (COM_Argc() == 2)
{
WRITEUINT8(p, KICK_MSG_GO_AWAY);
@@ -2700,12 +2739,14 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
// If a verified admin banned someone, the server needs to know about it.
// If the playernum isn't zero (the server) then the server needs to record the ban.
- if (server && playernum && msg == KICK_MSG_BANNED)
+ if (server && playernum && (msg == KICK_MSG_BANNED || msg == KICK_MSG_CUSTOM_BAN))
{
if (I_Ban && !I_Ban(playernode[(INT32)pnum]))
- {
CONS_Alert(CONS_WARNING, M_GetText("Too many bans! Geez, that's a lot of people you're excluding...\n"));
- }
+#ifndef NONET
+ else
+ Ban_Add(reason);
+#endif
}
switch (msg)
@@ -3403,17 +3444,42 @@ static void HandlePacketFromAwayNode(SINT8 node)
if (node != servernode)
DEBFILE(va("Received packet from unknown host %d\n", node));
+// macro for packets that should only be sent by the server
+// if it is NOT from the server, bail out and close the connection!
+#define SERVERONLY \
+ if (node != servernode) \
+ { \
+ Net_CloseConnection(node); \
+ break; \
+ }
switch (netbuffer->packettype)
{
case PT_ASKINFOVIAMS:
+#if 0
if (server && serverrunning)
{
- INT32 clientnode = I_NetMakeNode(netbuffer->u.msaskinfo.clientaddr);
- SV_SendServerInfo(clientnode, (tic_t)LONG(netbuffer->u.msaskinfo.time));
- SV_SendPlayerInfo(clientnode); // Send extra info
- Net_CloseConnection(clientnode);
- // Don't close connection to MS.
+ INT32 clientnode;
+ if (ms_RoomId < 0) // ignore if we're not actually on the MS right now
+ {
+ Net_CloseConnection(node); // and yes, close connection
+ return;
+ }
+ clientnode = I_NetMakeNode(netbuffer->u.msaskinfo.clientaddr);
+ if (clientnode != -1)
+ {
+ SV_SendServerInfo(clientnode, (tic_t)LONG(netbuffer->u.msaskinfo.time));
+ SV_SendPlayerInfo(clientnode); // Send extra info
+ Net_CloseConnection(clientnode);
+ // Don't close connection to MS...
+ }
+ else
+ Net_CloseConnection(node); // ...unless the IP address is not valid
}
+ else
+ Net_CloseConnection(node); // you're not supposed to get it, so ignore it
+#else
+ Net_CloseConnection(node);
+#endif
break;
case PT_ASKINFO:
@@ -3421,8 +3487,8 @@ static void HandlePacketFromAwayNode(SINT8 node)
{
SV_SendServerInfo(node, (tic_t)LONG(netbuffer->u.askinfo.time));
SV_SendPlayerInfo(node); // Send extra info
- Net_CloseConnection(node);
}
+ Net_CloseConnection(node);
break;
case PT_SERVERREFUSE: // Negative response of client join request
@@ -3431,6 +3497,7 @@ static void HandlePacketFromAwayNode(SINT8 node)
Net_CloseConnection(node);
break;
}
+ SERVERONLY
if (cl_mode == CL_WAITJOINRESPONSE)
{
// Save the reason so it can be displayed after quitting the netgame
@@ -3462,6 +3529,7 @@ static void HandlePacketFromAwayNode(SINT8 node)
Net_CloseConnection(node);
break;
}
+ SERVERONLY
/// \note how would this happen? and is it doing the right thing if it does?
if (cl_mode != CL_WAITJOINRESPONSE)
break;
@@ -3527,13 +3595,18 @@ static void HandlePacketFromAwayNode(SINT8 node)
Net_CloseConnection(node);
break;
}
- else
- Got_Filetxpak();
+ SERVERONLY
+ Got_Filetxpak();
break;
case PT_REQUESTFILE:
if (server)
- Got_RequestFilePak(node);
+ {
+ if (!cv_downloading.value || !Got_RequestFilePak(node))
+ Net_CloseConnection(node); // close connection if one of the requested files could not be sent, or you disabled downloading anyway
+ }
+ else
+ Net_CloseConnection(node); // nope
break;
case PT_NODETIMEOUT:
@@ -3556,6 +3629,7 @@ static void HandlePacketFromAwayNode(SINT8 node)
break; // Ignore it
}
+#undef SERVERONLY
}
/** Handles a packet received from a node that is in game
@@ -3588,6 +3662,8 @@ FILESTAMP
{
// -------------------------------------------- SERVER RECEIVE ----------
case PT_RESYNCHGET:
+ if (client)
+ break;
SV_AcknowledgeResynchAck(netconsole, netbuffer->u.resynchgot);
break;
case PT_CLIENTCMD:
@@ -3654,7 +3730,8 @@ FILESTAMP
}
// Splitscreen cmd
- if (netbuffer->packettype == PT_CLIENT2CMD && nodetoplayer2[node] >= 0)
+ if ((netbuffer->packettype == PT_CLIENT2CMD || netbuffer->packettype == PT_CLIENT2MIS)
+ && nodetoplayer2[node] >= 0)
G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]],
&netbuffer->u.client2pak.cmd2, 1);
@@ -3713,6 +3790,27 @@ FILESTAMP
tic_t tic = maketic;
UINT8 *textcmd;
+ // ignore if the textcmd has a reported size of zero
+ // this shouldn't be sent at all
+ if (!netbuffer->u.textcmd[0])
+ {
+ DEBFILE(va("GetPacket: Textcmd with size 0 detected! (node %u, player %d)\n",
+ node, netconsole));
+ Net_UnAcknowledgePacket(node);
+ break;
+ }
+
+ // ignore if the textcmd size var is actually larger than it should be
+ // BASEPACKETSIZE + 1 (for size) + textcmd[0] should == datalength
+ if (netbuffer->u.textcmd[0] > (size_t)doomcom->datalength-BASEPACKETSIZE-1)
+ {
+ DEBFILE(va("GetPacket: Bad Textcmd packet size! (expected %d, actual %s, node %u, player %d)\n",
+ netbuffer->u.textcmd[0], sizeu1((size_t)doomcom->datalength-BASEPACKETSIZE-1),
+ node, netconsole));
+ Net_UnAcknowledgePacket(node);
+ break;
+ }
+
// check if tic that we are making isn't too large else we cannot send it :(
// doomcom->numslots+1 "+1" since doomcom->numslots can change within this time and sent time
j = software_MAXPACKETLENGTH
@@ -3906,7 +4004,7 @@ FILESTAMP
if (client)
{
INT32 i;
- for (i = 0; i < MAXNETNODES; i++)
+ for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
playerpingtable[i] = (tic_t)netbuffer->u.pingtable[i];
}
@@ -3916,6 +4014,21 @@ FILESTAMP
case PT_SERVERCFG:
break;
case PT_FILEFRAGMENT:
+ // Only accept PT_FILEFRAGMENT from the server.
+ if (node != servernode)
+ {
+ CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_FILEFRAGMENT", node);
+
+ if (server)
+ {
+ XBOXSTATIC UINT8 buf[2];
+ buf[0] = (UINT8)node;
+ buf[1] = KICK_MSG_CON_FAIL;
+ SendNetXCmd(XD_KICK, &buf, 2);
+ }
+
+ break;
+ }
if (client)
Got_Filetxpak();
break;
@@ -4449,8 +4562,8 @@ static inline void PingUpdate(void)
}
//send out our ping packets
- for (i = 0; i < MAXPLAYERS; i++)
- if (playeringame[i])
+ for (i = 0; i < MAXNETNODES; i++)
+ if (nodeingame[i])
HSendPacket(i, true, 0, sizeof(INT32) * MAXPLAYERS);
pingmeasurecount = 1; //Reset count
@@ -4480,20 +4593,15 @@ void NetUpdate(void)
gametime = nowtime;
- if (!(gametime % 255) && netgame && server)
- {
-#ifdef NEWPING
- PingUpdate();
-#endif
- }
-
#ifdef NEWPING
if (server)
{
+ if (netgame && !(gametime % 255))
+ PingUpdate();
// update node latency values so we can take an average later.
- for (i = 0; i < MAXNETNODES; i++)
+ for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
- realpingtable[i] += G_TicsToMilliseconds(GetLag(i));
+ realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i]));
pingmeasurecount++;
}
#endif
diff --git a/src/d_clisrv.h b/src/d_clisrv.h
index 1ca82fdc5..b9a4eec3e 100644
--- a/src/d_clisrv.h
+++ b/src/d_clisrv.h
@@ -136,6 +136,7 @@ typedef struct
fixed_t flagz[2];
UINT32 ingame; // Spectator bit for each player
+ UINT32 outofcoop; // outofcoop bit for each player
INT32 ctfteam[MAXPLAYERS]; // Which team? (can't be 1 bit, since in regular Match there are no teams)
// Resynch game scores and the like all at once
@@ -315,6 +316,7 @@ typedef struct
} ATTRPACK clientconfig_pak;
#define MAXSERVERNAME 32
+#define MAXFILENEEDED 915
// This packet is too large
typedef struct
{
@@ -336,7 +338,7 @@ typedef struct
unsigned char mapmd5[16];
UINT8 actnum;
UINT8 iszone;
- UINT8 fileneeded[915]; // is filled with writexxx (byteptr.h)
+ UINT8 fileneeded[MAXFILENEEDED]; // is filled with writexxx (byteptr.h)
} ATTRPACK serverinfo_pak;
typedef struct
diff --git a/src/d_main.c b/src/d_main.c
index b23ffebb4..7a8a85f25 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -74,6 +74,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
#include "m_cond.h" // condition initialization
#include "fastcmp.h"
#include "keys.h"
+#include "filesrch.h" // refreshdirmenu, mainwadstally
#ifdef CMAKECONFIG
#include "config.h"
@@ -107,8 +108,6 @@ UINT8 window_notinfocus = false;
//
// DEMO LOOP
//
-//static INT32 demosequence;
-static const char *pagename = "MAP1PIC";
static char *startupwadfiles[MAX_WADFILES];
boolean devparm = false; // started game with -devparm
@@ -420,10 +419,13 @@ static void D_Display(void)
}
// Image postprocessing effect
- if (postimgtype)
- V_DoPostProcessor(0, postimgtype, postimgparam);
- if (postimgtype2)
- V_DoPostProcessor(1, postimgtype2, postimgparam2);
+ if (rendermode == render_soft)
+ {
+ if (postimgtype)
+ V_DoPostProcessor(0, postimgtype, postimgparam);
+ if (postimgtype2)
+ V_DoPostProcessor(1, postimgtype2, postimgparam2);
+ }
}
if (lastdraw)
@@ -586,6 +588,8 @@ void D_SRB2Loop(void)
realtics = entertic - oldentertics;
oldentertics = entertic;
+ refreshdirmenu = 0; // not sure where to put this, here as good as any?
+
#ifdef DEBUGFILE
if (!realtics)
if (debugload)
@@ -711,6 +715,7 @@ void D_StartTitle(void)
botskin = 0;
cv_debug = 0;
emeralds = 0;
+ lastmaploaded = 0;
// In case someone exits out at the same time they start a time attack run,
// reset modeattacking
@@ -719,10 +724,16 @@ void D_StartTitle(void)
// empty maptol so mario/etc sounds don't play in sound test when they shouldn't
maptol = 0;
+ // reset to default player stuff
+ COM_BufAddText (va("%s \"%s\"\n",cv_playername.name,cv_defaultplayername.string));
+ COM_BufAddText (va("%s \"%s\"\n",cv_skin.name,cv_defaultskin.string));
+ COM_BufAddText (va("%s \"%s\"\n",cv_playercolor.name,cv_defaultplayercolor.string));
+ COM_BufAddText (va("%s \"%s\"\n",cv_playername2.name,cv_defaultplayername2.string));
+ COM_BufAddText (va("%s \"%s\"\n",cv_skin2.name,cv_defaultskin2.string));
+ COM_BufAddText (va("%s \"%s\"\n",cv_playercolor2.name,cv_defaultplayercolor2.string));
+
gameaction = ga_nothing;
- playerdeadview = false;
displayplayer = consoleplayer = 0;
- //demosequence = -1;
gametype = GT_COOP;
paused = false;
advancedemo = false;
@@ -874,7 +885,7 @@ static void IdentifyVersion(void)
}
#endif
-#if 1 // This section can be deleted when music_new is merged with music.dta
+#ifdef DEVELOP // This section can be deleted when music_new is merged with music.dta
{
const char *musicfile = "music_new.dta";
const char *musicpath = va(pandf,srb2waddir,musicfile);
@@ -887,27 +898,10 @@ static void IdentifyVersion(void)
#endif
}
-/* ======================================================================== */
-// Just print the nice red titlebar like the original SRB2 for DOS.
-/* ======================================================================== */
#ifdef PC_DOS
-static inline void D_Titlebar(char *title1, char *title2)
-{
- // SRB2 banner
- clrscr();
- textattr((BLUE<<4)+WHITE);
- clreol();
- cputs(title1);
-
- // standard srb2 banner
- textattr((RED<<4)+WHITE);
- clreol();
- gotoxy((80-strlen(title2))/2, 2);
- cputs(title2);
- normvideo();
- gotoxy(1,3);
-}
-#endif
+/* ======================================================================== */
+// Code for printing SRB2's title bar in DOS
+/* ======================================================================== */
//
// Center the title string, then add the date and time of compilation.
@@ -936,6 +930,31 @@ static inline void D_MakeTitleString(char *s)
strcpy(s, temp);
}
+static inline void D_Titlebar(void)
+{
+ char title1[82]; // srb2 title banner
+ char title2[82];
+
+ strcpy(title1, "Sonic Robo Blast 2");
+ strcpy(title2, "Sonic Robo Blast 2");
+
+ D_MakeTitleString(title1);
+
+ // SRB2 banner
+ clrscr();
+ textattr((BLUE<<4)+WHITE);
+ clreol();
+ cputs(title1);
+
+ // standard srb2 banner
+ textattr((RED<<4)+WHITE);
+ clreol();
+ gotoxy((80-strlen(title2))/2, 2);
+ cputs(title2);
+ normvideo();
+ gotoxy(1,3);
+}
+#endif
//
// D_SRB2Main
@@ -943,8 +962,6 @@ static inline void D_MakeTitleString(char *s)
void D_SRB2Main(void)
{
INT32 p;
- char srb2[82]; // srb2 title banner
- char title[82];
INT32 pstartmap = 1;
boolean autostart = false;
@@ -987,20 +1004,8 @@ void D_SRB2Main(void)
dedicated = M_CheckParm("-dedicated") != 0;
#endif
- strcpy(title, "Sonic Robo Blast 2");
- strcpy(srb2, "Sonic Robo Blast 2");
- D_MakeTitleString(srb2);
-
#ifdef PC_DOS
- D_Titlebar(srb2, title);
-#endif
-
-#if defined (__OS2__) && !defined (HAVE_SDL)
- // set PM window title
- snprintf(pmData->title, sizeof (pmData->title),
- "Sonic Robo Blast 2" VERSIONSTRING ": %s",
- title);
- pmData->title[sizeof (pmData->title) - 1] = '\0';
+ D_Titlebar();
#endif
if (devparm)
@@ -1172,6 +1177,11 @@ void D_SRB2Main(void)
#ifdef USE_PATCH_DTA
++mainwads; // patch.dta adds one more
#endif
+#ifdef DEVELOP
+ ++mainwads; // music_new, too
+#endif
+
+ mainwadstally = packetsizetally;
cht_Init();
@@ -1400,7 +1410,6 @@ void D_SRB2Main(void)
if (dedicated && server)
{
- pagename = "TITLESKY";
levelstarttic = gametic;
G_SetGamestate(GS_LEVEL);
if (!P_SetupLevel(false))
diff --git a/src/d_main.h b/src/d_main.h
index 6dc273b15..d73b19d1f 100644
--- a/src/d_main.h
+++ b/src/d_main.h
@@ -34,7 +34,7 @@ void D_SRB2Loop(void) FUNCNORETURN;
// D_SRB2Main()
// Not a globally visible function, just included for source reference,
// calls all startup code, parses command line options.
-// If not overrided by user input, calls N_AdvanceDemo.
+// If not overrided by user input, calls D_AdvanceDemo.
//
void D_SRB2Main(void);
@@ -51,9 +51,6 @@ const char *D_Home(void);
//
// BASE LEVEL
//
-void D_PageTicker(void);
-// pagename is lumpname of a 320x200 patch to fill the screen
-void D_PageDrawer(const char *pagename);
void D_AdvanceDemo(void);
void D_StartTitle(void);
diff --git a/src/d_net.c b/src/d_net.c
index 7f16c302d..48c1d60ea 100644
--- a/src/d_net.c
+++ b/src/d_net.c
@@ -49,7 +49,9 @@ doomcom_t *doomcom = NULL;
/// \brief network packet data, points inside doomcom
doomdata_t *netbuffer = NULL;
+#ifdef DEBUGFILE
FILE *debugfile = NULL; // put some net info in a file during the game
+#endif
#define MAXREBOUND 8
static doomdata_t reboundstore[MAXREBOUND];
@@ -711,11 +713,24 @@ void Net_CloseConnection(INT32 node)
#else
INT32 i;
boolean forceclose = (node & FORCECLOSE) != 0;
+
+ if (node == -1)
+ {
+ DEBFILE(M_GetText("Net_CloseConnection: node -1 detected!\n"));
+ return; // nope, just ignore it
+ }
+
node &= ~FORCECLOSE;
if (!node)
return;
+ if (node < 0 || node >= MAXNETNODES) // prevent invalid nodes from crashing the game
+ {
+ DEBFILE(va(M_GetText("Net_CloseConnection: invalid node %d detected!\n"), node));
+ return;
+ }
+
nodes[node].flags |= NF_CLOSE;
// try to Send ack back (two army problem)
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 43f04bae3..7f408a2b5 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -37,6 +37,7 @@
#include "d_main.h"
#include "m_random.h"
#include "f_finale.h"
+#include "filesrch.h"
#include "mserv.h"
#include "md5.h"
#include "z_zone.h"
@@ -60,9 +61,6 @@ static void Got_WeaponPref(UINT8 **cp, INT32 playernum);
static void Got_Mapcmd(UINT8 **cp, INT32 playernum);
static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum);
static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum);
-#ifdef DELFILE
-static void Got_Delfilecmd(UINT8 **cp, INT32 playernum);
-#endif
static void Got_Addfilecmd(UINT8 **cp, INT32 playernum);
static void Got_Pause(UINT8 **cp, INT32 playernum);
static void Got_Suicide(UINT8 **cp, INT32 playernum);
@@ -84,6 +82,9 @@ static void TeamScramble_OnChange(void);
static void NetTimeout_OnChange(void);
static void JoinTimeout_OnChange(void);
+static void CoopStarposts_OnChange(void);
+static void CoopLives_OnChange(void);
+
static void Ringslinger_OnChange(void);
static void Gravity_OnChange(void);
static void ForceSkin_OnChange(void);
@@ -111,9 +112,6 @@ static void Command_ResetCamera_f(void);
static void Command_Addfile(void);
static void Command_ListWADS_f(void);
-#ifdef DELFILE
-static void Command_Delfile(void);
-#endif
static void Command_RunSOC(void);
static void Command_Pause(void);
static void Command_Suicide(void);
@@ -184,19 +182,17 @@ static CV_PossibleValue_t joyport_cons_t[] = {{1, "/dev/js0"}, {2, "/dev/js1"},
#define usejoystick_cons_t NULL
#endif
-static CV_PossibleValue_t autobalance_cons_t[] = {{0, "MIN"}, {4, "MAX"}, {0, NULL}};
static CV_PossibleValue_t teamscramble_cons_t[] = {{0, "Off"}, {1, "Random"}, {2, "Points"}, {0, NULL}};
static CV_PossibleValue_t startingliveslimit_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, NULL}};
static CV_PossibleValue_t sleeping_cons_t[] = {{-1, "MIN"}, {1000/TICRATE, "MAX"}, {0, NULL}};
-static CV_PossibleValue_t competitionboxes_cons_t[] = {{0, "Normal"}, {1, "Random"}, {2, "Teleports"},
+static CV_PossibleValue_t competitionboxes_cons_t[] = {{0, "Normal"}, {1, "Mystery"}, //{2, "Teleport"},
{3, "None"}, {0, NULL}};
-static CV_PossibleValue_t matchboxes_cons_t[] = {{0, "Normal"}, {1, "Random"}, {2, "Non-Random"},
+static CV_PossibleValue_t matchboxes_cons_t[] = {{0, "Normal"}, {1, "Mystery"}, {2, "Unchanging"},
{3, "None"}, {0, NULL}};
static CV_PossibleValue_t chances_cons_t[] = {{0, "MIN"}, {9, "MAX"}, {0, NULL}};
-static CV_PossibleValue_t match_scoring_cons_t[] = {{0, "Normal"}, {1, "Classic"}, {0, NULL}};
static CV_PossibleValue_t pause_cons_t[] = {{0, "Server"}, {1, "All"}, {0, NULL}};
static CV_PossibleValue_t timetic_cons_t[] = {{0, "Normal"}, {1, "Tics"}, {2, "Centiseconds"}, {0, NULL}};
@@ -215,7 +211,7 @@ consvar_t cv_startinglives = {"startinglives", "3", CV_NETVAR|CV_CHEAT, starting
static CV_PossibleValue_t respawntime_cons_t[] = {{0, "MIN"}, {30, "MAX"}, {0, NULL}};
consvar_t cv_respawntime = {"respawndelay", "3", CV_NETVAR|CV_CHEAT, respawntime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_competitionboxes = {"competitionboxes", "Random", CV_NETVAR|CV_CHEAT, competitionboxes_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_competitionboxes = {"competitionboxes", "Mystery", CV_NETVAR|CV_CHEAT, competitionboxes_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
#ifdef SEENAMES
static CV_PossibleValue_t seenames_cons_t[] = {{0, "Off"}, {1, "Colorless"}, {2, "Team"}, {3, "Ally/Foe"}, {0, NULL}};
@@ -223,9 +219,9 @@ consvar_t cv_seenames = {"seenames", "Ally/Foe", CV_SAVE, seenames_cons_t, 0, 0,
consvar_t cv_allowseenames = {"allowseenames", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif
-// these are just meant to be saved to the config
-consvar_t cv_playername = {"name", "Sonic", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name_OnChange, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_playername2 = {"name2", "Tails", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name2_OnChange, 0, NULL, NULL, 0, 0, NULL};
+// names
+consvar_t cv_playername = {"name", "Sonic", CV_CALL|CV_NOINIT, NULL, Name_OnChange, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_playername2 = {"name2", "Tails", CV_CALL|CV_NOINIT, NULL, Name2_OnChange, 0, NULL, NULL, 0, 0, NULL};
// player colors
consvar_t cv_playercolor = {"color", "Blue", CV_CALL|CV_NOINIT, Color_cons_t, Color_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_playercolor2 = {"color2", "Orange", CV_CALL|CV_NOINIT, Color_cons_t, Color2_OnChange, 0, NULL, NULL, 0, 0, NULL};
@@ -233,6 +229,14 @@ consvar_t cv_playercolor2 = {"color2", "Orange", CV_CALL|CV_NOINIT, Color_cons_t
consvar_t cv_skin = {"skin", DEFAULTSKIN, CV_CALL|CV_NOINIT, NULL, Skin_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_skin2 = {"skin2", DEFAULTSKIN2, CV_CALL|CV_NOINIT, NULL, Skin2_OnChange, 0, NULL, NULL, 0, 0, NULL};
+// saved versions of the above six
+consvar_t cv_defaultplayername = {"defaultname", "Sonic", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_defaultplayername2 = {"defaultname2", "Tails", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_defaultplayercolor = {"defaultcolor", "Blue", CV_SAVE, Color_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_defaultplayercolor2 = {"defaultcolor2", "Orange", CV_SAVE, Color_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_defaultskin = {"defaultskin", DEFAULTSKIN, CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_defaultskin2 = {"defaultskin2", DEFAULTSKIN2, CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
+
consvar_t cv_skipmapcheck = {"skipmapcheck", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
INT32 cv_debug;
@@ -303,7 +307,7 @@ consvar_t cv_countdowntime = {"countdowntime", "60", CV_NETVAR|CV_CHEAT, minitim
consvar_t cv_touchtag = {"touchtag", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_hidetime = {"hidetime", "30", CV_NETVAR|CV_CALL, minitimelimit_cons_t, Hidetime_OnChange, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_autobalance = {"autobalance", "0", CV_NETVAR|CV_CALL, autobalance_cons_t, AutoBalance_OnChange, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_autobalance = {"autobalance", "Off", CV_NETVAR|CV_CALL, CV_OnOff, AutoBalance_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_teamscramble = {"teamscramble", "Off", CV_NETVAR|CV_CALL|CV_NOINIT, teamscramble_cons_t, TeamScramble_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_scrambleonchange = {"scrambleonchange", "Off", CV_NETVAR, teamscramble_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -311,7 +315,6 @@ consvar_t cv_friendlyfire = {"friendlyfire", "Off", CV_NETVAR, CV_OnOff, NULL, 0
consvar_t cv_itemfinder = {"itemfinder", "Off", CV_CALL, CV_OnOff, ItemFinder_OnChange, 0, NULL, NULL, 0, 0, NULL};
// Scoring type options
-consvar_t cv_match_scoring = {"matchscoring", "Normal", CV_NETVAR|CV_CHEAT, match_scoring_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_overtime = {"overtime", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_rollingdemos = {"rollingdemos", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -349,12 +352,18 @@ consvar_t cv_maxping = {"maxping", "0", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NUL
#endif
// Intermission time Tails 04-19-2002
static CV_PossibleValue_t inttime_cons_t[] = {{0, "MIN"}, {3600, "MAX"}, {0, NULL}};
-consvar_t cv_inttime = {"inttime", "20", CV_NETVAR, inttime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_inttime = {"inttime", "10", CV_NETVAR, inttime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+
+static CV_PossibleValue_t coopstarposts_cons_t[] = {{0, "Per-player"}, {1, "Shared"}, {2, "Teamwork"}, {0, NULL}};
+consvar_t cv_coopstarposts = {"coopstarposts", "Teamwork", CV_NETVAR|CV_CALL|CV_CHEAT, coopstarposts_cons_t, CoopStarposts_OnChange, 0, NULL, NULL, 0, 0, NULL};
+
+static CV_PossibleValue_t cooplives_cons_t[] = {{0, "Infinite"}, {1, "Per-player"}, {2, "Avoid Game Over"}, {3, "Single pool"}, {0, NULL}};
+consvar_t cv_cooplives = {"cooplives", "Avoid Game Over", CV_NETVAR|CV_CALL|CV_CHEAT, cooplives_cons_t, CoopLives_OnChange, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t advancemap_cons_t[] = {{0, "Off"}, {1, "Next"}, {2, "Random"}, {0, NULL}};
consvar_t cv_advancemap = {"advancemap", "Next", CV_NETVAR, advancemap_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
-static CV_PossibleValue_t playersforexit_cons_t[] = {{0, "One"}, {1, "All"}, {0, NULL}};
-consvar_t cv_playersforexit = {"playersforexit", "One", CV_NETVAR, playersforexit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+static CV_PossibleValue_t playersforexit_cons_t[] = {{0, "One"}, {1, "1/4"}, {2, "Half"}, {3, "3/4"}, {4, "All"}, {0, NULL}};
+consvar_t cv_playersforexit = {"playersforexit", "All", CV_NETVAR, playersforexit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_runscripts = {"runscripts", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -388,7 +397,7 @@ const char *netxcmdnames[MAXNETXCMD - 1] =
"RANDOMSEED",
"RUNSOC",
"REQADDFILE",
- "DELFILE",
+ "DELFILE", // replace next time we add an XD
"SETMOTD",
"SUICIDE",
#ifdef HAVE_BLUA
@@ -414,9 +423,6 @@ void D_RegisterServerCommands(void)
RegisterNetXCmd(XD_EXITLEVEL, Got_ExitLevelcmd);
RegisterNetXCmd(XD_ADDFILE, Got_Addfilecmd);
RegisterNetXCmd(XD_REQADDFILE, Got_RequestAddfilecmd);
-#ifdef DELFILE
- RegisterNetXCmd(XD_DELFILE, Got_Delfilecmd);
-#endif
RegisterNetXCmd(XD_PAUSE, Got_Pause);
RegisterNetXCmd(XD_SUICIDE, Got_Suicide);
RegisterNetXCmd(XD_RUNSOC, Got_RunSOCcmd);
@@ -450,9 +456,6 @@ void D_RegisterServerCommands(void)
COM_AddCommand("addfile", Command_Addfile);
COM_AddCommand("listwad", Command_ListWADS_f);
-#ifdef DELFILE
- COM_AddCommand("delfile", Command_Delfile);
-#endif
COM_AddCommand("runsoc", Command_RunSOC);
COM_AddCommand("pause", Command_Pause);
COM_AddCommand("suicide", Command_Suicide);
@@ -485,7 +488,6 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_itemrespawntime);
CV_RegisterVar(&cv_itemrespawn);
CV_RegisterVar(&cv_flagtime);
- CV_RegisterVar(&cv_suddendeath);
// misc
CV_RegisterVar(&cv_friendlyfire);
@@ -510,6 +512,9 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_forceskin);
CV_RegisterVar(&cv_downloading);
+ CV_RegisterVar(&cv_coopstarposts);
+ CV_RegisterVar(&cv_cooplives);
+
CV_RegisterVar(&cv_specialrings);
CV_RegisterVar(&cv_powerstones);
CV_RegisterVar(&cv_competitionboxes);
@@ -533,7 +538,6 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_startinglives);
CV_RegisterVar(&cv_countdowntime);
CV_RegisterVar(&cv_runscripts);
- CV_RegisterVar(&cv_match_scoring);
CV_RegisterVar(&cv_overtime);
CV_RegisterVar(&cv_pause);
CV_RegisterVar(&cv_mute);
@@ -616,6 +620,7 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_screenshot_option);
CV_RegisterVar(&cv_screenshot_folder);
+ CV_RegisterVar(&cv_screenshot_colorprofile);
CV_RegisterVar(&cv_moviemode);
// PNG variables
CV_RegisterVar(&cv_zlib_level);
@@ -638,7 +643,7 @@ void D_RegisterClientCommands(void)
// register these so it is saved to config
if ((username = I_GetUserName()))
- cv_playername.defaultvalue = username;
+ cv_playername.defaultvalue = cv_defaultplayername.defaultvalue = username;
CV_RegisterVar(&cv_playername);
CV_RegisterVar(&cv_playercolor);
CV_RegisterVar(&cv_skin); // r_things.c (skin NAME)
@@ -646,6 +651,13 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_playername2);
CV_RegisterVar(&cv_playercolor2);
CV_RegisterVar(&cv_skin2);
+ // saved versions of the above six
+ CV_RegisterVar(&cv_defaultplayername);
+ CV_RegisterVar(&cv_defaultplayercolor);
+ CV_RegisterVar(&cv_defaultskin);
+ CV_RegisterVar(&cv_defaultplayername2);
+ CV_RegisterVar(&cv_defaultplayercolor2);
+ CV_RegisterVar(&cv_defaultskin2);
#ifdef SEENAMES
CV_RegisterVar(&cv_seenames);
@@ -673,7 +685,29 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_resetmusic);
// FIXME: not to be here.. but needs be done for config loading
- CV_RegisterVar(&cv_usegamma);
+ CV_RegisterVar(&cv_globalgamma);
+ CV_RegisterVar(&cv_globalsaturation);
+
+ CV_RegisterVar(&cv_rhue);
+ CV_RegisterVar(&cv_yhue);
+ CV_RegisterVar(&cv_ghue);
+ CV_RegisterVar(&cv_chue);
+ CV_RegisterVar(&cv_bhue);
+ CV_RegisterVar(&cv_mhue);
+
+ CV_RegisterVar(&cv_rgamma);
+ CV_RegisterVar(&cv_ygamma);
+ CV_RegisterVar(&cv_ggamma);
+ CV_RegisterVar(&cv_cgamma);
+ CV_RegisterVar(&cv_bgamma);
+ CV_RegisterVar(&cv_mgamma);
+
+ CV_RegisterVar(&cv_rsaturation);
+ CV_RegisterVar(&cv_ysaturation);
+ CV_RegisterVar(&cv_gsaturation);
+ CV_RegisterVar(&cv_csaturation);
+ CV_RegisterVar(&cv_bsaturation);
+ CV_RegisterVar(&cv_msaturation);
// m_menu.c
CV_RegisterVar(&cv_crosshair);
@@ -695,6 +729,14 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_firenaxis);
CV_RegisterVar(&cv_firenaxis2);
+ // filesrch.c
+ CV_RegisterVar(&cv_addons_option);
+ CV_RegisterVar(&cv_addons_folder);
+ CV_RegisterVar(&cv_addons_md5);
+ CV_RegisterVar(&cv_addons_showall);
+ CV_RegisterVar(&cv_addons_search_type);
+ CV_RegisterVar(&cv_addons_search_case);
+
// WARNING: the order is important when initialising mouse2
// we need the mouse2port
CV_RegisterVar(&cv_mouse2port);
@@ -731,6 +773,7 @@ void D_RegisterClientCommands(void)
// s_sound.c
CV_RegisterVar(&cv_soundvolume);
+ CV_RegisterVar(&cv_closedcaptioning);
CV_RegisterVar(&cv_digmusicvolume);
CV_RegisterVar(&cv_midimusicvolume);
CV_RegisterVar(&cv_numChannels);
@@ -1144,7 +1187,7 @@ static void SendNameAndColor(void)
{
CV_StealthSetValue(&cv_playercolor, skins[cv_skin.value].prefcolor);
- players[consoleplayer].skincolor = (cv_playercolor.value&0x1F) % MAXSKINCOLORS;
+ players[consoleplayer].skincolor = cv_playercolor.value % MAXSKINCOLORS;
if (players[consoleplayer].mo)
players[consoleplayer].mo->color = (UINT8)players[consoleplayer].skincolor;
@@ -1271,7 +1314,7 @@ static void SendNameAndColor2(void)
{
CV_StealthSetValue(&cv_playercolor2, skins[players[secondplaya].skin].prefcolor);
- players[secondplaya].skincolor = (cv_playercolor2.value&0x1F) % MAXSKINCOLORS;
+ players[secondplaya].skincolor = cv_playercolor2.value % MAXSKINCOLORS;
if (players[secondplaya].mo)
players[secondplaya].mo->color = players[secondplaya].skincolor;
@@ -1589,8 +1632,13 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese
mapchangepending = 0;
// spawn the server if needed
// reset players if there is a new one
- if (!(adminplayer == consoleplayer) && SV_SpawnServer())
- buf[0] &= ~(1<<1);
+ if (!(adminplayer == consoleplayer))
+ {
+ if (SV_SpawnServer())
+ buf[0] &= ~(1<<1);
+ if (!Playing()) // you failed to start a server somehow, so cancel the map change
+ return;
+ }
// Kick bot from special stages
if (botskin)
@@ -2134,7 +2182,7 @@ static void Command_Teamchange_f(void)
return;
}
- if (!cv_allowteamchange.value && !NetPacket.packet.newteam) // allow swapping to spectator even in locked teams.
+ if (!cv_allowteamchange.value && NetPacket.packet.newteam) // allow swapping to spectator even in locked teams.
{
CONS_Alert(CONS_NOTICE, M_GetText("The server is not allowing team changes at the moment.\n"));
return;
@@ -2231,7 +2279,7 @@ static void Command_Teamchange2_f(void)
return;
}
- if (!cv_allowteamchange.value && !NetPacket.packet.newteam) // allow swapping to spectator even in locked teams.
+ if (!cv_allowteamchange.value && NetPacket.packet.newteam) // allow swapping to spectator even in locked teams.
{
CONS_Alert(CONS_NOTICE, M_GetText("The server is not allowing team changes at the moment.\n"));
return;
@@ -2985,6 +3033,7 @@ static void Command_Addfile(void)
XBOXSTATIC char buf[256];
char *buf_p = buf;
INT32 i;
+ int musiconly; // W_VerifyNMUSlumps isn't boolean
if (COM_Argc() != 2)
{
@@ -2999,7 +3048,9 @@ static void Command_Addfile(void)
if (!isprint(fn[i]) || fn[i] == ';')
return;
- if (!W_VerifyNMUSlumps(fn))
+ musiconly = W_VerifyNMUSlumps(fn);
+
+ if (!musiconly)
{
// ... But only so long as they contain nothing more then music and sprites.
if (netgame && !(server || adminplayer == consoleplayer))
@@ -3011,7 +3062,7 @@ static void Command_Addfile(void)
}
// Add file on your client directly if it is trivial, or you aren't in a netgame.
- if (!(netgame || multiplayer) || W_VerifyNMUSlumps(fn))
+ if (!(netgame || multiplayer) || musiconly)
{
P_AddWadFile(fn, NULL);
return;
@@ -3031,9 +3082,7 @@ static void Command_Addfile(void)
#else
FILE *fhandle;
- fhandle = fopen(fn, "rb");
-
- if (fhandle)
+ if ((fhandle = W_OpenWadFile(&fn, true)) != NULL)
{
tic_t t = I_GetTime();
CONS_Debug(DBG_SETUP, "Making MD5 for %s\n",fn);
@@ -3041,11 +3090,8 @@ static void Command_Addfile(void)
CONS_Debug(DBG_SETUP, "MD5 calc for %s took %f second\n", fn, (float)(I_GetTime() - t)/TICRATE);
fclose(fhandle);
}
- else
- {
- CONS_Printf(M_GetText("File %s not found.\n"), fn);
+ else // file not found
return;
- }
#endif
WRITEMEM(buf_p, md5sum, 16);
}
@@ -3056,49 +3102,19 @@ static void Command_Addfile(void)
SendNetXCmd(XD_ADDFILE, buf, buf_p - buf);
}
-#ifdef DELFILE
-/** removes the last added pwad at runtime.
- * Searches for sounds, maps, music and images to remove
- */
-static void Command_Delfile(void)
-{
- if (gamestate == GS_LEVEL)
- {
- CONS_Printf(M_GetText("You must NOT be in a level to use this.\n"));
- return;
- }
-
- if (netgame && !(server || adminplayer == consoleplayer))
- {
- CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
- return;
- }
-
- if (numwadfiles <= mainwads)
- {
- CONS_Printf(M_GetText("No additional WADs are loaded.\n"));
- return;
- }
-
- if (!(netgame || multiplayer))
- {
- P_DelWadFile();
- if (mainwads == numwadfiles && modifiedgame)
- modifiedgame = false;
- return;
- }
-
- SendNetXCmd(XD_DELFILE, NULL, 0);
-}
-#endif
-
static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
{
char filename[241];
filestatus_t ncs = FS_NOTFOUND;
UINT8 md5sum[16];
boolean kick = false;
+ boolean toomany = false;
INT32 i;
+ size_t packetsize = 0;
+ serverinfo_pak *dummycheck = NULL;
+
+ // Shut the compiler up.
+ (void)dummycheck;
READSTRINGN(*cp, filename, 240);
READMEM(*cp, md5sum, 16);
@@ -3124,13 +3140,25 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
return;
}
- ncs = findfile(filename,md5sum,true);
+ // See W_LoadWadFile in w_wad.c
+ for (i = 0; i < numwadfiles; i++)
+ packetsize += nameonlylength(wadfiles[i]->filename) + 22;
- if (ncs != FS_FOUND)
+ packetsize += nameonlylength(filename) + 22;
+
+ if ((numwadfiles >= MAX_WADFILES)
+ || (packetsize > sizeof(dummycheck->fileneeded)))
+ toomany = true;
+ else
+ ncs = findfile(filename,md5sum,true);
+
+ if (ncs != FS_FOUND || toomany)
{
char message[256];
- if (ncs == FS_NOTFOUND)
+ if (toomany)
+ sprintf(message, M_GetText("Too many files loaded to add %s\n"), filename);
+ else if (ncs == FS_NOTFOUND)
sprintf(message, M_GetText("The server doesn't have %s\n"), filename);
else if (ncs == FS_MD5SUMBAD)
sprintf(message, M_GetText("Checksum mismatch on %s\n"), filename);
@@ -3148,33 +3176,6 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
COM_BufAddText(va("addfile %s\n", filename));
}
-#ifdef DELFILE
-static void Got_Delfilecmd(UINT8 **cp, INT32 playernum)
-{
- if (playernum != serverplayer && playernum != adminplayer)
- {
- CONS_Alert(CONS_WARNING, M_GetText("Illegal delfile command received from %s\n"), player_names[playernum]);
- if (server)
- {
- XBOXSTATIC UINT8 buf[2];
-
- buf[0] = (UINT8)playernum;
- buf[1] = KICK_MSG_CON_FAIL;
- SendNetXCmd(XD_KICK, &buf, 2);
- }
- return;
- }
- (void)cp;
-
- if (numwadfiles <= mainwads) //sanity
- return;
-
- P_DelWadFile();
- if (mainwads == numwadfiles && modifiedgame)
- modifiedgame = false;
-}
-#endif
-
static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
{
char filename[241];
@@ -3200,10 +3201,15 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
ncs = findfile(filename,md5sum,true);
- if (ncs != FS_FOUND)
+ if (ncs != FS_FOUND || !P_AddWadFile(filename, NULL))
{
Command_ExitGame_f();
- if (ncs == FS_NOTFOUND)
+ if (ncs == FS_FOUND)
+ {
+ CONS_Printf(M_GetText("The server tried to add %s,\nbut you have too many files added.\nRestart the game to clear loaded files\nand play on this server."), filename);
+ M_StartMessage(va("The server added a file \n(%s)\nbut you have too many files added.\nRestart the game to clear loaded files.\n\nPress ESC\n",filename), NULL, MM_NOTHING);
+ }
+ else if (ncs == FS_NOTFOUND)
{
CONS_Printf(M_GetText("The server tried to add %s,\nbut you don't have this file.\nYou need to find it in order\nto play on this server."), filename);
M_StartMessage(va("The server added a file \n(%s)\nthat you do not have.\n\nPress ESC\n",filename), NULL, MM_NOTHING);
@@ -3221,7 +3227,6 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
return;
}
- P_AddWadFile(filename, NULL);
G_SetGameModified(true);
}
@@ -3376,6 +3381,102 @@ static void JoinTimeout_OnChange(void)
jointimeout = (tic_t)cv_jointimeout.value;
}
+static void CoopStarposts_OnChange(void)
+{
+ INT32 i;
+
+ if (!(netgame || multiplayer) || gametype != GT_COOP)
+ return;
+
+ switch (cv_coopstarposts.value)
+ {
+ case 0:
+ CONS_Printf(M_GetText("Starposts are now per-player.\n"));
+ break;
+ case 1:
+ CONS_Printf(M_GetText("Starposts are now shared between players.\n"));
+ break;
+ case 2:
+ CONS_Printf(M_GetText("Players now only spawn when starposts are hit.\n"));
+ return;
+ }
+
+ if (G_IsSpecialStage(gamemap))
+ return;
+
+ for (i = 0; i < MAXPLAYERS; i++)
+ {
+ if (!playeringame[i])
+ continue;
+
+ if (!players[i].spectator)
+ continue;
+
+ if (players[i].lives <= 0)
+ continue;
+
+ break;
+ }
+
+ if (i == MAXPLAYERS)
+ return;
+
+ for (i = 0; i < MAXPLAYERS; i++)
+ {
+ if (!playeringame[i])
+ continue;
+
+ if (!players[i].spectator)
+ continue;
+
+ if (players[i].lives <= 0 && (cv_cooplives.value == 1))
+ continue;
+
+ P_SpectatorJoinGame(&players[i]);
+ }
+}
+
+static void CoopLives_OnChange(void)
+{
+ INT32 i;
+
+ if (!(netgame || multiplayer) || gametype != GT_COOP)
+ return;
+
+ switch (cv_cooplives.value)
+ {
+ case 0:
+ CONS_Printf(M_GetText("Players can now respawn indefinitely.\n"));
+ return;
+ case 1:
+ CONS_Printf(M_GetText("Lives are now per-player.\n"));
+ return;
+ case 2:
+ CONS_Printf(M_GetText("Players can now steal lives to avoid game over.\n"));
+ break;
+ case 3:
+ CONS_Printf(M_GetText("Lives are now shared between players.\n"));
+ break;
+ }
+
+ if (cv_coopstarposts.value == 2)
+ return;
+
+ for (i = 0; i < MAXPLAYERS; i++)
+ {
+ if (!playeringame[i])
+ continue;
+
+ if (!players[i].spectator)
+ continue;
+
+ if (players[i].lives > 0)
+ continue;
+
+ P_SpectatorJoinGame(&players[i]);
+ }
+}
+
UINT32 timelimitintics = 0;
/** Deals with a timelimit change by printing the change to the console.
@@ -3666,7 +3767,7 @@ retryscramble:
{
if (red == maxcomposition)
newteam = 2;
- else if (blue == maxcomposition)
+ else //if (blue == maxcomposition)
newteam = 1;
repick = false;
@@ -3707,14 +3808,11 @@ retryscramble:
newteam = (INT16)((M_RandomByte() % 2) + 1);
repick = false;
}
- else
+ else if (i != 2) // Mystic's secret sauce - ABBA is better than ABAB, so team B doesn't get worse players all around
{
// We will only randomly pick the team for the first guy.
// Otherwise, just alternate back and forth, distributing players.
- if (newteam == 1)
- newteam = 2;
- else
- newteam = 1;
+ newteam = 3 - newteam;
}
scrambleteams[i] = newteam;
diff --git a/src/d_netcmd.h b/src/d_netcmd.h
index 08fc8b831..57e23b0f1 100644
--- a/src/d_netcmd.h
+++ b/src/d_netcmd.h
@@ -20,6 +20,19 @@
// console vars
extern consvar_t cv_playername;
extern consvar_t cv_playercolor;
+extern consvar_t cv_skin;
+// secondary splitscreen player
+extern consvar_t cv_playername2;
+extern consvar_t cv_playercolor2;
+extern consvar_t cv_skin2;
+// saved versions of the above six
+extern consvar_t cv_defaultplayername;
+extern consvar_t cv_defaultplayercolor;
+extern consvar_t cv_defaultskin;
+extern consvar_t cv_defaultplayername2;
+extern consvar_t cv_defaultplayercolor2;
+extern consvar_t cv_defaultskin2;
+
#ifdef SEENAMES
extern consvar_t cv_seenames, cv_allowseenames;
#endif
@@ -32,7 +45,6 @@ extern consvar_t cv_joyport2;
#endif
extern consvar_t cv_joyscale;
extern consvar_t cv_joyscale2;
-extern consvar_t cv_controlperkey;
// splitscreen with second mouse
extern consvar_t cv_mouse2port;
@@ -40,25 +52,12 @@ extern consvar_t cv_usemouse2;
#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON)
extern consvar_t cv_mouse2opt;
#endif
-extern consvar_t cv_invertmouse2;
-extern consvar_t cv_alwaysfreelook2;
-extern consvar_t cv_mousemove2;
-extern consvar_t cv_mousesens2;
-extern consvar_t cv_mouseysens2;
// normally in p_mobj but the .h is not read
extern consvar_t cv_itemrespawntime;
extern consvar_t cv_itemrespawn;
extern consvar_t cv_flagtime;
-extern consvar_t cv_suddendeath;
-
-extern consvar_t cv_skin;
-
-// secondary splitscreen player
-extern consvar_t cv_playername2;
-extern consvar_t cv_playercolor2;
-extern consvar_t cv_skin2;
extern consvar_t cv_touchtag;
extern consvar_t cv_hidetime;
@@ -77,9 +76,6 @@ extern consvar_t cv_autobalance;
extern consvar_t cv_teamscramble;
extern consvar_t cv_scrambleonchange;
-extern consvar_t cv_useranalog, cv_useranalog2;
-extern consvar_t cv_analog, cv_analog2;
-
extern consvar_t cv_netstat;
#ifdef WALLSPLATS
extern consvar_t cv_splats;
@@ -100,8 +96,7 @@ extern consvar_t cv_recycler;
extern consvar_t cv_itemfinder;
-extern consvar_t cv_inttime, cv_advancemap, cv_playersforexit;
-extern consvar_t cv_match_scoring;
+extern consvar_t cv_inttime, cv_coopstarposts, cv_cooplives, cv_advancemap, cv_playersforexit;
extern consvar_t cv_overtime;
extern consvar_t cv_startinglives;
@@ -120,17 +115,7 @@ extern consvar_t cv_maxping;
extern consvar_t cv_skipmapcheck;
-extern consvar_t cv_sleep, cv_screenshot_option, cv_screenshot_folder;
-
-extern consvar_t cv_moviemode;
-
-extern consvar_t cv_zlib_level, cv_zlib_memory, cv_zlib_strategy;
-
-extern consvar_t cv_zlib_window_bits, cv_zlib_levela, cv_zlib_memorya;
-
-extern consvar_t cv_zlib_strategya, cv_zlib_window_bitsa;
-
-extern consvar_t cv_apng_delay;
+extern consvar_t cv_sleep;
typedef enum
{
@@ -151,7 +136,7 @@ typedef enum
XD_RANDOMSEED, // 15
XD_RUNSOC, // 16
XD_REQADDFILE, // 17
- XD_DELFILE, // 18
+ XD_DELFILE, // 18 - replace next time we add an XD
XD_SETMOTD, // 19
XD_SUICIDE, // 20
#ifdef HAVE_BLUA
@@ -211,7 +196,6 @@ void Command_ExitGame_f(void);
void Command_Retry_f(void);
void D_GameTypeChanged(INT32 lastgametype); // not a real _OnChange function anymore
void D_MapChange(INT32 pmapnum, INT32 pgametype, boolean pultmode, boolean presetplayers, INT32 pdelay, boolean pskipprecutscene, boolean pfromlevelselect);
-void ObjectPlace_OnChange(void);
void ItemFinder_OnChange(void);
void D_SetPassword(const char *pw);
diff --git a/src/d_netfil.c b/src/d_netfil.c
index bf4e59878..9f2446e7e 100644
--- a/src/d_netfil.c
+++ b/src/d_netfil.c
@@ -62,7 +62,8 @@
#include
-static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid);
+// Prototypes
+static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid);
// Sender structure
typedef struct filetx_s
@@ -103,6 +104,7 @@ INT32 lastfilenum = -1;
/** Fills a serverinfo packet with information about wad files loaded.
*
* \todo Give this function a better name since it is in global scope.
+ * Used to have size limiting built in - now handled via W_LoadWadFile in w_wad.c
*
*/
UINT8 *PutFileNeeded(void)
@@ -111,29 +113,22 @@ UINT8 *PutFileNeeded(void)
UINT8 *p = netbuffer->u.serverinfo.fileneeded;
char wadfilename[MAX_WADPATH] = "";
UINT8 filestatus;
- size_t bytesused = 0;
for (i = 0; i < numwadfiles; i++)
{
- // If it has only music/sound lumps, mark it as unimportant
- if (W_VerifyNMUSlumps(wadfiles[i]->filename))
- filestatus = 0;
- else
- filestatus = 1; // Important
+ // If it has only music/sound lumps, don't put it in the list
+ if (!wadfiles[i]->important)
+ continue;
+
+ filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS
// Store in the upper four bits
if (!cv_downloading.value)
filestatus += (2 << 4); // Won't send
- else if ((wadfiles[i]->filesize > (UINT32)cv_maxsend.value * 1024))
- filestatus += (0 << 4); // Won't send
- else
+ else if ((wadfiles[i]->filesize <= (UINT32)cv_maxsend.value * 1024))
filestatus += (1 << 4); // Will send if requested
-
- bytesused += (nameonlylength(wadfilename) + 22);
-
- // Don't write too far...
- if (bytesused > sizeof(netbuffer->u.serverinfo.fileneeded))
- I_Error("Too many wad files added to host a game. (%s, stopped on %s)\n", sizeu1(bytesused), wadfilename);
+ // else
+ // filestatus += (0 << 4); -- Won't send, too big
WRITEUINT8(p, filestatus);
@@ -166,7 +161,6 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr)
{
fileneeded[i].status = FS_NOTFOUND; // We haven't even started looking for the file yet
filestatus = READUINT8(p); // The first byte is the file status
- fileneeded[i].important = (UINT8)(filestatus & 3);
fileneeded[i].willsend = (UINT8)(filestatus >> 4);
fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size
fileneeded[i].file = NULL; // The file isn't open yet
@@ -196,7 +190,7 @@ boolean CL_CheckDownloadable(void)
UINT8 i,dlstatus = 0;
for (i = 0; i < fileneedednum; i++)
- if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN && fileneeded[i].important)
+ if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN)
{
if (fileneeded[i].willsend == 1)
continue;
@@ -217,7 +211,7 @@ boolean CL_CheckDownloadable(void)
// not downloadable, put reason in console
CONS_Alert(CONS_NOTICE, M_GetText("You need additional files to connect to this server:\n"));
for (i = 0; i < fileneedednum; i++)
- if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN && fileneeded[i].important)
+ if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN)
{
CONS_Printf(" * \"%s\" (%dK)", fileneeded[i].filename, fileneeded[i].totalsize >> 10);
@@ -270,7 +264,7 @@ boolean CL_SendRequestFile(void)
for (i = 0; i < fileneedednum; i++)
if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN
- && fileneeded[i].important && (fileneeded[i].willsend == 0 || fileneeded[i].willsend == 2))
+ && (fileneeded[i].willsend == 0 || fileneeded[i].willsend == 2))
{
I_Error("Attempted to download files that were not sendable");
}
@@ -279,8 +273,7 @@ boolean CL_SendRequestFile(void)
netbuffer->packettype = PT_REQUESTFILE;
p = (char *)netbuffer->u.textcmd;
for (i = 0; i < fileneedednum; i++)
- if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)
- && fileneeded[i].important)
+ if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD))
{
totalfreespaceneeded += fileneeded[i].totalsize;
nameonly(fileneeded[i].filename);
@@ -303,7 +296,8 @@ boolean CL_SendRequestFile(void)
}
// get request filepak and put it on the send queue
-void Got_RequestFilePak(INT32 node)
+// returns false if a requested file was not found or cannot be sent
+boolean Got_RequestFilePak(INT32 node)
{
char wad[MAX_WADPATH+1];
UINT8 *p = netbuffer->u.textcmd;
@@ -314,8 +308,13 @@ void Got_RequestFilePak(INT32 node)
if (id == 0xFF)
break;
READSTRINGN(p, wad, MAX_WADPATH);
- SV_SendFile(node, wad, id);
+ if (!SV_SendFile(node, wad, id))
+ {
+ SV_AbortSendFiles(node);
+ return false; // don't read the rest of the files
+ }
}
+ return true; // no problems with any files
}
/** Checks if the files needed aren't already loaded or on the disk
@@ -330,6 +329,12 @@ INT32 CL_CheckFiles(void)
INT32 i, j;
char wadfilename[MAX_WADPATH];
INT32 ret = 1;
+ size_t packetsize = 0;
+ size_t filestoget = 0;
+ serverinfo_pak *dummycheck = NULL;
+
+ // Shut the compiler up.
+ (void)dummycheck;
// if (M_CheckParm("-nofiles"))
// return 1;
@@ -347,15 +352,9 @@ INT32 CL_CheckFiles(void)
CONS_Debug(DBG_NETPLAY, "game is modified; only doing basic checks\n");
for (i = 1, j = 1; i < fileneedednum || j < numwadfiles;)
{
- if (i < fileneedednum && !fileneeded[i].important)
+ if (j < numwadfiles && !wadfiles[j]->important)
{
- // Eh whatever, don't care
- ++i;
- continue;
- }
- if (j < numwadfiles && W_VerifyNMUSlumps(wadfiles[j]->filename))
- {
- // Unimportant on our side. still don't care.
+ // Unimportant on our side.
++j;
continue;
}
@@ -378,6 +377,10 @@ INT32 CL_CheckFiles(void)
return 1;
}
+ // See W_LoadWadFile in w_wad.c
+ for (i = 0; i < numwadfiles; i++)
+ packetsize += nameonlylength(wadfiles[i]->filename) + 22;
+
for (i = 1; i < fileneedednum; i++)
{
CONS_Debug(DBG_NETPLAY, "searching for '%s' ", fileneeded[i].filename);
@@ -394,9 +397,17 @@ INT32 CL_CheckFiles(void)
break;
}
}
- if (fileneeded[i].status != FS_NOTFOUND || !fileneeded[i].important)
+ if (fileneeded[i].status != FS_NOTFOUND)
continue;
+ packetsize += nameonlylength(fileneeded[i].filename) + 22;
+
+ if ((numwadfiles+filestoget >= MAX_WADFILES)
+ || (packetsize > sizeof(dummycheck->fileneeded)))
+ return 3;
+
+ filestoget++;
+
fileneeded[i].status = findfile(fileneeded[i].filename, fileneeded[i].md5sum, true);
CONS_Debug(DBG_NETPLAY, "found %d\n", fileneeded[i].status);
if (fileneeded[i].status != FS_FOUND)
@@ -424,27 +435,8 @@ void CL_LoadServerFiles(void)
fileneeded[i].status = FS_OPEN;
}
else if (fileneeded[i].status == FS_MD5SUMBAD)
- {
- // If the file is marked important, don't even bother proceeding.
- if (fileneeded[i].important)
- I_Error("Wrong version of important file %s", fileneeded[i].filename);
-
- // If it isn't, no need to worry the user with a console message,
- // although it can't hurt to put something in the debug file.
-
- // ...but wait a second. What if the local version is "important"?
- if (!W_VerifyNMUSlumps(fileneeded[i].filename))
- I_Error("File %s should only contain music and sound effects!",
- fileneeded[i].filename);
-
- // Okay, NOW we know it's safe. Whew.
- P_AddWadFile(fileneeded[i].filename, NULL);
- if (fileneeded[i].important)
- G_SetGameModified(true);
- fileneeded[i].status = FS_OPEN;
- DEBFILE(va("File %s found but with different md5sum\n", fileneeded[i].filename));
- }
- else if (fileneeded[i].important)
+ I_Error("Wrong version of file %s", fileneeded[i].filename);
+ else
{
const char *s;
switch(fileneeded[i].status)
@@ -480,7 +472,7 @@ static INT32 filestosend = 0;
* \sa SV_SendRam
*
*/
-static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid)
+static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid)
{
filetx_t **q; // A pointer to the "next" field of the last file in the list
filetx_t *p; // The new file request
@@ -488,7 +480,7 @@ static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid)
char wadfilename[MAX_WADPATH];
if (cv_noticedownload.value)
- CONS_Printf("Sending file \"%s\" to node %d\n", filename, node);
+ CONS_Printf("Sending file \"%s\" to node %d (%s)\n", filename, node, I_GetNodeAddress(node));
// Find the last file in the list and set a pointer to its "next" field
q = &transfer[node].txlist;
@@ -537,7 +529,7 @@ static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid)
free(p->id.filename);
free(p);
*q = NULL;
- return;
+ return false; // cancel the rest of the requests
}
// Handle huge file requests (i.e. bigger than cv_maxsend.value KB)
@@ -549,7 +541,7 @@ static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid)
free(p->id.filename);
free(p);
*q = NULL;
- return;
+ return false; // cancel the rest of the requests
}
DEBFILE(va("Sending file %s (id=%d) to %d\n", filename, fileid, node));
@@ -557,6 +549,7 @@ static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid)
p->fileid = fileid;
p->next = NULL; // End of list
filestosend++;
+ return true;
}
/** Adds a memory block to the file list for a node
diff --git a/src/d_netfil.h b/src/d_netfil.h
index c9085a5b0..6fdd0a8a1 100644
--- a/src/d_netfil.h
+++ b/src/d_netfil.h
@@ -35,7 +35,6 @@ typedef enum
typedef struct
{
- UINT8 important;
UINT8 willsend; // Is the server willing to send it?
char filename[MAX_WADPATH];
UINT8 md5sum[16];
@@ -69,7 +68,7 @@ boolean SV_SendingFile(INT32 node);
boolean CL_CheckDownloadable(void);
boolean CL_SendRequestFile(void);
-void Got_RequestFilePak(INT32 node);
+boolean Got_RequestFilePak(INT32 node);
void SV_AbortSendFiles(INT32 node);
void CloseNetFile(void);
diff --git a/src/d_player.h b/src/d_player.h
index 05a99db2a..c10e59405 100644
--- a/src/d_player.h
+++ b/src/d_player.h
@@ -181,6 +181,14 @@ typedef enum
PA_RIDE
} panim_t;
+//
+// All of the base srb2 shields are either a single constant,
+// or use damagetype-protecting flags applied to a constant,
+// or are the force shield (which does everything weirdly).
+//
+// Base flags by themselves aren't used so modders can make
+// abstract, ability-less shields should they so choose.
+//
typedef enum
{
SH_NONE = 0,
@@ -189,19 +197,21 @@ typedef enum
SH_PROTECTFIRE = 0x400,
SH_PROTECTWATER = 0x800,
SH_PROTECTELECTRIC = 0x1000,
+ SH_PROTECTSPIKE = 0x2000, // cactus shield one day? thanks, subarashii
+ //SH_PROTECTNUKE = 0x4000, // intentionally no hardcoded defense against nukes
// Indivisible shields
SH_PITY = 1, // the world's most basic shield ever, given to players who suck at Match
SH_WHIRLWIND,
SH_ARMAGEDDON,
- // normal shields that use flags
- SH_ATTRACT = SH_PROTECTELECTRIC,
- SH_ELEMENTAL = SH_PROTECTFIRE|SH_PROTECTWATER,
+ // Normal shields that use flags
+ SH_ATTRACT = SH_PITY|SH_PROTECTELECTRIC,
+ SH_ELEMENTAL = SH_PITY|SH_PROTECTFIRE|SH_PROTECTWATER,
// Sonic 3 shields
- SH_FLAMEAURA = SH_PROTECTFIRE,
- SH_BUBBLEWRAP = SH_PROTECTWATER,
+ SH_FLAMEAURA = SH_PITY|SH_PROTECTFIRE,
+ SH_BUBBLEWRAP = SH_PITY|SH_PROTECTWATER,
SH_THUNDERCOIN = SH_WHIRLWIND|SH_PROTECTELECTRIC,
// The force shield uses the lower 8 bits to count how many extra hits are left.
@@ -475,6 +485,7 @@ typedef struct player_s
angle_t awayviewaiming; // Used for cut-away view
boolean spectator;
+ boolean outofcoop;
UINT8 bot;
tic_t jointime; // Timer when player joins game to change skin/color
diff --git a/src/dehacked.c b/src/dehacked.c
index 8657e8de3..5867eb90a 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -78,97 +78,6 @@ static int dbg_line;
static boolean gamedataadded = false;
-#ifdef DELFILE
-typedef struct undehacked_s
-{
- char *undata;
- struct undehacked_s *next;
-} undehacked_t;
-
-static UINT16 unsocwad;
-static undehacked_t *unsocdata[MAX_WADFILES];
-static boolean disableundo = false;
-
-void DEH_WriteUndoline(const char *value, const char *data, undotype_f flags)
-{
- const char *eqstr = " = ";
- const char *space = " ";
- const char *pader = eqstr;
- undehacked_t *newdata;
-
- if (disableundo || !unsocwad)
- return;
-
- if ((newdata = malloc(sizeof(*newdata))) == NULL)
- I_Error("Out of memory for unsoc line");
-
- if (flags & UNDO_SPACE)
- pader = space;
-
- if (flags & UNDO_ENDTEXT && !data)
- data = space;
-
- if (value)
- {
- const size_t plen = strlen(pader);
- const char *pound = "#";
- char *undata = NULL;
- const size_t elen = strlen(pound);
- size_t vlen = strlen(value), dlen = 0, len = 1;
-
- if (*(value+vlen-1) == '\n')
- vlen--; // lnet not copy the ending \n
-
- if (flags & UNDO_ENDTEXT)
- len += elen; // let malloc more space
-
- if (flags & UNDO_NEWLINE)
- len++; // more space for the beginning \n
-
- if (data)
- {
- dlen = strlen(data);
- if (flags & UNDO_CUTLINE && *(data+dlen-1) == '\n')
- dlen--; // let not copy the ending \n
- newdata->undata = malloc(vlen+plen+dlen+len);
- newdata->undata[vlen+plen+dlen+len-1] = '\0';
- }
- else
- {
- newdata->undata = malloc(vlen+len);
- newdata->undata[vlen+len-1] = '\0';
- }
-
- if (newdata->undata)
- {
- undata = newdata->undata;
- *undata = '\0';
- }
- else
- {
- free(newdata);
- I_Error("Out of memory for unsoc data");
- }
-
- if (flags & UNDO_NEWLINE) // let start with \n
- strcat(undata, "\n");
-
- strncat(undata, value, vlen);
-
- if (data) // value+pader+data
- strncat(strncat(undata, pader, plen), data, dlen);
-
- if (flags & UNDO_ENDTEXT) // let end the text
- strncat(undata, pound, elen);
- }
- else
- newdata->undata = NULL;
-
- newdata->next = unsocdata[unsocwad];
- unsocdata[unsocwad] = newdata;
-}
-#endif
-
ATTRINLINE static FUNCINLINE char myfget_color(MYFILE *f)
{
char c = *f->curpos++;
@@ -382,56 +291,6 @@ static void clear_levels(void)
P_AllocMapHeader(gamemap-1);
}
-/*
-// Edits an animated texture slot on the array
-// Tails 12-27-2003
-static void readAnimTex(MYFILE *f, INT32 num)
-{
- char s[MAXLINELEN];
- char *word;
- char *word2;
- INT32 i;
-
- do {
- if (myfgets(s, sizeof s, f) != NULL)
- {
- if (s[0] == '\n') break;
-
- tmp = strchr(s, '#');
- if (tmp)
- *tmp = '\0';
- // set the value in the appropriate field
-
- word = strtok(s, " ");
- if (word)
- strupr(word);
- else
- break;
-
- word2 = strtok(NULL, " = ");
- if (word2)
- strupr(word2);
- else
- break;
-
- if (word2[strlen(word2)-1] == '\n')
- word2[strlen(word2)-1] = '\0';
-
- i = atoi(word2);
-
- if (fastcmp(word, "START"))
- strncpy(harddefs[num].startname, word2, 8);
- if (fastcmp(word, "END"))
- strncpy(harddefs[num].endname, word2, 8);
- else if (fastcmp(word, "SPEED")) harddefs[num].speed = i;
- else if (fastcmp(word, "ISTEXTURE")) harddefs[num].istexture = i;
-
- else deh_warning("readAnimTex %d: unknown word '%s'", num, word);
- }
- } while (s[0] != '\n' && !myfeof(f)); //finish when the line is empty
-}
-*/
-
static boolean findFreeSlot(INT32 *num)
{
// Send the character select entry to a free slot.
@@ -458,8 +317,6 @@ static void readPlayer(MYFILE *f, INT32 num)
INT32 i;
boolean slotfound = false;
- DEH_WriteUndoline("PLAYERTEXT", description[num].notes, UNDO_ENDTEXT);
-
do
{
if (myfgets(s, MAXLINELEN, f))
@@ -528,7 +385,6 @@ static void readPlayer(MYFILE *f, INT32 num)
{
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
goto done;
- DEH_WriteUndoline(word, &description[num].picname[0], UNDO_NONE);
strncpy(description[num].picname, word2, 8);
}
@@ -543,7 +399,7 @@ static void readPlayer(MYFILE *f, INT32 num)
*/
if (i && !slotfound && (slotfound = findFreeSlot(&num)) == false)
goto done;
- DEH_WriteUndoline(word, va("%d", description[num].used), UNDO_NONE);
+
description[num].used = (!!i);
}
else if (fastcmp(word, "SKINNAME"))
@@ -551,7 +407,6 @@ static void readPlayer(MYFILE *f, INT32 num)
// Send to free slot.
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
goto done;
- DEH_WriteUndoline(word, description[num].skinname, UNDO_NONE);
strlcpy(description[num].skinname, word2, sizeof description[num].skinname);
strlwr(description[num].skinname);
@@ -561,11 +416,6 @@ static void readPlayer(MYFILE *f, INT32 num)
}
} while (!myfeof(f)); // finish when the line is empty
-#ifdef DELFILE
- if (slotfound)
- DEH_WriteUndoline("MENUPOSITION", va("%d", num), UNDO_NONE);
-#endif
-
done:
Z_Free(s);
}
@@ -703,122 +553,98 @@ static void readthing(MYFILE *f, INT32 num)
if (fastcmp(word, "MAPTHINGNUM") || fastcmp(word, "DOOMEDNUM"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].doomednum), UNDO_NONE);
mobjinfo[num].doomednum = (INT32)atoi(word2);
}
else if (fastcmp(word, "SPAWNSTATE"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].spawnstate), UNDO_NONE);
mobjinfo[num].spawnstate = get_number(word2);
}
else if (fastcmp(word, "SPAWNHEALTH"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].spawnhealth), UNDO_NONE);
mobjinfo[num].spawnhealth = (INT32)get_number(word2);
}
else if (fastcmp(word, "SEESTATE"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].seestate), UNDO_NONE);
mobjinfo[num].seestate = get_number(word2);
}
else if (fastcmp(word, "SEESOUND"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].seesound), UNDO_NONE);
mobjinfo[num].seesound = get_number(word2);
}
else if (fastcmp(word, "REACTIONTIME"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].reactiontime), UNDO_NONE);
mobjinfo[num].reactiontime = (INT32)get_number(word2);
}
else if (fastcmp(word, "ATTACKSOUND"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].attacksound), UNDO_NONE);
mobjinfo[num].attacksound = get_number(word2);
}
else if (fastcmp(word, "PAINSTATE"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].painstate), UNDO_NONE);
mobjinfo[num].painstate = get_number(word2);
}
else if (fastcmp(word, "PAINCHANCE"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].painchance), UNDO_NONE);
mobjinfo[num].painchance = (INT32)get_number(word2);
}
else if (fastcmp(word, "PAINSOUND"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].painsound), UNDO_NONE);
mobjinfo[num].painsound = get_number(word2);
}
else if (fastcmp(word, "MELEESTATE"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].meleestate), UNDO_NONE);
mobjinfo[num].meleestate = get_number(word2);
}
else if (fastcmp(word, "MISSILESTATE"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].missilestate), UNDO_NONE);
mobjinfo[num].missilestate = get_number(word2);
}
else if (fastcmp(word, "DEATHSTATE"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].deathstate), UNDO_NONE);
mobjinfo[num].deathstate = get_number(word2);
}
else if (fastcmp(word, "DEATHSOUND"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].deathsound), UNDO_NONE);
mobjinfo[num].deathsound = get_number(word2);
}
else if (fastcmp(word, "XDEATHSTATE"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].xdeathstate), UNDO_NONE);
mobjinfo[num].xdeathstate = get_number(word2);
}
else if (fastcmp(word, "SPEED"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].speed), UNDO_NONE);
mobjinfo[num].speed = get_number(word2);
}
else if (fastcmp(word, "RADIUS"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].radius), UNDO_NONE);
mobjinfo[num].radius = get_number(word2);
}
else if (fastcmp(word, "HEIGHT"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].height), UNDO_NONE);
mobjinfo[num].height = get_number(word2);
}
else if (fastcmp(word, "DISPOFFSET"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].dispoffset), UNDO_NONE);
mobjinfo[num].dispoffset = get_number(word2);
}
else if (fastcmp(word, "MASS"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].mass), UNDO_NONE);
mobjinfo[num].mass = (INT32)get_number(word2);
}
else if (fastcmp(word, "DAMAGE"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].damage), UNDO_NONE);
mobjinfo[num].damage = (INT32)get_number(word2);
}
else if (fastcmp(word, "ACTIVESOUND"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].activesound), UNDO_NONE);
mobjinfo[num].activesound = get_number(word2);
}
else if (fastcmp(word, "FLAGS"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].flags), UNDO_NONE);
mobjinfo[num].flags = (INT32)get_number(word2);
}
else if (fastcmp(word, "RAISESTATE"))
{
- DEH_WriteUndoline(word, va("%d", mobjinfo[num].raisestate), UNDO_NONE);
mobjinfo[num].raisestate = get_number(word2);
}
else
@@ -862,37 +688,30 @@ static void readlight(MYFILE *f, INT32 num)
if (fastcmp(word, "TYPE"))
{
- DEH_WriteUndoline(word, va("%d", lspr[num].type), UNDO_NONE);
lspr[num].type = (UINT16)value;
}
else if (fastcmp(word, "OFFSETX"))
{
- DEH_WriteUndoline(word, va("%f", lspr[num].light_xoffset), UNDO_NONE);
lspr[num].light_xoffset = fvalue;
}
else if (fastcmp(word, "OFFSETY"))
{
- DEH_WriteUndoline(word, va("%f", lspr[num].light_yoffset), UNDO_NONE);
lspr[num].light_yoffset = fvalue;
}
else if (fastcmp(word, "CORONACOLOR"))
{
- DEH_WriteUndoline(word, va("%u", lspr[num].corona_color), UNDO_NONE);
lspr[num].corona_color = value;
}
else if (fastcmp(word, "CORONARADIUS"))
{
- DEH_WriteUndoline(word, va("%f", lspr[num].corona_radius), UNDO_NONE);
lspr[num].corona_radius = fvalue;
}
else if (fastcmp(word, "DYNAMICCOLOR"))
{
- DEH_WriteUndoline(word, va("%u", lspr[num].dynamic_color), UNDO_NONE);
lspr[num].dynamic_color = value;
}
else if (fastcmp(word, "DYNAMICRADIUS"))
{
- DEH_WriteUndoline(word, va("%f", lspr[num].dynamic_radius), UNDO_NONE);
lspr[num].dynamic_radius = fvalue;
/// \note Update the sqrradius! unnecessary?
@@ -939,7 +758,6 @@ static void readspritelight(MYFILE *f, INT32 num)
INT32 oldvar;
for (oldvar = 0; t_lspr[num] != &lspr[oldvar]; oldvar++)
;
- DEH_WriteUndoline(word, va("%d", oldvar), UNDO_NONE);
t_lspr[num] = &lspr[value];
}
else
@@ -1022,8 +840,6 @@ static void readlevelheader(MYFILE *f, INT32 num)
INT32 i;
// Reset all previous map header information
- // This call automatically saves all previous information when DELFILE is defined.
- // We don't need to do it ourselves.
P_AllocMapHeader((INT16)(num-1));
do
@@ -1379,6 +1195,13 @@ static void readlevelheader(MYFILE *f, INT32 num)
else
mapheaderinfo[num-1]->levelflags &= ~LF_NOZONE;
}
+ else if (fastcmp(word, "SAVEGAME"))
+ {
+ if (i || word2[0] == 'T' || word2[0] == 'Y')
+ mapheaderinfo[num-1]->levelflags |= LF_SAVEGAME;
+ else
+ mapheaderinfo[num-1]->levelflags &= ~LF_SAVEGAME;
+ }
// Individual triggers for menu flags
else if (fastcmp(word, "HIDDEN"))
@@ -1442,8 +1265,6 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
UINT16 usi;
UINT8 picid;
- DEH_WriteUndoline("SCENETEXT", cutscenes[num]->scene[scenenum].text, UNDO_ENDTEXT);
-
do
{
if (myfgets(s, MAXLINELEN, f))
@@ -1520,7 +1341,6 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
if (fastcmp(word, "NUMBEROFPICS"))
{
- DEH_WriteUndoline(word, va("%d", cutscenes[num]->scene[scenenum].numpics), UNDO_NONE);
cutscenes[num]->scene[scenenum].numpics = (UINT8)i;
}
else if (fastncmp(word, "PIC", 3))
@@ -1535,27 +1355,22 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
if (fastcmp(word+4, "NAME"))
{
- DEH_WriteUndoline(word, cutscenes[num]->scene[scenenum].picname[picid], UNDO_NONE);
strncpy(cutscenes[num]->scene[scenenum].picname[picid], word2, 8);
}
else if (fastcmp(word+4, "HIRES"))
{
- DEH_WriteUndoline(word, va("%d", cutscenes[num]->scene[scenenum].pichires[picid]), UNDO_NONE);
cutscenes[num]->scene[scenenum].pichires[picid] = (UINT8)(i || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word+4, "DURATION"))
{
- DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].picduration[picid]), UNDO_NONE);
cutscenes[num]->scene[scenenum].picduration[picid] = usi;
}
else if (fastcmp(word+4, "XCOORD"))
{
- DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].xcoord[picid]), UNDO_NONE);
cutscenes[num]->scene[scenenum].xcoord[picid] = usi;
}
else if (fastcmp(word+4, "YCOORD"))
{
- DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].ycoord[picid]), UNDO_NONE);
cutscenes[num]->scene[scenenum].ycoord[picid] = usi;
}
else
@@ -1563,14 +1378,12 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
}
else if (fastcmp(word, "MUSIC"))
{
- DEH_WriteUndoline(word, cutscenes[num]->scene[scenenum].musswitch, UNDO_NONE);
strncpy(cutscenes[num]->scene[scenenum].musswitch, word2, 7);
cutscenes[num]->scene[scenenum].musswitch[6] = 0;
}
#ifdef MUSICSLOT_COMPATIBILITY
else if (fastcmp(word, "MUSICSLOT"))
{
- DEH_WriteUndoline(word, cutscenes[num]->scene[scenenum].musswitch, UNDO_NONE);
i = get_mus(word2, true);
if (i && i <= 1035)
snprintf(cutscenes[num]->scene[scenenum].musswitch, 7, "%sM", G_BuildMapName(i));
@@ -1583,37 +1396,30 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
#endif
else if (fastcmp(word, "MUSICTRACK"))
{
- DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musswitchflags), UNDO_NONE);
cutscenes[num]->scene[scenenum].musswitchflags = ((UINT16)i) & MUSIC_TRACKMASK;
}
else if (fastcmp(word, "MUSICLOOP"))
{
- DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musicloop), UNDO_NONE);
cutscenes[num]->scene[scenenum].musicloop = (UINT8)(i || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word, "TEXTXPOS"))
{
- DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].textxpos), UNDO_NONE);
cutscenes[num]->scene[scenenum].textxpos = usi;
}
else if (fastcmp(word, "TEXTYPOS"))
{
- DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].textypos), UNDO_NONE);
cutscenes[num]->scene[scenenum].textypos = usi;
}
else if (fastcmp(word, "FADEINID"))
{
- DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].fadenum), UNDO_NONE);
cutscenes[num]->scene[scenenum].fadeinid = (UINT8)i;
}
else if (fastcmp(word, "FADEOUTID"))
{
- DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].fadenum), UNDO_NONE);
cutscenes[num]->scene[scenenum].fadeoutid = (UINT8)i;
}
else if (fastcmp(word, "FADECOLOR"))
{
- DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].fadenum), UNDO_NONE);
cutscenes[num]->scene[scenenum].fadecolor = (UINT8)i;
}
else
@@ -1631,9 +1437,6 @@ static void readcutscene(MYFILE *f, INT32 num)
char *word2;
char *tmp;
INT32 value;
-#ifdef DELFILE
- const INT32 oldnumscenes = cutscenes[num]->numscenes;
-#endif
// Allocate memory for this cutscene if we don't yet have any
if (!cutscenes[num])
@@ -1676,8 +1479,6 @@ static void readcutscene(MYFILE *f, INT32 num)
if (1 <= value && value <= 128)
{
readcutscenescene(f, num, value - 1);
- DEH_WriteUndoline(word, word2, UNDO_SPACE|UNDO_CUTLINE);
- DEH_WriteUndoline("NUMSCENES", va("%d", oldnumscenes), UNDO_SPACE);
}
else
deh_warning("Scene number %d out of range (1 - 128)", value);
@@ -1730,12 +1531,10 @@ static void readhuditem(MYFILE *f, INT32 num)
if (fastcmp(word, "X"))
{
- DEH_WriteUndoline(word, va("%d", hudinfo[num].x), UNDO_NONE);
hudinfo[num].x = i;
}
else if (fastcmp(word, "Y"))
{
- DEH_WriteUndoline(word, va("%d", hudinfo[num].y), UNDO_NONE);
hudinfo[num].y = i;
}
else
@@ -1782,7 +1581,6 @@ static actionpointer_t actionpointers[] =
{{A_BossDeath}, "A_BOSSDEATH"},
{{A_CustomPower}, "A_CUSTOMPOWER"},
{{A_GiveWeapon}, "A_GIVEWEAPON"},
- {{A_RingShield}, "A_RINGSHIELD"},
{{A_RingBox}, "A_RINGBOX"},
{{A_Invincibility}, "A_INVINCIBILITY"},
{{A_SuperSneakers}, "A_SUPERSNEAKERS"},
@@ -1793,14 +1591,7 @@ static actionpointer_t actionpointers[] =
{{A_BubbleCheck}, "A_BUBBLECHECK"},
{{A_AwardScore}, "A_AWARDSCORE"},
{{A_ExtraLife}, "A_EXTRALIFE"},
- {{A_BombShield}, "A_BOMBSHIELD"},
- {{A_JumpShield}, "A_JUMPSHIELD"},
- {{A_WaterShield}, "A_WATERSHIELD"},
- {{A_ForceShield}, "A_FORCESHIELD"},
- {{A_PityShield}, "A_PITYSHIELD"},
- {{A_FlameShield}, "A_FLAMESHIELD"},
- {{A_BubbleShield}, "A_BUBBLESHIELD"},
- {{A_ThunderShield}, "A_THUNDERSHIELD"},
+ {{A_GiveShield}, "A_GIVESHIELD"},
{{A_GravityBox}, "A_GRAVITYBOX"},
{{A_ScoreRise}, "A_SCORERISE"},
{{A_ParticleSpawn}, "A_PARTICLESPAWN"},
@@ -1826,7 +1617,6 @@ static actionpointer_t actionpointers[] =
{{A_CapeChase}, "A_CAPECHASE"},
{{A_RotateSpikeBall}, "A_ROTATESPIKEBALL"},
{{A_SlingAppear}, "A_SLINGAPPEAR"},
- {{A_MaceRotate}, "A_MACEROTATE"},
{{A_UnidusBall}, "A_UNIDUSBALL"},
{{A_RockSpawn}, "A_ROCKSPAWN"},
{{A_SetFuse}, "A_SETFUSE"},
@@ -2021,32 +1811,26 @@ static void readframe(MYFILE *f, INT32 num)
if (fastcmp(word1, "SPRITENUMBER") || fastcmp(word1, "SPRITENAME"))
{
- DEH_WriteUndoline(word1, va("%u", states[num].sprite), UNDO_NONE);
states[num].sprite = get_sprite(word2);
}
else if (fastcmp(word1, "SPRITESUBNUMBER") || fastcmp(word1, "SPRITEFRAME"))
{
- DEH_WriteUndoline(word1, va("%d", states[num].frame), UNDO_NONE);
states[num].frame = (INT32)get_number(word2); // So the FF_ flags get calculated
}
else if (fastcmp(word1, "DURATION"))
{
- DEH_WriteUndoline(word1, va("%u", states[num].tics), UNDO_NONE);
states[num].tics = (INT32)get_number(word2); // So TICRATE can be used
}
else if (fastcmp(word1, "NEXT"))
{
- DEH_WriteUndoline(word1, va("%d", states[num].nextstate), UNDO_NONE);
states[num].nextstate = get_state(word2);
}
else if (fastcmp(word1, "VAR1"))
{
- DEH_WriteUndoline(word1, va("%d", states[num].var1), UNDO_NONE);
states[num].var1 = (INT32)get_number(word2);
}
else if (fastcmp(word1, "VAR2"))
{
- DEH_WriteUndoline(word1, va("%d", states[num].var2), UNDO_NONE);
states[num].var2 = (INT32)get_number(word2);
}
else if (fastcmp(word1, "ACTION"))
@@ -2071,10 +1855,7 @@ static void readframe(MYFILE *f, INT32 num)
for (z = 0; actionpointers[z].name; z++)
{
if (actionpointers[z].action.acv == states[num].action.acv)
- {
- DEH_WriteUndoline(word1, actionpointers[z].name, UNDO_NONE);
break;
- }
}
z = 0;
@@ -2106,10 +1887,11 @@ static void readframe(MYFILE *f, INT32 num)
Z_Free(s);
}
-static void readsound(MYFILE *f, INT32 num, const char *savesfxnames[])
+static void readsound(MYFILE *f, INT32 num)
{
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
char *word;
+ char *word2;
char *tmp;
INT32 value;
@@ -2123,8 +1905,8 @@ static void readsound(MYFILE *f, INT32 num, const char *savesfxnames[])
tmp = strchr(s, '#');
if (tmp)
*tmp = '\0';
-
- value = searchvalue(s);
+ if (s == tmp)
+ continue; // Skip comment lines, but don't break.
word = strtok(s, " ");
if (word)
@@ -2132,43 +1914,38 @@ static void readsound(MYFILE *f, INT32 num, const char *savesfxnames[])
else
break;
-/* if (fastcmp(word, "OFFSET"))
+ word2 = strtok(NULL, " ");
+ if (word2)
+ value = atoi(word2);
+ else
{
- value -= 150360;
- if (value <= 64)
- value /= 8;
- else if (value <= 260)
- value = (value+4)/8;
- else
- value = (value+8)/8;
- if (value >= -1 && value < sfx_freeslot0 - 1)
- S_sfx[num].name = savesfxnames[value+1];
- else
- deh_warning("Sound %d: offset out of bounds", num);
+ deh_warning("No value for token %s", word);
+ continue;
}
- else */if (fastcmp(word, "SINGULAR"))
+
+ if (fastcmp(word, "SINGULAR"))
{
- DEH_WriteUndoline(word, va("%d", S_sfx[num].singularity), UNDO_NONE);
S_sfx[num].singularity = value;
}
else if (fastcmp(word, "PRIORITY"))
{
- DEH_WriteUndoline(word, va("%d", S_sfx[num].priority), UNDO_NONE);
S_sfx[num].priority = value;
}
else if (fastcmp(word, "FLAGS"))
{
- DEH_WriteUndoline(word, va("%d", S_sfx[num].pitch), UNDO_NONE);
S_sfx[num].pitch = value;
}
+ else if (fastcmp(word, "CAPTION") || fastcmp(word, "DESCRIPTION"))
+ {
+ deh_strlcpy(S_sfx[num].caption, word2,
+ sizeof(S_sfx[num].caption), va("Sound effect %d: caption", num));
+ }
else
deh_warning("Sound %d : unknown word '%s'",num,word);
}
} while (!myfeof(f));
Z_Free(s);
-
- (void)savesfxnames;
}
/** Checks if a game data file name for a mod is good.
@@ -2199,11 +1976,7 @@ static boolean GoodDataFileName(const char *s)
p = s + strlen(s) - strlen(tail);
if (p <= s) return false; // too short
if (!fasticmp(p, tail)) return false; // doesn't end in .dat
-#ifdef DELFILE
- if (fasticmp(s, "gamedata.dat") && !disableundo) return false;
-#else
if (fasticmp(s, "gamedata.dat")) return false;
-#endif
return true;
}
@@ -2216,17 +1989,6 @@ static void reademblemdata(MYFILE *f, INT32 num)
char *tmp;
INT32 value;
- // Reset all data initially
- DEH_WriteUndoline("TYPE", va("%d", emblemlocations[num-1].type), UNDO_NONE);
- DEH_WriteUndoline("X", va("%d", emblemlocations[num-1].x), UNDO_NONE);
- DEH_WriteUndoline("Y", va("%d", emblemlocations[num-1].y), UNDO_NONE);
- DEH_WriteUndoline("Z", va("%d", emblemlocations[num-1].z), UNDO_NONE);
- DEH_WriteUndoline("MAPNUM", va("%d", emblemlocations[num-1].level), UNDO_NONE);
- DEH_WriteUndoline("VAR", va("%d", emblemlocations[num-1].var), UNDO_NONE);
- DEH_WriteUndoline("SPRITE", va("%d", emblemlocations[num-1].sprite), UNDO_NONE);
- DEH_WriteUndoline("COLOR", va("%d", emblemlocations[num-1].color), UNDO_NONE);
- DEH_WriteUndoline("HINT", extraemblems[num-1].hint, UNDO_NONE);
-
memset(&emblemlocations[num-1], 0, sizeof(emblem_t));
do
@@ -2278,12 +2040,12 @@ static void reademblemdata(MYFILE *f, INT32 num)
emblemlocations[num-1].type = ET_TIME;
else if (fastcmp(word2, "RINGS"))
emblemlocations[num-1].type = ET_RINGS;
+ else if (fastcmp(word2, "MAP"))
+ emblemlocations[num-1].type = ET_MAP;
else if (fastcmp(word2, "NGRADE"))
emblemlocations[num-1].type = ET_NGRADE;
else if (fastcmp(word2, "NTIME"))
emblemlocations[num-1].type = ET_NTIME;
- else if (fastcmp(word2, "MAP"))
- emblemlocations[num-1].type = ET_MAP;
else
emblemlocations[num-1].type = (UINT8)value;
}
@@ -2362,13 +2124,6 @@ static void readextraemblemdata(MYFILE *f, INT32 num)
char *tmp;
INT32 value;
- // Reset all data initially
- DEH_WriteUndoline("NAME", extraemblems[num-1].name, UNDO_NONE);
- DEH_WriteUndoline("OBJECTIVE", extraemblems[num-1].description, UNDO_NONE);
- DEH_WriteUndoline("CONDITIONSET", va("%d", extraemblems[num-1].conditionset), UNDO_NONE);
- DEH_WriteUndoline("SPRITE", va("%d", extraemblems[num-1].sprite), UNDO_NONE);
- DEH_WriteUndoline("COLOR", va("%d", extraemblems[num-1].color), UNDO_NONE);
-
memset(&extraemblems[num-1], 0, sizeof(extraemblem_t));
do
@@ -2443,17 +2198,8 @@ static void readunlockable(MYFILE *f, INT32 num)
char *tmp;
INT32 i;
- // Same deal with unlockables, clear all first
- DEH_WriteUndoline("NAME", unlockables[num].name, UNDO_NONE);
- DEH_WriteUndoline("OBJECTIVE", unlockables[num].objective, UNDO_NONE);
- DEH_WriteUndoline("HEIGHT", va("%d", unlockables[num].height), UNDO_NONE);
- DEH_WriteUndoline("CONDITIONSET", va("%d", unlockables[num].conditionset), UNDO_NONE);
- DEH_WriteUndoline("TYPE", va("%d", unlockables[num].type), UNDO_NONE);
- DEH_WriteUndoline("NOCECHO", va("%d", unlockables[num].nocecho), UNDO_NONE);
- DEH_WriteUndoline("NOCHECKLIST", va("%d", unlockables[num].nochecklist), UNDO_NONE);
- DEH_WriteUndoline("VAR", va("%d", unlockables[num].variable), UNDO_NONE);
-
memset(&unlockables[num], 0, sizeof(unlockable_t));
+ unlockables[num].objective[0] = '/';
do
{
@@ -2795,190 +2541,6 @@ static void readconditionset(MYFILE *f, UINT8 setnum)
Z_Free(s);
}
-static void readtexture(MYFILE *f, const char *name)
-{
- char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
- char *word;
- char *word2;
- char *tmp;
- INT32 i, j, value;
- UINT16 width = 0, height = 0;
- INT16 patchcount = 0;
- texture_t *texture;
-
- do
- {
- if (myfgets(s, MAXLINELEN, f))
- {
- if (s[0] == '\n')
- break;
-
- tmp = strchr(s, '#');
- if (tmp)
- *tmp = '\0';
-
- value = searchvalue(s);
- word = strtok(s, " ");
- if (word)
- strupr(word);
- else
- break;
-
- word2 = strtok(NULL, " ");
- if (word2)
- strupr(word2);
- else
- break;
-
- // Width of the texture.
- if (fastcmp(word, "WIDTH"))
- {
- DEH_WriteUndoline(word, va("%d", width), UNDO_NONE);
- width = SHORT((UINT16)value);
- }
- // Height of the texture.
- else if (fastcmp(word, "HEIGHT"))
- {
- DEH_WriteUndoline(word, va("%d", height), UNDO_NONE);
- height = SHORT((UINT16)value);
- }
- // Number of patches the texture has.
- else if (fastcmp(word, "NUMPATCHES"))
- {
- DEH_WriteUndoline(word, va("%d", patchcount), UNDO_NONE);
- patchcount = SHORT((UINT16)value);
- }
- else
- deh_warning("readtexture: unknown word '%s'", word);
- }
- } while (!myfeof(f));
-
- // Error checking.
- if (!width)
- I_Error("Texture %s has no width!\n", name);
-
- if (!height)
- I_Error("Texture %s has no height!\n", name);
-
- if (!patchcount)
- I_Error("Texture %s has no patches!\n", name);
-
- // Allocate memory for the texture, and fill in information.
- texture = Z_Calloc(sizeof(texture_t) + (sizeof(texpatch_t) * SHORT(patchcount)), PU_STATIC, NULL);
- M_Memcpy(texture->name, name, sizeof(texture->name));
- texture->width = width;
- texture->height = height;
- texture->patchcount = patchcount;
- texture->holes = false;
- // Fill out the texture patches, to allow them to be detected
- // accurately by readpatch.
- for (i = 0; i < patchcount; i++)
- {
- texture->patches[i].originx = 0;
- texture->patches[i].originy = 0;
- texture->patches[i].wad = UINT16_MAX;
- texture->patches[i].lump = UINT16_MAX;
- }
-
- // Jump to the next empty texture entry.
- i = 0;
- while (textures[i])
- i++;
-
- // Fill the global texture buffer entries.
- j = 1;
- while (j << 1 <= texture->width)
- j <<= 1;
-
- textures[i] = texture;
- texturewidthmask[i] = j - 1;
- textureheight[i] = texture->height << FRACBITS;
-
- // Clean up.
- Z_Free(s);
-}
-
-static void readpatch(MYFILE *f, const char *name, UINT16 wad)
-{
- char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
- char *word;
- char *word2;
- char *tmp;
- INT32 i = 0, j = 0, value;
- texpatch_t patch = {0, 0, UINT16_MAX, UINT16_MAX, 0, 255, AST_COPY};
-
- // Jump to the texture this patch belongs to, which,
- // coincidentally, is always the last one on the buffer cache.
- while (textures[i+1])
- i++;
-
- // Jump to the next empty patch entry.
- while (memcmp(&(textures[i]->patches[j]), &patch, sizeof(patch)))
- j++;
-
- patch.wad = wad;
- // Set the texture number, but only if the lump exists.
- if ((patch.lump = W_CheckNumForNamePwad(name, wad, 0)) == INT16_MAX)
- I_Error("readpatch: Missing patch in texture %s", textures[i]->name);
-
- // note: undoing this patch will be done by other means
- do
- {
- if (myfgets(s, MAXLINELEN, f))
- {
- if (s[0] == '\n')
- break;
-
- tmp = strchr(s, '#');
- if (tmp)
- *tmp = '\0';
-
- value = searchvalue(s);
- word = strtok(s, " ");
- if (word)
- strupr(word);
- else
- break;
-
- word2 = strtok(NULL, " ");
- if (word2)
- strupr(word2);
- else
- break;
-
- // X position of the patch in the texture.
- if (fastcmp(word, "X"))
- {
- //DEH_WriteUndoline(word, va("%d", patch->originx), UNDO_NONE);
- patch.originx = (INT16)value;
- }
- // Y position of the patch in the texture.
- else if (fastcmp(word, "Y"))
- {
- //DEH_WriteUndoline(word, va("%d", patch->originy), UNDO_NONE);
- patch.originy = (INT16)value;
- }
- else
- deh_warning("readpatch: unknown word '%s'", word);
- }
- } while (!myfeof(f));
-
- // Error checking.
- /* // Irrelevant. Origins cannot be unsigned.
- if (patch.originx == UINT16_MAX)
- I_Error("Patch %s on texture %s has no X position!\n", name, textures[i]->name);
-
- if (patch.originy == UINT16_MAX)
- I_Error("Patch %s on texture %s has no Y position!\n", name, textures[i]->name);
-*/
-
- // Set the patch as that patch number.
- textures[i]->patches[j] = patch;
-
- // Clean up.
- Z_Free(s);
-}
-
static void readmaincfg(MYFILE *f)
{
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
@@ -3030,7 +2592,6 @@ static void readmaincfg(MYFILE *f)
else
value = get_number(word2);
- DEH_WriteUndoline(word, va("%d", spstage_start), UNDO_NONE);
spstage_start = (INT16)value;
}
else if (fastcmp(word, "SSTAGE_START"))
@@ -3044,79 +2605,64 @@ static void readmaincfg(MYFILE *f)
else
value = get_number(word2);
- DEH_WriteUndoline(word, va("%d", sstage_start), UNDO_NONE);
sstage_start = (INT16)value;
sstage_end = (INT16)(sstage_start+6); // 7 special stages total
}
else if (fastcmp(word, "USENIGHTSSS"))
{
- DEH_WriteUndoline(word, va("%d", useNightsSS), UNDO_NONE);
useNightsSS = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word, "REDTEAM"))
{
- DEH_WriteUndoline(word, va("%d", skincolor_redteam), UNDO_NONE);
skincolor_redteam = (UINT8)get_number(word2);
}
else if (fastcmp(word, "BLUETEAM"))
{
- DEH_WriteUndoline(word, va("%d", skincolor_blueteam), UNDO_NONE);
skincolor_blueteam = (UINT8)get_number(word2);
}
else if (fastcmp(word, "REDRING"))
{
- DEH_WriteUndoline(word, va("%d", skincolor_redring), UNDO_NONE);
skincolor_redring = (UINT8)get_number(word2);
}
else if (fastcmp(word, "BLUERING"))
{
- DEH_WriteUndoline(word, va("%d", skincolor_bluering), UNDO_NONE);
skincolor_bluering = (UINT8)get_number(word2);
}
else if (fastcmp(word, "INVULNTICS"))
{
- DEH_WriteUndoline(word, va("%u", invulntics), UNDO_NONE);
invulntics = (UINT16)get_number(word2);
}
else if (fastcmp(word, "SNEAKERTICS"))
{
- DEH_WriteUndoline(word, va("%u", sneakertics), UNDO_NONE);
sneakertics = (UINT16)get_number(word2);
}
else if (fastcmp(word, "FLASHINGTICS"))
{
- DEH_WriteUndoline(word, va("%u", flashingtics), UNDO_NONE);
flashingtics = (UINT16)get_number(word2);
}
else if (fastcmp(word, "TAILSFLYTICS"))
{
- DEH_WriteUndoline(word, va("%u", tailsflytics), UNDO_NONE);
tailsflytics = (UINT16)get_number(word2);
}
else if (fastcmp(word, "UNDERWATERTICS"))
{
- DEH_WriteUndoline(word, va("%u", underwatertics), UNDO_NONE);
underwatertics = (UINT16)get_number(word2);
}
else if (fastcmp(word, "SPACETIMETICS"))
{
- DEH_WriteUndoline(word, va("%u", spacetimetics), UNDO_NONE);
spacetimetics = (UINT16)get_number(word2);
}
else if (fastcmp(word, "EXTRALIFETICS"))
{
- DEH_WriteUndoline(word, va("%u", extralifetics), UNDO_NONE);
extralifetics = (UINT16)get_number(word2);
}
else if (fastcmp(word, "GAMEOVERTICS"))
{
- DEH_WriteUndoline(word, va("%u", gameovertics), UNDO_NONE);
gameovertics = get_number(word2);
}
else if (fastcmp(word, "INTROTOPLAY"))
{
- DEH_WriteUndoline(word, va("%d", introtoplay), UNDO_NONE);
introtoplay = (UINT8)get_number(word2);
// range check, you morons.
if (introtoplay > 128)
@@ -3124,17 +2670,14 @@ static void readmaincfg(MYFILE *f)
}
else if (fastcmp(word, "LOOPTITLE"))
{
- DEH_WriteUndoline(word, va("%d", looptitle), UNDO_NONE);
looptitle = (boolean)(value || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word, "TITLESCROLLSPEED"))
{
- DEH_WriteUndoline(word, va("%d", titlescrollspeed), UNDO_NONE);
titlescrollspeed = get_number(word2);
}
else if (fastcmp(word, "CREDITSCUTSCENE"))
{
- DEH_WriteUndoline(word, va("%d", creditscutscene), UNDO_NONE);
creditscutscene = (UINT8)get_number(word2);
// range check, you morons.
if (creditscutscene > 128)
@@ -3142,32 +2685,26 @@ static void readmaincfg(MYFILE *f)
}
else if (fastcmp(word, "DISABLESPEEDADJUST"))
{
- DEH_WriteUndoline(word, va("%d", disableSpeedAdjust), UNDO_NONE);
disableSpeedAdjust = (UINT8)get_number(word2);
}
else if (fastcmp(word, "NUMDEMOS"))
{
- DEH_WriteUndoline(word, va("%d", numDemos), UNDO_NONE);
numDemos = (UINT8)get_number(word2);
}
else if (fastcmp(word, "DEMODELAYTIME"))
{
- DEH_WriteUndoline(word, va("%d", demoDelayTime), UNDO_NONE);
demoDelayTime = get_number(word2);
}
else if (fastcmp(word, "DEMOIDLETIME"))
{
- DEH_WriteUndoline(word, va("%d", demoIdleTime), UNDO_NONE);
demoIdleTime = get_number(word2);
}
else if (fastcmp(word, "USE1UPSOUND"))
{
- DEH_WriteUndoline(word, va("%u", use1upSound), UNDO_NONE);
use1upSound = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word, "MAXXTRALIFE"))
{
- DEH_WriteUndoline(word, va("%u", maxXtraLife), UNDO_NONE);
maxXtraLife = (UINT8)get_number(word2);
}
@@ -3181,7 +2718,6 @@ static void readmaincfg(MYFILE *f)
I_Error("Maincfg: bad data file name '%s'\n", word2);
G_SaveGameData();
- DEH_WriteUndoline(word, gamedatafilename, UNDO_NONE);
strlcpy(gamedatafilename, word2, sizeof (gamedatafilename));
strlwr(gamedatafilename);
savemoddata = true;
@@ -3198,12 +2734,10 @@ static void readmaincfg(MYFILE *f)
}
else if (fastcmp(word, "RESETDATA"))
{
- DEH_WriteUndoline(word, "0", UNDO_TODO); /// \todo
P_ResetData(value);
}
else if (fastcmp(word, "CUSTOMVERSION"))
{
- DEH_WriteUndoline(word, customversionstring, UNDO_NONE);
strlcpy(customversionstring, word2, sizeof (customversionstring));
}
else
@@ -3389,30 +2923,17 @@ static void ignorelines(MYFILE *f)
Z_Free(s);
}
-static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
+static void DEH_LoadDehackedFile(MYFILE *f)
{
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
char *word;
char *word2;
INT32 i;
- // do a copy of this for cross references probleme
- //XBOXSTATIC actionf_t saveactions[NUMSTATES];
- //XBOXSTATIC const char *savesprnames[NUMSPRITES];
- XBOXSTATIC const char *savesfxnames[NUMSFX];
if (!deh_loaded)
initfreeslots();
deh_num_warning = 0;
- // save values for cross reference
- /*
- for (i = 0; i < NUMSTATES; i++)
- saveactions[i] = states[i].action;
- for (i = 0; i < NUMSPRITES; i++)
- savesprnames[i] = sprnames[i];
- */
- for (i = 0; i < NUMSFX; i++)
- savesfxnames[i] = S_sfx[i].name;
gamedataadded = false;
@@ -3454,13 +2975,11 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
else if (fastcmp(word, "MAINCFG"))
{
readmaincfg(f);
- DEH_WriteUndoline(word, "", UNDO_HEADER);
continue;
}
else if (fastcmp(word, "WIPES"))
{
readwipes(f);
- DEH_WriteUndoline(word, "", UNDO_HEADER);
continue;
}
word2 = strtok(NULL, " ");
@@ -3480,7 +2999,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("Character %d out of range (0 - 31)", i);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
continue;
}
if (word2)
@@ -3489,19 +3007,8 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
if (word2[strlen(word2)-1] == '\n')
word2[strlen(word2)-1] = '\0';
i = atoi(word2);
- if (fastcmp(word, "TEXTURE"))
- {
- // Read texture from spec file.
- readtexture(f, word2);
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
- }
- else if (fastcmp(word, "PATCH"))
- {
- // Read patch from spec file.
- readpatch(f, word2, wad);
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
- }
- else if (fastcmp(word, "THING") || fastcmp(word, "MOBJ") || fastcmp(word, "OBJECT"))
+
+ if (fastcmp(word, "THING") || fastcmp(word, "MOBJ") || fastcmp(word, "OBJECT"))
{
if (i == 0 && word2[0] != '0') // If word2 isn't a number
i = get_mobjtype(word2); // find a thing by name
@@ -3512,12 +3019,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("Thing %d out of range (1 - %d)", i, NUMMOBJTYPES-1);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
-/* else if (fastcmp(word, "ANIMTEX"))
- {
- readAnimTex(f, i);
- }*/
else if (fastcmp(word, "LIGHT"))
{
#ifdef HWRENDER
@@ -3529,7 +3031,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("Light number %d out of range (1 - %d)", i, NUMLIGHTS-1);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
#endif
}
else if (fastcmp(word, "SPRITE"))
@@ -3544,7 +3045,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("Sprite number %d out of range (0 - %d)", i, NUMSPRITES-1);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
#endif
}
else if (fastcmp(word, "LEVEL"))
@@ -3563,7 +3063,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("Level number %d out of range (1 - %d)", i, NUMMAPS);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if (fastcmp(word, "CUTSCENE"))
{
@@ -3574,7 +3073,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("Cutscene number %d out of range (1 - 128)", i);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if (fastcmp(word, "FRAME") || fastcmp(word, "STATE"))
{
@@ -3587,63 +3085,19 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("Frame %d out of range (0 - %d)", i, NUMSTATES-1);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
- // Added translations to this just in case its re-enabled
-/* else if (fastcmp(word, "POINTER"))
- {
- word = strtok(NULL, " "); // get frame
- word = strtok(NULL, ")");
- if (word)
- {
- i = atoi(word);
- if (i < NUMSTATES && i >= 0)
- {
- if (myfgets(s, MAXLINELEN, f))
- states[i].action = saveactions[searchvalue(s)];
- }
- else
- {
- deh_warning("Pointer: Frame %d doesn't exist", i);
- ignorelines(f);
- }
- }
- else
- deh_warning("pointer (Frame %d) : missing ')'", i);
- }*/
else if (fastcmp(word, "SOUND"))
{
if (i == 0 && word2[0] != '0') // If word2 isn't a number
i = get_sfx(word2); // find a sound by name
- if (i < NUMSFX && i >= 0)
- readsound(f, i, savesfxnames);
+ if (i < NUMSFX && i > 0)
+ readsound(f, i);
else
{
- deh_warning("Sound %d out of range (0 - %d)", i, NUMSFX-1);
+ deh_warning("Sound %d out of range (1 - %d)", i, NUMSFX-1);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
-/* else if (fastcmp(word, "SPRITE"))
- {
- if (i < NUMSPRITES && i >= 0)
- {
- if (myfgets(s, MAXLINELEN, f))
- {
- INT32 k;
- k = (searchvalue(s) - 151328)/8;
- if (k >= 0 && k < NUMSPRITES)
- sprnames[i] = savesprnames[k];
- else
- {
- deh_warning("Sprite %d: offset out of bounds", i);
- ignorelines(f);
- }
- }
- }
- else
- deh_warning("Sprite %d doesn't exist",i);
- }*/
else if (fastcmp(word, "HUDITEM"))
{
if (i == 0 && word2[0] != '0') // If word2 isn't a number
@@ -3655,7 +3109,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("HUD item number %d out of range (0 - %d)", i, NUMHUDITEMS-1);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if (fastcmp(word, "EMBLEM"))
{
@@ -3675,7 +3128,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("Emblem number %d out of range (1 - %d)", i, MAXEMBLEMS);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if (fastcmp(word, "EXTRAEMBLEM"))
{
@@ -3695,7 +3147,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("Extra emblem number %d out of range (1 - %d)", i, MAXEXTRAEMBLEMS);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if (fastcmp(word, "UNLOCKABLE"))
{
@@ -3711,7 +3162,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("Unlockable number %d out of range (1 - %d)", i, MAXUNLOCKABLES);
ignorelines(f);
}
- DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
else if (fastcmp(word, "CONDITIONSET"))
{
@@ -3727,20 +3177,21 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("Condition set number %d out of range (1 - %d)", i, MAXCONDITIONSETS);
ignorelines(f);
}
- // no undo support for this insanity yet
- //DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
- else if (fastcmp(word, "SRB2"))
+ // Last I heard this crashes the game if you try to use it
+ // so this is disabled for now
+ // -- Monster Iestyn
+/* else if (fastcmp(word, "SRB2"))
{
INT32 ver = searchvalue(strtok(NULL, "\n"));
if (ver != PATCHVERSION)
deh_warning("Patch is for SRB2 version %d,\nonly version %d is supported", ver, PATCHVERSION);
- //DEH_WriteUndoline(word, va("%d", ver), UNDO_NONE);
}
// Clear all data in certain locations (mostly for unlocks)
// Unless you REALLY want to piss people off,
// define a custom gamedata /before/ doing this!!
// (then again, modifiedgame will prevent game data saving anyway)
+*/
else if (fastcmp(word, "CLEAR"))
{
boolean clearall = (fastcmp(word2, "ALL"));
@@ -3805,17 +3256,13 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
void DEH_LoadDehackedLumpPwad(UINT16 wad, UINT16 lump)
{
MYFILE f;
-#ifdef DELFILE
- unsocwad = wad;
-#endif
f.wad = wad;
f.size = W_LumpLengthPwad(wad, lump);
f.data = Z_Malloc(f.size + 1, PU_STATIC, NULL);
W_ReadLumpPwad(wad, lump, f.data);
f.curpos = f.data;
f.data[f.size] = 0;
- DEH_LoadDehackedFile(&f, wad);
- DEH_WriteUndoline(va("# uload for wad: %u, lump: %u", wad, lump), NULL, UNDO_DONE);
+ DEH_LoadDehackedFile(&f);
Z_Free(f.data);
}
@@ -3824,67 +3271,6 @@ void DEH_LoadDehackedLump(lumpnum_t lumpnum)
DEH_LoadDehackedLumpPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum));
}
-#ifdef DELFILE
-#define DUMPUNDONE
-
-// read (un)dehacked lump in wad's memory
-void DEH_UnloadDehackedWad(UINT16 wad)
-{
- undehacked_t *tmp, *curundo = unsocdata[wad];
- MYFILE f;
- size_t len = 0;
- char *data;
-#ifdef DUMPUNDONE
- FILE *UNDO = fopen("undo.soc", "wt");
-#endif
- CONS_Printf(M_GetText("Unloading WAD SOC edits\n"));
- while (curundo)
- {
- data = curundo->undata;
- curundo = curundo->next;
- if (data)
- len += strlen(data);
- len += 1;
-#ifdef DUMPUNDONE
- if (UNDO)
- {
- if (data)
- fprintf(UNDO, "%s\n", data);
- else
- fprintf(UNDO, "\n");
- }
-#endif
- }
-#ifndef DUMPUNDONE
- if (UNDO) fclose(UNDO);
-#endif
- if (!len) return;
- f.size = len;
- data = f.data = Z_Malloc(f.size + 1, PU_STATIC, NULL);
- curundo = unsocdata[wad];
- unsocdata[wad] = NULL;
- while (curundo)
- {
- tmp = curundo;
- curundo = curundo->next;
- if (tmp->undata)
- data += sprintf(data, "%s\n", tmp->undata);
- else
- data += sprintf(data, "\n");
- if (tmp->undata) free(tmp->undata);
- free(tmp);
- }
- f.wad = wad;
- f.curpos = f.data;
- f.data[f.size] = 0;
- disableundo = true;
- DEH_LoadDehackedFile(&f);
- disableundo = false;
- Z_Free(f.data);
-}
-#endif //DELFILE
-
-
////////////////////////////////////////////////////////////////////////////////
// CRAZY LIST OF STATE NAMES AND ALL FROM HERE DOWN
// TODO: Make this all a seperate file or something, like part of info.c??
@@ -4822,12 +4208,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// Individual Team Rings
"S_TEAMRING",
- // Special Stage Token
- "S_EMMY",
-
// Special Stage Token
"S_TOKEN",
- "S_MOVINGTOKEN",
// CTF Flags
"S_REDFLAG",
@@ -4978,6 +4360,17 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_SPIKED1",
"S_SPIKED2",
+ // Wall spikes
+ "S_WALLSPIKE1",
+ "S_WALLSPIKE2",
+ "S_WALLSPIKE3",
+ "S_WALLSPIKE4",
+ "S_WALLSPIKE5",
+ "S_WALLSPIKE6",
+ "S_WALLSPIKEBASE",
+ "S_WALLSPIKED1",
+ "S_WALLSPIKED2",
+
// Starpost
"S_STARPOST_IDLE",
"S_STARPOST_FLASH",
@@ -5164,6 +4557,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_DEMONFIRE5",
"S_DEMONFIRE6",
+ // GFZ flowers
"S_GFZFLOWERA",
"S_GFZFLOWERB",
"S_GFZFLOWERC",
@@ -5171,6 +4565,18 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_BERRYBUSH",
"S_BUSH",
+ // Trees (both GFZ and misc)
+ "S_GFZTREE",
+ "S_GFZBERRYTREE",
+ "S_GFZCHERRYTREE",
+ "S_CHECKERTREE",
+ "S_CHECKERSUNSETTREE",
+ "S_FHZTREE", // Frozen Hillside
+ "S_FHZPINKTREE",
+ "S_POLYGONTREE",
+ "S_BUSHTREE",
+ "S_BUSHREDTREE",
+
// THZ Plant
"S_THZFLOWERA",
"S_THZFLOWERB",
@@ -5180,6 +4586,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// Deep Sea Gargoyle
"S_GARGOYLE",
+ "S_BIGGARGOYLE",
// DSZ Seaweed
"S_SEAWEED1",
@@ -5231,18 +4638,62 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_SLING1",
"S_SLING2",
- // CEZ Small Mace Chain
+ // CEZ maces and chains
"S_SMALLMACECHAIN",
-
- // CEZ Big Mace Chain
"S_BIGMACECHAIN",
-
- // CEZ Small Mace
"S_SMALLMACE",
-
- // CEZ Big Mace
"S_BIGMACE",
+ // Yellow spring on a ball
+ "S_YELLOWSPRINGBALL",
+ "S_YELLOWSPRINGBALL2",
+ "S_YELLOWSPRINGBALL3",
+ "S_YELLOWSPRINGBALL4",
+ "S_YELLOWSPRINGBALL5",
+
+ // Red spring on a ball
+ "S_REDSPRINGBALL",
+ "S_REDSPRINGBALL2",
+ "S_REDSPRINGBALL3",
+ "S_REDSPRINGBALL4",
+ "S_REDSPRINGBALL5",
+
+ // Small Firebar
+ "S_SMALLFIREBAR1",
+ "S_SMALLFIREBAR2",
+ "S_SMALLFIREBAR3",
+ "S_SMALLFIREBAR4",
+ "S_SMALLFIREBAR5",
+ "S_SMALLFIREBAR6",
+ "S_SMALLFIREBAR7",
+ "S_SMALLFIREBAR8",
+ "S_SMALLFIREBAR9",
+ "S_SMALLFIREBAR10",
+ "S_SMALLFIREBAR11",
+ "S_SMALLFIREBAR12",
+ "S_SMALLFIREBAR13",
+ "S_SMALLFIREBAR14",
+ "S_SMALLFIREBAR15",
+ "S_SMALLFIREBAR16",
+
+ // Big Firebar
+ "S_BIGFIREBAR1",
+ "S_BIGFIREBAR2",
+ "S_BIGFIREBAR3",
+ "S_BIGFIREBAR4",
+ "S_BIGFIREBAR5",
+ "S_BIGFIREBAR6",
+ "S_BIGFIREBAR7",
+ "S_BIGFIREBAR8",
+ "S_BIGFIREBAR9",
+ "S_BIGFIREBAR10",
+ "S_BIGFIREBAR11",
+ "S_BIGFIREBAR12",
+ "S_BIGFIREBAR13",
+ "S_BIGFIREBAR14",
+ "S_BIGFIREBAR15",
+ "S_BIGFIREBAR16",
+
"S_CEZFLOWER1",
// Big Tumbleweed
@@ -5338,7 +4789,14 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// Xmas-specific stuff
"S_XMASPOLE",
"S_CANDYCANE",
- "S_SNOWMAN",
+ "S_SNOWMAN", // normal
+ "S_SNOWMANHAT", // with hat + scarf
+ "S_LAMPPOST1", // normal
+ "S_LAMPPOST2", // with snow
+ "S_HANGSTAR",
+ // Xmas GFZ bushes
+ "S_XMASBERRYBUSH",
+ "S_XMASBUSH",
// Botanic Serenity's loads of scenery states
"S_BSZTALLFLOWER_RED",
@@ -5530,10 +4988,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_PITY4",
"S_PITY5",
"S_PITY6",
- "S_PITY7",
- "S_PITY8",
- "S_PITY9",
- "S_PITY10",
"S_FIRS1",
"S_FIRS2",
@@ -6213,16 +5667,11 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_NIGHTSWING_XMAS",
// NiGHTS Paraloop Powerups
- "S_NIGHTSPOWERUP1",
- "S_NIGHTSPOWERUP2",
- "S_NIGHTSPOWERUP3",
- "S_NIGHTSPOWERUP4",
- "S_NIGHTSPOWERUP5",
- "S_NIGHTSPOWERUP6",
- "S_NIGHTSPOWERUP7",
- "S_NIGHTSPOWERUP8",
- "S_NIGHTSPOWERUP9",
- "S_NIGHTSPOWERUP10",
+ "S_NIGHTSSUPERLOOP",
+ "S_NIGHTSDRILLREFILL",
+ "S_NIGHTSHELPER",
+ "S_NIGHTSEXTRATIME",
+ "S_NIGHTSLINKFREEZE",
"S_EGGCAPSULE",
// Orbiting Chaos Emeralds
@@ -6419,8 +5868,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_BLUEBALL", // Blue sphere replacement for special stages
"MT_REDTEAMRING", //Rings collectable by red team.
"MT_BLUETEAMRING", //Rings collectable by blue team.
- "MT_EMMY", // emerald token for special stage
- "MT_TOKEN", // Special Stage Token (uncollectible part)
+ "MT_TOKEN", // Special Stage Token
"MT_REDFLAG", // Red CTF Flag
"MT_BLUEFLAG", // Blue CTF Flag
"MT_EMBLEM",
@@ -6454,6 +5902,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_SPECIALSPIKEBALL",
"MT_SPINFIRE",
"MT_SPIKE",
+ "MT_WALLSPIKE",
+ "MT_WALLSPIKEBASE",
"MT_STARPOST",
"MT_BIGMINE",
"MT_BIGAIRMINE",
@@ -6544,6 +5994,17 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_GFZFLOWER3",
"MT_BERRYBUSH",
"MT_BUSH",
+ // Trees (both GFZ and misc)
+ "MT_GFZTREE",
+ "MT_GFZBERRYTREE",
+ "MT_GFZCHERRYTREE",
+ "MT_CHECKERTREE",
+ "MT_CHECKERSUNSETTREE",
+ "MT_FHZTREE", // Frozen Hillside
+ "MT_FHZPINKTREE",
+ "MT_POLYGONTREE",
+ "MT_BUSHTREE",
+ "MT_BUSHREDTREE",
// Techno Hill Scenery
"MT_THZFLOWER1",
@@ -6552,6 +6013,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
// Deep Sea Scenery
"MT_GARGOYLE", // Deep Sea Gargoyle
+ "MT_BIGGARGOYLE", // Deep Sea Gargoyle (Big)
"MT_SEAWEED", // DSZ Seaweed
"MT_WATERDRIP", // Dripping Water source
"MT_WATERDROP", // Water drop from dripping water
@@ -6566,14 +6028,20 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_FLAMEPARTICLE",
"MT_EGGSTATUE", // Eggman Statue
"MT_MACEPOINT", // Mace rotation point
- "MT_SWINGMACEPOINT", // Mace swinging point
- "MT_HANGMACEPOINT", // Hangable mace chain
- "MT_SPINMACEPOINT", // Spin/Controllable mace chain
+ "MT_CHAINMACEPOINT", // Combination of chains and maces point
+ "MT_SPRINGBALLPOINT", // Spring ball point
+ "MT_CHAINPOINT", // Mace chain
"MT_HIDDEN_SLING", // Spin mace chain (activatable)
+ "MT_FIREBARPOINT", // Firebar
+ "MT_CUSTOMMACEPOINT", // Custom mace
"MT_SMALLMACECHAIN", // Small Mace Chain
"MT_BIGMACECHAIN", // Big Mace Chain
"MT_SMALLMACE", // Small Mace
"MT_BIGMACE", // Big Mace
+ "MT_YELLOWSPRINGBALL", // Yellow spring on a ball
+ "MT_REDSPRINGBALL", // Red spring on a ball
+ "MT_SMALLFIREBAR", // Small Firebar
+ "MT_BIGFIREBAR", // Big Firebar
"MT_CEZFLOWER",
// Arid Canyon Scenery
@@ -6620,7 +6088,14 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
// Christmas Scenery
"MT_XMASPOLE",
"MT_CANDYCANE",
- "MT_SNOWMAN",
+ "MT_SNOWMAN", // normal
+ "MT_SNOWMANHAT", // with hat + scarf
+ "MT_LAMPPOST1", // normal
+ "MT_LAMPPOST2", // with snow
+ "MT_HANGSTAR",
+ // Xmas GFZ bushes
+ "MT_XMASBERRYBUSH",
+ "MT_XMASBUSH",
// Botanic Serenity
"MT_BSZTALLFLOWER_RED",
@@ -6919,6 +6394,7 @@ static const char *const MOBJFLAG2_LIST[] = {
"AMBUSH", // Alternate behaviour typically set by MTF_AMBUSH
"LINKDRAW", // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position)
"SHIELD", // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use)
+ "MACEROTATE", // Thinker calls P_MaceRotate around tracer
NULL
};
@@ -7029,91 +6505,130 @@ static const char *const ML_LIST[16] = {
// This DOES differ from r_draw's Color_Names, unfortunately.
// Also includes Super colors
static const char *COLOR_ENUMS[] = {
- "NONE", // SKINCOLOR_NONE
- "WHITE", // SKINCOLOR_WHITE
- "SILVER", // SKINCOLOR_SILVER
- "GREY", // SKINCOLOR_GREY
- "BLACK", // SKINCOLOR_BLACK
- "BEIGE", // SKINCOLOR_BEIGE
- "PEACH", // SKINCOLOR_PEACH
- "BROWN", // SKINCOLOR_BROWN
- "RED", // SKINCOLOR_RED
- "CRIMSON", // SKINCOLOR_CRIMSON
- "ORANGE", // SKINCOLOR_ORANGE
- "RUST", // SKINCOLOR_RUST
- "GOLD", // SKINCOLOR_GOLD
- "YELLOW", // SKINCOLOR_YELLOW
- "TAN", // SKINCOLOR_TAN
- "MOSS", // SKINCOLOR_MOSS
- "PERIDOT", // SKINCOLOR_PERIDOT
- "GREEN", // SKINCOLOR_GREEN
- "EMERALD", // SKINCOLOR_EMERALD
- "AQUA", // SKINCOLOR_AQUA
- "TEAL", // SKINCOLOR_TEAL
- "CYAN", // SKINCOLOR_CYAN
- "BLUE", // SKINCOLOR_BLUE
- "AZURE", // SKINCOLOR_AZURE
- "PASTEL", // SKINCOLOR_PASTEL
- "PURPLE", // SKINCOLOR_PURPLE
- "LAVENDER", // SKINCOLOR_LAVENDER
- "MAGENTA", // SKINCOLOR_MAGENTA
- "PINK", // SKINCOLOR_PINK
- "ROSY", // SKINCOLOR_ROSY
+ "NONE", // SKINCOLOR_NONE,
+
+ // Greyscale ranges
+ "WHITE", // SKINCOLOR_WHITE,
+ "BONE", // SKINCOLOR_BONE,
+ "CLOUDY", // SKINCOLOR_CLOUDY,
+ "GREY", // SKINCOLOR_GREY,
+ "SILVER", // SKINCOLOR_SILVER,
+ "CARBON", // SKINCOLOR_CARBON,
+ "JET", // SKINCOLOR_JET,
+ "BLACK", // SKINCOLOR_BLACK,
+
+ // Desaturated
+ "AETHER", // SKINCOLOR_AETHER,
+ "SLATE", // SKINCOLOR_SLATE,
+ "PINK", // SKINCOLOR_PINK,
+ "YOGURT", // SKINCOLOR_YOGURT,
+ "BROWN", // SKINCOLOR_BROWN,
+ "TAN", // SKINCOLOR_TAN,
+ "BEIGE", // SKINCOLOR_BEIGE,
+ "MOSS", // SKINCOLOR_MOSS,
+ "AZURE", // SKINCOLOR_AZURE,
+ "LAVENDER", // SKINCOLOR_LAVENDER,
+
+ // Viv's vivid colours (toast 21/07/17)
+ "RUBY", // SKINCOLOR_RUBY,
+ "SALMON", // SKINCOLOR_SALMON,
+ "RED", // SKINCOLOR_RED,
+ "CRIMSON", // SKINCOLOR_CRIMSON,
+ "FLAME", // SKINCOLOR_FLAME,
+ "PEACHY", // SKINCOLOR_PEACHY,
+ "QUAIL", // SKINCOLOR_QUAIL,
+ "SUNSET", // SKINCOLOR_SUNSET,
+ "APRICOT", // SKINCOLOR_APRICOT,
+ "ORANGE", // SKINCOLOR_ORANGE,
+ "RUST", // SKINCOLOR_RUST,
+ "GOLD", // SKINCOLOR_GOLD,
+ "SANDY", // SKINCOLOR_SANDY,
+ "YELLOW", // SKINCOLOR_YELLOW,
+ "OLIVE", // SKINCOLOR_OLIVE,
+ "LIME", // SKINCOLOR_LIME,
+ "PERIDOT", // SKINCOLOR_PERIDOT,
+ "GREEN", // SKINCOLOR_GREEN,
+ "FOREST", // SKINCOLOR_FOREST,
+ "EMERALD", // SKINCOLOR_EMERALD,
+ "MINT", // SKINCOLOR_MINT,
+ "SEAFOAM", // SKINCOLOR_SEAFOAM,
+ "AQUA", // SKINCOLOR_AQUA,
+ "TEAL", // SKINCOLOR_TEAL,
+ "WAVE", // SKINCOLOR_WAVE,
+ "CYAN", // SKINCOLOR_CYAN,
+ "SKY", // SKINCOLOR_SKY,
+ "CERULEAN", // SKINCOLOR_CERULEAN,
+ "ICY", // SKINCOLOR_ICY,
+ "SAPPHIRE", // SKINCOLOR_SAPPHIRE,
+ "CORNFLOWER", // SKINCOLOR_CORNFLOWER,
+ "BLUE", // SKINCOLOR_BLUE,
+ "COBALT", // SKINCOLOR_COBALT,
+ "VAPOR", // SKINCOLOR_VAPOR,
+ "DUSK", // SKINCOLOR_DUSK,
+ "PASTEL", // SKINCOLOR_PASTEL,
+ "PURPLE", // SKINCOLOR_PURPLE,
+ "BUBBLEGUM", // SKINCOLOR_BUBBLEGUM,
+ "MAGENTA", // SKINCOLOR_MAGENTA,
+ "NEON", // SKINCOLOR_NEON,
+ "VIOLET", // SKINCOLOR_VIOLET,
+ "LILAC", // SKINCOLOR_LILAC,
+ "PLUM", // SKINCOLOR_PLUM,
+ "ROSY", // SKINCOLOR_ROSY,
// Super special awesome Super flashing colors!
- "SUPERSILVER1", // SKINCOLOR_SUPERSILVER1
- "SUPERSILVER2", // SKINCOLOR_SUPERSILVER2,
- "SUPERSILVER3", // SKINCOLOR_SUPERSILVER3,
- "SUPERSILVER4", // SKINCOLOR_SUPERSILVER4,
- "SUPERSILVER5", // SKINCOLOR_SUPERSILVER5,
+ "SUPERSILVER1", // SKINCOLOR_SUPERSILVER1
+ "SUPERSILVER2", // SKINCOLOR_SUPERSILVER2,
+ "SUPERSILVER3", // SKINCOLOR_SUPERSILVER3,
+ "SUPERSILVER4", // SKINCOLOR_SUPERSILVER4,
+ "SUPERSILVER5", // SKINCOLOR_SUPERSILVER5,
- "SUPERRED1", // SKINCOLOR_SUPERRED1
- "SUPERRED2", // SKINCOLOR_SUPERRED2,
- "SUPERRED3", // SKINCOLOR_SUPERRED3,
- "SUPERRED4", // SKINCOLOR_SUPERRED4,
- "SUPERRED5", // SKINCOLOR_SUPERRED5,
+ "SUPERRED1", // SKINCOLOR_SUPERRED1
+ "SUPERRED2", // SKINCOLOR_SUPERRED2,
+ "SUPERRED3", // SKINCOLOR_SUPERRED3,
+ "SUPERRED4", // SKINCOLOR_SUPERRED4,
+ "SUPERRED5", // SKINCOLOR_SUPERRED5,
- "SUPERORANGE1", // SKINCOLOR_SUPERORANGE1
- "SUPERORANGE2", // SKINCOLOR_SUPERORANGE2,
- "SUPERORANGE3", // SKINCOLOR_SUPERORANGE3,
- "SUPERORANGE4", // SKINCOLOR_SUPERORANGE4,
- "SUPERORANGE5", // SKINCOLOR_SUPERORANGE5,
+ "SUPERORANGE1", // SKINCOLOR_SUPERORANGE1
+ "SUPERORANGE2", // SKINCOLOR_SUPERORANGE2,
+ "SUPERORANGE3", // SKINCOLOR_SUPERORANGE3,
+ "SUPERORANGE4", // SKINCOLOR_SUPERORANGE4,
+ "SUPERORANGE5", // SKINCOLOR_SUPERORANGE5,
- "SUPERGOLD1", // SKINCOLOR_SUPERGOLD1
- "SUPERGOLD2", // SKINCOLOR_SUPERGOLD2,
- "SUPERGOLD3", // SKINCOLOR_SUPERGOLD3,
- "SUPERGOLD4", // SKINCOLOR_SUPERGOLD4,
- "SUPERGOLD5", // SKINCOLOR_SUPERGOLD5,
+ "SUPERGOLD1", // SKINCOLOR_SUPERGOLD1
+ "SUPERGOLD2", // SKINCOLOR_SUPERGOLD2,
+ "SUPERGOLD3", // SKINCOLOR_SUPERGOLD3,
+ "SUPERGOLD4", // SKINCOLOR_SUPERGOLD4,
+ "SUPERGOLD5", // SKINCOLOR_SUPERGOLD5,
- "SUPERPERIDOT1", // SKINCOLOR_SUPERPERIDOT1
- "SUPERPERIDOT2", // SKINCOLOR_SUPERPERIDOT2,
- "SUPERPERIDOT3", // SKINCOLOR_SUPERPERIDOT3,
- "SUPERPERIDOT4", // SKINCOLOR_SUPERPERIDOT4,
- "SUPERPERIDOT5", // SKINCOLOR_SUPERPERIDOT5,
+ "SUPERPERIDOT1", // SKINCOLOR_SUPERPERIDOT1
+ "SUPERPERIDOT2", // SKINCOLOR_SUPERPERIDOT2,
+ "SUPERPERIDOT3", // SKINCOLOR_SUPERPERIDOT3,
+ "SUPERPERIDOT4", // SKINCOLOR_SUPERPERIDOT4,
+ "SUPERPERIDOT5", // SKINCOLOR_SUPERPERIDOT5,
- "SUPERCYAN1", // SKINCOLOR_SUPERCYAN1
- "SUPERCYAN2", // SKINCOLOR_SUPERCYAN2,
- "SUPERCYAN3", // SKINCOLOR_SUPERCYAN3,
- "SUPERCYAN4", // SKINCOLOR_SUPERCYAN4,
- "SUPERCYAN5", // SKINCOLOR_SUPERCYAN5,
+ "SUPERSKY1", // SKINCOLOR_SUPERSKY1
+ "SUPERSKY2", // SKINCOLOR_SUPERSKY2,
+ "SUPERSKY3", // SKINCOLOR_SUPERSKY3,
+ "SUPERSKY4", // SKINCOLOR_SUPERSKY4,
+ "SUPERSKY5", // SKINCOLOR_SUPERSKY5,
- "SUPERPURPLE1", // SKINCOLOR_SUPERPURPLE1,
- "SUPERPURPLE2", // SKINCOLOR_SUPERPURPLE2,
- "SUPERPURPLE3", // SKINCOLOR_SUPERPURPLE3,
- "SUPERPURPLE4", // SKINCOLOR_SUPERPURPLE4,
- "SUPERPURPLE5", // SKINCOLOR_SUPERPURPLE5,
+ "SUPERPURPLE1", // SKINCOLOR_SUPERPURPLE1,
+ "SUPERPURPLE2", // SKINCOLOR_SUPERPURPLE2,
+ "SUPERPURPLE3", // SKINCOLOR_SUPERPURPLE3,
+ "SUPERPURPLE4", // SKINCOLOR_SUPERPURPLE4,
+ "SUPERPURPLE5", // SKINCOLOR_SUPERPURPLE5,
- "SUPERRUST1", // SKINCOLOR_SUPERRUST1
- "SUPERRUST2", // SKINCOLOR_SUPERRUST2,
- "SUPERRUST3", // SKINCOLOR_SUPERRUST3,
- "SUPERRUST4", // SKINCOLOR_SUPERRUST4,
- "SUPERRUST5", // SKINCOLOR_SUPERRUST5,
+ "SUPERRUST1", // SKINCOLOR_SUPERRUST1
+ "SUPERRUST2", // SKINCOLOR_SUPERRUST2,
+ "SUPERRUST3", // SKINCOLOR_SUPERRUST3,
+ "SUPERRUST4", // SKINCOLOR_SUPERRUST4,
+ "SUPERRUST5", // SKINCOLOR_SUPERRUST5,
- "SUPERTAN1", // SKINCOLOR_SUPERTAN1
- "SUPERTAN2", // SKINCOLOR_SUPERTAN2,
- "SUPERTAN3", // SKINCOLOR_SUPERTAN3,
- "SUPERTAN4", // SKINCOLOR_SUPERTAN4,
- "SUPERTAN5" // SKINCOLOR_SUPERTAN5,
+ "SUPERTAN1", // SKINCOLOR_SUPERTAN1
+ "SUPERTAN2", // SKINCOLOR_SUPERTAN2,
+ "SUPERTAN3", // SKINCOLOR_SUPERTAN3,
+ "SUPERTAN4", // SKINCOLOR_SUPERTAN4,
+ "SUPERTAN5" // SKINCOLOR_SUPERTAN5,
};
static const char *const POWERS_LIST[] = {
@@ -7306,6 +6821,7 @@ struct {
{"LF_NOSSMUSIC",LF_NOSSMUSIC},
{"LF_NORELOAD",LF_NORELOAD},
{"LF_NOZONE",LF_NOZONE},
+ {"LF_SAVEGAME",LF_SAVEGAME},
// And map flags
{"LF2_HIDEINMENU",LF2_HIDEINMENU},
{"LF2_HIDEINSTATS",LF2_HIDEINSTATS},
@@ -7351,6 +6867,7 @@ struct {
{"SH_PROTECTFIRE",SH_PROTECTFIRE},
{"SH_PROTECTWATER",SH_PROTECTWATER},
{"SH_PROTECTELECTRIC",SH_PROTECTELECTRIC},
+ {"SH_PROTECTSPIKE",SH_PROTECTSPIKE},
// Indivisible shields
{"SH_PITY",SH_PITY},
{"SH_WHIRLWIND",SH_WHIRLWIND},
@@ -7438,7 +6955,11 @@ struct {
{"SF_X8AWAYSOUND",SF_X8AWAYSOUND},
{"SF_NOINTERRUPT",SF_NOINTERRUPT},
{"SF_X2AWAYSOUND",SF_X2AWAYSOUND},
-
+
+ // Global emblem var flags
+ {"GE_NIGHTSPULL",GE_NIGHTSPULL},
+ {"GE_NIGHTSITEM",GE_NIGHTSITEM},
+
// Map emblem var flags
{"ME_ALLEMERALDS",ME_ALLEMERALDS},
{"ME_ULTIMATE",ME_ULTIMATE},
@@ -8120,11 +7641,14 @@ void FUNCMATH DEH_Check(void)
static inline int lib_freeslot(lua_State *L)
{
int n = lua_gettop(L);
- int r = 0; // args returned
+ int r = 0; // args returned
char *s, *type,*word;
- while (n-- > 0)
- {
+ if (!lua_lumploading)
+ return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
+
+ while (n-- > 0)
+ {
s = Z_StrDup(luaL_checkstring(L,1));
type = strtok(s, "_");
if (type)
diff --git a/src/dehacked.h b/src/dehacked.h
index 8832216b8..dfce996a2 100644
--- a/src/dehacked.h
+++ b/src/dehacked.h
@@ -27,13 +27,6 @@ typedef enum
UNDO_DONE = 0,
} undotype_f;
-#ifdef DELFILE
-void DEH_WriteUndoline(const char *value, const char *data, undotype_f flags);
-void DEH_UnloadDehackedWad(UINT16 wad);
-#else // null the undo lines
-#define DEH_WriteUndoline(a,b,c)
-#endif
-
void DEH_LoadDehackedLump(lumpnum_t lumpnum);
void DEH_LoadDehackedLumpPwad(UINT16 wad, UINT16 lump);
diff --git a/src/djgppdos/i_video.c b/src/djgppdos/i_video.c
index 612c72215..6a7641174 100644
--- a/src/djgppdos/i_video.c
+++ b/src/djgppdos/i_video.c
@@ -90,6 +90,10 @@ static unsigned long nombre = NEWTICRATE*10;
static void I_BlitScreenVesa1(void); //see later
void I_FinishUpdate (void)
{
+ // draw captions if enabled
+ if (cv_closedcaptioning.value)
+ SCR_ClosedCaptions();
+
// draw FPS if enabled
if (cv_ticrate.value)
SCR_DisplayTicRate();
diff --git a/src/doomdata.h b/src/doomdata.h
index 033cc71b3..c0586fd65 100644
--- a/src/doomdata.h
+++ b/src/doomdata.h
@@ -207,8 +207,9 @@ typedef struct
#define ZSHIFT 4
+extern const UINT8 Color_Index[MAXTRANSLATIONS-1][16];
extern const char *Color_Names[MAXSKINCOLORS + NUMSUPERCOLORS];
-extern const UINT8 Color_Opposite[MAXSKINCOLORS*2];
+extern const UINT8 Color_Opposite[(MAXSKINCOLORS - 1)*2];
#define NUMMAPS 1035
diff --git a/src/doomdef.h b/src/doomdef.h
index 73ecf7dc9..4d6bf75bb 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -214,7 +214,7 @@ extern FILE *logstream;
// it's only for detection of the version the player is using so the MS can alert them of an update.
// Only set it higher, not lower, obviously.
// Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1".
-#define MODVERSION 22
+#define MODVERSION 24
// =========================================================================
@@ -229,39 +229,77 @@ extern FILE *logstream;
typedef enum
{
SKINCOLOR_NONE = 0,
+
+ // Greyscale ranges
SKINCOLOR_WHITE,
- SKINCOLOR_SILVER,
+ SKINCOLOR_BONE,
+ SKINCOLOR_CLOUDY,
SKINCOLOR_GREY,
+ SKINCOLOR_SILVER,
+ SKINCOLOR_CARBON,
+ SKINCOLOR_JET,
SKINCOLOR_BLACK,
- SKINCOLOR_BEIGE,
- SKINCOLOR_PEACH,
+
+ // Desaturated
+ SKINCOLOR_AETHER,
+ SKINCOLOR_SLATE,
+ SKINCOLOR_PINK,
+ SKINCOLOR_YOGURT,
SKINCOLOR_BROWN,
+ SKINCOLOR_TAN,
+ SKINCOLOR_BEIGE,
+ SKINCOLOR_MOSS,
+ SKINCOLOR_AZURE,
+ SKINCOLOR_LAVENDER,
+
+ // Viv's vivid colours (toast 21/07/17)
+ SKINCOLOR_RUBY,
+ SKINCOLOR_SALMON,
SKINCOLOR_RED,
SKINCOLOR_CRIMSON,
+ SKINCOLOR_FLAME,
+ SKINCOLOR_PEACHY,
+ SKINCOLOR_QUAIL,
+ SKINCOLOR_SUNSET,
+ SKINCOLOR_APRICOT,
SKINCOLOR_ORANGE,
SKINCOLOR_RUST,
SKINCOLOR_GOLD,
+ SKINCOLOR_SANDY,
SKINCOLOR_YELLOW,
- SKINCOLOR_TAN,
- SKINCOLOR_MOSS,
+ SKINCOLOR_OLIVE,
+ SKINCOLOR_LIME,
SKINCOLOR_PERIDOT,
SKINCOLOR_GREEN,
+ SKINCOLOR_FOREST,
SKINCOLOR_EMERALD,
+ SKINCOLOR_MINT,
+ SKINCOLOR_SEAFOAM,
SKINCOLOR_AQUA,
SKINCOLOR_TEAL,
+ SKINCOLOR_WAVE,
SKINCOLOR_CYAN,
+ SKINCOLOR_SKY,
+ SKINCOLOR_CERULEAN,
+ SKINCOLOR_ICY,
+ SKINCOLOR_SAPPHIRE, // sweet mother, i cannot weave – slender aphrodite has overcome me with longing for a girl
+ SKINCOLOR_CORNFLOWER,
SKINCOLOR_BLUE,
- SKINCOLOR_AZURE,
+ SKINCOLOR_COBALT,
+ SKINCOLOR_VAPOR,
+ SKINCOLOR_DUSK,
SKINCOLOR_PASTEL,
SKINCOLOR_PURPLE,
- SKINCOLOR_LAVENDER,
+ SKINCOLOR_BUBBLEGUM,
SKINCOLOR_MAGENTA,
- SKINCOLOR_PINK,
+ SKINCOLOR_NEON,
+ SKINCOLOR_VIOLET,
+ SKINCOLOR_LILAC,
+ SKINCOLOR_PLUM,
SKINCOLOR_ROSY,
- //SKINCOLOR_?
- //SKINCOLOR_?
- // Careful! MAXSKINCOLORS cannot be greater than 0x20! Two slots left...
+ // SKINCOLOR_? - one left before we bump up against 0x39, which isn't a HARD limit anymore but would be excessive
+
MAXSKINCOLORS,
// Super special awesome Super flashing colors!
@@ -295,11 +333,11 @@ typedef enum
SKINCOLOR_SUPERPERIDOT4,
SKINCOLOR_SUPERPERIDOT5,
- SKINCOLOR_SUPERCYAN1,
- SKINCOLOR_SUPERCYAN2,
- SKINCOLOR_SUPERCYAN3,
- SKINCOLOR_SUPERCYAN4,
- SKINCOLOR_SUPERCYAN5,
+ SKINCOLOR_SUPERSKY1,
+ SKINCOLOR_SUPERSKY2,
+ SKINCOLOR_SUPERSKY3,
+ SKINCOLOR_SUPERSKY4,
+ SKINCOLOR_SUPERSKY5,
SKINCOLOR_SUPERPURPLE1,
SKINCOLOR_SUPERPURPLE2,
@@ -483,10 +521,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
#define ESLOPE_TYPESHIM
#endif
-/// Delete file while the game is running.
-/// \note EXTREMELY buggy, tends to crash game.
-//#define DELFILE
-
/// Allows the use of devmode in multiplayer. AKA "fishcake"
//#define NETGAME_DEVMODE
@@ -546,4 +580,15 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// Hudname padding.
#define SKINNAMEPADDING
+/// FINALLY some real clipping that doesn't make walls dissappear AND speeds the game up
+/// (that was the original comment from SRB2CB, sadly it is a lie and actually slows game down)
+/// on the bright side it fixes some weird issues with translucent walls
+/// \note SRB2CB port.
+/// SRB2CB itself ported this from PrBoom+
+#define NEWCLIP
+
+/// Handle touching sector specials in P_PlayerAfterThink instead of P_PlayerThink.
+/// \note Required for proper collision with moving sloped surfaces that have sector specials on them.
+//#define SECTORSPECIALSAFTERTHINK
+
#endif // __DOOMDEF__
diff --git a/src/doomstat.h b/src/doomstat.h
index 7ee0382b2..a24bad79d 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -41,7 +41,8 @@ extern INT16 maptol;
extern UINT8 globalweather;
extern INT32 curWeather;
extern INT32 cursaveslot;
-extern INT16 lastmapsaved;
+//extern INT16 lastmapsaved;
+extern INT16 lastmaploaded;
extern boolean gamecomplete;
#define PRECIP_NONE 0
@@ -263,6 +264,7 @@ typedef struct
#define LF_NOSSMUSIC 4 ///< Disable Super Sonic music
#define LF_NORELOAD 8 ///< Don't reload level on death
#define LF_NOZONE 16 ///< Don't include "ZONE" on level title
+#define LF_SAVEGAME 32 ///< Save the game upon loading this level
#define LF2_HIDEINMENU 1 ///< Hide in the multiplayer menu
#define LF2_HIDEINSTATS 2 ///< Hide in the statistics screen
@@ -379,6 +381,7 @@ nightsdata_t ntemprecords;
extern UINT32 token; ///< Number of tokens collected in a level
extern UINT32 tokenlist; ///< List of tokens collected
+extern boolean gottoken; ///< Did you get a token? Used for end of act
extern INT32 tokenbits; ///< Used for setting token bits
extern INT32 sstimer; ///< Time allotted in the special stage
extern UINT32 bluescore; ///< Blue Team Scores
@@ -452,19 +455,17 @@ extern mapthing_t *redctfstarts[MAXPLAYERS]; // CTF
#if defined (macintosh)
#define DEBFILE(msg) I_OutputMsg(msg)
-extern FILE *debugfile;
#else
#define DEBUGFILE
#ifdef DEBUGFILE
#define DEBFILE(msg) { if (debugfile) { fputs(msg, debugfile); fflush(debugfile); } }
-extern FILE *debugfile;
#else
#define DEBFILE(msg) {}
-extern FILE *debugfile;
#endif
#endif
#ifdef DEBUGFILE
+extern FILE *debugfile;
extern INT32 debugload;
#endif
diff --git a/src/f_finale.c b/src/f_finale.c
index 167fdd880..db497daf7 100644
--- a/src/f_finale.c
+++ b/src/f_finale.c
@@ -434,7 +434,6 @@ void F_StartIntro(void)
G_SetGamestate(GS_INTRO);
gameaction = ga_nothing;
- playerdeadview = false;
paused = false;
CON_ToggleOff();
CON_ClearHUD();
@@ -1125,7 +1124,6 @@ void F_StartCredits(void)
}
gameaction = ga_nothing;
- playerdeadview = false;
paused = false;
CON_ToggleOff();
CON_ClearHUD();
@@ -1272,7 +1270,6 @@ void F_StartGameEvaluation(void)
G_SaveGame((UINT32)cursaveslot);
gameaction = ga_nothing;
- playerdeadview = false;
paused = false;
CON_ToggleOff();
CON_ClearHUD();
@@ -1383,7 +1380,6 @@ void F_StartGameEnd(void)
G_SetGamestate(GS_GAMEEND);
gameaction = ga_nothing;
- playerdeadview = false;
paused = false;
CON_ToggleOff();
CON_ClearHUD();
@@ -1586,7 +1582,6 @@ void F_StartContinue(void)
gameaction = ga_nothing;
keypressed = false;
- playerdeadview = false;
paused = false;
CON_ToggleOff();
CON_ClearHUD();
@@ -1728,7 +1723,7 @@ static void F_AdvanceToNextScene(void)
void F_EndCutScene(void)
{
- cutsceneover = true; // do this first, just in case Y_EndGame or something wants to turn it back false later
+ cutsceneover = true; // do this first, just in case G_EndGame or something wants to turn it back false later
if (runningprecutscene)
{
if (server)
@@ -1743,7 +1738,7 @@ void F_EndCutScene(void)
else if (nextmap < 1100-1)
G_NextLevel();
else
- Y_EndGame();
+ G_EndGame();
}
}
@@ -1755,7 +1750,6 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset
G_SetGamestate(GS_CUTSCENE);
gameaction = ga_nothing;
- playerdeadview = false;
paused = false;
CON_ToggleOff();
diff --git a/src/f_wipe.c b/src/f_wipe.c
index a0b685a32..acc4efaaa 100644
--- a/src/f_wipe.c
+++ b/src/f_wipe.c
@@ -86,7 +86,7 @@ INT32 lastwipetic = 0;
static UINT8 *wipe_scr_start; //screen 3
static UINT8 *wipe_scr_end; //screen 4
static UINT8 *wipe_scr; //screen 0 (main drawing)
-static fixed_t paldiv;
+static fixed_t paldiv = 0;
/** Create fademask_t from lump
*
@@ -145,7 +145,7 @@ static fademask_t *F_GetFadeMask(UINT8 masknum, UINT8 scrnnum) {
while (lsize--)
{
// Determine pixel to use from fademask
- pcolor = &pLocalPalette[*lump++];
+ pcolor = &pMasterPalette[*lump++];
*mask++ = FixedDiv((pcolor->s.red+1)<>FRACBITS;
}
@@ -337,7 +337,8 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
UINT8 wipeframe = 0;
fademask_t *fmask;
- paldiv = FixedDiv(257<dd_stat = 0;
+
+ return 0;
+}
+
/*
* closedir
*
@@ -285,6 +309,35 @@ closedir (DIR * dirp)
return rc;
}
#endif
+
+static CV_PossibleValue_t addons_cons_t[] = {{0, "SRB2 Folder"}, /*{1, "HOME"}, {2, "SRB2 Folder"},*/ {3, "CUSTOM"}, {0, NULL}};
+consvar_t cv_addons_option = {"addons_option", "SRB2 Folder", CV_SAVE|CV_CALL, addons_cons_t, Addons_option_Onchange, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_addons_folder = {"addons_folder", "./", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
+
+static CV_PossibleValue_t addons_md5_cons_t[] = {{0, "Name"}, {1, "Contents"}, {0, NULL}};
+consvar_t cv_addons_md5 = {"addons_md5", "Name", CV_SAVE, addons_md5_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+
+consvar_t cv_addons_showall = {"addons_showall", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
+
+consvar_t cv_addons_search_case = {"addons_search_case", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
+
+static CV_PossibleValue_t addons_search_type_cons_t[] = {{0, "Start"}, {1, "Anywhere"}, {0, NULL}};
+consvar_t cv_addons_search_type = {"addons_search_type", "Anywhere", CV_SAVE, addons_search_type_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+
+char menupath[1024];
+size_t menupathindex[menudepth];
+size_t menudepthleft = menudepth;
+
+char menusearch[MAXSTRINGLENGTH+1];
+
+char **dirmenu;
+size_t sizedirmenu;
+size_t dir_on[menudepth];
+UINT8 refreshdirmenu = 0;
+
+size_t packetsizetally = 0;
+size_t mainwadstally = 0;
+
#if defined (_XBOX) && defined (_MSC_VER)
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
boolean completepath, int maxsearchdepth)
@@ -296,6 +349,13 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
completepath = false;
return FS_NOTFOUND;
}
+
+boolean preparefilemenu(boolean samedepth)
+{
+ (void)samedepth;
+ return false;
+}
+
#elif defined (_WIN32_WCE)
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
boolean completepath, int maxsearchdepth)
@@ -346,6 +406,12 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
#endif
return FS_NOTFOUND;
}
+
+boolean preparefilemenu(boolean samedepth)
+{
+ (void)samedepth;
+ return false;
+}
#else
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth)
{
@@ -387,25 +453,29 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
{
searchpath[searchpathindex[depthleft]]=0;
dent = readdir(dirhandle[depthleft]);
- if (dent)
- strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name);
if (!dent)
+ {
closedir(dirhandle[depthleft++]);
- else if (dent->d_name[0]=='.' &&
+ continue;
+ }
+
+ if (dent->d_name[0]=='.' &&
(dent->d_name[1]=='\0' ||
(dent->d_name[1]=='.' &&
dent->d_name[2]=='\0')))
{
// we don't want to scan uptree
+ continue;
}
- else if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
- {
- // was the file (re)moved? can't stat it
- }
+
+ // okay, now we actually want searchpath to incorporate d_name
+ strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name);
+
+ if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
+ ; // was the file (re)moved? can't stat it
else if (S_ISDIR(fsstat.st_mode) && depthleft)
{
- strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name);
searchpathindex[--depthleft] = strlen(searchpath) + 1;
dirhandle[depthleft] = opendir(searchpath);
if (!dirhandle[depthleft])
@@ -444,6 +514,255 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
free(searchname);
free(searchpathindex);
free(dirhandle);
+
return retval;
}
+
+char exttable[NUM_EXT_TABLE][5] = {
+ ".txt", ".cfg", // exec
+ ".wad", ".soc", ".lua"}; // addfile
+
+char filenamebuf[MAX_WADFILES][MAX_WADPATH];
+
+
+static boolean filemenusearch(char *haystack, char *needle)
+{
+ static char localhaystack[128];
+ strlcpy(localhaystack, haystack, 128);
+ if (!cv_addons_search_case.value)
+ strupr(localhaystack);
+ return ((cv_addons_search_type.value)
+ ? (strstr(localhaystack, needle) != 0)
+ : (!strncmp(localhaystack, needle, menusearch[0])));
+}
+
+#define searchdir if (menusearch[0] && !filemenusearch(dent->d_name, localmenusearch))\
+ {\
+ rejected++;\
+ continue;\
+ }\
+
+boolean preparefilemenu(boolean samedepth)
+{
+ DIR *dirhandle;
+ struct dirent *dent;
+ struct stat fsstat;
+ size_t pos = 0, folderpos = 0, numfolders = 0, rejected = 0;
+ char *tempname = NULL;
+ boolean noresults = false;
+ char localmenusearch[MAXSTRINGLENGTH] = "";
+
+ if (samedepth)
+ {
+ if (dirmenu && dirmenu[dir_on[menudepthleft]])
+ tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL
+ }
+ else
+ menusearch[0] = menusearch[1] = 0; // clear search
+
+ for (; sizedirmenu > 0; sizedirmenu--) // clear out existing items
+ {
+ Z_Free(dirmenu[sizedirmenu-1]);
+ dirmenu[sizedirmenu-1] = NULL;
+ }
+
+ if (!(dirhandle = opendir(menupath))) // get directory
+ return false;
+
+ if (menusearch[0])
+ {
+ strcpy(localmenusearch, menusearch+1);
+ if (!cv_addons_search_case.value)
+ strupr(localmenusearch);
+ }
+
+ while (true)
+ {
+ menupath[menupathindex[menudepthleft]] = 0;
+ dent = readdir(dirhandle);
+
+ if (!dent)
+ break;
+ else if (dent->d_name[0]=='.' &&
+ (dent->d_name[1]=='\0' ||
+ (dent->d_name[1]=='.' &&
+ dent->d_name[2]=='\0')))
+ continue; // we don't want to scan uptree
+
+ strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name);
+
+ if (stat(menupath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
+ ; // was the file (re)moved? can't stat it
+ else // is a file or directory
+ {
+ if (!S_ISDIR(fsstat.st_mode)) // file
+ {
+ if (!cv_addons_showall.value)
+ {
+ size_t len = strlen(dent->d_name)+1;
+ UINT8 ext;
+ for (ext = 0; ext < NUM_EXT_TABLE; ext++)
+ if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; // extension comparison
+ if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file
+ }
+ searchdir;
+ }
+ else // directory
+ {
+ searchdir;
+ numfolders++;
+ }
+ sizedirmenu++;
+ }
+ }
+
+ if (!rejected && !sizedirmenu)
+ {
+ if (tempname)
+ Z_Free(tempname);
+ closedir(dirhandle);
+ return false;
+ }
+
+ if (((noresults = (menusearch[0] && !sizedirmenu)))
+ || (!menusearch[0] && menudepthleft != menudepth-1)) // Make room for UP... or search entry
+ {
+ sizedirmenu++;
+ numfolders++;
+ folderpos++;
+ }
+
+ if (!(dirmenu = Z_Realloc(dirmenu, sizedirmenu*sizeof(char *), PU_STATIC, NULL)))
+ {
+ closedir(dirhandle); // just in case
+ I_Error("Ran out of memory whilst preparing add-ons menu");
+ }
+
+ rejected = 0;
+ rewinddir(dirhandle);
+
+ while ((pos+folderpos) < sizedirmenu)
+ {
+ menupath[menupathindex[menudepthleft]] = 0;
+ dent = readdir(dirhandle);
+
+ if (!dent)
+ break;
+ else if (dent->d_name[0]=='.' &&
+ (dent->d_name[1]=='\0' ||
+ (dent->d_name[1]=='.' &&
+ dent->d_name[2]=='\0')))
+ continue; // we don't want to scan uptree
+
+ strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name);
+
+ if (stat(menupath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
+ ; // was the file (re)moved? can't stat it
+ else // is a file or directory
+ {
+ char *temp;
+ size_t len = strlen(dent->d_name)+1;
+ UINT8 ext = EXT_FOLDER;
+ UINT8 folder;
+
+ if (!S_ISDIR(fsstat.st_mode)) // file
+ {
+ if (!((numfolders+pos) < sizedirmenu)) continue; // crash prevention
+ for (; ext < NUM_EXT_TABLE; ext++)
+ if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; // extension comparison
+ if (ext == NUM_EXT_TABLE && !cv_addons_showall.value) continue; // not an addfile-able (or exec-able) file
+ ext += EXT_START; // moving to be appropriate position
+
+ searchdir;
+
+ if (ext >= EXT_LOADSTART)
+ {
+ size_t i;
+ for (i = 0; i < numwadfiles; i++)
+ {
+ if (!filenamebuf[i][0])
+ {
+ strncpy(filenamebuf[i], wadfiles[i]->filename, MAX_WADPATH);
+ filenamebuf[i][MAX_WADPATH - 1] = '\0';
+ nameonly(filenamebuf[i]);
+ }
+
+ if (strcmp(dent->d_name, filenamebuf[i]))
+ continue;
+ if (cv_addons_md5.value && !checkfilemd5(menupath, wadfiles[i]->md5sum))
+ continue;
+
+ ext |= EXT_LOADED;
+ }
+ }
+ else if (ext == EXT_TXT)
+ {
+ if (!strcmp(dent->d_name, "log.txt") || !strcmp(dent->d_name, "errorlog.txt"))
+ ext |= EXT_LOADED;
+ }
+
+ if (!strcmp(dent->d_name, configfile))
+ ext |= EXT_LOADED;
+
+ folder = 0;
+ }
+ else // directory
+ {
+ searchdir;
+ len += (folder = 1);
+ }
+
+ if (len > 255)
+ len = 255;
+
+ if (!(temp = Z_Malloc((len+DIR_STRING+folder) * sizeof (char), PU_STATIC, NULL)))
+ I_Error("Ran out of memory whilst preparing add-ons menu");
+ temp[DIR_TYPE] = ext;
+ temp[DIR_LEN] = (UINT8)(len);
+ strlcpy(temp+DIR_STRING, dent->d_name, len);
+ if (folder)
+ {
+ strcpy(temp+len, "/");
+ dirmenu[folderpos++] = temp;
+ }
+ else
+ dirmenu[numfolders + pos++] = temp;
+ }
+ }
+
+ closedir(dirhandle);
+
+ if (noresults) // no results
+ dirmenu[0] = Z_StrDup(va("%c\13No results...", EXT_NORESULTS));
+ else if (!menusearch[0] &&menudepthleft != menudepth-1) // now for UP... entry
+ dirmenu[0] = Z_StrDup(va("%c\5UP...", EXT_UP));
+
+ menupath[menupathindex[menudepthleft]] = 0;
+ sizedirmenu = (numfolders+pos); // just in case things shrink between opening and rewind
+
+ if (tempname)
+ {
+ size_t i;
+ for (i = 0; i < sizedirmenu; i++)
+ {
+ if (!strcmp(dirmenu[i]+DIR_STRING, tempname))
+ {
+ dir_on[menudepthleft] = i;
+ break;
+ }
+ }
+ Z_Free(tempname);
+ }
+
+ if (!sizedirmenu)
+ {
+ dir_on[menudepthleft] = 0;
+ Z_Free(dirmenu);
+ return false;
+ }
+ else if (dir_on[menudepthleft] >= sizedirmenu)
+ dir_on[menudepthleft] = sizedirmenu-1;
+
+ return true;
+}
#endif
diff --git a/src/filesrch.h b/src/filesrch.h
index 33b148d4b..c2201b453 100644
--- a/src/filesrch.h
+++ b/src/filesrch.h
@@ -6,6 +6,9 @@
#include "doomdef.h"
#include "d_netfil.h"
+#include "m_menu.h" // MAXSTRINGLENGTH
+
+extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_showall, cv_addons_search_case, cv_addons_search_type;
/** \brief The filesearch function
@@ -25,4 +28,64 @@
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
boolean completepath, int maxsearchdepth);
+#define menudepth 20
+
+extern char menupath[1024];
+extern size_t menupathindex[menudepth];
+extern size_t menudepthleft;
+
+extern char menusearch[MAXSTRINGLENGTH+1];
+
+extern char **dirmenu;
+extern size_t sizedirmenu;
+extern size_t dir_on[menudepth];
+extern UINT8 refreshdirmenu;
+
+extern size_t packetsizetally;
+extern size_t mainwadstally;
+
+typedef enum
+{
+ EXT_FOLDER = 0,
+ EXT_UP,
+ EXT_NORESULTS,
+ EXT_START,
+ EXT_TXT = EXT_START,
+ EXT_CFG,
+ EXT_LOADSTART,
+ EXT_WAD = EXT_LOADSTART,
+ EXT_SOC,
+ EXT_LUA, // allowed even if not HAVE_BLUA so that we can yell on load attempt
+ NUM_EXT,
+ NUM_EXT_TABLE = NUM_EXT-EXT_START,
+ EXT_LOADED = 0x80
+ /*
+ obviously there can only be 0x7F supported extensions in
+ addons menu because we're cramming this into a char out of
+ laziness/easy memory allocation (what's the difference?)
+ and have stolen a bit to show whether it's loaded or not
+ in practice the size of the data type is probably overkill
+ toast 02/05/17
+ */
+} ext_enum;
+
+typedef enum
+{
+ DIR_TYPE = 0,
+ DIR_LEN,
+ DIR_STRING
+} dirname_enum;
+
+typedef enum
+{
+ REFRESHDIR_NORMAL = 1,
+ REFRESHDIR_ADDFILE = 2,
+ REFRESHDIR_WARNING = 4,
+ REFRESHDIR_ERROR = 8,
+ REFRESHDIR_NOTLOADED = 16,
+ REFRESHDIR_MAX = 32
+} refreshdir_enum;
+
+boolean preparefilemenu(boolean samedepth);
+
#endif // __FILESRCH_H__
diff --git a/src/g_game.c b/src/g_game.c
index 8bd71d123..e996938ab 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -77,7 +77,8 @@ INT16 maptol;
UINT8 globalweather = 0;
INT32 curWeather = PRECIP_NONE;
INT32 cursaveslot = -1; // Auto-save 1p savegame slot
-INT16 lastmapsaved = 0; // Last map we auto-saved at
+//INT16 lastmapsaved = 0; // Last map we auto-saved at
+INT16 lastmaploaded = 0; // Last map the game loaded
boolean gamecomplete = false;
UINT16 mainwads = 0;
@@ -156,6 +157,7 @@ UINT8 stagefailed; // Used for GEMS BONUS? Also to see if you beat the stage.
UINT16 emeralds;
UINT32 token; // Number of tokens collected in a level
UINT32 tokenlist; // List of tokens collected
+boolean gottoken; // Did you get a token? Used for end of act
INT32 tokenbits; // Used for setting token bits
// Old Special Stage
@@ -1011,13 +1013,13 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
if (turnleft)
cmd->angleturn = (INT16)(cmd->angleturn + angleturn[tspeed]);
}
- if (cv_analog.value || twodlevel
+ if (twodlevel
|| (player->mo && (player->mo->flags2 & MF2_TWOD))
|| (!demoplayback && (player->climbing
|| (player->powers[pw_carry] == CR_NIGHTSMODE)
|| (player->pflags & (PF_SLIDING|PF_FORCESTRAFE))))) // Analog
forcestrafe = true;
- if (forcestrafe) // Analog
+ if (forcestrafe)
{
if (turnright)
side += sidemove[speed];
@@ -1030,6 +1032,13 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
side += ((axis * sidemove[1]) >> 10);
}
}
+ else if (cv_analog.value) // Analog
+ {
+ if (turnright)
+ cmd->buttons |= BT_CAMRIGHT;
+ if (turnleft)
+ cmd->buttons |= BT_CAMLEFT;
+ }
else
{
if (turnright)
@@ -1117,15 +1126,6 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
if (PLAYER1INPUTDOWN(gc_use))
cmd->buttons |= BT_USE;
- // Camera Controls
- if (cv_debug || cv_analog.value || demoplayback || objectplacing || player->powers[pw_carry] == CR_NIGHTSMODE)
- {
- if (PLAYER1INPUTDOWN(gc_camleft))
- cmd->buttons |= BT_CAMLEFT;
- if (PLAYER1INPUTDOWN(gc_camright))
- cmd->buttons |= BT_CAMRIGHT;
- }
-
if (PLAYER1INPUTDOWN(gc_camreset))
{
if (camera.chase && !resetdown)
@@ -1187,10 +1187,19 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
if (!mouseaiming && cv_mousemove.value)
forward += mousey;
- if (cv_analog.value ||
- (!demoplayback && (player->climbing
+ if ((!demoplayback && (player->climbing
|| (player->pflags & PF_SLIDING)))) // Analog for mouse
side += mousex*2;
+ else if (cv_analog.value)
+ {
+ if (mousex)
+ {
+ if (mousex > 0)
+ cmd->buttons |= BT_CAMRIGHT;
+ else
+ cmd->buttons |= BT_CAMLEFT;
+ }
+ }
else
cmd->angleturn = (INT16)(cmd->angleturn - (mousex*8));
@@ -1225,9 +1234,10 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
cmd->sidemove = (SINT8)(cmd->sidemove + side);
if (cv_analog.value) {
- cmd->angleturn = (INT16)(thiscam->angle >> 16);
if (player->awayviewtics)
cmd->angleturn = (INT16)(player->awayviewmobj->angle >> 16);
+ else
+ cmd->angleturn = (INT16)(thiscam->angle >> 16);
}
else
{
@@ -1301,7 +1311,7 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
if (turnleft)
cmd->angleturn = (INT16)(cmd->angleturn + angleturn[tspeed]);
}
- if (cv_analog2.value || twodlevel
+ if (twodlevel
|| (player->mo && (player->mo->flags2 & MF2_TWOD))
|| player->climbing
|| (player->powers[pw_carry] == CR_NIGHTSMODE)
@@ -1320,6 +1330,13 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
side += ((axis * sidemove[1]) >> 10);
}
}
+ else if (cv_analog2.value) // Analog
+ {
+ if (turnright)
+ cmd->buttons |= BT_CAMRIGHT;
+ if (turnleft)
+ cmd->buttons |= BT_CAMLEFT;
+ }
else
{
if (turnright)
@@ -1404,15 +1421,6 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
if (PLAYER2INPUTDOWN(gc_use))
cmd->buttons |= BT_USE;
- // Camera Controls
- if (cv_debug || cv_analog2.value || player->powers[pw_carry] == CR_NIGHTSMODE)
- {
- if (PLAYER2INPUTDOWN(gc_camleft))
- cmd->buttons |= BT_CAMLEFT;
- if (PLAYER2INPUTDOWN(gc_camright))
- cmd->buttons |= BT_CAMRIGHT;
- }
-
if (PLAYER2INPUTDOWN(gc_camreset))
{
if (camera2.chase && !resetdown)
@@ -1474,9 +1482,19 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
if (!mouseaiming && cv_mousemove2.value)
forward += mouse2y;
- if (cv_analog2.value || player->climbing
+ if (player->climbing
|| (player->pflags & PF_SLIDING)) // Analog for mouse
side += mouse2x*2;
+ else if (cv_analog2.value)
+ {
+ if (mouse2x)
+ {
+ if (mouse2x > 0)
+ cmd->buttons |= BT_CAMRIGHT;
+ else
+ cmd->buttons |= BT_CAMLEFT;
+ }
+ }
else
cmd->angleturn = (INT16)(cmd->angleturn - (mouse2x*8));
@@ -1524,9 +1542,10 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
}
if (cv_analog2.value) {
- cmd->angleturn = (INT16)(thiscam->angle >> 16);
if (player->awayviewtics)
cmd->angleturn = (INT16)(player->awayviewmobj->angle >> 16);
+ else
+ cmd->angleturn = (INT16)(thiscam->angle >> 16);
}
else
{
@@ -2072,6 +2091,7 @@ void G_PlayerReborn(INT32 player)
UINT32 availabilities;
tic_t jointime;
boolean spectator;
+ boolean outofcoop;
INT16 bot;
SINT8 pity;
@@ -2082,6 +2102,7 @@ void G_PlayerReborn(INT32 player)
exiting = players[player].exiting;
jointime = players[player].jointime;
spectator = players[player].spectator;
+ outofcoop = players[player].outofcoop;
pflags = (players[player].pflags & (PF_TIMEOVER|PF_FLIPCAM|PF_TAGIT|PF_TAGGED|PF_ANALOGMODE));
// As long as we're not in multiplayer, carry over cheatcodes from map to map
@@ -2136,6 +2157,7 @@ void G_PlayerReborn(INT32 player)
p->ctfteam = ctfteam;
p->jointime = jointime;
p->spectator = spectator;
+ p->outofcoop = outofcoop;
// save player config truth reborn
p->skincolor = skincolor;
@@ -2187,8 +2209,8 @@ void G_PlayerReborn(INT32 player)
p->rings = 0; // 0 rings
p->panim = PA_IDLE; // standing animation
- if ((netgame || multiplayer) && !p->spectator)
- p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent
+ //if ((netgame || multiplayer) && !p->spectator) -- moved into P_SpawnPlayer to account for forced changes there
+ //p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent
if (p-players == consoleplayer)
{
@@ -2291,6 +2313,9 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost)
if (starpost) //Don't even bother with looking for a place to spawn.
{
P_MovePlayerToStarpost(playernum);
+#ifdef HAVE_BLUA
+ LUAh_PlayerSpawn(&players[playernum]); // Lua hook for player spawning :)
+#endif
return;
}
@@ -2474,7 +2499,8 @@ void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo)
void G_DoReborn(INT32 playernum)
{
player_t *player = &players[playernum];
- boolean starpost = false;
+ boolean resetlevel = false;
+ INT32 i;
if (modeattacking)
{
@@ -2500,35 +2526,98 @@ void G_DoReborn(INT32 playernum)
B_RespawnBot(playernum);
if (oldmo)
G_ChangePlayerReferences(oldmo, players[playernum].mo);
+
+ return;
}
- else if (countdowntimeup || (!multiplayer && gametype == GT_COOP))
+
+ if (countdowntimeup || (!(netgame || multiplayer) && gametype == GT_COOP))
+ resetlevel = true;
+ else if (gametype == GT_COOP && (netgame || multiplayer))
+ {
+ boolean notgameover = true;
+
+ if (cv_cooplives.value != 0 && player->lives <= 0) // consider game over first
+ {
+ for (i = 0; i < MAXPLAYERS; i++)
+ {
+ if (!playeringame[i])
+ continue;
+ if (players[i].exiting || players[i].lives > 0)
+ break;
+ }
+
+ if (i == MAXPLAYERS)
+ {
+ notgameover = false;
+ if (!countdown2)
+ {
+ // They're dead, Jim.
+ //nextmapoverride = spstage_start;
+ nextmapoverride = gamemap;
+ countdown2 = TICRATE;
+ skipstats = true;
+
+ for (i = 0; i < MAXPLAYERS; i++)
+ {
+ if (playeringame[i])
+ players[i].score = 0;
+ }
+
+ //emeralds = 0;
+ tokenbits = 0;
+ tokenlist = 0;
+ token = 0;
+ }
+ }
+ }
+
+ if (notgameover && cv_coopstarposts.value == 2)
+ {
+ for (i = 0; i < MAXPLAYERS; i++)
+ {
+ if (!playeringame[i])
+ continue;
+
+ if (players[i].playerstate != PST_DEAD && !players[i].spectator && players[i].mo && players[i].mo->health)
+ break;
+ }
+ if (i == MAXPLAYERS)
+ resetlevel = true;
+ }
+ }
+
+ if (resetlevel)
{
// reload the level from scratch
if (countdowntimeup)
{
- player->starpostangle = 0;
- player->starposttime = 0;
- player->starpostx = 0;
- player->starposty = 0;
- player->starpostz = 0;
- player->starpostnum = 0;
+ for (i = 0; i < MAXPLAYERS; i++)
+ {
+ if (!playeringame[i])
+ continue;
+ players[i].starpostangle = 0;
+ players[i].starposttime = 0;
+ players[i].starpostx = 0;
+ players[i].starposty = 0;
+ players[i].starpostz = 0;
+ players[i].starpostnum = 0;
+ }
}
if (!countdowntimeup && (mapheaderinfo[gamemap-1]->levelflags & LF_NORELOAD))
{
- INT32 i;
-
- player->playerstate = PST_REBORN;
-
P_LoadThingsOnly();
- P_ClearStarPost(player->starpostnum);
+ for (i = 0; i < MAXPLAYERS; i++)
+ {
+ if (!playeringame[i])
+ continue;
+ players[i].playerstate = PST_REBORN;
+ P_ClearStarPost(players[i].starpostnum);
+ }
// Do a wipe
wipegamestate = -1;
- if (player->starposttime)
- starpost = true;
-
if (camera.chase)
P_ResetCamera(&players[displayplayer], &camera);
if (camera2.chase && splitscreen)
@@ -2536,7 +2625,7 @@ void G_DoReborn(INT32 playernum)
// clear cmd building stuff
memset(gamekeydown, 0, sizeof (gamekeydown));
- for (i = 0;i < JOYAXISSET; i++)
+ for (i = 0; i < JOYAXISSET; i++)
{
joyxmove[i] = joyymove[i] = 0;
joy2xmove[i] = joy2ymove[i] = 0;
@@ -2548,31 +2637,45 @@ void G_DoReborn(INT32 playernum)
CON_ClearHUD();
// Starpost support
- G_SpawnPlayer(playernum, starpost);
+ for (i = 0; i < MAXPLAYERS; i++)
+ {
+ if (!playeringame[i])
+ continue;
+ G_SpawnPlayer(i, (players[i].starposttime));
+ }
- if (botingame)
- { // Bots respawn next to their master.
- players[secondarydisplayplayer].playerstate = PST_REBORN;
- G_SpawnPlayer(secondarydisplayplayer, false);
+ // restore time in netgame (see also p_setup.c)
+ if ((netgame || multiplayer) && gametype == GT_COOP && cv_coopstarposts.value == 2)
+ {
+ // is this a hack? maybe
+ tic_t maxstarposttime = 0;
+ for (i = 0; i < MAXPLAYERS; i++)
+ {
+ if (playeringame[i] && players[i].starposttime > maxstarposttime)
+ maxstarposttime = players[i].starposttime;
+ }
+ leveltime = maxstarposttime;
}
}
else
-#ifdef HAVE_BLUA
{
+#ifdef HAVE_BLUA
LUAh_MapChange();
#endif
G_DoLoadLevel(true);
-#ifdef HAVE_BLUA
+ return;
}
-#endif
}
else
{
// respawn at the start
mobj_t *oldmo = NULL;
- if (player->starposttime)
- starpost = true;
+ // Not resetting map, so return to level music
+ if (!countdown2
+ && player->lives <= 0
+ && cv_cooplives.value == 1) // not allowed for life steal because no way to come back from zero group lives without addons, which should call this anyways
+ P_RestoreMultiMusic(player);
// first dissasociate the corpse
if (player->mo)
@@ -2582,7 +2685,7 @@ void G_DoReborn(INT32 playernum)
P_RemoveMobj(player->mo);
}
- G_SpawnPlayer(playernum, starpost);
+ G_SpawnPlayer(playernum, (player->starposttime));
if (oldmo)
G_ChangePlayerReferences(oldmo, players[playernum].mo);
}
@@ -2590,10 +2693,49 @@ void G_DoReborn(INT32 playernum)
void G_AddPlayer(INT32 playernum)
{
+ INT32 countplayers = 0, notexiting = 0;
+
player_t *p = &players[playernum];
+ // Go through the current players and make sure you have the latest starpost set
+ if (G_PlatformGametype() && (netgame || multiplayer))
+ {
+ INT32 i;
+ for (i = 0; i < MAXPLAYERS; i++)
+ {
+ if (!playeringame[i])
+ continue;
+
+ if (players[i].bot) // ignore dumb, stupid tails
+ continue;
+
+ countplayers++;
+
+ if (!players->exiting)
+ notexiting++;
+
+ if (!(cv_coopstarposts.value && (gametype == GT_COOP) && (p->starpostnum < players[i].starpostnum)))
+ continue;
+
+ p->starposttime = players[i].starposttime;
+ p->starpostx = players[i].starpostx;
+ p->starposty = players[i].starposty;
+ p->starpostz = players[i].starpostz;
+ p->starpostangle = players[i].starpostangle;
+ p->starpostnum = players[i].starpostnum;
+ }
+ }
+
p->jointime = 0;
p->playerstate = PST_REBORN;
+
+ p->height = mobjinfo[MT_PLAYER].height;
+
+ if (G_GametypeUsesLives() || ((netgame || multiplayer) && gametype == GT_COOP))
+ p->lives = cv_startinglives.value;
+
+ if (countplayers && !notexiting)
+ P_DoPlayerExit(p);
}
void G_ExitLevel(void)
@@ -2615,7 +2757,7 @@ void G_ExitLevel(void)
CONS_Printf(M_GetText("The round has ended.\n"));
// Remove CEcho text on round end.
- HU_DoCEcho("");
+ HU_ClearCEcho();
}
}
@@ -2763,7 +2905,6 @@ static INT16 RandMap(INT16 tolflags, INT16 pprevmap)
static void G_DoCompleted(void)
{
INT32 i;
- boolean gottoken = false;
tokenlist = 0; // Reset the list
@@ -2849,10 +2990,9 @@ static void G_DoCompleted(void)
if (nextmap >= 1100-1 && nextmap <= 1102-1 && (gametype == GT_RACE || gametype == GT_COMPETITION))
nextmap = (INT16)(spstage_start-1);
- if (gametype == GT_COOP && token)
+ if ((gottoken = (gametype == GT_COOP && token)))
{
token--;
- gottoken = true;
if (!(emeralds & EMERALD1))
nextmap = (INT16)(sstage_start - 1); // Special Stage 1
@@ -2911,7 +3051,7 @@ void G_AfterIntermission(void)
if (nextmap < 1100-1)
G_NextLevel();
else
- Y_EndGame();
+ G_EndGame();
}
}
@@ -2997,6 +3137,38 @@ static void G_DoContinued(void)
gameaction = ga_nothing;
}
+//
+// G_EndGame (formerly Y_EndGame)
+// Frankly this function fits better in g_game.c than it does in y_inter.c
+//
+// ...Gee, (why) end the game?
+// Because G_AfterIntermission and F_EndCutscene would
+// both do this exact same thing *in different ways* otherwise,
+// which made it so that you could only unlock Ultimate mode
+// if you had a cutscene after the final level and crap like that.
+// This function simplifies it so only one place has to be updated
+// when something new is added.
+void G_EndGame(void)
+{
+ // Only do evaluation and credits in coop games.
+ if (gametype == GT_COOP)
+ {
+ if (nextmap == 1102-1) // end game with credits
+ {
+ F_StartCredits();
+ return;
+ }
+ if (nextmap == 1101-1) // end game with evaluation
+ {
+ F_StartGameEvaluation();
+ return;
+ }
+ }
+
+ // 1100 or competitive multiplayer, so go back to title screen.
+ D_StartTitle();
+}
+
//
// G_LoadGameSettings
//
@@ -3561,7 +3733,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
if (netgame || multiplayer)
{
- if (!FLS || (players[i].lives < cv_startinglives.value))
+ if (!FLS || (players[i].lives < 1))
players[i].lives = cv_startinglives.value;
players[i].continues = 0;
}
@@ -3619,7 +3791,6 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
mapmusflags |= MUSIC_RELOADRESET;
ultimatemode = pultmode;
- playerdeadview = false;
automapactive = false;
imcontinuing = false;
@@ -3647,6 +3818,9 @@ char *G_BuildMapTitle(INT32 mapnum)
{
char *title = NULL;
+ if (!mapheaderinfo[mapnum-1])
+ P_AllocMapHeader(mapnum-1);
+
if (strcmp(mapheaderinfo[mapnum-1]->lvlttl, ""))
{
size_t len = 1;
@@ -3880,7 +4054,7 @@ void G_GhostAddColor(ghostcolor_t color)
ghostext.color = (UINT8)color;
}
-void G_GhostAddScale(UINT16 scale)
+void G_GhostAddScale(fixed_t scale)
{
if (!demorecording || !(demoflags & DF_GHOST))
return;
@@ -4361,7 +4535,7 @@ void G_GhostTicker(void)
g->mo->color += abs( ( (signed)( (unsigned)leveltime >> 1 ) % 9) - 4);
break;
case GHC_INVINCIBLE: // Mario invincibility (P_CheckInvincibilityTimer)
- g->mo->color = (UINT8)(SKINCOLOR_RED + (leveltime % (MAXSKINCOLORS - SKINCOLOR_RED))); // Passes through all saturated colours
+ g->mo->color = (UINT8)(SKINCOLOR_RUBY + (leveltime % (MAXSKINCOLORS - SKINCOLOR_RUBY))); // Passes through all saturated colours
break;
default:
break;
diff --git a/src/g_game.h b/src/g_game.h
index bfde7698a..72a6f3d6e 100644
--- a/src/g_game.h
+++ b/src/g_game.h
@@ -56,6 +56,9 @@ extern INT16 rw_maximums[NUM_WEAPONS];
// used in game menu
extern consvar_t cv_crosshair, cv_crosshair2;
extern consvar_t cv_invertmouse, cv_alwaysfreelook, cv_mousemove;
+extern consvar_t cv_invertmouse2, cv_alwaysfreelook2, cv_mousemove2;
+extern consvar_t cv_useranalog, cv_useranalog2;
+extern consvar_t cv_analog, cv_analog2;
extern consvar_t cv_sideaxis,cv_turnaxis,cv_moveaxis,cv_lookaxis,cv_fireaxis,cv_firenaxis;
extern consvar_t cv_sideaxis2,cv_turnaxis2,cv_moveaxis2,cv_lookaxis2,cv_fireaxis2,cv_firenaxis2;
extern consvar_t cv_ghost_bestscore, cv_ghost_besttime, cv_ghost_bestrings, cv_ghost_last, cv_ghost_guest;
@@ -139,7 +142,7 @@ void G_GhostAddSpin(void);
void G_GhostAddRev(void);
void G_GhostAddColor(ghostcolor_t color);
void G_GhostAddFlip(void);
-void G_GhostAddScale(UINT16 scale);
+void G_GhostAddScale(fixed_t scale);
void G_GhostAddHit(mobj_t *victim);
void G_WriteGhostTic(mobj_t *ghost);
void G_ConsGhostTic(void);
@@ -171,6 +174,7 @@ void G_NextLevel(void);
void G_Continue(void);
void G_UseContinue(void);
void G_AfterIntermission(void);
+void G_EndGame(void); // moved from y_inter.c/h and renamed
void G_Ticker(boolean run);
boolean G_Responder(event_t *ev);
diff --git a/src/g_input.c b/src/g_input.c
index a538df06c..36b8373aa 100644
--- a/src/g_input.c
+++ b/src/g_input.c
@@ -977,8 +977,6 @@ static const char *gamecontrolname[num_gamecontrols] =
"tossflag",
"use",
"camtoggle",
- "camleft",
- "camright",
"camreset",
"lookup",
"lookdown",
@@ -1074,8 +1072,6 @@ void G_Controldefault(void)
gamecontrol[gc_use ][0] = KEY_JOY1+1; //B
gamecontrol[gc_use ][1] = '.';
gamecontrol[gc_camtoggle ][1] = ',';
- gamecontrol[gc_camleft ][0] = 'o';
- gamecontrol[gc_camright ][0] = 'p';
gamecontrol[gc_camreset ][0] = 'c';
gamecontrol[gc_lookup ][0] = KEY_PGUP;
gamecontrol[gc_lookdown ][0] = KEY_PGDN;
@@ -1178,8 +1174,6 @@ void G_Controldefault(void)
gamecontrol[gc_tossflag ][0] = '\'';
gamecontrol[gc_use ][0] = KEY_LSHIFT;
gamecontrol[gc_camtoggle ][0] = 'v';
- gamecontrol[gc_camleft ][0] = '[';
- gamecontrol[gc_camright ][0] = ']';
gamecontrol[gc_camreset ][0] = 'r';
gamecontrol[gc_lookup ][0] = KEY_UPARROW;
gamecontrol[gc_lookdown ][0] = KEY_DOWNARROW;
diff --git a/src/g_input.h b/src/g_input.h
index d65339321..808397438 100644
--- a/src/g_input.h
+++ b/src/g_input.h
@@ -105,8 +105,6 @@ typedef enum
gc_tossflag,
gc_use,
gc_camtoggle,
- gc_camleft,
- gc_camright,
gc_camreset,
gc_lookup,
gc_lookdown,
@@ -126,6 +124,8 @@ typedef enum
// mouse values are used once
extern consvar_t cv_mousesens, cv_mouseysens;
+extern consvar_t cv_mousesens2, cv_mouseysens2;
+extern consvar_t cv_controlperkey;
extern INT32 mousex, mousey;
extern INT32 mlooky; //mousey with mlookSensitivity
diff --git a/src/hardware/hw_bsp.c b/src/hardware/hw_bsp.c
index 17eb8761c..fa5bce308 100644
--- a/src/hardware/hw_bsp.c
+++ b/src/hardware/hw_bsp.c
@@ -564,8 +564,6 @@ static inline void HWR_SubsecPoly(INT32 num, poly_t *poly)
subsector_t *sub;
seg_t *lseg;
- sscount++;
-
sub = &subsectors[num];
count = sub->numlines;
lseg = &segs[sub->firstline];
@@ -880,8 +878,8 @@ static void AdjustSegs(void)
count = subsectors[i].numlines;
lseg = &segs[subsectors[i].firstline];
p = extrasubsectors[i].planepoly;
- if (!p)
- continue;
+ //if (!p)
+ //continue;
for (; count--; lseg++)
{
float distv1,distv2,tmp;
@@ -894,29 +892,31 @@ static void AdjustSegs(void)
continue;
#endif
- for (j = 0; j < p->numpts; j++)
- {
- distv1 = p->pts[j].x - FIXED_TO_FLOAT(lseg->v1->x);
- tmp = p->pts[j].y - FIXED_TO_FLOAT(lseg->v1->y);
- distv1 = distv1*distv1+tmp*tmp;
- if (distv1 <= nearv1)
+ if (p) {
+ for (j = 0; j < p->numpts; j++)
{
- v1found = j;
- nearv1 = distv1;
- }
- // the same with v2
- distv2 = p->pts[j].x - FIXED_TO_FLOAT(lseg->v2->x);
- tmp = p->pts[j].y - FIXED_TO_FLOAT(lseg->v2->y);
- distv2 = distv2*distv2+tmp*tmp;
- if (distv2 <= nearv2)
- {
- v2found = j;
- nearv2 = distv2;
+ distv1 = p->pts[j].x - FIXED_TO_FLOAT(lseg->v1->x);
+ tmp = p->pts[j].y - FIXED_TO_FLOAT(lseg->v1->y);
+ distv1 = distv1*distv1+tmp*tmp;
+ if (distv1 <= nearv1)
+ {
+ v1found = j;
+ nearv1 = distv1;
+ }
+ // the same with v2
+ distv2 = p->pts[j].x - FIXED_TO_FLOAT(lseg->v2->x);
+ tmp = p->pts[j].y - FIXED_TO_FLOAT(lseg->v2->y);
+ distv2 = distv2*distv2+tmp*tmp;
+ if (distv2 <= nearv2)
+ {
+ v2found = j;
+ nearv2 = distv2;
+ }
}
}
- if (nearv1 <= NEARDIST*NEARDIST)
+ if (p && nearv1 <= NEARDIST*NEARDIST)
// share vertice with segs
- lseg->v1 = (vertex_t *)&(p->pts[v1found]);
+ lseg->pv1 = &(p->pts[v1found]);
else
{
// BP: here we can do better, using PointInSeg and compute
@@ -927,24 +927,24 @@ static void AdjustSegs(void)
polyvertex_t *pv = HWR_AllocVertex();
pv->x = FIXED_TO_FLOAT(lseg->v1->x);
pv->y = FIXED_TO_FLOAT(lseg->v1->y);
- lseg->v1 = (vertex_t *)pv;
+ lseg->pv1 = pv;
}
- if (nearv2 <= NEARDIST*NEARDIST)
- lseg->v2 = (vertex_t *)&(p->pts[v2found]);
+ if (p && nearv2 <= NEARDIST*NEARDIST)
+ lseg->pv2 = &(p->pts[v2found]);
else
{
polyvertex_t *pv = HWR_AllocVertex();
pv->x = FIXED_TO_FLOAT(lseg->v2->x);
pv->y = FIXED_TO_FLOAT(lseg->v2->y);
- lseg->v2 = (vertex_t *)pv;
+ lseg->pv2 = pv;
}
// recompute length
{
float x,y;
- x = ((polyvertex_t *)lseg->v2)->x - ((polyvertex_t *)lseg->v1)->x
+ x = ((polyvertex_t *)lseg->pv2)->x - ((polyvertex_t *)lseg->pv1)->x
+ FIXED_TO_FLOAT(FRACUNIT/2);
- y = ((polyvertex_t *)lseg->v2)->y - ((polyvertex_t *)lseg->v1)->y
+ y = ((polyvertex_t *)lseg->pv2)->y - ((polyvertex_t *)lseg->pv1)->y
+ FIXED_TO_FLOAT(FRACUNIT/2);
lseg->flength = (float)hypot(x, y);
// BP: debug see this kind of segs
diff --git a/src/hardware/hw_clip.c b/src/hardware/hw_clip.c
new file mode 100644
index 000000000..8b01cabd5
--- /dev/null
+++ b/src/hardware/hw_clip.c
@@ -0,0 +1,465 @@
+/* Emacs style mode select -*- C++ -*-
+ *-----------------------------------------------------------------------------
+ *
+ *
+ * PrBoom: a Doom port merged with LxDoom and LSDLDoom
+ * based on BOOM, a modified and improved DOOM engine
+ * Copyright (C) 1999 by
+ * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
+ * Copyright (C) 1999-2000 by
+ * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
+ * Copyright 2005, 2006 by
+ * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * DESCRIPTION:
+ *
+ *---------------------------------------------------------------------
+ */
+
+/*
+ *
+ ** gl_clipper.cpp
+ **
+ ** Handles visibility checks.
+ ** Loosely based on the JDoom clipper.
+ **
+ **---------------------------------------------------------------------------
+ ** Copyright 2003 Tim Stump
+ ** All rights reserved.
+ **
+ ** Redistribution and use in source and binary forms, with or without
+ ** modification, are permitted provided that the following conditions
+ ** are met:
+ **
+ ** 1. Redistributions of source code must retain the above copyright
+ ** notice, this list of conditions and the following disclaimer.
+ ** 2. Redistributions in binary form must reproduce the above copyright
+ ** notice, this list of conditions and the following disclaimer in the
+ ** documentation and/or other materials provided with the distribution.
+ ** 3. The name of the author may not be used to endorse or promote products
+ ** derived from this software without specific prior written permission.
+ **
+ ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ **---------------------------------------------------------------------------
+ **
+ */
+
+#include
+#include "../v_video.h"
+#include "hw_clip.h"
+#include "hw_glob.h"
+#include "../r_state.h"
+#include "../tables.h"
+#include "r_opengl/r_opengl.h"
+
+#ifdef HAVE_SPHEREFRUSTRUM
+static GLdouble viewMatrix[16];
+static GLdouble projMatrix[16];
+float frustum[6][4];
+#endif
+
+typedef struct clipnode_s
+ {
+ struct clipnode_s *prev, *next;
+ angle_t start, end;
+ } clipnode_t;
+
+clipnode_t *freelist;
+clipnode_t *clipnodes;
+clipnode_t *cliphead;
+
+static clipnode_t * gld_clipnode_GetNew(void);
+static clipnode_t * gld_clipnode_NewRange(angle_t start, angle_t end);
+static boolean gld_clipper_IsRangeVisible(angle_t startAngle, angle_t endAngle);
+static void gld_clipper_AddClipRange(angle_t start, angle_t end);
+static void gld_clipper_RemoveRange(clipnode_t * range);
+static void gld_clipnode_Free(clipnode_t *node);
+
+static clipnode_t * gld_clipnode_GetNew(void)
+{
+ if (freelist)
+ {
+ clipnode_t * p = freelist;
+ freelist = p->next;
+ return p;
+ }
+ else
+ {
+ return (clipnode_t*)malloc(sizeof(clipnode_t));
+ }
+}
+
+static clipnode_t * gld_clipnode_NewRange(angle_t start, angle_t end)
+{
+ clipnode_t * c = gld_clipnode_GetNew();
+ c->start = start;
+ c->end = end;
+ c->next = c->prev=NULL;
+ return c;
+}
+
+boolean gld_clipper_SafeCheckRange(angle_t startAngle, angle_t endAngle)
+{
+ if(startAngle > endAngle)
+ {
+ return (gld_clipper_IsRangeVisible(startAngle, ANGLE_MAX) || gld_clipper_IsRangeVisible(0, endAngle));
+ }
+
+ return gld_clipper_IsRangeVisible(startAngle, endAngle);
+}
+
+static boolean gld_clipper_IsRangeVisible(angle_t startAngle, angle_t endAngle)
+{
+ clipnode_t *ci;
+ ci = cliphead;
+
+ if (endAngle == 0 && ci && ci->start == 0)
+ return false;
+
+ while (ci != NULL && ci->start < endAngle)
+ {
+ if (startAngle >= ci->start && endAngle <= ci->end)
+ {
+ return false;
+ }
+ ci = ci->next;
+ }
+
+ return true;
+}
+
+static void gld_clipnode_Free(clipnode_t *node)
+{
+ node->next = freelist;
+ freelist = node;
+}
+
+static void gld_clipper_RemoveRange(clipnode_t *range)
+{
+ if (range == cliphead)
+ {
+ cliphead = cliphead->next;
+ }
+ else
+ {
+ if (range->prev)
+ {
+ range->prev->next = range->next;
+ }
+ if (range->next)
+ {
+ range->next->prev = range->prev;
+ }
+ }
+
+ gld_clipnode_Free(range);
+}
+
+void gld_clipper_SafeAddClipRange(angle_t startangle, angle_t endangle)
+{
+ if(startangle > endangle)
+ {
+ // The range has to added in two parts.
+ gld_clipper_AddClipRange(startangle, ANGLE_MAX);
+ gld_clipper_AddClipRange(0, endangle);
+ }
+ else
+ {
+ // Add the range as usual.
+ gld_clipper_AddClipRange(startangle, endangle);
+ }
+}
+
+static void gld_clipper_AddClipRange(angle_t start, angle_t end)
+{
+ clipnode_t *node, *temp, *prevNode, *node2, *delnode;
+
+ if (cliphead)
+ {
+ //check to see if range contains any old ranges
+ node = cliphead;
+ while (node != NULL && node->start < end)
+ {
+ if (node->start >= start && node->end <= end)
+ {
+ temp = node;
+ node = node->next;
+ gld_clipper_RemoveRange(temp);
+ }
+ else
+ {
+ if (node->start <= start && node->end >= end)
+ {
+ return;
+ }
+ else
+ {
+ node = node->next;
+ }
+ }
+ }
+
+ //check to see if range overlaps a range (or possibly 2)
+ node = cliphead;
+ while (node != NULL && node->start <= end)
+ {
+ if (node->end >= start)
+ {
+ // we found the first overlapping node
+ if (node->start > start)
+ {
+ // the new range overlaps with this node's start point
+ node->start = start;
+ }
+ if (node->end < end)
+ {
+ node->end = end;
+ }
+
+ node2 = node->next;
+ while (node2 && node2->start <= node->end)
+ {
+ if (node2->end > node->end)
+ {
+ node->end = node2->end;
+ }
+
+ delnode = node2;
+ node2 = node2->next;
+ gld_clipper_RemoveRange(delnode);
+ }
+ return;
+ }
+ node = node->next;
+ }
+
+ //just add range
+ node = cliphead;
+ prevNode = NULL;
+ temp = gld_clipnode_NewRange(start, end);
+ while (node != NULL && node->start < end)
+ {
+ prevNode = node;
+ node = node->next;
+ }
+ temp->next = node;
+ if (node == NULL)
+ {
+ temp->prev = prevNode;
+ if (prevNode)
+ {
+ prevNode->next = temp;
+ }
+ if (!cliphead)
+ {
+ cliphead = temp;
+ }
+ }
+ else
+ {
+ if (node == cliphead)
+ {
+ cliphead->prev = temp;
+ cliphead = temp;
+ }
+ else
+ {
+ temp->prev = prevNode;
+ prevNode->next = temp;
+ node->prev = temp;
+ }
+ }
+ }
+ else
+ {
+ temp = gld_clipnode_NewRange(start, end);
+ cliphead = temp;
+ return;
+ }
+}
+
+void gld_clipper_Clear(void)
+{
+ clipnode_t *node = cliphead;
+ clipnode_t *temp;
+
+ while (node != NULL)
+ {
+ temp = node;
+ node = node->next;
+ gld_clipnode_Free(temp);
+ }
+
+ cliphead = NULL;
+}
+
+#define RMUL (1.6f/1.333333f)
+
+angle_t gld_FrustumAngle(void)
+{
+ double floatangle;
+ angle_t a1;
+
+ float tilt = (float)fabs(((double)(int)aimingangle) / ANG1);
+
+ // NEWCLIP TODO: SRB2CBTODO: make a global render_fov for this function
+
+ float render_fov = FIXED_TO_FLOAT(cv_grfov.value);
+ float render_fovratio = (float)BASEVIDWIDTH / (float)BASEVIDHEIGHT; // SRB2CBTODO: NEWCLIPTODO: Is this right?
+ float render_multiplier = 64.0f / render_fovratio / RMUL;
+
+ if (tilt > 90.0f)
+ {
+ tilt = 90.0f;
+ }
+
+ // If the pitch is larger than this you can look all around at a FOV of 90
+ if (abs(aimingangle) > 46 * ANG1)
+ return 0xffffffff;
+
+ // ok, this is a gross hack that barely works...
+ // but at least it doesn't overestimate too much...
+ floatangle = 2.0f + (45.0f + (tilt / 1.9f)) * (float)render_fov * 48.0f / render_multiplier / 90.0f;
+ a1 = ANG1 * (int)floatangle;
+ if (a1 >= ANGLE_180)
+ return 0xffffffff;
+ return a1;
+}
+
+// SRB2CB I don't think used any of this stuff, let's disable for now since SRB2 probably doesn't want it either
+// compiler complains about (p)glGetDoublev anyway, in case anyone wants this
+// only r_opengl.c can use the base gl funcs as it turns out, that's a problem for whoever wants sphere frustum checks
+// btw to renable define HAVE_SPHEREFRUSTRUM in hw_clip.h
+#ifdef HAVE_SPHEREFRUSTRUM
+//
+// gld_FrustrumSetup
+//
+
+#define CALCMATRIX(a, b, c, d, e, f, g, h)\
+(float)(viewMatrix[a] * projMatrix[b] + \
+viewMatrix[c] * projMatrix[d] + \
+viewMatrix[e] * projMatrix[f] + \
+viewMatrix[g] * projMatrix[h])
+
+#define NORMALIZE_PLANE(i)\
+t = (float)sqrt(\
+frustum[i][0] * frustum[i][0] + \
+frustum[i][1] * frustum[i][1] + \
+frustum[i][2] * frustum[i][2]); \
+frustum[i][0] /= t; \
+frustum[i][1] /= t; \
+frustum[i][2] /= t; \
+frustum[i][3] /= t
+
+void gld_FrustrumSetup(void)
+{
+ float t;
+ float clip[16];
+
+ pglGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
+ pglGetDoublev(GL_MODELVIEW_MATRIX, viewMatrix);
+
+ clip[0] = CALCMATRIX(0, 0, 1, 4, 2, 8, 3, 12);
+ clip[1] = CALCMATRIX(0, 1, 1, 5, 2, 9, 3, 13);
+ clip[2] = CALCMATRIX(0, 2, 1, 6, 2, 10, 3, 14);
+ clip[3] = CALCMATRIX(0, 3, 1, 7, 2, 11, 3, 15);
+
+ clip[4] = CALCMATRIX(4, 0, 5, 4, 6, 8, 7, 12);
+ clip[5] = CALCMATRIX(4, 1, 5, 5, 6, 9, 7, 13);
+ clip[6] = CALCMATRIX(4, 2, 5, 6, 6, 10, 7, 14);
+ clip[7] = CALCMATRIX(4, 3, 5, 7, 6, 11, 7, 15);
+
+ clip[8] = CALCMATRIX(8, 0, 9, 4, 10, 8, 11, 12);
+ clip[9] = CALCMATRIX(8, 1, 9, 5, 10, 9, 11, 13);
+ clip[10] = CALCMATRIX(8, 2, 9, 6, 10, 10, 11, 14);
+ clip[11] = CALCMATRIX(8, 3, 9, 7, 10, 11, 11, 15);
+
+ clip[12] = CALCMATRIX(12, 0, 13, 4, 14, 8, 15, 12);
+ clip[13] = CALCMATRIX(12, 1, 13, 5, 14, 9, 15, 13);
+ clip[14] = CALCMATRIX(12, 2, 13, 6, 14, 10, 15, 14);
+ clip[15] = CALCMATRIX(12, 3, 13, 7, 14, 11, 15, 15);
+
+ // Right plane
+ frustum[0][0] = clip[ 3] - clip[ 0];
+ frustum[0][1] = clip[ 7] - clip[ 4];
+ frustum[0][2] = clip[11] - clip[ 8];
+ frustum[0][3] = clip[15] - clip[12];
+ NORMALIZE_PLANE(0);
+
+ // Left plane
+ frustum[1][0] = clip[ 3] + clip[ 0];
+ frustum[1][1] = clip[ 7] + clip[ 4];
+ frustum[1][2] = clip[11] + clip[ 8];
+ frustum[1][3] = clip[15] + clip[12];
+ NORMALIZE_PLANE(1);
+
+ // Bottom plane
+ frustum[2][0] = clip[ 3] + clip[ 1];
+ frustum[2][1] = clip[ 7] + clip[ 5];
+ frustum[2][2] = clip[11] + clip[ 9];
+ frustum[2][3] = clip[15] + clip[13];
+ NORMALIZE_PLANE(2);
+
+ // Top plane
+ frustum[3][0] = clip[ 3] - clip[ 1];
+ frustum[3][1] = clip[ 7] - clip[ 5];
+ frustum[3][2] = clip[11] - clip[ 9];
+ frustum[3][3] = clip[15] - clip[13];
+ NORMALIZE_PLANE(3);
+
+ // Far plane
+ frustum[4][0] = clip[ 3] - clip[ 2];
+ frustum[4][1] = clip[ 7] - clip[ 6];
+ frustum[4][2] = clip[11] - clip[10];
+ frustum[4][3] = clip[15] - clip[14];
+ NORMALIZE_PLANE(4);
+
+ // Near plane
+ frustum[5][0] = clip[ 3] + clip[ 2];
+ frustum[5][1] = clip[ 7] + clip[ 6];
+ frustum[5][2] = clip[11] + clip[10];
+ frustum[5][3] = clip[15] + clip[14];
+ NORMALIZE_PLANE(5);
+}
+
+boolean gld_SphereInFrustum(float x, float y, float z, float radius)
+{
+ int p;
+
+ for (p = 0; p < 4; p++)
+ {
+ if (frustum[p][0] * x +
+ frustum[p][1] * y +
+ frustum[p][2] * z +
+ frustum[p][3] <= -radius)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+#endif
diff --git a/src/hardware/hw_clip.h b/src/hardware/hw_clip.h
new file mode 100644
index 000000000..3ba26e5e5
--- /dev/null
+++ b/src/hardware/hw_clip.h
@@ -0,0 +1,24 @@
+/*
+ * hw_clip.h
+ * SRB2CB
+ *
+ * PrBoom's OpenGL clipping
+ *
+ *
+ */
+
+// OpenGL BSP clipping
+#include "../doomdef.h"
+#include "../tables.h"
+#include "../doomtype.h"
+
+//#define HAVE_SPHEREFRUSTRUM // enable if you want gld_SphereInFrustum and related code
+
+boolean gld_clipper_SafeCheckRange(angle_t startAngle, angle_t endAngle);
+void gld_clipper_SafeAddClipRange(angle_t startangle, angle_t endangle);
+void gld_clipper_Clear(void);
+angle_t gld_FrustumAngle(void);
+#ifdef HAVE_SPHEREFRUSTRUM
+void gld_FrustrumSetup(void);
+boolean gld_SphereInFrustum(float x, float y, float z, float radius);
+#endif
diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c
index a00bf3aeb..9c912495a 100644
--- a/src/hardware/hw_draw.c
+++ b/src/hardware/hw_draw.c
@@ -789,7 +789,7 @@ boolean HWR_Screenshot(const char *lbmname)
HWD.pfnReadRect(0, 0, vid.width, vid.height, vid.width * 3, (void *)buf);
#ifdef USE_PNG
- ret = M_SavePNG(lbmname, buf, vid.width, vid.height, NULL);
+ ret = M_SavePNG(lbmname, buf, vid.width, vid.height, false);
#else
ret = saveTGA(lbmname, buf, vid.width, vid.height);
#endif
diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h
index 94eef1d3e..5d1a81d4f 100644
--- a/src/hardware/hw_glob.h
+++ b/src/hardware/hw_glob.h
@@ -78,6 +78,7 @@ typedef struct gr_vissprite_s
//Hurdler: 25/04/2000: now support colormap in hardware mode
UINT8 *colormap;
INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing
+ float z1, z2;
} gr_vissprite_t;
// --------
diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c
index a49a788e6..267666749 100644
--- a/src/hardware/hw_light.c
+++ b/src/hardware/hw_light.c
@@ -226,8 +226,7 @@ light_t *t_lspr[NUMSPRITES] =
// Collectible Items
&lspr[NOLIGHT], // SPR_RING
&lspr[NOLIGHT], // SPR_TRNG
- &lspr[NOLIGHT], // SPR_EMMY
- &lspr[BLUEBALL_L], // SPR_TOKE
+ &lspr[NOLIGHT], // SPR_TOKE
&lspr[REDBALL_L], // SPR_RFLG
&lspr[BLUEBALL_L], // SPR_BFLG
&lspr[NOLIGHT], // SPR_NWNG
@@ -243,6 +242,8 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_SPIK
&lspr[NOLIGHT], // SPR_SFLM
&lspr[NOLIGHT], // SPR_USPK
+ &lspr[NOLIGHT], // SPR_WSPK
+ &lspr[NOLIGHT], // SPR_WSPB
&lspr[NOLIGHT], // SPR_STPT
&lspr[NOLIGHT], // SPR_BMNE
@@ -293,6 +294,12 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_FWR4
&lspr[NOLIGHT], // SPR_BUS1
&lspr[NOLIGHT], // SPR_BUS2
+ // Trees (both GFZ and misc)
+ &lspr[NOLIGHT], // SPR_TRE1
+ &lspr[NOLIGHT], // SPR_TRE2
+ &lspr[NOLIGHT], // SPR_TRE3
+ &lspr[NOLIGHT], // SPR_TRE4
+ &lspr[NOLIGHT], // SPR_TRE5
// Techno Hill Scenery
&lspr[NOLIGHT], // SPR_THZP
@@ -316,6 +323,10 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_BMCH
&lspr[NOLIGHT], // SPR_SMCE
&lspr[NOLIGHT], // SPR_BMCE
+ &lspr[NOLIGHT], // SPR_YSPB
+ &lspr[NOLIGHT], // SPR_RSPB
+ &lspr[REDBALL_L], // SPR_SFBR
+ &lspr[REDBALL_L], // SPR_BFBR
// Arid Canyon Scenery
&lspr[NOLIGHT], // SPR_BTBL
@@ -334,6 +345,8 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_XMS1
&lspr[NOLIGHT], // SPR_XMS2
&lspr[NOLIGHT], // SPR_XMS3
+ &lspr[NOLIGHT], // SPR_XMS4
+ &lspr[NOLIGHT], // SPR_XMS5
// Botanic Serenity Scenery
&lspr[NOLIGHT], // SPR_BSZ1
@@ -345,13 +358,9 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_BSZ7
&lspr[NOLIGHT], // SPR_BSZ8
- // Stalagmites
+ // Misc Scenery
&lspr[NOLIGHT], // SPR_STLG
-
- // Disco Ball
&lspr[NOLIGHT], // SPR_DBAL
-
- // ATZ Red Crystal
&lspr[NOLIGHT], // SPR_RCRY
// Powerup Indicators
@@ -396,8 +405,11 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_SPRB Graue
&lspr[NOLIGHT], // SPR_YSPR
&lspr[NOLIGHT], // SPR_RSPR
+ &lspr[NOLIGHT], // SPR_SSWY
+ &lspr[NOLIGHT], // SPR_SSWR
+ &lspr[NOLIGHT], // SPR_SSWB
- // Environmentals Effects
+ // Environmental Effects
&lspr[NOLIGHT], // SPR_RAIN
&lspr[NOLIGHT], // SPR_SNO1
&lspr[NOLIGHT], // SPR_SPLH
@@ -405,6 +417,8 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_SMOK
&lspr[NOLIGHT], // SPR_BUBL
&lspr[RINGLIGHT_L], // SPR_WZAP
+ &lspr[NOLIGHT], // SPR_DUST
+ &lspr[NOLIGHT], // SPR_FPRT
&lspr[SUPERSPARK_L], // SPR_TFOG
&lspr[NIGHTSLIGHT_L], // SPR_SEED // Sonic CD flower seed
&lspr[NOLIGHT], // SPR_PRTL
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index ac4c896bf..f8ac272a4 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -44,6 +44,10 @@
#endif
#include "hw_md2.h"
+#ifdef NEWCLIP
+#include "hw_clip.h"
+#endif
+
#define R_FAKEFLOORS
#define HWPRECIP
#define SORTING
@@ -99,8 +103,9 @@ CV_PossibleValue_t granisotropicmode_cons_t[] = {{1, "MIN"}, {16, "MAX"}, {0, NU
boolean drawsky = true;
// needs fix: walls are incorrectly clipped one column less
+#ifndef NEWCLIP
static consvar_t cv_grclipwalls = {"gr_clipwalls", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
-
+#endif
//development variables for diverse uses
static consvar_t cv_gralpha = {"gr_alpha", "160", 0, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
static consvar_t cv_grbeta = {"gr_beta", "0", 0, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -323,9 +328,6 @@ static angle_t gr_xtoviewangle[MAXVIDWIDTH+1];
// test change fov when looking up/down but bsp projection messup :(
//#define NOCRAPPYMLOOK
-/// \note crappy
-#define drawtextured true
-
// base values set at SetViewSize
static float gr_basecentery;
@@ -641,13 +643,13 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
{
scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize;
- angle = FOFsector->floorpic_angle>>ANGLETOFINESHIFT;
+ angle = FOFsector->floorpic_angle;
}
else // it's a ceiling
{
scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatsize;
- angle = FOFsector->ceilingpic_angle>>ANGLETOFINESHIFT;
+ angle = FOFsector->ceilingpic_angle;
}
}
else if (gr_frontsector)
@@ -656,25 +658,19 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
{
scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize;
- angle = gr_frontsector->floorpic_angle>>ANGLETOFINESHIFT;
+ angle = gr_frontsector->floorpic_angle;
}
else // it's a ceiling
{
scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatsize;
- angle = gr_frontsector->ceilingpic_angle>>ANGLETOFINESHIFT;
+ angle = gr_frontsector->ceilingpic_angle;
}
}
if (angle) // Only needs to be done if there's an altered angle
{
-
- // This needs to be done so that it scrolls in a different direction after rotation like software
- tempxsow = FLOAT_TO_FIXED(scrollx);
- tempytow = FLOAT_TO_FIXED(scrolly);
- scrollx = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));
- scrolly = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));
-
+ angle = InvAngle(angle)>>ANGLETOFINESHIFT;
// This needs to be done so everything aligns after rotation
// It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does
tempxsow = FLOAT_TO_FIXED(flatxref);
@@ -687,7 +683,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
{
// Hurdler: add scrolling texture on floor/ceiling
v3d->sow = (float)((pv->x / fflatsize) - flatxref + scrollx);
- v3d->tow = (float)(flatyref - (pv->y / fflatsize) + scrolly);
+ v3d->tow = (float)(-(pv->y / fflatsize) + flatyref + scrolly);
//v3d->sow = (float)(pv->x / fflatsize);
//v3d->tow = (float)(pv->y / fflatsize);
@@ -698,7 +694,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
tempxsow = FLOAT_TO_FIXED(v3d->sow);
tempytow = FLOAT_TO_FIXED(v3d->tow);
v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));
- v3d->tow = (FIXED_TO_FLOAT(-FixedMul(tempxsow, FINESINE(angle)) - FixedMul(tempytow, FINECOSINE(angle))));
+ v3d->tow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));
}
//v3d->sow = (float)(v3d->sow - flatxref + scrollx);
@@ -858,11 +854,11 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf)
M_ClearBox(segbbox);
M_AddToBox(segbbox,
- FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->x),
- FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->y));
+ FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->x),
+ FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->y));
M_AddToBox(segbbox,
- FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->x),
- FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->y));
+ FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x),
+ FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y));
splat = (wallsplat_t *)gr_curline->linedef->splats;
for (; splat; splat = splat->next)
@@ -1035,6 +1031,7 @@ static void HWR_ProjectWall(wallVert3D * wallVerts,
// (in fact a clipping plane that has a constant, so can clip with simple 2d)
// with the wall segment
//
+#ifndef NEWCLIP
static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2)
{
float num, den;
@@ -1063,6 +1060,7 @@ static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2)
return num / den;
}
+#endif
//
// HWR_SplitWall
@@ -1084,9 +1082,9 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
float endheight = 0.0f, endbheight = 0.0f;
fixed_t v1x = FLOAT_TO_FIXED(wallVerts[0].x);
- fixed_t v1y = FLOAT_TO_FIXED(wallVerts[0].y);
+ fixed_t v1y = FLOAT_TO_FIXED(wallVerts[0].z); // not a typo
fixed_t v2x = FLOAT_TO_FIXED(wallVerts[1].x);
- fixed_t v2y = FLOAT_TO_FIXED(wallVerts[1].y);
+ fixed_t v2y = FLOAT_TO_FIXED(wallVerts[1].z); // not a typo
// compiler complains when P_GetZAt is used in FLOAT_TO_FIXED directly
// use this as a temp var to store P_GetZAt's return value each time
fixed_t temp;
@@ -1437,7 +1435,11 @@ static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf, fixed_t b
// Anything between means the wall segment has been clipped with solidsegs,
// reducing wall overdraw to a minimum
//
+#ifdef NEWCLIP
+static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
+#else
static void HWR_StoreWallRange(double startfrac, double endfrac)
+#endif
{
wallVert3D wallVerts[4];
v2d_t vs, ve; // start, end vertices of 2d line (view from above)
@@ -1462,16 +1464,18 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
extracolormap_t *colormap;
FSurfaceInfo Surf;
+#ifndef NEWCLIP
if (startfrac > endfrac)
return;
+#endif
gr_sidedef = gr_curline->sidedef;
gr_linedef = gr_curline->linedef;
- vs.x = ((polyvertex_t *)gr_curline->v1)->x;
- vs.y = ((polyvertex_t *)gr_curline->v1)->y;
- ve.x = ((polyvertex_t *)gr_curline->v2)->x;
- ve.y = ((polyvertex_t *)gr_curline->v2)->y;
+ vs.x = ((polyvertex_t *)gr_curline->pv1)->x;
+ vs.y = ((polyvertex_t *)gr_curline->pv1)->y;
+ ve.x = ((polyvertex_t *)gr_curline->pv2)->x;
+ ve.y = ((polyvertex_t *)gr_curline->pv2)->y;
#ifdef ESLOPE
v1x = FLOAT_TO_FIXED(vs.x);
@@ -1479,44 +1483,21 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
v2x = FLOAT_TO_FIXED(ve.x);
v2y = FLOAT_TO_FIXED(ve.y);
#endif
-
- if (gr_frontsector->heightsec != -1)
- {
#ifdef ESLOPE
- worldtop = worldtopslope = sectors[gr_frontsector->heightsec].ceilingheight;
- worldbottom = worldbottomslope = sectors[gr_frontsector->heightsec].floorheight;
-#else
- worldtop = sectors[gr_frontsector->heightsec].ceilingheight;
- worldbottom = sectors[gr_frontsector->heightsec].floorheight;
-#endif
- }
- else
- {
-#ifdef ESLOPE
- if (gr_frontsector->c_slope)
- {
- worldtop = P_GetZAt(gr_frontsector->c_slope, v1x, v1y);
- worldtopslope = P_GetZAt(gr_frontsector->c_slope, v2x, v2y);
- }
- else
- {
- worldtop = worldtopslope = gr_frontsector->ceilingheight;
- }
- if (gr_frontsector->f_slope)
- {
- worldbottom = P_GetZAt(gr_frontsector->f_slope, v1x, v1y);
- worldbottomslope = P_GetZAt(gr_frontsector->f_slope, v2x, v2y);
- }
- else
- {
- worldbottom = worldbottomslope = gr_frontsector->floorheight;
- }
+#define SLOPEPARAMS(slope, end1, end2, normalheight) \
+ if (slope) { \
+ end1 = P_GetZAt(slope, v1x, v1y); \
+ end2 = P_GetZAt(slope, v2x, v2y); \
+ } else \
+ end1 = end2 = normalheight;
+
+ SLOPEPARAMS(gr_frontsector->c_slope, worldtop, worldtopslope, gr_frontsector->ceilingheight)
+ SLOPEPARAMS(gr_frontsector->f_slope, worldbottom, worldbottomslope, gr_frontsector->floorheight)
#else
- worldtop = gr_frontsector->ceilingheight;
- worldbottom = gr_frontsector->floorheight;
+ worldtop = gr_frontsector->ceilingheight;
+ worldbottom = gr_frontsector->floorheight;
#endif
- }
// remember vertices ordering
// 3--2
@@ -1531,20 +1512,23 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
wallVerts[2].z = wallVerts[1].z = ve.y;
wallVerts[0].w = wallVerts[1].w = wallVerts[2].w = wallVerts[3].w = 1.0f;
- if (drawtextured)
{
// x offset the texture
fixed_t texturehpeg = gr_sidedef->textureoffset + gr_curline->offset;
+#ifndef NEWCLIP
// clip texture s start/end coords with solidsegs
if (startfrac > 0.0f && startfrac < 1.0f)
cliplow = (float)(texturehpeg + (gr_curline->flength*FRACUNIT) * startfrac);
else
+#endif
cliplow = (float)texturehpeg;
+#ifndef NEWCLIP
if (endfrac > 0.0f && endfrac < 1.0f)
cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT) * endfrac);
else
+#endif
cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT));
}
@@ -1560,43 +1544,15 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
{
INT32 gr_toptexture, gr_bottomtexture;
// two sided line
- if (gr_backsector->heightsec != -1)
- {
-#ifdef ESLOPE
- worldhigh = worldhighslope = sectors[gr_backsector->heightsec].ceilingheight;
- worldlow = worldlowslope = sectors[gr_backsector->heightsec].floorheight;
-#else
- worldhigh = sectors[gr_backsector->heightsec].ceilingheight;
- worldlow = sectors[gr_backsector->heightsec].floorheight;
-#endif
- }
- else
- {
-#ifdef ESLOPE
- if (gr_backsector->c_slope)
- {
- worldhigh = P_GetZAt(gr_backsector->c_slope, v1x, v1y);
- worldhighslope = P_GetZAt(gr_backsector->c_slope, v2x, v2y);
- }
- else
- {
- worldhigh = worldhighslope = gr_backsector->ceilingheight;
- }
- if (gr_backsector->f_slope)
- {
- worldlow = P_GetZAt(gr_backsector->f_slope, v1x, v1y);
- worldlowslope = P_GetZAt(gr_backsector->f_slope, v2x, v2y);
- }
- else
- {
- worldlow = worldlowslope = gr_backsector->floorheight;
- }
+#ifdef ESLOPE
+ SLOPEPARAMS(gr_backsector->c_slope, worldhigh, worldhighslope, gr_backsector->ceilingheight)
+ SLOPEPARAMS(gr_backsector->f_slope, worldlow, worldlowslope, gr_backsector->floorheight)
+#undef SLOPEPARAMS
#else
- worldhigh = gr_backsector->ceilingheight;
- worldlow = gr_backsector->floorheight;
+ worldhigh = gr_backsector->ceilingheight;
+ worldlow = gr_backsector->floorheight;
#endif
- }
// hack to allow height changes in outdoor areas
// This is what gets rid of the upper textures if there should be sky
@@ -1620,7 +1576,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
worldhigh < worldtop
) && gr_toptexture)
{
- if (drawtextured)
{
fixed_t texturevpegtop; // top
@@ -1701,7 +1656,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
#endif
worldlow > worldbottom) && gr_bottomtexture) //only if VISIBLE!!!
{
- if (drawtextured)
{
fixed_t texturevpegbottom = 0; // bottom
@@ -1893,7 +1847,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
h = min(highcut, polytop);
l = max(polybottom, lowcut);
- if (drawtextured)
{
// PEGGING
#ifdef ESLOPE
@@ -1949,7 +1902,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
h = min(highcut, polytop);
l = max(polybottom, lowcut);
- if (drawtextured)
{
// PEGGING
if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3))
@@ -2141,7 +2093,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
gr_midtexture = R_GetTextureNum(gr_sidedef->midtexture);
if (gr_midtexture)
{
- if (drawtextured)
{
fixed_t texturevpeg;
// PEGGING
@@ -2282,7 +2233,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
wallVerts[0].s = wallVerts[3].s = 0;
wallVerts[2].s = wallVerts[1].s = 0;
}
- else if (drawtextured)
+ else
{
#ifdef ESLOPE // P.S. this is better-organized than the old version
fixed_t offs = sides[(newline ? newline : rover->master)->sidenum[0]].rowoffset;
@@ -2415,7 +2366,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
wallVerts[0].s = wallVerts[3].s = 0;
wallVerts[2].s = wallVerts[1].s = 0;
}
- else if (drawtextured)
+ else
{
grTex = HWR_GetTexture(texnum);
@@ -2488,6 +2439,110 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
//Hurdler: end of 3d-floors test
}
+// From PrBoom:
+//
+// e6y: Check whether the player can look beyond this line
+//
+#ifdef NEWCLIP
+boolean checkforemptylines = true;
+// Don't modify anything here, just check
+// Kalaron: Modified for sloped linedefs
+static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacksector)
+{
+ fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
+ fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends
+
+ // GZDoom method of sloped line clipping
+
+#ifdef ESLOPE
+ if (afrontsector->f_slope || afrontsector->c_slope || abacksector->f_slope || abacksector->c_slope)
+ {
+ fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t
+ v1x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->x);
+ v1y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->y);
+ v2x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x);
+ v2y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y);
+#define SLOPEPARAMS(slope, end1, end2, normalheight) \
+ if (slope) { \
+ end1 = P_GetZAt(slope, v1x, v1y); \
+ end2 = P_GetZAt(slope, v2x, v2y); \
+ } else \
+ end1 = end2 = normalheight;
+
+ SLOPEPARAMS(afrontsector->f_slope, frontf1, frontf2, afrontsector->floorheight)
+ SLOPEPARAMS(afrontsector->c_slope, frontc1, frontc2, afrontsector->ceilingheight)
+ SLOPEPARAMS( abacksector->f_slope, backf1, backf2, abacksector->floorheight)
+ SLOPEPARAMS( abacksector->c_slope, backc1, backc2, abacksector->ceilingheight)
+#undef SLOPEPARAMS
+ }
+ else
+#endif
+ {
+ frontf1 = frontf2 = afrontsector->floorheight;
+ frontc1 = frontc2 = afrontsector->ceilingheight;
+ backf1 = backf2 = abacksector->floorheight;
+ backc1 = backc2 = abacksector->ceilingheight;
+ }
+
+ // now check for closed sectors!
+ if (backc1 <= frontf1 && backc2 <= frontf2)
+ {
+ checkforemptylines = false;
+ if (!seg->sidedef->toptexture)
+ return false;
+
+ if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum)
+ return false;
+
+ return true;
+ }
+
+ if (backf1 >= frontc1 && backf2 >= frontc2)
+ {
+ checkforemptylines = false;
+ if (!seg->sidedef->bottomtexture)
+ return false;
+
+ // properly render skies (consider door "open" if both floors are sky):
+ if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum)
+ return false;
+
+ return true;
+ }
+
+ if (backc1 <= backf1 && backc2 <= backf2)
+ {
+ checkforemptylines = false;
+ // preserve a kind of transparent door/lift special effect:
+ if (backc1 < frontc1 || backc2 < frontc2)
+ {
+ if (!seg->sidedef->toptexture)
+ return false;
+ }
+ if (backf1 > frontf1 || backf2 > frontf2)
+ {
+ if (!seg->sidedef->bottomtexture)
+ return false;
+ }
+ if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum)
+ return false;
+
+ if (abacksector->floorpic == skyflatnum && afrontsector->floorpic == skyflatnum)
+ return false;
+
+ return true;
+ }
+
+ if (backc1 != frontc1 || backc2 != frontc2
+ || backf1 != frontf1 || backf2 != frontf2)
+ {
+ checkforemptylines = false;
+ return false;
+ }
+
+ return false;
+}
+#else
//Hurdler: just like in r_bsp.c
#if 1
#define MAXSEGS MAXVIDWIDTH/2+1
@@ -2559,7 +2614,7 @@ static void HWR_ClipSolidWallSegment(INT32 first, INT32 last)
}
else
{
- highfrac = HWR_ClipViewSegment(start->first+1, (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
+ highfrac = HWR_ClipViewSegment(start->first+1, (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
HWR_StoreWallRange(0, highfrac);
}
// Now adjust the clip size.
@@ -2583,8 +2638,8 @@ static void HWR_ClipSolidWallSegment(INT32 first, INT32 last)
}
else
{
- lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
- highfrac = HWR_ClipViewSegment((next+1)->first+1, (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
+ lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
+ highfrac = HWR_ClipViewSegment((next+1)->first+1, (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
HWR_StoreWallRange(lowfrac, highfrac);
}
next++;
@@ -2618,7 +2673,7 @@ static void HWR_ClipSolidWallSegment(INT32 first, INT32 last)
}
else
{
- lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
+ lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
HWR_StoreWallRange(lowfrac, 1);
}
}
@@ -2681,8 +2736,8 @@ static void HWR_ClipPassWallSegment(INT32 first, INT32 last)
else
{
highfrac = HWR_ClipViewSegment(min(start->first + 1,
- start->last), (polyvertex_t *)gr_curline->v1,
- (polyvertex_t *)gr_curline->v2);
+ start->last), (polyvertex_t *)gr_curline->pv1,
+ (polyvertex_t *)gr_curline->pv2);
HWR_StoreWallRange(0, highfrac);
}
}
@@ -2701,8 +2756,8 @@ static void HWR_ClipPassWallSegment(INT32 first, INT32 last)
}
else
{
- lowfrac = HWR_ClipViewSegment(max(start->last-1,start->first), (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
- highfrac = HWR_ClipViewSegment(min((start+1)->first+1,(start+1)->last), (polyvertex_t *)gr_curline->v1, (polyvertex_t *)gr_curline->v2);
+ lowfrac = HWR_ClipViewSegment(max(start->last-1,start->first), (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
+ highfrac = HWR_ClipViewSegment(min((start+1)->first+1,(start+1)->last), (polyvertex_t *)gr_curline->pv1, (polyvertex_t *)gr_curline->pv2);
HWR_StoreWallRange(lowfrac, highfrac);
}
start++;
@@ -2732,8 +2787,8 @@ static void HWR_ClipPassWallSegment(INT32 first, INT32 last)
else
{
lowfrac = HWR_ClipViewSegment(max(start->last - 1,
- start->first), (polyvertex_t *)gr_curline->v1,
- (polyvertex_t *)gr_curline->v2);
+ start->first), (polyvertex_t *)gr_curline->pv1,
+ (polyvertex_t *)gr_curline->pv2);
HWR_StoreWallRange(lowfrac, 1);
}
}
@@ -2773,6 +2828,7 @@ static void HWR_ClearClipSegs(void)
gr_solidsegs[1].last = 0x7fffffff;
hw_newend = gr_solidsegs+2;
}
+#endif // NEWCLIP
// -----------------+
// HWR_AddLine : Clips the given segment and adds any visible pieces to the line list.
@@ -2781,24 +2837,46 @@ static void HWR_ClearClipSegs(void)
// -----------------+
static void HWR_AddLine(seg_t * line)
{
- INT32 x1, x2;
angle_t angle1, angle2;
+#ifndef NEWCLIP
+ INT32 x1, x2;
angle_t span, tspan;
+#endif
// SoM: Backsector needs to be run through R_FakeFlat
sector_t tempsec;
+ fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t
+#ifdef POLYOBJECTS
if (line->polyseg && !(line->polyseg->flags & POF_RENDERSIDES))
return;
+#endif
gr_curline = line;
- // OPTIMIZE: quickly reject orthogonal back sides.
- angle1 = R_PointToAngle(FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->x),
- FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->y));
- angle2 = R_PointToAngle(FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->x),
- FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->y));
+ v1x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->x);
+ v1y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->y);
+ v2x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x);
+ v2y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y);
+ // OPTIMIZE: quickly reject orthogonal back sides.
+ angle1 = R_PointToAngle(v1x, v1y);
+ angle2 = R_PointToAngle(v2x, v2y);
+
+#ifdef NEWCLIP
+ // PrBoom: Back side, i.e. backface culling - read: endAngle >= startAngle!
+ if (angle2 - angle1 < ANGLE_180)
+ return;
+
+ // PrBoom: use REAL clipping math YAYYYYYYY!!!
+
+ if (!gld_clipper_SafeCheckRange(angle2, angle1))
+ {
+ return;
+ }
+
+ checkforemptylines = true;
+#else
// Clip to view edges.
span = angle1 - angle2;
@@ -2839,8 +2917,8 @@ static void HWR_AddLine(seg_t * line)
float fx1,fx2,fy1,fy2;
//BP: test with a better projection than viewangletox[R_PointToAngle(angle)]
// do not enable this at release 4 mul and 2 div
- fx1 = ((polyvertex_t *)(line->v1))->x-gr_viewx;
- fy1 = ((polyvertex_t *)(line->v1))->y-gr_viewy;
+ fx1 = ((polyvertex_t *)(line->pv1))->x-gr_viewx;
+ fy1 = ((polyvertex_t *)(line->pv1))->y-gr_viewy;
fy2 = (fx1 * gr_viewcos + fy1 * gr_viewsin);
if (fy2 < 0)
// the point is back
@@ -2848,8 +2926,8 @@ static void HWR_AddLine(seg_t * line)
else
fx1 = gr_windowcenterx + (fx1 * gr_viewsin - fy1 * gr_viewcos) * gr_centerx / fy2;
- fx2 = ((polyvertex_t *)(line->v2))->x-gr_viewx;
- fy2 = ((polyvertex_t *)(line->v2))->y-gr_viewy;
+ fx2 = ((polyvertex_t *)(line->pv2))->x-gr_viewx;
+ fy2 = ((polyvertex_t *)(line->pv2))->y-gr_viewy;
fy1 = (fx2 * gr_viewcos + fy2 * gr_viewsin);
if (fy1 < 0)
// the point is back
@@ -2877,8 +2955,34 @@ static void HWR_AddLine(seg_t * line)
return;
}
*/
+#endif
+
gr_backsector = line->backsector;
+#ifdef NEWCLIP
+ if (!line->backsector)
+ {
+ gld_clipper_SafeAddClipRange(angle2, angle1);
+ }
+ else
+ {
+ gr_backsector = R_FakeFlat(gr_backsector, &tempsec, NULL, NULL, true);
+ if (CheckClip(line, gr_frontsector, gr_backsector))
+ {
+ gld_clipper_SafeAddClipRange(angle2, angle1);
+ checkforemptylines = false;
+ }
+ // Reject empty lines used for triggers and special events.
+ // Identical floor and ceiling on both sides,
+ // identical light levels on both sides,
+ // and no middle texture.
+ if (checkforemptylines && R_IsEmptyLine(line, gr_frontsector, gr_backsector))
+ return;
+ }
+
+ HWR_ProcessSeg(); // Doesn't need arguments because they're defined globally :D
+ return;
+#else
// Single sided line?
if (!gr_backsector)
goto clipsolid;
@@ -2888,14 +2992,9 @@ static void HWR_AddLine(seg_t * line)
#ifdef ESLOPE
if (gr_frontsector->f_slope || gr_frontsector->c_slope || gr_backsector->f_slope || gr_backsector->c_slope)
{
- fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t
fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends
- v1x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->x);
- v1y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v1)->y);
- v2x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->x);
- v2y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->v2)->y);
#define SLOPEPARAMS(slope, end1, end2, normalheight) \
if (slope) { \
end1 = P_GetZAt(slope, v1x, v1y); \
@@ -2916,6 +3015,13 @@ static void HWR_AddLine(seg_t * line)
goto clipsolid;
}
+ // Check for automap fix.
+ if (backc1 <= backf1 && backc2 <= backf2
+ && ((backc1 >= frontc1 && backc2 >= frontc2) || gr_curline->sidedef->toptexture)
+ && ((backf1 <= frontf1 && backf2 >= frontf2) || gr_curline->sidedef->bottomtexture)
+ && (gr_backsector->ceilingpic != skyflatnum || gr_frontsector->ceilingpic != skyflatnum))
+ goto clipsolid;
+
// Window.
if (backc1 != frontc1 || backc2 != frontc2
|| backf1 != frontf1 || backf2 != frontf2)
@@ -2931,6 +3037,13 @@ static void HWR_AddLine(seg_t * line)
gr_backsector->floorheight >= gr_frontsector->ceilingheight)
goto clipsolid;
+ // Check for automap fix.
+ if (gr_backsector->ceilingheight <= gr_backsector->floorheight
+ && ((gr_backsector->ceilingheight >= gr_frontsector->ceilingheight) || gr_curline->sidedef->toptexture)
+ && ((gr_backsector->floorheight <= gr_backsector->floorheight) || gr_curline->sidedef->bottomtexture)
+ && (gr_backsector->ceilingpic != skyflatnum || gr_frontsector->ceilingpic != skyflatnum))
+ goto clipsolid;
+
// Window.
if (gr_backsector->ceilingheight != gr_frontsector->ceilingheight ||
gr_backsector->floorheight != gr_frontsector->floorheight)
@@ -2941,25 +3054,8 @@ static void HWR_AddLine(seg_t * line)
// Identical floor and ceiling on both sides,
// identical light levels on both sides,
// and no middle texture.
- if (
-#ifdef POLYOBJECTS
- !line->polyseg &&
-#endif
- gr_backsector->ceilingpic == gr_frontsector->ceilingpic
- && gr_backsector->floorpic == gr_frontsector->floorpic
-#ifdef ESLOPE
- && gr_backsector->f_slope == gr_frontsector->f_slope
- && gr_backsector->c_slope == gr_frontsector->c_slope
-#endif
- && gr_backsector->lightlevel == gr_frontsector->lightlevel
- && gr_curline->sidedef->midtexture == 0
- && !gr_backsector->ffloors && !gr_frontsector->ffloors)
- // SoM: For 3D sides... Boris, would you like to take a
- // crack at rendering 3D sides? You would need to add the
- // above check and add code to HWR_StoreWallRange...
- {
+ if (R_IsEmptyLine(gr_curline, gr_frontsector, gr_backsector))
return;
- }
clippass:
if (x1 == x2)
@@ -2971,6 +3067,7 @@ clipsolid:
if (x1 == x2)
goto clippass;
HWR_ClipSolidWallSegment(x1, x2-1);
+#endif
}
// HWR_CheckBBox
@@ -2982,9 +3079,13 @@ clipsolid:
static boolean HWR_CheckBBox(fixed_t *bspcoord)
{
- INT32 boxpos, sx1, sx2;
+ INT32 boxpos;
fixed_t px1, py1, px2, py2;
- angle_t angle1, angle2, span, tspan;
+ angle_t angle1, angle2;
+#ifndef NEWCLIP
+ INT32 sx1, sx2;
+ angle_t span, tspan;
+#endif
// Find the corners of the box
// that define the edges from current viewpoint.
@@ -3010,6 +3111,11 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord)
px2 = bspcoord[checkcoord[boxpos][2]];
py2 = bspcoord[checkcoord[boxpos][3]];
+#ifdef NEWCLIP
+ angle1 = R_PointToAngle(px1, py1);
+ angle2 = R_PointToAngle(px2, py2);
+ return gld_clipper_SafeCheckRange(angle2, angle1);
+#else
// check clip list for an open space
angle1 = R_PointToAngle(px1, py1) - dup_viewangle;
angle2 = R_PointToAngle(px2, py2) - dup_viewangle;
@@ -3057,6 +3163,7 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord)
return false;
return HWR_ClipToSolidSegs(sx1, sx2 - 1);
+#endif
}
#ifdef POLYOBJECTS
@@ -3090,8 +3197,8 @@ static inline void HWR_AddPolyObjectSegs(void)
pv2->x = FIXED_TO_FLOAT(gr_fakeline->v2->x);
pv2->y = FIXED_TO_FLOAT(gr_fakeline->v2->y);
- gr_fakeline->v1 = (vertex_t *)pv1;
- gr_fakeline->v2 = (vertex_t *)pv2;
+ gr_fakeline->pv1 = pv1;
+ gr_fakeline->pv2 = pv2;
HWR_AddLine(gr_fakeline);
}
@@ -3367,7 +3474,6 @@ static void HWR_Subsector(size_t num)
if (num < numsubsectors)
{
- sscount++;
// subsector
sub = &subsectors[num];
// sector
@@ -3722,6 +3828,9 @@ static void HWR_Subsector(size_t num)
while (count--)
{
+#ifdef POLYOBJECTS
+ if (!line->polyseg) // ignore segs that belong to polyobjects
+#endif
HWR_AddLine(line);
line++;
}
@@ -4227,6 +4336,7 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
GLPatch_t *gpatch; // sprite patch converted to hardware
FSurfaceInfo Surf;
const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES);
+ //const boolean papersprite = (spr->mobj && (spr->mobj->frame & FF_PAPERSPRITE));
if (spr->mobj)
this_scale = FIXED_TO_FLOAT(spr->mobj->scale);
if (hires)
@@ -4270,7 +4380,8 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
// make a wall polygon (with 2 triangles), using the floor/ceiling heights,
// and the 2d map coords of start/end vertices
- wallVerts[0].z = wallVerts[1].z = wallVerts[2].z = wallVerts[3].z = spr->tz;
+ wallVerts[0].z = wallVerts[3].z = spr->z1;
+ wallVerts[2].z = wallVerts[1].z = spr->z2;
// transform
wv = wallVerts;
@@ -5066,6 +5177,10 @@ static void HWR_ProjectSprite(mobj_t *thing)
angle_t ang;
INT32 heightsec, phs;
+ const boolean papersprite = (thing->frame & FF_PAPERSPRITE);
+ float offset;
+ float ang_scale = 1.0f, ang_scalez = 0.0f;
+ float z1, z2;
if (!thing)
return;
@@ -5080,7 +5195,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
tz = (tr_x * gr_viewcos) + (tr_y * gr_viewsin);
// thing is behind view plane?
- if (tz < ZCLIP_PLANE && (!cv_grmd2.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear
+ if (tz < ZCLIP_PLANE && !papersprite && (!cv_grmd2.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear
return;
tx = (tr_x * gr_viewsin) - (tr_y * gr_viewcos);
@@ -5118,6 +5233,27 @@ static void HWR_ProjectSprite(mobj_t *thing)
I_Error("sprframes NULL for sprite %d\n", thing->sprite);
#endif
+ if (papersprite)
+ {
+ // Use the actual view angle, rather than the angle formed
+ // between the view point and the thing
+ // this makes sure paper sprites always appear at the right angle!
+ // Note: DO NOT do this in software mode version, it actually
+ // makes papersprites look WORSE there (I know, I've tried)
+ // Monster Iestyn - 13/05/17
+ ang = dup_viewangle - (thing->player ? thing->player->drawangle : thing->angle);
+ ang_scale = FIXED_TO_FLOAT(FINESINE(ang>>ANGLETOFINESHIFT));
+ ang_scalez = FIXED_TO_FLOAT(FINECOSINE(ang>>ANGLETOFINESHIFT));
+
+ if (ang_scale < 0)
+ {
+ ang_scale = -ang_scale;
+ ang_scalez = -ang_scalez;
+ }
+ }
+ else if (sprframe->rotate != SRF_SINGLE)
+ ang = R_PointToAngle (thing->x, thing->y) - (thing->player ? thing->player->drawangle : thing->angle);
+
if (sprframe->rotate == SRF_SINGLE)
{
// use single rotation for all views
@@ -5128,8 +5264,6 @@ static void HWR_ProjectSprite(mobj_t *thing)
else
{
// choose a different rotation based on player view
- ang = R_PointToAngle (thing->x, thing->y) - (thing->player ? thing->player->drawangle : thing->angle);
-
if ((sprframe->rotate & SRF_RIGHT) && (ang < ANGLE_180)) // See from right
rot = 6; // F7 slot
else if ((sprframe->rotate & SRF_LEFT) && (ang >= ANGLE_180)) // See from left
@@ -5147,9 +5281,12 @@ static void HWR_ProjectSprite(mobj_t *thing)
// calculate edges of the shape
if (flip)
- tx -= FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width - spritecachedinfo[lumpoff].offset) * this_scale;
+ offset = FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width - spritecachedinfo[lumpoff].offset) * this_scale;
else
- tx -= FIXED_TO_FLOAT(spritecachedinfo[lumpoff].offset) * this_scale;
+ offset = FIXED_TO_FLOAT(spritecachedinfo[lumpoff].offset) * this_scale;
+
+ z1 = tz - (offset * ang_scalez);
+ tx -= offset * ang_scale;
// project x
x1 = gr_windowcenterx + (tx * gr_centerx / tz);
@@ -5160,7 +5297,14 @@ static void HWR_ProjectSprite(mobj_t *thing)
x1 = tx;
- tx += FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width) * this_scale;
+ offset = FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width) * this_scale;
+
+ z2 = z1 + (offset * ang_scalez);
+ tx += offset * ang_scale;
+
+ if (papersprite && max(z1, z2) < ZCLIP_PLANE)
+ return;
+
x2 = gr_windowcenterx + (tx * gr_centerx / tz);
if (vflip)
@@ -5209,6 +5353,8 @@ static void HWR_ProjectSprite(mobj_t *thing)
vis->patchlumpnum = sprframe->lumppat[rot];
vis->flip = flip;
vis->mobj = thing;
+ vis->z1 = z1;
+ vis->z2 = z2;
//Hurdler: 25/04/2000: now support colormap in hardware mode
if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash"
@@ -5597,7 +5743,19 @@ if (0)
#ifdef SORTING
drawcount = 0;
#endif
+#ifdef NEWCLIP
+ if (rendermode == render_opengl)
+ {
+ angle_t a1 = gld_FrustumAngle();
+ gld_clipper_Clear();
+ gld_clipper_SafeAddClipRange(viewangle + a1, viewangle - a1);
+#ifdef HAVE_SPHEREFRUSTRUM
+ gld_FrustrumSetup();
+#endif
+ }
+#else
HWR_ClearClipSegs();
+#endif
//04/01/2000: Hurdler: added for T&L
// Actually it only works on Walls and Planes
@@ -5607,6 +5765,7 @@ if (0)
HWR_RenderBSPNode((INT32)numnodes-1);
+#ifndef NEWCLIP
// Make a viewangle int so we can render things based on mouselook
if (player == &players[consoleplayer])
viewangle = localaiming;
@@ -5633,6 +5792,7 @@ if (0)
dup_viewangle += ANGLE_90;
}
+#endif
// Check for new console commands.
NetUpdate();
@@ -5827,7 +5987,19 @@ if (0)
#ifdef SORTING
drawcount = 0;
#endif
+#ifdef NEWCLIP
+ if (rendermode == render_opengl)
+ {
+ angle_t a1 = gld_FrustumAngle();
+ gld_clipper_Clear();
+ gld_clipper_SafeAddClipRange(viewangle + a1, viewangle - a1);
+#ifdef HAVE_SPHEREFRUSTRUM
+ gld_FrustrumSetup();
+#endif
+ }
+#else
HWR_ClearClipSegs();
+#endif
//04/01/2000: Hurdler: added for T&L
// Actually it only works on Walls and Planes
@@ -5837,6 +6009,7 @@ if (0)
HWR_RenderBSPNode((INT32)numnodes-1);
+#ifndef NEWCLIP
// Make a viewangle int so we can render things based on mouselook
if (player == &players[consoleplayer])
viewangle = localaiming;
@@ -5863,6 +6036,7 @@ if (0)
dup_viewangle += ANGLE_90;
}
+#endif
// Check for new console commands.
NetUpdate();
@@ -6008,7 +6182,9 @@ static inline void HWR_AddEngineCommands(void)
{
// engine state variables
//CV_RegisterVar(&cv_grzbuffer);
+#ifndef NEWCLIP
CV_RegisterVar(&cv_grclipwalls);
+#endif
// engine development mode variables
// - usage may vary from version to version..
diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c
index 29a3e72db..6fa5c3afb 100644
--- a/src/hardware/hw_md2.c
+++ b/src/hardware/hw_md2.c
@@ -298,8 +298,8 @@ static md2_model_t *md2_readModel(const char *filename)
// initialize model and read header
if (fread(&model->header, sizeof (model->header), 1, file) != 1
- || model->header.magic !=
- (INT32)(('2' << 24) + ('P' << 16) + ('D' << 8) + 'I'))
+ || model->header.magic != MD2_IDENT
+ || model->header.version != MD2_VERSION)
{
fclose(file);
free(model);
@@ -313,6 +313,7 @@ static md2_model_t *md2_readModel(const char *filename)
{ \
CONS_Alert(CONS_ERROR, "md2_readModel: %s has too many " msgname " (# found: %d, maximum: %d)\n", filename, field, max); \
md2_freeModel (model); \
+ fclose(file); \
return 0; \
}
@@ -334,6 +335,7 @@ static md2_model_t *md2_readModel(const char *filename)
fread(model->skins, sizeof (md2_skin_t), model->header.numSkins, file))
{
md2_freeModel (model);
+ fclose(file);
return 0;
}
}
@@ -347,6 +349,7 @@ static md2_model_t *md2_readModel(const char *filename)
fread(model->texCoords, sizeof (md2_textureCoordinate_t), model->header.numTexCoords, file))
{
md2_freeModel (model);
+ fclose(file);
return 0;
}
}
@@ -360,6 +363,7 @@ static md2_model_t *md2_readModel(const char *filename)
fread(model->triangles, sizeof (md2_triangle_t), model->header.numTriangles, file))
{
md2_freeModel (model);
+ fclose(file);
return 0;
}
}
@@ -372,6 +376,7 @@ static md2_model_t *md2_readModel(const char *filename)
if (!model->frames)
{
md2_freeModel (model);
+ fclose(file);
return 0;
}
@@ -385,6 +390,7 @@ static md2_model_t *md2_readModel(const char *filename)
fread(frame, 1, model->header.frameSize, file))
{
md2_freeModel (model);
+ fclose(file);
return 0;
}
@@ -410,6 +416,7 @@ static md2_model_t *md2_readModel(const char *filename)
fread(model->glCommandBuffer, sizeof (INT32), model->header.numGlCommands, file))
{
md2_freeModel (model);
+ fclose(file);
return 0;
}
}
@@ -961,244 +968,10 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch,
image = gpatch->mipmap.grInfo.data;
blendimage = blendgpatch->mipmap.grInfo.data;
- switch (color)
- {
- case SKINCOLOR_WHITE:
- blendcolor = V_GetColor(3);
- break;
- case SKINCOLOR_SILVER:
- blendcolor = V_GetColor(10);
- break;
- case SKINCOLOR_GREY:
- blendcolor = V_GetColor(15);
- break;
- case SKINCOLOR_BLACK:
- blendcolor = V_GetColor(27);
- break;
- case SKINCOLOR_BEIGE:
- blendcolor = V_GetColor(247);
- break;
- case SKINCOLOR_PEACH:
- blendcolor = V_GetColor(218);
- break;
- case SKINCOLOR_BROWN:
- blendcolor = V_GetColor(234);
- break;
- case SKINCOLOR_RED:
- blendcolor = V_GetColor(38);
- break;
- case SKINCOLOR_CRIMSON:
- blendcolor = V_GetColor(45);
- break;
- case SKINCOLOR_ORANGE:
- blendcolor = V_GetColor(54);
- break;
- case SKINCOLOR_RUST:
- blendcolor = V_GetColor(60);
- break;
- case SKINCOLOR_GOLD:
- blendcolor = V_GetColor(67);
- break;
- case SKINCOLOR_YELLOW:
- blendcolor = V_GetColor(73);
- break;
- case SKINCOLOR_TAN:
- blendcolor = V_GetColor(85);
- break;
- case SKINCOLOR_MOSS:
- blendcolor = V_GetColor(92);
- break;
- case SKINCOLOR_PERIDOT:
- blendcolor = V_GetColor(188);
- break;
- case SKINCOLOR_GREEN:
- blendcolor = V_GetColor(101);
- break;
- case SKINCOLOR_EMERALD:
- blendcolor = V_GetColor(112);
- break;
- case SKINCOLOR_AQUA:
- blendcolor = V_GetColor(122);
- break;
- case SKINCOLOR_TEAL:
- blendcolor = V_GetColor(141);
- break;
- case SKINCOLOR_CYAN:
- blendcolor = V_GetColor(131);
- break;
- case SKINCOLOR_BLUE:
- blendcolor = V_GetColor(152);
- break;
- case SKINCOLOR_AZURE:
- blendcolor = V_GetColor(171);
- break;
- case SKINCOLOR_PASTEL:
- blendcolor = V_GetColor(161);
- break;
- case SKINCOLOR_PURPLE:
- blendcolor = V_GetColor(165);
- break;
- case SKINCOLOR_LAVENDER:
- blendcolor = V_GetColor(195);
- break;
- case SKINCOLOR_MAGENTA:
- blendcolor = V_GetColor(183);
- break;
- case SKINCOLOR_PINK:
- blendcolor = V_GetColor(211);
- break;
- case SKINCOLOR_ROSY:
- blendcolor = V_GetColor(202);
- break;
-
- case SKINCOLOR_SUPERSILVER1: // Super silver
- blendcolor = V_GetColor(0);
- break;
- case SKINCOLOR_SUPERSILVER2:
- blendcolor = V_GetColor(2);
- break;
- case SKINCOLOR_SUPERSILVER3:
- blendcolor = V_GetColor(4);
- break;
- case SKINCOLOR_SUPERSILVER4:
- blendcolor = V_GetColor(7);
- break;
- case SKINCOLOR_SUPERSILVER5:
- blendcolor = V_GetColor(10);
- break;
-
- case SKINCOLOR_SUPERRED1: // Super red
- blendcolor = V_GetColor(208);
- break;
- case SKINCOLOR_SUPERRED2:
- blendcolor = V_GetColor(210);
- break;
- case SKINCOLOR_SUPERRED3:
- blendcolor = V_GetColor(32);
- break;
- case SKINCOLOR_SUPERRED4:
- blendcolor = V_GetColor(33);
- break;
- case SKINCOLOR_SUPERRED5:
- blendcolor = V_GetColor(35);
- break;
-
- case SKINCOLOR_SUPERORANGE1: // Super orange
- blendcolor = V_GetColor(208);
- break;
- case SKINCOLOR_SUPERORANGE2:
- blendcolor = V_GetColor(48);
- break;
- case SKINCOLOR_SUPERORANGE3:
- blendcolor = V_GetColor(50);
- break;
- case SKINCOLOR_SUPERORANGE4:
- blendcolor = V_GetColor(54);
- break;
- case SKINCOLOR_SUPERORANGE5:
- blendcolor = V_GetColor(58);
- break;
-
- case SKINCOLOR_SUPERGOLD1: // Super gold
- blendcolor = V_GetColor(80);
- break;
- case SKINCOLOR_SUPERGOLD2:
- blendcolor = V_GetColor(83);
- break;
- case SKINCOLOR_SUPERGOLD3:
- blendcolor = V_GetColor(73);
- break;
- case SKINCOLOR_SUPERGOLD4:
- blendcolor = V_GetColor(64);
- break;
- case SKINCOLOR_SUPERGOLD5:
- blendcolor = V_GetColor(67);
- break;
-
- case SKINCOLOR_SUPERPERIDOT1: // Super peridot
- blendcolor = V_GetColor(88);
- break;
- case SKINCOLOR_SUPERPERIDOT2:
- blendcolor = V_GetColor(188);
- break;
- case SKINCOLOR_SUPERPERIDOT3:
- blendcolor = V_GetColor(189);
- break;
- case SKINCOLOR_SUPERPERIDOT4:
- blendcolor = V_GetColor(190);
- break;
- case SKINCOLOR_SUPERPERIDOT5:
- blendcolor = V_GetColor(191);
- break;
-
- case SKINCOLOR_SUPERCYAN1: // Super cyan
- blendcolor = V_GetColor(128);
- break;
- case SKINCOLOR_SUPERCYAN2:
- blendcolor = V_GetColor(131);
- break;
- case SKINCOLOR_SUPERCYAN3:
- blendcolor = V_GetColor(133);
- break;
- case SKINCOLOR_SUPERCYAN4:
- blendcolor = V_GetColor(134);
- break;
- case SKINCOLOR_SUPERCYAN5:
- blendcolor = V_GetColor(136);
- break;
-
- case SKINCOLOR_SUPERPURPLE1: // Super purple
- blendcolor = V_GetColor(144);
- break;
- case SKINCOLOR_SUPERPURPLE2:
- blendcolor = V_GetColor(162);
- break;
- case SKINCOLOR_SUPERPURPLE3:
- blendcolor = V_GetColor(164);
- break;
- case SKINCOLOR_SUPERPURPLE4:
- blendcolor = V_GetColor(166);
- break;
- case SKINCOLOR_SUPERPURPLE5:
- blendcolor = V_GetColor(168);
- break;
-
- case SKINCOLOR_SUPERRUST1: // Super rust
- blendcolor = V_GetColor(51);
- break;
- case SKINCOLOR_SUPERRUST2:
- blendcolor = V_GetColor(54);
- break;
- case SKINCOLOR_SUPERRUST3:
- blendcolor = V_GetColor(68);
- break;
- case SKINCOLOR_SUPERRUST4:
- blendcolor = V_GetColor(70);
- break;
- case SKINCOLOR_SUPERRUST5:
- blendcolor = V_GetColor(234);
- break;
-
- case SKINCOLOR_SUPERTAN1: // Super tan
- blendcolor = V_GetColor(80);
- break;
- case SKINCOLOR_SUPERTAN2:
- blendcolor = V_GetColor(82);
- break;
- case SKINCOLOR_SUPERTAN3:
- blendcolor = V_GetColor(84);
- break;
- case SKINCOLOR_SUPERTAN4:
- blendcolor = V_GetColor(87);
- break;
- case SKINCOLOR_SUPERTAN5:
- blendcolor = V_GetColor(247);
- break;
-
- default:
- blendcolor = V_GetColor(255);
- break;
- }
+ if (color == SKINCOLOR_NONE || color >= MAXTRANSLATIONS)
+ blendcolor = V_GetColor(0xff);
+ else
+ blendcolor = V_GetColor(Color_Index[color-1][4]);
while (size--)
{
diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h
index 5a7e6d2b3..299d12400 100644
--- a/src/hardware/hw_md2.h
+++ b/src/hardware/hw_md2.h
@@ -23,6 +23,11 @@
#include "hw_glob.h"
+// magic number "IDP2" or 844121161
+#define MD2_IDENT (INT32)(('2' << 24) + ('P' << 16) + ('D' << 8) + 'I')
+// model version
+#define MD2_VERSION 8
+
#define MD2_MAX_TRIANGLES 8192
#define MD2_MAX_VERTICES 4096
#define MD2_MAX_TEXCOORDS 4096
diff --git a/src/hardware/hw_trick.c b/src/hardware/hw_trick.c
index e9ba19efb..97d86b944 100644
--- a/src/hardware/hw_trick.c
+++ b/src/hardware/hw_trick.c
@@ -107,17 +107,17 @@ static void releaseLineChains(void)
for (i = 0; i < numsectors; i++)
{
- sector = §ors[i];
- nextElem = sector->sectorLines;
+ sector = §ors[i];
+ nextElem = sector->sectorLines;
- while (nextElem)
- {
- thisElem = nextElem;
- nextElem = thisElem->next;
- free(thisElem);
- }
+ while (nextElem)
+ {
+ thisElem = nextElem;
+ nextElem = thisElem->next;
+ free(thisElem);
+ }
- sector->sectorLines = NULL;
+ sector->sectorLines = NULL;
}
}
@@ -397,7 +397,7 @@ static void sortStacklist(sector_t *sector)
i = 0;
finished = true;
- while (NULL != *(list+i+1))
+ while (*(list+i+1))
{
sec1 = *(list+i);
sec2 = *(list+i+1);
@@ -438,7 +438,7 @@ static double calcLineoutLength(sector_t *sector)
double length = 0.0L;
chain = sector->sectorLines;
- while (NULL != chain) // sum up lengths of all lines
+ while (chain) // sum up lengths of all lines
{
length += lineLength(chain->line);
chain = chain->next;
@@ -454,7 +454,7 @@ static void calcLineouts(sector_t *sector)
size_t secCount = 0;
sector_t *encSector = *(sector->stackList);
- while (NULL != encSector)
+ while (encSector)
{
if (encSector->lineoutLength < 0.0L) // if length has not yet been calculated
{
@@ -552,7 +552,7 @@ static boolean areBottomtexturesMissing(sector_t *thisSector)
if (frontSector == backSector) // skip damn renderer tricks here
continue;
- if (frontSector == NULL || backSector == NULL)
+ if (!frontSector || !backSector)
continue;
sider = &sides[thisElem->line->sidenum[0]];
@@ -587,73 +587,12 @@ static boolean areBottomtexturesMissing(sector_t *thisSector)
static boolean isCeilingFloating(sector_t *thisSector)
{
sector_t *adjSector, *refSector = NULL, *frontSector, *backSector;
- boolean floating = true;
linechain_t *thisElem, *nextElem;
if (!thisSector)
return false;
- nextElem = thisSector->sectorLines;
-
- while (NULL != nextElem) // walk through chain
- {
- thisElem = nextElem;
- nextElem = thisElem->next;
-
- frontSector = thisElem->line->frontsector;
- backSector = thisElem->line->backsector;
-
- if (frontSector == thisSector)
- adjSector = backSector;
- else
- adjSector = frontSector;
-
- if (!adjSector) // assume floating sectors have surrounding sectors
- {
- floating = false;
- break;
- }
-
- if (!refSector)
- {
- refSector = adjSector;
- continue;
- }
-
- // if adjacent sector has same height or more than one adjacent sector exists -> stop
- if (thisSector->ceilingheight == adjSector->ceilingheight ||
- refSector != adjSector)
- {
- floating = false;
- break;
- }
- }
-
- // now check for walltextures
- if (floating)
- {
- if (!areToptexturesMissing(thisSector))
- {
- floating = false;
- }
- }
- return floating;
-}
-
-//
-// check if no adjacent sector has same ceiling height
-// FIXME: throw that together with isCeilingFloating??
-//
-static boolean isFloorFloating(sector_t *thisSector)
-{
- sector_t *adjSector, *refSector = NULL, *frontSector, *backSector;
- boolean floating = true;
- linechain_t *thisElem, *nextElem;
-
- if (!thisSector)
- return false;
-
- nextElem = thisSector->sectorLines;
+ nextElem = thisSector->sectorLines;
while (nextElem) // walk through chain
{
@@ -668,36 +607,83 @@ static boolean isFloorFloating(sector_t *thisSector)
else
adjSector = frontSector;
- if (NULL == adjSector) // assume floating sectors have surrounding sectors
- {
- floating = false;
- break;
- }
+ if (!adjSector) // assume floating sectors have surrounding sectors
+ return false;
- if (NULL == refSector)
+#ifdef ESLOPE
+ if (adjSector->c_slope) // Don't bother with slopes
+ return false;
+#endif
+
+ if (!refSector)
{
refSector = adjSector;
continue;
}
// if adjacent sector has same height or more than one adjacent sector exists -> stop
- if (thisSector->floorheight == adjSector->floorheight ||
- refSector != adjSector)
- {
- floating = false;
- break;
- }
+ if (thisSector->ceilingheight == adjSector->ceilingheight || refSector != adjSector)
+ return false;
}
// now check for walltextures
- if (floating)
+ if (!areToptexturesMissing(thisSector))
+ return false;
+
+ return true;
+}
+
+//
+// check if no adjacent sector has same ceiling height
+// FIXME: throw that together with isCeilingFloating??
+//
+static boolean isFloorFloating(sector_t *thisSector)
+{
+ sector_t *adjSector, *refSector = NULL, *frontSector, *backSector;
+ linechain_t *thisElem, *nextElem;
+
+ if (!thisSector)
+ return false;
+
+ nextElem = thisSector->sectorLines;
+
+ while (nextElem) // walk through chain
{
- if (!areBottomtexturesMissing(thisSector))
+ thisElem = nextElem;
+ nextElem = thisElem->next;
+
+ frontSector = thisElem->line->frontsector;
+ backSector = thisElem->line->backsector;
+
+ if (frontSector == thisSector)
+ adjSector = backSector;
+ else
+ adjSector = frontSector;
+
+ if (!adjSector) // assume floating sectors have surrounding sectors
+ return false;
+
+#ifdef ESLOPE
+ if (adjSector->f_slope) // Don't bother with slopes
+ return false;
+#endif
+
+ if (!refSector)
{
- floating = false;
+ refSector = adjSector;
+ continue;
}
+
+ // if adjacent sector has same height or more than one adjacent sector exists -> stop
+ if (thisSector->floorheight == adjSector->floorheight || refSector != adjSector)
+ return false;
}
- return floating;
+
+ // now check for walltextures
+ if (!areBottomtexturesMissing(thisSector))
+ return false;
+
+ return true;
}
//
@@ -707,14 +693,12 @@ static fixed_t estimateCeilHeight(sector_t *thisSector)
{
sector_t *adjSector;
- if (!thisSector ||
- !thisSector->sectorLines ||
- !thisSector->sectorLines->line)
+ if (!thisSector || !thisSector->sectorLines || !thisSector->sectorLines->line)
return 0;
adjSector = thisSector->sectorLines->line->frontsector;
if (adjSector == thisSector)
- adjSector = thisSector->sectorLines->line->backsector;
+ adjSector = thisSector->sectorLines->line->backsector;
if (!adjSector)
return 0;
@@ -729,17 +713,15 @@ static fixed_t estimateFloorHeight(sector_t *thisSector)
{
sector_t *adjSector;
- if (!thisSector ||
- !thisSector->sectorLines ||
- !thisSector->sectorLines->line)
- return 0;
+ if (!thisSector || !thisSector->sectorLines || !thisSector->sectorLines->line)
+ return 0;
adjSector = thisSector->sectorLines->line->frontsector;
if (adjSector == thisSector)
- adjSector = thisSector->sectorLines->line->backsector;
+ adjSector = thisSector->sectorLines->line->backsector;
- if (NULL == adjSector)
- return 0;
+ if (!adjSector)
+ return 0;
return adjSector->floorheight;
}
@@ -845,18 +827,12 @@ void HWR_CorrectSWTricks(void)
// correct height of floating sectors
if (isCeilingFloating(floatSector))
{
- fixed_t corrheight;
-
- corrheight = estimateCeilHeight(floatSector);
- floatSector->virtualCeilingheight = corrheight;
+ floatSector->virtualCeilingheight = estimateCeilHeight(floatSector);
floatSector->virtualCeiling = true;
}
if (isFloorFloating(floatSector))
{
- fixed_t corrheight;
-
- corrheight = estimateFloorHeight(floatSector);
- floatSector->virtualFloorheight = corrheight;
+ floatSector->virtualFloorheight = estimateFloorHeight(floatSector);
floatSector->virtualFloor = true;
}
}
diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c
index 3a0bf7054..e6ff83e89 100644
--- a/src/hardware/r_opengl/r_opengl.c
+++ b/src/hardware/r_opengl/r_opengl.c
@@ -244,6 +244,7 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...)
#define pglMaterialfv glMaterialfv
/* Raster functions */
+#define pglPixelStorei glPixelStorei
#define pglReadPixels glReadPixels
/* Texture mapping */
@@ -262,15 +263,8 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...)
/* texture mapping */ //GL_EXT_copy_texture
#ifndef KOS_GL_COMPATIBILITY
#define pglCopyTexImage2D glCopyTexImage2D
+#endif
-/* GLU functions */
-#define pgluBuild2DMipmaps gluBuild2DMipmaps
-#endif
-#ifndef MINI_GL_COMPATIBILITY
-/* 1.3 functions for multitexturing */
-#define pglActiveTexture glActiveTexture
-#define pglMultiTexCoord2f glMultiTexCoord2f
-#endif
#else //!STATIC_OPENGL
/* 1.0 functions */
@@ -365,6 +359,8 @@ typedef void (APIENTRY * PFNglMaterialfv) (GLint face, GLenum pname, GLfloat *pa
static PFNglMaterialfv pglMaterialfv;
/* Raster functions */
+typedef void (APIENTRY * PFNglPixelStorei) (GLenum pname, GLint param);
+static PFNglPixelStorei pglPixelStorei;
typedef void (APIENTRY * PFNglReadPixels) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
static PFNglReadPixels pglReadPixels;
@@ -391,7 +387,7 @@ static PFNglBindTexture pglBindTexture;
/* texture mapping */ //GL_EXT_copy_texture
typedef void (APIENTRY * PFNglCopyTexImage2D) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
static PFNglCopyTexImage2D pglCopyTexImage2D;
-
+#endif
/* GLU functions */
typedef GLint (APIENTRY * PFNgluBuild2DMipmaps) (GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *data);
static PFNgluBuild2DMipmaps pgluBuild2DMipmaps;
@@ -403,7 +399,6 @@ static PFNglActiveTexture pglActiveTexture;
typedef void (APIENTRY *PFNglMultiTexCoord2f) (GLenum, GLfloat, GLfloat);
static PFNglMultiTexCoord2f pglMultiTexCoord2f;
#endif
-#endif
#ifndef MINI_GL_COMPATIBILITY
/* 1.2 Parms */
@@ -494,6 +489,7 @@ boolean SetupGLfunc(void)
GETOPENGLFUNC(pglLightModelfv , glLightModelfv)
GETOPENGLFUNC(pglMaterialfv , glMaterialfv)
+ GETOPENGLFUNC(pglPixelStorei , glPixelStorei)
GETOPENGLFUNC(pglReadPixels , glReadPixels)
GETOPENGLFUNC(pglTexEnvi , glTexEnvi)
@@ -519,35 +515,23 @@ boolean SetupGLfunc(void)
// This has to be done after the context is created so the version number can be obtained
boolean SetupGLFunc13(void)
{
+#ifdef MINI_GL_COMPATIBILITY
+ return false;
+#else
const GLubyte *version = pglGetString(GL_VERSION);
int glmajor, glminor;
gl13 = false;
-#ifdef MINI_GL_COMPATIBILITY
- return false;
-#else
-#ifdef STATIC_OPENGL
- gl13 = true;
-#else
-
// Parse the GL version
if (version != NULL)
{
if (sscanf((const char*)version, "%d.%d", &glmajor, &glminor) == 2)
{
// Look, we gotta prepare for the inevitable arrival of GL 2.0 code...
- switch (glmajor)
- {
- case 1:
- if (glminor == 3) gl13 = true;
- break;
- case 2:
- case 3:
- case 4:
- gl13 = true;
- default:
- break;
- }
+ if (glmajor == 1 && glminor >= 3)
+ gl13 = true;
+ else if (glmajor > 1)
+ gl13 = true;
}
}
@@ -568,9 +552,6 @@ boolean SetupGLFunc13(void)
}
else
DBG_Printf("GL_ARB_multitexture support: disabled\n");
-#undef GETOPENGLFUNC
-
-#endif
return true;
#endif
}
@@ -897,7 +878,9 @@ EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height,
GLubyte*top = (GLvoid*)dst_data, *bottom = top + dst_stride * (height - 1);
GLubyte *row = malloc(dst_stride);
if (!row) return;
+ pglPixelStorei(GL_PACK_ALIGNMENT, 1);
pglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, dst_data);
+ pglPixelStorei(GL_UNPACK_ALIGNMENT, 1);
for(i = 0; i < height/2; i++)
{
memcpy(row, top, dst_stride);
@@ -913,7 +896,9 @@ EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height,
INT32 j;
GLubyte *image = malloc(width*height*3*sizeof (*image));
if (!image) return;
+ pglPixelStorei(GL_PACK_ALIGNMENT, 1);
pglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, image);
+ pglPixelStorei(GL_UNPACK_ALIGNMENT, 1);
for (i = height-1; i >= 0; i--)
{
for (j = 0; j < width; j++)
@@ -1815,13 +1800,11 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value)
min_filter = GL_NEAREST;
#endif
}
-#ifndef STATIC_OPENGL
if (!pgluBuild2DMipmaps)
{
MipMap = GL_FALSE;
min_filter = GL_LINEAR;
}
-#endif
Flush(); //??? if we want to change filter mode by texture, remove this
break;
diff --git a/src/hu_stuff.c b/src/hu_stuff.c
index f6275631c..e92b96995 100644
--- a/src/hu_stuff.c
+++ b/src/hu_stuff.c
@@ -91,7 +91,8 @@ patch_t *tallminus;
patch_t *emeraldpics[7];
patch_t *tinyemeraldpics[7];
static patch_t *emblemicon;
-static patch_t *tokenicon;
+patch_t *tokenicon;
+static patch_t *exiticon;
//-------------------------------------------
// misc vars
@@ -245,6 +246,7 @@ void HU_LoadGraphics(void)
emblemicon = W_CachePatchName("EMBLICON", PU_HUDGFX);
tokenicon = W_CachePatchName("TOKNICON", PU_HUDGFX);
+ exiticon = W_CachePatchName("EXITICON", PU_HUDGFX);
emeraldpics[0] = W_CachePatchName("CHAOS1", PU_HUDGFX);
emeraldpics[1] = W_CachePatchName("CHAOS2", PU_HUDGFX);
@@ -840,7 +842,7 @@ static void HU_DrawChat(void)
else
{
//charwidth = SHORT(hu_font[talk[i]-HU_FONTSTART]->width) * con_scalefactor;
- V_DrawCharacter(HU_INPUTX + c, y, talk[i++] | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value);
+ V_DrawCharacter(HU_INPUTX + c, y, talk[i++] | cv_constextsize.value | V_NOSCALESTART, true);
}
c += charwidth;
}
@@ -857,7 +859,7 @@ static void HU_DrawChat(void)
else
{
//charwidth = SHORT(hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor;
- V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | cv_constextsize.value | V_NOSCALESTART | t, !cv_allcaps.value);
+ V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | cv_constextsize.value | V_NOSCALESTART | t, true);
}
c += charwidth;
@@ -869,7 +871,7 @@ static void HU_DrawChat(void)
}
if (hu_tick < 4)
- V_DrawCharacter(HU_INPUTX + c, y, '_' | cv_constextsize.value |V_NOSCALESTART|t, !cv_allcaps.value);
+ V_DrawCharacter(HU_INPUTX + c, y, '_' | cv_constextsize.value |V_NOSCALESTART|t, true);
}
@@ -1176,6 +1178,9 @@ void HU_Erase(void)
// IN-LEVEL MULTIPLAYER RANKINGS
//======================================================================
+#define supercheckdef ((players[tab[i].num].powers[pw_super] && players[tab[i].num].mo && (players[tab[i].num].mo->state < &states[S_PLAY_SUPER_TRANS] || players[tab[i].num].mo->state > &states[S_PLAY_SUPER_TRANS9])) || (players[tab[i].num].powers[pw_carry] == CR_NIGHTSMODE && skins[players[tab[i].num].skin].flags & SF_SUPER))
+#define greycheckdef ((players[tab[i].num].mo && players[tab[i].num].mo->health <= 0) || players[tab[i].num].spectator)
+
//
// HU_DrawTabRankings
//
@@ -1183,6 +1188,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
{
INT32 i;
const UINT8 *colormap;
+ boolean greycheck, supercheck;
//this function is designed for 9 or less score lines only
I_Assert(scorelines <= 9);
@@ -1191,12 +1197,15 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
for (i = 0; i < scorelines; i++)
{
- if (players[tab[i].num].spectator)
+ if (players[tab[i].num].spectator && gametype != GT_COOP)
continue; //ignore them.
+ greycheck = greycheckdef;
+ supercheck = supercheckdef;
+
V_DrawString(x + 20, y,
((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0)
- | ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_60TRANS)
+ | (greycheck ? V_60TRANS : 0)
| V_ALLOWLOWERCASE, tab[i].name);
// Draw emeralds
@@ -1206,7 +1215,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
HU_DrawEmeralds(x-12,y+2,tab[i].emeralds);
}
- if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0)
+ if (greycheck)
V_DrawSmallTranslucentPatch (x, y-4, V_80TRANS, livesback);
else
V_DrawSmallScaledPatch (x, y-4, 0, livesback);
@@ -1214,11 +1223,11 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
if (tab[i].color == 0)
{
colormap = colormaps;
- if (players[tab[i].num].powers[pw_super])
+ if (supercheck)
V_DrawSmallScaledPatch(x, y-4, 0, superprefix[players[tab[i].num].skin]);
else
{
- if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0)
+ if (greycheck)
V_DrawSmallTranslucentPatch(x, y-4, V_80TRANS, faceprefix[players[tab[i].num].skin]);
else
V_DrawSmallScaledPatch(x, y-4, 0, faceprefix[players[tab[i].num].skin]);
@@ -1226,7 +1235,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
}
else
{
- if (players[tab[i].num].powers[pw_super] && players[tab[i].num].mo && (players[tab[i].num].mo->state < &states[S_PLAY_SUPER_TRANS] || players[tab[i].num].mo->state > &states[S_PLAY_SUPER_TRANS9]))
+ if (supercheck)
{
colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo->color, GTC_CACHE);
V_DrawSmallMappedPatch (x, y-4, 0, superprefix[players[tab[i].num].skin], colormap);
@@ -1234,23 +1243,26 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
else
{
colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE);
- if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0)
+ if (greycheck)
V_DrawSmallTranslucentMappedPatch (x, y-4, V_80TRANS, faceprefix[players[tab[i].num].skin], colormap);
else
V_DrawSmallMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap);
}
}
- if (G_GametypeUsesLives()) //show lives
- V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE|((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_60TRANS), va("%dx", players[tab[i].num].lives));
+ if (G_GametypeUsesLives() && !(gametype == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3))) //show lives
+ V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE|(greycheck ? V_60TRANS : 0), va("%dx", players[tab[i].num].lives));
else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT)
{
- if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0)
+ if (greycheck)
V_DrawSmallTranslucentPatch(x-32, y-4, V_60TRANS, tagico);
else
V_DrawSmallScaledPatch(x-32, y-4, 0, tagico);
}
+ if (players[tab[i].num].exiting)
+ V_DrawSmallScaledPatch(x - SHORT(exiticon->width)/2 - 1, y-3, 0, exiticon);
+
if (gametype == GT_RACE)
{
if (circuitmap)
@@ -1258,13 +1270,13 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
if (players[tab[i].num].exiting)
V_DrawRightAlignedString(x+240, y, 0, va("%i:%02i.%02i", G_TicsToMinutes(players[tab[i].num].realtime,true), G_TicsToSeconds(players[tab[i].num].realtime), G_TicsToCentiseconds(players[tab[i].num].realtime)));
else
- V_DrawRightAlignedString(x+240, y, ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_60TRANS), va("%u", tab[i].count));
+ V_DrawRightAlignedString(x+240, y, (greycheck ? V_60TRANS : 0), va("%u", tab[i].count));
}
else
- V_DrawRightAlignedString(x+240, y, ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_60TRANS), va("%i:%02i.%02i", G_TicsToMinutes(tab[i].count,true), G_TicsToSeconds(tab[i].count), G_TicsToCentiseconds(tab[i].count)));
+ V_DrawRightAlignedString(x+240, y, (greycheck ? V_60TRANS : 0), va("%i:%02i.%02i", G_TicsToMinutes(tab[i].count,true), G_TicsToSeconds(tab[i].count), G_TicsToCentiseconds(tab[i].count)));
}
else
- V_DrawRightAlignedString(x+240, y, ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_60TRANS), va("%u", tab[i].count));
+ V_DrawRightAlignedString(x+240, y, (greycheck ? V_60TRANS : 0), va("%u", tab[i].count));
y += 16;
}
@@ -1279,6 +1291,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer)
INT32 redplayers = 0, blueplayers = 0;
const UINT8 *colormap;
char name[MAXPLAYERNAME+1];
+ boolean greycheck, supercheck;
V_DrawFill(160, 26, 1, 154, 0); //Draw a vertical line to separate the two teams.
V_DrawFill(1, 26, 318, 1, 0); //And a horizontal line to make a T.
@@ -1306,10 +1319,13 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer)
else //er? not on red or blue, so ignore them
continue;
+ greycheck = greycheckdef;
+ supercheck = supercheckdef;
+
strlcpy(name, tab[i].name, 9);
V_DrawString(x + 20, y,
((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0)
- | ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_TRANSLUCENT)
+ | (greycheck ? V_TRANSLUCENT : 0)
| V_ALLOWLOWERCASE, name);
if (gametype == GT_CTF)
@@ -1327,7 +1343,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer)
HU_DrawEmeralds(x-12,y+2,tab[i].emeralds);
}
- if (players[tab[i].num].powers[pw_super])
+ if (supercheck)
{
colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE);
V_DrawSmallMappedPatch (x, y-4, 0, superprefix[players[tab[i].num].skin], colormap);
@@ -1335,12 +1351,12 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer)
else
{
colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE);
- if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0)
- V_DrawSmallTranslucentMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap);
+ if (greycheck)
+ V_DrawSmallTranslucentMappedPatch (x, y-4, V_80TRANS, faceprefix[players[tab[i].num].skin], colormap);
else
V_DrawSmallMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap);
}
- V_DrawRightAlignedThinString(x+120, y, ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count));
+ V_DrawRightAlignedThinString(x+120, y, (greycheck ? V_TRANSLUCENT : 0), va("%u", tab[i].count));
}
}
@@ -1352,6 +1368,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
INT32 i;
const UINT8 *colormap;
char name[MAXPLAYERNAME+1];
+ boolean greycheck, supercheck;
V_DrawFill(160, 26, 1, 154, 0); //Draw a vertical line to separate the two sides.
V_DrawFill(1, 26, 318, 1, 0); //And a horizontal line to make a T.
@@ -1359,20 +1376,26 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
for (i = 0; i < scorelines; i++)
{
- if (players[tab[i].num].spectator)
+ if (players[tab[i].num].spectator && gametype != GT_COOP)
continue; //ignore them.
+ greycheck = greycheckdef;
+ supercheck = supercheckdef;
+
strlcpy(name, tab[i].name, 9);
V_DrawString(x + 20, y,
((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0)
- | ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_TRANSLUCENT)
+ | (greycheck ? V_TRANSLUCENT : 0)
| V_ALLOWLOWERCASE, name);
- if (G_GametypeUsesLives()) //show lives
+ if (G_GametypeUsesLives() && !(gametype == GT_COOP && (cv_cooplives.value == 0 || cv_cooplives.value == 3))) //show lives
V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE, va("%dx", players[tab[i].num].lives));
else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT)
V_DrawSmallScaledPatch(x-28, y-4, 0, tagico);
+ if (players[tab[i].num].exiting)
+ V_DrawSmallScaledPatch(x - SHORT(exiticon->width)/2 - 1, y-3, 0, exiticon);
+
// Draw emeralds
if (!players[tab[i].num].powers[pw_super]
|| ((leveltime/7) & 1))
@@ -1384,19 +1407,19 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
if (tab[i].color == 0)
{
colormap = colormaps;
- if (players[tab[i].num].powers[pw_super])
+ if (supercheck)
V_DrawSmallScaledPatch (x, y-4, 0, superprefix[players[tab[i].num].skin]);
else
{
- if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0)
- V_DrawSmallTranslucentPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin]);
+ if (greycheck)
+ V_DrawSmallTranslucentPatch (x, y-4, V_80TRANS, faceprefix[players[tab[i].num].skin]);
else
V_DrawSmallScaledPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin]);
}
}
else
{
- if (players[tab[i].num].powers[pw_super])
+ if (supercheck)
{
colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE);
V_DrawSmallMappedPatch (x, y-4, 0, superprefix[players[tab[i].num].skin], colormap);
@@ -1404,8 +1427,8 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
else
{
colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE);
- if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0)
- V_DrawSmallTranslucentMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap);
+ if (greycheck)
+ V_DrawSmallTranslucentMappedPatch (x, y-4, V_80TRANS, faceprefix[players[tab[i].num].skin], colormap);
else
V_DrawSmallMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap);
}
@@ -1419,13 +1442,13 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
if (players[tab[i].num].exiting)
V_DrawRightAlignedThinString(x+156, y, 0, va("%i:%02i.%02i", G_TicsToMinutes(players[tab[i].num].realtime,true), G_TicsToSeconds(players[tab[i].num].realtime), G_TicsToCentiseconds(players[tab[i].num].realtime)));
else
- V_DrawRightAlignedThinString(x+156, y, ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count));
+ V_DrawRightAlignedThinString(x+156, y, (greycheck ? V_TRANSLUCENT : 0), va("%u", tab[i].count));
}
else
- V_DrawRightAlignedThinString(x+156, y, ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_TRANSLUCENT), va("%i:%02i.%02i", G_TicsToMinutes(tab[i].count,true), G_TicsToSeconds(tab[i].count), G_TicsToCentiseconds(tab[i].count)));
+ V_DrawRightAlignedThinString(x+156, y, (greycheck ? V_TRANSLUCENT : 0), va("%i:%02i.%02i", G_TicsToMinutes(tab[i].count,true), G_TicsToSeconds(tab[i].count), G_TicsToCentiseconds(tab[i].count)));
}
else
- V_DrawRightAlignedThinString(x+120, y, ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count));
+ V_DrawRightAlignedThinString(x+120, y, (greycheck ? V_TRANSLUCENT : 0), va("%u", tab[i].count));
y += 16;
if (y > 160)
@@ -1622,61 +1645,67 @@ static void HU_DrawRankings(void)
for (j = 0; j < MAXPLAYERS; j++)
{
- if (!playeringame[j] || players[j].spectator)
+ if (!playeringame[j])
+ continue;
+
+ if (gametype != GT_COOP && players[j].spectator)
continue;
for (i = 0; i < MAXPLAYERS; i++)
{
- if (playeringame[i] && !players[i].spectator)
+ if (!playeringame[i])
+ continue;
+
+ if (gametype != GT_COOP && players[i].spectator)
+ continue;
+
+ if (gametype == GT_RACE)
{
- if (gametype == GT_RACE)
+ if (circuitmap)
{
- if (circuitmap)
+ if ((unsigned)players[i].laps+1 >= tab[scorelines].count && completed[i] == false)
{
- if ((unsigned)players[i].laps+1 >= tab[scorelines].count && completed[i] == false)
- {
- tab[scorelines].count = players[i].laps+1;
- tab[scorelines].num = i;
- tab[scorelines].color = players[i].skincolor;
- tab[scorelines].name = player_names[i];
- }
- }
- else
- {
- if (players[i].realtime <= tab[scorelines].count && completed[i] == false)
- {
- tab[scorelines].count = players[i].realtime;
- tab[scorelines].num = i;
- tab[scorelines].color = players[i].skincolor;
- tab[scorelines].name = player_names[i];
- }
- }
- }
- else if (gametype == GT_COMPETITION)
- {
- // todo put something more fitting for the gametype here, such as current
- // number of categories led
- if (players[i].score >= tab[scorelines].count && completed[i] == false)
- {
- tab[scorelines].count = players[i].score;
+ tab[scorelines].count = players[i].laps+1;
tab[scorelines].num = i;
tab[scorelines].color = players[i].skincolor;
tab[scorelines].name = player_names[i];
- tab[scorelines].emeralds = players[i].powers[pw_emeralds];
}
}
else
{
- if (players[i].score >= tab[scorelines].count && completed[i] == false)
+ if (players[i].realtime <= tab[scorelines].count && completed[i] == false)
{
- tab[scorelines].count = players[i].score;
+ tab[scorelines].count = players[i].realtime;
tab[scorelines].num = i;
tab[scorelines].color = players[i].skincolor;
tab[scorelines].name = player_names[i];
- tab[scorelines].emeralds = players[i].powers[pw_emeralds];
}
}
}
+ else if (gametype == GT_COMPETITION)
+ {
+ // todo put something more fitting for the gametype here, such as current
+ // number of categories led
+ if (players[i].score >= tab[scorelines].count && completed[i] == false)
+ {
+ tab[scorelines].count = players[i].score;
+ tab[scorelines].num = i;
+ tab[scorelines].color = players[i].skincolor;
+ tab[scorelines].name = player_names[i];
+ tab[scorelines].emeralds = players[i].powers[pw_emeralds];
+ }
+ }
+ else
+ {
+ if (players[i].score >= tab[scorelines].count && completed[i] == false)
+ {
+ tab[scorelines].count = players[i].score;
+ tab[scorelines].num = i;
+ tab[scorelines].color = players[i].skincolor;
+ tab[scorelines].name = player_names[i];
+ tab[scorelines].emeralds = players[i].powers[pw_emeralds];
+ }
+ }
}
completed[tab[scorelines].num] = true;
scorelines++;
diff --git a/src/hu_stuff.h b/src/hu_stuff.h
index 7b22f33f1..e757db85a 100644
--- a/src/hu_stuff.h
+++ b/src/hu_stuff.h
@@ -21,7 +21,7 @@
//------------------------------------
// heads up font
//------------------------------------
-#define HU_FONTSTART '\x1F' // the first font character
+#define HU_FONTSTART '\x16' // the first font character
#define HU_FONTEND '~'
#define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1)
@@ -71,6 +71,7 @@ extern patch_t *rmatcico;
extern patch_t *bmatcico;
extern patch_t *tagico;
extern patch_t *tallminus;
+extern patch_t *tokenicon;
// set true when entering a chat message
extern boolean chat_on;
@@ -78,9 +79,6 @@ extern boolean chat_on;
// set true whenever the tab rankings are being shown for any reason
extern boolean hu_showscores;
-// P_DeathThink sets this true to show scores while dead, in multiplayer
-extern boolean playerdeadview;
-
// init heads up data at game startup.
void HU_Init(void);
diff --git a/src/info.c b/src/info.c
index 7d6e1fede..2d6c9a3d1 100644
--- a/src/info.c
+++ b/src/info.c
@@ -114,7 +114,6 @@ char sprnames[NUMSPRITES + 1][5] =
// Collectible Items
"RING",
"TRNG", // Team Rings
- "EMMY", // emerald test
"TOKE", // Special Stage Token
"RFLG", // Red CTF Flag
"BFLG", // Blue CTF Flag
@@ -131,6 +130,8 @@ char sprnames[NUMSPRITES + 1][5] =
"SPIK", // Spike Ball
"SFLM", // Spin fire
"USPK", // Floor spike
+ "WSPK", // Wall spike
+ "WSPB", // Wall spike base
"STPT", // Starpost
"BMNE", // Big floating mine
@@ -181,6 +182,12 @@ char sprnames[NUMSPRITES + 1][5] =
"FWR4",
"BUS1", // GFZ Bush w/ berries
"BUS2", // GFZ Bush w/o berries
+ // Trees (both GFZ and misc)
+ "TRE1", // GFZ
+ "TRE2", // Checker
+ "TRE3", // Frozen Hillside
+ "TRE4", // Polygon
+ "TRE5", // Bush tree
// Techno Hill Scenery
"THZP", // Techno Hill Zone Plant
@@ -204,6 +211,10 @@ char sprnames[NUMSPRITES + 1][5] =
"BMCH", // Big Mace Chain
"SMCE", // Small Mace
"BMCE", // Big Mace
+ "YSPB", // Yellow spring on a ball
+ "RSPB", // Red spring on a ball
+ "SFBR", // Small Firebar
+ "BFBR", // Big Firebar
// Arid Canyon Scenery
"BTBL", // Big tumbleweed
@@ -219,9 +230,11 @@ char sprnames[NUMSPRITES + 1][5] =
// Egg Rock Scenery
// Christmas Scenery
- "XMS1",
- "XMS2",
- "XMS3",
+ "XMS1", // Christmas Pole
+ "XMS2", // Candy Cane
+ "XMS3", // Snowman
+ "XMS4", // Lamppost
+ "XMS5", // Hanging Star
// Botanic Serenity Scenery
"BSZ1", // Tall flowers
@@ -924,13 +937,13 @@ state_t states[NUMSTATES] =
{SPR_EGGM, 20, 2, {NULL}, 0, 0, S_EGGMOBILE_STND}, // S_EGGMOBILE_RATK10
{SPR_EGGM, 3, 12, {NULL}, 0, 0, S_EGGMOBILE_PANIC2}, // S_EGGMOBILE_PANIC1
{SPR_EGGM, 4, 4, {A_Boss1Spikeballs}, 0, 4, S_EGGMOBILE_PANIC3}, // S_EGGMOBILE_PANIC2
- {SPR_EGGM, 3, 5, {NULL}, 0, 0, S_EGGMOBILE_PANIC4}, // S_EGGMOBILE_PANIC3
+ {SPR_EGGM, 3, 8, {NULL}, 0, 0, S_EGGMOBILE_PANIC4}, // S_EGGMOBILE_PANIC3
{SPR_EGGM, 4, 4, {A_Boss1Spikeballs}, 1, 4, S_EGGMOBILE_PANIC5}, // S_EGGMOBILE_PANIC4
- {SPR_EGGM, 3, 5, {NULL}, 0, 0, S_EGGMOBILE_PANIC6}, // S_EGGMOBILE_PANIC5
+ {SPR_EGGM, 3, 8, {NULL}, 0, 0, S_EGGMOBILE_PANIC6}, // S_EGGMOBILE_PANIC5
{SPR_EGGM, 4, 4, {A_Boss1Spikeballs}, 2, 4, S_EGGMOBILE_PANIC7}, // S_EGGMOBILE_PANIC6
- {SPR_EGGM, 3, 5, {NULL}, 0, 0, S_EGGMOBILE_PANIC8}, // S_EGGMOBILE_PANIC7
+ {SPR_EGGM, 3, 8, {NULL}, 0, 0, S_EGGMOBILE_PANIC8}, // S_EGGMOBILE_PANIC7
{SPR_EGGM, 4, 4, {A_Boss1Spikeballs}, 3, 4, S_EGGMOBILE_PANIC9}, // S_EGGMOBILE_PANIC8
- {SPR_EGGM, 3, 5, {NULL}, 0, 0, S_EGGMOBILE_PANIC10},// S_EGGMOBILE_PANIC9
+ {SPR_EGGM, 3, 8, {NULL}, 0, 0, S_EGGMOBILE_PANIC10},// S_EGGMOBILE_PANIC9
{SPR_EGGM, 0, 35, {A_SkullAttack}, 0, 0, S_EGGMOBILE_STND}, // S_EGGMOBILE_PANIC10
{SPR_EGGM, 21, 24, {A_Pain}, 0, 0, S_EGGMOBILE_PAIN2}, // S_EGGMOBILE_PAIN
{SPR_EGGM, 21, 16, {A_SkullAttack}, 1, 1, S_EGGMOBILE_STND}, // S_EGGMOBILE_PAIN2
@@ -1407,14 +1420,10 @@ state_t states[NUMSTATES] =
{SPR_GWLR, 2, 1, {NULL}, 0, 0, S_GRAVWELLRED}, // S_GRAVWELLRED3
// Individual Team Rings (now with shield attracting action! =P)
- {SPR_TRNG, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 23, 1, S_TEAMRING}, // S_TEAMRING1
+ {SPR_TRNG, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 23, 1, S_TEAMRING}, // S_TEAMRING
// Special Stage Token
- {SPR_EMMY, FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 6, 2, S_EMMY}, // S_EMMY
-
- // Special Stage Token
- {SPR_TOKE, FF_TRANS50|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_TOKEN
- {SPR_TOKE, FF_TRANS50|FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_MOVINGTOKEN}, // S_MOVINGTOKEN
+ {SPR_TOKE, FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 19, 1, S_TOKEN}, // S_TOKEN
// CTF Flags
{SPR_RFLG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_REDFLAG
@@ -1558,13 +1567,24 @@ state_t states[NUMSTATES] =
// Floor Spike
{SPR_USPK, 0,-1, {A_SpikeRetract}, 1, 0, S_SPIKE2}, // S_SPIKE1 -- Fully extended
- {SPR_USPK, 5, 2, {A_Pain}, 0, 0, S_SPIKE3}, // S_SPIKE2
- {SPR_USPK, 4, 2, {NULL}, 0, 0, S_SPIKE4}, // S_SPIKE3
+ {SPR_USPK, 1, 2, {A_Pain}, 0, 0, S_SPIKE3}, // S_SPIKE2
+ {SPR_USPK, 2, 2, {NULL}, 0, 0, S_SPIKE4}, // S_SPIKE3
{SPR_USPK, 3,-1, {A_SpikeRetract}, 0, 0, S_SPIKE5}, // S_SPIKE4 -- Fully retracted
- {SPR_USPK, 4, 2, {A_Pain}, 0, 0, S_SPIKE6}, // S_SPIKE5
- {SPR_USPK, 5, 2, {NULL}, 0, 0, S_SPIKE1}, // S_SPIKE6
- {SPR_USPK, 1,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED1 -- Busted spike particles
- {SPR_USPK, 2,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED2
+ {SPR_USPK, 2, 2, {A_Pain}, 0, 0, S_SPIKE6}, // S_SPIKE5
+ {SPR_USPK, 1, 2, {NULL}, 0, 0, S_SPIKE1}, // S_SPIKE6
+ {SPR_USPK, 4,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED1 -- Busted spike particles
+ {SPR_USPK, 5,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED2
+
+ // Wall Spike
+ {SPR_WSPK, 0|FF_PAPERSPRITE,-1, {A_SpikeRetract}, 1, 0, S_WALLSPIKE2}, // S_WALLSPIKE1 -- Fully extended
+ {SPR_WSPK, 1|FF_PAPERSPRITE, 2, {A_Pain}, 0, 0, S_WALLSPIKE3}, // S_WALLSPIKE2
+ {SPR_WSPK, 2|FF_PAPERSPRITE, 2, {NULL}, 0, 0, S_WALLSPIKE4}, // S_WALLSPIKE3
+ {SPR_WSPK, 3|FF_PAPERSPRITE,-1, {A_SpikeRetract}, 0, 0, S_WALLSPIKE5}, // S_WALLSPIKE4 -- Fully retracted
+ {SPR_WSPK, 2|FF_PAPERSPRITE, 2, {A_Pain}, 0, 0, S_WALLSPIKE6}, // S_WALLSPIKE5
+ {SPR_WSPK, 1|FF_PAPERSPRITE, 2, {NULL}, 0, 0, S_WALLSPIKE1}, // S_WALLSPIKE6
+ {SPR_WSPB, 0|FF_PAPERSPRITE,-1, {NULL}, 0, 0, S_NULL}, // S_WALLSPIKEBASE -- Base
+ {SPR_WSPK, 4,-1, {NULL}, 0, 0, S_NULL}, // S_WALLSPIKED1 -- Busted spike particles
+ {SPR_WSPK, 5,-1, {NULL}, 0, 0, S_NULL}, // S_WALLSPIKED2
// Starpost
{SPR_STPT, 0 , -1, {NULL}, 0, 0, S_NULL}, // S_STARPOST_IDLE
@@ -1659,22 +1679,22 @@ state_t states[NUMSTATES] =
{SPR_TVRI, 2, 18, {A_RingBox}, 0, 0, S_NULL}, // S_RING_ICON2
{SPR_TVPI, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_PITY_ICON2}, // S_PITY_ICON1
- {SPR_TVPI, 2, 18, {A_PityShield}, 0, 0, S_NULL}, // S_PITY_ICON2
+ {SPR_TVPI, 2, 18, {A_GiveShield}, SH_PITY, 0, S_NULL}, // S_PITY_ICON2
{SPR_TVAT, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_ATTRACT_ICON2}, // S_ATTRACT_ICON1
- {SPR_TVAT, 2, 18, {A_RingShield},0, 0, S_NULL}, // S_ATTRACT_ICON2
+ {SPR_TVAT, 2, 18, {A_GiveShield}, SH_ATTRACT, 0, S_NULL}, // S_ATTRACT_ICON2
{SPR_TVFO, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_FORCE_ICON2}, // S_FORCE_ICON1
- {SPR_TVFO, 2, 18, {A_ForceShield}, 1, 0, S_NULL}, // S_FORCE_ICON2
+ {SPR_TVFO, 2, 18, {A_GiveShield}, SH_FORCE|1, 0, S_NULL}, // S_FORCE_ICON2
{SPR_TVAR, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_ARMAGEDDON_ICON2}, // S_ARMAGEDDON_ICON1
- {SPR_TVAR, 2, 18, {A_BombShield}, 0, 0, S_NULL}, // S_ARMAGEDDON_ICON2
+ {SPR_TVAR, 2, 18, {A_GiveShield}, SH_ARMAGEDDON, 0, S_NULL}, // S_ARMAGEDDON_ICON2
{SPR_TVWW, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_WHIRLWIND_ICON2}, // S_WHIRLWIND_ICON1
- {SPR_TVWW, 2, 18, {A_JumpShield}, 0, 0, S_NULL}, // S_WHIRLWIND_ICON2
+ {SPR_TVWW, 2, 18, {A_GiveShield}, SH_WHIRLWIND, 0, S_NULL}, // S_WHIRLWIND_ICON2
{SPR_TVEL, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_ELEMENTAL_ICON2}, // S_ELEMENTAL_ICON1
- {SPR_TVEL, 2, 18, {A_WaterShield}, 0, 0, S_NULL}, // S_ELEMENTAL_ICON2
+ {SPR_TVEL, 2, 18, {A_GiveShield}, SH_ELEMENTAL, 0, S_NULL}, // S_ELEMENTAL_ICON2
{SPR_TVSS, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_SNEAKERS_ICON2}, // S_SNEAKERS_ICON1
{SPR_TVSS, 2, 18, {A_SuperSneakers}, 0, 0, S_NULL}, // S_SNEAKERS_ICON2
@@ -1704,13 +1724,13 @@ state_t states[NUMSTATES] =
{SPR_TVTK, 2, 18, {A_AwardScore}, 0, 0, S_NULL}, // S_SCORE10K_ICON2
{SPR_TVFL, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_FLAMEAURA_ICON2}, // S_FLAMEAURA_ICON1
- {SPR_TVFL, 2, 18, {A_FlameShield}, 0, 0, S_NULL}, // S_FLAMEAURA_ICON2
+ {SPR_TVFL, 2, 18, {A_GiveShield}, SH_FLAMEAURA, 0, S_NULL}, // S_FLAMEAURA_ICON2
{SPR_TVBB, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_BUBBLEWRAP_ICON2}, // S_BUBBLEWRAP_ICON1
- {SPR_TVBB, 2, 18, {A_BubbleShield}, 0, 0, S_NULL}, // S_BUBBLERWAP_ICON2
+ {SPR_TVBB, 2, 18, {A_GiveShield}, SH_BUBBLEWRAP, 0, S_NULL}, // S_BUBBLERWAP_ICON2
{SPR_TVZP, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_THUNDERCOIN_ICON2}, // S_THUNDERCOIN_ICON1
- {SPR_TVZP, 2, 18, {A_ThunderShield}, 0, 0, S_NULL}, // S_THUNDERCOIN_ICON2
+ {SPR_TVZP, 2, 18, {A_GiveShield}, SH_THUNDERCOIN, 0, S_NULL}, // S_THUNDERCOIN_ICON2
// ---
@@ -1759,6 +1779,18 @@ state_t states[NUMSTATES] =
{SPR_BUS1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BERRYBUSH
{SPR_BUS2, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BUSH
+ // Trees
+ {SPR_TRE1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_GFZTREE
+ {SPR_TRE1, 1, -1, {NULL}, 0, 0, S_NULL}, // S_GFZBERRYTREE
+ {SPR_TRE1, 2, -1, {NULL}, 0, 0, S_NULL}, // S_GFZCHERRYTREE
+ {SPR_TRE2, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CHECKERTREE
+ {SPR_TRE2, 1, -1, {NULL}, 0, 0, S_NULL}, // S_CHECKERSUNSETTREE
+ {SPR_TRE3, 0, -1, {NULL}, 0, 0, S_NULL}, // S_FHZTREE
+ {SPR_TRE3, 1, -1, {NULL}, 0, 0, S_NULL}, // S_FHZPINKTREE
+ {SPR_TRE4, 0, -1, {NULL}, 0, 0, S_NULL}, // S_POLYGONTREE
+ {SPR_TRE5, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BUSHTREE
+ {SPR_TRE5, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BUSHREDTREE
+
{SPR_THZP, FF_ANIMATE, -1, {NULL}, 7, 4, S_NULL}, // S_THZFLOWERA
{SPR_FWR5, FF_ANIMATE, -1, {NULL}, 19, 2, S_NULL}, // S_THZFLOWERB
@@ -1767,6 +1799,7 @@ state_t states[NUMSTATES] =
// Deep Sea Gargoyle
{SPR_GARG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_GARGOYLE
+ {SPR_GARG, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BIGGARGOYLE
// DSZ Seaweed
{SPR_SEWE, 0, -1, {NULL}, 0, 0, S_SEAWEED2}, // S_SEAWEED1
@@ -1801,13 +1834,13 @@ state_t states[NUMSTATES] =
{SPR_CHAN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZCHAIN
// Flame
- {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20, 3, {A_FlameParticle}, 3, 0, S_FLAME2}, // S_FLAME1
- {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|1, 3, {NULL}, 0, 0, S_FLAME3}, // S_FLAME2
- {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|2, 3, {A_FlameParticle}, 3, 0, S_FLAME4}, // S_FLAME3
- {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|3, 3, {NULL}, 0, 0, S_FLAME5}, // S_FLAME4
- {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|4, 3, {A_FlameParticle}, 3, 0, S_FLAME6}, // S_FLAME5
- {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|5, 3, {NULL}, 0, 0, S_FLAME1}, // S_FLAME6
- {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS10|6, 24, {NULL}, 0, 0, S_NULL}, // S_FLAMEPARTICLE
+ {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20, 3, {A_FlameParticle}, 3, FRACUNIT/2, S_FLAME2}, // S_FLAME1
+ {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|1, 3, {NULL}, 0, 0 , S_FLAME3}, // S_FLAME2
+ {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|2, 3, {A_FlameParticle}, 3, FRACUNIT/2, S_FLAME4}, // S_FLAME3
+ {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|3, 3, {NULL}, 0, 0 , S_FLAME5}, // S_FLAME4
+ {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|4, 3, {A_FlameParticle}, 3, FRACUNIT/2, S_FLAME6}, // S_FLAME5
+ {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|5, 3, {NULL}, 0, 0 , S_FLAME1}, // S_FLAME6
+ {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS10|6, 24, {NULL}, 0, 0 , S_NULL}, // S_FLAMEPARTICLE
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|FF_ANIMATE, -1, {NULL}, 5, 3, S_FLAME2}, // S_FLAMEREST
@@ -1818,31 +1851,75 @@ state_t states[NUMSTATES] =
{SPR_NULL, 0, -1, {NULL}, 0, 0, S_SLING2}, // S_SLING1
{SPR_NULL, 0, -1, {A_SlingAppear}, 0, 0, S_NULL}, // S_SLING2
- // Small Mace Chain
- {SPR_SMCH, 0, 1, {A_MaceRotate}, 0, 0, S_SMALLMACECHAIN}, // S_SMALLMACECHAIN
+ // CEZ maces and chains
+ {SPR_SMCH, 0, -1, {NULL}, 0, 0, S_SMALLMACECHAIN}, // S_SMALLMACECHAIN
+ {SPR_BMCH, 0, -1, {NULL}, 0, 0, S_BIGMACECHAIN}, // S_BIGMACECHAIN
+ {SPR_SMCE, 0, -1, {NULL}, 0, 0, S_SMALLMACE}, // S_SMALLMACE
+ {SPR_BMCE, 0, -1, {NULL}, 0, 0, S_BIGMACE}, // S_BIGMACE
- // Big Mace Chain
- {SPR_BMCH, 0, 1, {A_MaceRotate}, 0, 0, S_BIGMACECHAIN}, // S_BIGMACECHAIN
+ // Yellow spring on a ball
+ {SPR_YSPB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_YELLOWSPRINGBALL
+ {SPR_YSPB, 4, 4, {A_Pain}, 0, 0, S_YELLOWSPRINGBALL3}, // S_YELLOWSPRINGBALL2
+ {SPR_YSPB, 3, 1, {NULL}, 0, 0, S_YELLOWSPRINGBALL4}, // S_YELLOWSPRINGBALL3
+ {SPR_YSPB, 2, 1, {NULL}, 0, 0, S_YELLOWSPRINGBALL5}, // S_YELLOWSPRINGBALL4
+ {SPR_YSPB, 1, 1, {NULL}, 0, 0, S_YELLOWSPRINGBALL}, // S_YELLOWSPRINGBALL5
- // Small Mace
- {SPR_SMCE, 0, 1, {A_MaceRotate}, 0, 0, S_SMALLMACE}, // S_SMALLMACE
+ // Red spring on a ball
+ {SPR_RSPB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_REDSPRINGBALL
+ {SPR_RSPB, 4, 4, {A_Pain}, 0, 0, S_REDSPRINGBALL3}, // S_REDSPRINGBALL2
+ {SPR_RSPB, 3, 1, {NULL}, 0, 0, S_REDSPRINGBALL4}, // S_REDSPRINGBALL3
+ {SPR_RSPB, 2, 1, {NULL}, 0, 0, S_REDSPRINGBALL5}, // S_REDSPRINGBALL4
+ {SPR_RSPB, 1, 1, {NULL}, 0, 0, S_REDSPRINGBALL}, // S_REDSPRINGBALL5
- // Big Mace
- {SPR_BMCE, 0, 1, {A_MaceRotate}, 0, 0, S_BIGMACE}, // S_BIGMACE
+ // Small Firebar
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR2}, // S_SMALLFIREBAR1
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 1, 1, {NULL}, 0, 0, S_SMALLFIREBAR3}, // S_SMALLFIREBAR2
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 2, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR4}, // S_SMALLFIREBAR3
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 3, 1, {NULL}, 0, 0, S_SMALLFIREBAR5}, // S_SMALLFIREBAR4
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 4, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR6}, // S_SMALLFIREBAR5
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 5, 1, {NULL}, 0, 0, S_SMALLFIREBAR7}, // S_SMALLFIREBAR6
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 6, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR8}, // S_SMALLFIREBAR7
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 7, 1, {NULL}, 0, 0, S_SMALLFIREBAR9}, // S_SMALLFIREBAR8
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 8, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR10}, // S_SMALLFIREBAR9
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 9, 1, {NULL}, 0, 0, S_SMALLFIREBAR11}, // S_SMALLFIREBAR10
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|10, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR12}, // S_SMALLFIREBAR11
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|11, 1, {NULL}, 0, 0, S_SMALLFIREBAR13}, // S_SMALLFIREBAR12
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|12, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR14}, // S_SMALLFIREBAR13
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|13, 1, {NULL}, 0, 0, S_SMALLFIREBAR15}, // S_SMALLFIREBAR14
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|14, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR16}, // S_SMALLFIREBAR15
+ {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|15, 1, {NULL}, 0, 0, S_SMALLFIREBAR1}, // S_SMALLFIREBAR16
+
+ // Big Firebar
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR2}, // S_BIGFIREBAR1
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 1, 1, {NULL}, 0, 0, S_BIGFIREBAR3}, // S_BIGFIREBAR2
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 2, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR4}, // S_BIGFIREBAR3
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 3, 1, {NULL}, 0, 0, S_BIGFIREBAR5}, // S_BIGFIREBAR4
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 4, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR6}, // S_BIGFIREBAR5
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 5, 1, {NULL}, 0, 0, S_BIGFIREBAR7}, // S_BIGFIREBAR6
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 6, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR8}, // S_BIGFIREBAR7
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 7, 1, {NULL}, 0, 0, S_BIGFIREBAR9}, // S_BIGFIREBAR8
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 8, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR10}, // S_BIGFIREBAR9
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 9, 1, {NULL}, 0, 0, S_BIGFIREBAR11}, // S_BIGFIREBAR10
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|10, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR12}, // S_BIGFIREBAR11
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|11, 1, {NULL}, 0, 0, S_BIGFIREBAR13}, // S_BIGFIREBAR12
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|12, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR14}, // S_BIGFIREBAR13
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|13, 1, {NULL}, 0, 0, S_BIGFIREBAR15}, // S_BIGFIREBAR14
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|14, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR16}, // S_BIGFIREBAR15
+ {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|15, 1, {NULL}, 0, 0, S_BIGFIREBAR1}, // S_BIGFIREBAR16
// CEZ Flower
{SPR_FWR4, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZFLOWER1
// Big Tumbleweed
- {SPR_BTBL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BIGTUMBLEWEED
- {SPR_BTBL, 0, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL2}, // S_BIGTUMBLEWEED_ROLL1
- {SPR_BTBL, 1, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL3}, // S_BIGTUMBLEWEED_ROLL2
- {SPR_BTBL, 2, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL4}, // S_BIGTUMBLEWEED_ROLL3
- {SPR_BTBL, 3, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL5}, // S_BIGTUMBLEWEED_ROLL4
- {SPR_BTBL, 4, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL6}, // S_BIGTUMBLEWEED_ROLL5
- {SPR_BTBL, 5, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL7}, // S_BIGTUMBLEWEED_ROLL6
- {SPR_BTBL, 6, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL8}, // S_BIGTUMBLEWEED_ROLL7
- {SPR_BTBL, 7, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL1}, // S_BIGTUMBLEWEED_ROLL8
+ {SPR_BTBL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BIGTUMBLEWEED
+ {SPR_BTBL, 0, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL2}, // S_BIGTUMBLEWEED_ROLL1
+ {SPR_BTBL, 1, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL3}, // S_BIGTUMBLEWEED_ROLL2
+ {SPR_BTBL, 2, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL4}, // S_BIGTUMBLEWEED_ROLL3
+ {SPR_BTBL, 3, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL5}, // S_BIGTUMBLEWEED_ROLL4
+ {SPR_BTBL, 4, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL6}, // S_BIGTUMBLEWEED_ROLL5
+ {SPR_BTBL, 5, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL7}, // S_BIGTUMBLEWEED_ROLL6
+ {SPR_BTBL, 6, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL8}, // S_BIGTUMBLEWEED_ROLL7
+ {SPR_BTBL, 7, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL1}, // S_BIGTUMBLEWEED_ROLL8
// Little Tumbleweed
{SPR_STBL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_LITTLETUMBLEWEED
@@ -1933,6 +2010,13 @@ state_t states[NUMSTATES] =
{SPR_XMS1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_XMASPOLE
{SPR_XMS2, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CANDYCANE
{SPR_XMS3, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SNOWMAN
+ {SPR_XMS3, 1, -1, {NULL}, 0, 0, S_NULL}, // S_SNOWMANHAT
+ {SPR_XMS4, 0, -1, {NULL}, 0, 0, S_NULL}, // S_LAMPPOST1
+ {SPR_XMS4, 1, -1, {NULL}, 0, 0, S_NULL}, // S_LAMPPOST2
+ {SPR_XMS5, 0, -1, {NULL}, 0, 0, S_NULL}, // S_HANGSTAR
+ // Xmas GFZ bushes
+ {SPR_BUS1, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BERRYBUSH
+ {SPR_BUS2, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BUSH
// Loads of Botanic Serenity bullshit
{SPR_BSZ1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BSZTALLFLOWER_RED
@@ -2122,16 +2206,12 @@ state_t states[NUMSTATES] =
{SPR_ELEM, FF_FULLBRIGHT|20, 1, {NULL}, 0, 0, S_ELEMF10}, // S_ELEMF9
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_ELEMF1 }, // S_ELEMF10
- {SPR_PITY, FF_TRANS20 , 1, {NULL}, 0, 0, S_PITY2 }, // S_PITY1
- {SPR_PITY, FF_TRANS20|1, 1, {NULL}, 0, 0, S_PITY3 }, // S_PITY2
- {SPR_PITY, FF_TRANS20 , 1, {NULL}, 0, 0, S_PITY4 }, // S_PITY3
- {SPR_PITY, FF_TRANS20|2, 1, {NULL}, 0, 0, S_PITY5 }, // S_PITY4
- {SPR_PITY, FF_TRANS20 , 1, {NULL}, 0, 0, S_PITY6 }, // S_PITY5
- {SPR_PITY, FF_TRANS20|3, 1, {NULL}, 0, 0, S_PITY7 }, // S_PITY6
- {SPR_PITY, FF_TRANS20 , 1, {NULL}, 0, 0, S_PITY8 }, // S_PITY7
- {SPR_PITY, FF_TRANS20|4, 1, {NULL}, 0, 0, S_PITY9 }, // S_PITY8
- {SPR_PITY, FF_TRANS20 , 1, {NULL}, 0, 0, S_PITY10}, // S_PITY9
- {SPR_PITY, FF_TRANS20|5, 1, {NULL}, 0, 0, S_PITY1 }, // S_PITY10
+ {SPR_PITY, FF_TRANS30 , 2, {NULL}, 0, 0, S_PITY2}, // S_PITY1
+ {SPR_PITY, FF_TRANS30|1, 2, {NULL}, 0, 0, S_PITY3}, // S_PITY2
+ {SPR_PITY, FF_TRANS30|2, 2, {NULL}, 0, 0, S_PITY4}, // S_PITY3
+ {SPR_PITY, FF_TRANS20|3, 2, {NULL}, 0, 0, S_PITY5}, // S_PITY4
+ {SPR_PITY, FF_TRANS30|4, 2, {NULL}, 0, 0, S_PITY6}, // S_PITY5
+ {SPR_PITY, FF_TRANS20|5, 2, {NULL}, 0, 0, S_PITY1}, // S_PITY6
{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40 , 2, {NULL}, 0, 0, S_FIRS2}, // S_FIRS1
{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|1, 2, {NULL}, 0, 0, S_FIRS3}, // S_FIRS2
@@ -2501,7 +2581,7 @@ state_t states[NUMSTATES] =
// Particle sprite
{SPR_PRTL, FF_FULLBRIGHT|FF_TRANS70, 2*TICRATE, {NULL}, 0, 0, S_NULL}, // S_PARTICLE
- {SPR_NULL, 0, 1, {A_ParticleSpawn}, 0, 0, S_PARTICLEGEN}, // S_PARTICLEGEN
+ {SPR_NULL, 0, 3, {A_ParticleSpawn}, 0, 0, S_PARTICLEGEN}, // S_PARTICLEGEN
{SPR_SCOR, 0, 32, {A_ScoreRise}, 0, 0, S_NULL}, // S_SCRA - 100
{SPR_SCOR, 1, 32, {A_ScoreRise}, 0, 0, S_NULL}, // S_SCRB - 200
@@ -2864,16 +2944,11 @@ state_t states[NUMSTATES] =
{SPR_NWNG, 1, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSWING_XMAS
// NiGHTS Paraloop Powerups
- {SPR_NULL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP1
- {SPR_NPRU, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP2
- {SPR_NULL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP3
- {SPR_NPRU, 1, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP4
- {SPR_NULL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP5
- {SPR_NPRU, 2, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP6
- {SPR_NULL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP7
- {SPR_NPRU, 3, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP8
- {SPR_NULL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP9
- {SPR_NPRU, 4, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPOWERUP10
+ {SPR_NPRU, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSSUPERLOOP
+ {SPR_NPRU, 1, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSDRILLREFILL
+ {SPR_NPRU, 2, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSHELPER
+ {SPR_NPRU, 3, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSEXTRATIME
+ {SPR_NPRU, 4, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSLINKFREEZE
{SPR_CAPS, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGCAPSULE
@@ -4091,7 +4166,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
- 2*FRACUNIT, // speed
+ 4*FRACUNIT, // speed
13*FRACUNIT, // radius
26*FRACUNIT, // height
0, // display offset
@@ -5156,9 +5231,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
- { // MT_EMMY
+ { // MT_TOKEN
312, // doomednum
- S_EMMY, // spawnstate
+ S_TOKEN, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
@@ -5183,33 +5258,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
- { // MT_TOKEN
- -1, // doomednum
- S_TOKEN, // spawnstate
- 1000, // spawnhealth
- S_MOVINGTOKEN, // seestate
- sfx_None, // seesound
- 8, // reactiontime
- sfx_None, // attacksound
- S_NULL, // painstate
- 0, // painchance
- sfx_None, // painsound
- S_NULL, // meleestate
- S_NULL, // missilestate
- S_NULL, // deathstate
- S_NULL, // xdeathstate
- sfx_None, // deathsound
- 8, // speed
- 8*FRACUNIT, // radius
- 16*FRACUNIT, // height
- 0, // display offset
- 100, // mass
- 0, // damage
- sfx_None, // activesound
- MF_NOGRAVITY|MF_NOBLOCKMAP|MF_NOCLIP, // flags
- S_NULL // raisestate
- },
-
{ // MT_REDFLAG
310, // doomednum
S_REDFLAG, // spawnstate
@@ -5987,6 +6035,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
+ { // MT_WALLSPIKE
+ 522, // doomednum
+ S_WALLSPIKE1, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_s3k64, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_WALLSPIKED1, // deathstate
+ S_WALLSPIKED2, // xdeathstate
+ sfx_mspogo, // deathsound
+ 2*TICRATE, // speed
+ 16*FRACUNIT, // radius
+ 14*FRACUNIT, // height
+ 0, // display offset
+ 4, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SCENERY|MF_NOCLIPHEIGHT|MF_PAPERCOLLISION, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_WALLSPIKEBASE
+ -1, // doomednum
+ S_WALLSPIKEBASE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 7*FRACUNIT, // radius
+ 14*FRACUNIT, // height
+ 0, // display offset
+ 4, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPTHING, // flags
+ S_NULL // raisestate
+ },
+
{ // MT_STARPOST
502, // doomednum
S_STARPOST_IDLE, // spawnstate
@@ -6447,7 +6549,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
},
{ // MT_MYSTERY_BOX
- 412, // doomednum
+ -1, //412, // doomednum
S_MYSTERY_BOX, // spawnstate
1, // spawnhealth
S_NULL, // seestate
@@ -7099,7 +7201,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_PITY_ICON1, // spawnstate
1, // spawnhealth
S_NULL, // seestate
- sfx_s3k3a, // seesound
+ sfx_shield, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
@@ -7450,7 +7552,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_SCORE1K_ICON1, // spawnstate
1, // spawnhealth
S_NULL, // seestate
- sfx_token, // seesound
+ sfx_chchng, // seesound
1000, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
@@ -7477,7 +7579,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_SCORE10K_ICON1, // spawnstate
1, // spawnhealth
S_NULL, // seestate
- sfx_token, // seesound
+ sfx_chchng, // seesound
10000, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
@@ -8039,6 +8141,276 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
+ { // MT_GFZTREE
+ 806, // doomednum
+ S_GFZTREE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 20*FRACUNIT, // radius
+ 128*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_SOLID|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_GFZBERRYTREE
+ 807, // doomednum
+ S_GFZBERRYTREE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 20*FRACUNIT, // radius
+ 128*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_SOLID|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_GFZCHERRYTREE
+ 808, // doomednum
+ S_GFZCHERRYTREE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 20*FRACUNIT, // radius
+ 128*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_SOLID|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_CHECKERTREE
+ 810, // doomednum
+ S_CHECKERTREE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 20*FRACUNIT, // radius
+ 200*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_CHECKERSUNSETTREE
+ 811, // doomednum
+ S_CHECKERSUNSETTREE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 20*FRACUNIT, // radius
+ 200*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_FHZTREE
+ 812, // doomednum
+ S_FHZTREE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 20*FRACUNIT, // radius
+ 200*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_FHZPINKTREE
+ 813, // doomednum
+ S_FHZPINKTREE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 20*FRACUNIT, // radius
+ 200*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_POLYGONTREE
+ 814, // doomednum
+ S_POLYGONTREE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 20*FRACUNIT, // radius
+ 200*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_BUSHTREE
+ 815, // doomednum
+ S_BUSHTREE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 20*FRACUNIT, // radius
+ 200*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_BUSHREDTREE
+ 816, // doomednum
+ S_BUSHREDTREE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 20*FRACUNIT, // radius
+ 200*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
{ // MT_THZFLOWER1
900, // doomednum
S_THZFLOWERA, // spawnstate
@@ -8147,6 +8519,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
+ { // MT_BIGGARGOYLE
+ 1009, // doomednum
+ S_BIGGARGOYLE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 12*FRACUNIT, // speed
+ 32*FRACUNIT, // radius
+ 80*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 1, // damage
+ sfx_statu2, // activesound
+ MF_SLIDEME|MF_SOLID|MF_PUSHABLE, // flags
+ S_NULL // raisestate
+ },
+
{ // MT_SEAWEED
1001, // doomednum
S_SEAWEED1, // spawnstate
@@ -8471,7 +8870,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
- { // MT_SWINGMACEPOINT
+ { // MT_CHAINMACEPOINT
1105, // doomednum
S_INVISIBLE, // spawnstate
1000, // spawnhealth
@@ -8498,7 +8897,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
- { // MT_HANGMACEPOINT
+ { // MT_SPRINGBALLPOINT
1106, // doomednum
S_INVISIBLE, // spawnstate
1000, // spawnhealth
@@ -8525,7 +8924,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
- { // MT_SPINMACEPOINT
+ { // MT_CHAINPOINT
1107, // doomednum
S_INVISIBLE, // spawnstate
1000, // spawnhealth
@@ -8545,7 +8944,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
128*FRACUNIT, // radius
1*FRACUNIT, // height
0, // display offset
- 200, // mass
+ 10000, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
@@ -8579,6 +8978,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
+ { // MT_FIREBARPOINT
+ 1109, // doomednum
+ S_INVISIBLE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 0, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 10*FRACUNIT, // speed
+ 128*FRACUNIT, // radius
+ 1*FRACUNIT, // height
+ 0, // display offset
+ 200, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_CUSTOMMACEPOINT
+ 1111, // doomednum
+ S_INVISIBLE, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 0, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 10*FRACUNIT, // speed
+ 128*FRACUNIT, // radius
+ 1*FRACUNIT, // height
+ 0, // display offset
+ 200, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
+ S_NULL // raisestate
+ },
+
{ // MT_SMALLMACECHAIN
-1, // doomednum
S_SMALLMACECHAIN, // spawnstate
@@ -8602,7 +9055,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
1, // damage
sfx_None, // activesound
- MF_NOGRAVITY|MF_SPECIAL|MF_NOCLIPHEIGHT, // flags
+ MF_SCENERY|MF_SPECIAL|MF_NOGRAVITY, // flags
S_NULL // raisestate
},
@@ -8629,7 +9082,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
1, // damage
sfx_None, // activesound
- MF_NOGRAVITY|MF_SPECIAL|MF_NOCLIPHEIGHT, // flags
+ MF_SCENERY|MF_SPECIAL|MF_NOGRAVITY, // flags
S_NULL // raisestate
},
@@ -8652,11 +9105,11 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
24*FRACUNIT, // speed
17*FRACUNIT, // radius
34*FRACUNIT, // height
- 0, // display offset
+ 1, // display offset
100, // mass
1, // damage
sfx_mswing, // activesound
- MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
+ MF_SCENERY|MF_PAIN|MF_NOGRAVITY, // flags
S_NULL // raisestate
},
@@ -8679,11 +9132,119 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
48*FRACUNIT, // speed
34*FRACUNIT, // radius
68*FRACUNIT, // height
- 0, // display offset
+ 1, // display offset
100, // mass
1, // damage
sfx_mswing, // activesound
- MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
+ MF_SCENERY|MF_PAIN|MF_NOGRAVITY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_YELLOWSPRINGBALL
+ -1, // doomednum
+ S_YELLOWSPRINGBALL, // spawnstate
+ 1000, // spawnhealth
+ S_YELLOWSPRINGBALL2, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_spring, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 24*FRACUNIT, // speed
+ 17*FRACUNIT, // radius
+ 34*FRACUNIT, // height
+ 1, // display offset
+ 20*FRACUNIT, // mass
+ 0, // damage
+ sfx_mswing, // activesound
+ MF_SCENERY|MF_SOLID|MF_SPRING|MF_NOGRAVITY, // flags
+ S_YELLOWSPRINGBALL2 // raisestate
+ },
+
+ { // MT_REDSPRINGBALL
+ -1, // doomednum
+ S_REDSPRINGBALL, // spawnstate
+ 1000, // spawnhealth
+ S_REDSPRINGBALL2, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_spring, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 24*FRACUNIT, // speed
+ 17*FRACUNIT, // radius
+ 34*FRACUNIT, // height
+ 1, // display offset
+ 32*FRACUNIT, // mass
+ 0, // damage
+ sfx_mswing, // activesound
+ MF_SCENERY|MF_SOLID|MF_SPRING|MF_NOGRAVITY, // flags
+ S_REDSPRINGBALL2 // raisestate
+ },
+
+ { // MT_SMALLFIREBAR
+ -1, // doomednum
+ S_SMALLFIREBAR1, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ MT_FLAMEPARTICLE, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 24*FRACUNIT, // speed
+ 17*FRACUNIT, // radius
+ 34*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 1, // damage
+ sfx_None, // activesound
+ MF_SCENERY|MF_PAIN|MF_FIRE|MF_NOGRAVITY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_BIGFIREBAR
+ -1, // doomednum
+ S_BIGFIREBAR1, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ MT_FLAMEPARTICLE, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 48*FRACUNIT, // speed
+ 34*FRACUNIT, // radius
+ 68*FRACUNIT, // height
+ 1, // display offset
+ 100, // mass
+ 1, // damage
+ sfx_None, // activesound
+ MF_SCENERY|MF_PAIN|MF_FIRE|MF_NOGRAVITY, // flags
S_NULL // raisestate
},
@@ -9515,7 +10076,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // deathsound
25*FRACUNIT, // speed
16*FRACUNIT, // radius
- 40*FRACUNIT, // height
+ 64*FRACUNIT, // height
0, // display offset
100, // mass
1, // damage
@@ -9524,6 +10085,168 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
+ { // MT_SNOWMANHAT
+ 1853, // doomednum
+ S_SNOWMANHAT, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 25*FRACUNIT, // speed
+ 16*FRACUNIT, // radius
+ 80*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 1, // damage
+ sfx_None, // activesound
+ MF_SLIDEME|MF_SOLID|MF_PUSHABLE, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_LAMPPOST1
+ 1854, // doomednum
+ S_LAMPPOST1, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 8*FRACUNIT, // radius
+ 120*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 1, // damage
+ sfx_None, // activesound
+ MF_SOLID, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_LAMPPOST2
+ 1855, // doomednum
+ S_LAMPPOST2, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 8*FRACUNIT, // radius
+ 120*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 1, // damage
+ sfx_None, // activesound
+ MF_SOLID, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_HANGSTAR
+ 1856, // doomednum
+ S_HANGSTAR, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 4*FRACUNIT, // radius
+ 80*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 1, // damage
+ sfx_None, // activesound
+ MF_NOBLOCKMAP|MF_NOCLIP|MF_SPAWNCEILING|MF_NOGRAVITY|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_XMASBERRYBUSH
+ 1857, // doomednum
+ S_XMASBERRYBUSH, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 16*FRACUNIT, // radius
+ 32*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
+ { // MT_XMASBUSH
+ 1858, // doomednum
+ S_XMASBUSH, // spawnstate
+ 1000, // spawnhealth
+ S_NULL, // seestate
+ sfx_None, // seesound
+ 8, // reactiontime
+ sfx_None, // attacksound
+ S_NULL, // painstate
+ 0, // painchance
+ sfx_None, // painsound
+ S_NULL, // meleestate
+ S_NULL, // missilestate
+ S_NULL, // deathstate
+ S_NULL, // xdeathstate
+ sfx_None, // deathsound
+ 0, // speed
+ 16*FRACUNIT, // radius
+ 32*FRACUNIT, // height
+ 0, // display offset
+ 100, // mass
+ 0, // damage
+ sfx_None, // activesound
+ MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
+ S_NULL // raisestate
+ },
+
// No, I did not do all of this by hand.
// I made a script to make all of these for me.
// Ha HA. ~Inuyasha
@@ -12457,7 +13180,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_RRNG1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
- sfx_thok, // seesound
+ sfx_wepfir, // seesound
0, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
@@ -12864,7 +13587,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_THROWNINFINITY1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
- sfx_thok, // seesound
+ sfx_wepfir, // seesound
0, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
@@ -12891,7 +13614,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_THROWNAUTOMATIC1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
- sfx_thok, // seesound
+ sfx_wepfir, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
@@ -12972,7 +13695,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_THROWNGRENADE1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
- sfx_thok, // seesound
+ sfx_wepfir, // seesound
8, // reactiontime
sfx_gbeep, // attacksound
S_NULL, // painstate
@@ -13759,7 +14482,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
- sfx_itemup, // painsound
+ sfx_s3k33, // painsound
S_RING, // meleestate
S_NULL, // missilestate
S_SPRK1, // deathstate
@@ -13778,9 +14501,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_NIGHTSSUPERLOOP
1707, // doomednum
- S_NIGHTSPOWERUP1, // spawnstate
+ S_NIGHTSSUPERLOOP, // spawnstate
1000, // spawnhealth
- S_NIGHTSPOWERUP2, // seestate
+ S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
@@ -13805,9 +14528,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_NIGHTSDRILLREFILL
1708, // doomednum
- S_NIGHTSPOWERUP3, // spawnstate
+ S_NIGHTSDRILLREFILL, // spawnstate
1000, // spawnhealth
- S_NIGHTSPOWERUP4, // seestate
+ S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
@@ -13832,9 +14555,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_NIGHTSHELPER
1709, // doomednum
- S_NIGHTSPOWERUP5, // spawnstate
+ S_NIGHTSHELPER, // spawnstate
1000, // spawnhealth
- S_NIGHTSPOWERUP6, // seestate
+ S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
@@ -13859,9 +14582,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_NIGHTSEXTRATIME
1711, // doomednum
- S_NIGHTSPOWERUP7, // spawnstate
+ S_NIGHTSEXTRATIME, // spawnstate
1000, // spawnhealth
- S_NIGHTSPOWERUP8, // seestate
+ S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
@@ -13886,9 +14609,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_NIGHTSLINKFREEZE
1712, // doomednum
- S_NIGHTSPOWERUP9, // spawnstate
+ S_NIGHTSLINKFREEZE, // spawnstate
1000, // spawnhealth
- S_NIGHTSPOWERUP10, // seestate
+ S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
diff --git a/src/info.h b/src/info.h
index 4b21e98ec..cd79b12a9 100644
--- a/src/info.h
+++ b/src/info.h
@@ -40,8 +40,6 @@ void A_Scream();
void A_BossDeath();
void A_CustomPower(); // Use this for a custom power
void A_GiveWeapon(); // Gives the player weapon(s)
-void A_JumpShield(); // Obtained Jump Shield
-void A_RingShield(); // Obtained Ring Shield
void A_RingBox(); // Obtained Ring Box Tails
void A_Invincibility(); // Obtained Invincibility Box
void A_SuperSneakers(); // Obtained Super Sneakers Box
@@ -52,13 +50,7 @@ void A_BubbleRise(); // Bubbles float to surface
void A_BubbleCheck(); // Don't draw if not underwater
void A_AwardScore();
void A_ExtraLife(); // Extra Life
-void A_BombShield(); // Obtained Bomb Shield
-void A_WaterShield(); // Obtained Water Shield
-void A_ForceShield(); // Obtained Force Shield
-void A_PityShield(); // Obtained Pity Shield. We're... sorry.
-void A_FlameShield(); // Obtained Flame Shield
-void A_BubbleShield(); // Obtained Bubble Shield
-void A_ThunderShield(); // Obtained Thunder Shield
+void A_GiveShield(); // Obtained Shield
void A_GravityBox();
void A_ScoreRise(); // Rise the score logo
void A_ParticleSpawn();
@@ -84,7 +76,6 @@ void A_DetonChase(); // Deton Chaser
void A_CapeChase(); // Fake little Super Sonic cape
void A_RotateSpikeBall(); // Spike ball rotation
void A_SlingAppear();
-void A_MaceRotate();
void A_UnidusBall();
void A_RockSpawn();
void A_SetFuse();
@@ -320,7 +311,6 @@ typedef enum sprite
// Collectible Items
SPR_RING,
SPR_TRNG, // Team Rings
- SPR_EMMY, // emerald test
SPR_TOKE, // Special Stage Token
SPR_RFLG, // Red CTF Flag
SPR_BFLG, // Blue CTF Flag
@@ -337,6 +327,8 @@ typedef enum sprite
SPR_SPIK, // Spike Ball
SPR_SFLM, // Spin fire
SPR_USPK, // Floor spike
+ SPR_WSPK, // Wall spike
+ SPR_WSPB, // Wall spike base
SPR_STPT, // Starpost
SPR_BMNE, // Big floating mine
@@ -387,6 +379,12 @@ typedef enum sprite
SPR_FWR4,
SPR_BUS1, // GFZ Bush w/ berries
SPR_BUS2, // GFZ Bush w/o berries
+ // Trees (both GFZ and misc)
+ SPR_TRE1, // GFZ
+ SPR_TRE2, // Checker
+ SPR_TRE3, // Frozen Hillside
+ SPR_TRE4, // Polygon
+ SPR_TRE5, // Bush tree
// Techno Hill Scenery
SPR_THZP, // THZ1 Flower
@@ -410,6 +408,10 @@ typedef enum sprite
SPR_BMCH, // Big Mace Chain
SPR_SMCE, // Small Mace
SPR_BMCE, // Big Mace
+ SPR_YSPB, // Yellow spring on a ball
+ SPR_RSPB, // Red spring on a ball
+ SPR_SFBR, // Small Firebar
+ SPR_BFBR, // Big Firebar
// Arid Canyon Scenery
SPR_BTBL, // Big tumbleweed
@@ -425,9 +427,11 @@ typedef enum sprite
// Egg Rock Scenery
// Christmas Scenery
- SPR_XMS1,
- SPR_XMS2,
- SPR_XMS3,
+ SPR_XMS1, // Christmas Pole
+ SPR_XMS2, // Candy Cane
+ SPR_XMS3, // Snowman
+ SPR_XMS4, // Lamppost
+ SPR_XMS5, // Hanging Star
// Botanic Serenity Scenery
SPR_BSZ1, // Tall flowers
@@ -1615,12 +1619,8 @@ typedef enum state
// Individual Team Rings
S_TEAMRING,
- // Special Stage Token
- S_EMMY,
-
// Special Stage Token
S_TOKEN,
- S_MOVINGTOKEN,
// CTF Flags
S_REDFLAG,
@@ -1771,6 +1771,17 @@ typedef enum state
S_SPIKED1,
S_SPIKED2,
+ // Wall spikes
+ S_WALLSPIKE1,
+ S_WALLSPIKE2,
+ S_WALLSPIKE3,
+ S_WALLSPIKE4,
+ S_WALLSPIKE5,
+ S_WALLSPIKE6,
+ S_WALLSPIKEBASE,
+ S_WALLSPIKED1,
+ S_WALLSPIKED2,
+
// Starpost
S_STARPOST_IDLE,
S_STARPOST_FLASH,
@@ -1959,6 +1970,7 @@ typedef enum state
S_DEMONFIRE5,
S_DEMONFIRE6,
+ // GFZ flowers
S_GFZFLOWERA,
S_GFZFLOWERB,
S_GFZFLOWERC,
@@ -1966,6 +1978,18 @@ typedef enum state
S_BERRYBUSH,
S_BUSH,
+ // Trees (both GFZ and misc)
+ S_GFZTREE,
+ S_GFZBERRYTREE,
+ S_GFZCHERRYTREE,
+ S_CHECKERTREE,
+ S_CHECKERSUNSETTREE,
+ S_FHZTREE, // Frozen Hillside
+ S_FHZPINKTREE,
+ S_POLYGONTREE,
+ S_BUSHTREE,
+ S_BUSHREDTREE,
+
// THZ Plant
S_THZFLOWERA,
S_THZFLOWERB,
@@ -1975,6 +1999,7 @@ typedef enum state
// Deep Sea Gargoyle
S_GARGOYLE,
+ S_BIGGARGOYLE,
// DSZ Seaweed
S_SEAWEED1,
@@ -2026,18 +2051,62 @@ typedef enum state
S_SLING1,
S_SLING2,
- // CEZ Small Mace Chain
+ // CEZ maces and chains
S_SMALLMACECHAIN,
-
- // CEZ Big Mace Chain
S_BIGMACECHAIN,
-
- // CEZ Small Mace
S_SMALLMACE,
-
- // CEZ Big Mace
S_BIGMACE,
+ // Yellow spring on a ball
+ S_YELLOWSPRINGBALL,
+ S_YELLOWSPRINGBALL2,
+ S_YELLOWSPRINGBALL3,
+ S_YELLOWSPRINGBALL4,
+ S_YELLOWSPRINGBALL5,
+
+ // Red spring on a ball
+ S_REDSPRINGBALL,
+ S_REDSPRINGBALL2,
+ S_REDSPRINGBALL3,
+ S_REDSPRINGBALL4,
+ S_REDSPRINGBALL5,
+
+ // Small Firebar
+ S_SMALLFIREBAR1,
+ S_SMALLFIREBAR2,
+ S_SMALLFIREBAR3,
+ S_SMALLFIREBAR4,
+ S_SMALLFIREBAR5,
+ S_SMALLFIREBAR6,
+ S_SMALLFIREBAR7,
+ S_SMALLFIREBAR8,
+ S_SMALLFIREBAR9,
+ S_SMALLFIREBAR10,
+ S_SMALLFIREBAR11,
+ S_SMALLFIREBAR12,
+ S_SMALLFIREBAR13,
+ S_SMALLFIREBAR14,
+ S_SMALLFIREBAR15,
+ S_SMALLFIREBAR16,
+
+ // Big Firebar
+ S_BIGFIREBAR1,
+ S_BIGFIREBAR2,
+ S_BIGFIREBAR3,
+ S_BIGFIREBAR4,
+ S_BIGFIREBAR5,
+ S_BIGFIREBAR6,
+ S_BIGFIREBAR7,
+ S_BIGFIREBAR8,
+ S_BIGFIREBAR9,
+ S_BIGFIREBAR10,
+ S_BIGFIREBAR11,
+ S_BIGFIREBAR12,
+ S_BIGFIREBAR13,
+ S_BIGFIREBAR14,
+ S_BIGFIREBAR15,
+ S_BIGFIREBAR16,
+
S_CEZFLOWER1,
// Big Tumbleweed
@@ -2133,7 +2202,14 @@ typedef enum state
// Xmas-specific stuff
S_XMASPOLE,
S_CANDYCANE,
- S_SNOWMAN,
+ S_SNOWMAN, // normal
+ S_SNOWMANHAT, // with hat + scarf
+ S_LAMPPOST1, // normal
+ S_LAMPPOST2, // with snow
+ S_HANGSTAR,
+ // Xmas GFZ bushes
+ S_XMASBERRYBUSH,
+ S_XMASBUSH,
// Botanic Serenity's loads of scenery states
S_BSZTALLFLOWER_RED,
@@ -2325,10 +2401,6 @@ typedef enum state
S_PITY4,
S_PITY5,
S_PITY6,
- S_PITY7,
- S_PITY8,
- S_PITY9,
- S_PITY10,
S_FIRS1,
S_FIRS2,
@@ -3008,16 +3080,11 @@ typedef enum state
S_NIGHTSWING_XMAS,
// NiGHTS Paraloop Powerups
- S_NIGHTSPOWERUP1,
- S_NIGHTSPOWERUP2,
- S_NIGHTSPOWERUP3,
- S_NIGHTSPOWERUP4,
- S_NIGHTSPOWERUP5,
- S_NIGHTSPOWERUP6,
- S_NIGHTSPOWERUP7,
- S_NIGHTSPOWERUP8,
- S_NIGHTSPOWERUP9,
- S_NIGHTSPOWERUP10,
+ S_NIGHTSSUPERLOOP,
+ S_NIGHTSDRILLREFILL,
+ S_NIGHTSHELPER,
+ S_NIGHTSEXTRATIME,
+ S_NIGHTSLINKFREEZE,
S_EGGCAPSULE,
// Orbiting Chaos Emeralds
@@ -3233,8 +3300,7 @@ typedef enum mobj_type
MT_BLUEBALL, // Blue sphere replacement for special stages
MT_REDTEAMRING, //Rings collectable by red team.
MT_BLUETEAMRING, //Rings collectable by blue team.
- MT_EMMY, // emerald token for special stage
- MT_TOKEN, // Special Stage Token (uncollectible part)
+ MT_TOKEN, // Special Stage token for special stage
MT_REDFLAG, // Red CTF Flag
MT_BLUEFLAG, // Blue CTF Flag
MT_EMBLEM,
@@ -3268,6 +3334,8 @@ typedef enum mobj_type
MT_SPECIALSPIKEBALL,
MT_SPINFIRE,
MT_SPIKE,
+ MT_WALLSPIKE,
+ MT_WALLSPIKEBASE,
MT_STARPOST,
MT_BIGMINE,
MT_BIGAIRMINE,
@@ -3358,6 +3426,17 @@ typedef enum mobj_type
MT_GFZFLOWER3,
MT_BERRYBUSH,
MT_BUSH,
+ // Trees (both GFZ and misc)
+ MT_GFZTREE,
+ MT_GFZBERRYTREE,
+ MT_GFZCHERRYTREE,
+ MT_CHECKERTREE,
+ MT_CHECKERSUNSETTREE,
+ MT_FHZTREE, // Frozen Hillside
+ MT_FHZPINKTREE,
+ MT_POLYGONTREE,
+ MT_BUSHTREE,
+ MT_BUSHREDTREE,
// Techno Hill Scenery
MT_THZFLOWER1,
@@ -3366,6 +3445,7 @@ typedef enum mobj_type
// Deep Sea Scenery
MT_GARGOYLE, // Deep Sea Gargoyle
+ MT_BIGGARGOYLE, // Deep Sea Gargoyle (Big)
MT_SEAWEED, // DSZ Seaweed
MT_WATERDRIP, // Dripping Water source
MT_WATERDROP, // Water drop from dripping water
@@ -3380,14 +3460,20 @@ typedef enum mobj_type
MT_FLAMEPARTICLE,
MT_EGGSTATUE, // Eggman Statue
MT_MACEPOINT, // Mace rotation point
- MT_SWINGMACEPOINT, // Mace swinging point
- MT_HANGMACEPOINT, // Hangable mace chain
- MT_SPINMACEPOINT, // Spin/Controllable mace chain
+ MT_CHAINMACEPOINT, // Combination of chains and maces point
+ MT_SPRINGBALLPOINT, // Spring ball point
+ MT_CHAINPOINT, // Mace chain
MT_HIDDEN_SLING, // Spin mace chain (activatable)
+ MT_FIREBARPOINT, // Firebar
+ MT_CUSTOMMACEPOINT, // Custom mace
MT_SMALLMACECHAIN, // Small Mace Chain
MT_BIGMACECHAIN, // Big Mace Chain
MT_SMALLMACE, // Small Mace
MT_BIGMACE, // Big Mace
+ MT_YELLOWSPRINGBALL, // Yellow spring on a ball
+ MT_REDSPRINGBALL, // Red spring on a ball
+ MT_SMALLFIREBAR, // Small Firebar
+ MT_BIGFIREBAR, // Big Firebar
MT_CEZFLOWER,
// Arid Canyon Scenery
@@ -3434,7 +3520,14 @@ typedef enum mobj_type
// Christmas Scenery
MT_XMASPOLE,
MT_CANDYCANE,
- MT_SNOWMAN,
+ MT_SNOWMAN, // normal
+ MT_SNOWMANHAT, // with hat + scarf
+ MT_LAMPPOST1, // normal
+ MT_LAMPPOST2, // with snow
+ MT_HANGSTAR,
+ // Xmas GFZ bushes
+ MT_XMASBERRYBUSH,
+ MT_XMASBUSH,
// Botanic Serenity scenery
MT_BSZTALLFLOWER_RED,
diff --git a/src/lua_baselib.c b/src/lua_baselib.c
index 71f6a7e65..be1455415 100644
--- a/src/lua_baselib.c
+++ b/src/lua_baselib.c
@@ -462,7 +462,7 @@ static int lib_pSpawnLockOn(lua_State *L)
return LUA_ErrInvalid(L, "mobj_t");
if (!player)
return LUA_ErrInvalid(L, "player_t");
- if (player == &players[consoleplayer] || player == &players[secondarydisplayplayer] || player == &players[displayplayer]) // Only display it on your own view.
+ if (P_IsLocalPlayer(player)) // Only display it on your own view.
{
mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker
visual->target = lockon;
@@ -978,6 +978,19 @@ static int lib_pGivePlayerLives(lua_State *L)
return 0;
}
+static int lib_pGiveCoopLives(lua_State *L)
+{
+ player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
+ INT32 numlives = (INT32)luaL_checkinteger(L, 2);
+ boolean sound = (boolean)lua_opttrueboolean(L, 3);
+ NOHUD
+ INLEVEL
+ if (!player)
+ return LUA_ErrInvalid(L, "player_t");
+ P_GiveCoopLives(player, numlives, sound);
+ return 0;
+}
+
static int lib_pResetScore(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
@@ -1183,6 +1196,18 @@ static int lib_pTelekinesis(lua_State *L)
return 0;
}
+static int lib_pSwitchShield(lua_State *L)
+{
+ player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
+ UINT16 shield = luaL_checkinteger(L, 2);
+ NOHUD
+ INLEVEL
+ if (!player)
+ return LUA_ErrInvalid(L, "player_t");
+ P_SwitchShield(player, shield);
+ return 0;
+}
+
// P_MAP
///////////
@@ -2181,6 +2206,31 @@ static int lib_sSoundPlaying(lua_State *L)
return 1;
}
+// This doesn't really exist, but we're providing it as a handy netgame-safe wrapper for stuff that should be locally handled.
+
+static int lib_sStartMusicCaption(lua_State *L)
+{
+ player_t *player = NULL;
+ const char *caption = luaL_checkstring(L, 1);
+ UINT16 lifespan = (UINT16)luaL_checkinteger(L, 2);
+ //HUDSAFE
+ INLEVEL
+
+ if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
+ {
+ player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
+ if (!player)
+ return LUA_ErrInvalid(L, "player_t");
+ }
+
+ if (lifespan && (!player || P_IsLocalPlayer(player)))
+ {
+ strlcpy(S_sfx[sfx_None].caption, caption, sizeof(S_sfx[sfx_None].caption));
+ S_StartCaption(sfx_None, -1, lifespan);
+ }
+ return 0;
+}
+
// G_GAME
////////////
@@ -2403,6 +2453,7 @@ static luaL_Reg lib[] = {
{"P_SpawnGhostMobj",lib_pSpawnGhostMobj},
{"P_GivePlayerRings",lib_pGivePlayerRings},
{"P_GivePlayerLives",lib_pGivePlayerLives},
+ {"P_GiveCoopLives",lib_pGiveCoopLives},
{"P_ResetScore",lib_pResetScore},
{"P_DoJumpShield",lib_pDoJumpShield},
{"P_DoBubbleBounce",lib_pDoBubbleBounce},
@@ -2420,6 +2471,7 @@ static luaL_Reg lib[] = {
{"P_SpawnThokMobj",lib_pSpawnThokMobj},
{"P_SpawnSpinMobj",lib_pSpawnSpinMobj},
{"P_Telekinesis",lib_pTelekinesis},
+ {"P_SwitchShield",lib_pSwitchShield},
// p_map
{"P_CheckPosition",lib_pCheckPosition},
@@ -2493,6 +2545,7 @@ static luaL_Reg lib[] = {
{"S_OriginPlaying",lib_sOriginPlaying},
{"S_IdPlaying",lib_sIdPlaying},
{"S_SoundPlaying",lib_sSoundPlaying},
+ {"S_StartMusicCaption", lib_sStartMusicCaption},
// g_game
{"G_BuildMapName",lib_gBuildMapName},
diff --git a/src/lua_blockmaplib.c b/src/lua_blockmaplib.c
index d90ef4d67..ccd90f993 100644
--- a/src/lua_blockmaplib.c
+++ b/src/lua_blockmaplib.c
@@ -266,4 +266,4 @@ int LUA_BlockmapLib(lua_State *L)
return 0;
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c
index 322fecb64..559c576f0 100644
--- a/src/lua_consolelib.c
+++ b/src/lua_consolelib.c
@@ -22,8 +22,13 @@
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
+// for functions not allowed in hud.add hooks
#define NOHUD if (hud_running)\
return luaL_error(L, "HUD rendering code should not call this function!");
+// for functions not allowed in hooks or coroutines (supercedes above)
+#define NOHOOK if (!lua_lumploading)\
+ return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
+// for functions only allowed within a level
#define INLEVEL if (gamestate != GS_LEVEL)\
return luaL_error(L, "This function can only be used in a level!");
@@ -184,7 +189,7 @@ static int lib_comAddCommand(lua_State *L)
strlwr(name);
luaL_checktype(L, 2, LUA_TFUNCTION);
- NOHUD
+ NOHOOK
if (lua_gettop(L) >= 3)
{ // For the third argument, only take a boolean or a number.
lua_settop(L, 3);
@@ -296,7 +301,7 @@ static int lib_cvRegisterVar(lua_State *L)
consvar_t *cvar;
luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 1); // Clear out all other possible arguments, leaving only the first one.
- NOHUD
+ NOHOOK
cvar = lua_newuserdata(L, sizeof(consvar_t));
luaL_getmetatable(L, META_CVAR);
lua_setmetatable(L, -2);
@@ -394,12 +399,21 @@ static int lib_cvRegisterVar(lua_State *L)
// stack: cvar table, cvar userdata
lua_getfield(L, LUA_REGISTRYINDEX, "CV_Vars");
I_Assert(lua_istable(L, 3));
+
+ lua_getfield(L, 3, cvar->name);
+ if (lua_type(L, -1) != LUA_TNIL)
+ return luaL_error(L, M_GetText("Variable %s is already defined\n"), cvar->name);
+ lua_pop(L, 1);
+
lua_pushvalue(L, 2);
lua_setfield(L, 3, cvar->name);
lua_pop(L, 1);
// actually time to register it to the console now! Finally!
+ cvar->flags |= CV_MODIFIED;
CV_RegisterVar(cvar);
+ if (cvar->flags & CV_MODIFIED)
+ return luaL_error(L, "failed to register cvar (probable conflict with internal variable/command names)");
// return cvar userdata
return 1;
diff --git a/src/lua_hook.h b/src/lua_hook.h
index 88867db2b..fe5706f56 100644
--- a/src/lua_hook.h
+++ b/src/lua_hook.h
@@ -46,6 +46,7 @@ enum hook {
hook_ShieldSpawn,
hook_ShieldSpecial,
hook_MobjMoveBlocked,
+ hook_MapThingSpawn,
hook_MAX // last hook
};
@@ -83,5 +84,6 @@ boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8
#define LUAh_ShieldSpawn(player) LUAh_PlayerHook(player, hook_ShieldSpawn) // Hook for P_SpawnShieldOrb
#define LUAh_ShieldSpecial(player) LUAh_PlayerHook(player, hook_ShieldSpecial) // Hook for shield abilities
#define LUAh_MobjMoveBlocked(mo) LUAh_MobjHook(mo, hook_MobjMoveBlocked) // Hook for P_XYMovement (when movement is blocked)
+boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing); // Hook for P_SpawnMapThing by mobj type
#endif
diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index dadc1861a..3dd3f932f 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -57,6 +57,7 @@ const char *const hookNames[hook_MAX+1] = {
"ShieldSpawn",
"ShieldSpecial",
"MobjMoveBlocked",
+ "MapThingSpawn",
NULL
};
@@ -108,8 +109,8 @@ static int lib_addHook(lua_State *L)
luaL_checktype(L, 1, LUA_TFUNCTION);
- if (hud_running)
- return luaL_error(L, "HUD rendering code should not call this function!");
+ if (!lua_lumploading)
+ return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
switch(hook.type)
{
@@ -128,6 +129,7 @@ static int lib_addHook(lua_State *L)
case hook_MobjRemoved:
case hook_HurtMsg:
case hook_MobjMoveBlocked:
+ case hook_MapThingSpawn:
hook.s.mt = MT_NULL;
if (lua_isnumber(L, 2))
hook.s.mt = lua_tonumber(L, 2);
@@ -187,6 +189,7 @@ static int lib_addHook(lua_State *L)
case hook_BossDeath:
case hook_MobjRemoved:
case hook_MobjMoveBlocked:
+ case hook_MapThingSpawn:
lastp = &mobjhooks[hook.s.mt];
break;
case hook_JumpSpecial:
@@ -1073,4 +1076,66 @@ void LUAh_NetArchiveHook(lua_CFunction archFunc)
// stack: tables
}
+boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing)
+{
+ hook_p hookp;
+ boolean hooked = false;
+ if (!gL || !(hooksAvailable[hook_MapThingSpawn/8] & (1<<(hook_MapThingSpawn%8))))
+ return false;
+
+ lua_settop(gL, 0);
+
+ // Look for all generic mobj map thing spawn hooks
+ for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next)
+ if (hookp->type == hook_MapThingSpawn)
+ {
+ if (lua_gettop(gL) == 0)
+ {
+ LUA_PushUserdata(gL, mo, META_MOBJ);
+ LUA_PushUserdata(gL, mthing, META_MAPTHING);
+ }
+ lua_pushfstring(gL, FMT_HOOKID, hookp->id);
+ lua_gettable(gL, LUA_REGISTRYINDEX);
+ lua_pushvalue(gL, -3);
+ lua_pushvalue(gL, -3);
+ if (lua_pcall(gL, 2, 1, 0)) {
+ if (!hookp->error || cv_debug & DBG_LUA)
+ CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
+ lua_pop(gL, 1);
+ hookp->error = true;
+ continue;
+ }
+ if (lua_toboolean(gL, -1))
+ hooked = true;
+ lua_pop(gL, 1);
+ }
+
+ for (hookp = mobjhooks[mo->type]; hookp; hookp = hookp->next)
+ if (hookp->type == hook_MapThingSpawn)
+ {
+ if (lua_gettop(gL) == 0)
+ {
+ LUA_PushUserdata(gL, mo, META_MOBJ);
+ LUA_PushUserdata(gL, mthing, META_MAPTHING);
+ }
+ lua_pushfstring(gL, FMT_HOOKID, hookp->id);
+ lua_gettable(gL, LUA_REGISTRYINDEX);
+ lua_pushvalue(gL, -3);
+ lua_pushvalue(gL, -3);
+ if (lua_pcall(gL, 2, 1, 0)) {
+ if (!hookp->error || cv_debug & DBG_LUA)
+ CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
+ lua_pop(gL, 1);
+ hookp->error = true;
+ continue;
+ }
+ if (lua_toboolean(gL, -1))
+ hooked = true;
+ lua_pop(gL, 1);
+ }
+
+ lua_settop(gL, 0);
+ return hooked;
+}
+
#endif
diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c
index 5b3cd46ce..29e4970c1 100644
--- a/src/lua_hudlib.c
+++ b/src/lua_hudlib.c
@@ -612,6 +612,9 @@ static int lib_hudadd(lua_State *L)
luaL_checktype(L, 1, LUA_TFUNCTION);
field = luaL_checkoption(L, 2, "game", hudhook_opt);
+ if (!lua_lumploading)
+ return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
+
lua_getfield(L, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(L, -1));
lua_rawgeti(L, -1, field+2); // HUD[2+]
diff --git a/src/lua_infolib.c b/src/lua_infolib.c
index 4f7fdaa26..9361abe94 100644
--- a/src/lua_infolib.c
+++ b/src/lua_infolib.c
@@ -31,6 +31,7 @@ enum sfxinfo_read {
sfxinfor_singular,
sfxinfor_priority,
sfxinfor_flags, // "pitch"
+ sfxinfor_caption,
sfxinfor_skinsound
};
const char *const sfxinfo_ropt[] = {
@@ -38,18 +39,21 @@ const char *const sfxinfo_ropt[] = {
"singular",
"priority",
"flags",
+ "caption",
"skinsound",
NULL};
enum sfxinfo_write {
sfxinfow_singular = 0,
sfxinfow_priority,
- sfxinfow_flags // "pitch"
+ sfxinfow_flags, // "pitch"
+ sfxinfow_caption
};
const char *const sfxinfo_wopt[] = {
"singular",
"priority",
"flags",
+ "caption",
NULL};
//
@@ -769,8 +773,8 @@ static int lib_getSfxInfo(lua_State *L)
lua_remove(L, 1);
i = luaL_checkinteger(L, 1);
- if (i >= NUMSFX)
- return luaL_error(L, "sfxinfo[] index %d out of range (0 - %d)", i, NUMSFX-1);
+ if (i == 0 || i >= NUMSFX)
+ return luaL_error(L, "sfxinfo[] index %d out of range (1 - %d)", i, NUMSFX-1);
LUA_PushUserdata(L, &S_sfx[i], META_SFXINFO);
return 1;
}
@@ -783,9 +787,9 @@ static int lib_setSfxInfo(lua_State *L)
lua_remove(L, 1);
{
UINT32 i = luaL_checkinteger(L, 1);
- if (i >= NUMSFX)
- return luaL_error(L, "sfxinfo[] index %d out of range (0 - %d)", i, NUMSFX-1);
- info = &S_sfx[i]; // get the mobjinfo to assign to.
+ if (i == 0 || i >= NUMSFX)
+ return luaL_error(L, "sfxinfo[] index %d out of range (1 - %d)", i, NUMSFX-1);
+ info = &S_sfx[i]; // get the sfxinfo to assign to.
}
luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table.
lua_remove(L, 1); // pop mobjtype num, don't need it any more.
@@ -814,6 +818,9 @@ static int lib_setSfxInfo(lua_State *L)
case sfxinfow_flags:
info->pitch = (INT32)luaL_checkinteger(L, 3);
break;
+ case sfxinfow_caption:
+ strlcpy(info->caption, luaL_checkstring(L, 3), sizeof(info->caption));
+ break;
default:
break;
}
@@ -851,11 +858,14 @@ static int sfxinfo_get(lua_State *L)
case sfxinfor_flags:
lua_pushinteger(L, sfx->pitch);
return 1;
+ case sfxinfor_caption:
+ lua_pushstring(L, sfx->caption);
+ return 1;
case sfxinfor_skinsound:
lua_pushinteger(L, sfx->skinsound);
return 1;
default:
- return luaL_error(L, "impossible error");
+ return luaL_error(L, "Field does not exist in sfxinfo_t");
}
return 0;
}
@@ -886,8 +896,11 @@ static int sfxinfo_set(lua_State *L)
case sfxinfow_flags:
sfx->pitch = luaL_checkinteger(L, 1);
break;
+ case sfxinfow_caption:
+ strlcpy(sfx->caption, luaL_checkstring(L, 1), sizeof(sfx->caption));
+ break;
default:
- return luaL_error(L, "impossible error");
+ return luaL_error(L, "Field does not exist in sfxinfo_t");
}
return 0;
}
diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c
index 2fcccab66..d384b75d1 100644
--- a/src/lua_mobjlib.c
+++ b/src/lua_mobjlib.c
@@ -417,7 +417,7 @@ static int mobj_set(lua_State *L)
mo->frame = (UINT32)luaL_checkinteger(L, 3);
break;
case mobj_sprite2:
- mo->sprite2 = P_GetMobjSprite2(mo, (UINT8)luaL_checkinteger(L, 3));
+ mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), (UINT8)luaL_checkinteger(L, 3), mo->player);
break;
case mobj_anim_duration:
mo->anim_duration = (UINT16)luaL_checkinteger(L, 3);
diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c
index 19ede443b..7c55012d2 100644
--- a/src/lua_playerlib.c
+++ b/src/lua_playerlib.c
@@ -322,6 +322,8 @@ static int player_get(lua_State *L)
lua_pushangle(L, plr->awayviewaiming);
else if (fastcmp(field,"spectator"))
lua_pushboolean(L, plr->spectator);
+ else if (fastcmp(field,"outofcoop"))
+ lua_pushboolean(L, plr->outofcoop);
else if (fastcmp(field,"bot"))
lua_pushinteger(L, plr->bot);
else if (fastcmp(field,"jointime"))
@@ -601,6 +603,8 @@ static int player_set(lua_State *L)
plr->awayviewaiming = luaL_checkangle(L, 3);
else if (fastcmp(field,"spectator"))
plr->spectator = lua_toboolean(L, 3);
+ else if (fastcmp(field,"outofcoop"))
+ plr->outofcoop = lua_toboolean(L, 3);
else if (fastcmp(field,"bot"))
return NOSET;
else if (fastcmp(field,"jointime"))
diff --git a/src/lua_script.c b/src/lua_script.c
index d30790be1..994f81a40 100644
--- a/src/lua_script.c
+++ b/src/lua_script.c
@@ -161,6 +161,11 @@ void LUA_ClearExtVars(void)
}
#endif
+// Use this variable to prevent certain functions from running
+// if they were not called on lump load
+// (i.e. they were called in hooks or coroutines etc)
+boolean lua_lumploading = false;
+
// Load a script from a MYFILE
static inline void LUA_LoadFile(MYFILE *f, char *name)
{
@@ -198,7 +203,9 @@ void LUA_LoadLump(UINT16 wad, UINT16 lump)
name[strlen(wadfiles[wad]->filename)+9] = '\0';
}
- LUA_LoadFile(&f, name);
+ lua_lumploading = true; // turn on loading flag
+ LUA_LoadFile(&f, name); // actually load file!
+ lua_lumploading = false; // turn off again
free(name);
Z_Free(f.data);
@@ -596,14 +603,14 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
{
mobjinfo_t *info = *((mobjinfo_t **)lua_touserdata(gL, myindex));
WRITEUINT8(save_p, ARCH_MOBJINFO);
- WRITEUINT8(save_p, info - mobjinfo);
+ WRITEUINT16(save_p, info - mobjinfo);
break;
}
case ARCH_STATE:
{
state_t *state = *((state_t **)lua_touserdata(gL, myindex));
WRITEUINT8(save_p, ARCH_STATE);
- WRITEUINT8(save_p, state - states);
+ WRITEUINT16(save_p, state - states);
break;
}
case ARCH_MOBJ:
diff --git a/src/lua_script.h b/src/lua_script.h
index d143ed879..51f1eaeaa 100644
--- a/src/lua_script.h
+++ b/src/lua_script.h
@@ -38,6 +38,8 @@
void LUA_ClearExtVars(void);
#endif
+extern boolean lua_lumploading; // is LUA_LoadLump being called?
+
void LUA_LoadLump(UINT16 wad, UINT16 lump);
#ifdef LUA_ALLOW_BYTECODE
void LUA_DumpFile(const char *filename);
diff --git a/src/lua_thinkerlib.c b/src/lua_thinkerlib.c
index b8cf1baec..a661aaf04 100644
--- a/src/lua_thinkerlib.c
+++ b/src/lua_thinkerlib.c
@@ -16,89 +16,127 @@
#include "lua_script.h"
#include "lua_libs.h"
+#define META_ITERATIONSTATE "iteration state"
+
static const char *const iter_opt[] = {
"all",
"mobj",
NULL};
+static const actionf_p1 iter_funcs[] = {
+ NULL,
+ (actionf_p1)P_MobjThinker
+};
+
+struct iterationState {
+ actionf_p1 filter;
+ int next;
+};
+
+static int iterationState_gc(lua_State *L)
+{
+ struct iterationState *it = luaL_checkudata(L, -1, META_ITERATIONSTATE);
+ if (it->next != LUA_REFNIL)
+ {
+ luaL_unref(L, LUA_REGISTRYINDEX, it->next);
+ it->next = LUA_REFNIL;
+ }
+ return 0;
+}
+
+#define push_thinker(th) {\
+ if ((th)->function.acp1 == (actionf_p1)P_MobjThinker) \
+ LUA_PushUserdata(L, (th), META_MOBJ); \
+ else \
+ lua_pushlightuserdata(L, (th)); \
+}
+
static int lib_iterateThinkers(lua_State *L)
{
- int state = luaL_checkoption(L, 1, "mobj", iter_opt);
-
- thinker_t *th = NULL;
- actionf_p1 searchFunc;
- const char *searchMeta;
+ thinker_t *th = NULL, *next = NULL;
+ struct iterationState *it;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
- lua_settop(L, 2);
- lua_remove(L, 1); // remove state now.
+ it = luaL_checkudata(L, 1, META_ITERATIONSTATE);
- switch(state)
+ lua_settop(L, 2);
+
+ if (lua_isnil(L, 2))
+ th = &thinkercap;
+ else if (lua_isuserdata(L, 2))
{
- case 0:
- searchFunc = NULL;
- searchMeta = NULL;
- break;
- case 1:
- default:
- searchFunc = (actionf_p1)P_MobjThinker;
- searchMeta = META_MOBJ;
- break;
+ if (lua_islightuserdata(L, 2))
+ th = lua_touserdata(L, 2);
+ else
+ {
+ th = *(thinker_t **)lua_touserdata(L, -1);
+ if (!th)
+ {
+ if (it->next == LUA_REFNIL)
+ return 0;
+
+ lua_rawgeti(L, LUA_REGISTRYINDEX, it->next);
+ if (lua_islightuserdata(L, -1))
+ next = lua_touserdata(L, -1);
+ else
+ next = *(thinker_t **)lua_touserdata(L, -1);
+ }
+ }
}
- if (!lua_isnil(L, 1)) {
- if (lua_islightuserdata(L, 1))
- th = (thinker_t *)lua_touserdata(L, 1);
- else if (searchMeta)
- th = *((thinker_t **)luaL_checkudata(L, 1, searchMeta));
- else
- th = *((thinker_t **)lua_touserdata(L, 1));
- } else
- th = &thinkercap;
+ luaL_unref(L, LUA_REGISTRYINDEX, it->next);
+ it->next = LUA_REFNIL;
- if (!th) // something got our userdata invalidated!
- return 0;
+ if (th && !next)
+ next = th->next;
+ if (!next)
+ return luaL_error(L, "next thinker invalidated during iteration");
- if (searchFunc == NULL)
- {
- if ((th = th->next) != &thinkercap)
+ for (; next != &thinkercap; next = next->next)
+ if (!it->filter || next->function.acp1 == it->filter)
{
- if (th->function.acp1 == (actionf_p1)P_MobjThinker)
- LUA_PushUserdata(L, th, META_MOBJ);
- else
- lua_pushlightuserdata(L, th);
+ push_thinker(next);
+ if (next->next != &thinkercap)
+ {
+ push_thinker(next->next);
+ it->next = luaL_ref(L, LUA_REGISTRYINDEX);
+ }
return 1;
}
- return 0;
- }
-
- for (th = th->next; th != &thinkercap; th = th->next)
- {
- if (th->function.acp1 != searchFunc)
- continue;
-
- LUA_PushUserdata(L, th, searchMeta);
- return 1;
- }
return 0;
}
static int lib_startIterate(lua_State *L)
{
+ struct iterationState *it;
+
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
- luaL_checkoption(L, 1, iter_opt[0], iter_opt);
- lua_pushcfunction(L, lib_iterateThinkers);
- lua_pushvalue(L, 1);
+
+ lua_pushvalue(L, lua_upvalueindex(1));
+ it = lua_newuserdata(L, sizeof(struct iterationState));
+ luaL_getmetatable(L, META_ITERATIONSTATE);
+ lua_setmetatable(L, -2);
+
+ it->filter = iter_funcs[luaL_checkoption(L, 1, "mobj", iter_opt)];
+ it->next = LUA_REFNIL;
return 2;
}
+#undef push_thinker
+
int LUA_ThinkerLib(lua_State *L)
{
+ luaL_newmetatable(L, META_ITERATIONSTATE);
+ lua_pushcfunction(L, iterationState_gc);
+ lua_setfield(L, -2, "__gc");
+ lua_pop(L, 1);
+
lua_createtable(L, 0, 1);
- lua_pushcfunction(L, lib_startIterate);
+ lua_pushcfunction(L, lib_iterateThinkers);
+ lua_pushcclosure(L, lib_startIterate, 1);
lua_setfield(L, -2, "iterate");
lua_setglobal(L, "thinkers");
return 0;
diff --git a/src/m_anigif.c b/src/m_anigif.c
index 2540665ad..6ae112ea8 100644
--- a/src/m_anigif.c
+++ b/src/m_anigif.c
@@ -18,6 +18,7 @@
#include "z_zone.h"
#include "v_video.h"
#include "i_video.h"
+#include "m_misc.h"
// GIFs are always little-endian
#include "byteptr.h"
@@ -396,7 +397,6 @@ static void GIF_headwrite(void)
{
UINT8 *gifhead = Z_Malloc(800, PU_STATIC, NULL);
UINT8 *p = gifhead;
- RGBA_t *c;
INT32 i;
UINT16 rwidth, rheight;
@@ -427,12 +427,17 @@ static void GIF_headwrite(void)
WRITEUINT8(p, 0x00);
// write color table
- for (i = 0; i < 256; ++i)
{
- c = &pLocalPalette[i];
- WRITEUINT8(p, c->s.red);
- WRITEUINT8(p, c->s.green);
- WRITEUINT8(p, c->s.blue);
+ RGBA_t *pal = ((cv_screenshot_colorprofile.value)
+ ? pLocalPalette
+ : pMasterPalette);
+
+ for (i = 0; i < 256; i++)
+ {
+ WRITEUINT8(p, pal[i].s.red);
+ WRITEUINT8(p, pal[i].s.green);
+ WRITEUINT8(p, pal[i].s.blue);
+ }
}
// write extension block
diff --git a/src/m_cheat.c b/src/m_cheat.c
index 8eb9551a8..f0472b11a 100644
--- a/src/m_cheat.c
+++ b/src/m_cheat.c
@@ -968,7 +968,7 @@ void OP_NightsObjectplace(player_t *player)
if (player->pflags & PF_ATTACKDOWN)
{
// Are ANY objectplace buttons pressed? If no, remove flag.
- if (!(cmd->buttons & (BT_ATTACK|BT_TOSSFLAG|BT_USE|BT_CAMRIGHT|BT_CAMLEFT)))
+ if (!(cmd->buttons & (BT_ATTACK|BT_TOSSFLAG|BT_USE|BT_WEAPONNEXT|BT_WEAPONPREV)))
player->pflags &= ~PF_ATTACKDOWN;
// Do nothing.
@@ -1019,7 +1019,7 @@ void OP_NightsObjectplace(player_t *player)
}
// This places a ring!
- if (cmd->buttons & BT_CAMRIGHT)
+ if (cmd->buttons & BT_WEAPONNEXT)
{
player->pflags |= PF_ATTACKDOWN;
if (!OP_HeightOkay(player, false))
@@ -1030,7 +1030,7 @@ void OP_NightsObjectplace(player_t *player)
}
// This places a wing item!
- if (cmd->buttons & BT_CAMLEFT)
+ if (cmd->buttons & BT_WEAPONPREV)
{
player->pflags |= PF_ATTACKDOWN;
if (!OP_HeightOkay(player, false))
diff --git a/src/m_cond.c b/src/m_cond.c
index 7f977c15d..9339c4989 100644
--- a/src/m_cond.c
+++ b/src/m_cond.c
@@ -499,63 +499,63 @@ emblem_t emblemlocations[MAXEMBLEMS] =
// FLORAL FIELD
// ---
{0, 5394, -996, 160, 50, 'N', SKINCOLOR_RUST, 0, "", 0},
- {ET_NGRADE, 0,0,0, 50, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0},
+ {ET_NGRADE, 0,0,0, 50, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0},
{ET_NTIME, 0,0,0, 50, 'T', SKINCOLOR_GREY, 40*TICRATE, "", 0},
// TOXIC PLATEAU
// ---
{0, 780, -1664, 32, 51, 'N', SKINCOLOR_RUST, 0, "", 0},
- {ET_NGRADE, 0,0,0, 51, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0},
+ {ET_NGRADE, 0,0,0, 51, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0},
{ET_NTIME, 0,0,0, 51, 'T', SKINCOLOR_GREY, 50*TICRATE, "", 0},
// FLOODED COVE
// ---
{0, 1824, -1888, 2448, 52, 'N', SKINCOLOR_RUST, 0, "", 0},
- {ET_NGRADE, 0,0,0, 52, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0},
+ {ET_NGRADE, 0,0,0, 52, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0},
{ET_NTIME, 0,0,0, 52, 'T', SKINCOLOR_GREY, 90*TICRATE, "", 0},
// CAVERN FORTRESS
// ---
{0, -3089, -431, 1328, 53, 'N', SKINCOLOR_RUST, 0, "", 0},
- {ET_NGRADE, 0,0,0, 53, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0},
+ {ET_NGRADE, 0,0,0, 53, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0},
{ET_NTIME, 0,0,0, 53, 'T', SKINCOLOR_GREY, 75*TICRATE, "", 0},
// DUSTY WASTELAND
// ---
{0, 957, 924, 2956, 54, 'N', SKINCOLOR_RUST, 0, "", 0},
- {ET_NGRADE, 0,0,0, 54, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0},
+ {ET_NGRADE, 0,0,0, 54, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0},
{ET_NTIME, 0,0,0, 54, 'T', SKINCOLOR_GREY, 65*TICRATE, "", 0},
// MAGMA CAVES
// ---
{0, -2752, 3104, 1800, 55, 'N', SKINCOLOR_RUST, 0, "", 0},
- {ET_NGRADE, 0,0,0, 55, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0},
+ {ET_NGRADE, 0,0,0, 55, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0},
{ET_NTIME, 0,0,0, 55, 'T', SKINCOLOR_GREY, 80*TICRATE, "", 0},
// EGG SATELLITE
// ---
{0, 5334, -609, 3426, 56, 'N', SKINCOLOR_RUST, 0, "", 0},
- {ET_NGRADE, 0,0,0, 56, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0},
+ {ET_NGRADE, 0,0,0, 56, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0},
{ET_NTIME, 0,0,0, 56, 'T', SKINCOLOR_GREY, 120*TICRATE, "", 0},
// BLACK HOLE
// ---
{0, 2108, 3776, 32, 57, 'N', SKINCOLOR_RUST, 0, "", 0},
- {ET_NGRADE, 0,0,0, 57, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0},
+ {ET_NGRADE, 0,0,0, 57, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0},
{ET_NTIME, 0,0,0, 57, 'T', SKINCOLOR_GREY, 150*TICRATE, "", 0},
// SPRING HILL
// ---
{0, -1840, -1024, 1644, 58, 'N', SKINCOLOR_RUST, 0, "", 0},
- {ET_NGRADE, 0,0,0, 58, 'Q', SKINCOLOR_TEAL, GRADE_A, "", 0},
+ {ET_NGRADE, 0,0,0, 58, 'Q', SKINCOLOR_CYAN, GRADE_A, "", 0},
{ET_NTIME, 0,0,0, 58, 'T', SKINCOLOR_GREY, 60*TICRATE, "", 0},
};
@@ -566,38 +566,38 @@ extraemblem_t extraemblems[MAXEXTRAEMBLEMS] =
{"All Emeralds", "Complete 1P Mode with all Emeralds", 11, 'V', SKINCOLOR_GREY, 0},
{"Perfect Bonus", "Perfect Bonus on a non-secret stage", 30, 'P', SKINCOLOR_GOLD, 0},
{"PLACEHOLDER", "PLACEHOLDER", 0, 'O', SKINCOLOR_RUST, 0},
- {"NiGHTS Mastery", "Show your mastery of NiGHTS!", 22, 'W', SKINCOLOR_TEAL, 0},
+ {"NiGHTS Mastery", "Show your mastery of NiGHTS!", 22, 'W', SKINCOLOR_CYAN, 0},
};
// Default Unlockables
unlockable_t unlockables[MAXUNLOCKABLES] =
{
// Name, Objective, Menu Height, ConditionSet, Unlock Type, Variable, NoCecho, NoChecklist
- /* 01 */ {"Record Attack", "Complete Greenflower Zone, Act 1", 0, 1, SECRET_RECORDATTACK, 0, true, true, 0},
- /* 02 */ {"NiGHTS Mode", "Complete Floral Field", 0, 2, SECRET_NIGHTSMODE, 0, true, true, 0},
+ /* 01 */ {"Record Attack", "/", 0, 1, SECRET_RECORDATTACK, 0, true, true, 0},
+ /* 02 */ {"NiGHTS Mode", "/", 0, 2, SECRET_NIGHTSMODE, 0, true, true, 0},
- /* 03 */ {"Play Credits", "Complete 1P Mode", 30, 10, SECRET_CREDITS, 0, true, true, 0},
- /* 04 */ {"Sound Test", "Complete 1P Mode", 40, 10, SECRET_SOUNDTEST, 0, false, false, 0},
+ /* 03 */ {"Play Credits", "/", 30, 10, SECRET_CREDITS, 0, true, true, 0},
+ /* 04 */ {"Sound Test", "/", 40, 10, SECRET_SOUNDTEST, 0, false, false, 0},
- /* 05 */ {"EXTRA LEVELS", "", 60, 0, SECRET_HEADER, 0, true, true, 0},
+ /* 05 */ {"EXTRA LEVELS", "/", 58, 0, SECRET_HEADER, 0, true, true, 0},
- /* 06 */ {"Aerial Garden Zone", "Complete 1P Mode w/ all emeralds", 70, 11, SECRET_WARP, 40, false, false, 0},
- /* 07 */ {"Azure Temple Zone", "Complete Aerial Garden Zone", 80, 20, SECRET_WARP, 41, false, false, 0},
+ /* 06 */ {"Aerial Garden Zone", "/", 70, 11, SECRET_WARP, 40, false, false, 0},
+ /* 07 */ {"Azure Temple Zone", "/", 80, 20, SECRET_WARP, 41, false, false, 0},
- /* 08 */ {"BONUS LEVELS", "", 100, 0, SECRET_HEADER, 0, true, true, 0},
+ /* 08 */ {"BONUS LEVELS", "/", 98, 0, SECRET_HEADER, 0, true, true, 0},
- /* 09 */ {"PLACEHOLDER", "PLACEHOLDER", 0, 0, SECRET_NONE, 0, true, true, 0},
- /* 10 */ {"Mario Koopa Blast", "Collect 60 Emblems", 110, 42, SECRET_WARP, 30, false, false, 0},
- /* 11 */ {"PLACEHOLDER", "PLACEHOLDER", 0, 0, SECRET_NONE, 0, true, true, 0},
+ /* 09 */ {"PLACEHOLDER", "/", 0, 0, SECRET_NONE, 0, true, true, 0},
+ /* 10 */ {"Mario Koopa Blast", "/", 110, 42, SECRET_WARP, 30, false, false, 0},
+ /* 11 */ {"PLACEHOLDER", "/", 0, 0, SECRET_NONE, 0, true, true, 0},
- /* 12 */ {"Spring Hill Zone", "Collect 100 Emblems", 0, 44, SECRET_NONE, 0, false, false, 0},
- /* 13 */ {"Black Hole", "A Rank in all Special Stages", 0, 50, SECRET_NONE, 0, false, true, 0},
+ /* 12 */ {"Spring Hill Zone", "/", 0, 44, SECRET_NONE, 0, false, false, 0},
+ /* 13 */ {"Black Hole", "Get grade A in all Special Stages", 0, 50, SECRET_NONE, 0, false, true, 0},
- /* 14 */ {"Emblem Hints", "Collect 40 Emblems", 0, 41, SECRET_EMBLEMHINTS, 0, false, true, 0},
- /* 15 */ {"Emblem Radar", "Collect 80 Emblems", 0, 43, SECRET_ITEMFINDER, 0, false, true, 0},
+ /* 14 */ {"Emblem Hints", "/", 0, 41, SECRET_EMBLEMHINTS, 0, false, true, 0},
+ /* 15 */ {"Emblem Radar", "/", 0, 43, SECRET_ITEMFINDER, 0, false, true, 0},
- /* 16 */ {"Pandora's Box", "Collect All Emblems", 0, 45, SECRET_PANDORA, 0, false, false, 0},
- /* 17 */ {"Level Select", "Collect All Emblems", 20, 45, SECRET_LEVELSELECT, 1, false, true, 0},
+ /* 16 */ {"Pandora's Box", "/", 0, 45, SECRET_PANDORA, 0, false, false, 0},
+ /* 17 */ {"Level Select", "/", 20, 45, SECRET_LEVELSELECT, 1, false, true, 0},
};
// Default number of emblems and extra emblems
diff --git a/src/m_cond.h b/src/m_cond.h
index 94802f665..00f633a8d 100644
--- a/src/m_cond.h
+++ b/src/m_cond.h
@@ -66,14 +66,18 @@ typedef struct
} conditionset_t;
// Emblem information
-#define ET_GLOBAL 0 // Global map emblem, var == color
-#define ET_SKIN 1 // Skin specific emblem, var == skin
-#define ET_SCORE 2
-#define ET_TIME 3
-#define ET_RINGS 4
-#define ET_NGRADE 5
-#define ET_NTIME 6
-#define ET_MAP 7
+#define ET_GLOBAL 0 // Emblem with a position in space
+#define ET_SKIN 1 // Skin specific emblem with a position in space, var == skin
+#define ET_MAP 2 // Beat the map
+#define ET_SCORE 3 // Get the score
+#define ET_TIME 4 // Get the time
+#define ET_RINGS 5 // Get the rings
+#define ET_NGRADE 6 // Get the grade
+#define ET_NTIME 7 // Get the time (NiGHTS mode)
+
+// Global emblem flags
+#define GE_NIGHTSPULL 1 // sun off the nights track - loop it
+#define GE_NIGHTSITEM 2 // moon on the nights track - find it
// Map emblem flags
#define ME_ALLEMERALDS 1
diff --git a/src/m_menu.c b/src/m_menu.c
index fb8aeedad..64255e71a 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -33,6 +33,9 @@
#include "s_sound.h"
#include "i_system.h"
+// Addfile
+#include "filesrch.h"
+
#include "v_video.h"
#include "i_video.h"
#include "keys.h"
@@ -72,9 +75,8 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
#define STRINGHEIGHT 8
#define FONTBHEIGHT 20
#define SMALLLINEHEIGHT 8
-#define SLIDER_RANGE 10
-#define SLIDER_WIDTH (8*SLIDER_RANGE+6)
-#define MAXSTRINGLENGTH 32
+#define SLIDER_RANGE 9
+#define SLIDER_WIDTH 78
#define SERVERS_PER_PAGE 11
typedef enum
@@ -211,14 +213,13 @@ menu_t SPauseDef;
// Level Select
static levelselect_t levelselect = {0, NULL};
-static UINT8 levelselectselect[4];
+static UINT8 levelselectselect[3];
static patch_t *levselp[2][3];
static INT32 lsoffs[2];
#define lsrow levelselectselect[0]
#define lscol levelselectselect[1]
-#define lstic levelselectselect[2]
-#define lshli levelselectselect[3]
+#define lshli levelselectselect[2]
#define lshseperation 101
#define lsbasevseperation 62
@@ -241,8 +242,11 @@ static void M_LevelSelectWarp(INT32 choice);
static void M_Credits(INT32 choice);
static void M_PandorasBox(INT32 choice);
static void M_EmblemHints(INT32 choice);
+static void M_HandleChecklist(INT32 choice);
menu_t SR_MainDef, SR_UnlockChecklistDef;
+static UINT8 check_on;
+
// Misc. Main Menu
static void M_SinglePlayerMenu(INT32 choice);
static void M_Options(INT32 choice);
@@ -259,7 +263,7 @@ static void M_ConfirmTeamChange(INT32 choice);
static void M_SecretsMenu(INT32 choice);
static void M_SetupChoosePlayer(INT32 choice);
static void M_QuitSRB2(INT32 choice);
-menu_t SP_MainDef, MP_MainDef, OP_MainDef;
+menu_t SP_MainDef, OP_MainDef;
menu_t MISC_ScrambleTeamDef, MISC_ChangeTeamDef;
// Single Player
@@ -277,35 +281,34 @@ static void M_ModeAttackEndGame(INT32 choice);
static void M_SetGuestReplay(INT32 choice);
static void M_HandleChoosePlayerMenu(INT32 choice);
static void M_ChoosePlayer(INT32 choice);
-menu_t SP_GameStatsDef, SP_LevelStatsDef;
+menu_t SP_LevelStatsDef;
static menu_t SP_TimeAttackDef, SP_ReplayDef, SP_GuestReplayDef, SP_GhostDef;
static menu_t SP_NightsAttackDef, SP_NightsReplayDef, SP_NightsGuestReplayDef, SP_NightsGhostDef;
// Multiplayer
-#ifndef NONET
-static void M_StartServerMenu(INT32 choice);
-static void M_ConnectMenu(INT32 choice);
-static void M_ConnectIPMenu(INT32 choice);
-#endif
+static void M_SetupMultiPlayer(INT32 choice);
+static void M_SetupMultiPlayer2(INT32 choice);
static void M_StartSplitServerMenu(INT32 choice);
static void M_StartServer(INT32 choice);
static void M_ServerOptions(INT32 choice);
#ifndef NONET
+static void M_StartServerMenu(INT32 choice);
+static void M_ConnectMenu(INT32 choice);
static void M_Refresh(INT32 choice);
static void M_Connect(INT32 choice);
static void M_ChooseRoom(INT32 choice);
+menu_t MP_MainDef;
#endif
-static void M_SetupMultiPlayer(INT32 choice);
-static void M_SetupMultiPlayer2(INT32 choice);
// Options
// Split into multiple parts due to size
// Controls
-menu_t OP_ControlsDef, OP_ControlListDef, OP_MoveControlsDef;
+menu_t OP_ChangeControlsDef;
menu_t OP_MPControlsDef, OP_CameraControlsDef, OP_MiscControlsDef;
menu_t OP_P1ControlsDef, OP_P2ControlsDef, OP_MouseOptionsDef;
menu_t OP_Mouse2OptionsDef, OP_Joystick1Def, OP_Joystick2Def;
static void M_VideoModeMenu(INT32 choice);
+static void M_SoundMenu(INT32 choice);
static void M_Setup1PControlsMenu(INT32 choice);
static void M_Setup2PControlsMenu(INT32 choice);
static void M_Setup1PJoystickMenu(INT32 choice);
@@ -314,26 +317,36 @@ static void M_AssignJoystick(INT32 choice);
static void M_ChangeControl(INT32 choice);
// Video & Sound
-menu_t OP_VideoOptionsDef, OP_VideoModeDef;
+menu_t OP_VideoOptionsDef, OP_VideoModeDef, OP_ColorOptionsDef;
#ifdef HWRENDER
menu_t OP_OpenGLOptionsDef, OP_OpenGLFogDef, OP_OpenGLColorDef;
#endif
menu_t OP_SoundOptionsDef;
-static void M_ToggleSFX(void);
-static void M_ToggleDigital(void);
-static void M_ToggleMIDI(void);
+static void M_ToggleSFX(INT32 choice);
+static void M_ToggleDigital(INT32 choice);
+static void M_ToggleMIDI(INT32 choice);
//Misc
menu_t OP_DataOptionsDef, OP_ScreenshotOptionsDef, OP_EraseDataDef;
-menu_t OP_GameOptionsDef, OP_ServerOptionsDef;
-menu_t OP_NetgameOptionsDef, OP_GametypeOptionsDef;
+menu_t OP_ServerOptionsDef;
menu_t OP_MonitorToggleDef;
static void M_ScreenshotOptions(INT32 choice);
static void M_EraseData(INT32 choice);
+static void M_Addons(INT32 choice);
+static void M_AddonsOptions(INT32 choice);
+static patch_t *addonsp[NUM_EXT+6];
+static UINT8 addonsresponselimit = 0;
+
+#define numaddonsshown 4
+
+static void M_DrawLevelPlatterHeader(INT32 y, const char *header, boolean headerhighlight, boolean allowlowercase);
+
// Drawing functions
static void M_DrawGenericMenu(void);
+static void M_DrawGenericScrollMenu(void);
static void M_DrawCenteredMenu(void);
+static void M_DrawAddons(void);
static void M_DrawSkyRoom(void);
static void M_DrawChecklist(void);
static void M_DrawEmblemHints(void);
@@ -344,38 +357,40 @@ static void M_DrawLevelPlatterMenu(void);
static void M_DrawImageDef(void);
static void M_DrawLoad(void);
static void M_DrawLevelStats(void);
-static void M_DrawGameStats(void);
static void M_DrawTimeAttackMenu(void);
static void M_DrawNightsAttackMenu(void);
static void M_DrawSetupChoosePlayerMenu(void);
static void M_DrawControl(void);
+static void M_DrawMainVideoMenu(void);
static void M_DrawVideoMode(void);
+static void M_DrawColorMenu(void);
+static void M_DrawSoundMenu(void);
+static void M_DrawScreenshotMenu(void);
static void M_DrawMonitorToggles(void);
#ifdef HWRENDER
static void M_OGL_DrawFogMenu(void);
static void M_OGL_DrawColorMenu(void);
#endif
#ifndef NONET
+static void M_DrawScreenshotMenu(void);
static void M_DrawConnectMenu(void);
-static void M_DrawConnectIPMenu(void);
+static void M_DrawMPMainMenu(void);
static void M_DrawRoomMenu(void);
#endif
static void M_DrawJoystick(void);
static void M_DrawSetupMultiPlayerMenu(void);
// Handling functions
-#ifndef NONET
-static boolean M_CancelConnect(void);
-#endif
static boolean M_ExitPandorasBox(void);
static boolean M_QuitMultiPlayerMenu(void);
+static void M_HandleAddons(INT32 choice);
static void M_HandleLevelPlatter(INT32 choice);
static void M_HandleSoundTest(INT32 choice);
static void M_HandleImageDef(INT32 choice);
static void M_HandleLoadSave(INT32 choice);
-static void M_HandleGameStats(INT32 choice);
static void M_HandleLevelStats(INT32 choice);
#ifndef NONET
+static boolean M_CancelConnect(void);
static void M_HandleConnectIP(INT32 choice);
#endif
static void M_HandleSetupMultiPlayer(INT32 choice);
@@ -384,6 +399,8 @@ static void M_HandleFogColor(INT32 choice);
#endif
static void M_HandleVideoMode(INT32 choice);
+static void M_ResetCvars(void);
+
// Consvar onchange functions
static void Newgametype_OnChange(void);
static void Dummymares_OnChange(void);
@@ -476,11 +493,16 @@ static consvar_t cv_dummymares = {"dummymares", "Overall", CV_HIDEN|CV_CALL, dum
// ---------
static menuitem_t MainMenu[] =
{
- {IT_CALL |IT_STRING, NULL, "Secrets", M_SecretsMenu, 84},
- {IT_CALL |IT_STRING, NULL, "1 player", M_SinglePlayerMenu, 92},
- {IT_SUBMENU|IT_STRING, NULL, "multiplayer", &MP_MainDef, 100},
- {IT_CALL |IT_STRING, NULL, "options", M_Options, 108},
- {IT_CALL |IT_STRING, NULL, "quit game", M_QuitSRB2, 116},
+ {IT_STRING|IT_CALL, NULL, "Secrets", M_SecretsMenu, 76},
+ {IT_STRING|IT_CALL, NULL, "1 player", M_SinglePlayerMenu, 84},
+#ifndef NONET
+ {IT_STRING|IT_SUBMENU, NULL, "multiplayer", &MP_MainDef, 92},
+#else
+ {IT_STRING|IT_CALL, NULL, "multiplayer", M_StartSplitServerMenu, 92},
+#endif
+ {IT_STRING|IT_CALL, NULL, "options", M_Options, 100},
+ {IT_CALL |IT_STRING, NULL, "addons", M_Addons, 108},
+ {IT_STRING|IT_CALL, NULL, "quit game", M_QuitSRB2, 116},
};
typedef enum
@@ -489,9 +511,15 @@ typedef enum
singleplr,
multiplr,
options,
+ addons,
quitdoom
} main_e;
+static menuitem_t MISC_AddonsMenu[] =
+{
+ {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleAddons, 0}, // dummy menuitem for the control func
+};
+
// ---------------------------------
// Pause Menu Mode Attacking Edition
// ---------------------------------
@@ -514,26 +542,28 @@ typedef enum
// ---------------------
static menuitem_t MPauseMenu[] =
{
- {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16},
- {IT_STRING | IT_CALL, NULL, "Switch Gametype/Level...", M_GameTypeChange, 24},
+ {IT_STRING | IT_CALL, NULL, "Add-ons...", M_Addons, 8},
+ {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16},
+ {IT_STRING | IT_CALL, NULL, "Switch Gametype/Level...", M_GameTypeChange, 24},
- {IT_CALL | IT_STRING, NULL, "Continue", M_SelectableClearMenus,40},
- {IT_CALL | IT_STRING, NULL, "Player 1 Setup", M_SetupMultiPlayer, 48}, // splitscreen
- {IT_CALL | IT_STRING, NULL, "Player 2 Setup", M_SetupMultiPlayer2, 56}, // splitscreen
+ {IT_STRING | IT_CALL, NULL, "Continue", M_SelectableClearMenus,40},
+ {IT_STRING | IT_CALL, NULL, "Player 1 Setup", M_SetupMultiPlayer, 48}, // splitscreen
+ {IT_STRING | IT_CALL, NULL, "Player 2 Setup", M_SetupMultiPlayer2, 56}, // splitscreen
{IT_STRING | IT_CALL, NULL, "Spectate", M_ConfirmSpectate, 48},
{IT_STRING | IT_CALL, NULL, "Enter Game", M_ConfirmEnterGame, 48},
{IT_STRING | IT_SUBMENU, NULL, "Switch Team...", &MISC_ChangeTeamDef, 48},
- {IT_CALL | IT_STRING, NULL, "Player Setup", M_SetupMultiPlayer, 56}, // alone
- {IT_CALL | IT_STRING, NULL, "Options", M_Options, 64},
+ {IT_STRING | IT_CALL, NULL, "Player Setup", M_SetupMultiPlayer, 56}, // alone
+ {IT_STRING | IT_CALL, NULL, "Options", M_Options, 64},
- {IT_CALL | IT_STRING, NULL, "Return to Title", M_EndGame, 80},
- {IT_CALL | IT_STRING, NULL, "Quit Game", M_QuitSRB2, 88},
+ {IT_STRING | IT_CALL, NULL, "Return to Title", M_EndGame, 80},
+ {IT_STRING | IT_CALL, NULL, "Quit Game", M_QuitSRB2, 88},
};
typedef enum
{
- mpause_scramble = 0,
+ mpause_addons = 0,
+ mpause_scramble,
mpause_switchmap,
mpause_continue,
@@ -576,6 +606,7 @@ typedef enum
spause_continue,
spause_retry,
spause_options,
+
spause_title,
spause_quit
} spause_e;
@@ -705,7 +736,7 @@ static menuitem_t SR_LevelSelectMenu[] =
static menuitem_t SR_UnlockChecklistMenu[] =
{
- {IT_SUBMENU | IT_STRING, NULL, "NEXT", &SR_MainDef, 192},
+ {IT_KEYHANDLER | IT_STRING, NULL, "", M_HandleChecklist, 0},
};
static menuitem_t SR_EmblemHintMenu[] =
@@ -876,11 +907,6 @@ enum
};
// Statistics
-static menuitem_t SP_GameStatsMenu[] =
-{
- {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleGameStats, 0}, // dummy menuitem for the control func
-};
-
static menuitem_t SP_LevelStatsMenu[] =
{
{IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelStats, 0}, // dummy menuitem for the control func
@@ -896,56 +922,56 @@ static menuitem_t SP_PlayerMenu[] =
// Multiplayer and all of its submenus
// -----------------------------------
// Prefix: MP_
+
+// Separated splitscreen and normal servers.
+static menuitem_t MP_SplitServerMenu[] =
+{
+ {IT_STRING|IT_CALL, NULL, "Select Gametype/Level...", M_GameTypeChange, 100},
+#ifdef NONET // In order to keep player setup accessible.
+ {IT_STRING|IT_CALL, NULL, "Player 1 setup...", M_SetupMultiPlayer, 110},
+ {IT_STRING|IT_CALL, NULL, "Player 2 setup...", M_SetupMultiPlayer2, 120},
+#endif
+ {IT_STRING|IT_CALL, NULL, "More Options...", M_ServerOptions, 130},
+ {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 140},
+};
+
+#ifndef NONET
+
static menuitem_t MP_MainMenu[] =
{
-#ifndef NONET
- {IT_CALL | IT_STRING, NULL, "HOST GAME", M_StartServerMenu, 10},
- {IT_CALL | IT_STRING, NULL, "JOIN GAME (Search)", M_ConnectMenu, 30},
- {IT_CALL | IT_STRING, NULL, "JOIN GAME (Specify IP)", M_ConnectIPMenu, 40},
-#endif
- {IT_CALL | IT_STRING, NULL, "TWO PLAYER GAME", M_StartSplitServerMenu, 60},
-
- {IT_CALL | IT_STRING, NULL, "SETUP PLAYER 1", M_SetupMultiPlayer, 80},
- {IT_CALL | IT_STRING, NULL, "SETUP PLAYER 2", M_SetupMultiPlayer2, 90},
+ {IT_HEADER, NULL, "Host a game", NULL, 0},
+ {IT_STRING|IT_CALL, NULL, "Internet/LAN...", M_StartServerMenu, 12},
+ {IT_STRING|IT_CALL, NULL, "Splitscreen...", M_StartSplitServerMenu, 22},
+ {IT_HEADER, NULL, "Join a game", NULL, 40},
+ {IT_STRING|IT_CALL, NULL, "Server browser...", M_ConnectMenu, 52},
+ {IT_STRING|IT_KEYHANDLER, NULL, "Specify IPv4 address:", M_HandleConnectIP, 62},
+ {IT_HEADER, NULL, "Player setup", NULL, 94},
+ {IT_STRING|IT_CALL, NULL, "Player 1...", M_SetupMultiPlayer, 106},
+ {IT_STRING|IT_CALL, NULL, "Player 2... ", M_SetupMultiPlayer2, 116},
};
static menuitem_t MP_ServerMenu[] =
{
- {IT_DISABLED|IT_NOTHING, NULL, "", NULL, 0},
-#ifndef NONET
- {IT_STRING|IT_CALL, NULL, "Room...", M_RoomMenu, 10},
- {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 20},
- {IT_STRING|IT_CVAR, NULL, "Max Players", &cv_maxplayers, 46},
- {IT_STRING|IT_CVAR, NULL, "Allow WAD Downloading", &cv_downloading, 56},
-#endif
- {IT_STRING|IT_CALL, NULL, "Select Gametype/Level...", M_GameTypeChange, 100},
- {IT_STRING|IT_CALL, NULL, "More Options...", M_ServerOptions, 130},
- {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 140},
+ {IT_STRING|IT_CALL, NULL, "Room...", M_RoomMenu, 10},
+ {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 20},
+ {IT_STRING|IT_CVAR, NULL, "Max Players", &cv_maxplayers, 46},
+ {IT_STRING|IT_CVAR, NULL, "Allow Add-on Downloading", &cv_downloading, 56},
+ {IT_STRING|IT_CALL, NULL, "Select Gametype/Level...", M_GameTypeChange, 100},
+ {IT_STRING|IT_CALL, NULL, "More Options...", M_ServerOptions, 130},
+ {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 140},
};
enum
{
- mp_server_dummy = 0, // exists solely so zero-indexed in both NONET and not NONET
-#ifndef NONET
- mp_server_room,
+ mp_server_room = 0,
mp_server_name,
mp_server_maxpl,
mp_server_waddl,
-#endif
mp_server_levelgt,
mp_server_options,
mp_server_start
};
-// Separated splitscreen and normal servers.
-static menuitem_t MP_SplitServerMenu[] =
-{
- {IT_STRING|IT_CALL, NULL, "Select Gametype/Level...", M_GameTypeChange, 100},
- {IT_STRING|IT_CALL, NULL, "More Options...", M_ServerOptions, 130},
- {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 140},
-};
-
-#ifndef NONET
static menuitem_t MP_ConnectMenu[] =
{
{IT_STRING | IT_CALL, NULL, "Room...", M_RoomMenu, 4},
@@ -997,17 +1023,14 @@ static menuitem_t MP_RoomMenu[] =
{IT_DISABLED, NULL, "", M_ChooseRoom, 162},
};
-static menuitem_t MP_ConnectIPMenu[] =
-{
- {IT_KEYHANDLER | IT_STRING, NULL, " IP Address:", M_HandleConnectIP, 0},
-};
#endif
static menuitem_t MP_PlayerSetupMenu[] =
{
- {IT_KEYHANDLER | IT_STRING, NULL, "Your name", M_HandleSetupMultiPlayer, 0},
- {IT_KEYHANDLER | IT_STRING, NULL, "Your color", M_HandleSetupMultiPlayer, 16},
- {IT_KEYHANDLER | IT_STRING, NULL, "Your player", M_HandleSetupMultiPlayer, 96}, // Tails 01-18-2001
+ {IT_KEYHANDLER, NULL, "", M_HandleSetupMultiPlayer, 0}, // name
+ {IT_KEYHANDLER, NULL, "", M_HandleSetupMultiPlayer, 0}, // skin
+ {IT_KEYHANDLER, NULL, "", M_HandleSetupMultiPlayer, 0}, // colour
+ {IT_KEYHANDLER, NULL, "", M_HandleSetupMultiPlayer, 0}, // default
};
// ------------------------------------
@@ -1016,22 +1039,16 @@ static menuitem_t MP_PlayerSetupMenu[] =
// Prefix: OP_
static menuitem_t OP_MainMenu[] =
{
- {IT_SUBMENU | IT_STRING, NULL, "Setup Controls...", &OP_ControlsDef, 10},
+ {IT_SUBMENU | IT_STRING, NULL, "Player 1 Controls...", &OP_P1ControlsDef, 10},
+ {IT_SUBMENU | IT_STRING, NULL, "Player 2 Controls...", &OP_P2ControlsDef, 20},
+ {IT_CVAR | IT_STRING, NULL, "Controls per key", &cv_controlperkey, 30},
- {IT_SUBMENU | IT_STRING, NULL, "Video Options...", &OP_VideoOptionsDef, 30},
- {IT_SUBMENU | IT_STRING, NULL, "Sound Options...", &OP_SoundOptionsDef, 40},
- {IT_SUBMENU | IT_STRING, NULL, "Data Options...", &OP_DataOptionsDef, 50},
+ {IT_SUBMENU | IT_STRING, NULL, "Video Options...", &OP_VideoOptionsDef, 50},
+ {IT_CALL | IT_STRING, NULL, "Sound Options...", M_SoundMenu, 60},
- {IT_SUBMENU | IT_STRING, NULL, "Game Options...", &OP_GameOptionsDef, 70},
- {IT_CALL | IT_STRING, NULL, "Server Options...", M_ServerOptions, 80},
-};
+ {IT_CALL | IT_STRING, NULL, "Server Options...", M_ServerOptions, 80},
-static menuitem_t OP_ControlsMenu[] =
-{
- {IT_SUBMENU | IT_STRING, NULL, "Player 1 Controls...", &OP_P1ControlsDef, 10},
- {IT_SUBMENU | IT_STRING, NULL, "Player 2 Controls...", &OP_P2ControlsDef, 20},
-
- {IT_STRING | IT_CVAR, NULL, "Controls per key", &cv_controlperkey, 40},
+ {IT_SUBMENU | IT_STRING, NULL, "Data Options...", &OP_DataOptionsDef, 100},
};
static menuitem_t OP_P1ControlsMenu[] =
@@ -1040,10 +1057,11 @@ static menuitem_t OP_P1ControlsMenu[] =
{IT_SUBMENU | IT_STRING, NULL, "Mouse Options...", &OP_MouseOptionsDef, 20},
{IT_SUBMENU | IT_STRING, NULL, "Joystick Options...", &OP_Joystick1Def , 30},
- {IT_STRING | IT_CVAR, NULL, "Camera" , &cv_chasecam , 50},
- {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair , 60},
+ {IT_STRING | IT_CVAR, NULL, "Third-person Camera" , &cv_chasecam , 50},
+ {IT_STRING | IT_CVAR, NULL, "Flip Camera with Gravity" , &cv_flipcam , 60},
+ {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair, 70},
- {IT_STRING | IT_CVAR, NULL, "Analog Control", &cv_useranalog, 80},
+ {IT_STRING | IT_CVAR, NULL, "Analog Control", &cv_useranalog, 90},
};
static menuitem_t OP_P2ControlsMenu[] =
@@ -1052,93 +1070,84 @@ static menuitem_t OP_P2ControlsMenu[] =
{IT_SUBMENU | IT_STRING, NULL, "Second Mouse Options...", &OP_Mouse2OptionsDef, 20},
{IT_SUBMENU | IT_STRING, NULL, "Second Joystick Options...", &OP_Joystick2Def , 30},
- {IT_STRING | IT_CVAR, NULL, "Camera" , &cv_chasecam2 , 50},
- {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair2, 60},
+ {IT_STRING | IT_CVAR, NULL, "Third-person Camera" , &cv_chasecam2 , 50},
+ {IT_STRING | IT_CVAR, NULL, "Flip Camera with Gravity" , &cv_flipcam2 , 60},
+ {IT_STRING | IT_CVAR, NULL, "Crosshair", &cv_crosshair2, 70},
- {IT_STRING | IT_CVAR, NULL, "Analog Control", &cv_useranalog2, 80},
+ {IT_STRING | IT_CVAR, NULL, "Analog Control", &cv_useranalog2, 90},
};
-static menuitem_t OP_ControlListMenu[] =
+static menuitem_t OP_ChangeControlsMenu[] =
{
- {IT_SUBMENU | IT_STRING, NULL, "Movement Controls...", &OP_MoveControlsDef, 10},
- {IT_SUBMENU | IT_STRING, NULL, "Multiplayer Controls...", &OP_MPControlsDef, 20},
- {IT_SUBMENU | IT_STRING, NULL, "Camera Controls...", &OP_CameraControlsDef, 30},
- {IT_SUBMENU | IT_STRING, NULL, "Miscellaneous Controls...", &OP_MiscControlsDef, 40},
-};
-
-static menuitem_t OP_MoveControlsMenu[] =
-{
- {IT_CALL | IT_STRING2, NULL, "Forward", M_ChangeControl, gc_forward },
- {IT_CALL | IT_STRING2, NULL, "Reverse", M_ChangeControl, gc_backward },
- {IT_CALL | IT_STRING2, NULL, "Turn Left", M_ChangeControl, gc_turnleft },
- {IT_CALL | IT_STRING2, NULL, "Turn Right", M_ChangeControl, gc_turnright },
- {IT_CALL | IT_STRING2, NULL, "Jump", M_ChangeControl, gc_jump },
- {IT_CALL | IT_STRING2, NULL, "Spin", M_ChangeControl, gc_use },
- {IT_CALL | IT_STRING2, NULL, "Strafe Left", M_ChangeControl, gc_strafeleft },
- {IT_CALL | IT_STRING2, NULL, "Strafe Right", M_ChangeControl, gc_straferight},
-};
-
-static menuitem_t OP_MPControlsMenu[] =
-{
- {IT_CALL | IT_STRING2, NULL, "Talk key", M_ChangeControl, gc_talkkey },
- {IT_CALL | IT_STRING2, NULL, "Team-Talk key", M_ChangeControl, gc_teamkey },
- {IT_CALL | IT_STRING2, NULL, "Rankings/Scores", M_ChangeControl, gc_scores },
- {IT_CALL | IT_STRING2, NULL, "Toss Flag", M_ChangeControl, gc_tossflag },
- {IT_CALL | IT_STRING2, NULL, "Next Weapon", M_ChangeControl, gc_weaponnext },
- {IT_CALL | IT_STRING2, NULL, "Prev Weapon", M_ChangeControl, gc_weaponprev },
- {IT_CALL | IT_STRING2, NULL, "Weapon Slot 1", M_ChangeControl, gc_wepslot1 },
- {IT_CALL | IT_STRING2, NULL, "Weapon Slot 2", M_ChangeControl, gc_wepslot2 },
- {IT_CALL | IT_STRING2, NULL, "Weapon Slot 3", M_ChangeControl, gc_wepslot3 },
- {IT_CALL | IT_STRING2, NULL, "Weapon Slot 4", M_ChangeControl, gc_wepslot4 },
- {IT_CALL | IT_STRING2, NULL, "Weapon Slot 5", M_ChangeControl, gc_wepslot5 },
- {IT_CALL | IT_STRING2, NULL, "Weapon Slot 6", M_ChangeControl, gc_wepslot6 },
- {IT_CALL | IT_STRING2, NULL, "Weapon Slot 7", M_ChangeControl, gc_wepslot7 },
- {IT_CALL | IT_STRING2, NULL, "Ring Toss", M_ChangeControl, gc_fire },
- {IT_CALL | IT_STRING2, NULL, "Ring Toss Normal", M_ChangeControl, gc_firenormal },
-};
-
-static menuitem_t OP_CameraControlsMenu[] =
-{
- {IT_CALL | IT_STRING2, NULL, "Look Up", M_ChangeControl, gc_lookup },
- {IT_CALL | IT_STRING2, NULL, "Look Down", M_ChangeControl, gc_lookdown },
- {IT_CALL | IT_STRING2, NULL, "Rotate Camera L", M_ChangeControl, gc_camleft },
- {IT_CALL | IT_STRING2, NULL, "Rotate Camera R", M_ChangeControl, gc_camright },
- {IT_CALL | IT_STRING2, NULL, "Center View", M_ChangeControl, gc_centerview },
- {IT_CALL | IT_STRING2, NULL, "Mouselook", M_ChangeControl, gc_mouseaiming },
- {IT_CALL | IT_STRING2, NULL, "Reset Camera", M_ChangeControl, gc_camreset },
- {IT_CALL | IT_STRING2, NULL, "Toggle Chasecam", M_ChangeControl, gc_camtoggle },
-};
-
-static menuitem_t OP_MiscControlsMenu[] =
-{
- {IT_CALL | IT_STRING2, NULL, "Custom Action 1", M_ChangeControl, gc_custom1 },
- {IT_CALL | IT_STRING2, NULL, "Custom Action 2", M_ChangeControl, gc_custom2 },
- {IT_CALL | IT_STRING2, NULL, "Custom Action 3", M_ChangeControl, gc_custom3 },
-
- {IT_CALL | IT_STRING2, NULL, "Pause", M_ChangeControl, gc_pause },
- {IT_CALL | IT_STRING2, NULL, "Console", M_ChangeControl, gc_console },
+ {IT_HEADER, NULL, "Movement", NULL, 0},
+ {IT_SPACE, NULL, NULL, NULL, 0}, // padding
+ {IT_CALL | IT_STRING2, NULL, "Move Forward", M_ChangeControl, gc_forward },
+ {IT_CALL | IT_STRING2, NULL, "Move Backward", M_ChangeControl, gc_backward },
+ {IT_CALL | IT_STRING2, NULL, "Move Left", M_ChangeControl, gc_strafeleft },
+ {IT_CALL | IT_STRING2, NULL, "Move Right", M_ChangeControl, gc_straferight },
+ {IT_CALL | IT_STRING2, NULL, "Jump / Main Action", M_ChangeControl, gc_jump },
+ {IT_CALL | IT_STRING2, NULL, "Spin / Shield Action", M_ChangeControl, gc_use },
+ {IT_HEADER, NULL, "Camera", NULL, 0},
+ {IT_SPACE, NULL, NULL, NULL, 0}, // padding
+ {IT_CALL | IT_STRING2, NULL, "Camera Up", M_ChangeControl, gc_lookup },
+ {IT_CALL | IT_STRING2, NULL, "Camera Down", M_ChangeControl, gc_lookdown },
+ {IT_CALL | IT_STRING2, NULL, "Camera Left", M_ChangeControl, gc_turnleft },
+ {IT_CALL | IT_STRING2, NULL, "Camera Right", M_ChangeControl, gc_turnright },
+ {IT_CALL | IT_STRING2, NULL, "Center View", M_ChangeControl, gc_centerview },
+ {IT_CALL | IT_STRING2, NULL, "Toggle Mouselook", M_ChangeControl, gc_mouseaiming },
+ {IT_CALL | IT_STRING2, NULL, "Toggle Third-Person", M_ChangeControl, gc_camtoggle},
+ {IT_CALL | IT_STRING2, NULL, "Reset Camera", M_ChangeControl, gc_camreset },
+ {IT_HEADER, NULL, "Meta", NULL, 0},
+ {IT_SPACE, NULL, NULL, NULL, 0}, // padding
+ {IT_CALL | IT_STRING2, NULL, "Game Status",
+ M_ChangeControl, gc_scores },
+ {IT_CALL | IT_STRING2, NULL, "Pause", M_ChangeControl, gc_pause },
+ {IT_CALL | IT_STRING2, NULL, "Console", M_ChangeControl, gc_console },
+ {IT_HEADER, NULL, "Multiplayer", NULL, 0},
+ {IT_SPACE, NULL, NULL, NULL, 0}, // padding
+ {IT_CALL | IT_STRING2, NULL, "Talk", M_ChangeControl, gc_talkkey },
+ {IT_CALL | IT_STRING2, NULL, "Talk (Team only)", M_ChangeControl, gc_teamkey },
+ {IT_HEADER, NULL, "Ringslinger (Match, CTF, Tag, H&S)", NULL, 0},
+ {IT_SPACE, NULL, NULL, NULL, 0}, // padding
+ {IT_CALL | IT_STRING2, NULL, "Fire", M_ChangeControl, gc_fire },
+ {IT_CALL | IT_STRING2, NULL, "Fire Normal", M_ChangeControl, gc_firenormal },
+ {IT_CALL | IT_STRING2, NULL, "Toss Flag", M_ChangeControl, gc_tossflag },
+ {IT_CALL | IT_STRING2, NULL, "Next Weapon", M_ChangeControl, gc_weaponnext },
+ {IT_CALL | IT_STRING2, NULL, "Prev Weapon", M_ChangeControl, gc_weaponprev },
+ {IT_CALL | IT_STRING2, NULL, "Normal / Infinity", M_ChangeControl, gc_wepslot1 },
+ {IT_CALL | IT_STRING2, NULL, "Automatic", M_ChangeControl, gc_wepslot2 },
+ {IT_CALL | IT_STRING2, NULL, "Bounce", M_ChangeControl, gc_wepslot3 },
+ {IT_CALL | IT_STRING2, NULL, "Scatter", M_ChangeControl, gc_wepslot4 },
+ {IT_CALL | IT_STRING2, NULL, "Grenade", M_ChangeControl, gc_wepslot5 },
+ {IT_CALL | IT_STRING2, NULL, "Explosion", M_ChangeControl, gc_wepslot6 },
+ {IT_CALL | IT_STRING2, NULL, "Rail", M_ChangeControl, gc_wepslot7 },
+ {IT_HEADER, NULL, "Add-ons", NULL, 0},
+ {IT_SPACE, NULL, NULL, NULL, 0}, // padding
+ {IT_CALL | IT_STRING2, NULL, "Custom Action 1", M_ChangeControl, gc_custom1 },
+ {IT_CALL | IT_STRING2, NULL, "Custom Action 2", M_ChangeControl, gc_custom2 },
+ {IT_CALL | IT_STRING2, NULL, "Custom Action 3", M_ChangeControl, gc_custom3 },
};
static menuitem_t OP_Joystick1Menu[] =
{
{IT_STRING | IT_CALL, NULL, "Select Joystick...", M_Setup1PJoystickMenu, 10},
- {IT_STRING | IT_CVAR, NULL, "Axis For Turning" , &cv_turnaxis , 30},
- {IT_STRING | IT_CVAR, NULL, "Axis For Moving" , &cv_moveaxis , 40},
- {IT_STRING | IT_CVAR, NULL, "Axis For Strafe" , &cv_sideaxis , 50},
- {IT_STRING | IT_CVAR, NULL, "Axis For Looking" , &cv_lookaxis , 60},
- {IT_STRING | IT_CVAR, NULL, "Axis For Firing" , &cv_fireaxis , 70},
- {IT_STRING | IT_CVAR, NULL, "Axis For NFiring" , &cv_firenaxis , 80},
+ {IT_STRING | IT_CVAR, NULL, "Move \x17 Axis" , &cv_moveaxis , 30},
+ {IT_STRING | IT_CVAR, NULL, "Move \x18 Axis" , &cv_sideaxis , 40},
+ {IT_STRING | IT_CVAR, NULL, "Camera \x17 Axis" , &cv_lookaxis , 50},
+ {IT_STRING | IT_CVAR, NULL, "Camera \x18 Axis" , &cv_turnaxis , 60},
+ {IT_STRING | IT_CVAR, NULL, "Fire Axis" , &cv_fireaxis , 70},
+ {IT_STRING | IT_CVAR, NULL, "Fire Normal Axis" , &cv_firenaxis , 80},
};
static menuitem_t OP_Joystick2Menu[] =
{
{IT_STRING | IT_CALL, NULL, "Select Joystick...", M_Setup2PJoystickMenu, 10},
- {IT_STRING | IT_CVAR, NULL, "Axis For Turning" , &cv_turnaxis2 , 30},
- {IT_STRING | IT_CVAR, NULL, "Axis For Moving" , &cv_moveaxis2 , 40},
- {IT_STRING | IT_CVAR, NULL, "Axis For Strafe" , &cv_sideaxis2 , 50},
- {IT_STRING | IT_CVAR, NULL, "Axis For Looking" , &cv_lookaxis2 , 60},
- {IT_STRING | IT_CVAR, NULL, "Axis For Firing" , &cv_fireaxis2 , 70},
- {IT_STRING | IT_CVAR, NULL, "Axis For NFiring" , &cv_firenaxis2 , 80},
+ {IT_STRING | IT_CVAR, NULL, "Move \x17 Axis" , &cv_moveaxis2 , 30},
+ {IT_STRING | IT_CVAR, NULL, "Move \x18 Axis" , &cv_sideaxis2 , 40},
+ {IT_STRING | IT_CVAR, NULL, "Camera \x17 Axis" , &cv_lookaxis2 , 50},
+ {IT_STRING | IT_CVAR, NULL, "Camera \x18 Axis" , &cv_turnaxis2 , 60},
+ {IT_STRING | IT_CVAR, NULL, "Fire Axis" , &cv_fireaxis2 , 70},
+ {IT_STRING | IT_CVAR, NULL, "Fire Normal Axis" , &cv_firenaxis2 , 80},
};
static menuitem_t OP_JoystickSetMenu[] =
@@ -1148,8 +1157,6 @@ static menuitem_t OP_JoystickSetMenu[] =
{IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, '2'},
{IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, '3'},
{IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, '4'},
- {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, '5'},
- {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, '6'},
};
static menuitem_t OP_MouseOptionsMenu[] =
@@ -1157,13 +1164,13 @@ static menuitem_t OP_MouseOptionsMenu[] =
{IT_STRING | IT_CVAR, NULL, "Use Mouse", &cv_usemouse, 10},
- {IT_STRING | IT_CVAR, NULL, "Always MouseLook", &cv_alwaysfreelook, 30},
+ {IT_STRING | IT_CVAR, NULL, "Always Mouselook", &cv_alwaysfreelook, 30},
{IT_STRING | IT_CVAR, NULL, "Mouse Move", &cv_mousemove, 40},
- {IT_STRING | IT_CVAR, NULL, "Invert Mouse", &cv_invertmouse, 50},
+ {IT_STRING | IT_CVAR, NULL, "Invert Y Axis", &cv_invertmouse, 50},
{IT_STRING | IT_CVAR | IT_CV_SLIDER,
- NULL, "Mouse X Speed", &cv_mousesens, 60},
+ NULL, "Mouse X Sensitivity", &cv_mousesens, 60},
{IT_STRING | IT_CVAR | IT_CV_SLIDER,
- NULL, "Mouse Y Speed", &cv_mouseysens, 70},
+ NULL, "Mouse Y Sensitivity", &cv_mouseysens, 70},
};
static menuitem_t OP_Mouse2OptionsMenu[] =
@@ -1171,37 +1178,56 @@ static menuitem_t OP_Mouse2OptionsMenu[] =
{IT_STRING | IT_CVAR, NULL, "Use Mouse 2", &cv_usemouse2, 10},
{IT_STRING | IT_CVAR, NULL, "Second Mouse Serial Port",
&cv_mouse2port, 20},
- {IT_STRING | IT_CVAR, NULL, "Always MouseLook", &cv_alwaysfreelook2, 30},
+ {IT_STRING | IT_CVAR, NULL, "Always Mouselook", &cv_alwaysfreelook2, 30},
{IT_STRING | IT_CVAR, NULL, "Mouse Move", &cv_mousemove2, 40},
- {IT_STRING | IT_CVAR, NULL, "Invert Mouse", &cv_invertmouse2, 50},
+ {IT_STRING | IT_CVAR, NULL, "Invert Y Axis", &cv_invertmouse2, 50},
{IT_STRING | IT_CVAR | IT_CV_SLIDER,
- NULL, "Mouse X Speed", &cv_mousesens2, 60},
+ NULL, "Mouse X Sensitivity", &cv_mousesens2, 60},
{IT_STRING | IT_CVAR | IT_CV_SLIDER,
- NULL, "Mouse Y Speed", &cv_mouseysens2, 70},
+ NULL, "Mouse Y Sensitivity", &cv_mouseysens2, 70},
};
static menuitem_t OP_VideoOptionsMenu[] =
{
- {IT_STRING | IT_CALL, NULL, "Video Modes...", M_VideoModeMenu, 10},
-
-#ifdef HWRENDER
- {IT_SUBMENU|IT_STRING, NULL, "3D Card Options...", &OP_OpenGLOptionsDef, 20},
-#endif
+ {IT_HEADER, NULL, "Screen", NULL, 0},
+ {IT_STRING | IT_CALL, NULL, "Set Resolution...", M_VideoModeMenu, 6},
#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL)
- {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 30},
+ {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 11},
+#endif
+ {IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 16},
+
+#ifdef HWRENDER
+ {IT_SUBMENU|IT_STRING, NULL, "OpenGL Options...", &OP_OpenGLOptionsDef, 21},
#endif
- {IT_STRING | IT_CVAR | IT_CV_SLIDER,
- NULL, "Brightness", &cv_usegamma, 50},
- {IT_STRING | IT_CVAR, NULL, "Draw Distance", &cv_drawdist, 60},
- {IT_STRING | IT_CVAR, NULL, "NiGHTS Draw Dist", &cv_drawdist_nights, 70},
- {IT_STRING | IT_CVAR, NULL, "Precip Draw Dist", &cv_drawdist_precip, 80},
- {IT_STRING | IT_CVAR, NULL, "Precip Density", &cv_precipdensity, 90},
+ {IT_HEADER, NULL, "Color Profile", NULL, 30},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Brightness (F11)", &cv_globalgamma, 36},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Saturation", &cv_globalsaturation, 41},
+ {IT_SUBMENU|IT_STRING, NULL, "Advanced Settings...", &OP_ColorOptionsDef, 46},
- {IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 110},
- {IT_STRING | IT_CVAR, NULL, "Clear Before Redraw", &cv_homremoval, 120},
- {IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 130},
+ {IT_HEADER, NULL, "Heads-Up Display", NULL, 55},
+ {IT_STRING | IT_CVAR, NULL, "Show HUD", &cv_showhud, 61},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER,
+ NULL, "HUD Transparency", &cv_translucenthud, 66},
+ {IT_STRING | IT_CVAR, NULL, "Time Display", &cv_timetic, 71},
+#ifdef SEENAMES
+ {IT_STRING | IT_CVAR, NULL, "Show player names", &cv_seenames, 76},
+#endif
+
+ {IT_HEADER, NULL, "Console", NULL, 85},
+ {IT_STRING | IT_CVAR, NULL, "Background color", &cons_backcolor, 91},
+ {IT_STRING | IT_CVAR, NULL, "Text Size", &cv_constextsize, 96},
+
+ {IT_HEADER, NULL, "Level", NULL, 105},
+ {IT_STRING | IT_CVAR, NULL, "Draw Distance", &cv_drawdist, 111},
+ {IT_STRING | IT_CVAR, NULL, "NiGHTS Draw Dist.", &cv_drawdist_nights, 116},
+ {IT_STRING | IT_CVAR, NULL, "Weather Draw Dist.", &cv_drawdist_precip, 121},
+ {IT_STRING | IT_CVAR, NULL, "Weather Density", &cv_precipdensity, 126},
+
+ {IT_HEADER, NULL, "Diagnostic", NULL, 135},
+ {IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 141},
+ {IT_STRING | IT_CVAR, NULL, "Clear Before Redraw", &cv_homremoval, 146},
};
static menuitem_t OP_VideoModeMenu[] =
@@ -1209,6 +1235,47 @@ static menuitem_t OP_VideoModeMenu[] =
{IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleVideoMode, 0}, // dummy menuitem for the control func
};
+static menuitem_t OP_ColorOptionsMenu[] =
+{
+ {IT_STRING | IT_CALL, NULL, "Reset to defaults", M_ResetCvars, 0},
+
+ {IT_HEADER, NULL, "Red", NULL, 9},
+ {IT_DISABLED, NULL, NULL, NULL, 35},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Hue", &cv_rhue, 15},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Saturation", &cv_rsaturation, 20},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Brightness", &cv_rgamma, 25},
+
+ {IT_HEADER, NULL, "Yellow", NULL, 34},
+ {IT_DISABLED, NULL, NULL, NULL, 73},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Hue", &cv_yhue, 40},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Saturation", &cv_ysaturation, 45},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Brightness", &cv_ygamma, 50},
+
+ {IT_HEADER, NULL, "Green", NULL, 59},
+ {IT_DISABLED, NULL, NULL, NULL, 112},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Hue", &cv_ghue, 65},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Saturation", &cv_gsaturation, 70},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Brightness", &cv_ggamma, 75},
+
+ {IT_HEADER, NULL, "Cyan", NULL, 84},
+ {IT_DISABLED, NULL, NULL, NULL, 255},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Hue", &cv_chue, 90},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Saturation", &cv_csaturation, 95},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Brightness", &cv_cgamma, 100},
+
+ {IT_HEADER, NULL, "Blue", NULL, 109},
+ {IT_DISABLED, NULL, NULL, NULL, 152},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Hue", &cv_bhue, 115},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Saturation", &cv_bsaturation, 120},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Brightness", &cv_bgamma, 125},
+
+ {IT_HEADER, NULL, "Magenta", NULL, 134},
+ {IT_DISABLED, NULL, NULL, NULL, 181},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Hue", &cv_mhue, 140},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Saturation", &cv_msaturation, 145},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Brightness", &cv_mgamma, 150},
+};
+
#ifdef HWRENDER
static menuitem_t OP_OpenGLOptionsMenu[] =
{
@@ -1216,7 +1283,7 @@ static menuitem_t OP_OpenGLOptionsMenu[] =
{IT_STRING|IT_CVAR, NULL, "Quality", &cv_scr_depth, 20},
{IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 30},
{IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode,40},
-#ifdef _WINDOWS
+#if defined (_WINDOWS) && (!((defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL)))
{IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 50},
#endif
#ifdef ALAM_LIGHTING
@@ -1254,60 +1321,60 @@ static menuitem_t OP_OpenGLColorMenu[] =
static menuitem_t OP_SoundOptionsMenu[] =
{
- {IT_STRING | IT_CVAR | IT_CV_SLIDER,
- NULL, "Sound Volume" , &cv_soundvolume, 10},
- {IT_STRING | IT_CVAR | IT_CV_SLIDER,
- NULL, "Music Volume" , &cv_digmusicvolume, 20},
- {IT_STRING | IT_CVAR | IT_CV_SLIDER,
- NULL, "MIDI Volume" , &cv_midimusicvolume, 30},
-#ifdef PC_DOS
- {IT_STRING | IT_CVAR | IT_CV_SLIDER,
- NULL, "CD Volume" , &cd_volume, 40},
-#endif
+ {IT_STRING | IT_KEYHANDLER, NULL, "Sound Effects", M_ToggleSFX, 10},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Sound Volume", &cv_soundvolume, 20},
- {IT_STRING | IT_CALL, NULL, "Toggle SFX" , M_ToggleSFX, 50},
- {IT_STRING | IT_CALL, NULL, "Toggle Digital Music", M_ToggleDigital, 60},
- {IT_STRING | IT_CALL, NULL, "Toggle MIDI Music", M_ToggleMIDI, 70},
+ {IT_STRING | IT_KEYHANDLER, NULL, "Digital Music", M_ToggleDigital, 40},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Digital Music Volume", &cv_digmusicvolume, 50},
+
+ {IT_STRING | IT_KEYHANDLER, NULL, "MIDI Music", M_ToggleMIDI, 70},
+ {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "MIDI Music Volume", &cv_midimusicvolume, 80},
+
+ {IT_STRING | IT_CVAR, NULL, "Closed Captioning", &cv_closedcaptioning, 100},
};
static menuitem_t OP_DataOptionsMenu[] =
{
- {IT_STRING | IT_CALL, NULL, "Screenshot Options...", M_ScreenshotOptions, 10},
+ {IT_STRING | IT_CALL, NULL, "Add-on Options...", M_AddonsOptions, 10},
+ {IT_STRING | IT_CALL, NULL, "Screenshot Options...", M_ScreenshotOptions, 20},
- {IT_STRING | IT_SUBMENU, NULL, "Erase Data...", &OP_EraseDataDef, 30},
+ {IT_STRING | IT_SUBMENU, NULL, "\x85" "Erase Data...", &OP_EraseDataDef, 40},
};
static menuitem_t OP_ScreenshotOptionsMenu[] =
{
- {IT_STRING|IT_CVAR, NULL, "Storage Location", &cv_screenshot_option, 10},
- {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_screenshot_folder, 20},
+ {IT_HEADER, NULL, "General", NULL, 0},
+ {IT_STRING|IT_CVAR, NULL, "Use color profile", &cv_screenshot_colorprofile, 6},
+ {IT_STRING|IT_CVAR, NULL, "Storage Location", &cv_screenshot_option, 11},
+ {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_screenshot_folder, 16},
- {IT_HEADER, NULL, "Screenshots (F8)", NULL, 50},
- {IT_STRING|IT_CVAR, NULL, "Memory Level", &cv_zlib_memory, 60},
- {IT_STRING|IT_CVAR, NULL, "Compression Level", &cv_zlib_level, 70},
- {IT_STRING|IT_CVAR, NULL, "Strategy", &cv_zlib_strategy, 80},
- {IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bits, 90},
+ {IT_HEADER, NULL, "Screenshots (F8)", NULL, 30},
+ {IT_STRING|IT_CVAR, NULL, "Memory Level", &cv_zlib_memory, 36},
+ {IT_STRING|IT_CVAR, NULL, "Compression Level", &cv_zlib_level, 41},
+ {IT_STRING|IT_CVAR, NULL, "Strategy", &cv_zlib_strategy, 46},
+ {IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bits, 51},
- {IT_HEADER, NULL, "Movie Mode (F9)", NULL, 105},
- {IT_STRING|IT_CVAR, NULL, "Capture Mode", &cv_moviemode, 115},
+ {IT_HEADER, NULL, "Movie Mode (F9)", NULL, 60},
+ {IT_STRING|IT_CVAR, NULL, "Capture Mode", &cv_moviemode, 66},
- {IT_STRING|IT_CVAR, NULL, "Region Optimizing", &cv_gif_optimize, 125},
- {IT_STRING|IT_CVAR, NULL, "Downscaling", &cv_gif_downscale, 135},
+ {IT_STRING|IT_CVAR, NULL, "Region Optimizing", &cv_gif_optimize, 71},
+ {IT_STRING|IT_CVAR, NULL, "Downscaling", &cv_gif_downscale, 76},
- {IT_STRING|IT_CVAR, NULL, "Memory Level", &cv_zlib_memorya, 125},
- {IT_STRING|IT_CVAR, NULL, "Compression Level", &cv_zlib_levela, 135},
- {IT_STRING|IT_CVAR, NULL, "Strategy", &cv_zlib_strategya, 145},
- {IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bitsa, 155},
+ {IT_STRING|IT_CVAR, NULL, "Memory Level", &cv_zlib_memorya, 71},
+ {IT_STRING|IT_CVAR, NULL, "Compression Level", &cv_zlib_levela, 76},
+ {IT_STRING|IT_CVAR, NULL, "Strategy", &cv_zlib_strategya, 81},
+ {IT_STRING|IT_CVAR, NULL, "Window Size", &cv_zlib_window_bitsa, 86},
};
enum
{
- op_screenshot_folder = 1,
- op_screenshot_capture = 8,
- op_screenshot_gif_start = 9,
- op_screenshot_gif_end = 10,
- op_screenshot_apng_start = 11,
- op_screenshot_apng_end = 14,
+ op_screenshot_colorprofile = 1,
+ op_screenshot_folder = 3,
+ op_screenshot_capture = 10,
+ op_screenshot_gif_start = 11,
+ op_screenshot_gif_end = 12,
+ op_screenshot_apng_start = 13,
+ op_screenshot_apng_end = 16,
};
static menuitem_t OP_EraseDataMenu[] =
@@ -1318,111 +1385,94 @@ static menuitem_t OP_EraseDataMenu[] =
{IT_STRING | IT_CALL, NULL, "\x85" "Erase ALL Data", M_EraseData, 40},
};
-static menuitem_t OP_GameOptionsMenu[] =
+static menuitem_t OP_AddonsOptionsMenu[] =
{
-#ifndef NONET
- {IT_STRING | IT_CVAR | IT_CV_STRING,
- NULL, "Master server", &cv_masterserver, 10},
-#endif
- {IT_STRING | IT_CVAR, NULL, "Show HUD", &cv_showhud, 40},
- {IT_STRING | IT_CVAR | IT_CV_SLIDER,
- NULL, "HUD Visibility", &cv_translucenthud, 50},
- {IT_STRING | IT_CVAR, NULL, "Timer Display", &cv_timetic, 60},
-#ifdef SEENAMES
- {IT_STRING | IT_CVAR, NULL, "HUD Player Names", &cv_seenames, 80},
-#endif
- {IT_STRING | IT_CVAR, NULL, "Log Hazard Damage", &cv_hazardlog, 90},
+ {IT_HEADER, NULL, "Menu", NULL, 0},
+ {IT_STRING|IT_CVAR, NULL, "Location", &cv_addons_option, 12},
+ {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_addons_folder, 22},
+ {IT_STRING|IT_CVAR, NULL, "Identify add-ons via", &cv_addons_md5, 50},
+ {IT_STRING|IT_CVAR, NULL, "Show unsupported file types", &cv_addons_showall, 60},
- {IT_STRING | IT_CVAR, NULL, "Console Back Color", &cons_backcolor, 100},
- {IT_STRING | IT_CVAR, NULL, "Console Text Size", &cv_constextsize,110},
- {IT_STRING | IT_CVAR, NULL, "Uppercase Console", &cv_allcaps, 120},
+ {IT_HEADER, NULL, "Search", NULL, 78},
+ {IT_STRING|IT_CVAR, NULL, "Matching", &cv_addons_search_type, 90},
+ {IT_STRING|IT_CVAR, NULL, "Case-sensitive", &cv_addons_search_case, 100},
+};
- {IT_STRING | IT_CVAR, NULL, "Title Screen Demos", &cv_rollingdemos, 140},
+enum
+{
+ op_addons_folder = 2,
};
static menuitem_t OP_ServerOptionsMenu[] =
{
- {IT_STRING | IT_SUBMENU, NULL, "General netgame options...", &OP_NetgameOptionsDef, 10},
- {IT_STRING | IT_SUBMENU, NULL, "Gametype options...", &OP_GametypeOptionsDef, 20},
- {IT_STRING | IT_SUBMENU, NULL, "Random Monitor Toggles...", &OP_MonitorToggleDef, 30},
-
+ {IT_HEADER, NULL, "General", NULL, 0},
#ifndef NONET
{IT_STRING | IT_CVAR | IT_CV_STRING,
- NULL, "Server name", &cv_servername, 50},
+ NULL, "Server name", &cv_servername, 7},
+ {IT_STRING | IT_CVAR, NULL, "Max Players", &cv_maxplayers, 21},
+ {IT_STRING | IT_CVAR, NULL, "Allow Add-on Downloading", &cv_downloading, 26},
+ {IT_STRING | IT_CVAR, NULL, "Allow players to join", &cv_allownewplayer, 31},
#endif
+ {IT_STRING | IT_CVAR, NULL, "Map progression", &cv_advancemap, 36},
+ {IT_STRING | IT_CVAR, NULL, "Intermission Timer", &cv_inttime, 41},
- {IT_STRING | IT_CVAR, NULL, "Intermission Timer", &cv_inttime, 80},
- {IT_STRING | IT_CVAR, NULL, "Advance to next map", &cv_advancemap, 90},
+ {IT_HEADER, NULL, "Characters", NULL, 50},
+ {IT_STRING | IT_CVAR, NULL, "Force a character", &cv_forceskin, 56},
+ {IT_STRING | IT_CVAR, NULL, "Restrict character changes", &cv_restrictskinchange, 61},
+
+ {IT_HEADER, NULL, "Items", NULL, 70},
+ {IT_STRING | IT_CVAR, NULL, "Item respawn delay", &cv_itemrespawntime, 76},
+ {IT_STRING | IT_SUBMENU, NULL, "Mystery Item Monitor Toggles...", &OP_MonitorToggleDef, 81},
+
+ {IT_HEADER, NULL, "Cooperative", NULL, 90},
+ {IT_STRING | IT_CVAR, NULL, "Players required for exit", &cv_playersforexit, 96},
+ {IT_STRING | IT_CVAR, NULL, "Starposts", &cv_coopstarposts, 101},
+ {IT_STRING | IT_CVAR, NULL, "Life sharing", &cv_cooplives, 106},
+
+ {IT_HEADER, NULL, "Race, Competition", NULL, 115},
+ {IT_STRING | IT_CVAR, NULL, "Level completion countdown", &cv_countdowntime, 121},
+ {IT_STRING | IT_CVAR, NULL, "Item Monitors", &cv_competitionboxes, 126},
+
+ {IT_HEADER, NULL, "Ringslinger (Match, CTF, Tag, H&S)", NULL, 135},
+ {IT_STRING | IT_CVAR, NULL, "Time Limit", &cv_timelimit, 141},
+ {IT_STRING | IT_CVAR, NULL, "Score Limit", &cv_pointlimit, 146},
+ {IT_STRING | IT_CVAR, NULL, "Overtime on Tie", &cv_overtime, 151},
+ {IT_STRING | IT_CVAR, NULL, "Player respawn delay", &cv_respawntime, 156},
+
+ {IT_STRING | IT_CVAR, NULL, "Item Monitors", &cv_matchboxes, 166},
+ {IT_STRING | IT_CVAR, NULL, "Weapon Rings", &cv_specialrings, 171},
+ {IT_STRING | IT_CVAR, NULL, "Power Stones", &cv_powerstones, 176},
+
+ {IT_STRING | IT_CVAR, NULL, "Flag respawn delay", &cv_flagtime, 186},
+ {IT_STRING | IT_CVAR, NULL, "Hiding time", &cv_hidetime, 191},
+
+ {IT_HEADER, NULL, "Teams", NULL, 200},
+ {IT_STRING | IT_CVAR, NULL, "Autobalance sizes", &cv_autobalance, 206},
+ {IT_STRING | IT_CVAR, NULL, "Scramble on Map Change", &cv_scrambleonchange, 211},
#ifndef NONET
- {IT_STRING | IT_CVAR, NULL, "Max Players", &cv_maxplayers, 110},
- {IT_STRING | IT_CVAR, NULL, "Allow players to join", &cv_allownewplayer, 120},
- {IT_STRING | IT_CVAR, NULL, "Allow WAD Downloading", &cv_downloading, 130},
- {IT_STRING | IT_CVAR, NULL, "Attempts to Resynch", &cv_resynchattempts, 140},
+ {IT_HEADER, NULL, "Advanced", NULL, 220},
+ {IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server", &cv_masterserver, 226},
+ {IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 240},
#endif
};
-static menuitem_t OP_NetgameOptionsMenu[] =
-{
- {IT_STRING | IT_CVAR, NULL, "Time Limit", &cv_timelimit, 10},
- {IT_STRING | IT_CVAR, NULL, "Point Limit", &cv_pointlimit, 18},
- {IT_STRING | IT_CVAR, NULL, "Overtime Tie-Breaker", &cv_overtime, 26},
-
- {IT_STRING | IT_CVAR, NULL, "Special Ring Weapons", &cv_specialrings, 42},
- {IT_STRING | IT_CVAR, NULL, "Emeralds", &cv_powerstones, 50},
- {IT_STRING | IT_CVAR, NULL, "Item Boxes", &cv_matchboxes, 58},
- {IT_STRING | IT_CVAR, NULL, "Item Respawn", &cv_itemrespawn, 66},
- {IT_STRING | IT_CVAR, NULL, "Item Respawn time", &cv_itemrespawntime, 74},
-
- {IT_STRING | IT_CVAR, NULL, "Sudden Death", &cv_suddendeath, 90},
- {IT_STRING | IT_CVAR, NULL, "Player respawn delay", &cv_respawntime, 98},
-
- {IT_STRING | IT_CVAR, NULL, "Force Skin", &cv_forceskin, 114},
- {IT_STRING | IT_CVAR, NULL, "Restrict skin changes", &cv_restrictskinchange, 122},
-
- {IT_STRING | IT_CVAR, NULL, "Autobalance Teams", &cv_autobalance, 138},
- {IT_STRING | IT_CVAR, NULL, "Scramble Teams on Map Change", &cv_scrambleonchange, 146},
-};
-
-static menuitem_t OP_GametypeOptionsMenu[] =
-{
- {IT_HEADER, NULL, "CO-OP", NULL, 2},
- {IT_STRING | IT_CVAR, NULL, "Players for exit", &cv_playersforexit, 10},
- {IT_STRING | IT_CVAR, NULL, "Starting Lives", &cv_startinglives, 18},
-
- {IT_HEADER, NULL, "COMPETITION", NULL, 34},
- {IT_STRING | IT_CVAR, NULL, "Item Boxes", &cv_competitionboxes, 42},
- {IT_STRING | IT_CVAR, NULL, "Countdown Time", &cv_countdowntime, 50},
-
- {IT_HEADER, NULL, "RACE", NULL, 66},
- {IT_STRING | IT_CVAR, NULL, "Number of Laps", &cv_numlaps, 74},
- {IT_STRING | IT_CVAR, NULL, "Use Map Lap Counts", &cv_usemapnumlaps, 82},
-
- {IT_HEADER, NULL, "MATCH", NULL, 98},
- {IT_STRING | IT_CVAR, NULL, "Scoring Type", &cv_match_scoring, 106},
-
- {IT_HEADER, NULL, "TAG", NULL, 122},
- {IT_STRING | IT_CVAR, NULL, "Hide Time", &cv_hidetime, 130},
-
- {IT_HEADER, NULL, "CTF", NULL, 146},
- {IT_STRING | IT_CVAR, NULL, "Flag Respawn Time", &cv_flagtime, 154},
-};
-
static menuitem_t OP_MonitorToggleMenu[] =
{
// Printing handled by drawing function
- {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Recycler", &cv_recycler, 20},
- {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Teleporters", &cv_teleporters, 30},
- {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Super Ring", &cv_superring, 40},
- {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Super Sneakers", &cv_supersneakers, 50},
- {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Invincibility", &cv_invincibility, 60},
- {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Jump Shield", &cv_jumpshield, 70},
- {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Elemental Shield", &cv_watershield, 80},
- {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Attraction Shield", &cv_ringshield, 90},
- {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Force Shield", &cv_forceshield, 100},
- {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Armageddon Shield", &cv_bombshield, 110},
- {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "1 Up", &cv_1up, 120},
- {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Eggman Box", &cv_eggmanbox, 130},
+ {IT_STRING|IT_CALL, NULL, "Reset to defaults", M_ResetCvars, 15},
+ {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Recycler", &cv_recycler, 30},
+ {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Teleport", &cv_teleporters, 40},
+ {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Super Ring", &cv_superring, 50},
+ {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Super Sneakers", &cv_supersneakers, 60},
+ {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Invincibility", &cv_invincibility, 70},
+ {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Whirlwind Shield", &cv_jumpshield, 80},
+ {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Elemental Shield", &cv_watershield, 90},
+ {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Attraction Shield", &cv_ringshield, 100},
+ {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Force Shield", &cv_forceshield, 110},
+ {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Armageddon Shield", &cv_bombshield, 120},
+ {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "1 Up", &cv_1up, 130},
+ {IT_STRING|IT_CVAR|IT_CV_INVISSLIDER, NULL, "Eggman Box", &cv_eggmanbox, 140},
};
// ==========================================================================
@@ -1432,6 +1482,18 @@ static menuitem_t OP_MonitorToggleMenu[] =
// Main Menu and related
menu_t MainDef = CENTERMENUSTYLE(NULL, MainMenu, NULL, 72);
+menu_t MISC_AddonsDef =
+{
+ NULL,
+ sizeof (MISC_AddonsMenu)/sizeof (menuitem_t),
+ &MainDef,
+ MISC_AddonsMenu,
+ M_DrawAddons,
+ 50, 28,
+ 0,
+ NULL
+};
+
menu_t MAPauseDef = PAUSEMENUSTYLE(MAPauseMenu, 40, 72);
menu_t SPauseDef = PAUSEMENUSTYLE(SPauseMenu, 40, 72);
menu_t MPauseDef = PAUSEMENUSTYLE(MPauseMenu, 40, 72);
@@ -1494,12 +1556,12 @@ menu_t SR_LevelSelectDef = MAPPLATTERMENUSTYLE(NULL, SR_LevelSelectMenu);
menu_t SR_UnlockChecklistDef =
{
- NULL,
+ "M_SECRET",
1,
&SR_MainDef,
SR_UnlockChecklistMenu,
M_DrawChecklist,
- 280, 185,
+ 30, 30,
0,
NULL
};
@@ -1531,17 +1593,6 @@ menu_t SP_LoadDef =
menu_t SP_LevelSelectDef = MAPPLATTERMENUSTYLE(NULL, SP_LevelSelectMenu);
-menu_t SP_GameStatsDef =
-{
- "M_STATS",
- 1,
- &SP_MainDef,
- SP_GameStatsMenu,
- M_DrawGameStats,
- 280, 185,
- 0,
- NULL
-};
menu_t SP_LevelStatsDef =
{
"M_STATS",
@@ -1662,29 +1713,16 @@ menu_t SP_PlayerDef =
};
// Multiplayer
-menu_t MP_MainDef = DEFAULTMENUSTYLE("M_MULTI", MP_MainMenu, &MainDef, 60, 40);
-
-menu_t MP_ServerDef =
-{
- "M_MULTI",
- sizeof (MP_ServerMenu)/sizeof (menuitem_t),
- &MP_MainDef,
- MP_ServerMenu,
- M_DrawServerMenu,
- 27, 30
-#ifdef NONET
- - 50
-#endif
- ,
- 0,
- NULL
-};
menu_t MP_SplitServerDef =
{
"M_MULTI",
sizeof (MP_SplitServerMenu)/sizeof (menuitem_t),
+#ifndef NONET
&MP_MainDef,
+#else
+ &MainDef,
+#endif
MP_SplitServerMenu,
M_DrawServerMenu,
27, 30 - 50,
@@ -1693,6 +1731,31 @@ menu_t MP_SplitServerDef =
};
#ifndef NONET
+
+menu_t MP_MainDef =
+{
+ "M_MULTI",
+ sizeof (MP_MainMenu)/sizeof (menuitem_t),
+ &MainDef,
+ MP_MainMenu,
+ M_DrawMPMainMenu,
+ 27, 40,
+ 0,
+ M_CancelConnect
+};
+
+menu_t MP_ServerDef =
+{
+ "M_MULTI",
+ sizeof (MP_ServerMenu)/sizeof (menuitem_t),
+ &MP_MainDef,
+ MP_ServerMenu,
+ M_DrawServerMenu,
+ 27, 30,
+ 0,
+ NULL
+};
+
menu_t MP_ConnectDef =
{
"M_MULTI",
@@ -1704,17 +1767,7 @@ menu_t MP_ConnectDef =
0,
M_CancelConnect
};
-menu_t MP_ConnectIPDef =
-{
- "M_MULTI",
- sizeof (MP_ConnectIPMenu)/sizeof (menuitem_t),
- &MP_MainDef,
- MP_ConnectIPMenu,
- M_DrawConnectIPMenu,
- 27,40,
- 0,
- M_CancelConnect
-};
+
menu_t MP_RoomDef =
{
"M_MULTI",
@@ -1732,28 +1785,23 @@ menu_t MP_PlayerSetupDef =
{
"M_SPLAYR",
sizeof (MP_PlayerSetupMenu)/sizeof (menuitem_t),
- &MP_MainDef,
+ &MainDef, // doesn't matter
MP_PlayerSetupMenu,
M_DrawSetupMultiPlayerMenu,
- 27, 40,
+ 19, 22,
0,
M_QuitMultiPlayerMenu
};
// Options
-menu_t OP_MainDef = DEFAULTMENUSTYLE("M_OPTTTL", OP_MainMenu, &MainDef, 60, 30);
-menu_t OP_ControlsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_ControlsMenu, &OP_MainDef, 60, 30);
-menu_t OP_ControlListDef = DEFAULTMENUSTYLE("M_CONTRO", OP_ControlListMenu, &OP_ControlsDef, 60, 30);
-menu_t OP_MoveControlsDef = CONTROLMENUSTYLE(OP_MoveControlsMenu, &OP_ControlListDef);
-menu_t OP_MPControlsDef = CONTROLMENUSTYLE(OP_MPControlsMenu, &OP_ControlListDef);
-menu_t OP_CameraControlsDef = CONTROLMENUSTYLE(OP_CameraControlsMenu, &OP_ControlListDef);
-menu_t OP_MiscControlsDef = CONTROLMENUSTYLE(OP_MiscControlsMenu, &OP_ControlListDef);
-menu_t OP_P1ControlsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_P1ControlsMenu, &OP_ControlsDef, 60, 30);
-menu_t OP_P2ControlsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_P2ControlsMenu, &OP_ControlsDef, 60, 30);
-menu_t OP_MouseOptionsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_MouseOptionsMenu, &OP_P1ControlsDef, 60, 30);
-menu_t OP_Mouse2OptionsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_Mouse2OptionsMenu, &OP_P2ControlsDef, 60, 30);
-menu_t OP_Joystick1Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick1Menu, &OP_P1ControlsDef, 60, 30);
-menu_t OP_Joystick2Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick2Menu, &OP_P2ControlsDef, 60, 30);
+menu_t OP_MainDef = DEFAULTMENUSTYLE("M_OPTTTL", OP_MainMenu, &MainDef, 50, 30);
+menu_t OP_ChangeControlsDef = CONTROLMENUSTYLE(OP_ChangeControlsMenu, &OP_MainDef);
+menu_t OP_P1ControlsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_P1ControlsMenu, &OP_MainDef, 50, 30);
+menu_t OP_P2ControlsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_P2ControlsMenu, &OP_MainDef, 50, 30);
+menu_t OP_MouseOptionsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_MouseOptionsMenu, &OP_P1ControlsDef, 35, 30);
+menu_t OP_Mouse2OptionsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_Mouse2OptionsMenu, &OP_P2ControlsDef, 35, 30);
+menu_t OP_Joystick1Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick1Menu, &OP_P1ControlsDef, 50, 30);
+menu_t OP_Joystick2Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick2Menu, &OP_P2ControlsDef, 50, 30);
menu_t OP_JoystickSetDef =
{
"M_CONTRO",
@@ -1761,12 +1809,22 @@ menu_t OP_JoystickSetDef =
&OP_Joystick1Def,
OP_JoystickSetMenu,
M_DrawJoystick,
- 50, 40,
+ 60, 40,
0,
NULL
};
-menu_t OP_VideoOptionsDef = DEFAULTMENUSTYLE("M_VIDEO", OP_VideoOptionsMenu, &OP_MainDef, 60, 30);
+menu_t OP_VideoOptionsDef =
+{
+ "M_VIDEO",
+ sizeof (OP_VideoOptionsMenu)/sizeof (menuitem_t),
+ &OP_MainDef,
+ OP_VideoOptionsMenu,
+ M_DrawMainVideoMenu,
+ 30, 30,
+ 0,
+ NULL
+};
menu_t OP_VideoModeDef =
{
"M_VIDEO",
@@ -1778,12 +1836,31 @@ menu_t OP_VideoModeDef =
0,
NULL
};
-menu_t OP_SoundOptionsDef = DEFAULTMENUSTYLE("M_SOUND", OP_SoundOptionsMenu, &OP_MainDef, 60, 30);
-menu_t OP_GameOptionsDef = DEFAULTMENUSTYLE("M_GAME", OP_GameOptionsMenu, &OP_MainDef, 30, 30);
-menu_t OP_ServerOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_ServerOptionsMenu, &OP_MainDef, 30, 30);
+menu_t OP_ColorOptionsDef =
+{
+ "M_VIDEO",
+ sizeof (OP_ColorOptionsMenu)/sizeof (menuitem_t),
+ &OP_VideoOptionsDef,
+ OP_ColorOptionsMenu,
+ M_DrawColorMenu,
+ 30, 30,
+ 0,
+ NULL
+};
+menu_t OP_SoundOptionsDef =
+{
+ "M_SOUND",
+ sizeof (OP_SoundOptionsMenu)/sizeof (menuitem_t),
+ &OP_MainDef,
+ OP_SoundOptionsMenu,
+ M_DrawSoundMenu,
+ 30, 30,
+ 0,
+ NULL
+};
+
+menu_t OP_ServerOptionsDef = DEFAULTSCROLLMENUSTYLE("M_SERVER", OP_ServerOptionsMenu, &OP_MainDef, 30, 30);
-menu_t OP_NetgameOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_NetgameOptionsMenu, &OP_ServerOptionsDef, 30, 30);
-menu_t OP_GametypeOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_GametypeOptionsMenu, &OP_ServerOptionsDef, 30, 30);
menu_t OP_MonitorToggleDef =
{
"M_SERVER",
@@ -1825,7 +1902,21 @@ menu_t OP_OpenGLColorDef =
};
#endif
menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_DataOptionsMenu, &OP_MainDef, 60, 30);
-menu_t OP_ScreenshotOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_ScreenshotOptionsMenu, &OP_DataOptionsDef, 30, 30);
+
+menu_t OP_ScreenshotOptionsDef =
+{
+ "M_DATA",
+ sizeof (OP_ScreenshotOptionsMenu)/sizeof (menuitem_t),
+ &OP_DataOptionsDef,
+ OP_ScreenshotOptionsMenu,
+ M_DrawScreenshotMenu,
+ 30, 30,
+ 0,
+ NULL
+};
+
+menu_t OP_AddonsOptionsDef = DEFAULTMENUSTYLE("M_ADDONS", OP_AddonsOptionsMenu, &OP_DataOptionsDef, 30, 30);
+
menu_t OP_EraseDataDef = DEFAULTMENUSTYLE("M_DATA", OP_EraseDataMenu, &OP_DataOptionsDef, 60, 30);
// ==========================================================================
@@ -2044,6 +2135,12 @@ void Moviemode_mode_Onchange(void)
OP_ScreenshotOptionsMenu[i].status = IT_STRING|IT_CVAR;
}
+void Addons_option_Onchange(void)
+{
+ OP_AddonsOptionsMenu[op_addons_folder].status =
+ (cv_addons_option.value == 3 ? IT_CVAR|IT_STRING|IT_CV_STRING : IT_DISABLED);
+}
+
// ==========================================================================
// END ORGANIZATION STUFF.
// ==========================================================================
@@ -2106,9 +2203,12 @@ static void M_ChangeCvar(INT32 choice)
static boolean M_ChangeStringCvar(INT32 choice)
{
consvar_t *cv = (consvar_t *)currentMenu->menuitems[itemOn].itemaction;
- char buf[255];
+ char buf[MAXSTRINGLENGTH];
size_t len;
+ if (shiftdown && choice >= 32 && choice <= 127)
+ choice = shiftxform[choice];
+
switch (choice)
{
case KEY_BACKSPACE:
@@ -2138,6 +2238,19 @@ static boolean M_ChangeStringCvar(INT32 choice)
return false;
}
+// resets all cvars on a menu - assumes that all that have itemactions are cvars
+static void M_ResetCvars(void)
+{
+ INT32 i;
+ consvar_t *cv;
+ for (i = 0; i < currentMenu->numitems; i++)
+ {
+ if (!(currentMenu->menuitems[i].status & IT_CVAR) || !(cv = (consvar_t *)currentMenu->menuitems[i].itemaction))
+ continue;
+ CV_SetValue(cv, atoi(cv->defaultvalue));
+ }
+}
+
static void M_NextOpt(void)
{
INT16 oldItemOn = itemOn; // prevent infinite loop
@@ -2342,7 +2455,7 @@ boolean M_Responder(event_t *ev)
return true;
case KEY_F11: // Gamma Level
- CV_AddValue(&cv_usegamma, 1);
+ CV_AddValue(&cv_globalgamma, 1);
return true;
// Spymode on F12 handled in game logic
@@ -2406,8 +2519,6 @@ boolean M_Responder(event_t *ev)
{
if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_STRING)
{
- if (shiftdown && ch >= 32 && ch <= 127)
- ch = shiftxform[ch];
if (M_ChangeStringCvar(ch))
return true;
else
@@ -2444,8 +2555,7 @@ boolean M_Responder(event_t *ev)
if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS
|| (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR))
{
- if (currentMenu != &OP_SoundOptionsDef)
- S_StartSound(NULL, sfx_menu1);
+ S_StartSound(NULL, sfx_menu1);
routine(0);
}
return true;
@@ -2454,8 +2564,7 @@ boolean M_Responder(event_t *ev)
if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS
|| (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR))
{
- if (currentMenu != &OP_SoundOptionsDef)
- S_StartSound(NULL, sfx_menu1);
+ S_StartSound(NULL, sfx_menu1);
routine(1);
}
return true;
@@ -2507,6 +2616,7 @@ boolean M_Responder(event_t *ev)
{
// detach any keys associated with the game control
G_ClearControlKeys(setupcontrols, currentMenu->menuitems[itemOn].alphaKey);
+ S_StartSound(NULL, sfx_shldls);
return true;
}
// Why _does_ backspace go back anyway?
@@ -2654,6 +2764,7 @@ void M_StartControlPanel(void)
else // multiplayer
{
MPauseMenu[mpause_switchmap].status = IT_DISABLED;
+ MPauseMenu[mpause_addons].status = IT_DISABLED;
MPauseMenu[mpause_scramble].status = IT_DISABLED;
MPauseMenu[mpause_psetupsplit].status = IT_DISABLED;
MPauseMenu[mpause_psetupsplit2].status = IT_DISABLED;
@@ -2665,15 +2776,20 @@ void M_StartControlPanel(void)
if ((server || adminplayer == consoleplayer))
{
MPauseMenu[mpause_switchmap].status = IT_STRING | IT_CALL;
+ MPauseMenu[mpause_addons].status = IT_STRING | IT_CALL;
if (G_GametypeHasTeams())
MPauseMenu[mpause_scramble].status = IT_STRING | IT_SUBMENU;
}
if (splitscreen)
+ {
MPauseMenu[mpause_psetupsplit].status = MPauseMenu[mpause_psetupsplit2].status = IT_STRING | IT_CALL;
+ MPauseMenu[mpause_psetup].text = "Player 1 Setup";
+ }
else
{
MPauseMenu[mpause_psetup].status = IT_STRING | IT_CALL;
+ MPauseMenu[mpause_psetup].text = "Player Setup";
if (G_GametypeHasTeams())
MPauseMenu[mpause_switchteam].status = IT_STRING | IT_SUBMENU;
@@ -2822,15 +2938,14 @@ void M_Init(void)
#ifdef HWRENDER
// Permanently hide some options based on render mode
if (rendermode == render_soft)
- OP_VideoOptionsMenu[1].status = IT_DISABLED;
+ OP_VideoOptionsMenu[4].status = IT_DISABLED;
+ else if (rendermode == render_opengl)
+ OP_ScreenshotOptionsMenu[op_screenshot_colorprofile].status = IT_GRAYEDOUT;
#endif
#ifndef NONET
CV_RegisterVar(&cv_serversort);
#endif
-
- //todo put this somewhere better...
- CV_RegisterVar(&cv_allcaps);
}
// ==========================================================================
@@ -2889,36 +3004,58 @@ static void M_DrawThermo(INT32 x, INT32 y, consvar_t *cv)
}
// A smaller 'Thermo', with range given as percents (0-100)
-static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv)
+static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv, boolean ontop)
{
INT32 i;
INT32 range;
patch_t *p;
+ x = BASEVIDWIDTH - x - SLIDER_WIDTH;
+
+ V_DrawScaledPatch(x, y, 0, W_CachePatchName("M_SLIDEL", PU_CACHE));
+
+ p = W_CachePatchName("M_SLIDEM", PU_CACHE);
+ for (i = 1; i < SLIDER_RANGE; i++)
+ V_DrawScaledPatch (x+i*8, y, 0,p);
+
+ if (ontop)
+ {
+ V_DrawCharacter(x - 6 - (skullAnimCounter/5), y,
+ '\x1C' | V_YELLOWMAP, false);
+ V_DrawCharacter(x+i*8 + 8 + (skullAnimCounter/5), y,
+ '\x1D' | V_YELLOWMAP, false);
+ }
+
+ p = W_CachePatchName("M_SLIDER", PU_CACHE);
+ V_DrawScaledPatch(x+i*8, y, 0, p);
+
+ // draw the slider cursor
+ p = W_CachePatchName("M_SLIDEC", PU_CACHE);
+
for (i = 0; cv->PossibleValue[i+1].strvalue; i++);
+ if ((range = atoi(cv->defaultvalue)) != cv->value)
+ {
+ range = ((range - cv->PossibleValue[0].value) * 100 /
+ (cv->PossibleValue[i].value - cv->PossibleValue[0].value));
+
+ if (range < 0)
+ range = 0;
+ else if (range > 100)
+ range = 100;
+
+ V_DrawMappedPatch(x + 2 + (SLIDER_RANGE*8*range)/100, y, V_TRANSLUCENT, p, yellowmap);
+ }
+
range = ((cv->value - cv->PossibleValue[0].value) * 100 /
(cv->PossibleValue[i].value - cv->PossibleValue[0].value));
if (range < 0)
range = 0;
- if (range > 100)
+ else if (range > 100)
range = 100;
- x = BASEVIDWIDTH - x - SLIDER_WIDTH;
-
- V_DrawScaledPatch(x - 8, y, 0, W_CachePatchName("M_SLIDEL", PU_CACHE));
-
- p = W_CachePatchName("M_SLIDEM", PU_CACHE);
- for (i = 0; i < SLIDER_RANGE; i++)
- V_DrawScaledPatch (x+i*8, y, 0,p);
-
- p = W_CachePatchName("M_SLIDER", PU_CACHE);
- V_DrawScaledPatch(x+SLIDER_RANGE*8, y, 0, p);
-
- // draw the slider cursor
- p = W_CachePatchName("M_SLIDEC", PU_CACHE);
- V_DrawMappedPatch(x + ((SLIDER_RANGE-1)*8*range)/100, y, 0, p, yellowmap);
+ V_DrawMappedPatch(x + 2 + (SLIDER_RANGE*8*range)/100, y, 0, p, yellowmap);
}
//
@@ -3138,7 +3275,7 @@ static void M_DrawGenericMenu(void)
switch (currentMenu->menuitems[i].status & IT_CVARTYPE)
{
case IT_CV_SLIDER:
- M_DrawSlider(x, y, cv);
+ M_DrawSlider(x, y, cv, (i == itemOn));
case IT_CV_NOPRINT: // color use this
case IT_CV_INVISSLIDER: // monitor toggles use this
break;
@@ -3151,8 +3288,15 @@ static void M_DrawGenericMenu(void)
y += 16;
break;
default:
- V_DrawString(BASEVIDWIDTH - x - V_StringWidth(cv->string, 0), y,
+ V_DrawRightAlignedString(BASEVIDWIDTH - x, y,
((cv->flags & CV_CHEAT) && !CV_IsSetToDefault(cv) ? V_REDMAP : V_YELLOWMAP), cv->string);
+ if (i == itemOn)
+ {
+ V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(cv->string, 0) - (skullAnimCounter/5), y,
+ '\x1C' | V_YELLOWMAP, false);
+ V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y,
+ '\x1D' | V_YELLOWMAP, false);
+ }
break;
}
break;
@@ -3188,7 +3332,8 @@ static void M_DrawGenericMenu(void)
if (currentMenu->menuitems[i].alphaKey)
y = currentMenu->y+currentMenu->menuitems[i].alphaKey;
- V_DrawString(x-16, y, V_YELLOWMAP, currentMenu->menuitems[i].text);
+ //V_DrawString(x-16, y, V_YELLOWMAP, currentMenu->menuitems[i].text);
+ M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), currentMenu->menuitems[i].text, true, false);
y += SMALLLINEHEIGHT;
break;
}
@@ -3209,6 +3354,142 @@ static void M_DrawGenericMenu(void)
}
}
+#define scrollareaheight 72
+
+// note that alphakey is multiplied by 2 for scrolling menus to allow greater usage in UINT8 range.
+static void M_DrawGenericScrollMenu(void)
+{
+ INT32 x, y, i, max, bottom, tempcentery, cursory = 0;
+
+ // DRAW MENU
+ x = currentMenu->x;
+ y = currentMenu->y;
+
+ if ((currentMenu->menuitems[itemOn].alphaKey*2 - currentMenu->menuitems[0].alphaKey*2) <= scrollareaheight)
+ tempcentery = currentMenu->y - currentMenu->menuitems[0].alphaKey*2;
+ else if ((currentMenu->menuitems[currentMenu->numitems-1].alphaKey*2 - currentMenu->menuitems[itemOn].alphaKey*2) <= scrollareaheight)
+ tempcentery = currentMenu->y - currentMenu->menuitems[currentMenu->numitems-1].alphaKey*2 + 2*scrollareaheight;
+ else
+ tempcentery = currentMenu->y - currentMenu->menuitems[itemOn].alphaKey*2 + scrollareaheight;
+
+ for (i = 0; i < currentMenu->numitems; i++)
+ {
+ if (currentMenu->menuitems[i].status != IT_DISABLED && currentMenu->menuitems[i].alphaKey*2 + tempcentery >= currentMenu->y)
+ break;
+ }
+
+ for (bottom = currentMenu->numitems; bottom > 0; bottom--)
+ {
+ if (currentMenu->menuitems[bottom-1].status != IT_DISABLED)
+ break;
+ }
+
+ for (max = bottom; max > 0; max--)
+ {
+ if (currentMenu->menuitems[max-1].status != IT_DISABLED && currentMenu->menuitems[max-1].alphaKey*2 + tempcentery <= (currentMenu->y + 2*scrollareaheight))
+ break;
+ }
+
+ if (i)
+ V_DrawString(currentMenu->x - 20, currentMenu->y - (skullAnimCounter/5), V_YELLOWMAP, "\x1A"); // up arrow
+ if (max != bottom)
+ V_DrawString(currentMenu->x - 20, currentMenu->y + 2*scrollareaheight + (skullAnimCounter/5), V_YELLOWMAP, "\x1B"); // down arrow
+
+ // draw title (or big pic)
+ M_DrawMenuTitle();
+
+ for (; i < max; i++)
+ {
+ y = currentMenu->menuitems[i].alphaKey*2 + tempcentery;
+ if (i == itemOn)
+ cursory = y;
+ switch (currentMenu->menuitems[i].status & IT_DISPLAY)
+ {
+ case IT_PATCH:
+ case IT_DYBIGSPACE:
+ case IT_BIGSLIDER:
+ case IT_STRING2:
+ case IT_DYLITLSPACE:
+ case IT_GRAYPATCH:
+ case IT_TRANSTEXT2:
+ // unsupported
+ break;
+ case IT_NOTHING:
+ break;
+ case IT_STRING:
+ case IT_WHITESTRING:
+ if (i != itemOn && (currentMenu->menuitems[i].status & IT_DISPLAY)==IT_STRING)
+ V_DrawString(x, y, 0, currentMenu->menuitems[i].text);
+ else
+ V_DrawString(x, y, V_YELLOWMAP, currentMenu->menuitems[i].text);
+
+ // Cvar specific handling
+ switch (currentMenu->menuitems[i].status & IT_TYPE)
+ case IT_CVAR:
+ {
+ consvar_t *cv = (consvar_t *)currentMenu->menuitems[i].itemaction;
+ switch (currentMenu->menuitems[i].status & IT_CVARTYPE)
+ {
+ case IT_CV_SLIDER:
+ M_DrawSlider(x, y, cv, (i == itemOn));
+ case IT_CV_NOPRINT: // color use this
+ case IT_CV_INVISSLIDER: // monitor toggles use this
+ break;
+ case IT_CV_STRING:
+#if 1
+ if (y + 12 > (currentMenu->y + 2*scrollareaheight))
+ break;
+ M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1);
+ V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, cv->string);
+ if (skullAnimCounter < 4 && i == itemOn)
+ V_DrawCharacter(x + 8 + V_StringWidth(cv->string, 0), y + 12,
+ '_' | 0x80, false);
+#else // cool new string type stuff, not ready for limelight
+ if (i == itemOn)
+ {
+ V_DrawFill(x-2, y-1, MAXSTRINGLENGTH*8 + 4, 8+3, 159);
+ V_DrawString(x, y, V_ALLOWLOWERCASE, cv->string);
+ if (skullAnimCounter < 4)
+ V_DrawCharacter(x + V_StringWidth(cv->string, 0), y, '_' | 0x80, false);
+ }
+ else
+ V_DrawRightAlignedString(BASEVIDWIDTH - x, y,
+ V_YELLOWMAP|V_ALLOWLOWERCASE, cv->string);
+#endif
+ break;
+ default:
+ V_DrawRightAlignedString(BASEVIDWIDTH - x, y,
+ ((cv->flags & CV_CHEAT) && !CV_IsSetToDefault(cv) ? V_REDMAP : V_YELLOWMAP), cv->string);
+ if (i == itemOn)
+ {
+ V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(cv->string, 0) - (skullAnimCounter/5), y,
+ '\x1C' | V_YELLOWMAP, false);
+ V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y,
+ '\x1D' | V_YELLOWMAP, false);
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ case IT_TRANSTEXT:
+ V_DrawString(x, y, V_TRANSLUCENT, currentMenu->menuitems[i].text);
+ break;
+ case IT_QUESTIONMARKS:
+ V_DrawString(x, y, V_TRANSLUCENT|V_OLDSPACING, M_CreateSecretMenuOption(currentMenu->menuitems[i].text));
+ break;
+ case IT_HEADERTEXT:
+ //V_DrawString(x-16, y, V_YELLOWMAP, currentMenu->menuitems[i].text);
+ M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), currentMenu->menuitems[i].text, true, false);
+ break;
+ }
+ }
+
+ // DRAW THE SKULL CURSOR
+ V_DrawScaledPatch(currentMenu->x - 24, cursory, 0,
+ W_CachePatchName("M_CURSOR", PU_CACHE));
+}
+
static void M_DrawPauseMenu(void)
{
if (!netgame && !multiplayer && (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION))
@@ -3413,7 +3694,7 @@ static void M_DrawCenteredMenu(void)
switch(currentMenu->menuitems[i].status & IT_CVARTYPE)
{
case IT_CV_SLIDER:
- M_DrawSlider(x, y, cv);
+ M_DrawSlider(x, y, cv, (i == itemOn));
case IT_CV_NOPRINT: // color use this
break;
case IT_CV_STRING:
@@ -3427,6 +3708,13 @@ static void M_DrawCenteredMenu(void)
default:
V_DrawString(BASEVIDWIDTH - x - V_StringWidth(cv->string, 0), y,
((cv->flags & CV_CHEAT) && !CV_IsSetToDefault(cv) ? V_REDMAP : V_YELLOWMAP), cv->string);
+ if (i == itemOn)
+ {
+ V_DrawCharacter(BASEVIDWIDTH - x - 10 - V_StringWidth(cv->string, 0) - (skullAnimCounter/5), y,
+ '\x1C' | V_YELLOWMAP, false);
+ V_DrawCharacter(BASEVIDWIDTH - x + 2 + (skullAnimCounter/5), y,
+ '\x1D' | V_YELLOWMAP, false);
+ }
break;
}
break;
@@ -3709,7 +3997,7 @@ static boolean M_PrepareLevelPlatter(INT32 gt)
I_Error("Insufficient memory to prepare level platter");
// done here so lsrow and lscol can be set if cv_nextmap is on the platter
- lsrow = lscol = lstic = lshli = lsoffs[0] = lsoffs[1] = 0;
+ lsrow = lscol = lshli = lsoffs[0] = lsoffs[1] = 0;
while (mapnum < NUMMAPS)
{
@@ -3932,6 +4220,8 @@ static void M_HandleLevelPlatter(INT32 choice)
M_SetupNextMenu(currentMenu->prevMenu->prevMenu);
else
M_ChangeLevel(0);
+ Z_Free(levelselect.rows);
+ levelselect.rows = NULL;
}
else
M_LevelSelectWarp(0);
@@ -3961,13 +4251,15 @@ static void M_HandleLevelPlatter(INT32 choice)
}
else
M_ClearMenus(true);
+ Z_Free(levelselect.rows);
+ levelselect.rows = NULL;
}
}
-static void M_DrawLevelPlatterHeader(INT32 y, const char *header, boolean headerhighlight)
+void M_DrawLevelPlatterHeader(INT32 y, const char *header, boolean headerhighlight, boolean allowlowercase)
{
y += lsheadingheight - 12;
- V_DrawString(19, y, (headerhighlight ? V_YELLOWMAP : 0), header);
+ V_DrawString(19, y, (headerhighlight ? V_YELLOWMAP : 0)|(allowlowercase ? V_ALLOWLOWERCASE : 0), header);
y += 9;
if ((y >= 0) && (y < 200))
{
@@ -3976,10 +4268,7 @@ static void M_DrawLevelPlatterHeader(INT32 y, const char *header, boolean header
}
y++;
if ((y >= 0) && (y < 200))
- {
V_DrawFill(19, y, 282, 1, 26);
- }
- y += 2;
}
static void M_DrawLevelPlatterWideMap(UINT8 row, UINT8 col, INT32 x, INT32 y, boolean highlight)
@@ -4073,7 +4362,7 @@ static void M_DrawLevelPlatterRow(UINT8 row, INT32 y)
const boolean rowhighlight = (row == lsrow);
if (levelselect.rows[row].header[0])
{
- M_DrawLevelPlatterHeader(y, levelselect.rows[row].header, (rowhighlight || (row == lshli)));
+ M_DrawLevelPlatterHeader(y, levelselect.rows[row].header, (rowhighlight || (row == lshli)), false);
y += lsheadingheight;
}
@@ -4092,9 +4381,6 @@ static void M_DrawLevelPlatterMenu(void)
INT32 y = lsbasey + lsoffs[0] - getheadingoffset(lsrow);
const INT32 cursorx = (sizeselect ? 0 : (lscol*lshseperation));
- if (++lstic == 32)
- lstic = 0;
-
if (gamestate == GS_TIMEATTACK)
V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE));
@@ -4114,7 +4400,7 @@ static void M_DrawLevelPlatterMenu(void)
}
// draw cursor box
- V_DrawSmallScaledPatch(lsbasex + cursorx + lsoffs[1], lsbasey, 0, ((lstic & 8) ? levselp[sizeselect][0] : levselp[sizeselect][1]));
+ V_DrawSmallScaledPatch(lsbasex + cursorx + lsoffs[1], lsbasey, 0, (levselp[sizeselect][((skullAnimCounter/4) ? 1 : 0)]));
if (levelselect.rows[lsrow].maplist[lscol])
V_DrawScaledPatch(lsbasex + cursorx-17, lsbasey+50+lsoffs[0], 0, W_CachePatchName("M_CURSOR", PU_CACHE));
@@ -4414,6 +4700,511 @@ static void M_HandleImageDef(INT32 choice)
// MISC MAIN MENU OPTIONS
// ======================
+static void M_AddonsOptions(INT32 choice)
+{
+ (void)choice;
+ Addons_option_Onchange();
+
+ M_SetupNextMenu(&OP_AddonsOptionsDef);
+}
+
+#define LOCATIONSTRING "Visit \x83SRB2.ORG/MODS\x80 to get & make add-ons!"
+
+static void M_Addons(INT32 choice)
+{
+ const char *pathname = ".";
+
+ (void)choice;
+
+ /*if (cv_addons_option.value == 0)
+ pathname = srb2home; usehome ? srb2home : srb2path;
+ else if (cv_addons_option.value == 1)
+ pathname = srb2home;
+ else if (cv_addons_option.value == 2)
+ pathname = srb2path;
+ else*/
+ if (cv_addons_option.value == 3 && *cv_addons_folder.string != '\0')
+ pathname = cv_addons_folder.string;
+
+ strlcpy(menupath, pathname, 1024);
+ menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath) + 1;
+
+ if (menupath[menupathindex[menudepthleft]-2] != '/')
+ {
+ menupath[menupathindex[menudepthleft]-1] = '/';
+ menupath[menupathindex[menudepthleft]] = 0;
+ }
+ else
+ --menupathindex[menudepthleft];
+
+ if (!preparefilemenu(false))
+ {
+ M_StartMessage(M_GetText("No files/folders found.\n\n"LOCATIONSTRING"\n\n(Press a key)\n"),NULL,MM_NOTHING);
+ return;
+ }
+ else
+ dir_on[menudepthleft] = 0;
+
+ if (addonsp[0]) // never going to have some provided but not all, saves individually checking
+ {
+ size_t i;
+ for (i = 0; i < NUM_EXT+6; i++)
+ W_UnlockCachedPatch(addonsp[i]);
+ }
+
+ addonsp[EXT_FOLDER] = W_CachePatchName("M_FFLDR", PU_STATIC);
+ addonsp[EXT_UP] = W_CachePatchName("M_FBACK", PU_STATIC);
+ addonsp[EXT_NORESULTS] = W_CachePatchName("M_FNOPE", PU_STATIC);
+ addonsp[EXT_TXT] = W_CachePatchName("M_FTXT", PU_STATIC);
+ addonsp[EXT_CFG] = W_CachePatchName("M_FCFG", PU_STATIC);
+ addonsp[EXT_WAD] = W_CachePatchName("M_FWAD", PU_STATIC);
+ addonsp[EXT_SOC] = W_CachePatchName("M_FSOC", PU_STATIC);
+ addonsp[EXT_LUA] = W_CachePatchName("M_FLUA", PU_STATIC);
+ addonsp[NUM_EXT] = W_CachePatchName("M_FUNKN", PU_STATIC);
+ addonsp[NUM_EXT+1] = W_CachePatchName("M_FSEL1", PU_STATIC);
+ addonsp[NUM_EXT+2] = W_CachePatchName("M_FSEL2", PU_STATIC);
+ addonsp[NUM_EXT+3] = W_CachePatchName("M_FLOAD", PU_STATIC);
+ addonsp[NUM_EXT+4] = W_CachePatchName("M_FSRCH", PU_STATIC);
+ addonsp[NUM_EXT+5] = W_CachePatchName("M_FSAVE", PU_STATIC);
+
+ MISC_AddonsDef.prevMenu = currentMenu;
+ M_SetupNextMenu(&MISC_AddonsDef);
+}
+
+#define width 4
+#define vpadding 27
+#define h (BASEVIDHEIGHT-(2*vpadding))
+#define NUMCOLOURS 8 // when toast's coding it's british english hacker fucker
+static void M_DrawTemperature(INT32 x, fixed_t t)
+{
+ INT32 y;
+
+ // bounds check
+ if (t > FRACUNIT)
+ t = FRACUNIT;
+ /*else if (t < 0) -- not needed
+ t = 0;*/
+
+ // scale
+ if (t > 1)
+ t = (FixedMul(h<>FRACBITS);
+
+ // border
+ V_DrawFill(x - 1, vpadding, 1, h, 3);
+ V_DrawFill(x + width, vpadding, 1, h, 3);
+ V_DrawFill(x - 1, vpadding-1, width+2, 1, 3);
+ V_DrawFill(x - 1, vpadding+h, width+2, 1, 3);
+
+ // bar itself
+ y = h;
+ if (t)
+ for (t = h - t; y > 0; y--)
+ {
+ UINT8 colours[NUMCOLOURS] = {42, 40, 58, 222, 65, 90, 97, 98};
+ UINT8 c;
+ if (y <= t) break;
+ if (y+vpadding >= BASEVIDHEIGHT/2)
+ c = 113;
+ else
+ c = colours[(NUMCOLOURS*(y-1))/(h/2)];
+ V_DrawFill(x, y-1 + vpadding, width, 1, c);
+ }
+
+ // fill the rest of the backing
+ if (y)
+ V_DrawFill(x, vpadding, width, y, 27);
+}
+#undef width
+#undef vpadding
+#undef h
+#undef NUMCOLOURS
+
+static char *M_AddonsHeaderPath(void)
+{
+ UINT32 len;
+ static char header[1024];
+
+ if (menupath[0] == '.')
+ strlcpy(header, va("SRB2 folder%s", menupath+1), 1024);
+ else
+ strcpy(header, menupath);
+
+ len = strlen(header);
+ if (len > 34)
+ {
+ len = len-34;
+ header[len] = header[len+1] = header[len+2] = '.';
+ }
+ else
+ len = 0;
+
+ return header+len;
+}
+
+#define UNEXIST S_StartSound(NULL, sfx_lose);\
+ M_SetupNextMenu(MISC_AddonsDef.prevMenu);\
+ M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING)
+
+// returns whether to do message draw
+static boolean M_AddonsRefresh(void)
+{
+ if ((refreshdirmenu & REFRESHDIR_NORMAL) && !preparefilemenu(true))
+ {
+ UNEXIST;
+ return true;
+ }
+
+ if (refreshdirmenu & REFRESHDIR_ADDFILE)
+ {
+ addonsresponselimit = 0;
+
+ if (refreshdirmenu & REFRESHDIR_NOTLOADED)
+ {
+ char *message = NULL;
+ S_StartSound(NULL, sfx_lose);
+ if (refreshdirmenu & REFRESHDIR_MAX)
+ message = va("\x82%s\x80\nMaximum number of add-ons reached.\nThis file could not be loaded.\nIf you want to play with this add-on, restart the game to clear existing ones.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING);
+ else
+ message = va("\x82%s\x80\nThe file was not loaded.\nCheck the console log for more information.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING);
+ M_StartMessage(message,NULL,MM_NOTHING);
+ return true;
+ }
+
+ if (refreshdirmenu & (REFRESHDIR_WARNING|REFRESHDIR_ERROR))
+ {
+ S_StartSound(NULL, sfx_skid);
+ M_StartMessage(va("\x82%s\x80\nThe file was loaded with %s.\nCheck the console log for more information.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING, ((refreshdirmenu & REFRESHDIR_ERROR) ? "errors" : "warnings")),NULL,MM_NOTHING);
+ return true;
+ }
+
+ S_StartSound(NULL, sfx_strpst);
+ }
+
+ return false;
+}
+
+#define offs 1
+
+static void M_DrawAddons(void)
+{
+ INT32 x, y;
+ ssize_t i, max;
+
+ // hack - need to refresh at end of frame to handle addfile...
+ if (refreshdirmenu & M_AddonsRefresh())
+ return M_DrawMessageMenu();
+
+ if (addonsresponselimit)
+ addonsresponselimit--;
+
+ V_DrawCenteredString(BASEVIDWIDTH/2, 4+offs, 0, (Playing()
+ ? "\x85""Adding files mid-game may cause problems."
+ : LOCATIONSTRING));
+
+ if (numwadfiles <= mainwads+1)
+ y = 0;
+ else if (numwadfiles >= MAX_WADFILES)
+ y = FRACUNIT;
+ else
+ {
+ x = FixedDiv((numwadfiles - mainwads+1)< y)
+ y = x;
+ if (y > FRACUNIT) // happens because of how we're shrinkin' it a little
+ y = FRACUNIT;
+ }
+
+ M_DrawTemperature(BASEVIDWIDTH - 19 - 5, y);
+
+ // DRAW MENU
+ x = currentMenu->x;
+ y = currentMenu->y + offs;
+
+ //M_DrawLevelPlatterHeader(y - 16, M_AddonsHeaderPath(), true, true); -- wanted different width
+ V_DrawString(x-21, (y - 16) + (lsheadingheight - 12), V_YELLOWMAP|V_ALLOWLOWERCASE, M_AddonsHeaderPath());
+ V_DrawFill(x-21, (y - 16) + (lsheadingheight - 3), (MAXSTRINGLENGTH*8+6 - 1), 1, yellowmap[3]);
+ V_DrawFill(x-21 + (MAXSTRINGLENGTH*8+6 - 1), (y - 16) + (lsheadingheight - 3), 1, 1, 26);
+ V_DrawFill(x-21, (y - 16) + (lsheadingheight - 2), MAXSTRINGLENGTH*8+6, 1, 26);
+
+ V_DrawFill(x - 21, y - 1, MAXSTRINGLENGTH*8+6, (BASEVIDHEIGHT - currentMenu->y + 1 + offs) - (y - 1), 159);
+
+ // get bottom...
+ max = dir_on[menudepthleft] + numaddonsshown + 1;
+ if (max > (ssize_t)sizedirmenu)
+ max = sizedirmenu;
+
+ // then top...
+ i = max - (2*numaddonsshown + 1);
+
+ // then adjust!
+ if (i < 0)
+ {
+ if ((max -= i) > (ssize_t)sizedirmenu)
+ max = sizedirmenu;
+ i = 0;
+ }
+
+ if (i != 0)
+ V_DrawString(19, y+4 - (skullAnimCounter/5), V_YELLOWMAP, "\x1A");
+
+ for (; i < max; i++)
+ {
+ UINT32 flags = V_ALLOWLOWERCASE;
+ if (y > BASEVIDHEIGHT) break;
+ if (dirmenu[i])
+#define type (UINT8)(dirmenu[i][DIR_TYPE])
+ {
+ if (type & EXT_LOADED)
+ flags |= V_TRANSLUCENT;
+
+ V_DrawSmallScaledPatch(x-(16+4), y, (flags & V_TRANSLUCENT), addonsp[((UINT8)(dirmenu[i][DIR_TYPE]) & ~EXT_LOADED)]);
+
+ if (type & EXT_LOADED)
+ V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+3]);
+
+ if ((size_t)i == dir_on[menudepthleft])
+ {
+ V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+1+((skullAnimCounter/4) ? 1 : 0)]);
+ flags = V_ALLOWLOWERCASE|V_YELLOWMAP;
+ }
+
+#define charsonside 14
+ if (dirmenu[i][DIR_LEN] > (charsonside*2 + 3))
+ V_DrawString(x, y+4, flags, va("%.*s...%s", charsonside, dirmenu[i]+DIR_STRING, dirmenu[i]+DIR_STRING+dirmenu[i][DIR_LEN]-(charsonside+1)));
+#undef charsonside
+ else
+ V_DrawString(x, y+4, flags, dirmenu[i]+DIR_STRING);
+ }
+#undef type
+ y += 16;
+ }
+
+ if (max != (ssize_t)sizedirmenu)
+ V_DrawString(19, y-12 + (skullAnimCounter/5), V_YELLOWMAP, "\x1B");
+
+ y = BASEVIDHEIGHT - currentMenu->y + offs;
+
+ M_DrawTextBox(x - (21 + 5), y, MAXSTRINGLENGTH, 1);
+ if (menusearch[0])
+ V_DrawString(x - 18, y + 8, V_ALLOWLOWERCASE, menusearch+1);
+ else
+ V_DrawString(x - 18, y + 8, V_ALLOWLOWERCASE|V_TRANSLUCENT, "Type to search...");
+ if (skullAnimCounter < 4)
+ V_DrawCharacter(x - 18 + V_StringWidth(menusearch+1, 0), y + 8,
+ '_' | 0x80, false);
+
+ x -= (21 + 5 + 16);
+ V_DrawSmallScaledPatch(x, y + 4, (menusearch[0] ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+4]);
+
+#define CANSAVE (!modifiedgame || savemoddata)
+ x = BASEVIDWIDTH - x - 16;
+ V_DrawSmallScaledPatch(x, y + 4, (CANSAVE ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+5]);
+
+ if CANSAVE
+ V_DrawSmallScaledPatch(x, y + 4, 0, addonsp[NUM_EXT+3]);
+#undef CANSAVE
+}
+
+#undef offs
+
+static void M_AddonExec(INT32 ch)
+{
+ if (ch != 'y' && ch != KEY_ENTER)
+ return;
+
+ S_StartSound(NULL, sfx_zoom);
+ COM_BufAddText(va("exec %s%s", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING));
+}
+
+#define len menusearch[0]
+static boolean M_ChangeStringAddons(INT32 choice)
+{
+ if (shiftdown && choice >= 32 && choice <= 127)
+ choice = shiftxform[choice];
+
+ switch (choice)
+ {
+ case KEY_DEL:
+ if (len)
+ {
+ len = menusearch[1] = 0;
+ return true;
+ }
+ break;
+ case KEY_BACKSPACE:
+ if (len)
+ {
+ menusearch[1+--len] = 0;
+ return true;
+ }
+ break;
+ default:
+ if (choice >= 32 && choice <= 127)
+ {
+ if (len < MAXSTRINGLENGTH - 1)
+ {
+ menusearch[1+len++] = (char)choice;
+ menusearch[1+len] = 0;
+ return true;
+ }
+ }
+ break;
+ }
+ return false;
+}
+#undef len
+
+static void M_HandleAddons(INT32 choice)
+{
+ boolean exitmenu = false; // exit to previous menu
+
+ if (addonsresponselimit)
+ return;
+
+ if (M_ChangeStringAddons(choice))
+ {
+ if (!preparefilemenu(true))
+ {
+ UNEXIST;
+ return;
+ }
+ }
+
+ switch (choice)
+ {
+ case KEY_DOWNARROW:
+ if (dir_on[menudepthleft] < sizedirmenu-1)
+ dir_on[menudepthleft]++;
+ S_StartSound(NULL, sfx_menu1);
+ break;
+ case KEY_UPARROW:
+ if (dir_on[menudepthleft])
+ dir_on[menudepthleft]--;
+ S_StartSound(NULL, sfx_menu1);
+ break;
+ case KEY_PGDN:
+ {
+ UINT8 i;
+ for (i = numaddonsshown; i && (dir_on[menudepthleft] < sizedirmenu-1); i--)
+ dir_on[menudepthleft]++;
+ }
+ S_StartSound(NULL, sfx_menu1);
+ break;
+ case KEY_PGUP:
+ {
+ UINT8 i;
+ for (i = numaddonsshown; i && (dir_on[menudepthleft]); i--)
+ dir_on[menudepthleft]--;
+ }
+ S_StartSound(NULL, sfx_menu1);
+ break;
+ case KEY_ENTER:
+ {
+ boolean refresh = true;
+ if (!dirmenu[dir_on[menudepthleft]])
+ S_StartSound(NULL, sfx_lose);
+ else
+ {
+ switch (dirmenu[dir_on[menudepthleft]][DIR_TYPE])
+ {
+ case EXT_FOLDER:
+ strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+DIR_STRING);
+ if (menudepthleft)
+ {
+ menupathindex[--menudepthleft] = strlen(menupath);
+ menupath[menupathindex[menudepthleft]] = 0;
+
+ if (!preparefilemenu(false))
+ {
+ S_StartSound(NULL, sfx_skid);
+ M_StartMessage(va("\x82%s\x80\nThis folder is empty.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING);
+ menupath[menupathindex[++menudepthleft]] = 0;
+
+ if (!preparefilemenu(true))
+ {
+ UNEXIST;
+ return;
+ }
+ }
+ else
+ {
+ S_StartSound(NULL, sfx_menu1);
+ dir_on[menudepthleft] = 1;
+ }
+ refresh = false;
+ }
+ else
+ {
+ S_StartSound(NULL, sfx_lose);
+ M_StartMessage(va("\x82%s\x80\nThis folder is too deep to navigate to!\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING);
+ menupath[menupathindex[menudepthleft]] = 0;
+ }
+ break;
+ case EXT_UP:
+ S_StartSound(NULL, sfx_menu1);
+ menupath[menupathindex[++menudepthleft]] = 0;
+ if (!preparefilemenu(false))
+ {
+ UNEXIST;
+ return;
+ }
+ break;
+ case EXT_TXT:
+ M_StartMessage(va("\x82%s\x80\nThis file may not be a console script.\nAttempt to run anyways? \n\n(Press 'Y' to confirm)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING),M_AddonExec,MM_YESNO);
+ break;
+ case EXT_CFG:
+ M_AddonExec(KEY_ENTER);
+ break;
+ case EXT_LUA:
+#ifndef HAVE_BLUA
+ S_StartSound(NULL, sfx_lose);
+ M_StartMessage(va("\x82%s\x80\nThis copy of SRB2 was compiled\nwithout support for .lua files.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING),NULL,MM_NOTHING);
+ break;
+#endif
+ // else intentional fallthrough
+ case EXT_SOC:
+ case EXT_WAD:
+ COM_BufAddText(va("addfile %s%s", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING));
+ addonsresponselimit = 5;
+ break;
+ default:
+ S_StartSound(NULL, sfx_lose);
+ }
+ }
+ if (refresh)
+ refreshdirmenu |= REFRESHDIR_NORMAL;
+ }
+ break;
+
+ case KEY_ESCAPE:
+ exitmenu = true;
+ break;
+
+ default:
+ break;
+ }
+ if (exitmenu)
+ {
+ for (; sizedirmenu > 0; sizedirmenu--)
+ {
+ Z_Free(dirmenu[sizedirmenu-1]);
+ dirmenu[sizedirmenu-1] = NULL;
+ }
+
+ Z_Free(dirmenu);
+ dirmenu = NULL;
+
+ // secrets disabled by addfile...
+ MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED);
+
+ if (currentMenu->prevMenu)
+ M_SetupNextMenu(currentMenu->prevMenu);
+ else
+ M_ClearMenus(true);
+ }
+}
+
static void M_PandorasBox(INT32 choice)
{
(void)choice;
@@ -4450,6 +5241,7 @@ static void M_ChangeLevel(INT32 choice)
static void M_ConfirmSpectate(INT32 choice)
{
(void)choice;
+ // We allow switching to spectator even if team changing is not allowed
M_ClearMenus(true);
COM_ImmedExecute("changeteam spectator");
}
@@ -4457,6 +5249,11 @@ static void M_ConfirmSpectate(INT32 choice)
static void M_ConfirmEnterGame(INT32 choice)
{
(void)choice;
+ if (!cv_allowteamchange.value)
+ {
+ M_StartMessage(M_GetText("The server is not allowing\nteam changes at this time.\nPress a key.\n"), NULL, MM_NOTHING);
+ return;
+ }
M_ClearMenus(true);
COM_ImmedExecute("changeteam playing");
}
@@ -4510,7 +5307,7 @@ static void M_Options(INT32 choice)
OP_MainMenu[5].status = (Playing() && !(server || adminplayer == consoleplayer)) ? (IT_GRAYEDOUT) : (IT_STRING|IT_CALL);
// if the player is playing _at all_, disable the erase data options
- OP_DataOptionsMenu[1].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU);
+ OP_DataOptionsMenu[2].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU);
OP_MainDef.prevMenu = currentMenu;
M_SetupNextMenu(&OP_MainDef);
@@ -4609,28 +5406,341 @@ static void M_LevelSelectWarp(INT32 choice)
UINT8 skyRoomMenuTranslations[MAXUNLOCKABLES];
-#define NUMCHECKLIST 8
+static boolean checklist_cangodown; // uuuueeerggghhhh HACK
+
+static void M_HandleChecklist(INT32 choice)
+{
+ INT32 j;
+ switch (choice)
+ {
+ case KEY_DOWNARROW:
+ S_StartSound(NULL, sfx_menu1);
+ if ((check_on != MAXUNLOCKABLES) && checklist_cangodown)
+ {
+ for (j = check_on+1; j < MAXUNLOCKABLES; j++)
+ {
+ if (!unlockables[j].name[0])
+ continue;
+ // if (unlockables[j].nochecklist)
+ // continue;
+ if (!unlockables[j].conditionset)
+ continue;
+ if (unlockables[j].conditionset > MAXCONDITIONSETS)
+ continue;
+ if (unlockables[j].conditionset == unlockables[check_on].conditionset)
+ continue;
+ break;
+ }
+ if (j != MAXUNLOCKABLES)
+ check_on = j;
+ }
+ return;
+
+ case KEY_UPARROW:
+ S_StartSound(NULL, sfx_menu1);
+ if (check_on)
+ {
+ for (j = check_on-1; j > -1; j--)
+ {
+ if (!unlockables[j].name[0])
+ continue;
+ // if (unlockables[j].nochecklist)
+ // continue;
+ if (!unlockables[j].conditionset)
+ continue;
+ if (unlockables[j].conditionset > MAXCONDITIONSETS)
+ continue;
+ if (j && unlockables[j].conditionset == unlockables[j-1].conditionset)
+ continue;
+ break;
+ }
+ if (j != -1)
+ check_on = j;
+ }
+ return;
+
+ case KEY_ESCAPE:
+ if (currentMenu->prevMenu)
+ M_SetupNextMenu(currentMenu->prevMenu);
+ else
+ M_ClearMenus(true);
+ return;
+ default:
+ break;
+ }
+}
+
+#define addy(add) { y += add; if ((y - currentMenu->y) > (scrollareaheight*2)) goto finishchecklist; }
+
static void M_DrawChecklist(void)
{
- INT32 i, j = 0;
+ INT32 i = check_on, j = 0, y = currentMenu->y;
+ UINT32 condnum, previd, maxcond;
+ condition_t *cond;
- for (i = 0; i < MAXUNLOCKABLES; i++)
+ // draw title (or big pic)
+ M_DrawMenuTitle();
+
+ if (check_on)
+ V_DrawString(10, y-(skullAnimCounter/5), V_YELLOWMAP, "\x1A");
+
+ while (i < MAXUNLOCKABLES)
{
- if (unlockables[i].name[0] == 0 || unlockables[i].nochecklist
+ if (unlockables[i].name[0] == 0 //|| unlockables[i].nochecklist
|| !unlockables[i].conditionset || unlockables[i].conditionset > MAXCONDITIONSETS)
continue;
- V_DrawString(8, 8+(24*j), V_RETURN8, unlockables[i].name);
- V_DrawString(160, 8+(24*j), V_RETURN8, V_WordWrap(160, 292, 0, unlockables[i].objective));
+ V_DrawString(currentMenu->x, y, ((unlockables[i].unlocked) ? V_GREENMAP : V_TRANSLUCENT), ((unlockables[i].unlocked || !unlockables[i].nochecklist) ? unlockables[i].name : M_CreateSecretMenuOption(unlockables[i].name)));
+
+ for (j = i+1; j < MAXUNLOCKABLES; j++)
+ {
+ if (!(unlockables[j].name[0] == 0 //|| unlockables[j].nochecklist
+ || !unlockables[j].conditionset || unlockables[j].conditionset > MAXCONDITIONSETS))
+ break;
+ }
+ if ((j != MAXUNLOCKABLES) && (unlockables[i].conditionset == unlockables[j].conditionset))
+ addy(8)
+ else
+ {
+ if ((maxcond = conditionSets[unlockables[i].conditionset-1].numconditions))
+ {
+ cond = conditionSets[unlockables[i].conditionset-1].condition;
+ previd = cond[0].id;
+ addy(2);
+
+ if (unlockables[i].objective[0] != '/')
+ {
+ addy(8);
+ V_DrawString(currentMenu->x, y,
+ V_ALLOWLOWERCASE,
+ va("\x1E %s", unlockables[i].objective));
+ }
+ else
+ {
+ for (condnum = 0; condnum < maxcond; condnum++)
+ {
+ const char *beat = "!";
+
+ if (cond[condnum].id != previd)
+ {
+ addy(8);
+ V_DrawString(currentMenu->x + 4, y, V_YELLOWMAP, "OR");
+ }
+
+ addy(8);
+
+ switch (cond[condnum].type)
+ {
+ case UC_PLAYTIME:
+ {
+ UINT32 hours = G_TicsToHours(cond[condnum].requirement);
+ UINT32 minutes = G_TicsToMinutes(cond[condnum].requirement, false);
+ UINT32 seconds = G_TicsToSeconds(cond[condnum].requirement);
+
+#define getplural(field) ((field == 1) ? "" : "s")
+ if (hours)
+ {
+ if (minutes)
+ beat = va("Play the game for %d hour%s %d minute%s", hours, getplural(hours), minutes, getplural(minutes));
+ else
+ beat = va("Play the game for %d hour%s", hours, getplural(hours));
+ }
+ else
+ {
+ if (minutes && seconds)
+ beat = va("Play the game for %d minute%s %d second%s", minutes, getplural(minutes), seconds, getplural(seconds));
+ else if (minutes)
+ beat = va("Play the game for %d minute%s", minutes, getplural(minutes));
+ else
+ beat = va("Play the game for %d second%s", seconds, getplural(seconds));
+ }
+#undef getplural
+ }
+ break;
+ case UC_MAPVISITED:
+ case UC_MAPBEATEN:
+ case UC_MAPALLEMERALDS:
+ case UC_MAPULTIMATE:
+ case UC_MAPPERFECT:
+ {
+ char *title = G_BuildMapTitle(cond[condnum].requirement);
+
+ if (title)
+ {
+ const char *level = ((M_MapLocked(cond[condnum].requirement) || !((mapheaderinfo[cond[condnum].requirement-1]->menuflags & LF2_NOVISITNEEDED) || mapvisited[cond[condnum].requirement-1])) ? M_CreateSecretMenuOption(title) : title);
+
+ switch (cond[condnum].type)
+ {
+ case UC_MAPVISITED:
+ beat = va("Visit %s", level);
+ break;
+ case UC_MAPALLEMERALDS:
+ beat = va("Beat %s with all emeralds", level);
+ break;
+ case UC_MAPULTIMATE:
+ beat = va("Beat %s in Ultimate mode", level);
+ break;
+ case UC_MAPPERFECT:
+ beat = va("Get all rings in %s", level);
+ break;
+ case UC_MAPBEATEN:
+ default:
+ beat = va("Beat %s", level);
+ break;
+ }
+ Z_Free(title);
+ }
+ }
+ break;
+ case UC_MAPSCORE:
+ case UC_MAPTIME:
+ case UC_MAPRINGS:
+ {
+ char *title = G_BuildMapTitle(cond[condnum].extrainfo1);
+
+ if (title)
+ {
+ const char *level = ((M_MapLocked(cond[condnum].extrainfo1) || !((mapheaderinfo[cond[condnum].extrainfo1-1]->menuflags & LF2_NOVISITNEEDED) || mapvisited[cond[condnum].extrainfo1-1])) ? M_CreateSecretMenuOption(title) : title);
+
+ switch (cond[condnum].type)
+ {
+ case UC_MAPSCORE:
+ beat = va("Get %d points in %s", cond[condnum].requirement, level);
+ break;
+ case UC_MAPTIME:
+ beat = va("Beat %s in %d:%d.%d", level,
+ G_TicsToMinutes(cond[condnum].requirement, true),
+ G_TicsToSeconds(cond[condnum].requirement),
+ G_TicsToCentiseconds(cond[condnum].requirement));
+ break;
+ case UC_MAPRINGS:
+ beat = va("Get %d rings in %s", cond[condnum].requirement, level);
+ break;
+ default:
+ break;
+ }
+ Z_Free(title);
+ }
+ }
+ break;
+ case UC_OVERALLSCORE:
+ case UC_OVERALLTIME:
+ case UC_OVERALLRINGS:
+ {
+ switch (cond[condnum].type)
+ {
+ case UC_OVERALLSCORE:
+ beat = va("Get %d points over all maps", cond[condnum].requirement);
+ break;
+ case UC_OVERALLTIME:
+ beat = va("Get a total time of less than %d:%d.%d",
+ G_TicsToMinutes(cond[condnum].requirement, true),
+ G_TicsToSeconds(cond[condnum].requirement),
+ G_TicsToCentiseconds(cond[condnum].requirement));
+ break;
+ case UC_OVERALLRINGS:
+ beat = va("Get %d rings over all maps", cond[condnum].requirement);
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case UC_GAMECLEAR:
+ case UC_ALLEMERALDS:
+ {
+ const char *emeraldtext = ((cond[condnum].type == UC_ALLEMERALDS) ? " with all emeralds" : "");
+ if (cond[condnum].requirement != 1)
+ beat = va("Beat the game %d times%s",
+ cond[condnum].requirement, emeraldtext);
+ else
+ beat = va("Beat the game%s",
+ emeraldtext);
+ }
+ break;
+ case UC_TOTALEMBLEMS:
+ beat = va("Collect %s%d emblems", ((numemblems+numextraemblems == cond[condnum].requirement) ? "all " : ""), cond[condnum].requirement);
+ break;
+ case UC_NIGHTSTIME:
+ case UC_NIGHTSSCORE:
+ case UC_NIGHTSGRADE:
+ {
+ char *title = G_BuildMapTitle(cond[condnum].extrainfo1);
+
+ if (title)
+ {
+ const char *level = ((M_MapLocked(cond[condnum].extrainfo1) || !((mapheaderinfo[cond[condnum].extrainfo1-1]->menuflags & LF2_NOVISITNEEDED) || mapvisited[cond[condnum].extrainfo1-1])) ? M_CreateSecretMenuOption(title) : title);
+
+ switch (cond[condnum].type)
+ {
+ case UC_NIGHTSSCORE:
+ if (cond[condnum].extrainfo2)
+ beat = va("Get %d points in %s, mare %d", cond[condnum].requirement, level, cond[condnum].extrainfo2);
+ else
+ beat = va("Get %d points in %s", cond[condnum].requirement, level);
+ break;
+ case UC_NIGHTSTIME:
+ if (cond[condnum].extrainfo2)
+ beat = va("Beat %s, mare %d in %d:%d.%d", level, cond[condnum].extrainfo2,
+ G_TicsToMinutes(cond[condnum].requirement, true),
+ G_TicsToSeconds(cond[condnum].requirement),
+ G_TicsToCentiseconds(cond[condnum].requirement));
+ else
+ beat = va("Beat %s in %d:%d.%d",
+ level,
+ G_TicsToMinutes(cond[condnum].requirement, true),
+ G_TicsToSeconds(cond[condnum].requirement),
+ G_TicsToCentiseconds(cond[condnum].requirement));
+ break;
+ case UC_NIGHTSGRADE:
+ {
+ char grade = ('F' - (char)cond[condnum].requirement);
+ if (grade < 'A')
+ grade = 'A';
+ if (cond[condnum].extrainfo2)
+ beat = va("Get grade %c in %s, mare %d", grade, level, cond[condnum].extrainfo2);
+ else
+ beat = va("Get grade %c in %s", grade, level);
+ }
+ break;
+ default:
+ break;
+ }
+ Z_Free(title);
+ }
+ }
+ break;
+ case UC_TRIGGER:
+ case UC_EMBLEM:
+ case UC_CONDITIONSET:
+ default:
+ y -= 8; // Nope, not showing this.
+ break;
+ }
+ if (beat[0] != '!')
+ {
+ V_DrawString(currentMenu->x, y, 0, "\x1E");
+ V_DrawString(currentMenu->x+12, y, V_ALLOWLOWERCASE, beat);
+ }
+ previd = cond[condnum].id;
+ }
+ }
+ }
+ addy(12);
+ }
+ i = j;
+
+ /*V_DrawString(160, 8+(24*j), V_RETURN8, V_WordWrap(160, 292, 0, unlockables[i].objective));
if (unlockables[i].unlocked)
V_DrawString(308, 8+(24*j), V_YELLOWMAP, "Y");
else
- V_DrawString(308, 8+(24*j), V_YELLOWMAP, "N");
-
- if (++j >= NUMCHECKLIST)
- break;
+ V_DrawString(308, 8+(24*j), V_YELLOWMAP, "N");*/
}
+
+finishchecklist:
+ if ((checklist_cangodown = ((y - currentMenu->y) > (scrollareaheight*2)))) // haaaaaaacks.
+ V_DrawString(10, currentMenu->y+(scrollareaheight*2)+(skullAnimCounter/5), V_YELLOWMAP, "\x1B");
}
#define NUMHINTS 5
@@ -4701,6 +5811,13 @@ static void M_DrawSkyRoom(void)
return;
V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + y, V_YELLOWMAP, cv_soundtest.string);
+ if (i == itemOn)
+ {
+ V_DrawCharacter(BASEVIDWIDTH - currentMenu->x - 10 - V_StringWidth(cv_soundtest.string, 0) - (skullAnimCounter/5), currentMenu->y + y,
+ '\x1C' | V_YELLOWMAP, false);
+ V_DrawCharacter(BASEVIDWIDTH - currentMenu->x + 2 + (skullAnimCounter/5), currentMenu->y + y,
+ '\x1D' | V_YELLOWMAP, false);
+ }
if (cv_soundtest.value)
V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + y + 8, V_YELLOWMAP, S_sfx[cv_soundtest.value].name);
}
@@ -5603,11 +6720,15 @@ static void M_ChoosePlayer(INT32 choice)
if (startmap != spstage_start)
cursaveslot = -1;
- lastmapsaved = 0;
+ //lastmapsaved = 0;
gamecomplete = false;
G_DeferedInitNew(ultmode, G_BuildMapName(startmap), (UINT8)skinnum, false, fromlevelselect);
COM_BufAddText("dummyconsvar 1\n"); // G_DeferedInitNew doesn't do this
+
+ if (levelselect.rows)
+ Z_Free(levelselect.rows);
+ levelselect.rows = NULL;
}
// ===============
@@ -5640,23 +6761,24 @@ static void M_Statistics(INT32 choice)
statsMapList[j++] = i;
}
statsMapList[j] = -1;
- statsMax = j - 13 + numextraemblems;
+ statsMax = j - 11 + numextraemblems;
statsLocation = 0;
if (statsMax < 0)
statsMax = 0;
- M_SetupNextMenu(&SP_GameStatsDef);
+ M_SetupNextMenu(&SP_LevelStatsDef);
}
static void M_DrawStatsMaps(int location)
{
- INT32 y = 76, i = -1;
+ INT32 y = 80, i = -1;
INT16 mnum;
extraemblem_t *exemblem;
+ boolean dotopname = true, dobottomarrow = (location < statsMax);
- V_DrawString(20, y-12, 0, "LEVEL NAME");
- V_DrawString(248, y-12, 0, "EMBLEMS");
+ if (location)
+ V_DrawString(10, y-(skullAnimCounter/5), V_YELLOWMAP, "\x1A");
while (statsMapList[++i] != -1)
{
@@ -5665,6 +6787,13 @@ static void M_DrawStatsMaps(int location)
--location;
continue;
}
+ else if (dotopname)
+ {
+ V_DrawString(20, y, V_GREENMAP, "LEVEL NAME");
+ V_DrawString(248, y, V_GREENMAP, "EMBLEMS");
+ y += 8;
+ dotopname = false;
+ }
mnum = statsMapList[i];
M_DrawMapEmblems(mnum+1, 292, y);
@@ -5677,21 +6806,36 @@ static void M_DrawStatsMaps(int location)
y += 8;
if (y >= BASEVIDHEIGHT-8)
- return;
+ goto bottomarrow;
}
+ if (dotopname && !location)
+ {
+ V_DrawString(20, y, V_GREENMAP, "LEVEL NAME");
+ V_DrawString(248, y, V_GREENMAP, "EMBLEMS");
+ y += 8;
+ }
+ else if (location)
+ --location;
// Extra Emblems
for (i = -2; i < numextraemblems; ++i)
{
+ if (i == -1)
+ {
+ V_DrawString(20, y, V_GREENMAP, "EXTRA EMBLEMS");
+ if (location)
+ {
+ y += 8;
+ location++;
+ }
+ }
if (location)
{
--location;
continue;
}
- if (i == -1)
- V_DrawString(20, y, V_GREENMAP, "EXTRA EMBLEMS");
- else if (i >= 0)
+ if (i >= 0)
{
exemblem = &extraemblems[i];
@@ -5707,17 +6851,87 @@ static void M_DrawStatsMaps(int location)
y += 8;
if (y >= BASEVIDHEIGHT-8)
- return;
+ goto bottomarrow;
}
+bottomarrow:
+ if (dobottomarrow)
+ V_DrawString(10, y-8 + (skullAnimCounter/5), V_YELLOWMAP, "\x1B");
}
static void M_DrawLevelStats(void)
{
- M_DrawMenuTitle();
- V_DrawCenteredString(BASEVIDWIDTH/2, 24, V_YELLOWMAP, "PAGE 2 OF 2");
+ char beststr[40];
- V_DrawString(72, 48, 0, va("x %d/%d", M_CountEmblems(), numemblems+numextraemblems));
- V_DrawScaledPatch(40, 48-4, 0, W_CachePatchName("EMBLICON", PU_STATIC));
+ tic_t besttime = 0;
+ UINT32 bestscore = 0;
+ UINT32 bestrings = 0;
+
+ INT32 i;
+ INT32 mapsunfinished = 0;
+ boolean bestunfinished[3] = {false, false, false};
+
+ M_DrawMenuTitle();
+
+ V_DrawString(20, 24, V_YELLOWMAP, "Total Play Time:");
+ V_DrawCenteredString(BASEVIDWIDTH/2, 32, 0, va("%i hours, %i minutes, %i seconds",
+ G_TicsToHours(totalplaytime),
+ G_TicsToMinutes(totalplaytime, false),
+ G_TicsToSeconds(totalplaytime)));
+
+ for (i = 0; i < NUMMAPS; i++)
+ {
+ boolean mapunfinished = false;
+
+ if (!mapheaderinfo[i] || !(mapheaderinfo[i]->menuflags & LF2_RECORDATTACK))
+ continue;
+
+ if (!mainrecords[i])
+ {
+ mapsunfinished++;
+ bestunfinished[0] = bestunfinished[1] = bestunfinished[2] = true;
+ continue;
+ }
+
+ if (mainrecords[i]->score > 0)
+ bestscore += mainrecords[i]->score;
+ else
+ mapunfinished = bestunfinished[0] = true;
+
+ if (mainrecords[i]->time > 0)
+ besttime += mainrecords[i]->time;
+ else
+ mapunfinished = bestunfinished[1] = true;
+
+ if (mainrecords[i]->rings > 0)
+ bestrings += mainrecords[i]->rings;
+ else
+ mapunfinished = bestunfinished[2] = true;
+
+ if (mapunfinished)
+ mapsunfinished++;
+ }
+
+ V_DrawString(20, 48, 0, "Combined records:");
+
+ if (mapsunfinished)
+ V_DrawString(20, 56, V_REDMAP, va("(%d unfinished)", mapsunfinished));
+ else
+ V_DrawString(20, 56, V_GREENMAP, "(complete)");
+
+ V_DrawString(36, 64, 0, va("x %d/%d", M_CountEmblems(), numemblems+numextraemblems));
+ V_DrawSmallScaledPatch(20, 64, 0, W_CachePatchName("EMBLICON", PU_STATIC));
+
+ sprintf(beststr, "%u", bestscore);
+ V_DrawString(BASEVIDWIDTH/2, 48, V_YELLOWMAP, "SCORE:");
+ V_DrawRightAlignedString(BASEVIDWIDTH-16, 48, (bestunfinished[0] ? V_REDMAP : 0), beststr);
+
+ sprintf(beststr, "%i:%02i:%02i.%02i", G_TicsToHours(besttime), G_TicsToMinutes(besttime, false), G_TicsToSeconds(besttime), G_TicsToCentiseconds(besttime));
+ V_DrawString(BASEVIDWIDTH/2, 56, V_YELLOWMAP, "TIME:");
+ V_DrawRightAlignedString(BASEVIDWIDTH-16, 56, (bestunfinished[1] ? V_REDMAP : 0), beststr);
+
+ sprintf(beststr, "%u", bestrings);
+ V_DrawString(BASEVIDWIDTH/2, 64, V_YELLOWMAP, "RINGS:");
+ V_DrawRightAlignedString(BASEVIDWIDTH-16, 64, (bestunfinished[2] ? V_REDMAP : 0), beststr);
M_DrawStatsMaps(statsLocation);
}
@@ -5741,120 +6955,19 @@ static void M_HandleLevelStats(INT32 choice)
--statsLocation;
break;
- case KEY_RIGHTARROW:
+ case KEY_PGDN:
S_StartSound(NULL, sfx_menu1);
- statsLocation += (statsLocation+15 >= statsMax) ? statsMax-statsLocation : 15;
+ statsLocation += (statsLocation+13 >= statsMax) ? statsMax-statsLocation : 13;
break;
- case KEY_LEFTARROW:
+ case KEY_PGUP:
S_StartSound(NULL, sfx_menu1);
- statsLocation -= (statsLocation < 15) ? statsLocation : 15;
+ statsLocation -= (statsLocation < 13) ? statsLocation : 13;
break;
case KEY_ESCAPE:
exitmenu = true;
break;
-
- case KEY_ENTER:
- S_StartSound(NULL, sfx_menu1);
- M_SetupNextMenu(&SP_GameStatsDef);
- break;
- }
- if (exitmenu)
- {
- if (currentMenu->prevMenu)
- M_SetupNextMenu(currentMenu->prevMenu);
- else
- M_ClearMenus(true);
- }
-}
-
-// Handle GAME statistics.
-static void M_DrawGameStats(void)
-{
- char beststr[40];
-
- tic_t besttime = 0;
- UINT32 bestscore = 0;
- UINT32 bestrings = 0;
-
- INT32 i;
- INT32 mapsunfinished[3] = {0, 0, 0};
-
- M_DrawMenuTitle();
- V_DrawCenteredString(BASEVIDWIDTH/2, 24, V_YELLOWMAP, "PAGE 1 OF 2");
-
- V_DrawString(32, 60, V_YELLOWMAP, "Total Play Time:");
- V_DrawRightAlignedString(BASEVIDWIDTH-32, 70, 0, va("%i hours, %i minutes, %i seconds",
- G_TicsToHours(totalplaytime),
- G_TicsToMinutes(totalplaytime, false),
- G_TicsToSeconds(totalplaytime)));
-
- for (i = 0; i < NUMMAPS; i++)
- {
- if (!mapheaderinfo[i] || !(mapheaderinfo[i]->menuflags & LF2_RECORDATTACK))
- continue;
-
- if (!mainrecords[i])
- {
- mapsunfinished[0]++;
- mapsunfinished[1]++;
- mapsunfinished[2]++;
- continue;
- }
-
- if (mainrecords[i]->score > 0)
- bestscore += mainrecords[i]->score;
- else
- mapsunfinished[0]++;
-
- if (mainrecords[i]->time > 0)
- besttime += mainrecords[i]->time;
- else
- mapsunfinished[1]++;
-
- if (mainrecords[i]->rings > 0)
- bestrings += mainrecords[i]->rings;
- else
- mapsunfinished[2]++;
-
- }
-
- V_DrawCenteredString(BASEVIDWIDTH/2, 90, 0, "* COMBINED RECORDS *");
-
- sprintf(beststr, "%u", bestscore);
- V_DrawString(32, 100, V_YELLOWMAP, "SCORE:");
- V_DrawRightAlignedString(BASEVIDWIDTH-32, 100, 0, beststr);
- if (mapsunfinished[0])
- V_DrawRightAlignedString(BASEVIDWIDTH-32, 108, V_REDMAP, va("(%d unfinished)", mapsunfinished[0]));
-
- sprintf(beststr, "%i:%02i:%02i.%02i", G_TicsToHours(besttime), G_TicsToMinutes(besttime, false), G_TicsToSeconds(besttime), G_TicsToCentiseconds(besttime));
- V_DrawString(32, 120, V_YELLOWMAP, "TIME:");
- V_DrawRightAlignedString(BASEVIDWIDTH-32, 120, 0, beststr);
- if (mapsunfinished[1])
- V_DrawRightAlignedString(BASEVIDWIDTH-32, 128, V_REDMAP, va("(%d unfinished)", mapsunfinished[1]));
-
- sprintf(beststr, "%u", bestrings);
- V_DrawString(32, 140, V_YELLOWMAP, "RINGS:");
- V_DrawRightAlignedString(BASEVIDWIDTH-32, 140, 0, beststr);
- if (mapsunfinished[2])
- V_DrawRightAlignedString(BASEVIDWIDTH-32, 148, V_REDMAP, va("(%d unfinished)", mapsunfinished[2]));
-}
-
-static void M_HandleGameStats(INT32 choice)
-{
- boolean exitmenu = false; // exit to previous menu
-
- switch (choice)
- {
- case KEY_ESCAPE:
- exitmenu = true;
- break;
-
- case KEY_ENTER:
- S_StartSound(NULL, sfx_menu1);
- M_SetupNextMenu(&SP_LevelStatsDef);
- break;
}
if (exitmenu)
{
@@ -5911,6 +7024,13 @@ void M_DrawTimeAttackMenu(void)
// Should see nothing but strings
V_DrawString(BASEVIDWIDTH - x - soffset - V_StringWidth(cv->string, 0), y, V_YELLOWMAP, cv->string);
+ if (i == itemOn)
+ {
+ V_DrawCharacter(BASEVIDWIDTH - x - soffset - 10 - V_StringWidth(cv->string, 0) - (skullAnimCounter/5), y,
+ '\x1C' | V_YELLOWMAP, false);
+ V_DrawCharacter(BASEVIDWIDTH - x - soffset + 2 + (skullAnimCounter/5), y,
+ '\x1D' | V_YELLOWMAP, false);
+ }
}
}
@@ -5937,7 +7057,7 @@ void M_DrawTimeAttackMenu(void)
lumpnum_t lumpnum;
char beststr[40];
- M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true);
+ M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true, false);
// A 160x100 image of the level as entry MAPxxP
lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value)));
@@ -6093,6 +7213,13 @@ void M_DrawNightsAttackMenu(void)
// Should see nothing but strings
V_DrawString(BASEVIDWIDTH - x - soffset - V_StringWidth(cv->string, 0), y, V_YELLOWMAP, cv->string);
+ if (i == itemOn)
+ {
+ V_DrawCharacter(BASEVIDWIDTH - x - soffset - 10 - V_StringWidth(cv->string, 0) - (skullAnimCounter/5), y,
+ '\x1C' | V_YELLOWMAP, false);
+ V_DrawCharacter(BASEVIDWIDTH - x - soffset + 2 + (skullAnimCounter/5), y,
+ '\x1D' | V_YELLOWMAP, false);
+ }
}
}
@@ -6114,7 +7241,7 @@ void M_DrawNightsAttackMenu(void)
UINT32 bestscore = G_GetBestNightsScore(cv_nextmap.value, cv_dummymares.value);
tic_t besttime = G_GetBestNightsTime(cv_nextmap.value, cv_dummymares.value);
- M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true);
+ M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true, false);
// A 160x100 image of the level as entry MAPxxP
lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value)));
@@ -6870,7 +7997,7 @@ static void M_DrawServerMenu(void)
// Room name
if (currentMenu == &MP_ServerDef)
{
- M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight/2, "Server settings", true);
+ M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight/2, "Server settings", true, false);
if (ms_RoomId < 0)
V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey,
V_YELLOWMAP, (itemOn == mp_server_room) ? "