Merge branch 'next' into md3-vanilla-kart

# Conflicts:
#	src/hardware/r_opengl/r_opengl.c
This commit is contained in:
wolfy852 2019-03-20 19:50:20 -05:00
commit 6b743d383b
140 changed files with 12510 additions and 10732 deletions

View File

@ -36,12 +36,15 @@ jobs:
- v1-SRB2-APT - v1-SRB2-APT
- run: - run:
name: Install SDK name: Install SDK
command: apt-get -qq -y install git build-essential nasm libpng12-dev:i386 libsdl2-mixer-dev:i386 libgme-dev:i386 gettext ccache wget gcc-multilib upx command: apt-get -qq -y --no-install-recommends install git build-essential nasm libpng12-dev:i386 libsdl2-mixer-dev:i386 libgme-dev:i386 gettext ccache wget gcc-multilib upx openssh-client
- save_cache: - save_cache:
key: v1-SRB2-APT key: v1-SRB2-APT
paths: paths:
- /var/cache/apt/archives - /var/cache/apt/archives
- checkout - checkout
- run:
name: Compile without network support
command: make -C src LINUX=1 ERRORMODE=1 -k NONET=1
- run: - run:
name: Clean build name: Clean build
command: make -C src LINUX=1 clean command: make -C src LINUX=1 clean

View File

@ -26,6 +26,7 @@ matrix:
- p7zip-full - p7zip-full
- gcc-4.4 - gcc-4.4
compiler: gcc-4.4 compiler: gcc-4.4
env: GCC44=1
if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/ if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
#gcc-4.4 (Ubuntu/Linaro 4.4.7-8ubuntu1) 4.4.7 #gcc-4.4 (Ubuntu/Linaro 4.4.7-8ubuntu1) 4.4.7
- os: linux - os: linux
@ -39,6 +40,7 @@ matrix:
- p7zip-full - p7zip-full
- gcc-4.6 - gcc-4.6
compiler: gcc-4.6 compiler: gcc-4.6
env: GCC46=1
if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/ if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
#gcc-4.6 (Ubuntu/Linaro 4.6.4-6ubuntu2) 4.6.4 #gcc-4.6 (Ubuntu/Linaro 4.6.4-6ubuntu2) 4.6.4
- os: linux - os: linux
@ -52,10 +54,12 @@ matrix:
- p7zip-full - p7zip-full
- gcc-4.7 - gcc-4.7
compiler: gcc-4.7 compiler: gcc-4.7
env: GCC47=1
if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/ if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
#gcc-4.7 #gcc-4.7
- os: linux - os: linux
compiler: gcc compiler: gcc
env: GCC48=1
if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/ if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
#gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4 #gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
- os: linux - os: linux
@ -71,6 +75,7 @@ matrix:
- p7zip-full - p7zip-full
- gcc-4.8 - gcc-4.8
compiler: gcc-4.8 compiler: gcc-4.8
env: GCC48=1
if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/ if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
#gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5 #gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5
- os: linux - os: linux
@ -86,7 +91,7 @@ matrix:
- p7zip-full - p7zip-full
- gcc-7 - gcc-7
compiler: gcc-7 compiler: gcc-7
env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough" env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough" GCC72=1
if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/ if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
#gcc-7 (Ubuntu 7.2.0-1ubuntu1~14.04) 7.2.0 20170802 #gcc-7 (Ubuntu 7.2.0-1ubuntu1~14.04) 7.2.0 20170802
- os: linux - os: linux
@ -102,7 +107,7 @@ matrix:
- p7zip-full - p7zip-full
- gcc-8 - gcc-8
compiler: gcc-8 compiler: gcc-8
env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough -Wno-error=format-overflow" env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough -Wno-error=format-overflow" GCC81=1
if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/ if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
#gcc-8 (Ubuntu 7.2.0-1ubuntu1~14.04) 8.1.0 #gcc-8 (Ubuntu 7.2.0-1ubuntu1~14.04) 8.1.0
- os: linux - os: linux

View File

@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0)
# DO NOT CHANGE THIS SRB2 STRING! Some variable names depend on this string. # DO NOT CHANGE THIS SRB2 STRING! Some variable names depend on this string.
# Version change is fine. # Version change is fine.
project(SRB2 project(SRB2
VERSION 1.0.2 VERSION 1.0.4
LANGUAGES C) LANGUAGES C)
if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR}) if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR})

View File

@ -1545,6 +1545,10 @@ HW3SOUND for 3D hardware sound support
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
<Unit filename="src/info.h" /> <Unit filename="src/info.h" />
<Unit filename="src/k_kart.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="src/k_kart.h" />
<Unit filename="src/keys.h" /> <Unit filename="src/keys.h" />
<Unit filename="src/lua_baselib.c"> <Unit filename="src/lua_baselib.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />

View File

@ -1,4 +1,4 @@
version: 1.0.2.{branch}-{build} version: 1.0.4.{branch}-{build}
os: MinGW os: MinGW
environment: environment:
@ -29,7 +29,7 @@ environment:
############################## ##############################
DPL_ENABLED: 0 DPL_ENABLED: 0
DPL_TAG_ENABLED: 0 DPL_TAG_ENABLED: 0
DPL_INSTALLER_NAME: srb2kart-v102 DPL_INSTALLER_NAME: srb2kart-v104
# Asset handling is barebones vs. Travis Deployer. We operate on 7z only. # Asset handling is barebones vs. Travis Deployer. We operate on 7z only.
# Include the README files and the OpenGL batch in the main and patch archives. # Include the README files and the OpenGL batch in the main and patch archives.
# The x86/x64 archives contain the DLL binaries. # The x86/x64 archives contain the DLL binaries.

View File

@ -129,7 +129,7 @@ Oni: Sev, Sal, and toast were the most unexpected things to ever happen to this
[Oni wiping sweat off his brow] Things only got more drastically revamped… very very rapidly. [Oni wiping sweat off his brow] Things only got more drastically revamped… very very rapidly.
The Mario aesthetic was entirely tossed out, as Sal was willing to work with me night and day on redoing most of everything about items… and then sounds. My power level for sprites massively jumped during TD development, so I decided to take it upon myself to do almost everything. Theyre such friendly and cooperative coders that I cant help but push a little harder than I used to (I was WAY lazier before they got here) to keep up. The Mario aesthetic was entirely tossed out, as Sal was willing to work with me night and day on redoing most of everything about items… and then sounds. My power level for sprites massively jumped during TD development, so I decided to take it upon myself to do almost everything. Theyre such friendly and cooperative coders that I cant help but push a little harder than I used to (I was WAY lazier before they got here) to keep up.

Binary file not shown.

Binary file not shown.

View File

@ -4,7 +4,7 @@ project(libgme)
include (CheckCXXCompilerFlag) include (CheckCXXCompilerFlag)
# When version is changed, also change the one in gme/gme.h to match # When version is changed, also change the one in gme/gme.h to match
set(GME_VERSION 0.6.0 CACHE INTERNAL "libgme Version") set(GME_VERSION 0.6.2 CACHE INTERNAL "libgme Version")
# 2.6+ always assumes FATAL_ERROR, but 2.4 and below don't. # 2.6+ always assumes FATAL_ERROR, but 2.4 and below don't.
# Of course, 2.4 might work, in which case you're welcome to drop # Of course, 2.4 might work, in which case you're welcome to drop
@ -57,6 +57,8 @@ if (USE_GME_NSFE AND NOT USE_GME_NSF)
SET(USE_GME_NSF 1 CACHE BOOL "Enable NES NSF music emulation" FORCE) SET(USE_GME_NSF 1 CACHE BOOL "Enable NES NSF music emulation" FORCE)
endif() endif()
option(BUILD_SHARED_LIBS "Build shared library (set to OFF for static library)" ON)
# Check for GCC "visibility" support. # Check for GCC "visibility" support.
if (CMAKE_COMPILER_IS_GNUCXX) if (CMAKE_COMPILER_IS_GNUCXX)
check_cxx_compiler_flag (-fvisibility=hidden __LIBGME_TEST_VISIBILITY) check_cxx_compiler_flag (-fvisibility=hidden __LIBGME_TEST_VISIBILITY)
@ -79,10 +81,10 @@ if (CMAKE_COMPILER_IS_GNUCXX)
endif() endif()
endif() endif()
endif() # test visibility endif() # test visibility
endif (CMAKE_COMPILER_IS_GNUCXX)
# Cache this result # Cache this result
set( LIBGME_HAVE_GCC_VISIBILITY ${ENABLE_VISIBILITY} CACHE BOOL "GCC support for hidden visibility") set( LIBGME_HAVE_GCC_VISIBILITY ${ENABLE_VISIBILITY} CACHE BOOL "GCC support for hidden visibility")
endif (CMAKE_COMPILER_IS_GNUCXX)
# Shared library defined here # Shared library defined here
add_subdirectory(gme) add_subdirectory(gme)

View File

@ -1,262 +1,5 @@
Game_Music_Emu Change Log Game_Music_Emu Change Log
------------------------- -------------------------
Game_Music_Emu 0.6.0 Please see the git version history (e.g. git shortlog tags/0.6.0..tags/0.6.1)
-------------------- for the accurate change log.
- Note: A 0.5.6 release was referenced but never tagged or packaged.
- SPC improvements:
- Switched to newer snes_spc 0.9.0 for SPC emulation. Uses fast DSP.
- Fixed Spc_Emu::gain().
- Fixed support for files <0x10200 bytes.
- Other bugfixes:
- Fixed a couple of GBS bugs, one involving access of memory after
realloc.
- Blip_Buffer works on systems where 'double' is a single-precision
floating-point type.
- Fix uninitialized buffer size in dual_resampler.
- Compilation warnings squashed out as of clang 3.3-pre and gcc 4.7.2.
- API changes/additions:
- Removed documentation of C++ interface, as the C interface in gme.h is
the only supported one.
- Added gme_enable_accuracy() for enabling more accurate sound emulation
options (currently affects SPC only).
- Build system improvements:
- Add pkg_config support.
- Fix build on case-insensitive systems.
- Allow for install on Cygwin.
- Fix install on multilib systems, such as many 64-bit distros (CMake must
be able to figure out your system's libsuffix, if any).
- C++ implementation symbols are not leaked into the resultant library
file (requires symbol visibility support).
- Sample player improvements:
- Can toggle fast/accurate emulation (with the 'A' key).
Game_Music_Emu 0.5.5
--------------------
- CMake build support has been added. You can build Game_Music_Emu as
a shared library and install it so that you do not have to include your
own copy if you know libgme will be present on your target system.
Requires CMake 2.6 or higher.
Game_Music_Emu 0.5.2
--------------------
- *TONS* of changes and improvements. You should re-read the new header
files and documentation as the changes will allow you to simplify your
code a lot (it might even be simpler to just rewrite it). Existing code
should continue to work without changes in most cases (see Deprecated
features in gme.txt).
- New file formats: AY, HES, KSS, SAP, NSFE
- All-new comprehensive C interface (also usable from C++). Simplifies
many things, especially file loading, and brings everything together in
one header file (gme.h).
- Information tags and track names and times can be accessed for all
game music formats
- New features supported by all emulators: end of track fading,
automatic silence detection, adjustable song tempo, seek to new time in
track
- Updated mini player example to support track names and times, echo,
tempo, and channel muting, and added visual waveform display
- Improved configuration to use blargg_config.h, which you can modify
and keep when you update to a newer libary version. Includes flag for
library to automatically handle gzipped files using zlib (so you don't
need to use Gzip_File_Reader anymore).
- GBS: Fixed wave channel to not reset waveform when APU is powered off
(affected Garfield). Also improved invalid bank selection (affected Game
& Watch and others).
- VGM: Added support for alternate noise shifter register
configurations, used by other systems like the BBC Micro.
- SPC: Removed IPL ROM dump from emulator, as none of the SPC files I
scanned needed it, and an SPC file can include a copy if necessary. Also
re-enabled supposed clamping in gaussian interpolation between the third
and fourth lookups, though I don't know whether it matters
- Added Music_Emu::load_mem() to use music data already in memory
(without copying it)
- Added Music_Emu::warning(), which reports minor problems when loading
and playing a music file
- Added Music_Emu::set_gain() for uniform adjustment of gain. Can only
be set during initialization, so not useful as a general volume control.
- Added custom operator new to ensure that no exceptions are thrown in
the library (I'd use std::nothrow if it were part of pre-ISO (ARM) C++)
- Added BLIP_BUFFER_FAST flag to blargg_config.h to use a lower quality
bandlimited synthesis in "classic" emulators, which might help
performance on ancient processors (measure first!). Don't use this
unless absolutely necessary, as quality suffers.
- Improved performance a bit for x86 platforms
- Text files now in DOS newline format so they will open in Notepad
properly
- Removed requirement that file header structures not have any padding
added to the end
- Fixed common bug in all CPU emulators where negative program counter
could crash emulator (occurred during a negative branch from the
beginning of memory). Also fixed related bug in Z80 emulator for
IX/IY+displacement mode.
- Eliminated all warnings when compiling on gcc 4.0. The following
generates no diagnostics:
gcc -S gme/*.cpp -o /dev/null -ansi -fno-gnu-keywords
-fno-nonansi-builtins -pedantic -W -Wabi -Wall -Wcast-align
-Wcast-qual -Wchar-subscripts -Wdisabled-optimization -Werror
-Winline -Wlong-long -Wmultichar -Winvalid-offsetof
-Wnon-virtual-dtor -Woverloaded-virtual -Wparentheses
-Wpointer-arith -Wredundant-decls -Wreorder -Wsign-compare
-Wsign-promo -Wunknown-pragmas -Wwrite-strings
Game_Music_Emu 0.3.0
--------------------
- Added more demos, including music player using the SDL multimedia
library for sound, and improved documentation
- All: Improved interface to emulators to allow simpler setup and
loading. Instead of various init() functions, all now support
set_sample_rate( long rate ) and load( const char* file_path ).
- All: Removed error return from start_track() and play(), and added
error_count() to get the total number of emulation errors since the
track was last started. See demos for examples of new usage.
- All: Fixed mute_voices() muting to be preserved after loading files
and starting tracks, instead of being cleared as it was whenever a track
was started
- VGM: Rewrote Vgm_Emu to support Sega Genesis/Mega Drive FM sound at
any sample rate with optional FM oversampling, support for alternate
YM2612 sound cores, and support for optional YM2413
- VGM: Added tempo control, useful for slowing 60Hz NTSC Sega Genesis
music to 50Hz PAL
- VGM: Removed Vgm_Emu::track_data(), since I realized that this
information is already present in the VGM header (oops!)
- GYM: Changed Gym_Emu::track_length() operation (see Gym_Emu.h)
- NSF: Added support for Sunsoft FME-7 sound chip used by Gimmick
soundtrack
- NSF: Fixed Namco 106 problems with Final Lap and others
- Moved library sources to gme/ directory to reduce clutter, and merged
boost/ functionality into blargg_common.h
- Added Gzip_File_Reader for transparently using gzipped files
Game_Music_Emu 0.2.4
--------------------
- Created a discussion forum for problems and feedback:
http://groups-beta.google.com/group/blargg-sound-libs
- Changed error return value of Blip_Buffer::sample_rate() (also for
Stereo_Buffer, Effects_Buffer, etc.) to blargg_err_t (defined in
blargg_common.h), to make error reporting consistent with other
functions. This means the "no error" return value is the opposite of
what it was before, which will break current code which checks the error
return value:
// current code (broken)
if ( !buf.sample_rate( samples_per_sec ) )
out_of_memory();
// quick-and-dirty fix (just remove the ! operation)
if ( buf.sample_rate( samples_per_sec ) )
out_of_memory();
// proper fix
blargg_err_t error = buf.sample_rate( samples_per_sec );
if ( error )
report_error( error );
- Implemented workaround for MSVC++ 6 compiler limitations, allowing it
to work on that compiler again
- Added sample clamping to avoid wrap-around at high volumes, allowing
higher volume with little distortion
- Added to-do list and design notes
- Added Music_Emu::skip( long sample_count ) to skip ahead in current
track
- Added Gym_Emu::track_length() and Vgm_Emu::track_length() for
determining the length of non-looped GYM and VGM files
- Partially implemented DMC non-linearity when its value is directly set
using $4011, which reduces previously over-emphasized "popping" of
percussion on some games (TMNT II in particular)
- Fixed Fir_Resampler, used for SPC and GYM playback (was incorrectly
using abs() instead of fabs()...argh)
- Fixed SPC emulation bugs: eliminated clicks in Plok! soundtrack and
now stops sample slightly earlier than the end, as the SNES does. Fixed
a totally broken CPU addressing mode.
- Fixed Konami VRC6 saw wave (was very broken before). Now VRC6 music
sounds decent
- Fixed a minor GBS emulation bug
- Fixed GYM loop point bug when track was restarted before loop point
had been reached
- Made default GBS frequency equalization less muffled
- Added pseudo-surround effect removal for SPC files
- Added Music_Emu::voice_names() which returns names for each voice.
- Added BLARGG_SOURCE_BEGIN which allows custom compiler options to be
easily set for library sources
- Changed assignment of expansion sound chips in Nsf_Emu to be spread
more evenly when using Effects_Buffer
- Changed 'size_t' values in Blip_Buffer interface to 'long'
- Changed demo to generate a WAVE sound file rather than an AIFF file
Game_Music_Emu 0.2.0
--------------------
- Redid framework and rewrote/cleaned up emulators
- Changed licensing to GNU Lesser General Public License (LGPL)
- Added Sega Genesis GYM and Super Nintendo SPC emulators
- Added Namco-106 and Konami VRC6 sound chip support to NSF emulator
- Eliminated use of static mutable data in emulators, allowing
multi-instance safety
Game_Music_Emu 0.1.0
--------------------
- First release

View File

@ -1,7 +1,5 @@
/* C example that opens a game music file and records 10 seconds to "out.wav" */ /* C example that opens a game music file and records 10 seconds to "out.wav" */
static char filename [] = "test.nsf"; /* opens this file (can be any music type) */
#include "gme/gme.h" #include "gme/gme.h"
#include "Wave_Writer.h" /* wave_ functions for writing sound file */ #include "Wave_Writer.h" /* wave_ functions for writing sound file */
@ -10,10 +8,15 @@ static char filename [] = "test.nsf"; /* opens this file (can be any music type)
void handle_error( const char* str ); void handle_error( const char* str );
int main() int main(int argc, char *argv[])
{ {
const char *filename = "test.nsf"; /* Default file to open */
if ( argc >= 2 )
filename = argv[1];
long sample_rate = 44100; /* number of samples per second */ long sample_rate = 44100; /* number of samples per second */
int track = 0; /* index of track to play (0 = first) */ /* index of track to play (0 = first) */
int track = argc >= 3 ? atoi(argv[2]) : 0;
/* Open music file in new emulator */ /* Open music file in new emulator */
Music_Emu* emu; Music_Emu* emu;

View File

@ -1,7 +1,5 @@
// C++ example that opens a game music file and records 10 seconds to "out.wav" // C++ example that opens a game music file and records 10 seconds to "out.wav"
static char filename [] = "test.nsf"; /* opens this file (can be any music type) */
#include "gme/Music_Emu.h" #include "gme/Music_Emu.h"
#include "Wave_Writer.h" #include "Wave_Writer.h"
@ -10,10 +8,15 @@ static char filename [] = "test.nsf"; /* opens this file (can be any music type)
void handle_error( const char* str ); void handle_error( const char* str );
int main() int main(int argc, char *argv[])
{ {
const char *filename = "test.nsf"; /* Default file to open */
if ( argc >= 2 )
filename = argv[1];
long sample_rate = 44100; // number of samples per second long sample_rate = 44100; // number of samples per second
int track = 0; // index of track to play (0 = first) // index of track to play (0 = first)
int track = argc >= 3 ? atoi(argv[2]) : 0;
// Determine file type // Determine file type
gme_type_t file_type; gme_type_t file_type;

View File

@ -1,10 +1,10 @@
Game_Music_Emu 0.6.0 Game_Music_Emu 0.6.2
-------------------- --------------------
Author : Shay Green <gblargg@gmail.com> Author : Shay Green <gblargg@gmail.com>
Website: http://www.slack.net/~ant/libs/ Maintainer : Michael Pyne <mpyne@purinchu.net>
Forum : http://groups.google.com/group/blargg-sound-libs Website : https://bitbucket.org/mpyne/game-music-emu/
Source : https://code.google.com/p/game-music-emu/ Source : https://bitbucket.org/mpyne/game-music-emu/
License: GNU Lesser General Public License (LGPL) License : GNU Lesser General Public License (LGPL), see LICENSE.txt
Contents Contents
-------- --------

View File

@ -143,7 +143,7 @@ add_definitions(-DBLARGG_BUILD_DLL)
include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_BINARY_DIR})
# Add library to be compiled. # Add library to be compiled.
add_library(gme SHARED ${libgme_SRCS}) add_library(gme ${libgme_SRCS})
# The version is the release. The "soversion" is the API version. As long # The version is the release. The "soversion" is the API version. As long
# as only build fixes are performed (i.e. no backwards-incompatible changes # as only build fixes are performed (i.e. no backwards-incompatible changes
@ -159,4 +159,4 @@ install(TARGETS gme LIBRARY DESTINATION lib${LIB_SUFFIX}
ARCHIVE DESTINATION lib) # DLL platforms ARCHIVE DESTINATION lib) # DLL platforms
install(FILES ${EXPORTED_HEADERS} DESTINATION include/gme) install(FILES ${EXPORTED_HEADERS} DESTINATION include/gme)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libgme.pc DESTINATION lib/pkgconfig) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libgme.pc DESTINATION lib${LIB_SUFFIX}/pkgconfig)

View File

@ -22,8 +22,13 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
const char Data_Reader::eof_error [] = "Unexpected end of file"; const char Data_Reader::eof_error [] = "Unexpected end of file";
#define RETURN_VALIDITY_CHECK( cond ) \
do { if ( unlikely( !(cond) ) ) return "Corrupt file"; } while(0)
blargg_err_t Data_Reader::read( void* p, long s ) blargg_err_t Data_Reader::read( void* p, long s )
{ {
RETURN_VALIDITY_CHECK( s > 0 );
long result = read_avail( p, s ); long result = read_avail( p, s );
if ( result != s ) if ( result != s )
{ {
@ -38,6 +43,8 @@ blargg_err_t Data_Reader::read( void* p, long s )
blargg_err_t Data_Reader::skip( long count ) blargg_err_t Data_Reader::skip( long count )
{ {
RETURN_VALIDITY_CHECK( count >= 0 );
char buf [512]; char buf [512];
while ( count ) while ( count )
{ {
@ -54,7 +61,8 @@ long File_Reader::remain() const { return size() - tell(); }
blargg_err_t File_Reader::skip( long n ) blargg_err_t File_Reader::skip( long n )
{ {
assert( n >= 0 ); RETURN_VALIDITY_CHECK( n >= 0 );
if ( !n ) if ( !n )
return 0; return 0;
return seek( tell() + n ); return seek( tell() + n );
@ -67,13 +75,14 @@ Subset_Reader::Subset_Reader( Data_Reader* dr, long size )
in = dr; in = dr;
remain_ = dr->remain(); remain_ = dr->remain();
if ( remain_ > size ) if ( remain_ > size )
remain_ = size; remain_ = max( 0l, size );
} }
long Subset_Reader::remain() const { return remain_; } long Subset_Reader::remain() const { return remain_; }
long Subset_Reader::read_avail( void* p, long s ) long Subset_Reader::read_avail( void* p, long s )
{ {
s = max( 0l, s );
if ( s > remain_ ) if ( s > remain_ )
s = remain_; s = remain_;
remain_ -= s; remain_ -= s;
@ -85,7 +94,7 @@ long Subset_Reader::read_avail( void* p, long s )
Remaining_Reader::Remaining_Reader( void const* h, long size, Data_Reader* r ) Remaining_Reader::Remaining_Reader( void const* h, long size, Data_Reader* r )
{ {
header = (char const*) h; header = (char const*) h;
header_end = header + size; header_end = header + max( 0l, size );
in = r; in = r;
} }
@ -93,6 +102,7 @@ long Remaining_Reader::remain() const { return header_end - header + in->remain(
long Remaining_Reader::read_first( void* out, long count ) long Remaining_Reader::read_first( void* out, long count )
{ {
count = max( 0l, count );
long first = header_end - header; long first = header_end - header;
if ( first ) if ( first )
{ {
@ -107,8 +117,9 @@ long Remaining_Reader::read_first( void* out, long count )
long Remaining_Reader::read_avail( void* out, long count ) long Remaining_Reader::read_avail( void* out, long count )
{ {
count = max( 0l, count );
long first = read_first( out, count ); long first = read_first( out, count );
long second = count - first; long second = max( 0l, count - first );
if ( second ) if ( second )
{ {
second = in->read_avail( (char*) out + first, second ); second = in->read_avail( (char*) out + first, second );
@ -120,8 +131,9 @@ long Remaining_Reader::read_avail( void* out, long count )
blargg_err_t Remaining_Reader::read( void* out, long count ) blargg_err_t Remaining_Reader::read( void* out, long count )
{ {
count = max( 0l, count );
long first = read_first( out, count ); long first = read_first( out, count );
long second = count - first; long second = max( 0l, count - first );
if ( !second ) if ( !second )
return 0; return 0;
return in->read( (char*) out + first, second ); return in->read( (char*) out + first, second );
@ -131,7 +143,7 @@ blargg_err_t Remaining_Reader::read( void* out, long count )
Mem_File_Reader::Mem_File_Reader( const void* p, long s ) : Mem_File_Reader::Mem_File_Reader( const void* p, long s ) :
begin( (const char*) p ), begin( (const char*) p ),
size_( s ) size_( max( 0l, s ) )
{ {
pos = 0; pos = 0;
} }
@ -141,6 +153,7 @@ long Mem_File_Reader::size() const { return size_; }
long Mem_File_Reader::read_avail( void* p, long s ) long Mem_File_Reader::read_avail( void* p, long s )
{ {
long r = remain(); long r = remain();
s = max( 0l, s );
if ( s > r ) if ( s > r )
s = r; s = r;
memcpy( p, begin + pos, s ); memcpy( p, begin + pos, s );
@ -152,6 +165,7 @@ long Mem_File_Reader::tell() const { return pos; }
blargg_err_t Mem_File_Reader::seek( long n ) blargg_err_t Mem_File_Reader::seek( long n )
{ {
RETURN_VALIDITY_CHECK( n >= 0 );
if ( n > size_ ) if ( n > size_ )
return eof_error; return eof_error;
pos = n; pos = n;
@ -164,7 +178,7 @@ Callback_Reader::Callback_Reader( callback_t c, long size, void* d ) :
callback( c ), callback( c ),
data( d ) data( d )
{ {
remain_ = size; remain_ = max( 0l, size );
} }
long Callback_Reader::remain() const { return remain_; } long Callback_Reader::remain() const { return remain_; }
@ -173,13 +187,14 @@ long Callback_Reader::read_avail( void* out, long count )
{ {
if ( count > remain_ ) if ( count > remain_ )
count = remain_; count = remain_;
if ( Callback_Reader::read( out, count ) ) if ( count < 0 || Callback_Reader::read( out, count ) )
count = -1; count = -1;
return count; return count;
} }
blargg_err_t Callback_Reader::read( void* out, long count ) blargg_err_t Callback_Reader::read( void* out, long count )
{ {
RETURN_VALIDITY_CHECK( count >= 0 );
if ( count > remain_ ) if ( count > remain_ )
return eof_error; return eof_error;
return callback( data, out, count ); return callback( data, out, count );
@ -210,11 +225,12 @@ long Std_File_Reader::size() const
long Std_File_Reader::read_avail( void* p, long s ) long Std_File_Reader::read_avail( void* p, long s )
{ {
return fread( p, 1, s, (FILE*) file_ ); return fread( p, 1, max( 0l, s ), (FILE*) file_ );
} }
blargg_err_t Std_File_Reader::read( void* p, long s ) blargg_err_t Std_File_Reader::read( void* p, long s )
{ {
RETURN_VALIDITY_CHECK( s > 0 );
if ( s == (long) fread( p, 1, s, (FILE*) file_ ) ) if ( s == (long) fread( p, 1, s, (FILE*) file_ ) )
return 0; return 0;
if ( feof( (FILE*) file_ ) ) if ( feof( (FILE*) file_ ) )

View File

@ -129,6 +129,8 @@ private:
}; };
#ifdef HAVE_ZLIB_H #ifdef HAVE_ZLIB_H
#include <zlib.h>
// Gzip compressed file reader // Gzip compressed file reader
class Gzip_File_Reader : public File_Reader { class Gzip_File_Reader : public File_Reader {
public: public:
@ -143,7 +145,7 @@ public:
long tell() const; long tell() const;
blargg_err_t seek( long ); blargg_err_t seek( long );
private: private:
void* file_; gzFile file_;
long size_; long size_;
}; };
#endif #endif

View File

@ -178,6 +178,11 @@ blargg_long Music_Emu::msec_to_samples( blargg_long msec ) const
return (sec * sample_rate() + msec * sample_rate() / 1000) * stereo; return (sec * sample_rate() + msec * sample_rate() / 1000) * stereo;
} }
long Music_Emu::tell_samples() const
{
return out_time;
}
long Music_Emu::tell() const long Music_Emu::tell() const
{ {
blargg_long rate = sample_rate() * stereo; blargg_long rate = sample_rate() * stereo;
@ -185,14 +190,18 @@ long Music_Emu::tell() const
return sec * 1000 + (out_time - sec * rate) * 1000 / rate; return sec * 1000 + (out_time - sec * rate) * 1000 / rate;
} }
blargg_err_t Music_Emu::seek( long msec ) blargg_err_t Music_Emu::seek_samples( long time )
{ {
blargg_long time = msec_to_samples( msec );
if ( time < out_time ) if ( time < out_time )
RETURN_ERR( start_track( current_track_ ) ); RETURN_ERR( start_track( current_track_ ) );
return skip( time - out_time ); return skip( time - out_time );
} }
blargg_err_t Music_Emu::seek( long msec )
{
return seek_samples( msec_to_samples( msec ) );
}
blargg_err_t Music_Emu::skip( long count ) blargg_err_t Music_Emu::skip( long count )
{ {
require( current_track() >= 0 ); // start_track() must have been called already require( current_track() >= 0 ); // start_track() must have been called already

View File

@ -41,9 +41,15 @@ public:
// Number of milliseconds (1000 msec = 1 second) played since beginning of track // Number of milliseconds (1000 msec = 1 second) played since beginning of track
long tell() const; long tell() const;
// Number of samples generated since beginning of track
long tell_samples() const;
// Seek to new time in track. Seeking backwards or far forward can take a while. // Seek to new time in track. Seeking backwards or far forward can take a while.
blargg_err_t seek( long msec ); blargg_err_t seek( long msec );
// Equivalent to restarting track then skipping n samples
blargg_err_t seek_samples( long n );
// Skip n samples // Skip n samples
blargg_err_t skip( long n ); blargg_err_t skip( long n );

View File

@ -134,6 +134,9 @@ blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsf_Emu* nsf_emu )
RETURN_ERR( in.read( block_header, sizeof block_header ) ); RETURN_ERR( in.read( block_header, sizeof block_header ) );
blargg_long size = get_le32( block_header [0] ); blargg_long size = get_le32( block_header [0] );
blargg_long tag = get_le32( block_header [1] ); blargg_long tag = get_le32( block_header [1] );
if ( size <= 0 )
return "Corrupt file";
//debug_printf( "tag: %c%c%c%c\n", char(tag), char(tag>>8), char(tag>>16), char(tag>>24) ); //debug_printf( "tag: %c%c%c%c\n", char(tag), char(tag>>8), char(tag>>16), char(tag>>24) );

View File

@ -433,9 +433,7 @@ void Snes_Spc::cpu_write( int data, int addr, rel_time_t time )
#endif #endif
// Registers other than $F2 and $F4-$F7 // Registers other than $F2 and $F4-$F7
//if ( reg != 2 && reg != 4 && reg != 5 && reg != 6 && reg != 7 ) if ( reg != 2 && (reg < 4 || reg > 7) ) // 36%
// TODO: this is a bit on the fragile side
if ( ((~0x2F00 << (bits_in_int - 16)) << reg) < 0 ) // 36%
cpu_write_smp_reg( data, time, reg ); cpu_write_smp_reg( data, time, reg );
} }
// High mem/address wrap-around // High mem/address wrap-around

View File

@ -76,8 +76,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
// TODO: remove non-wrapping versions? // TODO: remove non-wrapping versions?
#define SPC_NO_SP_WRAPAROUND 0 #define SPC_NO_SP_WRAPAROUND 0
#define SET_SP( v ) (sp = ram + 0x101 + (v)) #define SET_SP( v ) (sp = ram + 0x101 + ((uint8_t) v))
#define GET_SP() (sp - 0x101 - ram) #define GET_SP() (uint8_t (sp - 0x101 - ram))
#if SPC_NO_SP_WRAPAROUND #if SPC_NO_SP_WRAPAROUND
#define PUSH16( v ) (sp -= 2, SET_LE16( sp, v )) #define PUSH16( v ) (sp -= 2, SET_LE16( sp, v ))
@ -485,7 +485,7 @@ loop:
case 0xAF: // MOV (X)+,A case 0xAF: // MOV (X)+,A
WRITE_DP( 0, x, a + no_read_before_write ); WRITE_DP( 0, x, a + no_read_before_write );
x++; x = (uint8_t) (x + 1);
goto loop; goto loop;
// 5. 8-BIT LOGIC OPERATION COMMANDS // 5. 8-BIT LOGIC OPERATION COMMANDS
@ -808,7 +808,7 @@ loop:
unsigned temp = y * a; unsigned temp = y * a;
a = (uint8_t) temp; a = (uint8_t) temp;
nz = ((temp >> 1) | temp) & 0x7F; nz = ((temp >> 1) | temp) & 0x7F;
y = temp >> 8; y = (uint8_t) (temp >> 8);
nz |= y; nz |= y;
goto loop; goto loop;
} }
@ -838,6 +838,7 @@ loop:
nz = (uint8_t) a; nz = (uint8_t) a;
a = (uint8_t) a; a = (uint8_t) a;
y = (uint8_t) y;
goto loop; goto loop;
} }
@ -1004,7 +1005,7 @@ loop:
case 0x7F: // RET1 case 0x7F: // RET1
temp = *sp; temp = *sp;
SET_PC( GET_LE16( sp + 1 ) ); SET_PC( GET_LE16( sp + 1 ) );
sp += 3; SET_SP( GET_SP() + 3 );
goto set_psw; goto set_psw;
case 0x8E: // POP PSW case 0x8E: // POP PSW
POP( temp ); POP( temp );

View File

@ -18,6 +18,19 @@ all other #include lines. */
#undef require #undef require
#define require( expr ) assert( expr ) #define require( expr ) assert( expr )
// Use to provide hints to compiler for optimized code layout in situations where we
// can almost always expect a conditional to go one way or the other. Should only be
// used in situations where an unexpected branch is truly exceptional though!
#undef likely
#undef unlikely
#ifdef __GNUC__
#define likely( x ) __builtin_expect(x, 1)
#define unlikely( x ) __builtin_expect(x, 0)
#else
#define likely( x ) (x)
#define unlikely( x ) (x)
#endif
// Like printf() except output goes to debug log file. Might be defined to do // Like printf() except output goes to debug log file. Might be defined to do
// nothing (not even evaluate its arguments). // nothing (not even evaluate its arguments).
// void debug_printf( const char* format, ... ); // void debug_printf( const char* format, ... );

View File

@ -337,7 +337,9 @@ BLARGG_EXPORT gme_err_t gme_play ( Music_Emu* me, int n, short* p )
BLARGG_EXPORT void gme_set_fade ( Music_Emu* me, int start_msec ) { me->set_fade( start_msec ); } BLARGG_EXPORT void gme_set_fade ( Music_Emu* me, int start_msec ) { me->set_fade( start_msec ); }
BLARGG_EXPORT int gme_track_ended ( Music_Emu const* me ) { return me->track_ended(); } BLARGG_EXPORT int gme_track_ended ( Music_Emu const* me ) { return me->track_ended(); }
BLARGG_EXPORT int gme_tell ( Music_Emu const* me ) { return me->tell(); } BLARGG_EXPORT int gme_tell ( Music_Emu const* me ) { return me->tell(); }
BLARGG_EXPORT int gme_tell_samples ( Music_Emu const* me ) { return me->tell_samples(); }
BLARGG_EXPORT gme_err_t gme_seek ( Music_Emu* me, int msec ) { return me->seek( msec ); } BLARGG_EXPORT gme_err_t gme_seek ( Music_Emu* me, int msec ) { return me->seek( msec ); }
BLARGG_EXPORT gme_err_t gme_seek_samples ( Music_Emu* me, int n ) { return me->seek_samples( n ); }
BLARGG_EXPORT int gme_voice_count ( Music_Emu const* me ) { return me->voice_count(); } BLARGG_EXPORT int gme_voice_count ( Music_Emu const* me ) { return me->voice_count(); }
BLARGG_EXPORT void gme_ignore_silence ( Music_Emu* me, int disable ) { me->ignore_silence( disable != 0 ); } BLARGG_EXPORT void gme_ignore_silence ( Music_Emu* me, int disable ) { me->ignore_silence( disable != 0 ); }
BLARGG_EXPORT void gme_set_tempo ( Music_Emu* me, double t ) { me->set_tempo( t ); } BLARGG_EXPORT void gme_set_tempo ( Music_Emu* me, double t ) { me->set_tempo( t ); }

View File

@ -1,6 +1,6 @@
/* Game music emulator library C interface (also usable from C++) */ /* Game music emulator library C interface (also usable from C++) */
/* Game_Music_Emu 0.6.0 */ /* Game_Music_Emu 0.6.1 */
#ifndef GME_H #ifndef GME_H
#define GME_H #define GME_H
@ -8,7 +8,7 @@
extern "C" { extern "C" {
#endif #endif
#define GME_VERSION 0x000600 /* 1 byte major, 1 byte minor, 1 byte patch-level */ #define GME_VERSION 0x000601 /* 1 byte major, 1 byte minor, 1 byte patch-level */
/* Error string returned by library functions, or NULL if no error (success) */ /* Error string returned by library functions, or NULL if no error (success) */
typedef const char* gme_err_t; typedef const char* gme_err_t;
@ -47,9 +47,15 @@ int gme_track_ended( Music_Emu const* );
/* Number of milliseconds (1000 = one second) played since beginning of track */ /* Number of milliseconds (1000 = one second) played since beginning of track */
int gme_tell( Music_Emu const* ); int gme_tell( Music_Emu const* );
/* Number of samples generated since beginning of track */
int gme_tell_samples( Music_Emu const* );
/* Seek to new time in track. Seeking backwards or far forward can take a while. */ /* Seek to new time in track. Seeking backwards or far forward can take a while. */
gme_err_t gme_seek( Music_Emu*, int msec ); gme_err_t gme_seek( Music_Emu*, int msec );
/* Equivalent to restarting track then skipping n samples */
gme_err_t gme_seek_samples( Music_Emu*, int n );
/******** Informational ********/ /******** Informational ********/

View File

@ -3,7 +3,7 @@
# later are used by pkg-config. # later are used by pkg-config.
prefix=@CMAKE_INSTALL_PREFIX@ prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix} exec_prefix=${prefix}
lib_suffix= lib_suffix=@LIB_SUFFIX@
libdir=${exec_prefix}/lib${lib_suffix} libdir=${exec_prefix}/lib${lib_suffix}
includedir=${prefix}/include includedir=${prefix}/include
@ -13,3 +13,4 @@ URL: http://code.google.com/p/game-music-emu/
Version: @GME_VERSION@ Version: @GME_VERSION@
Cflags: -I${includedir} Cflags: -I${includedir}
Libs: -L${libdir} -lgme Libs: -L${libdir} -lgme
Libs.private: -lstdc++

View File

@ -1,6 +1,6 @@
/* Game music emulator library C interface (also usable from C++) */ /* Game music emulator library C interface (also usable from C++) */
/* Game_Music_Emu 0.6.0 */ /* Game_Music_Emu 0.6.1 */
#ifndef GME_H #ifndef GME_H
#define GME_H #define GME_H
@ -8,7 +8,7 @@
extern "C" { extern "C" {
#endif #endif
#define GME_VERSION 0x000600 /* 1 byte major, 1 byte minor, 1 byte patch-level */ #define GME_VERSION 0x000601 /* 1 byte major, 1 byte minor, 1 byte patch-level */
/* Error string returned by library functions, or NULL if no error (success) */ /* Error string returned by library functions, or NULL if no error (success) */
typedef const char* gme_err_t; typedef const char* gme_err_t;
@ -47,9 +47,15 @@ int gme_track_ended( Music_Emu const* );
/* Number of milliseconds (1000 = one second) played since beginning of track */ /* Number of milliseconds (1000 = one second) played since beginning of track */
int gme_tell( Music_Emu const* ); int gme_tell( Music_Emu const* );
/* Number of samples generated since beginning of track */
int gme_tell_samples( Music_Emu const* );
/* Seek to new time in track. Seeking backwards or far forward can take a while. */ /* Seek to new time in track. Seeking backwards or far forward can take a while. */
gme_err_t gme_seek( Music_Emu*, int msec ); gme_err_t gme_seek( Music_Emu*, int msec );
/* Equivalent to restarting track then skipping n samples */
gme_err_t gme_seek_samples( Music_Emu*, int n );
/******** Informational ********/ /******** Informational ********/

View File

@ -1,4 +1,4 @@
Game_Music_Emu 0.6.0: Game Music Emulators Game_Music_Emu 0.6.2: Game Music Emulators
------------------------------------------ ------------------------------------------
Game_Music_Emu is a collection of video game music file emulators that Game_Music_Emu is a collection of video game music file emulators that
support the following formats and systems: support the following formats and systems:
@ -34,30 +34,45 @@ several architectures, Mac OS, MorphOS, Xbox, PlayStation Portable,
GP2X, and Nintendo DS. GP2X, and Nintendo DS.
Author : Shay Green <gblargg@gmail.com> Author : Shay Green <gblargg@gmail.com>
Website: http://www.slack.net/~ant/ Website: https://bitbucket.org/mpyne/game-music-emu/wiki/Home
Forum : http://groups.google.com/group/blargg-sound-libs
License: GNU Lesser General Public License (LGPL) License: GNU Lesser General Public License (LGPL)
Current Maintainer: Michael Pyne <mpyne@purinchu.net>
Getting Started Getting Started
--------------- ---------------
Build a program consisting of demo/basics.c, demo/Wave_Writer.cpp, and Build a program consisting of demo/basics.c, demo/Wave_Writer.cpp, and
all source files in gme/. If you have CMake 2.6 or later, execute all source files in gme/.
run cmake Or, if you have CMake 2.6 or later, execute at a command prompt (from the
cd demo extracted source directory):
run make
Be sure "test.nsf" is in the same directory as the program. Running it mkdir build
cd build
cmake ../ # <-- Pass any needed CMake flags here
make # To build the library
cd demo
make # To build the demo itself
Be sure "test.nsf" is in the same directory as the demo program. Running it
should generate the recording "out.wav". should generate the recording "out.wav".
You can use "make install" to install the library. To choose where to install
the library to, use the CMake argument "-DCMAKE_INSTALL_PREFIX=/usr/local"
(and replace /usr/local with the base path you wish to use). Alternately, you
can specify the base path to install to when you run "make install" by passing
'DESTDIR=/usr/local' on the make install command line (again, replace
/usr/local as appropriate).
To build a static library instead of shared (the default), pass
-DBUILD_SHARED_LIBS=OFF to the cmake command when running cmake.
A slightly more extensive demo application is available in the player/ A slightly more extensive demo application is available in the player/
directory. It requires SDL to build. directory. It requires SDL to build.
Read gme.txt for more information. Post to the discussion forum for Read gme.txt for more information. Post to the discussion forum for
assistance. assistance.
Files Files
----- -----
gme.txt General notes about the library gme.txt General notes about the library

Binary file not shown.

Binary file not shown.

View File

@ -379,6 +379,12 @@ if(${SRB2_CONFIG_HAVE_PNG} AND ${SRB2_CONFIG_HAVE_ZLIB})
set(SRB2_HAVE_PNG ON) set(SRB2_HAVE_PNG ON)
add_definitions(-DHAVE_PNG) add_definitions(-DHAVE_PNG)
add_definitions(-D_LARGEFILE64_SOURCE) add_definitions(-D_LARGEFILE64_SOURCE)
set(SRB2_PNG_SOURCES apng.c)
set(SRB2_PNG_HEADERS apng.h)
prepend_sources(SRB2_PNG_SOURCES)
prepend_sources(SRB2_PNG_HEADERS)
source_group("Main" FILES ${SRB2_CORE_SOURCES} ${SRB2_CORE_HEADERS}
${SRB2_PNG_SOURCES} ${SRB2_PNG_HEADERS})
else() else()
message(WARNING "You have specified that PNG is available but it was not found. SRB2Kart may not compile correctly.") message(WARNING "You have specified that PNG is available but it was not found. SRB2Kart may not compile correctly.")
endif() endif()

View File

@ -342,6 +342,8 @@ endif
LIBS+=$(PNG_LDFLAGS) LIBS+=$(PNG_LDFLAGS)
CFLAGS+=$(PNG_CFLAGS) CFLAGS+=$(PNG_CFLAGS)
OBJS+=$(OBJDIR)/apng.o
endif endif
ifdef HAVE_LIBGME ifdef HAVE_LIBGME

View File

@ -7,6 +7,10 @@
# and other things # and other things
# #
ifdef GCC81
GCC80=1
endif
ifdef GCC80 ifdef GCC80
GCC72=1 GCC72=1
endif endif
@ -116,6 +120,7 @@ WFLAGS+=-Wfloat-equal
#WFLAGS+=-Wtraditional #WFLAGS+=-Wtraditional
ifdef VCHELP ifdef VCHELP
WFLAGS+=-Wdeclaration-after-statement WFLAGS+=-Wdeclaration-after-statement
WFLAGS+=-Wno-error=declaration-after-statement
endif endif
WFLAGS+=-Wundef WFLAGS+=-Wundef
ifndef GCC295 ifndef GCC295
@ -189,12 +194,6 @@ ifdef GCC46
WFLAGS+=-Wno-suggest-attribute=noreturn WFLAGS+=-Wno-suggest-attribute=noreturn
endif endif
ifndef MINGW
ifdef GCC45
WFLAGS+=-Wunsuffixed-float-constants
endif
endif
ifdef NOLDWARNING ifdef NOLDWARNING
LDFLAGS+=-Wl,--as-needed LDFLAGS+=-Wl,--as-needed
endif endif
@ -208,6 +207,9 @@ WFLAGS+=$(OLDWFLAGS)
ifdef GCC43 ifdef GCC43
#WFLAGS+=-Wno-error=clobbered #WFLAGS+=-Wno-error=clobbered
endif endif
ifdef GCC44
WFLAGS+=-Wno-error=array-bounds
endif
ifdef GCC46 ifdef GCC46
WFLAGS+=-Wno-error=suggest-attribute=noreturn WFLAGS+=-Wno-error=suggest-attribute=noreturn
endif endif
@ -228,6 +230,7 @@ ifdef GCC80
WFLAGS+=-Wno-format-overflow WFLAGS+=-Wno-format-overflow
WFLAGS+=-Wno-stringop-truncation WFLAGS+=-Wno-stringop-truncation
WFLAGS+=-Wno-stringop-overflow WFLAGS+=-Wno-stringop-overflow
WFLAGS+=-Wno-error=multistatement-macros
endif endif

289
src/apng.c Normal file
View File

@ -0,0 +1,289 @@
/*
Copyright 2019, James R.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdlib.h>
#include <string.h>
#include "apng.h"
#define APNG_INFO_acTL 0x20000U
#define APNG_WROTE_acTL 0x10000U
struct apng_info_def
{
png_uint_32 mode;
png_uint_32 valid;
png_uint_32 num_frames;
png_uint_32 num_plays;
long start_acTL;/* acTL is written here */
png_flush_ptr output_flush_fn;
apng_seek_ptr output_seek_fn;
apng_tell_ptr output_tell_fn;
apng_set_acTL_ptr set_acTL_fn;
};
/* PROTOS (FUCK COMPILER) */
void apng_seek (png_structp, apng_const_infop, size_t);
size_t apng_tell (png_structp, apng_const_infop);
#ifdef PNG_WRITE_FLUSH_SUPPORTED
void apng_flush (png_structp, apng_infop);
#ifdef PNG_STDIO_SUPPORTED
void apng_default_flush (png_structp);
#endif/* PNG_STDIO_SUPPORTED */
#endif/* PNG_WRITE_FLUSH_SUPPORTED */
#ifdef PNG_STDIO_SUPPORTED
void apng_default_seek (png_structp, size_t);
size_t apng_default_tell (png_structp);
#endif/* PNG_STDIO_SUPPORTED */
void apng_write_IEND (png_structp);
void apng_write_acTL (png_structp, png_uint_32, png_uint_32);
#ifndef PNG_WRITE_APNG_SUPPORTED
png_uint_32 apng_set_acTL_dummy (png_structp, png_infop,
png_uint_32, png_uint_32);
#endif/* PNG_WRITE_APNG_SUPPORTED */
apng_infop
apng_create_info_struct (png_structp pngp)
{
apng_infop ainfop;
(void)pngp;
if (( ainfop = calloc(sizeof (apng_info),1) ))
{
apng_set_write_fn(pngp, ainfop, 0, 0, 0, 0, 0);
apng_set_set_acTL_fn(pngp, ainfop, 0);
}
return ainfop;
}
void
apng_destroy_info_struct (png_structp pngp, apng_infopp ainfopp)
{
(void)pngp;
if (!( pngp && ainfopp ))
return;
free((*ainfopp));
}
void
apng_seek (png_structp pngp, apng_const_infop ainfop, size_t l)
{
(*(ainfop->output_seek_fn))(pngp, l);
}
size_t
apng_tell (png_structp pngp, apng_const_infop ainfop)
{
return (*(ainfop->output_tell_fn))(pngp);
}
#ifdef PNG_WRITE_FLUSH_SUPPORTED
void
apng_flush (png_structp pngp, apng_infop ainfop)
{
if (ainfop->output_flush_fn)
(*(ainfop->output_flush_fn))(pngp);
}
#ifdef PNG_STDIO_SUPPORTED
void
apng_default_flush (png_structp pngp)
{
if (!( pngp ))
return;
fflush((png_FILE_p)png_get_io_ptr);
}
#endif/* PNG_STDIO_SUPPORTED */
#endif/* PNG_WRITE_FLUSH_SUPPORTED */
#ifdef PNG_STDIO_SUPPORTED
void
apng_default_seek (png_structp pngp, size_t l)
{
if (!( pngp ))
return;
if (fseek((png_FILE_p)png_get_io_ptr(pngp), (long)l, SEEK_SET) == -1)
png_error(pngp, "Seek Error");
}
size_t
apng_default_tell (png_structp pngp)
{
long l;
if (!( pngp ))
{
png_error(pngp, "Call to apng_default_tell with NULL pngp failed");
}
if (( l = ftell((png_FILE_p)png_get_io_ptr(pngp)) ) == -1)
png_error(pngp, "Tell Error");
return (size_t)l;
}
#endif/* PNG_STDIO_SUPPORTED */
void
apng_set_write_fn (png_structp pngp, apng_infop ainfop, png_voidp iop,
png_rw_ptr write_f, png_flush_ptr flush_f,
apng_seek_ptr seek_f, apng_tell_ptr tell_f)
{
if (!( pngp && ainfop ))
return;
png_set_write_fn(pngp, iop, write_f, flush_f);
#ifdef PNG_WRITE_FLUSH_SUPPORTED
#ifdef PNG_STDIO_SUPPORTED
if (!flush_f)
ainfop->output_flush_fn = &apng_default_flush;
else
#endif/* PNG_STDIO_SUPPORTED */
ainfop->output_flush_fn = flush_f;
#endif/* PNG_WRITE_FLUSH_SUPPORTED */
#ifdef PNG_STDIO_SUPPORTED
if (!seek_f)
ainfop->output_seek_fn = &apng_default_seek;
else
#endif/* PNG_STDIO_SUPPORTED */
ainfop->output_seek_fn = seek_f;
#ifdef PNG_STDIO_SUPPORTED
if (!seek_f)
ainfop->output_tell_fn = apng_default_tell;
else
#endif/* PNG_STDIO_SUPPORTED */
ainfop->output_tell_fn = tell_f;
}
void
apng_write_IEND (png_structp pngp)
{
png_byte chunkc[] = "IEND";
png_write_chunk(pngp, chunkc, 0, 0);
}
void
apng_write_acTL (png_structp pngp, png_uint_32 frames, png_uint_32 plays)
{
png_byte chunkc[] = "acTL";
png_byte buf[8];
png_save_uint_32(buf, frames);
png_save_uint_32(buf + 4, plays);
png_write_chunk(pngp, chunkc, buf, 8);
}
png_uint_32
apng_set_acTL (png_structp pngp, png_infop infop, apng_infop ainfop,
png_uint_32 frames, png_uint_32 plays)
{
(void)pngp;
(void)infop;
if (!( pngp && infop && ainfop ))
return 0;
ainfop->num_frames = frames;
ainfop->num_plays = plays;
ainfop->valid |= APNG_INFO_acTL;
return 1;
}
void
apng_write_info_before_PLTE (png_structp pngp, png_infop infop,
apng_infop ainfop)
{
if (!( pngp && infop && ainfop ))
return;
png_write_info_before_PLTE(pngp, infop);
if (( ainfop->valid & APNG_INFO_acTL )&&!( ainfop->mode & APNG_WROTE_acTL ))
{
ainfop->start_acTL = apng_tell(pngp, ainfop);
apng_write_acTL(pngp, 0, 0);
/* modified for runtime dynamic linking */
(*(ainfop->set_acTL_fn))(pngp, infop, PNG_UINT_31_MAX, 0);
ainfop->mode |= APNG_WROTE_acTL;
}
}
void
apng_write_info (png_structp pngp, png_infop infop,
apng_infop ainfop)
{
apng_write_info_before_PLTE(pngp, infop, ainfop);
png_write_info(pngp, infop);
}
void
apng_write_end (png_structp pngp, png_infop infop, apng_infop ainfop)
{
(void)infop;
apng_write_IEND(pngp);
apng_seek(pngp, ainfop, ainfop->start_acTL);
apng_write_acTL(pngp, ainfop->num_frames, ainfop->num_plays);
#ifdef PNG_WRITE_FLUSH_SUPPORTED
#ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED
apng_flush(pngp, infop);
#endif/* PNG_WRITE_FLUSH_SUPPORTED */
#endif/* PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED */
}
#ifndef PNG_WRITE_APNG_SUPPORTED
png_uint_32
apng_set_acTL_dummy (png_structp pngp, png_infop infop,
png_uint_32 frames, png_uint_32 plays)
{
(void)pngp;
(void)infop;
(void)frames;
(void)plays;
return 0;
}
#endif/* PNG_WRITE_APNG_SUPPORTED */
/* Dynamic runtime linking capable! (Hopefully.) */
void
apng_set_set_acTL_fn (png_structp pngp, apng_infop ainfop,
apng_set_acTL_ptr set_acTL_f)
{
(void)pngp;
if (!ainfop->set_acTL_fn)
#ifndef PNG_WRITE_APNG_SUPPORTED
ainfop->set_acTL_fn = &apng_set_acTL_dummy;
#else
ainfop->set_acTL_fn = &png_set_acTL;
#endif/* PNG_WRITE_APNG_SUPPORTED */
else
ainfop->set_acTL_fn = set_acTL_f;
}

82
src/apng.h Normal file
View File

@ -0,0 +1,82 @@
/*
Copyright 2019, James R.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef APNG_H
#define APNG_H
#ifndef _MSC_VER
#ifndef _WII
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif
#endif
#endif
#ifndef _LFS64_LARGEFILE
#define _LFS64_LARGEFILE
#endif
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 0
#endif
#include <png.h>
typedef struct apng_info_def apng_info;
typedef apng_info * apng_infop;
typedef const apng_info * apng_const_infop;
typedef apng_info * * apng_infopp;
typedef void (*apng_seek_ptr)(png_structp, size_t);
typedef size_t (*apng_tell_ptr)(png_structp);
typedef png_uint_32 (*apng_set_acTL_ptr)(png_structp, png_infop,
png_uint_32, png_uint_32);
apng_infop apng_create_info_struct (png_structp png_ptr);
void apng_destroy_info_struct (png_structp png_ptr,
apng_infopp info_ptr_ptr);
/* Call the following functions in place of the libpng counterparts. */
png_uint_32 apng_set_acTL (png_structp png_ptr, png_infop info_ptr,
apng_infop ainfo_ptr,
png_uint_32 num_frames, png_uint_32 num_plays);
void apng_write_info_before_PLTE (png_structp png_ptr, png_infop info_ptr,
apng_infop ainfo_ptr);
void apng_write_info (png_structp png_ptr, png_infop info_ptr,
apng_infop ainfo_ptr);
void apng_write_end (png_structp png_ptr, png_infop info_ptr,
apng_infop ainfo_ptr);
void apng_set_write_fn (png_structp png_ptr, apng_infop ainfo_ptr,
png_voidp io_ptr,
png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn,
apng_seek_ptr output_seek_fn, apng_tell_ptr output_tell_fn);
void apng_set_set_acTL_fn (png_structp png_ptr, apng_infop ainfo_ptr,
apng_set_acTL_ptr set_acTL_fn);
#endif/* APNG_H */

View File

@ -1254,7 +1254,8 @@ found:
var->string = var->zstring = Z_StrDup(valstr); var->string = var->zstring = Z_StrDup(valstr);
if (override) if (var->flags & CV_PASSWORD); // Don't change value for password field
else if (override)
var->value = overrideval; var->value = overrideval;
else if (var->flags & CV_FLOAT) else if (var->flags & CV_FLOAT)
{ {

View File

@ -95,7 +95,8 @@ typedef enum
CV_HIDEN = 1024, // variable is not part of the cvar list so cannot be accessed by the console CV_HIDEN = 1024, // variable is not part of the cvar list so cannot be accessed by the console
// can only be set when we have the pointer to it // can only be set when we have the pointer to it
// used on menus // used on menus
CV_CHEAT = 2048 // Don't let this be used in multiplayer unless cheats are on. CV_CHEAT = 2048, // Don't let this be used in multiplayer unless cheats are on.
CV_PASSWORD = 4096 // Password field
} cvflags_t; } cvflags_t;
typedef struct CV_PossibleValue_s typedef struct CV_PossibleValue_s

View File

@ -36,8 +36,8 @@
/* Manually defined asset hashes for non-CMake builds /* Manually defined asset hashes for non-CMake builds
* Last updated 2015 / 05 / 03 - SRB2 v2.1.15 - srb2.srb * Last updated 2015 / 05 / 03 - SRB2 v2.1.15 - srb2.srb
* Last updated 2018 / 12 / 23 - SRB2 v2.1.22 - patch.dta * Last updated 2018 / 12 / 23 - SRB2 v2.1.22 - patch.dta
* Last updated 2018 / 11 / 16 - Kart v1.0.0 - Main assets * Last updated 2019 / 01 / 18 - Kart v1.0.2 - Main assets
* Last updated 2018 / 12 / 13 - Kart v1.0.2 - patch.kart * Last updated 2019 / 03 / 11 - Kart v1.0.4 - patch.kart
*/ */
// Base SRB2 hashes // Base SRB2 hashes
@ -49,10 +49,10 @@
// SRB2Kart-specific hashes // SRB2Kart-specific hashes
#define ASSET_HASH_GFX_KART "99c39f223d84ebc78e67ab68f3bead95" #define ASSET_HASH_GFX_KART "99c39f223d84ebc78e67ab68f3bead95"
#define ASSET_HASH_TEXTURES_KART "ec8e9b7535cf585afe72ef277b08f490" #define ASSET_HASH_TEXTURES_KART "ec8e9b7535cf585afe72ef277b08f490"
#define ASSET_HASH_CHARS_KART "784ee9177b01c8cb26edff43eaf93d87" #define ASSET_HASH_CHARS_KART "e2c428347dde52858a3dacd29fc5b964"
#define ASSET_HASH_MAPS_KART "84018d9b35d181ca9fcc2be5a9d43a45" #define ASSET_HASH_MAPS_KART "1335cd064656aedca359cfbb5233ac4a"
#ifdef USE_PATCH_KART #ifdef USE_PATCH_KART
#define ASSET_HASH_PATCH_KART "843a13a73935dc4df721427a8948fb89" #define ASSET_HASH_PATCH_KART "b5f48e1abccfa47a5745199182e2fef4"
#endif #endif
#endif #endif

View File

@ -544,6 +544,22 @@ static void CON_MoveConsole(void)
} }
} }
INT32 CON_ShiftChar(INT32 ch)
{
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
{
if (shiftdown ^ capslock)
ch = shiftxform[ch];
}
else // if we're holding shift we should still shift non letter symbols
{
if (shiftdown)
ch = shiftxform[ch];
}
return ch;
}
// Clear time of console heads up messages // Clear time of console heads up messages
// //
void CON_ClearHUD(void) void CON_ClearHUD(void)
@ -1084,16 +1100,6 @@ boolean CON_Responder(event_t *ev)
else if (key == KEY_KPADSLASH) else if (key == KEY_KPADSLASH)
key = '/'; key = '/';
// capslock
if (key == KEY_CAPSLOCK) // it's a toggle.
{
if (capslock)
capslock = false;
else
capslock = true;
return true;
}
// same capslock code as hu_stuff.c's HU_responder. Check there for details. // same capslock code as hu_stuff.c's HU_responder. Check there for details.
if ((key >= 'a' && key <= 'z') || (key >= 'A' && key <= 'Z')) if ((key >= 'a' && key <= 'z') || (key >= 'A' && key <= 'Z'))
{ {

View File

@ -44,6 +44,8 @@ extern UINT8 *yellowmap, *purplemap, *greenmap, *bluemap, *graymap, *redmap, *or
// Console bg color (auto updated to match) // Console bg color (auto updated to match)
extern UINT8 *consolebgmap; extern UINT8 *consolebgmap;
INT32 CON_ShiftChar(INT32 ch);
void CON_SetupBackColormap(void); void CON_SetupBackColormap(void);
void CON_ClearHUD(void); // clear heads up messages void CON_ClearHUD(void); // clear heads up messages

View File

@ -22,6 +22,7 @@
#include "i_video.h" #include "i_video.h"
#include "d_net.h" #include "d_net.h"
#include "d_main.h" #include "d_main.h"
#include "d_event.h"
#include "g_game.h" #include "g_game.h"
#include "hu_stuff.h" #include "hu_stuff.h"
#include "keys.h" #include "keys.h"
@ -72,6 +73,7 @@
#define PREDICTIONQUEUE BACKUPTICS #define PREDICTIONQUEUE BACKUPTICS
#define PREDICTIONMASK (PREDICTIONQUEUE-1) #define PREDICTIONMASK (PREDICTIONQUEUE-1)
#define MAX_REASONLENGTH 30 #define MAX_REASONLENGTH 30
#define FORCECLOSE 0x8000
boolean server = true; // true or false but !server == client boolean server = true; // true or false but !server == client
#define client (!server) #define client (!server)
@ -93,6 +95,7 @@ static tic_t freezetimeout[MAXNETNODES]; // Until when can this node freeze the
UINT16 pingmeasurecount = 1; UINT16 pingmeasurecount = 1;
UINT32 realpingtable[MAXPLAYERS]; //the base table of ping where an average will be sent to everyone. UINT32 realpingtable[MAXPLAYERS]; //the base table of ping where an average will be sent to everyone.
UINT32 playerpingtable[MAXPLAYERS]; //table of player latency values. UINT32 playerpingtable[MAXPLAYERS]; //table of player latency values.
tic_t servermaxping = 800; // server's max ping. Defaults to 800
#endif #endif
SINT8 nodetoplayer[MAXNETNODES]; SINT8 nodetoplayer[MAXNETNODES];
SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen) SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen)
@ -648,6 +651,8 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
rsp->jointime = (tic_t)LONG(players[i].jointime); rsp->jointime = (tic_t)LONG(players[i].jointime);
rsp->splitscreenindex = players[i].splitscreenindex;
rsp->hasmo = false; rsp->hasmo = false;
//Transfer important mo information if the player has a body. //Transfer important mo information if the player has a body.
//This lets us resync players even if they are dead. //This lets us resync players even if they are dead.
@ -783,6 +788,8 @@ static void resynch_read_player(resynch_pak *rsp)
players[i].jointime = (tic_t)LONG(rsp->jointime); players[i].jointime = (tic_t)LONG(rsp->jointime);
players[i].splitscreenindex = rsp->splitscreenindex;
//We get a packet for each player in game. //We get a packet for each player in game.
if (!playeringame[i]) if (!playeringame[i])
return; return;
@ -1121,12 +1128,22 @@ typedef enum
CL_DOWNLOADSAVEGAME, CL_DOWNLOADSAVEGAME,
#endif #endif
CL_CONNECTED, CL_CONNECTED,
CL_ABORTED CL_ABORTED,
CL_ASKDOWNLOADFILES,
CL_WAITDOWNLOADFILESRESPONSE,
CL_CHALLENGE
} cl_mode_t; } cl_mode_t;
static void GetPackets(void); static void GetPackets(void);
static cl_mode_t cl_mode = CL_SEARCHING; static cl_mode_t cl_mode = CL_SEARCHING;
static boolean cl_needsdownload = false;
static UINT8 cl_challengenum = 0;
static UINT8 cl_challengequestion[MD5_LEN+1];
static char cl_challengepassword[65];
static UINT8 cl_challengeanswer[MD5_LEN+1];
static UINT8 cl_challengeattempted = 0;
// Player name send/load // Player name send/load
@ -1163,6 +1180,8 @@ static void CV_LoadPlayerNames(UINT8 **p)
} }
#ifdef CLIENT_LOADINGSCREEN #ifdef CLIENT_LOADINGSCREEN
static UINT32 SL_SearchServer(INT32 node);
// //
// CL_DrawConnectionStatus // CL_DrawConnectionStatus
// //
@ -1186,11 +1205,42 @@ static inline void CL_DrawConnectionStatus(void)
// 15 pal entries total. // 15 pal entries total.
const char *cltext; const char *cltext;
for (i = 0; i < 16; ++i) if (cl_mode != CL_CHALLENGE)
V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-24, 16, 8, palstart + ((animtime - i) & 15)); for (i = 0; i < 16; ++i)
V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-24, 16, 8, palstart + ((animtime - i) & 15));
switch (cl_mode) switch (cl_mode)
{ {
case CL_CHALLENGE:
{
char asterisks[33];
size_t sl = min(32, strlen(cl_challengepassword));
UINT32 serverid;
memset(asterisks, '*', sl);
memset(asterisks+sl, 0, 33-sl);
V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, V_MONOSPACE|V_ALLOWLOWERCASE, asterisks);
V_DrawFixedPatch((BASEVIDWIDTH/2) << FRACBITS, (BASEVIDHEIGHT/2) << FRACBITS, FRACUNIT, 0, W_CachePatchName("BSRVLOCK", PU_CACHE), NULL);
serverid = SL_SearchServer(servernode);
if (serverid == UINT32_MAX)
{
M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT/2-8, 32, 1);
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, V_REDMAP, M_GetText("This server is password protected."));
}
else
{
M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT/2-8, 32, 3);
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, V_REDMAP, M_GetText("This server,"));
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2+8, V_ALLOWLOWERCASE, serverlist[serverid].info.servername);
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2+16, V_REDMAP, M_GetText("is password protected."));
}
cltext = M_GetText(cl_challengeattempted ? "Incorrect password. Please try again." : "Please enter the server password.");
}
break;
#ifdef JOININGAME #ifdef JOININGAME
case CL_DOWNLOADSAVEGAME: case CL_DOWNLOADSAVEGAME:
if (lastfilenum != -1) if (lastfilenum != -1)
@ -1210,6 +1260,9 @@ static inline void CL_DrawConnectionStatus(void)
case CL_WAITJOINRESPONSE: case CL_WAITJOINRESPONSE:
cltext = M_GetText("Requesting to join..."); cltext = M_GetText("Requesting to join...");
break; break;
case CL_ASKDOWNLOADFILES:
case CL_WAITDOWNLOADFILESRESPONSE:
cltext = M_GetText("Waiting to download files...");
default: default:
cltext = M_GetText("Connecting to server..."); cltext = M_GetText("Connecting to server...");
break; break;
@ -1287,6 +1340,9 @@ static boolean CL_SendJoin(void)
netbuffer->u.clientcfg.localplayers = localplayers; netbuffer->u.clientcfg.localplayers = localplayers;
netbuffer->u.clientcfg.version = VERSION; netbuffer->u.clientcfg.version = VERSION;
netbuffer->u.clientcfg.subversion = SUBVERSION; netbuffer->u.clientcfg.subversion = SUBVERSION;
netbuffer->u.clientcfg.needsdownload = cl_needsdownload;
netbuffer->u.clientcfg.challengenum = cl_challengenum;
memcpy(netbuffer->u.clientcfg.challengeanswer, cl_challengeanswer, MD5_LEN);
return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak)); return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak));
} }
@ -1307,7 +1363,13 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
netbuffer->u.serverinfo.gametype = (UINT8)(G_BattleGametype() ? VANILLA_GT_MATCH : VANILLA_GT_RACE); // SRB2Kart: Vanilla's gametype constants for MS support netbuffer->u.serverinfo.gametype = (UINT8)(G_BattleGametype() ? VANILLA_GT_MATCH : VANILLA_GT_RACE); // SRB2Kart: Vanilla's gametype constants for MS support
netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame; netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame;
netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled(); netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled();
netbuffer->u.serverinfo.isdedicated = (UINT8)dedicated;
netbuffer->u.serverinfo.kartvars = (UINT8) (
(cv_kartspeed.value & SV_SPEEDMASK) |
(dedicated ? SV_DEDICATED : 0) |
(D_IsJoinPasswordOn() ? SV_PASSWORD : 0)
);
strncpy(netbuffer->u.serverinfo.servername, cv_servername.string, strncpy(netbuffer->u.serverinfo.servername, cv_servername.string,
MAXSERVERNAME); MAXSERVERNAME);
strncpy(netbuffer->u.serverinfo.mapname, G_BuildMapName(gamemap), 7); strncpy(netbuffer->u.serverinfo.mapname, G_BuildMapName(gamemap), 7);
@ -1740,8 +1802,6 @@ static void SendAskInfo(INT32 node, boolean viams)
serverelem_t serverlist[MAXSERVERLIST]; serverelem_t serverlist[MAXSERVERLIST];
UINT32 serverlistcount = 0; UINT32 serverlistcount = 0;
#define FORCECLOSE 0x8000
static void SL_ClearServerList(INT32 connectedserver) static void SL_ClearServerList(INT32 connectedserver)
{ {
UINT32 i; UINT32 i;
@ -1867,7 +1927,7 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room)
/** Called by CL_ServerConnectionTicker /** Called by CL_ServerConnectionTicker
* *
* \param viams ??? * \param viams ???
* \param asksent ??? * \param asksent The last time we asked the server to join. We re-ask every second in case our request got lost in transmit.
* \return False if the connection was aborted * \return False if the connection was aborted
* \sa CL_ServerConnectionTicker * \sa CL_ServerConnectionTicker
* \sa CL_ConnectToServer * \sa CL_ConnectToServer
@ -1960,9 +2020,12 @@ static boolean CL_ServerConnectionSearchTicker(boolean viams, tic_t *asksent)
), NULL, MM_NOTHING); ), NULL, MM_NOTHING);
return false; return false;
} }
cl_mode = CL_ASKDOWNLOADFILES;
// no problem if can't send packet, we will retry later // no problem if can't send packet, we will retry later
if (CL_SendRequestFile()) //if (CL_SendRequestFile())
cl_mode = CL_DOWNLOADFILES; // cl_mode = CL_DOWNLOADFILES;
} }
} }
else else
@ -1992,7 +2055,7 @@ static boolean CL_ServerConnectionSearchTicker(boolean viams, tic_t *asksent)
* \param viams ??? * \param viams ???
* \param tmpsave The name of the gamestate file??? * \param tmpsave The name of the gamestate file???
* \param oldtic Used for knowing when to poll events and redraw * \param oldtic Used for knowing when to poll events and redraw
* \param asksent ??? * \param asksent The last time we asked the server to join. We re-ask every second in case our request got lost in transmit.
* \return False if the connection was aborted * \return False if the connection was aborted
* \sa CL_ServerConnectionSearchTicker * \sa CL_ServerConnectionSearchTicker
* \sa CL_ConnectToServer * \sa CL_ConnectToServer
@ -2030,6 +2093,7 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic
/* FALLTHRU */ /* FALLTHRU */
case CL_ASKJOIN: case CL_ASKJOIN:
cl_needsdownload = false;
CL_LoadServerFiles(); CL_LoadServerFiles();
#ifdef JOININGAME #ifdef JOININGAME
// prepare structures to save the file // prepare structures to save the file
@ -2038,9 +2102,23 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic
CL_PrepareDownloadSaveGame(tmpsave); CL_PrepareDownloadSaveGame(tmpsave);
#endif #endif
if (CL_SendJoin()) if (CL_SendJoin())
{
*asksent = I_GetTime();
cl_mode = CL_WAITJOINRESPONSE; cl_mode = CL_WAITJOINRESPONSE;
}
break; break;
case CL_ASKDOWNLOADFILES:
cl_needsdownload = true;
if (CL_SendJoin())
{
*asksent = I_GetTime();
cl_mode = CL_WAITDOWNLOADFILESRESPONSE;
}
break;
#ifdef JOININGAME #ifdef JOININGAME
case CL_DOWNLOADSAVEGAME: case CL_DOWNLOADSAVEGAME:
// At this state, the first (and only) needed file is the gamestate // At this state, the first (and only) needed file is the gamestate
@ -2054,7 +2132,19 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic
break; break;
#endif #endif
case CL_CHALLENGE:
(*asksent) = I_GetTime() - NEWTICRATE; // Send password immediately upon entering
break;
case CL_WAITJOINRESPONSE: case CL_WAITJOINRESPONSE:
case CL_WAITDOWNLOADFILESRESPONSE:
if (*asksent + NEWTICRATE < I_GetTime() && CL_SendJoin())
{
*asksent = I_GetTime();
}
break;
case CL_CONNECTED: case CL_CONNECTED:
default: default:
break; break;
@ -2072,19 +2162,10 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic
// Call it only once by tic // Call it only once by tic
if (*oldtic != I_GetTime()) if (*oldtic != I_GetTime())
{ {
INT32 key;
I_OsPolling(); I_OsPolling();
key = I_GetKey(); D_ProcessEvents();
if (key == KEY_ESCAPE || key == KEY_JOY1+1) if (gamestate != GS_WAITINGPLAYERS)
{
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; return false;
}
// why are these here? this is for servers, we're a client // why are these here? this is for servers, we're a client
//if (key == 's' && server) //if (key == 's' && server)
@ -2113,6 +2194,71 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic
return true; return true;
} }
boolean CL_Responder(event_t *ev)
{
size_t len;
INT32 ch;
if (!(client && cl_mode != CL_CONNECTED && cl_mode != CL_ABORTED))
return false; // Don't do anything outside of the connection screen
if (ev->type != ev_keydown)
return false;
ch = (INT32)ev->data1;
// Only ESC and non-keyboard keys abort connection
if (ch == KEY_ESCAPE || ch >= KEY_MOUSE1)
{
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 true;
}
if (cl_mode != CL_CHALLENGE)
return false;
if ((ch >= HU_FONTSTART && ch <= HU_FONTEND && hu_font[ch-HU_FONTSTART])
|| ch == ' ') // Allow spaces, of course
{
len = strlen(cl_challengepassword);
if (len < 64)
{
cl_challengepassword[len+1] = 0;
cl_challengepassword[len] = CON_ShiftChar(ch);
}
cl_challengeattempted = 0;
}
else if (ch == KEY_BACKSPACE)
{
len = strlen(cl_challengepassword);
if (len > 0)
cl_challengepassword[len-1] = 0;
cl_challengeattempted = 0;
}
else if (ch == KEY_ENTER)
{
netgame = true;
multiplayer = true;
#ifndef NONET
SL_ClearServerList(servernode);
#endif
cl_mode = CL_SEARCHING;
D_ComputeChallengeAnswer(cl_challengequestion, cl_challengepassword, cl_challengeanswer);
cl_challengeattempted = 1;
}
return true;
}
/** Use adaptive send using net_bandwidth and stat.sendbytes /** Use adaptive send using net_bandwidth and stat.sendbytes
* *
* \param viams ??? * \param viams ???
@ -2133,6 +2279,7 @@ static void CL_ConnectToServer(boolean viams)
#endif #endif
cl_mode = CL_SEARCHING; cl_mode = CL_SEARCHING;
cl_challengenum = 0;
#ifdef CLIENT_LOADINGSCREEN #ifdef CLIENT_LOADINGSCREEN
lastfilenum = -1; lastfilenum = -1;
@ -2190,6 +2337,8 @@ static void CL_ConnectToServer(boolean viams)
SL_ClearServerList(servernode); SL_ClearServerList(servernode);
#endif #endif
cl_challengeattempted = 0;
do do
{ {
// If the connection was aborted for some reason, leave // If the connection was aborted for some reason, leave
@ -2210,8 +2359,10 @@ static void CL_ConnectToServer(boolean viams)
} }
while (!(cl_mode == CL_CONNECTED && (client || (server && nodewaited <= pnumnodes)))); while (!(cl_mode == CL_CONNECTED && (client || (server && nodewaited <= pnumnodes))));
#ifndef NONET
if (netgame) if (netgame)
F_StartWaitingPlayers(); F_StartWaitingPlayers();
#endif
DEBFILE(va("Synchronisation Finished\n")); DEBFILE(va("Synchronisation Finished\n"));
displayplayer = consoleplayer; displayplayer = consoleplayer;
@ -2539,6 +2690,8 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason)
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
LUAh_PlayerQuit(&players[playernum], reason); // Lua hook for player quitting LUAh_PlayerQuit(&players[playernum], reason); // Lua hook for player quitting
#else
(void)reason;
#endif #endif
// Reset player data // Reset player data
@ -2722,7 +2875,10 @@ static void Command_Ban(void)
else else
{ {
if (server) // only the server is allowed to do this right now if (server) // only the server is allowed to do this right now
{
Ban_Add(COM_Argv(2)); Ban_Add(COM_Argv(2));
D_SaveBan(); // save the ban list
}
if (COM_Argc() == 2) if (COM_Argc() == 2)
{ {
@ -2753,6 +2909,42 @@ static void Command_Ban(void)
} }
static void Command_BanIP(void)
{
if (COM_Argc() < 2)
{
CONS_Printf(M_GetText("banip <ip> <reason>: ban an ip address\n"));
return;
}
if (server) // Only the server can use this, otherwise does nothing.
{
const char *address = (COM_Argv(1));
const char *reason;
if (COM_Argc() == 2)
reason = NULL;
else
reason = COM_Argv(2);
if (I_SetBanAddress && I_SetBanAddress(address, NULL))
{
if (reason)
CONS_Printf("Banned IP address %s for: %s\n", address, reason);
else
CONS_Printf("Banned IP address %s\n", address);
Ban_Add(reason);
D_SaveBan();
}
else
{
return;
}
}
}
static void Command_Kick(void) static void Command_Kick(void)
{ {
if (COM_Argc() < 2) if (COM_Argc() < 2)
@ -3024,6 +3216,9 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
} }
} }
static CV_PossibleValue_t netticbuffer_cons_t[] = {{0, "MIN"}, {3, "MAX"}, {0, NULL}};
consvar_t cv_netticbuffer = {"netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL }; consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL };
#ifdef VANILLAJOINNEXTROUND #ifdef VANILLAJOINNEXTROUND
consvar_t cv_joinnextround = {"joinnextround", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done consvar_t cv_joinnextround = {"joinnextround", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done
@ -3056,6 +3251,7 @@ void D_ClientServerInit(void)
COM_AddCommand("getplayernum", Command_GetPlayerNum); COM_AddCommand("getplayernum", Command_GetPlayerNum);
COM_AddCommand("kick", Command_Kick); COM_AddCommand("kick", Command_Kick);
COM_AddCommand("ban", Command_Ban); COM_AddCommand("ban", Command_Ban);
COM_AddCommand("banip", Command_BanIP);
COM_AddCommand("clearbans", Command_ClearBans); COM_AddCommand("clearbans", Command_ClearBans);
COM_AddCommand("showbanlist", Command_ShowBan); COM_AddCommand("showbanlist", Command_ShowBan);
COM_AddCommand("reloadbans", Command_ReloadBan); COM_AddCommand("reloadbans", Command_ReloadBan);
@ -3079,7 +3275,6 @@ void D_ClientServerInit(void)
CV_RegisterVar(&cv_joinnextround); CV_RegisterVar(&cv_joinnextround);
#endif #endif
CV_RegisterVar(&cv_showjoinaddress); CV_RegisterVar(&cv_showjoinaddress);
CV_RegisterVar(&cv_resynchattempts);
CV_RegisterVar(&cv_blamecfail); CV_RegisterVar(&cv_blamecfail);
#ifdef DUMPCONSISTENCY #ifdef DUMPCONSISTENCY
CV_RegisterVar(&cv_dumpconsistency); CV_RegisterVar(&cv_dumpconsistency);
@ -3090,6 +3285,9 @@ void D_ClientServerInit(void)
gametic = 0; gametic = 0;
localgametic = 0; localgametic = 0;
memset(cl_challengequestion, 0x00, MD5_LEN+1);
memset(cl_challengeanswer, 0x00, MD5_LEN+1);
// do not send anything before the real begin // do not send anything before the real begin
SV_StopServer(); SV_StopServer();
SV_ResetServer(); SV_ResetServer();
@ -3311,6 +3509,8 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
addedtogame = true; addedtogame = true;
} }
players[newplayernum].splitscreenindex = splitscreenplayer;
if (netgame) if (netgame)
{ {
if (server && cv_showjoinaddress.value) if (server && cv_showjoinaddress.value)
@ -3577,6 +3777,33 @@ static void HandleConnect(SINT8 node)
boolean newnode = false; boolean newnode = false;
#endif #endif
if (node != servernode && !nodeingame[node] && D_IsJoinPasswordOn())
{
// Ensure node sent the correct password challenge
boolean passed = false;
if (netbuffer->u.clientcfg.challengenum && D_VerifyJoinPasswordChallenge(netbuffer->u.clientcfg.challengenum, netbuffer->u.clientcfg.challengeanswer))
passed = true;
if (!passed)
{
D_MakeJoinPasswordChallenge(&netbuffer->u.joinchallenge.challengenum, netbuffer->u.joinchallenge.question);
netbuffer->packettype = PT_JOINCHALLENGE;
HSendPacket(node, true, 0, sizeof(joinchallenge_pak));
Net_CloseConnection(node);
return;
}
}
if (netbuffer->u.clientcfg.needsdownload)
{
netbuffer->packettype = PT_DOWNLOADFILESOKAY;
HSendPacket(node, true, 0, 0);
return;
}
// client authorised to join // client authorised to join
nodewaiting[node] = (UINT8)(netbuffer->u.clientcfg.localplayers - playerpernode[node]); nodewaiting[node] = (UINT8)(netbuffer->u.clientcfg.localplayers - playerpernode[node]);
if (!nodeingame[node]) if (!nodeingame[node])
@ -3585,6 +3812,7 @@ static void HandleConnect(SINT8 node)
#ifndef NONET #ifndef NONET
newnode = true; newnode = true;
#endif #endif
SV_AddNode(node); SV_AddNode(node);
/// \note Wait what??? /// \note Wait what???
@ -3740,6 +3968,43 @@ static void HandlePacketFromAwayNode(SINT8 node)
Net_CloseConnection(node); Net_CloseConnection(node);
break; break;
case PT_JOINCHALLENGE:
if (server && serverrunning)
{ // But wait I thought I'm the server?
Net_CloseConnection(node);
break;
}
SERVERONLY
if (cl_mode == CL_WAITJOINRESPONSE || cl_mode == CL_WAITDOWNLOADFILESRESPONSE)
{
cl_challengenum = netbuffer->u.joinchallenge.challengenum;
memcpy(cl_challengequestion, netbuffer->u.joinchallenge.question, 16);
Net_CloseConnection(node|FORCECLOSE); // Don't need to stay connected while challenging
cl_mode = CL_CHALLENGE;
switch (cl_challengeattempted)
{
case 2:
// We already sent a correct password, so throw it back up again.
D_ComputeChallengeAnswer(cl_challengequestion, cl_challengepassword, cl_challengeanswer);
cl_mode = CL_ASKJOIN;
break;
case 1:
// We entered the wrong password!
S_StartSound(NULL, sfx_s26d);
break;
default:
// First entry to the password screen.
S_StartSound(NULL, sfx_s224);
break;
}
}
break;
case PT_SERVERREFUSE: // Negative response of client join request case PT_SERVERREFUSE: // Negative response of client join request
if (server && serverrunning) if (server && serverrunning)
{ // But wait I thought I'm the server? { // But wait I thought I'm the server?
@ -3768,6 +4033,41 @@ static void HandlePacketFromAwayNode(SINT8 node)
} }
break; break;
case PT_DOWNLOADFILESOKAY:
if (server && serverrunning)
{ // But wait I thought I'm the server?
Net_CloseConnection(node);
break;
}
SERVERONLY
// This should've already been checked, but just to be safe...
if (!CL_CheckDownloadable())
{
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);
break;
}
if (cl_challengeattempted == 1) // Successful password noise.
S_StartSound(NULL, sfx_s221);
cl_challengeattempted = 2;
CONS_Printf("trying to download\n");
if (CL_SendRequestFile())
cl_mode = CL_DOWNLOADFILES;
break;
case PT_SERVERCFG: // Positive response of client join request case PT_SERVERCFG: // Positive response of client join request
{ {
INT32 j; INT32 j;
@ -3783,6 +4083,9 @@ static void HandlePacketFromAwayNode(SINT8 node)
if (cl_mode != CL_WAITJOINRESPONSE) if (cl_mode != CL_WAITJOINRESPONSE)
break; break;
if (cl_challengeattempted == 1) // Successful password noise.
S_StartSound(NULL, sfx_s221);
if (client) if (client)
{ {
maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic); maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic);
@ -3882,6 +4185,32 @@ static void HandlePacketFromAwayNode(SINT8 node)
#undef SERVERONLY #undef SERVERONLY
} }
/** Checks ticcmd for "speed hacks"
*
* \param p Which player
* \return True if player is hacking
* \sa HandlePacketFromPlayer
*
*/
static boolean CheckForSpeedHacks(UINT8 p)
{
if (netcmds[maketic%BACKUPTICS][p].forwardmove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][p].forwardmove < -MAXPLMOVE
|| netcmds[maketic%BACKUPTICS][p].sidemove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][p].sidemove < -MAXPLMOVE
|| netcmds[maketic%BACKUPTICS][p].driftturn > KART_FULLTURN || netcmds[maketic%BACKUPTICS][p].driftturn < -KART_FULLTURN)
{
XBOXSTATIC char buf[2];
CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), playernode[p]);
//D_Clearticcmd(k);
buf[0] = (char)p;
buf[1] = KICK_MSG_CON_FAIL;
SendNetXCmd(XD_KICK, &buf, 2);
return true;
}
return false;
}
/** Handles a packet received from a node that is in game /** Handles a packet received from a node that is in game
* *
* \param node The packet sender * \param node The packet sender
@ -3976,18 +4305,8 @@ FILESTAMP
G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1); G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1);
// Check ticcmd for "speed hacks" // Check ticcmd for "speed hacks"
if (netcmds[maketic%BACKUPTICS][netconsole].forwardmove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].forwardmove < -MAXPLMOVE if (CheckForSpeedHacks((UINT8)netconsole))
|| 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; break;
}
// Splitscreen cmd // Splitscreen cmd
if (((netbuffer->packettype == PT_CLIENT2CMD || netbuffer->packettype == PT_CLIENT2MIS) if (((netbuffer->packettype == PT_CLIENT2CMD || netbuffer->packettype == PT_CLIENT2MIS)
@ -3997,6 +4316,9 @@ FILESTAMP
{ {
G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]], G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]],
&netbuffer->u.client2pak.cmd2, 1); &netbuffer->u.client2pak.cmd2, 1);
if (CheckForSpeedHacks((UINT8)nodetoplayer2[node]))
break;
} }
if (((netbuffer->packettype == PT_CLIENT3CMD || netbuffer->packettype == PT_CLIENT3MIS) if (((netbuffer->packettype == PT_CLIENT3CMD || netbuffer->packettype == PT_CLIENT3MIS)
@ -4005,6 +4327,9 @@ FILESTAMP
{ {
G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer3[node]], G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer3[node]],
&netbuffer->u.client3pak.cmd3, 1); &netbuffer->u.client3pak.cmd3, 1);
if (CheckForSpeedHacks((UINT8)nodetoplayer3[node]))
break;
} }
if ((netbuffer->packettype == PT_CLIENT4CMD || netbuffer->packettype == PT_CLIENT4MIS) if ((netbuffer->packettype == PT_CLIENT4CMD || netbuffer->packettype == PT_CLIENT4MIS)
@ -4012,6 +4337,9 @@ FILESTAMP
{ {
G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer4[node]], G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer4[node]],
&netbuffer->u.client4pak.cmd4, 1); &netbuffer->u.client4pak.cmd4, 1);
if (CheckForSpeedHacks((UINT8)nodetoplayer4[node]))
break;
} }
// A delay before we check resynching // A delay before we check resynching
@ -4055,6 +4383,21 @@ FILESTAMP
else if (resynch_score[node]) else if (resynch_score[node])
--resynch_score[node]; --resynch_score[node];
break; break;
case PT_BASICKEEPALIVE:
if (client)
break;
// This should probably still timeout though, as the node should always have a player 1 number
if (netconsole == -1)
break;
// If a client sends this it should mean they are done receiving the savegame
sendingsavegame[node] = false;
// As long as clients send keep alives, the server can keep running, so reset the timeout
/// \todo Use a separate cvar for that kind of timeout?
freezetimeout[node] = I_GetTime() + connectiontimeout;
break;
case PT_TEXTCMD: case PT_TEXTCMD:
case PT_TEXTCMD2: case PT_TEXTCMD2:
case PT_TEXTCMD3: case PT_TEXTCMD3:
@ -4308,10 +4651,12 @@ FILESTAMP
//Update client ping table from the server. //Update client ping table from the server.
if (client) if (client)
{ {
INT32 i; UINT8 i;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i]) if (playeringame[i])
playerpingtable[i] = (tic_t)netbuffer->u.pingtable[i]; playerpingtable[i] = (tic_t)netbuffer->u.pingtable[i];
servermaxping = (tic_t)netbuffer->u.pingtable[MAXPLAYERS];
} }
break; break;
@ -4558,6 +4903,15 @@ static INT16 Consistancy(void)
return (INT16)(ret & 0xFFFF); return (INT16)(ret & 0xFFFF);
} }
// confusing, but this DOESN'T send PT_NODEKEEPALIVE, it sends PT_BASICKEEPALIVE
// used during wipes to tell the server that a node is still connected
static void CL_SendClientKeepAlive(void)
{
netbuffer->packettype = PT_BASICKEEPALIVE;
HSendPacket(servernode, false, 0, 0);
}
// send the client packet to the server // send the client packet to the server
static void CL_SendClientCmd(void) static void CL_SendClientCmd(void)
{ {
@ -4932,6 +5286,10 @@ void TryRunTics(tic_t realtics)
ExtraDataTicker(); ExtraDataTicker();
gametic++; gametic++;
consistancy[gametic%BACKUPTICS] = Consistancy(); consistancy[gametic%BACKUPTICS] = Consistancy();
// Leave a certain amount of tics present in the net buffer as long as we've ran at least one tic this frame.
if (client && gamestate == GS_LEVEL && leveltime > 3 && neededtic <= gametic + cv_netticbuffer.value)
break;
} }
} }
else else
@ -4941,6 +5299,18 @@ void TryRunTics(tic_t realtics)
} }
#ifdef NEWPING #ifdef NEWPING
/* Ping Update except better:
We call this once per second and check for people's pings. If their ping happens to be too high, we increment some timer and kick them out.
If they're not lagging, decrement the timer by 1. Of course, reset all of this if they leave.
Why do we do that? Well, I'm a person with unfortunately sometimes unstable internet and happen to keep getting kicked very unconveniently for very short high spikes. (700+ ms)
Because my spikes are so high, the average ping is exponentially higher too (700s really add up...!) which leads me to getting kicked for a short burst of spiking.
With this change here, this doesn't happen anymore as it checks if my ping has been CONSISTENTLY bad for long enough before killing me.
*/
static INT32 pingtimeout[MAXPLAYERS];
static inline void PingUpdate(void) static inline void PingUpdate(void)
{ {
INT32 i; INT32 i;
@ -4961,6 +5331,9 @@ static inline void PingUpdate(void)
laggers[i] = true; laggers[i] = true;
numlaggers++; numlaggers++;
} }
else
pingtimeout[i] = 0;
} }
//kick lagging players... unless everyone but the server's ping sucks. //kick lagging players... unless everyone but the server's ping sucks.
@ -4971,12 +5344,20 @@ static inline void PingUpdate(void)
{ {
if (playeringame[i] && laggers[i]) if (playeringame[i] && laggers[i])
{ {
XBOXSTATIC char buf[2]; pingtimeout[i]++;
if (pingtimeout[i] > cv_pingtimeout.value) // ok your net has been bad for too long, you deserve to die.
{
XBOXSTATIC char buf[2];
buf[0] = (char)i; pingtimeout[i] = 0;
buf[1] = KICK_MSG_PING_HIGH;
SendNetXCmd(XD_KICK, &buf, 2); buf[0] = (char)i;
buf[1] = KICK_MSG_PING_HIGH;
SendNetXCmd(XD_KICK, &buf, 2);
}
} }
else // you aren't lagging, but you aren't free yet. In case you'll keep spiking, we just make the timer go back down. (Very unstable net must still get kicked).
pingtimeout[i] = (pingtimeout[i] == 0 ? 0 : pingtimeout[i]-1);
} }
} }
} }
@ -4991,18 +5372,89 @@ static inline void PingUpdate(void)
realpingtable[i] = 0; //Reset each as we go. realpingtable[i] = 0; //Reset each as we go.
} }
// send the server's maxping as last element of our ping table. This is useful to let us know when we're about to get kicked.
netbuffer->u.pingtable[MAXPLAYERS] = cv_maxping.value;
//send out our ping packets //send out our ping packets
for (i = 0; i < MAXNETNODES; i++) for (i = 0; i < MAXNETNODES; i++)
if (nodeingame[i]) if (nodeingame[i])
HSendPacket(i, true, 0, sizeof(INT32) * MAXPLAYERS); HSendPacket(i, true, 0, sizeof(INT32) * (MAXPLAYERS+1));
pingmeasurecount = 1; //Reset count pingmeasurecount = 1; //Reset count
} }
#endif #endif
static tic_t gametime = 0;
#ifdef NEWPING
static void UpdatePingTable(void)
{
INT32 i;
if (server)
{
if (netgame && !(gametime % 35)) // update once per second.
PingUpdate();
// update node latency values so we can take an average later.
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i]));
pingmeasurecount++;
}
}
#endif
// Handle timeouts to prevent definitive freezes from happenning
static void HandleNodeTimeouts(void)
{
INT32 i;
if (server)
for (i = 1; i < MAXNETNODES; i++)
if (nodeingame[i] && freezetimeout[i] < I_GetTime())
Net_ConnectionTimeout(i);
}
// Keep the network alive while not advancing tics!
void NetKeepAlive(void)
{
tic_t nowtime;
INT32 realtics;
nowtime = I_GetTime();
realtics = nowtime - gametime;
// return if there's no time passed since the last call
if (realtics <= 0) // nothing new to update
return;
#ifdef NEWPING
UpdatePingTable();
#endif
if (server)
CL_SendClientKeepAlive();
// Sryder: What is FILESTAMP???
FILESTAMP
GetPackets();
FILESTAMP
MasterClient_Ticker();
if (client)
{
// send keep alive
CL_SendClientKeepAlive();
// No need to check for resynch because we aren't running any tics
}
// No else because no tics are being run and we can't resynch during this
Net_AckTicker();
HandleNodeTimeouts();
SV_FileSendTicker();
}
void NetUpdate(void) void NetUpdate(void)
{ {
static tic_t gametime = 0;
static tic_t resptime = 0; static tic_t resptime = 0;
tic_t nowtime; tic_t nowtime;
INT32 i; INT32 i;
@ -5024,16 +5476,7 @@ void NetUpdate(void)
gametime = nowtime; gametime = nowtime;
#ifdef NEWPING #ifdef NEWPING
if (server) UpdatePingTable();
{
if (netgame && !(gametime % 255))
PingUpdate();
// update node latency values so we can take an average later.
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i]));
pingmeasurecount++;
}
#endif #endif
if (client) if (client)
@ -5101,12 +5544,7 @@ FILESTAMP
} }
} }
Net_AckTicker(); Net_AckTicker();
// Handle timeouts to prevent definitive freezes from happenning HandleNodeTimeouts();
if (server)
for (i = 1; i < MAXNETNODES; i++)
if (nodeingame[i] && freezetimeout[i] < I_GetTime())
Net_ConnectionTimeout(i);
nowtime /= NEWTICRATERATIO;
if (nowtime > resptime) if (nowtime > resptime)
{ {
resptime = nowtime; resptime = nowtime;

View File

@ -13,11 +13,14 @@
#ifndef __D_CLISRV__ #ifndef __D_CLISRV__
#define __D_CLISRV__ #define __D_CLISRV__
#include "d_event.h"
#include "d_ticcmd.h" #include "d_ticcmd.h"
#include "d_netcmd.h" #include "d_netcmd.h"
#include "tables.h" #include "tables.h"
#include "d_player.h" #include "d_player.h"
#include "md5.h"
// Network play related stuff. // Network play related stuff.
// There is a data struct that stores network // There is a data struct that stores network
// communication related stuff, and another // communication related stuff, and another
@ -71,6 +74,10 @@ typedef enum
PT_CLIENT3MIS, PT_CLIENT3MIS,
PT_CLIENT4CMD, // 4P PT_CLIENT4CMD, // 4P
PT_CLIENT4MIS, PT_CLIENT4MIS,
PT_BASICKEEPALIVE,// Keep the network alive during wipes, as tics aren't advanced and NetUpdate isn't called
PT_JOINCHALLENGE, // You must give a password to joinnnnn
PT_DOWNLOADFILESOKAY, // You can download files from the server....
PT_CANFAIL, // This is kind of a priority. Anything bigger than CANFAIL PT_CANFAIL, // This is kind of a priority. Anything bigger than CANFAIL
// allows HSendPacket(*, true, *, *) to return false. // allows HSendPacket(*, true, *, *) to return false.
@ -282,6 +289,8 @@ typedef struct
tic_t jointime; tic_t jointime;
UINT8 splitscreenindex;
//player->mo stuff //player->mo stuff
UINT8 hasmo; // Boolean UINT8 hasmo; // Boolean
@ -350,9 +359,21 @@ typedef struct
UINT8 version; // Different versions don't work UINT8 version; // Different versions don't work
UINT8 subversion; // Contains build version UINT8 subversion; // Contains build version
UINT8 localplayers; UINT8 localplayers;
UINT8 mode; UINT8 needsdownload;
UINT8 challengenum; // Non-zero if trying to join with a password attempt
UINT8 challengeanswer[MD5_LEN]; // Join challenge
} ATTRPACK clientconfig_pak; } ATTRPACK clientconfig_pak;
typedef struct
{
UINT8 challengenum; // Number to send back in join attempt
UINT8 question[MD5_LEN]; // Challenge data to be manipulated and answered with
} ATTRPACK joinchallenge_pak;
#define SV_SPEEDMASK 0x03
#define SV_DEDICATED 0x40
#define SV_PASSWORD 0x80
#define MAXSERVERNAME 32 #define MAXSERVERNAME 32
#define MAXFILENEEDED 915 #define MAXFILENEEDED 915
// This packet is too large // This packet is too large
@ -365,7 +386,7 @@ typedef struct
UINT8 gametype; UINT8 gametype;
UINT8 modifiedgame; UINT8 modifiedgame;
UINT8 cheatsenabled; UINT8 cheatsenabled;
UINT8 isdedicated; UINT8 kartvars; // Previously isdedicated, now appropriated for our own nefarious purposes
UINT8 fileneedednum; UINT8 fileneedednum;
SINT8 adminplayer; SINT8 adminplayer;
tic_t time; tic_t time;
@ -433,10 +454,10 @@ typedef struct
UINT8 reserved; // Padding UINT8 reserved; // Padding
union union
{ {
clientcmd_pak clientpak; // 144 bytes clientcmd_pak clientpak; // 145 bytes
client2cmd_pak client2pak; // 200 bytes client2cmd_pak client2pak; // 202 bytes
client3cmd_pak client3pak; // 256 bytes(?) client3cmd_pak client3pak; // 258 bytes(?)
client4cmd_pak client4pak; // 312 bytes(?) client4cmd_pak client4pak; // 316 bytes(?)
servertics_pak serverpak; // 132495 bytes (more around 360, no?) servertics_pak serverpak; // 132495 bytes (more around 360, no?)
serverconfig_pak servercfg; // 773 bytes serverconfig_pak servercfg; // 773 bytes
resynchend_pak resynchend; // resynchend_pak resynchend; //
@ -444,15 +465,16 @@ typedef struct
UINT8 resynchgot; // UINT8 resynchgot; //
UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...) UINT8 textcmd[MAXTEXTCMD+1]; // 66049 bytes (wut??? 64k??? More like 257 bytes...)
filetx_pak filetxpak; // 139 bytes filetx_pak filetxpak; // 139 bytes
clientconfig_pak clientcfg; // 136 bytes clientconfig_pak clientcfg; // 153 bytes
joinchallenge_pak joinchallenge; // 17 bytes
serverinfo_pak serverinfo; // 1024 bytes serverinfo_pak serverinfo; // 1024 bytes
serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...) serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...)
askinfo_pak askinfo; // 61 bytes askinfo_pak askinfo; // 61 bytes
msaskinfo_pak msaskinfo; // 22 bytes msaskinfo_pak msaskinfo; // 22 bytes
plrinfo playerinfo[MAXPLAYERS]; // 1152 bytes (I'd say 36~38) plrinfo playerinfo[MAXPLAYERS]; // 576 bytes(?)
plrconfig playerconfig[MAXPLAYERS]; // (up to) 896 bytes (welp they ARE) plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?)
#ifdef NEWPING #ifdef NEWPING
UINT32 pingtable[MAXPLAYERS]; // 128 bytes UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes
#endif #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; } ATTRPACK doomdata_t;
@ -518,13 +540,14 @@ extern tic_t jointimeout;
extern UINT16 pingmeasurecount; extern UINT16 pingmeasurecount;
extern UINT32 realpingtable[MAXPLAYERS]; extern UINT32 realpingtable[MAXPLAYERS];
extern UINT32 playerpingtable[MAXPLAYERS]; extern UINT32 playerpingtable[MAXPLAYERS];
extern tic_t servermaxping;
#endif #endif
extern consvar_t extern consvar_t
#ifdef VANILLAJOINNEXTROUND #ifdef VANILLAJOINNEXTROUND
cv_joinnextround, cv_joinnextround,
#endif #endif
cv_allownewplayer, cv_maxplayers, cv_resynchattempts, cv_blamecfail, cv_maxsend, cv_noticedownload, cv_downloadspeed; cv_netticbuffer, 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); tic_t ExpandTics(INT32 low);
@ -538,6 +561,7 @@ void SendNetXCmd3(netxcmd_t id, const void *param, size_t nparam); // splitsreen
void SendNetXCmd4(netxcmd_t id, const void *param, size_t nparam); // splitsreen4 player void SendNetXCmd4(netxcmd_t id, const void *param, size_t nparam); // splitsreen4 player
// Create any new ticcmds and broadcast to other players. // Create any new ticcmds and broadcast to other players.
void NetKeepAlive(void);
void NetUpdate(void); void NetUpdate(void);
void SV_StartSinglePlayerServer(void); void SV_StartSinglePlayerServer(void);
@ -550,6 +574,7 @@ void CL_RemoveSplitscreenPlayer(UINT8 p);
void CL_Reset(void); void CL_Reset(void);
void CL_ClearPlayer(INT32 playernum); void CL_ClearPlayer(INT32 playernum);
void CL_UpdateServerList(boolean internetsearch, INT32 room); void CL_UpdateServerList(boolean internetsearch, INT32 room);
boolean CL_Responder(event_t *ev);
// Is there a game running // Is there a game running
boolean Playing(void); boolean Playing(void);

View File

@ -111,6 +111,7 @@ UINT8 window_notinfocus = false;
//static INT32 demosequence; //static INT32 demosequence;
static const char *pagename = "MAP1PIC"; static const char *pagename = "MAP1PIC";
static char *startupwadfiles[MAX_WADFILES]; static char *startupwadfiles[MAX_WADFILES];
static char *startuppwads[MAX_WADFILES];
boolean devparm = false; // started game with -devparm boolean devparm = false; // started game with -devparm
@ -203,6 +204,8 @@ static inline void D_ModifierKeyResponder(event_t *ev)
case KEY_RCTRL: ctrldown |= 0x2; return; case KEY_RCTRL: ctrldown |= 0x2; return;
case KEY_LALT: altdown |= 0x1; return; case KEY_LALT: altdown |= 0x1; return;
case KEY_RALT: altdown |= 0x2; return; case KEY_RALT: altdown |= 0x2; return;
case KEY_CAPSLOCK: capslock = !capslock; return;
default: return; default: return;
} }
else if (ev->type == ev_keyup) switch (ev->data1) else if (ev->type == ev_keyup) switch (ev->data1)
@ -236,6 +239,9 @@ void D_ProcessEvents(void)
if (M_ScreenshotResponder(ev)) if (M_ScreenshotResponder(ev))
continue; // ate the event continue; // ate the event
if (CL_Responder(ev))
continue;
if (gameaction == ga_nothing && gamestate == GS_TITLESCREEN) if (gameaction == ga_nothing && gamestate == GS_TITLESCREEN)
{ {
if (cht_Responder(ev)) if (cht_Responder(ev))
@ -821,12 +827,12 @@ void D_StartTitle(void)
// //
// D_AddFile // D_AddFile
// //
static void D_AddFile(const char *file) static void D_AddFile(const char *file, char **filearray)
{ {
size_t pnumwadfiles; size_t pnumwadfiles;
char *newfile; char *newfile;
for (pnumwadfiles = 0; startupwadfiles[pnumwadfiles]; pnumwadfiles++) for (pnumwadfiles = 0; filearray[pnumwadfiles]; pnumwadfiles++)
; ;
newfile = malloc(strlen(file) + 1); newfile = malloc(strlen(file) + 1);
@ -836,16 +842,16 @@ static void D_AddFile(const char *file)
} }
strcpy(newfile, file); strcpy(newfile, file);
startupwadfiles[pnumwadfiles] = newfile; filearray[pnumwadfiles] = newfile;
} }
static inline void D_CleanFile(void) static inline void D_CleanFile(char **filearray)
{ {
size_t pnumwadfiles; size_t pnumwadfiles;
for (pnumwadfiles = 0; startupwadfiles[pnumwadfiles]; pnumwadfiles++) for (pnumwadfiles = 0; filearray[pnumwadfiles]; pnumwadfiles++)
{ {
free(startupwadfiles[pnumwadfiles]); free(filearray[pnumwadfiles]);
startupwadfiles[pnumwadfiles] = NULL; filearray[pnumwadfiles] = NULL;
} }
} }
@ -905,9 +911,9 @@ static void IdentifyVersion(void)
// Load the IWAD // Load the IWAD
if (srb2wad2 != NULL && FIL_ReadFileOK(srb2wad2)) if (srb2wad2 != NULL && FIL_ReadFileOK(srb2wad2))
D_AddFile(srb2wad2); D_AddFile(srb2wad2, startupwadfiles);
else if (srb2wad1 != NULL && FIL_ReadFileOK(srb2wad1)) else if (srb2wad1 != NULL && FIL_ReadFileOK(srb2wad1))
D_AddFile(srb2wad1); D_AddFile(srb2wad1, startupwadfiles);
else else
I_Error("SRB2.SRB/SRB2.WAD not found! Expected in %s, ss files: %s or %s\n", srb2waddir, srb2wad1, srb2wad2); I_Error("SRB2.SRB/SRB2.WAD not found! Expected in %s, ss files: %s or %s\n", srb2waddir, srb2wad1, srb2wad2);
@ -924,12 +930,12 @@ static void IdentifyVersion(void)
D_AddFile(va(pandf,srb2waddir,"patch.dta")); D_AddFile(va(pandf,srb2waddir,"patch.dta"));
#endif #endif
D_AddFile(va(pandf,srb2waddir,"gfx.kart")); D_AddFile(va(pandf,srb2waddir,"gfx.kart"), startupwadfiles);
D_AddFile(va(pandf,srb2waddir,"textures.kart")); D_AddFile(va(pandf,srb2waddir,"textures.kart"), startupwadfiles);
D_AddFile(va(pandf,srb2waddir,"chars.kart")); D_AddFile(va(pandf,srb2waddir,"chars.kart"), startupwadfiles);
D_AddFile(va(pandf,srb2waddir,"maps.kart")); D_AddFile(va(pandf,srb2waddir,"maps.kart"), startupwadfiles);
#ifdef USE_PATCH_KART #ifdef USE_PATCH_KART
D_AddFile(va(pandf,srb2waddir,"patch.kart")); D_AddFile(va(pandf,srb2waddir,"patch.kart"), startupwadfiles);
#endif #endif
#if !defined (HAVE_SDL) || defined (HAVE_MIXER) #if !defined (HAVE_SDL) || defined (HAVE_MIXER)
@ -938,7 +944,7 @@ static void IdentifyVersion(void)
const char *musicpath = va(pandf,srb2waddir,str);\ const char *musicpath = va(pandf,srb2waddir,str);\
int ms = W_VerifyNMUSlumps(musicpath); \ int ms = W_VerifyNMUSlumps(musicpath); \
if (ms == 1) \ if (ms == 1) \
D_AddFile(musicpath); \ D_AddFile(musicpath, startupwadfiles); \
else if (ms == 0) \ else if (ms == 0) \
I_Error("File "str" has been modified with non-music/sound lumps"); \ I_Error("File "str" has been modified with non-music/sound lumps"); \
} }
@ -1003,9 +1009,12 @@ static inline void D_MakeTitleString(char *s)
// //
void D_SRB2Main(void) void D_SRB2Main(void)
{ {
INT32 p; INT32 p, i;
char srb2[82]; // srb2 title banner char srb2[82]; // srb2 title banner
char title[82]; char title[82];
lumpinfo_t *lumpinfo;
UINT16 wadnum;
char *name;
INT32 pstartmap = 1; INT32 pstartmap = 1;
boolean autostart = false; boolean autostart = false;
@ -1157,11 +1166,7 @@ void D_SRB2Main(void)
const char *s = M_GetNextParm(); const char *s = M_GetNextParm();
if (s) // Check for NULL? if (s) // Check for NULL?
{ D_AddFile(s, startuppwads);
if (!W_VerifyNMUSlumps(s))
G_SetGameModified(true);
D_AddFile(s);
}
} }
} }
} }
@ -1186,7 +1191,7 @@ void D_SRB2Main(void)
else else
{ {
if (!M_CheckParm("-server")) if (!M_CheckParm("-server"))
G_SetGameModified(true); G_SetGameModified(true, true);
autostart = true; autostart = true;
} }
} }
@ -1211,13 +1216,13 @@ void D_SRB2Main(void)
// load wad, including the main wad file // load wad, including the main wad file
CONS_Printf("W_InitMultipleFiles(): Adding IWAD and main PWADs.\n"); CONS_Printf("W_InitMultipleFiles(): Adding IWAD and main PWADs.\n");
if (!W_InitMultipleFiles(startupwadfiles)) if (!W_InitMultipleFiles(startupwadfiles, false))
#ifdef _DEBUG #ifdef _DEBUG
CONS_Error("A WAD file was not found or not valid.\nCheck the log to see which ones.\n"); CONS_Error("A WAD file was not found or not valid.\nCheck the log to see which ones.\n");
#else #else
I_Error("A WAD file was not found or not valid.\nCheck the log to see which ones.\n"); I_Error("A WAD file was not found or not valid.\nCheck the log to see which ones.\n");
#endif #endif
D_CleanFile(); D_CleanFile(startupwadfiles);
mainwads = 0; mainwads = 0;
@ -1231,7 +1236,7 @@ void D_SRB2Main(void)
mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_GFX_KART); // gfx.kart mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_GFX_KART); // gfx.kart
mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_TEXTURES_KART); // textures.kart mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_TEXTURES_KART); // textures.kart
mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_CHARS_KART); // chars.kart mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_CHARS_KART); // chars.kart
mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_MAPS_KART); // maps.kart mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_MAPS_KART); // maps.kart -- 4 - If you touch this, make sure to touch up the majormods stuff below.
#ifdef USE_PATCH_KART #ifdef USE_PATCH_KART
mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_PATCH_KART); // patch.kart mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_PATCH_KART); // patch.kart
#endif #endif
@ -1251,6 +1256,66 @@ void D_SRB2Main(void)
mainwadstally = packetsizetally; mainwadstally = packetsizetally;
//
// search for maps
//
for (wadnum = 4; wadnum < 6; wadnum++) // fucking arbitrary numbers
{
lumpinfo = wadfiles[wadnum]->lumpinfo;
for (i = 0; i < wadfiles[wadnum]->numlumps; i++, lumpinfo++)
{
name = lumpinfo->name;
if (name[0] == 'M' && name[1] == 'A' && name[2] == 'P') // Ignore the headers
{
INT16 num;
if (name[5] != '\0')
continue;
num = (INT16)M_MapNumber(name[3], name[4]);
// we want to record whether this map exists. if it doesn't have a header, we can assume it's not relephant
if (num <= NUMMAPS && mapheaderinfo[num - 1])
{
mapheaderinfo[num - 1]->menuflags |= LF2_EXISTSHACK;
}
}
}
}
if (!W_InitMultipleFiles(startuppwads, true))
CONS_Error("A PWAD file was not found or not valid.\nCheck the log to see which ones.\n");
D_CleanFile(startuppwads);
//
// search for maps... again.
//
for (wadnum = mainwads+1; wadnum < numwadfiles; wadnum++)
{
lumpinfo = wadfiles[wadnum]->lumpinfo;
for (i = 0; i < wadfiles[wadnum]->numlumps; i++, lumpinfo++)
{
name = lumpinfo->name;
if (name[0] == 'M' && name[1] == 'A' && name[2] == 'P') // Ignore the headers
{
INT16 num;
if (name[5] != '\0')
continue;
num = (INT16)M_MapNumber(name[3], name[4]);
// we want to record whether this map exists. if it doesn't have a header, we can assume it's not relephant
if (num <= NUMMAPS && mapheaderinfo[num - 1])
{
if (mapheaderinfo[num - 1]->menuflags & LF2_EXISTSHACK)
G_SetGameModified(multiplayer, true); // oops, double-defined - no record attack privileges for you
mapheaderinfo[num - 1]->menuflags |= LF2_EXISTSHACK;
}
CONS_Printf("%s\n", name);
}
}
}
cht_Init(); cht_Init();
//---------------------------------------------------- READY SCREEN //---------------------------------------------------- READY SCREEN
@ -1322,10 +1387,6 @@ void D_SRB2Main(void)
midi_disabled = true; midi_disabled = true;
#endif #endif
} }
else
{
CONS_Printf("S_InitSfxChannels(): Setting up sound channels.\n");
}
if (M_CheckParm("-nosound")) if (M_CheckParm("-nosound"))
sound_disabled = true; sound_disabled = true;
if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic
@ -1344,10 +1405,18 @@ void D_SRB2Main(void)
if (M_CheckParm("-nodigmusic")) if (M_CheckParm("-nodigmusic"))
digital_disabled = true; // WARNING: DOS version initmusic in I_StartupSound digital_disabled = true; // WARNING: DOS version initmusic in I_StartupSound
} }
I_StartupSound(); if (!( sound_disabled && digital_disabled
I_InitMusic(); #ifndef NO_MIDI
S_InitSfxChannels(cv_soundvolume.value); && midi_disabled
S_InitMusicDefs(); #endif
))
{
CONS_Printf("S_InitSfxChannels(): Setting up sound channels.\n");
I_StartupSound();
I_InitMusic();
S_InitSfxChannels(cv_soundvolume.value);
S_InitMusicDefs();
}
CONS_Printf("ST_Init(): Init status bar.\n"); CONS_Printf("ST_Init(): Init status bar.\n");
ST_Init(); ST_Init();

View File

@ -821,10 +821,6 @@ static const char *packettypename[NUMPACKETTYPE] =
"CLIENTMIS", "CLIENTMIS",
"CLIENT2CMD", "CLIENT2CMD",
"CLIENT2MIS", "CLIENT2MIS",
"CLIENT3CMD",
"CLIENT3MIS",
"CLIENT4CMD",
"CLIENT4MIS",
"NODEKEEPALIVE", "NODEKEEPALIVE",
"NODEKEEPALIVEMIS", "NODEKEEPALIVEMIS",
"SERVERTICS", "SERVERTICS",
@ -841,6 +837,15 @@ static const char *packettypename[NUMPACKETTYPE] =
"RESYNCHEND", "RESYNCHEND",
"RESYNCHGET", "RESYNCHGET",
"CLIENT3CMD",
"CLIENT3MIS",
"CLIENT4CMD",
"CLIENT4MIS",
"BASICKEEPALIVE",
"JOINCHALLENGE",
"DOWNLOADFILESOKAY",
"FILEFRAGMENT", "FILEFRAGMENT",
"TEXTCMD", "TEXTCMD",
"TEXTCMD2", "TEXTCMD2",
@ -868,7 +873,7 @@ static void DebugPrintpacket(const char *header)
break; break;
case PT_CLIENTJOIN: case PT_CLIENTJOIN:
fprintf(debugfile, " number %d mode %d\n", netbuffer->u.clientcfg.localplayers, fprintf(debugfile, " number %d mode %d\n", netbuffer->u.clientcfg.localplayers,
netbuffer->u.clientcfg.mode); netbuffer->u.clientcfg.needsdownload);
break; break;
case PT_SERVERTICS: case PT_SERVERTICS:
{ {
@ -903,6 +908,9 @@ static void DebugPrintpacket(const char *header)
(UINT32)ExpandTics(netbuffer->u.clientpak.client_tic), (UINT32)ExpandTics(netbuffer->u.clientpak.client_tic),
(UINT32)ExpandTics (netbuffer->u.clientpak.resendfrom)); (UINT32)ExpandTics (netbuffer->u.clientpak.resendfrom));
break; break;
case PT_BASICKEEPALIVE:
fprintf(debugfile, " keep alive\n");
break;
case PT_TEXTCMD: case PT_TEXTCMD:
case PT_TEXTCMD2: case PT_TEXTCMD2:
case PT_TEXTCMD3: case PT_TEXTCMD3:

View File

@ -19,7 +19,7 @@
#define __D_NET__ #define __D_NET__
// Max computers in a game // Max computers in a game
#define MAXNETNODES 16 #define MAXNETNODES (MAXPLAYERS+4)
#define BROADCASTADDR MAXNETNODES #define BROADCASTADDR MAXNETNODES
#define MAXSPLITSCREENPLAYERS 4 // Max number of players on a single computer #define MAXSPLITSCREENPLAYERS 4 // Max number of players on a single computer
#define NETSPLITSCREEN // Kart's splitscreen netgame feature #define NETSPLITSCREEN // Kart's splitscreen netgame feature

View File

@ -169,6 +169,7 @@ static void Got_Verification(UINT8 **cp, INT32 playernum);
static void Got_Removal(UINT8 **cp, INT32 playernum); static void Got_Removal(UINT8 **cp, INT32 playernum);
static void Command_Verify_f(void); static void Command_Verify_f(void);
static void Command_RemoveAdmin_f(void); static void Command_RemoveAdmin_f(void);
static void Command_ChangeJoinPassword_f(void);
static void Command_MotD_f(void); static void Command_MotD_f(void);
static void Got_MotD_f(UINT8 **cp, INT32 playernum); static void Got_MotD_f(UINT8 **cp, INT32 playernum);
@ -214,7 +215,7 @@ static CV_PossibleValue_t autobalance_cons_t[] = {{0, "MIN"}, {4, "MAX"}, {0, NU
static CV_PossibleValue_t teamscramble_cons_t[] = {{0, "Off"}, {1, "Random"}, {2, "Points"}, {0, NULL}}; static CV_PossibleValue_t teamscramble_cons_t[] = {{0, "Off"}, {1, "Random"}, {2, "Points"}, {0, NULL}};
static CV_PossibleValue_t startingliveslimit_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, NULL}}; static CV_PossibleValue_t startingliveslimit_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, NULL}};
static CV_PossibleValue_t sleeping_cons_t[] = {{-1, "MIN"}, {1000/TICRATE, "MAX"}, {0, NULL}}; static CV_PossibleValue_t sleeping_cons_t[] = {{0, "MIN"}, {1000/TICRATE, "MAX"}, {0, NULL}};
static CV_PossibleValue_t competitionboxes_cons_t[] = {{0, "Normal"}, {1, "Random"}, {2, "Teleports"}, static CV_PossibleValue_t competitionboxes_cons_t[] = {{0, "Normal"}, {1, "Random"}, {2, "Teleports"},
{3, "None"}, {0, NULL}}; {3, "None"}, {0, NULL}};
@ -236,6 +237,9 @@ static consvar_t cv_dummyconsvar = {"dummyconsvar", "Off", CV_CALL|CV_NOSHOWHELP
consvar_t cv_restrictskinchange = {"restrictskinchange", "No", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_restrictskinchange = {"restrictskinchange", "No", CV_NETVAR|CV_CHEAT, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_allowteamchange = {"allowteamchange", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_allowteamchange = {"allowteamchange", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t ingamecap_cons_t[] = {{0, "MIN"}, {MAXPLAYERS-1, "MAX"}, {0, NULL}};
consvar_t cv_ingamecap = {"ingamecap", "0", CV_NETVAR, ingamecap_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_startinglives = {"startinglives", "3", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, startingliveslimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_startinglives = {"startinglives", "3", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, startingliveslimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t respawntime_cons_t[] = {{0, "MIN"}, {30, "MAX"}, {0, NULL}}; static CV_PossibleValue_t respawntime_cons_t[] = {{0, "MIN"}, {30, "MAX"}, {0, NULL}};
@ -357,7 +361,7 @@ consvar_t cv_kartfrantic = {"kartfrantic", "Off", CV_NETVAR|CV_CHEAT|CV_CALL|CV_
consvar_t cv_kartcomeback = {"kartcomeback", "On", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartComeback_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartcomeback = {"kartcomeback", "On", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_OnOff, KartComeback_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_kartencore = {"kartencore", "Off", CV_NETVAR|CV_CALL|CV_NOINIT, CV_OnOff, KartEncore_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartencore = {"kartencore", "Off", CV_NETVAR|CV_CALL|CV_NOINIT, CV_OnOff, KartEncore_OnChange, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t kartvoterulechanges_cons_t[] = {{0, "Never"}, {1, "Sometimes"}, {2, "Frequent"}, {3, "Always"}, {0, NULL}}; static CV_PossibleValue_t kartvoterulechanges_cons_t[] = {{0, "Never"}, {1, "Sometimes"}, {2, "Frequent"}, {3, "Always"}, {0, NULL}};
consvar_t cv_kartvoterulechanges = {"kartvoterulechanges", "Sometimes", CV_NETVAR, kartvoterulechanges_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartvoterulechanges = {"kartvoterulechanges", "Frequent", CV_NETVAR, kartvoterulechanges_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t kartspeedometer_cons_t[] = {{0, "Off"}, {1, "Kilometers"}, {2, "Miles"}, {3, "Fracunits"}, {0, NULL}}; static CV_PossibleValue_t kartspeedometer_cons_t[] = {{0, "Off"}, {1, "Kilometers"}, {2, "Miles"}, {3, "Fracunits"}, {0, NULL}};
consvar_t cv_kartspeedometer = {"kartdisplayspeed", "Off", CV_SAVE, kartspeedometer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // use tics in display consvar_t cv_kartspeedometer = {"kartdisplayspeed", "Off", CV_SAVE, kartspeedometer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // use tics in display
static CV_PossibleValue_t kartvoices_cons_t[] = {{0, "Never"}, {1, "Tasteful"}, {2, "Meme"}, {0, NULL}}; static CV_PossibleValue_t kartvoices_cons_t[] = {{0, "Never"}, {1, "Tasteful"}, {2, "Meme"}, {0, NULL}};
@ -375,6 +379,7 @@ consvar_t cv_kartdebughuddrop = {"kartdebughuddrop", "Off", CV_NETVAR|CV_CHEAT|C
consvar_t cv_kartdebugcheckpoint = {"kartdebugcheckpoint", "Off", CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartdebugcheckpoint = {"kartdebugcheckpoint", "Off", CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_kartdebugnodes = {"kartdebugnodes", "Off", CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_kartdebugnodes = {"kartdebugnodes", "Off", CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_kartdebugcolorize = {"kartdebugcolorize", "Off", CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t votetime_cons_t[] = {{10, "MIN"}, {3600, "MAX"}, {0, NULL}}; static CV_PossibleValue_t votetime_cons_t[] = {{10, "MIN"}, {3600, "MAX"}, {0, NULL}};
consvar_t cv_votetime = {"votetime", "20", CV_NETVAR, votetime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_votetime = {"votetime", "20", CV_NETVAR, votetime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -432,6 +437,14 @@ consvar_t cv_jointimeout = {"jointimeout", "105", CV_CALL|CV_SAVE, nettimeout_co
#ifdef NEWPING #ifdef NEWPING
static CV_PossibleValue_t maxping_cons_t[] = {{0, "MIN"}, {1000, "MAX"}, {0, NULL}}; static CV_PossibleValue_t maxping_cons_t[] = {{0, "MIN"}, {1000, "MAX"}, {0, NULL}};
consvar_t cv_maxping = {"maxping", "800", CV_SAVE, maxping_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_maxping = {"maxping", "800", CV_SAVE, maxping_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t pingtimeout_cons_t[] = {{8, "MIN"}, {120, "MAX"}, {0, NULL}};
consvar_t cv_pingtimeout = {"pingtimeout", "10", CV_SAVE, pingtimeout_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
// show your ping on the HUD next to framerate. Defaults to warning only (shows up if your ping is > maxping)
static CV_PossibleValue_t showping_cons_t[] = {{0, "Off"}, {1, "Always"}, {2, "Warning"}, {0, NULL}};
consvar_t cv_showping = {"showping", "Always", CV_SAVE, showping_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif #endif
// Intermission time Tails 04-19-2002 // Intermission time Tails 04-19-2002
static CV_PossibleValue_t inttime_cons_t[] = {{0, "MIN"}, {3600, "MAX"}, {0, NULL}}; static CV_PossibleValue_t inttime_cons_t[] = {{0, "MIN"}, {3600, "MAX"}, {0, NULL}};
@ -447,7 +460,7 @@ consvar_t cv_runscripts = {"runscripts", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL
consvar_t cv_pause = {"pausepermission", "Server", CV_NETVAR, pause_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_pause = {"pausepermission", "Server", CV_NETVAR, pause_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mute = {"mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_mute = {"mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_sleep = {"cpusleep", "-1", CV_SAVE, sleeping_cons_t, NULL, -1, NULL, NULL, 0, 0, NULL}; consvar_t cv_sleep = {"cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL, -1, NULL, NULL, 0, 0, NULL};
INT16 gametype = GT_RACE; // SRB2kart INT16 gametype = GT_RACE; // SRB2kart
boolean forceresetplayers = false; boolean forceresetplayers = false;
@ -483,6 +496,7 @@ const char *netxcmdnames[MAXNETXCMD - 1] =
"SETUPVOTE", "SETUPVOTE",
"MODIFYVOTE", "MODIFYVOTE",
"PICKVOTE", "PICKVOTE",
"REMOVEPLAYER",
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
"LUACMD", "LUACMD",
"LUAVAR" "LUAVAR"
@ -521,6 +535,8 @@ void D_RegisterServerCommands(void)
RegisterNetXCmd(XD_PICKVOTE, Got_PickVotecmd); RegisterNetXCmd(XD_PICKVOTE, Got_PickVotecmd);
// Remote Administration // Remote Administration
CV_RegisterVar(&cv_dummyjoinpassword);
COM_AddCommand("joinpassword", Command_ChangeJoinPassword_f);
COM_AddCommand("password", Command_Changepassword_f); COM_AddCommand("password", Command_Changepassword_f);
RegisterNetXCmd(XD_LOGIN, Got_Login); RegisterNetXCmd(XD_LOGIN, Got_Login);
COM_AddCommand("login", Command_Login_f); // useful in dedicated to kick off remote admin COM_AddCommand("login", Command_Login_f); // useful in dedicated to kick off remote admin
@ -641,11 +657,13 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_allowexitlevel); CV_RegisterVar(&cv_allowexitlevel);
CV_RegisterVar(&cv_restrictskinchange); CV_RegisterVar(&cv_restrictskinchange);
CV_RegisterVar(&cv_allowteamchange); CV_RegisterVar(&cv_allowteamchange);
CV_RegisterVar(&cv_ingamecap);
CV_RegisterVar(&cv_respawntime); CV_RegisterVar(&cv_respawntime);
CV_RegisterVar(&cv_killingdead); CV_RegisterVar(&cv_killingdead);
// d_clisrv // d_clisrv
CV_RegisterVar(&cv_maxplayers); CV_RegisterVar(&cv_maxplayers);
CV_RegisterVar(&cv_resynchattempts);
CV_RegisterVar(&cv_maxsend); CV_RegisterVar(&cv_maxsend);
CV_RegisterVar(&cv_noticedownload); CV_RegisterVar(&cv_noticedownload);
CV_RegisterVar(&cv_downloadspeed); CV_RegisterVar(&cv_downloadspeed);
@ -658,6 +676,8 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_sleep); CV_RegisterVar(&cv_sleep);
#ifdef NEWPING #ifdef NEWPING
CV_RegisterVar(&cv_maxping); CV_RegisterVar(&cv_maxping);
CV_RegisterVar(&cv_pingtimeout);
CV_RegisterVar(&cv_showping);
#endif #endif
#ifdef SEENAMES #ifdef SEENAMES
@ -761,6 +781,7 @@ void D_RegisterClientCommands(void)
#endif #endif
CV_RegisterVar(&cv_rollingdemos); CV_RegisterVar(&cv_rollingdemos);
CV_RegisterVar(&cv_netstat); CV_RegisterVar(&cv_netstat);
CV_RegisterVar(&cv_netticbuffer);
#ifdef NETGAME_DEVMODE #ifdef NETGAME_DEVMODE
CV_RegisterVar(&cv_fishcake); CV_RegisterVar(&cv_fishcake);
@ -800,6 +821,8 @@ void D_RegisterClientCommands(void)
//CV_RegisterVar(&cv_alwaysfreelook2); //CV_RegisterVar(&cv_alwaysfreelook2);
//CV_RegisterVar(&cv_chasefreelook); //CV_RegisterVar(&cv_chasefreelook);
//CV_RegisterVar(&cv_chasefreelook2); //CV_RegisterVar(&cv_chasefreelook2);
CV_RegisterVar(&cv_showfocuslost);
CV_RegisterVar(&cv_pauseifunfocused);
// g_input.c // g_input.c
CV_RegisterVar(&cv_turnaxis); CV_RegisterVar(&cv_turnaxis);
@ -839,14 +862,6 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_addons_search_type); CV_RegisterVar(&cv_addons_search_type);
CV_RegisterVar(&cv_addons_search_case); CV_RegisterVar(&cv_addons_search_case);
// filesrch.c
CV_RegisterVar(&cv_addons_option);
CV_RegisterVar(&cv_addons_folder);
CV_RegisterVar(&cv_addons_md5);
CV_RegisterVar(&cv_addons_showall);
CV_RegisterVar(&cv_addons_search_type);
CV_RegisterVar(&cv_addons_search_case);
// WARNING: the order is important when initialising mouse2 // WARNING: the order is important when initialising mouse2
// we need the mouse2port // we need the mouse2port
CV_RegisterVar(&cv_mouse2port); CV_RegisterVar(&cv_mouse2port);
@ -2214,10 +2229,12 @@ static void Command_Map_f(void)
return; return;
} }
if (!(netgame || multiplayer) && (!modifiedgame || savemoddata)) if (!(netgame || multiplayer) && !majormods)
{ {
if (COM_CheckParm("-force")) if (COM_CheckParm("-force"))
G_SetGameModified(false); {
G_SetGameModified(false, true);
}
else else
{ {
CONS_Printf(M_GetText("Sorry, level change disabled in single player.\n")); CONS_Printf(M_GetText("Sorry, level change disabled in single player.\n"));
@ -2501,6 +2518,12 @@ static void Command_Respawn(void)
return; return;
} }
if (players[consoleplayer].mo && !P_IsObjectOnGround(players[consoleplayer].mo)) // KART: Nice try, but no, you won't be cheesing spb anymore.
{
CONS_Printf(M_GetText("You must be on the floor to use this.\n"));
return;
}
/*if (!G_RaceGametype()) // srb2kart: not necessary, respawning makes you lose a bumper in battle, so it's not desirable to use as a way to escape a hit /*if (!G_RaceGametype()) // srb2kart: not necessary, respawning makes you lose a bumper in battle, so it's not desirable to use as a way to escape a hit
{ {
CONS_Printf(M_GetText("You may only use this in co-op, race, and competition!\n")); CONS_Printf(M_GetText("You may only use this in co-op, race, and competition!\n"));
@ -2522,7 +2545,7 @@ static void Got_Respawn(UINT8 **cp, INT32 playernum)
{ {
INT32 respawnplayer = READINT32(*cp); INT32 respawnplayer = READINT32(*cp);
// You can't respawn someone else. Nice try, there. // You can't respawn someone else. Nice try, there.
if (respawnplayer != playernum) // srb2kart: "|| (!G_RaceGametype())" if (respawnplayer != playernum) // srb2kart: "|| (!G_RaceGametype())"
{ {
CONS_Alert(CONS_WARNING, M_GetText("Illegal respawn command received from %s\n"), player_names[playernum]); CONS_Alert(CONS_WARNING, M_GetText("Illegal respawn command received from %s\n"), player_names[playernum]);
@ -2537,6 +2560,10 @@ static void Got_Respawn(UINT8 **cp, INT32 playernum)
return; return;
} }
// incase the above checks were modified to allow sending a respawn on these occasions:
if (players[respawnplayer].mo && !P_IsObjectOnGround(players[respawnplayer].mo))
return;
if (players[respawnplayer].mo) if (players[respawnplayer].mo)
P_DamageMobj(players[respawnplayer].mo, NULL, NULL, 10000); P_DamageMobj(players[respawnplayer].mo, NULL, NULL, 10000);
} }
@ -3405,6 +3432,7 @@ static void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt,
if (len > 256-sl) if (len > 256-sl)
len = 256-sl; len = 256-sl;
memcpy(tmpbuf, buffer, len); memcpy(tmpbuf, buffer, len);
memmove(&tmpbuf[len], salt, sl); memmove(&tmpbuf[len], salt, sl);
//strcpy(&tmpbuf[len], salt); //strcpy(&tmpbuf[len], salt);
@ -3418,7 +3446,7 @@ static void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt,
} }
#define BASESALT "basepasswordstorage" #define BASESALT "basepasswordstorage"
static UINT8 adminpassmd5[16]; static UINT8 adminpassmd5[MD5_LEN];
static boolean adminpasswordset = false; static boolean adminpasswordset = false;
void D_SetPassword(const char *pw) void D_SetPassword(const char *pw)
@ -3457,7 +3485,7 @@ static void Command_Login_f(void)
// If we have no MD5 support then completely disable XD_LOGIN responses for security. // 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"); CONS_Alert(CONS_NOTICE, "Remote administration commands are not supported in this build.\n");
#else #else
XBOXSTATIC UINT8 finalmd5[16]; XBOXSTATIC UINT8 finalmd5[MD5_LEN];
const char *pw; const char *pw;
if (!netgame) if (!netgame)
@ -3480,11 +3508,11 @@ static void Command_Login_f(void)
D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &finalmd5); D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &finalmd5);
// Do the final pass to get the comparison the server will come up with // Do the final pass to get the comparison the server will come up with
D_MD5PasswordPass(finalmd5, 16, va("PNUM%02d", consoleplayer), &finalmd5); D_MD5PasswordPass(finalmd5, MD5_LEN, va("PNUM%02d", consoleplayer), &finalmd5);
CONS_Printf(M_GetText("Sending login... (Notice only given if password is correct.)\n")); CONS_Printf(M_GetText("Sending login... (Notice only given if password is correct.)\n"));
SendNetXCmd(XD_LOGIN, finalmd5, 16); SendNetXCmd(XD_LOGIN, finalmd5, MD5_LEN);
#endif #endif
} }
@ -3495,9 +3523,9 @@ static void Got_Login(UINT8 **cp, INT32 playernum)
(void)cp; (void)cp;
(void)playernum; (void)playernum;
#else #else
UINT8 sentmd5[16], finalmd5[16]; UINT8 sentmd5[MD5_LEN], finalmd5[MD5_LEN];
READMEM(*cp, sentmd5, 16); READMEM(*cp, sentmd5, MD5_LEN);
if (client) if (client)
return; return;
@ -3509,9 +3537,9 @@ static void Got_Login(UINT8 **cp, INT32 playernum)
} }
// Do the final pass to compare with the sent md5 // Do the final pass to compare with the sent md5
D_MD5PasswordPass(adminpassmd5, 16, va("PNUM%02d", playernum), &finalmd5); D_MD5PasswordPass(adminpassmd5, MD5_LEN, va("PNUM%02d", playernum), &finalmd5);
if (!memcmp(sentmd5, finalmd5, 16)) if (!memcmp(sentmd5, finalmd5, MD5_LEN))
{ {
CONS_Printf(M_GetText("%s passed authentication.\n"), player_names[playernum]); CONS_Printf(M_GetText("%s passed authentication.\n"), player_names[playernum]);
COM_BufInsertText(va("promote %d\n", playernum)); // do this immediately COM_BufInsertText(va("promote %d\n", playernum)); // do this immediately
@ -3680,6 +3708,131 @@ static void Got_Removal(UINT8 **cp, INT32 playernum)
CONS_Printf(M_GetText("You are no longer a server administrator.\n")); CONS_Printf(M_GetText("You are no longer a server administrator.\n"));
} }
// Join password stuff
consvar_t cv_dummyjoinpassword = {"dummyjoinpassword", "", CV_HIDEN|CV_NOSHOWHELP|CV_PASSWORD, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
#define NUMJOINCHALLENGES 32
static UINT8 joinpassmd5[MD5_LEN+1];
boolean joinpasswordset = false;
static UINT8 joinpasschallenges[NUMJOINCHALLENGES][MD5_LEN];
static tic_t joinpasschallengeson[NUMJOINCHALLENGES];
boolean D_IsJoinPasswordOn(void)
{
return joinpasswordset;
}
static inline void GetChallengeAnswer(UINT8 *question, UINT8 *passwordmd5, UINT8 *answer)
{
D_MD5PasswordPass(question, MD5_LEN, (char *) passwordmd5, answer);
}
void D_ComputeChallengeAnswer(UINT8 *question, const char *pw, UINT8 *answer)
{
static UINT8 passwordmd5[MD5_LEN+1];
memset(passwordmd5, 0x00, MD5_LEN+1);
D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &passwordmd5);
GetChallengeAnswer(question, passwordmd5, answer);
}
void D_SetJoinPassword(const char *pw)
{
memset(joinpassmd5, 0x00, MD5_LEN+1);
D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &joinpassmd5);
joinpasswordset = true;
}
boolean D_VerifyJoinPasswordChallenge(UINT8 num, UINT8 *answer)
{
boolean passed = false;
num %= NUMJOINCHALLENGES;
//@TODO use a constant-time memcmp....
if (joinpasschallengeson[num] > 0 && memcmp(answer, joinpasschallenges[num], MD5_LEN) == 0)
passed = true;
// Wipe and reset the challenge so that it can't be tried against again, as a small measure against brute-force attacks.
memset(joinpasschallenges[num], 0x00, MD5_LEN);
joinpasschallengeson[num] = 0;
return passed;
}
void D_MakeJoinPasswordChallenge(UINT8 *num, UINT8 *question)
{
size_t i;
for (i = 0; i < NUMJOINCHALLENGES; i++)
{
(*num) = M_RandomKey(NUMJOINCHALLENGES);
if (joinpasschallengeson[(*num)] == 0)
break;
}
if (joinpasschallengeson[(*num)] > 0)
{
// Ugh, all challenges are (probably) taken. Let's find the oldest one and overwrite it.
tic_t oldesttic = INT32_MAX;
for (i = 0; i < NUMJOINCHALLENGES; i++)
{
if (joinpasschallengeson[i] < oldesttic)
{
(*num) = i;
oldesttic = joinpasschallengeson[i];
}
}
}
joinpasschallengeson[(*num)] = I_GetTime();
memset(question, 0x00, MD5_LEN);
for (i = 0; i < MD5_LEN; i++)
question[i] = M_RandomByte();
// Store the answer in memory. What was the question again?
GetChallengeAnswer(question, joinpassmd5, joinpasschallenges[(*num)]);
// This ensures that num is always non-zero and will be valid when used for the answer
if ((*num) == 0)
(*num) = NUMJOINCHALLENGES;
}
// Remote Administration
static void Command_ChangeJoinPassword_f(void)
{
#ifdef NOMD5
// 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 (client) // cannot change remotely
{
CONS_Printf(M_GetText("Only the server can use this.\n"));
return;
}
if (COM_Argc() != 2)
{
CONS_Printf(M_GetText("joinpassword <password>: set a password to join the server\nUse -remove to disable the password.\n"));
return;
}
if (strcmp(COM_Argv(1), "-remove") == 0)
{
joinpasswordset = false;
CONS_Printf(M_GetText("Join password removed.\n"));
}
else
{
D_SetJoinPassword(COM_Argv(1));
CONS_Printf(M_GetText("Join password set.\n"));
}
#endif
}
static void Command_MotD_f(void) static void Command_MotD_f(void)
{ {
size_t i, j; size_t i, j;
@ -3786,7 +3939,7 @@ static void Command_RunSOC(void)
if (!P_RunSOC(fn)) if (!P_RunSOC(fn))
CONS_Printf(M_GetText("Could not find SOC.\n")); CONS_Printf(M_GetText("Could not find SOC.\n"));
else else
G_SetGameModified(multiplayer); G_SetGameModified(multiplayer, false);
return; return;
} }
@ -3840,7 +3993,7 @@ static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum)
} }
P_RunSOC(filename); P_RunSOC(filename);
G_SetGameModified(true); G_SetGameModified(true, false);
} }
/** Adds a pwad at runtime. /** Adds a pwad at runtime.
@ -3877,7 +4030,7 @@ static void Command_Addfile(void)
CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
return; return;
} }
G_SetGameModified(multiplayer); G_SetGameModified(multiplayer, false);
} }
// Add file on your client directly if it is trivial, or you aren't in a netgame. // Add file on your client directly if it is trivial, or you aren't in a netgame.
@ -4123,7 +4276,7 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
return; return;
} }
G_SetGameModified(true); G_SetGameModified(true, false);
} }
static void Command_ListWADS_f(void) static void Command_ListWADS_f(void)
@ -4480,7 +4633,7 @@ static void Ringslinger_OnChange(void)
} }
if (cv_ringslinger.value) // Only if it's been turned on if (cv_ringslinger.value) // Only if it's been turned on
G_SetGameModified(multiplayer); G_SetGameModified(multiplayer, true);
} }
static void Gravity_OnChange(void) static void Gravity_OnChange(void)
@ -4501,7 +4654,7 @@ static void Gravity_OnChange(void)
#endif #endif
if (!CV_IsSetToDefault(&cv_gravity)) if (!CV_IsSetToDefault(&cv_gravity))
G_SetGameModified(multiplayer); G_SetGameModified(multiplayer, true);
gravity = cv_gravity.value; gravity = cv_gravity.value;
} }
@ -4897,7 +5050,7 @@ static void Fishcake_OnChange(void)
// so don't make modifiedgame always on! // so don't make modifiedgame always on!
if (cv_debug) if (cv_debug)
{ {
G_SetGameModified(multiplayer); G_SetGameModified(multiplayer, true);
} }
else if (cv_debug != cv_fishcake.value) else if (cv_debug != cv_fishcake.value)
@ -4913,12 +5066,14 @@ static void Fishcake_OnChange(void)
*/ */
static void Command_Isgamemodified_f(void) static void Command_Isgamemodified_f(void)
{ {
if (savemoddata) if (majormods)
CONS_Printf(M_GetText("modifiedgame is true, but you can save medal and record data in this mod.\n")); CONS_Printf("The game has been modified with major add-ons, so you cannot play Record Attack.\n");
else if (savemoddata)
CONS_Printf("The game has been modified with an add-on with its own save data, so you can play Record Attack and earn medals.\n");
else if (modifiedgame) else if (modifiedgame)
CONS_Printf(M_GetText("modifiedgame is true, extras will not be unlocked\n")); CONS_Printf("The game has been modified with only minor add-ons. You can play Record Attack, earn medals and unlock extras.\n");
else else
CONS_Printf(M_GetText("modifiedgame is false, you can unlock extras\n")); CONS_Printf("The game has not been modified. You can play Record Attack, earn medals and unlock extras.\n");
} }
static void Command_Cheats_f(void) static void Command_Cheats_f(void)

View File

@ -33,6 +33,8 @@ extern consvar_t cv_skin3;
extern consvar_t cv_playername4; extern consvar_t cv_playername4;
extern consvar_t cv_playercolor4; extern consvar_t cv_playercolor4;
extern consvar_t cv_skin4; extern consvar_t cv_skin4;
// preferred number of players
extern consvar_t cv_splitplayers;
#ifdef SEENAMES #ifdef SEENAMES
extern consvar_t cv_seenames, cv_allowseenames; extern consvar_t cv_seenames, cv_allowseenames;
@ -91,7 +93,7 @@ extern consvar_t cv_mute;
extern consvar_t cv_killingdead; extern consvar_t cv_killingdead;
extern consvar_t cv_pause; extern consvar_t cv_pause;
extern consvar_t cv_restrictskinchange, cv_allowteamchange, cv_respawntime; extern consvar_t cv_restrictskinchange, cv_allowteamchange, cv_ingamecap, cv_respawntime;
/*extern consvar_t cv_teleporters, cv_superring, cv_supersneakers, cv_invincibility; /*extern consvar_t cv_teleporters, cv_superring, cv_supersneakers, cv_invincibility;
extern consvar_t cv_jumpshield, cv_watershield, cv_ringshield, cv_forceshield, cv_bombshield; extern consvar_t cv_jumpshield, cv_watershield, cv_ringshield, cv_forceshield, cv_bombshield;
@ -124,7 +126,7 @@ extern consvar_t cv_karteliminatelast;
extern consvar_t cv_votetime; extern consvar_t cv_votetime;
extern consvar_t cv_kartdebugitem, cv_kartdebugamount, cv_kartdebugshrink, cv_kartdebugdistribution, cv_kartdebughuddrop; extern consvar_t cv_kartdebugitem, cv_kartdebugamount, cv_kartdebugshrink, cv_kartdebugdistribution, cv_kartdebughuddrop;
extern consvar_t cv_kartdebugcheckpoint, cv_kartdebugnodes; extern consvar_t cv_kartdebugcheckpoint, cv_kartdebugnodes, cv_kartdebugcolorize;
extern consvar_t cv_itemfinder; extern consvar_t cv_itemfinder;
@ -143,6 +145,8 @@ extern consvar_t cv_specialrings, cv_powerstones, cv_matchboxes, cv_competitionb
#ifdef NEWPING #ifdef NEWPING
extern consvar_t cv_maxping; extern consvar_t cv_maxping;
extern consvar_t cv_pingtimeout;
extern consvar_t cv_showping;
#endif #endif
extern consvar_t cv_skipmapcheck; extern consvar_t cv_skipmapcheck;
@ -244,6 +248,14 @@ void RemoveAdminPlayer(INT32 playernum);
void ItemFinder_OnChange(void); void ItemFinder_OnChange(void);
void D_SetPassword(const char *pw); void D_SetPassword(const char *pw);
extern consvar_t cv_dummyjoinpassword;
extern boolean joinpasswordset;
boolean D_IsJoinPasswordOn(void);
void D_ComputeChallengeAnswer(UINT8 *question, const char *pw, UINT8 *answer);
void D_SetJoinPassword(const char *pw);
boolean D_VerifyJoinPasswordChallenge(UINT8 num, UINT8 *answer);
void D_MakeJoinPasswordChallenge(UINT8 *num, UINT8 *question);
// used for the player setup menu // used for the player setup menu
UINT8 CanChangeSkin(INT32 playernum); UINT8 CanChangeSkin(INT32 playernum);

View File

@ -426,7 +426,7 @@ void CL_LoadServerFiles(void)
else if (fileneeded[i].status == FS_FOUND) else if (fileneeded[i].status == FS_FOUND)
{ {
P_AddWadFile(fileneeded[i].filename); P_AddWadFile(fileneeded[i].filename);
G_SetGameModified(true); G_SetGameModified(true, false);
fileneeded[i].status = FS_OPEN; fileneeded[i].status = FS_OPEN;
} }
else if (fileneeded[i].status == FS_MD5SUMBAD) else if (fileneeded[i].status == FS_MD5SUMBAD)

View File

@ -32,13 +32,7 @@
// Extra abilities/settings for skins (combinable stuff) // Extra abilities/settings for skins (combinable stuff)
typedef enum typedef enum
{ {
SF_SUPER = 1, // Can turn super in singleplayer/co-op mode. SF_HIRES = 1, // Draw the sprite 2x as small?
SF_SUPERANIMS = 1<<1, // If super, use the super sonic animations
SF_SUPERSPIN = 1<<2, // Should spin frames be played while super?
SF_HIRES = 1<<3, // Draw the sprite 2x as small?
SF_NOSKID = 1<<4, // No skid particles etc
SF_NOSPEEDADJUST = 1<<5, // Skin-specific version of disablespeedadjust
SF_RUNONWATER = 1<<6, // Run on top of water FOFs?
} skinflags_t; } skinflags_t;
//Primary and secondary skin abilities //Primary and secondary skin abilities
@ -275,6 +269,7 @@ typedef enum
k_nextcheck, // Next checkpoint distance; for p_user.c (was "pw_ncd") k_nextcheck, // Next checkpoint distance; for p_user.c (was "pw_ncd")
k_waypoint, // Waypoints. k_waypoint, // Waypoints.
k_starpostwp, // Temporarily stores player waypoint for... some reason. Used when respawning and finishing. k_starpostwp, // Temporarily stores player waypoint for... some reason. Used when respawning and finishing.
k_starpostflip, // the last starpost we hit requires flipping?
k_respawn, // Timer for the DEZ laser respawn effect k_respawn, // Timer for the DEZ laser respawn effect
k_dropdash, // Charge up for respawn Drop Dash k_dropdash, // Charge up for respawn Drop Dash
@ -348,10 +343,13 @@ typedef enum
k_wanted, // Timer for determining WANTED status, lowers when hitting people, prevents the game turning into Camp Lazlo k_wanted, // Timer for determining WANTED status, lowers when hitting people, prevents the game turning into Camp Lazlo
k_yougotem, // "You Got Em" gfx when hitting someone as a karma player via a method that gets you back in the game instantly k_yougotem, // "You Got Em" gfx when hitting someone as a karma player via a method that gets you back in the game instantly
// v1.0.2 vars // v1.0.2+ vars
k_itemblink, // Item flashing after roulette, prevents Hyudoro stealing AND serves as a mashing indicator k_itemblink, // Item flashing after roulette, prevents Hyudoro stealing AND serves as a mashing indicator
k_itemblinkmode, // Type of flashing: 0 = white (normal), 1 = red (mashing), 2 = rainbow (enhanced items) k_itemblinkmode, // Type of flashing: 0 = white (normal), 1 = red (mashing), 2 = rainbow (enhanced items)
k_getsparks, // Disable drift sparks at low speed, JUST enough to give acceleration the actual headstart above speed k_getsparks, // Disable drift sparks at low speed, JUST enough to give acceleration the actual headstart above speed
k_jawztargetdelay, // Delay for Jawz target switching, to make it less twitchy
k_spectatewait, // How long have you been waiting as a spectator
k_growcancel, // Hold the item button down to cancel Grow
NUMKARTSTUFF NUMKARTSTUFF
} kartstufftype_t; } kartstufftype_t;
@ -416,6 +414,8 @@ typedef struct player_s
// SRB2kart stuff // SRB2kart stuff
INT32 kartstuff[NUMKARTSTUFF]; INT32 kartstuff[NUMKARTSTUFF];
angle_t frameangle; // for the player add the ability to have the sprite only face other angles angle_t frameangle; // for the player add the ability to have the sprite only face other angles
INT16 lturn_max[MAXPREDICTTICS]; // What's the expected turn value for full-left for a number of frames back (to account for netgame latency)?
INT16 rturn_max[MAXPREDICTTICS]; // Ditto but for full-right
// Bit flags. // Bit flags.
// See pflags_t, above. // See pflags_t, above.
@ -567,6 +567,8 @@ typedef struct player_s
UINT8 bot; UINT8 bot;
tic_t jointime; // Timer when player joins game to change skin/color tic_t jointime; // Timer when player joins game to change skin/color
UINT8 splitscreenindex;
#ifdef HWRENDER #ifdef HWRENDER
fixed_t fovadd; // adjust FOV for hw rendering fixed_t fovadd; // adjust FOV for hw rendering
#endif #endif

View File

@ -21,6 +21,8 @@
#pragma interface #pragma interface
#endif #endif
#define MAXPREDICTTICS 12
// Button/action code definitions. // Button/action code definitions.
typedef enum typedef enum
{ {
@ -60,6 +62,7 @@ typedef struct
INT16 aiming; // vertical aiming, see G_BuildTicCmd INT16 aiming; // vertical aiming, see G_BuildTicCmd
UINT16 buttons; UINT16 buttons;
INT16 driftturn; // SRB2Kart: Used for getting drift turn speed INT16 driftturn; // SRB2Kart: Used for getting drift turn speed
UINT8 latency; // Netgames: how many tics ago was this ticcmd generated from this player's end?
} ATTRPACK ticcmd_t; } ATTRPACK ticcmd_t;
#if defined(_MSC_VER) #if defined(_MSC_VER)

View File

@ -21,6 +21,7 @@
#include "w_wad.h" #include "w_wad.h"
#include "m_menu.h" #include "m_menu.h"
#include "m_misc.h" #include "m_misc.h"
#include "filesrch.h" // for refreshdirmenu
#include "f_finale.h" #include "f_finale.h"
#include "dehacked.h" #include "dehacked.h"
#include "st_stuff.h" #include "st_stuff.h"
@ -79,8 +80,6 @@ static powertype_t get_power(const char *word);
boolean deh_loaded = false; boolean deh_loaded = false;
static int dbg_line; static int dbg_line;
static boolean gamedataadded = false;
#ifdef DELFILE #ifdef DELFILE
typedef struct undehacked_s typedef struct undehacked_s
{ {
@ -436,11 +435,11 @@ static void readAnimTex(MYFILE *f, INT32 num)
static boolean findFreeSlot(INT32 *num) static boolean findFreeSlot(INT32 *num)
{ {
// Send the character select entry to a free slot. // Send the character select entry to a free slot.
while (*num < 32 && PlayerMenu[*num].status != IT_DISABLED) while (*num < MAXSKINS && PlayerMenu[*num].status != IT_DISABLED)
*num = *num+1; *num = *num+1;
// No more free slots. :( // No more free slots. :(
if (*num >= 32) if (*num >= MAXSKINS)
return false; return false;
// Found one! ^_^ // Found one! ^_^
@ -602,6 +601,14 @@ done:
Z_Free(s); Z_Free(s);
} }
static int freeslotusage[2][2] = {{0, 0}, {0, 0}}; // [S_, MT_][max, previous .wad's max]
void DEH_UpdateMaxFreeslots(void)
{
freeslotusage[0][1] = freeslotusage[0][0];
freeslotusage[1][1] = freeslotusage[1][0];
}
// TODO: Figure out how to do undolines for this.... // TODO: Figure out how to do undolines for this....
// TODO: Warnings for running out of freeslots // TODO: Warnings for running out of freeslots
static void readfreeslots(MYFILE *f) static void readfreeslots(MYFILE *f)
@ -664,6 +671,7 @@ static void readfreeslots(MYFILE *f)
if (!FREE_STATES[i]) { if (!FREE_STATES[i]) {
FREE_STATES[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL); FREE_STATES[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_STATES[i],word); strcpy(FREE_STATES[i],word);
freeslotusage[0][0]++;
break; break;
} }
} }
@ -673,6 +681,7 @@ static void readfreeslots(MYFILE *f)
if (!FREE_MOBJS[i]) { if (!FREE_MOBJS[i]) {
FREE_MOBJS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL); FREE_MOBJS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_MOBJS[i],word); strcpy(FREE_MOBJS[i],word);
freeslotusage[1][0]++;
break; break;
} }
} }
@ -3094,11 +3103,6 @@ static void readmaincfg(MYFILE *f)
if (creditscutscene > 128) if (creditscutscene > 128)
creditscutscene = 128; creditscutscene = 128;
} }
else if (fastcmp(word, "DISABLESPEEDADJUST"))
{
DEH_WriteUndoline(word, va("%d", disableSpeedAdjust), UNDO_NONE);
disableSpeedAdjust = (value || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word, "NUMDEMOS")) else if (fastcmp(word, "NUMDEMOS"))
{ {
DEH_WriteUndoline(word, va("%d", numDemos), UNDO_NONE); DEH_WriteUndoline(word, va("%d", numDemos), UNDO_NONE);
@ -3139,6 +3143,7 @@ static void readmaincfg(MYFILE *f)
strlcpy(gamedatafilename, word2, sizeof (gamedatafilename)); strlcpy(gamedatafilename, word2, sizeof (gamedatafilename));
strlwr(gamedatafilename); strlwr(gamedatafilename);
savemoddata = true; savemoddata = true;
majormods = false;
// Also save a time attack folder // Also save a time attack folder
filenamelen = strlen(gamedatafilename)-4; // Strip off the extension filenamelen = strlen(gamedatafilename)-4; // Strip off the extension
@ -3151,7 +3156,7 @@ static void readmaincfg(MYFILE *f)
// can't use sprintf since there is %u in savegamename // can't use sprintf since there is %u in savegamename
strcatbf(savegamename, srb2home, PATHSEP); strcatbf(savegamename, srb2home, PATHSEP);
gamedataadded = true; refreshdirmenu |= REFRESHDIR_GAMEDATA;
} }
else if (fastcmp(word, "RESETDATA")) else if (fastcmp(word, "RESETDATA"))
{ {
@ -3382,8 +3387,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
for (i = 0; i < NUMSFX; i++) for (i = 0; i < NUMSFX; i++)
savesfxnames[i] = S_sfx[i].name; savesfxnames[i] = S_sfx[i].name;
gamedataadded = false;
// it doesn't test the version of SRB2 and version of dehacked file // it doesn't test the version of SRB2 and version of dehacked file
dbg_line = -1; // start at -1 so the first line is 0. dbg_line = -1; // start at -1 so the first line is 0.
while (!myfeof(f)) while (!myfeof(f))
@ -3417,10 +3420,12 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
if (fastcmp(word, "FREESLOT")) if (fastcmp(word, "FREESLOT"))
{ {
readfreeslots(f); readfreeslots(f);
// This is not a major mod.
continue; continue;
} }
else if (fastcmp(word, "MAINCFG")) else if (fastcmp(word, "MAINCFG"))
{ {
G_SetGameModified(multiplayer, true);
readmaincfg(f); readmaincfg(f);
DEH_WriteUndoline(word, "", UNDO_HEADER); DEH_WriteUndoline(word, "", UNDO_HEADER);
continue; continue;
@ -3429,6 +3434,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
{ {
readwipes(f); readwipes(f);
DEH_WriteUndoline(word, "", UNDO_HEADER); DEH_WriteUndoline(word, "", UNDO_HEADER);
// This is not a major mod.
continue; continue;
} }
word2 = strtok(NULL, " "); word2 = strtok(NULL, " ");
@ -3449,6 +3455,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
ignorelines(f); ignorelines(f);
} }
DEH_WriteUndoline(word, word2, UNDO_HEADER); DEH_WriteUndoline(word, word2, UNDO_HEADER);
// This is not a major mod.
continue; continue;
} }
if (word2) if (word2)
@ -3462,19 +3469,25 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
// Read texture from spec file. // Read texture from spec file.
readtexture(f, word2); readtexture(f, word2);
DEH_WriteUndoline(word, word2, UNDO_HEADER); DEH_WriteUndoline(word, word2, UNDO_HEADER);
// This is not a major mod.
} }
else if (fastcmp(word, "PATCH")) else if (fastcmp(word, "PATCH"))
{ {
// Read patch from spec file. // Read patch from spec file.
readpatch(f, word2, wad); readpatch(f, word2, wad);
DEH_WriteUndoline(word, word2, UNDO_HEADER); DEH_WriteUndoline(word, word2, UNDO_HEADER);
// This is not a major mod.
} }
else if (fastcmp(word, "THING") || fastcmp(word, "MOBJ") || fastcmp(word, "OBJECT")) else if (fastcmp(word, "THING") || fastcmp(word, "MOBJ") || fastcmp(word, "OBJECT"))
{ {
if (i == 0 && word2[0] != '0') // If word2 isn't a number if (i == 0 && word2[0] != '0') // If word2 isn't a number
i = get_mobjtype(word2); // find a thing by name i = get_mobjtype(word2); // find a thing by name
if (i < NUMMOBJTYPES && i >= 0) if (i < NUMMOBJTYPES && i >= 0)
{
if (i < (MT_FIRSTFREESLOT+freeslotusage[1][1]))
G_SetGameModified(multiplayer, true); // affecting something earlier than the first freeslot allocated in this .wad? DENIED
readthing(f, i); readthing(f, i);
}
else else
{ {
deh_warning("Thing %d out of range (0 - %d)", i, NUMMOBJTYPES-1); deh_warning("Thing %d out of range (0 - %d)", i, NUMMOBJTYPES-1);
@ -3485,6 +3498,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
/* else if (fastcmp(word, "ANIMTEX")) /* else if (fastcmp(word, "ANIMTEX"))
{ {
readAnimTex(f, i); readAnimTex(f, i);
// This is not a major mod.
}*/ }*/
else if (fastcmp(word, "LIGHT")) else if (fastcmp(word, "LIGHT"))
{ {
@ -3498,6 +3512,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
ignorelines(f); ignorelines(f);
} }
DEH_WriteUndoline(word, word2, UNDO_HEADER); DEH_WriteUndoline(word, word2, UNDO_HEADER);
// This is not a major mod.
#endif #endif
} }
else if (fastcmp(word, "SPRITE")) else if (fastcmp(word, "SPRITE"))
@ -3513,6 +3528,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
ignorelines(f); ignorelines(f);
} }
DEH_WriteUndoline(word, word2, UNDO_HEADER); DEH_WriteUndoline(word, word2, UNDO_HEADER);
// This is not a major mod.
#endif #endif
} }
else if (fastcmp(word, "LEVEL")) else if (fastcmp(word, "LEVEL"))
@ -3525,7 +3541,11 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
i = M_MapNumber(word2[0], word2[1]); i = M_MapNumber(word2[0], word2[1]);
if (i > 0 && i <= NUMMAPS) if (i > 0 && i <= NUMMAPS)
{
if (mapheaderinfo[i])
G_SetGameModified(multiplayer, true); // only mark as a major mod if it replaces an already-existing mapheaderinfo
readlevelheader(f, i); readlevelheader(f, i);
}
else else
{ {
deh_warning("Level number %d out of range (1 - %d)", i, NUMMAPS); deh_warning("Level number %d out of range (1 - %d)", i, NUMMAPS);
@ -3543,13 +3563,18 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
ignorelines(f); ignorelines(f);
} }
DEH_WriteUndoline(word, word2, UNDO_HEADER); DEH_WriteUndoline(word, word2, UNDO_HEADER);
//G_SetGameModified(multiplayer, true); -- might have to reconsider in a future update
} }
else if (fastcmp(word, "FRAME") || fastcmp(word, "STATE")) else if (fastcmp(word, "FRAME") || fastcmp(word, "STATE"))
{ {
if (i == 0 && word2[0] != '0') // If word2 isn't a number if (i == 0 && word2[0] != '0') // If word2 isn't a number
i = get_state(word2); // find a state by name i = get_state(word2); // find a state by name
if (i < NUMSTATES && i >= 0) if (i < NUMSTATES && i >= 0)
{
if (i < (S_FIRSTFREESLOT+freeslotusage[0][1]))
G_SetGameModified(multiplayer, true); // affecting something earlier than the first freeslot allocated in this .wad? DENIED
readframe(f, i); readframe(f, i);
}
else else
{ {
deh_warning("Frame %d out of range (0 - %d)", i, NUMSTATES-1); deh_warning("Frame %d out of range (0 - %d)", i, NUMSTATES-1);
@ -3578,6 +3603,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
} }
else else
deh_warning("pointer (Frame %d) : missing ')'", i); deh_warning("pointer (Frame %d) : missing ')'", i);
G_SetGameModified(multiplayer, true);
}*/ }*/
else if (fastcmp(word, "SOUND")) else if (fastcmp(word, "SOUND"))
{ {
@ -3591,6 +3617,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
ignorelines(f); ignorelines(f);
} }
DEH_WriteUndoline(word, word2, UNDO_HEADER); DEH_WriteUndoline(word, word2, UNDO_HEADER);
// This is not a major mod.
} }
/* else if (fastcmp(word, "SPRITE")) /* else if (fastcmp(word, "SPRITE"))
{ {
@ -3611,6 +3638,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
} }
else else
deh_warning("Sprite %d doesn't exist",i); deh_warning("Sprite %d doesn't exist",i);
// This is not a major mod.
}*/ }*/
else if (fastcmp(word, "HUDITEM")) else if (fastcmp(word, "HUDITEM"))
{ {
@ -3624,10 +3652,11 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
ignorelines(f); ignorelines(f);
} }
DEH_WriteUndoline(word, word2, UNDO_HEADER); DEH_WriteUndoline(word, word2, UNDO_HEADER);
// This is not a major mod.
} }
else if (fastcmp(word, "EMBLEM")) else if (fastcmp(word, "EMBLEM"))
{ {
if (!gamedataadded) if (!(refreshdirmenu & REFRESHDIR_GAMEDATA))
{ {
deh_warning("You must define a custom gamedata to use \"%s\"", word); deh_warning("You must define a custom gamedata to use \"%s\"", word);
ignorelines(f); ignorelines(f);
@ -3647,7 +3676,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
} }
else if (fastcmp(word, "EXTRAEMBLEM")) else if (fastcmp(word, "EXTRAEMBLEM"))
{ {
if (!gamedataadded) if (!(refreshdirmenu & REFRESHDIR_GAMEDATA))
{ {
deh_warning("You must define a custom gamedata to use \"%s\"", word); deh_warning("You must define a custom gamedata to use \"%s\"", word);
ignorelines(f); ignorelines(f);
@ -3667,7 +3696,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
} }
else if (fastcmp(word, "UNLOCKABLE")) else if (fastcmp(word, "UNLOCKABLE"))
{ {
if (!gamedataadded) if (!(refreshdirmenu & REFRESHDIR_GAMEDATA))
{ {
deh_warning("You must define a custom gamedata to use \"%s\"", word); deh_warning("You must define a custom gamedata to use \"%s\"", word);
ignorelines(f); ignorelines(f);
@ -3683,7 +3712,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
} }
else if (fastcmp(word, "CONDITIONSET")) else if (fastcmp(word, "CONDITIONSET"))
{ {
if (!gamedataadded) if (!(refreshdirmenu & REFRESHDIR_GAMEDATA))
{ {
deh_warning("You must define a custom gamedata to use \"%s\"", word); deh_warning("You must define a custom gamedata to use \"%s\"", word);
ignorelines(f); ignorelines(f);
@ -3698,13 +3727,18 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
// no undo support for this insanity yet // no undo support for this insanity yet
//DEH_WriteUndoline(word, word2, UNDO_HEADER); //DEH_WriteUndoline(word, word2, UNDO_HEADER);
} }
else if (fastcmp(word, "SRB2")) else if (fastcmp(word, "SRB2KART"))
{ {
INT32 ver = searchvalue(strtok(NULL, "\n")); INT32 ver = searchvalue(strtok(NULL, "\n"));
if (ver != PATCHVERSION) if (ver != PATCHVERSION)
deh_warning("Patch is for SRB2Kart version %d,\nonly version %d is supported", ver, PATCHVERSION); deh_warning("Patch is for SRB2Kart version %d,\nonly version %d is supported", ver, PATCHVERSION);
//DEH_WriteUndoline(word, va("%d", ver), UNDO_NONE); //DEH_WriteUndoline(word, va("%d", ver), UNDO_NONE);
} }
else if (fastcmp(word, "SRB2"))
{
if (mainwads) // srb2.srb triggers this warning otherwise
deh_warning("Patch is only compatible with base SRB2.");
}
// Clear all data in certain locations (mostly for unlocks) // Clear all data in certain locations (mostly for unlocks)
// Unless you REALLY want to piss people off, // Unless you REALLY want to piss people off,
// define a custom gamedata /before/ doing this!! // define a custom gamedata /before/ doing this!!
@ -3713,7 +3747,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
{ {
boolean clearall = (fastcmp(word2, "ALL")); boolean clearall = (fastcmp(word2, "ALL"));
if (!gamedataadded) if (!(refreshdirmenu & REFRESHDIR_GAMEDATA))
{ {
deh_warning("You must define a custom gamedata to use \"%s\"", word); deh_warning("You must define a custom gamedata to use \"%s\"", word);
continue; continue;
@ -3750,8 +3784,8 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
deh_warning("No word in this line: %s", s); deh_warning("No word in this line: %s", s);
} // end while } // end while
if (gamedataadded) /*if (gamedataadded) -- REFRESHDIR_GAMEDATA murdered this
G_LoadGameData(); G_LoadGameData();*/
dbg_line = -1; dbg_line = -1;
if (deh_num_warning) if (deh_num_warning)
@ -7111,6 +7145,13 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_KARMAFIREWORK4", "S_KARMAFIREWORK4",
"S_KARMAFIREWORKTRAIL", "S_KARMAFIREWORKTRAIL",
// Opaque smoke version, to prevent lag
"S_OPAQUESMOKE1",
"S_OPAQUESMOKE2",
"S_OPAQUESMOKE3",
"S_OPAQUESMOKE4",
"S_OPAQUESMOKE5",
#ifdef SEENAMES #ifdef SEENAMES
"S_NAMECHECK", "S_NAMECHECK",
#endif #endif
@ -8095,89 +8136,164 @@ static const char *const ML_LIST[16] = {
// This DOES differ from r_draw's Color_Names, unfortunately. // This DOES differ from r_draw's Color_Names, unfortunately.
// Also includes Super colors // Also includes Super colors
static const char *COLOR_ENUMS[] = { // Rejigged for Kart. static const char *COLOR_ENUMS[] = { // Rejigged for Kart.
"NONE", // 00 // SKINCOLOR_NONE "NONE", // SKINCOLOR_NONE
"WHITE", // 01 // SKINCOLOR_WHITE "WHITE", // SKINCOLOR_WHITE
"SILVER", // 02 // SKINCOLOR_SILVER "SILVER", // SKINCOLOR_SILVER
"GREY", // 03 // SKINCOLOR_GREY "GREY", // SKINCOLOR_GREY
"NICKEL", // 04 // SKINCOLOR_NICKEL "NICKEL", // SKINCOLOR_NICKEL
"BLACK", // 05 // SKINCOLOR_BLACK "BLACK", // SKINCOLOR_BLACK
"SEPIA", // 06 // SKINCOLOR_SEPIA "FAIRY", // SKINCOLOR_FAIRY
"BEIGE", // 07 // SKINCOLOR_BEIGE "POPCORN", // SKINCOLOR_POPCORN
"BROWN", // 08 // SKINCOLOR_BROWN "SEPIA", // SKINCOLOR_SEPIA
"LEATHER", // 09 // SKINCOLOR_LEATHER "BEIGE", // SKINCOLOR_BEIGE
"SALMON", // 10 // SKINCOLOR_SALMON "BROWN", // SKINCOLOR_BROWN
"PINK", // 11 // SKINCOLOR_PINK "LEATHER", // SKINCOLOR_LEATHER
"ROSE", // 12 // SKINCOLOR_ROSE "SALMON", // SKINCOLOR_SALMON
"RUBY", // 13 // SKINCOLOR_RUBY "PINK", // SKINCOLOR_PINK
"RASPBERRY", // 14 // SKINCOLOR_RASPBERRY "ROSE", // SKINCOLOR_ROSE
"RED", // 15 // SKINCOLOR_RED "BRICK", // SKINCOLOR_BRICK
"CRIMSON", // 16 // SKINCOLOR_CRIMSON "RUBY", // SKINCOLOR_RUBY
"KETCHUP", // 17 // SKINCOLOR_KETCHUP "RASPBERRY", // SKINCOLOR_RASPBERRY
"DAWN", // 18 // SKINCOLOR_DAWN "CHERRY", // SKINCOLOR_CHERRY
"CREAMSICLE", // 19 // SKINCOLOR_CREAMSICLE "RED", // SKINCOLOR_RED
"ORANGE", // 20 // SKINCOLOR_ORANGE "CRIMSON", // SKINCOLOR_CRIMSON
"PUMPKIN", // 21 // SKINCOLOR_PUMPKIN "MAROON", // SKINCOLOR_MAROON
"ROSEWOOD", // 22 // SKINCOLOR_ROSEWOOD "FLAME", // SKINCOLOR_FLAME
"BURGUNDY", // 23 // SKINCOLOR_BURGUNDY "SCARLET", // SKINCOLOR_SCARLET
"TANGERINE", // 24 // SKINCOLOR_TANGERINE "KETCHUP", // SKINCOLOR_KETCHUP
"PEACH", // 25 // SKINCOLOR_PEACH "DAWN", // SKINCOLOR_DAWN
"CARAMEL", // 26 // SKINCOLOR_CARAMEL "SUNSET", // SKINCOLOR_SUNSET
"GOLD", // 27 // SKINCOLOR_GOLD "CREAMSICLE", // SKINCOLOR_CREAMSICLE
"BRONZE", // 28 // SKINCOLOR_BRONZE "ORANGE", // SKINCOLOR_ORANGE
"YELLOW", // 29 // SKINCOLOR_YELLOW "PUMPKIN", // SKINCOLOR_PUMPKIN
"MUSTARD", // 30 // SKINCOLOR_MUSTARD "ROSEWOOD", // SKINCOLOR_ROSEWOOD
"OLIVE", // 31 // SKINCOLOR_OLIVE "BURGUNDY", // SKINCOLOR_BURGUNDY
"VOMIT", // 32 // SKINCOLOR_VOMIT "TANGERINE", // SKINCOLOR_TANGERINE
"GARDEN", // 33 // SKINCOLOR_GARDEN "PEACH", // SKINCOLOR_PEACH
"LIME", // 34 // SKINCOLOR_LIME "CARAMEL", // SKINCOLOR_CARAMEL
"TEA", // 35 // SKINCOLOR_TEA "CREAM", // SKINCOLOR_CREAM
"PISTACHIO", // 36 // SKINCOLOR_PISTACHIO "GOLD", // SKINCOLOR_GOLD
"ROBOHOOD", // 37 // SKINCOLOR_ROBOHOOD "ROYAL", // SKINCOLOR_ROYAL
"MOSS", // 38 // SKINCOLOR_MOSS "BRONZE", // SKINCOLOR_BRONZE
"MINT", // 39 // SKINCOLOR_MINT "COPPER", // SKINCOLOR_COPPER
"GREEN", // 40 // SKINCOLOR_GREEN "YELLOW", // SKINCOLOR_YELLOW
"PINETREE", // 41 // SKINCOLOR_PINETREE "MUSTARD", // SKINCOLOR_MUSTARD
"EMERALD", // 42 // SKINCOLOR_EMERALD "OLIVE", // SKINCOLOR_OLIVE
"SWAMP", // 43 // SKINCOLOR_SWAMP "VOMIT", // SKINCOLOR_VOMIT
"DREAM", // 44 // SKINCOLOR_DREAM "GARDEN", // SKINCOLOR_GARDEN
"AQUA", // 45 // SKINCOLOR_AQUA "LIME", // SKINCOLOR_LIME
"TEAL", // 46 // SKINCOLOR_TEAL "HANDHELD", // SKINCOLOR_HANDHELD
"CYAN", // 47 // SKINCOLOR_CYAN "TEA", // SKINCOLOR_TEA
"JAWZ", // 48 // SKINCOLOR_JAWZ "PISTACHIO", // SKINCOLOR_PISTACHIO
"CERULEAN", // 49 // SKINCOLOR_CERULEAN "MOSS", // SKINCOLOR_MOSS
"NAVY", // 50 // SKINCOLOR_NAVY "CAMOUFLAGE", // SKINCOLOR_CAMOUFLAGE
"SLATE", // 51 // SKINCOLOR_SLATE "ROBOHOOD", // SKINCOLOR_ROBOHOOD
"STEEL", // 52 // SKINCOLOR_STEEL "MINT", // SKINCOLOR_MINT
"JET", // 53 // SKINCOLOR_JET "GREEN", // SKINCOLOR_GREEN
"SAPPHIRE", // 54 // SKINCOLOR_SAPPHIRE "PINETREE", // SKINCOLOR_PINETREE
"PERIWINKLE", // 55 // SKINCOLOR_PERIWINKLE "EMERALD", // SKINCOLOR_EMERALD
"BLUE", // 56 // SKINCOLOR_BLUE "SWAMP", // SKINCOLOR_SWAMP
"BLUEBERRY", // 57 // SKINCOLOR_BLUEBERRY "DREAM", // SKINCOLOR_DREAM
"DUSK", // 58 // SKINCOLOR_DUSK "PLAGUE", // SKINCOLOR_PLAGUE
"PURPLE", // 59 // SKINCOLOR_PURPLE "ALGAE", // SKINCOLOR_ALGAE
"LAVENDER", // 60 // SKINCOLOR_LAVENDER "CARIBBEAN", // SKINCOLOR_CARIBBEAN
"BYZANTIUM", // 61 // SKINCOLOR_BYZANTIUM "AQUA", // SKINCOLOR_AQUA
"POMEGRANATE", // 62 // SKINCOLOR_POMEGRANATE "TEAL", // SKINCOLOR_TEAL
"LILAC", // 63 // SKINCOLOR_LILAC "CYAN", // SKINCOLOR_CYAN
"JAWZ", // SKINCOLOR_JAWZ
"CERULEAN", // SKINCOLOR_CERULEAN
"NAVY", // SKINCOLOR_NAVY
"PLATINUM", // SKINCOLOR_PLATINUM
"SLATE", // SKINCOLOR_SLATE
"STEEL", // SKINCOLOR_STEEL
"RUST", // SKINCOLOR_RUST
"JET", // SKINCOLOR_JET
"SAPPHIRE", // SKINCOLOR_SAPPHIRE
"PERIWINKLE", // SKINCOLOR_PERIWINKLE
"BLUE", // SKINCOLOR_BLUE
"BLUEBERRY", // SKINCOLOR_BLUEBERRY
"NOVA", // SKINCOLOR_NOVA
"PASTEL", // SKINCOLOR_PASTEL
"MOONSLAM", // SKINCOLOR_MOONSLAM
"ULTRAVIOLET", // SKINCOLOR_ULTRAVIOLET
"DUSK", // SKINCOLOR_DUSK
"BUBBLEGUM", // SKINCOLOR_BUBBLEGUM
"PURPLE", // SKINCOLOR_PURPLE
"FUCHSIA", // SKINCOLOR_FUCHSIA
"TOXIC", // SKINCOLOR_TOXIC
"MAUVE", // SKINCOLOR_MAUVE
"LAVENDER", // SKINCOLOR_LAVENDER
"BYZANTIUM", // SKINCOLOR_BYZANTIUM
"POMEGRANATE", // SKINCOLOR_POMEGRANATE
"LILAC", // SKINCOLOR_LILAC
// Super special awesome Super flashing colors!
"SUPER1", // SKINCOLOR_SUPER1
"SUPER2", // SKINCOLOR_SUPER2,
"SUPER3", // SKINCOLOR_SUPER3,
"SUPER4", // SKINCOLOR_SUPER4, // Special super colors
"SUPER5", // SKINCOLOR_SUPER5, // Super Sonic Yellow
// Super Tails "SUPER1", // SKINCOLOR_SUPER1
"TSUPER1", // SKINCOLOR_TSUPER1, "SUPER2", // SKINCOLOR_SUPER2,
"TSUPER2", // SKINCOLOR_TSUPER2, "SUPER3", // SKINCOLOR_SUPER3,
"TSUPER3", // SKINCOLOR_TSUPER3, "SUPER4", // SKINCOLOR_SUPER4,
"TSUPER4", // SKINCOLOR_TSUPER4, "SUPER5", // SKINCOLOR_SUPER5,
"TSUPER5", // SKINCOLOR_TSUPER5,
// Super Knuckles // Super Tails Orange
"KSUPER1", // SKINCOLOR_KSUPER1, "TSUPER1", // SKINCOLOR_TSUPER1,
"KSUPER2", // SKINCOLOR_KSUPER2, "TSUPER2", // SKINCOLOR_TSUPER2,
"KSUPER3", // SKINCOLOR_KSUPER3, "TSUPER3", // SKINCOLOR_TSUPER3,
"KSUPER4", // SKINCOLOR_KSUPER4, "TSUPER4", // SKINCOLOR_TSUPER4,
"KSUPER5" // SKINCOLOR_KSUPER5, "TSUPER5", // SKINCOLOR_TSUPER5,
// Super Knuckles Red
"KSUPER1", // SKINCOLOR_KSUPER1,
"KSUPER2", // SKINCOLOR_KSUPER2,
"KSUPER3", // SKINCOLOR_KSUPER3,
"KSUPER4", // SKINCOLOR_KSUPER4,
"KSUPER5", // SKINCOLOR_KSUPER5,
// Hyper Sonic Pink
"PSUPER1", // SKINCOLOR_PSUPER1,
"PSUPER2", // SKINCOLOR_PSUPER2,
"PSUPER3", // SKINCOLOR_PSUPER3,
"PSUPER4", // SKINCOLOR_PSUPER4,
"PSUPER5", // SKINCOLOR_PSUPER5,
// Hyper Sonic Blue
"BSUPER1", // SKINCOLOR_BSUPER1,
"BSUPER2", // SKINCOLOR_BSUPER2,
"BSUPER3", // SKINCOLOR_BSUPER3,
"BSUPER4", // SKINCOLOR_BSUPER4,
"BSUPER5", // SKINCOLOR_BSUPER5,
// Aqua Super
"ASUPER1", // SKINCOLOR_ASUPER1,
"ASUPER2", // SKINCOLOR_ASUPER2,
"ASUPER3", // SKINCOLOR_ASUPER3,
"ASUPER4", // SKINCOLOR_ASUPER4,
"ASUPER5", // SKINCOLOR_ASUPER5,
// Hyper Sonic Green
"GSUPER1", // SKINCOLOR_GSUPER1,
"GSUPER2", // SKINCOLOR_GSUPER2,
"GSUPER3", // SKINCOLOR_GSUPER3,
"GSUPER4", // SKINCOLOR_GSUPER4,
"GSUPER5", // SKINCOLOR_GSUPER5,
// Hyper Sonic White
"WSUPER1", // SKINCOLOR_WSUPER1,
"WSUPER2", // SKINCOLOR_WSUPER2,
"WSUPER3", // SKINCOLOR_WSUPER3,
"WSUPER4", // SKINCOLOR_WSUPER4,
"WSUPER5", // SKINCOLOR_WSUPER5,
// Creamy Super (Shadow?)
"CSUPER1", // SKINCOLOR_CSUPER1,
"CSUPER2", // SKINCOLOR_CSUPER2,
"CSUPER3", // SKINCOLOR_CSUPER3,
"CSUPER4", // SKINCOLOR_CSUPER4,
"CSUPER5" // SKINCOLOR_CSUPER5,
}; };
static const char *const POWERS_LIST[] = { static const char *const POWERS_LIST[] = {
@ -8215,6 +8331,7 @@ static const char *const POWERS_LIST[] = {
"INGOOP" // In goop "INGOOP" // In goop
}; };
#ifdef HAVE_BLUA
static const char *const KARTSTUFF_LIST[] = { static const char *const KARTSTUFF_LIST[] = {
"POSITION", "POSITION",
"OLDPOSITION", "OLDPOSITION",
@ -8223,6 +8340,7 @@ static const char *const KARTSTUFF_LIST[] = {
"NEXTCHECK", "NEXTCHECK",
"WAYPOINT", "WAYPOINT",
"STARPOSTWP", "STARPOSTWP",
"STARPOSTFLIP",
"RESPAWN", "RESPAWN",
"DROPDASH", "DROPDASH",
@ -8294,8 +8412,12 @@ static const char *const KARTSTUFF_LIST[] = {
"ITEMBLINK", "ITEMBLINK",
"ITEMBLINKMODE", "ITEMBLINKMODE",
"GETSPARKS" "GETSPARKS",
"JAWZTARGETDELAY",
"SPECTATEWAIT",
"GROWCANCEL"
}; };
#endif
static const char *const HUDITEMS_LIST[] = { static const char *const HUDITEMS_LIST[] = {
"LIVESNAME", "LIVESNAME",
@ -8518,13 +8640,7 @@ struct {
{"RW_RAIL",RW_RAIL}, {"RW_RAIL",RW_RAIL},
// Character flags (skinflags_t) // Character flags (skinflags_t)
{"SF_SUPER",SF_SUPER},
{"SF_SUPERANIMS",SF_SUPERANIMS},
{"SF_SUPERSPIN",SF_SUPERSPIN},
{"SF_HIRES",SF_HIRES}, {"SF_HIRES",SF_HIRES},
{"SF_NOSKID",SF_NOSKID},
{"SF_NOSPEEDADJUST",SF_NOSPEEDADJUST},
{"SF_RUNONWATER",SF_RUNONWATER},
// Character abilities! // Character abilities!
// Primary // Primary
@ -9001,20 +9117,6 @@ static powertype_t get_power(const char *word)
return pw_invulnerability; return pw_invulnerability;
} }
static kartstufftype_t get_kartstuff(const char *word)
{ // Returns the vlaue of k_ enumerations
kartstufftype_t i;
if (*word >= '0' && *word <= '9')
return atoi(word);
if (fastncmp("K_",word,2))
word += 2; // take off the k_
for (i = 0; i < NUMKARTSTUFF; i++)
if (fastcmp(word, KARTSTUFF_LIST[i]))
return i;
deh_warning("Couldn't find power named 'k_%s'",word);
return k_position;
}
/// \todo Make ANY of this completely over-the-top math craziness obey the order of operations. /// \todo Make ANY of this completely over-the-top math craziness obey the order of operations.
static fixed_t op_mul(fixed_t a, fixed_t b) { return a*b; } static fixed_t op_mul(fixed_t a, fixed_t b) { return a*b; }
static fixed_t op_div(fixed_t a, fixed_t b) { return a/b; } static fixed_t op_div(fixed_t a, fixed_t b) { return a/b; }
@ -9351,6 +9453,7 @@ static inline int lib_freeslot(lua_State *L)
CONS_Printf("State S_%s allocated.\n",word); CONS_Printf("State S_%s allocated.\n",word);
FREE_STATES[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL); FREE_STATES[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_STATES[i],word); strcpy(FREE_STATES[i],word);
freeslotusage[0][0]++;
lua_pushinteger(L, i); lua_pushinteger(L, i);
r++; r++;
break; break;
@ -9366,6 +9469,7 @@ static inline int lib_freeslot(lua_State *L)
CONS_Printf("MobjType MT_%s allocated.\n",word); CONS_Printf("MobjType MT_%s allocated.\n",word);
FREE_MOBJS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL); FREE_MOBJS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_MOBJS[i],word); strcpy(FREE_MOBJS[i],word);
freeslotusage[1][0]++;
lua_pushinteger(L, i); lua_pushinteger(L, i);
r++; r++;
break; break;
@ -9735,6 +9839,9 @@ static inline int lib_getenum(lua_State *L)
} else if (fastcmp(word,"modifiedgame")) { } else if (fastcmp(word,"modifiedgame")) {
lua_pushboolean(L, modifiedgame && !savemoddata); lua_pushboolean(L, modifiedgame && !savemoddata);
return 1; return 1;
} else if (fastcmp(word,"majormods")) {
lua_pushboolean(L, majormods);
return 1;
} else if (fastcmp(word,"menuactive")) { } else if (fastcmp(word,"menuactive")) {
lua_pushboolean(L, menuactive); lua_pushboolean(L, menuactive);
return 1; return 1;
@ -9806,6 +9913,9 @@ static inline int lib_getenum(lua_State *L)
} else if (fastcmp(word,"indirectitemcooldown")) { } else if (fastcmp(word,"indirectitemcooldown")) {
lua_pushinteger(L, indirectitemcooldown); lua_pushinteger(L, indirectitemcooldown);
return 1; return 1;
} else if (fastcmp(word,"hyubgone")) {
lua_pushinteger(L, hyubgone);
return 1;
} else if (fastcmp(word,"thwompsactive")) { } else if (fastcmp(word,"thwompsactive")) {
lua_pushboolean(L, thwompsactive); lua_pushboolean(L, thwompsactive);
return 1; return 1;

View File

@ -37,6 +37,8 @@ void DEH_UnloadDehackedWad(UINT16 wad);
void DEH_LoadDehackedLump(lumpnum_t lumpnum); void DEH_LoadDehackedLump(lumpnum_t lumpnum);
void DEH_LoadDehackedLumpPwad(UINT16 wad, UINT16 lump); void DEH_LoadDehackedLumpPwad(UINT16 wad, UINT16 lump);
void DEH_UpdateMaxFreeslots(void);
void DEH_Check(void); void DEH_Check(void);
fixed_t get_number(const char *word); fixed_t get_number(const char *word);
@ -54,7 +56,7 @@ extern const char *superactions[MAXRECURSION];
extern UINT8 superstack; extern UINT8 superstack;
// If the dehacked patch does not match this version, we throw a warning // If the dehacked patch does not match this version, we throw a warning
#define PATCHVERSION 210 #define PATCHVERSION 1
#define MAXLINELEN 1024 #define MAXLINELEN 1024

View File

@ -94,6 +94,9 @@ void I_FinishUpdate (void)
if (cv_ticrate.value) if (cv_ticrate.value)
SCR_DisplayTicRate(); SCR_DisplayTicRate();
if (cv_showping.value && netgame && consoleplayer != serverplayer)
SCR_DisplayLocalPing();
//blast it to the screen //blast it to the screen
// this code sucks // this code sucks
//memcpy(dascreen,screens[0],screenwidth*screenheight); //memcpy(dascreen,screens[0],screenwidth*screenheight);

View File

@ -150,9 +150,9 @@ extern FILE *logstream;
// we use comprevision and compbranch instead. // we use comprevision and compbranch instead.
#else #else
#define VERSION 100 // Game version #define VERSION 100 // Game version
#define SUBVERSION 2 // more precise version number #define SUBVERSION 4 // more precise version number
#define VERSIONSTRING "v1.0.2" #define VERSIONSTRING "v1.0.4"
#define VERSIONSTRINGW L"v1.0.2" #define VERSIONSTRINGW L"v1.0.4"
// Hey! If you change this, add 1 to the MODVERSION below! // Hey! If you change this, add 1 to the MODVERSION below!
// Otherwise we can't force updates! // Otherwise we can't force updates!
#endif #endif
@ -221,7 +221,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. // 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. // 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". // Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1".
#define MODVERSION 2 #define MODVERSION 4
// Filter consvars by version // Filter consvars by version
// To version config.cfg, MAJOREXECVERSION is set equal to MODVERSION automatically. // To version config.cfg, MAJOREXECVERSION is set equal to MODVERSION automatically.
@ -244,7 +244,7 @@ extern FILE *logstream;
// NOTE: it needs more than this to increase the number of players... // NOTE: it needs more than this to increase the number of players...
#define MAXPLAYERS 16 #define MAXPLAYERS 16
#define MAXSKINS 32 #define MAXSKINS 128
#define PLAYERSMASK (MAXPLAYERS-1) #define PLAYERSMASK (MAXPLAYERS-1)
#define MAXPLAYERNAME 21 #define MAXPLAYERNAME 21
@ -256,6 +256,8 @@ typedef enum
SKINCOLOR_GREY, SKINCOLOR_GREY,
SKINCOLOR_NICKEL, SKINCOLOR_NICKEL,
SKINCOLOR_BLACK, SKINCOLOR_BLACK,
SKINCOLOR_FAIRY,
SKINCOLOR_POPCORN,
SKINCOLOR_SEPIA, SKINCOLOR_SEPIA,
SKINCOLOR_BEIGE, SKINCOLOR_BEIGE,
SKINCOLOR_BROWN, SKINCOLOR_BROWN,
@ -263,12 +265,18 @@ typedef enum
SKINCOLOR_SALMON, SKINCOLOR_SALMON,
SKINCOLOR_PINK, SKINCOLOR_PINK,
SKINCOLOR_ROSE, SKINCOLOR_ROSE,
SKINCOLOR_BRICK,
SKINCOLOR_RUBY, SKINCOLOR_RUBY,
SKINCOLOR_RASPBERRY, SKINCOLOR_RASPBERRY,
SKINCOLOR_CHERRY,
SKINCOLOR_RED, SKINCOLOR_RED,
SKINCOLOR_CRIMSON, SKINCOLOR_CRIMSON,
SKINCOLOR_MAROON,
SKINCOLOR_FLAME,
SKINCOLOR_SCARLET,
SKINCOLOR_KETCHUP, SKINCOLOR_KETCHUP,
SKINCOLOR_DAWN, SKINCOLOR_DAWN,
SKINCOLOR_SUNSET,
SKINCOLOR_CREAMSICLE, SKINCOLOR_CREAMSICLE,
SKINCOLOR_ORANGE, SKINCOLOR_ORANGE,
SKINCOLOR_PUMPKIN, SKINCOLOR_PUMPKIN,
@ -277,68 +285,130 @@ typedef enum
SKINCOLOR_TANGERINE, SKINCOLOR_TANGERINE,
SKINCOLOR_PEACH, SKINCOLOR_PEACH,
SKINCOLOR_CARAMEL, SKINCOLOR_CARAMEL,
SKINCOLOR_CREAM,
SKINCOLOR_GOLD, SKINCOLOR_GOLD,
SKINCOLOR_ROYAL,
SKINCOLOR_BRONZE, SKINCOLOR_BRONZE,
SKINCOLOR_COPPER,
SKINCOLOR_YELLOW, SKINCOLOR_YELLOW,
SKINCOLOR_MUSTARD, SKINCOLOR_MUSTARD,
SKINCOLOR_OLIVE, SKINCOLOR_OLIVE,
SKINCOLOR_VOMIT, SKINCOLOR_VOMIT,
SKINCOLOR_GARDEN, SKINCOLOR_GARDEN,
SKINCOLOR_LIME, SKINCOLOR_LIME,
SKINCOLOR_HANDHELD,
SKINCOLOR_TEA, SKINCOLOR_TEA,
SKINCOLOR_PISTACHIO, SKINCOLOR_PISTACHIO,
SKINCOLOR_ROBOHOOD,
SKINCOLOR_MOSS, SKINCOLOR_MOSS,
SKINCOLOR_CAMOUFLAGE,
SKINCOLOR_ROBOHOOD,
SKINCOLOR_MINT, SKINCOLOR_MINT,
SKINCOLOR_GREEN, SKINCOLOR_GREEN,
SKINCOLOR_PINETREE, SKINCOLOR_PINETREE,
SKINCOLOR_EMERALD, SKINCOLOR_EMERALD,
SKINCOLOR_SWAMP, SKINCOLOR_SWAMP,
SKINCOLOR_DREAM, SKINCOLOR_DREAM,
SKINCOLOR_PLAGUE,
SKINCOLOR_ALGAE,
SKINCOLOR_CARIBBEAN,
SKINCOLOR_AQUA, SKINCOLOR_AQUA,
SKINCOLOR_TEAL, SKINCOLOR_TEAL,
SKINCOLOR_CYAN, SKINCOLOR_CYAN,
SKINCOLOR_JAWZ, // Oni's torment SKINCOLOR_JAWZ, // Oni's torment
SKINCOLOR_CERULEAN, SKINCOLOR_CERULEAN,
SKINCOLOR_NAVY, SKINCOLOR_NAVY,
SKINCOLOR_PLATINUM,
SKINCOLOR_SLATE, SKINCOLOR_SLATE,
SKINCOLOR_STEEL, SKINCOLOR_STEEL,
SKINCOLOR_RUST,
SKINCOLOR_JET, SKINCOLOR_JET,
SKINCOLOR_SAPPHIRE, // sweet mother, i cannot weave - slender aphrodite has overcome me with longing for a girl SKINCOLOR_SAPPHIRE, // sweet mother, i cannot weave - slender aphrodite has overcome me with longing for a girl
SKINCOLOR_PERIWINKLE, SKINCOLOR_PERIWINKLE,
SKINCOLOR_BLUE, SKINCOLOR_BLUE,
SKINCOLOR_BLUEBERRY, SKINCOLOR_BLUEBERRY,
SKINCOLOR_NOVA,
SKINCOLOR_PASTEL,
SKINCOLOR_MOONSLAM,
SKINCOLOR_ULTRAVIOLET,
SKINCOLOR_DUSK, SKINCOLOR_DUSK,
SKINCOLOR_BUBBLEGUM,
SKINCOLOR_PURPLE, SKINCOLOR_PURPLE,
SKINCOLOR_FUCHSIA,
SKINCOLOR_TOXIC,
SKINCOLOR_MAUVE,
SKINCOLOR_LAVENDER, SKINCOLOR_LAVENDER,
SKINCOLOR_BYZANTIUM, SKINCOLOR_BYZANTIUM,
SKINCOLOR_POMEGRANATE, SKINCOLOR_POMEGRANATE,
SKINCOLOR_LILAC, SKINCOLOR_LILAC,
// Careful! MAXSKINCOLORS cannot be greater than 0x40 -- Which it is now. // "Careful! MAXSKINCOLORS cannot be greater than 0x40 -- Which it is now."
// (This comment is a dirty liar! This is only limited by the integer type, so 255 for UINT8.)
MAXSKINCOLORS, MAXSKINCOLORS,
// Super special awesome Super flashing colors! // Super special awesome Super flashing colors!
// Super Sonic Yellow
SKINCOLOR_SUPER1 = MAXSKINCOLORS, SKINCOLOR_SUPER1 = MAXSKINCOLORS,
SKINCOLOR_SUPER2, SKINCOLOR_SUPER2,
SKINCOLOR_SUPER3, SKINCOLOR_SUPER3,
SKINCOLOR_SUPER4, SKINCOLOR_SUPER4,
SKINCOLOR_SUPER5, SKINCOLOR_SUPER5,
// Super Tails // Super Tails Orange
SKINCOLOR_TSUPER1, SKINCOLOR_TSUPER1,
SKINCOLOR_TSUPER2, SKINCOLOR_TSUPER2,
SKINCOLOR_TSUPER3, SKINCOLOR_TSUPER3,
SKINCOLOR_TSUPER4, SKINCOLOR_TSUPER4,
SKINCOLOR_TSUPER5, SKINCOLOR_TSUPER5,
// Super Knuckles // Super Knuckles Red
SKINCOLOR_KSUPER1, SKINCOLOR_KSUPER1,
SKINCOLOR_KSUPER2, SKINCOLOR_KSUPER2,
SKINCOLOR_KSUPER3, SKINCOLOR_KSUPER3,
SKINCOLOR_KSUPER4, SKINCOLOR_KSUPER4,
SKINCOLOR_KSUPER5, SKINCOLOR_KSUPER5,
// Hyper Sonic Pink
SKINCOLOR_PSUPER1,
SKINCOLOR_PSUPER2,
SKINCOLOR_PSUPER3,
SKINCOLOR_PSUPER4,
SKINCOLOR_PSUPER5,
// Hyper Sonic Blue
SKINCOLOR_BSUPER1,
SKINCOLOR_BSUPER2,
SKINCOLOR_BSUPER3,
SKINCOLOR_BSUPER4,
SKINCOLOR_BSUPER5,
// Aqua Super
SKINCOLOR_ASUPER1,
SKINCOLOR_ASUPER2,
SKINCOLOR_ASUPER3,
SKINCOLOR_ASUPER4,
SKINCOLOR_ASUPER5,
// Hyper Sonic Green
SKINCOLOR_GSUPER1,
SKINCOLOR_GSUPER2,
SKINCOLOR_GSUPER3,
SKINCOLOR_GSUPER4,
SKINCOLOR_GSUPER5,
// Hyper Sonic White
SKINCOLOR_WSUPER1,
SKINCOLOR_WSUPER2,
SKINCOLOR_WSUPER3,
SKINCOLOR_WSUPER4,
SKINCOLOR_WSUPER5,
// Creamy Super (Shadow?)
SKINCOLOR_CSUPER1,
SKINCOLOR_CSUPER2,
SKINCOLOR_CSUPER3,
SKINCOLOR_CSUPER4,
SKINCOLOR_CSUPER5,
MAXTRANSLATIONS MAXTRANSLATIONS
} skincolors_t; } skincolors_t;
@ -471,13 +541,17 @@ INT32 I_GetKey(void);
#define max(x, y) (((x) > (y)) ? (x) : (y)) #define max(x, y) (((x) > (y)) ? (x) : (y))
#endif #endif
#ifndef M_PIl
#define M_PIl 3.1415926535897932384626433832795029L
#endif
// Floating point comparison epsilons from float.h // Floating point comparison epsilons from float.h
#ifndef FLT_EPSILON #ifndef FLT_EPSILON
#define FLT_EPSILON 1.1920928955078125e-7f #define FLT_EPSILON 1.1920928955078125e-7f
#endif #endif
#ifndef DBL_EPSILON #ifndef DBL_EPSILON
#define DBL_EPSILON 2.2204460492503131e-16 #define DBL_EPSILON 2.2204460492503131e-16l
#endif #endif
// An assert-type mechanism. // An assert-type mechanism.

View File

@ -54,9 +54,9 @@ extern boolean gamecomplete;
// Set if homebrew PWAD stuff has been added. // Set if homebrew PWAD stuff has been added.
extern boolean modifiedgame; extern boolean modifiedgame;
extern boolean majormods;
extern UINT16 mainwads; extern UINT16 mainwads;
extern boolean savemoddata; // This mod saves time/emblem data. extern boolean savemoddata; // This mod saves time/emblem data.
extern boolean disableSpeedAdjust; // Don't alter the duration of player states if true
extern boolean imcontinuing; // Temporary flag while continuing extern boolean imcontinuing; // Temporary flag while continuing
extern boolean metalrecording; extern boolean metalrecording;
@ -280,6 +280,8 @@ typedef struct
#define LF2_NIGHTSATTACK 8 ///< Show this map in NiGHTS mode menu #define LF2_NIGHTSATTACK 8 ///< Show this map in NiGHTS mode menu
#define LF2_NOVISITNEEDED 16 ///< Available in time attack/nights mode without visiting the level #define LF2_NOVISITNEEDED 16 ///< Available in time attack/nights mode without visiting the level
#define LF2_EXISTSHACK 128 ///< Map lump exists; as noted, a single-bit hack that can be freely movable to other variables without concern.
// Save override // Save override
#define SAVE_NEVER -1 #define SAVE_NEVER -1
#define SAVE_DEFAULT 0 #define SAVE_DEFAULT 0
@ -465,6 +467,7 @@ extern boolean comeback;
extern SINT8 battlewanted[4]; extern SINT8 battlewanted[4];
extern tic_t wantedcalcdelay; extern tic_t wantedcalcdelay;
extern tic_t indirectitemcooldown; extern tic_t indirectitemcooldown;
extern tic_t hyubgone;
extern tic_t mapreset; extern tic_t mapreset;
extern UINT8 nospectategrief; extern UINT8 nospectategrief;
extern boolean thwompsactive; extern boolean thwompsactive;

View File

@ -181,7 +181,7 @@ static void F_SkyScroll(INT32 scrollspeed)
{ {
V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT, V_SNAPTOTOP|V_SNAPTOLEFT, pat, NULL); V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT, V_SNAPTOTOP|V_SNAPTOLEFT, pat, NULL);
x += SHORT(pat->width); x += SHORT(pat->width);
} }
x = -anim2; x = -anim2;
y = BASEVIDHEIGHT - SHORT(pat2->height); y = BASEVIDHEIGHT - SHORT(pat2->height);
@ -438,7 +438,7 @@ static const char *credits[] = {
"\"ZarroTsu\"", "\"ZarroTsu\"",
"", "",
"\1Support Programming", "\1Support Programming",
"\"fickle\"", "Colette \"fickleheart\" Bordelon",
"\"Lat\'\"", "\"Lat\'\"",
"\"Monster Iestyn\"", "\"Monster Iestyn\"",
"\"Shuffle\"", "\"Shuffle\"",
@ -479,40 +479,10 @@ static const char *credits[] = {
"\"VAdaPEGA\"", "\"VAdaPEGA\"",
"\"VelocitOni\"", "\"VelocitOni\"",
"", "",
"\1Music", // Can't list song names here, so we're listing artists "\1Music",
"\"Arrow\"",
"Jonny Atma",
"Moot Booxle", // Booxlé, add the accent char later?
"Malcolm Brown",
"Karl Brueggemann",
"\"DrTapeworm\"", "\"DrTapeworm\"",
"\"Elwood\"",
"Wesley \"Charyb\" Gillebaard", "Wesley \"Charyb\" Gillebaard",
"\"gxf4c3\"",
"James \"SeventhSentinel\" Hall", "James \"SeventhSentinel\" Hall",
"Chris Holland",
"Johnny \"J\"",
"Masato Kouda",
"Fumie Kumatani",
"Luke Kwing",
"James Landino",
"\"Lange\"",
"Takenobu Mitsuyoshi",
"\"Nib Roc\"",
"Tomoya Ohtani",
"Vincent Rubinetti",
"Jun Senoue",
"\"SSNTails\"",
"Michael \"MaxieDaMan\" Staple",
"Simon Stalenhag", // Stålenhag, add the accent char later?
"\"Synthescissor\"",
"Yuko Takehara",
"Tony Thai",
"\"The8BitDrummer\"",
"Kenichi Tokoi",
"\"Tokyo Active NEETs\"",
"\"xaki\"",
"Michiru Yamane",
"", "",
"\1Lead Level Design", "\1Lead Level Design",
"\"Blitz-T\"", "\"Blitz-T\"",
@ -586,7 +556,7 @@ static struct {
// This Tyler52 gag is troublesome // This Tyler52 gag is troublesome
// Alignment should be ((spaces+1 * 100) + (headers+1 * 38) + (lines * 15)) // Alignment should be ((spaces+1 * 100) + (headers+1 * 38) + (lines * 15))
// Current max image spacing: (200*17) // Current max image spacing: (200*17)
{112, (15*100)+(17*38)+(102*15), "TYLER52", SKINCOLOR_NONE}, {112, (15*100)+(17*38)+(72*15), "TYLER52", SKINCOLOR_NONE},
{0, 0, NULL, SKINCOLOR_NONE} {0, 0, NULL, SKINCOLOR_NONE}
}; };
@ -641,7 +611,7 @@ void F_CreditDrawer(void)
if (credits_pics[i].colorize != SKINCOLOR_NONE) if (credits_pics[i].colorize != SKINCOLOR_NONE)
{ {
colormap = R_GetTranslationColormap(TC_RAINBOW, credits_pics[i].colorize, 0); colormap = R_GetTranslationColormap(TC_RAINBOW, credits_pics[i].colorize, GTC_MENUCACHE);
sc = FRACUNIT; // quick hack so I don't have to add another field to credits_pics sc = FRACUNIT; // quick hack so I don't have to add another field to credits_pics
} }
@ -1133,6 +1103,10 @@ void F_StartWaitingPlayers(void)
finalecount = 0; finalecount = 0;
randskin = M_RandomKey(numskins); randskin = M_RandomKey(numskins);
if (waitcolormap)
Z_Free(waitcolormap);
waitcolormap = R_GetTranslationColormap(randskin, skins[randskin].prefcolor, 0); waitcolormap = R_GetTranslationColormap(randskin, skins[randskin].prefcolor, 0);
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)

View File

@ -26,6 +26,7 @@
#include "console.h" #include "console.h"
#include "d_main.h" #include "d_main.h"
#include "m_misc.h" // movie mode #include "m_misc.h" // movie mode
#include "d_clisrv.h" // So the network state can be updated during the wipe
#ifdef HWRENDER #ifdef HWRENDER
#include "hardware/hw_main.h" #include "hardware/hw_main.h"
@ -96,7 +97,7 @@ static fixed_t paldiv;
* \return fademask_t for lump * \return fademask_t for lump
*/ */
static fademask_t *F_GetFadeMask(UINT8 masknum, UINT8 scrnnum) { static fademask_t *F_GetFadeMask(UINT8 masknum, UINT8 scrnnum) {
static char lumpname[10] = "FADEmmss"; static char lumpname[9] = "FADEmmss";
static fademask_t fm = {NULL,0,0,0,0,0}; static fademask_t fm = {NULL,0,0,0,0,0};
lumpnum_t lumpnum; lumpnum_t lumpnum;
UINT8 *lump, *mask; UINT8 *lump, *mask;
@ -106,7 +107,14 @@ static fademask_t *F_GetFadeMask(UINT8 masknum, UINT8 scrnnum) {
if (masknum > 99 || scrnnum > 99) if (masknum > 99 || scrnnum > 99)
goto freemask; goto freemask;
sprintf(&lumpname[4], "%.2hu%.2hu", (UINT16)masknum, (UINT16)scrnnum); // SRB2Kart: This suddenly triggers ERRORMODE now
//sprintf(&lumpname[4], "%.2hu%.2hu", (UINT16)masknum, (UINT16)scrnnum);
lumpname[4] = '0'+(masknum/10);
lumpname[5] = '0'+(masknum%10);
lumpname[6] = '0'+(scrnnum/10);
lumpname[7] = '0'+(scrnnum%10);
lumpnum = W_CheckNumForName(lumpname); lumpnum = W_CheckNumForName(lumpname);
if (lumpnum == LUMPERROR) if (lumpnum == LUMPERROR)
@ -375,6 +383,8 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
if (moviemode) if (moviemode)
M_SaveFrame(); M_SaveFrame();
NetKeepAlive(); // Update the network so we don't cause timeouts
} }
WipeInAction = false; WipeInAction = false;
#endif #endif

View File

@ -88,7 +88,8 @@ typedef enum
REFRESHDIR_WARNING = 4, REFRESHDIR_WARNING = 4,
REFRESHDIR_ERROR = 8, REFRESHDIR_ERROR = 8,
REFRESHDIR_NOTLOADED = 16, REFRESHDIR_NOTLOADED = 16,
REFRESHDIR_MAX = 32 REFRESHDIR_MAX = 32,
REFRESHDIR_GAMEDATA = 64
} refreshdir_enum; } refreshdir_enum;
void closefilemenu(boolean validsize); void closefilemenu(boolean validsize);

View File

@ -16,6 +16,7 @@
#include "d_main.h" #include "d_main.h"
#include "d_player.h" #include "d_player.h"
#include "f_finale.h" #include "f_finale.h"
#include "filesrch.h" // for refreshdirmenu
#include "p_setup.h" #include "p_setup.h"
#include "p_saveg.h" #include "p_saveg.h"
#include "i_system.h" #include "i_system.h"
@ -86,11 +87,11 @@ INT16 lastmapsaved = 0; // Last map we auto-saved at
boolean gamecomplete = false; boolean gamecomplete = false;
UINT16 mainwads = 0; UINT16 mainwads = 0;
boolean modifiedgame; // Set if homebrew PWAD stuff has been added. boolean modifiedgame = false; // Set if homebrew PWAD stuff has been added.
boolean majormods = false; // Set if Lua/Gameplay SOC/replacement map has been added.
boolean savemoddata = false; boolean savemoddata = false;
UINT8 paused; UINT8 paused;
UINT8 modeattacking = ATTACKING_NONE; UINT8 modeattacking = ATTACKING_NONE;
boolean disableSpeedAdjust = true;
boolean imcontinuing = false; boolean imcontinuing = false;
boolean runemeraldmanager = false; boolean runemeraldmanager = false;
@ -265,6 +266,7 @@ SINT8 pickedvote; // What vote the host rolls
SINT8 battlewanted[4]; // WANTED players in battle, worth x2 points SINT8 battlewanted[4]; // WANTED players in battle, worth x2 points
tic_t wantedcalcdelay; // Time before it recalculates WANTED tic_t wantedcalcdelay; // Time before it recalculates WANTED
tic_t indirectitemcooldown; // Cooldown before any more Shrink, SPB, or any other item that works indirectly is awarded tic_t indirectitemcooldown; // Cooldown before any more Shrink, SPB, or any other item that works indirectly is awarded
tic_t hyubgone; // Cooldown before hyudoro is allowed to be rerolled
tic_t mapreset; // Map reset delay when enough players have joined an empty game tic_t mapreset; // Map reset delay when enough players have joined an empty game
UINT8 nospectategrief; // How many players need to be in-game to eliminate last; for preventing spectate griefing UINT8 nospectategrief; // How many players need to be in-game to eliminate last; for preventing spectate griefing
boolean thwompsactive; // Thwomps activate on lap 2 boolean thwompsactive; // Thwomps activate on lap 2
@ -435,6 +437,9 @@ consvar_t cv_chatbacktint = {"chatbacktint", "On", CV_SAVE, CV_OnOff, NULL, 0, N
static CV_PossibleValue_t consolechat_cons_t[] = {{0, "Window"}, {1, "Console"}, {2, "Window (Hidden)"}, {0, NULL}}; static CV_PossibleValue_t consolechat_cons_t[] = {{0, "Window"}, {1, "Console"}, {2, "Window (Hidden)"}, {0, NULL}};
consvar_t cv_consolechat = {"chatmode", "Window", CV_SAVE, consolechat_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_consolechat = {"chatmode", "Window", CV_SAVE, consolechat_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
// Pause game upon window losing focus
consvar_t cv_pauseifunfocused = {"pauseifunfocused", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
// Display song credits // Display song credits
consvar_t cv_songcredits = {"songcredits", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_songcredits = {"songcredits", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -752,16 +757,21 @@ void G_SetNightsRecords(void)
}*/ }*/
// for consistency among messages: this modifies the game and removes savemoddata. // for consistency among messages: this modifies the game and removes savemoddata.
void G_SetGameModified(boolean silent) void G_SetGameModified(boolean silent, boolean major)
{ {
if (modifiedgame && !savemoddata) if ((majormods && modifiedgame) || !mainwads || (refreshdirmenu & REFRESHDIR_GAMEDATA)) // new gamedata amnesty?
return; return;
modifiedgame = true; modifiedgame = true;
savemoddata = false;
if (!major)
return;
//savemoddata = false; -- there is literally no reason to do this anymore.
majormods = true;
if (!silent) if (!silent)
CONS_Alert(CONS_NOTICE, M_GetText("Game must be restarted to record statistics.\n")); CONS_Alert(CONS_NOTICE, M_GetText("Game must be restarted to play record attack.\n"));
// If in record attack recording, cancel it. // If in record attack recording, cancel it.
if (modeattacking) if (modeattacking)
@ -1209,7 +1219,7 @@ boolean camspin, camspin2, camspin3, camspin4;
static fixed_t forwardmove[2] = {25<<FRACBITS>>16, 50<<FRACBITS>>16}; static fixed_t forwardmove[2] = {25<<FRACBITS>>16, 50<<FRACBITS>>16};
static fixed_t sidemove[2] = {2<<FRACBITS>>16, 4<<FRACBITS>>16}; static fixed_t sidemove[2] = {2<<FRACBITS>>16, 4<<FRACBITS>>16};
static fixed_t angleturn[3] = {400, 800, 200}; // + slow turn static fixed_t angleturn[3] = {KART_FULLTURN/2, KART_FULLTURN, KART_FULLTURN/4}; // + slow turn
void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
{ {
@ -1352,41 +1362,30 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
// let movement keys cancel each other out // let movement keys cancel each other out
if (turnright && !(turnleft)) if (turnright && !(turnleft))
{ {
cmd->angleturn = (INT16)(cmd->angleturn - (angleturn[tspeed] * realtics)); cmd->angleturn = (INT16)(cmd->angleturn - (angleturn[tspeed]));
cmd->driftturn = (INT16)(cmd->driftturn - (angleturn[tspeed] * realtics)); cmd->driftturn = (INT16)(cmd->driftturn - (angleturn[tspeed]));
side += sidemove[1];
} }
else if (turnleft && !(turnright)) else if (turnleft && !(turnright))
{ {
cmd->angleturn = (INT16)(cmd->angleturn + (angleturn[tspeed] * realtics)); cmd->angleturn = (INT16)(cmd->angleturn + (angleturn[tspeed]));
cmd->driftturn = (INT16)(cmd->driftturn + (angleturn[tspeed] * realtics)); cmd->driftturn = (INT16)(cmd->driftturn + (angleturn[tspeed]));
side -= sidemove[1];
} }
if (analogjoystickmove && axis != 0) if (analogjoystickmove && axis != 0)
{ {
// JOYAXISRANGE should be 1023 (divide by 1024) // JOYAXISRANGE should be 1023 (divide by 1024)
cmd->angleturn = (INT16)(cmd->angleturn - (((axis * angleturn[1]) >> 10) * realtics)); // ANALOG! cmd->angleturn = (INT16)(cmd->angleturn - (((axis * angleturn[1]) >> 10))); // ANALOG!
cmd->driftturn = (INT16)(cmd->driftturn - (((axis * angleturn[1]) >> 10) * realtics)); cmd->driftturn = (INT16)(cmd->driftturn - (((axis * angleturn[1]) >> 10)));
side += ((axis * sidemove[0]) >> 10);
} }
// Specator mouse turning // Specator mouse turning
if (player->spectator) if (player->spectator)
{ {
cmd->angleturn = (INT16)(cmd->angleturn - ((mousex*(encoremode ? -1 : 1)*8) * realtics)); cmd->angleturn = (INT16)(cmd->angleturn - ((mousex*(encoremode ? -1 : 1)*8)));
cmd->driftturn = (INT16)(cmd->driftturn - ((mousex*(encoremode ? -1 : 1)*8) * realtics)); cmd->driftturn = (INT16)(cmd->driftturn - ((mousex*(encoremode ? -1 : 1)*8)));
}
// Speed bump strafing
if (!demoplayback && ((player->pflags & PF_FORCESTRAFE) || (player->kartstuff[k_pogospring])))
{
if (turnright)
side += sidemove[1];
if (turnleft)
side -= sidemove[1];
if (analogjoystickmove && axis != 0)
{
// JOYAXISRANGE is supposed to be 1023 (divide by 1024)
side += ((axis * sidemove[0]) >> 10);
}
} }
if (player->spectator || objectplacing) // SRB2Kart: spectators need special controls if (player->spectator || objectplacing) // SRB2Kart: spectators need special controls
@ -1531,15 +1530,6 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
else if (side < -MAXPLMOVE) else if (side < -MAXPLMOVE)
side = -MAXPLMOVE; side = -MAXPLMOVE;
// No additional acceleration when moving forward/backward and strafing simultaneously.
// do this AFTER we cap to MAXPLMOVE so people can't find ways to cheese around this.
// SRB2Kart: We don't need this; we WANT bounce strafing to plain stack on top of normal movement.
/*if (!bouncestrafe && forward && side)
{
forward = FixedMul(forward, 3*FRACUNIT/4);
side = FixedMul(side, 3*FRACUNIT/4);
}*/
if (forward || side) if (forward || side)
{ {
cmd->forwardmove = (SINT8)(cmd->forwardmove + forward); cmd->forwardmove = (SINT8)(cmd->forwardmove + forward);
@ -1549,19 +1539,21 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
//{ SRB2kart - Drift support //{ SRB2kart - Drift support
// Not grouped with the rest of turn stuff because it needs to know what buttons you're pressing for rubber-burn turn // Not grouped with the rest of turn stuff because it needs to know what buttons you're pressing for rubber-burn turn
// limit turning to angleturn[1] to stop mouselook letting you look too fast // limit turning to angleturn[1] to stop mouselook letting you look too fast
if (cmd->angleturn > (angleturn[1] * realtics)) if (cmd->angleturn > (angleturn[1]))
cmd->angleturn = (angleturn[1] * realtics); cmd->angleturn = (angleturn[1]);
else if (cmd->angleturn < (-angleturn[1] * realtics)) else if (cmd->angleturn < (-angleturn[1]))
cmd->angleturn = (-angleturn[1] * realtics); cmd->angleturn = (-angleturn[1]);
if (cmd->driftturn > (angleturn[1] * realtics)) if (cmd->driftturn > (angleturn[1]))
cmd->driftturn = (angleturn[1] * realtics); cmd->driftturn = (angleturn[1]);
else if (cmd->driftturn < (-angleturn[1] * realtics)) else if (cmd->driftturn < (-angleturn[1]))
cmd->driftturn = (-angleturn[1] * realtics); cmd->driftturn = (-angleturn[1]);
if (player->mo) if (player->mo)
cmd->angleturn = K_GetKartTurnValue(player, cmd->angleturn); cmd->angleturn = K_GetKartTurnValue(player, cmd->angleturn);
cmd->angleturn *= realtics;
// SRB2kart - no additional angle if not moving // SRB2kart - no additional angle if not moving
if (((player->mo && player->speed > 0) // Moving if (((player->mo && player->speed > 0) // Moving
|| (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn || (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn
@ -1571,6 +1563,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
lang += (cmd->angleturn<<16); lang += (cmd->angleturn<<16);
cmd->angleturn = (INT16)(lang >> 16); cmd->angleturn = (INT16)(lang >> 16);
cmd->latency = modeattacking ? 0 : (leveltime & 0xFF); // Send leveltime when this tic was generated to the server for control lag calculations
if (!hu_stopped) if (!hu_stopped)
{ {
@ -1612,10 +1605,26 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
} }
} }
/* Lua: Allow this hook to overwrite ticcmd.
We check if we're actually in a level because for some reason this Hook would run in menus and on the titlescreen otherwise.
Be aware that within this hook, nothing but this player's cmd can be edited (otherwise we'd run in some pretty bad synching problems since this is clientsided, or something)
Possible usages for this are:
-Forcing the player to perform an action, which could otherwise require terrible, terrible hacking to replicate.
-Preventing the player to perform an action, which would ALSO require some weirdo hacks.
-Making some galaxy brain autopilot Lua if you're a masochist
-Making a Mario Kart 8 Deluxe tier baby mode that steers you away from walls and whatnot. You know what, do what you want!
*/
#ifdef HAVE_BLUA
if (gamestate == GS_LEVEL)
LUAh_PlayerCmd(player, cmd);
#endif
//Reset away view if a command is given. //Reset away view if a command is given.
if ((cmd->forwardmove || cmd->sidemove || cmd->buttons) if ((cmd->forwardmove || cmd->sidemove || cmd->buttons)
&& displayplayer != consoleplayer && ssplayer == 1) && displayplayer != consoleplayer && ssplayer == 1)
displayplayer = consoleplayer; displayplayer = consoleplayer;
} }
// User has designated that they want // User has designated that they want
@ -1814,80 +1823,6 @@ static INT32 spectatedelay, spectatedelay2, spectatedelay3, spectatedelay4 = 0;
// //
boolean G_Responder(event_t *ev) boolean G_Responder(event_t *ev)
{ {
// allow spy mode changes even during the demo
if (gamestate == GS_LEVEL && ev->type == ev_keydown
&& (ev->data1 == KEY_F12 || ev->data1 == gamecontrol[gc_viewpoint][0] || ev->data1 == gamecontrol[gc_viewpoint][1]))
{
if (splitscreen || !netgame)
displayplayer = consoleplayer;
else
{
UINT8 i = 0; // spy mode
for (i = 0; i < MAXPLAYERS; i++)
{
displayplayer++;
if (displayplayer == MAXPLAYERS)
displayplayer = 0;
if (displayplayer == consoleplayer)
break; // End loop
if (!playeringame[displayplayer])
continue;
if (players[displayplayer].spectator)
continue;
// SRB2Kart: Only go through players who are actually playing
if (players[displayplayer].exiting)
continue;
if (players[displayplayer].pflags & PF_TIMEOVER)
continue;
// I don't know if we want this actually, but I'll humor the suggestion anyway
if (G_BattleGametype())
{
if (players[displayplayer].kartstuff[k_bumper] <= 0)
continue;
}
// SRB2Kart: we have no team-based modes, YET...
/*if (G_GametypeHasTeams())
{
if (players[consoleplayer].ctfteam
&& players[displayplayer].ctfteam != players[consoleplayer].ctfteam)
continue;
}
else if (gametype == GT_HIDEANDSEEK)
{
if (players[consoleplayer].pflags & PF_TAGIT)
continue;
}
// Other Tag-based gametypes?
else if (G_TagGametype())
{
if (!players[consoleplayer].spectator
&& (players[consoleplayer].pflags & PF_TAGIT) != (players[displayplayer].pflags & PF_TAGIT))
continue;
}
else if (G_GametypeHasSpectators() && G_BattleGametype())
{
if (!players[consoleplayer].spectator)
continue;
}*/
break;
}
// change statusbar also if playing back demo
if (singledemo)
ST_changeDemoView();
return true;
}
}
// any other key pops up menu if in demos // any other key pops up menu if in demos
if (gameaction == ga_nothing && !singledemo && if (gameaction == ga_nothing && !singledemo &&
((demoplayback && !modeattacking && !titledemo) || gamestate == GS_TITLESCREEN)) ((demoplayback && !modeattacking && !titledemo) || gamestate == GS_TITLESCREEN))
@ -1965,6 +1900,80 @@ boolean G_Responder(event_t *ev)
if (HU_Responder(ev)) if (HU_Responder(ev))
return true; // chat ate the event return true; // chat ate the event
// allow spy mode changes even during the demo
if (gamestate == GS_LEVEL && ev->type == ev_keydown
&& (ev->data1 == KEY_F12 || ev->data1 == gamecontrol[gc_viewpoint][0] || ev->data1 == gamecontrol[gc_viewpoint][1]))
{
if (splitscreen || !netgame)
displayplayer = consoleplayer;
else
{
UINT8 i = 0; // spy mode
for (i = 0; i < MAXPLAYERS; i++)
{
displayplayer++;
if (displayplayer == MAXPLAYERS)
displayplayer = 0;
if (displayplayer == consoleplayer)
break; // End loop
if (!playeringame[displayplayer])
continue;
if (players[displayplayer].spectator)
continue;
// SRB2Kart: Only go through players who are actually playing
if (players[displayplayer].exiting)
continue;
if (players[displayplayer].pflags & PF_TIMEOVER)
continue;
// I don't know if we want this actually, but I'll humor the suggestion anyway
if (G_BattleGametype())
{
if (players[displayplayer].kartstuff[k_bumper] <= 0)
continue;
}
// SRB2Kart: we have no team-based modes, YET...
/*if (G_GametypeHasTeams())
{
if (players[consoleplayer].ctfteam
&& players[displayplayer].ctfteam != players[consoleplayer].ctfteam)
continue;
}
else if (gametype == GT_HIDEANDSEEK)
{
if (players[consoleplayer].pflags & PF_TAGIT)
continue;
}
// Other Tag-based gametypes?
else if (G_TagGametype())
{
if (!players[consoleplayer].spectator
&& (players[consoleplayer].pflags & PF_TAGIT) != (players[displayplayer].pflags & PF_TAGIT))
continue;
}
else if (G_GametypeHasSpectators() && G_BattleGametype())
{
if (!players[consoleplayer].spectator)
continue;
}*/
break;
}
// change statusbar also if playing back demo
if (singledemo)
ST_changeDemoView();
return true;
}
}
// update keys current state // update keys current state
G_MapEventsToControls(ev); G_MapEventsToControls(ev);
@ -2154,6 +2163,9 @@ void G_Ticker(boolean run)
players[i].kartstuff[k_throwdir] = 0; players[i].kartstuff[k_throwdir] = 0;
G_CopyTiccmd(cmd, &netcmds[buf][i], 1); G_CopyTiccmd(cmd, &netcmds[buf][i], 1);
// Use the leveltime sent in the player's ticcmd to determine control lag
cmd->latency = modeattacking ? 0 : min(((leveltime & 0xFF) - cmd->latency) & 0xFF, MAXPREDICTTICS-1); //@TODO add a cvar to allow setting this max
} }
} }
@ -2348,6 +2360,7 @@ void G_PlayerReborn(INT32 player)
UINT8 skincolor; UINT8 skincolor;
INT32 skin; INT32 skin;
tic_t jointime; tic_t jointime;
UINT8 splitscreenindex;
boolean spectator; boolean spectator;
INT16 bot; INT16 bot;
SINT8 pity; SINT8 pity;
@ -2362,6 +2375,7 @@ void G_PlayerReborn(INT32 player)
INT32 bumper; INT32 bumper;
INT32 comebackpoints; INT32 comebackpoints;
INT32 wanted; INT32 wanted;
INT32 respawnflip;
boolean songcredit = false; boolean songcredit = false;
score = players[player].score; score = players[player].score;
@ -2371,6 +2385,7 @@ void G_PlayerReborn(INT32 player)
ctfteam = players[player].ctfteam; ctfteam = players[player].ctfteam;
exiting = players[player].exiting; exiting = players[player].exiting;
jointime = players[player].jointime; jointime = players[player].jointime;
splitscreenindex = players[player].splitscreenindex;
spectator = players[player].spectator; spectator = players[player].spectator;
pflags = (players[player].pflags & (PF_TIMEOVER|PF_FLIPCAM|PF_TAGIT|PF_TAGGED|PF_ANALOGMODE|PF_WANTSTOJOIN)); pflags = (players[player].pflags & (PF_TIMEOVER|PF_FLIPCAM|PF_TAGIT|PF_TAGGED|PF_ANALOGMODE|PF_WANTSTOJOIN));
@ -2402,6 +2417,7 @@ void G_PlayerReborn(INT32 player)
starposty = players[player].starposty; starposty = players[player].starposty;
starpostz = players[player].starpostz; starpostz = players[player].starpostz;
starpostnum = players[player].starpostnum; starpostnum = players[player].starpostnum;
respawnflip = players[player].kartstuff[k_starpostflip]; //SRB2KART
starpostangle = players[player].starpostangle; starpostangle = players[player].starpostangle;
jumpfactor = players[player].jumpfactor; jumpfactor = players[player].jumpfactor;
thokitem = players[player].thokitem; thokitem = players[player].thokitem;
@ -2467,6 +2483,7 @@ void G_PlayerReborn(INT32 player)
p->pflags = pflags; p->pflags = pflags;
p->ctfteam = ctfteam; p->ctfteam = ctfteam;
p->jointime = jointime; p->jointime = jointime;
p->splitscreenindex = splitscreenindex;
p->spectator = spectator; p->spectator = spectator;
// save player config truth reborn // save player config truth reborn
@ -2521,6 +2538,7 @@ void G_PlayerReborn(INT32 player)
p->kartstuff[k_comebacktimer] = comebacktime; p->kartstuff[k_comebacktimer] = comebacktime;
p->kartstuff[k_wanted] = wanted; p->kartstuff[k_wanted] = wanted;
p->kartstuff[k_eggmanblame] = -1; p->kartstuff[k_eggmanblame] = -1;
p->kartstuff[k_starpostflip] = respawnflip;
// Don't do anything immediately // Don't do anything immediately
p->pflags |= PF_USEDOWN; p->pflags |= PF_USEDOWN;
@ -3173,7 +3191,7 @@ INT16 G_SometimesGetDifferentGametype(void)
break; break;
case 1: // sometimes case 1: // sometimes
default: default:
encorepossible = M_RandomChance(FRACUNIT>>3); encorepossible = M_RandomChance(FRACUNIT>>2);
break; break;
} }
if (encorepossible != (boolean)cv_kartencore.value) if (encorepossible != (boolean)cv_kartencore.value)
@ -3188,12 +3206,12 @@ INT16 G_SometimesGetDifferentGametype(void)
randmapbuffer[NUMMAPS] = 1; // every other vote (or always if !encorepossible) randmapbuffer[NUMMAPS] = 1; // every other vote (or always if !encorepossible)
break; break;
case 1: // sometimes case 1: // sometimes
randmapbuffer[NUMMAPS] = 10; // ...every two cups? randmapbuffer[NUMMAPS] = 5; // per "cup"
break; break;
default: default:
// fallthrough - happens when clearing buffer, but needs a reasonable countdown if cvar is modified // fallthrough - happens when clearing buffer, but needs a reasonable countdown if cvar is modified
case 2: // frequent case 2: // frequent
randmapbuffer[NUMMAPS] = 5; // per "cup" randmapbuffer[NUMMAPS] = 2; // ...every 1/2th-ish cup?
break; break;
} }
@ -3940,7 +3958,6 @@ void G_LoadGameData(void)
// Saves the main data file, which stores information such as emblems found, etc. // Saves the main data file, which stores information such as emblems found, etc.
void G_SaveGameData(boolean force) void G_SaveGameData(boolean force)
{ {
const boolean wasmodified = modifiedgame;
size_t length; size_t length;
INT32 i, j; INT32 i, j;
UINT8 btemp; UINT8 btemp;
@ -3957,9 +3974,7 @@ void G_SaveGameData(boolean force)
return; return;
} }
if (force) // SRB2Kart: for enabling unlocks online, even if the game is modified if (majormods && !force)
modifiedgame = savemoddata; // L-let's just sort of... hack around the cheat protection, because I'm too worried about just removing it @@;
else if (modifiedgame && !savemoddata)
{ {
free(savebuffer); free(savebuffer);
save_p = savebuffer = NULL; save_p = savebuffer = NULL;
@ -3972,7 +3987,7 @@ void G_SaveGameData(boolean force)
WRITEUINT32(save_p, totalplaytime); WRITEUINT32(save_p, totalplaytime);
WRITEUINT32(save_p, matchesplayed); WRITEUINT32(save_p, matchesplayed);
btemp = (UINT8)(savemoddata || modifiedgame); btemp = (UINT8)(savemoddata); // what used to be here was profoundly dunderheaded
WRITEUINT8(save_p, btemp); WRITEUINT8(save_p, btemp);
// TODO put another cipher on these things? meh, I don't care... // TODO put another cipher on these things? meh, I don't care...
@ -4058,9 +4073,6 @@ void G_SaveGameData(boolean force)
FIL_WriteFile(va(pandf, srb2home, gamedatafilename), savebuffer, length); FIL_WriteFile(va(pandf, srb2home, gamedatafilename), savebuffer, length);
free(savebuffer); free(savebuffer);
save_p = savebuffer = NULL; save_p = savebuffer = NULL;
if (force) // Eeeek, I'm sorry for my sins!
modifiedgame = wasmodified;
} }
#define VERSIONSIZE 16 #define VERSIONSIZE 16
@ -4561,6 +4573,7 @@ ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n)
dest[i].aiming = (INT16)SHORT(src[i].aiming); dest[i].aiming = (INT16)SHORT(src[i].aiming);
dest[i].buttons = (UINT16)SHORT(src[i].buttons); dest[i].buttons = (UINT16)SHORT(src[i].buttons);
dest[i].driftturn = (INT16)SHORT(src[i].driftturn); dest[i].driftturn = (INT16)SHORT(src[i].driftturn);
dest[i].latency = (INT16)SHORT(src[i].latency);
} }
return dest; return dest;
} }
@ -4759,7 +4772,8 @@ void G_WriteGhostTic(mobj_t *ghost)
// GZT_XYZ is only useful if you've moved 256 FRACUNITS or more in a single tic. // GZT_XYZ is only useful if you've moved 256 FRACUNITS or more in a single tic.
if (abs(ghost->x-oldghost.x) > MAXMOM if (abs(ghost->x-oldghost.x) > MAXMOM
|| abs(ghost->y-oldghost.y) > MAXMOM || abs(ghost->y-oldghost.y) > MAXMOM
|| abs(ghost->z-oldghost.z) > MAXMOM) || abs(ghost->z-oldghost.z) > MAXMOM
|| (leveltime & 255) == 1) // Hack to enable slightly nicer resyncing
{ {
oldghost.x = ghost->x; oldghost.x = ghost->x;
oldghost.y = ghost->y; oldghost.y = ghost->y;
@ -4773,8 +4787,8 @@ void G_WriteGhostTic(mobj_t *ghost)
{ {
// For moving normally: // For moving normally:
// Store one full byte of movement, plus one byte of fractional movement. // Store one full byte of movement, plus one byte of fractional movement.
INT16 momx = (INT16)((ghost->x-oldghost.x)>>8); INT16 momx = (INT16)((ghost->x-oldghost.x + (1<<4))>>8);
INT16 momy = (INT16)((ghost->y-oldghost.y)>>8); INT16 momy = (INT16)((ghost->y-oldghost.y + (1<<4))>>8);
if (momx != oldghost.momx if (momx != oldghost.momx
|| momy != oldghost.momy) || momy != oldghost.momy)
{ {
@ -4784,7 +4798,7 @@ void G_WriteGhostTic(mobj_t *ghost)
WRITEINT16(demo_p,momx); WRITEINT16(demo_p,momx);
WRITEINT16(demo_p,momy); WRITEINT16(demo_p,momy);
} }
momx = (INT16)((ghost->z-oldghost.z)>>8); momx = (INT16)((ghost->z-oldghost.z + (1<<4))>>8);
if (momx != oldghost.momz) if (momx != oldghost.momz)
{ {
oldghost.momz = momx; oldghost.momz = momx;
@ -4888,8 +4902,9 @@ void G_WriteGhostTic(mobj_t *ghost)
void G_ConsGhostTic(void) void G_ConsGhostTic(void)
{ {
UINT8 ziptic; UINT8 ziptic;
UINT16 px,py,pz,gx,gy,gz; fixed_t px,py,pz,gx,gy,gz;
mobj_t *testmo; mobj_t *testmo;
fixed_t syncleeway;
boolean nightsfail = false; boolean nightsfail = false;
if (!demo_p || !demo_start) if (!demo_p || !demo_start)
@ -4906,6 +4921,7 @@ void G_ConsGhostTic(void)
oldghost.x = READFIXED(demo_p); oldghost.x = READFIXED(demo_p);
oldghost.y = READFIXED(demo_p); oldghost.y = READFIXED(demo_p);
oldghost.z = READFIXED(demo_p); oldghost.z = READFIXED(demo_p);
syncleeway = 0;
} }
else else
{ {
@ -4919,6 +4935,7 @@ void G_ConsGhostTic(void)
oldghost.x += oldghost.momx; oldghost.x += oldghost.momx;
oldghost.y += oldghost.momy; oldghost.y += oldghost.momy;
oldghost.z += oldghost.momz; oldghost.z += oldghost.momz;
syncleeway = FRACUNIT;
} }
if (ziptic & GZT_ANGLE) if (ziptic & GZT_ANGLE)
demo_p++; demo_p++;
@ -4984,14 +5001,14 @@ void G_ConsGhostTic(void)
} }
// Re-synchronise // Re-synchronise
px = testmo->x>>FRACBITS; px = testmo->x;
py = testmo->y>>FRACBITS; py = testmo->y;
pz = testmo->z>>FRACBITS; pz = testmo->z;
gx = oldghost.x>>FRACBITS; gx = oldghost.x;
gy = oldghost.y>>FRACBITS; gy = oldghost.y;
gz = oldghost.z>>FRACBITS; gz = oldghost.z;
if (nightsfail || px != gx || py != gy || pz != gz) if (nightsfail || abs(px-gx) > syncleeway || abs(py-gy) > syncleeway || abs(pz-gz) > syncleeway)
{ {
if (demosynced) if (demosynced)
CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n"));
@ -5102,17 +5119,16 @@ void G_GhostTicker(void)
INT32 type = -1; INT32 type = -1;
if (g->mo->skin) if (g->mo->skin)
{ {
skin_t *skin = (skin_t *)g->mo->skin;
switch (ziptic & EZT_THOKMASK) switch (ziptic & EZT_THOKMASK)
{ {
case EZT_THOK: case EZT_THOK:
type = skin->thokitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].painchance : (UINT32)skin->thokitem; type = (UINT32)mobjinfo[MT_PLAYER].painchance;
break; break;
case EZT_SPIN: case EZT_SPIN:
type = skin->spinitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].damage : (UINT32)skin->spinitem; type = (UINT32)mobjinfo[MT_PLAYER].damage;
break; break;
case EZT_REV: case EZT_REV:
type = skin->revitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem; type = (UINT32)mobjinfo[MT_PLAYER].raisestate;
break; break;
} }
} }
@ -5147,22 +5163,20 @@ void G_GhostTicker(void)
if (ziptic & EZT_HIT) if (ziptic & EZT_HIT)
{ // Spawn hit poofs for killing things! { // Spawn hit poofs for killing things!
UINT16 i, count = READUINT16(g->p), health; UINT16 i, count = READUINT16(g->p), health;
UINT32 type; //UINT32 type;
fixed_t x,y,z; fixed_t x,y,z;
angle_t angle; angle_t angle;
mobj_t *poof; mobj_t *poof;
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
g->p += 4; // reserved g->p += 4; // reserved
type = READUINT32(g->p); g->p += 4; // backwards compat., type used to be here
health = READUINT16(g->p); health = READUINT16(g->p);
x = READFIXED(g->p); x = READFIXED(g->p);
y = READFIXED(g->p); y = READFIXED(g->p);
z = READFIXED(g->p); z = READFIXED(g->p);
angle = READANGLE(g->p); angle = READANGLE(g->p);
if (!(mobjinfo[type].flags & MF_SHOOTABLE) if (health != 0 || i >= 4) // only spawn for the first 4 hits per frame, to prevent ghosts from splode-spamming too bad.
|| !(mobjinfo[type].flags & (MF_ENEMY|MF_MONITOR))
|| health != 0 || i >= 4) // only spawn for the first 4 hits per frame, to prevent ghosts from splode-spamming too bad.
continue; continue;
poof = P_SpawnMobj(x, y, z, MT_GHOST); poof = P_SpawnMobj(x, y, z, MT_GHOST);
poof->angle = angle; poof->angle = angle;
@ -5918,6 +5932,32 @@ void G_DoPlayDemo(char *defdemoname)
return; return;
} }
// Skin not loaded?
if (!SetPlayerSkin(0, skin))
{
snprintf(msg, 1024, M_GetText("%s features a character that is not currently loaded.\n"), pdemoname);
CONS_Alert(CONS_ERROR, "%s", msg);
M_StartMessage(msg, NULL, MM_NOTHING);
Z_Free(pdemoname);
Z_Free(demobuffer);
demoplayback = false;
titledemo = false;
return;
}
// ...*map* not loaded?
if (!gamemap || (gamemap > NUMMAPS) || !mapheaderinfo[gamemap-1] || !(mapheaderinfo[gamemap-1]->menuflags & LF2_EXISTSHACK))
{
snprintf(msg, 1024, M_GetText("%s features a course that is not currently loaded.\n"), pdemoname);
CONS_Alert(CONS_ERROR, "%s", msg);
M_StartMessage(msg, NULL, MM_NOTHING);
Z_Free(pdemoname);
Z_Free(demobuffer);
demoplayback = false;
titledemo = false;
return;
}
Z_Free(pdemoname); Z_Free(pdemoname);
memset(&oldcmd,0,sizeof(oldcmd)); memset(&oldcmd,0,sizeof(oldcmd));
@ -5949,9 +5989,6 @@ void G_DoPlayDemo(char *defdemoname)
P_SetRandSeed(randseed); P_SetRandSeed(randseed);
G_InitNew(false, G_BuildMapName(gamemap), true, true); // Doesn't matter whether you reset or not here, given changes to resetplayer. G_InitNew(false, G_BuildMapName(gamemap), true, true); // Doesn't matter whether you reset or not here, given changes to resetplayer.
// Set skin
SetPlayerSkin(0, skin);
// Set color // Set color
for (i = 0; i < MAXSKINCOLORS; i++) for (i = 0; i < MAXSKINCOLORS; i++)
if (!stricmp(KartColor_Names[i],color)) // SRB2kart if (!stricmp(KartColor_Names[i],color)) // SRB2kart
@ -6001,6 +6038,7 @@ void G_AddGhost(char *defdemoname)
UINT8 *buffer,*p; UINT8 *buffer,*p;
mapthing_t *mthing; mapthing_t *mthing;
UINT16 count, ghostversion; UINT16 count, ghostversion;
skin_t *ghskin = &skins[0];
name[16] = '\0'; name[16] = '\0';
skin[16] = '\0'; skin[16] = '\0';
@ -6146,6 +6184,21 @@ void G_AddGhost(char *defdemoname)
return; return;
} }
for (i = 0; i < numskins; i++)
if (!stricmp(skins[i].name,skin))
{
ghskin = &skins[i];
break;
}
if (i == numskins)
{
CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid character.\n"), pdemoname);
Z_Free(pdemoname);
Z_Free(buffer);
return;
}
gh = Z_Calloc(sizeof(demoghost), PU_LEVEL, NULL); gh = Z_Calloc(sizeof(demoghost), PU_LEVEL, NULL);
gh->next = ghosts; gh->next = ghosts;
gh->buffer = buffer; gh->buffer = buffer;
@ -6191,14 +6244,7 @@ void G_AddGhost(char *defdemoname)
gh->oldmo.z = gh->mo->z; gh->oldmo.z = gh->mo->z;
// Set skin // Set skin
gh->mo->skin = &skins[0]; gh->mo->skin = gh->oldmo.skin = ghskin;
for (i = 0; i < numskins; i++)
if (!stricmp(skins[i].name,skin))
{
gh->mo->skin = &skins[i];
break;
}
gh->oldmo.skin = gh->mo->skin;
// Set color // Set color
gh->mo->color = ((skin_t*)gh->mo->skin)->prefcolor; gh->mo->color = ((skin_t*)gh->mo->skin)->prefcolor;

View File

@ -56,6 +56,7 @@ extern INT16 rw_maximums[NUM_WEAPONS];
// used in game menu // used in game menu
extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatbacktint, cv_chatspamprotection/*, cv_compactscoreboard*/; extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatbacktint, cv_chatspamprotection/*, cv_compactscoreboard*/;
extern consvar_t cv_songcredits; extern consvar_t cv_songcredits;
extern consvar_t cv_pauseifunfocused;
//extern consvar_t cv_crosshair, cv_crosshair2, cv_crosshair3, cv_crosshair4; //extern consvar_t cv_crosshair, cv_crosshair2, cv_crosshair3, cv_crosshair4;
extern consvar_t cv_invertmouse/*, cv_alwaysfreelook, cv_chasefreelook, cv_mousemove*/; extern consvar_t cv_invertmouse/*, cv_alwaysfreelook, cv_chasefreelook, cv_mousemove*/;
extern consvar_t cv_invertmouse2/*, cv_alwaysfreelook2, cv_chasefreelook2, cv_mousemove2*/; extern consvar_t cv_invertmouse2/*, cv_alwaysfreelook2, cv_chasefreelook2, cv_mousemove2*/;
@ -66,7 +67,6 @@ extern consvar_t cv_turnaxis2,cv_moveaxis2,cv_brakeaxis2,cv_aimaxis2,cv_lookaxis
extern consvar_t cv_turnaxis3,cv_moveaxis3,cv_brakeaxis3,cv_aimaxis3,cv_lookaxis3,cv_fireaxis3,cv_driftaxis3; extern consvar_t cv_turnaxis3,cv_moveaxis3,cv_brakeaxis3,cv_aimaxis3,cv_lookaxis3,cv_fireaxis3,cv_driftaxis3;
extern consvar_t cv_turnaxis4,cv_moveaxis4,cv_brakeaxis4,cv_aimaxis4,cv_lookaxis4,cv_fireaxis4,cv_driftaxis4; extern consvar_t cv_turnaxis4,cv_moveaxis4,cv_brakeaxis4,cv_aimaxis4,cv_lookaxis4,cv_fireaxis4,cv_driftaxis4;
extern consvar_t cv_ghost_besttime, cv_ghost_bestlap, cv_ghost_last, cv_ghost_guest, cv_ghost_staff; extern consvar_t cv_ghost_besttime, cv_ghost_bestlap, cv_ghost_last, cv_ghost_guest, cv_ghost_staff;
extern consvar_t cv_splitplayers;
typedef enum typedef enum
{ {
@ -227,7 +227,7 @@ boolean G_GetRetryFlag(void);
void G_LoadGameData(void); void G_LoadGameData(void);
void G_LoadGameSettings(void); void G_LoadGameSettings(void);
void G_SetGameModified(boolean silent); void G_SetGameModified(boolean silent, boolean major);
void G_SetGamestate(gamestate_t newstate); void G_SetGamestate(gamestate_t newstate);

View File

@ -37,7 +37,7 @@ INT32 mlooky; // like mousey but with a custom sensitivity for mlook
INT32 mouse2x, mouse2y, mlook2y; INT32 mouse2x, mouse2y, mlook2y;
// joystick values are repeated // joystick values are repeated
INT32 joyxmove[JOYAXISSET], joyymove[JOYAXISSET], joy2xmove[JOYAXISSET], joy2ymove[JOYAXISSET], INT32 joyxmove[JOYAXISSET], joyymove[JOYAXISSET], joy2xmove[JOYAXISSET], joy2ymove[JOYAXISSET],
joy3xmove[JOYAXISSET], joy3ymove[JOYAXISSET], joy4xmove[JOYAXISSET], joy4ymove[JOYAXISSET]; joy3xmove[JOYAXISSET], joy3ymove[JOYAXISSET], joy4xmove[JOYAXISSET], joy4ymove[JOYAXISSET];
// current state of the keys: true if pushed // current state of the keys: true if pushed
@ -120,7 +120,7 @@ void G_MapEventsToControls(event_t *ev)
case ev_joystick2: // buttons are virtual keys case ev_joystick2: // buttons are virtual keys
i = ev->data1; i = ev->data1;
if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on) if (i >= JOYAXISSET || menuactive)
break; break;
if (ev->data2 != INT32_MAX) joy2xmove[i] = ev->data2; if (ev->data2 != INT32_MAX) joy2xmove[i] = ev->data2;
if (ev->data3 != INT32_MAX) joy2ymove[i] = ev->data3; if (ev->data3 != INT32_MAX) joy2ymove[i] = ev->data3;
@ -1308,7 +1308,7 @@ void G_Controldefault(UINT8 player)
gamecontrol[gc_brake ][1] = KEY_JOY1+1; // B gamecontrol[gc_brake ][1] = KEY_JOY1+1; // B
gamecontrol[gc_fire ][1] = KEY_JOY1+4; // LB gamecontrol[gc_fire ][1] = KEY_JOY1+4; // LB
gamecontrol[gc_drift ][1] = KEY_JOY1+5; // RB gamecontrol[gc_drift ][1] = KEY_JOY1+5; // RB
// Extra controls // Extra controls
gamecontrol[gc_pause ][0] = KEY_PAUSE; gamecontrol[gc_pause ][0] = KEY_PAUSE;
gamecontrol[gc_console ][0] = KEY_CONSOLE; gamecontrol[gc_console ][0] = KEY_CONSOLE;

View File

@ -201,7 +201,7 @@ static polyvertex_t *fracdivline(fdivline_t *bsp, polyvertex_t *v1,
// (do not accept hit with the extensions) // (do not accept hit with the extensions)
num = (v2x - v1x)*v2dy + (v1y - v2y)*v2dx; num = (v2x - v1x)*v2dy + (v1y - v2y)*v2dx;
frac = num / den; frac = num / den;
if (frac < 0.0 || frac > 1.0) if (frac < 0.0l || frac > 1.0l)
return NULL; return NULL;
// now get the frac along the BSP line // now get the frac along the BSP line

View File

@ -72,6 +72,7 @@
#include "../v_video.h" #include "../v_video.h"
#include "hw_clip.h" #include "hw_clip.h"
#include "hw_glob.h" #include "hw_glob.h"
#include "../r_main.h"
#include "../r_state.h" #include "../r_state.h"
#include "../tables.h" #include "../tables.h"
#include "r_opengl/r_opengl.h" #include "r_opengl/r_opengl.h"
@ -328,7 +329,7 @@ angle_t gld_FrustumAngle(void)
// NEWCLIP TODO: SRB2CBTODO: make a global render_fov for this function // NEWCLIP TODO: SRB2CBTODO: make a global render_fov for this function
float render_fov = FIXED_TO_FLOAT(cv_grfov.value); float render_fov = FIXED_TO_FLOAT(cv_fov.value);
float render_fovratio = (float)BASEVIDWIDTH / (float)BASEVIDHEIGHT; // SRB2CBTODO: NEWCLIPTODO: Is this right? float render_fovratio = (float)BASEVIDWIDTH / (float)BASEVIDHEIGHT; // SRB2CBTODO: NEWCLIPTODO: Is this right?
float render_multiplier = 64.0f / render_fovratio / RMUL; float render_multiplier = 64.0f / render_fovratio / RMUL;

View File

@ -61,9 +61,6 @@ typedef void (*I_Error_t) (const char *error, ...) FUNCIERROR;
// ========================================================================== // ==========================================================================
// Constants // Constants
#ifndef M_PIl
#define M_PIl 3.1415926535897932384626433832795029L
#endif
#define DEGREE (0.017453292519943295769236907684883l) // 2*PI/360 #define DEGREE (0.017453292519943295769236907684883l) // 2*PI/360
void DBG_Printf(const char *lpFmt, ...) /*FUNCPRINTF*/; void DBG_Printf(const char *lpFmt, ...) /*FUNCPRINTF*/;

View File

@ -86,12 +86,10 @@ static UINT32 atohex(const char *s);
static void CV_filtermode_ONChange(void); static void CV_filtermode_ONChange(void);
static void CV_anisotropic_ONChange(void); static void CV_anisotropic_ONChange(void);
static void CV_FogDensity_ONChange(void); static void CV_FogDensity_ONChange(void);
static void CV_grFov_OnChange(void);
// ========================================================================== // ==========================================================================
// 3D ENGINE COMMANDS & CONSOLE VARS // 3D ENGINE COMMANDS & CONSOLE VARS
// ========================================================================== // ==========================================================================
static CV_PossibleValue_t grfov_cons_t[] = {{0, "MIN"}, {179*FRACUNIT, "MAX"}, {0, NULL}};
static CV_PossibleValue_t grfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSAMPLED, "Nearest"}, static CV_PossibleValue_t grfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSAMPLED, "Nearest"},
{HWD_SET_TEXTUREFILTER_BILINEAR, "Bilinear"}, {HWD_SET_TEXTUREFILTER_TRILINEAR, "Trilinear"}, {HWD_SET_TEXTUREFILTER_BILINEAR, "Bilinear"}, {HWD_SET_TEXTUREFILTER_TRILINEAR, "Trilinear"},
{HWD_SET_TEXTUREFILTER_MIXED1, "Linear_Nearest"}, {HWD_SET_TEXTUREFILTER_MIXED1, "Linear_Nearest"},
@ -112,7 +110,6 @@ static consvar_t cv_grbeta = {"gr_beta", "0", 0, CV_Unsigned, NULL, 0, NULL, NUL
static float HWRWipeCounter = 1.0f; static float HWRWipeCounter = 1.0f;
consvar_t cv_grrounddown = {"gr_rounddown", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grrounddown = {"gr_rounddown", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grfov = {"gr_fov", "90", CV_FLOAT|CV_CALL, grfov_cons_t, CV_grFov_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grfogdensity = {"gr_fogdensity", "150", CV_CALL|CV_NOINIT, CV_Unsigned, consvar_t cv_grfogdensity = {"gr_fogdensity", "150", CV_CALL|CV_NOINIT, CV_Unsigned,
CV_FogDensity_ONChange, 0, NULL, NULL, 0, 0, NULL}; CV_FogDensity_ONChange, 0, NULL, NULL, 0, 0, NULL};
@ -5263,7 +5260,8 @@ static void HWR_DrawSprites(void)
#endif #endif
if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
{ {
if (!cv_grmd2.value || md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) // 8/1/19: Only don't display player models if no default SPR_PLAY is found.
if (!cv_grmd2.value || ((md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) && (md2_models[SPR_PLAY].notfound || md2_models[SPR_PLAY].scale < 0.0f)))
HWR_DrawSprite(spr); HWR_DrawSprite(spr);
else else
HWR_DrawMD2(spr); HWR_DrawMD2(spr);
@ -5906,7 +5904,7 @@ void HWR_SetViewSize(void)
// ========================================================================== // ==========================================================================
void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player)
{ {
const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd); const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd);
postimg_t *type; postimg_t *type;
UINT8 ssplayer = 0; UINT8 ssplayer = 0;
@ -6072,7 +6070,7 @@ if (0)
viewangle = localaiming4; viewangle = localaiming4;
// Handle stuff when you are looking farther up or down. // Handle stuff when you are looking farther up or down.
if ((aimingangle || cv_grfov.value+player->fovadd > 90*FRACUNIT)) if ((aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT))
{ {
dup_viewangle += ANGLE_90; dup_viewangle += ANGLE_90;
HWR_ClearClipSegs(); HWR_ClearClipSegs();
@ -6150,7 +6148,7 @@ if (0)
// ========================================================================== // ==========================================================================
void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
{ {
const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd); const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd);
postimg_t *type; postimg_t *type;
UINT8 ssplayer = 0; UINT8 ssplayer = 0;
@ -6331,7 +6329,7 @@ if (0)
viewangle = localaiming4; viewangle = localaiming4;
// Handle stuff when you are looking farther up or down. // Handle stuff when you are looking farther up or down.
if ((aimingangle || cv_grfov.value+player->fovadd > 90*FRACUNIT)) if ((aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT))
{ {
dup_viewangle += ANGLE_90; dup_viewangle += ANGLE_90;
HWR_ClearClipSegs(); HWR_ClearClipSegs();
@ -6454,11 +6452,6 @@ static void HWR_FoggingOn(void)
// ========================================================================== // ==========================================================================
static void CV_grFov_OnChange(void)
{
if ((netgame || multiplayer) && !cv_debug && cv_grfov.value != 90*FRACUNIT)
CV_Set(&cv_grfov, cv_grfov.defaultvalue);
}
static void Command_GrStats_f(void) static void Command_GrStats_f(void)
{ {
@ -6481,7 +6474,6 @@ static void Command_GrStats_f(void)
void HWR_AddCommands(void) void HWR_AddCommands(void)
{ {
CV_RegisterVar(&cv_grrounddown); CV_RegisterVar(&cv_grrounddown);
CV_RegisterVar(&cv_grfov);
CV_RegisterVar(&cv_grfogdensity); CV_RegisterVar(&cv_grfogdensity);
CV_RegisterVar(&cv_grfiltermode); CV_RegisterVar(&cv_grfiltermode);
CV_RegisterVar(&cv_granisotropicmode); CV_RegisterVar(&cv_granisotropicmode);

View File

@ -79,7 +79,6 @@ extern consvar_t cv_grstaticlighting;
extern consvar_t cv_grcoronas; extern consvar_t cv_grcoronas;
extern consvar_t cv_grcoronasize; extern consvar_t cv_grcoronasize;
#endif #endif
extern consvar_t cv_grfov;
extern consvar_t cv_grmd2; extern consvar_t cv_grmd2;
extern consvar_t cv_grfog; extern consvar_t cv_grfog;
extern consvar_t cv_grfogcolor; extern consvar_t cv_grfogcolor;

View File

@ -162,7 +162,7 @@ static GrTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_
jmp_buf jmpbuf; jmp_buf jmpbuf;
#endif #endif
#endif #endif
png_FILE_p png_FILE; volatile png_FILE_p png_FILE;
//Filename checking fixed ~Monster Iestyn and Golden //Filename checking fixed ~Monster Iestyn and Golden
char *pngfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2home, filename); char *pngfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2home, filename);
@ -508,11 +508,12 @@ void HWR_InitMD2(void)
} }
while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4) while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4)
{ {
if (stricmp(name, "PLAY") == 0) /*if (stricmp(name, "PLAY") == 0)
{ {
CONS_Printf("MD2 for sprite PLAY detected in kmd2.dat, use a player skin instead!\n"); CONS_Printf("MD2 for sprite PLAY detected in kmd2.dat, use a player skin instead!\n");
continue; continue;
} }*/
// 8/1/19: Allow PLAY to load for default MD2.
for (i = 0; i < NUMSPRITES; i++) for (i = 0; i < NUMSPRITES; i++)
{ {
@ -874,6 +875,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
// MD2 colormap fix // MD2 colormap fix
// colormap test // colormap test
if (spr->mobj->subsector)
{ {
sector_t *sector = spr->mobj->subsector->sector; sector_t *sector = spr->mobj->subsector->sector;
UINT8 lightlevel = 255; UINT8 lightlevel = 255;
@ -905,6 +907,10 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
else else
Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false); Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false);
} }
else
{
Surf.FlatColor.rgba = 0xFFFFFFFF;
}
// Look at HWR_ProjectSprite for more // Look at HWR_ProjectSprite for more
{ {
@ -933,19 +939,19 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
// 1. load model+texture if not already loaded // 1. load model+texture if not already loaded
// 2. draw model with correct position, rotation,... // 2. draw model with correct position, rotation,...
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) // Use the player MD2 list if the mobj has a skin and is using the player sprites if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY && !md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound) // Use the player MD2 list if the mobj has a skin and is using the player sprites
{ {
md2 = &md2_playermodels[(skin_t*)spr->mobj->skin-skins]; md2 = &md2_playermodels[(skin_t*)spr->mobj->skin-skins];
md2->skin = (skin_t*)spr->mobj->skin-skins; md2->skin = (skin_t*)spr->mobj->skin-skins;
} }
else else // if we can't find the player md2, use SPR_PLAY's MD2.
md2 = &md2_models[spr->mobj->sprite]; md2 = &md2_models[spr->mobj->sprite];
if (md2->error) if (md2->error)
return; // we already failed loading this before :( return; // we already failed loading this before :(
if (!md2->model) if (!md2->model)
{ {
//CONS_Debug(DBG_RENDER, "Loading MD2... (%s)", sprnames[spr->mobj->sprite]); CONS_Debug(DBG_RENDER, "Loading MD2... (%s, %s)", sprnames[spr->mobj->sprite], md2->filename);
sprintf(filename, "md2/%s", md2->filename); sprintf(filename, "md2/%s", md2->filename);
md2->model = md2_readModel(filename); md2->model = md2_readModel(filename);

View File

@ -1951,10 +1951,11 @@ EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration,
EXPORT void HWRAPI(SetTransform) (FTransform *stransform) EXPORT void HWRAPI(SetTransform) (FTransform *stransform)
{ {
static boolean special_splitscreen; static boolean special_splitscreen;
GLdouble used_fov;
pglLoadIdentity(); pglLoadIdentity();
if (stransform) if (stransform)
{ {
boolean fovx90; used_fov = stransform->fovxangle;
// keep a trace of the transformation for md2 // keep a trace of the transformation for md2
memcpy(&md2_transform, stransform, sizeof (md2_transform)); memcpy(&md2_transform, stransform, sizeof (md2_transform));
@ -1973,32 +1974,27 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform)
pglRotatef(stransform->angley+270.0f, 0.0f, 1.0f, 0.0f); pglRotatef(stransform->angley+270.0f, 0.0f, 1.0f, 0.0f);
pglTranslatef(-stransform->x, -stransform->z, -stransform->y); pglTranslatef(-stransform->x, -stransform->z, -stransform->y);
pglMatrixMode(GL_PROJECTION); special_splitscreen = (stransform->splitscreen == 1);
pglLoadIdentity();
fovx90 = stransform->fovxangle > 0.0f && fabsf(stransform->fovxangle - 90.0f) < 0.5f;
special_splitscreen = (stransform->splitscreen == 1 && fovx90);
if (special_splitscreen)
GLPerspective(53.13f, 2*ASPECT_RATIO); // 53.13 = 2*atan(0.5)
else
GLPerspective(stransform->fovxangle, ASPECT_RATIO);
pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer)
pglMatrixMode(GL_MODELVIEW);
} }
else else
{ {
//Hurdler: is "fov" correct?
used_fov = fov;
pglScalef(1.0f, 1.0f, -1.0f); pglScalef(1.0f, 1.0f, -1.0f);
pglMatrixMode(GL_PROJECTION);
pglLoadIdentity();
if (special_splitscreen)
GLPerspective(53.13f, 2*ASPECT_RATIO); // 53.13 = 2*atan(0.5)
else
//Hurdler: is "fov" correct?
GLPerspective(fov, ASPECT_RATIO);
pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer)
pglMatrixMode(GL_MODELVIEW);
} }
pglMatrixMode(GL_PROJECTION);
pglLoadIdentity();
if (special_splitscreen)
{
used_fov = atan(tan(used_fov*M_PIl/360.0l)*0.8l)*360/M_PIl;
GLPerspective(used_fov, 2*ASPECT_RATIO);
}
else
GLPerspective(used_fov, ASPECT_RATIO);
pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer)
pglMatrixMode(GL_MODELVIEW);
pglGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer) pglGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer)
} }

View File

@ -74,6 +74,14 @@ patch_t *nightsnum[10]; // 0-9
patch_t *lt_font[LT_FONTSIZE]; patch_t *lt_font[LT_FONTSIZE];
patch_t *cred_font[CRED_FONTSIZE]; patch_t *cred_font[CRED_FONTSIZE];
// ping font
// Note: I'd like to adress that at this point we might *REALLY* want to work towards a common drawString function that can take any font we want because this is really turning into a MESS. :V -Lat'
patch_t *pingnum[10];
patch_t *pinggfx[5]; // small ping graphic
patch_t *framecounter;
patch_t *frameslash; // framerate stuff. Used in screen.c
static player_t *plr; static player_t *plr;
boolean chat_on; // entering a chat message? boolean chat_on; // entering a chat message?
static char w_chat[HU_MAXMSGLEN]; static char w_chat[HU_MAXMSGLEN];
@ -263,6 +271,8 @@ void HU_LoadGraphics(void)
tallnum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); tallnum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
sprintf(buffer, "NGTNUM%d", i); sprintf(buffer, "NGTNUM%d", i);
nightsnum[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); nightsnum[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX);
sprintf(buffer, "PINGN%d", i);
pingnum[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX);
} }
// minus for negative tallnums // minus for negative tallnums
@ -295,6 +305,17 @@ void HU_LoadGraphics(void)
tinyemeraldpics[6] = W_CachePatchName("TEMER7", PU_HUDGFX); tinyemeraldpics[6] = W_CachePatchName("TEMER7", PU_HUDGFX);
songcreditbg = W_CachePatchName("K_SONGCR", PU_HUDGFX); songcreditbg = W_CachePatchName("K_SONGCR", PU_HUDGFX);
// cache ping gfx:
for (i = 0; i < 5; i++)
{
sprintf(buffer, "PINGGFX%d", i+1);
pinggfx[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
}
// fps stuff
framecounter = W_CachePatchName("FRAMER", PU_HUDGFX);
frameslash = W_CachePatchName("FRAMESL", PU_HUDGFX);;
} }
// Initialise Heads up // Initialise Heads up
@ -757,44 +778,139 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
} }
} }
else else
{ {
const UINT8 color = players[playernum].skincolor; const UINT8 color = players[playernum].skincolor;
cstart = "\x83"; cstart = "\x83";
if (color <= SKINCOLOR_SILVER || color == SKINCOLOR_SLATE) switch (color)
cstart = "\x80"; // white {
else if (color <= SKINCOLOR_BLACK || color == SKINCOLOR_JET) case SKINCOLOR_WHITE:
cstart = "\x86"; // V_GRAYMAP case SKINCOLOR_SILVER:
else if (color <= SKINCOLOR_LEATHER) case SKINCOLOR_SLATE:
cstart = "\x8e"; // V_BROWNMAP cstart = "\x80"; // White
else if (color <= SKINCOLOR_ROSE || color == SKINCOLOR_LILAC) break;
cstart = "\x8d"; // V_PINKMAP case SKINCOLOR_GREY:
else if (color <= SKINCOLOR_KETCHUP) case SKINCOLOR_NICKEL:
cstart = "\x85"; // V_REDMAP case SKINCOLOR_BLACK:
else if (color <= SKINCOLOR_TANGERINE) case SKINCOLOR_JET:
cstart = "\x87"; // V_ORANGEMAP cstart = "\x86"; // V_GRAYMAP
else if (color <= SKINCOLOR_CARAMEL) break;
cstart = "\x8f"; // V_PEACHMAP case SKINCOLOR_SEPIA:
else if (color <= SKINCOLOR_BRONZE) case SKINCOLOR_BEIGE:
cstart = "\x8A"; // V_GOLDMAP case SKINCOLOR_BROWN:
else if (color <= SKINCOLOR_OLIVE) case SKINCOLOR_LEATHER:
cstart = "\x82"; // V_YELLOWMAP case SKINCOLOR_RUST:
else if (color <= SKINCOLOR_PISTACHIO) cstart = "\x8e"; // V_BROWNMAP
cstart = "\x8b"; // V_TEAMAP break;
else if (color <= SKINCOLOR_DREAM || color == SKINCOLOR_LIME) case SKINCOLOR_FAIRY:
cstart = "\x83"; // V_GREENMAP case SKINCOLOR_SALMON:
else if (color <= SKINCOLOR_NAVY || color == SKINCOLOR_SAPPHIRE) case SKINCOLOR_PINK:
cstart = "\x88"; // V_SKYMAP case SKINCOLOR_ROSE:
else if (color <= SKINCOLOR_STEEL) case SKINCOLOR_BRICK:
cstart = "\x8c"; // V_STEELMAP case SKINCOLOR_BUBBLEGUM:
else if (color <= SKINCOLOR_BLUEBERRY) case SKINCOLOR_LILAC:
cstart = "\x84"; // V_BLUEMAP cstart = "\x8d"; // V_PINKMAP
else if (color == SKINCOLOR_PURPLE) break;
cstart = "\x81"; // V_PURPLEMAP case SKINCOLOR_RUBY:
else //if (color <= SKINCOLOR_POMEGRANATE) case SKINCOLOR_RASPBERRY:
cstart = "\x89"; // V_LAVENDERMAP case SKINCOLOR_CHERRY:
} case SKINCOLOR_RED:
case SKINCOLOR_CRIMSON:
case SKINCOLOR_MAROON:
case SKINCOLOR_FLAME:
case SKINCOLOR_SCARLET:
case SKINCOLOR_KETCHUP:
cstart = "\x85"; // V_REDMAP
break;
case SKINCOLOR_DAWN:
case SKINCOLOR_SUNSET:
case SKINCOLOR_CREAMSICLE:
case SKINCOLOR_ORANGE:
case SKINCOLOR_PUMPKIN:
case SKINCOLOR_ROSEWOOD:
case SKINCOLOR_BURGUNDY:
case SKINCOLOR_TANGERINE:
cstart = "\x87"; // V_ORANGEMAP
break;
case SKINCOLOR_PEACH:
case SKINCOLOR_CARAMEL:
case SKINCOLOR_CREAM:
cstart = "\x8f"; // V_PEACHMAP
break;
case SKINCOLOR_GOLD:
case SKINCOLOR_ROYAL:
case SKINCOLOR_BRONZE:
case SKINCOLOR_COPPER:
cstart = "\x8A"; // V_GOLDMAP
break;
case SKINCOLOR_POPCORN:
case SKINCOLOR_YELLOW:
case SKINCOLOR_MUSTARD:
case SKINCOLOR_OLIVE:
cstart = "\x82"; // V_YELLOWMAP
break;
case SKINCOLOR_VOMIT:
case SKINCOLOR_GARDEN:
case SKINCOLOR_TEA:
case SKINCOLOR_PISTACHIO:
cstart = "\x8b"; // V_TEAMAP
break;
case SKINCOLOR_LIME:
case SKINCOLOR_HANDHELD:
case SKINCOLOR_MOSS:
case SKINCOLOR_CAMOUFLAGE:
case SKINCOLOR_ROBOHOOD:
case SKINCOLOR_MINT:
case SKINCOLOR_GREEN:
case SKINCOLOR_PINETREE:
case SKINCOLOR_EMERALD:
case SKINCOLOR_SWAMP:
case SKINCOLOR_DREAM:
case SKINCOLOR_PLAGUE:
case SKINCOLOR_ALGAE:
cstart = "\x83"; // V_GREENMAP
break;
case SKINCOLOR_CARIBBEAN:
case SKINCOLOR_AQUA:
case SKINCOLOR_TEAL:
case SKINCOLOR_CYAN:
case SKINCOLOR_JAWZ:
case SKINCOLOR_CERULEAN:
case SKINCOLOR_NAVY:
case SKINCOLOR_SAPPHIRE:
cstart = "\x88"; // V_SKYMAP
break;
case SKINCOLOR_PLATINUM:
case SKINCOLOR_STEEL:
cstart = "\x8c"; // V_STEELMAP
break;
case SKINCOLOR_PERIWINKLE:
case SKINCOLOR_BLUE:
case SKINCOLOR_BLUEBERRY:
case SKINCOLOR_NOVA:
cstart = "\x84"; // V_BLUEMAP
break;
case SKINCOLOR_ULTRAVIOLET:
case SKINCOLOR_PURPLE:
case SKINCOLOR_FUCHSIA:
cstart = "\x81"; // V_PURPLEMAP
break;
case SKINCOLOR_PASTEL:
case SKINCOLOR_MOONSLAM:
case SKINCOLOR_DUSK:
case SKINCOLOR_TOXIC:
case SKINCOLOR_MAUVE:
case SKINCOLOR_LAVENDER:
case SKINCOLOR_BYZANTIUM:
case SKINCOLOR_POMEGRANATE:
cstart = "\x89"; // V_LAVENDERMAP
break;
default:
break;
}
}
prefix = cstart; prefix = cstart;
// Give admins and remote admins their symbols. // Give admins and remote admins their symbols.
@ -1109,8 +1225,6 @@ static INT16 typelines = 1; // number of drawfill lines we need when drawing the
// //
boolean HU_Responder(event_t *ev) boolean HU_Responder(event_t *ev)
{ {
INT32 c=0;
if (ev->type != ev_keydown) if (ev->type != ev_keydown)
return false; return false;
@ -1136,18 +1250,6 @@ boolean HU_Responder(event_t *ev)
return false; return false;
} }
c = (INT32)ev->data1;
// capslock (now handled outside of chat on so that it works everytime......)
if (c && c == KEY_CAPSLOCK) // it's a toggle.
{
if (capslock)
capslock = false;
else
capslock = true;
return true;
}
#ifndef NONET #ifndef NONET
if (!chat_on) if (!chat_on)
{ {
@ -1175,6 +1277,7 @@ boolean HU_Responder(event_t *ev)
} }
else // if chat_on else // if chat_on
{ {
INT32 c = (INT32)ev->data1;
// Ignore modifier keys // Ignore modifier keys
// Note that we do this here so users can still set // Note that we do this here so users can still set
@ -1184,20 +1287,13 @@ boolean HU_Responder(event_t *ev)
|| ev->data1 == KEY_LALT || ev->data1 == KEY_RALT) || ev->data1 == KEY_LALT || ev->data1 == KEY_RALT)
return true; return true;
c = (INT32)ev->data1; // Ignore non-keyboard keys, except when the talk key is bound
if (ev->data1 >= KEY_MOUSE1
&& (ev->data1 != gamecontrol[gc_talkkey][0]
&& ev->data1 != gamecontrol[gc_talkkey][1]))
return false;
// I know this looks very messy but this works. If it ain't broke, don't fix it! c = CON_ShiftChar(c);
// shift LETTERS to uppercase if we have capslock or are holding shift
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
{
if (shiftdown ^ capslock)
c = shiftxform[c];
}
else // if we're holding shift we should still shift non letter symbols
{
if (shiftdown)
c = shiftxform[c];
}
// pasting. pasting is cool. chat is a bit limited, though :( // pasting. pasting is cool. chat is a bit limited, though :(
if (((c == 'v' || c == 'V') && ctrldown) && !CHAT_MUTE) if (((c == 'v' || c == 'V') && ctrldown) && !CHAT_MUTE)
@ -1421,13 +1517,16 @@ static void HU_drawMiniChat(void)
y = chaty - charheight*(msglines+1); y = chaty - charheight*(msglines+1);
#ifdef NETSPLITSCREEN
if (splitscreen) if (splitscreen)
{ {
y -= BASEVIDHEIGHT/2; y -= BASEVIDHEIGHT/2;
if (splitscreen > 1) if (splitscreen > 1)
y += 16; y += 16;
} }
y -= (cv_kartspeedometer.value ? 16 : 0); else
#endif
y -= (cv_kartspeedometer.value ? 16 : 0);
dx = 0; dx = 0;
dy = 0; dy = 0;
@ -1603,9 +1702,9 @@ static void HU_drawChatLog(INT32 offset)
// draw arrows to indicate that we can (or not) scroll. // draw arrows to indicate that we can (or not) scroll.
if (chat_scroll > 0) if (chat_scroll > 0)
V_DrawThinString(chatx-9, ((justscrolledup) ? (chat_topy-1) : (chat_topy)), V_SNAPTOBOTTOM | V_SNAPTOLEFT | highlight, "\x1A"); // up arrow V_DrawCharacter(chatx-9, ((justscrolledup) ? (chat_topy-1) : (chat_topy)), V_SNAPTOBOTTOM | V_SNAPTOLEFT | highlight | '\x1A', false); // up arrow
if (chat_scroll < chat_maxscroll) if (chat_scroll < chat_maxscroll)
V_DrawThinString(chatx-9, chat_bottomy-((justscrolleddown) ? 5 : 6), V_SNAPTOBOTTOM | V_SNAPTOLEFT | highlight, "\x1B"); // down arrow V_DrawCharacter(chatx-9, chat_bottomy-((justscrolleddown) ? 5 : 6), V_SNAPTOBOTTOM | V_SNAPTOLEFT | highlight | '\x1B', false); // down arrow
justscrolleddown = false; justscrolleddown = false;
justscrolledup = false; justscrolledup = false;
@ -2169,6 +2268,7 @@ static void HU_DrawSongCredits(void)
V_DrawRightAlignedThinString(cursongcredit.x, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE|V_SNAPTOLEFT|(cursongcredit.trans<<V_ALPHASHIFT), str); V_DrawRightAlignedThinString(cursongcredit.x, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE|V_SNAPTOLEFT|(cursongcredit.trans<<V_ALPHASHIFT), str);
} }
// Heads up displays drawer, call each frame // Heads up displays drawer, call each frame
// //
void HU_Drawer(void) void HU_Drawer(void)
@ -2360,36 +2460,25 @@ void HU_Erase(void)
// //
// HU_drawPing // HU_drawPing
// //
void HU_drawPing(INT32 x, INT32 y, INT32 ping, boolean notext) void HU_drawPing(INT32 x, INT32 y, UINT32 ping, INT32 flags)
{ {
UINT8 numbars = 1; // how many ping bars do we draw? INT32 gfxnum = 4; // gfx to draw
UINT8 barcolor = 128; // color we use for the bars (green, yellow or red) UINT8 const *colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_SALMON, GTC_CACHE);
SINT8 i = 0;
SINT8 yoffset = 6;
INT32 dx = x+1 - (V_SmallStringWidth(va("%dms", ping), V_ALLOWLOWERCASE)/2);
if (ping < 128) if (ping < 76)
{ gfxnum = 0;
numbars = 3; else if (ping < 137)
barcolor = 184; gfxnum = 1;
}
else if (ping < 256) else if (ping < 256)
{ gfxnum = 2;
numbars = 2; // Apparently ternaries w/ multiple statements don't look good in C so I decided against it. else if (ping < 500)
barcolor = 103; gfxnum = 3;
}
if (!notext || vid.width >= 640) // how sad, we're using a shit resolution. V_DrawScaledPatch(x, y, flags, pinggfx[gfxnum]);
V_DrawSmallString(dx, y+4, V_ALLOWLOWERCASE, va("%dms", ping)); if (servermaxping && ping > servermaxping && hu_tick < 4) // flash ping red if too high
V_DrawPingNum(x, y+9, flags, ping, colormap);
for (i=0; (i<3); i++) // Draw the ping bar else
{ V_DrawPingNum(x, y+9, flags, ping, NULL);
V_DrawFill(x+2 *(i-1), y+yoffset-4, 2, 8-yoffset, 31);
if (i < numbars)
V_DrawFill(x+2 *(i-1), y+yoffset-3, 1, 8-yoffset-1, barcolor);
yoffset -= 2;
}
} }
// //

View File

@ -63,6 +63,7 @@ typedef struct
//------------------------------------ //------------------------------------
#define HU_MAXMSGLEN 224 #define HU_MAXMSGLEN 224
#define CHAT_BUFSIZE 64 // that's enough messages, right? We'll delete the older ones when that gets out of hand. #define CHAT_BUFSIZE 64 // that's enough messages, right? We'll delete the older ones when that gets out of hand.
#define NETSPLITSCREEN // why the hell WOULDN'T we want this?
#ifdef NETSPLITSCREEN #ifdef NETSPLITSCREEN
#define OLDCHAT (cv_consolechat.value == 1 || dedicated || vid.width < 640) #define OLDCHAT (cv_consolechat.value == 1 || dedicated || vid.width < 640)
#else #else
@ -79,7 +80,11 @@ extern boolean chat_on;
extern patch_t *hu_font[HU_FONTSIZE], *kart_font[KART_FONTSIZE], *tny_font[HU_FONTSIZE]; // SRB2kart extern patch_t *hu_font[HU_FONTSIZE], *kart_font[KART_FONTSIZE], *tny_font[HU_FONTSIZE]; // SRB2kart
extern patch_t *tallnum[10]; extern patch_t *tallnum[10];
extern patch_t *pingnum[10];
extern patch_t *pinggfx[5];
extern patch_t *nightsnum[10]; extern patch_t *nightsnum[10];
extern patch_t *framecounter;
extern patch_t *frameslash;
extern patch_t *lt_font[LT_FONTSIZE]; extern patch_t *lt_font[LT_FONTSIZE];
extern patch_t *cred_font[CRED_FONTSIZE]; extern patch_t *cred_font[CRED_FONTSIZE];
extern patch_t *emeraldpics[7]; extern patch_t *emeraldpics[7];
@ -108,7 +113,7 @@ void HU_Drawer(void);
char HU_dequeueChatChar(void); char HU_dequeueChatChar(void);
void HU_Erase(void); void HU_Erase(void);
void HU_clearChatChars(void); void HU_clearChatChars(void);
void HU_drawPing(INT32 x, INT32 y, INT32 ping, boolean notext); // Lat': Ping drawer for scoreboard. void HU_drawPing(INT32 x, INT32 y, UINT32 ping, INT32 flags); // Lat': Ping drawer for scoreboard.
//void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer); //void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer);
//void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer); //void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer);
void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer, INT32 hilicol); void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer, INT32 hilicol);

View File

@ -3140,11 +3140,11 @@ state_t states[NUMSTATES] =
{SPR_NULL, 0, 1, {A_FZBoomSmoke}, 1, 0, S_FZEROBOOM12}, // S_FZEROBOOM11 {SPR_NULL, 0, 1, {A_FZBoomSmoke}, 1, 0, S_FZEROBOOM12}, // S_FZEROBOOM11
{SPR_NULL, 0, 1, {A_FZBoomSmoke}, 0, 0, S_NULL}, // S_FZEROBOOM12 {SPR_NULL, 0, 1, {A_FZBoomSmoke}, 0, 0, S_NULL}, // S_FZEROBOOM12
{SPR_SMOK, FF_TRANS30, 30, {NULL}, 0, 0, S_FZSLOWSMOKE2}, // S_FZSLOWSMOKE1 {SPR_SMOK, 0, 30, {NULL}, 0, 0, S_FZSLOWSMOKE2}, // S_FZSLOWSMOKE1
{SPR_SMOK, FF_TRANS30|1, 30, {NULL}, 0, 0, S_FZSLOWSMOKE3}, // S_FZSLOWSMOKE2 {SPR_SMOK, 1, 30, {NULL}, 0, 0, S_FZSLOWSMOKE3}, // S_FZSLOWSMOKE2
{SPR_SMOK, FF_TRANS30|2, 30, {NULL}, 0, 0, S_FZSLOWSMOKE4}, // S_FZSLOWSMOKE3 {SPR_SMOK, 2, 30, {NULL}, 0, 0, S_FZSLOWSMOKE4}, // S_FZSLOWSMOKE3
{SPR_SMOK, FF_TRANS30|3, 30, {NULL}, 0, 0, S_FZSLOWSMOKE5}, // S_FZSLOWSMOKE4 {SPR_SMOK, 3, 30, {NULL}, 0, 0, S_FZSLOWSMOKE5}, // S_FZSLOWSMOKE4
{SPR_SMOK, FF_TRANS30|4, 30, {NULL}, 0, 0, S_NULL}, // S_FZSLOWSMOKE5 {SPR_SMOK, 4, 30, {NULL}, 0, 0, S_NULL}, // S_FZSLOWSMOKE5
// Various plants // Various plants
{SPR_SBUS, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SONICBUSH {SPR_SBUS, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SONICBUSH
@ -3297,39 +3297,39 @@ state_t states[NUMSTATES] =
{SPR_CNDL, 1|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_BLUEFIRE3}, // S_BLUEFIRE2 {SPR_CNDL, 1|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_BLUEFIRE3}, // S_BLUEFIRE2
{SPR_CNDL, 2|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_BLUEFIRE4}, // S_BLUEFIRE3 {SPR_CNDL, 2|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_BLUEFIRE4}, // S_BLUEFIRE3
{SPR_CNDL, 3|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_BLUEFIRE1}, // S_BLUEFIRE4 {SPR_CNDL, 3|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_BLUEFIRE1}, // S_BLUEFIRE4
{SPR_CNDL, 4|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_GREENFIRE2}, // S_GREENFIRE1 {SPR_CNDL, 4|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_GREENFIRE2}, // S_GREENFIRE1
{SPR_CNDL, 5|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_GREENFIRE3}, // S_GREENFIRE2 {SPR_CNDL, 5|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_GREENFIRE3}, // S_GREENFIRE2
{SPR_CNDL, 6|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_GREENFIRE4}, // S_GREENFIRE3 {SPR_CNDL, 6|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_GREENFIRE4}, // S_GREENFIRE3
{SPR_CNDL, 7|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_GREENFIRE1}, // S_GREENFIRE4 {SPR_CNDL, 7|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_GREENFIRE1}, // S_GREENFIRE4
{SPR_CHES, 0, -1, {NULL}, 0, 0, S_NULL}, // S_REGALCHEST {SPR_CHES, 0, -1, {NULL}, 0, 0, S_NULL}, // S_REGALCHEST
{SPR_CHIM, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_CHIMERASTATUE {SPR_CHIM, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_CHIMERASTATUE
{SPR_DRGN, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_DRAGONSTATUE {SPR_DRGN, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_DRAGONSTATUE
{SPR_LZMN, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LIZARDMANSTATUE {SPR_LZMN, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LIZARDMANSTATUE
{SPR_PGSS, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_PEGASUSSTATUE {SPR_PGSS, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_PEGASUSSTATUE
{SPR_ZTCH, FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_ZELDAFIRE2}, // S_ZELDAFIRE1 {SPR_ZTCH, FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_ZELDAFIRE2}, // S_ZELDAFIRE1
{SPR_ZTCH, 1|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_ZELDAFIRE3}, // S_ZELDAFIRE2 {SPR_ZTCH, 1|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_ZELDAFIRE3}, // S_ZELDAFIRE2
{SPR_ZTCH, 2|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_ZELDAFIRE4}, // S_ZELDAFIRE3 {SPR_ZTCH, 2|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_ZELDAFIRE4}, // S_ZELDAFIRE3
{SPR_ZTCH, 3|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_ZELDAFIRE1}, // S_ZELDAFIRE4 {SPR_ZTCH, 3|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_ZELDAFIRE1}, // S_ZELDAFIRE4
{SPR_DOCH, 0, -1, {NULL}, 0, 0, S_NULL}, // S_GANBARETHING {SPR_DOCH, 0, -1, {NULL}, 0, 0, S_NULL}, // S_GANBARETHING
{SPR_DUCK, 0, -1, {NULL}, 0, 0, S_NULL}, // S_GANBAREDUCK {SPR_DUCK, 0, -1, {NULL}, 0, 0, S_NULL}, // S_GANBAREDUCK
{SPR_GTRE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_GANBARETREE {SPR_GTRE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_GANBARETREE
{SPR_MKMA, 1, 2, {A_Look}, (256<<16)|1, 0, S_MONOIDLE}, // S_MONOIDLE {SPR_MKMA, 1, 2, {A_Look}, (256<<16)|1, 0, S_MONOIDLE}, // S_MONOIDLE
{SPR_MKMA, 0, 3, {A_Chase}, 3, 0, S_MONOCHASE2}, // S_MONOCHASE1 {SPR_MKMA, 0, 3, {A_Chase}, 3, 0, S_MONOCHASE2}, // S_MONOCHASE1
{SPR_MKMA, 1, 3, {A_Chase}, 3, 0, S_MONOCHASE3}, // S_MONOCHASE2 {SPR_MKMA, 1, 3, {A_Chase}, 3, 0, S_MONOCHASE3}, // S_MONOCHASE2
{SPR_MKMA, 2, 3, {A_Chase}, 3, 0, S_MONOCHASE4}, // S_MONOCHASE3 {SPR_MKMA, 2, 3, {A_Chase}, 3, 0, S_MONOCHASE4}, // S_MONOCHASE3
{SPR_MKMA, 3, 3, {A_Chase}, 3, 0, S_MONOCHASE1}, // S_MONOCHASE4 {SPR_MKMA, 3, 3, {A_Chase}, 3, 0, S_MONOCHASE1}, // S_MONOCHASE4
{SPR_MKMP, 0, 24, {A_Pain}, 3, 0, S_MONOIDLE}, // S_MONOPAIN {SPR_MKMP, 0, 24, {A_Pain}, 3, 0, S_MONOIDLE}, // S_MONOPAIN
{SPR_RTCH, FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_REDZELDAFIRE2}, // S_REDZELDAFIRE1 {SPR_RTCH, FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_REDZELDAFIRE2}, // S_REDZELDAFIRE1
{SPR_RTCH, 1|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_REDZELDAFIRE3}, // S_REDZELDAFIRE2 {SPR_RTCH, 1|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_REDZELDAFIRE3}, // S_REDZELDAFIRE2
{SPR_RTCH, 2|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_REDZELDAFIRE4}, // S_REDZELDAFIRE3 {SPR_RTCH, 2|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_REDZELDAFIRE4}, // S_REDZELDAFIRE3
{SPR_RTCH, 3|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_REDZELDAFIRE1}, // S_REDZELDAFIRE4 {SPR_RTCH, 3|FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_REDZELDAFIRE1}, // S_REDZELDAFIRE4
{SPR_BOWL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BOWLINGPIN {SPR_BOWL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BOWLINGPIN
{SPR_BOWH, 0, 4, {A_BunnyHop}, 5, 20, S_BOWLINGHIT2}, // S_BOWLINGHIT1 {SPR_BOWH, 0, 4, {A_BunnyHop}, 5, 20, S_BOWLINGHIT2}, // S_BOWLINGHIT1
{SPR_BOWH, 1, 2, {NULL}, 0, 0, S_BOWLINGHIT3}, // S_BOWLINGHIT2 {SPR_BOWH, 1, 2, {NULL}, 0, 0, S_BOWLINGHIT3}, // S_BOWLINGHIT2
@ -3341,7 +3341,7 @@ state_t states[NUMSTATES] =
{SPR_TOAH, 1, 3, {NULL}, 0, 0, S_TOADHIT3}, // S_TOADHIT2 {SPR_TOAH, 1, 3, {NULL}, 0, 0, S_TOADHIT3}, // S_TOADHIT2
{SPR_TOAH, 2, 3, {NULL}, 0, 0, S_TOADHIT4}, // S_TOADHIT3 {SPR_TOAH, 2, 3, {NULL}, 0, 0, S_TOADHIT4}, // S_TOADHIT3
{SPR_TOAH, 3, 3, {NULL}, 0, 0, S_EBARREL18}, // S_TOADHIT4 {SPR_TOAH, 3, 3, {NULL}, 0, 0, S_EBARREL18}, // S_TOADHIT4
{SPR_BRRL, 0, 1, {A_Look}, (96<<16)|1, 0, S_EBARRELIDLE}, // S_EBARRELIDLE {SPR_BRRL, 0, 1, {A_Look}, (96<<16)|1, 0, S_EBARRELIDLE}, // S_EBARRELIDLE
{SPR_BRRR, 0, 4, {NULL}, 0, 0, S_EBARREL2}, // S_EBARREL1 {SPR_BRRR, 0, 4, {NULL}, 0, 0, S_EBARREL2}, // S_EBARREL1
{SPR_BRRR, 1, 4, {NULL}, 0, 0, S_EBARREL3}, // S_EBARREL2 {SPR_BRRR, 1, 4, {NULL}, 0, 0, S_EBARREL3}, // S_EBARREL2
@ -3361,30 +3361,30 @@ state_t states[NUMSTATES] =
{SPR_BRRR, 15, 4, {NULL}, 0, 0, S_EBARREL17}, // S_EBARREL16 {SPR_BRRR, 15, 4, {NULL}, 0, 0, S_EBARREL17}, // S_EBARREL16
{SPR_BRRR, 16, 4, {NULL}, 0, 0, S_EBARREL18}, // S_EBARREL17 {SPR_BRRR, 16, 4, {NULL}, 0, 0, S_EBARREL18}, // S_EBARREL17
{SPR_BRRR, 16, 0, {A_MineExplode}, MT_MINEEXPLOSION, 0, S_NULL}, // S_EBARREL18 {SPR_BRRR, 16, 0, {A_MineExplode}, MT_MINEEXPLOSION, 0, S_NULL}, // S_EBARREL18
{SPR_HRSE, 0, 230, {A_PlaySeeSound}, 0, 0, S_MERRYHORSE}, // S_MERRYHORSE {SPR_HRSE, 0, 230, {A_PlaySeeSound}, 0, 0, S_MERRYHORSE}, // S_MERRYHORSE
{SPR_BFRT, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BLUEFRUIT {SPR_BFRT, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BLUEFRUIT
{SPR_OFRT, 0, -1, {NULL}, 0, 0, S_NULL}, // S_ORANGEFRUIT {SPR_OFRT, 0, -1, {NULL}, 0, 0, S_NULL}, // S_ORANGEFRUIT
{SPR_RFRT, 0, -1, {NULL}, 0, 0, S_NULL}, // S_REDFRUIT {SPR_RFRT, 0, -1, {NULL}, 0, 0, S_NULL}, // S_REDFRUIT
{SPR_PFRT, 0, -1, {NULL}, 0, 0, S_NULL}, // S_PINKFRUIT {SPR_PFRT, 0, -1, {NULL}, 0, 0, S_NULL}, // S_PINKFRUIT
{SPR_ASPK, 0, 50, {A_PlayAttackSound}, 0, 0, S_ADVENTURESPIKEA2}, // S_ADVENTURESPIKEA1 {SPR_ASPK, 0, 50, {A_PlayAttackSound}, 0, 0, S_ADVENTURESPIKEA2}, // S_ADVENTURESPIKEA1
{SPR_ASPK, 0, 50, {A_BunnyHop}, 20, 0, S_ADVENTURESPIKEA1}, // S_ADVENTURESPIKEA2 {SPR_ASPK, 0, 50, {A_BunnyHop}, 20, 0, S_ADVENTURESPIKEA1}, // S_ADVENTURESPIKEA2
{SPR_ASPK, 0, 50, {A_PlayAttackSound}, 0, 0, S_ADVENTURESPIKEB2}, // S_ADVENTURESPIKEB1 {SPR_ASPK, 0, 50, {A_PlayAttackSound}, 0, 0, S_ADVENTURESPIKEB2}, // S_ADVENTURESPIKEB1
{SPR_ASPK, 0, 35, {A_BunnyHop}, 15, 0, S_ADVENTURESPIKEB1}, // S_ADVENTURESPIKEB2 {SPR_ASPK, 0, 35, {A_BunnyHop}, 15, 0, S_ADVENTURESPIKEB1}, // S_ADVENTURESPIKEB2
{SPR_ASPK, 0, 50, {A_PlayAttackSound}, 0, 0, S_ADVENTURESPIKEC2}, // S_ADVENTURESPIKEC1 {SPR_ASPK, 0, 50, {A_PlayAttackSound}, 0, 0, S_ADVENTURESPIKEC2}, // S_ADVENTURESPIKEC1
{SPR_ASPK, 0, 65, {A_BunnyHop}, 25, 0, S_ADVENTURESPIKEC1}, // S_ADVENTURESPIKEC1 {SPR_ASPK, 0, 65, {A_BunnyHop}, 25, 0, S_ADVENTURESPIKEC1}, // S_ADVENTURESPIKEC1
{SPR_HBST, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_BOOSTPROMPT2}, // S_BOOSTPROMPT1 {SPR_HBST, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_BOOSTPROMPT2}, // S_BOOSTPROMPT1
{SPR_HBST, 1|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_BOOSTPROMPT1}, // S_BOOSTPROMPT2 {SPR_HBST, 1|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_BOOSTPROMPT1}, // S_BOOSTPROMPT2
{SPR_HBSF, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_BOOSTOFF2}, // S_BOOSTOFF1 {SPR_HBSF, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_BOOSTOFF2}, // S_BOOSTOFF1
{SPR_HBSF, 1|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_BOOSTOFF1}, // S_BOOSTOFF2 {SPR_HBSF, 1|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_BOOSTOFF1}, // S_BOOSTOFF2
{SPR_HBSO, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_BOOSTON2}, // S_BOOSTON1 {SPR_HBSO, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_BOOSTON2}, // S_BOOSTON1
{SPR_HBSO, 1|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_BOOSTON1}, // S_BOOSTON2 {SPR_HBSO, 1|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_BOOSTON1}, // S_BOOSTON2
{SPR_WBLZ, 0, -1, {NULL}, 0, 0, S_NULL}, // S_LIZARDMAN {SPR_WBLZ, 0, -1, {NULL}, 0, 0, S_NULL}, // S_LIZARDMAN
{SPR_WBLN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_LIONMAN {SPR_WBLN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_LIONMAN
@ -3394,6 +3394,13 @@ state_t states[NUMSTATES] =
{SPR_FWRK, 3|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_KARMAFIREWORK1}, // S_KARMAFIREWORK4 {SPR_FWRK, 3|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_KARMAFIREWORK1}, // S_KARMAFIREWORK4
{SPR_FWRK, 4|FF_FULLBRIGHT, TICRATE, {NULL}, 0, 0, S_NULL}, // S_KARMAFIREWORKTRAIL {SPR_FWRK, 4|FF_FULLBRIGHT, TICRATE, {NULL}, 0, 0, S_NULL}, // S_KARMAFIREWORKTRAIL
// Opaque smoke
{SPR_SMOK, 0, 4, {NULL}, 0, 0, S_OPAQUESMOKE2}, // S_OPAQUESMOKE1
{SPR_SMOK, 1, 5, {NULL}, 0, 0, S_OPAQUESMOKE3}, // S_OPAQUESMOKE2
{SPR_SMOK, 2, 6, {NULL}, 0, 0, S_OPAQUESMOKE4}, // S_OPAQUESMOKE3
{SPR_SMOK, 3, 7, {NULL}, 0, 0, S_OPAQUESMOKE5}, // S_OPAQUESMOKE4
{SPR_SMOK, 4, 8, {NULL}, 0, 0, S_NULL}, // S_OPAQUESMOKE5
#ifdef SEENAMES #ifdef SEENAMES
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK
#endif #endif
@ -15018,8 +15025,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate S_NULL, // xdeathstate
sfx_None, // deathsound sfx_None, // deathsound
8, // speed 8, // speed
8*FRACUNIT, // radius 32*FRACUNIT, // radius
8*FRACUNIT, // height 64*FRACUNIT, // height
1, // display offset 1, // display offset
100, // mass 100, // mass
0, // damage 0, // damage
@ -15449,7 +15456,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_ORBINAUT_SHIELDDEAD, // deathstate S_ORBINAUT_SHIELDDEAD, // deathstate
S_NULL, // xdeathstate S_NULL, // xdeathstate
sfx_None, // deathsound sfx_None, // deathsound
10*FRACUNIT, // speed 4*FRACUNIT, // speed
16*FRACUNIT, // radius 16*FRACUNIT, // radius
32*FRACUNIT, // height 32*FRACUNIT, // height
0, // display offset 0, // display offset
@ -15530,7 +15537,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_JAWZ_DEAD1, // deathstate S_JAWZ_DEAD1, // deathstate
S_JAWZ_DEAD2, // xdeathstate S_JAWZ_DEAD2, // xdeathstate
sfx_None, // deathsound sfx_None, // deathsound
10*FRACUNIT, // speed 4*FRACUNIT, // speed
16*FRACUNIT, // radius 16*FRACUNIT, // radius
32*FRACUNIT, // height 32*FRACUNIT, // height
0, // display offset 0, // display offset
@ -15574,7 +15581,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
1, // spawnhealth 1, // spawnhealth
S_NULL, // seestate S_NULL, // seestate
sfx_tossed, // seesound sfx_tossed, // seesound
6*TICRATE, // reactiontime 0, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
S_NULL, // painstate S_NULL, // painstate
192*FRACUNIT, // painchance 192*FRACUNIT, // painchance
@ -15861,7 +15868,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass 100, // mass
1, // damage 1, // damage
sfx_None, // activesound sfx_None, // activesound
MF_BOUNCE|MF_FLOAT|MF_NOCLIPTHING|MF_MISSILE|MF_SHOOTABLE|MF_DONTENCOREMAP, // flags MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_DONTENCOREMAP, // flags
S_NULL // raisestate S_NULL // raisestate
}, },

View File

@ -608,7 +608,7 @@ typedef enum sprite
// Kart Items // Kart Items
SPR_RSHE, // Rocket sneaker SPR_RSHE, // Rocket sneaker
SPR_FITM, // Eggman Monitor SPR_FITM, // Eggman Monitor
SPR_BANA, // Banana Peel SPR_BANA, // Banana Peel
SPR_ORBN, // Orbinaut SPR_ORBN, // Orbinaut
SPR_JAWZ, // Jawz SPR_JAWZ, // Jawz
SPR_SSMN, // SS Mine SPR_SSMN, // SS Mine
@ -3871,7 +3871,7 @@ typedef enum state
S_GARU1, S_GARU1,
S_GARU2, S_GARU2,
S_GARU3, S_GARU3,
S_TGARU0, S_TGARU0,
S_TGARU1, S_TGARU1,
S_TGARU2, S_TGARU2,
S_TGARU3, // Wind attack used by Roaming Shadows on Players. S_TGARU3, // Wind attack used by Roaming Shadows on Players.
@ -4052,6 +4052,12 @@ typedef enum state
S_KARMAFIREWORK4, S_KARMAFIREWORK4,
S_KARMAFIREWORKTRAIL, S_KARMAFIREWORKTRAIL,
S_OPAQUESMOKE1,
S_OPAQUESMOKE2,
S_OPAQUESMOKE3,
S_OPAQUESMOKE4,
S_OPAQUESMOKE5,
#ifdef SEENAMES #ifdef SEENAMES
S_NAMECHECK, S_NAMECHECK,
#endif #endif
@ -4612,14 +4618,14 @@ typedef enum mobj_type
MT_EGGMANITEM_SHIELD, MT_EGGMANITEM_SHIELD,
MT_BANANA, // Banana Stuff MT_BANANA, // Banana Stuff
MT_BANANA_SHIELD, MT_BANANA_SHIELD,
MT_ORBINAUT, // Orbinaut stuff MT_ORBINAUT, // Orbinaut stuff
MT_ORBINAUT_SHIELD, MT_ORBINAUT_SHIELD,
MT_JAWZ, // Jawz stuff MT_JAWZ, // Jawz stuff
MT_JAWZ_DUD, MT_JAWZ_DUD,
MT_JAWZ_SHIELD, MT_JAWZ_SHIELD,
MT_PLAYERRETICULE, // Jawz reticule MT_PLAYERRETICULE, // Jawz reticule

17204
src/k_kart.c

File diff suppressed because it is too large Load Diff

View File

@ -1,74 +1,85 @@
// SONIC ROBO BLAST 2 KART ~ ZarroTsu // SONIC ROBO BLAST 2 KART ~ ZarroTsu
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// \file k_kart.h /// \file k_kart.h
/// \brief SRB2kart stuff. /// \brief SRB2kart stuff.
#ifndef __K_KART__ #ifndef __K_KART__
#define __K_KART__ #define __K_KART__
#include "doomdef.h" #include "doomdef.h"
#include "d_player.h" // Need for player_t #include "d_player.h" // Need for player_t
UINT8 colortranslations[MAXSKINCOLORS][16]; #define KART_FULLTURN 800
extern const char *KartColor_Names[MAXSKINCOLORS];
extern const UINT8 KartColor_Opposite[MAXSKINCOLORS*2]; UINT8 colortranslations[MAXTRANSLATIONS][16];
void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor); extern const char *KartColor_Names[MAXSKINCOLORS];
void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color); extern const UINT8 KartColor_Opposite[MAXSKINCOLORS*2];
UINT8 K_GetKartColorByName(const char *name); void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor);
void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color);
void K_RegisterKartStuff(void); UINT8 K_GetKartColorByName(const char *name);
boolean K_IsPlayerLosing(player_t *player); void K_RegisterKartStuff(void);
boolean K_IsPlayerWanted(player_t *player);
void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid); boolean K_IsPlayerLosing(player_t *player);
void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master); boolean K_IsPlayerWanted(player_t *player);
void K_RespawnChecker(player_t *player); void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid);
void K_KartMoveAnimation(player_t *player); void K_FlipFromObject(mobj_t *mo, mobj_t *master);
void K_KartPlayerHUDUpdate(player_t *player); void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master);
void K_KartPlayerThink(player_t *player, ticcmd_t *cmd); void K_RespawnChecker(player_t *player);
void K_KartPlayerAfterThink(player_t *player); void K_KartMoveAnimation(player_t *player);
void K_DoInstashield(player_t *player); void K_KartPlayerHUDUpdate(player_t *player);
void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount); void K_KartPlayerThink(player_t *player, ticcmd_t *cmd);
void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflictor, boolean trapitem); void K_KartPlayerAfterThink(player_t *player);
void K_SquishPlayer(player_t *player, mobj_t *source, mobj_t *inflictor); void K_DoInstashield(player_t *player);
void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor); void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount);
void K_StealBumper(player_t *player, player_t *victim, boolean force); void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflictor, boolean trapitem);
void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle, boolean spawncenter, boolean ghostit, mobj_t *source); void K_SquishPlayer(player_t *player, mobj_t *source, mobj_t *inflictor);
void K_SpawnMineExplosion(mobj_t *source, UINT8 color); void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor);
void K_SpawnBoostTrail(player_t *player); void K_StealBumper(player_t *player, player_t *victim, boolean force);
void K_SpawnSparkleTrail(mobj_t *mo); void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle, boolean spawncenter, boolean ghostit, mobj_t *source);
void K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent); void K_SpawnMineExplosion(mobj_t *source, UINT8 color);
void K_DriftDustHandling(mobj_t *spawner); void K_SpawnBoostTrail(player_t *player);
void K_DoSneaker(player_t *player, INT32 type); void K_SpawnSparkleTrail(mobj_t *mo);
void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound); void K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent);
void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source); void K_DriftDustHandling(mobj_t *spawner);
void K_UpdateHnextList(player_t *player, boolean clean); void K_PuntMine(mobj_t *mine, mobj_t *punter);
void K_DropHnextList(player_t *player); void K_DoSneaker(player_t *player, INT32 type);
void K_RepairOrbitChain(mobj_t *orbit); void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound);
player_t *K_FindJawzTarget(mobj_t *actor, player_t *source); void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source);
boolean K_CheckPlayersRespawnColliding(INT32 playernum, fixed_t x, fixed_t y); void K_UpdateHnextList(player_t *player, boolean clean);
INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue); void K_DropHnextList(player_t *player);
INT32 K_GetKartDriftSparkValue(player_t *player); void K_RepairOrbitChain(mobj_t *orbit);
void K_KartUpdatePosition(player_t *player); player_t *K_FindJawzTarget(mobj_t *actor, player_t *source);
void K_DropItems(player_t *player); boolean K_CheckPlayersRespawnColliding(INT32 playernum, fixed_t x, fixed_t y);
void K_StripItems(player_t *player); INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue);
void K_StripOther(player_t *player); INT32 K_GetKartDriftSparkValue(player_t *player);
void K_MomentumToFacing(player_t *player); void K_KartUpdatePosition(player_t *player);
fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower); void K_DropItems(player_t *player);
fixed_t K_GetKartAccel(player_t *player); void K_StripItems(player_t *player);
UINT16 K_GetKartFlashing(player_t *player); void K_StripOther(player_t *player);
fixed_t K_3dKartMovement(player_t *player, boolean onground, fixed_t forwardmove); void K_MomentumToFacing(player_t *player);
void K_MoveKartPlayer(player_t *player, boolean onground); fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower);
void K_CalculateBattleWanted(void); fixed_t K_GetKartAccel(player_t *player);
void K_CheckBumpers(void); UINT16 K_GetKartFlashing(player_t *player);
void K_CheckSpectateStatus(void); fixed_t K_3dKartMovement(player_t *player, boolean onground, fixed_t forwardmove);
void K_MoveKartPlayer(player_t *player, boolean onground);
const char *K_GetItemPatch(UINT8 item, boolean tiny); void K_CalculateBattleWanted(void);
INT32 K_calcSplitFlags(INT32 snapflags); void K_CheckBumpers(void);
void K_LoadKartHUDGraphics(void); void K_CheckSpectateStatus(void);
void K_drawKartHUD(void);
void K_drawKartFreePlay(UINT32 flashtime); // sound stuff for lua
void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UINT8 mode); void K_PlayAttackTaunt(mobj_t *source);
void K_PlayBoostTaunt(mobj_t *source);
// ========================================================================= void K_PlayOvertakeSound(mobj_t *source);
#endif // __K_KART__ void K_PlayHitEmSound(mobj_t *source);
void K_PlayPowerGloatSound(mobj_t *source);
const char *K_GetItemPatch(UINT8 item, boolean tiny);
INT32 K_calcSplitFlags(INT32 snapflags);
void K_LoadKartHUDGraphics(void);
void K_drawKartHUD(void);
void K_drawKartFreePlay(UINT32 flashtime);
void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UINT8 mode);
// =========================================================================
#endif // __K_KART__

View File

@ -31,9 +31,10 @@
#include "lua_script.h" #include "lua_script.h"
#include "lua_libs.h" #include "lua_libs.h"
#include "lua_hud.h" // hud_running errors #include "lua_hud.h" // hud_running errors
#include "lua_hook.h" // hook_cmd_running
#define NOHUD if (hud_running) return luaL_error(L, "HUD rendering code should not call this function!"); #define NOHUD if (hud_running) return luaL_error(L, "HUD rendering code should not call this function!"); else if (hook_cmd_running) return luaL_error(L, "CMD Building code should not call this function!");
// Yes technically cmd hook isn't a hud but whatever, this avoids having 2 defines for virtually the same thing.
boolean luaL_checkboolean(lua_State *L, int narg) { boolean luaL_checkboolean(lua_State *L, int narg) {
luaL_checktype(L, narg, LUA_TBOOLEAN); luaL_checktype(L, narg, LUA_TBOOLEAN);
@ -631,19 +632,6 @@ static int lib_pCheckSolidLava(lua_State *L)
return 1; return 1;
} }
static int lib_pCanRunOnWater(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
//HUDSAFE
if (!player)
return LUA_ErrInvalid(L, "player_t");
if (!rover)
return LUA_ErrInvalid(L, "ffloor_t");
lua_pushboolean(L, P_CanRunOnWater(player, rover));
return 1;
}
static int lib_pSpawnShadowMobj(lua_State *L) static int lib_pSpawnShadowMobj(lua_State *L)
{ {
mobj_t *caster = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *caster = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
@ -677,16 +665,6 @@ static int lib_pGetPlayerSpinHeight(lua_State *L)
return 1; return 1;
} }
static int lib_pGetPlayerControlDirection(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
//HUDSAFE
if (!player)
return LUA_ErrInvalid(L, "player_t");
lua_pushinteger(L, P_GetPlayerControlDirection(player));
return 1;
}
static int lib_pAddPlayerScore(lua_State *L) static int lib_pAddPlayerScore(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
@ -2141,6 +2119,72 @@ static int lib_gTicsToMilliseconds(lua_State *L)
// K_KART // K_KART
//////////// ////////////
// Seriously, why weren't those exposed before?
static int lib_kAttackSound(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
if (!mobj->player)
return luaL_error(L, "K_PlayAttackTaunt: mobj_t isn't a player object."); //Nothing bad would happen if we let it run the func, but telling why it ain't doing anything is helpful.
K_PlayAttackTaunt(mobj);
return 0;
}
static int lib_kBoostSound(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
if (!mobj->player)
return luaL_error(L, "K_PlayBoostTaunt: mobj_t isn't a player object."); //Nothing bad would happen if we let it run the func, but telling why it ain't doing anything is helpful.
K_PlayBoostTaunt(mobj);
return 0;
}
static int lib_kOvertakeSound(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
if (!mobj->player)
return luaL_error(L, "K_PlayOvertakeSound: mobj_t isn't a player object."); //Nothing bad would happen if we let it run the func, but telling why it ain't doing anything is helpful.
K_PlayOvertakeSound(mobj);
return 0;
}
static int lib_kHitEmSound(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
if (!mobj->player)
return luaL_error(L, "K_PlayHitEmSound: mobj_t isn't a player object."); //Nothing bad would happen if we let it run the func, but telling why it ain't doing anything is helpful.
K_PlayHitEmSound(mobj);
return 0;
}
static int lib_kGloatSound(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
if (!mobj->player)
return luaL_error(L, "K_PlayPowerGloatSound: mobj_t isn't a player object."); //Nothing bad would happen if we let it run the func, but telling why it ain't doing anything is helpful.
K_PlayPowerGloatSound(mobj);
return 0;
}
static int lib_kLossSound(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); // let's require a mobj for consistency with the other functions
sfxenum_t sfx_id;
NOHUD
if (!mobj->player)
return luaL_error(L, "K_PlayLossSound: mobj_t isn't a player object.");
sfx_id = ((skin_t *)mobj->skin)->soundsid[S_sfx[sfx_klose].skinsound];
S_StartSound(mobj, sfx_id);
return 0;
}
// Note: Pain, Death and Victory are already exposed.
static int lib_kGetKartColorByName(lua_State *L) static int lib_kGetKartColorByName(lua_State *L)
{ {
const char *name = luaL_checkstring(L, 1); const char *name = luaL_checkstring(L, 1);
@ -2570,13 +2614,11 @@ static luaL_Reg lib[] = {
{"P_InsideANonSolidFFloor",lib_pInsideANonSolidFFloor}, {"P_InsideANonSolidFFloor",lib_pInsideANonSolidFFloor},
{"P_CheckDeathPitCollide",lib_pCheckDeathPitCollide}, {"P_CheckDeathPitCollide",lib_pCheckDeathPitCollide},
{"P_CheckSolidLava",lib_pCheckSolidLava}, {"P_CheckSolidLava",lib_pCheckSolidLava},
{"P_CanRunOnWater",lib_pCanRunOnWater},
{"P_SpawnShadowMobj",lib_pSpawnShadowMobj}, {"P_SpawnShadowMobj",lib_pSpawnShadowMobj},
// p_user // p_user
{"P_GetPlayerHeight",lib_pGetPlayerHeight}, {"P_GetPlayerHeight",lib_pGetPlayerHeight},
{"P_GetPlayerSpinHeight",lib_pGetPlayerSpinHeight}, {"P_GetPlayerSpinHeight",lib_pGetPlayerSpinHeight},
{"P_GetPlayerControlDirection",lib_pGetPlayerControlDirection},
{"P_AddPlayerScore",lib_pAddPlayerScore}, {"P_AddPlayerScore",lib_pAddPlayerScore},
{"P_PlayerInPain",lib_pPlayerInPain}, {"P_PlayerInPain",lib_pPlayerInPain},
{"P_DoPlayerPain",lib_pDoPlayerPain}, {"P_DoPlayerPain",lib_pDoPlayerPain},
@ -2708,6 +2750,12 @@ static luaL_Reg lib[] = {
{"G_TicsToMilliseconds",lib_gTicsToMilliseconds}, {"G_TicsToMilliseconds",lib_gTicsToMilliseconds},
// k_kart // k_kart
{"K_PlayAttackTaunt", lib_kAttackSound},
{"K_PlayBoostTaunt", lib_kBoostSound},
{"K_PlayPowerGloatSund", lib_kGloatSound},
{"K_PlayOvertakeSound", lib_kOvertakeSound},
{"K_PlayLossSound", lib_kLossSound},
{"K_PlayHitEmSound", lib_kHitEmSound},
{"K_GetKartColorByName",lib_kGetKartColorByName}, {"K_GetKartColorByName",lib_kGetKartColorByName},
{"K_IsPlayerLosing",lib_kIsPlayerLosing}, {"K_IsPlayerLosing",lib_kIsPlayerLosing},
{"K_IsPlayerWanted",lib_kIsPlayerWanted}, {"K_IsPlayerWanted",lib_kIsPlayerWanted},

View File

@ -50,11 +50,14 @@ enum hook {
hook_PlayerSpin, //SRB2KART hook_PlayerSpin, //SRB2KART
hook_PlayerExplode, //SRB2KART hook_PlayerExplode, //SRB2KART
hook_PlayerSquish, //SRB2KART hook_PlayerSquish, //SRB2KART
hook_PlayerCmd, //SRB2KART
hook_MAX // last hook hook_MAX // last hook
}; };
extern const char *const hookNames[]; extern const char *const hookNames[];
extern boolean hook_cmd_running; // This is used by PlayerCmd and lua_playerlib to prevent anything from being wirtten to player while we run PlayerCmd.
void LUAh_MapChange(INT16 mapnumber); // Hook for map change (before load) void LUAh_MapChange(INT16 mapnumber); // Hook for map change (before load)
void LUAh_MapLoad(void); // Hook for map load void LUAh_MapLoad(void); // Hook for map load
void LUAh_PlayerJoin(int playernum); // Hook for Got_AddPlayer void LUAh_PlayerJoin(int playernum); // Hook for Got_AddPlayer
@ -93,4 +96,7 @@ UINT8 LUAh_ShouldSquish(player_t *player, mobj_t *inflictor, mobj_t *source); //
boolean LUAh_PlayerSpin(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_SpinPlayer. Allows Lua to execute code and/or overwrite its behavior. boolean LUAh_PlayerSpin(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_SpinPlayer. Allows Lua to execute code and/or overwrite its behavior.
boolean LUAh_PlayerExplode(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_ExplodePlayer. Allows Lua to execute code and/or overwrite its behavior. boolean LUAh_PlayerExplode(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_ExplodePlayer. Allows Lua to execute code and/or overwrite its behavior.
boolean LUAh_PlayerSquish(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_SquishPlayer. Allows Lua to execute code and/or overwrite its behavior. boolean LUAh_PlayerSquish(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_SquishPlayer. Allows Lua to execute code and/or overwrite its behavior.
boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Allows to write to player cmd before the game does anything with them.
#endif #endif

View File

@ -61,6 +61,7 @@ const char *const hookNames[hook_MAX+1] = {
"PlayerSpin", "PlayerSpin",
"PlayerExplode", "PlayerExplode",
"PlayerSquish", "PlayerSquish",
"PlayerCmd",
NULL NULL
}; };
@ -877,6 +878,47 @@ boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd)
return hooked; return hooked;
} }
// Hook for G_BuildTicCmd
boolean hook_cmd_running = false;
boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd)
{
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_PlayerCmd/8] & (1<<(hook_PlayerCmd%8))))
return false;
lua_settop(gL, 0);
hook_cmd_running = true;
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_PlayerCmd)
{
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, player, META_PLAYER);
LUA_PushUserdata(gL, cmd, META_TICCMD);
}
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);
}
hook_cmd_running = false;
lua_settop(gL, 0);
return hooked;
}
// Hook for B_BuildTailsTiccmd by skin name // Hook for B_BuildTailsTiccmd by skin name
boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
{ {

View File

@ -20,8 +20,10 @@ enum hud {
hud_item, hud_item,
hud_position, hud_position,
hud_minirankings, // Rankings to the left hud_minirankings, // Rankings to the left
hud_battlebumpers, // mini rankings battle bumpers.
hud_wanted, hud_wanted,
hud_speedometer, hud_speedometer,
hud_freeplay,
hud_rankings, // Tab rankings hud_rankings, // Tab rankings
hud_MAX hud_MAX

View File

@ -34,6 +34,8 @@ static UINT8 hud_enabled[(hud_MAX/8)+1];
static UINT8 hudAvailable; // hud hooks field static UINT8 hudAvailable; // hud hooks field
static UINT8 camnum = 1;
// must match enum hud in lua_hud.h // must match enum hud in lua_hud.h
static const char *const hud_disable_options[] = { static const char *const hud_disable_options[] = {
"stagetitle", "stagetitle",
@ -45,8 +47,10 @@ static const char *const hud_disable_options[] = {
"item", "item",
"position", "position",
"minirankings", // Gametype rankings to the left "minirankings", // Gametype rankings to the left
"battlerankingsbumpers", // bumper drawer for battle. Useful if you want to make a custom battle gamemode without bumpers being involved.
"wanted", "wanted",
"speedometer", "speedometer",
"freeplay",
"rankings", "rankings",
NULL}; NULL};
@ -132,7 +136,8 @@ enum cameraf {
camera_height, camera_height,
camera_momx, camera_momx,
camera_momy, camera_momy,
camera_momz camera_momz,
camera_pnum
}; };
@ -151,6 +156,7 @@ static const char *const camera_opt[] = {
"momx", "momx",
"momy", "momy",
"momz", "momz",
"pnum",
NULL}; NULL};
static int lib_getHudInfo(lua_State *L) static int lib_getHudInfo(lua_State *L)
@ -306,6 +312,9 @@ static int camera_get(lua_State *L)
case camera_momz: case camera_momz:
lua_pushinteger(L, cam->momz); lua_pushinteger(L, cam->momz);
break; break;
case camera_pnum:
lua_pushinteger(L, camnum);
break;
} }
return 1; return 1;
} }
@ -401,6 +410,24 @@ static int libd_drawPaddedNum(lua_State *L)
return 0; return 0;
} }
static int libd_drawPingNum(lua_State *L)
{
INT32 x, y, flags, num;
const UINT8 *colormap = NULL;
HUDONLY
x = luaL_checkinteger(L, 1);
y = luaL_checkinteger(L, 2);
num = luaL_checkinteger(L, 3);
flags = luaL_optinteger(L, 4, 0);
flags &= ~V_PARAMMASK; // Don't let crashes happen.
if (!lua_isnoneornil(L, 5))
colormap = *((UINT8 **)luaL_checkudata(L, 5, META_COLORMAP));
V_DrawPingNum(x, y, flags, num, colormap);
return 0;
}
static int libd_drawFill(lua_State *L) static int libd_drawFill(lua_State *L)
{ {
INT32 x = luaL_optinteger(L, 1, 0); INT32 x = luaL_optinteger(L, 1, 0);
@ -482,6 +509,20 @@ static int libd_drawString(lua_State *L)
return 0; return 0;
} }
static int libd_drawKartString(lua_State *L)
{
fixed_t x = luaL_checkinteger(L, 1);
fixed_t y = luaL_checkinteger(L, 2);
const char *str = luaL_checkstring(L, 3);
INT32 flags = luaL_optinteger(L, 4, V_ALLOWLOWERCASE);
flags &= ~V_PARAMMASK; // Don't let crashes happen.
HUDONLY
V_DrawKartString(x, y, flags, str);
return 0;
}
static int libd_stringWidth(lua_State *L) static int libd_stringWidth(lua_State *L)
{ {
const char *str = luaL_checkstring(L, 1); const char *str = luaL_checkstring(L, 1);
@ -590,9 +631,11 @@ static luaL_Reg lib_draw[] = {
{"drawScaled", libd_drawScaled}, {"drawScaled", libd_drawScaled},
{"drawNum", libd_drawNum}, {"drawNum", libd_drawNum},
{"drawPaddedNum", libd_drawPaddedNum}, {"drawPaddedNum", libd_drawPaddedNum},
{"drawPingNum", libd_drawPingNum},
{"drawFill", libd_drawFill}, {"drawFill", libd_drawFill},
{"fadeScreen", libd_fadeScreen}, {"fadeScreen", libd_fadeScreen},
{"drawString", libd_drawString}, {"drawString", libd_drawString},
{"drawKartString", libd_drawKartString},
{"stringWidth", libd_stringWidth}, {"stringWidth", libd_stringWidth},
{"getColormap", libd_getColormap}, {"getColormap", libd_getColormap},
{"width", libd_width}, {"width", libd_width},
@ -755,13 +798,25 @@ void LUAh_GameHUD(player_t *stplayr)
LUA_PushUserdata(gL, stplayr, META_PLAYER); LUA_PushUserdata(gL, stplayr, META_PLAYER);
if (splitscreen > 2 && stplayr == &players[fourthdisplayplayer]) if (splitscreen > 2 && stplayr == &players[fourthdisplayplayer])
{
LUA_PushUserdata(gL, &camera4, META_CAMERA); LUA_PushUserdata(gL, &camera4, META_CAMERA);
camnum = 4;
}
else if (splitscreen > 1 && stplayr == &players[thirddisplayplayer]) else if (splitscreen > 1 && stplayr == &players[thirddisplayplayer])
{
LUA_PushUserdata(gL, &camera3, META_CAMERA); LUA_PushUserdata(gL, &camera3, META_CAMERA);
camnum = 3;
}
else if (splitscreen && stplayr == &players[secondarydisplayplayer]) else if (splitscreen && stplayr == &players[secondarydisplayplayer])
{
LUA_PushUserdata(gL, &camera2, META_CAMERA); LUA_PushUserdata(gL, &camera2, META_CAMERA);
camnum = 2;
}
else else
{
LUA_PushUserdata(gL, &camera, META_CAMERA); LUA_PushUserdata(gL, &camera, META_CAMERA);
camnum = 1;
}
lua_pushnil(gL); lua_pushnil(gL);
while (lua_next(gL, -5) != 0) { while (lua_next(gL, -5) != 0) {

View File

@ -22,6 +22,7 @@
#include "lua_script.h" #include "lua_script.h"
#include "lua_libs.h" #include "lua_libs.h"
#include "lua_hud.h" // hud_running errors #include "lua_hud.h" // hud_running errors
#include "lua_hook.h" // cmd errors
boolean LUA_CallAction(const char *action, mobj_t *actor); boolean LUA_CallAction(const char *action, mobj_t *actor);
state_t *astate; state_t *astate;
@ -169,6 +170,8 @@ static int lib_setState(lua_State *L)
if (hud_running) if (hud_running)
return luaL_error(L, "Do not alter states in HUD rendering code!"); return luaL_error(L, "Do not alter states in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter states in BuildCMD code!");
// clear the state to start with, in case of missing table elements // clear the state to start with, in case of missing table elements
memset(state,0,sizeof(state_t)); memset(state,0,sizeof(state_t));
@ -378,6 +381,8 @@ static int state_set(lua_State *L)
if (hud_running) if (hud_running)
return luaL_error(L, "Do not alter states in HUD rendering code!"); return luaL_error(L, "Do not alter states in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter states in BuildCMD code!");
if (fastcmp(field,"sprite")) { if (fastcmp(field,"sprite")) {
value = luaL_checknumber(L, 3); value = luaL_checknumber(L, 3);
@ -466,6 +471,8 @@ static int lib_setMobjInfo(lua_State *L)
if (hud_running) if (hud_running)
return luaL_error(L, "Do not alter mobjinfo in HUD rendering code!"); return luaL_error(L, "Do not alter mobjinfo in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter mobjinfo in BuildCMD code!");
// clear the mobjinfo to start with, in case of missing table elements // clear the mobjinfo to start with, in case of missing table elements
memset(info,0,sizeof(mobjinfo_t)); memset(info,0,sizeof(mobjinfo_t));
@ -633,6 +640,8 @@ static int mobjinfo_set(lua_State *L)
if (hud_running) if (hud_running)
return luaL_error(L, "Do not alter mobjinfo in HUD rendering code!"); return luaL_error(L, "Do not alter mobjinfo in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter mobjinfo in BuildCMD code!");
I_Assert(info != NULL); I_Assert(info != NULL);
I_Assert(info >= mobjinfo); I_Assert(info >= mobjinfo);
@ -755,6 +764,8 @@ static int lib_setSfxInfo(lua_State *L)
if (hud_running) if (hud_running)
return luaL_error(L, "Do not alter sfxinfo in HUD rendering code!"); return luaL_error(L, "Do not alter sfxinfo in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter sfxinfo in BuildCMD code!");
lua_pushnil(L); lua_pushnil(L);
while (lua_next(L, 1)) { while (lua_next(L, 1)) {
@ -830,6 +841,8 @@ static int sfxinfo_set(lua_State *L)
if (hud_running) if (hud_running)
return luaL_error(L, "Do not alter S_sfx in HUD rendering code!"); return luaL_error(L, "Do not alter S_sfx in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter S_sfx in BuildCMD code!");
I_Assert(sfx != NULL); I_Assert(sfx != NULL);

View File

@ -24,6 +24,7 @@
#include "lua_script.h" #include "lua_script.h"
#include "lua_libs.h" #include "lua_libs.h"
#include "lua_hud.h" // hud_running errors #include "lua_hud.h" // hud_running errors
#include "lua_hook.h" // cmd errors
#include "dehacked.h" #include "dehacked.h"
#include "fastcmp.h" #include "fastcmp.h"
@ -484,6 +485,8 @@ static int sector_set(lua_State *L)
if (hud_running) if (hud_running)
return luaL_error(L, "Do not alter sector_t in HUD rendering code!"); return luaL_error(L, "Do not alter sector_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter sector_t in BuildCMD code!");
switch(field) switch(field)
{ {
@ -1174,6 +1177,8 @@ static int ffloor_set(lua_State *L)
if (hud_running) if (hud_running)
return luaL_error(L, "Do not alter ffloor_t in HUD rendering code!"); return luaL_error(L, "Do not alter ffloor_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter ffloor_t in BuildCMD code!");
switch(field) switch(field)
{ {
@ -1303,6 +1308,8 @@ static int slope_set(lua_State *L)
if (hud_running) if (hud_running)
return luaL_error(L, "Do not alter pslope_t in HUD rendering code!"); return luaL_error(L, "Do not alter pslope_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter pslope_t in BuildCMD code!");
switch(field) // todo: reorganize this shit switch(field) // todo: reorganize this shit
{ {

View File

@ -21,6 +21,7 @@
#include "lua_script.h" #include "lua_script.h"
#include "lua_libs.h" #include "lua_libs.h"
#include "lua_hud.h" // hud_running errors #include "lua_hud.h" // hud_running errors
#include "lua_hook.h" // cmd errors
static const char *const array_opt[] ={"iterate",NULL}; static const char *const array_opt[] ={"iterate",NULL};
@ -391,6 +392,9 @@ static int mobj_set(lua_State *L)
if (hud_running) if (hud_running)
return luaL_error(L, "Do not alter mobj_t in HUD rendering code!"); return luaL_error(L, "Do not alter mobj_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter mobj_t in BuildCMD code!");
switch(field) switch(field)
{ {
case mobj_valid: case mobj_valid:
@ -756,6 +760,8 @@ static int mapthing_set(lua_State *L)
if (hud_running) if (hud_running)
return luaL_error(L, "Do not alter mapthing_t in HUD rendering code!"); return luaL_error(L, "Do not alter mapthing_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter mapthing_t in BuildCMD code!");
if(fastcmp(field,"x")) if(fastcmp(field,"x"))
mt->x = (INT16)luaL_checkinteger(L, 3); mt->x = (INT16)luaL_checkinteger(L, 3);

View File

@ -21,6 +21,7 @@
#include "lua_script.h" #include "lua_script.h"
#include "lua_libs.h" #include "lua_libs.h"
#include "lua_hud.h" // hud_running errors #include "lua_hud.h" // hud_running errors
#include "lua_hook.h" // hook_cmd_running
static int lib_iteratePlayers(lua_State *L) static int lib_iteratePlayers(lua_State *L)
{ {
@ -324,6 +325,8 @@ static int player_get(lua_State *L)
lua_pushinteger(L, plr->bot); lua_pushinteger(L, plr->bot);
else if (fastcmp(field,"jointime")) else if (fastcmp(field,"jointime"))
lua_pushinteger(L, plr->jointime); lua_pushinteger(L, plr->jointime);
else if (fastcmp(field,"splitscreenindex"))
lua_pushinteger(L, plr->splitscreenindex);
#ifdef HWRENDER #ifdef HWRENDER
else if (fastcmp(field,"fovadd")) else if (fastcmp(field,"fovadd"))
lua_pushfixed(L, plr->fovadd); lua_pushfixed(L, plr->fovadd);
@ -356,6 +359,9 @@ static int player_set(lua_State *L)
if (hud_running) if (hud_running)
return luaL_error(L, "Do not alter player_t in HUD rendering code!"); return luaL_error(L, "Do not alter player_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter player_t in BuildCMD code!");
if (fastcmp(field,"mo")) { if (fastcmp(field,"mo")) {
mobj_t *newmo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); mobj_t *newmo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
plr->mo->player = NULL; // remove player pointer from old mobj plr->mo->player = NULL; // remove player pointer from old mobj
@ -609,6 +615,8 @@ static int player_set(lua_State *L)
return NOSET; return NOSET;
else if (fastcmp(field,"jointime")) else if (fastcmp(field,"jointime"))
plr->jointime = (tic_t)luaL_checkinteger(L, 3); plr->jointime = (tic_t)luaL_checkinteger(L, 3);
else if (fastcmp(field,"splitscreenindex"))
return NOSET;
#ifdef HWRENDER #ifdef HWRENDER
else if (fastcmp(field,"fovadd")) else if (fastcmp(field,"fovadd"))
plr->fovadd = luaL_checkfixed(L, 3); plr->fovadd = luaL_checkfixed(L, 3);
@ -667,6 +675,8 @@ static int power_set(lua_State *L)
return luaL_error(L, LUA_QL("powertype_t") " cannot be %u", p); return luaL_error(L, LUA_QL("powertype_t") " cannot be %u", p);
if (hud_running) if (hud_running)
return luaL_error(L, "Do not alter player_t in HUD rendering code!"); return luaL_error(L, "Do not alter player_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter player_t in BuildCMD code!");
powers[p] = i; powers[p] = i;
return 0; return 0;
} }
@ -699,6 +709,8 @@ static int kartstuff_set(lua_State *L)
return luaL_error(L, LUA_QL("kartstufftype_t") " cannot be %u", ks); return luaL_error(L, LUA_QL("kartstufftype_t") " cannot be %u", ks);
if (hud_running) if (hud_running)
return luaL_error(L, "Do not alter player_t in HUD rendering code!"); return luaL_error(L, "Do not alter player_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter player_t in BuildCMD code!");
kartstuff[ks] = i; kartstuff[ks] = i;
return 0; return 0;
} }
@ -731,6 +743,8 @@ static int ticcmd_get(lua_State *L)
lua_pushinteger(L, cmd->buttons); lua_pushinteger(L, cmd->buttons);
else if (fastcmp(field,"driftturn")) else if (fastcmp(field,"driftturn"))
lua_pushinteger(L, cmd->driftturn); lua_pushinteger(L, cmd->driftturn);
else if (fastcmp(field,"latency"))
lua_pushinteger(L, cmd->latency);
else else
return NOFIELD; return NOFIELD;

View File

@ -212,6 +212,9 @@ void LUA_LoadLump(UINT16 wad, UINT16 lump)
LUA_LoadFile(&f, name); // actually load file! LUA_LoadFile(&f, name); // actually load file!
// Okay, we've modified the game beyond the point of no return.
G_SetGameModified(multiplayer, true);
free(name); free(name);
Z_Free(f.data); Z_Free(f.data);
} }
@ -1017,7 +1020,7 @@ void LUA_Archive(void)
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i]) if (!playeringame[i] && i > 0) // NEVER skip player 0, this is for dedi servs.
continue; continue;
// all players in game will be archived, even if they just add a 0. // all players in game will be archived, even if they just add a 0.
ArchiveExtVars(&players[i], "player"); ArchiveExtVars(&players[i], "player");
@ -1053,7 +1056,7 @@ void LUA_UnArchive(void)
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i]) if (!playeringame[i] && i > 0) // same here, this is to synch dediservs properly.
continue; continue;
UnArchiveExtVars(&players[i]); UnArchiveExtVars(&players[i]);
} }

View File

@ -30,24 +30,10 @@ enum skin {
skin_facerank, skin_facerank,
skin_facewant, skin_facewant,
skin_facemmap, skin_facemmap,
skin_ability,
skin_ability2,
skin_thokitem,
skin_spinitem,
skin_revitem,
skin_actionspd,
skin_mindash,
skin_maxdash,
// SRB2kart // SRB2kart
skin_kartspeed, skin_kartspeed,
skin_kartweight, skin_kartweight,
// //
skin_normalspeed,
skin_runspeed,
skin_thrustfactor,
skin_accelstart,
skin_acceleration,
skin_jumpfactor,
skin_starttranscolor, skin_starttranscolor,
skin_prefcolor, skin_prefcolor,
skin_highresscale, skin_highresscale,
@ -64,24 +50,10 @@ static const char *const skin_opt[] = {
"facerank", "facerank",
"facewant", "facewant",
"facemmap", "facemmap",
"ability",
"ability2",
"thokitem",
"spinitem",
"revitem",
"actionspd",
"mindash",
"maxdash",
// SRB2kart // SRB2kart
"kartspeed", "kartspeed",
"kartweight", "kartweight",
// //
"normalspeed",
"runspeed",
"thrustfactor",
"accelstart",
"acceleration",
"jumpfactor",
"starttranscolor", "starttranscolor",
"prefcolor", "prefcolor",
"highresscale", "highresscale",
@ -139,30 +111,6 @@ static int skin_get(lua_State *L)
break; break;
lua_pushlstring(L, skin->facemmap, i); lua_pushlstring(L, skin->facemmap, i);
break; break;
case skin_ability:
lua_pushinteger(L, skin->ability);
break;
case skin_ability2:
lua_pushinteger(L, skin->ability2);
break;
case skin_thokitem:
lua_pushinteger(L, skin->thokitem);
break;
case skin_spinitem:
lua_pushinteger(L, skin->spinitem);
break;
case skin_revitem:
lua_pushinteger(L, skin->revitem);
break;
case skin_actionspd:
lua_pushfixed(L, skin->actionspd);
break;
case skin_mindash:
lua_pushfixed(L, skin->mindash);
break;
case skin_maxdash:
lua_pushfixed(L, skin->maxdash);
break;
// SRB2kart // SRB2kart
case skin_kartspeed: case skin_kartspeed:
lua_pushinteger(L, skin->kartspeed); lua_pushinteger(L, skin->kartspeed);
@ -171,24 +119,6 @@ static int skin_get(lua_State *L)
lua_pushinteger(L, skin->kartweight); lua_pushinteger(L, skin->kartweight);
break; break;
// //
case skin_normalspeed:
lua_pushfixed(L, skin->normalspeed);
break;
case skin_runspeed:
lua_pushfixed(L, skin->runspeed);
break;
case skin_thrustfactor:
lua_pushinteger(L, skin->thrustfactor);
break;
case skin_accelstart:
lua_pushinteger(L, skin->accelstart);
break;
case skin_acceleration:
lua_pushinteger(L, skin->acceleration);
break;
case skin_jumpfactor:
lua_pushfixed(L, skin->jumpfactor);
break;
case skin_starttranscolor: case skin_starttranscolor:
lua_pushinteger(L, skin->starttranscolor); lua_pushinteger(L, skin->starttranscolor);
break; break;

View File

@ -121,7 +121,7 @@ static UINT8 cheatf_devmode(void)
S_StartSound(0, sfx_itemup); S_StartSound(0, sfx_itemup);
// Just unlock all the things and turn on -debug and console devmode. // Just unlock all the things and turn on -debug and console devmode.
G_SetGameModified(false); G_SetGameModified(false, false); // might need to revist the latter later
for (i = 0; i < MAXUNLOCKABLES; i++) for (i = 0; i < MAXUNLOCKABLES; i++)
unlockables[i].unlocked = true; unlockables[i].unlocked = true;
devparm = true; devparm = true;
@ -295,7 +295,7 @@ void Command_CheatNoClip_f(void)
plyr->pflags ^= PF_NOCLIP; plyr->pflags ^= PF_NOCLIP;
CONS_Printf(M_GetText("No Clipping %s\n"), plyr->pflags & PF_NOCLIP ? M_GetText("On") : M_GetText("Off")); CONS_Printf(M_GetText("No Clipping %s\n"), plyr->pflags & PF_NOCLIP ? M_GetText("On") : M_GetText("Off"));
G_SetGameModified(multiplayer); G_SetGameModified(multiplayer, true);
} }
void Command_CheatGod_f(void) void Command_CheatGod_f(void)
@ -310,7 +310,7 @@ void Command_CheatGod_f(void)
plyr->pflags ^= PF_GODMODE; plyr->pflags ^= PF_GODMODE;
CONS_Printf(M_GetText("Sissy Mode %s\n"), plyr->pflags & PF_GODMODE ? M_GetText("On") : M_GetText("Off")); CONS_Printf(M_GetText("Sissy Mode %s\n"), plyr->pflags & PF_GODMODE ? M_GetText("On") : M_GetText("Off"));
G_SetGameModified(multiplayer); G_SetGameModified(multiplayer, true);
} }
void Command_CheatNoTarget_f(void) void Command_CheatNoTarget_f(void)
@ -325,7 +325,7 @@ void Command_CheatNoTarget_f(void)
plyr->pflags ^= PF_INVIS; plyr->pflags ^= PF_INVIS;
CONS_Printf(M_GetText("SEP Field %s\n"), plyr->pflags & PF_INVIS ? M_GetText("On") : M_GetText("Off")); CONS_Printf(M_GetText("SEP Field %s\n"), plyr->pflags & PF_INVIS ? M_GetText("On") : M_GetText("Off"));
G_SetGameModified(multiplayer); G_SetGameModified(multiplayer, true);
} }
void Command_Scale_f(void) void Command_Scale_f(void)
@ -727,7 +727,7 @@ void Command_Devmode_f(void)
return; return;
} }
G_SetGameModified(multiplayer); G_SetGameModified(multiplayer, true);
} }
/*void Command_Setrings_f(void) /*void Command_Setrings_f(void)
@ -1130,12 +1130,12 @@ void OP_ObjectplaceMovement(player_t *player)
P_TeleportMove(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, player->mo->z); P_TeleportMove(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, player->mo->z);
player->mo->momx = player->mo->momy = 0; player->mo->momx = player->mo->momy = 0;
} }
if (cmd->sidemove != 0) /*if (cmd->sidemove != 0) -- was disabled in practice anyways, since sidemove was suppressed
{ {
P_Thrust(player->mo, player->mo->angle-ANGLE_90, (cmd->sidemove*FRACUNIT/MAXPLMOVE)*cv_speed.value); P_Thrust(player->mo, player->mo->angle-ANGLE_90, (cmd->sidemove*FRACUNIT/MAXPLMOVE)*cv_speed.value);
P_TeleportMove(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, player->mo->z); P_TeleportMove(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, player->mo->z);
player->mo->momx = player->mo->momy = 0; player->mo->momx = player->mo->momy = 0;
} }*/
if (player->mo->z > player->mo->ceilingz - player->mo->height) if (player->mo->z > player->mo->ceilingz - player->mo->height)
player->mo->z = player->mo->ceilingz - player->mo->height; player->mo->z = player->mo->ceilingz - player->mo->height;
@ -1267,7 +1267,7 @@ void Command_ObjectPlace_f(void)
REQUIRE_SINGLEPLAYER; REQUIRE_SINGLEPLAYER;
REQUIRE_NOULTIMATE; REQUIRE_NOULTIMATE;
G_SetGameModified(multiplayer); G_SetGameModified(multiplayer, true);
// Entering objectplace? // Entering objectplace?
if (!objectplacing) if (!objectplacing)

View File

@ -385,8 +385,7 @@ UINT8 M_UpdateUnlockablesAndExtraEmblems(boolean force)
char cechoText[992] = ""; char cechoText[992] = "";
UINT8 cechoLines = 0; UINT8 cechoLines = 0;
if (modifiedgame && !savemoddata if (majormods && !force) // SRB2Kart: for enabling unlocks online in modified servers
&& !force) // SRB2Kart: for enabling unlocks online in modified servers
return false; return false;
M_CheckUnlockConditions(); M_CheckUnlockConditions();

View File

@ -274,14 +274,13 @@ static menu_t SP_TimeAttackDef, SP_ReplayDef, SP_GuestReplayDef, SP_GhostDef;
#ifndef NONET #ifndef NONET
static void M_StartServerMenu(INT32 choice); static void M_StartServerMenu(INT32 choice);
static void M_ConnectMenu(INT32 choice); static void M_ConnectMenu(INT32 choice);
#endif static void M_ConnectMenuModChecks(INT32 choice);
static void M_StartOfflineServerMenu(INT32 choice);
static void M_StartServer(INT32 choice);
#ifndef NONET
static void M_Refresh(INT32 choice); static void M_Refresh(INT32 choice);
static void M_Connect(INT32 choice); static void M_Connect(INT32 choice);
static void M_ChooseRoom(INT32 choice); static void M_ChooseRoom(INT32 choice);
#endif #endif
static void M_StartOfflineServerMenu(INT32 choice);
static void M_StartServer(INT32 choice);
static void M_SetupMultiPlayer(INT32 choice); static void M_SetupMultiPlayer(INT32 choice);
static void M_SetupMultiPlayer2(INT32 choice); static void M_SetupMultiPlayer2(INT32 choice);
static void M_SetupMultiPlayer3(INT32 choice); static void M_SetupMultiPlayer3(INT32 choice);
@ -400,6 +399,8 @@ static void Dummystaff_OnChange(void);
// CONSOLE VARIABLES AND THEIR POSSIBLE VALUES GO HERE. // CONSOLE VARIABLES AND THEIR POSSIBLE VALUES GO HERE.
// ========================================================================== // ==========================================================================
consvar_t cv_showfocuslost = {"showfocuslost", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL };
static CV_PossibleValue_t map_cons_t[] = { static CV_PossibleValue_t map_cons_t[] = {
{0,"MIN"}, {0,"MIN"},
{NUMMAPS, "MAX"}, {NUMMAPS, "MAX"},
@ -439,11 +440,11 @@ static CV_PossibleValue_t serversort_cons_t[] = {
{1,"Modified State"}, {1,"Modified State"},
{2,"Most Players"}, {2,"Most Players"},
{3,"Least Players"}, {3,"Least Players"},
{4,"Max Players"}, {4,"Max Player Slots"},
{5,"Gametype"}, {5,"Gametype"},
{0,NULL} {0,NULL}
}; };
consvar_t cv_serversort = {"serversort", "Ping", CV_HIDEN | CV_CALL, serversort_cons_t, M_SortServerList, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_serversort = {"serversort", "Ping", CV_CALL, serversort_cons_t, M_SortServerList, 0, NULL, NULL, 0, 0, NULL};
// autorecord demos for time attack // autorecord demos for time attack
static consvar_t cv_autorecord = {"autorecord", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; static consvar_t cv_autorecord = {"autorecord", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -911,41 +912,7 @@ static menuitem_t SP_LevelStatsMenu[] =
// External files modify this menu, so we can't call it static. // External files modify this menu, so we can't call it static.
// And I'm too lazy to go through and rename it everywhere. ARRGH! // And I'm too lazy to go through and rename it everywhere. ARRGH!
#define M_ChoosePlayer NULL #define M_ChoosePlayer NULL
menuitem_t PlayerMenu[32] = menuitem_t PlayerMenu[MAXSKINS];
{
{IT_CALL, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0},
{IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}
};
// ----------------------------------- // -----------------------------------
// Multiplayer and all of its submenus // Multiplayer and all of its submenus
@ -969,11 +936,11 @@ static menuitem_t MP_MainMenu[] =
{IT_HEADER, NULL, "Join a game", NULL, 132-24}, {IT_HEADER, NULL, "Join a game", NULL, 132-24},
#ifndef NONET #ifndef NONET
{IT_STRING|IT_CALL, NULL, "Internet server browser...",M_ConnectMenu, 142-24}, {IT_STRING|IT_CALL, NULL, "Internet server browser...",M_ConnectMenuModChecks, 142-24},
{IT_STRING|IT_KEYHANDLER, NULL, "Specify IPv4 address:", M_HandleConnectIP, 150-24}, {IT_STRING|IT_KEYHANDLER, NULL, "Specify IPv4 address:", M_HandleConnectIP, 150-24},
#else #else
{IT_GRAYEDOUT, NULL, "Internet server browser...",M_ConnectMenu, 142-24}, {IT_GRAYEDOUT, NULL, "Internet server browser...",NULL, 142-24},
{IT_GRAYEDOUT, NULL, "Specify IPv4 address:", M_HandleConnectIP, 150-24}, {IT_GRAYEDOUT, NULL, "Specify IPv4 address:", NULL, 150-24},
#endif #endif
//{IT_HEADER, NULL, "Player setup", NULL, 80}, //{IT_HEADER, NULL, "Player setup", NULL, 80},
//{IT_STRING|IT_CALL, NULL, "Name, character, color...", M_SetupMultiPlayer, 90}, //{IT_STRING|IT_CALL, NULL, "Name, character, color...", M_SetupMultiPlayer, 90},
@ -983,14 +950,15 @@ static menuitem_t MP_MainMenu[] =
static menuitem_t MP_ServerMenu[] = static menuitem_t MP_ServerMenu[] =
{ {
{IT_STRING|IT_CVAR, NULL, "Max. Player Count", &cv_maxplayers, 10}, {IT_STRING|IT_CVAR, NULL, "Max. Player Count", &cv_maxplayers, 0},
{IT_STRING|IT_CALL, NULL, "Room...", M_RoomMenu, 20}, {IT_STRING|IT_CALL, NULL, "Room...", M_RoomMenu, 10},
{IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 30}, {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 20},
{IT_STRING|IT_CVAR|IT_CV_PASSWORD, NULL, "Password", &cv_dummyjoinpassword, 44},
{IT_STRING|IT_CVAR, NULL, "Game Type", &cv_newgametype, 68}, {IT_STRING|IT_CVAR, NULL, "Game Type", &cv_newgametype, 68},
{IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 78}, {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 78},
{IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 130}, {IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 130},
}; };
#endif #endif
@ -1284,7 +1252,7 @@ static menuitem_t OP_OpenGLOptionsMenu[] =
{IT_SUBMENU|IT_STRING, NULL, "Fog...", &OP_OpenGLFogDef, 10}, {IT_SUBMENU|IT_STRING, NULL, "Fog...", &OP_OpenGLFogDef, 10},
{IT_SUBMENU|IT_STRING, NULL, "Gamma...", &OP_OpenGLColorDef, 20}, {IT_SUBMENU|IT_STRING, NULL, "Gamma...", &OP_OpenGLColorDef, 20},
{IT_STRING|IT_CVAR, NULL, "Field of View", &cv_grfov, 35}, {IT_STRING|IT_CVAR, NULL, "Field of View", &cv_fov, 35},
{IT_STRING|IT_CVAR, NULL, "Quality", &cv_scr_depth, 45}, {IT_STRING|IT_CVAR, NULL, "Quality", &cv_scr_depth, 45},
{IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 55}, {IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 55},
{IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode, 65}, {IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode, 65},
@ -1351,6 +1319,9 @@ static menuitem_t OP_SoundOptionsMenu[] =
{IT_STRING|IT_CVAR, NULL, "Powerup Warning", &cv_kartinvinsfx, 95}, {IT_STRING|IT_CVAR, NULL, "Powerup Warning", &cv_kartinvinsfx, 95},
{IT_KEYHANDLER|IT_STRING, NULL, "Sound Test", M_HandleSoundTest, 110}, {IT_KEYHANDLER|IT_STRING, NULL, "Sound Test", M_HandleSoundTest, 110},
{IT_STRING|IT_CVAR, NULL, "Play Music While Unfocused", &cv_playmusicifunfocused, 125},
{IT_STRING|IT_CVAR, NULL, "Play SFX While Unfocused", &cv_playsoundifunfocused, 135},
}; };
/*static menuitem_t OP_DataOptionsMenu[] = /*static menuitem_t OP_DataOptionsMenu[] =
@ -1425,7 +1396,7 @@ static menuitem_t OP_HUDOptionsMenu[] =
{IT_STRING | IT_CVAR | IT_CV_SLIDER, {IT_STRING | IT_CVAR | IT_CV_SLIDER,
NULL, "HUD Visibility", &cv_translucenthud, 20}, NULL, "HUD Visibility", &cv_translucenthud, 20},
{IT_STRING | IT_SUBMENU, NULL, "Online chat options...",&OP_ChatOptionsDef, 35}, {IT_STRING | IT_SUBMENU, NULL, "Online HUD options...",&OP_ChatOptionsDef, 35},
{IT_STRING | IT_CVAR, NULL, "Background Glass", &cons_backcolor, 45}, {IT_STRING | IT_CVAR, NULL, "Background Glass", &cons_backcolor, 45},
{IT_STRING | IT_CVAR | IT_CV_SLIDER, {IT_STRING | IT_CVAR | IT_CV_SLIDER,
@ -1437,8 +1408,11 @@ static menuitem_t OP_HUDOptionsMenu[] =
// highlight info - (GOOD HIGHLIGHT, WARNING HIGHLIGHT) - 105 (see M_DrawHUDOptions) // highlight info - (GOOD HIGHLIGHT, WARNING HIGHLIGHT) - 105 (see M_DrawHUDOptions)
{IT_STRING | IT_CVAR, NULL, "Console Text Size", &cv_constextsize, 120}, {IT_STRING | IT_CVAR, NULL, "Console Text Size", &cv_constextsize, 120},
{IT_STRING | IT_CVAR, NULL, "Show \"FOCUS LOST\"", &cv_showfocuslost, 135},
}; };
// Ok it's still called chatoptions but we'll put ping display in here to be clean
static menuitem_t OP_ChatOptionsMenu[] = static menuitem_t OP_ChatOptionsMenu[] =
{ {
// will ANYONE who doesn't know how to use the console want to touch this one? // will ANYONE who doesn't know how to use the console want to touch this one?
@ -1452,6 +1426,8 @@ static menuitem_t OP_ChatOptionsMenu[] =
{IT_STRING | IT_CVAR, NULL, "Chat Background Tint", &cv_chatbacktint, 50}, {IT_STRING | IT_CVAR, NULL, "Chat Background Tint", &cv_chatbacktint, 50},
{IT_STRING | IT_CVAR, NULL, "Message Fadeout Time", &cv_chattime, 60}, {IT_STRING | IT_CVAR, NULL, "Message Fadeout Time", &cv_chattime, 60},
{IT_STRING | IT_CVAR, NULL, "Spam Protection", &cv_chatspamprotection, 70}, {IT_STRING | IT_CVAR, NULL, "Spam Protection", &cv_chatspamprotection, 70},
{IT_STRING | IT_CVAR, NULL, "Local ping display", &cv_showping, 90}, // shows ping next to framerate if we want to.
}; };
static menuitem_t OP_GameOptionsMenu[] = static menuitem_t OP_GameOptionsMenu[] =
@ -1504,15 +1480,16 @@ static menuitem_t OP_AdvServerOptionsMenu[] =
{IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 40}, {IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 40},
{IT_STRING | IT_CVAR, NULL, "Ping limit (ms)", &cv_maxping, 50}, {IT_STRING | IT_CVAR, NULL, "Ping limit (ms)", &cv_maxping, 50},
{IT_STRING | IT_CVAR, NULL, "Connection timeout (tics)", &cv_nettimeout, 60}, {IT_STRING | IT_CVAR, NULL, "Ping timeout (s)", &cv_pingtimeout, 60},
{IT_STRING | IT_CVAR, NULL, "Join timeout (tics)", &cv_jointimeout, 70}, {IT_STRING | IT_CVAR, NULL, "Connection timeout (tics)", &cv_nettimeout, 70},
{IT_STRING | IT_CVAR, NULL, "Join timeout (tics)", &cv_jointimeout, 80},
{IT_STRING | IT_CVAR, NULL, "Max. file transfer send (KB)", &cv_maxsend, 90}, {IT_STRING | IT_CVAR, NULL, "Max. file transfer send (KB)", &cv_maxsend, 100},
{IT_STRING | IT_CVAR, NULL, "File transfer packet rate", &cv_downloadspeed, 100}, {IT_STRING | IT_CVAR, NULL, "File transfer packet rate", &cv_downloadspeed, 110},
{IT_STRING | IT_CVAR, NULL, "Log join addresses", &cv_showjoinaddress, 120}, {IT_STRING | IT_CVAR, NULL, "Log join addresses", &cv_showjoinaddress, 130},
{IT_STRING | IT_CVAR, NULL, "Log resyncs", &cv_blamecfail, 130}, {IT_STRING | IT_CVAR, NULL, "Log resyncs", &cv_blamecfail, 140},
{IT_STRING | IT_CVAR, NULL, "Log file transfers", &cv_noticedownload, 140}, {IT_STRING | IT_CVAR, NULL, "Log file transfers", &cv_noticedownload, 150},
}; };
#endif #endif
@ -1865,7 +1842,6 @@ static menu_t SP_NightsGhostDef =
NULL NULL
};*/ };*/
#ifndef NONET
// Multiplayer // Multiplayer
menu_t MP_MainDef = menu_t MP_MainDef =
{ {
@ -1876,12 +1852,18 @@ menu_t MP_MainDef =
M_DrawMPMainMenu, M_DrawMPMainMenu,
42, 30, 42, 30,
0, 0,
M_CancelConnect
};
menu_t MP_ServerDef = MAPICONMENUSTYLE("M_MULTI", MP_ServerMenu, &MP_MainDef);
#endif
menu_t MP_OfflineServerDef = MAPICONMENUSTYLE("M_MULTI", MP_OfflineServerMenu, &MP_MainDef);
#ifndef NONET #ifndef NONET
M_CancelConnect
#else
NULL
#endif
};
menu_t MP_OfflineServerDef = MAPICONMENUSTYLE("M_MULTI", MP_OfflineServerMenu, &MP_MainDef);
#ifndef NONET
menu_t MP_ServerDef = MAPICONMENUSTYLE("M_MULTI", MP_ServerMenu, &MP_MainDef);
menu_t MP_ConnectDef = menu_t MP_ConnectDef =
{ {
"M_MULTI", "M_MULTI",
@ -2409,6 +2391,9 @@ static void M_NextOpt(void)
{ {
INT16 oldItemOn = itemOn; // prevent infinite loop INT16 oldItemOn = itemOn; // prevent infinite loop
if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_PASSWORD)
((consvar_t *)currentMenu->menuitems[itemOn].itemaction)->value = 0;
do do
{ {
if (itemOn + 1 > currentMenu->numitems - 1) if (itemOn + 1 > currentMenu->numitems - 1)
@ -2422,6 +2407,9 @@ static void M_PrevOpt(void)
{ {
INT16 oldItemOn = itemOn; // prevent infinite loop INT16 oldItemOn = itemOn; // prevent infinite loop
if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_PASSWORD)
((consvar_t *)currentMenu->menuitems[itemOn].itemaction)->value = 0;
do do
{ {
if (!itemOn) if (!itemOn)
@ -2584,7 +2572,7 @@ boolean M_Responder(event_t *ev)
return false; return false;
else if (ch == gamecontrol[gc_systemmenu][0] || ch == gamecontrol[gc_systemmenu][1]) // allow remappable ESC key else if (ch == gamecontrol[gc_systemmenu][0] || ch == gamecontrol[gc_systemmenu][1]) // allow remappable ESC key
ch = KEY_ESCAPE; ch = KEY_ESCAPE;
else if (ch == gamecontrol[gc_accelerate][0] || ch == gamecontrol[gc_accelerate][1]) else if ((ch == gamecontrol[gc_accelerate][0] || ch == gamecontrol[gc_accelerate][1]) && ch >= KEY_MOUSE1)
ch = KEY_ENTER; ch = KEY_ENTER;
// F-Keys // F-Keys
@ -2662,7 +2650,7 @@ boolean M_Responder(event_t *ev)
return false; return false;
} }
if (ch == gamecontrol[gc_brake][0] || ch == gamecontrol[gc_brake][1]) // do this here, otherwise brake opens the menu mid-game if ((ch == gamecontrol[gc_brake][0] || ch == gamecontrol[gc_brake][1]) && ch >= KEY_MOUSE1) // do this here, otherwise brake opens the menu mid-game
ch = KEY_ESCAPE; ch = KEY_ESCAPE;
routine = currentMenu->menuitems[itemOn].itemaction; routine = currentMenu->menuitems[itemOn].itemaction;
@ -2708,8 +2696,11 @@ boolean M_Responder(event_t *ev)
// BP: one of the more big hack i have never made // BP: one of the more big hack i have never made
if (routine && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR) if (routine && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR)
{ {
if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_STRING) if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_STRING || (currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_PASSWORD)
{ {
if (ch == KEY_TAB && (currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_PASSWORD)
((consvar_t *)currentMenu->menuitems[itemOn].itemaction)->value ^= 1;
if (shiftdown && ch >= 32 && ch <= 127) if (shiftdown && ch >= 32 && ch <= 127)
ch = shiftxform[ch]; ch = shiftxform[ch];
if (M_ChangeStringCvar(ch)) if (M_ChangeStringCvar(ch))
@ -2773,10 +2764,10 @@ boolean M_Responder(event_t *ev)
|| (currentMenu->menuitems[itemOn].status & IT_TYPE)==IT_SUBMENU) || (currentMenu->menuitems[itemOn].status & IT_TYPE)==IT_SUBMENU)
&& (currentMenu->menuitems[itemOn].status & IT_CALLTYPE)) && (currentMenu->menuitems[itemOn].status & IT_CALLTYPE))
{ {
if (((currentMenu->menuitems[itemOn].status & IT_CALLTYPE) & IT_CALL_NOTMODIFIED) && modifiedgame && !savemoddata) if (((currentMenu->menuitems[itemOn].status & IT_CALLTYPE) & IT_CALL_NOTMODIFIED) && majormods)
{ {
S_StartSound(NULL, sfx_menu1); S_StartSound(NULL, sfx_menu1);
M_StartMessage(M_GetText("This cannot be done with add-ons\nor in a cheated game.\n\n(Press a key)\n"), NULL, MM_NOTHING); M_StartMessage(M_GetText("This cannot be done with complex add-ons\nor in a cheated game.\n\n(Press a key)\n"), NULL, MM_NOTHING);
return true; return true;
} }
} }
@ -2910,7 +2901,7 @@ void M_Drawer(void)
} }
// focus lost notification goes on top of everything, even the former everything // focus lost notification goes on top of everything, even the former everything
if (window_notinfocus) if (window_notinfocus && cv_showfocuslost.value)
{ {
M_DrawTextBox((BASEVIDWIDTH/2) - (60), (BASEVIDHEIGHT/2) - (16), 13, 2); M_DrawTextBox((BASEVIDWIDTH/2) - (60), (BASEVIDHEIGHT/2) - (16), 13, 2);
if (gamestate == GS_LEVEL && (P_AutoPause() || paused)) if (gamestate == GS_LEVEL && (P_AutoPause() || paused))
@ -3188,6 +3179,8 @@ void M_Ticker(void)
// //
void M_Init(void) void M_Init(void)
{ {
UINT8 i;
COM_AddCommand("manual", Command_Manual_f); COM_AddCommand("manual", Command_Manual_f);
CV_RegisterVar(&cv_nextmap); CV_RegisterVar(&cv_nextmap);
@ -3199,7 +3192,6 @@ void M_Init(void)
return; return;
// Menu hacks // Menu hacks
CV_RegisterVar(&cv_splitplayers);
CV_RegisterVar(&cv_dummymenuplayer); CV_RegisterVar(&cv_dummymenuplayer);
CV_RegisterVar(&cv_dummyteam); CV_RegisterVar(&cv_dummyteam);
CV_RegisterVar(&cv_dummyspectate); CV_RegisterVar(&cv_dummyspectate);
@ -3235,6 +3227,15 @@ void M_Init(void)
quitmsg[QUIT3MSG5] = M_GetText("You'll be back to play soon, though...\n...right?\n\n(Press 'Y' to quit)"); quitmsg[QUIT3MSG5] = M_GetText("You'll be back to play soon, though...\n...right?\n\n(Press 'Y' to quit)");
quitmsg[QUIT3MSG6] = M_GetText("Aww, is Eggman's Nightclub too\ndifficult for you?\n\n(Press 'Y' to quit)"); quitmsg[QUIT3MSG6] = M_GetText("Aww, is Eggman's Nightclub too\ndifficult for you?\n\n(Press 'Y' to quit)");
// Setup PlayerMenu table
for (i = 0; i < MAXSKINS; i++)
{
PlayerMenu[i].status = (i == 0 ? IT_CALL : IT_DISABLED);
PlayerMenu[i].patch = PlayerMenu[i].text = NULL;
PlayerMenu[i].itemaction = M_ChoosePlayer;
PlayerMenu[i].alphaKey = 0;
}
#ifdef HWRENDER #ifdef HWRENDER
// Permanently hide some options based on render mode // Permanently hide some options based on render mode
if (rendermode == render_soft) if (rendermode == render_soft)
@ -3473,7 +3474,7 @@ static void M_DrawMapEmblems(INT32 mapnum, INT32 x, INT32 y)
if (emblem->collected) if (emblem->collected)
V_DrawSmallMappedPatch(x, y, 0, W_CachePatchName(M_GetEmblemPatch(emblem), PU_CACHE), V_DrawSmallMappedPatch(x, y, 0, W_CachePatchName(M_GetEmblemPatch(emblem), PU_CACHE),
R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE)); R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_MENUCACHE));
else else
V_DrawSmallScaledPatch(x, y, 0, W_CachePatchName("NEEDIT", PU_CACHE)); V_DrawSmallScaledPatch(x, y, 0, W_CachePatchName("NEEDIT", PU_CACHE));
@ -3573,6 +3574,8 @@ static void M_DrawGenericMenu(void)
case IT_CVAR: case IT_CVAR:
{ {
consvar_t *cv = (consvar_t *)currentMenu->menuitems[i].itemaction; consvar_t *cv = (consvar_t *)currentMenu->menuitems[i].itemaction;
char asterisks[MAXSTRINGLENGTH+1];
size_t sl;
switch (currentMenu->menuitems[i].status & IT_CVARTYPE) switch (currentMenu->menuitems[i].status & IT_CVARTYPE)
{ {
case IT_CV_SLIDER: case IT_CV_SLIDER:
@ -3580,6 +3583,27 @@ static void M_DrawGenericMenu(void)
case IT_CV_NOPRINT: // color use this case IT_CV_NOPRINT: // color use this
case IT_CV_INVISSLIDER: // monitor toggles use this case IT_CV_INVISSLIDER: // monitor toggles use this
break; break;
case IT_CV_PASSWORD:
if (i == itemOn)
{
V_DrawRightAlignedThinString(x + MAXSTRINGLENGTH*8 + 10, y, V_ALLOWLOWERCASE, va(M_GetText("Tab: %s password"), cv->value ? "hide" : "show"));
}
if (!cv->value || i != itemOn)
{
sl = strlen(cv->string);
memset(asterisks, '*', sl);
memset(asterisks + sl, 0, MAXSTRINGLENGTH+1-sl);
M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1);
V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, asterisks);
if (skullAnimCounter < 4 && i == itemOn)
V_DrawCharacter(x + 8 + V_StringWidth(asterisks, 0), y + 12,
'_' | 0x80, false);
y += 16;
break;
}
/* fallthru */
case IT_CV_STRING: case IT_CV_STRING:
M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1); M_DrawTextBox(x, y + 4, MAXSTRINGLENGTH, 1);
V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, cv->string); V_DrawString(x + 8, y + 12, V_ALLOWLOWERCASE, cv->string);
@ -3787,7 +3811,7 @@ static void M_DrawPauseMenu(void)
if (emblem->collected) if (emblem->collected)
V_DrawSmallMappedPatch(40, 44 + (i*8), 0, W_CachePatchName(M_GetEmblemPatch(emblem), PU_CACHE), V_DrawSmallMappedPatch(40, 44 + (i*8), 0, W_CachePatchName(M_GetEmblemPatch(emblem), PU_CACHE),
R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE)); R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_MENUCACHE));
else else
V_DrawSmallScaledPatch(40, 44 + (i*8), 0, W_CachePatchName("NEEDIT", PU_CACHE)); V_DrawSmallScaledPatch(40, 44 + (i*8), 0, W_CachePatchName("NEEDIT", PU_CACHE));
@ -4551,9 +4575,14 @@ static char *M_AddonsHeaderPath(void)
#define CLEARNAME Z_Free(refreshdirname);\ #define CLEARNAME Z_Free(refreshdirname);\
refreshdirname = NULL refreshdirname = NULL
static boolean prevmajormods = false;
static void M_AddonsClearName(INT32 choice) static void M_AddonsClearName(INT32 choice)
{ {
CLEARNAME; if (!majormods || prevmajormods)
{
CLEARNAME;
}
M_StopMessage(choice); M_StopMessage(choice);
} }
@ -4563,10 +4592,17 @@ static boolean M_AddonsRefresh(void)
if ((refreshdirmenu & REFRESHDIR_NORMAL) && !preparefilemenu(true)) if ((refreshdirmenu & REFRESHDIR_NORMAL) && !preparefilemenu(true))
{ {
UNEXIST; UNEXIST;
if (refreshdirname)
{
CLEARNAME;
}
return true; return true;
} }
if (refreshdirmenu & REFRESHDIR_ADDFILE) if (!majormods && prevmajormods)
prevmajormods = false;
if ((refreshdirmenu & REFRESHDIR_ADDFILE) || (majormods && !prevmajormods))
{ {
char *message = NULL; char *message = NULL;
@ -4574,7 +4610,7 @@ static boolean M_AddonsRefresh(void)
{ {
S_StartSound(NULL, sfx_s26d); S_StartSound(NULL, sfx_s26d);
if (refreshdirmenu & REFRESHDIR_MAX) if (refreshdirmenu & REFRESHDIR_MAX)
message = va("%c%s\x80\nMaximum number of add-ons reached.\nA file could not be loaded.\nIf you want to play with this add-on, restart the game to clear existing ones.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); message = va("%c%s\x80\nMaximum number of add-ons reached.\nA file could not be loaded.\nIf you wish to play with this add-on, restart the game to clear existing ones.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname);
else else
message = va("%c%s\x80\nA file was not loaded.\nCheck the console log for more information.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname); message = va("%c%s\x80\nA file was not loaded.\nCheck the console log for more information.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname);
} }
@ -4583,6 +4619,12 @@ static boolean M_AddonsRefresh(void)
S_StartSound(NULL, sfx_s224); S_StartSound(NULL, sfx_s224);
message = va("%c%s\x80\nA file was loaded with %s.\nCheck the console log for more information.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname, ((refreshdirmenu & REFRESHDIR_ERROR) ? "errors" : "warnings")); message = va("%c%s\x80\nA file was loaded with %s.\nCheck the console log for more information.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname, ((refreshdirmenu & REFRESHDIR_ERROR) ? "errors" : "warnings"));
} }
else if (majormods && !prevmajormods)
{
S_StartSound(NULL, sfx_s221);
message = va("%c%s\x80\nGameplay has now been modified.\nIf you wish to play Record Attack mode, restart the game to clear existing add-ons.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), refreshdirname);
prevmajormods = majormods;
}
if (message) if (message)
{ {
@ -4733,7 +4775,7 @@ static void M_DrawAddons(void)
V_DrawSmallScaledPatch(x, y + 4, (menusearch[0] ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+3]); V_DrawSmallScaledPatch(x, y + 4, (menusearch[0] ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+3]);
x = BASEVIDWIDTH - x - 16; x = BASEVIDWIDTH - x - 16;
V_DrawSmallScaledPatch(x, y + 4, ((!modifiedgame || savemoddata) ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+4]); V_DrawSmallScaledPatch(x, y + 4, ((!majormods) ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+4]);
if (modifiedgame) if (modifiedgame)
V_DrawSmallScaledPatch(x, y + 4, 0, addonsp[NUM_EXT+2]); V_DrawSmallScaledPatch(x, y + 4, 0, addonsp[NUM_EXT+2]);
@ -5130,7 +5172,7 @@ static void M_GetAllEmeralds(INT32 choice)
emeralds = ((EMERALD7)*2)-1; emeralds = ((EMERALD7)*2)-1;
M_StartMessage(M_GetText("You now have all 7 emeralds.\nUse them wisely.\nWith great power comes great ring drain.\n"),NULL,MM_NOTHING); M_StartMessage(M_GetText("You now have all 7 emeralds.\nUse them wisely.\nWith great power comes great ring drain.\n"),NULL,MM_NOTHING);
G_SetGameModified(multiplayer); G_SetGameModified(multiplayer, true);
} }
static void M_DestroyRobotsResponse(INT32 ch) static void M_DestroyRobotsResponse(INT32 ch)
@ -5141,7 +5183,7 @@ static void M_DestroyRobotsResponse(INT32 ch)
// Destroy all robots // Destroy all robots
P_DestroyRobots(); P_DestroyRobots();
G_SetGameModified(multiplayer); G_SetGameModified(multiplayer, true);
} }
static void M_DestroyRobots(INT32 choice) static void M_DestroyRobots(INT32 choice)
@ -5317,7 +5359,7 @@ static void M_DrawEmblemHints(void)
{ {
collected = recommendedflags; collected = recommendedflags;
V_DrawMappedPatch(12, 12+(28*j), 0, W_CachePatchName(M_GetEmblemPatch(emblem), PU_CACHE), V_DrawMappedPatch(12, 12+(28*j), 0, W_CachePatchName(M_GetEmblemPatch(emblem), PU_CACHE),
R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE)); R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_MENUCACHE));
} }
else else
{ {
@ -5660,7 +5702,7 @@ static void M_DrawLoadGameData(void)
V_DrawScaledPatch(SP_LoadDef.x,144+8,0,W_CachePatchName(skins[savegameinfo[saveSlotSelected].skinnum].face, PU_CACHE)); V_DrawScaledPatch(SP_LoadDef.x,144+8,0,W_CachePatchName(skins[savegameinfo[saveSlotSelected].skinnum].face, PU_CACHE));
else else
{ {
UINT8 *colormap = R_GetTranslationColormap(savegameinfo[saveSlotSelected].skinnum, savegameinfo[saveSlotSelected].skincolor, 0); UINT8 *colormap = R_GetTranslationColormap(savegameinfo[saveSlotSelected].skinnum, savegameinfo[saveSlotSelected].skincolor, GTC_MENUCACHE);
V_DrawMappedPatch(SP_LoadDef.x,144+8,0,W_CachePatchName(skins[savegameinfo[saveSlotSelected].skinnum].face, PU_CACHE), colormap); V_DrawMappedPatch(SP_LoadDef.x,144+8,0,W_CachePatchName(skins[savegameinfo[saveSlotSelected].skinnum].face, PU_CACHE), colormap);
} }
@ -6350,7 +6392,7 @@ static void M_DrawStatsMaps(int location)
if (exemblem->collected) if (exemblem->collected)
V_DrawSmallMappedPatch(295, y, 0, W_CachePatchName(M_GetExtraEmblemPatch(exemblem), PU_CACHE), V_DrawSmallMappedPatch(295, y, 0, W_CachePatchName(M_GetExtraEmblemPatch(exemblem), PU_CACHE),
R_GetTranslationColormap(TC_DEFAULT, M_GetExtraEmblemColor(exemblem), GTC_CACHE)); R_GetTranslationColormap(TC_DEFAULT, M_GetExtraEmblemColor(exemblem), GTC_MENUCACHE));
else else
V_DrawSmallScaledPatch(295, y, 0, W_CachePatchName("NEEDIT", PU_CACHE)); V_DrawSmallScaledPatch(295, y, 0, W_CachePatchName("NEEDIT", PU_CACHE));
@ -6485,7 +6527,7 @@ void M_DrawTimeAttackMenu(void)
// Character face! // Character face!
if (W_CheckNumForName(skins[cv_chooseskin.value-1].facewant) != LUMPERROR) if (W_CheckNumForName(skins[cv_chooseskin.value-1].facewant) != LUMPERROR)
{ {
UINT8 *colormap = R_GetTranslationColormap(cv_chooseskin.value-1, cv_playercolor.value, 0); UINT8 *colormap = R_GetTranslationColormap(cv_chooseskin.value-1, cv_playercolor.value, GTC_MENUCACHE);
V_DrawMappedPatch(BASEVIDWIDTH-x - SHORT(facewantprefix[cv_chooseskin.value-1]->width), y, 0, facewantprefix[cv_chooseskin.value-1], colormap); V_DrawMappedPatch(BASEVIDWIDTH-x - SHORT(facewantprefix[cv_chooseskin.value-1]->width), y, 0, facewantprefix[cv_chooseskin.value-1], colormap);
} }
@ -6610,7 +6652,7 @@ void M_DrawTimeAttackMenu(void)
if (em->collected) if (em->collected)
V_DrawMappedPatch(BASEVIDWIDTH - 64 - 24, y+48, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), V_DrawMappedPatch(BASEVIDWIDTH - 64 - 24, y+48, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE),
R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE)); R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_MENUCACHE));
else else
V_DrawScaledPatch(BASEVIDWIDTH - 64 - 24, y+48, 0, W_CachePatchName("NEEDIT", PU_CACHE)); V_DrawScaledPatch(BASEVIDWIDTH - 64 - 24, y+48, 0, W_CachePatchName("NEEDIT", PU_CACHE));
@ -6770,7 +6812,7 @@ static boolean M_QuitTimeAttackMenu(void)
if (em->collected) if (em->collected)
V_DrawSmallMappedPatch(160+88, yHeight, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), V_DrawSmallMappedPatch(160+88, yHeight, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE),
R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_CACHE)); R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_MENUCACHE));
else else
V_DrawSmallScaledPatch(160+88, yHeight, 0, W_CachePatchName("NEEDIT", PU_CACHE)); V_DrawSmallScaledPatch(160+88, yHeight, 0, W_CachePatchName("NEEDIT", PU_CACHE));
@ -7239,6 +7281,7 @@ static void M_DrawConnectMenu(void)
{ {
UINT16 i, j; UINT16 i, j;
const char *gt = "Unknown"; const char *gt = "Unknown";
const char *spd = "";
INT32 numPages = (serverlistcount+(SERVERS_PER_PAGE-1))/SERVERS_PER_PAGE; INT32 numPages = (serverlistcount+(SERVERS_PER_PAGE-1))/SERVERS_PER_PAGE;
for (i = FIRSTSERVERLINE; i < min(localservercount, SERVERS_PER_PAGE)+FIRSTSERVERLINE; i++) for (i = FIRSTSERVERLINE; i < min(localservercount, SERVERS_PER_PAGE)+FIRSTSERVERLINE; i++)
@ -7292,7 +7335,17 @@ static void M_DrawConnectMenu(void)
V_DrawSmallString(currentMenu->x+46,S_LINEY(i)+8, globalflags, V_DrawSmallString(currentMenu->x+46,S_LINEY(i)+8, globalflags,
va("Players: %02d/%02d", serverlist[slindex].info.numberofplayer, serverlist[slindex].info.maxplayer)); va("Players: %02d/%02d", serverlist[slindex].info.numberofplayer, serverlist[slindex].info.maxplayer));
V_DrawSmallString(currentMenu->x+112, S_LINEY(i)+8, globalflags, va("Gametype: %s", gt)); V_DrawSmallString(currentMenu->x+112, S_LINEY(i)+8, globalflags, gt);
if (serverlist[slindex].info.gametype == GT_RACE)
{
spd = kartspeed_cons_t[serverlist[slindex].info.kartvars & SV_SPEEDMASK].strvalue;
V_DrawSmallString(currentMenu->x+132, S_LINEY(i)+8, globalflags, va("(%s Speed)", spd));
}
if (serverlist[slindex].info.kartvars & SV_PASSWORD)
V_DrawFixedPatch((currentMenu->x - 9) << FRACBITS, (S_LINEY(i)) << FRACBITS, FRACUNIT, globalflags & (~V_ALLOWLOWERCASE), W_CachePatchName("SERVLOCK", PU_CACHE), NULL);
MP_ConnectMenu[i+FIRSTSERVERLINE].status = IT_STRING | IT_CALL; MP_ConnectMenu[i+FIRSTSERVERLINE].status = IT_STRING | IT_CALL;
} }
@ -7408,6 +7461,20 @@ static void M_ConnectMenu(INT32 choice)
M_Refresh(0); M_Refresh(0);
} }
static void M_ConnectMenuModChecks(INT32 choice)
{
(void)choice;
// okay never mind we want to COMMUNICATE to the player pre-emptively instead of letting them try and then get confused when it doesn't work
if (modifiedgame)
{
M_StartMessage(M_GetText("Add-ons are currently loaded.\n\nYou will only be able to join a server if\nit has the same ones loaded in the same order, which may be unlikely.\n\nIf you wish to play on other servers,\nrestart the game to clear existing add-ons.\n\n(Press a key)\n"),M_ConnectMenu,MM_EVENTHANDLER);
return;
}
M_ConnectMenu(-1);
}
static UINT32 roomIds[NUM_LIST_ROOMS]; static UINT32 roomIds[NUM_LIST_ROOMS];
static void M_RoomMenu(INT32 choice) static void M_RoomMenu(INT32 choice)
@ -7513,6 +7580,11 @@ static void M_StartServer(INT32 choice)
// Still need to reset devmode // Still need to reset devmode
cv_debug = 0; cv_debug = 0;
if (strlen(cv_dummyjoinpassword.string) > 0)
D_SetJoinPassword(cv_dummyjoinpassword.string);
else
joinpasswordset = false;
if (demoplayback) if (demoplayback)
G_StopDemo(); G_StopDemo();
if (metalrecording) if (metalrecording)
@ -7732,7 +7804,7 @@ static void M_StartServerMenu(INT32 choice)
// CONNECT VIA IP // CONNECT VIA IP
// ============== // ==============
static char setupm_ip[16]; static char setupm_ip[28];
#endif #endif
static UINT8 setupm_pselect = 1; static UINT8 setupm_pselect = 1;
@ -7765,12 +7837,12 @@ Update the maxplayers label...
V_DrawFill(x+5, y+4+5, /*16*8 + 6,*/ BASEVIDWIDTH - 2*(x+5), 8+6, 239); V_DrawFill(x+5, y+4+5, /*16*8 + 6,*/ BASEVIDWIDTH - 2*(x+5), 8+6, 239);
// draw name string // draw name string
V_DrawString(x+8,y+12, V_MONOSPACE, setupm_ip); V_DrawString(x+8,y+12, V_ALLOWLOWERCASE, setupm_ip);
// draw text cursor for name // draw text cursor for name
if (itemOn == 8 if (itemOn == 8
&& skullAnimCounter < 4) //blink cursor && skullAnimCounter < 4) //blink cursor
V_DrawCharacter(x+8+V_StringWidth(setupm_ip, V_MONOSPACE),y+12,'_',false); V_DrawCharacter(x+8+V_StringWidth(setupm_ip, V_ALLOWLOWERCASE),y+12,'_',false);
#endif #endif
// character bar, ripped off the color bar :V // character bar, ripped off the color bar :V
@ -7814,7 +7886,7 @@ Update the maxplayers label...
if (!trans && i > cv_splitplayers.value) if (!trans && i > cv_splitplayers.value)
trans = V_TRANSLUCENT; trans = V_TRANSLUCENT;
colmap = R_GetTranslationColormap(pskin, pcol, 0); colmap = R_GetTranslationColormap(pskin, pcol, GTC_MENUCACHE);
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, FRACUNIT, trans, facewantprefix[pskin], colmap); V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, FRACUNIT, trans, facewantprefix[pskin], colmap);
@ -7984,10 +8056,11 @@ static void M_HandleConnectIP(INT32 choice)
default: default:
l = strlen(setupm_ip); l = strlen(setupm_ip);
if (l >= 16-1) if (l >= 28-1)
break; break;
if (choice == 46 || (choice >= 48 && choice <= 57)) // Rudimentary number and period enforcing // Rudimentary number and period enforcing - also allows letters so hostnames can be used instead
if ((choice >= '-' && choice <= ':') || (choice >= 'A' && choice <= 'Z') || (choice >= 'a' && choice <= 'z'))
{ {
S_StartSound(NULL,sfx_menu1); // Tails S_StartSound(NULL,sfx_menu1); // Tails
setupm_ip[l] = (char)choice; setupm_ip[l] = (char)choice;
@ -8001,7 +8074,6 @@ static void M_HandleConnectIP(INT32 choice)
setupm_ip[l] = (char)choice; setupm_ip[l] = (char)choice;
setupm_ip[l+1] = 0; setupm_ip[l+1] = 0;
} }
break; break;
} }
@ -8125,7 +8197,7 @@ static void M_DrawSetupMultiPlayerMenu(void)
statdot = W_CachePatchName("K_SDOT2", PU_CACHE); // coloured center statdot = W_CachePatchName("K_SDOT2", PU_CACHE); // coloured center
if (setupm_fakecolor) if (setupm_fakecolor)
V_DrawFixedPatch(((BASEVIDWIDTH - mx - 80) + ((speed-1)*8))<<FRACBITS, ((my+76) + ((weight-1)*8))<<FRACBITS, FRACUNIT, 0, statdot, R_GetTranslationColormap(0, setupm_fakecolor, 0)); V_DrawFixedPatch(((BASEVIDWIDTH - mx - 80) + ((speed-1)*8))<<FRACBITS, ((my+76) + ((weight-1)*8))<<FRACBITS, FRACUNIT, 0, statdot, R_GetTranslationColormap(0, setupm_fakecolor, GTC_MENUCACHE));
// 2.2 color bar backported with permission // 2.2 color bar backported with permission
#define charw 72 #define charw 72
@ -8195,7 +8267,7 @@ static void M_DrawSetupMultiPlayerMenu(void)
offx = 8; offx = 8;
offy = 8; offy = 8;
} }
colmap = R_GetTranslationColormap(col, setupm_fakecolor, 0); colmap = R_GetTranslationColormap(col, setupm_fakecolor, GTC_MENUCACHE);
V_DrawFixedPatch((x+offx)<<FRACBITS, (my+28+offy)<<FRACBITS, FRACUNIT, 0, face, colmap); V_DrawFixedPatch((x+offx)<<FRACBITS, (my+28+offy)<<FRACBITS, FRACUNIT, 0, face, colmap);
if (scale == FRACUNIT) // bit of a hack if (scale == FRACUNIT) // bit of a hack
V_DrawFixedPatch((x+offx)<<FRACBITS, (my+28+offy)<<FRACBITS, FRACUNIT, 0, cursor, colmap); V_DrawFixedPatch((x+offx)<<FRACBITS, (my+28+offy)<<FRACBITS, FRACUNIT, 0, cursor, colmap);
@ -8241,7 +8313,7 @@ static void M_DrawSetupMultiPlayerMenu(void)
// draw player sprite // draw player sprite
if (setupm_fakecolor) // inverse should never happen if (setupm_fakecolor) // inverse should never happen
{ {
UINT8 *colormap = R_GetTranslationColormap(setupm_fakeskin, setupm_fakecolor, 0); UINT8 *colormap = R_GetTranslationColormap(setupm_fakeskin, setupm_fakecolor, GTC_MENUCACHE);
if (skins[setupm_fakeskin].flags & SF_HIRES) if (skins[setupm_fakeskin].flags & SF_HIRES)
{ {
@ -8252,8 +8324,6 @@ static void M_DrawSetupMultiPlayerMenu(void)
} }
else else
V_DrawMappedPatch(mx+43, my+131, flags, patch, colormap); V_DrawMappedPatch(mx+43, my+131, flags, patch, colormap);
Z_Free(colormap);
} }
#undef charw #undef charw
} }

View File

@ -104,6 +104,7 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt);
#define IT_CV_NOPRINT 1536 #define IT_CV_NOPRINT 1536
#define IT_CV_NOMOD 2048 #define IT_CV_NOMOD 2048
#define IT_CV_INVISSLIDER 2560 #define IT_CV_INVISSLIDER 2560
#define IT_CV_PASSWORD 3072
//call/submenu specific //call/submenu specific
// There used to be a lot more here but ... // There used to be a lot more here but ...
@ -150,7 +151,7 @@ typedef struct menuitem_s
UINT8 alphaKey; UINT8 alphaKey;
} menuitem_t; } menuitem_t;
extern menuitem_t PlayerMenu[32]; extern menuitem_t PlayerMenu[MAXSKINS];
typedef struct menu_s typedef struct menu_s
{ {
@ -211,6 +212,7 @@ typedef struct
extern description_t description[32]; extern description_t description[32];
extern consvar_t cv_showfocuslost;
extern consvar_t cv_newgametype, cv_nextmap, cv_chooseskin, cv_serversort; extern consvar_t cv_newgametype, cv_nextmap, cv_chooseskin, cv_serversort;
extern CV_PossibleValue_t gametype_cons_t[]; extern CV_PossibleValue_t gametype_cons_t[];

View File

@ -93,7 +93,8 @@ typedef off_t off64_t;
#ifdef PNG_WRITE_SUPPORTED #ifdef PNG_WRITE_SUPPORTED
#define USE_PNG // Only actually use PNG if write is supported. #define USE_PNG // Only actually use PNG if write is supported.
#if defined (PNG_WRITE_APNG_SUPPORTED) //|| !defined(PNG_STATIC) #if defined (PNG_WRITE_APNG_SUPPORTED) //|| !defined(PNG_STATIC)
#define USE_APNG #include "apng.h"
#define USE_APNG
#endif #endif
// See hardware/hw_draw.c for a similar check to this one. // See hardware/hw_draw.c for a similar check to this one.
#endif #endif
@ -793,13 +794,13 @@ static inline void M_PNGImage(png_structp png_ptr, png_infop png_info_ptr, PNG_C
#ifdef USE_APNG #ifdef USE_APNG
static png_structp apng_ptr = NULL; static png_structp apng_ptr = NULL;
static png_infop apng_info_ptr = NULL; static png_infop apng_info_ptr = NULL;
static apng_infop apng_ainfo_ptr = NULL;
static png_FILE_p apng_FILE = NULL; static png_FILE_p apng_FILE = NULL;
static png_uint_32 apng_frames = 0; static png_uint_32 apng_frames = 0;
static png_byte acTL_cn[5] = { 97, 99, 84, 76, '\0'};
#ifdef PNG_STATIC // Win32 build have static libpng #ifdef PNG_STATIC // Win32 build have static libpng
#define apng_set_acTL png_set_acTL #define aPNG_set_acTL png_set_acTL
#define apng_write_frame_head png_write_frame_head #define aPNG_write_frame_head png_write_frame_head
#define apng_write_frame_tail png_write_frame_tail #define aPNG_write_frame_tail png_write_frame_tail
#else // outside libpng may not have apng support #else // outside libpng may not have apng support
#ifndef PNG_WRITE_APNG_SUPPORTED // libpng header may not have apng patch #ifndef PNG_WRITE_APNG_SUPPORTED // libpng header may not have apng patch
@ -836,20 +837,20 @@ static png_byte acTL_cn[5] = { 97, 99, 84, 76, '\0'};
#endif #endif
#endif #endif
typedef PNG_EXPORT(png_uint_32, (*P_png_set_acTL)) PNGARG((png_structp png_ptr, typedef png_uint_32 (*P_png_set_acTL) (png_structp png_ptr,
png_infop info_ptr, png_uint_32 num_frames, png_uint_32 num_plays)); png_infop info_ptr, png_uint_32 num_frames, png_uint_32 num_plays);
typedef PNG_EXPORT (void, (*P_png_write_frame_head)) PNGARG((png_structp png_ptr, typedef void (*P_png_write_frame_head) (png_structp png_ptr,
png_infop info_ptr, png_bytepp row_pointers, png_infop info_ptr, png_bytepp row_pointers,
png_uint_32 width, png_uint_32 height, png_uint_32 width, png_uint_32 height,
png_uint_32 x_offset, png_uint_32 y_offset, png_uint_32 x_offset, png_uint_32 y_offset,
png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
png_byte blend_op)); png_byte blend_op);
typedef PNG_EXPORT (void, (*P_png_write_frame_tail)) PNGARG((png_structp png_ptr, typedef void (*P_png_write_frame_tail) (png_structp png_ptr,
png_infop info_ptr)); png_infop info_ptr);
static P_png_set_acTL apng_set_acTL = NULL; static P_png_set_acTL aPNG_set_acTL = NULL;
static P_png_write_frame_head apng_write_frame_head = NULL; static P_png_write_frame_head aPNG_write_frame_head = NULL;
static P_png_write_frame_tail apng_write_frame_tail = NULL; static P_png_write_frame_tail aPNG_write_frame_tail = NULL;
#endif #endif
static inline boolean M_PNGLib(void) static inline boolean M_PNGLib(void)
@ -858,7 +859,7 @@ static inline boolean M_PNGLib(void)
return true; return true;
#else #else
static void *pnglib = NULL; static void *pnglib = NULL;
if (apng_set_acTL && apng_write_frame_head && apng_write_frame_tail) if (aPNG_set_acTL && aPNG_write_frame_head && aPNG_write_frame_tail)
return true; return true;
if (pnglib) if (pnglib)
return false; return false;
@ -878,16 +879,16 @@ static inline boolean M_PNGLib(void)
if (!pnglib) if (!pnglib)
return false; return false;
#ifdef HAVE_SDL #ifdef HAVE_SDL
apng_set_acTL = hwSym("png_set_acTL", pnglib); aPNG_set_acTL = hwSym("png_set_acTL", pnglib);
apng_write_frame_head = hwSym("png_write_frame_head", pnglib); aPNG_write_frame_head = hwSym("png_write_frame_head", pnglib);
apng_write_frame_tail = hwSym("png_write_frame_tail", pnglib); aPNG_write_frame_tail = hwSym("png_write_frame_tail", pnglib);
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
apng_set_acTL = GetProcAddress("png_set_acTL", pnglib); aPNG_set_acTL = GetProcAddress("png_set_acTL", pnglib);
apng_write_frame_head = GetProcAddress("png_write_frame_head", pnglib); aPNG_write_frame_head = GetProcAddress("png_write_frame_head", pnglib);
apng_write_frame_tail = GetProcAddress("png_write_frame_tail", pnglib); aPNG_write_frame_tail = GetProcAddress("png_write_frame_tail", pnglib);
#endif #endif
return (apng_set_acTL && apng_write_frame_head && apng_write_frame_tail); return (aPNG_set_acTL && aPNG_write_frame_head && aPNG_write_frame_tail);
#endif #endif
} }
@ -901,11 +902,6 @@ static void M_PNGFrame(png_structp png_ptr, png_infop png_info_ptr, png_bytep pn
apng_frames++; apng_frames++;
#ifndef PNG_STATIC
if (apng_set_acTL)
#endif
apng_set_acTL(apng_ptr, apng_info_ptr, apng_frames, 0);
for (y = 0; y < height; y++) for (y = 0; y < height; y++)
{ {
row_pointers[y] = png_buf; row_pointers[y] = png_buf;
@ -913,9 +909,9 @@ static void M_PNGFrame(png_structp png_ptr, png_infop png_info_ptr, png_bytep pn
} }
#ifndef PNG_STATIC #ifndef PNG_STATIC
if (apng_write_frame_head) if (aPNG_write_frame_head)
#endif #endif
apng_write_frame_head(apng_ptr, apng_info_ptr, row_pointers, aPNG_write_frame_head(apng_ptr, apng_info_ptr, row_pointers,
vid.width, /* width */ vid.width, /* width */
height, /* height */ height, /* height */
0, /* x offset */ 0, /* x offset */
@ -928,57 +924,21 @@ static void M_PNGFrame(png_structp png_ptr, png_infop png_info_ptr, png_bytep pn
png_write_image(png_ptr, row_pointers); png_write_image(png_ptr, row_pointers);
#ifndef PNG_STATIC #ifndef PNG_STATIC
if (apng_write_frame_tail) if (aPNG_write_frame_tail)
#endif #endif
apng_write_frame_tail(apng_ptr, apng_info_ptr); aPNG_write_frame_tail(apng_ptr, apng_info_ptr);
png_free(png_ptr, (png_voidp)row_pointers); png_free(png_ptr, (png_voidp)row_pointers);
} }
static inline boolean M_PNGfind_acTL(void) static void M_PNGfix_acTL(png_structp png_ptr, png_infop png_info_ptr,
apng_infop png_ainfo_ptr)
{ {
png_byte cn[8]; // 4 bytes for len then 4 byes for name apng_set_acTL(png_ptr, png_info_ptr, png_ainfo_ptr, apng_frames, 0);
long endpos = ftell(apng_FILE); // not the real end of file, just what of libpng wrote
for (fseek(apng_FILE, 0, SEEK_SET); // let go to the start of the file
ftell(apng_FILE)+12 < endpos; // let not go over the file bound
fseek(apng_FILE, 1, SEEK_CUR) // we went 8 steps back and now we go 1 step forward
)
{
if (fread(cn, sizeof(cn), 1, apng_FILE) != 1) // read 8 bytes
return false; // failed to read data
if (fseek(apng_FILE, -8, SEEK_CUR) != 0) //rewind 8 bytes
return false; // failed to rewird
if (!png_memcmp(cn+4, acTL_cn, 4)) //cmp for chuck header
return true; // found it
}
return false; // acTL chuck not found
}
static void M_PNGfix_acTL(png_structp png_ptr, png_infop png_info_ptr)
{
png_byte data[16];
long oldpos;
#ifndef PNG_STATIC
if (apng_set_acTL)
#endif
apng_set_acTL(png_ptr, png_info_ptr, apng_frames, 0);
#ifndef NO_PNG_DEBUG #ifndef NO_PNG_DEBUG
png_debug(1, "in png_write_acTL\n"); png_debug(1, "in png_write_acTL\n");
#endif #endif
png_ptr->num_frames_to_write = apng_frames;
png_save_uint_32(data, apng_frames);
png_save_uint_32(data + 4, 0);
oldpos = ftell(apng_FILE);
if (M_PNGfind_acTL())
png_write_chunk(png_ptr, (png_bytep)acTL_cn, data, (png_size_t)8);
fseek(apng_FILE, oldpos, SEEK_SET);
} }
static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal) static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal)
@ -1010,6 +970,16 @@ static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal)
return false; return false;
} }
apng_ainfo_ptr = apng_create_info_struct(apng_ptr);
if (!apng_ainfo_ptr)
{
CONS_Debug(DBG_RENDER, "M_StartMovie: Error on allocate for apng\n");
png_destroy_write_struct(&apng_ptr, &apng_info_ptr);
fclose(apng_FILE);
remove(filename);
return false;
}
png_init_io(apng_ptr, apng_FILE); png_init_io(apng_ptr, apng_FILE);
#ifdef PNG_SET_USER_LIMITS_SUPPORTED #ifdef PNG_SET_USER_LIMITS_SUPPORTED
@ -1027,12 +997,11 @@ static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal)
M_PNGText(apng_ptr, apng_info_ptr, true); M_PNGText(apng_ptr, apng_info_ptr, true);
#ifndef PNG_STATIC apng_set_set_acTL_fn(apng_ptr, apng_ainfo_ptr, aPNG_set_acTL);
if (apng_set_acTL)
#endif
apng_set_acTL(apng_ptr, apng_info_ptr, PNG_UINT_31_MAX, 0);
png_write_info(apng_ptr, apng_info_ptr); apng_set_acTL(apng_ptr, apng_info_ptr, apng_ainfo_ptr, PNG_UINT_31_MAX, 0);
apng_write_info(apng_ptr, apng_info_ptr, apng_ainfo_ptr);
apng_frames = 0; apng_frames = 0;
@ -1235,8 +1204,8 @@ void M_StopMovie(void)
if (apng_frames) if (apng_frames)
{ {
M_PNGfix_acTL(apng_ptr, apng_info_ptr); M_PNGfix_acTL(apng_ptr, apng_info_ptr, apng_ainfo_ptr);
png_write_end(apng_ptr, apng_info_ptr); apng_write_end(apng_ptr, apng_info_ptr, apng_ainfo_ptr);
} }
png_destroy_write_struct(&apng_ptr, &apng_info_ptr); png_destroy_write_struct(&apng_ptr, &apng_info_ptr);

View File

@ -22,6 +22,8 @@
# include <limits.h> # include <limits.h>
#endif #endif
#define MD5_LEN 16
/* The following contortions are an attempt to use the C preprocessor /* The following contortions are an attempt to use the C preprocessor
to determine an unsigned integral type that is 32 bits wide. An to determine an unsigned integral type that is 32 bits wide. An
alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but

View File

@ -8264,8 +8264,8 @@ void A_JawzChase(mobj_t *actor)
if (actor->tracer) if (actor->tracer)
{ {
if (G_RaceGametype()) // Stop looking after first target in race /*if (G_RaceGametype()) // Stop looking after first target in race
actor->extravalue1 = 1; actor->extravalue1 = 1;*/
if (actor->tracer->health) if (actor->tracer->health)
{ {
@ -8364,13 +8364,13 @@ void A_SPBChase(mobj_t *actor)
if (!playeringame[i] || players[i].spectator || players[i].exiting) if (!playeringame[i] || players[i].spectator || players[i].exiting)
continue; // not in-game continue; // not in-game
if (!players[i].mo) /*if (!players[i].mo)
continue; // no mobj continue; // no mobj
if (players[i].mo->health <= 0) if (players[i].mo->health <= 0)
continue; // dead continue; // dead
/*if (players[i].kartstuff[k_respawn]) if (players[i].kartstuff[k_respawn])
continue;*/ // respawning continue;*/ // respawning
if (players[i].kartstuff[k_position] < bestrank) if (players[i].kartstuff[k_position] < bestrank)
@ -8386,18 +8386,35 @@ void A_SPBChase(mobj_t *actor)
{ {
fixed_t defspeed = wspeed; fixed_t defspeed = wspeed;
fixed_t range = (160*actor->tracer->scale); fixed_t range = (160*actor->tracer->scale);
fixed_t cx = 0, cy =0;
// Play the intimidating gurgle
if (!S_SoundPlaying(actor, actor->info->activesound))
S_StartSound(actor, actor->info->activesound);
// Maybe we want SPB to target an object later? IDK lol // Maybe we want SPB to target an object later? IDK lol
if (actor->tracer->player) // 7/8ths max speed for Knuckles, 3/4ths max speed for min accel, exactly max speed for max accel if (actor->tracer->player)
{ {
UINT8 fracmax = 32;
UINT8 spark = ((10-actor->tracer->player->kartspeed) + actor->tracer->player->kartweight) / 2;
fixed_t easiness = ((actor->tracer->player->kartspeed + (10-spark)) << FRACBITS) / 2;
actor->lastlook = actor->tracer->player-players; // Save the player num for death scumming... actor->lastlook = actor->tracer->player-players; // Save the player num for death scumming...
if (!P_IsObjectOnGround(actor->tracer) /*&& !actor->tracer->player->kartstuff[k_pogospring]*/) if (!P_IsObjectOnGround(actor->tracer) /*&& !actor->tracer->player->kartstuff[k_pogospring]*/)
defspeed = (7*actor->tracer->player->speed)/8; // In the air you have no control; basically don't hit unless you make a near complete stop {
// In the air you have no control; basically don't hit unless you make a near complete stop
defspeed = (7 * actor->tracer->player->speed) / 8;
}
else else
defspeed = ((33 - actor->tracer->player->kartspeed) * K_GetKartSpeed(actor->tracer->player, false)) / 32; {
// 7/8ths max speed for Knuckles, 3/4ths max speed for min accel, exactly max speed for max accel
defspeed = FixedMul(((fracmax+1)<<FRACBITS) - easiness, K_GetKartSpeed(actor->tracer->player, false)) / fracmax;
}
defspeed -= (9*R_PointToDist2(0, 0, actor->tracer->player->cmomx, actor->tracer->player->cmomy))/8; // Be fairer on conveyors // Be fairer on conveyors
cx = actor->tracer->player->cmomx;
cy = actor->tracer->player->cmomy;
// Switch targets if you're no longer 1st for long enough // Switch targets if you're no longer 1st for long enough
if (actor->tracer->player->kartstuff[k_position] <= bestrank) if (actor->tracer->player->kartstuff[k_position] <= bestrank)
@ -8408,10 +8425,6 @@ void A_SPBChase(mobj_t *actor)
spbplace = actor->tracer->player->kartstuff[k_position]; spbplace = actor->tracer->player->kartstuff[k_position];
} }
// Play the intimidating gurgle
if (!S_SoundPlaying(actor, actor->info->activesound))
S_StartSound(actor, actor->info->activesound);
dist = P_AproxDistance(P_AproxDistance(actor->x-actor->tracer->x, actor->y-actor->tracer->y), actor->z-actor->tracer->z); dist = P_AproxDistance(P_AproxDistance(actor->x-actor->tracer->x, actor->y-actor->tracer->y), actor->z-actor->tracer->z);
wspeed = FixedMul(defspeed, FRACUNIT + FixedDiv(dist-range, range)); wspeed = FixedMul(defspeed, FRACUNIT + FixedDiv(dist-range, range));
@ -8419,10 +8432,18 @@ void A_SPBChase(mobj_t *actor)
wspeed = defspeed; wspeed = defspeed;
if (wspeed > (3*defspeed)/2) if (wspeed > (3*defspeed)/2)
wspeed = (3*defspeed)/2; wspeed = (3*defspeed)/2;
if (wspeed < 20*actor->tracer->scale)
wspeed = 20*actor->tracer->scale;
hang = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y); hang = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y);
vang = R_PointToAngle2(0, actor->z, dist, actor->tracer->z); vang = R_PointToAngle2(0, actor->z, dist, actor->tracer->z);
// Modify stored speed
if (wspeed > actor->cvmem)
actor->cvmem += (wspeed - actor->cvmem) / TICRATE;
else
actor->cvmem = wspeed;
{ {
// Smoothly rotate horz angle // Smoothly rotate horz angle
angle_t input = hang - actor->angle; angle_t input = hang - actor->angle;
@ -8431,7 +8452,7 @@ void A_SPBChase(mobj_t *actor)
input = InvAngle(input); input = InvAngle(input);
// Slow down when turning; it looks better and makes U-turns not unfair // Slow down when turning; it looks better and makes U-turns not unfair
xyspeed = FixedMul(wspeed, max(0, (((180<<FRACBITS) - AngleFixed(input)) / 90) - FRACUNIT)); xyspeed = FixedMul(actor->cvmem, max(0, (((180<<FRACBITS) - AngleFixed(input)) / 90) - FRACUNIT));
input = FixedAngle(AngleFixed(input)/4); input = FixedAngle(AngleFixed(input)/4);
if (invert) if (invert)
@ -8446,7 +8467,7 @@ void A_SPBChase(mobj_t *actor)
input = InvAngle(input); input = InvAngle(input);
// Slow down when turning; might as well do it for momz, since we do it above too // Slow down when turning; might as well do it for momz, since we do it above too
zspeed = FixedMul(wspeed, max(0, (((180<<FRACBITS) - AngleFixed(input)) / 90) - FRACUNIT)); zspeed = FixedMul(actor->cvmem, max(0, (((180<<FRACBITS) - AngleFixed(input)) / 90) - FRACUNIT));
input = FixedAngle(AngleFixed(input)/4); input = FixedAngle(AngleFixed(input)/4);
if (invert) if (invert)
@ -8455,8 +8476,8 @@ void A_SPBChase(mobj_t *actor)
actor->movedir += input; actor->movedir += input;
} }
actor->momx = FixedMul(FixedMul(xyspeed, FINECOSINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); actor->momx = cx + FixedMul(FixedMul(xyspeed, FINECOSINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT));
actor->momy = FixedMul(FixedMul(xyspeed, FINESINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); actor->momy = cy + FixedMul(FixedMul(xyspeed, FINESINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT));
actor->momz = FixedMul(zspeed, FINESINE(actor->movedir>>ANGLETOFINESHIFT)); actor->momz = FixedMul(zspeed, FINESINE(actor->movedir>>ANGLETOFINESHIFT));
// Red speed lines for when it's gaining on its target. A tell for when you're starting to lose too much speed! // Red speed lines for when it's gaining on its target. A tell for when you're starting to lose too much speed!
@ -8491,15 +8512,18 @@ void A_SPBChase(mobj_t *actor)
{ {
actor->momx = actor->momy = actor->momz = 0; // Stoooop actor->momx = actor->momy = actor->momz = 0; // Stoooop
if (actor->lastlook != -1 && playeringame[actor->lastlook] && players[actor->lastlook].mo) if (actor->lastlook != -1
&& playeringame[actor->lastlook]
&& !players[actor->lastlook].spectator
&& !players[actor->lastlook].exiting)
{ {
spbplace = players[actor->lastlook].kartstuff[k_position]; spbplace = players[actor->lastlook].kartstuff[k_position];
if (actor->extravalue2-- <= 0) if (actor->extravalue2-- <= 0 && players[actor->lastlook].mo)
{ {
P_SetTarget(&actor->tracer, players[actor->lastlook].mo); P_SetTarget(&actor->tracer, players[actor->lastlook].mo);
actor->extravalue1 = 1; // TARGETING actor->extravalue1 = 1; // TARGET ACQUIRED
actor->extravalue2 = 7*TICRATE; actor->extravalue2 = 7*TICRATE;
actor->extravalue2 = 0; actor->cvmem = wspeed;
} }
} }
else else
@ -8513,22 +8537,12 @@ void A_SPBChase(mobj_t *actor)
{ {
actor->lastlook = -1; // Just make sure this is reset actor->lastlook = -1; // Just make sure this is reset
// No one there? if (!player || !player->mo || player->mo->health <= 0 || player->kartstuff[k_respawn])
if (player == NULL || !player->mo)
{ {
#if 0 // No one there? Completely STOP.
// SELF-DESTRUCT?
mobj_t *spbexplode;
S_StopSound(actor); // Don't continue playing the gurgle or the siren
spbexplode = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SPBEXPLOSION);
P_SetTarget(&spbexplode->target, actor->target);
P_RemoveMobj(actor);
#else
actor->momx = actor->momy = actor->momz = 0; actor->momx = actor->momy = actor->momz = 0;
#endif if (!player)
spbplace = -1; spbplace = -1;
return; return;
} }
@ -8582,6 +8596,7 @@ void A_SPBChase(mobj_t *actor)
S_StartSound(actor, actor->info->attacksound); // Siren sound; might not need this anymore, but I'm keeping it for now just for debugging. S_StartSound(actor, actor->info->attacksound); // Siren sound; might not need this anymore, but I'm keeping it for now just for debugging.
actor->extravalue1 = 1; // TARGET ACQUIRED actor->extravalue1 = 1; // TARGET ACQUIRED
actor->extravalue2 = 7*TICRATE; actor->extravalue2 = 7*TICRATE;
actor->cvmem = wspeed;
} }
} }
@ -8625,6 +8640,7 @@ void A_LightningFollowPlayer(mobj_t *actor)
else // else just teleport to player directly else // else just teleport to player directly
P_TeleportMove(actor, actor->target->x, actor->target->y, actor->target->z); P_TeleportMove(actor, actor->target->x, actor->target->y, actor->target->z);
K_MatchGenericExtraFlags(actor, actor->target); // copy our target for graviflip
actor->momx = actor->target->momx; actor->momx = actor->target->momx;
actor->momy = actor->target->momy; actor->momy = actor->target->momy;
actor->momz = actor->target->momz; // Give momentum since we don't teleport to our player literally every frame. actor->momz = actor->target->momz; // Give momentum since we don't teleport to our player literally every frame.

View File

@ -141,6 +141,9 @@ boolean P_CanPickupItem(player_t *player, UINT8 weapon)
|| (weapon != 3 && player->kartstuff[k_itemamount]) || (weapon != 3 && player->kartstuff[k_itemamount])
|| player->kartstuff[k_itemheld]) || player->kartstuff[k_itemheld])
return false; return false;
if (weapon == 3 && player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD)
return false; // No stacking thunder shields!
} }
} }
@ -411,6 +414,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
player->kartstuff[k_roulettetype] = 2; player->kartstuff[k_roulettetype] = 2;
} }
#if 0
// Eggbox snipe!
if (special->type == MT_EGGMANITEM && special->health > 1)
S_StartSound(toucher, sfx_bsnipe);
#endif
{ {
mobj_t *poof = P_SpawnMobj(special->x, special->y, special->z, MT_EXPLODE); mobj_t *poof = P_SpawnMobj(special->x, special->y, special->z, MT_EXPLODE);
S_StartSound(poof, special->info->deathsound); S_StartSound(poof, special->info->deathsound);
@ -579,30 +588,31 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (special->health <= 0 || toucher->health <= 0) if (special->health <= 0 || toucher->health <= 0)
return; return;
if (!player->mo || player->spectator) if (player->spectator)
return; return;
if (special->tracer && toucher == special->tracer) if (special->tracer && !P_MobjWasRemoved(special->tracer) && toucher == special->tracer)
{ {
mobj_t *spbexplode; mobj_t *spbexplode;
S_StopSound(special); // Don't continue playing the gurgle or the siren if (player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0)
if (!player->kartstuff[k_invincibilitytimer] && !player->kartstuff[k_growshrinktimer])
{ {
//player->powers[pw_flashing] = 0;
K_DropHnextList(player); K_DropHnextList(player);
K_StripItems(player); K_StripItems(player);
//player->powers[pw_flashing] = 0;
} }
S_StopSound(special); // Don't continue playing the gurgle or the siren
spbexplode = P_SpawnMobj(toucher->x, toucher->y, toucher->z, MT_SPBEXPLOSION); spbexplode = P_SpawnMobj(toucher->x, toucher->y, toucher->z, MT_SPBEXPLOSION);
spbexplode->extravalue1 = 1; // Tell K_ExplodePlayer to use extra knockback spbexplode->extravalue1 = 1; // Tell K_ExplodePlayer to use extra knockback
P_SetTarget(&spbexplode->target, special->target); if (special->target && !P_MobjWasRemoved(special->target))
P_SetTarget(&spbexplode->target, special->target);
P_RemoveMobj(special); P_RemoveMobj(special);
} }
else else
K_SpinPlayer(player, NULL, 0, special, false); K_SpinPlayer(player, special->target, 0, special, false);
return; return;
/*case MT_EERIEFOG: /*case MT_EERIEFOG:
special->frame &= ~FF_TRANS80; special->frame &= ~FF_TRANS80;
@ -1467,6 +1477,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
player->starpostz = special->z>>FRACBITS; player->starpostz = special->z>>FRACBITS;
player->starpostangle = special->angle; player->starpostangle = special->angle;
player->starpostnum = special->health; player->starpostnum = special->health;
player->kartstuff[k_starpostflip] = special->spawnpoint->options & MTF_OBJECTFLIP; // store flipping
//S_StartSound(toucher, special->info->painsound); //S_StartSound(toucher, special->info->painsound);
return; return;
@ -2951,66 +2962,6 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
} }
} }
/*
static inline void P_SuperDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage) // SRB2kart - unused.
{
fixed_t fallbackspeed;
angle_t ang;
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
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);
ang = R_PointToAngle2(inflictor->x, inflictor->y, player->mo->x, player->mo->y);
// 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(28*FRACUNIT, inflictor->scale); // 7x
else
fallbackspeed = FixedMul(20*FRACUNIT, inflictor->scale); // 5x
}
else if (inflictor->flags2 & MF2_RAILRING)
fallbackspeed = FixedMul(16*FRACUNIT, inflictor->scale); // 4x
else
fallbackspeed = FixedMul(4*FRACUNIT, inflictor->scale); // the usual amount of force
P_InstaThrust(player->mo, ang, fallbackspeed);
// SRB2kart - This shouldn't be reachable, but this frame is invalid.
//if (player->charflags & SF_SUPERANIMS)
// P_SetPlayerMobjState(player->mo, S_PLAY_SUPERHIT);
//else
P_SetPlayerMobjState(player->mo, player->mo->info->painstate);
P_ResetPlayer(player);
if (player->timeshit != UINT8_MAX)
++player->timeshit;
}
*/
void P_RemoveShield(player_t *player) void P_RemoveShield(player_t *player)
{ {
if (player->powers[pw_shield] & SH_FORCE) if (player->powers[pw_shield] & SH_FORCE)

View File

@ -128,7 +128,6 @@ extern fixed_t t_cam4_dist, t_cam4_height, t_cam4_rotate;
fixed_t P_GetPlayerHeight(player_t *player); fixed_t P_GetPlayerHeight(player_t *player);
fixed_t P_GetPlayerSpinHeight(player_t *player); fixed_t P_GetPlayerSpinHeight(player_t *player);
INT32 P_GetPlayerControlDirection(player_t *player);
void P_AddPlayerScore(player_t *player, UINT32 amount); void P_AddPlayerScore(player_t *player, UINT32 amount);
void P_ResetCamera(player_t *player, camera_t *thiscam); void P_ResetCamera(player_t *player, camera_t *thiscam);
boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam); boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam);
@ -275,8 +274,6 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
void P_Attract(mobj_t *source, mobj_t *enemy, boolean nightsgrab); void P_Attract(mobj_t *source, mobj_t *enemy, boolean nightsgrab);
mobj_t *P_GetClosestAxis(mobj_t *source); mobj_t *P_GetClosestAxis(mobj_t *source);
boolean P_CanRunOnWater(player_t *player, ffloor_t *rover);
void P_FlashPal(player_t *pl, UINT16 type, UINT16 duration); void P_FlashPal(player_t *pl, UINT16 type, UINT16 duration);
#define PAL_WHITE 1 #define PAL_WHITE 1
#define PAL_MIXUP 2 #define PAL_MIXUP 2

View File

@ -747,14 +747,15 @@ static boolean PIT_CheckThing(mobj_t *thing)
&& !(tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD)) && !(tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD))
return true; return true;
if (thing->player && thing->player->kartstuff[k_hyudorotimer])
return true; // no interaction
if (thing->type == MT_PLAYER) if (thing->type == MT_PLAYER)
{ {
// Player Damage // Player Damage
P_DamageMobj(thing, tmthing, tmthing->target, 1); P_DamageMobj(thing, tmthing, tmthing->target, 1);
K_KartBouncing(thing, tmthing, false, false); K_KartBouncing(thing, tmthing, false, false);
S_StartSound(thing, sfx_s3k7b);
if (tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD)
S_StartSound(thing, sfx_s3k7b);
// This Item Damage // This Item Damage
if (tmthing->eflags & MFE_VERTICALFLIP) if (tmthing->eflags & MFE_VERTICALFLIP)
@ -852,7 +853,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->type == MT_PLAYER) if (thing->type == MT_PLAYER)
{ {
S_StartSound(NULL, sfx_cgot); //let all players hear it. S_StartSound(NULL, sfx_bsnipe); //let all players hear it.
HU_SetCEchoFlags(0); HU_SetCEchoFlags(0);
HU_SetCEchoDuration(5); HU_SetCEchoDuration(5);
HU_DoCEcho(va("%s\\was hit by a kitchen sink.\\\\\\\\", player_names[thing->player-players])); HU_DoCEcho(va("%s\\was hit by a kitchen sink.\\\\\\\\", player_names[thing->player-players]));
@ -914,6 +915,10 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->type == MT_PLAYER) if (thing->type == MT_PLAYER)
{ {
// Banana snipe!
if (tmthing->type == MT_BANANA && tmthing->health > 1)
S_StartSound(thing, sfx_bsnipe);
// Player Damage // Player Damage
K_SpinPlayer(thing->player, tmthing->target, 0, tmthing, (tmthing->type == MT_BANANA || tmthing->type == MT_BANANA_SHIELD)); K_SpinPlayer(thing->player, tmthing->target, 0, tmthing, (tmthing->type == MT_BANANA || tmthing->type == MT_BANANA_SHIELD));
@ -982,7 +987,12 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->type == MT_PLAYER) if (thing->type == MT_PLAYER)
{ {
P_KillMobj(tmthing, thing, thing); // Bomb punting
if ((tmthing->state >= &states[S_SSMINE1] && tmthing->state <= &states[S_SSMINE4])
|| (tmthing->state >= &states[S_SSMINE_DEPLOY8] && tmthing->state <= &states[S_SSMINE_DEPLOY13]))
P_KillMobj(tmthing, thing, thing);
else
K_PuntMine(tmthing, thing);
} }
else if (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD else if (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD
|| thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD) || thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD)
@ -1023,6 +1033,9 @@ static boolean PIT_CheckThing(mobj_t *thing)
&& !(thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD)) && !(thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD))
return true; return true;
if (tmthing->player && tmthing->player->kartstuff[k_hyudorotimer]) // I thought about doing this for just the objects below but figured it should apply to everything.
return true; // no interaction
if (thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD if (thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD
|| thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD) || thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD)
{ {
@ -1035,9 +1048,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
// Player Damage // Player Damage
P_DamageMobj(tmthing, thing, thing->target, 1); P_DamageMobj(tmthing, thing, thing->target, 1);
K_KartBouncing(tmthing, thing, false, false); K_KartBouncing(tmthing, thing, false, false);
S_StartSound(tmthing, sfx_s3k7b);
if (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD)
S_StartSound(tmthing, sfx_s3k7b);
// Other Item Damage // Other Item Damage
if (thing->eflags & MFE_VERTICALFLIP) if (thing->eflags & MFE_VERTICALFLIP)
@ -1060,6 +1071,10 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (tmthing->health <= 0 || thing->health <= 0) if (tmthing->health <= 0 || thing->health <= 0)
return true; return true;
// Banana snipe!
if (thing->type == MT_BANANA && thing->health > 1)
S_StartSound(tmthing, sfx_bsnipe);
// Player Damage // Player Damage
K_SpinPlayer(tmthing->player, thing->target, 0, tmthing, (thing->type == MT_BANANA || thing->type == MT_BANANA_SHIELD)); K_SpinPlayer(tmthing->player, thing->target, 0, tmthing, (thing->type == MT_BANANA || thing->type == MT_BANANA_SHIELD));
@ -1083,7 +1098,12 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (tmthing->health <= 0 || thing->health <= 0) if (tmthing->health <= 0 || thing->health <= 0)
return true; return true;
P_KillMobj(thing, tmthing, tmthing); // Bomb punting
if ((thing->state >= &states[S_SSMINE1] && thing->state <= &states[S_SSMINE4])
|| (thing->state >= &states[S_SSMINE_DEPLOY8] && thing->state <= &states[S_SSMINE_DEPLOY13]))
P_KillMobj(thing, tmthing, tmthing);
else
K_PuntMine(thing, tmthing);
} }
else if (thing->type == MT_MINEEXPLOSION && tmthing->player) else if (thing->type == MT_MINEEXPLOSION && tmthing->player)
{ {
@ -2094,7 +2114,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
continue; continue;
} }
if (thing->player && (P_CheckSolidLava(thing, rover) || P_CanRunOnWater(thing->player, rover))) if (thing->player && P_CheckSolidLava(thing, rover))
; ;
else if (thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE)) else if (thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE))
; ;
@ -2767,8 +2787,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
thing->eflags |= MFE_JUSTSTEPPEDDOWN; thing->eflags |= MFE_JUSTSTEPPEDDOWN;
} }
#ifdef ESLOPE #ifdef ESLOPE
// HACK TO FIX DSZ2: apply only if slopes are involved else if (tmceilingz < thingtop && thingtop - tmceilingz <= maxstep)
else if (tmceilingslope && tmceilingz < thingtop && thingtop - tmceilingz <= maxstep)
{ {
thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height; thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height;
thing->eflags |= MFE_JUSTSTEPPEDDOWN; thing->eflags |= MFE_JUSTSTEPPEDDOWN;
@ -2781,8 +2800,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
thing->eflags |= MFE_JUSTSTEPPEDDOWN; thing->eflags |= MFE_JUSTSTEPPEDDOWN;
} }
#ifdef ESLOPE #ifdef ESLOPE
// HACK TO FIX DSZ2: apply only if slopes are involved else if (tmfloorz > thing->z && tmfloorz - thing->z <= maxstep)
else if (tmfloorslope && tmfloorz > thing->z && tmfloorz - thing->z <= maxstep)
{ {
thing->z = thing->floorz = tmfloorz; thing->z = thing->floorz = tmfloorz;
thing->eflags |= MFE_JUSTSTEPPEDDOWN; thing->eflags |= MFE_JUSTSTEPPEDDOWN;
@ -3231,129 +3249,6 @@ isblocking:
return false; // stop return false; // stop
} }
//
// P_IsClimbingValid
//
// Unlike P_DoClimbing, don't use when up against a one-sided linedef.
//
static boolean P_IsClimbingValid(player_t *player, angle_t angle)
{
fixed_t platx, platy;
subsector_t *glidesector;
fixed_t floorz, ceilingz;
platx = P_ReturnThrustX(player->mo, angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale));
platy = P_ReturnThrustY(player->mo, angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale));
glidesector = R_PointInSubsector(player->mo->x + platx, player->mo->y + platy);
#ifdef ESLOPE
floorz = glidesector->sector->f_slope ? P_GetZAt(glidesector->sector->f_slope, player->mo->x, player->mo->y) : glidesector->sector->floorheight;
ceilingz = glidesector->sector->c_slope ? P_GetZAt(glidesector->sector->c_slope, player->mo->x, player->mo->y) : glidesector->sector->ceilingheight;
#else
floorz = glidesector->sector->floorheight;
ceilingz = glidesector->sector->ceilingheight;
#endif
if (glidesector->sector != player->mo->subsector->sector)
{
boolean floorclimb = false;
fixed_t topheight, bottomheight;
if (glidesector->sector->ffloors)
{
ffloor_t *rover;
for (rover = glidesector->sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER))
continue;
topheight = *rover->topheight;
bottomheight = *rover->bottomheight;
#ifdef ESLOPE
if (*rover->t_slope)
topheight = P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y);
if (*rover->b_slope)
bottomheight = P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y);
#endif
floorclimb = true;
if (player->mo->eflags & MFE_VERTICALFLIP)
{
if ((topheight < player->mo->z + player->mo->height) && ((player->mo->z + player->mo->height + player->mo->momz) < topheight))
{
floorclimb = true;
}
if (topheight < player->mo->z) // Waaaay below the ledge.
{
floorclimb = false;
}
if (bottomheight > player->mo->z + player->mo->height - FixedMul(16*FRACUNIT,player->mo->scale))
{
floorclimb = false;
}
}
else
{
if ((bottomheight > player->mo->z) && ((player->mo->z - player->mo->momz) > bottomheight))
{
floorclimb = true;
}
if (bottomheight > player->mo->z + player->mo->height) // Waaaay below the ledge.
{
floorclimb = false;
}
if (topheight < player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale))
{
floorclimb = false;
}
}
if (floorclimb)
break;
}
}
if (player->mo->eflags & MFE_VERTICALFLIP)
{
if ((floorz <= player->mo->z + player->mo->height)
&& ((player->mo->z + player->mo->height - player->mo->momz) <= floorz))
floorclimb = true;
if ((floorz > player->mo->z)
&& glidesector->sector->floorpic == skyflatnum)
return false;
if ((player->mo->z + player->mo->height - FixedMul(16*FRACUNIT,player->mo->scale) > ceilingz)
|| (player->mo->z + player->mo->height <= floorz))
floorclimb = true;
}
else
{
if ((ceilingz >= player->mo->z)
&& ((player->mo->z - player->mo->momz) >= ceilingz))
floorclimb = true;
if ((ceilingz < player->mo->z+player->mo->height)
&& glidesector->sector->ceilingpic == skyflatnum)
return false;
if ((player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale) < ceilingz)
|| (player->mo->z >= ceilingz))
floorclimb = true;
}
if (!floorclimb)
return false;
return true;
}
return false;
}
// //
// PTR_SlideTraverse // PTR_SlideTraverse
// //
@ -3407,117 +3302,7 @@ isblocking:
P_ProcessSpecialSector(slidemo->player, slidemo->subsector->sector, li->polyobj->lines[0]->backsector); P_ProcessSpecialSector(slidemo->player, slidemo->subsector->sector, li->polyobj->lines[0]->backsector);
} }
if (slidemo->player && (slidemo->player->pflags & PF_GLIDING || slidemo->player->climbing) if (in->frac < bestslidefrac)
&& slidemo->player->charability == CA_GLIDEANDCLIMB)
{
line_t *checkline = li;
sector_t *checksector;
ffloor_t *rover;
fixed_t topheight, bottomheight;
boolean fofline = false;
INT32 side = P_PointOnLineSide(slidemo->x, slidemo->y, li);
if (!side && li->backsector)
checksector = li->backsector;
else
checksector = li->frontsector;
if (checksector->ffloors)
{
for (rover = checksector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP))
continue;
topheight = *rover->topheight;
bottomheight = *rover->bottomheight;
#ifdef ESLOPE
if (*rover->t_slope)
topheight = P_GetZAt(*rover->t_slope, slidemo->x, slidemo->y);
if (*rover->b_slope)
bottomheight = P_GetZAt(*rover->b_slope, slidemo->x, slidemo->y);
#endif
if (topheight < slidemo->z)
continue;
if (bottomheight > slidemo->z + slidemo->height)
continue;
// Got this far, so I guess it's climbable. // TODO: Climbing check, also, better method to do this?
if (rover->master->flags & ML_TFERLINE)
{
size_t linenum = li-checksector->lines[0];
checkline = rover->master->frontsector->lines[0] + linenum;
fofline = true;
}
break;
}
}
// see about climbing on the wall
if (!(checkline->flags & ML_NOCLIMB))
{
boolean canclimb;
angle_t climbangle, climbline;
INT32 whichside = P_PointOnLineSide(slidemo->x, slidemo->y, li);
climbangle = climbline = R_PointToAngle2(li->v1->x, li->v1->y, li->v2->x, li->v2->y);
if (whichside) // on second side?
climbline += ANGLE_180;
climbangle += (ANGLE_90 * (whichside ? -1 : 1));
canclimb = (li->backsector ? P_IsClimbingValid(slidemo->player, climbangle) : true);
if (((!slidemo->player->climbing && abs((signed)(slidemo->angle - ANGLE_90 - climbline)) < ANGLE_45)
|| (slidemo->player->climbing == 1 && abs((signed)(slidemo->angle - climbline)) < ANGLE_135))
&& canclimb)
{
slidemo->angle = climbangle;
if (!demoplayback || P_AnalogMove(slidemo->player))
{
if (slidemo->player == &players[consoleplayer])
localangle = slidemo->angle;
else if (slidemo->player == &players[secondarydisplayplayer])
localangle2 = slidemo->angle;
else if (slidemo->player == &players[thirddisplayplayer])
localangle3 = slidemo->angle;
else if (slidemo->player == &players[fourthdisplayplayer])
localangle4 = slidemo->angle;
}
if (!slidemo->player->climbing)
{
S_StartSound(slidemo->player->mo, sfx_s3k4a);
slidemo->player->climbing = 5;
}
slidemo->player->pflags &= ~(PF_GLIDING|PF_SPINNING|PF_JUMPED|PF_THOKKED);
slidemo->player->glidetime = 0;
slidemo->player->secondjump = 0;
if (slidemo->player->climbing > 1)
slidemo->momz = slidemo->momx = slidemo->momy = 0;
if (fofline)
whichside = 0;
if (!whichside)
{
slidemo->player->lastsidehit = checkline->sidenum[whichside];
slidemo->player->lastlinehit = (INT16)(checkline - lines);
}
P_Thrust(slidemo, slidemo->angle, FixedMul(5*FRACUNIT, slidemo->scale));
}
}
}
if (in->frac < bestslidefrac && (!slidemo->player || !slidemo->player->climbing))
{ {
secondslidefrac = bestslidefrac; secondslidefrac = bestslidefrac;
secondslideline = bestslideline; secondslideline = bestslideline;

View File

@ -649,7 +649,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
if (!(rover->flags & FF_EXISTS)) if (!(rover->flags & FF_EXISTS))
continue; continue;
if (mobj->player && (P_CheckSolidLava(mobj, rover) || P_CanRunOnWater(mobj->player, rover))) if (mobj->player && P_CheckSolidLava(mobj, rover))
; ;
else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player) else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player)
|| (rover->flags & FF_BLOCKOTHERS && !mobj->player))) || (rover->flags & FF_BLOCKOTHERS && !mobj->player)))
@ -693,7 +693,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
if (!(rover->flags & FF_EXISTS)) if (!(rover->flags & FF_EXISTS))
continue; continue;
if (mobj->player && (P_CheckSolidLava(mobj, rover) || P_CanRunOnWater(mobj->player, rover))) if (mobj->player && P_CheckSolidLava(mobj, rover))
; ;
else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player) else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player)
|| (rover->flags & FF_BLOCKOTHERS && !mobj->player))) || (rover->flags & FF_BLOCKOTHERS && !mobj->player)))

View File

@ -167,58 +167,8 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
I_Error("P_SetPlayerMobjState used for non-player mobj. Use P_SetMobjState instead!\n(Mobj type: %d, State: %d)", mobj->type, state); I_Error("P_SetPlayerMobjState used for non-player mobj. Use P_SetMobjState instead!\n(Mobj type: %d, State: %d)", mobj->type, state);
#endif #endif
// Catch state changes for Super Sonic
/* // SRB2kart - don't need
if (player->powers[pw_super] && (player->charflags & SF_SUPERANIMS))
{
switch (state)
{
case S_PLAY_STND:
case S_PLAY_TAP1:
case S_PLAY_TAP2:
case S_PLAY_GASP:
P_SetPlayerMobjState(mobj, S_PLAY_SUPERSTAND);
return true;
case S_PLAY_FALL1:
case S_PLAY_SPRING:
case S_PLAY_RUN1:
case S_PLAY_RUN2:
case S_PLAY_RUN3:
case S_PLAY_RUN4:
P_SetPlayerMobjState(mobj, S_PLAY_SUPERWALK1);
return true;
case S_PLAY_FALL2:
case S_PLAY_RUN5:
case S_PLAY_RUN6:
case S_PLAY_RUN7:
case S_PLAY_RUN8:
P_SetPlayerMobjState(mobj, S_PLAY_SUPERWALK2);
return true;
case S_PLAY_SPD1:
case S_PLAY_SPD2:
P_SetPlayerMobjState(mobj, S_PLAY_SUPERFLY1);
return true;
case S_PLAY_SPD3:
case S_PLAY_SPD4:
P_SetPlayerMobjState(mobj, S_PLAY_SUPERFLY2);
return true;
case S_PLAY_TEETER1:
case S_PLAY_TEETER2:
P_SetPlayerMobjState(mobj, S_PLAY_SUPERTEETER);
return true;
case S_PLAY_ATK1:
case S_PLAY_ATK2:
case S_PLAY_ATK3:
case S_PLAY_ATK4:
if (!(player->charflags & SF_SUPERSPIN))
return true;
break;
default:
break;
}
}
// You were in pain state after taking a hit, and you're moving out of pain state now? // You were in pain state after taking a hit, and you're moving out of pain state now?
else */if (mobj->state == &states[mobj->info->painstate] && player->powers[pw_flashing] == K_GetKartFlashing(player) && state != mobj->info->painstate) if (mobj->state == &states[mobj->info->painstate] && player->powers[pw_flashing] == K_GetKartFlashing(player) && state != mobj->info->painstate)
{ {
// Start flashing, since you've landed. // Start flashing, since you've landed.
player->powers[pw_flashing] = K_GetKartFlashing(player)-1; player->powers[pw_flashing] = K_GetKartFlashing(player)-1;
@ -260,51 +210,6 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
st = &states[state]; st = &states[state];
mobj->state = st; mobj->state = st;
mobj->tics = st->tics; mobj->tics = st->tics;
// Adjust the player's animation speed to match their velocity.
if (!(disableSpeedAdjust || player->charflags & SF_NOSPEEDADJUST))
{
fixed_t speed = FixedDiv(player->speed, FixedMul(mobj->scale, player->mo->movefactor)); // fixed_t speed = FixedDiv(player->speed, mobj->scale);
if (player->panim == PA_ROLL)
{
if (speed > 16<<FRACBITS)
mobj->tics = 1;
else
mobj->tics = 2;
}
else if (player->panim == PA_FALL)
{
speed = FixedDiv(abs(mobj->momz), mobj->scale);
if (speed < 10<<FRACBITS)
mobj->tics = 4;
else if (speed < 20<<FRACBITS)
mobj->tics = 3;
else if (speed < 30<<FRACBITS)
mobj->tics = 2;
else
mobj->tics = 1;
}
else if (P_IsObjectOnGround(mobj) || player->powers[pw_super]) // Only if on the ground or superflying.
{
if (player->panim == PA_WALK)
{
if (speed > 12<<FRACBITS)
mobj->tics = 2;
else if (speed > 6<<FRACBITS)
mobj->tics = 3;
else
mobj->tics = 4;
}
else if (player->panim == PA_RUN)
{
if (speed > 52<<FRACBITS)
mobj->tics = 1;
else
mobj->tics = 2;
}
}
}
mobj->sprite = st->sprite; mobj->sprite = st->sprite;
mobj->frame = st->frame; mobj->frame = st->frame;
mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set
@ -1354,7 +1259,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo)
if (wasflip == !(mo->eflags & MFE_VERTICALFLIP)) // note!! == ! is not equivalent to != here - turns numeric into bool this way if (wasflip == !(mo->eflags & MFE_VERTICALFLIP)) // note!! == ! is not equivalent to != here - turns numeric into bool this way
P_PlayerFlip(mo); P_PlayerFlip(mo);
if (mo->player->kartstuff[k_pogospring]) if (mo->player->kartstuff[k_pogospring])
gravityadd = FixedMul(gravityadd, 5*FRACUNIT/2); gravityadd = (5*gravityadd)/2;
} }
else else
{ {
@ -1405,10 +1310,14 @@ fixed_t P_GetMobjGravity(mobj_t *mo)
case MT_BANANA: case MT_BANANA:
case MT_EGGMANITEM: case MT_EGGMANITEM:
case MT_SSMINE: case MT_SSMINE:
gravityadd = FixedMul(gravityadd, 5*FRACUNIT/2);
break;
case MT_SINK: case MT_SINK:
gravityadd = FixedMul(gravityadd, 5*FRACUNIT); // Double gravity if (mo->extravalue2 > 0)
gravityadd *= mo->extravalue2;
/* FALLTHRU */
case MT_ORBINAUT:
case MT_JAWZ:
case MT_JAWZ_DUD:
gravityadd = (5*gravityadd)/2;
break; break;
case MT_SIGN: case MT_SIGN:
gravityadd /= 8; gravityadd /= 8;
@ -2098,7 +2007,7 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp
topheight = P_GetFOFTopZ(mo, sector, rover, mo->x, mo->y, NULL); topheight = P_GetFOFTopZ(mo, sector, rover, mo->x, mo->y, NULL);
bottomheight = P_GetFOFBottomZ(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)) // only the player should be affected
; ;
else if (motype != 0 && rover->flags & FF_SWIMMABLE) // "scenery" only else if (motype != 0 && rover->flags & FF_SWIMMABLE) // "scenery" only
continue; continue;
@ -3221,28 +3130,6 @@ static boolean P_SceneryZMovement(mobj_t *mo)
return true; return true;
} }
// P_CanRunOnWater
//
// Returns true if player can waterrun on the 3D floor
//
boolean P_CanRunOnWater(player_t *player, ffloor_t *rover)
{
fixed_t topheight =
#ifdef ESLOPE
*rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) :
#endif
*rover->topheight;
if (!(player->pflags & PF_NIGHTSMODE) && !player->homing
&& (((player->charability == CA_SWIM) || player->powers[pw_super] || player->charflags & SF_RUNONWATER) && player->mo->ceilingz-topheight >= player->mo->height)
&& (rover->flags & FF_SWIMMABLE) && !(player->pflags & PF_SPINNING) && player->speed > FixedMul(player->runspeed, player->mo->scale)
&& !(player->pflags & PF_SLIDING)
&& abs(player->mo->z - topheight) < FixedMul(30*FRACUNIT, player->mo->scale))
return true;
return false;
}
// //
// P_MobjCheckWater // P_MobjCheckWater
// //
@ -3399,8 +3286,8 @@ void P_MobjCheckWater(mobj_t *mobj)
// skipping stone! // skipping stone!
if (p && p->kartstuff[k_waterskip] < 2 if (p && p->kartstuff[k_waterskip] < 2
&& ((p->speed/2 > abs(mobj->momz)) // Going more forward than horizontal, so you can skip across the water. && ((p->speed/3 > abs(mobj->momz)) // Going more forward than horizontal, so you can skip across the water.
|| (p->speed > K_GetKartSpeed(p,false)/4 && p->kartstuff[k_waterskip])) // Already skipped once, so you can skip once more! || (p->speed > K_GetKartSpeed(p,false)/3 && p->kartstuff[k_waterskip])) // Already skipped once, so you can skip once more!
&& ((!(mobj->eflags & MFE_VERTICALFLIP) && thingtop - mobj->momz > mobj->watertop) && ((!(mobj->eflags & MFE_VERTICALFLIP) && thingtop - mobj->momz > mobj->watertop)
|| ((mobj->eflags & MFE_VERTICALFLIP) && mobj->z - mobj->momz < mobj->waterbottom))) || ((mobj->eflags & MFE_VERTICALFLIP) && mobj->z - mobj->momz < mobj->waterbottom)))
{ {
@ -6637,7 +6524,7 @@ void P_MobjThinker(mobj_t *mobj)
case MT_SINK_SHIELD: case MT_SINK_SHIELD:
if ((mobj->health > 0 if ((mobj->health > 0
&& (!mobj->target || !mobj->target->player || mobj->target->player->health <= 0 || mobj->target->player->spectator)) && (!mobj->target || !mobj->target->player || mobj->target->player->health <= 0 || mobj->target->player->spectator))
|| (mobj->health <= 0 && mobj->z <= mobj->floorz) || (mobj->health <= 0 && P_IsObjectOnGround(mobj))
|| P_CheckDeathPitCollide(mobj)) // When in death state || P_CheckDeathPitCollide(mobj)) // When in death state
{ {
P_RemoveMobj(mobj); P_RemoveMobj(mobj);
@ -6651,19 +6538,22 @@ void P_MobjThinker(mobj_t *mobj)
fixed_t y = P_RandomRange(-35, 35)*mobj->scale; fixed_t y = P_RandomRange(-35, 35)*mobj->scale;
fixed_t z = P_RandomRange(0, 70)*mobj->scale; fixed_t z = P_RandomRange(0, 70)*mobj->scale;
mobj_t *smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_SMOKE); mobj_t *smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_SMOKE);
P_SetMobjState(smoke, S_OPAQUESMOKE1);
K_MatchGenericExtraFlags(smoke, mobj);
smoke->scale = mobj->scale * 2; smoke->scale = mobj->scale * 2;
smoke->destscale = mobj->scale * 6; smoke->destscale = mobj->scale * 6;
smoke->momz = P_RandomRange(4, 9)*FRACUNIT; smoke->momz = P_RandomRange(4, 9)*FRACUNIT*P_MobjFlip(smoke);
} }
break; break;
case MT_BOOMPARTICLE: case MT_BOOMPARTICLE:
{ {
fixed_t x = P_RandomRange(-16, 16)*mobj->scale; fixed_t x = P_RandomRange(-16, 16)*mobj->scale;
fixed_t y = P_RandomRange(-16, 16)*mobj->scale; fixed_t y = P_RandomRange(-16, 16)*mobj->scale;
fixed_t z = P_RandomRange(0, 32)*mobj->scale; fixed_t z = P_RandomRange(0, 32)*mobj->scale*P_MobjFlip(mobj);
if (leveltime % 2 == 0) if (leveltime % 2 == 0)
{ {
mobj_t *smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_BOSSEXPLODE); mobj_t *smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_BOSSEXPLODE);
K_MatchGenericExtraFlags(smoke, mobj);
P_SetMobjState(smoke, S_QUICKBOOM1); P_SetMobjState(smoke, S_QUICKBOOM1);
smoke->scale = mobj->scale/2; smoke->scale = mobj->scale/2;
smoke->destscale = mobj->scale; smoke->destscale = mobj->scale;
@ -6672,6 +6562,8 @@ void P_MobjThinker(mobj_t *mobj)
else else
{ {
mobj_t *smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_SMOKE); mobj_t *smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_SMOKE);
P_SetMobjState(smoke, S_OPAQUESMOKE1);
K_MatchGenericExtraFlags(smoke, mobj);
smoke->scale = mobj->scale; smoke->scale = mobj->scale;
smoke->destscale = mobj->scale*2; smoke->destscale = mobj->scale*2;
} }
@ -6777,7 +6669,7 @@ void P_MobjThinker(mobj_t *mobj)
} }
else if ((mobj->health > 0 else if ((mobj->health > 0
&& (!mobj->target || !mobj->target->player || !mobj->target->player->mo || mobj->target->player->health <= 0 || mobj->target->player->spectator)) && (!mobj->target || !mobj->target->player || !mobj->target->player->mo || mobj->target->player->health <= 0 || mobj->target->player->spectator))
|| (mobj->health <= 0 && mobj->z <= mobj->floorz) || (mobj->health <= 0 && P_IsObjectOnGround(mobj))
|| P_CheckDeathPitCollide(mobj)) // When in death state || P_CheckDeathPitCollide(mobj)) // When in death state
{ {
P_RemoveMobj(mobj); P_RemoveMobj(mobj);
@ -7225,6 +7117,9 @@ void P_MobjThinker(mobj_t *mobj)
y = mobj->target->y; y = mobj->target->y;
z = mobj->target->z + (80*mapobjectscale); z = mobj->target->z + (80*mapobjectscale);
} }
if (mobj->target->eflags & MFE_VERTICALFLIP)
z += mobj->target->height - FixedMul(mobj->target->scale, mobj->height);
P_TeleportMove(mobj, x, y, z); P_TeleportMove(mobj, x, y, z);
} }
break; break;
@ -7420,7 +7315,7 @@ void P_MobjThinker(mobj_t *mobj)
case MT_BANANA: case MT_BANANA:
case MT_EGGMANITEM: case MT_EGGMANITEM:
case MT_SPB: case MT_SPB:
if (mobj->z <= mobj->floorz) if (P_IsObjectOnGround(mobj))
{ {
P_RemoveMobj(mobj); P_RemoveMobj(mobj);
return; return;
@ -7433,7 +7328,7 @@ void P_MobjThinker(mobj_t *mobj)
break; break;
case MT_JAWZ: case MT_JAWZ:
case MT_JAWZ_DUD: case MT_JAWZ_DUD:
if (mobj->z <= mobj->floorz) if (P_IsObjectOnGround(mobj))
P_SetMobjState(mobj, mobj->info->xdeathstate); P_SetMobjState(mobj, mobj->info->xdeathstate);
// fallthru // fallthru
case MT_JAWZ_SHIELD: case MT_JAWZ_SHIELD:
@ -7441,10 +7336,10 @@ void P_MobjThinker(mobj_t *mobj)
break; break;
case MT_SSMINE: case MT_SSMINE:
case MT_SPBEXPLOSION: case MT_SPBEXPLOSION:
if (mobj->health > -100) if (mobj->extravalue2 != -100)
{ {
P_SetMobjState(mobj, mobj->info->deathstate); P_SetMobjState(mobj, mobj->info->deathstate);
mobj->health = -100; mobj->extravalue2 = -100;
} }
else else
{ {
@ -7467,7 +7362,7 @@ void P_MobjThinker(mobj_t *mobj)
/* FALLTHRU */ /* FALLTHRU */
case MT_SMK_MOLE: case MT_SMK_MOLE:
mobj->flags2 ^= MF2_DONTDRAW; mobj->flags2 ^= MF2_DONTDRAW;
if (mobj->z <= mobj->floorz) if (P_IsObjectOnGround(mobj))
{ {
P_RemoveMobj(mobj); P_RemoveMobj(mobj);
return; return;
@ -7488,7 +7383,7 @@ void P_MobjThinker(mobj_t *mobj)
} }
mobj->flags2 ^= MF2_DONTDRAW; mobj->flags2 ^= MF2_DONTDRAW;
if (mobj->z <= mobj->floorz) if (P_IsObjectOnGround(mobj))
{ {
P_RemoveMobj(mobj); P_RemoveMobj(mobj);
return; return;
@ -8157,7 +8052,7 @@ void P_MobjThinker(mobj_t *mobj)
mobj->friction = ORIG_FRICTION/4; mobj->friction = ORIG_FRICTION/4;
if (mobj->momx || mobj->momy) if (mobj->momx || mobj->momy)
P_SpawnGhostMobj(mobj); P_SpawnGhostMobj(mobj);
if (mobj->z <= mobj->floorz && mobj->health > 1) if (P_IsObjectOnGround(mobj) && mobj->health > 1)
{ {
S_StartSound(mobj, mobj->info->activesound); S_StartSound(mobj, mobj->info->activesound);
mobj->momx = mobj->momy = 0; mobj->momx = mobj->momy = 0;
@ -8177,7 +8072,7 @@ void P_MobjThinker(mobj_t *mobj)
case MT_SINK: case MT_SINK:
if (mobj->momx || mobj->momy) if (mobj->momx || mobj->momy)
P_SpawnGhostMobj(mobj); P_SpawnGhostMobj(mobj);
if (mobj->z <= mobj->floorz) if (P_IsObjectOnGround(mobj))
{ {
S_StartSound(mobj, mobj->info->deathsound); S_StartSound(mobj, mobj->info->deathsound);
P_SetMobjState(mobj, S_NULL); P_SetMobjState(mobj, S_NULL);
@ -8190,28 +8085,26 @@ void P_MobjThinker(mobj_t *mobj)
mobj->color = mobj->target->player->skincolor; mobj->color = mobj->target->player->skincolor;
else else
mobj->color = SKINCOLOR_KETCHUP; mobj->color = SKINCOLOR_KETCHUP;
if (mobj->momx || mobj->momy) if (mobj->momx || mobj->momy)
P_SpawnGhostMobj(mobj); P_SpawnGhostMobj(mobj);
if (P_IsObjectOnGround(mobj))
if (P_IsObjectOnGround(mobj) && (mobj->state == &states[S_SSMINE_AIR1] || mobj->state == &states[S_SSMINE_AIR2]))
{ {
if (mobj->state == &states[S_SSMINE_AIR1] || mobj->state == &states[S_SSMINE_AIR2]) if (mobj->extravalue1 > 0)
P_SetMobjState(mobj, S_SSMINE_DEPLOY1); mobj->extravalue1--;
if (mobj->reactiontime >= mobj->info->reactiontime) else
{ {
mobj->momx = mobj->momy = 0; mobj->momx = mobj->momy = 0;
S_StartSound(mobj, mobj->info->activesound); S_StartSound(mobj, mobj->info->activesound);
mobj->reactiontime--; P_SetMobjState(mobj, S_SSMINE_DEPLOY1);
} }
} }
if (mobj->reactiontime && mobj->reactiontime < mobj->info->reactiontime)
{
mobj->reactiontime--;
if (!mobj->reactiontime)
P_KillMobj(mobj, NULL, NULL);
}
if ((mobj->state >= &states[S_SSMINE1] && mobj->state <= &states[S_SSMINE4]) if ((mobj->state >= &states[S_SSMINE1] && mobj->state <= &states[S_SSMINE4])
|| (mobj->state >= &states[S_SSMINE_DEPLOY8] && mobj->state <= &states[S_SSMINE_DEPLOY13])) || (mobj->state >= &states[S_SSMINE_DEPLOY8] && mobj->state <= &states[S_SSMINE_DEPLOY13]))
A_GrenadeRing(mobj); A_GrenadeRing(mobj);
if (mobj->threshold > 0) if (mobj->threshold > 0)
mobj->threshold--; mobj->threshold--;
break; break;
@ -8355,6 +8248,7 @@ void P_MobjThinker(mobj_t *mobj)
break; break;
case MT_INSTASHIELDB: case MT_INSTASHIELDB:
mobj->flags2 ^= MF2_DONTDRAW; mobj->flags2 ^= MF2_DONTDRAW;
K_MatchGenericExtraFlags(mobj, mobj->target);
/* FALLTHRU */ /* FALLTHRU */
case MT_INSTASHIELDA: case MT_INSTASHIELDA:
if (!mobj->target || !mobj->target->health || (mobj->target->player && !mobj->target->player->kartstuff[k_instashield])) if (!mobj->target || !mobj->target->health || (mobj->target->player && !mobj->target->player->kartstuff[k_instashield]))
@ -8363,6 +8257,7 @@ void P_MobjThinker(mobj_t *mobj)
return; return;
} }
P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
K_MatchGenericExtraFlags(mobj, mobj->target);
break; break;
case MT_BATTLEPOINT: case MT_BATTLEPOINT:
if (!mobj->target || P_MobjWasRemoved(mobj->target)) if (!mobj->target || P_MobjWasRemoved(mobj->target))
@ -8383,7 +8278,7 @@ void P_MobjThinker(mobj_t *mobj)
if (mobj->movefactor < mobj->target->height) if (mobj->movefactor < mobj->target->height)
mobj->movefactor = mobj->target->height; mobj->movefactor = mobj->target->height;
} }
K_MatchGenericExtraFlags(mobj, mobj->target);
P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z + (mobj->target->height/2) + mobj->movefactor); P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z + (mobj->target->height/2) + mobj->movefactor);
break; break;
case MT_THUNDERSHIELD: case MT_THUNDERSHIELD:
@ -8508,6 +8403,10 @@ void P_MobjThinker(mobj_t *mobj)
mobj->flags2 &= ~MF2_DONTDRAW; mobj->flags2 &= ~MF2_DONTDRAW;
} }
// Update mobj antigravity status:
mobj->eflags = (mobj->eflags & ~MFE_VERTICALFLIP)|(mobj->target->eflags & MFE_VERTICALFLIP);
mobj->flags2 = (mobj->flags2 & ~MF2_OBJECTFLIP)|(mobj->target->flags2 & MF2_OBJECTFLIP);
// Now for the wheels // Now for the wheels
{ {
const fixed_t rad = FixedMul(mobjinfo[MT_PLAYER].radius, mobj->target->scale); const fixed_t rad = FixedMul(mobjinfo[MT_PLAYER].radius, mobj->target->scale);
@ -8529,6 +8428,7 @@ void P_MobjThinker(mobj_t *mobj)
P_SetScale(cur, mobj->target->scale); P_SetScale(cur, mobj->target->scale);
cur->color = mobj->target->color; cur->color = mobj->target->color;
cur->colorized = true; cur->colorized = true;
K_FlipFromObject(cur, mobj->target);
if (mobj->flags2 & MF2_DONTDRAW) if (mobj->flags2 & MF2_DONTDRAW)
cur->flags2 |= MF2_DONTDRAW; cur->flags2 |= MF2_DONTDRAW;
@ -11124,7 +11024,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
if (mthing->options >> ZSHIFT) if (mthing->options >> ZSHIFT)
z -= ((mthing->options >> ZSHIFT) << FRACBITS); z -= ((mthing->options >> ZSHIFT) << FRACBITS);
if (p->kartstuff[k_respawn]) if (p->kartstuff[k_respawn])
z -= 128*FRACUNIT; // Too late for v1, but for later: 128*mapobjectscale; z -= 128*mapobjectscale;
} }
else else
{ {
@ -11132,7 +11032,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
if (mthing->options >> ZSHIFT) if (mthing->options >> ZSHIFT)
z += ((mthing->options >> ZSHIFT) << FRACBITS); z += ((mthing->options >> ZSHIFT) << FRACBITS);
if (p->kartstuff[k_respawn]) if (p->kartstuff[k_respawn])
z += 128*FRACUNIT; // Too late for v1, but for later: 128*mapobjectscale; z += 128*mapobjectscale;
} }
if (mthing->options & MTF_OBJECTFLIP) // flip the player! if (mthing->options & MTF_OBJECTFLIP) // flip the player!
@ -11193,7 +11093,14 @@ void P_MovePlayerToStarpost(INT32 playernum)
#endif #endif
sector->ceilingheight; sector->ceilingheight;
z = (p->starpostz + 128) << FRACBITS; // Respawn off the ground if (mobj->player->kartstuff[k_starpostflip])
z = (p->starpostz<<FRACBITS) - FixedMul(128<<FRACBITS, mapobjectscale) - mobj->height;
else
z = (p->starpostz<<FRACBITS) + FixedMul(128<<FRACBITS, mapobjectscale);
//z = (p->starpostz + 128) << FRACBITS; // reverse gravity exists, pls
mobj->player->kartstuff[k_starpostflip] = 0;
if (z < floor) if (z < floor)
z = floor; z = floor;
else if (z > ceiling - mobjinfo[MT_PLAYER].height) else if (z > ceiling - mobjinfo[MT_PLAYER].height)

View File

@ -249,6 +249,8 @@ static void P_NetArchivePlayers(void)
WRITEUINT32(save_p, players[i].jointime); WRITEUINT32(save_p, players[i].jointime);
WRITEUINT8(save_p, players[i].splitscreenindex);
WRITEUINT16(save_p, flags); WRITEUINT16(save_p, flags);
if (flags & CAPSULE) if (flags & CAPSULE)
@ -282,6 +284,12 @@ static void P_NetArchivePlayers(void)
WRITEUINT8(save_p, players[i].accelstart); WRITEUINT8(save_p, players[i].accelstart);
WRITEUINT8(save_p, players[i].acceleration); WRITEUINT8(save_p, players[i].acceleration);
WRITEFIXED(save_p, players[i].jumpfactor); WRITEFIXED(save_p, players[i].jumpfactor);
for (j = 0; j < MAXPREDICTTICS; j++)
{
WRITEINT16(save_p, players[i].lturn_max[j]);
WRITEINT16(save_p, players[i].rturn_max[j]);
}
} }
} }
@ -420,6 +428,8 @@ static void P_NetUnArchivePlayers(void)
players[i].jointime = READUINT32(save_p); players[i].jointime = READUINT32(save_p);
players[i].splitscreenindex = READUINT8(save_p);
flags = READUINT16(save_p); flags = READUINT16(save_p);
if (flags & CAPSULE) if (flags & CAPSULE)
@ -456,6 +466,12 @@ static void P_NetUnArchivePlayers(void)
players[i].accelstart = READUINT8(save_p); players[i].accelstart = READUINT8(save_p);
players[i].acceleration = READUINT8(save_p); players[i].acceleration = READUINT8(save_p);
players[i].jumpfactor = READFIXED(save_p); players[i].jumpfactor = READFIXED(save_p);
for (j = 0; j < MAXPREDICTTICS; j++)
{
players[i].lturn_max[j] = READINT16(save_p);
players[i].rturn_max[j] = READINT16(save_p);
}
} }
} }
@ -663,8 +679,6 @@ static void P_NetArchiveWorld(void)
WRITEUINT16(put, 0xffff); WRITEUINT16(put, 0xffff);
mld = W_CacheLumpNum(lastloadedmaplumpnum+ML_LINEDEFS, PU_CACHE);
msd = W_CacheLumpNum(lastloadedmaplumpnum+ML_SIDEDEFS, PU_CACHE);
// do lines // do lines
for (i = 0; i < numlines; i++, mld++, li++) for (i = 0; i < numlines; i++, mld++, li++)
{ {
@ -683,13 +697,13 @@ static void P_NetArchiveWorld(void)
diff |= LD_S1TEXOFF; diff |= LD_S1TEXOFF;
//SoM: 4/1/2000: Some textures are colormaps. Don't worry about invalid textures. //SoM: 4/1/2000: Some textures are colormaps. Don't worry about invalid textures.
if (R_CheckTextureNumForName(msd[li->sidenum[0]].toptexture) != -1 if (R_CheckTextureNumForName(msd[li->sidenum[0]].toptexture) != -1
&& si->toptexture != R_TextureNumForName(msd[li->sidenum[0]].toptexture)) && si->toptexture != R_TextureNumForName(msd[li->sidenum[0]].toptexture))
diff |= LD_S1TOPTEX; diff |= LD_S1TOPTEX;
if (R_CheckTextureNumForName(msd[li->sidenum[0]].bottomtexture) != -1 if (R_CheckTextureNumForName(msd[li->sidenum[0]].bottomtexture) != -1
&& si->bottomtexture != R_TextureNumForName(msd[li->sidenum[0]].bottomtexture)) && si->bottomtexture != R_TextureNumForName(msd[li->sidenum[0]].bottomtexture))
diff |= LD_S1BOTTEX; diff |= LD_S1BOTTEX;
if (R_CheckTextureNumForName(msd[li->sidenum[0]].midtexture) != -1 if (R_CheckTextureNumForName(msd[li->sidenum[0]].midtexture) != -1
&& si->midtexture != R_TextureNumForName(msd[li->sidenum[0]].midtexture)) && si->midtexture != R_TextureNumForName(msd[li->sidenum[0]].midtexture))
diff |= LD_S1MIDTEX; diff |= LD_S1MIDTEX;
} }
if (li->sidenum[1] != 0xffff) if (li->sidenum[1] != 0xffff)
@ -698,13 +712,13 @@ static void P_NetArchiveWorld(void)
if (si->textureoffset != SHORT(msd[li->sidenum[1]].textureoffset)<<FRACBITS) if (si->textureoffset != SHORT(msd[li->sidenum[1]].textureoffset)<<FRACBITS)
diff2 |= LD_S2TEXOFF; diff2 |= LD_S2TEXOFF;
if (R_CheckTextureNumForName(msd[li->sidenum[1]].toptexture) != -1 if (R_CheckTextureNumForName(msd[li->sidenum[1]].toptexture) != -1
&& si->toptexture != R_TextureNumForName(msd[li->sidenum[1]].toptexture)) && si->toptexture != R_TextureNumForName(msd[li->sidenum[1]].toptexture))
diff2 |= LD_S2TOPTEX; diff2 |= LD_S2TOPTEX;
if (R_CheckTextureNumForName(msd[li->sidenum[1]].bottomtexture) != -1 if (R_CheckTextureNumForName(msd[li->sidenum[1]].bottomtexture) != -1
&& si->bottomtexture != R_TextureNumForName(msd[li->sidenum[1]].bottomtexture)) && si->bottomtexture != R_TextureNumForName(msd[li->sidenum[1]].bottomtexture))
diff2 |= LD_S2BOTTEX; diff2 |= LD_S2BOTTEX;
if (R_CheckTextureNumForName(msd[li->sidenum[1]].midtexture) != -1 if (R_CheckTextureNumForName(msd[li->sidenum[1]].midtexture) != -1
&& si->midtexture != R_TextureNumForName(msd[li->sidenum[1]].midtexture)) && si->midtexture != R_TextureNumForName(msd[li->sidenum[1]].midtexture))
diff2 |= LD_S2MIDTEX; diff2 |= LD_S2MIDTEX;
if (diff2) if (diff2)
diff |= LD_DIFF2; diff |= LD_DIFF2;
@ -3301,6 +3315,7 @@ static void P_NetArchiveMisc(void)
WRITEUINT32(save_p, wantedcalcdelay); WRITEUINT32(save_p, wantedcalcdelay);
WRITEUINT32(save_p, indirectitemcooldown); WRITEUINT32(save_p, indirectitemcooldown);
WRITEUINT32(save_p, hyubgone);
WRITEUINT32(save_p, mapreset); WRITEUINT32(save_p, mapreset);
WRITEUINT8(save_p, nospectategrief); WRITEUINT8(save_p, nospectategrief);
WRITEUINT8(save_p, thwompsactive); WRITEUINT8(save_p, thwompsactive);
@ -3409,6 +3424,7 @@ static inline boolean P_NetUnArchiveMisc(void)
wantedcalcdelay = READUINT32(save_p); wantedcalcdelay = READUINT32(save_p);
indirectitemcooldown = READUINT32(save_p); indirectitemcooldown = READUINT32(save_p);
hyubgone = READUINT32(save_p);
mapreset = READUINT32(save_p); mapreset = READUINT32(save_p);
nospectategrief = READUINT8(save_p); nospectategrief = READUINT8(save_p);
thwompsactive = (boolean)READUINT8(save_p); thwompsactive = (boolean)READUINT8(save_p);

View File

@ -234,7 +234,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
DEH_WriteUndoline("LEVELFLAGS", va("%d", mapheaderinfo[num]->levelflags), UNDO_NONE); DEH_WriteUndoline("LEVELFLAGS", va("%d", mapheaderinfo[num]->levelflags), UNDO_NONE);
mapheaderinfo[num]->levelflags = 0; mapheaderinfo[num]->levelflags = 0;
DEH_WriteUndoline("MENUFLAGS", va("%d", mapheaderinfo[num]->menuflags), UNDO_NONE); DEH_WriteUndoline("MENUFLAGS", va("%d", mapheaderinfo[num]->menuflags), UNDO_NONE);
mapheaderinfo[num]->menuflags = 0; mapheaderinfo[num]->menuflags = (mainwads ? 0 : LF2_EXISTSHACK); // see p_setup.c - prevents replacing maps in addons with easier versions
// TODO grades support for delfile (pfft yeah right) // TODO grades support for delfile (pfft yeah right)
P_DeleteGrades(num); P_DeleteGrades(num);
// SRB2Kart // SRB2Kart
@ -1120,7 +1120,7 @@ static inline void P_SpawnEmblems(void)
static void P_SpawnSecretItems(boolean loademblems) static void P_SpawnSecretItems(boolean loademblems)
{ {
// Now let's spawn those funky emblem things! Tails 12-08-2002 // Now let's spawn those funky emblem things! Tails 12-08-2002
if (netgame || multiplayer || (modifiedgame && !savemoddata)) // No cheating!! if (netgame || multiplayer || majormods) // No cheating!!
return; return;
if (loademblems) if (loademblems)
@ -2857,6 +2857,9 @@ boolean P_SetupLevel(boolean skipprecip)
lastwipetic = nowtime; lastwipetic = nowtime;
if (moviemode) // make sure we save frames for the white hold too if (moviemode) // make sure we save frames for the white hold too
M_SaveFrame(); M_SaveFrame();
// Keep the network alive
NetKeepAlive();
} }
ranspecialwipe = 1; ranspecialwipe = 1;
@ -3211,10 +3214,9 @@ boolean P_SetupLevel(boolean skipprecip)
if (!cv_analog4.changed) if (!cv_analog4.changed)
CV_SetValue(&cv_analog4, 0);*/ CV_SetValue(&cv_analog4, 0);*/
#ifdef HWRENDER // Shouldn't be necessary with render parity?
if (rendermode != render_soft && rendermode != render_none) /*if (rendermode != render_none)
CV_Set(&cv_grfov, cv_grfov.defaultvalue); CV_Set(&cv_fov, cv_fov.defaultvalue);*/
#endif
displayplayer = consoleplayer; // Start with your OWN view, please! displayplayer = consoleplayer; // Start with your OWN view, please!
} }
@ -3241,6 +3243,7 @@ boolean P_SetupLevel(boolean skipprecip)
wantedcalcdelay = wantedfrequency*2; wantedcalcdelay = wantedfrequency*2;
indirectitemcooldown = 0; indirectitemcooldown = 0;
hyubgone = 0;
mapreset = 0; mapreset = 0;
nospectategrief = 0; nospectategrief = 0;
thwompsactive = false; thwompsactive = false;
@ -3272,7 +3275,7 @@ boolean P_SetupLevel(boolean skipprecip)
nextmapoverride = 0; nextmapoverride = 0;
skipstats = false; skipstats = false;
if (!(netgame || multiplayer) && (!modifiedgame || savemoddata)) if (!(netgame || multiplayer) && !majormods)
mapvisited[gamemap-1] |= MV_VISITED; mapvisited[gamemap-1] |= MV_VISITED;
levelloading = false; levelloading = false;
@ -3435,7 +3438,7 @@ boolean P_AddWadFile(const char *wadfilename)
// //
R_AddSkins(wadnum); // faB: wadfile index in wadfiles[] R_AddSkins(wadnum); // faB: wadfile index in wadfiles[]
// //
// edit music defs // edit music defs
// //
S_LoadMusicDefs(wadnum); S_LoadMusicDefs(wadnum);
@ -3455,6 +3458,14 @@ boolean P_AddWadFile(const char *wadfilename)
continue; continue;
num = (INT16)M_MapNumber(name[3], name[4]); num = (INT16)M_MapNumber(name[3], name[4]);
// we want to record whether this map exists. if it doesn't have a header, we can assume it's not relephant
if (num <= NUMMAPS && mapheaderinfo[num-1])
{
if (mapheaderinfo[num-1]->menuflags & LF2_EXISTSHACK)
G_SetGameModified(multiplayer, true); // oops, double-defined - no record attack privileges for you
mapheaderinfo[num-1]->menuflags |= LF2_EXISTSHACK;
}
//If you replaced the map you're on, end the level when done. //If you replaced the map you're on, end the level when done.
if (num == gamemap) if (num == gamemap)
replacedcurrentmap = true; replacedcurrentmap = true;
@ -3481,6 +3492,8 @@ boolean P_AddWadFile(const char *wadfilename)
SendNetXCmd(XD_EXITLEVEL, NULL, 0); SendNetXCmd(XD_EXITLEVEL, NULL, 0);
} }
refreshdirmenu &= ~REFRESHDIR_GAMEDATA; // Under usual circumstances we'd wait for REFRESHDIR_GAMEDATA to disappear the next frame, but it's a bit too dangerous for that...
return true; return true;
} }

View File

@ -1758,12 +1758,12 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
switch (specialtype) switch (specialtype)
{ {
case 305: // continuous /*case 305: // continuous
case 306: // each time case 306: // each time
case 307: // once case 307: // once
if (!(actor && actor->player && actor->player->charability == dist/10)) if (!(actor && actor->player && actor->player->charability == dist/10))
return false; return false;
break; break;*/
case 309: // continuous case 309: // continuous
case 310: // each time case 310: // each time
// Only red team members can activate this. // Only red team members can activate this.
@ -3864,14 +3864,6 @@ DoneSection2:
P_InstaThrust(player->mo, player->mo->angle, linespeed); P_InstaThrust(player->mo, player->mo->angle, linespeed);
/*if (GETSECSPECIAL(sector->special, 3) == 6 && (player->charability2 == CA2_SPINDASH)) // SRB2kart
{
if (!(player->pflags & PF_SPINNING))
player->pflags |= PF_SPINNING;
//P_SetPlayerMobjState(player->mo, S_PLAY_ATK1);
}*/
player->kartstuff[k_dashpadcooldown] = TICRATE/3; player->kartstuff[k_dashpadcooldown] = TICRATE/3;
player->kartstuff[k_drift] = 0; player->kartstuff[k_drift] = 0;
player->kartstuff[k_driftcharge] = 0; player->kartstuff[k_driftcharge] = 0;
@ -4255,13 +4247,14 @@ DoneSection2:
player->starpostx = player->mo->x>>FRACBITS; player->starpostx = player->mo->x>>FRACBITS;
player->starposty = player->mo->y>>FRACBITS; player->starposty = player->mo->y>>FRACBITS;
player->starpostz = player->mo->floorz>>FRACBITS; player->starpostz = player->mo->floorz>>FRACBITS;
player->kartstuff[k_starpostflip] = player->mo->flags2 & MF2_OBJECTFLIP; // store flipping
player->starpostangle = player->mo->angle; //R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); torn; a momentum-based guess is less likely to be wrong in general, but when it IS wrong, it fucks you over entirely... player->starpostangle = player->mo->angle; //R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); torn; a momentum-based guess is less likely to be wrong in general, but when it IS wrong, it fucks you over entirely...
} }
else else
{ {
// SRB2kart 200117 // SRB2kart 200117
// Reset starposts (checkpoints) info // Reset starposts (checkpoints) info
player->starpostangle = player->starpostx = player->starposty = player->starpostz = 0; player->starpostangle = player->starpostx = player->starposty = player->starpostz = player->kartstuff[k_starpostflip] = 0;
} }
if (P_IsLocalPlayer(player)) if (P_IsLocalPlayer(player))
@ -5781,7 +5774,7 @@ void P_SpawnSpecials(INT32 fromnetsave)
lines[i].special = 0; lines[i].special = 0;
continue; continue;
} }
/*else -- commented out because irrelevant to kart /*else -- commented out because irrelevant to kart. keeping here because we can use these flags for something else now
{ {
if ((players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC)) 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_FLY && (lines[i].flags & ML_NOTAILS))
@ -7997,12 +7990,13 @@ static void P_SearchForDisableLinedefs(void)
} }
else if ((lines[i].flags & ML_NETONLY) == ML_NETONLY) else if ((lines[i].flags & ML_NETONLY) == ML_NETONLY)
continue; // Net-only never triggers in single player continue; // Net-only never triggers in single player
else if (players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC)) // commented out because irrelevant to kart. keeping here because we can use these flags for something else now
/*else if (players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC))
continue; continue;
else if (players[consoleplayer].charability == CA_FLY && (lines[i].flags & ML_NOTAILS)) else if (players[consoleplayer].charability == CA_FLY && (lines[i].flags & ML_NOTAILS))
continue; continue;
else if (players[consoleplayer].charability == CA_GLIDEANDCLIMB && (lines[i].flags & ML_NOKNUX)) else if (players[consoleplayer].charability == CA_GLIDEANDCLIMB && (lines[i].flags & ML_NOKNUX))
continue; continue;*/
// Disable any linedef specials with our tag. // Disable any linedef specials with our tag.
for (j = -1; (j = P_FindLineFromLineTag(&lines[i], j)) >= 0;) for (j = -1; (j = P_FindLineFromLineTag(&lines[i], j)) >= 0;)

View File

@ -680,6 +680,8 @@ void P_Ticker(boolean run)
if (indirectitemcooldown) if (indirectitemcooldown)
indirectitemcooldown--; indirectitemcooldown--;
if (hyubgone)
hyubgone--;
if (G_BattleGametype()) if (G_BattleGametype())
{ {

Some files were not shown because too many files have changed in this diff Show More