mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-15 09:11:48 +00:00
Merge branch 'master' of http://git.magicalgirl.moe/STJr/SRB2Internal.git into directionchar
# Conflicts: # src/hardware/hw_main.c
This commit is contained in:
commit
2e6c09a636
147 changed files with 11180 additions and 7032 deletions
|
@ -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})
|
||||
|
|
33
SRB2.cbp
33
SRB2.cbp
|
@ -1174,6 +1174,39 @@ HW3SOUND for 3D hardware sound support
|
|||
<Option target="Debug Mingw64/DirectX" />
|
||||
<Option target="Release Mingw64/DirectX" />
|
||||
</Unit>
|
||||
<Unit filename="src/hardware/hw_clip.c">
|
||||
<Option compilerVar="CC" />
|
||||
<Option target="Debug Native/SDL" />
|
||||
<Option target="Release Native/SDL" />
|
||||
<Option target="Debug Mingw/SDL" />
|
||||
<Option target="Release Mingw/SDL" />
|
||||
<Option target="Debug Mingw/DirectX" />
|
||||
<Option target="Release Mingw/DirectX" />
|
||||
<Option target="Debug Any/Dummy" />
|
||||
<Option target="Release Any/Dummy" />
|
||||
<Option target="Debug Linux/SDL" />
|
||||
<Option target="Release Linux/SDL" />
|
||||
<Option target="Debug Mingw64/SDL" />
|
||||
<Option target="Release Mingw64/SDL" />
|
||||
<Option target="Debug Mingw64/DirectX" />
|
||||
<Option target="Release Mingw64/DirectX" />
|
||||
</Unit>
|
||||
<Unit filename="src/hardware/hw_clip.h">
|
||||
<Option target="Debug Native/SDL" />
|
||||
<Option target="Release Native/SDL" />
|
||||
<Option target="Debug Mingw/SDL" />
|
||||
<Option target="Release Mingw/SDL" />
|
||||
<Option target="Debug Mingw/DirectX" />
|
||||
<Option target="Release Mingw/DirectX" />
|
||||
<Option target="Debug Any/Dummy" />
|
||||
<Option target="Release Any/Dummy" />
|
||||
<Option target="Debug Linux/SDL" />
|
||||
<Option target="Release Linux/SDL" />
|
||||
<Option target="Debug Mingw64/SDL" />
|
||||
<Option target="Release Mingw64/SDL" />
|
||||
<Option target="Debug Mingw64/DirectX" />
|
||||
<Option target="Release Mingw64/DirectX" />
|
||||
</Unit>
|
||||
<Unit filename="src/hardware/hw_data.h">
|
||||
<Option target="Debug Native/SDL" />
|
||||
<Option target="Release Native/SDL" />
|
||||
|
|
37
appveyor.yml
37
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:
|
||||
|
|
6
bin/Mingw/Debug/.gitignore
vendored
6
bin/Mingw/Debug/.gitignore
vendored
|
@ -1,3 +1,3 @@
|
|||
/srb2sdl.exe
|
||||
/srb2win.exe
|
||||
/r_opengl.dll
|
||||
*.exe
|
||||
*.mo
|
||||
r_opengl.dll
|
||||
|
|
6
bin/Mingw/Release/.gitignore
vendored
6
bin/Mingw/Release/.gitignore
vendored
|
@ -1,3 +1,3 @@
|
|||
/srb2sdl.exe
|
||||
/srb2win.exe
|
||||
/r_opengl.dll
|
||||
*.exe
|
||||
*.mo
|
||||
r_opengl.dll
|
||||
|
|
8
objs/.gitignore
vendored
Normal file
8
objs/.gitignore
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
#All folders
|
||||
SRB2.res
|
||||
depend.dep
|
||||
depend.ped
|
||||
*.o
|
||||
#VC9 folder only
|
||||
/VC9/Win32
|
||||
/VC9/x64
|
3
objs/DC/SDL/Debug/.gitignore
vendored
3
objs/DC/SDL/Debug/.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
/depend.dep
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
3
objs/DC/SDL/Release/.gitignore
vendored
3
objs/DC/SDL/Release/.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
/depend.dep
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
4
objs/Linux/SDL/Debug/.gitignore
vendored
4
objs/Linux/SDL/Debug/.gitignore
vendored
|
@ -1,2 +1,2 @@
|
|||
/depend.dep
|
||||
/*.o
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
4
objs/Linux/SDL/Release/.gitignore
vendored
4
objs/Linux/SDL/Release/.gitignore
vendored
|
@ -1,2 +1,2 @@
|
|||
/depend.dep
|
||||
/*.o
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
4
objs/Linux64/SDL/Debug/.gitignore
vendored
4
objs/Linux64/SDL/Debug/.gitignore
vendored
|
@ -1,2 +1,2 @@
|
|||
/depend.dep
|
||||
/*.o
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
4
objs/Linux64/SDL/Release/.gitignore
vendored
4
objs/Linux64/SDL/Release/.gitignore
vendored
|
@ -1,2 +1,2 @@
|
|||
/depend.dep
|
||||
/*.o
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
5
objs/Mingw/Debug/.gitignore
vendored
5
objs/Mingw/Debug/.gitignore
vendored
|
@ -1,3 +1,2 @@
|
|||
/SRB2.res
|
||||
/depend.dep
|
||||
/*.o
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
5
objs/Mingw/Release/.gitignore
vendored
5
objs/Mingw/Release/.gitignore
vendored
|
@ -1,3 +1,2 @@
|
|||
/SRB2.res
|
||||
/depend.dep
|
||||
/*.o
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
5
objs/Mingw/SDL/Debug/.gitignore
vendored
5
objs/Mingw/SDL/Debug/.gitignore
vendored
|
@ -1,3 +1,2 @@
|
|||
/SRB2.res
|
||||
/depend.dep
|
||||
/*.o
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
5
objs/Mingw/SDL/Release/.gitignore
vendored
5
objs/Mingw/SDL/Release/.gitignore
vendored
|
@ -1,3 +1,2 @@
|
|||
/SRB2.res
|
||||
/depend.dep
|
||||
/*.o
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
5
objs/Mingw64/Debug/.gitignore
vendored
5
objs/Mingw64/Debug/.gitignore
vendored
|
@ -1,3 +1,2 @@
|
|||
/SRB2.res
|
||||
/depend.dep
|
||||
/*.o
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
5
objs/Mingw64/Release/.gitignore
vendored
5
objs/Mingw64/Release/.gitignore
vendored
|
@ -1,3 +1,2 @@
|
|||
/SRB2.res
|
||||
/depend.dep
|
||||
/*.o
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
5
objs/Mingw64/SDL/Debug/.gitignore
vendored
5
objs/Mingw64/SDL/Debug/.gitignore
vendored
|
@ -1,3 +1,2 @@
|
|||
/SRB2.res
|
||||
/depend.dep
|
||||
/*.o
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
5
objs/Mingw64/SDL/Release/.gitignore
vendored
5
objs/Mingw64/SDL/Release/.gitignore
vendored
|
@ -1,3 +1,2 @@
|
|||
/SRB2.res
|
||||
/depend.dep
|
||||
/*.o
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
4
objs/PS3/SDL/Debug/.gitignore
vendored
4
objs/PS3/SDL/Debug/.gitignore
vendored
|
@ -1,2 +1,2 @@
|
|||
/depend.dep
|
||||
/*.o
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
4
objs/PS3/SDL/Release/.gitignore
vendored
4
objs/PS3/SDL/Release/.gitignore
vendored
|
@ -1,2 +1,2 @@
|
|||
/depend.dep
|
||||
/*.o
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
3
objs/PSP/SDL/Release/.gitignore
vendored
3
objs/PSP/SDL/Release/.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
/depend.dep
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
3
objs/SDL/Release/.gitignore
vendored
3
objs/SDL/Release/.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
/depend.ped
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
2
objs/VC/.gitignore
vendored
2
objs/VC/.gitignore
vendored
|
@ -0,0 +1,2 @@
|
|||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
4
objs/VC9/.gitignore
vendored
4
objs/VC9/.gitignore
vendored
|
@ -1,2 +1,2 @@
|
|||
/Win32
|
||||
/x64
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
4
objs/Wii/SDL/Debug/.gitignore
vendored
4
objs/Wii/SDL/Debug/.gitignore
vendored
|
@ -1,2 +1,2 @@
|
|||
/depend.dep
|
||||
/*.o
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
4
objs/Wii/SDL/Release/.gitignore
vendored
4
objs/Wii/SDL/Release/.gitignore
vendored
|
@ -1,2 +1,2 @@
|
|||
/depend.dep
|
||||
/*.o
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
3
objs/WinCE/SDL/Release/.gitignore
vendored
3
objs/WinCE/SDL/Release/.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
/depend.dep
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
3
objs/djgppdos/Debug/.gitignore
vendored
3
objs/djgppdos/Debug/.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
/depend.dep
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
3
objs/djgppdos/Release/.gitignore
vendored
3
objs/djgppdos/Release/.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
/depend.dep
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
4
objs/nds/Debug/.gitignore
vendored
4
objs/nds/Debug/.gitignore
vendored
|
@ -1,2 +1,2 @@
|
|||
/depend.dep
|
||||
/*.o
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
4
objs/nds/Release/.gitignore
vendored
4
objs/nds/Release/.gitignore
vendored
|
@ -1,2 +1,2 @@
|
|||
/depend.dep
|
||||
/*.o
|
||||
# DON'T REMOVE
|
||||
# This keeps the folder from disappearing
|
||||
|
|
|
@ -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
|
||||
|
|
14
src/Makefile
14
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 $@
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
194
src/d_clisrv.c
194
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<<i);
|
||||
if (players[i].outofcoop)
|
||||
rst->outofcoop |= (1<<i);
|
||||
rst->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<<i));
|
||||
players[i].outofcoop = (loc_outofcoop & (1<<i));
|
||||
players[i].ctfteam = (INT32)LONG(p->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 <playername/playernum> <reason>: 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 <playername/playernum> <reason>: 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
|
||||
|
|
|
@ -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
|
||||
|
|
99
src/d_main.c
99
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))
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
15
src/d_net.c
15
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)
|
||||
|
|
338
src/d_netcmd.c
338
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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
109
src/d_netfil.c
109
src/d_netfil.c
|
@ -62,7 +62,8 @@
|
|||
|
||||
#include <errno.h>
|
||||
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
1056
src/dehacked.c
1056
src/dehacked.c
File diff suppressed because it is too large
Load diff
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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, paldiv)>>FRACBITS;
|
||||
}
|
||||
|
||||
|
@ -337,7 +337,8 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
|
|||
UINT8 wipeframe = 0;
|
||||
fademask_t *fmask;
|
||||
|
||||
paldiv = FixedDiv(257<<FRACBITS, 11<<FRACBITS);
|
||||
if (!paldiv)
|
||||
paldiv = FixedDiv(257<<FRACBITS, 11<<FRACBITS);
|
||||
|
||||
// Init the wipe
|
||||
WipeInAction = true;
|
||||
|
|
335
src/filesrch.c
335
src/filesrch.c
|
@ -31,6 +31,8 @@
|
|||
#include "filesrch.h"
|
||||
#include "d_netfil.h"
|
||||
#include "m_misc.h"
|
||||
#include "z_zone.h"
|
||||
#include "m_menu.h" // Addons_option_Onchange
|
||||
|
||||
#if (defined (_WIN32) && !defined (_WIN32_WCE)) && defined (_MSC_VER) && !defined (_XBOX)
|
||||
|
||||
|
@ -255,6 +257,28 @@ readdir (DIR * dirp)
|
|||
return (struct dirent *) 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* rewinddir
|
||||
*
|
||||
* Makes the next readdir start from the beginning.
|
||||
*/
|
||||
int
|
||||
rewinddir (DIR * dirp)
|
||||
{
|
||||
errno = 0;
|
||||
|
||||
/* Check for valid DIR struct. */
|
||||
if (!dirp)
|
||||
{
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
dirp->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
|
||||
|
|
|
@ -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__
|
||||
|
|
306
src/g_game.c
306
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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
465
src/hardware/hw_clip.c
Normal file
465
src/hardware/hw_clip.c
Normal file
|
@ -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 <math.h>
|
||||
#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
|
24
src/hardware/hw_clip.h
Normal file
24
src/hardware/hw_clip.h
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
// --------
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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..
|
||||
|
|
|
@ -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--)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
165
src/hu_stuff.c
165
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++;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
991
src/info.c
991
src/info.c
File diff suppressed because it is too large
Load diff
185
src/info.h
185
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,
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -266,4 +266,4 @@ int LUA_BlockmapLib(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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+]
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"))
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
54
src/m_cond.c
54
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
|
||||
|
|
20
src/m_cond.h
20
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
|
||||
|
|
3114
src/m_menu.c
3114
src/m_menu.c
File diff suppressed because it is too large
Load diff
17
src/m_menu.h
17
src/m_menu.h
|
@ -124,6 +124,8 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt);
|
|||
#define IT_HEADER (IT_SPACE +IT_HEADERTEXT)
|
||||
#define IT_SECRET (IT_SPACE +IT_QUESTIONMARKS)
|
||||
|
||||
#define MAXSTRINGLENGTH 32
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct menu_s *submenu; // IT_SUBMENU
|
||||
|
@ -249,6 +251,9 @@ void Nextmap_OnChange(void);
|
|||
void Moviemode_mode_Onchange(void);
|
||||
void Screenshot_option_Onchange(void);
|
||||
|
||||
// Addons menu updating
|
||||
void Addons_option_Onchange(void);
|
||||
|
||||
// These defines make it a little easier to make menus
|
||||
#define DEFAULTMENUSTYLE(header, source, prev, x, y)\
|
||||
{\
|
||||
|
@ -262,6 +267,18 @@ void Screenshot_option_Onchange(void);
|
|||
NULL\
|
||||
}
|
||||
|
||||
#define DEFAULTSCROLLMENUSTYLE(header, source, prev, x, y)\
|
||||
{\
|
||||
header,\
|
||||
sizeof(source)/sizeof(menuitem_t),\
|
||||
prev,\
|
||||
source,\
|
||||
M_DrawGenericScrollMenu,\
|
||||
x, y,\
|
||||
0,\
|
||||
NULL\
|
||||
}
|
||||
|
||||
#define PAUSEMENUSTYLE(source, x, y)\
|
||||
{\
|
||||
NULL,\
|
||||
|
|
54
src/m_misc.c
54
src/m_misc.c
|
@ -100,6 +100,8 @@ static CV_PossibleValue_t screenshot_cons_t[] = {{0, "Default"}, {1, "HOME"}, {2
|
|||
consvar_t cv_screenshot_option = {"screenshot_option", "Default", CV_SAVE|CV_CALL, screenshot_cons_t, Screenshot_option_Onchange, 0, NULL, NULL, 0, 0, NULL};
|
||||
consvar_t cv_screenshot_folder = {"screenshot_folder", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
consvar_t cv_screenshot_colorprofile = {"screenshot_colorprofile", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
static CV_PossibleValue_t moviemode_cons_t[] = {{MM_GIF, "GIF"}, {MM_APNG, "aPNG"}, {MM_SCREENSHOT, "Screenshots"}, {0, NULL}};
|
||||
consvar_t cv_moviemode = {"moviemode_mode", "GIF", CV_SAVE|CV_CALL, moviemode_cons_t, Moviemode_mode_Onchange, 0, NULL, NULL, 0, 0, NULL};
|
||||
|
||||
|
@ -610,20 +612,25 @@ static void PNG_warn(png_structp PNG, png_const_charp pngtext)
|
|||
CONS_Debug(DBG_RENDER, "libpng warning at %p: %s", PNG, pngtext);
|
||||
}
|
||||
|
||||
static void M_PNGhdr(png_structp png_ptr, png_infop png_info_ptr, PNG_CONST png_uint_32 width, PNG_CONST png_uint_32 height, PNG_CONST png_byte *palette)
|
||||
static void M_PNGhdr(png_structp png_ptr, png_infop png_info_ptr, PNG_CONST png_uint_32 width, PNG_CONST png_uint_32 height, const boolean palette)
|
||||
{
|
||||
const png_byte png_interlace = PNG_INTERLACE_NONE; //PNG_INTERLACE_ADAM7
|
||||
if (palette)
|
||||
{
|
||||
png_colorp png_PLTE = png_malloc(png_ptr, sizeof(png_color)*256); //palette
|
||||
const png_byte *pal = palette;
|
||||
png_uint_16 i;
|
||||
|
||||
RGBA_t *pal = ((cv_screenshot_colorprofile.value)
|
||||
? pLocalPalette
|
||||
: pMasterPalette);
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
png_PLTE[i].red = *pal; pal++;
|
||||
png_PLTE[i].green = *pal; pal++;
|
||||
png_PLTE[i].blue = *pal; pal++;
|
||||
png_PLTE[i].red = pal[i].s.red;
|
||||
png_PLTE[i].green = pal[i].s.green;
|
||||
png_PLTE[i].blue = pal[i].s.blue;
|
||||
}
|
||||
|
||||
png_set_IHDR(png_ptr, png_info_ptr, width, height, 8, PNG_COLOR_TYPE_PALETTE,
|
||||
png_interlace, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
||||
png_write_info_before_PLTE(png_ptr, png_info_ptr);
|
||||
|
@ -924,7 +931,7 @@ static void M_PNGfix_acTL(png_structp png_ptr, png_infop png_info_ptr)
|
|||
fseek(apng_FILE, oldpos, SEEK_SET);
|
||||
}
|
||||
|
||||
static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal)
|
||||
static boolean M_SetupaPNG(png_const_charp filename, boolean palette)
|
||||
{
|
||||
apng_FILE = fopen(filename,"wb+"); // + mode for reading
|
||||
if (!apng_FILE)
|
||||
|
@ -966,7 +973,7 @@ static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal)
|
|||
png_set_compression_strategy(apng_ptr, cv_zlib_strategya.value);
|
||||
png_set_compression_window_bits(apng_ptr, cv_zlib_window_bitsa.value);
|
||||
|
||||
M_PNGhdr(apng_ptr, apng_info_ptr, vid.width, vid.height, pal);
|
||||
M_PNGhdr(apng_ptr, apng_info_ptr, vid.width, vid.height, palette);
|
||||
|
||||
M_PNGText(apng_ptr, apng_info_ptr, true);
|
||||
|
||||
|
@ -1007,9 +1014,9 @@ static inline moviemode_t M_StartMovieAPNG(const char *pathname)
|
|||
}
|
||||
|
||||
if (rendermode == render_soft)
|
||||
ret = M_SetupaPNG(va(pandf,pathname,freename), W_CacheLumpName(GetPalette(), PU_CACHE));
|
||||
ret = M_SetupaPNG(va(pandf,pathname,freename), true);
|
||||
else
|
||||
ret = M_SetupaPNG(va(pandf,pathname,freename), NULL);
|
||||
ret = M_SetupaPNG(va(pandf,pathname,freename), false);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
|
@ -1215,11 +1222,10 @@ void M_StopMovie(void)
|
|||
* \param palette Palette of image data
|
||||
* \note if palette is NULL, BGR888 format
|
||||
*/
|
||||
boolean M_SavePNG(const char *filename, void *data, int width, int height, const UINT8 *palette)
|
||||
boolean M_SavePNG(const char *filename, void *data, int width, int height, const boolean palette)
|
||||
{
|
||||
png_structp png_ptr;
|
||||
png_infop png_info_ptr;
|
||||
PNG_CONST png_byte *PLTE = (const png_byte *)palette;
|
||||
#ifdef PNG_SETJMP_SUPPORTED
|
||||
#ifdef USE_FAR_KEYWORD
|
||||
jmp_buf jmpbuf;
|
||||
|
@ -1282,7 +1288,7 @@ boolean M_SavePNG(const char *filename, void *data, int width, int height, const
|
|||
png_set_compression_strategy(png_ptr, cv_zlib_strategy.value);
|
||||
png_set_compression_window_bits(png_ptr, cv_zlib_window_bits.value);
|
||||
|
||||
M_PNGhdr(png_ptr, png_info_ptr, width, height, PLTE);
|
||||
M_PNGhdr(png_ptr, png_info_ptr, width, height, palette);
|
||||
|
||||
M_PNGText(png_ptr, png_info_ptr, false);
|
||||
|
||||
|
@ -1329,7 +1335,7 @@ typedef struct
|
|||
* \param palette Palette of image data
|
||||
*/
|
||||
#if NUMSCREENS > 2
|
||||
static boolean WritePCXfile(const char *filename, const UINT8 *data, int width, int height, const UINT8 *palette)
|
||||
static boolean WritePCXfile(const char *filename, const UINT8 *data, int width, int height)
|
||||
{
|
||||
int i;
|
||||
size_t length;
|
||||
|
@ -1370,8 +1376,20 @@ static boolean WritePCXfile(const char *filename, const UINT8 *data, int width,
|
|||
|
||||
// write the palette
|
||||
*pack++ = 0x0c; // palette ID byte
|
||||
for (i = 0; i < 768; i++)
|
||||
*pack++ = *palette++;
|
||||
|
||||
// write color table
|
||||
{
|
||||
RGBA_t *pal = ((cv_screenshot_colorprofile.value)
|
||||
? pLocalPalette
|
||||
: pMasterPalette);
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
*pack++ = pal[i].s.red;
|
||||
*pack++ = pal[i].s.green;
|
||||
*pack++ = pal[i].s.blue;
|
||||
}
|
||||
}
|
||||
|
||||
// write output file
|
||||
length = pack - (UINT8 *)pcx;
|
||||
|
@ -1445,11 +1463,9 @@ void M_DoScreenShot(void)
|
|||
if (rendermode != render_none)
|
||||
{
|
||||
#ifdef USE_PNG
|
||||
ret = M_SavePNG(va(pandf,pathname,freename), linear, vid.width, vid.height,
|
||||
W_CacheLumpName(GetPalette(), PU_CACHE));
|
||||
ret = M_SavePNG(va(pandf,pathname,freename), linear, vid.width, vid.height, true);
|
||||
#else
|
||||
ret = WritePCXfile(va(pandf,pathname,freename), linear, vid.width, vid.height,
|
||||
W_CacheLumpName(GetPalette(), PU_CACHE));
|
||||
ret = WritePCXfile(va(pandf,pathname,freename), linear, vid.width, vid.height);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "tables.h"
|
||||
|
||||
#include "d_event.h" // Screenshot responder
|
||||
#include "command.h"
|
||||
|
||||
typedef enum {
|
||||
MM_OFF = 0,
|
||||
|
@ -28,6 +29,12 @@ typedef enum {
|
|||
} moviemode_t;
|
||||
extern moviemode_t moviemode;
|
||||
|
||||
extern consvar_t cv_screenshot_option, cv_screenshot_folder, cv_screenshot_colorprofile;
|
||||
extern consvar_t cv_moviemode;
|
||||
extern consvar_t cv_zlib_memory, cv_zlib_level, cv_zlib_strategy, cv_zlib_window_bits;
|
||||
extern consvar_t cv_zlib_memorya, cv_zlib_levela, cv_zlib_strategya, cv_zlib_window_bitsa;
|
||||
extern consvar_t cv_apng_delay;
|
||||
|
||||
void M_StartMovie(void);
|
||||
void M_SaveFrame(void);
|
||||
void M_StopMovie(void);
|
||||
|
@ -57,7 +64,7 @@ void FIL_ForceExtension(char *path, const char *extension);
|
|||
boolean FIL_CheckExtension(const char *in);
|
||||
|
||||
#ifdef HAVE_PNG
|
||||
boolean M_SavePNG(const char *filename, void *data, int width, int height, const UINT8 *palette);
|
||||
boolean M_SavePNG(const char *filename, void *data, int width, int height, const boolean palette);
|
||||
#endif
|
||||
|
||||
extern boolean takescreenshot;
|
||||
|
|
512
src/p_enemy.c
512
src/p_enemy.c
|
@ -93,20 +93,12 @@ void A_Explode(mobj_t *actor);
|
|||
void A_BossDeath(mobj_t *actor);
|
||||
void A_CustomPower(mobj_t *actor);
|
||||
void A_GiveWeapon(mobj_t *actor);
|
||||
void A_JumpShield(mobj_t *actor);
|
||||
void A_RingShield(mobj_t *actor);
|
||||
void A_RingBox(mobj_t *actor);
|
||||
void A_Invincibility(mobj_t *actor);
|
||||
void A_SuperSneakers(mobj_t *actor);
|
||||
void A_AwardScore(mobj_t *actor);
|
||||
void A_ExtraLife(mobj_t *actor);
|
||||
void A_BombShield(mobj_t *actor);
|
||||
void A_WaterShield(mobj_t *actor);
|
||||
void A_ForceShield(mobj_t *actor);
|
||||
void A_PityShield(mobj_t *actor);
|
||||
void A_FlameShield(mobj_t *actor);
|
||||
void A_BubbleShield(mobj_t *actor);
|
||||
void A_ThunderShield(mobj_t *actor);
|
||||
void A_GiveShield(mobj_t *actor);
|
||||
void A_GravityBox(mobj_t *actor);
|
||||
void A_ScoreRise(mobj_t *actor);
|
||||
void A_ParticleSpawn(mobj_t *actor);
|
||||
|
@ -137,7 +129,6 @@ void A_DetonChase(mobj_t *actor);
|
|||
void A_CapeChase(mobj_t *actor);
|
||||
void A_RotateSpikeBall(mobj_t *actor);
|
||||
void A_SlingAppear(mobj_t *actor);
|
||||
void A_MaceRotate(mobj_t *actor);
|
||||
void A_UnidusBall(mobj_t *actor);
|
||||
void A_RockSpawn(mobj_t *actor);
|
||||
void A_SetFuse(mobj_t *actor);
|
||||
|
@ -841,6 +832,34 @@ static mobjtype_t P_DoRandomBoxChances(void)
|
|||
mobjtype_t spawnchance[256];
|
||||
INT32 numchoices = 0, i = 0;
|
||||
|
||||
if (!(netgame || multiplayer))
|
||||
{
|
||||
switch (P_RandomKey(10))
|
||||
{
|
||||
case 0:
|
||||
return MT_RING_ICON;
|
||||
case 1:
|
||||
return MT_SNEAKERS_ICON;
|
||||
case 2:
|
||||
return MT_INVULN_ICON;
|
||||
case 3:
|
||||
return MT_WHIRLWIND_ICON;
|
||||
case 4:
|
||||
return MT_ELEMENTAL_ICON;
|
||||
case 5:
|
||||
return MT_ATTRACT_ICON;
|
||||
case 6:
|
||||
return MT_FORCE_ICON;
|
||||
case 7:
|
||||
return MT_ARMAGEDDON_ICON;
|
||||
case 8:
|
||||
return MT_1UP_ICON;
|
||||
case 9:
|
||||
return MT_EGGMAN_ICON;
|
||||
}
|
||||
return MT_NULL;
|
||||
}
|
||||
|
||||
#define QUESTIONBOXCHANCES(type, cvar) \
|
||||
for (i = cvar.value; i; --i) spawnchance[numchoices++] = type
|
||||
QUESTIONBOXCHANCES(MT_RING_ICON, cv_superring);
|
||||
|
@ -1145,7 +1164,7 @@ void A_JetJawChomp(mobj_t *actor)
|
|||
if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)
|
||||
|| actor->target->health <= 0 || !P_CheckSight(actor, actor->target))
|
||||
{
|
||||
P_SetMobjState(actor, actor->info->spawnstate);
|
||||
P_SetMobjStateNF(actor, actor->info->spawnstate);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2835,8 +2854,8 @@ void A_BossDeath(mobj_t *mo)
|
|||
|
||||
// make sure there is a player alive for victory
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
if (playeringame[i] && ((players[i].mo && players[i].mo->health > 0)
|
||||
|| ((netgame || multiplayer) && (players[i].lives > 0 || players[i].continues > 0))))
|
||||
if (playeringame[i] && ((players[i].mo && players[i].mo->health)
|
||||
|| ((netgame || multiplayer) && (players[i].lives || players[i].continues))))
|
||||
break;
|
||||
|
||||
if (i == MAXPLAYERS)
|
||||
|
@ -3057,62 +3076,6 @@ void A_GiveWeapon(mobj_t *actor)
|
|||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
// Function: A_JumpShield
|
||||
//
|
||||
// Description: Awards the player a jump shield.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_JumpShield(mobj_t *actor)
|
||||
{
|
||||
player_t *player;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_JumpShield", actor))
|
||||
return;
|
||||
#endif
|
||||
if (!actor->target || !actor->target->player)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
player = actor->target->player;
|
||||
|
||||
P_SwitchShield(player, SH_WHIRLWIND);
|
||||
|
||||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
// Function: A_RingShield
|
||||
//
|
||||
// Description: Awards the player a ring shield.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_RingShield(mobj_t *actor)
|
||||
{
|
||||
player_t *player;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_RingShield", actor))
|
||||
return;
|
||||
#endif
|
||||
if (!actor->target || !actor->target->player)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
player = actor->target->player;
|
||||
|
||||
P_SwitchShield(player, SH_ATTRACT);
|
||||
|
||||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
// Function: A_RingBox
|
||||
//
|
||||
// Description: Awards the player 10 rings.
|
||||
|
@ -3170,6 +3133,8 @@ void A_Invincibility(mobj_t *actor)
|
|||
S_StopMusic();
|
||||
if (mariomode)
|
||||
G_GhostAddColor(GHC_INVINCIBLE);
|
||||
strlcpy(S_sfx[sfx_None].caption, "Invincibility", 14);
|
||||
S_StartCaption(sfx_None, -1, player->powers[pw_invulnerability]);
|
||||
S_ChangeMusicInternal((mariomode) ? "_minv" : "_inv", false);
|
||||
}
|
||||
}
|
||||
|
@ -3208,6 +3173,8 @@ void A_SuperSneakers(mobj_t *actor)
|
|||
S_StopMusic();
|
||||
S_ChangeMusicInternal("_shoes", false);
|
||||
}
|
||||
strlcpy(S_sfx[sfx_None].caption, "Speed shoes", 12);
|
||||
S_StartCaption(sfx_None, -1, player->powers[pw_sneakers]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3276,25 +3243,28 @@ void A_ExtraLife(mobj_t *actor)
|
|||
|
||||
// In shooter gametypes, give the player 100 rings instead of an extra life.
|
||||
if (gametype != GT_COOP && gametype != GT_COMPETITION)
|
||||
{
|
||||
P_GivePlayerRings(player, 100);
|
||||
P_PlayLivesJingle(player);
|
||||
}
|
||||
else
|
||||
P_GivePlayerLives(player, 1);
|
||||
P_PlayLivesJingle(player);
|
||||
P_GiveCoopLives(player, 1, true);
|
||||
}
|
||||
|
||||
// Function: A_BombShield
|
||||
// Function: A_GiveShield
|
||||
//
|
||||
// Description: Awards the player a bomb shield.
|
||||
// Description: Awards the player a specified shield.
|
||||
//
|
||||
// var1 = unused
|
||||
// var1 = Shield type (make with SH_ constants)
|
||||
// var2 = unused
|
||||
//
|
||||
void A_BombShield(mobj_t *actor)
|
||||
void A_GiveShield(mobj_t *actor)
|
||||
{
|
||||
player_t *player;
|
||||
UINT16 locvar1 = var1;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_BombShield", actor))
|
||||
if (LUA_CallAction("A_GiveShield", actor))
|
||||
return;
|
||||
#endif
|
||||
if (!actor->target || !actor->target->player)
|
||||
|
@ -3305,196 +3275,10 @@ void A_BombShield(mobj_t *actor)
|
|||
|
||||
player = actor->target->player;
|
||||
|
||||
// If you already have a bomb shield, use it!
|
||||
if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ARMAGEDDON)
|
||||
P_BlackOw(player);
|
||||
|
||||
// Now we know for certain that we don't have a bomb shield, so add one. :3
|
||||
P_SwitchShield(player, SH_ARMAGEDDON);
|
||||
|
||||
P_SwitchShield(player, locvar1);
|
||||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
// Function: A_WaterShield
|
||||
//
|
||||
// Description: Awards the player a water shield.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_WaterShield(mobj_t *actor)
|
||||
{
|
||||
player_t *player;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_WaterShield", actor))
|
||||
return;
|
||||
#endif
|
||||
if (!actor->target || !actor->target->player)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
player = actor->target->player;
|
||||
|
||||
P_SwitchShield(player, SH_ELEMENTAL);
|
||||
|
||||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
// Function: A_ForceShield
|
||||
//
|
||||
// Description: Awards the player a force shield.
|
||||
//
|
||||
// var1 = Number of additional hitpoints to give
|
||||
// var2 = unused
|
||||
//
|
||||
void A_ForceShield(mobj_t *actor)
|
||||
{
|
||||
player_t *player;
|
||||
INT32 locvar1 = var1;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_ForceShield", actor))
|
||||
return;
|
||||
#endif
|
||||
if (!actor->target || !actor->target->player)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (locvar1 & ~SH_FORCEHP)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Invalid number of additional hitpoints.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
player = actor->target->player;
|
||||
|
||||
P_SwitchShield(player, SH_FORCE|locvar1);
|
||||
|
||||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
// Function: A_PityShield
|
||||
//
|
||||
// Description: Awards the player a pity shield.
|
||||
// Because you fail it.
|
||||
// Your skill is not enough.
|
||||
// See you next time.
|
||||
// Bye-bye.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_PityShield(mobj_t *actor)
|
||||
{
|
||||
player_t *player;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_PityShield", actor))
|
||||
return;
|
||||
#endif
|
||||
if (!actor->target || !actor->target->player)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
player = actor->target->player;
|
||||
|
||||
P_SwitchShield(player, SH_PITY);
|
||||
|
||||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
// Function: A_FlameShield
|
||||
//
|
||||
// Description: Awards the player a flame shield.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_FlameShield(mobj_t *actor)
|
||||
{
|
||||
player_t *player;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_FlameShield", actor))
|
||||
return;
|
||||
#endif
|
||||
if (!actor->target || !actor->target->player)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
player = actor->target->player;
|
||||
|
||||
P_SwitchShield(player, SH_FLAMEAURA);
|
||||
|
||||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
// Function: A_BubbleShield
|
||||
//
|
||||
// Description: Awards the player a bubble shield.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_BubbleShield(mobj_t *actor)
|
||||
{
|
||||
player_t *player;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_BubbleShield", actor))
|
||||
return;
|
||||
#endif
|
||||
if (!actor->target || !actor->target->player)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
player = actor->target->player;
|
||||
|
||||
P_SwitchShield(player, SH_BUBBLEWRAP);
|
||||
|
||||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
// Function: A_ThunderShield
|
||||
//
|
||||
// Description: Awards the player a thunder shield.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_ThunderShield(mobj_t *actor)
|
||||
{
|
||||
player_t *player;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_ThunderShield", actor))
|
||||
return;
|
||||
#endif
|
||||
if (!actor->target || !actor->target->player)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
player = actor->target->player;
|
||||
|
||||
P_SwitchShield(player, SH_THUNDERCOIN);
|
||||
|
||||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
|
||||
// Function: A_GravityBox
|
||||
//
|
||||
// Description: Awards the player gravity boots.
|
||||
|
@ -3579,12 +3363,12 @@ void A_ParticleSpawn(mobj_t *actor)
|
|||
spawn->tics = (tic_t)actor->health;
|
||||
spawn->flags2 |= (actor->flags2 & MF2_OBJECTFLIP);
|
||||
spawn->angle += P_RandomKey(36)*ANG10; // irrelevant for default objects but might make sense for some custom ones
|
||||
if (spawn->frame & FF_ANIMATE)
|
||||
spawn->frame += P_RandomKey(spawn->state->var1);
|
||||
|
||||
actor->angle += actor->movedir;
|
||||
}
|
||||
|
||||
actor->angle += (angle_t)actor->movecount;
|
||||
actor->tics = (tic_t)actor->reactiontime;
|
||||
}
|
||||
|
||||
// Function: A_BunnyHop
|
||||
|
@ -4106,15 +3890,18 @@ void A_SetSolidSteam(mobj_t *actor)
|
|||
#endif
|
||||
actor->flags &= ~MF_NOCLIP;
|
||||
actor->flags |= MF_SOLID;
|
||||
if (P_RandomChance(FRACUNIT/8))
|
||||
if (!(actor->flags2 & MF2_AMBUSH))
|
||||
{
|
||||
if (actor->info->deathsound)
|
||||
S_StartSound(actor, actor->info->deathsound); // Hiss!
|
||||
}
|
||||
else
|
||||
{
|
||||
if (actor->info->painsound)
|
||||
S_StartSound(actor, actor->info->painsound);
|
||||
if (P_RandomChance(FRACUNIT/8))
|
||||
{
|
||||
if (actor->info->deathsound)
|
||||
S_StartSound(actor, actor->info->deathsound); // Hiss!
|
||||
}
|
||||
else
|
||||
{
|
||||
if (actor->info->painsound)
|
||||
S_StartSound(actor, actor->info->painsound);
|
||||
}
|
||||
}
|
||||
|
||||
P_SetObjectMomZ (actor, 1, true);
|
||||
|
@ -4174,12 +3961,12 @@ void A_SignPlayer(mobj_t *actor)
|
|||
of in the name. If you have a better idea, feel free
|
||||
to let me know. ~toast 2016/07/20
|
||||
*/
|
||||
actor->frame += Color_Opposite[Color_Opposite[skin->prefoppositecolor*2]*2+1];
|
||||
actor->frame += (15 - Color_Opposite[(Color_Opposite[(skin->prefoppositecolor - 1)*2] - 1)*2 + 1]);
|
||||
}
|
||||
else // Set the sign to be an appropriate background color for this player's skincolor.
|
||||
else if (actor->target->player->skincolor) // Set the sign to be an appropriate background color for this player's skincolor.
|
||||
{
|
||||
actor->color = Color_Opposite[actor->target->player->skincolor*2];
|
||||
actor->frame += Color_Opposite[actor->target->player->skincolor*2+1];
|
||||
actor->color = Color_Opposite[(actor->target->player->skincolor - 1)*2];
|
||||
actor->frame += (15 - Color_Opposite[(actor->target->player->skincolor - 1)*2 + 1]);
|
||||
}
|
||||
|
||||
if (skin->sprites[SPR2_SIGN].numframes)
|
||||
|
@ -5141,15 +4928,12 @@ void A_SlingAppear(mobj_t *actor)
|
|||
actor->movefactor = actor->threshold;
|
||||
actor->friction = 128;
|
||||
|
||||
actor->flags |= MF_SLIDEME;
|
||||
|
||||
while (mlength > 0)
|
||||
{
|
||||
spawnee = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMALLMACECHAIN);
|
||||
|
||||
P_SetTarget(&spawnee->target, actor);
|
||||
|
||||
spawnee->movecount = 0;
|
||||
spawnee->threshold = 0;
|
||||
spawnee->reactiontime = mlength;
|
||||
|
||||
|
@ -5164,129 +4948,6 @@ void A_SlingAppear(mobj_t *actor)
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Function: A_MaceRotate
|
||||
//
|
||||
// Spins an object around its target, or, swings it from side to side.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
// So NOBODY forgets:
|
||||
// actor->
|
||||
// threshold - X tilt
|
||||
// movecount - Z tilt
|
||||
// reactiontime - link # in the chain (1 is closest)
|
||||
// lastlook - speed
|
||||
// friction - top speed
|
||||
// movedir - current angle holder
|
||||
// extravalue1 - smoothly move link into place
|
||||
//
|
||||
void A_MaceRotate(mobj_t *actor)
|
||||
{
|
||||
TVector v;
|
||||
TVector *res;
|
||||
fixed_t radius;
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_MaceRotate", actor))
|
||||
return;
|
||||
#endif
|
||||
|
||||
// Target was removed.
|
||||
if (!actor->target)
|
||||
{
|
||||
P_RemoveMobj(actor);
|
||||
return;
|
||||
}
|
||||
|
||||
P_UnsetThingPosition(actor);
|
||||
|
||||
// Radius of the link's rotation.
|
||||
radius = FixedMul(actor->info->speed * actor->reactiontime, actor->target->scale);
|
||||
|
||||
// Double the radius if the chain links are made up of maces.
|
||||
if (actor->target->type == MT_AXIS && (actor->type == MT_SMALLMACE || actor->type == MT_BIGMACE))
|
||||
radius *= 2;
|
||||
|
||||
// Axis offset for the axis.
|
||||
radius += actor->target->extravalue1;
|
||||
|
||||
// Smoothly move the link into position.
|
||||
if (actor->extravalue1)
|
||||
{
|
||||
radius = FixedMul(radius, FixedDiv(actor->extravalue1, 100));
|
||||
actor->extravalue1 += 1;
|
||||
if (actor->extravalue1 >= 100)
|
||||
actor->extravalue1 = 0;
|
||||
}
|
||||
|
||||
actor->x = actor->target->x;
|
||||
actor->y = actor->target->y;
|
||||
actor->z = actor->target->z;
|
||||
|
||||
// Cut the height to align the link with the axis.
|
||||
if (actor->type == MT_SMALLMACECHAIN || actor->type == MT_BIGMACECHAIN)
|
||||
actor->z -= actor->height/4;
|
||||
else
|
||||
actor->z -= actor->height/2;
|
||||
|
||||
// Set the top speed for the link if it happens to be over that speed.
|
||||
if (actor->target->lastlook > actor->target->friction)
|
||||
actor->target->lastlook = actor->target->friction;
|
||||
|
||||
// Swinging Chain.
|
||||
if (actor->target->type == MT_HANGMACEPOINT || actor->target->type == MT_SWINGMACEPOINT)
|
||||
{
|
||||
actor->movecount += actor->target->lastlook;
|
||||
actor->movecount &= FINEMASK;
|
||||
|
||||
actor->threshold = FixedMul(FINECOSINE(actor->movecount), actor->target->lastlook << FRACBITS);
|
||||
|
||||
v[0] = FRACUNIT;
|
||||
v[1] = 0;
|
||||
v[2] = -radius;
|
||||
v[3] = FRACUNIT;
|
||||
|
||||
// Calculate the angle matrixes for the link.
|
||||
res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(actor->threshold)));
|
||||
M_Memcpy(&v, res, sizeof(v));
|
||||
res = VectorMatrixMultiply(v, *RotateZMatrix(actor->target->health << ANGLETOFINESHIFT));
|
||||
M_Memcpy(&v, res, sizeof(v));
|
||||
}
|
||||
// Rotating Chain.
|
||||
else
|
||||
{
|
||||
angle_t fa;
|
||||
|
||||
actor->threshold += actor->target->lastlook;
|
||||
actor->threshold &= FINEMASK;
|
||||
actor->target->health &= FINEMASK;
|
||||
|
||||
fa = actor->threshold;
|
||||
v[0] = FixedMul(FINECOSINE(fa), radius);
|
||||
v[1] = 0;
|
||||
v[2] = FixedMul(FINESINE(fa), radius);
|
||||
v[3] = FRACUNIT;
|
||||
|
||||
// Calculate the angle matrixes for the link.
|
||||
res = VectorMatrixMultiply(v, *RotateXMatrix(actor->target->threshold << ANGLETOFINESHIFT));
|
||||
M_Memcpy(&v, res, sizeof(v));
|
||||
res = VectorMatrixMultiply(v, *RotateZMatrix(actor->target->health << ANGLETOFINESHIFT));
|
||||
M_Memcpy(&v, res, sizeof(v));
|
||||
}
|
||||
|
||||
// Add on the appropriate distances to the actor's co-ordinates.
|
||||
actor->x += v[0];
|
||||
actor->y += v[1];
|
||||
actor->z += v[2];
|
||||
|
||||
P_SetThingPosition(actor);
|
||||
|
||||
if (!(actor->target->flags2 & MF2_BOSSNOTRAP) // flag that makes maces shut up on request
|
||||
&& !(leveltime & 63) && (actor->type == MT_BIGMACE || actor->type == MT_SMALLMACE) && actor->target->type == MT_MACEPOINT)
|
||||
S_StartSound(actor, actor->info->activesound);
|
||||
}
|
||||
|
||||
// Function: A_SetFuse
|
||||
//
|
||||
// Description: Sets the actor's fuse timer if not set already. May also change state when fuse reaches the last tic, otherwise by default the actor will die or disappear. (Replaces A_SnowBall)
|
||||
|
@ -5605,7 +5266,10 @@ void A_MixUp(mobj_t *actor)
|
|||
// No mix-up monitors in hide and seek or time only race.
|
||||
// The random factor is okay for other game modes, but in these, it is cripplingly unfair.
|
||||
if (gametype == GT_HIDEANDSEEK || gametype == GT_RACE)
|
||||
{
|
||||
S_StartSound(actor, sfx_lose);
|
||||
return;
|
||||
}
|
||||
|
||||
numplayers = 0;
|
||||
memset(teleported, 0, sizeof (teleported));
|
||||
|
@ -5623,7 +5287,10 @@ void A_MixUp(mobj_t *actor)
|
|||
}
|
||||
|
||||
if (numplayers <= 1) // Not enough players to mix up.
|
||||
{
|
||||
S_StartSound(actor, sfx_lose);
|
||||
return;
|
||||
}
|
||||
else if (numplayers == 2) // Special case -- simple swap
|
||||
{
|
||||
fixed_t x, y, z;
|
||||
|
@ -5869,7 +5536,10 @@ void A_RecyclePowers(mobj_t *actor)
|
|||
#endif
|
||||
|
||||
if (!multiplayer)
|
||||
{
|
||||
S_StartSound(actor, sfx_lose);
|
||||
return;
|
||||
}
|
||||
|
||||
numplayers = 0;
|
||||
|
||||
|
@ -5905,7 +5575,10 @@ void A_RecyclePowers(mobj_t *actor)
|
|||
}
|
||||
|
||||
if (numplayers <= 1)
|
||||
{
|
||||
S_StartSound(actor, sfx_lose);
|
||||
return; //nobody to touch!
|
||||
}
|
||||
|
||||
//shuffle the post scramble list, whee!
|
||||
// hardcoded 0-1 to 1-0 for two players
|
||||
|
@ -9385,8 +9058,8 @@ void A_ForceWin(mobj_t *actor)
|
|||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && ((players[i].mo && players[i].mo->health > 0)
|
||||
|| ((netgame || multiplayer) && (players[i].lives > 0 || players[i].continues > 0))))
|
||||
if (playeringame[i] && ((players[i].mo && players[i].mo->health)
|
||||
|| ((netgame || multiplayer) && (players[i].lives || players[i].continues))))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -10787,26 +10460,33 @@ void A_FlickyFlutter(mobj_t *actor)
|
|||
// Description: Creates the mobj's painchance at a random position around the object's radius.
|
||||
//
|
||||
// var1 = momz of particle.
|
||||
// var2 = chance of particle spawn
|
||||
//
|
||||
void A_FlameParticle(mobj_t *actor)
|
||||
{
|
||||
mobjtype_t type = (mobjtype_t)(mobjinfo[actor->type].painchance);
|
||||
fixed_t rad, hei;
|
||||
mobj_t *particle;
|
||||
INT32 locvar1 = var1;
|
||||
INT32 locvar2 = var2;
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_FlameParticle", actor))
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (type)
|
||||
{
|
||||
fixed_t rad = 2*actor->radius>>FRACBITS;
|
||||
fixed_t hei = actor->height>>FRACBITS;
|
||||
mobj_t *particle = P_SpawnMobjFromMobj(actor,
|
||||
P_RandomRange(rad, -rad)<<FRACBITS,
|
||||
P_RandomRange(rad, -rad)<<FRACBITS,
|
||||
P_RandomRange(hei/2, hei)<<FRACBITS,
|
||||
type);
|
||||
P_SetObjectMomZ(particle, locvar1<<FRACBITS, false);
|
||||
}
|
||||
if (!P_RandomChance(locvar2))
|
||||
return;
|
||||
|
||||
if (!type)
|
||||
return;
|
||||
|
||||
rad = 2*actor->radius>>FRACBITS;
|
||||
hei = actor->height>>FRACBITS;
|
||||
particle = P_SpawnMobjFromMobj(actor,
|
||||
P_RandomRange(rad, -rad)<<FRACBITS,
|
||||
P_RandomRange(rad, -rad)<<FRACBITS,
|
||||
P_RandomRange(hei/2, hei)<<FRACBITS,
|
||||
type);
|
||||
P_SetObjectMomZ(particle, locvar1<<FRACBITS, false);
|
||||
}
|
||||
|
|
|
@ -2061,6 +2061,33 @@ void T_NoEnemiesSector(levelspecthink_t *nobaddies)
|
|||
P_RemoveThinker(&nobaddies->thinker);
|
||||
}
|
||||
|
||||
//
|
||||
// P_IsObjectOnRealGround
|
||||
//
|
||||
// Helper function for T_EachTimeThinker
|
||||
// Like P_IsObjectOnGroundIn, except ONLY THE REAL GROUND IS CONSIDERED, NOT FOFS
|
||||
// I'll consider whether to make this a more globally accessible function or whatever in future
|
||||
// -- Monster Iestyn
|
||||
//
|
||||
static boolean P_IsObjectOnRealGround(mobj_t *mo, sector_t *sec)
|
||||
{
|
||||
// Is the object in reverse gravity?
|
||||
if (mo->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
// Detect if the player is on the ceiling.
|
||||
if (mo->z+mo->height >= P_GetSpecialTopZ(mo, sec, sec))
|
||||
return true;
|
||||
}
|
||||
// Nope!
|
||||
else
|
||||
{
|
||||
// Detect if the player is on the floor.
|
||||
if (mo->z <= P_GetSpecialBottomZ(mo, sec, sec))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// P_HavePlayersEnteredArea
|
||||
//
|
||||
|
@ -2113,6 +2140,7 @@ void T_EachTimeThinker(levelspecthink_t *eachtime)
|
|||
boolean inAndOut = false;
|
||||
boolean floortouch = false;
|
||||
fixed_t bottomheight, topheight;
|
||||
msecnode_t *node;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
|
@ -2174,7 +2202,23 @@ void T_EachTimeThinker(levelspecthink_t *eachtime)
|
|||
if ((netgame || multiplayer) && players[j].spectator)
|
||||
continue;
|
||||
|
||||
if (players[j].mo->subsector->sector != targetsec)
|
||||
if (players[j].mo->subsector->sector == targetsec)
|
||||
;
|
||||
else if (sec->flags & SF_TRIGGERSPECIAL_TOUCH)
|
||||
{
|
||||
boolean insector = false;
|
||||
for (node = players[j].mo->touching_sectorlist; node; node = node->m_sectorlist_next)
|
||||
{
|
||||
if (node->m_sector == targetsec)
|
||||
{
|
||||
insector = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!insector)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
topheight = P_GetSpecialTopZ(players[j].mo, sec, targetsec);
|
||||
|
@ -2224,10 +2268,30 @@ void T_EachTimeThinker(levelspecthink_t *eachtime)
|
|||
if ((netgame || multiplayer) && players[i].spectator)
|
||||
continue;
|
||||
|
||||
if (players[i].mo->subsector->sector != sec)
|
||||
if (players[i].mo->subsector->sector == sec)
|
||||
;
|
||||
else if (sec->flags & SF_TRIGGERSPECIAL_TOUCH)
|
||||
{
|
||||
boolean insector = false;
|
||||
for (node = players[i].mo->touching_sectorlist; node; node = node->m_sectorlist_next)
|
||||
{
|
||||
if (node->m_sector == sec)
|
||||
{
|
||||
insector = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!insector)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
if (floortouch == true && P_IsObjectOnGroundIn(players[i].mo, sec))
|
||||
if (!(players[i].mo->subsector->sector == sec
|
||||
|| P_PlayerTouchingSectorSpecial(&players[i], 2, (GETSECSPECIAL(sec->special, 2))) == sec))
|
||||
continue;
|
||||
|
||||
if (floortouch == true && P_IsObjectOnRealGround(players[i].mo, sec))
|
||||
{
|
||||
if (i & 1)
|
||||
eachtime->var2s[i/2] |= 1;
|
||||
|
@ -2557,6 +2621,12 @@ void T_PlaneDisplace(planedisplace_t *pd)
|
|||
direction = (control->floorheight > pd->last_height) ? 1 : -1;
|
||||
diff = FixedMul(control->floorheight-pd->last_height, pd->speed);
|
||||
|
||||
if (pd->reverse) // reverse direction?
|
||||
{
|
||||
direction *= -1;
|
||||
diff *= -1;
|
||||
}
|
||||
|
||||
if (pd->type == pd_floor || pd->type == pd_both)
|
||||
T_MovePlane(target, INT32_MAX/2, target->floorheight+diff, 0, 0, direction); // move floor
|
||||
if (pd->type == pd_ceiling || pd->type == pd_both)
|
||||
|
@ -2923,7 +2993,7 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
|
|||
fixed_t leftx, rightx;
|
||||
fixed_t topy, bottomy;
|
||||
fixed_t topz, bottomz;
|
||||
fixed_t widthfactor, heightfactor;
|
||||
fixed_t widthfactor = FRACUNIT, heightfactor = FRACUNIT;
|
||||
fixed_t a, b, c;
|
||||
mobjtype_t type = MT_ROCKCRUMBLE1;
|
||||
fixed_t spacing = (32<<FRACBITS);
|
||||
|
@ -3240,14 +3310,6 @@ INT32 EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (thing->type == MT_EMMY && thing->spawnpoint && (thing->spawnpoint->options & MTF_OBJECTSPECIAL))
|
||||
{
|
||||
mobj_t *tokenobj = P_SpawnMobj(sector->soundorg.x, sector->soundorg.y, topheight, MT_TOKEN);
|
||||
P_SetTarget(&thing->tracer, tokenobj);
|
||||
P_SetTarget(&tokenobj->target, thing);
|
||||
P_SetMobjState(tokenobj, mobjinfo[MT_TOKEN].seestate);
|
||||
}
|
||||
|
||||
// "Powerup rise" sound
|
||||
S_StartSound(puncher, sfx_mario9); // Puncher is "close enough"
|
||||
}
|
||||
|
|
376
src/p_inter.c
376
src/p_inter.c
|
@ -257,6 +257,8 @@ void P_DoMatchSuper(player_t *player)
|
|||
S_StopMusic();
|
||||
if (mariomode)
|
||||
G_GhostAddColor(GHC_INVINCIBLE);
|
||||
strlcpy(S_sfx[sfx_None].caption, "Invincibility", 14);
|
||||
S_StartCaption(sfx_None, -1, player->powers[pw_invulnerability]);
|
||||
S_ChangeMusicInternal((mariomode) ? "_minv" : "_inv", false);
|
||||
}
|
||||
|
||||
|
@ -278,6 +280,8 @@ void P_DoMatchSuper(player_t *player)
|
|||
S_StopMusic();
|
||||
if (mariomode)
|
||||
G_GhostAddColor(GHC_INVINCIBLE);
|
||||
strlcpy(S_sfx[sfx_None].caption, "Invincibility", 14);
|
||||
S_StartCaption(sfx_None, -1, player->powers[pw_invulnerability]);
|
||||
S_ChangeMusicInternal((mariomode) ? "_minv" : "_inv", false);
|
||||
}
|
||||
}
|
||||
|
@ -410,13 +414,15 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
////////////////////////////////////////////////////////
|
||||
if (special->type == MT_GSNAPPER && !(((player->powers[pw_carry] == CR_NIGHTSMODE) && (player->pflags & PF_DRILLING))
|
||||
|| player->powers[pw_invulnerability] || player->powers[pw_super] || elementalpierce)
|
||||
&& toucher->z < special->z + special->height && toucher->z + toucher->height > special->z)
|
||||
&& toucher->z < special->z + special->height && toucher->z + toucher->height > special->z
|
||||
&& !(player->powers[pw_shield] & SH_PROTECTSPIKE))
|
||||
{
|
||||
// Can only hit snapper from above
|
||||
P_DamageMobj(toucher, special, special, 1, 0);
|
||||
P_DamageMobj(toucher, special, special, 1, DMG_SPIKE);
|
||||
}
|
||||
else if (special->type == MT_SHARP
|
||||
&& ((special->state == &states[special->info->xdeathstate]) || (toucher->z > special->z + special->height/2)))
|
||||
&& ((special->state == &states[special->info->xdeathstate]) || (toucher->z > special->z + special->height/2))
|
||||
&& !(player->powers[pw_shield] & SH_PROTECTSPIKE))
|
||||
{
|
||||
if (player->pflags & PF_BOUNCING)
|
||||
{
|
||||
|
@ -424,7 +430,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
P_DoAbilityBounce(player, false);
|
||||
}
|
||||
else // Cannot hit sharp from above or when red and angry
|
||||
P_DamageMobj(toucher, special, special, 1, 0);
|
||||
P_DamageMobj(toucher, special, special, 1, DMG_SPIKE);
|
||||
}
|
||||
else if (((player->powers[pw_carry] == CR_NIGHTSMODE) && (player->pflags & PF_DRILLING))
|
||||
|| ((player->pflags & PF_JUMPED) && (!(player->pflags & PF_NOJUMPDAMAGE) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY)))
|
||||
|
@ -566,21 +572,25 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
// Gameplay related collectibles //
|
||||
// ***************************** //
|
||||
// Special Stage Token
|
||||
case MT_EMMY:
|
||||
case MT_TOKEN:
|
||||
if (player->bot)
|
||||
return;
|
||||
tokenlist += special->health;
|
||||
|
||||
P_AddPlayerScore(player, 1000);
|
||||
|
||||
if (ALL7EMERALDS(emeralds)) // Got all 7
|
||||
{
|
||||
P_GivePlayerRings(player, 50);
|
||||
nummaprings += 50; // no cheating towards Perfect!
|
||||
if (!(netgame || multiplayer))
|
||||
{
|
||||
player->continues += 1;
|
||||
players->gotcontinue = true;
|
||||
if (P_IsLocalPlayer(player))
|
||||
S_StartSound(NULL, sfx_s3kac);
|
||||
}
|
||||
}
|
||||
else
|
||||
token++;
|
||||
|
||||
if (special->tracer) // token BG
|
||||
P_RemoveMobj(special->tracer);
|
||||
break;
|
||||
|
||||
// Emerald Hunt
|
||||
|
@ -870,7 +880,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
|
||||
if (!(mo2->flags & MF_SPECIAL) && mo2->health)
|
||||
{
|
||||
P_SetMobjState(mo2, mo2->info->seestate);
|
||||
mo2->flags2 &= ~MF2_DONTDRAW;
|
||||
mo2->flags |= MF_SPECIAL;
|
||||
mo2->flags &= ~MF_NIGHTSITEM;
|
||||
S_StartSound(toucher, sfx_hidden);
|
||||
|
@ -879,7 +889,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
}
|
||||
|
||||
if (!(mo2->type == MT_NIGHTSWING || mo2->type == MT_RING || mo2->type == MT_COIN
|
||||
|| mo2->type == MT_BLUEBALL))
|
||||
|| mo2->type == MT_BLUEBALL
|
||||
|| ((mo2->type == MT_EMBLEM) && (mo2->reactiontime & GE_NIGHTSPULL))))
|
||||
continue;
|
||||
|
||||
// Yay! The thing's in reach! Pull it in!
|
||||
|
@ -1282,13 +1293,40 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
if (player->starpostnum >= special->health)
|
||||
return; // Already hit this post
|
||||
|
||||
// Save the player's time and position.
|
||||
player->starposttime = leveltime;
|
||||
player->starpostx = toucher->x>>FRACBITS;
|
||||
player->starposty = toucher->y>>FRACBITS;
|
||||
player->starpostz = special->z>>FRACBITS;
|
||||
player->starpostangle = special->angle;
|
||||
player->starpostnum = special->health;
|
||||
if (cv_coopstarposts.value && gametype == GT_COOP && (netgame || multiplayer))
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i])
|
||||
{
|
||||
if (players[i].bot) // ignore dumb, stupid tails
|
||||
continue;
|
||||
|
||||
players[i].starposttime = leveltime;
|
||||
players[i].starpostx = player->mo->x>>FRACBITS;
|
||||
players[i].starposty = player->mo->y>>FRACBITS;
|
||||
players[i].starpostz = special->z>>FRACBITS;
|
||||
players[i].starpostangle = special->angle;
|
||||
players[i].starpostnum = special->health;
|
||||
|
||||
if (cv_coopstarposts.value == 2 && (players[i].playerstate == PST_DEAD || players[i].spectator) && P_GetLives(&players[i]))
|
||||
P_SpectatorJoinGame(&players[i]); //players[i].playerstate = PST_REBORN;
|
||||
}
|
||||
}
|
||||
S_StartSound(NULL, special->info->painsound);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Save the player's time and position.
|
||||
player->starposttime = leveltime;
|
||||
player->starpostx = toucher->x>>FRACBITS;
|
||||
player->starposty = toucher->y>>FRACBITS;
|
||||
player->starpostz = special->z>>FRACBITS;
|
||||
player->starpostangle = special->angle;
|
||||
player->starpostnum = special->health;
|
||||
S_StartSound(toucher, special->info->painsound);
|
||||
}
|
||||
|
||||
P_ClearStarPost(special->health);
|
||||
|
||||
// Find all starposts in the level with this value.
|
||||
|
@ -1460,10 +1498,19 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
if (player->powers[pw_flashing])
|
||||
return;
|
||||
|
||||
if (special->movefactor && special->tracer && (angle_t)special->tracer->health != ANGLE_90 && (angle_t)special->tracer->health != ANGLE_270)
|
||||
{ // I don't expect you to understand this, Mr Bond...
|
||||
angle_t ang = R_PointToAngle2(special->x, special->y, toucher->x, toucher->y) - special->tracer->threshold;
|
||||
if ((special->movefactor > 0) == ((angle_t)special->tracer->health > ANGLE_90 && (angle_t)special->tracer->health < ANGLE_270))
|
||||
ang += ANGLE_180;
|
||||
if (ang < ANGLE_180)
|
||||
return; // I expect you to die.
|
||||
}
|
||||
|
||||
P_ResetPlayer(player);
|
||||
P_SetTarget(&toucher->tracer, special);
|
||||
|
||||
if (special->target && (special->target->type == MT_SPINMACEPOINT || special->target->type == MT_HIDDEN_SLING))
|
||||
if (special->tracer && !(special->tracer->flags2 & MF2_STRONGBOX))
|
||||
{
|
||||
player->powers[pw_carry] = CR_MACESPIN;
|
||||
S_StartSound(toucher, sfx_spin);
|
||||
|
@ -1474,6 +1521,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
|
||||
// Can't jump first frame
|
||||
player->pflags |= PF_JUMPSTASIS;
|
||||
|
||||
return;
|
||||
case MT_BIGMINE:
|
||||
case MT_BIGAIRMINE:
|
||||
|
@ -1657,7 +1705,7 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour
|
|||
if (damagetype == DMG_NUKE) // SH_ARMAGEDDON, armageddon shield
|
||||
str = M_GetText("%s%s's armageddon blast %s %s.\n");
|
||||
else if ((inflictor->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL && (inflictor->player->pflags & PF_SHIELDABILITY))
|
||||
str = M_GetText("%s%s's flame stomp %s %s.\n");
|
||||
str = M_GetText("%s%s's elemental stomp %s %s.\n");
|
||||
else if (inflictor->player->powers[pw_invulnerability])
|
||||
str = M_GetText("%s%s's invincibility aura %s %s.\n");
|
||||
else if (inflictor->player->powers[pw_super])
|
||||
|
@ -1711,6 +1759,7 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour
|
|||
str = M_GetText("%s was %s by Eggman's nefarious TV magic.\n");
|
||||
break;
|
||||
case MT_SPIKE:
|
||||
case MT_WALLSPIKE:
|
||||
str = M_GetText("%s was %s by spikes.\n");
|
||||
break;
|
||||
default:
|
||||
|
@ -2097,7 +2146,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
{
|
||||
if (metalrecording) // Ack! Metal Sonic shouldn't die! Cut the tape, end recording!
|
||||
G_StopMetalRecording();
|
||||
if (gametype == GT_MATCH && cv_match_scoring.value == 0 // note, no team match suicide penalty
|
||||
if (gametype == GT_MATCH // note, no team match suicide penalty
|
||||
&& ((target == source) || (source == NULL && inflictor == NULL) || (source && !source->player)))
|
||||
{ // Suicide penalty
|
||||
if (target->player->score >= 50)
|
||||
|
@ -2208,14 +2257,34 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
target->flags |= MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY;
|
||||
P_SetThingPosition(target);
|
||||
|
||||
if (!target->player->bot && !G_IsSpecialStage(gamemap)
|
||||
if ((target->player->lives <= 1) && (netgame || multiplayer) && (gametype == GT_COOP) && (cv_cooplives.value == 0))
|
||||
;
|
||||
else if (!target->player->bot && !target->player->spectator && !G_IsSpecialStage(gamemap)
|
||||
&& G_GametypeUsesLives())
|
||||
{
|
||||
target->player->lives -= 1; // Lose a life Tails 03-11-2000
|
||||
|
||||
if (target->player->lives <= 0) // Tails 03-14-2000
|
||||
{
|
||||
if (P_IsLocalPlayer(target->player)/* && target->player == &players[consoleplayer] */)
|
||||
boolean gameovermus = false;
|
||||
if ((netgame || multiplayer) && (gametype == GT_COOP) && (cv_cooplives.value != 1))
|
||||
{
|
||||
INT32 i;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
if (players[i].lives > 0)
|
||||
break;
|
||||
}
|
||||
if (i == MAXPLAYERS)
|
||||
gameovermus = true;
|
||||
}
|
||||
else if (P_IsLocalPlayer(target->player))
|
||||
gameovermus = true;
|
||||
|
||||
if (gameovermus)
|
||||
{
|
||||
S_StopMusic(); // Stop the Music! Tails 03-14-2000
|
||||
S_ChangeMusicInternal("_gover", false); // Yousa dead now, Okieday? Tails 03-14-2000
|
||||
|
@ -2387,7 +2456,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
else
|
||||
{
|
||||
P_SetObjectMomZ(target, 14*FRACUNIT, false);
|
||||
if ((source && source->type == MT_SPIKE) || damagetype == DMG_SPIKE) // Spikes
|
||||
if (damagetype == DMG_SPIKE) // Spikes
|
||||
S_StartSound(target, sfx_spkdth);
|
||||
else
|
||||
P_PlayDeathSound(target);
|
||||
|
@ -2449,90 +2518,159 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
}
|
||||
}
|
||||
|
||||
if (target->type == MT_SPIKE && inflictor && target->info->deathstate != S_NULL)
|
||||
if (target->type == MT_SPIKE && target->info->deathstate != S_NULL)
|
||||
{
|
||||
const fixed_t x=target->x,y=target->y,z=target->z;
|
||||
const fixed_t scale=target->scale;
|
||||
const boolean flip=(target->eflags & MFE_VERTICALFLIP) == MFE_VERTICALFLIP;
|
||||
S_StartSound(target,target->info->deathsound);
|
||||
const angle_t ang = ((inflictor) ? inflictor->angle : 0) + ANGLE_90;
|
||||
const fixed_t scale = target->scale;
|
||||
const fixed_t xoffs = P_ReturnThrustX(target, ang, 8*scale), yoffs = P_ReturnThrustY(target, ang, 8*scale);
|
||||
const UINT16 flip = (target->eflags & MFE_VERTICALFLIP);
|
||||
mobj_t *chunk;
|
||||
fixed_t momz;
|
||||
|
||||
P_SetMobjState(target, target->info->deathstate);
|
||||
target->health = 0;
|
||||
target->angle = inflictor->angle + ANGLE_90;
|
||||
P_UnsetThingPosition(target);
|
||||
target->flags = MF_NOCLIP;
|
||||
target->x += P_ReturnThrustX(target, target->angle, FixedMul(8*FRACUNIT, target->scale));
|
||||
target->y += P_ReturnThrustY(target, target->angle, FixedMul(8*FRACUNIT, target->scale));
|
||||
if (flip)
|
||||
target->z -= FixedMul(12*FRACUNIT, target->scale);
|
||||
else
|
||||
target->z += FixedMul(12*FRACUNIT, target->scale);
|
||||
P_SetThingPosition(target);
|
||||
P_InstaThrust(target,target->angle,FixedMul(2*FRACUNIT, target->scale));
|
||||
target->momz = FixedMul(7*FRACUNIT, target->scale);
|
||||
if (flip)
|
||||
target->momz = -target->momz;
|
||||
|
||||
if (flip)
|
||||
{
|
||||
target = P_SpawnMobj(x,y,z-FixedMul(12*FRACUNIT, target->scale),MT_SPIKE);
|
||||
target->eflags |= MFE_VERTICALFLIP;
|
||||
}
|
||||
else
|
||||
target = P_SpawnMobj(x,y,z+FixedMul(12*FRACUNIT, target->scale),MT_SPIKE);
|
||||
P_SetMobjState(target, target->info->deathstate);
|
||||
target->health = 0;
|
||||
target->angle = inflictor->angle - ANGLE_90;
|
||||
target->destscale = scale;
|
||||
P_SetScale(target, scale);
|
||||
P_UnsetThingPosition(target);
|
||||
target->flags = MF_NOCLIP;
|
||||
target->x += P_ReturnThrustX(target, target->angle, FixedMul(8*FRACUNIT, target->scale));
|
||||
target->y += P_ReturnThrustY(target, target->angle, FixedMul(8*FRACUNIT, target->scale));
|
||||
P_SetThingPosition(target);
|
||||
P_InstaThrust(target,target->angle,FixedMul(2*FRACUNIT, target->scale));
|
||||
target->momz = FixedMul(7*FRACUNIT, target->scale);
|
||||
if (flip)
|
||||
target->momz = -target->momz;
|
||||
S_StartSound(target, target->info->deathsound);
|
||||
|
||||
if (target->info->xdeathstate != S_NULL)
|
||||
{
|
||||
target = P_SpawnMobj(x,y,z,MT_SPIKE);
|
||||
momz = 6*scale;
|
||||
if (flip)
|
||||
target->eflags |= MFE_VERTICALFLIP;
|
||||
P_SetMobjState(target, target->info->xdeathstate);
|
||||
target->health = 0;
|
||||
target->angle = inflictor->angle + ANGLE_90;
|
||||
target->destscale = scale;
|
||||
P_SetScale(target, scale);
|
||||
P_UnsetThingPosition(target);
|
||||
target->flags = MF_NOCLIP;
|
||||
target->x += P_ReturnThrustX(target, target->angle, FixedMul(8*FRACUNIT, target->scale));
|
||||
target->y += P_ReturnThrustY(target, target->angle, FixedMul(8*FRACUNIT, target->scale));
|
||||
P_SetThingPosition(target);
|
||||
P_InstaThrust(target,target->angle,FixedMul(4*FRACUNIT, target->scale));
|
||||
target->momz = FixedMul(6*FRACUNIT, target->scale);
|
||||
if (flip)
|
||||
target->momz = -target->momz;
|
||||
momz *= -1;
|
||||
#define makechunk(angtweak, xmov, ymov) \
|
||||
chunk = P_SpawnMobj(target->x, target->y, target->z, MT_SPIKE);\
|
||||
chunk->eflags |= flip;\
|
||||
P_SetMobjState(chunk, target->info->xdeathstate);\
|
||||
chunk->health = 0;\
|
||||
chunk->angle = angtweak;\
|
||||
chunk->destscale = scale;\
|
||||
P_SetScale(chunk, scale);\
|
||||
P_UnsetThingPosition(chunk);\
|
||||
chunk->flags = MF_NOCLIP;\
|
||||
chunk->x += xmov;\
|
||||
chunk->y += ymov;\
|
||||
P_SetThingPosition(chunk);\
|
||||
P_InstaThrust(chunk,chunk->angle, 4*scale);\
|
||||
chunk->momz = momz
|
||||
|
||||
target = P_SpawnMobj(x,y,z,MT_SPIKE);
|
||||
if (flip)
|
||||
target->eflags |= MFE_VERTICALFLIP;
|
||||
P_SetMobjState(target, target->info->xdeathstate);
|
||||
target->health = 0;
|
||||
target->angle = inflictor->angle - ANGLE_90;
|
||||
target->destscale = scale;
|
||||
P_SetScale(target, scale);
|
||||
P_UnsetThingPosition(target);
|
||||
target->flags = MF_NOCLIP;
|
||||
target->x += P_ReturnThrustX(target, target->angle, FixedMul(8*FRACUNIT, target->scale));
|
||||
target->y += P_ReturnThrustY(target, target->angle, FixedMul(8*FRACUNIT, target->scale));
|
||||
P_SetThingPosition(target);
|
||||
P_InstaThrust(target,target->angle,FixedMul(4*FRACUNIT, target->scale));
|
||||
target->momz = FixedMul(6*FRACUNIT, target->scale);
|
||||
if (flip)
|
||||
target->momz = -target->momz;
|
||||
makechunk(ang + ANGLE_180, -xoffs, -yoffs);
|
||||
makechunk(ang, xoffs, yoffs);
|
||||
|
||||
#undef makechunk
|
||||
}
|
||||
|
||||
momz = 7*scale;
|
||||
if (flip)
|
||||
momz *= -1;
|
||||
|
||||
chunk = P_SpawnMobj(target->x, target->y, target->z, MT_SPIKE);
|
||||
chunk->eflags |= flip;
|
||||
|
||||
P_SetMobjState(chunk, target->info->deathstate);
|
||||
chunk->health = 0;
|
||||
chunk->angle = ang + ANGLE_180;
|
||||
chunk->destscale = scale;
|
||||
P_SetScale(chunk, scale);
|
||||
P_UnsetThingPosition(chunk);
|
||||
chunk->flags = MF_NOCLIP;
|
||||
chunk->x -= xoffs;
|
||||
chunk->y -= yoffs;
|
||||
if (flip)
|
||||
chunk->z -= 12*scale;
|
||||
else
|
||||
chunk->z += 12*scale;
|
||||
P_SetThingPosition(chunk);
|
||||
P_InstaThrust(chunk, chunk->angle, 2*scale);
|
||||
chunk->momz = momz;
|
||||
|
||||
P_SetMobjState(target, target->info->deathstate);
|
||||
target->health = 0;
|
||||
target->angle = ang;
|
||||
P_UnsetThingPosition(target);
|
||||
target->flags = MF_NOCLIP;
|
||||
target->x += xoffs;
|
||||
target->y += yoffs;
|
||||
target->z = chunk->z;
|
||||
P_SetThingPosition(target);
|
||||
P_InstaThrust(target, target->angle, 2*scale);
|
||||
target->momz = momz;
|
||||
}
|
||||
else if (target->type == MT_WALLSPIKE && target->info->deathstate != S_NULL)
|
||||
{
|
||||
const angle_t ang = (/*(inflictor) ? inflictor->angle : */target->angle) + ANGLE_90;
|
||||
const fixed_t scale = target->scale;
|
||||
const fixed_t xoffs = P_ReturnThrustX(target, ang, 8*scale), yoffs = P_ReturnThrustY(target, ang, 8*scale), forwardxoffs = P_ReturnThrustX(target, target->angle, 7*scale), forwardyoffs = P_ReturnThrustY(target, target->angle, 7*scale);
|
||||
const UINT16 flip = (target->eflags & MFE_VERTICALFLIP);
|
||||
mobj_t *chunk;
|
||||
boolean sprflip;
|
||||
|
||||
S_StartSound(target, target->info->deathsound);
|
||||
if (!P_MobjWasRemoved(target->tracer))
|
||||
P_RemoveMobj(target->tracer);
|
||||
|
||||
if (target->info->xdeathstate != S_NULL)
|
||||
{
|
||||
sprflip = P_RandomChance(FRACUNIT/2);
|
||||
|
||||
#define makechunk(angtweak, xmov, ymov) \
|
||||
chunk = P_SpawnMobj(target->x, target->y, target->z, MT_WALLSPIKE);\
|
||||
chunk->eflags |= flip;\
|
||||
P_SetMobjState(chunk, target->info->xdeathstate);\
|
||||
chunk->health = 0;\
|
||||
chunk->angle = target->angle;\
|
||||
chunk->destscale = scale;\
|
||||
P_SetScale(chunk, scale);\
|
||||
P_UnsetThingPosition(chunk);\
|
||||
chunk->flags = MF_NOCLIP;\
|
||||
chunk->x += xmov - forwardxoffs;\
|
||||
chunk->y += ymov - forwardyoffs;\
|
||||
P_SetThingPosition(chunk);\
|
||||
P_InstaThrust(chunk, angtweak, 4*scale);\
|
||||
chunk->momz = P_RandomRange(5, 7)*scale;\
|
||||
if (flip)\
|
||||
chunk->momz *= -1;\
|
||||
if (sprflip)\
|
||||
chunk->frame |= FF_VERTICALFLIP
|
||||
|
||||
makechunk(ang + ANGLE_180, -xoffs, -yoffs);
|
||||
sprflip = !sprflip;
|
||||
makechunk(ang, xoffs, yoffs);
|
||||
|
||||
#undef makechunk
|
||||
}
|
||||
|
||||
sprflip = P_RandomChance(FRACUNIT/2);
|
||||
|
||||
chunk = P_SpawnMobj(target->x, target->y, target->z, MT_WALLSPIKE);
|
||||
chunk->eflags |= flip;
|
||||
|
||||
P_SetMobjState(chunk, target->info->deathstate);
|
||||
chunk->health = 0;
|
||||
chunk->angle = target->angle;
|
||||
chunk->destscale = scale;
|
||||
P_SetScale(chunk, scale);
|
||||
P_UnsetThingPosition(chunk);
|
||||
chunk->flags = MF_NOCLIP;
|
||||
chunk->x += forwardxoffs - xoffs;
|
||||
chunk->y += forwardyoffs - yoffs;
|
||||
P_SetThingPosition(chunk);
|
||||
P_InstaThrust(chunk, ang + ANGLE_180, 2*scale);
|
||||
chunk->momz = P_RandomRange(5, 7)*scale;
|
||||
if (flip)
|
||||
chunk->momz *= -1;
|
||||
if (sprflip)
|
||||
chunk->frame |= FF_VERTICALFLIP;
|
||||
|
||||
P_SetMobjState(target, target->info->deathstate);
|
||||
target->health = 0;
|
||||
P_UnsetThingPosition(target);
|
||||
target->flags = MF_NOCLIP;
|
||||
target->x += forwardxoffs + xoffs;
|
||||
target->y += forwardyoffs + yoffs;
|
||||
P_SetThingPosition(target);
|
||||
P_InstaThrust(target, ang, 2*scale);
|
||||
target->momz = P_RandomRange(5, 7)*scale;
|
||||
if (flip)
|
||||
target->momz *= -1;
|
||||
if (!sprflip)
|
||||
target->frame |= FF_VERTICALFLIP;
|
||||
}
|
||||
else if (target->player)
|
||||
{
|
||||
|
@ -2868,7 +3006,7 @@ static void P_ShieldDamage(player_t *player, mobj_t *inflictor, mobj_t *source,
|
|||
|
||||
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
|
||||
|
||||
if ((source && source->type == MT_SPIKE) || damagetype == DMG_SPIKE) // spikes
|
||||
if (damagetype == DMG_SPIKE) // spikes
|
||||
S_StartSound(player->mo, sfx_spkdth);
|
||||
else
|
||||
S_StartSound (player->mo, sfx_shldls); // Ba-Dum! Shield loss.
|
||||
|
@ -2887,7 +3025,7 @@ static void P_ShieldDamage(player_t *player, mobj_t *inflictor, mobj_t *source,
|
|||
{
|
||||
// Award no points when players shoot each other when cv_friendlyfire is on.
|
||||
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
|
||||
P_AddPlayerScore(source->player, cv_match_scoring.value == 1 ? 25 : 50);
|
||||
P_AddPlayerScore(source->player, 50);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2897,7 +3035,7 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN
|
|||
|
||||
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
|
||||
|
||||
if ((source && source->type == MT_SPIKE) || damagetype == DMG_SPIKE) // spikes
|
||||
if (damagetype == DMG_SPIKE) // spikes
|
||||
S_StartSound(player->mo, sfx_spkdth);
|
||||
|
||||
if (source && source->player && !player->powers[pw_super]) //don't score points against super players
|
||||
|
@ -3075,18 +3213,16 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
|
||||
switch (damagetype)
|
||||
{
|
||||
case DMG_WATER:
|
||||
if (player->powers[pw_shield] & SH_PROTECTWATER)
|
||||
return false; // Invincible to water damage
|
||||
break;
|
||||
case DMG_FIRE:
|
||||
if (player->powers[pw_shield] & SH_PROTECTFIRE)
|
||||
return false; // Invincible to fire damage
|
||||
break;
|
||||
case DMG_ELECTRIC:
|
||||
if (player->powers[pw_shield] & SH_PROTECTELECTRIC)
|
||||
return false; // Invincible to electric damage
|
||||
break;
|
||||
#define DAMAGECASE(type)\
|
||||
case DMG_##type:\
|
||||
if (player->powers[pw_shield] & SH_PROTECT##type)\
|
||||
return false;\
|
||||
break
|
||||
DAMAGECASE(WATER);
|
||||
DAMAGECASE(FIRE);
|
||||
DAMAGECASE(ELECTRIC);
|
||||
DAMAGECASE(SPIKE);
|
||||
#undef DAMAGECASE
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -3120,14 +3256,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
return false; // Don't get hurt by fire generated from friends.
|
||||
}
|
||||
|
||||
// Sudden-Death mode
|
||||
if (source && source->type == MT_PLAYER)
|
||||
{
|
||||
if ((gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF) && cv_suddendeath.value
|
||||
&& !player->powers[pw_flashing] && !player->powers[pw_invulnerability])
|
||||
damagetype = DMG_INSTAKILL;
|
||||
}
|
||||
|
||||
// Player hits another player
|
||||
if (!force && source && source->player)
|
||||
{
|
||||
|
|
|
@ -72,7 +72,6 @@
|
|||
|
||||
// both the head and tail of the thinker list
|
||||
extern thinker_t thinkercap;
|
||||
extern INT32 runcount;
|
||||
|
||||
void P_InitThinkers(void);
|
||||
void P_AddThinker(thinker_t *thinker);
|
||||
|
@ -149,6 +148,7 @@ void P_SwitchShield(player_t *player, UINT16 shieldtype);
|
|||
mobj_t *P_SpawnGhostMobj(mobj_t *mobj);
|
||||
void P_GivePlayerRings(player_t *player, INT32 num_rings);
|
||||
void P_GivePlayerLives(player_t *player, INT32 numlives);
|
||||
void P_GiveCoopLives(player_t *player, INT32 numlives, boolean sound);
|
||||
UINT8 P_GetNextEmerald(void);
|
||||
void P_GiveEmerald(boolean spawnObj);
|
||||
#if 0
|
||||
|
@ -199,6 +199,9 @@ void P_PlayLivesJingle(player_t *player);
|
|||
#define P_PlayDeathSound(s) S_StartSound(s, sfx_altdi1 + P_RandomKey(4));
|
||||
#define P_PlayVictorySound(s) S_StartSound(s, sfx_victr1 + P_RandomKey(4));
|
||||
|
||||
boolean P_GetLives(player_t *player);
|
||||
boolean P_SpectatorJoinGame(player_t *player);
|
||||
void P_RestoreMultiMusic(player_t *player);
|
||||
|
||||
//
|
||||
// P_MOBJ
|
||||
|
@ -225,7 +228,6 @@ void P_PrecipitationEffects(void);
|
|||
void P_RemoveMobj(mobj_t *th);
|
||||
boolean P_MobjWasRemoved(mobj_t *th);
|
||||
void P_RemoveSavegameMobj(mobj_t *th);
|
||||
UINT8 P_GetMobjSprite2(mobj_t *mobj, UINT8 spr2);
|
||||
boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state);
|
||||
boolean P_SetMobjState(mobj_t *mobj, statenum_t state);
|
||||
void P_RunShields(void);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue