diff --git a/CMakeLists.txt b/CMakeLists.txt index cb93d22f0..31597f399 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.0) project(SRB2 - VERSION 2.1.14 + VERSION 2.1.17 LANGUAGES C) if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR}) diff --git a/SRB2.cbp b/SRB2.cbp index 99a712264..88dc400fe 100644 --- a/SRB2.cbp +++ b/SRB2.cbp @@ -14,7 +14,7 @@ If you are compiling for Windows, use Mingw targets Interface Defines: _WINDOWS for DirectX Interface SDL for SDL Interface -HAVE_MIXER for SDL_Mixer +HAVE_MIXER for SDL2_mixer HAVE_PNG for PNG support (for APNG support. compile libs/libpng-src) HWRENDER for hardware render support @@ -31,7 +31,7 @@ HW3SOUND for 3D hardware sound support <Option compiler="gcc" /> <Compiler> <Add option="-g" /> - <Add option="`sdl-config --cflags`" /> + <Add option="`sdl2-config --cflags`" /> <Add option="-DDIRECTFULLSCREEN" /> <Add option="-DHAVE_SDL" /> <Add option="-DPARANOIA" /> @@ -41,8 +41,8 @@ HW3SOUND for 3D hardware sound support <Add option="-DHAVE_BLUA" /> </Compiler> <Linker> - <Add option="`sdl-config --libs`" /> - <Add library="SDL_mixer" /> + <Add option="`sdl2-config --libs`" /> + <Add library="SDL2_mixer" /> </Linker> </Target> <Target title="Release Native/SDL"> @@ -54,7 +54,7 @@ HW3SOUND for 3D hardware sound support <Compiler> <Add option="-O2" /> <Add option="-g" /> - <Add option="`sdl-config --cflags`" /> + <Add option="`sdl2-config --cflags`" /> <Add option="-DDIRECTFULLSCREEN" /> <Add option="-DHAVE_SDL" /> <Add option="-DNDEBUG" /> @@ -62,8 +62,8 @@ HW3SOUND for 3D hardware sound support <Add option="-DHAVE_BLUA" /> </Compiler> <Linker> - <Add option="`sdl-config --libs`" /> - <Add library="SDL_mixer" /> + <Add option="`sdl2-config --libs`" /> + <Add library="SDL2_mixer" /> </Linker> </Target> <Target title="Debug Linux/SDL"> @@ -74,7 +74,7 @@ HW3SOUND for 3D hardware sound support <Option compiler="gcc" /> <Compiler> <Add option="-g" /> - <Add option="`sdl-config --cflags`" /> + <Add option="`sdl2-config --cflags`" /> <Add option="`libpng-config --cflags`" /> <Add option="-DDIRECTFULLSCREEN" /> <Add option="-DHAVE_SDL" /> @@ -89,9 +89,9 @@ HW3SOUND for 3D hardware sound support <Add option="-DHAVE_BLUA" /> </Compiler> <Linker> - <Add option="`sdl-config --libs`" /> + <Add option="`sdl2-config --libs`" /> <Add option="`libpng-config --libs`" /> - <Add library="SDL_mixer" /> + <Add library="SDL2_mixer" /> <Add library="rt" /> </Linker> </Target> @@ -104,7 +104,7 @@ HW3SOUND for 3D hardware sound support <Compiler> <Add option="-O2" /> <Add option="-g" /> - <Add option="`sdl-config --cflags`" /> + <Add option="`sdl2-config --cflags`" /> <Add option="`libpng-config --cflags`" /> <Add option="-DDIRECTFULLSCREEN" /> <Add option="-DHAVE_SDL" /> @@ -117,9 +117,9 @@ HW3SOUND for 3D hardware sound support <Add option="-DHAVE_BLUA" /> </Compiler> <Linker> - <Add option="`sdl-config --libs`" /> + <Add option="`sdl2-config --libs`" /> <Add option="`libpng-config --libs`" /> - <Add library="SDL_mixer" /> + <Add library="SDL2_mixer" /> <Add library="rt" /> </Linker> </Target> @@ -152,6 +152,8 @@ HW3SOUND for 3D hardware sound support <Add directory="libs/libpng-src" /> <Add directory="libs/zlib" /> <Add directory="libs/gme/include" /> + <Add directory="libs/SDL2/include" /> + <Add directory="libs/SDL2_mixer/include" /> </Compiler> <Linker> <Add library="SDL2" /> @@ -167,6 +169,8 @@ HW3SOUND for 3D hardware sound support <Add directory="libs/zlib/win32" /> <Add directory="libs/libpng-src/projects" /> <Add directory="libs/gme/win32" /> + <Add directory="libs/SDL2/lib/x86" /> + <Add directory="libs/SDL2_mixer/lib/x86" /> </Linker> </Target> <Target title="Release Mingw/SDL"> @@ -198,6 +202,8 @@ HW3SOUND for 3D hardware sound support <Add directory="libs/libpng-src" /> <Add directory="libs/zlib" /> <Add directory="libs/gme/include" /> + <Add directory="libs/SDL2/include" /> + <Add directory="libs/SDL2_mixer/include" /> </Compiler> <Linker> <Add library="SDL2" /> @@ -213,6 +219,8 @@ HW3SOUND for 3D hardware sound support <Add directory="libs/zlib/win32" /> <Add directory="libs/libpng-src/projects" /> <Add directory="libs/gme/win32" /> + <Add directory="libs/SDL2/lib/x86" /> + <Add directory="libs/SDL2_mixer/lib/x86" /> </Linker> </Target> <Target title="Debug Mingw/DirectX"> @@ -567,7 +575,7 @@ HW3SOUND for 3D hardware sound support <Linker> <Add option="-g" /> <Add library="SDL" /> - <Add library="SDL_mixer" /> + <Add library="SDL2_mixer" /> <Add library="advapi32" /> <Add library="kernel32" /> <Add library="msvcrt" /> @@ -606,7 +614,7 @@ HW3SOUND for 3D hardware sound support <Linker> <Add option="-g" /> <Add library="SDL" /> - <Add library="SDL_mixer" /> + <Add library="SDL2_mixer" /> <Add library="advapi32" /> <Add library="kernel32" /> <Add library="msvcrt" /> @@ -884,385 +892,90 @@ HW3SOUND for 3D hardware sound support <Unit filename="cpdebug.mk" /> <Unit filename="src/am_map.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/am_map.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/am_map.h" /> <Unit filename="src/b_bot.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/b_bot.h" /> <Unit filename="src/blua/lapi.c"> <Option compilerVar="CC" /> - <Option target="Debug Native/SDL" /> - <Option target="Release Native/SDL" /> - <Option target="Debug Linux/SDL" /> - <Option target="Release Linux/SDL" /> - <Option target="Debug Mingw/SDL" /> - <Option target="Release Mingw/SDL" /> - <Option target="Debug Mingw/DirectX" /> - <Option target="Release Mingw/DirectX" /> - <Option target="Debug Mingw64/SDL" /> - <Option target="Release Mingw64/SDL" /> - <Option target="Debug Mingw64/DirectX" /> - <Option target="Release Mingw64/DirectX" /> </Unit> <Unit filename="src/blua/lapi.h" /> <Unit filename="src/blua/lauxlib.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 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/blua/lauxlib.h" /> <Unit filename="src/blua/lbaselib.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 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/blua/lcode.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 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/blua/lcode.h" /> <Unit filename="src/blua/ldebug.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 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/blua/ldebug.h" /> <Unit filename="src/blua/ldo.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 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/blua/ldo.h" /> <Unit filename="src/blua/ldump.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 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/blua/lfunc.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 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/blua/lfunc.h" /> <Unit filename="src/blua/lgc.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 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/blua/lgc.h" /> <Unit filename="src/blua/linit.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 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/blua/llex.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 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/blua/llex.h" /> <Unit filename="src/blua/llimits.h" /> <Unit filename="src/blua/lmem.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 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/blua/lmem.h" /> <Unit filename="src/blua/lobject.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 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/blua/lobject.h" /> <Unit filename="src/blua/lopcodes.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 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/blua/lopcodes.h" /> <Unit filename="src/blua/lparser.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 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/blua/lparser.h" /> <Unit filename="src/blua/lstate.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 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/blua/lstate.h" /> <Unit filename="src/blua/lstring.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 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/blua/lstring.h" /> <Unit filename="src/blua/lstrlib.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 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/blua/ltable.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 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/blua/ltable.h" /> <Unit filename="src/blua/ltablib.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 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/blua/ltm.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 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/blua/ltm.h" /> <Unit filename="src/blua/lua.h" /> @@ -1270,478 +983,62 @@ HW3SOUND for 3D hardware sound support <Unit filename="src/blua/lualib.h" /> <Unit filename="src/blua/lundump.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 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/blua/lundump.h" /> <Unit filename="src/blua/lvm.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 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/blua/lvm.h" /> <Unit filename="src/blua/lzio.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 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/blua/lzio.h" /> - <Unit filename="src/byteptr.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/byteptr.h" /> <Unit filename="src/command.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/command.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/command.h" /> <Unit filename="src/comptime.c"> <Option compilerVar="CC" /> <Option weight="100" /> - <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/comptime.h" /> <Unit filename="src/console.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/console.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/console.h" /> <Unit filename="src/d_clisrv.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/d_clisrv.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/d_event.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/d_clisrv.h" /> + <Unit filename="src/d_event.h" /> <Unit filename="src/d_main.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/d_main.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/d_main.h" /> <Unit filename="src/d_net.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/d_net.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/d_net.h" /> <Unit filename="src/d_netcmd.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/d_netcmd.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/d_netcmd.h" /> <Unit filename="src/d_netfil.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/d_netfil.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/d_player.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/d_think.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/d_ticcmd.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/d_netfil.h" /> + <Unit filename="src/d_player.h" /> + <Unit filename="src/d_think.h" /> + <Unit filename="src/d_ticcmd.h" /> <Unit filename="src/dehacked.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/dehacked.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/doomdata.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/doomdef.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/doomstat.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/doomtype.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/dehacked.h" /> + <Unit filename="src/doomdata.h" /> + <Unit filename="src/doomdef.h" /> + <Unit filename="src/doomstat.h" /> + <Unit filename="src/doomtype.h" /> <Unit filename="src/dummy/i_cdmus.c"> <Option compilerVar="CC" /> <Option target="Debug Any/Dummy" /> @@ -1772,187 +1069,28 @@ HW3SOUND for 3D hardware sound support <Option target="Debug Any/Dummy" /> <Option target="Release Any/Dummy" /> </Unit> + <Unit filename="src/endian.h" /> <Unit filename="src/f_finale.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/f_finale.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/f_finale.h" /> <Unit filename="src/f_wipe.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/fastcmp.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/fastcmp.h" /> <Unit filename="src/filesrch.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/filesrch.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/filesrch.h" /> <Unit filename="src/g_game.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/g_game.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/g_game.h" /> <Unit filename="src/g_input.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/g_input.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/g_state.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/g_input.h" /> + <Unit filename="src/g_state.h" /> <Unit filename="src/hardware/hw3dsdrv.h"> <Option target="Debug Native/SDL" /> <Option target="Release Native/SDL" /> @@ -2353,1811 +1491,268 @@ HW3SOUND for 3D hardware sound support </Unit> <Unit filename="src/hu_stuff.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/hu_stuff.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/i_joy.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/i_net.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/i_sound.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/i_system.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 filename="src/hu_stuff.h" /> + <Unit filename="src/i_addrinfo.c"> + <Option compilerVar="CC" /> + <Option compile="0" /> + <Option link="0" /> </Unit> + <Unit filename="src/i_addrinfo.h" /> + <Unit filename="src/i_joy.h" /> + <Unit filename="src/i_net.h" /> + <Unit filename="src/i_sound.h" /> + <Unit filename="src/i_system.h" /> <Unit filename="src/i_tcp.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/i_tcp.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/i_video.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/i_tcp.h" /> + <Unit filename="src/i_video.h" /> <Unit filename="src/info.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/info.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/keys.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/info.h" /> + <Unit filename="src/keys.h" /> <Unit filename="src/lua_baselib.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 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/lua_blockmaplib.c"> + <Option compilerVar="CC" /> </Unit> <Unit filename="src/lua_consolelib.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 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/lua_hook.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 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/lua_hook.h" /> <Unit filename="src/lua_hooklib.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 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/lua_hud.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 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/lua_hud.h" /> <Unit filename="src/lua_hudlib.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 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/lua_infolib.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 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/lua_libs.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 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/lua_libs.h" /> <Unit filename="src/lua_maplib.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 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/lua_mathlib.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 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/lua_mobjlib.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 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/lua_playerlib.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 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/lua_script.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 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/lua_script.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 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/lua_script.h" /> <Unit filename="src/lua_skinlib.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 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/lua_thinkerlib.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 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/lzf.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/lzf.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/lzf.h" /> <Unit filename="src/m_aatree.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/m_aatree.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/m_aatree.h" /> <Unit filename="src/m_anigif.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/m_anigif.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/m_anigif.h" /> <Unit filename="src/m_argv.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/m_argv.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/m_argv.h" /> <Unit filename="src/m_bbox.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/m_bbox.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/m_bbox.h" /> <Unit filename="src/m_cheat.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/m_cheat.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/m_cheat.h" /> <Unit filename="src/m_cond.c"> <Option compilerVar="CC" /> - <Option target="Debug Native/SDL" /> - <Option target="Release Native/SDL" /> - <Option target="Debug Linux/SDL" /> - <Option target="Release Linux/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 Mingw64/SDL" /> - <Option target="Release Mingw64/SDL" /> - <Option target="Debug Mingw64/DirectX" /> - <Option target="Release Mingw64/DirectX" /> - </Unit> - <Unit filename="src/m_cond.h"> - <Option target="Debug Native/SDL" /> - <Option target="Release Native/SDL" /> - <Option target="Debug Linux/SDL" /> - <Option target="Release Linux/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 Mingw64/SDL" /> - <Option target="Release Mingw64/SDL" /> - <Option target="Debug Mingw64/DirectX" /> - <Option target="Release Mingw64/DirectX" /> - </Unit> - <Unit filename="src/m_dllist.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/m_cond.h" /> + <Unit filename="src/m_dllist.h" /> <Unit filename="src/m_fixed.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/m_fixed.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/m_fixed.h" /> <Unit filename="src/m_menu.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/m_menu.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/m_menu.h" /> <Unit filename="src/m_misc.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/m_misc.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/m_misc.h" /> <Unit filename="src/m_queue.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/m_queue.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/m_queue.h" /> <Unit filename="src/m_random.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/m_random.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/m_swap.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/m_random.h" /> + <Unit filename="src/m_swap.h" /> <Unit filename="src/md5.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/md5.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/md5.h" /> <Unit filename="src/mserv.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/mserv.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/p5prof.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/mserv.h" /> + <Unit filename="src/p5prof.h" /> <Unit filename="src/p_ceilng.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/p_enemy.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/p_floor.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/p_inter.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/p_lights.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/p_local.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/p_local.h" /> <Unit filename="src/p_map.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/p_maputl.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/p_maputl.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/p_maputl.h" /> <Unit filename="src/p_mobj.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/p_mobj.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/p_mobj.h" /> <Unit filename="src/p_polyobj.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/p_polyobj.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/p_pspr.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/p_polyobj.h" /> + <Unit filename="src/p_pspr.h" /> <Unit filename="src/p_saveg.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/p_saveg.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/p_saveg.h" /> <Unit filename="src/p_setup.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/p_setup.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/p_setup.h" /> <Unit filename="src/p_sight.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/p_slopes.c"> + <Option compilerVar="CC" /> + </Unit> + <Unit filename="src/p_slopes.h" /> <Unit filename="src/p_spec.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/p_spec.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/p_spec.h" /> <Unit filename="src/p_telept.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/p_tick.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/p_tick.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/p_tick.h" /> <Unit filename="src/p_user.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/r_bsp.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/r_bsp.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/r_bsp.h" /> <Unit filename="src/r_data.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/r_data.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/r_defs.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/r_data.h" /> + <Unit filename="src/r_defs.h" /> <Unit filename="src/r_draw.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/r_draw.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/r_draw.h" /> <Unit filename="src/r_draw16.c"> <Option compilerVar="CC" /> <Option compile="0" /> <Option link="0" /> - <Option target="Debug Native/SDL" /> - <Option target="Release Native/SDL" /> - <Option target="Debug Linux/SDL" /> - <Option target="Release Linux/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 Mingw64/SDL" /> - <Option target="Release Mingw64/SDL" /> - <Option target="Debug Mingw64/DirectX" /> - <Option target="Release Mingw64/DirectX" /> </Unit> <Unit filename="src/r_draw8.c"> <Option compilerVar="CC" /> <Option compile="0" /> <Option link="0" /> - <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/r_local.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/r_local.h" /> <Unit filename="src/r_main.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/r_main.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/r_main.h" /> <Unit filename="src/r_plane.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/r_plane.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/r_plane.h" /> <Unit filename="src/r_segs.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/r_segs.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/r_segs.h" /> <Unit filename="src/r_sky.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/r_sky.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/r_sky.h" /> <Unit filename="src/r_splats.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/r_splats.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/r_state.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/r_splats.h" /> + <Unit filename="src/r_state.h" /> <Unit filename="src/r_things.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/r_things.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/r_things.h" /> <Unit filename="src/s_sound.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/s_sound.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/s_sound.h" /> <Unit filename="src/screen.c"> <Option compilerVar="CC" /> + </Unit> + <Unit filename="src/screen.h" /> + <Unit filename="src/sdl/IMG_xpm.c"> + <Option compilerVar="CC" /> + <Option compile="0" /> + <Option link="0" /> <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" /> + <Option target="Debug Mingw/SDL" /> + <Option target="Release Mingw/SDL" /> </Unit> - <Unit filename="src/screen.h"> + <Unit filename="src/sdl/SDL_icon.xpm"> <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" /> + <Option target="Debug Mingw/SDL" /> + <Option target="Release Mingw/SDL" /> </Unit> - <Unit filename="src/sdl2/IMG_xpm.c"> + <Unit filename="src/sdl/dosstr.c"> <Option compilerVar="CC" /> <Option target="Debug Native/SDL" /> <Option target="Release Native/SDL" /> @@ -4166,15 +1761,7 @@ HW3SOUND for 3D hardware sound support <Option target="Debug Mingw/SDL" /> <Option target="Release Mingw/SDL" /> </Unit> - <Unit filename="src/sdl2/SDL_icon.xpm"> - <Option target="Debug Native/SDL" /> - <Option target="Release Native/SDL" /> - <Option target="Debug Linux/SDL" /> - <Option target="Release Linux/SDL" /> - <Option target="Debug Mingw/SDL" /> - <Option target="Release Mingw/SDL" /> - </Unit> - <Unit filename="src/sdl2/dosstr.c"> + <Unit filename="src/sdl/endtxt.c"> <Option compilerVar="CC" /> <Option target="Debug Native/SDL" /> <Option target="Release Native/SDL" /> @@ -4183,7 +1770,15 @@ HW3SOUND for 3D hardware sound support <Option target="Debug Mingw/SDL" /> <Option target="Release Mingw/SDL" /> </Unit> - <Unit filename="src/sdl2/endtxt.c"> + <Unit filename="src/sdl/endtxt.h"> + <Option target="Debug Native/SDL" /> + <Option target="Release Native/SDL" /> + <Option target="Debug Linux/SDL" /> + <Option target="Release Linux/SDL" /> + <Option target="Debug Mingw/SDL" /> + <Option target="Release Mingw/SDL" /> + </Unit> + <Unit filename="src/sdl/hwsym_sdl.c"> <Option compilerVar="CC" /> <Option target="Debug Native/SDL" /> <Option target="Release Native/SDL" /> @@ -4192,7 +1787,7 @@ HW3SOUND for 3D hardware sound support <Option target="Debug Mingw/SDL" /> <Option target="Release Mingw/SDL" /> </Unit> - <Unit filename="src/sdl2/endtxt.h"> + <Unit filename="src/sdl/hwsym_sdl.h"> <Option target="Debug Native/SDL" /> <Option target="Release Native/SDL" /> <Option target="Debug Linux/SDL" /> @@ -4200,7 +1795,7 @@ HW3SOUND for 3D hardware sound support <Option target="Debug Mingw/SDL" /> <Option target="Release Mingw/SDL" /> </Unit> - <Unit filename="src/sdl2/hwsym_sdl.c"> + <Unit filename="src/sdl/i_cdmus.c"> <Option compilerVar="CC" /> <Option target="Debug Native/SDL" /> <Option target="Release Native/SDL" /> @@ -4209,15 +1804,7 @@ HW3SOUND for 3D hardware sound support <Option target="Debug Mingw/SDL" /> <Option target="Release Mingw/SDL" /> </Unit> - <Unit filename="src/sdl2/hwsym_sdl.h"> - <Option target="Debug Native/SDL" /> - <Option target="Release Native/SDL" /> - <Option target="Debug Linux/SDL" /> - <Option target="Release Linux/SDL" /> - <Option target="Debug Mingw/SDL" /> - <Option target="Release Mingw/SDL" /> - </Unit> - <Unit filename="src/sdl2/i_cdmus.c"> + <Unit filename="src/sdl/i_main.c"> <Option compilerVar="CC" /> <Option target="Debug Native/SDL" /> <Option target="Release Native/SDL" /> @@ -4226,7 +1813,7 @@ HW3SOUND for 3D hardware sound support <Option target="Debug Mingw/SDL" /> <Option target="Release Mingw/SDL" /> </Unit> - <Unit filename="src/sdl2/i_main.c"> + <Unit filename="src/sdl/i_net.c"> <Option compilerVar="CC" /> <Option target="Debug Native/SDL" /> <Option target="Release Native/SDL" /> @@ -4235,7 +1822,7 @@ HW3SOUND for 3D hardware sound support <Option target="Debug Mingw/SDL" /> <Option target="Release Mingw/SDL" /> </Unit> - <Unit filename="src/sdl2/i_net.c"> + <Unit filename="src/sdl/i_system.c"> <Option compilerVar="CC" /> <Option target="Debug Native/SDL" /> <Option target="Release Native/SDL" /> @@ -4244,7 +1831,7 @@ HW3SOUND for 3D hardware sound support <Option target="Debug Mingw/SDL" /> <Option target="Release Mingw/SDL" /> </Unit> - <Unit filename="src/sdl2/i_system.c"> + <Unit filename="src/sdl/i_ttf.c"> <Option compilerVar="CC" /> <Option target="Debug Native/SDL" /> <Option target="Release Native/SDL" /> @@ -4253,7 +1840,15 @@ HW3SOUND for 3D hardware sound support <Option target="Debug Mingw/SDL" /> <Option target="Release Mingw/SDL" /> </Unit> - <Unit filename="src/sdl2/i_ttf.c"> + <Unit filename="src/sdl/i_ttf.h"> + <Option target="Debug Native/SDL" /> + <Option target="Release Native/SDL" /> + <Option target="Debug Linux/SDL" /> + <Option target="Release Linux/SDL" /> + <Option target="Debug Mingw/SDL" /> + <Option target="Release Mingw/SDL" /> + </Unit> + <Unit filename="src/sdl/i_video.c"> <Option compilerVar="CC" /> <Option target="Debug Native/SDL" /> <Option target="Release Native/SDL" /> @@ -4262,15 +1857,7 @@ HW3SOUND for 3D hardware sound support <Option target="Debug Mingw/SDL" /> <Option target="Release Mingw/SDL" /> </Unit> - <Unit filename="src/sdl2/i_ttf.h"> - <Option target="Debug Native/SDL" /> - <Option target="Release Native/SDL" /> - <Option target="Debug Linux/SDL" /> - <Option target="Release Linux/SDL" /> - <Option target="Debug Mingw/SDL" /> - <Option target="Release Mingw/SDL" /> - </Unit> - <Unit filename="src/sdl2/i_video.c"> + <Unit filename="src/sdl/mixer_sound.c"> <Option compilerVar="CC" /> <Option target="Debug Native/SDL" /> <Option target="Release Native/SDL" /> @@ -4279,7 +1866,7 @@ HW3SOUND for 3D hardware sound support <Option target="Debug Mingw/SDL" /> <Option target="Release Mingw/SDL" /> </Unit> - <Unit filename="src/sdl2/mixer_sound.c"> + <Unit filename="src/sdl/ogl_sdl.c"> <Option compilerVar="CC" /> <Option target="Debug Native/SDL" /> <Option target="Release Native/SDL" /> @@ -4288,7 +1875,15 @@ HW3SOUND for 3D hardware sound support <Option target="Debug Mingw/SDL" /> <Option target="Release Mingw/SDL" /> </Unit> - <Unit filename="src/sdl2/ogl_sdl.c"> + <Unit filename="src/sdl/ogl_sdl.h"> + <Option target="Debug Native/SDL" /> + <Option target="Release Native/SDL" /> + <Option target="Debug Linux/SDL" /> + <Option target="Release Linux/SDL" /> + <Option target="Debug Mingw/SDL" /> + <Option target="Release Mingw/SDL" /> + </Unit> + <Unit filename="src/sdl/sdl_sound.c"> <Option compilerVar="CC" /> <Option target="Debug Native/SDL" /> <Option target="Release Native/SDL" /> @@ -4297,24 +1892,7 @@ HW3SOUND for 3D hardware sound support <Option target="Debug Mingw/SDL" /> <Option target="Release Mingw/SDL" /> </Unit> - <Unit filename="src/sdl2/ogl_sdl.h"> - <Option target="Debug Native/SDL" /> - <Option target="Release Native/SDL" /> - <Option target="Debug Linux/SDL" /> - <Option target="Release Linux/SDL" /> - <Option target="Debug Mingw/SDL" /> - <Option target="Release Mingw/SDL" /> - </Unit> - <Unit filename="src/sdl2/sdl_sound.c"> - <Option compilerVar="CC" /> - <Option target="Debug Native/SDL" /> - <Option target="Release Native/SDL" /> - <Option target="Debug Linux/SDL" /> - <Option target="Release Linux/SDL" /> - <Option target="Debug Mingw/SDL" /> - <Option target="Release Mingw/SDL" /> - </Unit> - <Unit filename="src/sdl2/sdlmain.h"> + <Unit filename="src/sdl/sdlmain.h"> <Option target="Debug Native/SDL" /> <Option target="Release Native/SDL" /> <Option target="Debug Linux/SDL" /> @@ -4324,120 +1902,39 @@ HW3SOUND for 3D hardware sound support </Unit> <Unit filename="src/sounds.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/sounds.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/sounds.h" /> <Unit filename="src/st_stuff.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/st_stuff.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/st_stuff.h" /> <Unit filename="src/string.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/t_facon.c"> + <Option compilerVar="CC" /> + <Option compile="0" /> + <Option link="0" /> + </Unit> + <Unit filename="src/t_fsin.c"> + <Option compilerVar="CC" /> + <Option compile="0" /> + <Option link="0" /> + </Unit> + <Unit filename="src/t_ftan.c"> + <Option compilerVar="CC" /> + <Option compile="0" /> + <Option link="0" /> + </Unit> + <Unit filename="src/t_tan2a.c"> + <Option compilerVar="CC" /> + <Option compile="0" /> + <Option link="0" /> </Unit> <Unit filename="src/tables.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/tables.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/tables.h" /> <Unit filename="src/tmap.nas"> <Option target="Debug Mingw/SDL" /> <Option target="Release Mingw/SDL" /> @@ -4460,46 +1957,17 @@ HW3SOUND for 3D hardware sound support </Unit> <Unit filename="src/v_video.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/v_video.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/v_video.h" /> <Unit filename="src/vid_copy.s"> <Option compilerVar="CC" /> - <Option compiler="gcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" /> - <Option compiler="ppcgcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" /> + <Option compiler="avrgcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" /> <Option compiler="gnu_gcc_compiler_for_mingw32" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" /> + <Option compiler="gnu_gcc_compiler_for_mingw64" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" /> <Option compiler="armelfgcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" /> <Option compiler="tricoregcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" /> - <Option compiler="avrgcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" /> - <Option compiler="gnu_gcc_compiler_for_mingw64" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" /> + <Option compiler="ppcgcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" /> + <Option compiler="gcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" /> <Option target="Debug Native/SDL" /> <Option target="Release Native/SDL" /> <Option target="Debug Linux/SDL" /> @@ -4511,37 +1979,8 @@ HW3SOUND for 3D hardware sound support </Unit> <Unit filename="src/w_wad.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/w_wad.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/w_wad.h" /> <Unit filename="src/win32/Srb2win.rc"> <Option compilerVar="WINDRES" /> <Option target="Debug Mingw/DirectX" /> @@ -4667,70 +2106,12 @@ HW3SOUND for 3D hardware sound support </Unit> <Unit filename="src/y_inter.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/y_inter.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/y_inter.h" /> <Unit filename="src/z_zone.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/z_zone.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/z_zone.h" /> <Extensions> <envvars /> <code_completion /> diff --git a/appveyor.yml b/appveyor.yml index e0ee99c61..25b95d292 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 2.1.16.{branch}-{build} +version: 2.1.17.{branch}-{build} os: MinGW environment: diff --git a/debian/docs b/debian/docs index f3d4ef20e..b43bf86b5 100644 --- a/debian/docs +++ b/debian/docs @@ -1,2 +1 @@ -readme.txt -readme.txt +README.md diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ba354c289..da8438a59 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -231,6 +231,7 @@ if(${SRB2_CONFIG_HAVE_BLUA}) add_definitions(-DHAVE_BLUA) set(SRB2_LUA_SOURCES lua_baselib.c + lua_blockmaplib.c lua_consolelib.c lua_hooklib.c lua_hudlib.c @@ -390,18 +391,25 @@ if(${SRB2_CONFIG_HWRENDER} AND ${SRB2_CONFIG_STATIC_OPENGL}) endif() if(${SRB2_CONFIG_USEASM}) + #SRB2_ASM_FLAGS can be used to pass flags to either nasm or yasm. + if(${CMAKE_SYSTEM} MATCHES "Linux") + set(SRB2_ASM_FLAGS "-DLINUX ${SRB2_ASM_FLAGS}") + endif() + if(${SRB2_CONFIG_YASM}) set(CMAKE_ASM_YASM_SOURCE_FILE_EXTENSIONS ${CMAKE_ASM_YASM_SOURCE_FILE_EXTENSIONS} nas) + set(CMAKE_ASM_YASM_FLAGS "${SRB2_ASM_FLAGS}" CACHE STRING "Flags used by the assembler during all build types.") enable_language(ASM_YASM) else() set(CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS ${CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS} nas) + set(CMAKE_ASM_NASM_FLAGS "${SRB2_ASM_FLAGS}" CACHE STRING "Flags used by the assembler during all build types.") enable_language(ASM_NASM) endif() set(SRB2_USEASM ON) add_definitions(-DUSEASM) else() set(SRB2_USEASM OFF) - add_definitions(-DNOASM -DNONX86) + add_definitions(-DNONX86 -DNORUSEASM) endif() # Targets diff --git a/src/Makefile b/src/Makefile index ce4b569ee..76f013c52 100644 --- a/src/Makefile +++ b/src/Makefile @@ -179,6 +179,9 @@ endif ifdef LINUX UNIXCOMMON=1 +ifndef NOGME +HAVE_LIBGME=1 +endif endif ifdef SOLARIS @@ -315,6 +318,13 @@ LIBS+=$(PNG_LDFLAGS) CFLAGS+=$(PNG_CFLAGS) endif +ZLIB_PKGCONFIG?=zlib +ZLIB_CFLAGS?=$(shell $(PKG_CONFIG) $(ZLIB_PKGCONFIG) --cflags) +ZLIB_LDFLAGS?=$(shell $(PKG_CONFIG) $(ZLIB_PKGCONFIG) --libs) + +LIBS+=$(ZLIB_LDFLAGS) +CFLAGS+=$(ZLIB_CFLAGS) + ifdef HAVE_LIBGME OPTS+=-DHAVE_LIBGME @@ -366,6 +376,14 @@ endif OPTS:=-fno-exceptions $(OPTS) +ifdef MOBJCONSISTANCY + OPTS+=-DMOBJCONSISTANCY +endif + +ifdef PACKETDROP + OPTS+=-DPACKETDROP +endif + ifdef DEBUGMODE # build with debugging information @@ -375,7 +393,7 @@ ifdef GCC48 else CFLAGS+=-O0 endif - CFLAGS+= -Wall -DPARANOIA -DRANGECHECK + CFLAGS+= -Wall -DPARANOIA -DRANGECHECK -DPACKETDROP -DMOBJCONSISTANCY else diff --git a/src/android/i_system.c b/src/android/i_system.c index 150cbd505..58fca7c19 100644 --- a/src/android/i_system.c +++ b/src/android/i_system.c @@ -258,6 +258,18 @@ INT32 I_PutEnv(char *variable) return -1; } +INT32 I_ClipboardCopy(const char *data, size_t size) +{ + (void)data; + (void)size; + return -1; +} + +char *I_ClipboardPaste(void) +{ + return NULL; +} + void I_RegisterSysCommands(void) {} #include "../sdl/dosstr.c" diff --git a/src/blua/Makefile.cfg b/src/blua/Makefile.cfg index e3fb3df46..8d2e73714 100644 --- a/src/blua/Makefile.cfg +++ b/src/blua/Makefile.cfg @@ -48,4 +48,5 @@ OBJS:=$(OBJS) \ $(OBJDIR)/lua_skinlib.o \ $(OBJDIR)/lua_thinkerlib.o \ $(OBJDIR)/lua_maplib.o \ + $(OBJDIR)/lua_blockmaplib.o \ $(OBJDIR)/lua_hudlib.o diff --git a/src/console.c b/src/console.c index be4eee210..3702dd560 100644 --- a/src/console.c +++ b/src/console.c @@ -84,19 +84,23 @@ UINT32 con_scalefactor; // text size scale factor // hold 32 last lines of input for history #define CON_MAXPROMPTCHARS 256 -#define CON_PROMPTCHAR '>' +#define CON_PROMPTCHAR '$' static char inputlines[32][CON_MAXPROMPTCHARS]; // hold last 32 prompt lines static INT32 inputline; // current input line number static INT32 inputhist; // line number of history input line to restore -static size_t input_cx; // position in current input line +static size_t input_cur; // position of cursor in line +static size_t input_sel; // position of selection marker (I.E.: anything between this and input_cur is "selected") +static size_t input_len; // length of current line, used to bound cursor and such +// notice: input does NOT include the "$" at the start of the line. - 11/3/16 // protos. static void CON_InputInit(void); static void CON_RecalcSize(void); static void CONS_hudlines_Change(void); +static void CONS_backcolor_Change(void); static void CON_DrawBackpic(patch_t *pic, INT32 startx, INT32 destwidth); //static void CON_DrawBackpic2(pic_t *pic, INT32 startx, INT32 destwidth); @@ -129,10 +133,12 @@ static CV_PossibleValue_t backpic_cons_t[] = {{0, "translucent"}, {1, "picture"} // whether to use console background picture, or translucent mode static consvar_t cons_backpic = {"con_backpic", "translucent", CV_SAVE, backpic_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Orange"}, - {2, "Blue"}, {3, "Green"}, {4, "Gray"}, - {5, "Red"}, {0, NULL}}; -consvar_t cons_backcolor = {"con_backcolor", "3", CV_SAVE, backcolor_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Gray"}, {2, "Brown"}, + {3, "Red"}, {4, "Orange"}, {5, "Yellow"}, + {6, "Green"}, {7, "Blue"}, {8, "Purple"}, + {9, "Magenta"}, {10, "Aqua"}, + {0, NULL}}; +consvar_t cons_backcolor = {"con_backcolor", "Green", CV_CALL|CV_SAVE, backcolor_cons_t, CONS_backcolor_Change, 0, NULL, NULL, 0, 0, NULL}; static void CON_Print(char *msg); @@ -219,8 +225,9 @@ static void CONS_Bind_f(void) // CONSOLE SETUP //====================================================================== -// Prepare a colormap for GREEN ONLY translucency over background -// +// Font colormap colors +// TODO: This could probably be improved somehow... +// These colormaps are 99% identical, with just a few changed bytes UINT8 *yellowmap; UINT8 *purplemap; UINT8 *lgreenmap; @@ -229,44 +236,52 @@ UINT8 *graymap; UINT8 *redmap; UINT8 *orangemap; -// Console BG colors -UINT8 *cwhitemap; -UINT8 *corangemap; -UINT8 *cbluemap; -UINT8 *cgreenmap; -UINT8 *cgraymap; -UINT8 *credmap; +// Console BG color +UINT8 *consolebgmap = NULL; -void CON_ReSetupBackColormap(UINT16 num) +void CON_SetupBackColormap(void) { - UINT16 i, j; - UINT8 k; - UINT8 *pal = W_CacheLumpName(R_GetPalname(num), PU_CACHE); + UINT16 i, palsum; + UINT8 j, palindex, shift; + UINT8 *pal = W_CacheLumpName(GetPalette(), PU_CACHE); - // setup the green translucent background colormaps - for (i = 0, k = 0; i < 768; i += 3, k++) + if (!consolebgmap) + consolebgmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); + + shift = 6; // 12 colors -- shift of 7 means 6 colors + switch (cons_backcolor.value) { - j = pal[i] + pal[i+1] + pal[i+2]; - cwhitemap[k] = (UINT8)(15 - (j>>6)); - corangemap[k] = (UINT8)(63 - (j>>6)); - cbluemap[k] = (UINT8)(159 - (j>>6)); - cgreenmap[k] = (UINT8)(111 - (j>>6)); - cgraymap[k] = (UINT8)(31 - (j>>6)); - credmap[k] = (UINT8)(47 - (j>>6)); + case 0: palindex = 15; break; // White + case 1: palindex = 31; break; // Gray + case 2: palindex = 239; break; // Brown + case 3: palindex = 47; break; // Red + case 4: palindex = 63; break; // Orange + case 5: palindex = 79; shift = 7; break; // Yellow + case 6: palindex = 111; break; // Green + case 7: palindex = 159; break; // Blue + case 8: palindex = 199; shift = 7; break; // Purple + case 9: palindex = 187; break; // Magenta + case 10: palindex = 139; break; // Aqua + // Default green + default: palindex = 175; break; +} + + // setup background colormap + for (i = 0, j = 0; i < 768; i += 3, j++) + { + palsum = (pal[i] + pal[i+1] + pal[i+2]) >> shift; + consolebgmap[j] = (UINT8)(palindex - palsum); } } -static void CON_SetupBackColormap(void) +static void CONS_backcolor_Change(void) { - INT32 i, j, k; - UINT8 *pal; + CON_SetupBackColormap(); +} - cwhitemap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); - corangemap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); - cbluemap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); - cgreenmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); - cgraymap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); - credmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); +static void CON_SetupColormaps(void) +{ + INT32 i; yellowmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); graymap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); @@ -276,20 +291,6 @@ static void CON_SetupBackColormap(void) redmap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); orangemap = (UINT8 *)Z_Malloc(256, PU_STATIC, NULL); - pal = W_CacheLumpName("PLAYPAL", PU_CACHE); - - // setup the green translucent background colormaps - for (i = 0, k = 0; i < 768; i += 3, k++) - { - j = pal[i] + pal[i+1] + pal[i+2]; - cwhitemap[k] = (UINT8)(15 - (j>>6)); - corangemap[k] = (UINT8)(63 - (j>>6)); - cbluemap[k] = (UINT8)(159 - (j>>6)); - cgreenmap[k] = (UINT8)(111 - (j>>6)); - cgraymap[k] = (UINT8)(31 - (j>>6)); - credmap[k] = (UINT8)(47 - (j>>6)); - } - // setup the other colormaps, for console text // these don't need to be aligned, unless you convert the @@ -320,6 +321,9 @@ static void CON_SetupBackColormap(void) redmap[9] = (UINT8)32; orangemap[3] = (UINT8)52; orangemap[9] = (UINT8)57; + + // Init back colormap + CON_SetupBackColormap(); } // Setup the console text buffer @@ -343,7 +347,7 @@ void CON_Init(void) con_width = 0; CON_RecalcSize(); - CON_SetupBackColormap(); + CON_SetupColormaps(); //note: CON_Ticker should always execute at least once before D_Display() con_clipviewtop = -1; // -1 does not clip @@ -386,14 +390,10 @@ void CON_Init(void) // static void CON_InputInit(void) { - INT32 i; - // prepare the first prompt line memset(inputlines, 0, sizeof (inputlines)); - for (i = 0; i < 32; i++) - inputlines[i][0] = CON_PROMPTCHAR; inputline = 0; - input_cx = 1; + input_cur = input_sel = input_len = 0; } //====================================================================== @@ -618,13 +618,91 @@ void CON_Ticker(void) } } +// +// ---- +// +// Shortcuts for adding and deleting characters, strings, and sections +// Necessary due to moving cursor +// + +static void CON_InputClear(void) +{ + memset(inputlines[inputline], 0, CON_MAXPROMPTCHARS); + input_cur = input_sel = input_len = 0; +} + +static void CON_InputSetString(const char *c) +{ + memset(inputlines[inputline], 0, CON_MAXPROMPTCHARS); + strcpy(inputlines[inputline], c); + input_cur = input_sel = input_len = strlen(c); +} + +static void CON_InputAddString(const char *c) +{ + size_t csize = strlen(c); + if (input_len + csize > CON_MAXPROMPTCHARS-1) + return; + if (input_cur != input_len) + memmove(&inputlines[inputline][input_cur+csize], &inputlines[inputline][input_cur], input_len-input_cur); + memcpy(&inputlines[inputline][input_cur], c, csize); + input_len += csize; + input_sel = (input_cur += csize); +} + +static void CON_InputDelSelection(void) +{ + size_t start, end, len; + if (input_cur > input_sel) + { + start = input_sel; + end = input_cur; + } + else + { + start = input_cur; + end = input_sel; + } + len = (end - start); + + if (end != input_len) + memmove(&inputlines[inputline][start], &inputlines[inputline][end], input_len-end); + memset(&inputlines[inputline][input_len - len], 0, len); + + input_len -= len; + input_sel = input_cur = start; +} + +static void CON_InputAddChar(char c) +{ + if (input_len >= CON_MAXPROMPTCHARS-1) + return; + if (input_cur != input_len) + memmove(&inputlines[inputline][input_cur+1], &inputlines[inputline][input_cur], input_len-input_cur); + inputlines[inputline][input_cur++] = c; + inputlines[inputline][++input_len] = 0; + input_sel = input_cur; +} + +static void CON_InputDelChar(void) +{ + if (!input_cur) + return; + if (input_cur != input_len) + memmove(&inputlines[inputline][input_cur-1], &inputlines[inputline][input_cur], input_len-input_cur); + inputlines[inputline][--input_len] = 0; + input_sel = --input_cur; +} + +// +// ---- +// + // Handles console key input // boolean CON_Responder(event_t *ev) { - static boolean consdown; - static boolean shiftdown; - static boolean ctrldown; + static UINT8 consdown = false; // console is treated differently due to rare usage // sequential completions a la 4dos static char completion[80]; @@ -639,13 +717,8 @@ boolean CON_Responder(event_t *ev) // let go keyup events, don't eat them if (ev->type != ev_keydown && ev->type != ev_console) { - if (ev->data1 == KEY_LSHIFT || ev->data1 == KEY_RSHIFT) - shiftdown = false; - else if (ev->data1 == KEY_LCTRL || ev->data1 == KEY_RCTRL) - ctrldown = false; - else if (ev->data1 == gamecontrol[gc_console][0] || ev->data1 == gamecontrol[gc_console][1]) + if (ev->data1 == gamecontrol[gc_console][0] || ev->data1 == gamecontrol[gc_console][1]) consdown = false; - return false; } @@ -684,94 +757,110 @@ boolean CON_Responder(event_t *ev) consoletoggle = true; return true; } - } - // eat shift only if console active - if (key == KEY_LSHIFT || key == KEY_RSHIFT) - { - shiftdown = true; + // Always eat ctrl/shift/alt if console open, so the menu doesn't get ideas + if (key == KEY_LSHIFT || key == KEY_RSHIFT + || key == KEY_LCTRL || key == KEY_RCTRL + || key == KEY_LALT || key == KEY_RALT) return true; - } - // same for ctrl - if (key == KEY_LCTRL || key == KEY_RCTRL) + // ctrl modifier -- changes behavior, adds shortcuts + if (ctrldown) { - ctrldown = true; - return true; + // show all cvars/commands that match what we have inputted + if (key == KEY_TAB) + { + size_t i, len; + + if (!completion[0]) + { + if (!input_len || input_len >= 40 || strchr(inputlines[inputline], ' ')) + return true; + strcpy(completion, inputlines[inputline]); + comskips = varskips = 0; + } + len = strlen(completion); + + //first check commands + CONS_Printf("\nCommands:\n"); + for (i = 0, cmd = COM_CompleteCommand(completion, i); cmd; cmd = COM_CompleteCommand(completion, ++i)) + CONS_Printf(" \x83" "%s" "\x80" "%s\n", completion, cmd+len); + if (i == 0) CONS_Printf(" (none)\n"); + + //now we move on to CVARs + CONS_Printf("Variables:\n"); + for (i = 0, cmd = CV_CompleteVar(completion, i); cmd; cmd = CV_CompleteVar(completion, ++i)) + CONS_Printf(" \x83" "%s" "\x80" "%s\n", completion, cmd+len); + if (i == 0) CONS_Printf(" (none)\n"); + + return true; + } + // --- + + if (key == KEY_HOME) // oldest text in buffer + { + con_scrollup = (con_totallines-((con_curlines-16)>>3)); + return true; + } + else if (key == KEY_END) // most recent text in buffer + { + con_scrollup = 0; + return true; + } + + if (key == 'x' || key == 'X') + { + if (input_sel > input_cur) + I_ClipboardCopy(&inputlines[inputline][input_cur], input_sel-input_cur); + else + I_ClipboardCopy(&inputlines[inputline][input_sel], input_cur-input_sel); + CON_InputDelSelection(); + completion[0] = 0; + return true; + } + else if (key == 'c' || key == 'C') + { + if (input_sel > input_cur) + I_ClipboardCopy(&inputlines[inputline][input_cur], input_sel-input_cur); + else + I_ClipboardCopy(&inputlines[inputline][input_sel], input_cur-input_sel); + return true; + } + else if (key == 'v' || key == 'V') + { + const char *paste = I_ClipboardPaste(); + if (input_sel != input_cur) + CON_InputDelSelection(); + if (paste != NULL) + CON_InputAddString(paste); + completion[0] = 0; + return true; + } + + // Select all + if (key == 'a' || key == 'A') + { + input_sel = 0; + input_cur = input_len; + return true; + } + + // don't eat the key + return false; } // command completion forward (tab) and backward (shift-tab) if (key == KEY_TAB) { - // show all cvars/commands that match what we have inputted - if (ctrldown) - { - UINT32 i; - size_t stop = input_cx - 1; - char nameremainder[255]; - - if (input_cx < 2 || strlen(inputlines[inputline]+1) >= 80) - return true; - - strcpy(completion, inputlines[inputline]+1); - - // trimming: stop at the first newline - for (i = 0; i < input_cx - 1; ++i) - { - if (completion[i] == ' ') - { - completion[i] = '\0'; - stop = i; - break; - } - } - - i = 0; - - //first check commands - CONS_Printf("\nCommands:\n"); - - for (cmd = COM_CompleteCommand(completion, i); cmd; cmd = COM_CompleteCommand(completion, i)) - { - strncpy(nameremainder, cmd+(stop), strlen(cmd)-(stop)); - nameremainder[strlen(cmd)-(stop)] = '\0'; - - CONS_Printf(" \x83" "%s" "\x80" "%s\n", completion, nameremainder); - ++i; - } - if (i == 0) - CONS_Printf(" (none)\n"); - - i = 0; - - //now we move on to CVARs - CONS_Printf("Variables:\n"); - - for (cmd = CV_CompleteVar(completion, i); cmd; cmd = CV_CompleteVar(completion, i)) - { - strncpy(nameremainder, cmd+(stop), strlen(cmd)-(stop)); - nameremainder[strlen(cmd)-(stop)] = '\0'; - - CONS_Printf(" \x83" "%s" "\x80" "%s\n", completion, nameremainder); - ++i; - } - if (i == 0) - CONS_Printf(" (none)\n"); - - return true; - } - // sequential command completion forward and backward // remember typing for several completions (a-la-4dos) - if (inputlines[inputline][input_cx-1] != ' ') + if (!completion[0]) { - if (strlen(inputlines[inputline]+1) < 80) - strcpy(completion, inputlines[inputline]+1); - else - completion[0] = 0; - + if (!input_len || input_len >= 40 || strchr(inputlines[inputline], ' ')) + return true; + strcpy(completion, inputlines[inputline]); comskips = varskips = 0; } else @@ -783,37 +872,26 @@ boolean CON_Responder(event_t *ev) if (--varskips < 0) comskips = -comskips - 2; } - else if (comskips > 0) - comskips--; + else if (comskips > 0) comskips--; } else { - if (comskips < 0) - varskips++; - else - comskips++; + if (comskips < 0) varskips++; + else comskips++; } } if (comskips >= 0) { cmd = COM_CompleteCommand(completion, comskips); - if (!cmd) - // dirty: make sure if comskips is zero, to have a neg value + if (!cmd) // dirty: make sure if comskips is zero, to have a neg value comskips = -comskips - 1; } if (comskips < 0) cmd = CV_CompleteVar(completion, varskips); if (cmd) - { - memset(inputlines[inputline]+1, 0, CON_MAXPROMPTCHARS-1); - strcpy(inputlines[inputline]+1, cmd); - input_cx = strlen(cmd) + 1; - inputlines[inputline][input_cx] = ' '; - input_cx++; - inputlines[inputline][input_cx] = 0; - } + CON_InputSetString(va("%s ", cmd)); else { if (comskips > 0) @@ -839,47 +917,80 @@ boolean CON_Responder(event_t *ev) return true; } - if (key == KEY_HOME) // oldest text in buffer + if (key == KEY_LEFTARROW) { - con_scrollup = (con_totallines-((con_curlines-16)>>3)); + if (input_cur != 0) + --input_cur; + if (!shiftdown) + input_sel = input_cur; return true; } - else if (key == KEY_END) // most recent text in buffer + else if (key == KEY_RIGHTARROW) { - con_scrollup = 0; + if (input_cur < input_len) + ++input_cur; + if (!shiftdown) + input_sel = input_cur; return true; } + else if (key == KEY_HOME) + { + input_cur = 0; + if (!shiftdown) + input_sel = input_cur; + return true; + } + else if (key == KEY_END) + { + input_cur = input_len; + if (!shiftdown) + input_sel = input_cur; + return true; + } + + // At this point we're messing with input + // Clear completion + completion[0] = 0; // command enter if (key == KEY_ENTER) { - if (input_cx < 2) + if (!input_len) return true; // push the command - COM_BufAddText(inputlines[inputline]+1); + COM_BufAddText(inputlines[inputline]); COM_BufAddText("\n"); - CONS_Printf("%s\n", inputlines[inputline]); + CONS_Printf("\x86""%c""\x80""%s\n", CON_PROMPTCHAR, inputlines[inputline]); inputline = (inputline+1) & 31; inputhist = inputline; - - memset(inputlines[inputline], 0, CON_MAXPROMPTCHARS); - inputlines[inputline][0] = CON_PROMPTCHAR; - input_cx = 1; + CON_InputClear(); return true; } - // backspace command prompt - if (key == KEY_BACKSPACE) + // backspace and delete command prompt + if (input_sel != input_cur) { - if (input_cx > 1) + if (key == KEY_BACKSPACE || key == KEY_DEL) { - input_cx--; - inputlines[inputline][input_cx] = 0; + CON_InputDelSelection(); + return true; } + } + else if (key == KEY_BACKSPACE) + { + CON_InputDelChar(); + return true; + } + else if (key == KEY_DEL) + { + if (input_cur == input_len) + return true; + ++input_cur; + CON_InputDelChar(); return true; } @@ -888,18 +999,15 @@ boolean CON_Responder(event_t *ev) { // copy one of the previous inputlines to the current do - { inputhist = (inputhist - 1) & 31; // cycle back - } while (inputhist != inputline && !inputlines[inputhist][1]); + while (inputhist != inputline && !inputlines[inputhist][0]); // stop at the last history input line, which is the // current line + 1 because we cycle through the 32 input lines if (inputhist == inputline) inputhist = (inputline + 1) & 31; - M_Memcpy(inputlines[inputline], inputlines[inputhist], CON_MAXPROMPTCHARS); - input_cx = strlen(inputlines[inputline]); - + CON_InputSetString(inputlines[inputhist]); return true; } @@ -909,23 +1017,14 @@ boolean CON_Responder(event_t *ev) if (inputhist == inputline) return true; do - { inputhist = (inputhist + 1) & 31; - } while (inputhist != inputline && !inputlines[inputhist][1]); - - memset(inputlines[inputline], 0, CON_MAXPROMPTCHARS); + while (inputhist != inputline && !inputlines[inputhist][0]); // back to currentline if (inputhist == inputline) - { - inputlines[inputline][0] = CON_PROMPTCHAR; - input_cx = 1; - } + CON_InputClear(); else - { - strcpy(inputlines[inputline], inputlines[inputhist]); - input_cx = strlen(inputlines[inputline]); - } + CON_InputSetString(inputlines[inputhist]); return true; } @@ -950,15 +1049,12 @@ boolean CON_Responder(event_t *ev) return false; // add key to cmd line here - if (input_cx < CON_MAXPROMPTCHARS) - { - if (key >= 'A' && key <= 'Z' && !shiftdown) //this is only really necessary for dedicated servers - key = key + 'a' - 'A'; + if (key >= 'A' && key <= 'Z' && !shiftdown) //this is only really necessary for dedicated servers + key = key + 'a' - 'A'; - inputlines[inputline][input_cx] = (char)key; - inputlines[inputline][input_cx + 1] = 0; - input_cx++; - } + if (input_sel != input_cur) + CON_InputDelSelection(); + CON_InputAddChar(key); return true; } @@ -1242,26 +1338,89 @@ void CONS_Error(const char *msg) // static void CON_DrawInput(void) { - char *p; - size_t c; - INT32 x, y; INT32 charwidth = (INT32)con_scalefactor << 3; - - // input line scrolls left if it gets too long - p = inputlines[inputline]; - if (input_cx >= con_width-11) - p += input_cx - (con_width-11) + 1; + const char *p = inputlines[inputline]; + size_t c, clen, cend; + UINT8 lellip = 0, rellip = 0; + INT32 x, y, i; y = con_curlines - 12 * con_scalefactor; + x = charwidth*2; - for (c = 0, x = charwidth; c < con_width-11; c++, x += charwidth) - V_DrawCharacter(x, y, p[c] | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value); + clen = con_width-13; - // draw the blinking cursor - // - x = ((input_cx >= con_width-11) ? (INT32)(con_width-11) : (INT32)((input_cx + 1)) * charwidth); - if (con_tick < 4) - V_DrawCharacter(x, y, '_' | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value); + if (input_len <= clen) + { + c = 0; + clen = input_len; + } + else // input line scrolls left if it gets too long + { + clen -= 2; // There will always be some extra truncation -- but where is what we'll find out + + if (input_cur <= clen/2) + { + // Close enough to right edge to show all + c = 0; + // Always will truncate right side from this position, so always draw right ellipsis + rellip = 1; + } + else + { + // Cursor in the middle (or right side) of input + // Move over for the ellipsis + c = input_cur - (clen/2) + 2; + x += charwidth*2; + lellip = 1; + + if (c + clen >= input_len) + { + // Cursor in the right side of input + // We were too far over, so move back + c = input_len - clen; + } + else + { + // Cursor in the middle -- ellipses on both sides + clen -= 2; + rellip = 1; + } + } + } + + if (lellip) + { + x -= charwidth*3; + 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); + } + else + V_DrawCharacter(x-charwidth, y, CON_PROMPTCHAR | cv_constextsize.value | V_GRAYMAP | V_NOSCALESTART, !cv_allcaps.value); + + 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); + } + else + V_DrawCharacter(x, y, p[c] | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value); + + if (c == input_cur && con_tick >= 4) + V_DrawCharacter(x, y + (con_scalefactor*2), '_' | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value); + } + if (cend == input_cur && con_tick >= 4) + V_DrawCharacter(x, y + (con_scalefactor*2), '_' | cv_constextsize.value | V_NOSCALESTART, !cv_allcaps.value); + 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); + } } // draw the last lines of console text to the top of the screen @@ -1417,7 +1576,7 @@ static void CON_DrawConsole(void) { // inu: no more width (was always 0 and vid.width) if (rendermode != render_none) - V_DrawFadeConsBack(con_curlines, cons_backcolor.value); // translucent background + V_DrawFadeConsBack(con_curlines); // translucent background } // draw console text lines from top to bottom diff --git a/src/console.h b/src/console.h index 47af65e21..8cf6483ff 100644 --- a/src/console.h +++ b/src/console.h @@ -40,11 +40,10 @@ extern consvar_t cons_backcolor; extern UINT8 *yellowmap, *purplemap, *lgreenmap, *bluemap, *graymap, *redmap, *orangemap; -// Console bg colors: -extern UINT8 *cwhitemap, *corangemap, *cbluemap, *cgreenmap, *cgraymap, - *credmap; +// Console bg color (auto updated to match) +extern UINT8 *consolebgmap; -void CON_ReSetupBackColormap(UINT16 num); +void CON_SetupBackColormap(void); void CON_ClearHUD(void); // clear heads up messages void CON_Ticker(void); diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 734173f8d..574cce7ab 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -58,28 +58,35 @@ // NETWORKING // // gametic is the tic about to (or currently being) run -// maketic is the tic that hasn't had control made for it yet -// server: +// Server: +// maketic is the tic that hasn't had control made for it yet // nettics is the tic for each node // firstticstosend is the lowest value of nettics -// client: -// neededtic is the tic needed by the client for run the game +// Client: +// neededtic is the tic needed by the client to run the game // firstticstosend is used to optimize a condition -// normally maketic >= gametic > 0 +// Normally maketic >= gametic > 0 #define PREDICTIONQUEUE BACKUPTICS #define PREDICTIONMASK (PREDICTIONQUEUE-1) #define MAX_REASONLENGTH 30 boolean server = true; // true or false but !server == client +#define client (!server) boolean nodownload = false; static boolean serverrunning = false; INT32 serverplayer = 0; char motd[254], server_context[8]; // Message of the Day, Unique Context (even without Mumble support) -// server specific vars +// Server specific vars UINT8 playernode[MAXPLAYERS]; +// Minimum timeout for sending the savegame +// The actual timeout will be longer depending on the savegame length +tic_t jointimeout = (10*TICRATE); +static boolean sendingsavegame[MAXNETNODES]; // Are we sending the savegame? +static tic_t freezetimeout[MAXNETNODES]; // Until when can this node freeze the server before getting a timeout? + #ifdef NEWPING UINT16 pingmeasurecount = 1; UINT32 realpingtable[MAXPLAYERS]; //the base table of ping where an average will be sent to everyone. @@ -108,7 +115,7 @@ static UINT8 resynch_local_inprogress = false; // WE are desynched and getting p static UINT8 player_joining = false; UINT8 hu_resynching = 0; -// client specific +// Client specific static ticcmd_t localcmds; static ticcmd_t localcmds2; static boolean cl_packetmissed; @@ -151,12 +158,6 @@ static consvar_t cv_showjoinaddress = {"showjoinaddress", "On", 0, CV_OnOff, NUL static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, NULL}}; consvar_t cv_playbackspeed = {"playbackspeed", "1", 0, playbackspeed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -void D_ResetTiccmds(void) -{ - memset(&localcmds, 0, sizeof(ticcmd_t)); - memset(&localcmds2, 0, sizeof(ticcmd_t)); -} - static inline void *G_DcpyTiccmd(void* dest, const ticcmd_t* src, const size_t n) { const size_t d = n / sizeof(ticcmd_t); @@ -185,11 +186,17 @@ static inline void *G_ScpyTiccmd(ticcmd_t* dest, void* src, const size_t n) -// some software don't support largest packet -// (original sersetup, not exactely, but the probabylity of sending a packet -// of 512 octet is like 0.1) +// Some software don't support largest packet +// (original sersetup, not exactely, but the probability of sending a packet +// of 512 bytes is like 0.1) UINT16 software_MAXPACKETLENGTH; +/** Guesses the value of a tic from its lowest byte and from maketic + * + * \param low The lowest byte of the tic value + * \return The full tic value + * + */ tic_t ExpandTics(INT32 low) { INT32 delta; @@ -214,7 +221,7 @@ void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum)) { #ifdef PARANOIA if (id >= MAXNETXCMD) - I_Error("command id %d too big", id); + I_Error("Command id %d too big", id); if (listnetxcmd[id] != 0) I_Error("Command id %d already used", id); #endif @@ -378,7 +385,7 @@ static void ExtraDataTicker(void) { const UINT8 id = *curpos; curpos++; - DEBFILE(va("executing x_cmd %u ply %u ", id, i)); + DEBFILE(va("executing x_cmd %s ply %u ", netxcmdnames[id - 1], i)); (listnetxcmd[id])(&curpos, i); DEBFILE("done\n"); } @@ -401,7 +408,11 @@ static void ExtraDataTicker(void) } } - D_FreeTextcmd(gametic); + // If you are a client, you can safely forget the net commands for this tic + // If you are the server, you need to remember them until every client has been aknowledged, + // because if you need to resend a PT_SERVERTICS packet, you need to put the commands in it + if (client) + D_FreeTextcmd(gametic); } static void D_Clearticcmd(tic_t tic) @@ -416,6 +427,19 @@ static void D_Clearticcmd(tic_t tic) DEBFILE(va("clear tic %5u (%2u)\n", tic, tic%BACKUPTICS)); } +void D_ResetTiccmds(void) +{ + INT32 i; + + memset(&localcmds, 0, sizeof(ticcmd_t)); + memset(&localcmds2, 0, sizeof(ticcmd_t)); + + // Reset the net command list + for (i = 0; i < TEXTCMD_HASH_SIZE; i++) + while (textcmds[i]) + D_Clearticcmd(textcmds[i]->tic); +} + // ----------------------------------------------------------------- // end of extra data function // ----------------------------------------------------------------- @@ -495,7 +519,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->powers[j] = (UINT16)SHORT(players[i].powers[j]); // Score is resynched in the rspfirm resync packet - rsp->health = 0; // resynched with mo health + rsp->rings = LONG(players[i].rings); rsp->lives = players[i].lives; rsp->continues = players[i].continues; rsp->scoreadd = players[i].scoreadd; @@ -582,7 +606,6 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->hasmo = true; rsp->health = LONG(players[i].mo->health); - rsp->angle = (angle_t)LONG(players[i].mo->angle); rsp->x = LONG(players[i].mo->x); rsp->y = LONG(players[i].mo->y); @@ -625,7 +648,7 @@ static void resynch_read_player(resynch_pak *rsp) players[i].powers[j] = (UINT16)SHORT(rsp->powers[j]); // Score is resynched in the rspfirm resync packet - players[i].health = rsp->health; + players[i].rings = LONG(rsp->rings); players[i].lives = rsp->lives; players[i].continues = rsp->continues; players[i].scoreadd = rsp->scoreadd; @@ -859,12 +882,13 @@ static inline void resynch_write_others(resynchend_pak *rst) { UINT8 i; - rst->ingame = rst->ctfteam = 0; + rst->ingame = 0; for (i = 0; i < MAXPLAYERS; ++i) { if (!playeringame[i]) { + rst->ctfteam[i] = 0; rst->score[i] = 0; rst->numboxes[i] = 0; rst->totalring[i] = 0; @@ -874,11 +898,8 @@ static inline void resynch_write_others(resynchend_pak *rst) } if (!players[i].spectator) - { rst->ingame |= (1<<i); - if (players[i].ctfteam > 1) - rst->ctfteam |= (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); rst->totalring[i] = SHORT(players[i].totalring); @@ -888,28 +909,18 @@ static inline void resynch_write_others(resynchend_pak *rst) // endian safeness rst->ingame = (UINT32)LONG(rst->ingame); - rst->ctfteam = (UINT32)LONG(rst->ctfteam); } static inline void resynch_read_others(resynchend_pak *p) { UINT8 i; UINT32 loc_ingame = (UINT32)LONG(p->ingame); - UINT32 loc_ctfteam = (UINT32)LONG(p->ctfteam); for (i = 0; i < MAXPLAYERS; ++i) { // We don't care if they're in the game or not, just write all the data. - if (loc_ingame & (1<<i)) - { - players[i].spectator = false; - players[i].ctfteam = (loc_ctfteam & (1<<i)) ? 2 : 1; - } - else - { - players[i].spectator = true; - players[i].ctfteam = 0; - } + players[i].spectator = !(loc_ingame & (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]); players[i].totalring = SHORT(p->totalring[i]); @@ -1029,6 +1040,9 @@ static void SV_AcknowledgeResynchAck(INT32 node, UINT8 rsg) resynch_status[node] &= ~(1<<rsg); --resynch_score[node]; // unpenalize } + + // Don't let resynch cause a timeout + freezetimeout[node] = I_GetTime() + connectiontimeout; } // ----------------------------------------------------------------- // end resynch @@ -1042,20 +1056,20 @@ static INT16 Consistancy(void); typedef enum { - cl_searching, - cl_downloadfiles, - cl_askjoin, - cl_waitjoinresponse, + CL_SEARCHING, + CL_DOWNLOADFILES, + CL_ASKJOIN, + CL_WAITJOINRESPONSE, #ifdef JOININGAME - cl_downloadsavegame, + CL_DOWNLOADSAVEGAME, #endif - cl_connected, - cl_aborted + CL_CONNECTED, + CL_ABORTED } cl_mode_t; static void GetPackets(void); -static cl_mode_t cl_mode = cl_searching; +static cl_mode_t cl_mode = CL_SEARCHING; // Player name send/load @@ -1108,10 +1122,10 @@ static inline void CL_DrawConnectionStatus(void) M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1); V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press ESC to abort"); - if (cl_mode != cl_downloadfiles) + if (cl_mode != CL_DOWNLOADFILES) { INT32 i, animtime = ((ccstime / 4) & 15) + 16; - UINT8 palstart = (cl_mode == cl_searching) ? 32 : 96; + UINT8 palstart = (cl_mode == CL_SEARCHING) ? 32 : 96; // 15 pal entries total. const char *cltext; @@ -1121,17 +1135,22 @@ static inline void CL_DrawConnectionStatus(void) switch (cl_mode) { #ifdef JOININGAME - case cl_downloadsavegame: - cltext = M_GetText("Downloading game state..."); - Net_GetNetStat(); - V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE, - va(" %4uK",fileneeded[lastfilenum].currentsize>>10)); - V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE, - va("%3.1fK/s ", ((double)getbps)/1024)); + case CL_DOWNLOADSAVEGAME: + if (lastfilenum != -1) + { + cltext = M_GetText("Downloading game state..."); + Net_GetNetStat(); + V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE, + va(" %4uK",fileneeded[lastfilenum].currentsize>>10)); + V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE, + va("%3.1fK/s ", ((double)getbps)/1024)); + } + else + cltext = M_GetText("Waiting to download game state..."); break; #endif - case cl_askjoin: - case cl_waitjoinresponse: + case CL_ASKJOIN: + case CL_WAITJOINRESPONSE: cltext = M_GetText("Requesting to join..."); break; default: @@ -1142,34 +1161,45 @@ static inline void CL_DrawConnectionStatus(void) } else { - INT32 dldlength; - static char tempname[32]; + if (lastfilenum != -1) + { + INT32 dldlength; + static char tempname[32]; - Net_GetNetStat(); - dldlength = (INT32)((fileneeded[lastfilenum].currentsize/(double)fileneeded[lastfilenum].totalsize) * 256); - if (dldlength > 256) - dldlength = 256; - V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 111); - V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, dldlength, 8, 96); + Net_GetNetStat(); + dldlength = (INT32)((fileneeded[lastfilenum].currentsize/(double)fileneeded[lastfilenum].totalsize) * 256); + if (dldlength > 256) + dldlength = 256; + V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 111); + V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, dldlength, 8, 96); - memset(tempname, 0, sizeof(tempname)); - nameonly(strncpy(tempname, fileneeded[lastfilenum].filename, 31)); + memset(tempname, 0, sizeof(tempname)); + nameonly(strncpy(tempname, fileneeded[lastfilenum].filename, 31)); - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-32, V_YELLOWMAP, - va(M_GetText("Downloading \"%s\""), tempname)); - V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE, - va(" %4uK/%4uK",fileneeded[lastfilenum].currentsize>>10,fileneeded[lastfilenum].totalsize>>10)); - V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE, - va("%3.1fK/s ", ((double)getbps)/1024)); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-32, V_YELLOWMAP, + va(M_GetText("Downloading \"%s\""), tempname)); + V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE, + va(" %4uK/%4uK",fileneeded[lastfilenum].currentsize>>10,fileneeded[lastfilenum].totalsize>>10)); + V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE, + va("%3.1fK/s ", ((double)getbps)/1024)); + } + else + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-32, V_YELLOWMAP, + M_GetText("Waiting to download files...")); } } #endif -// -// CL_SendJoin -// -// send a special packet for declare how many player in local -// used only in arbitratrenetstart() +/** Sends a special packet to declare how many players in local + * Used only in arbitratrenetstart() + * Sends a PT_CLIENTJOIN packet to the server + * + * \return True if the packet was successfully sent + * \todo Improve the description... + * Because to be honest, I have no idea what arbitratrenetstart is... + * Is it even used...? + * + */ static boolean CL_SendJoin(void) { UINT8 localplayers = 1; @@ -1304,6 +1334,12 @@ static void SV_SendPlayerInfo(INT32 node) HSendPacket(node, false, 0, sizeof(plrinfo) * MAXPLAYERS); } +/** Sends a PT_SERVERCFG packet + * + * \param node The destination + * \return True if the packet was successfully sent + * + */ static boolean SV_SendServerConfig(INT32 node) { INT32 i; @@ -1436,8 +1472,12 @@ static void SV_SendSaveGame(INT32 node) WRITEUINT32(savebuffer, 0); } - SendRam(node, buffertosend, length, SF_RAM, 0); + SV_SendRam(node, buffertosend, length, SF_RAM, 0); save_p = NULL; + + // Remember when we started sending the savegame so we can handle timeouts + sendingsavegame[node] = true; + freezetimeout[node] = I_GetTime() + jointimeout + length / 1024; // 1 extra tic for each kilobyte } #ifdef DUMPCONSISTENCY @@ -1531,7 +1571,7 @@ static void CL_LoadReceivedSavegame(void) { CONS_Printf(": %s", mapheaderinfo[gamemap-1]->lvlttl); if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) - CONS_Printf(M_GetText("ZONE")); + CONS_Printf(M_GetText(" ZONE")); if (actnum > 0) CONS_Printf(" %2d", actnum); } @@ -1687,11 +1727,252 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room) #endif // ifndef NONET -// use adaptive send using net_bandwidth and stat.sendbytes +/** Called by CL_ServerConnectionTicker + * + * \param viams ??? + * \param asksent ??? + * \return False if the connection was aborted + * \sa CL_ServerConnectionTicker + * \sa CL_ConnectToServer + * + */ +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) + { + // this can be a responce to our broadcast request + if (servernode == -1 || servernode >= MAXNETNODES) + { + i = 0; + servernode = serverlist[i].node; + CONS_Printf(M_GetText("Found, ")); + } + else + { + i = SL_SearchServer(servernode); + if (i < 0) + return true; + } + + // Quit here rather than downloading files and being refused later. + if (serverlist[i].info.numberofplayer >= serverlist[i].info.maxplayer) + { + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(va(M_GetText("Maximum players reached: %d\n\nPress ESC\n"), serverlist[i].info.maxplayer), NULL, MM_NOTHING); + return false; + } + + if (client) + { + D_ParseFileneeded(serverlist[i].info.fileneedednum, + serverlist[i].info.fileneeded); + CONS_Printf(M_GetText("Checking files...\n")); + i = CL_CheckFiles(); + if (i == 2) // cannot join for some reason + { + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText( + "You have WAD files loaded or have\n" + "modified the game in some way, and\n" + "your file list does not match\n" + "the server's file list.\n" + "Please restart SRB2 before connecting.\n\n" + "Press ESC\n" + ), NULL, MM_NOTHING); + return false; + } + else if (i == 1) + cl_mode = CL_ASKJOIN; + else + { + // must download something + // can we, though? + if (!CL_CheckDownloadable()) // nope! + { + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + M_StartMessage(M_GetText( + "You cannot connect to this server\n" + "because you cannot download the files\n" + "that you are missing from the server.\n\n" + "See the console or log file for\n" + "more details.\n\n" + "Press ESC\n" + ), NULL, MM_NOTHING); + return false; + } + // no problem if can't send packet, we will retry later + if (CL_SendRequestFile()) + cl_mode = CL_DOWNLOADFILES; + } + } + else + cl_mode = CL_ASKJOIN; // files need not be checked for the server. + + return true; + } + + // Ask the info to the server (askinfo packet) + if (*asksent + NEWTICRATE < I_GetTime()) + { + SendAskInfo(servernode, viams); + *asksent = I_GetTime(); + } +#else + (void)viams; + (void)asksent; + // No netgames, so we skip this state. + cl_mode = CL_ASKJOIN; +#endif // ifndef NONET/else + + return true; +} + +/** Called by CL_ConnectToServer + * + * \param viams ??? + * \param tmpsave The name of the gamestate file??? + * \param oldtic Used for knowing when to poll events and redraw + * \param asksent ??? + * \return False if the connection was aborted + * \sa CL_ServerConnectionSearchTicker + * \sa CL_ConnectToServer + * + */ +static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic_t *oldtic, tic_t *asksent) +{ + boolean waitmore; + INT32 i; + +#ifdef NONET + (void)tmpsave; +#endif + + switch (cl_mode) + { + case CL_SEARCHING: + if (!CL_ServerConnectionSearchTicker(viams, asksent)) + return false; + break; + + case CL_DOWNLOADFILES: + waitmore = false; + for (i = 0; i < fileneedednum; i++) + if (fileneeded[i].status == FS_DOWNLOADING + || fileneeded[i].status == FS_REQUESTED) + { + waitmore = true; + break; + } + if (waitmore) + break; // exit the case + + cl_mode = CL_ASKJOIN; // don't break case continue to cljoin request now + + case CL_ASKJOIN: + CL_LoadServerFiles(); +#ifdef JOININGAME + // prepare structures to save the file + // WARNING: this can be useless in case of server not in GS_LEVEL + // but since the network layer doesn't provide ordered packets... + CL_PrepareDownloadSaveGame(tmpsave); +#endif + if (CL_SendJoin()) + cl_mode = CL_WAITJOINRESPONSE; + break; + +#ifdef JOININGAME + case CL_DOWNLOADSAVEGAME: + // At this state, the first (and only) needed file is the gamestate + if (fileneeded[0].status == FS_FOUND) + { + // Gamestate is now handled within CL_LoadReceivedSavegame() + CL_LoadReceivedSavegame(); + cl_mode = CL_CONNECTED; + } // don't break case continue to CL_CONNECTED + else + break; +#endif + + case CL_WAITJOINRESPONSE: + case CL_CONNECTED: + default: + break; + + // Connection closed by cancel, timeout or refusal. + case CL_ABORTED: + cl_mode = CL_SEARCHING; + return false; + + } + + GetPackets(); + Net_AckTicker(); + + // Call it only once by tic + if (*oldtic != I_GetTime()) + { + INT32 key; + + I_OsPolling(); + key = I_GetKey(); + if (key == KEY_ESCAPE) + { + CONS_Printf(M_GetText("Network game synchronization aborted.\n")); +// M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING); + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + return false; + } + + // why are these here? this is for servers, we're a client + //if (key == 's' && server) + // doomcom->numnodes = (INT16)pnumnodes; + //SV_FileSendTicker(); + *oldtic = I_GetTime(); + +#ifdef CLIENT_LOADINGSCREEN + if (client && cl_mode != CL_CONNECTED && cl_mode != CL_ABORTED) + { + F_TitleScreenTicker(true); + F_TitleScreenDrawer(); + CL_DrawConnectionStatus(); + I_UpdateNoVsync(); // page flip or blit buffer + if (moviemode) + M_SaveFrame(); + } +#else + CON_Drawer(); + I_UpdateNoVsync(); +#endif + } + else + I_Sleep(); + + return true; +} + +/** Use adaptive send using net_bandwidth and stat.sendbytes + * + * \param viams ??? + * \todo Better description... + * + */ static void CL_ConnectToServer(boolean viams) { INT32 pnumnodes, nodewaited = doomcom->numnodes, i; - boolean waitmore; tic_t oldtic; #ifndef NONET tic_t asksent; @@ -1702,14 +1983,14 @@ static void CL_ConnectToServer(boolean viams) sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); #endif - cl_mode = cl_searching; + cl_mode = CL_SEARCHING; #ifdef CLIENT_LOADINGSCREEN - lastfilenum = 0; + lastfilenum = -1; #endif #ifdef JOININGAME - // don't get a corrupt savegame error because tmpsave already exists + // Don't get a corrupt savegame error because tmpsave already exists if (FIL_FileExists(tmpsave) && unlink(tmpsave) == -1) I_Error("Can't delete %s\n", tmpsave); #endif @@ -1733,7 +2014,7 @@ static void CL_ConnectToServer(boolean viams) pnumnodes = 1; oldtic = I_GetTime() - 1; #ifndef NONET - asksent = (tic_t)-TICRATE; + asksent = (tic_t) - TICRATE; i = SL_SearchServer(servernode); @@ -1760,197 +2041,23 @@ static void CL_ConnectToServer(boolean viams) do { - switch (cl_mode) - { - case cl_searching: + // If the connection was aborted for some reason, leave #ifndef NONET - // serverlist is updated by GetPacket function - if (serverlistcount > 0) - { - // this can be a responce to our broadcast request - if (servernode == -1 || servernode >= MAXNETNODES) - { - i = 0; - servernode = serverlist[i].node; - CONS_Printf(M_GetText("Found, ")); - } - else - { - i = SL_SearchServer(servernode); - if (i < 0) - break; // the case - } - - // Quit here rather than downloading files and being refused later. - if (serverlist[i].info.numberofplayer >= serverlist[i].info.maxplayer) - { - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(va(M_GetText("Maximum players reached: %d\n\nPress ESC\n"), serverlist[i].info.maxplayer), NULL, MM_NOTHING); - return; - } - - if (!server) - { - D_ParseFileneeded(serverlist[i].info.fileneedednum, - serverlist[i].info.fileneeded); - CONS_Printf(M_GetText("Checking files...\n")); - i = CL_CheckFiles(); - if (i == 2) // cannot join for some reason - { - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(M_GetText( - "You have WAD files loaded or have\n" - "modified the game in some way, and\n" - "your file list does not match\n" - "the server's file list.\n" - "Please restart SRB2 before connecting.\n\n" - "Press ESC\n" - ), NULL, MM_NOTHING); - return; - } - else if (i == 1) - cl_mode = cl_askjoin; - else - { - // must download something - // can we, though? - if (!CL_CheckDownloadable()) // nope! - { - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - M_StartMessage(M_GetText( - "You cannot conect to this server\n" - "because you cannot download the files\n" - "that you are missing from the server.\n\n" - "See the console or log file for\n" - "more details.\n\n" - "Press ESC\n" - ), NULL, MM_NOTHING); - return; - } - // no problem if can't send packet, we will retry later - if (CL_SendRequestFile()) - cl_mode = cl_downloadfiles; - } - } - else - cl_mode = cl_askjoin; // files need not be checked for the server. - break; - } - // ask the info to the server (askinfo packet) - if (asksent + NEWTICRATE < I_GetTime()) - { - SendAskInfo(servernode, viams); - asksent = I_GetTime(); - } + if (!CL_ServerConnectionTicker(viams, tmpsave, &oldtic, &asksent)) #else - (void)viams; - // No netgames, so we skip this state. - cl_mode = cl_askjoin; -#endif // ifndef NONET/else - break; - case cl_downloadfiles: - waitmore = false; - for (i = 0; i < fileneedednum; i++) - if (fileneeded[i].status == FS_DOWNLOADING - || fileneeded[i].status == FS_REQUESTED) - { - waitmore = true; - break; - } - if (waitmore) - break; // exit the case - - cl_mode = cl_askjoin; // don't break case continue to cljoin request now - case cl_askjoin: - CL_LoadServerFiles(); -#ifdef JOININGAME - // prepare structures to save the file - // WARNING: this can be useless in case of server not in GS_LEVEL - // but since the network layer doesn't provide ordered packets... - CL_PrepareDownloadSaveGame(tmpsave); + if (!CL_ServerConnectionTicker(viams, (char*)NULL, &oldtic, (tic_t *)NULL)) #endif - if (CL_SendJoin()) - cl_mode = cl_waitjoinresponse; - break; -#ifdef JOININGAME - case cl_downloadsavegame: - if (fileneeded[0].status == FS_FOUND) - { - // Gamestate is now handled within CL_LoadReceivedSavegame() - CL_LoadReceivedSavegame(); - cl_mode = cl_connected; - } // don't break case continue to cl_connected - else - break; -#endif - case cl_waitjoinresponse: - case cl_connected: - default: - break; - - // Connection closed by cancel, timeout or refusal. - case cl_aborted: - cl_mode = cl_searching; - return; - } - - GetPackets(); - Net_AckTicker(); - - // call it only one by tic - if (oldtic != I_GetTime()) - { - INT32 key; - - I_OsPolling(); - key = I_GetKey(); - if (key == KEY_ESCAPE) - { - CONS_Printf(M_GetText("Network game synchronization aborted.\n")); -// M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING); - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - return; - } - - // why are these here? this is for servers, we're a client - //if (key == 's' && server) - // doomcom->numnodes = (INT16)pnumnodes; - //FiletxTicker(); - oldtic = I_GetTime(); - -#ifdef CLIENT_LOADINGSCREEN - if (!server && cl_mode != cl_connected && cl_mode != cl_aborted) - { - F_TitleScreenTicker(true); - F_TitleScreenDrawer(); - CL_DrawConnectionStatus(); - I_UpdateNoVsync(); // page flip or blit buffer - if (moviemode) - M_SaveFrame(); - } -#else - CON_Drawer(); - I_UpdateNoVsync(); -#endif - } - else I_Sleep(); + return; if (server) { pnumnodes = 0; for (i = 0; i < MAXNETNODES; i++) - if (nodeingame[i]) pnumnodes++; + if (nodeingame[i]) + pnumnodes++; } } - while (!(cl_mode == cl_connected && (!server || (server && nodewaited <= pnumnodes)))); + while (!(cl_mode == CL_CONNECTED && (client || (server && nodewaited <= pnumnodes)))); DEBFILE(va("Synchronisation Finished\n")); @@ -2207,7 +2314,6 @@ void CL_ClearPlayer(INT32 playernum) P_RemoveMobj(players[playernum].mo->tracer); P_RemoveMobj(players[playernum].mo); } - players[playernum].mo = NULL; memset(&players[playernum], 0, sizeof (player_t)); } @@ -2254,7 +2360,7 @@ static void CL_RemovePlayer(INT32 playernum) } count--; - rings = players[playernum].health - 1; + rings = players[playernum].rings; increment = rings/count; for (i = 0; i < MAXPLAYERS; i++) @@ -2488,6 +2594,14 @@ static void Command_Kick(void) 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 + if (sendingsavegame[playernode[pn]]) + { + Net_ConnectionTimeout(playernode[pn]); + return; + } if (COM_Argc() == 2) { WRITEUINT8(p, KICK_MSG_GO_AWAY); @@ -2700,7 +2814,12 @@ consvar_t cv_blamecfail = {"blamecfail", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL // max file size to send to a player (in kilobytes) static CV_PossibleValue_t maxsend_cons_t[] = {{0, "MIN"}, {51200, "MAX"}, {0, NULL}}; -consvar_t cv_maxsend = {"maxsend", "1024", CV_SAVE, maxsend_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_maxsend = {"maxsend", "4096", CV_SAVE, maxsend_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_noticedownload = {"noticedownload", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; + +// Speed of file downloading (in packets per tic) +static CV_PossibleValue_t downloadspeed_cons_t[] = {{0, "MIN"}, {32, "MAX"}, {0, NULL}}; +consvar_t cv_downloadspeed = {"downloadspeed", "16", CV_SAVE, downloadspeed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static void Got_AddPlayer(UINT8 **p, INT32 playernum); @@ -2719,6 +2838,13 @@ void D_ClientServerInit(void) COM_AddCommand("reloadbans", Command_ReloadBan); COM_AddCommand("connect", Command_connect); COM_AddCommand("nodes", Command_Nodes); +#ifdef PACKETDROP + COM_AddCommand("drop", Command_Drop); + COM_AddCommand("droprate", Command_Droprate); +#endif +#ifdef _DEBUG + COM_AddCommand("numnodes", Command_Numnodes); +#endif #endif RegisterNetXCmd(XD_KICK, Got_KickCmd); @@ -2754,6 +2880,7 @@ static void ResetNode(INT32 node) supposedtics[node] = gametic; nodewaiting[node] = 0; playerpernode[node] = 0; + sendingsavegame[node] = false; } void SV_ResetServer(void) @@ -2762,7 +2889,7 @@ void SV_ResetServer(void) // +1 because this command will be executed in com_executebuffer in // tryruntic so gametic will be incremented, anyway maketic > gametic - // is not a issue + // is not an issue maketic = gametic + 1; neededtic = maketic; @@ -2816,7 +2943,7 @@ static inline void SV_GenContext(void) for (i = 0; i < 8; i++) { const char a = M_RandomKey(26*2); - if (a <= 26) // uppercase + if (a < 26) // uppercase server_context[i] = 'A'+a; else // lowercase server_context[i] = 'a'+(a-26); @@ -2851,7 +2978,7 @@ void D_QuitNetGame(void) if (serverrunning && ms_RoomId > 0) UnregisterServer(); } - else if (servernode > 0 && servernode < MAXNETNODES && nodeingame[(UINT8)servernode]!=0) + else if (servernode > 0 && servernode < MAXNETNODES && nodeingame[(UINT8)servernode]) { netbuffer->packettype = PT_CLIENTQUIT; HSendPacket(servernode, true, 0, 0); @@ -2872,12 +2999,12 @@ void D_QuitNetGame(void) #endif } -// add a node to the game (player will follow at map change or at savegame....) +// Adds a node to the game (player will follow at map change or at savegame....) static inline void SV_AddNode(INT32 node) { nettics[node] = gametic; supposedtics[node] = gametic; - // little hack because the server connect to itself and put + // little hack because the server connects to itself and puts // nodeingame when connected not here if (node) nodeingame[node] = true; @@ -3027,7 +3154,7 @@ static boolean SV_AddWaitingPlayers(void) void CL_AddSplitscreenPlayer(void) { - if (cl_mode == cl_connected) + if (cl_mode == CL_CONNECTED) CL_SendJoin(); } @@ -3035,7 +3162,7 @@ void CL_RemoveSplitscreenPlayer(void) { XBOXSTATIC UINT8 buf[2]; - if (cl_mode != cl_connected) + if (cl_mode != CL_CONNECTED) return; buf[0] = (UINT8)secondarydisplayplayer; @@ -3046,7 +3173,7 @@ void CL_RemoveSplitscreenPlayer(void) // is there a game running boolean Playing(void) { - return (server && serverrunning) || (!server && cl_mode == cl_connected); + return (server && serverrunning) || (client && cl_mode == CL_CONNECTED); } boolean SV_SpawnServer(void) @@ -3094,7 +3221,7 @@ void SV_StopServer(void) D_Clearticcmd(i); consoleplayer = 0; - cl_mode = cl_searching; + cl_mode = CL_SEARCHING; maketic = gametic+1; neededtic = maketic; serverrunning = false; @@ -3140,6 +3267,11 @@ static size_t TotalTextCmdPerTic(tic_t tic) return total; } +/** Called when a PT_CLIENTJOIN packet is received + * + * \param node The packet sender + * + */ static void HandleConnect(SINT8 node) { if (bannednode && bannednode[node]) @@ -3171,6 +3303,9 @@ static void HandleConnect(SINT8 node) #endif SV_AddNode(node); + /// \note Wait what??? + /// What if the gamestate takes more than one second to get downloaded? + /// Or if a lagspike happens? // you get a free second before desynch checks. use it wisely. SV_InitResynchVars(node); @@ -3179,6 +3314,7 @@ static void HandleConnect(SINT8 node) if (!SV_SendServerConfig(node)) { G_SetGamestate(backupstate); + /// \note Shouldn't SV_SendRefuse be called before ResetNode? ResetNode(node); SV_SendRefuse(node, M_GetText("Server couldn't send info, please try again")); /// \todo fix this !!! @@ -3209,6 +3345,11 @@ static void HandleConnect(SINT8 node) } } +/** Called when a PT_SERVERSHUTDOWN packet is received + * + * \param node The packet sender (should be the server) + * + */ static void HandleShutdown(SINT8 node) { (void)node; @@ -3218,6 +3359,11 @@ static void HandleShutdown(SINT8 node) M_StartMessage(M_GetText("Server has shutdown\n\nPress Esc\n"), NULL, MM_NOTHING); } +/** Called when a PT_NODETIMEOUT packet is received + * + * \param node The packet sender (should be the server) + * + */ static void HandleTimeout(SINT8 node) { (void)node; @@ -3228,6 +3374,12 @@ static void HandleTimeout(SINT8 node) } #ifndef NONET +/** Called when a PT_SERVERINFO packet is received + * + * \param node The packet sender + * \note What happens if the packet comes from a client or something like that? + * + */ static void HandleServerInfo(SINT8 node) { // compute ping in ms @@ -3241,39 +3393,572 @@ static void HandleServerInfo(SINT8 node) } #endif -/** \brief GetPackets +/** Handles a packet received from a node that isn't in game + * + * \param node The packet sender + * \todo Choose a better name, as the packet can also come from the server apparently? + * \sa HandlePacketFromPlayer + * \sa GetPackets + * + */ +static void HandlePacketFromAwayNode(SINT8 node) +{ + if (node != servernode) + DEBFILE(va("Received packet from unknown host %d\n", node)); - \todo break this 300 line function into multiple functions -*/ -static void GetPackets(void) + switch (netbuffer->packettype) + { + case PT_ASKINFOVIAMS: + 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. + } + break; + + case PT_ASKINFO: + if (server && serverrunning) + { + SV_SendServerInfo(node, (tic_t)LONG(netbuffer->u.askinfo.time)); + SV_SendPlayerInfo(node); // Send extra info + Net_CloseConnection(node); + } + break; + + case PT_SERVERREFUSE: // Negative response of client join request + if (server && serverrunning) + { // But wait I thought I'm the server? + Net_CloseConnection(node); + break; + } + if (cl_mode == CL_WAITJOINRESPONSE) + { + // Save the reason so it can be displayed after quitting the netgame + char *reason = strdup(netbuffer->u.serverrefuse.reason); + if (!reason) + I_Error("Out of memory!\n"); + + D_QuitNetGame(); + CL_Reset(); + D_StartTitle(); + + M_StartMessage(va(M_GetText("Server refuses connection\n\nReason:\n%s"), + reason), NULL, MM_NOTHING); + + free(reason); + + // Will be reset by caller. Signals refusal. + cl_mode = CL_ABORTED; + } + break; + + case PT_SERVERCFG: // Positive response of client join request + { + INT32 j; + UINT8 *scp; + + if (server && serverrunning && node != servernode) + { // but wait I thought I'm the server? + Net_CloseConnection(node); + break; + } + /// \note how would this happen? and is it doing the right thing if it does? + if (cl_mode != CL_WAITJOINRESPONSE) + break; + + if (client) + { + maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic); + gametype = netbuffer->u.servercfg.gametype; + modifiedgame = netbuffer->u.servercfg.modifiedgame; + adminplayer = netbuffer->u.servercfg.adminplayer; + memcpy(server_context, netbuffer->u.servercfg.server_context, 8); + } + + nodeingame[(UINT8)servernode] = true; + serverplayer = netbuffer->u.servercfg.serverplayer; + doomcom->numslots = SHORT(netbuffer->u.servercfg.totalslotnum); + mynode = netbuffer->u.servercfg.clientnode; + if (serverplayer >= 0) + playernode[(UINT8)serverplayer] = servernode; + + if (netgame) +#ifdef JOININGAME + CONS_Printf(M_GetText("Join accepted, waiting for complete game state...\n")); +#else + CONS_Printf(M_GetText("Join accepted, waiting for next level change...\n")); +#endif + DEBFILE(va("Server accept join gametic=%u mynode=%d\n", gametic, mynode)); + + memset(playeringame, 0, sizeof(playeringame)); + for (j = 0; j < MAXPLAYERS; j++) + { + if (netbuffer->u.servercfg.playerskins[j] == 0xFF + && netbuffer->u.servercfg.playercolor[j] == 0xFF) + continue; // not in game + + playeringame[j] = true; + SetPlayerSkinByNum(j, (INT32)netbuffer->u.servercfg.playerskins[j]); + players[j].skincolor = netbuffer->u.servercfg.playercolor[j]; + } + + scp = netbuffer->u.servercfg.varlengthinputs; + CV_LoadPlayerNames(&scp); + CV_LoadNetVars(&scp); +#ifdef JOININGAME + /// \note Wait. What if a Lua script uses some global custom variables synched with the NetVars hook? + /// Shouldn't them be downloaded even at intermission time? + /// Also, according to HandleConnect, the server will send the savegame even during intermission... + if (netbuffer->u.servercfg.gamestate == GS_LEVEL/* || + netbuffer->u.servercfg.gamestate == GS_INTERMISSION*/) + cl_mode = CL_DOWNLOADSAVEGAME; + else +#endif + cl_mode = CL_CONNECTED; + break; + } + + // Handled in d_netfil.c + case PT_FILEFRAGMENT: + if (server) + { // But wait I thought I'm the server? + Net_CloseConnection(node); + break; + } + else + Got_Filetxpak(); + break; + + case PT_REQUESTFILE: + if (server) + Got_RequestFilePak(node); + break; + + case PT_NODETIMEOUT: + case PT_CLIENTQUIT: + if (server) + Net_CloseConnection(node); + break; + + case PT_CLIENTCMD: + break; // This is not an "unknown packet" + + case PT_SERVERTICS: + // Do not remove my own server (we have just get a out of order packet) + if (node == servernode) + break; + + default: + DEBFILE(va("unknown packet received (%d) from unknown host\n",netbuffer->packettype)); + Net_CloseConnection(node); + break; // Ignore it + + } +} + +/** Handles a packet received from a node that is in game + * + * \param node The packet sender + * \todo Choose a better name + * \sa HandlePacketFromAwayNode + * \sa GetPackets + * + */ +static void HandlePacketFromPlayer(SINT8 node) {FILESTAMP XBOXSTATIC INT32 netconsole; - XBOXSTATIC SINT8 node; - XBOXSTATIC tic_t realend,realstart; + XBOXSTATIC tic_t realend, realstart; XBOXSTATIC UINT8 *pak, *txtpak, numtxtpak; FILESTAMP + txtpak = NULL; + + if (dedicated && node == 0) + netconsole = 0; + else + netconsole = nodetoplayer[node]; +#ifdef PARANOIA + if (netconsole >= MAXPLAYERS) + I_Error("bad table nodetoplayer: node %d player %d", doomcom->remotenode, netconsole); +#endif + + switch (netbuffer->packettype) + { +// -------------------------------------------- SERVER RECEIVE ---------- + case PT_RESYNCHGET: + SV_AcknowledgeResynchAck(netconsole, netbuffer->u.resynchgot); + break; + case PT_CLIENTCMD: + case PT_CLIENT2CMD: + case PT_CLIENTMIS: + case PT_CLIENT2MIS: + case PT_NODEKEEPALIVE: + case PT_NODEKEEPALIVEMIS: + if (client) + break; + + // Ignore tics from those not synched + if (resynch_inprogress[node]) + break; + + // To save bytes, only the low byte of tic numbers are sent + // Use ExpandTics to figure out what the rest of the bytes are + realstart = ExpandTics(netbuffer->u.clientpak.client_tic); + realend = ExpandTics(netbuffer->u.clientpak.resendfrom); + + if (netbuffer->packettype == PT_CLIENTMIS || netbuffer->packettype == PT_CLIENT2MIS + || netbuffer->packettype == PT_NODEKEEPALIVEMIS + || supposedtics[node] < realend) + { + supposedtics[node] = realend; + } + // Discard out of order packet + if (nettics[node] > realend) + { + DEBFILE(va("out of order ticcmd discarded nettics = %u\n", nettics[node])); + break; + } + + // Update the nettics + nettics[node] = realend; + + // Don't do anything for packets of type NODEKEEPALIVE? + if (netconsole == -1 || netbuffer->packettype == PT_NODEKEEPALIVE + || netbuffer->packettype == PT_NODEKEEPALIVEMIS) + break; + + // If a client sends a ticcmd it should mean they are done receiving the savegame + sendingsavegame[node] = false; + + // As long as clients send valid ticcmds, the server can keep running, so reset the timeout + /// \todo Use a separate cvar for that kind of timeout? + freezetimeout[node] = I_GetTime() + connectiontimeout; + + // Copy ticcmd + G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1); + + // Check ticcmd for "speed hacks" + if (netcmds[maketic%BACKUPTICS][netconsole].forwardmove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].forwardmove < -MAXPLMOVE + || netcmds[maketic%BACKUPTICS][netconsole].sidemove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].sidemove < -MAXPLMOVE) + { + XBOXSTATIC char buf[2]; + CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), netconsole); + //D_Clearticcmd(k); + + buf[0] = (char)netconsole; + buf[1] = KICK_MSG_CON_FAIL; + SendNetXCmd(XD_KICK, &buf, 2); + break; + } + + // Splitscreen cmd + if (netbuffer->packettype == PT_CLIENT2CMD && nodetoplayer2[node] >= 0) + G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]], + &netbuffer->u.client2pak.cmd2, 1); + + // A delay before we check resynching + // Used on join or just after a synch fail + if (resynch_delay[node]) + { + --resynch_delay[node]; + break; + } + // Check player consistancy during the level + if (realstart <= gametic && realstart > gametic - BACKUPTICS+1 && gamestate == GS_LEVEL + && consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy)) + { + SV_RequireResynch(node); + + if (cv_resynchattempts.value && resynch_score[node] <= (unsigned)cv_resynchattempts.value*250) + { + if (cv_blamecfail.value) + CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"), + netconsole+1, player_names[netconsole], + consistancy[realstart%BACKUPTICS], + SHORT(netbuffer->u.clientpak.consistancy)); + DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n", + netconsole, realstart, consistancy[realstart%BACKUPTICS], + SHORT(netbuffer->u.clientpak.consistancy))); + break; + } + else + { + XBOXSTATIC UINT8 buf[3]; + + buf[0] = (UINT8)netconsole; + buf[1] = KICK_MSG_CON_FAIL; + SendNetXCmd(XD_KICK, &buf, 2); + DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n", + netconsole, realstart, consistancy[realstart%BACKUPTICS], + SHORT(netbuffer->u.clientpak.consistancy))); + break; + } + } + else if (resynch_score[node]) + --resynch_score[node]; + break; + case PT_TEXTCMD2: // splitscreen special + netconsole = nodetoplayer2[node]; + case PT_TEXTCMD: + if (client) + break; + + if (netconsole < 0 || netconsole >= MAXPLAYERS) + Net_UnAcknowledgePacket(node); + else + { + size_t j; + tic_t tic = maketic; + UINT8 *textcmd; + + // 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 + - (netbuffer->u.textcmd[0]+2+BASESERVERTICSSIZE + + (doomcom->numslots+1)*sizeof(ticcmd_t)); + + // search a tic that have enougth space in the ticcmd + while ((textcmd = D_GetExistingTextcmd(tic, netconsole)), + (TotalTextCmdPerTic(tic) > j || netbuffer->u.textcmd[0] + (textcmd ? textcmd[0] : 0) > MAXTEXTCMD) + && tic < firstticstosend + BACKUPTICS) + tic++; + + if (tic >= firstticstosend + BACKUPTICS) + { + DEBFILE(va("GetPacket: Textcmd too long (max %s, used %s, mak %d, " + "tosend %u, node %u, player %d)\n", sizeu1(j), sizeu2(TotalTextCmdPerTic(maketic)), + maketic, firstticstosend, node, netconsole)); + Net_UnAcknowledgePacket(node); + break; + } + + // Make sure we have a buffer + if (!textcmd) textcmd = D_GetTextcmd(tic, netconsole); + + DEBFILE(va("textcmd put in tic %u at position %d (player %d) ftts %u mk %u\n", + tic, textcmd[0]+1, netconsole, firstticstosend, maketic)); + + M_Memcpy(&textcmd[textcmd[0]+1], netbuffer->u.textcmd+1, netbuffer->u.textcmd[0]); + textcmd[0] += (UINT8)netbuffer->u.textcmd[0]; + } + break; + case PT_NODETIMEOUT: + case PT_CLIENTQUIT: + if (client) + break; + + // nodeingame will be put false in the execution of kick command + // this allow to send some packets to the quitting client to have their ack back + nodewaiting[node] = 0; + if (netconsole != -1 && playeringame[netconsole]) + { + XBOXSTATIC UINT8 buf[2]; + buf[0] = (UINT8)netconsole; + if (netbuffer->packettype == PT_NODETIMEOUT) + buf[1] = KICK_MSG_TIMEOUT; + else + buf[1] = KICK_MSG_PLAYER_QUIT; + SendNetXCmd(XD_KICK, &buf, 2); + nodetoplayer[node] = -1; + if (nodetoplayer2[node] != -1 && nodetoplayer2[node] >= 0 + && playeringame[(UINT8)nodetoplayer2[node]]) + { + buf[0] = nodetoplayer2[node]; + SendNetXCmd(XD_KICK, &buf, 2); + nodetoplayer2[node] = -1; + } + } + Net_CloseConnection(node); + nodeingame[node] = false; + break; +// -------------------------------------------- CLIENT RECEIVE ---------- + case PT_RESYNCHEND: + // Only accept PT_RESYNCHEND from the server. + if (node != servernode) + { + CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_RESYNCHEND", node); + + if (server) + { + XBOXSTATIC UINT8 buf[2]; + buf[0] = (UINT8)node; + buf[1] = KICK_MSG_CON_FAIL; + SendNetXCmd(XD_KICK, &buf, 2); + } + + break; + } + resynch_local_inprogress = false; + + P_SetRandSeed(netbuffer->u.resynchend.randomseed); + + if (gametype == GT_CTF) + resynch_read_ctf(&netbuffer->u.resynchend); + resynch_read_others(&netbuffer->u.resynchend); + + break; + case PT_SERVERTICS: + // Only accept PT_SERVERTICS from the server. + if (node != servernode) + { + CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_SERVERTICS", node); + + if (server) + { + XBOXSTATIC UINT8 buf[2]; + buf[0] = (UINT8)node; + buf[1] = KICK_MSG_CON_FAIL; + SendNetXCmd(XD_KICK, &buf, 2); + } + + break; + } + + realstart = ExpandTics(netbuffer->u.serverpak.starttic); + realend = realstart + netbuffer->u.serverpak.numtics; + + if (!txtpak) + txtpak = (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots + * netbuffer->u.serverpak.numtics]; + + if (realend > gametic + BACKUPTICS) + realend = gametic + BACKUPTICS; + cl_packetmissed = realstart > neededtic; + + if (realstart <= neededtic && realend > neededtic) + { + tic_t i, j; + pak = (UINT8 *)&netbuffer->u.serverpak.cmds; + + for (i = realstart; i < realend; i++) + { + // clear first + D_Clearticcmd(i); + + // copy the tics + pak = G_ScpyTiccmd(netcmds[i%BACKUPTICS], pak, + netbuffer->u.serverpak.numslots*sizeof (ticcmd_t)); + + // copy the textcmds + numtxtpak = *txtpak++; + for (j = 0; j < numtxtpak; j++) + { + INT32 k = *txtpak++; // playernum + const size_t txtsize = txtpak[0]+1; + + M_Memcpy(D_GetTextcmd(i, k), txtpak, txtsize); + txtpak += txtsize; + } + } + + neededtic = realend; + } + else + { + DEBFILE(va("frame not in bound: %u\n", neededtic)); + /*if (realend < neededtic - 2 * TICRATE || neededtic + 2 * TICRATE < realstart) + I_Error("Received an out of order PT_SERVERTICS packet!\n" + "Got tics %d-%d, needed tic %d\n\n" + "Please report this crash on the Master Board,\n" + "IRC or Discord so it can be fixed.\n", (INT32)realstart, (INT32)realend, (INT32)neededtic);*/ + } + break; + case PT_RESYNCHING: + // Only accept PT_RESYNCHING from the server. + if (node != servernode) + { + CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_RESYNCHING", node); + + if (server) + { + XBOXSTATIC char buf[2]; + buf[0] = (char)node; + buf[1] = KICK_MSG_CON_FAIL; + SendNetXCmd(XD_KICK, &buf, 2); + } + + break; + } + resynch_local_inprogress = true; + CL_AcknowledgeResynch(&netbuffer->u.resynchpak); + break; +#ifdef NEWPING + case PT_PING: + // Only accept PT_PING from the server. + if (node != servernode) + { + CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_PING", node); + + if (server) + { + XBOXSTATIC char buf[2]; + buf[0] = (char)node; + buf[1] = KICK_MSG_CON_FAIL; + SendNetXCmd(XD_KICK, &buf, 2); + } + + break; + } + + //Update client ping table from the server. + if (client) + { + INT32 i; + for (i = 0; i < MAXNETNODES; i++) + if (playeringame[i]) + playerpingtable[i] = (tic_t)netbuffer->u.pingtable[i]; + } + + break; +#endif + case PT_SERVERCFG: + break; + case PT_FILEFRAGMENT: + if (client) + Got_Filetxpak(); + break; + default: + DEBFILE(va("UNKNOWN PACKET TYPE RECEIVED %d from host %d\n", + netbuffer->packettype, node)); + } // end switch +} + +/** Handles all received packets, if any + * + * \todo Add details to this description (lol) + * + */ +static void GetPackets(void) +{FILESTAMP + XBOXSTATIC SINT8 node; // The packet sender +FILESTAMP + player_joining = false; while (HGetPacket()) { node = (SINT8)doomcom->remotenode; + if (netbuffer->packettype == PT_CLIENTJOIN && server) { HandleConnect(node); continue; } - if (netbuffer->packettype == PT_SERVERSHUTDOWN && node == servernode - && !server && cl_mode != cl_searching) + if (node == servernode && client && cl_mode != CL_SEARCHING) { - HandleShutdown(node); - continue; - } - if (netbuffer->packettype == PT_NODETIMEOUT && node == servernode - && !server && cl_mode != cl_searching) - { - HandleTimeout(node); - continue; + if (netbuffer->packettype == PT_SERVERSHUTDOWN) + { + HandleShutdown(node); + continue; + } + if (netbuffer->packettype == PT_NODETIMEOUT) + { + HandleTimeout(node); + continue; + } } #ifndef NONET @@ -3287,481 +3972,13 @@ FILESTAMP if (netbuffer->packettype == PT_PLAYERINFO) continue; // We do nothing with PLAYERINFO, that's for the MS browser. - if (!nodeingame[node]) - { - if (node != servernode) - DEBFILE(va("Received packet from unknown host %d\n", node)); - - // anyone trying to join - switch (netbuffer->packettype) - { - case PT_ASKINFOVIAMS: - 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. - } - break; - - case PT_ASKINFO: - if (server && serverrunning) - { - SV_SendServerInfo(node, (tic_t)LONG(netbuffer->u.askinfo.time)); - SV_SendPlayerInfo(node); // send extra info - Net_CloseConnection(node); - } - break; - case PT_SERVERREFUSE: // negative response of client join request - if (server && serverrunning) - { // but wait I thought I'm the server? - Net_CloseConnection(node); - break; - } - if (cl_mode == cl_waitjoinresponse) - { - D_QuitNetGame(); - CL_Reset(); - D_StartTitle(); - - M_StartMessage(va(M_GetText("Server refuses connection\n\nReason:\n%s"), - netbuffer->u.serverrefuse.reason), NULL, MM_NOTHING); - - // Will be reset by caller. Signals refusal. - cl_mode = cl_aborted; - } - break; - case PT_SERVERCFG: // positive response of client join request - { - INT32 j; - UINT8 *scp; - - if (server && serverrunning && node != servernode) - { // but wait I thought I'm the server? - Net_CloseConnection(node); - break; - } - /// \note how would this happen? and is it doing the right thing if it does? - if (cl_mode != cl_waitjoinresponse) - break; - - if (!server) - { - maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic); - gametype = netbuffer->u.servercfg.gametype; - modifiedgame = netbuffer->u.servercfg.modifiedgame; - adminplayer = netbuffer->u.servercfg.adminplayer; - memcpy(server_context, netbuffer->u.servercfg.server_context, 8); - } - - nodeingame[(UINT8)servernode] = true; - serverplayer = netbuffer->u.servercfg.serverplayer; - doomcom->numslots = SHORT(netbuffer->u.servercfg.totalslotnum); - mynode = netbuffer->u.servercfg.clientnode; - if (serverplayer >= 0) - playernode[(UINT8)serverplayer] = servernode; - - if (netgame) -#ifdef JOININGAME - CONS_Printf(M_GetText("Join accepted, waiting for complete game state...\n")); -#else - CONS_Printf(M_GetText("Join accepted, waiting for next level change...\n")); -#endif - DEBFILE(va("Server accept join gametic=%u mynode=%d\n", gametic, mynode)); - - memset(playeringame, 0, sizeof(playeringame)); - for (j = 0; j < MAXPLAYERS; j++) - { - if (netbuffer->u.servercfg.playerskins[j] == 0xFF - && netbuffer->u.servercfg.playercolor[j] == 0xFF) - continue; // not in game - - playeringame[j] = true; - SetPlayerSkinByNum(j, (INT32)netbuffer->u.servercfg.playerskins[j]); - players[j].skincolor = netbuffer->u.servercfg.playercolor[j]; - } - - scp = netbuffer->u.servercfg.varlengthinputs; - CV_LoadPlayerNames(&scp); - CV_LoadNetVars(&scp); -#ifdef JOININGAME - if (netbuffer->u.servercfg.gamestate == GS_LEVEL/* || - netbuffer->u.servercfg.gamestate == GS_INTERMISSION*/) - cl_mode = cl_downloadsavegame; - else -#endif - cl_mode = cl_connected; - break; - } - // handled in d_netfil.c - case PT_FILEFRAGMENT: - if (server) - { // but wait I thought I'm the server? - Net_CloseConnection(node); - break; - } - else - Got_Filetxpak(); - break; - case PT_REQUESTFILE: - if (server) - Got_RequestFilePak(node); - break; - case PT_NODETIMEOUT: - case PT_CLIENTQUIT: - if (server) - Net_CloseConnection(node); - break; - case PT_CLIENTCMD: - break; // this is not an "unknown packet" - case PT_SERVERTICS: - // do not remove my own server (we have just get a out of order packet) - if (node == servernode) - break; - default: - DEBFILE(va("unknown packet received (%d) from unknown host\n",netbuffer->packettype)); - Net_CloseConnection(node); - break; // ignore it - } // switch - continue; //while - } - if (dedicated && node == 0) netconsole = 0; - else netconsole = nodetoplayer[node]; -#ifdef PARANOIA - if (netconsole >= MAXPLAYERS) - I_Error("bad table nodetoplayer: node %d player %d", doomcom->remotenode, netconsole); -#endif - - txtpak = NULL; - - switch (netbuffer->packettype) - { -// -------------------------------------------- SERVER RECEIVE ---------- - case PT_RESYNCHGET: - SV_AcknowledgeResynchAck(netconsole, netbuffer->u.resynchgot); - break; - case PT_CLIENTCMD: - case PT_CLIENT2CMD: - case PT_CLIENTMIS: - case PT_CLIENT2MIS: - case PT_NODEKEEPALIVE: - case PT_NODEKEEPALIVEMIS: - if (!server) - break; - - // ignore tics from those not synched - if (resynch_inprogress[node]) - break; - - // to save bytes, only the low byte of tic numbers are sent - // Figure out what the rest of the bytes are - realstart = ExpandTics(netbuffer->u.clientpak.client_tic); - realend = ExpandTics(netbuffer->u.clientpak.resendfrom); - - if (netbuffer->packettype == PT_CLIENTMIS || netbuffer->packettype == PT_CLIENT2MIS - || netbuffer->packettype == PT_NODEKEEPALIVEMIS - || supposedtics[node] < realend) - { - supposedtics[node] = realend; - } - // discard out of order packet - if (nettics[node] > realend) - { - DEBFILE(va("out of order ticcmd discarded nettics = %u\n", nettics[node])); - break; - } - - // update the nettics - nettics[node] = realend; - - // don't do anything for packets of type NODEKEEPALIVE? - if (netconsole == -1 || netbuffer->packettype == PT_NODEKEEPALIVE - || netbuffer->packettype == PT_NODEKEEPALIVEMIS) - break; - - // copy ticcmd - G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1); - - // check ticcmd for "speed hacks" - if (netcmds[maketic%BACKUPTICS][netconsole].forwardmove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].forwardmove < -MAXPLMOVE - || netcmds[maketic%BACKUPTICS][netconsole].sidemove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].sidemove < -MAXPLMOVE) - { - XBOXSTATIC char buf[2]; - CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value recieved from node %d\n"), netconsole); - //D_Clearticcmd(k); - - buf[0] = (char)netconsole; - buf[1] = KICK_MSG_CON_FAIL; - SendNetXCmd(XD_KICK, &buf, 2); - break; - } - - // splitscreen cmd - if (netbuffer->packettype == PT_CLIENT2CMD && nodetoplayer2[node] >= 0) - G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]], - &netbuffer->u.client2pak.cmd2, 1); - - // a delay before we check resynching - // used on join or just after a synch fail - if (resynch_delay[node]) - { - --resynch_delay[node]; - break; - } - // check player consistancy during the level - if (realstart <= gametic && realstart > gametic - BACKUPTICS+1 && gamestate == GS_LEVEL - && consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy)) - { - SV_RequireResynch(node); - - if (cv_resynchattempts.value && resynch_score[node] <= (unsigned)cv_resynchattempts.value*250) - { - if (cv_blamecfail.value) - CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"), - netconsole+1, player_names[netconsole], - consistancy[realstart%BACKUPTICS], - SHORT(netbuffer->u.clientpak.consistancy)); - DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n", - netconsole, realstart, consistancy[realstart%BACKUPTICS], - SHORT(netbuffer->u.clientpak.consistancy))); - break; - } - else - { - XBOXSTATIC UINT8 buf[3]; - - buf[0] = (UINT8)netconsole; - buf[1] = KICK_MSG_CON_FAIL; - SendNetXCmd(XD_KICK, &buf, 2); - DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n", - netconsole, realstart, consistancy[realstart%BACKUPTICS], - SHORT(netbuffer->u.clientpak.consistancy))); - break; - } - } - else if (resynch_score[node]) - --resynch_score[node]; - break; - case PT_TEXTCMD2: // splitscreen special - netconsole = nodetoplayer2[node]; - case PT_TEXTCMD: - if (!server) - break; - - if (netconsole < 0 || netconsole >= MAXPLAYERS) - Net_UnAcknowledgPacket(node); - else - { - size_t j; - tic_t tic = maketic; - UINT8 *textcmd; - - // 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 - - (netbuffer->u.textcmd[0]+2+BASESERVERTICSSIZE - + (doomcom->numslots+1)*sizeof(ticcmd_t)); - - // search a tic that have enougth space in the ticcmd - while ((textcmd = D_GetExistingTextcmd(tic, netconsole)), - (TotalTextCmdPerTic(tic) > j || netbuffer->u.textcmd[0] + (textcmd ? textcmd[0] : 0) > MAXTEXTCMD) - && tic < firstticstosend + BACKUPTICS) - tic++; - - if (tic >= firstticstosend + BACKUPTICS) - { - DEBFILE(va("GetPacket: Textcmd too long (max %s, used %s, mak %d, " - "tosend %u, node %u, player %d)\n", sizeu1(j), sizeu2(TotalTextCmdPerTic(maketic)), - maketic, firstticstosend, node, netconsole)); - Net_UnAcknowledgPacket(node); - break; - } - - // Make sure we have a buffer - if (!textcmd) textcmd = D_GetTextcmd(tic, netconsole); - - DEBFILE(va("textcmd put in tic %u at position %d (player %d) ftts %u mk %u\n", - tic, textcmd[0]+1, netconsole, firstticstosend, maketic)); - - M_Memcpy(&textcmd[textcmd[0]+1], netbuffer->u.textcmd+1, netbuffer->u.textcmd[0]); - textcmd[0] += (UINT8)netbuffer->u.textcmd[0]; - } - break; - case PT_NODETIMEOUT: - case PT_CLIENTQUIT: - if (!server) - break; - - // nodeingame will be put false in the execution of kick command - // this allow to send some packets to the quitting client to have their ack back - nodewaiting[node] = 0; - if (netconsole != -1 && playeringame[netconsole]) - { - XBOXSTATIC UINT8 buf[2]; - buf[0] = (UINT8)netconsole; - if (netbuffer->packettype == PT_NODETIMEOUT) - buf[1] = KICK_MSG_TIMEOUT; - else - buf[1] = KICK_MSG_PLAYER_QUIT; - SendNetXCmd(XD_KICK, &buf, 2); - nodetoplayer[node] = -1; - if (nodetoplayer2[node] != -1 && nodetoplayer2[node] >= 0 - && playeringame[(UINT8)nodetoplayer2[node]]) - { - buf[0] = nodetoplayer2[node]; - SendNetXCmd(XD_KICK, &buf, 2); - nodetoplayer2[node] = -1; - } - } - Net_CloseConnection(node); - nodeingame[node] = false; - break; -// -------------------------------------------- CLIENT RECEIVE ---------- - case PT_RESYNCHEND: - // Only accept PT_RESYNCHEND from the server. - if (node != servernode) - { - CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_RESYNCHEND", node); - - if (server) - { - XBOXSTATIC UINT8 buf[2]; - buf[0] = (UINT8)node; - buf[1] = KICK_MSG_CON_FAIL; - SendNetXCmd(XD_KICK, &buf, 2); - } - - break; - } - resynch_local_inprogress = false; - - P_SetRandSeed(netbuffer->u.resynchend.randomseed); - - if (gametype == GT_CTF) - resynch_read_ctf(&netbuffer->u.resynchend); - resynch_read_others(&netbuffer->u.resynchend); - - break; - case PT_SERVERTICS: - // Only accept PT_SERVERTICS from the server. - if (node != servernode) - { - CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_SERVERTICS", node); - - if (server) - { - XBOXSTATIC UINT8 buf[2]; - buf[0] = (UINT8)node; - buf[1] = KICK_MSG_CON_FAIL; - SendNetXCmd(XD_KICK, &buf, 2); - } - - break; - } - - realstart = ExpandTics(netbuffer->u.serverpak.starttic); - realend = realstart + netbuffer->u.serverpak.numtics; - - if (!txtpak) - txtpak = (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots - * netbuffer->u.serverpak.numtics]; - - if (realend > gametic + BACKUPTICS) - realend = gametic + BACKUPTICS; - cl_packetmissed = realstart > neededtic; - - if (realstart <= neededtic && realend > neededtic) - { - tic_t i, j; - pak = (UINT8 *)&netbuffer->u.serverpak.cmds; - - for (i = realstart; i < realend; i++) - { - // clear first - D_Clearticcmd(i); - - // copy the tics - pak = G_ScpyTiccmd(netcmds[i%BACKUPTICS], pak, - netbuffer->u.serverpak.numslots*sizeof (ticcmd_t)); - - // copy the textcmds - numtxtpak = *txtpak++; - for (j = 0; j < numtxtpak; j++) - { - INT32 k = *txtpak++; // playernum - const size_t txtsize = txtpak[0]+1; - - M_Memcpy(D_GetTextcmd(i, k), txtpak, txtsize); - txtpak += txtsize; - } - } - - neededtic = realend; - } - else - DEBFILE(va("frame not in bound: %u\n", neededtic)); - break; - case PT_RESYNCHING: - // Only accept PT_RESYNCHING from the server. - if (node != servernode) - { - CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_RESYNCHING", node); - - if (server) - { - XBOXSTATIC char buf[2]; - buf[0] = (char)node; - buf[1] = KICK_MSG_CON_FAIL; - SendNetXCmd(XD_KICK, &buf, 2); - } - - break; - } - resynch_local_inprogress = true; - CL_AcknowledgeResynch(&netbuffer->u.resynchpak); - break; -#ifdef NEWPING - case PT_PING: - // Only accept PT_PING from the server. - if (node != servernode) - { - CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_PING", node); - - if (server) - { - XBOXSTATIC char buf[2]; - buf[0] = (char)node; - buf[1] = KICK_MSG_CON_FAIL; - SendNetXCmd(XD_KICK, &buf, 2); - } - - break; - } - - //Update client ping table from the server. - if (!server) - { - INT32 i; - for (i = 0; i < MAXNETNODES; i++) - if (playeringame[i]) - playerpingtable[i] = (tic_t)netbuffer->u.pingtable[i]; - } - - break; -#endif - case PT_SERVERCFG: - break; - case PT_FILEFRAGMENT: - if (!server) - Got_Filetxpak(); - break; - default: - DEBFILE(va("UNKNOWN PACKET TYPE RECEIVED %d from host %d\n", - netbuffer->packettype, node)); - } // end switch - } // end while + // Packet received from someone already playing + if (nodeingame[node]) + HandlePacketFromPlayer(node); + // Packet received from someone not playing + else + HandlePacketFromAwayNode(node); + } } // @@ -3776,6 +3993,10 @@ static INT16 Consistancy(void) { INT32 i; UINT32 ret = 0; +#ifdef MOBJCONSISTANCY + thinker_t *th; + mobj_t *mo; +#endif DEBFILE(va("TIC %u ", gametic)); @@ -3797,6 +4018,77 @@ static INT16 Consistancy(void) if (!G_PlatformGametype()) ret += P_GetRandSeed(); +#ifdef MOBJCONSISTANCY + if (!thinkercap.next) + return ret; + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo = (mobj_t *)th; + + if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_MONITOR | MF_FIRE | MF_ENEMY | MF_PAIN | MF_STICKY)) + { + ret -= mo->type; + ret += mo->x; + ret -= mo->y; + ret += mo->z; + ret -= mo->momx; + ret += mo->momy; + ret -= mo->momz; + ret += mo->angle; + ret -= mo->flags; + ret += mo->flags2; + ret -= mo->eflags; + if (mo->target) + { + ret += mo->target->type; + ret -= mo->target->x; + ret += mo->target->y; + ret -= mo->target->z; + ret += mo->target->momx; + ret -= mo->target->momy; + ret += mo->target->momz; + ret -= mo->target->angle; + ret += mo->target->flags; + ret -= mo->target->flags2; + ret += mo->target->eflags; + ret -= mo->target->state - states; + ret += mo->target->tics; + ret -= mo->target->sprite; + ret += mo->target->frame; + } + else + ret ^= 0x3333; + if (mo->tracer && mo->tracer->type != MT_OVERLAY) + { + ret += mo->tracer->type; + ret -= mo->tracer->x; + ret += mo->tracer->y; + ret -= mo->tracer->z; + ret += mo->tracer->momx; + ret -= mo->tracer->momy; + ret += mo->tracer->momz; + ret -= mo->tracer->angle; + ret += mo->tracer->flags; + ret -= mo->tracer->flags2; + ret += mo->tracer->eflags; + ret -= mo->tracer->state - states; + ret += mo->tracer->tics; + ret -= mo->tracer->sprite; + ret += mo->tracer->frame; + } + else + ret ^= 0xAAAA; + ret -= mo->state - states; + ret += mo->tics; + ret -= mo->sprite; + ret += mo->frame; + } + } +#endif + return (INT16)(ret & 0xFFFF); } @@ -3814,7 +4106,7 @@ static void CL_SendClientCmd(void) if (gamestate == GS_WAITINGPLAYERS) { - // send NODEKEEPALIVE packet + // Send PT_NODEKEEPALIVE packet netbuffer->packettype += 4; packetsize = sizeof (clientcmd_pak) - sizeof (ticcmd_t) - sizeof (INT16); HSendPacket(servernode, false, 0, packetsize); @@ -3824,7 +4116,7 @@ static void CL_SendClientCmd(void) G_MoveTiccmd(&netbuffer->u.clientpak.cmd, &localcmds, 1); netbuffer->u.clientpak.consistancy = SHORT(consistancy[gametic%BACKUPTICS]); - // send a special packet with 2 cmd for splitscreen + // Send a special packet with 2 cmd for splitscreen if (splitscreen || botingame) { netbuffer->packettype += 2; @@ -3837,25 +4129,25 @@ static void CL_SendClientCmd(void) HSendPacket(servernode, false, 0, packetsize); } - if (cl_mode == cl_connected || dedicated) + if (cl_mode == CL_CONNECTED || dedicated) { - // send extra data if needed + // Send extra data if needed if (localtextcmd[0]) { netbuffer->packettype = PT_TEXTCMD; M_Memcpy(netbuffer->u.textcmd,localtextcmd, localtextcmd[0]+1); - // all extra data have been sended - if (HSendPacket(servernode, true, 0, localtextcmd[0]+1)) // send can fail... + // All extra data have been sent + if (HSendPacket(servernode, true, 0, localtextcmd[0]+1)) // Send can fail... localtextcmd[0] = 0; } - // send extra data if needed for player 2 (splitscreen) + // Send extra data if needed for player 2 (splitscreen) if (localtextcmd2[0]) { netbuffer->packettype = PT_TEXTCMD2; M_Memcpy(netbuffer->u.textcmd, localtextcmd2, localtextcmd2[0]+1); - // all extra data have been sended - if (HSendPacket(servernode, true, 0, localtextcmd2[0]+1)) // send can fail... + // All extra data have been sent + if (HSendPacket(servernode, true, 0, localtextcmd2[0]+1)) // Send can fail... localtextcmd2[0] = 0; } } @@ -4119,7 +4411,7 @@ static inline void PingUpdate(void) //check for ping limit breakage. if (cv_maxping.value) { - for (i = 1; i < MAXNETNODES; i++) + for (i = 1; i < MAXPLAYERS; i++) { if (playeringame[i] && (realpingtable[i] / pingmeasurecount > (unsigned)cv_maxping.value)) { @@ -4133,7 +4425,7 @@ static inline void PingUpdate(void) //in that case, it is probably the server's fault. if (numlaggers < D_NumPlayers() - 1) { - for (i = 1; i < MAXNETNODES; i++) + for (i = 1; i < MAXPLAYERS; i++) { if (playeringame[i] && laggers[i]) { @@ -4148,7 +4440,7 @@ static inline void PingUpdate(void) } //make the ping packet and clear server data for next one - for (i = 0; i < MAXNETNODES; i++) + for (i = 0; i < MAXPLAYERS; i++) { netbuffer->u.pingtable[i] = realpingtable[i] / pingmeasurecount; //server takes a snapshot of the real ping for display. @@ -4158,7 +4450,7 @@ static inline void PingUpdate(void) } //send out our ping packets - for (i = 0; i < MAXNETNODES; i++) + for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) HSendPacket(i, true, 0, sizeof(INT32) * MAXPLAYERS); @@ -4207,7 +4499,7 @@ void NetUpdate(void) } #endif - if (!server) + if (client) maketic = neededtic; Local_Maketic(realtics); // make local tic, and call menu? @@ -4220,12 +4512,12 @@ FILESTAMP // client send the command after a receive of the server // the server send before because in single player is beter - MasterClient_Ticker(); // acking the master server + MasterClient_Ticker(); // Acking the Master Server - if (!server) + if (client) { if (!resynch_local_inprogress) - CL_SendClientCmd(); // send tic cmd + CL_SendClientCmd(); // Send tic cmd hu_resynching = resynch_local_inprogress; } else @@ -4251,27 +4543,32 @@ FILESTAMP counts = -666; } - // do not make tics while resynching + // Do not make tics while resynching if (counts != -666) { if (maketic + counts >= firstticstosend + BACKUPTICS) counts = firstticstosend+BACKUPTICS-maketic-1; for (i = 0; i < counts; i++) - SV_Maketic(); // create missed tics and increment maketic + SV_Maketic(); // Create missed tics and increment maketic - for (; tictoclear < firstticstosend; tictoclear++) // clear only when acknoledged - D_Clearticcmd(tictoclear); // clear the maketic the new tic + for (; tictoclear < firstticstosend; tictoclear++) // Clear only when acknowledged + D_Clearticcmd(tictoclear); // Clear the maketic the new tic SV_SendTics(); - neededtic = maketic; // the server is a client too + neededtic = maketic; // The server is a client too } else hu_resynching = true; } } Net_AckTicker(); + // Handle timeouts to prevent definitive freezes from happenning + if (server) + for (i = 1; i < MAXNETNODES; i++) + if (nodeingame[i] && freezetimeout[i] < I_GetTime()) + Net_ConnectionTimeout(i); nowtime /= NEWTICRATERATIO; if (nowtime > resptime) { @@ -4279,7 +4576,7 @@ FILESTAMP M_Ticker(); CON_Ticker(); } - FiletxTicker(); + SV_FileSendTicker(); } /** Returns the number of players playing. diff --git a/src/d_clisrv.h b/src/d_clisrv.h index f86c09b45..382329539 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -59,7 +59,7 @@ typedef enum // Add non-PT_CANFAIL packet types here to avoid breaking MS compatibility. PT_CANFAIL, // This is kind of a priority. Anything bigger than CANFAIL - // allows HSendPacket(,true,,) to return false. + // allows HSendPacket(*, true, *, *) to return false. // In addition, this packet can't occupy all the available slots. PT_FILEFRAGMENT = PT_CANFAIL, // A part of a file. @@ -76,11 +76,19 @@ typedef enum NUMPACKETTYPE } packettype_t; +#ifdef PACKETDROP +void Command_Drop(void); +void Command_Droprate(void); +#endif +#ifdef _DEBUG +void Command_Numnodes(void); +#endif + #if defined(_MSC_VER) #pragma pack(1) #endif -// client to server packet +// Client to server packet typedef struct { UINT8 client_tic; @@ -89,7 +97,7 @@ typedef struct ticcmd_t cmd; } ATTRPACK clientcmd_pak; -// splitscreen packet +// Splitscreen packet // WARNING: must have the same format of clientcmd_pak, for more easy use typedef struct { @@ -110,16 +118,16 @@ typedef struct UINT8 starttic; UINT8 numtics; UINT8 numslots; // "Slots filled": Highest player number in use plus one. - ticcmd_t cmds[45]; // normally [BACKUPTIC][MAXPLAYERS] but too large + ticcmd_t cmds[45]; // Normally [BACKUPTIC][MAXPLAYERS] but too large } ATTRPACK servertics_pak; -// sent to client when all consistency data +// Sent to client when all consistency data // for players has been restored typedef struct { UINT32 randomseed; - //ctf flag stuff + // CTF flag stuff SINT8 flagplayer[2]; INT32 flagloose[2]; INT32 flagflags[2]; @@ -127,11 +135,11 @@ typedef struct fixed_t flagy[2]; fixed_t flagz[2]; - UINT32 ingame; // spectator bit for each player - UINT32 ctfteam; // if not spectator, then which team? + UINT32 ingame; // Spectator 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 - UINT32 score[MAXPLAYERS]; // Everyone's score. + UINT32 score[MAXPLAYERS]; // Everyone's score INT16 numboxes[MAXPLAYERS]; INT16 totalring[MAXPLAYERS]; tic_t realtime[MAXPLAYERS]; @@ -140,14 +148,14 @@ typedef struct typedef struct { - //player stuff + // Player stuff UINT8 playernum; // Do not send anything visual related. // Only send data that we need to know for physics. - UINT8 playerstate; //playerstate_t - UINT32 pflags; //pflags_t - UINT8 panim; //panim_t + UINT8 playerstate; // playerstate_t + UINT32 pflags; // pflags_t + UINT8 panim; // panim_t angle_t aiming; INT32 currentweapon; @@ -155,7 +163,7 @@ typedef struct UINT16 powers[NUMPOWERS]; // Score is resynched in the confirm resync packet - INT32 health; + INT32 rings; SINT8 lives; SINT8 continues; UINT8 scoreadd; @@ -176,9 +184,9 @@ typedef struct UINT8 charability; UINT8 charability2; UINT32 charflags; - UINT32 thokitem; //mobjtype_t - UINT32 spinitem; //mobjtype_t - UINT32 revitem; //mobjtype_t + UINT32 thokitem; // mobjtype_t + UINT32 spinitem; // mobjtype_t + UINT32 revitem; // mobjtype_t fixed_t actionspd; fixed_t mindash; fixed_t maxdash; @@ -234,8 +242,9 @@ typedef struct INT32 onconveyor; //player->mo stuff - UINT8 hasmo; //boolean + UINT8 hasmo; // Boolean + INT32 health; angle_t angle; fixed_t x; fixed_t y; @@ -261,10 +270,10 @@ typedef struct typedef struct { - UINT8 version; // different versions don't work - UINT8 subversion; // contains build version + UINT8 version; // Different versions don't work + UINT8 subversion; // Contains build version - // server launch stuffs + // Server launch stuffs UINT8 serverplayer; UINT8 totalslotnum; // "Slots": highest player number in use plus one. @@ -278,18 +287,18 @@ typedef struct UINT8 gametype; UINT8 modifiedgame; - SINT8 adminplayer; // needs to be signed + SINT8 adminplayer; // Needs to be signed - char server_context[8]; // unique context id, generated at server startup. + char server_context[8]; // Unique context id, generated at server startup. - UINT8 varlengthinputs[0]; // playernames and netvars + UINT8 varlengthinputs[0]; // Playernames and netvars } ATTRPACK serverconfig_pak; typedef struct { UINT8 fileid; UINT32 position; UINT16 size; - UINT8 data[0]; // size is variable using hardware_MAXPACKETLENGTH + UINT8 data[0]; // Size is variable using hardware_MAXPACKETLENGTH } ATTRPACK filetx_pak; #ifdef _MSC_VER @@ -298,14 +307,14 @@ typedef struct { typedef struct { - UINT8 version; // different versions don't work - UINT8 subversion; // contains build version + UINT8 version; // Different versions don't work + UINT8 subversion; // Contains build version UINT8 localplayers; UINT8 mode; } ATTRPACK clientconfig_pak; #define MAXSERVERNAME 32 -// this packet is too large +// This packet is too large typedef struct { UINT8 version; @@ -371,45 +380,45 @@ typedef struct } ATTRPACK plrconfig; // -// Network packet data. +// Network packet data // typedef struct { UINT32 checksum; - UINT8 ack; // if not null the node asks for acknowledgement, the receiver must resend the ack - UINT8 ackreturn; // the return of the ack number + UINT8 ack; // If not zero the node asks for acknowledgement, the receiver must resend the ack + UINT8 ackreturn; // The return of the ack number UINT8 packettype; - UINT8 reserved; // padding + UINT8 reserved; // Padding union { - clientcmd_pak clientpak; // 144 bytes - client2cmd_pak client2pak; // 200 bytes - servertics_pak serverpak; // 132495 bytes - serverconfig_pak servercfg; // 773 bytes - resynchend_pak resynchend; // - resynch_pak resynchpak; // - UINT8 resynchgot; // - UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes - filetx_pak filetxpak; // 139 bytes - clientconfig_pak clientcfg; // 136 bytes - serverinfo_pak serverinfo; // 1024 bytes - serverrefuse_pak serverrefuse; // 65025 bytes - askinfo_pak askinfo; // 61 bytes - msaskinfo_pak msaskinfo; // 22 bytes - plrinfo playerinfo[MAXPLAYERS]; // 1152 bytes - plrconfig playerconfig[MAXPLAYERS]; // (up to) 896 bytes + clientcmd_pak clientpak; // 144 bytes + client2cmd_pak client2pak; // 200 bytes + servertics_pak serverpak; // 132495 bytes (more around 360, no?) + serverconfig_pak servercfg; // 773 bytes + resynchend_pak resynchend; // + resynch_pak resynchpak; // + UINT8 resynchgot; // + UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...) + filetx_pak filetxpak; // 139 bytes + clientconfig_pak clientcfg; // 136 bytes + serverinfo_pak serverinfo; // 1024 bytes + serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...) + askinfo_pak askinfo; // 61 bytes + msaskinfo_pak msaskinfo; // 22 bytes + plrinfo playerinfo[MAXPLAYERS]; // 1152 bytes (I'd say 36~38) + plrconfig playerconfig[MAXPLAYERS]; // (up to) 896 bytes (welp they ARE) #ifdef NEWPING - UINT32 pingtable[MAXPLAYERS]; // 128 bytes + UINT32 pingtable[MAXPLAYERS]; // 128 bytes #endif - } u; // this is needed to pack diff packet types data together + } u; // This is needed to pack diff packet types data together } ATTRPACK doomdata_t; #if defined(_MSC_VER) #pragma pack() #endif -#define MAXSERVERLIST 64 // depends only on the display +#define MAXSERVERLIST 64 // Depends only on the display typedef struct { SINT8 node; @@ -420,7 +429,7 @@ extern serverelem_t serverlist[MAXSERVERLIST]; extern UINT32 serverlistcount; extern INT32 mapchangepending; -// points inside doomcom +// Points inside doomcom extern doomdata_t *netbuffer; extern consvar_t cv_playbackspeed; @@ -441,26 +450,28 @@ extern consvar_t cv_playbackspeed; #define KICK_MSG_CUSTOM_BAN 8 extern boolean server; -extern boolean dedicated; // for dedicated server +#define client (!server) +extern boolean dedicated; // For dedicated server extern UINT16 software_MAXPACKETLENGTH; extern boolean acceptnewnode; extern SINT8 servernode; void Command_Ping_f(void); extern tic_t connectiontimeout; +extern tic_t jointimeout; #ifdef NEWPING extern UINT16 pingmeasurecount; extern UINT32 realpingtable[MAXPLAYERS]; extern UINT32 playerpingtable[MAXPLAYERS]; #endif -extern consvar_t cv_joinnextround, cv_allownewplayer, cv_maxplayers, cv_resynchattempts, cv_blamecfail, cv_maxsend; +extern consvar_t cv_joinnextround, cv_allownewplayer, cv_maxplayers, cv_resynchattempts, cv_blamecfail, cv_maxsend, cv_noticedownload, cv_downloadspeed; -// used in d_net, the only dependence +// Used in d_net, the only dependence tic_t ExpandTics(INT32 low); void D_ClientServerInit(void); -// initialise the other field +// Initialise the other field void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum)); void SendNetXCmd(netxcmd_t id, const void *param, size_t nparam); void SendNetXCmd2(netxcmd_t id, const void *param, size_t nparam); // splitsreen player @@ -478,14 +489,14 @@ void CL_RemoveSplitscreenPlayer(void); void CL_Reset(void); void CL_ClearPlayer(INT32 playernum); void CL_UpdateServerList(boolean internetsearch, INT32 room); -// is there a game running +// Is there a game running boolean Playing(void); // Broadcasts special packets to other players // to notify of game exit void D_QuitNetGame(void); -//? how many ticks to run? +//? How many ticks to run? void TryRunTics(tic_t realtic); // extra data for lmps diff --git a/src/d_main.c b/src/d_main.c index d9df1f544..63f6bd02c 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -73,6 +73,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...); #include "dehacked.h" // Dehacked list test #include "m_cond.h" // condition initialization #include "fastcmp.h" +#include "keys.h" #ifdef CMAKECONFIG #include "config.h" @@ -176,6 +177,38 @@ void D_PostEvent(const event_t *ev) void D_PostEvent_end(void) {}; #endif +// modifier keys +UINT8 shiftdown = 0; // 0x1 left, 0x2 right +UINT8 ctrldown = 0; // 0x1 left, 0x2 right +UINT8 altdown = 0; // 0x1 left, 0x2 right +// +// D_ModifierKeyResponder +// Sets global shift/ctrl/alt variables, never actually eats events +// +static inline void D_ModifierKeyResponder(event_t *ev) +{ + if (ev->type == ev_keydown) switch (ev->data1) + { + case KEY_LSHIFT: shiftdown |= 0x1; return; + case KEY_RSHIFT: shiftdown |= 0x2; return; + case KEY_LCTRL: ctrldown |= 0x1; return; + case KEY_RCTRL: ctrldown |= 0x2; return; + case KEY_LALT: altdown |= 0x1; return; + case KEY_RALT: altdown |= 0x2; return; + default: return; + } + else if (ev->type == ev_keyup) switch (ev->data1) + { + case KEY_LSHIFT: shiftdown &= ~0x1; return; + case KEY_RSHIFT: shiftdown &= ~0x2; return; + case KEY_LCTRL: ctrldown &= ~0x1; return; + case KEY_RCTRL: ctrldown &= ~0x2; return; + case KEY_LALT: altdown &= ~0x1; return; + case KEY_RALT: altdown &= ~0x2; return; + default: return; + } +} + // // D_ProcessEvents // Send all the events of the given timestamp down the responder chain @@ -188,6 +221,9 @@ void D_ProcessEvents(void) { ev = &events[eventtail]; + // Set global shift/ctrl/alt down variables + D_ModifierKeyResponder(ev); // never eats events + // Screenshots over everything so that they can be taken anywhere. if (M_ScreenshotResponder(ev)) continue; // ate the event diff --git a/src/d_net.c b/src/d_net.c index 03e126b50..fae1ea311 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -31,18 +31,18 @@ // // NETWORKING // -// gametic is the tic about to be (or currently being) run -// server: +// gametic is the tic about to (or currently being) run +// Server: // maketic is the tic that hasn't had control made for it yet -// nettics: is the tic for each node -// firsttictosend: is the lowest value of nettics -// client: -// neededtic: is the tic needed by the client to run the game -// firsttictosend: is used to optimize a condition -// normally maketic >= gametic > 0 +// nettics is the tic for each node +// firstticstosend is the lowest value of nettics +// Client: +// neededtic is the tic needed by the client to run the game +// firstticstosend is used to optimize a condition +// Normally maketic >= gametic > 0 #define FORCECLOSE 0x8000 -tic_t connectiontimeout = (15*TICRATE); +tic_t connectiontimeout = (10*TICRATE); /// \brief network packet doomcom_t *doomcom = NULL; @@ -62,7 +62,7 @@ INT32 net_bandwidth; /// \brief max length per packet INT16 hardware_MAXPACKETLENGTH; -void (*I_NetGet)(void) = NULL; +boolean (*I_NetGet)(void) = NULL; void (*I_NetSend)(void) = NULL; boolean (*I_NetCanSend)(void) = NULL; boolean (*I_NetCanGet)(void) = NULL; @@ -129,9 +129,9 @@ boolean Net_GetNetStat(void) // ----------------------------------------------------------------- // Some structs and functions for acknowledgement of packets // ----------------------------------------------------------------- -#define MAXACKPACKETS 96 // minimum number of nodes +#define MAXACKPACKETS 96 // Minimum number of nodes (wat) #define MAXACKTOSEND 96 -#define URGENTFREESLOTENUM 10 +#define URGENTFREESLOTNUM 10 #define ACKTOSENDTIMEOUT (TICRATE/11) #ifndef NONET @@ -139,10 +139,10 @@ typedef struct { UINT8 acknum; UINT8 nextacknum; - UINT8 destinationnode; - tic_t senttime; - UINT16 length; - UINT16 resentnum; + UINT8 destinationnode; // The node to send the ack to + tic_t senttime; // The time when the ack was sent + UINT16 length; // The packet size + UINT16 resentnum; // The number of times the ack has been resent union { SINT8 raw[MAXPACKETLENGTH]; doomdata_t data; @@ -152,11 +152,12 @@ typedef struct typedef enum { - CLOSE = 1, // flag is set when connection is closing + NF_CLOSE = 1, // Flag is set when connection is closing + NF_TIMEOUT = 2, // Flag is set when the node got a timeout } node_flags_t; #ifndef NONET -// table of packet that was not acknowleged can be resend (the sender window) +// Table of packets that were not acknowleged can be resent (the sender window) static ackpak_t ackpak[MAXACKPACKETS]; #endif @@ -212,11 +213,16 @@ FUNCMATH static INT32 cmpack(UINT8 a, UINT8 b) return d; } -// return a free acknum and copy netbuffer in the ackpak table +/** Sets freeack to a free acknum and copies the netbuffer in the ackpak table + * + * \param freeack The address to store the free acknum at + * \param lowtimer ??? + * \return True if a free acknum was found + */ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer) { node_t *node = &nodes[doomcom->remotenode]; - INT32 i, numfreeslote = 0; + INT32 i, numfreeslot = 0; if (cmpack((UINT8)((node->remotefirstack + MAXACKTOSEND) % 256), node->nextacknum) < 0) { @@ -227,10 +233,13 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer) for (i = 0; i < MAXACKPACKETS; i++) if (!ackpak[i].acknum) { - // for low priority packet, make sure let freeslotes so urgents packets can be sent - numfreeslote++; - if (netbuffer->packettype >= PT_CANFAIL && numfreeslote < URGENTFREESLOTENUM) - continue; + // For low priority packets, make sure to let freeslots so urgent packets can be sent + if (netbuffer->packettype >= PT_CANFAIL) + { + numfreeslot++; + if (numfreeslot <= URGENTFREESLOTNUM) + continue; + } ackpak[i].acknum = node->nextacknum; ackpak[i].nextacknum = node->nextacknum; @@ -241,7 +250,7 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer) ackpak[i].length = doomcom->datalength; if (lowtimer) { - // lowtime mean can't be sent now so try it soon as possible + // Lowtime means can't be sent now so try it as soon as possible ackpak[i].senttime = 0; ackpak[i].resentnum = 1; } @@ -254,7 +263,7 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer) *freeack = ackpak[i].acknum; - sendackpacket++; // for stat + sendackpacket++; // For stat return true; } @@ -266,14 +275,46 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer) return false; } -// Get a ack to send in the queu of this node +/** Counts how many acks are free + * + * \param urgent True if the type of the packet meant to + * use an ack is lower than PT_CANFAIL + * If for some reason you don't want use it + * for any packet type in particular, + * just set to false + * \return The number of free acks + * + */ +INT32 Net_GetFreeAcks(boolean urgent) +{ + INT32 i, numfreeslot = 0; + INT32 n = 0; // Number of free acks found + + for (i = 0; i < MAXACKPACKETS; i++) + if (!ackpak[i].acknum) + { + // For low priority packets, make sure to let freeslots so urgent packets can be sent + if (!urgent) + { + numfreeslot++; + if (numfreeslot <= URGENTFREESLOTNUM) + continue; + } + + n++; + } + + return n; +} + +// Get a ack to send in the queue of this node static UINT8 GetAcktosend(INT32 node) { nodes[node].lasttimeacktosend_sent = I_GetTime(); return nodes[node].firstacktosend; } -static void Removeack(INT32 i) +static void RemoveAck(INT32 i) { INT32 node = ackpak[i].destinationnode; #ifndef NEWPING @@ -290,31 +331,31 @@ static void Removeack(INT32 i) DEBFILE(va("Remove ack %d\n",ackpak[i].acknum)); #endif ackpak[i].acknum = 0; - if (nodes[node].flags & CLOSE) + if (nodes[node].flags & NF_CLOSE) Net_CloseConnection(node); } -// we have got a packet proceed the ack request and ack return +// We have got a packet, proceed the ack request and ack return static boolean Processackpak(void) { INT32 i; boolean goodpacket = true; node_t *node = &nodes[doomcom->remotenode]; - // received an ack return, so remove the ack in the list + // Received an ack return, so remove the ack in the list if (netbuffer->ackreturn && cmpack(node->remotefirstack, netbuffer->ackreturn) < 0) { node->remotefirstack = netbuffer->ackreturn; - // search the ackbuffer and free it + // Search the ackbuffer and free it for (i = 0; i < MAXACKPACKETS; i++) if (ackpak[i].acknum && ackpak[i].destinationnode == node - nodes && cmpack(ackpak[i].acknum, netbuffer->ackreturn) <= 0) { - Removeack(i); + RemoveAck(i); } } - // received a packet with ack, queue it to send the ack back + // Received a packet with ack, queue it to send the ack back if (netbuffer->ack) { UINT8 ack = netbuffer->ack; @@ -323,23 +364,23 @@ static boolean Processackpak(void) { DEBFILE(va("Discard(1) ack %d (duplicated)\n", ack)); duppacket++; - goodpacket = false; // discard packet (duplicate) + goodpacket = false; // Discard packet (duplicate) } else { - // check if it is not already in the queue + // Check if it is not already in the queue for (i = node->acktosend_tail; i != node->acktosend_head; i = (i+1) % MAXACKTOSEND) if (node->acktosend[i] == ack) { DEBFILE(va("Discard(2) ack %d (duplicated)\n", ack)); duppacket++; - goodpacket = false; // discard packet (duplicate) + goodpacket = false; // Discard packet (duplicate) break; } if (goodpacket) { - // is a good packet so increment the acknowledge number, - // then search for a "hole" in the queue + // Is a good packet so increment the acknowledge number, + // Then search for a "hole" in the queue UINT8 nextfirstack = (UINT8)(node->firstacktosend + 1); if (!nextfirstack) nextfirstack = 1; @@ -383,10 +424,10 @@ static boolean Processackpak(void) } } } - else // out of order packet + else // Out of order packet { - // don't increment firsacktosend, put it in asktosend queue - // will be incremented when the nextfirstack comes (code above) + // Don't increment firsacktosend, put it in asktosend queue + // Will be incremented when the nextfirstack comes (code above) UINT8 newhead = (UINT8)((node->acktosend_head+1) % MAXACKTOSEND); DEBFILE(va("out of order packet (%d expected)\n", nextfirstack)); if (newhead != node->acktosend_tail) @@ -394,8 +435,8 @@ static boolean Processackpak(void) node->acktosend[node->acktosend_head] = ack; node->acktosend_head = newhead; } - else // buffer full discard packet, sender will resend it - { // we can admit the packet but we will not detect the duplication after :( + else // Buffer full discard packet, sender will resend it + { // We can admit the packet but we will not detect the duplication after :( DEBFILE("no more freeackret\n"); goodpacket = false; } @@ -430,25 +471,29 @@ static void GotAcks(void) if (ackpak[i].acknum && ackpak[i].destinationnode == doomcom->remotenode) { if (ackpak[i].acknum == netbuffer->u.textcmd[j]) - Removeack(i); - else - // nextacknum is first equal to acknum, then when receiving bigger ack - // there is big chance the packet is lost - // when resent, nextacknum = nodes[node].nextacknum - // will redo the same but with different value - if (cmpack(ackpak[i].nextacknum, netbuffer->u.textcmd[j]) <= 0 - && ackpak[i].senttime > 0) - { - ackpak[i].senttime--; // hurry up - } + RemoveAck(i); + // nextacknum is first equal to acknum, then when receiving bigger ack + // there is big chance the packet is lost + // When resent, nextacknum = nodes[node].nextacknum + // will redo the same but with different value + else if (cmpack(ackpak[i].nextacknum, netbuffer->u.textcmd[j]) <= 0 + && ackpak[i].senttime > 0) + { + ackpak[i].senttime--; // hurry up + } } } #endif -static inline void Net_ConnectionTimeout(INT32 node) +void Net_ConnectionTimeout(INT32 node) { - // send a very special packet to self (hack the reboundstore queue) - // main code will handle it + // Don't timeout several times + if (nodes[node].flags & NF_TIMEOUT) + return; + nodes[node].flags |= NF_TIMEOUT; + + // Send a very special packet to self (hack the reboundstore queue) + // Main code will handle it reboundstore[rebound_head].packettype = PT_NODETIMEOUT; reboundstore[rebound_head].ack = 0; reboundstore[rebound_head].ackreturn = 0; @@ -456,12 +501,12 @@ static inline void Net_ConnectionTimeout(INT32 node) reboundsize[rebound_head] = (INT16)(BASEPACKETSIZE + 1); rebound_head = (rebound_head+1) % MAXREBOUND; - // do not redo it quickly (if we do not close connection it is + // Do not redo it quickly (if we do not close connection it is // for a good reason!) nodes[node].lasttimepacketreceived = I_GetTime(); } -// resend the data if needed +// Resend the data if needed void Net_AckTicker(void) { #ifndef NONET @@ -477,7 +522,7 @@ void Net_AckTicker(void) if (ackpak[i].acknum && ackpak[i].senttime + node->timeout < I_GetTime()) #endif { - if (ackpak[i].resentnum > 10 && (node->flags & CLOSE)) + if (ackpak[i].resentnum > 10 && (node->flags & NF_CLOSE)) { DEBFILE(va("ack %d sent 10 times so connection is supposed lost: node %d\n", i, nodei)); @@ -497,7 +542,7 @@ void Net_AckTicker(void) ackpak[i].senttime = I_GetTime(); ackpak[i].resentnum++; ackpak[i].nextacknum = node->nextacknum; - retransmit++; // for stat + retransmit++; // For stat HSendPacket((INT32)(node - nodes), false, ackpak[i].acknum, (size_t)(ackpak[i].length - BASEPACKETSIZE)); } @@ -505,15 +550,15 @@ void Net_AckTicker(void) for (i = 1; i < MAXNETNODES; i++) { - // this is something like node open flag + // This is something like node open flag if (nodes[i].firstacktosend) { - // we haven't sent a packet for a long time - // acknowledge packet if needed + // We haven't sent a packet for a long time + // Acknowledge packet if needed if (nodes[i].lasttimeacktosend_sent + ACKTOSENDTIMEOUT < I_GetTime()) Net_SendAcks(i); - if (!(nodes[i].flags & CLOSE) + if (!(nodes[i].flags & NF_CLOSE) && nodes[i].lasttimepacketreceived + connectiontimeout < I_GetTime()) { Net_ConnectionTimeout(i); @@ -523,9 +568,9 @@ void Net_AckTicker(void) #endif } -// remove last packet received ack before resending the ackret +// Remove last packet received ack before resending the ackreturn // (the higher layer doesn't have room, or something else ....) -void Net_UnAcknowledgPacket(INT32 node) +void Net_UnAcknowledgePacket(INT32 node) { #ifdef NONET (void)node; @@ -564,20 +609,29 @@ void Net_UnAcknowledgPacket(INT32 node) #endif } -boolean Net_AllAckReceived(void) -{ #ifndef NONET +/** Checks if all acks have been received + * + * \return True if all acks have been received + * + */ +static boolean Net_AllAcksReceived(void) +{ INT32 i; for (i = 0; i < MAXACKPACKETS; i++) if (ackpak[i].acknum) return false; -#endif return true; } +#endif -// wait for all ackreturns with timeout in seconds +/** Waits for all ackreturns + * + * \param timeout Timeout in seconds + * + */ void Net_WaitAllAckReceived(UINT32 timeout) { #ifdef NONET @@ -587,7 +641,7 @@ void Net_WaitAllAckReceived(UINT32 timeout) timeout = tictac + timeout*NEWTICRATE; HGetPacket(); - while (timeout > I_GetTime() && !Net_AllAckReceived()) + while (timeout > I_GetTime() && !Net_AllAcksReceived()) { while (tictac == I_GetTime()) I_Sleep(); @@ -598,18 +652,18 @@ void Net_WaitAllAckReceived(UINT32 timeout) #endif } -static void InitNode(INT32 node) +static void InitNode(node_t *node) { - nodes[node].acktosend_head = nodes[node].acktosend_tail = 0; + node->acktosend_head = node->acktosend_tail = 0; #ifndef NEWPING - nodes[node].ping = PINGDEFAULT; - nodes[node].varping = VARPINGDEFAULT; - nodes[node].timeout = TIMEOUT(nodes[node].ping,nodes[node].varping); + node->ping = PINGDEFAULT; + node->varping = VARPINGDEFAULT; + node->timeout = TIMEOUT(node->ping, node->varping); #endif - nodes[node].firstacktosend = 0; - nodes[node].nextacknum = 1; - nodes[node].remotefirstack = 0; - nodes[node].flags = 0; + node->firstacktosend = 0; + node->nextacknum = 1; + node->remotefirstack = 0; + node->flags = 0; } static void InitAck(void) @@ -622,9 +676,14 @@ static void InitAck(void) #endif for (i = 0; i < MAXNETNODES; i++) - InitNode(i); + InitNode(&nodes[i]); } +/** Removes all acks of a given packet type + * + * \param packettype The packet type to forget + * + */ void Net_AbortPacketType(UINT8 packettype) { #ifdef NONET @@ -657,7 +716,7 @@ void Net_CloseConnection(INT32 node) if (!node) return; - nodes[node].flags |= CLOSE; + nodes[node].flags |= NF_CLOSE; // try to Send ack back (two army problem) if (GetAcktosend(node)) @@ -676,8 +735,8 @@ void Net_CloseConnection(INT32 node) ackpak[i].acknum = 0; } - InitNode(node); - AbortSendFiles(node); + InitNode(&nodes[node]); + SV_AbortSendFiles(node); I_NetFreeNodenum(node); #endif } @@ -729,9 +788,15 @@ static void fprintfstring(char *s, size_t len) } if (mode) fprintf(debugfile, "]"); +} + +static void fprintfstringnewline(char *s, size_t len) +{ + fprintfstring(s, len); fprintf(debugfile, "\n"); } +/// \warning Keep this up-to-date if you add/remove/rename packet types static const char *packettypename[NUMPACKETTYPE] = { "NOTHING", @@ -749,15 +814,22 @@ static const char *packettypename[NUMPACKETTYPE] = "ASKINFO", "SERVERINFO", + "PLAYERINFO", "REQUESTFILE", "ASKINFOVIAMS", - "PLAYERCONFIGS", + "RESYNCHEND", + "RESYNCHGET", + "FILEFRAGMENT", "TEXTCMD", "TEXTCMD2", "CLIENTJOIN", "NODETIMEOUT", + "RESYNCHING", +#ifdef NEWPING + "PING" +#endif }; static void DebugPrintpacket(const char *header) @@ -770,20 +842,31 @@ static void DebugPrintpacket(const char *header) { case PT_ASKINFO: case PT_ASKINFOVIAMS: - fprintf(debugfile, " time %u\n", (tic_t)LONG(netbuffer->u.askinfo.time) ); + fprintf(debugfile, " time %u\n", (tic_t)LONG(netbuffer->u.askinfo.time)); break; case PT_CLIENTJOIN: fprintf(debugfile, " number %d mode %d\n", netbuffer->u.clientcfg.localplayers, netbuffer->u.clientcfg.mode); break; case PT_SERVERTICS: + { + servertics_pak *serverpak = &netbuffer->u.serverpak; + UINT8 *cmd = (UINT8 *)(&serverpak->cmds[serverpak->numslots * serverpak->numtics]); + size_t ntxtcmd = &((UINT8 *)netbuffer)[doomcom->datalength] - cmd; + fprintf(debugfile, " firsttic %u ply %d tics %d ntxtcmd %s\n ", - (UINT32)ExpandTics(netbuffer->u.serverpak.starttic), netbuffer->u.serverpak.numslots, - netbuffer->u.serverpak.numtics, - sizeu1((size_t)(&((UINT8 *)netbuffer)[doomcom->datalength] - (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots*netbuffer->u.serverpak.numtics]))); - fprintfstring((char *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots*netbuffer->u.serverpak.numtics],(size_t)( - &((UINT8 *)netbuffer)[doomcom->datalength] - (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots*netbuffer->u.serverpak.numtics])); + (UINT32)ExpandTics(serverpak->starttic), serverpak->numslots, serverpak->numtics, sizeu1(ntxtcmd)); + /// \todo Display more readable information about net commands + fprintfstringnewline((char *)cmd, ntxtcmd); + /*fprintfstring((char *)cmd, 3); + if (ntxtcmd > 4) + { + fprintf(debugfile, "[%s]", netxcmdnames[*((cmd) + 3) - 1]); + fprintfstring(((char *)cmd) + 4, ntxtcmd - 4); + } + fprintf(debugfile, "\n");*/ break; + } case PT_CLIENTCMD: case PT_CLIENT2CMD: case PT_CLIENTMIS: @@ -797,7 +880,8 @@ static void DebugPrintpacket(const char *header) case PT_TEXTCMD: case PT_TEXTCMD2: fprintf(debugfile, " length %d\n ", netbuffer->u.textcmd[0]); - fprintfstring((char *)netbuffer->u.textcmd+1, netbuffer->u.textcmd[0]); + fprintf(debugfile, "[%s]", netxcmdnames[netbuffer->u.textcmd[1] - 1]); + fprintfstringnewline((char *)netbuffer->u.textcmd + 2, netbuffer->u.textcmd[0] - 1); break; case PT_SERVERCFG: fprintf(debugfile, " playerslots %d clientnode %d serverplayer %d " @@ -813,7 +897,7 @@ static void DebugPrintpacket(const char *header) netbuffer->u.serverinfo.maxplayer, netbuffer->u.serverinfo.mapname, netbuffer->u.serverinfo.fileneedednum, (UINT32)LONG(netbuffer->u.serverinfo.time)); - fprintfstring((char *)netbuffer->u.serverinfo.fileneeded, + fprintfstringnewline((char *)netbuffer->u.serverinfo.fileneeded, (UINT8)((UINT8 *)netbuffer + doomcom->datalength - (UINT8 *)netbuffer->u.serverinfo.fileneeded)); break; @@ -827,20 +911,100 @@ static void DebugPrintpacket(const char *header) break; case PT_REQUESTFILE: default: // write as a raw packet - fprintfstring((char *)netbuffer->u.textcmd, + fprintfstringnewline((char *)netbuffer->u.textcmd, (UINT8)((UINT8 *)netbuffer + doomcom->datalength - (UINT8 *)netbuffer->u.textcmd)); break; } } #endif +#ifdef PACKETDROP +static INT32 packetdropquantity[NUMPACKETTYPE] = {0}; +static INT32 packetdroprate = 0; + +void Command_Drop(void) +{ + INT32 packetquantity; + const char *packetname; + size_t i; + + if (COM_Argc() < 2) + { + CONS_Printf("drop <packettype> [quantity]: drop packets\n" + "drop reset: cancel all packet drops\n"); + return; + } + + if (!(stricmp(COM_Argv(1), "reset") && stricmp(COM_Argv(1), "cancel") && stricmp(COM_Argv(1), "stop"))) + { + memset(packetdropquantity, 0, sizeof(packetdropquantity)); + return; + } + + if (COM_Argc() >= 3) + { + packetquantity = atoi(COM_Argv(2)); + if (packetquantity <= 0 && COM_Argv(2)[0] != '0') + { + CONS_Printf("Invalid quantity\n"); + return; + } + } + else + packetquantity = -1; + + packetname = COM_Argv(1); + + if (!(stricmp(packetname, "all") && stricmp(packetname, "any"))) + for (i = 0; i < NUMPACKETTYPE; i++) + packetdropquantity[i] = packetquantity; + else + { + for (i = 0; i < NUMPACKETTYPE; i++) + if (!stricmp(packetname, packettypename[i])) + { + packetdropquantity[i] = packetquantity; + return; + } + + CONS_Printf("Unknown packet name\n"); + } +} + +void Command_Droprate(void) +{ + INT32 droprate; + + if (COM_Argc() < 2) + { + CONS_Printf("Packet drop rate: %d%%\n", packetdroprate); + return; + } + + droprate = atoi(COM_Argv(1)); + if ((droprate <= 0 && COM_Argv(1)[0] != '0') || droprate > 100) + { + CONS_Printf("Packet drop rate must be between 0 and 100!\n"); + return; + } + + packetdroprate = droprate; +} + +static boolean ShouldDropPacket(void) +{ + return (packetdropquantity[netbuffer->packettype]) + || (packetdroprate != 0 && rand() < (RAND_MAX * (packetdroprate / 100.f))) || packetdroprate == 100; +} +#endif + // // HSendPacket // boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlength) { doomcom->datalength = (INT16)(packetlength + BASEPACKETSIZE); - if (node == 0) // packet is to go back to us + if (node == 0) // Packet is to go back to us { if ((rebound_head+1) % MAXREBOUND == rebound_tail) { @@ -871,7 +1035,7 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen (void)reliable; (void)acknum; #else - // do this before GetFreeAcknum because this function backup + // do this before GetFreeAcknum because this function backups // the current packet doomcom->remotenode = (INT16)node; if (doomcom->datalength <= 0) @@ -884,7 +1048,7 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen return false; } - if (node < MAXNETNODES) // can be a broadcast + if (node < MAXNETNODES) // Can be a broadcast netbuffer->ackreturn = GetAcktosend(node); else netbuffer->ackreturn = 0; @@ -905,20 +1069,30 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen netbuffer->ack = acknum; netbuffer->checksum = NetbufferChecksum(); - sendbytes += packetheaderlength + doomcom->datalength; // for stat + sendbytes += packetheaderlength + doomcom->datalength; // For stat - // simulate internet :) - if (true || rand()<(INT32)RAND_MAX/5) +#ifdef PACKETDROP + // Simulate internet :) + //if (rand() >= (INT32)(RAND_MAX * (PACKETLOSSRATE / 100.f))) + if (!ShouldDropPacket()) { +#endif #ifdef DEBUGFILE if (debugfile) - DebugPrintpacket("SEND"); + DebugPrintpacket("SENT"); #endif I_NetSend(); +#ifdef PACKETDROP } + else + { + if (packetdropquantity[netbuffer->packettype] > 0) + packetdropquantity[netbuffer->packettype]--; #ifdef DEBUGFILE - else if (debugfile) - DebugPrintpacket("NOTSEND"); + if (debugfile) + DebugPrintpacket("NOT SENT"); +#endif + } #endif #endif // ndef NONET @@ -933,7 +1107,9 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen // boolean HGetPacket(void) { - // get a packet from self + //boolean nodejustjoined; + + // Get a packet from self if (rebound_tail != rebound_head) { M_Memcpy(netbuffer, &reboundstore[rebound_tail], reboundsize[rebound_tail]); @@ -958,16 +1134,17 @@ boolean HGetPacket(void) while(true) { + //nodejustjoined = I_NetGet(); I_NetGet(); - if (doomcom->remotenode == -1) + if (doomcom->remotenode == -1) // No packet received return false; - getbytes += packetheaderlength + doomcom->datalength; // for stat + getbytes += packetheaderlength + doomcom->datalength; // For stat if (doomcom->remotenode >= MAXNETNODES) { - DEBFILE(va("receive packet from node %d !\n", doomcom->remotenode)); + DEBFILE(va("Received packet from node %d!\n", doomcom->remotenode)); continue; } @@ -976,6 +1153,7 @@ boolean HGetPacket(void) if (netbuffer->checksum != NetbufferChecksum()) { DEBFILE("Bad packet checksum\n"); + //Net_CloseConnection(nodejustjoined ? (doomcom->remotenode | FORCECLOSE) : doomcom->remotenode); Net_CloseConnection(doomcom->remotenode); continue; } @@ -985,11 +1163,26 @@ boolean HGetPacket(void) DebugPrintpacket("GET"); #endif - // proceed the ack and ackreturn field + /*// If a new node sends an unexpected packet, just ignore it + if (nodejustjoined && server + && !(netbuffer->packettype == PT_ASKINFO + || netbuffer->packettype == PT_SERVERINFO + || netbuffer->packettype == PT_PLAYERINFO + || netbuffer->packettype == PT_REQUESTFILE + || netbuffer->packettype == PT_ASKINFOVIAMS + || netbuffer->packettype == PT_CLIENTJOIN)) + { + DEBFILE(va("New node sent an unexpected %s packet\n", packettypename[netbuffer->packettype])); + //CONS_Alert(CONS_NOTICE, "New node sent an unexpected %s packet\n", packettypename[netbuffer->packettype]); + Net_CloseConnection(doomcom->remotenode | FORCECLOSE); + continue; + }*/ + + // Proceed the ack and ackreturn field if (!Processackpak()) continue; // discarded (duplicated) - // a packet with just ackreturn + // A packet with just ackreturn if (netbuffer->packettype == PT_NOTHING) { GotAcks(); @@ -1002,9 +1195,10 @@ boolean HGetPacket(void) return true; } -static void Internal_Get(void) +static boolean Internal_Get(void) { doomcom->remotenode = -1; + return false; } FUNCNORETURN static ATTRNORETURN void Internal_Send(void) @@ -1089,7 +1283,7 @@ boolean D_CheckNetGame(void) if (netgame) ret = true; - if (!server && netgame) + if (client && netgame) netgame = false; server = true; // WTF? server always true??? // no! The deault mode is server. Client is set elsewhere @@ -1230,4 +1424,6 @@ void D_CloseConnection(void) netgame = false; addedtogame = false; } + + D_ResetTiccmds(); } diff --git a/src/d_net.h b/src/d_net.h index 285b44235..84814ce39 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -18,10 +18,10 @@ #ifndef __D_NET__ #define __D_NET__ -// Max computers in a game. +// Max computers in a game #define MAXNETNODES 32 #define BROADCASTADDR MAXNETNODES -#define MAXSPLITSCREENPLAYERS 2 // max number of players on a single computer +#define MAXSPLITSCREENPLAYERS 2 // Max number of players on a single computer #define STATLENGTH (TICRATE*2) @@ -32,17 +32,17 @@ extern float lostpercent, duppercent, gamelostpercent; extern INT32 packetheaderlength; boolean Net_GetNetStat(void); extern INT32 getbytes; -extern INT64 sendbytes; // realtime updated +extern INT64 sendbytes; // Realtime updated extern SINT8 nodetoplayer[MAXNETNODES]; -extern SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen) -extern UINT8 playerpernode[MAXNETNODES]; // used specialy for scplitscreen -extern boolean nodeingame[MAXNETNODES]; // set false as nodes leave game +extern SINT8 nodetoplayer2[MAXNETNODES]; // Say the numplayer for this node if any (splitscreen) +extern UINT8 playerpernode[MAXNETNODES]; // Used specially for splitscreen +extern boolean nodeingame[MAXNETNODES]; // Set false as nodes leave game +INT32 Net_GetFreeAcks(boolean urgent); void Net_AckTicker(void); -boolean Net_AllAckReceived(void); -// if reliable return true if packet sent, 0 else +// If reliable return true if packet sent, 0 else boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlength); boolean HGetPacket(void); @@ -52,9 +52,11 @@ void D_SaveBan(void); #endif boolean D_CheckNetGame(void); void D_CloseConnection(void); -void Net_UnAcknowledgPacket(INT32 node); +void Net_UnAcknowledgePacket(INT32 node); void Net_CloseConnection(INT32 node); +void Net_ConnectionTimeout(INT32 node); void Net_AbortPacketType(UINT8 packettype); void Net_SendAcks(INT32 node); void Net_WaitAllAckReceived(UINT32 timeout); + #endif diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 65b415e65..55a3b30f9 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -82,6 +82,7 @@ static void AutoBalance_OnChange(void); static void TeamScramble_OnChange(void); static void NetTimeout_OnChange(void); +static void JoinTimeout_OnChange(void); static void Ringslinger_OnChange(void); static void Gravity_OnChange(void); @@ -340,7 +341,9 @@ consvar_t cv_killingdead = {"killingdead", "Off", CV_NETVAR, CV_OnOff, NULL, 0, consvar_t cv_netstat = {"netstat", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; // show bandwidth statistics static CV_PossibleValue_t nettimeout_cons_t[] = {{TICRATE/7, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}}; -consvar_t cv_nettimeout = {"nettimeout", "525", CV_CALL|CV_SAVE, nettimeout_cons_t, NetTimeout_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_nettimeout = {"nettimeout", "350", CV_CALL|CV_SAVE, nettimeout_cons_t, NetTimeout_OnChange, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t jointimeout_cons_t[] = {{5*TICRATE, "MIN"}, {60*TICRATE, "MAX"}, {0, NULL}}; +consvar_t cv_jointimeout = {"jointimeout", "350", CV_CALL|CV_SAVE, jointimeout_cons_t, JoinTimeout_OnChange, 0, NULL, NULL, 0, 0, NULL}; #ifdef NEWPING consvar_t cv_maxping = {"maxping", "0", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; #endif @@ -365,6 +368,35 @@ boolean splitscreen = false; boolean circuitmap = false; INT32 adminplayer = -1; +/// \warning Keep this up-to-date if you add/remove/rename net text commands +const char *netxcmdnames[MAXNETXCMD - 1] = +{ + "NAMEANDCOLOR", + "WEAPONPREF", + "KICK", + "NETVAR", + "SAY", + "MAP", + "EXITLEVEL", + "ADDFILE", + "PAUSE", + "ADDPLAYER", + "TEAMCHANGE", + "CLEARSCORES", + "LOGIN", + "VERIFIED", + "RANDOMSEED", + "RUNSOC", + "REQADDFILE", + "DELFILE", + "SETMOTD", + "SUICIDE", +#ifdef HAVE_BLUA + "LUACMD", + "LUAVAR" +#endif +}; + // ========================================================================= // SERVER STARTUP // ========================================================================= @@ -517,9 +549,12 @@ void D_RegisterServerCommands(void) // d_clisrv CV_RegisterVar(&cv_maxplayers); CV_RegisterVar(&cv_maxsend); + CV_RegisterVar(&cv_noticedownload); + CV_RegisterVar(&cv_downloadspeed); COM_AddCommand("ping", Command_Ping_f); CV_RegisterVar(&cv_nettimeout); + CV_RegisterVar(&cv_jointimeout); CV_RegisterVar(&cv_skipmapcheck); CV_RegisterVar(&cv_sleep); @@ -976,7 +1011,7 @@ UINT8 CanChangeSkin(INT32 playernum) return true; // Force skin in effect. - if (!server && (cv_forceskin.value != -1) && !(adminplayer == playernum && serverplayer == -1)) + if (client && (cv_forceskin.value != -1) && !(adminplayer == playernum && serverplayer == -1)) return false; // Can change skin in intermission and whatnot. @@ -1587,7 +1622,7 @@ static void Command_Map_f(void) return; } - if (!server && !(adminplayer == consoleplayer)) + if (client && !(adminplayer == consoleplayer)) { CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); return; @@ -1914,7 +1949,7 @@ static void Got_Suicide(UINT8 **cp, INT32 playernum) // You can't suicide someone else. Nice try, there. if (suicideplayer != playernum || (!G_PlatformGametype())) { - CONS_Alert(CONS_WARNING, M_GetText("Illegal suicide command recieved from %s\n"), player_names[playernum]); + CONS_Alert(CONS_WARNING, M_GetText("Illegal suicide command received from %s\n"), player_names[playernum]); if (server) { XBOXSTATIC UINT8 buf[2]; @@ -2574,7 +2609,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) if (players[playernum].spectator) { players[playernum].score = 0; - players[playernum].health = 1; + players[playernum].rings = 0; if (players[playernum].mo) players[playernum].mo->health = 1; } @@ -2629,7 +2664,7 @@ static void Command_Changepassword_f(void) // If we have no MD5 support then completely disable XD_LOGIN responses for security. CONS_Alert(CONS_NOTICE, "Remote administration commands are not supported in this build.\n"); #else - if (!server) // cannot change remotely + if (client) // cannot change remotely { CONS_Printf(M_GetText("Only the server can use this.\n")); return; @@ -2688,7 +2723,7 @@ static void Got_Login(UINT8 **cp, INT32 playernum) READMEM(*cp, sentmd5, 16); - if (!server) + if (client) return; // Do the final pass to compare with the sent md5 @@ -2710,7 +2745,7 @@ static void Command_Verify_f(void) char *temp; INT32 playernum; - if (!server) + if (client) { CONS_Printf(M_GetText("Only the server can use this.\n")); return; @@ -2794,7 +2829,7 @@ static void Command_MotD_f(void) return; } - if ((netgame || multiplayer) && !server) + if ((netgame || multiplayer) && client) SendNetXCmd(XD_SETMOTD, mymotd, sizeof(motd)); else { @@ -3051,7 +3086,7 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum) READMEM(*cp, md5sum, 16); // Only the server processes this message. - if (!server) + if (client) return; // Disallow non-printing characters and semicolons. @@ -3318,6 +3353,11 @@ static void NetTimeout_OnChange(void) connectiontimeout = (tic_t)cv_nettimeout.value; } +static void JoinTimeout_OnChange(void) +{ + jointimeout = (tic_t)cv_jointimeout.value; +} + UINT32 timelimitintics = 0; /** Deals with a timelimit change by printing the change to the console. @@ -3960,7 +4000,7 @@ static void Command_Archivetest_f(void) } // assign mobjnum - i = 0; + i = 1; for (th = thinkercap.next; th != &thinkercap; th = th->next) if (th->function.acp1 == (actionf_p1)P_MobjThinker) ((mobj_t *)th)->mobjnum = i++; @@ -4055,8 +4095,7 @@ static void Skin_OnChange(void) if (!Playing()) return; // do whatever you want - if (!(cv_debug || devparm) && !(multiplayer || netgame) // In single player. - && (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_CONTINUING)) + if (!(cv_debug || devparm) && !(multiplayer || netgame)) // In single player. { CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name); return; diff --git a/src/d_netcmd.h b/src/d_netcmd.h index c090699f1..08fc8b831 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -101,7 +101,6 @@ extern consvar_t cv_recycler; extern consvar_t cv_itemfinder; extern consvar_t cv_inttime, cv_advancemap, cv_playersforexit; -extern consvar_t cv_soniccd; extern consvar_t cv_match_scoring; extern consvar_t cv_overtime; extern consvar_t cv_startinglives; @@ -162,6 +161,8 @@ typedef enum MAXNETXCMD } netxcmd_t; +extern const char *netxcmdnames[MAXNETXCMD - 1]; + #if defined(_MSC_VER) #pragma pack(1) #endif diff --git a/src/d_netfil.c b/src/d_netfil.c index 85196217f..bf4e59878 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -62,44 +62,48 @@ #include <errno.h> -static void SendFile(INT32 node, const char *filename, UINT8 fileid); +static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid); -// sender structure +// Sender structure typedef struct filetx_s { INT32 ram; - char *filename; // name of the file or ptr of the data in ram - UINT32 size; + union { + char *filename; // Name of the file + char *ram; // Pointer to the data in RAM + } id; + UINT32 size; // Size of the file UINT8 fileid; - INT32 node; // destination - struct filetx_s *next; // a queue + INT32 node; // Destination + struct filetx_s *next; // Next file in the list } filetx_t; -// current transfers (one for each node) +// Current transfers (one for each node) typedef struct filetran_s { - filetx_t *txlist; - UINT32 position; - FILE *currentfile; + filetx_t *txlist; // Linked list of all files for the node + UINT32 position; // The current position in the file + FILE *currentfile; // The file currently being sent/received } filetran_t; static filetran_t transfer[MAXNETNODES]; -// read time of file: stat _stmtime -// write time of file: utime +// Read time of file: stat _stmtime +// Write time of file: utime -// receiver structure -INT32 fileneedednum; -fileneeded_t fileneeded[MAX_WADFILES]; +// Receiver structure +INT32 fileneedednum; // Number of files needed to join the server +fileneeded_t fileneeded[MAX_WADFILES]; // List of needed files char downloaddir[256] = "DOWNLOAD"; #ifdef CLIENT_LOADINGSCREEN // for cl loading screen -INT32 lastfilenum = 0; +INT32 lastfilenum = -1; #endif /** Fills a serverinfo packet with information about wad files loaded. * * \todo Give this function a better name since it is in global scope. + * */ UINT8 *PutFileNeeded(void) { @@ -111,19 +115,19 @@ UINT8 *PutFileNeeded(void) for (i = 0; i < numwadfiles; i++) { - // if it has only music/sound lumps, mark it as unimportant + // If it has only music/sound lumps, mark it as unimportant if (W_VerifyNMUSlumps(wadfiles[i]->filename)) filestatus = 0; else - filestatus = 1; // important + filestatus = 1; // Important // Store in the upper four bits if (!cv_downloading.value) - filestatus += (2 << 4); // won't send + filestatus += (2 << 4); // Won't send else if ((wadfiles[i]->filesize > (UINT32)cv_maxsend.value * 1024)) - filestatus += (0 << 4); // won't send + filestatus += (0 << 4); // Won't send else - filestatus += (1 << 4); // will send if requested + filestatus += (1 << 4); // Will send if requested bytesused += (nameonlylength(wadfilename) + 22); @@ -144,7 +148,12 @@ UINT8 *PutFileNeeded(void) return p; } -// parse the serverinfo packet and fill fileneeded table on client +/** Parses the serverinfo packet and fills the fileneeded table on client + * + * \param fileneedednum_parm The number of files needed to join the server + * \param fileneededstr The memory block containing the list of needed files + * + */ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr) { INT32 i; @@ -155,14 +164,14 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr) p = (UINT8 *)fileneededstr; for (i = 0; i < fileneedednum; i++) { - fileneeded[i].status = FS_NOTFOUND; - filestatus = READUINT8(p); + 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); - fileneeded[i].phandle = NULL; - READSTRINGN(p, fileneeded[i].filename, MAX_WADPATH); - READMEM(p, fileneeded[i].md5sum, 16); + fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size + fileneeded[i].file = NULL; // The file isn't open yet + READSTRINGN(p, fileneeded[i].filename, MAX_WADPATH); // The next bytes are the file name + READMEM(p, fileneeded[i].md5sum, 16); // The last 16 bytes are the file checksum } } @@ -171,13 +180,16 @@ void CL_PrepareDownloadSaveGame(const char *tmpsave) fileneedednum = 1; fileneeded[0].status = FS_REQUESTED; fileneeded[0].totalsize = UINT32_MAX; - fileneeded[0].phandle = NULL; + fileneeded[0].file = NULL; memset(fileneeded[0].md5sum, 0, 16); strcpy(fileneeded[0].filename, tmpsave); } /** Checks the server to see if we CAN download all the files, * before starting to create them and requesting. + * + * \return True if we can download all the files + * */ boolean CL_CheckDownloadable(void) { @@ -239,8 +251,12 @@ boolean CL_CheckDownloadable(void) return false; } -/** Send requests for files in the ::fileneeded table with a status of +/** Sends requests for files in the ::fileneeded table with a status of * ::FS_NOTFOUND. + * + * \return True if the packet was successfully sent + * \note Sends a PT_REQUESTFILE packet + * */ boolean CL_SendRequestFile(void) { @@ -298,11 +314,17 @@ void Got_RequestFilePak(INT32 node) if (id == 0xFF) break; READSTRINGN(p, wad, MAX_WADPATH); - SendFile(node, wad, id); + SV_SendFile(node, wad, id); } } -// client check if the fileneeded aren't already loaded or on the disk +/** Checks if the files needed aren't already loaded or on the disk + * + * \return 0 if some files are missing + * 1 if all files exist + * 2 if some already loaded files are not requested or are in a different order + * + */ INT32 CL_CheckFiles(void) { INT32 i, j; @@ -333,7 +355,7 @@ INT32 CL_CheckFiles(void) } if (j < numwadfiles && W_VerifyNMUSlumps(wadfiles[j]->filename)) { - // unimportant on our side. still don't care. + // Unimportant on our side. still don't care. ++j; continue; } @@ -343,11 +365,11 @@ INT32 CL_CheckFiles(void) if (i >= fileneedednum || j >= numwadfiles) return 2; - // for the sake of speed, only bother with a md5 check + // For the sake of speed, only bother with a md5 check if (memcmp(wadfiles[j]->md5sum, fileneeded[i].md5sum, 16)) return 2; - // it's accounted for! let's keep going. + // It's accounted for! let's keep going. CONS_Debug(DBG_NETPLAY, "'%s' accounted for\n", fileneeded[i].filename); fileneeded[i].status = FS_OPEN; ++i; @@ -360,7 +382,7 @@ INT32 CL_CheckFiles(void) { CONS_Debug(DBG_NETPLAY, "searching for '%s' ", fileneeded[i].filename); - // check in allready loaded files + // Check in already loaded files for (j = 1; wadfiles[j]; j++) { nameonly(strcpy(wadfilename, wadfiles[j]->filename)); @@ -383,7 +405,7 @@ INT32 CL_CheckFiles(void) return ret; } -// load it now +// Load it now void CL_LoadServerFiles(void) { INT32 i; @@ -394,7 +416,7 @@ void CL_LoadServerFiles(void) for (i = 1; i < fileneedednum; i++) { if (fileneeded[i].status == FS_OPEN) - continue; // already loaded + continue; // Already loaded else if (fileneeded[i].status == FS_FOUND) { P_AddWadFile(fileneeded[i].filename, NULL); @@ -423,172 +445,269 @@ void CL_LoadServerFiles(void) DEBFILE(va("File %s found but with different md5sum\n", fileneeded[i].filename)); } else if (fileneeded[i].important) - I_Error("Try to load file %s with status of %d\n", fileneeded[i].filename, - fileneeded[i].status); + { + const char *s; + switch(fileneeded[i].status) + { + case FS_NOTFOUND: + s = "FS_NOTFOUND"; + break; + case FS_REQUESTED: + s = "FS_REQUESTED"; + break; + case FS_DOWNLOADING: + s = "FS_DOWNLOADING"; + break; + default: + s = "unknown"; + break; + } + I_Error("Try to load file \"%s\" with status of %d (%s)\n", fileneeded[i].filename, + fileneeded[i].status, s); + } } } -// little optimization to test if there is a file in the queue -static INT32 filetosend = 0; +// Number of files to send +// Little optimization to quickly test if there is a file in the queue +static INT32 filestosend = 0; -static void SendFile(INT32 node, const char *filename, UINT8 fileid) +/** Adds a file to the file list for a node + * + * \param node The node to send the file to + * \param filename The file to send + * \param fileid ??? + * \sa SV_SendRam + * + */ +static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid) { - filetx_t **q; - filetx_t *p; + filetx_t **q; // A pointer to the "next" field of the last file in the list + filetx_t *p; // The new file request INT32 i; char wadfilename[MAX_WADPATH]; + if (cv_noticedownload.value) + CONS_Printf("Sending file \"%s\" to node %d\n", filename, node); + + // Find the last file in the list and set a pointer to its "next" field q = &transfer[node].txlist; while (*q) q = &((*q)->next); + + // Allocate a file request and append it to the file list p = *q = (filetx_t *)malloc(sizeof (filetx_t)); - if (p) - memset(p, 0, sizeof (filetx_t)); - else - I_Error("SendFile: No more ram\n"); - p->filename = (char *)malloc(MAX_WADPATH); - if (!p->filename) - I_Error("SendFile: No more ram\n"); + if (!p) + I_Error("SV_SendFile: No more memory\n"); - // a minimum of security, can get only file in srb2 direcory - strlcpy(p->filename, filename, MAX_WADPATH); - nameonly(p->filename); + // Initialise with zeros + memset(p, 0, sizeof (filetx_t)); - // check first in wads loaded the majority of case + // Allocate the file name + p->id.filename = (char *)malloc(MAX_WADPATH); + if (!p->id.filename) + I_Error("SV_SendFile: No more memory\n"); + + // Set the file name and get rid of the path + strlcpy(p->id.filename, filename, MAX_WADPATH); + nameonly(p->id.filename); + + // Look for the requested file through all loaded files for (i = 0; wadfiles[i]; i++) { strlcpy(wadfilename, wadfiles[i]->filename, MAX_WADPATH); nameonly(wadfilename); - if (!stricmp(wadfilename, p->filename)) + if (!stricmp(wadfilename, p->id.filename)) { - // copy filename with full path - strlcpy(p->filename, wadfiles[i]->filename, MAX_WADPATH); + // Copy file name with full path + strlcpy(p->id.filename, wadfiles[i]->filename, MAX_WADPATH); break; } } + // Handle non-loaded file requests if (!wadfiles[i]) { DEBFILE(va("%s not found in wadfiles\n", filename)); - // this formerly checked if (!findfile(p->filename, NULL, true)) + // This formerly checked if (!findfile(p->id.filename, NULL, true)) - // not found - // don't inform client (probably hacker) + // Not found + // Don't inform client (probably someone who thought they could leak 2.2 ACZ) DEBFILE(va("Client %d request %s: not found\n", node, filename)); - free(p->filename); + free(p->id.filename); free(p); *q = NULL; return; } + // Handle huge file requests (i.e. bigger than cv_maxsend.value KB) if (wadfiles[i]->filesize > (UINT32)cv_maxsend.value * 1024) { - // too big - // don't inform client (client sucks, man) + // Too big + // Don't inform client (client sucks, man) DEBFILE(va("Client %d request %s: file too big, not sending\n", node, filename)); - free(p->filename); + free(p->id.filename); free(p); *q = NULL; return; } DEBFILE(va("Sending file %s (id=%d) to %d\n", filename, fileid, node)); - p->ram = SF_FILE; + p->ram = SF_FILE; // It's a file, we need to close it and free its name once we're done sending it p->fileid = fileid; - p->next = NULL; // end of list - filetosend++; + p->next = NULL; // End of list + filestosend++; } -void SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod, UINT8 fileid) +/** Adds a memory block to the file list for a node + * + * \param node The node to send the memory block to + * \param data The memory block to send + * \param size The size of the block in bytes + * \param freemethod How to free the block after it has been sent + * \param fileid ??? + * \sa SV_SendFile + * + */ +void SV_SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod, UINT8 fileid) { - filetx_t **q; - filetx_t *p; + filetx_t **q; // A pointer to the "next" field of the last file in the list + filetx_t *p; // The new file request + // Find the last file in the list and set a pointer to its "next" field q = &transfer[node].txlist; while (*q) q = &((*q)->next); + + // Allocate a file request and append it to the file list p = *q = (filetx_t *)malloc(sizeof (filetx_t)); - if (p) - memset(p, 0, sizeof (filetx_t)); - else - I_Error("SendRam: No more ram\n"); - p->ram = freemethod; - p->filename = data; + if (!p) + I_Error("SV_SendRam: No more memory\n"); + + // Initialise with zeros + memset(p, 0, sizeof (filetx_t)); + + p->ram = freemethod; // Remember how to free the memory block for when we're done sending it + p->id.ram = data; p->size = (UINT32)size; p->fileid = fileid; - p->next = NULL; // end of list + p->next = NULL; // End of list - DEBFILE(va("Sending ram %p(size:%u) to %d (id=%u)\n",p->filename,p->size,node,fileid)); + DEBFILE(va("Sending ram %p(size:%u) to %d (id=%u)\n",p->id.ram,p->size,node,fileid)); - filetosend++; + filestosend++; } -static void EndSend(INT32 node) +/** Stops sending a file for a node, and removes the file request from the list, + * either because the file has been fully sent or because the node was disconnected + * + * \param node The destination + * + */ +static void SV_EndFileSend(INT32 node) { filetx_t *p = transfer[node].txlist; + + // Free the file request according to the freemethod parameter used with SV_SendFile/Ram switch (p->ram) { - case SF_FILE: + case SF_FILE: // It's a file, close it and free its filename + if (cv_noticedownload.value) + CONS_Printf("Ending file transfer for node %d\n", node); if (transfer[node].currentfile) fclose(transfer[node].currentfile); - free(p->filename); + free(p->id.filename); break; - case SF_Z_RAM: - Z_Free(p->filename); + case SF_Z_RAM: // It's a memory block allocated with Z_Alloc or the likes, use Z_Free + Z_Free(p->id.ram); break; - case SF_RAM: - free(p->filename); - case SF_NOFREERAM: + case SF_RAM: // It's a memory block allocated with malloc, use free + free(p->id.ram); + case SF_NOFREERAM: // Nothing to free break; } + + // Remove the file request from the list transfer[node].txlist = p->next; - transfer[node].currentfile = NULL; free(p); - filetosend--; + + // Indicate that the transmission is over + transfer[node].currentfile = NULL; + + filestosend--; } #define PACKETPERTIC net_bandwidth/(TICRATE*software_MAXPACKETLENGTH) -void FiletxTicker(void) +/** Handles file transmission + * + * \todo Use an acknowledging method more adapted to file transmission + * The current download speed suffers from lack of ack packets, + * especially when the one downloading has high latency + * + */ +void SV_FileSendTicker(void) { static INT32 currentnode = 0; filetx_pak *p; size_t size; filetx_t *f; - INT32 packetsent = PACKETPERTIC, ram, i; + INT32 packetsent, ram, i, j; + INT32 maxpacketsent; - if (!filetosend) + if (!filestosend) // No file to send return; - if (!packetsent) - packetsent++; - // (((sendbytes-nowsentbyte)*TICRATE)/(I_GetTime()-starttime)<(UINT32)net_bandwidth) - while (packetsent-- && filetosend != 0) + + if (cv_downloadspeed.value) // New (and experimental) behavior { - for (i = currentnode, ram = 0; ram < MAXNETNODES; - i = (i+1) % MAXNETNODES, ram++) + packetsent = cv_downloadspeed.value; + // Don't send more packets than we have free acks +#ifndef NONET + maxpacketsent = Net_GetFreeAcks(false) - 5; // Let 5 extra acks just in case +#else + maxpacketsent = 1; +#endif + if (packetsent > maxpacketsent && maxpacketsent > 0) // Send at least one packet + packetsent = maxpacketsent; + } + else // Old behavior + { + packetsent = PACKETPERTIC; + if (!packetsent) + packetsent = 1; + } + + netbuffer->packettype = PT_FILEFRAGMENT; + + // (((sendbytes-nowsentbyte)*TICRATE)/(I_GetTime()-starttime)<(UINT32)net_bandwidth) + while (packetsent-- && filestosend != 0) + { + for (i = currentnode, j = 0; j < MAXNETNODES; + i = (i+1) % MAXNETNODES, j++) { if (transfer[i].txlist) goto found; } // no transfer to do - I_Error("filetosend=%d but no filetosend found\n", filetosend); + I_Error("filestosend=%d but no file to send found\n", filestosend); found: currentnode = (i+1) % MAXNETNODES; f = transfer[i].txlist; ram = f->ram; - if (!transfer[i].currentfile) // file not already open + // Open the file if it isn't open yet, or + if (!transfer[i].currentfile) { - if (!ram) + if (!ram) // Sending a file { long filesize; transfer[i].currentfile = - fopen(f->filename, "rb"); + fopen(f->id.filename, "rb"); if (!transfer[i].currentfile) I_Error("File %s does not exist", - f->filename); + f->id.filename); fseek(transfer[i].currentfile, 0, SEEK_END); filesize = ftell(transfer[i].currentfile); @@ -596,45 +715,47 @@ void FiletxTicker(void) // Nobody wants to transfer a file bigger // than 4GB! if (filesize >= LONG_MAX) - I_Error("filesize of %s is too large", f->filename); - if (-1 == filesize) - I_Error("Error getting filesize of %s", f->filename); + I_Error("filesize of %s is too large", f->id.filename); + if (filesize == -1) + I_Error("Error getting filesize of %s", f->id.filename); f->size = (UINT32)filesize; fseek(transfer[i].currentfile, 0, SEEK_SET); } - else - transfer[i].currentfile = (FILE *)1; + else // Sending RAM + transfer[i].currentfile = (FILE *)1; // Set currentfile to a non-null value to indicate that it is open transfer[i].position = 0; } + // Build a packet containing a file fragment p = &netbuffer->u.filetxpak; size = software_MAXPACKETLENGTH - (FILETXHEADER + BASEPACKETSIZE); if (f->size-transfer[i].position < size) size = f->size-transfer[i].position; if (ram) - M_Memcpy(p->data, &f->filename[transfer[i].position], size); + M_Memcpy(p->data, &f->id.ram[transfer[i].position], size); else if (fread(p->data, 1, size, transfer[i].currentfile) != size) - I_Error("FiletxTicker: can't read %s byte on %s at %d because %s", sizeu1(size), f->filename, transfer[i].position, strerror(ferror(transfer[i].currentfile))); + I_Error("SV_FileSendTicker: can't read %s byte on %s at %d because %s", sizeu1(size), f->id.filename, transfer[i].position, strerror(ferror(transfer[i].currentfile))); p->position = LONG(transfer[i].position); - // put flag so receiver know the totalsize + // Put flag so receiver knows the total size if (transfer[i].position + size == f->size) p->position |= LONG(0x80000000); p->fileid = f->fileid; p->size = SHORT((UINT16)size); - netbuffer->packettype = PT_FILEFRAGMENT; - if (!HSendPacket(i, true, 0, FILETXHEADER + size)) // reliable SEND - { // not sent for some odd reason, retry at next call - if (!ram) - fseek(transfer[i].currentfile,transfer[i].position,SEEK_SET); - // exit the while (can't send this one so why should i send the next?) - break; + + // Send the packet + if (HSendPacket(i, true, 0, FILETXHEADER + size)) // Reliable SEND + { // Success + transfer[i].position = (UINT32)(transfer[i].position + size); + if (transfer[i].position == f->size) // Finish? + SV_EndFileSend(i); } - else // success - { - transfer[i].position = (UINT32)(size+transfer[i].position); - if (transfer[i].position == f->size) // finish ? - EndSend(i); + else + { // Not sent for some odd reason, retry at next call + if (!ram) + fseek(transfer[i].currentfile,transfer[i].position, SEEK_SET); + // Exit the while (can't send this one so why should i send the next?) + break; } } } @@ -642,55 +763,90 @@ void FiletxTicker(void) void Got_Filetxpak(void) { INT32 filenum = netbuffer->u.filetxpak.fileid; + fileneeded_t *file = &fileneeded[filenum]; + char *filename = file->filename; static INT32 filetime = 0; + if (!(strcmp(filename, "srb2.srb") + && strcmp(filename, "srb2.wad") + && strcmp(filename, "zones.dta") + && strcmp(filename, "player.dta") + && strcmp(filename, "rings.dta") + && strcmp(filename, "patch.dta") + && strcmp(filename, "music.dta") + )) + I_Error("Tried to download \"%s\"", filename); + if (filenum >= fileneedednum) { - DEBFILE(va("fileframent not needed %d>%d\n",filenum, fileneedednum)); + DEBFILE(va("fileframent not needed %d>%d\n", filenum, fileneedednum)); + //I_Error("Received an unneeded file fragment (file id received: %d, file id needed: %d)\n", filenum, fileneedednum); return; } - if (fileneeded[filenum].status == FS_REQUESTED) + if (file->status == FS_REQUESTED) { - if (fileneeded[filenum].phandle) I_Error("Got_Filetxpak: allready open file\n"); - fileneeded[filenum].phandle = fopen(fileneeded[filenum].filename, "wb"); - if (!fileneeded[filenum].phandle) I_Error("Can't create file %s: %s",fileneeded[filenum].filename, strerror(errno)); - CONS_Printf("\r%s...\n",fileneeded[filenum].filename); - fileneeded[filenum].currentsize = 0; - fileneeded[filenum].status = FS_DOWNLOADING; + if (file->file) + I_Error("Got_Filetxpak: already open file\n"); + file->file = fopen(filename, "wb"); + if (!file->file) + I_Error("Can't create file %s: %s", filename, strerror(errno)); + CONS_Printf("\r%s...\n",filename); + file->currentsize = 0; + file->status = FS_DOWNLOADING; } - if (fileneeded[filenum].status == FS_DOWNLOADING) + if (file->status == FS_DOWNLOADING) { UINT32 pos = LONG(netbuffer->u.filetxpak.position); UINT16 size = SHORT(netbuffer->u.filetxpak.size); - // use a special tric to know when file is finished (not allways used) - // WARNING: filepak can arrive out of order so don't stop now ! + // Use a special trick to know when the file is complete (not always used) + // WARNING: file fragments can arrive out of order so don't stop yet! if (pos & 0x80000000) { pos &= ~0x80000000; - fileneeded[filenum].totalsize = pos + size; + file->totalsize = pos + size; } - // we can receive packet in the wrong order, anyway all os support gaped file - fseek(fileneeded[filenum].phandle,pos,SEEK_SET); - if (fwrite(netbuffer->u.filetxpak.data,size,1,fileneeded[filenum].phandle)!=1) - I_Error("Can't write to %s: %s\n",fileneeded[filenum].filename, strerror(ferror(fileneeded[filenum].phandle))); - fileneeded[filenum].currentsize += size; + // We can receive packet in the wrong order, anyway all os support gaped file + fseek(file->file, pos, SEEK_SET); + if (fwrite(netbuffer->u.filetxpak.data,size,1,file->file) != 1) + I_Error("Can't write to %s: %s\n",filename, strerror(ferror(file->file))); + file->currentsize += size; - // finished? - if (fileneeded[filenum].currentsize == fileneeded[filenum].totalsize) + // Finished? + if (file->currentsize == file->totalsize) { - fclose(fileneeded[filenum].phandle); - fileneeded[filenum].phandle = NULL; - fileneeded[filenum].status = FS_FOUND; + fclose(file->file); + file->file = NULL; + file->status = FS_FOUND; CONS_Printf(M_GetText("Downloading %s...(done)\n"), - fileneeded[filenum].filename); + filename); } } else - I_Error("Received a file not requested\n"); - // send ack back quickly - + { + const char *s; + switch(file->status) + { + case FS_NOTFOUND: + s = "FS_NOTFOUND"; + break; + case FS_FOUND: + s = "FS_FOUND"; + break; + case FS_OPEN: + s = "FS_OPEN"; + break; + case FS_MD5SUMBAD: + s = "FS_MD5SUMBAD"; + break; + default: + s = "unknown"; + break; + } + I_Error("Received a file not requested (file id: %d, file status: %s)\n", filenum, s); + } + // Send ack back quickly if (++filetime == 3) { Net_SendAcks(servernode); @@ -702,33 +858,50 @@ void Got_Filetxpak(void) #endif } -void AbortSendFiles(INT32 node) +/** \brief Checks if a node is downloading a file + * + * \param node The node to check for + * \return True if the node is downloading a file + * + */ +boolean SV_SendingFile(INT32 node) +{ + return transfer[node].txlist != NULL; +} + +/** Cancels all file requests for a node + * + * \param node The destination + * \sa SV_EndFileSend + * + */ +void SV_AbortSendFiles(INT32 node) { while (transfer[node].txlist) - EndSend(node); + SV_EndFileSend(node); } void CloseNetFile(void) { INT32 i; - // is sending? + // Is sending? for (i = 0; i < MAXNETNODES; i++) - AbortSendFiles(i); + SV_AbortSendFiles(i); - // receiving a file? + // Receiving a file? for (i = 0; i < MAX_WADFILES; i++) - if (fileneeded[i].status == FS_DOWNLOADING && fileneeded[i].phandle) + if (fileneeded[i].status == FS_DOWNLOADING && fileneeded[i].file) { - fclose(fileneeded[i].phandle); - // file is not complete delete it + fclose(fileneeded[i].file); + // File is not complete delete it remove(fileneeded[i].filename); } - // remove FILEFRAGMENT from acknledge list + // Remove PT_FILEFRAGMENT from acknowledge list Net_AbortPacketType(PT_FILEFRAGMENT); } -// functions cut and pasted from doomatic :) +// Functions cut and pasted from Doomatic :) void nameonly(char *s) { diff --git a/src/d_netfil.h b/src/d_netfil.h index a68119f10..c9085a5b0 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -29,21 +29,21 @@ typedef enum FS_FOUND, FS_REQUESTED, FS_DOWNLOADING, - FS_OPEN, // is opened and used in w_wad + FS_OPEN, // Is opened and used in w_wad FS_MD5SUMBAD } filestatus_t; typedef struct { UINT8 important; - UINT8 willsend; // is the server willing to send it? + UINT8 willsend; // Is the server willing to send it? char filename[MAX_WADPATH]; UINT8 md5sum[16]; - // used only for download - FILE *phandle; + // Used only for download + FILE *file; UINT32 currentsize; UINT32 totalsize; - filestatus_t status; // the value returned by recsearch + filestatus_t status; // The value returned by recsearch } fileneeded_t; extern INT32 fileneedednum; @@ -58,28 +58,25 @@ UINT8 *PutFileNeeded(void); void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr); void CL_PrepareDownloadSaveGame(const char *tmpsave); -// check file list in wadfiles return 0 when a file is not found -// 1 if all file are found -// 2 if you cannot connect (different wad version or -// no enought space to download files) INT32 CL_CheckFiles(void); void CL_LoadServerFiles(void); -void SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod, +void SV_SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod, UINT8 fileid); -void FiletxTicker(void); +void SV_FileSendTicker(void); void Got_Filetxpak(void); +boolean SV_SendingFile(INT32 node); boolean CL_CheckDownloadable(void); boolean CL_SendRequestFile(void); void Got_RequestFilePak(INT32 node); -void AbortSendFiles(INT32 node); +void SV_AbortSendFiles(INT32 node); void CloseNetFile(void); boolean fileexist(char *filename, time_t ptime); -// search a file in the wadpath, return FS_FOUND when found +// Search a file in the wadpath, return FS_FOUND when found filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean completepath); filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum); diff --git a/src/d_player.h b/src/d_player.h index bd553d9fa..1c57e6167 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -44,6 +44,7 @@ typedef enum SF_STOMPDAMAGE = 1<<9, // Always damage enemies, etc by landing on them, no matter your vunerability? SF_MARIODAMAGE = SF_NOJUMPDAMAGE|SF_STOMPDAMAGE, // The Mario method of being able to damage enemies, etc. SF_MACHINE = 1<<10, // Beep boop. Are you a robot? + SF_NOSPINDASHDUST = 1<<11, // Don't spawn dust particles when charging a spindash // free up to and including 1<<31 } skinflags_t; @@ -151,7 +152,13 @@ typedef enum PF_ANALOGMODE = 1<<26, // Analog mode? // Can carry another player? - PF_CANCARRY = 1<<27 + PF_CANCARRY = 1<<27, + + // Used shield ability + PF_SHIELDABILITY = 1<<28, + + // Force jump damage? + PF_FORCEJUMPDAMAGE = 1<<29 // free up to and including 1<<31 } pflags_t; @@ -178,23 +185,34 @@ typedef enum typedef enum { SH_NONE = 0, - // Standard shields - SH_JUMP, - SH_ATTRACT, - SH_ELEMENTAL, - SH_BOMB, - // Stupid useless unimplimented Sonic 3 shields - SH_BUBBLEWRAP, - SH_THUNDERCOIN, - SH_FLAMEAURA, - // Pity shield: the world's most basic shield ever, given to players who suck at Match - SH_PITY, - // The fireflower is special, it combines with other shields. - SH_FIREFLOWER = 0x100, - // The force shield uses the lower 8 bits to count how many hits are left. - SH_FORCE = 0x200, - SH_STACK = SH_FIREFLOWER, + // Shield flags + SH_PROTECTFIRE = 0x400, + SH_PROTECTWATER = 0x800, + SH_PROTECTELECTRIC = 0x1000, + + // 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, + + // Sonic 3 shields + SH_FLAMEAURA = SH_PROTECTFIRE, + SH_BUBBLEWRAP = SH_PROTECTWATER, + SH_THUNDERCOIN = SH_WHIRLWIND|SH_PROTECTELECTRIC, + + // The force shield uses the lower 8 bits to count how many extra hits are left. + SH_FORCE = 0x100, + SH_FORCEHP = 0xFF, // to be used as a bitmask only + + // Mostly for use with Mario mode. + SH_FIREFLOWER = 0x200, + + SH_STACK = SH_FIREFLOWER, // second-layer shields SH_NOSTACK = ~SH_STACK } shieldtype_t; // pw_shield @@ -297,10 +315,8 @@ typedef struct player_s // It is updated with cmd->aiming. angle_t aiming; - // This is only used between levels, - // mo->health is used during levels. - /// \todo Remove this. We don't need a second health definition for players. - INT32 health; + // player's ring count + INT32 rings; SINT8 pity; // i pity the fool. INT32 currentweapon; // current weapon selected. @@ -361,8 +377,8 @@ typedef struct player_s UINT8 gotcontinue; // Got continue from this stage? fixed_t speed; // Player's speed (distance formula of MOMX and MOMY values) - UINT8 jumping; // Jump counter - UINT8 secondjump; + UINT8 jumping; // Holding down jump button + UINT8 secondjump; // Jump counter UINT8 fly1; // Tails flying UINT8 scoreadd; // Used for multiple enemy attack bonus diff --git a/src/dehacked.c b/src/dehacked.c index c3b606fe0..c71c55ac1 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -371,7 +371,9 @@ static void clear_levels(void) // (no need to set num to 0, we're freeing the entire header shortly) Z_Free(mapheaderinfo[i]->customopts); + P_DeleteFlickies(i); P_DeleteGrades(i); + Z_Free(mapheaderinfo[i]); mapheaderinfo[i] = NULL; } @@ -990,6 +992,34 @@ static const struct { {NULL, 0} }; +static const struct { + const char *name; + const mobjtype_t type; +} FLICKYTYPES[] = { + {"BLUEBIRD", MT_FLICKY_01}, + {"RABBIT", MT_FLICKY_02}, + {"CHICKEN", MT_FLICKY_03}, + {"SEAL", MT_FLICKY_04}, + {"PIG", MT_FLICKY_05}, + {"CHIPMUNK", MT_FLICKY_06}, + {"PENGUIN", MT_FLICKY_07}, + {"FISH", MT_FLICKY_08}, + {"RAM", MT_FLICKY_09}, + {"PUFFIN", MT_FLICKY_10}, + {"COW", MT_FLICKY_11}, + {"RAT", MT_FLICKY_12}, + {"BEAR", MT_FLICKY_13}, + {"DOVE", MT_FLICKY_14}, + {"CAT", MT_FLICKY_15}, + {"CANARY", MT_FLICKY_16}, + {"a", 0}, // End of normal flickies - a lower case character so will never fastcmp valid with uppercase tmp + //{"FLICKER", MT_FLICKER}, + {"SEED", MT_SEED}, + {NULL, 0} +}; + +#define MAXFLICKIES 64 + static void readlevelheader(MYFILE *f, INT32 num) { char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); @@ -1088,8 +1118,82 @@ static void readlevelheader(MYFILE *f, INT32 num) // Now go to uppercase strupr(word2); + // List of flickies that are be freed in this map + if (fastcmp(word, "FLICKYLIST") || fastcmp(word, "ANIMALLIST")) + { + if (fastcmp(word2, "NONE")) + P_DeleteFlickies(num-1); + else if (fastcmp(word2, "DEMO")) + P_SetDemoFlickies(num-1); + else if (fastcmp(word2, "ALL")) + { + mobjtype_t tmpflickies[MAXFLICKIES]; + + for (mapheaderinfo[num-1]->numFlickies = 0; + ((mapheaderinfo[num-1]->numFlickies < MAXFLICKIES) && FLICKYTYPES[mapheaderinfo[num-1]->numFlickies].type); + mapheaderinfo[num-1]->numFlickies++) + tmpflickies[mapheaderinfo[num-1]->numFlickies] = FLICKYTYPES[mapheaderinfo[num-1]->numFlickies].type; + + if (mapheaderinfo[num-1]->numFlickies) // just in case... + { + size_t newsize = sizeof(mobjtype_t) * mapheaderinfo[num-1]->numFlickies; + mapheaderinfo[num-1]->flickies = Z_Realloc(mapheaderinfo[num-1]->flickies, newsize, PU_STATIC, NULL); + M_Memcpy(mapheaderinfo[num-1]->flickies, tmpflickies, newsize); + } + } + else + { + mobjtype_t tmpflickies[MAXFLICKIES]; + mapheaderinfo[num-1]->numFlickies = 0; + tmp = strtok(word2,","); + // get up to the first MAXFLICKIES flickies + do { + if (mapheaderinfo[num-1]->numFlickies == MAXFLICKIES) // never going to get above that number + { + deh_warning("Level header %d: too many flickies\n", num); + break; + } + + if (fastncmp(tmp, "MT_", 3)) // support for specified mobjtypes... + { + i = get_mobjtype(tmp); + if (!i) + { + //deh_warning("Level header %d: unknown flicky mobj type %s\n", num, tmp); -- no need for this line as get_mobjtype complains too + continue; + } + tmpflickies[mapheaderinfo[num-1]->numFlickies] = i; + } + else // ...or a quick, limited selection of default flickies! + { + for (i = 0; FLICKYTYPES[i].name; i++) + if (fastcmp(tmp, FLICKYTYPES[i].name)) + break; + + if (!FLICKYTYPES[i].name) + { + deh_warning("Level header %d: unknown flicky selection %s\n", num, tmp); + continue; + } + tmpflickies[mapheaderinfo[num-1]->numFlickies] = FLICKYTYPES[i].type; + } + mapheaderinfo[num-1]->numFlickies++; + } while ((tmp = strtok(NULL,",")) != NULL); + + if (mapheaderinfo[num-1]->numFlickies) + { + size_t newsize = sizeof(mobjtype_t) * mapheaderinfo[num-1]->numFlickies; + mapheaderinfo[num-1]->flickies = Z_Realloc(mapheaderinfo[num-1]->flickies, newsize, PU_STATIC, NULL); + // now we add them to the list! + M_Memcpy(mapheaderinfo[num-1]->flickies, tmpflickies, newsize); + } + else + deh_warning("Level header %d: no valid flicky types found\n", num); + } + } + // NiGHTS grades - if (fastncmp(word, "GRADES", 6)) + else if (fastncmp(word, "GRADES", 6)) { UINT8 mare = (UINT8)atoi(word + 6); @@ -1322,6 +1426,8 @@ static void readlevelheader(MYFILE *f, INT32 num) Z_Free(s); } +#undef MAXFLICKIES + static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum) { char *s = Z_Calloc(MAXLINELEN, PU_STATIC, NULL); @@ -1687,6 +1793,9 @@ static actionpointer_t actionpointers[] = {{A_WaterShield}, "A_WATERSHIELD"}, {{A_ForceShield}, "A_FORCESHIELD"}, {{A_PityShield}, "A_PITYSHIELD"}, + {{A_FlameShield}, "A_FLAMESHIELD"}, + {{A_BubbleShield}, "A_BUBBLESHIELD"}, + {{A_ThunderShield}, "A_THUNDERSHIELD"}, {{A_GravityBox}, "A_GRAVITYBOX"}, {{A_ScoreRise}, "A_SCORERISE"}, {{A_ParticleSpawn}, "A_PARTICLESPAWN"}, @@ -1842,6 +1951,17 @@ static actionpointer_t actionpointers[] = {{A_BrakLobShot}, "A_BRAKLOBSHOT"}, {{A_NapalmScatter}, "A_NAPALMSCATTER"}, {{A_SpawnFreshCopy}, "A_SPAWNFRESHCOPY"}, + {{A_FlickySpawn}, "A_FLICKYSPAWN"}, + {{A_FlickyAim}, "A_FLICKYAIM"}, + {{A_FlickyFly}, "A_FLICKYFLY"}, + {{A_FlickySoar}, "A_FLICKYSOAR"}, + {{A_FlickyCoast}, "A_FLICKYCOAST"}, + {{A_FlickyHop}, "A_FLICKYHOP"}, + {{A_FlickyFlounder}, "A_FLICKYFLOUNDER"}, + {{A_FlickyCheck}, "A_FLICKYCHECK"}, + {{A_FlickyHeightCheck}, "A_FLICKYHEIGHTCHECK"}, + {{A_FlickyFlutter}, "A_FLICKYFLUTTER"}, + {{A_FlameParticle}, "A_FLAMEPARTICLE"}, {{NULL}, "NONE"}, @@ -2778,7 +2898,7 @@ static void readpatch(MYFILE *f, const char *name, UINT16 wad) char *word2; char *tmp; INT32 i = 0, j = 0, value; - texpatch_t patch = {0, 0, UINT16_MAX, UINT16_MAX}; + texpatch_t patch = {0, 0, UINT16_MAX, UINT16_MAX, 0}; // Jump to the texture this patch belongs to, which, // coincidentally, is always the last one on the buffer cache. @@ -3378,11 +3498,11 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) { if (i == 0 && word2[0] != '0') // If word2 isn't a number i = get_mobjtype(word2); // find a thing by name - if (i < NUMMOBJTYPES && i >= 0) + if (i < NUMMOBJTYPES && i > 0) readthing(f, i); else { - deh_warning("Thing %d out of range (0 - %d)", i, NUMMOBJTYPES-1); + deh_warning("Thing %d out of range (1 - %d)", i, NUMMOBJTYPES-1); ignorelines(f); } DEH_WriteUndoline(word, word2, UNDO_HEADER); @@ -4279,6 +4399,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_GOOP1", "S_GOOP2", "S_GOOP3", + "S_GOOPTRAIL", // Boss 3 "S_EGGMOBILE3_STND", @@ -4834,7 +4955,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_SPIKEBALL7", "S_SPIKEBALL8", - // Fire Shield's Spawn + // Elemental Shield's Spawn "S_SPINFIRE1", "S_SPINFIRE2", "S_SPINFIRE3", @@ -4855,7 +4976,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit // Starpost "S_STARPOST_IDLE", "S_STARPOST_FLASH", + "S_STARPOST_STARTSPIN", "S_STARPOST_SPIN", + "S_STARPOST_ENDSPIN", // Big floating mine "S_BIGMINE1", @@ -4908,6 +5031,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_RECYCLER_BOX", "S_SCORE1K_BOX", "S_SCORE10K_BOX", + "S_FLAMEAURA_BOX", + "S_BUBBLEWRAP_BOX", + "S_THUNDERCOIN_BOX", // Gold Repeat Monitor States (one per box) "S_PITY_GOLDBOX", @@ -4920,6 +5046,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_INVULN_GOLDBOX", "S_EGGMAN_GOLDBOX", "S_GRAVITY_GOLDBOX", + "S_FLAMEAURA_GOLDBOX", + "S_BUBBLEWRAP_GOLDBOX", + "S_THUNDERCOIN_GOLDBOX", // Team Ring Boxes (these are special) "S_RING_REDBOX1", @@ -4981,6 +5110,15 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_SCORE10K_ICON1", "S_SCORE10K_ICON2", + "S_FLAMEAURA_ICON1", + "S_FLAMEAURA_ICON2", + + "S_BUBBLEWRAP_ICON1", + "S_BUBBLEWRAP_ICON2", + + "S_THUNDERCOIN_ICON1", + "S_THUNDERCOIN_ICON2", + "S_ROCKET", "S_LASER", @@ -5022,21 +5160,15 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_DEMONFIRE6", "S_GFZFLOWERA", - "S_GFZFLOWERA2", - - "S_GFZFLOWERB1", - "S_GFZFLOWERB2", - - "S_GFZFLOWERC1", + "S_GFZFLOWERB", + "S_GFZFLOWERC", "S_BERRYBUSH", "S_BUSH", // THZ Plant - "S_THZPLANT1", - "S_THZPLANT2", - "S_THZPLANT3", - "S_THZPLANT4", + "S_THZFLOWERA", + "S_THZFLOWERB", // THZ Alarm "S_ALARM1", @@ -5081,6 +5213,11 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FLAME2", "S_FLAME3", "S_FLAME4", + "S_FLAME5", + "S_FLAME6", + "S_FLAMEPARTICLE", + + "S_FLAMEREST", // Eggman Statue "S_EGGSTATUE1", @@ -5142,36 +5279,13 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit // Spinning flame jets "S_FJSPINAXISA1", // Counter-clockwise "S_FJSPINAXISA2", - "S_FJSPINAXISA3", - "S_FJSPINAXISA4", - "S_FJSPINAXISA5", - "S_FJSPINAXISA6", - "S_FJSPINAXISA7", - "S_FJSPINAXISA8", - "S_FJSPINAXISA9", - "S_FJSPINHELPERA1", - "S_FJSPINHELPERA2", - "S_FJSPINHELPERA3", "S_FJSPINAXISB1", // Clockwise "S_FJSPINAXISB2", - "S_FJSPINAXISB3", - "S_FJSPINAXISB4", - "S_FJSPINAXISB5", - "S_FJSPINAXISB6", - "S_FJSPINAXISB7", - "S_FJSPINAXISB8", - "S_FJSPINAXISB9", - "S_FJSPINHELPERB1", - "S_FJSPINHELPERB2", - "S_FJSPINHELPERB3", // Blade's flame "S_FLAMEJETFLAMEB1", "S_FLAMEJETFLAMEB2", "S_FLAMEJETFLAMEB3", - "S_FLAMEJETFLAMEB4", - "S_FLAMEJETFLAMEB5", - "S_FLAMEJETFLAMEB6", // Trapgoyles "S_TRAPGOYLE", @@ -5266,8 +5380,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_BSZVINE_ORANGE", "S_BSZSHRUB", "S_BSZCLOVER", - "S_BSZFISH", - "S_BSZSUNFLOWER", + "S_BIG_PALMTREE_TRUNK", + "S_BIG_PALMTREE_TOP", + "S_PALMTREE_TRUNK", + "S_PALMTREE_TOP", "S_DBALL1", "S_DBALL2", @@ -5350,6 +5466,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_MAGN10", "S_MAGN11", "S_MAGN12", + "S_MAGN13", "S_FORC1", "S_FORC2", @@ -5373,6 +5490,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FORC19", "S_FORC20", + "S_FORC21", + "S_ELEM1", "S_ELEM2", "S_ELEM3", @@ -5386,6 +5505,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_ELEM11", "S_ELEM12", + "S_ELEM13", + "S_ELEM14", + "S_ELEMF1", "S_ELEMF2", "S_ELEMF3", @@ -5394,6 +5516,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_ELEMF6", "S_ELEMF7", "S_ELEMF8", + "S_ELEMF9", + "S_ELEMF10", "S_PITY1", "S_PITY2", @@ -5406,6 +5530,84 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_PITY9", "S_PITY10", + "S_FIRS1", + "S_FIRS2", + "S_FIRS3", + "S_FIRS4", + "S_FIRS5", + "S_FIRS6", + "S_FIRS7", + "S_FIRS8", + "S_FIRS9", + + "S_FIRS10", + "S_FIRS11", + + "S_FIRSB1", + "S_FIRSB2", + "S_FIRSB3", + "S_FIRSB4", + "S_FIRSB5", + "S_FIRSB6", + "S_FIRSB7", + "S_FIRSB8", + "S_FIRSB9", + + "S_FIRSB10", + + "S_BUBS1", + "S_BUBS2", + "S_BUBS3", + "S_BUBS4", + "S_BUBS5", + "S_BUBS6", + "S_BUBS7", + "S_BUBS8", + "S_BUBS9", + + "S_BUBS10", + "S_BUBS11", + + "S_BUBSB1", + "S_BUBSB2", + "S_BUBSB3", + "S_BUBSB4", + + "S_BUBSB5", + "S_BUBSB6", + + "S_ZAPS1", + "S_ZAPS2", + "S_ZAPS3", + "S_ZAPS4", + "S_ZAPS5", + "S_ZAPS6", + "S_ZAPS7", + "S_ZAPS8", + "S_ZAPS9", + "S_ZAPS10", + "S_ZAPS11", + "S_ZAPS12", + "S_ZAPS13", // blank frame + "S_ZAPS14", + "S_ZAPS15", + "S_ZAPS16", + + "S_ZAPSB1", // blank frame + "S_ZAPSB2", + "S_ZAPSB3", + "S_ZAPSB4", + "S_ZAPSB5", + "S_ZAPSB6", + "S_ZAPSB7", + "S_ZAPSB8", + "S_ZAPSB9", + "S_ZAPSB10", + "S_ZAPSB11", // blank frame + + // Thunder spark + "S_THUNDERCOIN_SPARK", + // Invincibility Sparkles "S_IVSP", @@ -5416,43 +5618,133 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_SSPK4", "S_SSPK5", - // Freed Birdie - "S_BIRD1", - "S_BIRD2", - "S_BIRD3", + // Flicky-sized bubble + "S_FLICKY_BUBBLE", - // Freed Bunny - "S_BUNNY1", - "S_BUNNY2", - "S_BUNNY3", - "S_BUNNY4", - "S_BUNNY5", - "S_BUNNY6", - "S_BUNNY7", - "S_BUNNY8", - "S_BUNNY9", - "S_BUNNY10", + // Bluebird + "S_FLICKY_01_OUT", + "S_FLICKY_01_FLAP1", + "S_FLICKY_01_FLAP2", + "S_FLICKY_01_FLAP3", - // Freed Mouse - "S_MOUSE1", - "S_MOUSE2", + // Rabbit + "S_FLICKY_02_OUT", + "S_FLICKY_02_AIM", + "S_FLICKY_02_HOP", + "S_FLICKY_02_UP", + "S_FLICKY_02_DOWN", - // Freed Chicken - "S_CHICKEN1", - "S_CHICKENHOP", - "S_CHICKENFLY1", - "S_CHICKENFLY2", + // Chicken + "S_FLICKY_03_OUT", + "S_FLICKY_03_AIM", + "S_FLICKY_03_HOP", + "S_FLICKY_03_UP", + "S_FLICKY_03_FLAP1", + "S_FLICKY_03_FLAP2", - // Freed Cow - "S_COW1", - "S_COW2", - "S_COW3", - "S_COW4", + // Seal + "S_FLICKY_04_OUT", + "S_FLICKY_04_AIM", + "S_FLICKY_04_HOP", + "S_FLICKY_04_UP", + "S_FLICKY_04_DOWN", + "S_FLICKY_04_SWIM1", + "S_FLICKY_04_SWIM2", + "S_FLICKY_04_SWIM3", + "S_FLICKY_04_SWIM4", - // Red Birdie in Bubble - "S_RBIRD1", - "S_RBIRD2", - "S_RBIRD3", + // Pig + "S_FLICKY_05_OUT", + "S_FLICKY_05_AIM", + "S_FLICKY_05_HOP", + "S_FLICKY_05_UP", + "S_FLICKY_05_DOWN", + + // Chipmunk + "S_FLICKY_06_OUT", + "S_FLICKY_06_AIM", + "S_FLICKY_06_HOP", + "S_FLICKY_06_UP", + "S_FLICKY_06_DOWN", + + // Penguin + "S_FLICKY_07_OUT", + "S_FLICKY_07_AIML", + "S_FLICKY_07_HOPL", + "S_FLICKY_07_UPL", + "S_FLICKY_07_DOWNL", + "S_FLICKY_07_AIMR", + "S_FLICKY_07_HOPR", + "S_FLICKY_07_UPR", + "S_FLICKY_07_DOWNR", + "S_FLICKY_07_SWIM1", + "S_FLICKY_07_SWIM2", + "S_FLICKY_07_SWIM3", + + // Fish + "S_FLICKY_08_OUT", + "S_FLICKY_08_AIM", + "S_FLICKY_08_HOP", + "S_FLICKY_08_FLAP1", + "S_FLICKY_08_FLAP2", + "S_FLICKY_08_FLAP3", + "S_FLICKY_08_FLAP4", + "S_FLICKY_08_SWIM1", + "S_FLICKY_08_SWIM2", + "S_FLICKY_08_SWIM3", + "S_FLICKY_08_SWIM4", + + // Ram + "S_FLICKY_09_OUT", + "S_FLICKY_09_AIM", + "S_FLICKY_09_HOP", + "S_FLICKY_09_UP", + "S_FLICKY_09_DOWN", + + // Puffin + "S_FLICKY_10_OUT", + "S_FLICKY_10_FLAP1", + "S_FLICKY_10_FLAP2", + + // Cow + "S_FLICKY_11_OUT", + "S_FLICKY_11_AIM", + "S_FLICKY_11_RUN1", + "S_FLICKY_11_RUN2", + "S_FLICKY_11_RUN3", + + // Rat + "S_FLICKY_12_OUT", + "S_FLICKY_12_AIM", + "S_FLICKY_12_RUN1", + "S_FLICKY_12_RUN2", + "S_FLICKY_12_RUN3", + + // Bear + "S_FLICKY_13_OUT", + "S_FLICKY_13_AIM", + "S_FLICKY_13_HOP", + "S_FLICKY_13_UP", + "S_FLICKY_13_DOWN", + + // Dove + "S_FLICKY_14_OUT", + "S_FLICKY_14_FLAP1", + "S_FLICKY_14_FLAP2", + "S_FLICKY_14_FLAP3", + + // Cat + "S_FLICKY_15_OUT", + "S_FLICKY_15_AIM", + "S_FLICKY_15_HOP", + "S_FLICKY_15_UP", + "S_FLICKY_15_DOWN", + + // Canary + "S_FLICKY_16_OUT", + "S_FLICKY_16_FLAP1", + "S_FLICKY_16_FLAP2", + "S_FLICKY_16_FLAP3", "S_YELLOWSPRING", "S_YELLOWSPRING2", @@ -5566,6 +5858,20 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_WATERZAP", + // Spindash dust + "S_SPINDUST1", + "S_SPINDUST2", + "S_SPINDUST3", + "S_SPINDUST4", + "S_SPINDUST_BUBBLE1", + "S_SPINDUST_BUBBLE2", + "S_SPINDUST_BUBBLE3", + "S_SPINDUST_BUBBLE4", + "S_SPINDUST_FIRE1", + "S_SPINDUST_FIRE2", + "S_SPINDUST_FIRE3", + "S_SPINDUST_FIRE4", + "S_FOG1", "S_FOG2", "S_FOG3", @@ -5796,20 +6102,19 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FIREBALLEXP2", "S_FIREBALLEXP3", "S_SHELL", - "S_SHELL1", - "S_SHELL2", - "S_SHELL3", - "S_SHELL4", - "S_PUMA1", - "S_PUMA2", - "S_PUMA3", - "S_PUMA4", - "S_PUMA5", - "S_PUMA6", - "S_HAMMER1", - "S_HAMMER2", - "S_HAMMER3", - "S_HAMMER4", + "S_PUMA_START1", + "S_PUMA_START2", + "S_PUMA_UP1", + "S_PUMA_UP2", + "S_PUMA_UP3", + "S_PUMA_DOWN1", + "S_PUMA_DOWN2", + "S_PUMA_DOWN3", + "S_PUMATRAIL1", + "S_PUMATRAIL2", + "S_PUMATRAIL3", + "S_PUMATRAIL4", + "S_HAMMER", "S_KOOPA1", "S_KOOPA2", "S_KOOPAFLAME1", @@ -5938,6 +6243,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_NIGHTOPIANHELPER6", "S_NIGHTOPIANHELPER7", "S_NIGHTOPIANHELPER8", + "S_NIGHTOPIANHELPER9", "S_CRUMBLE1", "S_CRUMBLE2", @@ -5961,10 +6267,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_SPRK16", // Robot Explosion + "S_XPLD_FLICKY", "S_XPLD1", "S_XPLD2", - "S_XPLD3", - "S_XPLD4", + "S_XPLD_EGGTRAP", // Underwater Explosion "S_WPLD1", @@ -6061,6 +6367,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_BOSSTANK2", "MT_BOSSSPIGOT", "MT_GOOP", + "MT_GOOPTRAIL", // Boss 3 "MT_EGGMOBILE3", @@ -6164,6 +6471,9 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_RECYCLER_BOX", "MT_SCORE1K_BOX", "MT_SCORE10K_BOX", + "MT_FLAMEAURA_BOX", + "MT_BUBBLEWRAP_BOX", + "MT_THUNDERCOIN_BOX", // Monitor boxes -- repeating (big) boxes "MT_PITY_GOLDBOX", @@ -6176,6 +6486,9 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_INVULN_GOLDBOX", "MT_EGGMAN_GOLDBOX", "MT_GRAVITY_GOLDBOX", + "MT_FLAMEAURA_GOLDBOX", + "MT_BUBBLEWRAP_GOLDBOX", + "MT_THUNDERCOIN_GOLDBOX", // Monitor boxes -- special "MT_RING_REDBOX", @@ -6198,6 +6511,9 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_RECYCLER_ICON", "MT_SCORE1K_ICON", "MT_SCORE10K_ICON", + "MT_FLAMEAURA_ICON", + "MT_BUBBLEWRAP_ICON", + "MT_THUNDERCOIN_ICON", // Projectiles "MT_ROCKET", @@ -6221,7 +6537,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_BUSH", // Techno Hill Scenery - "MT_THZPLANT", // THZ Plant + "MT_THZFLOWER1", + "MT_THZFLOWER2", "MT_ALARM", // Deep Sea Scenery @@ -6237,6 +6554,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s // Castle Eggman Scenery "MT_CHAIN", // CEZ Chain "MT_FLAME", // Flame (has corona) + "MT_FLAMEPARTICLE", "MT_EGGSTATUE", // Eggman Statue "MT_MACEPOINT", // Mace rotation point "MT_SWINGMACEPOINT", // Mace swinging point @@ -6263,9 +6581,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_FLAMEJETFLAME", "MT_FJSPINAXISA", // Counter-clockwise - "MT_FJSPINHELPERA", "MT_FJSPINAXISB", // Clockwise - "MT_FJSPINHELPERB", "MT_FLAMEJETFLAMEB", // Blade's flame @@ -6342,30 +6658,46 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_BSZVINE_ORANGE", "MT_BSZSHRUB", "MT_BSZCLOVER", - "MT_BSZFISH", - "MT_BSZSUNFLOWER", + "MT_BIG_PALMTREE_TRUNK", + "MT_BIG_PALMTREE_TOP", + "MT_PALMTREE_TRUNK", + "MT_PALMTREE_TOP", // Misc scenery "MT_DBALL", "MT_EGGSTATUE2", // Powerup Indicators - "MT_GREENORB", // Elemental shield mobj - "MT_YELLOWORB", // Attract shield mobj - "MT_BLUEORB", // Force shield mobj - "MT_BLACKORB", // Armageddon shield mobj - "MT_WHITEORB", // Whirlwind shield mobj - "MT_PITYORB", // Pity shield mobj - "MT_IVSP", // invincibility sparkles + "MT_ELEMENTAL_ORB", // Elemental shield mobj + "MT_ATTRACT_ORB", // Attract shield mobj + "MT_FORCE_ORB", // Force shield mobj + "MT_ARMAGEDDON_ORB", // Armageddon shield mobj + "MT_WHIRLWIND_ORB", // Whirlwind shield mobj + "MT_PITY_ORB", // Pity shield mobj + "MT_FLAMEAURA_ORB", // Flame shield mobj + "MT_BUBBLEWRAP_ORB", // Bubble shield mobj + "MT_THUNDERCOIN_ORB", // Thunder shield mobj + "MT_THUNDERCOIN_SPARK", // Thunder spark + "MT_IVSP", // Invincibility sparkles "MT_SUPERSPARK", // Super Sonic Spark - // Freed Animals - "MT_BIRD", // Birdie freed! - "MT_BUNNY", // Bunny freed! - "MT_MOUSE", // Mouse - "MT_CHICKEN", // Chicken - "MT_COW", // Cow - "MT_REDBIRD", // Red Birdie in Bubble + // Flickies + "MT_FLICKY_01", // Bluebird + "MT_FLICKY_02", // Rabbit + "MT_FLICKY_03", // Chicken + "MT_FLICKY_04", // Seal + "MT_FLICKY_05", // Pig + "MT_FLICKY_06", // Chipmunk + "MT_FLICKY_07", // Penguin + "MT_FLICKY_08", // Fish + "MT_FLICKY_09", // Ram + "MT_FLICKY_10", // Puffin + "MT_FLICKY_11", // Cow + "MT_FLICKY_12", // Rat + "MT_FLICKY_13", // Bear + "MT_FLICKY_14", // Dove + "MT_FLICKY_15", // Cat + "MT_FLICKY_16", // Canary // Environmental Effects "MT_RAIN", // Rain @@ -6376,6 +6708,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_MEDIUMBUBBLE", // medium bubble "MT_EXTRALARGEBUBBLE", // extra large bubble "MT_WATERZAP", + "MT_SPINDUST", // Spindash dust "MT_TFOG", "MT_SEED", "MT_PARTICLE", @@ -6434,6 +6767,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_FIREBALL", "MT_SHELL", "MT_PUMA", + "MT_PUMATRAIL", "MT_HAMMER", "MT_KOOPA", "MT_KOOPAFLAME", @@ -6544,35 +6878,36 @@ static const char *const MOBJFLAG_LIST[] = { // \tMF2_(\S+).*// (.+) --> \t"\1", // \2 static const char *const MOBJFLAG2_LIST[] = { - "AXIS", // It's a NiGHTS axis! (For faster checking) - "TWOD", // Moves like it's in a 2D level - "DONTRESPAWN", // Don't respawn this object! - "DONTDRAW", // Don't generate a vissprite - "AUTOMATIC", // Thrown ring has automatic properties - "RAILRING", // Thrown ring has rail properties - "BOUNCERING", // Thrown ring has bounce properties - "EXPLOSION", // Thrown ring has explosive properties - "SCATTER", // Thrown ring has scatter properties - "BEYONDTHEGRAVE",// Source of this missile has died and has since respawned. - "SLIDEPUSH", // MF_PUSHABLE that pushes continuously. - "CLASSICPUSH", // Drops straight down when object has negative Z. - "STANDONME", // While not pushable, stand on me anyway. - "INFLOAT", // Floating to a height for a move, don't auto float to target's height. - "DEBRIS", // Splash ring from explosion ring - "NIGHTSPULL", // Attracted from a paraloop - "JUSTATTACKED", // can be pushed by other moving mobjs - "FIRING", // turret fire - "SUPERFIRE", // Firing something with Super Sonic-stopping properties. Or, if mobj has MF_MISSILE, this is the actual fire from it. - "SHADOW", // Fuzzy draw, makes targeting harder. - "STRONGBOX", // Flag used for "strong" random monitors. - "OBJECTFLIP", // Flag for objects that always have flipped gravity. - "SKULLFLY", // Special handling: skull in flight. - "FRET", // Flashing from a previous hit - "BOSSNOTRAP", // No Egg Trap after boss - "BOSSFLEE", // Boss is fleeing! - "BOSSDEAD", // Boss is dead! (Not necessarily fleeing, if a fleeing point doesn't exist.) - "AMBUSH", // Alternate behaviour typically set by MTF_AMBUSH - "LINKDRAW", // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position) + "AXIS", // It's a NiGHTS axis! (For faster checking) + "TWOD", // Moves like it's in a 2D level + "DONTRESPAWN", // Don't respawn this object! + "DONTDRAW", // Don't generate a vissprite + "AUTOMATIC", // Thrown ring has automatic properties + "RAILRING", // Thrown ring has rail properties + "BOUNCERING", // Thrown ring has bounce properties + "EXPLOSION", // Thrown ring has explosive properties + "SCATTER", // Thrown ring has scatter properties + "BEYONDTHEGRAVE", // Source of this missile has died and has since respawned. + "SLIDEPUSH", // MF_PUSHABLE that pushes continuously. + "CLASSICPUSH", // Drops straight down when object has negative Z. + "STANDONME", // While not pushable, stand on me anyway. + "INFLOAT", // Floating to a height for a move, don't auto float to target's height. + "DEBRIS", // Splash ring from explosion ring + "NIGHTSPULL", // Attracted from a paraloop + "JUSTATTACKED", // can be pushed by other moving mobjs + "FIRING", // turret fire + "SUPERFIRE", // Firing something with Super Sonic-stopping properties. Or, if mobj has MF_MISSILE, this is the actual fire from it. + "SHADOW", // Fuzzy draw, makes targeting harder. + "STRONGBOX", // Flag used for "strong" random monitors. + "OBJECTFLIP", // Flag for objects that always have flipped gravity. + "SKULLFLY", // Special handling: skull in flight. + "FRET", // Flashing from a previous hit + "BOSSNOTRAP", // No Egg Trap after boss + "BOSSFLEE", // Boss is fleeing! + "BOSSDEAD", // Boss is dead! (Not necessarily fleeing, if a fleeing point doesn't exist.) + "AMBUSH", // Alternate behaviour typically set by MTF_AMBUSH + "LINKDRAW", // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position) + "SHIELD", // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use) NULL }; @@ -6654,6 +6989,9 @@ static const char *const PLAYERFLAG_LIST[] = { /*** misc ***/ "FORCESTRAFE", // Translate turn inputs into strafe inputs "ANALOGMODE", // Analog mode? + "CANCARRY", // Can carry? + "SHIELDABILITY", // Thokked with shield ability + "FORCEJUMPDAMAGE", // Force jump damage NULL // stop loop here. }; @@ -6998,20 +7336,27 @@ struct { {"PRECIP_STORM_NOSTRIKES",PRECIP_STORM_NOSTRIKES}, // Shields - // These ones use the lower 8 bits {"SH_NONE",SH_NONE}, - {"SH_JUMP",SH_JUMP}, + // Shield flags + {"SH_PROTECTFIRE",SH_PROTECTFIRE}, + {"SH_PROTECTWATER",SH_PROTECTWATER}, + {"SH_PROTECTELECTRIC",SH_PROTECTELECTRIC}, + // Indivisible shields + {"SH_PITY",SH_PITY}, + {"SH_WHIRLWIND",SH_WHIRLWIND}, + {"SH_ARMAGEDDON",SH_ARMAGEDDON}, + // normal shields that use flags {"SH_ATTRACT",SH_ATTRACT}, {"SH_ELEMENTAL",SH_ELEMENTAL}, - {"SH_BOMB",SH_BOMB}, + // Sonic 3 shields + {"SH_FLAMEAURA",SH_FLAMEAURA}, {"SH_BUBBLEWRAP",SH_BUBBLEWRAP}, {"SH_THUNDERCOIN",SH_THUNDERCOIN}, - {"SH_FLAMEAURA",SH_FLAMEAURA}, - {"SH_PITY",SH_PITY}, - // These ones are special and use the upper bits - {"SH_FIREFLOWER",SH_FIREFLOWER}, // Lower bits are a normal shield stacked on top of the fire flower - {"SH_FORCE",SH_FORCE}, // Lower bits are how many hits left, 0 is the last hit - // Stack masks + // The force shield uses the lower 8 bits to count how many extra hits are left. + {"SH_FORCE",SH_FORCE}, + {"SH_FORCEHP",SH_FORCEHP}, // to be used as a bitmask only + // Mostly for use with Mario mode. + {"SH_FIREFLOWER", SH_FIREFLOWER}, {"SH_STACK",SH_STACK}, {"SH_NOSTACK",SH_NOSTACK}, @@ -7045,6 +7390,7 @@ struct { {"SF_STOMPDAMAGE",SF_STOMPDAMAGE}, {"SF_MARIODAMAGE",SF_MARIODAMAGE}, {"SF_MACHINE",SF_MACHINE}, + {"SF_NOSPINDASHDUST",SF_NOSPINDASHDUST}, // Character abilities! // Primary @@ -7093,6 +7439,22 @@ struct { {"PAL_MIXUP",PAL_MIXUP}, {"PAL_RECYCLE",PAL_RECYCLE}, {"PAL_NUKE",PAL_NUKE}, + // for P_DamageMobj + //// Damage types + {"DMG_WATER",DMG_WATER}, + {"DMG_FIRE",DMG_FIRE}, + {"DMG_ELECTRIC",DMG_ELECTRIC}, + {"DMG_SPIKE",DMG_SPIKE}, + {"DMG_NUKE",DMG_NUKE}, + //// Death types + {"DMG_INSTAKILL",DMG_INSTAKILL}, + {"DMG_DROWNED",DMG_DROWNED}, + {"DMG_SPACEDROWN",DMG_SPACEDROWN}, + {"DMG_DEATHPIT",DMG_DEATHPIT}, + {"DMG_CRUSHED",DMG_CRUSHED}, + {"DMG_SPECTATOR",DMG_SPECTATOR}, + //// Masks + {"DMG_DEATHMASK",DMG_DEATHMASK}, // Gametypes, for use with global var "gametype" {"GT_COOP",GT_COOP}, @@ -7201,6 +7563,11 @@ struct { {"FF_COLORMAPONLY",FF_COLORMAPONLY}, ///< Only copy the colormap, not the lightlevel {"FF_GOOWATER",FF_GOOWATER}, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop. +#ifdef HAVE_LUA_SEGS + // Node flags + {"NF_SUBSECTOR",NF_SUBSECTOR}, // Indicate a leaf. +#endif + // Angles {"ANG1",ANG1}, {"ANG2",ANG2}, @@ -7346,7 +7713,7 @@ static mobjtype_t get_mobjtype(const char *word) if (fastcmp(word, MOBJTYPE_LIST[i]+3)) return i; deh_warning("Couldn't find mobjtype named 'MT_%s'",word); - return MT_BLUECRAWLA; + return MT_NULL; } static statenum_t get_state(const char *word) diff --git a/src/djgppdos/i_system.c b/src/djgppdos/i_system.c index 854d68f4d..dae9ed16e 100644 --- a/src/djgppdos/i_system.c +++ b/src/djgppdos/i_system.c @@ -1721,6 +1721,18 @@ INT32 I_PutEnv(char *variable) return putenv(variable); } +INT32 I_ClipboardCopy(const char *data, size_t size) +{ + (void)data; + (void)size; + return -1; +} + +char *I_ClipboardPaste(void) +{ + return NULL; +} + const CPUInfoFlags *I_CPUInfo(void) { static CPUInfoFlags DOS_CPUInfo; diff --git a/src/doomdef.h b/src/doomdef.h index 410e740fa..a35c17ba6 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -214,7 +214,7 @@ extern FILE *logstream; // it's only for detection of the version the player is using so the MS can alert them of an update. // Only set it higher, not lower, obviously. // Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1". -#define MODVERSION 21 +#define MODVERSION 22 // ========================================================================= @@ -407,6 +407,7 @@ void M_StartupLocale(void); extern void *(*M_Memcpy)(void* dest, const void* src, size_t n) FUNCNONNULL; char *va(const char *format, ...) FUNCPRINTF; char *M_GetToken(const char *inputString); +void M_UnGetToken(void); char *sizeu1(size_t num); char *sizeu2(size_t num); char *sizeu3(size_t num); @@ -435,6 +436,9 @@ extern INT32 cv_debug; // Misc stuff for later... // ======================= +// Modifier key variables, accessible anywhere +extern UINT8 shiftdown, ctrldown, altdown; + // if we ever make our alloc stuff... #define ZZ_Alloc(x) Z_Malloc(x, PU_STATIC, NULL) diff --git a/src/doomstat.h b/src/doomstat.h index 8072a1552..f1b7d2169 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -241,6 +241,10 @@ typedef struct UINT8 levelflags; ///< LF_flags: merged eight booleans into one UINT8 for space, see below UINT8 menuflags; ///< LF2_flags: options that affect record attack / nights mode menus + // Freed animals stuff. + UINT8 numFlickies; ///< Internal. For freed flicky support. + mobjtype_t *flickies; ///< List of freeable flickies in this level. Allocated dynamically for space reasons. Be careful. + // NiGHTS stuff. UINT8 numGradedMares; ///< Internal. For grade support. nightsgrades_t *grades; ///< NiGHTS grades. Allocated dynamically for space reasons. Be careful. diff --git a/src/dummy/i_system.c b/src/dummy/i_system.c index c1e48b60b..a3fe3077c 100644 --- a/src/dummy/i_system.c +++ b/src/dummy/i_system.c @@ -162,6 +162,18 @@ INT32 I_PutEnv(char *variable) return -1; } +INT32 I_ClipboardCopy(const char *data, size_t size) +{ + (void)data; + (void)size; + return -1; +} + +char *I_ClipboardPaste(void) +{ + return NULL; +} + void I_RegisterSysCommands(void) {} #include "../sdl/dosstr.c" diff --git a/src/f_finale.c b/src/f_finale.c index 78e9ada17..167fdd880 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -974,7 +974,7 @@ static const char *credits[] = { "Scott \"Graue\" Feeney", "Nathan \"Jazz\" Giroux", "Thomas \"Shadow Hog\" Igoe", - "\"Monster\" Iestyn Jealous", + "Iestyn \"Monster Iestyn\" Jealous", "Ronald \"Furyhunter\" Kinard", // The SDL2 port "John \"JTE\" Muniz", "Ehab \"Wolfy\" Saeed", @@ -986,6 +986,7 @@ static const char *credits[] = { "\"chi.miru\"", // Red's secret weapon, the REAL reason slopes exist (also helped port drawing code from ZDoom) "Andrew \"orospakr\" Clunis", "Gregor \"Oogaland\" Dick", + "Louis-Antoine \"LJSonic\" de Moulins", // for fixing 2.1's netcode (de Rochefort doesn't quite fit on the screen sorry lol) "Vivian \"toaster\" Grannell", "Julio \"Chaos Zero 64\" Guir", "\"Kalaron\"", // Coded some of Sryder13's collection of OpenGL fixes, especially fog @@ -1021,7 +1022,7 @@ static const char *credits[] = { "Paul \"Boinciel\" Clempson", "Cyan Helkaraxe", "Kepa \"Nev3r\" Iceta", - "\"Monster\" Iestyn Jealous", + "Iestyn \"Monster Iestyn\" Jealous", "Jarel \"Arrow\" Jones", "Stefan \"Stuf\" Rimalia", "Shane Mychal Sexton", diff --git a/src/g_game.c b/src/g_game.c index 5e45921b7..5e04af496 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -88,6 +88,7 @@ UINT8 modeattacking = ATTACKING_NONE; boolean disableSpeedAdjust = false; boolean imcontinuing = false; boolean runemeraldmanager = false; +UINT16 emeraldspawndelay = 60*TICRATE; // menu demo things UINT8 numDemos = 3; @@ -2193,7 +2194,7 @@ void G_PlayerReborn(INT32 player) p->pflags |= PF_JUMPDOWN; p->playerstate = PST_LIVE; - p->health = 1; // 0 rings + p->rings = 0; // 0 rings p->panim = PA_IDLE; // standing animation if ((netgame || multiplayer) && !p->spectator) @@ -4727,7 +4728,7 @@ void G_BeginRecording(void) // Don't do it. WRITEFIXED(demo_p, player->jumpfactor); - // Save netvar data (SONICCD, etc) + // Save netvar data CV_SaveNetVars(&demo_p); memset(&oldcmd,0,sizeof(oldcmd)); diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 60183b58e..f23753ee5 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -656,6 +656,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) { FOutVector v[4]; FSurfaceInfo Surf; + float sdupx, sdupy; if (w < 0 || h < 0) return; // consistency w/ software @@ -664,10 +665,16 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) // | /| // |/ | // 0--1 - v[0].x = v[3].x = (x - 160.0f)/160.0f; - v[2].x = v[1].x = ((x+w) - 160.0f)/160.0f; - v[0].y = v[1].y = -(y - 100.0f)/100.0f; - v[2].y = v[3].y = -((y+h) - 100.0f)/100.0f; + sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f; + sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f; + + if (color & V_NOSCALESTART) + sdupx = sdupy = 2.0f; + + v[0].x = v[3].x = (x*sdupx)/vid.width - 1; + v[2].x = v[1].x = (x*sdupx + w*sdupx)/vid.width - 1; + v[0].y = v[1].y = 1-(y*sdupy)/vid.height; + v[2].y = v[3].y = 1-(y*sdupy + h*sdupy)/vid.height; //Hurdler: do we still use this argb color? if not, we should remove it v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //; diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 9e5d92e0b..cdd778caa 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -271,6 +271,9 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_TVRC &lspr[NOLIGHT], // SPR_TV1K &lspr[NOLIGHT], // SPR_TVTK + &lspr[NOLIGHT], // SPR_TVFL + &lspr[NOLIGHT], // SPR_TVBB + &lspr[NOLIGHT], // SPR_TVZP // Projectiles &lspr[NOLIGHT], // SPR_MISL @@ -293,6 +296,7 @@ light_t *t_lspr[NUMSPRITES] = // Techno Hill Scenery &lspr[NOLIGHT], // SPR_THZP + &lspr[NOLIGHT], // SPR_FWR5 &lspr[REDBALL_L], // SPR_ALRM // Deep Sea Scenery @@ -359,18 +363,32 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_ELEM &lspr[NOLIGHT], // SPR_FORC &lspr[NOLIGHT], // SPR_PITY + &lspr[NOLIGHT], // SPR_FIRS + &lspr[NOLIGHT], // SPR_BUBS + &lspr[NOLIGHT], // SPR_ZAPS &lspr[INVINCIBLE_L], // SPR_IVSP &lspr[SUPERSPARK_L], // SPR_SSPK &lspr[NOLIGHT], // SPR_GOAL - // Freed Animals - &lspr[NOLIGHT], // SPR_BIRD - &lspr[NOLIGHT], // SPR_BUNY - &lspr[NOLIGHT], // SPR_MOUS - &lspr[NOLIGHT], // SPR_CHIC - &lspr[NOLIGHT], // SPR_COWZ - &lspr[NOLIGHT], // SPR_RBRD + // Flickies + &lspr[NOLIGHT], // SPR_FBUB + &lspr[NOLIGHT], // SPR_FL01 + &lspr[NOLIGHT], // SPR_FL02 + &lspr[NOLIGHT], // SPR_FL03 + &lspr[NOLIGHT], // SPR_FL04 + &lspr[NOLIGHT], // SPR_FL05 + &lspr[NOLIGHT], // SPR_FL06 + &lspr[NOLIGHT], // SPR_FL07 + &lspr[NOLIGHT], // SPR_FL08 + &lspr[NOLIGHT], // SPR_FL09 + &lspr[NOLIGHT], // SPR_FL10 + &lspr[NOLIGHT], // SPR_FL11 + &lspr[NOLIGHT], // SPR_FL12 + &lspr[NOLIGHT], // SPR_FL13 + &lspr[NOLIGHT], // SPR_FL14 + &lspr[NOLIGHT], // SPR_FL15 + &lspr[NOLIGHT], // SPR_FL16 // Springs &lspr[NOLIGHT], // SPR_SPRY diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 270229ad0..7bc12ba75 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1558,6 +1558,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) if (gr_backsector) { + INT32 gr_toptexture, gr_bottomtexture; // two sided line if (gr_backsector->heightsec != -1) { @@ -1608,19 +1609,22 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) #endif } + gr_toptexture = R_GetTextureNum(gr_sidedef->toptexture); + gr_bottomtexture = R_GetTextureNum(gr_sidedef->bottomtexture); + // check TOP TEXTURE if (( #ifdef ESLOPE worldhighslope < worldtopslope || #endif worldhigh < worldtop - ) && texturetranslation[gr_sidedef->toptexture]) + ) && gr_toptexture) { if (drawtextured) { fixed_t texturevpegtop; // top - grTex = HWR_GetTexture(texturetranslation[gr_sidedef->toptexture]); + grTex = HWR_GetTexture(gr_toptexture); // PEGGING if (gr_linedef->flags & ML_DONTPEGTOP) @@ -1638,7 +1642,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) texturevpegtop += gr_sidedef->rowoffset; // This is so that it doesn't overflow and screw up the wall, it doesn't need to go higher than the texture's height anyway - texturevpegtop %= SHORT(textures[texturetranslation[gr_sidedef->toptexture]]->height)<<FRACBITS; + texturevpegtop %= SHORT(textures[gr_toptexture]->height)<<FRACBITS; wallVerts[3].t = wallVerts[2].t = texturevpegtop * grTex->scaleY; wallVerts[0].t = wallVerts[1].t = (texturevpegtop + gr_frontsector->ceilingheight - gr_backsector->ceilingheight) * grTex->scaleY; @@ -1683,9 +1687,9 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) #endif if (gr_frontsector->numlights) - HWR_SplitWall(gr_frontsector, wallVerts, texturetranslation[gr_sidedef->toptexture], &Surf, FF_CUTSOLIDS); + HWR_SplitWall(gr_frontsector, wallVerts, gr_toptexture, &Surf, FF_CUTSOLIDS); else if (grTex->mipmap.flags & TF_TRANSPARENT) - HWR_AddTransparentWall(wallVerts, &Surf, texturetranslation[gr_sidedef->toptexture], PF_Environment, false, lightnum, colormap); + HWR_AddTransparentWall(wallVerts, &Surf, gr_toptexture, PF_Environment, false, lightnum, colormap); else HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap); } @@ -1695,13 +1699,13 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) #ifdef ESLOPE worldlowslope > worldbottomslope || #endif - worldlow > worldbottom) && texturetranslation[gr_sidedef->bottomtexture]) //only if VISIBLE!!! + worldlow > worldbottom) && gr_bottomtexture) //only if VISIBLE!!! { if (drawtextured) { fixed_t texturevpegbottom = 0; // bottom - grTex = HWR_GetTexture(texturetranslation[gr_sidedef->bottomtexture]); + grTex = HWR_GetTexture(gr_bottomtexture); // PEGGING #ifdef ESLOPE @@ -1721,7 +1725,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) texturevpegbottom += gr_sidedef->rowoffset; // This is so that it doesn't overflow and screw up the wall, it doesn't need to go higher than the texture's height anyway - texturevpegbottom %= SHORT(textures[texturetranslation[gr_sidedef->bottomtexture]]->height)<<FRACBITS; + texturevpegbottom %= SHORT(textures[gr_bottomtexture]->height)<<FRACBITS; wallVerts[3].t = wallVerts[2].t = texturevpegbottom * grTex->scaleY; wallVerts[0].t = wallVerts[1].t = (texturevpegbottom + gr_backsector->floorheight - gr_frontsector->floorheight) * grTex->scaleY; @@ -1766,13 +1770,13 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) #endif if (gr_frontsector->numlights) - HWR_SplitWall(gr_frontsector, wallVerts, texturetranslation[gr_sidedef->bottomtexture], &Surf, FF_CUTSOLIDS); + HWR_SplitWall(gr_frontsector, wallVerts, gr_bottomtexture, &Surf, FF_CUTSOLIDS); else if (grTex->mipmap.flags & TF_TRANSPARENT) - HWR_AddTransparentWall(wallVerts, &Surf, texturetranslation[gr_sidedef->bottomtexture], PF_Environment, false, lightnum, colormap); + HWR_AddTransparentWall(wallVerts, &Surf, gr_bottomtexture, PF_Environment, false, lightnum, colormap); else HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap); } - gr_midtexture = texturetranslation[gr_sidedef->midtexture]; + gr_midtexture = R_GetTextureNum(gr_sidedef->midtexture); if (gr_midtexture) { FBITFIELD blendmode; @@ -2134,7 +2138,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) else { // Single sided line... Deal only with the middletexture (if one exists) - gr_midtexture = texturetranslation[gr_sidedef->midtexture]; + gr_midtexture = R_GetTextureNum(gr_sidedef->midtexture); if (gr_midtexture) { if (drawtextured) @@ -2232,13 +2236,13 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) if (*rover->topheight < lowcut || *rover->bottomheight > highcut) continue; - texnum = texturetranslation[sides[rover->master->sidenum[0]].midtexture]; + texnum = R_GetTextureNum(sides[rover->master->sidenum[0]].midtexture); if (rover->master->flags & ML_TFERLINE) { size_t linenum = gr_curline->linedef-gr_backsector->lines[0]; newline = rover->master->frontsector->lines[0] + linenum; - texnum = texturetranslation[sides[newline->sidenum[0]].midtexture]; + texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture); } #ifdef ESLOPE @@ -2366,13 +2370,13 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) if (*rover->topheight < lowcut || *rover->bottomheight > highcut) continue; - texnum = texturetranslation[sides[rover->master->sidenum[0]].midtexture]; + texnum = R_GetTextureNum(sides[rover->master->sidenum[0]].midtexture); if (rover->master->flags & ML_TFERLINE) { size_t linenum = gr_curline->linedef-gr_backsector->lines[0]; newline = rover->master->frontsector->lines[0] + linenum; - texnum = texturetranslation[sides[newline->sidenum[0]].midtexture]; + texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture); } #ifdef ESLOPE //backsides h = *rover->t_slope ? P_GetZAt(*rover->t_slope, v1x, v1y) : *rover->topheight; @@ -4519,8 +4523,8 @@ static void HWR_SortVisSprites(void) gr_vissprite_t *ds, *dsprev, *dsnext, *dsfirst; gr_vissprite_t *best = NULL; gr_vissprite_t unsorted; - float bestdist; - INT32 bestdispoffset; + float bestdist = 0.0f; + INT32 bestdispoffset = 0; if (!gr_visspritecount) return; diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 8ed24e654..7edf02db0 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -308,6 +308,23 @@ static md2_model_t *md2_readModel(const char *filename) model->header.numSkins = 1; +#define MD2LIMITCHECK(field, max, msgname) \ + if (field > max) \ + { \ + CONS_Alert(CONS_ERROR, "md2_readModel: %s has too many " msgname " (# found: %d, maximum: %d)\n", filename, field, max); \ + md2_freeModel (model); \ + return 0; \ + } + + // Uncomment if these are actually needed +// MD2LIMITCHECK(model->header.numSkins, MD2_MAX_SKINS, "skins") +// MD2LIMITCHECK(model->header.numTexCoords, MD2_MAX_TEXCOORDS, "texture coordinates") + MD2LIMITCHECK(model->header.numTriangles, MD2_MAX_TRIANGLES, "triangles") + MD2LIMITCHECK(model->header.numFrames, MD2_MAX_FRAMES, "frames") + MD2LIMITCHECK(model->header.numVertices, MD2_MAX_VERTICES, "vertices") + +#undef MD2LIMITCHECK + // read skins fseek(file, model->header.offsetSkins, SEEK_SET); if (model->header.numSkins > 0) @@ -319,8 +336,6 @@ static md2_model_t *md2_readModel(const char *filename) md2_freeModel (model); return 0; } - - ; } // read texture coordinates @@ -334,8 +349,6 @@ static md2_model_t *md2_readModel(const char *filename) md2_freeModel (model); return 0; } - - } // read triangles @@ -769,6 +782,7 @@ void HWR_InitMD2(void) md2_playermodels[s].grpatch = NULL; md2_playermodels[s].skin = -1; md2_playermodels[s].notfound = true; + md2_playermodels[s].error = false; } for (i = 0; i < NUMSPRITES; i++) { @@ -777,6 +791,7 @@ void HWR_InitMD2(void) md2_models[i].grpatch = NULL; md2_models[i].skin = -1; md2_models[i].notfound = true; + md2_models[i].error = false; } // read the md2.dat file @@ -1378,6 +1393,8 @@ void HWR_DrawMD2(gr_vissprite_t *spr) else md2 = &md2_models[spr->mobj->sprite]; + if (md2->error) + return; // we already failed loading this before :( if (!md2->model) { //CONS_Debug(DBG_RENDER, "Loading MD2... (%s)", sprnames[spr->mobj->sprite]); @@ -1391,6 +1408,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) else { //CONS_Debug(DBG_RENDER, " FAILED\n"); + md2->error = true; // prevent endless fail return; } } diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h index 36078268b..5a7e6d2b3 100644 --- a/src/hardware/hw_md2.h +++ b/src/hardware/hw_md2.h @@ -123,6 +123,7 @@ typedef struct void *blendgrpatch; boolean notfound; INT32 skin; + boolean error; } md2_t; extern md2_t md2_models[NUMSPRITES]; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index ec747305e..01d4ed524 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -470,7 +470,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) boolean action = false; char *ptr; - CONS_Debug(DBG_NETPLAY,"Recieved SAY cmd from Player %d (%s)\n", playernum+1, player_names[playernum]); + CONS_Debug(DBG_NETPLAY,"Received SAY cmd from Player %d (%s)\n", playernum+1, player_names[playernum]); target = READSINT8(*p); flags = READUINT8(*p); @@ -757,15 +757,8 @@ void HU_clearChatChars(void) // boolean HU_Responder(event_t *ev) { - static boolean shiftdown = false; UINT8 c; - if (ev->data1 == KEY_LSHIFT || ev->data1 == KEY_RSHIFT) - { - shiftdown = (ev->type == ev_keydown); - return chat_on; - } - if (ev->type != ev_keydown) return false; @@ -797,6 +790,14 @@ boolean HU_Responder(event_t *ev) } else // if chat_on { + // Ignore modifier keys + // Note that we do this here so users can still set + // their chat keys to one of these, if they so desire. + if (ev->data1 == KEY_LSHIFT || ev->data1 == KEY_RSHIFT + || ev->data1 == KEY_LCTRL || ev->data1 == KEY_RCTRL + || ev->data1 == KEY_LALT || ev->data1 == KEY_RALT) + return true; + c = (UINT8)ev->data1; // use console translations @@ -1101,7 +1102,19 @@ void HU_Drawer(void) // draw desynch text if (hu_resynching) - V_DrawCenteredString(BASEVIDWIDTH/2, 180, V_YELLOWMAP, "Resynching..."); + { + static UINT32 resynch_ticker = 0; + char resynch_text[14]; + UINT32 i; + + // Animate the dots + resynch_ticker++; + strcpy(resynch_text, "Resynching"); + for (i = 0; i < (resynch_ticker / 16) % 4; i++) + strcat(resynch_text, "."); + + V_DrawCenteredString(BASEVIDWIDTH/2, 180, V_YELLOWMAP | V_ALLOWLOWERCASE, resynch_text); + } } //====================================================================== @@ -1198,7 +1211,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I V_DrawString(x + 20, y, ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) - | ((players[tab[i].num].health > 0) ? 0 : V_60TRANS) + | ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_60TRANS) | V_ALLOWLOWERCASE, tab[i].name); // Draw emeralds @@ -1208,7 +1221,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].health <= 0) + if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0) V_DrawSmallTranslucentPatch (x, y-4, V_80TRANS, livesback); else V_DrawSmallScaledPatch (x, y-4, 0, livesback); @@ -1220,7 +1233,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I V_DrawSmallScaledPatch(x, y-4, 0, superprefix[players[tab[i].num].skin]); else { - if (players[tab[i].num].health <= 0) + if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0) 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]); @@ -1236,7 +1249,7 @@ 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].health <= 0) + if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0) 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); @@ -1244,10 +1257,10 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I } if (G_GametypeUsesLives()) //show lives - V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE|((players[tab[i].num].health > 0) ? 0 : V_60TRANS), va("%dx", players[tab[i].num].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)); else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT) { - if (players[tab[i].num].health <= 0) + if (players[tab[i].num].mo && players[tab[i].num].mo->health <= 0) V_DrawSmallTranslucentPatch(x-32, y-4, V_60TRANS, tagico); else V_DrawSmallScaledPatch(x-32, y-4, 0, tagico); @@ -1260,13 +1273,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].health > 0) ? 0 : V_60TRANS), va("%u", tab[i].count)); + 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)); } else - V_DrawRightAlignedString(x+240, y, ((players[tab[i].num].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, ((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))); } else - V_DrawRightAlignedString(x+240, y, ((players[tab[i].num].health > 0) ? 0 : V_60TRANS), va("%u", tab[i].count)); + 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)); y += 16; } @@ -1311,7 +1324,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) strlcpy(name, tab[i].name, 9); V_DrawString(x + 20, y, ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) - | ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT) + | ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_TRANSLUCENT) | V_ALLOWLOWERCASE, name); if (gametype == GT_CTF) @@ -1337,12 +1350,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].health <= 0) + 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); else V_DrawSmallMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap); } - V_DrawRightAlignedThinString(x+120, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); + 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)); } } @@ -1367,7 +1380,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline strlcpy(name, tab[i].name, 9); V_DrawString(x + 20, y, ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) - | ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT) + | ((players[tab[i].num].mo && players[tab[i].num].mo->health > 0) ? 0 : V_TRANSLUCENT) | V_ALLOWLOWERCASE, name); if (G_GametypeUsesLives()) //show lives @@ -1390,7 +1403,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline V_DrawSmallScaledPatch (x, y-4, 0, superprefix[players[tab[i].num].skin]); else { - if (players[tab[i].num].health <= 0) + 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]); else V_DrawSmallScaledPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin]); @@ -1406,7 +1419,7 @@ 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].health <= 0) + 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); else V_DrawSmallMappedPatch (x, y-4, 0, faceprefix[players[tab[i].num].skin], colormap); @@ -1421,13 +1434,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].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); + 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)); } else - V_DrawRightAlignedThinString(x+156, y, ((players[tab[i].num].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, ((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))); } else - V_DrawRightAlignedThinString(x+120, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); + 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)); y += 16; if (y > 160) diff --git a/src/i_net.h b/src/i_net.h index e378f5723..2bfa5eac7 100644 --- a/src/i_net.h +++ b/src/i_net.h @@ -85,7 +85,7 @@ extern doomcom_t *doomcom; /** \brief return packet in doomcom struct */ -extern void (*I_NetGet)(void); +extern boolean (*I_NetGet)(void); /** \brief ask to driver if there is data waiting */ diff --git a/src/i_system.h b/src/i_system.h index c161851e0..d61f2d16e 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -296,6 +296,14 @@ char *I_GetEnv(const char *name); INT32 I_PutEnv(char *variable); +/** \brief Put data in system clipboard +*/ +INT32 I_ClipboardCopy(const char *data, size_t size); + +/** \brief Retrieve data from system clipboard +*/ +const char *I_ClipboardPaste(void); + void I_RegisterSysCommands(void); #endif diff --git a/src/i_tcp.c b/src/i_tcp.c index f6212458b..c65a536a8 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -179,6 +179,7 @@ static UINT8 UPNP_support = TRUE; #include "i_system.h" #include "i_net.h" #include "d_net.h" +#include "d_netfil.h" #include "i_tcp.h" #include "m_argv.h" @@ -482,21 +483,12 @@ static boolean SOCK_cmpaddr(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask) return false; } -static SINT8 getfreenode(void) -{ - SINT8 j; - - for (j = 0; j < MAXNETNODES; j++) - if (!nodeconnected[j]) - { - nodeconnected[j] = true; - return j; - } - return -1; -} - // This is a hack. For some reason, nodes aren't being freed properly. // This goes through and cleans up what nodes were supposed to be freed. +/** \warning This function causes the file downloading to stop if someone joins. + * How? Because it removes nodes that are connected but not in game, + * which is exactly what clients downloading a file are. + */ static void cleanupnodes(void) { SINT8 j; @@ -506,13 +498,81 @@ static void cleanupnodes(void) // Why can't I start at zero? for (j = 1; j < MAXNETNODES; j++) + //if (!(nodeingame[j] || SV_SendingFile(j))) if (!nodeingame[j]) nodeconnected[j] = false; } + +static SINT8 getfreenode(void) +{ + SINT8 j; + + cleanupnodes(); + + for (j = 0; j < MAXNETNODES; j++) + if (!nodeconnected[j]) + { + nodeconnected[j] = true; + return j; + } + + /** \warning No free node? Just in case a node might not have been freed properly, + * look if there are connected nodes that aren't in game, and forget them. + * It's dirty, and might result in a poor guy having to restart + * downloading a needed wad, but it's better than not letting anyone join... + */ + /*I_Error("No more free nodes!!1!11!11!!1111\n"); + for (j = 1; j < MAXNETNODES; j++) + if (!nodeingame[j]) + return j;*/ + + return -1; +} + +#ifdef _DEBUG +void Command_Numnodes(void) +{ + INT32 connected = 0; + INT32 ingame = 0; + INT32 i; + + for (i = 1; i < MAXNETNODES; i++) + { + if (!(nodeconnected[i] || nodeingame[i])) + continue; + + if (nodeconnected[i]) + connected++; + if (nodeingame[i]) + ingame++; + + CONS_Printf("%2d - ", i); + if (nodetoplayer[i] != -1) + CONS_Printf("player %.2d", nodetoplayer[i]); + else + CONS_Printf(" "); + if (nodeconnected[i]) + CONS_Printf(" - connected"); + else + CONS_Printf(" - "); + if (nodeingame[i]) + CONS_Printf(" - ingame"); + else + CONS_Printf(" - "); + CONS_Printf(" - %s\n", I_GetNodeAddress(i)); + } + + CONS_Printf("\n" + "Connected: %d\n" + "Ingame: %d\n", + connected, ingame); +} +#endif #endif #ifndef NONET -static void SOCK_Get(void) +// Returns true if a packet was received from a new node, false in all other cases +static boolean SOCK_Get(void) { size_t i, n; int j; @@ -535,13 +595,12 @@ static void SOCK_Get(void) doomcom->remotenode = (INT16)j; // good packet from a game player doomcom->datalength = (INT16)c; nodesocket[j] = mysockets[n]; - return; + return false; } } // not found // find a free slot - cleanupnodes(); j = getfreenode(); if (j > 0) { @@ -564,14 +623,15 @@ static void SOCK_Get(void) } if (i == numbans) SOCK_bannednode[j] = false; - return; + return true; } else DEBFILE("New node detected: No more free slots\n"); - } } + doomcom->remotenode = -1; // no packet + return false; } #endif @@ -1256,7 +1316,6 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) gaie = I_getaddrinfo(address, port, &hints, &ai); if (gaie == 0) { - cleanupnodes(); newnode = getfreenode(); } if (newnode == -1) diff --git a/src/info.c b/src/info.c index 9fb442883..fdea617c1 100644 --- a/src/info.c +++ b/src/info.c @@ -159,6 +159,9 @@ char sprnames[NUMSPRITES + 1][5] = "TVRC", // ReCycler "TV1K", // 1,000 points (1 K) "TVTK", // 10,000 points (Ten K) + "TVFL", // FLame shield + "TVBB", // BuBble shield + "TVZP", // Thunder shield (ZaP) // Projectiles "MISL", @@ -181,6 +184,7 @@ char sprnames[NUMSPRITES + 1][5] = // Techno Hill Scenery "THZP", // Techno Hill Zone Plant + "FWR5", // Another one "ALRM", // THZ2 Alarm // Deep Sea Scenery @@ -243,18 +247,32 @@ char sprnames[NUMSPRITES + 1][5] = "ELEM", // Elemental Shield Orb and Fire "FORC", // Force Shield Orb "PITY", // Pity Shield Orb + "FIRS", // Flame Shield Orb + "BUBS", // Bubble Shield Orb + "ZAPS", // Thunder Shield Orb "IVSP", // invincibility sparkles "SSPK", // Super Sonic Spark "GOAL", // Special Stage goal (here because lol NiGHTS) - // Freed Animals - "BIRD", // Birdie freed! - "BUNY", // Bunny freed! - "MOUS", // Mouse - "CHIC", // Chicken - "COWZ", // Cow - "RBRD", // Red Birdie in Bubble + // Flickies + "FBUB", // Flicky-sized bubble + "FL01", // Bluebird + "FL02", // Rabbit + "FL03", // Chicken + "FL04", // Seal + "FL05", // Pig + "FL06", // Chipmunk + "FL07", // Penguin + "FL08", // Fish + "FL09", // Ram + "FL10", // Puffin + "FL11", // Cow + "FL12", // Rat + "FL13", // Bear + "FL14", // Dove + "FL15", // Cat + "FL16", // Canary // Springs "SPRY", // yellow spring @@ -274,6 +292,8 @@ char sprnames[NUMSPRITES + 1][5] = "SMOK", "BUBL", // Bubble "WZAP", + "DUST", // Spindash dust + "FPRT", // Spindash dust (flame) "TFOG", // Teleport Fog "SEED", // Sonic CD flower seed "PRTL", // Particle (for fans, etc.) @@ -479,32 +499,32 @@ state_t states[NUMSTATES] = {SPR_THOK, FF_TRANS50, 8, {NULL}, 0, 0, S_NULL}, // S_THOK // Player - {SPR_PLAY, SPR2_STND, 105, {NULL}, 0, 0, S_PLAY_WAIT}, // S_PLAY_STND - {SPR_PLAY, SPR2_WAIT, 16, {NULL}, 0, 0, S_PLAY_WAIT}, // S_PLAY_WAIT - {SPR_PLAY, SPR2_WALK, 4, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_WALK - {SPR_PLAY, SPR2_RUN , 2, {NULL}, 0, 0, S_PLAY_RUN}, // S_PLAY_RUN - {SPR_PLAY, SPR2_PEEL, 2, {NULL}, 0, 0, S_PLAY_PEEL}, // S_PLAY_PEEL - {SPR_PLAY, SPR2_PAIN, 350, {NULL}, 0, 0, S_PLAY_FALL}, // S_PLAY_PAIN - {SPR_PLAY, SPR2_DEAD, 4, {NULL}, 0, 0, S_PLAY_DEAD}, // S_PLAY_DEAD - {SPR_PLAY, SPR2_DRWN, 4, {NULL}, 0, 0, S_PLAY_DRWN}, // S_PLAY_DRWN - {SPR_PLAY, SPR2_SPIN, 1, {NULL}, 0, 0, S_PLAY_SPIN}, // S_PLAY_SPIN - {SPR_PLAY, SPR2_DASH, 2, {NULL}, 0, 0, S_PLAY_DASH}, // S_PLAY_DASH - {SPR_PLAY, SPR2_GASP, 14, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_GASP - {SPR_PLAY, SPR2_JUMP, 1, {NULL}, 0, 0, S_PLAY_JUMP}, // S_PLAY_JUMP - {SPR_PLAY, SPR2_SPNG, 2, {NULL}, 0, 0, S_PLAY_SPRING}, // S_PLAY_SPRING - {SPR_PLAY, SPR2_FALL, 2, {NULL}, 0, 0, S_PLAY_FALL}, // S_PLAY_FALL - {SPR_PLAY, SPR2_EDGE, 12, {NULL}, 0, 0, S_PLAY_EDGE}, // S_PLAY_EDGE - {SPR_PLAY, SPR2_RIDE, 4, {NULL}, 0, 0, S_PLAY_RIDE}, // S_PLAY_RIDE + {SPR_PLAY, SPR2_STND|FF_ANIMATE, 105, {NULL}, 0, 7, S_PLAY_WAIT}, // S_PLAY_STND + {SPR_PLAY, SPR2_WAIT|FF_ANIMATE, -1, {NULL}, 0, 16, S_NULL}, // S_PLAY_WAIT + {SPR_PLAY, SPR2_WALK, 4, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_WALK + {SPR_PLAY, SPR2_RUN , 2, {NULL}, 0, 0, S_PLAY_RUN}, // S_PLAY_RUN + {SPR_PLAY, SPR2_PEEL, 2, {NULL}, 0, 0, S_PLAY_PEEL}, // S_PLAY_PEEL + {SPR_PLAY, SPR2_PAIN|FF_ANIMATE, 350, {NULL}, 0, 4, S_PLAY_FALL}, // S_PLAY_PAIN + {SPR_PLAY, SPR2_DEAD|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL}, // S_PLAY_DEAD + {SPR_PLAY, SPR2_DRWN|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL}, // S_PLAY_DRWN + {SPR_PLAY, SPR2_SPIN, 1, {NULL}, 0, 0, S_PLAY_SPIN}, // S_PLAY_SPIN + {SPR_PLAY, SPR2_DASH, 2, {NULL}, 0, 0, S_PLAY_DASH}, // S_PLAY_DASH + {SPR_PLAY, SPR2_GASP|FF_ANIMATE, 14, {NULL}, 0, 4, S_PLAY_WALK}, // S_PLAY_GASP + {SPR_PLAY, SPR2_JUMP, 1, {NULL}, 0, 0, S_PLAY_JUMP}, // S_PLAY_JUMP + {SPR_PLAY, SPR2_SPNG, 2, {NULL}, 0, 0, S_PLAY_SPRING}, // S_PLAY_SPRING + {SPR_PLAY, SPR2_FALL, 2, {NULL}, 0, 0, S_PLAY_FALL}, // S_PLAY_FALL + {SPR_PLAY, SPR2_EDGE|FF_ANIMATE, -1, {NULL}, 0, 12, S_NULL}, // S_PLAY_EDGE + {SPR_PLAY, SPR2_RIDE, 4, {NULL}, 0, 0, S_PLAY_RIDE}, // S_PLAY_RIDE // CA_FLY/CA_SWIM - {SPR_PLAY, SPR2_FLY , 2, {NULL}, 0, 0, S_PLAY_FLY}, // S_PLAY_FLY - {SPR_PLAY, SPR2_SWIM, 2, {NULL}, 0, 0, S_PLAY_SWIM}, // S_PLAY_SWIM - {SPR_PLAY, SPR2_TIRE, 12, {NULL}, 0, 0, S_PLAY_FLY_TIRED}, // S_PLAY_FLY_TIRED + {SPR_PLAY, SPR2_FLY , 2, {NULL}, 0, 0, S_PLAY_FLY}, // S_PLAY_FLY + {SPR_PLAY, SPR2_SWIM, 2, {NULL}, 0, 0, S_PLAY_SWIM}, // S_PLAY_SWIM + {SPR_PLAY, SPR2_TIRE, 12, {NULL}, 0, 0, S_PLAY_FLY_TIRED}, // S_PLAY_FLY_TIRED // CA_GLIDEANDCLIMB - {SPR_PLAY, SPR2_GLID, 2, {NULL}, 0, 0, S_PLAY_GLIDE}, // S_PLAY_GLIDE - {SPR_PLAY, SPR2_CLNG, 6, {NULL}, 0, 0, S_PLAY_CLING}, // S_PLAY_CLING - {SPR_PLAY, SPR2_CLMB, 5, {NULL}, 0, 0, S_PLAY_CLIMB}, // S_PLAY_CLIMB + {SPR_PLAY, SPR2_GLID, 2, {NULL}, 0, 0, S_PLAY_GLIDE}, // S_PLAY_GLIDE + {SPR_PLAY, SPR2_CLNG|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL}, // S_PLAY_CLING + {SPR_PLAY, SPR2_CLMB, 5, {NULL}, 0, 0, S_PLAY_CLIMB}, // S_PLAY_CLIMB // CA_TWINSPIN {SPR_PLAY, SPR2_TWIN|FF_SPR2ENDSTATE, 1, {NULL}, S_PLAY_JUMP, 0, S_PLAY_TWINSPIN}, // S_PLAY_TWINSPIN @@ -514,33 +534,33 @@ state_t states[NUMSTATES] = {SPR_PLAY, SPR2_MLEE, 20, {NULL}, 0, 0, S_PLAY_FALL}, // S_PLAY_MELEE_FINISH // SF_SUPERANIMS - {SPR_PLAY, SPR2_SSTD, 7, {NULL}, 0, 0, S_PLAY_SUPER_STND}, // S_PLAY_SUPER_STND - {SPR_PLAY, SPR2_SWLK, 7, {NULL}, 0, 0, S_PLAY_SUPER_WALK}, // S_PLAY_SUPER_WALK - {SPR_PLAY, SPR2_SRUN, 7, {NULL}, 0, 0, S_PLAY_SUPER_RUN}, // S_PLAY_SUPER_RUN - {SPR_PLAY, SPR2_SPEE, 7, {NULL}, 0, 0, S_PLAY_SUPER_PEEL}, // S_PLAY_SUPER_PEEL - {SPR_PLAY, SPR2_SPAN, -1, {NULL}, 0, 0, S_PLAY_SUPER_STND}, // S_PLAY_SUPER_PAIN - {SPR_PLAY, SPR2_SSTN, -1, {NULL}, 0, 0, S_PLAY_SUPER_STND}, // S_PLAY_SUPER_STUN - {SPR_PLAY, SPR2_SDTH, 4, {NULL}, 0, 0, S_PLAY_SUPER_DEAD}, // S_PLAY_SUPER_DEAD - {SPR_PLAY, SPR2_SDRN, 4, {NULL}, 0, 0, S_PLAY_SUPER_DRWN}, // S_PLAY_SUPER_DRWN - {SPR_PLAY, SPR2_SSPN, 1, {NULL}, 0, 0, S_PLAY_SUPER_SPIN}, // S_PLAY_SUPER_SPIN - {SPR_PLAY, SPR2_SGSP, 14, {NULL}, 0, 0, S_PLAY_SUPER_WALK}, // S_PLAY_SUPER_GASP - {SPR_PLAY, SPR2_SJMP, 1, {NULL}, 0, 0, S_PLAY_SUPER_JUMP}, // S_PLAY_SUPER_JUMP - {SPR_PLAY, SPR2_SSPG, 2, {NULL}, 0, 0, S_PLAY_SUPER_SPRING}, // S_PLAY_SUPER_SPRING - {SPR_PLAY, SPR2_SFAL, 2, {NULL}, 0, 0, S_PLAY_SUPER_FALL}, // S_PLAY_SUPER_FALL - {SPR_PLAY, SPR2_SEDG, 12, {NULL}, 0, 0, S_PLAY_SUPER_EDGE}, // S_PLAY_SUPER_EDGE - {SPR_PLAY, SPR2_SRID, 4, {NULL}, 0, 0, S_PLAY_SUPER_RIDE}, // S_PLAY_SUPER_RIDE - {SPR_PLAY, SPR2_SFLT, 7, {NULL}, 0, 0, S_PLAY_SUPER_FLOAT}, // S_PLAY_SUPER_FLOAT + {SPR_PLAY, SPR2_SSTD|FF_ANIMATE, -1, {NULL}, 0, 7, S_NULL}, // S_PLAY_SUPER_STND + {SPR_PLAY, SPR2_SWLK, 7, {NULL}, 0, 0, S_PLAY_SUPER_WALK}, // S_PLAY_SUPER_WALK + {SPR_PLAY, SPR2_SRUN, 7, {NULL}, 0, 0, S_PLAY_SUPER_RUN}, // S_PLAY_SUPER_RUN + {SPR_PLAY, SPR2_SPEE, 7, {NULL}, 0, 0, S_PLAY_SUPER_PEEL}, // S_PLAY_SUPER_PEEL + {SPR_PLAY, SPR2_SPAN|FF_ANIMATE, 350, {NULL}, 0, 4, S_PLAY_SUPER_FALL}, // S_PLAY_SUPER_PAIN + {SPR_PLAY, SPR2_SSTN|FF_ANIMATE, 350, {NULL}, 0, 4, S_PLAY_SUPER_FALL}, // S_PLAY_SUPER_STUN + {SPR_PLAY, SPR2_SDTH|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL}, // S_PLAY_SUPER_DEAD + {SPR_PLAY, SPR2_SDRN|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL}, // S_PLAY_SUPER_DRWN + {SPR_PLAY, SPR2_SSPN, 1, {NULL}, 0, 0, S_PLAY_SUPER_SPIN}, // S_PLAY_SUPER_SPIN + {SPR_PLAY, SPR2_SGSP|FF_ANIMATE, 14, {NULL}, 0, 4, S_PLAY_SUPER_WALK}, // S_PLAY_SUPER_GASP + {SPR_PLAY, SPR2_SJMP, 1, {NULL}, 0, 0, S_PLAY_SUPER_JUMP}, // S_PLAY_SUPER_JUMP + {SPR_PLAY, SPR2_SSPG, 2, {NULL}, 0, 0, S_PLAY_SUPER_SPRING}, // S_PLAY_SUPER_SPRING + {SPR_PLAY, SPR2_SFAL, 2, {NULL}, 0, 0, S_PLAY_SUPER_FALL}, // S_PLAY_SUPER_FALL + {SPR_PLAY, SPR2_SEDG|FF_ANIMATE, -1, {NULL}, 0, 12, S_NULL}, // S_PLAY_SUPER_EDGE + {SPR_PLAY, SPR2_SRID, 4, {NULL}, 0, 0, S_PLAY_SUPER_RIDE}, // S_PLAY_SUPER_RIDE + {SPR_PLAY, SPR2_SFLT, 7, {NULL}, 0, 0, S_PLAY_SUPER_FLOAT}, // S_PLAY_SUPER_FLOAT // SF_SUPER - {SPR_PLAY, SPR2_TRNS, 4, {NULL}, 0, 0, S_PLAY_SUPER_TRANS2}, // S_PLAY_SUPER_TRANS - {SPR_PLAY, SPR2_TRNS, 4, {NULL}, 0, 0, S_PLAY_SUPER_TRANS3}, // S_PLAY_SUPER_TRANS2 - {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 4, {NULL}, 0, 0, S_PLAY_SUPER_TRANS4}, // S_PLAY_SUPER_TRANS3 - {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS5}, // S_PLAY_SUPER_TRANS4 - {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS6}, // S_PLAY_SUPER_TRANS5 - {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS7}, // S_PLAY_SUPER_TRANS6 - {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS8}, // S_PLAY_SUPER_TRANS7 - {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS9}, // S_PLAY_SUPER_TRANS8 - {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 16, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_SUPER_TRANS9 + {SPR_PLAY, SPR2_TRNS, 4, {NULL}, 0, 0, S_PLAY_SUPER_TRANS2}, // S_PLAY_SUPER_TRANS + {SPR_PLAY, SPR2_TRNS, 4, {NULL}, 0, 0, S_PLAY_SUPER_TRANS3}, // S_PLAY_SUPER_TRANS2 + {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 4, {NULL}, 0, 0, S_PLAY_SUPER_TRANS4}, // S_PLAY_SUPER_TRANS3 + {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS5}, // S_PLAY_SUPER_TRANS4 + {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS6}, // S_PLAY_SUPER_TRANS5 + {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS7}, // S_PLAY_SUPER_TRANS6 + {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS8}, // S_PLAY_SUPER_TRANS7 + {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS9}, // S_PLAY_SUPER_TRANS8 + {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 16, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_SUPER_TRANS9 {SPR_NULL, 0, -1, {NULL}, 0, 0, S_OBJPLACE_DUMMY}, //S_OBJPLACE_DUMMY @@ -971,9 +991,10 @@ state_t states[NUMSTATES] = {SPR_SPNK, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSSPIGOT // Boss 2 Goop - {SPR_GOOP, 0, 2, {NULL}, 0, 0, S_GOOP2}, // S_GOOP1 - {SPR_GOOP, 1, 2, {NULL}, 0, 0, S_GOOP1}, // S_GOOP2 - {SPR_GOOP, 2,-1, {NULL}, 0, 0, S_NULL}, // S_GOOP3 + {SPR_GOOP, 0, 2, {A_SpawnObjectRelative}, 0, MT_GOOPTRAIL, S_GOOP2}, // S_GOOP1 + {SPR_GOOP, 1, 2, {A_SpawnObjectRelative}, 0, MT_GOOPTRAIL, S_GOOP1}, // S_GOOP2 + {SPR_GOOP, 2, -1, {NULL}, 0, 0, S_NULL}, // S_GOOP3 + {SPR_GOOP, FF_ANIMATE|3, 11, {NULL}, 2, 6, S_NULL}, // S_GOOPTRAIL // Boss 3 {SPR_EGGO, 0, 1, {NULL}, 0, 0, S_EGGMOBILE3_STND}, // S_EGGMOBILE3_STND @@ -1225,12 +1246,12 @@ state_t states[NUMSTATES] = {SPR_RCKT, 2 + FF_FULLBRIGHT, 6, {A_NapalmScatter}, MT_CYBRAKDEMON_NAPALM_FLAMES + (6<<16), 32 + (16<<16), S_CYBRAKDEMONMISSILE_EXPLODE3}, // S_CYBRAKDEMONMISSILE_EXPLODE2 {SPR_RCKT, 3 + FF_FULLBRIGHT, 4, {NULL}, 0, 0, S_NULL}, // S_CYBRAKDEMONMISSILE_EXPLODE3 - {SPR_FLME, FF_TRANS50|FF_FULLBRIGHT , 15, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY2}, // S_CYBRAKDEMONFLAMESHOT_FLY1 - {SPR_FLME, FF_TRANS50|FF_FULLBRIGHT|1, 15, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY3}, // S_CYBRAKDEMONFLAMESHOT_FLY2 - {SPR_FLME, FF_TRANS50|FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY3}, // S_CYBRAKDEMONFLAMESHOT_FLY3 - {SPR_FLME, FF_TRANS50|FF_FULLBRIGHT|2, 0, {A_SpawnObjectRelative}, 0, MT_CYBRAKDEMON_FLAMEREST, S_NULL}, // S_CYBRAKDEMONFLAMESHOT_DIE + {SPR_FLME, FF_TRANS20|FF_FULLBRIGHT , 15, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY2}, // S_CYBRAKDEMONFLAMESHOT_FLY1 + {SPR_FLME, FF_TRANS20|FF_FULLBRIGHT|1, 15, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY3}, // S_CYBRAKDEMONFLAMESHOT_FLY2 + {SPR_FLME, FF_TRANS20|FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY3}, // S_CYBRAKDEMONFLAMESHOT_FLY3 + {SPR_FLME, FF_TRANS20|FF_FULLBRIGHT|2, 0, {A_SpawnObjectRelative}, 0, MT_CYBRAKDEMON_FLAMEREST, S_NULL}, // S_CYBRAKDEMONFLAMESHOT_DIE - {SPR_FLAM, FF_TRANS50|FF_FULLBRIGHT|3, 3, {A_SetFuse}, 10*TICRATE, 0, S_FLAME1}, // S_CYBRAKDEMONFLAMEREST + {SPR_FLAM, FF_TRANS20|FF_FULLBRIGHT|5, 3, {A_SetFuse}, 10*TICRATE, 0, S_FLAMEREST}, // S_CYBRAKDEMONFLAMEREST {SPR_ELEC, 0 + FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_INIT2}, // S_CYBRAKDEMONELECTRICBARRIER_INIT1 {SPR_ELEC, 0 + FF_FULLBRIGHT, 0, {A_RemoteAction}, -1, S_CYBRAKDEMON_INVINCIBLERIZE, S_CYBRAKDEMONELECTRICBARRIER_PLAYSOUND}, // S_CYBRAKDEMONELECTRICBARRIER_INIT2 @@ -1532,7 +1553,7 @@ state_t states[NUMSTATES] = {SPR_SPIK, 6, 1, {A_RotateSpikeBall}, 0, 0, S_SPIKEBALL8}, // S_SPIKEBALL7 {SPR_SPIK, 7, 1, {A_RotateSpikeBall}, 0, 0, S_SPIKEBALL1}, // S_SPIKEBALL8 - // Red Shield's Spawn + // Elemental Shield's Spawn {SPR_SFLM, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SPINFIRE2}, // S_SPINFIRE1 {SPR_SFLM, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_SPINFIRE3}, // S_SPINFIRE2 {SPR_SFLM, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_SPINFIRE4}, // S_SPINFIRE3 @@ -1551,9 +1572,11 @@ state_t states[NUMSTATES] = {SPR_USPK, 2,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED2 // Starpost - {SPR_STPT, 0 , -1, {NULL}, 0, 0, S_NULL}, // S_STARPOST_IDLE - {SPR_STPT, FF_ANIMATE , -1, {NULL}, 1, 2, S_NULL}, // S_STARPOST_FLASH - {SPR_STPT, FF_ANIMATE|2, 31, {NULL}, 15, 1, S_STARPOST_FLASH}, // S_STARPOST_SPIN + {SPR_STPT, 0 , -1, {NULL}, 0, 0, S_NULL}, // S_STARPOST_IDLE + {SPR_STPT, FF_ANIMATE|17, -1, {NULL}, 5, 1, S_NULL}, // S_STARPOST_FLASH + {SPR_STPT, FF_ANIMATE|13, 2, {NULL}, 1, 1, S_STARPOST_SPIN}, // S_STARPOST_STARTSPIN + {SPR_STPT, FF_ANIMATE|1 , 23, {NULL}, 11, 1, S_STARPOST_ENDSPIN}, // S_STARPOST_SPIN + {SPR_STPT, FF_ANIMATE|15, 2, {NULL}, 1, 1, S_STARPOST_FLASH}, // S_STARPOST_ENDSPIN // Big floating mine {SPR_BMNE, 0, 5, {NULL}, 0, 0, S_BIGMINE2}, // S_BIGMINE1 @@ -1606,6 +1629,9 @@ state_t states[NUMSTATES] = {SPR_TVRC, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_RECYCLER_BOX {SPR_TV1K, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_SCORE1K_BOX {SPR_TVTK, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_SCORE10K_BOX + {SPR_TVFL, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_FLAMEAURA_BOX + {SPR_TVBB, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_BUBBLEWRAP_BOX + {SPR_TVZP, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_THUNDERCOIN_BOX // Gold Repeat Monitor States (one per box) {SPR_TVPI, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_PITY_GOLDBOX @@ -1618,6 +1644,9 @@ state_t states[NUMSTATES] = {SPR_TVIV, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_INVULN_GOLDBOX {SPR_TVEG, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_EGGMAN_GOLDBOX {SPR_TVGV, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_GRAVITY_GOLDBOX + {SPR_TVFL, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_FLAMEAURA_GOLDBOX + {SPR_TVBB, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_BUBBLEWRAP_GOLDBOX + {SPR_TVZP, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_THUNDERCOIN_GOLDBOX // Team Ring Boxes (these are special) {SPR_TRRI, 0, 2, {NULL}, 0, 0, S_RING_REDBOX2}, // S_RING_REDBOX1 @@ -1641,7 +1670,7 @@ state_t states[NUMSTATES] = {SPR_TVAT, 2, 18, {A_RingShield},0, 0, S_NULL}, // S_ATTRACT_ICON2 {SPR_TVFO, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_FORCE_ICON2}, // S_FORCE_ICON1 - {SPR_TVFO, 2, 18, {A_ForceShield}, 0, 0, S_NULL}, // S_FORCE_ICON2 + {SPR_TVFO, 2, 18, {A_ForceShield}, 1, 0, S_NULL}, // S_FORCE_ICON2 {SPR_TVAR, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_ARMAGEDDON_ICON2}, // S_ARMAGEDDON_ICON1 {SPR_TVAR, 2, 18, {A_BombShield}, 0, 0, S_NULL}, // S_ARMAGEDDON_ICON2 @@ -1679,6 +1708,15 @@ state_t states[NUMSTATES] = {SPR_TVTK, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_SCORE10K_ICON2}, // S_SCORE10K_ICON1 {SPR_TVTK, 2, 18, {A_AwardScore}, 0, 0, S_NULL}, // S_SCORE10K_ICON2 + {SPR_TVFL, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_FLAMEAURA_ICON2}, // S_FLAMEAURA_ICON1 + {SPR_TVFL, 2, 18, {A_FlameShield}, 0, 0, S_NULL}, // S_FLAMEAURA_ICON2 + + {SPR_TVBB, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_BUBBLEWRAP_ICON2}, // S_BUBBLEWRAP_ICON1 + {SPR_TVBB, 2, 18, {A_BubbleShield}, 0, 0, S_NULL}, // S_BUBBLERWAP_ICON2 + + {SPR_TVZP, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_THUNDERCOIN_ICON2}, // S_THUNDERCOIN_ICON1 + {SPR_TVZP, 2, 18, {A_ThunderShield}, 0, 0, S_NULL}, // S_THUNDERCOIN_ICON2 + // --- {SPR_MISL, FF_FULLBRIGHT, 1, {A_SmokeTrailer}, MT_SMOKE, 0, S_ROCKET}, // S_ROCKET @@ -1719,21 +1757,15 @@ state_t states[NUMSTATES] = {SPR_CFIR, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_DEMONFIRE1}, // S_DEMONFIRE6 // GFZ Flower - {SPR_FWR1, 0, 14, {NULL}, 0, 0, S_GFZFLOWERA2}, // S_GFZFLOWERA - {SPR_FWR1, 1, 14, {NULL}, 0, 0, S_GFZFLOWERA}, // S_GFZFLOWERA2 - - {SPR_FWR2, 0, 7, {NULL}, 0, 0, S_GFZFLOWERB2}, // S_GFZFLOWERB1 - {SPR_FWR2, 1, 7, {NULL}, 0, 0, S_GFZFLOWERB1}, // S_GFZFLOWERB1 - - {SPR_FWR3, 0, -1, {NULL}, 0, 0, S_NULL}, // S_GFZFLOWERC1 + {SPR_FWR1, FF_ANIMATE, -1, {NULL}, 7, 3, S_NULL}, // S_GFZFLOWERA + {SPR_FWR2, FF_ANIMATE, -1, {NULL}, 19, 3, S_NULL}, // S_GFZFLOWERB + {SPR_FWR3, FF_ANIMATE, -1, {NULL}, 11, 4, S_NULL}, // S_GFZFLOWERC {SPR_BUS1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BERRYBUSH {SPR_BUS2, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BUSH - {SPR_THZP, 0, 4, {NULL}, 0, 0, S_THZPLANT2}, // S_THZPLANT1 - {SPR_THZP, 1, 4, {NULL}, 0, 0, S_THZPLANT3}, // S_THZPLANT1 - {SPR_THZP, 2, 4, {NULL}, 0, 0, S_THZPLANT4}, // S_THZPLANT1 - {SPR_THZP, 3, 4, {NULL}, 0, 0, S_THZPLANT1}, // S_THZPLANT1 + {SPR_THZP, FF_ANIMATE, -1, {NULL}, 7, 4, S_NULL}, // S_THZFLOWERA + {SPR_FWR5, FF_ANIMATE, -1, {NULL}, 19, 2, S_NULL}, // S_THZFLOWERB // THZ Alarm {SPR_ALRM, FF_FULLBRIGHT, 35, {A_Scream}, 0, 0, S_ALARM1}, // S_ALARM1 @@ -1774,10 +1806,15 @@ state_t states[NUMSTATES] = {SPR_CHAN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZCHAIN // Flame - {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_FLAME2}, // S_FLAME1 - {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS50|1, 3, {NULL}, 0, 0, S_FLAME3}, // S_FLAME2 - {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS50|2, 3, {NULL}, 0, 0, S_FLAME4}, // S_FLAME3 - {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS50|3, 3, {NULL}, 0, 0, S_FLAME1}, // S_FLAME4 + {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20, 3, {A_FlameParticle}, 3, 0, S_FLAME2}, // S_FLAME1 + {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|1, 3, {NULL}, 0, 0, S_FLAME3}, // S_FLAME2 + {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|2, 3, {A_FlameParticle}, 3, 0, S_FLAME4}, // S_FLAME3 + {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|3, 3, {NULL}, 0, 0, S_FLAME5}, // S_FLAME4 + {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|4, 3, {A_FlameParticle}, 3, 0, S_FLAME6}, // S_FLAME5 + {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|5, 3, {NULL}, 0, 0, S_FLAME1}, // S_FLAME6 + {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS10|6, 24, {NULL}, 0, 0, S_NULL}, // S_FLAMEPARTICLE + + {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|FF_ANIMATE, -1, {NULL}, 5, 3, S_FLAME2}, // S_FLAMEREST // Eggman statue {SPR_ESTA, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGSTATUE1 @@ -1833,48 +1870,23 @@ state_t states[NUMSTATES] = {SPR_NULL, 0, 2*TICRATE, {NULL}, 0, 0, S_FLAMEJETSTART}, // S_FLAMEJETSTND {SPR_NULL, 0, 3*TICRATE, {A_ToggleFlameJet}, 0, 0, S_FLAMEJETSTOP}, // S_FLAMEJETSTART {SPR_NULL, 0, 1, {A_ToggleFlameJet}, 0, 0, S_FLAMEJETSTND}, // S_FLAMEJETSTOP - {SPR_FLME, FF_TRANS50 , 4, {NULL}, 0, 0, S_FLAMEJETFLAME2}, // S_FLAMEJETFLAME1 - {SPR_FLME, FF_TRANS60|1, 5, {NULL}, 0, 0, S_FLAMEJETFLAME3}, // S_FLAMEJETFLAME2 - {SPR_FLME, FF_TRANS70|2, 11, {NULL}, 0, 0, S_NULL}, // S_FLAMEJETFLAME3 + {SPR_FLME, FF_FULLBRIGHT|FF_TRANS50 , 4, {NULL}, 0, 0, S_FLAMEJETFLAME2}, // S_FLAMEJETFLAME1 + {SPR_FLME, FF_FULLBRIGHT|FF_TRANS60|1, 5, {NULL}, 0, 0, S_FLAMEJETFLAME3}, // S_FLAMEJETFLAME2 + {SPR_FLME, FF_FULLBRIGHT|FF_TRANS70|2, 11, {NULL}, 0, 0, S_NULL}, // S_FLAMEJETFLAME3 // Spinning flame jets // A: Counter-clockwise - {SPR_NULL, 0, 1, {NULL}, 0, 0, S_FJSPINAXISA2}, // S_FJSPINAXISA1 - {SPR_NULL, 0, 1, {A_Thrust}, 10, 1, S_FJSPINAXISA3}, // S_FJSPINAXISA2 - {SPR_NULL, 0, 0, {A_Thrust}, 0, 1, S_FJSPINAXISA4}, // S_FJSPINAXISA3 - {SPR_NULL, 0, 0, {A_SpawnObjectRelative}, 0, MT_FJSPINHELPERA, S_FJSPINAXISA5}, // S_FJSPINAXISA4 - {SPR_NULL, 0, 2, {A_FindTarget}, MT_FJSPINHELPERA, 0, S_FJSPINAXISA6}, // S_FJSPINAXISA5 - {SPR_NULL, 0, 1, {A_Thrust}, -10, 1, S_FJSPINAXISA7}, // S_FJSPINAXISA6 - {SPR_NULL, 0, 1, {A_Thrust}, 0, 1, S_FJSPINAXISA8}, // S_FJSPINAXISA7 - {SPR_NULL, 0, 0, {A_FireShot}, MT_FLAMEJETFLAMEB, -64, S_FJSPINAXISA9}, // S_FJSPINAXISA8 - {SPR_NULL, 0, 3, {A_ChangeAngleRelative}, 6, 6, S_FJSPINAXISA8}, // S_FJSPINAXISA9 - - {SPR_NULL, 0, 1, {NULL}, 0, 0, S_FJSPINHELPERA2}, // S_FJSPINHELPERA1 - {SPR_NULL, 0, 0, {A_FindTarget}, MT_FJSPINAXISA, 0, S_FJSPINHELPERA3}, // S_FJSPINHELPERA2 - {SPR_NULL, 0, 1, {A_CapeChase}, 0, (64<<16), S_FJSPINHELPERA3}, // S_FJSPINHELPERA3 + {SPR_NULL, 0, 1, {A_TrapShot}, MT_FLAMEJETFLAMEB, -(16<<16)|(1<<15)|64, S_FJSPINAXISA2}, // S_FJSPINAXISA1 + {SPR_NULL, 0, 2, {A_ChangeAngleRelative}, 6, 6, S_FJSPINAXISA1}, // S_FJSPINAXISA2 // B: Clockwise - {SPR_NULL, 0, 1, {NULL}, 0, 0, S_FJSPINAXISB2}, // S_FJSPINAXISB1 - {SPR_NULL, 0, 1, {A_Thrust}, 10, 1, S_FJSPINAXISB3}, // S_FJSPINAXISB2 - {SPR_NULL, 0, 0, {A_Thrust}, 0, 1, S_FJSPINAXISB4}, // S_FJSPINAXISB3 - {SPR_NULL, 0, 0, {A_SpawnObjectRelative}, 0, MT_FJSPINHELPERB, S_FJSPINAXISB5}, // S_FJSPINAXISB4 - {SPR_NULL, 0, 2, {A_FindTarget}, MT_FJSPINHELPERB, 0, S_FJSPINAXISB6}, // S_FJSPINAXISB5 - {SPR_NULL, 0, 1, {A_Thrust}, -10, 1, S_FJSPINAXISB7}, // S_FJSPINAXISB6 - {SPR_NULL, 0, 1, {A_Thrust}, 0, 1, S_FJSPINAXISB8}, // S_FJSPINAXISB7 - {SPR_NULL, 0, 0, {A_FireShot}, MT_FLAMEJETFLAMEB, -64, S_FJSPINAXISB9}, // S_FJSPINAXISB8 - {SPR_NULL, 0, 3, {A_ChangeAngleRelative}, -6, -6, S_FJSPINAXISB8}, // S_FJSPINAXISB9 - - {SPR_NULL, 0, 1, {NULL}, 0, 0, S_FJSPINHELPERB2}, // S_FJSPINHELPERB1 - {SPR_NULL, 0, 0, {A_FindTarget}, MT_FJSPINAXISB, 0, S_FJSPINHELPERB3}, // S_FJSPINHELPERB2 - {SPR_NULL, 0, 1, {A_CapeChase}, 0, (64<<16), S_FJSPINHELPERB3}, // S_FJSPINHELPERB3 + {SPR_NULL, 0, 1, {A_TrapShot}, MT_FLAMEJETFLAMEB, -(16<<16)|(1<<15)|64, S_FJSPINAXISB2}, // S_FJSPINAXISB1 + {SPR_NULL, 0, 2, {A_ChangeAngleRelative}, -6, -6, S_FJSPINAXISB1}, // S_FJSPINAXISB2 // Blade's flame - {SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|1, 1, {A_MoveRelative}, 0, 5, S_FLAMEJETFLAMEB2}, // S_FLAMEJETFLAMEB1 - {SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|2, 1, {A_MoveRelative}, 0, 7, S_FLAMEJETFLAMEB3}, // S_FLAMEJETFLAMEB2 - {SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|3,24, {NULL}, 0, 0, S_FLAMEJETFLAMEB4}, // S_FLAMEJETFLAMEB3 - {SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|4,24, {NULL}, 0, 0, S_FLAMEJETFLAMEB5}, // S_FLAMEJETFLAMEB4 - {SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|5,24, {NULL}, 0, 0, S_FLAMEJETFLAMEB6}, // S_FLAMEJETFLAMEB5 - {SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|6,12, {NULL}, 0, 0, S_NULL}, // S_FLAMEJETFLAMEB6 + {SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40, 1, {A_MoveRelative}, 0, 5, S_FLAMEJETFLAMEB2}, // S_FLAMEJETFLAMEB1 + {SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40, 1, {A_MoveRelative}, 0, 7, S_FLAMEJETFLAMEB3}, // S_FLAMEJETFLAMEB2 + {SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|FF_ANIMATE, (12*7), {NULL}, 7, 12, S_NULL}, // S_FLAMEJETFLAMEB3 // Trapgoyles {SPR_GARG, 0, 67, {NULL}, 0, 0, S_TRAPGOYLE_CHECK}, // S_TRAPGOYLE @@ -1972,8 +1984,10 @@ state_t states[NUMSTATES] = {SPR_BSZ7, 5, -1, {NULL}, 0, 0, S_NULL}, // S_BSZVINE_ORANGE {SPR_BSZ8, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BSZSHRUB {SPR_BSZ8, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BSZCLOVER - {SPR_BSZ8, 2, -1, {NULL}, 0, 0, S_NULL}, // S_BSZFISH - {SPR_BSZ8, 3, -1, {NULL}, 0, 0, S_NULL}, // S_BSZSUNFLOWER + {SPR_BSZ8, 2, -1, {NULL}, 0, 0, S_NULL}, // S_BIG_PALMTREE_TRUNK + {SPR_BSZ8, 3, -1, {NULL}, 0, 0, S_NULL}, // S_BIG_PALMTREE_TOP + {SPR_BSZ8, 4, -1, {NULL}, 0, 0, S_NULL}, // S_PALMTREE_TRUNK + {SPR_BSZ8, 5, -1, {NULL}, 0, 0, S_NULL}, // S_PALMTREE_TOP // Disco ball {SPR_DBAL, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_DBALL2}, // S_DBALL1 @@ -2059,6 +2073,8 @@ state_t states[NUMSTATES] = {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40|10, 2, {NULL}, 0, 0, S_MAGN12}, // S_MAGN11 {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40|11, 2, {NULL}, 0, 0, S_MAGN1 }, // S_MAGN12 + {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS10|12, 2, {NULL}, 0, 0, S_MAGN1 }, // S_MAGN13 + {SPR_FORC, FF_TRANS50 , 3, {NULL}, 0, 0, S_FORC2 }, // S_FORC1 {SPR_FORC, FF_TRANS50|1, 3, {NULL}, 0, 0, S_FORC3 }, // S_FORC2 {SPR_FORC, FF_TRANS50|2, 3, {NULL}, 0, 0, S_FORC4 }, // S_FORC3 @@ -2081,6 +2097,8 @@ state_t states[NUMSTATES] = {SPR_FORC, FF_TRANS50|18, 3, {NULL}, 0, 0, S_FORC20}, // S_FORC19 {SPR_FORC, FF_TRANS50|19, 3, {NULL}, 0, 0, S_FORC11}, // S_FORC20 + {SPR_FORC, FF_TRANS50|20, -1, {NULL}, 0, 0, S_NULL}, // S_FORC21 + {SPR_ELEM, FF_TRANS50 , 4, {NULL}, 0, 0, S_ELEM2 }, // S_ELEM1 {SPR_ELEM, FF_TRANS50| 1, 4, {NULL}, 0, 0, S_ELEM3 }, // S_ELEM2 {SPR_ELEM, FF_TRANS50| 2, 4, {NULL}, 0, 0, S_ELEM4 }, // S_ELEM3 @@ -2094,14 +2112,20 @@ state_t states[NUMSTATES] = {SPR_ELEM, FF_TRANS50|10, 4, {NULL}, 0, 0, S_ELEM12}, // S_ELEM11 {SPR_ELEM, FF_TRANS50|11, 4, {NULL}, 0, 0, S_ELEM1 }, // S_ELEM12 - {SPR_ELEM, FF_FULLBRIGHT|12, 3, {NULL}, 0, 0, S_ELEMF2}, // S_ELEMF1 - {SPR_ELEM, FF_FULLBRIGHT|13, 3, {NULL}, 0, 0, S_ELEMF3}, // S_ELEMF2 - {SPR_ELEM, FF_FULLBRIGHT|14, 3, {NULL}, 0, 0, S_ELEMF4}, // S_ELEMF3 - {SPR_ELEM, FF_FULLBRIGHT|15, 3, {NULL}, 0, 0, S_ELEMF5}, // S_ELEMF4 - {SPR_ELEM, FF_FULLBRIGHT|16, 3, {NULL}, 0, 0, S_ELEMF6}, // S_ELEMF5 - {SPR_ELEM, FF_FULLBRIGHT|17, 3, {NULL}, 0, 0, S_ELEMF7}, // S_ELEMF6 - {SPR_ELEM, FF_FULLBRIGHT|18, 3, {NULL}, 0, 0, S_ELEMF8}, // S_ELEMF7 - {SPR_ELEM, FF_FULLBRIGHT|19, 3, {NULL}, 0, 0, S_ELEMF1}, // S_ELEMF8 + {SPR_NULL, 0, 1, {NULL}, 0, 0, S_ELEM14}, // S_ELEM13 + {SPR_ELEM, FF_TRANS50|11, 1, {NULL}, 0, 0, S_ELEM1 }, // S_ELEM14 + + {SPR_ELEM, FF_FULLBRIGHT|12, 3, {NULL}, 0, 0, S_ELEMF2 }, // S_ELEMF1 + {SPR_ELEM, FF_FULLBRIGHT|13, 3, {NULL}, 0, 0, S_ELEMF3 }, // S_ELEMF2 + {SPR_ELEM, FF_FULLBRIGHT|14, 3, {NULL}, 0, 0, S_ELEMF4 }, // S_ELEMF3 + {SPR_ELEM, FF_FULLBRIGHT|15, 3, {NULL}, 0, 0, S_ELEMF5 }, // S_ELEMF4 + {SPR_ELEM, FF_FULLBRIGHT|16, 3, {NULL}, 0, 0, S_ELEMF6 }, // S_ELEMF5 + {SPR_ELEM, FF_FULLBRIGHT|17, 3, {NULL}, 0, 0, S_ELEMF7 }, // S_ELEMF6 + {SPR_ELEM, FF_FULLBRIGHT|18, 3, {NULL}, 0, 0, S_ELEMF8 }, // S_ELEMF7 + {SPR_ELEM, FF_FULLBRIGHT|19, 3, {NULL}, 0, 0, S_ELEMF1 }, // S_ELEMF8 + + {SPR_ELEM, FF_FULLBRIGHT|20, 1, {NULL}, 0, 0, S_ELEMF10}, // S_ELEMF9 + {SPR_NULL, 0, 1, {NULL}, 0, 0, S_ELEMF1 }, // S_ELEMF10 {SPR_PITY, FF_TRANS20 , 1, {NULL}, 0, 0, S_PITY2 }, // S_PITY1 {SPR_PITY, FF_TRANS20|1, 1, {NULL}, 0, 0, S_PITY3 }, // S_PITY2 @@ -2114,6 +2138,84 @@ state_t states[NUMSTATES] = {SPR_PITY, FF_TRANS20 , 1, {NULL}, 0, 0, S_PITY10}, // S_PITY9 {SPR_PITY, FF_TRANS20|5, 1, {NULL}, 0, 0, S_PITY1 }, // S_PITY10 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40 , 2, {NULL}, 0, 0, S_FIRS2}, // S_FIRS1 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|1, 2, {NULL}, 0, 0, S_FIRS3}, // S_FIRS2 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|2, 2, {NULL}, 0, 0, S_FIRS4}, // S_FIRS3 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|3, 2, {NULL}, 0, 0, S_FIRS5}, // S_FIRS4 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|4, 2, {NULL}, 0, 0, S_FIRS6}, // S_FIRS5 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|5, 2, {NULL}, 0, 0, S_FIRS7}, // S_FIRS6 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|6, 2, {NULL}, 0, 0, S_FIRS8}, // S_FIRS7 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|7, 2, {NULL}, 0, 0, S_FIRS9}, // S_FIRS8 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|8, 2, {NULL}, 0, 0, S_FIRS1}, // S_FIRS9 + + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|18, 1, {NULL}, 0, 0, S_FIRS11}, // S_FIRS10 + {SPR_NULL, 0, 1, {NULL}, 0, 0, S_FIRS1 }, // S_FIRS11 + + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40| 9, 2, {NULL}, 0, 0, S_FIRSB2}, // S_FIRSB1 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|10, 2, {NULL}, 0, 0, S_FIRSB3}, // S_FIRSB2 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|11, 2, {NULL}, 0, 0, S_FIRSB4}, // S_FIRSB3 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|12, 2, {NULL}, 0, 0, S_FIRSB5}, // S_FIRSB4 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|13, 2, {NULL}, 0, 0, S_FIRSB6}, // S_FIRSB5 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|14, 2, {NULL}, 0, 0, S_FIRSB7}, // S_FIRSB6 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|15, 2, {NULL}, 0, 0, S_FIRSB8}, // S_FIRSB7 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|16, 2, {NULL}, 0, 0, S_FIRSB9}, // S_FIRSB8 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|17, 2, {NULL}, 0, 0, S_FIRSB1}, // S_FIRSB9 + + {SPR_NULL, 0, 2, {NULL}, 0, 0, S_FIRSB1 }, // S_FIRSB10 + + {SPR_BUBS, FF_TRANS30 , 3, {NULL}, 0, 0, S_BUBS2}, // S_BUBS1 + {SPR_BUBS, FF_TRANS30|1, 3, {NULL}, 0, 0, S_BUBS3}, // S_BUBS2 + {SPR_BUBS, FF_TRANS30|2, 3, {NULL}, 0, 0, S_BUBS4}, // S_BUBS3 + {SPR_BUBS, FF_TRANS30|3, 3, {NULL}, 0, 0, S_BUBS5}, // S_BUBS4 + {SPR_BUBS, FF_TRANS30|4, 3, {NULL}, 0, 0, S_BUBS6}, // S_BUBS5 + {SPR_BUBS, FF_TRANS30|5, 3, {NULL}, 0, 0, S_BUBS7}, // S_BUBS6 + {SPR_BUBS, FF_TRANS30|6, 3, {NULL}, 0, 0, S_BUBS8}, // S_BUBS7 + {SPR_BUBS, FF_TRANS30|7, 3, {NULL}, 0, 0, S_BUBS9}, // S_BUBS8 + {SPR_BUBS, FF_TRANS30|8, 3, {NULL}, 0, 0, S_BUBS1}, // S_BUBS9 + + {SPR_NULL, 0, 3, {NULL}, 0, 0, S_BUBS1}, // S_BUBS10 + {SPR_NULL, 0, 4*3, {NULL}, 0, 0, S_BUBS1}, // S_BUBS11 + + {SPR_BUBS, FF_TRANS30| 9, 3, {NULL}, 0, 0, S_BUBSB2}, // S_BUBSB1 + {SPR_BUBS, FF_TRANS30|10, 3, {NULL}, 0, 0, S_BUBSB3}, // S_BUBSB2 + {SPR_BUBS, FF_TRANS30|11, 3, {NULL}, 0, 0, S_BUBSB4}, // S_BUBSB3 + {SPR_BUBS, FF_TRANS30|10, 3, {NULL}, 0, 0, S_BUBSB1}, // S_BUBSB4 + + {SPR_BUBS, FF_TRANS30|12, 3, {NULL}, 0, 0, S_BUBSB3}, // S_BUBSB5 + {SPR_BUBS, FF_TRANS30|13, 3, {NULL}, 0, 0, S_BUBSB5}, // S_BUBSB6 + + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20 , 2, {NULL}, 0, 0, S_ZAPS2 }, // S_ZAPS1 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 1, 2, {NULL}, 0, 0, S_ZAPS3 }, // S_ZAPS2 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 2, 2, {NULL}, 0, 0, S_ZAPS4 }, // S_ZAPS3 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 3, 2, {NULL}, 0, 0, S_ZAPS5 }, // S_ZAPS4 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 4, 2, {NULL}, 0, 0, S_ZAPS6 }, // S_ZAPS5 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 5, 2, {NULL}, 0, 0, S_ZAPS7 }, // S_ZAPS6 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 6, 2, {NULL}, 0, 0, S_ZAPS8 }, // S_ZAPS7 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 7, 2, {NULL}, 0, 0, S_ZAPS9 }, // S_ZAPS8 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 8, 2, {NULL}, 0, 0, S_ZAPS10}, // S_ZAPS9 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 9, 2, {NULL}, 0, 0, S_ZAPS11}, // S_ZAPS10 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20|10, 2, {NULL}, 0, 0, S_ZAPS12}, // S_ZAPS11 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20|11, 2, {NULL}, 0, 0, S_ZAPS13}, // S_ZAPS12 + {SPR_NULL, 0, 9*2, {NULL}, 0, 0, S_ZAPS14}, // S_ZAPS13 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 9, 2, {NULL}, 0, 0, S_ZAPS15}, // S_ZAPS14 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20|10, 2, {NULL}, 0, 0, S_ZAPS16}, // S_ZAPS15 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20|11, 2, {NULL}, 0, 0, S_ZAPS1 }, // S_ZAPS16 + + {SPR_NULL, 0, 12*2, {NULL}, 0, 0, S_ZAPSB2 }, // S_ZAPSB1 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 8, 2, {NULL}, 0, 0, S_ZAPSB3 }, // S_ZAPSB2 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 7, 2, {NULL}, 0, 0, S_ZAPSB4 }, // S_ZAPSB3 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 6, 2, {NULL}, 0, 0, S_ZAPSB5 }, // S_ZAPSB4 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 5, 2, {NULL}, 0, 0, S_ZAPSB6 }, // S_ZAPSB5 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 4, 2, {NULL}, 0, 0, S_ZAPSB7 }, // S_ZAPSB6 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 3, 2, {NULL}, 0, 0, S_ZAPSB8 }, // S_ZAPSB7 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 2, 2, {NULL}, 0, 0, S_ZAPSB9 }, // S_ZAPSB8 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 1, 2, {NULL}, 0, 0, S_ZAPSB10}, // S_ZAPSB9 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20 , 2, {NULL}, 0, 0, S_ZAPSB11}, // S_ZAPSB10 + {SPR_NULL, 0, 15*2, {NULL}, 0, 0, S_ZAPSB2 }, // S_ZAPSB11 + + // Thunder spark + {SPR_SSPK, FF_ANIMATE, 18, {NULL}, 1, 2, S_NULL}, // S_THUNDERCOIN_SPARK + // Invincibility Sparkles {SPR_IVSP, FF_ANIMATE, 32, {NULL}, 31, 1, S_NULL}, // S_IVSP @@ -2124,43 +2226,133 @@ state_t states[NUMSTATES] = {SPR_SSPK, 1, 2, {NULL}, 0, 0, S_SSPK5}, // S_SSPK4 {SPR_SSPK, 0, 2, {NULL}, 0, 0, S_NULL}, // S_SSPK5 - // Freed Birdie - {SPR_BIRD, 0, 4, {NULL}, 0, 0, S_BIRD2}, // S_BIRD1 - {SPR_BIRD, 0, 4, {A_Chase}, 0, 0, S_BIRD3}, // S_BIRD2 - {SPR_BIRD, 1, 4, {A_Chase}, 0, 0, S_BIRD2}, // S_BIRD3 + // Flicky-sized bubble + {SPR_FBUB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_FLICKY_BUBBLE - // Freed Bunny - {SPR_BUNY, 0, 4, {NULL}, 0, 0, S_BUNNY2}, // S_BUNNY1 - {SPR_BUNY, 0, 64, {NULL}, 0, 0, S_BUNNY3}, // S_BUNNY2 - {SPR_BUNY, 1, 2, {A_BunnyHop}, 6, 3, S_BUNNY4}, // S_BUNNY3 - {SPR_BUNY, 1, 2, {A_Chase}, 0, 0, S_BUNNY5}, // S_BUNNY4 - {SPR_BUNY, 1, 2, {A_Chase}, 0, 0, S_BUNNY6}, // S_BUNNY5 - {SPR_BUNY, 1, 2, {A_Chase}, 0, 0, S_BUNNY7}, // S_BUNNY6 - {SPR_BUNY, 1, 2, {A_Chase}, 0, 0, S_BUNNY8}, // S_BUNNY7 - {SPR_BUNY, 1, 2, {A_Chase}, 0, 0, S_BUNNY9}, // S_BUNNY8 - {SPR_BUNY, 1, 2, {A_Chase}, 0, 0, S_BUNNY10}, // S_BUNNY9 - {SPR_BUNY, 1, 2, {A_Chase}, 0, 0, S_BUNNY2}, // S_BUNNY10 + // Bluebird + {SPR_FL01, 0, 2, {A_FlickyCheck}, S_FLICKY_01_FLAP1, S_FLICKY_01_FLAP1, S_FLICKY_01_OUT}, // S_FLICKY_01_OUT + {SPR_FL01, 1, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_01_FLAP2}, // S_FLICKY_01_FLAP1 + {SPR_FL01, 2, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_01_FLAP3}, // S_FLICKY_01_FLAP2 + {SPR_FL01, 3, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_01_FLAP1}, // S_FLICKY_01_FLAP3 - // Freed Mouse - {SPR_MOUS, 0, 2, {A_MouseThink}, 0, 0, S_MOUSE2}, // S_MOUSE1 - {SPR_MOUS, 1, 2, {A_MouseThink}, 0, 0, S_MOUSE1}, // S_MOUSE2 + // Rabbit + {SPR_FL02, 0, 2, {A_FlickyCheck}, S_FLICKY_02_AIM, 0, S_FLICKY_02_OUT}, // S_FLICKY_02_OUT + {SPR_FL02, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_02_HOP}, // S_FLICKY_02_AIM + {SPR_FL02, 1, 1, {A_FlickyHop}, 6*FRACUNIT, 4*FRACUNIT, S_FLICKY_02_UP}, // S_FLICKY_02_HOP + {SPR_FL02, 2, 2, {A_FlickyCheck}, S_FLICKY_02_AIM, S_FLICKY_02_DOWN, S_FLICKY_02_UP}, // S_FLICKY_02_UP + {SPR_FL02, 3, 2, {A_FlickyCheck}, S_FLICKY_02_AIM, 0, S_FLICKY_02_DOWN}, // S_FLICKY_02_DOWN - // Freed Chicken - {SPR_CHIC, 0, 7, {A_Chase}, 3, 0, S_CHICKENHOP}, // S_CHICKEN1 - {SPR_CHIC, 0, 1, {A_BunnyHop}, 4, 2, S_CHICKENFLY1}, // S_CHICKENHOP - {SPR_CHIC, 1, 2, {A_ChickenCheck}, 0, 0, S_CHICKENFLY2}, // S_CHICKENFLY1 - {SPR_CHIC, 2, 2, {NULL}, 0, 0, S_CHICKENFLY1}, // S_CHICKENFLY2 + // Chicken + {SPR_FL03, 0, 2, {A_FlickyCheck}, S_FLICKY_03_AIM, S_FLICKY_03_FLAP1, S_FLICKY_03_OUT}, // S_FLICKY_03_OUT + {SPR_FL03, 1, 1, {A_FlickyAim}, ANGLE_45, 32*FRACUNIT, S_FLICKY_03_HOP}, // S_FLICKY_03_AIM + {SPR_FL03, 1, 1, {A_FlickyHop}, 7*FRACUNIT, 2*FRACUNIT, S_FLICKY_03_UP}, // S_FLICKY_03_HOP + {SPR_FL03, 2, 2, {A_FlickyFlutter}, S_FLICKY_03_HOP, S_FLICKY_03_FLAP1, S_FLICKY_03_UP}, // S_FLICKY_03_UP + {SPR_FL03, 3, 2, {A_FlickyFlutter}, S_FLICKY_03_HOP, 0, S_FLICKY_03_FLAP2}, // S_FLICKY_03_FLAP1 + {SPR_FL03, 4, 2, {A_FlickyFlutter}, S_FLICKY_03_HOP, 0, S_FLICKY_03_FLAP1}, // S_FLICKY_03_FLAP2 - // Freed Cow - {SPR_COWZ, 0, 4, {A_Chase}, 3, 0, S_COW2}, // S_COW1 - {SPR_COWZ, 1, 4, {A_Chase}, 3, 0, S_COW3}, // S_COW2 - {SPR_COWZ, 2, 4, {A_Chase}, 3, 0, S_COW4}, // S_COW3 - {SPR_COWZ, 3, 4, {A_Chase}, 3, 0, S_COW1}, // S_COW4 + // Seal + {SPR_FL04, 0, 2, {A_FlickyCheck}, S_FLICKY_04_AIM, 0, S_FLICKY_04_OUT}, // S_FLICKY_04_OUT + {SPR_FL04, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_04_HOP}, // S_FLICKY_04_AIM + {SPR_FL04, 1, 1, {A_FlickyHop}, 3*FRACUNIT, 2*FRACUNIT, S_FLICKY_04_UP}, // S_FLICKY_04_HOP + {SPR_FL04, 2, 4, {A_FlickyCheck}, S_FLICKY_04_AIM, S_FLICKY_04_DOWN, S_FLICKY_04_UP}, // S_FLICKY_04_UP + {SPR_FL04, 3, 4, {A_FlickyCheck}, S_FLICKY_04_AIM, 0, S_FLICKY_04_DOWN}, // S_FLICKY_04_DOWN + {SPR_FL04, 3, 4, {A_FlickyFly}, 2*FRACUNIT, 48*FRACUNIT, S_FLICKY_04_SWIM2}, // S_FLICKY_04_SWIM1 + {SPR_FL04, 4, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_04_SWIM1, S_FLICKY_04_SWIM3}, // S_FLICKY_04_SWIM2 + {SPR_FL04, 3, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_04_SWIM1, S_FLICKY_04_SWIM4}, // S_FLICKY_04_SWIM3 + {SPR_FL04, 5, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_04_SWIM1, S_FLICKY_04_SWIM1}, // S_FLICKY_04_SWIM4 - // Freed Birdie - {SPR_RBRD, 0, 4, {NULL}, 0, 0, S_RBIRD2}, // S_RBIRD1 - {SPR_RBRD, 0, 4, {A_Chase}, 0, 0, S_RBIRD3}, // S_RBIRD2 - {SPR_RBRD, 1, 4, {A_Chase}, 0, 0, S_RBIRD2}, // S_RBIRD3 + // Pig + {SPR_FL05, 0, 2, {A_FlickyCheck}, S_FLICKY_05_AIM, 0, S_FLICKY_05_OUT}, // S_FLICKY_05_OUT + {SPR_FL05, 1, 1, {A_FlickyAim}, ANG20, 32*FRACUNIT, S_FLICKY_05_HOP}, // S_FLICKY_05_AIM + {SPR_FL05, 1, 1, {A_FlickyHop}, 4*FRACUNIT, 3*FRACUNIT, S_FLICKY_05_UP}, // S_FLICKY_05_HOP + {SPR_FL05, 2, 2, {A_FlickyCheck}, S_FLICKY_05_AIM, S_FLICKY_05_DOWN, S_FLICKY_05_UP}, // S_FLICKY_05_UP + {SPR_FL05, 3, 2, {A_FlickyCheck}, S_FLICKY_05_AIM, 0, S_FLICKY_05_DOWN}, // S_FLICKY_05_DOWN + + // Chipmunk + {SPR_FL06, 0, 2, {A_FlickyCheck}, S_FLICKY_06_AIM, 0, S_FLICKY_06_OUT}, // S_FLICKY_06_OUT + {SPR_FL06, 1, 1, {A_FlickyAim}, ANGLE_90, 32*FRACUNIT, S_FLICKY_06_HOP}, // S_FLICKY_06_AIM + {SPR_FL06, 1, 1, {A_FlickyHop}, 5*FRACUNIT, 6*FRACUNIT, S_FLICKY_06_UP}, // S_FLICKY_06_HOP + {SPR_FL06, 2, 2, {A_FlickyCheck}, S_FLICKY_06_AIM, S_FLICKY_06_DOWN, S_FLICKY_06_UP}, // S_FLICKY_06_UP + {SPR_FL06, 3, 2, {A_FlickyCheck}, S_FLICKY_06_AIM, 0, S_FLICKY_06_DOWN}, // S_FLICKY_06_DOWN + + // Penguin + {SPR_FL07, 0, 2, {A_FlickyCheck}, S_FLICKY_07_AIML, 0, S_FLICKY_07_OUT}, // S_FLICKY_07_OUT + {SPR_FL07, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_07_HOPL}, // S_FLICKY_07_AIML + {SPR_FL07, 1, 1, {A_FlickyHop}, 4*FRACUNIT, 2*FRACUNIT, S_FLICKY_07_UPL}, // S_FLICKY_07_HOPL + {SPR_FL07, 2, 4, {A_FlickyCheck}, S_FLICKY_07_AIMR, S_FLICKY_07_DOWNL, S_FLICKY_07_UPL}, // S_FLICKY_07_UPL + {SPR_FL07, 1, 4, {A_FlickyCheck}, S_FLICKY_07_AIMR, 0, S_FLICKY_07_DOWNL}, // S_FLICKY_07_DOWNL + {SPR_FL07, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_07_HOPR}, // S_FLICKY_07_AIMR + {SPR_FL07, 1, 1, {A_FlickyHop}, 4*FRACUNIT, 2*FRACUNIT, S_FLICKY_07_UPR}, // S_FLICKY_07_HOPR + {SPR_FL07, 3, 4, {A_FlickyCheck}, S_FLICKY_07_AIML, S_FLICKY_07_DOWNR, S_FLICKY_07_UPR}, // S_FLICKY_07_UPR + {SPR_FL07, 1, 4, {A_FlickyCheck}, S_FLICKY_07_AIML, 0, S_FLICKY_07_DOWNR}, // S_FLICKY_07_DOWNR + {SPR_FL07, 4, 4, {A_FlickyFly}, 3*FRACUNIT, 72*FRACUNIT, S_FLICKY_07_SWIM2}, // S_FLICKY_07_SWIM1 + {SPR_FL07, 5, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_07_SWIM1, S_FLICKY_07_SWIM3}, // S_FLICKY_07_SWIM2 + {SPR_FL07, 6, 4, {A_FlickyCoast}, 2*FRACUNIT, S_FLICKY_07_SWIM1, S_FLICKY_07_SWIM3}, // S_FLICKY_07_SWIM3 + + // Fish + {SPR_FL08, 0, 2, {A_FlickyCheck}, S_FLICKY_08_AIM, 0, S_FLICKY_08_OUT}, // S_FLICKY_08_OUT + {SPR_FL08, 2, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_08_HOP}, // S_FLICKY_08_AIM + {SPR_FL08, 2, 1, {A_FlickyFlounder}, 2*FRACUNIT, 1*FRACUNIT, S_FLICKY_08_FLAP1}, // S_FLICKY_08_HOP + {SPR_FL08, 0, 4, {A_FlickyCheck}, S_FLICKY_08_AIM, 0, S_FLICKY_08_FLAP2}, // S_FLICKY_08_FLAP1 + {SPR_FL08, 1, 4, {A_FlickyCheck}, S_FLICKY_08_AIM, 0, S_FLICKY_08_FLAP3}, // S_FLICKY_08_FLAP2 + {SPR_FL08, 0, 4, {A_FlickyCheck}, S_FLICKY_08_AIM, 0, S_FLICKY_08_FLAP4}, // S_FLICKY_08_FLAP3 + {SPR_FL08, 2, 4, {A_FlickyCheck}, S_FLICKY_08_AIM, 0, S_FLICKY_08_FLAP1}, // S_FLICKY_08_FLAP4 + {SPR_FL08, 0, 4, {A_FlickyFly}, 3*FRACUNIT, 64*FRACUNIT, S_FLICKY_08_SWIM2}, // S_FLICKY_08_SWIM1 + {SPR_FL08, 1, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_08_SWIM1, S_FLICKY_08_SWIM3}, // S_FLICKY_08_SWIM2 + {SPR_FL08, 0, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_08_SWIM1, S_FLICKY_08_SWIM4}, // S_FLICKY_08_SWIM3 + {SPR_FL08, 2, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_08_SWIM1, S_FLICKY_08_SWIM4}, // S_FLICKY_08_SWIM4 + + // Ram + {SPR_FL09, 0, 2, {A_FlickyCheck}, S_FLICKY_09_AIM, 0, S_FLICKY_09_OUT}, // S_FLICKY_09_OUT + {SPR_FL09, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_09_HOP}, // S_FLICKY_09_AIM + {SPR_FL09, 1, 1, {A_FlickyHop}, 7*FRACUNIT, 2*FRACUNIT, S_FLICKY_09_UP}, // S_FLICKY_09_HOP + {SPR_FL09, 2, 2, {A_FlickyCheck}, S_FLICKY_09_AIM, S_FLICKY_09_DOWN, S_FLICKY_09_UP}, // S_FLICKY_09_UP + {SPR_FL09, 3, 2, {A_FlickyCheck}, S_FLICKY_09_AIM, 0, S_FLICKY_09_DOWN}, // S_FLICKY_09_DOWN + + // Puffin + {SPR_FL10, 0, 2, {A_FlickyCheck}, S_FLICKY_10_FLAP1, S_FLICKY_10_FLAP1, S_FLICKY_10_OUT}, // S_FLICKY_10_OUT + {SPR_FL10, 1, 3, {A_FlickySoar}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_10_FLAP2}, // S_FLICKY_10_FLAP1 + {SPR_FL10, 2, 3, {A_FlickySoar}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_10_FLAP1}, // S_FLICKY_10_FLAP2 + + // Cow + {SPR_FL11, 0, 2, {A_FlickyCheck}, S_FLICKY_11_AIM, 0, S_FLICKY_11_OUT}, // S_FLICKY_11_OUT + {SPR_FL11, 1, 1, {A_FlickyAim}, ANGLE_90, 64*FRACUNIT, S_FLICKY_11_RUN1}, // S_FLICKY_11_AIM + {SPR_FL11, 1, 3, {A_FlickyHop}, FRACUNIT/2, 2*FRACUNIT, S_FLICKY_11_RUN2}, // S_FLICKY_11_RUN1 + {SPR_FL11, 2, 4, {A_FlickyHop}, FRACUNIT/2, 2*FRACUNIT, S_FLICKY_11_RUN3}, // S_FLICKY_11_RUN2 + {SPR_FL11, 3, 4, {A_FlickyHop}, FRACUNIT/2, 2*FRACUNIT, S_FLICKY_11_AIM}, // S_FLICKY_11_RUN3 + + // Rat + {SPR_FL12, 0, 2, {A_FlickyCheck}, S_FLICKY_12_AIM, 0, S_FLICKY_12_OUT}, // S_FLICKY_12_OUT + {SPR_FL12, 1, 1, {A_FlickyAim}, ANGLE_90, 32*FRACUNIT, S_FLICKY_12_RUN1}, // S_FLICKY_12_AIM + {SPR_FL12, 1, 2, {A_FlickyHop}, 1, 12*FRACUNIT, S_FLICKY_12_RUN2}, // S_FLICKY_12_RUN1 + {SPR_FL12, 2, 3, {A_FlickyHop}, 1, 12*FRACUNIT, S_FLICKY_12_RUN3}, // S_FLICKY_12_RUN2 + {SPR_FL12, 3, 3, {A_FlickyHop}, 1, 12*FRACUNIT, S_FLICKY_12_AIM}, // S_FLICKY_12_RUN3 + + // Bear + {SPR_FL13, 0, 2, {A_FlickyCheck}, S_FLICKY_13_AIM, 0, S_FLICKY_13_OUT}, // S_FLICKY_13_OUT + {SPR_FL13, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_13_HOP}, // S_FLICKY_13_AIM + {SPR_FL13, 1, 1, {A_FlickyHop}, 5*FRACUNIT, 3*FRACUNIT, S_FLICKY_13_UP}, // S_FLICKY_13_HOP + {SPR_FL13, 2, 2, {A_FlickyCheck}, S_FLICKY_13_AIM, S_FLICKY_13_DOWN, S_FLICKY_13_UP}, // S_FLICKY_13_UP + {SPR_FL13, 3, 2, {A_FlickyCheck}, S_FLICKY_13_AIM, 0, S_FLICKY_13_DOWN}, // S_FLICKY_13_DOWN + + // Dove + {SPR_FL14, 0, 2, {A_FlickyCheck}, S_FLICKY_14_FLAP1, S_FLICKY_14_FLAP1, S_FLICKY_14_OUT}, // S_FLICKY_14_OUT + {SPR_FL14, 1, 3, {A_FlickySoar}, 4*FRACUNIT, 32*FRACUNIT, S_FLICKY_14_FLAP2}, // S_FLICKY_14_FLAP1 + {SPR_FL14, 2, 3, {A_FlickySoar}, 4*FRACUNIT, 32*FRACUNIT, S_FLICKY_14_FLAP3}, // S_FLICKY_14_FLAP2 + {SPR_FL14, 3, 3, {A_FlickySoar}, 4*FRACUNIT, 32*FRACUNIT, S_FLICKY_14_FLAP1}, // S_FLICKY_14_FLAP3 + + // Cat + {SPR_FL15, 0, 2, {A_FlickyCheck}, S_FLICKY_15_AIM, 0, S_FLICKY_15_OUT}, // S_FLICKY_15_OUT + {SPR_FL15, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_15_HOP}, // S_FLICKY_15_AIM + {SPR_FL15, 1, 1, {A_FlickyFlounder}, 2*FRACUNIT, 6*FRACUNIT, S_FLICKY_15_UP}, // S_FLICKY_15_HOP + {SPR_FL15, 2, 2, {A_FlickyCheck}, S_FLICKY_15_AIM, S_FLICKY_15_DOWN, S_FLICKY_15_UP}, // S_FLICKY_15_UP + {SPR_FL15, 3, 2, {A_FlickyCheck}, S_FLICKY_15_AIM, 0, S_FLICKY_15_DOWN}, // S_FLICKY_15_DOWN + + // Canary + {SPR_FL16, 0, 2, {A_FlickyHeightCheck}, S_FLICKY_16_FLAP1, 0, S_FLICKY_16_OUT}, // S_FLICKY_16_OUT + {SPR_FL16, 1, 3, {A_FlickyFly}, 4*FRACUNIT, 8*FRACUNIT, S_FLICKY_16_FLAP2}, // S_FLICKY_16_FLAP1 + {SPR_FL16, 2, 3, {A_SetObjectFlags}, MF_NOGRAVITY, 1, S_FLICKY_16_FLAP3}, // S_FLICKY_16_FLAP2 + {SPR_FL16, 3, 3, {A_FlickyHeightCheck}, S_FLICKY_16_FLAP1, 0, S_FLICKY_16_FLAP3}, // S_FLICKY_16_FLAP3 // Yellow Spring {SPR_SPRY, 0, -1, {NULL}, 0, 0, S_NULL}, // S_YELLOWSPRING @@ -2279,6 +2471,21 @@ state_t states[NUMSTATES] = {SPR_WZAP, FF_TRANS10|FF_ANIMATE|FF_RANDOMANIM, 4, {NULL}, 3, 2, S_NULL}, // S_WATERZAP + // Spindash dust + {SPR_DUST, 0, 7, {NULL}, 0, 0, S_SPINDUST2}, // S_SPINDUST1 + {SPR_DUST, 1, 6, {NULL}, 0, 0, S_SPINDUST3}, // S_SPINDUST2 + {SPR_DUST, FF_TRANS30|2, 4, {NULL}, 0, 0, S_SPINDUST4}, // S_SPINDUST3 + {SPR_DUST, FF_TRANS60|3, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST4 + {SPR_BUBL, 0, 7, {NULL}, 0, 0, S_SPINDUST_BUBBLE2}, // S_SPINDUST_BUBBLE1 + {SPR_BUBL, 0, 6, {NULL}, 0, 0, S_SPINDUST_BUBBLE3}, // S_SPINDUST_BUBBLE2 + {SPR_BUBL, FF_TRANS30|0, 4, {NULL}, 0, 0, S_SPINDUST_BUBBLE4}, // S_SPINDUST_BUBBLE3 + {SPR_BUBL, FF_TRANS60|0, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST_BUBBLE4 + {SPR_FPRT, 0, 7, {NULL}, 0, 0, S_SPINDUST_FIRE2}, // S_SPINDUST_FIRE1 + {SPR_FPRT, 0, 6, {NULL}, 0, 0, S_SPINDUST_FIRE3}, // S_SPINDUST_FIRE2 + {SPR_FPRT, FF_TRANS30|0, 4, {NULL}, 0, 0, S_SPINDUST_FIRE4}, // S_SPINDUST_FIRE3 + {SPR_FPRT, FF_TRANS60|0, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST_FIRE4 + + {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50, 2, {NULL}, 0, 0, S_FOG2}, // S_FOG1 {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|1, 2, {NULL}, 0, 0, S_FOG3}, // S_FOG2 {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|2, 2, {NULL}, 0, 0, S_FOG4}, // S_FOG3 @@ -2295,7 +2502,7 @@ state_t states[NUMSTATES] = {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|13, 2, {NULL}, 0, 0, S_NULL}, // S_FOG14 // Flower Seed - {SPR_SEED, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_SEED + {SPR_SEED, FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 2, 2, S_NULL}, // S_SEED // Particle sprite {SPR_PRTL, FF_FULLBRIGHT|FF_TRANS70, 2*TICRATE, {NULL}, 0, 0, S_NULL}, // S_PARTICLE @@ -2535,25 +2742,25 @@ state_t states[NUMSTATES] = {SPR_FBLL, FF_FULLBRIGHT|6, 3, {NULL}, 0, 0, S_NULL}, // S_FIREBALLEXP3 // Turtle Shell - {SPR_SHLL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SHELL - {SPR_SHLL, 0, 2, {NULL}, 0, 0, S_SHELL2}, // S_SHELL1 - {SPR_SHLL, 1, 2, {NULL}, 0, 0, S_SHELL3}, // S_SHELL2 - {SPR_SHLL, 2, 2, {NULL}, 0, 0, S_SHELL4}, // S_SHELL3 - {SPR_SHLL, 3, 2, {NULL}, 0, 0, S_SHELL1}, // S_SHELL4 + {SPR_SHLL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SHELL // Puma (Mario fireball) - {SPR_PUMA, FF_FULLBRIGHT, 3, {A_FishJump}, 0, 0, S_PUMA2}, // S_PUMA1 - {SPR_PUMA, FF_FULLBRIGHT|1, 3, {A_FishJump}, 0, 0, S_PUMA3}, // S_PUMA2 - {SPR_PUMA, FF_FULLBRIGHT|2, 3, {A_FishJump}, 0, 0, S_PUMA1}, // S_PUMA3 - {SPR_PUMA, FF_FULLBRIGHT|3, 3, {A_FishJump}, 0, 0, S_PUMA5}, // S_PUMA4 - {SPR_PUMA, FF_FULLBRIGHT|4, 3, {A_FishJump}, 0, 0, S_PUMA6}, // S_PUMA5 - {SPR_PUMA, FF_FULLBRIGHT|5, 3, {A_FishJump}, 0, 0, S_PUMA4}, // S_PUMA6 + {SPR_PUMA, FF_FULLBRIGHT|2, 1, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_START2}, // S_PUMA_START1 + {SPR_PUMA, FF_FULLBRIGHT|2, 1, {A_PlaySound}, sfx_s3k70, 1, S_PUMA_UP1}, // S_PUMA_START2 + {SPR_PUMA, FF_FULLBRIGHT , 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_UP2}, // S_PUMA_UP1 + {SPR_PUMA, FF_FULLBRIGHT|1, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_UP3}, // S_PUMA_UP2 + {SPR_PUMA, FF_FULLBRIGHT|2, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_UP1}, // S_PUMA_UP3 + {SPR_PUMA, FF_FULLBRIGHT|3, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_DOWN2}, // S_PUMA_DOWN1 + {SPR_PUMA, FF_FULLBRIGHT|4, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_DOWN3}, // S_PUMA_DOWN2 + {SPR_PUMA, FF_FULLBRIGHT|5, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_DOWN1}, // S_PUMA_DOWN3 + + {SPR_PUMA, FF_FULLBRIGHT|FF_TRANS20|6, 4, {NULL}, 0, 0, S_PUMATRAIL2}, // S_PUMATRAIL1 + {SPR_PUMA, FF_FULLBRIGHT|FF_TRANS40|6, 5, {A_SetScale}, FRACUNIT, 1, S_PUMATRAIL3}, // S_PUMATRAIL2 + {SPR_PUMA, FF_FULLBRIGHT|FF_TRANS50|7, 4, {NULL}, 0, 0, S_PUMATRAIL4}, // S_PUMATRAIL3 + {SPR_PUMA, FF_FULLBRIGHT|FF_TRANS60|8, 3, {NULL}, 0, 0, S_NULL}, // S_PUMATRAIL4 // Hammer - {SPR_HAMM, 0, 3, {NULL}, 0, 0, S_HAMMER2}, // S_HAMMER1 - {SPR_HAMM, 1, 3, {NULL}, 0, 0, S_HAMMER3}, // S_HAMMER2 - {SPR_HAMM, 2, 3, {NULL}, 0, 0, S_HAMMER4}, // S_HAMMER3 - {SPR_HAMM, 3, 3, {NULL}, 0, 0, S_HAMMER1}, // S_HAMMER4 + {SPR_HAMM, FF_ANIMATE, -1, {NULL}, 4, 3, S_NULL}, // S_HAMMER // Koopa {SPR_KOOP, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KOOPA1 @@ -2690,14 +2897,15 @@ state_t states[NUMSTATES] = {SPR_CEMG, FF_FULLBRIGHT|15, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM16 // Flicky helper for NiGHTS - {SPR_BIRD, 0, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER2}, // S_NIGHTOPIANHELPER1 - {SPR_BIRD, 0, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER3}, // S_NIGHTOPIANHELPER2 - {SPR_BIRD, 0, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER4}, // S_NIGHTOPIANHELPER3 - {SPR_BIRD, 0, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER5}, // S_NIGHTOPIANHELPER4 - {SPR_BIRD, 1, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER6}, // S_NIGHTOPIANHELPER5 - {SPR_BIRD, 1, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER7}, // S_NIGHTOPIANHELPER6 - {SPR_BIRD, 1, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER8}, // S_NIGHTOPIANHELPER7 - {SPR_BIRD, 1, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER1}, // S_NIGHTOPIANHELPER8 + {SPR_FL01, 1, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER2}, // S_NIGHTOPIANHELPER1 + {SPR_FL01, 1, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER3}, // S_NIGHTOPIANHELPER2 + {SPR_FL01, 1, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER4}, // S_NIGHTOPIANHELPER3 + {SPR_FL01, 2, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER5}, // S_NIGHTOPIANHELPER4 + {SPR_FL01, 2, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER6}, // S_NIGHTOPIANHELPER5 + {SPR_FL01, 2, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER7}, // S_NIGHTOPIANHELPER6 + {SPR_FL01, 3, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER8}, // S_NIGHTOPIANHELPER7 + {SPR_FL01, 3, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER9}, // S_NIGHTOPIANHELPER8 + {SPR_FL01, 3, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER1}, // S_NIGHTOPIANHELPER9 {SPR_NULL, 0, 35, {NULL}, 0, 0, S_CRUMBLE2}, // S_CRUMBLE1 {SPR_NULL, 0, 105, {A_Scream}, 0, 0, S_NULL}, // S_CRUMBLE2 @@ -2721,10 +2929,11 @@ state_t states[NUMSTATES] = {SPR_SPRK, FF_TRANS90|3, 1, {NULL}, 0, 0, S_NULL}, // S_SPRK16 // Robot Explosion - {SPR_BOM1, 0, 1, {A_Scream}, 0, 0, S_XPLD2}, // S_XPLD1 - {SPR_BOM1, 1, 5, {NULL}, 0, 0, S_XPLD3}, // S_XPLD2 - {SPR_BOM1, 2, 5, {NULL}, 0, 0, S_XPLD4}, // S_XPLD3 - {SPR_BOM1, 3, 5, {NULL}, 0, 0, S_NULL}, // S_XPLD4 + {SPR_BOM1, 0, 0, {A_FlickySpawn}, 0, 0, S_XPLD1}, // S_XPLD_FLICKY + {SPR_BOM1, 0, 1, {A_Scream}, 0, 0, S_XPLD2}, // S_XPLD1 + {SPR_BOM1, FF_ANIMATE|1, 15, {NULL}, 2, 5, S_NULL}, // S_XPLD2 + + {SPR_BOM1, FF_ANIMATE, 20, {NULL}, 3, 5, S_INVISIBLE}, // S_XPLD_EGGTRAP // Underwater Explosion {SPR_BOM4, 0, 3, {A_Scream}, 0, 0, S_WPLD2}, // S_WPLD1 @@ -2881,7 +3090,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_NULL, // xdeathstate sfx_pop, // deathsound 3, // speed @@ -2908,7 +3117,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_NULL, // xdeathstate sfx_pop, // deathsound 3, // speed @@ -2935,7 +3144,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_FISH3, // meleestate S_NULL, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_FISH4, // xdeathstate sfx_pop, // deathsound 0, // speed @@ -2962,12 +3171,12 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_NULL, // xdeathstate sfx_pop, // deathsound 4*FRACUNIT, // speed - 20*FRACUNIT, // radius - 24*FRACUNIT, // height + 28*FRACUNIT, // radius + 40*FRACUNIT, // height 0, // display offset 100, // mass 0, // damage @@ -2989,12 +3198,12 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_NULL, // xdeathstate sfx_pop, // deathsound 8*FRACUNIT, // speed - 20*FRACUNIT, // radius - 24*FRACUNIT, // height + 28*FRACUNIT, // radius + 40*FRACUNIT, // height 0, // display offset 100, // mass 0, // damage @@ -3016,7 +3225,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_NULL, // xdeathstate sfx_pop, // deathsound 6*FRACUNIT, // speed @@ -3043,7 +3252,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_NULL, // xdeathstate sfx_pop, // deathsound 1*FRACUNIT, // speed @@ -3070,7 +3279,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_JETGSHOOT1, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_NULL, // xdeathstate sfx_pop, // deathsound 1*FRACUNIT, // speed @@ -3097,7 +3306,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_dmpain, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_NULL, // xdeathstate sfx_pop, // deathsound 3, // speed @@ -3124,7 +3333,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_DETON16, // xdeathstate sfx_pop, // deathsound 1*FRACUNIT, // speed @@ -3151,7 +3360,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_SKIM3, // meleestate S_NULL, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_NULL, // xdeathstate sfx_pop, // deathsound 8, // speed @@ -3205,7 +3414,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_s3k64, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_NULL, // xdeathstate sfx_pop, // deathsound 0, // speed @@ -3232,7 +3441,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_SHARP_AIM1, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_SHARP_SPIN, // xdeathstate sfx_pop, // deathsound 2, // speed @@ -3259,7 +3468,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_NULL, // xdeathstate sfx_pop, // deathsound 8, // speed @@ -3286,7 +3495,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_NULL, // xdeathstate sfx_pop, // deathsound FRACUNIT, // speed @@ -3313,7 +3522,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_VULTURE_ZOOM1,// missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_NULL, // xdeathstate sfx_pop, // deathsound 3, // speed @@ -3340,7 +3549,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_NULL, // xdeathstate sfx_pop, // deathsound 5*FRACUNIT, // speed @@ -3394,7 +3603,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_ROBOHOOD_SHOOT, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_ROBOHOOD_JUMP2, // xdeathstate sfx_pop, // deathsound 0, // speed @@ -3421,7 +3630,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_FACESTABBER_CHARGE1, // meleestate S_NULL, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_NULL, // xdeathstate sfx_pop, // deathsound 3, // speed @@ -3448,7 +3657,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_EGGGUARD_RUN1, // meleestate S_NULL, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_NULL, // xdeathstate sfx_pop, // deathsound 6, // speed @@ -3502,7 +3711,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_NULL, // xdeathstate sfx_pop, // deathsound 3, // speed @@ -3529,7 +3738,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_MINUS_DOWNWARD1,// meleestate S_MINUS_POPUP, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_NULL, // xdeathstate sfx_pop, // deathsound 12, // speed @@ -3556,7 +3765,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_spring, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_NULL, // xdeathstate sfx_pop, // deathsound 6, // speed @@ -3583,7 +3792,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_spring, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_NULL, // xdeathstate sfx_pop, // deathsound 6, // speed @@ -3610,7 +3819,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_XPLD1, // deathstate + S_XPLD_FLICKY, // deathstate S_NULL, // xdeathstate sfx_pop, // deathsound 2, // speed @@ -4110,6 +4319,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_GOOPTRAIL + -1, // doomednum + S_GOOPTRAIL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 3, // speed + 4*FRACUNIT, // radius + 4*FRACUNIT, // height + 0, // display offset + 4, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_EGGMOBILE3 202, // doomednum S_EGGMOBILE3_STND, // spawnstate @@ -4497,7 +4733,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate - 0, // painchance + MT_NULL, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate @@ -5760,7 +5996,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound - S_STARPOST_SPIN, // painstate + S_STARPOST_STARTSPIN, // painstate 0, // painchance sfx_strpst, // painsound S_NULL, // meleestate @@ -5770,7 +6006,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // deathsound 8, // speed 64*FRACUNIT, // radius - 80*FRACUNIT, // height + 128*FRACUNIT, // height 0, // display offset 4, // mass 0, // damage @@ -6346,6 +6582,87 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_FLAMEAURA_BOX + 420, // doomednum + S_FLAMEAURA_BOX, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_FLAMEAURA_BOX, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_BOX_POP1, // deathstate + S_NULL, // xdeathstate + sfx_pop, // deathsound + 1, // speed + 16*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 100, // mass + MT_FLAMEAURA_ICON, // damage + sfx_None, // activesound + MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + S_NULL // raisestate + }, + + { // MT_BUBBLEWRAP_BOX + 421, // doomednum + S_BUBBLEWRAP_BOX, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_BUBBLEWRAP_BOX, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_BOX_POP1, // deathstate + S_NULL, // xdeathstate + sfx_pop, // deathsound + 1, // speed + 16*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 100, // mass + MT_BUBBLEWRAP_ICON, // damage + sfx_None, // activesound + MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + S_NULL // raisestate + }, + + { // MT_THUNDERCOIN_BOX + 422, // doomednum + S_THUNDERCOIN_BOX, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_THUNDERCOIN_BOX, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_BOX_POP1, // deathstate + S_NULL, // xdeathstate + sfx_pop, // deathsound + 1, // speed + 16*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 100, // mass + MT_THUNDERCOIN_ICON, // damage + sfx_None, // activesound + MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags + S_NULL // raisestate + }, + { // MT_PITY_GOLDBOX 431, // doomednum S_PITY_GOLDBOX, // spawnstate @@ -6616,6 +6933,87 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_FLAMEAURA_GOLDBOX + 450, // doomednum + S_FLAMEAURA_GOLDBOX, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_monton, // attacksound + S_FLAMEAURA_GOLDBOX, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_GOLDBOX_OFF1, // deathstate + S_NULL, // xdeathstate + sfx_pop, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 36*FRACUNIT, // height + 0, // display offset + 100, // mass + MT_FLAMEAURA_ICON, // damage + sfx_None, // activesound + MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + S_NULL // raisestate + }, + + { // MT_BUBBLEWRAP_GOLDBOX + 451, // doomednum + S_BUBBLEWRAP_GOLDBOX, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_monton, // attacksound + S_BUBBLEWRAP_GOLDBOX, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_GOLDBOX_OFF1, // deathstate + S_NULL, // xdeathstate + sfx_pop, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 36*FRACUNIT, // height + 0, // display offset + 100, // mass + MT_BUBBLEWRAP_ICON, // damage + sfx_None, // activesound + MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + S_NULL // raisestate + }, + + { // MT_THUNDERCOIN_GOLDBOX + 452, // doomednum + S_THUNDERCOIN_GOLDBOX, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_monton, // attacksound + S_THUNDERCOIN_GOLDBOX, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_GOLDBOX_OFF1, // deathstate + S_NULL, // xdeathstate + sfx_pop, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 36*FRACUNIT, // height + 0, // display offset + 100, // mass + MT_THUNDERCOIN_ICON, // damage + sfx_None, // activesound + MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags + S_NULL // raisestate + }, + { // MT_RING_REDBOX 414, // doomednum S_RING_REDBOX1, // spawnstate @@ -6702,7 +7100,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_PITY_ICON1, // spawnstate 1, // spawnhealth S_NULL, // seestate - sfx_shield, // seesound + sfx_s3k3a, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate @@ -6729,7 +7127,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_ATTRACT_ICON1, // spawnstate 1, // spawnhealth S_NULL, // seestate - sfx_shield, // seesound + sfx_s3k41, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate @@ -6756,7 +7154,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_FORCE_ICON1, // spawnstate 1, // spawnhealth S_NULL, // seestate - sfx_shield, // seesound + sfx_forcsg, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate @@ -6783,7 +7181,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_ARMAGEDDON_ICON1, // spawnstate 1, // spawnhealth S_NULL, // seestate - sfx_shield, // seesound + sfx_armasg, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate @@ -6810,7 +7208,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_WHIRLWIND_ICON1, // spawnstate 1, // spawnhealth S_NULL, // seestate - sfx_shield, // seesound + sfx_wirlsg, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate @@ -6837,7 +7235,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_ELEMENTAL_ICON1, // spawnstate 1, // spawnhealth S_NULL, // seestate - sfx_shield, // seesound + sfx_elemsg, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate @@ -7102,6 +7500,87 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_FLAMEAURA_ICON + -1, // doomednum + S_FLAMEAURA_ICON1, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_s3k3e, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 2*FRACUNIT, // speed + 8*FRACUNIT, // radius + 14*FRACUNIT, // height + 0, // display offset + 100, // mass + 62*FRACUNIT, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags + S_NULL // raisestate + }, + + { // MT_BUBBLEWRAP_ICON + -1, // doomednum + S_BUBBLEWRAP_ICON1, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_s3k3f, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 2*FRACUNIT, // speed + 8*FRACUNIT, // radius + 14*FRACUNIT, // height + 0, // display offset + 100, // mass + 62*FRACUNIT, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags + S_NULL // raisestate + }, + + { // MT_THUNDERCOIN_ICON + -1, // doomednum + S_THUNDERCOIN_ICON1, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_s3k41, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 2*FRACUNIT, // speed + 8*FRACUNIT, // radius + 14*FRACUNIT, // height + 0, // display offset + 100, // mass + 62*FRACUNIT, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags + S_NULL // raisestate + }, + { // MT_ROCKET -1, // doomednum S_ROCKET, // spawnstate @@ -7455,7 +7934,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_GFZFLOWER2 801, // doomednum - S_GFZFLOWERB1, // spawnstate + S_GFZFLOWERB, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -7482,7 +7961,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_GFZFLOWER3 802, // doomednum - S_GFZFLOWERC1, // spawnstate + S_GFZFLOWERC, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -7503,7 +7982,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags S_NULL // raisestate }, @@ -7561,9 +8040,36 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_THZPLANT + { // MT_THZFLOWER1 900, // doomednum - S_THZPLANT1, // spawnstate + S_THZFLOWERA, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 8*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_THZFLOWER2 + 902, // doomednum + S_THZFLOWERB, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -7867,7 +8373,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate - 0, // painchance + MT_FLAMEPARTICLE, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate @@ -7885,6 +8391,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_FLAMEPARTICLE + -1, // doomednum + S_FLAMEPARTICLE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + FRACUNIT, // radius + FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SCENERY, // flags + S_NULL // raisestate + }, + { // MT_EGGSTATUE 1102, // doomednum S_EGGSTATUE1, // spawnstate @@ -8452,33 +8985,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_FJSPINHELPERA - -1, // doomednum - S_FJSPINHELPERA1,// spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 10*FRACUNIT, // speed - 16*FRACUNIT, // radius - 1*FRACUNIT, // height - 0, // display offset - 100, // mass - 1, // damage - sfx_None, // activesound - MF_NOCLIP|MF_NOCLIPTHING|MF_NOGRAVITY|MF_NOSECTOR, // flags - S_NULL // raisestate - }, - { // MT_FJSPINAXISB 3576, // doomednum S_FJSPINAXISB1, // spawnstate @@ -8506,33 +9012,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_FJSPINHELPERB - -1, // doomednum - S_FJSPINHELPERB1,// spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 10*FRACUNIT, // speed - 16*FRACUNIT, // radius - 1*FRACUNIT, // height - 0, // display offset - 100, // mass - 1, // damage - sfx_None, // activesound - MF_NOCLIP|MF_NOCLIPTHING|MF_NOGRAVITY|MF_NOSECTOR, // flags - S_NULL // raisestate - }, - { // MT_FLAMEJETFLAMEB -1, // doomednum S_FLAMEJETFLAMEB1, // spawnstate @@ -10237,9 +10716,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_BSZFISH + { // MT_BIG_PALMTREE_TRUNK 1472, // doomednum - S_BSZFISH, // spawnstate + S_BIG_PALMTREE_TRUNK, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -10264,9 +10743,63 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_BSZSUNFLOWER + { // MT_BIG_PALMTREE_TOP 1473, // doomednum - S_BSZSUNFLOWER, // spawnstate + S_BIG_PALMTREE_TOP, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_PALMTREE_TRUNK + 1474, // doomednum + S_PALMTREE_TRUNK, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_PALMTREE_TOP + 1475, // doomednum + S_PALMTREE_TOP, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -10345,7 +10878,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_GREENORB + { // MT_ELEMENTAL_ORB -1, // doomednum S_ELEM1, // spawnstate 1000, // spawnhealth @@ -10353,7 +10886,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // seesound 0, // reactiontime sfx_None, // attacksound - S_NULL, // painstate + S_ELEM13, // painstate SKINCOLOR_NONE, // painchance sfx_None, // painsound S_NULL, // meleestate @@ -10364,15 +10897,15 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = SH_ELEMENTAL, // speed 64*FRACUNIT, // radius 64*FRACUNIT, // height - 1, // display offset + 2, // display offset 16, // mass 0, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags - S_NULL // raisestate + S_ELEMF9 // raisestate }, - { // MT_YELLOWORB + { // MT_ATTRACT_ORB -1, // doomednum S_MAGN1, // spawnstate 1000, // spawnhealth @@ -10380,7 +10913,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound - S_NULL, // painstate + S_MAGN13, // painstate SKINCOLOR_NONE, // painchance sfx_None, // painsound S_NULL, // meleestate @@ -10391,7 +10924,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = SH_ATTRACT, // speed 64*FRACUNIT, // radius 64*FRACUNIT, // height - 1, // display offset + 2, // display offset 16, // mass 0, // damage sfx_None, // activesound @@ -10399,7 +10932,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_BLUEORB + { // MT_FORCE_ORB -1, // doomednum S_FORC1, // spawnstate 1000, // spawnhealth @@ -10418,15 +10951,15 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = SH_FORCE, // speed 64*FRACUNIT, // radius 64*FRACUNIT, // height - 1, // display offset + 2, // display offset 16, // mass 0, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags - S_NULL // raisestate + S_FORC21 // raisestate }, - { // MT_BLACKORB + { // MT_ARMAGEDDON_ORB -1, // doomednum S_ARMA1, // spawnstate 1000, // spawnhealth @@ -10442,10 +10975,10 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound - SH_BOMB, // speed + SH_ARMAGEDDON, // speed 64*FRACUNIT, // radius 64*FRACUNIT, // height - 1, // display offset + 2, // display offset 16, // mass 0, // damage sfx_None, // activesound @@ -10453,7 +10986,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_WHITEORB + { // MT_WHIRLWIND_ORB -1, // doomednum S_WIND1, // spawnstate 1000, // spawnhealth @@ -10469,10 +11002,10 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound - SH_JUMP, // speed + SH_WHIRLWIND, // speed 64*FRACUNIT, // radius 64*FRACUNIT, // height - 1, // display offset + 2, // display offset 16, // mass 0, // damage sfx_None, // activesound @@ -10480,7 +11013,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_PITYORB + { // MT_PITY_ORB -1, // doomednum S_PITY1, // spawnstate 1000, // spawnhealth @@ -10499,7 +11032,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = SH_PITY, // speed 64*FRACUNIT, // radius 64*FRACUNIT, // height - 1, // display offset + 2, // display offset 16, // mass 0, // damage sfx_None, // activesound @@ -10507,6 +11040,114 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_FLAMEAURA_ORB + -1, // doomednum + S_FIRSB1, // spawnstate + 1000, // spawnhealth + S_FIRS1, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_FIRSB10, // painstate + SKINCOLOR_NONE, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + SH_FLAMEAURA, // speed + 64*FRACUNIT, // radius + 64*FRACUNIT, // height + -2, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + S_FIRS10 // raisestate + }, + + { // MT_BUBBLEWRAP_ORB + -1, // doomednum + S_BUBSB1, // spawnstate + 1000, // spawnhealth + S_BUBS1, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_BUBSB5, // painstate + SKINCOLOR_NONE, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + SH_BUBBLEWRAP, // speed + 64*FRACUNIT, // radius + 64*FRACUNIT, // height + 2, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + S_BUBS10 // raisestate + }, + + { // MT_THUNDERCOIN_ORB + -1, // doomednum + S_ZAPSB1, // spawnstate + 1000, // spawnhealth + S_ZAPS1, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_ZAPSB11, // painstate + SKINCOLOR_NONE, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + SH_THUNDERCOIN, // speed + 64*FRACUNIT, // radius + 64*FRACUNIT, // height + -2, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + S_ZAPS14 // raisestate + }, + + { // MT_THUNDERCOIN_SPARK + -1, // doomednum + S_THUNDERCOIN_SPARK, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 4*FRACUNIT, // radius + 4*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + S_NULL // raisestate + }, + { // MT_IVSP -1, // doomednum S_IVSP, // spawnstate @@ -10526,7 +11167,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 8, // speed 64*FRACUNIT, // radius 64*FRACUNIT, // height - 2, // display offset + 3, // display offset 16, // mass 0, // damage sfx_None, // activesound @@ -10561,148 +11202,121 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_BIRD + // Bluebird + { // MT_FLICKY_01 -1, // doomednum - S_BIRD1, // spawnstate + S_FLICKY_01_OUT, // spawnstate 1000, // spawnhealth - S_BIRD1, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 8, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 0, // display offset - 16, // mass - 0, // damage - sfx_None, // activesound - MF_NOCLIPTHING|MF_FLOAT|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - // freed bunny - { // MT_BUNNY - -1, // doomednum - S_BUNNY1, // spawnstate - 1000, // spawnhealth - S_BUNNY1, // seestate - sfx_None, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 8, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 0, // display offset - 16, // mass - 0, // damage - sfx_None, // activesound - MF_NOCLIPTHING|MF_FLOAT, // flags - S_NULL // raisestate - }, - - { // MT_MOUSE - -1, // doomednum - S_MOUSE1, // spawnstate - 1, // spawnhealth S_NULL, // seestate sfx_None, // seesound - 1, // reactiontime + 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate - 200, // painchance + 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound - 20*FRACUNIT, // speed - 4*FRACUNIT, // radius - 4*FRACUNIT, // height + 8, // speed + 8*FRACUNIT, // radius + 20*FRACUNIT, // height 0, // display offset - 100, // mass + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOCLIPTHING, // flags + S_FLICKY_BUBBLE // raisestate + }, + + { // MT_FLICKY_02 + -1, // doomednum + S_FLICKY_02_OUT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 8*FRACUNIT, // radius + 20*FRACUNIT, // height + 0, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOCLIPTHING, // flags + S_FLICKY_BUBBLE // raisestate + }, + + { // MT_FLICKY_03 + -1, // doomednum + S_FLICKY_03_OUT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 8*FRACUNIT, // radius + 20*FRACUNIT, // height + 0, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOCLIPTHING, // flags + S_FLICKY_BUBBLE // raisestate + }, + + { // MT_FLICKY_04 + -1, // doomednum + S_FLICKY_04_OUT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_FLICKY_04_SWIM1, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 8*FRACUNIT, // radius + 20*FRACUNIT, // height + 0, // display offset + 16, // mass 0, // damage sfx_None, // activesound MF_NOCLIPTHING, // flags S_NULL // raisestate }, - { // MT_CHICKEN + { // MT_FLICKY_05 -1, // doomednum - S_CHICKEN1, // spawnstate + S_FLICKY_05_OUT, // spawnstate 1000, // spawnhealth - S_CHICKEN1, // seestate - sfx_None, // seesound - 0, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 1, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height - 0, // display offset - 16, // mass - 0, // damage - sfx_None, // activesound - MF_NOCLIPTHING|MF_FLOAT, // flags - S_NULL // raisestate - }, - - { // MT_COW - -1, // doomednum - S_COW1, // spawnstate - 1, // spawnhealth S_NULL, // seestate sfx_None, // seesound - 1, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 200, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_NULL, // deathstate - S_NULL, // xdeathstate - sfx_None, // deathsound - 4, // speed - 4*FRACUNIT, // radius - 4*FRACUNIT, // height - 0, // display offset - 100, // mass - 0, // damage - sfx_None, // activesound - MF_NOCLIPTHING, // flags - S_NULL // raisestate - }, - - { // MT_REDBIRD - -1, // doomednum - S_RBIRD1, // spawnstate - 1000, // spawnhealth - S_RBIRD1, // seestate - sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate @@ -10714,16 +11328,313 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 8, // speed - 16*FRACUNIT, // radius - 16*FRACUNIT, // height + 8*FRACUNIT, // radius + 20*FRACUNIT, // height 0, // display offset 16, // mass 0, // damage sfx_None, // activesound - MF_NOCLIPTHING|MF_FLOAT|MF_NOGRAVITY, // flags + MF_NOCLIPTHING, // flags + S_FLICKY_BUBBLE // raisestate + }, + + { // MT_FLICKY_06 + -1, // doomednum + S_FLICKY_06_OUT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 8*FRACUNIT, // radius + 20*FRACUNIT, // height + 0, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOCLIPTHING, // flags + S_FLICKY_BUBBLE // raisestate + }, + + { // MT_FLICKY_07 + -1, // doomednum + S_FLICKY_07_OUT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_FLICKY_07_SWIM1, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 8*FRACUNIT, // radius + 20*FRACUNIT, // height + 0, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOCLIPTHING, // flags S_NULL // raisestate }, + { // MT_FLICKY_08 + -1, // doomednum + S_FLICKY_08_OUT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_FLICKY_08_SWIM1, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 8*FRACUNIT, // radius + 20*FRACUNIT, // height + 0, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOCLIPTHING, // flags + S_NULL // raisestate + }, + + { // MT_FLICKY_09 + -1, // doomednum + S_FLICKY_09_OUT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 8*FRACUNIT, // radius + 20*FRACUNIT, // height + 0, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOCLIPTHING, // flags + S_FLICKY_BUBBLE // raisestate + }, + + { // MT_FLICKY_10 + -1, // doomednum + S_FLICKY_10_OUT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 8*FRACUNIT, // radius + 20*FRACUNIT, // height + 0, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOCLIPTHING, // flags + S_FLICKY_BUBBLE // raisestate + }, + + { // MT_FLICKY_11 + -1, // doomednum + S_FLICKY_11_OUT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 8*FRACUNIT, // radius + 20*FRACUNIT, // height + 0, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOCLIPTHING, // flags + S_FLICKY_BUBBLE // raisestate + }, + + { // MT_FLICKY_12 + -1, // doomednum + S_FLICKY_12_OUT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 8*FRACUNIT, // radius + 20*FRACUNIT, // height + 0, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOCLIPTHING, // flags + S_FLICKY_BUBBLE // raisestate + }, + + { // MT_FLICKY_13 + -1, // doomednum + S_FLICKY_13_OUT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 8*FRACUNIT, // radius + 20*FRACUNIT, // height + 0, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOCLIPTHING, // flags + S_FLICKY_BUBBLE // raisestate + }, + + { // MT_FLICKY_14 + -1, // doomednum + S_FLICKY_14_OUT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 8*FRACUNIT, // radius + 20*FRACUNIT, // height + 0, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOCLIPTHING, // flags + S_FLICKY_BUBBLE // raisestate + }, + + { // MT_FLICKY_15 + -1, // doomednum + S_FLICKY_15_OUT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 8*FRACUNIT, // radius + 20*FRACUNIT, // height + 0, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOCLIPTHING, // flags + S_FLICKY_BUBBLE // raisestate + }, + + { // MT_FLICKY_16 + -1, // doomednum + S_FLICKY_16_OUT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 8*FRACUNIT, // radius + 20*FRACUNIT, // height + 0, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOCLIPTHING, // flags + S_FLICKY_BUBBLE // raisestate + }, + { // MT_RAIN -1, // doomednum S_RAIN1, // spawnstate @@ -10940,6 +11851,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_SPINDUST + -1, // doomednum + S_SPINDUST1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 4*FRACUNIT, // speed + 4*FRACUNIT, // radius + 4*FRACUNIT, // height + 0, // display offset + 4, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIP, // flags + S_NULL // raisestate + }, + { // MT_TFOG -1, // doomednum S_FOG1, // spawnstate @@ -10990,7 +11928,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 4, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_SCENERY, // flags S_NULL // raisestate }, @@ -12153,7 +13091,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate - sfx_mario3, // deathsound + sfx_None, // deathsound 0, // speed 16*FRACUNIT, // radius 32*FRACUNIT, // height @@ -12208,9 +13146,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound - 20*FRACUNIT, // speed - 8*FRACUNIT, // radius - 16*FRACUNIT, // height + 16, // speed + 16*FRACUNIT, // radius + 20*FRACUNIT, // height 0, // display offset 100, // mass 1, // damage @@ -12221,19 +13159,19 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_PUMA 1805, // doomednum - S_PUMA1, // spawnstate + S_PUMA_START1, // spawnstate 1000, // spawnhealth - S_PUMA1, // seestate + S_PUMA_START1, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound - S_PUMA4, // meleestate + S_PUMA_DOWN1, // meleestate S_NULL, // missilestate S_NULL, // deathstate - S_PUMA6, // xdeathstate + S_PUMA_DOWN3, // xdeathstate sfx_None, // deathsound 0, // speed 8*FRACUNIT, // radius @@ -12242,12 +13180,40 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 0, // damage sfx_None, // activesound - MF_PAIN|MF_FIRE, // flags + MF_PAIN|MF_FIRE, // flags S_NULL // raisestate }, + + { // MT_PUMATRAIL + -1, // doomednum + S_PUMATRAIL1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 2*FRACUNIT, // radius + 4*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_HAMMER -1, // doomednum - S_HAMMER1, // spawnstate + S_HAMMER, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -13458,7 +14424,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // display offset 1000, // mass 0, // damage - sfx_None, // activesound + sfx_crumbl, // activesound MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, @@ -13485,7 +14451,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // display offset 1000, // mass 0, // damage - sfx_None, // activesound + sfx_crumbl, // activesound MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, @@ -13512,7 +14478,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // display offset 1000, // mass 0, // damage - sfx_None, // activesound + sfx_crumbl, // activesound MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, @@ -13539,7 +14505,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // display offset 1000, // mass 0, // damage - sfx_None, // activesound + sfx_crumbl, // activesound MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, @@ -13566,7 +14532,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // display offset 1000, // mass 0, // damage - sfx_None, // activesound + sfx_crumbl, // activesound MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, @@ -13593,7 +14559,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // display offset 1000, // mass 0, // damage - sfx_None, // activesound + sfx_crumbl, // activesound MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, @@ -13620,7 +14586,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // display offset 1000, // mass 0, // damage - sfx_None, // activesound + sfx_crumbl, // activesound MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, @@ -13647,7 +14613,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // display offset 1000, // mass 0, // damage - sfx_None, // activesound + sfx_crumbl, // activesound MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, @@ -13674,7 +14640,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // display offset 1000, // mass 0, // damage - sfx_None, // activesound + sfx_crumbl, // activesound MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, @@ -13701,7 +14667,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // display offset 1000, // mass 0, // damage - sfx_None, // activesound + sfx_crumbl, // activesound MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, @@ -13728,7 +14694,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // display offset 1000, // mass 0, // damage - sfx_None, // activesound + sfx_crumbl, // activesound MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, @@ -13755,7 +14721,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // display offset 1000, // mass 0, // damage - sfx_None, // activesound + sfx_crumbl, // activesound MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, @@ -13782,7 +14748,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // display offset 1000, // mass 0, // damage - sfx_None, // activesound + sfx_crumbl, // activesound MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, @@ -13809,7 +14775,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // display offset 1000, // mass 0, // damage - sfx_None, // activesound + sfx_crumbl, // activesound MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, @@ -13836,7 +14802,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // display offset 1000, // mass 0, // damage - sfx_None, // activesound + sfx_crumbl, // activesound MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, @@ -13863,7 +14829,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // display offset 1000, // mass 0, // damage - sfx_None, // activesound + sfx_crumbl, // activesound MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, diff --git a/src/info.h b/src/info.h index b0683c172..1a6c14a70 100644 --- a/src/info.h +++ b/src/info.h @@ -56,6 +56,9 @@ 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_GravityBox(); void A_ScoreRise(); // Rise the score logo void A_ParticleSpawn(); @@ -211,6 +214,17 @@ void A_BrakFireShot(); void A_BrakLobShot(); void A_NapalmScatter(); void A_SpawnFreshCopy(); +void A_FlickySpawn(); +void A_FlickyAim(); +void A_FlickyFly(); +void A_FlickySoar(); +void A_FlickyCoast(); +void A_FlickyHop(); +void A_FlickyFlounder(); +void A_FlickyCheck(); +void A_FlickyHeightCheck(); +void A_FlickyFlutter(); +void A_FlameParticle(); // ratio of states to sprites to mobj types is roughly 6 : 1 : 1 #define NUMMOBJFREESLOTS 256 @@ -351,6 +365,9 @@ typedef enum sprite SPR_TVRC, // ReCycler SPR_TV1K, // 1,000 points (1 K) SPR_TVTK, // 10,000 points (Ten K) + SPR_TVFL, // FLame shield + SPR_TVBB, // BuBble shield + SPR_TVZP, // Thunder shield (ZaP) // Projectiles SPR_MISL, @@ -372,7 +389,8 @@ typedef enum sprite SPR_BUS2, // GFZ Bush w/o berries // Techno Hill Scenery - SPR_THZP, // Techno Hill Zone Plant + SPR_THZP, // THZ1 Flower + SPR_FWR5, // Another flower SPR_ALRM, // THZ2 Alarm // Deep Sea Scenery @@ -435,18 +453,32 @@ typedef enum sprite SPR_ELEM, // Elemental Shield Orb and Fire SPR_FORC, // Force Shield Orb SPR_PITY, // Pity Shield Orb + SPR_FIRS, // Flame Shield Orb + SPR_BUBS, // Bubble Shield Orb + SPR_ZAPS, // Thunder Shield Orb SPR_IVSP, // invincibility sparkles SPR_SSPK, // Super Sonic Spark SPR_GOAL, // Special Stage goal (here because lol NiGHTS) - // Freed Animals - SPR_BIRD, // Birdie freed! - SPR_BUNY, // Bunny freed! - SPR_MOUS, // Mouse - SPR_CHIC, // Chicken - SPR_COWZ, // Cow - SPR_RBRD, // Red Birdie in Bubble + // Flickies + SPR_FBUB, // Flicky-sized bubble + SPR_FL01, // Bluebird + SPR_FL02, // Rabbit + SPR_FL03, // Chicken + SPR_FL04, // Seal + SPR_FL05, // Pig + SPR_FL06, // Chipmunk + SPR_FL07, // Penguin + SPR_FL08, // Fish + SPR_FL09, // Ram + SPR_FL10, // Puffin + SPR_FL11, // Cow + SPR_FL12, // Rat + SPR_FL13, // Bear + SPR_FL14, // Dove + SPR_FL15, // Cat + SPR_FL16, // Canary // Springs SPR_SPRY, // yellow spring @@ -466,6 +498,8 @@ typedef enum sprite SPR_SMOK, SPR_BUBL, // Bubble SPR_WZAP, + SPR_DUST, // Spindash dust + SPR_FPRT, // Spindash dust (flame) SPR_TFOG, // Teleport Fog SPR_SEED, // Sonic CD flower seed SPR_PRTL, // Particle (for fans, etc.) @@ -1168,6 +1202,7 @@ typedef enum state S_GOOP1, S_GOOP2, S_GOOP3, + S_GOOPTRAIL, // Boss 3 S_EGGMOBILE3_STND, @@ -1723,7 +1758,7 @@ typedef enum state S_SPIKEBALL7, S_SPIKEBALL8, - // Fire Shield's Spawn + // Elemental Shield's Spawn S_SPINFIRE1, S_SPINFIRE2, S_SPINFIRE3, @@ -1744,7 +1779,9 @@ typedef enum state // Starpost S_STARPOST_IDLE, S_STARPOST_FLASH, + S_STARPOST_STARTSPIN, S_STARPOST_SPIN, + S_STARPOST_ENDSPIN, // Big floating mine S_BIGMINE1, @@ -1797,6 +1834,9 @@ typedef enum state S_RECYCLER_BOX, S_SCORE1K_BOX, S_SCORE10K_BOX, + S_FLAMEAURA_BOX, + S_BUBBLEWRAP_BOX, + S_THUNDERCOIN_BOX, // Gold Repeat Monitor States (one per box) S_PITY_GOLDBOX, @@ -1809,6 +1849,9 @@ typedef enum state S_INVULN_GOLDBOX, S_EGGMAN_GOLDBOX, S_GRAVITY_GOLDBOX, + S_FLAMEAURA_GOLDBOX, + S_BUBBLEWRAP_GOLDBOX, + S_THUNDERCOIN_GOLDBOX, // Team Ring Boxes (these are special) S_RING_REDBOX1, @@ -1870,6 +1913,15 @@ typedef enum state S_SCORE10K_ICON1, S_SCORE10K_ICON2, + S_FLAMEAURA_ICON1, + S_FLAMEAURA_ICON2, + + S_BUBBLEWRAP_ICON1, + S_BUBBLEWRAP_ICON2, + + S_THUNDERCOIN_ICON1, + S_THUNDERCOIN_ICON2, + // --- S_ROCKET, @@ -1913,21 +1965,15 @@ typedef enum state S_DEMONFIRE6, S_GFZFLOWERA, - S_GFZFLOWERA2, - - S_GFZFLOWERB1, - S_GFZFLOWERB2, - - S_GFZFLOWERC1, + S_GFZFLOWERB, + S_GFZFLOWERC, S_BERRYBUSH, S_BUSH, // THZ Plant - S_THZPLANT1, - S_THZPLANT2, - S_THZPLANT3, - S_THZPLANT4, + S_THZFLOWERA, + S_THZFLOWERB, // THZ Alarm S_ALARM1, @@ -1972,6 +2018,11 @@ typedef enum state S_FLAME2, S_FLAME3, S_FLAME4, + S_FLAME5, + S_FLAME6, + S_FLAMEPARTICLE, + + S_FLAMEREST, // Eggman Statue S_EGGSTATUE1, @@ -2033,36 +2084,13 @@ typedef enum state // Spinning flame jets S_FJSPINAXISA1, // Counter-clockwise S_FJSPINAXISA2, - S_FJSPINAXISA3, - S_FJSPINAXISA4, - S_FJSPINAXISA5, - S_FJSPINAXISA6, - S_FJSPINAXISA7, - S_FJSPINAXISA8, - S_FJSPINAXISA9, - S_FJSPINHELPERA1, - S_FJSPINHELPERA2, - S_FJSPINHELPERA3, S_FJSPINAXISB1, // Clockwise S_FJSPINAXISB2, - S_FJSPINAXISB3, - S_FJSPINAXISB4, - S_FJSPINAXISB5, - S_FJSPINAXISB6, - S_FJSPINAXISB7, - S_FJSPINAXISB8, - S_FJSPINAXISB9, - S_FJSPINHELPERB1, - S_FJSPINHELPERB2, - S_FJSPINHELPERB3, // Blade's flame S_FLAMEJETFLAMEB1, S_FLAMEJETFLAMEB2, S_FLAMEJETFLAMEB3, - S_FLAMEJETFLAMEB4, - S_FLAMEJETFLAMEB5, - S_FLAMEJETFLAMEB6, // Trapgoyles S_TRAPGOYLE, @@ -2157,8 +2185,10 @@ typedef enum state S_BSZVINE_ORANGE, S_BSZSHRUB, S_BSZCLOVER, - S_BSZFISH, - S_BSZSUNFLOWER, + S_BIG_PALMTREE_TRUNK, + S_BIG_PALMTREE_TOP, + S_PALMTREE_TRUNK, + S_PALMTREE_TOP, S_DBALL1, S_DBALL2, @@ -2241,6 +2271,7 @@ typedef enum state S_MAGN10, S_MAGN11, S_MAGN12, + S_MAGN13, S_FORC1, S_FORC2, @@ -2264,6 +2295,8 @@ typedef enum state S_FORC19, S_FORC20, + S_FORC21, + S_ELEM1, S_ELEM2, S_ELEM3, @@ -2277,6 +2310,9 @@ typedef enum state S_ELEM11, S_ELEM12, + S_ELEM13, + S_ELEM14, + S_ELEMF1, S_ELEMF2, S_ELEMF3, @@ -2285,6 +2321,8 @@ typedef enum state S_ELEMF6, S_ELEMF7, S_ELEMF8, + S_ELEMF9, + S_ELEMF10, S_PITY1, S_PITY2, @@ -2297,6 +2335,84 @@ typedef enum state S_PITY9, S_PITY10, + S_FIRS1, + S_FIRS2, + S_FIRS3, + S_FIRS4, + S_FIRS5, + S_FIRS6, + S_FIRS7, + S_FIRS8, + S_FIRS9, + + S_FIRS10, + S_FIRS11, + + S_FIRSB1, + S_FIRSB2, + S_FIRSB3, + S_FIRSB4, + S_FIRSB5, + S_FIRSB6, + S_FIRSB7, + S_FIRSB8, + S_FIRSB9, + + S_FIRSB10, + + S_BUBS1, + S_BUBS2, + S_BUBS3, + S_BUBS4, + S_BUBS5, + S_BUBS6, + S_BUBS7, + S_BUBS8, + S_BUBS9, + + S_BUBS10, + S_BUBS11, + + S_BUBSB1, + S_BUBSB2, + S_BUBSB3, + S_BUBSB4, + + S_BUBSB5, + S_BUBSB6, + + S_ZAPS1, + S_ZAPS2, + S_ZAPS3, + S_ZAPS4, + S_ZAPS5, + S_ZAPS6, + S_ZAPS7, + S_ZAPS8, + S_ZAPS9, + S_ZAPS10, + S_ZAPS11, + S_ZAPS12, + S_ZAPS13, // blank frame + S_ZAPS14, + S_ZAPS15, + S_ZAPS16, + + S_ZAPSB1, // blank frame + S_ZAPSB2, + S_ZAPSB3, + S_ZAPSB4, + S_ZAPSB5, + S_ZAPSB6, + S_ZAPSB7, + S_ZAPSB8, + S_ZAPSB9, + S_ZAPSB10, + S_ZAPSB11, // blank frame + + //Thunder spark + S_THUNDERCOIN_SPARK, + // Invincibility Sparkles S_IVSP, @@ -2307,43 +2423,133 @@ typedef enum state S_SSPK4, S_SSPK5, - // Freed Birdie - S_BIRD1, - S_BIRD2, - S_BIRD3, + // Flicky-sized bubble + S_FLICKY_BUBBLE, - // Freed Bunny - S_BUNNY1, - S_BUNNY2, - S_BUNNY3, - S_BUNNY4, - S_BUNNY5, - S_BUNNY6, - S_BUNNY7, - S_BUNNY8, - S_BUNNY9, - S_BUNNY10, + // Bluebird + S_FLICKY_01_OUT, + S_FLICKY_01_FLAP1, + S_FLICKY_01_FLAP2, + S_FLICKY_01_FLAP3, - // Freed Mouse - S_MOUSE1, - S_MOUSE2, + // Rabbit + S_FLICKY_02_OUT, + S_FLICKY_02_AIM, + S_FLICKY_02_HOP, + S_FLICKY_02_UP, + S_FLICKY_02_DOWN, - // Freed Chicken - S_CHICKEN1, - S_CHICKENHOP, - S_CHICKENFLY1, - S_CHICKENFLY2, + // Chicken + S_FLICKY_03_OUT, + S_FLICKY_03_AIM, + S_FLICKY_03_HOP, + S_FLICKY_03_UP, + S_FLICKY_03_FLAP1, + S_FLICKY_03_FLAP2, - // Freed Cow - S_COW1, - S_COW2, - S_COW3, - S_COW4, + // Seal + S_FLICKY_04_OUT, + S_FLICKY_04_AIM, + S_FLICKY_04_HOP, + S_FLICKY_04_UP, + S_FLICKY_04_DOWN, + S_FLICKY_04_SWIM1, + S_FLICKY_04_SWIM2, + S_FLICKY_04_SWIM3, + S_FLICKY_04_SWIM4, - // Red Birdie in Bubble - S_RBIRD1, - S_RBIRD2, - S_RBIRD3, + // Pig + S_FLICKY_05_OUT, + S_FLICKY_05_AIM, + S_FLICKY_05_HOP, + S_FLICKY_05_UP, + S_FLICKY_05_DOWN, + + // Chipmunk + S_FLICKY_06_OUT, + S_FLICKY_06_AIM, + S_FLICKY_06_HOP, + S_FLICKY_06_UP, + S_FLICKY_06_DOWN, + + // Penguin + S_FLICKY_07_OUT, + S_FLICKY_07_AIML, + S_FLICKY_07_HOPL, + S_FLICKY_07_UPL, + S_FLICKY_07_DOWNL, + S_FLICKY_07_AIMR, + S_FLICKY_07_HOPR, + S_FLICKY_07_UPR, + S_FLICKY_07_DOWNR, + S_FLICKY_07_SWIM1, + S_FLICKY_07_SWIM2, + S_FLICKY_07_SWIM3, + + // Fish + S_FLICKY_08_OUT, + S_FLICKY_08_AIM, + S_FLICKY_08_HOP, + S_FLICKY_08_FLAP1, + S_FLICKY_08_FLAP2, + S_FLICKY_08_FLAP3, + S_FLICKY_08_FLAP4, + S_FLICKY_08_SWIM1, + S_FLICKY_08_SWIM2, + S_FLICKY_08_SWIM3, + S_FLICKY_08_SWIM4, + + // Ram + S_FLICKY_09_OUT, + S_FLICKY_09_AIM, + S_FLICKY_09_HOP, + S_FLICKY_09_UP, + S_FLICKY_09_DOWN, + + // Puffin + S_FLICKY_10_OUT, + S_FLICKY_10_FLAP1, + S_FLICKY_10_FLAP2, + + // Cow + S_FLICKY_11_OUT, + S_FLICKY_11_AIM, + S_FLICKY_11_RUN1, + S_FLICKY_11_RUN2, + S_FLICKY_11_RUN3, + + // Rat + S_FLICKY_12_OUT, + S_FLICKY_12_AIM, + S_FLICKY_12_RUN1, + S_FLICKY_12_RUN2, + S_FLICKY_12_RUN3, + + // Bear + S_FLICKY_13_OUT, + S_FLICKY_13_AIM, + S_FLICKY_13_HOP, + S_FLICKY_13_UP, + S_FLICKY_13_DOWN, + + // Dove + S_FLICKY_14_OUT, + S_FLICKY_14_FLAP1, + S_FLICKY_14_FLAP2, + S_FLICKY_14_FLAP3, + + // Cat + S_FLICKY_15_OUT, + S_FLICKY_15_AIM, + S_FLICKY_15_HOP, + S_FLICKY_15_UP, + S_FLICKY_15_DOWN, + + // Canary + S_FLICKY_16_OUT, + S_FLICKY_16_FLAP1, + S_FLICKY_16_FLAP2, + S_FLICKY_16_FLAP3, S_YELLOWSPRING, S_YELLOWSPRING2, @@ -2457,6 +2663,20 @@ typedef enum state S_WATERZAP, + // Spindash dust + S_SPINDUST1, + S_SPINDUST2, + S_SPINDUST3, + S_SPINDUST4, + S_SPINDUST_BUBBLE1, + S_SPINDUST_BUBBLE2, + S_SPINDUST_BUBBLE3, + S_SPINDUST_BUBBLE4, + S_SPINDUST_FIRE1, + S_SPINDUST_FIRE2, + S_SPINDUST_FIRE3, + S_SPINDUST_FIRE4, + S_FOG1, S_FOG2, S_FOG3, @@ -2687,20 +2907,19 @@ typedef enum state S_FIREBALLEXP2, S_FIREBALLEXP3, S_SHELL, - S_SHELL1, - S_SHELL2, - S_SHELL3, - S_SHELL4, - S_PUMA1, - S_PUMA2, - S_PUMA3, - S_PUMA4, - S_PUMA5, - S_PUMA6, - S_HAMMER1, - S_HAMMER2, - S_HAMMER3, - S_HAMMER4, + S_PUMA_START1, + S_PUMA_START2, + S_PUMA_UP1, + S_PUMA_UP2, + S_PUMA_UP3, + S_PUMA_DOWN1, + S_PUMA_DOWN2, + S_PUMA_DOWN3, + S_PUMATRAIL1, + S_PUMATRAIL2, + S_PUMATRAIL3, + S_PUMATRAIL4, + S_HAMMER, S_KOOPA1, S_KOOPA2, S_KOOPAFLAME1, @@ -2829,6 +3048,7 @@ typedef enum state S_NIGHTOPIANHELPER6, S_NIGHTOPIANHELPER7, S_NIGHTOPIANHELPER8, + S_NIGHTOPIANHELPER9, S_CRUMBLE1, S_CRUMBLE2, @@ -2852,10 +3072,10 @@ typedef enum state S_SPRK16, // Robot Explosion + S_XPLD_FLICKY, S_XPLD1, S_XPLD2, - S_XPLD3, - S_XPLD4, + S_XPLD_EGGTRAP, // Underwater Explosion S_WPLD1, @@ -2971,6 +3191,7 @@ typedef enum mobj_type MT_BOSSTANK2, MT_BOSSSPIGOT, MT_GOOP, + MT_GOOPTRAIL, // Boss 3 MT_EGGMOBILE3, @@ -3074,6 +3295,9 @@ typedef enum mobj_type MT_RECYCLER_BOX, MT_SCORE1K_BOX, MT_SCORE10K_BOX, + MT_FLAMEAURA_BOX, + MT_BUBBLEWRAP_BOX, + MT_THUNDERCOIN_BOX, // Monitor boxes -- repeating (big) boxes MT_PITY_GOLDBOX, @@ -3086,6 +3310,9 @@ typedef enum mobj_type MT_INVULN_GOLDBOX, MT_EGGMAN_GOLDBOX, MT_GRAVITY_GOLDBOX, + MT_FLAMEAURA_GOLDBOX, + MT_BUBBLEWRAP_GOLDBOX, + MT_THUNDERCOIN_GOLDBOX, // Monitor boxes -- special MT_RING_REDBOX, @@ -3108,6 +3335,9 @@ typedef enum mobj_type MT_RECYCLER_ICON, MT_SCORE1K_ICON, MT_SCORE10K_ICON, + MT_FLAMEAURA_ICON, + MT_BUBBLEWRAP_ICON, + MT_THUNDERCOIN_ICON, // Projectiles MT_ROCKET, @@ -3131,7 +3361,8 @@ typedef enum mobj_type MT_BUSH, // Techno Hill Scenery - MT_THZPLANT, // THZ Plant + MT_THZFLOWER1, + MT_THZFLOWER2, MT_ALARM, // Deep Sea Scenery @@ -3147,6 +3378,7 @@ typedef enum mobj_type // Castle Eggman Scenery MT_CHAIN, // CEZ Chain MT_FLAME, // Flame (has corona) + MT_FLAMEPARTICLE, MT_EGGSTATUE, // Eggman Statue MT_MACEPOINT, // Mace rotation point MT_SWINGMACEPOINT, // Mace swinging point @@ -3173,9 +3405,7 @@ typedef enum mobj_type MT_FLAMEJETFLAME, MT_FJSPINAXISA, // Counter-clockwise - MT_FJSPINHELPERA, MT_FJSPINAXISB, // Clockwise - MT_FJSPINHELPERB, MT_FLAMEJETFLAMEB, // Blade's flame @@ -3252,30 +3482,46 @@ typedef enum mobj_type MT_BSZVINE_ORANGE, MT_BSZSHRUB, MT_BSZCLOVER, - MT_BSZFISH, - MT_BSZSUNFLOWER, + MT_BIG_PALMTREE_TRUNK, + MT_BIG_PALMTREE_TOP, + MT_PALMTREE_TRUNK, + MT_PALMTREE_TOP, // Misc scenery MT_DBALL, MT_EGGSTATUE2, // Powerup Indicators - MT_GREENORB, // Elemental shield mobj - MT_YELLOWORB, // Attract shield mobj - MT_BLUEORB, // Force shield mobj - MT_BLACKORB, // Armageddon shield mobj - MT_WHITEORB, // Whirlwind shield mobj - MT_PITYORB, // Pity shield mobj - MT_IVSP, // invincibility sparkles + MT_ELEMENTAL_ORB, // Elemental shield mobj + MT_ATTRACT_ORB, // Attract shield mobj + MT_FORCE_ORB, // Force shield mobj + MT_ARMAGEDDON_ORB, // Armageddon shield mobj + MT_WHIRLWIND_ORB, // Whirlwind shield mobj + MT_PITY_ORB, // Pity shield mobj + MT_FLAMEAURA_ORB, // Flame shield mobj + MT_BUBBLEWRAP_ORB, // Bubble shield mobj + MT_THUNDERCOIN_ORB, // Thunder shield mobj + MT_THUNDERCOIN_SPARK, // Thunder spark + MT_IVSP, // Invincibility sparkles MT_SUPERSPARK, // Super Sonic Spark - // Freed Animals - MT_BIRD, // Birdie freed! - MT_BUNNY, // Bunny freed! - MT_MOUSE, // Mouse - MT_CHICKEN, // Chicken - MT_COW, // Cow - MT_REDBIRD, // Red Birdie in Bubble + // Flickies + MT_FLICKY_01, // Bluebird + MT_FLICKY_02, // Rabbit + MT_FLICKY_03, // Chicken + MT_FLICKY_04, // Seal + MT_FLICKY_05, // Pig + MT_FLICKY_06, // Chipmunk + MT_FLICKY_07, // Penguin + MT_FLICKY_08, // Fish + MT_FLICKY_09, // Ram + MT_FLICKY_10, // Puffin + MT_FLICKY_11, // Cow + MT_FLICKY_12, // Rat + MT_FLICKY_13, // Bear + MT_FLICKY_14, // Dove + MT_FLICKY_15, // Cat + MT_FLICKY_16, // Canary // Environmental Effects MT_RAIN, // Rain @@ -3286,6 +3532,7 @@ typedef enum mobj_type MT_MEDIUMBUBBLE, // medium bubble MT_EXTRALARGEBUBBLE, // extra large bubble MT_WATERZAP, + MT_SPINDUST, // Spindash dust MT_TFOG, MT_SEED, MT_PARTICLE, @@ -3344,6 +3591,7 @@ typedef enum mobj_type MT_FIREBALL, MT_SHELL, MT_PUMA, + MT_PUMATRAIL, MT_HAMMER, MT_KOOPA, MT_KOOPAFLAME, diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 035194fc8..abec99444 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -27,7 +27,6 @@ #define NOHUD if (hud_running) return luaL_error(L, "HUD rendering code should not call this function!"); - boolean luaL_checkboolean(lua_State *L, int narg) { luaL_checktype(L, narg, LUA_TBOOLEAN); return lua_toboolean(L, narg); @@ -205,6 +204,41 @@ static int lib_pClosestPointOnLine(lua_State *L) return 2; } +static int lib_pPointOnLineSide(lua_State *L) +{ + int n = lua_gettop(L); + fixed_t x = luaL_checkfixed(L, 1); + fixed_t y = luaL_checkfixed(L, 2); + //HUDSAFE + if (lua_isuserdata(L, 3)) // use a real linedef to get our points + { + line_t *line = *((line_t **)luaL_checkudata(L, 3, META_LINE)); + if (!line) + return LUA_ErrInvalid(L, "line_t"); + lua_pushinteger(L, P_PointOnLineSide(x, y, line)); + } + else // use custom coordinates of our own! + { + vertex_t v1, v2; // fake vertexes + line_t junk; // fake linedef + + if (n < 6) + return luaL_error(L, "arguments 3 to 6 not all given (expected 4 fixed-point integers)"); + + v1.x = luaL_checkfixed(L, 3); + v1.y = luaL_checkfixed(L, 4); + v2.x = luaL_checkfixed(L, 5); + v2.y = luaL_checkfixed(L, 6); + + junk.v1 = &v1; + junk.v2 = &v2; + junk.dx = v2.x - v1.x; + junk.dy = v2.y - v1.y; + lua_pushinteger(L, P_PointOnLineSide(x, y, &junk)); + } + return 1; +} + // P_ENEMY ///////////// @@ -309,6 +343,19 @@ static int lib_pRemoveMobj(lua_State *L) return 0; } +// P_IsValidSprite2 technically doesn't exist, and probably never should... but too much would need to be exposed to allow this to be checked by other methods. + +static int lib_pIsValidSprite2(lua_State *L) +{ + mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + UINT8 spr2 = (UINT8)luaL_checkinteger(L, 2); + //HUDSAFE + if (!mobj) + return LUA_ErrInvalid(L, "mobj_t"); + lua_pushboolean(L, (mobj->skin && (((skin_t *)mobj->skin)->sprites[spr2].numframes > 0))); + return 1; +} + static int lib_pSpawnMissile(lua_State *L) { mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); @@ -618,6 +665,17 @@ static int lib_pAddPlayerScore(lua_State *L) return 0; } +static int lib_pStealPlayerScore(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + UINT32 amount = (UINT32)luaL_checkinteger(L, 2); + NOHUD + if (!player) + return LUA_ErrInvalid(L, "player_t"); + P_StealPlayerScore(player, amount); + return 0; +} + static int lib_pPlayerInPain(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -777,6 +835,16 @@ static int lib_pDoJumpShield(lua_State *L) return 0; } +static int lib_pDoBubbleBounce(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + NOHUD + if (!player) + return LUA_ErrInvalid(L, "player_t"); + P_DoBubbleBounce(player); + return 0; +} + static int lib_pBlackOw(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -787,13 +855,14 @@ static int lib_pBlackOw(lua_State *L) return 0; } -static int lib_pElementalFireTrail(lua_State *L) +static int lib_pElementalFire(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + boolean cropcircle = lua_optboolean(L, 2); NOHUD if (!player) return LUA_ErrInvalid(L, "player_t"); - P_ElementalFireTrail(player); + P_ElementalFire(player, cropcircle); return 0; } @@ -848,10 +917,11 @@ static int lib_pReturnThrustY(lua_State *L) static int lib_pLookForEnemies(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + boolean nonenemies = lua_opttrueboolean(L, 2); NOHUD if (!player) return LUA_ErrInvalid(L, "player_t"); - lua_pushboolean(L, P_LookForEnemies(player)); + lua_pushboolean(L, P_LookForEnemies(player, nonenemies)); return 1; } @@ -1132,7 +1202,7 @@ static int lib_pPlayerRingBurst(lua_State *L) if (!player) return LUA_ErrInvalid(L, "player_t"); if (num_rings == -1) - num_rings = player->health - 1; + num_rings = player->rings; P_PlayerRingBurst(player, num_rings); return 0; } @@ -1157,6 +1227,16 @@ static int lib_pPlayerWeaponAmmoBurst(lua_State *L) return 0; } +static int lib_pPlayerWeaponPanelOrAmmoBurst(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + NOHUD + if (!player) + return LUA_ErrInvalid(L, "player_t"); + P_PlayerWeaponPanelOrAmmoBurst(player); + return 0; +} + static int lib_pPlayerEmeraldBurst(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -1264,6 +1344,16 @@ static int lib_pDoNightsScore(lua_State *L) return 0; } +static int lib_pDoMatchSuper(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + NOHUD + if (!player) + return LUA_ErrInvalid(L, "player_t"); + P_DoMatchSuper(player); + return 0; +} + // P_SPEC //////////// @@ -2018,6 +2108,7 @@ static luaL_Reg lib[] = { // p_maputil {"P_AproxDistance",lib_pAproxDistance}, {"P_ClosestPointOnLine",lib_pClosestPointOnLine}, + {"P_PointOnLineSide",lib_pPointOnLineSide}, // p_enemy {"P_CheckMeleeRange", lib_pCheckMeleeRange}, @@ -2032,6 +2123,7 @@ static luaL_Reg lib[] = { // don't add P_SetMobjState or P_SetPlayerMobjState, use "mobj.state = S_NEWSTATE" instead. {"P_SpawnMobj",lib_pSpawnMobj}, {"P_RemoveMobj",lib_pRemoveMobj}, + {"P_IsValidSprite2", lib_pIsValidSprite2}, {"P_SpawnMissile",lib_pSpawnMissile}, {"P_SpawnXYZMissile",lib_pSpawnXYZMissile}, {"P_SpawnPointMissile",lib_pSpawnPointMissile}, @@ -2058,6 +2150,7 @@ static luaL_Reg lib[] = { {"P_GetPlayerSpinHeight",lib_pGetPlayerSpinHeight}, {"P_GetPlayerControlDirection",lib_pGetPlayerControlDirection}, {"P_AddPlayerScore",lib_pAddPlayerScore}, + {"P_StealPlayerScore",lib_pStealPlayerScore}, {"P_PlayerInPain",lib_pPlayerInPain}, {"P_DoPlayerPain",lib_pDoPlayerPain}, {"P_ResetPlayer",lib_pResetPlayer}, @@ -2073,8 +2166,9 @@ static luaL_Reg lib[] = { {"P_GivePlayerLives",lib_pGivePlayerLives}, {"P_ResetScore",lib_pResetScore}, {"P_DoJumpShield",lib_pDoJumpShield}, + {"P_DoBubbleBounce",lib_pDoBubbleBounce}, {"P_BlackOw",lib_pBlackOw}, - {"P_ElementalFireTrail",lib_pElementalFireTrail}, + {"P_ElementalFire",lib_pElementalFire}, {"P_DoPlayerExit",lib_pDoPlayerExit}, {"P_InstaThrust",lib_pInstaThrust}, {"P_ReturnThrustX",lib_pReturnThrustX}, @@ -2108,6 +2202,7 @@ static luaL_Reg lib[] = { {"P_PlayerRingBurst",lib_pPlayerRingBurst}, {"P_PlayerWeaponPanelBurst",lib_pPlayerWeaponPanelBurst}, {"P_PlayerWeaponAmmoBurst",lib_pPlayerWeaponAmmoBurst}, + {"P_PlayerWeaponPanelOrAmmoBurst", lib_pPlayerWeaponPanelOrAmmoBurst}, {"P_PlayerEmeraldBurst",lib_pPlayerEmeraldBurst}, {"P_PlayerFlagBurst",lib_pPlayerFlagBurst}, {"P_PlayRinglossSound",lib_pPlayRinglossSound}, @@ -2116,6 +2211,7 @@ static luaL_Reg lib[] = { {"P_PlayLivesJingle",lib_pPlayLivesJingle}, {"P_CanPickupItem",lib_pCanPickupItem}, {"P_DoNightsScore",lib_pDoNightsScore}, + {"P_DoMatchSuper",lib_pDoMatchSuper}, // p_spec {"P_Thrust",lib_pThrust}, diff --git a/src/lua_blockmaplib.c b/src/lua_blockmaplib.c new file mode 100644 index 000000000..33f350d69 --- /dev/null +++ b/src/lua_blockmaplib.c @@ -0,0 +1,266 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2016 by Iestyn "Monster Iestyn" Jealous. +// Copyright (C) 2016 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file lua_blockmaplib.c +/// \brief blockmap library for Lua scripting + +#include "doomdef.h" +#ifdef HAVE_BLUA +#include "p_local.h" +#include "r_main.h" // validcount +#include "lua_script.h" +#include "lua_libs.h" +//#include "lua_hud.h" // hud_running errors + +static const char *const search_opt[] = { + "objects", + "lines", + NULL}; + +// a quickly-made function pointer typedef used by lib_searchBlockmap... +// return values: +// 0 - normal, no interruptions +// 1 - stop search through current block +// 2 - stop search completely +typedef UINT8 (*blockmap_func)(lua_State *, INT32, INT32, mobj_t *); + +static boolean blockfuncerror = false; // errors should only print once per search blockmap call + +// Helper function for "objects" search +static UINT8 lib_searchBlockmap_Objects(lua_State *L, INT32 x, INT32 y, mobj_t *thing) +{ + mobj_t *mobj, *bnext = NULL; + + if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) + return 0; + + // Check interaction with the objects in the blockmap. + for (mobj = blocklinks[y*bmapwidth + x]; mobj; mobj = bnext) + { + P_SetTarget(&bnext, mobj->bnext); // We want to note our reference to bnext here incase it is MF_NOTHINK and gets removed! + if (mobj == thing) + continue; // our thing just found itself, so move on + lua_pushvalue(L, 1); // push function + LUA_PushUserdata(L, thing, META_MOBJ); + LUA_PushUserdata(L, mobj, META_MOBJ); + if (lua_pcall(gL, 2, 1, 0)) { + if (!blockfuncerror || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + blockfuncerror = true; + return 0; // *shrugs* + } + if (!lua_isnil(gL, -1)) + { // if nil, continue + if (lua_toboolean(gL, -1)) + return 2; // stop whole search + else + return 1; // stop block search + } + lua_pop(gL, 1); + if (P_MobjWasRemoved(thing) // func just popped our thing, cannot continue. + || (bnext && P_MobjWasRemoved(bnext))) // func just broke blockmap chain, cannot continue. + { + P_SetTarget(&bnext, NULL); + return (P_MobjWasRemoved(thing)) ? 2 : 1; + } + } + return 0; +} + +// Helper function for "lines" search +static UINT8 lib_searchBlockmap_Lines(lua_State *L, INT32 x, INT32 y, mobj_t *thing) +{ + INT32 offset; + const INT32 *list; // Big blockmap +#ifdef POLYOBJECTS + polymaplink_t *plink; // haleyjd 02/22/06 +#endif + line_t *ld; + + if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) + return 0; + + offset = y*bmapwidth + x; + +#ifdef POLYOBJECTS + // haleyjd 02/22/06: consider polyobject lines + plink = polyblocklinks[offset]; + + while (plink) + { + polyobj_t *po = plink->po; + + if (po->validcount != validcount) // if polyobj hasn't been checked + { + size_t i; + po->validcount = validcount; + + for (i = 0; i < po->numLines; ++i) + { + if (po->lines[i]->validcount == validcount) // line has been checked + continue; + po->lines[i]->validcount = validcount; + + lua_pushvalue(L, 1); + LUA_PushUserdata(L, thing, META_MOBJ); + LUA_PushUserdata(L, po->lines[i], META_LINE); + if (lua_pcall(gL, 2, 1, 0)) { + if (!blockfuncerror || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + blockfuncerror = true; + return 0; // *shrugs* + } + if (!lua_isnil(gL, -1)) + { // if nil, continue + if (lua_toboolean(gL, -1)) + return 2; // stop whole search + else + return 1; // stop block search + } + lua_pop(gL, 1); + if (P_MobjWasRemoved(thing)) + return 2; + } + } + plink = (polymaplink_t *)(plink->link.next); + } +#endif + + offset = *(blockmap + offset); // offset = blockmap[y*bmapwidth+x]; + + // First index is really empty, so +1 it. + for (list = blockmaplump + offset + 1; *list != -1; list++) + { + ld = &lines[*list]; + + if (ld->validcount == validcount) + continue; // Line has already been checked. + + ld->validcount = validcount; + + lua_pushvalue(L, 1); + LUA_PushUserdata(L, thing, META_MOBJ); + LUA_PushUserdata(L, ld, META_LINE); + if (lua_pcall(gL, 2, 1, 0)) { + if (!blockfuncerror || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + blockfuncerror = true; + return 0; // *shrugs* + } + if (!lua_isnil(gL, -1)) + { // if nil, continue + if (lua_toboolean(gL, -1)) + return 2; // stop whole search + else + return 1; // stop block search + } + lua_pop(gL, 1); + if (P_MobjWasRemoved(thing)) + return 2; + } + return 0; // Everything was checked. +} + +// The searchBlockmap function +// arguments: searchBlockmap(searchtype, function, mobj, [x1, x2, y1, y2]) +// return value: +// true = search completely uninteruppted, +// false = searching of at least one block stopped mid-way (including if the whole search was stopped) +static int lib_searchBlockmap(lua_State *L) +{ + int searchtype = luaL_checkoption(L, 1, "objects", search_opt); + int n; + mobj_t *mobj; + INT32 xl, xh, yl, yh, bx, by; + fixed_t x1, x2, y1, y2; + boolean retval = true; + UINT8 funcret = 0; + blockmap_func searchFunc; + + lua_remove(L, 1); // remove searchtype, stack is now function, mobj, [x1, x2, y1, y2] + luaL_checktype(L, 1, LUA_TFUNCTION); + + switch (searchtype) + { + case 0: // "objects" + default: + searchFunc = lib_searchBlockmap_Objects; + break; + case 1: // "lines" + searchFunc = lib_searchBlockmap_Lines; + break; + } + + // the mobj we are searching around, the "calling" mobj we could say + mobj = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + if (!mobj) + return LUA_ErrInvalid(L, "mobj_t"); + + n = lua_gettop(L); + + if (n > 2) // specific x/y ranges have been supplied + { + if (n < 6) + return luaL_error(L, "arguments 4 to 6 not all given (expected 4 fixed-point integers)"); + + x1 = luaL_checkfixed(L, 3); + x2 = luaL_checkfixed(L, 4); + y1 = luaL_checkfixed(L, 5); + y2 = luaL_checkfixed(L, 6); + } + else // mobj and function only - search around mobj's radius by default + { + fixed_t radius = mobj->radius + MAXRADIUS; + x1 = mobj->x - radius; + x2 = mobj->x + radius; + y1 = mobj->y - radius; + y2 = mobj->y + radius; + } + lua_settop(L, 2); // pop everything except function, mobj + + xl = (unsigned)(x1 - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(x2 - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(y1 - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(y2 - bmaporgy)>>MAPBLOCKSHIFT; + + BMBOUNDFIX(xl, xh, yl, yh); + + blockfuncerror = false; // reset + validcount++; + for (bx = xl; bx <= xh; bx++) + for (by = yl; by <= yh; by++) + { + funcret = searchFunc(L, bx, by, mobj); + // return value of searchFunc determines searchFunc's return value and/or when to stop + if (funcret == 2){ // stop whole search + lua_pushboolean(L, false); // return false + return 1; + } + else if (funcret == 1) // search was interrupted for this block + retval = false; // this changes the return value, but doesn't stop the whole search + // else don't do anything, continue as normal + if (P_MobjWasRemoved(mobj)){ // ...unless the original object was removed + lua_pushboolean(L, false); // in which case we have to stop now regardless + return 1; + } + } + lua_pushboolean(L, retval); + return 1; +} + +int LUA_BlockmapLib(lua_State *L) +{ + lua_register(L, "searchBlockmap", lib_searchBlockmap); + return 0; +} + +#endif \ No newline at end of file diff --git a/src/lua_hook.h b/src/lua_hook.h index bed32edac..7192a2979 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -43,6 +43,8 @@ enum hook { hook_PlayerMsg, hook_HurtMsg, hook_PlayerSpawn, + hook_ShieldSpawn, + hook_ShieldSpecial, hook_MAX // last hook }; @@ -60,11 +62,11 @@ UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which); #define LUAh_MobjMoveCollide(thing1, thing2) LUAh_MobjCollideHook(thing1, thing2, hook_MobjMoveCollide) // Hook for PIT_CheckThing by (tmthing) mobj type boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher); // Hook for P_TouchSpecialThing by mobj type #define LUAh_MobjFuse(mo) LUAh_MobjHook(mo, hook_MobjFuse) // Hook for mobj->fuse == 0 by mobj type -#define LUAh_MobjThinker(mo) LUAh_MobjHook(mo, hook_MobjThinker) // Hook for P_MobjThinker or P_SceneryThinker by mobj type +boolean LUAh_MobjThinker(mobj_t *mo); // Hook for P_MobjThinker or P_SceneryThinker by mobj type #define LUAh_BossThinker(mo) LUAh_MobjHook(mo, hook_BossThinker) // Hook for P_GenericBossThinker by mobj type -UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage); // Hook for P_DamageMobj by mobj type (Should mobj take damage?) -boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage); // Hook for P_DamageMobj by mobj type (Mobj actually takes damage!) -boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source); // Hook for P_KillMobj by mobj type +UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); // Hook for P_DamageMobj by mobj type (Should mobj take damage?) +boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); // Hook for P_DamageMobj by mobj type (Mobj actually takes damage!) +boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype); // Hook for P_KillMobj by mobj type #define LUAh_BossDeath(mo) LUAh_MobjHook(mo, hook_BossDeath) // Hook for A_BossDeath by mobj type #define LUAh_MobjRemoved(mo) LUAh_MobjHook(mo, hook_MobjRemoved) // Hook for P_RemoveMobj by mobj type #define LUAh_JumpSpecial(player) LUAh_PlayerHook(player, hook_JumpSpecial) // Hook for P_DoJumpStuff (Any-jumping) @@ -75,7 +77,9 @@ boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd); // Hook for B_BuildTiccmd boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd); // Hook for B_BuildTailsTiccmd by skin name boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector); // Hook for linedef executors boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg); // Hook for chat messages -boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source); // Hook for hurt messages +boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 damagetype); // Hook for hurt messages #define LUAh_PlayerSpawn(player) LUAh_PlayerHook(player, hook_PlayerSpawn) // Hook for G_SpawnPlayer +#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 #endif diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 1b9652571..f7ea25224 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -54,6 +54,8 @@ const char *const hookNames[hook_MAX+1] = { "PlayerMsg", "HurtMsg", "PlayerSpawn", + "ShieldSpawn", + "ShieldSpecial", NULL }; @@ -74,12 +76,30 @@ typedef struct hook_s* hook_p; #define FMT_HOOKID "hook_%d" +// For each mobj type, a linked list to its thinker and collision hooks. +// That way, we don't have to iterate through all the hooks. +// We could do that with all other mobj hooks, but it would probably just be +// a waste of memory since they are only called occasionally. Probably... +static hook_p mobjthinkerhooks[NUMMOBJTYPES]; +static hook_p mobjcollidehooks[NUMMOBJTYPES]; + +// For each mobj type, a linked list for other mobj hooks +static hook_p mobjhooks[NUMMOBJTYPES]; + +// A linked list for player hooks +static hook_p playerhooks; + +// A linked list for linedef executor hooks +static hook_p linedefexecutorhooks; + +// For other hooks, a unique linked list hook_p roothook; // Takes hook, function, and additional arguments (mobj type to act on, etc.) static int lib_addHook(lua_State *L) { static struct hook_s hook = {NULL, 0, 0, {0}, false}; + static UINT32 nextid; hook_p hookp, *lastp; hook.type = luaL_checkoption(L, 1, NULL, hookNames); @@ -109,6 +129,7 @@ static int lib_addHook(lua_State *L) hook.s.mt = MT_NULL; if (lua_isnumber(L, 2)) hook.s.mt = lua_tonumber(L, 2); + luaL_argcheck(L, hook.s.mt < NUMMOBJTYPES, 2, "invalid mobjtype_t"); break; case hook_BotAI: hook.s.skinname = NULL; @@ -141,18 +162,49 @@ static int lib_addHook(lua_State *L) hooksAvailable[hook.type/8] |= 1<<(hook.type%8); - // iterate the hook metadata structs // set hook.id to the highest id + 1 - // set lastp to the last hook struct's "next" pointer. - lastp = &roothook; - hook.id = 0; - for (hookp = roothook; hookp; hookp = hookp->next) + hook.id = nextid++; + + // Special cases for some hook types (see the comments above mobjthinkerhooks declaration) + switch(hook.type) { - if (hookp->id >= hook.id) - hook.id = hookp->id+1; - lastp = &hookp->next; + case hook_MobjThinker: + lastp = &mobjthinkerhooks[hook.s.mt]; + break; + case hook_MobjCollide: + case hook_MobjMoveCollide: + lastp = &mobjcollidehooks[hook.s.mt]; + break; + case hook_MobjSpawn: + case hook_TouchSpecial: + case hook_MobjFuse: + case hook_BossThinker: + case hook_ShouldDamage: + case hook_MobjDamage: + case hook_MobjDeath: + case hook_BossDeath: + case hook_MobjRemoved: + lastp = &mobjhooks[hook.s.mt]; + break; + case hook_JumpSpecial: + case hook_AbilitySpecial: + case hook_SpinSpecial: + case hook_JumpSpinSpecial: + case hook_PlayerSpawn: + lastp = &playerhooks; + break; + case hook_LinedefExecute: + lastp = &linedefexecutorhooks; + break; + default: + lastp = &roothook; + break; } + // iterate the hook metadata structs + // set lastp to the last hook struct's "next" pointer. + for (hookp = *lastp; hookp; hookp = hookp->next) + lastp = &hookp->next; // allocate a permanent memory struct to stuff hook. hookp = ZZ_Alloc(sizeof(struct hook_s)); memcpy(hookp, &hook, sizeof(struct hook_s)); @@ -183,9 +235,29 @@ boolean LUAh_MobjHook(mobj_t *mo, enum hook which) lua_settop(gL, 0); - for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == which - && (hookp->s.mt == MT_NULL || hookp->s.mt == mo->type)) + // Look for all generic mobj hooks + for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) + if (hookp->type == which) + { + if (lua_gettop(gL) == 0) + LUA_PushUserdata(gL, mo, META_MOBJ); + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -2); + if (lua_pcall(gL, 1, 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 == which) { if (lua_gettop(gL) == 0) LUA_PushUserdata(gL, mo, META_MOBJ); @@ -217,7 +289,7 @@ boolean LUAh_PlayerHook(player_t *plr, enum hook which) lua_settop(gL, 0); - for (hookp = roothook; hookp; hookp = hookp->next) + for (hookp = playerhooks; hookp; hookp = hookp->next) if (hookp->type == which) { if (lua_gettop(gL) == 0) @@ -338,9 +410,38 @@ UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which) lua_settop(gL, 0); - for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == which - && (hookp->s.mt == MT_NULL || hookp->s.mt == thing1->type)) + // Look for all generic mobj collision hooks + for (hookp = mobjcollidehooks[MT_NULL]; hookp; hookp = hookp->next) + if (hookp->type == which) + { + if (lua_gettop(gL) == 0) + { + LUA_PushUserdata(gL, thing1, META_MOBJ); + LUA_PushUserdata(gL, thing2, META_MOBJ); + } + 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_isnil(gL, -1)) + { // if nil, leave shouldCollide = 0. + if (lua_toboolean(gL, -1)) + shouldCollide = 1; // Force yes + else + shouldCollide = 2; // Force no + } + lua_pop(gL, 1); + } + + for (hookp = mobjcollidehooks[thing1->type]; hookp; hookp = hookp->next) + if (hookp->type == which) { if (lua_gettop(gL) == 0) { @@ -372,6 +473,59 @@ UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which) return shouldCollide; } +// Hook for mobj thinkers +boolean LUAh_MobjThinker(mobj_t *mo) +{ + hook_p hookp; + boolean hooked = false; + if (!gL || !(hooksAvailable[hook_MobjThinker/8] & (1<<(hook_MobjThinker%8)))) + return false; + + lua_settop(gL, 0); + + // Look for all generic mobj thinker hooks + for (hookp = mobjthinkerhooks[MT_NULL]; hookp; hookp = hookp->next) + { + if (lua_gettop(gL) == 0) + LUA_PushUserdata(gL, mo, META_MOBJ); + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -2); + if (lua_pcall(gL, 1, 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 = mobjthinkerhooks[mo->type]; hookp; hookp = hookp->next) + { + if (lua_gettop(gL) == 0) + LUA_PushUserdata(gL, mo, META_MOBJ); + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -2); + if (lua_pcall(gL, 1, 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; +} + // Hook for P_TouchSpecialThing by mobj type boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher) { @@ -382,9 +536,33 @@ boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher) lua_settop(gL, 0); - for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_TouchSpecial - && (hookp->s.mt == MT_NULL || hookp->s.mt == special->type)) + // Look for all generic touch special hooks + for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) + if (hookp->type == hook_TouchSpecial) + { + if (lua_gettop(gL) == 0) + { + LUA_PushUserdata(gL, special, META_MOBJ); + LUA_PushUserdata(gL, toucher, META_MOBJ); + } + 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[special->type]; hookp; hookp = hookp->next) + if (hookp->type == hook_TouchSpecial) { if (lua_gettop(gL) == 0) { @@ -412,7 +590,7 @@ boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher) } // Hook for P_DamageMobj by mobj type (Should mobj take damage?) -UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage) +UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) { hook_p hookp; UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no. @@ -421,9 +599,9 @@ UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 lua_settop(gL, 0); - for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_ShouldDamage - && (hookp->s.mt == MT_NULL || hookp->s.mt == target->type)) + // Look for all generic should damage hooks + for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) + if (hookp->type == hook_ShouldDamage) { if (lua_gettop(gL) == 0) { @@ -455,12 +633,47 @@ UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 lua_pop(gL, 1); } + for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next) + if (hookp->type == hook_ShouldDamage) + { + if (lua_gettop(gL) == 0) + { + LUA_PushUserdata(gL, target, META_MOBJ); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + lua_pushinteger(gL, damage); + lua_pushinteger(gL, damagetype); + } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + if (lua_pcall(gL, 5, 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_isnil(gL, -1)) + { + if (lua_toboolean(gL, -1)) + shouldDamage = 1; // Force yes + else + shouldDamage = 2; // Force no + } + lua_pop(gL, 1); + } + lua_settop(gL, 0); return shouldDamage; } // Hook for P_DamageMobj by mobj type (Mobj actually takes damage!) -boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage) +boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) { hook_p hookp; boolean hooked = false; @@ -469,9 +682,9 @@ boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 lua_settop(gL, 0); - for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_MobjDamage - && (hookp->s.mt == MT_NULL || hookp->s.mt == target->type)) + // Look for all generic mobj damage hooks + for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) + if (hookp->type == hook_MobjDamage) { if (lua_gettop(gL) == 0) { @@ -498,12 +711,42 @@ boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 lua_pop(gL, 1); } + for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next) + if (hookp->type == hook_MobjDamage) + { + if (lua_gettop(gL) == 0) + { + LUA_PushUserdata(gL, target, META_MOBJ); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + lua_pushinteger(gL, damage); + lua_pushinteger(gL, damagetype); + } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + if (lua_pcall(gL, 5, 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; } // Hook for P_KillMobj by mobj type -boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source) +boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype) { hook_p hookp; boolean hooked = false; @@ -512,9 +755,9 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source) lua_settop(gL, 0); - for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_MobjDeath - && (hookp->s.mt == MT_NULL || hookp->s.mt == target->type)) + // Look for all generic mobj death hooks + for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) + if (hookp->type == hook_MobjDeath) { if (lua_gettop(gL) == 0) { @@ -539,6 +782,34 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source) lua_pop(gL, 1); } + for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next) + if (hookp->type == hook_MobjDeath) + { + if (lua_gettop(gL) == 0) + { + LUA_PushUserdata(gL, target, META_MOBJ); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + lua_pushinteger(gL, damagetype); + } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + if (lua_pcall(gL, 4, 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; } @@ -652,9 +923,8 @@ boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector) lua_settop(gL, 0); - for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_LinedefExecute - && !strcmp(hookp->s.funcname, line->text)) + for (hookp = linedefexecutorhooks; hookp; hookp = hookp->next) + if (!strcmp(hookp->s.funcname, line->text)) { if (lua_gettop(gL) == 0) { @@ -729,7 +999,7 @@ boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg) } // Hook for hurt messages -boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source) +boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 damagetype) { hook_p hookp; boolean hooked = false; @@ -747,13 +1017,15 @@ boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source) LUA_PushUserdata(gL, player, META_PLAYER); LUA_PushUserdata(gL, inflictor, META_MOBJ); LUA_PushUserdata(gL, source, META_MOBJ); + lua_pushinteger(gL, damagetype); } lua_pushfstring(gL, FMT_HOOKID, hookp->id); lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 0)) { + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + if (lua_pcall(gL, 4, 1, 0)) { if (!hookp->error || cv_debug & DBG_LUA) CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 60cbbe501..5b3cd46ce 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -226,7 +226,12 @@ static int hudinfo_num(lua_State *L) static int colormap_get(lua_State *L) { - return luaL_error(L, "colormap is not a struct."); + const UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP)); + UINT32 i = luaL_checkinteger(L, 2); + if (i >= 256) + return luaL_error(L, "colormap index %d out of range (0 - %d)", i, 255); + lua_pushinteger(L, colormap[i]); + return 1; } static int patch_get(lua_State *L) diff --git a/src/lua_libs.h b/src/lua_libs.h index 931cf62d0..fd4937b63 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -38,12 +38,22 @@ extern lua_State *gL; #define META_SUBSECTOR "SUBSECTOR_T*" #define META_SECTOR "SECTOR_T*" #define META_FFLOOR "FFLOOR_T*" +#ifdef HAVE_LUA_SEGS +#define META_SEG "SEG_T*" +#define META_NODE "NODE_T*" +#endif #define META_MAPHEADER "MAPHEADER_T*" #define META_CVAR "CONSVAR_T*" #define META_SECTORLINES "SECTOR_T*LINES" #define META_SIDENUM "LINE_T*SIDENUM" +#ifdef HAVE_LUA_SEGS +#define META_NODEBBOX "NODE_T*BBOX" +#define META_NODECHILDREN "NODE_T*CHILDREN" +#endif + +#define META_BBOX "BOUNDING_BOX" #define META_HUDINFO "HUDINFO_T*" #define META_PATCH "PATCH_T*" @@ -64,6 +74,7 @@ int LUA_PlayerLib(lua_State *L); int LUA_SkinLib(lua_State *L); int LUA_ThinkerLib(lua_State *L); int LUA_MapLib(lua_State *L); +int LUA_BlockmapLib(lua_State *L); int LUA_HudLib(lua_State *L); #endif diff --git a/src/lua_maplib.c b/src/lua_maplib.c index c512bf3c5..9f6d3e7fa 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -185,6 +185,82 @@ static const char *const ffloor_opt[] = { "alpha", NULL}; +#ifdef HAVE_LUA_SEGS +enum seg_e { + seg_valid = 0, + seg_v1, + seg_v2, + seg_side, + seg_offset, + seg_angle, + seg_sidedef, + seg_linedef, + seg_frontsector, + seg_backsector, +}; + +static const char *const seg_opt[] = { + "valid", + "v1", + "v2", + "side", + "offset", + "angle", + "sidedef", + "linedef", + "frontsector", + "backsector", + NULL}; + +enum node_e { + node_valid = 0, + node_x, + node_y, + node_dx, + node_dy, + node_bbox, + node_children, +}; + +static const char *const node_opt[] = { + "valid", + "x", + "y", + "dx", + "dy", + "bbox", + "children", + NULL}; + +enum nodechild_e { + nodechild_valid = 0, + nodechild_right, + nodechild_left, +}; + +static const char *const nodechild_opt[] = { + "valid", + "right", + "left", + NULL}; +#endif + +enum bbox_e { + bbox_valid = 0, + bbox_top, + bbox_bottom, + bbox_left, + bbox_right, +}; + +static const char *const bbox_opt[] = { + "valid", + "top", + "bottom", + "left", + "right", + NULL}; + static const char *const array_opt[] ={"iterate",NULL}; static const char *const valid_opt[] ={"valid",NULL}; @@ -348,22 +424,12 @@ static int sector_get(lua_State *L) case sector_ceilingheight: lua_pushfixed(L, sector->ceilingheight); return 1; - case sector_floorpic: { // floorpic - levelflat_t *levelflat; - INT16 i; - for (i = 0, levelflat = levelflats; i != sector->floorpic; i++, levelflat++) - ; - lua_pushlstring(L, levelflat->name, 8); + case sector_floorpic: // floorpic + lua_pushlstring(L, levelflats[sector->floorpic].name, 8); return 1; - } - case sector_ceilingpic: { // ceilingpic - levelflat_t *levelflat; - INT16 i; - for (i = 0, levelflat = levelflats; i != sector->ceilingpic; i++, levelflat++) - ; - lua_pushlstring(L, levelflat->name, 8); + case sector_ceilingpic: // ceilingpic + lua_pushlstring(L, levelflats[sector->ceilingpic].name, 8); return 1; - } case sector_lightlevel: lua_pushinteger(L, sector->lightlevel); return 1; @@ -400,46 +466,6 @@ static int sector_get(lua_State *L) return 0; } -// help function for P_LoadSectors, find a flat in the active wad files, -// allocate an id for it, and set the levelflat (to speedup search) -// -static INT32 P_AddLevelFlatRuntime(const char *flatname) -{ - size_t i; - levelflat_t *levelflat = levelflats; - - // - // first scan through the already found flats - // - for (i = 0; i < numlevelflats; i++, levelflat++) - if (strnicmp(levelflat->name,flatname,8)==0) - break; - - // that flat was already found in the level, return the id - if (i == numlevelflats) - { - // allocate new flat memory - levelflats = Z_Realloc(levelflats, (numlevelflats + 1) * sizeof(*levelflats), PU_LEVEL, NULL); - levelflat = levelflats+i; - - // store the name - strlcpy(levelflat->name, flatname, sizeof (levelflat->name)); - strupr(levelflat->name); - - // store the flat lump number - levelflat->lumpnum = R_GetFlatNumForName(flatname); - -#ifndef ZDEBUG - CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name); -#endif - - numlevelflats++; - } - - // level flat id - return (INT32)i; -} - static int sector_set(lua_State *L) { sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); @@ -818,6 +844,262 @@ static int vertex_num(lua_State *L) return 1; } +#ifdef HAVE_LUA_SEGS +static int seg_get(lua_State *L) +{ + seg_t *seg = *((seg_t **)luaL_checkudata(L, 1, META_SEG)); + enum seg_e field = luaL_checkoption(L, 2, seg_opt[0], seg_opt); + + if (!seg) + { + if (field == seg_valid) { + lua_pushboolean(L, 0); + return 1; + } + return luaL_error(L, "accessed seg_t doesn't exist anymore."); + } + + switch(field) + { + case seg_valid: // valid + lua_pushboolean(L, 1); + return 1; + case seg_v1: + LUA_PushUserdata(L, seg->v1, META_VERTEX); + return 1; + case seg_v2: + LUA_PushUserdata(L, seg->v2, META_VERTEX); + return 1; + case seg_side: + lua_pushinteger(L, seg->side); + return 1; + case seg_offset: + lua_pushfixed(L, seg->offset); + return 1; + case seg_angle: + lua_pushangle(L, seg->angle); + return 1; + case seg_sidedef: + LUA_PushUserdata(L, seg->sidedef, META_SIDE); + return 1; + case seg_linedef: + LUA_PushUserdata(L, seg->linedef, META_LINE); + return 1; + case seg_frontsector: + LUA_PushUserdata(L, seg->frontsector, META_SECTOR); + return 1; + case seg_backsector: + LUA_PushUserdata(L, seg->backsector, META_SECTOR); + return 1; + } + return 0; +} + +static int seg_num(lua_State *L) +{ + seg_t *seg = *((seg_t **)luaL_checkudata(L, 1, META_SEG)); + lua_pushinteger(L, seg-segs); + return 1; +} + +static int node_get(lua_State *L) +{ + node_t *node = *((node_t **)luaL_checkudata(L, 1, META_NODE)); + enum node_e field = luaL_checkoption(L, 2, node_opt[0], node_opt); + + if (!node) + { + if (field == node_valid) { + lua_pushboolean(L, 0); + return 1; + } + return luaL_error(L, "accessed node_t doesn't exist anymore."); + } + + switch(field) + { + case node_valid: // valid + lua_pushboolean(L, 1); + return 1; + case node_x: + lua_pushfixed(L, node->x); + return 1; + case node_y: + lua_pushfixed(L, node->y); + return 1; + case node_dx: + lua_pushfixed(L, node->x); + return 1; + case node_dy: + lua_pushfixed(L, node->x); + return 1; + case node_bbox: + LUA_PushUserdata(L, node->bbox, META_NODEBBOX); + return 1; + case node_children: + LUA_PushUserdata(L, node->children, META_NODECHILDREN); + return 1; + } + return 0; +} + +static int node_num(lua_State *L) +{ + node_t *node = *((node_t **)luaL_checkudata(L, 1, META_NODE)); + lua_pushinteger(L, node-nodes); + return 1; +} +/* +// node.bbox[i][j]: i = 0 or 1, j = 0 1 2 or 3 +// NOTE: 2D arrays are NOT double pointers, +// the second bbox will be directly after the first in memory (hence the way the bbox is pushed here) +// this function handles the [i] part, bbox_get handles the [j] part +static int nodebbox_get(lua_State *L) +{ + fixed_t *bbox = *((fixed_t **)luaL_checkudata(L, 1, META_NODEBBOX)); + int i; + lua_settop(L, 2); + if (!lua_isnumber(L, 2)) + { + int field = luaL_checkoption(L, 2, NULL, valid_opt); + if (!bbox) + { + if (field == 0) { + lua_pushboolean(L, 0); + return 1; + } + return luaL_error(L, "accessed node_t doesn't exist anymore."); + } else if (field == 0) { + lua_pushboolean(L, 1); + return 1; + } + } + + i = lua_tointeger(L, 2); + if (i < 0 || i > 1) + return 0; + LUA_PushUserdata(L, bbox + i*4*sizeof(fixed_t), META_BBOX); + return 1; +} +*/ +static int nodebbox_call(lua_State *L) +{ + fixed_t *bbox = *((fixed_t **)luaL_checkudata(L, 1, META_NODEBBOX)); + int i, j; + int n = lua_gettop(L); + + if (!bbox) + return luaL_error(L, "accessed node bbox doesn't exist anymore."); + if (n < 3) + return luaL_error(L, "arguments 2 and/or 3 not given (expected node.bbox(child, coord))"); + // get child + if (!lua_isnumber(L, 2)) { + enum nodechild_e field = luaL_checkoption(L, 2, nodechild_opt[0], nodechild_opt); + switch (field) { + case nodechild_right: i = 0; break; + case nodechild_left: i = 1; break; + default: + return luaL_error(L, "invalid node child \"%s\".", lua_tostring(L, 2)); + } + } + else { + i = lua_tointeger(L, 2); + if (i < 0 || i > 1) + return 0; + } + // get bbox coord + if (!lua_isnumber(L, 3)) { + enum bbox_e field = luaL_checkoption(L, 3, bbox_opt[0], bbox_opt); + switch (field) { + case bbox_top: j = BOXTOP; break; + case bbox_bottom: j = BOXBOTTOM; break; + case bbox_left: j = BOXLEFT; break; + case bbox_right: j = BOXRIGHT; break; + default: + return luaL_error(L, "invalid bbox coordinate \"%s\".", lua_tostring(L, 3)); + } + } + else { + j = lua_tointeger(L, 3); + if (j < 0 || j > 3) + return 0; + } + lua_pushinteger(L, bbox[i*4 + j]); + return 1; +} + +// node.children[i]: i = 0 or 1 +static int nodechildren_get(lua_State *L) +{ + UINT16 *children = *((UINT16 **)luaL_checkudata(L, 1, META_NODECHILDREN)); + int i; + lua_settop(L, 2); + if (!lua_isnumber(L, 2)) + { + enum nodechild_e field = luaL_checkoption(L, 2, nodechild_opt[0], nodechild_opt); + if (!children) + { + if (field == nodechild_valid) { + lua_pushboolean(L, 0); + return 1; + } + return luaL_error(L, "accessed node_t doesn't exist anymore."); + } else if (field == nodechild_valid) { + lua_pushboolean(L, 1); + return 1; + } else switch (field) { + case nodechild_right: i = 0; break; + case nodechild_left: i = 1; break; + default: return 0; + } + } + else { + i = lua_tointeger(L, 2); + if (i < 0 || i > 1) + return 0; + } + lua_pushinteger(L, children[i]); + return 1; +} +#endif + +// bounding box (aka fixed_t array with four elements) +// NOTE: may be useful for polyobjects or other things later +static int bbox_get(lua_State *L) +{ + fixed_t *bbox = *((fixed_t **)luaL_checkudata(L, 1, META_BBOX)); + int i; + lua_settop(L, 2); + if (!lua_isnumber(L, 2)) + { + enum bbox_e field = luaL_checkoption(L, 2, bbox_opt[0], bbox_opt); + if (!bbox) + { + if (field == bbox_valid) { + lua_pushboolean(L, 0); + return 1; + } + return luaL_error(L, "accessed bbox doesn't exist anymore."); + } else if (field == bbox_valid) { + lua_pushboolean(L, 1); + return 1; + } else switch (field) { + case bbox_top: i = BOXTOP; break; + case bbox_bottom: i = BOXBOTTOM; break; + case bbox_left: i = BOXLEFT; break; + case bbox_right: i = BOXRIGHT; break; + default: return 0; + } + } + else { + i = lua_tointeger(L, 2); + if (i < 0 || i > 3) + return 0; + } + lua_pushinteger(L, bbox[i]); + return 1; +} + static int lib_iterateSectors(lua_State *L) { size_t i = 0; @@ -1048,6 +1330,100 @@ static int lib_numvertexes(lua_State *L) return 1; } +#ifdef HAVE_LUA_SEGS +static int lib_iterateSegs(lua_State *L) +{ + size_t i = 0; + if (lua_gettop(L) < 2) + return luaL_error(L, "Don't call segs.iterate() directly, use it as 'for seg in segs.iterate do <block> end'."); + lua_settop(L, 2); + lua_remove(L, 1); // state is unused. + if (!lua_isnil(L, 1)) + i = (size_t)(*((seg_t **)luaL_checkudata(L, 1, META_SEG)) - segs)+1; + if (i < numsegs) + { + LUA_PushUserdata(L, &segs[i], META_SEG); + return 1; + } + return 0; +} + +static int lib_getSeg(lua_State *L) +{ + int field; + lua_settop(L, 2); + lua_remove(L, 1); // dummy userdata table is unused. + if (lua_isnumber(L, 1)) + { + size_t i = lua_tointeger(L, 1); + if (i >= numsegs) + return 0; + LUA_PushUserdata(L, &segs[i], META_SEG); + return 1; + } + field = luaL_checkoption(L, 1, NULL, array_opt); + switch(field) + { + case 0: // iterate + lua_pushcfunction(L, lib_iterateSegs); + return 1; + } + return 0; +} + +static int lib_numsegs(lua_State *L) +{ + lua_pushinteger(L, numsegs); + return 1; +} + +static int lib_iterateNodes(lua_State *L) +{ + size_t i = 0; + if (lua_gettop(L) < 2) + return luaL_error(L, "Don't call nodes.iterate() directly, use it as 'for node in nodes.iterate do <block> end'."); + lua_settop(L, 2); + lua_remove(L, 1); // state is unused. + if (!lua_isnil(L, 1)) + i = (size_t)(*((node_t **)luaL_checkudata(L, 1, META_NODE)) - nodes)+1; + if (i < numsegs) + { + LUA_PushUserdata(L, &nodes[i], META_NODE); + return 1; + } + return 0; +} + +static int lib_getNode(lua_State *L) +{ + int field; + lua_settop(L, 2); + lua_remove(L, 1); // dummy userdata table is unused. + if (lua_isnumber(L, 1)) + { + size_t i = lua_tointeger(L, 1); + if (i >= numnodes) + return 0; + LUA_PushUserdata(L, &nodes[i], META_NODE); + return 1; + } + field = luaL_checkoption(L, 1, NULL, array_opt); + switch(field) + { + case 0: // iterate + lua_pushcfunction(L, lib_iterateNodes); + return 1; + } + return 0; +} + +static int lib_numnodes(lua_State *L) +{ + lua_pushinteger(L, numnodes); + return 1; +} +#endif + static int ffloor_get(lua_State *L) { ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR)); @@ -1367,6 +1743,41 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__newindex"); lua_pop(L, 1); +#ifdef HAVE_LUA_SEGS + luaL_newmetatable(L, META_SEG); + lua_pushcfunction(L, seg_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, seg_num); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + + luaL_newmetatable(L, META_NODE); + lua_pushcfunction(L, node_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, node_num); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + + luaL_newmetatable(L, META_NODEBBOX); + //lua_pushcfunction(L, nodebbox_get); + //lua_setfield(L, -2, "__index"); + lua_pushcfunction(L, nodebbox_call); + lua_setfield(L, -2, "__call"); + lua_pop(L, 1); + + luaL_newmetatable(L, META_NODECHILDREN); + lua_pushcfunction(L, nodechildren_get); + lua_setfield(L, -2, "__index"); + lua_pop(L, 1); +#endif + + luaL_newmetatable(L, META_BBOX); + lua_pushcfunction(L, bbox_get); + lua_setfield(L, -2, "__index"); + lua_pop(L, 1); + luaL_newmetatable(L, META_MAPHEADER); lua_pushcfunction(L, mapheaderinfo_get); lua_setfield(L, -2, "__index"); @@ -1425,6 +1836,28 @@ int LUA_MapLib(lua_State *L) lua_setmetatable(L, -2); lua_setglobal(L, "vertexes"); +#ifdef HAVE_LUA_SEGS + lua_newuserdata(L, 0); + lua_createtable(L, 0, 2); + lua_pushcfunction(L, lib_getSeg); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_numsegs); + lua_setfield(L, -2, "__len"); + lua_setmetatable(L, -2); + lua_setglobal(L, "segs"); + + lua_newuserdata(L, 0); + lua_createtable(L, 0, 2); + lua_pushcfunction(L, lib_getNode); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_numnodes); + lua_setfield(L, -2, "__len"); + lua_setmetatable(L, -2); + lua_setglobal(L, "nodes"); +#endif + lua_newuserdata(L, 0); lua_createtable(L, 0, 2); lua_pushcfunction(L, lib_getMapheaderinfo); diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 6bb1388fc..9ebc38a61 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -34,6 +34,7 @@ enum mobj_e { mobj_angle, mobj_sprite, mobj_frame, + mobj_sprite2, mobj_anim_duration, mobj_touching_sectorlist, mobj_subsector, @@ -93,6 +94,7 @@ static const char *const mobj_opt[] = { "angle", "sprite", "frame", + "sprite2", "anim_duration", "touching_sectorlist", "subsector", @@ -189,6 +191,9 @@ static int mobj_get(lua_State *L) case mobj_frame: lua_pushinteger(L, mo->frame); break; + case mobj_sprite2: + lua_pushinteger(L, mo->sprite2); + break; case mobj_anim_duration: lua_pushinteger(L, mo->anim_duration); break; @@ -411,6 +416,9 @@ static int mobj_set(lua_State *L) case mobj_frame: mo->frame = (UINT32)luaL_checkinteger(L, 3); break; + case mobj_sprite2: + mo->sprite2 = P_GetMobjSprite2(mo, (UINT8)luaL_checkinteger(L, 3)); + break; case mobj_anim_duration: mo->anim_duration = (UINT16)luaL_checkinteger(L, 3); break; diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index d3e01a430..29f1c6ff0 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -122,8 +122,8 @@ static int player_get(lua_State *L) lua_pushfixed(L, plr->bob); else if (fastcmp(field,"aiming")) lua_pushangle(L, plr->aiming); - else if (fastcmp(field,"health")) - lua_pushinteger(L, plr->health); + else if (fastcmp(field,"rings")) + lua_pushinteger(L, plr->rings); else if (fastcmp(field,"pity")) lua_pushinteger(L, plr->pity); else if (fastcmp(field,"currentweapon")) @@ -382,8 +382,8 @@ static int player_set(lua_State *L) else if (plr == &players[secondarydisplayplayer]) localaiming2 = plr->aiming; } - else if (fastcmp(field,"health")) - plr->health = (INT32)luaL_checkinteger(L, 3); + else if (fastcmp(field,"rings")) + plr->rings = (INT32)luaL_checkinteger(L, 3); else if (fastcmp(field,"pity")) plr->pity = (SINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"currentweapon")) diff --git a/src/lua_script.c b/src/lua_script.c index acb306827..d30790be1 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -48,6 +48,7 @@ static lua_CFunction liblist[] = { LUA_SkinLib, // skin_t, skins[] LUA_ThinkerLib, // thinker_t LUA_MapLib, // line_t, side_t, sector_t, subsector_t + LUA_BlockmapLib, // blockmap stuff LUA_HudLib, // HUD stuff NULL }; @@ -395,6 +396,7 @@ void LUA_InvalidateLevel(void) { thinker_t *th; size_t i; + ffloor_t *rover = NULL; if (!gL) return; @@ -406,7 +408,15 @@ void LUA_InvalidateLevel(void) for (i = 0; i < numsubsectors; i++) LUA_InvalidateUserdata(&subsectors[i]); for (i = 0; i < numsectors; i++) + { LUA_InvalidateUserdata(§ors[i]); + LUA_InvalidateUserdata(sectors[i].lines); + if (sectors[i].ffloors) + { + for (rover = sectors[i].ffloors; rover; rover = rover->next) + LUA_InvalidateUserdata(rover); + } + } for (i = 0; i < numlines; i++) { LUA_InvalidateUserdata(&lines[i]); @@ -416,6 +426,16 @@ void LUA_InvalidateLevel(void) LUA_InvalidateUserdata(&sides[i]); for (i = 0; i < numvertexes; i++) LUA_InvalidateUserdata(&vertexes[i]); +#ifdef HAVE_LUA_SEGS + for (i = 0; i < numsegs; i++) + LUA_InvalidateUserdata(&segs[i]); + for (i = 0; i < numnodes; i++) + { + LUA_InvalidateUserdata(&nodes[i]); + LUA_InvalidateUserdata(nodes[i].bbox); + LUA_InvalidateUserdata(nodes[i].children); + } +#endif } void LUA_InvalidateMapthings(void) @@ -455,6 +475,11 @@ enum ARCH_SIDE, ARCH_SUBSECTOR, ARCH_SECTOR, +#ifdef HAVE_LUA_SEGS + ARCH_SEG, + ARCH_NODE, +#endif + ARCH_FFLOOR, ARCH_MAPHEADER, ARCH_TEND=0xFF, @@ -474,6 +499,11 @@ static const struct { {META_SIDE, ARCH_SIDE}, {META_SUBSECTOR,ARCH_SUBSECTOR}, {META_SECTOR, ARCH_SECTOR}, +#ifdef HAVE_LUA_SEGS + {META_SEG, ARCH_SEG}, + {META_NODE, ARCH_NODE}, +#endif + {META_FFLOOR, ARCH_FFLOOR}, {META_MAPHEADER, ARCH_MAPHEADER}, {NULL, ARCH_NULL} }; @@ -664,6 +694,56 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) } break; } +#ifdef HAVE_LUA_SEGS + case ARCH_SEG: + { + seg_t *seg = *((seg_t **)lua_touserdata(gL, myindex)); + if (!seg) + WRITEUINT8(save_p, ARCH_NULL); + else { + WRITEUINT8(save_p, ARCH_SEG); + WRITEUINT16(save_p, seg - segs); + } + break; + } + case ARCH_NODE: + { + node_t *node = *((node_t **)lua_touserdata(gL, myindex)); + if (!node) + WRITEUINT8(save_p, ARCH_NULL); + else { + WRITEUINT8(save_p, ARCH_NODE); + WRITEUINT16(save_p, node - nodes); + } + break; + } +#endif + case ARCH_FFLOOR: + { + ffloor_t *rover = *((ffloor_t **)lua_touserdata(gL, myindex)); + if (!rover) + WRITEUINT8(save_p, ARCH_NULL); + else { + ffloor_t *r2; + UINT16 i = 0; + // search for id + for (r2 = rover->target->ffloors; r2; r2 = r2->next) + { + if (r2 == rover) + break; + i++; + } + if (!r2) + WRITEUINT8(save_p, ARCH_NULL); + else + { + WRITEUINT8(save_p, ARCH_FFLOOR); + WRITEUINT16(save_p, rover->target - sectors); + WRITEUINT16(save_p, i); + } + } + break; + } case ARCH_MAPHEADER: { mapheader_t *header = *((mapheader_t **)lua_touserdata(gL, myindex)); @@ -842,6 +922,23 @@ static UINT8 UnArchiveValue(int TABLESINDEX) case ARCH_SECTOR: LUA_PushUserdata(gL, §ors[READUINT16(save_p)], META_SECTOR); break; +#ifdef HAVE_LUA_SEGS + case ARCH_SEG: + LUA_PushUserdata(gL, &segs[READUINT16(save_p)], META_SEG); + break; + case ARCH_NODE: + LUA_PushUserdata(gL, &nodes[READUINT16(save_p)], META_NODE); + break; +#endif + case ARCH_FFLOOR: + { + sector_t *sector = §ors[READUINT16(save_p)]; + UINT16 id = READUINT16(save_p); + ffloor_t *rover = P_GetFFloorByID(sector, id); + if (rover) + LUA_PushUserdata(gL, rover, META_FFLOOR); + break; + } case ARCH_MAPHEADER: LUA_PushUserdata(gL, §ors[READUINT16(save_p)], META_MAPHEADER); break; diff --git a/src/lua_script.h b/src/lua_script.h index 3b159234a..d143ed879 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -92,4 +92,7 @@ void COM_Lua_f(void); }\ } +// uncomment if you want seg_t/node_t in Lua +// #define HAVE_LUA_SEGS + #endif diff --git a/src/m_aatree.h b/src/m_aatree.h index c9077b974..eeaebca3b 100644 --- a/src/m_aatree.h +++ b/src/m_aatree.h @@ -28,4 +28,4 @@ void M_AATreeSet(aatree_t *aatree, INT32 key, void* value); void *M_AATreeGet(aatree_t *aatree, INT32 key); void M_AATreeIterate(aatree_t *aatree, aatree_iter_t callback); -#endif \ No newline at end of file +#endif diff --git a/src/m_cheat.c b/src/m_cheat.c index f9f8454a0..ce9519799 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -606,7 +606,7 @@ void Command_CauseCfail_f(void) players[consoleplayer].mo->y = 123311; //cfail cansuled kthxbye players[consoleplayer].mo->z = 123311; players[consoleplayer].score = 1337; - players[consoleplayer].health = 1337; + players[consoleplayer].rings = 1337; players[consoleplayer].mo->destscale = 25; P_SetThingPosition(players[consoleplayer].mo); @@ -720,7 +720,7 @@ void Command_Setrings_f(void) if (COM_Argc() > 1) { // P_GivePlayerRings does value clamping - players[consoleplayer].health = players[consoleplayer].mo->health = 1; + players[consoleplayer].rings = 0; P_GivePlayerRings(&players[consoleplayer], atoi(COM_Argv(1))); if (!G_IsSpecialStage(gamemap) || !useNightsSS) players[consoleplayer].totalring -= atoi(COM_Argv(1)); //undo totalring addition done in P_GivePlayerRings @@ -1298,7 +1298,7 @@ void Command_ObjectPlace_f(void) // Like the classics, recover from death by entering objectplace if (players[0].mo->health <= 0) { - players[0].mo->health = players[0].health = 1; + players[0].mo->health = 1; players[0].deadtimer = 0; op_oldflags1 = mobjinfo[MT_PLAYER].flags; ++players[0].lives; diff --git a/src/m_fixed.h b/src/m_fixed.h index 70402f27a..1cf9abbae 100644 --- a/src/m_fixed.h +++ b/src/m_fixed.h @@ -46,41 +46,6 @@ typedef INT32 fixed_t; #define FLOAT_TO_FIXED(f) (fixed_t)((f) * ((float)FRACUNIT)) -/** \brief The TMulScale16 function - - \param a a parameter of type fixed_t - \param b a parameter of type fixed_t - \param c a parameter of type fixed_t - \param d a parameter of type fixed_t - \param e a parameter of type fixed_t - \param f a parameter of type fixed_t - - \return fixed_t - - -*/ -FUNCMATH FUNCINLINE static ATTRINLINE fixed_t TMulScale16(fixed_t a, fixed_t b, fixed_t c, fixed_t d, fixed_t e, fixed_t f) \ -{ \ - return (fixed_t)((((INT64)a * (INT64)b) + ((INT64)c * (INT64)d) \ - + ((INT64)e * (INT64)f)) >> 16); \ -} - -/** \brief The DMulScale16 function - - \param a a parameter of type fixed_t - \param b a parameter of type fixed_t - \param c a parameter of type fixed_t - \param d a parameter of type fixed_t - - \return fixed_t - - -*/ -FUNCMATH FUNCINLINE static ATTRINLINE fixed_t DMulScale16(fixed_t a, fixed_t b, fixed_t c, fixed_t d) \ -{ \ - return (fixed_t)((((INT64)a * (INT64)b) + ((INT64)c * (INT64)d)) >> 16); \ -} - #if defined (__WATCOMC__) && FRACBITS == 16 #pragma aux FixedMul = \ "imul ebx", \ @@ -283,9 +248,16 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedFloor(fixed_t x) { const fixed_t a = abs(x); //absolute of x const fixed_t i = (a>>FRACBITS)<<FRACBITS; // cut out the fractional part - const fixed_t f = i-a; // cut out the integral part + const fixed_t f = a-i; // cut out the integral part + if (f == 0) + return x; if (x != INT32_MIN) - return x-f; // return largest integral value not greater than argument + { // return rounded down to nearest whole number + if (x > 0) + return x-f; + else + return x-(FRACUNIT-f); + } return INT32_MIN; } @@ -301,7 +273,7 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedTrunc(fixed_t x) { const fixed_t a = abs(x); //absolute of x const fixed_t i = (a>>FRACBITS)<<FRACBITS; // cut out the fractional part - const fixed_t f = i-a; // cut out the integral part + const fixed_t f = a-i; // cut out the integral part if (x != INT32_MIN) { // return rounded to nearest whole number, towards zero if (x > 0) @@ -324,11 +296,18 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedCeil(fixed_t x) { const fixed_t a = abs(x); //absolute of x const fixed_t i = (a>>FRACBITS)<<FRACBITS; // cut out the fractional part - const fixed_t f = i-a; // cut out the integral part + const fixed_t f = a-i; // cut out the integral part + if (f == 0) + return x; if (x == INT32_MIN) return INT32_MIN; else if (x < FixedFloor(INT32_MAX)) - return x+(FRACUNIT-f); // return smallest integral value not less than argument + { // return rounded up to nearest whole number + if (x > 0) + return x+(FRACUNIT-f); + else + return x+f; + } return INT32_MAX; } @@ -344,7 +323,9 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedRound(fixed_t x) { const fixed_t a = abs(x); //absolute of x const fixed_t i = (a>>FRACBITS)<<FRACBITS; // cut out the fractional part - const fixed_t f = i-a; // cut out the integral part + const fixed_t f = a-i; // cut out the integral part + if (f == 0) + return x; if (x == INT32_MIN) return INT32_MIN; else if (x < FixedFloor(INT32_MAX)) diff --git a/src/m_menu.c b/src/m_menu.c index 3cd142e69..f682cd1b5 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -183,9 +183,6 @@ static INT32 vidm_selected = 0; static INT32 vidm_nummodes; static INT32 vidm_column_size; -// what a headache. -static boolean shiftdown = false; - // // PROTOTYPES // @@ -2083,11 +2080,6 @@ boolean M_Responder(event_t *ev) || gamestate == GS_CREDITS || gamestate == GS_EVALUATION) return false; - if (ev->type == ev_keyup && (ev->data1 == KEY_LSHIFT || ev->data1 == KEY_RSHIFT)) - { - shiftdown = false; - return false; - } if (noFurtherInput) { // Ignore input after enter/escape/other buttons @@ -2101,10 +2093,6 @@ boolean M_Responder(event_t *ev) // added 5-2-98 remap virtual keys (mouse & joystick buttons) switch (ch) { - case KEY_LSHIFT: - case KEY_RSHIFT: - shiftdown = true; - break; //return false; case KEY_MOUSE1: case KEY_JOY1: case KEY_JOY1 + 2: @@ -3831,7 +3819,7 @@ static void M_HandleImageDef(INT32 choice) static void M_PandorasBox(INT32 choice) { (void)choice; - CV_StealthSetValue(&cv_dummyrings, max(players[consoleplayer].health - 1, 0)); + CV_StealthSetValue(&cv_dummyrings, max(players[consoleplayer].rings, 0)); CV_StealthSetValue(&cv_dummylives, players[consoleplayer].lives); CV_StealthSetValue(&cv_dummycontinues, players[consoleplayer].continues); M_SetupNextMenu(&SR_PandoraDef); @@ -3839,7 +3827,7 @@ static void M_PandorasBox(INT32 choice) static boolean M_ExitPandorasBox(void) { - if (cv_dummyrings.value != max(players[consoleplayer].health - 1, 0)) + if (cv_dummyrings.value != max(players[consoleplayer].rings, 0)) COM_ImmedExecute(va("setrings %d", cv_dummyrings.value)); if (cv_dummylives.value != players[consoleplayer].lives) COM_ImmedExecute(va("setlives %d", cv_dummylives.value)); diff --git a/src/m_misc.c b/src/m_misc.c index cfe73d88f..d6ab40196 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -1617,6 +1617,11 @@ INT32 axtoi(const char *hexStg) return intValue; } +// Token parser variables + +static UINT32 oldendPos = 0; // old value of endPos, used by M_UnGetToken +static UINT32 endPos = 0; // now external to M_GetToken, but still static + /** Token parser for TEXTURES, ANIMDEFS, and potentially other lumps later down the line. * Was originally R_GetTexturesToken when I was coding up the TEXTURES parser, until I realized I needed it for ANIMDEFS too. * Parses up to the next whitespace character or comma. When finding the start of the next token, whitespace is skipped. @@ -1631,7 +1636,7 @@ char *M_GetToken(const char *inputString) { static const char *stringToUse = NULL; // Populated if inputString != NULL; used otherwise static UINT32 startPos = 0; - static UINT32 endPos = 0; +// static UINT32 endPos = 0; static UINT32 stringLength = 0; static UINT8 inComment = 0; // 0 = not in comment, 1 = // Single-line, 2 = /* Multi-line */ char *texturesToken = NULL; @@ -1641,12 +1646,12 @@ char *M_GetToken(const char *inputString) { stringToUse = inputString; startPos = 0; - endPos = 0; + oldendPos = endPos = 0; stringLength = strlen(inputString); } else { - startPos = endPos; + startPos = oldendPos = endPos; } if (stringToUse == NULL) return NULL; @@ -1777,6 +1782,16 @@ char *M_GetToken(const char *inputString) return texturesToken; } +/** Undoes the last M_GetToken call + * The current position along the string being parsed is reset to the last saved position. + * This exists mostly because of R_ParseTexture/R_ParsePatch honestly, but could be useful elsewhere? + * -Monster Iestyn (22/10/16) + */ +void M_UnGetToken(void) +{ + endPos = oldendPos; +} + /** Count bits in a number. */ UINT8 M_CountBits(UINT32 num, UINT8 size) diff --git a/src/nds/i_system.c b/src/nds/i_system.c index 0ed58029c..3e5c4b8c6 100644 --- a/src/nds/i_system.c +++ b/src/nds/i_system.c @@ -269,6 +269,18 @@ INT32 I_PutEnv(char *variable) return -1; } +INT32 I_ClipboardCopy(const char *data, size_t size) +{ + (void)data; + (void)size; + return -1; +} + +char *I_ClipboardPaste(void) +{ + return NULL; +} + void I_RegisterSysCommands(void) {} #include "../sdl/dosstr.c" diff --git a/src/p_enemy.c b/src/p_enemy.c index f21841d13..08a79b8cf 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -104,6 +104,9 @@ 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_GravityBox(mobj_t *actor); void A_ScoreRise(mobj_t *actor); void A_ParticleSpawn(mobj_t *actor); @@ -239,6 +242,17 @@ void A_BrakFireShot(mobj_t *actor); void A_BrakLobShot(mobj_t *actor); void A_NapalmScatter(mobj_t *actor); void A_SpawnFreshCopy(mobj_t *actor); +void A_FlickySpawn(mobj_t *actor); +void A_FlickyAim(mobj_t *actor); +void A_FlickyFly(mobj_t *actor); +void A_FlickySoar(mobj_t *actor); +void A_FlickyCoast(mobj_t *actor); +void A_FlickyHop(mobj_t *actor); +void A_FlickyFlounder(mobj_t *actor); +void A_FlickyCheck(mobj_t *actor); +void A_FlickyHeightCheck(mobj_t *actor); +void A_FlickyFlutter(mobj_t *actor); +void A_FlameParticle(mobj_t *actor); // // ENEMY THINKING @@ -658,15 +672,15 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed if ((netgame || multiplayer) && player->spectator) continue; - if (player->health <= 0) - continue; // dead - if (player->pflags & PF_INVIS) continue; // ignore notarget if (!player->mo || P_MobjWasRemoved(player->mo)) continue; + if (player->mo->health <= 0) + continue; // dead + if (dist > 0 && P_AproxDistance(P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y), player->mo->z - actor->z) > dist) continue; // Too far away @@ -730,7 +744,7 @@ static boolean P_LookForShield(mobj_t *actor) player = &players[actor->lastlook]; - if (player->health <= 0 || !player->mo) + if (!player->mo || player->mo->health <= 0) continue; // dead //When in CTF, don't pull rings that you cannot pick up. @@ -738,7 +752,7 @@ static boolean P_LookForShield(mobj_t *actor) (actor->type == MT_BLUETEAMRING && player->ctfteam != 2)) continue; - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT + if ((player->powers[pw_shield] & SH_PROTECTELECTRIC) && (P_AproxDistance(P_AproxDistance(actor->x-player->mo->x, actor->y-player->mo->y), actor->z-player->mo->z) < FixedMul(RING_DIST, player->mo->scale))) { P_SetTarget(&actor->tracer, player->mo); @@ -2121,13 +2135,15 @@ void A_Boss1Laser(mobj_t *actor) if (!(actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH)) { point = P_SpawnMobj(x + P_ReturnThrustX(actor, actor->angle, actor->radius), y + P_ReturnThrustY(actor, actor->angle, actor->radius), actor->z - actor->height / 2, MT_EGGMOBILE_TARGET); + point->angle = actor->angle; point->fuse = actor->tics+1; P_SetTarget(&point->target, actor->target); P_SetTarget(&actor->target, point); } } + /* -- the following was relevant when the MT_EGGMOBILE_TARGET was allowed to move left and right from its path else if (actor->target && !(actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH)) - actor->angle = R_PointToAngle2(x, y, actor->target->x, actor->target->y); + actor->angle = R_PointToAngle2(x, y, actor->target->x, actor->target->y);*/ if (actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH) angle = FixedAngle(FixedDiv(actor->tics*160*FRACUNIT, actor->state->tics*FRACUNIT) + 10*FRACUNIT); @@ -2177,11 +2193,16 @@ void A_Boss1Laser(mobj_t *actor) // var1: // 0 - accelerative focus with friction // 1 - steady focus with fixed movement speed -// var2 = unused +// anything else - don't move +// var2: +// 0 - don't trace target, just move forwards +// & 1 - change horizontal angle +// & 2 - change vertical angle // void A_FocusTarget(mobj_t *actor) { INT32 locvar1 = var1; + INT32 locvar2 = var2; #ifdef HAVE_BLUA if (LUA_CallAction("A_FocusTarget", actor)) return; @@ -2190,9 +2211,9 @@ void A_FocusTarget(mobj_t *actor) if (actor->target) { fixed_t speed = FixedMul(actor->info->speed, actor->scale); - fixed_t dist = R_PointToDist2(actor->x, actor->y, actor->target->x, actor->target->y); - angle_t vangle = R_PointToAngle2(actor->z , 0, actor->target->z + (actor->target->height>>1), dist); - angle_t hangle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); + fixed_t dist = (locvar2 ? R_PointToDist2(actor->x, actor->y, actor->target->x, actor->target->y) : speed+1); + angle_t hangle = ((locvar2 & 1) ? R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) : actor->angle); + angle_t vangle = ((locvar2 & 2) ? R_PointToAngle2(actor->z , 0, actor->target->z + (actor->target->height>>1), dist) : ANGLE_90); switch(locvar1) { case 0: @@ -2553,6 +2574,7 @@ void A_1upThinker(mobj_t *actor) { P_SetTarget(&actor->tracer, P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY)); P_SetTarget(&actor->tracer->target, actor); + actor->tracer->skin = &skins[players[closestplayer].skin]; // required here to prevent spr2 default showing stand for a single frame P_SetMobjState(actor->tracer, actor->info->seestate); // The overlay is going to be one tic early turning off and on @@ -2813,7 +2835,7 @@ 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].health > 0 + if (playeringame[i] && ((players[i].mo && players[i].mo->health > 0) || ((netgame || multiplayer) && (players[i].lives > 0 || players[i].continues > 0)))) break; @@ -3058,11 +3080,7 @@ void A_JumpShield(mobj_t *actor) player = actor->target->player; - if ((player->powers[pw_shield] & SH_NOSTACK) != SH_JUMP) - { - player->powers[pw_shield] = SH_JUMP|(player->powers[pw_shield] & SH_STACK); - P_SpawnShieldOrb(player); - } + P_SwitchShield(player, SH_WHIRLWIND); S_StartSound(player->mo, actor->info->seesound); } @@ -3090,11 +3108,7 @@ void A_RingShield(mobj_t *actor) player = actor->target->player; - if ((player->powers[pw_shield] & SH_NOSTACK) != SH_ATTRACT) - { - player->powers[pw_shield] = SH_ATTRACT|(player->powers[pw_shield] & SH_STACK); - P_SpawnShieldOrb(player); - } + P_SwitchShield(player, SH_ATTRACT); S_StartSound(player->mo, actor->info->seesound); } @@ -3291,11 +3305,12 @@ void A_BombShield(mobj_t *actor) player = actor->target->player; - if ((player->powers[pw_shield] & SH_NOSTACK) != SH_BOMB) - { - player->powers[pw_shield] = SH_BOMB|(player->powers[pw_shield] & SH_STACK); - P_SpawnShieldOrb(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); S_StartSound(player->mo, actor->info->seesound); } @@ -3323,22 +3338,8 @@ void A_WaterShield(mobj_t *actor) player = actor->target->player; - if ((player->powers[pw_shield] & SH_NOSTACK) != SH_ELEMENTAL) - { - player->powers[pw_shield] = SH_ELEMENTAL|(player->powers[pw_shield] & SH_STACK); - P_SpawnShieldOrb(player); - } + P_SwitchShield(player, SH_ELEMENTAL); - if (player->powers[pw_underwater] && player->powers[pw_underwater] <= 12*TICRATE + 1) - P_RestoreMusic(player); - - player->powers[pw_underwater] = 0; - - if (player->powers[pw_spacetime] > 1) - { - player->powers[pw_spacetime] = 0; - P_RestoreMusic(player); - } S_StartSound(player->mo, actor->info->seesound); } @@ -3346,12 +3347,13 @@ void A_WaterShield(mobj_t *actor) // // Description: Awards the player a force shield. // -// var1 = unused +// 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)) @@ -3363,15 +3365,15 @@ void A_ForceShield(mobj_t *actor) return; } + if (locvar1 & ~SH_FORCEHP) + { + CONS_Debug(DBG_GAMELOGIC, "Invalid number of additional hitpoints.\n"); + return; + } + player = actor->target->player; - if (!(player->powers[pw_shield] & SH_FORCE)) - { - player->powers[pw_shield] = SH_FORCE|(player->powers[pw_shield] & SH_STACK)|0x01; - P_SpawnShieldOrb(player); - } - else - player->powers[pw_shield] = SH_FORCE|(player->powers[pw_shield] & SH_STACK)|0x01; + P_SwitchShield(player, SH_FORCE|locvar1); S_StartSound(player->mo, actor->info->seesound); } @@ -3403,12 +3405,92 @@ void A_PityShield(mobj_t *actor) player = actor->target->player; - if ((player->powers[pw_shield] & SH_NOSTACK) != SH_PITY) + 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) { - player->powers[pw_shield] = SH_PITY+(player->powers[pw_shield] & SH_STACK); - P_SpawnShieldOrb(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); } @@ -3435,9 +3517,10 @@ void A_GravityBox(mobj_t *actor) } player = actor->target->player; - player->powers[pw_gravityboots] = (UINT16)(actor->info->reactiontime + 1); S_StartSound(player, actor->info->activesound); + + player->powers[pw_gravityboots] = (UINT16)(actor->info->reactiontime + 1); } // Function: A_ScoreRise @@ -3459,41 +3542,49 @@ void A_ScoreRise(mobj_t *actor) // Function: A_ParticleSpawn // -// Description: Spawns a particle at a specified interval +// Description: Hyper-specialised function for spawning a particle for MT_PARTICLEGEN. // -// var1 = type (if 0, defaults to MT_PARTICLE) +// var1 = unused // var2 = unused // void A_ParticleSpawn(mobj_t *actor) { - INT32 locvar1 = var1; - fixed_t speed; - mobjtype_t type; + INT32 i = 0; mobj_t *spawn; #ifdef HAVE_BLUA if (LUA_CallAction("A_ParticleSpawn", actor)) return; #endif - if (!actor->spawnpoint) - { - P_RemoveMobj(actor); + if (!actor->health) return; + + if (!actor->lastlook) + return; + + if (!actor->threshold) + return; + + for (i = 0; i < actor->lastlook; i++) + { + spawn = P_SpawnMobj( + actor->x + FixedMul(FixedMul(actor->friction, actor->scale), FINECOSINE(actor->angle>>ANGLETOFINESHIFT)), + actor->y + FixedMul(FixedMul(actor->friction, actor->scale), FINESINE(actor->angle>>ANGLETOFINESHIFT)), + actor->z, + (mobjtype_t)actor->threshold); + P_SetScale(spawn, actor->scale); + spawn->momz = FixedMul(actor->movefactor, spawn->scale); + spawn->destscale = spawn->scale/100; + spawn->scalespeed = spawn->scale/actor->health; + 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; } - - if (locvar1) - type = (mobjtype_t)locvar1; - else - type = MT_PARTICLE; - - speed = FixedMul((actor->spawnpoint->angle >> 12)<<FRACBITS, actor->scale); - - spawn = P_SpawnMobj(actor->x, actor->y, actor->z, type); - P_SetScale(spawn, actor->scale); - spawn->momz = speed; - spawn->destscale = FixedDiv(spawn->scale<<FRACBITS, 100<<FRACBITS); - spawn->scalespeed = FixedDiv(((actor->spawnpoint->angle >> 8) & 63) << FRACBITS, 100<<FRACBITS); - actor->tics = actor->spawnpoint->extrainfo + 1; + actor->angle += (angle_t)actor->movecount; } // Function: A_BunnyHop @@ -3703,7 +3794,7 @@ void A_AttractChase(mobj_t *actor) // Turn flingrings back into regular rings if attracted. if (actor->tracer && actor->tracer->player - && (actor->tracer->player->powers[pw_shield] & SH_NOSTACK) != SH_ATTRACT && actor->info->reactiontime && actor->type != (mobjtype_t)actor->info->reactiontime) + && !(actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRIC) && actor->info->reactiontime && actor->type != (mobjtype_t)actor->info->reactiontime) { mobj_t *newring; newring = P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->reactiontime); @@ -3807,11 +3898,18 @@ void A_DropMine(mobj_t *actor) void A_FishJump(mobj_t *actor) { INT32 locvar1 = var1; + INT32 locvar2 = var2; #ifdef HAVE_BLUA if (LUA_CallAction("A_FishJump", actor)) return; #endif + if (locvar2) + { + fixed_t rad = actor->radius>>FRACBITS; + P_SpawnMobjFromMobj(actor, P_RandomRange(rad, -rad)<<FRACBITS, P_RandomRange(rad, -rad)<<FRACBITS, 0, (mobjtype_t)locvar2); + } + if ((actor->z <= actor->floorz) || (actor->z <= actor->watertop - FixedMul((64 << FRACBITS), actor->scale))) { fixed_t jumpval; @@ -3908,7 +4006,7 @@ void A_ThrownRing(mobj_t *actor) // A non-homing ring getting attracted by a // magnetic player. If he gets too far away, make // sure to stop the attraction! - if ((!actor->tracer->health) || (actor->tracer->player && (actor->tracer->player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT + if ((!actor->tracer->health) || (actor->tracer->player && (actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRIC) && P_AproxDistance(P_AproxDistance(actor->tracer->x-actor->x, actor->tracer->y-actor->y), actor->tracer->z-actor->z) > FixedMul(RING_DIST/4, actor->tracer->scale))) { @@ -3916,7 +4014,7 @@ void A_ThrownRing(mobj_t *actor) } if (actor->tracer && (actor->tracer->health) - && (actor->tracer->player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT)// Already found someone to follow. + && (actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRIC))// Already found someone to follow. { const INT32 temp = actor->threshold; actor->threshold = 32000; @@ -3984,7 +4082,7 @@ void A_ThrownRing(mobj_t *actor) if (!P_CheckSight(actor, player->mo)) continue; // out of sight - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT + if ((player->powers[pw_shield] & SH_PROTECTELECTRIC) && dist < FixedMul(RING_DIST/4, player->mo->scale)) P_SetTarget(&actor->tracer, player->mo); return; @@ -7763,7 +7861,7 @@ void A_SetObjectFlags(mobj_t *actor) else if (locvar2 == 1) locvar1 = actor->flags & ~locvar1; - if ((locvar1 & (MF_NOBLOCKMAP|MF_NOSECTOR)) != (actor->flags & (MF_NOBLOCKMAP|MF_NOSECTOR))) // Blockmap/sector status has changed, so reset the links + if ((UINT32)(locvar1 & (MF_NOBLOCKMAP|MF_NOSECTOR)) != (actor->flags & (MF_NOBLOCKMAP|MF_NOSECTOR))) // Blockmap/sector status has changed, so reset the links unlinkthings = true; if (unlinkthings) { @@ -8379,7 +8477,7 @@ void A_RingDrain(mobj_t *actor) } player = actor->target->player; - P_GivePlayerRings(player, -min(locvar1, player->mo->health-1)); + P_GivePlayerRings(player, -min(locvar1, player->rings)); } // Function: A_SplitShot @@ -8687,7 +8785,7 @@ void A_CheckTargetRings(mobj_t *actor) if (!(actor->target) || !(actor->target->player)) return; - if (actor->target->player->health >= locvar1) + if (actor->target->player->rings >= locvar1) P_SetMobjState(actor, locvar2); } @@ -8709,7 +8807,7 @@ void A_CheckRings(mobj_t *actor) #endif for (i = 0; i < MAXPLAYERS; i++) - cntr += players[i].health-1; + cntr += players[i].rings; if (cntr >= locvar1) P_SetMobjState(actor, locvar2); @@ -9281,7 +9379,7 @@ void A_ForceWin(mobj_t *actor) for (i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && (players[i].health > 0 + if (playeringame[i] && ((players[i].mo && players[i].mo->health > 0) || ((netgame || multiplayer) && (players[i].lives > 0 || players[i].continues > 0)))) break; } @@ -9548,14 +9646,19 @@ void A_HomingChase(mobj_t *actor) // lower 16 bits = object # to fire // upper 16 bits = front offset // var2: -// lower 16 bits = vertical angle +// lower 15 bits = vertical angle variable +// 16th bit: +// - 0: use vertical angle variable as vertical angle in degrees +// - 1: mimic P_SpawnXYZMissile +// use z of actor minus z of missile as vertical distance to cover during momz calculation +// use vertical angle variable as horizontal distance to cover during momz calculation // upper 16 bits = height offset // void A_TrapShot(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; - angle_t vertang = FixedAngle(((INT16)(locvar2 & 65535))*FRACUNIT); + boolean oldstyle = (locvar2 & 32768) ? true : false; mobjtype_t type = (mobjtype_t)(locvar1 & 65535); mobj_t *missile; INT16 frontoff = (INT16)(locvar1 >> 16); @@ -9571,10 +9674,7 @@ void A_TrapShot(mobj_t *actor) y = actor->y + P_ReturnThrustY(actor, actor->angle, FixedMul(frontoff*FRACUNIT, actor->scale)); if (actor->eflags & MFE_VERTICALFLIP) - { z = actor->z + actor->height - FixedMul(vertoff*FRACUNIT, actor->scale) - FixedMul(mobjinfo[type].height, actor->scale); - vertang = InvAngle(vertang); // flip firing angle - } else z = actor->z + FixedMul(vertoff*FRACUNIT, actor->scale); @@ -9585,20 +9685,35 @@ void A_TrapShot(mobj_t *actor) if (actor->eflags & MFE_VERTICALFLIP) missile->flags2 |= MF2_OBJECTFLIP; - missile->destscale = actor->destscale; - P_SetScale(missile, missile->destscale); + + missile->destscale = actor->scale; + P_SetScale(missile, actor->scale); if (missile->info->seesound) - S_StartSound(actor, missile->info->seesound); + S_StartSound(missile, missile->info->seesound); P_SetTarget(&missile->target, actor); missile->angle = actor->angle; speed = FixedMul(missile->info->speed, missile->scale); - missile->momx = FixedMul(FINECOSINE(vertang>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(missile->angle>>ANGLETOFINESHIFT), speed)); - missile->momy = FixedMul(FINECOSINE(vertang>>ANGLETOFINESHIFT), FixedMul(FINESINE(missile->angle>>ANGLETOFINESHIFT), speed)); - missile->momz = FixedMul(FINESINE(vertang>>ANGLETOFINESHIFT), speed); + if (oldstyle) + { + missile->momx = FixedMul(FINECOSINE(missile->angle>>ANGLETOFINESHIFT), speed); + missile->momy = FixedMul(FINESINE(missile->angle>>ANGLETOFINESHIFT), speed); + // The below line basically mimics P_SpawnXYZMissile's momz calculation. + missile->momz = (actor->z + ((actor->eflags & MFE_VERTICALFLIP) ? actor->height : 0) - z) / ((fixed_t)(locvar2 & 32767)*FRACUNIT / speed); + P_CheckMissileSpawn(missile); + } + else + { + angle_t vertang = FixedAngle(((INT16)(locvar2 & 32767))*FRACUNIT); + if (actor->eflags & MFE_VERTICALFLIP) + vertang = InvAngle(vertang); // flip firing angle + missile->momx = FixedMul(FINECOSINE(vertang>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(missile->angle>>ANGLETOFINESHIFT), speed)); + missile->momy = FixedMul(FINECOSINE(vertang>>ANGLETOFINESHIFT), FixedMul(FINESINE(missile->angle>>ANGLETOFINESHIFT), speed)); + missile->momz = FixedMul(FINESINE(vertang>>ANGLETOFINESHIFT), speed); + } } // Function: A_VileTarget @@ -10271,3 +10386,421 @@ void A_SpawnFreshCopy(mobj_t *actor) if (newObject->info->seesound) S_StartSound(newObject, newObject->info->seesound); } + +// Internal Flicky spawning function. +mobj_t *P_InternalFlickySpawn(mobj_t *actor, mobjtype_t flickytype, fixed_t momz, boolean lookforplayers) +{ + mobj_t *flicky; + + if (!flickytype) + { + if (!mapheaderinfo[gamemap-1] || !mapheaderinfo[gamemap-1]->numFlickies) // No mapheader, no shoes, no service. + return NULL; + else + { + INT32 prandom = P_RandomKey(mapheaderinfo[gamemap-1]->numFlickies); + flickytype = mapheaderinfo[gamemap-1]->flickies[prandom]; + } + } + + flicky = P_SpawnMobjFromMobj(actor, 0, 0, 0, flickytype); + flicky->angle = actor->angle; + + if (flickytype == MT_SEED) + flicky->z += P_MobjFlip(actor)*(actor->height - flicky->height)/2; + + if (actor->eflags & MFE_UNDERWATER) + momz = FixedDiv(momz, FixedSqrt(3*FRACUNIT)); + + P_SetObjectMomZ(flicky, momz, false); + flicky->movedir = (P_RandomChance(FRACUNIT/2) ? -1 : 1); + flicky->fuse = P_RandomRange(595, 700); // originally 300, 350 + flicky->threshold = 0; + + if (lookforplayers) + P_LookForPlayers(flicky, true, false, 0); + + return flicky; +} + +// Function: A_FlickySpawn +// +// Description: Flicky spawning function. +// +// var1: +// lower 16 bits: if 0, spawns random flicky based on level header. Else, spawns the designated thing type. +// upper 16 bits: if 0, no sound is played. Else, A_Scream is called. +// var2 = upwards thrust for spawned flicky. If zero, default value is provided. +// +void A_FlickySpawn(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FlickySpawn", actor)) + return; +#endif + + if (locvar1 >> 16) { + A_Scream(actor); // A shortcut for the truly lazy. + locvar1 &= 65535; + } + + P_InternalFlickySpawn(actor, locvar1, ((locvar2) ? locvar2 : 8*FRACUNIT), true); +} + +// Internal Flicky bubbling function. +void P_InternalFlickyBubble(mobj_t *actor) +{ + if (actor->eflags & MFE_UNDERWATER) + { + mobj_t *overlay; + + if (!((actor->z + 3*actor->height/2) < actor->watertop) || !mobjinfo[actor->type].raisestate || actor->tracer) + return; + + overlay = P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY); + P_SetMobjStateNF(overlay, mobjinfo[actor->type].raisestate); + P_SetTarget(&actor->tracer, overlay); + P_SetTarget(&overlay->target, actor); + return; + } + + if (!actor->tracer || P_MobjWasRemoved(actor->tracer)) + return; + + P_RemoveMobj(actor->tracer); + P_SetTarget(&actor->tracer, NULL); +} + +// Function: A_FlickyAim +// +// Description: Flicky aiming function. +// +// var1 = how far around the target (in angle constants) the flicky should look +// var2 = distance from target to aim for +// +void A_FlickyAim(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + boolean flickyhitwall = false; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FlickyAim", actor)) + return; +#endif + + if (actor->momx == actor->momy && actor->momy == 0) + flickyhitwall = true; + + P_InternalFlickyBubble(actor); + P_InstaThrust(actor, 0, 0); + + if (!actor->target) + { + P_LookForPlayers(actor, true, false, 0); + actor->angle = P_RandomKey(36)*ANG10; + return; + } + + if (actor->fuse > 2*TICRATE) + { + angle_t posvar; + fixed_t chasevar, chasex, chasey; + + if (flickyhitwall) + actor->movedir *= -1; + + posvar = ((R_PointToAngle2(actor->target->x, actor->target->y, actor->x, actor->y) + actor->movedir*locvar1) >> ANGLETOFINESHIFT) & FINEMASK; + chasevar = FixedSqrt(max(FRACUNIT, P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y) - locvar2)) + locvar2; + + chasex = actor->target->x + FixedMul(FINECOSINE(posvar), chasevar); + chasey = actor->target->y + FixedMul(FINESINE(posvar), chasevar); + + if (P_AproxDistance(chasex - actor->x, chasey - actor->y)) + actor->angle = R_PointToAngle2(actor->x, actor->y, chasex, chasey); + } + else if (flickyhitwall) + { + actor->angle += ANGLE_180; + actor->threshold = 0; + } +} + +//Internal Flicky flying function. Also usuable as an underwater swim thrust. +void P_InternalFlickyFly(mobj_t *actor, fixed_t flyspeed, fixed_t targetdist, fixed_t chasez) +{ + angle_t vertangle; + + flyspeed = FixedMul(flyspeed, actor->scale); + actor->flags |= MF_NOGRAVITY; + + var1 = ANG30; + var2 = 32*FRACUNIT; + A_FlickyAim(actor); + + chasez *= 8; + if (!actor->target || !(actor->fuse > 2*TICRATE)) + chasez += ((actor->eflags & MFE_VERTICALFLIP) ? actor->ceilingz - 24*FRACUNIT : actor->floorz + 24*FRACUNIT); + else + { + fixed_t add = actor->target->z + (actor->target->height - actor->height)/2; + if (add > (actor->ceilingz - 24*actor->scale - actor->height)) + add = actor->ceilingz - 24*actor->scale - actor->height; + else if (add < (actor->floorz + 24*actor->scale)) + add = actor->floorz + 24*actor->scale; + chasez += add; + } + + if (!targetdist) + targetdist = 16*FRACUNIT; //Default! + + if (actor->target && abs(chasez - actor->z) > targetdist) + targetdist = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y); + + vertangle = (R_PointToAngle2(0, actor->z, targetdist, chasez) >> ANGLETOFINESHIFT) & FINEMASK; + P_InstaThrust(actor, actor->angle, FixedMul(FINECOSINE(vertangle), flyspeed)); + actor->momz = FixedMul(FINESINE(vertangle), flyspeed); +} + +// Function: A_FlickyFly +// +// Description: Flicky flying function. +// +// var1 = how fast to fly +// var2 = how far ahead the target should be considered +// +void A_FlickyFly(mobj_t *actor) +{ + // We're not setting up locvars here - it passes var1 and var2 through to P_InternalFlickyFly instead. + //INT32 locvar1 = var1; + //INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FlickyFly", actor)) + return; +#endif + P_InternalFlickyFly(actor, var1, var2, + FINECOSINE((((actor->fuse % 36) * ANG10) >> ANGLETOFINESHIFT) & FINEMASK) + ); +} + +// Function: A_FlickySoar +// +// Description: Flicky soaring function - specific to puffin. +// +// var1 = how fast to fly +// var2 = how far ahead the target should be considered +// +void A_FlickySoar(mobj_t *actor) +{ + // We're not setting up locvars here - it passes var1 and var2 through to P_InternalFlickyFly instead. + //INT32 locvar1 = var1; + //INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FlickySoar", actor)) + return; +#endif + P_InternalFlickyFly(actor, var1, var2, + 2*(FRACUNIT/2 - abs(FINECOSINE((((actor->fuse % 144) * 5*ANG1/2) >> ANGLETOFINESHIFT) & FINEMASK))) + ); + + if (P_MobjFlip(actor)*actor->momz > 0 && actor->frame == 1 && actor->sprite == SPR_FL10) + actor->frame = 3; +} + +//Function: A_FlickyCoast +// +// Description: Flicky swim-coasting function. +// +// var1 = speed to change state upon reaching +// var2 = state to change to upon slowing down +// the spawnstate of the mobj = state to change to when above water +// +void A_FlickyCoast(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FlickyCoast", actor)) + return; +#endif + if (actor->eflags & MFE_UNDERWATER) + { + actor->momx = (11*actor->momx)/12; + actor->momy = (11*actor->momy)/12; + actor->momz = (11*actor->momz)/12; + + if (P_AproxDistance(P_AproxDistance(actor->momx, actor->momy), actor->momz) < locvar1) + P_SetMobjState(actor, locvar2); + + return; + } + + actor->flags &= ~MF_NOGRAVITY; + P_SetMobjState(actor, mobjinfo[actor->type].spawnstate); +} + +// Internal Flicky hopping function. +void P_InternalFlickyHop(mobj_t *actor, fixed_t momz, fixed_t momh, angle_t angle) +{ + if (((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz) + || ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz))) + { + if (momz) + { + if (actor->eflags & MFE_UNDERWATER) + momz = FixedDiv(momz, FixedSqrt(3*FRACUNIT)); + P_SetObjectMomZ(actor, momz, false); + } + P_InstaThrust(actor, angle, FixedMul(momh, actor->scale)); + } +} + +// Function: A_FlickyHop +// +// Description: Flicky hopping function. +// +// var1 = vertical thrust +// var2 = horizontal thrust +// +void A_FlickyHop(mobj_t *actor) +{ + // We're not setting up locvars here - it passes var1 and var2 through to P_InternalFlickyHop instead. + //INT32 locvar1 = var1; + //INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FlickyHop", actor)) + return; +#endif + P_InternalFlickyHop(actor, var1, var2, actor->angle); +} + +// Function: A_FlickyFlounder +// +// Description: Flicky floundering function. +// +// var1 = intended vertical thrust +// var2 = intended horizontal thrust +// +void A_FlickyFlounder(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + angle_t hopangle; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FlickyFlounder", actor)) + return; +#endif + locvar1 *= (P_RandomKey(2) + 1); + locvar2 *= (P_RandomKey(2) + 1); + hopangle = (actor->angle + (P_RandomKey(9) - 4)*ANG2); + P_InternalFlickyHop(actor, locvar1, locvar2, hopangle); +} + +// Function: A_FlickyCheck +// +// Description: Flicky airtime check function. +// +// var1 = state to change to upon touching the floor +// var2 = state to change to upon falling +// the meleestate of the mobj = state to change to when underwater +// +void A_FlickyCheck(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FlickyCheck", actor)) + return; +#endif + if (locvar2 && P_MobjFlip(actor)*actor->momz < 1) + P_SetMobjState(actor, locvar2); + else if (locvar1 && ((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz) + || ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz))) + P_SetMobjState(actor, locvar1); + else if (mobjinfo[actor->type].meleestate && (actor->eflags & MFE_UNDERWATER)) + P_SetMobjState(actor, mobjinfo[actor->type].meleestate); + P_InternalFlickyBubble(actor); +} + +// Function: A_FlickyHeightCheck +// +// Description: Flicky height check function. +// +// var1 = state to change to when falling below height relative to target +// var2 = height relative to target to change state at +// +void A_FlickyHeightCheck(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FlickyHeightCheck", actor)) + return; +#endif + if (locvar1 && actor->target && P_MobjFlip(actor)*actor->momz < 1 + && ((P_MobjFlip(actor)*((actor->z + actor->height/2) - (actor->target->z + actor->target->height/2)) < locvar2) + || (actor->z - actor->height < actor->floorz) || (actor->z + 2*actor->height > actor->ceilingz))) + P_SetMobjState(actor, locvar1); + P_InternalFlickyBubble(actor); +} + +// Function: A_FlickyFlutter +// +// Description: Flicky fluttering function - specific to chicken. +// +// var1 = state to change to upon touching the floor +// var2 = state to change to upon falling +// the meleestate of the mobj = state to change to when underwater +// +void A_FlickyFlutter(mobj_t *actor) +{ + // We're not setting up locvars here - it passes var1 and var2 through to A_FlickyCheck instead. + //INT32 locvar1 = var1; + //INT32 locvar2 = var2; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FlickyFlutter", actor)) + return; +#endif + A_FlickyCheck(actor); + + var1 = ANG30; + var2 = 32*FRACUNIT; + A_FlickyAim(actor); + + P_InstaThrust(actor, actor->angle, 2*actor->scale); + if (P_MobjFlip(actor)*actor->momz < -FRACUNIT/2) + actor->momz = -P_MobjFlip(actor)*actor->scale/2; +} + +#undef FLICKYHITWALL + +// Function: A_FlameParticle +// +// Description: Creates the mobj's painchance at a random position around the object's radius. +// +// var1 = momz of particle. +// +void A_FlameParticle(mobj_t *actor) +{ + mobjtype_t type = (mobjtype_t)(mobjinfo[actor->type].painchance); + INT32 locvar1 = var1; + +#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); + } +} diff --git a/src/p_floor.c b/src/p_floor.c index 8f51698cc..f401271d1 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -13,7 +13,11 @@ #include "doomdef.h" #include "doomstat.h" +#include "m_random.h" #include "p_local.h" +#ifdef ESLOPE +#include "p_slopes.h" +#endif #include "r_state.h" #include "s_sound.h" #include "z_zone.h" @@ -1141,6 +1145,7 @@ void T_MarioBlock(levelspecthink_t *block) block->sector->ceilingdata = NULL; block->sector->floorspeed = 0; block->sector->ceilspeed = 0; + block->direction = 0; } for (i = -1; (i = P_FindSectorFromTag((INT16)block->vars[0], i)) >= 0 ;) @@ -1748,12 +1753,15 @@ static mobj_t *SearchMarioNode(msecnode_t *node) case MT_GHOST: case MT_OVERLAY: case MT_EMERALDSPAWN: - case MT_GREENORB: - case MT_YELLOWORB: - case MT_BLUEORB: - case MT_BLACKORB: - case MT_WHITEORB: - case MT_PITYORB: + case MT_ELEMENTAL_ORB: + case MT_ATTRACT_ORB: + case MT_FORCE_ORB: + case MT_ARMAGEDDON_ORB: + case MT_WHIRLWIND_ORB: + case MT_PITY_ORB: + case MT_FLAMEAURA_ORB: + case MT_BUBBLEWRAP_ORB: + case MT_THUNDERCOIN_ORB: case MT_IVSP: case MT_SUPERSPARK: case MT_RAIN: @@ -1782,8 +1790,8 @@ static mobj_t *SearchMarioNode(msecnode_t *node) break; } // Ignore popped monitors, too. - if (node->m_thing->flags & MF_MONITOR - && node->m_thing->threshold == 68) + if (node->m_thing->health == 0 // this only really applies for monitors + || (!(node->m_thing->flags & MF_MONITOR) && (mobjinfo[node->m_thing->type].flags & MF_MONITOR))) // gold monitor support continue; // Okay, we found something valid. if (!thing // take either the first thing @@ -1797,10 +1805,24 @@ static mobj_t *SearchMarioNode(msecnode_t *node) void T_MarioBlockChecker(levelspecthink_t *block) { line_t *masterline = block->sourceline; + if (block->vars[2] == 1) // Don't update the textures when the block's being bumped upwards. + return; if (SearchMarioNode(block->sector->touching_thinglist)) - sides[masterline->sidenum[0]].midtexture = sides[masterline->sidenum[0]].bottomtexture; + { + sides[masterline->sidenum[0]].midtexture = sides[masterline->sidenum[0]].bottomtexture; // Update textures + if (masterline->backsector) + { + block->sector->ceilingpic = block->sector->floorpic = masterline->backsector->ceilingpic; // Update flats to be backside's ceiling + } + } else + { sides[masterline->sidenum[0]].midtexture = sides[masterline->sidenum[0]].toptexture; + if (masterline->backsector) + { + block->sector->ceilingpic = block->sector->floorpic = masterline->backsector->floorpic; // Update flats to be backside's floor + } + } } // This is the Thwomp's 'brain'. It looks around for players nearby, and if @@ -2520,6 +2542,29 @@ void T_CameraScanner(elevator_t *elevator) } } +void T_PlaneDisplace(planedisplace_t *pd) +{ + sector_t *control, *target; + INT32 direction; + fixed_t diff; + + control = §ors[pd->control]; + target = §ors[pd->affectee]; + + if (control->floorheight == pd->last_height) + return; // no change, no movement + + direction = (control->floorheight > pd->last_height) ? 1 : -1; + diff = FixedMul(control->floorheight-pd->last_height, pd->speed); + + 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) + T_MovePlane(target, INT32_MAX/2, target->ceilingheight+diff, 0, 1, direction); // move ceiling + + pd->last_height = control->floorheight; +} + // // EV_DoFloor // @@ -2877,18 +2922,41 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover) size_t topmostvertex = 0, bottommostvertex = 0; fixed_t leftx, rightx; fixed_t topy, bottomy; - fixed_t topz; + fixed_t topz, bottomz; + fixed_t widthfactor, heightfactor; fixed_t a, b, c; mobjtype_t type = MT_ROCKCRUMBLE1; + fixed_t spacing = (32<<FRACBITS); + tic_t lifetime = 3*TICRATE; + INT16 flags = 0; - // If the control sector has a special - // of Section3:7-15, use the custom debris. - if (GETSECSPECIAL(rover->master->frontsector->special, 3) >= 8) - type = MT_ROCKCRUMBLE1+(GETSECSPECIAL(rover->master->frontsector->special, 3)-7); +#define controlsec rover->master->frontsector + + if (controlsec->tag != 0) + { + INT32 tagline = P_FindSpecialLineFromTag(14, controlsec->tag, -1); + if (tagline != -1) + { + if (sides[lines[tagline].sidenum[0]].toptexture) + type = (mobjtype_t)sides[lines[tagline].sidenum[0]].toptexture; // Set as object type in p_setup.c... + if (sides[lines[tagline].sidenum[0]].textureoffset) + spacing = sides[lines[tagline].sidenum[0]].textureoffset; + if (sides[lines[tagline].sidenum[0]].rowoffset) + { + if (sides[lines[tagline].sidenum[0]].rowoffset>>FRACBITS != -1) + lifetime = (sides[lines[tagline].sidenum[0]].rowoffset>>FRACBITS); + else + lifetime = 0; + } + flags = lines[tagline].flags; + } + } + +#undef controlsec // soundorg z height never gets set normally, so MEH. sec->soundorg.z = sec->floorheight; - S_StartSound(&sec->soundorg, sfx_crumbl); + S_StartSound(&sec->soundorg, mobjinfo[type].activesound); // Find the outermost vertexes in the subsector for (i = 0; i < sec->linecount; i++) @@ -2907,23 +2975,46 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover) bottommostvertex = i; } - leftx = sec->lines[leftmostvertex]->v1->x+(16<<FRACBITS); + leftx = sec->lines[leftmostvertex]->v1->x+(spacing>>1); rightx = sec->lines[rightmostvertex]->v1->x; - topy = sec->lines[topmostvertex]->v1->y-(16<<FRACBITS); + topy = sec->lines[topmostvertex]->v1->y-(spacing>>1); bottomy = sec->lines[bottommostvertex]->v1->y; - topz = *rover->topheight-(16<<FRACBITS); - for (a = leftx; a < rightx; a += (32<<FRACBITS)) + topz = *rover->topheight-(spacing>>1); + bottomz = *rover->bottomheight; + + if (flags & ML_EFFECT1) { - for (b = topy; b > bottomy; b -= (32<<FRACBITS)) + widthfactor = (rightx + topy - leftx - bottomy)>>3; + heightfactor = (topz - *rover->bottomheight)>>2; + } + + for (a = leftx; a < rightx; a += spacing) + { + for (b = topy; b > bottomy; b -= spacing) { if (R_PointInSubsector(a, b)->sector == sec) { mobj_t *spawned = NULL; - for (c = topz; c > *rover->bottomheight; c -= (32<<FRACBITS)) +#ifdef ESLOPE + if (*rover->t_slope) + topz = P_GetZAt(*rover->t_slope, a, b) - (spacing>>1); + if (*rover->b_slope) + bottomz = P_GetZAt(*rover->b_slope, a, b); +#endif + + for (c = topz; c > bottomz; c -= spacing) { spawned = P_SpawnMobj(a, b, c, type); - spawned->fuse = 3*TICRATE; + spawned->angle += P_RandomKey(36)*ANG10; // irrelevant for default objects but might make sense for some custom ones + + if (flags & ML_EFFECT1) + { + P_InstaThrust(spawned, R_PointToAngle2(sec->soundorg.x, sec->soundorg.y, a, b), FixedDiv(P_AproxDistance(a - sec->soundorg.x, b - sec->soundorg.y), widthfactor)); + P_SetObjectMomZ(spawned, FixedDiv((c - bottomz), heightfactor), false); + } + + spawned->fuse = lifetime; } } } @@ -3083,8 +3174,10 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating, return 1; } -INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mobj_t *puncher) +INT32 EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher) { + sector_t *roversec = rover->master->frontsector; + fixed_t topheight = *rover->topheight; levelspecthink_t *block; mobj_t *thing; fixed_t oldx = 0, oldy = 0, oldz = 0; @@ -3092,11 +3185,14 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob I_Assert(puncher != NULL); I_Assert(puncher->player != NULL); - if (sec->floordata || sec->ceilingdata) + if (roversec->floordata || roversec->ceilingdata) return 0; + if (!(rover->flags & FF_SOLID)) + rover->flags |= (FF_SOLID|FF_RENDERALL|FF_CUTLEVEL); + // Find an item to pop out! - thing = SearchMarioNode(sec->touching_thinglist); + thing = SearchMarioNode(roversec->touching_thinglist); // Found something! if (thing) @@ -3106,13 +3202,13 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL); P_AddThinker(&block->thinker); - sec->floordata = block; - sec->ceilingdata = block; + roversec->floordata = block; + roversec->ceilingdata = block; block->thinker.function.acp1 = (actionf_p1)T_MarioBlock; // Set up the fields - block->sector = sec; - block->vars[0] = roversector->tag; // actionsector + block->sector = roversec; + block->vars[0] = sector->tag; // actionsector block->vars[1] = 4*FRACUNIT; // speed block->vars[2] = 1; // Up // direction block->vars[3] = block->sector->floorheight; // floorwasheight @@ -3128,8 +3224,8 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob } P_UnsetThingPosition(thing); - thing->x = roversector->soundorg.x; - thing->y = roversector->soundorg.y; + thing->x = sector->soundorg.x; + thing->y = sector->soundorg.y; thing->z = topheight; thing->momz = FixedMul(6*FRACUNIT, thing->scale); P_SetThingPosition(thing); @@ -3146,7 +3242,7 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob { if (thing->type == MT_EMMY && thing->spawnpoint && (thing->spawnpoint->options & MTF_OBJECTSPECIAL)) { - mobj_t *tokenobj = P_SpawnMobj(roversector->soundorg.x, roversector->soundorg.y, topheight, MT_TOKEN); + 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); @@ -3156,15 +3252,15 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob S_StartSound(puncher, sfx_mario9); // Puncher is "close enough" } - if (itsamonitor) + if (itsamonitor && thing) { - P_UnsetThingPosition(tmthing); - tmthing->x = oldx; - tmthing->y = oldy; - tmthing->z = oldz; - tmthing->momx = 1; - tmthing->momy = 1; - P_SetThingPosition(tmthing); + P_UnsetThingPosition(thing); + thing->x = oldx; + thing->y = oldy; + thing->z = oldz; + thing->momx = 1; + thing->momy = 1; + P_SetThingPosition(thing); } } else diff --git a/src/p_inter.c b/src/p_inter.c index d74726ecb..c7a15275a 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -142,7 +142,10 @@ boolean P_CanPickupItem(player_t *player, boolean weapon) if (player->bot && weapon) return false; - if (player->powers[pw_flashing] > (flashingtics/4)*3 && player->powers[pw_flashing] <= flashingtics) + if (player->powers[pw_flashing] > (flashingtics/4)*3 && player->powers[pw_flashing] < UINT16_MAX) + return false; + + if (player->mo && player->mo->health <= 0) return false; return true; @@ -221,6 +224,65 @@ void P_DoNightsScore(player_t *player) dummymo->destscale = 2*FRACUNIT; } +// +// P_DoMatchSuper +// +// Checks if you have all 7 pw_emeralds, then turns you "super". =P +// +void P_DoMatchSuper(player_t *player) +{ + UINT16 match_emeralds = player->powers[pw_emeralds]; + boolean doteams = false; + int i; + + // If this gametype has teams, check every player on your team for emeralds. + if (G_GametypeHasTeams()) + { + doteams = true; + for (i = 0; i < MAXPLAYERS; i++) + if (players[i].ctfteam == player->ctfteam) + match_emeralds |= players[i].powers[pw_emeralds]; + } + + if (!ALL7EMERALDS(match_emeralds)) + return; + + // Got 'em all? Turn "super"! + emeraldspawndelay = invulntics + 1; + player->powers[pw_emeralds] = 0; + player->powers[pw_invulnerability] = emeraldspawndelay; + player->powers[pw_sneakers] = emeraldspawndelay; + if (P_IsLocalPlayer(player) && !player->powers[pw_super]) + { + S_StopMusic(); + if (mariomode) + G_GhostAddColor(GHC_INVINCIBLE); + S_ChangeMusicInternal((mariomode) ? "_minv" : "_inv", false); + } + + // Also steal 50 points from every enemy, sealing your victory. + P_StealPlayerScore(player, 50); + + // In a team game? + // Check everyone else on your team for emeralds, and turn those helpful assisting players invincible too. + if (doteams) + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] && players[i].ctfteam == player->ctfteam + && players[i].powers[pw_emeralds] != 0) + { + players[i].powers[pw_emeralds] = 0; + player->powers[pw_invulnerability] = invulntics + 1; + player->powers[pw_sneakers] = player->powers[pw_invulnerability]; + if (P_IsLocalPlayer(player) && !player->powers[pw_super]) + { + S_StopMusic(); + if (mariomode) + G_GhostAddColor(GHC_INVINCIBLE); + S_ChangeMusicInternal((mariomode) ? "_minv" : "_inv", false); + } + } +} + /** Takes action based on a ::MF_SPECIAL thing touched by a player. * Actually, this just checks a few things (heights, toucher->player, no * objectplace, no dead or disappearing things) @@ -237,6 +299,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) { player_t *player; INT32 i; + UINT8 elementalpierce; if (objectplacing) return; @@ -291,6 +354,11 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; #endif + // 0 = none, 1 = elemental pierce, 2 = bubble bounce + elementalpierce = (((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (player->pflags & PF_SHIELDABILITY) + ? (((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) ? 1 : 2) + : 0); + if (special->flags & MF_BOSS) { if (special->type == MT_BLACKEGGMAN) @@ -300,14 +368,20 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } if (((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING)) - || ((player->pflags & PF_JUMPED) && !(player->charflags & SF_NOJUMPDAMAGE && !(player->charability == CA_TWINSPIN && player->panim == PA_ABILITY))) + || ((player->pflags & PF_JUMPED) && (player->pflags & PF_FORCEJUMPDAMAGE || !(player->charflags & SF_NOJUMPSPIN) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY))) || (player->pflags & (PF_SPINNING|PF_GLIDING)) || (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) || ((player->charflags & SF_STOMPDAMAGE) && (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0)) - || player->powers[pw_invulnerability] || player->powers[pw_super]) // Do you possess the ability to subdue the object? + || player->powers[pw_invulnerability] || player->powers[pw_super] + || elementalpierce) // Do you possess the ability to subdue the object? { - if (P_MobjFlip(toucher)*toucher->momz < 0) - toucher->momz = -toucher->momz; + if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1)) + { + if (elementalpierce == 2) + P_DoBubbleBounce(player); + else + toucher->momz = -toucher->momz; + } toucher->momx = -toucher->momx; toucher->momy = -toucher->momy; P_DamageMobj(special, toucher, toucher, 1, 0); @@ -333,7 +407,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) /////ENEMIES!!////////////////////////////////////////// //////////////////////////////////////////////////////// if (special->type == MT_GSNAPPER && !(((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING)) - || player->powers[pw_invulnerability] || player->powers[pw_super]) + || player->powers[pw_invulnerability] || player->powers[pw_super] || elementalpierce) && toucher->z < special->z + special->height && toucher->z + toucher->height > special->z) { // Can only hit snapper from above @@ -346,14 +420,19 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) P_DamageMobj(toucher, special, special, 1, 0); } else if (((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING)) - || ((player->pflags & PF_JUMPED) && !(player->charflags & SF_NOJUMPDAMAGE && !(player->charability == CA_TWINSPIN && player->panim == PA_ABILITY))) + || ((player->pflags & PF_JUMPED) && (player->pflags & PF_FORCEJUMPDAMAGE || !(player->charflags & SF_NOJUMPSPIN) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY))) || (player->pflags & (PF_SPINNING|PF_GLIDING)) || (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) || ((player->charflags & SF_STOMPDAMAGE) && (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0)) || player->powers[pw_invulnerability] || player->powers[pw_super]) // Do you possess the ability to subdue the object? { - if (P_MobjFlip(toucher)*toucher->momz < 0) - toucher->momz = -toucher->momz; + if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1)) + { + if (elementalpierce == 2) + P_DoBubbleBounce(player); + else + toucher->momz = -toucher->momz; + } P_DamageMobj(special, toucher, toucher, 1, 0); } @@ -445,7 +524,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) { INT32 pindex = special->info->mass - (INT32)pw_infinityring; - player->powers[special->info->mass] += (UINT16)special->info->reactiontime; + player->powers[special->info->mass] += (UINT16)special->reactiontime; player->ringweapons |= 1 << (pindex-1); if (player->powers[special->info->mass] > rw_maximums[pindex]) @@ -532,7 +611,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; if (special->threshold) + { player->powers[pw_emeralds] |= special->info->speed; + P_DoMatchSuper(player); + } else emeralds |= special->info->speed; @@ -553,6 +635,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; player->powers[pw_emeralds] |= special->threshold; + P_DoMatchSuper(player); break; // Secret emblem thingy @@ -814,16 +897,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (G_IsSpecialStage(gamemap) && !player->exiting) { // In special stages, share rings. Everyone gives up theirs to the player who touched the capsule for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && (&players[i] != player) && players[i].mo->health > 1) + if (playeringame[i] && (&players[i] != player) && players[i].rings > 0) { - toucher->health += players[i].mo->health-1; - player->health = toucher->health; - players[i].mo->health = 1; - players[i].health = players[i].mo->health; + player->rings += players[i].rings; + players[i].rings = 0; } } - if (!(player->health > 1) || player->exiting) + if (player->rings <= 0 || player->exiting) return; // Mark the player as 'pull into the capsule' @@ -1093,15 +1174,33 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // Mario // // ***** // case MT_SHELL: - if (special->state == &states[S_SHELL]) // Resting anim { - // Kick that sucker around! - special->angle = toucher->angle; - P_InstaThrust(special, special->angle, FixedMul(special->info->speed, special->scale)); - S_StartSound(toucher, sfx_mario2); - P_SetMobjState(special, S_SHELL1); - P_SetTarget(&special->target, toucher); - special->threshold = (3*TICRATE)/2; + boolean bounceon = ((P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0)); + if (special->threshold == TICRATE) // it's moving + { + if (bounceon) + { + // Stop it! + special->momx = special->momy = 0; + S_StartSound(toucher, sfx_mario2); + P_SetTarget(&special->target, NULL); + special->threshold = TICRATE - 1; + toucher->momz = -toucher->momz; + } + else // can't handle in PIT_CheckThing because of landing-on causing it to stop + P_DamageMobj(toucher, special, special->target, 1, 0); + } + else if (special->threshold == 0) + { + // Kick that sucker around! + special->movedir = ((special->movedir == 1) ? -1 : 1); + P_InstaThrust(special, toucher->angle, (special->info->speed*special->scale)); + S_StartSound(toucher, sfx_mario2); + P_SetTarget(&special->target, toucher); + special->threshold = (3*TICRATE)/2; + if (bounceon) + toucher->momz = -toucher->momz; + } } return; case MT_AXE: @@ -1134,9 +1233,17 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) case MT_FIREFLOWER: if (player->bot) return; - player->powers[pw_shield] |= SH_FIREFLOWER; - toucher->color = SKINCOLOR_WHITE; - G_GhostAddColor(GHC_FIREFLOWER); + + S_StartSound(toucher, sfx_mario3); + + player->powers[pw_shield] = (player->powers[pw_shield] & SH_NOSTACK)|SH_FIREFLOWER; + + if (!(player->powers[pw_super] || (mariomode && player->powers[pw_invulnerability]))) + { + player->mo->color = SKINCOLOR_WHITE; + G_GhostAddColor(GHC_FIREFLOWER); + } + break; // *************** // @@ -1305,7 +1412,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; } else if (((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING)) - || ((player->pflags & PF_JUMPED) && !(player->charflags & SF_NOJUMPDAMAGE)) + || ((player->pflags & PF_JUMPED) && (player->pflags & PF_FORCEJUMPDAMAGE || !(player->charflags & SF_NOJUMPSPIN) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY))) || ((player->charflags & SF_STOMPDAMAGE) && (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0)) || (player->pflags & (PF_SPINNING|PF_GLIDING)) || player->powers[pw_invulnerability] || player->powers[pw_super]) // Do you possess the ability to subdue the object? @@ -1380,7 +1487,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } if (player->powers[pw_invulnerability] || player->powers[pw_flashing] - || (player->powers[pw_super] && !(ALL7EMERALDS(player->powers[pw_emeralds])))) + || player->powers[pw_super]) return; if (player->powers[pw_shield] || player->bot) //If One-Hit Shield { @@ -1390,11 +1497,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) else { P_PlayRinglossSound(toucher); - if (toucher->health > 10) - toucher->health -= 10; + if (player->rings >= 10) + player->rings -= 10; else - toucher->health = 1; - player->health = toucher->health; + player->rings = 0; } P_DoPlayerPain(player, special, NULL); @@ -1418,7 +1524,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; case MT_EXTRALARGEBUBBLE: - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) + if (player->powers[pw_shield] & SH_PROTECTWATER) return; if (maptol & TOL_NIGHTS) return; @@ -1496,6 +1602,9 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour if (!player) return; // Impossible! + if (!player->mo) + return; // Also impossible! + if (player->spectator) return; // No messages for dying (crushed) spectators. @@ -1503,11 +1612,11 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour return; // Presumably it's obvious what's happening in splitscreen. #ifdef HAVE_BLUA - if (LUAh_HurtMsg(player, inflictor, source)) + if (LUAh_HurtMsg(player, inflictor, source, damagetype)) return; #endif - deadtarget = (player->health <= 0); + deadtarget = (player->mo->health <= 0); // Target's name snprintf(targetname, sizeof(targetname), "%s%s%s", @@ -1541,8 +1650,10 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour else switch (inflictor->type) { case MT_PLAYER: - if ((inflictor->player->powers[pw_shield] & SH_NOSTACK) == SH_BOMB) + 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"); 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]) @@ -1699,7 +1810,7 @@ void P_CheckTimeLimit(void) return; //Tagmode round end but only on the tic before the - //XD_EXITLEVEL packet is recieved by all players. + //XD_EXITLEVEL packet is received by all players. if (G_TagGametype()) { if (leveltime == (timelimitintics + 1)) @@ -1710,7 +1821,7 @@ void P_CheckTimeLimit(void) || (players[i].pflags & PF_TAGGED) || (players[i].pflags & PF_TAGIT)) continue; - CONS_Printf(M_GetText("%s recieved double points for surviving the round.\n"), player_names[i]); + CONS_Printf(M_GetText("%s received double points for surviving the round.\n"), player_names[i]); P_AddPlayerScore(&players[i], players[i].score); } } @@ -1950,7 +2061,6 @@ boolean P_CheckRacers(void) */ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype) { - mobjtype_t item; mobj_t *mo; if (inflictor && (inflictor->type == MT_SHELL || inflictor->type == MT_FIREBALL)) @@ -1974,7 +2084,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget target->health = 0; // This makes it easy to check if something's dead elsewhere. #ifdef HAVE_BLUA - if (LUAh_MobjDeath(target, inflictor, source) || P_MobjWasRemoved(target)) + if (LUAh_MobjDeath(target, inflictor, source, damagetype) || P_MobjWasRemoved(target)) return; #endif @@ -2166,81 +2276,80 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget if (source && target && target->player && source->player) P_PlayVictorySound(source); // Killer laughs at you. LAUGHS! BWAHAHAHA! +#ifdef OLDANIMALSPAWNING // Drop stuff. // This determines the kind of object spawned // during the death frame of a thing. if (!mariomode // Don't show birds, etc. in Mario Mode Tails 12-23-2001 && target->flags & MF_ENEMY) { - if (cv_soniccd.value) - item = MT_SEED; - else + mobjtype_t item; + INT32 prandom; + + switch (target->type) { - INT32 prandom; + case MT_REDCRAWLA: + case MT_GOLDBUZZ: + case MT_SKIM: + case MT_UNIDUS: + item = MT_FLICKY_02/*MT_BUNNY*/; + break; - switch (target->type) - { - case MT_REDCRAWLA: - case MT_GOLDBUZZ: - case MT_SKIM: - case MT_UNIDUS: - item = MT_BUNNY; - break; + case MT_BLUECRAWLA: + case MT_JETTBOMBER: + case MT_GFZFISH: + item = MT_FLICKY_01/*MT_BIRD*/; + break; - case MT_BLUECRAWLA: - case MT_JETTBOMBER: - case MT_GFZFISH: - item = MT_BIRD; - break; + case MT_JETTGUNNER: + case MT_CRAWLACOMMANDER: + case MT_REDBUZZ: + case MT_DETON: + item = MT_FLICKY_12/*MT_MOUSE*/; + break; - case MT_JETTGUNNER: - case MT_CRAWLACOMMANDER: - case MT_REDBUZZ: - case MT_DETON: - item = MT_MOUSE; - break; + case MT_GSNAPPER: + case MT_EGGGUARD: + case MT_SPRINGSHELL: + item = MT_FLICKY_11/*MT_COW*/; + break; - case MT_GSNAPPER: - case MT_EGGGUARD: - case MT_SPRINGSHELL: - item = MT_COW; - break; + case MT_MINUS: + case MT_VULTURE: + case MT_POINTY: + case MT_YELLOWSHELL: + item = MT_FLICKY_03/*MT_CHICKEN*/; + break; - case MT_MINUS: - case MT_VULTURE: - case MT_POINTY: - case MT_YELLOWSHELL: - item = MT_CHICKEN; - break; + case MT_AQUABUZZ: + item = MT_FLICKY_01/*MT_REDBIRD*/; + break; - case MT_AQUABUZZ: - item = MT_REDBIRD; - break; + default: + if (target->info->doomednum) + prandom = target->info->doomednum%5; // "Random" animal for new enemies. + else + prandom = P_RandomKey(5); // No placable object, just use a random number. - default: - if (target->info->doomednum) - prandom = target->info->doomednum%5; // "Random" animal for new enemies. - else - prandom = P_RandomKey(5); // No placable object, just use a random number. - - switch(prandom) - { - default: item = MT_BUNNY; break; - case 1: item = MT_BIRD; break; - case 2: item = MT_MOUSE; break; - case 3: item = MT_COW; break; - case 4: item = MT_CHICKEN; break; - } - break; - } + switch(prandom) + { + default: item = MT_FLICKY_02/*MT_BUNNY*/; break; + case 1: item = MT_FLICKY_01/*MT_BIRD*/; break; + case 2: item = MT_FLICKY_12/*MT_MOUSE*/; break; + case 3: item = MT_FLICKY_11/*MT_COW*/; break; + case 4: item = MT_FLICKY_03/*MT_CHICKEN*/; break; + } + break; } mo = P_SpawnMobj(target->x, target->y, target->z + (target->height / 2) - FixedMul(mobjinfo[item].height / 2, target->scale), item); mo->destscale = target->scale; P_SetScale(mo, mo->destscale); } + else +#endif // Other death animation effects - else switch(target->type) + switch(target->type) { case MT_BOUNCEPICKUP: case MT_RAILPICKUP: @@ -2258,24 +2367,27 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget break; case MT_PLAYER: - target->fuse = TICRATE*3; // timer before mobj disappears from view (even if not an actual player) - target->momx = target->momy = target->momz = 0; - if (damagetype == DMG_DROWNED) // drowned { - target->movedir = damagetype; // we're MOVING the Damage Into anotheR function... Okay, this is a bit of a hack. - if (target->player->charflags & SF_MACHINE) - S_StartSound(target, sfx_fizzle); + target->fuse = TICRATE*3; // timer before mobj disappears from view (even if not an actual player) + target->momx = target->momy = target->momz = 0; + + if (damagetype == DMG_DROWNED) // drowned + { + target->movedir = damagetype; // we're MOVING the Damage Into anotheR function... Okay, this is a bit of a hack. + if (target->player->charflags & SF_MACHINE) + S_StartSound(target, sfx_fizzle); + else + S_StartSound(target, sfx_drown); + // Don't jump up when drowning + } else - S_StartSound(target, sfx_drown); - // Don't jump up when drowning - } - else - { - P_SetObjectMomZ(target, 14*FRACUNIT, false); - if ((source && source->type == MT_SPIKE) || damagetype == DMG_SPIKE) // Spikes - S_StartSound(target, sfx_spkdth); - else - P_PlayDeathSound(target); + { + P_SetObjectMomZ(target, 14*FRACUNIT, false); + if ((source && source->type == MT_SPIKE) || damagetype == DMG_SPIKE) // Spikes + S_StartSound(target, sfx_spkdth); + else + P_PlayDeathSound(target); + } } break; default: @@ -2442,8 +2554,7 @@ static inline void P_NiGHTSDamage(mobj_t *target, mobj_t *source) player_t *player = target->player; tic_t oldnightstime = player->nightstime; - if (!player->powers[pw_flashing] - && !(player->pflags & PF_GODMODE)) + if (!player->powers[pw_flashing]) { angle_t fa; @@ -2558,27 +2669,18 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou return true; } - if (target->health <= 1) // Death + if (player->rings > 0) // Ring loss + { + P_PlayRinglossSound(target); + P_PlayerRingBurst(player, player->rings); + } + else // Death { P_PlayDeathSound(target); P_PlayVictorySound(source); // Killer laughs at you! LAUGHS! BWAHAHAHHAHAA!! } - else if (target->health > 1) // Ring loss - { - P_PlayRinglossSound(target); - P_PlayerRingBurst(player, player->mo->health - 1); - } - - if (inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player) && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds])) - { - player->health -= 10; - if (player->health < 2) - player->health = 2; - target->health = player->health; - } - else - player->health = target->health = 1; + player->rings = 0; return true; } @@ -2629,7 +2731,7 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage) // Burst weapons and emeralds in Match/CTF only if (source && (gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF)) { - P_PlayerRingBurst(player, player->health - 1); + P_PlayerRingBurst(player, player->rings); P_PlayerEmeraldBurst(player, false); } @@ -2733,22 +2835,21 @@ void P_RemoveShield(player_t *player) { if (player->powers[pw_shield] & SH_FORCE) { // Multi-hit - if ((player->powers[pw_shield] & 0xFF) == 0) - player->powers[pw_shield] &= ~SH_FORCE; - else + if (player->powers[pw_shield] & SH_FORCEHP) player->powers[pw_shield]--; + else + player->powers[pw_shield] &= SH_STACK; } else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_NONE) { // Second layer shields - player->powers[pw_shield] = SH_NONE; - // Reset fireflower - if (!player->powers[pw_super]) + if (((player->powers[pw_shield] & SH_STACK) == SH_FIREFLOWER) && !(player->powers[pw_super] || (mariomode && player->powers[pw_invulnerability]))) { player->mo->color = player->skincolor; G_GhostAddColor(GHC_NORMAL); } + player->powers[pw_shield] = SH_NONE; } - else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_BOMB) // Give them what's coming to them! + else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ARMAGEDDON) // Give them what's coming to them! { P_BlackOw(player); // BAM! player->pflags |= PF_JUMPDOWN; @@ -2757,7 +2858,7 @@ void P_RemoveShield(player_t *player) player->powers[pw_shield] = player->powers[pw_shield] & SH_STACK; } -static void P_ShieldDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage) +static void P_ShieldDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) { // Must do pain first to set flashing -- P_RemoveShield can cause damage P_DoPlayerPain(player, source, inflictor); @@ -2766,7 +2867,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 || (source->type == MT_NULL && source->threshold == 43))) // spikes + if ((source && source->type == MT_SPIKE) || damagetype == DMG_SPIKE) // spikes S_StartSound(player->mo, sfx_spkdth); else S_StartSound (player->mo, sfx_shldls); // Ba-Dum! Shield loss. @@ -2791,15 +2892,12 @@ static void P_ShieldDamage(player_t *player, mobj_t *inflictor, mobj_t *source, static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) { - if (!(inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player) && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))) - { - P_DoPlayerPain(player, source, inflictor); + P_DoPlayerPain(player, source, inflictor); - P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2); + P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2); - if ((source && source->type == MT_SPIKE) || damagetype == DMG_SPIKE) // spikes - S_StartSound(player->mo, sfx_spkdth); - } + if ((source && source->type == MT_SPIKE) || 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 { @@ -2821,6 +2919,10 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN // Ring loss sound plays despite hitting spikes P_PlayRinglossSound(player->mo); // Ringledingle! + P_PlayerRingBurst(player, damage); + player->rings -= damage; + if (player->rings < 0) + player->rings = 0; } /** Damages an object, which may or may not be a player. @@ -2869,7 +2971,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da // Everything above here can't be forced. if (!metalrecording) { - UINT8 shouldForce = LUAh_ShouldDamage(target, inflictor, source, damage); + UINT8 shouldForce = LUAh_ShouldDamage(target, inflictor, source, damage, damagetype); if (P_MobjWasRemoved(target)) return (shouldForce == 1); // mobj was removed if (shouldForce == 1) @@ -2912,7 +3014,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da return false; #ifdef HAVE_BLUA - if (LUAh_MobjDamage(target, inflictor, source, damage) || P_MobjWasRemoved(target)) + if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype) || P_MobjWasRemoved(target)) return true; #endif @@ -2940,7 +3042,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da return false; #ifdef HAVE_BLUA - if (LUAh_MobjDamage(target, inflictor, source, damage) || P_MobjWasRemoved(target)) + if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype) || P_MobjWasRemoved(target)) return true; #endif @@ -2950,7 +3052,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da #ifdef HAVE_BLUA else if (target->flags & MF_ENEMY) { - if (LUAh_MobjDamage(target, inflictor, source, damage) || P_MobjWasRemoved(target)) + if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype) || P_MobjWasRemoved(target)) return true; } #endif @@ -2964,18 +3066,24 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (player->exiting) return false; + if (player->pflags & PF_GODMODE) + return false; + if (!(target->player->pflags & (PF_NIGHTSMODE|PF_NIGHTSFALL)) && (maptol & TOL_NIGHTS)) return false; 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_NOSTACK) == SH_ELEMENTAL) - return false; // Invincible to water/fire damage + if (player->powers[pw_shield] & SH_PROTECTFIRE) + return false; // Invincible to fire damage break; case DMG_ELECTRIC: - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT) + if (player->powers[pw_shield] & SH_PROTECTELECTRIC) return false; // Invincible to electric damage break; default: @@ -2991,11 +3099,11 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da return false; // Don't hit yourself with your own paraloop, baka if (source && source->player && !cv_friendlyfire.value && (gametype == GT_COOP - || (G_GametypeHasTeams() && target->player->ctfteam == source->player->ctfteam))) + || (G_GametypeHasTeams() && player->ctfteam == source->player->ctfteam))) return false; // Don't run eachother over in special stages and team games and such } #ifdef HAVE_BLUA - if (LUAh_MobjDamage(target, inflictor, source, damage)) + if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype)) return true; #endif P_NiGHTSDamage(target, source); // -5s :( @@ -3004,7 +3112,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (!force && inflictor && inflictor->flags & MF_FIRE) { - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) + if (player->powers[pw_shield] & SH_PROTECTFIRE) return false; // Invincible to fire objects if (G_PlatformGametype() && inflictor && source && source->player) @@ -3026,12 +3134,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da return false; } - if (!force && player->pflags & PF_GODMODE) - return false; - // Instant-Death if (damagetype & DMG_DEATHMASK) + { P_KillPlayer(player, source, damage); + player->rings = 0; + } else if (metalrecording) { if (!inflictor) @@ -3045,19 +3153,19 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da return false; // Metal Sonic walk through flame !! else { // Oh no! Metal Sonic is hit !! - P_ShieldDamage(player, inflictor, source, damage); + P_ShieldDamage(player, inflictor, source, damage, damagetype); return true; } } else if (player->powers[pw_invulnerability] || player->powers[pw_flashing] // ignore bouncing & such in invulnerability - || (player->powers[pw_super] && !(ALL7EMERALDS(player->powers[pw_emeralds]) && inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player)))) + || player->powers[pw_super]) { if (force || (inflictor && (inflictor->flags & MF_MISSILE) && (inflictor->flags2 & MF2_SUPERFIRE) && player->powers[pw_super])) { #ifdef HAVE_BLUA - if (!LUAh_MobjDamage(target, inflictor, source, damage)) + if (!LUAh_MobjDamage(target, inflictor, source, damage, damagetype)) #endif P_SuperDamage(player, inflictor, source, damage); return true; @@ -3066,67 +3174,35 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da return false; } #ifdef HAVE_BLUA - else if (LUAh_MobjDamage(target, inflictor, source, damage)) + else if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype)) return true; #endif - else if (!player->powers[pw_super] && (player->powers[pw_shield] || player->bot)) //If One-Hit Shield + else if (player->powers[pw_shield] || player->bot) //If One-Hit Shield { - P_ShieldDamage(player, inflictor, source, damage); + P_ShieldDamage(player, inflictor, source, damage, damagetype); damage = 0; } - else if (player->mo->health > 1) // No shield but have rings. + else if (player->rings > 0) // No shield but have rings. { - damage = player->mo->health - 1; + damage = player->rings; P_RingDamage(player, inflictor, source, damage, damagetype); + damage = 0; + } + // To reduce griefing potential, don't allow players to be killed + // by friendly fire. Spilling their rings and other items is enough. + else if (!force && G_GametypeHasTeams() + && source && source->player && (source->player->ctfteam == player->ctfteam) + && cv_friendlyfire.value) + { + damage = 0; + P_ShieldDamage(player, inflictor, source, damage, damagetype); } else // No shield, no rings, no invincibility. { - // To reduce griefing potential, don't allow players to be killed - // by friendly fire. Spilling their rings and other items is enough. - if (force || !(G_GametypeHasTeams() - && source && source->player && (source->player->ctfteam == player->ctfteam) - && cv_friendlyfire.value)) - { - damage = 1; - P_KillPlayer(player, source, damage); - } - else - { - damage = 0; - P_ShieldDamage(player, inflictor, source, damage); - } + damage = 1; + P_KillPlayer(player, source, damage); } - if (inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player) && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds])) - { - if (player->powers[pw_shield]) - { - P_RemoveShield(player); - return true; - } - else - { - player->health -= (10 * (1 << (INT32)(player->powers[pw_super] / 10500))); - if (player->health < 2) - player->health = 2; - } - - if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) - P_PlayerFlagBurst(player, false); - } - else if (damagetype & DMG_DEATHMASK) - player->health = 0; - else - { - player->health -= damage; // mirror mobj health here - target->player->powers[pw_flashing] = flashingtics; - if (damage > 0) // don't spill emeralds/ammo/panels for shield damage - P_PlayerRingBurst(player, damage); - } - - if (player->health < 0) - player->health = 0; - P_HitDeathMessages(player, inflictor, source, damagetype); P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2); @@ -3138,13 +3214,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da P_DamageMobj(source, target, target, 1, 0); // do the damage - if (player && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]) && inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player)) - { - target->health -= (10 * (1 << (INT32)(player->powers[pw_super] / 10500))); - if (target->health < 2) - target->health = 2; - } - else if (damagetype & DMG_DEATHMASK) + if (damagetype & DMG_DEATHMASK) target->health = 0; else target->health -= damage; @@ -3159,10 +3229,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } if (player) - { - if (!(player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))) - P_ResetPlayer(target->player); - } + P_ResetPlayer(target->player); else switch (target->type) { @@ -3185,16 +3252,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da // if not intent on another player, // chase after this one P_SetTarget(&target->target, source); - if (target->state == &states[target->info->spawnstate] && target->info->seestate != S_NULL) - { - if (player) - { - if (!(player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))) - P_SetPlayerMobjState(target, target->info->seestate); - } - else - P_SetMobjState(target, target->info->seestate); - } } return true; @@ -3220,7 +3277,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) return; // If no health, don't spawn ring! - if (player->mo->health <= 1) + if (player->rings <= 0) num_rings = 0; if (num_rings > 32 && !(player->pflags & PF_NIGHTSFALL)) @@ -3230,11 +3287,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) P_PlayerEmeraldBurst(player, false); // Spill weapons first - if (player->ringweapons) - P_PlayerWeaponPanelBurst(player); - - // Spill the ammo - P_PlayerWeaponAmmoBurst(player); + P_PlayerWeaponPanelOrAmmoBurst(player); for (i = 0; i < num_rings; i++) { @@ -3491,6 +3544,75 @@ void P_PlayerWeaponAmmoBurst(player_t *player) } } +void P_PlayerWeaponPanelOrAmmoBurst(player_t *player) +{ + mobj_t *mo; + angle_t fa; + fixed_t ns; + INT32 i = 0; + fixed_t z; + + #define SETUP_DROP(thingtype) \ + z = player->mo->z; \ + if (player->mo->eflags & MFE_VERTICALFLIP) \ + z += player->mo->height - mobjinfo[thingtype].height; \ + fa = ((i*FINEANGLES/16) + (player->mo->angle>>ANGLETOFINESHIFT)) & FINEMASK; \ + ns = FixedMul(3*FRACUNIT, player->mo->scale); \ + + #define DROP_WEAPON(rwflag, pickup, ammo, power) \ + if (player->ringweapons & rwflag) \ + { \ + player->ringweapons &= ~rwflag; \ + SETUP_DROP(pickup) \ + mo = P_SpawnMobj(player->mo->x, player->mo->y, z, pickup); \ + mo->reactiontime = 0; \ + mo->flags2 |= MF2_DONTRESPAWN; \ + mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT); \ + P_SetTarget(&mo->target, player->mo); \ + mo->fuse = 12*TICRATE; \ + mo->destscale = player->mo->scale; \ + P_SetScale(mo, player->mo->scale); \ + mo->momx = FixedMul(FINECOSINE(fa),ns); \ + if (!(twodlevel || (player->mo->flags2 & MF2_TWOD))) \ + mo->momy = FixedMul(FINESINE(fa),ns); \ + P_SetObjectMomZ(mo, 4*FRACUNIT, false); \ + if (i & 1) \ + P_SetObjectMomZ(mo, 4*FRACUNIT, true); \ + ++i; \ + } \ + else if (player->powers[power] > 0) \ + { \ + SETUP_DROP(ammo) \ + mo = P_SpawnMobj(player->mo->x, player->mo->y, z, ammo); \ + mo->health = player->powers[power]; \ + mo->flags2 |= MF2_DONTRESPAWN; \ + mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT); \ + P_SetTarget(&mo->target, player->mo); \ + mo->fuse = 12*TICRATE; \ + mo->destscale = player->mo->scale; \ + P_SetScale(mo, player->mo->scale); \ + mo->momx = FixedMul(FINECOSINE(fa),ns); \ + if (!(twodlevel || (player->mo->flags2 & MF2_TWOD))) \ + mo->momy = FixedMul(FINESINE(fa),ns); \ + P_SetObjectMomZ(mo, 3*FRACUNIT, false); \ + if (i & 1) \ + P_SetObjectMomZ(mo, 3*FRACUNIT, true); \ + player->powers[power] = 0; \ + ++i; \ + } + + DROP_WEAPON(RW_BOUNCE, MT_BOUNCEPICKUP, MT_BOUNCERING, pw_bouncering); + DROP_WEAPON(RW_RAIL, MT_RAILPICKUP, MT_RAILRING, pw_railring); + DROP_WEAPON(RW_AUTO, MT_AUTOPICKUP, MT_AUTOMATICRING, pw_automaticring); + DROP_WEAPON(RW_EXPLODE, MT_EXPLODEPICKUP, MT_EXPLOSIONRING, pw_explosionring); + DROP_WEAPON(RW_SCATTER, MT_SCATTERPICKUP, MT_SCATTERRING, pw_scatterring); + DROP_WEAPON(RW_GRENADE, MT_GRENADEPICKUP, MT_GRENADERING, pw_grenadering); + DROP_WEAPON(0, 0, MT_INFINITYRING, pw_infinityring); + + #undef DROP_WEAPON + #undef SETUP_DROP +} + // // P_PlayerEmeraldBurst // diff --git a/src/p_local.h b/src/p_local.h index de717801e..9b7c16702 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -59,9 +59,10 @@ #define AIMINGTOSLOPE(aiming) FINESINE((aiming>>ANGLETOFINESHIFT) & FINEMASK) -#define mariomode (maptol & TOL_MARIO) #define twodlevel (maptol & TOL_2D) +#define mariomode (maptol & TOL_MARIO) + #define P_GetPlayerHeight(player) FixedMul(player->height, player->mo->scale) #define P_GetPlayerSpinHeight(player) FixedMul(player->spinheight, player->mo->scale) @@ -124,6 +125,7 @@ extern fixed_t t_cam2_dist, t_cam2_height, t_cam2_rotate; INT32 P_GetPlayerControlDirection(player_t *player); void P_AddPlayerScore(player_t *player, UINT32 amount); +void P_StealPlayerScore(player_t *player, UINT32 amount); void P_ResetCamera(player_t *player, camera_t *thiscam); boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam); void P_SlideCameraMove(camera_t *thiscam); @@ -142,6 +144,7 @@ boolean P_InQuicksand(mobj_t *mo); void P_SetObjectMomZ(mobj_t *mo, fixed_t value, boolean relative); void P_RestoreMusic(player_t *player); void P_SpawnShieldOrb(player_t *player); +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); @@ -151,8 +154,9 @@ void P_ResetScore(player_t *player); boolean P_AutoPause(void); void P_DoJumpShield(player_t *player); +void P_DoBubbleBounce(player_t *player); void P_BlackOw(player_t *player); -void P_ElementalFireTrail(player_t *player); +void P_ElementalFire(player_t *player, boolean cropcircle); void P_DoPityCheck(player_t *player); void P_PlayerThink(player_t *player); @@ -165,7 +169,7 @@ fixed_t P_ReturnThrustX(mobj_t *mo, angle_t angle, fixed_t move); fixed_t P_ReturnThrustY(mobj_t *mo, angle_t angle, fixed_t move); void P_InstaThrustEvenIn2D(mobj_t *mo, angle_t angle, fixed_t move); -boolean P_LookForEnemies(player_t *player); +boolean P_LookForEnemies(player_t *player, boolean nonenemies); void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius); void P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user boolean P_SuperReady(player_t *player); @@ -211,6 +215,7 @@ 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); @@ -290,6 +295,11 @@ boolean P_CheckMissileRange(mobj_t *actor); void P_NewChaseDir(mobj_t *actor); boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed_t dist); +mobj_t *P_InternalFlickySpawn(mobj_t *actor, mobjtype_t flickytype, fixed_t momz, boolean lookforplayers); +void P_InternalFlickyBubble(mobj_t *actor); +void P_InternalFlickyFly(mobj_t *actor, fixed_t flyspeed, fixed_t targetdist, fixed_t chasez); +void P_InternalFlickyHop(mobj_t *actor, fixed_t momz, fixed_t momh, angle_t angle); + // // P_MAP // @@ -380,7 +390,8 @@ typedef struct BasicFF_s #define DMG_FIRE 2 #define DMG_ELECTRIC 3 #define DMG_SPIKE 4 -//#define DMG_SPECIALSTAGE 5 +#define DMG_NUKE 5 // bomb shield +//#define DMG_SPECIALSTAGE 6 //// Death types - cannot be combined with damage types #define DMG_INSTAKILL 0x80 #define DMG_DROWNED 0x80+1 @@ -399,6 +410,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget void P_PlayerRingBurst(player_t *player, INT32 num_rings); /// \todo better fit in p_user.c void P_PlayerWeaponPanelBurst(player_t *player); void P_PlayerWeaponAmmoBurst(player_t *player); +void P_PlayerWeaponPanelOrAmmoBurst(player_t *player); void P_PlayerEmeraldBurst(player_t *player, boolean toss); void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck); @@ -413,6 +425,7 @@ void P_ResetStarposts(void); boolean P_CanPickupItem(player_t *player, boolean weapon); void P_DoNightsScore(player_t *player); +void P_DoMatchSuper(player_t *player); // // P_SPEC diff --git a/src/p_map.c b/src/p_map.c index 6ac48a7c8..d362caf80 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -203,7 +203,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) } } - pflags = object->player->pflags & (PF_JUMPED|PF_SPINNING|PF_THOKKED); // I still need these. + pflags = object->player->pflags & (PF_JUMPED|PF_SPINNING|PF_THOKKED|PF_SHIELDABILITY); // I still need these. jumping = object->player->jumping; secondjump = object->player->secondjump; P_ResetPlayer(object->player); @@ -768,8 +768,6 @@ static boolean PIT_CheckThing(mobj_t *thing) } } - if (tmthing->type == MT_SHELL && tmthing->threshold > TICRATE) - return true; // damage / explode if (tmthing->flags & MF_ENEMY) // An actual ENEMY! (Like the deton, for example) P_DamageMobj(thing, tmthing, tmthing, 1, 0); @@ -810,7 +808,7 @@ static boolean PIT_CheckThing(mobj_t *thing) tmthing->y = thing->y; P_SetThingPosition(tmthing); } - else + else if (!(tmthing->type == MT_SHELL && thing->player)) // player collision handled in touchspecial P_DamageMobj(thing, tmthing, tmthing->target, 1, 0); // don't traverse any more @@ -969,10 +967,10 @@ static boolean PIT_CheckThing(mobj_t *thing) { if (G_RingSlingerGametype() && (!G_GametypeHasTeams() || tmthing->player->ctfteam != thing->player->ctfteam)) { - if ((tmthing->player->powers[pw_invulnerability] || tmthing->player->powers[pw_super]) + if ((tmthing->player->powers[pw_invulnerability] || tmthing->player->powers[pw_super] || (((tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) && (tmthing->player->pflags & PF_SHIELDABILITY))) && !thing->player->powers[pw_super]) P_DamageMobj(thing, tmthing, tmthing, 1, 0); - else if ((thing->player->powers[pw_invulnerability] || thing->player->powers[pw_super]) + else if ((thing->player->powers[pw_invulnerability] || thing->player->powers[pw_super] || (((thing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) && (thing->player->pflags & PF_SHIELDABILITY))) && !tmthing->player->powers[pw_super]) P_DamageMobj(tmthing, thing, thing, 1, 0); } @@ -1052,24 +1050,41 @@ static boolean PIT_CheckThing(mobj_t *thing) else if (thing->z - FixedMul(FRACUNIT, thing->scale) <= tmthing->z + tmthing->height && thing->z + thing->height + FixedMul(FRACUNIT, thing->scale) >= tmthing->z) { + // 0 = none, 1 = elemental pierce, 2 = bubble bounce + UINT8 elementalpierce = (((tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (tmthing->player->pflags & PF_SHIELDABILITY) + ? (((tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) ? 1 : 2) + : 0); if (thing->flags & MF_MONITOR && (tmthing->player->pflags & (PF_SPINNING|PF_GLIDING) || ((tmthing->player->pflags & PF_JUMPED) - && !(tmthing->player->charflags & SF_NOJUMPDAMAGE - && !(tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY))) + && (tmthing->player->pflags & PF_FORCEJUMPDAMAGE + || !(tmthing->player->charflags & SF_NOJUMPSPIN) + || (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY))) || (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2) || ((tmthing->player->charflags & SF_STOMPDAMAGE) - && (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0)))) + && (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0)) + || elementalpierce)) { + player_t *player = tmthing->player; SINT8 flipval = P_MobjFlip(thing); // Save this value in case monitor gets removed. fixed_t *momz = &tmthing->momz; // tmthing gets changed by P_DamageMobj, so we need a new pointer?! X_x;; + fixed_t *z = &tmthing->z; // aau. P_DamageMobj(thing, tmthing, tmthing, 1, 0); // break the monitor // Going down? Then bounce back up. if ((P_MobjWasRemoved(thing) // Monitor was removed || !thing->health) // or otherwise popped - && (flipval*(*momz) < 0)) // monitor is on the floor and you're going down, or on the ceiling and you're going up - *momz = -*momz; // Therefore, you should be thrust in the opposite direction, vertically. - return false; + && (flipval*(*momz) < 0) // monitor is on the floor and you're going down, or on the ceiling and you're going up + && (elementalpierce != 1)) // you're not piercing through the monitor... + { + if (elementalpierce == 2) + P_DoBubbleBounce(player); + else + *momz = -*momz; // Therefore, you should be thrust in the opposite direction, vertically. + } + if (!(elementalpierce == 1 && thing->flags & MF_GRENADEBOUNCE)) // prevent gold monitor clipthrough. + return false; + else + *z -= *momz; // to ensure proper collision. } } } @@ -1084,8 +1099,9 @@ static boolean PIT_CheckThing(mobj_t *thing) else if (thing->flags & MF_MONITOR && tmthing->player && (tmthing->player->pflags & (PF_SPINNING|PF_GLIDING) || ((tmthing->player->pflags & PF_JUMPED) - && !(tmthing->player->charflags & SF_NOJUMPDAMAGE - && !(tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY))) + && (tmthing->player->pflags & PF_FORCEJUMPDAMAGE + || !(tmthing->player->charflags & SF_NOJUMPSPIN) + || (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY))) || (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2) || ((tmthing->player->charflags & SF_STOMPDAMAGE) && (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0))) @@ -1124,7 +1140,10 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->player && tmthing->z + tmthing->height > topz && tmthing->z + tmthing->height < tmthing->ceilingz) { - tmfloorz = tmceilingz = INT32_MIN; // block while in air + if (thing->flags & MF_GRENADEBOUNCE && (thing->flags & MF_MONITOR || thing->flags2 & MF2_STANDONME)) // Gold monitor hack... + return false; + + tmfloorz = tmceilingz = topz; // block while in air #ifdef ESLOPE tmceilingslope = NULL; #endif @@ -1167,7 +1186,10 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->player && tmthing->z < topz && tmthing->z > tmthing->floorz) { - tmfloorz = tmceilingz = INT32_MAX; // block while in air + if (thing->flags & MF_GRENADEBOUNCE && (thing->flags & MF_MONITOR || thing->flags2 & MF2_STANDONME)) // Gold monitor hack... + return false; + + tmfloorz = tmceilingz = topz; // block while in air #ifdef ESLOPE tmfloorslope = NULL; #endif diff --git a/src/p_maputl.c b/src/p_maputl.c index fea8530a1..46b033386 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -572,51 +572,54 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) side_t *side = &sides[linedef->sidenum[0]]; fixed_t textop, texbottom, texheight; fixed_t texmid, delta1, delta2; + INT32 texnum = R_GetTextureNum(side->midtexture); // make sure the texture is actually valid - // Get the midtexture's height - texheight = textures[texturetranslation[side->midtexture]]->height << FRACBITS; + if (texnum) { + // Get the midtexture's height + texheight = textures[texnum]->height << FRACBITS; - // Set texbottom and textop to the Z coordinates of the texture's boundaries + // Set texbottom and textop to the Z coordinates of the texture's boundaries #if 0 // #ifdef POLYOBJECTS - // don't remove this code unless solid midtextures - // on non-solid polyobjects should NEVER happen in the future - if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) { - if (linedef->flags & ML_EFFECT5 && !side->repeatcnt) { // "infinite" repeat - texbottom = back->floorheight + side->rowoffset; - textop = back->ceilingheight + side->rowoffset; - } else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) { - texbottom = back->floorheight + side->rowoffset; - textop = texbottom + texheight*(side->repeatcnt+1); - } else { - textop = back->ceilingheight + side->rowoffset; - texbottom = textop - texheight*(side->repeatcnt+1); - } - } else + // don't remove this code unless solid midtextures + // on non-solid polyobjects should NEVER happen in the future + if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) { + if (linedef->flags & ML_EFFECT5 && !side->repeatcnt) { // "infinite" repeat + texbottom = back->floorheight + side->rowoffset; + textop = back->ceilingheight + side->rowoffset; + } else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) { + texbottom = back->floorheight + side->rowoffset; + textop = texbottom + texheight*(side->repeatcnt+1); + } else { + textop = back->ceilingheight + side->rowoffset; + texbottom = textop - texheight*(side->repeatcnt+1); + } + } else #endif - { - if (linedef->flags & ML_EFFECT5 && !side->repeatcnt) { // "infinite" repeat - texbottom = openbottom + side->rowoffset; - textop = opentop + side->rowoffset; - } else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) { - texbottom = openbottom + side->rowoffset; - textop = texbottom + texheight*(side->repeatcnt+1); - } else { - textop = opentop + side->rowoffset; - texbottom = textop - texheight*(side->repeatcnt+1); + { + if (linedef->flags & ML_EFFECT5 && !side->repeatcnt) { // "infinite" repeat + texbottom = openbottom + side->rowoffset; + textop = opentop + side->rowoffset; + } else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) { + texbottom = openbottom + side->rowoffset; + textop = texbottom + texheight*(side->repeatcnt+1); + } else { + textop = opentop + side->rowoffset; + texbottom = textop - texheight*(side->repeatcnt+1); + } } - } - texmid = texbottom+(textop-texbottom)/2; + texmid = texbottom+(textop-texbottom)/2; - delta1 = abs(mobj->z - texmid); - delta2 = abs(thingtop - texmid); + delta1 = abs(mobj->z - texmid); + delta2 = abs(thingtop - texmid); - if (delta1 > delta2) { // Below - if (opentop > texbottom) - opentop = texbottom; - } else { // Above - if (openbottom < textop) - openbottom = textop; + if (delta1 > delta2) { // Below + if (opentop > texbottom) + opentop = texbottom; + } else { // Above + if (openbottom < textop) + openbottom = textop; + } } } diff --git a/src/p_mobj.c b/src/p_mobj.c index 27897be2b..39682a7ef 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -86,9 +86,14 @@ void P_AddCachedAction(mobj_t *mobj, INT32 statenum) // FUNCINLINE static ATTRINLINE void P_SetupStateAnimation(mobj_t *mobj, state_t *st) { + INT32 animlength = (mobj->skin && mobj->sprite == SPR_PLAY) + ? (INT32)(((skin_t *)mobj->skin)->sprites[mobj->sprite2].numframes) - 1 + : st->var1; + if (!(st->frame & FF_ANIMATE)) return; - if (st->var1 == 0 || st->var2 == 0) + + if (animlength <= 0 || st->var2 == 0) { mobj->frame &= ~FF_ANIMATE; return; // Crash/stupidity prevention @@ -102,11 +107,11 @@ FUNCINLINE static ATTRINLINE void P_SetupStateAnimation(mobj_t *mobj, state_t *s if (!leveltime) return; mobj->anim_duration -= (leveltime + 2) % st->var2; // Duration synced to timer - mobj->frame += ((leveltime + 2) / st->var2) % (st->var1 + 1); // Frame synced to timer (duration taken into account) + mobj->frame += ((leveltime + 2) / st->var2) % (animlength + 1); // Frame synced to timer (duration taken into account) } else if (st->frame & FF_RANDOMANIM) { - mobj->frame += P_RandomKey(st->var1 + 1); // Random starting frame + mobj->frame += P_RandomKey(animlength + 1); // Random starting frame mobj->anim_duration -= P_RandomKey(st->var2); // Random duration for first frame } } @@ -119,13 +124,23 @@ FUNCINLINE static ATTRINLINE void P_CycleStateAnimation(mobj_t *mobj) // var2 determines delay between animation frames if (!(mobj->frame & FF_ANIMATE) || --mobj->anim_duration != 0) return; + mobj->anim_duration = (UINT16)mobj->state->var2; - // compare the current sprite frame to the one we started from - // if more than var1 away from it, swap back to the original - // else just advance by one - if (((++mobj->frame) & FF_FRAMEMASK) - (mobj->state->frame & FF_FRAMEMASK) > (UINT32)mobj->state->var1) - mobj->frame = (mobj->state->frame & FF_FRAMEMASK) | (mobj->frame & ~FF_FRAMEMASK); + if (mobj->sprite != SPR_PLAY) + { + // compare the current sprite frame to the one we started from + // if more than var1 away from it, swap back to the original + // else just advance by one + if (((++mobj->frame) & FF_FRAMEMASK) - (mobj->state->frame & FF_FRAMEMASK) > (UINT32)mobj->state->var1) + mobj->frame = (mobj->state->frame & FF_FRAMEMASK) | (mobj->frame & ~FF_FRAMEMASK); + + return; + } + + // sprite2 version of above + if (mobj->skin && (((++mobj->frame) & FF_FRAMEMASK) >= (UINT32)(((skin_t *)mobj->skin)->sprites[mobj->sprite2].numframes))) + mobj->frame &= ~FF_FRAMEMASK; } // @@ -170,6 +185,215 @@ static void P_CyclePlayerMobjState(mobj_t *mobj) } } +// +// P_GetMobjSprite2 +// + +UINT8 P_GetMobjSprite2(mobj_t *mobj, UINT8 spr2) +{ + player_t *player = mobj->player; + skin_t *skin = ((skin_t *)mobj->skin); + + if (!skin) + return 0; + + while ((skin->sprites[spr2].numframes <= 0) + && spr2 != SPR2_STND) + { + switch(spr2) + { + case SPR2_PEEL: + spr2 = SPR2_RUN; + break; + case SPR2_RUN: + spr2 = SPR2_WALK; + break; + case SPR2_DRWN: + spr2 = SPR2_DEAD; + break; + case SPR2_DASH: + spr2 = SPR2_SPIN; + break; + case SPR2_GASP: + spr2 = SPR2_SPNG; + break; + case SPR2_JUMP: + spr2 = ((player + ? player->charflags + : skin->flags) + & SF_NOJUMPSPIN) ? SPR2_SPNG : SPR2_SPIN; + break; + case SPR2_SPNG: // spring + spr2 = SPR2_FALL; + break; + case SPR2_FALL: + spr2 = SPR2_WALK; + break; + case SPR2_RIDE: + spr2 = SPR2_FALL; + break; + + case SPR2_FLY: + spr2 = SPR2_SPNG; + break; + case SPR2_SWIM: + spr2 = SPR2_FLY; + break; + case SPR2_TIRE: + spr2 = (player && player->charability == CA_SWIM) ? SPR2_SWIM : SPR2_FLY; + break; + + case SPR2_GLID: + spr2 = SPR2_FLY; + break; + case SPR2_CLMB: + spr2 = SPR2_SPIN; + break; + case SPR2_CLNG: + spr2 = SPR2_CLMB; + break; + + case SPR2_TWIN: + spr2 = SPR2_SPIN; + break; + + case SPR2_MLEE: + spr2 = SPR2_TWIN; + break; + + // Super sprites fallback to regular sprites + case SPR2_SWLK: + spr2 = SPR2_WALK; + break; + case SPR2_SRUN: + spr2 = SPR2_RUN; + break; + case SPR2_SPEE: + spr2 = SPR2_PEEL; + break; + case SPR2_SPAN: + spr2 = SPR2_PAIN; + break; + case SPR2_SSTN: + spr2 = SPR2_SPAN; + break; + case SPR2_SDTH: + spr2 = SPR2_DEAD; + break; + case SPR2_SDRN: + spr2 = SPR2_DRWN; + break; + case SPR2_SSPN: + spr2 = SPR2_SPIN; + break; + case SPR2_SGSP: + spr2 = SPR2_GASP; + break; + case SPR2_SJMP: + spr2 = ((player + ? player->charflags + : skin->flags) + & SF_NOJUMPSPIN) ? SPR2_SSPG : SPR2_SSPN; + break; + case SPR2_SSPG: + spr2 = SPR2_SPNG; + break; + case SPR2_SFAL: + spr2 = SPR2_FALL; + break; + case SPR2_SEDG: + spr2 = SPR2_EDGE; + break; + case SPR2_SRID: + spr2 = SPR2_RIDE; + break; + case SPR2_SFLT: + spr2 = SPR2_SWLK; + break; + + // NiGHTS sprites. + case SPR2_NTRN: + spr2 = SPR2_TRNS; + break; + case SPR2_NSTD: + spr2 = SPR2_SSTD; + break; + case SPR2_NFLT: + spr2 = (skin->flags & SF_SUPERANIMS) ? SPR2_SFLT : SPR2_FALL; // This is skin-exclusive so the default NiGHTS skin changing system plays nice. + break; + case SPR2_NPUL: + spr2 = SPR2_NFLT; + break; + case SPR2_NPAN: + spr2 = SPR2_NPUL; + break; + case SPR2_NATK: + spr2 = SPR2_SSPN; + break; + /*case SPR2_NGT0: + spr2 = SPR2_STND; + break;*/ + case SPR2_NGT1: + case SPR2_NGT7: + case SPR2_DRL0: + spr2 = SPR2_NGT0; + break; + case SPR2_NGT2: + case SPR2_DRL1: + spr2 = SPR2_NGT1; + break; + case SPR2_NGT3: + case SPR2_DRL2: + spr2 = SPR2_NGT2; + break; + case SPR2_NGT4: + case SPR2_DRL3: + spr2 = SPR2_NGT3; + break; + case SPR2_NGT5: + case SPR2_DRL4: + spr2 = SPR2_NGT4; + break; + case SPR2_NGT6: + case SPR2_DRL5: + spr2 = SPR2_NGT5; + break; + case SPR2_DRL6: + spr2 = SPR2_NGT6; + break; + case SPR2_NGT8: + case SPR2_DRL7: + spr2 = SPR2_NGT7; + break; + case SPR2_NGT9: + case SPR2_DRL8: + spr2 = SPR2_NGT8; + break; + case SPR2_NGTA: + case SPR2_DRL9: + spr2 = SPR2_NGT9; + break; + case SPR2_NGTB: + case SPR2_DRLA: + spr2 = SPR2_NGTA; + break; + case SPR2_NGTC: + case SPR2_DRLB: + spr2 = SPR2_NGTB; + break; + case SPR2_DRLC: + spr2 = SPR2_NGTC; + break; + + // Dunno? Just go to standing then. + default: + spr2 = SPR2_STND; + break; + } + } + return spr2; +} + // // P_SetPlayerMobjState // Returns true if the mobj is still present. @@ -340,7 +564,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) // Adjust the player's animation speed to match their velocity. if (!(disableSpeedAdjust || player->charflags & SF_NOSPEEDADJUST)) { - fixed_t speed;// = FixedDiv(player->speed, mobj->scale); + fixed_t speed;// = FixedDiv(player->speed, FixedMul(mobj->scale, player->mo->movefactor)); if (player->panim == PA_FALL) { speed = FixedDiv(abs(mobj->momz), mobj->scale); @@ -366,7 +590,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) } else { - speed = FixedDiv(player->speed, mobj->scale); + speed = FixedDiv(player->speed, FixedMul(mobj->scale, player->mo->movefactor)); if (player->panim == PA_ROLL || player->panim == PA_JUMP) { if (speed > 16<<FRACBITS) @@ -396,216 +620,18 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) } } - mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set - // Player animations if (st->sprite == SPR_PLAY) { skin_t *skin = ((skin_t *)mobj->skin); - boolean noalt = false; - UINT8 spr2 = st->frame & FF_FRAMEMASK; UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1; UINT8 numframes; - while (skin && ((numframes = skin->sprites[spr2].numframes) <= 0) - && spr2 != SPR2_STND) - { - switch(spr2) - { - case SPR2_PEEL: - spr2 = SPR2_RUN; - break; - case SPR2_RUN: - spr2 = SPR2_WALK; - break; - case SPR2_DRWN: - spr2 = SPR2_DEAD; - break; - case SPR2_DASH: - spr2 = SPR2_SPIN; - break; - case SPR2_GASP: - spr2 = SPR2_SPNG; - break; - case SPR2_JUMP: - spr2 = (player->charflags & SF_NOJUMPSPIN) ? SPR2_SPNG : SPR2_SPIN; - break; - case SPR2_SPNG: // spring - spr2 = SPR2_FALL; - break; - case SPR2_FALL: - spr2 = SPR2_WALK; - break; - case SPR2_RIDE: - spr2 = SPR2_FALL; - break; + UINT8 spr2 = P_GetMobjSprite2(mobj, st->frame & FF_FRAMEMASK); - case SPR2_FLY: - spr2 = SPR2_SPNG; - break; - case SPR2_SWIM: - spr2 = SPR2_FLY; - break; - case SPR2_TIRE: - spr2 = (player->charability == CA_FLY) ? SPR2_FLY : SPR2_SWIM; - break; - - case SPR2_GLID: - spr2 = SPR2_FLY; - break; - case SPR2_CLMB: - spr2 = SPR2_SPIN; - break; - case SPR2_CLNG: - spr2 = SPR2_CLMB; - break; - - case SPR2_TWIN: - spr2 = SPR2_SPIN; - break; - - case SPR2_MLEE: - spr2 = SPR2_TWIN; - break; - - // Super sprites fallback to regular sprites - case SPR2_SWLK: - spr2 = SPR2_WALK; - break; - case SPR2_SRUN: - spr2 = SPR2_RUN; - break; - case SPR2_SPEE: - spr2 = SPR2_PEEL; - break; - case SPR2_SPAN: - spr2 = SPR2_PAIN; - break; - case SPR2_SSTN: - spr2 = SPR2_SPAN; - break; - case SPR2_SDTH: - spr2 = SPR2_DEAD; - break; - case SPR2_SDRN: - spr2 = SPR2_DRWN; - break; - case SPR2_SSPN: - spr2 = SPR2_SPIN; - break; - case SPR2_SGSP: - spr2 = SPR2_GASP; - break; - case SPR2_SJMP: - spr2 = (player->charflags & SF_NOJUMPSPIN) ? SPR2_SSPG : SPR2_SSPN; - break; - case SPR2_SSPG: - spr2 = SPR2_SPNG; - break; - case SPR2_SFAL: - spr2 = SPR2_FALL; - break; - case SPR2_SEDG: - spr2 = SPR2_EDGE; - break; - case SPR2_SRID: - spr2 = SPR2_RIDE; - break; - case SPR2_SFLT: - spr2 = SPR2_SWLK; - break; - - // NiGHTS sprites. - case SPR2_NTRN: - spr2 = SPR2_TRNS; - break; - case SPR2_NSTD: - spr2 = SPR2_SSTD; - break; - case SPR2_NFLT: - spr2 = (skin->flags & SF_SUPERANIMS) ? SPR2_SFLT : SPR2_FALL; // This is skin-exclusive so the default NiGHTS skin changing system plays nice. - break; - case SPR2_NPUL: - spr2 = SPR2_NFLT; - break; - case SPR2_NPAN: - spr2 = SPR2_NPUL; - break; - case SPR2_NATK: - spr2 = SPR2_SSPN; - break; - /*case SPR2_NGT0: - spr2 = SPR2_STND; - break;*/ - case SPR2_NGT1: - case SPR2_NGT7: - case SPR2_DRL0: - spr2 = SPR2_NGT0; - break; - case SPR2_NGT2: - case SPR2_DRL1: - spr2 = SPR2_NGT1; - break; - case SPR2_NGT3: - case SPR2_DRL2: - spr2 = SPR2_NGT2; - break; - case SPR2_NGT4: - case SPR2_DRL3: - spr2 = SPR2_NGT3; - break; - case SPR2_NGT5: - case SPR2_DRL4: - spr2 = SPR2_NGT4; - break; - case SPR2_NGT6: - case SPR2_DRL5: - spr2 = SPR2_NGT5; - break; - case SPR2_DRL6: - spr2 = SPR2_NGT6; - break; - case SPR2_NGT8: - case SPR2_DRL7: - spr2 = SPR2_NGT7; - break; - case SPR2_NGT9: - case SPR2_DRL8: - spr2 = SPR2_NGT8; - break; - case SPR2_NGTA: - case SPR2_DRL9: - spr2 = SPR2_NGT9; - break; - case SPR2_NGTB: - case SPR2_DRLA: - spr2 = SPR2_NGTA; - break; - case SPR2_NGTC: - case SPR2_DRLB: - spr2 = SPR2_NGTB; - break; - case SPR2_DRLC: - spr2 = SPR2_NGTC; - break; - - - // Sprites for non-player objects? There's nothing we can do. - case SPR2_SIGN: - case SPR2_LIFE: - noalt = true; - break; - - // Dunno? Just go to standing then. - default: - spr2 = SPR2_STND; - break; - } - if (noalt) - break; - } - - if (!skin) + if (skin) + numframes = skin->sprites[spr2].numframes; + else { frame = 0; numframes = 0; @@ -628,7 +654,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) { if (st->frame & FF_SPR2ENDSTATE) // no frame advancement { - if (st->var1 == S_NULL) + if (st->var1 == mobj->state-states) frame--; else { @@ -651,9 +677,10 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) { mobj->sprite = st->sprite; mobj->frame = st->frame; - P_SetupStateAnimation(mobj, st); } + P_SetupStateAnimation(mobj, st); + // Modified handling. // Call action functions when the state is set @@ -723,10 +750,11 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state) if (st->sprite == SPR_PLAY) { skin_t *skin = ((skin_t *)mobj->skin); - UINT8 spr2 = st->frame & FF_FRAMEMASK; UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1; UINT8 numframes; + UINT8 spr2 = P_GetMobjSprite2(mobj, st->frame & FF_FRAMEMASK); + if (skin) numframes = skin->sprites[spr2].numframes; else @@ -750,8 +778,17 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state) if (frame >= numframes) { - if (st->frame & FF_SPR2ENDSTATE) - return P_SetPlayerMobjState(mobj, st->var1); // Differs from P_SetPlayerMobjState - allows object to be removed via S_NULL + if (st->frame & FF_SPR2ENDSTATE) // no frame advancement + { + if (st->var1 == mobj->state-states) + frame--; + else + { + if (mobj->frame & FF_FRAMEMASK) + mobj->frame--; + return P_SetMobjState(mobj, st->var1); + } + } else frame = 0; } @@ -764,9 +801,10 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state) { mobj->sprite = st->sprite; mobj->frame = st->frame; - P_SetupStateAnimation(mobj, st); } + P_SetupStateAnimation(mobj, st); + // Modified handling. // Call action functions when the state is set @@ -1046,14 +1084,12 @@ void P_EmeraldManager(void) else break; - if (leveltime < TICRATE) // Start of map - spawnpoints[j]->threshold = 60*TICRATE + P_RandomByte() * (TICRATE/5); - else - spawnpoints[j]->threshold = P_RandomByte() * (TICRATE/5); - + spawnpoints[j]->threshold = emeraldspawndelay + P_RandomByte() * (TICRATE/5); break; } } + + emeraldspawndelay = 0; } // @@ -1099,9 +1135,6 @@ void P_ExplodeMissile(mobj_t *mo) explodemo->momx -= (P_RandomByte() % 96) * FixedMul(FRACUNIT/8, explodemo->scale); explodemo->momy -= (P_RandomByte() % 96) * FixedMul(FRACUNIT/8, explodemo->scale); S_StartSound(explodemo, sfx_cybdth); - - // Hack: Release an animal. - P_DamageMobj(mo, NULL, NULL, 1, DMG_INSTAKILL); } mo->flags &= ~MF_MISSILE; @@ -1809,7 +1842,6 @@ void P_CheckGravity(mobj_t *mo, boolean affect) } #define STOPSPEED (FRACUNIT) -#define FRICTION (ORIG_FRICTION) // 0.90625 // // P_SceneryXYFriction @@ -1842,7 +1874,6 @@ static void P_SceneryXYFriction(mobj_t *mo, fixed_t oldx, fixed_t oldy) { // Stolen from P_SpawnFriction mo->friction = FRACUNIT - 0x100; - mo->movefactor = ((0x10092 - mo->friction)*(0x70))/0x158; } else mo->friction = ORIG_FRICTION; @@ -1867,7 +1898,7 @@ static void P_XYFriction(mobj_t *mo, fixed_t oldx, fixed_t oldy) // spinning friction if (player->pflags & PF_SPINNING && (player->rmomx || player->rmomy) && !(player->pflags & PF_STARTDASH)) { - const fixed_t ns = FixedDiv(549*FRICTION,500*FRACUNIT); + const fixed_t ns = FixedDiv(549*ORIG_FRICTION,500*FRACUNIT); mo->momx = FixedMul(mo->momx, ns); mo->momy = FixedMul(mo->momy, ns); } @@ -2145,8 +2176,39 @@ void P_XYMovement(mobj_t *mo) } else if (player || mo->flags & (MF_SLIDEME|MF_PUSHABLE)) { // try to slide along it +#ifdef ESLOPE + // Wall transfer part 1. + pslope_t *transferslope = NULL; + fixed_t transfermomz = 0; + if (oldslope && (P_MobjFlip(mo)*(predictedz - mo->z) > 0)) // Only for moving up (relative to gravity), otherwise there's a failed launch when going down slopes and hitting walls + { + transferslope = ((mo->standingslope) ? mo->standingslope : oldslope); + if (((transferslope->zangle < ANGLE_180) ? transferslope->zangle : InvAngle(transferslope->zangle)) >= ANGLE_45) // Prevent some weird stuff going on on shallow slopes. + transfermomz = P_GetWallTransferMomZ(mo, transferslope); + } +#endif + P_SlideMove(mo); xmove = ymove = 0; + +#ifdef ESLOPE + // Wall transfer part 2. + if (transfermomz && transferslope) // Are we "transferring onto the wall" (really just a disguised vertical launch)? + { + angle_t relation; // Scale transfer momentum based on how head-on it is to the slope. + if (mo->momx || mo->momy) // "Guess" the angle of the wall you hit using new momentum + relation = transferslope->xydirection - R_PointToAngle2(0, 0, mo->momx, mo->momy); + else // Give it for free, I guess. + relation = ANGLE_90; + transfermomz = FixedMul(transfermomz, + abs(FINESINE((relation >> ANGLETOFINESHIFT) & FINEMASK))); + if (P_MobjFlip(mo)*(transfermomz - mo->momz) > 2*FRACUNIT) // Do the actual launch! + { + mo->momz = transfermomz; + mo->standingslope = NULL; + } + } +#endif } else if (mo->type == MT_SPINFIRE) { @@ -2376,14 +2438,16 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp topheight = P_GetFOFTopZ(mo, sector, rover, mo->x, mo->y, NULL); bottomheight = P_GetFOFBottomZ(mo, sector, rover, mo->x, mo->y, NULL); - if (mo->player && (P_CheckSolidLava(mo, rover) || P_CanRunOnWater(mo->player, rover))) // only the player should be affected + if (mo->player && (P_CheckSolidLava(mo, rover) || P_CanRunOnWater(mo->player, rover))) // only the player should stand on lava or run on water ; else if (motype != 0 && rover->flags & FF_SWIMMABLE) // "scenery" only continue; else if (rover->flags & FF_QUICKSAND) // quicksand ; - else if (!((rover->flags & FF_BLOCKPLAYER && mo->player) // solid to players? - || (rover->flags & FF_BLOCKOTHERS && !mo->player))) // solid to others? + else if (!( // if it's not either of the following... + (rover->flags & (FF_BLOCKPLAYER|FF_MARIO) && mo->player) // ...solid to players? (mario blocks are always solid from beneath to players) + || (rover->flags & FF_BLOCKOTHERS && !mo->player) // ...solid to others? + )) // ...don't take it into account. continue; if (rover->flags & FF_QUICKSAND) { @@ -2408,7 +2472,9 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp delta1 = mo->z - (bottomheight + ((topheight - bottomheight)/2)); delta2 = thingtop - (bottomheight + ((topheight - bottomheight)/2)); + if (topheight > mo->floorz && abs(delta1) < abs(delta2) + && (rover->flags & FF_SOLID) // Non-FF_SOLID Mario blocks are only solid from bottom && !(rover->flags & FF_REVERSEPLATFORM) && ((P_MobjFlip(mo)*mo->momz >= 0) || (!(rover->flags & FF_PLATFORM)))) // In reverse gravity, only clip for FOFs that are intangible from their bottom (the "top" you're falling through) if you're coming from above ("below" in your frame of reference) { @@ -2416,7 +2482,7 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp } if (bottomheight < mo->ceilingz && abs(delta1) >= abs(delta2) && !(rover->flags & FF_PLATFORM) - && ((P_MobjFlip(mo)*mo->momz >= 0) || (!(rover->flags & FF_REVERSEPLATFORM)))) // In normal gravity, only clip for FOFs that are intangible from the top if you're coming from below + && ((P_MobjFlip(mo)*mo->momz >= 0) || ((rover->flags & FF_SOLID) && !(rover->flags & FF_REVERSEPLATFORM)))) // In normal gravity, only clip for FOFs that are intangible from the top if you're coming from below { mo->ceilingz = bottomheight; } @@ -2600,6 +2666,23 @@ static boolean P_ZMovement(mobj_t *mo) mo->flags |= MF_NOGRAVITY; } break; + case MT_SPINFIRE: + if (P_CheckDeathPitCollide(mo)) + { + P_RemoveMobj(mo); + return false; + } + if (mo->momz + && !(mo->flags & MF_NOGRAVITY) + && ((!(mo->eflags & MFE_VERTICALFLIP) && mo->z <= mo->floorz) + || ((mo->eflags & MFE_VERTICALFLIP) && mo->z+mo->height >= mo->ceilingz))) + { + mo->flags |= MF_NOGRAVITY; + mo->momx = 8; // this is a hack which is used to ensure it still behaves as a missile and can damage others + mo->momy = mo->momz = 0; + mo->z = ((mo->eflags & MFE_VERTICALFLIP) ? mo->ceilingz-mo->height : mo->floorz); + } + break; case MT_GOOP: if (P_CheckDeathPitCollide(mo)) { @@ -2884,7 +2967,6 @@ static boolean P_ZMovement(mobj_t *mo) // Stolen from P_SpawnFriction mo->friction = FRACUNIT - 0x100; - mo->movefactor = ((0x10092 - mo->friction)*(0x70))/0x158; } else if (mo->type == MT_FALLINGROCK) { @@ -3085,6 +3167,8 @@ static void P_PlayerZMovement(mobj_t *mo) if (P_MobjFlip(mo)*mo->momz < 0) // falling { + boolean clipmomz = !(P_CheckDeathPitCollide(mo)); + mo->pmomz = 0; // We're on a new floor, don't keep doing platform movement. // Squat down. Decrease viewheight for a moment after hitting the ground (hard), @@ -3214,23 +3298,56 @@ static void P_PlayerZMovement(mobj_t *mo) mo->player->pflags &= ~PF_SPINNING; if (!(mo->player->pflags & PF_GLIDING)) - mo->player->pflags &= ~PF_JUMPED; + mo->player->pflags &= ~(PF_JUMPED|PF_FORCEJUMPDAMAGE); + mo->player->pflags &= ~(PF_THOKKED|PF_CANCARRY/*|PF_GLIDING*/); mo->player->jumping = 0; mo->player->secondjump = 0; mo->player->glidetime = 0; mo->player->climbing = 0; mo->player->powers[pw_tailsfly] = 0; + + if (mo->player->pflags & PF_SHIELDABILITY) + { + mo->player->pflags &= ~PF_SHIELDABILITY; + + if ((mo->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) // Elemental shield's stomp attack. + { + if (mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) // play a blunt sound + S_StartSound(mo, sfx_s3k4c); + else // create a fire pattern on the ground + { + S_StartSound(mo, sfx_s3k47); + P_ElementalFire(mo->player, true); + } + P_SetObjectMomZ(mo, + (mo->eflags & MFE_UNDERWATER) + ? 6*FRACUNIT/5 + : 5*FRACUNIT/2, + false); + P_SetPlayerMobjState(mo, S_PLAY_FALL); + mo->momx = mo->momy = 0; + clipmomz = false; + } + else if ((mo->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) // Bubble shield's bounce attack. + { + P_DoBubbleBounce(mo->player); + clipmomz = false; + } + } } } if (!(mo->player->pflags & PF_SPINNING)) mo->player->pflags &= ~PF_STARTDASH; - if (tmfloorthing && (tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR) - || tmfloorthing->flags2 & MF2_STANDONME || tmfloorthing->type == MT_PLAYER)) - mo->momz = tmfloorthing->momz; - else if (!tmfloorthing) - mo->momz = 0; + if (clipmomz) + { + if (tmfloorthing && (tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR) + || tmfloorthing->flags2 & MF2_STANDONME || tmfloorthing->type == MT_PLAYER)) + mo->momz = tmfloorthing->momz; + else if (!tmfloorthing) + mo->momz = 0; + } } else if (tmfloorthing && (tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR) || tmfloorthing->flags2 & MF2_STANDONME || tmfloorthing->type == MT_PLAYER)) @@ -3304,8 +3421,13 @@ nightsdone: if (rover->flags & FF_MARIO && !(mo->eflags & MFE_VERTICALFLIP) // if you were flipped, your head isn't actually hitting your ceilingz is it? && *rover->bottomheight == mo->ceilingz) // The player's head hit the bottom! + { // DO THE MARIO! - EV_MarioBlock(rover->master->frontsector, node->m_sector, *rover->topheight, mo); + if (rover->flags & FF_SHATTERBOTTOM) // Brick block! + EV_CrumbleChain(node->m_sector, rover); + else // Question block! + EV_MarioBlock(rover, node->m_sector, mo); + } } } // Ugly ugly billions of braces! Argh! } @@ -3394,17 +3516,14 @@ static boolean P_SceneryZMovement(mobj_t *mo) if ((!(mo->eflags & MFE_VERTICALFLIP) && mo->z <= mo->floorz) || (mo->eflags & MFE_VERTICALFLIP && mo->z+mo->height >= mo->ceilingz)) { - // DO NOT use random numbers here. - // SonicCD mode is console togglable and - // affects demos. - UINT8 rltime = (leveltime & 4); - - if (!rltime) - P_SpawnMobj(mo->x, mo->y, mo->floorz, MT_GFZFLOWER3); - else if (rltime == 2) - P_SpawnMobj(mo->x, mo->y, mo->floorz, MT_GFZFLOWER2); - else - P_SpawnMobj(mo->x, mo->y, mo->floorz, MT_GFZFLOWER1); + mobjtype_t flowertype = ((P_RandomChance(FRACUNIT/2)) ? MT_GFZFLOWER1 : MT_GFZFLOWER3); + mobj_t *flower = P_SpawnMobjFromMobj(mo, 0, 0, 0, flowertype); + if (flower) + { + P_SetScale(flower, mo->scale/16); + flower->destscale = mo->scale; + flower->scalespeed = mo->scale/8; + } P_RemoveMobj(mo); return false; @@ -3502,6 +3621,7 @@ void P_MobjCheckWater(mobj_t *mobj) ffloor_t *rover; player_t *p = mobj->player; // Will just be null if not a player. fixed_t height = (p ? P_GetPlayerHeight(p) : mobj->height); // for players, calculation height does not necessarily match actual height for gameplay reasons (spin, etc) + boolean wasgroundpounding = (p && (mobj->eflags & MFE_GOOWATER) && ((p->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (p->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (p->pflags & PF_SHIELDABILITY)); // Default if no water exists. mobj->watertop = mobj->waterbottom = mobj->z - 1000*FRACUNIT; @@ -3572,15 +3692,24 @@ void P_MobjCheckWater(mobj_t *mobj) { if (!((p->powers[pw_super]) || (p->powers[pw_invulnerability]))) { - if ((p->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT) - { // Water removes attract shield. + boolean electric = !!(p->powers[pw_shield] & SH_PROTECTELECTRIC); +#define SH_OP (SH_PROTECTFIRE|SH_PROTECTWATER|SH_PROTECTELECTRIC) + if ((p->powers[pw_shield] & SH_OP) == SH_OP) // No. + P_KillMobj(mobj, NULL, NULL, DMG_INSTAKILL); +#undef SH_OP + else if (electric || ((p->powers[pw_shield] & SH_PROTECTFIRE) && !(p->powers[pw_shield] & SH_PROTECTWATER))) + { // Water removes electric and non-water fire shields... + P_FlashPal(p, + electric + ? PAL_WHITE + : PAL_NUKE, + 1); p->powers[pw_shield] = p->powers[pw_shield] & SH_STACK; - P_FlashPal(p, PAL_WHITE, 1); } } // Drown timer setting - if ((p->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL // Has elemental + if ((p->powers[pw_shield] & SH_PROTECTWATER) // Has water protection || (p->exiting) // Or exiting || (maptol & TOL_NIGHTS) // Or in NiGHTS mode || (mariomode)) // Or in Mario mode... @@ -3593,6 +3722,12 @@ void P_MobjCheckWater(mobj_t *mobj) // Then we'll set it! p->powers[pw_underwater] = underwatertics + 1; } + + if (wasgroundpounding) + { + p->pflags &= ~PF_SHIELDABILITY; + mobj->momz >>= 1; + } } // The rest of this code only executes on a water state change. @@ -3610,7 +3745,7 @@ void P_MobjCheckWater(mobj_t *mobj) || ((mobj->eflags & MFE_VERTICALFLIP) && mobj->ceilingz-mobj->waterbottom <= height>>1)) return; - if ((mobj->eflags & MFE_GOOWATER || wasingoo)) { // Decide what happens to your momentum when you enter/leave goopy water. + if (!wasgroundpounding && (mobj->eflags & MFE_GOOWATER || wasingoo)) { // Decide what happens to your momentum when you enter/leave goopy water. if (P_MobjFlip(mobj)*mobj->momz < 0) // You are entering the goo? mobj->momz = FixedMul(mobj->momz, FixedDiv(2*FRACUNIT, 5*FRACUNIT)); // kill momentum significantly, to make the goo feel thick. } @@ -4156,17 +4291,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj) } animonly: - // cycle through states, - // calling action functions at transitions - if (mobj->tics != -1) - { - mobj->tics--; - - // you can cycle through multiple states in a tic - if (!mobj->tics) - if (!P_SetPlayerMobjState(mobj, mobj->state->nextstate)) - return; // freed itself - } + P_CyclePlayerMobjState(mobj); } static void CalculatePrecipFloor(precipmobj_t *mobj) @@ -4337,15 +4462,15 @@ boolean P_BossTargetPlayer(mobj_t *actor, boolean closest) player = &players[actor->lastlook]; - if (player->health <= 0) - continue; // dead - if (player->pflags & PF_INVIS || player->bot || player->spectator) continue; // ignore notarget if (!player->mo || P_MobjWasRemoved(player->mo)) continue; + if (player->mo->health <= 0) + continue; //dead + if (!P_CheckSight(actor, player->mo)) continue; // out of sight @@ -4375,15 +4500,15 @@ boolean P_SupermanLook4Players(mobj_t *actor) { if (playeringame[c]) { - if (players[c].health <= 0) - continue; // dead - if (players[c].pflags & PF_INVIS) continue; // ignore notarget if (!players[c].mo || players[c].bot) continue; + if (players[c].mo->health <= 0) + continue; // dead + playersinthegame[stop] = &players[c]; stop++; } @@ -4463,7 +4588,15 @@ static void P_Boss1Thinker(mobj_t *mobj) return; } - if (mobj->state != &states[mobj->info->spawnstate] && mobj->health > 0 && mobj->flags & MF_FLOAT && !(mobj->flags2 & MF2_SKULLFLY)) + if (mobj->flags2 & MF2_SKULLFLY) + { + fixed_t dist = (mobj->eflags & MFE_VERTICALFLIP) + ? ((mobj->ceilingz-(2*mobj->height)) - (mobj->z+mobj->height)) + : (mobj->z - (mobj->floorz+(2*mobj->height))); + if (dist > 0 && P_MobjFlip(mobj)*mobj->momz > 0) + mobj->momz = FixedMul(mobj->momz, FRACUNIT - (dist>>12)); + } + else if (mobj->state != &states[mobj->info->spawnstate] && mobj->health > 0 && mobj->flags & MF_FLOAT) mobj->momz = FixedMul(mobj->momz,7*FRACUNIT/8); if (mobj->state == &states[mobj->info->meleestate] @@ -4839,7 +4972,7 @@ static void P_Boss4MoveSpikeballs(mobj_t *mobj, angle_t angle, fixed_t fz) { INT32 s; mobj_t *base = mobj, *seg; - fixed_t dist, bz = (mobj->spawnpoint->z+16)<<FRACBITS; + fixed_t dist, bz = mobj->watertop+(16<<FRACBITS); while ((base = base->tracer)) { for (seg = base, dist = 172*FRACUNIT, s = 9; seg; seg = seg->hnext, dist += 124*FRACUNIT, --s) @@ -4853,7 +4986,7 @@ static void P_Boss4PinchSpikeballs(mobj_t *mobj, angle_t angle, fixed_t fz) { INT32 s; mobj_t *base = mobj, *seg; - fixed_t dist, bz = (mobj->spawnpoint->z+16)<<FRACBITS; + fixed_t dist, bz = mobj->watertop+(16<<FRACBITS); while ((base = base->tracer)) { for (seg = base, dist = 112*FRACUNIT, s = 9; seg; seg = seg->hnext, dist += 132*FRACUNIT, --s) @@ -4969,7 +5102,7 @@ static void P_Boss4Thinker(mobj_t *mobj) INT32 i, arm; mobj_t *seg, *base = mobj; // First frame init, spawn all the things. - mobj->spawnpoint->z = mobj->z>>FRACBITS; + mobj->watertop = mobj->z; z = mobj->z + mobj->height/2 - mobjinfo[MT_EGGMOBILE4_MACE].height/2; for (arm = 0; arm <3 ; arm++) { @@ -5025,7 +5158,7 @@ static void P_Boss4Thinker(mobj_t *mobj) case 3: { fixed_t z; - if (mobj->z < (mobj->spawnpoint->z+512)<<FRACBITS) + if (mobj->z < mobj->watertop+(512<<FRACBITS)) mobj->momz = 8*FRACUNIT; else { @@ -5034,7 +5167,7 @@ static void P_Boss4Thinker(mobj_t *mobj) } mobj->movecount += 400<<(FRACBITS>>1); mobj->movecount %= 360*FRACUNIT; - z = mobj->z - (mobj->spawnpoint->z<<FRACBITS) - mobjinfo[MT_EGGMOBILE4_MACE].height - mobj->height/2; + z = mobj->z - mobj->watertop - mobjinfo[MT_EGGMOBILE4_MACE].height - mobj->height/2; if (z < 0) // We haven't risen high enough to pull the spikeballs along yet P_Boss4MoveSpikeballs(mobj, FixedAngle(mobj->movecount), 0); // So don't pull the spikeballs along yet. else @@ -5044,13 +5177,13 @@ static void P_Boss4Thinker(mobj_t *mobj) // Pinch phase! case 4: { - if (mobj->z < (mobj->spawnpoint->z+512+128*(mobj->info->damage-mobj->health))<<FRACBITS) + if (mobj->z < (mobj->watertop + ((512+128*(mobj->info->damage-mobj->health))<<FRACBITS))) mobj->momz = 8*FRACUNIT; else mobj->momz = 0; mobj->movecount += (800+800*(mobj->info->damage-mobj->health))<<(FRACBITS>>1); mobj->movecount %= 360*FRACUNIT; - P_Boss4PinchSpikeballs(mobj, FixedAngle(mobj->movecount), mobj->z - (mobj->spawnpoint->z<<FRACBITS) - mobjinfo[MT_EGGMOBILE4_MACE].height - mobj->height/2); + P_Boss4PinchSpikeballs(mobj, FixedAngle(mobj->movecount), mobj->z - mobj->watertop - mobjinfo[MT_EGGMOBILE4_MACE].height - mobj->height/2); if (!mobj->target || !mobj->target->health) P_SupermanLook4Players(mobj); @@ -6292,7 +6425,7 @@ static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield) // TODO: Make an MT_SHIELDORB which changes color/states to always match the appropriate shield, // instead of having completely seperate mobjtypes. - if (shield != SH_FORCE) + if (!(shield & SH_FORCE)) { // Regular shields check for themselves only if ((shieldtype_t)(thing->target->player->powers[pw_shield] & SH_NOSTACK) != shield) { @@ -6306,9 +6439,9 @@ static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield) return false; } - if (shield == SH_FORCE && thing->movecount != (thing->target->player->powers[pw_shield] & 0xFF)) + if (shield & SH_FORCE && thing->movecount != (thing->target->player->powers[pw_shield] & SH_FORCEHP)) { - thing->movecount = (thing->target->player->powers[pw_shield] & 0xFF); + thing->movecount = (thing->target->player->powers[pw_shield] & SH_FORCEHP); if (thing->movecount < 1) { if (thing->info->painstate) @@ -6329,13 +6462,14 @@ static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield) thing->eflags = (thing->eflags & ~MFE_VERTICALFLIP)|(thing->target->eflags & MFE_VERTICALFLIP); P_SetScale(thing, FixedMul(thing->target->scale, thing->target->player->shieldscale)); + thing->destscale = thing->scale; P_UnsetThingPosition(thing); thing->x = thing->target->x; thing->y = thing->target->y; if (thing->eflags & MFE_VERTICALFLIP) - thing->z = thing->target->z + thing->target->height - thing->height + FixedDiv(P_GetPlayerHeight(thing->target->player) - thing->target->height, 3*FRACUNIT) - FixedMul(2*FRACUNIT, thing->target->scale); + thing->z = thing->target->z + (thing->target->height - thing->height + FixedDiv(P_GetPlayerHeight(thing->target->player) - thing->target->height, 3*FRACUNIT)) - FixedMul(2*FRACUNIT, thing->target->scale); else - thing->z = thing->target->z - FixedDiv(P_GetPlayerHeight(thing->target->player) - thing->target->height, 3*FRACUNIT) + FixedMul(2*FRACUNIT, thing->target->scale); + thing->z = thing->target->z - (FixedDiv(P_GetPlayerHeight(thing->target->player) - thing->target->height, 3*FRACUNIT)) + FixedMul(2*FRACUNIT, thing->target->scale); P_SetThingPosition(thing); P_CheckPosition(thing, thing->x, thing->y); @@ -6358,7 +6492,7 @@ void P_RunShields(void) // run shields for (i = 0; i < numshields; i++) { - P_ShieldLook(shields[i], shields[i]->info->speed); + P_ShieldLook(shields[i], shields[i]->threshold); P_SetTarget(&shields[i], NULL); } numshields = 0; @@ -6366,7 +6500,7 @@ void P_RunShields(void) static boolean P_AddShield(mobj_t *thing) { - shieldtype_t shield = thing->info->speed; + shieldtype_t shield = thing->threshold; if (!thing->target || thing->target->health <= 0 || !thing->target->player || (thing->target->player->powers[pw_shield] & SH_NOSTACK) == SH_NONE || thing->target->player->powers[pw_super] @@ -6376,7 +6510,7 @@ static boolean P_AddShield(mobj_t *thing) return false; } - if (shield != SH_FORCE) + if (!(shield & SH_FORCE)) { // Regular shields check for themselves only if ((shieldtype_t)(thing->target->player->powers[pw_shield] & SH_NOSTACK) != shield) { @@ -6414,6 +6548,13 @@ void P_RunOverlays(void) if (!mo->target) continue; + + if (P_MobjWasRemoved(mo->target)) + { + P_RemoveMobj(mo); + continue; + } + if (!splitscreen /*&& rendermode != render_soft*/) { angle_t viewingangle; @@ -6593,7 +6734,7 @@ void P_MobjThinker(mobj_t *mobj) fixed_t oldheight = mobj->height; UINT8 correctionType = 0; // Don't correct Z position, just gain height - if (mobj->z > mobj->floorz && mobj->z + mobj->height < mobj->ceilingz + if ((mobj->flags & MF_NOCLIPHEIGHT || (mobj->z > mobj->floorz && mobj->z + mobj->height < mobj->ceilingz)) && mobj->type != MT_EGGMOBILE_FIRE) correctionType = 1; // Correct Z position by centering else if (mobj->eflags & MFE_VERTICALFLIP) @@ -6624,7 +6765,7 @@ void P_MobjThinker(mobj_t *mobj) } } - if (mobj->type == MT_GHOST && mobj->fuse > 0 // Not guaranteed to be MF_SCENERY or not MF_SCENERY! + if ((mobj->type == MT_GHOST || mobj->type == MT_THOK) && mobj->fuse > 0 // Not guaranteed to be MF_SCENERY or not MF_SCENERY! && (signed)(mobj->frame >> FF_TRANSSHIFT) < (NUMTRANSMAPS-1) - mobj->fuse / 2) // fade out when nearing the end of fuse... mobj->frame = (mobj->frame & ~FF_TRANSMASK) | (((NUMTRANSMAPS-1) - mobj->fuse / 2) << FF_TRANSSHIFT); @@ -6638,6 +6779,11 @@ void P_MobjThinker(mobj_t *mobj) if (P_MobjWasRemoved(mobj)) return; #endif + + if (mobj->flags2 & MF2_SHIELD) + if (!P_AddShield(mobj)) + return; + switch (mobj->type) { case MT_HOOP: @@ -6694,15 +6840,121 @@ void P_MobjThinker(mobj_t *mobj) else P_AddOverlay(mobj); break; - case MT_BLACKORB: - case MT_WHITEORB: - case MT_GREENORB: - case MT_YELLOWORB: - case MT_BLUEORB: - case MT_PITYORB: - if (!P_AddShield(mobj)) + case MT_PITY_ORB: + case MT_WHIRLWIND_ORB: + case MT_ARMAGEDDON_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) return; break; + case MT_ATTRACT_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if (/*(mobj->target) -- the following is implicit by P_AddShield + && (mobj->target->player) + && */ (mobj->target->player->homing)) + { + P_SetMobjState(mobj, mobj->info->painstate); + mobj->tics++; + } + break; + case MT_ELEMENTAL_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if (mobj->tracer + /* && mobj->target -- the following is implicit by P_AddShield + && mobj->target->player + && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL */ + && mobj->target->player->pflags & PF_SHIELDABILITY + && ((statenum_t)(mobj->tracer->state-states) < mobj->info->raisestate + || (mobj->tracer->state->nextstate < mobj->info->raisestate && mobj->tracer->tics == 1))) + { + P_SetMobjState(mobj, mobj->info->painstate); + mobj->tics++; + P_SetMobjState(mobj->tracer, mobj->info->raisestate); + mobj->tracer->tics++; + } + break; + case MT_FORCE_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if (/* + && mobj->target -- the following is implicit by P_AddShield + && mobj->target->player + && (mobj->target->player->powers[pw_shield] & SH_FORCE) + && */ (mobj->target->player->pflags & PF_SHIELDABILITY)) + { + mobj_t *whoosh = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_GHOST); // done here so the offset is correct + P_SetMobjState(whoosh, mobj->info->raisestate); + whoosh->destscale = whoosh->scale<<1; + whoosh->scalespeed = FixedMul(whoosh->scalespeed, whoosh->scale); + whoosh->height = 38*whoosh->scale; + whoosh->fuse = 10; + whoosh->flags |= MF_NOCLIPHEIGHT; + whoosh->momz = mobj->target->momz; // Stay reasonably centered for a few frames + mobj->target->player->pflags &= ~PF_SHIELDABILITY; // prevent eternal whoosh + } + case MT_FLAMEAURA_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + mobj->angle = mobj->target->angle; // implicitly okay because of P_AddShield + if (mobj->tracer + /* && mobj->target -- the following is implicit by P_AddShield + && mobj->target->player + && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_FLAMEAURA */ + && mobj->target->player->pflags & PF_SHIELDABILITY + && ((statenum_t)(mobj->tracer->state-states) < mobj->info->raisestate + || (mobj->tracer->state->nextstate < mobj->info->raisestate && mobj->tracer->tics == 1))) + { + P_SetMobjState(mobj, mobj->info->painstate); + mobj->tics++; + P_SetMobjState(mobj->tracer, mobj->info->raisestate); + mobj->tracer->tics++; + } + break; + case MT_BUBBLEWRAP_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if (mobj->tracer + /* && mobj->target -- the following is implicit by P_AddShield + && mobj->target->player + && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP */ + ) + { + if (mobj->target->player->pflags & PF_SHIELDABILITY + && ((statenum_t)(mobj->state-states) < mobj->info->painstate + || (mobj->state->nextstate < mobj->info->painstate && mobj->tics == 1))) + { + P_SetMobjState(mobj, mobj->info->painstate); + mobj->tics++; + P_SetMobjState(mobj->tracer, mobj->info->raisestate); + mobj->tracer->tics++; + } + else if (mobj->target->eflags & MFE_JUSTHITFLOOR + && (statenum_t)(mobj->state-states) == mobj->info->painstate) + { + P_SetMobjState(mobj, mobj->info->painstate+1); + mobj->tics++; + P_SetMobjState(mobj->tracer, mobj->info->raisestate+1); + mobj->tracer->tics++; + } + } + break; + case MT_THUNDERCOIN_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if (mobj->tracer + /* && mobj->target -- the following is implicit by P_AddShield + && mobj->target->player + && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_THUNDERCOIN */ + && (mobj->target->player->pflags & PF_SHIELDABILITY)) + { + P_SetMobjState(mobj, mobj->info->painstate); + mobj->tics++; + P_SetMobjState(mobj->tracer, mobj->info->raisestate); + mobj->tracer->tics++; + mobj->target->player->pflags &= ~PF_SHIELDABILITY; // prevent eternal spark + } + break; case MT_WATERDROP: P_SceneryCheckWater(mobj); if ((mobj->z <= mobj->floorz || mobj->z <= mobj->watertop) @@ -6836,7 +7088,8 @@ void P_MobjThinker(mobj_t *mobj) } break; case MT_SEED: - mobj->momz = mobj->info->speed; + if (P_MobjFlip(mobj)*mobj->momz < mobj->info->speed) + mobj->momz = P_MobjFlip(mobj)*mobj->info->speed; break; case MT_ROCKCRUMBLE1: case MT_ROCKCRUMBLE2: @@ -6985,14 +7238,14 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->fuse > 0 && mobj->fuse < 2*TICRATE-(TICRATE/7) && (mobj->fuse & 3)) { - INT32 i,j; + INT32 i; fixed_t x,y,z; fixed_t ns; mobj_t *mo2; + mobj_t *flicky; - i = P_RandomByte(); z = mobj->subsector->sector->floorheight + ((P_RandomByte()&63)*FRACUNIT); - for (j = 0; j < 2; j++) + for (i = 0; i < 2; i++) { const angle_t fa = (P_RandomByte()*FINEANGLES/16) & FINEMASK; ns = 64 * FRACUNIT; @@ -7000,25 +7253,22 @@ void P_MobjThinker(mobj_t *mobj) y = mobj->y + FixedMul(FINECOSINE(fa),ns); mo2 = P_SpawnMobj(x, y, z, MT_EXPLODE); + P_SetMobjStateNF(mo2, S_XPLD_EGGTRAP); // so the flickies don't lose their target if they spawn ns = 4 * FRACUNIT; mo2->momx = FixedMul(FINESINE(fa),ns); mo2->momy = FixedMul(FINECOSINE(fa),ns); + mo2->angle = fa << ANGLETOFINESHIFT; - i = P_RandomByte(); - - if (i % 5 == 0) - P_SpawnMobj(x, y, z, MT_CHICKEN); - else if (i % 4 == 0) - P_SpawnMobj(x, y, z, MT_COW); - else if (i % 3 == 0) - { - P_SpawnMobj(x, y, z, MT_BIRD); + if (P_RandomChance(FRACUNIT/4)) // I filled a spreadsheet trying to get the equivalent chance to the original P_RandomByte hack! S_StartSound(mo2, mobj->info->deathsound); - } - else if ((i & 1) == 0) - P_SpawnMobj(x, y, z, MT_BUNNY); - else - P_SpawnMobj(x, y, z, MT_MOUSE); + + flicky = P_InternalFlickySpawn(mo2, 0, 8*FRACUNIT, false); + if (!flicky) + break; + + P_SetTarget(&flicky->target, mo2); + flicky->momx = mo2->momx; + flicky->momy = mo2->momy; } mobj->fuse--; @@ -7079,6 +7329,8 @@ void P_MobjThinker(mobj_t *mobj) } break; case MT_AQUABUZZ: + P_MobjCheckWater(mobj); // solely for MFE_UNDERWATER for A_FlickySpawn + // no break here on purpose case MT_BIGAIRMINE: { if (mobj->tracer && mobj->tracer->player && mobj->tracer->health > 0 @@ -7156,7 +7408,7 @@ void P_MobjThinker(mobj_t *mobj) P_SetTarget(&mobj->target, NULL); for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].mo - && players[i].mare == mobj->threshold && players[i].health > 1) + && players[i].mare == mobj->threshold && players[i].rings > 0) { fixed_t dist = P_AproxDistance(players[i].mo->x - mobj->x, players[i].mo->y - mobj->y); if (dist < shortest) @@ -7470,13 +7722,13 @@ void P_MobjThinker(mobj_t *mobj) P_NightsItemChase(mobj); break; case MT_SHELL: - if (mobj->threshold > TICRATE) + if (mobj->threshold && mobj->threshold != TICRATE) mobj->threshold--; - if (mobj->state != &states[S_SHELL]) + if (mobj->threshold >= TICRATE) { - mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); - P_InstaThrust(mobj, mobj->angle, FixedMul(mobj->info->speed, mobj->scale)); + mobj->angle += ((mobj->movedir == 1) ? ANGLE_22h : ANGLE_337h); + P_InstaThrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), (mobj->info->speed*mobj->scale)); } break; case MT_TURRET: @@ -7537,11 +7789,26 @@ void P_MobjThinker(mobj_t *mobj) mobj->tracer->y, mobj->tracer->floorz, SPLATDRAWMODE_SHADE); #endif break; + case MT_SPINDUST: // Spindash dust + mobj->momx = FixedMul(mobj->momx, (3*FRACUNIT)/4); // originally 50000 + mobj->momy = FixedMul(mobj->momy, (3*FRACUNIT)/4); // same + //mobj->momz = mobj->momz+P_MobjFlip(mobj)/3; // no meaningful change in value to be frank + if (mobj->state >= &states[S_SPINDUST_BUBBLE1] && mobj->state <= &states[S_SPINDUST_BUBBLE4]) // bubble dust! + { + P_MobjCheckWater(mobj); + if (mobj->watertop != mobj->subsector->sector->floorheight - 1000*FRACUNIT + && mobj->z+mobj->height >= mobj->watertop - 5*FRACUNIT) + mobj->flags2 |= MF2_DONTDRAW; + } + break; case MT_SPINFIRE: - if (mobj->eflags & MFE_VERTICALFLIP) - mobj->z = mobj->ceilingz - mobj->height; - else - mobj->z = mobj->floorz; + if (mobj->flags & MF_NOGRAVITY) + { + if (mobj->eflags & MFE_VERTICALFLIP) + mobj->z = mobj->ceilingz - mobj->height; + else + mobj->z = mobj->floorz; + } // THERE IS NO BREAK HERE ON PURPOSE default: // check mobj against possible water content, before movement code @@ -8033,7 +8300,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->friction = ORIG_FRICTION; - mobj->movefactor = ORIG_FRICTION_FACTOR; + mobj->movefactor = FRACUNIT; // All mobjs are created at 100% scale. mobj->scale = FRACUNIT; @@ -8082,6 +8349,10 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) if (mobj->type == MT_UNIDUS) mobj->z -= FixedMul(mobj->info->mass, mobj->scale); + + // defaults onground + if (mobj->z + mobj->height == mobj->ceilingz) + mobj->eflags |= MFE_ONGROUND; } else mobj->z = z; @@ -8170,13 +8441,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) // Special condition for the 2nd boss. mobj->watertop = mobj->info->speed; break; - case MT_BIRD: - case MT_BUNNY: - case MT_MOUSE: - case MT_CHICKEN: - case MT_COW: - case MT_REDBIRD: - mobj->fuse = P_RandomRange(300, 350); + case MT_FLICKY_08: + mobj->color = (P_RandomChance(FRACUNIT/2) ? SKINCOLOR_RED : SKINCOLOR_AQUA); break; case MT_REDRING: // Make MT_REDRING red by default mobj->color = skincolor_redring; @@ -8820,8 +9086,10 @@ void P_SpawnPlayer(INT32 playernum) // (usefulness: when body mobj is detached from player (who respawns), // the dead body mobj retains the skin through the 'spritedef' override). mobj->skin = &skins[p->skin]; + P_SetupStateAnimation(mobj, mobj->state); - mobj->health = p->health; + mobj->health = 1; + p->rings = 0; p->playerstate = PST_LIVE; p->bonustime = false; @@ -9543,6 +9811,85 @@ ML_NOCLIMB : Direction not controllable } break; } + case MT_PARTICLEGEN: + { + fixed_t radius, speed, bottomheight, topheight; + INT32 type, numdivisions, time, anglespeed; + angle_t angledivision; + size_t line; + const size_t mthingi = (size_t)(mthing - mapthings); + + for (line = 0; line < numlines; line++) + { + if (lines[line].special == 15 && lines[line].tag == mthing->angle) + break; + } + + if (line == numlines) + { + CONS_Debug(DBG_GAMELOGIC, "Particle generator (mapthing #%s) needs tagged to a #15 parameter line (trying to find tag %d).\n", sizeu1(mthingi), mthing->angle); + return; + } + + if (sides[lines[line].sidenum[0]].toptexture) + type = sides[lines[line].sidenum[0]].toptexture; // Set as object type in p_setup.c... + else + type = (INT32)MT_PARTICLE; + + speed = abs(sides[lines[line].sidenum[0]].textureoffset); + bottomheight = lines[line].frontsector->floorheight; + topheight = lines[line].frontsector->ceilingheight - mobjinfo[(mobjtype_t)type].height; + + numdivisions = (mthing->options >> ZSHIFT); + + if (numdivisions) + { + radius = R_PointToDist2(lines[line].v1->x, lines[line].v1->y, lines[line].v2->x, lines[line].v2->y); + anglespeed = (sides[lines[line].sidenum[0]].rowoffset >> FRACBITS) % 360; + angledivision = 360/numdivisions; + } + else + { + numdivisions = 1; // Simple trick to make A_ParticleSpawn simpler. + radius = 0; + anglespeed = 0; + angledivision = 0; + } + + if ((speed) && (topheight > bottomheight)) + time = (INT32)(FixedDiv((topheight - bottomheight), speed) >> FRACBITS); + else + time = 1; // There's no reasonable way to set it, so just show the object for one tic and move on. + + if (mthing->options & MTF_OBJECTFLIP) + { + mobj->z = topheight; + speed *= -1; + } + else + mobj->z = bottomheight; + + CONS_Debug(DBG_GAMELOGIC, "Particle Generator (mapthing #%s):\n" + "Radius is %d\n" + "Speed is %d\n" + "Anglespeed is %d\n" + "Numdivisions is %d\n" + "Angledivision is %d\n" + "Time is %d\n" + "Type is %d\n", + sizeu1(mthingi), radius, speed, anglespeed, numdivisions, angledivision, time, type); + + mobj->angle = 0; + mobj->movefactor = speed; + mobj->lastlook = numdivisions; + mobj->movedir = angledivision*ANG1; + mobj->movecount = anglespeed*ANG1; + mobj->health = time; + mobj->friction = radius; + mobj->threshold = type; + + break; + } case MT_ROCKSPAWNER: mobj->threshold = mthing->angle; mobj->movecount = mthing->extrainfo; @@ -10721,7 +11068,7 @@ mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle, UINT8 allowai { mobj_t *th; angle_t an; - fixed_t x, y, z, slope = 0; + fixed_t x, y, z, slope = 0, speed; // angle at which you fire, is player angle an = angle; @@ -10753,9 +11100,13 @@ mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle, UINT8 allowai P_SetTarget(&th->target, source); + speed = th->info->speed; + if (source->player && source->player->charability == CA_FLY) + speed = FixedMul(speed, 3*FRACUNIT/2); + th->angle = an; - th->momx = FixedMul(th->info->speed, FINECOSINE(an>>ANGLETOFINESHIFT)); - th->momy = FixedMul(th->info->speed, FINESINE(an>>ANGLETOFINESHIFT)); + th->momx = FixedMul(speed, FINECOSINE(an>>ANGLETOFINESHIFT)); + th->momy = FixedMul(speed, FINESINE(an>>ANGLETOFINESHIFT)); if (allowaim) { @@ -10763,7 +11114,7 @@ mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle, UINT8 allowai th->momy = FixedMul(th->momy,FINECOSINE(source->player->aiming>>ANGLETOFINESHIFT)); } - th->momz = FixedMul(th->info->speed, slope); + th->momz = FixedMul(speed, slope); //scaling done here so it doesn't clutter up the code above th->momx = FixedMul(th->momx, th->scale); @@ -10817,4 +11168,3 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo P_SetScale(newmobj, mobj->scale); return newmobj; } - diff --git a/src/p_mobj.h b/src/p_mobj.h index 69e0e11aa..f6ebd3cad 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -193,6 +193,7 @@ typedef enum MF2_BOSSDEAD = 1<<26, // Boss is dead! (Not necessarily fleeing, if a fleeing point doesn't exist.) MF2_AMBUSH = 1<<27, // Alternate behaviour typically set by MTF_AMBUSH MF2_LINKDRAW = 1<<28, // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position) + MF2_SHIELD = 1<<29, // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use) // free: to and including 1<<31 } mobjflag2_t; @@ -453,5 +454,6 @@ void P_EmeraldManager(void); extern mapthing_t *huntemeralds[MAXHUNTEMERALDS]; extern INT32 numhuntemeralds; extern boolean runemeraldmanager; +extern UINT16 emeraldspawndelay; extern INT32 numstarposts; #endif diff --git a/src/p_saveg.c b/src/p_saveg.c index b086b076e..6abb4d14c 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -128,7 +128,7 @@ static void P_NetArchivePlayers(void) WRITEANGLE(save_p, players[i].aiming); WRITEANGLE(save_p, players[i].awayviewaiming); WRITEINT32(save_p, players[i].awayviewtics); - WRITEINT32(save_p, players[i].health); + WRITEINT32(save_p, players[i].rings); WRITESINT8(save_p, players[i].pity); WRITEINT32(save_p, players[i].currentweapon); @@ -308,7 +308,7 @@ static void P_NetUnArchivePlayers(void) players[i].aiming = READANGLE(save_p); players[i].awayviewaiming = READANGLE(save_p); players[i].awayviewtics = READINT32(save_p); - players[i].health = READINT32(save_p); + players[i].rings = READINT32(save_p); players[i].pity = READSINT8(save_p); players[i].currentweapon = READINT32(save_p); @@ -470,6 +470,7 @@ static void P_NetUnArchivePlayers(void) #define SD_TAG 0x10 #define SD_FLOORANG 0x20 #define SD_CEILANG 0x40 +#define SD_TAGLIST 0x80 #define LD_FLAG 0x01 #define LD_SPECIAL 0x02 @@ -519,10 +520,9 @@ static void P_NetArchiveWorld(void) // // flats // - // P_AddLevelFlat should not add but just return the number - if (ss->floorpic != P_AddLevelFlat(ms->floorpic, levelflats)) + if (ss->floorpic != P_CheckLevelFlat(ms->floorpic)) diff |= SD_FLOORPIC; - if (ss->ceilingpic != P_AddLevelFlat(ms->ceilingpic, levelflats)) + if (ss->ceilingpic != P_CheckLevelFlat(ms->ceilingpic)) diff |= SD_CEILPIC; if (ss->lightlevel != SHORT(ms->lightlevel)) @@ -545,6 +545,8 @@ static void P_NetArchiveWorld(void) if (ss->tag != SHORT(ms->tag)) diff2 |= SD_TAG; + if (ss->nexttag != ss->spawn_nexttag || ss->firsttag != ss->spawn_firsttag) + diff2 |= SD_TAGLIST; // Check if any of the sector's FOFs differ from how they spawned if (ss->ffloors) @@ -592,16 +594,17 @@ static void P_NetArchiveWorld(void) WRITEFIXED(put, ss->ceiling_xoffs); if (diff2 & SD_CYOFFS) WRITEFIXED(put, ss->ceiling_yoffs); - if (diff2 & SD_TAG) - { + if (diff2 & SD_TAG) // save only the tag WRITEINT16(put, ss->tag); - WRITEINT32(put, ss->firsttag); - WRITEINT32(put, ss->nexttag); - } if (diff2 & SD_FLOORANG) WRITEANGLE(put, ss->floorpic_angle); if (diff2 & SD_CEILANG) WRITEANGLE(put, ss->ceilingpic_angle); + if (diff2 & SD_TAGLIST) // save both firsttag and nexttag + { // either of these could be changed even if tag isn't + WRITEINT32(put, ss->firsttag); + WRITEINT32(put, ss->nexttag); + } // Special case: save the stats of all modified ffloors along with their ffloor "number"s // we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed @@ -762,12 +765,12 @@ static void P_NetUnArchiveWorld(void) sectors[i].ceilingheight = READFIXED(get); if (diff & SD_FLOORPIC) { - sectors[i].floorpic = P_AddLevelFlat((char *)get, levelflats); + sectors[i].floorpic = P_AddLevelFlatRuntime((char *)get); get += 8; } if (diff & SD_CEILPIC) { - sectors[i].ceilingpic = P_AddLevelFlat((char *)get, levelflats); + sectors[i].ceilingpic = P_AddLevelFlatRuntime((char *)get); get += 8; } if (diff & SD_LIGHT) @@ -784,12 +787,11 @@ static void P_NetUnArchiveWorld(void) if (diff2 & SD_CYOFFS) sectors[i].ceiling_yoffs = READFIXED(get); if (diff2 & SD_TAG) + sectors[i].tag = READINT16(get); // DON'T use P_ChangeSectorTag + if (diff2 & SD_TAGLIST) { - INT16 tag; - tag = READINT16(get); sectors[i].firsttag = READINT32(get); sectors[i].nexttag = READINT32(get); - P_ChangeSectorTag(i, tag); } if (diff2 & SD_FLOORANG) sectors[i].floorpic_angle = READANGLE(get); @@ -972,6 +974,7 @@ typedef enum tc_noenemies, tc_eachtime, tc_disappear, + tc_planedisplace, #ifdef POLYOBJECTS tc_polyrotate, // haleyjd 03/26/06: polyobjects tc_polymove, @@ -1095,7 +1098,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff |= MD_TRACER; if (mobj->friction != ORIG_FRICTION) diff |= MD_FRICTION; - if (mobj->movefactor != ORIG_FRICTION_FACTOR) + if (mobj->movefactor != FRACUNIT) diff |= MD_MOVEFACTOR; if (mobj->fuse) diff |= MD_FUSE; @@ -1535,6 +1538,21 @@ static void SaveDisappearThinker(const thinker_t *th, const UINT8 type) WRITEINT32(save_p, ht->exists); } +// +// SavePlaneDisplaceThinker +// +// Saves a planedisplace_t thinker +// +static void SavePlaneDisplaceThinker(const thinker_t *th, const UINT8 type) +{ + const planedisplace_t *ht = (const void *)th; + WRITEUINT8(save_p, type); + WRITEINT32(save_p, ht->affectee); + WRITEINT32(save_p, ht->control); + WRITEFIXED(save_p, ht->last_height); + WRITEFIXED(save_p, ht->speed); + WRITEUINT8(save_p, ht->type); +} #ifdef POLYOBJECTS // @@ -1816,6 +1834,12 @@ static void P_NetArchiveThinkers(void) SaveDisappearThinker(th, tc_disappear); continue; } + + else if (th->function.acp1 == (actionf_p1)T_PlaneDisplace) + { + SavePlaneDisplaceThinker(th, tc_planedisplace); + continue; + } #ifdef POLYOBJECTS else if (th->function.acp1 == (actionf_p1)T_PolyObjRotate) { @@ -2081,7 +2105,7 @@ static void LoadMobjThinker(actionf_p1 thinker) if (diff & MD_MOVEFACTOR) mobj->movefactor = READFIXED(save_p); else - mobj->movefactor = ORIG_FRICTION_FACTOR; + mobj->movefactor = FRACUNIT; if (diff & MD_FUSE) mobj->fuse = READINT32(save_p); if (diff & MD_WATERTOP) @@ -2484,6 +2508,23 @@ static inline void LoadDisappearThinker(actionf_p1 thinker) P_AddThinker(&ht->thinker); } +// +// LoadPlaneDisplaceThinker +// +// Loads a planedisplace_t thinker +// +static inline void LoadPlaneDisplaceThinker(actionf_p1 thinker) +{ + planedisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + ht->affectee = READINT32(save_p); + ht->control = READINT32(save_p); + ht->last_height = READFIXED(save_p); + ht->speed = READFIXED(save_p); + ht->type = READUINT8(save_p); + P_AddThinker(&ht->thinker); +} + #ifdef POLYOBJECTS // @@ -2628,6 +2669,7 @@ static void P_NetUnArchiveThinkers(void) thinker_t *next; UINT8 tclass; UINT8 restoreNum = false; + UINT32 i; if (READUINT32(save_p) != ARCHIVEBLOCK_THINKERS) I_Error("Bad $$$.sav at archive block Thinkers"); @@ -2648,6 +2690,12 @@ static void P_NetUnArchiveThinkers(void) iquetail = iquehead = 0; P_InitThinkers(); + // clear sector thinker pointers so they don't point to non-existant thinkers for all of eternity + for (i = 0; i < numsectors; i++) + { + sectors[i].floordata = sectors[i].ceilingdata = sectors[i].lightingdata = NULL; + } + // read in saved thinkers for (;;) { @@ -2760,6 +2808,10 @@ static void P_NetUnArchiveThinkers(void) case tc_disappear: LoadDisappearThinker((actionf_p1)T_Disappear); break; + + case tc_planedisplace: + LoadPlaneDisplaceThinker((actionf_p1)T_PlaneDisplace); + break; #ifdef POLYOBJECTS case tc_polyrotate: LoadPolyrotatetThinker((actionf_p1)T_PolyObjRotate); @@ -3306,7 +3358,7 @@ void P_SaveNetGame(void) { thinker_t *th; mobj_t *mobj; - INT32 i = 0; + INT32 i = 1; // don't start from 0, it'd be confused with a blank pointer otherwise CV_SaveNetVars(&save_p); P_NetArchiveMisc(); diff --git a/src/p_setup.c b/src/p_setup.c index f1d3a68c8..6df103255 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -160,6 +160,33 @@ FUNCNORETURN static ATTRNORETURN void CorruptMapError(const char *msg) I_Error("Invalid or corrupt map.\nLook in log file or text console for technical details."); } +/** Sets a header's flickies to be equivalent to the original Freed Animals + * + * \param i The header to set flickies for + */ +void P_SetDemoFlickies(INT16 i) +{ + mapheaderinfo[i]->numFlickies = 5; + mapheaderinfo[i]->flickies = Z_Realloc(mapheaderinfo[i]->flickies, 5*sizeof(mobjtype_t), PU_STATIC, NULL); + mapheaderinfo[i]->flickies[0] = MT_FLICKY_02/*MT_BUNNY*/; + mapheaderinfo[i]->flickies[1] = MT_FLICKY_01/*MT_BIRD*/; + mapheaderinfo[i]->flickies[2] = MT_FLICKY_12/*MT_MOUSE*/; + mapheaderinfo[i]->flickies[3] = MT_FLICKY_11/*MT_COW*/; + mapheaderinfo[i]->flickies[4] = MT_FLICKY_03/*MT_CHICKEN*/; +} + +/** Clears a header's flickies + * + * \param i The header to clear flickies for + */ +void P_DeleteFlickies(INT16 i) +{ + if (mapheaderinfo[i]->flickies) + Z_Free(mapheaderinfo[i]->flickies); + mapheaderinfo[i]->flickies = NULL; + mapheaderinfo[i]->numFlickies = 0; +} + #define NUMLAPS_DEFAULT 4 /** Clears the data from a single map header. @@ -223,6 +250,12 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) mapheaderinfo[num]->levelflags = 0; DEH_WriteUndoline("MENUFLAGS", va("%d", mapheaderinfo[num]->menuflags), UNDO_NONE); mapheaderinfo[num]->menuflags = 0; + // Flickies. Nope, no delfile support here either +#if 1 // equivalent to "FlickyList = DEMO" + P_SetDemoFlickies(num); +#else // equivalent to "FlickyList = NONE" + P_DeleteFlickies(num); +#endif // TODO grades support for delfile (pfft yeah right) P_DeleteGrades(num); // an even further impossibility, delfile custom opts support @@ -241,6 +274,7 @@ void P_AllocMapHeader(INT16 i) if (!mapheaderinfo[i]) { mapheaderinfo[i] = Z_Malloc(sizeof(mapheader_t), PU_STATIC, NULL); + mapheaderinfo[i]->flickies = NULL; mapheaderinfo[i]->grades = NULL; } P_ClearSingleMapHeaderInfo(i + 1); @@ -574,6 +608,69 @@ INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat) return (INT32)i; } +// help function for Lua and $$$.sav reading +// same as P_AddLevelFlat, except this is not setup so we must realloc levelflats to fit in the new flat +// no longer a static func in lua_maplib.c because p_saveg.c also needs it +// +INT32 P_AddLevelFlatRuntime(const char *flatname) +{ + size_t i; + levelflat_t *levelflat = levelflats; + + // + // first scan through the already found flats + // + for (i = 0; i < numlevelflats; i++, levelflat++) + if (strnicmp(levelflat->name,flatname,8)==0) + break; + + // that flat was already found in the level, return the id + if (i == numlevelflats) + { + // allocate new flat memory + levelflats = Z_Realloc(levelflats, (numlevelflats + 1) * sizeof(*levelflats), PU_LEVEL, NULL); + levelflat = levelflats+i; + + // store the name + strlcpy(levelflat->name, flatname, sizeof (levelflat->name)); + strupr(levelflat->name); + + // store the flat lump number + levelflat->lumpnum = R_GetFlatNumForName(flatname); + +#ifndef ZDEBUG + CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name); +#endif + + numlevelflats++; + } + + // level flat id + return (INT32)i; +} + +// help function for $$$.sav checking +// this simply returns the flat # for the name given +// +INT32 P_CheckLevelFlat(const char *flatname) +{ + size_t i; + levelflat_t *levelflat = levelflats; + + // + // scan through the already found flats + // + for (i = 0; i < numlevelflats; i++, levelflat++) + if (strnicmp(levelflat->name,flatname,8)==0) + break; + + if (i == numlevelflats) + return 0; // ??? flat was not found, this should not happen! + + // level flat id + return (INT32)i; +} + static void P_LoadSectors(lumpnum_t lumpnum) { UINT8 *data; @@ -614,6 +711,7 @@ static void P_LoadSectors(lumpnum_t lumpnum) ss->special = SHORT(ms->special); ss->tag = SHORT(ms->tag); ss->nexttag = ss->firsttag = -1; + ss->spawn_nexttag = ss->spawn_firsttag = -1; memset(&ss->soundorg, 0, sizeof(ss->soundorg)); ss->validcount = 0; @@ -1463,6 +1561,8 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum) sd->text[6] = 0; break; } + + case 4: // Speed pad parameters case 414: // Play SFX { sd->toptexture = sd->midtexture = sd->bottomtexture = 0; @@ -1476,6 +1576,8 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum) break; } + case 14: // Bustable block parameters + case 15: // Fan particle spawner parameters case 425: // Calls P_SetMobjState on calling mobj case 434: // Custom Power case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors @@ -2086,6 +2188,7 @@ static void P_LevelInitStuff(void) // special stage tokens, emeralds, and ring total tokenbits = 0; runemeraldmanager = false; + emeraldspawndelay = 60*TICRATE; nummaprings = 0; // emerald hunt @@ -2128,7 +2231,7 @@ static void P_LevelInitStuff(void) players[i].gotcontinue = false; players[i].xtralife = players[i].deadtimer = players[i].numboxes = players[i].totalring = players[i].laps = 0; - players[i].health = 1; + players[i].rings = 0; players[i].aiming = 0; players[i].pflags &= ~PF_TIMEOVER; @@ -2585,7 +2688,7 @@ boolean P_SetupLevel(boolean skipprecip) lastloadedmaplumpnum = W_GetNumForName(maplumpname = G_BuildMapName(gamemap)); R_ReInitColormaps(mapheaderinfo[gamemap-1]->palette); - CON_ReSetupBackColormap(mapheaderinfo[gamemap-1]->palette); + CON_SetupBackColormap(); // SRB2 determines the sky texture to be used depending on the map header. P_SetupLevelSky(mapheaderinfo[gamemap-1]->skynum, true); diff --git a/src/p_setup.h b/src/p_setup.h index 0d735fd71..95976d276 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -47,6 +47,8 @@ typedef struct extern size_t numlevelflats; extern levelflat_t *levelflats; INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat); +INT32 P_AddLevelFlatRuntime(const char *flatname); +INT32 P_CheckLevelFlat(const char *flatname); extern size_t nummapthings; extern mapthing_t *mapthings; @@ -66,6 +68,9 @@ void P_WriteThings(lumpnum_t lump); size_t P_PrecacheLevelFlats(void); void P_AllocMapHeader(INT16 i); +void P_SetDemoFlickies(INT16 i); +void P_DeleteFlickies(INT16 i); + // Needed for NiGHTS void P_ReloadRings(void); void P_DeleteGrades(INT16 i); diff --git a/src/p_slopes.c b/src/p_slopes.c index d939fee98..f480b6e4f 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -804,6 +804,39 @@ void P_SlopeLaunch(mobj_t *mo) mo->standingslope = NULL; } +// +// P_GetWallTransferMomZ +// +// It would be nice to have a single function that does everything necessary for slope-to-wall transfer. +// However, it needs to be seperated out in P_XYMovement to take into account momentum before and after hitting the wall. +// This just performs the necessary calculations for getting the base vertical momentum; the horizontal is already reasonably calculated by P_SlideMove. +fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope) +{ + vector3_t slopemom, axis; + angle_t ang; + + if (mo->standingslope->flags & SL_NOPHYSICS) + return 0; + + // If there's physics, time for launching. + // Doesn't kill the vertical momentum as much as P_SlopeLaunch does. + ang = slope->zangle + ANG15*((slope->zangle > 0) ? 1 : -1); + if (ang > ANGLE_90 && ang < ANGLE_180) + ang = ((slope->zangle > 0) ? ANGLE_90 : InvAngle(ANGLE_90)); // hard cap of directly upwards + + slopemom.x = mo->momx; + slopemom.y = mo->momy; + slopemom.z = 3*(mo->momz/2); + + axis.x = -slope->d.y; + axis.y = slope->d.x; + axis.z = 0; + + FV3_Rotate(&slopemom, &axis, ang >> ANGLETOFINESHIFT); + + return 2*(slopemom.z/3); +} + // Function to help handle landing on slopes void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) { diff --git a/src/p_slopes.h b/src/p_slopes.h index de38f1d9e..f59c5b767 100644 --- a/src/p_slopes.h +++ b/src/p_slopes.h @@ -37,6 +37,7 @@ fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y); void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope); void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope); void P_SlopeLaunch(mobj_t *mo); +fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope); void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope); void P_ButteredSlope(mobj_t *mo); diff --git a/src/p_spec.c b/src/p_spec.c index c3c6d98ed..ddcdfbd53 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -51,6 +51,9 @@ mobj_t *skyboxmo[2]; // Amount (dx, dy) vector linedef is shifted right to get scroll amount #define SCROLL_SHIFT 5 +// This must be updated whenever we up the max flat size - quicker to assume rather than figuring out the sqrt of the specific flat's filesize. +#define MAXFLATSIZE (2048<<FRACBITS) + /** Animated texture descriptor * This keeps track of an animated texture or an animated flat. * \sa P_UpdateSpecials, P_InitPicAnims, animdef_t @@ -108,6 +111,7 @@ static void P_AddFakeFloorsByLine(size_t line, ffloortype_e ffloorflags, thinker static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec); static void Add_Friction(INT32 friction, INT32 movefactor, INT32 affectee, INT32 referrer); static void P_AddSpikeThinker(sector_t *sec, INT32 referrer); +static void P_AddPlaneDisplaceThinker(INT32 type, fixed_t speed, INT32 control, INT32 affectee); //SoM: 3/7/2000: New sturcture without limits. @@ -1519,6 +1523,8 @@ static inline void P_InitTagLists(void) size_t j = (unsigned)sectors[i].tag % numsectors; sectors[i].nexttag = sectors[j].firsttag; sectors[j].firsttag = (INT32)i; + sectors[i].spawn_nexttag = sectors[i].nexttag; + sectors[j].spawn_firsttag = sectors[j].firsttag; } for (i = numlines - 1; i != (size_t)-1; i--) @@ -1621,10 +1627,10 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (!playeringame[i] || players[i].spectator) continue; - if (!players[i].mo || players[i].mo->health < 1) + if (!players[i].mo || players[i].rings <= 0) continue; - rings += players[i].mo->health-1; + rings += players[i].rings; } } else @@ -1632,7 +1638,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (!(actor && actor->player)) return false; // no player to count rings from here, sorry - rings = actor->health-1; + rings = actor->player->rings; } if (triggerline->flags & ML_NOCLIMB) @@ -2438,7 +2444,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { fixed_t sfxnum; - sfxnum = sides[line->sidenum[0]].toptexture; //P_AproxDistance(line->dx, line->dy)>>FRACBITS; + sfxnum = sides[line->sidenum[0]].toptexture; if (line->tag != 0 && line->flags & ML_EFFECT5) { @@ -3593,10 +3599,9 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers break; case 9: // Ring Drainer (Floor Touch) case 10: // Ring Drainer (No Floor Touch) - if (leveltime % (TICRATE/2) == 0 && player->mo->health > 1) + if (leveltime % (TICRATE/2) == 0 && player->rings > 0) { - player->mo->health--; - player->health--; + player->rings--; S_StartSound(player->mo, sfx_itemup); } break; @@ -3604,7 +3609,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super] || player->exiting || player->bot) break; - if (!(player->powers[pw_shield] || player->mo->health > 1)) // Don't do anything if no shield or rings anyway + if (!(player->powers[pw_shield] || player->rings > 0)) // Don't do anything if no shield or rings anyway break; if (player->powers[pw_shield]) @@ -3612,14 +3617,13 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers P_RemoveShield(player); S_StartSound(player->mo, sfx_shldls); // Ba-Dum! Shield loss. } - else if (player->mo->health > 1) + else if (player->rings > 0) { P_PlayRinglossSound(player->mo); - if (player->mo->health > 10) - player->mo->health -= 10; + if (player->rings >= 10) + player->rings -= 10; else - player->mo->health = 1; - player->health = player->mo->health; + player->rings = 0; } P_DoPlayerPain(player, NULL, NULL); // this does basically everything that was here before @@ -3628,7 +3632,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers P_PlayerFlagBurst(player, false); break; case 12: // Space Countdown - if ((player->powers[pw_shield] & SH_NOSTACK) != SH_ELEMENTAL && !player->powers[pw_spacetime]) + if (!(player->powers[pw_shield] & SH_PROTECTWATER) && !player->powers[pw_spacetime]) player->powers[pw_spacetime] = spacetimetics + 1; break; case 13: // Ramp Sector (Increase step-up/down) @@ -3728,14 +3732,13 @@ DoneSection2: // Process Section 3 switch (special) { - case 1: // Ice/Sludge + case 1: // Unused case 2: // Wind/Current - case 3: // Ice/Sludge and Wind/Current + case 3: // Unused case 4: // Conveyor Belt break; - case 5: // Speed pad w/o spin - case 6: // Speed pad w/ spin + case 5: // Speed pad if (player->powers[pw_flashing] != 0 && player->powers[pw_flashing] < TICRATE/2) break; @@ -3745,9 +3748,16 @@ DoneSection2: { angle_t lineangle; fixed_t linespeed; + fixed_t sfxnum; lineangle = R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y); - linespeed = P_AproxDistance(lines[i].v2->x-lines[i].v1->x, lines[i].v2->y-lines[i].v1->y); + linespeed = sides[lines[i].sidenum[0]].textureoffset; + + if (linespeed == 0) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: Speed pad (tag %d) at zero speed.\n", sector->tag); + break; + } player->mo->angle = lineangle; @@ -3777,7 +3787,7 @@ DoneSection2: P_InstaThrust(player->mo, player->mo->angle, linespeed); - if (GETSECSPECIAL(sector->special, 3) == 6 && (player->charability2 == CA2_SPINDASH)) + if ((lines[i].flags & ML_EFFECT5) && (player->charability2 == CA2_SPINDASH)) // Roll! { if (!(player->pflags & PF_SPINNING)) player->pflags |= PF_SPINNING; @@ -3786,19 +3796,26 @@ DoneSection2: } player->powers[pw_flashing] = TICRATE/3; - S_StartSound(player->mo, sfx_spdpad); + + sfxnum = sides[lines[i].sidenum[0]].toptexture; + + if (!sfxnum) + sfxnum = sfx_spdpad; + + S_StartSound(player->mo, sfxnum); } break; - case 7: // Bustable block sprite parameter - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: + case 6: // Unused + case 7: // Unused + case 8: // Unused + case 9: // Unused + case 10: // Unused + case 11: // Unused + case 12: // Unused + case 13: // Unused + case 14: // Unused + case 15: // Unused break; } @@ -3968,8 +3985,14 @@ DoneSection2: } // Grab speed and sequence values - speed = abs(lines[lineindex].dx)/8; - sequence = abs(lines[lineindex].dy)>>FRACBITS; + speed = abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8; + sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS; + + if (speed == 0) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence); + break; + } // scan the thinkers // to find the first waypoint @@ -4041,8 +4064,14 @@ DoneSection2: } // Grab speed and sequence values - speed = -(abs(lines[lineindex].dx)/8); // Negative means reverse - sequence = abs(lines[lineindex].dy)>>FRACBITS; + speed = -abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8; // Negative means reverse + sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS; + + if (speed == 0) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence); + break; + } // scan the thinkers // to find the last waypoint @@ -4082,6 +4111,7 @@ DoneSection2: player->speed = speed; player->pflags |= PF_SPINNING; player->pflags &= ~(PF_JUMPED|PF_GLIDING|PF_SLIDING|PF_CANCARRY); + player->climbing = 0; if (player->mo->state-states != S_PLAY_SPIN) { @@ -4180,8 +4210,14 @@ DoneSection2: } // Grab speed and sequence values - speed = abs(lines[lineindex].dx)/8; - sequence = abs(lines[lineindex].dy)>>FRACBITS; + speed = abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8; + sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS; + + if (speed == 0) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence); + break; + } // Find the closest waypoint // Find the preceding waypoint @@ -4797,6 +4833,13 @@ void P_UpdateSpecials(void) } } +/** Gets a 3Dfloor by control sector. + * + * \param sec Target sector. + * \param sec2 Control sector. + * \return Pointer to found 3Dfloor, or NULL. + * \sa P_GetFFloorByID + */ static inline ffloor_t *P_GetFFloorBySec(sector_t *sec, sector_t *sec2) { ffloor_t *rover; @@ -4809,6 +4852,26 @@ static inline ffloor_t *P_GetFFloorBySec(sector_t *sec, sector_t *sec2) return NULL; } +/** Gets a 3Dfloor by ID number. + * + * \param sec Target sector. + * \param id ID of 3Dfloor in target sector. Note that the first FOF's ID is 0. + * \return Pointer to found 3Dfloor, or NULL. + * \sa P_GetFFloorBySec + */ +ffloor_t *P_GetFFloorByID(sector_t *sec, UINT16 id) +{ + ffloor_t *rover; + UINT16 i = 0; + + if (!sec->ffloors) + return NULL; + for (rover = sec->ffloors; rover; rover = rover->next) + if (i++ == id) + return rover; + return NULL; +} + /** Adds a newly formed 3Dfloor structure to a sector's ffloors list. * * \param sec Target sector. @@ -5001,7 +5064,8 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f if ((flags & FF_MARIO)) { - P_AddBlockThinker(sec2, master); + if (!(flags & FF_SHATTERBOTTOM)) // Don't change the textures of a brick block, just a question block + P_AddBlockThinker(sec2, master); CheckForMarioBlocks = true; } @@ -5101,6 +5165,33 @@ static inline void P_AddBridgeThinker(line_t *sourceline, sector_t *sec) } */ +/** + * Adds a plane displacement thinker. + * Whenever the "control" sector moves, + * the "affectee" sector's floor or ceiling plane moves too! + * + * \param speed Rate of movement relative to control sector + * \param control Control sector. + * \param affectee Target sector. + * \sa P_SpawnSpecials, T_PlaneDisplace + * \author Monster Iestyn + */ +static void P_AddPlaneDisplaceThinker(INT32 type, fixed_t speed, INT32 control, INT32 affectee) +{ + planedisplace_t *displace; + + // create and initialize new displacement thinker + displace = Z_Calloc(sizeof (*displace), PU_LEVSPEC, NULL); + P_AddThinker(&displace->thinker); + + displace->thinker.function.acp1 = (actionf_p1)T_PlaneDisplace; + displace->affectee = affectee; + displace->control = control; + displace->last_height = sectors[control].floorheight; + displace->speed = speed; + displace->type = type; +} + /** Adds a Mario block thinker, which changes the block's texture between blank * and ? depending on whether it has contents. * Needed in case objects respawn inside. @@ -5339,7 +5430,7 @@ static inline void P_AddCameraScanner(sector_t *sourcesec, sector_t *actionsecto elevator->distance = FixedInt(AngleFixed(angle)); } -static const ffloortype_e laserflags = FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA; +static const ffloortype_e laserflags = FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA|FF_TRANSLUCENT; /** Flashes a laser block. * @@ -5359,10 +5450,12 @@ void T_LaserFlash(laserthink_t *flash) if (!ffloor || !(ffloor->flags & FF_EXISTS)) return; - if (leveltime & 1) - ffloor->flags |= FF_RENDERALL; + if (leveltime & 2) + //ffloor->flags |= FF_RENDERALL; + ffloor->alpha = 0xB0; else - ffloor->flags &= ~FF_RENDERALL; + //ffloor->flags &= ~FF_RENDERALL; + ffloor->alpha = 0x90; sourcesec = ffloor->master->frontsector; // Less to type! @@ -5386,6 +5479,10 @@ void T_LaserFlash(laserthink_t *flash) && thing->flags & MF_BOSS) continue; // Don't hurt bosses + // Don't endlessly kill egg guard shields (or anything else for that matter) + if (thing->health <= 0) + continue; + top = P_GetSpecialTopZ(thing, sourcesec, sector); bottom = P_GetSpecialBottomZ(thing, sourcesec, sector); @@ -5586,32 +5683,27 @@ void P_SpawnSpecials(INT32 fromnetsave) // Init line EFFECTs for (i = 0; i < numlines; i++) { - // set line specials to 0 here too, same reason as above - if (netgame || multiplayer) + if (lines[i].special != 7) // This is a hack. I can at least hope nobody wants to prevent flat alignment with arbitrary skin setups... { - // future: nonet flag? - } - else if ((lines[i].flags & ML_NETONLY) == ML_NETONLY) - { - lines[i].special = 0; - continue; - } - else - { - if (players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC)) + // set line specials to 0 here too, same reason as above + if (netgame || multiplayer) + { + // future: nonet flag? + } + else if ((lines[i].flags & ML_NETONLY) == ML_NETONLY) { lines[i].special = 0; continue; } - if (players[consoleplayer].charability == CA_FLY && (lines[i].flags & ML_NOTAILS)) + else { - lines[i].special = 0; - continue; - } - if (players[consoleplayer].charability == CA_GLIDEANDCLIMB && (lines[i].flags & ML_NOKNUX)) - { - lines[i].special = 0; - continue; + if ((players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC)) + || (players[consoleplayer].charability == CA_FLY && (lines[i].flags & ML_NOTAILS)) + || (players[consoleplayer].charability == CA_GLIDEANDCLIMB && (lines[i].flags & ML_NOKNUX))) + { + lines[i].special = 0; + continue; + } } } @@ -5657,47 +5749,53 @@ void P_SpawnSpecials(INT32 fromnetsave) break; #endif - case 7: // Flat alignment - if (lines[i].flags & ML_EFFECT4) // Align angle + case 7: // Flat alignment - redone by toast + if ((lines[i].flags & (ML_NOSONIC|ML_NOTAILS)) != (ML_NOSONIC|ML_NOTAILS)) // If you can do something... { - if (!(lines[i].flags & ML_EFFECT5)) // Align floor unless ALLTRIGGER flag is set + angle_t flatangle = InvAngle(R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y)); + fixed_t xoffs; + fixed_t yoffs; + + if (lines[i].flags & ML_NOKNUX) // Set offset through x and y texture offsets if NOKNUX flag is set { - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) - sectors[s].spawn_flrpic_angle = sectors[s].floorpic_angle = R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y); + xoffs = sides[lines[i].sidenum[0]].textureoffset; + yoffs = sides[lines[i].sidenum[0]].rowoffset; + } + else // Otherwise, set calculated offsets such that line's v1 is the apparent origin + { + fixed_t cosinecomponent = FINECOSINE(flatangle>>ANGLETOFINESHIFT); + fixed_t sinecomponent = FINESINE(flatangle>>ANGLETOFINESHIFT); + xoffs = (-FixedMul(lines[i].v1->x, cosinecomponent) % MAXFLATSIZE) + (FixedMul(lines[i].v1->y, sinecomponent) % MAXFLATSIZE); // No danger of overflow thanks to the strategically placed modulo operations. + yoffs = (FixedMul(lines[i].v1->x, sinecomponent) % MAXFLATSIZE) + (FixedMul(lines[i].v1->y, cosinecomponent) % MAXFLATSIZE); // Ditto. } - if (!(lines[i].flags & ML_BOUNCY)) // Align ceiling unless BOUNCY flag is set + for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) { - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) - sectors[s].spawn_ceilpic_angle = sectors[s].ceilingpic_angle = R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y); - } - } - else // Do offsets - { - if (!(lines[i].flags & ML_BLOCKMONSTERS)) // Align floor unless BLOCKMONSTERS flag is set - { - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) + if (!(lines[i].flags & ML_NOSONIC)) // Modify floor flat alignment unless NOSONIC flag is set { - sectors[s].floor_xoffs += lines[i].dx; - sectors[s].floor_yoffs += lines[i].dy; + sectors[s].spawn_flrpic_angle = sectors[s].floorpic_angle = flatangle; + sectors[s].floor_xoffs += xoffs; + sectors[s].floor_yoffs += yoffs; // saved for netgames sectors[s].spawn_flr_xoffs = sectors[s].floor_xoffs; sectors[s].spawn_flr_yoffs = sectors[s].floor_yoffs; } - } - if (!(lines[i].flags & ML_NOCLIMB)) // Align ceiling unless NOCLIMB flag is set - { - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) + if (!(lines[i].flags & ML_NOTAILS)) // Modify ceiling flat alignment unless NOTAILS flag is set { - sectors[s].ceiling_xoffs += lines[i].dx; - sectors[s].ceiling_yoffs += lines[i].dy; + sectors[s].spawn_ceilpic_angle = sectors[s].ceilingpic_angle = flatangle; + sectors[s].ceiling_xoffs += xoffs; + sectors[s].ceiling_yoffs += yoffs; // saved for netgames sectors[s].spawn_ceil_xoffs = sectors[s].ceiling_xoffs; sectors[s].spawn_ceil_yoffs = sectors[s].ceiling_yoffs; } } } + else // Otherwise, print a helpful warning. Can I do no less? + CONS_Alert(CONS_WARNING, + M_GetText("Flat alignment linedef (tag %d) doesn't have anything to do.\nConsider changing the linedef's flag configuration or removing it entirely.\n"), + lines[i].tag); break; case 8: // Sector Parameters @@ -5809,6 +5907,19 @@ void P_SpawnSpecials(INT32 fromnetsave) P_AddBridgeThinker(&lines[i], §ors[s]);*/ break; + case 66: // Displace floor by front sector + for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) + P_AddPlaneDisplaceThinker(pd_floor, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s); + break; + case 67: // Displace ceiling by front sector + for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) + P_AddPlaneDisplaceThinker(pd_ceiling, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s); + break; + case 68: // Displace both floor AND ceiling by front sector + for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) + P_AddPlaneDisplaceThinker(pd_both, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s); + break; + case 100: // FOF (solid, opaque, shadows) P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); break; @@ -5823,11 +5934,8 @@ void P_SpawnSpecials(INT32 fromnetsave) // Draw the 'insides' of the block too if (lines[i].flags & ML_NOCLIMB) { - ffloorflags |= FF_CUTLEVEL; - ffloorflags |= FF_BOTHPLANES; - ffloorflags |= FF_ALLSIDES; - ffloorflags &= ~FF_EXTRA; - ffloorflags &= ~FF_CUTEXTRA; + ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES; + ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA); } P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); @@ -5934,11 +6042,8 @@ void P_SpawnSpecials(INT32 fromnetsave) // Draw the 'insides' of the block too if (lines[i].flags & ML_EFFECT2) { - ffloorflags |= FF_CUTLEVEL; - ffloorflags |= FF_BOTHPLANES; - ffloorflags |= FF_ALLSIDES; - ffloorflags &= ~FF_EXTRA; - ffloorflags &= ~FF_CUTEXTRA; + ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES; + ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA); } P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); @@ -5952,11 +6057,8 @@ void P_SpawnSpecials(INT32 fromnetsave) // Draw the 'insides' of the block too if (lines[i].flags & ML_EFFECT2) { - ffloorflags |= FF_CUTLEVEL; - ffloorflags |= FF_BOTHPLANES; - ffloorflags |= FF_ALLSIDES; - ffloorflags &= ~FF_EXTRA; - ffloorflags &= ~FF_CUTEXTRA; + ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES; + ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA); } P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); @@ -5980,11 +6082,8 @@ void P_SpawnSpecials(INT32 fromnetsave) // Draw the 'insides' of the block too if (lines[i].flags & ML_EFFECT2) { - ffloorflags |= FF_CUTLEVEL; - ffloorflags |= FF_BOTHPLANES; - ffloorflags |= FF_ALLSIDES; - ffloorflags &= ~FF_EXTRA; - ffloorflags &= ~FF_CUTEXTRA; + ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES; + ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA); } P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); @@ -5998,11 +6097,8 @@ void P_SpawnSpecials(INT32 fromnetsave) // Draw the 'insides' of the block too if (lines[i].flags & ML_EFFECT2) { - ffloorflags |= FF_CUTLEVEL; - ffloorflags |= FF_BOTHPLANES; - ffloorflags |= FF_ALLSIDES; - ffloorflags &= ~FF_EXTRA; - ffloorflags &= ~FF_CUTEXTRA; + ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES; + ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA); } P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); @@ -6180,7 +6276,13 @@ void P_SpawnSpecials(INT32 fromnetsave) break; case 250: // Mario Block - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_MARIO, secthinkers); + ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_MARIO; + if (lines[i].flags & ML_NOCLIMB) + ffloorflags |= FF_SHATTERBOTTOM; + if (lines[i].flags & ML_EFFECT1) + ffloorflags &= ~(FF_SOLID|FF_RENDERALL|FF_CUTLEVEL); + + P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; case 251: // A THWOMP! @@ -6194,10 +6296,11 @@ void P_SpawnSpecials(INT32 fromnetsave) break; case 252: // Shatter block (breaks when touched) + ffloorflags = FF_EXISTS|FF_RENDERALL|FF_BUSTUP|FF_SHATTER; if (lines[i].flags & ML_NOCLIMB) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP|FF_SHATTER|FF_SHATTERBOTTOM, secthinkers); - else - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_RENDERALL|FF_BUSTUP|FF_SHATTER, secthinkers); + ffloorflags |= FF_SOLID|FF_SHATTERBOTTOM; + + P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; case 253: // Translucent shatter block (see 76) @@ -6205,10 +6308,11 @@ void P_SpawnSpecials(INT32 fromnetsave) break; case 254: // Bustable block + ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP; if (lines[i].flags & ML_NOCLIMB) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP|FF_ONLYKNUX, secthinkers); - else - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP, secthinkers); + ffloorflags |= FF_ONLYKNUX; + + P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; case 255: // Spin bust block (breaks when jumped or spun downwards onto) @@ -6220,10 +6324,11 @@ void P_SpawnSpecials(INT32 fromnetsave) break; case 257: // Quicksand + ffloorflags = FF_EXISTS|FF_QUICKSAND|FF_RENDERALL|FF_ALLSIDES|FF_CUTSPRITES; if (lines[i].flags & ML_EFFECT5) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_QUICKSAND|FF_RENDERALL|FF_ALLSIDES|FF_CUTSPRITES|FF_RIPPLE, secthinkers); - else - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_QUICKSAND|FF_RENDERALL|FF_ALLSIDES|FF_CUTSPRITES, secthinkers); + ffloorflags |= FF_RIPPLE; + + P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; case 258: // Laser block @@ -6984,7 +7089,6 @@ void T_Disappear(disappear_t *d) /** Adds friction thinker. * * \param friction Friction value, 0xe800 is normal. - * \param movefactor Inertia factor. * \param affectee Target sector. * \param roverfriction FOF or not * \sa T_Friction, P_SpawnFriction @@ -7022,22 +7126,10 @@ void T_Friction(friction_t *f) sec = sectors + f->affectee; - // Make sure the sector type hasn't changed + // Get FOF control sector if (f->roverfriction) - { referrer = sectors + f->referrer; - if (!(GETSECSPECIAL(referrer->special, 3) == 1 - || GETSECSPECIAL(referrer->special, 3) == 3)) - return; - } - else - { - if (!(GETSECSPECIAL(sec->special, 3) == 1 - || GETSECSPECIAL(sec->special, 3) == 3)) - return; - } - // Assign the friction value to players on the floor, non-floating, // and clipped. Normally the object's friction value is kept at // ORIG_FRICTION and this thinker changes it for icy or muddy floors. @@ -7067,14 +7159,16 @@ void T_Friction(friction_t *f) || (f->friction < thing->friction)) { thing->friction = f->friction; - thing->movefactor = f->movefactor; + if (thing->player) + thing->movefactor = f->movefactor; } } else if (P_GetSpecialBottomZ(thing, sec, sec) == thing->floorz && (thing->friction == ORIG_FRICTION // normal friction? || f->friction < thing->friction)) { thing->friction = f->friction; - thing->movefactor = f->movefactor; + if (thing->player) + thing->movefactor = f->movefactor; } } node = node->m_thinglist_next; @@ -7090,33 +7184,32 @@ static void P_SpawnFriction(void) size_t i; line_t *l = lines; register INT32 s; - fixed_t length; // line length controls magnitude + fixed_t strength; // frontside texture offset controls magnitude fixed_t friction; // friction value to be applied during movement INT32 movefactor; // applied to each player move to simulate inertia for (i = 0; i < numlines; i++, l++) if (l->special == 540) { - length = P_AproxDistance(l->dx, l->dy)>>FRACBITS; - friction = (0x1EB8*length)/0x80 + 0xD000; + strength = sides[l->sidenum[0]].textureoffset>>FRACBITS; + if (strength > 0) // sludge + strength = strength*2; // otherwise, the maximum sludginess value is +967... + + // The following might seem odd. At the time of movement, + // the move distance is multiplied by 'friction/0x10000', so a + // higher friction value actually means 'less friction'. + friction = ORIG_FRICTION - (0x1EB8*strength)/0x80; // ORIG_FRICTION is 0xE800 if (friction > FRACUNIT) friction = FRACUNIT; if (friction < 0) friction = 0; - // The following check might seem odd. At the time of movement, - // the move distance is multiplied by 'friction/0x10000', so a - // higher friction value actually means 'less friction'. - - if (friction > ORIG_FRICTION) // ice - movefactor = ((0x10092 - friction)*(0x70))/0x158; + movefactor = FixedDiv(ORIG_FRICTION, friction); + if (movefactor < FRACUNIT) + movefactor = 8*movefactor - 7*FRACUNIT; else - movefactor = ((friction - 0xDB34)*(0xA))/0x80; - - // killough 8/28/98: prevent odd situations - if (movefactor < 32) - movefactor = 32; + movefactor = FRACUNIT; for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;) Add_Friction(friction, movefactor, s, -1); @@ -7366,12 +7459,10 @@ void T_Pusher(pusher_t *p) { referrer = §ors[p->referrer]; - if (!(GETSECSPECIAL(referrer->special, 3) == 2 - || GETSECSPECIAL(referrer->special, 3) == 3)) + if (GETSECSPECIAL(referrer->special, 3) != 2) return; } - else if (!(GETSECSPECIAL(sec->special, 3) == 2 - || GETSECSPECIAL(sec->special, 3) == 3)) + else if (GETSECSPECIAL(sec->special, 3) != 2) return; // For constant pushers (wind/current) there are 3 situations: diff --git a/src/p_spec.h b/src/p_spec.h index a8f9ac492..0c77eb19f 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -64,6 +64,8 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller); void P_ChangeSectorTag(UINT32 sector, INT16 newtag); +ffloor_t *P_GetFFloorByID(sector_t *sec, UINT16 id); + // // P_LIGHTS // @@ -323,7 +325,7 @@ INT32 EV_StartCrumble(sector_t *sector, ffloor_t *rover, INT32 EV_DoContinuousFall(sector_t *sec, sector_t *pbacksector, fixed_t spd, boolean backwards); -INT32 EV_MarioBlock(sector_t *sector, sector_t *roversector, fixed_t topheight, mobj_t *puncher); +INT32 EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher); void T_MoveFloor(floormove_t *movefloor); @@ -386,7 +388,7 @@ typedef struct { thinker_t thinker; ///< Thinker structure for friction. INT32 friction; ///< Friction value, 0xe800 = normal. - INT32 movefactor; ///< Inertia factor when adding to momentum. + INT32 movefactor; ///< Inertia factor when adding to momentum, FRACUNIT = normal. INT32 affectee; ///< Number of affected sector. INT32 referrer; ///< If roverfriction == true, then this will contain the sector # of the control sector where the effect was applied. UINT8 roverfriction; ///< flag for whether friction originated from a FOF or not @@ -448,6 +450,26 @@ void T_Disappear(disappear_t *d); void T_Pusher(pusher_t *p); mobj_t *P_GetPushThing(UINT32 s); +// Plane displacement +typedef struct +{ + thinker_t thinker; ///< Thinker structure for plane displacement effect. + INT32 affectee; ///< Number of affected sector. + INT32 control; ///< Control sector used to control plane positions. + fixed_t last_height; ///< Last known height of control sector. + fixed_t speed; ///< Plane movement speed. + /** Types of plane displacement effects. + */ + enum + { + pd_floor, ///< Displace floor. + pd_ceiling, ///< Displace ceiling. + pd_both, ///< Displace both floor AND ceiling. + } type; +} planedisplace_t; + +void T_PlaneDisplace(planedisplace_t *pd); + void P_CalcHeight(player_t *player); sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo); diff --git a/src/p_tick.c b/src/p_tick.c index 55df9ca28..5235a1a03 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -469,7 +469,7 @@ static inline void P_DoSpecialStageStuff(void) for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) { - ssrings += (players[i].mo->health-1); + ssrings += players[i].rings; // If in water, deplete timer 6x as fast. if ((players[i].mo->eflags & MFE_TOUCHWATER) diff --git a/src/p_user.c b/src/p_user.c index 697f42e4d..905c3be62 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -650,7 +650,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) if (!(player->pflags & PF_NIGHTSMODE)) player->mo->height = P_GetPlayerHeight(player); // Just to make sure jumping into the drone doesn't result in a squashed hitbox. - player->pflags &= ~(PF_USEDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_STARTDASH|PF_GLIDING|PF_JUMPED|PF_THOKKED|PF_SPINNING|PF_DRILLING); + player->pflags &= ~(PF_USEDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_STARTDASH|PF_GLIDING|PF_JUMPED|PF_THOKKED|PF_SHIELDABILITY|PF_SPINNING|PF_DRILLING); player->homing = 0; player->mo->fuse = 0; player->speed = 0; @@ -697,7 +697,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) { for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]/* && players[i].pflags & PF_NIGHTSMODE*/) - total_rings += players[i].health-1; + total_rings += players[i].rings; } for (i = 0; i < MAXPLAYERS; i++) @@ -715,8 +715,8 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) } else { - players[i].finishedrings = (INT16)(players[i].health - 1); - P_AddPlayerScore(&players[i], (players[i].health - 1) * 50); + players[i].finishedrings = (INT16)(players[i].rings); + P_AddPlayerScore(&players[i], (players[i].rings) * 50); } // Add score to leaderboards now @@ -727,7 +727,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) players[i].lastmarescore = players[i].marescore; players[i].marescore = 0; - players[i].mo->health = players[i].health = 1; + players[i].rings = 0; P_DoPlayerExit(&players[i]); } } @@ -735,12 +735,12 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) { /// \todo Handle multi-mare special stages. // Ring bonus - P_AddPlayerScore(player, (player->health - 1) * 50); + P_AddPlayerScore(player, (player->rings) * 50); player->lastmare = (UINT8)oldmare; player->texttimer = 4*TICRATE; player->textvar = 4; // Score and grades - player->finishedrings = (INT16)(player->health - 1); + player->finishedrings = (INT16)(player->rings); // Add score to temp leaderboards if (!(netgame||multiplayer) && P_IsLocalPlayer(player)) @@ -751,7 +751,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) player->marescore = 0; player->marebegunat = leveltime; - player->mo->health = player->health = 1; + player->rings = 0; } else { @@ -790,59 +790,64 @@ boolean P_PlayerInPain(player_t *player) // void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor) { - angle_t ang; - fixed_t fallbackspeed; - - if (player->mo->eflags & MFE_VERTICALFLIP) - player->mo->z--; - else - player->mo->z++; - - if (player->mo->eflags & MFE_UNDERWATER) - P_SetObjectMomZ(player->mo, FixedDiv(10511*FRACUNIT,2600*FRACUNIT), false); - else - P_SetObjectMomZ(player->mo, FixedDiv(69*FRACUNIT,10*FRACUNIT), false); - - if (inflictor) - { - ang = R_PointToAngle2(inflictor->x-inflictor->momx, inflictor->y - inflictor->momy, player->mo->x - player->mo->momx, player->mo->y - player->mo->momy); - - // explosion and rail rings send you farther back, making it more difficult - // to recover - if ((inflictor->flags2 & MF2_SCATTER) && source) - { - fixed_t dist = P_AproxDistance(P_AproxDistance(source->x-player->mo->x, source->y-player->mo->y), source->z-player->mo->z); - - dist = FixedMul(128*FRACUNIT, inflictor->scale) - dist/4; - - if (dist < FixedMul(4*FRACUNIT, inflictor->scale)) - dist = FixedMul(4*FRACUNIT, inflictor->scale); - - fallbackspeed = dist; - } - else if (inflictor->flags2 & MF2_EXPLOSION) - { - if (inflictor->flags2 & MF2_RAILRING) - fallbackspeed = FixedMul(38*FRACUNIT, inflictor->scale); // 7x - else - fallbackspeed = FixedMul(30*FRACUNIT, inflictor->scale); // 5x - } - else if (inflictor->flags2 & MF2_RAILRING) - fallbackspeed = FixedMul(45*FRACUNIT, inflictor->scale); // 4x - else - fallbackspeed = FixedMul(4*FRACUNIT, inflictor->scale); // the usual amount of force - } - else - { - ang = R_PointToAngle2(player->mo->momx, player->mo->momy, 0, 0); - fallbackspeed = FixedMul(4*FRACUNIT, player->mo->scale); - } - - P_InstaThrust(player->mo, ang, fallbackspeed); - if (player->powers[pw_carry] == CR_ROPEHANG) P_SetTarget(&player->mo->tracer, NULL); + { + angle_t ang; + fixed_t fallbackspeed; + + P_ResetPlayer(player); + P_SetPlayerMobjState(player->mo, player->mo->info->painstate); + + if (player->mo->eflags & MFE_VERTICALFLIP) + player->mo->z--; + else + player->mo->z++; + + if (player->mo->eflags & MFE_UNDERWATER) + P_SetObjectMomZ(player->mo, FixedDiv(10511*FRACUNIT,2600*FRACUNIT), false); + else + P_SetObjectMomZ(player->mo, FixedDiv(69*FRACUNIT,10*FRACUNIT), false); + + if (inflictor) + { + ang = R_PointToAngle2(inflictor->x-inflictor->momx, inflictor->y - inflictor->momy, player->mo->x - player->mo->momx, player->mo->y - player->mo->momy); + + // explosion and rail rings send you farther back, making it more difficult + // to recover + if ((inflictor->flags2 & MF2_SCATTER) && source) + { + fixed_t dist = P_AproxDistance(P_AproxDistance(source->x-player->mo->x, source->y-player->mo->y), source->z-player->mo->z); + + dist = FixedMul(128*FRACUNIT, inflictor->scale) - dist/4; + + if (dist < FixedMul(4*FRACUNIT, inflictor->scale)) + dist = FixedMul(4*FRACUNIT, inflictor->scale); + + fallbackspeed = dist; + } + else if (inflictor->flags2 & MF2_EXPLOSION) + { + if (inflictor->flags2 & MF2_RAILRING) + fallbackspeed = FixedMul(38*FRACUNIT, inflictor->scale); // 7x + else + fallbackspeed = FixedMul(30*FRACUNIT, inflictor->scale); // 5x + } + else if (inflictor->flags2 & MF2_RAILRING) + fallbackspeed = FixedMul(45*FRACUNIT, inflictor->scale); // 4x + else + fallbackspeed = FixedMul(4*FRACUNIT, inflictor->scale); // the usual amount of force + } + else + { + ang = R_PointToAngle2(player->mo->momx, player->mo->momy, 0, 0); + fallbackspeed = FixedMul(4*FRACUNIT, player->mo->scale); + } + + P_InstaThrust(player->mo, ang, fallbackspeed); + } + // Point penalty for hitting a hazard during tag. // Discourages players from intentionally hurting themselves to avoid being tagged. if (gametype == GT_TAG && (!(player->pflags & PF_TAGGED) && !(player->pflags & PF_TAGIT))) @@ -853,8 +858,6 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor) player->score = 0; } - P_ResetPlayer(player); - P_SetPlayerMobjState(player->mo, player->mo->info->painstate); player->powers[pw_flashing] = flashingtics; if (player->timeshit != UINT8_MAX) @@ -867,7 +870,7 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor) // Useful when you want to kill everything the player is doing. void P_ResetPlayer(player_t *player) { - player->pflags &= ~(PF_SPINNING|PF_STARTDASH|PF_JUMPED|PF_GLIDING|PF_THOKKED|PF_CANCARRY); + player->pflags &= ~(PF_SPINNING|PF_STARTDASH|PF_JUMPED|PF_FORCEJUMPDAMAGE|PF_GLIDING|PF_THOKKED|PF_CANCARRY|PF_SHIELDABILITY); player->powers[pw_carry] = CR_NONE; player->jumping = 0; player->secondjump = 0; @@ -895,30 +898,23 @@ void P_GivePlayerRings(player_t *player, INT32 num_rings) if (!player->mo) return; - player->mo->health += num_rings; - player->health += num_rings; + player->rings += num_rings; if (!G_IsSpecialStage(gamemap) || !useNightsSS) player->totalring += num_rings; // Can only get up to 9999 rings, sorry! - if (player->mo->health > 10000) - { - player->mo->health = 10000; - player->health = 10000; - } - else if (player->mo->health < 1) - { - player->mo->health = 1; - player->health = 1; - } + if (player->rings > 9999) + player->rings = 9999; + else if (player->rings < 0) + player->rings = 0; // Now extra life bonuses are handled here instead of in P_MovePlayer, since why not? if (!ultimatemode && !modeattacking && !G_IsSpecialStage(gamemap) && G_GametypeUsesLives()) { INT32 gainlives = 0; - while (player->xtralife < maxXtraLife && player->health > 100 * (player->xtralife+1)) + while (player->xtralife < maxXtraLife && player->rings >= 100 * (player->xtralife+1)) { ++gainlives; ++player->xtralife; @@ -969,10 +965,7 @@ void P_DoSuperTransformation(player_t *player, boolean giverings) player->mo->momx = player->mo->momy = player->mo->momz = 0; if (giverings) - { - player->mo->health = 51; - player->health = player->mo->health; - } + player->rings = 50; // Just in case. if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOSSMUSIC)) @@ -991,6 +984,7 @@ void P_DoSuperTransformation(player_t *player, boolean giverings) P_PlayerFlagBurst(player, false); } + // Adds to the player's score void P_AddPlayerScore(player_t *player, UINT32 amount) { @@ -1077,6 +1071,42 @@ void P_AddPlayerScore(player_t *player, UINT32 amount) } } +// Steals from every enemy's score. +void P_StealPlayerScore(player_t *player, UINT32 amount) +{ + boolean teams = G_GametypeHasTeams(); + UINT32 stolen = 0; + int i; + for (i = 0; i < MAXPLAYERS; i++) + { + if (&players[i] == player + || (teams && players[i].ctfteam == player->ctfteam)) + continue; + if (players[i].score >= amount) + { + stolen += amount; + players[i].score -= amount; + } + else + { + stolen += players[i].score; + players[i].score = 0; + } + } + if (stolen > 0) + { + // In team match, all stolen points are removed from the enemy team's running score. + if (gametype == GT_TEAMMATCH) + { + if (player->ctfteam == 1) + bluescore -= amount; + else if (player->ctfteam == 2) + redscore -= amount; + } + P_AddPlayerScore(player, stolen); + } +} + // // P_PlayLivesJingle // @@ -1321,24 +1351,38 @@ void P_SpawnShieldOrb(player_t *player) I_Error("P_SpawnShieldOrb: player->mo is NULL!\n"); #endif +#ifdef HAVE_BLUA + if (LUAh_ShieldSpawn(player)) + return; +#endif + if (player->powers[pw_shield] & SH_FORCE) - orbtype = MT_BLUEORB; + orbtype = MT_FORCE_ORB; else switch (player->powers[pw_shield] & SH_NOSTACK) { - case SH_JUMP: - orbtype = MT_WHITEORB; + case SH_WHIRLWIND: + orbtype = MT_WHIRLWIND_ORB; break; case SH_ATTRACT: - orbtype = MT_YELLOWORB; + orbtype = MT_ATTRACT_ORB; break; case SH_ELEMENTAL: - orbtype = MT_GREENORB; + orbtype = MT_ELEMENTAL_ORB; break; - case SH_BOMB: - orbtype = MT_BLACKORB; + case SH_ARMAGEDDON: + orbtype = MT_ARMAGEDDON_ORB; break; case SH_PITY: - orbtype = MT_PITYORB; + orbtype = MT_PITY_ORB; + break; + case SH_FLAMEAURA: + orbtype = MT_FLAMEAURA_ORB; + break; + case SH_BUBBLEWRAP: + orbtype = MT_BUBBLEWRAP_ORB; + break; + case SH_THUNDERCOIN: + orbtype = MT_THUNDERCOIN_ORB; break; default: return; @@ -1357,14 +1401,17 @@ void P_SpawnShieldOrb(player_t *player) } shieldobj = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, orbtype); + shieldobj->flags2 |= MF2_SHIELD; P_SetTarget(&shieldobj->target, player->mo); shieldobj->color = (UINT8)shieldobj->info->painchance; + shieldobj->threshold = (player->powers[pw_shield] & SH_FORCE) ? SH_FORCE : (player->powers[pw_shield] & SH_NOSTACK); if (shieldobj->info->seestate) { ov = P_SpawnMobj(shieldobj->x, shieldobj->y, shieldobj->z, MT_OVERLAY); P_SetTarget(&ov->target, shieldobj); P_SetMobjState(ov, shieldobj->info->seestate); + P_SetTarget(&shieldobj->tracer, ov); } if (shieldobj->info->meleestate) { @@ -1381,7 +1428,7 @@ void P_SpawnShieldOrb(player_t *player) if (player->powers[pw_shield] & SH_FORCE) { //Copy and pasted from P_ShieldLook in p_mobj.c - shieldobj->movecount = (player->powers[pw_shield] & 0xFF); + shieldobj->movecount = (player->powers[pw_shield] & SH_FORCEHP); if (shieldobj->movecount < 1) { if (shieldobj->info->painstate) @@ -1392,6 +1439,51 @@ void P_SpawnShieldOrb(player_t *player) } } +// +// P_SwitchShield +// +// Handles the possibility of switching between +// the non-stack layer of shields thoroughly, +// then adds the desired one. +// +void P_SwitchShield(player_t *player, UINT16 shieldtype) +{ + boolean donthavealready = (shieldtype & SH_FORCE) + ? (!(player->powers[pw_shield] & SH_FORCE) || (player->powers[pw_shield] & SH_FORCEHP) < (shieldtype & ~SH_FORCE)) + : ((player->powers[pw_shield] & SH_NOSTACK) != shieldtype); + + if (donthavealready) + { + boolean stopshieldability = (shieldtype & SH_FORCE) + ? (!(player->powers[pw_shield] & SH_FORCE)) + : true; + + // Just in case. + if (stopshieldability && player->pflags & PF_SHIELDABILITY) + { + player->pflags &= ~(PF_SPINNING|PF_SHIELDABILITY); // They'll still have PF_THOKKED... + player->homing = 0; + } + + player->powers[pw_shield] = shieldtype|(player->powers[pw_shield] & SH_STACK); + P_SpawnShieldOrb(player); + + if (shieldtype & SH_PROTECTWATER) + { + if (player->powers[pw_underwater] && player->powers[pw_underwater] <= 12*TICRATE + 1) + P_RestoreMusic(player); + + player->powers[pw_underwater] = 0; + + if (player->powers[pw_spacetime] > 1) + { + player->powers[pw_spacetime] = 0; + P_RestoreMusic(player); + } + } + } +} + // // P_SpawnGhostMobj // @@ -1532,6 +1624,12 @@ void P_SpawnSpinMobj(player_t *player, mobjtype_t type) // scale P_SetScale(mobj, player->mo->scale); mobj->destscale = player->mo->scale; + + if (type == MT_THOK) // spintrail-specific modification for MT_THOK + { + mobj->frame = FF_TRANS70; + mobj->fuse = mobj->tics; + } } P_SetTarget(&mobj->target, player->mo); // the one thing P_SpawnGhostMobj doesn't do @@ -2093,7 +2191,7 @@ static void P_CheckInvincibilityTimer(player_t *player) { if (mariomode) { - if (player->powers[pw_shield] & SH_FIREFLOWER) + if ((player->powers[pw_shield] & SH_STACK) == SH_FIREFLOWER) { player->mo->color = SKINCOLOR_WHITE; G_GhostAddColor(GHC_FIREFLOWER); @@ -2130,7 +2228,7 @@ static void P_DoBubbleBreath(player_t *player) fixed_t z = player->mo->z; mobj_t *bubble = NULL; - if (!(player->mo->eflags & MFE_UNDERWATER) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL && !(player->pflags & PF_NIGHTSMODE)) || player->spectator) + if (!(player->mo->eflags & MFE_UNDERWATER) || ((player->powers[pw_shield] & SH_PROTECTWATER) && !(player->pflags & PF_NIGHTSMODE)) || player->spectator) return; if (player->charflags & SF_MACHINE) @@ -3116,7 +3214,7 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd) if (cmd->buttons & BT_ATTACK || cmd->buttons & BT_FIRENORMAL) { - if (!(player->pflags & PF_ATTACKDOWN) && player->powers[pw_shield] & SH_FIREFLOWER && !player->climbing) + if (!(player->pflags & PF_ATTACKDOWN) && (player->powers[pw_shield] & SH_STACK) == SH_FIREFLOWER && !player->climbing) { player->pflags |= PF_ATTACKDOWN; P_SpawnPlayerMissile(player->mo, MT_FIREBALL, 0); @@ -3129,72 +3227,61 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd) mobj_t *mo = NULL; player->pflags |= PF_ATTACKDOWN; + #define TAKE_AMMO(player, power) \ + player->powers[power]--; \ + if (player->rings < 1) \ + { \ + if (player->powers[power] > 0) \ + player->powers[power]--; \ + } \ + else \ + player->rings--; + if (cmd->buttons & BT_FIRENORMAL) // No powers, just a regular ring. goto firenormal; //code repetition sucks. // Bounce ring else if (player->currentweapon == WEP_BOUNCE && player->powers[pw_bouncering]) { - if (player->health <= 1) - return; + TAKE_AMMO(player, pw_bouncering); P_SetWeaponDelay(player, TICRATE/4); mo = P_SpawnPlayerMissile(player->mo, MT_THROWNBOUNCE, MF2_BOUNCERING); if (mo) mo->fuse = 3*TICRATE; // Bounce Ring time - - player->powers[pw_bouncering]--; - player->mo->health--; - player->health--; } // Rail ring else if (player->currentweapon == WEP_RAIL && player->powers[pw_railring]) { - if (player->health <= 1) - return; + TAKE_AMMO(player, pw_railring); P_SetWeaponDelay(player, (3*TICRATE)/2); mo = P_SpawnPlayerMissile(player->mo, MT_REDRING, MF2_RAILRING|MF2_DONTDRAW); // Rail has no unique thrown object, therefore its sound plays here. S_StartSound(player->mo, sfx_rail1); - - player->powers[pw_railring]--; - player->mo->health--; - player->health--; } // Automatic else if (player->currentweapon == WEP_AUTO && player->powers[pw_automaticring]) { - if (player->health <= 1) - return; + TAKE_AMMO(player, pw_automaticring); player->pflags &= ~PF_ATTACKDOWN; P_SetWeaponDelay(player, 2); mo = P_SpawnPlayerMissile(player->mo, MT_THROWNAUTOMATIC, MF2_AUTOMATIC); - - player->powers[pw_automaticring]--; - player->mo->health--; - player->health--; } // Explosion else if (player->currentweapon == WEP_EXPLODE && player->powers[pw_explosionring]) { - if (player->health <= 1) - return; + TAKE_AMMO(player, pw_explosionring); P_SetWeaponDelay(player, (3*TICRATE)/2); mo = P_SpawnPlayerMissile(player->mo, MT_THROWNEXPLOSION, MF2_EXPLOSION); - - player->powers[pw_explosionring]--; - player->mo->health--; - player->health--; } // Grenade else if (player->currentweapon == WEP_GRENADE && player->powers[pw_grenadering]) { - if (player->health <= 1) - return; + TAKE_AMMO(player, pw_grenadering); P_SetWeaponDelay(player, TICRATE/3); mo = P_SpawnPlayerMissile(player->mo, MT_THROWNGRENADE, MF2_EXPLOSION); @@ -3204,10 +3291,6 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd) //P_InstaThrust(mo, player->mo->angle, FixedMul(mo->info->speed, player->mo->scale)); mo->fuse = mo->info->mass; } - - player->powers[pw_grenadering]--; - player->mo->health--; - player->health--; } // Scatter // Note: Ignores MF2_RAILRING @@ -3217,8 +3300,7 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd) angle_t shotangle = player->mo->angle; angle_t oldaiming = player->aiming; - if (player->health <= 1) - return; + TAKE_AMMO(player, pw_scatterring); P_SetWeaponDelay(player, (2*TICRATE)/3); // Center @@ -3244,10 +3326,6 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd) player->mo->z = oldz; player->aiming = oldaiming; - - player->powers[pw_scatterring]--; - player->mo->health--; - player->health--; return; } // No powers, just a regular ring. @@ -3271,7 +3349,7 @@ firenormal: // Red Ring else { - if (player->health <= 1) + if (player->rings <= 0) return; P_SetWeaponDelay(player, TICRATE/4); @@ -3280,11 +3358,12 @@ firenormal: if (mo) P_ColorTeamMissile(mo, player); - player->mo->health--; - player->health--; + player->rings--; } } + #undef TAKE_AMMO + if (mo) { if (mo->flags & MF_MISSILE && mo->flags2 & MF2_RAILRING) @@ -3335,7 +3414,7 @@ static void P_DoSuperStuff(player_t *player) return; // NiGHTS Super doesn't mix with normal super // Does player have all emeralds? If so, flag the "Ready For Super!" - if ((ALL7EMERALDS(emeralds) || ALL7EMERALDS(player->powers[pw_emeralds])) && player->health > 50) + if (ALL7EMERALDS(emeralds) && player->rings >= 50) player->pflags |= PF_SUPERREADY; else player->pflags &= ~PF_SUPERREADY; @@ -3343,7 +3422,7 @@ static void P_DoSuperStuff(player_t *player) if (player->powers[pw_super]) { // If you're super and not Sonic, de-superize! - if (!((ALL7EMERALDS(emeralds)) && (player->charflags & SF_SUPER)) && !(ALL7EMERALDS(player->powers[pw_emeralds]))) + if (!(ALL7EMERALDS(emeralds) && player->charflags & SF_SUPER)) { player->powers[pw_super] = 0; P_SetPlayerMobjState(player->mo, S_PLAY_STND); @@ -3351,7 +3430,7 @@ static void P_DoSuperStuff(player_t *player) P_SpawnShieldOrb(player); // Restore color - if (player->powers[pw_shield] & SH_FIREFLOWER) + if ((player->powers[pw_shield] & SH_NOSTACK) == SH_FIREFLOWER) { player->mo->color = SKINCOLOR_WHITE; G_GhostAddColor(GHC_FIREFLOWER); @@ -3373,10 +3452,7 @@ static void P_DoSuperStuff(player_t *player) // Deplete one ring every second while super if ((leveltime % TICRATE == 0) && !(player->exiting)) - { - player->health--; - player->mo->health--; - } + player->rings--; player->mo->color = (player->pflags & PF_GODMODE && cv_debug == 0) ? (SKINCOLOR_SUPERSILVER1 + 5*((leveltime >> 1) % 7)) // A wholesome easter egg. @@ -3393,7 +3469,7 @@ static void P_DoSuperStuff(player_t *player) G_GhostAddColor(GHC_SUPER); // Ran out of rings while super! - if (player->health <= 1 || player->exiting) + if (player->rings <= 0 || player->exiting) { player->powers[pw_emeralds] = 0; // lost the power stones P_SpawnGhostMobj(player->mo); @@ -3401,7 +3477,7 @@ static void P_DoSuperStuff(player_t *player) player->powers[pw_super] = 0; // Restore color - if (player->powers[pw_shield] & SH_FIREFLOWER) + if ((player->powers[pw_shield] & SH_NOSTACK) == SH_FIREFLOWER) { player->mo->color = SKINCOLOR_WHITE; G_GhostAddColor(GHC_FIREFLOWER); @@ -3450,12 +3526,6 @@ static void P_DoSuperStuff(player_t *player) P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); break; } - - if (!player->exiting) - { - player->health = 1; - player->mo->health = 1; - } } // Inform the netgame that the champion has fallen in the heat of battle. @@ -3483,12 +3553,12 @@ static void P_DoSuperStuff(player_t *player) // boolean P_SuperReady(player_t *player) { - if ((player->pflags & PF_SUPERREADY) && !player->powers[pw_super] && !player->powers[pw_tailsfly] + if (player->pflags & PF_SUPERREADY && !player->powers[pw_super] && !player->powers[pw_tailsfly] && !(player->powers[pw_shield] & SH_NOSTACK) && !player->powers[pw_invulnerability] && !(maptol & TOL_NIGHTS) // don't turn 'regular super' in nights levels && player->pflags & PF_JUMPED - && ((player->charflags & SF_SUPER) || ALL7EMERALDS(player->powers[pw_emeralds]))) + && player->charflags & SF_SUPER) return true; return false; @@ -3667,6 +3737,35 @@ void P_DoJump(player_t *player, boolean soundandstate) } } +static void P_DoSpinDashDust(player_t *player) +{ + UINT32 i; + mobj_t *particle; + INT32 prandom[3]; + for (i = 0; i <= (leveltime%7)/2; i++) { // 1, 2, 3 or 4 particles + particle = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_SPINDUST); + + if (player->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) // overrides fire version + P_SetMobjState(particle, S_SPINDUST_BUBBLE1); + else if (player->powers[pw_shield] == SH_ELEMENTAL) + P_SetMobjState(particle, S_SPINDUST_FIRE1); + + P_SetTarget(&particle->target, player->mo); + particle->destscale = (2*player->mo->scale)/3; + P_SetScale(particle, particle->destscale); + if (player->mo->eflags & MFE_VERTICALFLIP) // readjust z position if needed + particle->z = player->mo->z + player->mo->height - particle->height; + prandom[0] = P_RandomFixed()<<2; // P_RandomByte()<<10 + prandom[1] = P_RandomRange(-30, 30); // P_RandomRange(-ANG30/FRACUNIT, ANG30/FRACUNIT)*FRACUNIT + prandom[2] = P_RandomFixed()<<3; // P_RandomByte()<<11 + P_SetObjectMomZ(particle, player->dashspeed/50 + prandom[0], false); + P_InstaThrust(particle, + player->mo->angle + (prandom[1]*ANG1), + -FixedMul(player->dashspeed/12 + FRACUNIT + prandom[2], player->mo->scale)); + P_TryMove(particle, particle->x+particle->momx, particle->y+particle->momy, true); + } +} + // // P_DoSpinAbility // @@ -3674,6 +3773,7 @@ void P_DoJump(player_t *player, boolean soundandstate) // static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) { + boolean canstand = true; // can we stand on the ground? (mostly relevant for slopes) if (player->pflags & PF_STASIS) return; @@ -3685,69 +3785,92 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) } #endif - // Spinning and Spindashing - if ((player->charability2 == CA2_SPINDASH) && !(player->pflags & PF_SLIDING) && !player->exiting - && !P_PlayerInPain(player)) // subsequent revs - { - if ((cmd->buttons & BT_USE) && player->speed < FixedMul(5<<FRACBITS, player->mo->scale) && !player->mo->momz && onground && !(player->pflags & PF_USEDOWN) && !(player->pflags & PF_SPINNING) #ifdef ESLOPE - && (!player->mo->standingslope || (player->mo->standingslope->flags & SL_NOPHYSICS) || abs(player->mo->standingslope->zdelta) < FRACUNIT/2) + canstand = (!player->mo->standingslope || (player->mo->standingslope->flags & SL_NOPHYSICS) || abs(player->mo->standingslope->zdelta) < FRACUNIT/2); #endif - ) - { - player->mo->momx = player->cmomx; - player->mo->momy = player->cmomy; - player->pflags |= PF_STARTDASH|PF_SPINNING; - player->dashspeed = player->mindash; - P_SetPlayerMobjState(player->mo, S_PLAY_DASH); - player->pflags |= PF_USEDOWN; - if (!player->spectator) - S_StartSound(player->mo, sfx_s3kab); // Make the rev sound! Previously sfx_spndsh. - } - else if ((cmd->buttons & BT_USE) && (player->pflags & PF_STARTDASH)) - { - if (player->dashspeed < player->maxdash) - { -#define chargecalculation (6*(player->dashspeed - player->mindash))/(player->maxdash - player->mindash) - fixed_t soundcalculation = chargecalculation; - player->dashspeed += FRACUNIT; - if (!player->spectator && soundcalculation != chargecalculation) - S_StartSound(player->mo, sfx_s3kab); // Make the rev sound! Previously sfx_spndsh. -#undef chargecalculation - } - if (player->revitem && !(leveltime % 5)) // Now spawn the color thok circle. - { - P_SpawnSpinMobj(player, player->revitem); - if (demorecording) - G_GhostAddRev(); - } - } - // If not moving up or down, and travelling faster than a speed of four while not holding - // down the spin button and not spinning. - // AKA Just go into a spin on the ground, you idiot. ;) - else if ((cmd->buttons & BT_USE || ((twodlevel || (player->mo->flags2 & MF2_TWOD)) && cmd->forwardmove < -20)) - && !player->climbing && !player->mo->momz && onground && (player->speed > FixedMul(5<<FRACBITS, player->mo->scale) -#ifdef ESLOPE - || (player->mo->standingslope && (!(player->mo->standingslope->flags & SL_NOPHYSICS)) && abs(player->mo->standingslope->zdelta) >= FRACUNIT/2) -#endif - ) && !(player->pflags & PF_USEDOWN) && !(player->pflags & PF_SPINNING)) + /////////////////////////////// + // ability-specific behavior // + /////////////////////////////// + if (!(player->pflags & PF_SLIDING) && !player->exiting && !P_PlayerInPain(player)) + { + switch (player->charability2) { - player->pflags |= PF_SPINNING; - P_SetPlayerMobjState(player->mo, S_PLAY_SPIN); - if (!player->spectator) - S_StartSound(player->mo, sfx_spin); - player->pflags |= PF_USEDOWN; + case CA2_SPINDASH: // Spinning and Spindashing + // Start revving + if ((cmd->buttons & BT_USE) && player->speed < FixedMul(5<<FRACBITS, player->mo->scale) + && !player->mo->momz && onground && !(player->pflags & (PF_USEDOWN|PF_SPINNING)) + && canstand) + { + player->mo->momx = player->cmomx; + player->mo->momy = player->cmomy; + player->pflags |= PF_STARTDASH|PF_SPINNING; + player->dashspeed = player->mindash; + P_SetPlayerMobjState(player->mo, S_PLAY_DASH); + player->pflags |= PF_USEDOWN; + if (!player->spectator) + S_StartSound(player->mo, sfx_s3kab); // Make the rev sound! Previously sfx_spndsh. + } + // Revving + else if ((cmd->buttons & BT_USE) && (player->pflags & PF_STARTDASH)) + { + if (player->dashspeed < player->maxdash) + { +#define chargecalculation (6*(player->dashspeed - player->mindash))/(player->maxdash - player->mindash) + fixed_t soundcalculation = chargecalculation; + player->dashspeed += FRACUNIT; + if (!player->spectator && soundcalculation != chargecalculation) + S_StartSound(player->mo, sfx_s3kab); // Make the rev sound! Previously sfx_spndsh. +#undef chargecalculation + } + if (player->revitem && !(leveltime % 5)) // Now spawn the color thok circle. + { + P_SpawnSpinMobj(player, player->revitem); + if (demorecording) + G_GhostAddRev(); + } + } + + // If not moving up or down, and travelling faster than a speed of four while not holding + // down the spin button and not spinning. + // AKA Just go into a spin on the ground, you idiot. ;) + else if ((cmd->buttons & BT_USE || ((twodlevel || (player->mo->flags2 & MF2_TWOD)) && cmd->forwardmove < -20)) + && !player->climbing && !player->mo->momz && onground && (player->speed > FixedMul(5<<FRACBITS, player->mo->scale) + || !canstand) && !(player->pflags & (PF_USEDOWN|PF_SPINNING))) + { + player->pflags |= PF_SPINNING; + P_SetPlayerMobjState(player->mo, S_PLAY_SPIN); + if (!player->spectator) + S_StartSound(player->mo, sfx_spin); + player->pflags |= PF_USEDOWN; + } + break; + case CA2_MELEE: // Melee attack + if (!(player->panim == PA_ABILITY2) && (cmd->buttons & BT_USE) && player->speed < FixedMul(10<<FRACBITS, player->mo->scale) + && !player->mo->momz && onground && !(player->pflags & PF_USEDOWN) + && canstand) + { + P_ResetPlayer(player); + player->mo->z += P_MobjFlip(player->mo); + player->mo->momx = player->cmomx = 0; + player->mo->momy = player->cmomy = 0; + P_SetObjectMomZ(player->mo, player->mindash, false); + P_InstaThrust(player->mo, player->mo->angle, FixedMul(player->maxdash, player->mo->scale)); + P_SetPlayerMobjState(player->mo, S_PLAY_MELEE); + player->pflags |= PF_USEDOWN; + S_StartSound(player->mo, sfx_s3k8b); + } + break; } } + /////////////////////////////// + // general spinning behavior // + /////////////////////////////// + // Rolling normally if (onground && player->pflags & PF_SPINNING && !(player->pflags & PF_STARTDASH) - && player->speed < FixedMul(5*FRACUNIT,player->mo->scale) -#ifdef ESLOPE - && (!player->mo->standingslope || (player->mo->standingslope->flags & SL_NOPHYSICS) || abs(player->mo->standingslope->zdelta) < FRACUNIT/2) -#endif - ) + && player->speed < FixedMul(5*FRACUNIT,player->mo->scale) && canstand) { if (GETSECSPECIAL(player->mo->subsector->sector->special, 4) == 7 || (player->mo->ceilingz - player->mo->floorz < P_GetPlayerHeight(player))) P_InstaThrust(player->mo, player->mo->angle, FixedMul(10*FRACUNIT, player->mo->scale)); @@ -3792,29 +3915,12 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) { if (player->mo->state-states != S_PLAY_DASH) P_SetPlayerMobjState(player->mo, S_PLAY_DASH); + // Spawn spin dash dust + if (!(player->charflags & SF_NOSPINDASHDUST) && !(player->mo->eflags & MFE_GOOWATER)) + P_DoSpinDashDust(player); } else if (onground && player->pflags & PF_SPINNING && !(player->panim == PA_ROLL)) P_SetPlayerMobjState(player->mo, S_PLAY_SPIN); - - // Melee attack - if ((player->charability2 == CA2_MELEE) && !(player->panim == PA_ABILITY2) && !player->exiting - && !P_PlayerInPain(player) && (cmd->buttons & BT_USE) && player->speed < FixedMul(10<<FRACBITS, player->mo->scale) - && !player->mo->momz && onground && !(player->pflags & PF_USEDOWN) -#ifdef ESLOPE - && (!player->mo->standingslope || (player->mo->standingslope->flags & SL_NOPHYSICS) || abs(player->mo->standingslope->zdelta) < FRACUNIT/2) -#endif - ) - { - P_ResetPlayer(player); - player->mo->z += P_MobjFlip(player->mo); - player->mo->momx = player->cmomx = 0; - player->mo->momy = player->cmomy = 0; - P_SetObjectMomZ(player->mo, player->mindash, false); - P_InstaThrust(player->mo, player->mo->angle, FixedMul(player->maxdash, player->mo->scale)); - P_SetPlayerMobjState(player->mo, S_PLAY_MELEE); - player->pflags |= PF_USEDOWN; - S_StartSound(player->mo, sfx_s3k8b); - } } // @@ -3824,18 +3930,59 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) // void P_DoJumpShield(player_t *player) { + boolean electric = ((player->powers[pw_shield] & SH_PROTECTELECTRIC) == SH_PROTECTELECTRIC); + if (player->pflags & PF_THOKKED) return; player->pflags &= ~PF_JUMPED; P_DoJump(player, false); - player->pflags &= ~PF_JUMPED; - player->secondjump = 0; player->jumping = 0; - player->pflags |= PF_THOKKED; + player->secondjump = 0; + player->pflags |= PF_THOKKED|PF_SHIELDABILITY; player->pflags &= ~PF_SPINNING; - P_SetPlayerMobjState(player->mo, S_PLAY_FALL); - S_StartSound(player->mo, sfx_wdjump); + if (electric) + { + mobj_t *spark; + INT32 i; +#define numangles 6 +#define limitangle (360/numangles) + angle_t travelangle = player->mo->angle + P_RandomRange(-limitangle, limitangle)*ANG1; + for (i = 0; i < numangles; i++) + { + spark = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_THUNDERCOIN_SPARK); + P_InstaThrust(spark, travelangle + i*(ANGLE_MAX/numangles), FixedMul(4*FRACUNIT, spark->scale)); + if (i % 2) + P_SetObjectMomZ(spark, -4*FRACUNIT, false); + } +#undef limitangle +#undef numangles + S_StartSound(player->mo, sfx_s3k45); + } + else + { + player->pflags &= ~PF_JUMPED; + P_SetPlayerMobjState(player->mo, S_PLAY_FALL); + S_StartSound(player->mo, sfx_wdjump); + } +} + +// +// P_DoBubbleBounce +// +// Bubblewrap shield landing handling +// +void P_DoBubbleBounce(player_t *player) +{ + player->pflags &= ~(PF_JUMPED|PF_SHIELDABILITY); + S_StartSound(player->mo, sfx_s3k44); + P_DoJump(player, false); + if (player->charflags & SF_NOJUMPSPIN) + P_SetPlayerMobjState(player->mo, S_PLAY_FALL); + player->pflags |= PF_THOKKED; + player->jumping = 0; + player->secondjump = UINT8_MAX; + player->mo->momz = FixedMul(player->mo->momz, 5*FRACUNIT/4); } // @@ -3906,6 +4053,10 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) {} else if (onground || player->climbing || (player->mo->tracer && player->powers[pw_carry])) {} + else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_WHIRLWIND + && !(player->pflags & PF_JUMPED) + && !(player->pflags & PF_USEDOWN)) + P_DoJumpShield(player); else if (!(player->pflags & PF_SLIDING) && ((gametype != GT_CTF) || (!player->gotflag))) { #ifdef HAVE_BLUA @@ -4048,7 +4199,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) if (player->charability == CA_HOMINGTHOK && !player->homing) { - if (P_LookForEnemies(player)) + if (P_LookForEnemies(player, true)) { if (player->mo->tracer) player->homing = 3*TICRATE; @@ -4085,13 +4236,6 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) player->pflags |= PF_GLIDING|PF_THOKKED; player->glidetime = 0; - if (player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds])) - { - // Glide at double speed while super. - glidespeed *= 2; - player->pflags &= ~PF_THOKKED; - } - P_SetPlayerMobjState(player->mo, S_PLAY_GLIDE); P_InstaThrust(player->mo, player->mo->angle, FixedMul(glidespeed, player->mo->scale)); player->pflags &= ~(PF_SPINNING|PF_STARTDASH); @@ -4183,7 +4327,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) break; } } - else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_JUMP && !player->powers[pw_super]) + else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_WHIRLWIND && !player->powers[pw_super]) P_DoJumpShield(player); } @@ -4216,8 +4360,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) player->pflags &= ~PF_JUMPDOWN; // Repeat abilities, but not double jump! - if ((player->charability2 == CA2_MULTIABILITY && player->charability != CA_DOUBLEJUMP) - || (player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))) + if (player->charability2 == CA2_MULTIABILITY && player->charability != CA_DOUBLEJUMP) player->secondjump = 0; else if (player->charability == CA_FLOAT && player->secondjump == 1) player->secondjump = 2; @@ -4461,9 +4604,6 @@ static void P_2dMovement(player_t *player) if (cmd->forwardmove != 0) P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT,10*FRACUNIT), false); - if (player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds])) - player->mo->momz *= 2; - player->mo->momx = 0; } else if (cmd->sidemove != 0 && !(player->pflags & PF_GLIDING || player->exiting @@ -4657,15 +4797,14 @@ static void P_3dMovement(player_t *player) acceleration = player->accelstart + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration; } + if (player->mo->movefactor != FRACUNIT) // Friction-scaled acceleration... + acceleration = FixedMul(acceleration<<FRACBITS, player->mo->movefactor)>>FRACBITS; + // Forward movement if (player->climbing) { if (cmd->forwardmove) - { P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT, 10*FRACUNIT), false); - if (player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds])) - player->mo->momz *= 2; - } } else if (!analogmove && cmd->forwardmove != 0 && !(player->pflags & PF_GLIDING || player->exiting @@ -4699,12 +4838,7 @@ static void P_3dMovement(player_t *player) } // Sideways movement if (player->climbing) - { - if (player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds])) - P_InstaThrust(player->mo, player->mo->angle-ANGLE_90, FixedMul(FixedDiv(cmd->sidemove*FRACUNIT, 5*FRACUNIT), player->mo->scale)); - else - P_InstaThrust(player->mo, player->mo->angle-ANGLE_90, FixedMul(FixedDiv(cmd->sidemove*FRACUNIT, 10*FRACUNIT), player->mo->scale)); - } + P_InstaThrust(player->mo, player->mo->angle-ANGLE_90, FixedMul(FixedDiv(cmd->sidemove*FRACUNIT, 10*FRACUNIT), player->mo->scale)); // Analog movement control else if (analogmove) { @@ -5433,12 +5567,10 @@ static void P_DoNiGHTSCapsule(player_t *player) if (G_IsSpecialStage(gamemap)) { // In special stages, share rings. Everyone gives up theirs to the capsule player always, because we can't have any individualism here! for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && (&players[i] != player) && players[i].mo->health > 1) + if (playeringame[i] && (&players[i] != player) && players[i].rings > 0) { - player->mo->health += players[i].mo->health-1; - player->health = player->mo->health; - players[i].mo->health = 1; - players[i].health = players[i].mo->health; + player->rings += players[i].rings; + players[i].rings = 0; } } @@ -5447,10 +5579,9 @@ static void P_DoNiGHTSCapsule(player_t *player) && player->mo->y == player->capsule->y && player->mo->z == player->capsule->z+(player->capsule->height/3)) { - if (player->mo->health > 1) + if (player->rings > 0) { - player->mo->health--; - player->health--; + player->rings--; player->capsule->health--; player->capsule->extravalue1++; @@ -5518,11 +5649,13 @@ static void P_DoNiGHTSCapsule(player_t *player) } else { - fixed_t z; - - z = player->capsule->z + player->capsule->height/2; for (i = 0; i < 16; i++) - P_SpawnMobj(player->capsule->x, player->capsule->y, z, MT_BIRD); + { + mobj_t *flicky = P_InternalFlickySpawn(player->capsule, 0, ((i%4) + 1)*2*FRACUNIT, true); + flicky->z += player->capsule->height/2; + flicky->angle = (i*(ANGLE_MAX/16)); + P_InstaThrust(flicky, flicky->angle, 8*FRACUNIT); + } } for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].mare == player->mare) @@ -6142,7 +6275,7 @@ static void P_PlayerDropWeapon(player_t *player) if (mo) { - player->mo->health--; + player->rings--; P_InstaThrust(mo, player->mo->angle-ANGLE_180, 8*FRACUNIT); P_SetObjectMomZ(mo, 4*FRACUNIT, false); mo->flags2 |= MF2_DONTRESPAWN; @@ -6167,7 +6300,7 @@ void P_BlackOw(player_t *player) player->powers[pw_shield] = player->powers[pw_shield] & SH_STACK; } -void P_ElementalFireTrail(player_t *player) +void P_ElementalFire(player_t *player, boolean cropcircle) { fixed_t newx; fixed_t newy; @@ -6185,40 +6318,65 @@ void P_ElementalFireTrail(player_t *player) else ground = player->mo->floorz; - travelangle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy); - - for (i = 0; i < 2; i++) + if (cropcircle) { - newx = player->mo->x + P_ReturnThrustX(player->mo, travelangle + ((i&1) ? -1 : 1)*ANGLE_135, FixedMul(24*FRACUNIT, player->mo->scale)); - newy = player->mo->y + P_ReturnThrustY(player->mo, travelangle + ((i&1) ? -1 : 1)*ANGLE_135, FixedMul(24*FRACUNIT, player->mo->scale)); -#ifdef ESLOPE - if (player->mo->standingslope) +#define numangles 8 +#define limitangle (180/numangles) + travelangle = player->mo->angle + P_RandomRange(-limitangle, limitangle)*ANG1; + for (i = 0; i < numangles; i++) { - ground = P_GetZAt(player->mo->standingslope, newx, newy); - if (player->mo->eflags & MFE_VERTICALFLIP) - ground -= FixedMul(mobjinfo[MT_SPINFIRE].height, player->mo->scale); + flame = P_SpawnMobj(player->mo->x, player->mo->y, ground, MT_SPINFIRE); + flame->flags &= ~MF_NOGRAVITY; + P_SetTarget(&flame->target, player->mo); + flame->angle = travelangle + i*(ANGLE_MAX/numangles); + flame->fuse = TICRATE*7; // takes about an extra second to hit the ground + flame->destscale = player->mo->scale; + P_SetScale(flame, player->mo->scale); + flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); + P_InstaThrust(flame, flame->angle, FixedMul(3*FRACUNIT, flame->scale)); + P_SetObjectMomZ(flame, 3*FRACUNIT, false); } -#endif - flame = P_SpawnMobj(newx, newy, ground, MT_SPINFIRE); - P_SetTarget(&flame->target, player->mo); - flame->angle = travelangle; - flame->fuse = TICRATE*6; - flame->destscale = player->mo->scale; - P_SetScale(flame, player->mo->scale); - flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); - - flame->momx = 8; - P_XYMovement(flame); - if (P_MobjWasRemoved(flame)) - continue; - - if (player->mo->eflags & MFE_VERTICALFLIP) +#undef limitangle +#undef numangles + } + else + { + travelangle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy); + for (i = 0; i < 2; i++) { - if (flame->z + flame->height < flame->ceilingz) + + newx = player->mo->x + P_ReturnThrustX(player->mo, (travelangle + ((i&1) ? -1 : 1)*ANGLE_135), FixedMul(24*FRACUNIT, player->mo->scale)); + newy = player->mo->y + P_ReturnThrustY(player->mo, (travelangle + ((i&1) ? -1 : 1)*ANGLE_135), FixedMul(24*FRACUNIT, player->mo->scale)); + +#ifdef ESLOPE + if (player->mo->standingslope) + { + ground = P_GetZAt(player->mo->standingslope, newx, newy); + if (player->mo->eflags & MFE_VERTICALFLIP) + ground -= FixedMul(mobjinfo[MT_SPINFIRE].height, player->mo->scale); + } +#endif + flame = P_SpawnMobj(newx, newy, ground, MT_SPINFIRE); + P_SetTarget(&flame->target, player->mo); + flame->angle = travelangle; + flame->fuse = TICRATE*6; + flame->destscale = player->mo->scale; + P_SetScale(flame, player->mo->scale); + flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); + + flame->momx = 8; // this is a hack which is used to ensure it still behaves as a missile and can damage others + P_XYMovement(flame); + if (P_MobjWasRemoved(flame)) + continue; + + if (player->mo->eflags & MFE_VERTICALFLIP) + { + if (flame->z + flame->height < flame->ceilingz) + P_RemoveMobj(flame); + } + else if (flame->z > flame->floorz) P_RemoveMobj(flame); } - else if (flame->z > flame->floorz) - P_RemoveMobj(flame); } } @@ -6298,7 +6456,7 @@ static void P_SkidStuff(player_t *player) // If your push angle is more than this close to a full 180 degrees, trigger a skid. if (dang > ANGLE_157h) { - player->skidtime = TICRATE/2; + player->skidtime = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS; S_StartSound(player->mo, sfx_skid); if (player->panim != PA_WALK) P_SetPlayerMobjState(player->mo, S_PLAY_WALK); @@ -6335,6 +6493,9 @@ static void P_MovePlayer(player_t *player) cmd = &player->cmd; runspd = FixedMul(player->runspeed, player->mo->scale); + // Let's have some movement speed fun on low-friction surfaces, JUST for players... (high friction surfaces shouldn't have any adjustment, since the acceleration in this game is super high and that ends up cheesing high-friction surfaces.) + runspd = FixedMul(runspd, player->mo->movefactor); + // Control relinquishing stuff! if (player->powers[pw_ingoop]) player->pflags |= PF_FULLSTASIS; @@ -6445,7 +6606,7 @@ static void P_MovePlayer(player_t *player) if (playeringame[i]) players[i].exiting = (14*TICRATE)/5 + 1; } - else if (player->health > 1) + else if (player->rings > 0) P_DamageMobj(player->mo, NULL, NULL, 1, 0); player->pflags &= ~PF_NIGHTSFALL; } @@ -6512,7 +6673,7 @@ static void P_MovePlayer(player_t *player) P_SetPlayerMobjState(player->mo, S_PLAY_WALK); } - // If Springing (or nojumpspinning), but travelling DOWNWARD, change back! (nojumpspin also turns to fall once PF_THOKKED is added.) + // If Springing (or nojumpspinning), but travelling DOWNWARD, change back! if ((player->panim == PA_SPRING && P_MobjFlip(player->mo)*player->mo->momz < 0) || ((((player->charflags & SF_NOJUMPSPIN) && (player->pflags & PF_JUMPED) && player->panim == PA_JUMP)) && (P_MobjFlip(player->mo)*player->mo->momz < 0))) @@ -6525,6 +6686,7 @@ static void P_MovePlayer(player_t *player) if (!player->mo->momx && !player->mo->momy && !player->mo->momz && player->panim == PA_WALK) P_SetPlayerMobjState(player->mo, S_PLAY_STND); + player->mo->movefactor = FRACUNIT; // We're not going to do any more with this, so let's change it back for the next frame. ////////////////// //GAMEPLAY STUFF// @@ -6602,8 +6764,8 @@ static void P_MovePlayer(player_t *player) P_ResetPlayer(player); // down, stop gliding. if (onground) P_SetPlayerMobjState(player->mo, S_PLAY_WALK); - else if ((player->charability2 == CA2_MULTIABILITY) - || (player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]) && player->charability == CA_GLIDEANDCLIMB)) + else if (player->charability2 == CA2_MULTIABILITY + && player->charability == CA_GLIDEANDCLIMB) { player->pflags |= PF_JUMPED; P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); @@ -6746,7 +6908,7 @@ static void P_MovePlayer(player_t *player) P_ResetScore(player); // Show the "THOK!" graphic when spinning quickly across the ground. (even applies to non-spinners, in the case of zoom tubes) - if (player->pflags & PF_SPINNING && player->speed > FixedMul(15<<FRACBITS, player->mo->scale) && !(player->pflags & PF_JUMPED)) + if (player->pflags & PF_SPINNING && P_AproxDistance(player->speed, player->mo->momz) > FixedMul(15<<FRACBITS, player->mo->scale) && !(player->pflags & PF_JUMPED)) { P_SpawnSpinMobj(player, player->spinitem); if (demorecording) @@ -6768,7 +6930,7 @@ static void P_MovePlayer(player_t *player) if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL && (player->pflags & PF_SPINNING) && player->speed > FixedMul(4<<FRACBITS, player->mo->scale) && onground && (leveltime & 1) && !(player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))) - P_ElementalFireTrail(player); + P_ElementalFire(player, false); P_DoSpinAbility(player, cmd); @@ -6836,56 +6998,121 @@ static void P_MovePlayer(player_t *player) localangle2 = player->mo->angle; } - /////////////////////////// - //BOMB SHIELD ACTIVATION,// - //HOMING, AND OTHER COOL // - //STUFF! // - /////////////////////////// + ////////////////// + //SHIELD ACTIVES// + //& SUPER FLOAT!// + ////////////////// - if (cmd->buttons & BT_USE) // Spin button effects + if (player->pflags & PF_JUMPED && !player->exiting && player->mo->health) { - if (player->pflags & PF_JUMPED) // If the player is jumping + if (cmd->buttons & BT_USE) // Spin button effects { - if (!(player->pflags & PF_USEDOWN)) // If the player is not holding down BT_USE + if (player->powers[pw_super]) // Super can't use shield actives, only passives { - // Jump shield activation - if (!P_PlayerInPain(player) // If the player is not in pain - && !player->climbing // If the player is not climbing - && !(player->pflags & (PF_GLIDING|PF_SLIDING|PF_THOKKED)) // If the player is not gliding or sliding and hasn't used their ability - && !onground) // If the player isn't on the ground + if ((player->charability == CA_THOK) // Super Sonic float + && (player->speed > 5*player->mo->scale) // FixedMul(5<<FRACBITS, player->mo->scale), but scale is FRACUNIT-based + && (P_MobjFlip(player->mo)*player->mo->momz <= 0)) { - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_JUMP && !player->powers[pw_super]) - P_DoJumpShield(player); - else if (player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]) && player->charability == CA_FLY) - { - P_DoJumpShield(player); - player->mo->momz *= 2; - } - } - // Bomb shield activation - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_BOMB) - { - // Don't let Super Sonic or invincibility use it - if (!(player->powers[pw_super] || player->powers[pw_invulnerability])) - P_BlackOw(player); + if (player->panim == PA_PAIN || player->panim == PA_JUMP || player->panim == PA_FALL + || (player->panim == PA_WALK && player->mo->state-states != S_PLAY_SUPER_FLOAT)) + P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_FLOAT); + + player->mo->momz = 0; + player->pflags &= ~PF_SPINNING; + player->jumping = 0; // don't cut jump height after bouncing off something } } - // Super Sonic move - if (player->skin == 0 && player->powers[pw_super] && player->speed > FixedMul(5<<FRACBITS, player->mo->scale) - && P_MobjFlip(player->mo)*player->mo->momz <= 0) + else +#ifdef HAVE_BLUA + if (!LUAh_ShieldSpecial(player)) +#endif { - if (player->panim == PA_ROLL || player->panim == PA_JUMP || player->mo->state-states == S_PLAY_PAIN || player->panim == PA_WALK) - P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_FLOAT); - - player->mo->momz = 0; - player->pflags &= ~PF_SPINNING; - player->jumping = 0; // don't cut jump height after bouncing off something + if (!(player->pflags & (PF_USEDOWN|PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY)) // If the player is not holding down BT_USE, or having used an ability previously + && (!(player->pflags & PF_THOKKED) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP && player->secondjump == UINT8_MAX))) // thokked is optional if you're bubblewrapped + { + // Force shield activation + if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE) + { + player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + player->mo->momx = player->mo->momy = player->mo->momz = 0; + S_StartSound(player->mo, sfx_ngskid); + } + else + { + switch (player->powers[pw_shield] & SH_NOSTACK) + { + // Whirlwind/Thundercoin shield activation + case SH_WHIRLWIND: + case SH_THUNDERCOIN: + P_DoJumpShield(player); + break; + // Armageddon shield activation + case SH_ARMAGEDDON: + player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + P_BlackOw(player); + break; + // Attract shield activation + case SH_ATTRACT: + player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + player->homing = 2; + if (P_LookForEnemies(player, false) && player->mo->tracer) + { + player->pflags |= PF_FORCEJUMPDAMAGE; + P_SetPlayerMobjState(player->mo, S_PLAY_SPIN); + S_StartSound(player->mo, sfx_s3k40); + player->homing = 3*TICRATE; + } + else + S_StartSound(player->mo, sfx_s3ka6); + break; + // Elemental/Bubblewrap shield activation + case SH_ELEMENTAL: + case SH_BUBBLEWRAP: + player->pflags |= PF_FORCEJUMPDAMAGE|PF_THOKKED|PF_SHIELDABILITY; + P_SetPlayerMobjState(player->mo, S_PLAY_SPIN); + player->secondjump = 0; + player->mo->momx = player->mo->momy = 0; + P_SetObjectMomZ(player->mo, -24*FRACUNIT, false); + S_StartSound(player->mo, + ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) + ? sfx_s3k43 + : sfx_s3k44); + break; + // Flame shield activation + case SH_FLAMEAURA: + player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + P_Thrust(player->mo, player->mo->angle, FixedMul(30*FRACUNIT - FixedSqrt(FixedDiv(player->speed, player->mo->scale)), player->mo->scale)); + S_StartSound(player->mo, sfx_s3k43); + default: + break; + } + } + } } } } // HOMING option. - if (player->charability == CA_HOMINGTHOK) + if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT // Sonic 3D Blast. + && player->pflags & PF_SHIELDABILITY) + { + if (player->homing && player->mo->tracer) + { + P_HomingAttack(player->mo, player->mo->tracer); + if (player->mo->tracer->health <= 0 || (player->mo->tracer->flags2 & MF2_FRET)) + { + P_SetObjectMomZ(player->mo, 6*FRACUNIT, false); + if (player->mo->eflags & MFE_UNDERWATER) + player->mo->momz = FixedMul(player->mo->momz, FRACUNIT/3); + player->homing = 0; + } + } + + // If you're not jumping, then you obviously wouldn't be homing. + if (!(player->pflags & PF_JUMPED)) + player->homing = 0; + } + else if (player->charability == CA_HOMINGTHOK) // Sonic Adventure. { // If you've got a target, chase after it! if (player->homing && player->mo->tracer) @@ -7188,13 +7415,6 @@ static void P_DoZoomTube(player_t *player) P_SetTarget(&player->mo->tracer, waypoint); // calculate MOMX/MOMY/MOMZ for next waypoint - // change angle - player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, player->mo->tracer->x, player->mo->tracer->y); - - if (player == &players[consoleplayer]) - localangle = player->mo->angle; - else if (player == &players[secondarydisplayplayer]) - localangle2 = player->mo->angle; // change slope dist = P_AproxDistance(P_AproxDistance(player->mo->tracer->x - player->mo->x, player->mo->tracer->y - player->mo->y), player->mo->tracer->z - player->mo->z); @@ -7214,6 +7434,17 @@ static void P_DoZoomTube(player_t *player) CONS_Debug(DBG_GAMELOGIC, "Next waypoint not found, releasing from track...\n"); } } + + // change angle + if (player->mo->tracer) + { + player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, player->mo->tracer->x, player->mo->tracer->y); + + if (player == &players[consoleplayer]) + localangle = player->mo->angle; + else if (player == &players[secondarydisplayplayer]) + localangle2 = player->mo->angle; + } } // @@ -7457,21 +7688,21 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) mo->flags |= MF_SPECIAL|MF_SHOOTABLE; if (mo->type == MT_EGGGUARD && mo->tracer) //nuke Egg Guard's shield! - P_KillMobj(mo->tracer, inflictor, source, 0); + P_KillMobj(mo->tracer, inflictor, source, DMG_NUKE); if (mo->flags & MF_BOSS || mo->type == MT_PLAYER) //don't OHKO bosses nor players! - P_DamageMobj(mo, inflictor, source, 1, 0); + P_DamageMobj(mo, inflictor, source, 1, DMG_NUKE); else - P_DamageMobj(mo, inflictor, source, 1000, 0); + P_DamageMobj(mo, inflictor, source, 1000, DMG_NUKE); } } // // P_LookForEnemies // Looks for something you can hit - Used for homing attack -// Includes monitors and springs! +// If nonenemies is true, includes monitors and springs! // -boolean P_LookForEnemies(player_t *player) +boolean P_LookForEnemies(player_t *player, boolean nonenemies) { mobj_t *mo; thinker_t *think; @@ -7484,7 +7715,8 @@ boolean P_LookForEnemies(player_t *player) continue; // not a mobj thinker mo = (mobj_t *)think; - if (!(mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR|MF_SPRING))) + if ((nonenemies && !(mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR|MF_SPRING))) + || (!nonenemies && !(mo->flags & (MF_ENEMY|MF_BOSS)))) continue; // not a valid enemy if (mo->health <= 0) // dead @@ -7582,7 +7814,12 @@ void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target ns = FixedMul(source->info->speed, source->scale); } else if (source->player) - ns = FixedDiv(FixedMul(source->player->actionspd, source->scale), 3*FRACUNIT/2); + { + if (source->player->charability == CA_HOMINGTHOK && !(source->player->pflags & PF_SHIELDABILITY)) + ns = FixedDiv(FixedMul(source->player->actionspd, source->scale), 3*FRACUNIT/2); + else + ns = FixedMul(45*FRACUNIT, source->scale); + } source->momx = FixedMul(FixedDiv(enemy->x - source->x, dist), ns); source->momy = FixedMul(FixedDiv(enemy->y - source->y, dist), ns); @@ -8651,7 +8888,7 @@ void P_PlayerThink(player_t *player) #endif // todo: Figure out what is actually causing these problems in the first place... - if ((player->health <= 0 || player->mo->health <= 0) && player->playerstate == PST_LIVE) //you should be DEAD! + if (player->mo->health <= 0 && player->playerstate == PST_LIVE) //you should be DEAD! { CONS_Debug(DBG_GAMELOGIC, "P_PlayerThink: Player %s in PST_LIVE with 0 health. (\"Zombie bug\")\n", sizeu1(playeri)); player->playerstate = PST_DEAD; @@ -8696,8 +8933,13 @@ void P_PlayerThink(player_t *player) if (player->panim != PA_ABILITY) P_SetPlayerMobjState(player->mo, S_PLAY_GLIDE); } - else if ((player->pflags & PF_JUMPED) && !player->powers[pw_super] && player->panim != PA_JUMP && !(player->charflags & SF_NOJUMPSPIN)) - P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); + else if ((player->pflags & PF_JUMPED) && !player->powers[pw_super] && ((player->charflags & SF_NOJUMPSPIN && player->pflags & PF_FORCEJUMPDAMAGE && player->panim != PA_ROLL) || (!(player->charflags & SF_NOJUMPSPIN) && player->panim != PA_JUMP))) + { + if (!(player->charflags & SF_NOJUMPSPIN)) + P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); + else if (player->pflags & PF_FORCEJUMPDAMAGE) + P_SetPlayerMobjState(player->mo, S_PLAY_SPIN); + } if (player->flashcount) player->flashcount--; @@ -8751,7 +8993,7 @@ void P_PlayerThink(player_t *player) // it to the exit, you're a goner! else if (countdown == 1 && !player->exiting && player->lives > 0) { - if (netgame && player->health > 0) + if (netgame && player->mo->health > 0) CONS_Printf(M_GetText("%s ran out of time.\n"), player_names[player-players]); player->pflags |= PF_TIMEOVER; @@ -8840,7 +9082,7 @@ void P_PlayerThink(player_t *player) { player->score = 0; player->mo->health = 1; - player->health = 1; + player->rings = 0; } if ((netgame || multiplayer) && player->lives <= 0) @@ -9013,10 +9255,10 @@ void P_PlayerThink(player_t *player) if (player->powers[pw_flashing] && player->powers[pw_flashing] < UINT16_MAX && ((player->pflags & PF_NIGHTSMODE) || player->powers[pw_flashing] < flashingtics)) player->powers[pw_flashing]--; - if (player->powers[pw_tailsfly] && player->powers[pw_tailsfly] < UINT16_MAX && player->charability != CA_SWIM && !(player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))) // tails fly counter + if (player->powers[pw_tailsfly] && player->powers[pw_tailsfly] < UINT16_MAX && player->charability != CA_SWIM) // tails fly counter player->powers[pw_tailsfly]--; - if (player->powers[pw_underwater] && (player->pflags & PF_GODMODE || (player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL)) + if (player->powers[pw_underwater] && (player->pflags & PF_GODMODE || (player->powers[pw_shield] & SH_PROTECTWATER))) { if (player->powers[pw_underwater] <= 12*TICRATE+1) P_RestoreMusic(player); //incase they were about to drown @@ -9026,7 +9268,7 @@ void P_PlayerThink(player_t *player) else if (player->powers[pw_underwater] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && player->spectator)) // underwater timer player->powers[pw_underwater]--; - if (player->powers[pw_spacetime] && (player->pflags & PF_GODMODE || (player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL)) + if (player->powers[pw_spacetime] && (player->pflags & PF_GODMODE || (player->powers[pw_shield] & SH_PROTECTWATER))) player->powers[pw_spacetime] = 0; else if (player->powers[pw_spacetime] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && player->spectator)) // underwater timer player->powers[pw_spacetime]--; @@ -9329,10 +9571,6 @@ void P_PlayerAfterThink(player_t *player) if (player->currentweapon == WEP_RAIL && (!(player->ringweapons & RW_RAIL) || !player->powers[pw_railring])) player->currentweapon = 0; - // If you're out of rings, but have Infinity Rings left, switch to that. - if (player->currentweapon != 0 && player->health <= 1 && player->powers[pw_infinityring]) - player->currentweapon = 0; - if (P_IsLocalPlayer(player) && (player->pflags & PF_WPNDOWN) && player->currentweapon != oldweapon) S_StartSound(NULL, sfx_wepchg); @@ -9445,7 +9683,7 @@ void P_PlayerAfterThink(player_t *player) player->mo->momy = (player->mo->tracer->y - player->mo->y)*2; player->mo->momz = (player->mo->tracer->z - (player->mo->height-player->mo->tracer->height/2) - player->mo->z)*2; P_TeleportMove(player->mo, player->mo->tracer->x, player->mo->tracer->y, player->mo->tracer->z - (player->mo->height-player->mo->tracer->height/2)); - player->pflags |= PF_JUMPED; + player->pflags |= PF_JUMPED|PF_FORCEJUMPDAMAGE; player->secondjump = 0; player->pflags &= ~PF_THOKKED; diff --git a/src/r_bsp.c b/src/r_bsp.c index 69aa7be29..2562cff66 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -859,6 +859,7 @@ static void R_Subsector(size_t num) static sector_t tempsec; // Deep water hack extracolormap_t *floorcolormap; extracolormap_t *ceilingcolormap; + fixed_t floorcenterz, ceilingcenterz; #ifdef RANGECHECK if (num >= numsubsectors) @@ -879,6 +880,18 @@ static void R_Subsector(size_t num) floorcolormap = ceilingcolormap = frontsector->extra_colormap; + floorcenterz = +#ifdef ESLOPE + frontsector->f_slope ? P_GetZAt(frontsector->f_slope, frontsector->soundorg.x, frontsector->soundorg.y) : +#endif + frontsector->floorheight; + + ceilingcenterz = +#ifdef ESLOPE + frontsector->c_slope ? P_GetZAt(frontsector->c_slope, frontsector->soundorg.x, frontsector->soundorg.y) : +#endif + frontsector->ceilingheight; + // Check and prep all 3D floors. Set the sector floor/ceiling light levels and colormaps. if (frontsector->ffloors) { @@ -891,19 +904,11 @@ static void R_Subsector(size_t num) sub->sector->moved = frontsector->moved = false; } - light = R_GetPlaneLight(frontsector, -#ifdef ESLOPE - frontsector->f_slope ? P_GetZAt(frontsector->f_slope, frontsector->soundorg.x, frontsector->soundorg.y) : -#endif - frontsector->floorheight, false); + light = R_GetPlaneLight(frontsector, floorcenterz, false); if (frontsector->floorlightsec == -1) floorlightlevel = *frontsector->lightlist[light].lightlevel; floorcolormap = frontsector->lightlist[light].extra_colormap; - light = R_GetPlaneLight(frontsector, -#ifdef ESLOPE - frontsector->c_slope ? P_GetZAt(frontsector->c_slope, frontsector->soundorg.x, frontsector->soundorg.y) : -#endif - frontsector->ceilingheight, false); + light = R_GetPlaneLight(frontsector, ceilingcenterz, false); if (frontsector->ceilinglightsec == -1) ceilinglightlevel = *frontsector->lightlist[light].lightlevel; ceilingcolormap = frontsector->lightlist[light].extra_colormap; @@ -920,6 +925,9 @@ static void R_Subsector(size_t num) { floorplane = R_FindPlane(frontsector->floorheight, frontsector->floorpic, floorlightlevel, frontsector->floor_xoffs, frontsector->floor_yoffs, frontsector->floorpic_angle, floorcolormap, NULL +#ifdef POLYOBJECTS_PLANES + , NULL +#endif #ifdef ESLOPE , frontsector->f_slope #endif @@ -939,6 +947,9 @@ static void R_Subsector(size_t num) ceilingplane = R_FindPlane(frontsector->ceilingheight, frontsector->ceilingpic, ceilinglightlevel, frontsector->ceiling_xoffs, frontsector->ceiling_yoffs, frontsector->ceilingpic_angle, ceilingcolormap, NULL +#ifdef POLYOBJECTS_PLANES + , NULL +#endif #ifdef ESLOPE , frontsector->c_slope #endif @@ -956,7 +967,7 @@ static void R_Subsector(size_t num) if (frontsector->ffloors) { ffloor_t *rover; - fixed_t heightcheck, planecenterz, floorcenterz, ceilingcenterz; + fixed_t heightcheck, planecenterz; for (rover = frontsector->ffloors; rover && numffloors < MAXFFLOORS; rover = rover->next) { @@ -975,18 +986,6 @@ static void R_Subsector(size_t num) ffloor[numffloors].plane = NULL; ffloor[numffloors].polyobj = NULL; - floorcenterz = -#ifdef ESLOPE - frontsector->f_slope ? P_GetZAt(frontsector->f_slope, frontsector->soundorg.x, frontsector->soundorg.y) : -#endif - frontsector->floorheight; - - ceilingcenterz = -#ifdef ESLOPE - frontsector->c_slope ? P_GetZAt(frontsector->c_slope, frontsector->soundorg.x, frontsector->soundorg.y) : -#endif - frontsector->ceilingheight; - heightcheck = #ifdef ESLOPE *rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) : @@ -1009,6 +1008,9 @@ static void R_Subsector(size_t num) ffloor[numffloors].plane = R_FindPlane(*rover->bottomheight, *rover->bottompic, *frontsector->lightlist[light].lightlevel, *rover->bottomxoffs, *rover->bottomyoffs, *rover->bottomangle, frontsector->lightlist[light].extra_colormap, rover +#ifdef POLYOBJECTS_PLANES + , NULL +#endif #ifdef ESLOPE , *rover->b_slope #endif @@ -1052,6 +1054,9 @@ static void R_Subsector(size_t num) ffloor[numffloors].plane = R_FindPlane(*rover->topheight, *rover->toppic, *frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs, *rover->topangle, frontsector->lightlist[light].extra_colormap, rover +#ifdef POLYOBJECTS_PLANES + , NULL +#endif #ifdef ESLOPE , *rover->t_slope #endif @@ -1093,8 +1098,8 @@ static void R_Subsector(size_t num) polysec = po->lines[0]->backsector; ffloor[numffloors].plane = NULL; - if (polysec->floorheight <= frontsector->ceilingheight - && polysec->floorheight >= frontsector->floorheight + if (polysec->floorheight <= ceilingcenterz + && polysec->floorheight >= floorcenterz && (viewz < polysec->floorheight)) { fixed_t xoff, yoff; @@ -1118,11 +1123,13 @@ static void R_Subsector(size_t num) polysec->floorpic_angle-po->angle, NULL, NULL +#ifdef POLYOBJECTS_PLANES + , po +#endif #ifdef ESLOPE , NULL // will ffloors be slopable eventually? #endif ); - //ffloor[numffloors].plane->polyobj = po; ffloor[numffloors].height = polysec->floorheight; ffloor[numffloors].polyobj = po; @@ -1139,8 +1146,8 @@ static void R_Subsector(size_t num) ffloor[numffloors].plane = NULL; - if (polysec->ceilingheight >= frontsector->floorheight - && polysec->ceilingheight <= frontsector->ceilingheight + if (polysec->ceilingheight >= floorcenterz + && polysec->ceilingheight <= ceilingcenterz && (viewz > polysec->ceilingheight)) { fixed_t xoff, yoff; @@ -1162,11 +1169,13 @@ static void R_Subsector(size_t num) ffloor[numffloors].plane = R_FindPlane(polysec->ceilingheight, polysec->ceilingpic, polysec->lightlevel, xoff, yoff, polysec->ceilingpic_angle-po->angle, NULL, NULL +#ifdef POLYOBJECTS_PLANES + , po +#endif #ifdef ESLOPE , NULL // will ffloors be slopable eventually? #endif ); - //ffloor[numffloors].plane->polyobj = po; ffloor[numffloors].polyobj = po; ffloor[numffloors].height = polysec->ceilingheight; diff --git a/src/r_data.c b/src/r_data.c index 87b6b1193..cd9ff6273 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -160,6 +160,7 @@ static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, INT32 orig if (position < 0) { count += position; + source -= position; // start further down the column position = 0; } @@ -173,6 +174,44 @@ static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, INT32 orig } } +static inline void R_DrawFlippedColumnInCache(column_t *patch, UINT8 *cache, INT32 originy, INT32 cacheheight, INT32 patchheight) +{ + INT32 count, position; + UINT8 *source, *dest; + INT32 topdelta, prevdelta = -1; + + while (patch->topdelta != 0xff) + { + topdelta = patch->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + topdelta = patchheight-patch->length-topdelta; + source = (UINT8 *)patch + 2 + patch->length; // patch + 3 + (patch->length-1) + count = patch->length; + position = originy + topdelta; + + if (position < 0) + { + count += position; + source += position; // start further UP the column + position = 0; + } + + if (position + count > cacheheight) + count = cacheheight - position; + + dest = cache + position; + if (count > 0) + { + for (; dest < cache + position + count; --source) + *dest++ = *source; + } + + patch = (column_t *)((UINT8 *)patch + patch->length + 4); + } +} + // // R_GenerateTexture // @@ -191,7 +230,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) texture_t *texture; texpatch_t *patch; patch_t *realpatch; - int x, x1, x2, i; + int x, x1, x2, i, width, height; size_t blocksize; column_t *patchcol; UINT32 *colofs; @@ -239,6 +278,7 @@ static UINT8 *R_GenerateTexture(size_t texnum) if (holey) { texture->holes = true; + texture->flip = patch->flip; blocksize = W_LumpLengthPwad(patch->wad, patch->lump); block = Z_Calloc(blocksize, PU_STATIC, // will change tag at end of this function &texturecache[texnum]); @@ -249,6 +289,14 @@ static UINT8 *R_GenerateTexture(size_t texnum) colofs = (UINT32 *)(void *)(block + 8); texturecolumnofs[texnum] = colofs; blocktex = block; + if (patch->flip & 1) // flip the patch horizontally + { + UINT32 *realcolofs = (UINT32 *)realpatch->columnofs; + for (x = 0; x < texture->width; x++) + colofs[x] = realcolofs[texture->width-1-x]; // swap with the offset of the other side of the texture + } + // we can't as easily flip the patch vertically sadly though, + // we have wait until the texture itself is drawn to do that for (x = 0; x < texture->width; x++) colofs[x] = LONG(LONG(colofs[x]) + 3); goto done; @@ -259,11 +307,12 @@ static UINT8 *R_GenerateTexture(size_t texnum) // multi-patch textures (or 'composite') texture->holes = false; + texture->flip = 0; blocksize = (texture->width * 4) + (texture->width * texture->height); texturememory += blocksize; block = Z_Malloc(blocksize+1, PU_STATIC, &texturecache[texnum]); - memset(block, 0xF7, blocksize+1); // Transparency hack + memset(block, 0xFF, blocksize+1); // Transparency hack // columns lookup table colofs = (UINT32 *)(void *)block; @@ -277,7 +326,9 @@ static UINT8 *R_GenerateTexture(size_t texnum) { realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); x1 = patch->originx; - x2 = x1 + SHORT(realpatch->width); + width = SHORT(realpatch->width); + height = SHORT(realpatch->height); + x2 = x1 + width; if (x1 < 0) x = 0; @@ -289,11 +340,17 @@ static UINT8 *R_GenerateTexture(size_t texnum) for (; x < x2; x++) { - patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[x-x1])); + if (patch->flip & 1) + patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[(x1+width-1)-x])); + else + patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[x-x1])); // generate column ofset lookup colofs[x] = LONG((x * texture->height) + (texture->width*4)); - R_DrawColumnInCache(patchcol, block + LONG(colofs[x]), patch->originy, texture->height); + if (patch->flip & 2) + R_DrawFlippedColumnInCache(patchcol, block + LONG(colofs[x]), patch->originy, texture->height, height); + else + R_DrawColumnInCache(patchcol, block + LONG(colofs[x]), patch->originy, texture->height); } } @@ -303,6 +360,32 @@ done: return blocktex; } +// +// R_GetTextureNum +// +// Returns the actual texture id that we should use. +// This can either be texnum, the current frame for texnum's anim (if animated), +// or 0 if not valid. +// +INT32 R_GetTextureNum(INT32 texnum) +{ + if (texnum < 0 || texnum >= numtextures) + return 0; + return texturetranslation[texnum]; +} + +// +// R_CheckTextureCache +// +// Use this if you need to make sure the texture is cached before R_GetColumn calls +// e.g.: midtextures and FOF walls +// +void R_CheckTextureCache(INT32 tex) +{ + if (!texturecache[tex]) + R_GenerateTexture(tex); +} + // // R_GetColumn // @@ -469,6 +552,7 @@ void R_LoadTextures(void) texture->height = SHORT(patchlump->height)*patchcount; texture->patchcount = patchcount; texture->holes = false; + texture->flip = 0; // Allocate information for the texture's patches. for (k = 0; k < patchcount; k++) @@ -479,6 +563,7 @@ void R_LoadTextures(void) patch->originy = (INT16)(k*patchlump->height); patch->wad = (UINT16)w; patch->lump = texstart + j; + patch->flip = 0; } Z_Unlock(patchlump); @@ -502,6 +587,7 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) char *patchName = NULL; INT16 patchXPos; INT16 patchYPos; + UINT8 flip = 0; texpatch_t *resultPatch = NULL; lumpnum_t patchLumpNum; @@ -598,6 +684,47 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) } Z_Free(texturesToken); + // Patch parameters block (OPTIONAL) + // added by Monster Iestyn (22/10/16) + + // Left Curly Brace + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + ; // move on and ignore, R_ParseTextures will deal with this + else + { + if (strcmp(texturesToken,"{")==0) + { + Z_Free(texturesToken); + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + { + I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s parameters should be",patchName); + } + while (strcmp(texturesToken,"}")!=0) + { + if (stricmp(texturesToken, "FLIPX")==0) + flip |= 1; + else if (stricmp(texturesToken, "FLIPY")==0) + flip |= 2; + Z_Free(texturesToken); + + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + { + I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s parameters or right curly brace should be",patchName); + } + } + } + else + { + // this is not what we wanted... + // undo last read so R_ParseTextures can re-get the token for its own purposes + M_UnGetToken(); + } + Z_Free(texturesToken); + } + if (actuallyLoadPatch == true) { // Check lump exists @@ -608,6 +735,7 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) resultPatch->originy = patchYPos; resultPatch->lump = patchLumpNum & 65535; resultPatch->wad = patchLumpNum>>16; + resultPatch->flip = flip; // Clean up a little after ourselves Z_Free(patchName); // Then return it diff --git a/src/r_data.h b/src/r_data.h index 69a2882af..bea1cba3b 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -31,6 +31,7 @@ typedef struct // Block origin (always UL), which has already accounted for the internal origin of the patch. INT16 originx, originy; UINT16 wad, lump; + UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both } texpatch_t; // A maptexturedef_t describes a rectangular texture, @@ -42,6 +43,7 @@ typedef struct char name[8]; INT16 width, height; boolean holes; + UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both // All the patches[patchcount] are drawn back to front into the cached texture. INT16 patchcount; @@ -65,6 +67,9 @@ extern CV_PossibleValue_t Color_cons_t[]; void R_LoadTextures(void); void R_FlushTextureCache(void); +INT32 R_GetTextureNum(INT32 texnum); +void R_CheckTextureCache(INT32 tex); + // Retrieve column data for span blitting. UINT8 *R_GetColumn(fixed_t tex, INT32 col); diff --git a/src/r_defs.h b/src/r_defs.h index 9109ac7c3..32be7c4c8 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -203,6 +203,7 @@ typedef struct r_lightlist_s fixed_t heightstep; fixed_t botheight; fixed_t botheightstep; + fixed_t startheight; // for repeating midtextures INT16 lightlevel; extracolormap_t *extra_colormap; lighttable_t *rcolormap; @@ -224,15 +225,6 @@ typedef struct linechain_s -// ZDoom C++ to Legacy C conversion Tails 04-29-2002 (for slopes) -typedef struct secplane_t -{ - // the plane is defined as a*x + b*y + c*z + d = 0 - // ic is 1/c, for faster Z calculations - - fixed_t a, b, c, d, ic; -} secplane_t; - // Slopes #ifdef ESLOPE typedef enum { @@ -392,6 +384,7 @@ typedef struct sector_s #endif // these are saved for netgames, so do not let Lua touch these! + INT32 spawn_nexttag, spawn_firsttag; // the actual nexttag/firsttag values may differ if the sector's tag was changed // offsets sector spawned with (via linedef type 7) fixed_t spawn_flr_xoffs, spawn_flr_yoffs; diff --git a/src/r_draw.h b/src/r_draw.h index 60c3c9db6..4a105b5b0 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -162,6 +162,7 @@ void R_DrawSplat_8(void); void R_DrawTranslucentSplat_8(void); void R_DrawTranslucentSpan_8(void); void R_Draw2sMultiPatchColumn_8(void); +void R_Draw2sMultiPatchTranslucentColumn_8(void); void R_DrawFogSpan_8(void); void R_DrawFogColumn_8(void); void R_DrawColumnShadowed_8(void); diff --git a/src/r_draw8.c b/src/r_draw8.c index c1b7da11b..9340b61c6 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -203,6 +203,103 @@ void R_Draw2sMultiPatchColumn_8(void) } } +void R_Draw2sMultiPatchTranslucentColumn_8(void) +{ + INT32 count; + register UINT8 *dest; + register fixed_t frac; + fixed_t fracstep; + + count = dc_yh - dc_yl; + + if (count < 0) // Zero length, column does not exceed a pixel. + return; + +#ifdef RANGECHECK + if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + return; +#endif + + // Framebuffer destination address. + // Use ylookup LUT to avoid multiply with ScreenWidth. + // Use columnofs LUT for subwindows? + + //dest = ylookup[dc_yl] + columnofs[dc_x]; + dest = &topleft[dc_yl*vid.width + dc_x]; + + count++; + + // Determine scaling, which is the only mapping to be done. + fracstep = dc_iscale; + //frac = dc_texturemid + (dc_yl - centery)*fracstep; + frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); + + // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. + // This is as fast as it gets. + { + register const UINT8 *source = dc_source; + register const UINT8 *transmap = dc_transmap; + register const lighttable_t *colormap = dc_colormap; + register INT32 heightmask = dc_texheight-1; + register UINT8 val; + if (dc_texheight & heightmask) // not a power of 2 -- killough + { + heightmask++; + heightmask <<= FRACBITS; + + if (frac < 0) + while ((frac += heightmask) < 0); + else + while (frac >= heightmask) + frac -= heightmask; + + do + { + // Re-map color indices from wall texture column + // using a lighting/special effects LUT. + // heightmask is the Tutti-Frutti fix + val = source[frac>>FRACBITS]; + + if (val != TRANSPARENTPIXEL) + *dest = colormap[*(transmap + (val<<8) + (*dest))]; + + dest += vid.width; + + // Avoid overflow. + if (fracstep > 0x7FFFFFFF - frac) + frac += fracstep - heightmask; + else + frac += fracstep; + + while (frac >= heightmask) + frac -= heightmask; + } while (--count); + } + else + { + while ((count -= 2) >= 0) // texture height is a power of 2 + { + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + *dest = colormap[*(transmap + (val<<8) + (*dest))]; + dest += vid.width; + frac += fracstep; + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + *dest = colormap[*(transmap + (val<<8) + (*dest))]; + dest += vid.width; + frac += fracstep; + } + if (count & 1) + { + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + *dest = colormap[*(transmap + (val<<8) + (*dest))]; + } + } + } +} + /** \brief The R_DrawShadeColumn_8 function Experiment to make software go faster. Taken from the Boom source */ diff --git a/src/r_main.c b/src/r_main.c index b05e37b53..4cff0ff83 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -148,7 +148,6 @@ consvar_t cv_flipcam2 = {"flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, consvar_t cv_shadow = {"shadow", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_shadowoffs = {"offsetshadows", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_soniccd = {"soniccd", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_translucenthud = {"translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -366,69 +365,6 @@ fixed_t R_PointToDist(fixed_t x, fixed_t y) return R_PointToDist2(viewx, viewy, x, y); } -/*************************************** -*** Zdoom C++ to Legacy C conversion *** -****************************************/ - -// Utility to find the Z height at an XY location in a sector (for slopes) -fixed_t R_SecplaneZatPoint(secplane_t *secplane, fixed_t x, fixed_t y) -{ - return FixedMul(secplane->ic, -secplane->d - DMulScale16(secplane->a, x, secplane->b, y)); -} - -// Returns the value of z at (x,y) if d is equal to dist -fixed_t R_SecplaneZatPointDist (secplane_t *secplane, fixed_t x, fixed_t y, fixed_t dist) -{ - return FixedMul(secplane->ic, -dist - DMulScale16(secplane->a, x, secplane->b, y)); -} - -// Flips the plane's vertical orientiation, so that if it pointed up, -// it will point down, and vice versa. -void R_SecplaneFlipVert(secplane_t *secplane) -{ - secplane->a = -secplane->a; - secplane->b = -secplane->b; - secplane->c = -secplane->c; - secplane->d = -secplane->d; - secplane->ic = -secplane->ic; -} - -// Returns true if 2 planes are the same -boolean R_ArePlanesSame(secplane_t *original, secplane_t *other) -{ - return original->a == other->a && original->b == other->b - && original->c == other->c && original->d == other->d; -} - -// Returns true if 2 planes are different -boolean R_ArePlanesDifferent(secplane_t *original, secplane_t *other) -{ - return original->a != other->a || original->b != other->b - || original->c != other->c || original->d != other->d; -} - -// Moves a plane up/down by hdiff units -void R_SecplaneChangeHeight(secplane_t *secplane, fixed_t hdiff) -{ - secplane->d = secplane->d - FixedMul(hdiff, secplane->c); -} - -// Returns how much this plane's height would change if d were set to oldd -fixed_t R_SecplaneHeightDiff(secplane_t *secplane, fixed_t oldd) -{ - return FixedMul(oldd - secplane->d, secplane->ic); -} - -fixed_t R_SecplanePointToDist(secplane_t *secplane, fixed_t x, fixed_t y, fixed_t z) -{ - return -TMulScale16(secplane->a, x, y, secplane->b, z, secplane->c); -} - -fixed_t R_SecplanePointToDist2(secplane_t *secplane, fixed_t x, fixed_t y, fixed_t z) -{ - return -TMulScale16(secplane->a, x, secplane->b, y, z, secplane->c); -} - // // R_ScaleFromGlobalAngle // Returns the texture mapping scale for the current line (horizontal span) @@ -1424,7 +1360,6 @@ void R_RegisterEngineStuff(void) { CV_RegisterVar(&cv_gravity); CV_RegisterVar(&cv_tailspickup); - CV_RegisterVar(&cv_soniccd); CV_RegisterVar(&cv_allowmlook); CV_RegisterVar(&cv_homremoval); CV_RegisterVar(&cv_flipcam); diff --git a/src/r_main.h b/src/r_main.h index 8f46a938e..2e768cb9c 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -61,18 +61,6 @@ angle_t R_PointToAngle2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1); fixed_t R_PointToDist(fixed_t x, fixed_t y); fixed_t R_PointToDist2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1); -// ZDoom C++ to Legacy C conversion Tails 04-29-2002 -fixed_t R_SecplaneZatPoint(secplane_t *secplane, fixed_t x, fixed_t y); -fixed_t R_SecplaneZatPointDist(secplane_t *secplane, fixed_t x, fixed_t y, - fixed_t dist); -void R_SecplaneFlipVert(secplane_t *secplane); -boolean R_ArePlanesSame(secplane_t *original, secplane_t *other); -boolean R_ArePlanesDifferent(secplane_t *original, secplane_t *other); -void R_SecplaneChangeHeight(secplane_t *secplane, fixed_t hdiff); -fixed_t R_SecplaneHeightDiff(secplane_t *secplane, fixed_t oldd); -fixed_t R_SecplanePointToDist(secplane_t *secplane, fixed_t x, fixed_t y, fixed_t z); -fixed_t R_SecplanePointToDist2(secplane_t *secplane, fixed_t x, fixed_t y, fixed_t z); - fixed_t R_ScaleFromGlobalAngle(angle_t visangle); subsector_t *R_PointInSubsector(fixed_t x, fixed_t y); subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y); diff --git a/src/r_plane.c b/src/r_plane.c index e21e15d1a..11dd79d41 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -431,6 +431,9 @@ static visplane_t *new_visplane(unsigned hash) visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t xoff, fixed_t yoff, angle_t plangle, extracolormap_t *planecolormap, ffloor_t *pfloor +#ifdef POLYOBJECTS_PLANES + , polyobj_t *polyobj +#endif #ifdef ESLOPE , pslope_t *slope #endif @@ -470,6 +473,8 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, #ifdef POLYOBJECTS_PLANES if (check->polyobj && pfloor) continue; + if (polyobj != check->polyobj) + continue; #endif if (height == check->height && picnum == check->picnum && lightlevel == check->lightlevel @@ -504,7 +509,7 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, check->viewangle = viewangle; check->plangle = plangle; #ifdef POLYOBJECTS_PLANES - check->polyobj = NULL; + check->polyobj = polyobj; #endif #ifdef ESLOPE check->slope = slope; @@ -720,7 +725,11 @@ void R_DrawPlanes(void) continue; } - if (pl->ffloor != NULL) + if (pl->ffloor != NULL +#ifdef POLYOBJECTS_PLANES + || pl->polyobj != NULL +#endif + ) continue; R_DrawSinglePlane(pl); diff --git a/src/r_plane.h b/src/r_plane.h index ec1940716..16c8c12a4 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -97,6 +97,9 @@ void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2); void R_DrawPlanes(void); visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t xoff, fixed_t yoff, angle_t plangle, extracolormap_t *planecolormap, ffloor_t *ffloor +#ifdef POLYOBJECTS_PLANES + , polyobj_t *polyobj +#endif #ifdef ESLOPE , pslope_t *slope #endif diff --git a/src/r_segs.c b/src/r_segs.c index 257be2989..a4264eea5 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -271,11 +271,20 @@ static void R_Render2sidedMultiPatchColumn(column_t *column) if (colfunc == wallcolfunc) twosmultipatchfunc(); + else if (colfunc == fuzzcolfunc) + twosmultipatchtransfunc(); else colfunc(); } } +// quick wrapper for R_DrawFlippedMaskedColumn so it can be set as a colfunc_2s value +// uses column2s_length for texture->height as above +static void R_DrawFlippedMaskedSegColumn(column_t *column) +{ + R_DrawFlippedMaskedColumn(column, column2s_length); +} + void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) { size_t pindex; @@ -300,7 +309,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) curline = ds->curline; frontsector = curline->frontsector; backsector = curline->backsector; - texnum = texturetranslation[curline->sidedef->midtexture]; + texnum = R_GetTextureNum(curline->sidedef->midtexture); windowbottom = windowtop = sprbotscreen = INT32_MAX; // hack translucent linedef types (900-909 for transtables 1-9) @@ -344,10 +353,21 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) rw_scalestep = ds->scalestep; spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; + // Texture must be cached before setting colfunc_2s, + // otherwise texture[texnum]->holes may be false when it shouldn't be + R_CheckTextureCache(texnum); // handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures // are not stored per-column with post info in SRB2 if (textures[texnum]->holes) - colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture + { + if (textures[texnum]->flip & 2) // vertically flipped? + { + colfunc_2s = R_DrawFlippedMaskedSegColumn; + column2s_length = textures[texnum]->height; + } + else + colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture + } else { colfunc_2s = R_Render2sidedMultiPatchColumn; // render multipatch with no holes (no post_t info) @@ -391,6 +411,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) rlight->height = (centeryfrac) - FixedMul((light->height - viewz), spryscale); rlight->heightstep = -FixedMul(rw_scalestep, (light->height - viewz)); #endif + rlight->startheight = rlight->height; // keep starting value here to reset for each repeat rlight->lightlevel = *light->lightlevel; rlight->extra_colormap = light->extra_colormap; rlight->flags = light->flags; @@ -484,6 +505,14 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) { rw_scalestep = ds->scalestep; spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; + if (dc_numlights) + { // reset all lights to their starting heights + for (i = 0; i < dc_numlights; i++) + { + rlight = &dc_lightlist[i]; + rlight->height = rlight->startheight; + } + } } #ifndef ESLOPE @@ -700,6 +729,14 @@ static void R_DrawRepeatMaskedColumn(column_t *col) } while (sprtopscreen < sprbotscreen); } +static void R_DrawRepeatFlippedMaskedColumn(column_t *col) +{ + do { + R_DrawFlippedMaskedColumn(col, column2s_length); + sprtopscreen += dc_texheight*spryscale; + } while (sprtopscreen < sprbotscreen); +} + // // R_RenderThickSideRange // Renders all the thick sides in the given range. @@ -746,7 +783,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) curline = ds->curline; backsector = pfloor->target; frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector; - texnum = texturetranslation[sides[pfloor->master->sidenum[0]].midtexture]; + texnum = R_GetTextureNum(sides[pfloor->master->sidenum[0]].midtexture); colfunc = wallcolfunc; @@ -754,7 +791,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { size_t linenum = curline->linedef-backsector->lines[0]; newline = pfloor->master->frontsector->lines[0] + linenum; - texnum = texturetranslation[sides[newline->sidenum[0]].midtexture]; + texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture); } if (pfloor->flags & FF_TRANSLUCENT) @@ -1024,10 +1061,21 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) dc_texturemid += offsetvalue; + // Texture must be cached before setting colfunc_2s, + // otherwise texture[texnum]->holes may be false when it shouldn't be + R_CheckTextureCache(texnum); //faB: handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures // are not stored per-column with post info anymore in Doom Legacy if (textures[texnum]->holes) - colfunc_2s = R_DrawRepeatMaskedColumn; //render the usual 2sided single-patch packed texture + { + if (textures[texnum]->flip & 2) // vertically flipped? + { + colfunc_2s = R_DrawRepeatFlippedMaskedColumn; + column2s_length = textures[texnum]->height; + } + else + colfunc_2s = R_DrawRepeatMaskedColumn; // render the usual 2sided single-patch packed texture + } else { colfunc_2s = R_Render2sidedMultiPatchColumn; //render multipatch with no holes (no post_t info) @@ -1936,14 +1984,16 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (!backsector) { + fixed_t texheight; // single sided line - midtexture = texturetranslation[sidedef->midtexture]; + midtexture = R_GetTextureNum(sidedef->midtexture); + texheight = textureheight[midtexture]; // a single sided line is terminal, so it must mark ends markfloor = markceiling = true; #ifdef ESLOPE if (linedef->flags & ML_EFFECT2) { if (linedef->flags & ML_DONTPEGBOTTOM) - rw_midtexturemid = frontsector->floorheight + textureheight[sidedef->midtexture] - viewz; + rw_midtexturemid = frontsector->floorheight + texheight - viewz; else rw_midtexturemid = frontsector->ceilingheight - viewz; } @@ -1952,10 +2002,10 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (linedef->flags & ML_DONTPEGBOTTOM) { #ifdef ESLOPE - rw_midtexturemid = worldbottom + textureheight[sidedef->midtexture]; + rw_midtexturemid = worldbottom + texheight; rw_midtextureslide = floorfrontslide; #else - vtop = frontsector->floorheight + textureheight[sidedef->midtexture]; + vtop = frontsector->floorheight + texheight; // bottom of texture at bottom rw_midtexturemid = vtop - viewz; #endif @@ -2187,76 +2237,50 @@ void R_StoreWallRange(INT32 start, INT32 stop) #endif ) { + fixed_t texheight; // top texture if ((linedef->flags & (ML_DONTPEGTOP) && (linedef->flags & ML_DONTPEGBOTTOM)) && linedef->sidenum[1] != 0xffff) { // Special case... use offsets from 2nd side but only if it has a texture. side_t *def = &sides[linedef->sidenum[1]]; - toptexture = texturetranslation[def->toptexture]; + toptexture = R_GetTextureNum(def->toptexture); if (!toptexture) //Second side has no texture, use the first side's instead. - toptexture = texturetranslation[sidedef->toptexture]; - -#ifdef ESLOPE - if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked - if (linedef->flags & ML_DONTPEGTOP) - rw_toptexturemid = frontsector->ceilingheight - viewz; - else - rw_toptexturemid = backsector->ceilingheight - viewz; - } else -#endif - if (linedef->flags & ML_DONTPEGTOP) - { - // top of texture at top - rw_toptexturemid = worldtop; -#ifdef ESLOPE - rw_toptextureslide = ceilingfrontslide; -#endif - } - else - { -#ifdef ESLOPE - rw_toptexturemid = worldhigh + textureheight[def->toptexture]; - rw_toptextureslide = ceilingbackslide; -#else - vtop = backsector->ceilingheight + textureheight[def->toptexture]; - // bottom of texture - rw_toptexturemid = vtop - viewz; -#endif - } + toptexture = R_GetTextureNum(sidedef->toptexture); + texheight = textureheight[toptexture]; } else { - toptexture = texturetranslation[sidedef->toptexture]; - + toptexture = R_GetTextureNum(sidedef->toptexture); + texheight = textureheight[toptexture]; + } #ifdef ESLOPE - if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked - if (linedef->flags & ML_DONTPEGTOP) - rw_toptexturemid = frontsector->ceilingheight - viewz; - else - rw_toptexturemid = backsector->ceilingheight - viewz; - } else -#endif + if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked if (linedef->flags & ML_DONTPEGTOP) - { - // top of texture at top - rw_toptexturemid = worldtop; -#ifdef ESLOPE - rw_toptextureslide = ceilingfrontslide; -#endif - } + rw_toptexturemid = frontsector->ceilingheight - viewz; else - { -#ifdef ESLOPE - rw_toptexturemid = worldhigh + textureheight[sidedef->toptexture]; - rw_toptextureslide = ceilingbackslide; -#else - vtop = backsector->ceilingheight + textureheight[sidedef->toptexture]; - // bottom of texture - rw_toptexturemid = vtop - viewz; + rw_toptexturemid = backsector->ceilingheight - viewz; + } else +#endif + if (linedef->flags & ML_DONTPEGTOP) + { + // top of texture at top + rw_toptexturemid = worldtop; +#ifdef ESLOPE + rw_toptextureslide = ceilingfrontslide; +#endif + } + else + { +#ifdef ESLOPE + rw_toptexturemid = worldhigh + texheight; + rw_toptextureslide = ceilingbackslide; +#else + vtop = backsector->ceilingheight + texheight; + // bottom of texture + rw_toptexturemid = vtop - viewz; #endif - } } } // check BOTTOM TEXTURE @@ -2267,7 +2291,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) ) //seulement si VISIBLE!!! { // bottom texture - bottomtexture = texturetranslation[sidedef->bottomtexture]; + bottomtexture = R_GetTextureNum(sidedef->bottomtexture); #ifdef ESLOPE if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked @@ -2552,7 +2576,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) ds_p->numthicksides = numthicksides = i; } - if (sidedef->midtexture) + if (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) { // masked midtexture if (!ds_p->thicksidecol) @@ -3164,12 +3188,12 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (maskedtexture && !(ds_p->silhouette & SIL_TOP)) { ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = sidedef->midtexture ? INT32_MIN: INT32_MAX; + ds_p->tsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MIN: INT32_MAX; } if (maskedtexture && !(ds_p->silhouette & SIL_BOTTOM)) { ds_p->silhouette |= SIL_BOTTOM; - ds_p->bsilheight = sidedef->midtexture ? INT32_MAX: INT32_MIN; + ds_p->bsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MAX: INT32_MIN; } ds_p++; } diff --git a/src/r_things.c b/src/r_things.c index e8aa2956f..e9080dc05 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -712,7 +712,7 @@ void R_DrawMaskedColumn(column_t *column) dc_texturemid = basetexturemid; } -static void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight) +void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight) { INT32 topscreen; INT32 bottomscreen; @@ -1349,7 +1349,7 @@ static void R_ProjectSprite(mobj_t *thing) if (sortscale < linkscale) dispoffset *= -1; // if it's physically behind, make sure it's ordered behind (if dispoffset > 0) - sortscale = linkscale; // now make sure it's linked + sortscale = linkscale; // now make sure it's linked } // PORTAL SPRITE CLIPPING @@ -1885,21 +1885,25 @@ static void R_CreateDrawNodes(void) entry->ffloor = ds->thicksides[i]; } } +#ifdef POLYOBJECTS_PLANES + // Check for a polyobject plane, but only if this is a front line + if (ds->curline->polyseg && ds->curline->polyseg->visplane && !ds->curline->side) { + plane = ds->curline->polyseg->visplane; + R_PlaneBounds(plane); + + if (plane->low < con_clipviewtop || plane->high > vid.height || plane->high > plane->low) + ; + else { + // Put it in! + entry = R_CreateDrawNode(&nodehead); + entry->plane = plane; + entry->seg = ds; + } + ds->curline->polyseg->visplane = NULL; + } +#endif if (ds->maskedtexturecol) { -#ifdef POLYOBJECTS_PLANES - // Check for a polyobject plane, but only if this is a front line - if (ds->curline->polyseg && ds->curline->polyseg->visplane && !ds->curline->side) { - // Put it in! - - entry = R_CreateDrawNode(&nodehead); - entry->plane = ds->curline->polyseg->visplane; - entry->seg = ds; - ds->curline->polyseg->visplane->polyobj = ds->curline->polyseg; - ds->curline->polyseg->visplane = NULL; - } -#endif - entry = R_CreateDrawNode(&nodehead); entry->seg = ds; } @@ -1942,6 +1946,29 @@ static void R_CreateDrawNodes(void) } } +#ifdef POLYOBJECTS_PLANES + // find all the remaining polyobject planes and add them on the end of the list + // probably this is a terrible idea if we wanted them to be sorted properly + // but it works getting them in for now + for (i = 0; i < numPolyObjects; i++) + { + if (!PolyObjects[i].visplane) + continue; + plane = PolyObjects[i].visplane; + R_PlaneBounds(plane); + + if (plane->low < con_clipviewtop || plane->high > vid.height || plane->high > plane->low) + { + PolyObjects[i].visplane = NULL; + continue; + } + entry = R_CreateDrawNode(&nodehead); + entry->plane = plane; + // note: no seg is set, for what should be obvious reasons + PolyObjects[i].visplane = NULL; + } +#endif + if (visspritecount == 0) return; @@ -1998,13 +2025,16 @@ static void R_CreateDrawNodes(void) if (x1 < r2->plane->minx) x1 = r2->plane->minx; if (x2 > r2->plane->maxx) x2 = r2->plane->maxx; - for (i = x1; i <= x2; i++) + if (r2->seg) // if no seg set, assume the whole thing is in front or something stupid { - if (r2->seg->frontscale[i] > rover->sortscale) - break; + for (i = x1; i <= x2; i++) + { + if (r2->seg->frontscale[i] > rover->sortscale) + break; + } + if (i > x2) + continue; } - if (i > x2) - continue; entry = R_CreateDrawNode(NULL); (entry->prev = r2->prev)->next = entry; @@ -2880,6 +2910,7 @@ void R_AddSkins(UINT16 wadnum) GETFLAG(STOMPDAMAGE) GETFLAG(MARIODAMAGE) GETFLAG(MACHINE) + GETFLAG(NOSPINDASHDUST) #undef GETFLAG else // let's check if it's a sound, otherwise error out diff --git a/src/r_things.h b/src/r_things.h index 20dd25abf..572884d21 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -46,6 +46,7 @@ extern fixed_t windowtop; extern fixed_t windowbottom; void R_DrawMaskedColumn(column_t *column); +void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight); void R_SortVisSprites(void); //faB: find sprites in wadfile, replace existing, add new ones diff --git a/src/s_sound.c b/src/s_sound.c index 47a955561..971961897 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -607,6 +607,13 @@ void S_StartSound(const void *origin, sfxenum_t sfx_id) sfx_id = sfx_mario6; break; case sfx_shield: + case sfx_wirlsg: + case sfx_forcsg: + case sfx_elemsg: + case sfx_armasg: + case sfx_s3k3e: + case sfx_s3k3f: + case sfx_s3k41: sfx_id = sfx_mario3; break; case sfx_itemup: diff --git a/src/screen.c b/src/screen.c index d00155785..7fdef4b19 100644 --- a/src/screen.c +++ b/src/screen.c @@ -30,7 +30,7 @@ #include "f_finale.h" -#if defined (USEASM) //&& (!defined (_MSC_VER) || (_MSC_VER <= 1200)) +#if defined (USEASM) && !defined (NORUSEASM)//&& (!defined (_MSC_VER) || (_MSC_VER <= 1200)) #define RUSEASM //MSC.NET can't patch itself #endif @@ -49,6 +49,7 @@ void (*splatfunc)(void); // span drawer w/ transparency void (*basespanfunc)(void); // default span func for color mode void (*transtransfunc)(void); // translucent translated column drawer void (*twosmultipatchfunc)(void); // for cols with transparent pixels +void (*twosmultipatchtransfunc)(void); // for cols with transparent pixels AND translucency // ------------------ // global video state @@ -127,6 +128,7 @@ void SCR_SetMode(void) fuzzcolfunc = R_DrawTranslucentColumn_8; walldrawerfunc = R_DrawWallColumn_8; twosmultipatchfunc = R_Draw2sMultiPatchColumn_8; + twosmultipatchtransfunc = R_Draw2sMultiPatchTranslucentColumn_8; #ifdef RUSEASM if (R_ASM) { diff --git a/src/screen.h b/src/screen.h index 2dff4590e..a61de7f92 100644 --- a/src/screen.h +++ b/src/screen.h @@ -136,6 +136,7 @@ extern void (*basespanfunc)(void); extern void (*splatfunc)(void); extern void (*transtransfunc)(void); extern void (*twosmultipatchfunc)(void); +extern void (*twosmultipatchtransfunc)(void); // ----- // CPUID diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index 820192649..abf6d76d2 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -295,6 +295,7 @@ </ClCompile> <ClCompile Include="..\i_tcp.c" /> <ClCompile Include="..\lua_baselib.c" /> + <ClCompile Include="..\lua_blockmaplib.c" /> <ClCompile Include="..\lua_consolelib.c" /> <ClCompile Include="..\lua_hooklib.c" /> <ClCompile Include="..\lua_hudlib.c" /> diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters index d04007dd7..bdb029cf9 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj.filters +++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters @@ -633,6 +633,9 @@ <ClCompile Include="..\lua_baselib.c"> <Filter>LUA</Filter> </ClCompile> + <ClCompile Include="..\lua_blockmaplib.c"> + <Filter>LUA</Filter> + </ClCompile> <ClCompile Include="..\lua_consolelib.c"> <Filter>LUA</Filter> </ClCompile> diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index ea8ade8c1..71ee3f794 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2647,6 +2647,47 @@ INT32 I_PutEnv(char *variable) #endif } +INT32 I_ClipboardCopy(const char *data, size_t size) +{ + char storage[256]; + if (size > 255) + size = 255; + memcpy(storage, data, size); + storage[size] = 0; + + if (SDL_SetClipboardText(storage)) + return 0; + return -1; +} + +const char *I_ClipboardPaste(void) +{ + static char clipboard_modified[256]; + char *clipboard_contents, *i = clipboard_modified; + + if (!SDL_HasClipboardText()) + return NULL; + clipboard_contents = SDL_GetClipboardText(); + memcpy(clipboard_modified, clipboard_contents, 255); + SDL_free(clipboard_contents); + clipboard_modified[255] = 0; + + while (*i) + { + if (*i == '\n' || *i == '\r') + { // End on newline + *i = 0; + break; + } + else if (*i == '\t') + *i = ' '; // Tabs become spaces + else if (*i < 32 || (unsigned)*i > 127) + *i = '?'; // Nonprintable chars become question marks + ++i; + } + return (const char *)&clipboard_modified; +} + /** \brief The isWadPathOk function \param path string path to check diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 71baca510..aa572e6e0 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -33,14 +33,6 @@ #pragma warning(default : 4214 4244) #endif -#if SDL_VERSION_ATLEAST(1,3,0) -#define SDLK_EQUALS SDLK_KP_EQUALSAS400 -#define SDLK_LMETA SDLK_LGUI -#define SDLK_RMETA SDLK_RGUI -#else -#define HAVE_SDLMETAKEYS -#endif - #ifdef HAVE_TTF #include "i_ttf.h" #endif @@ -189,14 +181,14 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen) wasfullscreen = SDL_TRUE; SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); } - else if (!fullscreen && wasfullscreen) + else if (wasfullscreen) { wasfullscreen = SDL_FALSE; SDL_SetWindowFullscreen(window, 0); SDL_SetWindowSize(window, width, height); SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED_DISPLAY(1), SDL_WINDOWPOS_CENTERED_DISPLAY(1)); } - else if (!wasfullscreen) + else { // Reposition window only in windowed mode SDL_SetWindowSize(window, width, height); @@ -282,129 +274,70 @@ static INT32 Impl_SDL_Scancode_To_Keycode(SDL_Scancode code) } switch (code) { - case SDL_SCANCODE_F11: // F11 and F12 are - return KEY_F11; // separated from the - case SDL_SCANCODE_F12: // rest of the function - return KEY_F12; // keys + // F11 and F12 are separated from the rest of the function keys + case SDL_SCANCODE_F11: return KEY_F11; + case SDL_SCANCODE_F12: return KEY_F12; - case SDL_SCANCODE_KP_0: - return KEY_KEYPAD0; - case SDL_SCANCODE_KP_1: - return KEY_KEYPAD1; - case SDL_SCANCODE_KP_2: - return KEY_KEYPAD2; - case SDL_SCANCODE_KP_3: - return KEY_KEYPAD3; - case SDL_SCANCODE_KP_4: - return KEY_KEYPAD4; - case SDL_SCANCODE_KP_5: - return KEY_KEYPAD5; - case SDL_SCANCODE_KP_6: - return KEY_KEYPAD6; - case SDL_SCANCODE_KP_7: - return KEY_KEYPAD7; - case SDL_SCANCODE_KP_8: - return KEY_KEYPAD8; - case SDL_SCANCODE_KP_9: - return KEY_KEYPAD9; + case SDL_SCANCODE_KP_0: return KEY_KEYPAD0; + case SDL_SCANCODE_KP_1: return KEY_KEYPAD1; + case SDL_SCANCODE_KP_2: return KEY_KEYPAD2; + case SDL_SCANCODE_KP_3: return KEY_KEYPAD3; + case SDL_SCANCODE_KP_4: return KEY_KEYPAD4; + case SDL_SCANCODE_KP_5: return KEY_KEYPAD5; + case SDL_SCANCODE_KP_6: return KEY_KEYPAD6; + case SDL_SCANCODE_KP_7: return KEY_KEYPAD7; + case SDL_SCANCODE_KP_8: return KEY_KEYPAD8; + case SDL_SCANCODE_KP_9: return KEY_KEYPAD9; - case SDL_SCANCODE_RETURN: - return KEY_ENTER; - case SDL_SCANCODE_ESCAPE: - return KEY_ESCAPE; - case SDL_SCANCODE_BACKSPACE: - return KEY_BACKSPACE; - case SDL_SCANCODE_TAB: - return KEY_TAB; - case SDL_SCANCODE_SPACE: - return KEY_SPACE; - case SDL_SCANCODE_MINUS: - return KEY_MINUS; - case SDL_SCANCODE_EQUALS: - return KEY_EQUALS; - case SDL_SCANCODE_LEFTBRACKET: - return '['; - case SDL_SCANCODE_RIGHTBRACKET: - return ']'; - case SDL_SCANCODE_BACKSLASH: - return '\\'; - case SDL_SCANCODE_NONUSHASH: - return '#'; - case SDL_SCANCODE_SEMICOLON: - return ';'; - case SDL_SCANCODE_APOSTROPHE: - return '\''; - case SDL_SCANCODE_GRAVE: - return '`'; - case SDL_SCANCODE_COMMA: - return ','; - case SDL_SCANCODE_PERIOD: - return '.'; - case SDL_SCANCODE_SLASH: - return '/'; - case SDL_SCANCODE_CAPSLOCK: - return KEY_CAPSLOCK; - case SDL_SCANCODE_PRINTSCREEN: - return 0; // undefined? - case SDL_SCANCODE_SCROLLLOCK: - return KEY_SCROLLLOCK; - case SDL_SCANCODE_PAUSE: - return KEY_PAUSE; - case SDL_SCANCODE_INSERT: - return KEY_INS; - case SDL_SCANCODE_HOME: - return KEY_HOME; - case SDL_SCANCODE_PAGEUP: - return KEY_PGUP; - case SDL_SCANCODE_DELETE: - return KEY_DEL; - case SDL_SCANCODE_END: - return KEY_END; - case SDL_SCANCODE_PAGEDOWN: - return KEY_PGDN; - case SDL_SCANCODE_RIGHT: - return KEY_RIGHTARROW; - case SDL_SCANCODE_LEFT: - return KEY_LEFTARROW; - case SDL_SCANCODE_DOWN: - return KEY_DOWNARROW; - case SDL_SCANCODE_UP: - return KEY_UPARROW; - case SDL_SCANCODE_NUMLOCKCLEAR: - return KEY_NUMLOCK; - case SDL_SCANCODE_KP_DIVIDE: - return KEY_KPADSLASH; - case SDL_SCANCODE_KP_MULTIPLY: - return '*'; // undefined? - case SDL_SCANCODE_KP_MINUS: - return KEY_MINUSPAD; - case SDL_SCANCODE_KP_PLUS: - return KEY_PLUSPAD; - case SDL_SCANCODE_KP_ENTER: - return KEY_ENTER; - case SDL_SCANCODE_KP_PERIOD: - return KEY_KPADDEL; - case SDL_SCANCODE_NONUSBACKSLASH: - return '\\'; + case SDL_SCANCODE_RETURN: return KEY_ENTER; + case SDL_SCANCODE_ESCAPE: return KEY_ESCAPE; + case SDL_SCANCODE_BACKSPACE: return KEY_BACKSPACE; + case SDL_SCANCODE_TAB: return KEY_TAB; + case SDL_SCANCODE_SPACE: return KEY_SPACE; + case SDL_SCANCODE_MINUS: return KEY_MINUS; + case SDL_SCANCODE_EQUALS: return KEY_EQUALS; + case SDL_SCANCODE_LEFTBRACKET: return '['; + case SDL_SCANCODE_RIGHTBRACKET: return ']'; + case SDL_SCANCODE_BACKSLASH: return '\\'; + case SDL_SCANCODE_NONUSHASH: return '#'; + case SDL_SCANCODE_SEMICOLON: return ';'; + case SDL_SCANCODE_APOSTROPHE: return '\''; + case SDL_SCANCODE_GRAVE: return '`'; + case SDL_SCANCODE_COMMA: return ','; + case SDL_SCANCODE_PERIOD: return '.'; + case SDL_SCANCODE_SLASH: return '/'; + case SDL_SCANCODE_CAPSLOCK: return KEY_CAPSLOCK; + case SDL_SCANCODE_PRINTSCREEN: return 0; // undefined? + case SDL_SCANCODE_SCROLLLOCK: return KEY_SCROLLLOCK; + case SDL_SCANCODE_PAUSE: return KEY_PAUSE; + case SDL_SCANCODE_INSERT: return KEY_INS; + case SDL_SCANCODE_HOME: return KEY_HOME; + case SDL_SCANCODE_PAGEUP: return KEY_PGUP; + case SDL_SCANCODE_DELETE: return KEY_DEL; + case SDL_SCANCODE_END: return KEY_END; + case SDL_SCANCODE_PAGEDOWN: return KEY_PGDN; + case SDL_SCANCODE_RIGHT: return KEY_RIGHTARROW; + case SDL_SCANCODE_LEFT: return KEY_LEFTARROW; + case SDL_SCANCODE_DOWN: return KEY_DOWNARROW; + case SDL_SCANCODE_UP: return KEY_UPARROW; + case SDL_SCANCODE_NUMLOCKCLEAR: return KEY_NUMLOCK; + case SDL_SCANCODE_KP_DIVIDE: return KEY_KPADSLASH; + case SDL_SCANCODE_KP_MULTIPLY: return '*'; // undefined? + case SDL_SCANCODE_KP_MINUS: return KEY_MINUSPAD; + case SDL_SCANCODE_KP_PLUS: return KEY_PLUSPAD; + case SDL_SCANCODE_KP_ENTER: return KEY_ENTER; + case SDL_SCANCODE_KP_PERIOD: return KEY_KPADDEL; + case SDL_SCANCODE_NONUSBACKSLASH: return '\\'; - case SDL_SCANCODE_LSHIFT: - return KEY_LSHIFT; - case SDL_SCANCODE_RSHIFT: - return KEY_RSHIFT; - case SDL_SCANCODE_LCTRL: - return KEY_LCTRL; - case SDL_SCANCODE_RCTRL: - return KEY_RCTRL; - case SDL_SCANCODE_LALT: - return KEY_LALT; - case SDL_SCANCODE_RALT: - return KEY_RALT; - case SDL_SCANCODE_LGUI: - return KEY_LEFTWIN; - case SDL_SCANCODE_RGUI: - return KEY_RIGHTWIN; - default: - break; + case SDL_SCANCODE_LSHIFT: return KEY_LSHIFT; + case SDL_SCANCODE_RSHIFT: return KEY_RSHIFT; + case SDL_SCANCODE_LCTRL: return KEY_LCTRL; + case SDL_SCANCODE_RCTRL: return KEY_RCTRL; + case SDL_SCANCODE_LALT: return KEY_LALT; + case SDL_SCANCODE_RALT: return KEY_RALT; + case SDL_SCANCODE_LGUI: return KEY_LEFTWIN; + case SDL_SCANCODE_RGUI: return KEY_RIGHTWIN; + default: break; } #ifdef HWRENDER DBG_Printf("Unknown incoming scancode: %d, represented %c\n", @@ -432,15 +365,10 @@ static void VID_Command_NumModes_f (void) CONS_Printf(M_GetText("%d video mode(s) available(s)\n"), VID_NumModes()); } +// SDL2 doesn't have SDL_GetVideoSurface or a lot of the SDL_Surface flags that SDL 1.2 had static void SurfaceInfo(const SDL_Surface *infoSurface, const char *SurfaceText) { -#if 1 - (void)infoSurface; - (void)SurfaceText; - SDL2STUB(); -#else INT32 vfBPP; - const SDL_Surface *VidSur = SDL_GetVideoSurface(); if (!infoSurface) return; @@ -453,49 +381,12 @@ static void SurfaceInfo(const SDL_Surface *infoSurface, const char *SurfaceText) CONS_Printf("\x82" "%s\n", SurfaceText); CONS_Printf(M_GetText(" %ix%i at %i bit color\n"), infoSurface->w, infoSurface->h, vfBPP); - if (infoSurface->flags&SDL_HWSURFACE) - CONS_Printf("%s", M_GetText(" Stored in video memory\n")); - else if (infoSurface->flags&SDL_OPENGL) - CONS_Printf("%s", M_GetText(" Stored in an OpenGL context\n")); - else if (infoSurface->flags&SDL_PREALLOC) + if (infoSurface->flags&SDL_PREALLOC) CONS_Printf("%s", M_GetText(" Uses preallocated memory\n")); else CONS_Printf("%s", M_GetText(" Stored in system memory\n")); - - if (infoSurface->flags&SDL_ASYNCBLIT) - CONS_Printf("%s", M_GetText(" Uses asynchronous blits if possible\n")); - else - CONS_Printf("%s", M_GetText(" Uses synchronous blits if possible\n")); - - if (infoSurface->flags&SDL_ANYFORMAT) - CONS_Printf("%s", M_GetText(" Allows any pixel-format\n")); - - if (infoSurface->flags&SDL_HWPALETTE) - CONS_Printf("%s", M_GetText(" Has exclusive palette access\n")); - else if (VidSur == infoSurface) - CONS_Printf("%s", M_GetText(" Has nonexclusive palette access\n")); - - if (infoSurface->flags&SDL_DOUBLEBUF) - CONS_Printf("%s", M_GetText(" Double buffered\n")); - else if (VidSur == infoSurface) - CONS_Printf("%s", M_GetText(" No hardware flipping\n")); - - if (infoSurface->flags&SDL_FULLSCREEN) - CONS_Printf("%s", M_GetText(" Full screen\n")); - else if (infoSurface->flags&SDL_RESIZABLE) - CONS_Printf("%s", M_GetText(" Resizable window\n")); - else if (VidSur == infoSurface) - CONS_Printf("%s", M_GetText(" Nonresizable window\n")); - - if (infoSurface->flags&SDL_HWACCEL) - CONS_Printf("%s", M_GetText(" Uses hardware acceleration blit\n")); - if (infoSurface->flags&SDL_SRCCOLORKEY) - CONS_Printf("%s", M_GetText(" Use colorkey blitting\n")); if (infoSurface->flags&SDL_RLEACCEL) CONS_Printf("%s", M_GetText(" Colorkey RLE acceleration blit\n")); - if (infoSurface->flags&SDL_SRCALPHA) - CONS_Printf("%s", M_GetText(" Use alpha blending acceleration blit\n")); -#endif } static void VID_Command_Info_f (void) @@ -579,23 +470,6 @@ static void VID_Command_Mode_f (void) setmodeneeded = modenum+1; // request vid mode change } -#if 0 -#if defined(RPC_NO_WINDOWS_H) -static VOID MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - UNREFERENCED_PARAMETER(hWnd); - UNREFERENCED_PARAMETER(message); - UNREFERENCED_PARAMETER(wParam); - switch (message) - { - case WM_SETTEXT: - COM_BufAddText((LPCSTR)lParam); - break; - } -} -#endif -#endif - static inline void SDLJoyRemap(event_t *event) { (void)event; @@ -954,218 +828,6 @@ void I_GetEvent(void) // In order to make wheels act like buttons, we have to set their state to Up. // This is because wheel messages don't have an up/down state. gamekeydown[KEY_MOUSEWHEELDOWN] = gamekeydown[KEY_MOUSEWHEELUP] = 0; - -#if 0 - SDL_Event inputEvent; - static SDL_bool sdlquit = SDL_FALSE; //Alam: once, just once - event_t event; - - if (!graphics_started) - return; - - memset(&inputEvent, 0x00, sizeof(inputEvent)); - while (SDL_PollEvent(&inputEvent)) - { - memset(&event,0x00,sizeof (event_t)); - switch (inputEvent.type) - { - case SDL_ACTIVEEVENT: - if (inputEvent.active.state & (SDL_APPACTIVE|SDL_APPINPUTFOCUS)) - { - // pause music when alt-tab - if (inputEvent.active.gain /*&& !paused */) - { - static SDL_bool firsttimeonmouse = SDL_TRUE; - if (!firsttimeonmouse) - { - if (cv_usemouse.value) I_StartupMouse(); - } - else firsttimeonmouse = SDL_FALSE; - //if (!netgame && !con_destlines) paused = false; - if (gamestate == GS_LEVEL) - if (!paused) I_ResumeSong(0); //resume it - } - else /*if (!paused)*/ - { - if (!disable_mouse) - SDLforceUngrabMouse(); - if (!netgame && gamestate == GS_LEVEL) paused = true; - memset(gamekeydown, 0, NUMKEYS); - //S_PauseSound(); - if (gamestate == GS_LEVEL) - I_PauseSong(0); //pause it - } - } - if (MOUSE_MENU) - { - SDLdoUngrabMouse(); - break; - } - if ((SDL_APPMOUSEFOCUS&inputEvent.active.state) && USE_MOUSEINPUT && inputEvent.active.gain) - HalfWarpMouse(realwidth, realheight); - break; - case SDL_KEYDOWN: - case SDL_KEYUP: - /// \todo inputEvent.key.which? - if (inputEvent.type == SDL_KEYUP) - event.type = ev_keyup; - else if (inputEvent.type == SDL_KEYDOWN) - event.type = ev_keydown; - else break; - event.data1 = SDLatekey(inputEvent.key.keysym.sym); - if (event.data1) D_PostEvent(&event); - break; - case SDL_MOUSEMOTION: - /// \todo inputEvent.motion.which - if (MOUSE_MENU) - { - SDLdoUngrabMouse(); - break; - } - //if (USE_MOUSEINPUT) TODO SDL2 stub - { - // If the event is from warping the pointer back to middle - // of the screen then ignore it. - if ((inputEvent.motion.x == realwidth/2) && - (inputEvent.motion.y == realheight/2)) - { - break; - } - else - { - event.data2 = +inputEvent.motion.xrel; - event.data3 = -inputEvent.motion.yrel; - } - event.type = ev_mouse; - D_PostEvent(&event); - // Warp the pointer back to the middle of the window - // or we cannot move any further if it's at a border. - if ((inputEvent.motion.x < (realwidth/2 )-(realwidth/4 )) || - (inputEvent.motion.y < (realheight/2)-(realheight/4)) || - (inputEvent.motion.x > (realwidth/2 )+(realwidth/4 )) || - (inputEvent.motion.y > (realheight/2)+(realheight/4) ) ) - { - //if (SDL_GRAB_ON == SDL_WM_GrabInput(SDL_GRAB_QUERY) || !mousegrabok) - HalfWarpMouse(realwidth, realheight); - } - } - break; - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - /// \todo inputEvent.button.which - if (USE_MOUSEINPUT) - { - if (inputEvent.type == SDL_MOUSEBUTTONUP) - event.type = ev_keyup; - else if (inputEvent.type == SDL_MOUSEBUTTONDOWN) - event.type = ev_keydown; - else break; - if (inputEvent.button.button==SDL_BUTTON_WHEELUP || inputEvent.button.button==SDL_BUTTON_WHEELDOWN) - { - if (inputEvent.type == SDL_MOUSEBUTTONUP) - event.data1 = 0; //Alam: dumb! this could be a real button with some mice - else - event.data1 = KEY_MOUSEWHEELUP + inputEvent.button.button - SDL_BUTTON_WHEELUP; - } - else if (inputEvent.button.button == SDL_BUTTON_MIDDLE) - event.data1 = KEY_MOUSE1+2; - else if (inputEvent.button.button == SDL_BUTTON_RIGHT) - event.data1 = KEY_MOUSE1+1; - else if (inputEvent.button.button <= MOUSEBUTTONS) - event.data1 = KEY_MOUSE1 + inputEvent.button.button - SDL_BUTTON_LEFT; - if (event.data1) D_PostEvent(&event); - } - break; - case SDL_JOYAXISMOTION: - inputEvent.jaxis.which++; - inputEvent.jaxis.axis++; - event.data1 = event.data2 = event.data3 = INT32_MAX; - if (cv_usejoystick.value == inputEvent.jaxis.which) - { - event.type = ev_joystick; - } - else if (cv_usejoystick.value == inputEvent.jaxis.which) - { - event.type = ev_joystick2; - } - else break; - //axis - if (inputEvent.jaxis.axis > JOYAXISSET*2) - break; - //vaule - if (inputEvent.jaxis.axis%2) - { - event.data1 = inputEvent.jaxis.axis / 2; - event.data2 = SDLJoyAxis(inputEvent.jaxis.value, event.type); - } - else - { - inputEvent.jaxis.axis--; - event.data1 = inputEvent.jaxis.axis / 2; - event.data3 = SDLJoyAxis(inputEvent.jaxis.value, event.type); - } - D_PostEvent(&event); - break; - case SDL_JOYBALLMOTION: - case SDL_JOYHATMOTION: - break; //NONE - case SDL_JOYBUTTONDOWN: - case SDL_JOYBUTTONUP: - inputEvent.jbutton.which++; - if (cv_usejoystick.value == inputEvent.jbutton.which) - event.data1 = KEY_JOY1; - else if (cv_usejoystick.value == inputEvent.jbutton.which) - event.data1 = KEY_2JOY1; - else break; - if (inputEvent.type == SDL_JOYBUTTONUP) - event.type = ev_keyup; - else if (inputEvent.type == SDL_JOYBUTTONDOWN) - event.type = ev_keydown; - else break; - if (inputEvent.jbutton.button < JOYBUTTONS) - event.data1 += inputEvent.jbutton.button; - else - break; - SDLJoyRemap(&event); - if (event.type != ev_console) D_PostEvent(&event); - break; - case SDL_QUIT: - if (!sdlquit) - { - sdlquit = SDL_TRUE; - M_QuitResponse('y'); - } - break; -#if defined(RPC_NO_WINDOWS_H) - case SDL_SYSWMEVENT: - MainWndproc(inputEvent.syswm.msg->hwnd, - inputEvent.syswm.msg->msg, - inputEvent.syswm.msg->wParam, - inputEvent.syswm.msg->lParam); - break; -#endif - case SDL_VIDEORESIZE: - if (gamestate == GS_LEVEL || gamestate == GS_TITLESCREEN || gamestate == GS_EVALUATION) - setmodeneeded = VID_GetModeForSize(inputEvent.resize.w,inputEvent.resize.h)+1; - if (render_soft == rendermode) - { - SDLSetMode(realwidth, realheight, vid.bpp*8, surfaceFlagsW); - if (vidSurface) SDL_SetColors(vidSurface, localPalette, 0, 256); - } - else - SDLSetMode(realwidth, realheight, vid.bpp*8, surfaceFlagsW); - if (!vidSurface) - I_Error("Could not reset vidmode: %s\n",SDL_GetError()); - break; - case SDL_VIDEOEXPOSE: - exposevideo = SDL_TRUE; - break; - default: - break; - } - } - //reset wheel like in win32, I don't understand it but works -#endif } void I_StartupMouse(void) @@ -1494,11 +1156,6 @@ void VID_PrepareModeList(void) #endif } -static inline void SDLESSet(void) -{ - SDL2STUB(); -} - INT32 VID_SetMode(INT32 modeNum) { SDLdoUngrabMouse(); @@ -1550,6 +1207,12 @@ INT32 VID_SetMode(INT32 modeNum) static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) { int flags = 0; + + if (rendermode == render_none) // dedicated + { + return SDL_TRUE; // Monster Iestyn -- not sure if it really matters what we return here tbh + } + if (window != NULL) { return SDL_FALSE; @@ -1568,38 +1231,43 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) #ifdef HWRENDER if (rendermode == render_opengl) { - window = SDL_CreateWindow("SRB2 "VERSIONSTRING, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - realwidth, realheight, flags | SDL_WINDOW_OPENGL); - if (window != NULL) - { - sdlglcontext = SDL_GL_CreateContext(window); - if (sdlglcontext == NULL) - { - SDL_DestroyWindow(window); - I_Error("Failed to create a GL context: %s\n", SDL_GetError()); - } - else - { - SDL_GL_MakeCurrent(window, sdlglcontext); - } - } - else return SDL_FALSE; + flags |= SDL_WINDOW_OPENGL; } #endif + + // Create a window + window = SDL_CreateWindow("SRB2 "VERSIONSTRING, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + realwidth, realheight, flags); + + if (window == NULL) + { + CONS_Printf(M_GetText("Couldn't create window: %s\n"), SDL_GetError()); + return SDL_FALSE; + } + + // Renderer-specific stuff +#ifdef HWRENDER + if (rendermode == render_opengl) + { + sdlglcontext = SDL_GL_CreateContext(window); + if (sdlglcontext == NULL) + { + SDL_DestroyWindow(window); + I_Error("Failed to create a GL context: %s\n", SDL_GetError()); + } + SDL_GL_MakeCurrent(window, sdlglcontext); + } + else +#endif if (rendermode == render_soft) { - window = SDL_CreateWindow("SRB2 "VERSIONSTRING, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - realwidth, realheight, flags); - if (window != NULL) + renderer = SDL_CreateRenderer(window, -1, (usesdl2soft ? SDL_RENDERER_SOFTWARE : 0) | (cv_vidwait.value && !usesdl2soft ? SDL_RENDERER_PRESENTVSYNC : 0)); + if (renderer == NULL) { - renderer = SDL_CreateRenderer(window, -1, (usesdl2soft ? SDL_RENDERER_SOFTWARE : 0) | (cv_vidwait.value && !usesdl2soft ? SDL_RENDERER_PRESENTVSYNC : 0)); - if (renderer != NULL) - { - SDL_RenderSetLogicalSize(renderer, BASEVIDWIDTH, BASEVIDHEIGHT); - } - else return SDL_FALSE; + CONS_Printf(M_GetText("Couldn't create rendering context: %s\n"), SDL_GetError()); + return SDL_FALSE; } - else return SDL_FALSE; + SDL_RenderSetLogicalSize(renderer, BASEVIDWIDTH, BASEVIDHEIGHT); } return SDL_TRUE; @@ -1620,7 +1288,7 @@ static void Impl_SetWindowIcon(void) { return; } - SDL2STUB(); + //SDL2STUB(); // Monster Iestyn: why is this stubbed? SDL_SetWindowIcon(window, icoSurface); } @@ -1718,7 +1386,6 @@ void I_StartupGraphics(void) borderlesswindow = M_CheckParm("-borderless"); //SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY>>1,SDL_DEFAULT_REPEAT_INTERVAL<<2); - SDLESSet(); VID_Command_ModeList_f(); #ifdef HWRENDER if (M_CheckParm("-opengl") || rendermode == render_opengl) diff --git a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj index c3f0d3b38..32ae88c02 100644 --- a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj +++ b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj @@ -1214,7 +1214,7 @@ C01FCF4B08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.14; + CURRENT_PROJECT_VERSION = 2.1.17; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", NORMALSRB2, @@ -1226,7 +1226,7 @@ C01FCF4C08A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.14; + CURRENT_PROJECT_VERSION = 2.1.17; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_PREPROCESSOR_DEFINITIONS = ( diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 4a46813c1..88bbadd20 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -220,7 +220,7 @@ static Mix_Chunk *ds2chunk(void *stream) break; default: // convert arbitrary hz to 44100. step = 0; - frac = ((UINT32)freq << FRACBITS) / 44100; + frac = ((UINT32)freq << FRACBITS) / 44100 + 1; //Add 1 to counter truncation. while (i < samples) { o = (INT16)(*s+0x80)<<8; // changed signedness and shift up to 16 bits diff --git a/src/sdl/ogl_sdl.h b/src/sdl/ogl_sdl.h index 7e144644c..2d6209f2b 100644 --- a/src/sdl/ogl_sdl.h +++ b/src/sdl/ogl_sdl.h @@ -24,7 +24,6 @@ boolean OglSdlSurface(INT32 w, INT32 h); void OglSdlFinishUpdate(boolean vidwait); -extern SDL_Window *window; extern SDL_Renderer *renderer; extern SDL_GLContext sdlglcontext; extern Uint16 realwidth; diff --git a/src/sdl/sdlmain.h b/src/sdl/sdlmain.h index 7ac32f4b3..fea1e1648 100644 --- a/src/sdl/sdlmain.h +++ b/src/sdl/sdlmain.h @@ -71,4 +71,7 @@ void I_GetConsoleEvents(void); void SDLforceUngrabMouse(void); +// Needed for some WIN32 functions +extern SDL_Window *window; + #endif diff --git a/src/sdl12/i_system.c b/src/sdl12/i_system.c index 888a6a507..ed0db653d 100644 --- a/src/sdl12/i_system.c +++ b/src/sdl12/i_system.c @@ -2666,6 +2666,18 @@ INT32 I_PutEnv(char *variable) #endif } +INT32 I_ClipboardCopy(const char *data, size_t size) +{ + (void)data; + (void)size; + return -1; +} + +char *I_ClipboardPaste(void) +{ + return NULL; +} + /** \brief The isWadPathOk function \param path string path to check diff --git a/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj b/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj index 98599fb60..13e78f314 100644 --- a/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj +++ b/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj @@ -1214,7 +1214,7 @@ C01FCF4B08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.14; + CURRENT_PROJECT_VERSION = 2.1.17; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", NORMALSRB2, @@ -1226,7 +1226,7 @@ C01FCF4C08A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.14; + CURRENT_PROJECT_VERSION = 2.1.17; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_PREPROCESSOR_DEFINITIONS = ( diff --git a/src/sounds.c b/src/sounds.c index 75ee1358c..b551b73b5 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -165,8 +165,12 @@ sfxinfo_t S_sfx[NUMSFX] = {"rail1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"rail2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"rlaunc", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"shield", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"shldls", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"shield", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // generic GET! + {"wirlsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Whirlwind GET! + {"forcsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Force GET! + {"elemsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Elemental GET! + {"armasg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Armaggeddon GET! + {"shldls", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // You LOSE! {"spdpad", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"spkdth", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"spring", false, 112, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -183,6 +187,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"wdjump", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"mswarp", false, 60, 16, -1, NULL, 0, -1, -1, LUMPERROR}, {"mspogo", false, 60, 8, -1, NULL, 0, -1, -1, LUMPERROR}, + {"boingf", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Menu, interface {"chchng", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR}, diff --git a/src/sounds.h b/src/sounds.h index 532c61da6..42fa4c308 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -229,6 +229,10 @@ typedef enum sfx_rail2, sfx_rlaunc, sfx_shield, + sfx_wirlsg, + sfx_forcsg, + sfx_elemsg, + sfx_armasg, sfx_shldls, sfx_spdpad, sfx_spkdth, @@ -246,6 +250,7 @@ typedef enum sfx_wdjump, sfx_mswarp, sfx_mspogo, + sfx_boingf, // Menu, interface sfx_chchng, diff --git a/src/st_stuff.c b/src/st_stuff.c index 626145847..658c2c6d6 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -99,6 +99,9 @@ static patch_t *ringshield; static patch_t *watershield; static patch_t *bombshield; static patch_t *pityshield; +static patch_t *flameshield; +static patch_t *bubbleshield; +static patch_t *thundershield; static patch_t *invincibility; static patch_t *sneakers; static patch_t *gravboots; @@ -288,15 +291,18 @@ void ST_LoadGraphics(void) scatterring = W_CachePatchName("SCATIND", PU_HUDGFX); grenadering = W_CachePatchName("GRENIND", PU_HUDGFX); railring = W_CachePatchName("RAILIND", PU_HUDGFX); - jumpshield = W_CachePatchName("WHTVB0", PU_HUDGFX); - forceshield = W_CachePatchName("BLTVB0", PU_HUDGFX); - ringshield = W_CachePatchName("YLTVB0", PU_HUDGFX); - watershield = W_CachePatchName("ELTVB0", PU_HUDGFX); - bombshield = W_CachePatchName("BKTVB0", PU_HUDGFX); - pityshield = W_CachePatchName("GRTVB0", PU_HUDGFX); - invincibility = W_CachePatchName("PINVB0", PU_HUDGFX); - sneakers = W_CachePatchName("SHTVB0", PU_HUDGFX); - gravboots = W_CachePatchName("GBTVB0", PU_HUDGFX); + jumpshield = W_CachePatchName("TVWWC0", PU_HUDGFX); + forceshield = W_CachePatchName("TVFOC0", PU_HUDGFX); + ringshield = W_CachePatchName("TVATC0", PU_HUDGFX); + watershield = W_CachePatchName("TVELC0", PU_HUDGFX); + bombshield = W_CachePatchName("TVARC0", PU_HUDGFX); + pityshield = W_CachePatchName("TVPIC0", PU_HUDGFX); + flameshield = W_CachePatchName("TVFLC0", PU_HUDGFX); + bubbleshield = W_CachePatchName("TVBBC0", PU_HUDGFX); + thundershield = W_CachePatchName("TVZPC0", PU_HUDGFX); + invincibility = W_CachePatchName("TVIVC0", PU_HUDGFX); + sneakers = W_CachePatchName("TVSSC0", PU_HUDGFX); + gravboots = W_CachePatchName("TVGVC0", PU_HUDGFX); tagico = W_CachePatchName("TAGICO", PU_HUDGFX); rflagico = W_CachePatchName("RFLAGICO", PU_HUDGFX); @@ -576,12 +582,13 @@ static void ST_drawDebugInfo(void) V_DrawRightAlignedString(320, height - 80, V_MONOSPACE, va("AIR: %4d, %3d", stplyr->powers[pw_underwater], stplyr->powers[pw_spacetime])); // Flags - V_DrawRightAlignedString(304-74, height - 72, V_MONOSPACE, "PF:"); - V_DrawString(304-72, height - 72, (stplyr->jumping) ? V_GREENMAP : V_REDMAP, "JM"); - V_DrawString(304-54, height - 72, (stplyr->pflags & PF_JUMPED) ? V_GREENMAP : V_REDMAP, "JD"); - V_DrawString(304-36, height - 72, (stplyr->pflags & PF_SPINNING) ? V_GREENMAP : V_REDMAP, "SP"); - V_DrawString(304-18, height - 72, (stplyr->pflags & PF_STARTDASH) ? V_GREENMAP : V_REDMAP, "ST"); - V_DrawString(304, height - 72, (stplyr->pflags & PF_THOKKED) ? V_GREENMAP : V_REDMAP, "TH"); + V_DrawRightAlignedString(304-92, height - 72, V_MONOSPACE, "PF:"); + V_DrawString(304-90, height - 72, (stplyr->jumping) ? V_GREENMAP : V_REDMAP, "JM"); + V_DrawString(304-72, height - 72, (stplyr->pflags & PF_JUMPED) ? V_GREENMAP : V_REDMAP, "JD"); + V_DrawString(304-54, height - 72, (stplyr->pflags & PF_SPINNING) ? V_GREENMAP : V_REDMAP, "SP"); + V_DrawString(304-36, height - 72, (stplyr->pflags & PF_STARTDASH) ? V_GREENMAP : V_REDMAP, "ST"); + V_DrawString(304-18, height - 72, (stplyr->pflags & PF_THOKKED) ? V_GREENMAP : V_REDMAP, "TH"); + V_DrawString(304, height - 72, (stplyr->pflags & PF_SHIELDABILITY) ? V_GREENMAP : V_REDMAP, "SH"); V_DrawRightAlignedString(320, height - 64, V_MONOSPACE, va("CEILZ: %6d", stplyr->mo->ceilingz>>FRACBITS)); V_DrawRightAlignedString(320, height - 56, V_MONOSPACE, va("FLOORZ: %6d", stplyr->mo->floorz>>FRACBITS)); @@ -672,9 +679,9 @@ static void ST_drawTime(void) static inline void ST_drawRings(void) { - INT32 ringnum = max(stplyr->health-1, 0); + INT32 ringnum = max(stplyr->rings, 0); - ST_DrawPatchFromHudWS(HUD_RINGS, ((stplyr->health <= 1 && leveltime/5 & 1) ? rrings : sborings)); + ST_DrawPatchFromHudWS(HUD_RINGS, ((stplyr->rings <= 0 && leveltime/5 & 1) ? rrings : sborings)); if (objectplacing) ringnum = op_currentdoomednum; @@ -683,8 +690,8 @@ static inline void ST_drawRings(void) INT32 i; ringnum = 0; for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].mo && players[i].mo->health > 1) - ringnum += players[i].mo->health - 1; + if (playeringame[i] && players[i].mo && players[i].rings > 0) + ringnum += players[i].rings; } ST_DrawNumFromHudWS(HUD_RINGSNUM, ringnum); @@ -806,18 +813,21 @@ static void ST_drawFirstPersonHUD(void) return; // Graue 06-18-2004: no V_NOSCALESTART, no SCX, no SCY, snap to right - if (player->powers[pw_shield] & SH_FORCE) + if ((player->powers[pw_shield] & SH_NOSTACK & ~SH_FORCEHP) == SH_FORCE) { - if ((player->powers[pw_shield] & 0xFF) > 0 || leveltime & 1) + if ((player->powers[pw_shield] & SH_FORCEHP) > 0 || leveltime & 1) p = forceshield; } else switch (player->powers[pw_shield] & SH_NOSTACK) { - case SH_JUMP: p = jumpshield; break; - case SH_ELEMENTAL: p = watershield; break; - case SH_BOMB: p = bombshield; break; - case SH_ATTRACT: p = ringshield; break; - case SH_PITY: p = pityshield; break; + case SH_WHIRLWIND: p = jumpshield; break; + case SH_ELEMENTAL: p = watershield; break; + case SH_ARMAGEDDON: p = bombshield; break; + case SH_ATTRACT: p = ringshield; break; + case SH_PITY: p = pityshield; break; + case SH_FLAMEAURA: p = flameshield; break; + case SH_BUBBLEWRAP: p = bubbleshield; break; + case SH_THUNDERCOIN: p = thundershield; break; default: break; } @@ -1153,11 +1163,11 @@ static void ST_drawNiGHTSHUD(void) INT32 i; total_ringcount = 0; for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] /*&& players[i].pflags & PF_NIGHTSMODE*/ && players[i].health) - total_ringcount += players[i].health - 1; + if (playeringame[i] /*&& players[i].pflags & PF_NIGHTSMODE*/ && players[i].rings) + total_ringcount += players[i].rings; } else - total_ringcount = stplyr->health-1; + total_ringcount = stplyr->rings; if (stplyr->capsule) { @@ -1369,7 +1379,7 @@ static void ST_drawWeaponRing(powertype_t weapon, INT32 rwflag, INT32 wepflag, I txtflags |= V_YELLOWMAP; if (weapon == pw_infinityring - || (stplyr->ringweapons & rwflag && stplyr->health > 1)) + || (stplyr->ringweapons & rwflag)) txtflags |= V_20TRANS; else { @@ -1407,7 +1417,7 @@ static void ST_drawMatchHUD(void) if (stplyr->powers[pw_infinityring]) ST_drawWeaponRing(pw_infinityring, 0, 0, offset, infinityring); - else if (stplyr->health > 1) + else if (stplyr->rings > 0) V_DrawScaledPatch(8 + offset, STRINGY(162), V_SNAPTOLEFT, normring); else V_DrawTranslucentPatch(8 + offset, STRINGY(162), V_SNAPTOLEFT|V_80TRANS, normring); diff --git a/src/v_video.c b/src/v_video.c index 91d730513..9109ce5cc 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -267,7 +267,7 @@ static void CV_Gammaxxx_ONChange(void) #endif -#if defined (__GNUC__) && defined (__i386__) && !defined (NOASM) && !defined (__APPLE__) +#if defined (__GNUC__) && defined (__i386__) && !defined (NOASM) && !defined (__APPLE__) && !defined (NORUSEASM) void VID_BlitLinearScreen_ASM(const UINT8 *srcptr, UINT8 *destptr, INT32 width, INT32 height, size_t srcrowbytes, size_t destrowbytes); #define HAVE_VIDCOPY @@ -774,43 +774,51 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) if (!screens[0]) return; - if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) - { // Clear the entire screen, from dest to deststop. Yes, this really works. - memset(screens[0], (UINT8)(c&255), vid.width * vid.height * vid.bpp); - return; - } - - dest = screens[0] + y*dupy*vid.width + x*dupx; - deststop = screens[0] + vid.rowbytes * vid.height; - - if (w == BASEVIDWIDTH) - w = vid.width; - else - w *= dupx; - if (h == BASEVIDHEIGHT) - h = vid.height; - else - h *= dupy; - - if (x && y && x + w < vid.width && y + h < vid.height) + if (c & V_NOSCALESTART) { - // Center it if necessary - if (vid.width != BASEVIDWIDTH * dupx) - { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, - // so center this imaginary screen - if (c & V_SNAPTORIGHT) - dest += (vid.width - (BASEVIDWIDTH * dupx)); - else if (!(c & V_SNAPTOLEFT)) - dest += (vid.width - (BASEVIDWIDTH * dupx)) / 2; + dest = screens[0] + y*vid.width + x; + deststop = screens[0] + vid.rowbytes * vid.height; + } + else + { + if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) + { // Clear the entire screen, from dest to deststop. Yes, this really works. + memset(screens[0], (UINT8)(c&255), vid.width * vid.height * vid.bpp); + return; } - if (vid.height != BASEVIDHEIGHT * dupy) + + dest = screens[0] + y*dupy*vid.width + x*dupx; + deststop = screens[0] + vid.rowbytes * vid.height; + + if (w == BASEVIDWIDTH) + w = vid.width; + else + w *= dupx; + if (h == BASEVIDHEIGHT) + h = vid.height; + else + h *= dupy; + + if (x && y && x + w < vid.width && y + h < vid.height) { - // same thing here - if (c & V_SNAPTOBOTTOM) - dest += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width; - else if (!(c & V_SNAPTOTOP)) - dest += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; + // Center it if necessary + if (vid.width != BASEVIDWIDTH * dupx) + { + // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, + // so center this imaginary screen + if (c & V_SNAPTORIGHT) + dest += (vid.width - (BASEVIDWIDTH * dupx)); + else if (!(c & V_SNAPTOLEFT)) + dest += (vid.width - (BASEVIDWIDTH * dupx)) / 2; + } + if (vid.height != BASEVIDHEIGHT * dupy) + { + // same thing here + if (c & V_SNAPTOBOTTOM) + dest += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width; + else if (!(c & V_SNAPTOTOP)) + dest += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2; + } } } @@ -968,45 +976,38 @@ void V_DrawFadeScreen(void) } // Simple translucency with one color, over a set number of lines starting from the top. -void V_DrawFadeConsBack(INT32 plines, INT32 pcolor) +void V_DrawFadeConsBack(INT32 plines) { - UINT8 *deststop, *colormap, *buf; + UINT8 *deststop, *buf; #ifdef HWRENDER // not win32 only 19990829 by Kin if (rendermode != render_soft && rendermode != render_none) { UINT32 hwcolor; - switch (pcolor) + switch (cons_backcolor.value) { - case 0: hwcolor = 0xffffff00; break; //white - case 1: hwcolor = 0xff800000; break; //orange - case 2: hwcolor = 0x0000ff00; break; //blue - case 3: hwcolor = 0x00800000; break; //green - case 4: hwcolor = 0x80808000; break; //gray - case 5: hwcolor = 0xff000000; break; //red - default: hwcolor = 0x00800000; break; //green + case 0: hwcolor = 0xffffff00; break; // White + case 1: hwcolor = 0x80808000; break; // Gray + case 2: hwcolor = 0x40201000; break; // Brown + case 3: hwcolor = 0xff000000; break; // Red + case 4: hwcolor = 0xff800000; break; // Orange + case 5: hwcolor = 0x80800000; break; // Yellow + case 6: hwcolor = 0x00800000; break; // Green + case 7: hwcolor = 0x0000ff00; break; // Blue + case 8: hwcolor = 0x4080ff00; break; // Cyan + // Default green + default: hwcolor = 0x00800000; break; } HWR_DrawConsoleBack(hwcolor, plines); return; } #endif - switch (pcolor) - { - case 0: colormap = cwhitemap; break; - case 1: colormap = corangemap; break; - case 2: colormap = cbluemap; break; - case 3: colormap = cgreenmap; break; - case 4: colormap = cgraymap; break; - case 5: colormap = credmap; break; - default: colormap = cgreenmap; break; - } - // heavily simplified -- we don't need to know x or y position, // just the stop position deststop = screens[0] + vid.rowbytes * min(plines, vid.height); for (buf = screens[0]; buf < deststop; ++buf) - *buf = colormap[*buf]; + *buf = consolebgmap[*buf]; } // Gets string colormap, used for 0x80 color codes diff --git a/src/v_video.h b/src/v_video.h index 70255d0ef..353f84c1d 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -145,7 +145,7 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum); // fade down the screen buffer before drawing the menu over void V_DrawFadeScreen(void); -void V_DrawFadeConsBack(INT32 plines, INT32 pcolor); +void V_DrawFadeConsBack(INT32 plines); // draw a single character void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed); diff --git a/src/w_wad.c b/src/w_wad.c index aeaad3ced..e4cb93050 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1223,6 +1223,7 @@ int W_VerifyNMUSlumps(const char *filename) {"COLORMAP", 8}, {"PAL", 3}, {"CLM", 3}, + {"TRANS", 5}, {NULL, 0}, }; return W_VerifyFile(filename, NMUSlist, false); diff --git a/src/win32/Makefile.cfg b/src/win32/Makefile.cfg index f309f7db1..99b8bc9b2 100644 --- a/src/win32/Makefile.cfg +++ b/src/win32/Makefile.cfg @@ -85,13 +85,21 @@ endif OBJS=$(OBJDIR)/dx_error.o $(OBJDIR)/fabdxlib.o $(OBJDIR)/win_vid.o $(OBJDIR)/win_dll.o endif + +ZLIB_CFLAGS?=-I../libs/zlib +ifdef MINGW64 +ZLIB_LDFLAGS?=-L../libs/zlib/win32 -lz64 +else +ZLIB_LDFLAGS?=-L../libs/zlib/win32 -lz32 +endif + ifndef NOPNG ifndef PNG_CONFIG - PNG_CFLAGS?=-I../libs/libpng-src -I../libs/zlib + PNG_CFLAGS?=-I../libs/libpng-src ifdef MINGW64 - PNG_LDFLAGS?=-L../libs/libpng-src/projects -lpng64 -L../libs/zlib/win32 -lz64 + PNG_LDFLAGS?=-L../libs/libpng-src/projects -lpng64 else - PNG_LDFLAGS?=-L../libs/libpng-src/projects -lpng32 -L../libs/zlib/win32 -lz32 + PNG_LDFLAGS?=-L../libs/libpng-src/projects -lpng32 endif #MINGW64 endif #PNG_CONFIG endif #NOPNG diff --git a/src/win32/Srb2win-vc10.vcxproj b/src/win32/Srb2win-vc10.vcxproj index 064f75d7d..95f9c85f9 100644 --- a/src/win32/Srb2win-vc10.vcxproj +++ b/src/win32/Srb2win-vc10.vcxproj @@ -131,6 +131,7 @@ </ClCompile> <ClCompile Include="..\i_tcp.c" /> <ClCompile Include="..\lua_baselib.c" /> + <ClCompile Include="..\lua_blockmaplib.c" /> <ClCompile Include="..\lua_consolelib.c" /> <ClCompile Include="..\lua_hooklib.c" /> <ClCompile Include="..\lua_hudlib.c" /> diff --git a/src/win32/Srb2win-vc10.vcxproj.filters b/src/win32/Srb2win-vc10.vcxproj.filters index b2647ea1c..cfd46f1f8 100644 --- a/src/win32/Srb2win-vc10.vcxproj.filters +++ b/src/win32/Srb2win-vc10.vcxproj.filters @@ -225,6 +225,9 @@ <ClCompile Include="..\lua_baselib.c"> <Filter>LUA</Filter> </ClCompile> + <ClCompile Include="..\lua_blockmaplib.c"> + <Filter>LUA</Filter> + </ClCompile> <ClCompile Include="..\lua_consolelib.c"> <Filter>LUA</Filter> </ClCompile> diff --git a/src/win32/win_dbg.c b/src/win32/win_dbg.c index 23416af1b..fe6ebb04a 100644 --- a/src/win32/win_dbg.c +++ b/src/win32/win_dbg.c @@ -20,7 +20,9 @@ #include <tchar.h> +#ifndef HAVE_SDL #include "win_main.h" +#endif #include "../doomdef.h" //just for VERSION #include "win_dbg.h" #include "../m_argv.h" //print the parameter in the log diff --git a/src/win32/win_main.c b/src/win32/win_main.c index 663eddbd4..d84c86232 100644 --- a/src/win32/win_main.c +++ b/src/win32/win_main.c @@ -69,7 +69,7 @@ static HCURSOR windowCursor = NULL; // main window cursor static LPCSTR wClassName = "SRB2WC"; -boolean appActive = false; // app window is active +INT appActive = false; // app window is active #ifdef LOGMESSAGES FILE *logstream; diff --git a/src/win32/win_main.h b/src/win32/win_main.h index ed55246ab..326a813dd 100644 --- a/src/win32/win_main.h +++ b/src/win32/win_main.h @@ -23,7 +23,7 @@ extern HWND hWndMain; -extern boolean appActive; +extern INT appActive; VOID I_GetSysMouseEvents(INT mouse_state); extern UINT MSHWheelMessage; diff --git a/src/win32/win_sys.c b/src/win32/win_sys.c index 0331080c8..80b89a6e6 100644 --- a/src/win32/win_sys.c +++ b/src/win32/win_sys.c @@ -3598,6 +3598,18 @@ INT32 I_PutEnv(char *variable) return putenv(variable); } +INT32 I_ClipboardCopy(const char *data, size_t size) +{ + (void)data; + (void)size; + return -1; +} + +const char *I_ClipboardPaste(void) +{ + return NULL; +} + typedef BOOL (WINAPI *p_IsProcessorFeaturePresent) (DWORD); const CPUInfoFlags *I_CPUInfo(void) diff --git a/src/win32ce/win_sys.c b/src/win32ce/win_sys.c index 88764ef73..3b6a47258 100644 --- a/src/win32ce/win_sys.c +++ b/src/win32ce/win_sys.c @@ -3470,6 +3470,18 @@ INT32 I_PutEnv(char *variable) return putenv(variable); } +INT32 I_ClipboardCopy(const char *data, size_t size) +{ + (void)data; + (void)size; + return -1; +} + +char *I_ClipboardPaste(void) +{ + return NULL; +} + typedef BOOL (WINAPI *MyFunc3) (DWORD); const CPUInfoFlags *I_CPUInfo(void) diff --git a/src/y_inter.c b/src/y_inter.c index 8f158a1b4..3b14f2837 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -839,13 +839,13 @@ static void Y_UpdateRecordReplays(void) if ((mainrecords[gamemap-1]->time == 0) || (players[consoleplayer].realtime < mainrecords[gamemap-1]->time)) mainrecords[gamemap-1]->time = players[consoleplayer].realtime; - if ((UINT16)(players[consoleplayer].health - 1) > mainrecords[gamemap-1]->rings) - mainrecords[gamemap-1]->rings = (UINT16)(players[consoleplayer].health - 1); + if ((UINT16)(players[consoleplayer].rings) > mainrecords[gamemap-1]->rings) + mainrecords[gamemap-1]->rings = (UINT16)(players[consoleplayer].rings); // Save demo! bestdemo[255] = '\0'; lastdemo[255] = '\0'; - G_SetDemoTime(players[consoleplayer].realtime, players[consoleplayer].score, (UINT16)(players[consoleplayer].health-1)); + G_SetDemoTime(players[consoleplayer].realtime, players[consoleplayer].score, (UINT16)(players[consoleplayer].rings)); G_CheckDemoStatus(); I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755); @@ -1435,7 +1435,7 @@ static void Y_CalculateCompetitionWinners(void) bestat[j] = true; times[i] = players[i].realtime; - rings[i] = (UINT32)max(players[i].health-1, 0); + rings[i] = (UINT32)max(players[i].rings, 0); maxrings[i] = (UINT32)players[i].totalring; monitors[i] = (UINT32)players[i].numboxes; scores[i] = (UINT32)min(players[i].score, 99999990); @@ -1450,7 +1450,7 @@ static void Y_CalculateCompetitionWinners(void) else bestat[0] = false; - if (max(players[i].health-1, 0) >= max(players[j].health-1, 0)) + if (max(players[i].rings, 0) >= max(players[j].rings, 0)) points[i]++; else bestat[1] = false; @@ -1573,7 +1573,7 @@ static void Y_SetRingBonus(player_t *player, y_bonus_t *bstruct) { strncpy(bstruct->patch, "YB_RING", sizeof(bstruct->patch)); bstruct->display = true; - bstruct->points = max(0, (player->health-1) * 100); + bstruct->points = max(0, (player->rings) * 100); } // @@ -1621,7 +1621,7 @@ static void Y_SetPerfectBonus(player_t *player, y_bonus_t *bstruct) for (i = 0; i < MAXPLAYERS; i++) { if (!playeringame[i]) continue; - sharedringtotal += players[i].health - 1; + sharedringtotal += players[i].rings; } if (!sharedringtotal || sharedringtotal < nummaprings) data.coop.gotperfbonus = 0;