Merge branch 'master' into improve-backtrace

This commit is contained in:
Alam Ed Arias 2023-10-28 20:00:31 -04:00
commit 11fc21e7ec
205 changed files with 12891 additions and 15587 deletions

View file

@ -1,9 +1,9 @@
version: 2
jobs:
build:
working_directory: /root/SRB2
working_directory: /home/circleci/SRB2
docker:
- image: debian:stretch
- image: cimg/base:current
environment:
CC: ccache gcc -m32
PKG_CONFIG_LIBDIR: /usr/lib/i386-linux-gnu/pkgconfig
@ -11,7 +11,7 @@ jobs:
LIBGME_LDFLAGS: -lgme
CCACHE_COMPRESS: true
WFLAGS: -Wno-unsuffixed-float-constants
GCC49: true
GCC81: true
#- image: ubuntu:trusty
# environment:
# CC: ccache gcc -m32
@ -25,39 +25,42 @@ jobs:
steps:
- run:
name: Add i386 arch
command: dpkg --add-architecture i386
command: sudo dpkg --add-architecture i386
- run:
name: Add STJr PPA
command: |
apt-get -qq update
apt-get -qq -y install dirmngr
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 0B1702D71499D9C25F986507F240F4449D3B0EC6
echo "deb http://ppa.launchpad.net/stjr/srb2/ubuntu trusty main" >> /etc/apt/sources.list
sudo apt-get -qq update
sudo apt-get -qq -y install dirmngr
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 0B1702D71499D9C25F986507F240F4449D3B0EC6
echo "deb http://ppa.launchpad.net/stjr/srb2/ubuntu trusty main" | sudo tee -a /etc/apt/sources.list
- run:
name: Make APT cache folder
command: mkdir -p /root/.cache/apt/archives/partial
command: mkdir -p /home/circleci/.cache/apt/archives/partial
- run:
name: Make APT cache usage by _apt
command: chown -Rv _apt:root /root/.cache/apt/archives/partial
command: sudo chown -Rv _apt:root /home/circleci/.cache/apt/archives/partial
- run:
name: Update APT listing
command: apt-get -qq update
command: sudo apt-get -qq update
- run:
name: Support S3 upload
command: apt-get -qq -y install ca-certificates
command: sudo apt-get -qq -y install ca-certificates
- restore_cache:
keys:
- v1-SRB2-APT
- run:
name: Install SDK
command: apt-get -o Dir::Cache="/root/.cache/apt" -qq -y --no-install-recommends install git build-essential nasm libpng-dev:i386 libsdl2-mixer-dev:i386 libgme-dev:i386 libcurl4-openssl-dev:i386 libopenmpt-dev:i386 gettext ccache wget gcc-multilib upx openssh-client
name: Uninstall amd64 SDK
command: sudo apt-get -o Dir::Cache="/home/circleci/.cache/apt" -qq -y --no-install-recommends remove libcurl4-openssl-dev:amd64
- run:
name: Install i386 SDK
command: sudo apt-get -o Dir::Cache="/home/circleci/.cache/apt" -qq -y --no-install-recommends install git build-essential libpng-dev:i386 libsdl2-mixer-dev:i386 libgme-dev:i386 libcurl4-openssl-dev:i386 libopenmpt-dev:i386 gettext ccache wget gcc-multilib upx openssh-client
- run:
name: make md5sum
command: find /root/.cache/apt/archives -type f -print0 | sort -z | xargs -r0 md5sum > /root/.cache/apt_archives.md5
command: sudo find /home/circleci/.cache/apt/archives -type f -print0 | sort -z | sudo xargs -r0 md5sum > /home/circleci/.cache/apt_archives.md5
- save_cache:
key: v1-SRB2-APT-{{ checksum "/root/.cache/apt_archives.md5" }}
key: v1-SRB2-APT-{{ checksum "/home/circleci/.cache/apt_archives.md5" }}
paths:
- /root/.cache/apt
- /home/circleci/.cache/apt
- checkout
- run:
name: Compile without network support
@ -78,9 +81,9 @@ jobs:
name: Compile
command: make -C src LINUX=1 ERRORMODE=1 -k -j4
- store_artifacts:
path: /root/SRB2/bin/
path: /home/circleci/SRB2/bin/
destination: bin
- save_cache:
key: v1-SRB2-{{ .Branch }}-{{ checksum "make/linux/SDL.deps" }}
paths:
- /root/.ccache
- /home/circleci/.ccache

4
.gitattributes vendored
View file

@ -1,15 +1,17 @@
#Source code
/Makefile text=auto
/src/*.c text=auto
/src/*.h text=auto
/src/*.s text=auto
/src/*.m text=auto
/src/*.xpm text=auto
/src/Makefile text=auto
/tools/Makefile text=auto
/src/Make*.cfg text=auto
/src/CMakeLists.txt text=auto
*.mk -whitespace text=auto
# Windows EOL
*.cs -crlf -whitespace
*.mk -crlf -whitespace
*.bat -crlf -whitespace
*.dev -crlf -whitespace
*.dsp -crlf -whitespace

3
.gitignore vendored
View file

@ -22,4 +22,5 @@ Win32_LIB_ASM_Release
/make
/bin
/build
/build.*
/build/*
/CMakeUserPresets.json

434
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,434 @@
variables:
GIT_STRATEGY: clone
GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/$CI_PROJECT_PATH
default:
image: debian:stable-slim
cache:
- key: ccache-$CI_PROJECT_PATH_SLUG-$CI_JOB_NAME_SLUG
fallback_keys:
- cache-$CI_PROJECT_PATH_SLUG-$CI_DEFAULT_BRANCH
- cache-$CI_PROJECT_PATH_SLUG-default
paths:
- ccache
- ccache_statslog
- key: apt-$CI_JOB_IMAGE
paths:
- apt-cache
unprotect: true
before_script:
- - |
# debconf
echo -e "\e[0Ksection_start:`date +%s`:debconf[collapsed=true]\r\e[0KSetup debconf's environment"
- export DEBIAN_FRONTEND="noninteractive"
- export DEBIAN_PRIORITY="low"
- export DEBCONF_NONINTERACTIVE_SEEN="true"
- |
# debconf
echo -e "\e[0Ksection_end:`date +%s`:debconf\r\e[0K"
- - |
# dpkg_aa
echo -e "\e[0Ksection_start:`date +%s`:dpkg_aa[collapsed=true]\r\e[0KAdding architectures to dpkg"
- dpkg --add-architecture i386
- dpkg --add-architecture amd64
- dpkg --add-architecture arm64
- |
# dpkg_aa
echo -e "\e[0Ksection_end:`date +%s`:dpkg_aa\r\e[0K"
- - |
# apt_conf
echo -e "\e[0Ksection_start:`date +%s`:apt_conf[collapsed=true]\r\e[0KSetting up APT conf"
- export APT_CACHE_DIR=`pwd`/apt-cache
- mkdir --parents --verbose $APT_CACHE_DIR/partial/
- touch /etc/apt/apt.conf.d/99build
- |
# apt.conf
echo Adding options to apt.conf':'
- |
# APT::Install-Recommends
echo APT::Install-Recommends "false"\; | tee --append /etc/apt/apt.conf.d/99build
- |
# quit
echo quiet "1"\; | tee --append /etc/apt/apt.conf.d/99build
- |
# APT::Get::Assume-Yes
echo APT::Get::Assume-Yes "true"\; | tee --append /etc/apt/apt.conf.d/99build
- |
# Dir::Cache::Archives
echo Dir::Cache::Archives "$APT_CACHE_DIR"\; | tee --append /etc/apt/apt.conf.d/99build
- |
# apt_conf
echo -e "\e[0Ksection_end:`date +%s`:apt_conf\r\e[0K"
- - |
# apt_update
echo -e "\e[0Ksection_start:`date +%s`:apt_update[collapsed=true]\r\e[0KUpdating APT listing"
- apt-get update
- |
# apt_update
echo -e "\e[0Ksection_end:`date +%s`:apt_update\r\e[0K"
- - |
# apt_pre
echo -e "\e[0Ksection_start:`date +%s`:apt_pre[collapsed=true]\r\e[0KInstalling pre packages"
- apt-get install apt-utils
- |
# apt_pre
echo -e "\e[0Ksection_end:`date +%s`:apt_pre\r\e[0K"
- - |
# apt_upgrade
echo -e "\e[0Ksection_start:`date +%s`:apt_upgrade[collapsed=true]\r\e[0KUpdating existing packages"
- apt-get upgrade
- |
# apt_update
echo -e "\e[0Ksection_end:`date +%s`:apt_upgrade\r\e[0K"
- - |
# apt_common
echo -e "\e[0Ksection_start:`date +%s`:apt_common[collapsed=true]\r\e[0KInstalling common packages"
- apt-get install make git ccache nasm
- |
# apt_common
echo -e "\e[0Ksection_end:`date +%s`:apt_common\r\e[0K"
- - |
# ccache_config
echo -e "\e[0Ksection_start:`date +%s`:ccache_config[collapsed=true]\r\e[0KSetting up ccache config"
- mkdir --parents --verbose ~/.ccache/
- touch ~/.ccache/ccache.conf
- |
# cache.conf
echo Adding ccache configution option
- |
# base_dir
echo base_dir = $PWD | tee --append ~/.ccache/ccache.conf
- |
# cache_dir
echo cache_dir = $PWD/ccache | tee --append ~/.ccache/ccache.conf
- |
# compiler_check
echo compiler_check = content | tee --append ~/.ccache/ccache.conf
- |
# stats_log
echo stats_log = $PWD/ccache_statslog | tee --append ~/.ccache/ccache.conf
- |
# max_size
echo max_size = 50M | tee --append ~/.ccache/ccache.conf
- |
# ccache_config
echo -e "\e[0Ksection_end:`date +%s`:ccache_config\r\e[0K"
- - |
# cache_reset
echo -e "\e[0Ksection_start:`date +%s`:ccache_reset[collapsed=true]\r\e[0KResetting ccache statistics"
- ccache --zero-stats
- ccache --show-stats
- |
# ccache_reset
echo -e "\e[0Ksection_end:`date +%s`:ccache_reset\r\e[0K"
artifacts:
paths:
- "bin/"
- "src/comptime.h"
name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-$CI_JOB_NAME_SLUG"
after_script:
- - |
# apt_clean
echo -e "\e[0Ksection_start:`date +%s`:apt_clean[collapsed=true]\r\e[0KCleaning of unneeded APT packages"
- apt-get autoclean
- |
# apt_clean
echo -e "\e[0Ksection_end:`date +%s`:apt_clean\r\e[0K"
- - |
# ccache_stats
echo -e "\e[0Ksection_start:`date +%s`:ccache_stats[collapsed=true]\r\e[0Kccache statistics:"
- ccache --show-stats --verbose
- ccache --show-log-stats --verbose
- |
# ccahe_stats
echo -e "\e[0Ksection_end:`date +%s`:ccache_stats\r\e[0K"
stages:
- build
Debian testing GCC:
stage: build
image: debian:testing-slim
allow_failure: true
artifacts:
name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-testing-gcc"
variables:
CC: gcc
LDFLAGS: -Wl,-fuse-ld=gold
script:
- - |
# apt_toolchain
echo -e "\e[0Ksection_start:`date +%s`:apt_toolchain[collapsed=true]\r\e[0KInstalling toolchain packages"
- apt-get install gcc
- |
# apt_toolchain
echo -e "\e[0Ksection_end:`date +%s`:apt_toolchain\r\e[0K"
- - |
# apt_development
echo -e "\e[0Ksection_start:`date +%s`:apt_development[collapsed=true]\r\e[0KInstalling development packages"
- apt-get install libsdl2-mixer-dev libpng-dev libcurl4-openssl-dev libgme-dev libopenmpt-dev
- |
# apt_development
echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K"
- - |
# make
echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2"
- make --directory=src --keep-going CCACHE=1 ERRORMODE=1 NONX86=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 NONX86=1
- |
# make
echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K"
Windows x86:
stage: build
artifacts:
paths:
- "bin/"
- "src/comptime.h"
expose_as: "Win32"
name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-Win32"
variables:
PREFIX: i686-w64-mingw32
script:
- - |
# apt_toolchain
echo -e "\e[0Ksection_start:`date +%s`:apt_toolchain[collapsed=true]\r\e[0KInstalling toolchain packages"
- apt-get install gcc-mingw-w64-i686-win32
- |
# apt_toolchain
echo -e "\e[0Ksection_end:`date +%s`:apt_toolchain\r\e[0K"
- - |
# make
echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2"
- make --directory=src --keep-going CCACHE=1 ERRORMODE=1 MINGW=1 SDL=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 MINGW=1 SDL=1
- |
# make
echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K"
Debian stable:amd64:
stage: build
artifacts:
paths:
- "bin/"
- "src/comptime.h"
expose_as: "Debian amd64"
name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-x86-64"
variables:
CC: x86_64-linux-gnu-gcc
LDFLAGS: -Wl,-fuse-ld=gold
OBJCOPY: x86_64-linux-gnu-objcopy
OBJDUMP: x86_64-linux-gnu-objdump
PKG_CONFIG_PATH: /usr/lib/x86_64-linux-gnu/pkgconfig
script:
- - |
# apt_toolchain
echo -e "\e[0Ksection_start:`date +%s`:apt_toolchain[collapsed=true]\r\e[0KInstalling toolchain packages"
- apt-get install gcc-x86-64-linux-gnu || apt-get install gcc
- |
# apt_toolchain
echo -e "\e[0Ksection_end:`date +%s`:apt_toolchain\r\e[0K"
- - |
# apt_development
echo -e "\e[0Ksection_start:`date +%s`:apt_development[collapsed=true]\r\e[0KInstalling development packages"
- apt-get install libsdl2-mixer-dev:amd64 libpng-dev:amd64 libcurl4-openssl-dev:amd64 libgme-dev:amd64 libopenmpt-dev:amd64
- |
# apt_development
echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K"
- - |
# make
echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2"
- make --directory=src --keep-going CCACHE=1 ERRORMODE=1 LINUX64=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 LINUX64=1
- |
# make
echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K"
Debian stable:i386:
stage: build
artifacts:
paths:
- "bin/"
- "src/comptime.h"
expose_as: "Debian i386"
name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-i686"
variables:
CC: i686-linux-gnu-gcc
OBJCOPY: i686-linux-gnu-objcopy
OBJDUMP: i686-linux-gnu-objdump
PKG_CONFIG_PATH: /usr/lib/i386-linux-gnu/pkgconfig
script:
- - |
# apt_toolchain
echo -e "\e[0Ksection_start:`date +%s`:apt_toolchain[collapsed=true]\r\e[0KInstalling toolchain packages"
- apt-get install gcc-i686-linux-gnu || apt-get install gcc
- |
# apt_toolchain
echo -e "\e[0Ksection_end:`date +%s`:apt_toolchain\r\e[0K"
- - |
# apt_development
echo -e "\e[0Ksection_start:`date +%s`:apt_development[collapsed=true]\r\e[0KInstalling development packages"
- apt-get install libsdl2-mixer-dev:i386 libpng-dev:i386 libcurl4-openssl-dev:i386 libgme-dev:i386 libopenmpt-dev:i386
- |
# apt_development
echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K"
- - |
# make
echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2"
- make --directory=src --keep-going CCACHE=1 ERRORMODE=1 LINUX=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 LINUX=1
- |
# make
echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K"
Debian stable:arm64:
stage: build
artifacts:
paths:
- "bin/"
- "src/comptime.h"
expose_as: "Debian arm64"
name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-aarch64"
variables:
CC: aarch64-linux-gnu-gcc
LDFLAGS: -Wl,-fuse-ld=gold
OBJCOPY: aarch64-linux-gnu-objcopy
OBJDUMP: aarch64-linux-gnu-objdump
PKG_CONFIG_PATH: /usr/lib/aarch64-linux-gnu/pkgconfig
script:
- - |
# apt_toolchain
echo -e "\e[0Ksection_start:`date +%s`:apt_toolchain[collapsed=true]\r\e[0KInstalling toolchain packages"
- apt-get install gcc-aarch64-linux-gnu || apt-get install gcc
- |
# apt_toolchain
echo -e "\e[0Ksection_end:`date +%s`:apt_toolchain\r\e[0K"
- - |
# apt_development
echo -e "\e[0Ksection_start:`date +%s`:apt_development[collapsed=true]\r\e[0KInstalling development packages"
- apt-get install libsdl2-mixer-dev:arm64 libpng-dev:arm64 libcurl4-openssl-dev:arm64 libgme-dev:arm64 libopenmpt-dev:arm64
- |
# apt_development
echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K"
- - |
# make
echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2"
- make --directory=src --keep-going CCACHE=1 ERRORMODE=1 LINUX64=1 ERRORMODE=1 NONX86=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 LINUX64=1 NONX86=1
- |
# make
echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K"
Windows x64:
stage: build
artifacts:
paths:
- "bin/"
- "src/comptime.h"
expose_as: "Win64"
name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-Win64"
variables:
PREFIX: x86_64-w64-mingw32
script:
- - |
# apt_toolchain
echo -e "\e[0Ksection_start:`date +%s`:apt_toolchain[collapsed=true]\r\e[0KInstalling toolchain packages"
- apt-get install gcc-mingw-w64-x86-64-win32
- |
# apt_toolchain
echo -e "\e[0Ksection_end:`date +%s`:apt_toolchain\r\e[0K"
- - |
# make
echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2"
- make --directory=src --keep-going CCACHE=1 ERRORMODE=1 MINGW64=1 SDL=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 MINGW64=1 SDL=1
- |
# make
echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K"
Debian stable Clang:
stage: build
allow_failure: true
artifacts:
name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-clang"
variables:
CC: clang
WFLAGS: -Wno-cast-align
CFLAGS: -Wno-cast-align
LDFLAGS: -Wl,-fuse-ld=gold
script:
- - |
# apt_toolchain
echo -e "\e[0Ksection_start:`date +%s`:apt_toolchain[collapsed=true]\r\e[0KInstalling toolchain packages"
- apt-get install clang
- |
# apt_toolchain
echo -e "\e[0Ksection_end:`date +%s`:apt_toolchain\r\e[0K"
- - |
# apt_development
echo -e "\e[0Ksection_start:`date +%s`:apt_development[collapsed=true]\r\e[0KInstalling development packages"
- apt-get install libsdl2-mixer-dev libpng-dev libcurl4-openssl-dev libgme-dev libopenmpt-dev
- |
# apt_development
echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K"
- - |
# make
echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2"
- make --directory=src --keep-going CCACHE=1 ERRORMODE=1 NONX86=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 NONX86=1
- |
# make
echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K"
Debian testing Clang:
extends: Debian stable Clang
image: debian:testing-slim
artifacts:
name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-testing-clang"
variables:
CC: clang
WFLAGS: -Wno-cast-align -Wno-deprecated-non-prototype
CFLAGS: -Wno-cast-align -Wno-deprecated-non-prototype
LDFLAGS: -Wl,-fuse-ld=gold

View file

@ -53,11 +53,15 @@ else()
set(SRB2_CONFIG_SYSTEM_LIBRARIES_DEFAULT OFF)
endif()
# Clang tidy options will be ignored if CMAKE_<LANG>_CLANG_TIDY are set.
option(SRB2_CONFIG_ENABLE_CLANG_TIDY_C "Enable default clang-tidy check configuration for C" OFF)
option(SRB2_CONFIG_ENABLE_CLANG_TIDY_CXX "Enable default clang-tidy check configuration for C++" OFF)
option(
SRB2_CONFIG_SYSTEM_LIBRARIES
"Link dependencies using CMake's find_package and do not use internal builds"
${SRB2_CONFIG_SYSTEM_LIBRARIES_DEFAULT}
)
option(SRB2_CONFIG_ENABLE_TESTS "Build the test suite" ON)
# This option isn't recommended for distribution builds and probably won't work (yet).
cmake_dependent_option(
SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES
@ -76,6 +80,25 @@ option(SRB2_CONFIG_ZDEBUG "Compile with ZDEBUG defined." OFF)
option(SRB2_CONFIG_PROFILEMODE "Compile for profiling (GCC only)." OFF)
set(SRB2_CONFIG_ASSET_DIRECTORY "" CACHE PATH "Path to directory that contains all asset files for the installer. If set, assets will be part of installation and cpack.")
if(SRB2_CONFIG_ENABLE_TESTS)
# https://github.com/catchorg/Catch2
CPMAddPackage(
NAME Catch2
VERSION 3.4.0
GITHUB_REPOSITORY catchorg/Catch2
OPTIONS
"CATCH_INSTALL_DOCS OFF"
)
list(APPEND CMAKE_MODULE_PATH "${Catch2_SOURCE_DIR}/extras")
include(CTest)
include(Catch)
add_executable(srb2tests)
# To add tests, use target_sources to add individual test files to the target in subdirs.
target_link_libraries(srb2tests PRIVATE Catch2::Catch2 Catch2::Catch2WithMain)
target_compile_features(srb2tests PRIVATE c_std_11 cxx_std_17)
catch_discover_tests(srb2tests)
endif()
# Enable CCache
# (Set USE_CCACHE=ON to use, CCACHE_OPTIONS for options)
if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL Windows)
@ -108,7 +131,11 @@ if("${SRB2_CONFIG_SYSTEM_LIBRARIES}")
find_package(SDL2_mixer REQUIRED)
find_package(CURL REQUIRED)
find_package(OPENMPT REQUIRED)
find_package(GME REQUIRED)
# libgme defaults to "Nuked" YM2612 emulator, which is
# very SLOW. The system library probably uses the
# default so just always build it.
#find_package(GME REQUIRED)
endif()
if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR})
@ -119,13 +146,6 @@ if ((${SRB2_USE_CCACHE}) AND (${CMAKE_C_COMPILER} MATCHES "clang"))
message(WARNING "Using clang and CCache: You may want to set environment variable CCACHE_CPP2=yes to prevent include errors during compile.")
endif()
# Add sources from Sourcefile
function(target_sourcefile type)
file(STRINGS Sourcefile list
REGEX "[-0-9A-Za-z_]+\.${type}")
target_sources(SRB2SDL2 PRIVATE ${list})
endfunction()
# bitness check
set(SRB2_SYSTEM_BITS 0)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
@ -144,7 +164,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 CACHE STRING "Executable binary output name")
set(SRB2_SDL2_EXE_NAME "" CACHE STRING "Override executable binary output name")
set(SRB2_SDL2_EXE_SUFFIX "" CACHE STRING "Optional executable suffix, separated by an underscore")
include_directories(${CMAKE_CURRENT_BINARY_DIR}/src)
@ -152,11 +173,37 @@ add_subdirectory(src)
add_subdirectory(assets)
## config.h generation
set(GIT_EXECUTABLE "git" CACHE FILEPATH "Path to git binary")
include(GitUtilities)
git_latest_commit(SRB2_COMP_COMMIT "${CMAKE_SOURCE_DIR}")
git_current_branch(SRB2_GIT_BRANCH "${CMAKE_SOURCE_DIR}")
set(SRB2_COMP_BRANCH "${SRB2_GIT_BRANCH}")
set(SRB2_COMP_REVISION "${SRB2_COMP_COMMIT}")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/src/config.h)
if("${SRB2_SDL2_EXE_NAME}" STREQUAL "")
# cause a reconfigure if the branch changes
get_git_dir(SRB2_GIT_DIR)
configure_file("${SRB2_GIT_DIR}/HEAD" HEAD COPYONLY)
git_current_branch(SRB2_GIT_REVISION)
if("${SRB2_GIT_REVISION}" STREQUAL "")
# use abbreviated commit hash if on detached HEAD
git_latest_commit(SRB2_GIT_REVISION)
endif()
if("${CMAKE_SYSTEM_NAME}" MATCHES "Windows")
list(APPEND EXE_NAME_PARTS "srb2win")
elseif("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
list(APPEND EXE_NAME_PARTS "lsdlsrb2")
else()
list(APPEND EXE_NAME_PARTS "srb2")
endif()
if(NOT "${SRB2_GIT_REVISION}" STREQUAL "master")
list(APPEND EXE_NAME_PARTS ${SRB2_GIT_REVISION})
endif()
else()
list(APPEND EXE_NAME_PARTS ${SRB2_SDL2_EXE_NAME})
endif()
list(APPEND EXE_NAME_PARTS ${SRB2_SDL2_EXE_SUFFIX})
list(JOIN EXE_NAME_PARTS "_" EXE_NAME)
set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME ${EXE_NAME})

29
CMakePresets.json Normal file
View file

@ -0,0 +1,29 @@
{
"version": 3,
"configurePresets": [
{
"name": "default",
"description": "Build using default generator",
"binaryDir": "build",
"cacheVariables": {
"CMAKE_C_FLAGS": "-fdiagnostics-color",
"CMAKE_CXX_FLAGS": "-fdiagnostics-color",
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
}
},
{
"name": "debug",
"description": "Build for development (no optimizations)",
"inherits": "default",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
}
],
"buildPresets": [
{
"name": "default",
"configurePreset": "default"
}
]
}

View file

@ -8,7 +8,6 @@
[Sonic Robo Blast 2](https://srb2.org/) is a 3D Sonic the Hedgehog fangame based on a modified version of [Doom Legacy](http://doomlegacy.sourceforge.net/).
## Dependencies
- NASM (x86 builds only)
- SDL2 (Linux/OS X only)
- SDL2-Mixer (Linux/OS X only)
- libupnp (Linux/OS X only)

View file

@ -1992,24 +1992,6 @@ HW3SOUND for 3D hardware sound support
<Option compilerVar="CC" />
</Unit>
<Unit filename="src/v_video.h" />
<Unit filename="src/vid_copy.s">
<Option compilerVar="CC" />
<Option compiler="avrgcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
<Option compiler="gnu_gcc_compiler_for_mingw32" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
<Option compiler="gnu_gcc_compiler_for_mingw64" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
<Option compiler="armelfgcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
<Option compiler="tricoregcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
<Option compiler="ppcgcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
<Option compiler="gcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Mingw/DirectX" />
<Option target="Release Mingw/DirectX" />
</Unit>
<Unit filename="src/w_wad.c">
<Option compilerVar="CC" />
</Unit>

View file

@ -25,9 +25,6 @@
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(PlatformTarget)'=='x86'">
<ClCompile>
<PreprocessorDefinitions>USEASM;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>

View file

@ -5,7 +5,7 @@ Ver=3
IsCpp=0
Type=0
UnitCount=279
Folders=A_Asm,B_Bot,BLUA,D_Doom,F_Frame,G_Game,H_Hud,Hw_Hardware,Hw_Hardware/r_opengl,I_Interface,I_Interface/Dummy,I_Interface/SDL,I_Interface/Win32,LUA,M_Misc,P_Play,R_Rend,S_Sounds,W_Wad
Folders=B_Bot,BLUA,D_Doom,F_Frame,G_Game,H_Hud,Hw_Hardware,Hw_Hardware/r_opengl,I_Interface,I_Interface/Dummy,I_Interface/SDL,I_Interface/Win32,LUA,M_Misc,P_Play,R_Rend,S_Sounds,W_Wad
CommandLine=
CompilerSettings=00000000000100000111e1
PchHead=-1
@ -1473,36 +1473,6 @@ Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit149]
FileName=src\tmap.nas
Folder=A_Asm
Compile=0
CompileCpp=0
Link=0
Priority=1000
OverrideBuildCmd=1
BuildCmd=nasm.exe -g -o $@ -f win32 src/tmap.nas
[Unit150]
FileName=src\asm_defs.inc
Folder=A_Asm
Compile=0
CompileCpp=0
Link=0
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit151]
FileName=src\vid_copy.s
Folder=A_Asm
Compile=1
CompileCpp=0
Link=1
Priority=1000
OverrideBuildCmd=1
BuildCmd=$(CC) $(CFLAGS) -x assembler-with-cpp -c src/vid_copy.s -o $@
[Unit152]
FileName=src\y_inter.h
Folder=H_Hud
@ -1543,26 +1513,6 @@ Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit156]
FileName=src\p5prof.h
Folder=A_Asm
Compile=1
CompileCpp=0
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit157]
FileName=src\tmap_mmx.nas
Folder=A_Asm
Compile=0
CompileCpp=0
Link=0
Priority=1000
OverrideBuildCmd=1
BuildCmd=nasm.exe -g -o $@ -f win32 src/tmap_mmx.nas
[Unit159]
FileName=src\lzf.h
Folder=W_Wad

29
alias-bootstrap.sh Executable file
View file

@ -0,0 +1,29 @@
#!/usr/bin/env sh
# All these commands can be run from anywhere in the git
# tree, not just the top level.
# Usage: git cmake
#
# Same usage as standard CMake command.
#
git config 'alias.cmake' '!cmake'
# Usage: git build <build preset> [options]
# Usage: git build [options]
#
# In the second usage, when no preset is given, the
# "default" build preset is used.
#
# Available options can be found by running:
#
# git cmake --build
#
git config 'alias.build' '!p="${1##-*}"; [ "$p" ] && shift; git cmake --build --preset "${p:-default}"'
# Usage: git crossmake
#
# Shortcut to i686-w64-mingw32-cmake (CMake cross
# compiler)
#
git config 'alias.crossmake' '!i686-w64-mingw32-cmake'

View file

@ -1,4 +1,4 @@
version: 2.2.10.{branch}-{build}
version: 2.2.13.{branch}-{build}
os: MinGW
environment:
@ -7,8 +7,6 @@ environment:
# c:\mingw-w64 i686 has gcc 6.3.0, so use c:\msys64 7.3.0 instead
MINGW_SDK: c:\msys64\mingw32
CFLAGS: -Wno-implicit-fallthrough
NASM_ZIP: nasm-2.12.01
NASM_URL: http://www.nasm.us/pub/nasm/releasebuilds/2.12.01/win64/nasm-2.12.01-win64.zip
UPX_ZIP: upx391w
UPX_URL: http://upx.sourceforge.net/download/upx391w.zip
CCACHE_EXE: ccache.exe
@ -40,17 +38,12 @@ environment:
ASSET_CLEAN: 0
cache:
- nasm-2.12.01.zip
- upx391w.zip
- ccache.exe
- C:\Users\appveyor\.ccache
- C:\Users\appveyor\srb2_cache
install:
- if not exist "%NASM_ZIP%.zip" appveyor DownloadFile "%NASM_URL%" -FileName "%NASM_ZIP%.zip"
- 7z x -y "%NASM_ZIP%.zip" -o%TMP% >null
- robocopy /S /xx /ns /nc /nfl /ndl /np /njh /njs "%TMP%\%NASM_ZIP%" "%MINGW_SDK%\bin" nasm.exe || exit 0
- if not exist "%UPX_ZIP%.zip" appveyor DownloadFile "%UPX_URL%" -FileName "%UPX_ZIP%.zip"
- 7z x -y "%UPX_ZIP%.zip" -o%TMP% >null
- robocopy /S /xx /ns /nc /nfl /ndl /np /njh /njs "%TMP%\%UPX_ZIP%" "%MINGW_SDK%\bin" upx.exe || exit 0
@ -65,7 +58,6 @@ configuration:
before_build:
- set "Path=%MINGW_SDK%\bin;%Path%"
- mingw32-make --version
- nasm -v
- if not [%NOUPX%] == [1] ( upx -V )
- ccache -V
- ccache -s

View file

@ -29,6 +29,7 @@ set(SRB2_ASSETS_GAME
"srb2.pk3"
"player.dta"
"zones.pk3"
"patch.pk3"
"music.dta"
"models.dat"
)

32
cmake/Comptime.cmake Normal file
View file

@ -0,0 +1,32 @@
cmake_minimum_required(VERSION 3.3 FATAL_ERROR)
set(CMAKE_BINARY_DIR "${BINARY_DIR}")
set(CMAKE_CURRENT_BINARY_DIR "${BINARY_DIR}")
# Set up CMAKE path
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/")
include(GitUtilities)
git_current_branch(SRB2_COMP_BRANCH)
git_working_tree_dirty(SRB2_COMP_UNCOMMITTED)
git_latest_commit(SRB2_COMP_REVISION)
git_subject(subject)
string(REGEX REPLACE "([\"\\])" "\\\\\\1" SRB2_COMP_NOTE "${subject}")
if("${CMAKE_BUILD_TYPE}" STREQUAL "")
set(CMAKE_BUILD_TYPE None)
endif()
# These build types enable optimizations of some kind by default.
set(optimized_build_types "MINSIZEREL;RELEASE;RELWITHDEBINFO")
string(TOUPPER "${CMAKE_BUILD_TYPE}" build_type)
if("${build_type}" IN_LIST optimized_build_types)
set(SRB2_COMP_OPTIMIZED TRUE)
else()
set(SRB2_COMP_OPTIMIZED FALSE)
endif()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/config.h.in" "${CMAKE_CURRENT_BINARY_DIR}/src/config.h")

View file

@ -1,46 +0,0 @@
#=============================================================================
# Copyright 2010 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
# support for the yasm assembler
set(CMAKE_ASM_YASM_SOURCE_FILE_EXTENSIONS nasm yasm asm)
if(NOT CMAKE_ASM_YASM_OBJECT_FORMAT)
if(WIN32)
if(CMAKE_C_SIZEOF_DATA_PTR EQUAL 8)
set(CMAKE_ASM_YASM_OBJECT_FORMAT win64)
else()
set(CMAKE_ASM_YASM_OBJECT_FORMAT win32)
endif()
elseif(APPLE)
if(CMAKE_C_SIZEOF_DATA_PTR EQUAL 8)
set(CMAKE_ASM_YASM_OBJECT_FORMAT macho64)
else()
set(CMAKE_ASM_YASM_OBJECT_FORMAT macho)
endif()
else()
if(CMAKE_C_SIZEOF_DATA_PTR EQUAL 8)
set(CMAKE_ASM_YASM_OBJECT_FORMAT elf64)
else()
set(CMAKE_ASM_YASM_OBJECT_FORMAT elf)
endif()
endif()
endif()
set(CMAKE_ASM_YASM_COMPILE_OBJECT "<CMAKE_ASM_YASM_COMPILER> <FLAGS> -f ${CMAKE_ASM_YASM_OBJECT_FORMAT} -o <OBJECT> <SOURCE>")
# Load the generic ASMInformation file:
set(ASM_DIALECT "_YASM")
include(CMakeASMInformation)
set(ASM_DIALECT)

View file

@ -1,27 +0,0 @@
#=============================================================================
# Copyright 2010 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
# Find the nasm assembler. yasm (http://www.tortall.net/projects/yasm/) is nasm compatible
set(CMAKE_ASM_YASM_COMPILER_LIST nasm yasm)
if(NOT CMAKE_ASM_YASM_COMPILER)
find_program(CMAKE_ASM_YASM_COMPILER yasm
"$ENV{ProgramFiles}/YASM")
endif()
# Load the generic DetermineASM compiler file with the DIALECT set properly:
set(ASM_DIALECT "_YASM")
include(CMakeDetermineASMCompiler)
set(ASM_DIALECT)

View file

@ -1,23 +0,0 @@
#=============================================================================
# Copyright 2010 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
# This file is used by EnableLanguage in cmGlobalGenerator to
# determine that the selected ASM_NASM "compiler" works.
# For assembler this can only check whether the compiler has been found,
# because otherwise there would have to be a separate assembler source file
# for each assembler on every architecture.
set(ASM_DIALECT "_YASM")
include(CMakeTestASMCompiler)
set(ASM_DIALECT)

View file

@ -6,38 +6,54 @@ endif()
set(__GitUtilities ON)
function(git_describe variable path)
execute_process(COMMAND "${GIT_EXECUTABLE}" "describe"
WORKING_DIRECTORY "${path}"
RESULT_VARIABLE result
macro(_git_command)
execute_process(
COMMAND "${GIT_EXECUTABLE}" ${ARGN}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
OUTPUT_VARIABLE output
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
endmacro()
macro(_git_easy_command)
_git_command(${ARGN})
set(${variable} "${output}" PARENT_SCOPE)
endmacro()
function(git_current_branch variable)
_git_command(symbolic-ref -q --short HEAD)
# If a detached head, a ref could still be resolved.
if("${output}" STREQUAL "")
_git_command(describe --all --exact-match)
# Get the ref, in the form heads/master or
# remotes/origin/master so isolate the final part.
string(REGEX REPLACE ".*/" "" output "${output}")
endif()
set(${variable} "${output}" PARENT_SCOPE)
endfunction()
function(git_current_branch variable path)
execute_process(COMMAND ${GIT_EXECUTABLE} "symbolic-ref" "--short" "HEAD"
WORKING_DIRECTORY "${path}"
RESULT_VARIABLE result
OUTPUT_VARIABLE output
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(${variable} "${output}" PARENT_SCOPE)
function(git_latest_commit variable)
_git_easy_command(rev-parse --short HEAD)
endfunction()
function(git_latest_commit variable path)
execute_process(COMMAND ${GIT_EXECUTABLE} "rev-parse" "--short" "HEAD"
WORKING_DIRECTORY "${path}"
RESULT_VARIABLE result
OUTPUT_VARIABLE output
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
function(git_working_tree_dirty variable)
_git_command(status --porcelain -uno)
set(${variable} "${output}" PARENT_SCOPE)
endfunction()
if(output STREQUAL "")
set(${variable} FALSE PARENT_SCOPE)
else()
set(${variable} TRUE PARENT_SCOPE)
endif()
endfunction()
function(git_subject variable)
_git_easy_command(log -1 --format=%s)
endfunction()
function(get_git_dir variable)
_git_easy_command(rev-parse --git-dir)
endfunction()

View file

@ -0,0 +1,21 @@
find_program(CLANG_TIDY clang-tidy)
# Note: Apple Clang does not ship with clang tools. If you want clang-tidy on
# macOS, it's best to install the Homebrew llvm bottle and set CLANG_TIDY
# in your build directory. The llvm package is keg-only, so it will not
# collide with Apple Clang.
function(target_set_default_clang_tidy target lang checks)
if("${CLANG_TIDY}" STREQUAL "CLANG_TIDY-NOTFOUND")
return()
endif()
get_target_property(c_clang_tidy_prop SRB2SDL2 C_CLANG_TIDY)
if(NOT ("${c_clang_tidy_prop}" STREQUAL "c_clang_tidy_prop-NOTFOUND"))
return()
endif()
set_target_properties("${target}" PROPERTIES
${lang}_CLANG_TIDY "${CLANG_TIDY};-checks=${checks}"
)
endfunction()

View file

@ -3,12 +3,12 @@ ifdef ComSpec
COMSPEC=$(ComSpec)
endif
ifdef COMSPEC
OBJCOPY=objcopy.exe
OBJDUMP=objdump.exe
OBJCOPY?=objcopy.exe
OBJDUMP?=objdump.exe
GZIP?=gzip.exe
else
OBJCOPY=objcopy
OBJDUMP=objdump
OBJCOPY?=objcopy
OBJDUMP?=objdump
GZIP?=gzip
endif
DBGNAME=$(BIN).debug

File diff suppressed because it is too large Load diff

View file

@ -15,7 +15,7 @@ common
ignoredextensions = "wad pk3 pk7 bak backup1 backup2 backup3 zip rar 7z";
// Default testing parameters
testparameters = "-file \"%AP\" \"%F\" -warp %L";
testparameters = "-folder \"%AF\" -file \"%AA\" \"%F\" -warp %L";
testshortpaths = true;
// Action special help
@ -26,7 +26,7 @@ common
generalizedsectors = true;
// Maximum safe map size check (0 means skip check)
safeboundary = 1;
safeboundary = 0;
// Map boundaries. Map objects can only be placed within these boundaries
leftboundary = -32768;
@ -40,6 +40,8 @@ common
defaultflatscale = 1.0f;
scaledtextureoffsets = true;
maxcolormapalpha = 25;
// Thing number for start position in 3D Mode
start3dmode = 3328;
@ -68,137 +70,6 @@ common
}
}
mapformat_doom
{
// The format interface handles the map data format
formatinterface = "DoomMapSetIO";
// Default nodebuilder configurations
defaultsavecompiler = "zennode_normal";
defaulttestcompiler = "zennode_fast";
/*
GAME DETECT PATTERN
Used to guess the game for which a WAD file is made.
1 = One of these lumps must exist
2 = None of these lumps must exist
3 = All of these lumps must exist
*/
gamedetect
{
EXTENDED = 2;
BEHAVIOR = 2;
E#M# = 2;
MAP?? = 1;
}
/*
MAP LUMP NAMES
Map lumps are loaded with the map as long as they are right after each other. When the editor
meets a lump which is not defined in this list it will ignore the map if not satisfied.
The order of items defines the order in which lumps will be written to WAD file on save.
To indicate the map header lump, use ~MAP
Legenda:
required = Lump is required to exist.
blindcopy = Lump will be copied along with the map blindly. (usefull for lumps Doom Builder doesn't use)
nodebuild = The nodebuilder generates this lump.
allowempty = The nodebuilder is allowed to leave this lump empty.
script = This lump is a text-based script. Specify the filename of the script configuration to use.
*/
maplumpnames
{
include("SRB222_misc.cfg", "doommaplumpnames");
}
// When this is set to true, sectors with the same tag will light up when a line is highlighted
linetagindicatesectors = true;
// Special linedefs
include("SRB222_misc.cfg", "speciallinedefs");
// Default flags for first new thing
defaultthingflags
{
}
// DEFAULT SECTOR BRIGHTNESS LEVELS
sectorbrightness
{
include("SRB222_misc.cfg", "sectorbrightness");
}
// SECTOR TYPES
sectortypes
{
include("SRB222_sectors.cfg", "sectortypes");
}
// GENERALISED SECTOR TYPES
gen_sectortypes
{
include("SRB222_sectors.cfg", "gen_sectortypes");
}
// LINEDEF FLAGS
linedefflags
{
include("SRB222_misc.cfg", "linedefflags");
}
// Linedef flags UDMF translation table
// This is needed for copy/paste and prefabs to work properly
// When the UDMF field name is prefixed with ! it is inverted
linedefflagstranslation
{
include("SRB222_misc.cfg", "linedefflagstranslation");
}
// LINEDEF ACTIVATIONS
linedefactivations
{
}
// LINEDEF TYPES
linedeftypes
{
include("SRB222_linedefs.cfg", "doom");
}
// THING FLAGS
thingflags
{
include("SRB222_misc.cfg", "thingflags");
}
// Thing flags UDMF translation table
// This is needed for copy/paste and prefabs to work properly
// When the UDMF field name is prefixed with ! it is inverted
thingflagstranslation
{
include("SRB222_misc.cfg", "thingflagstranslation");
}
// THING FLAGS ERROR MASK
// Mask for the thing flags which indicates the options
// that make the same thing appear in the same modes
thingflagsmask1 = 7; // 1 + 2 + 4
thingflagsmask2 = 0;
// THING TYPES
thingtypes
{
include("SRB222_things.cfg", "doom");
}
}
mapformat_udmf
{
// The format interface handles the map data format
@ -222,9 +93,17 @@ mapformat_udmf
{
include("SRB222_misc.cfg", "universalfields");
}
// Disable Doom-related modes that don't make sense for SRB2
soundsupport = false;
automapsupport = false;
// When this is set to true, sectors with the same tag will light up when a line is highlighted
linetagindicatesectors = false;
localsidedeftextureoffsets = true;
distinctfloorandceilingbrightness = true;
planeequationsupport = true;
// Special linedefs
include("SRB222_misc.cfg", "speciallinedefs_udmf");
@ -240,6 +119,11 @@ mapformat_udmf
include("SRB222_misc.cfg", "sectorflags");
}
sectorflagscategories
{
include("SRB222_misc.cfg", "sectorflagscategories");
}
// DEFAULT SECTOR BRIGHTNESS LEVELS
sectorbrightness
{
@ -247,6 +131,7 @@ mapformat_udmf
}
damagetypes = "Generic Water Fire Lava Electric Spike DeathPitTilt DeathPitNoTilt Instakill SpecialStage";
triggerertypes = "Player AllPlayers Mobj";
// LINEDEF FLAGS
linedefflags
@ -282,7 +167,6 @@ mapformat_udmf
// How to compare thing flags (for the stuck things error checker)
thingflagscompare
{
include("UDMF_misc.cfg", "thingflagscompare");
}
// THING TYPES

File diff suppressed because it is too large Load diff

View file

@ -1,24 +1,3 @@
linedefflags
{
1 = "[0] Impassable";
2 = "[1] Block Enemies";
4 = "[2] Double-Sided";
8 = "[3] Upper Unpegged";
16 = "[4] Lower Unpegged";
32 = "[5] Slope Skew (E1)";
64 = "[6] Not Climbable";
128 = "[7] No Midtexture Skew (E2)";
256 = "[8] Peg Midtexture (E3)";
512 = "[9] Solid Midtexture (E4)";
1024 = "[10] Repeat Midtexture (E5)";
2048 = "[11] Netgame Only";
4096 = "[12] No Netgame";
8192 = "[13] Effect 6";
16384 = "[14] Bouncy Wall";
32768 = "[15] Transfer Line";
}
// Linedef flags UDMF translation table
// This is needed for copy/paste and prefabs to work properly
// When the UDMF field name is prefixed with ! it is inverted
@ -42,7 +21,6 @@ linedefflagstranslation
32768 = "transfer";
}
linedefflags_udmf
{
blocking = "Impassable";
@ -74,19 +52,13 @@ linedefrenderstyles
sectorflags
{
colormapfog = "Fog Planes in Colormap";
colormapfadesprites = "Fade Fullbright in Colormap";
colormapprotected = "Protected Colormap";
flipspecial_nofloor = "No Trigger on Floor Touch";
flipspecial_ceiling = "Trigger on Ceiling Touch";
triggerspecial_touch = "Trigger on Edge Touch";
triggerspecial_headbump = "Trigger on Headbump";
triggerline_plane = "Linedef Trigger Requires Plane Touch";
triggerline_mobj = "Non-Pushables Can Trigger Linedef";
invertprecip = "Invert Precipitation";
gravityflip = "Flip Objects in Reverse Gravity";
heatwave = "Heat Wave";
noclipcamera = "Intangible to the Camera";
colormapfog = "Fog Planes";
colormapfadesprites = "Fade Fullbright";
colormapprotected = "Protected from Tagging";
outerspace = "Space Countdown";
doublestepup = "Ramp Sector (double step-up/down)";
nostepdown = "Non-Ramp Sector (No step-down)";
@ -104,23 +76,59 @@ sectorflags
zoomtubeend = "Zoom Tube End";
finishline = "Circuit Finish Line";
ropehang = "Rope Hang";
jumpflip = "Flip Gravity on Jump";
gravityoverride = "Make Reverse Gravity Temporary";
flipspecial_nofloor = "No Trigger on Floor Touch";
flipspecial_ceiling = "Trigger on Ceiling Touch";
triggerspecial_touch = "Trigger on Edge Touch";
triggerspecial_headbump = "Trigger on Headbump";
triggerline_plane = "Linedef Trigger Requires Plane Touch";
triggerline_mobj = "Non-Pushables Can Trigger Linedef";
}
thingflags
sectorflagscategories
{
1 = "[1] Extra";
2 = "[2] Flip";
4 = "[4] Special";
8 = "[8] Ambush";
invertprecip = "regular";
gravityflip = "regular";
heatwave = "regular";
noclipcamera = "regular";
colormapfog = "colormap";
colormapfadesprites = "colormap";
colormapprotected = "colormap";
outerspace = "special";
doublestepup = "special";
nostepdown = "special";
speedpad = "special";
starpostactivator = "special";
exit = "special";
specialstagepit = "special";
returnflag = "special";
redteambase = "special";
blueteambase = "special";
fan = "special";
supertransform = "special";
forcespin = "special";
zoomtubestart = "special";
zoomtubeend = "special";
finishline = "special";
ropehang = "special";
jumpflip = "special";
gravityoverride = "special";
flipspecial_nofloor = "trigger";
flipspecial_ceiling = "trigger";
triggerspecial_touch = "trigger";
triggerspecial_headbump = "trigger";
triggerline_plane = "trigger";
triggerline_mobj = "trigger";
}
// THING FLAGS
thingflags_udmf
{
flip = "Flip";
absolutez = "Absolute Z height";
}
// Thing flags UDMF translation table
// This is needed for copy/paste and prefabs to work properly
// When the UDMF field name is prefixed with ! it is inverted
@ -130,9 +138,9 @@ thingflagstranslation
2 = "flip";
4 = "special";
8 = "ambush";
16 = "absolutez";
}
// DEFAULT SECTOR BRIGHTNESS LEVELS
sectorbrightness
{
@ -171,6 +179,8 @@ sectorbrightness
0;
}
numbrightnesslevels = 32;
/*
TEXTURES AND FLAT SOURCES
This tells Doom Builder where to find the information for textures
@ -221,145 +231,18 @@ universalfields
{
sector
{
lightalpha
{
type = 0;
default = 25;
}
fadealpha
{
type = 0;
default = 25;
}
fadestart
{
type = 0;
default = 0;
}
fadeend
{
type = 0;
default = 33;
}
foglighting
{
type = 3;
default = false;
}
friction
{
type = 1;
default = 0.90625;
}
triggertag
{
type = 15;
default = 0;
}
triggerer
{
type = 2;
default = "Player";
}
}
linedef
{
arg5
{
type = 0;
default = 0;
}
arg6
{
type = 0;
default = 0;
}
arg7
{
type = 0;
default = 0;
}
arg8
{
type = 0;
default = 0;
}
arg9
{
type = 0;
default = 0;
}
stringarg0
{
type = 2;
default = "";
}
stringarg1
{
type = 2;
default = "";
}
executordelay
{
type = 0;
default = 0;
}
}
sidedef
{
repeatcnt
{
type = 0;
default = 0;
}
}
thing
{
arg5
{
type = 0;
default = 0;
}
arg6
{
type = 0;
default = 0;
}
arg7
{
type = 0;
default = 0;
}
arg8
{
type = 0;
default = 0;
}
arg9
{
type = 0;
default = 0;
}
stringarg0
{
type = 2;
default = "";
}
stringarg1
{
type = 2;
default = "";
}
}
}
@ -378,87 +261,6 @@ allowempty = The nodebuilder is allowed to leave this lump empty.
scriptbuild = This lump is a text-based script, which should be compiled using current script compiler;
script = This lump is a text-based script. Specify the filename of the script configuration to use.
*/
doommaplumpnames
{
~MAP
{
required = true;
blindcopy = true;
nodebuild = false;
}
THINGS
{
required = true;
nodebuild = true;
allowempty = true;
}
LINEDEFS
{
required = true;
nodebuild = true;
allowempty = false;
}
SIDEDEFS
{
required = true;
nodebuild = true;
allowempty = false;
}
VERTEXES
{
required = true;
nodebuild = true;
allowempty = false;
}
SEGS
{
required = false;
nodebuild = true;
allowempty = false;
}
SSECTORS
{
required = false;
nodebuild = true;
allowempty = false;
}
NODES
{
required = false;
nodebuild = true;
allowempty = false;
}
SECTORS
{
required = true;
nodebuild = true;
allowempty = false;
}
REJECT
{
required = false;
nodebuild = true;
allowempty = false;
}
BLOCKMAP
{
required = false;
nodebuild = true;
allowempty = true;
}
}
udmfmaplumpnames
{
ZNODES
@ -682,48 +484,32 @@ thingsfilters
}
//filter3
//{
// name = "Normal Gravity";
// category = "";
// type = -1;
//
// fields
// {
// 2 = false;
// }
//}
filter3
{
name = "Normal Gravity";
category = "";
type = -1;
fields
{
2 = false;
}
}
filter4
{
name = "Reverse Gravity";
category = "";
type = -1;
fields
{
2 = true;
}
}
//filter4
//{
// name = "Reverse Gravity";
// category = "";
// type = -1;
//
// fields
// {
// 2 = true;
// }
//}
}
// Special linedefs
speciallinedefs
{
soundlinedefflag = 64; // See linedefflags
singlesidedflag = 1; // See linedefflags
doublesidedflag = 4; // See linedefflags
impassableflag = 1;
upperunpeggedflag = 8;
lowerunpeggedflag = 16;
repeatmidtextureflag = 1024;
pegmidtextureflag = 256;
}
speciallinedefs_udmf
{
soundlinedefflag = "noclimb";
@ -734,6 +520,8 @@ speciallinedefs_udmf
lowerunpeggedflag = "dontpegbottom";
repeatmidtextureflag = "wrapmidtex";
pegmidtextureflag = "midpeg";
slopeskewflag = "skewtd";
nomidtextureskewflag = "noskew";
}
scriptlumpnames

View file

@ -1,107 +0,0 @@
sectortypes
{
0 = "Normal";
1 = "Damage";
2 = "Damage (Water)";
3 = "Damage (Fire)";
4 = "Damage (Electrical)";
5 = "Spikes";
6 = "Death Pit (Camera Tilt)";
7 = "Death Pit (No Camera Tilt)";
8 = "Instant Kill";
9 = "Ring Drainer (Floor Touch)";
10 = "Ring Drainer (Anywhere in Sector)";
11 = "Special Stage Damage";
12 = "Space Countdown";
13 = "Ramp Sector (double step-up/down)";
14 = "Non-Ramp Sector (no step-down)";
15 = "Bouncy FOF <deprecated>";
16 = "Trigger Line Ex. (Pushable Objects)";
32 = "Trigger Line Ex. (Anywhere, All Players)";
48 = "Trigger Line Ex. (Floor Touch, All Players)";
64 = "Trigger Line Ex. (Anywhere in Sector)";
80 = "Trigger Line Ex. (Floor Touch)";
96 = "Trigger Line Ex. (Emerald Check) <deprecated>";
112 = "Trigger Line Ex. (NiGHTS Mare) <deprecated>";
128 = "Check for Linedef Executor on FOFs";
144 = "Egg Capsule";
160 = "Special Stage Time/Spheres Parameters <deprecated>";
176 = "Custom Global Gravity <deprecated>";
1280 = "Speed Pad";
1536 = "Flip Gravity on Jump";
4096 = "Star Post Activator";
8192 = "Exit/Special Stage Pit/Return Flag";
12288 = "CTF Red Team Base";
16384 = "CTF Blue Team Base";
20480 = "Fan Sector";
24576 = "Super Sonic Transform";
28672 = "Force Spin";
32768 = "Zoom Tube Start";
36864 = "Zoom Tube End";
40960 = "Circuit Finish Line";
45056 = "Rope Hang";
49152 = "Intangible to the Camera";
}
gen_sectortypes
{
first
{
0 = "Normal";
1 = "Damage";
2 = "Damage (Water)";
3 = "Damage (Fire)";
4 = "Damage (Electrical)";
5 = "Spikes";
6 = "Death Pit (Camera Tilt)";
7 = "Death Pit (No Camera Tilt)";
8 = "Instant Kill";
9 = "Ring Drainer (Floor Touch)";
10 = "Ring Drainer (Anywhere in Sector)";
11 = "Special Stage Damage";
12 = "Space Countdown";
13 = "Ramp Sector (double step-up/down)";
14 = "Non-Ramp Sector (no step-down)";
15 = "Bouncy FOF <deprecated>";
}
second
{
0 = "Normal";
16 = "Trigger Line Ex. (Pushable Objects)";
32 = "Trigger Line Ex. (Anywhere, All Players)";
48 = "Trigger Line Ex. (Floor Touch, All Players)";
64 = "Trigger Line Ex. (Anywhere in Sector)";
80 = "Trigger Line Ex. (Floor Touch)";
96 = "Trigger Line Ex. (Emerald Check) <deprecated>";
112 = "Trigger Line Ex. (NiGHTS Mare) <deprecated>";
128 = "Check for Linedef Executor on FOFs";
144 = "Egg Capsule";
160 = "Special Stage Time/Spheres Parameters <deprecated>";
176 = "Custom Global Gravity <deprecated>";
}
third
{
0 = "Normal";
1280 = "Speed Pad";
1536 = "Flip Gravity on Jump";
}
fourth
{
0 = "Normal";
4096 = "Star Post Activator";
8192 = "Exit/Special Stage Pit/Return Flag";
12288 = "CTF Red Team Base";
16384 = "CTF Blue Team Base";
20480 = "Fan Sector";
24576 = "Super Sonic Transform";
28672 = "Force Spin";
32768 = "Zoom Tube Start";
36864 = "Zoom Tube End";
40960 = "Circuit Finish Line";
45056 = "Rope Hang";
49152 = "Intangible to the Camera";
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,32 +0,0 @@
/************************************************************************\
Ultimate Doom Builder Game Configuration for Sonic Robo Blast 2 Version 2.2
\************************************************************************/
// This is required to prevent accidental use of a different configuration
type = "Doom Builder 2 Game Configuration";
// This is the title to show for this game
game = "Sonic Robo Blast 2 - 2.2 (Doom format)";
// This is the simplified game engine/sourceport name
engine = "zdoom";
// Settings common to all games and all map formats
include("Includes\\SRB222_common.cfg", "common");
// Settings common to Doom map format
include("Includes\\SRB222_common.cfg", "mapformat_doom");
include("Includes\\Game_SRB222.cfg");
// Script lumps detection
scriptlumpnames
{
include("Includes\\SRB222_misc.cfg", "scriptlumpnames");
}
//Default things filters
thingsfilters
{
include("Includes\\SRB222_misc.cfg", "thingsfilters");
}

View file

@ -76,7 +76,7 @@ LOCAL_SRC_FILES := am_map.c \
android/i_system.c \
android/i_video.c
LOCAL_CFLAGS += -DPLATFORM_ANDROID -DNONX86 -DLINUX -DDEBUGMODE -DNOASM -DNOPIX -DUNIXCOMMON -DNOTERMIOS
LOCAL_CFLAGS += -DPLATFORM_ANDROID -DNONX86 -DLINUX -DDEBUGMODE -DNOPIX -DUNIXCOMMON -DNOTERMIOS
LOCAL_MODULE := libsrb2

View file

@ -1,23 +1,150 @@
add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32)
include(clang-tidy-default)
if("${CMAKE_COMPILER_IS_GNUCC}" AND "${CMAKE_SYSTEM_NAME}" MATCHES "Windows" AND NOT "${SRB2_CONFIG_SYSTEM_LIBRARIES}" AND NOT "${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}")
# On MinGW with internal libraries, link the standard library statically
target_link_options(SRB2SDL2 PRIVATE "-static")
add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
comptime.c
md5.c
config.h.in
string.c
d_main.c
d_clisrv.c
d_net.c
d_netfil.c
d_netcmd.c
dehacked.c
deh_soc.c
deh_lua.c
deh_tables.c
z_zone.c
f_finale.c
f_wipe.c
g_demo.c
g_game.c
g_input.c
am_map.c
command.c
console.c
hu_stuff.c
i_time.c
y_inter.c
st_stuff.c
m_aatree.c
m_anigif.c
m_argv.c
m_bbox.c
m_cheat.c
m_cond.c
m_easing.c
m_fixed.c
m_menu.c
m_misc.c
m_perfstats.c
m_random.c
m_queue.c
info.c
p_ceilng.c
p_enemy.c
p_floor.c
p_inter.c
p_lights.c
p_map.c
p_maputl.c
p_mobj.c
p_polyobj.c
p_saveg.c
p_setup.c
p_sight.c
p_spec.c
p_telept.c
p_tick.c
p_user.c
p_slopes.c
tables.c
r_bsp.c
r_data.c
r_draw.c
r_fps.c
r_main.c
r_plane.c
r_segs.c
r_skins.c
r_sky.c
r_splats.c
r_things.c
r_bbox.c
r_textures.c
r_patch.c
r_patchrotation.c
r_picformats.c
r_portal.c
screen.c
taglist.c
v_video.c
s_sound.c
sounds.c
w_wad.c
filesrch.c
mserv.c
http-mserv.c
i_tcp.c
lzf.c
b_bot.c
u_list.c
lua_script.c
lua_baselib.c
lua_mathlib.c
lua_hooklib.c
lua_consolelib.c
lua_infolib.c
lua_mobjlib.c
lua_playerlib.c
lua_skinlib.c
lua_thinkerlib.c
lua_maplib.c
lua_taglib.c
lua_polyobjlib.c
lua_blockmaplib.c
lua_hudlib.c
lua_hudlib_drawlist.c
lua_inputlib.c
)
# This updates the modification time for comptime.c at the
# end of building so when the build system is ran next time,
# that file gets flagged. comptime.c will always be rebuilt.
#
# This begs the question, why always rebuild comptime.c?
# Some things like the git commit must be checked each time
# the program is built. But the build system determines which
# files should be rebuilt before anything else. So
# comptime.c, which only needs to be rebuilt based on
# information known at build time, must be told to rebuild
# before that information can be ascertained.
add_custom_command(
TARGET SRB2SDL2
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E touch_nocreate ${CMAKE_CURRENT_SOURCE_DIR}/comptime.c
)
# config.h is generated by this command. It should be done at
# build time for accurate git information and before anything
# that needs it, obviously.
add_custom_target(_SRB2_reconf ALL
COMMAND ${CMAKE_COMMAND} -DGIT_EXECUTABLE=${GIT_EXECUTABLE} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DBINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}/.. -P ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/Comptime.cmake
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.."
)
add_dependencies(SRB2SDL2 _SRB2_reconf)
if("${CMAKE_COMPILER_IS_GNUCC}" AND "${CMAKE_SYSTEM_NAME}" MATCHES "Windows")
target_link_options(SRB2SDL2 PRIVATE "-Wl,--disable-dynamicbase")
if(NOT "${SRB2_CONFIG_SYSTEM_LIBRARIES}" AND NOT "${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}")
# On MinGW with internal libraries, link the standard library statically
target_link_options(SRB2SDL2 PRIVATE "-static")
endif()
endif()
# Core sources
target_sourcefile(c)
target_sources(SRB2SDL2 PRIVATE comptime.c md5.c config.h.in)
set(SRB2_ASM_SOURCES vid_copy.s)
set(SRB2_NASM_SOURCES tmap_mmx.nas tmap.nas)
target_compile_features(SRB2SDL2 PRIVATE c_std_11 cxx_std_17)
### Configuration
set(SRB2_CONFIG_USEASM OFF CACHE BOOL
"Enable NASM tmap implementation for software mode speedup.")
set(SRB2_CONFIG_YASM OFF CACHE BOOL
"Use YASM in place of NASM.")
set(SRB2_CONFIG_DEV_BUILD OFF CACHE BOOL
"Compile a development build of SRB2.")
@ -74,33 +201,6 @@ if("${SRB2_CONFIG_HWRENDER}")
endif()
endif()
if(${SRB2_CONFIG_USEASM})
#SRB2_ASM_FLAGS can be used to pass flags to either nasm or yasm.
if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
set(SRB2_ASM_FLAGS "-DLINUX ${SRB2_ASM_FLAGS}")
endif()
if(${SRB2_CONFIG_YASM})
set(CMAKE_ASM_YASM_SOURCE_FILE_EXTENSIONS ${CMAKE_ASM_YASM_SOURCE_FILE_EXTENSIONS} nas)
set(CMAKE_ASM_YASM_FLAGS "${SRB2_ASM_FLAGS}" CACHE STRING "Flags used by the assembler during all build types.")
enable_language(ASM_YASM)
else()
set(CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS ${CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS} nas)
set(CMAKE_ASM_NASM_FLAGS "${SRB2_ASM_FLAGS}" CACHE STRING "Flags used by the assembler during all build types.")
enable_language(ASM_NASM)
endif()
set(SRB2_USEASM ON)
target_compile_definitions(SRB2SDL2 PRIVATE -DUSEASM)
target_compile_options(SRB2SDL2 PRIVATE -msse3 -mfpmath=sse)
target_sources(SRB2SDL2 PRIVATE ${SRB2_ASM_SOURCES}
${SRB2_NASM_SOURCES})
else()
set(SRB2_USEASM OFF)
target_compile_definitions(SRB2SDL2 PRIVATE -DNONX86 -DNORUSEASM)
endif()
# Targets
# If using CCACHE, then force it.
@ -289,6 +389,9 @@ if(SRB2_CONFIG_PROFILEMODE AND "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
endif()
add_subdirectory(sdl)
if(SRB2_CONFIG_ENABLE_TESTS)
add_subdirectory(tests)
endif()
# strip debug symbols into separate file when using gcc.
# to be consistent with Makefile, don't generate for OS X.
@ -329,3 +432,11 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL Windows AND NOT "${SRB2_CONFIG_INTERNAL_LIBRA
COMMENT "Copying runtime DLLs"
)
endif()
# Setup clang-tidy
if(SRB2_CONFIG_ENABLE_CLANG_TIDY_C)
target_set_default_clang_tidy(SRB2SDL2 C "-*,clang-analyzer-*,-clang-analyzer-cplusplus-*")
endif()
if(SRB2_CONFIG_ENABLE_CLANG_TIDY_CXX)
target_set_default_clang_tidy(SRB2SDL2 CXX "-*,clang-analyzer-*,modernize-*")
endif()

View file

@ -47,8 +47,6 @@
# HAVE_MINIUPNPC=1 - Enable automated port forwarding.
# Already enabled by default for 32-bit
# Windows.
# NOASM=1 - Disable hand optimized assembly code for the
# Software renderer.
# NOPNG=1 - Disable PNG graphics support. (TODO: double
# check netplay compatible.)
# NOCURL=1 - Disable libcurl--HTTP capability.
@ -88,7 +86,6 @@
# executable.
# WINDOWSHELL=1 - Use Windows commands.
# PREFIX= - Prefix to many commands, for cross compiling.
# YASM=1 - Use Yasm instead of NASM assembler.
# STABS=1 - ?
# ECHO=1 - Print out each command in the build process.
# NOECHOFILENAMES=1 - Don't print out each that is being
@ -144,25 +141,9 @@ endif
OBJDUMP_OPTS?=--wide --source --line-numbers
OBJCOPY:=$(call Prefix,objcopy)
OBJDUMP:=$(call Prefix,objdump)
WINDRES:=$(call Prefix,windres)
ifdef YASM
NASM?=yasm
else
NASM?=nasm
endif
ifdef YASM
ifdef STABS
NASMOPTS?=-g stabs
else
NASMOPTS?=-g dwarf2
endif
else
NASMOPTS?=-g
endif
OBJCOPY?=$(call Prefix,objcopy)
OBJDUMP?=$(call Prefix,objdump)
WINDRES?=$(call Prefix,windres)
GZIP?=gzip
GZIP_OPTS?=-9 -f -n
@ -187,8 +168,6 @@ makedir:=../make
opts:=-DCOMPVERSION -g
libs:=
nasm_format:=
# This is a list of variables names, of which if defined,
# also defines the name as a macro to the compiler.
passthru_opts:=
@ -316,7 +295,6 @@ endif
LD:=$(CC)
cc:=$(cc) $(opts)
nasm=$(NASM) $(NASMOPTS) -f $(nasm_format)
ifdef UPX
upx=$(UPX) $(UPX_OPTS)
endif
@ -393,7 +371,6 @@ $(objdir)/%.$(1) : %.$(2) | $$$$(@D)/
endef
$(eval $(call _recipe,o,c,$(cc) -c -o $$@ $$<))
$(eval $(call _recipe,o,nas,$(nasm) -o $$@ $$<))
$(eval $(call _recipe,o,s,$(cc) $(asflags) -c -o $$@ $$<))
$(eval $(call _recipe,res,rc,$(windres) -i $$< -o $$@))
@ -414,3 +391,5 @@ ifdef WINDOWSHELL
else
@:
endif
#$(warning The handwritten GNU Makefile for SRB2 is deprecated, and may be removed in the future. Please consider switching to CMake.)

View file

@ -56,15 +56,18 @@ endif
# This must have high to low order.
gcc_versions:=\
102 101\
93 92 91\
84 83 82 81\
75 74 73 72 71\
64 63 62 61\
55 54 53 52 51\
132 131 130\
123 122 121 120\
114 113 112 111 110\
105 104 103 102 101 100\
95 94 93 92 91 90\
85 84 83 82 81 80\
75 74 73 72 71 70\
64 63 62 61 60\
55 54 53 52 51 50\
49 48 47 46 45 44 43 42 41 40
latest_gcc_version:=10.2
latest_gcc_version:=13.2
# Automatically set version flag, but not if one was
# manually set. And don't bother if this is a clean only
@ -74,13 +77,18 @@ ifeq (,$(call Wildvar,GCC% destructive))
# can't use $(CC) --version here since that uses argv[0] to display the name
# also gcc outputs the information to stderr, so I had to do 2>&1
# this program really doesn't like identifying itself
version:=$(shell $(CC) -v 2>&1)
shellversion:=$(shell $(CC) -v 2>&1)
# Try to remove "-win32"
version:=$(subst -win32,.0,$(shellversion))
# check if this is in fact GCC
ifneq (,$(findstring gcc version,$(version)))
# in stark contrast to the name, gcc will give me a nicely formatted version number for free
version:=$(shell $(CC) -dumpfullversion)
shellversion:=$(shell $(CC) -dumpfullversion)
# Try to remove "-win32"
version:=$(subst -win32,.0,$(shellversion))
# Turn version into words of major, minor
v:=$(subst ., ,$(version))

View file

@ -1,75 +1,72 @@
#
# Makefile for feature flags.
#
passthru_opts+=\
NONET NO_IPV6 NOHW NOMD5 NOPOSTPROCESSING\
MOBJCONSISTANCY PACKETDROP ZDEBUG\
HAVE_MINIUPNPC\
# build with debugging information
ifdef DEBUGMODE
PACKETDROP=1
opts+=-DPARANOIA -DRANGECHECK
endif
ifndef NOHW
opts+=-DHWRENDER
sources+=$(call List,hardware/Sourcefile)
endif
ifndef NOASM
ifndef NONX86
sources+=tmap.nas tmap_mmx.nas
opts+=-DUSEASM
endif
endif
ifndef NOMD5
sources+=md5.c
endif
ifndef NOZLIB
ifndef NOPNG
ifdef PNG_PKGCONFIG
$(eval $(call Use_pkg_config,PNG_PKGCONFIG))
else
PNG_CONFIG?=$(call Prefix,libpng-config)
$(eval $(call Configure,PNG,$(PNG_CONFIG) \
$(if $(PNG_STATIC),--static),,--ldflags))
endif
ifdef LINUX
opts+=-D_LARGEFILE64_SOURCE
endif
opts+=-DHAVE_PNG
sources+=apng.c
endif
endif
ifndef NONET
ifndef NOCURL
CURLCONFIG?=curl-config
$(eval $(call Configure,CURL,$(CURLCONFIG)))
opts+=-DHAVE_CURL
endif
endif
ifdef HAVE_MINIUPNPC
libs+=-lminiupnpc
endif
# (Valgrind is a memory debugger.)
ifdef VALGRIND
VALGRIND_PKGCONFIG?=valgrind
$(eval $(call Use_pkg_config,VALGRIND))
ZDEBUG=1
opts+=-DHAVE_VALGRIND
endif
default_packages:=\
GME/libgme/LIBGME\
OPENMPT/libopenmpt/LIBOPENMPT\
ZLIB/zlib\
$(foreach p,$(default_packages),\
$(eval $(call Check_pkg_config,$(p))))
#
# Makefile for feature flags.
#
passthru_opts+=\
NONET NO_IPV6 NOHW NOMD5 NOPOSTPROCESSING\
MOBJCONSISTANCY PACKETDROP ZDEBUG\
HAVE_MINIUPNPC\
# build with debugging information
ifdef DEBUGMODE
PACKETDROP=1
opts+=-DPARANOIA -DRANGECHECK
endif
ifndef NOHW
opts+=-DHWRENDER
sources+=$(call List,hardware/Sourcefile)
endif
ifdef NONET
NOCURL=1
endif
ifndef NOMD5
sources+=md5.c
endif
ifndef NOZLIB
ifndef NOPNG
ifdef PNG_PKGCONFIG
$(eval $(call Use_pkg_config,PNG_PKGCONFIG))
else
PNG_CONFIG?=$(call Prefix,libpng-config)
$(eval $(call Configure,PNG,$(PNG_CONFIG) \
$(if $(PNG_STATIC),--static),,--ldflags))
endif
ifdef LINUX
opts+=-D_LARGEFILE64_SOURCE
endif
opts+=-DHAVE_PNG
sources+=apng.c
endif
endif
ifndef NONET
ifndef NOCURL
CURLCONFIG?=curl-config
$(eval $(call Configure,CURL,$(CURLCONFIG)))
opts+=-DHAVE_CURL
endif
endif
ifdef HAVE_MINIUPNPC
libs+=-lminiupnpc
endif
# (Valgrind is a memory debugger.)
ifdef VALGRIND
VALGRIND_PKGCONFIG?=valgrind
$(eval $(call Use_pkg_config,VALGRIND))
ZDEBUG=1
opts+=-DHAVE_VALGRIND
endif
default_packages:=\
GME/libgme/LIBGME\
OPENMPT/libopenmpt/LIBOPENMPT\
ZLIB/zlib\
$(foreach p,$(default_packages),\
$(eval $(call Check_pkg_config,$(p))))

View file

@ -9,10 +9,6 @@ opts+=-DUNIXCOMMON -DLUA_USE_POSIX
# instead of addresses
libs+=-lm -rdynamic
ifndef nasm_format
nasm_format:=elf -DLINUX
endif
ifndef NOHW
opts+=-I/usr/X11R6/include
libs+=-L/usr/X11R6/lib
@ -29,13 +25,12 @@ endif
# Tested by Steel, as of release 2.2.8.
ifdef FREEBSD
opts+=-I/usr/X11R6/include -DLINUX -DFREEBSD
libs+=-L/usr/X11R6/lib -lipx -lkvm
libs+=-L/usr/X11R6/lib -lkvm -lexecinfo
endif
# FIXME: UNTESTED
#ifdef SOLARIS
#NOIPX=1
#NOASM=1
#opts+=-I/usr/local/include -I/opt/sfw/include \
# -DSOLARIS -DINADDR_NONE=INADDR_ANY -DBSD_COMP
#libs+=-L/opt/sfw/lib -lsocket -lnsl

View file

@ -39,7 +39,6 @@ else ifdef SOLARIS # FIXME: UNTESTED
UNIX=1
platform=solaris
else ifdef CYGWIN32 # FIXME: UNTESTED
nasm_format=win32
platform=cygwin
else ifdef MINGW
ifdef MINGW64

View file

@ -56,13 +56,6 @@ SDL_LDFLAGS?=$(shell $(SDL_CONFIG) \
$(eval $(call Propogate_flags,SDL))
endif
# use the x86 asm code
ifndef CYGWIN32
ifndef NOASM
USEASM=1
endif
endif
ifdef MINGW
ifndef NOSDLMAIN
SDLMAIN=1

View file

@ -17,8 +17,6 @@ sources+=win32/Srb2win.rc
opts+=-DSTDC_HEADERS
libs+=-ladvapi32 -lkernel32 -lmsvcrt -luser32
nasm_format:=win32
SDL?=1
ifndef NOHW

View file

@ -64,6 +64,7 @@ r_skins.c
r_sky.c
r_splats.c
r_things.c
r_bbox.c
r_textures.c
r_patch.c
r_patchrotation.c
@ -80,8 +81,8 @@ mserv.c
http-mserv.c
i_tcp.c
lzf.c
vid_copy.s
b_bot.c
u_list.c
lua_script.c
lua_baselib.c
lua_mathlib.c

View file

@ -24,7 +24,7 @@ static INT64 start_time; // as microseconds since the epoch
// I should probably return how much memory is remaining
// for this process, considering Android's process memory limit.
UINT32 I_GetFreeMem(UINT32 *total)
size_t I_GetFreeMem(size_t *total)
{
// what the heck? sysinfo() is partially missing in bionic?
/* struct sysinfo si; */
@ -278,4 +278,26 @@ char *I_ClipboardPaste(void)
void I_RegisterSysCommands(void) {}
// This is identical to the SDL implementation.
size_t I_GetRandomBytes(char *destination, size_t count)
{
FILE *rndsource;
size_t actual_bytes;
if (!(rndsource = fopen("/dev/urandom", "r")))
if (!(rndsource = fopen("/dev/random", "r")))
actual_bytes = 0;
if (rndsource)
{
actual_bytes = fread(destination, 1, count, rndsource);
fclose(rndsource);
}
if (actual_bytes == 0)
I_OutputMsg("I_GetRandomBytes(): couldn't get any random bytes");
return actual_bytes;
}
#include "../sdl/dosstr.c"

View file

@ -1,43 +0,0 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file asm_defs.inc
/// \brief must match the C structures
#ifndef __ASM_DEFS__
#define __ASM_DEFS__
// this makes variables more noticable,
// and make the label match with C code
// Linux, unlike DOS, has no "_" 19990119 by Kin
// and nasm needs .data code segs under linux 20010210 by metzgermeister
// FIXME: nasm ignores these settings, so I put the macros into the makefile
#ifdef __ELF__
#define C(label) label
#define CODE_SEG .data
#else
#define C(label) _##label
#define CODE_SEG .text
#endif
/* This is a more readable way to access the arguments passed from C code */
/* PLEASE NOTE: it is supposed that all arguments passed from C code are */
/* 32bit integer (INT32, long, and most *pointers) */
#define ARG1 8(%ebp)
#define ARG2 12(%ebp)
#define ARG3 16(%ebp)
#define ARG4 20(%ebp)
#define ARG5 24(%ebp)
#define ARG6 28(%ebp)
#define ARG7 32(%ebp)
#define ARG8 36(%ebp)
#define ARG9 40(%ebp) //(c)tm ... Allegro by Shawn Hargreaves.
#endif

View file

@ -631,7 +631,8 @@ void B_HandleFlightIndicator(player_t *player)
}
// otherwise, update its visibility
if (P_IsLocalPlayer(player->botleader))
tails->hnext->drawonlyforplayer = player->botleader; // Hide it from the other player in splitscreen, and yourself when spectating
if (P_IsLocalPlayer(player->botleader)) // Only display it on your own view. Don't display it for spectators
tails->hnext->flags2 &= ~MF2_DONTDRAW;
else
tails->hnext->flags2 |= MF2_DONTDRAW;

View file

@ -1 +1,28 @@
target_sourcefile(c)
target_sources(SRB2SDL2 PRIVATE
lapi.c
lbaselib.c
ldo.c
lfunc.c
linit.c
liolib.c
llex.c
lmem.c
lobject.c
lstate.c
lstrlib.c
ltablib.c
lundump.c
lzio.c
lauxlib.c
lcode.c
ldebug.c
ldump.c
lgc.c
lopcodes.c
lparser.c
lstring.c
ltable.c
ltm.c
lvm.c
loslib.c
)

View file

@ -23,3 +23,4 @@ lstring.c
ltable.c
ltm.c
lvm.c
loslib.c

View file

@ -18,6 +18,7 @@ static const luaL_Reg lualibs[] = {
{"", luaopen_base},
{LUA_TABLIBNAME, luaopen_table},
{LUA_IOLIBNAME, luaopen_io},
{LUA_OSLIBNAME, luaopen_os},
{LUA_STRLIBNAME, luaopen_string},
{NULL, NULL}
};

167
src/blua/loslib.c Normal file
View file

@ -0,0 +1,167 @@
/*
** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $
** Standard Operating System library
** See Copyright Notice in lua.h
*/
#include <errno.h>
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define loslib_c
#define LUA_LIB
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
static int os_clock (lua_State *L) {
lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC);
return 1;
}
/*
** {======================================================
** Time/Date operations
** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,
** wday=%w+1, yday=%j, isdst=? }
** =======================================================
*/
static void setfield (lua_State *L, const char *key, int value) {
lua_pushinteger(L, value);
lua_setfield(L, -2, key);
}
static void setboolfield (lua_State *L, const char *key, int value) {
if (value < 0) /* undefined? */
return; /* does not set field */
lua_pushboolean(L, value);
lua_setfield(L, -2, key);
}
static int getboolfield (lua_State *L, const char *key) {
int res;
lua_getfield(L, -1, key);
res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);
lua_pop(L, 1);
return res;
}
static int getfield (lua_State *L, const char *key, int d) {
int res;
lua_getfield(L, -1, key);
if (lua_isnumber(L, -1))
res = (int)lua_tointeger(L, -1);
else {
if (d < 0)
return luaL_error(L, "field " LUA_QS " missing in date table", key);
res = d;
}
lua_pop(L, 1);
return res;
}
static int os_date (lua_State *L) {
const char *s = luaL_optstring(L, 1, "%c");
time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL));
struct tm *stm;
if (*s == '!') { /* UTC? */
stm = gmtime(&t);
s++; /* skip `!' */
}
else
stm = localtime(&t);
if (stm == NULL) /* invalid date? */
lua_pushnil(L);
else if (strcmp(s, "*t") == 0) {
lua_createtable(L, 0, 9); /* 9 = number of fields */
setfield(L, "sec", stm->tm_sec);
setfield(L, "min", stm->tm_min);
setfield(L, "hour", stm->tm_hour);
setfield(L, "day", stm->tm_mday);
setfield(L, "month", stm->tm_mon+1);
setfield(L, "year", stm->tm_year+1900);
setfield(L, "wday", stm->tm_wday+1);
setfield(L, "yday", stm->tm_yday+1);
setboolfield(L, "isdst", stm->tm_isdst);
}
else {
char cc[3];
luaL_Buffer b;
cc[0] = '%'; cc[2] = '\0';
luaL_buffinit(L, &b);
for (; *s; s++) {
if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */
luaL_addchar(&b, *s);
else {
size_t reslen;
char buff[200]; /* should be big enough for any conversion result */
cc[1] = *(++s);
reslen = strftime(buff, sizeof(buff), cc, stm);
luaL_addlstring(&b, buff, reslen);
}
}
luaL_pushresult(&b);
}
return 1;
}
static int os_time (lua_State *L) {
time_t t;
if (lua_isnoneornil(L, 1)) /* called without args? */
t = time(NULL); /* get current time */
else {
struct tm ts;
luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 1); /* make sure table is at the top */
ts.tm_sec = getfield(L, "sec", 0);
ts.tm_min = getfield(L, "min", 0);
ts.tm_hour = getfield(L, "hour", 12);
ts.tm_mday = getfield(L, "day", -1);
ts.tm_mon = getfield(L, "month", -1) - 1;
ts.tm_year = getfield(L, "year", -1) - 1900;
ts.tm_isdst = getboolfield(L, "isdst");
t = mktime(&ts);
}
if (t == (time_t)(-1))
lua_pushnil(L);
else
lua_pushnumber(L, (lua_Number)t);
return 1;
}
static int os_difftime (lua_State *L) {
lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
(time_t)(luaL_optnumber(L, 2, 0))));
return 1;
}
/* }====================================================== */
static const luaL_Reg syslib[] = {
{"clock", os_clock},
{"date", os_date},
{"difftime", os_difftime},
{"time", os_time},
{NULL, NULL}
};
/* }====================================================== */
LUALIB_API int luaopen_os (lua_State *L) {
luaL_register(L, LUA_OSLIBNAME, syslib);
return 1;
}

View file

@ -24,6 +24,9 @@ LUALIB_API int (luaopen_table) (lua_State *L);
#define LUA_IOLIBNAME "io"
LUALIB_API int (luaopen_io) (lua_State *L);
#define LUA_OSLIBNAME "os"
LUALIB_API int (luaopen_os) (lua_State *L);
#define LUA_STRLIBNAME "string"
LUALIB_API int (luaopen_string) (lua_State *L);

View file

@ -34,6 +34,7 @@
#include "lua_script.h"
#include "d_netfil.h" // findfile
#include "r_data.h" // Color_cons_t
#include "d_main.h" // D_IsPathAllowed
//========
// protos.
@ -75,6 +76,7 @@ CV_PossibleValue_t CV_OnOff[] = {{0, "Off"}, {1, "On"}, {0, NULL}};
CV_PossibleValue_t CV_YesNo[] = {{0, "No"}, {1, "Yes"}, {0, NULL}};
CV_PossibleValue_t CV_Unsigned[] = {{0, "MIN"}, {999999999, "MAX"}, {0, NULL}};
CV_PossibleValue_t CV_Natural[] = {{1, "MIN"}, {999999999, "MAX"}, {0, NULL}};
CV_PossibleValue_t CV_TrueFalse[] = {{0, "False"}, {1, "True"}, {0, NULL}};
// Filter consvars by EXECVERSION
// First implementation is 26 (2.1.21), so earlier configs default at 25 (2.1.20)
@ -679,25 +681,58 @@ static void COM_ExecuteString(char *ptext)
// SCRIPT COMMANDS
// =========================================================================
static void print_alias(void)
{
cmdalias_t *a;
CONS_Printf("\x82""Current alias commands:\n");
for (a = com_alias; a; a = a->next)
{
CONS_Printf("%s : %s", a->name, a->value);
}
}
static void add_alias(char *newname, char *newcmd)
{
cmdalias_t *a;
// Check for existing aliases first
for (a = com_alias; a; a = a->next)
{
if (!stricmp(newname, a->name))
{
Z_Free(a->value); // Free old cmd
a->value = newcmd;
return;
}
}
// No alias found, add it instead
a = ZZ_Alloc(sizeof *a);
a->next = com_alias;
com_alias = a;
a->name = newname;
a->value = newcmd;
}
/** Creates a command name that replaces another command.
*/
static void COM_Alias_f(void)
{
cmdalias_t *a;
char *name;
char *zcmd;
char cmd[1024];
size_t i, c;
if (COM_Argc() < 3)
{
CONS_Printf(M_GetText("alias <name> <command>: create a shortcut command that executes other command(s)\n"));
print_alias();
return;
}
a = ZZ_Alloc(sizeof *a);
a->next = com_alias;
com_alias = a;
a->name = Z_StrDup(COM_Argv(1));
name = Z_StrDup(COM_Argv(1));
// copy the rest of the command line
cmd[0] = 0; // start out with a null string
@ -709,8 +744,8 @@ static void COM_Alias_f(void)
strcat(cmd, " ");
}
strcat(cmd, "\n");
a->value = Z_StrDup(cmd);
zcmd = Z_StrDup(cmd);
add_alias(name, zcmd);
}
/** Prints a line of text to the console.
@ -781,6 +816,9 @@ static void COM_Exec_f(void)
return;
}
if (!D_CheckPathAllowed(COM_Argv(1), "tried to exec"))
return;
// load file
// Try with Argv passed verbatim first, for back compat
FIL_ReadFile(COM_Argv(1), &buf);
@ -859,9 +897,11 @@ static void COM_Help_f(void)
{
CONS_Printf(" Possible values:\n");
if (cvar->PossibleValue == CV_YesNo)
CONS_Printf(" Yes or No (On or Off, 1 or 0)\n");
CONS_Printf(" Yes or No (On or Off, True or False, 1 or 0)\n");
else if (cvar->PossibleValue == CV_OnOff)
CONS_Printf(" On or Off (Yes or No, 1 or 0)\n");
CONS_Printf(" On or Off (Yes or No, True or False, 1 or 0)\n");
else if (cvar->PossibleValue == CV_TrueFalse)
CONS_Printf(" True or False (On or Off, Yes or No, 1 or 0)\n");
else if (cvar->PossibleValue == Color_cons_t)
{
for (i = 1; i < numskincolors; ++i)
@ -1012,7 +1052,7 @@ static void COM_Toggle_f(void)
if (CV_Immutable(cvar))
return;
if (!(cvar->PossibleValue == CV_YesNo || cvar->PossibleValue == CV_OnOff))
if (!(cvar->PossibleValue == CV_YesNo || cvar->PossibleValue == CV_OnOff || cvar->PossibleValue == CV_TrueFalse))
{
CONS_Alert(CONS_NOTICE, M_GetText("%s is not a boolean value\n"), COM_Argv(1));
return;
@ -1503,12 +1543,12 @@ static void Setvalue(consvar_t *var, const char *valstr, boolean stealth)
goto found;
}
// Not found ... but wait, there's hope!
if (var->PossibleValue == CV_OnOff || var->PossibleValue == CV_YesNo)
if (var->PossibleValue == CV_OnOff || var->PossibleValue == CV_YesNo || var->PossibleValue == CV_TrueFalse)
{
overrideval = -1;
if (!stricmp(valstr, "on") || !stricmp(valstr, "yes"))
if (!stricmp(valstr, "on") || !stricmp(valstr, "yes") || !stricmp(valstr, "true"))
overrideval = 1;
else if (!stricmp(valstr, "off") || !stricmp(valstr, "no"))
else if (!stricmp(valstr, "off") || !stricmp(valstr, "no") || !stricmp(valstr, "false"))
overrideval = 0;
if (overrideval != -1)

View file

@ -177,6 +177,7 @@ extern CV_PossibleValue_t CV_OnOff[];
extern CV_PossibleValue_t CV_YesNo[];
extern CV_PossibleValue_t CV_Unsigned[];
extern CV_PossibleValue_t CV_Natural[];
extern CV_PossibleValue_t CV_TrueFalse[];
// Filter consvars by version
extern consvar_t cv_execversion;

View file

@ -11,6 +11,9 @@
#include "config.h"
const char *compbranch = SRB2_COMP_BRANCH;
const char *comprevision = SRB2_COMP_REVISION;
const char *compnote = SRB2_COMP_NOTE;
const char *comptype = CMAKE_BUILD_TYPE;
const int compoptimized = SRB2_COMP_OPTIMIZED;
#elif (defined(COMPVERSION))
#include "comptime.h"
@ -21,5 +24,12 @@ const char *comprevision = "illegal";
#endif
const int compuncommitted =
#if (defined(COMPVERSION_UNCOMMITTED))
1;
#else
0;
#endif
const char *compdate = __DATE__;
const char *comptime = __TIME__;

View file

@ -11,8 +11,18 @@
#ifdef CMAKECONFIG
#define SRB2_COMP_REVISION "${SRB2_COMP_REVISION}"
#define SRB2_COMP_BRANCH "${SRB2_COMP_BRANCH}"
#define SRB2_COMP_REVISION "${SRB2_COMP_REVISION}"
#define SRB2_COMP_BRANCH "${SRB2_COMP_BRANCH}"
#define SRB2_COMP_NOTE "${SRB2_COMP_NOTE}"
// This is done with configure_file instead of defines in order to avoid
// recompiling the whole target whenever the working directory state changes
#cmakedefine SRB2_COMP_UNCOMMITTED
#ifdef SRB2_COMP_UNCOMMITTED
#define COMPVERSION_UNCOMMITTED
#endif
#define CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}"
#cmakedefine01 SRB2_COMP_OPTIMIZED
#endif
@ -27,12 +37,15 @@
* Last updated 2020 / 10 / 02 - v2.2.8 - patch.pk3
* Last updated 2021 / 05 / 06 - v2.2.9 - patch.pk3 & zones.pk3
* Last updated 2022 / 03 / 06 - v2.2.10 - main assets
* Last updated 2023 / 05 / 02 - v2.2.11 - patch.pk3 & zones.pk3
* Last updated 2023 / 09 / 06 - v2.2.12 - patch.pk3
* Last updated 2023 / 09 / 09 - v2.2.13 - none
*/
#define ASSET_HASH_SRB2_PK3 "ad911f29a28a18968ee5b2d11c2acb39"
#define ASSET_HASH_ZONES_PK3 "86ae55cae4e0a93ceda868635706a093"
#define ASSET_HASH_ZONES_PK3 "1c8adf8d079ecb87d00081f158acf3c7"
#define ASSET_HASH_PLAYER_DTA "2e7aaae8a6b1b77d90ffe7606ceadb6c"
#ifdef USE_PATCH_DTA
#define ASSET_HASH_PATCH_PK3 "7d467a883f7887b3c311798ee2f56b6a"
#define ASSET_HASH_PATCH_PK3 "3c7b73f34af7e9a7bceb2d5260f76172"
#endif
#endif

View file

@ -61,7 +61,7 @@ static boolean con_started = false; // console has been initialised
static boolean con_forcepic = true; // at startup toggle console translucency when first off
boolean con_recalc; // set true when screen size has changed
static tic_t con_tick; // console ticker for anim or blinking prompt cursor
static tic_t con_tick; // console ticker for blinking prompt cursor
// con_scrollup should use time (currenttime - lasttime)..
static boolean consoletoggle; // true when console key pushed, ticker will handle
@ -72,8 +72,8 @@ static INT32 con_curlines; // vid lines currently used by console
INT32 con_clipviewtop; // (useless)
static INT32 con_hudlines; // number of console heads up message lines
static INT32 con_hudtime[MAXHUDLINES]; // remaining time of display for hud msg lines
static UINT8 con_hudlines; // number of console heads up message lines
static UINT32 con_hudtime[MAXHUDLINES]; // remaining time of display for hud msg lines
INT32 con_clearlines; // top screen lines to refresh when view reduced
boolean con_hudupdate; // when messages scroll, we need a backgrnd refresh
@ -110,6 +110,7 @@ static void CON_RecalcSize(void);
static void CON_ChangeHeight(void);
static void CON_DrawBackpic(void);
static void CONS_height_Change(void);
static void CONS_hudlines_Change(void);
static void CONS_backcolor_Change(void);
@ -125,10 +126,13 @@ static void CONS_backcolor_Change(void);
static char con_buffer[CON_BUFFERSIZE];
// how many seconds the hud messages lasts on the screen
static consvar_t cons_msgtimeout = CVAR_INIT ("con_hudtime", "5", CV_SAVE, CV_Unsigned, NULL);
// CV_Unsigned can overflow when multiplied by TICRATE later, so let's use a 3-year limit instead
static CV_PossibleValue_t hudtime_cons_t[] = {{0, "MIN"}, {99999999, "MAX"}, {0, NULL}};
static consvar_t cons_hudtime = CVAR_INIT ("con_hudtime", "5", CV_SAVE, hudtime_cons_t, NULL);
// number of lines displayed on the HUD
static consvar_t cons_hudlines = CVAR_INIT ("con_hudlines", "5", CV_CALL|CV_SAVE, CV_Unsigned, CONS_hudlines_Change);
static CV_PossibleValue_t hudlines_cons_t[] = {{0, "MIN"}, {MAXHUDLINES, "MAX"}, {0, NULL}};
static consvar_t cons_hudlines = CVAR_INIT ("con_hudlines", "5", CV_CALL|CV_SAVE, hudlines_cons_t, CONS_hudlines_Change);
// number of lines console move per frame
// (con_speed needs a limit, apparently)
@ -136,7 +140,7 @@ static CV_PossibleValue_t speed_cons_t[] = {{0, "MIN"}, {64, "MAX"}, {0, NULL}};
static consvar_t cons_speed = CVAR_INIT ("con_speed", "8", CV_SAVE, speed_cons_t, NULL);
// percentage of screen height to use for console
static consvar_t cons_height = CVAR_INIT ("con_height", "50", CV_SAVE, CV_Unsigned, NULL);
static consvar_t cons_height = CVAR_INIT ("con_height", "50", CV_CALL|CV_SAVE, CV_Unsigned, CONS_height_Change);
static CV_PossibleValue_t backpic_cons_t[] = {{0, "translucent"}, {1, "picture"}, {0, NULL}};
// whether to use console background picture, or translucent mode
@ -156,6 +160,18 @@ consvar_t cons_backcolor = CVAR_INIT ("con_backcolor", "Green", CV_CALL|CV_SAVE,
static void CON_Print(char *msg);
// Change the console height on demand
//
static void CONS_height_Change(void)
{
Lock_state();
if (con_destlines > 0 && !con_startup) // If the console is open (as in, not using "bind")...
CON_ChangeHeight(); // ...update its height now, not only when it's closed and re-opened
Unlock_state();
}
//
//
static void CONS_hudlines_Change(void)
@ -168,11 +184,6 @@ static void CONS_hudlines_Change(void)
for (i = 0; i < con_hudlines; i++)
con_hudtime[i] = 0;
if (cons_hudlines.value < 1)
cons_hudlines.value = 1;
else if (cons_hudlines.value > MAXHUDLINES)
cons_hudlines.value = MAXHUDLINES;
con_hudlines = cons_hudlines.value;
Unlock_state();
@ -382,16 +393,16 @@ static void CON_SetupColormaps(void)
// 0x1 0x3 0x9 0xF
colset(magentamap, 177, 177, 178, 178, 178, 180, 180, 180, 182, 182, 182, 182, 184, 184, 184, 185);
colset(yellowmap, 82, 82, 73, 73, 73, 64, 64, 64, 66, 66, 66, 66, 67, 67, 67, 68);
colset(lgreenmap, 96, 96, 98, 98, 98, 101, 101, 101, 104, 104, 104, 104, 106, 106, 106, 107);
colset(bluemap, 146, 146, 147, 147, 147, 149, 149, 149, 152, 152, 152, 152, 155, 155, 155, 157);
colset(redmap, 32, 32, 33, 33, 33, 35, 35, 35, 39, 39, 39, 39, 42, 42, 42, 44);
colset(yellowmap, 82, 82, 73, 73, 73, 74, 74, 74, 66, 66, 66, 66, 67, 67, 67, 68);
colset(lgreenmap, 96, 96, 98, 98, 98, 100, 100, 100, 103, 103, 103, 103, 105, 105, 105, 107);
colset(bluemap, 146, 146, 147, 147, 147, 148, 148, 148, 149, 149, 149, 149, 150, 150, 150, 151);
colset(redmap, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 35, 37, 37, 37, 39);
colset(graymap, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23);
colset(orangemap, 50, 50, 52, 52, 52, 54, 54, 54, 56, 56, 56, 56, 59, 59, 59, 60);
colset(skymap, 129, 129, 130, 130, 130, 131, 131, 131, 133, 133, 133, 133, 135, 135, 135, 136);
colset(purplemap, 160, 160, 161, 161, 161, 162, 162, 162, 163, 163, 163, 163, 164, 164, 164, 165);
colset(aquamap, 120, 120, 121, 121, 121, 122, 122, 122, 123, 123, 123, 123, 124, 124, 124, 125);
colset(peridotmap, 72, 72, 188, 188, 189, 189, 189, 189, 190, 190, 190, 190, 191, 191, 191, 94);
colset(peridotmap, 73, 73, 188, 188, 188, 189, 189, 189, 190, 190, 190, 190, 191, 191, 191, 94);
colset(azuremap, 144, 144, 145, 145, 145, 146, 146, 146, 170, 170, 170, 170, 171, 171, 171, 172);
colset(brownmap, 219, 219, 221, 221, 221, 222, 222, 222, 224, 224, 224, 224, 227, 227, 227, 229);
colset(rosymap, 200, 200, 201, 201, 201, 202, 202, 202, 203, 203, 203, 203, 204, 204, 204, 205);
@ -464,7 +475,7 @@ void CON_Init(void)
Unlock_state();
CV_RegisterVar(&cons_msgtimeout);
CV_RegisterVar(&cons_hudtime);
CV_RegisterVar(&cons_hudlines);
CV_RegisterVar(&cons_speed);
CV_RegisterVar(&cons_height);
@ -643,33 +654,39 @@ static void CON_ChangeHeight(void)
//
static void CON_MoveConsole(void)
{
fixed_t conspeed;
static fixed_t fracmovement = 0;
Lock_state();
conspeed = FixedDiv(cons_speed.value*vid.fdupy, FRACUNIT);
// instant
if (!cons_speed.value)
{
con_curlines = con_destlines;
Unlock_state();
return;
}
// up/down move to dest
if (con_curlines < con_destlines)
// Not instant - Increment fracmovement fractionally
fracmovement += FixedMul(cons_speed.value*vid.fdupy, renderdeltatics);
if (con_curlines < con_destlines) // Move the console downwards
{
con_curlines += FixedInt(conspeed);
if (con_curlines > con_destlines)
con_curlines = con_destlines;
con_curlines += FixedInt(fracmovement); // Move by fracmovement's integer value
if (con_curlines > con_destlines) // If we surpassed the destination...
con_curlines = con_destlines; // ...clamp to it!
}
else if (con_curlines > con_destlines)
else // Move the console upwards
{
con_curlines -= FixedInt(conspeed);
con_curlines -= FixedInt(fracmovement);
if (con_curlines < con_destlines)
con_curlines = con_destlines;
if (con_destlines == 0) // If the console is being closed, not just moved up...
con_tick = 0; // ...don't show the blinking cursor
}
fracmovement %= FRACUNIT; // Reset fracmovement's integer value, but keep the fraction
Unlock_state();
}
@ -752,10 +769,6 @@ void CON_Ticker(void)
CON_ChangeHeight();
}
// console movement
if (con_destlines != con_curlines)
CON_MoveConsole();
// clip the view, so that the part under the console is not drawn
con_clipviewtop = -1;
if (cons_backpic.value) // clip only when using an opaque background
@ -777,9 +790,8 @@ void CON_Ticker(void)
// make overlay messages disappear after a while
for (i = 0; i < con_hudlines; i++)
{
con_hudtime[i]--;
if (con_hudtime[i] < 0)
con_hudtime[i] = 0;
if (con_hudtime[i])
con_hudtime[i]--;
}
Unlock_state();
@ -1328,7 +1340,8 @@ boolean CON_Responder(event_t *ev)
static void CON_Linefeed(void)
{
// set time for heads up messages
con_hudtime[con_cy%con_hudlines] = cons_msgtimeout.value*TICRATE;
if (con_hudlines)
con_hudtime[con_cy%con_hudlines] = cons_hudtime.value*TICRATE;
con_cy++;
con_cx = 0;
@ -1684,7 +1697,7 @@ static void CON_DrawHudlines(void)
INT32 charwidth = 8 * con_scalefactor;
INT32 charheight = 8 * con_scalefactor;
if (con_hudlines <= 0)
if (!con_hudlines)
return;
if (chat_on && OLDCHAT)
@ -1692,7 +1705,7 @@ static void CON_DrawHudlines(void)
else
y = 0;
for (i = con_cy - con_hudlines+1; i <= con_cy; i++)
for (i = con_cy - con_hudlines; i <= con_cy; i++)
{
size_t c;
INT32 x;
@ -1809,41 +1822,41 @@ static void CON_DrawConsole(void)
}
// draw console text lines from top to bottom
if (con_curlines < minheight)
return;
i = con_cy - con_scrollup;
// skip the last empty line due to the cursor being at the start of a new line
i--;
i -= (con_curlines - minheight) / charheight;
if (rendermode == render_none) return;
for (y = (con_curlines-minheight) % charheight; y <= con_curlines-minheight; y += charheight, i++)
if (con_curlines >= minheight)
{
INT32 x;
size_t c;
i = con_cy - con_scrollup;
p = (UINT8 *)&con_buffer[((i > 0 ? i : 0)%con_totallines)*con_width];
// skip the last empty line due to the cursor being at the start of a new line
i--;
for (c = 0, x = charwidth; c < con_width; c++, x += charwidth, p++)
i -= (con_curlines - minheight) / charheight;
if (rendermode == render_none) return;
for (y = (con_curlines-minheight) % charheight; y <= con_curlines-minheight; y += charheight, i++)
{
while (*p & 0x80)
INT32 x;
size_t c;
p = (UINT8 *)&con_buffer[((i > 0 ? i : 0)%con_totallines)*con_width];
for (c = 0, x = charwidth; c < con_width; c++, x += charwidth, p++)
{
charflags = (*p & 0x7f) << V_CHARCOLORSHIFT;
p++;
c++;
while (*p & 0x80)
{
charflags = (*p & 0x7f) << V_CHARCOLORSHIFT;
p++;
c++;
}
if (c >= con_width)
break;
V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, true);
}
if (c >= con_width)
break;
V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, true);
}
}
// draw prompt if enough place (not while game startup)
if ((con_curlines == con_destlines) && (con_curlines >= minheight) && !con_startup)
if ((con_curlines >= (minheight-charheight)) && !con_startup)
CON_DrawInput();
}
@ -1866,11 +1879,15 @@ void CON_Drawer(void)
CON_ClearHUD();
}
// console movement
if (con_curlines != con_destlines)
CON_MoveConsole();
if (con_curlines > 0)
CON_DrawConsole();
else if (gamestate == GS_LEVEL
|| gamestate == GS_INTERMISSION || gamestate == GS_ENDING || gamestate == GS_CUTSCENE
|| gamestate == GS_CREDITS || gamestate == GS_EVALUATION)
|| gamestate == GS_CREDITS || gamestate == GS_EVALUATION || gamestate == GS_WAITINGPLAYERS)
CON_DrawHudlines();
Unlock_state();

View file

@ -120,6 +120,8 @@ UINT8 hu_redownloadinggamestate = 0;
// true when a player is connecting or disconnecting so that the gameplay has stopped in its tracks
boolean hu_stopped = false;
consvar_t cv_dedicatedidletime = CVAR_INIT ("dedicatedidletime", "10", CV_SAVE, CV_Unsigned, NULL);
UINT8 adminpassmd5[16];
boolean adminpasswordset = false;
@ -1293,6 +1295,7 @@ static boolean CL_AskFileList(INT32 firstfile)
static boolean CL_SendJoin(void)
{
UINT8 localplayers = 1;
char const *player2name;
if (netgame)
CONS_Printf(M_GetText("Sending join request...\n"));
netbuffer->packettype = PT_CLIENTJOIN;
@ -1309,18 +1312,23 @@ static boolean CL_SendJoin(void)
CleanupPlayerName(consoleplayer, cv_playername.zstring);
if (splitscreen)
CleanupPlayerName(1, cv_playername2.zstring);/* 1 is a HACK? oh no */
// Avoid empty string on bots to avoid softlocking in singleplayer
if (botingame)
player2name = strcmp(cv_playername.zstring, "Tails") == 0 ? "Tail" : "Tails";
else
player2name = cv_playername2.zstring;
strncpy(netbuffer->u.clientcfg.names[0], cv_playername.zstring, MAXPLAYERNAME);
strncpy(netbuffer->u.clientcfg.names[1], cv_playername2.zstring, MAXPLAYERNAME);
strncpy(netbuffer->u.clientcfg.names[1], player2name, MAXPLAYERNAME);
return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak));
}
static INT32 FindRejoinerNum(SINT8 node)
{
char strippednodeaddress[64];
char addressbuffer[64];
const char *nodeaddress;
char *port;
const char *strippednodeaddress;
INT32 i;
// Make sure there is no dead dress before proceeding to the stripping
@ -1331,10 +1339,8 @@ static INT32 FindRejoinerNum(SINT8 node)
return -1;
// Strip the address of its port
strcpy(strippednodeaddress, nodeaddress);
port = strchr(strippednodeaddress, ':');
if (port)
*port = '\0';
strcpy(addressbuffer, nodeaddress);
strippednodeaddress = I_NetSplitAddress(addressbuffer, NULL);
// Check if any player matches the stripped address
for (i = 0; i < MAXPLAYERS; i++)
@ -1506,6 +1512,7 @@ static boolean SV_SendServerConfig(INT32 node)
netbuffer->u.servercfg.gamestate = (UINT8)gamestate;
netbuffer->u.servercfg.gametype = (UINT8)gametype;
netbuffer->u.servercfg.modifiedgame = (UINT8)modifiedgame;
netbuffer->u.servercfg.usedCheats = (UINT8)usedCheats;
memcpy(netbuffer->u.servercfg.server_context, server_context, 8);
@ -2486,7 +2493,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
{
if (!snake)
{
F_MenuPresTicker(true); // title sky
F_MenuPresTicker(); // title sky
F_TitleScreenTicker(true);
F_TitleScreenDrawer();
}
@ -2601,6 +2608,8 @@ static void CL_ConnectToServer(void)
}
while (!(cl_mode == CL_CONNECTED && (client || (server && nodewaited <= pnumnodes))));
if (netgame)
F_StartWaitingPlayers();
DEBFILE(va("Synchronisation Finished\n"));
displayplayer = consoleplayer;
@ -2734,7 +2743,6 @@ static void Command_ClearBans(void)
static void Ban_Load_File(boolean warning)
{
FILE *f;
size_t i;
const char *address, *mask;
char buffer[MAX_WADPATH];
@ -2752,7 +2760,7 @@ static void Ban_Load_File(boolean warning)
Ban_Clear();
for (i=0; fgets(buffer, (int)sizeof(buffer), f); i++)
for (; fgets(buffer, (int)sizeof(buffer), f);)
{
address = strtok(buffer, " \t\r\n");
mask = strtok(NULL, " \t\r\n");
@ -3644,6 +3652,9 @@ void SV_ResetServer(void)
CV_RevertNetVars();
// Ensure synched when creating a new server
M_CopyGameData(serverGamedata, clientGamedata);
DEBFILE("\n-=-=-=-=-=-=-= Server Reset =-=-=-=-=-=-=-\n\n");
}
@ -3767,14 +3778,13 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
if (server && I_GetNodeAddress)
{
char addressbuffer[64];
const char *address = I_GetNodeAddress(node);
char *port = NULL;
if (address) // MI: fix msvcrt.dll!_mbscat crash?
{
strcpy(playeraddress[newplayernum], address);
port = strchr(playeraddress[newplayernum], ':');
if (port)
*port = '\0';
strcpy(addressbuffer, address);
strcpy(playeraddress[newplayernum],
I_NetSplitAddress(addressbuffer, NULL));
}
}
}
@ -4406,6 +4416,8 @@ static void HandlePacketFromAwayNode(SINT8 node)
maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic);
G_SetGametype(netbuffer->u.servercfg.gametype);
modifiedgame = netbuffer->u.servercfg.modifiedgame;
if (netbuffer->u.servercfg.usedCheats)
G_SetUsedCheats(true);
memcpy(server_context, netbuffer->u.servercfg.server_context, 8);
}
@ -4515,6 +4527,7 @@ static void HandlePacketFromPlayer(SINT8 node)
netconsole = 0;
else
netconsole = nodetoplayer[node];
#ifdef PARANOIA
if (netconsole >= MAXPLAYERS)
I_Error("bad table nodetoplayer: node %d player %d", doomcom->remotenode, netconsole);
@ -4553,21 +4566,32 @@ static void HandlePacketFromPlayer(SINT8 node)
// Update the nettics
nettics[node] = realend;
// Don't do anything for packets of type NODEKEEPALIVE?
if (netconsole == -1 || netbuffer->packettype == PT_NODEKEEPALIVE
|| netbuffer->packettype == PT_NODEKEEPALIVEMIS)
// This should probably still timeout though, as the node should always have a player 1 number
if (netconsole == -1)
break;
// As long as clients send valid ticcmds, the server can keep running, so reset the timeout
/// \todo Use a separate cvar for that kind of timeout?
freezetimeout[node] = I_GetTime() + connectiontimeout;
// Don't do anything for packets of type NODEKEEPALIVE?
// Sryder 2018/07/01: Update the freezetimeout still!
if (netbuffer->packettype == PT_NODEKEEPALIVE
|| netbuffer->packettype == PT_NODEKEEPALIVEMIS)
break;
// If we've alredy received a ticcmd for this tic, just submit it for the next one.
tic_t faketic = maketic;
if ((!!(netcmds[maketic % BACKUPTICS][netconsole].angleturn & TICCMD_RECEIVED))
&& (maketic - firstticstosend < BACKUPTICS - 1))
faketic++;
// Copy ticcmd
G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1);
G_MoveTiccmd(&netcmds[faketic%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)
if (netcmds[faketic%BACKUPTICS][netconsole].forwardmove > MAXPLMOVE || netcmds[faketic%BACKUPTICS][netconsole].forwardmove < -MAXPLMOVE
|| netcmds[faketic%BACKUPTICS][netconsole].sidemove > MAXPLMOVE || netcmds[faketic%BACKUPTICS][netconsole].sidemove < -MAXPLMOVE)
{
CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), netconsole);
//D_Clearticcmd(k);
@ -4579,9 +4603,10 @@ static void HandlePacketFromPlayer(SINT8 node)
// Splitscreen cmd
if ((netbuffer->packettype == PT_CLIENT2CMD || netbuffer->packettype == PT_CLIENT2MIS)
&& nodetoplayer2[node] >= 0)
G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]],
G_MoveTiccmd(&netcmds[faketic%BACKUPTICS][(UINT8)nodetoplayer2[node]],
&netbuffer->u.client2pak.cmd2, 1);
// Check player consistancy during the level
if (realstart <= gametic && realstart + BACKUPTICS - 1 > gametic && gamestate == GS_LEVEL
&& consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy)
@ -4618,6 +4643,21 @@ static void HandlePacketFromPlayer(SINT8 node)
}
}
break;
case PT_BASICKEEPALIVE:
if (client)
break;
// This should probably still timeout though, as the node should always have a player 1 number
if (netconsole == -1)
break;
// If a client sends this it should mean they are done receiving the savegame
sendingsavegame[node] = false;
// As long as clients send keep alives, the server can keep running, so reset the timeout
/// \todo Use a separate cvar for that kind of timeout?
freezetimeout[node] = I_GetTime() + connectiontimeout;
break;
case PT_TEXTCMD2: // splitscreen special
netconsole = nodetoplayer2[node];
/* FALLTHRU */
@ -5044,39 +5084,66 @@ static INT16 Consistancy(void)
return (INT16)(ret & 0xFFFF);
}
// confusing, but this DOESN'T send PT_NODEKEEPALIVE, it sends PT_BASICKEEPALIVE
// used during wipes to tell the server that a node is still connected
static void CL_SendClientKeepAlive(void)
{
netbuffer->packettype = PT_BASICKEEPALIVE;
HSendPacket(servernode, false, 0, 0);
}
static void SV_SendServerKeepAlive(void)
{
INT32 n;
for (n = 1; n < MAXNETNODES; n++)
{
if (nodeingame[n])
{
netbuffer->packettype = PT_BASICKEEPALIVE;
HSendPacket(n, false, 0, 0);
}
}
}
// send the client packet to the server
static void CL_SendClientCmd(void)
{
size_t packetsize = 0;
boolean mis = false;
netbuffer->packettype = PT_CLIENTCMD;
if (cl_packetmissed)
netbuffer->packettype++;
{
netbuffer->packettype = PT_CLIENTMIS;
mis = true;
}
netbuffer->u.clientpak.resendfrom = (UINT8)(neededtic & UINT8_MAX);
netbuffer->u.clientpak.client_tic = (UINT8)(gametic & UINT8_MAX);
if (gamestate == GS_WAITINGPLAYERS)
{
// Send PT_NODEKEEPALIVE packet
netbuffer->packettype += 4;
netbuffer->packettype = (mis ? PT_NODEKEEPALIVEMIS : PT_NODEKEEPALIVE);
packetsize = sizeof (clientcmd_pak) - sizeof (ticcmd_t) - sizeof (INT16);
HSendPacket(servernode, false, 0, packetsize);
}
else if (gamestate != GS_NULL && (addedtogame || dedicated))
{
packetsize = sizeof (clientcmd_pak);
G_MoveTiccmd(&netbuffer->u.clientpak.cmd, &localcmds, 1);
netbuffer->u.clientpak.consistancy = SHORT(consistancy[gametic%BACKUPTICS]);
// Send a special packet with 2 cmd for splitscreen
if (splitscreen || botingame)
{
netbuffer->packettype += 2;
G_MoveTiccmd(&netbuffer->u.client2pak.cmd2, &localcmds2, 1);
netbuffer->packettype = (mis ? PT_CLIENT2MIS : PT_CLIENT2CMD);
packetsize = sizeof (client2cmd_pak);
G_MoveTiccmd(&netbuffer->u.client2pak.cmd2, &localcmds2, 1);
}
else
packetsize = sizeof (clientcmd_pak);
HSendPacket(servernode, false, 0, packetsize);
}
@ -5087,7 +5154,7 @@ static void CL_SendClientCmd(void)
if (localtextcmd[0])
{
netbuffer->packettype = PT_TEXTCMD;
M_Memcpy(netbuffer->u.textcmd,localtextcmd, localtextcmd[0]+1);
M_Memcpy(netbuffer->u.textcmd, localtextcmd, localtextcmd[0]+1);
// All extra data have been sent
if (HSendPacket(servernode, true, 0, localtextcmd[0]+1)) // Send can fail...
localtextcmd[0] = 0;
@ -5467,28 +5534,11 @@ static inline void PingUpdate(void)
pingmeasurecount = 1; //Reset count
}
void NetUpdate(void)
static tic_t gametime = 0;
static void UpdatePingTable(void)
{
static tic_t gametime = 0;
static tic_t resptime = 0;
tic_t nowtime;
INT32 i;
INT32 realtics;
nowtime = I_GetTime();
realtics = nowtime - gametime;
if (realtics <= 0) // nothing new to update
return;
if (realtics > 5)
{
if (server)
realtics = 1;
else
realtics = 5;
}
gametime = nowtime;
if (server)
{
@ -5500,6 +5550,150 @@ void NetUpdate(void)
realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i]));
pingmeasurecount++;
}
}
// Handle timeouts to prevent definitive freezes from happenning
static void HandleNodeTimeouts(void)
{
INT32 i;
if (server)
{
for (i = 1; i < MAXNETNODES; i++)
if (nodeingame[i] && freezetimeout[i] < I_GetTime())
Net_ConnectionTimeout(i);
// In case the cvar value was lowered
if (joindelay)
joindelay = min(joindelay - 1, 3 * (tic_t)cv_joindelay.value * TICRATE);
}
}
// Keep the network alive while not advancing tics!
void NetKeepAlive(void)
{
tic_t nowtime;
INT32 realtics;
nowtime = I_GetTime();
realtics = nowtime - gametime;
// return if there's no time passed since the last call
if (realtics <= 0) // nothing new to update
return;
UpdatePingTable();
GetPackets();
#ifdef MASTERSERVER
MasterClient_Ticker();
#endif
if (client)
{
// send keep alive
CL_SendClientKeepAlive();
// No need to check for resynch because we aren't running any tics
}
else
{
SV_SendServerKeepAlive();
}
// No else because no tics are being run and we can't resynch during this
Net_AckTicker();
HandleNodeTimeouts();
FileSendTicker();
}
void NetUpdate(void)
{
static tic_t resptime = 0;
tic_t nowtime;
INT32 i;
INT32 realtics;
nowtime = I_GetTime();
realtics = nowtime - gametime;
if (realtics <= 0) // nothing new to update
return;
if (realtics > 5)
{
if (server)
realtics = 1;
else
realtics = 5;
}
if (server && dedicated && gamestate == GS_LEVEL)
{
const tic_t dedicatedidletime = cv_dedicatedidletime.value * TICRATE;
static tic_t dedicatedidletimeprev = 0;
static tic_t dedicatedidle = 0;
if (dedicatedidletime > 0)
{
for (i = 1; i < MAXNETNODES; ++i)
if (nodeingame[i])
{
if (dedicatedidle >= dedicatedidletime)
{
CONS_Printf("DEDICATED: Awakening from idle (Node %d detected...)\n", i);
dedicatedidle = 0;
}
break;
}
if (i == MAXNETNODES)
{
if (leveltime == 2)
{
// On next tick...
dedicatedidle = dedicatedidletime-1;
}
else if (dedicatedidle >= dedicatedidletime)
{
if (D_GetExistingTextcmd(gametic, 0) || D_GetExistingTextcmd(gametic+1, 0))
{
CONS_Printf("DEDICATED: Awakening from idle (Netxcmd detected...)\n");
dedicatedidle = 0;
}
else
{
realtics = 0;
}
}
else if ((dedicatedidle += realtics) >= dedicatedidletime)
{
const char *idlereason = "at round start";
if (leveltime > 3)
idlereason = va("for %d seconds", dedicatedidle/TICRATE);
CONS_Printf("DEDICATED: No nodes %s, idling...\n", idlereason);
realtics = 0;
dedicatedidle = dedicatedidletime;
}
}
}
else
{
if (dedicatedidletimeprev > 0 && dedicatedidle >= dedicatedidletimeprev)
{
CONS_Printf("DEDICATED: Awakening from idle (Idle disabled...)\n");
}
dedicatedidle = 0;
}
dedicatedidletimeprev = dedicatedidletime;
}
gametime = nowtime;
UpdatePingTable();
if (client)
maketic = neededtic;
@ -5531,25 +5725,26 @@ void NetUpdate(void)
}
else
{
if (!demoplayback)
if (!demoplayback && realtics > 0)
{
INT32 counts;
hu_redownloadinggamestate = false;
firstticstosend = gametic;
for (i = 0; i < MAXNETNODES; i++)
if (nodeingame[i] && nettics[i] < firstticstosend)
{
firstticstosend = nettics[i];
if (maketic + 1 >= nettics[i] + BACKUPTICS)
Net_ConnectionTimeout(i);
}
// Don't erase tics not acknowledged
counts = realtics;
firstticstosend = gametic;
for (i = 0; i < MAXNETNODES; i++)
{
if (!nodeingame[i])
continue;
if (nettics[i] < firstticstosend)
firstticstosend = nettics[i];
if (maketic + counts >= nettics[i] + (BACKUPTICS - TICRATE))
Net_ConnectionTimeout(i);
}
if (maketic + counts >= firstticstosend + BACKUPTICS)
counts = firstticstosend+BACKUPTICS-maketic-1;
@ -5566,20 +5761,10 @@ void NetUpdate(void)
}
Net_AckTicker();
// Handle timeouts to prevent definitive freezes from happenning
if (server)
{
for (i = 1; i < MAXNETNODES; i++)
if (nodeingame[i] && freezetimeout[i] < I_GetTime())
Net_ConnectionTimeout(i);
// In case the cvar value was lowered
if (joindelay)
joindelay = min(joindelay - 1, 3 * (tic_t)cv_joindelay.value * TICRATE);
}
HandleNodeTimeouts();
nowtime /= NEWTICRATERATIO;
if (nowtime > resptime)
{
resptime = nowtime;

View file

@ -77,6 +77,8 @@ typedef enum
PT_ASKLUAFILE, // Client telling the server they don't have the file
PT_HASLUAFILE, // Client telling the server they have the file
PT_BASICKEEPALIVE,// Keep the network alive during wipes, as tics aren't advanced and NetUpdate isn't called
// Add non-PT_CANFAIL packet types here to avoid breaking MS compatibility.
PT_CANFAIL, // This is kind of a priority. Anything bigger than CANFAIL
@ -158,6 +160,7 @@ typedef struct
UINT8 gametype;
UINT8 modifiedgame;
UINT8 usedCheats;
char server_context[8]; // Unique context id, generated at server startup.
} ATTRPACK serverconfig_pak;
@ -397,6 +400,7 @@ extern tic_t servermaxping;
extern consvar_t cv_netticbuffer, cv_allownewplayer, cv_joinnextround, cv_maxplayers, cv_joindelay, cv_rejointimeout;
extern consvar_t cv_resynchattempts, cv_blamecfail;
extern consvar_t cv_maxsend, cv_noticedownload, cv_downloadspeed;
extern consvar_t cv_dedicatedidletime;
// Used in d_net, the only dependence
tic_t ExpandTics(INT32 low, INT32 node);
@ -411,6 +415,9 @@ void SendKick(UINT8 playernum, UINT8 msg);
// Create any new ticcmds and broadcast to other players.
void NetUpdate(void);
// Maintain connections to nodes without timing them all out.
void NetKeepAlive(void);
void SV_StartSinglePlayerServer(void);
boolean SV_SpawnServer(void);
void SV_StopServer(void);

View file

@ -70,6 +70,8 @@
#include "filesrch.h" // refreshdirmenu
#include "g_input.h" // tutorial mode control scheming
#include "m_perfstats.h"
#include "m_random.h"
#include "command.h"
#ifdef CMAKECONFIG
#include "config.h"
@ -458,6 +460,13 @@ static void D_Display(void)
case GS_WAITINGPLAYERS:
// The clientconnect drawer is independent...
if (netgame)
{
// I don't think HOM from nothing drawing is independent...
F_WaitingPlayersDrawer();
HU_Erase();
HU_Drawer();
}
case GS_DEDICATEDSERVER:
case GS_NULL:
break;
@ -1208,6 +1217,15 @@ D_ConvertVersionNumbers (void)
#endif
}
static void Command_assert(void)
{
#if !defined(NDEBUG) || defined(PARANOIA)
CONS_Printf("Yes, assertions are enabled.\n");
#else
CONS_Printf("No, assertions are NOT enabled.\n");
#endif
}
//
// D_SRB2Main
//
@ -1221,6 +1239,11 @@ void D_SRB2Main(void)
/* break the version string into version numbers, for netplay */
D_ConvertVersionNumbers();
if (!strcmp(compbranch, ""))
{
compbranch = "detached HEAD";
}
// Print GPL notice for our console users (Linux)
CONS_Printf(
"\n\nSonic Robo Blast 2\n"
@ -1334,11 +1357,12 @@ void D_SRB2Main(void)
snprintf(addonsdir, sizeof addonsdir, "%s%s%s", srb2home, PATHSEP, "addons");
I_mkdir(addonsdir, 0755);
// rand() needs seeded regardless of password
srand((unsigned int)time(NULL));
rand();
rand();
rand();
// seed M_Random because it is necessary; seed P_Random for scripts that
// might want to use random numbers immediately at start
if (!M_RandomSeedFromOS())
M_RandomSeed((UINT32)time(NULL)); // less good but serviceable
P_SetRandSeed(M_RandomizedSeed());
if (M_CheckParm("-password") && M_IsNextParm())
D_SetPassword(M_GetNextParm());
@ -1350,9 +1374,14 @@ void D_SRB2Main(void)
CONS_Printf("Z_Init(): Init zone memory allocation daemon. \n");
Z_Init();
clientGamedata = M_NewGameDataStruct();
serverGamedata = M_NewGameDataStruct();
// Do this up here so that WADs loaded through the command line can use ExecCfg
COM_Init();
COM_AddCommand("assert", Command_assert, COM_LUA);
// Add any files specified on the command line with
// "-file <file>" or "-folder <folder>" to the add-on list
if (!((M_GetUrlProtocolArg() || M_CheckParm("-connect")) && !M_CheckParm("-server")))
@ -1473,7 +1502,15 @@ void D_SRB2Main(void)
//--------------------------------------------------------- CONFIG.CFG
M_FirstLoadConfig(); // WARNING : this do a "COM_BufExecute()"
G_LoadGameData();
if (M_CheckParm("-gamedata") && M_IsNextParm())
{
// Moved from G_LoadGameData itself, as it would cause some crazy
// confusion issues when loading mods.
strlcpy(gamedatafilename, M_GetNextParm(), sizeof gamedatafilename);
}
G_LoadGameData(clientGamedata);
M_CopyGameData(serverGamedata, clientGamedata);
#if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL)
VID_PrepareModeList(); // Regenerate Modelist according to cv_fullscreen
@ -1500,7 +1537,7 @@ void D_SRB2Main(void)
else
{
if (!M_CheckParm("-server"))
G_SetGameModified(true);
G_SetUsedCheats(true);
autostart = true;
}
}
@ -1700,14 +1737,15 @@ void D_SRB2Main(void)
// Prevent warping to nonexistent levels
if (W_CheckNumForName(G_BuildMapName(pstartmap)) == LUMPERROR)
I_Error("Could not warp to %s (map not found)\n", G_BuildMapName(pstartmap));
// Prevent warping to locked levels
// ... unless you're in a dedicated server. Yes, technically this means you can view any level by
// running a dedicated server and joining it yourself, but that's better than making dedicated server's
// lives hell.
else if (!dedicated && M_MapLocked(pstartmap))
I_Error("You need to unlock this level before you can warp to it!\n");
else
{
if (M_CampaignWarpIsCheat(gametype, pstartmap, serverGamedata))
{
// If you're warping via command line, you know what you're doing.
// No need to I_Error over this.
G_SetUsedCheats(false);
}
D_MapChange(pstartmap, gametype, ultimatemode, true, 0, false, false);
}
}
@ -1777,3 +1815,85 @@ const char *D_Home(void)
if (usehome) return userhome;
else return NULL;
}
static boolean check_top_dir(const char **path, const char *top)
{
// empty string does NOT match
if (!strcmp(top, ""))
return false;
if (!startswith(*path, top))
return false;
*path += strlen(top);
// if it doesn't already end with a path separator,
// check if a separator follows
if (!endswith(top, PATHSEP))
{
if (startswith(*path, PATHSEP))
*path += strlen(PATHSEP);
else
return false;
}
return true;
}
static int cmp_strlen_desc(const void *a, const void *b)
{
return ((int)strlen(*(const char*const*)b) - (int)strlen(*(const char*const*)a));
}
boolean D_IsPathAllowed(const char *path)
{
const char *paths[] = {
srb2home,
srb2path,
cv_addons_folder.string
};
const size_t n_paths = sizeof paths / sizeof *paths;
size_t i;
// Sort folder paths by longest to shortest so
// overlapping paths work. E.g.:
// Path 1: /home/james/.srb2/addons
// Path 2: /home/james/.srb2
qsort(paths, n_paths, sizeof *paths, cmp_strlen_desc);
// These paths are allowed to be absolute
// path is offset so ".." can be checked only in the
// rest of the path
for (i = 0; i < n_paths; ++i)
{
if (check_top_dir(&path, paths[i]))
break;
}
// Only if none of the presets matched
if (i == n_paths)
{
// Cannot be an absolute path
if (M_IsPathAbsolute(path))
return false;
}
// Cannot traverse upwards
if (strstr(path, ".."))
return false;
return true;
}
boolean D_CheckPathAllowed(const char *path, const char *why)
{
if (!D_IsPathAllowed(path))
{
CONS_Alert(CONS_WARNING, "%s: %s, location is not allowed\n", why, path);
return false;
}
return true;
}

View file

@ -44,6 +44,9 @@ void D_ProcessEvents(void);
const char *D_Home(void);
boolean D_IsPathAllowed(const char *path);
boolean D_CheckPathAllowed(const char *path, const char *why);
//
// BASE LEVEL
//

View file

@ -869,6 +869,9 @@ static void DebugPrintpacket(const char *header)
(UINT32)ExpandTics(netbuffer->u.clientpak.client_tic, doomcom->remotenode),
(UINT32)ExpandTics (netbuffer->u.clientpak.resendfrom, doomcom->remotenode));
break;
case PT_BASICKEEPALIVE:
fprintf(debugfile, " wipetime\n");
break;
case PT_TEXTCMD:
case PT_TEXTCMD2:
fprintf(debugfile, " length %d\n ", netbuffer->u.textcmd[0]);
@ -1207,26 +1210,32 @@ static void Internal_FreeNodenum(INT32 nodenum)
(void)nodenum;
}
char *I_NetSplitAddress(char *host, char **port)
{
boolean v4 = (strchr(host, '.') != NULL);
host = strtok(host, v4 ? ":" : "[]");
if (port)
*port = strtok(NULL, ":");
return host;
}
SINT8 I_NetMakeNode(const char *hostname)
{
SINT8 newnode = -1;
if (I_NetMakeNodewPort)
{
char *localhostname = strdup(hostname);
char *t = localhostname;
const char *port;
char *port;
if (!localhostname)
return newnode;
// retrieve portnum from address!
strtok(localhostname, ":");
port = strtok(NULL, ":");
hostname = I_NetSplitAddress(localhostname, &port);
// remove the port in the hostname as we've it already
while ((*t != ':') && (*t != '\0'))
t++;
*t = '\0';
newnode = I_NetMakeNodewPort(localhostname, port);
newnode = I_NetMakeNodewPort(hostname, port);
free(localhostname);
}
return newnode;

View file

@ -49,7 +49,7 @@
#include "m_anigif.h"
#include "md5.h"
#include "m_perfstats.h"
#include "hardware/u_list.h" // TODO: this should be a standard utility class
#include "u_list.h"
#ifdef NETGAME_DEVMODE
#define CV_RESTRICT CV_NETVAR
@ -599,6 +599,7 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_joinnextround);
CV_RegisterVar(&cv_showjoinaddress);
CV_RegisterVar(&cv_blamecfail);
CV_RegisterVar(&cv_dedicatedidletime);
#endif
COM_AddCommand("ping", Command_Ping_f, COM_LUA);
@ -613,6 +614,10 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_allowseenames);
// Other filesrch.c consvars are defined in D_RegisterClientCommands
CV_RegisterVar(&cv_addons_option);
CV_RegisterVar(&cv_addons_folder);
CV_RegisterVar(&cv_dummyconsvar);
}
@ -771,6 +776,8 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_showfocuslost);
CV_RegisterVar(&cv_pauseifunfocused);
CV_RegisterVar(&cv_instantretry);
// g_input.c
CV_RegisterVar(&cv_sideaxis);
CV_RegisterVar(&cv_sideaxis2);
@ -794,8 +801,8 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_digitaldeadzone2);
// filesrch.c
CV_RegisterVar(&cv_addons_option);
CV_RegisterVar(&cv_addons_folder);
//CV_RegisterVar(&cv_addons_option); // These two are now defined
//CV_RegisterVar(&cv_addons_folder); // in D_RegisterServerCommands
CV_RegisterVar(&cv_addons_md5);
CV_RegisterVar(&cv_addons_showall);
CV_RegisterVar(&cv_addons_search_type);
@ -869,10 +876,15 @@ void D_RegisterClientCommands(void)
// screen.c
CV_RegisterVar(&cv_fullscreen);
CV_RegisterVar(&cv_renderview);
CV_RegisterVar(&cv_renderhitboxinterpolation);
CV_RegisterVar(&cv_renderhitboxgldepth);
CV_RegisterVar(&cv_renderhitbox);
CV_RegisterVar(&cv_renderer);
CV_RegisterVar(&cv_scr_depth);
CV_RegisterVar(&cv_scr_width);
CV_RegisterVar(&cv_scr_height);
CV_RegisterVar(&cv_scr_width_w);
CV_RegisterVar(&cv_scr_height_w);
CV_RegisterVar(&cv_soundtest);
@ -1633,9 +1645,14 @@ static void Command_Playdemo_f(void)
{
char name[256];
if (COM_Argc() != 2)
if (COM_Argc() < 2)
{
CONS_Printf(M_GetText("playdemo <demoname>: playback a demo\n"));
CONS_Printf("playdemo <demoname> [-addfiles / -force]:\n");
CONS_Printf(M_GetText(
"Play back a demo file. The full path from your SRB2 directory must be given.\n\n"
"* With \"-addfiles\", any required files are added from a list contained within the demo file.\n"
"* With \"-force\", the demo is played even if the necessary files have not been added.\n"));
return;
}
@ -1657,6 +1674,16 @@ static void Command_Playdemo_f(void)
CONS_Printf(M_GetText("Playing back demo '%s'.\n"), name);
demofileoverride = DFILE_OVERRIDE_NONE;
if (strcmp(COM_Argv(2), "-addfiles") == 0)
{
demofileoverride = DFILE_OVERRIDE_LOAD;
}
else if (strcmp(COM_Argv(2), "-force") == 0)
{
demofileoverride = DFILE_OVERRIDE_SKIP;
}
// Internal if no extension, external if one exists
// If external, convert the file name to a path in SRB2's home directory
if (FIL_CheckExtension(name))
@ -1877,8 +1904,8 @@ static void Command_Map_f(void)
size_t option_gametype;
const char *gametypename;
boolean newresetplayers;
boolean mustmodifygame;
boolean prevent_cheat;
boolean set_cheated;
INT32 newmapnum;
@ -1899,21 +1926,34 @@ static void Command_Map_f(void)
option_gametype = COM_CheckPartialParm("-g");
newresetplayers = ! COM_CheckParm("-noresetplayers");
mustmodifygame =
!( netgame || multiplayer ) &&
(!modifiedgame || savemoddata );
prevent_cheat = !( usedCheats ) && !( option_force || cv_debug );
set_cheated = false;
if (mustmodifygame && !option_force)
if (!( netgame || multiplayer ))
{
/* May want to be more descriptive? */
CONS_Printf(M_GetText("Sorry, level change disabled in single player.\n"));
return;
if (prevent_cheat)
{
/* May want to be more descriptive? */
CONS_Printf(M_GetText("Cheats must be enabled to level change in single player.\n"));
return;
}
else
{
set_cheated = true;
}
}
if (!newresetplayers && !cv_debug)
if (!newresetplayers)
{
CONS_Printf(M_GetText("DEVMODE must be enabled.\n"));
return;
if (prevent_cheat)
{
CONS_Printf(M_GetText("Cheats must be enabled to use -noresetplayers.\n"));
return;
}
else
{
set_cheated = true;
}
}
if (option_gametype)
@ -1921,7 +1961,7 @@ static void Command_Map_f(void)
if (!multiplayer)
{
CONS_Printf(M_GetText(
"You can't switch gametypes in single player!\n"));
"You can't switch gametypes in single player!\n"));
return;
}
else if (COM_Argc() < option_gametype + 2)/* no argument after? */
@ -1934,7 +1974,9 @@ static void Command_Map_f(void)
}
if (!( first_option = COM_FirstOption() ))
{
first_option = COM_Argc();
}
if (first_option < 2)
{
@ -1957,11 +1999,6 @@ static void Command_Map_f(void)
return;
}
if (mustmodifygame && option_force)
{
G_SetGameModified(false);
}
// new gametype value
// use current one by default
if (option_gametype)
@ -2003,15 +2040,13 @@ static void Command_Map_f(void)
}
// don't use a gametype the map doesn't support
if (cv_debug || option_force || cv_skipmapcheck.value)
fromlevelselect = false; // The player wants us to trek on anyway. Do so.
// G_TOLFlag handles both multiplayer gametype and ignores it for !multiplayer
else
if (!(
mapheaderinfo[newmapnum-1] &&
mapheaderinfo[newmapnum-1]->typeoflevel & G_TOLFlag(newgametype)
))
{
if (!(
mapheaderinfo[newmapnum-1] &&
mapheaderinfo[newmapnum-1]->typeoflevel & G_TOLFlag(newgametype)
))
if (prevent_cheat && !cv_skipmapcheck.value)
{
CONS_Alert(CONS_WARNING, M_GetText("%s (%s) doesn't support %s mode!\n(Use -force to override)\n"), realmapname, G_BuildMapName(newmapnum),
(multiplayer ? gametype_cons_t[newgametype].strvalue : "Single Player"));
@ -2021,23 +2056,33 @@ static void Command_Map_f(void)
}
else
{
fromlevelselect =
( netgame || multiplayer ) &&
newgametype == gametype &&
gametypedefaultrules[newgametype] & GTR_CAMPAIGN;
// The player wants us to trek on anyway. Do so.
fromlevelselect = false;
set_cheated = ((gametypedefaultrules[newgametype] & GTR_CAMPAIGN) == GTR_CAMPAIGN);
}
}
else
{
fromlevelselect =
( netgame || multiplayer ) &&
newgametype == gametype &&
(gametypedefaultrules[newgametype] & GTR_CAMPAIGN);
}
// Prevent warping to locked levels
// ... unless you're in a dedicated server. Yes, technically this means you can view any level by
// running a dedicated server and joining it yourself, but that's better than making dedicated server's
// lives hell.
if (!dedicated && M_MapLocked(newmapnum))
if (M_CampaignWarpIsCheat(newgametype, newmapnum, serverGamedata))
{
CONS_Alert(CONS_NOTICE, M_GetText("You need to unlock this level before you can warp to it!\n"));
Z_Free(realmapname);
Z_Free(mapname);
return;
if (prevent_cheat)
{
CONS_Alert(CONS_NOTICE, M_GetText("Cheats must be enabled to warp to a locked level!\n"));
Z_Free(realmapname);
Z_Free(mapname);
return;
}
else
{
set_cheated = true;
}
}
// Ultimate Mode only in SP via menu
@ -2054,6 +2099,11 @@ static void Command_Map_f(void)
}
tutorialmode = false; // warping takes us out of tutorial mode
if (set_cheated && !usedCheats)
{
G_SetUsedCheats(false);
}
D_MapChange(newmapnum, newgametype, false, newresetplayers, 0, false, fromlevelselect);
Z_Free(realmapname);
@ -2095,11 +2145,13 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
lastgametype = gametype;
gametype = READUINT8(*cp);
G_SetGametype(gametype); // I fear putting that macro as an argument
if (gametype < 0 || gametype >= gametypecount)
gametype = lastgametype;
else if (gametype != lastgametype)
else
G_SetGametype(gametype);
if (gametype != lastgametype)
D_GameTypeChanged(lastgametype); // emulate consvar_t behavior for gametype
skipprecutscene = ((flags & (1<<2)) != 0);
@ -2121,12 +2173,6 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
if (demoplayback && !timingdemo)
precache = false;
if (resetplayer && !FLS)
{
emeralds = 0;
memset(&luabanks, 0, sizeof(luabanks));
}
if (modeattacking)
{
SetPlayerSkinByNum(0, cv_chooseskin.value-1);
@ -2167,7 +2213,7 @@ static void Command_Pause(void)
if (cv_pause.value || server || (IsPlayerAdmin(consoleplayer)))
{
if (modeattacking || !(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) || (marathonmode && gamestate == GS_INTERMISSION))
if (modeattacking || !(gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_WAITINGPLAYERS) || (marathonmode && gamestate == GS_INTERMISSION))
{
CONS_Printf(M_GetText("You can't pause here.\n"));
return;
@ -2330,7 +2376,7 @@ static void Got_Clearscores(UINT8 **cp, INT32 playernum)
}
for (i = 0; i < MAXPLAYERS; i++)
players[i].score = 0;
players[i].score = players[i].recordscore = 0;
CONS_Printf(M_GetText("Scores have been reset by the server.\n"));
}
@ -3834,7 +3880,7 @@ static void Command_ListWADS_f(void)
static void Command_Version_f(void)
{
#ifdef DEVELOP
CONS_Printf("Sonic Robo Blast 2 %s-%s (%s %s) ", compbranch, comprevision, compdate, comptime);
CONS_Printf("Sonic Robo Blast 2 %s %s %s (%s %s) ", compbranch, comprevision, compnote, compdate, comptime);
#else
CONS_Printf("Sonic Robo Blast 2 %s (%s %s %s %s) ", VERSIONSTRING, compdate, comptime, comprevision, compbranch);
#endif
@ -3868,11 +3914,6 @@ static void Command_Version_f(void)
else // 16-bit? 128-bit?
CONS_Printf("Bits Unknown ");
// No ASM?
#ifdef NOASM
CONS_Printf("\x85" "NOASM " "\x80");
#endif
// Debug build
#ifdef _DEBUG
CONS_Printf("\x85" "DEBUG " "\x80");
@ -3941,18 +3982,12 @@ void ItemFinder_OnChange(void)
if (!cv_itemfinder.value)
return; // it's fine.
if (!M_SecretUnlocked(SECRET_ITEMFINDER))
if (!M_SecretUnlocked(SECRET_ITEMFINDER, clientGamedata))
{
CONS_Printf(M_GetText("You haven't earned this yet.\n"));
CV_StealthSetValue(&cv_itemfinder, 0);
return;
}
else if (netgame || multiplayer)
{
CONS_Printf(M_GetText("This only works in single player.\n"));
CV_StealthSetValue(&cv_itemfinder, 0);
return;
}
}
/** Deals with a pointlimit change by printing the change to the console.
@ -4244,9 +4279,6 @@ void D_GameTypeChanged(INT32 lastgametype)
else if (!multiplayer && !netgame)
{
G_SetGametype(GT_COOP);
// These shouldn't matter anymore
//CV_Set(&cv_itemrespawntime, cv_itemrespawntime.defaultvalue);
//CV_SetValue(&cv_itemrespawn, 0);
}
// reset timelimit and pointlimit in race/coop, prevent stupid cheats
@ -4301,7 +4333,7 @@ void D_GameTypeChanged(INT32 lastgametype)
static void Ringslinger_OnChange(void)
{
if (!M_SecretUnlocked(SECRET_PANDORA) && !netgame && cv_ringslinger.value && !cv_debug)
if (!M_SecretUnlocked(SECRET_PANDORA, serverGamedata) && !netgame && cv_ringslinger.value && !cv_debug)
{
CONS_Printf(M_GetText("You haven't earned this yet.\n"));
CV_StealthSetValue(&cv_ringslinger, 0);
@ -4309,12 +4341,12 @@ static void Ringslinger_OnChange(void)
}
if (cv_ringslinger.value) // Only if it's been turned on
G_SetGameModified(multiplayer);
G_SetUsedCheats(false);
}
static void Gravity_OnChange(void)
{
if (!M_SecretUnlocked(SECRET_PANDORA) && !netgame && !cv_debug
if (!M_SecretUnlocked(SECRET_PANDORA, serverGamedata) && !netgame && !cv_debug
&& strcmp(cv_gravity.string, cv_gravity.defaultvalue))
{
CONS_Printf(M_GetText("You haven't earned this yet.\n"));
@ -4330,7 +4362,7 @@ static void Gravity_OnChange(void)
#endif
if (!CV_IsSetToDefault(&cv_gravity))
G_SetGameModified(multiplayer);
G_SetUsedCheats(false);
gravity = cv_gravity.value;
}
@ -4547,25 +4579,37 @@ static void Command_Mapmd5_f(void)
CONS_Printf(M_GetText("You must be in a level to use this.\n"));
}
void D_SendExitLevel(boolean cheat)
{
UINT8 buf[8];
UINT8 *buf_p = buf;
WRITEUINT8(buf_p, cheat);
SendNetXCmd(XD_EXITLEVEL, &buf, buf_p - buf);
}
static void Command_ExitLevel_f(void)
{
if (!(netgame || (multiplayer && gametype != GT_COOP)) && !cv_debug)
CONS_Printf(M_GetText("This only works in a netgame.\n"));
else if (!(server || (IsPlayerAdmin(consoleplayer))))
if (!(server || (IsPlayerAdmin(consoleplayer))))
CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
else if (( gamestate != GS_LEVEL && gamestate != GS_CREDITS ) || demoplayback)
CONS_Printf(M_GetText("You must be in a level to use this.\n"));
else
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
D_SendExitLevel(true);
}
static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum)
{
(void)cp;
boolean cheat = false;
cheat = (boolean)READUINT8(*cp);
// Ignore duplicate XD_EXITLEVEL commands.
if (gameaction == ga_completed)
{
return;
}
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
{
@ -4575,6 +4619,11 @@ static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum)
return;
}
if (G_CoopGametype() && cheat)
{
G_SetUsedCheats(false);
}
G_ExitLevel();
}
@ -4611,6 +4660,7 @@ void Command_ExitGame_f(void)
botskin = 0;
cv_debug = 0;
emeralds = 0;
automapactive = false;
memset(&luabanks, 0, sizeof(luabanks));
if (dirmenu)
@ -4646,7 +4696,7 @@ static void Fishcake_OnChange(void)
// so don't make modifiedgame always on!
if (cv_debug)
{
G_SetGameModified(multiplayer);
G_SetUsedCheats(false);
}
else if (cv_debug != cv_fishcake.value)
@ -4663,11 +4713,11 @@ static void Fishcake_OnChange(void)
static void Command_Isgamemodified_f(void)
{
if (savemoddata)
CONS_Printf(M_GetText("modifiedgame is true, but you can save emblem and time data in this mod.\n"));
CONS_Printf(M_GetText("modifiedgame is true, but you can save time data in this mod.\n"));
else if (modifiedgame)
CONS_Printf(M_GetText("modifiedgame is true, extras will not be unlocked\n"));
CONS_Printf(M_GetText("modifiedgame is true, time data can't be saved\n"));
else
CONS_Printf(M_GetText("modifiedgame is false, you can unlock extras\n"));
CONS_Printf(M_GetText("modifiedgame is false, you can save time data\n"));
}
static void Command_Cheats_f(void)

View file

@ -201,6 +201,7 @@ void D_SendPlayerConfig(void);
void Command_ExitGame_f(void);
void Command_Retry_f(void);
void D_GameTypeChanged(INT32 lastgametype); // not a real _OnChange function anymore
void D_SendExitLevel(boolean cheat);
void D_MapChange(INT32 pmapnum, INT32 pgametype, boolean pultmode, boolean presetplayers, INT32 pdelay, boolean pskipprecutscene, boolean pfromlevelselect);
boolean IsPlayerAdmin(INT32 playernum);
void SetAdminPlayer(INT32 playernum);

View file

@ -498,7 +498,7 @@ INT32 CL_CheckFiles(void)
CONS_Debug(DBG_NETPLAY, "searching for '%s' ", fileneeded[i].filename);
// Check in already loaded files
for (j = mainwads; wadfiles[j]; j++)
for (j = mainwads; j < numwadfiles; j++)
{
nameonly(strcpy(wadfilename, wadfiles[j]->filename));
if (!stricmp(wadfilename, fileneeded[i].filename) &&

View file

@ -249,6 +249,38 @@ typedef enum
CR_FAN
} carrytype_t; // pw_carry
typedef enum
{
STR_NONE = 0, // All strong powers can stack onto each other
// Attack powers
STR_ANIM = 0x1, // remove powers when leaving current animation
STR_PUNCH = 0x2, // frontal attack (knuckles glide)
STR_TAIL = 0x4, // rear attack
STR_STOMP = 0x8, // falling onto object (fang bounce)
STR_UPPER = 0x10, // moving upwards into object (tails fly)
STR_GUARD = 0x20, //protect against damage
STR_HEAVY = 0x40, // ignore vertical rebound
STR_DASH = 0x80, // special type for machine dashmode, automatically removes your powers when leaving dashmode
// Environment powers
STR_WALL = 0x100, // fof busting
STR_FLOOR = 0x200,
STR_CEILING = 0x400,
STR_SPRING = 0x800, // power up hit springs
STR_SPIKE = 0x1000, // break spikes
// Shortcuts
STR_ATTACK = STR_PUNCH|STR_TAIL|STR_STOMP|STR_UPPER,
STR_BUST = STR_WALL|STR_FLOOR|STR_CEILING,
STR_FLY = STR_ANIM|STR_UPPER,
STR_GLIDE = STR_ANIM|STR_PUNCH,
STR_TWINSPIN = STR_ANIM|STR_ATTACK|STR_BUST|STR_SPRING|STR_SPIKE,
STR_MELEE = STR_ANIM|STR_PUNCH|STR_HEAVY|STR_WALL|STR_FLOOR|STR_SPRING|STR_SPIKE,
STR_BOUNCE = STR_ANIM|STR_STOMP|STR_FLOOR,
STR_METAL = STR_DASH|STR_SPIKE
} strongtype_t; // pw_strong
// Player powers. (don't edit this comment)
typedef enum
{
@ -293,6 +325,8 @@ typedef enum
pw_ignorelatch, // Don't grab onto CR_GENERIC, add 32768 (powers[pw_ignorelatch] & 1<<15) to avoid ALL not-NiGHTS CR_ types
pw_strong, // Additional properties for powerful attacks
NUMPOWERS
} powertype_t;
@ -407,6 +441,7 @@ typedef struct player_s
// playing animation.
panim_t panim;
UINT8 stronganim;
// For screen flashing (bright).
UINT16 flashcount;
@ -418,7 +453,8 @@ typedef struct player_s
INT32 skin;
UINT32 availabilities;
UINT32 score; // player score
UINT32 score; // player score (total)
UINT32 recordscore; // player score (per life / map)
fixed_t dashspeed; // dashing speed
fixed_t normalspeed; // Normal ground

View file

@ -17,6 +17,8 @@
#ifndef __D_THINK__
#define __D_THINK__
#include "doomdef.h"
#ifdef __GNUG__
#pragma interface
#endif
@ -49,6 +51,11 @@ typedef struct thinker_s
// killough 11/98: count of how many other objects reference
// this one using pointers. Used for garbage collection.
INT32 references;
#ifdef PARANOIA
INT32 debug_mobjtype;
tic_t debug_time;
#endif
} thinker_t;
#endif

View file

@ -10,20 +10,7 @@
/// \file deh_lua.c
/// \brief Lua SOC library
#include "g_game.h"
#include "s_sound.h"
#include "z_zone.h"
#include "m_menu.h"
#include "m_misc.h"
#include "p_local.h"
#include "st_stuff.h"
#include "fastcmp.h"
#include "lua_script.h"
#include "lua_libs.h"
#include "dehacked.h"
#include "deh_lua.h"
#include "deh_tables.h"
// freeslot takes a name (string only!)
// and allocates it to the appropriate free slot.
@ -89,6 +76,8 @@ static inline int lib_freeslot(lua_State *L)
strncpy(sprnames[j],word,4);
//sprnames[j][4] = 0;
used_spr[(j-SPR_FIRSTFREESLOT)/8] |= 1<<(j%8); // Okay, this sprite slot has been named now.
// Lua needs to update the value in _G if it exists
LUA_UpdateSprName(word, j);
lua_pushinteger(L, j);
r++;
break;
@ -188,6 +177,9 @@ static inline int lib_freeslot(lua_State *L)
lua_remove(L, 1);
continue;
}
R_RefreshSprite2();
return r;
}
@ -195,39 +187,54 @@ static inline int lib_freeslot(lua_State *L)
// Arguments: mobj_t actor, int var1, int var2
static int action_call(lua_State *L)
{
//actionf_t *action = lua_touserdata(L,lua_upvalueindex(1));
actionf_t *action = *((actionf_t **)luaL_checkudata(L, 1, META_ACTION));
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
var1 = (INT32)luaL_optinteger(L, 3, 0);
var2 = (INT32)luaL_optinteger(L, 4, 0);
if (!actor)
{
return LUA_ErrInvalid(L, "mobj_t");
}
action->acp1(actor);
return 0;
}
// Hardcoded A_Action name to call for super() or NULL if super() would be invalid.
// Set in lua_infolib.
const char *superactions[MAXRECURSION];
UINT8 superstack = 0;
const char *luaactions[MAX_ACTION_RECURSION];
UINT8 luaactionstack = 0;
static int lib_dummysuper(lua_State *L)
{
return luaL_error(L, "Can't call super() outside of hardcode-replacing A_Action functions being called by state changes!"); // convoluted, I know. @_@;;
// TODO: Now that the restriction on only being allowed in state changes was lifted,
// it'd be nice to have super extend to Lua A_ functions too :)
return luaL_error(L, "Can't call super() outside of hardcode-replacing A_Action functions!");
}
static inline int lib_getenum(lua_State *L)
static void CacheAndPushConstant(lua_State *L, const char *name, lua_Integer value)
{
const char *word, *p;
// "cache" into _G
lua_pushstring(L, name);
lua_pushinteger(L, value);
lua_rawset(L, LUA_GLOBALSINDEX);
// push
lua_pushinteger(L, value);
}
// Search for a matching constant variable.
// Result is stored into _G for faster subsequent use. (Except for SPR_ in the SOC parser)
static int ScanConstants(lua_State *L, boolean mathlib, const char *word)
{
const char *p;
fixed_t i;
boolean mathlib = lua_toboolean(L, lua_upvalueindex(1));
if (lua_type(L,2) != LUA_TSTRING)
return 0;
word = lua_tostring(L,2);
if (strlen(word) == 1) { // Assume sprite frame if length 1.
if (*word >= 'A' && *word <= '~')
{
lua_pushinteger(L, *word-'A');
CacheAndPushConstant(L, word, *word-'A');
return 1;
}
if (mathlib) return luaL_error(L, "constant '%s' could not be parsed.\n", word);
@ -237,7 +244,7 @@ static inline int lib_getenum(lua_State *L)
p = word+3;
for (i = 0; MOBJFLAG_LIST[i]; i++)
if (fastcmp(p, MOBJFLAG_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
CacheAndPushConstant(L, word, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "mobjflag '%s' could not be found.\n", word);
@ -247,7 +254,7 @@ static inline int lib_getenum(lua_State *L)
p = word+4;
for (i = 0; MOBJFLAG2_LIST[i]; i++)
if (fastcmp(p, MOBJFLAG2_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
CacheAndPushConstant(L, word, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "mobjflag2 '%s' could not be found.\n", word);
@ -257,12 +264,12 @@ static inline int lib_getenum(lua_State *L)
p = word+4;
for (i = 0; MOBJEFLAG_LIST[i]; i++)
if (fastcmp(p, MOBJEFLAG_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
CacheAndPushConstant(L, word, ((lua_Integer)1<<i));
return 1;
}
if (fastcmp(p, "REVERSESUPER"))
{
lua_pushinteger(L, (lua_Integer)MFE_REVERSESUPER);
CacheAndPushConstant(L, word, (lua_Integer)MFE_REVERSESUPER);
return 1;
}
if (mathlib) return luaL_error(L, "mobjeflag '%s' could not be found.\n", word);
@ -270,9 +277,9 @@ static inline int lib_getenum(lua_State *L)
}
else if (fastncmp("MTF_", word, 4)) {
p = word+4;
for (i = 0; i < 4; i++)
if (MAPTHINGFLAG_LIST[i] && fastcmp(p, MAPTHINGFLAG_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
for (i = 0; MAPTHINGFLAG_LIST[i]; i++)
if (fastcmp(p, MAPTHINGFLAG_LIST[i])) {
CacheAndPushConstant(L, word, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "mapthingflag '%s' could not be found.\n", word);
@ -282,17 +289,17 @@ static inline int lib_getenum(lua_State *L)
p = word+3;
for (i = 0; PLAYERFLAG_LIST[i]; i++)
if (fastcmp(p, PLAYERFLAG_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
CacheAndPushConstant(L, word, ((lua_Integer)1<<i));
return 1;
}
if (fastcmp(p, "FULLSTASIS"))
{
lua_pushinteger(L, (lua_Integer)PF_FULLSTASIS);
CacheAndPushConstant(L, word, (lua_Integer)PF_FULLSTASIS);
return 1;
}
else if (fastcmp(p, "USEDOWN")) // Remove case when 2.3 nears release...
{
lua_pushinteger(L, (lua_Integer)PF_SPINDOWN);
CacheAndPushConstant(L, word, (lua_Integer)PF_SPINDOWN);
return 1;
}
if (mathlib) return luaL_error(L, "playerflag '%s' could not be found.\n", word);
@ -302,7 +309,7 @@ static inline int lib_getenum(lua_State *L)
p = word;
for (i = 0; Gametype_ConstantNames[i]; i++)
if (fastcmp(p, Gametype_ConstantNames[i])) {
lua_pushinteger(L, i);
CacheAndPushConstant(L, word, i);
return 1;
}
if (mathlib) return luaL_error(L, "gametype '%s' could not be found.\n", word);
@ -312,7 +319,7 @@ static inline int lib_getenum(lua_State *L)
p = word+4;
for (i = 0; GAMETYPERULE_LIST[i]; i++)
if (fastcmp(p, GAMETYPERULE_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
CacheAndPushConstant(L, word, ((lua_Integer)1<<i));
return 1;
}
if (mathlib) return luaL_error(L, "game type rule '%s' could not be found.\n", word);
@ -322,7 +329,7 @@ static inline int lib_getenum(lua_State *L)
p = word+4;
for (i = 0; TYPEOFLEVEL[i].name; i++)
if (fastcmp(p, TYPEOFLEVEL[i].name)) {
lua_pushinteger(L, TYPEOFLEVEL[i].flag);
CacheAndPushConstant(L, word, TYPEOFLEVEL[i].flag);
return 1;
}
if (mathlib) return luaL_error(L, "typeoflevel '%s' could not be found.\n", word);
@ -330,9 +337,10 @@ static inline int lib_getenum(lua_State *L)
}
else if (fastncmp("ML_", word, 3)) {
p = word+3;
for (i = 0; ML_LIST[i]; i++)
if (fastcmp(p, ML_LIST[i])) {
lua_pushinteger(L, ((lua_Integer)1<<i));
CacheAndPushConstant(L, word, ((lua_Integer)1<<i));
return 1;
}
// Aliases
@ -415,13 +423,13 @@ static inline int lib_getenum(lua_State *L)
if (!FREE_STATES[i])
break;
if (fastcmp(p, FREE_STATES[i])) {
lua_pushinteger(L, S_FIRSTFREESLOT+i);
CacheAndPushConstant(L, word, S_FIRSTFREESLOT+i);
return 1;
}
}
for (i = 0; i < S_FIRSTFREESLOT; i++)
if (fastcmp(p, STATE_LIST[i]+2)) {
lua_pushinteger(L, i);
CacheAndPushConstant(L, word, i);
return 1;
}
return luaL_error(L, "state '%s' does not exist.\n", word);
@ -432,13 +440,13 @@ static inline int lib_getenum(lua_State *L)
if (!FREE_MOBJS[i])
break;
if (fastcmp(p, FREE_MOBJS[i])) {
lua_pushinteger(L, MT_FIRSTFREESLOT+i);
CacheAndPushConstant(L, word, MT_FIRSTFREESLOT+i);
return 1;
}
}
for (i = 0; i < MT_FIRSTFREESLOT; i++)
if (fastcmp(p, MOBJTYPE_LIST[i]+3)) {
lua_pushinteger(L, i);
CacheAndPushConstant(L, word, i);
return 1;
}
return luaL_error(L, "mobjtype '%s' does not exist.\n", word);
@ -447,7 +455,12 @@ static inline int lib_getenum(lua_State *L)
p = word+4;
for (i = 0; i < NUMSPRITES; i++)
if (!sprnames[i][4] && fastncmp(p,sprnames[i],4)) {
lua_pushinteger(L, i);
// updating overridden sprnames is not implemented for soc parser,
// so don't use cache
if (mathlib)
lua_pushinteger(L, i);
else
CacheAndPushConstant(L, word, i);
return 1;
}
if (mathlib) return luaL_error(L, "sprite '%s' could not be found.\n", word);
@ -462,12 +475,12 @@ static inline int lib_getenum(lua_State *L)
// the spr2names entry will have "_" on the end, as in "RUN_"
if (spr2names[i][3] == '_' && !p[3]) {
if (fastncmp(p,spr2names[i],3)) {
lua_pushinteger(L, i);
CacheAndPushConstant(L, word, i);
return 1;
}
}
else if (fastncmp(p,spr2names[i],4)) {
lua_pushinteger(L, i);
CacheAndPushConstant(L, word, i);
return 1;
}
}
@ -478,7 +491,7 @@ static inline int lib_getenum(lua_State *L)
p = word+4;
for (i = 0; i < NUMSFX; i++)
if (S_sfx[i].name && fastcmp(p, S_sfx[i].name)) {
lua_pushinteger(L, i);
CacheAndPushConstant(L, word, i);
return 1;
}
return 0;
@ -487,7 +500,7 @@ static inline int lib_getenum(lua_State *L)
p = word+4;
for (i = 0; i < NUMSFX; i++)
if (S_sfx[i].name && fasticmp(p, S_sfx[i].name)) {
lua_pushinteger(L, i);
CacheAndPushConstant(L, word, i);
return 1;
}
return luaL_error(L, "sfx '%s' could not be found.\n", word);
@ -496,7 +509,7 @@ static inline int lib_getenum(lua_State *L)
p = word+2;
for (i = 0; i < NUMSFX; i++)
if (S_sfx[i].name && fasticmp(p, S_sfx[i].name)) {
lua_pushinteger(L, i);
CacheAndPushConstant(L, word, i);
return 1;
}
if (mathlib) return luaL_error(L, "sfx '%s' could not be found.\n", word);
@ -506,7 +519,7 @@ static inline int lib_getenum(lua_State *L)
p = word+3;
for (i = 0; i < NUMPOWERS; i++)
if (fasticmp(p, POWERS_LIST[i])) {
lua_pushinteger(L, i);
CacheAndPushConstant(L, word, i);
return 1;
}
return 0;
@ -515,7 +528,7 @@ static inline int lib_getenum(lua_State *L)
p = word+3;
for (i = 0; i < NUMPOWERS; i++)
if (fastcmp(p, POWERS_LIST[i])) {
lua_pushinteger(L, i);
CacheAndPushConstant(L, word, i);
return 1;
}
return luaL_error(L, "power '%s' could not be found.\n", word);
@ -524,7 +537,7 @@ static inline int lib_getenum(lua_State *L)
p = word+4;
for (i = 0; i < NUMHUDITEMS; i++)
if (fastcmp(p, HUDITEMS_LIST[i])) {
lua_pushinteger(L, i);
CacheAndPushConstant(L, word, i);
return 1;
}
if (mathlib) return luaL_error(L, "huditem '%s' could not be found.\n", word);
@ -536,13 +549,13 @@ static inline int lib_getenum(lua_State *L)
if (!FREE_SKINCOLORS[i])
break;
if (fastcmp(p, FREE_SKINCOLORS[i])) {
lua_pushinteger(L, SKINCOLOR_FIRSTFREESLOT+i);
CacheAndPushConstant(L, word, SKINCOLOR_FIRSTFREESLOT+i);
return 1;
}
}
for (i = 0; i < SKINCOLOR_FIRSTFREESLOT; i++)
if (fastcmp(p, COLOR_ENUMS[i])) {
lua_pushinteger(L, i);
CacheAndPushConstant(L, word, i);
return 1;
}
return luaL_error(L, "skincolor '%s' could not be found.\n", word);
@ -553,7 +566,7 @@ static inline int lib_getenum(lua_State *L)
for (i = 0; NIGHTSGRADE_LIST[i]; i++)
if (*p == NIGHTSGRADE_LIST[i])
{
lua_pushinteger(L, i);
CacheAndPushConstant(L, word, i);
return 1;
}
if (mathlib) return luaL_error(L, "NiGHTS grade '%s' could not be found.\n", word);
@ -563,70 +576,127 @@ static inline int lib_getenum(lua_State *L)
p = word+3;
for (i = 0; i < NUMMENUTYPES; i++)
if (fastcmp(p, MENUTYPES_LIST[i])) {
lua_pushinteger(L, i);
CacheAndPushConstant(L, word, i);
return 1;
}
if (mathlib) return luaL_error(L, "menutype '%s' could not be found.\n", word);
return 0;
}
else if (!mathlib && fastncmp("A_",word,2)) {
char *caps;
// Try to get a Lua action first.
/// \todo Push a closure that sets superactions[] and superstack.
lua_getfield(L, LUA_REGISTRYINDEX, LREG_ACTIONS);
// actions are stored in all uppercase.
caps = Z_StrDup(word);
strupr(caps);
lua_getfield(L, -1, caps);
Z_Free(caps);
if (!lua_isnil(L, -1))
return 1; // Success! :D That was easy.
// Welp, that failed.
lua_pop(L, 2); // pop nil and LREG_ACTIONS
// Hardcoded actions as callable Lua functions!
// Retrieving them from this metatable allows them to be case-insensitive!
for (i = 0; actionpointers[i].name; i++)
if (fasticmp(word, actionpointers[i].name)) {
// We push the actionf_t* itself as userdata!
LUA_PushUserdata(L, &actionpointers[i].action, META_ACTION);
return 1;
}
return 0;
}
else if (!mathlib && fastcmp("super",word))
{
if (!superstack)
{
lua_pushcfunction(L, lib_dummysuper);
return 1;
}
for (i = 0; actionpointers[i].name; i++)
if (fasticmp(superactions[superstack-1], actionpointers[i].name)) {
LUA_PushUserdata(L, &actionpointers[i].action, META_ACTION);
return 1;
}
return 0;
}
if (fastcmp(word, "BT_USE")) // Remove case when 2.3 nears release...
{
lua_pushinteger(L, (lua_Integer)BT_SPIN);
CacheAndPushConstant(L, word, (lua_Integer)BT_SPIN);
return 1;
}
for (i = 0; INT_CONST[i].n; i++)
if (fastcmp(word,INT_CONST[i].n)) {
lua_pushinteger(L, INT_CONST[i].v);
CacheAndPushConstant(L, word, INT_CONST[i].v);
return 1;
}
return 0;
}
static inline int lib_getenum(lua_State *L)
{
const char *word;
fixed_t i;
boolean mathlib = lua_toboolean(L, lua_upvalueindex(1));
if (lua_type(L,2) != LUA_TSTRING)
return 0;
word = lua_tostring(L,2);
// check actions, super and globals first, as they don't have _G caching implemented
// so they benefit from being checked first
if (!mathlib && fastncmp("A_",word,2)) {
char *caps;
// Hardcoded actions come first.
// Trying to call them will invoke LUA_CallAction, which will handle super properly.
// Retrieving them from this metatable allows them to be case-insensitive!
for (i = 0; actionpointers[i].name; i++)
{
if (fasticmp(word, actionpointers[i].name))
{
// We push the actionf_t* itself as userdata!
LUA_PushUserdata(L, &actionpointers[i].action, META_ACTION);
return 1;
}
}
// Now try to get Lua actions.
/// \todo Push a closure that sets luaactions[] and luaactionstack.
/// This would be part one of a step to get super functions working for custom A_ functions.
/// Custom functions.
lua_getfield(L, LUA_REGISTRYINDEX, LREG_ACTIONS);
// actions are stored in all uppercase.
caps = Z_StrDup(word);
strupr(caps);
lua_getfield(L, -1, caps);
Z_Free(caps);
if (!lua_isnil(L, -1))
{
return 1; // Success! :D That was easy.
}
// Welp, that failed.
lua_pop(L, 2); // pop nil and LREG_ACTIONS
return 0;
}
else if (!mathlib && fastcmp("super",word))
{
if (!luaactionstack)
{
// Not in A_ action routine
lua_pushcfunction(L, lib_dummysuper);
return 1;
}
for (i = 0; actionpointers[i].name; i++)
{
if (fasticmp(luaactions[luaactionstack-1], actionpointers[i].name))
{
LUA_PushUserdata(L, &actionpointers[i].action, META_ACTION);
return 1;
}
}
// Not a hardcoded A_ action.
lua_pushcfunction(L, lib_dummysuper);
return 1;
}
else if ((!mathlib && LUA_PushGlobals(L, word)) || ScanConstants(L, mathlib, word))
return 1;
if (mathlib) return luaL_error(L, "constant '%s' could not be parsed.\n", word);
// DYNAMIC variables too!!
// Try not to add anything that would break netgames or timeattack replays here.
// You know, like consoleplayer, displayplayer, secondarydisplayplayer, or gametime.
return LUA_PushGlobals(L, word);
return 0;
}
// If a sprname has been "cached" to _G, update it to a new value.
void LUA_UpdateSprName(const char *name, lua_Integer value)
{
char fullname[9] = "SPR_XXXX";
if (!gL)
return;
strncpy(&fullname[4], name, 4);
lua_pushstring(gL, fullname);
lua_rawget(gL, LUA_GLOBALSINDEX);
if (!lua_isnil(gL, -1))
{
lua_pushstring(gL, name);
lua_pushinteger(gL, value);
lua_rawset(gL, LUA_GLOBALSINDEX);
}
lua_pop(gL, 1); // pop the rawget result
}
int LUA_EnumLib(lua_State *L)

View file

@ -13,6 +13,21 @@
#ifndef __DEH_LUA_H__
#define __DEH_LUA_H__
#include "g_game.h"
#include "s_sound.h"
#include "z_zone.h"
#include "m_menu.h"
#include "m_misc.h"
#include "p_local.h"
#include "st_stuff.h"
#include "fastcmp.h"
#include "lua_script.h"
#include "lua_libs.h"
#include "dehacked.h"
#include "deh_tables.h"
void LUA_UpdateSprName(const char *name, lua_Integer value);
boolean LUA_SetLuaAction(void *state, const char *actiontocompare);
const char *LUA_GetActionName(void *action);
void LUA_SetActionByName(void *state, const char *actiontocompare);

View file

@ -45,6 +45,7 @@
#include "dehacked.h"
#include "deh_soc.h"
#include "deh_lua.h" // included due to some LUA_SetLuaAction hack smh
// also used for LUA_UpdateSprName
#include "deh_tables.h"
// Loops through every constant and operation in word and performs its calculations, returning the final value.
@ -439,6 +440,8 @@ void readfreeslots(MYFILE *f)
strncpy(sprnames[i],word,4);
//sprnames[i][4] = 0;
used_spr[(i-SPR_FIRSTFREESLOT)/8] |= 1<<(i%8); // Okay, this sprite slot has been named now.
// Lua needs to update the value in _G if it exists
LUA_UpdateSprName(word, i);
break;
}
}
@ -513,6 +516,8 @@ void readfreeslots(MYFILE *f)
} while (!myfeof(f)); // finish when the line is empty
Z_Free(s);
R_RefreshSprite2();
}
void readthing(MYFILE *f, INT32 num)
@ -907,7 +912,7 @@ static void readspriteframe(MYFILE *f, spriteinfo_t *sprinfo, UINT8 frame)
else if (fastcmp(word, "YPIVOT"))
sprinfo->pivot[frame].y = value;
else if (fastcmp(word, "ROTAXIS"))
sprinfo->pivot[frame].rotaxis = value;
deh_warning("SpriteInfo: ROTAXIS is deprecated and will be removed.");
else
{
f->curpos = lastline;
@ -2907,7 +2912,9 @@ static boolean GoodDataFileName(const char *s)
p = s + strlen(s) - strlen(tail);
if (p <= s) return false; // too short
if (!fasticmp(p, tail)) return false; // doesn't end in .dat
if (fasticmp(s, "gamedata.dat")) return false;
if (fasticmp(s, "gamedata.dat")) return false; // Don't overwrite default gamedata
if (fasticmp(s, "main.dat")) return false; // Don't overwrite default time attack replays
return true;
}
@ -3835,6 +3842,10 @@ void readmaincfg(MYFILE *f)
{
useContinues = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word, "SHAREEMBLEMS"))
{
shareEmblems = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y');
}
else if (fastcmp(word, "GAMEDATA"))
{
@ -3845,7 +3856,7 @@ void readmaincfg(MYFILE *f)
if (!GoodDataFileName(word2))
I_Error("Maincfg: bad data file name '%s'\n", word2);
G_SaveGameData();
G_SaveGameData(clientGamedata);
strlcpy(gamedatafilename, word2, sizeof (gamedatafilename));
strlwr(gamedatafilename);
savemoddata = true;

View file

@ -198,6 +198,7 @@ actionpointer_t actionpointers[] =
{{A_Boss3TakeDamage}, "A_BOSS3TAKEDAMAGE"},
{{A_Boss3Path}, "A_BOSS3PATH"},
{{A_Boss3ShockThink}, "A_BOSS3SHOCKTHINK"},
{{A_Shockwave}, "A_SHOCKWAVE"},
{{A_LinedefExecute}, "A_LINEDEFEXECUTE"},
{{A_LinedefExecuteFromArg}, "A_LINEDEFEXECUTEFROMARG"},
{{A_PlaySeeSound}, "A_PLAYSEESOUND"},
@ -4409,11 +4410,12 @@ const char *const MOBJEFLAG_LIST[] = {
NULL
};
const char *const MAPTHINGFLAG_LIST[4] = {
const char *const MAPTHINGFLAG_LIST[] = {
"EXTRA", // Extra flag for objects.
"OBJECTFLIP", // Reverse gravity flag for objects.
"OBJECTSPECIAL", // Special flag used with certain objects.
"AMBUSH" // Deaf monsters/do not react to sound.
"AMBUSH", // Deaf monsters/do not react to sound.
"ABSOLUTEZ" // Absolute spawn height flag for objects.
};
const char *const PLAYERFLAG_LIST[] = {
@ -4550,6 +4552,7 @@ const char *const MSF_LIST[] = {
const char *const SSF_LIST[] = {
"OUTERSPACE",
"DOUBLESTEPUP",
"NOSTEPDOWN",
"WINDCURRENT",
"CONVEYOR",
"SPEEDPAD",
@ -4566,6 +4569,8 @@ const char *const SSF_LIST[] = {
"ZOOMTUBEEND",
"FINISHLINE",
"ROPEHANG",
"JUMPFLIP",
"GRAVITYOVERRIDE",
NULL
};
@ -4609,66 +4614,111 @@ const char *COLOR_ENUMS[] = {
// Desaturated
"AETHER", // SKINCOLOR_AETHER,
"SLATE", // SKINCOLOR_SLATE,
"MOONSTONE", // SKINCOLOR_MOONSTONE,
"BLUEBELL", // SKINCOLOR_BLUEBELL,
"PINK", // SKINCOLOR_PINK,
"ROSEWOOD", // SKINCOLOR_ROSEWOOD,
"YOGURT", // SKINCOLOR_YOGURT,
"LATTE", // SKINCOLOR_LATTE,
"BROWN", // SKINCOLOR_BROWN,
"BOULDER", // SKINCOLOR_BOULDER
"BRONZE", // SKINCOLOR_BRONZE,
"TAN", // SKINCOLOR_TAN,
"SEPIA", // SKINCOLOR_SEPIA,
"ECRU", // SKINCOLOR_ECRU,
"TAN", // SKINCOLOR_TAN,
"BEIGE", // SKINCOLOR_BEIGE,
"ROSEBUSH", // SKINCOLOR_ROSEBUSH,
"MOSS", // SKINCOLOR_MOSS,
"AZURE", // SKINCOLOR_AZURE,
"LAVENDER", // SKINCOLOR_LAVENDER,
"EGGPLANT", // SKINCOLOR_EGGPLANT,
"LAVENDER", // SKINCOLOR_LAVENDER,
// Viv's vivid colours (toast 21/07/17)
// Tweaks & additions (Lach, sphere, Alice, MotorRoach 26/10/22)
"RUBY", // SKINCOLOR_RUBY,
"CHERRY", // SKINCOLOR_CHERRY,
"SALMON", // SKINCOLOR_SALMON,
"PEPPER", // SKINCOLOR_PEPPER,
"RED", // SKINCOLOR_RED,
"CRIMSON", // SKINCOLOR_CRIMSON,
"FLAME", // SKINCOLOR_FLAME,
"GARNET", // SKINCOLOR_GARNET,
"KETCHUP", // SKINCOLOR_KETCHUP,
"PEACHY", // SKINCOLOR_PEACHY,
"QUAIL", // SKINCOLOR_QUAIL,
"FOUNDATION", // SKINCOLOR_FOUNDATION,
"SUNSET", // SKINCOLOR_SUNSET,
"COPPER", // SKINCOLOR_COPPER,
"APRICOT", // SKINCOLOR_APRICOT,
"ORANGE", // SKINCOLOR_ORANGE,
"RUST", // SKINCOLOR_RUST,
"TANGERINE", // SKINCOLOR_TANGERINE,
"TOPAZ", // SKINCOLOR_TOPAZ,
"GOLD", // SKINCOLOR_GOLD,
"SANDY", // SKINCOLOR_SANDY,
"GOLDENROD", // SKINCOLOR_GOLDENROD,
"YELLOW", // SKINCOLOR_YELLOW,
"OLIVE", // SKINCOLOR_OLIVE,
"PEAR", // SKINCOLOR_PEAR,
"LEMON", // SKINCOLOR_LEMON,
"LIME", // SKINCOLOR_LIME,
"PERIDOT", // SKINCOLOR_PERIDOT,
"APPLE", // SKINCOLOR_APPLE,
"HEADLIGHT", // SKINCOLOR_HEADLIGHT,
"CHARTREUSE", // SKINCOLOR_CHARTREUSE,
"GREEN", // SKINCOLOR_GREEN,
"FOREST", // SKINCOLOR_FOREST,
"EMERALD", // SKINCOLOR_EMERALD,
"SHAMROCK", // SKINCOLOR_SHAMROCK,
"JADE", // SKINCOLOR_JADE,
"MINT", // SKINCOLOR_MINT,
"MASTER", // SKINCOLOR_MASTER,
"EMERALD", // SKINCOLOR_EMERALD,
"SEAFOAM", // SKINCOLOR_SEAFOAM,
"ISLAND", // SKINCOLOR_ISLAND,
"BOTTLE", // SKINCOLOR_BOTTLE,
"AQUA", // SKINCOLOR_AQUA,
"TEAL", // SKINCOLOR_TEAL,
"OCEAN", // SKINCOLOR_OCEAN,
"WAVE", // SKINCOLOR_WAVE,
"CYAN", // SKINCOLOR_CYAN,
"TURQUOISE", // SKINCOLOR_TURQUOISE,
"AQUAMARINE", // SKINCOLOR_AQUAMARINE,
"SKY", // SKINCOLOR_SKY,
"MARINE", // SKINCOLOR_MARINE,
"CERULEAN", // SKINCOLOR_CERULEAN,
"DREAM", // SKINCOLOR_DREAM,
"ICY", // SKINCOLOR_ICY,
"DAYBREAK", // SKINCOLOR_DAYBREAK,
"SAPPHIRE", // SKINCOLOR_SAPPHIRE,
"ARCTIC", // SKINCOLOR_ARCTIC,
"CORNFLOWER", // SKINCOLOR_CORNFLOWER,
"BLUE", // SKINCOLOR_BLUE,
"COBALT", // SKINCOLOR_COBALT,
"MIDNIGHT", // SKINCOLOR_MIDNIGHT,
"GALAXY", // SKINCOLOR_GALAXY,
"VAPOR", // SKINCOLOR_VAPOR,
"DUSK", // SKINCOLOR_DUSK,
"MAJESTY", // SKINCOLOR_MAJESTY,
"PASTEL", // SKINCOLOR_PASTEL,
"PURPLE", // SKINCOLOR_PURPLE,
"BUBBLEGUM", // SKINCOLOR_BUBBLEGUM,
"NOBLE", // SKINCOLOR_NOBLE,
"FUCHSIA", // SKINCOLOR_FUCHSIA,
"BUBBLEGUM", // SKINCOLOR_BUBBLEGUM,
"SIBERITE", // SKINCOLOR_SIBERITE,
"MAGENTA", // SKINCOLOR_MAGENTA,
"NEON", // SKINCOLOR_NEON,
"VIOLET", // SKINCOLOR_VIOLET,
"ROYAL", // SKINCOLOR_ROYAL,
"LILAC", // SKINCOLOR_LILAC,
"MAUVE", // SKINCOLOR_MAUVE,
"EVENTIDE", // SKINCOLOR_EVENTIDE,
"PLUM", // SKINCOLOR_PLUM,
"RASPBERRY", // SKINCOLOR_RASPBERRY,
"TAFFY", // SKINCOLOR_TAFFY,
"ROSY", // SKINCOLOR_ROSY,
"FANCY", // SKINCOLOR_FANCY,
"SANGRIA", // SKINCOLOR_SANGRIA,
"VOLCANIC", // SKINCOLOR_VOLCANIC,
// Super special awesome Super flashing colors!
"SUPERSILVER1", // SKINCOLOR_SUPERSILVER1
@ -4768,7 +4818,9 @@ const char *const POWERS_LIST[] = {
"JUSTLAUNCHED",
"IGNORELATCH"
"IGNORELATCH",
"STRONG"
};
const char *const HUDITEMS_LIST[] = {
@ -5121,6 +5173,30 @@ struct int_const_s const INT_CONST[] = {
{"CR_DUSTDEVIL",CR_DUSTDEVIL},
{"CR_FAN",CR_FAN},
// Strong powers
{"STR_NONE",STR_NONE},
{"STR_ANIM",STR_ANIM},
{"STR_PUNCH",STR_PUNCH},
{"STR_TAIL",STR_TAIL},
{"STR_STOMP",STR_STOMP},
{"STR_UPPER",STR_UPPER},
{"STR_GUARD",STR_GUARD},
{"STR_HEAVY",STR_HEAVY},
{"STR_DASH",STR_DASH},
{"STR_WALL",STR_WALL},
{"STR_FLOOR",STR_FLOOR},
{"STR_CEILING",STR_CEILING},
{"STR_SPRING",STR_SPRING},
{"STR_SPIKE",STR_SPIKE},
{"STR_ATTACK",STR_ATTACK},
{"STR_BUST",STR_BUST},
{"STR_FLY",STR_FLY},
{"STR_GLIDE",STR_GLIDE},
{"STR_TWINSPIN",STR_TWINSPIN},
{"STR_MELEE",STR_MELEE},
{"STR_BOUNCE",STR_BOUNCE},
{"STR_METAL",STR_METAL},
// Ring weapons (ringweapons_t)
// Useful for A_GiveWeapon
{"RW_AUTO",RW_AUTO},

View file

@ -30,6 +30,7 @@ extern UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite
memset(FREE_MOBJS,0,sizeof(char *) * NUMMOBJFREESLOTS);\
memset(FREE_SKINCOLORS,0,sizeof(char *) * NUMCOLORFREESLOTS);\
memset(used_spr,0,sizeof(UINT8) * ((NUMSPRITEFREESLOTS / 8) + 1));\
memset(actionsoverridden, LUA_REFNIL, sizeof(actionsoverridden));\
}
struct flickytypes_s {
@ -61,7 +62,7 @@ extern const char *const MOBJTYPE_LIST[];
extern const char *const MOBJFLAG_LIST[];
extern const char *const MOBJFLAG2_LIST[]; // \tMF2_(\S+).*// (.+) --> \t"\1", // \2
extern const char *const MOBJEFLAG_LIST[];
extern const char *const MAPTHINGFLAG_LIST[4];
extern const char *const MAPTHINGFLAG_LIST[];
extern const char *const PLAYERFLAG_LIST[];
extern const char *const GAMETYPERULE_LIST[];
extern const char *const ML_LIST[]; // Linedef flags

View file

@ -575,7 +575,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
} // end while
if (gamedataadded)
G_LoadGameData();
G_LoadGameData(clientGamedata);
if (gamestate == GS_TITLESCREEN)
{

View file

@ -40,9 +40,9 @@ extern boolean gamedataadded;
extern boolean titlechanged;
extern boolean introchanged;
#define MAXRECURSION 30
extern const char *superactions[MAXRECURSION];
extern UINT8 superstack;
#define MAX_ACTION_RECURSION 30
extern const char *luaactions[MAX_ACTION_RECURSION];
extern UINT8 luaactionstack;
// If the dehacked patch does not match this version, we throw a warning
#define PATCHVERSION 220

View file

@ -62,6 +62,10 @@ enum
#define MTF_AMBUSH 8
// Do not use bit five or after, as they are used for object z-offsets.
// Unless it's exclusive to UDMF.
// Flag to use Z as absolute spawn height, ignoring the floor and ceiling.
#define MTF_ABSOLUTEZ 16
#if defined(_MSC_VER)
#pragma pack(1)
@ -211,6 +215,7 @@ typedef struct
UINT8 extrainfo;
taglist_t tags;
fixed_t scale;
fixed_t spritexscale, spriteyscale;
INT32 args[NUMMAPTHINGARGS];
char *stringargs[NUMMAPTHINGSTRINGARGS];
struct mobj_s *mobj;

View file

@ -104,8 +104,18 @@
#include <io.h>
#endif
FILE *fopenfile(const char*, const char*);
//#define NOMD5
// If you don't disable ALL debug first, you get ALL debug enabled
#if !defined (NDEBUG)
#define PACKETDROP
#define PARANOIA
#define RANGECHECK
#define ZDEBUG
#endif
// Uncheck this to compile debugging code
//#define RANGECHECK
//#ifndef PARANOIA
@ -150,7 +160,7 @@ extern char logfilename[1024];
// Does this version require an added patch file?
// Comment or uncomment this as necessary.
// #define USE_PATCH_DTA
#define USE_PATCH_DTA
// Enforce a limit of loaded WAD files.
//#define ENFORCE_WAD_LIMIT
@ -259,66 +269,111 @@ typedef enum
// Desaturated
SKINCOLOR_AETHER,
SKINCOLOR_SLATE,
SKINCOLOR_MOONSTONE,
SKINCOLOR_BLUEBELL,
SKINCOLOR_PINK,
SKINCOLOR_ROSEWOOD,
SKINCOLOR_YOGURT,
SKINCOLOR_LATTE,
SKINCOLOR_BROWN,
SKINCOLOR_BOULDER,
SKINCOLOR_BRONZE,
SKINCOLOR_SEPIA,
SKINCOLOR_ECRU,
SKINCOLOR_TAN,
SKINCOLOR_BEIGE,
SKINCOLOR_ROSEBUSH,
SKINCOLOR_MOSS,
SKINCOLOR_AZURE,
SKINCOLOR_EGGPLANT,
SKINCOLOR_LAVENDER,
// Viv's vivid colours (toast 21/07/17)
// Tweaks & additions (Lach, sphere, Alice, MotorRoach 26/10/22)
SKINCOLOR_RUBY,
SKINCOLOR_CHERRY,
SKINCOLOR_SALMON,
SKINCOLOR_PEPPER,
SKINCOLOR_RED,
SKINCOLOR_CRIMSON,
SKINCOLOR_FLAME,
SKINCOLOR_GARNET,
SKINCOLOR_KETCHUP,
SKINCOLOR_PEACHY,
SKINCOLOR_QUAIL,
SKINCOLOR_FOUNDATION,
SKINCOLOR_SUNSET,
SKINCOLOR_COPPER,
SKINCOLOR_APRICOT,
SKINCOLOR_ORANGE,
SKINCOLOR_RUST,
SKINCOLOR_TANGERINE,
SKINCOLOR_TOPAZ,
SKINCOLOR_GOLD,
SKINCOLOR_SANDY,
SKINCOLOR_GOLDENROD,
SKINCOLOR_YELLOW,
SKINCOLOR_OLIVE,
SKINCOLOR_PEAR,
SKINCOLOR_LEMON,
SKINCOLOR_LIME,
SKINCOLOR_PERIDOT,
SKINCOLOR_APPLE,
SKINCOLOR_HEADLIGHT,
SKINCOLOR_CHARTREUSE,
SKINCOLOR_GREEN,
SKINCOLOR_FOREST,
SKINCOLOR_EMERALD,
SKINCOLOR_SHAMROCK,
SKINCOLOR_JADE,
SKINCOLOR_MINT,
SKINCOLOR_MASTER,
SKINCOLOR_EMERALD,
SKINCOLOR_SEAFOAM,
SKINCOLOR_ISLAND,
SKINCOLOR_BOTTLE,
SKINCOLOR_AQUA,
SKINCOLOR_TEAL,
SKINCOLOR_OCEAN,
SKINCOLOR_WAVE,
SKINCOLOR_CYAN,
SKINCOLOR_TURQUOISE,
SKINCOLOR_AQUAMARINE,
SKINCOLOR_SKY,
SKINCOLOR_MARINE,
SKINCOLOR_CERULEAN,
SKINCOLOR_DREAM,
SKINCOLOR_ICY,
SKINCOLOR_DAYBREAK,
SKINCOLOR_SAPPHIRE, // sweet mother, i cannot weave slender aphrodite has overcome me with longing for a girl
SKINCOLOR_ARCTIC,
SKINCOLOR_CORNFLOWER,
SKINCOLOR_BLUE,
SKINCOLOR_COBALT,
SKINCOLOR_MIDNIGHT,
SKINCOLOR_GALAXY,
SKINCOLOR_VAPOR,
SKINCOLOR_DUSK,
SKINCOLOR_MAJESTY,
SKINCOLOR_PASTEL,
SKINCOLOR_PURPLE,
SKINCOLOR_NOBLE,
SKINCOLOR_FUCHSIA,
SKINCOLOR_BUBBLEGUM,
SKINCOLOR_SIBERITE,
SKINCOLOR_MAGENTA,
SKINCOLOR_NEON,
SKINCOLOR_VIOLET,
SKINCOLOR_ROYAL,
SKINCOLOR_LILAC,
SKINCOLOR_MAUVE,
SKINCOLOR_EVENTIDE,
SKINCOLOR_PLUM,
SKINCOLOR_RASPBERRY,
SKINCOLOR_TAFFY,
SKINCOLOR_ROSY,
SKINCOLOR_FANCY,
SKINCOLOR_SANGRIA,
SKINCOLOR_VOLCANIC,
FIRSTSUPERCOLOR,
@ -590,7 +645,16 @@ UINT32 quickncasehash (const char *p, size_t n)
#define PUNCTUATION "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
// Compile date and time and revision.
extern const char *compdate, *comptime, *comprevision, *compbranch;
extern const char
*compdate,
*comptime,
*comprevision,
*compbranch,
*compnote,
*comptype;
extern int
compuncommitted,
compoptimized;
// Disabled code and code under testing
// None of these that are disabled in the normal build are guaranteed to work perfectly

View file

@ -75,6 +75,7 @@ extern SINT8 startinglivesbalance[maxgameovers+1];
extern boolean modifiedgame;
extern UINT16 mainwads;
extern boolean savemoddata; // This mod saves time/emblem data.
extern boolean usedCheats;
extern boolean disableSpeedAdjust; // Don't alter the duration of player states if true
extern boolean imcontinuing; // Temporary flag while continuing
extern boolean metalrecording;
@ -131,8 +132,6 @@ extern INT32 postimgparam2;
extern INT32 viewwindowx, viewwindowy;
extern INT32 viewwidth, scaledviewwidth;
extern boolean gamedataloaded;
// Player taking events, and displaying.
extern INT32 consoleplayer;
extern INT32 displayplayer;
@ -250,6 +249,7 @@ extern textprompt_t *textprompts[MAX_PROMPTS];
// For the Custom Exit linedef.
extern INT16 nextmapoverride;
extern UINT8 skipstats;
extern INT16 nextgametype;
extern UINT32 ssspheres; // Total # of spheres in a level
@ -494,8 +494,6 @@ typedef struct
extern tolinfo_t TYPEOFLEVEL[NUMTOLNAMES];
extern UINT32 lastcustomtol;
extern tic_t totalplaytime;
extern boolean stagefailed;
// Emeralds stored as bits to throw savegame hackers off.
@ -514,52 +512,6 @@ extern INT32 luabanks[NUM_LUABANKS];
extern INT32 nummaprings; //keep track of spawned rings/coins
/** Time attack information, currently a very small structure.
*/
typedef struct
{
tic_t time; ///< Time in which the level was finished.
UINT32 score; ///< Score when the level was finished.
UINT16 rings; ///< Rings when the level was finished.
} recorddata_t;
/** Setup for one NiGHTS map.
* These are dynamically allocated because I am insane
*/
#define GRADE_F 0
#define GRADE_E 1
#define GRADE_D 2
#define GRADE_C 3
#define GRADE_B 4
#define GRADE_A 5
#define GRADE_S 6
typedef struct
{
// 8 mares, 1 overall (0)
UINT8 nummares;
UINT32 score[9];
UINT8 grade[9];
tic_t time[9];
} nightsdata_t;
extern nightsdata_t *nightsrecords[NUMMAPS];
extern recorddata_t *mainrecords[NUMMAPS];
// mapvisited is now a set of flags that says what we've done in the map.
#define MV_VISITED 1
#define MV_BEATEN 2
#define MV_ALLEMERALDS 4
#define MV_ULTIMATE 8
#define MV_PERFECT 16
#define MV_PERFECTRA 32
#define MV_MAX 63 // used in gamedata check, update whenever MV's are added
#define MV_MP 128
extern UINT8 mapvisited[NUMMAPS];
// Temporary holding place for nights data for the current map
extern nightsdata_t ntemprecords;
extern UINT32 token; ///< Number of tokens collected in a level
extern UINT32 tokenlist; ///< List of tokens collected
extern boolean gottoken; ///< Did you get a token? Used for end of act
@ -592,9 +544,12 @@ extern UINT8 useBlackRock;
extern UINT8 use1upSound;
extern UINT8 maxXtraLife; // Max extra lives from rings
extern UINT8 useContinues;
#define continuesInSession (!multiplayer && (ultimatemode || (useContinues && !marathonmode) || (!modeattacking && !(cursaveslot > 0))))
extern UINT8 shareEmblems;
extern mobj_t *hunt1, *hunt2, *hunt3; // Emerald hunt locations
// For racing
@ -615,10 +570,6 @@ extern INT32 cheats;
extern tic_t hidetime;
extern UINT32 timesBeaten; // # of times the game has been beaten.
extern UINT32 timesBeatenWithEmeralds;
extern UINT32 timesBeatenUltimate;
// ===========================
// Internal parameters, fixed.
// ===========================

View file

@ -17,6 +17,10 @@
#ifndef __DOOMTYPE__
#define __DOOMTYPE__
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _WIN32
//#define WIN32_LEAN_AND_MEAN
#define RPC_NO_WINDOWS_H
@ -78,7 +82,9 @@ typedef long ssize_t;
#endif
#define strncasecmp strnicmp
#define strcasecmp stricmp
#ifndef __cplusplus
#define inline __inline
#endif
#elif defined (__WATCOMC__)
#include <dos.h>
#include <sys\types.h>
@ -94,31 +100,28 @@ typedef long ssize_t;
#define strnicmp(x,y,n) strncasecmp(x,y,n)
#endif
char *strcasestr(const char *in, const char *what);
char *nongnu_strcasestr(const char *in, const char *what);
#ifndef _GNU_SOURCE
#define strcasestr nongnu_strcasestr
#endif
#define stristr strcasestr
#if defined (macintosh) //|| defined (__APPLE__) //skip all boolean/Boolean crap
#define true 1
#define false 0
#define min(x,y) (((x)<(y)) ? (x) : (y))
#define max(x,y) (((x)>(y)) ? (x) : (y))
#ifdef macintosh
#define stricmp strcmp
#define strnicmp strncmp
#endif
#define boolean INT32
#ifndef O_BINARY
#define O_BINARY 0
#endif
#endif //macintosh
int startswith (const char *base, const char *tag);
int endswith (const char *base, const char *tag);
#if defined (_WIN32) || defined (__HAIKU__)
#define HAVE_DOSSTR_FUNCS
#endif
#if defined (__APPLE__)
#define SRB2_HAVE_STRLCPY
#elif defined (__GLIBC_PREREQ)
// glibc 2.38: added strlcpy and strlcat to _DEFAULT_SOURCE
#if __GLIBC_PREREQ(2, 38)
#define SRB2_HAVE_STRLCPY
#endif
#endif
#ifndef HAVE_DOSSTR_FUNCS
int strupr(char *n); // from dosstr.c
int strlwr(char *n); // from dosstr.c
@ -126,7 +129,7 @@ int strlwr(char *n); // from dosstr.c
#include <stddef.h> // for size_t
#ifndef __APPLE__
#ifndef SRB2_HAVE_STRLCPY
size_t strlcat(char *dst, const char *src, size_t siz);
size_t strlcpy(char *dst, const char *src, size_t siz);
#endif
@ -141,22 +144,24 @@ size_t strlcpy(char *dst, const char *src, size_t siz);
/* Boolean type definition */
// \note __BYTEBOOL__ used to be set above if "macintosh" was defined,
// if macintosh's version of boolean type isn't needed anymore, then isn't this macro pointless now?
#ifndef __BYTEBOOL__
#define __BYTEBOOL__
// Note: C++ bool and C99/C11 _Bool are NOT compatible.
// Historically, boolean was win32 BOOL on Windows. For equivalence, it's now
// int32_t. "true" and "false" are only declared for C code; in C++, conversion
// between "bool" and "int32_t" takes over.
#ifndef _WIN32
typedef int32_t boolean;
#else
#define boolean BOOL
#endif
//faB: clean that up !!
#if defined( _MSC_VER) && (_MSC_VER >= 1800) // MSVC 2013 and forward
#include "stdbool.h"
#elif defined (_WIN32)
#define false FALSE // use windows types
#define true TRUE
#define boolean BOOL
#else
typedef enum {false, true} boolean;
#endif
#endif // __BYTEBOOL__
#ifndef __cplusplus
#ifndef _WIN32
enum {false = 0, true = 1};
#else
#define false FALSE
#define true TRUE
#endif
#endif
/* 7.18.2.1 Limits of exact-width integer types */
@ -384,4 +389,8 @@ unset_bit_array (bitarray_t * const array, const int value)
typedef UINT64 precise_t;
#ifdef __cplusplus
} // extern "C"
#endif
#endif //__DOOMTYPE__

View file

@ -8,19 +8,24 @@ UINT8 graphics_started = 0;
UINT8 keyboard_started = 0;
UINT32 I_GetFreeMem(UINT32 *total)
size_t I_GetFreeMem(size_t *total)
{
*total = 0;
return 0;
}
void I_Sleep(UINT32 ms){}
void I_Sleep(UINT32 ms)
{
(void)ms;
}
precise_t I_GetPreciseTime(void) {
precise_t I_GetPreciseTime(void)
{
return 0;
}
UINT64 I_GetPrecisePrecision(void) {
UINT64 I_GetPrecisePrecision(void)
{
return 1000000;
}
@ -180,7 +185,14 @@ const char *I_ClipboardPaste(void)
return NULL;
}
void I_RegisterSysCommands(void) {}
size_t I_GetRandomBytes(char *destination, size_t amount)
{
(void)destination;
(void)amount;
return 0;
}
void I_RegisterSysCommands(void){}
void I_GetCursorPosition(INT32 *x, INT32 *y)
{

View file

@ -57,6 +57,8 @@ const char *VID_GetModeName(INT32 modenum)
return NULL;
}
UINT32 I_GetRefreshRate(void) { return 35; }
void I_UpdateNoBlit(void){}
void I_FinishUpdate(void){}

View file

@ -63,7 +63,6 @@ static tic_t stoptimer;
static boolean keypressed = false;
// (no longer) De-Demo'd Title Screen
static INT32 menuanimtimer; // Title screen: background animation timing
mobj_t *titlemapcameraref = NULL;
// menu presentation state
@ -75,6 +74,8 @@ INT32 curbgyspeed;
boolean curbghide;
boolean hidetitlemap; // WARNING: set to false by M_SetupNextMenu and M_ClearMenus
static fixed_t curbgx = 0;
static fixed_t curbgy = 0;
static UINT8 curDemo = 0;
static UINT32 demoDelayLeft;
static UINT32 demoIdleLeft;
@ -223,7 +224,6 @@ static INT32 cutscene_writeptr = 0;
static INT32 cutscene_textcount = 0;
static INT32 cutscene_textspeed = 0;
static UINT8 cutscene_boostspeed = 0;
static tic_t cutscene_lasttextwrite = 0;
// STJR Intro
char stjrintro[9] = "STJRI000";
@ -239,11 +239,6 @@ static UINT8 F_WriteText(void)
{
INT32 numtowrite = 1;
const char *c;
tic_t ltw = I_GetTime();
if (cutscene_lasttextwrite == ltw)
return 1; // singletics prevention
cutscene_lasttextwrite = ltw;
if (cutscene_boostspeed)
{
@ -337,7 +332,7 @@ static tic_t introscenetime[NUMINTROSCENES] =
};
// custom intros
void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean resetplayer);
void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean resetplayer, boolean FLS);
void F_StartIntro(void)
{
@ -349,7 +344,7 @@ void F_StartIntro(void)
if (!cutscenes[introtoplay - 1])
D_StartTitle();
else
F_StartCustomCutscene(introtoplay - 1, false, false);
F_StartCustomCutscene(introtoplay - 1, false, false, false);
return;
}
@ -1067,12 +1062,14 @@ static const char *credits[] = {
"\"Golden\"",
"Vivian \"toaster\" Grannell",
"Julio \"Chaos Zero 64\" Guir",
"\"Hanicef\"",
"\"Hannu_Hanhi\"", // For many OpenGL performance improvements!
"Kepa \"Nev3r\" Iceta",
"Thomas \"Shadow Hog\" Igoe",
"Iestyn \"Monster Iestyn\" Jealous",
"\"Kaito Sinclaire\"",
"\"Kalaron\"", // Coded some of Sryder13's collection of OpenGL fixes, especially fog
"\"katsy\"",
"Ronald \"Furyhunter\" Kinard", // The SDL2 port
"\"Lat'\"", // SRB2-CHAT, the chat window from Kart
"\"LZA\"",
@ -1095,6 +1092,7 @@ static const char *credits[] = {
"Ben \"Cue\" Woodford",
"Lachlan \"Lach\" Wright",
"Marco \"mazmazz\" Zafra",
"\"Zwip-Zwap Zapony\"",
"",
"\1Art",
"Victor \"VAdaPEGA\" Ara\x1Fjo", // Araújo -- sorry for our limited font! D:
@ -1202,6 +1200,7 @@ static const char *credits[] = {
"FreeDoom Project", // Used some of the mancubus and rocket launcher sprites for Brak
"Kart Krew",
"Alex \"MistaED\" Fuller",
"Howard Drossin", // Virtual Sonic - Sonic & Knuckles Theme
"Pascal \"CodeImp\" vd Heiden", // Doom Builder developer
"Randi Heit (<!>)", // For their MSPaint <!> sprite that we nicked
"Simon \"sirjuddington\" Judd", // SLADE developer
@ -1257,7 +1256,7 @@ void F_StartCredits(void)
if (creditscutscene)
{
F_StartCustomCutscene(creditscutscene - 1, false, false);
F_StartCustomCutscene(creditscutscene - 1, false, false, false);
return;
}
@ -1279,14 +1278,23 @@ void F_CreditDrawer(void)
UINT16 i;
INT16 zagpos = (timetonext - finalecount - animtimer) % 32;
fixed_t y = (80<<FRACBITS) - (animtimer<<FRACBITS>>1);
UINT8 colornum;
const UINT8 *colormap;
if (players[consoleplayer].skincolor)
colornum = players[consoleplayer].skincolor;
else
colornum = cv_playercolor.value;
colormap = R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE);
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
// Zig Zagz
V_DrawScaledPatch(-16, zagpos, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY));
V_DrawScaledPatch(-16, zagpos - 320, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY));
V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY));
V_DrawScaledPatch(BASEVIDWIDTH + 16, zagpos - 320, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY));
V_DrawFixedPatch(-16*FRACUNIT, zagpos<<FRACBITS, FRACUNIT, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY), colormap);
V_DrawFixedPatch(-16*FRACUNIT, (zagpos - 320)<<FRACBITS, FRACUNIT, V_SNAPTOLEFT, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY), colormap);
V_DrawFixedPatch((BASEVIDWIDTH + 16)*FRACUNIT, zagpos<<FRACBITS, FRACUNIT, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY), colormap);
V_DrawFixedPatch((BASEVIDWIDTH + 16)*FRACUNIT, (zagpos - 320)<<FRACBITS, FRACUNIT, V_SNAPTORIGHT|V_FLIP, W_CachePatchName("LTZIGZAG", PU_PATCH_LOWPRIORITY), colormap);
// Draw background pictures first
for (i = 0; credits_pics[i].patch; i++)
@ -1411,7 +1419,7 @@ boolean F_CreditResponder(event_t *event)
break;
}
if (!(timesBeaten) && !(netgame || multiplayer) && !cv_debug)
if (!(serverGamedata->timesBeaten) && !(netgame || multiplayer) && !cv_debug)
return false;
if (event->type != ev_keydown)
@ -1573,27 +1581,19 @@ void F_GameEvaluationDrawer(void)
#if 0 // the following looks like hot garbage the more unlockables we add, and we now have a lot of unlockables
if (finalecount >= 5*TICRATE)
{
INT32 startcoord = 32;
V_DrawString(8, 16, V_YELLOWMAP, "Unlocked:");
if (!(netgame) && (!modifiedgame || savemoddata))
for (i = 0; i < MAXUNLOCKABLES; i++)
{
INT32 startcoord = 32;
for (i = 0; i < MAXUNLOCKABLES; i++)
if (unlockables[i].conditionset && unlockables[i].conditionset < MAXCONDITIONSETS
&& unlockables[i].type && !unlockables[i].nocecho)
{
if (unlockables[i].conditionset && unlockables[i].conditionset < MAXCONDITIONSETS
&& unlockables[i].type && !unlockables[i].nocecho)
{
if (unlockables[i].unlocked)
V_DrawString(8, startcoord, 0, unlockables[i].name);
startcoord += 8;
}
if (clientGamedata->unlocked[i])
V_DrawString(8, startcoord, 0, unlockables[i].name);
startcoord += 8;
}
}
else if (netgame)
V_DrawString(8, 96, V_YELLOWMAP, "Multiplayer games\ncan't unlock\nextras!");
else
V_DrawString(8, 96, V_YELLOWMAP, "Modified games\ncan't unlock\nextras!");
}
#endif
@ -1648,37 +1648,29 @@ void F_GameEvaluationTicker(void)
sparklloop = 0;
}
if (finalecount == 5*TICRATE)
if (G_CoopGametype() && !stagefailed && finalecount == 5*TICRATE)
{
if (netgame || multiplayer) // modify this when we finally allow unlocking stuff in 2P
serverGamedata->timesBeaten++;
clientGamedata->timesBeaten++;
if (ALL7EMERALDS(emeralds))
{
HU_SetCEchoFlags(V_YELLOWMAP|V_RETURN8);
HU_SetCEchoDuration(6);
HU_DoCEcho("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\Multiplayer games can't unlock extras!");
serverGamedata->timesBeatenWithEmeralds++;
clientGamedata->timesBeatenWithEmeralds++;
}
if (ultimatemode)
{
serverGamedata->timesBeatenUltimate++;
clientGamedata->timesBeatenUltimate++;
}
M_SilentUpdateUnlockablesAndEmblems(serverGamedata);
if (M_UpdateUnlockablesAndExtraEmblems(clientGamedata))
S_StartSound(NULL, sfx_s3k68);
}
else if (!modifiedgame || savemoddata)
{
++timesBeaten;
if (ALL7EMERALDS(emeralds))
++timesBeatenWithEmeralds;
if (ultimatemode)
++timesBeatenUltimate;
if (M_UpdateUnlockablesAndExtraEmblems())
S_StartSound(NULL, sfx_s3k68);
G_SaveGameData();
}
else
{
HU_SetCEchoFlags(V_YELLOWMAP|V_RETURN8);
HU_SetCEchoDuration(6);
HU_DoCEcho("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\Modified games can't unlock extras!");
S_StartSound(NULL, sfx_s3k68);
}
G_SaveGameData(clientGamedata);
}
}
@ -2192,7 +2184,7 @@ void F_EndingDrawer(void)
//colset(linkmap, 164, 165, 169); -- the ideal purple colour to represent a clicked in-game link, but not worth it just for a soundtest-controlled secret
V_DrawCenteredString(BASEVIDWIDTH/2, 8, V_ALLOWLOWERCASE|(trans<<V_ALPHASHIFT), str);
V_DrawCharacter(32, BASEVIDHEIGHT-16, '>'|(trans<<V_ALPHASHIFT), false);
V_DrawString(40, ((finalecount == STOPPINGPOINT-(20+TICRATE)) ? 1 : 0)+BASEVIDHEIGHT-16, ((timesBeaten || finalecount >= STOPPINGPOINT-TICRATE) ? V_PURPLEMAP : V_BLUEMAP)|(trans<<V_ALPHASHIFT), " [S] ===>");
V_DrawString(40, ((finalecount == STOPPINGPOINT-(20+TICRATE)) ? 1 : 0)+BASEVIDHEIGHT-16, ((serverGamedata->timesBeaten || finalecount >= STOPPINGPOINT-TICRATE) ? V_PURPLEMAP : V_BLUEMAP)|(trans<<V_ALPHASHIFT), " [S] ===>");
}
if (finalecount > STOPPINGPOINT-(20+(2*TICRATE)))
@ -2258,7 +2250,8 @@ void F_GameEndTicker(void)
void F_InitMenuPresValues(void)
{
menuanimtimer = 0;
curbgx = 0;
curbgy = 0;
prevMenuId = 0;
activeMenuId = MainDef.menuid;
@ -2267,7 +2260,7 @@ void F_InitMenuPresValues(void)
curfadevalue = 16;
curbgcolor = -1;
curbgxspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollxspeed;
curbgyspeed = (gamestate == GS_TIMEATTACK) ? 22 : titlescrollyspeed;
curbgyspeed = (gamestate == GS_TIMEATTACK) ? 18 : titlescrollyspeed;
curbghide = (gamestate == GS_TIMEATTACK) ? false : true;
curhidepics = hidetitlepics;
@ -2291,17 +2284,11 @@ void F_InitMenuPresValues(void)
//
// F_SkyScroll
//
void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname)
void F_SkyScroll(const char *patchname)
{
INT32 xscrolled, x, xneg = (scrollxspeed > 0) - (scrollxspeed < 0), tilex;
INT32 yscrolled, y, yneg = (scrollyspeed > 0) - (scrollyspeed < 0), tiley;
boolean xispos = (scrollxspeed >= 0), yispos = (scrollyspeed >= 0);
INT32 x, basey = 0;
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
INT16 patwidth, patheight;
INT32 pw, ph; // scaled by dupz
patch_t *pat;
INT32 i, j;
fixed_t fracmenuanimtimer, xscrolltimer, yscrolltimer;
if (rendermode == render_none)
return;
@ -2312,43 +2299,34 @@ void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname)
return;
}
if (!scrollxspeed && !scrollyspeed)
pat = W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY);
if (!curbgxspeed && !curbgyspeed)
{
V_DrawPatchFill(W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY));
V_DrawPatchFill(pat);
W_UnlockCachedPatch(pat);
return;
}
pat = W_CachePatchName(patchname, PU_PATCH_LOWPRIORITY);
// Modulo the background scrolling to prevent jumps from integer overflows
// We already load the background patch here, so we can modulo it here
// to avoid also having to load the patch in F_MenuPresTicker
curbgx %= pat->width * 16;
curbgy %= pat->height * 16;
patwidth = pat->width;
patheight = pat->height;
pw = patwidth * dupz;
ph = patheight * dupz;
// Ooh, fancy frame interpolation
x = ((curbgx*dupz) + FixedInt((rendertimefrac-FRACUNIT) * curbgxspeed*dupz)) / 16;
basey = ((curbgy*dupz) + FixedInt((rendertimefrac-FRACUNIT) * curbgyspeed*dupz)) / 16;
tilex = max(FixedCeil(FixedDiv(vid.width, pw)) >> FRACBITS, 1)+2; // one tile on both sides of center
tiley = max(FixedCeil(FixedDiv(vid.height, ph)) >> FRACBITS, 1)+2;
if (x > 0) // Make sure that we don't leave the left or top sides empty
x -= pat->width * dupz;
if (basey > 0)
basey -= pat->height * dupz;
fracmenuanimtimer = (menuanimtimer * FRACUNIT) - (FRACUNIT - rendertimefrac);
xscrolltimer = ((fracmenuanimtimer*scrollxspeed)/16 + patwidth*xneg*FRACUNIT) % (patwidth * FRACUNIT);
yscrolltimer = ((fracmenuanimtimer*scrollyspeed)/16 + patheight*yneg*FRACUNIT) % (patheight * FRACUNIT);
// coordinate offsets
xscrolled = FixedInt(xscrolltimer * dupz);
yscrolled = FixedInt(yscrolltimer * dupz);
for (x = (xispos) ? -pw*(tilex-1)+pw : 0, i = 0;
i < tilex;
x += pw, i++)
for (; x < vid.width; x += pat->width * dupz)
{
for (y = (yispos) ? -ph*(tiley-1)+ph : 0, j = 0;
j < tiley;
y += ph, j++)
{
V_DrawScaledPatch(
(xispos) ? xscrolled - x : x + xscrolled,
(yispos) ? yscrolled - y : y + yscrolled,
V_NOSCALESTART, pat);
}
for (INT32 y = basey; y < vid.height; y += pat->height * dupz)
V_DrawScaledPatch(x, y, V_NOSCALESTART, pat);
}
W_UnlockCachedPatch(pat);
@ -2671,7 +2649,7 @@ void F_TitleScreenDrawer(void)
if (curbgcolor >= 0)
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor);
else if (!curbghide || !titlemapinaction || gamestate == GS_WAITINGPLAYERS)
F_SkyScroll(curbgxspeed, curbgyspeed, curbgname);
F_SkyScroll(curbgname);
// Don't draw outside of the title screen, or if the patch isn't there.
if (gamestate != GS_TITLESCREEN && gamestate != GS_WAITINGPLAYERS)
@ -3426,10 +3404,10 @@ luahook:
// separate animation timer for backgrounds, since we also count
// during GS_TIMEATTACK
void F_MenuPresTicker(boolean run)
void F_MenuPresTicker(void)
{
if (run)
menuanimtimer++;
curbgx += curbgxspeed;
curbgy += curbgyspeed;
}
// (no longer) De-Demo'd Title Screen
@ -3535,6 +3513,7 @@ void F_TitleScreenTicker(boolean run)
}
titledemo = true;
demofileoverride = DFILE_OVERRIDE_NONE;
G_DoPlayDemo(dname);
}
}
@ -3859,7 +3838,7 @@ static INT32 scenenum, cutnum;
static INT32 picxpos, picypos, picnum, pictime, picmode, numpics, pictoloop;
static INT32 textxpos, textypos;
static boolean cutsceneover = false;
static boolean runningprecutscene = false, precutresetplayer = false;
static boolean runningprecutscene = false, precutresetplayer = false, precutFLS = false;
static void F_AdvanceToNextScene(void)
{
@ -3928,7 +3907,7 @@ void F_EndCutScene(void)
if (runningprecutscene)
{
if (server)
D_MapChange(gamemap, gametype, ultimatemode, precutresetplayer, 0, true, false);
D_MapChange(gamemap, gametype, ultimatemode, precutresetplayer, 0, true, precutFLS);
}
else
{
@ -3943,7 +3922,7 @@ void F_EndCutScene(void)
}
}
void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean resetplayer)
void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean resetplayer, boolean FLS)
{
if (!cutscenes[cutscenenum])
return;
@ -3962,6 +3941,7 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset
cutsceneover = false;
runningprecutscene = precutscene;
precutresetplayer = resetplayer;
precutFLS = FLS;
scenenum = picnum = 0;
cutnum = cutscenenum;
@ -4694,3 +4674,36 @@ void F_TextPromptTicker(void)
animtimer--;
}
}
// ================
// WAITINGPLAYERS
// ================
void F_StartWaitingPlayers(void)
{
wipegamestate = GS_TITLESCREEN; // technically wiping from title screen
finalecount = 0;
}
void F_WaitingPlayersTicker(void)
{
if (paused)
return;
finalecount++;
// dumb hack, only start the music on the 1st tick so if you instantly go into the map you aren't hearing a tic of music
if (finalecount == 2)
S_ChangeMusicInternal("_CHSEL", true);
}
void F_WaitingPlayersDrawer(void)
{
const char *waittext1 = "You will join";
const char *waittext2 = "next level...";
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
V_DrawCreditString((160 - (V_CreditStringWidth(waittext1)>>1))<<FRACBITS, 48<<FRACBITS, 0, waittext1);
V_DrawCreditString((160 - (V_CreditStringWidth(waittext2)>>1))<<FRACBITS, 64<<FRACBITS, 0, waittext2);
}

View file

@ -40,7 +40,7 @@ void F_TextPromptTicker(void);
void F_GameEndDrawer(void);
void F_IntroDrawer(void);
void F_TitleScreenDrawer(void);
void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname);
void F_SkyScroll(const char *patchname);
void F_GameEvaluationDrawer(void);
void F_StartGameEvaluation(void);
@ -52,7 +52,7 @@ void F_EndingDrawer(void);
void F_CreditTicker(void);
void F_CreditDrawer(void);
void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean resetplayer);
void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean resetplayer, boolean FLS);
void F_CutsceneDrawer(void);
void F_EndCutScene(void);
@ -74,6 +74,10 @@ void F_StartContinue(void);
void F_ContinueTicker(void);
void F_ContinueDrawer(void);
void F_StartWaitingPlayers(void);
void F_WaitingPlayersTicker(void);
void F_WaitingPlayersDrawer(void);
extern INT32 finalecount;
extern INT32 titlescrollxspeed;
extern INT32 titlescrollyspeed;
@ -131,7 +135,7 @@ extern UINT16 curtttics;
#define TITLEBACKGROUNDACTIVE (curfadevalue >= 0 || curbgname[0])
void F_InitMenuPresValues(void);
void F_MenuPresTicker(boolean run);
void F_MenuPresTicker(void);
//
// WIPE

View file

@ -614,6 +614,8 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu)
if (moviemode)
M_SaveFrame();
NetKeepAlive(); // Update the network so we don't cause timeouts
}
WipeInAction = false;

View file

@ -39,6 +39,7 @@
#define SUFFIX "*"
#define SLASH "\\"
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#ifndef INVALID_FILE_ATTRIBUTES
@ -307,6 +308,39 @@ closedir (DIR * dirp)
}
#endif
// fopen but it REALLY only works on regular files
// Turns out, on linux, anyway, you can fopen directories
// in read mode. (It's supposed to fail in write mode
// though!!)
FILE *fopenfile(const char *path, const char *mode)
{
FILE *h = fopen(path, mode);
if (h != NULL)
{
struct stat st;
int eno;
if (fstat(fileno(h), &st) == -1)
{
eno = errno;
}
else if (!S_ISREG(st.st_mode))
{
eno = EACCES; // set some kinda error
}
else
{
return h; // ok
}
fclose(h);
errno = eno;
}
return NULL;
}
static CV_PossibleValue_t addons_cons_t[] = {{0, "Default"},
#if 1
{1, "HOME"}, {2, "SRB2"},

View file

@ -39,6 +39,7 @@
#include "v_video.h"
#include "lua_hook.h"
#include "md5.h" // demo checksums
#include "d_netfil.h" // G_CheckDemoExtraFiles
boolean timingdemo; // if true, exit with report on completion
boolean nodrawers; // for comparative timing purposes
@ -49,6 +50,7 @@ static char demoname[64];
boolean demorecording;
boolean demoplayback;
boolean titledemo; // Title Screen demo can be cancelled by any key
demo_file_override_e demofileoverride;
static UINT8 *demobuffer = NULL;
static UINT8 *demo_p, *demotime_p;
static UINT8 *demoend;
@ -56,6 +58,7 @@ static UINT8 demoflags;
static UINT16 demoversion;
boolean singledemo; // quit after playing a demo from cmdline
boolean demo_start; // don't start playing demo right away
boolean demo_forwardmove_rng; // old demo backwards compatibility
boolean demosynced = true; // console warning message
boolean metalrecording; // recording as metal sonic
@ -95,7 +98,7 @@ demoghost *ghosts = NULL;
// DEMO RECORDING
//
#define DEMOVERSION 0x000f
#define DEMOVERSION 0x0010
#define DEMOHEADER "\xF0" "SRB2Replay" "\x0F"
#define DF_GHOST 0x01 // This demo contains ghost data too!
@ -1413,6 +1416,10 @@ void G_BeginRecording(void)
char name[MAXCOLORNAME+1];
player_t *player = &players[consoleplayer];
char *filename;
UINT16 totalfiles;
UINT8 *m;
if (demo_p)
return;
memset(name,0,sizeof(name));
@ -1435,23 +1442,43 @@ void G_BeginRecording(void)
M_Memcpy(demo_p, mapmd5, 16); demo_p += 16;
WRITEUINT8(demo_p,demoflags);
// file list
m = demo_p;/* file count */
demo_p += 2;
totalfiles = 0;
for (i = mainwads; ++i < numwadfiles; )
{
if (wadfiles[i]->important)
{
nameonly(( filename = va("%s", wadfiles[i]->filename) ));
WRITESTRINGL(demo_p, filename, MAX_WADPATH);
WRITEMEM(demo_p, wadfiles[i]->md5sum, 16);
totalfiles++;
}
}
WRITEUINT16(m, totalfiles);
switch ((demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT)
{
case ATTACKING_NONE: // 0
break;
case ATTACKING_RECORD: // 1
demotime_p = demo_p;
WRITEUINT32(demo_p,UINT32_MAX); // time
WRITEUINT32(demo_p,0); // score
WRITEUINT16(demo_p,0); // rings
break;
case ATTACKING_NIGHTS: // 2
demotime_p = demo_p;
WRITEUINT32(demo_p,UINT32_MAX); // time
WRITEUINT32(demo_p,0); // score
break;
default: // 3
break;
case ATTACKING_NONE: // 0
break;
case ATTACKING_RECORD: // 1
demotime_p = demo_p;
WRITEUINT32(demo_p,UINT32_MAX); // time
WRITEUINT32(demo_p,0); // score
WRITEUINT16(demo_p,0); // rings
break;
case ATTACKING_NIGHTS: // 2
demotime_p = demo_p;
WRITEUINT32(demo_p,UINT32_MAX); // time
WRITEUINT32(demo_p,0); // score
break;
default: // 3
break;
}
WRITEUINT32(demo_p,P_GetInitSeed());
@ -1483,18 +1510,18 @@ void G_BeginRecording(void)
// Stats
WRITEUINT8(demo_p,player->charability);
WRITEUINT8(demo_p,player->charability2);
WRITEUINT8(demo_p,player->actionspd>>FRACBITS);
WRITEUINT8(demo_p,player->mindash>>FRACBITS);
WRITEUINT8(demo_p,player->maxdash>>FRACBITS);
WRITEUINT8(demo_p,player->normalspeed>>FRACBITS);
WRITEUINT8(demo_p,player->runspeed>>FRACBITS);
WRITEFIXED(demo_p,player->actionspd);
WRITEFIXED(demo_p,player->mindash);
WRITEFIXED(demo_p,player->maxdash);
WRITEFIXED(demo_p,player->normalspeed);
WRITEFIXED(demo_p,player->runspeed);
WRITEUINT8(demo_p,player->thrustfactor);
WRITEUINT8(demo_p,player->accelstart);
WRITEUINT8(demo_p,player->acceleration);
WRITEFIXED(demo_p,player->height);
WRITEFIXED(demo_p,player->spinheight);
WRITEUINT8(demo_p,player->camerascale>>FRACBITS);
WRITEUINT8(demo_p,player->shieldscale>>FRACBITS);
WRITEFIXED(demo_p,player->camerascale);
WRITEFIXED(demo_p,player->shieldscale);
// Trying to convert it back to % causes demo desync due to precision loss.
// Don't do it.
@ -1590,6 +1617,183 @@ void G_BeginMetal(void)
oldmetal.angle = mo->angle>>24;
}
static void G_LoadDemoExtraFiles(UINT8 **pp, UINT16 this_demo_version)
{
UINT16 totalfiles;
char filename[MAX_WADPATH];
UINT8 md5sum[16];
filestatus_t ncs;
boolean toomany = false;
boolean alreadyloaded;
UINT16 i, j;
if (this_demo_version < 0x0010)
{
// demo has no file list
return;
}
totalfiles = READUINT16((*pp));
for (i = 0; i < totalfiles; ++i)
{
if (toomany)
SKIPSTRING((*pp));
else
{
strlcpy(filename, (char *)(*pp), sizeof filename);
SKIPSTRING((*pp));
}
READMEM((*pp), md5sum, 16);
if (!toomany)
{
alreadyloaded = false;
for (j = 0; j < numwadfiles; ++j)
{
if (memcmp(md5sum, wadfiles[j]->md5sum, 16) == 0)
{
alreadyloaded = true;
break;
}
}
if (alreadyloaded)
continue;
if (numwadfiles >= MAX_WADFILES)
toomany = true;
else
ncs = findfile(filename, md5sum, false);
if (toomany)
{
CONS_Alert(CONS_WARNING, M_GetText("Too many files loaded to add anymore for demo playback\n"));
if (!CON_Ready())
M_StartMessage(M_GetText("There are too many files loaded to add this demo's addons.\n\nDemo playback may desync.\n\nPress ESC\n"), NULL, MM_NOTHING);
}
else if (ncs != FS_FOUND)
{
if (ncs == FS_NOTFOUND)
CONS_Alert(CONS_NOTICE, M_GetText("You do not have a copy of %s\n"), filename);
else if (ncs == FS_MD5SUMBAD)
CONS_Alert(CONS_NOTICE, M_GetText("Checksum mismatch on %s\n"), filename);
else
CONS_Alert(CONS_NOTICE, M_GetText("Unknown error finding file %s\n"), filename);
if (!CON_Ready())
M_StartMessage(M_GetText("There were errors trying to add this demo's addons. Check the console for more information.\n\nDemo playback may desync.\n\nPress ESC\n"), NULL, MM_NOTHING);
}
else
{
P_AddWadFile(filename);
}
}
}
}
static void G_SkipDemoExtraFiles(UINT8 **pp, UINT16 this_demo_version)
{
UINT16 totalfiles;
UINT16 i;
if (this_demo_version < 0x0010)
{
// demo has no file list
return;
}
totalfiles = READUINT16((*pp));
for (i = 0; i < totalfiles; ++i)
{
SKIPSTRING((*pp));// file name
(*pp) += 16;// md5
}
}
// G_CheckDemoExtraFiles: checks if our loaded WAD list matches the demo's.
// Enabling quick prevents filesystem checks to see if needed files are available to load.
static UINT8 G_CheckDemoExtraFiles(UINT8 **pp, boolean quick, UINT16 this_demo_version)
{
UINT16 totalfiles, filesloaded, nmusfilecount;
char filename[MAX_WADPATH];
UINT8 md5sum[16];
boolean toomany = false;
boolean alreadyloaded;
UINT16 i, j;
UINT8 error = DFILE_ERROR_NONE;
if (this_demo_version < 0x0010)
{
// demo has no file list
return DFILE_ERROR_NONE;
}
totalfiles = READUINT16((*pp));
filesloaded = 0;
for (i = 0; i < totalfiles; ++i)
{
if (toomany)
SKIPSTRING((*pp));
else
{
strlcpy(filename, (char *)(*pp), sizeof filename);
SKIPSTRING((*pp));
}
READMEM((*pp), md5sum, 16);
if (!toomany)
{
alreadyloaded = false;
nmusfilecount = 0;
for (j = 0; j < numwadfiles; ++j)
{
if (wadfiles[j]->important && j > mainwads)
nmusfilecount++;
else
continue;
if (memcmp(md5sum, wadfiles[j]->md5sum, 16) == 0)
{
alreadyloaded = true;
if (i != nmusfilecount-1 && error < DFILE_ERROR_OUTOFORDER)
error |= DFILE_ERROR_OUTOFORDER;
break;
}
}
if (alreadyloaded)
{
filesloaded++;
continue;
}
if (numwadfiles >= MAX_WADFILES)
error = DFILE_ERROR_CANNOTLOAD;
else if (!quick && findfile(filename, md5sum, false) != FS_FOUND)
error = DFILE_ERROR_CANNOTLOAD;
else if (error < DFILE_ERROR_INCOMPLETEOUTOFORDER)
error |= DFILE_ERROR_NOTLOADED;
} else
error = DFILE_ERROR_CANNOTLOAD;
}
// Get final file count
nmusfilecount = 0;
for (j = 0; j < numwadfiles; ++j)
if (wadfiles[j]->important && j > mainwads)
nmusfilecount++;
if (!error && filesloaded < nmusfilecount)
error = DFILE_ERROR_EXTRAFILES;
return error;
}
void G_SetDemoTime(UINT32 ptime, UINT32 pscore, UINT16 prings)
{
if (!demorecording || !demotime_p)
@ -1618,10 +1822,9 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
UINT8 *buffer,*p;
UINT8 flags;
UINT32 oldtime, newtime, oldscore, newscore;
UINT16 oldrings, newrings, oldversion;
UINT16 oldrings, newrings, oldversion, newversion;
size_t bufsize ATTRUNUSED;
UINT8 c;
UINT16 s ATTRUNUSED;
UINT8 aflags = 0;
// load the new file
@ -1637,15 +1840,15 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
I_Assert(c == VERSION);
c = READUINT8(p); // SUBVERSION
I_Assert(c == SUBVERSION);
s = READUINT16(p);
I_Assert(s >= 0x000c);
newversion = READUINT16(p);
I_Assert(newversion == DEMOVERSION);
p += 16; // demo checksum
I_Assert(!memcmp(p, "PLAY", 4));
p += 4; // PLAY
p += 2; // gamemap
p += 16; // map md5
flags = READUINT8(p); // demoflags
G_SkipDemoExtraFiles(&p, newversion);
aflags = flags & (DF_RECORDATTACK|DF_NIGHTSATTACK);
I_Assert(aflags);
if (flags & DF_RECORDATTACK)
@ -1687,7 +1890,8 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
switch(oldversion) // demoversion
{
case DEMOVERSION: // latest always supported
case 0x000e: // The previous demoversions also supported
case 0x000f: // The previous demoversions also supported
case 0x000e:
case 0x000d: // all that changed between then and now was longer color name
case 0x000c:
break;
@ -1710,6 +1914,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
p += 2; // gamemap
p += 16; // mapmd5
flags = READUINT8(p);
G_SkipDemoExtraFiles(&p, oldversion);
if (!(flags & aflags))
{
CONS_Alert(CONS_NOTICE, M_GetText("File '%s' not from same game mode. It will be overwritten.\n"), oldname);
@ -1829,8 +2034,10 @@ void G_DoPlayDemo(char *defdemoname)
version = READUINT8(demo_p);
subversion = READUINT8(demo_p);
demoversion = READUINT16(demo_p);
demo_forwardmove_rng = (demoversion < 0x0010);
switch(demoversion)
{
case 0x000f:
case 0x000d:
case 0x000e:
case DEMOVERSION: // latest always supported
@ -1871,6 +2078,69 @@ void G_DoPlayDemo(char *defdemoname)
demo_p += 16; // mapmd5
demoflags = READUINT8(demo_p);
if (titledemo)
{
// Titledemos should always play and ought to always be compatible with whatever wadlist is running.
G_SkipDemoExtraFiles(&demo_p, demoversion);
}
else if (demofileoverride == DFILE_OVERRIDE_LOAD)
{
G_LoadDemoExtraFiles(&demo_p, demoversion);
}
else if (demofileoverride == DFILE_OVERRIDE_SKIP)
{
G_SkipDemoExtraFiles(&demo_p, demoversion);
}
else
{
UINT8 error = G_CheckDemoExtraFiles(&demo_p, false, demoversion);
if (error)
{
switch (error)
{
case DFILE_ERROR_NOTLOADED:
snprintf(msg, 1024,
M_GetText("Required files for this demo are not loaded.\n\nUse\n\"playdemo %s -addfiles\"\nto load them and play the demo.\n"),
pdemoname);
break;
case DFILE_ERROR_OUTOFORDER:
snprintf(msg, 1024,
M_GetText("Required files for this demo are loaded out of order.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"),
pdemoname);
break;
case DFILE_ERROR_INCOMPLETEOUTOFORDER:
snprintf(msg, 1024,
M_GetText("Required files for this demo are not loaded, and some are out of order.\n\nUse\n\"playdemo %s -addfiles\"\nto load needed files and play the demo.\n"),
pdemoname);
break;
case DFILE_ERROR_CANNOTLOAD:
snprintf(msg, 1024,
M_GetText("Required files for this demo cannot be loaded.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"),
pdemoname);
break;
case DFILE_ERROR_EXTRAFILES:
snprintf(msg, 1024,
M_GetText("You have additional files loaded beyond the demo's file list.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"),
pdemoname);
break;
}
CONS_Alert(CONS_ERROR, "%s", msg);
M_StartMessage(msg, NULL, MM_NOTHING);
Z_Free(pdemoname);
Z_Free(demobuffer);
demoplayback = false;
titledemo = false;
return;
}
}
modeattacking = (demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT;
CON_ToggleOff();
@ -1913,18 +2183,18 @@ void G_DoPlayDemo(char *defdemoname)
charability = READUINT8(demo_p);
charability2 = READUINT8(demo_p);
actionspd = (fixed_t)READUINT8(demo_p)<<FRACBITS;
mindash = (fixed_t)READUINT8(demo_p)<<FRACBITS;
maxdash = (fixed_t)READUINT8(demo_p)<<FRACBITS;
normalspeed = (fixed_t)READUINT8(demo_p)<<FRACBITS;
runspeed = (fixed_t)READUINT8(demo_p)<<FRACBITS;
actionspd = (demoversion < 0x0010) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
mindash = (demoversion < 0x0010) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
maxdash = (demoversion < 0x0010) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
normalspeed = (demoversion < 0x0010) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
runspeed = (demoversion < 0x0010) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
thrustfactor = READUINT8(demo_p);
accelstart = READUINT8(demo_p);
acceleration = READUINT8(demo_p);
height = (demoversion < 0x000e) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
spinheight = (demoversion < 0x000e) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
camerascale = (fixed_t)READUINT8(demo_p)<<FRACBITS;
shieldscale = (fixed_t)READUINT8(demo_p)<<FRACBITS;
camerascale = (demoversion < 0x0010) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
shieldscale = (demoversion < 0x0010) ? (fixed_t)READUINT8(demo_p)<<FRACBITS : READFIXED(demo_p);
jumpfactor = READFIXED(demo_p);
followitem = READUINT32(demo_p);
@ -2026,6 +2296,88 @@ void G_DoPlayDemo(char *defdemoname)
demo_start = true;
}
//
// Check if a replay can be loaded from the menu
//
UINT8 G_CheckDemoForError(char *defdemoname)
{
lumpnum_t l;
char *n,*pdemoname;
UINT16 our_demo_version;
if (titledemo)
{
// Don't do anything with files for these.
return DFILE_ERROR_NONE;
}
n = defdemoname+strlen(defdemoname);
while (*n != '/' && *n != '\\' && n != defdemoname)
n--;
if (n != defdemoname)
n++;
pdemoname = ZZ_Alloc(strlen(n)+1);
strcpy(pdemoname,n);
// Internal if no extension, external if one exists
if (FIL_CheckExtension(defdemoname))
{
//FIL_DefaultExtension(defdemoname, ".lmp");
if (!FIL_ReadFile(defdemoname, &demobuffer))
{
return DFILE_ERROR_NOTDEMO;
}
demo_p = demobuffer;
}
// load demo resource from WAD
else if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR)
{
return DFILE_ERROR_NOTDEMO;
}
else // it's an internal demo
{
demobuffer = demo_p = W_CacheLumpNum(l, PU_STATIC);
}
// read demo header
if (memcmp(demo_p, DEMOHEADER, 12))
{
return DFILE_ERROR_NOTDEMO;
}
demo_p += 12; // DEMOHEADER
demo_p++; // version
demo_p++; // subversion
our_demo_version = READUINT16(demo_p);
switch(our_demo_version)
{
case 0x000d:
case 0x000e:
case 0x000f:
case DEMOVERSION: // latest always supported
break;
#ifdef OLD22DEMOCOMPAT
case 0x000c:
break;
#endif
// too old, cannot support.
default:
return DFILE_ERROR_NOTDEMO;
}
demo_p += 16; // demo checksum
if (memcmp(demo_p, "PLAY", 4))
{
return DFILE_ERROR_NOTDEMO;
}
demo_p += 4; // "PLAY"
demo_p += 2; // gamemap
demo_p += 16; // mapmd5
demo_p++; // demoflags
return G_CheckDemoExtraFiles(&demo_p, true, our_demo_version);
}
void G_AddGhost(char *defdemoname)
{
INT32 i;
@ -2085,6 +2437,7 @@ void G_AddGhost(char *defdemoname)
ghostversion = READUINT16(p);
switch(ghostversion)
{
case 0x000f:
case 0x000d:
case 0x000e:
case DEMOVERSION: // latest always supported
@ -2130,6 +2483,9 @@ void G_AddGhost(char *defdemoname)
Z_Free(buffer);
return;
}
G_SkipDemoExtraFiles(&p, ghostversion); // Don't wanna modify the file list for ghosts.
switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT)
{
case ATTACKING_NONE: // 0
@ -2161,17 +2517,12 @@ void G_AddGhost(char *defdemoname)
// Ghosts do not have a player structure to put this in.
p++; // charability
p++; // charability2
p++; // actionspd
p++; // mindash
p++; // maxdash
p++; // normalspeed
p++; // runspeed
p += (ghostversion < 0x0010) ? 5 : 5 * sizeof(fixed_t); // actionspd, mindash, maxdash, normalspeed, and runspeed
p++; // thrustfactor
p++; // accelstart
p++; // acceleration
p += (ghostversion < 0x000e) ? 2 : 2 * sizeof(fixed_t); // height and spinheight
p++; // camerascale
p++; // shieldscale
p += (ghostversion < 0x0010) ? 2 : 2 * sizeof(fixed_t); // camerascale and shieldscale
p += 4; // jumpfactor
p += 4; // followitem
@ -2347,6 +2698,7 @@ void G_DoPlayMetal(void)
switch(metalversion)
{
case DEMOVERSION: // latest always supported
case 0x000f:
case 0x000e: // There are checks wheter the momentum is from older demo versions or not
case 0x000d: // all that changed between then and now was longer color name
case 0x000c:

View file

@ -26,9 +26,19 @@
extern boolean demoplayback, titledemo, demorecording, timingdemo;
extern tic_t demostarttime;
typedef enum
{
DFILE_OVERRIDE_NONE = 0, // Show errors normally
DFILE_OVERRIDE_LOAD, // Forcefully load demo, add files beforehand
DFILE_OVERRIDE_SKIP, // Forcefully load demo, skip file list
} demo_file_override_e;
extern demo_file_override_e demofileoverride;
// Quit after playing a demo from cmdline.
extern boolean singledemo;
extern boolean demo_start;
extern boolean demo_forwardmove_rng;
extern boolean demosynced;
extern mobj_t *metalplayback;
@ -53,6 +63,18 @@ typedef enum
GHC_RETURNSKIN // ditto
} ghostcolor_t;
// G_CheckDemoExtraFiles: checks if our loaded WAD list matches the demo's.
typedef enum
{
DFILE_ERROR_NONE = 0, // No file error
DFILE_ERROR_NOTLOADED, // Files are not loaded, but can be without a restart.
DFILE_ERROR_OUTOFORDER, // Files are loaded, but out of order.
DFILE_ERROR_INCOMPLETEOUTOFORDER, // Some files are loaded out of order, but others are not.
DFILE_ERROR_CANNOTLOAD, // Files are missing and cannot be loaded.
DFILE_ERROR_EXTRAFILES, // Extra files outside of the replay's file list are loaded.
DFILE_ERROR_NOTDEMO = UINT8_MAX, // This replay isn't even a replay...
} demo_file_error_e;
// Record/playback tics
void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum);
void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum);
@ -83,5 +105,6 @@ ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill);
void G_StopDemo(void);
boolean G_CheckDemoStatus(void);
INT32 G_ConvertOldFrameFlags(INT32 frame);
UINT8 G_CheckDemoForError(char *defdemoname);
#endif // __G_DEMO__

File diff suppressed because it is too large Load diff

View file

@ -19,6 +19,7 @@
#include "d_event.h"
#include "g_demo.h"
#include "m_cheat.h" // objectplacing
#include "m_cond.h"
extern char gamedatafilename[64];
extern char timeattackfolder[64];
@ -48,6 +49,8 @@ extern boolean promptactive;
extern consvar_t cv_pauseifunfocused;
extern consvar_t cv_instantretry;
// used in game menu
extern consvar_t cv_tutorialprompt;
extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatbacktint, cv_chatspamprotection, cv_compactscoreboard;
@ -183,7 +186,7 @@ boolean G_IsTitleCardAvailable(void);
// Can be called by the startup code or M_Responder, calls P_SetupLevel.
void G_LoadGame(UINT32 slot, INT16 mapoverride);
void G_SaveGameData(void);
void G_SaveGameData(gamedata_t *data);
void G_SaveGame(UINT32 slot, INT16 mapnum);
@ -239,27 +242,27 @@ void G_SetModeAttackRetryFlag(void);
void G_ClearModeAttackRetryFlag(void);
boolean G_GetModeAttackRetryFlag(void);
void G_LoadGameData(void);
void G_LoadGameData(gamedata_t *data);
void G_LoadGameSettings(void);
void G_SetGameModified(boolean silent);
void G_SetUsedCheats(boolean silent);
void G_SetGamestate(gamestate_t newstate);
// Gamedata record shit
void G_AllocMainRecordData(INT16 i);
void G_AllocNightsRecordData(INT16 i);
void G_ClearRecords(void);
void G_AllocMainRecordData(INT16 i, gamedata_t *data);
void G_AllocNightsRecordData(INT16 i, gamedata_t *data);
void G_ClearRecords(gamedata_t *data);
UINT32 G_GetBestScore(INT16 map);
tic_t G_GetBestTime(INT16 map);
UINT16 G_GetBestRings(INT16 map);
UINT32 G_GetBestNightsScore(INT16 map, UINT8 mare);
tic_t G_GetBestNightsTime(INT16 map, UINT8 mare);
UINT8 G_GetBestNightsGrade(INT16 map, UINT8 mare);
UINT32 G_GetBestScore(INT16 map, gamedata_t *data);
tic_t G_GetBestTime(INT16 map, gamedata_t *data);
UINT16 G_GetBestRings(INT16 map, gamedata_t *data);
UINT32 G_GetBestNightsScore(INT16 map, UINT8 mare, gamedata_t *data);
tic_t G_GetBestNightsTime(INT16 map, UINT8 mare, gamedata_t *data);
UINT8 G_GetBestNightsGrade(INT16 map, UINT8 mare, gamedata_t *data);
void G_AddTempNightsRecords(UINT32 pscore, tic_t ptime, UINT8 mare);
void G_SetNightsRecords(void);
void G_AddTempNightsRecords(player_t *player, UINT32 pscore, tic_t ptime, UINT8 mare);
FUNCMATH INT32 G_TicsToHours(tic_t tics);
FUNCMATH INT32 G_TicsToMinutes(tic_t tics, boolean full);

View file

@ -1 +1,14 @@
target_sourcefile(c)
target_sources(SRB2SDL2 PRIVATE
hw_bsp.c
hw_draw.c
hw_light.c
hw_main.c
hw_clip.c
hw_md2.c
hw_cache.c
hw_md2load.c
hw_md3load.c
hw_model.c
hw_batching.c
r_opengl/r_opengl.c
)

View file

@ -8,6 +8,5 @@ hw_cache.c
hw_md2load.c
hw_md3load.c
hw_model.c
u_list.c
hw_batching.c
r_opengl/r_opengl.c

View file

@ -42,10 +42,10 @@ int unsortedVertexArrayAllocSize = 65536;
// Call HWR_RenderBatches to render all the collected geometry.
void HWR_StartBatching(void)
{
if (currently_batching)
I_Error("Repeat call to HWR_StartBatching without HWR_RenderBatches");
if (currently_batching)
I_Error("Repeat call to HWR_StartBatching without HWR_RenderBatches");
// init arrays if that has not been done yet
// init arrays if that has not been done yet
if (!finalVertexArray)
{
finalVertexArray = malloc(finalVertexArrayAllocSize * sizeof(FOutVector));
@ -55,7 +55,7 @@ void HWR_StartBatching(void)
unsortedVertexArray = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector));
}
currently_batching = true;
currently_batching = true;
}
// This replaces the direct calls to pfnSetTexture in cases where batching is available.

View file

@ -93,33 +93,22 @@ typedef struct FVector
//Hurdler: Transform (coords + angles)
//BP: transform order : scale(rotation_x(rotation_y(translation(v))))
// Kart features
//#define USE_FTRANSFORM_ANGLEZ
//#define USE_FTRANSFORM_MIRROR
// Vanilla features
#define USE_MODEL_NEXTFRAME
typedef struct
{
FLOAT x,y,z; // position
#ifdef USE_FTRANSFORM_ANGLEZ
FLOAT anglex,angley,anglez; // aimingangle / viewangle
#else
FLOAT anglex,angley; // aimingangle / viewangle
#endif
FLOAT scalex,scaley,scalez;
FLOAT fovxangle, fovyangle;
UINT8 splitscreen;
boolean flip; // screenflip
boolean roll;
SINT8 rollflip;
FLOAT rollangle; // done to not override USE_FTRANSFORM_ANGLEZ
UINT8 rotaxis;
FLOAT centerx, centery;
#ifdef USE_FTRANSFORM_MIRROR
FLOAT rollx, rollz;
boolean mirror; // SRB2Kart: Encore Mode
#endif
boolean shearing; // 14042019
float viewaiming; // 17052019
} FTransform;
@ -136,6 +125,7 @@ typedef struct
// Predefined shader types
enum
{
SHADER_NONE = -1,
SHADER_DEFAULT = 0,
SHADER_FLOOR,
@ -237,7 +227,8 @@ enum EPolyFlags
PF_RemoveYWrap = 0x00010000, // Forces clamp texture on Y
PF_ForceWrapX = 0x00020000, // Forces repeat texture on X
PF_ForceWrapY = 0x00040000, // Forces repeat texture on Y
PF_Ripple = 0x00100000 // Water ripple effect. The current backend doesn't use it for anything.
PF_Ripple = 0x00100000, // Water ripple effect. The current backend doesn't use it for anything.
PF_WireFrame = 0x00200000, // Draws vertices as lines instead of triangles
};

View file

@ -51,7 +51,7 @@ EXPORT void HWRAPI(ClearMipMapCache) (void);
EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value);
//Hurdler: added for new development
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface);
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface);
EXPORT void HWRAPI(CreateModelVBOs) (model_t *model);
EXPORT void HWRAPI(SetTransform) (FTransform *ptransform);
EXPORT INT32 HWRAPI(GetTextureUsed) (void);
@ -136,4 +136,3 @@ extern struct hwdriver_s hwdriver;
#endif //not defined _CREATE_DLL_
#endif //__HWR_DRV_H__

View file

@ -81,6 +81,7 @@ typedef struct gl_vissprite_s
boolean flip, vflip;
boolean precip; // Tails 08-25-2002
boolean bbox;
boolean rotated;
UINT8 translucency; //alpha level 0-255
@ -88,7 +89,7 @@ typedef struct gl_vissprite_s
//Hurdler: 25/04/2000: now support colormap in hardware mode
UINT8 *colormap;
INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing
INT32 dispoffset; // copy of mobj->dispoffset, affects ordering but not drawing
patch_t *gpatch;
mobj_t *mobj; // NOTE: This is a precipmobj_t if precip is true !!! Watch out.

View file

@ -66,6 +66,7 @@ static void HWR_ProjectSprite(mobj_t *thing);
#ifdef HWPRECIP
static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing);
#endif
static void HWR_ProjectBoundingBox(mobj_t *thing);
void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap);
void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight,
@ -139,7 +140,7 @@ static fixed_t dup_viewx, dup_viewy, dup_viewz;
static angle_t dup_viewangle;
static float gl_viewx, gl_viewy, gl_viewz;
static float gl_viewsin, gl_viewcos;
float gl_viewsin, gl_viewcos;
// Maybe not necessary with the new T&L code (needs to be checked!)
static float gl_viewludsin, gl_viewludcos; // look up down kik test
@ -459,30 +460,30 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
{
if (!isceiling) // it's a floor
{
scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatheight;
angle = FOFsector->floorpic_angle;
scrollx = FIXED_TO_FLOAT(FOFsector->floorxoffset)/fflatwidth;
scrolly = FIXED_TO_FLOAT(FOFsector->flooryoffset)/fflatheight;
angle = FOFsector->floorangle;
}
else // it's a ceiling
{
scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatheight;
angle = FOFsector->ceilingpic_angle;
scrollx = FIXED_TO_FLOAT(FOFsector->ceilingxoffset)/fflatwidth;
scrolly = FIXED_TO_FLOAT(FOFsector->ceilingyoffset)/fflatheight;
angle = FOFsector->ceilingangle;
}
}
else if (gl_frontsector)
{
if (!isceiling) // it's a floor
{
scrollx = FIXED_TO_FLOAT(gl_frontsector->floor_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(gl_frontsector->floor_yoffs)/fflatheight;
angle = gl_frontsector->floorpic_angle;
scrollx = FIXED_TO_FLOAT(gl_frontsector->floorxoffset)/fflatwidth;
scrolly = FIXED_TO_FLOAT(gl_frontsector->flooryoffset)/fflatheight;
angle = gl_frontsector->floorangle;
}
else // it's a ceiling
{
scrollx = FIXED_TO_FLOAT(gl_frontsector->ceiling_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(gl_frontsector->ceiling_yoffs)/fflatheight;
angle = gl_frontsector->ceilingpic_angle;
scrollx = FIXED_TO_FLOAT(gl_frontsector->ceilingxoffset)/fflatwidth;
scrolly = FIXED_TO_FLOAT(gl_frontsector->ceilingyoffset)/fflatheight;
angle = gl_frontsector->ceilingangle;
}
}
@ -1153,7 +1154,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
else
texturevpeg = gl_backsector->ceilingheight + textureheight[gl_toptexture] - gl_frontsector->ceilingheight;
texturevpeg += gl_sidedef->rowoffset;
texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_top;
// This is so that it doesn't overflow and screw up the wall, it doesn't need to go higher than the texture's height anyway
texturevpeg %= textureheight[gl_toptexture];
@ -1162,8 +1163,8 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY;
wallVerts[0].t = wallVerts[1].t = (texturevpeg + gl_frontsector->ceilingheight - gl_backsector->ceilingheight) * grTex->scaleY;
wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX;
wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX;
wallVerts[0].s = wallVerts[3].s = (cliplow + gl_sidedef->offsetx_top) * grTex->scaleX;
wallVerts[2].s = wallVerts[1].s = (cliphigh + gl_sidedef->offsetx_top) * grTex->scaleX;
// Adjust t value for sloped walls
if (!(gl_linedef->flags & ML_SKEWTD))
@ -1213,7 +1214,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
else
texturevpeg = gl_frontsector->floorheight - gl_backsector->floorheight;
texturevpeg += gl_sidedef->rowoffset;
texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_bot;
// This is so that it doesn't overflow and screw up the wall, it doesn't need to go higher than the texture's height anyway
texturevpeg %= textureheight[gl_bottomtexture];
@ -1222,8 +1223,8 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY;
wallVerts[0].t = wallVerts[1].t = (texturevpeg + gl_backsector->floorheight - gl_frontsector->floorheight) * grTex->scaleY;
wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX;
wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX;
wallVerts[0].s = wallVerts[3].s = (cliplow + gl_sidedef->offsetx_bot) * grTex->scaleX;
wallVerts[2].s = wallVerts[1].s = (cliphigh + gl_sidedef->offsetx_bot) * grTex->scaleX;
// Adjust t value for sloped walls
if (!(gl_linedef->flags & ML_SKEWTD))
@ -1333,13 +1334,13 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
// Peg it to the floor
if (gl_linedef->flags & ML_MIDPEG)
{
polybottom = max(front->floorheight, back->floorheight) + gl_sidedef->rowoffset;
polybottom = max(front->floorheight, back->floorheight) + gl_sidedef->rowoffset + gl_sidedef->offsety_mid;
polytop = polybottom + midtexheight;
}
// Peg it to the ceiling
else
{
polytop = min(front->ceilingheight, back->ceilingheight) + gl_sidedef->rowoffset;
polytop = min(front->ceilingheight, back->ceilingheight) + gl_sidedef->rowoffset + gl_sidedef->offsety_mid;
polybottom = polytop - midtexheight;
}
@ -1350,9 +1351,9 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
// Skew the texture, but peg it to the floor
else if (gl_linedef->flags & ML_MIDPEG)
{
polybottom = popenbottom + gl_sidedef->rowoffset;
polybottom = popenbottom + gl_sidedef->rowoffset + gl_sidedef->offsety_mid;
polytop = polybottom + midtexheight;
polybottomslope = popenbottomslope + gl_sidedef->rowoffset;
polybottomslope = popenbottomslope + gl_sidedef->rowoffset + gl_sidedef->offsety_mid;
polytopslope = polybottomslope + midtexheight;
}
// Skew it according to the ceiling's slope
@ -1407,12 +1408,12 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
// Left side
wallVerts[3].t = texturevpeg * grTex->scaleY;
wallVerts[0].t = (h - l + texturevpeg) * grTex->scaleY;
wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX;
wallVerts[0].s = wallVerts[3].s = (cliplow + gl_sidedef->offsetx_mid) * grTex->scaleX;
// Right side
wallVerts[2].t = texturevpegslope * grTex->scaleY;
wallVerts[1].t = (hS - lS + texturevpegslope) * grTex->scaleY;
wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX;
wallVerts[2].s = wallVerts[1].s = (cliphigh + gl_sidedef->offsetx_mid) * grTex->scaleX;
// set top/bottom coords
// Take the texture peg into account, rather than changing the offsets past
@ -1474,19 +1475,19 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
// PEGGING
if ((gl_linedef->flags & (ML_DONTPEGBOTTOM|ML_NOSKEW)) == (ML_DONTPEGBOTTOM|ML_NOSKEW))
texturevpeg = gl_frontsector->floorheight + textureheight[gl_sidedef->midtexture] - gl_frontsector->ceilingheight + gl_sidedef->rowoffset;
texturevpeg = gl_frontsector->floorheight + textureheight[gl_sidedef->midtexture] - gl_frontsector->ceilingheight + gl_sidedef->rowoffset + gl_sidedef->offsety_mid;
else if (gl_linedef->flags & ML_DONTPEGBOTTOM)
texturevpeg = worldbottom + textureheight[gl_sidedef->midtexture] - worldtop + gl_sidedef->rowoffset;
texturevpeg = worldbottom + textureheight[gl_sidedef->midtexture] - worldtop + gl_sidedef->rowoffset + gl_sidedef->offsety_mid;
else
// top of texture at top
texturevpeg = gl_sidedef->rowoffset;
texturevpeg = gl_sidedef->rowoffset + gl_sidedef->offsety_mid;
grTex = HWR_GetTexture(gl_midtexture);
wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY;
wallVerts[0].t = wallVerts[1].t = (texturevpeg + gl_frontsector->ceilingheight - gl_frontsector->floorheight) * grTex->scaleY;
wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX;
wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX;
wallVerts[0].s = wallVerts[3].s = (cliplow + gl_sidedef->offsetx_mid) * grTex->scaleX;
wallVerts[2].s = wallVerts[1].s = (cliphigh + gl_sidedef->offsetx_mid) * grTex->scaleX;
// Texture correction for slopes
if (gl_linedef->flags & ML_NOSKEW) {
@ -1634,13 +1635,13 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
// -- Monster Iestyn 26/06/18
if (newline)
{
texturevpeg = sides[newline->sidenum[0]].rowoffset;
texturevpeg = sides[newline->sidenum[0]].rowoffset + sides[newline->sidenum[0]].offsety_mid;
attachtobottom = !!(newline->flags & ML_DONTPEGBOTTOM);
slopeskew = !!(newline->flags & ML_SKEWTD);
}
else
{
texturevpeg = sides[rover->master->sidenum[0]].rowoffset;
texturevpeg = sides[rover->master->sidenum[0]].rowoffset + sides[rover->master->sidenum[0]].offsety_mid;
attachtobottom = !!(gl_linedef->flags & ML_DONTPEGBOTTOM);
slopeskew = !!(rover->master->flags & ML_SKEWTD);
}
@ -1672,8 +1673,8 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
}
}
wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX;
wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX;
wallVerts[0].s = wallVerts[3].s = (cliplow + gl_sidedef->offsetx_mid) * grTex->scaleX;
wallVerts[2].s = wallVerts[1].s = (cliphigh + gl_sidedef->offsetx_mid) * grTex->scaleX;
}
if (rover->fofflags & FOF_FOG)
{
@ -1698,7 +1699,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend)
{
blendmode = rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent;
Surf.PolyColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1;
Surf.PolyColor.s.alpha = max(0, min(rover->alpha, 255));
}
if (gl_frontsector->numlights)
@ -1785,17 +1786,17 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
if (newline)
{
wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + sides[newline->sidenum[0]].rowoffset) * grTex->scaleY;
wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + sides[newline->sidenum[0]].rowoffset)) * grTex->scaleY;
wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + sides[newline->sidenum[0]].rowoffset + sides[newline->sidenum[0]].offsety_mid) * grTex->scaleY;
wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + sides[newline->sidenum[0]].rowoffset) + sides[newline->sidenum[0]].offsety_mid) * grTex->scaleY;
}
else
{
wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset) * grTex->scaleY;
wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset)) * grTex->scaleY;
wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset + sides[rover->master->sidenum[0]].offsety_mid) * grTex->scaleY;
wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset + sides[rover->master->sidenum[0]].offsety_mid)) * grTex->scaleY;
}
wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX;
wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX;
wallVerts[0].s = wallVerts[3].s = (cliplow + gl_sidedef->offsetx_mid) * grTex->scaleX;
wallVerts[2].s = wallVerts[1].s = (cliphigh + gl_sidedef->offsetx_mid) * grTex->scaleX;
}
if (rover->fofflags & FOF_FOG)
@ -1821,7 +1822,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend)
{
blendmode = rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent;
Surf.PolyColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1;
Surf.PolyColor.s.alpha = max(0, min(rover->alpha, 255));
}
if (gl_backsector->numlights)
@ -2719,30 +2720,30 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling,
{
if (!isceiling) // it's a floor
{
scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatheight;
angle = FOFsector->floorpic_angle;
scrollx = FIXED_TO_FLOAT(FOFsector->floorxoffset)/fflatwidth;
scrolly = FIXED_TO_FLOAT(FOFsector->flooryoffset)/fflatheight;
angle = FOFsector->floorangle;
}
else // it's a ceiling
{
scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatheight;
angle = FOFsector->ceilingpic_angle;
scrollx = FIXED_TO_FLOAT(FOFsector->ceilingxoffset)/fflatwidth;
scrolly = FIXED_TO_FLOAT(FOFsector->ceilingyoffset)/fflatheight;
angle = FOFsector->ceilingangle;
}
}
else if (gl_frontsector)
{
if (!isceiling) // it's a floor
{
scrollx = FIXED_TO_FLOAT(gl_frontsector->floor_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(gl_frontsector->floor_yoffs)/fflatheight;
angle = gl_frontsector->floorpic_angle;
scrollx = FIXED_TO_FLOAT(gl_frontsector->floorxoffset)/fflatwidth;
scrolly = FIXED_TO_FLOAT(gl_frontsector->flooryoffset)/fflatheight;
angle = gl_frontsector->floorangle;
}
else // it's a ceiling
{
scrollx = FIXED_TO_FLOAT(gl_frontsector->ceiling_xoffs)/fflatwidth;
scrolly = FIXED_TO_FLOAT(gl_frontsector->ceiling_yoffs)/fflatheight;
angle = gl_frontsector->ceilingpic_angle;
scrollx = FIXED_TO_FLOAT(gl_frontsector->ceilingxoffset)/fflatwidth;
scrolly = FIXED_TO_FLOAT(gl_frontsector->ceilingyoffset)/fflatheight;
angle = gl_frontsector->ceilingangle;
}
}
@ -3094,7 +3095,7 @@ static void HWR_Subsector(size_t num)
false,
*rover->bottomheight,
*gl_frontsector->lightlist[light].lightlevel,
rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector,
max(0, min(rover->alpha, 255)), rover->master->frontsector,
HWR_RippleBlend(gl_frontsector, rover, false) | (rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent),
false, *gl_frontsector->lightlist[light].extra_colormap);
}
@ -3140,7 +3141,7 @@ static void HWR_Subsector(size_t num)
true,
*rover->topheight,
*gl_frontsector->lightlist[light].lightlevel,
rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector,
max(0, min(rover->alpha, 255)), rover->master->frontsector,
HWR_RippleBlend(gl_frontsector, rover, false) | (rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent),
false, *gl_frontsector->lightlist[light].extra_colormap);
}
@ -3594,7 +3595,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
return;
}
floordiff = abs((flip < 0 ? thing->height : 0) + interp.z - groundz);
floordiff = abs((flip < 0 ? interp.height : 0) + interp.z - groundz);
alpha = floordiff / (4*FRACUNIT) + 75;
if (alpha >= 255) return;
@ -3605,7 +3606,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
HWR_GetPatch(gpatch);
scalemul = FixedMul(FRACUNIT - floordiff/640, scale);
scalemul = FixedMul(scalemul, (thing->radius*2) / gpatch->height);
scalemul = FixedMul(scalemul, (interp.radius*2) / gpatch->height);
fscale = FIXED_TO_FLOAT(scalemul);
fx = FIXED_TO_FLOAT(interp.x);
@ -3717,7 +3718,7 @@ static void HWR_RotateSpritePolyToAim(gl_vissprite_t *spr, FOutVector *wallVerts
if (P_MobjFlip(spr->mobj) == -1)
{
basey = FIXED_TO_FLOAT(interp.z + spr->mobj->height);
basey = FIXED_TO_FLOAT(interp.z + interp.height);
}
else
{
@ -4036,6 +4037,54 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
HWR_LinkDrawHackAdd(wallVerts, spr);
}
static void HWR_DrawBoundingBox(gl_vissprite_t *vis)
{
FOutVector v[24];
FSurfaceInfo Surf = {0};
//
// create a cube (side view)
//
// 5--4 3
// |
// |
// 0--1 2
//
// repeat this 4 times (overhead)
//
//
// 15 16 17 09
// 14 13 12 08
// 23 18 *--* 07 10
// | |
// 22 19 *--* 06 11
// 20 00 01 02
// 21 05 04 03
//
v[ 0].x = v[ 5].x = v[13].x = v[14].x = v[15].x = v[16].x =
v[18].x = v[19].x = v[20].x = v[21].x = v[22].x = v[23].x = vis->x1; // west
v[ 1].x = v[ 2].x = v[ 3].x = v[ 4].x = v[ 6].x = v[ 7].x =
v[ 8].x = v[ 9].x = v[10].x = v[11].x = v[12].x = v[17].x = vis->x2; // east
v[ 0].z = v[ 1].z = v[ 2].z = v[ 3].z = v[ 4].z = v[ 5].z =
v[ 6].z = v[11].z = v[19].z = v[20].z = v[21].z = v[22].z = vis->z1; // south
v[ 7].z = v[ 8].z = v[ 9].z = v[10].z = v[12].z = v[13].z =
v[14].z = v[15].z = v[16].z = v[17].z = v[18].z = v[23].z = vis->z2; // north
v[ 0].y = v[ 1].y = v[ 2].y = v[ 6].y = v[ 7].y = v[ 8].y =
v[12].y = v[13].y = v[14].y = v[18].y = v[19].y = v[20].y = vis->gz; // bottom
v[ 3].y = v[ 4].y = v[ 5].y = v[ 9].y = v[10].y = v[11].y =
v[15].y = v[16].y = v[17].y = v[21].y = v[22].y = v[23].y = vis->gzt; // top
Surf.PolyColor = V_GetColor(R_GetBoundingBoxColor(vis->mobj));
HWR_ProcessPolygon(&Surf, v, 24, (cv_renderhitboxgldepth.value ? 0 : PF_NoDepthTest)|PF_Modulated|PF_NoTexture|PF_WireFrame, SHADER_NONE, false);
}
// -----------------+
// HWR_DrawSprite : Draw flat sprites
// : (monsters, bonuses, weapons, lights, ...)
@ -4092,14 +4141,11 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
float xscale, yscale;
float xoffset, yoffset;
float leftoffset, topoffset;
float scale = spr->scale;
float zoffset = (P_MobjFlip(spr->mobj) * 0.05f);
pslope_t *splatslope = NULL;
INT32 i;
renderflags_t renderflags = spr->renderflags;
if (renderflags & RF_SHADOWEFFECTS)
scale *= spr->shadowscale;
if (spr->rotateflags & SRF_3D || renderflags & RF_NOSPLATBILLBOARD)
angle = spr->mobj->angle;
@ -4107,7 +4153,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
angle = viewangle;
if (!spr->rotated)
angle += spr->mobj->rollangle;
angle += spr->mobj->spriteroll;
angle = -angle;
angle += ANGLE_90;
@ -4480,9 +4526,16 @@ static int CompareVisSprites(const void *p1, const void *p2)
int transparency1;
int transparency2;
int linkdraw1;
int linkdraw2;
// draw bbox after everything else
if (spr1->bbox || spr2->bbox)
return (spr1->bbox - spr2->bbox);
// check for precip first, because then sprX->mobj is actually a precipmobj_t and does not have flags2 or tracer
int linkdraw1 = !spr1->precip && (spr1->mobj->flags2 & MF2_LINKDRAW) && spr1->mobj->tracer;
int linkdraw2 = !spr2->precip && (spr2->mobj->flags2 & MF2_LINKDRAW) && spr2->mobj->tracer;
linkdraw1 = !spr1->precip && (spr1->mobj->flags2 & MF2_LINKDRAW) && spr1->mobj->tracer;
linkdraw2 = !spr2->precip && (spr2->mobj->flags2 & MF2_LINKDRAW) && spr2->mobj->tracer;
// ^ is the XOR operation
// if comparing a linkdraw and non-linkdraw sprite or 2 linkdraw sprites with different tracers, then use
@ -4852,6 +4905,9 @@ static void HWR_DrawSprites(void)
for (i = 0; i < gl_visspritecount; i++)
{
gl_vissprite_t *spr = gl_vsprorder[i];
if (spr->bbox)
HWR_DrawBoundingBox(spr);
else
#ifdef HWPRECIP
if (spr->precip)
HWR_DrawPrecipitationSprite(spr);
@ -4951,8 +5007,15 @@ static void HWR_AddSprites(sector_t *sec)
hoop_limit_dist = (fixed_t)(cv_drawdist_nights.value) << FRACBITS;
for (thing = sec->thinglist; thing; thing = thing->snext)
{
if (R_ThingVisibleWithinDist(thing, limit_dist, hoop_limit_dist))
HWR_ProjectSprite(thing);
if (R_ThingWithinDist(thing, limit_dist, hoop_limit_dist))
{
if (R_ThingVisible(thing))
{
HWR_ProjectSprite(thing);
}
HWR_ProjectBoundingBox(thing);
}
}
#ifdef HWPRECIP
@ -5010,6 +5073,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
#ifdef ROTSPRITE
patch_t *rotsprite = NULL;
INT32 rollangle = 0;
angle_t spriterotangle = 0;
#endif
// uncapped/interpolation
@ -5031,7 +5095,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
return;
}
dispoffset = thing->info->dispoffset;
dispoffset = thing->dispoffset;
if (R_UsingFrameInterpolation() && !paused)
@ -5177,18 +5241,21 @@ static void HWR_ProjectSprite(mobj_t *thing)
spr_topoffset = spritecachedinfo[lumpoff].topoffset;
#ifdef ROTSPRITE
if (thing->rollangle
spriterotangle = R_SpriteRotationAngle(&interp);
if (spriterotangle != 0
&& !(splat && !(thing->renderflags & RF_NOSPLATROLLANGLE)))
{
if (papersprite)
{
// a positive rollangle should should pitch papersprites upwards relative to their facing angle
rollangle = R_GetRollAngle(InvAngle(thing->rollangle));
rollangle = R_GetRollAngle(InvAngle(spriterotangle));
}
else
{
rollangle = R_GetRollAngle(thing->rollangle);
rollangle = R_GetRollAngle(spriterotangle);
}
rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, false, sprinfo, rollangle);
if (rotsprite != NULL)
@ -5254,7 +5321,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
}
groundz = R_GetShadowZ(thing, NULL);
floordiff = abs(((thing->eflags & MFE_VERTICALFLIP) ? caster->height : 0) + casterinterp.z - groundz);
floordiff = abs(((thing->eflags & MFE_VERTICALFLIP) ? casterinterp.height : 0) + casterinterp.z - groundz);
shadowheight = FIXED_TO_FLOAT(floordiff);
shadowscale = FIXED_TO_FLOAT(FixedMul(FRACUNIT - floordiff/640, casterinterp.scale));
@ -5306,7 +5373,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
if (vflip)
{
gz = FIXED_TO_FLOAT(interp.z + thing->height) - (FIXED_TO_FLOAT(spr_topoffset) * this_yscale);
gz = FIXED_TO_FLOAT(interp.z + interp.height) - (FIXED_TO_FLOAT(spr_topoffset) * this_yscale);
gzt = gz + (FIXED_TO_FLOAT(spr_height) * this_yscale);
}
else
@ -5470,6 +5537,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
vis->vflip = vflip;
vis->precip = false;
vis->bbox = false;
vis->angle = interp.angle;
}
@ -5592,6 +5660,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
vis->gz = vis->gzt - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].height);
vis->precip = true;
vis->bbox = false;
// okay... this is a hack, but weather isn't networked, so it should be ok
if (!(thing->precipflags & PCF_THUNK))
@ -5605,6 +5674,58 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
}
#endif
static void HWR_ProjectBoundingBox(mobj_t *thing)
{
gl_vissprite_t *vis;
float tr_x, tr_y;
float tz;
if (!thing)
return;
if (!R_ThingBoundingBoxVisible(thing))
return;
// uncapped/interpolation
boolean interpolate = cv_renderhitboxinterpolation.value;
interpmobjstate_t interp = {0};
if (R_UsingFrameInterpolation() && !paused && interpolate)
{
R_InterpolateMobjState(thing, rendertimefrac, &interp);
}
else
{
R_InterpolateMobjState(thing, FRACUNIT, &interp);
}
// transform the origin point
tr_x = FIXED_TO_FLOAT(interp.x) - gl_viewx;
tr_y = FIXED_TO_FLOAT(interp.y) - gl_viewy;
// rotation around vertical axis
tz = (tr_x * gl_viewcos) + (tr_y * gl_viewsin);
// thing is behind view plane?
if (tz < ZCLIP_PLANE)
return;
tr_x += gl_viewx;
tr_y += gl_viewy;
vis = HWR_NewVisSprite();
vis->x1 = tr_x - FIXED_TO_FLOAT(interp.radius);
vis->x2 = tr_x + FIXED_TO_FLOAT(interp.radius);
vis->z1 = tr_y - FIXED_TO_FLOAT(interp.radius);
vis->z2 = tr_y + FIXED_TO_FLOAT(interp.radius);
vis->gz = FIXED_TO_FLOAT(interp.z);
vis->gzt = vis->gz + FIXED_TO_FLOAT(interp.height);
vis->mobj = thing;
vis->precip = false;
vis->bbox = true;
}
// ==========================================================================
// Sky dome rendering, ported from PrBoom+
// ==========================================================================
@ -5788,6 +5909,8 @@ static void HWR_DrawSkyBackground(player_t *player)
fixed_t rol = AngleFixed(player->viewrollangle);
dometransform.rollangle = FIXED_TO_FLOAT(rol);
dometransform.roll = true;
dometransform.rollx = 1.0f;
dometransform.rollz = 0.0f;
}
dometransform.splitscreen = splitscreen;
@ -6066,6 +6189,8 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player)
fixed_t rol = AngleFixed(player->viewrollangle);
atransform.rollangle = FIXED_TO_FLOAT(rol);
atransform.roll = true;
atransform.rollx = 1.0f;
atransform.rollz = 0.0f;
}
atransform.splitscreen = splitscreen;
@ -6280,6 +6405,8 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
fixed_t rol = AngleFixed(player->viewrollangle);
atransform.rollangle = FIXED_TO_FLOAT(rol);
atransform.roll = true;
atransform.rollx = 1.0f;
atransform.rollz = 0.0f;
}
atransform.splitscreen = splitscreen;

View file

@ -115,6 +115,7 @@ extern float gl_viewwindowx, gl_basewindowcentery;
// BP: big hack for a test in lighting ref : 1249753487AB
extern fixed_t *hwbbox;
extern FTransform atransform;
extern float gl_viewsin, gl_viewcos;
// Render stats

View file

@ -486,7 +486,7 @@ void HWR_InitModels(void)
size_t i;
INT32 s;
FILE *f;
char name[24], filename[32];
char name[26], filename[32];
float scale, offset;
size_t prefixlen;
@ -585,7 +585,7 @@ modelfound:
void HWR_AddPlayerModel(int skin) // For skins that were added after startup
{
FILE *f;
char name[24], filename[32];
char name[26], filename[32];
float scale, offset;
size_t prefixlen;
@ -644,7 +644,7 @@ void HWR_AddSpriteModel(size_t spritenum) // For sprites that were added after s
// name[24] is used to check for names in the models.dat file that match with sprites or player skins
// sprite names are always 4 characters long, and names is for player skins can be up to 19 characters long
// PLAYERMODELPREFIX is 6 characters long
char name[24], filename[32];
char name[26], filename[32];
float scale, offset;
if (nomd2s)
@ -1146,7 +1146,7 @@ static void HWR_GetBlendedTexture(patch_t *patch, patch_t *blendpatch, INT32 ski
static boolean HWR_AllowModel(mobj_t *mobj)
{
// Signpost overlay. Not needed.
if (mobj->state-states == S_PLAY_SIGN)
if (mobj->sprite2 == SPR2_SIGN || mobj->state-states == S_PLAY_SIGN)
return false;
// Otherwise, render the model.
@ -1346,10 +1346,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
const UINT8 hflip = (UINT8)(!(spr->mobj->mirrored) != !R_ThingHorizontallyFlipped(spr->mobj));
spritedef_t *sprdef;
spriteframe_t *sprframe;
spriteinfo_t *sprinfo;
angle_t ang;
INT32 mod;
float finalscale;
interpmobjstate_t interp;
if (R_UsingFrameInterpolation() && !paused)
@ -1388,12 +1385,10 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
{
md2 = &md2_playermodels[(skin_t*)spr->mobj->skin-skins];
md2->skin = (skin_t*)spr->mobj->skin-skins;
sprinfo = &((skin_t *)spr->mobj->skin)->sprinfo[spr->mobj->sprite2];
}
else
{
md2 = &md2_models[spr->mobj->sprite];
sprinfo = &spriteinfo[spr->mobj->sprite];
}
// texture loading before model init, so it knows if sprite graphics are used, which
@ -1455,7 +1450,6 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
}
//HWD.pfnSetBlend(blend); // This seems to actually break translucency?
finalscale = md2->scale;
//Hurdler: arf, I don't like that implementation at all... too much crappy
if (gpatch && hwrPatch && hwrPatch->mipmap->format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture
@ -1591,7 +1585,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
p.y = FIXED_TO_FLOAT(interp.y)+md2->offset;
if (flip)
p.z = FIXED_TO_FLOAT(interp.z + spr->mobj->height);
p.z = FIXED_TO_FLOAT(interp.z + interp.height);
else
p.z = FIXED_TO_FLOAT(interp.z);
@ -1614,61 +1608,56 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
p.angley = FIXED_TO_FLOAT(anglef);
}
p.rollangle = 0.0f;
p.rollflip = 1;
p.rotaxis = 0;
if (spr->mobj->rollangle)
{
fixed_t anglef = AngleFixed(spr->mobj->rollangle);
p.rollangle = FIXED_TO_FLOAT(anglef);
p.roll = true;
fixed_t anglef = AngleFixed(R_ModelRotationAngle(&interp));
// rotation pivot
p.centerx = FIXED_TO_FLOAT(spr->mobj->radius/2);
p.centery = FIXED_TO_FLOAT(spr->mobj->height/(flip ? -2 : 2));
p.rollangle = 0.0f;
// rotation axis
if (sprinfo->available)
p.rotaxis = (UINT8)(sprinfo->pivot[(spr->mobj->frame & FF_FRAMEMASK)].rotaxis);
if (anglef)
{
fixed_t camAngleDiff = AngleFixed(viewangle) - FLOAT_TO_FIXED(p.angley); // dumb reconversion back, I know
// for NiGHTS specifically but should work everywhere else
ang = R_PointToAngle (interp.x, interp.y) - interp.angle;
if ((sprframe->rotate & SRF_RIGHT) && (ang < ANGLE_180)) // See from right
p.rollflip = 1;
else if ((sprframe->rotate & SRF_LEFT) && (ang >= ANGLE_180)) // See from left
p.rollflip = -1;
p.rollangle = FIXED_TO_FLOAT(anglef);
p.roll = true;
if (flip)
p.rollflip *= -1;
// rotation pivot
p.centerx = FIXED_TO_FLOAT(interp.radius / 2);
p.centery = FIXED_TO_FLOAT(interp.height / 2);
// rotation axes relative to camera
p.rollx = FIXED_TO_FLOAT(FINECOSINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT));
p.rollz = FIXED_TO_FLOAT(FINESINE(FixedAngle(camAngleDiff) >> ANGLETOFINESHIFT));
}
}
p.anglex = 0.0f;
#ifdef USE_FTRANSFORM_ANGLEZ
// Slope rotation from Kart
p.anglez = 0.0f;
if (spr->mobj->standingslope)
{
fixed_t tempz = spr->mobj->standingslope->normal.z;
fixed_t tempy = spr->mobj->standingslope->normal.y;
fixed_t tempx = spr->mobj->standingslope->normal.x;
fixed_t tempangle = AngleFixed(R_PointToAngle2(0, 0, FixedSqrt(FixedMul(tempy, tempy) + FixedMul(tempz, tempz)), tempx));
p.anglez = FIXED_TO_FLOAT(tempangle);
tempangle = -AngleFixed(R_PointToAngle2(0, 0, tempz, tempy));
p.anglex = FIXED_TO_FLOAT(tempangle);
}
#if 0
p.anglez = FIXED_TO_FLOAT(AngleFixed(interp.pitch));
p.anglex = FIXED_TO_FLOAT(AngleFixed(interp.roll));
#else
p.anglez = 0.f;
p.anglex = 0.f;
#endif
// SRB2CBTODO: MD2 scaling support
finalscale *= FIXED_TO_FLOAT(spr->mobj->scale);
p.flip = atransform.flip;
#ifdef USE_FTRANSFORM_MIRROR
p.mirror = atransform.mirror; // from Kart
#endif
p.mirror = atransform.mirror;
HWD.pfnSetShader(SHADER_MODEL); // model shader
HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, hflip, &Surf);
{
float this_scale = FIXED_TO_FLOAT(interp.scale);
float xs = this_scale * FIXED_TO_FLOAT(interp.spritexscale);
float ys = this_scale * FIXED_TO_FLOAT(interp.spriteyscale);
float ox = xs * FIXED_TO_FLOAT(interp.spritexoffset);
float oy = ys * FIXED_TO_FLOAT(interp.spriteyoffset);
// offset perpendicular to the camera angle
p.x -= ox * gl_viewsin;
p.y += ox * gl_viewcos;
p.z += oy;
HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, md2->scale * xs, md2->scale * ys, flip, hflip, &Surf);
}
}
return true;

View file

@ -15,7 +15,7 @@
#include "hw_md2load.h"
#include "hw_md3load.h"
#include "hw_md2.h"
#include "u_list.h"
#include "../u_list.h"
#include <string.h>
static float PI = (3.1415926535897932384626433832795f);
@ -672,6 +672,9 @@ void GeneratePolygonNormals(model_t *model, int ztag)
for (k = 0; k < mesh->numTriangles; k++)
{
/// TODO: normalize vectors
(void)vertices;
(void)polyNormals;
// Vector::Normal(vertices, polyNormals);
vertices += 3 * 3;
polyNormals++;

View file

@ -1030,6 +1030,12 @@ EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boole
EXPORT void HWRAPI(SetShader) (int type)
{
#ifdef GL_SHADERS
if (type == SHADER_NONE)
{
UnSetShader();
return;
}
if (gl_allowshaders != HWD_SHADEROPTION_OFF)
{
gl_shader_t *shader = gl_shaderstate.current;
@ -2290,7 +2296,7 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUI
pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x);
pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].s);
pglDrawArrays(GL_TRIANGLE_FAN, 0, iNumPts);
pglDrawArrays(PolyFlags & PF_WireFrame ? GL_LINES : GL_TRIANGLE_FAN, 0, iNumPts);
if (PolyFlags & PF_RemoveYWrap)
pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
@ -2673,7 +2679,7 @@ EXPORT void HWRAPI(CreateModelVBOs) (model_t *model)
#define BUFFER_OFFSET(i) ((void*)(i))
static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface)
static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface)
{
static GLRGBAFloat poly = {0,0,0,0};
static GLRGBAFloat tint = {0,0,0,0};
@ -2697,10 +2703,11 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float
#endif
// Affect input model scaling
scale *= 0.5f;
scalex = scale;
scaley = scale;
scalez = scale;
hscale *= 0.5f;
vscale *= 0.5f;
scalex = hscale;
scaley = vscale;
scalez = hscale;
if (duration > 0.0 && tics >= 0.0) // don't interpolate if instantaneous or infinite in length
{
@ -2776,7 +2783,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float
pglEnable(GL_CULL_FACE);
pglEnable(GL_NORMALIZE);
#ifdef USE_FTRANSFORM_MIRROR
// flipped is if the object is vertically flipped
// hflipped is if the object is horizontally flipped
// pos->flip is if the screen is flipped vertically
@ -2789,17 +2795,6 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float
else
pglCullFace(GL_BACK);
}
#else
// pos->flip is if the screen is flipped too
if (flipped ^ hflipped ^ pos->flip) // If one or three of these are active, but not two, invert the model's culling
{
pglCullFace(GL_FRONT);
}
else
{
pglCullFace(GL_BACK);
}
#endif
pglPushMatrix(); // should be the same as glLoadIdentity
//Hurdler: now it seems to work
@ -2809,22 +2804,14 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float
if (hflipped)
scalez = -scalez;
#ifdef USE_FTRANSFORM_ANGLEZ
pglRotatef(pos->anglez, 0.0f, 0.0f, -1.0f); // rotate by slope from Kart
#endif
pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f);
pglRotatef(pos->anglez, 0.0f, 0.0f, -1.0f);
pglRotatef(pos->anglex, 1.0f, 0.0f, 0.0f);
pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f);
if (pos->roll)
{
float roll = (1.0f * pos->rollflip);
pglTranslatef(pos->centerx, pos->centery, 0);
if (pos->rotaxis == 2) // Z
pglRotatef(pos->rollangle, 0.0f, 0.0f, roll);
else if (pos->rotaxis == 1) // Y
pglRotatef(pos->rollangle, 0.0f, roll, 0.0f);
else // X
pglRotatef(pos->rollangle, roll, 0.0f, 0.0f);
pglRotatef(pos->rollangle, pos->rollx, 0.0f, pos->rollz);
pglTranslatef(-pos->centerx, -pos->centery, 0);
}
@ -2978,9 +2965,9 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float
// -----------------+
// HWRAPI DrawModel : Draw a model
// -----------------+
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface)
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, float duration, float tics, INT32 nextFrameIndex, FTransform *pos, float hscale, float vscale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface)
{
DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, hflipped, Surface);
DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, hscale, vscale, flipped, hflipped, Surface);
}
// -----------------+
@ -2997,13 +2984,9 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform)
if (stransform)
{
used_fov = stransform->fovxangle;
#ifdef USE_FTRANSFORM_MIRROR
// mirroring from Kart
if (stransform->mirror)
pglScalef(-stransform->scalex, stransform->scaley, -stransform->scalez);
else
#endif
if (stransform->flip)
else if (stransform->flip)
pglScalef(stransform->scalex, -stransform->scaley, -stransform->scalez);
else
pglScalef(stransform->scalex, stransform->scaley, -stransform->scalez);

View file

@ -159,7 +159,7 @@ HMS_connect (const char *format, ...)
return NULL;
}
if (cv_masterserver_token.string[0])
if (cv_masterserver_token.string && cv_masterserver_token.string[0])
{
quack_token = curl_easy_escape(curl, cv_masterserver_token.string, 0);
token_length = ( sizeof "?token="-1 )+ strlen(quack_token);
@ -216,7 +216,11 @@ HMS_connect (const char *format, ...)
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
#ifndef NO_IPV6
if (M_CheckParm("-noipv6"))
#endif
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, cv_masterserver_timeout.value);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HMS_on_read);

View file

@ -2025,7 +2025,7 @@ void HU_Drawer(void)
V_DrawCenteredString(BASEVIDWIDTH/2, 180, V_YELLOWMAP | V_ALLOWLOWERCASE, resynch_text);
}
if (modeattacking && pausedelay > 0 && !pausebreakkey)
if (modeattacking && pausedelay > 0 && !(pausebreakkey || cv_instantretry.value))
{
INT32 strength = ((pausedelay - 1 - NEWTICRATE/2)*10)/(NEWTICRATE/3);
INT32 y = hudinfo[HUD_LIVES].y - 13;
@ -2862,18 +2862,6 @@ static void HU_DrawRankings(void)
V_DrawCenteredString(256, 16, 0, va("%d", cv_pointlimit.value));
}
}
else if (gametyperankings[gametype] == GT_COOP)
{
INT32 totalscore = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i])
totalscore += players[i].score;
}
V_DrawCenteredString(256, 8, 0, "TOTAL SCORE");
V_DrawCenteredString(256, 16, 0, va("%u", totalscore));
}
else
{
if (circuitmap)
@ -2994,9 +2982,9 @@ static void HU_DrawCoopOverlay(void)
V_DrawSmallScaledPatch(148, 172, 0, tokenicon);
}
if (LUA_HudEnabled(hud_tabemblems) && (!modifiedgame || savemoddata))
if (LUA_HudEnabled(hud_tabemblems))
{
V_DrawString(160, 144, 0, va("- %d/%d", M_CountEmblems(), numemblems+numextraemblems));
V_DrawString(160, 144, 0, va("- %d/%d", M_CountEmblems(clientGamedata), numemblems+numextraemblems));
V_DrawScaledPatch(128, 144 - emblemicon->height/4, 0, emblemicon);
}
@ -3029,6 +3017,15 @@ static void HU_DrawNetplayCoopOverlay(void)
V_DrawSmallScaledPatch(148, 6, 0, tokenicon);
}
if (G_CoopGametype() && LUA_HudEnabled(hud_tabemblems))
{
V_DrawCenteredString(256, 14, 0, "/");
V_DrawString(256 + 4, 14, 0, va("%d", numemblems + numextraemblems));
V_DrawRightAlignedString(256 - 4, 14, 0, va("%d", M_CountEmblems(clientGamedata)));
V_DrawSmallScaledPatch(256 - (emblemicon->width / 4), 6, 0, emblemicon);
}
if (!LUA_HudEnabled(hud_coopemeralds))
return;

View file

@ -109,6 +109,17 @@ extern boolean (*I_NetCanSend)(void);
*/
extern void (*I_NetFreeNodenum)(INT32 nodenum);
/**
\brief split a string into address and port
\param address string to split
\param port double pointer to hold port component (optional)
\return address component
*/
extern char *I_NetSplitAddress(char *address, char **port);
/** \brief open a connection with specified address
\param address address to connect to

View file

@ -40,7 +40,7 @@ extern UINT8 keyboard_started;
\return free memory in the system
*/
UINT32 I_GetFreeMem(UINT32 *total);
size_t I_GetFreeMem(size_t *total);
/** \brief Returns precise time value for performance measurement. The precise
time should be a monotonically increasing counter, and will wrap.
@ -49,6 +49,10 @@ UINT32 I_GetFreeMem(UINT32 *total);
*/
precise_t I_GetPreciseTime(void);
/** \brief Fills a buffer with random data, returns amount of data obtained.
*/
size_t I_GetRandomBytes(char *destination, size_t count);
/** \brief Get the precision of precise_t in units per second. Invocations of
this function for the program's duration MUST return the same value.
*/

View file

@ -340,8 +340,14 @@ static inline void I_UPnP_rem(const char *port, const char * servicetype)
static const char *SOCK_AddrToStr(mysockaddr_t *sk)
{
static char s[64]; // 255.255.255.255:65535 or IPv6:65535
static char s[64]; // 255.255.255.255:65535 or
// [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535
#ifdef HAVE_NTOP
#ifdef HAVE_IPV6
int v6 = (sk->any.sa_family == AF_INET6);
#else
int v6 = 0;
#endif
void *addr;
if(sk->any.sa_family == AF_INET)
@ -355,14 +361,21 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk)
if(addr == NULL)
sprintf(s, "No address");
else if(inet_ntop(sk->any.sa_family, addr, s, sizeof (s)) == NULL)
else if(inet_ntop(sk->any.sa_family, addr, &s[v6], sizeof (s) - v6) == NULL)
sprintf(s, "Unknown family type, error #%u", errno);
#ifdef HAVE_IPV6
else if(sk->any.sa_family == AF_INET6 && sk->ip6.sin6_port != 0)
strcat(s, va(":%d", ntohs(sk->ip6.sin6_port)));
else if(sk->any.sa_family == AF_INET6)
{
s[0] = '[';
strcat(s, "]");
if (sk->ip6.sin6_port != 0)
strcat(s, va(":%d", ntohs(sk->ip6.sin6_port)));
}
#endif
else if(sk->any.sa_family == AF_INET && sk->ip4.sin_port != 0)
strcat(s, va(":%d", ntohs(sk->ip4.sin_port)));
#else
if (sk->any.sa_family == AF_INET)
{
@ -427,7 +440,7 @@ static boolean SOCK_cmpaddr(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask)
&& (b->ip4.sin_port == 0 || (a->ip4.sin_port == b->ip4.sin_port));
#ifdef HAVE_IPV6
else if (b->any.sa_family == AF_INET6)
return memcmp(&a->ip6.sin6_addr, &b->ip6.sin6_addr, sizeof(b->ip6.sin6_addr))
return !memcmp(&a->ip6.sin6_addr, &b->ip6.sin6_addr, sizeof(b->ip6.sin6_addr))
&& (b->ip6.sin6_port == 0 || (a->ip6.sin6_port == b->ip6.sin6_port));
#endif
else
@ -735,8 +748,7 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
unsigned long trueval = true;
#endif
mysockaddr_t straddr;
struct sockaddr_in sin;
socklen_t len = sizeof(sin);
socklen_t len = sizeof(straddr);
if (s == (SOCKET_TYPE)ERRSOCKET)
return (SOCKET_TYPE)ERRSOCKET;
@ -754,14 +766,12 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
}
#endif
straddr.any = *addr;
memcpy(&straddr, addr, addrlen);
I_OutputMsg("Binding to %s\n", SOCK_AddrToStr(&straddr));
if (family == AF_INET)
{
mysockaddr_t tmpaddr;
tmpaddr.any = *addr ;
if (tmpaddr.ip4.sin_addr.s_addr == htonl(INADDR_ANY))
if (straddr.ip4.sin_addr.s_addr == htonl(INADDR_ANY))
{
opt = true;
opts = (socklen_t)sizeof(opt);
@ -778,7 +788,7 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
#ifdef HAVE_IPV6
else if (family == AF_INET6)
{
if (memcmp(addr, &in6addr_any, sizeof(in6addr_any)) == 0) //IN6_ARE_ADDR_EQUAL
if (memcmp(&straddr.ip6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0) //IN6_ARE_ADDR_EQUAL
{
opt = true;
opts = (socklen_t)sizeof(opt);
@ -788,7 +798,7 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
// make it IPv6 ony
opt = true;
opts = (socklen_t)sizeof(opt);
if (setsockopt(s, SOL_SOCKET, IPV6_V6ONLY, (char *)&opt, opts))
if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&opt, opts))
{
CONS_Alert(CONS_WARNING, M_GetText("Could not limit IPv6 bind\n")); // I do not care anymore
}
@ -830,10 +840,17 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
CONS_Printf(M_GetText("Network system buffer set to: %dKb\n"), opt>>10);
}
if (getsockname(s, (struct sockaddr *)&sin, &len) == -1)
if (getsockname(s, &straddr.any, &len) == -1)
CONS_Alert(CONS_WARNING, M_GetText("Failed to get port number\n"));
else
current_port = (UINT16)ntohs(sin.sin_port);
{
if (family == AF_INET)
current_port = (UINT16)ntohs(straddr.ip4.sin_port);
#ifdef HAVE_IPV6
else if (family == AF_INET6)
current_port = (UINT16)ntohs(straddr.ip6.sin6_port);
#endif
}
return s;
}
@ -844,7 +861,7 @@ static boolean UDP_Socket(void)
struct my_addrinfo *ai, *runp, hints;
int gaie;
#ifdef HAVE_IPV6
const INT32 b_ipv6 = M_CheckParm("-ipv6");
const INT32 b_ipv6 = !M_CheckParm("-noipv6");
#endif
const char *serv;
@ -1156,6 +1173,7 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port)
SINT8 newnode = -1;
struct my_addrinfo *ai = NULL, *runp, hints;
int gaie;
size_t i;
if (!port || !port[0])
port = DEFAULTPORT;
@ -1183,13 +1201,24 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port)
while (runp != NULL)
{
// find ip of the server
if (sendto(mysockets[0], NULL, 0, 0, runp->ai_addr, runp->ai_addrlen) == 0)
// test ip address of server
for (i = 0; i < mysocketses; ++i)
{
memcpy(&clientaddress[newnode], runp->ai_addr, runp->ai_addrlen);
break;
/* sendto tests that there is a network to this
address */
if (runp->ai_addr->sa_family == myfamily[i] &&
sendto(mysockets[i], NULL, 0, 0,
runp->ai_addr, runp->ai_addrlen) == 0)
{
memcpy(&clientaddress[newnode], runp->ai_addr, runp->ai_addrlen);
break;
}
}
runp = runp->ai_next;
if (i < mysocketses)
runp = runp->ai_next;
else
break;
}
I_freeaddrinfo(ai);
return newnode;

View file

@ -7194,7 +7194,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_cgot, // deathsound
EMERALD1, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
24*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
@ -7220,7 +7220,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_cgot, // deathsound
EMERALD2, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
24*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
@ -7246,7 +7246,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_cgot, // deathsound
EMERALD3, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
24*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
@ -7272,7 +7272,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_cgot, // deathsound
EMERALD4, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
24*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
@ -7298,7 +7298,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_cgot, // deathsound
EMERALD5, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
24*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
@ -7324,7 +7324,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_cgot, // deathsound
EMERALD6, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
24*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
@ -7350,7 +7350,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_cgot, // deathsound
EMERALD7, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
24*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
@ -18344,7 +18344,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_itemup, // deathsound
60*FRACUNIT, // speed
24*FRACUNIT, // radius
16*FRACUNIT, // radius
24*FRACUNIT, // height
0, // display offset
pw_bouncering, // mass
@ -18371,7 +18371,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_itemup, // deathsound
60*FRACUNIT, // speed
24*FRACUNIT, // radius
16*FRACUNIT, // radius
24*FRACUNIT, // height
0, // display offset
pw_railring, // mass
@ -18425,7 +18425,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_itemup, // deathsound
60*FRACUNIT, // speed
24*FRACUNIT, // radius
16*FRACUNIT, // radius
24*FRACUNIT, // height
0, // display offset
pw_automaticring, // mass
@ -18452,7 +18452,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_itemup, // deathsound
60*FRACUNIT, // speed
24*FRACUNIT, // radius
16*FRACUNIT, // radius
24*FRACUNIT, // height
0, // display offset
pw_explosionring, // mass
@ -18479,7 +18479,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_itemup, // deathsound
60*FRACUNIT, // speed
24*FRACUNIT, // radius
16*FRACUNIT, // radius
24*FRACUNIT, // height
0, // display offset
pw_scatterring, // mass
@ -18506,7 +18506,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_itemup, // deathsound
60*FRACUNIT, // speed
24*FRACUNIT, // radius
16*FRACUNIT, // radius
24*FRACUNIT, // height
0, // display offset
pw_grenadering, // mass
@ -18535,7 +18535,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_ncitem, // deathsound
60*FRACUNIT, // speed
24*FRACUNIT, // radius
24*FRACUNIT, // height
40*FRACUNIT, // height
0, // display offset
pw_bouncering, // mass
2*TICRATE, // damage
@ -18562,7 +18562,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_ncitem, // deathsound
60*FRACUNIT, // speed
24*FRACUNIT, // radius
24*FRACUNIT, // height
40*FRACUNIT, // height
0, // display offset
pw_railring, // mass
2*TICRATE, // damage
@ -18589,7 +18589,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_ncitem, // deathsound
60*FRACUNIT, // speed
24*FRACUNIT, // radius
24*FRACUNIT, // height
40*FRACUNIT, // height
0, // display offset
pw_automaticring, // mass
2*TICRATE, // damage
@ -18616,7 +18616,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_ncitem, // deathsound
60*FRACUNIT, // speed
24*FRACUNIT, // radius
24*FRACUNIT, // height
40*FRACUNIT, // height
0, // display offset
pw_explosionring, // mass
2*TICRATE, // damage
@ -18643,7 +18643,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_ncitem, // deathsound
60*FRACUNIT, // speed
24*FRACUNIT, // radius
24*FRACUNIT, // height
40*FRACUNIT, // height
0, // display offset
pw_scatterring, // mass
2*TICRATE, // damage
@ -18670,7 +18670,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_ncitem, // deathsound
60*FRACUNIT, // speed
24*FRACUNIT, // radius
24*FRACUNIT, // height
40*FRACUNIT, // height
0, // display offset
pw_grenadering, // mass
2*TICRATE, // damage
@ -21584,68 +21584,113 @@ skincolor_t skincolors[MAXSKINCOLORS] = {
{"Black", {0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1b, 0x1b, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f}, SKINCOLOR_WHITE, 7, V_GRAYMAP, true}, // SKINCOLOR_BLACK
// Desaturated
{"Aether", {0x00, 0x00, 0x01, 0x02, 0x02, 0x03, 0x91, 0x91, 0x91, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf}, SKINCOLOR_GREY, 15, 0, true}, // SKINCOLOR_AETHER
{"Slate", {0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0xaa, 0xaa, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_SILVER, 12, 0, true}, // SKINCOLOR_SLATE
{"Bluebell", {0x90, 0x91, 0x92, 0x93, 0x94, 0x94, 0x95, 0xac, 0xac, 0xad, 0xad, 0xa8, 0xa8, 0xa9, 0xfd, 0xfe}, SKINCOLOR_COPPER, 4, V_BLUEMAP, true}, // SKINCOLOR_BLUEBELL
{"Pink", {0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0x2b, 0x2c, 0x2e}, SKINCOLOR_AZURE, 9, V_REDMAP, true}, // SKINCOLOR_PINK
{"Yogurt", {0xd0, 0x30, 0xd8, 0xd9, 0xda, 0xdb, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe3, 0xe6, 0xe8, 0xe9}, SKINCOLOR_RUST, 7, V_BROWNMAP, true}, // SKINCOLOR_YOGURT
{"Brown", {0xdf, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef}, SKINCOLOR_TAN, 2, V_BROWNMAP, true}, // SKINCOLOR_BROWN
{"Bronze", {0xde, 0xe0, 0xe1, 0xe4, 0xe7, 0xe9, 0xeb, 0xec, 0xed, 0xed, 0xed, 0x19, 0x19, 0x1b, 0x1d, 0x1e}, SKINCOLOR_KETCHUP, 0, V_BROWNMAP, true}, // SKINCOLOR_BRONZE
{"Tan", {0x51, 0x51, 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0xf5, 0xf5, 0xf9, 0xf9, 0xed, 0xed}, SKINCOLOR_BROWN, 12, V_BROWNMAP, true}, // SKINCOLOR_TAN
{"Beige", {0x54, 0x55, 0x56, 0x56, 0xf2, 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfb, 0xed, 0xed}, SKINCOLOR_MOSS, 5, V_BROWNMAP, true}, // SKINCOLOR_BEIGE
{"Moss", {0x58, 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, 0x5f}, SKINCOLOR_BEIGE, 13, V_GREENMAP, true}, // SKINCOLOR_MOSS
{"Azure", {0x90, 0x90, 0x91, 0x91, 0xaa, 0xaa, 0xab, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf}, SKINCOLOR_PINK, 5, V_AZUREMAP, true}, // SKINCOLOR_AZURE
{"Lavender", {0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7}, SKINCOLOR_GOLD, 4, V_PURPLEMAP, true}, // SKINCOLOR_LAVENDER
{"Aether", {0x00, 0x00, 0x01, 0x01, 0x90, 0x90, 0x91, 0x91, 0x92, 0xaa, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xae}, SKINCOLOR_GREY, 15, 0, true}, // SKINCOLOR_AETHER
{"Slate", {0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0xaa, 0xaa, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_SILVER, 12, 0, true}, // SKINCOLOR_SLATE
{"Moonstone", { 0, 4, 8, 9, 11, 12, 14, 15, 171, 172, 173, 174, 175, 27, 29, 31}, SKINCOLOR_TOPAZ, 15, V_GRAYMAP, true}, // SKINCOLOR_MOONSTONE
{"Bluebell", {0x90, 0x91, 0x92, 0x93, 0x94, 0x94, 0x95, 0xac, 0xac, 0xad, 0xad, 0xa8, 0xa8, 0xa9, 0xfd, 0xfe}, SKINCOLOR_COPPER, 4, V_BLUEMAP, true}, // SKINCOLOR_BLUEBELL
{"Pink", {0xd0, 0xd0, 0xd1, 0xd1, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0x2b, 0x2c, 0x2e}, SKINCOLOR_AZURE, 9, V_REDMAP, true}, // SKINCOLOR_PINK
{"Rosewood", { 209, 210, 211, 212, 213, 214, 228, 230, 232, 234, 235, 237, 26, 27, 28, 29}, SKINCOLOR_SEPIA, 5, V_BROWNMAP, true}, // SKINCOLOR_ROSEWOOD
{"Yogurt", {0xd0, 0x30, 0xd8, 0xd9, 0xda, 0xdb, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe3, 0xe6, 0xe8, 0xe9}, SKINCOLOR_RUST, 7, V_BROWNMAP, true}, // SKINCOLOR_YOGURT
{"Latte", { 48, 217, 219, 221, 223, 224, 226, 228, 68, 69, 70, 70, 44, 45, 46, 47}, SKINCOLOR_BOTTLE, 12, V_BROWNMAP, true}, // SKINCOLOR_LATTE
{"Brown", {0xdf, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef}, SKINCOLOR_TAN, 2, V_BROWNMAP, true}, // SKINCOLOR_BROWN
{"Boulder", {0xde, 0xe0, 0xe1, 0xe4, 0xe7, 0xe9, 0xeb, 0xec, 0xed, 0xed, 0xed, 0x19, 0x19, 0x1b, 0x1d, 0x1e}, SKINCOLOR_KETCHUP, 0, V_BROWNMAP, true}, // SKINCOLOR_BOULDER
{"Bronze", { 82, 84, 50, 51, 223, 228, 230, 232, 234, 236, 237, 238, 239, 239, 30, 31}, SKINCOLOR_VOLCANIC, 9, V_BROWNMAP, true}, // SKINCOLOR_BRONZE
{"Sepia", { 88, 84, 85, 86, 224, 226, 228, 230, 232, 235, 236, 237, 238, 239, 28, 28}, SKINCOLOR_ROSEWOOD, 5, V_BROWNMAP, true}, // SKINCOLOR_SEPIA
{"Ecru", { 80, 83, 84, 85, 86, 242, 243, 245, 230, 232, 234, 236, 238, 239, 47, 47}, SKINCOLOR_ARCTIC, 12, V_BROWNMAP, true}, // SKINCOLOR_ECRU
{"Tan", {0x51, 0x51, 0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0xf5, 0xf5, 0xf9, 0xf9, 0xed, 0xed}, SKINCOLOR_BROWN, 12, V_BROWNMAP, true}, // SKINCOLOR_TAN
{"Beige", {0x54, 0x55, 0x56, 0x56, 0xf2, 0xf3, 0xf3, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfb, 0xed, 0xed}, SKINCOLOR_MOSS, 5, V_BROWNMAP, true}, // SKINCOLOR_BEIGE
{"Rosebush", { 208, 216, 209, 85, 90, 91, 91, 92, 191, 93, 94, 107, 109, 110, 111, 111}, SKINCOLOR_EGGPLANT, 5, V_GREENMAP, true}, // SKINCOLOR_ROSEBUSH
{"Moss", {0x58, 0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5e, 0x5f, 0x5f}, SKINCOLOR_BEIGE, 13, V_GREENMAP, true}, // SKINCOLOR_MOSS
{"Azure", {0x90, 0x90, 0x91, 0x91, 0xaa, 0xaa, 0xab, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf}, SKINCOLOR_PINK, 5, V_AZUREMAP, true}, // SKINCOLOR_AZURE
{"Eggplant", { 4, 8, 11, 11, 16, 195, 195, 195, 196, 186, 187, 187, 254, 254, 30, 31}, SKINCOLOR_ROSEBUSH, 5, V_PURPLEMAP, true}, // SKINCOLOR_EGGPLANT
{"Lavender", {0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7}, SKINCOLOR_GOLD, 4, V_PURPLEMAP, true}, // SKINCOLOR_LAVENDER
// Viv's vivid colours (toast 21/07/17)
// Tweaks & additions (Lach, Chrispy, sphere, Alice, MotorRoach & Saneko 26/10/22)
{"Ruby", {0xb0, 0xb0, 0xc9, 0xca, 0xcc, 0x26, 0x27, 0x28, 0x29, 0x2a, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfd}, SKINCOLOR_EMERALD, 10, V_REDMAP, true}, // SKINCOLOR_RUBY
{"Cherry", { 202, 203, 204, 205, 206, 40, 41, 42, 43, 44, 186, 187, 28, 29, 30, 31}, SKINCOLOR_MIDNIGHT, 10, V_REDMAP, true}, // SKINCOLOR_CHERRY
{"Salmon", {0xd0, 0xd0, 0xd1, 0xd2, 0x20, 0x21, 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e}, SKINCOLOR_FOREST, 6, V_REDMAP, true}, // SKINCOLOR_SALMON
{"Pepper", { 210, 32, 33, 34, 35, 35, 36, 37, 38, 39, 41, 43, 45, 45, 46, 47}, SKINCOLOR_MASTER, 8, V_REDMAP, true}, // SKINCOLOR_PEPPER
{"Red", {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x47, 0x2e, 0x2f}, SKINCOLOR_GREEN, 10, V_REDMAP, true}, // SKINCOLOR_RED
{"Crimson", {0x27, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2b, 0x2b, 0x2c, 0x2d, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x1f}, SKINCOLOR_ICY, 10, V_REDMAP, true}, // SKINCOLOR_CRIMSON
{"Flame", {0x31, 0x32, 0x33, 0x36, 0x22, 0x22, 0x25, 0x25, 0x25, 0xcd, 0xcf, 0xcf, 0xc5, 0xc5, 0xc7, 0xc7}, SKINCOLOR_PURPLE, 8, V_REDMAP, true}, // SKINCOLOR_FLAME
{"Ketchup", {0x48, 0x49, 0x40, 0x33, 0x34, 0x36, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2b, 0x2c, 0x47, 0x2e, 0x2f}, SKINCOLOR_BRONZE, 8, V_REDMAP, true}, // SKINCOLOR_KETCHUP
{"Garnet", { 0, 83, 50, 53, 34, 35, 37, 38, 39, 40, 42, 44, 45, 46, 47, 47}, SKINCOLOR_AQUAMARINE, 6, V_REDMAP, true}, // SKINCOLOR_GARNET
{"Ketchup", {0x48, 0x49, 0x40, 0x33, 0x34, 0x36, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2b, 0x2c, 0x47, 0x2e, 0x2f}, SKINCOLOR_BOULDER, 8, V_REDMAP, true}, // SKINCOLOR_KETCHUP
{"Peachy", {0xd0, 0x30, 0x31, 0x31, 0x32, 0x32, 0xdc, 0xdc, 0xdc, 0xd3, 0xd4, 0xd4, 0xcc, 0xcd, 0xce, 0xcf}, SKINCOLOR_TEAL, 7, V_ROSYMAP, true}, // SKINCOLOR_PEACHY
{"Quail", {0xd8, 0xd9, 0xdb, 0xdc, 0xde, 0xdf, 0xd5, 0xd5, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0x1d, 0x1f}, SKINCOLOR_WAVE, 5, V_BROWNMAP, true}, // SKINCOLOR_QUAIL
{"Foundation", { 80, 81, 82, 84, 219, 221, 221, 212, 213, 214, 215, 197, 186, 187, 187, 30}, SKINCOLOR_DREAM, 6, V_ORANGEMAP, true}, // SKINCOLOR_FOUNDATION
{"Sunset", {0x51, 0x52, 0x40, 0x40, 0x34, 0x36, 0xd5, 0xd5, 0xd6, 0xd7, 0xcf, 0xcf, 0xc6, 0xc6, 0xc7, 0xfe}, SKINCOLOR_SAPPHIRE, 5, V_ORANGEMAP, true}, // SKINCOLOR_SUNSET
{"Copper", {0x58, 0x54, 0x40, 0x34, 0x35, 0x38, 0x3a, 0x3c, 0x3d, 0x2a, 0x2b, 0x2c, 0x2c, 0xba, 0xba, 0xbb}, SKINCOLOR_BLUEBELL, 5, V_ORANGEMAP, true}, // SKINCOLOR_COPPER
{"Apricot", {0x00, 0xd8, 0xd9, 0xda, 0xdb, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e}, SKINCOLOR_CYAN, 4, V_ORANGEMAP, true}, // SKINCOLOR_APRICOT
{"Orange", {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x2c}, SKINCOLOR_BLUE, 4, V_ORANGEMAP, true}, // SKINCOLOR_ORANGE
{"Orange", { 49, 50, 51, 52, 53, 54, 55, 57, 58, 59, 60, 42, 44, 45, 46, 46}, SKINCOLOR_BLUE, 4, V_ORANGEMAP, true}, // SKINCOLOR_ORANGE
{"Rust", {0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3f, 0x2c, 0x2d, 0x47, 0x2e, 0x2f, 0x2f}, SKINCOLOR_YOGURT, 8, V_ORANGEMAP, true}, // SKINCOLOR_RUST
{"Tangerine", { 81, 83, 64, 64, 51, 52, 53, 54, 56, 58, 60, 61, 63, 45, 46, 47}, SKINCOLOR_OCEAN, 12, V_ORANGEMAP, true}, // SKINCOLOR_TANGERINE
{"Topaz", { 0, 81, 83, 73, 74, 74, 65, 52, 53, 54, 56, 58, 60, 42, 43, 45}, SKINCOLOR_MOONSTONE, 10, V_YELLOWMAP, true}, // SKINCOLOR_TOPAZ
{"Gold", {0x51, 0x51, 0x54, 0x54, 0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x3f, 0x2d, 0x2e, 0x2f, 0x2f}, SKINCOLOR_LAVENDER, 10, V_YELLOWMAP, true}, // SKINCOLOR_GOLD
{"Sandy", {0x53, 0x40, 0x41, 0x42, 0x43, 0xe6, 0xe9, 0xe9, 0xea, 0xec, 0xec, 0xc6, 0xc6, 0xc7, 0xc7, 0xfe}, SKINCOLOR_SKY, 8, V_YELLOWMAP, true}, // SKINCOLOR_SANDY
{"Goldenrod", { 0, 80, 81, 81, 83, 73, 73, 64, 65, 66, 67, 68, 69, 62, 44, 45}, SKINCOLOR_MAJESTY, 8, V_YELLOWMAP, true}, // SKINCOLOR_GOLDENROD
{"Yellow", {0x52, 0x53, 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e, 0x4e, 0x4f, 0xed}, SKINCOLOR_CORNFLOWER, 8, V_YELLOWMAP, true}, // SKINCOLOR_YELLOW
{"Olive", {0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4e, 0xe7, 0xe7, 0xe9, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7, 0xfd}, SKINCOLOR_DUSK, 3, V_YELLOWMAP, true}, // SKINCOLOR_OLIVE
{"Pear", { 88, 89, 188, 189, 189, 76, 76, 67, 67, 68, 69, 70, 45, 46, 47, 47}, SKINCOLOR_MARINE, 9, V_PERIDOTMAP, true}, // SKINCOLOR_PEAR
{"Lemon", { 0, 80, 81, 83, 73, 73, 74, 74, 76, 76, 191, 191, 79, 79, 110, 111}, SKINCOLOR_FUCHSIA, 8, V_YELLOWMAP, true}, // SKINCOLOR_LEMON
{"Lime", {0x50, 0x51, 0x52, 0x53, 0x48, 0xbc, 0xbd, 0xbe, 0xbe, 0xbf, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_MAGENTA, 9, V_PERIDOTMAP, true}, // SKINCOLOR_LIME
{"Peridot", {0x58, 0x58, 0xbc, 0xbc, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf, 0x5e, 0x5e, 0x5f, 0x5f, 0x77, 0x77}, SKINCOLOR_COBALT, 2, V_PERIDOTMAP, true}, // SKINCOLOR_PERIDOT
{"Apple", {0x49, 0x49, 0xbc, 0xbd, 0xbe, 0xbe, 0xbe, 0x67, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6d}, SKINCOLOR_RASPBERRY, 13, V_PERIDOTMAP, true}, // SKINCOLOR_APPLE
{"Headlight", { 0, 80, 81, 82, 73, 84, 64, 65, 91, 91, 124, 125, 126, 137, 138, 139}, SKINCOLOR_MAUVE, 8, V_YELLOWMAP, true}, // SKINCOLOR_HEADLIGHT
{"Chartreuse", { 80, 82, 72, 73, 188, 188, 113, 114, 114, 125, 126, 137, 138, 139, 253, 254}, SKINCOLOR_NOBLE, 9, V_PERIDOTMAP, true}, // SKINCOLOR_CHARTREUSE
{"Green", {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_RED, 6, V_GREENMAP, true}, // SKINCOLOR_GREEN
{"Forest", {0x65, 0x66, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6b, 0x6b, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f}, SKINCOLOR_SALMON, 9, V_GREENMAP, true}, // SKINCOLOR_FOREST
{"Emerald", {0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77}, SKINCOLOR_RUBY, 4, V_GREENMAP, true}, // SKINCOLOR_EMERALD
{"Shamrock", {0x70, 0x70, 0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77}, SKINCOLOR_SIBERITE, 10, V_GREENMAP, true}, // SKINCOLOR_SHAMROCK
{"Jade", { 128, 120, 121, 122, 122, 113, 114, 114, 115, 116, 117, 118, 119, 110, 111, 30}, SKINCOLOR_TAFFY, 10, V_GREENMAP, true}, // SKINCOLOR_JADE
{"Mint", {0x00, 0x00, 0x58, 0x58, 0x59, 0x62, 0x62, 0x62, 0x64, 0x67, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a}, SKINCOLOR_VIOLET, 5, V_GREENMAP, true}, // SKINCOLOR_MINT
{"Seafoam", {0x01, 0x58, 0x59, 0x5a, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0xfd, 0xfd}, SKINCOLOR_PLUM, 6, V_AQUAMAP, true}, // SKINCOLOR_SEAFOAM
{"Master", { 0, 80, 88, 96, 112, 113, 99, 100, 124, 125, 126, 117, 107, 118, 119, 111}, SKINCOLOR_PEPPER, 8, V_GREENMAP, true}, // SKINCOLOR_MASTER
{"Emerald", { 80, 96, 112, 113, 114, 114, 125, 125, 126, 126, 137, 137, 138, 138, 139, 139}, SKINCOLOR_RUBY, 9, V_GREENMAP, true}, // SKINCOLOR_EMERALD
{"Seafoam", {0x01, 0x58, 0x59, 0x5a, 0x7c, 0x7d, 0x7d, 0x7e, 0x7e, 0x8f, 0x8f, 0x8a, 0x8a, 0x8b, 0xfd, 0xfd}, SKINCOLOR_PLUM, 6, V_AQUAMAP, true}, // SKINCOLOR_SEAFOAM
{"Island", { 96, 97, 113, 113, 114, 124, 142, 136, 136, 150, 151, 153, 168, 168, 169, 169}, SKINCOLOR_GALAXY, 7, V_AQUAMAP, true}, // SKINCOLOR_ISLAND
{"Bottle", { 0, 1, 3, 4, 5, 140, 141, 141, 124, 125, 126, 127, 118, 119, 111, 111}, SKINCOLOR_LATTE, 14, V_AQUAMAP, true}, // SKINCOLOR_BOTTLE
{"Aqua", {0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x7e, 0x7f, 0x7f, 0x76, 0x77}, SKINCOLOR_ROSY, 7, V_AQUAMAP, true}, // SKINCOLOR_AQUA
{"Teal", {0x78, 0x78, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8a, 0x8a, 0x8a, 0x8a}, SKINCOLOR_PEACHY, 7, V_SKYMAP, true}, // SKINCOLOR_TEAL
{"Ocean", { 120, 121, 122, 122, 123, 141, 142, 142, 136, 137, 138, 138, 139, 139, 253, 253}, SKINCOLOR_TANGERINE, 4, V_AQUAMAP, true}, // SKINCOLOR_OCEAN
{"Wave", {0x00, 0x78, 0x78, 0x79, 0x8d, 0x87, 0x88, 0x89, 0x89, 0xae, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfd}, SKINCOLOR_QUAIL, 5, V_SKYMAP, true}, // SKINCOLOR_WAVE
{"Cyan", {0x80, 0x81, 0xff, 0xff, 0x83, 0x83, 0x8d, 0x8d, 0x8d, 0x8e, 0x7e, 0x7f, 0x76, 0x76, 0x77, 0x6e}, SKINCOLOR_APRICOT, 6, V_SKYMAP, true}, // SKINCOLOR_CYAN
{"Turquoise", { 0, 120, 121, 122, 123, 141, 141, 135, 136, 136, 150, 153, 155, 157, 159, 253}, SKINCOLOR_SANGRIA, 12, V_SKYMAP, true}, // SKINCOLOR_TURQUOISE
{"Aquamarine", { 0, 120, 121, 131, 132, 133, 134, 134, 135, 135, 149, 149, 172, 173, 174, 175}, SKINCOLOR_GARNET, 8, V_SKYMAP, true}, // SKINCOLOR_AQUAMARINE
{"Sky", {0x80, 0x80, 0x81, 0x82, 0x83, 0x83, 0x84, 0x85, 0x85, 0x86, 0x87, 0x88, 0x89, 0x89, 0x8a, 0x8b}, SKINCOLOR_SANDY, 1, V_SKYMAP, true}, // SKINCOLOR_SKY
{"Marine", { 144, 146, 147, 147, 148, 135, 136, 136, 137, 137, 127, 118, 119, 111, 111, 111}, SKINCOLOR_PEAR, 13, V_SKYMAP, true}, // SKINCOLOR_MARINE
{"Cerulean", {0x85, 0x86, 0x87, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0xfd, 0xfd, 0xfd, 0x1f, 0x1f, 0x1f}, SKINCOLOR_NEON, 4, V_SKYMAP, true}, // SKINCOLOR_CERULEAN
{"Dream", { 80, 208, 200, 200, 146, 146, 133, 134, 135, 136, 137, 138, 139, 139, 254, 254}, SKINCOLOR_FOUNDATION, 9, V_SKYMAP, true}, // SKINCOLOR_DREAM
{"Icy", {0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0x83, 0x83, 0x86, 0x87, 0x95, 0x95, 0xad, 0xad, 0xae, 0xaf}, SKINCOLOR_CRIMSON, 0, V_SKYMAP, true}, // SKINCOLOR_ICY
{"Sapphire", {0x80, 0x83, 0x86, 0x87, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_SUNSET, 5, V_SKYMAP, true}, // SKINCOLOR_SAPPHIRE
{"Daybreak", { 80, 81, 82, 72, 64, 9, 11, 171, 149, 150, 151, 153, 156, 157, 159, 253}, SKINCOLOR_EVENTIDE, 12, V_BLUEMAP, true}, // SKINCOLOR_DAYBREAK
{"Sapphire", {0x80, 0x82, 0x86, 0x87, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_SUNSET, 5, V_BLUEMAP, true}, // SKINCOLOR_SAPPHIRE
{"Arctic", { 0, 1, 3, 4, 145, 146, 147, 148, 148, 149, 150, 153, 156, 159, 253, 254}, SKINCOLOR_ECRU, 15, V_BLUEMAP, true}, // SKINCOLOR_ARCTIC
{"Cornflower", {0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x9a, 0x9c, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e}, SKINCOLOR_YELLOW, 4, V_BLUEMAP, true}, // SKINCOLOR_CORNFLOWER
{"Blue", {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfe}, SKINCOLOR_ORANGE, 5, V_BLUEMAP, true}, // SKINCOLOR_BLUE
{"Cobalt", {0x93, 0x94, 0x95, 0x96, 0x98, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xfd, 0xfd, 0xfe, 0xfe}, SKINCOLOR_PERIDOT, 5, V_BLUEMAP, true}, // SKINCOLOR_COBALT
{"Cobalt", { 145, 147, 149, 150, 151, 153, 154, 155, 156, 157, 158, 159, 253, 253, 254, 254}, SKINCOLOR_PERIDOT, 5, V_BLUEMAP, true}, // SKINCOLOR_COBALT
{"Midnight", { 171, 171, 172, 173, 173, 174, 175, 157, 158, 159, 253, 253, 254, 254, 31, 31}, SKINCOLOR_CHERRY, 10, V_GRAYMAP, true}, // SKINCOLOR_MIDNIGHT
{"Galaxy", { 160, 161, 162, 163, 164, 165, 166, 166, 154, 155, 156, 157, 159, 253, 254, 31}, SKINCOLOR_ISLAND, 7, V_PURPLEMAP, true}, // SKINCOLOR_GALAXY
{"Vapor", {0x80, 0x81, 0x83, 0x86, 0x94, 0x94, 0xa3, 0xa3, 0xa4, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa9, 0xa9}, SKINCOLOR_LILAC, 4, V_SKYMAP, true}, // SKINCOLOR_VAPOR
{"Dusk", {0x92, 0x93, 0x94, 0x94, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xa9, 0xa9, 0xfd, 0xfd}, SKINCOLOR_OLIVE, 0, V_BLUEMAP, true}, // SKINCOLOR_DUSK
{"Majesty", { 0, 1, 176, 160, 160, 161, 162, 162, 163, 172, 173, 174, 174, 175, 139, 139}, SKINCOLOR_GOLDENROD, 9, V_PURPLEMAP, true}, // SKINCOLOR_MAJESTY
{"Pastel", {0x90, 0x90, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, SKINCOLOR_BUBBLEGUM, 9, V_PURPLEMAP, true}, // SKINCOLOR_PASTEL
{"Purple", {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa8, 0xa9, 0xa9}, SKINCOLOR_FLAME, 7, V_PURPLEMAP, true}, // SKINCOLOR_PURPLE
{"Bubblegum", {0x00, 0xd0, 0xd0, 0xc8, 0xc8, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8}, SKINCOLOR_PASTEL, 8, V_MAGENTAMAP, true}, // SKINCOLOR_BUBBLEGUM
{"Noble", { 144, 146, 147, 148, 149, 164, 164, 165, 166, 185, 186, 186, 187, 187, 28, 29}, SKINCOLOR_CHARTREUSE, 12, V_PURPLEMAP, true}, // SKINCOLOR_NOBLE
{"Fuchsia", { 200, 201, 203, 204, 204, 183, 184, 184, 165, 166, 167, 168, 169, 159, 253, 254}, SKINCOLOR_LEMON, 10, V_PURPLEMAP, true}, // SKINCOLOR_FUCHSIA
{"Bubblegum", { 0, 208, 208, 176, 177, 178, 179, 180, 181, 182, 164, 166, 167, 168, 169, 253}, SKINCOLOR_PASTEL, 8, V_MAGENTAMAP, true}, // SKINCOLOR_BUBBLEGUM
{"Siberite", { 252, 177, 179, 180, 181, 181, 182, 182, 183, 164, 166, 167, 167, 168, 169, 159}, SKINCOLOR_EMERALD, 8, V_MAGENTAMAP, true}, // SKINCOLOR_SIBERITE
{"Magenta", {0xb3, 0xb3, 0xb4, 0xb5, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb}, SKINCOLOR_LIME, 6, V_MAGENTAMAP, true}, // SKINCOLOR_MAGENTA
{"Neon", {0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xbb, 0xc7, 0xc7, 0x1d, 0x1d, 0x1e}, SKINCOLOR_CERULEAN, 2, V_MAGENTAMAP, true}, // SKINCOLOR_NEON
{"Violet", {0xd0, 0xd1, 0xd2, 0xca, 0xcc, 0xb8, 0xb9, 0xb9, 0xba, 0xa8, 0xa8, 0xa9, 0xa9, 0xfd, 0xfe, 0xfe}, SKINCOLOR_MINT, 6, V_MAGENTAMAP, true}, // SKINCOLOR_VIOLET
{"Royal", { 208, 209, 192, 192, 192, 193, 193, 194, 194, 172, 173, 174, 175, 175, 139, 139}, SKINCOLOR_FANCY, 9, V_PURPLEMAP, true}, // SKINCOLOR_ROYAL
{"Lilac", {0x00, 0xd0, 0xd1, 0xd2, 0xd3, 0xc1, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xfe, 0x1f}, SKINCOLOR_VAPOR, 4, V_ROSYMAP, true}, // SKINCOLOR_LILAC
{"Mauve", { 176, 177, 178, 192, 193, 194, 195, 195, 196, 185, 185, 186, 186, 187, 187, 253}, SKINCOLOR_HEADLIGHT, 8, V_PURPLEMAP, true}, // SKINCOLOR_MAUVE
{"Eventide", { 51, 52, 53, 33, 34, 204, 183, 183, 184, 184, 166, 167, 168, 169, 253, 254}, SKINCOLOR_DAYBREAK, 13, V_MAGENTAMAP, true}, // SKINCOLOR_EVENTIDE
{"Plum", {0xc8, 0xd3, 0xd5, 0xd6, 0xd7, 0xce, 0xcf, 0xb9, 0xb9, 0xba, 0xba, 0xa9, 0xa9, 0xa9, 0xfd, 0xfe}, SKINCOLOR_MINT, 7, V_ROSYMAP, true}, // SKINCOLOR_PLUM
{"Raspberry", {0xc8, 0xc9, 0xca, 0xcb, 0xcb, 0xcc, 0xcd, 0xcd, 0xce, 0xb9, 0xb9, 0xba, 0xba, 0xbb, 0xfe, 0xfe}, SKINCOLOR_APPLE, 13, V_ROSYMAP, true}, // SKINCOLOR_RASPBERRY
{"Taffy", { 1, 176, 176, 177, 178, 179, 202, 203, 204, 204, 205, 206, 207, 44, 45, 46}, SKINCOLOR_JADE, 8, V_ROSYMAP, true}, // SKINCOLOR_TAFFY
{"Rosy", {0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, SKINCOLOR_AQUA, 1, V_ROSYMAP, true}, // SKINCOLOR_ROSY
{"Fancy", { 0, 208, 49, 210, 210, 202, 202, 203, 204, 204, 205, 206, 207, 207, 186, 186}, SKINCOLOR_ROYAL, 9, V_ROSYMAP, true}, // SKINCOLOR_FANCY
{"Sangria", { 210, 32, 33, 34, 34, 215, 215, 207, 207, 185, 186, 186, 186, 169, 169, 253}, SKINCOLOR_TURQUOISE, 12, V_ROSYMAP, true}, // SKINCOLOR_SANGRIA
{"Volcanic", { 54, 36, 42, 44, 45, 46, 46, 47, 28, 253, 253, 254, 254, 30, 31, 31}, SKINCOLOR_BRONZE, 9, V_REDMAP, true}, // SKINCOLOR_VOLCANIC
// super
{"Super Silver 1", {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03}, SKINCOLOR_BLACK, 15, 0, false}, // SKINCOLOR_SUPERSILVER1

View file

@ -18,6 +18,7 @@
#include "d_think.h"
#include "sounds.h"
#include "m_fixed.h"
#include "dehacked.h" // MAX_ACTION_RECURSION
// deh_tables.c now has lists for the more named enums! PLEASE keep them up to date!
// For great modding!!
@ -151,6 +152,7 @@ enum actionnum
A_BOSS3TAKEDAMAGE,
A_BOSS3PATH,
A_BOSS3SHOCKTHINK,
A_SHOCKWAVE,
A_LINEDEFEXECUTE,
A_LINEDEFEXECUTEFROMARG,
A_PLAYSEESOUND,
@ -415,6 +417,7 @@ void A_Boss1Spikeballs();
void A_Boss3TakeDamage();
void A_Boss3Path();
void A_Boss3ShockThink();
void A_Shockwave();
void A_LinedefExecute();
void A_LinedefExecuteFromArg();
void A_PlaySeeSound();
@ -564,7 +567,7 @@ void A_DragonWing();
void A_DragonSegment();
void A_ChangeHeight();
extern boolean actionsoverridden[NUMACTIONS];
extern int actionsoverridden[NUMACTIONS][MAX_ACTION_RECURSION];
// ratio of states to sprites to mobj types is roughly 6 : 1 : 1
#define NUMMOBJFREESLOTS 512

View file

@ -581,6 +581,11 @@ static inline void libdivide_u128_shift(uint64_t *u1, uint64_t *u0, int32_t sign
////////// UINT32
#if defined(__GNUC__) || defined(__clang__) // Suppress intentional compiler warnings
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Waggregate-return"
#endif
static inline struct libdivide_u32_t libdivide_internal_u32_gen(uint32_t d, int branchfree) {
struct libdivide_u32_t result;
uint32_t floor_log_2_d;
@ -647,6 +652,10 @@ struct libdivide_u32_t libdivide_u32_gen(uint32_t d) {
return ret;
}*/
#if defined(__GNUC__) || defined(__clang__) // Stop suppressing intentional compiler warnings
#pragma GCC diagnostic pop
#endif
uint32_t libdivide_u32_do(uint32_t numer, const struct libdivide_u32_t *denom) {
uint8_t more = denom->more;
if (!denom->magic) {

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