diff --git a/.gitignore b/.gitignore
index 922fac4aa..3090417dd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,3 +19,5 @@ Win32_LIB_ASM_Release
*.db
*.opendb
/.vs
+/debian
+/assets/debian
diff --git a/.travis.yml b/.travis.yml
index 1131bff3a..e9c8d0d71 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,9 +1,20 @@
+# Travis-CI Config
+#
+# You may use the Deployer to upload packages and builds to external servers.
+# See deployer/travis/deployer_defaults.sh for environment variables to configure.
+
language: c
sudo: required
dist: trusty
matrix:
include:
+################################
+# Test Buildbots
+# Deployer does not operate on these. See Deployer Buildbots, below.
+# These bots are disabled when a deployment is triggered by 'deployer' branch name AND DPL_TERMINATE_TESTS=1.
+# These bots remain enabled when a deployment is triggered by release tag.
+################################
- os: linux
addons:
apt:
@@ -15,6 +26,7 @@ matrix:
- p7zip-full
- gcc-4.4
compiler: gcc-4.4
+ 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
- os: linux
addons:
@@ -27,6 +39,7 @@ matrix:
- p7zip-full
- gcc-4.6
compiler: gcc-4.6
+ 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
- os: linux
addons:
@@ -39,9 +52,11 @@ matrix:
- p7zip-full
- gcc-4.7
compiler: gcc-4.7
+ if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
#gcc-4.7
- os: linux
compiler: gcc
+ 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
- os: linux
addons:
@@ -56,6 +71,7 @@ matrix:
- p7zip-full
- gcc-4.8
compiler: gcc-4.8
+ 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
- os: linux
addons:
@@ -71,6 +87,7 @@ matrix:
- gcc-7
compiler: gcc-7
env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough"
+ 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
- os: linux
addons:
@@ -86,9 +103,11 @@ matrix:
- gcc-8
compiler: gcc-8
env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough -Wno-error=format-overflow"
+ 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
- os: linux
compiler: clang
+ if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
#clang version 3.5.0 (tags/RELEASE_350/final)
- os: linux
addons:
@@ -103,6 +122,7 @@ matrix:
- p7zip-full
- clang-3.5
compiler: clang-3.5
+ if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
#Ubuntu clang version 3.5.0-4ubuntu2~trusty2 (tags/RELEASE_350/final) (based on LLVM 3.5.0)
- os: linux
addons:
@@ -118,6 +138,7 @@ matrix:
- p7zip-full
- clang-3.6
compiler: clang-3.6
+ if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
#Ubuntu clang version 3.6.2-svn240577-1~exp1 (branches/release_36) (based on LLVM 3.6.2)
- os: linux
addons:
@@ -133,6 +154,7 @@ matrix:
- p7zip-full
- clang-3.7
compiler: clang-3.7
+ if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
#Ubuntu clang version 3.7.1-svn253571-1~exp1 (branches/release_37) (based on LLVM 3.7.1)
- os: linux
addons:
@@ -148,6 +170,7 @@ matrix:
- p7zip-full
- clang-3.8
compiler: clang-3.8
+ if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
#clang version 3.8.1-svn271127-1~exp1 (branches/release_38)
- os: linux
addons:
@@ -163,6 +186,7 @@ matrix:
- p7zip-full
- clang-3.9
compiler: clang-3.9
+ if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
#clang version 3.9.X
# - os: linux
# addons:
@@ -178,6 +202,7 @@ matrix:
# - p7zip-full
# - clang-4.0
# compiler: clang-4.0
+# if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
# #clang version 4.0.X
# - os: linux
# addons:
@@ -193,32 +218,321 @@ matrix:
# - p7zip-full
# - clang-5.0
# compiler: clang-5.0
+# if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
# #clang version 5.0.X
# - os: osx
# osx_image: beta-xcode6.1
+# if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
# #Apple LLVM version 6.0 (clang-600.0.54) (based on LLVM 3.5svn)
# - os: osx
# osx_image: beta-xcode6.2
# compiler: gcc
+# if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
# #Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn)
## - os: osx
## osx_image: beta-xcode6.3
+## if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
## #I think xcode.6.3 VM is broken, it does not boot
# - os: osx
# osx_image: xcode6.4
+# if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
# #Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
# - os: osx
# osx_image: xcode7
+# if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
# #Apple LLVM version 7.0.0 (clang-700.0.72)
# - os: osx
# osx_image: xcode7.1
+# if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
# #Apple LLVM version 7.0.0 (clang-700.1.76)
# - os: osx
# osx_image: xcode7.2
+# if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
# #Apple LLVM version 7.0.2 (clang-700.1.81)
- os: osx
osx_image: xcode7.3
+ if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
#Apple LLVM version 7.3.0 (clang-703.0.31)
+
+
+################################
+# Deployer Buildbots - OSX
+################################
+ - os: osx
+ osx_image: xcode7.3
+ if: env(DPL_ENABLED) = "1" AND (env(_DPL_JOB_ENABLED) = "1" OR env(DPL_JOB_ENABLE_ALL) = "1")
+ AND (branch =~ /^.*deployer.*$/ OR (tag IS present AND env(DPL_TAG_ENABLED) = "1"))
+ AND env(DPL_TERMINATE_MAIN) != "1"
+ env:
+ - _DPL_JOB_ENABLED=1
+ - _DPL_JOB_NAME=osx
+ - _DPL_FTP_TARGET=1
+ - _DPL_PACKAGE_BINARY=1
+ #Apple LLVM version 7.3.0 (clang-703.0.31)
+
+
+################################
+# Deployer Buildbots - Linux assets
+# Set DPL_TERMINATE_ASSETS to disable all of these
+# List Ubuntu LTS next, newest to oldest
+# Then list non-LTS, newest to oldest
+################################
+ - os: linux
+ addons:
+ apt:
+ packages:
+ - libsdl2-mixer-dev
+ - libpng-dev
+ - libgl1-mesa-dev
+ - libgme-dev
+ - p7zip-full
+ - gcc-4.8
+ compiler: gcc-4.8
+ dist: xenial
+ if: env(DPL_ENABLED) = "1" AND (env(_DPL_JOB_ENABLED) = "1" OR env(DPL_JOB_ENABLE_ALL) = "1")
+ AND (branch =~ /^.*deployer.*$/ OR (tag IS present AND env(DPL_TAG_ENABLED) = "1"))
+ AND env(DPL_TERMINATE_ASSETS) != "1"
+ env:
+ - _DPL_JOB_ENABLED=1
+ - _DPL_JOB_NAME=bionic-asset
+ - _DPL_DPUT_TARGET=1
+ - _DPL_PACKAGE_SOURCE=1
+ - _DPL_PACKAGE_MAIN=0
+ - _DPL_PACKAGE_ASSET=1
+ - PACKAGE_DISTRO=bionic
+ #- PACKAGE_SUBVERSION=~18.04bionic
+ #gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5
+
+ ################################
+ # The below asset bots produce packages that occupy too much space.
+ # It would be nice if the asset files were not included in the source package itself,
+ # so these can deploy to each Ubuntu target without manual intervention.
+ #
+ # Currently, to get around Launchpad's space limitation,
+ # copy the packages from *one* bot and the space usage is not increased.
+ ################################
+ # - os: linux
+ # addons:
+ # apt:
+ # packages:
+ # - libsdl2-mixer-dev
+ # - libpng-dev
+ # - libgl1-mesa-dev
+ # - libgme-dev
+ # - p7zip-full
+ # - gcc-4.8
+ # compiler: gcc-4.8
+ # dist: trusty
+ # if: env(DPL_ENABLED) = "1" AND (env(_DPL_JOB_ENABLED) = "1" OR env(DPL_JOB_ENABLE_ALL) = "1")
+ # AND (branch =~ /^.*deployer.*$/ OR (tag IS present AND env(DPL_TAG_ENABLED) = "1"))
+ # AND env(DPL_TERMINATE_ASSETS) != "1"
+ # env:
+ # - _DPL_JOB_ENABLED=1
+ # - _DPL_JOB_NAME=trusty-asset
+ # - _DPL_DPUT_TARGET=1
+ # - _DPL_PACKAGE_SOURCE=1
+ # - _DPL_PACKAGE_MAIN=0
+ # - _DPL_PACKAGE_ASSET=1
+ # - PACKAGE_DISTRO=trusty
+ # #- PACKAGE_SUBVERSION=~14.04trusty
+ # #gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5
+ # - os: linux
+ # addons:
+ # apt:
+ # packages:
+ # - libsdl2-mixer-dev
+ # - libpng-dev
+ # - libgl1-mesa-dev
+ # - libgme-dev
+ # - p7zip-full
+ # - gcc-4.8
+ # compiler: gcc-4.8
+ # dist: xenial
+ # if: env(DPL_ENABLED) = "1" AND (env(_DPL_JOB_ENABLED) = "1" OR env(DPL_JOB_ENABLE_ALL) = "1")
+ # AND (branch =~ /^.*deployer.*$/ OR (tag IS present AND env(DPL_TAG_ENABLED) = "1"))
+ # AND env(DPL_TERMINATE_ASSETS) != "1"
+ # env:
+ # - _DPL_JOB_ENABLED=1
+ # - _DPL_JOB_NAME=disco-asset
+ # - _DPL_DPUT_TARGET=1
+ # - _DPL_PACKAGE_SOURCE=1
+ # - _DPL_PACKAGE_MAIN=0
+ # - _DPL_PACKAGE_ASSET=1
+ # - PACKAGE_DISTRO=disco
+ # #- PACKAGE_SUBVERSION=~19.04disco
+ # #gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5
+ # - os: linux
+ # addons:
+ # apt:
+ # packages:
+ # - libsdl2-mixer-dev
+ # - libpng-dev
+ # - libgl1-mesa-dev
+ # - libgme-dev
+ # - p7zip-full
+ # - gcc-4.8
+ # compiler: gcc-4.8
+ # dist: xenial
+ # if: env(DPL_ENABLED) = "1" AND (env(_DPL_JOB_ENABLED) = "1" OR env(DPL_JOB_ENABLE_ALL) = "1")
+ # AND (branch =~ /^.*deployer.*$/ OR (tag IS present AND env(DPL_TAG_ENABLED) = "1"))
+ # AND env(DPL_TERMINATE_ASSETS) != "1"
+ # env:
+ # - _DPL_JOB_ENABLED=1
+ # - _DPL_JOB_NAME=cosmic-asset
+ # - _DPL_DPUT_TARGET=1
+ # - _DPL_PACKAGE_SOURCE=1
+ # - _DPL_PACKAGE_MAIN=0
+ # - _DPL_PACKAGE_ASSET=1
+ # - PACKAGE_DISTRO=cosmic
+ # #- PACKAGE_SUBVERSION=~18.10cosmic
+ # #gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5
+ # - os: linux
+ # addons:
+ # apt:
+ # packages:
+ # - libsdl2-mixer-dev
+ # - libpng-dev
+ # - libgl1-mesa-dev
+ # - libgme-dev
+ # - p7zip-full
+ # - gcc-4.8
+ # compiler: gcc-4.8
+ # dist: xenial
+ # if: env(DPL_ENABLED) = "1" AND (env(_DPL_JOB_ENABLED) = "1" OR env(DPL_JOB_ENABLE_ALL) = "1")
+ # AND (branch =~ /^.*deployer.*$/ OR (tag IS present AND env(DPL_TAG_ENABLED) = "1"))
+ # AND env(DPL_TERMINATE_ASSETS) != "1"
+ # env:
+ # - _DPL_JOB_ENABLED=1
+ # - _DPL_JOB_NAME=xenial-asset
+ # - _DPL_DPUT_TARGET=1
+ # - _DPL_PACKAGE_SOURCE=1
+ # - _DPL_PACKAGE_MAIN=0
+ # - _DPL_PACKAGE_ASSET=1
+ # - PACKAGE_DISTRO=xenial
+ # #- PACKAGE_SUBVERSION=~16.04xenial
+ # #gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5
+
+
+################################
+# Deployer Buildbots - Linux binaries
+# List Ubuntu LTS, newest to oldest
+# Then list non-LTS, newest to oldest
+################################
+ - os: linux
+ addons:
+ apt:
+ packages:
+ - libsdl2-mixer-dev
+ - libpng-dev
+ - libgl1-mesa-dev
+ - libgme-dev
+ - p7zip-full
+ - gcc-4.8
+ compiler: gcc-4.8
+ dist: xenial
+ if: env(DPL_ENABLED) = "1" AND (env(_DPL_JOB_ENABLED) = "1" OR env(DPL_JOB_ENABLE_ALL) = "1")
+ AND (branch =~ /^.*deployer.*$/ OR (tag IS present AND env(DPL_TAG_ENABLED) = "1"))
+ AND env(DPL_TERMINATE_MAIN) != "1"
+ env:
+ - _DPL_JOB_ENABLED=1
+ - _DPL_JOB_NAME=bionic
+ - _DPL_DPUT_TARGET=1
+ - _DPL_PACKAGE_SOURCE=1
+ - PACKAGE_DISTRO=bionic
+ - PACKAGE_SUBVERSION=~18.04bionic
+ #gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5
+ - os: linux
+ addons:
+ apt:
+ packages:
+ - libsdl2-mixer-dev
+ - libpng-dev
+ - libgl1-mesa-dev
+ - libgme-dev
+ - p7zip-full
+ - gcc-4.8
+ compiler: gcc-4.8
+ dist: trusty
+ if: env(DPL_ENABLED) = "1" AND (env(_DPL_JOB_ENABLED) = "1" OR env(DPL_JOB_ENABLE_ALL) = "1")
+ AND (branch =~ /^.*deployer.*$/ OR (tag IS present AND env(DPL_TAG_ENABLED) = "1"))
+ AND env(DPL_TERMINATE_MAIN) != "1"
+ env:
+ - _DPL_JOB_ENABLED=1
+ - _DPL_JOB_NAME=trusty
+ - _DPL_DPUT_TARGET=1
+ - _DPL_PACKAGE_SOURCE=1
+ - PACKAGE_DISTRO=trusty
+ - PACKAGE_SUBVERSION=~14.04trusty
+ #gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5
+ - os: linux
+ addons:
+ apt:
+ packages:
+ - libsdl2-mixer-dev
+ - libpng-dev
+ - libgl1-mesa-dev
+ - libgme-dev
+ - p7zip-full
+ - gcc-4.8
+ compiler: gcc-4.8
+ dist: xenial
+ if: env(DPL_ENABLED) = "1" AND (env(_DPL_JOB_ENABLED) = "1" OR env(DPL_JOB_ENABLE_ALL) = "1")
+ AND (branch =~ /^.*deployer.*$/ OR (tag IS present AND env(DPL_TAG_ENABLED) = "1"))
+ AND env(DPL_TERMINATE_MAIN) != "1"
+ env:
+ - _DPL_JOB_ENABLED=1
+ - _DPL_JOB_NAME=disco
+ - _DPL_DPUT_TARGET=1
+ - _DPL_PACKAGE_SOURCE=1
+ - PACKAGE_DISTRO=disco
+ - PACKAGE_SUBVERSION=~19.04disco
+ #gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5
+ - os: linux
+ addons:
+ apt:
+ packages:
+ - libsdl2-mixer-dev
+ - libpng-dev
+ - libgl1-mesa-dev
+ - libgme-dev
+ - p7zip-full
+ - gcc-4.8
+ compiler: gcc-4.8
+ dist: xenial
+ if: env(DPL_ENABLED) = "1" AND (env(_DPL_JOB_ENABLED) = "1" OR env(DPL_JOB_ENABLE_ALL) = "1")
+ AND (branch =~ /^.*deployer.*$/ OR (tag IS present AND env(DPL_TAG_ENABLED) = "1"))
+ AND env(DPL_TERMINATE_MAIN) != "1"
+ env:
+ - _DPL_JOB_ENABLED=1
+ - _DPL_JOB_NAME=cosmic
+ - _DPL_DPUT_TARGET=1
+ - _DPL_PACKAGE_SOURCE=1
+ - PACKAGE_DISTRO=cosmic
+ - PACKAGE_SUBVERSION=~18.10cosmic
+ #gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5
+ - os: linux
+ addons:
+ apt:
+ packages:
+ - libsdl2-mixer-dev
+ - libpng-dev
+ - libgl1-mesa-dev
+ - libgme-dev
+ - p7zip-full
+ - gcc-4.8
+ compiler: gcc-4.8
+ dist: xenial
+ if: env(DPL_ENABLED) = "1" AND (env(_DPL_JOB_ENABLED) = "1" OR env(DPL_JOB_ENABLE_ALL) = "1")
+ AND (branch =~ /^.*deployer.*$/ OR (tag IS present AND env(DPL_TAG_ENABLED) = "1"))
+ AND env(DPL_TERMINATE_MAIN) != "1"
+ env:
+ - _DPL_JOB_ENABLED=1
+ - _DPL_JOB_NAME=xenial
+ - _DPL_DPUT_TARGET=1
+ - _DPL_PACKAGE_SOURCE=1
+ - PACKAGE_DISTRO=xenial
+ - PACKAGE_SUBVERSION=~16.04xenial
+ #gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5
allow_failures:
- compiler: clang-3.5
- compiler: clang-3.6
@@ -228,12 +542,14 @@ matrix:
- compiler: clang-4.0
- compiler: clang-5.0
+
cache:
apt: true
ccache: true
directories:
- $HOME/srb2_cache
+
addons:
apt:
packages:
@@ -241,23 +557,127 @@ addons:
- libpng-dev
- libgl1-mesa-dev
- libgme-dev
+ - zlib1g-dev
- p7zip-full
-before_script:
- - wget --verbose --server-response -c http://rosenthalcastle.org/srb2/SRB2-v2115-assets-2.7z -O $HOME/srb2_cache/SRB2-v2115-assets-2.7z
- - 7z x $HOME/srb2_cache/SRB2-v2115-assets-2.7z -oassets
- - mkdir build
- - cd build
- - export CFLAGS="-Wall -W -Werror $WFLAGS"
- - export CCACHE_COMPRESS=true
- - cmake .. -DCMAKE_BUILD_TYPE=Release
before_install:
- - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi
- - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install sdl2 sdl2_mixer game-music-emu p7zip; fi
- - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install cmake||true; fi
- - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then curl -O -L https://www.libsdl.org/release/SDL2-2.0.6.dmg; hdiutil attach SDL2-2.0.6.dmg; sudo cp -a /Volumes/SDL2/SDL2.framework /Library/Frameworks/; fi
- - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then curl -O -L https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-2.0.1.dmg; hdiutil attach SDL2_mixer-2.0.1.dmg; sudo cp -a /Volumes/SDL2_mixer/SDL2_mixer.framework /Library/Frameworks/; fi
+ # Initialize Deployer defaults
+ - . ./deployer/travis/deployer_defaults.sh
+
+ # Initialize Deployer; check if Deployer is enabled
+ # This needs to be run in the current shell so that $__DPL_ACTIVE is set for this session
+ - . ./deployer/travis/deployer.sh
+
+ # Also check if we should now terminate -- see `deployer.sh` for conditions.
+ # This should never happen on non-release buildbots when Deployer is not triggered.
+ - if [[ "$__DPL_TRY_TERMINATE_EARLY" == "1" ]]; then
+ if [[ "$__DPL_ACTIVE" != "1" ]]; then
+ echo "Exiting early because this job is not deploying.";
+ exit;
+ fi;
+ fi
+
+ # If we're triggered by release tag, force ASSET_FILES_OPTIONAL_GET=1
+ - if [[ "$__DPL_TAG_ELIGIBLE" = "1" ]]; then
+ ASSET_FILES_OPTIONAL_GET=1;
+ fi;
+
+
+install:
+ # Install OS X library dependencies via Homebrew
+ # Do this differently for release buildbots:
+ # * `brew install --build-bottle` builds libraries for x86_64's lowest common denominator CPU, core2
+ # * `sdl2_mixer` requires options from the formula tap https://github.com/mazmazz/homebrew-srb2
+ # * `brew postinstall` runs post-install scripts after building a bottle
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
+ brew update;
+ brew tap mazmazz/srb2;
+ fi;
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
+ if [[ "$__DPL_ACTIVE" != "1" ]]; then
+ brew install sdl2 sdl2_mixer game-music-emu p7zip;
+ brew install cmake||true;
+ else
+ brew install --build-bottle sdl2 game-music-emu p7zip;
+ brew install --build-bottle mazmazz/srb2/sdl2_mixer --with-flac --with-mpg123;
+ brew postinstall sdl2 game-music-emu p7zip mazmazz/srb2/sdl2_mixer;
+ brew install cmake||true;
+ fi;
+ fi
- mkdir -p $HOME/srb2_cache
-script: make -k
+
+before_script:
+ # OLDPWD is root repo folder
+ - OLDPWD=$PWD
+ - __ASSET_DIRECTORY="$OLDPWD/assets/installer"
+ - mkdir -p "$__ASSET_DIRECTORY"
+ - cd "$HOME/srb2_cache"
+
+ # Get stat command so we know what the cached archive date is.
+ # stat is different for OSX
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
+ STATCMD="stat -f %m";
+ else
+ STATCMD="stat -c %y";
+ fi
+
+ # Get asset files (required for MD5)
+ # See `deployer_defaults.sh` for asset download path
+ - if [[ "$ASSET_ARCHIVE_PATH" != "" ]]; then
+ if [ -f "$(basename $ASSET_ARCHIVE_PATH)" ]; then
+ echo "$(basename $ASSET_ARCHIVE_PATH) cache date -- $($STATCMD $(basename $ASSET_ARCHIVE_PATH))";
+ fi;
+ wget --verbose --server-response -N "$ASSET_ARCHIVE_PATH";
+ 7z x "$(basename $ASSET_ARCHIVE_PATH)" -o"$__ASSET_DIRECTORY" -aos;
+ fi;
+
+ # Get optional files too
+ - if [[ "$__DPL_ACTIVE" == "1" ]] && [[ "$ASSET_FILES_OPTIONAL_GET" == "1" ]] && [[ "$ASSET_ARCHIVE_OPTIONAL_PATH" != "" ]]; then
+ if [ -f "$(basename $ASSET_ARCHIVE_OPTIONAL_PATH)" ]; then
+ echo "$(basename $ASSET_ARCHIVE_OPTIONAL_PATH) cache date -- $($STATCMD $(basename $ASSET_ARCHIVE_OPTIONAL_PATH))";
+ fi;
+ wget --verbose --server-response -N "$ASSET_ARCHIVE_OPTIONAL_PATH";
+ 7z x "$(basename $ASSET_ARCHIVE_OPTIONAL_PATH)" -o"$__ASSET_DIRECTORY" -aos;
+ fi;
+
+ # Go back to root repo folder
+ - cd "$OLDPWD"
+
+ # Prepare CMake asset lists
+ - SRB2_ASSET_HASHED=$(echo ${ASSET_FILES_HASHED// /\;})
+ - SRB2_ASSET_DOCS=$(echo ${ASSET_FILES_DOCS// /\;})
+ - SRB2_ASSET_DIRECTORY="$__ASSET_DIRECTORY"
+
+ # Prepare CMake
+ - mkdir build
+ - cd build
+ - mkdir package
+ - export CFLAGS="-Wall -W -Werror $WFLAGS"
+ - export CCACHE_COMPRESS=true
+ # If OS X, set -march=core2 to build compatible binaries with old Macs
+ - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
+ export CFLAGS="${CFLAGS} -march=core2";
+ fi;
+ - cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$PWD/bin -DCPACK_PACKAGE_DIRECTORY=$PWD/package
+ -DSRB2_ASSET_HASHED="${SRB2_ASSET_HASHED}" -DSRB2_ASSET_DOCS="${SRB2_ASSET_DOCS}"
+ -DSRB2_ASSET_DIRECTORY="${SRB2_ASSET_DIRECTORY}"
+ -DCPACK_PACKAGE_DESCRIPTION_SUMMARY="${PROGRAM_NAME}"
+ -DCPACK_PACKAGE_VENDOR="${PROGRAM_VENDOR}"
+ -DSRB2_SDL2_EXE_NAME="${PROGRAM_FILENAME}"
+
+
+script:
+ # Build our Makefile from Cmake!
+ - if [[ "$__DPL_ACTIVE" == "1" ]]; then
+ . ../deployer/travis/deployer_build.sh;
+ else
+ make -k;
+ fi;
+
+after_success:
+ # Run the upload scripts
+ # These do nothing if Deployer is not triggered
+ - . ../deployer/travis/deployer_ftp.sh
+ - . ../deployer/travis/deployer_dput.sh
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d81947641..43142386d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,8 @@
cmake_minimum_required(VERSION 3.0)
+# DO NOT CHANGE THIS SRB2 STRING! Some variable names depend on this string.
+# Version change is fine.
project(SRB2
- VERSION 2.1.23
+ VERSION 1.0.2
LANGUAGES C)
if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR})
@@ -86,8 +88,8 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(CMAKE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
# Set EXE names so the assets CMakeLists can refer to its target
-set(SRB2_SDL2_EXE_NAME srb2)
-set(SRB2_WIN_EXE_NAME srb2dd)
+set(SRB2_SDL2_EXE_NAME srb2kart CACHE STRING "Executable binary output name")
+set(SRB2_WIN_EXE_NAME srb2kartdd CACHE STRING "Executable binary output name for DirectDraw build")
include_directories(${CMAKE_CURRENT_BINARY_DIR}/src)
@@ -116,8 +118,8 @@ if(${CMAKE_SYSTEM} MATCHES "Darwin")
set(CPACK_GENERATOR "DragNDrop")
endif()
-set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Sonic Robo Blast 2 Kart")
-set(CPACK_PACKAGE_VENDOR "Sonic Team Jr.")
+set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Sonic Robo Blast 2 Kart" CACHE STRING "Program name for display purposes")
+set(CPACK_PACKAGE_VENDOR "Kart Krew" CACHE STRING "Vendor name for display purposes")
#set(CPACK_PACKAGE_DESCRIPTION_FILE )
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_PACKAGE_VERSION_MAJOR ${SRB2_VERSION_MAJOR})
diff --git a/SRB2.cbp b/SRB2.cbp
index 2a1eb87b8..acdc61c7f 100644
--- a/SRB2.cbp
+++ b/SRB2.cbp
@@ -1545,6 +1545,10 @@ HW3SOUND for 3D hardware sound support
+
+
+
+
diff --git a/appveyor.yml b/appveyor.yml
index f0f843fbb..e7ce1b2f7 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,4 +1,4 @@
-version: 2.1.23.{branch}-{build}
+version: 1.0.2.{branch}-{build}
os: MinGW
environment:
@@ -29,15 +29,15 @@ environment:
##############################
DPL_ENABLED: 0
DPL_TAG_ENABLED: 0
- DPL_INSTALLER_NAME: SRB2-v2123
+ DPL_INSTALLER_NAME: srb2kart-v102
# 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.
# The x86/x64 archives contain the DLL binaries.
- ASSET_ARCHIVE_PATH: https://github.com/mazmazz/SRB2/releases/download/SRB2_assets/SRB2-v2122-assets.7z
- ASSET_ARCHIVE_PATCH_PATH: https://github.com/mazmazz/SRB2/releases/download/SRB2_assets/SRB2-v2122-patch-assets.7z
- ASSET_ARCHIVE_X86_PATH: https://github.com/mazmazz/SRB2/releases/download/SRB2_assets/SRB2-v2122-x86-assets.7z
- ASSET_ARCHIVE_X64_PATH: https://github.com/mazmazz/SRB2/releases/download/SRB2_assets/SRB2-v2122-x64-assets.7z
- ASSET_ARCHIVE_OPTIONAL_PATH: https://github.com/mazmazz/SRB2/releases/download/SRB2_assets/SRB2-v2122-optional-assets.7z
+ ASSET_ARCHIVE_PATH: https://github.com/mazmazz/Kart-Public/releases/download/kart_assets/srb2kart-v102-assets.7z
+ ASSET_ARCHIVE_PATCH_PATH: https://github.com/mazmazz/Kart-Public/releases/download/kart_assets/srb2kart-v102-patch-assets.7z
+ ASSET_ARCHIVE_X86_PATH: https://github.com/mazmazz/Kart-Public/releases/download/kart_assets/srb2kart-v102-x86-assets.7z
+ ASSET_ARCHIVE_X64_PATH: https://github.com/mazmazz/Kart-Public/releases/download/kart_assets/srb2kart-v102-x64-assets.7z
+ ASSET_ARCHIVE_OPTIONAL_PATH: https://github.com/mazmazz/Kart-Public/releases/download/kart_assets/srb2kart-v102-optional-assets.7z
# This is overridden to 1 for release tag builds
ASSET_FILES_OPTIONAL_GET: 0
# For patches, also include the X86/X64 DLLs.
@@ -75,8 +75,8 @@ install:
configuration:
- SDL
- SDL64
-- DD
-- DD64
+#- DD
+#- DD64
matrix:
allow_failures:
diff --git a/assets/.gitignore b/assets/.gitignore
index 9ed61ca1a..b9dc7c70d 100644
--- a/assets/.gitignore
+++ b/assets/.gitignore
@@ -1,5 +1,12 @@
-*
-*.*
+*.srb
+*.pk3
+*.dta
+*.wad
+*.txt
+*.kart
!README.txt
+!HISTORY.txt
!LICENSE.txt
-!LICENSE-3RD-PARTY.txt
\ No newline at end of file
+!LICENSE-3RD-PARTY.txt
+!CMakeLists.txt
+!debian-template/*
diff --git a/assets/CMakeLists.txt b/assets/CMakeLists.txt
index 2cf93c84a..1eab62cc9 100644
--- a/assets/CMakeLists.txt
+++ b/assets/CMakeLists.txt
@@ -1,46 +1,60 @@
## Assets Target Configuration ##
-# MD5 generation
-set(SRB2_ASSET_ALL
- ${CMAKE_CURRENT_SOURCE_DIR}/srb2.srb
- #${CMAKE_CURRENT_SOURCE_DIR}/patch.dta
- ${CMAKE_CURRENT_SOURCE_DIR}/patch.kart
- ${CMAKE_CURRENT_SOURCE_DIR}/gfx.kart
- ${CMAKE_CURRENT_SOURCE_DIR}/textures.kart
- ${CMAKE_CURRENT_SOURCE_DIR}/chars.kart
- ${CMAKE_CURRENT_SOURCE_DIR}/maps.kart
- ${CMAKE_CURRENT_SOURCE_DIR}/sounds.kart
- #${CMAKE_CURRENT_SOURCE_DIR}/music.dta
- ${CMAKE_CURRENT_SOURCE_DIR}/music.kart
- ${CMAKE_CURRENT_SOURCE_DIR}/README.txt
- ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt
- ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE-3RD-PARTY.txt
-)
+# For prepending the current source path, later
+FUNCTION(PREPEND var prefix)
+ SET(listVar "")
+ FOREACH(f ${ARGN})
+ LIST(APPEND listVar "${prefix}/${f}")
+ ENDFOREACH(f)
+ SET(${var} "${listVar}" PARENT_SCOPE)
+ENDFUNCTION(PREPEND)
+
+set(SRB2_ASSET_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/installer"
+ CACHE STRING "Path to directory that contains all asset files for the installer.")
set(SRB2_ASSET_HASHED
- srb2.srb
- #patch.dta
- patch.kart
- gfx.kart
- textures.kart
- chars.kart
- maps.kart
+"srb2.srb;\
+patch.kart;\
+gfx.kart;\
+textures.kart;\
+chars.kart;\
+maps.kart"
+ CACHE STRING "Asset filenames to apply MD5 checks. No spaces between entries!"
)
+set(SRB2_ASSET_DOCS
+"README.txt;\
+HISTORY.txt;\
+LICENSE.txt;\
+LICENSE-3RD-PARTY.txt"
+ CACHE STRING "Documentation filenames. In OS X, these are packaged separately from other assets. No spaces between entries!"
+)
+
+PREPEND(SRB2_ASSET_DOCS ${SRB2_ASSET_DIRECTORY} ${SRB2_ASSET_DOCS})
+
foreach(SRB2_ASSET ${SRB2_ASSET_HASHED})
- file(MD5 ${CMAKE_CURRENT_SOURCE_DIR}/${SRB2_ASSET} "SRB2_ASSET_${SRB2_ASSET}_HASH")
+ file(MD5 ${SRB2_ASSET_DIRECTORY}/${SRB2_ASSET} "SRB2_ASSET_${SRB2_ASSET}_HASH")
set(SRB2_ASSET_${SRB2_ASSET}_HASH ${SRB2_ASSET_${SRB2_ASSET}_HASH} PARENT_SCOPE)
endforeach()
# Installation
-if(CLANG)
+if(${CMAKE_SYSTEM} MATCHES Darwin)
get_target_property(outname SRB2SDL2 OUTPUT_NAME)
- install(FILES ${SRB2_ASSET_ALL}
+ install(DIRECTORY "${SRB2_ASSET_DIRECTORY}/"
DESTINATION "${outname}.app/Contents/Resources"
)
+ install(FILES ${SRB2_ASSET_DOCS}
+ DESTINATION .
+ OPTIONAL
+ )
else()
- install(FILES ${SRB2_ASSET_ALL}
+ install(DIRECTORY "${SRB2_ASSET_DIRECTORY}/"
DESTINATION .
)
+ # Docs are assumed to be located in SRB2_ASSET_DIRECTORY, so don't install again
+ #install(FILES ${SRB2_ASSET_DOCS}
+ # DESTINATION .
+ # OPTIONAL
+ #)
endif()
diff --git a/assets/HISTORY.txt b/assets/HISTORY.txt
new file mode 100644
index 000000000..dfa06f2c7
--- /dev/null
+++ b/assets/HISTORY.txt
@@ -0,0 +1,202 @@
+KartKrew: Chapter 1.0 - Who Would Actually Read All This???? [LIVE DOC]
+
+
+-beep-
+
+
+[Chromatian dual-wields onto the interview set, stage left, and takes a seat next to VelocitOni. Oni stands up to look at the confused camera-men before opening a binder to stoically show both of his redone Tails sprites for Kart 1.0 and Vanilla 2.2. He closes it and sits back down, the three sofa cushions being Sryder, toaster, and Lat’s limp timezone’d bodies respectively; throwing arm over the side of the Fooruman pillow]
+
+Chrome: Uh…......anyway Chaos Zero 64, a Vanilla SRB2 Developer at the time, during the “heyday” of Sonic Riders started working on his own side project of recreating that game in SRB2 v1.09.4. After programming a functional recreation, he went a step further and threw together a new race mode for all of the characters in the playable exe. After THAT, he took it another step further and made a Mario Kart game type as well. A bunch of young mappers (Including current KartKrew™ dev members Blade & I) tossed him a few maps and he called it a complete exe.
+
+ While fully functional, it was as barebones as you could get. Character stats were altered Vanilla stats (lowered jump, speed, no spindash, and no drifting!) weapon rings reskinned into mario items, and a bunch of checkpoints that you had to hit to count as a lap around the course. It was pretty jank, but seeing all of those dents in the core gameplay is what gave way to the inspiration to push it further than what it initially was.
+
+Oni: There’s only one way to describe how I found it in 1.09.4, and the phrasing kinda caught on (to my pleasure), “ghetto footrace”. It was definitely an absolute MIRACLE at the time to even have SRB2 do anything different from it’s main gameplay scheme, bare ass open maps with collapsing FOFs; and the entire community as a whole was younger… so we all ate it up anyways. Standards were lower, times were simpler, we still really appreciate CZ for trying something ‘new’. When you pulled the wool off though, it was just ghetto footrace with reskinned buttons and totally unique…but also totally random weapon panels.
+
+
+
+[FlareBlade pops out of loose pipe in the room for some reason and hits his head on a kitchen sink.]
+
+
+
+Blade: While most of the maps back then harkened back to the simpler style of the 1.09.4 era; and were scrapped as SRB2 as a whole improved, Pipe Speedway has survived all the way to the present, although with a heavy style change, including a new name! (Now Daytona Speedway)
+
+Oni: [laughs] You really like that map, don’t you?
+
+Random Audience Member:[shouting] PICK, PICK STARDUST!!
+
+[The audience member is immediately shot through the heart with striking accuracy... the vote-screen SFX of a map being picked and Palmtree Panic Zone kids screaming "Yeah!" sounds. Cut to SeventhSentinel who just logged into the middle of the room with a shocked expression, smoking quality-controlling Desert Eagle in hand. The audience member's mask falls off, turning out to be Stardust Speedway Battle himself, now dead from the rotation.]
+
+Sev: Why would Blade do this…?
+
+
+Chrome: Pipe Speedway opened the PIPES for Kart’s 2.0 development, you could say. [laughs]
+
+Blade: Well, it WAS the first one to be slope-ified! Mostly as a proof-of-concept to show what could be done. (the rest of you lot were too busy with that “TD” thing…) And then you all went and upstaged it anyway with some of the other maps. [chuckles] //shade
+
+Oni: Yeah, while we finished ANOTHER full fledged mod, you actually got about 54% done with Pipe Speedway after 4 years! I was impressed. ////clapback
+
+Chrome: Still, Blade kept the campfire lit while we went in search of food, that takes some dedication.
+
+Oni: No. That was Blitz-T who continued making entire maps the whole time--
+
+Blade --Thank you. Overall though, the original kart was more-or-less a side feature of Riders. Never really the main focus of the mod, but without a doubt the most popular part of it. The other two modes never really caught on. (Though we did have that ill-fated “Rivals” mod…) =P
+
+
+
+Oni: [Holding a knife up to the two] The “what” mod?? Anywho, I was a frequent player of 1.09.4 but never really in the community much until 2.0. It wasn’t until CZ ported his mod to be up to date, that I jumped in with the idea that I actually had enough of a brain to contribute to things… the problem was that my standards from the get-go were way way too high, and my skill as a spriter and general design experience were a lot lower. Nevertheless, when SRB2Riders hype died down, I approached him in DMs with all my expectations and ideas for his mod...and… surprisingly he didn’t laugh me out! I guess he’d never had anyone directly tell him they’d help outright before (besides Ground The Fox), but he was a bit noticeably bummed that I only cared for what he’d considered the minor Mario mod within the mod.
+
+ This is what kickstarted the chain of events. All my plans that I bugged CZ for every other day in PMs never came to fruition, he actually lost interest and began to slowly fade out of the SRB2 community as a whole. Instead out of LITERALLY nowhere, D00D64 decided to revive the SRB2Riders mod himself by releasing a pretty expansive mod...of a mod within a mod OF a mod himself. Naturally, everyone jumped onto this, it exploded in popularity pretty much right away, because there were finally more than just a few mediocre maps to play “kart mode” on. There were PORTS, glorious glorious ports. Of course, I flocked to D00D to help out.
+
+
+
+Blade: Flat, boring, ports. Though the crazy item spam helped. Also we FINALLY got DRIFTING! Separating the characters from the bloat of the other 2 modes also made making custom racers easier to make.
+
+
+
+Oni: ...yeah, the truth is, once the “D00DKart” era started, it didn’t help that there were so many more por-- er, maps to play kart-mode on that people realized the formula for a kart racer was just inherently more exciting than what CZ’d pulled off with the Riders half of it. I remember a LOT of content for kart, and then like 2 maps for the more fleshed out and polished main focus of the thing. Everyone just sorta... forgot about Riders mode, sadly. It didn’t help that someone else also exploded onto the scene in a siamese feedback loop once D00D churned out enough maps a day to actually make a full game out of; ZarroTsu, who also saw opportunity too.
+
+ D00DKart and “Super SRB2Kart Z”, a continuation of ChaosZero’s mod, combined into one super project. A ‘team’ just kinda assembled naturally out of this, and more original content started to, slowly but surely, get made by a wider variety of people. The train continued to accelerate, lots of familiar faces coming into play. All the basics you’d expect out of a Mario Kart clone were coded by Zarro, basically updates every single day, stuff just kept getting done by this specific group of people.
+
+
+
+Chrome: That’s about when things for kart started to die down. D00DKart kept the entire game afloat, but Kart was always a sideline to Vanilla. Once D00DKart finally got comfortable, people moved back to Vanilla to see what else they could do with that. Servers stopped popping up as quickly as they used to, and eventually Super SRB2 Kart Z fell into obscurity. It was at this point that the small group still excited for the game tried to push for an even better project.
+
+
+
+Oni: Yep. When steam on this makeshift game finally died, Zarro lost interest too, and outright just vanished for a year or two(?) and when then, when he returned, he had very little momentum to continue. So in the meanwhile we kinda came closer together under the team “Kart Krew”, and in his place Sryder took the helm. Zarro’s vision was always to be a Mario clone, so when he was absent I wanted to push my idea of getting rid of most if not all references to Mario pronto, going for a Sonic aesthetic instead. The idea was that we’ll never be as good as a Nintendo game, and comparisons will always be drawn, so why not do something more unique?
+
+ Progress boomed again, but in private this time. 2013 ended up being the “2.0 indev” period. Standards kept increasing and increasing internally, because no one was satisfied with “ghetto footrace” anymore, we grew out of it and wanted an actual game this time… not play-pretend with all the instathrust hacks and poor game design decisions we were left with. Like shields.
+
+NOBODY liked those shields. We just couldn’t force Zarro to do what he didn’t want with his mod of a mod in a mod of a mod.
+
+
+
+Chrome: [laughs] Whirlwind was just a bit too broken for everyone.
+
+
+
+Oni: Using a Whirlwind Shield felt like playing a game of fucking Twister with my fingers just to reach the convoluted buttons, and you’re rewarded with the equivalent of bomb-jumping into the sky, except your kart is a runaway shower tub on pig grease. Awful. But good going, you ruined the entire race! Your slap on the wrist is now an unavoidable Armageddon Shield to the entire server by that Brazilian player who accidentally somehow made it to Lap 2 by RNG.
+
+ Mechanics were being edited, handling changed a bit, sprites were getting updated (notably the karts themselves), videos were being released from each of our channels, maps were bloating, notorious bug fixes at light speed. Unfortunately, literally at the same time, the new “Kart Krew” decided to sink their teeth into the Top Down experiment (we were on a high of too much confidence from all the progress) WHILE the release of Vanilla 2.1 invalidated all thre-- BOTH of our projects in one fell swoop. These were the dark ages, and it only got worse when I decided to disappear TOO before TD even got done. The story behind that development cycle (Top Down took all our Kart focus away when it was in progress) is known by now, but the real unexpected meat happened when we finally pushed that abortion out the door.
+
+
+
+Chrome: You probably should have listened to Blade and stuck with our guns on Kart, and not take a “break” for a new experiment. [laughs]
+
+
+
+[A silhouette outside the window in the rain can be seen with glowing cones, waving. Before anyone can process it, American Airlines smashes through the studio. For some reason Charybdizs walks out of the left-frontmost hatch]
+
+
+Charyb: For the record, Top Down wasn't bad by any means! People are just jumping on it because its dev cycle was complicated and a big learning experience for everyone. There were numerous members who poured their hearts into it! I’m proud of them! But yeah… the dev cycle…
+
+[wolfs can be seen frantically searching for a point in this interview to be relevant, unscheduled anime forcing him to miss most of it]
+
+
+wolfs: Oh man, TD’s dev cycle. What a shitshow. You’d either get a response in 3 seconds or 3 days depending on who was around. Motivation was at an all-time low back then. I felt like I was talking into a vacuum sometime--
+
+Oni: Why the fuck would you interrupt THIS moment, talking about 3 day responses when you’ll be “online” and won’t say anything until Kony’s live fucking body is found. Get outta here.
+
+wolfs: says the guy who disappeared for two years
+
+Oni: 'ey fuk you mane
+
+[Oni can be seen across the room from the plane, his TD_PTSD.td filled breathing into a brown paper bag]
+
+Oni: No, if Top Down were bad it wouldn’t have made half the hype of what Kart is doing now by ITSELF and manage to make it on Retro’s front page. But the dev cycle was purgatory, a big explosion at the start that dwindled to a candlefire, put out by the rain of inactivity...and then reignited by the power of Discord Chat. The actual product itself was pretty decent, and another fresh multiplayer experience not ever done in SRB2. It had hype.
+
+
+Blade: ...When you say the karts were updated, you mean “Oni nit-picked them to death and redid them like 10 times”.
+
+Oni: I wish he were joking about that number.
+
+
+
+Chrome: It all worked out for the better though. That (rather lengthy!) experiment taught us a lot about time management and what not to do for the far more important modification. Discord got popular around this time, and Top Down hopped into that plane, and quickly parachuted out into the community. This gathered a few new, very important members into KartKrew™. TehRealSalt, host of the Sugoi series, Seventh Sentinel, a new mapper with a fresh take on level design, and toaster, a Vanilla dev programmer with a fire for Kart so hot keeping up with her pace is a job in itself. Seriously, without these three members, Kart wouldn’t have the polish it does now.
+
+ It’s around this time that the pioneer in Kart level design returned, Blitz-T. Every map he made for 2.0 indev kart was a jawdropper to everyone on the team, and his attention to the small details were more than impressive. On top of all of this, SRB2 version 2.1 supported sloped planes, something that was as unbelievable for this game as cell phones were back in the 50s.
+ This is where 2.1 Kart really started to shine, Zarro ported the entire game in the span of a few weeks, Blitz-T took his old maps and revamped them with slopes to nearly unrecognizable new iterations, TehRealSalt made the entire Battle mode in the span of a *single* night, and Seventh Sentinel finally gave us looped music and consistent sound quality.
+
+
+
+Blade: Yeah, they really picked up the slack of some of the older members that lost steam, such as myself.
+
+
+
+Oni: Sev, Sal, and toast were the most unexpected things to ever happen to this thing. This shit was literally overnight. It’s really crazy how new blood can help bring a new perspective and vision to the game, along with skills you didn’t know the team was lacking. SO much pressure was taken off of Sryder as Sal and toaster literally slapped the exe until it cried, like frame-perfect Ice Climber handoffs into a 300% wobble. EVERYONE was overwhelmed. I saw the chance and took it, so we decided to go with my vision while Zarro took a backseat. Most, if not all the remaining broken code was just thrown out the window at this point, the game was rapidly feeling cleaner in just nights.
+
+ If you took your eyes off of it for a few hours, something changed massively. The physics went from instathrust to momentum based, Zarro coded new acceleration code, toaster put in 2.2 friction physics as a test that turned out overwhelmingly positive...and also divisive with the previous vision of the mod. These changes were all happening so fast, despite being in kinda stored with me idea-wise for years, that it caused a bit of a rift in what this game was supposed to be. Zarro decided to take a step back and dip because it’d changed so much in just the span of 4 months, he took one good look at 4-Player Splitscreen… a never seen before feat, and just breathed. It didn’t feel like his mod anymore, his personal connection with it felt lost…
+
+[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. They’re such friendly and cooperative coders that I can’t help but push a little harder than I used to (I was WAY lazier before they got here) to keep up.
+
+
+
+
+Chrome: Those kart sprites took a good 6 months longer than they needed to for sure! [laughs]
+
+
+
+
+Oni: [laughs in Latin] It’s not as easy as sloping a single sector in Misty Maze, that’s for sure!
+
+ The mappers went bonkers, especially Blitz-T and TyrannoChao aka “Ezo” (previously ChaoticChao) who’s content probably makes up half the game combined. The creative freedom and supportive style/mentality of how the team is led pretty much went to an unstoppable feedback loop of content AND polish, surprisingly. We got to a point where we could not only lay any remaining ChaosZero64 code that might’ve seeped to rest, but also throw out almost every direct Mario port or reference right down to the sounds. It became a Sonic game, in one year.
+
+
+Blade: Stuff was added so rapidly, even right up to release it always felt like there was something new being added. Bonuschars alone got 2 extra characters added in the week before release!
+
+Oni: Really, if you asked me, I’d say that most of kart just happened since TD released til now, and the rest was just a confused fever dream of passing torches until it all just got thrown out and re-done anyway. That’s why a changelog is pretty pointless, it’s like going to a shop...sitting down…and getting a recommendation for your vehicle; but the paper’s blank and just reads “get new car”. Honestly, playing this and playing the old 2.0 public builds that people like Super Chris still host for some reason is like aging backwards, except you’re really just amputating your skeleton to appear small and young again, it’s HORRIBLE. So if they all liked that… hopefully they’ll like an actually good game...even more??
+
+[Sounds of an angry midnight release crowd erupting outside, muffled. D00D64 can be seen at the forefront...slapping yet another unnaturally high quality gif meme onto the glass window. The camera pans out, there’s hundreds of gif memes all over the outer walls]
+
+Oni: Is it midnight?? I told them to fuck off, there’s no midnight release! @Chromatian FIND SOMETHING TO SAY AFTER ME TO CLOSE THIS UP ALREADY
+
+Chrome: [this shitty Iwata Asks atmosphere cracking at the seams of its own immersion, reality warping his professional and calm demeanor, but he laughs regardless...shakily] You just don’t know when to stop!!
+
+[TehRealSalt struggles trying to get into the room through the tiny doggy door for 5 awkward minutes, before giving up and just opening the door] … [she doesn’t know what to say.]
+
+Oni: EZO
+
+[The towering dinosaur just nonchalantly sits in his chair on-stage, legs crossed, resting his head on his hand]
+
+Ezo: Sticky Kart was a shitshow. [referring to the old controls/physics]
+
+Oni: holy shit YOU CAN’T SAY THAT ZARRO MIGHT BE READING
+
+Ezo: I have no regretties. Except for maybe Arid S--wait, that’s a secret, isn’t it? Hm. Anyway, yeah, working on this was fun. Usually. Learning to sprite was annoying but it paid off since I got to cram Wonder Boy in everyone’s faces like the scaly fucko I am. Though Gamma’s pretty cool too. I hope you all enjoy my Sonic Adventure references and that you all suffer an appropriately huge amount in Egg Quarters and Spotlight Syndicate.
+
+Oni: THIS IS A NON FURRY DOCUMENT :boi:
+
+Ezo: Speciesism UwU
+
+
+
+Boinciel: [screaming from a speaker contained offstage] HI MY NAME IS BOINCIEL I DESIGNED KART MAPS TO DESTROY YOUR EYES AND/OR YOUR SOUL OKAY BYE I HAVE TO DO MY JOB NOW
+
+
+Oni: With a map like Kodachrome…..clearly...
+
+[Off in the corner, a lone wooden coat rack stands, although upon further inspection... It turns out to be, well, CoatRack in a disguise!]
+
+[The entire server pauses for Coat to come up with something]
+
+Coat: You know, these guys all did an awesome job. The controls, the graphics, music too! I just, uh… Had an engine stall on my map, sad how many times I ran out of fuel at a petroleum refinery when making it. Huh. But as one of the more outside members of the krew, just ask anyone, I could be placed under the decorative ornament members with how rarely I dropped in. But each time I did I was blown away by the leaps and bounds, filling me with joy to see this racer come to life. Even if I am a living example of why inanimate objects shouldn’t drive!
+
+[The entire Krew stares at the literal coat rack, smiling wholesomely until Blade opens his mouth]
+
+Blade: Whatever. Enough talking, LET’S GO AWAY!!!!!!!! DAYTONNNAAAAAAAAAAAAAAAA
+
+
+[...the .txt file itself cringes to a halt.]
+
+
+
+
+
+
+
+
+
+
+doot
diff --git a/assets/debian/README.Debian b/assets/debian-template/README.Debian
similarity index 59%
rename from assets/debian/README.Debian
rename to assets/debian-template/README.Debian
index 68c952a4e..f3fe90030 100644
--- a/assets/debian/README.Debian
+++ b/assets/debian-template/README.Debian
@@ -12,9 +12,39 @@ with apt-key add. Thanks!
-- Callum Dickinson Fri, 26 Nov 2010 18:25:31 +1300
+---------------
+
+
+Templating
+
+Note that you MUST run [repo-root]/debian_template.sh before running debuild
+on these scripts! debian_template.sh fills these template files with working values.
+
+You should also set PACKAGE_NAME_EMAIL="John Doe " to match
+the identity of the key you will use to sign the package.
+
+
+Building for Launchpad PPA
+
+Run this step first:
+
+ 1. source [repo-root]/debian_template.sh
+ * Initializes defaults for the package variables and fills in templates.
+
+Use these steps to prepare building a source package for Launchpad:
+
+ 1. cd [repo-root]/assets/
+ 2. debuild -T clean-all (optional; if you already have asset files, this clears them)
+
+Build the source package:
+
+ 1. debuild -T build (this downloads the asset files from srb2.org if necessary)
+ 2. debuild -S (builds the source package for Launchpad, including the asset files)
+
+
Signing for Launchpad PPA
-First, follow the above instructions to generate a GnuPG key with your identity. You will need
+First, follow Callum's instructions to generate a GnuPG key with your identity. You will need
to publish the fingerprint of that key to Ubuntu's key server.
https://help.ubuntu.com/community/GnuPrivacyGuardHowto#Uploading_the_key_to_Ubuntu_keyserver
@@ -26,22 +56,18 @@ upload signed source packages and publish them onto your PPA.
IF YOU UPLOAD A PACKAGE and Launchpad does NOT send you a confirmation or rejection email, that
means your key is not set up correctly with your Launchpad account.
+Finally, if your packages have not already been signed, follow these steps:
-Building for Launchpad PPA
+ 1. cd ..
+ * Packages are located in the parent folder of where debuild was called
+ 2. debsign "srb2-data_[version]_source.changes"
+ * You may need to specify -k [key-fingerprint]
-Use these steps to prepare building a source package for Launchpad:
- 1. Highly recommend copying the assets/ folder to outside your repo folder, or else the asset
- files may be included in the main source package, when you build that.
- 2. cd [wherever-your-assets-folder-is]/assets/
- 3. debuild -T clean (optional, if you already have asset files)
+Uploading for Launchpad PPA
-Building the source package is a two-step process:
-
- 1. debuild -T build (this downloads the asset files from srb2.org if necessary)
- 2. debuild -S (builds the source package for Launchpad, including the asset files)
-
-Then follow the instructions at to upload
+Follow the instructions at to upload
to your PPA and have Launchpad build your binary deb packages.
+
-- Marco Zafra Mon, 26 Nov 2018 21:13:00 -0500
diff --git a/assets/debian/README.source b/assets/debian-template/README.source
similarity index 100%
rename from assets/debian/README.source
rename to assets/debian-template/README.source
diff --git a/assets/debian-template/changelog b/assets/debian-template/changelog
new file mode 100644
index 000000000..64562e2a3
--- /dev/null
+++ b/assets/debian-template/changelog
@@ -0,0 +1,5 @@
+${PACKAGE_NAME}-data (${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION}) ${PACKAGE_DISTRO}; urgency=${PACKAGE_URGENCY}
+
+ * ${PROGRAM_NAME} v${PROGRAM_VERSION} asset data
+
+ -- ${PACKAGE_NAME_EMAIL} ${__PACKAGE_DATETIME}
diff --git a/assets/debian/compat b/assets/debian-template/compat
similarity index 100%
rename from assets/debian/compat
rename to assets/debian-template/compat
diff --git a/assets/debian/control b/assets/debian-template/control
similarity index 84%
rename from assets/debian/control
rename to assets/debian-template/control
index 22d9643ee..ae5c0ce67 100644
--- a/assets/debian/control
+++ b/assets/debian-template/control
@@ -1,15 +1,15 @@
# SRB2-data Debian package control file.
-Source: srb2-data
+Source: ${PACKAGE_NAME}-data
Section: games
Priority: extra
-Maintainer: Sonic Team Junior
+Maintainer: ${PACKAGE_GROUP_NAME_EMAIL}
Build-Depends: debhelper (>= 7.0.50~),
wget
Standards-Version: 3.8.4
-Homepage: http://www.srb2.org
+Homepage: ${PACKAGE_WEBSITE}
-Package: srb2-data
+Package: ${PACKAGE_NAME}-data
Architecture: all
Description: A cross-platform 3D Sonic fangame
Sonic Robo Blast 2 is a 3D open-source Sonic the Hedgehog
diff --git a/debian/copyright b/assets/debian-template/copyright
similarity index 57%
rename from debian/copyright
rename to assets/debian-template/copyright
index 97d606b0f..cc47c453b 100644
--- a/debian/copyright
+++ b/assets/debian-template/copyright
@@ -1,18 +1,18 @@
This work was packaged for Debian by:
- Marco Zafra Mon, 26 Nov 2018 14:31:00 -0500
+ ${PACKAGE_NAME_EMAIL} ${__PACKAGE_DATETIME}
It was downloaded from:
-
+ ${PACKAGE_WEBSITE}
Upstream Author(s):
- Sonic Team Junior
+ ${PACKAGE_GROUP_NAME_EMAIL}
Copyright:
- Copyright (C) 1998-2018 Sonic Team Junior
+ Copyright (C) 1998-2018 by Sonic Team Junior
License:
@@ -21,7 +21,7 @@ License:
The Debian packaging is:
Copyright (C) 2010 Callum Dickinson
- Copyright (C) 2010-2018 Sonic Team Junior
+ Copyright (C) 2010-2018 by Sonic Team Junior
and is licensed under the GPL version 2,
see "/usr/share/common-licenses/GPL-2".
diff --git a/assets/debian/rules b/assets/debian-template/rules
old mode 100755
new mode 100644
similarity index 70%
rename from assets/debian/rules
rename to assets/debian-template/rules
index a34a3393f..c2d19922d
--- a/assets/debian/rules
+++ b/assets/debian-template/rules
@@ -23,6 +23,16 @@
#
#############################################################################
+#############################################################################
+#
+# !!!!!!!!!! DEPLOYER NOTE !!!!!!!!!!
+#
+# Variables to be templated are curly-braced ${PACKAGE_INSTALL_PATH}
+# Variables used by the rules script are parenthese'd $(DATADIR)
+# See [repo-root]/debian_template.sh
+#
+#############################################################################
+
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
@@ -37,30 +47,32 @@ RM := rm -rf
DIR := $(shell pwd)
PACKAGE := $(shell cat $(DIR)/debian/control | grep 'Package:' | sed -e 's/Package: //g')
-DATAFILES := srb2.srb zones.dta player.dta rings.dta music.dta patch.dta README.txt LICENSE.txt LICENSE-3RD-PARTY.txt
+ARCHIVEPATH := ${ASSET_ARCHIVE_PATH}
+ARCHIVEOPTIONALPATH := ${ASSET_ARCHIVE_OPTIONAL_PATH}
+GETOPTIONALFILES := ${ASSET_FILES_OPTIONAL_GET}
-DATADIR := usr/games/SRB2
+DATADIR := $(shell echo "${PACKAGE_INSTALL_PATH}" | sed -e 's/^\///')
RESOURCEDIR := .
+STAGINGDIR := $(RESOURCEDIR)/installer
WGET := wget -P $(RESOURCEDIR) -c -nc
build:
$(MKDIR) $(DIR)/debian/tmp/$(DATADIR)
> $(DIR)/debian/source/include-binaries
- # This will need to be updated every time SRB2 official version is
# Copy data files to their install locations, and add data files to include-binaries
- for file in $(DATAFILES); do \
- if [ ! -f $(RESOURCEDIR)/$$file ]; then \
- $(WGET) http://alam.srb2.org/SRB2/2.1.21-Final/Resources/$$file; \
+ if [ ! -d $(STAGINGDIR) ]; then \
+ mkdir -p "$(STAGINGDIR)"; \
+ $(WGET) $(ARCHIVEPATH); \
+ 7z x "$(RESOURCEDIR)/$(shell basename $(ARCHIVEPATH))" -aos; \
+ if [ "$(GETOPTIONALFILES)" = "1" ]; then \
+ $(WGET) $(ARCHIVEOPTIONALPATH); \
+ 7z x "$(RESOURCEDIR)/$(shell basename $(ARCHIVEOPTIONALPATH))" -aos; \
fi; \
- if [ -f $(RESOURCEDIR)/$$file ]; then \
- $(INSTALL) $(RESOURCEDIR)/$$file $(DIR)/debian/tmp/$(DATADIR)/$$file; \
- echo $(RESOURCEDIR)/$$file >> $(DIR)/debian/source/include-binaries; \
- fi; \
- if [ ! -f $(DIR)/debian/tmp/$(DATADIR)/$$file ]; then \
- echo $(DIR)/debian/tmp/$(DATADIR)/$$file not found and could not be downloaded!; \
- return 1; \
- fi; \
- done
+ fi
+ # Install asset directory and add asset file to include-binaries
+ cp -vr "$(STAGINGDIR)/." "$(DIR)/debian/tmp/$(DATADIR)"
+ find "$(STAGINGDIR)" >> $(DIR)/debian/source/include-binaries
+
binary-indep:
# Generate install folder file
diff --git a/assets/debian/source/format b/assets/debian-template/source/format
similarity index 100%
rename from assets/debian/source/format
rename to assets/debian-template/source/format
diff --git a/assets/debian/source/options b/assets/debian-template/source/options
similarity index 100%
rename from assets/debian/source/options
rename to assets/debian-template/source/options
diff --git a/assets/debian/changelog b/assets/debian/changelog
deleted file mode 100644
index f3a92e1cd..000000000
--- a/assets/debian/changelog
+++ /dev/null
@@ -1,19 +0,0 @@
-srb2-data (2.1.21~7) trusty; urgency=high
-
- * Updated for SRB2 v2.1.21
-
- -- Marco Zafra Mon, 26 Nov 2018 14:31:00 -0500
-
-
-srb2-data (2.1.14~1) unstable; urgency=low
-
- * Updated for SRB2 v2.1.14
-
- -- Alam Arias Sat, 6 Jan 2016 11:00:00 -0500
-
-
-srb2-data (2.0.6-2) maverick; urgency=high
-
- * Initial proper release..
-
- -- Callum Dickinson Sat, 29 Jan 2011 01:18:42 +1300
diff --git a/debian/README.Debian b/debian-template/README.Debian
similarity index 62%
rename from debian/README.Debian
rename to debian-template/README.Debian
index 4b724816e..3aa52787e 100644
--- a/debian/README.Debian
+++ b/debian-template/README.Debian
@@ -10,10 +10,38 @@ and give them to your users to install with apt-key add. Thanks!
-- Callum Dickinson Fri, 26 Nov 2010 18:25:31 +1300
+---------------
+
+
+Templating
+
+Note that you MUST run [repo-root]/debian_template.sh before running debuild
+on these scripts! debian_template.sh fills these template files with working values.
+
+You should also set PACKAGE_NAME_EMAIL="John Doe " to match
+the identity of the key you will use to sign the package.
+
+
+Building for Launchpad PPA
+
+Use these steps to prepare building a source package for Launchpad:
+
+ 1. cd [repo-root]
+ 2. git reset --hard; git clean -fd; git clean -fx;
+ * Resets your repo folder to a committed state and removes untracked files
+ * If you built srb2-data in the assets/ folder, MAKE SURE THAT FOLDER DOES NOT HAVE ASSETS,
+ OR THEY MAY BE INCLUDED IN THE MAIN SOURCE PACKAGE!
+
+Build the source package:
+
+ 1. source [repo-root]/debian_template.sh
+ * Initializes defaults for the package variables and fills in templates.
+ 2. debuild -S (builds the source package for Launchpad)
+
Signing for Launchpad PPA
-First, follow the above instructions to generate a GnuPG key with your identity. You will need
+First, follow Callum's instructions to generate a GnuPG key with your identity. You will need
to publish the fingerprint of that key to Ubuntu's key server.
https://help.ubuntu.com/community/GnuPrivacyGuardHowto#Uploading_the_key_to_Ubuntu_keyserver
@@ -25,22 +53,18 @@ upload signed source packages and publish them onto your PPA.
IF YOU UPLOAD A PACKAGE and Launchpad does NOT send you a confirmation or rejection email, that
means your key is not set up correctly with your Launchpad account.
+Finally, if your packages have not already been signed, follow these steps:
-Building for Launchpad PPA
+ 1. cd ..
+ * Packages are located in the parent folder of where debuild was called
+ 2. debsign "srb2_[version]_source.changes"
+ * You may need to specify -k [key-fingerprint]
-Use these steps to prepare building a source package for Launchpad:
- 1. cd [srb2repo]
- 2. git reset --hard; git clean -fd; git clean -fx;
- * Resets your repo folder to a committed state and removes untracked files
- * If you built srb2-data in the assets/ folder, MAKE SURE THAT FOLDER DOES NOT HAVE ASSETS,
- OR THEY MAY BE INCLUDED IN THE MAIN SOURCE PACKAGE!
+Uploading for Launchpad PPA
-Building the source package takes just one step:
-
- 1. debuild -S (builds the source package for Launchpad)
-
-Then follow the instructions at to upload
+Follow the instructions at to upload
to your PPA and have Launchpad build your binary deb packages.
+
-- Marco Zafra Mon, 26 Nov 2018 21:13:00 -0500
diff --git a/debian/README.source b/debian-template/README.source
similarity index 100%
rename from debian/README.source
rename to debian-template/README.source
diff --git a/debian-template/changelog b/debian-template/changelog
new file mode 100644
index 000000000..fb08908cd
--- /dev/null
+++ b/debian-template/changelog
@@ -0,0 +1,5 @@
+${PACKAGE_NAME} (${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION}) ${PACKAGE_DISTRO}; urgency=${PACKAGE_URGENCY}
+
+ * ${PROGRAM_NAME} v${PROGRAM_VERSION} program build
+
+ -- ${PACKAGE_NAME_EMAIL} ${__PACKAGE_DATETIME}
diff --git a/debian/compat b/debian-template/compat
similarity index 100%
rename from debian/compat
rename to debian-template/compat
diff --git a/debian/control b/debian-template/control
similarity index 65%
rename from debian/control
rename to debian-template/control
index 0f2d8062b..e1348d704 100644
--- a/debian/control
+++ b/debian-template/control
@@ -1,24 +1,30 @@
# SRB2 Debian package control file.
-Source: srb2
+Source: ${PACKAGE_NAME}
Section: games
Priority: extra
-Maintainer: Sonic Team Junior
+Maintainer: ${PACKAGE_GROUP_NAME_EMAIL}
Build-Depends: debhelper (>= 7.0.50~),
libsdl2-dev,
libsdl2-mixer-dev,
- libpng12-dev (>= 1.2.7) | libpng-dev,
+ libpng-dev | libpng16-dev | libpng12-dev (>= 1.2.7),
zlib1g-dev,
libgme-dev,
libglu1-dev | libglu-dev,
libosmesa6-dev | libgl-dev,
nasm [i386]
Standards-Version: 3.8.4
-Homepage: http://www.srb2.org
+Homepage: ${PACKAGE_WEBSITE}
-Package: srb2
+Package: ${PACKAGE_NAME}
Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, srb2-data (>= 2.1.15), srb2-data (<= 2.1.23)
+Depends: ${SHLIBS_DEPENDS}, ${MISC_DEPENDS},
+ ${PACKAGE_NAME}-data (>> ${PACKAGE_ASSET_MINVERSION}), ${PACKAGE_NAME}-data (<< ${PACKAGE_ASSET_MAXVERSION}),
+ libsdl2-2.0-0,
+ libsdl2-mixer-2.0-0,
+ zlib1g,
+ libgme0,
+ libpng | libpng16-16 | libpng12-0
Description: A cross-platform 3D Sonic fangame
Sonic Robo Blast 2 is a 3D open-source Sonic the Hedgehog
fangame built using a modified version of the Doom Legacy
@@ -28,10 +34,10 @@ Description: A cross-platform 3D Sonic fangame
and quite a lot of the fun that the original Sonic games provided.
-Package: srb2-dbg
+Package: ${PACKAGE_NAME}-dbg
Architecture: any
-# FIXME: should be Depends: ${shlibs:Depends}, ${misc:Depends}, srb2-data (= 2.1.14), srb2 but dh_shlibdeps is being an asshat
-Depends: libc6, ${misc:Depends}, srb2-data (>= 2.1.15), srb2-data (<= 2.1.23), srb2
+# FIXME: should be Depends: ${SHLIBS_DEPENDS}, ${MISC_DEPENDS}, srb2-data (= 2.1.14), srb2 but dh_shlibdeps is being an asshat
+Depends: libc6, ${MISC_DEPENDS}, ${PACKAGE_NAME}-data (>> ${PACKAGE_ASSET_MINVERSION}), ${PACKAGE_NAME}-data (<< ${PACKAGE_ASSET_MAXVERSION}), ${PACKAGE_NAME}
Description: A cross-platform 3D Sonic fangame
Sonic Robo Blast 2 is a 3D open-source Sonic the Hedgehog
fangame built using a modified version of the Doom Legacy
diff --git a/assets/debian/copyright b/debian-template/copyright
similarity index 57%
rename from assets/debian/copyright
rename to debian-template/copyright
index 97d606b0f..cc47c453b 100644
--- a/assets/debian/copyright
+++ b/debian-template/copyright
@@ -1,18 +1,18 @@
This work was packaged for Debian by:
- Marco Zafra Mon, 26 Nov 2018 14:31:00 -0500
+ ${PACKAGE_NAME_EMAIL} ${__PACKAGE_DATETIME}
It was downloaded from:
-
+ ${PACKAGE_WEBSITE}
Upstream Author(s):
- Sonic Team Junior
+ ${PACKAGE_GROUP_NAME_EMAIL}
Copyright:
- Copyright (C) 1998-2018 Sonic Team Junior
+ Copyright (C) 1998-2018 by Sonic Team Junior
License:
@@ -21,7 +21,7 @@ License:
The Debian packaging is:
Copyright (C) 2010 Callum Dickinson
- Copyright (C) 2010-2018 Sonic Team Junior
+ Copyright (C) 2010-2018 by Sonic Team Junior
and is licensed under the GPL version 2,
see "/usr/share/common-licenses/GPL-2".
diff --git a/debian/docs b/debian-template/docs
similarity index 100%
rename from debian/docs
rename to debian-template/docs
diff --git a/debian/rules b/debian-template/rules
old mode 100755
new mode 100644
similarity index 87%
rename from debian/rules
rename to debian-template/rules
index ff80d50bf..0a77624cb
--- a/debian/rules
+++ b/debian-template/rules
@@ -23,6 +23,16 @@
#
#############################################################################
+#############################################################################
+#
+# !!!!!!!!!! DEPLOYER NOTE !!!!!!!!!!
+#
+# Variables to be templated are curly-braced ${PACKAGE_INSTALL_PATH}
+# Variables used by the rules script are parenthese'd $(PKGDIR)
+# See [repo-root]/debian_template.sh
+#
+#############################################################################
+
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
@@ -50,16 +60,16 @@ DIR := $(shell pwd)
# FIXME: hate hate hate head/tail hack :(
CONTROLF = $(DIR)/debian/control
-PACKAGE = srb2
-DBGPKG = $(PACKAGE)-dbg
-TITLE = Sonic Robo Blast 2
+PACKAGE = ${PACKAGE_NAME}
+DBGPKG = ${PACKAGE}-dbg
+TITLE = ${PROGRAM_NAME}
SECTION = Games/Action
-EXENAME = srb2
+EXENAME = ${PROGRAM_FILENAME}
DBGNAME = debug/$(EXENAME)
-PKGDIR = usr/games/SRB2
+PKGDIR = $(shell echo "${PACKAGE_INSTALL_PATH}" | sed -e 's/^\///')
DBGDIR = usr/lib/debug/$(PKGDIR)
-LINKDIR = usr/games
+LINKDIR = $(shell echo "${PACKAGE_LINK_PATH}" | sed -e 's/^\///')
PIXMAPS_DIR = usr/share/pixmaps
DESKTOP_DIR = usr/share/applications
PREFIX = $(shell test "$(CROSS_COMPILE_BUILD)" != "$(CROSS_COMPILE_HOST)" && echo "PREFIX=$(CROSS_COMPILE_HOST)")
@@ -102,8 +112,8 @@ binary-arch:
$(INSTALL) $(BINDIR)/$(EXENAME) $(DIR)/debian/tmp/$(PKGDIR)/$(PACKAGE)
$(INSTALL) $(BINDIR)/$(DBGNAME) $(DIR)/debian/tmp/$(DBGDIR)/$(PACKAGE)
# Install desktop file and banner image
- $(INSTALL) $(DIR)/srb2.png $(DIR)/debian/tmp/usr/share/pixmaps
- $(INSTALL) $(DIR)/debian/srb2.desktop $(DIR)/debian/tmp/usr/share/applications
+ $(INSTALL) $(DIR)/srb2.png $(DIR)/debian/tmp/usr/share/pixmaps/${PROGRAM_FILENAME}.png
+ $(INSTALL) $(DIR)/debian/srb2.desktop $(DIR)/debian/tmp/usr/share/applications/${PROGRAM_FILENAME}.desktop
# add compiled binaries to include-binaries
echo $(BINDIR)/$(EXENAME) >> $(DIR)/debian/source/include-binaries
echo $(BINDIR)/$(EXENAME) >> $(DIR)/debian/source/include-binaries
diff --git a/debian/source/format b/debian-template/source/format
similarity index 100%
rename from debian/source/format
rename to debian-template/source/format
diff --git a/debian/source/options b/debian-template/source/options
similarity index 74%
rename from debian/source/options
rename to debian-template/source/options
index 841c65a6f..9532ff202 100644
--- a/debian/source/options
+++ b/debian-template/source/options
@@ -2,7 +2,8 @@ tar-ignore = "assets/*.srb"
tar-ignore = "assets/*.pk3"
tar-ignore = "assets/*.dta"
tar-ignore = "assets/*.wad"
-tar-ignore = "assets/debian/srb2-data/*"
+tar-ignore = "assets/*.kart"
+tar-ignore = "assets/debian/${PACKAGE_NAME}-data/*"
tar-ignore = "assets/debian/tmp/*"
tar-ignore = "*.obj"
tar-ignore = "*.dep"
diff --git a/debian-template/srb2.desktop b/debian-template/srb2.desktop
new file mode 100644
index 000000000..07c7906e0
--- /dev/null
+++ b/debian-template/srb2.desktop
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Name=${PROGRAM_NAME}
+Comment=${PROGRAM_DESCRIPTION}
+Encoding=UTF-8
+Exec=${PACKAGE_INSTALL_PATH}/${PROGRAM_FILENAME}
+Icon=/usr/share/pixmaps/${PROGRAM_FILENAME}.png
+Terminal=false
+Type=Application
+StartupNotify=false
+Categories=Application;Game;
diff --git a/debian/changelog b/debian/changelog
deleted file mode 100644
index b06a78e2b..000000000
--- a/debian/changelog
+++ /dev/null
@@ -1,12 +0,0 @@
-srb2 (2.1.23~9) trusty; urgency=high
-
- * SRB2 v2.1.23 release
-
- -- Marco Zafra Mon, 27 Nov 2018 16:45:00 -0500
-
-
-srb2 (2.0.6-5) maverick; urgency=high
-
- * Initial proper release..
-
- -- Callum Dickinson Sat, 29 Jan 2011 01:18:42 +1300
diff --git a/debian/srb2.desktop b/debian/srb2.desktop
deleted file mode 100644
index 3a1cac9f6..000000000
--- a/debian/srb2.desktop
+++ /dev/null
@@ -1,10 +0,0 @@
-[Desktop Entry]
-Name=Sonic Robo Blast 2
-Comment=A free 3D Sonic the Hedgehog fangame closely inspired by the original Sonic games on the Sega Genesis.
-Encoding=UTF-8
-Exec=/usr/games/SRB2/srb2
-Icon=/usr/share/pixmaps/srb2.png
-Terminal=false
-Type=Application
-StartupNotify=false
-Categories=Application;Game;
diff --git a/debian_template.sh b/debian_template.sh
new file mode 100644
index 000000000..c1af3c19f
--- /dev/null
+++ b/debian_template.sh
@@ -0,0 +1,166 @@
+#!/bin/bash
+
+# Deployer for Travis-CI
+# Debian package templating
+#
+# Call this script BEFORE running debuild!
+# source ./debian_template.sh [clean] [main/asset]
+#
+# Before running this script,
+# you should also set PACKAGE_NAME_EMAIL="John Doe " to match
+# the identity of the key you will use to sign the package.
+#
+
+# Get script's actual path
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
+
+# Recursive function for directory crawling
+# $1 = Directory root to crawl
+# $2 = Code to eval on file
+# $3 = Code to eval on directory
+# Exposes $dirtails, $dirlevel, and $dirtailname
+dirlevel=0 # initialize
+dirtails=()
+
+# Utility function to make dira/dirb/dirc string
+makedirtailname () {
+ dirtailname=""
+ for tail in $dirtails; do
+ if [[ "$dirtailname" == "" ]]; then
+ dirtailname="/$tail";
+ else
+ dirtailname="$dirtailname/$tail";
+ fi;
+ done;
+}
+
+evaldirectory () {
+ if [ -d "$1" ]; then
+ # Set contextual variables
+ # dirtails is an array of directory basenames after the crawl root
+ if (( $dirlevel > 0 )); then
+ dirtails+=( "$(basename $1)" );
+ else
+ dirtails=();
+ fi;
+ dirlevel=$((dirlevel+1));
+
+ # Generate directory path after the crawl root
+ makedirtailname;
+
+ # Eval our directory with the latest contextual info
+ # Don't eval on root
+ if (( $dirlevel > 1 )) && [[ "$3" != "" ]]; then
+ eval "$3";
+ fi;
+
+ # Iterate entries
+ for name in $1/*; do
+ if [ -d "$name" ]; then
+ # Name is a directory, but don't eval yet
+ # Recurse so our vars are updated
+ evaldirectory "$name" "$2" "$3";
+
+ # Decrement our directory level and remove a dirtail
+ unset 'dirtails[ ${#dirtails[@]}-1 ]';
+ dirlevel=$((dirlevel-1));
+ makedirtailname;
+ else
+ # Name is a file
+ if [ -f "$name" ] && [[ "$2" != "" ]]; then
+ eval "$2";
+ fi;
+ fi;
+ done;
+
+ # Reset our variables; we're done iterating
+ if (( $dirlevel == 1 )); then
+ dirlevel=0;
+ fi;
+ fi;
+}
+
+#
+# Initialize package parameter defaults
+#
+if [[ "$__DEBIAN_PARAMETERS_INITIALIZED" != "1" ]]; then
+ . ${DIR}/deployer/travis/deployer_defaults.sh;
+fi;
+
+# Clean up after ourselves; we only expect to run this script once
+# during buildboting
+__DEBIAN_PARAMETERS_INITIALIZED=0
+
+# for envsubst
+export __PACKAGE_DATETIME="$(date '+%a, %d %b %Y %H:%M:%S %z')"
+export __PACKAGE_DATETIME_DIGIT="$(date -u '+%Y%m%d%H%M%S')"
+
+if [[ "$PACKAGE_REVISION" == "" ]]; then
+ PACKAGE_REVISION="-$__PACKAGE_DATETIME_DIGIT";
+ __PACKAGE_REVISION_BY_DATE=1;
+ export PACKAGE_REVISION=${PACKAGE_REVISION}; # for envsubst
+fi;
+
+#
+# Clean the old debian/ directories
+#
+if [[ "$1" == "clean" ]]; then
+ toclean=$2;
+else
+ toclean=$1;
+fi;
+
+if [[ "$toclean" == "" ]] || [[ "$toclean" == "main" ]]; then
+ echo "Cleaning main package scripts";
+ if [[ ! -f ${DIR}/debian ]]; then
+ rm -rf ${DIR}/debian;
+ fi;
+fi;
+if [[ "$toclean" == "" ]] || [[ "$toclean" == "asset" ]]; then
+ echo "Cleaning asset package scripts";
+ if [[ ! -f ${DIR}/assets/debian ]]; then
+ rm -rf ${DIR}/assets/debian;
+ fi;
+fi;
+
+#
+# Make new templates
+#
+if [[ "$1" != "clean" ]]; then
+ totemplate=$1;
+
+ # HACK: ${shlibs:Depends} in the templates make the templating fail
+ # So just define replacemment variables
+ export SHLIBS_DEPENDS=${SHLIBS_DEPENDS};
+ export MISC_DEPENDS=${MISC_DEPENDS};
+ export DEBFILEVAR='$$file'; # used in assets/debian/rules
+
+ # Package parameters are exported for envsubst in deployer_defaults.sh
+
+ if [[ "$totemplate" == "" ]] || [[ "$totemplate" == "main" ]]; then
+ echo "Generating main package scripts";
+ fromroot=${DIR}/debian-template;
+ toroot=${DIR}/debian;
+ mkdir ${toroot};
+
+ evaldirectory ${fromroot} \
+ "cat \$name | envsubst > ${toroot}\${dirtailname}/\$( basename \$name )" \
+ "mkdir \"${toroot}\${dirtailname}\"";
+ fi;
+
+ if [[ "$totemplate" == "" ]] || [[ "$totemplate" == "asset" ]]; then
+ echo "Generating asset package scripts";
+ fromroot=${DIR}/assets/debian-template;
+ toroot=${DIR}/assets/debian;
+ mkdir ${toroot};
+
+ # Root dir to crawl; file eval; directory eval
+ evaldirectory ${fromroot} \
+ "cat \$name | envsubst > ${toroot}\${dirtailname}/\$( basename \$name )" \
+ "mkdir \"${toroot}\${dirtailname}\"";
+ fi;
+fi;
+
+if [[ "$__DPL_ACTIVE" != "1" ]] && [[ "$__PACKAGE_REVISION_BY_DATE" == "1" ]]; then
+ unset PACKAGE_REVISION; # so we can reset the date on subsequent runs
+fi;
diff --git a/deployer/travis/deployer.sh b/deployer/travis/deployer.sh
new file mode 100644
index 000000000..c88155d21
--- /dev/null
+++ b/deployer/travis/deployer.sh
@@ -0,0 +1,157 @@
+#!/bin/bash
+
+# Deployer for Travis-CI
+# Initialization
+#
+# Performs validity checks to ensure that Deployer is allowed to run
+# e.g., is an FTP hostname specified? Are we whitelisted by OSNAMES and BRANCHES?
+#
+# Set these environment variables in your Travis-CI settings, where they are stored securely.
+# See other shell scripts for more options.
+#
+# DPL_ENABLED = 1 (leave blank to disable)
+# DPL_TAG_ENABLED = 1 (run Deployer on all tags)
+# DPL_JOB_ENABLE_ALL = 1 (run Deployer on all jobs; leave blank to act on specific jobs, see below)
+# DPL_JOBNAMES = name1,name2 (whitelist of job names to allow uploading; leave blank to upload from all jobs)
+# DPL_OSNAMES = osx (whitelist of OS names to allow uploading; leave blank to upload from all OSes)
+# DPL_BRANCHES = master,branch1,branch2 (whitelist of branches to upload; leave blank to upload all branches)
+#
+# To enable Deployer on specific jobs, set _DPL_JOB_ENABLED=1 for that job. Example:
+# - matrix:
+# - os: osx
+# env:
+# - _DPL_JOB_ENABLED=1
+#
+# DO NOT set __DPL_ACTIVE, because that would bypass these validity checks.
+
+# Validate Deployer state
+if [[ "$DPL_ENABLED" == "1" ]] && [[ "$TRAVIS_PULL_REQUEST" == "false" ]]; then
+ # Test for base eligibility:
+ # Are we in a deployer branch? Or
+ # Are we in a release tag AND DPL_TAG_ENABLED=1?
+ if [[ $TRAVIS_BRANCH == *"deployer"* ]]; then
+ __DPL_BASE_ELIGIBLE=1;
+ __DPL_TERMINATE_EARLY_ELIGIBLE=1;
+ fi;
+
+ if [[ "$TRAVIS_TAG" != "" ]] && [[ "$DPL_TAG_ENABLED" == "1" ]]; then
+ __DPL_BASE_ELIGIBLE=1;
+ __DPL_TAG_ELIGIBLE=1;
+ __DPL_TERMINATE_EARLY_ELIGIBLE=1;
+ fi;
+
+ # Logging message for trigger word
+ if [[ "$__DPL_TAG_ELIGIBLE" != "1" ]] && [[ "$DPL_TRIGGER" != "" ]]; then
+ echo "Testing for trigger $DPL_TRIGGER, commit message: $TRAVIS_COMMIT_MESSAGE";
+ echo "[${DPL_TRIGGER}]";
+ echo "[${DPL_TRIGGER}-${_DPL_JOB_NAME}]";
+ echo "[${DPL_TRIGGER}-${TRAVIS_OS_NAME}]";
+ fi;
+
+ #
+ # Search for the trigger word
+ # Force enable if release tags are eligible
+ #
+ if [[ "$__DPL_TAG_ELIGIBLE" == "1" ]] || [[ "$DPL_TRIGGER" == "" ]] \
+ || [[ $TRAVIS_COMMIT_MESSAGE == *"[$DPL_TRIGGER]"* ]] \
+ || [[ $TRAVIS_COMMIT_MESSAGE == *"[${DPL_TRIGGER}-${_DPL_JOB_NAME}]"* ]] \
+ || [[ $TRAVIS_COMMIT_MESSAGE == *"[${DPL_TRIGGER}-${TRAVIS_OS_NAME}]"* ]]; then
+ #
+ # Whitelist by branch name
+ # Force enable if release tags are eligible
+ #
+ if [[ "$__DPL_TAG_ELIGIBLE" == "1" ]] || [[ "$DPL_BRANCHES" == "" ]] || [[ $DPL_BRANCHES == *"$TRAVIS_BRANCH"* ]]; then
+ # Set this so we only early-terminate builds when we are specifically deploying
+ # Trigger string and branch are encompassing conditions; the rest are job-specific
+ # This check only matters for deployer branches and when DPL_TERMINATE_TESTS=1,
+ # because we're filtering non-deployer jobs.
+ #
+ # __DPL_TRY_TERMINATE_EARLY is invalidated in .travis.yml if __DPL_ACTIVE=1
+ if [[ "$__DPL_TERMINATE_EARLY_ELIGIBLE" == "1" ]] && [[ "$DPL_TERMINATE_TESTS" == "1" ]]; then
+ __DPL_TRY_TERMINATE_EARLY=1;
+ fi;
+
+ #
+ # Is the job enabled for deployment?
+ #
+ if [[ "$DPL_JOB_ENABLE_ALL" == "1" ]] || [[ "$_DPL_JOB_ENABLED" == "1" ]]; then
+ #
+ # Whitelist by job names
+ #
+ if [[ "$DPL_JOBNAMES" == "" ]] || [[ "$_DPL_JOB_NAME" == "" ]] || [[ $DPL_JOBNAMES == *"$_DPL_JOB_NAME"* ]]; then
+ #
+ # Whitelist by OS names
+ #
+ if [[ "$DPL_OSNAMES" == "" ]] || [[ $DPL_OSNAMES == *"$TRAVIS_OS_NAME"* ]]; then
+ # Base Deployer is eligible for becoming active
+
+ # Are we building for Linux?
+ if [[ "$_DPL_PACKAGE_BINARY" == "1" ]] || [[ "$_DPL_PACKAGE_SOURCE" == "1" ]]; then
+ if [[ "$_DPL_PACKAGE_MAIN" == "1" ]] || [[ "$_DPL_PACKAGE_ASSET" == "1" ]]; then
+ if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
+ __DPL_DEBIAN_ACTIVE=1;
+ fi;
+ fi;
+ fi;
+
+ # Now check for deployment targets
+ if [[ "$_DPL_FTP_TARGET" == "1" ]] && [[ "$DPL_FTP_HOSTNAME" != "" ]]; then
+ if [[ "$TRAVIS_OS_HOST" == "linux" ]] && [[ "$DPL_FTP_PROTOCOL" == "ftp" ]]; then
+ echo "Non-secure FTP will not work on Linux Travis-CI jobs!";
+ echo "Try SFTP or another target. Details:";
+ echo "https://blog.travis-ci.com/2018-07-23-the-tale-of-ftp-at-travis-ci";
+ else
+ if [[ "$__DPL_DEBIAN_ACTIVE" == "1" ]] || [[ "$_DPL_PACKAGE_BINARY" == "1" ]] || [[ "$_DPL_BINARY" == "1" ]]; then
+ echo "Deployer FTP target is enabled";
+ __DPL_FTP_ACTIVE=1;
+ else
+ echo "Deployer FTP target cannot be enabled: You must specify _DPL_PACKAGE_BINARY=1,";
+ echo "and/or _DPL_BINARY=1 in your job's environment variables.";
+ fi;
+ fi;
+ fi;
+
+ if [[ "$_DPL_DPUT_TARGET" == "1" ]] && [[ "$__DPL_DEBIAN_ACTIVE" == "1" ]] \
+ && [[ "$DPL_DPUT_INCOMING" != "" ]]; then
+ if [[ "$DPL_DPUT_METHOD" == "ftp" ]]; then
+ echo "DPUT will not work with non-secure FTP on Linux Travis-CI jobs!";
+ echo "Try SFTP or another method for DPUT. Details:";
+ echo "https://blog.travis-ci.com/2018-07-23-the-tale-of-ftp-at-travis-ci";
+ else
+ echo "Deployer DPUT target is enabled";
+ __DPL_DPUT_ACTIVE=1;
+ fi;
+ fi;
+
+ # If any deployment targets are active, then so is the Deployer at large
+ if [[ "$__DPL_FTP_ACTIVE" == "1" ]] || [[ "$__DPL_DPUT_ACTIVE" == "1" ]]; then
+ __DPL_ACTIVE=1;
+ fi;
+ fi;
+ fi;
+ fi;
+ fi;
+ else
+ if [[ "$DPL_TRIGGER" != "" ]]; then
+ echo "Testing for global trigger [$DPL_TRIGGER, commit message: $TRAVIS_COMMIT_MESSAGE";
+ fi;
+ if [[ "$DPL_TRIGGER" != "" ]] && [[ $TRAVIS_COMMIT_MESSAGE == *"[$DPL_TRIGGER"* ]]; then
+ if [[ "$__DPL_TAG_ELIGIBLE" == "1" ]] || [[ "$DPL_BRANCHES" == "" ]] || [[ $DPL_BRANCHES == *"$TRAVIS_BRANCH"* ]]; then
+ # This check only matters for deployer branches and when DPL_TERMINATE_TESTS=1,
+ # because we're filtering non-deployer jobs.
+ if [[ "$__DPL_TERMINATE_EARLY_ELIGIBLE" == "1" ]] && [[ "$DPL_TERMINATE_TESTS" == "1" ]]; then
+ # Assume that some job received the trigger, so mark this for early termination
+ __DPL_TRY_TERMINATE_EARLY=1;
+ fi;
+ fi;
+ fi;
+ fi;
+fi;
+
+if [[ "$__DPL_TRY_TERMINATE_EARLY" == "1" ]] && [[ "$__DPL_ACTIVE" != "1" ]]; then
+ echo "Deployer is active in another job";
+fi;
+
+if [[ "$__DPL_TRY_TERMINATE_EARLY" != "1" ]] && [[ "$__DPL_ACTIVE" != "1" ]]; then
+ echo "Deployer is not active";
+fi;
diff --git a/deployer/travis/deployer_build.sh b/deployer/travis/deployer_build.sh
new file mode 100644
index 000000000..3817f025d
--- /dev/null
+++ b/deployer/travis/deployer_build.sh
@@ -0,0 +1,190 @@
+#!/bin/bash
+
+# Deployer for Travis-CI
+# Build Script
+#
+# Builds the required targets depending on which sub-modules are enabled
+
+if [[ "$__DPL_FTP_ACTIVE" == "1" ]] || [[ "$__DPL_DPUT_ACTIVE" == "1" ]]; then
+ if [[ "$__DPL_DEBIAN_ACTIVE" == "1" ]]; then
+ echo "Building Debian package(s)"
+
+ sudo apt-get install devscripts debhelper fakeroot secure-delete expect;
+
+ # Build source packages first, since they zip up the entire source folder,
+ # binaries and all
+ if [[ "$_DPL_PACKAGE_MAIN" == "1" ]]; then
+ . ../debian_template.sh main;
+ OLDPWD=$PWD; # [repo]/build
+ cd ..; # repo root
+
+ if [[ "$_DPL_PACKAGE_SOURCE" == "1" ]]; then
+ echo "Building main source Debian package";
+ expect <(cat < key.asc;
+ echo "$DPL_PGP_KEY_PASSPHRASE" > phrase.txt;
+ gpg --import key.asc;
+
+ if [[ "$_DPL_PACKAGE_MAIN" == "1" ]]; then
+ echo "Signing main package(s)";
+
+ PACKAGEFILENAME=${PACKAGE_NAME}_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ PACKAGEDBGFILENAME=${PACKAGE_NAME}-dbg_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGENIGHTLYFILENAME=${PACKAGE_NAME}-nightly_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGENIGHTLYDBGFILENAME=${PACKAGE_NAME}-nightly-dbg_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGEPATCHFILENAME=${PACKAGE_NAME}-patch_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGEPATCHDBGFILENAME=${PACKAGE_NAME}-patch-dbg_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGEPATCHNIGHTLYFILENAME=${PACKAGE_NAME}-patch-nightly_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGEPATCHNIGHTLYDBGFILENAME=${PACKAGE_NAME}-patch-nightly-dbg_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+
+ PACKAGEFILENAMES=(
+ $PACKAGEFILENAME
+ $PACKAGEDBGFILENAME
+ #$PACKAGENIGHTLYFILENAME
+ #$PACKAGENIGHTLYDBGFILENAME
+ #$PACKAGEPATCHFILENAME
+ #$PACKAGEPATCHDBGFILENAME
+ #$PACKAGEPATCHNIGHTLYFILENAME
+ #$PACKAGEPATCHNIGHTLYDBGFILENAME
+ );
+
+ # Main packages are in parent of root repo folder
+ OLDPWD=$PWD; # [repo]/build
+ cd ../..; # parent of repo root
+
+ for n in ${PACKAGEFILENAMES}; do
+ for f in ./$n*.changes; do
+ debsign --no-re-sign -p"gpg --passphrase-file $OLDPWD/phrase.txt --batch" "$f";
+ done;
+ done;
+
+ cd $OLDPWD;
+ fi;
+
+ if [[ "$_DPL_PACKAGE_ASSET" == "1" ]]; then
+ echo "Signing asset package(s)";
+
+ PACKAGEFILENAME=${PACKAGE_NAME}-data_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGENIGHTLYFILENAME=${PACKAGE_NAME}-nightly-data_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGEPATCHFILENAME=${PACKAGE_NAME}-patch-data_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGEPATCHNIGHTLYFILENAME=${PACKAGE_NAME}-patch-nightly-data_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+
+ PACKAGEFILENAMES=(
+ $PACKAGEFILENAME
+ #$PACKAGENIGHTLYFILENAME
+ #$PACKAGEPATCHFILENAME
+ #$PACKAGEPATCHNIGHTLYFILENAME
+ )
+
+ # Asset packages are in root repo folder
+ OLDPWD=$PWD; # [repo]/build
+ cd ..; # repo root
+
+ for n in ${PACKAGEFILENAMES}; do
+ for f in ./$n*.changes; do
+ debsign --no-re-sign -p"gpg --passphrase-file $OLDPWD/phrase.txt --batch" "$f";
+ done;
+ done;
+
+ cd $OLDPWD;
+ fi;
+
+ # Delete the keys :eyes:
+ srm key.asc;
+ srm phrase.txt;
+ fi;
+ fi;
+
+ # all other OSes
+ if [[ "$TRAVIS_OS_NAME" != "linux" ]]; then
+ #
+ # Check for binary building
+ #
+ if [[ "$_DPL_BINARY" == "1" ]]; then
+ echo "Building a Binary";
+ make -k;
+ fi;
+
+ #
+ # Check for package building
+ #
+ if [[ "$_DPL_PACKAGE_BINARY" == "1" ]]; then
+ echo "Building a Package";
+
+ # Make an OSX package; superuser is required for library bundling
+ #
+ # HACK: OSX packaging can't write libraries to .app package unless we're superuser
+ # because the original library files don't have WRITE permission
+ # Bug may be sidestepped by using CHMOD_BUNDLE_ITEMS=TRUE
+ # But I don't know where this is set. Not `cmake -D...` because this var is ignored.
+ # https://cmake.org/Bug/view.php?id=9284
+ if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
+ sudo make -k package;
+ else
+ # Some day, when Windows is supported, we'll just make a standard package
+ make -k package;
+ fi;
+ fi;
+ fi;
+fi;
diff --git a/deployer/travis/deployer_defaults.sh b/deployer/travis/deployer_defaults.sh
new file mode 100644
index 000000000..9b853a80a
--- /dev/null
+++ b/deployer/travis/deployer_defaults.sh
@@ -0,0 +1,105 @@
+#!/bin/bash
+
+# Deployer for Travis-CI
+# Default Variables
+#
+# Here are all of the user-set variables used by Deployer.
+# See the "Cross-platform deployment" page on SRB2 Wiki for documentation.
+
+# Core Parameters
+: ${DPL_ENABLED} # Enable Deployer behavior; must be set for any deployment activity
+: ${DPL_TAG_ENABLED} # Trigger Deployer for all tag releases
+: ${DPL_JOB_ENABLE_ALL} # Enable all jobs for deployment
+: ${DPL_TERMINATE_TESTS} # Terminate all build test jobs (used in .travis.yml)
+: ${DPL_TRIGGER} # Use a [word] in the commit message to trigger Deployer
+: ${DPL_JOBNAMES} # Trigger Deployer by job name
+: ${DPL_OSNAMES} # Trigger Deployer by OS name (osx,linux)
+: ${DPL_BRANCHES} # Trigger Deployer by git branch name
+
+# Job Parameters
+: ${_DPL_JOB_ENABLED} # Enable Deployer for this specific job. DPL_ENABLED must be set too.
+: ${_DPL_JOB_NAME} # Identifier for the job, used for logging and trigger word matching
+: ${_DPL_FTP_TARGET} # Deploy to FTP
+: ${_DPL_DPUT_TARGET} # Deploy to DPUT
+: ${_DPL_PACKAGE_SOURCE} # Build packages into a Source distribution. Linux only.
+: ${_DPL_PACKAGE_BINARY} # Build packages into a Binary distribution.
+: ${_DPL_PACKAGE_MAIN:=1} # Build main installation package. Linux only; OS X assumes this.
+: ${_DPL_PACKAGE_ASSET} # Build asset installation package. Linux only.
+
+# Asset File Parameters
+: ${ASSET_ARCHIVE_PATH:=https://github.com/mazmazz/Kart-Public/releases/download/kart_assets/srb2kart-v102-assets.7z}
+: ${ASSET_ARCHIVE_OPTIONAL_PATH:=https://github.com/mazmazz/Kart-Public/releases/download/kart_assets/srb2kart-v102-optional-assets.7z}
+: ${ASSET_FILES_HASHED:=srb2.srb patch.kart gfx.kart textures.kart chars.kart maps.kart}
+: ${ASSET_FILES_DOCS:=README.txt HISTORY.txt LICENSE.txt LICENSE-3RD-PARTY.txt}
+: ${ASSET_FILES_OPTIONAL_GET:=0}
+
+# FTP Parameters
+: ${DPL_FTP_PROTOCOL}
+: ${DPL_FTP_USER}
+: ${DPL_FTP_PASS}
+: ${DPL_FTP_HOSTNAME}
+: ${DPL_FTP_PORT}
+: ${DPL_FTP_PATH}
+
+# DPUT Parameters
+: ${DPL_DPUT_DOMAIN:=ppa.launchpad.net}
+: ${DPL_DPUT_METHOD:=sftp}
+: ${DPL_DPUT_INCOMING}
+: ${DPL_DPUT_LOGIN:=anonymous}
+: ${DPL_SSH_KEY_PRIVATE} # Base64-encoded private key file. Used to sign repository uploads
+: ${DPL_SSH_KEY_PASSPHRASE} # Decodes the private key file.
+
+# Package Parameters
+: ${PACKAGE_NAME:=srb2kart}
+: ${PACKAGE_VERSION:=1.0.2}
+: ${PACKAGE_SUBVERSION} # Highly recommended to set this to reflect the distro series target (e.g., ~18.04bionic)
+: ${PACKAGE_REVISION} # Defaults to UTC timestamp
+: ${PACKAGE_INSTALL_PATH:=/usr/games/SRB2Kart}
+: ${PACKAGE_LINK_PATH:=/usr/games}
+: ${PACKAGE_DISTRO:=trusty}
+: ${PACKAGE_URGENCY:=high}
+: ${PACKAGE_NAME_EMAIL:=Kart Krew }
+: ${PACKAGE_GROUP_NAME_EMAIL:=Kart Krew }
+: ${PACKAGE_WEBSITE:=}
+
+: ${PACKAGE_ASSET_MINVERSION:=1.0.1} # Number this the version BEFORE the actual required version, because we do a > check
+: ${PACKAGE_ASSET_MAXVERSION:=1.0.3} # Number this the version AFTER the actual required version, because we do a < check
+
+: ${PROGRAM_NAME:=Sonic Robo Blast 2 Kart}
+: ${PROGRAM_VENDOR:=Kart Krew}
+: ${PROGRAM_VERSION:=1.0.2}
+: ${PROGRAM_DESCRIPTION:=A kart racing mod based on the 3D Sonic the Hedgehog fangame Sonic Robo Blast 2.}
+: ${PROGRAM_FILENAME:=srb2kart}
+
+: ${DPL_PGP_KEY_PRIVATE} # Base64-encoded private key file. Used to sign Debian packages
+: ${DPL_PGP_KEY_PASSPHRASE} # Decodes the private key file.
+
+# Export Asset and Package Parameters for envsubst templating
+
+export ASSET_ARCHIVE_PATH="${ASSET_ARCHIVE_PATH}"
+export ASSET_ARCHIVE_OPTIONAL_PATH="${ASSET_ARCHIVE_OPTIONAL_PATH}"
+export ASSET_FILES_HASHED="${ASSET_FILES_HASHED}"
+export ASSET_FILES_DOCS="${ASSET_FILES_DOCS}"
+export ASSET_FILES_OPTIONAL_GET="${ASSET_FILES_OPTIONAL_GET}"
+
+export PACKAGE_NAME="${PACKAGE_NAME}"
+export PACKAGE_VERSION="${PACKAGE_VERSION}"
+export PACKAGE_SUBVERSION="${PACKAGE_SUBVERSION}" # in case we have this
+export PACKAGE_REVISION="${PACKAGE_REVISION}"
+export PACKAGE_ASSET_MINVERSION="${PACKAGE_ASSET_MINVERSION}"
+export PACKAGE_ASSET_MAXVERSION="${PACKAGE_ASSET_MAXVERSION}"
+export PACKAGE_INSTALL_PATH="${PACKAGE_INSTALL_PATH}"
+export PACKAGE_LINK_PATH="${PACKAGE_LINK_PATH}"
+export PACKAGE_DISTRO="${PACKAGE_DISTRO}"
+export PACKAGE_URGENCY="${PACKAGE_URGENCY}"
+export PACKAGE_NAME_EMAIL="${PACKAGE_NAME_EMAIL}"
+export PACKAGE_GROUP_NAME_EMAIL="${PACKAGE_GROUP_NAME_EMAIL}"
+export PACKAGE_WEBSITE="${PACKAGE_WEBSITE}"
+
+export PROGRAM_NAME="${PROGRAM_NAME}"
+export PROGRAM_VERSION="${PROGRAM_VERSION}"
+export PROGRAM_DESCRIPTION="${PROGRAM_DESCRIPTION}"
+export PROGRAM_FILENAME="${PROGRAM_FILENAME}"
+
+# This file is called in debian_template.sh, so mark our completion so we don't run it again
+__DEBIAN_PARAMETERS_INITIALIZED=1
diff --git a/deployer/travis/deployer_dput.sh b/deployer/travis/deployer_dput.sh
new file mode 100644
index 000000000..863a928cd
--- /dev/null
+++ b/deployer/travis/deployer_dput.sh
@@ -0,0 +1,133 @@
+#!/bin/bash
+
+# Deployer for Travis-CI
+# DPUT uploader (e.g., Launchpad PPA)
+#
+
+if [[ "$__DPL_DPUT_ACTIVE" == "1" ]]; then
+ # Install APT dependencies
+ # paramiko required for ssh
+ sudo apt-get install python-paramiko expect dput; # python-pip
+ #pip install paramiko;
+
+ # Output the DPUT config
+ # Dput only works if you're using secure FTP, so that's what we default to.
+ cat > "./dput.cf" << EOM
+[deployer]
+fqdn = ${DPL_DPUT_DOMAIN}
+method = ${DPL_DPUT_METHOD}
+incoming = ${DPL_DPUT_INCOMING}
+login = ${DPL_DPUT_LOGIN}
+allow_unsigned_uploads = 0
+EOM
+
+ # Output SSH config
+ # Don't let SSH prompt us for untrusted hosts
+ cat >> "./ssh_config" << EOM
+
+Host *
+ StrictHostKeyChecking no
+ UserKnownHostsFile=/dev/null
+ PubKeyAuthentication yes
+ IdentityFile ${PWD}/key.private
+ IdentitiesOnly yes
+EOM
+ sudo sh -c "cat < ${PWD}/ssh_config >> /etc/ssh/ssh_config";
+
+ # Get the private key
+ echo "$DPL_SSH_KEY_PRIVATE" | base64 --decode > key.private;
+ chmod 700 ./key.private;
+
+ if [[ "$_DPL_PACKAGE_MAIN" == "1" ]]; then
+ PACKAGEFILENAME=${PACKAGE_NAME}_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ PACKAGEDBGFILENAME=${PACKAGE_NAME}-dbg_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGENIGHTLYFILENAME=${PACKAGE_NAME}-nightly_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGENIGHTLYDBGFILENAME=${PACKAGE_NAME}-nightly-dbg_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGEPATCHFILENAME=${PACKAGE_NAME}-patch_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGEPATCHDBGFILENAME=${PACKAGE_NAME}-patch-dbg_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGEPATCHNIGHTLYFILENAME=${PACKAGE_NAME}-patch-nightly_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGEPATCHNIGHTLYDBGFILENAME=${PACKAGE_NAME}-patch-nightly-dbg_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+
+ PACKAGEFILENAMES=(
+ $PACKAGEFILENAME
+ $PACKAGEDBGFILENAME
+ #$PACKAGENIGHTLYFILENAME
+ #$PACKAGENIGHTLYDBGFILENAME
+ #$PACKAGEPATCHFILENAME
+ #$PACKAGEPATCHDBGFILENAME
+ #$PACKAGEPATCHNIGHTLYFILENAME
+ #$PACKAGEPATCHNIGHTLYDBGFILENAME
+ );
+
+ # Main packages are in parent of root repo folder
+ OLDPWD=$PWD; # [repo]/build
+ cd ../..;
+
+ # Enter passphrase if required
+ for n in ${PACKAGEFILENAMES}; do
+ for f in $n*.changes; do
+ # Binary builds also generate source builds, so exclude the source
+ # builds if desired
+ if [[ "$_DPL_PACKAGE_SOURCE" != "1" ]]; then
+ if [[ "$f" == *"_source"* ]] || [[ "$f" == *".tar.xz"* ]]; then
+ continue;
+ fi;
+ fi;
+
+ expect <(cat < "commit.txt";
+ echo "Job ID $TRAVIS_JOB_ID" >> "commit.txt";
+ echo "" >> "commit.txt";
+ echo "Commit $TRAVIS_COMMIT" >> "commit.txt";
+ echo "$TRAVIS_COMMIT_MESSAGE" >> "commit.txt";
+ echo "" >> "commit.txt";
+
+ # Initialize FTP parameters
+ if [[ "$DPL_FTP_PORT" == "" ]]; then
+ DPL_FTP_PORT=21;
+ fi;
+ if [[ "$DPL_FTP_PROTOCOL" == "" ]]; then
+ DPL_FTP_PROTOCOL=ftp;
+ fi;
+ __DPL_FTP_LOCATION=$DPL_FTP_PROTOCOL://$DPL_FTP_HOSTNAME:$DPL_FTP_PORT/$DPL_FTP_PATH/$TRAVIS_REPO_SLUG/$TRAVIS_BRANCH/$TRAVIS_JOB_ID-$TRAVIS_JOB_NUMBER-$JOBNAME;
+
+ # Upload to FTP!
+ echo "Uploading to FTP...";
+ curl --ftp-create-dirs -T "commit.txt" -u $DPL_FTP_USER:$DPL_FTP_PASS "$__DPL_FTP_LOCATION/commit.txt";
+
+ if [[ "$__DPL_DEBIAN_ACTIVE" == "1" ]]; then
+ if [[ "$_DPL_PACKAGE_MAIN" == "1" ]]; then
+ PACKAGEFILENAME=${PACKAGE_NAME}_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ PACKAGEDBGFILENAME=${PACKAGE_NAME}-dbg_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGENIGHTLYFILENAME=${PACKAGE_NAME}-nightly_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGENIGHTLYDBGFILENAME=${PACKAGE_NAME}-nightly-dbg_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGEPATCHFILENAME=${PACKAGE_NAME}-patch_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGEPATCHDBGFILENAME=${PACKAGE_NAME}-patch-dbg_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGEPATCHNIGHTLYFILENAME=${PACKAGE_NAME}-patch-nightly_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGEPATCHNIGHTLYDBGFILENAME=${PACKAGE_NAME}-patch-nightly-dbg_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+
+ PACKAGEFILENAMES=(
+ $PACKAGEFILENAME
+ $PACKAGEDBGFILENAME
+ #$PACKAGENIGHTLYFILENAME
+ #$PACKAGENIGHTLYDBGFILENAME
+ #$PACKAGEPATCHFILENAME
+ #$PACKAGEPATCHDBGFILENAME
+ #$PACKAGEPATCHNIGHTLYFILENAME
+ #$PACKAGEPATCHNIGHTLYDBGFILENAME
+ );
+
+ # Main packages are in parent of root repo folder
+ OLDPWD=$PWD; # [repo]/build
+ cd ../..;
+
+ for n in ${PACKAGEFILENAMES}; do
+ for f in ./$n*; do
+ # Binary builds also generate source builds, so exclude the source
+ # builds if desired
+ if [[ "$_DPL_PACKAGE_SOURCE" != "1" ]]; then
+ if [[ "$f" == *"_source"* ]] || [[ "$f" == *".tar.xz"* ]]; then
+ continue;
+ fi;
+ fi;
+ curl --ftp-create-dirs -T "$f" -u $DPL_FTP_USER:$DPL_FTP_PASS "$__DPL_FTP_LOCATION/package/main/$f";
+ done;
+ done;
+
+ # Go back to [repo]/build folder
+ cd $OLDPWD;
+ fi;
+
+ if [[ "$_DPL_PACKAGE_ASSET" == "1" ]]; then
+ PACKAGEFILENAME=${PACKAGE_NAME}-data_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGENIGHTLYFILENAME=${PACKAGE_NAME}-nightly-data_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGEPATCHFILENAME=${PACKAGE_NAME}-patch-data_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+ #PACKAGEPATCHNIGHTLYFILENAME=${PACKAGE_NAME}-patch-nightly-data_${PACKAGE_VERSION}${PACKAGE_SUBVERSION}${PACKAGE_REVISION};
+
+ PACKAGEFILENAMES=(
+ $PACKAGEFILENAME
+ #$PACKAGENIGHTLYFILENAME
+ #$PACKAGEPATCHFILENAME
+ #$PACKAGEPATCHNIGHTLYFILENAME
+ )
+
+ # Asset packages are in root repo folder
+ OLDPWD=$PWD; # [repo]/build
+ cd ..;
+
+ for n in ${PACKAGEFILENAMES}; do
+ for f in ./$n*; do
+ # Binary builds also generate source builds, so exclude the source
+ # builds if desired
+ if [[ "$_DPL_PACKAGE_SOURCE" != "1" ]]; then
+ if [[ "$f" == *"_source"* ]] || [[ "$f" == *".tar.xz"* ]]; then
+ continue;
+ fi;
+ fi;
+ curl --ftp-create-dirs -T "$f" -u $DPL_FTP_USER:$DPL_FTP_PASS "$__DPL_FTP_LOCATION/package/asset/$f";
+ done;
+ done;
+
+ # Go back to [repo]/build folder
+ cd $OLDPWD;
+ fi;
+ else
+ if [[ "$_DPL_BINARY" == "1" ]]; then
+ find bin -type f -exec curl -u $DPL_FTP_USER:$DPL_FTP_PASS --ftp-create-dirs -T {} $__DPL_FTP_LOCATION/{} \;;
+ fi;
+
+ if [[ "$_DPL_PACKAGE_BINARY" == "1" ]]; then
+ sudo rm -r package/_CPack_Packages
+ find package -type f -exec curl -u $DPL_FTP_USER:$DPL_FTP_PASS --ftp-create-dirs -T {} $__DPL_FTP_LOCATION/{} \;;
+ fi;
+ fi;
+fi
diff --git a/srb2.png b/srb2.png
index 72a08f664..fccde9c3f 100644
Binary files a/srb2.png and b/srb2.png differ
diff --git a/src/config.h.in b/src/config.h.in
index dd86966e1..cb343d065 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -36,8 +36,8 @@
/* Manually defined asset hashes for non-CMake builds
* 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 / 11 / 16 - Kart v1.0.0 - Main assets
- * Last updated 2018 / 12 / 13 - Kart v1.0.2 - patch.kart
+ * Last updated 2019 / 01 / 18 - Kart v1.0.2 - Main assets
+ * Last updated 2019 / 01 / 15 - Kart v1.0.2 - patch.kart
*/
// Base SRB2 hashes
@@ -49,10 +49,10 @@
// SRB2Kart-specific hashes
#define ASSET_HASH_GFX_KART "99c39f223d84ebc78e67ab68f3bead95"
#define ASSET_HASH_TEXTURES_KART "ec8e9b7535cf585afe72ef277b08f490"
-#define ASSET_HASH_CHARS_KART "784ee9177b01c8cb26edff43eaf93d87"
-#define ASSET_HASH_MAPS_KART "84018d9b35d181ca9fcc2be5a9d43a45"
+#define ASSET_HASH_CHARS_KART "e2c428347dde52858a3dacd29fc5b964"
+#define ASSET_HASH_MAPS_KART "1335cd064656aedca359cfbb5233ac4a"
#ifdef USE_PATCH_KART
-#define ASSET_HASH_PATCH_KART "843a13a73935dc4df721427a8948fb89"
+#define ASSET_HASH_PATCH_KART "899aee1b63e731b7e2098406c85608b4"
#endif
#endif
diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index be6390341..c84faa721 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -2076,7 +2076,8 @@ static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic
I_OsPolling();
key = I_GetKey();
- if (key == KEY_ESCAPE || key == KEY_JOY1+1)
+ // Only ESC and non-keyboard keys abort connection
+ if (key == KEY_ESCAPE || key >= 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);
@@ -3024,6 +3025,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 };
#ifdef VANILLAJOINNEXTROUND
consvar_t cv_joinnextround = {"joinnextround", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done
@@ -3079,7 +3083,6 @@ void D_ClientServerInit(void)
CV_RegisterVar(&cv_joinnextround);
#endif
CV_RegisterVar(&cv_showjoinaddress);
- CV_RegisterVar(&cv_resynchattempts);
CV_RegisterVar(&cv_blamecfail);
#ifdef DUMPCONSISTENCY
CV_RegisterVar(&cv_dumpconsistency);
@@ -3882,6 +3885,32 @@ static void HandlePacketFromAwayNode(SINT8 node)
#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
*
* \param node The packet sender
@@ -3976,18 +4005,8 @@ FILESTAMP
G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1);
// Check ticcmd for "speed hacks"
- if (netcmds[maketic%BACKUPTICS][netconsole].forwardmove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].forwardmove < -MAXPLMOVE
- || netcmds[maketic%BACKUPTICS][netconsole].sidemove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].sidemove < -MAXPLMOVE)
- {
- XBOXSTATIC char buf[2];
- CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), netconsole);
- //D_Clearticcmd(k);
-
- buf[0] = (char)netconsole;
- buf[1] = KICK_MSG_CON_FAIL;
- SendNetXCmd(XD_KICK, &buf, 2);
+ if (CheckForSpeedHacks((UINT8)netconsole))
break;
- }
// Splitscreen cmd
if (((netbuffer->packettype == PT_CLIENT2CMD || netbuffer->packettype == PT_CLIENT2MIS)
@@ -3997,6 +4016,9 @@ FILESTAMP
{
G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]],
&netbuffer->u.client2pak.cmd2, 1);
+
+ if (CheckForSpeedHacks((UINT8)nodetoplayer2[node]))
+ break;
}
if (((netbuffer->packettype == PT_CLIENT3CMD || netbuffer->packettype == PT_CLIENT3MIS)
@@ -4005,6 +4027,9 @@ FILESTAMP
{
G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer3[node]],
&netbuffer->u.client3pak.cmd3, 1);
+
+ if (CheckForSpeedHacks((UINT8)nodetoplayer3[node]))
+ break;
}
if ((netbuffer->packettype == PT_CLIENT4CMD || netbuffer->packettype == PT_CLIENT4MIS)
@@ -4012,6 +4037,9 @@ FILESTAMP
{
G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer4[node]],
&netbuffer->u.client4pak.cmd4, 1);
+
+ if (CheckForSpeedHacks((UINT8)nodetoplayer4[node]))
+ break;
}
// A delay before we check resynching
@@ -4932,6 +4960,10 @@ void TryRunTics(tic_t realtics)
ExtraDataTicker();
gametic++;
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
diff --git a/src/d_clisrv.h b/src/d_clisrv.h
index f1abffaf2..39cb8c4de 100644
--- a/src/d_clisrv.h
+++ b/src/d_clisrv.h
@@ -433,10 +433,10 @@ typedef struct
UINT8 reserved; // Padding
union
{
- clientcmd_pak clientpak; // 144 bytes
- client2cmd_pak client2pak; // 200 bytes
- client3cmd_pak client3pak; // 256 bytes(?)
- client4cmd_pak client4pak; // 312 bytes(?)
+ clientcmd_pak clientpak; // 145 bytes
+ client2cmd_pak client2pak; // 202 bytes
+ client3cmd_pak client3pak; // 258 bytes(?)
+ client4cmd_pak client4pak; // 316 bytes(?)
servertics_pak serverpak; // 132495 bytes (more around 360, no?)
serverconfig_pak servercfg; // 773 bytes
resynchend_pak resynchend; //
@@ -524,7 +524,7 @@ extern consvar_t
#ifdef VANILLAJOINNEXTROUND
cv_joinnextround,
#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
tic_t ExpandTics(INT32 low);
diff --git a/src/d_main.c b/src/d_main.c
index 2a5993c17..29a916863 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -1350,6 +1350,7 @@ void D_SRB2Main(void)
I_StartupSound();
I_InitMusic();
S_InitSfxChannels(cv_soundvolume.value);
+ S_InitMusicDefs();
CONS_Printf("ST_Init(): Init status bar.\n");
ST_Init();
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 08ef0434d..6d90801cc 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -357,7 +357,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_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}};
-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}};
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}};
@@ -484,6 +484,7 @@ const char *netxcmdnames[MAXNETXCMD - 1] =
"SETUPVOTE",
"MODIFYVOTE",
"PICKVOTE",
+ "REMOVEPLAYER",
#ifdef HAVE_BLUA
"LUACMD",
"LUAVAR"
@@ -647,6 +648,7 @@ void D_RegisterServerCommands(void)
// d_clisrv
CV_RegisterVar(&cv_maxplayers);
+ CV_RegisterVar(&cv_resynchattempts);
CV_RegisterVar(&cv_maxsend);
CV_RegisterVar(&cv_noticedownload);
CV_RegisterVar(&cv_downloadspeed);
@@ -762,6 +764,7 @@ void D_RegisterClientCommands(void)
#endif
CV_RegisterVar(&cv_rollingdemos);
CV_RegisterVar(&cv_netstat);
+ CV_RegisterVar(&cv_netticbuffer);
#ifdef NETGAME_DEVMODE
CV_RegisterVar(&cv_fishcake);
@@ -792,6 +795,7 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_consolechat);
CV_RegisterVar(&cv_chatnotifications);
CV_RegisterVar(&cv_chatbacktint);
+ CV_RegisterVar(&cv_songcredits);
//CV_RegisterVar(&cv_crosshair);
//CV_RegisterVar(&cv_crosshair2);
//CV_RegisterVar(&cv_crosshair3);
@@ -839,14 +843,6 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_addons_search_type);
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
// we need the mouse2port
CV_RegisterVar(&cv_mouse2port);
@@ -2110,7 +2106,7 @@ void D_SetupVote(void)
else
m = G_RandMap(G_TOLFlag(gametype), prevmap, false, 0, true, votebuffer);
if (i < 3)
- votebuffer[i] = m;
+ votebuffer[min(i, 2)] = m; // min() is a dumb workaround for gcc 4.4 array-bounds error
WRITEUINT16(p, m);
}
@@ -2501,6 +2497,12 @@ static void Command_Respawn(void)
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
{
CONS_Printf(M_GetText("You may only use this in co-op, race, and competition!\n"));
@@ -2522,7 +2524,7 @@ static void Got_Respawn(UINT8 **cp, INT32 playernum)
{
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())"
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal respawn command received from %s\n"), player_names[playernum]);
@@ -2537,6 +2539,10 @@ static void Got_Respawn(UINT8 **cp, INT32 playernum)
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)
P_DamageMobj(players[respawnplayer].mo, NULL, NULL, 10000);
}
diff --git a/src/d_netcmd.h b/src/d_netcmd.h
index 7927aea00..2269996fb 100644
--- a/src/d_netcmd.h
+++ b/src/d_netcmd.h
@@ -33,6 +33,8 @@ extern consvar_t cv_skin3;
extern consvar_t cv_playername4;
extern consvar_t cv_playercolor4;
extern consvar_t cv_skin4;
+// preferred number of players
+extern consvar_t cv_splitplayers;
#ifdef SEENAMES
extern consvar_t cv_seenames, cv_allowseenames;
diff --git a/src/d_player.h b/src/d_player.h
index 9ae46c6a8..9308efff8 100644
--- a/src/d_player.h
+++ b/src/d_player.h
@@ -351,6 +351,7 @@ typedef enum
// v1.0.2 vars
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_getsparks, // Disable drift sparks at low speed, JUST enough to give acceleration the actual headstart above speed
k_killfield, // How long have you been in the kill field, stay in too long and lose a bumper
NUMKARTSTUFF
@@ -416,6 +417,8 @@ typedef struct player_s
// SRB2kart stuff
INT32 kartstuff[NUMKARTSTUFF];
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.
// See pflags_t, above.
diff --git a/src/d_ticcmd.h b/src/d_ticcmd.h
index 7df2d4122..dab758f8d 100644
--- a/src/d_ticcmd.h
+++ b/src/d_ticcmd.h
@@ -21,6 +21,8 @@
#pragma interface
#endif
+#define MAXPREDICTTICS 12
+
// Button/action code definitions.
typedef enum
{
@@ -60,6 +62,7 @@ typedef struct
INT16 aiming; // vertical aiming, see G_BuildTicCmd
UINT16 buttons;
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;
#if defined(_MSC_VER)
diff --git a/src/dehacked.c b/src/dehacked.c
index fea00f525..981ae8b30 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -436,11 +436,11 @@ static void readAnimTex(MYFILE *f, INT32 num)
static boolean findFreeSlot(INT32 *num)
{
// 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;
// No more free slots. :(
- if (*num >= 32)
+ if (*num >= MAXSKINS)
return false;
// Found one! ^_^
@@ -3246,9 +3246,9 @@ static void readwipes(MYFILE *f)
else if (fastcmp(pword, "FINAL"))
wipeoffset = wipe_specinter_final;
}
- else if (fastncmp(word, "VOTING_", 10))
+ else if (fastncmp(word, "VOTING_", 7))
{
- pword = word + 10;
+ pword = word + 7;
if (fastcmp(pword, "TOBLACK"))
wipeoffset = wipe_specinter_toblack;
else if (fastcmp(pword, "FINAL"))
@@ -3698,13 +3698,18 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
// no undo support for this insanity yet
//DEH_WriteUndoline(word, word2, UNDO_HEADER);
}
- else if (fastcmp(word, "SRB2"))
+ else if (fastcmp(word, "SRB2KART"))
{
INT32 ver = searchvalue(strtok(NULL, "\n"));
if (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);
}
+ 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)
// Unless you REALLY want to piss people off,
// define a custom gamedata /before/ doing this!!
@@ -6946,7 +6951,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_GARU1",
"S_GARU2",
"S_GARU3",
- "S_TGARU",
+ "S_TGARU",
"S_TGARU1",
"S_TGARU2",
"S_TGARU3", // Wind attack used by Roaming Shadows on Players.
@@ -8302,6 +8307,7 @@ static const char *const KARTSTUFF_LIST[] = {
"ITEMBLINK",
"ITEMBLINKMODE",
+ "GETSPARKS",
"KILLFIELD"
};
diff --git a/src/dehacked.h b/src/dehacked.h
index 411cb6c1b..683fe7d94 100644
--- a/src/dehacked.h
+++ b/src/dehacked.h
@@ -54,7 +54,7 @@ extern const char *superactions[MAXRECURSION];
extern UINT8 superstack;
// If the dehacked patch does not match this version, we throw a warning
-#define PATCHVERSION 210
+#define PATCHVERSION 1
#define MAXLINELEN 1024
diff --git a/src/doomdef.h b/src/doomdef.h
index 975c920b8..70e521b15 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -244,7 +244,7 @@ extern FILE *logstream;
// NOTE: it needs more than this to increase the number of players...
#define MAXPLAYERS 16
-#define MAXSKINS 32
+#define MAXSKINS 64
#define PLAYERSMASK (MAXPLAYERS-1)
#define MAXPLAYERNAME 21
@@ -364,9 +364,9 @@ enum {
// Name of local directory for config files and savegames
#if !defined(_arch_dreamcast) && !defined(_WIN32_WCE) && !defined(GP2X) && !defined(_WII) && !defined(_PS3)
#if (((defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON)) && !defined (__CYGWIN__)) && !defined (__APPLE__)
-#define DEFAULTDIR ".srb2"
+#define DEFAULTDIR ".srb2kart"
#else
-#define DEFAULTDIR "srb2"
+#define DEFAULTDIR "srb2kart"
#endif
#endif
diff --git a/src/f_finale.c b/src/f_finale.c
index d210b9c81..0fe13a8c9 100644
--- a/src/f_finale.c
+++ b/src/f_finale.c
@@ -438,7 +438,7 @@ static const char *credits[] = {
"\"ZarroTsu\"",
"",
"\1Support Programming",
- "\"fickle\"",
+ "Colette \"fickleheart\" Bordelon",
"\"Lat\'\"",
"\"Monster Iestyn\"",
"\"Shuffle\"",
@@ -479,40 +479,10 @@ static const char *credits[] = {
"\"VAdaPEGA\"",
"\"VelocitOni\"",
"",
- "\1Music", // Can't list song names here, so we're listing artists
- "\"Arrow\"",
- "Jonny Atma",
- "Moot Booxle", // Booxlé, add the accent char later?
- "Malcolm Brown",
- "Karl Brueggemann",
+ "\1Music",
"\"DrTapeworm\"",
- "\"Elwood\"",
"Wesley \"Charyb\" Gillebaard",
- "\"gxf4c3\"",
"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",
"\"Blitz-T\"",
@@ -586,7 +556,7 @@ static struct {
// This Tyler52 gag is troublesome
// Alignment should be ((spaces+1 * 100) + (headers+1 * 38) + (lines * 15))
// 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}
};
diff --git a/src/g_game.c b/src/g_game.c
index f0763dd64..68e7a8010 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -438,6 +438,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}};
consvar_t cv_consolechat = {"chatmode", "Window", CV_SAVE, consolechat_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+// Display song credits
+consvar_t cv_songcredits = {"songcredits", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
+
/*consvar_t cv_crosshair = {"crosshair", "Off", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_crosshair2 = {"crosshair2", "Off", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_crosshair3 = {"crosshair3", "Off", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -1209,7 +1212,7 @@ boolean camspin, camspin2, camspin3, camspin4;
static fixed_t forwardmove[2] = {25<>16, 50<>16};
static fixed_t sidemove[2] = {2<>16, 4<>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)
{
@@ -1352,41 +1355,30 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
// let movement keys cancel each other out
if (turnright && !(turnleft))
{
- cmd->angleturn = (INT16)(cmd->angleturn - (angleturn[tspeed] * realtics));
- cmd->driftturn = (INT16)(cmd->driftturn - (angleturn[tspeed] * realtics));
+ cmd->angleturn = (INT16)(cmd->angleturn - (angleturn[tspeed]));
+ cmd->driftturn = (INT16)(cmd->driftturn - (angleturn[tspeed]));
+ side += sidemove[1];
}
else if (turnleft && !(turnright))
{
- cmd->angleturn = (INT16)(cmd->angleturn + (angleturn[tspeed] * realtics));
- cmd->driftturn = (INT16)(cmd->driftturn + (angleturn[tspeed] * realtics));
+ cmd->angleturn = (INT16)(cmd->angleturn + (angleturn[tspeed]));
+ cmd->driftturn = (INT16)(cmd->driftturn + (angleturn[tspeed]));
+ side -= sidemove[1];
}
if (analogjoystickmove && axis != 0)
{
// JOYAXISRANGE should be 1023 (divide by 1024)
- cmd->angleturn = (INT16)(cmd->angleturn - (((axis * angleturn[1]) >> 10) * realtics)); // ANALOG!
- cmd->driftturn = (INT16)(cmd->driftturn - (((axis * angleturn[1]) >> 10) * realtics));
+ cmd->angleturn = (INT16)(cmd->angleturn - (((axis * angleturn[1]) >> 10))); // ANALOG!
+ cmd->driftturn = (INT16)(cmd->driftturn - (((axis * angleturn[1]) >> 10)));
+ side += ((axis * sidemove[0]) >> 10);
}
// Specator mouse turning
if (player->spectator)
{
- cmd->angleturn = (INT16)(cmd->angleturn - ((mousex*(encoremode ? -1 : 1)*8) * realtics));
- cmd->driftturn = (INT16)(cmd->driftturn - ((mousex*(encoremode ? -1 : 1)*8) * realtics));
- }
-
- // 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);
- }
+ cmd->angleturn = (INT16)(cmd->angleturn - ((mousex*(encoremode ? -1 : 1)*8)));
+ cmd->driftturn = (INT16)(cmd->driftturn - ((mousex*(encoremode ? -1 : 1)*8)));
}
if (player->spectator || objectplacing) // SRB2Kart: spectators need special controls
@@ -1531,15 +1523,6 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
else if (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)
{
cmd->forwardmove = (SINT8)(cmd->forwardmove + forward);
@@ -1549,19 +1532,21 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
//{ 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
// limit turning to angleturn[1] to stop mouselook letting you look too fast
- if (cmd->angleturn > (angleturn[1] * realtics))
- cmd->angleturn = (angleturn[1] * realtics);
- else if (cmd->angleturn < (-angleturn[1] * realtics))
- cmd->angleturn = (-angleturn[1] * realtics);
+ if (cmd->angleturn > (angleturn[1]))
+ cmd->angleturn = (angleturn[1]);
+ else if (cmd->angleturn < (-angleturn[1]))
+ cmd->angleturn = (-angleturn[1]);
- if (cmd->driftturn > (angleturn[1] * realtics))
- cmd->driftturn = (angleturn[1] * realtics);
- else if (cmd->driftturn < (-angleturn[1] * realtics))
- cmd->driftturn = (-angleturn[1] * realtics);
+ if (cmd->driftturn > (angleturn[1]))
+ cmd->driftturn = (angleturn[1]);
+ else if (cmd->driftturn < (-angleturn[1]))
+ cmd->driftturn = (-angleturn[1]);
if (player->mo)
cmd->angleturn = K_GetKartTurnValue(player, cmd->angleturn);
+ cmd->angleturn *= realtics;
+
// SRB2kart - no additional angle if not moving
if (((player->mo && player->speed > 0) // Moving
|| (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn
@@ -1571,6 +1556,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
lang += (cmd->angleturn<<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)
{
@@ -1612,10 +1598,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.
if ((cmd->forwardmove || cmd->sidemove || cmd->buttons)
&& displayplayer != consoleplayer && ssplayer == 1)
displayplayer = consoleplayer;
+
}
// User has designated that they want
@@ -2154,6 +2156,9 @@ void G_Ticker(boolean run)
players[i].kartstuff[k_throwdir] = 0;
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, MAXPREDICTTICS-1); //@TODO add a cvar to allow setting this max
}
}
@@ -2362,6 +2367,7 @@ void G_PlayerReborn(INT32 player)
INT32 bumper;
INT32 comebackpoints;
INT32 wanted;
+ boolean songcredit = false;
score = players[player].score;
marescore = players[player].marescore;
@@ -2540,10 +2546,13 @@ void G_PlayerReborn(INT32 player)
strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7);
mapmusname[6] = 0;
mapmusflags = mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK;
+ songcredit = true;
}
}
P_RestoreMusic(p);
+ if (songcredit)
+ S_ShowMusicCredit();
if (leveltime > (starttime + (TICRATE/2)) && !p->spectator)
p->kartstuff[k_respawn] = 48; // Respawn effect
@@ -3169,7 +3178,7 @@ INT16 G_SometimesGetDifferentGametype(void)
break;
case 1: // sometimes
default:
- encorepossible = M_RandomChance(FRACUNIT>>3);
+ encorepossible = M_RandomChance(FRACUNIT>>2);
break;
}
if (encorepossible != (boolean)cv_kartencore.value)
@@ -3184,12 +3193,12 @@ INT16 G_SometimesGetDifferentGametype(void)
randmapbuffer[NUMMAPS] = 1; // every other vote (or always if !encorepossible)
break;
case 1: // sometimes
- randmapbuffer[NUMMAPS] = 10; // ...every two cups?
+ randmapbuffer[NUMMAPS] = 5; // per "cup"
break;
default:
// fallthrough - happens when clearing buffer, but needs a reasonable countdown if cvar is modified
case 2: // frequent
- randmapbuffer[NUMMAPS] = 5; // per "cup"
+ randmapbuffer[NUMMAPS] = 2; // ...every 1/2th-ish cup?
break;
}
@@ -4557,6 +4566,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].buttons = (UINT16)SHORT(src[i].buttons);
dest[i].driftturn = (INT16)SHORT(src[i].driftturn);
+ dest[i].latency = (INT16)SHORT(src[i].latency);
}
return dest;
}
diff --git a/src/g_game.h b/src/g_game.h
index 720d561fb..6d11a4a02 100644
--- a/src/g_game.h
+++ b/src/g_game.h
@@ -55,6 +55,7 @@ extern INT16 rw_maximums[NUM_WEAPONS];
// 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_songcredits;
//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_invertmouse2/*, cv_alwaysfreelook2, cv_chasefreelook2, cv_mousemove2*/;
@@ -65,7 +66,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_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_splitplayers;
typedef enum
{
diff --git a/src/g_input.c b/src/g_input.c
index d7b7be91c..871c1e604 100644
--- a/src/g_input.c
+++ b/src/g_input.c
@@ -120,7 +120,7 @@ void G_MapEventsToControls(event_t *ev)
case ev_joystick2: // buttons are virtual keys
i = ev->data1;
- if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on)
+ if (i >= JOYAXISSET || menuactive)
break;
if (ev->data2 != INT32_MAX) joy2xmove[i] = ev->data2;
if (ev->data3 != INT32_MAX) joy2ymove[i] = ev->data3;
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 4d0a7236c..c45814bbc 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -5263,7 +5263,8 @@ static void HWR_DrawSprites(void)
#endif
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);
else
HWR_DrawMD2(spr);
diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c
index 2856cada3..e50c13652 100644
--- a/src/hardware/hw_md2.c
+++ b/src/hardware/hw_md2.c
@@ -300,8 +300,12 @@ static md2_model_t *md2_readModel(const char *filename)
file = fopen(va("%s"PATHSEP"%s", srb2home, filename), "rb");
if (!file)
{
- free(model);
- return 0;
+ file = fopen(va("%s"PATHSEP"%s", srb2path, filename), "rb");
+ if (!file)
+ {
+ free(model);
+ return 0;
+ }
}
// initialize model and read header
@@ -492,7 +496,7 @@ static GrTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_
jmp_buf jmpbuf;
#endif
#endif
- png_FILE_p png_FILE;
+ volatile png_FILE_p png_FILE;
//Filename checking fixed ~Monster Iestyn and Golden
char *pngfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2home, filename);
@@ -500,8 +504,12 @@ static GrTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_
png_FILE = fopen(pngfilename, "rb");
if (!png_FILE)
{
+ pngfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2path, filename);
+ FIL_ForceExtension(pngfilename, ".png");
+ png_FILE = fopen(pngfilename, "rb");
//CONS_Debug(DBG_RENDER, "M_SavePNG: Error on opening %s for loading\n", filename);
- return 0;
+ if (!png_FILE)
+ return 0;
}
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
@@ -628,7 +636,13 @@ static GrTextureFormat_t PCX_Load(const char *filename, int *w, int *h,
FIL_ForceExtension(pcxfilename, ".pcx");
file = fopen(pcxfilename, "rb");
if (!file)
- return 0;
+ {
+ pcxfilename = va("%s"PATHSEP"md2"PATHSEP"%s", srb2path, filename);
+ FIL_ForceExtension(pcxfilename, ".pcx");
+ file = fopen(pcxfilename, "rb");
+ if (!file)
+ return 0;
+ }
if (fread(&header, sizeof (PcxHeader), 1, file) != 1)
{
@@ -818,17 +832,22 @@ void HWR_InitMD2(void)
if (!f)
{
- CONS_Printf("%s %s\n", M_GetText("Error while loading kmd2.dat:"), strerror(errno));
- nomd2s = true;
- return;
+ f = fopen(va("%s"PATHSEP"%s", srb2path, "kmd2.dat"), "rt");
+ if (!f)
+ {
+ CONS_Printf("%s %s\n", M_GetText("Error while loading kmd2.dat:"), strerror(errno));
+ nomd2s = true;
+ return;
+ }
}
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");
continue;
- }
+ }*/
+ // 8/1/19: Allow PLAY to load for default MD2.
for (i = 0; i < NUMSPRITES; i++)
{
@@ -885,9 +904,13 @@ void HWR_AddPlayerMD2(int skin) // For MD2's that were added after startup
if (!f)
{
- CONS_Printf("Error while loading kmd2.dat\n");
- nomd2s = true;
- return;
+ f = fopen(va("%s"PATHSEP"%s", srb2path, "kmd2.dat"), "rt");
+ if (!f)
+ {
+ CONS_Printf("%s %s\n", M_GetText("Error while loading kmd2.dat:"), strerror(errno));
+ nomd2s = true;
+ return;
+ }
}
// Check for any MD2s that match the names of player skins!
@@ -931,9 +954,13 @@ void HWR_AddSpriteMD2(size_t spritenum) // For MD2s that were added after startu
if (!f)
{
- CONS_Printf("Error while loading kmd2.dat\n");
- nomd2s = true;
- return;
+ f = fopen(va("%s"PATHSEP"%s", srb2path, "kmd2.dat"), "rt");
+ if (!f)
+ {
+ CONS_Printf("%s %s\n", M_GetText("Error while loading kmd2.dat:"), strerror(errno));
+ nomd2s = true;
+ return;
+ }
}
// Check for any MD2s that match the names of player skins!
@@ -1181,6 +1208,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
// MD2 colormap fix
// colormap test
+ if (spr->mobj->subsector)
{
sector_t *sector = spr->mobj->subsector->sector;
UINT8 lightlevel = 255;
@@ -1212,6 +1240,10 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
else
Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false);
}
+ else
+ {
+ Surf.FlatColor.rgba = 0xFFFFFFFF;
+ }
// Look at HWR_ProjectSprite for more
{
@@ -1241,19 +1273,19 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
// 1. load model+texture if not already loaded
// 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->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];
if (md2->error)
return; // we already failed loading this before :(
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);
md2->model = md2_readModel(filename);
@@ -1286,7 +1318,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
md2->blendgrpatch && ((GLPatch_t *)md2->blendgrpatch)->mipmap.grInfo.format
&& gpatch->width == ((GLPatch_t *)md2->blendgrpatch)->width && gpatch->height == ((GLPatch_t *)md2->blendgrpatch)->height)
{
- INT32 skinnum;
+ INT32 skinnum = TC_DEFAULT;
if ((spr->mobj->flags & MF_BOSS) && (spr->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash"
{
if (spr->mobj->type == MT_CYBRAKDEMON)
diff --git a/src/hu_stuff.c b/src/hu_stuff.c
index 6e1ef35e8..a308dfc2b 100644
--- a/src/hu_stuff.c
+++ b/src/hu_stuff.c
@@ -51,6 +51,7 @@
#include "lua_hook.h"
#endif
+#include "s_sound.h" // song credits
#include "k_kart.h"
// coords are scaled
@@ -103,6 +104,8 @@ static patch_t *tokenicon;
// crosshair 0 = off, 1 = cross, 2 = angle, 3 = point, see m_menu.c
static patch_t *crosshair[HU_CROSSHAIRS]; // 3 precached crosshair graphics
+// song credits
+static patch_t *songcreditbg;
// -------
// protos.
@@ -290,6 +293,8 @@ void HU_LoadGraphics(void)
tinyemeraldpics[4] = W_CachePatchName("TEMER5", PU_HUDGFX);
tinyemeraldpics[5] = W_CachePatchName("TEMER6", PU_HUDGFX);
tinyemeraldpics[6] = W_CachePatchName("TEMER7", PU_HUDGFX);
+
+ songcreditbg = W_CachePatchName("K_SONGCR", PU_HUDGFX);
}
// Initialise Heads up
@@ -478,7 +483,6 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
const char *newmsg;
INT32 spc = 1; // used if nodenum[1] is a space.
char *nodenum = (char*) malloc(3);
-
strncpy(nodenum, msg+3, 3);
// check for undesirable characters in our "number"
if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9')))
@@ -1180,6 +1184,12 @@ boolean HU_Responder(event_t *ev)
|| ev->data1 == KEY_LALT || ev->data1 == KEY_RALT)
return true;
+ // 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;
+
c = (INT32)ev->data1;
// I know this looks very messy but this works. If it ain't broke, don't fix it!
@@ -1417,13 +1427,16 @@ static void HU_drawMiniChat(void)
y = chaty - charheight*(msglines+1);
+#ifdef NETSPLITSCREEN
if (splitscreen)
{
y -= BASEVIDHEIGHT/2;
if (splitscreen > 1)
y += 16;
}
- y -= (cv_kartspeedometer.value ? 16 : 0);
+ else
+#endif
+ y -= (cv_kartspeedometer.value ? 16 : 0);
dx = 0;
dy = 0;
@@ -2120,6 +2133,51 @@ static void HU_DrawDemoInfo(void)
}
}
+
+//
+// Song credits
+//
+static void HU_DrawSongCredits(void)
+{
+ char *str;
+ INT32 len, destx;
+ INT32 y = (splitscreen ? (BASEVIDHEIGHT/2)-4 : 32);
+ INT32 bgt;
+
+ if (!cursongcredit.def) // No def
+ return;
+
+ str = va("\x1F"" %s", cursongcredit.def->source);
+ len = V_ThinStringWidth(str, V_ALLOWLOWERCASE|V_6WIDTHSPACE);
+ destx = (len+7);
+
+ if (cursongcredit.anim)
+ {
+ if (cursongcredit.trans > 0)
+ cursongcredit.trans--;
+ if (cursongcredit.x < destx)
+ cursongcredit.x += (destx - cursongcredit.x) / 2;
+ if (cursongcredit.x > destx)
+ cursongcredit.x = destx;
+ cursongcredit.anim--;
+ }
+ else
+ {
+ if (cursongcredit.trans < NUMTRANSMAPS)
+ cursongcredit.trans++;
+ if (cursongcredit.x > 0)
+ cursongcredit.x /= 2;
+ if (cursongcredit.x < 0)
+ cursongcredit.x = 0;
+ }
+
+ bgt = (NUMTRANSMAPS/2)+(cursongcredit.trans/2);
+ if (bgt < NUMTRANSMAPS)
+ V_DrawScaledPatch(cursongcredit.x, y-2, V_SNAPTOLEFT|(bgt<kartstuff[k_tauntvoices] = 4*TICRATE;
}
-static void K_PlayAttackTaunt(mobj_t *source)
+void K_PlayAttackTaunt(mobj_t *source)
{
sfxenum_t pick = P_RandomKey(2); // Gotta roll the RNG every time this is called for sync reasons
boolean tasteful = (!source->player || !source->player->kartstuff[k_tauntvoices]);
@@ -1562,7 +1562,7 @@ static void K_PlayAttackTaunt(mobj_t *source)
K_TauntVoiceTimers(source->player);
}
-static void K_PlayBoostTaunt(mobj_t *source)
+void K_PlayBoostTaunt(mobj_t *source)
{
sfxenum_t pick = P_RandomKey(2); // Gotta roll the RNG every time this is called for sync reasons
boolean tasteful = (!source->player || !source->player->kartstuff[k_tauntvoices]);
@@ -1576,7 +1576,7 @@ static void K_PlayBoostTaunt(mobj_t *source)
K_TauntVoiceTimers(source->player);
}
-static void K_PlayOvertakeSound(mobj_t *source)
+void K_PlayOvertakeSound(mobj_t *source)
{
boolean tasteful = (!source->player || !source->player->kartstuff[k_voices]);
@@ -1596,7 +1596,7 @@ static void K_PlayOvertakeSound(mobj_t *source)
K_RegularVoiceTimers(source->player);
}
-static void K_PlayHitEmSound(mobj_t *source)
+void K_PlayHitEmSound(mobj_t *source)
{
if (cv_kartvoices.value)
S_StartSound(source, sfx_khitem);
@@ -1606,7 +1606,7 @@ static void K_PlayHitEmSound(mobj_t *source)
K_RegularVoiceTimers(source->player);
}
-static void K_PlayPowerGloatSound(mobj_t *source)
+void K_PlayPowerGloatSound(mobj_t *source)
{
if (cv_kartvoices.value)
S_StartSound(source, sfx_kgloat);
@@ -4483,7 +4483,10 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
// Plays the music after the starting countdown.
if (P_IsLocalPlayer(player) && leveltime == (starttime + (TICRATE/2)))
- S_ChangeMusicInternal(mapmusname, true);
+ {
+ S_ChangeMusic(mapmusname, mapmusflags, true);
+ S_ShowMusicCredit();
+ }
}
void K_KartPlayerAfterThink(player_t *player)
@@ -4624,6 +4627,7 @@ INT32 K_GetKartDriftSparkValue(player_t *player)
static void K_KartDrift(player_t *player, boolean onground)
{
+ fixed_t minspeed = (10 * player->mo->scale);
INT32 dsone = K_GetKartDriftSparkValue(player);
INT32 dstwo = dsone*2;
INT32 dsthree = dstwo*2;
@@ -4674,14 +4678,14 @@ static void K_KartDrift(player_t *player, boolean onground)
}
// Drifting: left or right?
- if ((player->cmd.driftturn > 0) && player->speed > FixedMul(10<<16, player->mo->scale) && player->kartstuff[k_jmp] == 1
+ if ((player->cmd.driftturn > 0) && player->speed > minspeed && player->kartstuff[k_jmp] == 1
&& (player->kartstuff[k_drift] == 0 || player->kartstuff[k_driftend] == 1)) // && player->kartstuff[k_drift] != 1)
{
// Starting left drift
player->kartstuff[k_drift] = 1;
player->kartstuff[k_driftend] = player->kartstuff[k_driftcharge] = 0;
}
- else if ((player->cmd.driftturn < 0) && player->speed > FixedMul(10<<16, player->mo->scale) && player->kartstuff[k_jmp] == 1
+ else if ((player->cmd.driftturn < 0) && player->speed > minspeed && player->kartstuff[k_jmp] == 1
&& (player->kartstuff[k_drift] == 0 || player->kartstuff[k_driftend] == 1)) // && player->kartstuff[k_drift] != -1)
{
// Starting right drift
@@ -4705,6 +4709,8 @@ static void K_KartDrift(player_t *player, boolean onground)
player->kartstuff[k_driftend] = 0;
}
+
+
// Incease/decrease the drift value to continue drifting in that direction
if (player->kartstuff[k_spinouttimer] == 0 && player->kartstuff[k_jmp] == 1 && onground && player->kartstuff[k_drift] != 0)
{
@@ -4733,6 +4739,12 @@ static void K_KartDrift(player_t *player, boolean onground)
driftadditive -= abs(player->cmd.driftturn)/75;
}
+ // Disable drift-sparks until you're going fast enough
+ if (player->kartstuff[k_getsparks] == 0)
+ driftadditive = 0;
+ if (player->speed > minspeed*2)
+ player->kartstuff[k_getsparks] = 1;
+
// This spawns the drift sparks
if (player->kartstuff[k_driftcharge] + driftadditive >= dsone)
K_SpawnDriftSparks(player);
@@ -4752,11 +4764,11 @@ static void K_KartDrift(player_t *player, boolean onground)
}
// Stop drifting
- if (player->kartstuff[k_spinouttimer] > 0 // banana peel
- || player->speed < FixedMul(10<<16, player->mo->scale)) // you're too slow!
+ if (player->kartstuff[k_spinouttimer] > 0 || player->speed < minspeed)
{
player->kartstuff[k_drift] = player->kartstuff[k_driftcharge] = 0;
player->kartstuff[k_aizdriftstrat] = player->kartstuff[k_brakedrift] = 0;
+ player->kartstuff[k_getsparks] = 0;
}
if ((!player->kartstuff[k_sneakertimer])
@@ -5526,7 +5538,12 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
if (leveltime >= starttime-(2*TICRATE) && leveltime <= starttime)
{
if (cmd->buttons & BT_ACCELERATE)
+ {
+ if (player->kartstuff[k_boostcharge] == 0)
+ player->kartstuff[k_boostcharge] = cmd->latency;
+
player->kartstuff[k_boostcharge]++;
+ }
else
player->kartstuff[k_boostcharge] = 0;
}
@@ -5855,6 +5872,8 @@ static patch_t *kp_battlelose;
static patch_t *kp_battlewait;
static patch_t *kp_battleinfo;
static patch_t *kp_wanted;
+static patch_t *kp_wantedsplit;
+static patch_t *kp_wantedreticle;
static patch_t *kp_itembg[4];
static patch_t *kp_itemtimer[2];
@@ -5995,6 +6014,8 @@ void K_LoadKartHUDGraphics(void)
kp_battlewait = W_CachePatchName("K_BWAIT", PU_HUDGFX);
kp_battleinfo = W_CachePatchName("K_BINFO", PU_HUDGFX);
kp_wanted = W_CachePatchName("K_WANTED", PU_HUDGFX);
+ kp_wantedsplit = W_CachePatchName("4PWANTED", PU_HUDGFX);
+ kp_wantedreticle = W_CachePatchName("MMAPWANT", PU_HUDGFX);
// Kart Item Windows
kp_itembg[0] = W_CachePatchName("K_ITBG", PU_HUDGFX);
@@ -6207,6 +6228,12 @@ INT32 CHEK_Y; // CHECK graphic
INT32 MINI_X, MINI_Y; // Minimap
INT32 WANT_X, WANT_Y; // Battle WANTED poster
+// This is for the P2 and P4 side of splitscreen. Then we'll flip P1's and P2's to the bottom with V_SPLITSCREEN.
+INT32 ITEM2_X, ITEM2_Y;
+INT32 LAPS2_X, LAPS2_Y;
+INT32 POSI2_X, POSI2_Y;
+
+
static void K_initKartHUD(void)
{
/*
@@ -6287,26 +6314,35 @@ static void K_initKartHUD(void)
MINI_Y = (BASEVIDHEIGHT/2);
- WANT_X = BASEVIDWIDTH-8;
- WANT_Y = (BASEVIDHEIGHT/2)-12;
-
if (splitscreen > 1) // 3P/4P Small Splitscreen
{
+ // 1P (top left)
ITEM_X = -9;
ITEM_Y = -8;
LAPS_X = 3;
LAPS_Y = (BASEVIDHEIGHT/2)-13;
- POSI_X = (BASEVIDWIDTH/2)-3;
+ POSI_X = 24;
+ POSI_Y = (BASEVIDHEIGHT/2)- 16;
+
+ // 2P (top right)
+ ITEM2_X = BASEVIDWIDTH-39;
+ ITEM2_Y = -8;
+
+ LAPS2_X = BASEVIDWIDTH-40;
+ LAPS2_Y = (BASEVIDHEIGHT/2)-13;
+
+ POSI2_X = BASEVIDWIDTH -4;
+ POSI2_Y = (BASEVIDHEIGHT/2)- 16;
+
+ // Reminder that 3P and 4P are just 1P and 2P splitscreen'd to the bottom.
STCD_X = BASEVIDWIDTH/4;
MINI_X = (3*BASEVIDWIDTH/4);
MINI_Y = (3*BASEVIDHEIGHT/4);
- WANT_X = (BASEVIDWIDTH/2)-8;
-
if (splitscreen > 2) // 4P-only
{
MINI_X = (BASEVIDWIDTH/2);
@@ -6372,12 +6408,14 @@ static void K_drawKartItem(void)
patch_t *localpatch = kp_nodraw;
patch_t *localbg = ((offset) ? kp_itembg[2] : kp_itembg[0]);
patch_t *localinv = ((offset) ? kp_invincibility[((leveltime % (6*3)) / 3) + 7] : kp_invincibility[(leveltime % (7*3)) / 3]);
- INT32 splitflags = K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTOLEFT);
+ INT32 fx = 0, fy = 0, fflags = 0; // final coords for hud and flags...
+ //INT32 splitflags = K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTOLEFT);
const INT32 numberdisplaymin = ((!offset && stplyr->kartstuff[k_itemtype] == KITEM_ORBINAUT) ? 5 : 2);
INT32 itembar = 0;
UINT8 localcolor = SKINCOLOR_NONE;
SINT8 colormode = TC_RAINBOW;
UINT8 *colmap = NULL;
+ boolean flipamount = false; // Used for 3P/4P splitscreen to flip item amount stuff
if (stplyr->kartstuff[k_itemroulette])
{
@@ -6589,26 +6627,53 @@ static void K_drawKartItem(void)
}
}
+ // pain and suffering defined below
+ if (splitscreen < 2) // don't change shit for THIS splitscreen.
+ {
+ fx = ITEM_X;
+ fy = ITEM_Y;
+ fflags = K_calcSplitFlags(V_SNAPTOTOP|V_SNAPTOLEFT);
+ }
+ else // now we're having a fun game.
+ {
+ if (stplyr == &players[displayplayer] || stplyr == &players[thirddisplayplayer]) // If we are P1 or P3...
+ {
+ fx = ITEM_X;
+ fy = ITEM_Y;
+ fflags = V_SNAPTOLEFT|((stplyr == &players[thirddisplayplayer]) ? V_SPLITSCREEN : V_SNAPTOTOP); // flip P3 to the bottom.
+ }
+ else // else, that means we're P2 or P4.
+ {
+ fx = ITEM2_X;
+ fy = ITEM2_Y;
+ fflags = V_SNAPTORIGHT|((stplyr == &players[fourthdisplayplayer]) ? V_SPLITSCREEN : V_SNAPTOTOP); // flip P4 to the bottom
+ flipamount = true;
+ }
+ }
+
if (localcolor != SKINCOLOR_NONE)
colmap = R_GetTranslationColormap(colormode, localcolor, 0);
- V_DrawScaledPatch(ITEM_X, ITEM_Y, V_HUDTRANS|splitflags, localbg);
+ V_DrawScaledPatch(fx, fy, V_HUDTRANS|fflags, localbg);
// Then, the numbers:
if (stplyr->kartstuff[k_itemamount] >= numberdisplaymin && !stplyr->kartstuff[k_itemroulette])
{
- V_DrawScaledPatch(ITEM_X, ITEM_Y, V_HUDTRANS|splitflags, kp_itemmulsticker[offset]);
- V_DrawFixedPatch(ITEM_X<kartstuff[k_itemamount]));
+ if (flipamount) // reminder that this is for 3/4p's right end of the screen.
+ V_DrawString(fx+2, fy+31, V_ALLOWLOWERCASE|V_HUDTRANS|fflags, va("x%d", stplyr->kartstuff[k_itemamount]));
+ else
+ V_DrawString(fx+24, fy+31, V_ALLOWLOWERCASE|V_HUDTRANS|fflags, va("x%d", stplyr->kartstuff[k_itemamount]));
else
{
- V_DrawScaledPatch(ITEM_X+28, ITEM_Y+41, V_HUDTRANS|splitflags, kp_itemx);
- V_DrawKartString(ITEM_X+38, ITEM_Y+36, V_HUDTRANS|splitflags, va("%d", stplyr->kartstuff[k_itemamount]));
+ V_DrawScaledPatch(fy+28, fy+41, V_HUDTRANS|fflags, kp_itemx);
+ V_DrawKartString(fx+38, fy+36, V_HUDTRANS|fflags, va("%d", stplyr->kartstuff[k_itemamount]));
}
}
else
- V_DrawFixedPatch(ITEM_X< 2)
{
- V_DrawFill(ITEM_X+x+length, ITEM_Y+y+1, 1, height, 12|splitflags); // the right one
+ V_DrawFill(fx+x+length, fy+y+1, 1, height, 12|fflags); // the right one
if (height == 2)
- V_DrawFill(ITEM_X+x+2, ITEM_Y+y+2, length-2, 1, 8|splitflags); // the dulled underside
- V_DrawFill(ITEM_X+x+2, ITEM_Y+y+1, length-2, 1, 120|splitflags); // the shine
+ V_DrawFill(fx+x+2, fy+y+2, length-2, 1, 8|fflags); // the dulled underside
+ V_DrawFill(fx+x+2, fy+y+1, length-2, 1, 120|fflags); // the shine
}
}
// Quick Eggman numbers
if (stplyr->kartstuff[k_eggmanexplode] > 1 /*&& stplyr->kartstuff[k_eggmanexplode] <= 3*TICRATE*/)
- V_DrawScaledPatch(ITEM_X+17, ITEM_Y+13-offset, V_HUDTRANS|splitflags, kp_eggnum[min(3, G_TicsToSeconds(stplyr->kartstuff[k_eggmanexplode]))]);
+ V_DrawScaledPatch(fx+17, fy+13-offset, V_HUDTRANS|fflags, kp_eggnum[min(3, G_TicsToSeconds(stplyr->kartstuff[k_eggmanexplode]))]);
+
}
void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UINT8 mode)
@@ -6795,23 +6861,72 @@ static void K_DrawKartPositionNum(INT32 num)
// POSI_Y = BASEVIDHEIGHT- 64; // 136
boolean win = (stplyr->exiting && num == 1);
- INT32 X = POSI_X;
+ //INT32 X = POSI_X;
INT32 W = SHORT(kp_positionnum[0][0]->width);
fixed_t scale = FRACUNIT;
patch_t *localpatch = kp_positionnum[0][0];
- INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTORIGHT);
+ //INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTORIGHT);
+ INT32 fx = 0, fy = 0, fflags = 0;
+ boolean flipdraw = false; // flip the order we draw it in for MORE splitscreen bs. fun.
+ boolean flipvdraw = false; // used only for 2p splitscreen so overtaking doesn't make 1P's position fly off the screen.
+ boolean overtake = false;
if (stplyr->kartstuff[k_positiondelay] || stplyr->exiting)
+ {
scale *= 2;
+ overtake = true; // this is used for splitscreen stuff in conjunction with flipdraw.
+ }
if (splitscreen)
scale /= 2;
W = FixedMul(W<>FRACBITS;
+ // pain and suffering defined below
+ if (!splitscreen)
+ {
+ fx = POSI_X;
+ fy = BASEVIDHEIGHT - 8;
+ fflags = V_SNAPTOBOTTOM|V_SNAPTORIGHT;
+ }
+ else if (splitscreen == 1) // for this splitscreen, we'll use case by case because it's a bit different.
+ {
+ fx = POSI_X;
+ if (stplyr == &players[displayplayer]) // for player 1: display this at the top right, above the minimap.
+ {
+ fy = 30;
+ fflags = V_SNAPTOTOP|V_SNAPTORIGHT;
+ if (overtake)
+ flipvdraw = true; // make sure overtaking doesn't explode us
+ }
+ else // if we're not p1, that means we're p2. display this at the bottom right, below the minimap.
+ {
+ fy = BASEVIDHEIGHT - 8;
+ fflags = V_SNAPTOBOTTOM|V_SNAPTORIGHT;
+ }
+ }
+ else
+ {
+ if (stplyr == &players[displayplayer] || stplyr == &players[thirddisplayplayer]) // If we are P1 or P3...
+ {
+ fx = POSI_X;
+ fy = POSI_Y;
+ fflags = V_SNAPTOLEFT|((stplyr == &players[thirddisplayplayer]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom.
+ flipdraw = true;
+ if (num && num >= 10)
+ fx += W; // this seems dumb, but we need to do this in order for positions above 10 going off screen.
+ }
+ else // else, that means we're P2 or P4.
+ {
+ fx = POSI2_X;
+ fy = POSI2_Y;
+ fflags = V_SNAPTORIGHT|((stplyr == &players[fourthdisplayplayer]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom
+ }
+ }
+
// Special case for 0
if (!num)
{
- V_DrawFixedPatch(X<width)*scale/2) : 0), (fy<height)*scale/2) : 0), scale, V_HUDTRANSHALF|fflags, localpatch, NULL);
+ // ^ if we overtake as p1 or p3 in splitscren, we shift it so that it doesn't go off screen.
+ // ^ if we overtake as p1 in 2p splits, shift vertically so that this doesn't happen either.
- X -= W;
+ fx -= W;
num /= 10;
}
}
@@ -6962,15 +7079,23 @@ static boolean K_drawKartPositionFaces(void)
colormap = R_GetTranslationColormap(players[rankplayer[i]].skin, players[rankplayer[i]].mo->color, GTC_CACHE);
V_DrawMappedPatch(FACE_X, Y, V_HUDTRANS|V_SNAPTOLEFT, facerankprefix[players[rankplayer[i]].skin], colormap);
- if (G_BattleGametype() && players[rankplayer[i]].kartstuff[k_bumper] > 0)
+
+#ifdef HAVE_BLUA
+ if (LUA_HudEnabled(hud_battlebumpers))
{
- V_DrawMappedPatch(bumperx-2, Y, V_HUDTRANS|V_SNAPTOLEFT, kp_tinybumper[0], colormap);
- for (j = 1; j < players[rankplayer[i]].kartstuff[k_bumper]; j++)
+#endif
+ if (G_BattleGametype() && players[rankplayer[i]].kartstuff[k_bumper] > 0)
{
- bumperx += 5;
- V_DrawMappedPatch(bumperx, Y, V_HUDTRANS|V_SNAPTOLEFT, kp_tinybumper[1], colormap);
+ V_DrawMappedPatch(bumperx-2, Y, V_HUDTRANS|V_SNAPTOLEFT, kp_tinybumper[0], colormap);
+ for (j = 1; j < players[rankplayer[i]].kartstuff[k_bumper]; j++)
+ {
+ bumperx += 5;
+ V_DrawMappedPatch(bumperx, Y, V_HUDTRANS|V_SNAPTOLEFT, kp_tinybumper[1], colormap);
+ }
}
- }
+#ifdef HAVE_BLUA
+ } // A new level of stupidity: checking if lua is enabled to close a bracket. :Fascinating:
+#endif
}
if (i == strank)
@@ -7096,15 +7221,57 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
static void K_drawKartLaps(void)
{
INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT);
+ INT32 fx = 0, fy = 0, fflags = 0; // stuff for 3p / 4p splitscreen.
+ boolean flipstring = false; // used for 3p or 4p
+ INT32 stringw = 0; // used with the above
if (splitscreen > 1)
{
- V_DrawScaledPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_splitlapflag);
- if (stplyr->exiting)
- V_DrawString(LAPS_X+13, LAPS_Y+1, V_HUDTRANS|splitflags, "FIN");
+ // pain and suffering defined below
+ if (splitscreen < 2) // don't change shit for THIS splitscreen.
+ {
+ fx = LAPS_X;
+ fy = LAPS_Y;
+ fflags = splitflags;
+ }
else
- V_DrawString(LAPS_X+13, LAPS_Y+1, V_HUDTRANS|splitflags, va("%d/%d", stplyr->laps+1, cv_numlaps.value));
+ {
+ if (stplyr == &players[displayplayer] || stplyr == &players[thirddisplayplayer]) // If we are P1 or P3...
+ {
+ fx = LAPS_X;
+ fy = LAPS_Y;
+ fflags = V_SNAPTOLEFT|((stplyr == &players[thirddisplayplayer]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom.
+ }
+ else // else, that means we're P2 or P4.
+ {
+ fx = LAPS2_X;
+ fy = LAPS2_Y;
+ fflags = V_SNAPTORIGHT|((stplyr == &players[fourthdisplayplayer]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom
+ flipstring = true; // make the string right aligned and other shit
+ }
+ }
+
+
+
+ if (stplyr->exiting) // draw stuff as god intended.
+ {
+ V_DrawScaledPatch(fx, fy, V_HUDTRANS|fflags, kp_splitlapflag);
+ V_DrawString(fx+13, fy+1, V_HUDTRANS|fflags, "FIN");
+ }
+ else // take flipstring into account here since we may have more laps than just 10
+ if (flipstring)
+ {
+ stringw = V_StringWidth(va("%d/%d", stplyr->laps+1, cv_numlaps.value), 0);
+
+ V_DrawScaledPatch(BASEVIDWIDTH-stringw-16, fy, V_HUDTRANS|fflags, kp_splitlapflag);
+ V_DrawRightAlignedString(BASEVIDWIDTH-3, fy+1, V_HUDTRANS|fflags, va("%d/%d", stplyr->laps+1, cv_numlaps.value));
+ }
+ else // draw stuff NORMALLY.
+ {
+ V_DrawScaledPatch(fx, fy, V_HUDTRANS|fflags, kp_splitlapflag);
+ V_DrawString(fx+13, fy+1, V_HUDTRANS|fflags, va("%d/%d", stplyr->laps+1, cv_numlaps.value));
+ }
}
else
{
@@ -7143,18 +7310,48 @@ static void K_drawKartBumpersOrKarma(void)
{
UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, stplyr->skincolor, 0);
INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT);
+ INT32 fx = 0, fy = 0, fflags = 0;
+ boolean flipstring = false; // same as laps, used for splitscreen
+ INT32 stringw = 0; // used with the above
if (splitscreen > 1)
{
+
+ // we will reuse lap coords here since it's essentially the same shit.
+
+ if (stplyr == &players[displayplayer] || stplyr == &players[thirddisplayplayer]) // If we are P1 or P3...
+ {
+ fx = LAPS_X;
+ fy = LAPS_Y;
+ fflags = V_SNAPTOLEFT|((stplyr == &players[thirddisplayplayer]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P3 to the bottom.
+ }
+ else // else, that means we're P2 or P4.
+ {
+ fx = LAPS2_X;
+ fy = LAPS2_Y;
+ fflags = V_SNAPTORIGHT|((stplyr == &players[fourthdisplayplayer]) ? V_SPLITSCREEN|V_SNAPTOBOTTOM : 0); // flip P4 to the bottom
+ flipstring = true;
+ }
+
if (stplyr->kartstuff[k_bumper] <= 0)
{
- V_DrawMappedPatch(LAPS_X, LAPS_Y-1, V_HUDTRANS|splitflags, kp_splitkarmabomb, colormap);
- V_DrawString(LAPS_X+13, LAPS_Y+1, V_HUDTRANS|splitflags, va("%d/2", stplyr->kartstuff[k_comebackpoints]));
+ V_DrawMappedPatch(fx, fy-1, V_HUDTRANS|fflags, kp_splitkarmabomb, colormap);
+ V_DrawString(fx+13, fy+1, V_HUDTRANS|fflags, va("%d/2", stplyr->kartstuff[k_comebackpoints]));
}
- else
+ else // the above doesn't need to account for weird stuff since the max amount of karma necessary is always 2 ^^^^
{
- V_DrawMappedPatch(LAPS_X, LAPS_Y-1, V_HUDTRANS|splitflags, kp_rankbumper, colormap);
- V_DrawString(LAPS_X+13, LAPS_Y+1, V_HUDTRANS|splitflags, va("%d/%d", stplyr->kartstuff[k_bumper], cv_kartbumpers.value));
+ if (flipstring) // for p2 and p4, assume we can have more than 10 bumpers. It's retarded but who knows.
+ {
+ stringw = V_StringWidth(va("%d/%d", stplyr->kartstuff[k_bumper], cv_kartbumpers.value), 0);
+
+ V_DrawMappedPatch(BASEVIDWIDTH-stringw-16, fy-1, V_HUDTRANS|fflags, kp_rankbumper, colormap);
+ V_DrawRightAlignedString(BASEVIDWIDTH-3, fy+1, V_HUDTRANS|fflags, va("%d/%d", stplyr->kartstuff[k_bumper], cv_kartbumpers.value));
+ }
+ else // draw bumpers normally.
+ {
+ V_DrawMappedPatch(fx, fy-1, V_HUDTRANS|fflags, kp_rankbumper, colormap);
+ V_DrawString(fx+13, fy+1, V_HUDTRANS|fflags, va("%d/%d", stplyr->kartstuff[k_bumper], cv_kartbumpers.value));
+ }
}
}
else
@@ -7207,13 +7404,10 @@ static void K_drawKartWanted(void)
{
UINT8 i, numwanted = 0;
UINT8 *colormap = NULL;
+ INT32 basex = 0, basey = 0;
- if (splitscreen) // Can't fit the poster on screen, sadly
- {
- if (K_IsPlayerWanted(stplyr) && leveltime % 10 > 3)
- V_DrawRightAlignedString(WANT_X, WANT_Y, K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_HUDTRANS|V_ORANGEMAP), "WANTED");
+ if (stplyr != &players[displayplayer])
return;
- }
for (i = 0; i < 4; i++)
{
@@ -7225,13 +7419,33 @@ static void K_drawKartWanted(void)
if (numwanted <= 0)
return;
+ // set X/Y coords depending on splitscreen.
+ if (splitscreen < 3) // 1P and 2P use the same code.
+ {
+ basex = WANT_X;
+ basey = WANT_Y;
+ if (splitscreen == 2)
+ {
+ basey += 16; // slight adjust for 3P
+ basex -= 6;
+ }
+ }
+ else if (splitscreen == 3) // 4P splitscreen...
+ {
+ basex = BASEVIDWIDTH/2 - (SHORT(kp_wantedsplit->width)/2); // center on screen
+ basey = BASEVIDHEIGHT - 55;
+ //basey2 = 4;
+ }
+
if (battlewanted[0] != -1)
colormap = R_GetTranslationColormap(0, players[battlewanted[0]].skincolor, GTC_CACHE);
- V_DrawFixedPatch(WANT_X< 1 ? kp_wantedsplit : kp_wanted), colormap);
+ /*if (basey2)
+ V_DrawFixedPatch(basex< 1 ? 13 : 8), y = basey+(splitscreen > 1 ? 16 : 21);
fixed_t scale = FRACUNIT/2;
player_t *p = &players[battlewanted[i]];
@@ -7251,7 +7465,9 @@ static void K_drawKartWanted(void)
if (players[battlewanted[i]].skincolor)
{
colormap = R_GetTranslationColormap(TC_RAINBOW, p->skincolor, GTC_CACHE);
- V_DrawFixedPatch(x<skin] : facerankprefix[p->skin]), colormap);
+ V_DrawFixedPatch(x<skin] : facerankprefix[p->skin]), colormap);
+ /*if (basey2) // again with 4p stuff
+ V_DrawFixedPatch(x<skin] : facerankprefix[p->skin]), colormap);*/
}
}
}
@@ -7306,7 +7522,7 @@ static void K_drawKartPlayerCheck(void)
}
}
-static void K_drawKartMinimapHead(fixed_t objx, fixed_t objy, INT32 hudx, INT32 hudy, INT32 flags, patch_t *icon, UINT8 *colormap, patch_t *AutomapPic)
+static void K_drawKartMinimapIcon(fixed_t objx, fixed_t objy, INT32 hudx, INT32 hudy, INT32 flags, patch_t *icon, UINT8 *colormap, patch_t *AutomapPic)
{
// amnum xpos & ypos are the icon's speed around the HUD.
// The number being divided by is for how fast it moves.
@@ -7386,10 +7602,11 @@ static void K_drawKartMinimap(void)
patch_t *AutomapPic;
INT32 i = 0;
INT32 x, y;
- INT32 minimaptrans, splitflags = (splitscreen ? 0 : V_SNAPTORIGHT);
- boolean dop1later = false;
+ INT32 minimaptrans, splitflags = (splitscreen == 3 ? 0 : V_SNAPTORIGHT); // flags should only be 0 when it's centered (4p split)
UINT8 skin = 0;
UINT8 *colormap = NULL;
+ SINT8 localplayers[4];
+ SINT8 numlocalplayers = 0;
// Draw the HUD only when playing in a level.
// hu_stuff needs this, unlike st_stuff.
@@ -7411,7 +7628,7 @@ static void K_drawKartMinimap(void)
if (timeinmap > 105)
{
- minimaptrans = (splitscreen ? 10 : cv_kartminimap.value);
+ minimaptrans = cv_kartminimap.value;
if (timeinmap <= 113)
minimaptrans = ((((INT32)timeinmap) - 105)*minimaptrans)/(113-105);
if (!minimaptrans)
@@ -7428,7 +7645,7 @@ static void K_drawKartMinimap(void)
else
V_DrawScaledPatch(x, y, splitflags, AutomapPic);
- if (!splitscreen)
+ if (!(splitscreen == 2))
{
splitflags &= ~minimaptrans;
splitflags |= V_HUDTRANSHALF;
@@ -7450,11 +7667,15 @@ static void K_drawKartMinimap(void)
splitflags &= ~V_HUDTRANSHALF;
splitflags |= V_HUDTRANS;
colormap = R_GetTranslationColormap(TC_RAINBOW, (UINT8)(1 + (leveltime % (MAXSKINCOLORS-1))), GTC_CACHE);
- K_drawKartMinimapHead(battleovertime.x, battleovertime.y, x, y, splitflags, kp_itemminimap, colormap, AutomapPic);
+ K_drawKartMinimapIcon(battleovertime.x, battleovertime.y, x, y, splitflags, kp_itemminimap, colormap, AutomapPic);
splitflags = prevsplitflags;
}
}
+ // initialize
+ for (i = 0; i < 4; i++)
+ localplayers[i] = -1;
+
// Player's tiny icons on the Automap. (drawn opposite direction so player 1 is drawn last in splitscreen)
if (ghosts)
{
@@ -7474,12 +7695,15 @@ static void K_drawKartMinimap(void)
}
else
colormap = NULL;
- K_drawKartMinimapHead(g->mo->x, g->mo->y, x, y, splitflags, facemmapprefix[skin], colormap, AutomapPic);
+ K_drawKartMinimapIcon(g->mo->x, g->mo->y, x, y, splitflags, facemmapprefix[skin], colormap, AutomapPic);
g = g->next;
}
+
if (!stplyr->mo || stplyr->spectator) // do we need the latter..?
return;
- dop1later = true;
+
+ localplayers[numlocalplayers] = stplyr-players;
+ numlocalplayers++;
}
else
{
@@ -7490,26 +7714,33 @@ static void K_drawKartMinimap(void)
if (!players[i].mo || players[i].spectator)
continue;
- if (!splitscreen && i == displayplayer)
+ if (i != displayplayer || splitscreen)
{
- dop1later = true; // Do displayplayer later
- continue;
+ if (G_BattleGametype() && players[i].kartstuff[k_bumper] <= 0)
+ continue;
+
+ if (players[i].kartstuff[k_hyudorotimer] > 0)
+ {
+ if (!((players[i].kartstuff[k_hyudorotimer] < 1*TICRATE/2
+ || players[i].kartstuff[k_hyudorotimer] > hyudorotime-(1*TICRATE/2))
+ && !(leveltime & 1)))
+ continue;
+ }
}
- if (G_BattleGametype() && players[i].kartstuff[k_bumper] <= 0)
- continue;
- if (players[i].kartstuff[k_hyudorotimer] > 0)
+ if (i == displayplayer || i == secondarydisplayplayer || i == thirddisplayplayer || i == fourthdisplayplayer)
{
- if (!((players[i].kartstuff[k_hyudorotimer] < 1*TICRATE/2
- || players[i].kartstuff[k_hyudorotimer] > hyudorotime-(1*TICRATE/2))
- && !(leveltime & 1)))
- continue;
+ // Draw display players on top of everything else
+ localplayers[numlocalplayers] = i;
+ numlocalplayers++;
+ continue;
}
if (players[i].mo->skin)
skin = ((skin_t*)players[i].mo->skin)-skins;
else
skin = 0;
+
if (players[i].mo->color)
{
if (players[i].mo->colorized)
@@ -7519,29 +7750,41 @@ static void K_drawKartMinimap(void)
}
else
colormap = NULL;
- K_drawKartMinimapHead(players[i].mo->x, players[i].mo->y, x, y, splitflags, facemmapprefix[skin], colormap, AutomapPic);
+
+ K_drawKartMinimapIcon(players[i].mo->x, players[i].mo->y, x, y, splitflags, facemmapprefix[skin], colormap, AutomapPic);
+ if (K_IsPlayerWanted(&players[i]))
+ K_drawKartMinimapIcon(players[i].mo->x, players[i].mo->y, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic);
}
}
- if (!dop1later)
- return; // Don't need this
-
+ // draw our local players here, opaque.
splitflags &= ~V_HUDTRANSHALF;
splitflags |= V_HUDTRANS;
- if (stplyr->mo->skin)
- skin = ((skin_t*)stplyr->mo->skin)-skins;
- else
- skin = 0;
- if (stplyr->mo->color)
+
+ for (i = 0; i < numlocalplayers; i++)
{
- if (stplyr->mo->colorized)
- colormap = R_GetTranslationColormap(TC_RAINBOW, stplyr->mo->color, GTC_CACHE);
+ if (i == -1)
+ continue; // this doesn't interest us
+
+ if (players[localplayers[i]].mo->skin)
+ skin = ((skin_t*)players[localplayers[i]].mo->skin)-skins;
else
- colormap = R_GetTranslationColormap(skin, stplyr->mo->color, GTC_CACHE);
+ skin = 0;
+
+ if (players[localplayers[i]].mo->color)
+ {
+ if (players[localplayers[i]].mo->colorized)
+ colormap = R_GetTranslationColormap(TC_RAINBOW, players[localplayers[i]].mo->color, GTC_CACHE);
+ else
+ colormap = R_GetTranslationColormap(skin, players[localplayers[i]].mo->color, GTC_CACHE);
+ }
+ else
+ colormap = NULL;
+
+ K_drawKartMinimapIcon(players[localplayers[i]].mo->x, players[localplayers[i]].mo->y, x, y, splitflags, facemmapprefix[skin], colormap, AutomapPic);
+ if (K_IsPlayerWanted(&players[localplayers[i]]))
+ K_drawKartMinimapIcon(players[localplayers[i]].mo->x, players[localplayers[i]].mo->y, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic);
}
- else
- colormap = NULL;
- K_drawKartMinimapHead(stplyr->mo->x, stplyr->mo->y, x, y, splitflags, facemmapprefix[skin], colormap, AutomapPic);
}
static void K_drawKartStartCountdown(void)
@@ -7647,7 +7890,7 @@ static void K_drawBattleFullscreen(void)
{
if (stplyr == &players[displayplayer])
V_DrawFadeScreen(0xFF00, 16);
- if (stplyr->exiting < 6*TICRATE)
+ if (stplyr->exiting < 6*TICRATE && !stplyr->spectator)
{
if (stplyr->kartstuff[k_position] == 1)
V_DrawFixedPatch(x< 2 && stplyr == &players[fourthdisplayplayer]) && !camera4.chase))
K_drawKartFirstPerson();
- if (splitscreen == 2) // Player 4 in 3P is the minimap :p
+/* if (splitscreen == 2) // Player 4 in 3P is the minimap :p
{
#ifdef HAVE_BLUA
if (LUA_HudEnabled(hud_minimap))
#endif
K_drawKartMinimap();
- }
+ }*/
// Draw full screen stuff that turns off the rest of the HUD
if (mapreset && stplyr == &players[displayplayer])
@@ -8203,7 +8449,16 @@ void K_drawKartHUD(void)
if (cv_kartcheck.value && !splitscreen && !players[displayplayer].exiting)
K_drawKartPlayerCheck();
- if (splitscreen == 0 && cv_kartminimap.value && !titledemo)
+ // Draw WANTED status
+ if (G_BattleGametype())
+ {
+#ifdef HAVE_BLUA
+ if (LUA_HudEnabled(hud_wanted))
+#endif
+ K_drawKartWanted();
+ }
+
+ if (cv_kartminimap.value && !titledemo)
{
#ifdef HAVE_BLUA
if (LUA_HudEnabled(hud_minimap))
@@ -8218,15 +8473,6 @@ void K_drawKartHUD(void)
#endif
K_drawKartItem();
- // Draw WANTED status
- if (G_BattleGametype())
- {
-#ifdef HAVE_BLUA
- if (LUA_HudEnabled(hud_wanted))
-#endif
- K_drawKartWanted();
- }
-
// If not splitscreen, draw...
if (!splitscreen && !titledemo)
{
@@ -8332,7 +8578,12 @@ void K_drawKartHUD(void)
// Draw FREE PLAY.
if (isfreeplay && !stplyr->spectator && timeinmap > 113)
- K_drawKartFreePlay(leveltime);
+ {
+#ifdef HAVE_BLUA
+ if (LUA_HudEnabled(hud_freeplay))
+#endif
+ K_drawKartFreePlay(leveltime);
+ }
if (cv_kartdebugdistribution.value)
K_drawDistributionDebugger();
@@ -8344,7 +8595,7 @@ void K_drawKartHUD(void)
{
UINT8 p;
for (p = 0; p < MAXPLAYERS; p++)
- V_DrawString(8, 64+(8*p), V_YELLOWMAP, va("%d - %d", p, playernode[p]));
+ V_DrawString(8, 64+(8*p), V_YELLOWMAP, va("%d - %d (%dl)", p, playernode[p], players[p].cmd.latency));
}
}
diff --git a/src/k_kart.h b/src/k_kart.h
index fed490db9..17652b9de 100644
--- a/src/k_kart.h
+++ b/src/k_kart.h
@@ -9,6 +9,8 @@
#include "doomdef.h"
#include "d_player.h" // Need for player_t
+#define KART_FULLTURN 800
+
UINT8 colortranslations[MAXSKINCOLORS][16];
extern const char *KartColor_Names[MAXSKINCOLORS];
extern const UINT8 KartColor_Opposite[MAXSKINCOLORS*2];
@@ -63,6 +65,13 @@ void K_CalculateBattleWanted(void);
void K_CheckBumpers(void);
void K_CheckSpectateStatus(void);
+// sound stuff for lua
+void K_PlayAttackTaunt(mobj_t *source);
+void K_PlayBoostTaunt(mobj_t *source);
+void K_PlayOvertakeSound(mobj_t *source);
+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);
diff --git a/src/lua_baselib.c b/src/lua_baselib.c
index 6f542fae4..78f972f87 100644
--- a/src/lua_baselib.c
+++ b/src/lua_baselib.c
@@ -31,9 +31,10 @@
#include "lua_script.h"
#include "lua_libs.h"
#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) {
luaL_checktype(L, narg, LUA_TBOOLEAN);
@@ -677,16 +678,6 @@ static int lib_pGetPlayerSpinHeight(lua_State *L)
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)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
@@ -1839,6 +1830,21 @@ static int lib_sStopSoundByID(lua_State *L)
return 0;
}
+static int lib_sShowMusicCredit(lua_State *L)
+{
+ player_t *player = NULL;
+ //HUDSAFE
+ if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
+ {
+ player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
+ if (!player)
+ return LUA_ErrInvalid(L, "player_t");
+ }
+ if (!player || P_IsLocalPlayer(player))
+ S_ShowMusicCredit();
+ return 0;
+}
+
static int lib_sChangeMusic(lua_State *L)
{
#ifdef MUSICSLOT_COMPATIBILITY
@@ -2126,6 +2132,72 @@ static int lib_gTicsToMilliseconds(lua_State *L)
// 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)
{
const char *name = luaL_checkstring(L, 1);
@@ -2561,7 +2633,6 @@ static luaL_Reg lib[] = {
// p_user
{"P_GetPlayerHeight",lib_pGetPlayerHeight},
{"P_GetPlayerSpinHeight",lib_pGetPlayerSpinHeight},
- {"P_GetPlayerControlDirection",lib_pGetPlayerControlDirection},
{"P_AddPlayerScore",lib_pAddPlayerScore},
{"P_PlayerInPain",lib_pPlayerInPain},
{"P_DoPlayerPain",lib_pDoPlayerPain},
@@ -2666,6 +2737,7 @@ static luaL_Reg lib[] = {
{"S_StartSoundAtVolume",lib_sStartSoundAtVolume},
{"S_StopSound",lib_sStopSound},
{"S_StopSoundByID",lib_sStopSoundByID},
+ {"S_ShowMusicCredit",lib_sShowMusicCredit},
{"S_ChangeMusic",lib_sChangeMusic},
{"S_SpeedMusic",lib_sSpeedMusic},
{"S_StopMusic",lib_sStopMusic},
@@ -2692,6 +2764,12 @@ static luaL_Reg lib[] = {
{"G_TicsToMilliseconds",lib_gTicsToMilliseconds},
// 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_IsPlayerLosing",lib_kIsPlayerLosing},
{"K_IsPlayerWanted",lib_kIsPlayerWanted},
diff --git a/src/lua_hook.h b/src/lua_hook.h
index 2c9cd346b..126e7e405 100644
--- a/src/lua_hook.h
+++ b/src/lua_hook.h
@@ -50,11 +50,14 @@ enum hook {
hook_PlayerSpin, //SRB2KART
hook_PlayerExplode, //SRB2KART
hook_PlayerSquish, //SRB2KART
+ hook_PlayerCmd, //SRB2KART
hook_MAX // last hook
};
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_MapLoad(void); // Hook for map load
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_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_PlayerCmd(player_t *player, ticcmd_t *cmd); // Allows to write to player cmd before the game does anything with them.
+
#endif
diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index 13ad03d35..5a95877e3 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -61,6 +61,7 @@ const char *const hookNames[hook_MAX+1] = {
"PlayerSpin",
"PlayerExplode",
"PlayerSquish",
+ "PlayerCmd",
NULL
};
@@ -877,6 +878,47 @@ boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd)
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
boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
{
diff --git a/src/lua_hud.h b/src/lua_hud.h
index 3216ab15f..4fbbbace4 100644
--- a/src/lua_hud.h
+++ b/src/lua_hud.h
@@ -20,8 +20,10 @@ enum hud {
hud_item,
hud_position,
hud_minirankings, // Rankings to the left
+ hud_battlebumpers, // mini rankings battle bumpers.
hud_wanted,
hud_speedometer,
+ hud_freeplay,
hud_rankings, // Tab rankings
hud_MAX
diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c
index 353aebb21..ca952a009 100644
--- a/src/lua_hudlib.c
+++ b/src/lua_hudlib.c
@@ -45,8 +45,10 @@ static const char *const hud_disable_options[] = {
"item",
"position",
"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",
"speedometer",
+ "freeplay",
"rankings",
NULL};
@@ -482,6 +484,20 @@ static int libd_drawString(lua_State *L)
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)
{
const char *str = luaL_checkstring(L, 1);
@@ -593,6 +609,7 @@ static luaL_Reg lib_draw[] = {
{"drawFill", libd_drawFill},
{"fadeScreen", libd_fadeScreen},
{"drawString", libd_drawString},
+ {"drawKartString", libd_drawKartString},
{"stringWidth", libd_stringWidth},
{"getColormap", libd_getColormap},
{"width", libd_width},
diff --git a/src/lua_infolib.c b/src/lua_infolib.c
index 9b22170f9..d8659a7e0 100644
--- a/src/lua_infolib.c
+++ b/src/lua_infolib.c
@@ -22,6 +22,7 @@
#include "lua_script.h"
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
+#include "lua_hook.h" // cmd errors
boolean LUA_CallAction(const char *action, mobj_t *actor);
state_t *astate;
@@ -169,6 +170,8 @@ static int lib_setState(lua_State *L)
if (hud_running)
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
memset(state,0,sizeof(state_t));
@@ -378,6 +381,8 @@ static int state_set(lua_State *L)
if (hud_running)
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")) {
value = luaL_checknumber(L, 3);
@@ -466,6 +471,8 @@ static int lib_setMobjInfo(lua_State *L)
if (hud_running)
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
memset(info,0,sizeof(mobjinfo_t));
@@ -633,6 +640,8 @@ static int mobjinfo_set(lua_State *L)
if (hud_running)
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 >= mobjinfo);
@@ -755,6 +764,8 @@ static int lib_setSfxInfo(lua_State *L)
if (hud_running)
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);
while (lua_next(L, 1)) {
@@ -830,6 +841,8 @@ static int sfxinfo_set(lua_State *L)
if (hud_running)
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);
diff --git a/src/lua_maplib.c b/src/lua_maplib.c
index 7599b2612..0bb9a99d6 100644
--- a/src/lua_maplib.c
+++ b/src/lua_maplib.c
@@ -24,6 +24,7 @@
#include "lua_script.h"
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
+#include "lua_hook.h" // cmd errors
#include "dehacked.h"
#include "fastcmp.h"
@@ -484,6 +485,8 @@ static int sector_set(lua_State *L)
if (hud_running)
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)
{
@@ -1174,6 +1177,8 @@ static int ffloor_set(lua_State *L)
if (hud_running)
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)
{
@@ -1303,6 +1308,8 @@ static int slope_set(lua_State *L)
if (hud_running)
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
{
diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c
index 34aba0a38..b56538d0f 100644
--- a/src/lua_mobjlib.c
+++ b/src/lua_mobjlib.c
@@ -21,6 +21,7 @@
#include "lua_script.h"
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
+#include "lua_hook.h" // cmd errors
static const char *const array_opt[] ={"iterate",NULL};
@@ -391,6 +392,9 @@ static int mobj_set(lua_State *L)
if (hud_running)
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)
{
case mobj_valid:
@@ -756,6 +760,8 @@ static int mapthing_set(lua_State *L)
if (hud_running)
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"))
mt->x = (INT16)luaL_checkinteger(L, 3);
diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c
index 067124ba9..5f136fc15 100644
--- a/src/lua_playerlib.c
+++ b/src/lua_playerlib.c
@@ -21,6 +21,7 @@
#include "lua_script.h"
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
+#include "lua_hook.h" // hook_cmd_running
static int lib_iteratePlayers(lua_State *L)
{
@@ -356,6 +357,9 @@ static int player_set(lua_State *L)
if (hud_running)
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")) {
mobj_t *newmo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
plr->mo->player = NULL; // remove player pointer from old mobj
@@ -667,6 +671,8 @@ static int power_set(lua_State *L)
return luaL_error(L, LUA_QL("powertype_t") " cannot be %u", p);
if (hud_running)
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;
return 0;
}
@@ -699,6 +705,8 @@ static int kartstuff_set(lua_State *L)
return luaL_error(L, LUA_QL("kartstufftype_t") " cannot be %u", ks);
if (hud_running)
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;
return 0;
}
diff --git a/src/m_cheat.c b/src/m_cheat.c
index 9c53f9011..38d8cc7a9 100644
--- a/src/m_cheat.c
+++ b/src/m_cheat.c
@@ -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);
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_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;
- }
+ }*/
if (player->mo->z > player->mo->ceilingz - player->mo->height)
player->mo->z = player->mo->ceilingz - player->mo->height;
diff --git a/src/m_menu.c b/src/m_menu.c
index d8b59676f..f0831a172 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -80,10 +80,6 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
//int vsnprintf(char *str, size_t n, const char *fmt, va_list ap);
#endif
-#if defined (__GNUC__) && (__GNUC__ >= 4)
-#define FIXUPO0
-#endif
-
#define SKULLXOFF -32
#define LINEHEIGHT 16
#define STRINGHEIGHT 8
@@ -915,41 +911,7 @@ static menuitem_t SP_LevelStatsMenu[] =
// 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!
#define M_ChoosePlayer NULL
-menuitem_t PlayerMenu[32] =
-{
- {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}
-};
+menuitem_t PlayerMenu[MAXSKINS];
// -----------------------------------
// Multiplayer and all of its submenus
@@ -2588,7 +2550,7 @@ boolean M_Responder(event_t *ev)
return false;
else if (ch == gamecontrol[gc_systemmenu][0] || ch == gamecontrol[gc_systemmenu][1]) // allow remappable ESC key
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;
// F-Keys
@@ -2666,7 +2628,7 @@ boolean M_Responder(event_t *ev)
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;
routine = currentMenu->menuitems[itemOn].itemaction;
@@ -3192,6 +3154,8 @@ void M_Ticker(void)
//
void M_Init(void)
{
+ UINT8 i;
+
COM_AddCommand("manual", Command_Manual_f);
CV_RegisterVar(&cv_nextmap);
@@ -3203,7 +3167,6 @@ void M_Init(void)
return;
// Menu hacks
- CV_RegisterVar(&cv_splitplayers);
CV_RegisterVar(&cv_dummymenuplayer);
CV_RegisterVar(&cv_dummyteam);
CV_RegisterVar(&cv_dummyspectate);
@@ -3239,6 +3202,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[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
// Permanently hide some options based on render mode
if (rendermode == render_soft)
@@ -7736,7 +7708,7 @@ static void M_StartServerMenu(INT32 choice)
// CONNECT VIA IP
// ==============
-static char setupm_ip[16];
+static char setupm_ip[28];
#endif
static UINT8 setupm_pselect = 1;
@@ -7769,12 +7741,12 @@ Update the maxplayers label...
V_DrawFill(x+5, y+4+5, /*16*8 + 6,*/ BASEVIDWIDTH - 2*(x+5), 8+6, 239);
// 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
if (itemOn == 8
&& 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
// character bar, ripped off the color bar :V
@@ -7988,10 +7960,11 @@ static void M_HandleConnectIP(INT32 choice)
default:
l = strlen(setupm_ip);
- if (l >= 16-1)
+ if (l >= 28-1)
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
setupm_ip[l] = (char)choice;
@@ -8005,7 +7978,6 @@ static void M_HandleConnectIP(INT32 choice)
setupm_ip[l] = (char)choice;
setupm_ip[l+1] = 0;
}
-
break;
}
diff --git a/src/m_menu.h b/src/m_menu.h
index 9509004b4..864f4cacc 100644
--- a/src/m_menu.h
+++ b/src/m_menu.h
@@ -150,7 +150,7 @@ typedef struct menuitem_s
UINT8 alphaKey;
} menuitem_t;
-extern menuitem_t PlayerMenu[32];
+extern menuitem_t PlayerMenu[MAXSKINS];
typedef struct menu_s
{
diff --git a/src/m_misc.c b/src/m_misc.c
index 0586f6e52..53b63e75f 100644
--- a/src/m_misc.c
+++ b/src/m_misc.c
@@ -93,7 +93,9 @@ typedef off_t off64_t;
#ifdef PNG_WRITE_SUPPORTED
#define USE_PNG // Only actually use PNG if write is supported.
#if defined (PNG_WRITE_APNG_SUPPORTED) //|| !defined(PNG_STATIC)
- #define USE_APNG
+ #if (PNG_LIBPNG_VER_MAJOR) == 1 && (PNG_LIBPNG_VER_MINOR <= 4) // Supposedly, the current APNG code can't work on newer versions as is
+ #define USE_APNG
+ #endif
#endif
// See hardware/hw_draw.c for a similar check to this one.
#endif
diff --git a/src/p_enemy.c b/src/p_enemy.c
index ea230b6e7..9de7c70e6 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -8364,13 +8364,13 @@ void A_SPBChase(mobj_t *actor)
if (!playeringame[i] || players[i].spectator || players[i].exiting)
continue; // not in-game
- if (!players[i].mo)
+ /*if (!players[i].mo)
continue; // no mobj
if (players[i].mo->health <= 0)
continue; // dead
- /*if (players[i].kartstuff[k_respawn])
+ if (players[i].kartstuff[k_respawn])
continue;*/ // respawning
if (players[i].kartstuff[k_position] < bestrank)
@@ -8386,18 +8386,35 @@ void A_SPBChase(mobj_t *actor)
{
fixed_t defspeed = wspeed;
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
- 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...
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
- 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)<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
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];
}
- // 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);
wspeed = FixedMul(defspeed, FRACUNIT + FixedDiv(dist-range, range));
@@ -8419,10 +8432,18 @@ void A_SPBChase(mobj_t *actor)
wspeed = defspeed;
if (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);
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
angle_t input = hang - actor->angle;
@@ -8431,7 +8452,7 @@ void A_SPBChase(mobj_t *actor)
input = InvAngle(input);
// Slow down when turning; it looks better and makes U-turns not unfair
- xyspeed = FixedMul(wspeed, max(0, (((180<cvmem, max(0, (((180<cvmem, max(0, (((180<movedir += input;
}
- actor->momx = 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->momx = cx + FixedMul(FixedMul(xyspeed, FINECOSINE(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));
// 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
- 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];
- if (actor->extravalue2-- <= 0)
+ if (actor->extravalue2-- <= 0 && 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 = 0;
+ actor->cvmem = wspeed;
}
}
else
@@ -8513,22 +8537,12 @@ void A_SPBChase(mobj_t *actor)
{
actor->lastlook = -1; // Just make sure this is reset
- // No one there?
- if (player == NULL || !player->mo)
+ if (!player || !player->mo || player->mo->health <= 0 || player->kartstuff[k_respawn])
{
-#if 0
- // 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
+ // No one there? Completely STOP.
actor->momx = actor->momy = actor->momz = 0;
-#endif
- spbplace = -1;
+ if (!player)
+ spbplace = -1;
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.
actor->extravalue1 = 1; // TARGET ACQUIRED
actor->extravalue2 = 7*TICRATE;
+ actor->cvmem = wspeed;
}
}
diff --git a/src/p_inter.c b/src/p_inter.c
index 3c0e3f927..3bf302b39 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -579,30 +579,31 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (special->health <= 0 || toucher->health <= 0)
return;
- if (!player->mo || player->spectator)
+ if (player->spectator)
return;
- if (special->tracer && toucher == special->tracer)
+ if (special->tracer && !P_MobjWasRemoved(special->tracer) && toucher == special->tracer)
{
mobj_t *spbexplode;
- S_StopSound(special); // Don't continue playing the gurgle or the siren
-
- if (!player->kartstuff[k_invincibilitytimer] && !player->kartstuff[k_growshrinktimer])
+ if (player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0)
{
+ //player->powers[pw_flashing] = 0;
K_DropHnextList(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->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);
}
else
- K_SpinPlayer(player, NULL, 0, special, false);
+ K_SpinPlayer(player, special->target, 0, special, false);
return;
/*case MT_EERIEFOG:
special->frame &= ~FF_TRANS80;
@@ -2952,7 +2953,8 @@ 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)
+/*
+static inline void P_SuperDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage) // SRB2kart - unused.
{
fixed_t fallbackspeed;
angle_t ang;
@@ -2998,11 +3000,10 @@ static inline void P_SuperDamage(player_t *player, mobj_t *inflictor, mobj_t *so
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
- */
+ // 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);
@@ -3010,6 +3011,7 @@ static inline void P_SuperDamage(player_t *player, mobj_t *inflictor, mobj_t *so
if (player->timeshit != UINT8_MAX)
++player->timeshit;
}
+*/
void P_RemoveShield(player_t *player)
{
diff --git a/src/p_local.h b/src/p_local.h
index 16804430a..0d93c0c84 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -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_GetPlayerSpinHeight(player_t *player);
-INT32 P_GetPlayerControlDirection(player_t *player);
void P_AddPlayerScore(player_t *player, UINT32 amount);
void P_ResetCamera(player_t *player, camera_t *thiscam);
boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam);
diff --git a/src/p_mobj.c b/src/p_mobj.c
index ec20ad0df..5d7bc7b1d 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -7650,10 +7650,10 @@ void P_MobjThinker(mobj_t *mobj)
break;
case MT_SSMINE:
case MT_SPBEXPLOSION:
- if (mobj->health > -100)
+ if (mobj->extravalue2 != -100)
{
P_SetMobjState(mobj, mobj->info->deathstate);
- mobj->health = -100;
+ mobj->extravalue2 = -100;
}
else
{
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 1d57280f9..e6af28d2f 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -282,6 +282,12 @@ static void P_NetArchivePlayers(void)
WRITEUINT8(save_p, players[i].accelstart);
WRITEUINT8(save_p, players[i].acceleration);
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]);
+ }
}
}
@@ -456,6 +462,12 @@ static void P_NetUnArchivePlayers(void)
players[i].accelstart = READUINT8(save_p);
players[i].acceleration = READUINT8(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);
+ }
}
}
diff --git a/src/p_setup.c b/src/p_setup.c
index d5b6159e8..7b5e9f28e 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -2265,8 +2265,10 @@ static void P_LevelInitStuff(void)
leveltime = 0;
- localaiming = 0;
- localaiming2 = 0;
+ localaiming = localaiming2 = localaiming3 = localaiming4 = 0;
+
+ // map object scale
+ mapobjectscale = mapheaderinfo[gamemap-1]->mobj_scale;
// special stage tokens, emeralds, and ring total
tokenbits = 0;
@@ -2302,6 +2304,10 @@ static void P_LevelInitStuff(void)
// earthquake camera
memset(&quake,0,sizeof(struct quake));
+ // song credit init
+ memset(&cursongcredit,0,sizeof(struct cursongcredit));
+ cursongcredit.trans = NUMTRANSMAPS;
+
for (i = 0; i < MAXPLAYERS; i++)
{
#if 0
@@ -2865,10 +2871,6 @@ boolean P_SetupLevel(boolean skipprecip)
// As oddly named as this is, this handles music only.
// We should be fine starting it here.
S_Start();
- // SRB2 Kart - Yes this is weird, but we don't want the music to start until after the countdown is finished
- // but we do still need the mapmusname to be changed
- if (leveltime < (starttime + (TICRATE/2)))
- S_ChangeMusicInternal((encoremode ? "estart" : "kstart"), false); //S_StopMusic();
levelfadecol = (encoremode && !ranspecialwipe ? 122 : 120);
@@ -3435,6 +3437,11 @@ boolean P_AddWadFile(const char *wadfilename)
//
R_AddSkins(wadnum); // faB: wadfile index in wadfiles[]
+ //
+ // edit music defs
+ //
+ S_LoadMusicDefs(wadnum);
+
//
// search for maps
//
diff --git a/src/p_spec.c b/src/p_spec.c
index 35d26c6cb..ca4967ce3 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -2450,6 +2450,8 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
mapmusflags |= MUSIC_RELOADRESET;
S_ChangeMusic(mapmusname, mapmusflags, !(line->flags & ML_EFFECT4));
+ if (!(line->flags & ML_EFFECT3))
+ S_ShowMusicCredit();
// Except, you can use the ML_BLOCKMONSTERS flag to change this behavior.
// if (mapmusflags & MUSIC_RELOADRESET) then it will reset the music in G_PlayerReborn.
@@ -5717,8 +5719,6 @@ void P_SpawnSpecials(INT32 fromnetsave)
else
curWeather = PRECIP_NONE;
- mapobjectscale = mapheaderinfo[gamemap-1]->mobj_scale;
-
P_InitTagLists(); // Create xref tables for tags
P_SearchForDisableLinedefs(); // Disable linedefs are now allowed to disable *any* line
diff --git a/src/p_user.c b/src/p_user.c
index ab6c61dc1..d7423d803 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -4509,7 +4509,7 @@ boolean P_AnalogMove(player_t *player)
// 1 = pressing in the direction of movement
// 2 = pressing in the opposite direction of movement
//
-INT32 P_GetPlayerControlDirection(player_t *player)
+/*INT32 P_GetPlayerControlDirection(player_t *player)
{
ticcmd_t *cmd = &player->cmd;
angle_t controllerdirection, controlplayerdirection;
@@ -4584,7 +4584,7 @@ INT32 P_GetPlayerControlDirection(player_t *player)
}
// Control scheme for 2d levels.
-/*static void P_2dMovement(player_t *player)
+static void P_2dMovement(player_t *player)
{
ticcmd_t *cmd;
INT32 topspeed, acceleration, thrustfactor;
@@ -4794,24 +4794,11 @@ static void P_3dMovement(player_t *player)
cmd->forwardmove = cmd->sidemove = 0;
if (player->kartstuff[k_sneakertimer])
cmd->forwardmove = 50;
- if (player->pflags & PF_GLIDING)
- {
- if (!player->skidtime)
- player->pflags &= ~PF_GLIDING;
- else if (player->exiting || mapreset)
- {
- player->pflags &= ~PF_GLIDING;
- P_SetPlayerMobjState(player->mo, S_KART_WALK1); // SRB2kart - was S_PLAY_RUN1
- player->skidtime = 0;
- }
- }
- if (player->pflags & PF_SPINNING && !(player->exiting || mapreset))
- {
- player->pflags &= ~PF_SPINNING;
- P_SetPlayerMobjState(player->mo, S_KART_STND1); // SRB2kart - was S_PLAY_STND
- }
}
+ if (!(player->pflags & PF_FORCESTRAFE) && !player->kartstuff[k_pogospring])
+ cmd->sidemove = 0;
+
if (analogmove)
{
movepushangle = (cmd->angleturn<<16 /* not FRACBITS */);
@@ -4819,9 +4806,7 @@ static void P_3dMovement(player_t *player)
else
{
if (player->kartstuff[k_drift] != 0)
- {
movepushangle = player->mo->angle-(ANGLE_45/5)*player->kartstuff[k_drift];
- }
else
movepushangle = player->mo->angle;
}
@@ -5039,10 +5024,10 @@ static void P_SpectatorMovement(player_t *player)
// Quake-style flying spectators :D
player->mo->momz += FixedMul(cmd->forwardmove*mapobjectscale, AIMINGTOSLOPE(player->aiming));
}
- 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*mapobjectscale);
- }
+ }*/
}
//
@@ -6633,8 +6618,53 @@ static void P_MovePlayer(player_t *player)
P_2dMovement(player);
else*/
{
- if (!player->climbing && (!P_AnalogMove(player)))
- player->mo->angle = (cmd->angleturn<<16 /* not FRACBITS */);
+ INT16 angle_diff, max_left_turn, max_right_turn;
+ boolean add_delta = true;
+
+ // Kart: store the current turn range for later use
+ if (((player->mo && player->speed > 0) // Moving
+ || (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn
+ || (player->kartstuff[k_respawn]) // Respawning
+ || (player->spectator || objectplacing)) // Not a physical player
+ && !(player->kartstuff[k_spinouttimer] && player->kartstuff[k_sneakertimer])) // Spinning and boosting cancels out turning
+ {
+ player->lturn_max[leveltime%MAXPREDICTTICS] = K_GetKartTurnValue(player, KART_FULLTURN)+1;
+ player->rturn_max[leveltime%MAXPREDICTTICS] = K_GetKartTurnValue(player, -KART_FULLTURN)-1;
+ } else {
+ player->lturn_max[leveltime%MAXPREDICTTICS] = player->rturn_max[leveltime%MAXPREDICTTICS] = 0;
+ }
+
+ if (leveltime >= starttime)
+ {
+ // KART: Don't directly apply angleturn! It may have been either A) forged by a malicious client, or B) not be a smooth turn due to a player dropping frames.
+ // Instead, turn the player only up to the amount they're supposed to turn accounting for latency. Allow exactly 1 extra turn unit to try to keep old replays synced.
+ angle_diff = cmd->angleturn - (player->mo->angle>>16);
+ max_left_turn = player->lturn_max[(leveltime + MAXPREDICTTICS - cmd->latency) % MAXPREDICTTICS];
+ max_right_turn = player->rturn_max[(leveltime + MAXPREDICTTICS - cmd->latency) % MAXPREDICTTICS];
+
+ //CONS_Printf("----------------\nangle diff: %d - turning options: %d to %d - ", angle_diff, max_left_turn, max_right_turn);
+
+ if (angle_diff > max_left_turn)
+ angle_diff = max_left_turn;
+ else if (angle_diff < max_right_turn)
+ angle_diff = max_right_turn;
+ else
+ {
+ // Try to keep normal turning as accurate to 1.0.1 as possible to reduce replay desyncs.
+ player->mo->angle = cmd->angleturn<<16;
+ add_delta = false;
+ }
+ //CONS_Printf("applied turn: %d\n", angle_diff);
+
+ if (add_delta) {
+ player->mo->angle += angle_diff<<16;
+ player->mo->angle &= ~0xFFFF; // Try to keep the turning somewhat similar to how it was before?
+ //CONS_Printf("leftover turn (%s): %5d or %4d%%\n",
+ // player_names[player-players],
+ // (INT16) (cmd->angleturn - (player->mo->angle>>16)),
+ // (INT16) (cmd->angleturn - (player->mo->angle>>16)) * 100 / (angle_diff ?: 1));
+ }
+ }
ticruned++;
if ((cmd->angleturn & TICCMD_RECEIVED) == 0)
@@ -7032,6 +7062,7 @@ static void P_MovePlayer(player_t *player)
//ANALOG CONTROL//
//////////////////
+#if 0
// This really looks like it should be moved to P_3dMovement. -Red
if (P_AnalogMove(player)
&& (cmd->forwardmove != 0 || cmd->sidemove != 0) && !player->climbing && !twodlevel && !(player->mo->flags2 & MF2_TWOD))
@@ -7088,6 +7119,7 @@ static void P_MovePlayer(player_t *player)
else if (player == &players[fourthdisplayplayer])
localangle4 = player->mo->angle;
}
+#endif
///////////////////////////
//BOMB SHIELD ACTIVATION,//
diff --git a/src/r_data.c b/src/r_data.c
index 9fc5aaeae..1a74f7336 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -924,7 +924,8 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *texindex)
Z_Free((void *)texturesText);
}
-static inline lumpnum_t R_CheckNumForNameList(const char *name, lumplist_t *list, size_t listsize)
+/*
+static inline lumpnum_t R_CheckNumForNameList(const char *name, lumplist_t *list, size_t listsize) // SRB2kart - unused.
{
size_t i;
UINT16 lump;
@@ -939,6 +940,7 @@ static inline lumpnum_t R_CheckNumForNameList(const char *name, lumplist_t *list
}
return LUMPERROR;
}
+*/
/*static lumplist_t *colormaplumps = NULL; ///\todo free leak
static size_t numcolormaplumps = 0;
diff --git a/src/r_segs.c b/src/r_segs.c
index 59abea3ad..62c0523d0 100644
--- a/src/r_segs.c
+++ b/src/r_segs.c
@@ -3093,8 +3093,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
else
markceiling = false;
- // Don't render the ceiling again when rendering polyobjects
- if (curline->polyseg)
+ // Don't mark ceiling flat lines for polys unless this line has an upper texture, otherwise we get flat leakage pulling downward
+ // (If it DOES have an upper texture and we do this, the ceiling won't render at all)
+ if (curline->polyseg && !curline->sidedef->toptexture)
markceiling = false;
}
@@ -3106,8 +3107,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
else
markfloor = false;
- // Don't render the floor again when rendering polyobjects
- if (curline->polyseg)
+ // Don't mark floor flat lines for polys unless this line has a lower texture, otherwise we get flat leakage pulling upward
+ // (If it DOES have a lower texture and we do this, the floor won't render at all)
+ if (curline->polyseg && !curline->sidedef->bottomtexture)
markfloor = false;
}
diff --git a/src/r_things.c b/src/r_things.c
index 1825d2d94..d6234d4b3 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -2500,7 +2500,7 @@ void R_DrawMasked(void)
// ==========================================================================
INT32 numskins = 0;
-skin_t skins[MAXSKINS+1];
+skin_t skins[MAXSKINS];
// FIXTHIS: don't work because it must be inistilised before the config load
//#define SKINVALUES
#ifdef SKINVALUES
@@ -2771,7 +2771,7 @@ void R_AddSkins(UINT16 wadnum)
// advance by default
lastlump = lump + 1;
- if (numskins > MAXSKINS)
+ if (numskins >= MAXSKINS)
{
CONS_Debug(DBG_RENDER, "ignored skin (%d skins maximum)\n", MAXSKINS);
continue; // so we know how many skins couldn't be added
diff --git a/src/r_things.h b/src/r_things.h
index a8635034a..53784415f 100644
--- a/src/r_things.h
+++ b/src/r_things.h
@@ -192,7 +192,7 @@ typedef struct drawnode_s
} drawnode_t;
extern INT32 numskins;
-extern skin_t skins[MAXSKINS + 1];
+extern skin_t skins[MAXSKINS];
void SetPlayerSkin(INT32 playernum,const char *skinname);
void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002
diff --git a/src/s_sound.c b/src/s_sound.c
index 34163fd3e..856aa0459 100644
--- a/src/s_sound.c
+++ b/src/s_sound.c
@@ -101,7 +101,7 @@ consvar_t cv_numChannels = {"snd_channels", "64", CV_SAVE|CV_CALL, CV_Unsigned,
#endif
consvar_t surround = {"surround", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_resetmusic = {"resetmusic", "No", CV_SAVE|CV_NOSHOWHELP, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
+//consvar_t cv_resetmusic = {"resetmusic", "No", CV_SAVE|CV_NOSHOWHELP, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
// Sound system toggles, saved into the config
consvar_t cv_gamedigimusic = {"digimusic", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, GameDigiMusic_OnChange, 0, NULL, NULL, 0, 0, NULL};
@@ -263,7 +263,7 @@ void S_RegisterSoundStuff(void)
#endif
CV_RegisterVar(&surround);
CV_RegisterVar(&cv_samplerate);
- CV_RegisterVar(&cv_resetmusic);
+ //CV_RegisterVar(&cv_resetmusic);
CV_RegisterVar(&cv_gamesounds);
CV_RegisterVar(&cv_gamedigimusic);
#ifndef NO_MIDI
@@ -1541,6 +1541,210 @@ static void *music_data;
static UINT16 music_flags;
static boolean music_looping;
+/// ------------------------
+/// Music Definitions
+/// ------------------------
+
+musicdef_t *musicdefstart = NULL; // First music definition
+struct cursongcredit cursongcredit; // Currently displayed song credit info
+
+//
+// search for music definition in wad
+//
+static UINT16 W_CheckForMusicDefInPwad(UINT16 wadid)
+{
+ UINT16 i;
+ lumpinfo_t *lump_p;
+
+ lump_p = wadfiles[wadid]->lumpinfo;
+ for (i = 0; i < wadfiles[wadid]->numlumps; i++, lump_p++)
+ if (memcmp(lump_p->name, "MUSICDEF", 8) == 0)
+ return i;
+
+ return INT16_MAX; // not found
+}
+
+void S_LoadMusicDefs(UINT16 wadnum)
+{
+ UINT16 lump;
+ char *buf;
+ char *buf2;
+ char *stoken;
+ char *value;
+ size_t size;
+ musicdef_t *def, *prev;
+ UINT16 line = 1; // for better error msgs
+
+ lump = W_CheckForMusicDefInPwad(wadnum);
+ if (lump == INT16_MAX)
+ return;
+
+ buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE);
+ size = W_LumpLengthPwad(wadnum, lump);
+
+ // for strtok
+ buf2 = malloc(size+1);
+ if (!buf2)
+ I_Error("S_LoadMusicDefs: No more free memory\n");
+ M_Memcpy(buf2,buf,size);
+ buf2[size] = '\0';
+
+ def = prev = NULL;
+
+ stoken = strtok (buf2, "\r\n ");
+ // Find music def
+ while (stoken)
+ {
+ /*if ((stoken[0] == '/' && stoken[1] == '/')
+ || (stoken[0] == '#')) // skip comments
+ {
+ stoken = strtok(NULL, "\r\n"); // skip end of line
+ if (def)
+ stoken = strtok(NULL, "\r\n= ");
+ else
+ stoken = strtok(NULL, "\r\n ");
+ line++;
+ }
+ else*/ if (!stricmp(stoken, "lump"))
+ {
+ value = strtok(NULL, "\r\n ");
+
+ if (!value)
+ {
+ CONS_Alert(CONS_WARNING, "MUSICDEF: Lump '%s' is missing name. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line);
+ stoken = strtok(NULL, "\r\n"); // skip end of line
+ goto skip_lump;
+ }
+
+ // No existing musicdefs
+ if (!musicdefstart)
+ {
+ musicdefstart = Z_Calloc(sizeof (musicdef_t), PU_STATIC, NULL);
+ STRBUFCPY(musicdefstart->name, value);
+ strlwr(musicdefstart->name);
+ def = musicdefstart;
+ //CONS_Printf("S_LoadMusicDefs: Initialized musicdef w/ song '%s'\n", def->name);
+ }
+ else
+ {
+ def = musicdefstart;
+
+ // Search if this is a replacement
+ //CONS_Printf("S_LoadMusicDefs: Searching for song replacement...\n");
+ while (def)
+ {
+ if (!stricmp(def->name, value))
+ {
+ //CONS_Printf("S_LoadMusicDefs: Found song replacement '%s'\n", def->name);
+ break;
+ }
+
+ prev = def;
+ def = def->next;
+ }
+
+ // Nothing found, add to the end.
+ if (!def)
+ {
+ def = Z_Calloc(sizeof (musicdef_t), PU_STATIC, NULL);
+ STRBUFCPY(def->name, value);
+ strlwr(def->name);
+ if (prev != NULL)
+ prev->next = def;
+ //CONS_Printf("S_LoadMusicDefs: Added song '%s'\n", def->name);
+ }
+ }
+
+skip_lump:
+ stoken = strtok(NULL, "\r\n ");
+ line++;
+ }
+ else
+ {
+ value = strtok(NULL, "\r\n= ");
+
+ if (!value)
+ {
+ CONS_Alert(CONS_WARNING, "MUSICDEF: Field '%s' is missing value. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line);
+ stoken = strtok(NULL, "\r\n"); // skip end of line
+ goto skip_field;
+ }
+
+ if (!def)
+ {
+ CONS_Alert(CONS_ERROR, "MUSICDEF: No music definition before field '%s'. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line);
+ free(buf2);
+ return;
+ }
+
+ if (!stricmp(stoken, "usage")) {
+#if 0 // Ignore for now
+ STRBUFCPY(def->usage, value);
+ for (value = def->usage; *value; value++)
+ if (*value == '_') *value = ' '; // turn _ into spaces.
+ //CONS_Printf("S_LoadMusicDefs: Set usage to '%s'\n", def->usage);
+#endif
+ } else if (!stricmp(stoken, "source")) {
+ STRBUFCPY(def->source, value);
+ for (value = def->source; *value; value++)
+ if (*value == '_') *value = ' '; // turn _ into spaces.
+ //CONS_Printf("S_LoadMusicDefs: Set source to '%s'\n", def->source);
+ } else {
+ CONS_Alert(CONS_WARNING, "MUSICDEF: Invalid field '%s'. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line);
+ }
+
+skip_field:
+ stoken = strtok(NULL, "\r\n= ");
+ line++;
+ }
+ }
+
+ free(buf2);
+ return;
+}
+
+//
+// S_InitMusicDefs
+//
+// Simply load music defs in all wads.
+//
+void S_InitMusicDefs(void)
+{
+ UINT16 i;
+ for (i = 0; i < numwadfiles; i++)
+ S_LoadMusicDefs(i);
+}
+
+//
+// S_ShowMusicCredit
+//
+// Display current song's credit on screen
+//
+void S_ShowMusicCredit(void)
+{
+ musicdef_t *def = musicdefstart;
+
+ if (!cv_songcredits.value)
+ return;
+
+ if (!def) // No definitions
+ return;
+
+ while (def)
+ {
+ if (!stricmp(def->name, music_name))
+ {
+ cursongcredit.def = def;
+ cursongcredit.anim = 5*TICRATE;
+ cursongcredit.x = 0;
+ cursongcredit.trans = NUMTRANSMAPS;
+ return;
+ }
+ else
+ def = def->next;
+ }
+}
+
/// ------------------------
/// Music Status
/// ------------------------
@@ -1839,9 +2043,13 @@ void S_Start(void)
mapmusflags = (mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK);
}
- if (cv_resetmusic.value)
+ //if (cv_resetmusic.value) // Starting ambience should always be restarted
S_StopMusic();
- S_ChangeMusic(mapmusname, mapmusflags, true);
+
+ if (leveltime < (starttime + (TICRATE/2))) // SRB2Kart
+ S_ChangeMusic((encoremode ? "estart" : "kstart"), 0, false);
+ else
+ S_ChangeMusic(mapmusname, mapmusflags, true);
}
static void Command_Tunes_f(void)
@@ -1974,7 +2182,7 @@ void GameDigiMusic_OnChange(void)
if (Playing())
P_RestoreMusic(&players[consoleplayer]);
else
- S_ChangeMusicInternal("lclear", false);
+ S_ChangeMusicInternal("titles", looptitle);
}
else
{
@@ -2016,7 +2224,7 @@ void GameMIDIMusic_OnChange(void)
if (Playing())
P_RestoreMusic(&players[consoleplayer]);
else
- S_ChangeMusicInternal("lclear", false);
+ S_ChangeMusicInternal("titles", looptitle);
}
else
{
diff --git a/src/s_sound.h b/src/s_sound.h
index c83188cf5..1ad519c20 100644
--- a/src/s_sound.h
+++ b/src/s_sound.h
@@ -27,7 +27,7 @@ extern consvar_t stereoreverse;
extern consvar_t cv_soundvolume, cv_digmusicvolume;//, cv_midimusicvolume;
extern consvar_t cv_numChannels;
extern consvar_t surround;
-extern consvar_t cv_resetmusic;
+//extern consvar_t cv_resetmusic;
extern consvar_t cv_gamedigimusic;
#ifndef NO_MIDI
extern consvar_t cv_gamemidimusic;
@@ -128,6 +128,29 @@ boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi);
// Set Speed of Music
boolean S_SpeedMusic(float speed);
+// Music credits
+typedef struct musicdef_s
+{
+ char name[7];
+ //char usage[256];
+ char source[256];
+ struct musicdef_s *next;
+} musicdef_t;
+
+extern struct cursongcredit
+{
+ musicdef_t *def;
+ UINT16 anim;
+ INT32 x;
+ UINT8 trans;
+} cursongcredit;
+
+extern musicdef_t *musicdefstart;
+
+void S_LoadMusicDefs(UINT16 wadnum);
+void S_InitMusicDefs(void);
+void S_ShowMusicCredit(void);
+
//
// Music Routines
//
diff --git a/src/sdl/CMakeLists.txt b/src/sdl/CMakeLists.txt
index f7b7c7ba4..ec5d63ac7 100644
--- a/src/sdl/CMakeLists.txt
+++ b/src/sdl/CMakeLists.txt
@@ -150,7 +150,7 @@ if(${SDL2_FOUND})
${ZLIB_LIBRARIES}
${OPENGL_LIBRARIES}
)
- set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME "Sonic Robo Blast 2")
+ set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}")
else()
target_link_libraries(SRB2SDL2 PRIVATE
${SDL2_LIBRARIES}
@@ -334,10 +334,19 @@ if(${SDL2_FOUND})
# Mac bundle fixup
+ # HACK: THIS IS IMPORTANT! See the escaped \${CMAKE_INSTALL_PREFIX}? This
+ # makes it so that var is evaluated LATER during cpack, not right now!
+ # This fixes the quirk where the bundled libraries don't land in the final package
+ # https://cmake.org/pipermail/cmake/2011-March/043532.html
+ #
+ # HOWEVER: ${CPACK_PACKAGE_DESCRIPTION_SUMMARY} is NOT escaped, because that var
+ # is only available to us at this step. Read the link: ${CMAKE_INSTALL_PREFIX} at
+ # this current step points to the CMAKE build folder, NOT the folder that CPACK uses.
+ # Therefore, it makes sense to escape that var, but not the other.
if(${CMAKE_SYSTEM} MATCHES Darwin)
install(CODE "
include(BundleUtilities)
- fixup_bundle(\"${CMAKE_INSTALL_PREFIX}/Sonic Robo Blast 2.app\"
+ fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/${CPACK_PACKAGE_DESCRIPTION_SUMMARY}.app\"
\"\"
/Library/Frameworks
)"
diff --git a/src/sdl/Srb2SDL.ico b/src/sdl/Srb2SDL.ico
index 6e667b61c..4e3f81336 100644
Binary files a/src/sdl/Srb2SDL.ico and b/src/sdl/Srb2SDL.ico differ
diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c
index f85176183..2154a070b 100644
--- a/src/sdl/i_system.c
+++ b/src/sdl/i_system.c
@@ -2166,6 +2166,12 @@ void I_InitJoystick(void)
if (M_CheckParm("-nojoy"))
return;
+ if (M_CheckParm("-noxinput"))
+ SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE);
+
+ if (M_CheckParm("-nohidapi"))
+ SDL_SetHintWithPriority("SDL_JOYSTICK_HIDAPI", "0", SDL_HINT_OVERRIDE);
+
if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0)
{
CONS_Printf("I_InitJoystick()...\n");
diff --git a/src/sdl/macosx/Srb2mac.icns b/src/sdl/macosx/Srb2mac.icns
index 96cb8a36d..890c268f7 100644
Binary files a/src/sdl/macosx/Srb2mac.icns and b/src/sdl/macosx/Srb2mac.icns differ
diff --git a/src/sdl12/Srb2SDL.ico b/src/sdl12/Srb2SDL.ico
index 6e667b61c..4e3f81336 100644
Binary files a/src/sdl12/Srb2SDL.ico and b/src/sdl12/Srb2SDL.ico differ
diff --git a/src/sdl12/macosx/Srb2mac.icns b/src/sdl12/macosx/Srb2mac.icns
index 96cb8a36d..890c268f7 100644
Binary files a/src/sdl12/macosx/Srb2mac.icns and b/src/sdl12/macosx/Srb2mac.icns differ
diff --git a/src/st_stuff.c b/src/st_stuff.c
index 10d624985..8ebd21321 100644
--- a/src/st_stuff.c
+++ b/src/st_stuff.c
@@ -425,11 +425,14 @@ void ST_changeDemoView(void)
boolean st_overlay;
+/*
static INT32 SCZ(INT32 z)
{
return FixedInt(FixedMul(z<health-1, 0);
@@ -687,6 +696,7 @@ static inline void ST_drawRings(void)
ST_DrawNumFromHudWS(HUD_RINGSNUM, ringnum);
}
+*/
/*
static void ST_drawLives(void) // SRB2kart - unused.
@@ -1487,7 +1497,8 @@ static void ST_drawMatchHUD(void) // SRB2kart - unused.
}
*/
-static inline void ST_drawRaceHUD(void)
+/*
+static inline void ST_drawRaceHUD(void) // SRB2kart - unused.
{
if (leveltime > starttime-(3*TICRATE) && leveltime <= starttime-(2*TICRATE))
V_DrawScaledPatch(SCX((BASEVIDWIDTH - SHORT(race3->width))/2), (INT32)(SCY(BASEVIDHEIGHT/2)), V_NOSCALESTART, race3);
@@ -1506,6 +1517,7 @@ static inline void ST_drawRaceHUD(void)
V_DrawString(hudinfo[HUD_LAP].x, STRINGY(hudinfo[HUD_LAP].y), 0, va("Lap: %u/%d", stplyr->laps+1, cv_numlaps.value));
}
}
+*/
/*
static void ST_drawTagHUD(void) // SRB2kart - unused.
@@ -1618,7 +1630,8 @@ static void ST_drawCTFHUD(void) // SRB2kart - unused.
*/
// Draws "Red Team", "Blue Team", or "Spectator" for team gametypes.
-static inline void ST_drawTeamName(void)
+/*
+static inline void ST_drawTeamName(void) // SRB2kart - unused.
{
if (stplyr->ctfteam == 1)
V_DrawString(256, splitscreen ? STRINGY(184) : STRINGY(192), V_HUDTRANSHALF, "RED TEAM");
@@ -1627,6 +1640,7 @@ static inline void ST_drawTeamName(void)
else
V_DrawString(244, splitscreen ? STRINGY(184) : STRINGY(192), V_HUDTRANSHALF, "SPECTATOR");
}
+*/
/*
static void ST_drawSpecialStageHUD(void) // SRB2kart - unused.
diff --git a/src/v_video.c b/src/v_video.c
index eeb2593ae..dd95efe3d 100644
--- a/src/v_video.c
+++ b/src/v_video.c
@@ -2267,6 +2267,7 @@ INT32 V_ThinStringWidth(const char *string, INT32 option)
{
INT32 c, w = 0;
INT32 spacewidth = 2, charwidth = 0;
+ boolean lowercase = (option & V_ALLOWLOWERCASE);
size_t i;
switch (option & V_SPACINGMASK)
@@ -2290,14 +2291,21 @@ INT32 V_ThinStringWidth(const char *string, INT32 option)
if ((UINT8)c >= 0x80 && (UINT8)c <= 0x8F) //color parsing! -Inuyasha 2.16.09
continue;
- c = toupper(c) - HU_FONTSTART;
+ if (!lowercase || !tny_font[c-HU_FONTSTART])
+ c = toupper(c);
+ c -= HU_FONTSTART;
+
if (c < 0 || c >= HU_FONTSIZE || !tny_font[c])
w += spacewidth;
else
+ {
w += (charwidth ? charwidth
- : (option & V_6WIDTHSPACE ? max(1, SHORT(tny_font[c]->width)-1) : SHORT(tny_font[c]->width))); // Reuse this flag for the alternate bunched-up spacing
+ : ((option & V_6WIDTHSPACE && i < strlen(string)-1) ? max(1, SHORT(tny_font[c]->width)-1) // Reuse this flag for the alternate bunched-up spacing
+ : SHORT(tny_font[c]->width)));
+ }
}
+
return w;
}
diff --git a/src/w_wad.c b/src/w_wad.c
index 69b4cb2e7..63bee97de 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -1738,6 +1738,7 @@ int W_VerifyNMUSlumps(const char *filename)
{"MKFNT", 5}, // Kart font changes
{"K_", 2}, // Kart graphic changes
+ {"MUSICDEF", 8}, // Kart song definitions
{NULL, 0},
};
diff --git a/src/win32/Srb2win.ico b/src/win32/Srb2win.ico
index 6e667b61c..4e3f81336 100644
Binary files a/src/win32/Srb2win.ico and b/src/win32/Srb2win.ico differ
diff --git a/src/win32ce/Srb2win.ico b/src/win32ce/Srb2win.ico
index 6e667b61c..4e3f81336 100644
Binary files a/src/win32ce/Srb2win.ico and b/src/win32ce/Srb2win.ico differ
diff --git a/src/y_inter.c b/src/y_inter.c
index 379d5cd39..021519e3b 100644
--- a/src/y_inter.c
+++ b/src/y_inter.c
@@ -1037,7 +1037,7 @@ void Y_VoteDrawer(void)
V_DrawFixedPatch((BASEVIDWIDTH-60)<