diff --git a/.circleci/config.yml b/.circleci/config.yml index b86b39f752a38aee24f50bb260f7b6b45d8b722f..9cf3c2a4e36338e88a9f08201a4df200395fdcf9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,6 +7,7 @@ jobs: environment: CC: ccache gcc CCACHE_COMPRESS: true + CFLAGS: -Wno-error=unused-result #- image: ubuntu:trusty # environment: # CC: ccache gcc -m32 @@ -49,12 +50,15 @@ jobs: paths: - /home/circleci/.cache/apt - checkout + - run: + name: Create deps folder as needed + command: mkdir -p make/linux/64/SDL/deps/ - run: name: make master depend file - command: find make/linux64/SDL/deps/ -type f -print0 | sort -z | xargs -r0 cat > make/linux64/SDL.deps + command: find make/linux/64/SDL/deps/ -type f -print0 | sort -z | xargs -r0 cat > make/linux/64/SDL.deps - restore_cache: keys: - - v1-SRB2-{{ .Branch }}-{{ checksum "make/linux64/SDL.deps" }} + - v1-SRB2-{{ .Branch }}-{{ checksum "make/linux/64/SDL.deps" }} - run: name: Compile command: make -C src LINUX64=1 ERRORMODE=1 -k -j4 @@ -62,6 +66,6 @@ jobs: path: /home/circleci/SRB2/bin/ destination: bin - save_cache: - key: v1-SRB2-{{ .Branch }}-{{ checksum "make/linux64/SDL.deps" }} + key: v1-SRB2-{{ .Branch }}-{{ checksum "make/linux/64/SDL.deps" }} paths: - /home/circleci/.ccache diff --git a/.gitignore b/.gitignore index 1dd1c19d51a706b7b792ba2e32895ed9d88f8228..a3d823fa2182edef86c35ee2810560e5d8f7408e 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,6 @@ Win32_LIB_ASM_Release /build /build/* /CMakeUserPresets.json -/out \ No newline at end of file +/out +/objs/VC10 +/thirdparty/vcpkg-overlays diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2169ac894ca377cdfe2a40d290619dba3ff52c4b..29f5ef5fff9f1bc4afb83006c65f54088762e6dc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,598 +1,19 @@ -variables: - GIT_STRATEGY: clone - GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/$CI_PROJECT_PATH - -default: - image: git.do.srb2.org:5050/stjr/srb2ci/srb2ci:stable - - 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 - - - key: apk-$CI_JOB_IMAGE - paths: - - apk-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" +include: + - '.gitlab/ci/templates/*.yml' + - '.gitlab/ci/jobs/*.yml' - - - | - # 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" +workflow: + auto_cancel: + on_new_commit: interruptible - 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" +variables: + GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_CONCURRENT_ID/$CI_PROJECT_PATH + GIT_DEPTH: 20 stages: - build -Debian testing GCC: - stage: build - - when: manual - - image: debian:testing-slim - - allow_failure: true - - artifacts: - paths: - - "bin/" - - "src/comptime.h" - expose_as: "testing-gcc" - 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 libminiupnpc-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 - - when: on_success - - 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 - - when: on_success - - 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 libminiupnpc-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 - - when: manual - - 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 libminiupnpc-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 - - when: manual - - 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 libminiupnpc-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 ARM64=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 LINUX64=1 NONX86=1 ARM64=1 - - | - # make - echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" - -Windows x64: - stage: build - - when: manual - - 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 - - when: manual - - allow_failure: true - - artifacts: - paths: - - "bin/" - - "src/comptime.h" - expose_as: "clang" - 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 libminiupnpc-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 - - when: manual - - image: debian:testing-slim - - artifacts: - paths: - - "bin/" - - "src/comptime.h" - expose_as: "testing-clang" - 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 -Wno-single-bit-bitfield-constant-conversion - CFLAGS: -Wno-cast-align -Wno-deprecated-non-prototype -Wno-single-bit-bitfield-constant-conversion - LDFLAGS: -Wl,-fuse-ld=gold - -Alpine 3 GCC: - stage: build - - when: on_success - - image: alpine:3 - - allow_failure: true - +default: + interruptible: true artifacts: - paths: - - "bin/" - - "src/comptime.h" - expose_as: "Apline-3" - name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-Apline-3" - - before_script: - - - | - # apk_cache - echo -e "\e[0Ksection_start:`date +%s`:apk_cache[collapsed=true]\r\e[0KUpdating APK listing" - - export APK_CACHE_DIR=`pwd`/apk-cache - - mkdir --parents --verbose $APK_CACHE_DIR/ - - ln -sf /etc/apk/cache $APK_CACHE_DIR - - | - # apk_cache - echo -e "\e[0Ksection_end:`date +%s`:apk_cache\r\e[0K" - - - - | - # apk_update - echo -e "\e[0Ksection_start:`date +%s`:apk_update[collapsed=true]\r\e[0KUpdating APK listing" - - apk update - - | - # apk_update - echo -e "\e[0Ksection_end:`date +%s`:apk_update\r\e[0K" - - - - | - # apk_upgrade - echo -e "\e[0Ksection_start:`date +%s`:apk_upgrade[collapsed=true]\r\e[0KUpdating existing packages" - - apk upgrade - - | - # apk_update - echo -e "\e[0Ksection_end:`date +%s`:apk_upgrade\r\e[0K" - - - - | - # apk_common - echo -e "\e[0Ksection_start:`date +%s`:apk_common[collapsed=true]\r\e[0KInstalling common packages" - - apk add make git ccache nasm - - | - # apk_common - echo -e "\e[0Ksection_end:`date +%s`:apk_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 -a ~/.ccache/ccache.conf - - | - # cache_dir - echo cache_dir = $PWD/ccache | tee -a ~/.ccache/ccache.conf - - | - # compiler_check - echo compiler_check = content | tee -a ~/.ccache/ccache.conf - - | - # stats_log - echo stats_log = $PWD/ccache_statslog | tee -a ~/.ccache/ccache.conf - - | - # max_size - echo max_size = 50M | tee -a ~/.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" - - script: - - - | - # apk_toolchain - echo -e "\e[0Ksection_start:`date +%s`:apk_toolchain[collapsed=true]\r\e[0KInstalling toolchain packages" - - apk add gcc - - | - # apk_toolchain - echo -e "\e[0Ksection_end:`date +%s`:apk_toolchain\r\e[0K" - - - - | - # apk_development - echo -e "\e[0Ksection_start:`date +%s`:apk_development[collapsed=true]\r\e[0KInstalling development packages" - - apk add musl-dev sdl2_mixer-dev libpng-dev curl-dev libgme-dev libopenmpt-dev miniupnpc-dev - - | - # apk_development - echo -e "\e[0Ksection_end:`date +%s`:apk_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 NOEXECINFO=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 NONX86=1 NOEXECINFO=1 - - | - # make - echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" - - after_script: - - - | - # apk_clean - echo -e "\e[0Ksection_start:`date +%s`:apk_clean[collapsed=true]\r\e[0KCleaning of unneeded APK packages" - - apk cache clean - - | - # apk_clean - echo -e "\e[0Ksection_end:`date +%s`:apk_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" + expire_in: 1 day diff --git a/.gitlab/ci/jobs/alpine-3-gcc-dedicated-makefile.yml b/.gitlab/ci/jobs/alpine-3-gcc-dedicated-makefile.yml new file mode 100644 index 0000000000000000000000000000000000000000..fe63e09c8368cca1da7203b81411f55b3165ac44 --- /dev/null +++ b/.gitlab/ci/jobs/alpine-3-gcc-dedicated-makefile.yml @@ -0,0 +1,34 @@ +Alpine 3 GCC Dedicated Makefile: + extends: Alpine 3 GCC Makefile + + artifacts: + paths: + - "bin/" + - "src/comptime.h" + expose_as: "Apline-3-Dedicated-makefile" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-Apline-3-Dedicated-makefile" + + script: + - - | + # apk_toolchain + echo -e "\e[0Ksection_start:`date +%s`:apk_toolchain[collapsed=true]\r\e[0KInstalling toolchain packages" + - apk add gcc g++ + - | + # apk_toolchain + echo -e "\e[0Ksection_end:`date +%s`:apk_toolchain\r\e[0K" + + - - | + # apk_development + echo -e "\e[0Ksection_start:`date +%s`:apk_development[collapsed=true]\r\e[0KInstalling development packages" + - apk add musl-dev libpng-dev curl-dev + - | + # apk_development + echo -e "\e[0Ksection_end:`date +%s`:apk_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 NOEXECINFO=1 DEDICATED=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 NONX86=1 NOEXECINFO=1 DEDICATED=1 + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" diff --git a/.gitlab/ci/jobs/alpine-3-gcc-makefile.yml b/.gitlab/ci/jobs/alpine-3-gcc-makefile.yml new file mode 100644 index 0000000000000000000000000000000000000000..2cc656ca78a5641a594ee894a07f591c628ee36f --- /dev/null +++ b/.gitlab/ci/jobs/alpine-3-gcc-makefile.yml @@ -0,0 +1,135 @@ +Alpine 3 GCC Makefile: + stage: build + + when: manual + + image: alpine:3 + + allow_failure: true + + cache: + - key: apk-$CI_JOB_IMAGE-makefile + paths: + - apk-cache + unprotect: true + + artifacts: + paths: + - "bin/" + - "src/comptime.h" + expose_as: "Apline-3-makefile" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-Apline-3-makefile" + + before_script: + - - | + # apk_cache + echo -e "\e[0Ksection_start:`date +%s`:apk_cache[collapsed=true]\r\e[0KUpdating APK listing" + - export APK_CACHE_DIR=`pwd`/apk-cache + - mkdir --parents --verbose $APK_CACHE_DIR/ + - ln -sf /etc/apk/cache $APK_CACHE_DIR + - | + # apk_cache + echo -e "\e[0Ksection_end:`date +%s`:apk_cache\r\e[0K" + + - - | + # apk_update + echo -e "\e[0Ksection_start:`date +%s`:apk_update[collapsed=true]\r\e[0KUpdating APK listing" + - apk update + - | + # apk_update + echo -e "\e[0Ksection_end:`date +%s`:apk_update\r\e[0K" + + - - | + # apk_upgrade + echo -e "\e[0Ksection_start:`date +%s`:apk_upgrade[collapsed=true]\r\e[0KUpdating existing packages" + - apk upgrade + - | + # apk_update + echo -e "\e[0Ksection_end:`date +%s`:apk_upgrade\r\e[0K" + + - - | + # apk_common + echo -e "\e[0Ksection_start:`date +%s`:apk_common[collapsed=true]\r\e[0KInstalling common packages" + - apk add make git ccache nasm + - | + # apk_common + echo -e "\e[0Ksection_end:`date +%s`:apk_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 -a ~/.ccache/ccache.conf + - | + # cache_dir + echo cache_dir = $PWD/ccache | tee -a ~/.ccache/ccache.conf + - | + # compiler_check + echo compiler_check = content | tee -a ~/.ccache/ccache.conf + - | + # stats_log + echo stats_log = $PWD/ccache_statslog | tee -a ~/.ccache/ccache.conf + - | + # max_size + echo max_size = 50M | tee -a ~/.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" + + script: + - - | + # apk_toolchain + echo -e "\e[0Ksection_start:`date +%s`:apk_toolchain[collapsed=true]\r\e[0KInstalling toolchain packages" + - apk add gcc g++ + - | + # apk_toolchain + echo -e "\e[0Ksection_end:`date +%s`:apk_toolchain\r\e[0K" + + - - | + # apk_development + echo -e "\e[0Ksection_start:`date +%s`:apk_development[collapsed=true]\r\e[0KInstalling development packages" + - apk add cmake musl-dev sdl2_mixer-dev libpng-dev curl-dev libgme-dev libopenmpt-dev miniupnpc-dev elfutils-dev + - | + # apk_development + echo -e "\e[0Ksection_end:`date +%s`:apk_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 NOEXECINFO=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 NONX86=1 NOEXECINFO=1 + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" + + after_script: + - - | + # apk_clean + echo -e "\e[0Ksection_start:`date +%s`:apk_clean[collapsed=true]\r\e[0KCleaning of unneeded APK packages" + - apk cache clean + - | + # apk_clean + echo -e "\e[0Ksection_end:`date +%s`:apk_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" diff --git a/.gitlab/ci/jobs/alpine-3-gcc.yml b/.gitlab/ci/jobs/alpine-3-gcc.yml new file mode 100644 index 0000000000000000000000000000000000000000..1881bf3c2a445b3a517e20f49fd2ecec34b81460 --- /dev/null +++ b/.gitlab/ci/jobs/alpine-3-gcc.yml @@ -0,0 +1,143 @@ +Alpine 3 GCC: + stage: build + + when: manual + + image: alpine:3 + + allow_failure: true + + cache: + - key: apk-$CI_JOB_IMAGE + paths: + - apk-cache + unprotect: true + + artifacts: + paths: + - "build.alpine3/bin/" + - "build.alpine3/src/config.h" + expose_as: "Apline-3" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-Apline-3" + + before_script: + - - | + # apk_cache + echo -e "\e[0Ksection_start:`date +%s`:apk_cache[collapsed=true]\r\e[0KUpdating APK listing" + - export APK_CACHE_DIR=`pwd`/apk-cache + - mkdir --parents --verbose $APK_CACHE_DIR/ + - ln -sf /etc/apk/cache $APK_CACHE_DIR + - | + # apk_cache + echo -e "\e[0Ksection_end:`date +%s`:apk_cache\r\e[0K" + + - - | + # apk_update + echo -e "\e[0Ksection_start:`date +%s`:apk_update[collapsed=true]\r\e[0KUpdating APK listing" + - apk update + - | + # apk_update + echo -e "\e[0Ksection_end:`date +%s`:apk_update\r\e[0K" + + - - | + # apk_upgrade + echo -e "\e[0Ksection_start:`date +%s`:apk_upgrade[collapsed=true]\r\e[0KUpdating existing packages" + - apk upgrade + - | + # apk_update + echo -e "\e[0Ksection_end:`date +%s`:apk_upgrade\r\e[0K" + + - - | + # apk_common + echo -e "\e[0Ksection_start:`date +%s`:apk_common[collapsed=true]\r\e[0KInstalling common packages" + - apk add cmake make git ccache nasm + - | + # apk_common + echo -e "\e[0Ksection_end:`date +%s`:apk_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 -a ~/.ccache/ccache.conf + - | + # cache_dir + echo cache_dir = $PWD/ccache | tee -a ~/.ccache/ccache.conf + - | + # compiler_check + echo compiler_check = content | tee -a ~/.ccache/ccache.conf + - | + # stats_log + echo stats_log = $PWD/ccache_statslog | tee -a ~/.ccache/ccache.conf + - | + # max_size + echo max_size = 50M | tee -a ~/.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" + + script: + - - | + # apk_toolchain + echo -e "\e[0Ksection_start:`date +%s`:apk_toolchain[collapsed=true]\r\e[0KInstalling toolchain packages" + - apk add gcc g++ + - | + # apk_toolchain + echo -e "\e[0Ksection_end:`date +%s`:apk_toolchain\r\e[0K" + + - - | + # apk_development + echo -e "\e[0Ksection_start:`date +%s`:apk_development[collapsed=true]\r\e[0KInstalling development packages" + - apk add cmake musl-dev sdl2_mixer-dev libpng-dev curl-dev libgme-dev libopenmpt-dev miniupnpc-dev elfutils-dev + - | + # apk_development + echo -e "\e[0Ksection_end:`date +%s`:apk_development\r\e[0K" + + - - | + # cmake + echo -e "\e[0Ksection_start:`date +%s`:cmake[collapsed=false]\r\e[0KBuilding Makefiles" + - cmake -B build.alpine3 -DSRB2_USE_CCACHE=YES -DSRB2_CONFIG_ERRORMODE=ON -DSRB2_CONFIG_EXECINFO=NO -G "Unix Makefiles" + - | + # cmake + echo -e "\e[0Ksection_end:`date +%s`:cmake\r\e[0K" + + - - | + # make + echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" + - make --directory=build.alpine3 --keep-going || make --directory=build.alpine3 --keep-going + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" + + after_script: + - - | + # apk_clean + echo -e "\e[0Ksection_start:`date +%s`:apk_clean[collapsed=true]\r\e[0KCleaning of unneeded APK packages" + - apk cache clean + - | + # apk_clean + echo -e "\e[0Ksection_end:`date +%s`:apk_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" diff --git a/.gitlab/ci/jobs/batocera-arm64-makefile.yml b/.gitlab/ci/jobs/batocera-arm64-makefile.yml new file mode 100644 index 0000000000000000000000000000000000000000..9a590807de1d819d2be713011a2d8a1fbb61d1d1 --- /dev/null +++ b/.gitlab/ci/jobs/batocera-arm64-makefile.yml @@ -0,0 +1,38 @@ +batocera:arm64 Makefile: + extends: Debian stable:arm64 Makefile + + when: manual + + allow_failure: true + + artifacts: + paths: + - "bin/" + - "src/comptime.h" + expose_as: "Debian old arm64 makefile" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-batocera-aarch64-makefile" + + 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 libopenmpt-dev:arm64 libminiupnpc-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 ARM64=1 NOGME=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 LINUX64=1 NONX86=1 ARM64=1 NOGME=1 + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" diff --git a/.gitlab/ci/jobs/batocera-arm64.yml b/.gitlab/ci/jobs/batocera-arm64.yml new file mode 100644 index 0000000000000000000000000000000000000000..c83a5badb0e096a48a83cc6fc32388a05ed245dd --- /dev/null +++ b/.gitlab/ci/jobs/batocera-arm64.yml @@ -0,0 +1,46 @@ +batocera:arm64: + extends: Debian stable:arm64 + + when: manual + + allow_failure: true + + artifacts: + paths: + - "build.cmake/bin/" + - "build.cmake/src/config.h" + expose_as: "Debian old arm64" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-batocera-aarch64" + + 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 libopenmpt-dev:arm64 libminiupnpc-dev:arm64 + - | + # apt_development + echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K" + + - - | + # cmake + echo -e "\e[0Ksection_start:`date +%s`:cmake[collapsed=false]\r\e[0KBuilding Makefiles" + - cmake -B build.cmake -DSRB2_USE_CCACHE=YES -DSRB2_CONFIG_ERRORMODE=ON -DSRB2_CONFIG_FORCE_NO_MS_BITFIELDS=ON -DSRB2_CONFIG_USE_GME=OFF -G "Unix Makefiles" + - | + # cmake + echo -e "\e[0Ksection_end:`date +%s`:cmake\r\e[0K" + + - - | + # make + echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" + - make --directory=build.cmake --keep-going || make --directory=build.cmake --keep-going + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" diff --git a/.gitlab/ci/jobs/debian-oldstable-amd64-makefile.yml b/.gitlab/ci/jobs/debian-oldstable-amd64-makefile.yml new file mode 100644 index 0000000000000000000000000000000000000000..ba2e745bd423326fa326e18ee2985f659a235401 --- /dev/null +++ b/.gitlab/ci/jobs/debian-oldstable-amd64-makefile.yml @@ -0,0 +1,40 @@ +Debian oldstable:amd64 Makefile: + extends: Debian stable:amd64 Makefile + + when: manual + + image: git.do.srb2.org:5050/stjr/srb2ci/srb2ci:oldstable + + allow_failure: true + + artifacts: + paths: + - "bin/" + - "src/comptime.h" + expose_as: "Debian old amd64 makefile" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-old-x86-64-makefile" + + 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 libopenmpt-dev:amd64 libminiupnpc-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 NOGME=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 LINUX64=1 NOGME=1 + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" diff --git a/.gitlab/ci/jobs/debian-oldstable-amd64.yml b/.gitlab/ci/jobs/debian-oldstable-amd64.yml new file mode 100644 index 0000000000000000000000000000000000000000..32c7f3e40f6f9ac8145a6c679c86856ff879212a --- /dev/null +++ b/.gitlab/ci/jobs/debian-oldstable-amd64.yml @@ -0,0 +1,48 @@ +Debian oldstable:amd64: + extends: Debian stable:amd64 + + when: manual + + image: git.do.srb2.org:5050/stjr/srb2ci/srb2ci:oldstable + + allow_failure: true + + artifacts: + paths: + - "build.cmake/bin/" + - "build.cmake/src/config.h" + expose_as: "Debian old amd64" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-old-x86-64" + + 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 libopenmpt-dev:amd64 libminiupnpc-dev:amd64 + - | + # apt_development + echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K" + + - - | + # cmake + echo -e "\e[0Ksection_start:`date +%s`:cmake[collapsed=false]\r\e[0KBuilding Makefiles" + - cmake -B build.cmake -DSRB2_USE_CCACHE=YES -DSRB2_CONFIG_ERRORMODE=ON -DSRB2_CONFIG_USE_GME=OFF -G "Unix Makefiles" + - | + # cmake + echo -e "\e[0Ksection_end:`date +%s`:cmake\r\e[0K" + + - - | + # make + echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" + - make --directory=build.cmake --keep-going || make --directory=build.cmake --keep-going + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" diff --git a/.gitlab/ci/jobs/debian-oldstable-arm64-makefile.yml b/.gitlab/ci/jobs/debian-oldstable-arm64-makefile.yml new file mode 100644 index 0000000000000000000000000000000000000000..79e282bc62bbaf450e67da14041cb89bfbd910ca --- /dev/null +++ b/.gitlab/ci/jobs/debian-oldstable-arm64-makefile.yml @@ -0,0 +1,40 @@ +Debian oldstable:arm64 Makefile: + extends: Debian stable:arm64 Makefile + + when: manual + + image: git.do.srb2.org:5050/stjr/srb2ci/srb2ci:oldstable + + allow_failure: true + + artifacts: + paths: + - "bin/" + - "src/comptime.h" + expose_as: "Debian old arm64 makefile" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-old-aarch64-makefile" + + 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 libopenmpt-dev:arm64 libminiupnpc-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 ARM64=1 NOGME=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 LINUX64=1 NONX86=1 ARM64=1 NOGME=1 + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" diff --git a/.gitlab/ci/jobs/debian-oldstable-arm64.yml b/.gitlab/ci/jobs/debian-oldstable-arm64.yml new file mode 100644 index 0000000000000000000000000000000000000000..4bf324e3be14425830c4ff6d218d5ec33c35e559 --- /dev/null +++ b/.gitlab/ci/jobs/debian-oldstable-arm64.yml @@ -0,0 +1,48 @@ +Debian oldstable:arm64: + extends: Debian stable:arm64 + + when: manual + + image: git.do.srb2.org:5050/stjr/srb2ci/srb2ci:oldstable + + allow_failure: true + + artifacts: + paths: + - "build.cmake/bin/" + - "build.cmake/src/config.h" + expose_as: "Debian old arm64" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-old-aarch64" + + 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 libopenmpt-dev:arm64 libminiupnpc-dev:arm64 + - | + # apt_development + echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K" + + - - | + # cmake + echo -e "\e[0Ksection_start:`date +%s`:cmake[collapsed=false]\r\e[0KBuilding Makefiles" + - cmake -B build.cmake -DSRB2_USE_CCACHE=YES -DSRB2_CONFIG_ERRORMODE=ON -DSRB2_CONFIG_FORCE_NO_MS_BITFIELDS=ON -DSRB2_CONFIG_USE_GME=OFF -G "Unix Makefiles" + - | + # cmake + echo -e "\e[0Ksection_end:`date +%s`:cmake\r\e[0K" + + - - | + # make + echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" + - make --directory=build.cmake --keep-going || make --directory=build.cmake --keep-going + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" diff --git a/.gitlab/ci/jobs/debian-stable-amd64-makefile.yml b/.gitlab/ci/jobs/debian-stable-amd64-makefile.yml new file mode 100644 index 0000000000000000000000000000000000000000..6dfe176cd5fda3b28f545f8d5e7907e2538f07de --- /dev/null +++ b/.gitlab/ci/jobs/debian-stable-amd64-makefile.yml @@ -0,0 +1,45 @@ +Debian stable:amd64 Makefile: + extends: .srb2ci + + stage: build + + artifacts: + paths: + - "bin/" + - "src/comptime.h" + expose_as: "Debian amd64 makefile" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-x86-64-makefile" + + 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 + + when: on_success + + 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 libminiupnpc-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" diff --git a/.gitlab/ci/jobs/debian-stable-amd64.yml b/.gitlab/ci/jobs/debian-stable-amd64.yml new file mode 100644 index 0000000000000000000000000000000000000000..533a3151d5d81e1d9df62e31471269c6bf2b89da --- /dev/null +++ b/.gitlab/ci/jobs/debian-stable-amd64.yml @@ -0,0 +1,53 @@ +Debian stable:amd64: + extends: .srb2ci + + stage: build + + artifacts: + paths: + - "build.cmake/bin/" + - "build.cmake/src/config.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 + + when: on_success + + 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 libminiupnpc-dev:amd64 + - | + # apt_development + echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K" + + - - | + # cmake + echo -e "\e[0Ksection_start:`date +%s`:cmake[collapsed=false]\r\e[0KBuilding Makefiles" + - cmake -B build.cmake -DSRB2_USE_CCACHE=YES -DSRB2_CONFIG_ERRORMODE=ON -G "Unix Makefiles" + - | + # cmake + echo -e "\e[0Ksection_end:`date +%s`:cmake\r\e[0K" + + - - | + # make + echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" + - make --directory=build.cmake --keep-going || make --directory=build.cmake --keep-going + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" diff --git a/.gitlab/ci/jobs/debian-stable-arm64-makefile.yml b/.gitlab/ci/jobs/debian-stable-arm64-makefile.yml new file mode 100644 index 0000000000000000000000000000000000000000..d932e9f4236d1983950ca61a9e41715af4aed5f5 --- /dev/null +++ b/.gitlab/ci/jobs/debian-stable-arm64-makefile.yml @@ -0,0 +1,46 @@ +Debian stable:arm64 Makefile: + extends: .srb2ci + + stage: build + + when: manual + + artifacts: + paths: + - "bin/" + - "src/comptime.h" + expose_as: "Debian arm64 makefile" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-aarch64-makefile" + + variables: + CC: aarch64-linux-gnu-gcc + LDFLAGS: -Wl,-fuse-ld=gold + OBJCOPY: aarch64-linux-gnu-objcopy + OBJDUMP: aarch64-linux-gnu-objdump + LD: aarch64-linux-gnu-ld + 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 libminiupnpc-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 ARM64=1 || make --directory=src --keep-going CCACHE=1 ERRORMODE=1 LINUX64=1 NONX86=1 ARM64=1 + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" diff --git a/.gitlab/ci/jobs/debian-stable-arm64.yml b/.gitlab/ci/jobs/debian-stable-arm64.yml new file mode 100644 index 0000000000000000000000000000000000000000..db82ee38a0ac4c7ad483479bb81ab78cdba0a98a --- /dev/null +++ b/.gitlab/ci/jobs/debian-stable-arm64.yml @@ -0,0 +1,54 @@ +Debian stable:arm64: + extends: .srb2ci + + stage: build + + when: manual + + artifacts: + paths: + - "build.cmake/bin/" + - "build.cmake/src/config.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 + LD: aarch64-linux-gnu-ld + 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 libminiupnpc-dev:arm64 + - | + # apt_development + echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K" + + - - | + # cmake + echo -e "\e[0Ksection_start:`date +%s`:cmake[collapsed=false]\r\e[0KBuilding Makefiles" + - cmake -B build.cmake -DSRB2_USE_CCACHE=YES -DSRB2_CONFIG_ERRORMODE=ON -DSRB2_CONFIG_FORCE_NO_MS_BITFIELDS=ON -G "Unix Makefiles" + - | + # cmake + echo -e "\e[0Ksection_end:`date +%s`:cmake\r\e[0K" + + - - | + # make + echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" + - make --directory=build.cmake --keep-going || make --directory=build.cmake --keep-going + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" diff --git a/.gitlab/ci/jobs/debian-stable-clang-amd64.yml b/.gitlab/ci/jobs/debian-stable-clang-amd64.yml new file mode 100644 index 0000000000000000000000000000000000000000..4686c1849196d3be6cbee936c1ad910c0f93627c --- /dev/null +++ b/.gitlab/ci/jobs/debian-stable-clang-amd64.yml @@ -0,0 +1,55 @@ +Debian stable Clang: + extends: .srb2ci + + stage: build + + when: on_success + + allow_failure: false + + artifacts: + paths: + - "build.clang/bin/" + - "build.clang/src/config.h" + expose_as: "clang" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-clang" + + variables: + CC: clang + CXX: clang + WFLAGS: -Wno-cast-align -Wno-implicit-const-int-float-conversion -Werror + CFLAGS: -Wno-cast-align -Wno-implicit-const-int-float-conversion -Werror + 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 libminiupnpc-dev + - | + # apt_development + echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K" + + - - | + # cmake + echo -e "\e[0Ksection_start:`date +%s`:cmake[collapsed=false]\r\e[0KBuilding Makefiles" + - cmake -B build.clang -DCPM_USE_LOCAL_PACKAGES:BOOL=ON -DSRB2_CONFIG_ENABLE_TESTS:BOOL=OFF -DSRB2_CONFIG_SYSTEM_LIBRARIES:BOOL=ON -DSRB2_USE_LIBGME:BOOL=OFF -G "Unix Makefiles" + - | + # cmake + echo -e "\e[0Ksection_end:`date +%s`:cmake\r\e[0K" + + - - | + # make + echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" + - make --directory=build.clang --keep-going || make --directory=build.clang --keep-going + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" diff --git a/.gitlab/ci/jobs/debian-stable-i386-makefile.yml b/.gitlab/ci/jobs/debian-stable-i386-makefile.yml new file mode 100644 index 0000000000000000000000000000000000000000..bbabee4a6cde37050ee3e6bbbc89e918914e275f --- /dev/null +++ b/.gitlab/ci/jobs/debian-stable-i386-makefile.yml @@ -0,0 +1,45 @@ +Debian stable:i386 Makefile: + extends: .srb2ci + + stage: build + + when: manual + + artifacts: + paths: + - "bin/" + - "src/comptime.h" + expose_as: "Debian i386 makefile" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-i686-makefile" + + variables: + CC: i686-linux-gnu-gcc + OBJCOPY: i686-linux-gnu-objcopy + OBJDUMP: i686-linux-gnu-objdump + LD: i686-linux-gnu-ld + 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 libminiupnpc-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" diff --git a/.gitlab/ci/jobs/debian-stable-i386.yml b/.gitlab/ci/jobs/debian-stable-i386.yml new file mode 100644 index 0000000000000000000000000000000000000000..8d9ea49644a700490c471414248e671eef8e3e00 --- /dev/null +++ b/.gitlab/ci/jobs/debian-stable-i386.yml @@ -0,0 +1,53 @@ +Debian stable:i386: + extends: .srb2ci + + stage: build + + when: manual + + artifacts: + paths: + - "build.cmake/bin/" + - "build.cmake/src/config.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 + LD: i686-linux-gnu-ld + 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 libminiupnpc-dev:i386 + - | + # apt_development + echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K" + + - - | + # cmake + echo -e "\e[0Ksection_start:`date +%s`:cmake[collapsed=false]\r\e[0KBuilding Makefiles" + - cmake -B build.cmake -DSRB2_USE_CCACHE=YES -DSRB2_CONFIG_ERRORMODE=ON -G "Unix Makefiles" + - | + # cmake + echo -e "\e[0Ksection_end:`date +%s`:cmake\r\e[0K" + + - - | + # make + echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" + - make --directory=build.cmake --keep-going || make --directory=build.cmake --keep-going + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" diff --git a/.gitlab/ci/jobs/debian-testing-clang-amd64.yml b/.gitlab/ci/jobs/debian-testing-clang-amd64.yml new file mode 100644 index 0000000000000000000000000000000000000000..dc790b397f2187b47a75c05bcf3e5973d5a175e1 --- /dev/null +++ b/.gitlab/ci/jobs/debian-testing-clang-amd64.yml @@ -0,0 +1,22 @@ +Debian testing Clang: + extends: Debian stable Clang + + when: manual + + allow_failure: true + + image: debian:testing-slim + + artifacts: + paths: + - "build.clang/bin/" + - "build.clang/src/config.h" + expose_as: "testing-clang" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-testing-clang" + + variables: + CC: clang + CXX: clang + WFLAGS: -Wno-cast-align -Wno-implicit-const-int-float-conversion -Werror -Wno-deprecated-non-prototype -Wno-single-bit-bitfield-constant-conversion + CFLAGS: -Wno-cast-align -Wno-implicit-const-int-float-conversion -Werror -Wno-deprecated-non-prototype -Wno-single-bit-bitfield-constant-conversion + LDFLAGS: -Wl,-fuse-ld=gold diff --git a/.gitlab/ci/jobs/debian-testing-gcc-amd64-makefile.yml b/.gitlab/ci/jobs/debian-testing-gcc-amd64-makefile.yml new file mode 100644 index 0000000000000000000000000000000000000000..5edaddf3373e3cdcad9d0a6eda0167df2d813c2e --- /dev/null +++ b/.gitlab/ci/jobs/debian-testing-gcc-amd64-makefile.yml @@ -0,0 +1,46 @@ +Debian testing GCC Makefile: + extends: .srb2ci + + stage: build + + when: manual + + image: debian:testing-slim + + allow_failure: true + + artifacts: + paths: + - "bin/" + - "src/comptime.h" + expose_as: "testing-gcc-makefile" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-testing-gcc-makefile" + + 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 libminiupnpc-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" diff --git a/.gitlab/ci/jobs/debian-testing-gcc-amd64.yml b/.gitlab/ci/jobs/debian-testing-gcc-amd64.yml new file mode 100644 index 0000000000000000000000000000000000000000..458c6d1efdc203da3d248a41ac5a29e583a53882 --- /dev/null +++ b/.gitlab/ci/jobs/debian-testing-gcc-amd64.yml @@ -0,0 +1,54 @@ +Debian testing GCC: + extends: .srb2ci + + stage: build + + when: manual + + image: debian:testing-slim + + allow_failure: true + + artifacts: + paths: + - "build.cmake/bin/" + - "build.cmake/src/config.h" + expose_as: "testing-gcc" + 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 libminiupnpc-dev + - | + # apt_development + echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K" + + - - | + # cmake + echo -e "\e[0Ksection_start:`date +%s`:cmake[collapsed=false]\r\e[0KBuilding Makefiles" + - cmake -B build.cmake -DSRB2_USE_CCACHE=YES -DSRB2_CONFIG_ERRORMODE=ON -G "Unix Makefiles" + - | + # cmake + echo -e "\e[0Ksection_end:`date +%s`:cmake\r\e[0K" + + - - | + # make + echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" + - make --directory=build.cmake --keep-going || make --directory=build.cmake --keep-going + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" diff --git a/.gitlab/ci/jobs/macos-arm64.yml b/.gitlab/ci/jobs/macos-arm64.yml new file mode 100644 index 0000000000000000000000000000000000000000..a9e31773e6b2d58ffa4fce856085a83ad0f8bece --- /dev/null +++ b/.gitlab/ci/jobs/macos-arm64.yml @@ -0,0 +1,44 @@ +osxcross arm64: + extends: .srb2ci + + stage: build + + when: manual + + allow_failure: true + + artifacts: + paths: + - "build.osxcross/bin/" + - "build.osxcross/src/config.h" + expose_as: "Mac arm64" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-clang" + + variables: + OSXCROSS_HOST: arm64-apple-darwin21.4 + LD: arm64-apple-darwin21.4-ld + + script: + - - | + # apt_development + echo -e "\e[0Ksection_start:`date +%s`:macports_development[collapsed=true]\r\e[0KInstalling development packages" + - osxcross-macports install --arm64 curl libopenmpt libsdl2_mixer + - | + # apt_development + echo -e "\e[0Ksection_end:`date +%s`:macports_development\r\e[0K" + + - - | + # cmake + echo -e "\e[0Ksection_start:`date +%s`:cmake[collapsed=false]\r\e[0KBuilding Makefiles" + - cmake -B build.osxcross --toolchain /osxcross/toolchain.cmake -DCPM_USE_LOCAL_PACKAGES:BOOL=ON -DOPENMPT_INCLUDE_DIR:PATH="/osxcross/macports/pkgs/opt/local/include" -DSDL2_INCLUDE_DIR:PATH="/osxcross/macports/pkgs/opt/local/lib" -DSRB2_CONFIG_ENABLE_TESTS:BOOL=OFF -DSRB2_CONFIG_SYSTEM_LIBRARIES:BOOL=ON -DSRB2_CONFIG_FORCE_NO_MS_BITFIELDS:BOOL=ON -DSRB2_CONFIG_USE_GME:BOOL=OFF -G "Unix Makefiles" + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" + + - - | + # make + echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" + - make --directory=build.osxcross --keep-going || make --directory=build.osxcross --keep-going + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" diff --git a/.gitlab/ci/jobs/macos-x86_64.yml b/.gitlab/ci/jobs/macos-x86_64.yml new file mode 100644 index 0000000000000000000000000000000000000000..525a919c8a6976308d752bc82e68143233d59798 --- /dev/null +++ b/.gitlab/ci/jobs/macos-x86_64.yml @@ -0,0 +1,115 @@ +osxcross x86_64: + extends: .srb2ci + + stage: build + + cache: + - key: ccache-$CI_JOB_NAME_SLUG-$CI_COMMIT_REF_SLUG + fallback_keys: + - ccache-$CI_JOB_NAME_SLUG-$CI_DEFAULT_BRANCH + - ccache-$CI_JOB_NAME_SLUG-master + paths: + - build/ccache + - build/ccache_statslog + + - key: apt-$CI_JOB_IMAGE + paths: + - build/apt-cache + unprotect: true + + - key: vcpkg-root + paths: + - build/vcpkg-root + unprotect: true + + - key: vcpkg-binary-cache-x64-osx + paths: + - build/vcpkg-binary-cache + unprotect: true + + artifacts: + paths: + - "build.osxcross/bin/" + - "build.osxcross/src/config.h" + expose_as: "Mac x86_64" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-clang" + + variables: + OSXCROSS_HOST: x86_64-apple-darwin21.4 + LD: x86_64-apple-darwin21.4-ld + + script: + - | + # vcpkg + echo -e "\e[0Ksection_start:`date +%s`:vcpkg-root[collapsed=true]\r\e[0KUpdating vcpkg" + + if [ -d "build/vcpkg-root" ]; then + pushd build/vcpkg-root + git fetch https://github.com/Microsoft/vcpkg master + git reset --hard FETCH_HEAD + popd + else + mkdir -p build + git clone https://github.com/Microsoft/vcpkg build/vcpkg-root + fi + + export VCPKG_ROOT=$(pwd)/build/vcpkg-root + export VCPKG_BINARY_SOURCES="clear;files,$(pwd)/build/vcpkg-binary-cache,readwrite" + + mkdir -p "build/vcpkg-binary-cache" + + echo -e "\e[0Ksection_end:`date +%s`:vcpkg-root\r\e[0K" + + - - | + # apt_development + echo -e "\e[0Ksection_start:`date +%s`:macports_development[collapsed=true]\r\e[0KInstalling development packages" + - osxcross-macports install curl libopenmpt libsdl2_mixer + - | + # apt_development + echo -e "\e[0Ksection_end:`date +%s`:macports_development\r\e[0K" + + - - | + # cmake + echo -e "\e[0Ksection_start:`date +%s`:cmake[collapsed=false]\r\e[0KBuilding Makefiles" + - cmake -B build.osxcross --toolchain /osxcross/toolchain.cmake -DCPM_USE_LOCAL_PACKAGES:BOOL=ON -DOPENMPT_INCLUDE_DIR:PATH="/osxcross/macports/pkgs/opt/local/include" -DSDL2_INCLUDE_DIR:PATH="/osxcross/macports/pkgs/opt/local/lib" -DSRB2_CONFIG_ENABLE_TESTS:BOOL=OFF -DSRB2_CONFIG_SYSTEM_LIBRARIES:BOOL=ON -DSRB2_CONFIG_USE_GME:BOOL=OFF -G "Unix Makefiles" + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" + + - - | + # make + echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" + - make --directory=build.osxcross --keep-going || make --directory=build.osxcross --keep-going + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" + + 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" + + - - | + # vcpkg_clean + echo -e "\e[0Ksection_start:`date +%s`:vcpkg_clean[collapsed=true]\r\e[0KCleaning vcpkg-root" + + if [ -d "build/vcpkg-root" ]; then + pushd "build/vcpkg-root" + git clean + popd + fi + + echo -e "\e[0Ksection_end:`date +%s`:vcpkg_clean\r\e[0K" + + - - | + # ccache_stats + echo -e "\e[0Ksection_start:`date +%s`:ccache_stats[collapsed=true]\r\e[0Kccache statistics:" + - ccache --show-stats + - ccache --show-log-stats || true + - | + # ccahe_stats + echo -e "\e[0Ksection_end:`date +%s`:ccache_stats\r\e[0K" diff --git a/.gitlab/ci/jobs/windows-x64-makefile.yml b/.gitlab/ci/jobs/windows-x64-makefile.yml new file mode 100644 index 0000000000000000000000000000000000000000..f28fa219cc09550684abeddb5300927f00882d1a --- /dev/null +++ b/.gitlab/ci/jobs/windows-x64-makefile.yml @@ -0,0 +1,35 @@ +Windows x64 Makefile: + extends: .srb2ci + + stage: build + + when: manual + + allow_failure: true + + artifacts: + paths: + - "bin/" + - "src/comptime.h" + expose_as: "Win64-makefile" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-Win64-makefile" + + 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" diff --git a/.gitlab/ci/jobs/windows-x64.yml b/.gitlab/ci/jobs/windows-x64.yml new file mode 100644 index 0000000000000000000000000000000000000000..180fa773c34823e9eebd8254500233d1be8215a7 --- /dev/null +++ b/.gitlab/ci/jobs/windows-x64.yml @@ -0,0 +1,51 @@ +Windows x64: + extends: .srb2ci + + stage: build + + when: manual + + allow_failure: true + + artifacts: + paths: + - "build.cmake/bin/" + - "build.cmake/src/config.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" + + - - | + # apt_development + echo -e "\e[0Ksection_start:`date +%s`:apt_development[collapsed=true]\r\e[0KInstalling development packages" + - apt-get install ninja-build + - | + # apt_development + echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K" + + - - | + # cmake + echo -e "\e[0Ksection_start:`date +%s`:cmake[collapsed=false]\r\e[0KBuilding Makefiles" + - cmake -B build.cmake -DSRB2_USE_CCACHE=YES -DSRB2_CONFIG_ERRORMODE=ON -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-mingw-static -DVCPKG_CHAINLOAD_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/toolchains/mingw.cmake + - | + # cmake + echo -e "\e[0Ksection_end:`date +%s`:cmake\r\e[0K" + + - - | + # make + echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" + - make --directory=build.cmake --keep-going || make --directory=build.cmake --keep-going + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" diff --git a/.gitlab/ci/jobs/windows-x86-makefile.yml b/.gitlab/ci/jobs/windows-x86-makefile.yml new file mode 100644 index 0000000000000000000000000000000000000000..9601cd6e68013b1971b6d3276802bad932a5a95c --- /dev/null +++ b/.gitlab/ci/jobs/windows-x86-makefile.yml @@ -0,0 +1,35 @@ +Windows x86 Makefile: + extends: .srb2ci + + stage: build + + when: on_success + + artifacts: + paths: + - "bin/" + - "src/comptime.h" + expose_as: "Win32-makefile" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-Win32-makefile" + + variables: + PREFIX: i686-w64-mingw32 + CC: /usr/bin/i686-w64-mingw32-gcc-posix + CXX: /usr/bin/i686-w64-mingw32-g++-posix + + 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" diff --git a/.gitlab/ci/jobs/windows-x86.yml b/.gitlab/ci/jobs/windows-x86.yml new file mode 100644 index 0000000000000000000000000000000000000000..2d885508570913bdb71bbb2bab1bd34f03c7e67a --- /dev/null +++ b/.gitlab/ci/jobs/windows-x86.yml @@ -0,0 +1,130 @@ +Windows x86: + extends: .srb2ci + + stage: build + + when: manual + + allow_failure: true + + cache: + - key: ccache-$CI_JOB_NAME_SLUG-$CI_COMMIT_REF_SLUG + fallback_keys: + - ccache-$CI_JOB_NAME_SLUG-$CI_DEFAULT_BRANCH + - ccache-$CI_JOB_NAME_SLUG-master + paths: + - build/ccache + - build/ccache_statslog + + - key: apt-$CI_JOB_IMAGE + paths: + - build/apt-cache + unprotect: true + + - key: vcpkg-root + paths: + - build/vcpkg-root + unprotect: true + + - key: vcpkg-binary-cache-x86-mingw-static + paths: + - build/vcpkg-binary-cache + unprotect: true + + artifacts: + paths: + - "build/ninja-x86_mingw_static_vcpkg-debug/bin/" + - "build/ninja-x86_mingw_static_vcpkg-debug/src/config.h" + expose_as: "Win32" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-Win32" + + variables: + PREFIX: i686-w64-mingw32 + CC: /usr/bin/i686-w64-mingw32-gcc-posix + CXX: /usr/bin/i686-w64-mingw32-g++-posix + + script: + - | + # vcpkg + echo -e "\e[0Ksection_start:`date +%s`:vcpkg-root[collapsed=true]\r\e[0KUpdating vcpkg" + + if [ -d "build/vcpkg-root" ]; then + pushd build/vcpkg-root + git fetch https://github.com/Microsoft/vcpkg master + git reset --hard FETCH_HEAD + popd + else + mkdir -p build + git clone https://github.com/Microsoft/vcpkg build/vcpkg-root + fi + + export VCPKG_ROOT=$(pwd)/build/vcpkg-root + export VCPKG_BINARY_SOURCES="clear;files,$(pwd)/build/vcpkg-binary-cache,readwrite" + + mkdir -p "build/vcpkg-binary-cache" + + echo -e "\e[0Ksection_end:`date +%s`:vcpkg-root\r\e[0K" + + - - | + # 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" + + - - | + # apt_development + echo -e "\e[0Ksection_start:`date +%s`:apt_development[collapsed=true]\r\e[0KInstalling development packages" + - apt-get install ninja-build + - | + # apt_development + echo -e "\e[0Ksection_end:`date +%s`:apt_development\r\e[0K" + + - - | + # cmake + echo -e "\e[0Ksection_start:`date +%s`:cmake[collapsed=false]\r\e[0KBuilding Makefiles" + # cmake + echo -e "\e[0Ksection_start:`date +%s`:cmake[collapsed=false]\r\e[0KBuilding Makefiles" + - cmake --preset ninja-x86_mingw_static_vcpkg-debug -G "Unix Makefiles" -DSRB2_USE_CCACHE=YES -DSRB2_CONFIG_ERRORMODE=ON -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake + - | + # cmake + echo -e "\e[0Ksection_end:`date +%s`:cmake\r\e[0K" + + - - | + # make + echo -e "\e[0Ksection_start:`date +%s`:make[collapsed=false]\r\e[0KCompiling SRB2" + - cmake --build --preset ninja-x86_mingw_static_vcpkg-debug --parallel 1 -- --keep-going || cmake --build --preset ninja-x86_mingw_static_vcpkg-debug --parallel 1 -- --keep-going + - | + # make + echo -e "\e[0Ksection_end:`date +%s`:make\r\e[0K" + + 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" + + - - | + # vcpkg_clean + echo -e "\e[0Ksection_start:`date +%s`:vcpkg_clean[collapsed=true]\r\e[0KCleaning vcpkg-root" + + if [ -d "build/vcpkg-root" ]; then + pushd "build/vcpkg-root" + git clean -f + popd + fi + + echo -e "\e[0Ksection_end:`date +%s`:vcpkg_clean\r\e[0K" + + - - | + # ccache_stats + echo -e "\e[0Ksection_start:`date +%s`:ccache_stats[collapsed=true]\r\e[0Kccache statistics:" + - ccache --show-stats + - ccache --show-log-stats || true + - | + # ccahe_stats + echo -e "\e[0Ksection_end:`date +%s`:ccache_stats\r\e[0K" diff --git a/.gitlab/ci/templates/srb2ci.yml b/.gitlab/ci/templates/srb2ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..bdf8a3ed66d8126559c25e5563da432da41932e0 --- /dev/null +++ b/.gitlab/ci/templates/srb2ci.yml @@ -0,0 +1,145 @@ +.srb2ci: + image: git.do.srb2.org:5050/stjr/srb2ci/srb2ci:stable + + cache: + - key: ccache-$CI_JOB_NAME_SLUG-$CI_COMMIT_REF_SLUG + fallback_keys: + - ccache-$CI_JOB_NAME_SLUG-$CI_DEFAULT_BRANCH + - ccache-$CI_JOB_NAME_SLUG-master + paths: + - build/ccache + - build/ccache_statslog + + - key: apt-$CI_JOB_IMAGE + paths: + - build/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=$CI_PROJECT_DIR/build/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" + - timeout 2m apt-get update || timeout 2m 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 cmake ca-certificates + - | + # 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 = $CI_PROJECT_DIR | tee --append ~/.ccache/ccache.conf + - | + # cache_dir + echo cache_dir = $CI_PROJECT_DIR/build/ccache | tee --append ~/.ccache/ccache.conf + - | + # compiler_check + echo compiler_check = content | tee --append ~/.ccache/ccache.conf + - | + # stats_log + echo stats_log = $CI_PROJECT_DIR/build/ccache_statslog | tee --append ~/.ccache/ccache.conf + - | + # max_size + echo max_size = 300M | 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" + + 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 + - ccache --show-log-stats || true + - | + # ccahe_stats + echo -e "\e[0Ksection_end:`date +%s`:ccache_stats\r\e[0K" diff --git a/CMakeLists.txt b/CMakeLists.txt index 8803620e7a9305cb28359aa31c973223d4df247f..a4c631102606ee3177c94f1bb7a35b100694bf4c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ endif() set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") include(CMakeDependentOption) -include(cmake/CPM.cmake) +include(CheckCXXCompilerFlag) file(STRINGS src/version.h SRB2_VERSION) string(REGEX MATCH "[0-9]+\\.[0-9.]+" SRB2_VERSION ${SRB2_VERSION}) @@ -46,30 +46,26 @@ SET(CPACK_OUTPUT_FILE_PREFIX package) include(CPack) # Options - -if("${CMAKE_SYSTEM_NAME}" MATCHES Linux) - set(SRB2_CONFIG_SYSTEM_LIBRARIES_DEFAULT ON) +if("${CMAKE_SYSTEM_NAME}" MATCHES Windows) + if(DEFINED VCPKG_TARGET_TRIPLET) + set(SRB2_CONFIG_SYSTEM_LIBRARIES_DEFAULT ON) + else() + set(SRB2_CONFIG_SYSTEM_LIBRARIES_DEFAULT OFF) + endif() else() - set(SRB2_CONFIG_SYSTEM_LIBRARIES_DEFAULT OFF) + set(SRB2_CONFIG_SYSTEM_LIBRARIES_DEFAULT ON) 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 - "Use dynamic libraries when compiling internal dependencies" - OFF "NOT SRB2_CONFIG_SYSTEM_LIBRARIES" - OFF + SRB2_CONFIG_STATIC_STDLIB + "Link static version of standard library. All dependencies must also be static" + ON ) option(SRB2_CONFIG_HWRENDER "Enable hardware render (OpenGL) support" ON) +option(SRB2_CONFIG_USE_GME "Enable GME playback support" OFF) option(SRB2_CONFIG_STATIC_OPENGL "Enable static linking GL (do not do this)" OFF) option(SRB2_CONFIG_ERRORMODE "Compile C code with warnings treated as errors." OFF) option(SRB2_CONFIG_DEBUGMODE "Compile with PARANOIA, ZDEBUG, RANGECHECK and PACKETDROP defined." OFF) @@ -77,67 +73,32 @@ option(SRB2_CONFIG_MOBJCONSISTANCY "Compile with MOBJCONSISTANCY defined." OFF) option(SRB2_CONFIG_PACKETDROP "Compile with PACKETDROP defined." OFF) option(SRB2_CONFIG_EXECINFO "Enable stack trace dump support." ON) option(SRB2_CONFIG_ZDEBUG "Compile with ZDEBUG defined." OFF) +option(SRB2_CONFIG_FORCE_NO_MS_BITFIELDS "Compile without -mno-ms-bitfields compiler flag" OFF) # SRB2_CONFIG_PROFILEMODE is probably superceded by some CMake setting. 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() +# Dependencies +add_subdirectory(thirdparty) -# Enable CCache -# (Set USE_CCACHE=ON to use, CCACHE_OPTIONS for options) -if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL Windows) - option(USE_CCACHE "Enable ccache support" OFF) - - if(USE_CCACHE) - find_program(CCACHE_TOOL_PATH ccache) - if(CCACHE_TOOL_PATH) - set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_TOOL_PATH} CACHE STRING "" FORCE) - set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_TOOL_PATH} CACHE STRING "" FORCE) - else() - message(WARNING "USE_CCACHE was set but ccache is not found (set CCACHE_TOOL_PATH)") - endif() - endif() +if(SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES) + set(SRB2_INTERNAL_LIBRARY_TYPE SHARED) + set(NOT_SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES OFF) else() - CPMAddPackage( - NAME Ccache.cmake - GITHUB_REPOSITORY TheLartians/Ccache.cmake - VERSION 1.2 - ) + set(SRB2_INTERNAL_LIBRARY_TYPE STATIC) + set(NOT_SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES ON) endif() -# Dependencies -add_subdirectory(thirdparty) -if("${SRB2_CONFIG_SYSTEM_LIBRARIES}") - find_package(ZLIB REQUIRED) - find_package(PNG REQUIRED) - find_package(SDL2 REQUIRED) - find_package(SDL2_mixer REQUIRED) - find_package(CURL REQUIRED) - find_package(OPENMPT 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) +find_package(ZLIB REQUIRED) +find_package(PNG REQUIRED) +find_package(CURL REQUIRED) +find_package(libopenmpt QUIET) +if("${SRB2_CONFIG_USE_GME}") + find_package(libgme QUIET) endif() +find_package(miniupnpc QUIET) + if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR}) message(FATAL_ERROR "In-source builds will bring you a world of pain. Please make a separate directory to invoke CMake from.") diff --git a/CMakePresets.json b/CMakePresets.json index effea7260656c6235c75b07669edea01eeb682b7..8cb95d797f7f4c3ae708effa15e0d38112175937 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -2,26 +2,263 @@ "version": 3, "configurePresets": [ { - "name": "default", - "description": "Build using default generator", - "binaryDir": "build", + "name": "__debug", + "hidden": true, "cacheVariables": { + "SRB2_CONFIG_DEV_BUILD": "ON", + "CMAKE_BUILD_TYPE": "Debug" + } + }, + { + "name": "__develop", + "hidden": true, + "cacheVariables": { + "CMAKE_C_FLAGS_RELWITHDEBINFO": "-DNDEBUG", + "CMAKE_CXX_FLAGS_RELWITHDEBINFO": "-DNDEBUG", + "SRB2_CONFIG_DEV_BUILD": "ON", "CMAKE_BUILD_TYPE": "RelWithDebInfo" } }, { - "name": "debug", - "description": "Build for development (no optimizations)", - "inherits": "default", + "name": "__release", + "hidden": true, "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug" + "CMAKE_C_FLAGS_RELWITHDEBINFO": "-DNDEBUG", + "CMAKE_CXX_FLAGS_RELWITHDEBINFO": "-DNDEBUG", + "SRB2_CONFIG_DEV_BUILD": "OFF", + "CMAKE_BUILD_TYPE": "RelWithDebInfo" + } + }, + { + "name": "__testers", + "hidden": true, + "cacheVariables": { + "CMAKE_C_FLAGS_RELWITHDEBINFO": "-DNDEBUG", + "CMAKE_CXX_FLAGS_RELWITHDEBINFO": "-DNDEBUG", + "SRB2_CONFIG_DEV_BUILD": "ON", + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "SRB2_CONFIG_TESTERS": "ON" + } + }, + { + "name": "__ninja", + "hidden": true, + "generator": "Ninja", + "cacheVariables": { + "CMAKE_COLOR_DIAGNOSTICS": "ON" + } + }, + { + "name": "__vcpkg-toolchain", + "hidden": true, + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" + } + }, + { + "name": "__compiler-mingw-w64-i686", + "hidden": true, + "cacheVariables": { + "CMAKE_C_COMPILER": "i686-w64-mingw32-gcc", + "CMAKE_CXX_COMPILER": "i686-w64-mingw32-g++" + } + }, + { + "name": "__mingw-dynamic", + "hidden": true, + "cacheVariables": { + "VCPKG_TARGET_TRIPLET": "x86-mingw-dynamic" } + }, + { + "name": "__mingw-static", + "hidden": true, + "cacheVariables": { + "VCPKG_HOST_TRIPLET": "x86-mingw-static", + "VCPKG_TARGET_TRIPLET": "x86-mingw-static" + } + }, + { + "name": "__osx_x64", + "hidden": true, + "cacheVariables": { + "VCPKG_TARGET_TRIPLET": "x64-osx" + } + }, + { + "name": "__osx_arm64", + "hidden": true, + "cacheVariables": { + "VCPKG_TARGET_TRIPLET": "arm64-osx" + } + }, + + { + "name": "ninja-debug", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__debug", "__ninja"] + }, + { + "name": "ninja-develop", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__develop", "__ninja"] + }, + { + "name": "ninja-release", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__release", "__ninja"] + }, + { + "name": "ninja-testers", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__testers", "__ninja"] + }, + + { + "name": "ninja-vcpkg-debug", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__debug", "__ninja", "__vcpkg-toolchain"] + }, + { + "name": "ninja-vcpkg-develop", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__develop", "__ninja", "__vcpkg-toolchain"] + }, + { + "name": "ninja-vcpkg-release", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__release", "__ninja", "__vcpkg-toolchain"] + }, + { + "name": "ninja-vcpkg-testers", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__testers", "__ninja", "__vcpkg-toolchain"] + }, + + { + "name": "ninja-x86_mingw_static_vcpkg-debug", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__debug", "__compiler-mingw-w64-i686", "__ninja", "__vcpkg-toolchain", "__mingw-static"] + }, + { + "name": "ninja-x86_mingw_static_vcpkg-develop", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__develop", "__compiler-mingw-w64-i686", "__ninja", "__vcpkg-toolchain", "__mingw-static"] + }, + { + "name": "ninja-x86_mingw_static_vcpkg-release", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__release", "__compiler-mingw-w64-i686", "__ninja", "__vcpkg-toolchain", "__mingw-static"] + }, + { + "name": "ninja-x86_mingw_static_vcpkg-testers", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__testers", "__compiler-mingw-w64-i686", "__ninja", "__vcpkg-toolchain", "__mingw-static"] + }, + + { + "name": "ninja-x64_osx_vcpkg-debug", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__debug", "__ninja", "__vcpkg-toolchain", "__osx_x64"] + }, + { + "name": "ninja-x64_osx_vcpkg-develop", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__develop", "__ninja", "__vcpkg-toolchain", "__osx_x64"] + }, + { + "name": "ninja-x64_osx_vcpkg-release", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__release", "__ninja", "__vcpkg-toolchain", "__osx_x64"] + }, + + { + "name": "ninja-arm64_osx_vcpkg-debug", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__debug", "__ninja", "__vcpkg-toolchain", "__osx_arm64"] + }, + { + "name": "ninja-arm64_osx_vcpkg-develop", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__develop", "__ninja", "__vcpkg-toolchain", "__osx_arm64"] + }, + { + "name": "ninja-arm64_osx_vcpkg-release", + "hidden": false, + "binaryDir": "build/${presetName}", + "inherits": ["__release", "__ninja", "__vcpkg-toolchain", "__osx_arm64"] } ], + "buildPresets": [ { - "name": "default", - "configurePreset": "default" + "name": "ninja-debug", + "configurePreset": "ninja-debug" + }, + { + "name": "ninja-develop", + "configurePreset": "ninja-develop" + }, + { + "name": "ninja-release", + "configurePreset": "ninja-release" + }, + { + "name": "ninja-x86_mingw_static_vcpkg-debug", + "configurePreset": "ninja-x86_mingw_static_vcpkg-debug" + }, + { + "name": "ninja-x86_mingw_static_vcpkg-develop", + "configurePreset": "ninja-x86_mingw_static_vcpkg-develop" + }, + { + "name": "ninja-x86_mingw_static_vcpkg-release", + "configurePreset": "ninja-x86_mingw_static_vcpkg-release" + }, + { + "name": "ninja-x86_mingw_static_vcpkg-testers", + "configurePreset": "ninja-x86_mingw_static_vcpkg-testers" + }, + { + "name": "ninja-x64_osx_vcpkg-debug", + "configurePreset": "ninja-x64_osx_vcpkg-debug" + }, + { + "name": "ninja-x64_osx_vcpkg-develop", + "configurePreset": "ninja-x64_osx_vcpkg-develop" + }, + { + "name": "ninja-x64_osx_vcpkg-release", + "configurePreset": "ninja-x64_osx_vcpkg-release" + }, + { + "name": "ninja-arm64_osx_vcpkg-debug", + "configurePreset": "ninja-arm64_osx_vcpkg-debug" + }, + { + "name": "ninja-arm64_osx_vcpkg-develop", + "configurePreset": "ninja-arm64_osx_vcpkg-develop" + }, + { + "name": "ninja-arm64_osx_vcpkg-release", + "configurePreset": "ninja-arm64_osx_vcpkg-release" } ] -} +} \ No newline at end of file diff --git a/assets/CMakeLists.txt b/assets/CMakeLists.txt index dfb2f4180db7dbbae9a454a6f939aeda9e6f26a4..68c84819513075a90e21917ce797acf893c2a40d 100644 --- a/assets/CMakeLists.txt +++ b/assets/CMakeLists.txt @@ -27,10 +27,10 @@ list(TRANSFORM SRB2_ASSETS_DOCS PREPEND "${SRB2_ASSET_DIRECTORY_ABSOLUTE}") set(SRB2_ASSETS_GAME "srb2.pk3" - "player.dta" + "characters.pk3" "zones.pk3" "patch.pk3" - "music.dta" + "music.pk3" "models.dat" ) list(TRANSFORM SRB2_ASSETS_GAME PREPEND "/") diff --git a/assets/README.txt b/assets/README.txt index e384333ed762459cd140fff13fdb777036d3d698..1ddacc999d7bde07f18e9c4fbb9041467dbda619 100644 --- a/assets/README.txt +++ b/assets/README.txt @@ -33,13 +33,10 @@ https://discord.gg/b3BGb8A Twitter: https://twitter.com/SonicTeamJr -Facebook: -https://facebook.com/SonicRoboBlast2 - COPYRIGHT AND DISCLAIMER -Design and content in Sonic Robo Blast 2 is copyright 1998-2023 by Sonic Team Jr. +Design and content in Sonic Robo Blast 2 is copyright 1998-2025 by Sonic Team Jr. All original material in this game is copyrighted by their respective owners, and no copyright infringement is intended. Sonic Team Jr. is in no way affiliated with SEGA or Sonic Team, and we do not claim ownership of any of SEGA's intellectual property used in SRB2. diff --git a/assets/debian-template/copyright b/assets/debian-template/copyright index cc47c453bf2b0ccc6db34c57a03dfe1ce2fc75a7..71d2cf583d6e6e624ad7a12638ea65df775f4223 100644 --- a/assets/debian-template/copyright +++ b/assets/debian-template/copyright @@ -12,7 +12,7 @@ Upstream Author(s): Copyright: - Copyright (C) 1998-2018 by Sonic Team Junior + Copyright (C) 1998-2025 by Sonic Team Junior License: @@ -21,7 +21,7 @@ License: The Debian packaging is: Copyright (C) 2010 Callum Dickinson <gcfreak_ag20@hotmail.com> - Copyright (C) 2010-2018 by Sonic Team Junior <stjr@srb2.org> + Copyright (C) 2010-2025 by Sonic Team Junior <stjr@srb2.org> and is licensed under the GPL version 2, see "/usr/share/common-licenses/GPL-2". diff --git a/cmake/CPM.cmake b/cmake/CPM.cmake deleted file mode 100644 index fba27d2fef3d2bf2edb50ea41687157dc0730c20..0000000000000000000000000000000000000000 --- a/cmake/CPM.cmake +++ /dev/null @@ -1,21 +0,0 @@ -set(CPM_DOWNLOAD_VERSION 0.38.7) - -if(CPM_SOURCE_CACHE) - set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") -elseif(DEFINED ENV{CPM_SOURCE_CACHE}) - set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") -else() - set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake") -endif() - -# Expand relative path. This is important if the provided path contains a tilde (~) -get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE) -if(NOT (EXISTS ${CPM_DOWNLOAD_LOCATION})) - message(STATUS "Downloading CPM.cmake to ${CPM_DOWNLOAD_LOCATION}") - file(DOWNLOAD - https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake - ${CPM_DOWNLOAD_LOCATION} - ) -endif() - -include(${CPM_DOWNLOAD_LOCATION}) diff --git a/cmake/Modules/FindGME.cmake b/cmake/Modules/FindGME.cmake deleted file mode 100644 index 3af0a94be604f44cf0eda200f3d90a129ea77809..0000000000000000000000000000000000000000 --- a/cmake/Modules/FindGME.cmake +++ /dev/null @@ -1,33 +0,0 @@ -include(LibFindMacros) - -libfind_pkg_check_modules(GME_PKGCONF GME) - -find_path(GME_INCLUDE_DIR - NAMES gme.h - PATHS - ${GME_PKGCONF_INCLUDE_DIRS} - "/usr/include/gme" - "/usr/local/include/gme" -) - -find_library(GME_LIBRARY - NAMES gme - PATHS - ${GME_PKGCONF_LIBRARY_DIRS} - "/usr/lib" - "/usr/local/lib" -) - -set(GME_PROCESS_INCLUDES GME_INCLUDE_DIR) -set(GME_PROCESS_LIBS GME_LIBRARY) -libfind_process(GME) - -if(GME_FOUND AND NOT TARGET gme) - add_library(gme UNKNOWN IMPORTED) - set_target_properties( - gme - PROPERTIES - IMPORTED_LOCATION "${GME_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${GME_INCLUDE_DIR}" - ) -endif() diff --git a/cmake/Modules/FindOPENMPT.cmake b/cmake/Modules/FindOPENMPT.cmake deleted file mode 100644 index 7e5b2d5a3966be22d22afdb815934cf20fe0e4d7..0000000000000000000000000000000000000000 --- a/cmake/Modules/FindOPENMPT.cmake +++ /dev/null @@ -1,33 +0,0 @@ -include(LibFindMacros) - -libfind_pkg_check_modules(OPENMPT_PKGCONF OPENMPT) - -find_path(OPENMPT_INCLUDE_DIR - NAMES libopenmpt.h - PATHS - ${OPENMPT_PKGCONF_INCLUDE_DIRS} - "/usr/include/libopenmpt" - "/usr/local/include/libopenmpt" -) - -find_library(OPENMPT_LIBRARY - NAMES openmpt - PATHS - ${OPENMPT_PKGCONF_LIBRARY_DIRS} - "/usr/lib" - "/usr/local/lib" -) - -set(OPENMPT_PROCESS_INCLUDES OPENMPT_INCLUDE_DIR) -set(OPENMPT_PROCESS_LIBS OPENMPT_LIBRARY) -libfind_process(OPENMPT) - -if(OPENMPT_FOUND AND NOT TARGET openmpt) - add_library(openmpt UNKNOWN IMPORTED) - set_target_properties( - openmpt - PROPERTIES - IMPORTED_LOCATION "${OPENMPT_LIBRARY}" - INTERFACE_INCLUDE_DIRECTORIES "${OPENMPT_INCLUDE_DIR}" - ) -endif() diff --git a/cmake/Modules/Findlibgme.cmake b/cmake/Modules/Findlibgme.cmake new file mode 100644 index 0000000000000000000000000000000000000000..6b693a7fd14234eb89c24798ea340b6a39030d33 --- /dev/null +++ b/cmake/Modules/Findlibgme.cmake @@ -0,0 +1,38 @@ +include(LibFindMacros) + +libfind_pkg_check_modules(libgme_PKGCONF gme libgme) + +find_path(libgme_INCLUDE_DIR + NAMES gme.h + PATHS + ${libgme_PKGCONF_INCLUDE_DIRS} + "/usr/include" + "/usr/local/include" + PATH_SUFFIXES + gme +) + +find_library(libgme_LIBRARY + NAMES gme + PATHS + ${libgme_PKGCONF_LIBRARY_DIRS} + "/usr/lib" + "/usr/local/lib" +) + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(libgme + REQUIRED_VARS libgme_LIBRARY libgme_INCLUDE_DIR) + +if(libgme_FOUND AND NOT TARGET gme) + add_library(gme UNKNOWN IMPORTED) + set_target_properties( + gme + PROPERTIES + IMPORTED_LOCATION "${libgme_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${libgme_INCLUDE_DIR}" + ) + add_library(gme::gme ALIAS gme) +endif() + +mark_as_advanced(libgme_LIBRARY libgme_INCLUDE_DIR) diff --git a/cmake/Modules/Findlibopenmpt.cmake b/cmake/Modules/Findlibopenmpt.cmake new file mode 100644 index 0000000000000000000000000000000000000000..96cc3102677c0639bed76fe28cf60efd13e63429 --- /dev/null +++ b/cmake/Modules/Findlibopenmpt.cmake @@ -0,0 +1,39 @@ +include(LibFindMacros) + +libfind_pkg_check_modules(libopenmpt_PKGCONF openmpt libopenmpt) + +find_path(libopenmpt_INCLUDE_DIR + NAMES libopenmpt.h + PATHS + ${libopenmpt_PKGCONF_INCLUDE_DIRS} + "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/include" + "/usr/include" + "/usr/local/include" + PATH_SUFFIXES ++ libopenmpt +) + +find_library(libopenmpt_LIBRARY + NAMES openmpt + PATHS + ${libopenmpt_PKGCONF_LIBRARY_DIRS} + "/usr/lib" + "/usr/local/lib" +) + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(libopenmpt + REQUIRED_VARS libopenmpt_LIBRARY libopenmpt_INCLUDE_DIR) + +if(libopenmpt_FOUND AND NOT TARGET openmpt) + add_library(openmpt UNKNOWN IMPORTED) + set_target_properties( + openmpt + PROPERTIES + IMPORTED_LOCATION "${libopenmpt_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${libopenmpt_INCLUDE_DIR}" + ) + add_library(libopenmpt::libopenmpt ALIAS openmpt) +endif() + +mark_as_advanced(libopenmpt_LIBRARY libopenmpt_INCLUDE_DIR) diff --git a/cmake/Modules/Findminiupnpc.cmake b/cmake/Modules/Findminiupnpc.cmake new file mode 100644 index 0000000000000000000000000000000000000000..f4931ad832eb856583be1c12daaf4d9883847ed3 --- /dev/null +++ b/cmake/Modules/Findminiupnpc.cmake @@ -0,0 +1,39 @@ +include(LibFindMacros) + +libfind_pkg_check_modules(libminiupnpc_PKGCONF miniupnpc libminiupnpc) + +find_path(libminiupnpc_INCLUDE_DIR + NAMES miniupnpc.h + PATHS + ${libminiupnpc_PKGCONF_INCLUDE_DIRS} + "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/include" + "/usr/include" + "/usr/local/include" + PATH_SUFFIXES + miniupnpc +) + +find_library(libminiupnpc_LIBRARY + NAMES miniupnpc + PATHS + ${libminiupnpc_PKGCONF_LIBRARY_DIRS} + "/usr/lib" + "/usr/local/lib" +) + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(miniupnpc + REQUIRED_VARS libminiupnpc_LIBRARY libminiupnpc_INCLUDE_DIR) + +if(miniupnpc_FOUND AND NOT TARGET miniupnpc) + add_library(miniupnpc UNKNOWN IMPORTED) + set_target_properties( + miniupnpc + PROPERTIES + IMPORTED_LOCATION "${libminiupnpc_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${libminiupnpc_INCLUDE_DIR}" + ) + add_library(miniupnpc::miniupnpc ALIAS miniupnpc) +endif() + +mark_as_advanced(libminiupnpc_LIBRARY libminiupnpc_INCLUDE_DIR) diff --git a/cmake/PatchFile.cmake b/cmake/PatchFile.cmake new file mode 100644 index 0000000000000000000000000000000000000000..f80da3434d764fdbc1eb1f0219c38204517ee19a --- /dev/null +++ b/cmake/PatchFile.cmake @@ -0,0 +1,30 @@ +# use GNU Patch from any platform + +if(WIN32) + # prioritize Git Patch on Windows as other Patches may be very old and incompatible. + find_package(Git) + if(Git_FOUND) + get_filename_component(GIT_DIR ${GIT_EXECUTABLE} DIRECTORY) + get_filename_component(GIT_DIR ${GIT_DIR} DIRECTORY) + endif() +endif() + +find_program(PATCH +NAMES patch +HINTS ${GIT_DIR} +PATH_SUFFIXES usr/bin +) + +if(NOT PATCH) + message(FATAL_ERROR "Did not find GNU Patch") +endif() + +execute_process(COMMAND ${PATCH} ${in_file} --input=${patch_file} --output=${out_file} --ignore-whitespace +TIMEOUT 15 +COMMAND_ECHO STDOUT +RESULT_VARIABLE ret +) + +if(NOT ret EQUAL 0) + message(FATAL_ERROR "Failed to apply patch ${patch_file} to ${in_file} with ${PATCH}") +endif() \ No newline at end of file diff --git a/cmake/Toolchains/mingw-w64-i686.cmake b/cmake/Toolchains/mingw-w64-i686.cmake new file mode 100644 index 0000000000000000000000000000000000000000..6b327291d79d905e7fd97e99196e8b0809fa8d06 --- /dev/null +++ b/cmake/Toolchains/mingw-w64-i686.cmake @@ -0,0 +1,16 @@ +set(CMAKE_SYSTEM_NAME Windows) +set(TOOLCHAIN_PREFIX i686-w64-mingw32) + +# cross compilers to use for C, C++ and Fortran +set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++) +set(CMAKE_Fortran_COMPILER ${TOOLCHAIN_PREFIX}-gfortran) +set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres) + +# target environment on the build host system +set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX}) + +# modify default behavior of FIND_XXX() commands +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/cmake/Toolchains/mingw-w64-x86_64.cmake b/cmake/Toolchains/mingw-w64-x86_64.cmake new file mode 100644 index 0000000000000000000000000000000000000000..2f22e13d8a5dc80e869c5ca2f0089e5d9917ff7d --- /dev/null +++ b/cmake/Toolchains/mingw-w64-x86_64.cmake @@ -0,0 +1,16 @@ +set(CMAKE_SYSTEM_NAME Windows) +set(TOOLCHAIN_PREFIX x86_64-w64-mingw32) + +# cross compilers to use for C, C++ and Fortran +set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++) +set(CMAKE_Fortran_COMPILER ${TOOLCHAIN_PREFIX}-gfortran) +set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres) + +# target environment on the build host system +set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX}) + +# modify default behavior of FIND_XXX() commands +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/debian-template/copyright b/debian-template/copyright index cc47c453bf2b0ccc6db34c57a03dfe1ce2fc75a7..71d2cf583d6e6e624ad7a12638ea65df775f4223 100644 --- a/debian-template/copyright +++ b/debian-template/copyright @@ -12,7 +12,7 @@ Upstream Author(s): Copyright: - Copyright (C) 1998-2018 by Sonic Team Junior + Copyright (C) 1998-2025 by Sonic Team Junior License: @@ -21,7 +21,7 @@ License: The Debian packaging is: Copyright (C) 2010 Callum Dickinson <gcfreak_ag20@hotmail.com> - Copyright (C) 2010-2018 by Sonic Team Junior <stjr@srb2.org> + Copyright (C) 2010-2025 by Sonic Team Junior <stjr@srb2.org> and is licensed under the GPL version 2, see "/usr/share/common-licenses/GPL-2". diff --git a/doc/Doublescan.txt b/doc/Doublescan.txt deleted file mode 100644 index 5e492ec89c56e550d1a653be5d695d78d798c9ca..0000000000000000000000000000000000000000 --- a/doc/Doublescan.txt +++ /dev/null @@ -1,93 +0,0 @@ - ================================================================ - How to add Low-res modes to your XF86Config under Linux MANUALLY - ================================================================ - - I TAKE NO RESPONSIBILITY FOR ANY DAMAGE DONE TO YOUR EQUIPMENT!!! - - This document explains how to add low-res modes like 320x200 to your - X-Server configuration, because some new setup tools for the X-Server - do not support this. ONLY RECOMMENDED FOR USERS WHO KNOW WHAT THEY DO! - - I do not take any responsibility for damage done to your monitor, your - videocard, your harddisk, your cat, your dog or anything else!!! - IMPORTANT IS, THAT YOUR "HorizSync" AND "VertRefresh" VALUES REALLY - MATCH YOUR MONITOR! OTHERWISE YOUR MONITOR CAN BLOW UP!!! - - OK, if you have read up to here, you either know what you do or really - die-hard want those low-res modes. Here is what to do: - Look up your XF86Config. Is is either in /etc or in /etc/X11. Here is - what you have to add to the definition of your modeslines: - -# Low-res Doublescan modes -# If your chipset does not support doublescan, you get a 'squashed' -# resolution like 320x400. - -# 320x200 @ 70 Hz, 31.5 kHz hsync, 8:5 aspect ratio -Modeline "320x200" 12.588 320 336 384 400 200 204 205 225 Doublescan -# 320x240 @ 60 Hz, 31.5 kHz hsync, 4:3 aspect ratio -Modeline "320x240" 12.588 320 336 384 400 240 245 246 262 Doublescan -# 320x240 @ 72 Hz, 36.5 kHz hsync -Modeline "320x240" 15.750 320 336 384 400 240 244 246 262 Doublescan -# 400x300 @ 56 Hz, 35.2 kHz hsync, 4:3 aspect ratio -ModeLine "400x300" 18 400 416 448 512 300 301 302 312 Doublescan -# 400x300 @ 60 Hz, 37.8 kHz hsync -Modeline "400x300" 20 400 416 480 528 300 301 303 314 Doublescan -# 400x300 @ 72 Hz, 48.0 kHz hsync -Modeline "400x300" 25 400 424 488 520 300 319 322 333 Doublescan - - If your video card only supports a specific set of discrete dotclocks - (RAMDAC) you may have to replace the dotclocks given here by one of the - specified (e.g in the first modeline the dotclock is 12.588 MHz). I believe - that nowadays all cards and monitors should work with these settings, but - if you have outdated hardware you better check the frequencies yourself. If - there is any uncertainty, please check the "XFree86 Video Timings HOWTO". - - - Then have a look at the section "Screen" with the appropriate driver - (usually either "svga" or "accel"). Under Subsection "Display" there - are modes for the given color depth. Add the desired modes. As an - example I give you my screens definition here with low-res modes in - 16 bit color depth: - -Section "Screen" - Driver "accel" - Device "3D Charger" - Monitor "Iiyama Pro 450" - DefaultColorDepth 16 - - Subsection "Display" - Depth 8 - Modes "1280x1024" "1024x768" "800x600" "640x480" - ViewPort 0 0 - Virtual 1280 1024 - EndSubsection - Subsection "Display" - Depth 16 - Modes "1152x864" "1024x768" "800x600" "640x480" "400x300" "320x200" <- THIS IS ACTUALLY WHAT YOU WANT!!! - ViewPort 0 0 ^^^^^^^^^^^^^^^^^^^ - Virtual 1152 864 - EndSubsection - Subsection "Display" - Depth 24 - Modes "800x600" "640x480" - ViewPort 0 0 - Virtual 800 600 - EndSubsection - Subsection "Display" - Depth 32 - Modes "800x600" "640x480" - ViewPort 0 0 - Virtual 800 600 - EndSubsection -EndSection - - Once again: important is, that you edit the correct Screen section. - If you use the SVGA Server and edit the ACCEL Server, you might - wonder where your new modes have gone. - - If everything went fine and you want to say thank you, just write - to "metzgermeister@users.sourceforge.net". If your monitor blew - up and you want to kill me, find me playing Legacy or Q3A on the net - and frag me (with your second monitor, hehe). - - - metzgermeister diff --git a/doc/Item Ranges.txt b/doc/Item Ranges.txt deleted file mode 100644 index 60251e5479c75e9b74a5b04c7ab7c9c9b5788a5b..0000000000000000000000000000000000000000 --- a/doc/Item Ranges.txt +++ /dev/null @@ -1,212 +0,0 @@ -1-99 : Player Starts - 1 - Player 1 Start 1 - 2 - Player 2 Start 2 - 3 - Player 3 Start 3 - 4 - Player 4 Start 4 - 5 - Player 5 Start 4001 - 6 - Player 6 Start 4002 - 7 - Player 7 Start 4003 - 8 - Player 8 Start 4004 - 9 - Player 9 Start 4005 - 10 - Player 10 Start 4006 - 11 - Player 11 Start 4007 - 12 - Player 12 Start 4008 - 13 - Player 13 Start 4009 - 14 - Player 14 Start 4010 - 15 - Player 15 Start 4011 - 16 - Player 16 Start 4012 - 17 - Player 17 Start 4013 - 18 - Player 18 Start 4014 - 19 - Player 19 Start 4015 - 20 - Player 20 Start 4016 - 21 - Player 21 Start 4017 - 22 - Player 22 Start 4018 - 23 - Player 23 Start 4019 - 24 - Player 24 Start 4020 - 25 - Player 25 Start 4021 - 26 - Player 26 Start 4022 - 27 - Player 27 Start 4023 - 28 - Player 28 Start 4024 - 29 - Player 29 Start 4025 - 30 - Player 30 Start 4026 - 31 - Player 31 Start 4027 - 32 - Player 32 Start 4028 - 33 - Player Match Start 11 - 34 - Red Team Start 87 - 35 - Blue Team Start 89 - 36 - Tag start New - -100 - 199 : Enemies - 100 - Blue Crawla 3004 - 101 - Red Crawla 9 - 102 - GFZ Fish 58 - 103 - Gold Buzz 5005 - 104 - Red Buzz 5006 - 105 - Jetty-Syn Bomber 3005 - 106 - Jetty-Syn Gunner 22 - 107 - Crawla Commander 21 - 108 - Deton 71 - 109 - Skim 56 - 110 - THZ Turret 2004 - 111 - Pop-up Turret 42 - -200 - 299 : Bosses and their associated items (if any) - 200 - Boss 1 16 - 201 - Boss 2 2008 - 290 - Boss Fly Point 17 - 291 - EggTrap Center 2049 - -300 - 399 : Collectibles - 300 - Ring 2014 - 301 - Homing Ring 69 - 302 - Rail Ring 3003 - 303 - Infinity Ring 80 - 304 - Automatic Ring 26 - 305 - Explosion Ring 54 - 306 - Red CTF Flag 31 - 307 - Blue CTF Flag 34 - 308 - Special Stage Token 2013 - 309 - Emerald 1 420 - 310 - Emerald 2 421 - 311 - Emerald 3 422 - 312 - Emerald 4 423 - 313 - Emerald 5 424 - 314 - Emerald 6 425 - 315 - Emerald 7 426 - 316 - Hunting Emerald 1 64 - 317 - Hunting Emerald 2 3002 - 318 - Hunting Emerald 3 3001 - -400 - 499 : Boxes - 400 - Super Ring Box 2011 - 401 - Grey Ring Box 2012 - 402 - Ring Shield Box 48 - 403 - Fire Shield Box 2002 - 404 - Bomb Shield Box 2018 - 405 - Jump Shield Box 35 - 406 - Water Shield Box 2028 - 407 - Sneaker Box 25 - 408 - Invincibility Box 2022 - 409 - 1-Up Box 41 - 410 - Eggman Box 2005 - 411 - Mixup Box 78 - 412 - Question Box 3000 - -500 - 599 : Interactive Objects (friendly or otherwise - includes springs) - 500 - Bubble Patch 33 - 501 - Level End Sign 86 - 502 - Starpost 3006 - 520 - Spike Ball -1 - 521 - Special Stage Spike Ball 23 - 522 - Ceiling Spike 67 - 523 - Floor Spike 68 - 540 - Fan 32 - 541 - Steam Riser 30 - 550 - Yellow Spring 28 - 551 - Red Spring 79 - 552 - Blue Spring 5004 - 553 - Yellow Spring Down 65 - 554 - Red Spring Down 66 - 555 - Yellow Diagonal Spring 2015 - 556 - Red Diagonal Spring 38 - 557 - Yellow Diag Spring Down 20 - 558 - Red Diag Spring Down 39 - -600 - 699 : Special placement patterns - 600 - Vertical Rigns - Stack of 5 (suitable for Yellow Spring) 84 - 601 - Vertical Rings - Stack of 5 (suitable for Red Spring) 44 - 602 - Diagonal rings (5) 76 - 603 - Diagonal rings (10) 77 - 604 - A ring of rings 47 - 605 - A BIGGER ring of rings 2007 - 606 - A ring of wing items 2048 - 607 - A BIGGER ring of wing items 2010 - 608 - A ring of rings and wings (alternating) 2046 - 609 - A BIGGER ring of rings and wings (alternating) 2047 - -700 - 799 : Powerup indicators/environmental effects/miscellany - 700 - Ambient Water 1a (S) 2026 - 701 - Ambient Water 1b (S) 2024 - 702 - Ambient Water 2a (M) 2023 - 703 - Ambient Water 2b (M) 2045 - 704 - Ambient Water 3a (L) 83 - 705 - Ambient Water 3b (L) 2019 - 706 - Ambient Water 4a (XL) 2025 - 707 - Ambient Water 4b (XL) 27 - 708 - Random Ambient 1 14 - 709 - Random Ambient 2 43 - 750 - Chaos Spawner 8 - 751 - Teleport Point 5003 - 752 - Alternate View Point 5007 - 753 - Zoom Tube Waypoint 18 - 754 - Pusher 5001 - 755 - Puller 5002 - 756 - Street Light 2003 - -800 - 899 : Greenflower Scenery - 800 - Flower 1 36 - 801 - Flower 2 70 - 802 - Flower 3 73 - 804 - Berry Bush 74 - 805 - Bush 75 - -900 - 999 : Techno Hill Scenery - 900 - THZ Plant 2035 - 901 - Alarm 2006 - -1000 - 1099 : Deep Sea Scenery - 1000 - Gargoyle 81 - -1100 - 1199 : Castle Eggman Scenery - 1100 - Ceiling Chain 49 - 1101 - Torch Flame 24 - 1102 - Eggman Statue 52 - 1103 - CEZ Flower 2001 - -1200 - 1299 : Arid Canyon Scenery -1300 - 1399 : Red Volcano Scenery -1400 - 1499 : Dark City Scenery -1500 - 1599 : Doom Ship Scenery -1600 - 1699 : Egg Rock/Final Fight Scenery -1700 - 1799 : NiGHTS Items - 1700 - Axis 72 - 1701 - Axis Transfer (Normal) 61 - 1702 - Axis Transfer (Line) 46 - 1703 - Nights Drone 60 - 1704 - Nights Bumper 82 - 1705 - Hoop 57 - 1706 - Nights Wing 37 - 1707 - Super Loop Powerup 3007 - 1708 - Drill Refill Powerup 3008 - 1709 - Helper Powerup 3009 - 1710 - Egg Capsule 40 - -1800 - 1849 : Mario Items - 1800 - Coin 10005 - 1801 - Goomba 10000 - 1802 - Blue Goomba 10001 - 1803 - FireFlower 50 - 1804 - Shell 10 - 1805 - Puma 29 - 1806 - Koopa 19 - 1807 - Axe 12 - 1808 - Mario Bush 1 10002 - 1809 - Mario Bush 2 10003 - 1810 - Toad 10004 - -1850 - 1899 : Christmas Items - 1850 - Xmas Pole 5 - 1851 - Candy Cane 13 - 1852 - Snowman 6 - -1900 - 1999 : Misc Scenery - 1900 - Stalagmite 0 - 1901 - Stalagmite 1 - 1902 - Stalagmite 2 - 1903 - Stalagmite 3 - 1904 - Stalagmite 4 - 1905 - Stalagmite 5 - 1906 - Stalagmite 6 - 1907 - Stalagmite 7 - 1908 - Stalagmite 8 - 1909 - Stalagmite 9 diff --git a/doc/Linedef Ranges.txt b/doc/Linedef Ranges.txt deleted file mode 100644 index 81fa695a0dcb8c0b3592225edbd82a7885c683e6..0000000000000000000000000000000000000000 --- a/doc/Linedef Ranges.txt +++ /dev/null @@ -1,223 +0,0 @@ - Description OldNum NewNum Description - Old Water 14 Removed - - Level Parameters/Misc: - Per-Sector Gravity 64 1 - Custom Exit 71 2 - Zoom Tube Parameters 18 3 - Speed Pad 65 4 - Camera Scanner 63 5 - Disable Linedef 73 6 - Flat Alignment 66 7 - Sector Special Parameters New 8 - Mace Parameters New 9 - Sprite Cull Height New 10 - Rope Hang Parameters New 11 - Rock Spawner Parameters New 12 - - PolyObjects - Marks first line in PolyObject New 20 - Explicitly includes a PolyObject line New 21 - PolyObject: Parameters New 22 - PolyObject: Waving Flag New 31 - - Level-Load Effects: - Instant Floor Lower 26 50 - Instant Ceiling Raise 24 51 - Continuously Falling Sector 88 52 - Continuous Floor/Ceiling Mover 2 53 - Continuous Floor Mover 3 54 - Continuous Ceiling Mover 4 55 - Continuous Two-Speed Floor/Ceiling Mover 6 56 - Continuous Two-Speed Floor Mover 7 57 - Continuous Two-Speed Ceiling Mover 8 58 - Activate Floating Platform 232 59 - Activate Floating Platform (Adjustable Speed) 233 60 - Crusher 1 (Ceiling to Floor) 43 61 - Crusher 2 (Floor to Ceiling) 50 62 - Fake Floor/Ceiling 242 63 - Appearing/Disappearing FOF New 64 - Bridge Thinker New 65 - - Floor Over Floors: - "Floor Over Floor: Solid, Opaque, Shadowcasting " 25 100 - "Floor Over Floor: Solid, Opaque, Non-Shadowcasting " 33 101 - "Floor Over Floor: Solid, Translucent " 44 102 - "Floor Over Floor: Solid, Sides Only " 69 103 - "Floor Over Floor: Solid, No Sides " 51 104 - "Floor Over Floor: Solid, Invisible " 57 105 - - "Floor Over Floor: Water, Opaque " 48 120 - "Floor Over Floor: Water, Translucent " 45 121 - "Floor Over Floor: Water, Opaque, No Sides " 75 122 - "Floor Over Floor: Water, Translucent, No Sides " 74 123 - - "Floor Over Floor: Platform, Opaque " 59 140 - "Floor Over Floor: Platform, Translucent " 81 141 - "Floor Over Floor: Platform, Translucent, No Sides " 77 142 - - Floor Over Floor: Bobbing (Air) 38 150 - Floor Over Floor: Adjustable Bobbing (Air) 68 151 - Floor Over Floor: Reverse Adjustable Bobbing (Air) 72 152 - - "Floor Over Floor: Floating, Bobbing " 34 160 - - Floor Over Floor: Crumbling (Respawn) 36 170 - Floor Over Floor: Crumbling (No Respawn) 35 171 - "Floor Over Floor: Crumbling (Respawn), Platform " 79 172 - "Floor Over Floor: Crumbling (No Respawn), Platform " 80 173 - "Floor Over Floor: Crumbling (Respawn), Platform, Translucent " 82 174 - "Floor Over Floor: Crumbling (No Respawn), Platform, Translucent " 83 175 - "Floor Over Floor: Crumbling (Respawn), Floating, Bobbing " 39 176 - "Floor Over Floor: Crumbling (No Respawn), Floating, Bobbing " 1 177 - "Floor Over Floor: Crumbling (Respawn), Floating " 37 178 - "Floor Over Floor: Crumbling (No Respawn), Floating " 42 179 - "Floor Over Floor: Crumbling (Respawn), Bobbing (Air) " 40 180 - - "Floor Over Floor: Rising Platform, Solid, Opaque, Shadowcasting " 89 190 - "Floor Over Floor: Rising Platform, Solid, Opaque, Non-Shadowcasting " 90 191 - "Floor Over Floor: Rising Platform, Solid, Translucent " 91 192 - "Floor Over Floor: Rising Platform, Solid, Invisible " 94 193 - "Floor Over Floor: Rising Platform, Platform, Opaque " 92 194 - "Floor Over Floor: Rising Platform, Platform, Translucent " 93 195 - - Floor Over Floor: Light Block 49 200 - Floor Over Floor: Half Light Block 47 201 - Floor Over Floor: Fog Block 46 202 - - "Floor Over Floor: Intangible, Opaque " 62 220 - "Floor Over Floor: Intangible, Translucent " 52 221 - "Floor Over Floor: Intangible, Sides Only " 67 222 - "Floor Over Floor: Intangible, Invisible " 58 223 - - Floor Over Floor: Mario Block 41 250 - Floor Over Floor: Thwomp Block 54 251 - Floor Over Floor: Shatter Block 76 252 - "Floor Over Floor: Shatter Block, Translucent " 86 253 - Floor Over Floor: Bustable Block 55 254 - Floor Over Floor: Spin Bust Block 78 255 - "Floor Over Floor: Spin Bust Block, Translucent " 84 256 - Floor Over Floor: Quicksand Block 56 257 - Floor Over Floor: Laser Block 53 258 - Floor Over Floor: Custom 87 259 - - Linedef Executor Triggers: - Trigger Linedef Executor (Continuous) 96 300 - Trigger Linedef Executor (Each Time) 97 301 - Trigger Linedef Executor (Once) 98 302 - Trigger Linedef Executor (Ring Count - Continuous) 95 303 - Trigger Linedef Executor (Ring Count - Once) 99 304 - Trigger Linedef Executor (Character Ability - Continuous) 19 305 - Trigger Linedef Executor (Character Ability - Each Time) 20 306 - Trigger Linedef Executor (Character Ability - Once) 21 307 - "Trigger Linedef Executor (Race Only, Once) " 9 308 - Trigger Linedef Executor (CTF Red Team - Continuous) 10 309 - Trigger Linedef Executor (CTF Red Team - Each Time) 11 310 - Trigger Linedef Executor (CTF Blue Team - Continuous) 12 311 - Trigger Linedef Executor (CTF Blue Team - Each Time) 13 312 - Trigger Linedef Executor (No More Enemies - Once) 15 313 - Trigger Linedef Executor (# of Pushables - Continuous) New 314 - Trigger Linedef Executor (# of Pushables - Once) New 315 - Trigger Linedef Executors (PolyObject - Land On) New 316 - Trigger Linedef Executor (Level Load) New 399 - - Linedef Executor Options: - Linedef Executor: Set Tagged Sector's Floor Height/Pic 101 400 - Linedef Executor: Set Tagged Sector's Ceiling Height/Pic 102 401 - Linedef Executor: Set Tagged Sector's Light Level 103 402 - Linedef Executor: Move Tagged Sector's Floor 106 403 - Linedef Executor: Move Tagged Sector's Ceiling 107 404 - Linedef Executor: Lower Floor by Line 108 405 - Linedef Executor: Raise Floor by Line 109 406 - Linedef Executor: Lower Ceiling by Line 110 407 - Linedef Executor: Raise Ceiling by Line 111 408 - Linedef Executor: Change Calling Sector's Tag 112 409 - Linedef Executor: Change Front Sector's Tag 114 410 - Linedef Executor: Stop Plane Movement 116 411 - Linedef Executor: Teleport Player to Tagged Sector 104 412 - Linedef Executor: Change Music 105 413 - Linedef Executor: Play SFX 115 414 - Linedef Executor: Run Script 113 415 - Linedef Executor: Start Adjustable Fire Flicker 119 416 - Linedef Executor: Start Adjustable Glowing Light 120 417 - Linedef Executor: Start Adjustable Strobe Flash (unsynchronized) New 418 - Linedef Executor: Start Adjustable Strobe Flash (synchronized) New 419 - Linedef Executor: Fade Light Level 117 420 - Linedef Executor: Stop Lighting Effect 118 421 - Linedef Executor: Cut-Away View 121 422 - Linedef Executor: Change Sky 123 423 - Linedef Executor: Change Weather 124 424 - Linedef Executor: Change Object State 125 425 - Linedef Executor: Stop Object 122 426 - Linedef Executor: Award Score 126 427 - Linedef Executor: Start Platform Movement 127 428 - Linedef Executor: Crush Ceiling Once New 429 - Linedef Executor: Crush Floor Once New 430 - Linedef Executor: Crush Floor & Ceiling Once New 431 - Linedef Executor: Enable 2D Mode New 432 - Linedef Executor: Disable 2D Mode New 433 - Linedef Executor: Award Custom Power New 434 - Linedef Executor: Stop Conveyor New 435 - Linedef Executor: Start Conveyor New 436 - Linedef Executor: Disable Player Movement New 437 - - Linedef Executor: Execute Linedef Executor New 450 - - Linedef Executor: PolyObject: Door Slide New 480 - Linedef Executor: PolyObject: Door Swing New 481 - Linedef Executor: PolyObject: Move XY New 482 - Linedef Executor: PolyObject: Move XY w/ override New 483 - Linedef Executor: PolyObject: Rotate Right New 484 - Linedef Executor: PolyObject: Rotate Right w/ override New 485 - Linedef Executor: PolyObject: Rotate Left New 486 - Linedef Executor: PolyObject: Rotate Left w/ override New 487 - Linedef Executor: PolyObject: Start waypoint movement New 488 - Linedef Executor: PolyObject: Make Invisible New 489 - Linedef Executor: PolyObject: Make Visible New 490 - - Scrollers/Pushers: - Scroll Wall First Side Left 100 500 - Scroll Wall First Side Opposite Direction 85 501 - Scroll Wall According to Linedef 254 502 - Acc Scroll Wall According to Linedef 218 503 - Disp Scroll Wall According to Linedef 249 504 - Scroll Texture by Offsets 255 505 - - Scroll Floor Texture 251 510 - Acc Scroll Floor Texture 215 511 - Disp Scroll Floor Texture 246 512 - Scroll Ceiling Texture 250 513 - Acc Scroll Ceiling Texture 214 514 - Disp Scroll Ceiling Texture 245 515 - - Carry Objects on Floor (no scroll) 252 520 - Acc Carry Objects on Floor 216 521 - Disp Carry Objects on Floor 247 522 - Carry Objects on Ceiling 203 523 - Acc Carry Objects on Ceiling 205 524 - Disp Carry Objects on Ceiling 201 525 - - Scroll Floor Texture and Carry Objects 253 530 - Acc Scroll Floor Texture and Carry Objects 217 531 - Disp Scroll Floor Texture and Carry Objects 248 532 - Scroll Ceiling Texture and Carry Objects 202 533 - Acc Scroll Ceiling Texture and Carry Objects 204 534 - Disp Scroll Ceiling Texture and Carry Objects 200 535 - - Friction 223 540 - Horizontal Wind 224 541 - Upwards Wind 229 542 - Downwards Wind 230 543 - Horizontal Current 225 544 - Upwards Current 227 545 - Downwards Current 228 546 - Boom Push/Pull Thing 226 547 - - Lighting: - Floor Lighting 213 600 - Ceiling Lighting 5 601 - Adjustable Pulsating Light 60 602 - Adjustable Flickering Light 61 603 - Adjustable Blinking Light (unsynchronized) New 604 - Adjustable Blinking Light (synchronized) New 605 - Colormap 16 606 diff --git a/doc/SSN-Todo.xls b/doc/SSN-Todo.xls deleted file mode 100644 index c468b34764f0b1a7ebcb3f552aeb8fd4cd56fb76..0000000000000000000000000000000000000000 Binary files a/doc/SSN-Todo.xls and /dev/null differ diff --git a/doc/Sector Ranges.txt b/doc/Sector Ranges.txt deleted file mode 100644 index 42760e1334a90a7fbf25028fcdaf62d0feb3156c..0000000000000000000000000000000000000000 --- a/doc/Sector Ranges.txt +++ /dev/null @@ -1,78 +0,0 @@ -Removed: - - Buttons 1-20 690-709 - - Button 21 (THZ2 A/740 B/741 D/742 E/745 710 - - Close Door Blazing (Tag 743) 711 - - Raise Ceiling to Highest (Tag 744) 981 - - THZ2 Slime Raise (B/712 W713 P714 D715 S716) 986 - -Stuff to Remove/Change: - - Light Blinks On Every 0.5 Seconds 2 Add Linedef Combine - - Light Blinks On Every 1 Second 3 Add Linedef Combine - - Light Pulses Smoothly 8 Remove - - Light Blinks On Every 0.5 Seconds (Sync) 12 Add Linedef Combine - - Lights Blinks On Every 1 Second (Sync) 13 Add Linedef Combine - - Light Flickers Like Fire 17 Remove - ? - Damage (Fire) and Current 519 Remove (convert to combination) - ? - Damage (Water) and Current 984 Remove (convert to combination) - -Section 1: - 1 - Damage (Generic) 11 - 2 - Damage (Water) 983 - 3 - Damage (Fire) 7 - 4 - Damage (Electrical) 18 - 5 - Spikes 4 - 6 - Death Pit (Camera Mod) 16 - 7 - Death Pit (No Camera Mod) 5 - 8 - Instant Kill 10 - 9 - Ring Drainer (Floor Touch) 978 - 10 - Ring Drainer (No Floor Touch) 980 - 11 - Special Stage Damage 9 - 12 - Space Countdown 6 - 13 - Ramp Sector (Increase step-up) 992 - 14 - Non-Ramp Sector (Don't step-down) 996 - 15 - Bouncy Sector (FOF Control Only) 14 - -Section 2: << 4 - 1 - Trigger Linedef Exec (Pushable Objects) 971 - 2 - Trigger LD Exec (Anywhere in Sec/All Pls) 972 - 3 - Trigger Linedef Exec (Floor Touch/All Pls) 973 - 4 - Trigger Linedef Exec (Anywhere in Sec) 974 - 5 - Trigger Linedef Exec (Floor Touch) 975 - 6 - Trigger Linedef Exec (Emerald Check) 967 - 7 - Trigger Linedef Exec (NiGHTS Mare) 968 - 8 - Check for linedef executor on FOFs (ANY) 970 - 9 - Egg Trap Capsule 666 - 10 - Special Stage Time/Rings, Par 990 - 11 - Custom Global Gravity 991 - -Section 3: << 8 - 1 - Ice/Sludge (required?!) 256 - 2 - Wind/Current (required?!) 512 - 3 - Ice/Sludge and Wind/Current 768 - 4 - Conveyor Belt 985 - 5 - Speed Pad (No Spin) 976 - 6 - Speed Pad (Spin) 977 - 7 - Bustable Block Sprite Parameter 1500-1515 - 8 - " - 9 - " - 10 - " - 11 - " - 12 - " - 13 - " - 14 - " - 15 - " - -Section 4: << 12 - 1 - Starpost Activator 993 - 2 - Special Stage Goal Combine 33 - 2 - Exit Sector Combine 982 - 2 - No Tag Zone Combine 987 - 2 - CTF: Flag Return Combine 995 - 3 - CTF: Red Team Base 988 - 4 - CTF: Blue Team Base 989 - 5 - Fan Sector 997 - 6 - Super Sonic Transform 969 - 7 - Spinner 979 - 8 - Zoom Tube Start 998 - 9 - Zoom Tube End 999 - 10 - Finish Line 994 \ No newline at end of file diff --git a/doc/faq.txt b/doc/faq.txt deleted file mode 100644 index 26c75bbadd5581c36c835ae1a11f405f634a2834..0000000000000000000000000000000000000000 --- a/doc/faq.txt +++ /dev/null @@ -1,307 +0,0 @@ - SRB2 - Release v1.09, ? 2005. - - Last Updated: June 2005 - - Original game & sources by: Id Software. - Additions: (c)1998 by: Fabrice Denis & Boris Pereira - (c)1999 by: Fabrice Denis, Boris Pereira & Thierry Van Elsuwe - (c)2000 by: Boris Pereira & Thierry Van Elsuwe - (c)2004 By: AJ, Graue, Alam Arias, Logan Arias & Andrew Clunis - - Special thanks to Steven McGranahan, Lee Killough, Robert B�uml and Bell Kin for - their large contribution and to other DooM LEGACY & SRB2 Team members. - - Web site: http://www.SRB2.org/ - e-mail: none@none.com - - OpenGL specific: - Web site: http://legacy.newdoom.com/gl - - - ----------------------------------------------------------------------- - F.A.Q. - ----------------------------------------------------------------------- - - - If you have any trouble with SRB2, you might find a solution - here. - - If you find a solution to a problem that was not listed here, - please tell us so that we can update the FAQ and help other people! - - Mail your hardware/software problems to: - - None@none.com subject: FAQ - - - -------- - CONTENTS - -------- - - [0] Miscellaneous - [1] Mouse/Joystick/Keyboard - [2] Video - [3] Sound - [4] Network - [5] Troubleshooting - - - ----------------- - [0] MISCELLANEOUS - ----------------- - - * under win95 or OS/2, I don't have enough memory. How can i handle with ? - - Tell win95 to put more dpmi memory for your dos box. - Or use the -mb option. - - - - --------------------------- - [1] MOUSE/JOYSTICK/KEYBOARD - --------------------------- - - * My mouse/joystick does not work in SRB2. - - First, check that the mouse/joystick is activated : go at the - console and type either 'use_mouse' (or use the respective - menuitem) or 'use_joystick'. - - If it tells '0' or off than the mouse/joystick is not used, - set the variable to 1. eg: 'use_mouse 1'. - - For the joystick, different values will support different - types of joystick, check the console documentation for the - command 'use_joystick' for more. - - Even if the mouse or joystick is activated, you have to - set up the contols into the Setup Controls menu. That is: - tell what use you will make of the mouse/joystick buttons. - - - --------- - [2] VIDEO - --------- - - - * Where are the other video modes ? I have only '320x200' in the - Video Modes menu. - - DOS - --- - - SRB2 adds new video modes only if a VESA2 (or better) driver - is present. The VESA2 driver is a standard of 'talking' between a - program and the huge amount of different graphics cards - available today. - - If you don't have a VESA2 driver, you can download UNIVBE, or - SMART DISPLAY DOCTOR from - - http://www.scitechsoft.com/products/ent/free_titles.html - - or if you have an S3 based card, you can download the free - software called 'S3VBE'. - - ftp://ftp.externet.hu/pub/mirror/sac/graph/s3vbe318.zip - ftp://ftp.digsys.bg/pub/simtelnet/msdos/graphics/s3vbe318.zip - http://www.filesearching.com/cgi-bin/s?q=s3vbe318.zip - http://www.google.com/search?q=s3vbe318.zip - - * The game doesn't restore the video mode I have chosen the last time - I played SRB2. - - The current video mode has to be made the 'default' so that it is - saved to the config : press the key 'D' on the Video Options menu - to set the current video mode the default. - - * I have some problems with OpenGL mode - - Have a look at the FAQ for OpenGL on the glLegacy web site: - - http://www.doomnation.com/gllegacy/faqe.htm - - # Linux: I only have a 1024x768 (or 800x600, 1280x1024, ...) resolution - in fullscreen mode under X and SRB2 is really really slow. Can I - have lower resolutions like 320x200 in fullscreen mode as well? - - Probably yes. SRB2 can only use the resolutions offered by the - X-Server. So if all fullscreen modes have a very high resolution you - have to modify /etc/XF86Config (or /etc/X11/XF86Config). Use XF86Setup - (or the appropriate tool coming with your distribution - sax, - xf86config, ...) to do this. - If you do not succeed there, you can enter them manually into your - XF86Config file. ONLY RECOMMENDED FOR USERS WHO KNOW WHAT THEY DO! - For a short guide on how to do this, have a look at the file - "Doublescan.txt". - In case of doubt consult the XFree86-HOWTO (or ask your system - administrator :). - - # Linux: I cannot have any fullscreen modes at all! - - You have only modes above 1024x768 in your XF86Config. Proceed as - described above. - - # Linux: After a certain idle time my screensaver jams the display of - SRB2. I can still operate SRB2, but I do not see what's happening - and the screensaver won't go away. - - You probably have KDE. The KDE screensaver does not obey the screensaver - rules (at least mine, version 1.1). The solution is to deactivate the - KDE screensaver and use another screensaver (like the xscreensaver, - e.g.). But the hell, when you started SRB2 you should have played it - as well and not left it alone!!! - - --------- - [3] SOUND - --------- - - + DOS:I can't have CD audio music, why ? - - Make sure that the MSCDEX driver version 2.0 or later is loaded. - If it says 'MSCDEX version xxx' at game startup, and you still - don't hear the cd music, then probably your card doesn't respond - when SRB2 tries to set the cd volume. If so, make sure your sound - card's mixer have the cd volume set up so that you can hear something. - - + When the CD plays, the game is very 'jerky'. It doesn't do that when - I type 'cd off' in the console. - - You have an old/bad cd driver, that can take up to a second to - respond to cd driver commands. Either get the latest version of - your driver, or turn cd update off. Check 'cd_udpate' in the - console documentation for more. - - * DOS:How can I *ALWAYS* disable the sounds or music of the game ? - - Edit the allegro.cfg file and set digicard/midicard to 0 (none) - - * DOS:My sterero sound is reversed, how can I set it the right way ? - - Change the console variable 'stereoreverse' to either 1 or 0. - Or, you can edit the allegro.cfg file, and set the 'flip_pan' variable. - - - * DOS:The sounds are too 'slow', or 'low-pitched' - - It seems to be a problem of the auto-detection of some 8bit sound - cards. You will have to set manually the 'sb_freq' value in the - allegro.cfg file to a lower value : 11906, 16129. - - * DOS:SRB2 doesn't play any sound/music, but I have a sound - blaster genuine/compatible card. - - If you have a genuine or compatible SoundBlaster card, it is very - important that you set the BLASTER environment variable. - - If you are playing under DOS, and never installed your sound card - under DOS, run the setup of your sound card for DOS. - - Check if the BLASTER variable was set: type 'SET' under dos - (or DOSbox) - - Do you see something like 'BLASTER=A220 I5 D1 ...' ? - - Yes? If you don't hear sounds/music, then tweak the settings in the - allegro.cfg file until you get something, first try changing the - type of the sound card, it is not always properly detected. - - No? You have to set this variable in order that your sound card is - detected. Run the setup that was shipped with your sound card, and - make sure you run the setup for DOS too, it will usually add a - line of the type 'SET BLASTER=... ...' in the autoexec.bat file. - - - * DOS:How can I have better midi music on my 8bit sound card ? - - Use the DIGMID driver, it is supported in SRB2. - - What the hell is this? Well, the Gravis Ultrasound uses digital - samples to play midi music. On a simple 8bit card, you can use digital - samples too, which will sound usually better than what is output - by the poor fm synthesis chip of 8bit cards. - - You will need to get a Gravis Ultrasound patch set, you can find - several ones for free on internet, it consists of a bunch of '.pat' - files which are the digital samples to play the midi instruments - (eg: piano, conga, guitar, ect.). - - Check the Allegro homepage for some links to GUS patches: - http://alleg.sourceforge.net/digmid.html - http://alleg.sourceforge.net/ - http://www.talula.demon.co.uk/allegro/digmid.html - http://www.talula.demon.co.uk/allegro/ - - Now to activate the DIGMID driver: - - Set the 'midi_card' value to 8 (DIGMID) in the allegro.cfg file. - Make sure you leave the 'digi_voices' blank, or set it to a low - value, because the midi music will use digital voices. - At the end of the allegro.cfg file, set the 'patches' value - to the path, where you have installed a Gravis Ultrasound midi - patch set. eg: patches = d:\music\midipat\ - - # Linux: CD music does not work or only works when run as root. - - We do not encourage you to run SRB2 as root (you never know - what SRB2 can do to your system - it's a mighty piece of code :). - There is a common problem with ATAPI CD-rom drives, which are - treated as harddisks. Usually there is a link /dev/cdrom pointing to - device hd[b,c,d]. As harddisks are not supposed to be read directly - via this device (especially not by a common user), there are no read - permissions for "all". For CD-roms you can savely set read permissions - unless you are very paranoid. Assuming your CD-rom drive is /dev/hdc, - set permissions with "chmod +r /dev/hdc" (as root). SCSI CD-rom drives - should not have this problem. But if they do, proceed as described - with ATAPI drives. - - # Linux: The CD music volume is not set properly. - - Go to the console and type "jigglecdvolume 1". - - ----------- - [4] NETWORK - ----------- - - * Where can I find Internet servers ? - - For the moment there is one public server. - http://srb2.servegame.org/ Master server web page - srb2.servegame.org:28910 current Master Server - - * When I start SRB2 with -server or -connect it say : - "BinToPort: Address already in use (EADDRINUSE)" - - It appears only when SRB2 crashes or when you leave with ctrl-break. - use -udpport 12345 (or any other free slot) on both sides (client and - server). - - This can also happens when there is already a SRB2 running on your - computer if you whant to try two SRB2 running on the same computer - use -clientport 12345 (or any other free slot). Then the second will - connect to the first one. - - * Do you use the tcp protocol ? - - No, we use the udp protocol which is faster, but don't worry udp is a - part of the internet protocol. - - - ------------------- - [5] Troubleshooting - ------------------- - - # Linux: SRB2 is hung in fullscreen mode and won�t let me leave. - What shall I do? - - Some people press the reset button, but hey, we are not in the - stoneage of operating systems! There are two "proper" ways to - get out: kill your X-Server. You can usually do this by pressing - "CTRL-ALT-BACKSPACE". But if you have other open applications with - important data (probably hacked away on your diploma thesis for 3 - weeks without saving once) you can also kill SRB2 directly. Press - "CTRL-ALT-F2" and you will get to a console. Log in, type - "killall llxSRB2" and switch back to the X-Server with "CTRL-ALT-F7". - Some X-Server crash on this procedure - blame the X-Server for the - loss of 3 weeks work on your diploma thesis :) diff --git a/doc/manual/manual.htm b/doc/manual/manual.htm deleted file mode 100644 index 3fea1b66f18b694468c9103064e8c6fd1f33efd3..0000000000000000000000000000000000000000 --- a/doc/manual/manual.htm +++ /dev/null @@ -1,68 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> -<html> -<head> - <title> - Sonic Robo Blast 2 Manual - </title> - <link rel="stylesheet" type="text/css" href="srb2manstyle.css"> - <!-- Borrowed some javascript code so the height of the iframe is equal to the size of the document - Sonict --> - <script type="text/javascript"> - /* free code from dyn-web.com */ - - function getDocHeight(doc) { - doc = doc || document; - // from http://stackoverflow.com/questions/1145850/get-height-of-entire-document-with-javascript - var body = doc.body, html = doc.documentElement; - var height = Math.max( body.scrollHeight, body.offsetHeight, - html.clientHeight, html.scrollHeight, html.offsetHeight ); - return height; -} - - function setIframeHeight(id) { - var ifrm = document.getElementById(id); - var doc = ifrm.contentDocument? ifrm.contentDocument: ifrm.contentWindow.document; - ifrm.style.visibility = 'hidden'; - ifrm.style.height = "10px"; // reset to minimal height in case going from longer to shorter doc - ifrm.style.height = getDocHeight( doc ) + "px"; - ifrm.style.visibility = 'visible'; - } - </script> - <meta http-equiv="Content-type" content="text/html; charset=UTF-8"> -</head> -<body> - <p class="c1"> - <img src="manual_img/sonicname2.png" alt="SONIC" width="136" height="36"> - <br> - <img src="manual_img/srb2banner.png" alt="ROBO BLAST 2" width="224" height="43"> - </p> - <p class="c1"> - <big><big><strong>Manual</strong></big></big> - </p> - <table class="cf" align="center"> - <tr><td class="c"> - <ul class="hmenu"> - <li class="hmenu"><a class="hmenu" href="intro.htm" target="ifrm">Main</a></li> - <li class="hmenu"><a class="hmenu" href="items.htm" target="ifrm">Items</a></li> - <li class="hmenu"><a class="hmenu" href="playerabilities.htm" target="ifrm">Player Abilities</a></li> - <li class="hmenu"><a class="hmenu" href="basicplay.htm" target="ifrm">Gameplay</a></li> - <li class="hmenu"><a class="hmenu" href="surroundings.htm" target="ifrm">Surroundings</a></li> - </ul> - </td></tr> - <tr><td class="c"> - <ul class="hmenu"> - <li class="hmenu"><a class="hmenu" href="multiplayer.htm" target="ifrm">Multiplayer</a></li> - <li class="hmenu"><a class="hmenu" href="zones.htm" target="ifrm">Zones</a></li> - <li class="hmenu"><a class="hmenu" href="controls.htm" target="ifrm">Controls</a></li> - <li class="hmenu"><a class="hmenu" href="consolecommands.htm" target="ifrm">Console Commands</a></li> - <li class="hmenu"><a class="hmenu" href="misc.htm" target="ifrm">Misc</a></li> - </ul> - </td></tr> - </table> - <hr> - <p class="c1"> - <!-- The "onload" property of the iframe makes an error when validated through the W3C validation checker. --> - <!-- This will not be fixed as it isn't worth the time to fix it up properly. - Sonict --> - <iframe id="ifrm" name="ifrm" src="intro.htm" onload="setIframeHeight(this.id)"> </iframe> - </p> -</body> -</html> diff --git a/doc/rules.txt b/doc/rules.txt deleted file mode 100644 index 4bbb8cdc1f786022bc0f090154de4e7733080d32..0000000000000000000000000000000000000000 --- a/doc/rules.txt +++ /dev/null @@ -1,39 +0,0 @@ -SVN-RULES - -- As you can see, there is sub-directory in the repository, one for eatch - platform (djgpp (dos),win32,SDL) the root directory is for all platform, - so take care of the order we have put in. -- do not commit/upload tests of bugged code, try to fix a maximum of know - bugs and update know bugs list in source.txt. If you must commit your source - make your code in #ifdef so we can disable it -- SRB2 is a modification of doom/Doom Legacy source. We allow additionnal feature - and visual addition. -- Maximize communications between members, do not impose your changes, if your - are not sure about a feature/change, talk about it in irc://irc.esper.net/srb2 chat room. - -CODE-RULES - -- We use no tab, 4 space indent, and tab size 8 (in case some tab have filtred - and for makefile) -- Self documented code, variable and function must have a name that help - understand the code, so do not call variable and function a,b, a2, ... -- the usage of extern in a c file is prohibited, except for declaration of a - function with body (so it is like public keyword in c++) - Also function protos haren't allowed for external function, put it un the - corresponding h file. -- Try to minimize #ifdef usage for : - - code readability - - the main code is for all port so if something is good for a platform all - platform can benefit by this feature -- Take care of platform dependent code, we would like to have code that work - on Dos, Win32, SDL, ... little and big endian, software/Glide/OpenGl. - -GOOD PRACTICE - -- Try to put as mush static variable and function on module so it help to - understand the role of the varaible/function in the module also this - help the compiler to optimize -- minimise global variable -- make a log of your work, so you don't need to put a lot of comment in - the code, this will also help us to update the what's new section of doc - when doing final release diff --git a/doc/source.txt b/doc/source.txt deleted file mode 100644 index 5926d95fb94d9a31edccac1266cbfdb9661bda07..0000000000000000000000000000000000000000 --- a/doc/source.txt +++ /dev/null @@ -1,240 +0,0 @@ - -1. Compile SRB2 -2. Explanation of the code - 2.1 The memory model - 2.2 Hardware Texture model - -1. Compile SRB2 -================= - -DOS ---- - -need: -- djgpp 2.03 (http://www.delorie.com/djgpp/) -- allegro 3.12 (http://alleg.sourceforge.net/index.html) -( -- libsocket 0.7.4 (beta 4) or better - for use with Winsock 1.1 (example Windows 3.1) - (http://www.phekda.freeserve.co.uk/richdawe/lsck/lsck.htm) - OR -- Wattcp-32 v2.2 dev.rel 6 or better - For use with a packet driver - (http://www.bgnett.no/~giva/) - (http://groups.yahoo.com/group/watt-32/) - (http://groups.yahoo.com/group/watt-32/files/v2.2/) -) -- bcd 1.03 (inlcude in this package) -- gcc 2.95.2 is recommended -- nasm 0.98 (or better) (http://nasm.sourceforge.net/) - -compile: -make -make WATTCP=1 (to make a Wattcp-32 version) - -debug: -when craching SRB2 will return eip -type make asm, then you will have a 8 megs srb2.s (a assembler file) -the you can find the faulting instruction and function - ------------------------------------------------------------------------- - -Linux/SDL ------ - -need: -- tested with gcc 2.95 and 3.X. -- SDL 1.2 -- SDL_mixer 1.2 -- ibogg and libvorbis (http://Xiph.org/) -- nasm 0.98 (or better)(http://nasm.sourceforge.net/) only with 2.95, else add CC30=1 - -compile -make LINUX=1 - -debug: -gdb ? - ------------------------------------------------------------------------- - -Win32 ------ - -need : -- glide 3.x sdk (optional) (http://www.3dfx.com) -- directx6 sdk (or higher) (http://www.micosoft.com/directx) -- nasm 0.98 (or better) (http://nasm.sourceforge.net/) -- use src\win32\wLegacy.dsp -- VC6 should also work with VC5, and VS.NET 200X - -debug: -press on "step over" with the release version (there is some debug info -on it). Then change the eip in the regster window when you will type -enter the edi will go to the faulting instruction. don't forget that -you can follow the stack for calls. -You can also use trace with the debug version but add -win and -nomouse. - ------------------------------------------------------------------------- - -Win32/minGW/SDL ------ - -need: -- tested with gcc 2.95 and 3.X. -- can also use Dev-C++ 5.0 beta 9 (4.9.9.0) from http://www.bloodshed.net/dev/devcpp.html -- SDL 1.2 -- SDL_mixer 1.2 - -compile -make minGW=1 SDL=1 -or use src\SDL\Win32SDL.dev with Dev-C++ 4.9.9.0 or later - -debug: -gdb ? - ------------------------------------------------------------------------- - -WinCE/SDL WIP ------ - -need: -- ActiveSync 3.8 - http://www.microsoft.com/windowsmobile/downloads/activesync38.mspx - -- ActiveSync 3.7.1, if 3.8 isn't available for your language - http://www.microsoft.com/windowsmobile/downloads/activesync37.mspx - -- eMbedded Visual Tools 3.0 - 2002 Edition - http://www.microsoft.com/downloads/details.aspx?FamilyID=f663bf48-31ee-4cbe-aac5-0affd5fb27dd - -- Pocket PC 2000 SDK - http://www.microsoft.com/downloads/details.aspx?FamilyID=bb3f4d7b-de2a-4e1a-a175-26a68c301ac4 - -- Pocket PC 2002 SDK (eMVT 3.0 2002 Ed. comes with this) - http://www.microsoft.com/downloads/details.aspx?FamilyID=2dbee84a-bd94-4167-b817-2b2e548b2e92 - -- Pocket PC 2002 SDK Emulator Images (eMVT 3.0 2002 Ed. comes with this) - http://www.microsoft.com/downloads/details.aspx?FamilyID=25f4de97-ae80-477a-9df1-496b85b3d3e3 - -- eMbedded Visual C++ 4.0 - http://www.microsoft.com/downloads/details.aspx?familyid=1DACDB3D-50D1-41B2-A107-FA75AE960856 - -- eMbedded Visual C++ 4.0 SP3 (Win CE 4.0-4.2) - http://www.microsoft.com/downloads/details.aspx?FamilyID=5bb36f3e-5b3d-419a-9610-2fe53815ae3b - - OR - -- eMbedded Visual C++ 4.0 SP4 (No SH3 support,Win CE 4.0-5.0 support) - http://www.microsoft.com/downloads/details.aspx?FamilyID=4a4ed1f4-91d3-4dbe-986e-a812984318e5 - -- eMbedded Visual C++ 4.0 Update 5625 (SP4 only) - http://www.microsoft.com/downloads/details.aspx?FamilyID=aa282a6d-6f57-436d-8c10-0ec02d94f5b1 - -- Windows CE: Standard Software Development Kit - http://www.microsoft.com/downloads/details.aspx?familyid=a08f6991-16b0-4019-a174-0c40e6d25fe7 - -- SDK for Windows Mobile 2003-based Pocket PCs - http://www.microsoft.com/downloads/details.aspx?FamilyId=9996B314-0364-4623-9EDE-0B5FBB133652 - -- Emulator Images for Windows Mobile 2003 Second Edition software for Pocket PC - http://www.microsoft.com/downloads/details.aspx?familyid=5C53E3B5-F2A2-47D7-A41D-825FD68EBB6C - -- Microsoft Device Emulator 1.0 Community Preview - http://beta.microsoft.com Use Guest ID "MSDEVICE" to access the Community Preview website - -- Windows CE Utilities for Visual Studio .NET 2003 Add-on Pack 1.1 - (if you also have VS 2003 installed, you need this to install Win CE 5.0 SDK, else no need) - http://www.microsoft.com/downloads/details.aspx?FamilyId=7EC99CA6-2095-4086-B0CC-7C6C39B28762 - -- Windows CE 5.0: Standard Software Development Kit (eMC++ 4 SP4 only) - http://www.microsoft.com/downloads/details.aspx?FamilyID=fa1a3d66-3f61-4ddc-9510-ae450e2318c3 - -- SDL 1.27 (use patch and zip in tools\SDL1.2.7_CE) - -compile -use src\SDL\WinCE\SRB2CE.vcw - -debug: -? - - -2. Explanation of the code -========================== - - 2.1 The memory model (original) (z_zone.c) (by BP) - -------------------- - - SRB2 allocate a heap of 6/32/48 megs at begining and provide a Z_Malloc function - to allocate in this heap. - - Z_Malloc( int size,int tag,void* user ) - - size is the size in byte - tag can be : PU_STATIC allocated static (like malloc do) - call Z_Free to free it - PU_LEVEL same as static but the zone is "tagged" with the - tag PU_LEVEL, when calling - Z_FreeTag (PU_LEVEL, PU_LEVEL) all zone tagged - with PU_LEVEL are freed (at the end of the level) - PU_CACHE this one _can_ be freed automatiquely by one other - call to Z_Malloc. the *user point to a pointer - to this zone so when freed automatiquely the - pointer is set to NULL so eatch time you use it - you must check if the pointer is not NULL and - reload it. - - (...) - - 2.2 Hardware Texture model (by BP) - -------------------------- - - Eatch texture/patch/flats/pic in SRB2 are converted to hardware texture at - runtime (the GlideMipmap_s structure (hw_data.h)). I will call hardware - texture a gr_texture so there is no confusion. - - To remind you : - - Texture are set of patch and are associate to linedefs (walls) can be - upper, lower or middle texture. It can have hole on it. - - patch are sprites (the doom patch are run of vertical lines) - - flats are used for floors and ceiling of sectors and have size of 64x64 - it can't have hole on it - - pic are new legacy format for picture, it can only handle plain texture - like flats it is now used for hud in full screen for the main picture - of legacy and for coronas (the format was extended to handle 32 bit color - or intensity + alpha, not all are implemented at this time) - - Since patch, flat and pic are basic structure represented by only one lump in - the wad, the wad loader allocate for eatch lump a GlideMipmap_s (cache3Dfx) - and init data field to NULL. Since the data structure is allocated in - PU_3DFXCACHE (like PU_CACHE) the data will be initilised when needed - (hw_cache.c). - - The GlideMipmap_s structures for textures are initialized on - HWR_PrepLevelCache (hw_cache.c) it is called in P_SetupLevel (load level) - the number of textures is computed with TEXTURE1, TEXTURE2 lumps since this - can be changed in runtime in SRB2 (load a wad while runing) it must be - reallocated. Well, at this time it is realloceted at eatch level start. We - can do better, since numtextures change only when a wad is loaded. - - The 3dfx driver use glide3, it load gr_texture in gr_texture memory of the - card in fifo order when there is no more place it remove the first gr_texture, - the downloaded field of GlideMipmap_s go to false and when needed it is - reloaded in gr_texture memory. In OpenGl, since OpenGl keep texture in there - own memory and handle gr_texture memory of the card we no more need to - redownload it but if we not free time to time gr_texture memory in opengl, - it will get alot of memory, so the gr_texture memory is cleared at eatch - new level (same time of texture reallocation). Opengl and 3dfx link the - loaded gr_texture with the nextmipmap field of GlideMipmap_s so before clear - textures of the heap we MUST free gr_texture memory of OpenGl or 3dfx ! - - SRB2 can also draw patch with a differant colormap (thanks to Hurdler). - When needed it create the same gr_texture but just with a differant colormap. - This one is linked with the original in the GlideMipmap_s with the - nextcolormap field. - - So when a polygone with a gr_texture must be drawn, first we check if the - gr_textures is not allready loaded in hadware memory (downloaded field) if - not then we check if gr_texture data is there (not grabbed by z_malloc - function) if not we must recompute it eatch type of gr_texture (texture, - patch, flat, pic have there own methode) the we can send the gr_texture - to 3dfx or OpenGl. diff --git a/doc/specials.html b/doc/specials.html deleted file mode 100644 index 2cc840632e4a32264dc0b089ab76fb8647683c38..0000000000000000000000000000000000000000 --- a/doc/specials.html +++ /dev/null @@ -1,1992 +0,0 @@ -<html> - -<head> -<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> -<title>Sonic Robo Blast II - Specials Reference Document</title> -</head> - -<body bgcolor="white" text="black" link="blue" vlink="blue" alink="blue"> - -<h1><big>SRB2 Specials Reference Document</big></h1> - -<p><i>Last updated May 27, 2008</i></p> - -<p><i>For v1.1 Private Beta</i></p> - -<p>This is the SRB2 Specials Reference Document. It is designed to be the ultimate -reference for effects used in SRB2. As such, it is rather technical in areas and quite -concise, and is not something a beginner with level design should be dealing with.</p> - -<h1><a name="things"></a>Thing Types</h1> - -<p>In general, thing bitsets have 4 flags and 3 digits for their height. The bitset is -0xAAAB, where AAA is the object's height above ground, and B are the Easy, Normal, Hard, -and Deaf flags. To get the bitset on a normal object, multiply the height desired by 16, -and then add the existant B. Some objects use 32 as this number, and they will be noted. -Objects that multiply by 16 can be placed up to 4095 units in the air, while objects that -multiply by 32 can be placed up to 2047 units in the air. - -<ul> - <li><u><big><big>Player Starts</big></big></u><ol> - <h3><a name="t1"></a>1 - Player 01 Start</h3> - <p>This is the start for the first player in single player mode, cooperative mode, or race - mode. This start must be placed on every map, as it is what the game defaults to if the - start it is attempting to find isn't there. If there is no Player 1 Start on the map, and - the game is confused over where to spawn the player, the game will crash outright.</p> - <p>The Deaf tag will make the player spawn from the ceiling, and the object needs to be - multiplied by 32 to give height, not 16.</p> - <h3><a name="t2"></a>2 - Player 02 Start</h3> - <p>This is the start for the second player in cooperative and race mode.</p> - <p>The Deaf tag will make the player spawn from the ceiling, and the object needs to be - multiplied by 32 to give height, not 16.</p> - <h3><a name="t3"></a>3 - Player 03 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t4"></a>4 - Player 04 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t5"></a>5 - Player 05 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t6"></a>6 - Player 06 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t7"></a>7 - Player 07 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t8"></a>8 - Player 08 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t9"></a>9 - Player 09 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t10"></a>10 - Player 10 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t11"></a>11 - Player 11 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t12"></a>12 - Player 12 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t13"></a>13 - Player 13 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t14"></a>14 - Player 14 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t15"></a>15 - Player 15 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t16"></a>16 - Player 16 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t17"></a>17 - Player 17 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t18"></a>18 - Player 18 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t19"></a>19 - Player 19 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t20"></a>20 - Player 20 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t21"></a>21 - Player 21 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t22"></a>22 - Player 22 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t23"></a>23 - Player 23 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t24"></a>24 - Player 24 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t25"></a>25 - Player 25 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t26"></a>26 - Player 26 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t27"></a>27 - Player 27 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t28"></a>28 - Player 28 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t29"></a>29 - Player 29 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t30"></a>30 - Player 30 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t31"></a>31 - Player 31 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t32"></a>32 - Player 32 Start</h3> - <p>See Thing <a href="#t2">2</a> for more information.</p> - <h3><a name="t33"></a>33 - Player Match Start</h3> - <p>This is the start for players in Match and Chaos modes. They should also be placed in - Capture the Flag maps as well. There should be 32 of these in a map to assure proper - randomization. While it's unelegant, they can be stacked on top of each other without - negative effect.</p> - <p>The Deaf tag will make the player spawn from the ceiling, and the object needs to be - multiplied by 32 to give height, not 16.</p> - <h3><a name="t34"></a>34 - CTF Team Start (Red)</h3> - <p>This is the start for players on the red team in Capture the Flag mode. There should be - 32 of these in a map to assure proper randomization. While it's unelegant, they can be - stacked on top of each other without negative effect.</p> - <p>The Deaf tag will make the player spawn from the ceiling, and the object needs to be - multiplied by 32 to give height, not 16.</p> - <h3><a name="t35"></a>35 - CTF Team Start (Blue)</h3> - <p>This is the start for players on the blue team in Capture the Flag mode. There should - be 32 of these in a map to assure proper randomization. While it's unelegant, they can be - stacked on top of each other without negative effect.</p> - <p>The Deaf tag will make the player spawn from the ceiling, and the object needs to be - multiplied by 32 to give height, not 16.</p> - <p> </p> - </ol> - </li> - <li><u><big><big>Enemies</big></big></u><ol> - <h3><a name="t100"></a>100 - Crawla (Blue)</h3> - <p>These are the blue ground enemies found in the one player stages. They can't move off - of cliffs and are exceedingly slow.</p> - <h3><a name="t101"></a>101 - Crawla (Red)</h3> - <p>These are the red ground enemies found in the one player stages. They can't move off - cliffs and are relatively slow.</p> - <h3><a name="t102"></a>102 - Stupid Dumb Unnamed RoboFish (tm)</h3> - <p>This is the little fish in Greenflower Zone. The angle determines the jump height, with - 0 being the old jump style. Note that the jump height is based on force, not units, so - experimentation will be necessary to get the correct height.</p> - <h3><a name="t103"></a>103 - Yellow Buzz</h3> - <p>This enemy flies at a moderate speed directly at the player.</p> - <h3><a name="t104"></a>104 - Red Buzz</h3> - <p>This enemy flies at a relatively high speed directly at the player.</p> - <h3><a name="t105"></a>105 - Jetty-Syn Bomber</h3> - <p>This is a highly mobile flying enemy with a bomb that it drops on the player from - directly above. It is considered highly difficult to kill, and should only be used in - situations where the stage is supposed to be difficult.</p> - <h3><a name="t106"></a>106 - Jetty-Syn Gunner</h3> - <p>This is a highly mobile flying enemy with a gun that it fires at the player with high - accuracy. It is considered highly difficult to kill, and should only be used in situations - where the stage is supposed to be difficult.</p> - <h3><a name="t107"></a>107 - Crawla Commander</h3> - <p>This is the grey floating enemy in the opening room of Techno Hill Zone Act 2. It is - quite fast and will start bouncing after taking the first hit. It is significantly - challenging, although a spindash will kill it given time.</p> - <h3><a name="t108"></a>108 - Deton</h3> - <p>This is the red spherical enemy in Techno Hill Zone Act 2. Upon seeing the player, it - makes a mad dash straight for them. With the exception of the <a href="#t404">Armageddon - Shield</a>, Detons are invincible, and must be avoided by running behind a wall or another - enemy.</p> - <h3><a name="t109"></a>109 - Skim</h3> - <p>This is an enemy that floats on the surface of the water, dropping bombs into the water - below. It is not currently used in any of the Single Player stages, but it is fully - operational. The designer does not have to put them on the surface of the water, they know - where it is.</p> - <h3><a name="t110"></a>110 - THZ Turret</h3> - <p>This is the turret from Techno Hill Zone Act 2. It fires large bursts of laser fire at - the player with high accuracy. It is invincible unless it is somehow dipped into water.</p> - <h3><a name="t111"></a>111 - Popup Turret</h3> - <p>This is a small turret that pops up now and then and shoots. The object's angle is a - value defining the delay between shooting.</p> - <h3><a name="t112"></a>112 - Sharp</h3> - <p>This is a blue enemy with spikes on top if it. It starts off by slowly chasing the player, - then it fades to red and runs after the player, and is invincible until it fades back to red.</p> - <h3><a name="t113"></a>113 � Jet Jaw</h3> - <p>This is an underwater enemy that tries to bite at the player, which can be found in - Deep Sea Zone.</p> - <h3><a name="t114"></a>114 � Snailer</h3> - <p>This is an incomplete enemy.</p> - <h3><a name="t115"></a>115 � Bird Aircraft Strike Hazard (B.A.S.H.)</h3> - <p>This is the red vulture-like enemy in Arid Canyon Zone. If it sees a player, it lifts off and - charges at him. Collision with a wall will send it plummeting.</p> - <h3><a name="t116"></a>116 � Pointy</h3> - <p>This is the orbinaut enemy that has spikes circling around it. None of the single player stages - currently use him. You have to place him in a map by using a WAD editor, he can't be placed using - objectplace.</p> - <h3><a name="t117"></a>117 � Robo-Hood</h3> - <p>This is the green enemy from Castle Eggman Zone, which shoots arrows at the player.</p> - <h3><a name="t118"></a>118 � CastleBot FaceStabber</h3> - <p>This is the large grey enemy from Castle Eggman Zone. It slowly trudges towards the player, - and if the player in range, lunges at them with his sword.</p> - <h3><a name="t119"></a>119 � Egg Guard</h3> - <p>This is the enemy from Castle Eggman Zone that wields a protective shield.</p> - <h3><a name="t120"></a>120 � Green Snapper</h3> - <p>This is the green turtle enemy from Arid Canyon Zone. This enemy behaves exactly like a blue - crawla does. The circumference of its shell is covered with spikes, so the only way to destroy it - is by jumping on top of it.</p> - <h3><a name="t121"></a>121 � Minus</h3> - <p>This is the digging enemy from Arid Canyon Zone. It burrows underground towards the player, and - once it's directly underneath, it bursts out from under the ground, jumping up and hurting the player.</p> - <p> </p> - </ol> - </li> - <li><u><big><big>Bosses and their associated items (if any)</big></big></u><ol> - <h3><a name="t200"></a>200 - Egg Mobile (Boss 1)</h3> - <p>The boss of Greenflower Zone and Castle Eggman Zone. He moves around firing at the - player, and after taking six hits, he dashes at the player.</p> - <p>Giving the boss the Deaf flag will make him have spikeballs, like CEZ3, and giving him - the Multi flag will make the level end when he is dead. To place him above ground, - multiply by 32 to give height, not 16.</p> - <h3><a name="t201"></a>201 - Egg Slimer (Boss 2)</h3> - <p>This is the boss of Techno Hill Zone. It requires an axis point at the center to - function, and it goes in a circle around the axis point dropping slime. After 6 hits, he - stops going in a circle, and bouncing at the player, spewing a lot more slime.</p> - <p>The Multi flag will make the level end when he is dead.</p> - <h3><a name="t201"></a>202 - Sea Egg (Boss 3)</h3> - <p>This is the boss of Deep Sea Zone. More information will be supplied later.</p> - <p>The Multi flag will make the level end when he is dead.</p> - <h3>203 - Eggscalibur (Boss 4)</h3> - <p>This is the boss of Castle Eggman Zone. More information will be supplied later.</p> - <p>The Multi flag will make the level end when he is dead.</p> - <h3><a name="t290"></a>290 - Boss Flypoint</h3> - <p>This is the location the boss will fly to after being killed.</p> - <h3><a name="t291"></a>291 - Egg Capsule Center</h3> - <p> </p> - </ol> - </li> - <li><u><big><big>Collectibles</big></big></u><ol> - <h3><a name="t300"></a>300 - Ring</h3> - <p>This is a normal ring. Pick this up to get one ring.</p> - <p>Giving the deaf tag to a ring will cause it to float 31 units above the ground. This - does stack with bitsets, allowing rings to be a total of 4127 units above the ground at - maximum.</p> - <h3><a name="t301"></a>301 - Bounce Ring</h3> - <p>Picking this up gives you more ammo for this particular ring weapon. You cannot fire - the weapon, however, if you do not have the associated panel. - <h3><a name="t302"></a>302 - Rail Ring</h3> - <p>See thing <a href="#t301">#301</a>.</p> - <h3><a name="t304"></a>304 - Automatic Ring</h3> - <p>See thing <a href="#t301">#301</a>.</p> - <h3><a name="t305"></a>305 - Explosion Ring</h3> - <p>See thing <a href="#t301">#301</a>.</p> - <h3><a name="t305"></a>306 - Scatter Ring</h3> - <p>See thing <a href="#t301">#301</a>.</p> - <h3><a name="t305"></a>307 - Grenade Ring</h3> - <p>See thing <a href="#t301">#301</a>.</p> - <h3>310 - CTF Flag (Red)</h3> - <p>This is the red team's flag in capture the flag mode. If the blue team takes this to - their team base (sector type <a href="#s16384">16384</a>), they score a point.</p> - <h3><a name="t307"></a>311 - CTF Flag (Blue)</h3> - <p>This is the blue team's flag in capture the flag mode. If the red team takes this to - their team base (sector type <a href="#s12288">12288</a>), they score a point.</p> - <h3><a name="t308"></a>312 - Special Stage Token</h3> - <p>This token gives the player a chance at the special stage after the current stage has - ended. If more than one token is collected, the player gets that many chances at the - special stages, continuing until they run out of tokens or have all the emeralds.</p> - <h3><a name="t309"></a>313 - Emerald 1 (Green)</h3> - <p>This object gives the player the first emerald as a pickup object, instead of by - completing a special stage.</p> - <h3><a name="t310"></a>314 - Emerald 2 (Orange)</h3> - <p>This object gives the player the second emerald as a pickup object, instead of by - completing a special stage.</p> - <h3><a name="t311"></a>315 - Emerald 3 (Pink)</h3> - <p>This object gives the player the third emerald as a pickup object, instead of by - completing a special stage.</p> - <h3><a name="t312"></a>316 - Emerald 4 (Blue)</h3> - <p>This object gives the player the fourth emerald as a pickup object, instead of by - completing a special stage.</p> - <h3><a name="t313"></a>317 - Emerald 5 (Red)</h3> - <p>This object gives the player the fifth emerald as a pickup object, instead of by - completing a special stage.</p> - <h3><a name="t314"></a>318 - Emerald 6 (Light Blue)</h3> - <p>This object gives the player the sixth emerald as a pickup object, instead of by - completing a special stage.</p> - <h3><a name="t315"></a>319 - Emerald 7 (Grey)</h3> - <p>This object gives the player the seventh emerald as a pickup object, instead of by - completing a special stage.</p> - <h3><a name="t316"></a>320 - Emerald Hunt Location</h3> - <p>This is one of the three emeralds to be used in Hunting mode.</p> - <h3>323 - Emerald Spawn</h3> - <p>Spawn location for emeralds in Match mode.</p> - <h3><a name="t330"></a>330 - Bounce Ring Panel</h3> - <p>This is a match weapon panel. The Bounce Ring throws a slow ring that will bounce when - it hits walls.</p> - <p>Giving the deaf tag to a panel will cause it to float 31 units above the ground. This - does stack with bitsets, allowing panels to be a total of 4127 units above the ground at - maximum.</p> - <h3><a name="t331"></a>331 - Rail Ring Panel</h3> - <p>This is a match weapon panel. The Rail Ring gives the player an instantaneous shot, that - strikes its target the instant its fired, however there is a long downtime between shots. - Being shot by a rail ring causes more kickback than normal.</p> - <p>Giving the deaf tag to a panel will cause it to float 31 units above the ground. This - does stack with bitsets, allowing panels to be a total of 4127 units above the ground at - maximum.</p> - <h3><a name="t332"></a>332 - Automatic Ring Panel</h3> - <p>This is a match weapon panel. The Automatic Ring gives the player a fire rate of 17.5 - rings per second.</p> - <p>Giving the deaf tag to a panel will cause it to float 31 units above the ground. This - does stack with bitsets, allowing panels to be a total of 4127 units above the ground at - maximum.</p> - <h3><a name="t333"></a>333 - Explosion Ring Panel</h3> - <p>This is a match weapon panel. The Explosion Ring throws a slow ring that explodes into - many fragments upon striking a wall or another player. Being struck directly by the - Explosion Ring causes more kickback than usual.</p> - <p>Giving the deaf tag to a panel will cause it to float 31 units above the ground. This - does stack with bitsets, allowing panels to be a total of 4127 units above the ground at - maximum.</p> - <h3><a name="t334"></a>334 - Scatter Ring Panel</h3> - <p>This is a match weapon panel. The Scatter Ring throws 5 rings in a plus-shape.</p> - <p>Giving the deaf tag to a panel will cause it to float 31 units above the ground. This - does stack with bitsets, allowing panels to be a total of 4127 units above the ground at - maximum.</p> - <h3><a name="t335"></a>335 - Grenade Ring Panel</h3> - <p>This is a match weapon panel. The Grenade Ring throws a grenade that will explode - if an opposing player gets too close to it. It will also explode automatically after a - while if left untouched.</p> - <p>Giving the deaf tag to a panel will cause it to float 31 units above the ground. This - does stack with bitsets, allowing panels to be a total of 4127 units above the ground at - maximum.</p> - <p> </p> - </ol> - </li> - <li><u><big><big>Boxes</big></big></u><ol> - <h3><a name="t400"></a>400 - Super Ring (10 Rings)</h3> - <p>This monitor gives the player ten rings.</p> - <p>If monitors are given the Deaf tag, they will respawn as a random monitor type (not a ? - monitor) from the weighted table in modes that support respawn. Elsewise, they will - respawn as the same monitor.</p> - <h3><a name="t402"></a>402 - Attraction Shield</h3> - <p>Also known as the yellow shield and god shield, this shield protects the player from a - single hit, then disappears. It also attracts all normal rings, spilled or on the map to - the player with the shield. It also protects the player from electric damage.</p> - <p>If monitors are given the Deaf tag, they will respawn as a random monitor type (not a ? - monitor) from the weighted table in modes that support respawn. Elsewise, they will - respawn as the same monitor.</p> - <h3><a name="t403"></a>403 - Force Shield</h3> - <p>Also known as the blue shield, this shield protects the player from two hits, then - disappears. If the spin button is pressed while jumping, it is also possible to - reflect many projectiles.</p> - <p>If monitors are given the Deaf tag, they will respawn as a random monitor type (not a ? - monitor) from the weighted table in modes that support respawn. Elsewise, they will - respawn as the same monitor.</p> - <h3><a name="t404"></a>404 - Armageddon Shield</h3> - <p>Also known as the black shield, this shield protects the player from a single hit, - triggering upon a hit. The shield can also be triggered by jumping, and then hitting the - spin key in midair. When the shield is triggered, a flash of light damages everything - within a large radius, destroying the shield in the process.</p> - <p>If monitors are given the Deaf tag, they will respawn as a random monitor type (not a ? - monitor) from the weighted table in modes that support respawn. Elsewise, they will - respawn as the same monitor.</p> - <h3><a name="t405"></a>405 - Whirlwind Shield</h3> - <p>This shield protects the player from a single hit, then disappears. If the player does - a jump-spin, they will do a second jump in midair, making the maximum height that the - player can jump with the shield 224.</p> - <p>Versions of SRB2 previous to 1.09 had the Basic Shield in this object number, so make - sure to note that if the player loads the map in an older version, that is what they will - see.</p> - <p>If monitors are given the Deaf tag, they will respawn as a random monitor type (not a ? - monitor) from the weighted table in modes that support respawn. Elsewise, they will - respawn as the same monitor.</p> - <h3><a name="t406"></a>406 - Elemental Shield</h3> - <p>Also known as the green shield, this shield protects the player from a single - hit, then disappears. While this shield is active, the player cannot drown. It also - protects the player from water, fire, and other damage. When the player with this shield - spin-dashes, it leaves a trail of fire, which deals fire damage to any enemy that touches - it.</p> - <p>If monitors are given the Deaf tag, they will respawn as a random monitor type (not a ? - monitor) from the weighted table in modes that support respawn. Elsewise, they will - respawn as the same monitor.</p> - <h3><a name="t407"></a>407 - Super Sneakers</h3> - <p>This is a monitor powerup that gives the player about 2x running speed for 20 seconds.</p> - <h3><a name="t408"></a>408 - Invincibility</h3> - <p>This is a monitor powerup that prevents all damage to the player for 20 seconds.</p> - <h3><a name="t409"></a>409 - Extra Life</h3> - <p>This powerup monitor features the player's face, and provides an extra life when - struck.</p> - <p>If monitors are given the Deaf tag, they will respawn as a random monitor type (not a ? - monitor) from the weighted table in modes that support respawn. Elsewise, they will - respawn as the same monitor.</p> - <h3><a name="t410"></a>410 - Eggman</h3> - <p>This monitor damages the player if they strike it.</p> - <p>If monitors are given the Deaf tag, they will respawn as a random monitor type (not a ? - monitor) from the weighted table in modes that support respawn. Elsewise, they will - respawn as the same monitor.</p> - <h3><a name="t411"></a>411 - Teleporter</h3> - <p>This monitor mixes up all locations of players, teleporting them to the location of a - random other player. It has no effect in Single Player or in multiplayer modes while only - one player is in the game.</p> - <p>If monitors are given the Deaf tag, they will respawn as a random monitor type (not a ? - monitor) from the weighted table in modes that support respawn. Elsewise, they will - respawn as the same monitor.</p> - <h3><a name="t412"></a>412 - Random Box</h3> - <p>Destroy this monitor and you will get a random powerup, like the boxes in Sonic 2 race - mode.</p> - <h3><a name="t412"></a>413 - Gravity Boots Box</h3> - <p>Destroy this monitor and the gravity will be flipped for a short time.</p> - <p> </p> - </ol> - </li> - <li><u><big><big>Interactive Objects (friendly or otherwise)</big></big></u><ol> - <h3><a name="t500"></a>500 - Air Bubble Patch</h3> - <p>This is the air bubble patch used underwater to give players air. It spawns big bubbles - randomly which replenish the player's air.</p> - <h3><a name="t501"></a>501 - End Level Sign</h3> - <p>This is the sign at the end of the stage. When the player enters the <a href="#s8192">Exit - Sector</a>, this sign will start to spin, and end on the face of the player. This sign - does not make the stage end, it's just a visual effect for it.</p> - <h3><a name="t502"></a>502 - Star Post</h3> - <p>Star Posts allow the player to respawn after dying at a point other than the beginning - of the stage. There can be up to 32 Star Posts in a map, and they work with the bitsets.</p> - <p>Instead of controlling the difficulty and deaf flags, the final digit of the bitset - determines the number of the Star Post. 0x0000 is the first one and 0x000f is the - sixteenth one. Note that since this overwrites all of the difficulty flags, they will - appear in all difficulties, even though 0x0000 would normally mean it wouldn't appear in - any difficulty level.</p> - <h3><a name="t520"></a>520 - Spikeball</h3> - <p>Just like thing <a href="#t521">521</a>, except they do normal damage to the player on - contact. </p> - <h3><a name="t521"></a>521 - Spikeball (Special Stage)</h3> - <p>These are the spikeballs used in the special stages. They harm the player for damage on - contact, but only if they are carrying rings.</p> - <h3><a name="t522"></a>522 - Ceiling Spike</h3> - <p>This is a downward pointing spike for use on the ceiling. Touching the pointy end of - the spike deals damage to the player.</p> - <p>By default, it attaches itself to the ceiling, and the height part of the bitset - measures how far down from the ceiling, instead of up from the floor.</p> - <h3><a name="t523"></a>523 - Floor Spike</h3> - <p>This is a upward pointing spike for use on the floor. Touching the pointy end of the - spike deals damage to the player.</p> - <h3><a name="t524"></a>524 - Big Floating Mine</h3> - <p>When you get close, this mine will start to follow you. Touches you, and it explodes.</p> - <h3><a name="t540"></a>540 - THZ Fan</h3> - <p>This is the fan used inside the secret passage in Techno Hill Zone Act 1. It pushes the - player slowly up until it reaches the maximum height it can. The maximum height is - determined by the angle, measured in normal fracunits (It can go above 360 just fine).</p> - <h3><a name="t541"></a>541 - THZ Gas Jet</h3> - <p>This is the gas jet used at the end of Techno Hill Zone Act 1. It launches the player - straight up on regular intervals about the same height as a yellow spring pointing up.</p> - <h3><a name="t550"></a>550 - Yellow Spring (Up)</h3> - <p>This is a yellow spring pointing straight up. It has a medium amount of force behind - it.</p> - <h3><a name="t551"></a>551 - Red Spring (Up)</h3> - <p>This is a red spring pointing straight up. It has a large amount of force behind it.</p> - <h3><a name="t552"></a>552 - Blue Spring</h3> - <p>This is a blue spring pointing straight up. It has a small amount of force behind it. - The intent is for this spring to be used underwater. It has about the same effect - underwater as a yellow spring does above water.</p> - <h3><a name="t553"></a>553 - Yellow Spring (Down)</h3> - <p>This is a yellow spring pointing straight down. It has a medium amount of force behind - it.</p> - <h3><a name="t554"></a>554 - Red Spring (Down)</h3> - <p>This is a red spring pointing straight down. It has a large amount of force behind it.</p> - <h3><a name="t555"></a>555 - Yellow Spring (Diagonal Up)</h3> - <p>This is a yellow spring pointing upwards and in the direction the thing is facing. It - has a medium amount of force behind it. When the player touches this spring, he will - automatically turn to face the direction the spring is launching the player.</p> - <h3><a name="t556"></a>556 - Red Spring (Diagonal Up)</h3> - <p>This is a red spring pointing upwards and in the direction the thing is facing. It has - a large amount of force behind it. When the player touches this spring, he will - automatically turn to face the direction the spring is launching the player.</p> - <h3><a name="t557"></a>557 - Yellow Spring (Diagonal Down)</h3> - <p>This is a yellow spring pointing downwards and in the direction the thing is facing. It - has a medium amount of force behind it. When the player touches this spring, he will - automatically turn to face the direction the spring is launching the player.</p> - <h3><a name="t558"></a>558 - Red Spring (Diagonal Down)</h3> - <p>This is a red spring pointing downward and in the direction the thing is facing. It has - a large amount of force behind it. When the player touches this spring, he will - automatically turn to face the direction the spring is launching the player.</p> - <p> </p> - </ol> - </li> - <li><u><big><big>Special placement patterns</big></big></u><ol> - <h3><a name="t600"></a>600 - 5 Vertical Rings (Yellow Spring)</h3> - <p>This is a chain of five rings intended to be used with thing <a href="#t550">550</a>. - Do not use ring chain objects in any mode where items respawn, because ring chains do not - respawn. Use bitsets to create chains in any mode with item respawn.</p> - <h3><a name="t601"></a>601 - 5 Vertical Rings (Red Spring)</h3> - <p>This is a chain of five rings intended to be used with thing <a href="#t551">551</a>. - Do not use ring chain objects in any mode where items respawn, because ring chains do not - respawn. Use bitsets to create chains in any mode with item respawn.</p> - <h3><a name="t602"></a>602 - 5 Diagonal Rings (Yellow Spring)</h3> - <p>This is a chain of five rings intended to be used with thing <a href="#t555">555</a>. - Do not use ring chain objects in any mode where items respawn, because ring chains do not - respawn. Use bitsets to create chains in any mode with item respawn.</p> - <h3><a name="t603"></a>603 - 10 Diagonal Rings (Red Spring)</h3> - <p>This is a chain of ten rings intended to be used with thing <a href="#t556">556</a>. Do - not use ring chain objects in any mode where items respawn, because ring chains do not - respawn. Use bitsets to create chains in any mode with item respawn.</p> - <h3><a name="t604"></a>604 - Nights: Circle of Rings</h3> - <h3><a name="t605"></a>605 - Nights: Circle of Rings (Big)</h3> - <h3><a name="t606"></a>606 - Nights: Circle of Wing Logos</h3> - <h3><a name="t607"></a>607 - Nights: Circle of Wing Logos (Big)</h3> - <h3><a name="t608"></a>608 - Nights: Circle of Rings and Wings</h3> - <h3><a name="t609"></a>609 - Nights: Circle of Rings and Wings (Big)</h3> - <p> </p> - </ol> - </li> - <li><u><big><big>Powerup indicators/environmental effects/miscellany</big></big></u><ol> - <h3><a name="t700"></a>700 - Ambient Water SFX 1A (Small)</h3> - <h3><a name="t701"></a>701 - Ambient Water SFX 1B (Small)</h3> - <h3><a name="t702"></a>702 - Ambient Water SFX 2A (Medium)</h3> - <h3><a name="t703"></a>703 - Ambient Water SFX 2B (Medium)</h3> - <h3><a name="t704"></a>704 - Ambient Water SFX 3A (Large)</h3> - <h3><a name="t705"></a>705 - Ambient Water SFX 3B (Large)</h3> - <h3><a name="t706"></a>706 - Ambient Water SFX 4A (Extra Large)</h3> - <h3><a name="t707"></a>707 - Ambient Water SFX 4B (Extra Large)</h3> - <h3><a name="t708"></a>708 - Random Ambience 1</h3> - <h3><a name="t709"></a>709 - Random Ambience 2</h3> - <h3><a name="t750"></a>750 - Chaos Mode Enemy Spawn</h3> - <p>This is where the enemies spawn from in Chaos mode. There should be around 12 of these - points on a map with Chaos support.</p> - <h3><a name="t751"></a>751 - Teleport Destination</h3> - <p>This is the thing to be used with linedef type <a href="#l412">412</a>, the linedef - executor that teleports a player. This thing is where the player will spawn in the tagged - sector.</p> - <h3><a name="t752"></a>752 - Alternate View Point</h3> - <p>This is the thing to be used with linedef type <a href="#l422">422</a>, the linedef - executor that changes the camera view. This thing is where the camera will be moved to in - the tagged sector.</p> - <h3><a name="t753"></a>753 - Zoom Tube Waypoint</h3> - <p>Waypoints for zoom tubes. Think of Sonic 2's Metropolis Zone, Sonic 3 & Knuckles's - Death Egg Zone, and Lava Reef Zone. The lower byte of the ANGLE field specifies the - waypoint's number in the sequence, and the upper byte specifies the sequence that the - waypoint belongs to. These are used in conjunction with sector type <a href="#s32768">32768</a> - and <a href="#s36864">36864</a>.</p> - <h3><a name="t754"></a>754 - Push</h3> - <h3><a name="t755"></a>755 - Pull</h3> - <h3><a name="t756"></a>756 - Street Light Source</h3> - <p>This produces a light in OpenGL. It is used in Starlit Warehouse Zone, one of the match - stages, as the street lights.</p> - <h3><a name="t760"></a>760 - PolyObject Anchor</h3> - <p>This is the first of the two points used to set up 'how much to move' a polyobject by - when creating it. Angle is the PolyObject ID#.</p> - <h3><a name="t761"></a>761 - PolyObject SpawnPoint</h3> - <p>This is the second of the two points used to set up 'how much to move' a polyobject by - when creating it. Angle is the PolyObject ID#.</p> - <h3><a name="t762"></a>762 - PolyObject SpawnPoint Crush</h3> - <p>This is the second of the two points used to set up 'how much to move' a polyobject by - when creating it. Angle is the PolyObject ID#. This item tells the PolyObject that it - should hurt the player.</p> - <p> </p> - </ol> - </li> - <li><u><big><big>Greenflower Scenery</big></big></u><ol> - <h3><a name="t800"></a>800 - GFZ Flower (Normal)</h3> - <p>This is a scenery object from Greenflower Zone. It is the orange flower seen all - throughout GFZ and most GFZ-themed custom maps.</p> - <h3><a name="t801"></a>801 - GFZ Sunflower</h3> - <p>This is a scenery object from Greenflower Zone. It is the large blue sunflower seen all - throughout GFZ and most GFZ-themed custom maps.</p> - <h3><a name="t802"></a>802 - GFZ Budding Flower</h3> - <p>This is a scenery object from Greenflower Zone. It is the small purple flower seen all - throughout GFZ and most GFZ-themed custom maps.</p> - <h3><a name="t804"></a>804 - Berry Bush</h3> - <p>This is a scenery object from Greenflower Zone. It is the green bush with red berries - seen all throughout GFZ and most GFZ-themed custom maps.</p> - <h3><a name="t805"></a>805 - Bush</h3> - <p>This is a scenery object from Greenflower Zone. It is the green bush without the - berries seen all throughout GFZ and most GFZ-themed custom maps.</p> - <p> </p> - </ol> - </li> - <li><u><big><big>Techno Hill Scenery</big></big></u><ol> - <h3><a name="t900"></a>900 - THZ Flower</h3> - <p>This is a scenery object from Techno Hill Zone Act 1. It is the metallic white flower.</p> - <h3><a name="t901"></a>901 - THZ Alarm</h3> - <p>This is a scenery object from Techno Hill Zone Act 2. It is the little alarm in the - passage with the first Star Post. It creates noise, but the red visual effect in THZ2 was - done with a colormap, not this object.</p> - <p> </p> - </ol> - </li> - <li><u><big><big>Deep Sea Scenery</big></big></u><ol> - <h3><a name="t1000"></a>1000 - Gargoyle</h3> - <p>Pushable gargoyle. Can be stood on top of as well.</p> - <p>Giving this the Deaf tag will prevent it from being pushable.</p> - <h3><a name="t1001"></a>1001 - Seaweed</h3> - <p>Animated seaweed. Intangible scenery.</p> - <h3><a name="t1002"></a>1002 - Dripping Water</h3> - <p>Water dripping from the ceiling. ANGLE value specifies start delay.</p> - <p> </p> - </ol> - </li> - <li><u><big><big>Castle Eggman Scenery</big></big></u><ol> - <h3><a name="t1100"></a>1100 - Hanging Chain</h3> - <p>This is a scenery object from Castle Eggman, a dungeon chain hanging from the ceiling.</p> - <p>By default, it attaches itself to the ceiling, and the height part of the bitset - measures how far down from the ceiling, instead of up from the floor.</p> - <h3><a name="t1101"></a>1101 - CEZ Torch</h3> - <p>This is the torch used in Castle Eggman Zone. It produces light in OpenGL, and it harms - the player for fire damage on contact.</p> - <h3><a name="t1102"></a>1102 - Eggman Statue </h3> - <p>This is the large Eggman statue in Castle Eggman Zone.</p> - <h3><a name="t1103"></a>1103 - CEZ Flower</h3> - <p>This is a scenery object from Castle Eggman Zone. It is the decaying flower.</p> - <p> </p> - </ol> - </li> - <li><u><big><big>Arid Canyon Scenery</big></big></u><ol> - <h3><a name="t1200"></a>1200 � Big Tumbleweed</h3> - <p>A large moveable tumbleweed that rolls along the floor.</p> - <h3><a name="t1201"></a>1201 � Little Tumbleweed</h3> - <p>A small movable tumbleweed that rolls along the floor.</p> - <h3><a name="t1202"></a>1202 � Rock Spawner</h3> - <p>An object which randomly spawns falling rocks, which damage the player on impact.<br> - Description on how to use goes here.</p> - </ol> - </li> - <li><u><big><big>Red Volcano Scenery</big></big></u><ol> - <h3><a name="t1300"></a>1300 � Horizontal Flame Jet</h3> - <p>A stready stream of flames comes out horizontally.</p> - <h3><a name="t1301"></a>1301 � Vertial Flame Jet</h3> - <p>A stready stream of flames comes out vertially.</p> - </ol> - </li> - <li><u><big><big>Dark City Scenery</big></big></u><ol> - </ol> - </li> - <li><u><big><big>Doom Ship Scenery</big></big></u><ol> - </ol> - </li> - <li><u><big><big>Egg Rock / Final Fight Scenery</big></big></u><ol> - </ol> - </li> - <li><u><big><big>NiGHTS Items</big></big></u><ol> - <h3><a name="t1700"></a>1700 - Nights: Axis</h3> - <p>Lower 10 bits: Axis number in the mare (0-based) Upper 6 bits: Mare that axis belongs - to (0-based). ANGLE value determines the size of the axis to rotate around. If 16384 is - added to the ANGLE value, the axis will be inverted.</p> - <h3><a name="t1701"></a>1701 - Nights: Axis Transfer (Normal)</h3> - <h3><a name="t1702"></a>1702 - Nights: Axis Transfer Line</h3> - <h3><a name="t1703"></a>1703 - Nights: Ideya Drone</h3> - <p>Angle value sets the NiGHTS timer, in seconds. </p> - <h3><a name="t1704"></a>1704 - Nights: Bumper</h3> - <p>Lower 4 bits of the flags specify the angle of the bumper in 30 degree increments.</p> - <h3><a name="t1705"></a>1705 - Nights: Hoop</h3> - <h3><a name="t1706"></a>1706 - Nights: Wing Logo</h3> - <h3><a name="t1707"></a>1707 - Nights: Super Loop</h3> - <h3><a name="t1708"></a>1708 - Nights: Drill Refill</h3> - <h3><a name="t1709"></a>1709 - Nights: Helper</h3> - <h3><a name="t1710"></a>1710 - Nights: Egg Capsule</h3> - <p>The capsule you need to collect rings to break in NiGHTS. The value of its ANGLE field - determines how many rings you need to break it. Just like the axis points, the upper bits - (value >> 10) determine the mare it belongs to. For example, an angle value of 1024 - means it belongs to mare 1 (2nd mare, it's zero based), and requires 0 rings to break. - 1030 would be mare 1, and 6 rings to break. 2048 would be mare 2, no rings.</p> - <p> </p> - </ol> - </li> - <li><u><big><big>Mario Items</big></big></u><ol> - <h3><a name="t1800"></a>1800 - Coin</h3> - <p>This is a coin, which is essentially a ring with Mario graphics and sound effects.</p> - <h3><a name="t1801"></a>1801 - Overworld Goomba</h3> - <p>These are the enemies in Mario Koopa Blast 1, and are essentially Crawlas with a Mario - graphic.</p> - <h3><a name="t1802"></a>1802 - Underworld Goomba</h3> - <p>These are the enemies in Mario Koopa Blast 2, and are essentially Crawlas with a Mario - graphic.</p> - <h3><a name="t1803"></a>1803 - Fire Flower</h3> - <p>This is the powerup from the Mario Koopa Blast stages. It changes the player to a white - palette, and allows the player to throw fireballs with the fire button. The fireballs fly - in a Mario-style bounce trajectory until they hit an enemy or a wall.</p> - <h3><a name="t1804"></a>1804 - Koopa Shell</h3> - <p>This is the Koopa Shell in Mario Koopa Blast 1. It will bounce around, striking enemies - and players.</p> - <h3><a name="t1805"></a>1805 - Puma (Mario Jumping Fireball)</h3> - <p>This is the fireball used in Mario Koopa Blast 3. The angle determines the jump height, - with 0 being the old jump style. Note that the jump height is based on force, not units, - so experimentation will be necessary to get the correct height.</p> - <h3><a name="t1806"></a>1806 - King Bowser</h3> - <h3><a name="t1807"></a>1807 - Axe</h3> - <p>The axe used to defeat Bowser in the third Mario level.</p> - <h3><a name="t1808"></a>1808 - Bush (Short)</h3> - <p>This is a scenery object from Mario Koopa Blast</p> - <h3><a name="t1809"></a>1809 - Bush (Tall)</h3> - <p>This is a scenery object from Mario Koopa Blast</p> - <h3><a name="t1810"></a>1810 - Toad</h3> - <p>This is Toad at the end of Mario Koopa Blast 3.</p> - <p> </p> - </ol> - </li> - <li><u><big><big>Xmas Items</big></big></u><ol> - <h3><a name="t1850"></a>1850 - Xmas Pole</h3> - <p>X-Mas scenery object. Looks like a little barber shop pole.</p> - <h3><a name="t1851"></a>1851 - Candy Cane</h3> - <p>X-Mas scenery object. Looks like a candy cane.</p> - <p>Note that Mystic Realm 4 replaces this object with the Sonic 1 palm tree, so any maps - loaded while Mystic Realm 4 is loaded will overwrite the image, making any candy canes - look like palm trees, which can look kinda stupid.</p> - <h3><a name="t1852"></a>1852 - Snowman</h3> - <p>X-Mas scenery object. Pushable snowman with a happy face. Can be stood on top of as - well. Acts the same as thing <a href="#t1000">1000</a>.</p> - <p>Giving this the Deaf tag will prevent it from being pushable.</p> - <p> </p> - </ol> - </li> - <h1><a name="linetypes"></a>Linedef Types</h1> - <p>Lines may have flags applied to them. The following is a reference of their values. - Unless specified otherwise in a line type, the flags behave as follows:</p> - <div align="left"><table border="1" width="83%"> - <tr> - <td width="33%">NAME</td> - <td width="10%">VALUE</td> - <td width="57%">DESCRIPTION</td> - </tr> - <tr> - <td width="33%"><a name="#EFFECT6"></a>EFFECT6</td> - <td width="10%">1</td> - <td width="57%">Special use flag #6.</td> - </tr> - <tr> - <td width="33%"><a name="#BLOCKMONSTERS"></a>BLOCKMONSTERS</td> - <td width="10%">2</td> - <td width="57%">Prevents an enemy from crossing the line. May not work for especially - speedy enemies.</td> - </tr> - <tr> - <td width="33%"><a name="#TWOSIDED"></a>TWOSIDED</td> - <td width="10%">4</td> - <td width="57%">Flag used to indicate if a line is two sided. Do not modify.</td> - </tr> - <tr> - <td width="33%"><a name="#DONTPEGTOP"></a>DONTPEGTOP</td> - <td width="10%">8</td> - <td width="57%">Unpeg upper texture. Good for moving floors.</td> - </tr> - <tr> - <td width="33%"><a name="#DONTPEGBOTTOM"></a>DONTPEGBOTTOM</td> - <td width="10%">16</td> - <td width="57%">Unpeg bottom texture. Good for moving ceilings.</td> - </tr> - <tr> - <td width="33%"><a name="#EFFECT1"></a>EFFECT1</td> - <td width="10%">32</td> - <td width="57%">Special use flag #1.</td> - </tr> - <tr> - <td width="33%"><a name="#NOCLIMB"></a>NOCLIMB</td> - <td width="10%">64</td> - <td width="57%">Don't allow Knuckles to climb on this wall.</td> - </tr> - <tr> - <td width="33%"><a name="#EFFECT2"></a>EFFECT2</td> - <td width="10%">128</td> - <td width="57%">Special use flag #2.</td> - </tr> - <tr> - <td width="33%"><a name="#EFFECT3"></a>EFFECT3</td> - <td width="10%">256</td> - <td width="57%">Special use flag #3.</td> - </tr> - <tr> - <td width="33%"><a name="#EFFECT4"></a>EFFECT4</td> - <td width="10%">512</td> - <td width="57%">Special use flag #4.</td> - </tr> - <tr> - <td width="33%"><a name="#EFFECT5"></a>EFFECT5</td> - <td width="10%">1024</td> - <td width="57%">Special use flag #5.</td> - </tr> - <tr> - <td width="33%"><a name="#NOSONIC"></a>NOSONIC</td> - <td width="10%">2048</td> - <td width="57%">Disable line special if playing as Sonic (Single Player Only).</td> - </tr> - <tr> - <td width="33%"><a name="#NOTAILS"></a>NOTAILS</td> - <td width="10%">4096</td> - <td width="57%">Disable line special if playing as Tails (Single Player Only).</td> - </tr> - <tr> - <td width="33%"><a name="#NOKNUX"></a>NOKNUX</td> - <td width="10%">8192</td> - <td width="57%">Disable line special if playing as Knuckles (Single Player Only).</td> - </tr> - <tr> - <td width="33%"><a name="#BOUNCY"></a>BOUNCY</td> - <td width="10%">16384</td> - <td width="57%">Bounce the player off this line.</td> - </tr> - <tr> - <td width="33%"><a name="#TFERLINE"></a>TFERLINE</td> - <td width="10%">32768</td> - <td width="57%">Use this on a FOF line special to define the texture & offsets for - each side of the FOF. The control sector must have at LEAST the same # of sides as the - target sector(s).</td> - </tr> - </table> - </div><hr> - <li><u><big><big>Level Parameters / Miscellany</big></big></u><ol> - <h3><a name="l1"></a>1 - Per-Sector Gravity</h3> - <p>Sets the gravity of the tagged sector or sectors, as a percentage of global gravity - (which can be set separately using sector type <a href="#s176">176</a>). The floor height - of the control sector is used. If it is 1000, then the target sector will have 100% - gravity. If it is 500, the target sector will have 50% of the global gravity. Negative - values work as well, but players can't jump down; they'll get stuck to the ceiling, unless - the <a href="#NOCLIMB">NOCLIMB</a> flag is checked.</p> - <p>You can apply this special to the control sector of an intangible FOF to change the - gravity only inside that FOF.</p> - <h3><a name="l2"></a>2 - Custom Exit</h3> - <p>Tag this to an Exit Sector (type <a href="#s8192">8192</a>) to exit to a custom level, - overriding the one set in the map header. The map number you go to is indicated by the - front sector's floor. Additionally, if the control linedef's bitset is set to disallow - climbing (with the <a href="#NOCLIMB">NOCLIMB</a> attribute, whose value is 64), skip the - score tally screen when switching to the new map.</p> - <p>If the control linedef has the <a href="#BLOCKMONSTERS">BLOCKMONSTERS</a> flag set, - this effect does something super complicated and fun, going to a different level depending - on whether the player has all emeralds or not. If the player has seven emeralds, the - linedef's front sector's ceiling height will be used. Otherwise, go to the map number - indicated by the linedef's front sector's floor. That's <i>only</i> if you set the <a - href="#BLOCKMONSTERS">BLOCKMONSTERS</a> flag.</p> - <p>If the <a href="#EFFECT4">EFFECT4</a> flag is set, the linedef's front side x offset - will be used as the new gametype after the map change, providing it is in range (from 0 to - 4, inclusive).</p> - <h3><a name="l3"></a>3 - Zoom Tube Parameters</h3> - <p>X length = speed. Y length = waypoint sequence #. See sector type <a href="#s32768">32768</a> - for more information.</p> - <h3><a name="l4"></a>4 - Speed Pad</h3> - <p>Creates a speed pad. The linedef direction and indicates the direction of the pad. The - target sector must have type <a href="#s1280">1280</a> or <a href="#s1536">1536</a> for - this to work.</p> - <p>If the <a href="#EFFECT4">EFFECT4</a> flag is set, you will not be teleported to the - center of the sector when the speed pad is activated.</p> - <h3><a name="l5"></a>5 - Camera Scanner</h3> - <p>Modifies camera position while the player is in the target sector. The floor and - ceiling of the control sector and the angle of the control linedef are the values for - CAM_HEIGHT, CAM_DIST, and CAM_ROTATE, respectively. Camera position is reset when the - player steps outside the sector.</p> - <h3><a name="l6"></a>6 - Disable Linedef</h3> - <p>Disables any linedef specials that share the same tag. Will be used in the future to - check if a particular level has been previously cleared or not.</p> - <h3><a name="l7"></a>7 - Flat Alignment</h3> - <p>Aligns floor and/or ceiling flats. The x alignment is specified by the control - linedef's x distance (the difference between the x values of its two vertices), and the y - alignment is specified by the control linedef's y distance.</p> - <p>By default, works on both the floor and ceiling (however, note that skies cannot be - "aligned" ;). Adding the <a href="#NOCLIMB">NOCLIMB</a> flag to the linedef will - align the floor only, while the <a href="#BLOCKMONSTERS">BLOCKMONSTERS</a> flag will make - it align the ceiling only.</p> - <h3><a name="l8"></a>8 - Sector Special Parameters</h3> - <p>Sets special behavior of a sector's type depending on the flag(s) checked:</p> - <p><a href="#NOCLIMB">NOCLIMB</a> - Special only operates when touching ceiling</p> - <p><a href="#EFFECT4">EFFECT4</a> - Special operates when touching either the floor or the - ceiling</p> - <p><a href="#EFFECT3">EFFECT3</a> - Special operates by just touching the sector, rather - than having to be inside of it.</p> - <h3><a name="l9"></a>9 - Chain Parameters</h3> - <p>Sets special behavior of a moving chain as such:</p> - <p>x length - # of links on the chain</p> - <p>y length - Overall speed (0-15)</p> - <p>X offset - Rotation speed on the X axis (0-15)</p> - <p>Y offset - Rotation speed on the Z axis (0-15)</p> - <p>floorheight - angle to start at (0-15)</p> - <p>ceilingheight - maximum rotation speed</p> - <h3><a name="l10"></a>10 - Culling Plane</h3> - <p>Set like <a href="#l1">line 1</a>, this creates an invisible plane in the sector. If - your view is above this plane, lots of things drawn below the height of this plane will be - discarded, and if your view is below the plane, a lot of things drawn above the height of - the plane will be discarded. This is to tell the game to not draw stuff that you aren't - going to see anyway. Do note that the view doesn't have to be in the current sector, you - can also be viewing from the side, which may be undesirable. To prevent this problem, you - can check the <a href="#NOCLIMB">NOCLIMB</a> flag, which will allow you to 'group' a set - of sectors to one control sector in which the culling will only take effect. For example, - you have a control sector set up for culling, and have two culling lines in the control - sector, tagged to sectors 'A' and 'B'. If the player is in sector 'A' or 'B', the culling - will occur, but if the player is in sector 'C', it will not.</p> - <h3>11 - Rope Hang Parameters</h3> - <p>X length = speed. Y length = waypoint sequence #.</p> - <p>EFFECT1 - Don't wrap movement</p> - <p>See sector type 45056 for more information.</p> - <h3>12 - Rock Spawn Parameters</h3> - <p>Sets special behavior of a rock spawner (#1202) as such:</p> - <p>length - momentum strength</p> - <p>line angle - momentum angle</p> - <p>X offset - # of tics to wait until another is spawned</p> - <p>Y offset - Rock crumble sprite to use (0-15)</p> - <p>NOCLIMB - add some randomization to the momentum</p> - <p> </p> - <h3>13 - Heat Wave</h3> - <p>Applies a heat effect to the screen. Tag this to a sector, or to the control sector of a FOF.</p> - <p> </p> - </ol> - </li> - <li><u><big><big>Level Parameters / Miscellany</big></big></u><ol> - <h3><a name="l20"></a>20 - Marks first line in PolyObject</h3> - <p>Explain here.</p> - <h3><a name="l21"></a>21 - Explicitly include a PolyObject line</h3> - <p>Explain here.</p> - <h3><a name="l30"></a>30 - PolyObject Parameters</h3> - <p>Explain here.</p> - <p> </p> - </ol> - </li> - <li><u><big><big>Level-Load Effects</big></big></u><ol> - <h3><a name="l50"></a>50 - Instant Floor Lower</h3> - <p>Makes the floor instantly lower on level load to be at the same height as the lowest - floor of any bordering sector.</p> - <h3><a name="l51"></a>51 - Instant Ceiling Raise</h3> - <p>Makes the ceiling instantly rise on level load to be the same height as the highest - ceiling of any bordering sector.</p> - <h3><a name="l52"></a>52 - Continuously Falling Sector</h3> - <p>Requires two control sectors. Sector continuously falls until its ceiling reaches the - floor of the line's back sector, then returns to its original position and keeps falling. - Linedef length determines speed. Good for things like intermittently falling lava. If the <a - href="#NOCLIMB">NOCLIMB</a> flag is set, it falls upwards, instead of downwards.</p> - <h3><a name="l53"></a>53 - Continuous Floor/Ceiling Mover</h3> - <p>Must be a two-sided linedef, tagged to another sector on the map. The tagged sector's - floor and ceiling will move, first so that they're equal to the floor and ceiling of the - linedef's front sector, then so they're equal to the floor and ceiling of the linedef's - back sector, then the front sector again, and so on.</p> - <p>The speed of the movement is determined by the linedef's length and uses the same units - as linetype <a href="#l60">60</a>.</p> - <h3><a name="l54"></a>54 - Continuous Floor Mover</h3> - <p>Like linetype <a href="#l53">53</a>, but only moves the floor, not the ceiling. Can be - used to replace floating platforms in some cases, where only the floor was desired to - move.</p> - <h3><a name="l55"></a>55 - Continuous Ceiling Mover</h3> - <p>Like linetype <a href="#l53">53</a>, but only moves the ceiling, not the floor.</p> - <h3><a name="l56"></a>56 - Continuous Two-Speed Floor/Ceiling Mover</h3> - <p>Must be a two-sided linedef, tagged to another sector on the map. The tagged sector's - floor and ceiling will move, first so that they're equal to the floor and ceiling of the - linedef's front sector, then so they're equal to the floor and ceiling of the linedef's - back sector, then the front sector again, and so on.</p> - <p>The speed of the movement is determined by the linedef's x distance (the first way, - towards the front sector) and y distance (the second way, towards the back sector), using - the same units as linetype <a href="#l60">60</a>.</p> - <p>Unlike linetype <a href="#l53">53</a>, this effect does not slow down when it reaches - the end of its movement. Instead, it changes instantly from going in one direction to - going in the other. It's designed for making more sophisticated crushers than the crusher - type allows (i.e. crushers with varying rise/crush speeds, FOF crushers, crushers with - different start points).</p> - <h3><a name="l57"></a>57 - Continuous Two-Speed Floor Mover</h3> - <p>Like linetype <a href="#l56">56</a>, but only moves the floor, not the ceiling.</p> - <h3><a name="l58"></a>58 - Continuous Two-Speed Ceiling Mover</h3> - <p>Like linetype <a href="#l56">56</a>, but only moves the ceiling, not the floor.</p> - <h3><a name="l59"></a>59 - Activate Floating Platform</h3> - <p>This is used to make floating platforms (that move up and down) as well as moving - water. In fact, you can use this to make any type of block move vertically. The way it - works is somewhat confusing - You use three control sectors, all connected by at least one - linedef. Easiest thing to do is make three square sectors together in a row. One of the - linedefs on the middle sector should contain the Floor Over Floor line special that you - want. This will be the Floor Over Floor control sector. The other two sectors represent - the bottommost position you want the Floor Over Floor to reach, and the topmost position - you want the Floor Over Floor to reach. The 59 line can be on any of these sectors, as - long as you tag it to the middle one. If you still don't understand, look at Greenflower - Zone Act 2. If the <a href="#NOCLIMB">NOCLIMB</a> flag is set, the platform will begin - moving upwards, rather than downwards.</p> - <h3><a name="l60"></a>60 - Activate Floating Platform (Adjustable Speed)</h3> - <p>Speed is indicated by linedef length; one unit of speed here is 0.25 fracunits per tic. - (Floating platforms made with type <a href="#l59">59</a> move at 2 fracunits per tic.) - Aside from the linedef length controlling speed, works exactly like linedef type <a - href="#l59">59</a>.</p> - <h3><a name="l61"></a>61 - Crusher 1 (Ceiling to Floor)</h3> - <p>The crush motion is from the ceiling to the floor. Linedef length indicates crusher - speed. See also linetype <a href="#l62">62</a>, Crusher 2.</p> - <h3><a name="l62"></a>62 - Crusher 2 (Floor to Ceiling)</h3> - <p>Like linetype <a href="#l61">61</a>, Crusher 1, except that it starts in a different - place, not synchronised with any crushers that use the Crusher 1 type. The highest ceiling - this crusher reaches will be the highest ceiling height of any bordering sector.</p> - <h3><a name="l63"></a>63 - Fake Floor</h3> - <p>Creates two fake planes, fake floor and fake ceiling. Main textures are not affected, - but as far as above/below textures and floor/ceiling flats are concerned, the floor and - ceiling height are those of the control sector. As far as collisions, walking, etc. are - concerned, the floor and ceiling flats are whatever they normally would be.</p> - <p>Fake floor is useful for railings (THZRAIL and WOODRAIL; see THZ2 for examples) and - snow effects (making a fake floor of snow just a few units above normal floor, so it looks - like the player's feet are buried in the snow).</p> - <h3><a name="l64"></a>64 - Appearing/Disappearing FOF</h3> - <p>Tag this to any FOF <i>line</i> and this will cause it to appear and disappear - intermittently. The line's X length is the amount of time (in tics) that the FOF will - appear, and Y length is the amount of time (in tics) that the FOF will disappear. The - control sector's floor height allows you to specify an offset (in tics) of how much time - will pass before the appearing/disappearing kicks in.</p> - <p> </p> - </ol> - </li> - <li><u><big><big>Floor-Over-Floors (FOFs)</big></big></u><ol> - <h3><a name="l100"></a>100 - Floor Over Floor: Solid, Opaque, Shadowcasting</h3> - <p>This is just a regular old FOF. As with any block, the ceiling of the control sector is - the top of the block, and the floor of the control sector is the bottom. - "Shadowcasting" means that the light value used in the control sector is used - for the area below where the actual FOF appears, as opposed to above it.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL--> - <h3><a name="l101"></a>101 - Floor Over Floor: Solid, Opaque, Non-Shadowcasting</h3> - <p>See notes for <a href="#l100">100</a>. "Non-shadowcasting" means that the - light value you set in the control sector will be used for the area above the FOF, instead - of below it.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_NOSHADE|FF_CUTLEVEL--> - <h3><a name="l102"></a>102 - Floor Over Floor: Solid, Translucent</h3> - <p>Useful for windows. The GLASSTEX texture is good for this purpose. You can change the - alpha value of the translucency by setting the control linedef's Above texture to a # - followed by a three-digit decimal number, 000 to 255. #000 is most transparent, #255 is - most opaque. Note that in software mode, there are actually only ten different values that - serve as a 'best guess'.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_NOSHADE|FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA--> - <h3><a name="l103"></a>103 - Floor Over Floor: Solid, Sides Only</h3> - <p>A solid FOF that renders sides only, not planes (floor and ceiling). You were supposed - to be able to use it to place railings (THZRAIL, WOODRAIL, etc.) on FOFs. It doesn't work - for that, because the railings use a different kind of transparency and software mode - won't draw them on FOFs. So this one is going on the list of useless effects, right next - to linetype <a href="#l104">104</a>.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERSIDES|FF_NOSHADE|FF_CUTLEVEL--> - <h3><a name="l104"></a>104 - Floor Over Floor: Solid, No Sides</h3> - <p>Like a 3D floor of type <a href="#l101">101</a>, except that sides are not drawn. - Supposedly a little bit faster than a normal 3D floor. You can use it when the sides - wouldn't be visible anyway.</p> - <p>This type of 3D floor will have shadows if and only if you set the control linedef's <a - href="#NOCLIMB">NOCLIMB</a> flag.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERPLANES|FF_CUTLEVEL -If the <a href="#NOCLIMB">NOCLIMB</a> flag is disabled, it also adds FF_NOSHADE--> - <h3><a name="l105"></a>105 - Floor Over Floor: Solid, Invisible</h3> - <p>For making invisible walls and other strange effects.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_NOSHADE--> - <hr> - <h3><a name="l120"></a>120 - Floor Over Floor: Water, Opaque</h3> - <p>This one looks exactly like linetype <a href="#l100">100</a> ingame, but is a block of - water instead of solid.</p> - <p>The block will have the attribute of linetype <a href="#l200">200</a> if the <a - href="#NOCLIMB">NOCLIMB</a> flag is set.</p> - <p>To use the light level of the target sector, utilize the <a href="#EFFECT4">EFFECT4</a> - flag.</p> - <p>If this is used as lava (Fire Damage), and you set the <a href="#BLOCKMONSTERS">BLOCKMONSTERS</a> - flag, you can still pass through the lava.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_RENDERALL|FF_SWIMMABLE|FF_BOTHPLANES|FF_ALLSIDES|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES--> - <h3><a name="l121"></a>121 - Floor Over Floor: Water, Translucent</h3> - <p>This one looks exactly like linetype <a href="#l102">102</a> ingame, but is a block of - water instead of solid.</p> - <p>The block will have the attribute of linetype <a href="#l200">200</a> if the <a - href="#NOCLIMB">NOCLIMB</a> flag is set.</p> - <p>To use the light level of the target sector, utilize the <a href="#EFFECT4">EFFECT4</a> - flag.</p> - <p>If this is used as lava (Fire Damage), and you set the <a href="#BLOCKMONSTERS">BLOCKMONSTERS</a> - flag, you can still pass through the lava.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_RENDERALL|FF_TRANSLUCENT|FF_SWIMMABLE|FF_BOTHPLANES|FF_ALLSIDES|FF_CUTEXTRA|FF_EXTRA| -FF_CUTSPRITES--> - <h3><a name="l122"></a>122 - Floor Over Floor: Water, Opaque, No Sides</h3> - <p>Like linetype <a href="#l120">120</a>, but doesn't render sides.</p> - <p>The block will have the attribute of linetype <a href="#l200">200</a> if the <a - href="#NOCLIMB">NOCLIMB</a> flag is set.</p> - <p>To use the light level of the target sector, utilize the <a href="#EFFECT4">EFFECT4</a> - flag.</p> - <p>If this is used as lava (Fire Damage), and you set the <a href="#BLOCKMONSTERS">BLOCKMONSTERS</a> - flag, you can still pass through the lava.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_RENDERPLANES|FF_SWIMMABLE|FF_BOTHPLANES|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES--> - <h3><a name="l123"></a>123 - Floor Over Floor: Water, Translucent, No Sides</h3> - <p>Like linetype <a href="#l121">121</a>, but doesn't render sides. Most of the time this - won't make a difference. It can be useful, however, for windows that have water on one - side and not on the other.</p> - <p>The block will have the attribute of linetype <a href="#l200">200</a> if the <a - href="#NOCLIMB">NOCLIMB</a> flag is set.</p> - <p>To use the light level of the target sector, utilize the <a href="#EFFECT4">EFFECT4</a> - flag.</p> - <p>If this is used as lava (Fire Damage), and you set the <a href="#BLOCKMONSTERS">BLOCKMONSTERS</a> - flag, you can still pass through the lava.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_RENDERPLANES|FF_TRANSLUCENT|FF_SWIMMABLE|FF_BOTHPLANES|FF_CUTEXTRA|FF_EXTRA| -FF_CUTSPRITES--> - <hr> - <h3><a name="l140"></a>140 - Floor Over Floor: Intangible from Bottom, Opaque </h3> - <p>This sector type is solid from the top and walls, but is not solid from the bottom. - This allows the designer to create one-way passages as well as simulate 2D design by - having platforms that players can jump up to from below.</p> - <p>This type of 3D floor will have shadows unless you set the control linedef's <a - href="#NOCLIMB">NOCLIMB</a> flag.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_PLATFORM|FF_BOTHPLANES|FF_ALLSIDES -If the <a href="#NOCLIMB">NOCLIMB</a> flag is enabled, it also adds FF_NOSHADE--> - <h3><a name="l141"></a>141 - Floor Over Floor: Intangible from Bottom, Translucent</h3> - <p>A copy of linetype <a href="#l140">140</a> that is also translucent.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_PLATFORM|FF_TRANSLUCENT|FF_BOTHPLANES|FF_ALLSIDES -If the <a href="#NOCLIMB">NOCLIMB</a> flag is enabled, it also adds FF_NOSHADE--> - <h3><a name="l142"></a>142 - Floor Over Floor: Intangible from Bottom, Translucent, No - Sides</h3> - <p>A platform you can jump up through, like linetype <a href="#l140">140</a> (and decides - the same way whether to have shadows or not), with translucency and that doesn't render - sides. Alpha value supported the same way as linetype <a href="#l102">102</a>.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_CUTLEVEL|FF_RENDERPLANES|FF_TRANSLUCENT|FF_PLATFORM|FF_BOTHPLANES -If the <a href="#NOCLIMB">NOCLIMB</a> flag is enabled, it also adds FF_NOSHADE--> - <hr> - <h3><a name="l150"></a>150 - Floor Over Floor: Bobbing (Air)</h3> - <p>FOF that moves down 16 units when you step on, then returns to its former position when - you step off. The control sector must be connected to another sector with the same floor - and ceiling height. This seemingly redundant sector is used for resetting the heights. (If - you forget to put it in, the bobbing floor when stepped on will go down, keep going down, - and never stop or come back up.) See also linetypes <a href="#l151">151</a> and <a - href="#l152">152</a>. This linedef is obsolete. Please use linetype 190-195.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_AIRBOB--> - <h3><a name="l151"></a>151 - Floor Over Floor: Adjustable Bobbing (Air)</h3> - <p>Like linetype <a href="#l150">150</a>, except that instead of the floor moving down 16 - units when you step on it, it moves down the number of units of the control linedef's - length. This linedef is obsolete. Please use linetype 190-195.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_AIRBOB--> - <h3><a name="l152"></a>152 - Floor Over Floor: Reverse Bobbing (Air)</h3> - <p>Like linetype <a href="#l151">151</a>, except in reverse. The platform goes <i>up</i> - when you step on it and back <i>down</i> when you step off. This linedef is obsolete. - Please use linetype 190-195.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_AIRBOB--> - <hr> - <h3><a name="l160"></a>160 - Floor Over Floor: Floating, Bobbing</h3> - <p>Bobs and floats in water. The floating part means that if the water moves or rises, - this platform will rise with it.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_FLOATBOB--> - <hr> - <h3><a name="l170"></a>170 - Floor Over Floor: Crumbling (Respawn)</h3> - <p>Crumbles and falls away, then reappears 15 seconds later.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_CRUMBLE--> - <h3><a name="l171"></a>171 - Floor Over Floor: Crumbling (No Respawn)</h3> - <p>Crumbles and falls away and never comes back.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_CRUMBLE|FF_NORETURN--> - <h3><a name="l172"></a>172 - Floor Over Floor: Crumbling (Respawn)</h3> - <p>A copy of linetype <a href="#l140">140</a> that also crumbles when stood on and - reappears after 15 seconds.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_PLATFORM|FF_CRUMBLE|FF_BOTHPLANES|FF_ALLSIDES -If the <a href="#NOCLIMB">NOCLIMB</a> flag is enabled, it also adds FF_NOSHADE--> - <h3><a name="l173"></a>173 - Floor Over Floor: Crumbling (No Respawn)</h3> - <p>A copy of linetype <a href="#l172">172</a> that stays gone forever after crumbling.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_PLATFORM|FF_CRUMBLE|FF_NORETURN|FF_BOTHPLANES| -FF_ALLSIDES -If the <a href="#NOCLIMB">NOCLIMB</a> flag is enabled, it also adds FF_NOSHADE--> - <h3><a name="l174"></a>174 - Floor Over Floor: Intangible from Bottom, Crumbling - (Respawn), Translucent</h3> - <p>A copy of linetype <a href="#l141">141</a> that also crumbles when stood on and - reappears after 15 seconds.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_PLATFORM|FF_CRUMBLE|FF_TRANSLUCENT|FF_BOTHPLANES| -FF_ALLSIDES -If the <a href="#NOCLIMB">NOCLIMB</a> flag is enabled, it also adds FF_NOSHADE--> - <h3><a name="l175"></a>175 - Floor Over Floor: Intangible from Bottom, Crumbling (No - Respawn), Translucent</h3> - <p>A copy of linetype <a href="#l174">174</a> that stays gone forever after crumbling.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_PLATFORM|FF_CRUMBLE|FF_NORETURN|FF_TRANSLUCENT| -FF_BOTHPLANES|FF_ALLSIDES -If the <a href="#NOCLIMB">NOCLIMB</a> flag is enabled, it also adds FF_NOSHADE--> - <h3><a name="l176"></a>176 - Floor Over Floor: Crumbling (Respawn), Floating, Bobbing</h3> - <p>Crumbles and falls, then floats on water, then bobs when you step on it.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_FLOATBOB|FF_AIRBOB|FF_CRUMBLE--> - <h3><a name="l177"></a>177 - Floor Over Floor: Crumbling (No Respawn), Floating, Bobbing</h3> - <p>Crumbles and falls, then floats on water, then bobs when you step on it. Unlike - linetype <a href="#l176">176</a>, does not return to its former position.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_FLOATBOB|FF_AIRBOB|FF_CRUMBLE|FF_NORETURN--> - <h3><a name="l178"></a>178 - Floor Over Floor: Crumbling (Respawn), Floating</h3> - <p>Crumbles and falls, then floats on water, then reappears up in the air 15 seconds - later.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_CRUMBLE|FF_FLOATBOB--> - <h3><a name="l179"></a>179 - Floor Over Floor: Crumbling (No Respawn), Floating</h3> - <p>Crumbles and falls, then spends the rest of its days floating on water, never to - reappear up in the air.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_CRUMBLE|FF_FLOATBOB|FF_NORETURN--> - <h3><a name="l180"></a>180 - Floor Over Floor: Crumbling (Respawn), Bobbing (Air)</h3> - <p>Bobs, crumbles, and falls when stepped on.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_AIRBOB|FF_CRUMBLE--> - <hr> - <h3><a name="l190"></a>190 - Floor Over Floor: Rising Platform, Solid, Opaque, - Shadowcasting</h3> - <p>Just like <a href="#l100">100</a>, except when a player steps on it, it will rise up to - the control sector's highest adjacent sector. You set the control sectors for this up like - special <a href="#l59">59</a>. Linedef length controls speed like <a href="#l60">60</a>. - If the <a href="#NOCLIMB">NOCLIMB</a> flag is set, it will require the player to spindash - to raise the platform.</p> - <h3><a name="l191"></a>191 - Floor Over Floor: Rising Platform, Solid, Opaque, - Non-Shadowcasting</h3> - <p>Just like <a href="#l101">101</a>, except when a player steps on it, it will rise up to - the control sector's highest adjacent sector. You set the control sectors for this up like - special <a href="#l59">59</a>. Linedef length controls speed like <a href="#l60">60</a>. - If the <a href="#NOCLIMB">NOCLIMB</a> flag is set, it will require the player to spindash - to raise the platform.</p> - <h3><a name="l192"></a>192 - Floor Over Floor: Rising Platform, Solid, Translucent</h3> - <p>Just like <a href="#l102">102</a>, except when a player steps on it, it will rise up to - the control sector's highest adjacent sector. You set the control sectors for this up like - special <a href="#l59">59</a>. Linedef length controls speed like <a href="#l60">60</a>. - If the <a href="#NOCLIMB">NOCLIMB</a> flag is set, it will require the player to spindash - to raise the platform.</p> - <h3><a name="l193"></a>193 - Floor Over Floor: Rising Platform, Solid, Invisible</h3> - <p>Just like <a href="#l105">105</a>, except when a player steps on it, it will rise up to - the control sector's highest adjacent sector. You set the control sectors for this up like - special <a href="#l59">59</a>. Linedef length controls speed like <a href="#l60">60</a>. - If the <a href="#NOCLIMB">NOCLIMB</a> flag is set, it will require the player to spindash - to raise the platform.</p> - <h3><a name="l194"></a>194 - Floor Over Floor: Rising Platform, Intangible from Bottom, - Opaque</h3> - <p>Just like <a href="#l140">140</a>, except when a player steps on it, it will rise up to - the control sector's highest adjacent sector. You set the control sectors for this up like - special <a href="#l59">59</a>. Linedef length controls speed like <a href="#l60">60</a>. - If the <a href="#NOCLIMB">NOCLIMB</a> flag is set, it will require the player to spindash - to raise the platform.</p> - <h3><a name="l195"></a>195 - Floor Over Floor: Rising Platform, Intangible from Bottom, - Translucent</h3> - <p>Just like <a href="#l141">141</a>, except when a player steps on it, it will rise up to - the control sector's highest adjacent sector. You set the control sectors for this up like - special <a href="#l59">59</a>. Linedef length controls speed like <a href="#l60">60</a>. - If the <a href="#NOCLIMB">NOCLIMB</a> flag is set, it will require the player to spindash - to raise the platform.</p> - <hr> - <h3><a name="l200"></a>200 - Floor Over Floor: Light Block</h3> - <p>Like a half light block, but it's really an actual block. That is, the light only comes - down to the control sector's floor, not to the bottom of the level (as with linetype <a - href="#l201">201</a>.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_CUTSPRITES|FF_DOUBLESHADOW--> - <h3><a name="l201"></a>201 - Floor Over Floor: Half Light Block</h3> - <p>Light blocks can be used to set color maps and light values. The light value of the - control sector will be used and any colormap attached to it will be used also. Note that - only the ceiling of the control sector is used; the light goes all the way down to the - bottom of the level. If this isn't what you want, consider using linedef type <a - href="#l200">200</a> instead.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_CUTSPRITES -Note: Although it's not a true FOF, it does still have the same kind of definition, so -the FOF flags are included despite not being a real block.--> - <h3><a name="l202"></a>202 - Floor Over Floor: Fog Block</h3> - <p>Creates a block of colored fog. Attach a colormap (linetype <a href="#l606">606</a>) to - the control sector for the fog block; otherwise you won't see anything out of the - ordinary.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_RENDERALL|FF_FOG|FF_BOTHPLANES|FF_INVERTPLANES|FF_ALLSIDES|FF_INVERTSIDES|FF_CUTEXTRA| -FF_EXTRA|FF_DOUBLESHADOW|FF_CUTSPRITES--> - <hr> - <h3><a name="l220"></a>220 - Floor Over Floor: Intangible, Opaque </h3> - <p>Like <a href="#l120">opaque water</a>, but not swimmable. Good for a snow effect on - FOFs. Can also be used to make hidden rooms, like you would normally do by setting a Main - texture.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_RENDERALL|FF_BOTHPLANES|FF_ALLSIDES|FF_CUTEXTRA|FF_EXTRA|FF_CUTSPRITES--> - <h3><a name="l221"></a>221 - Floor Over Floor: Intangible, Translucent</h3> - <p>See linedef type <a href="#l102">102</a> for how to adjust the translucency, making the - 3D floor more transparent or more opaque.</p> - <p>This type of 3D floor will have shadows if and only if you set the control linedef's <a - href="#NOCLIMB">NOCLIMB</a> flag.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_RENDERALL|FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA -If the <a href="#NOCLIMB">NOCLIMB</a> flag is disabled, it also adds FF_NOSHADE--> - <h3><a name="l222"></a>222 - Floor Over Floor: Intangible, Sides Only</h3> - <p>An intangible FOF that renders sides only, not planes (floor and ceiling). It renders - both inside sides and outside sides. You can use it to place sector borders (GFZGRASS, - etc.) on FOFs.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_RENDERSIDES|FF_NOSHADE|FF_ALLSIDES--> - <h3><a name="l223"></a>223 - Floor Over Floor: Intangible, Invisible</h3> - <p>Useful for setting effects, such as wind and gravity.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_NOSHADE--> - <hr> - <h3><a name="l250"></a>250 - Floor Over Floor: Mario Block</h3> - <p>Like a normal FOF, except that the control linedef's Above texture is used after the - block has been hit (the Main texture is used before this). Any things in the control - sector will pop out the top of the block in the order in which they were placed. Rings - will be obtained and the effects of monitors will begin as soon as the block has been hit.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_MARIO--> - <h3><a name="l251"></a>251 - Floor Over Floor: Thwomp Block</h3> - <p>The thwomps are the crazy platforms with faces in Mario Koopa Blast 3. They can crush - you, but you can also ride on them.</p> - <p>Control sector is set up like a <a href="#l100">normal FOF</a>. When a player steps - underneath the thwomp, it will crush down to the floor. You don't need to tell it where - the floor is. It knows.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL--> - <h3><a name="l252"></a>252 - Floor Over Floor: Shatter Block</h3> - <p>Like the bustable block, linetype <a href="#l254">254</a>, except that it shatters on - any sort of contact, whether it's a spindash or not (and whether you're Knuckles or not).</p> - <p>If the <a href="#NOCLIMB">NOCLIMB</a> flag is set, the block is only shatterable from - the bottom, like some things you spring up and break in Launch Base Zone from Sonic 3.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP|FF_SHATTER--> - <h3><a name="l253"></a>253 - Floor Over Floor: Shatter Block, Translucent</h3> - <p>Translucent version of <a href="#l252">252</a> supporting alpha values.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP|FF_SPINBUST|FF_TRANSLUCENT--> - <h3><a name="l254"></a>254 - Floor Over Floor: Bustable Block</h3> - <p>Bustable blocks can be destroyed by spindashing. Additionally, Knuckles can destroy - them by walking or jumping into them, since he is very strong. If the <a href="#NOCLIMB">NOCLIMB</a> - flag is set, only Knuckles can break the block.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP (|FF_ONLYKNUX if <a href="#NOCLIMB">NOCLIMB</a>)--> - <h3><a name="l255"></a>255 - Floor Over Floor: Spin Bust Block</h3> - <p>Like the bustable block, linetype <a href="#l254">254</a>, set off in a different way. - To break, jump onto it or fall down onto it while spinning. Similar to blocks found in - Marble Zone, as well as the ice cubes that would encase buttons and monitors in parts of - Ice Cap Zone.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP|FF_SPINBUST--> - <h3><a name="l256"></a>256 - Floor Over Floor: Spin Bust Block, Translucent</h3> - <p>Translucent version of <a href="#l255">255</a> supporting alpha values.</p> - <h3><a name="l257"></a>257 - Floor Over Floor: Quicksand Block</h3> - <p>It's set up like any block. You can, of course, sink and die in it. X length of the - linedef determines sink speed, Y length determines how "sludgy" movement in the - quicksand is.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_QUICKSAND|FF_RENDERALL|FF_ALLSIDES|FF_CUTSPRITES--> - <h3><a name="l258"></a>258 - Floor Over Floor: Laser Block</h3> - <p>Creates a blinking FOF that zaps you if you touch it. You can set the flats and texture - to whatever you want. For a red laser like in THZ2, use REDFLR for the flats and REDWALL - for the texture.</p> - <p>You can also make other colors using BLUEFLR/BLUWALL (blue laser), GREENFLR/GRNWALL - (green laser), and YELFLR/YELWALL (yellow laser). Of course, those colors of lasers are - very expensive, so Eggman doesn't have nearly as many of them. He usually goes with the - cheap red lasers.</p> -<!--Exact FOF flags: -FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA--> - <h3><a name="l259"></a>259 - Floor Over Floor: Custom</h3> - <p>Place the appropriate flag values in hex (do not include the 0x in front of it) in the - line's UPPER TEXTURE field on the 2nd side of the linedef.</p> - </ol> - </li> - <li><u><big><big>Linedef Executor Triggers</big></big></u><ol> - <h3><a name="l300"></a>300 - Trigger Linedef Executor (Continuous)</h3> - <p>Triggers linedef executor in the control sector when a player touches the tagged - sector's floor or steps in the sector (depending on the sector special used). The linedef - executor will keep being triggered over and over again as long as a player is there, hence - the word "continuous" in this linetype's name. Tagged sector must have one of - the <a href="#sCat2">Trigger Linedef Executor</a> types for this to work.</p> - <h3><a name="l301"></a>301 - Trigger Linedef Executor (Each Time)</h3> - <p>Like <a href="#l300">300</a>, except that it only gets triggered once for each time you - fall or jump onto the floor. Tagged sector must have one of the <a href="#sCat2">Trigger - Linedef Executor</a> types for this to work.</p> - <h3><a name="l302"></a>302 - Trigger Linedef Executor (Once)</h3> - <p>Like <a href="#l300">300</a>, except that after that linedef executor executes its - linedefs, it's done. It's over. The linedefs will never be executed again.</p> - <h3><a name="l303"></a>303 - Trigger Linedef Executor (Ring Count - Continuous)</h3> - <p>Triggers linedef executor in the control sector when a player touches the tagged - sector's floor or steps in the sector (depending on the sector special used). The linedef - executor will keep being triggered over and over again as long as a player is there, hence - the word "continuous" in this linetype's name. Tagged sector must have one of - the <a href="#sCat2">Trigger Linedef Executor</a> types for this to work. Executor will be - triggered depending on how many rings the player has:</p> - <p>No flags -> Runs if (rings = line length)</p> - <p><a href="#NOCLIMB">NOCLIMB</a> -> Runs if (rings <= line length)</p> - <p><a href="#BLOCKMONSTERS">BLOCKMONSTERS</a> -> Runs if (rings >= line length)</p> - <p><a href="#EFFECT4">EFFECT4</a> -> Takes the rings of ALL players into account.</p> - <h3><a name="l304"></a>304 - Trigger Linedef Executor (Ring Count - Once)</h3> - <p>Like <a href="#l303">303</a>, except that after that linedef executor executes its - linedefs, it's done. It's over. The linedefs will never be executed again.</p> - <h3><a name="l305"></a>305 - Trigger Linedef Executor (Character Ability - Once)</h3> - <p>Like linetype <a href="#l302">302</a>, but is only activated when the character's - ability number matches the linedef length by multiples of 10. For example:</p> - <p>0-9 = Charability 0</p> - <p>10-19 = Charability 1</p> - <p>20-29 = Charability 2</p> - <p>etc...</p> - <h3><a name="l306"></a>306 - Trigger Linedef Executor (Character Ability - Continuous)</h3> - <p>Like <a href="#l300">300</a>, but only triggers when the character's ability number - matches the linedef length by multiples of 10. See linetype <a href="#l305">305</a> for a - futher description.</p> - <h3><a name="l307"></a>307 - Trigger Linedef Executor (Character Ability - Each Time)</h3> - <p>Like <a href="#l301">301</a>, but only triggers when the character's ability number - matches the linedef length by multiples of 10. See linetype <a href="#l305">305</a> for a - futher description.</p> - <h3><a name="l308"></a>308 - Trigger Linedef Executor (Race Only, Once)</h3> - <p>Like linetype <a href="#l302">302</a>, but is only activated when the gametype is Race. - Useful for doing things like opening doors, pre-solving puzzles, etc. to make race - smoother.</p> - <h3><a name="l309"></a>309 - Trigger Linedef Executor (CTF Red Team - Continuous)</h3> - <p>Like <a href="#l300">300</a>, but only triggers if you are in CTF and on the red team.</p> - <h3><a name="l310"></a>310 - Trigger Linedef Executor (CTF Red Team - Each Time)</h3> - <p>Like <a href="#l301">301</a>, but only triggers if you are in CTF and on the red team.</p> - <h3><a name="l311"></a>311 - Trigger Linedef Executor (CTF Blue Team - Continuous)</h3> - <p>Like <a href="#l300">300</a>, but only triggers if you are in CTF and on the blue team.</p> - <h3><a name="l312"></a>312 - Trigger Linedef Executor (CTF Blue Team - Each Time)</h3> - <p>Like <a href="#l301">301</a>, but only triggers if you are in CTF and on the blue team.</p> - <h3><a name="l313"></a>313 - Trigger Linedef Executor (No More Enemies - Once)</h3> - <p>Like linetype <a href="#l302">302</a>, but is only activated when no more objects of - type MF_ENEMY exist in its tagged area. Think "destroy all enemies in this room for - the door to open to go to the next room". Tag this to a control sector. It will go - through the lines of the control sector, checking for any lines of type <a href="#l223">223</a> - and checking inside the area occupied by the invisible intangible FOF to see if any - enemies exist. If no alive enemies are in all of the type <a href="#l223">223</a> FOFs, - the linedef executor is run once. The line length is the tag number of the linedef - executor trigger to run.</p> - <h3><a name="l314"></a>314 - Trigger Linedef Executor (# of Pushables - Continuous)</h3> - <p>Like <a href="#l300">300</a>, but only triggers if the number of pushable objects in - the sector compared to the line length is:</p> - <p>No flags -> Runs if (# pushables = line length)</p> - <p><a href="#NOCLIMB">NOCLIMB</a> -> Runs if (# pushables >= line length)</p> - <p><a href="#EFFECT4">EFFECT4</a> -> Runs if (# pushables < line length)</p> - <h3><a name="l315"></a>315 - Trigger Linedef Executor (# of Pushables - Once)</h3> - <p>Like <a href="#l314">314</a>, but only triggers once.</p> - <h3><a name="l316"></a>316 - Trigger Linedef Executor (PolyObject - Land On)</h3> - <p>This will trigger every time you land on the polyobject. Line's tag # is 32000 + the - PolyObject ID #. You must also flag the PolyObject Start (#20) line with <a - href="#NOCLIMB">NOCLIMB</a> to tell the game it has a linedef executor associated with it.</p> - <p>So if you had a PolyObject with an ID of 1, this line would have a tag of 32001.</p> - <p> </p> - </ol> - </li> - <li><u><big><big>Linedef Executor Options</big></big></u><ol> - <h3><a name="l400"></a>400 - Linedef Executor: Set Tagged Sector's Floor Height/Pic</h3> - <p>When executed, instantly changes the tagged sector's floor height and flat to the floor - height and flat of the linedef's front sector.</p> - <h3><a name="l401"></a>401 - Linedef Executor: Set Tagged Sector's Ceiling Height/Pic</h3> - <p>When executed, instantly changes the tagged sector's ceiling height and flat to the - ceiling height and flat of the linedef's front sector.</p> - <h3><a name="l402"></a>402 - Linedef Executor: Set Tagged Sector's Light Level</h3> - <p>When executed, instantly changes the tagged sector's light level to that of the - linedef's front sector. Floor and ceiling light settings done with linetypes <a - href="#l601">601</a> and <a href="#l600">600</a> are transferred as well; colormaps are - not.</p> - <p>If there is a lighting effect active in the target sector or sectors at the time (glow, - fade, strobe, flicker), it will be stopped.</p> - <h3><a name="l403"></a>403 - Linedef Executor: Move Tagged Sector's Floor</h3> - <p>When executed, starts moving the tagged sector's floor until it is at the same height - as the linedef's front sector's floor. Speed is indicated in the same units used by - linetype <a href="#l60">60</a>.</p> - <p>If the line used has <a href="#NOCLIMB">NOCLIMB</a> flag, the floor flat will change - after the move, to that on the front sector's floor. This is like what linetype <a - href="#l400">400</a> does.</p> - <p>If the line used has <a href="#BLOCKMONSTERS">BLOCKMONSTERS</a> flag, another linedef - executor will be run when the floor movement is finished. (If multiple sectors finish at - different times, it goes by the lowest numbered sector, but you should probably try to - avoid this scenario.) The tag of the new linedef executor to run is specified by the X - alignment on the front side of the line. The tag number you use must be positive, and this - functionality cannot be combined with changing the floor flat using the <a href="#NOCLIMB">NOCLIMB</a> - flag. Running a linedef executor will take precedence over changing the floor flat.</p> - <h3><a name="l404"></a>404 - Linedef Executor: Move Tagged Sector's Ceiling</h3> - <p>When executed, starts moving the tagged sector's ceiling until it is at the same height - as the linedef's front sector's ceiling. Speed is indicated in the same units used by - linetype <a href="#l60">60</a>.</p> - <p>If the line used has <a href="#NOCLIMB">NOCLIMB</a> flag, the ceiling flat will change - after the move, to that on the front sector's ceiling. This is like what linetype <a - href="#l401">401</a> does.</p> - <p>If the line used has <a href="#BLOCKMONSTERS">BLOCKMONSTERS</a> flag, another linedef - executor will be run when the ceiling movement is finished. (If multiple sectors finish at - different times, it goes by the lowest numbered sector, but you should probably try to - avoid this scenario.) The tag of the new linedef executor to run is specified by the X - alignment on the front side of the line. The tag number you use must be positive, and this - functionality cannot be combined with changing the ceiling flat using the <a - href="#NOCLIMB">NOCLIMB</a> flag. Running a linedef executor will take precedence over - changing the ceiling flat.</p> - <h3><a name="l405"></a>405 - Linedef Executor: Lower Floor by Line</h3> - <p>Speed is indicated by x distance; amount to lower is indicated by y distance.</p> - <h3><a name="l406"></a>406 - Linedef Executor: Raise Floor by Line</h3> - <p>Speed is indicated by x distance; amount to raise is indicated by y distance.</p> - <h3><a name="l407"></a>407 - Linedef Executor: Lower Ceiling by Line</h3> - <p>Speed is indicated by x distance; amount to lower is indicated by y distance.</p> - <h3><a name="l408"></a>408 - Linedef Executor: Raise Ceiling by Line</h3> - <p>Speed is indicated by x distance; amount to raise is indicated by y distance.</p> - <h3><a name="l409"></a>409 - Linedef Executor: Change Calling Sector's Tag</h3> - <p>Changes the tag of the calling sector; that is, the sector on the map that activated - this linedef executor. The new tag is the linedef's length.</p> - <h3><a name="l410"></a>410 - Linedef Executor: Change Front Sector's Tag</h3> - <p>Changes the tag of the linedef's front sector. The new tag is the linedef's length.</p> - <h3><a name="l411"></a>411 - Linedef Executor: Stop Plane Movement</h3> - <p>Stops any and all floor, ceiling, or elevator movement in the tagged sector or sectors.</p> - <h2><a name="l412"></a>412 - Linedef Executor: Teleport Player to Tagged Sector</h2> - <p>The player who triggered the linedef executor will be teleported to the tagged sector. - The player's exact X, Y, Z, and angle are determined by a teleport destination thing, type - <a href="#t751">751</a>, somewhere in the tagged sector.</p> - <p>If the <a href="#BLOCKMONSTERS">BLOCKMONSTERS</a> flag is used, it won't flash and make - the teleport sound effects. If the <a href="#NOCLIMB">NOCLIMB</a> flag is used, it won't - reset the angle to the angle of the teleport destination thing, and if the <a - href="#EFFECT4">EFFECT4</a> flag is used, it will not kill your acceleration/speed upon - teleport.</p> - <h2><a name="l413"></a>413 - Linedef Executor: Change Music</h2> - <p>Linedef length indicates the music slot to use. If the linedef's <a href="#NOCLIMB">NOCLIMB</a> - flag is set, play the music once, otherwise loop it.</p> - <p>If the player dies and goes back to a starpost, the beginning of the level, or the - appropriate multiplayer start, the map music from before will be restored. The linedef - flag <a href="#BLOCKMONSTERS">BLOCKMONSTERS</a> can be set to change this behavior, and - retain the new music even after dying.</p> - <p>If the linedef length isn't a valid music slot, the music is stopped.</p> - <h3><a name="l414"></a>414 - Linedef Executor: Play SFX</h3> - <p>Plays a sound effect. The line length is the sound number to use. The list of sound - effects can be found in sounds.h. The origin of the sound depends on which linedef flags - are set: <ul> - <li><a href="#NOCLIMB">NOCLIMB</a> : The sound is played from nowhere, but only for the - player who triggered it.</li> - <li><a href="#EFFECT4">EFFECT4</a>: The sound is played from nowhere for everyone.</li> - <li><a href="#BLOCKMONSTERS">BLOCKMONSTERS</a>: The sound is played from the center of the - sector that triggered the linedef executor.</li> - </ul> - <p>Otherwise, the sound is played from the location of the player or thing who triggered - it.</p> - <h3><a name="l415"></a>415 - Linedef Executor: Run Script</h3> - <p>Runs a script, the same kind of script you can run on level load with the level header - scriptname attribute. The script that will be run should have a lumpname of the form SCR<i>xxyyy</i>, - where <i>xx</i> is the two-digit map number and <i>yyy</i> is the linedef's sector's floor - height in decimal, with leading zeroes as necessary (or 000 if the floor height exceeds - 999 fracunits). For instance, if the linedef is in MAP31 and the floor of its sector is - 337 fracunits, the script named SCR31337 will be run.</p> - <h3><a name="l416"></a>416 - Linedef Executor: Start Adjustable Fire Flicker</h3> - <p>Essentially a copy of linetype <a href="#l603">603</a> that waits to activate until the - linedef executor is triggered. It does have an extra feature, though. If you use a - two-sided linedef with the <a href="#NOCLIMB">NOCLIMB</a> flag, the linedef's back sector - will be used as the maximum light level, allowing you to set the target sector (or - sectors) at a different starting light level entirely.</p> - <h3><a name="l417"></a>417 - Linedef Executor: Start Adjustable Glowing Light</h3> - <p>Essentially a copy of linetype <a href="#l602">602</a> that waits to activate until the - linedef executor is triggered. It does have an extra feature, though. If you use a - two-sided linedef with the <a href="#NOCLIMB">NOCLIMB</a> flag, the linedef's back sector - will be used as the maximum light level, allowing you to set the target sector (or - sectors) at a different starting light level entirely.</p> - <h3><a name="l418"></a>418 - Linedef Executor: Start Adjustable Blinking Light - (unsynchronized)</h3> - <p>Essentially a copy of linetype <a href="#l604">604</a> that waits to activate until the - linedef executor is triggered. It does have an extra feature, though. If you use a - two-sided linedef with the <a href="#NOCLIMB">NOCLIMB</a> flag, the linedef's back sector - will be used as the maximum light level, allowing you to set the target sector (or - sectors) at a different starting light level entirely.</p> - <h3><a name="l419"></a>419 - Linedef Executor: Start Adjustable Blinking Light - (synchronized)</h3> - <p>Essentially a copy of linetype <a href="#l605">605</a> that waits to activate until the - linedef executor is triggered. It does have an extra feature, though. If you use a - two-sided linedef with the <a href="#NOCLIMB">NOCLIMB</a> flag, the linedef's back sector - will be used as the maximum light level, allowing you to set the target sector (or - sectors) at a different starting light level entirely.</p> - <h3><a name="l420"></a>420 - Linedef Executor: Fade Light Level</h3> - <p>When executed, gradually fades the tagged sector's light level to that of the linedef's - front sector. Floor and ceiling light settings done with linetypes <a href="#l601">601</a> - and <a href="#l600">600</a> are not affected or used.</p> - <p>If there is a lighting effect already active in the target sector or sectors at the - time (glow, other fade, strobe, flicker), it will be halted in favor of this one.</p> - <p>Linedef length in fracunits indicates speed. Fading from 224 to 64 with a linedef - length of 4 will take 40 fracunits (224 - 64 = 160, 160 / 4 = 40). There are 35 fracunits - in a second.</p> - <h3><a name="l421"></a>421 - Linedef Executor: Stop Lighting Effect</h3> - <p>Stops any lighting effects active in the tagged sector or sectors: glow, fade, strobe, - flicker, etc. The light level, whatever it is at the moment this script line is run, will - be preserved until a new lighting effect or light level change is used.</p> - <p>Note that the lighting effects will all stop other lighting effects when activated. In - other words, you only need to use this when you really want the lighting effect to stop, - not when you want one effect to stop and another to start.</p> - <h3><a name="l422"></a>422 - Linedef Executor: Cut-Away View</h3> - <p>Cuts away to a view from a different place for a moment. Only works for linedef - executors triggered by a player. Tag the line to a sector with an alt view thing (map - thing type 5007) in it at the proper location with the proper Z and angle. The line length - indicates how long to stay in this view, in tics.</p> - <p>By giving the linedef a <a href="#NOCLIMB">NOCLIMB</a> flag, you can adjust the - vertical viewing angle from the cut-away view. Set the x offset on the linedef's front - side to an integer -90 to 90. In software mode the range of viewing angles is actually - about -68 to 68. This is in degrees.</p> - <h3><a name="l423"></a>423 - Linedef Executor: Change Sky</h3> - <p>Changes sky to the # of the control sector's floorheight. This only affects the player - who activates it. If you'd like it to affect all players, make sure you check the <a - href="#NOCLIMB">NOCLIMB</a> flag.</p> - <h3><a name="l424"></a>424 - Linedef Executor: Change Weather</h3> - <p>Changes weather to the control sector's floorheight in powers of 10.</p> - <p>Example:</p> - <div align="left"><table border="1" width="28%"> - <tr> - <td width="50%">Linedef Length</td> - <td width="50%">Weather Type</td> - </tr> - <tr> - <td width="50%">10</td> - <td width="50%">None</td> - </tr> - <tr> - <td width="50%">20</td> - <td width="50%">Snow</td> - </tr> - <tr> - <td width="50%">30</td> - <td width="50%">Rain</td> - </tr> - <tr> - <td width="50%">40</td> - <td width="50%">Storm</td> - </tr> - </table> - </div><p>(higher numbers reserved for future use)</p> - <p>This only affects the player who activates it. If you'd like it to affect all players, - make sure you check the <a href="#NOCLIMB">NOCLIMB</a> flag.</p> - <h3><a name="l425"></a>425 - Linedef Executor: Change Object State</h3> - <p>Changes the animation frame of the activating object to the state # indicated by the - length of the control linedef. Be careful how you use this.</p> - <h3><a name="l426"></a>426 - Linedef Executor: Stop Object</h3> - <p>Makes the object that triggered the linedef executor stop moving, after being sent to - the center of the sector it's in (only if <a href="#NOCLIMB">NOCLIMB</a> flag is set), on - the floor. Although it comes to a complete stop, the object can begin moving right away - again. If the object is a player, the player will stop jumping, spinning, or anything - else.</p> - <h3><a name="l427"></a>427 - Linedef Executor: Award Score</h3> - <p>Adds to the score of the player who activated it. Control sector's floorheight = points - to award. This even works with negative values.</p> - <h3><a name="l428"></a>428 - Linedef Executor: Start Platform Movement</h3> - <p>Starts a moving platform in the nature of linetype <a href="#l59">59</a> or <a - href="#l60">60</a>. If the <a href="#NOCLIMB">NOCLIMB</a> flag is set, the platform will - begin moving upwards. Otherwise, it will start moving downwards. Speed of movement is set - just like with linetype <a href="#l60">60</a>.</p> - <h3><a name="l429"></a>429 - Linedef Executor: Crush Ceiling Once</h3> - <p>Ceiling moves down to the floor, then back up. Speed is determined by line length - - every 16 units equals 1 FRACUNIT/tic.</p> - <h3><a name="l430"></a>430 - Linedef Executor: Crush Floor Once</h3> - <p>Floor moves up to the ceiling, then back down. Speed is determined by line length - - every 16 units equals 1 FRACUNIT/tic.</p> - <h3><a name="l431"></a>431 - Linedef Executor: Crush Floor And Ceiling Once</h3> - <p>Floor and ceiling meet in the middle and then return, sandwiching anything that's - inbetween. Speed is determined by line length - every 16 units equals 1 FRACUNIT/tic.</p> - <h3><a name="l432"></a>432 - Linedef Executor: Enable 2D Mode</h3> - <p>Turns on 2D mode within the level. You'll probably only want to use this with a zoom - tube or teleport to guarantee that the player is in the correct position when it switches.</p> - <h3><a name="l433"></a>433 - Linedef Executor: Disable 2D Mode</h3> - <p>Turns off 2D mode within the level.</p> - <h3><a name="l434"></a>434 - Linedef Executor: Award Custom Power</h3> - <p>Awards (or removes!) a power to the calling player.</p> - <p>X length: Power Index + 1</p> - <p>Y length: Power Duration (in 35ths of a second)</p> - <h3><a name="l435"></a>435 - Linedef Executor: Change Scroller Direction</h3> - <p>Changes direction of a scroller (conveyor, texture). Also changes speed if this is not - an accelerative/displacement scroller.</p> - <h3><a name="l436"></a>436 - Linedef Executor: Shatter Block</h3> - <p>Shatters a FOF - of any type. Parameters are as follows:</p> - <p>Texture X Offset: Tag # of FOF target sector</p> - <p>Texture Y Offset: Tag # of FOF control sector</p> - <p>Note that the FOF should only have one target sector.</p> - <h3><a name="l437"></a>437 - Linedef Executor: Disable Player Control</h3> - <p>Disables the controls of the player that triggered the linedef executor. If the - <a href="#NOCLIMB">NOCLIMB</a> flag is set, they will be able to jump, however.</p> - <p>Giving the front texture of the linedef an X offset will make the effect last that amount - of time, in tics. Otherwise, it ends immediately, so you would need to use a continuous - trigger.</p> - <h3><a name="l438"></a>438 - Linedef Executor: Set Object's Scale</h3> - <p>Length of this line determines the scale size of an object, in percentage. Note that there is a max of 400%.</p> - <h3><a name="l450"></a>450 - Linedef Executor: Execute Linedef Executor</h3> - <p>Just what it says. Can be used for recursion. Be careful, because you CAN make a loop - out of this that will freeze the game.</p> - <p>Tag is the linedef executor trigger tag to run.</p> - <h3><a name="l488"></a>488 - Linedef Executor: PolyObject - Move by Waypoints</h3> - <p>Moves a polyobject along a sequence of Zoom Tube waypoints.</p> - <p>Texture X offset: Speed (8 = 1 FRACUNIT).</p> - <p>Texture Y offset: Sequence # of Zoom Tube waypoints.</p> - <p>The movement also depends on which linedef flags are set: <ul> - <li><a href="#EFFECT1">EFFECT1</a> : Moves from highest waypoint # to lowest waypoint #.</li> - <li><a href="#EFFECT2">EFFECT2</a> : Comes back the way it came when the end is reached.</li> - <li><a href="#EFFECT3">EFFECT3</a> : Wrap around the waypoints.</li> - <li><a href="#EFFECT4">EFFECT4</a>: Continuously move (used with EFFECT2 or EFFECT3).</li> - </ul> - <p> </p> - </ol> - </li> - <li><u><big><big>Scrollers / Pushers</big></big></u><ol> - <h3><a name="l500"></a>500 - Scroll Wall First Side Left</h3> - <h3><a name="l501"></a>501 - Scroll Wall First Side Opposite Direction</h3> - <h3><a name="l502"></a>502 - Scroll Wall According to Linedef</h3> - <h3><a name="l503"></a>503 - Acc Scroll Wall According to Linedef</h3> - <p>Accelerative scrolling version of <a href="#l502">502</a>.</p> - <h3><a name="l504"></a>504 - Disp Scroll Wall According to Linedef</h3> - <p>Displacement scrolling version of <a href="#l502">502</a>.</p> - <h3><a name="l505"></a>505 - Scroll Texture by Offsets</h3> - <hr> - <h3><a name="l510"></a>510 - Scroll Floor Texture</h3> - <p>Linedef length and direction indicate speed and direction.</p> - <h3><a name="l511"></a>511 - Acc Scroll Floor Texture</h3> - <p>Accelerative scrolling version of <a href="#l510">510</a>.</p> - <h3><a name="l512"></a>512 - Disp Scroll Floor Texture</h3> - <p>Displacement scrolling version of <a href="#l510">510</a>.</p> - <h3><a name="l513"></a>513 - Scroll Ceiling Texture</h3> - <p>Linedef length and direction indicate speed and direction.</p> - <h3><a name="l514"></a>514 - Acc Scroll Ceiling Texture</h3> - <p>Accelerative scrolling version of <a href="#l513">513</a>.</p> - <h3><a name="l515"></a>515 - Disp Scroll Ceiling Texture</h3> - <p>Displacement scrolling version of <a href="#l513">513</a>.</p> - <hr> - <h3><a name="l520"></a>520 - Carry Objects on Floor</h3> - <p>Like linedef type <a href="#l530">530</a>, without scrolling the floor texture, so the - floor doesn't look like it's moving.</p> - <h3><a name="l521"></a>521 - Acc Carry Objects on Floor</h3> - <p>Accelerative scrolling version of <a href="#l520">520</a>.</p> - <h3><a name="l522"></a>522 - Disp Carry Objects on Floor</h3> - <p>Displacement scrolling version of <a href="#l520">520</a>.</p> - <h3><a name="l523"></a>523 - Carry Objects on Ceiling</h3> - <p>For FOF conveyor belts. Like <a href="#l533">533</a>, except without the scrolling to - accompany it.</p> - <h3><a name="l524"></a>524 - Acc Carry Objects on Ceiling</h3> - <p>Accelerative scrolling version of <a href="#l523">523</a>. Untested.</p> - <h3><a name="l525"></a>525 - Disp Carry Objects on Ceiling</h3> - <p>Displacement scrolling version of <a href="#l523">523</a>. Untested.</p> - <hr> - <h3><a name="l530"></a>530 - Scroll Floor Texture and Carry Objects</h3> - <p>Used for conveyor belts, in conjunction with sector type <a href="#s1024">1024</a> - (Conveyor Belt). Linedef length and direction indicate conveyor speed and direction, - respectively. This can also be used to convey items on the underneath of a FOF. See Egg - Rock Zone for an example.</p> - <h3><a name="l531"></a>531 - Acc Scroll Floor Texture and Carry Objects</h3> - <p>Accelerative scrolling version of <a href="#l530">530</a>.</p> - <h3><a name="l532"></a>532 - Disp Scroll Floor Texture and Carry Objects</h3> - <p>Displacement scrolling version of <a href="#l530">530</a>.</p> - <h3><a name="l533"></a>533 - Scroll Ceiling Texture and Carry Objects</h3> - <p>For conveyor belts on the top of FOFs, or for conveying items on a ceiling. Tag this to - the FOF control sector and give the FOF control sector a type of <a href="#s1024">1024</a>, - Conveyor Belt. For realism you might also want to scroll the control sector's floor - texture in the opposite direction (see linetype <a href="#l510">510</a>).</p> - <h3><a name="l534"></a>534 - Acc Scroll Ceiling Texture and Carry Objects</h3> - <p>Accelerative scrolling version of <a href="#l533">533</a>. Untested.</p> - <h3><a name="l535"></a>535 - Disp Scroll Ceiling Texture and Carry Objects</h3> - <p>Displacement scrolling version of <a href="#l533">533</a>. Untested.</p> - <hr> - <h3><a name="l540"></a>540 - Friction</h3> - <p>Linedef lengths greater than 100 indicate slippery ice, while linedef lengths less than - 100 can be used for sludge, with extra friction.</p> - <p>If you want friction on a FOF, tag this line to the control sector of the FOF. - Otherwise, tag it to the sector of desired destination.</p> - <h3><a name="l541"></a>541 - Wind</h3> - <p>Speed and direction are indicated by linedef length and direction. The target sector - should be of type <a href="#s512">512</a>, Wind/Current. If being used in a 3D Floor, put - the 512/768 sector type in the control sector, not the target sector. Also tag the line to - the control sector, and not the target sector.</p> - <p>Special flags:</p> - <p><a href="#NOCLIMB">NOCLIMB</a> -> Only this pusher will affect the object - the - object can't have multiple 'pushings' due to being on the edge of a sector, etc.</p> - <p><a href="#EFFECT4">EFFECT4</a> -> Player will go into slide with limited control - (similar to the water and oil slides in Labyrinth and Oil Ocean).</p> - <h3><a name="l542"></a>542 - Upwards Wind</h3> - <p>The length of the linedef is the wind speed. The target sector will need type <a - href="#s512">512</a> or <a href="#s768">768</a>. If being used in a 3D Floor, put the - 512/768 sector type in the control sector, not the target sector. Also tag the line to the - control sector, and not the target sector.</p> - <p>NOCLIMB/EFFECT4 flags operate the same as for line <a href="#l541">541</a>.</p> - <h3><a name="l543"></a>543 - Downwards Wind</h3> - <p>Wind speed is determined by the linedef's length. Type <a href="#s512">512</a> or <a - href="#s768">768</a> must be applied to the target sector. If being used in a 3D Floor, - put the 512/768 sector type in the control sector, not the target sector. Also tag the - line to the control sector, and not the target sector.</p> - <p>NOCLIMB/EFFECT4 flags operate the same as for line <a href="#l541">541</a>.</p> - <h3><a name="l544"></a>544 - Current</h3> - <p>Speed and direction are indicated by linedef length and direction. The target sector - should have type <a href="#s512">512</a>, Wind/Current. If being used in a 3D Floor, put - the 512/768 sector type in the control sector, not the target sector. Also tag the line to - the control sector, and not the target sector.</p> - <p>NOCLIMB/EFFECT4 flags operate the same as for line <a href="#l541">541</a>.</p> - <h3><a name="l545"></a>545 - Upwards Current</h3> - <p>Linedef length indicates speed. Target sector needs sector type <a href="#s512">512</a> - or <a href="#s768">768</a>. If being used in a 3D Floor, put the 512/768 sector type in - the control sector, not the target sector. Also tag the line to the control sector, and - not the target sector.</p> - <p>NOCLIMB/EFFECT4 flags operate the same as for line <a href="#l541">541</a>.</p> - <h3><a name="l546"></a>546 - Downwards Current</h3> - <p>Speed is indicated by linedef length. Assign a type of <a href="#s512">512</a> or <a - href="#s768">768</a> to the target sector. If being used in a 3D Floor, put the 512/768 - sector type in the control sector, not the target sector. Also tag the line to the control - sector, and not the target sector.</p> - <p>NOCLIMB/EFFECT4 flags operate the same as for line <a href="#l541">541</a>.</p> - <h3><a name="l547"></a>547 - Boom Push/Pull Thing</h3> - <p>Creates a "point pusher," or a point that pushes you away or pulls you toward - it if you get close enough. Tag the linedef to a sector with type <a href="#s512">512</a>, - Wind/Current, and with a thing on it of type 5001 (push) or 5002 (pull). The control - linedef's length indicates pushing/pulling strength; if length is L, the effect fades away - to nothing when you are 2L away from the point.</p> - <p>If you want to create multiple point pushers/pullers, you'll need to have them in - different target sectors, but they can share the same tag.</p> - <p>NOCLIMB/EFFECT4 flags operate the same as for line <a href="#l541">541</a>.</p> - <p> </p> - </ol> - </li> - <li><u><big><big>Lighting</big></big></u><ol> - <h3><a name="l600"></a>600 - Floor Lighting</h3> - <p>Sets the lighting for the floor only. The control sector's light value will be used for - the target sector's floor. Also see type <a href="#l601">601</a>.</p> - <h3><a name="l601"></a>601 - Ceiling Lighting</h3> - <p>Sets the lighting of the ceiling only. The light value of the control sector will be - used for the target sector's ceiling. Also see type <a href="#l600">600</a>.</p> - <h3><a name="l602"></a>602 - Adjustable Pulsating Light</h3> - <p>Linedef length indicates glow speed. The normal speed would be a linedef 32 units long.</p> - <p>The control sector (the linedef's front sector) is used to get what will be the minimum - light level for this effect, while the target sector's light level ends up being the - maximum.</p> - <h3><a name="l603"></a>603 - Adjustable Flickering Light</h3> - <p>Linedef length indicates flicker speed. Normal speed would be a 16 fracunit long - linedef. A longer linedef means more time in between flickers.</p> - <p>The control sector (the linedef's front sector) is used to get what will be the minimum - light level for this effect, while the target sector's light level ends up being the - maximum.</p> - <h3><a name="l604"></a>604 - Adjustable Blinking Light (unsynchronized)</h3> - <p>Line's X length is time for the light to be off, and Y length is the time for the light - to be on.</p> - <p>The control sector (the linedef's front sector) is used to get what will be the minimum - light level for this effect, while the target sector's light level ends up being the - maximum.</p> - <h3><a name="l605"></a>605 - Adjustable Blinking Light (synchronized)</h3> - <p>Line's X length is time for the light to be off, and Y length is the time for the light - to be on.</p> - <p>The control sector (the linedef's front sector) is used to get what will be the minimum - light level for this effect, while the target sector's light level ends up being the - maximum.</p> - <h3><a name="l606"></a>606 - Colormap</h3> - <p>Sets a colormap. Tag the linedef to the sector or sectors affected by the colormap. The - control linedef's front Above texture is used to determine the colormap. The format is - #rrggbba, where rr, gg, and bb are two hexadecimal digits for determining each color: red, - blue, and green. The a stands for alpha, and is a number or letter indicating the - translucency; from A-Z and 0-9, with A being most transparent and 9 being most opaque.</p> - <p>It does not generally matter what sector the colormap linedef belongs to. However, it - should not belong to the same sector as another colormap, as this can cause problems.</p> - </ol> - </li> - <h1><a name="sectortypes"></a>Sector Types</h1> - <p>You can apply up to four different types to one sector, provided that you only choose - ONE from EACH category. Add the numbers together to obtain the final value to use in level - editors.</p> - <li><u><big><big>Section 1</big></big></u><ol> - <h3><a name="s1"></a>1 - Damage (Generic)</h3> - <p>This special hurts, period. It doesn't matter whether you have a liquid shield, fire - shield, attraction shield, or whatever else; step on one of these and suffer.</p> - <h3><a name="s2"></a>2 - Damage (Water)</h3> - <p>Also known as Slime Hurt. Stepping here will be painful, as in shield/ring/life loss - (depending on how you are equipped), unless you happen to have the liquid shield.</p> - <h3><a name="s3"></a>3 - Damage (Fire)</h3> - <p>Stepping here will hurt, unless you happen to have a fire shield.</p> - <h3><a name="s4"></a>4 - Damage (Electrical)</h3> - <p>Hurts players whenever they're in the sector, unless they have the attraction shield.</p> - <p>Usage tip: Give the sector a floor flat that looks electrical and looks like it could - hurt you. </p> - <h3><a name="s5"></a>5 - Spikes</h3> - <p>Making spikes using sectors is rather tedious and difficult. You can use things instead - (<a href="#t523">Floor Spike</a> and <a href="#t522">Ceiling Spike</a>). But the sector - version DOES look cooler. ;)</p> - <h3><a name="s6"></a>6 - Death Pit (Camera Modifications)</h3> - <p>Used for bottomless pits. You'll probably want the sector's floor flat to be either - F_SKY1 (falling from the sky) or PIT (falling into a pit of complete blackness). The - camera modifications keep the camera from following you all the way down, for a Sonic - Adventure-style pit death. If you don't like the camera modifications, use sector type <a - href="#s7">5</a>.</p> - <h3><a name="s7"></a>7 - Death Pit (No Camera Modifications)</h3> - <p>For bottomless pits. Use if the camera modifications of sector type <a href="#s6">6</a> - are not to your taste.</p> - <h3><a name="s8"></a>8 - Instant Kill</h3> - <p>Die right away if you even step into this sector. No need to touch the floor as with - those sissy death pits.</p> - <h3><a name="s9"></a>9 - Ring Drainer (Floor Touch)</h3> - <p>Lose one ring per 15 tics while touching the floor.</p> - <h3><a name="s10"></a>10 - Ring Drainer (No Floor Touch)</h3> - <p>Like sector type <a href="#s9">9</a>, but doesn't require touching floor.</p> - <h3><a name="s11"></a>11 - Special Stage Damage</h3> - <p>If you have rings and no shield, and you step on it, you only lose 10 rings, maximum. - It's just like the special stages!</p> - <h3><a name="s12"></a>12 - Space Countdown</h3> - <p>In space, you have no chance to survive make your time, ha ha ha. Starts an immediate - five-second countdown, like when you drown.</p> - <h3><a name="s13"></a>13 - Ramp Sector</h3> - <p>Doubles the step-up height of the player. Default step-up height is 24 fracunits, but - with this, it becomes 48. Useful for steps and other things if your players seem to be - getting 'stopped' by the stairs while moving quickly.</p> - <h3><a name="s14"></a>14 - Non-Ramp Sector (Don't step down)</h3> - <p>Removes the 'step-down' that a player will normally do when moving to a nearby sector.</p> - <h3><a name="s15"></a>15 - Bouncy Sector (FOF Control Only)</h3> - <p>Use this on a 3D floor's control sector to make it bouncy. Players will bounce off the - top of it. If the 3D floor's control line has the BOUNCY flag set, the linedef length sets - the minimum bounce force. Otherwise, you will slowly come to a stop.</p> - <p> </p> - </ol> - </li> - <li><u><big><big><a name="sCat2"></a>Section 2</big></big></u><ol> - <h3><a name="s16"></a>16 - Trigger Linedef Executor (Pushable Objects)</h3> - <p>Works like <a href="#s80">80</a> but with a pushable object (gargoyle or snowman) - touching the floor rather than a player.</p> - <h3><a name="s32"></a>32 - Trigger Linedef Executor (Anywhere in Sector) (All Players)</h3> - <p>Sector type <a href="#s64">64</a> with the added requirement that all players who don't - have a game over need to be in the sector, not just one player. Currently does not work in - FOFs.</p> - <h3><a name="s48"></a>48 - Trigger Linedef Executor (Floor Touch) (All Players)</h3> - <p>Sector type <a href="#s80">80</a> with the added requirement that all players who don't - have a game over need to be in the sector, not just one player.</p> - <h3><a name="s64"></a>64 - Trigger Linedef Executor (Anywhere in Sector)</h3> - <p>Like sector type <a href="#s80">80</a>, but you don't have to be touching the floor to - do the triggering. You could be flying high in the air. You should also use this one for - linedef executors triggered by FOFs.</p> - <h3><a name="s80"></a>80 - Trigger Linedef Executor (Floor Touch)</h3> - <p>Required for any of the <a href="#ltriggers">Linedef Executor Triggers</a> to work in - the sector.</p> - <h3><a name="s96"></a>96 - Trigger Linedef Executor (Emerald Check)</h3> - <p>Sector type <a href="#s64">64</a> which will only execute if you have all 7 chaos - emeralds.</p> - <h3><a name="s112"></a>112 - Trigger Linedef Executor (NiGHTS Mare)</h3> - <p>Like sector type <a href="#s64">64</a>, but this is only triggered if you are in a - NiGHTS map, and checks what mare you're on using the following format, depending on what - flags you have set for this line:</p> - <p>No flags -> Runs if (current mare = line length)</p> - <p><a href="#NOCLIMB">NOCLIMB</a> -> Runs if (current mare <= line length)</p> - <p><a href="#BLOCKMONSTERS">BLOCKMONSTERS</a> -> Runs if (current mare >= line - length)</p> - <h3><a name="s128"></a>128 - Check for linedef executor on 3D Floors (ANY object)</h3> - <p>For any item to detect sector type <a href="#l16">16</a> on a 3D floor, the target - sector on the map must have this type. This allows you to have any kind of object trigger - a linedef executor.</p> - <h3><a name="s144"></a>144 - Egg Trap Capsule</h3> - <h3><a name="s160"></a>160 - Special Stage Time/Rings, Par</h3> - <p>For special stages, floor height is time limit in seconds, and ceiling height is rings - required in seconds. If the ceiling height is 0, there is no ring requirement, only a time - limit to find an exit.</p> - <h3><a name="s176"></a>176 - Custom Global Gravity</h3> - <p>Floor height sets global gravity. 500 is normal. 1000 is twice the normal gravity, 250 - is half. You can also set per-sector gravity with linetype <a href="#l1">1</a>. This can - also be adjusted in realtime, for some really cool effects.</p> - <p> </p> - </ol> - </li> - <li><u><big><big>Section 3</big></big></u><ol> - <h3><a name="s256"></a>256 - Ice/Sludge</h3> - <p>See linedef type <a href="#l540">540</a>.</p> - <h3><a name="s512"></a>512 - Wind/Current</h3> - <p>See linedef types <a href="#l541">541</a> and <a href="#l544">544</a>.</p> - <h3><a name="s768"></a>768 - Ice/Sludge and Wind/Current</h3> - <p>Combination of sector specials 256 and 512.</p> - <h3><a name="s1024"></a>1024 - Conveyor Belt</h3> - <p>See linedef type <a href="#l520">520</a>.</p> - <h3><a name="s1280"></a>1280 - Speed Pad (No Spin)</h3> - <p>See linedef type <a href="#l4">4</a>.</p> - <h3><a name="s1536"></a>1536 - Speed Pad (Spin)</h3> - <p>See linedef type <a href="#l4">4</a>. This type of speed pad forces you into a spin.</p> - <h3><a name="s1792"></a>1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840 - Bustable - Block Sprite Parameter</h3> - <p>Used in a control sector of a bustable block. Chooses which debris sprite to spawn.</p> - <p>1792 = ROIA</p> - <p>2048 = ROIB</p> - <p>2304 = ROIC</p> - <p>2560 = ROID</p> - <p>2816 = ROIE</p> - <p>3072 = ROIF</p> - <p>3328 = ROIG</p> - <p>3584 = ROIH</p> - <p>3840 = ROII</p> - <p> </p> - </ol> - </li> - <li><u><big><big>Section 4</big></big></u><ol> - <h3><a name="s4096"></a>4096 - Starpost Activator</h3> - <p>Whenever a player steps in the sector, a starpost in that sector will be searched for - and, if found, activated.</p> - <h3><a name="s8192"></a>8192 - Special Stage Goal</h3> - <p>This is like the "GOAL" buttons in Sonic 1's special stages. Ends the special - stage when stepped on.</p> - <h3><a name="s8192a"></a>8192 - Exit Sector</h3> - <p>In single-player, cooperative, or race mode, being in this sector ends the level. You - don't necessarily have to be touching the floor. (If you want the player to have to be - touching the floor, you can use linedef type <a href="#l223">223</a>, an invisible, - intangible FOF, to do the trick. Give the FOF control sector a type of <a href="#s8192">8192</a>.)</p> - <p>See linedef type <a href="#l2">2</a> for a way to exit to any map, not just the one - whose number is specified in the map header. Linedef 2 also allows you to skip the score - tally screen.</p> - <h3><a name="s8192b"></a>8192 - No Tag Zone</h3> - <p>In games of tag, this sector is a safe spot. You cannot be tagged while in it.</p> - <h3><a name="s8192c"></a>8192 - CTF: Flag Return</h3> - <p>In CTF, if the red or blue flag enters this sector, it will automatically return to - base, much like how it behaves when it falls in a pit. This can also be set as a special - on a 3D floor.</p> - <h3><a name="s12288"></a>12288 - CTF: Red Team Base</h3> - <p>The red team has to bring the <a href="#t307">blue flag</a> onto this sector to score. - It's generally a good idea to have the <a href="#t306">red flag</a> here and the <a - href="#t34">red team player starts</a> somewhere close by.</p> - <h3><a name="s16384"></a>16384 - CTF: Blue Team Base</h3> - <p>The blue team has to bring the <a href="#t306">red flag</a> onto this sector to score. - It's generally a good idea to have the <a href="#t307">blue flag</a> here and the <a - href="#t35">blue team player starts</a> somewhere close by.</p> - <h3><a name="s20480"></a>20480 - Fan Sector</h3> - <p>Acts like a fan, pushing the player up at constant speed and activating the proper - animation. Can be used on intangible FOFs.</p> - <h3><a name="s24576"></a>24576 - Super Sonic Transform</h3> - <p>Transforms you into Super Sonic and gives you 50 rings, providing you have all of the - chaos emeralds.</p> - <h3><a name="s28672"></a>28672 - Spinner</h3> - <p>Forces the player into a spin.</p> - <h3><a name="s32768"></a>32768 - Zoom Tube Start</h3> - <p>When the player touches this sector, a line type <a href="#l3">3</a> with the same tag - as the sector is searched for, and if found, the line's X length determines the speed at - which the tube operates, while its Y length determines which zoom tube sequence to use. - Then the player is immediately put into a spin, loses control, and gravitates toward the - first Zoom Tube Waypoint (thing type <a href="#t753">753</a>), which does not have to be - in the same sector. Once they reach the first waypoint, they begin traveling to the 2nd, - 3rd, and so on, until the last waypoint is reached.</p> - <p>This can be used with Floor-Over-Floors, just use these specials in the control sector - instead. </p> - <h3><a name="s36864"></a>36864 - Zoom Tube End</h3> - <p>Just like sector type <a href="#s32768">32768</a>, but starts from the last waypoint - and goes to the first.</p> - <h3><a name="s40960"></a>40960 - Finish Line</h3> - <p>The finish line for a race circuit. This increments a lap when you pass it, after - hitting all the star posts in the stage in sequential order. Once the number of laps - specified by the server is reached, the level is completed.</p> - </ol> - </li> -</ul> -</body> -</html> diff --git a/doc/specs/udmf_srb2.txt b/doc/specs/udmf_srb2.txt new file mode 100644 index 0000000000000000000000000000000000000000..eaa3a8a9704439b72569aee0a0c4db956e8d8482 --- /dev/null +++ b/doc/specs/udmf_srb2.txt @@ -0,0 +1,316 @@ +=============================================================================== +Universal Doom Map Format Sonic Robo Blast 2 extensions v1.0 19.06.2024 + + Copyright (c) 2024 Sonic Team Junior + uses Universal Doom Map Format Specification v1.1 as a template, + original document Copyright (c) 2009 James Haley. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.2 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + +=============================================================================== + +This document discusses the UDMF implementation found in Sonic Robo Blast 2's engine. + +======================================= +I. Grammar / Syntax +======================================= + + No changes. + +======================================= +II. Implementation Semantics +======================================= + +------------------------------------ +II.A : Storage and Retrieval of Data +------------------------------------ + + No changes. + +----------------------------------- +II.B : Storage Within Archive Files +----------------------------------- + + No changes. + +-------------------------------- +II.C : Implementation Dependence +-------------------------------- + +The SRB2 engine only supports the following namespace: + "srb2" + +The engine is allowed to refuse maps with an unsupported namespace, +or emit a warning. + +======================================= +III. Standardized Fields +======================================= + +The SRB2 engine ignores any user-defined fields. +All boolean fields default to false unless mentioned otherwise. + +Sonic Robo Blast 2 defines the following standardized fields: + + vertex + { + x = <float>; // X coordinate. No valid default. + y = <float>; // Y coordinate. No valid default. + zfloor = <float>; // Floor height at this vertex. Only applies to triangular sectors + zceiling = <float>; // Ceiling height at this vertex. Only applies to triangular sectors + } + + linedef + { + id = <integer>; // ID of line. Interpreted as tag. + moreids = <string>; // Additional line IDs, specified as a space separated list of numbers (e.g. "2 666 1003 4505") + + v1 = <integer>; // Index of first vertex. No valid default. + v2 = <integer>; // Index of second vertex. No valid default. + + blocking = <bool>; // Line blocks things. + blockmonsters = <bool>; // Line blocks enemies. + twosided = <bool>; // Line is 2S. + dontpegtop = <bool>; // Upper texture unpegged. + dontpegbottom = <bool>; // Lower texture unpegged. + skewtd = <bool>; // Upper and lower textures are skewed. + noclimb = <bool>; // Line is not climbable. + noskew = <bool>; // Middle texture is not skewed. + midpeg = <bool>; // Middle texture is pegged. + midsolid = <bool>; // Middle texture is solid. + wrapmidtex = <bool>; // Line's mid textures are wrapped. + nonet = <bool>; // Special only takes effect in singleplayer games. + netonly = <bool>; // Special only takes effect in multiplayer games. + bouncy = <bool>; // Line is bouncy. + transfer = <bool>; // In 3D floor sides, uses the sidedef properties of the control sector. + + alpha = <float>; // Translucency of this line. Default is 1.0 + renderstyle = <string>; // Render style. Can be: + // - "translucent" + // - "add" + // - "subtract" + // - "reversesubtract" + // - "modulate" + // - "fog" + // Default is "translucent". + + special = <integer>; // Linedef action. Default = 0. + arg0 = <integer>; // Argument 0. Default = 0. + arg1 = <integer>; // Argument 1. Default = 0. + arg2 = <integer>; // Argument 2. Default = 0. + arg3 = <integer>; // Argument 3. Default = 0. + arg4 = <integer>; // Argument 4. Default = 0. + arg5 = <integer>; // Argument 5. Default = 0. + arg6 = <integer>; // Argument 6. Default = 0. + arg7 = <integer>; // Argument 7. Default = 0. + arg8 = <integer>; // Argument 8. Default = 0. + arg9 = <integer>; // Argument 9. Default = 0. + stringarg0 = <string>; // String argument 0. + stringarg1 = <string>; // String argument 1. + + sidefront = <integer>; // Sidedef 1 index. No valid default. + sideback = <integer>; // Sidedef 2 index. Default = -1. + + comment = <string>; // A comment. Implementors should attach no special + // semantic meaning to this field. + } + + sidedef + { + offsetx = <integer>; // X offset. Default = 0. + offsety = <integer>; // Y offset. Default = 0. + + texturetop = <string>; // Upper texture. Default = "-". + texturebottom = <string>; // Lower texture. Default = "-". + texturemiddle = <string>; // Middle texture. Default = "-". + + repeatcnt = <integer>; // Number of middle texture repetitions. Default = 0. + + sector = <integer>; // Sector index. No valid default. + + scalex_top = <float>; // X scale for upper texture. Default = 1.0. + scaley_top = <float>; // Y scale for upper texture. Default = 1.0. + scalex_mid = <float>; // X scale for mid texture. Default = 1.0. + scaley_mid = <float>; // Y scale for mid texture. Default = 1.0. + scalex_bottom = <float>; // X scale for lower texture. Default = 1.0. + scaley_bottom = <float>; // Y scale for lower texture. Default = 1.0. + offsetx_top = <float>; // X offset for upper texture. Default = 0.0. + offsety_top = <float>; // Y offset for upper texture. Default = 0.0. + offsetx_mid = <float>; // X offset for mid texture. Default = 0.0. + offsety_mid = <float>; // Y offset for mid texture. Default = 0.0. + offsetx_bottom = <float>; // X offset for lower texture. Default = 0.0. + offsety_bottom = <float>; // Y offset for lower texture. Default = 0.0. + + light = <integer>; // Light level, relative to 'sector' light level. Default = 0. + lightabsolute = <bool>; // true = 'light' is an absolute value, ignoring 'sector' light level. + + comment = <string>; // A comment. Implementors should attach no special + // semantic meaning to this field. + } + + sector + { + heightfloor = <integer>; // Floor height. Default = 0. + heightceiling = <integer>; // Ceiling height. Default = 0. + + texturefloor = <string>; // Floor flat. No valid default. + textureceiling = <string>; // Ceiling flat. No valid default. + + lightlevel = <integer>; // Light level. Default = 255. + lightfloor = <integer>; // The floor's light level. Default is 0. + lightceiling = <integer>; // The ceiling's light level. Default is 0. + lightfloorabsolute = <bool>; // true = 'lightfloor' is an absolute value. Default is + // relative to the owning sector's light level. + lightceilingabsolute = <bool>; // true = 'lightceiling' is an absolute value. Default is + // relative to the owning sector's light level. + + special = <integer>; // Sector special. Default = 0. + id = <integer>; // Sector tag/id. Default = 0. + moreids = <string>; // Additional sector IDs/tags, specified as a space separated list of numbers (e.g. "2 666 1003 4505") + + xpanningfloor = <float>; // X texture offset of floor texture. Default = 0.0. + ypanningfloor = <float>; // Y texture offset of floor texture. Default = 0.0. + xpanningceiling = <float>; // X texture offset of ceiling texture. Default = 0.0. + ypanningceiling = <float>; // Y texture offset of ceiling texture. Default = 0.0. + xscalefloor = <float>; // X texture scale of floor texture. Default = 1.0. + yscalefloor = <float>; // Y texture scale of floor texture. Default = 1.0. + xscaleceiling = <float>; // X texture scale of ceiling texture. Default = 1.0. + yscaleceiling = <float>; // Y texture scale of ceiling texture. Default = 1.0. + rotationfloor = <float>; // Rotation of floor texture in degrees. Default = 0.0. + rotationceiling = <float>; // Rotation of ceiling texture in degrees. Default = 0.0. + ceilingplane_a = <float>; // Define the plane equation for the sector's ceiling. Default is a horizontal plane at 'heightceiling'. + ceilingplane_b = <float>; // 'heightceiling' will still be used to calculate texture alignment. + ceilingplane_c = <float>; // The plane equation will only be used if all 4 values are given. + ceilingplane_d = <float>; // The plane is defined as a*x + b*y + c*z + d = 0 with the normal vector pointing downward. + floorplane_a = <float>; // Define the plane equation for the sector's floor. Default is a horizontal plane at 'heightfloor'. + floorplane_b = <float>; // 'heightfloor' will still be used to calculate texture alignment. + floorplane_c = <float>; // The plane equation will only be used if all 4 values are given. + floorplane_d = <float>; // The plane is defined as a*x + b*y + c*z + d = 0 with the normal vector pointing upward. + + lightcolor = <integer>; // Sector's light color as RRGGBB value. Default = 0x000000. + lightalpha = <integer>; // Sector's light opacity. Default = 25. + fadecolor = <integer>; // Sector's fog color as RRGGBB value. Default = 0x000000. + fadealpha = <integer>; // Sector's fog opacity. Default = 25. + fadestart = <integer>; // Sector's fading range start. Default = 0. + fadeend = <integer>; // Sector's fading range end. Default = 31. + colormapfog = <bool>; // Sector's colormap uses fog lighting. + colormapfadesprites = <bool>; // Sector's colormap affects full-bright sprites. + colormapprotected = <bool>; // Sector's colormap is not affected by colormap change specials. + + flipspecial_nofloor = <bool>; // Trigger effects that require a plane touch are not executed when the floor is touched. + flipspecial_ceiling = <bool>; // Trigger effects that require a plane touch are executed when the ceiling is touched. + triggerspecial_touch = <bool>; // Trigger effects are executed anywhere in the sector. + triggerspecial_headbump = <bool>; // Trigger effects are executed if the top of the triggerer object touches a plane. + triggerline_plane = <bool>; // Trigger effects require a plane touch to be executed. + triggerline_mobj = <bool>; // Trigger effects can be executed by non-pushable objects. + + invertprecip = <bool>; // Inverts the precipitation effect; if the sector is considered to be indoors, + // precipitation is generated, and if the sector is considered to be outdoors, + // precipitation is not generated. + gravityflip = <bool>; // Sector flips any objects in it, if the sector has negative gravity. + heatwave = <bool>; // Sector has the heat wave effect. + noclipcamera = <bool>; // Sector is not tangible to the camera. + outerspace = <bool>; // Sector has the space countdown effect. + doublestepup = <bool>; // Sector has half the vertical height needed for objects to walk into it. + nostepdown = <bool>; // Sector has the staircase effect disabled. + speedpad = <bool>; // Sector is a speed pad. + starpostactivator = <bool>; // Sector activates any Star Posts in it when walked into by a plyer. + exit = <bool>; // Sector is an exit sector. + specialstagepit = <bool>; // Sector is a Special Stage pit. + returnflag = <bool>; // Sector returns any Capture the Flag flags that come in contact with it to their respective bases. + redteambase = <bool>; // Sector is a Red Team base. + blueteambase = <bool>; // Sector is Blue Team base. + fan = <bool>; // Sector is a fan sector. + supertransform = <bool>; // Sector transforms any players that come in contact with it into their 'super' mode. + forcespin = <bool>; // Sector forces any players that come in contact with it to roll. + zoomtubestart = <bool>; // Sector is the starting point of a zoom tube path. + zoomtubeend = <bool>; // Sector is the ending point of a zoom tube path. + finishline = <bool>; // Sector is a Circuit finish line. + ropehang = <bool>; // Sector is a rope hang. Must be applied to a 3D floor. + jumpflip = <bool>; // Sector flips the gravity of players who jump from it. + gravityoverride = <bool>; // Reverse gravity effect is only applied when an object is in the sector. + nophysics_floor = <bool>; // Disables floor slope physics if created through a plane equation. + nophysics_ceiling = <bool>; // Disables ceiling slope physics if created through a plane equation. + + friction = <float>; // Sector's friction factor. + gravity = <float>; // Sector's gravity. Default is 1.0. + damagetype = <integer>; // Damage type for sector damage. Can be: + // - "None" + // - "Generic" + // - "Water" + // - "Fire" + // - "Lava" + // - "Electric" + // - "Spike" + // - "DeathPitTilt" + // - "DeathPitNoTilt" + // - "Instakill" + // - "SpecialStage" + // Default = "None". + triggertag = <integer>; // Tag to trigger when this sector is entered. Default = 0. + triggerer = <string>; // Who can execute the trigger tag when this sector is entered. Can be: + // - "Player" + // - "AllPlayers" + // - "Mobj" + // Default = "Player". + + comment = <string>; // A comment. Implementors should attach no special + // semantic meaning to this field. + } + + thing + { + id = <integer>; // Thing ID. Default = 0. + moreids = <string>; // Additional thing IDs, specified as a space separated list of numbers (e.g. "2 666 1003 4505") + + x = <float>; // X coordinate. No valid default. + y = <float>; // Y coordinate. No valid default. + + height = <float>; // Z height relative to floor. + // Relative to ceiling if flip = true. + // Absolute if absolutez = true. + // Default = 0. + + angle = <integer>; // Map angle of thing in degrees. Default = 0 (East). + pitch = <integer>; // Pitch of thing in degrees. Default = 0 (horizontal). + roll = <integer>; // Roll of thing in degrees. Default = 0. + scalex = <float>; // Horizontal visual scaling on thing. Default = 1.0. + scaley = <float>; // Vertical visual scaling on thing. Default = 1.0. + scale = <float>; // Vertical and horizontal visual scaling on thing. Default = 1.0. + mobjscale = <float>; // Physical scale of the thing. Default = 1.0. + + type = <integer>; // Thing type. No valid default. + + flip = <bool>; // Thing spawns flipped, on the ceiling. + absolutez = <bool>; // If true, the thing height is absolute, instead of being relative to the floor or ceiling. + + arg0 = <integer>; // Argument 0. Default = 0. + arg1 = <integer>; // Argument 1. Default = 0. + arg2 = <integer>; // Argument 2. Default = 0. + arg3 = <integer>; // Argument 3. Default = 0. + arg4 = <integer>; // Argument 4. Default = 0. + arg5 = <integer>; // Argument 5. Default = 0. + arg6 = <integer>; // Argument 6. Default = 0. + arg7 = <integer>; // Argument 7. Default = 0. + arg8 = <integer>; // Argument 8. Default = 0. + arg9 = <integer>; // Argument 9. Default = 0. + stringarg0 = <string>; // String argument 0. + stringarg1 = <string>; // String argument 1. + + comment = <string>; // A comment. Implementors should attach no special + // semantic meaning to this field. + } + + +======================================= +Changelog +======================================= + +1.0: 19.02.2024 +Initial version. + +=============================================================================== +EOF +=============================================================================== \ No newline at end of file diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg index 41ad998891154f56fe850cdfe457a48189dd648f..7ef5ab1e170dcb00041a0a341a8d7a82da0072d2 100644 --- a/extras/conf/SRB2-22.cfg +++ b/extras/conf/SRB2-22.cfg @@ -41,7 +41,7 @@ linetagindicatesectors = true; // The format interface handles the map data format - DoomMapSetIO for SRB2DB2, SRB2MapSetIO for Zone Builder formatinterface = "SRB2MapSetIO"; - + //Maximum safe map size check (0 means skip check) safeboundary = 0; @@ -502,7 +502,7 @@ gen_sectortypes { 0 = "Normal"; 512 = "Wind/Current <deprecated>"; - 1024 = "Conveyor Belt <deprecated>"; + 1024 = "Conveyor Belt <deprecated>"; 1280 = "Speed Pad"; 1536 = "Flip Gravity on Jump"; } @@ -3730,7 +3730,7 @@ thingtypes 3328 = "3D Mode Start"; } - + starts { color = 1; // Blue diff --git a/extras/conf/udb/Includes/SRB222_common.cfg b/extras/conf/udb/Includes/SRB222_common.cfg index 8f37aabaa41de4072ede5b6910666fb654d7cfd0..9bf882f56a11346709b7c7c263e37dd86ffad173 100644 --- a/extras/conf/udb/Includes/SRB222_common.cfg +++ b/extras/conf/udb/Includes/SRB222_common.cfg @@ -39,8 +39,11 @@ common defaulttexturescale = 1.0f; defaultflatscale = 1.0f; scaledtextureoffsets = true; + scaledflatoffsets = true; + // Colormap/fade related options maxcolormapalpha = 25; + // TODO: change to 255; // Thing number for start position in 3D Mode start3dmode = 3328; @@ -93,18 +96,30 @@ 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; + + // Enables support for individual offsets of upper/middle/lower sidedef textures localsidedeftextureoffsets = true; - distinctfloorandceilingbrightness = true; - + + // Enables support for plane equation slopes planeequationsupport = true; + // Enables support for vertex heights + vertexheightsupport = true; + + // Enables setting distinct brightness for floor, ceiling, and walls + distinctfloorandceilingbrightness = true; + distinctwallbrightness = true; + + // Enables setting distinct brightness for upper, middle, and lower sidedef parts + distinctsidedefpartbrightness = false; + // Special linedefs include("SRB222_misc.cfg", "speciallinedefs_udmf"); @@ -180,4 +195,4 @@ mapformat_udmf { include("SRB222_linedefs.cfg", "udmf"); } -} \ No newline at end of file +} diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index 152cafe211fe27ae8b2169e7fe795c253e8fb182..ce1979581fb7e1251ad76882154eab80ec204f06 100644 --- a/extras/conf/udb/Includes/SRB222_linedefs.cfg +++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg @@ -7,13 +7,11 @@ udmf 0 { title = "None"; - prefix = "(0)"; } 6 { title = "Sector Set Portal"; - prefix = "(6)"; arg0 { title = "Target sector tag"; @@ -52,7 +50,6 @@ udmf 7 { title = "Sector Flat Alignment"; - prefix = "(7)"; arg0 { title = "Target sector tag"; @@ -70,7 +67,6 @@ udmf 10 { title = "Culling Plane"; - prefix = "(10)"; arg0 { title = "Target sector tag"; @@ -91,19 +87,17 @@ udmf 40 { title = "Visual Portal Between Tagged Linedefs"; - prefix = "(40)"; } 41 { title = "Horizon Effect"; - prefix = "(41)"; + id = "srb2_horizonline"; } 63 { title = "Fake Floor/Ceiling Planes"; - prefix = "(63)"; arg0 { title = "Target sector tag"; @@ -119,7 +113,6 @@ udmf 2 { title = "Custom Exit"; - prefix = "(2)"; arg0 { title = "Next map"; @@ -143,14 +136,15 @@ udmf 3 { title = "Zoom Tube Parameters"; - prefix = "(3)"; arg0 { title = "Speed"; + tooltip = "In fracunits per tic."; } arg1 { - title = "Sequence"; + title = "Waypoint sequence"; + tooltip = "The sequence number of (zoom tube) waypoints to use."; } arg2 { @@ -163,10 +157,10 @@ udmf 4 { title = "Speed Pad Parameters"; - prefix = "(4)"; arg0 { title = "Speed"; + tooltip = "In fracunits per tic."; } arg1 { @@ -182,13 +176,13 @@ udmf { title = "Sound"; type = 2; + tooltip = "Takes a DS constant.\nExample: DSTHOK"; } } 8 { title = "Set Camera Collision Planes"; - prefix = "(8)"; arg0 { title = "Target sector tag"; @@ -199,14 +193,15 @@ udmf 11 { title = "Rope Hang Parameters"; - prefix = "(11)"; arg0 { title = "Speed"; + tooltip = "In fracunits per tic."; } arg1 { - title = "Sequence"; + title = "Waypoint sequence"; + tooltip = "The sequence number of (zoom tube) waypoints to use."; } arg2 { @@ -219,14 +214,13 @@ udmf 14 { title = "Bustable Block Parameters"; - prefix = "(14)"; arg0 { title = "Debris spacing"; } arg1 { - title = "Debris lifetime"; + title = "Debris lifetime (tics)"; } arg2 { @@ -237,6 +231,7 @@ udmf stringarg0 { title = "Debris object type"; + tooltip = "Uses a MT_ constant.\nExample: MT_ROCKCRUMBLE16\nDefaults to MT_ROCKCRUMBLE1."; type = 2; } } @@ -244,13 +239,11 @@ udmf 15 { title = "Fan Particle Generator Heights"; - prefix = "(15)"; } 16 { title = "Minecart Parameters"; - prefix = "(16)"; arg0 { title = "Order"; @@ -260,7 +253,6 @@ udmf 64 { title = "Continuously Appearing/Disappearing FOF"; - prefix = "(64)"; arg0 { title = "Control linedef tag"; @@ -298,21 +290,21 @@ udmf 20 { - title = "First Line"; - prefix = "(20)"; + title = "PolyObject First Line"; arg0 { - title = "PolyObject ID"; + title = "PolyObject tag"; type = 14; } arg1 { - title = "Parent ID"; + title = "Parent PolyObject tag"; type = 14; } arg2 { - title = "Translucency"; + title = "Translucency level"; + tooltip = "Ranges from 0 (fully opaque) to 10 (fully transparent)."; } arg3 { @@ -338,45 +330,45 @@ udmf 30 { - title = "Waving Flag"; - prefix = "(30)"; + title = "Waving PolyObject Flag"; arg0 { - title = "PolyObject ID"; + title = "PolyObject tag"; type = 14; } arg1 { title = "Speed"; + tooltip = "In fracunits per tic."; } arg2 { title = "Distance"; + tooltip = "How far to move in either direction, in fracunits."; } } 31 { - title = "Displacement by Front Sector"; - prefix = "(31)"; + title = "Move PolyObject by Front Sector Displacement"; arg0 { - title = "PolyObject ID"; + title = "PolyObject tag"; type = 14; } arg1 { title = "Base speed"; + tooltip = "How much the front sector displacement translates.\nA value of 256 amounts to a 1:1 translation."; } } 32 { - title = "Angular Displacement by Front Sector"; - prefix = "(32)"; + title = "Rotate PolyObject by Front Sector Displacement"; arg0 { - title = "PolyObject ID"; + title = "PolyObject tag"; type = 14; } arg1 @@ -409,10 +401,10 @@ udmf 52 { title = "Continuously Falling Sector"; - prefix = "(52)"; arg0 { title = "Speed"; + tooltip = "In fracunits per tic."; } arg1 { @@ -429,7 +421,6 @@ udmf 53 { title = "Continuous Plane Mover (Slowdown)"; - prefix = "(53)"; arg0 { title = "Target sector tag"; @@ -444,10 +435,12 @@ udmf arg2 { title = "Forward speed"; + tooltip = "In fracunits per tic."; } arg3 { title = "Return speed"; + tooltip = "In fracunits per tic."; } arg4 { @@ -462,7 +455,6 @@ udmf 56 { title = "Continuous Plane Mover (Constant)"; - prefix = "(56)"; arg0 { title = "Target sector tag"; @@ -477,10 +469,12 @@ udmf arg2 { title = "Forward speed"; + tooltip = "In fracunits per tic."; } arg3 { title = "Return speed"; + tooltip = "In fracunits per tic."; } arg4 { @@ -495,7 +489,6 @@ udmf 60 { title = "Activate Moving Platform"; - prefix = "(60)"; arg0 { title = "Target sector tag"; @@ -504,10 +497,11 @@ udmf arg1 { title = "Speed"; + tooltip = "In fracunits per tic."; } arg2 { - title = "Starting delay"; + title = "Starting delay (tics)"; } arg3 { @@ -524,7 +518,6 @@ udmf 61 { title = "Ceiling Crusher"; - prefix = "(61)"; arg0 { title = "Target sector tag"; @@ -543,17 +536,18 @@ udmf arg2 { title = "Crush speed"; + tooltip = "In fracunits per tic."; } arg3 { title = "Retract speed"; + tooltip = "In fracunits per tic."; } } 66 { - title = "Move Planes by Displacement"; - prefix = "(66)"; + title = "Move Planes by Front Sector Displacement"; arg0 { title = "Target sector tag"; @@ -580,7 +574,6 @@ udmf 70 { title = "Add Raise Thinker"; - prefix = "(70)"; arg0 { title = "Control linedef tag"; @@ -589,6 +582,7 @@ udmf arg1 { title = "Speed"; + tooltip = "In fracunits per tic."; } arg2 { @@ -605,7 +599,6 @@ udmf 71 { title = "Add Air Bobbing Thinker"; - prefix = "(71)"; arg0 { title = "Control linedef tag"; @@ -631,7 +624,6 @@ udmf 72 { title = "Add Thwomp Thinker"; - prefix = "(72)"; arg0 { title = "Control linedef tag"; @@ -640,14 +632,17 @@ udmf arg1 { title = "Falling speed"; + tooltip = "In fracunits per tic."; } arg2 { title = "Rising speed"; + tooltip = "In fracunits per tic."; } stringarg0 { title = "Crushing sound"; + tooltip = "Takes a DS constant.\nExample: DSTHOK"; type = 2; } } @@ -655,7 +650,6 @@ udmf 73 { title = "Add Laser Thinker"; - prefix = "(73)"; arg0 { title = "Control linedef tag"; @@ -672,7 +666,6 @@ udmf 74 { title = "Make FOF Bustable"; - prefix = "(74)"; arg0 { title = "Control linedef tag"; @@ -711,7 +704,6 @@ udmf 75 { title = "Make FOF Quicksand"; - prefix = "(75)"; arg0 { title = "Control linedef tag"; @@ -720,6 +712,7 @@ udmf arg1 { title = "Sinking speed"; + tooltip = "In fracunits per tic."; } arg2 { @@ -730,7 +723,6 @@ udmf 76 { title = "Make FOF Bouncy"; - prefix = "(76)"; arg0 { title = "Control linedef tag"; @@ -750,7 +742,6 @@ udmf 100 { title = "Solid"; - prefix = "(100)"; id = "srb2_fofsolid"; arg0 { @@ -761,6 +752,7 @@ udmf { title = "Alpha"; default = 255; + tooltip = "Ranges from 0 (fully transparent) to 255 (fully opaque)."; } arg2 { @@ -793,7 +785,6 @@ udmf 120 { title = "Water"; - prefix = "(120)"; id = "srb2_fofwater"; arg0 { @@ -804,6 +795,7 @@ udmf { title = "Alpha"; default = 128; + tooltip = "Ranges from 0 (fully transparent) to 255 (fully opaque)."; } arg2 { @@ -830,7 +822,6 @@ udmf 150 { title = "Air Bobbing"; - prefix = "(150)"; id = "srb2_fofsolidopaque"; arg0 { @@ -857,7 +848,6 @@ udmf 160 { title = "Water Bobbing"; - prefix = "(160)"; id = "srb2_fofsolidopaque"; arg0 { @@ -869,7 +859,6 @@ udmf 170 { title = "Crumbling"; - prefix = "(170)"; id = "srb2_fofcrumbling"; arg0 { @@ -880,6 +869,7 @@ udmf { title = "Alpha"; default = 255; + tooltip = "Ranges from 0 (fully transparent) to 255 (fully opaque)."; } arg2 { @@ -907,11 +897,10 @@ udmf } } } - + 190 { title = "Rising"; - prefix = "(190)"; id = "srb2_fofsolid"; arg0 { @@ -922,6 +911,7 @@ udmf { title = "Alpha"; default = 255; + tooltip = "Ranges from 0 (fully transparent) to 255 (fully opaque)."; } arg2 { @@ -952,6 +942,7 @@ udmf arg5 { title = "Speed"; + tooltip = "In fracunits per tic."; } arg6 { @@ -968,7 +959,6 @@ udmf 200 { title = "Light Block"; - prefix = "(200)"; id = "srb2_foflight"; arg0 { @@ -986,7 +976,6 @@ udmf 202 { title = "Fog Block"; - prefix = "(202)"; id = "srb2_foffog"; arg0 { @@ -998,7 +987,6 @@ udmf 220 { title = "Intangible"; - prefix = "(220)"; id = "srb2_fofintangible"; arg0 { @@ -1009,6 +997,7 @@ udmf { title = "Alpha"; default = 255; + tooltip = "Ranges from 0 (fully transparent) to 255 (fully opaque)."; } arg2 { @@ -1035,7 +1024,6 @@ udmf 223 { title = "Intangible, Invisible"; - prefix = "(223)"; id = "srb2_fofintangibleinvisible"; arg0 { @@ -1047,7 +1035,6 @@ udmf 250 { title = "Mario Block"; - prefix = "(250)"; id = "srb2_fofsolidopaque"; arg0 { @@ -1069,7 +1056,6 @@ udmf 251 { title = "Thwomp Block"; - prefix = "(251)"; id = "srb2_fofsolidopaque"; arg0 { @@ -1079,14 +1065,17 @@ udmf arg1 { title = "Falling speed"; + tooltip = "In fracunits per tic."; } arg2 { title = "Rising speed"; + tooltip = "In fracunits per tic."; } stringarg0 { title = "Crushing sound"; + tooltip = "Takes a DS constant.\nExample: DSTHOK"; type = 2; } } @@ -1094,7 +1083,6 @@ udmf 254 { title = "Bustable Block"; - prefix = "(254)"; id = "srb2_fofbustable"; arg0 { @@ -1105,6 +1093,7 @@ udmf { title = "Alpha"; default = 255; + tooltip = "Ranges from 0 (fully transparent) to 255 (fully opaque)."; } arg2 { @@ -1146,7 +1135,6 @@ udmf 257 { title = "Quicksand"; - prefix = "(257)"; id = "srb2_fofsolidopaque"; arg0 { @@ -1162,6 +1150,7 @@ udmf arg2 { title = "Sinking speed"; + tooltip = "In fracunits per tic."; } arg3 { @@ -1172,7 +1161,6 @@ udmf 258 { title = "Laser"; - prefix = "(258)"; id = "srb2_foflaser"; arg0 { @@ -1183,6 +1171,7 @@ udmf { title = "Alpha"; default = 128; + tooltip = "Ranges from 0 (fully transparent) to 255 (fully opaque)."; } arg2 { @@ -1205,7 +1194,6 @@ udmf 259 { title = "Custom"; - prefix = "(259)"; id = "srb2_fofcustom"; arg0 { @@ -1216,6 +1204,7 @@ udmf { title = "Alpha"; default = 255; + tooltip = "Ranges from 0 (fully transparent) to 255 (fully opaque)."; } arg2 { @@ -1269,7 +1258,6 @@ udmf 300 { title = "Basic"; - prefix = "(300)"; arg0 { title = "Trigger type"; @@ -1281,7 +1269,6 @@ udmf 303 { title = "Ring Count"; - prefix = "(303)"; arg0 { title = "Trigger type"; @@ -1309,7 +1296,6 @@ udmf 305 { title = "Character Ability"; - prefix = "(305)"; arg0 { title = "Trigger type"; @@ -1345,7 +1331,6 @@ udmf 308 { title = "Gametype"; - prefix = "(308)"; arg0 { title = "Trigger type"; @@ -1403,7 +1388,6 @@ udmf 309 { title = "CTF Team"; - prefix = "(309)"; arg0 { title = "Trigger type"; @@ -1421,7 +1405,6 @@ udmf 313 { title = "No More Enemies"; - prefix = "(313)"; arg0 { title = "Target sector tag"; @@ -1432,7 +1415,6 @@ udmf 314 { title = "Number of Pushables"; - prefix = "(314)"; arg0 { title = "Trigger type"; @@ -1454,7 +1436,6 @@ udmf 317 { title = "Condition Set Trigger"; - prefix = "(317)"; arg0 { title = "Trigger type"; @@ -1470,7 +1451,6 @@ udmf 319 { title = "Unlockable"; - prefix = "(319)"; arg0 { title = "Trigger type"; @@ -1486,7 +1466,6 @@ udmf 321 { title = "Trigger After X Calls"; - prefix = "(321)"; arg0 { title = "Trigger type"; @@ -1512,7 +1491,6 @@ udmf 323 { title = "NiGHTSerize"; - prefix = "(323)"; arg0 { title = "Trigger type"; @@ -1579,7 +1557,6 @@ udmf 325 { title = "De-NiGHTSerize"; - prefix = "(325)"; arg0 { title = "Trigger type"; @@ -1642,7 +1619,6 @@ udmf 327 { title = "NiGHTS Lap"; - prefix = "(327)"; arg0 { title = "Trigger type"; @@ -1694,7 +1670,6 @@ udmf 329 { title = "Ideya Capture Touch"; - prefix = "(329)"; arg0 { title = "Trigger type"; @@ -1762,7 +1737,6 @@ udmf 331 { title = "Player Skin"; - prefix = "(331)"; arg0 { title = "Trigger type"; @@ -1785,7 +1759,6 @@ udmf 334 { title = "Object Dye"; - prefix = "(334)"; arg0 { title = "Trigger type"; @@ -1808,7 +1781,6 @@ udmf 337 { title = "Emerald Check"; - prefix = "(337)"; arg0 { title = "Trigger type"; @@ -1841,7 +1813,6 @@ udmf 340 { title = "NiGHTS Mare"; - prefix = "(340)"; arg0 { title = "Trigger type"; @@ -1863,7 +1834,6 @@ udmf 343 { title = "Gravity Check"; - prefix = "(343)"; arg0 { title = "Trigger type"; @@ -1886,7 +1856,6 @@ udmf 399 { title = "Level Load"; - prefix = "(399)"; } } @@ -1897,7 +1866,6 @@ udmf 400 { title = "Set Tagged Sector's Heights/Textures"; - prefix = "(400)"; arg0 { title = "Target sector tag"; @@ -1920,7 +1888,6 @@ udmf 402 { title = "Copy Light Level to Tagged Sectors"; - prefix = "(402)"; arg0 { title = "Target sector tag"; @@ -1942,7 +1909,6 @@ udmf 408 { title = "Set Tagged Sector's Flats"; - prefix = "(408)"; arg0 { title = "Target sector tag"; @@ -1959,7 +1925,6 @@ udmf 409 { title = "Change Tagged Sector's Tag"; - prefix = "(409)"; arg0 { title = "Target sector tag"; @@ -1987,7 +1952,6 @@ udmf 410 { title = "Change Front Sector's Tag"; - prefix = "(410)"; arg0 { title = "Tag"; @@ -2010,7 +1974,6 @@ udmf 416 { title = "Start Adjustable Flickering Light"; - prefix = "(416)"; arg0 { title = "Target sector tag"; @@ -2039,7 +2002,6 @@ udmf 417 { title = "Start Adjustable Pulsating Light"; - prefix = "(417)"; arg0 { title = "Target sector tag"; @@ -2068,7 +2030,6 @@ udmf 418 { title = "Start Adjustable Blinking Light"; - prefix = "(418)"; arg0 { title = "Target sector tag"; @@ -2105,7 +2066,6 @@ udmf 420 { title = "Fade Light Level"; - prefix = "(420)"; arg0 { title = "Target sector tag"; @@ -2135,7 +2095,6 @@ udmf 421 { title = "Stop Lighting Effect"; - prefix = "(421)"; arg0 { title = "Target sector tag"; @@ -2146,7 +2105,6 @@ udmf 435 { title = "Change Plane Scroller Direction"; - prefix = "(435)"; arg0 { title = "Target sector tag"; @@ -2155,13 +2113,13 @@ udmf arg1 { title = "Speed"; + tooltip = "In fracunits per tic."; } } 467 { title = "Set Tagged Sector's Light Level"; - prefix = "(467)"; arg0 { title = "Target sector tag"; @@ -2193,7 +2151,6 @@ udmf 469 { title = "Change Tagged Sector's Gravity"; - prefix = "(469)"; arg0 { title = "Target sector tag"; @@ -2245,7 +2202,6 @@ udmf 403 { title = "Move Tagged Sector's Planes"; - prefix = "(403)"; arg0 { title = "Target sector tag"; @@ -2260,6 +2216,7 @@ udmf arg2 { title = "Speed"; + tooltip = "In fracunits per tic."; } arg3 { @@ -2276,8 +2233,7 @@ udmf 405 { - title = "Move Planes by Distance"; - prefix = "(405)"; + title = "Move Planes by Set Distance"; arg0 { title = "Target sector tag"; @@ -2296,6 +2252,7 @@ udmf arg3 { title = "Speed"; + tooltip = "In fracunits per tic."; } arg4 { @@ -2308,7 +2265,6 @@ udmf 411 { title = "Stop Plane Movement"; - prefix = "(411)"; arg0 { title = "Target sector tag"; @@ -2319,7 +2275,6 @@ udmf 428 { title = "Start Platform Movement"; - prefix = "(428)"; arg0 { title = "Target sector tag"; @@ -2328,14 +2283,15 @@ udmf arg1 { title = "Speed"; + tooltip = "In fracunits per tic."; } arg2 { - title = "Starting delay"; + title = "Starting delay (tics)"; } arg3 { - title = "Delay before flip"; + title = "Delay before flip (tics)"; } arg4 { @@ -2352,7 +2308,6 @@ udmf 429 { title = "Crush Planes Once"; - prefix = "(429)"; arg0 { title = "Target sector tag"; @@ -2367,10 +2322,12 @@ udmf arg2 { title = "Crush speed"; + tooltip = "In fracunits per tic."; } arg3 { title = "Retract speed"; + tooltip = "In fracunits per tic."; } } } @@ -2382,10 +2339,9 @@ udmf 412 { title = "Teleporter"; - prefix = "(412)"; arg0 { - title = "Destination tag"; + title = "Destination thing tag"; type = 14; } arg1 @@ -2417,7 +2373,6 @@ udmf 425 { title = "Change Object State"; - prefix = "(425)"; stringarg0 { title = "State"; @@ -2428,7 +2383,6 @@ udmf 426 { title = "Stop Object"; - prefix = "(426)"; arg0 { title = "Move to center?"; @@ -2440,7 +2394,6 @@ udmf 427 { title = "Award Score"; - prefix = "(427)"; arg0 { title = "Score"; @@ -2450,7 +2403,6 @@ udmf 432 { title = "Enable/Disable 2D Mode"; - prefix = "(432)"; arg0 { title = "Mode"; @@ -2466,7 +2418,6 @@ udmf 433 { title = "Enable/Disable Gravity Flip"; - prefix = "(433)"; arg0 { title = "Set gravity"; @@ -2502,7 +2453,6 @@ udmf 434 { title = "Award Power-Up"; - prefix = "(434)"; stringarg0 { title = "Power"; @@ -2518,7 +2468,6 @@ udmf 437 { title = "Disable Player Control"; - prefix = "(437)"; arg0 { title = "Time"; @@ -2534,7 +2483,6 @@ udmf 438 { title = "Change Object Size"; - prefix = "(438)"; arg0 { title = "Size (%)"; @@ -2545,7 +2493,6 @@ udmf 442 { title = "Change Object Type State"; - prefix = "(442)"; arg0 { title = "Target sector tag"; @@ -2576,7 +2523,6 @@ udmf 457 { title = "Track Object's Angle"; - prefix = "(457)"; arg0 { title = "Anchor tag"; @@ -2607,13 +2553,11 @@ udmf 458 { title = "Stop Tracking Object's Angle"; - prefix = "(458)"; } 460 { title = "Award Rings"; - prefix = "(460)"; arg0 { title = "Rings"; @@ -2627,7 +2571,6 @@ udmf 461 { title = "Spawn Object"; - prefix = "(461)"; arg0 { title = "X position"; @@ -2673,13 +2616,11 @@ udmf 462 { title = "Stop Timer/Exit Stage in Record Attack"; - prefix = "(462)"; } 463 { title = "Dye Object"; - prefix = "(463)"; stringarg0 { title = "Skin color"; @@ -2690,7 +2631,6 @@ udmf 464 { title = "Trigger Egg Capsule"; - prefix = "(464)"; arg0 { title = "Egg Capsule tag"; @@ -2707,7 +2647,6 @@ udmf 466 { title = "Set Level Failure State"; - prefix = "(466)"; arg0 { title = "State"; @@ -2728,7 +2667,6 @@ udmf 413 { title = "Change Music"; - prefix = "(413)"; arg0 { title = "Flags"; @@ -2771,6 +2709,7 @@ udmf stringarg0 { title = "Music name"; + tooltip = "Takes a music lump name, without the O_ or D_ prefix. Use - to disable music.\nExample: GFZ1"; type = 2; } } @@ -2778,7 +2717,6 @@ udmf 414 { title = "Play Sound Effect"; - prefix = "(414)"; arg0 { title = "Source"; @@ -2810,6 +2748,7 @@ udmf stringarg0 { title = "Sound name"; + tooltip = "Takes a DS constant.\nExample: DSTHOK"; type = 2; } } @@ -2817,7 +2756,6 @@ udmf 415 { title = "Run Script"; - prefix = "(415)"; stringarg0 { title = "Lump name"; @@ -2828,7 +2766,6 @@ udmf 422 { title = "Switch to Cut-Away View"; - prefix = "(422)"; arg0 { title = "Viewpoint tag"; @@ -2843,7 +2780,6 @@ udmf 423 { title = "Change Sky"; - prefix = "(423)"; arg0 { title = "Sky number"; @@ -2859,7 +2795,6 @@ udmf 424 { title = "Change Weather"; - prefix = "(424)"; arg0 { title = "Weather"; @@ -2886,7 +2821,6 @@ udmf 436 { title = "Shatter FOF"; - prefix = "(436)"; arg0 { title = "Target sector tag"; @@ -2902,7 +2836,6 @@ udmf 439 { title = "Change Tagged Linedef's Textures"; - prefix = "(439)"; arg0 { title = "Target linedef tag"; @@ -2931,13 +2864,11 @@ udmf 440 { title = "Start Metal Sonic Race"; - prefix = "(440)"; } 441 { title = "Condition Set Trigger"; - prefix = "(441)"; arg0 { title = "Trigger number"; @@ -2947,7 +2878,6 @@ udmf 443 { title = "Call Lua Function"; - prefix = "(443)"; stringarg0 { title = "Function name"; @@ -2958,7 +2888,6 @@ udmf 444 { title = "Earthquake"; - prefix = "(444)"; arg0 { title = "Duration"; @@ -2972,7 +2901,6 @@ udmf 445 { title = "Make FOF Disappear/Reappear"; - prefix = "(445)"; arg0 { title = "Target sector tag"; @@ -2998,7 +2926,6 @@ udmf 446 { title = "Make FOF Crumble"; - prefix = "(446)"; arg0 { title = "Target sector tag"; @@ -3026,7 +2953,6 @@ udmf 447 { title = "Change Tagged Sector's Colormap"; - prefix = "(447)"; arg0 { title = "Target sector tag"; @@ -3062,14 +2988,13 @@ udmf 448 { title = "Change Skybox"; - prefix = "(448)"; arg0 { - title = "Viewpoint ID"; + title = "Viewpoint thing tag"; } arg1 { - title = "Centerpoint ID"; + title = "Centerpoint thing tag"; } arg2 { @@ -3093,7 +3018,6 @@ udmf 449 { title = "Enable Bosses with Parameter"; - prefix = "(449)"; arg0 { title = "Boss ID"; @@ -3113,7 +3037,6 @@ udmf 450 { title = "Execute Linedef Executor (specific tag)"; - prefix = "(450)"; arg0 { title = "Trigger linedef tag"; @@ -3124,7 +3047,6 @@ udmf 451 { title = "Execute Linedef Executor (random tag in range)"; - prefix = "(451)"; arg0 { title = "Start of tag range"; @@ -3140,7 +3062,6 @@ udmf 452 { title = "Set FOF Translucency"; - prefix = "(452)"; arg0 { title = "Target sector tag"; @@ -3154,6 +3075,7 @@ udmf arg2 { title = "Alpha"; + tooltip = "Ranges from 0 (fully transparent) to 255 (fully opaque)."; } arg3 { @@ -3170,7 +3092,6 @@ udmf 453 { title = "Fade FOF"; - prefix = "(453)"; arg0 { title = "Target sector tag"; @@ -3184,10 +3105,11 @@ udmf arg2 { title = "Alpha"; + tooltip = "Ranges from 0 (fully transparent) to 255 (fully opaque)."; } arg3 { - title = "Fading speed"; + title = "Fading speed (tics)"; } arg4 { @@ -3212,7 +3134,6 @@ udmf 454 { title = "Stop Fading FOF"; - prefix = "(454)"; arg0 { title = "Target sector tag"; @@ -3234,7 +3155,6 @@ udmf 455 { title = "Fade Tagged Sector's Colormap"; - prefix = "(455)"; arg0 { title = "Target sector tag"; @@ -3276,7 +3196,6 @@ udmf 456 { title = "Stop Fading Tagged Sector's Colormap"; - prefix = "(456)"; arg0 { title = "Target sector tag"; @@ -3287,7 +3206,6 @@ udmf 459 { title = "Control Text Prompt"; - prefix = "(459)"; arg0 { title = "Prompt number"; @@ -3323,7 +3241,6 @@ udmf 465 { title = "Set Linedef Executor Delay"; - prefix = "(465)"; arg0 { title = "Linedef tag"; @@ -3344,7 +3261,6 @@ udmf 468 { title = "Change Linedef Argument"; - prefix = "(468)"; arg0 { title = "Linedef tag"; @@ -3373,16 +3289,16 @@ udmf 480 { - title = "Door Slide"; - prefix = "(480)"; + title = "PolyObject Door Slide"; arg0 { - title = "PolyObject ID"; + title = "PolyObject tag"; type = 14; } arg1 { title = "Speed"; + tooltip = "In fracunits per tic."; } arg2 { @@ -3390,22 +3306,22 @@ udmf } arg3 { - title = "Return delay"; + title = "Return delay (tics)"; } } 481 { - title = "Door Swing"; - prefix = "(481)"; + title = "PolyObject Door Swing"; arg0 { - title = "PolyObject ID"; + title = "PolyObject tag"; type = 14; } arg1 { title = "Speed"; + tooltip = "In fracunits per tic."; } arg2 { @@ -3414,22 +3330,22 @@ udmf } arg3 { - title = "Return delay"; + title = "Return delay (tics)"; } } 482 { - title = "Move"; - prefix = "(482)"; + title = "Move PolyObject"; arg0 { - title = "PolyObject ID"; + title = "PolyObject tag"; type = 14; } arg1 { title = "Speed"; + tooltip = "In fracunits per tic."; } arg2 { @@ -3445,20 +3361,21 @@ udmf 484 { - title = "Rotate"; - prefix = "(484)"; + title = "Rotate PolyObject"; arg0 { - title = "PolyObject ID"; + title = "PolyObject tag"; type = 14; } arg1 { title = "Speed"; + tooltip = "In degrees per tic."; } arg2 { title = "Rotation"; + tooltip = "How many degrees the PolyObject will rotate."; type = 8; } arg3 @@ -3477,20 +3394,21 @@ udmf 488 { - title = "Move by Waypoints"; - prefix = "(488)"; + title = "Move PolyObject by Waypoints"; arg0 { - title = "PolyObject ID"; + title = "PolyObject tag"; type = 14; } arg1 { title = "Speed"; + tooltip = "In fracunits per tic."; } arg2 { title = "Waypoint sequence"; + tooltip = "The sequence number of (zoom tube) waypoints to use."; } arg3 { @@ -3517,11 +3435,10 @@ udmf 489 { - title = "Set Visibility, Tangibility"; - prefix = "(489)"; + title = "Set PolyObject Visibility/Tangibility"; arg0 { - title = "PolyObject ID"; + title = "PolyObject tag"; type = 14; } arg1 @@ -3550,16 +3467,16 @@ udmf 491 { - title = "Set Translucency"; - prefix = "(491)"; + title = "Set PolyObject Translucency"; arg0 { - title = "PolyObject ID"; + title = "PolyObject tag"; type = 14; } arg1 { title = "Translucency level"; + tooltip = "Ranges from 0 (fully opaque) to 10 (fully transparent)."; } arg2 { @@ -3571,16 +3488,16 @@ udmf 492 { - title = "Fade Translucency"; - prefix = "(492)"; + title = "Fade PolyObject Translucency"; arg0 { - title = "PolyObject ID"; + title = "PolyObject tag"; type = 14; } arg1 { title = "Translucency level"; + tooltip = "Ranges from 0 (fully opaque) to 10 (fully transparent)."; } arg2 { @@ -3608,8 +3525,7 @@ udmf 500 { - title = "Scroll Walls"; - prefix = "(500)"; + title = "Scroll Wall"; arg0 { title = "Side"; @@ -3628,8 +3544,7 @@ udmf 502 { - title = "Scroll Walls Remotely"; - prefix = "(502)"; + title = "Scroll Tagged Walls"; arg0 { title = "Linedef tag"; @@ -3660,11 +3575,11 @@ udmf 510 { title = "Scroll Planes"; - prefix = "(510)"; arg0 { title = "Sector tag"; type = 13; + tooltip = "A tag of 0 will scroll the planes of this line's front sector."; } arg1 { @@ -3697,11 +3612,11 @@ udmf 541 { title = "Wind/Current"; - prefix = "(541)"; arg0 { title = "Sector tag"; type = 13; + tooltip = "A tag of 0 will apply the effect to this line's front sector."; } arg1 { @@ -3725,7 +3640,7 @@ udmf { title = "Flags"; type = 12; - flags + enum { 1 = "Slide"; 2 = "Non-exclusive"; @@ -3741,7 +3656,6 @@ udmf 600 { title = "Copy Light Level to Tagged Sector's Planes"; - prefix = "(600)"; arg0 { title = "Target sector tag"; @@ -3758,7 +3672,6 @@ udmf 602 { title = "Adjustable Pulsating Light"; - prefix = "(602)"; arg0 { title = "Target sector tag"; @@ -3787,7 +3700,6 @@ udmf 603 { title = "Adjustable Flickering Light"; - prefix = "(603)"; arg0 { title = "Target sector tag"; @@ -3816,7 +3728,6 @@ udmf 604 { title = "Adjustable Blinking Light"; - prefix = "(604)"; arg0 { title = "Target sector tag"; @@ -3853,7 +3764,6 @@ udmf 606 { title = "Copy Colormap"; - prefix = "(606)"; arg0 { title = "Target sector tag"; @@ -3874,7 +3784,6 @@ udmf 700 { title = "Create Sector-Based Slope"; - prefix = "(700)"; id = "plane_align"; arg0 { @@ -3904,7 +3813,6 @@ udmf 704 { title = "Create Vertex-Based Slope"; - prefix = "(704)"; id = "srb2_vertexslope"; arg0 { @@ -3948,7 +3856,6 @@ udmf 720 { title = "Copy Slope"; - prefix = "(720)"; id = "plane_copy"; arg0 { @@ -3987,7 +3894,6 @@ udmf 799 { title = "Set Tagged Dynamic Slope Vertex to Front Sector Height"; - prefix = "(799)"; arg0 { title = "Apply height"; diff --git a/extras/conf/udb/Includes/SRB222_misc.cfg b/extras/conf/udb/Includes/SRB222_misc.cfg index e274fece69ea37d4be43cd8b7560fde69e181ee5..e5786977bd4e9c3a543c2113d0f20fa8b84939a1 100644 --- a/extras/conf/udb/Includes/SRB222_misc.cfg +++ b/extras/conf/udb/Includes/SRB222_misc.cfg @@ -78,6 +78,8 @@ sectorflags ropehang = "Rope Hang"; jumpflip = "Flip Gravity on Jump"; gravityoverride = "Make Reverse Gravity Temporary"; + nophysics_floor = "Disable Floor Slope Physics"; + nophysics_ceiling = "Disable Ceiling Slope Physics"; flipspecial_nofloor = "No Trigger on Floor Touch"; flipspecial_ceiling = "Trigger on Ceiling Touch"; triggerspecial_touch = "Trigger on Edge Touch"; @@ -114,6 +116,8 @@ sectorflagscategories ropehang = "special"; jumpflip = "special"; gravityoverride = "special"; + nophysics_floor = "special"; + nophysics_ceiling = "special"; flipspecial_nofloor = "trigger"; flipspecial_ceiling = "trigger"; triggerspecial_touch = "trigger"; @@ -229,20 +233,369 @@ Field data types: */ universalfields { - sector - { - } - linedef { + alpha + { + type = 1; + default = 1.0; + } + + comment + { + type = 2; + default = ""; + } + + renderstyle + { + type = 2; + default = ""; + } + + stringarg0 + { + type = 2; + default = ""; + } + + stringarg1 + { + type = 2; + default = ""; + } + + executordelay + { + type = 0; + default = 0; + } } sidedef { + comment + { + type = 2; + default = ""; + } + + light + { + type = 0; + default = 0; + } + + lightabsolute + { + type = 3; + default = false; + } + + //light_top + //{ + // type = 0; + // default = 0; + //} + // + //lightabsolute_top + //{ + // type = 3; + // default = false; + //} + // + //light_mid + //{ + // type = 0; + // default = 0; + //} + // + //lightabsolute_mid + //{ + // type = 3; + // default = false; + //} + // + //light_bottom + //{ + // type = 0; + // default = 0; + //} + // + //lightabsolute_bottom + //{ + // type = 3; + // default = false; + //} + + offsetx_bottom + { + type = 1; + default = 0.0; + } + + offsetx_mid + { + type = 1; + default = 0.0; + } + + offsetx_top + { + type = 1; + default = 0.0; + } + + offsety_bottom + { + type = 1; + default = 0.0; + } + + offsety_mid + { + type = 1; + default = 0.0; + } + + offsety_top + { + type = 1; + default = 0.0; + } + + scalex_bottom + { + type = 1; + default = 1.0; + } + + scalex_mid + { + type = 1; + default = 1.0; + } + + scalex_top + { + type = 1; + default = 1.0; + } + + scaley_bottom + { + type = 1; + default = 1.0; + } + + scaley_mid + { + type = 1; + default = 1.0; + } + + scaley_top + { + type = 1; + default = 1.0; + } } thing { + comment + { + type = 2; + default = ""; + } + + pitch + { + type = 0; + } + + roll + { + type = 0; + } + + scalex + { + type = 1; + default = 1.0; + } + + scaley + { + type = 1; + default = 1.0; + } + + stringarg0 + { + type = 2; + default = ""; + } + + stringarg1 + { + type = 2; + default = ""; + } + + mobjscale + { + type = 1; + default = 1.0; + managed = false; + } + } + + sector + { + comment + { + type = 2; + default = ""; + } + + damagetype + { + type = 2; + default = ""; + } + + gravity + { + type = 1; + default = 1.0; + } + + lightcolor + { + type = 0; + default = 0; + } + + fadecolor + { + type = 0; + default = 0; + } + + lightalpha + { + type = 0; + default = 25; + } + + fadealpha + { + type = 0; + default = 25; + } + + fadestart + { + type = 0; + default = 0; + } + + fadeend + { + type = 0; + default = 31; + } + + xpanningfloor + { + type = 1; + default = 0.0; + } + + ypanningfloor + { + type = 1; + default = 0.0; + } + + rotationfloor + { + type = 1; + default = 0.0; + } + + xscalefloor + { + type = 1; + default = 1.0; + } + + yscalefloor + { + type = 1; + default = 1.0; + } + + lightfloor + { + type = 0; + default = 0; + } + + lightfloorabsolute + { + type = 3; + default = false; + } + + xpanningceiling + { + type = 1; + default = 0.0; + } + + ypanningceiling + { + type = 1; + default = 0.0; + } + + rotationceiling + { + type = 1; + default = 0.0; + } + + xscaleceiling + { + type = 1; + default = 1.0; + } + + yscaleceiling + { + type = 1; + default = 1.0; + } + + lightceiling + { + type = 0; + default = 0; + } + + lightceilingabsolute + { + type = 3; + default = false; + } + + triggertag + { + type = 0; + default = 0; + } } } diff --git a/extras/conf/udb/Includes/SRB222_things.cfg b/extras/conf/udb/Includes/SRB222_things.cfg index 9eb227974dfd0b33de593a7ced83b42fab7d6738..8b1e29751b7bb4b3e771813b414d80f9017a4f68 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -1127,56 +1127,63 @@ udmf } } } - 290 - { - arrow = 0; - title = "Boss Escape Point"; - width = 8; - height = 16; - sprite = "internal:eggmanend"; - } - 291 - { - arrow = 0; - title = "Egg Capsule Center"; - width = 8; - height = 16; - sprite = "internal:capsule"; - } - 292 + + bossinvisibles { - arrow = 0; - title = "Boss Waypoint"; - width = 8; - height = 16; - sprite = "internal:eggmanway"; - arg0 - { - title = "Sea Egg sequence"; + title = "Misc. Invisible"; + color = 15; // White + + 290 + { + arrow = 0; + title = "Boss Escape Point"; + width = 8; + height = 16; + sprite = "internal:eggmanend"; + } + 291 + { + arrow = 0; + title = "Egg Capsule Center"; + width = 8; + height = 16; + sprite = "internal:capsule"; + } + 292 + { + arrow = 0; + title = "Boss Waypoint"; + width = 8; + height = 16; + sprite = "internal:eggmanway"; + arg0 + { + title = "Sea Egg sequence"; + } + arg1 + { + title = "Brak Eggman sequence"; + } } - arg1 + 293 { - title = "Brak Eggman sequence"; + title = "Metal Sonic Gather Point"; + sprite = "internal:metal"; + width = 8; + height = 16; } - } - 293 - { - title = "Metal Sonic Gather Point"; - sprite = "internal:metal"; - width = 8; - height = 16; - } - 294 - { - title = "Fang Waypoint"; - sprite = "internal:eggmanway"; - width = 8; - height = 16; - arg0 + 294 { - title = "Center waypoint?"; - type = 11; - enum = "noyes"; + title = "Fang Waypoint"; + sprite = "internal:eggmanway"; + width = 8; + height = 16; + arg0 + { + title = "Center waypoint?"; + type = 11; + enum = "noyes"; + } } } } @@ -1196,6 +1203,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } @@ -1207,6 +1215,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } @@ -1218,6 +1227,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } @@ -1230,6 +1240,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } @@ -1241,6 +1252,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } @@ -1252,6 +1264,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } @@ -1263,6 +1276,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } @@ -1274,6 +1288,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } @@ -1285,6 +1300,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } @@ -1296,6 +1312,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } @@ -1309,6 +1326,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } @@ -1322,6 +1340,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } @@ -1335,6 +1354,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } @@ -1348,6 +1368,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } @@ -1361,6 +1382,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } @@ -1374,6 +1396,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } @@ -1412,6 +1435,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } @@ -1459,6 +1483,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } @@ -1470,6 +1495,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } @@ -1483,6 +1509,7 @@ udmf arg1 { title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } @@ -1952,7 +1979,7 @@ udmf generic { color = 11; // Light_Cyan - title = "Generic Items & Hazards"; + title = "Generic Objects "; 500 { @@ -1963,6 +1990,7 @@ udmf arg0 { title = "Distance check?"; + tooltip = "If enabled, bubbles are only spawned a player is within 2048 fracunits."; type = 11; enum = "yesno"; } @@ -1992,19 +2020,12 @@ udmf enum = "noyes"; } } - 520 - { - title = "Bomb Sphere"; - sprite = "SPHRD0"; - width = 16; - height = 24; - arg0 - { - title = "Float?"; - type = 11; - enum = "yesno"; - } - } + } + + hazards + { + color = 17; // Orange + title = "Generic Hazards"; 521 { title = "Spikeball"; @@ -2014,6 +2035,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } @@ -2162,6 +2184,7 @@ udmf stringarg0 { title = "Color"; + tooltip = "Uses a SKINCOLOR_ constant.\nExample: SKINCOLOR_RED"; } } 550 @@ -2240,6 +2263,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 16 fracunits."; type = 11; enum = "yesno"; } @@ -2254,6 +2278,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 16 fracunits."; type = 11; enum = "yesno"; } @@ -2268,6 +2293,7 @@ udmf arg0 { title = "Float?"; + tooltip = "This raises the object by 16 fracunits."; type = 11; enum = "yesno"; } @@ -2322,7 +2348,7 @@ udmf arrow = 1; title = "Special Placement Patterns"; width = 16; - height = 384; + height = 64; sprite = "RINGA0"; 600 @@ -2330,6 +2356,7 @@ udmf arrow = 0; title = "5 Vertical Rings (Yellow Spring)"; sprite = "internal:ringverticalyellow"; + height = 384; } 601 { @@ -2363,6 +2390,7 @@ udmf title = "Circle of Rings (Big)"; sprite = "internal:circlebigring"; width = 192; + height = 384; centerhitbox = true; } 606 @@ -2378,6 +2406,7 @@ udmf title = "Circle of Blue Spheres (Big)"; sprite = "internal:circlebigsphere"; width = 192; + height = 384; centerhitbox = true; } 608 @@ -2393,47 +2422,59 @@ udmf title = "Circle of Rings and Spheres (Big)"; sprite = "internal:circlebigringsphere"; width = 192; + height = 384; centerhitbox = true; } 610 { title = "Row of Items"; - sprite = "RINGA0"; + sprite = "internal:customrow"; + width = 32; + height = 384; arg0 { title = "Number of items"; + default = 5; } arg1 { title = "Horizontal spacing"; + default = 64; } arg2 { title = "Vertical spacing"; + default = 64; } stringarg0 { title = "Object types"; + tooltip = "A list of MT_ constants to use, separated by spaces.\nExample: MT_RING MT_BLUESPHERE"; } } 611 { title = "Circle of Items"; - sprite = "RINGA0"; - width = 96; - height = 192; + sprite = "internal:customcircle"; + width = 32; + height = 64; centerhitbox = true; arg0 { title = "Number of items"; + default = 16; } arg1 { title = "Radius"; + renderstyle = "circle"; + rendercolor = "#6600FF"; + default = 128; } stringarg0 { title = "Object types"; + tooltip = "A list of MT_ constants to use, separated by spaces.\nExample: MT_RING MT_BLUESPHERE"; } } } @@ -2456,10 +2497,13 @@ udmf arg0 { title = "Repeat speed"; + tooltip = "In tics."; + default = 35; } stringarg0 { title = "Sound"; + tooltip = "Takes a DS constant.\nExample: DSAMWTR3"; } } @@ -2495,7 +2539,7 @@ udmf sprite = "internal:zoom"; arg0 { - title = "Sequence"; + title = "Sequence number"; } arg1 { @@ -2510,6 +2554,7 @@ udmf arg0 { title = "Radius"; + renderstyle = "circle"; } arg1 { @@ -2547,24 +2592,28 @@ udmf height = 16; arg0 { - title = "Particles"; + title = "Number of particles"; } arg1 { title = "Radius"; + renderstyle = "circle"; } arg2 { title = "Rising speed"; + tooltip = "In fracunits per tic."; } arg3 { title = "Rotation speed"; + tooltip = "In degrees per tic."; type = 8; } arg4 { title = "Spawn interval"; + tooltip = "In tics."; } arg5 { @@ -2575,6 +2624,11 @@ udmf title = "Heights control linedef"; type = 15; } + stringarg0 + { + title = "Particle object type"; + tooltip = "Uses a MT_ constant.\nExample: MT_PARTICLE\nDefaults to MT_PARTICLE."; + } } 758 { @@ -2770,6 +2824,7 @@ udmf sprite = "GARGA1"; width = 16; height = 40; + color = 6; arg0 { title = "Push behavior"; @@ -2785,6 +2840,7 @@ udmf sprite = "GARGB1"; width = 32; height = 80; + color = 6; arg0 { title = "Push behavior"; @@ -2893,6 +2949,7 @@ udmf width = 28; height = 56; sprite = "BMNEA1"; + color = 17; } 1013 { @@ -2922,6 +2979,348 @@ udmf color = 2; // Green title = "Castle Eggman"; + macespawns + { + title = "Mace Spawnpoints"; + color = 11; + + 1104 + { + title = "Mace Spawn"; + sprite = "SMCEA0"; + width = 17; + height = 34; + arg0 + { + title = "Number of links"; + } + arg1 + { + title = "Number of extra spokes"; + } + arg2 + { + title = "Width"; + tooltip = "Adds extra maces to both sides."; + } + arg3 + { + title = "Speed"; + tooltip = "In fracunits per tic."; + } + arg4 + { + title = "Phase"; + type = 8; + } + arg5 + { + title = "Pinch"; + type = 8; + } + arg6 + { + title = "Omitted spokes"; + } + arg7 + { + title = "Omitted links"; + } + arg8 + { + title = "Flags"; + type = 12; + enum = "maceflags"; + } + } + 1105 + { + title = "Chain & Maces Spawn"; + sprite = "SMCEA0"; + width = 17; + height = 34; + arg0 + { + title = "Number of links"; + } + arg1 + { + title = "Number of extra spokes"; + } + arg2 + { + title = "Width"; + tooltip = "Adds extra chains/maces to both sides."; + } + arg3 + { + title = "Speed"; + tooltip = "In fracunits per tic."; + } + arg4 + { + title = "Phase"; + type = 8; + } + arg5 + { + title = "Pinch"; + type = 8; + } + arg6 + { + title = "Omitted spokes"; + } + arg7 + { + title = "Omitted links"; + } + arg8 + { + title = "Flags"; + type = 12; + enum = "maceflags"; + } + } + 1106 + { + title = "Spring Ball Spawn"; + sprite = "YSPBA0"; + width = 17; + height = 34; + arg0 + { + title = "Number of links"; + } + arg1 + { + title = "Number of extra spokes"; + } + arg2 + { + title = "Width"; + tooltip = "Adds extra springs to both sides."; + } + arg3 + { + title = "Speed"; + tooltip = "In fracunits per tic."; + } + arg4 + { + title = "Phase"; + type = 8; + } + arg5 + { + title = "Pinch"; + type = 8; + } + arg6 + { + title = "Omitted spokes"; + } + arg7 + { + title = "Omitted links"; + } + arg8 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Red spring"; + 2 = "No sounds"; + 4 = "Player-turnable chain"; + 8 = "Swing instead of spin"; + 16 = "Make chain from end item"; + 32 = "Spawn link at origin"; + 64 = "Clip inside ground"; + 128 = "No distance check"; + } + } + } + 1107 + { + title = "Chain Spawn"; + sprite = "BMCHA0"; + width = 17; + height = 34; + arg0 + { + title = "Number of links"; + } + arg1 + { + title = "Number of extra spokes"; + } + arg2 + { + title = "Width"; + tooltip = "Adds extra chains to both sides."; + } + arg3 + { + title = "Speed"; + tooltip = "In fracunits per tic."; + } + arg4 + { + title = "Phase"; + type = 8; + } + arg5 + { + title = "Pinch"; + type = 8; + } + arg6 + { + title = "Omitted spokes"; + } + arg7 + { + title = "Omitted links"; + } + arg8 + { + title = "Flags"; + type = 12; + enum = "maceflags"; + + } + } + 1108 + { + arrow = 1; + title = "Hidden Chain Spawn"; + sprite = "internal:chain3"; + width = 17; + height = 34; + } + 1109 + { + title = "Firebar Spawn"; + sprite = "BFBRA0"; + width = 17; + height = 34; + arg0 + { + title = "Number of links"; + } + arg1 + { + title = "Number of extra spokes"; + } + arg2 + { + title = "Width"; + tooltip = "Adds extra firebars to both sides."; + } + arg3 + { + title = "Speed"; + tooltip = "In fracunits per tic."; + } + arg4 + { + title = "Phase"; + type = 8; + } + arg5 + { + title = "Pinch"; + type = 8; + } + arg6 + { + title = "Omitted spokes"; + } + arg7 + { + title = "Omitted links"; + } + arg8 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Double size"; + 2 = "No sounds"; + 4 = "Player-turnable chain"; + 8 = "Swing instead of spin"; + 16 = "Omit chain links"; + 32 = "Spawn link at origin"; + 64 = "Clip inside ground"; + 128 = "No distance check"; + } + } + } + 1110 + { + title = "Custom Mace Spawn"; + sprite = "SMCEA0"; + width = 17; + height = 34; + arg0 + { + title = "Number of links"; + } + arg1 + { + title = "Number of extra spokes"; + } + arg2 + { + title = "Width"; + tooltip = "Adds extra maces to both sides."; + } + arg3 + { + title = "Speed"; + tooltip = "In fracunits per tic."; + } + arg4 + { + title = "Phase"; + type = 8; + } + arg5 + { + title = "Pinch"; + type = 8; + } + arg6 + { + title = "Omitted spokes"; + } + arg7 + { + title = "Omitted links"; + } + arg8 + { + title = "Flags"; + type = 12; + enum = "maceflags"; + } + stringarg0 + { + title = "Mace object type"; + tooltip = "Uses a MT_ constant.\nExample: MT_BIGMACE"; + type = 2; + } + stringarg1 + { + title = "Link object type"; + tooltip = "Uses a MT_ constant.\nExample: MT_BIGCHAIN"; + type = 2; + } + } + } + 1100 { title = "Chain (Decorative)"; @@ -2951,6 +3350,7 @@ udmf sprite = "ESTAA1"; width = 32; height = 240; + color = 6; arg0 { title = "Push behavior"; @@ -2971,355 +3371,36 @@ udmf width = 16; height = 40; } - 1104 + 1111 { - title = "Mace Spawnpoint"; - sprite = "SMCEA0"; - width = 17; - height = 34; + arrow = 1; + blocking = 2; + title = "Crawla Statue"; + sprite = "CSTAA1"; + width = 16; + height = 40; + color = 6; arg0 { - title = "Number of links"; - } - arg1 - { - title = "Number of spokes"; - } - arg2 - { - title = "Width"; - } - arg3 - { - title = "Speed"; - } - arg4 - { - title = "Phase"; - type = 8; - } - arg5 - { - title = "Pinch"; - type = 8; - } - arg6 - { - title = "Omitted spokes"; - } - arg7 - { - title = "Omitted links"; - } - arg8 - { - title = "Flags"; - type = 12; - enum = "maceflags"; + title = "Push behavior"; + type = 11; + enum = "pushablebehavior"; } } - 1105 + 1112 { - title = "Chain with Maces Spawnpoint"; - sprite = "SMCEA0"; - width = 17; - height = 34; + arrow = 1; + blocking = 2; + title = "Lance-a-Bot Statue"; + sprite = "CBBSA1"; + width = 32; + height = 72; + color = 6; arg0 { - title = "Number of links"; - } - arg1 - { - title = "Number of spokes"; - } - arg2 - { - title = "Width"; - } - arg3 - { - title = "Speed"; - } - arg4 - { - title = "Phase"; - type = 8; - } - arg5 - { - title = "Pinch"; - type = 8; - } - arg6 - { - title = "Omitted spokes"; - } - arg7 - { - title = "Omitted links"; - } - arg8 - { - title = "Flags"; - type = 12; - enum = "maceflags"; - } - } - 1106 - { - title = "Chained Spring Spawnpoint"; - sprite = "YSPBA0"; - width = 17; - height = 34; - arg0 - { - title = "Number of links"; - } - arg1 - { - title = "Number of spokes"; - } - arg2 - { - title = "Width"; - } - arg3 - { - title = "Speed"; - } - arg4 - { - title = "Phase"; - type = 8; - } - arg5 - { - title = "Pinch"; - type = 8; - } - arg6 - { - title = "Omitted spokes"; - } - arg7 - { - title = "Omitted links"; - } - arg8 - { - title = "Flags"; - type = 12; - enum - { - 1 = "Red spring"; - 2 = "No sounds"; - 4 = "Player-turnable chain"; - 8 = "Swing instead of spin"; - 16 = "Make chain from end item"; - 32 = "Spawn link at origin"; - 64 = "Clip inside ground"; - 128 = "No distance check"; - } - } - } - 1107 - { - title = "Chain Spawnpoint"; - sprite = "BMCHA0"; - width = 17; - height = 34; - arg0 - { - title = "Number of links"; - } - arg1 - { - title = "Number of spokes"; - } - arg2 - { - title = "Width"; - } - arg3 - { - title = "Speed"; - } - arg4 - { - title = "Phase"; - type = 8; - } - arg5 - { - title = "Pinch"; - type = 8; - } - arg6 - { - title = "Omitted spokes"; - } - arg7 - { - title = "Omitted links"; - } - arg8 - { - title = "Flags"; - type = 12; - enum = "maceflags"; - - } - } - 1108 - { - arrow = 1; - title = "Hidden Chain Spawnpoint"; - sprite = "internal:chain3"; - width = 17; - height = 34; - } - 1109 - { - title = "Firebar Spawnpoint"; - sprite = "BFBRA0"; - width = 17; - height = 34; - arg0 - { - title = "Number of links"; - } - arg1 - { - title = "Number of spokes"; - } - arg2 - { - title = "Width"; - } - arg3 - { - title = "Speed"; - } - arg4 - { - title = "Phase"; - type = 8; - } - arg5 - { - title = "Pinch"; - type = 8; - } - arg6 - { - title = "Omitted spokes"; - } - arg7 - { - title = "Omitted links"; - } - arg8 - { - title = "Flags"; - type = 12; - enum - { - 1 = "Double size"; - 2 = "No sounds"; - 4 = "Player-turnable chain"; - 8 = "Swing instead of spin"; - 16 = "Omit chain links"; - 32 = "Spawn link at origin"; - 64 = "Clip inside ground"; - 128 = "No distance check"; - } - } - } - 1110 - { - title = "Custom Mace Spawnpoint"; - sprite = "SMCEA0"; - width = 17; - height = 34; - arg0 - { - title = "Number of links"; - } - arg1 - { - title = "Number of spokes"; - } - arg2 - { - title = "Width"; - } - arg3 - { - title = "Speed"; - } - arg4 - { - title = "Phase"; - type = 8; - } - arg5 - { - title = "Pinch"; - type = 8; - } - arg6 - { - title = "Omitted spokes"; - } - arg7 - { - title = "Omitted links"; - } - arg8 - { - title = "Flags"; - type = 12; - enum = "maceflags"; - } - stringarg0 - { - title = "Mace object type"; - type = 2; - } - stringarg1 - { - title = "Link object type"; - type = 2; - } - } - 1111 - { - arrow = 1; - blocking = 2; - title = "Crawla Statue"; - sprite = "CSTAA1"; - width = 16; - height = 40; - arg0 - { - title = "Push behavior"; - type = 11; - enum = "pushablebehavior"; - } - } - 1112 - { - arrow = 1; - blocking = 2; - title = "Lance-a-Bot Statue"; - sprite = "CBBSA1"; - width = 32; - height = 72; - arg0 - { - title = "Push behavior"; - type = 11; - enum = "pushablebehavior"; + title = "Push behavior"; + type = 11; + enum = "pushablebehavior"; } } 1114 @@ -3415,6 +3496,7 @@ udmf sprite = "internal:cannonball"; width = 8; height = 16; + color = 17; } 1124 { @@ -3423,6 +3505,7 @@ udmf sprite = "CBLLA0"; width = 20; height = 40; + color = 6; arg0 { title = "Push behavior"; @@ -3443,6 +3526,7 @@ udmf sprite = "LCKNC0"; width = 16; height = 32; + color = 15; } 1127 { @@ -3450,6 +3534,7 @@ udmf sprite = "EGR1A1"; width = 20; height = 72; + color = 17; arg0 { title = "Movement"; @@ -3485,6 +3570,143 @@ udmf color = 2; // Green title = "Arid Canyon"; + + cacti + { + title = "Cacti"; + color = 17; + + 1203 + { + title = "Tiny Red Flower Cactus"; + sprite = "CACTA0"; + width = 13; + height = 24; + } + 1204 + { + title = "Small Red Flower Cactus"; + sprite = "CACTB0"; + width = 15; + height = 52; + } + 1205 + { + title = "Tiny Blue Flower Cactus"; + sprite = "CACTC0"; + width = 13; + height = 24; + } + 1206 + { + title = "Small Blue Flower Cactus"; + sprite = "CACTD0"; + width = 15; + height = 52; + } + 1207 + { + title = "Prickly Pear"; + sprite = "CACTE0"; + width = 32; + height = 96; + } + 1208 + { + title = "Barrel Cactus"; + sprite = "CACTF0"; + width = 20; + height = 128; + } + 1209 + { + title = "Tall Barrel Cactus"; + sprite = "CACTG0"; + width = 24; + height = 224; + } + 1210 + { + title = "Armed Cactus"; + sprite = "CACTH0"; + width = 24; + height = 256; + } + 1211 + { + title = "Ball Cactus"; + sprite = "CACTI0"; + width = 48; + height = 96; + } + 1230 + { + title = "Tiny Cactus"; + sprite = "CACTJ0"; + width = 13; + height = 28; + } + 1231 + { + title = "Small Cactus"; + sprite = "CACTK0"; + width = 15; + height = 60; + } + } + + minecarts + { + title = "Minecart"; + color = 11; + + 1219 + { + title = "Minecart Spawner"; + sprite = "MCRTCLFR"; + width = 22; + height = 32; + } + 1220 + { + title = "Minecart Stopper"; + sprite = "MCRTIR"; + width = 32; + height = 32; + } + 1221 + { + title = "Minecart Saloon Door"; + sprite = "SALDARAL"; + width = 96; + height = 160; + arg0 + { + title = "Allow non-minecart players?"; + type = 11; + enum = "noyes"; + } + } + 1229 + { + title = "Minecart Switch Point"; + sprite = "internal:zoom"; + width = 8; + height = 16; + color = 15; + arg0 + { + title = "Type"; + type = 11; + enum + { + 0 = "Disable"; + 1 = "Enable"; + } + } + } + } + 1200 { title = "Tumbleweed (Big)"; @@ -3518,6 +3740,7 @@ udmf sprite = "ROIAA0"; width = 8; height = 16; + color = 17; arg0 { title = "Speed"; @@ -3538,78 +3761,15 @@ udmf type = 2; } } - 1203 + 1212 { - title = "Tiny Red Flower Cactus"; - sprite = "CACTA0"; - width = 13; - height = 24; + title = "Caution Sign"; + sprite = "WWSGAR"; + width = 22; + height = 64; + wallsprite = true; } - 1204 - { - title = "Small Red Flower Cactus"; - sprite = "CACTB0"; - width = 15; - height = 52; - } - 1205 - { - title = "Tiny Blue Flower Cactus"; - sprite = "CACTC0"; - width = 13; - height = 24; - } - 1206 - { - title = "Small Blue Flower Cactus"; - sprite = "CACTD0"; - width = 15; - height = 52; - } - 1207 - { - title = "Prickly Pear"; - sprite = "CACTE0"; - width = 32; - height = 96; - } - 1208 - { - title = "Barrel Cactus"; - sprite = "CACTF0"; - width = 20; - height = 128; - } - 1209 - { - title = "Tall Barrel Cactus"; - sprite = "CACTG0"; - width = 24; - height = 224; - } - 1210 - { - title = "Armed Cactus"; - sprite = "CACTH0"; - width = 24; - height = 256; - } - 1211 - { - title = "Ball Cactus"; - sprite = "CACTI0"; - width = 48; - height = 96; - } - 1212 - { - title = "Caution Sign"; - sprite = "WWSGAR"; - width = 22; - height = 64; - wallsprite = true; - } - 1213 + 1213 { title = "Cacti Sign"; sprite = "WWS2AR"; @@ -3639,6 +3799,7 @@ udmf sprite = "BARRA1"; width = 24; height = 63; + color = 17; arg0 { title = "Push behavior"; @@ -3652,6 +3813,7 @@ udmf sprite = "REMTA0"; width = 64; height = 40; + color = 17; } 1218 { @@ -3659,33 +3821,7 @@ udmf sprite = "TAZDCR"; width = 80; height = 416; - } - 1219 - { - title = "Minecart Spawner"; - sprite = "MCRTCLFR"; - width = 22; - height = 32; - } - 1220 - { - title = "Minecart Stopper"; - sprite = "MCRTIR"; - width = 32; - height = 32; - } - 1221 - { - title = "Minecart Saloon Door"; - sprite = "SALDARAL"; - width = 96; - height = 160; - arg0 - { - title = "Allow non-minecart players?"; - type = 11; - enum = "noyes"; - } + color = 11; } 1222 { @@ -3693,6 +3829,7 @@ udmf sprite = "TRAEBRBL"; width = 28; height = 32; + color = 15; } 1223 { @@ -3700,6 +3837,7 @@ udmf sprite = "ADSTA0"; width = 4; height = 4; + color = 15; } 1224 { @@ -3707,37 +3845,7 @@ udmf sprite = "STEAA0"; width = 4; height = 4; - } - 1229 - { - title = "Minecart Switch Point"; - sprite = "internal:zoom"; - width = 8; - height = 16; - arg0 - { - title = "Type"; - type = 11; - enum - { - 0 = "Disable"; - 1 = "Enable"; - } - } - } - 1230 - { - title = "Tiny Cactus"; - sprite = "CACTJ0"; - width = 13; - height = 28; - } - 1231 - { - title = "Small Cactus"; - sprite = "CACTK0"; - width = 15; - height = 60; + color = 15; } } @@ -3753,6 +3861,7 @@ udmf sprite = "internal:flameh"; width = 16; height = 40; + color = 17; arg0 { title = "On time"; @@ -3782,6 +3891,7 @@ udmf sprite = "internal:flamev"; width = 16; height = 40; + color = 17; arg0 { title = "On time"; @@ -3811,6 +3921,7 @@ udmf sprite = "internal:flame2"; width = 16; height = 24; + color = 17; } 1303 { @@ -3818,6 +3929,7 @@ udmf sprite = "internal:flame1"; width = 16; height = 24; + color = 17; } 1304 { @@ -3825,6 +3937,8 @@ udmf sprite = "LFALF0"; width = 30; height = 32; + color = 17; + hangs = 1; arg0 { title = "Initial delay"; @@ -3842,6 +3956,7 @@ udmf sprite = "PUMIA1A5"; width = 30; height = 60; + color = 11; arg0 { title = "Buoyant?"; @@ -3886,293 +4001,233 @@ udmf } } - botanicserenity + tutorial { color = 2; // Green - title = "Botanic Serenity"; - width = 16; - height = 32; - sprite = "BSZ1A0"; - 1400 + title = "Tutorial"; + + 799 { - title = "Tall Flower (Red)"; - sprite = "BSZ1A0"; + title = "Tutorial Plant"; + sprite = "TUPFH0"; + width = 40; + height = 144; + arg0 + { + title = "Start frame"; + } } - 1401 + } + + frozenhillside + { + color = 2; // Green + title = "Frozen Hillside"; + + 2100 { - title = "Tall Flower (Purple)"; - sprite = "BSZ1B0"; + title = "Ice Shard (Small)"; + sprite = "FHZIA0"; + width = 8; + height = 32; } - 1402 + 2101 { - title = "Tall Flower (Blue)"; - sprite = "BSZ1C0"; + title = "Ice Shard (Large)"; + sprite = "FHZIB0"; + width = 8; + height = 32; } - 1403 + 2102 { - title = "Tall Flower (Cyan)"; - sprite = "BSZ1D0"; + title = "Crystal Tree (Aqua)"; + sprite = "TRE3A0"; + width = 20; + height = 200; } - 1404 + 2103 { - title = "Tall Flower (Yellow)"; - sprite = "BSZ1E0"; + title = "Crystal Tree (Pink)"; + sprite = "TRE3B0"; + width = 20; + height = 200; } - 1405 + 2104 { - title = "Tall Flower (Orange)"; - sprite = "BSZ1F0"; + title = "Amy Cameo"; + sprite = "ROSYA1"; + width = 16; + height = 48; + color = 11; + arg0 + { + title = "Grayscale?"; + type = 11; + enum = "noyes"; + } } - 1410 + 2105 { - title = "Medium Flower (Red)"; - sprite = "BSZ2A0"; + title = "Mistletoe"; + sprite = "XMS6A0"; + width = 52; + height = 106; } - 1411 + } + + hauntedheights + { + color = 2; // Green + title = "Haunted Heights"; + + 2000 { - title = "Medium Flower (Purple)"; - sprite = "BSZ2B0"; + title = "Smashing Spikeball"; + sprite = "FMCEA0"; + width = 18; + height = 28; + color = 17; + arg0 + { + title = "Initial delay"; + } } - 1412 + 2001 { - title = "Medium Flower (Blue)"; - sprite = "BSZ2C0"; + title = "HHZ Grass"; + sprite = "HHZMA0"; + width = 16; + height = 40; } - 1413 + 2002 { - title = "Medium Flower (Cyan)"; - sprite = "BSZ2D0"; + title = "HHZ Tentacle 1"; + sprite = "HHZMB0"; + width = 16; + height = 40; } - 1414 + 2003 { - title = "Medium Flower (Yellow)"; - sprite = "BSZ2E0"; + title = "HHZ Tentacle 2"; + sprite = "HHZMC0"; + width = 16; + height = 40; } - 1415 + 2004 { - title = "Medium Flower (Orange)"; - sprite = "BSZ2F0"; + title = "HHZ Stalagmite (Tall)"; + sprite = "HHZME0"; + width = 16; + height = 40; } - 1420 + 2005 { - title = "Short Flower (Red)"; - sprite = "BSZ3A0"; + title = "HHZ Stalagmite (Short)"; + sprite = "HHZMF0"; + width = 16; + height = 40; } - 1421 + 2006 { - title = "Short Flower (Purple)"; - sprite = "BSZ3B0"; + title = "Jack-o'-lantern 1"; + sprite = "PUMKA0"; + width = 16; + height = 40; + arg0 + { + title = "Flicker"; + type = 11; + enum = "yesno"; + } } - 1422 + 2007 { - title = "Short Flower (Blue)"; - sprite = "BSZ3C0"; + title = "Jack-o'-lantern 2"; + sprite = "PUMKB0"; + width = 16; + height = 40; + arg0 + { + title = "Flicker"; + type = 11; + enum = "yesno"; + } } - 1423 + 2008 { - title = "Short Flower (Cyan)"; - sprite = "BSZ3D0"; + title = "Jack-o'-lantern 3"; + sprite = "PUMKC0"; + width = 16; + height = 40; + arg0 + { + title = "Flicker"; + type = 11; + enum = "yesno"; + } } - 1424 + 2009 { - title = "Short Flower (Yellow)"; - sprite = "BSZ3E0"; + title = "Purple Mushroom"; + sprite = "SHRMD0"; + width = 16; + height = 48; } - 1425 + 2010 { - title = "Short Flower (Orange)"; - sprite = "BSZ3F0"; + title = "HHZ Tree"; + sprite = "HHPLC0"; + width = 12; + height = 40; } - 1430 + } + + azuretemple + { + color = 2; // Green + title = "Azure Temple"; + + 1500 { - title = "Tulip (Red)"; - sprite = "BST1A0"; + arrow = 1; + blocking = 2; + title = "Glaregoyle"; + sprite = "BGARA1"; + width = 16; + height = 40; + color = 17; + arg0 + { + title = "Push behavior"; + type = 11; + enum = "pushablebehavior"; + } + arg1 + { + title = "Starting delay"; + } } - 1431 + 1501 { - title = "Tulip (Purple)"; - sprite = "BST2A0"; + arrow = 1; + blocking = 2; + title = "Glaregoyle (Up)"; + sprite = "BGARA1"; + width = 16; + height = 40; + color = 17; + arg0 + { + title = "Push behavior"; + type = 11; + enum = "pushablebehavior"; + } + arg1 + { + title = "Starting delay"; + } } - 1432 - { - title = "Tulip (Blue)"; - sprite = "BST3A0"; - } - 1433 - { - title = "Tulip (Cyan)"; - sprite = "BST4A0"; - } - 1434 - { - title = "Tulip (Yellow)"; - sprite = "BST5A0"; - } - 1435 - { - title = "Tulip (Orange)"; - sprite = "BST6A0"; - } - 1440 - { - title = "Cluster (Red)"; - sprite = "BSZ5A0"; - } - 1441 - { - title = "Cluster (Purple)"; - sprite = "BSZ5B0"; - } - 1442 - { - title = "Cluster (Blue)"; - sprite = "BSZ5C0"; - } - 1443 - { - title = "Cluster (Cyan)"; - sprite = "BSZ5D0"; - } - 1444 - { - title = "Cluster (Yellow)"; - sprite = "BSZ5E0"; - } - 1445 - { - title = "Cluster (Orange)"; - sprite = "BSZ5F0"; - } - 1450 - { - title = "Bush (Red)"; - sprite = "BSZ6A0"; - } - 1451 - { - title = "Bush (Purple)"; - sprite = "BSZ6B0"; - } - 1452 - { - title = "Bush (Blue)"; - sprite = "BSZ6C0"; - } - 1453 - { - title = "Bush (Cyan)"; - sprite = "BSZ6D0"; - } - 1454 - { - title = "Bush (Yellow)"; - sprite = "BSZ6E0"; - } - 1455 - { - title = "Bush (Orange)"; - sprite = "BSZ6F0"; - } - 1460 - { - title = "Vine (Red)"; - sprite = "BSZ7A0"; - } - 1461 - { - title = "Vine (Purple)"; - sprite = "BSZ7B0"; - } - 1462 - { - title = "Vine (Blue)"; - sprite = "BSZ7C0"; - } - 1463 - { - title = "Vine (Cyan)"; - sprite = "BSZ7D0"; - } - 1464 - { - title = "Vine (Yellow)"; - sprite = "BSZ7E0"; - } - 1465 - { - title = "Vine (Orange)"; - sprite = "BSZ7F0"; - } - 1470 - { - title = "BSZ Shrub"; - sprite = "BSZ8A0"; - } - 1471 - { - title = "BSZ Clover"; - sprite = "BSZ8B0"; - } - 1473 - { - title = "Palm Tree (Big)"; - width = 16; - height = 160; - sprite = "BSZ8D0"; - } - 1475 - { - title = "Palm Tree (Small)"; - width = 16; - height = 80; - sprite = "BSZ8F0"; - } - } - - azuretemple - { - color = 2; // Green - title = "Azure Temple"; - - 1500 - { - arrow = 1; - blocking = 2; - title = "Glaregoyle"; - sprite = "BGARA1"; - width = 16; - height = 40; - arg0 - { - title = "Push behavior"; - type = 11; - enum = "pushablebehavior"; - } - arg1 - { - title = "Starting delay"; - } - } - 1501 - { - arrow = 1; - blocking = 2; - title = "Glaregoyle (Up)"; - sprite = "BGARA1"; - width = 16; - height = 40; - arg0 - { - title = "Push behavior"; - type = 11; - enum = "pushablebehavior"; - } - arg1 - { - title = "Starting delay"; - } - } - 1502 + 1502 { arrow = 1; blocking = 2; @@ -4180,6 +4235,7 @@ udmf sprite = "BGARA1"; width = 16; height = 40; + color = 17; arg0 { title = "Push behavior"; @@ -4199,6 +4255,7 @@ udmf sprite = "BGARA1"; width = 16; height = 40; + color = 17; arg0 { title = "Push behavior"; @@ -4216,6 +4273,7 @@ udmf sprite = "RCRYB0"; width = 24; height = 32; + color = 11; } 1505 { @@ -4223,6 +4281,7 @@ udmf sprite = "CFLMA0E0"; width = 8; height = 32; + color = 17; } 1506 { @@ -4232,6 +4291,7 @@ udmf sprite = "BGARD1"; width = 16; height = 40; + color = 6; arg0 { title = "Push behavior"; @@ -4241,44 +4301,10 @@ udmf } } - dreamhill - { - color = 2; // Green - title = "Dream Hill"; - - 1600 - { - title = "Spring Tree"; - sprite = "TRE6A0"; - width = 16; - height = 32; - } - 1601 - { - title = "Shleep"; - sprite = "SHLPA0"; - width = 24; - height = 32; - } - 1602 - { - title = "Nightopian"; - sprite = "NTPNA1"; - width = 16; - height = 40; - arg0 - { - title = "Can move?"; - type = 11; - enum = "yesno"; - } - } - } - nightstrk { color = 16; // Light Pink - title = "NiGHTS Track & Misc."; + title = "NiGHTS Track"; width = 8; height = 4096; sprite = "UNKNA0"; @@ -4299,6 +4325,7 @@ udmf arg2 { title = "Radius"; + default = 256; } arg3 { @@ -4337,12 +4364,21 @@ udmf title = "Order"; } } + } + + nights + { + color = 13; // Pink + title = "NiGHTS Items & Misc."; + width = 16; + height = 32; 1703 { title = "Ideya Drone"; sprite = "NDRNA1"; width = 16; height = 56; + color = 16; arg0 { title = "Time limit"; @@ -4380,6 +4416,7 @@ udmf sprite = "CAPSA0"; width = 72; height = 144; + color = 16; arg0 { title = "Mare"; @@ -4395,20 +4432,12 @@ udmf sprite = "internal:ideya"; width = 8; height = 16; + color = 16; arg0 { title = "Mare"; } } - } - - nights - { - color = 13; // Pink - title = "NiGHTS Items"; - width = 16; - height = 32; - 1704 { arrow = 1; @@ -4416,6 +4445,22 @@ udmf sprite = "NBMPG3G7"; width = 32; height = 64; + color = 12; + } + 520 + { + title = "Bomb Sphere"; + sprite = "SPHRD0"; + width = 16; + height = 24; + color = 17; + arg0 + { + title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; + type = 11; + enum = "yesno"; + } } 1706 { @@ -4423,9 +4468,11 @@ udmf sprite = "SPHRA0"; width = 16; height = 24; + color = 14; arg0 { title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } @@ -4513,231 +4560,310 @@ udmf width = 80; height = 160; centerhitbox = true; + color = 14; arg0 { title = "Radius"; + default = 96; } } } - mario + dreamhill { - color = 6; // Brown - title = "Mario"; + color = 2; // Green + title = "Dream Hill"; - 1800 + 1600 { - title = "Coin"; - sprite = "COINA0"; + title = "Spring Tree"; + sprite = "TRE6A0"; width = 16; - height = 24; - arg0 - { - title = "Float?"; - type = 11; - enum = "yesno"; - } - } - 1801 - { - arrow = 1; - title = "Goomba"; - sprite = "GOOMA0"; - width = 24; height = 32; } - 1802 + 1601 { - arrow = 1; - title = "Goomba (Blue)"; - sprite = "BGOMA0"; + title = "Shleep"; + sprite = "SHLPA0"; width = 24; height = 32; + color = 9; } - 1803 - { - title = "Fire Flower"; - sprite = "FFWRB0"; - width = 16; - height = 32; - } - 1804 - { - title = "Koopa Shell"; - sprite = "SHLLA1"; - width = 16; - height = 20; - } - 1805 - { - title = "Puma (Jumping Fireball)"; - sprite = "PUMAA0"; - width = 8; - height = 16; - arg0 - { - title = "Jump strength"; - } - } - 1806 + 1602 { - title = "King Bowser"; - sprite = "KOOPA0"; + title = "Nightopian"; + sprite = "NTPNA1"; width = 16; - height = 48; - arg0 - { - title = "Death trigger tag"; - type = 15; - } - } - 1807 - { - title = "Axe"; - sprite = "MAXEA0"; - width = 8; - height = 16; + height = 40; + color = 19; arg0 { - title = "Death trigger tag"; - type = 15; + title = "Can move?"; + type = 11; + enum = "yesno"; } } - 1808 - { - title = "Bush (Short)"; - sprite = "MUS1A0"; - width = 16; - height = 32; - } - 1809 - { - title = "Bush (Tall)"; - sprite = "MUS2A0"; - width = 16; - height = 32; - } - 1810 - { - title = "Toad"; - sprite = "TOADA0"; - width = 8; - height = 32; - } } - christmasdisco + botanicserenity { color = 2; // Green - title = "Christmas & Disco"; + title = "Botanic Serenity"; + width = 16; + height = 32; - 1850 - { - title = "Christmas Pole"; - sprite = "XMS1A0"; - width = 16; - height = 40; - } - 1851 - { - title = "Candy Cane"; - sprite = "XMS2A0"; - width = 8; - height = 32; - } - 1852 + flowers { - blocking = 2; - title = "Snowman"; - sprite = "XMS3A0"; - width = 16; - height = 64; - arg0 + title = "Flowers"; + 1400 { - title = "Push behavior"; - type = 11; - enum = "pushablebehavior"; + title = "Tall Flower (Red)"; + sprite = "BSZ1A0"; } - } - 1853 - { - blocking = 2; - title = "Snowman (With Hat)"; - sprite = "XMS3B0"; - width = 16; - height = 80; - arg0 + 1401 { - title = "Push behavior"; - type = 11; - enum = "pushablebehavior"; + title = "Tall Flower (Purple)"; + sprite = "BSZ1B0"; + } + 1402 + { + title = "Tall Flower (Blue)"; + sprite = "BSZ1C0"; + } + 1403 + { + title = "Tall Flower (Cyan)"; + sprite = "BSZ1D0"; + } + 1404 + { + title = "Tall Flower (Yellow)"; + sprite = "BSZ1E0"; + } + 1405 + { + title = "Tall Flower (Orange)"; + sprite = "BSZ1F0"; + } + 1410 + { + title = "Medium Flower (Red)"; + sprite = "BSZ2A0"; + } + 1411 + { + title = "Medium Flower (Purple)"; + sprite = "BSZ2B0"; + } + 1412 + { + title = "Medium Flower (Blue)"; + sprite = "BSZ2C0"; + } + 1413 + { + title = "Medium Flower (Cyan)"; + sprite = "BSZ2D0"; + } + 1414 + { + title = "Medium Flower (Yellow)"; + sprite = "BSZ2E0"; + } + 1415 + { + title = "Medium Flower (Orange)"; + sprite = "BSZ2F0"; + } + 1420 + { + title = "Short Flower (Red)"; + sprite = "BSZ3A0"; + } + 1421 + { + title = "Short Flower (Purple)"; + sprite = "BSZ3B0"; + } + 1422 + { + title = "Short Flower (Blue)"; + sprite = "BSZ3C0"; + } + 1423 + { + title = "Short Flower (Cyan)"; + sprite = "BSZ3D0"; + } + 1424 + { + title = "Short Flower (Yellow)"; + sprite = "BSZ3E0"; + } + 1425 + { + title = "Short Flower (Orange)"; + sprite = "BSZ3F0"; } } - 1854 + + tulips { - title = "Lamp Post"; - sprite = "XMS4A0"; - width = 8; - height = 120; + title = "Tulips"; + 1430 + { + title = "Tulip (Red)"; + sprite = "BST1A0"; + } + 1431 + { + title = "Tulip (Purple)"; + sprite = "BST2A0"; + } + 1432 + { + title = "Tulip (Blue)"; + sprite = "BST3A0"; + } + 1433 + { + title = "Tulip (Cyan)"; + sprite = "BST4A0"; + } + 1434 + { + title = "Tulip (Yellow)"; + sprite = "BST5A0"; + } + 1435 + { + title = "Tulip (Orange)"; + sprite = "BST6A0"; + } + 1440 + { + title = "Cluster (Red)"; + sprite = "BSZ5A0"; + } + 1441 + { + title = "Cluster (Purple)"; + sprite = "BSZ5B0"; + } + 1442 + { + title = "Cluster (Blue)"; + sprite = "BSZ5C0"; + } + 1443 + { + title = "Cluster (Cyan)"; + sprite = "BSZ5D0"; + } + 1444 + { + title = "Cluster (Yellow)"; + sprite = "BSZ5E0"; + } + 1445 + { + title = "Cluster (Orange)"; + sprite = "BSZ5F0"; + } } - 1855 + + bushes { - title = "Lamp Post (Snow)"; - sprite = "XMS4B0"; - width = 8; - height = 120; + title = "Bushes"; + 1450 + { + title = "Bush (Red)"; + sprite = "BSZ6A0"; + } + 1451 + { + title = "Bush (Purple)"; + sprite = "BSZ6B0"; + } + 1452 + { + title = "Bush (Blue)"; + sprite = "BSZ6C0"; + } + 1453 + { + title = "Bush (Cyan)"; + sprite = "BSZ6D0"; + } + 1454 + { + title = "Bush (Yellow)"; + sprite = "BSZ6E0"; + } + 1455 + { + title = "Bush (Orange)"; + sprite = "BSZ6F0"; + } } - 1856 + + vines { - title = "Hanging Star"; - sprite = "XMS5A0"; - width = 4; - height = 80; - hangs = 1; + title = "Vines"; + 1460 + { + title = "Vine (Red)"; + sprite = "BSZ7A0"; + } + 1461 + { + title = "Vine (Purple)"; + sprite = "BSZ7B0"; + } + 1462 + { + title = "Vine (Blue)"; + sprite = "BSZ7C0"; + } + 1463 + { + title = "Vine (Cyan)"; + sprite = "BSZ7D0"; + } + 1464 + { + title = "Vine (Yellow)"; + sprite = "BSZ7E0"; + } + 1465 + { + title = "Vine (Orange)"; + sprite = "BSZ7F0"; + } } - 1857 + 1470 { - title = "Berry Bush (Snow)"; - sprite = "BUS1B0"; - width = 16; - height = 32; + title = "BSZ Shrub"; + sprite = "BSZ8A0"; } - 1858 + 1471 { - title = "Bush (Snow)"; - sprite = "BUS2B0"; - width = 16; - height = 32; + title = "BSZ Clover"; + sprite = "BSZ8B0"; } - 1859 + 1473 { - title = "Blueberry Bush (Snow)"; - sprite = "BUS3B0"; + title = "Palm Tree (Big)"; width = 16; - height = 32; + height = 160; + sprite = "BSZ8D0"; } - 1875 + 1475 { - title = "Disco Ball"; - sprite = "DBALA0"; + title = "Palm Tree (Small)"; width = 16; - height = 54; - hangs = 1; - } - 1876 - { - arrow = 1; - blocking = 2; - title = "Eggman Disco Statue"; - sprite = "ESTAB1"; - width = 20; - height = 96; - arg0 - { - title = "Push behavior"; - type = 11; - enum = "pushablebehavior"; - } + height = 80; + sprite = "BSZ8F0"; } } @@ -4811,197 +4937,254 @@ udmf width = 16; height = 40; } - 1909 + 1909 + { + title = "Blue Stalagmite"; + sprite = "STLGJ0"; + width = 16; + height = 40; + } + } + + christmasdisco + { + color = 2; // Green + title = "Christmas & Disco"; + + 1850 + { + title = "Christmas Pole"; + sprite = "XMS1A0"; + width = 16; + height = 40; + } + 1851 + { + title = "Candy Cane"; + sprite = "XMS2A0"; + width = 8; + height = 32; + } + 1852 + { + blocking = 2; + title = "Snowman"; + sprite = "XMS3A0"; + width = 16; + height = 64; + color = 6; + arg0 + { + title = "Push behavior"; + type = 11; + enum = "pushablebehavior"; + } + } + 1853 { - title = "Blue Stalagmite"; - sprite = "STLGJ0"; + blocking = 2; + title = "Snowman (With Hat)"; + sprite = "XMS3B0"; width = 16; - height = 40; - } - } - - hauntedheights - { - color = 2; // Green - title = "Haunted Heights"; - - 2000 - { - title = "Smashing Spikeball"; - sprite = "FMCEA0"; - width = 18; - height = 28; + height = 80; + color = 6; arg0 { - title = "Initial delay"; + title = "Push behavior"; + type = 11; + enum = "pushablebehavior"; } } - 2001 + 1854 { - title = "HHZ Grass"; - sprite = "HHZMA0"; - width = 16; - height = 40; + title = "Lamp Post"; + sprite = "XMS4A0"; + width = 8; + height = 120; } - 2002 + 1855 { - title = "HHZ Tentacle 1"; - sprite = "HHZMB0"; - width = 16; - height = 40; + title = "Lamp Post (Snow)"; + sprite = "XMS4B0"; + width = 8; + height = 120; } - 2003 + 1856 { - title = "HHZ Tentacle 2"; - sprite = "HHZMC0"; - width = 16; - height = 40; + title = "Hanging Star"; + sprite = "XMS5A0"; + width = 4; + height = 80; + hangs = 1; } - 2004 + 1857 { - title = "HHZ Stalagmite (Tall)"; - sprite = "HHZME0"; + title = "Berry Bush (Snow)"; + sprite = "BUS1B0"; width = 16; - height = 40; + height = 32; } - 2005 + 1858 { - title = "HHZ Stalagmite (Short)"; - sprite = "HHZMF0"; + title = "Bush (Snow)"; + sprite = "BUS2B0"; width = 16; - height = 40; + height = 32; } - 2006 + 1859 { - title = "Jack-o'-lantern 1"; - sprite = "PUMKA0"; + title = "Blueberry Bush (Snow)"; + sprite = "BUS3B0"; width = 16; - height = 40; - arg0 - { - title = "Flicker"; - type = 11; - enum = "yesno"; - } + height = 32; } - 2007 + 1875 { - title = "Jack-o'-lantern 2"; - sprite = "PUMKB0"; + title = "Disco Ball"; + sprite = "DBALA0"; width = 16; - height = 40; + height = 54; + hangs = 1; + } + 1876 + { + arrow = 1; + blocking = 2; + title = "Eggman Disco Statue"; + sprite = "ESTAB1"; + width = 20; + height = 96; + color = 6; arg0 { - title = "Flicker"; + title = "Push behavior"; type = 11; - enum = "yesno"; + enum = "pushablebehavior"; } } - 2008 + } + + mario + { + color = 2; // Green + title = "Mario"; + + 1800 { - title = "Jack-o'-lantern 3"; - sprite = "PUMKC0"; + title = "Coin"; + sprite = "COINA0"; width = 16; - height = 40; + height = 24; + color = 14; arg0 { - title = "Flicker"; + title = "Float?"; + tooltip = "This raises the object by 24 fracunits."; type = 11; enum = "yesno"; } } - 2009 - { - title = "Purple Mushroom"; - sprite = "SHRMD0"; - width = 16; - height = 48; - } - 2010 + 1801 { - title = "HHZ Tree"; - sprite = "HHPLC0"; - width = 12; - height = 40; + arrow = 1; + title = "Goomba"; + sprite = "GOOMA0"; + width = 24; + height = 32; + color = 9; } - } - - frozenhillside - { - color = 2; // Green - title = "Frozen Hillside"; - - 2100 + 1802 { - title = "Ice Shard (Small)"; - sprite = "FHZIA0"; - width = 8; + arrow = 1; + title = "Goomba (Blue)"; + sprite = "BGOMA0"; + width = 24; height = 32; + color = 9; } - 2101 + 1803 { - title = "Ice Shard (Large)"; - sprite = "FHZIB0"; - width = 8; + title = "Fire Flower"; + sprite = "FFWRB0"; + width = 16; height = 32; + color = 14; } - 2102 + 1804 { - title = "Crystal Tree (Aqua)"; - sprite = "TRE3A0"; - width = 20; - height = 200; + title = "Koopa Shell"; + sprite = "SHLLA1"; + width = 16; + height = 20; + color = 11; } - 2103 + 1805 { - title = "Crystal Tree (Pink)"; - sprite = "TRE3B0"; - width = 20; - height = 200; + title = "Puma (Jumping Fireball)"; + sprite = "PUMAA0"; + width = 8; + height = 16; + color = 17; + arg0 + { + title = "Jump strength"; + } } - 2104 + 1806 { - title = "Amy Cameo"; - sprite = "ROSYA1"; + title = "King Bowser"; + sprite = "KOOPA0"; width = 16; height = 48; + color = 4; arg0 { - title = "Grayscale?"; - type = 11; - enum = "noyes"; + title = "Death trigger tag"; + type = 15; } } - 2105 - { - title = "Mistletoe"; - sprite = "XMS6A0"; - width = 52; - height = 106; - } - } - - tutorial - { - color = 2; // Green - title = "Tutorial"; - - 799 + 1807 { - title = "Tutorial Plant"; - sprite = "TUPFH0"; - width = 40; - height = 144; + title = "Axe"; + sprite = "MAXEA0"; + width = 8; + height = 16; + color = 11; arg0 { - title = "Start frame"; + title = "Death trigger tag"; + type = 15; } } + 1808 + { + title = "Bush (Short)"; + sprite = "MUS1A0"; + width = 16; + height = 32; + color = 2; + } + 1809 + { + title = "Bush (Tall)"; + sprite = "MUS2A0"; + width = 16; + height = 32; + color = 2; + } + 1810 + { + title = "Toad"; + sprite = "TOADA0"; + width = 8; + height = 32; + color = 2; + } } flickies { - color = 2; // Green + color = 6; // Brown title = "Flickies"; width = 8; height = 20; @@ -5391,7 +5574,7 @@ udmf } } } - + editor { color = 15; // White @@ -5404,4 +5587,4 @@ udmf 3328 = "3D Mode Start"; } -} \ No newline at end of file +} diff --git a/extras/conf/udb/SRB2-22binary.cfg b/extras/conf/udb/SRB2-22binary.cfg new file mode 100644 index 0000000000000000000000000000000000000000..2144ff7a61591b1c9a6865013cd44499179f2183 --- /dev/null +++ b/extras/conf/udb/SRB2-22binary.cfg @@ -0,0 +1,7183 @@ +/*********************************************************\ + Zone Builder Game Configuration + For Sonic Robo Blast 2 Version 2.2 + Contributors (alphabetical): + * Foxboy + * FuriousFox + * JJames19119 + * Kalaron + * Kristos + * MascaraSnake + * mazmazz + * Morpheus + * Neo Chaotikal + * Nev3r + * Oogaland + * Rob + * Shadow Hog + * sphere + * SRB2-Playah + * SSNTails + * SteelT + * ST218 + * toaster + * Viola +\*********************************************************/ + +// 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 (legacy)"; + +//GZDB specific. Don't try to load lumps that don't exist. +basegame = "doom"; + +// This is the simplified game engine/sourceport name +engine = "zdoom"; + +// When this is set to true, sectors with the same tag will light up when a line is highlighted +linetagindicatesectors = true; + +// The format interface handles the map data format - DoomMapSetIO for SRB2DB2, SRB2MapSetIO for Zone Builder +formatinterface = "DoomMapSetIO"; + +//Maximum safe map size check (0 means skip check) +safeboundary = 0; + +//Sky textures for vanilla maps +defaultskytextures +{ + SKY1 = "MAP01,MAP02,MAP03,MAP33,MAP50,MAP60,MAPF0,MAPM0"; + SKY2 = "MAPM7,MAPMB"; + SKY4 = "MAP04,MAP06,MAP61,MAPF6,MAPM1"; + SKY6 = "MAP05,MAP51,MAPMA"; + SKY7 = "MAPM2,MAPM5"; + SKY8 = "MAP07,MAP08,MAP09,MAP52,MAP62,MAPF1"; + SKY10 = "MAP10,MAP12,MAP53,MAP63,MAPM3"; + SKY11 = "MAP11,MAPF7"; + SKY13 = "MAP13,MAP64"; + SKY14 = "MAP14"; + SKY15 = "MAP15,MAP54"; + SKY17 = "MAP70"; + SKY20 = "MAP32,MAP55,MAP65,MAPF2,MAPF5"; + SKY21 = "MAPM4"; + SKY22 = "MAP22,MAP23,MAP25,MAP26,MAP27,MAP56,MAP66,MAPF4,MAPM6"; + SKY30 = "MAP30"; + SKY31 = "MAP31"; + SKY35 = "MAP42"; + SKY40 = "MAP41,MAP71,MAPM9"; + SKY55 = "MAPF3,MAPM8"; + SKY68 = "MAPF8"; + SKY99 = "MAP57,MAPZ0"; + SKY159 = "MAP16"; + SKY172 = "MAP40"; + SKY300 = "MAP72"; + SKY301 = "MAP73"; +} + +// Default lump name for new map +defaultlumpname = "MAP01"; + +// Default testing parameters +testparameters = "-folder \"%AF\" -file \"%AA\" \"%F\" -warp %L"; +testshortpaths = true; + +// Default nodebuilder configurations +defaultsavecompiler = "zennode_normal"; +defaulttestcompiler = "zennode_fast"; + +// Skill levels +skills +{ + 1 = "Normal"; +} + +// Skins +skins +{ + Sonic; + Tails; + Knuckles; + Amy; + Fang; + Metalsonic; +} + +// Gametypes +gametypes +{ + -1 = "Single Player"; + 0 = "Co-op"; + 1 = "Competition"; + 2 = "Race"; + 3 = "Match"; + 4 = "Team Match"; + 5 = "Tag"; + 6 = "Hide and Seek"; + 7 = "CTF"; +} + +// Special linedefs +soundlinedefflag = 64; // See linedefflags +singlesidedflag = 1; // See linedefflags +doublesidedflag = 4; // See linedefflags +impassableflag = 1; +upperunpeggedflag = 8; +lowerunpeggedflag = 16; +repeatmidtextureflag = 1024; +pegmidtextureflag = 256; + +// Generalized actions +generalizedlinedefs = false; +generalizedsectors = true; + +// Texture loading options +defaultwalltexture = "GFZROCK"; +defaultfloortexture = "GFZFLR01"; +defaultceilingtexture = "F_SKY1"; +mixtexturesflats = true; +defaulttexturescale = 1.0f; +defaultflatscale = 1.0f; + +// Thing number for start position in 3D Mode +start3dmode = 3328; + + + + +/* +TEXTURES AND FLAT SOURCES +This tells Doom Builder where to find the information for textures +and flats in the IWAD file, Addition WAD file and Map WAD file. + +Start and end lumps must be given in a structure (of which the +key name doesnt matter) and any textures or flats in between them +are loaded in either the textures category or flats category. + +For textures: PNAMES, TEXTURE1 and TEXTURE2 are loaded by default. +Kalaron: and now TX_START +*/ + +// Texture sources +textures +{ + zdoom1 + { + start = "TX_START"; + end = "TX_END"; + } +} + +// Patch sources +patches +{ + standard1 + { + start = "P_START"; + end = "P_END"; + } + + standard2 + { + start = "PP_START"; + end = "PP_END"; + } +} + +// Sprite sources +sprites +{ + standard1 + { + start = "S_START"; + end = "S_END"; + } + + standard2 + { + start = "SS_START"; + end = "SS_END"; + } +} + +// Flat sources +flats +{ + standard1 + { + start = "F_START"; + end = "F_END"; + } + + standard2 + { + start = "FF_START"; + end = "FF_END"; + } + + standard3 + { + start = "FF_START"; + end = "F_END"; + } + + standard4 + { + start = "F_START"; + end = "FF_END"; + } +} + + +/* +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 +{ + ~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; + } +} + +scriptlumpnames +{ + MAINCFG + { + script = "SOC.cfg"; + } + + OBJCTCFG + { + script = "SOC.cfg"; + } + + SOC_ + { + script = "SOC.cfg"; + isprefix = true; + } + + LUA_ + { + script = "Lua.cfg"; + isprefix = true; + } +} + +// DEFAULT SECTOR BRIGHTNESS LEVELS +sectorbrightness +{ + 255; + 248; + 240; + 232; + 224; + 216; + 208; + 200; + 192; + 184; + 176; + 168; + 160; + 152; + 144; + 136; + 128; + 120; + 112; + 104; + 96; + 88; + 80; + 72; + 64; + 56; + 48; + 40; + 32; + 24; + 16; + 8; + 0; +} + +// SECTOR TYPES----------------------------------------------------------------- +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>"; + 512 = "Wind/Current <deprecated>"; + 1024 = "Conveyor Belt <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"; +} + + +// GENERALISED SECTOR TYPES----------------------------------------------------------------- +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"; + 512 = "Wind/Current <deprecated>"; + 1024 = "Conveyor Belt <deprecated>"; + 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"; + } +} + +// LINEDEF FLAGS +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 +linedefflagstranslation +{ + 1 = "blocking"; + 2 = "blockmonsters"; + 4 = "twosided"; + 8 = "dontpegtop"; + 16 = "dontpegbottom"; + 32 = "secret"; + 64 = "blocksound"; + 128 = "dontdraw"; + 256 = "mapped"; +} + +// LINEDEF ACTIVATIONS +linedefactivations +{ +} + +// LINEDEF TYPES +linedeftypes +{ + misc + { + title = "Miscellaneous"; + + 0 + { + title = "None"; + prefix = "(0)"; + } + + 1 + { + title = "Per-Sector Gravity"; + prefix = "(1)"; + flags64text = "[6] Flip in reverse gravity"; + flags8192text = "[13] Cancel MF2_OBJECTFLIP"; + } + + 5 + { + title = "Camera Scanner"; + prefix = "(5)"; + } + + 7 + { + title = "Sector Flat Alignment"; + prefix = "(7)"; + flags2048text = "[11] Don't align floor"; + flags4096text = "[12] Don't align ceiling"; + flags8192text = "[13] Use texture offsets"; + } + + 10 + { + title = "Culling Plane"; + prefix = "(10)"; + flags64text = "[6] Cull only while in sector"; + } + + 13 + { + title = "Heat Wave Effect"; + prefix = "(13)"; + } + + 40 + { + title = "Visual Portal Between Tagged Linedefs"; + prefix = "(40)"; + } + + 41 + { + title = "Horizon Effect"; + prefix = "(41)"; + } + + 50 + { + title = "Instantly Lower Floor on Level Load"; + prefix = "(50)"; + } + + 51 + { + title = "Instantly Raise Ceiling on Level Load"; + prefix = "(51)"; + } + + 63 + { + title = "Fake Floor/Ceiling Planes"; + prefix = "(63)"; + } + + 96 + { + title = "Add Front Sector Tag to Tagged Sectors"; + prefix = "(96)"; + flags1024text = "[10] Offsets are target tags"; + flags8192text = "[13] Add front side offsets"; + flags32768text = "[15] Add back side offsets"; + } + + 97 + { + title = "Add Tag to Front Sector"; + prefix = "(97)"; + flags8192text = "[13] Add front side offsets"; + flags32768text = "[15] Add back side offsets"; + } + + 98 + { + title = "Add Tag to Back Sector"; + prefix = "(98)"; + flags8192text = "[13] Add front side offsets"; + flags32768text = "[15] Add back side offsets"; + } + + 99 + { + title = "Add Tag to Front and Back Sectors"; + prefix = "(99)"; + flags8192text = "[13] Add front side offsets"; + flags32768text = "[15] Add back side offsets"; + } + + 540 + { + title = "Floor Friction"; + prefix = "(540)"; + } + } + + parameters + { + title = "Parameters"; + + 2 + { + title = "Custom Exit"; + prefix = "(2)"; + flags2text = "[1] Check emeralds"; + flags64text = "[6] Skip score tally"; + } + + 3 + { + title = "Zoom Tube Parameters"; + prefix = "(3)"; + flags512text = "[9] Ignore player direction"; + } + + 4 + { + title = "Speed Pad Parameters"; + prefix = "(4)"; + flags512text = "[9] No teleport to center"; + flags1024text = "[10] Force spinning frames"; + } + + 8 + { + title = "Special Sector Properties"; + prefix = "(8)"; + flags32text = "[5] Invert precipitation"; + flags64text = "[6] Touch only ceiling"; + flags128text = "[7] Allow opposite gravity"; + flags256text = "[8] Touch sector edge"; + flags512text = "[9] Touch floor or ceiling"; + } + + 9 + { + title = "Chain Parameters"; + prefix = "(9)"; + flags32text = "[5] Swing instead of spin"; + flags128text = "[7] Make chain from end item"; + flags64text = "[6] Player-turnable chain"; + flags256text = "[8] Spawn link at origin"; + flags512text = "[9] Don't clip inside ground"; + flags1024text = "[10] No distance check"; + } + + 11 + { + title = "Rope Hang Parameters"; + prefix = "(11)"; + flags32text = "[5] Don't loop"; + flags64text = "[6] Static"; + } + + 12 + { + title = "Rock Spawner Parameters"; + prefix = "(12)"; + flags64text = "[6] Randomize speed"; + } + + 14 + { + title = "Bustable Block Parameters"; + prefix = "(14)"; + flags32text = "[5] Particles launch from center"; + } + + 15 + { + title = "Fan Particle Spawner Parameters"; + prefix = "(15)"; + } + + 16 + { + title = "Minecart Parameters"; + prefix = "(16)"; + } + + 64 + { + title = "Continuously Appearing/Disappearing FOF"; + prefix = "(64)"; + flags2text = "[1] Use control sector tag"; + flags64text = "[6] No sound effect"; + } + + 76 + { + title = "Make FOF Bouncy"; + prefix = "(76)"; + } + } + + polyobject + { + title = "PolyObject"; + + 20 + { + title = "PolyObject First Line"; + prefix = "(20)"; + } + + 22 + { + title = "PolyObject Parameters"; + prefix = "(22)"; + flags8text = "[3] Set translucency by X offset"; + flags32text = "[5] Render outer sides only"; + flags64text = "[6] Trigger linedef executor"; + flags128text = "[7] Intangible"; + flags256text = "[8] Stopped by pushables"; + flags512text = "[9] Render flats"; + flags8192text = "[13] Cut cyan flat pixels"; + } + + 30 + { + title = "PolyObject Waving Flag"; + prefix = "(30)"; + } + + 31 + { + title = "Move PolyObject by Front Sector Displacement"; + prefix = "(31)"; + } + + 32 + { + title = "Rotate PolyObject by Front Sector Displacement"; + prefix = "(32)"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + } + + planemove + { + title = "Plane Movement"; + + 52 + { + title = "Continuously Falling Sector"; + prefix = "(52)"; + flags64text = "[6] Continuously rising"; + } + + 53 + { + title = "Continuous Floor/Ceiling Mover"; + prefix = "(53)"; + } + + 54 + { + title = "Continuous Floor Mover"; + prefix = "(54)"; + } + + 55 + { + title = "Continuous Ceiling Mover"; + prefix = "(55)"; + } + + 56 + { + title = "Continuous Two-Speed Floor/Ceiling Mover"; + prefix = "(56)"; + } + + 57 + { + title = "Continuous Two-Speed Floor Mover"; + prefix = "(57)"; + } + + 58 + { + title = "Continuous Two-Speed Ceiling Mover"; + prefix = "(58)"; + } + + 59 + { + title = "Activate Moving Platform"; + prefix = "(59)"; + flags64text = "[6] Move upwards at start"; + } + + 60 + { + title = "Activate Moving Platform (Adjustable Speed)"; + prefix = "(60)"; + flags64text = "[6] Move upwards at start"; + } + + 61 + { + title = "Crusher (Ceiling to Floor)"; + prefix = "(61)"; + flags512text = "[9] Double, constant speed"; + } + + 62 + { + title = "Crusher (Floor to Ceiling)"; + prefix = "(62)"; + flags512text = "[9] Double, constant speed"; + } + + 66 + { + title = "Move Floor by Displacement"; + prefix = "(66)"; + flags64text = "[6] Inverse movement"; + } + + 67 + { + title = "Move Ceiling by Displacement"; + prefix = "(67)"; + flags64text = "[6] Inverse movement"; + } + + 68 + { + title = "Move Floor and Ceiling by Displacement"; + prefix = "(68)"; + flags64text = "[6] Inverse movement"; + } + } + + fofsolid + { + title = "FOF (solid)"; + + 100 + { + title = "Solid, Opaque"; + prefix = "(100)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 101 + { + title = "Solid, Opaque, No Shadow"; + prefix = "(101)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1DF"; + } + + 102 + { + title = "Solid, Translucent"; + prefix = "(102)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Render insides"; + flags128text = "[7] Only block non-players"; + flags8192text = "[13] Cut cyan flat pixels"; + 3dfloor = true; + 3dfloorflags = "195F"; + flags643dfloorflagsadd = "7C80"; + } + + 103 + { + title = "Solid, Sides Only"; + prefix = "(103)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1CF"; + } + + 104 + { + title = "Solid, No Sides"; + prefix = "(104)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1D7"; + flags643dfloorflagsremove = "40"; + } + + 105 + { + title = "Solid, Invisible"; + prefix = "(105)"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "47"; + invisiblefof = true; + } + + 140 + { + title = "Intangible from Bottom, Opaque"; + prefix = "(140)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "200841F"; + flags643dfloorflagsadd = "40"; + } + + 141 + { + title = "Intangible from Bottom, Translucent"; + prefix = "(141)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Render insides/block non-plr"; + flags8192text = "[13] Cut cyan flat pixels"; + 3dfloor = true; + 3dfloorflags = "200191F"; + flags1283dfloorflagsadd = "7C80"; + flags643dfloorflagsadd = "40"; + } + + 142 + { + title = "Intangible from Bottom, Translucent, No Sides"; + prefix = "(142)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Render insides/block non-plr"; + flags8192text = "[13] Cut cyan flat pixels"; + 3dfloor = true; + 3dfloorflags = "2001917"; + flags1283dfloorflagsadd = "7C80"; + flags643dfloorflagsadd = "40"; + } + + 143 + { + title = "Intangible from Top, Opaque"; + prefix = "(143)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "400841F"; + flags643dfloorflagsadd = "40"; + } + + 144 + { + title = "Intangible from Top, Translucent"; + prefix = "(144)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Render insides/block non-plr"; + flags8192text = "[13] Cut cyan flat pixels"; + 3dfloor = true; + 3dfloorflags = "400191F"; + flags1283dfloorflagsadd = "7C80"; + flags643dfloorflagsadd = "40"; + } + + 145 + { + title = "Intangible from Top, Translucent, No Sides"; + prefix = "(145)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Render insides/block non-plr"; + flags8192text = "[13] Cut cyan flat pixels"; + 3dfloor = true; + 3dfloorflags = "4001917"; + flags1283dfloorflagsadd = "7C80"; + flags643dfloorflagsadd = "40"; + } + + 146 + { + title = "Only Tangible from Sides"; + prefix = "(146)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "600800F"; + } + } + + fofintangible + { + title = "FOF (intangible)"; + + 120 + { + title = "Water, Opaque"; + prefix = "(120)"; + flags2text = "[1] Make lava intangible"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "8F39"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 121 + { + title = "Water, Translucent"; + prefix = "(121)"; + flags2text = "[1] Make lava intangible"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + flags8192text = "[13] Cut cyan flat pixels"; + 3dfloor = true; + 3dfloorflags = "9F39"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 122 + { + title = "Water, Opaque, No Sides"; + prefix = "(122)"; + flags2text = "[1] Make lava intangible"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "F31"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 123 + { + title = "Water, Translucent, No Sides"; + prefix = "(123)"; + flags2text = "[1] Make lava intangible"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + flags8192text = "[13] Cut cyan flat pixels"; + 3dfloor = true; + 3dfloorflags = "1F31"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 124 + { + title = "Goo Water, Translucent"; + prefix = "(124)"; + flags2text = "[1] Make lava intangible"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + flags8192text = "[13] Cut cyan flat pixels"; + 3dfloor = true; + 3dfloorflags = "209F39"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 125 + { + title = "Goo Water, Translucent, No Sides"; + prefix = "(125)"; + flags2text = "[1] Make lava intangible"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + flags8192text = "[13] Cut cyan flat pixels"; + 3dfloor = true; + 3dfloorflags = "201F31"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 220 + { + title = "Intangible, Opaque"; + prefix = "(220)"; + flags8text = "[3] Slope skew sides"; + 3dfloor = true; + 3dfloorflags = "8F19"; + } + + 221 + { + title = "Intangible, Translucent"; + prefix = "(221)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Cast shadow"; + flags8192text = "[13] Cut cyan flat pixels"; + 3dfloor = true; + 3dfloorflags = "1B59"; + flags643dfloorflagsremove = "40"; + } + + 222 + { + title = "Intangible, Sides Only"; + prefix = "(222)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Cast shadow"; + 3dfloor = true; + 3dfloorflags = "8249"; + flags643dfloorflagsremove = "240"; + } + + 223 + { + title = "Intangible, Invisible"; + prefix = "(223)"; + 3dfloor = true; + 3dfloorflags = "41"; + invisiblefof = true; + } + } + + fofmoving + { + title = "FOF (moving)"; + + 150 + { + title = "Air Bobbing"; + prefix = "(150)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 151 + { + title = "Air Bobbing (Adjustable)"; + prefix = "(151)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 152 + { + title = "Reverse Air Bobbing (Adjustable)"; + prefix = "(152)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 153 + { + title = "Dynamically Sinking Platform"; + prefix = "(153)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 160 + { + title = "Water Bobbing"; + prefix = "(160)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "4019F"; + } + + 190 + { + title = "Rising Platform, Solid, Opaque"; + prefix = "(190)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 191 + { + title = "Rising Platform, Solid, Opaque, No Shadow"; + prefix = "(191)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1DF"; + } + + 192 + { + title = "Rising Platform, Solid, Translucent"; + prefix = "(192)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + flags8192text = "[13] Cut cyan flat pixels"; + 3dfloor = true; + 3dfloorflags = "195F"; + } + + 193 + { + title = "Rising Platform, Solid, Invisible"; + prefix = "(193)"; + flags2text = "[1] Sink when stepped on"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "47"; + } + + 194 + { + title = "Rising Platform, Intangible from Bottom, Opaque"; + prefix = "(194)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash, no shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "200841F"; + flags643dfloorflagsadd = "40"; + } + + 195 + { + title = "Rising Platform, Intangible from Bottom, Translucent"; + prefix = "(195)"; + flags2text = "[1] Sink when stepped on"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash, no shadow"; + flags128text = "[7] Only block non-players"; + flags8192text = "[13] Cut cyan flat pixels"; + 3dfloor = true; + 3dfloorflags = "2009D1F"; + flags643dfloorflagsadd = "40"; + } + } + + fofcrumbling + { + title = "FOF (crumbling)"; + + 170 + { + title = "Crumbling, Respawn"; + prefix = "(170)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "10019F"; + } + + 171 + { + title = "Crumbling, No Respawn"; + prefix = "(171)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "80019F"; + } + + 172 + { + title = "Crumbling, Respawn, Intangible from Bottom"; + prefix = "(172)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "210841F"; + flags643dfloorflagsadd = "40"; + } + + 173 + { + title = "Crumbling, No Respawn, Intangible from Bottom"; + prefix = "(173)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "218841F"; + flags643dfloorflagsadd = "40"; + } + + 174 + { + title = "Crumbling, Respawn, Int. from Bottom, Translucent"; + prefix = "(174)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + flags8192text = "[13] Cut cyan flat pixels"; + 3dfloor = true; + 3dfloorflags = "210959F"; + flags643dfloorflagsadd = "40"; + } + + 175 + { + title = "Crumbling, No Respawn, Int. from Bottom, Translucent"; + prefix = "(175)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + flags8192text = "[13] Cut cyan flat pixels"; + 3dfloor = true; + 3dfloorflags = "218959F"; + flags643dfloorflagsadd = "40"; + } + + 176 + { + title = "Crumbling, Respawn, Floating, Bobbing"; + prefix = "(176)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "14019F"; + } + + 177 + { + title = "Crumbling, No Respawn, Floating, Bobbing"; + prefix = "(177)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1C019F"; + } + + 178 + { + title = "Crumbling, Respawn, Floating"; + prefix = "(178)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "14019F"; + } + + 179 + { + title = "Crumbling, No Respawn, Floating"; + prefix = "(179)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1C019F"; + } + + 180 + { + title = "Crumbling, Respawn, Air Bobbing"; + prefix = "(180)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "10019F"; + } + } + + fofspecial + { + title = "FOF (special)"; + + 200 + { + title = "Light Block"; + prefix = "(200)"; + 3dfloor = true; + 3dfloorflags = "20201"; + invisiblefof = true; + } + + 201 + { + title = "Half Light Block"; + prefix = "(201)"; + 3dfloor = true; + 3dfloorflags = "201"; + invisiblefof = true; + } + + 202 + { + title = "Fog Block"; + prefix = "(202)"; + 3dfloor = true; + 3dfloorflags = "3EF01"; + invisiblefof = true; + } + + 250 + { + title = "Mario Block"; + prefix = "(250)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Invisible block"; + flags64text = "[6] Brick block"; + 3dfloor = true; + 3dfloorflags = "40019F"; + flags323dfloorflagsremove = "19E"; + flags643dfloorflagsadd = "200000"; + } + + 251 + { + title = "Thwomp Block"; + prefix = "(251)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + flags512text = "[9] Custom crushing sound"; + flags1024text = "[10] Custom speed"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 252 + { + title = "Shatter Block"; + prefix = "(252)"; + flags8text = "[3] Slope skew sides"; + flags64text = "[6] Shatter only from below"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "880001D"; + flags643dfloorflagsadd = "200002"; + } + + 253 + { + title = "Shatter Block, Translucent"; + prefix = "(253)"; + flags8text = "[3] Slope skew sides"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + flags8192text = "[13] Cut cyan flat pixels"; + 3dfloor = true; + 3dfloorflags = "880101D"; + } + + 254 + { + title = "Bustable Block"; + prefix = "(254)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags64text = "[6] Strong characters only"; + flags128text = "[7] Only block non-players"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "80001F"; + flags643dfloorflagsadd = "20000000"; + } + + 255 + { + title = "Spin-Bustable Block"; + prefix = "(255)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "1080001F"; + } + + 256 + { + title = "Spin-Bustable Block, Translucent"; + prefix = "(256)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + flags8192text = "[13] Cut cyan flat pixels"; + 3dfloor = true; + 3dfloorflags = "1080101F"; + } + + 257 + { + title = "Quicksand"; + prefix = "(257)"; + flags8text = "[3] Slope skew sides"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "1008219"; + flags10243dfloorflagsadd = "40000000"; + } + + 258 + { + title = "Laser"; + prefix = "(258)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Don't damage bosses"; + flags8192text = "[13] Cut cyan flat pixels"; + 3dfloor = true; + 3dfloorflags = "959"; + } + + 259 + { + title = "Custom FOF"; + prefix = "(259)"; + flags8text = "[3] Slope skew sides"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + flags8192text = "[13] Cut cyan flat pixels"; + 3dfloor = true; + 3dfloorcustom = true; + } + } + + linedeftrigger + { + title = "Linedef Executor Trigger"; + + 300 + { + title = "Continuous"; + prefix = "(300)"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 301 + { + title = "Each Time"; + prefix = "(301)"; + flags1024text = "[10] Use faster, unordered execution"; + flags16384text = "[14] Also trigger on exit"; + } + + 302 + { + title = "Once"; + prefix = "(302)"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 303 + { + title = "Ring Count - Continuous"; + prefix = "(303)"; + flags2text = "[1] Rings greater or equal"; + flags64text = "[6] Rings less or equal"; + flags512text = "[9] Consider all players"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 304 + { + title = "Ring Count - Once"; + prefix = "(304)"; + flags2text = "[1] Rings greater or equal"; + flags64text = "[6] Rings less or equal"; + flags512text = "[9] Consider all players"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 305 + { + title = "Character Ability - Continuous"; + prefix = "(305)"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 306 + { + title = "Character Ability - Each Time"; + prefix = "(306)"; + flags1024text = "[10] Use faster, unordered execution"; + flags16384text = "[14] Also trigger on exit"; + } + + 307 + { + title = "Character Ability - Once"; + prefix = "(307)"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 308 + { + title = "Race Only - Once"; + prefix = "(308)"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 309 + { + title = "CTF Red Team - Continuous"; + prefix = "(309)"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 310 + { + title = "CTF Red Team - Each Time"; + prefix = "(310)"; + flags1024text = "[10] Use faster, unordered execution"; + flags16384text = "[14] Also trigger on exit"; + } + + 311 + { + title = "CTF Blue Team - Continuous"; + prefix = "(311)"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 312 + { + title = "CTF Blue Team - Each Time"; + prefix = "(312)"; + flags1024text = "[10] Use faster, unordered execution"; + flags16384text = "[14] Also trigger on exit"; + } + + 313 + { + title = "No More Enemies - Once"; + prefix = "(313)"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 314 + { + title = "Number of Pushables - Continuous"; + prefix = "(314)"; + flags64text = "[6] Number greater or equal"; + flags512text = "[9] Number less"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 315 + { + title = "Number of Pushables - Once"; + prefix = "(315)"; + flags64text = "[6] Number greater or equal"; + flags512text = "[9] Number less"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 317 + { + title = "Condition Set Trigger - Continuous"; + prefix = "(317)"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 318 + { + title = "Condition Set Trigger - Once"; + prefix = "(318)"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 319 + { + title = "Unlockable - Continuous"; + prefix = "(319)"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 320 + { + title = "Unlockable - Once"; + prefix = "(320)"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 321 + { + title = "Trigger After X Calls - Continuous"; + prefix = "(321)"; + flags64text = "[6] Trigger more than once"; + flags1024text = "[10] Use faster, unordered execution"; + + } + + 322 + { + title = "Trigger After X Calls - Each Time"; + prefix = "(322)"; + flags64text = "[6] Trigger more than once"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 323 + { + title = "NiGHTSerize - Each Time"; + prefix = "(323)"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run only if player is NiGHTS"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags1024text = "[10] Use faster, unordered execution"; + flags16384text = "[14] Run if no more mares"; + flags32768text = "[15] Run if player is not NiGHTS"; + } + + 324 + { + title = "NiGHTSerize - Once"; + prefix = "(324)"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run only if player is NiGHTS"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags1024text = "[10] Use faster, unordered execution"; + flags16384text = "[14] Run if no more mares"; + flags32768text = "[15] Run if player is not NiGHTS"; + } + + 325 + { + title = "De-NiGHTSerize - Each Time"; + prefix = "(325)"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run if anyone is NiGHTS"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags1024text = "[10] Use faster, unordered execution"; + flags32768text = "[15] Run if no one is NiGHTS"; + } + + 326 + { + title = "De-NiGHTSerize - Once"; + prefix = "(326)"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run if anyone is NiGHTS"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags1024text = "[10] Use faster, unordered execution"; + flags32768text = "[15] Run if no one is NiGHTS"; + } + + 327 + { + title = "NiGHTS Lap - Each Time"; + prefix = "(327)"; + flags2text = "[1] Mare >= Front X Offset"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 328 + { + title = "NiGHTS Lap - Once"; + prefix = "(328)"; + flags2text = "[1] Mare >= Front X Offset"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 329 + { + title = "Ideya Capture Touch - Each Time"; + prefix = "(329)"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run regardless of spheres"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags1024text = "[10] Use faster, unordered execution"; + flags16384text = "[14] Only if not enough spheres"; + flags32768text = "[15] Run when entering Capture"; + } + + 330 + { + title = "Ideya Capture Touch - Once"; + prefix = "(330)"; + flags2text = "[1] Mare >= Front X Offset"; + flags8text = "[3] Run regardless of spheres"; + flags16text = "[4] Count from lowest of players"; + flags32text = "[5] Lap <= Front Y Offset"; + flags64text = "[6] Mare <= Front X Offset"; + flags128text = "[7] Lap >= Front Y Offset"; + flags256text = "[8] Count laps from Bonus Time"; + flags512text = "[9] Count from triggering player"; + flags1024text = "[10] Use faster, unordered execution"; + flags16384text = "[14] Only if not enough spheres"; + flags32768text = "[15] Run when entering Capture"; + } + + 331 + { + title = "Player Skin - Continuous"; + prefix = "(331)"; + flags64text = "[6] Disable for this skin"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 332 + { + title = "Player Skin - Each Time"; + prefix = "(332)"; + flags64text = "[6] Disable for this skin"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 333 + { + title = "Player Skin - Once"; + prefix = "(333)"; + flags64text = "[6] Disable for this skin"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 334 + { + title = "Object Dye - Continuous"; + prefix = "(334)"; + flags64text = "[6] Disable for this color"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 335 + { + title = "Object Dye - Each Time"; + prefix = "(335)"; + flags64text = "[6] Disable for this color"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 336 + { + title = "Object Dye - Once"; + prefix = "(336)"; + flags64text = "[6] Disable for this color"; + flags1024text = "[10] Use faster, unordered execution"; + } + + 337 + { + title = "Emerald Check - Continuous"; + prefix = "(337)"; + } + + 338 + { + title = "Emerald Check - Each Time"; + prefix = "(338)"; + } + + 339 + { + title = "Emerald Check - Once"; + prefix = "(339)"; + } + + 340 + { + title = "NiGHTS Mare - Continuous"; + flags2text = "[1] Mare greater or equal"; + flags64text = "[6] Mare less or equal"; + prefix = "(340)"; + } + + 341 + { + title = "NiGHTS Mare - Each Time"; + flags2text = "[1] Mare greater or equal"; + flags64text = "[6] Mare less or equal"; + prefix = "(341)"; + } + + 342 + { + title = "NiGHTS Mare - Once"; + flags2text = "[1] Mare greater or equal"; + flags64text = "[6] Mare less or equal"; + prefix = "(342)"; + } + + 343 + { + title = "Gravity Check - Continuous"; + flags2text = "[1] Check temporary reverse gravity"; + flags64text = "[6] Check for reverse gravity"; + prefix = "(343)"; + } + + 344 + { + title = "Gravity Check - Each Time"; + flags2text = "[1] Check temporary reverse gravity"; + flags64text = "[6] Check for reverse gravity"; + prefix = "(344)"; + } + + 345 + { + title = "Gravity Check - Once"; + flags2text = "[1] Check temporary reverse gravity"; + flags64text = "[6] Check for reverse gravity"; + prefix = "(345)"; + } + + 399 + { + title = "Level Load"; + prefix = "(399)"; + flags1024text = "[10] Use faster, unordered execution"; + } + } + + linedefexecsector + { + title = "Linedef Executor (sector)"; + + 400 + { + title = "Set Tagged Sector's Floor Height/Texture"; + prefix = "(400)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't change floor texture"; + } + + 401 + { + title = "Set Tagged Sector's Ceiling Height/Texture"; + prefix = "(401)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't change ceiling texture"; + } + + 402 + { + title = "Copy Light Level to Tagged Sectors"; + prefix = "(402)"; + flags8text = "[3] Set delay by backside sector"; + } + + 408 + { + title = "Set Tagged Sector's Flats"; + prefix = "(408)"; + flags64text = "[6] Don't set floor flat"; + flags512text = "[9] Don't set ceiling flat"; + } + + 409 + { + title = "Change Tagged Sector's Tag"; + prefix = "(409)"; + flags2text = "[1] Remove tag"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Add tag"; + } + + 410 + { + title = "Change Front Sector's Tag"; + prefix = "(410)"; + flags2text = "[1] Remove tag"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Add tag"; + } + + 416 + { + title = "Start Adjustable Flickering Light"; + prefix = "(416)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Second level from back"; + } + + 417 + { + title = "Start Adjustable Pulsating Light"; + prefix = "(417)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Second level from back"; + } + + 418 + { + title = "Start Adjustable Blinking Light (unsynchronized)"; + prefix = "(418)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Second level from back"; + } + + 419 + { + title = "Start Adjustable Blinking Light (synchronized)"; + prefix = "(419)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Second level from back"; + } + + 420 + { + title = "Fade Light Level"; + prefix = "(420)"; + flags8text = "[3] Set delay by backside sector"; + flags16text = "[4] Set params by X/Y offsets"; + flags512text = "[9] Speed = Tic Duration"; + flags1024text = "[10] Override existing fade"; + } + + 421 + { + title = "Stop Lighting Effect"; + prefix = "(421)"; + flags8text = "[3] Set delay by backside sector"; + } + + 435 + { + title = "Change Plane Scroller Direction"; + prefix = "(435)"; + flags8text = "[3] Set delay by backside sector"; + } + + 467 + { + title = "Set Tagged Sector's Light Level"; + prefix = "(467)"; + flags8text = "[3] Set delay by backside sector"; + flags256text = "[8] Set relative to current"; + } + } + + linedefexecplane + { + title = "Linedef Executor (plane movement)"; + + 403 + { + title = "Move Tagged Sector's Floor"; + prefix = "(403)"; + flags2text = "[1] Trigger linedef executor"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Change floor texture"; + } + + 404 + { + title = "Move Tagged Sector's Ceiling"; + prefix = "(404)"; + flags2text = "[1] Trigger linedef executor"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Change ceiling texture"; + } + + 405 + { + title = "Move Floor According to Front Texture Offsets"; + prefix = "(405)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Move instantly"; + } + + 407 + { + title = "Move Ceiling According to Front Texture Offsets"; + prefix = "(407)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Move instantly"; + } + + 411 + { + title = "Stop Plane Movement"; + prefix = "(411)"; + flags8text = "[3] Set delay by backside sector"; + } + + 428 + { + title = "Start Platform Movement"; + prefix = "(428)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Move upwards at start"; + } + + 429 + { + title = "Crush Ceiling Once"; + prefix = "(429)"; + flags8text = "[3] Set delay by backside sector"; + flags512text = "[9] Double, constant speed"; + } + + 430 + { + title = "Crush Floor Once"; + prefix = "(430)"; + flags8text = "[3] Set delay by backside sector"; + } + + 431 + { + title = "Crush Floor and Ceiling Once"; + prefix = "(431)"; + flags8text = "[3] Set delay by backside sector"; + flags512text = "[9] Double, constant speed"; + } + } + + linedefexecplayer + { + title = "Linedef Executor (player/object)"; + + 412 + { + title = "Teleporter"; + prefix = "(412)"; + flags2text = "[1] Silent"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Retain angle"; + flags256text = "[8] Relative, silent"; + flags512text = "[9] Retain momentum"; + } + + 425 + { + title = "Change Object State"; + prefix = "(425)"; + flags8text = "[3] Set delay by backside sector"; + } + + 426 + { + title = "Stop Object"; + prefix = "(426)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Teleport to sector center"; + } + + 427 + { + title = "Award Score"; + prefix = "(427)"; + flags8text = "[3] Set delay by backside sector"; + } + + 432 + { + title = "Enable/Disable 2D Mode"; + prefix = "(432)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Return to 3D"; + } + + 433 + { + title = "Enable/Disable Gravity Flip"; + prefix = "(433)"; + flags2text = "[1] Force MFE_VERTICALFLIP"; + flags8text = "[3] Set delay by backside sector"; + flags32text = "[5] Invert current gravity"; + flags64text = "[6] Return to normal"; + } + + 434 + { + title = "Award Power-Up"; + prefix = "(434)"; + flags2text = "[1] Use back upper texture"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] No time limit"; + } + + 437 + { + title = "Disable Player Control"; + prefix = "(437)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Allow jumping"; + } + + 438 + { + title = "Change Object Size"; + prefix = "(438)"; + flags8text = "[3] Set delay by backside sector"; + } + + 442 + { + title = "Change Object Type State"; + prefix = "(442)"; + flags8text = "[3] Set delay by backside sector"; + } + + 449 + { + title = "Enable Bosses with Parameter"; + prefix = "(449)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Disable bosses"; + } + + 457 + { + title = "Track Object's Angle"; + prefix = "(457)"; + flags8text = "[3] Set delay by backside sector"; + flags128text = "[7] Don't stop after first fail"; + } + + 458 + { + title = "Stop Tracking Object's Angle"; + prefix = "(458)"; + flags8text = "[3] Set delay by backside sector"; + } + + 460 + { + title = "Award Rings"; + prefix = "(460)"; + flags8text = "[3] Set delay by backside sector"; + } + + 461 + { + title = "Spawn Object"; + prefix = "(461)"; + flags8text = "[3] Set delay by backside sector"; + flags32text = "[5] Use line angle for object"; + flags64text = "[6] Spawn inside a range"; + } + + 462 + { + title = "Stop Timer/Exit Stage in Record Attack"; + prefix = "(462)"; + flags8text = "[3] Set delay by backside sector"; + } + + 463 + { + title = "Dye Object"; + prefix = "(463)"; + } + + 464 + { + title = "Trigger Egg Capsule"; + prefix = "(464)"; + flags64text = "[6] Don't end level"; + } + } + + linedefexecmisc + { + title = "Linedef Executor (misc.)"; + + 413 + { + title = "Change Music"; + prefix = "(413)"; + flags2text = "[1] Keep after death"; + flags8text = "[3] Set delay by backside sector"; + flags32text = "[5] Seek from current position"; + flags64text = "[6] For everyone"; + flags128text = "[7] Fade to custom volume"; + flags512text = "[9] Don't loop"; + flags16384text = "[14] Force music reload"; + } + + 414 + { + title = "Play Sound Effect"; + prefix = "(414)"; + flags2text = "[1] From calling sector"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] From nowhere for triggerer"; + flags512text = "[9] From nowhere for everyone"; + flags1024text = "[10] From tagged sectors"; + } + + 415 + { + title = "Run Script"; + prefix = "(415)"; + flags8text = "[3] Set delay by backside sector"; + } + + 422 + { + title = "Switch to Cut-Away View"; + prefix = "(422)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Adjust pitch"; + } + + 423 + { + title = "Change Sky"; + prefix = "(423)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] For everyone"; + } + + 424 + { + title = "Change Weather"; + prefix = "(424)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] For everyone"; + } + + 436 + { + title = "Shatter FOF"; + prefix = "(436)"; + flags8text = "[3] Set delay by backside sector"; + } + + 439 + { + title = "Change Tagged Linedef's Textures"; + prefix = "(439)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Only existing"; + flags8192text = "[13] Use backside textures"; + } + + 440 + { + title = "Start Metal Sonic Race"; + prefix = "(440)"; + flags8text = "[3] Set delay by backside sector"; + } + + 441 + { + title = "Condition Set Trigger"; + prefix = "(441)"; + flags8text = "[3] Set delay by backside sector"; + } + + 443 + { + title = "Call Lua Function"; + prefix = "(443)"; + flags8text = "[3] Set delay by backside sector"; + } + + 444 + { + title = "Earthquake"; + prefix = "(444)"; + flags8text = "[3] Set delay by backside sector"; + } + + 445 + { + title = "Make FOF Disappear/Reappear"; + prefix = "(445)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Reappear"; + } + + 446 + { + title = "Make FOF Crumble"; + prefix = "(446)"; + flags2text = "[1] Flags determine respawn"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't respawn"; + } + + 447 + { + title = "Change Tagged Sector's Colormap"; + prefix = "(447)"; + flags8text = "[3] Set delay by backside sector"; + flags16text = "[4] Front X/Y = Alpha"; + flags32text = "[5] Subtract Red value"; + flags64text = "[6] Subtract Green value"; + flags128text = "[7] Subtract Blue value"; + flags256text = "[8] Set relative to current"; + flags32768text = "[15] Use backside colormap"; + } + + 448 + { + title = "Change Skybox"; + prefix = "(448)"; + flags2text = "[1] Change centerpoint"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] For everyone"; + flags512text = "[9] Don't change viewpoint"; + } + + 450 + { + title = "Execute Linedef Executor (specific tag)"; + prefix = "(450)"; + flags8text = "[3] Set delay by backside sector"; + } + + 451 + { + title = "Execute Linedef Executor (random tag in range)"; + prefix = "(451)"; + flags8text = "[3] Set delay by backside sector"; + } + + 452 + { + title = "Set FOF Translucency"; + prefix = "(452)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Do not handle FF_TRANS"; + flags256text = "[8] Set relative to current"; + } + + 453 + { + title = "Fade FOF"; + prefix = "(453)"; + flags2text = "[1] Do not handle FF_EXISTS"; + flags8text = "[3] Set delay by backside sector"; + flags32text = "[5] No collision during fade"; + flags64text = "[6] Do not handle FF_TRANS"; + flags128text = "[7] Do not handle lighting"; + flags256text = "[8] Set relative to current"; + flags512text = "[9] Speed = Tic Duration"; + flags1024text = "[10] Override existing fade"; + flags16384text = "[14] Do not handle collision"; + flags32768text = "[15] Use exact alpha in OGL"; + } + + 454 + { + title = "Stop Fading FOF"; + prefix = "(454)"; + flags2text = "[1] Do not finalize collision"; + flags8text = "[3] Set delay by backside sector"; + } + + 455 + { + title = "Fade Tagged Sector's Colormap"; + prefix = "(455)"; + flags8text = "[3] Set delay by backside sector"; + flags16text = "[4] Front X/Y = Alpha"; + flags32text = "[5] Subtract Red value"; + flags64text = "[6] Subtract Green value"; + flags128text = "[7] Subtract Blue value"; + flags256text = "[8] Set relative to current"; + flags512text = "[9] Speed = Tic Duration"; + flags1024text = "[10] Override existing fade"; + flags16384text = "[14] Fade from invisible black"; + flags32768text = "[15] Use backside colormap"; + } + + 456 + { + title = "Stop Fading Tagged Sector's Colormap"; + prefix = "(456)"; + flags8text = "[3] Set delay by backside sector"; + } + + 459 + { + title = "Control Text Prompt"; + prefix = "(459)"; + flags2text = "[1] Close text prompt"; + flags8text = "[3] Set delay by backside sector"; + flags32text = "[5] Run executor tag on close"; + flags128text = "[7] Don't disable controls"; + flags32768text = "[15] Find prompt by name"; + } + } + + linedefexecpoly + { + title = "Linedef Executor (polyobject)"; + + 480 + { + title = "PolyObject Door Slide"; + prefix = "(480)"; + flags8text = "[3] Set delay by backside sector"; + } + + 481 + { + title = "PolyObject Door Swing"; + prefix = "(481)"; + flags8text = "[3] Set delay by backside sector"; + } + + 482 + { + title = "Move PolyObject"; + prefix = "(482)"; + flags8text = "[3] Set delay by backside sector"; + } + + 483 + { + title = "Move PolyObject, Override"; + prefix = "(483)"; + flags8text = "[3] Set delay by backside sector"; + } + + 484 + { + title = "Rotate PolyObject Right"; + prefix = "(484)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + + 485 + { + title = "Rotate PolyObject Right, Override"; + prefix = "(485)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + + 486 + { + title = "Rotate PolyObject Left"; + prefix = "(486)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + + 487 + { + title = "Rotate PolyObject Left, Override"; + prefix = "(487)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + + 488 + { + title = "Move PolyObject by Waypoints"; + prefix = "(488)"; + flags8text = "[3] Set delay by backside sector"; + flags32text = "[5] Reverse order"; + flags128text = "[7] There and back"; + flags256text = "[8] Return when done"; + flags512text = "[9] Loop movement"; + } + + 489 + { + title = "Turn PolyObject Invisible, Intangible"; + prefix = "(489)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Only invisible"; + } + + 490 + { + title = "Turn PolyObject Visible, Tangible"; + prefix = "(490)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Only visible"; + } + + 491 + { + title = "Set PolyObject Translucency"; + prefix = "(491)"; + flags8text = "[3] Set delay by backside sector"; + flags16text = "[4] Set raw alpha by Front X"; + flags256text = "[8] Set relative to current"; + } + + 492 + { + title = "Fade PolyObject Translucency"; + prefix = "(492)"; + flags8text = "[3] Set delay by backside sector"; + flags16text = "[4] Set raw alpha by Front X"; + flags32text = "[5] No collision during fade"; + flags256text = "[8] Set relative to current"; + flags512text = "[9] Speed = Tic Duration"; + flags1024text = "[10] Override existing fade"; + flags16384text = "[14] Do not handle collision"; + } + } + + wallscroll + { + title = "Wall Scrolling"; + + 500 + { + title = "Scroll Front Wall Left"; + prefix = "(500)"; + } + + 501 + { + title = "Scroll Front Wall Right"; + prefix = "(501)"; + } + + 502 + { + title = "Scroll Tagged Walls"; + prefix = "(502)"; + flags128text = "[7] Use texture offsets"; + flags256text = "[8] Scroll back side"; + } + + 503 + { + title = "Scroll Tagged Walls (Accelerative)"; + prefix = "(503)"; + flags128text = "[7] Use texture offsets"; + flags256text = "[8] Scroll back side"; + } + + 504 + { + title = "Scroll Tagged Walls (Displacement)"; + prefix = "(504)"; + flags128text = "[7] Use texture offsets"; + flags256text = "[8] Scroll back side"; + } + + 505 + { + title = "Scroll Front Wall by Front Side Offsets"; + prefix = "(505)"; + } + + 506 + { + title = "Scroll Front Wall by Back Side Offsets"; + prefix = "(506)"; + } + + 507 + { + title = "Scroll Back Wall by Front Side Offsets"; + prefix = "(507)"; + } + + 508 + { + title = "Scroll Back Wall by Back Side Offsets"; + prefix = "(508)"; + } + } + + planescroll + { + title = "Plane Scrolling"; + + 510 + { + title = "Scroll Floor Texture"; + prefix = "(510)"; + } + + 511 + { + title = "Scroll Floor Texture (Accelerative)"; + prefix = "(511)"; + } + + 512 + { + title = "Scroll Floor Texture (Displacement)"; + prefix = "(512)"; + } + + 513 + { + title = "Scroll Ceiling Texture"; + prefix = "(513)"; + } + + 514 + { + title = "Scroll Ceiling Texture (Accelerative)"; + prefix = "(514)"; + } + + 515 + { + title = "Scroll Ceiling Texture (Displacement)"; + prefix = "(515)"; + } + + 520 + { + title = "Carry Objects on Floor"; + prefix = "(520)"; + flags64text = "[6] Exclusive"; + } + + 521 + { + title = "Carry Objects on Floor (Accelerative)"; + prefix = "(521)"; + flags64text = "[6] Exclusive"; + } + + 522 + { + title = "Carry Objects on Floor (Displacement)"; + prefix = "(522)"; + flags64text = "[6] Exclusive"; + } + + 523 + { + title = "Carry Objects on Ceiling"; + prefix = "(523)"; + flags64text = "[6] Exclusive"; + } + + 524 + { + title = "Carry Objects on Ceiling (Accelerative)"; + prefix = "(524)"; + flags64text = "[6] Exclusive"; + } + + 525 + { + title = "Carry Objects on Ceiling (Displacement)"; + prefix = "(525)"; + flags64text = "[6] Exclusive"; + } + + 530 + { + title = "Scroll Floor Texture and Carry Objects"; + prefix = "(530)"; + flags64text = "[6] Exclusive"; + } + + 531 + { + title = "Scroll Floor Texture and Carry Objects (Accelerative)"; + prefix = "(531)"; + flags64text = "[6] Exclusive"; + } + + 532 + { + title = "Scroll Floor Texture and Carry Objects (Displacement)"; + prefix = "(532)"; + flags64text = "[6] Exclusive"; + } + + 533 + { + title = "Scroll Ceiling Texture and Carry Objects"; + prefix = "(533)"; + flags64text = "[6] Exclusive"; + } + + 534 + { + title = "Scroll Ceiling Texture and Carry Objects (Accelerative)"; + prefix = "(534)"; + flags64text = "[6] Exclusive"; + } + + 535 + { + title = "Scroll Ceiling Texture and Carry Objects (Displacement)"; + prefix = "(535)"; + flags64text = "[6] Exclusive"; + } + } + + pusher + { + title = "Pusher"; + + 541 + { + title = "Wind"; + prefix = "(541)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Exclusive"; + } + + 542 + { + title = "Upwards Wind"; + prefix = "(542)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Exclusive"; + } + + 543 + { + title = "Downwards Wind"; + prefix = "(543)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Exclusive"; + } + + 544 + { + title = "Current"; + prefix = "(544)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Exclusive"; + } + + 545 + { + title = "Upwards Current"; + prefix = "(545)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Exclusive"; + } + + 546 + { + title = "Downwards Current"; + prefix = "(546)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Exclusive"; + } + + 547 + { + title = "Push/Pull"; + prefix = "(547)"; + flags64text = "[6] Exclusive"; + } + } + + light + { + title = "Lighting"; + + 600 + { + title = "Floor Lighting"; + prefix = "(600)"; + } + + 601 + { + title = "Ceiling Lighting"; + prefix = "(601)"; + } + + 602 + { + title = "Adjustable Pulsating Light"; + prefix = "(602)"; + } + + 603 + { + title = "Adjustable Flickering Light"; + prefix = "(603)"; + } + + 604 + { + title = "Adjustable Blinking Light (unsynchronized)"; + prefix = "(604)"; + } + + 605 + { + title = "Adjustable Blinking Light (synchronized)"; + prefix = "(605)"; + } + + 606 + { + title = "Colormap"; + prefix = "(606)"; + } + } + + slope + { + title = "Slope"; + + 700 + { + title = "Slope Frontside Floor"; + prefix = "(700)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags32768text = "[15] Copy to other side"; + slope = "regular"; + slopeargs = 1; + copyslopeargs = 1; + } + + 701 + { + title = "Slope Frontside Ceiling"; + prefix = "(701)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags32768text = "[15] Copy to other side"; + slope = "regular"; + slopeargs = 2; + copyslopeargs = 4; + } + + 702 + { + title = "Slope Frontside Floor and Ceiling"; + prefix = "(702)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags32768text = "[15] Copy to other side"; + slope = "regular"; + slopeargs = 3; + copyslopeargs = 5; + } + + 703 + { + title = "Slope Frontside Floor and Backside Ceiling"; + prefix = "(703)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags32768text = "[15] Copy to other side"; + slope = "regular"; + slopeargs = 9; + copyslopeargs = 8; + } + + 704 + { + title = "Slope Frontside Floor by 3 Tagged Vertex Things"; + prefix = "(704)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags8192text = "[13] Use tag and offsets"; + slope = "vertex"; + slopeargs = 0; + } + + 705 + { + title = "Slope Frontside Ceiling by 3 Tagged Vertex Things"; + prefix = "(705)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags8192text = "[13] Use tag and offsets"; + slope = "vertex"; + slopeargs = 1; + } + + 710 + { + title = "Slope Backside Floor"; + prefix = "(710)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags32768text = "[15] Copy to other side"; + slope = "regular"; + slopeargs = 4; + copyslopeargs = 2; + } + + 711 + { + title = "Slope Backside Ceiling"; + prefix = "(711)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags32768text = "[15] Copy to other side"; + slope = "regular"; + slopeargs = 8; + copyslopeargs = 8; + } + + 712 + { + title = "Slope Backside Floor and Ceiling"; + prefix = "(712)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags32768text = "[15] Copy to other side"; + slope = "regular"; + slopeargs = 12; + copyslopeargs = 10; + } + + 713 + { + title = "Slope Backside Floor and Frontside Ceiling"; + prefix = "(713)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags32768text = "[15] Copy to other side"; + slope = "regular"; + slopeargs = 6; + copyslopeargs = 6; + } + + 714 + { + title = "Slope Backside Floor by 3 Tagged Vertex Things"; + prefix = "(714)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags8192text = "[13] Use tag and offsets"; + slope = "vertex"; + slopeargs = 2; + } + + 715 + { + title = "Slope Backside Ceiling by 3 Tagged Vertex Things"; + prefix = "(715)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags8192text = "[13] Use tag and offsets"; + slope = "vertex"; + slopeargs = 3; + } + + 720 + { + title = "Copy Frontside Floor Slope from Line Tag"; + prefix = "(720)"; + slope = "copy"; + slopeargs = 1; + } + + 721 + { + title = "Copy Frontside Ceiling Slope from Line Tag"; + prefix = "(721)"; + slope = "copy"; + slopeargs = 2; + } + + 722 + { + title = "Copy Frontside Floor and Ceiling Slope from Line Tag"; + prefix = "(722)"; + slope = "copy"; + slopeargs = 3; + } + + 723 + { + title = "Copy Backside Floor Slope from Line Tag"; + prefix = "(723)"; + slope = "copy"; + slopeargs = 4; + } + + 724 + { + title = "Copy Backside Ceiling Slope from Line Tag"; + prefix = "(724)"; + slope = "copy"; + slopeargs = 8; + } + + 725 + { + title = "Copy Backside Floor and Ceiling Slope from Line Tag"; + prefix = "(725)"; + slope = "copy"; + slopeargs = 12; + } + + 730 + { + title = "Copy Frontside Floor Slope to Backside"; + prefix = "(730)"; + slope = "copy"; + copyslopeargs = 1; + } + + 731 + { + title = "Copy Frontside Ceiling Slope to Backside"; + prefix = "(731)"; + slope = "copy"; + copyslopeargs = 4; + } + + 732 + { + title = "Copy Frontside Floor and Ceiling Slope to Backside"; + prefix = "(732)"; + slope = "copy"; + copyslopeargs = 5; + } + + 733 + { + title = "Copy Backside Floor Slope to Frontside"; + prefix = "(733)"; + slope = "copy"; + copyslopeargs = 2; + } + + 734 + { + title = "Copy Backside Ceiling Slope to Frontside"; + prefix = "(734)"; + slope = "copy"; + copyslopeargs = 8; + } + + 735 + { + title = "Copy Backside Floor and Ceiling Slope to Frontside"; + prefix = "(735)"; + slope = "copy"; + copyslopeargs = 10; + } + + 799 + { + title = "Set Tagged Dynamic Slope Vertex to Front Sector Height"; + prefix = "(799)"; + flags64text = "[6] Use relative heights"; + } + } + + transwall + { + title = "Translucent Walls"; + + 900 + { + title = "90% Opaque"; + prefix = "(900)"; + } + + 901 + { + title = "80% Opaque"; + prefix = "(901)"; + } + + 902 + { + title = "70% Opaque"; + prefix = "(902)"; + } + + 903 + { + title = "60% Opaque"; + prefix = "(903)"; + } + + 904 + { + title = "50% Opaque"; + prefix = "(904)"; + } + + 905 + { + title = "40% Opaque"; + prefix = "(905)"; + } + + 906 + { + title = "30% Opaque"; + prefix = "(906)"; + } + + 907 + { + title = "20% Opaque"; + prefix = "(907)"; + } + + 908 + { + title = "10% Opaque"; + prefix = "(908)"; + } + + 909 + { + title = "Fog Wall"; + prefix = "(909)"; + } + + 910 + { + title = "100% Additive"; + prefix = "(910)"; + } + + 911 + { + title = "90% Additive"; + prefix = "(911)"; + } + + 912 + { + title = "80% Additive"; + prefix = "(912)"; + } + + 913 + { + title = "70% Additive"; + prefix = "(913)"; + } + + 914 + { + title = "60% Additive"; + prefix = "(914)"; + } + + 915 + { + title = "50% Additive"; + prefix = "(915)"; + } + + 916 + { + title = "40% Additive"; + prefix = "(916)"; + } + + 917 + { + title = "30% Additive"; + prefix = "(917)"; + } + + 918 + { + title = "20% Additive"; + prefix = "(918)"; + } + + 919 + { + title = "10% Additive"; + prefix = "(919)"; + } + + 920 + { + title = "100% Subtractive"; + prefix = "(920)"; + } + + 921 + { + title = "90% Subtractive"; + prefix = "(921)"; + } + + 922 + { + title = "80% Subtractive"; + prefix = "(922)"; + } + + 923 + { + title = "70% Subtractive"; + prefix = "(923)"; + } + + 924 + { + title = "60% Subtractive"; + prefix = "(924)"; + } + + 925 + { + title = "50% Subtractive"; + prefix = "(925)"; + } + + 926 + { + title = "40% Subtractive"; + prefix = "(926)"; + } + + 927 + { + title = "30% Subtractive"; + prefix = "(927)"; + } + + 928 + { + title = "20% Subtractive"; + prefix = "(928)"; + } + + 929 + { + title = "10% Subtractive"; + prefix = "(929)"; + } + + 930 + { + title = "100% Reverse Subtractive"; + prefix = "(930)"; + } + + 931 + { + title = "90% Reverse Subtractive"; + prefix = "(931)"; + } + + 932 + { + title = "80% Reverse Subtractive"; + prefix = "(932)"; + } + + 933 + { + title = "70% Reverse Subtractive"; + prefix = "(933)"; + } + + 934 + { + title = "60% Reverse Subtractive"; + prefix = "(934)"; + } + + 935 + { + title = "50% Reverse Subtractive"; + prefix = "(935)"; + } + + 936 + { + title = "40% Reverse Subtractive"; + prefix = "(936)"; + } + + 937 + { + title = "30% Reverse Subtractive"; + prefix = "(937)"; + } + + 938 + { + title = "20% Reverse Subtractive"; + prefix = "(938)"; + } + + 939 + { + title = "10% Reverse Subtractive"; + prefix = "(939)"; + } + + 940 + { + title = "Modulate"; + prefix = "(940)"; + } + } +} + + +// THING FLAGS +thingflags +{ + 1 = "[1] Extra"; + 2 = "[2] Flip"; + 4 = "[4] Special"; + 8 = "[8] Ambush"; +} + +// 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 +{ + 1 = "skill1"; + 2 = "skill2"; + 4 = "skill3"; + 8 = "ambush"; +} + +// 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------------------------------------------------------------------ +// Color values: 1-Dark_Blue 2-Dark_Green 3-Turqoise 4-Dark_Red 5-Purple 6-Brown 7-Gray +// 8-Dark_Gray 9-Blue 10-Green 11-Cyan 12-Red 13-Magenta +// 14-Yellow 15-White 16-Pink 17-Orange 18-Gold 19-Cream +thingtypes +{ + editor + { + color = 15; // White + arrow = 1; + title = "<Editor Things>"; + error = -1; + width = 8; + height = 16; + sort = 1; + + 3328 = "3D Mode Start"; + } + + starts + { + color = 1; // Blue + arrow = 1; + title = "Player Starts"; + width = 16; + height = 48; + flags8text = "[8] Spawn on ceiling"; + sprite = "PLAYA0"; + + 1 + { + title = "Player 01 Start"; + sprite = "PLAYA0"; + } + 2 + { + title = "Player 02 Start"; + sprite = "PLAYA0"; + } + 3 + { + title = "Player 03 Start"; + sprite = "PLAYA0"; + } + 4 + { + title = "Player 04 Start"; + sprite = "PLAYA0"; + } + 5 + { + title = "Player 05 Start"; + sprite = "PLAYA0"; + } + 6 + { + title = "Player 06 Start"; + sprite = "PLAYA0"; + } + 7 + { + title = "Player 07 Start"; + sprite = "PLAYA0"; + } + 8 + { + title = "Player 08 Start"; + sprite = "PLAYA0"; + } + 9 + { + title = "Player 09 Start"; + sprite = "PLAYA0"; + } + 10 + { + title = "Player 10 Start"; + sprite = "PLAYA0"; + } + 11 + { + title = "Player 11 Start"; + sprite = "PLAYA0"; + } + 12 + { + title = "Player 12 Start"; + sprite = "PLAYA0"; + } + 13 + { + title = "Player 13 Start"; + sprite = "PLAYA0"; + } + 14 + { + title = "Player 14 Start"; + sprite = "PLAYA0"; + } + 15 + { + title = "Player 15 Start"; + sprite = "PLAYA0"; + } + 16 + { + title = "Player 16 Start"; + sprite = "PLAYA0"; + } + 17 + { + title = "Player 17 Start"; + sprite = "PLAYA0"; + } + 18 + { + title = "Player 18 Start"; + sprite = "PLAYA0"; + } + 19 + { + title = "Player 19 Start"; + sprite = "PLAYA0"; + } + 20 + { + title = "Player 20 Start"; + sprite = "PLAYA0"; + } + 21 + { + title = "Player 21 Start"; + sprite = "PLAYA0"; + } + 22 + { + title = "Player 22 Start"; + sprite = "PLAYA0"; + } + 23 + { + title = "Player 23 Start"; + sprite = "PLAYA0"; + } + 24 + { + title = "Player 24 Start"; + sprite = "PLAYA0"; + } + 25 + { + title = "Player 25 Start"; + sprite = "PLAYA0"; + } + 26 + { + title = "Player 26 Start"; + sprite = "PLAYA0"; + } + 27 + { + title = "Player 27 Start"; + sprite = "PLAYA0"; + } + 28 + { + title = "Player 28 Start"; + sprite = "PLAYA0"; + } + 29 + { + title = "Player 29 Start"; + sprite = "PLAYA0"; + } + 30 + { + title = "Player 30 Start"; + sprite = "PLAYA0"; + } + 31 + { + title = "Player 31 Start"; + sprite = "PLAYA0"; + } + 32 + { + title = "Player 32 Start"; + sprite = "PLAYA0"; + } + 33 + { + title = "Match Start"; + sprite = "NDRNA2A8"; + } + 34 + { + title = "CTF Red Team Start"; + sprite = "SIGNG0"; + } + 35 + { + title = "CTF Blue Team Start"; + sprite = "SIGNE0"; + } + } + + enemies + { + color = 9; // Light Blue + arrow = 1; + title = "Enemies"; + + 100 + { + title = "Crawla (Blue)"; + sprite = "POSSA1"; + width = 24; + height = 32; + } + 101 + { + title = "Crawla (Red)"; + sprite = "SPOSA1"; + width = 24; + height = 32; + } + 102 + { + title = "Stupid Dumb Unnamed RoboFish"; + sprite = "FISHA0"; + width = 8; + height = 28; + angletext = "Jump strength"; + fixedrotation = 1; + } + 103 + { + title = "Buzz (Gold)"; + sprite = "BUZZA1"; + width = 28; + height = 40; + flags8text = "[8] Cannot move"; + } + 104 + { + title = "Buzz (Red)"; + sprite = "RBUZA1"; + width = 28; + height = 40; + flags8text = "[8] Cannot move"; + } + 108 + { + title = "Deton"; + sprite = "DETNA1"; + width = 20; + height = 32; + } + 110 + { + title = "Turret"; + sprite = "TRETA1"; + width = 16; + height = 32; + } + 111 + { + title = "Pop-up Turret"; + sprite = "TURRI1"; + width = 12; + height = 64; + angletext = "Firing delay"; + fixedrotation = 1; + } + 122 + { + title = "Spring Shell (Green)"; + sprite = "SSHLA1"; + width = 24; + height = 40; + } + 125 + { + title = "Spring Shell (Yellow)"; + sprite = "SSHLI1"; + width = 24; + height = 40; + } + 109 + { + title = "Skim"; + sprite = "SKIMA1"; + width = 16; + height = 24; + } + 113 + { + title = "Jet Jaw"; + sprite = "JJAWA3A7"; + width = 12; + height = 20; + } + 126 + { + title = "Crushstacean"; + sprite = "CRABA0"; + width = 24; + height = 32; + flags8text = "[8] Move left from spawn"; + } + 138 + { + title = "Banpyura"; + sprite = "CR2BA0"; + width = 24; + height = 32; + flags8text = "[8] Move left from spawn"; + } + 117 + { + title = "Robo-Hood"; + sprite = "ARCHA1"; + width = 24; + height = 32; + flags8text = "[8] Don't jump away"; + } + 118 + { + title = "Lance-a-Bot"; + sprite = "CBFSA1"; + width = 32; + height = 72; + } + 1113 + { + title = "Suspicious Lance-a-Bot Statue"; + sprite = "CBBSA1"; + width = 32; + height = 72; + } + 119 + { + title = "Egg Guard"; + sprite = "ESHIA1"; + width = 16; + height = 48; + flags1text = "[1] 90 degrees clockwise"; + flags4text = "[4] 90 degrees counter-clockwise"; + flags8text = "[8] Double speed"; + } + 115 + { + title = "Bird Aircraft Strike Hazard"; + sprite = "VLTRF1"; + width = 12; + height = 24; + } + 120 + { + title = "Green Snapper"; + sprite = "GSNPA1"; + width = 24; + height = 24; + } + 121 + { + title = "Minus"; + sprite = "MNUSA0"; + width = 24; + height = 32; + } + 134 + { + title = "Canarivore"; + sprite = "CANAA0"; + width = 12; + height = 80; + hangs = 1; + } + 123 + { + title = "Unidus"; + sprite = "UNIDA1"; + width = 18; + height = 36; + } + 135 + { + title = "Pterabyte Spawner"; + sprite = "PTERA2A8"; + width = 24; + height = 48; + parametertext = "Spawns +1"; + arrow = 0; + } + 136 + { + title = "Pyre Fly"; + sprite = "PYREA0"; + width = 24; + height = 34; + flags8text = "[8] Start on fire"; + } + 137 + { + title = "Dragonbomber"; + sprite = "DRABA1"; + width = 28; + height = 48; + } + 105 + { + title = "Jetty-Syn Bomber"; + sprite = "JETBB1"; + width = 20; + height = 50; + flags8text = "[8] Cannot move"; + } + 106 + { + title = "Jetty-Syn Gunner"; + sprite = "JETGB1"; + width = 20; + height = 48; + flags8text = "[8] Cannot move"; + } + 112 + { + title = "Spincushion"; + sprite = "SHRPA1"; + width = 16; + height = 24; + } + 114 + { + title = "Snailer"; + sprite = "SNLRA3A7"; + width = 24; + height = 48; + } + 129 + { + title = "Penguinator"; + sprite = "PENGA1"; + width = 24; + height = 32; + } + 130 + { + title = "Pophat"; + sprite = "POPHA1"; + width = 24; + height = 32; + } + 107 + { + title = "Crawla Commander"; + sprite = "CCOMA1"; + width = 16; + height = 32; + } + 131 + { + title = "Spinbobert"; + sprite = "SBOBB0"; + width = 32; + height = 32; + } + 132 + { + title = "Cacolantern"; + sprite = "CACOA0"; + width = 32; + height = 32; + flags8text = "[8] Cannot move"; + } + 133 + { + title = "Hangster"; + sprite = "HBATC1"; + width = 24; + height = 24; + hangs = 1; + } + 127 + { + title = "Hive Elemental"; + sprite = "HIVEA0"; + width = 32; + height = 80; + parametertext = "No. bees"; + } + 128 + { + title = "Bumblebore"; + sprite = "BUMBA1"; + width = 16; + height = 32; + flags8text = "[8] Cannot move"; + } + 124 + { + title = "Buggle"; + sprite = "BBUZA1"; + width = 20; + height = 24; + } + 116 + { + title = "Pointy"; + sprite = "PNTYA1"; + width = 8; + height = 16; + } + } + + bosses + { + color = 4; // Dark Red + arrow = 1; + title = "Bosses"; + + 200 + { + title = "Egg Mobile"; + sprite = "EGGMA1"; + width = 36; + height = 84; + flags4text = "[4] End level on death"; + } + 201 + { + title = "Egg Slimer"; + sprite = "EGGNA1"; + width = 36; + height = 84; + flags4text = "[4] End level on death"; + flags8text = "[8] Speed up when hit"; + } + 202 + { + title = "Sea Egg"; + sprite = "EGGOA1"; + width = 36; + height = 116; + flags4text = "[4] End level on death"; + } + 203 + { + title = "Egg Colosseum"; + sprite = "EGGPA1"; + width = 36; + height = 84; + flags4text = "[4] End level on death"; + } + 204 + { + title = "Fang"; + sprite = "FANGA1"; + width = 24; + height = 60; + flags1text = "[1] Grayscale mode"; + flags4text = "[4] End level on death"; + flags8text = "[8] Skip intro"; + } + 206 + { + title = "Brak Eggman (Old)"; + sprite = "BRAKB1"; + width = 48; + height = 160; + flags4text = "[4] End level on death"; + } + 207 + { + title = "Metal Sonic (Race)"; + sprite = "METLI1"; + width = 16; + height = 48; + flags1text = "[1] Grayscale mode"; + } + 208 + { + title = "Metal Sonic (Battle)"; + sprite = "METLC1"; + width = 16; + height = 48; + flags1text = "[1] Grayscale mode"; + flags4text = "[4] End level on death"; + } + 209 + { + title = "Brak Eggman"; + sprite = "BRAK01"; + width = 48; + height = 160; + flags1text = "[1] No origin-fling death"; + flags4text = "[4] End level on death"; + flags8text = "[8] Electric barrier"; + } + 290 + { + arrow = 0; + title = "Boss Escape Point"; + width = 8; + height = 16; + sprite = "internal:eggmanend"; + } + 291 + { + arrow = 0; + title = "Egg Capsule Center"; + width = 8; + height = 16; + sprite = "internal:capsule"; + angletext = "Tag"; + fixedrotation = 1; + tagthing = true; + } + 292 + { + arrow = 0; + title = "Boss Waypoint"; + width = 8; + height = 16; + flags8text = "[8] Sea Egg shooting point"; + sprite = "internal:eggmanway"; + angletext = "No. (Sea Egg)"; + fixedrotation = 1; + flagsvaluetext = "No. (Brak)"; + parametertext = "Next"; + } + 293 + { + arrow = 0; + title = "Metal Sonic Gather Point"; + sprite = "internal:metal"; + width = 8; + height = 16; + } + 294 + { + arrow = 0; + title = "Fang Waypoint"; + flags8text = "[8] Center waypoint"; + sprite = "internal:eggmanway"; + width = 8; + height = 16; + } + } + + rings + { + color = 14; // Yellow + title = "Rings and Weapon Panels"; + width = 24; + height = 24; + flags8height = 24; + flags8text = "[8] Float"; + sprite = "RINGA0"; + + 300 + { + title = "Ring"; + sprite = "RINGA0"; + width = 16; + } + 301 + { + title = "Bounce Ring"; + sprite = "RNGBA0"; + } + 302 + { + title = "Rail Ring"; + sprite = "RNGRA0"; + } + 303 + { + title = "Infinity Ring"; + sprite = "RNGIA0"; + } + 304 + { + title = "Automatic Ring"; + sprite = "RNGAA0"; + } + 305 + { + title = "Explosion Ring"; + sprite = "RNGEA0"; + } + 306 + { + title = "Scatter Ring"; + sprite = "RNGSA0"; + } + 307 + { + title = "Grenade Ring"; + sprite = "RNGGA0"; + } + 308 + { + title = "CTF Team Ring (Red)"; + sprite = "internal:TRNGA0R"; + width = 16; + } + 309 + { + title = "CTF Team Ring (Blue)"; + sprite = "internal:TRNGA0B"; + width = 16; + } + 330 + { + title = "Bounce Ring Panel"; + sprite = "PIKBA0"; + } + 331 + { + title = "Rail Ring Panel"; + sprite = "PIKRA0"; + } + 332 + { + title = "Automatic Ring Panel"; + sprite = "PIKAA0"; + } + 333 + { + title = "Explosion Ring Panel"; + sprite = "PIKEA0"; + } + 334 + { + title = "Scatter Ring Panel"; + sprite = "PIKSA0"; + } + 335 + { + title = "Grenade Ring Panel"; + sprite = "PIKGA0"; + } + } + + collectibles + { + color = 10; // Light Green + title = "Other Collectibles"; + width = 16; + height = 32; + sort = 1; + sprite = "CEMGA0"; + + 310 + { + title = "CTF Red Flag"; + sprite = "RFLGA0"; + width = 24; + height = 64; + } + 311 + { + title = "CTF Blue Flag"; + sprite = "BFLGA0"; + width = 24; + height = 64; + } + 312 + { + title = "Emerald Token"; + sprite = "TOKEA0"; + width = 16; + height = 32; + flags8height = 24; + flags8text = "[8] Float"; + } + 313 + { + title = "Chaos Emerald 1 (Green)"; + sprite = "CEMGA0"; + } + 314 + { + title = "Chaos Emerald 2 (Purple)"; + sprite = "CEMGB0"; + } + 315 + { + title = "Chaos Emerald 3 (Blue)"; + sprite = "CEMGC0"; + } + 316 + { + title = "Chaos Emerald 4 (Cyan)"; + sprite = "CEMGD0"; + } + 317 + { + title = "Chaos Emerald 5 (Orange)"; + sprite = "CEMGE0"; + } + 318 + { + title = "Chaos Emerald 6 (Red)"; + sprite = "CEMGF0"; + } + 319 + { + title = "Chaos Emerald 7 (Gray)"; + sprite = "CEMGG0"; + } + 320 + { + title = "Emerald Hunt Location"; + sprite = "SHRDA0"; + flags8height = 24; + flags8text = "[8] Float"; + } + 321 + { + title = "Match Chaos Emerald Spawn"; + sprite = "CEMGA0"; + flags8height = 24; + flags8text = "[8] Float"; + } + 322 + { + title = "Emblem"; + sprite = "EMBMA0"; + width = 16; + height = 30; + flags8height = 24; + flags8text = "[8] Float"; + angletext = "Tag"; + fixedrotation = 1; + } + } + + boxes + { + color = 7; // Gray + blocking = 2; + title = "Monitors"; + width = 18; + height = 40; + flags1text = "[1] Run linedef executor on pop"; + flags4text = "[4] Random (Strong)"; + flags8text = "[8] Random (Weak)"; + angletext = "Tag"; + fixedrotation = 1; + tagthing = true; + + 400 + { + title = "Super Ring (10 Rings)"; + sprite = "TVRIA0"; + } + 401 + { + title = "Pity Shield"; + sprite = "TVPIA0"; + } + 402 + { + title = "Attraction Shield"; + sprite = "TVATA0"; + } + 403 + { + title = "Force Shield"; + sprite = "TVFOA0"; + } + 404 + { + title = "Armageddon Shield"; + sprite = "TVARA0"; + } + 405 + { + title = "Whirlwind Shield"; + sprite = "TVWWA0"; + } + 406 + { + title = "Elemental Shield"; + sprite = "TVELA0"; + } + 407 + { + title = "Super Sneakers"; + sprite = "TVSSA0"; + } + 408 + { + title = "Invincibility"; + sprite = "TVIVA0"; + } + 409 + { + title = "Extra Life"; + sprite = "TV1UA0"; + flags4text = "[4] Random (Strong) / 10k points"; + flags8text = "[8] Random (Weak) / 10k points"; + } + 410 + { + title = "Eggman"; + sprite = "TVEGA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 411 + { + title = "Teleporter"; + sprite = "TVMXA0"; + } + 413 + { + title = "Gravity Boots"; + sprite = "TVGVA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 414 + { + title = "CTF Team Ring Monitor (Red)"; + sprite = "TRRIA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 415 + { + title = "CTF Team Ring Monitor (Blue)"; + sprite = "TBRIA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 416 + { + title = "Recycler"; + sprite = "TVRCA0"; + } + 418 + { + title = "Score (1,000 Points)"; + sprite = "TV1KA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 419 + { + title = "Score (10,000 Points)"; + sprite = "TVTKA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 420 + { + title = "Flame Shield"; + sprite = "TVFLA0"; + } + 421 + { + title = "Water Shield"; + sprite = "TVBBA0"; + } + 422 + { + title = "Lightning Shield"; + sprite = "TVZPA0"; + } + } + + boxes2 + { + color = 18; // Gold + blocking = 2; + title = "Monitors (Respawning)"; + width = 20; + height = 44; + flags1text = "[1] Run linedef executor on pop"; + angletext = "Tag"; + fixedrotation = 1; + tagthing = true; + + 431 + { + title = "Pity Shield (Respawn)"; + sprite = "TVPIB0"; + } + 432 + { + title = "Attraction Shield (Respawn)"; + sprite = "TVATB0"; + } + 433 + { + title = "Force Shield (Respawn)"; + sprite = "TVFOB0"; + } + 434 + { + title = "Armageddon Shield (Respawn)"; + sprite = "TVARB0"; + } + 435 + { + title = "Whirlwind Shield (Respawn)"; + sprite = "TVWWB0"; + } + 436 + { + title = "Elemental Shield (Respawn)"; + sprite = "TVELB0"; + } + 437 + { + title = "Super Sneakers (Respawn)"; + sprite = "TVSSB0"; + } + 438 + { + title = "Invincibility (Respawn)"; + sprite = "TVIVB0"; + } + 440 + { + title = "Eggman (Respawn)"; + sprite = "TVEGB0"; + } + 443 + { + title = "Gravity Boots (Respawn)"; + sprite = "TVGVB0"; + } + 450 + { + title = "Flame Shield (Respawn)"; + sprite = "TVFLB0"; + } + 451 + { + title = "Water Shield (Respawn)"; + sprite = "TVBBB0"; + } + 452 + { + title = "Lightning Shield (Respawn)"; + sprite = "TVZPB0"; + } + } + + generic + { + color = 11; // Light Cyan + title = "Generic Items & Hazards"; + + 500 + { + title = "Air Bubble Patch"; + sprite = "BUBLE0"; + width = 8; + height = 16; + flags8text = "[8] No distance check"; + } + 501 + { + title = "Signpost"; + sprite = "SIGND0"; + width = 8; + height = 32; + } + 502 + { + arrow = 1; + title = "Star Post"; + sprite = "STPTA0M0"; + width = 64; + height = 128; + flags4text = "[4] Respawn at center"; + angletext = "Angle/Order"; + fixedrotation = 1; + parametertext = "Order"; + } + 520 + { + title = "Bomb Sphere"; + sprite = "SPHRD0"; + width = 16; + height = 24; + flags8height = 24; + flags8text = "[8] Float"; + unflippable = true; + } + 521 + { + title = "Spikeball"; + sprite = "SPIKA0"; + width = 12; + height = 8; + flags8height = 24; + flags8text = "[8] Float"; + } + 522 + { + title = "Wall Spike"; + sprite = "WSPKALAR"; + width = 16; + height = 14; + arrow = 1; + flags1text = "[1] Start retracted"; + flags4text = "[4] Retractable"; + flags8text = "[8] Intangible"; + parametertext = "Start delay"; + } + 523 + { + title = "Spike"; + sprite = "USPKA0"; + width = 8; + height = 32; + flags1text = "[1] Start retracted"; + flags4text = "[4] Retractable"; + flags8text = "[8] Intangible"; + angletext = "Retraction interval"; + fixedrotation = 1; + parametertext = "Start delay"; + } + 1130 + { + title = "Small Mace"; + sprite = "SMCEA0"; + width = 17; + height = 34; + } + 1131 + { + title = "Big Mace"; + sprite = "BMCEA0"; + width = 34; + height = 68; + } + 1136 + { + title = "Small Fireball"; + sprite = "SFBRA0"; + width = 17; + height = 34; + } + 1137 + { + title = "Large Fireball"; + sprite = "BFBRA0"; + width = 34; + height = 68; + } + } + + springs + { + color = 12; // Light Red + title = "Springs and Fans"; + width = 20; + height = 16; + sprite = "RSPRD2"; + + 540 + { + title = "Fan"; + sprite = "FANSA0D0"; + width = 16; + height = 8; + flags4text = "[4] Invisible"; + flags8text = "[8] No distance check"; + angletext = "Lift height"; + fixedrotation = 1; + } + 541 + { + title = "Gas Jet"; + sprite = "STEMD0"; + flags8text = "[8] No sounds"; + width = 32; + } + 542 + { + title = "Bumper"; + sprite = "BUMPA0"; + width = 32; + height = 64; + angletext = "Strength"; + fixedrotation = 1; + } + 543 + { + title = "Balloon"; + sprite = "BLONA0"; + width = 32; + height = 64; + flags8text = "[8] Respawn"; + angletext = "Color"; + fixedrotation = 1; + } + 550 + { + title = "Yellow Spring"; + sprite = "SPRYA0"; + } + 551 + { + title = "Red Spring"; + sprite = "SPRRA0"; + } + 552 + { + title = "Blue Spring"; + sprite = "SPRBA0"; + } + 555 + { + arrow = 1; + title = "Diagonal Yellow Spring"; + sprite = "YSPRD2"; + width = 16; + flags4text = "[4] Ignore gravity"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 556 + { + arrow = 1; + title = "Diagonal Red Spring"; + sprite = "RSPRD2"; + width = 16; + flags4text = "[4] Ignore gravity"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 557 + { + arrow = 1; + title = "Diagonal Blue Spring"; + sprite = "BSPRD2"; + width = 16; + flags4text = "[4] Ignore gravity"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 558 + { + arrow = 1; + title = "Horizontal Yellow Spring"; + sprite = "SSWYD2D8"; + flags8height = 16; + flags8text = "[8] Float"; + width = 16; + height = 32; + } + 559 + { + arrow = 1; + title = "Horizontal Red Spring"; + sprite = "SSWRD2D8"; + flags8height = 16; + flags8text = "[8] Float"; + width = 16; + height = 32; + } + 560 + { + arrow = 1; + title = "Horizontal Blue Spring"; + sprite = "SSWBD2D8"; + flags8height = 16; + flags8text = "[8] Float"; + width = 16; + height = 32; + } + 1134 + { + title = "Yellow Spring Ball"; + sprite = "YSPBA0"; + width = 17; + height = 34; + } + 1135 + { + title = "Red Spring Ball"; + sprite = "RSPBA0"; + width = 17; + height = 34; + } + 544 + { + arrow = 1; + title = "Yellow Boost Panel"; + sprite = "BSTYA0"; + flags8text = "[8] Force spin"; + width = 28; + height = 2; + } + 545 + { + arrow = 1; + title = "Red Boost Panel"; + sprite = "BSTRA0"; + flags8text = "[8] Force spin"; + width = 28; + height = 2; + } + } + + patterns + { + color = 5; // Magenta + arrow = 1; + title = "Special Placement Patterns"; + width = 16; + height = 384; + sprite = "RINGA0"; + + 600 + { + arrow = 0; + title = "5 Vertical Rings (Yellow Spring)"; + sprite = "internal:ringverticalyellow"; + } + 601 + { + arrow = 0; + title = "5 Vertical Rings (Red Spring)"; + sprite = "internal:ringverticalred"; + height = 1024; + } + 602 + { + title = "5 Diagonal Rings (Yellow Spring)"; + sprite = "RINGA0"; + height = 32; + } + 603 + { + title = "10 Diagonal Rings (Red Spring)"; + sprite = "RINGA0"; + height = 32; + } + 604 + { + title = "Circle of Rings"; + sprite = "internal:circlering"; + width = 96; + height = 192; + unflippable = true; + centerHitbox = true; + } + 605 + { + title = "Circle of Rings (Big)"; + sprite = "internal:circlebigring"; + width = 192; + unflippable = true; + centerHitbox = true; + } + 606 + { + title = "Circle of Blue Spheres"; + sprite = "internal:circlesphere"; + width = 96; + height = 192; + unflippable = true; + centerHitbox = true; + } + 607 + { + title = "Circle of Blue Spheres (Big)"; + sprite = "internal:circlebigsphere"; + width = 192; + unflippable = true; + centerHitbox = true; + } + 608 + { + title = "Circle of Rings and Spheres"; + sprite = "internal:circleringsphere"; + width = 96; + height = 192; + unflippable = true; + centerHitbox = true; + } + 609 + { + title = "Circle of Rings and Spheres (Big)"; + sprite = "internal:circlebigringsphere"; + width = 192; + unflippable = true; + centerHitbox = true; + } + } + + ambience + { + color = 8; // Dark Gray + title = "Ambience"; + width = 8; + height = 16; + sprite = "internal:ambiance"; + + 700 + { + title = "Water Ambience A (Large)"; + } + + 701 + { + title = "Water Ambience B (Large)"; + } + + 702 + { + title = "Water Ambience C (Medium)"; + } + + 703 + { + title = "Water Ambience D (Medium)"; + } + + 704 + { + title = "Water Ambience E (Small)"; + } + + 705 + { + title = "Water Ambience F (Small)"; + } + + 706 + { + title = "Water Ambience G (Extra Large)"; + } + + 707 + { + title = "Water Ambience H (Extra Large)"; + } + + 708 + { + title = "Disco Ambience"; + } + + 709 + { + title = "Volcano Ambience"; + } + + 710 + { + title = "Machine Ambience"; + } + } + + invisible + { + color = 15; // White + title = "Misc. Invisible"; + width = 8; + height = 16; + sprite = "UNKNA0"; + + 750 + { + title = "Slope Vertex"; + sprite = "internal:vertexslope"; + angletext = "Tag"; + fixedrotation = 1; + parametertext = "Absolute?"; + flagsvaluetext = "Absolute Z"; + tagthing = true; + } + + 751 + { + arrow = 1; + title = "Teleport Destination"; + sprite = "internal:tele"; + } + + 752 + { + arrow = 1; + title = "Alternate View Point"; + sprite = "internal:view"; + } + + 753 + { + title = "Zoom Tube Waypoint"; + sprite = "internal:zoom"; + angletext = "Order"; + fixedrotation = 1; + } + + 754 + { + title = "Push Point"; + flags4text = "[4] Fades using XY"; + flags8text = "[8] Push using XYZ"; + sprite = "GWLGA0"; + angletext = "Radius"; + fixedrotation = 1; + } + 755 + { + title = "Pull Point"; + flags4text = "[4] Fades using XY"; + flags8text = "[8] Pull using XYZ"; + sprite = "GWLRA0"; + angletext = "Radius"; + fixedrotation = 1; + } + 756 + { + title = "Blast Linedef Executor"; + sprite = "internal:blastexec"; + width = 32; + height = 16; + angletext = "Tag"; + fixedrotation = 1; + tagthing = true; + } + 757 + { + title = "Fan Particle Generator"; + sprite = "internal:fanparticles"; + width = 8; + height = 16; + angletext = "Tag"; + fixedrotation = 1; + tagthing = true; + } + 758 + { + title = "Object Angle Anchor"; + sprite = "internal:view"; + } + 760 + { + title = "PolyObject Anchor"; + sprite = "internal:polyanchor"; + angletext = "Tag"; + fixedrotation = 1; + tagthing = true; + unflippable = true; + } + + 761 + { + title = "PolyObject Spawn Point"; + sprite = "internal:polycenter"; + angletext = "Tag"; + fixedrotation = 1; + tagthing = true; + unflippable = true; + } + + 762 + { + title = "PolyObject Spawn Point (Crush)"; + sprite = "internal:polycentercrush"; + angletext = "Tag"; + fixedrotation = 1; + tagthing = true; + unflippable = true; + } + 780 + { + title = "Skybox View Point"; + sprite = "internal:skyb"; + flags4text = "[4] In-map centerpoint"; + parametertext = "ID"; + fixedrotation = 1; + } + } + + greenflower + { + color = 2; // Green + title = "Greenflower"; + + 800 + { + title = "GFZ Flower"; + sprite = "FWR1A0"; + width = 16; + height = 40; + } + 801 + { + title = "Sunflower"; + sprite = "FWR2A0"; + width = 16; + height = 96; + } + 802 + { + title = "Budding Flower"; + sprite = "FWR3A0"; + width = 8; + height = 32; + } + 803 + { + title = "Blueberry Bush"; + sprite = "BUS3A0"; + width = 16; + height = 32; + } + 804 + { + title = "Berry Bush"; + sprite = "BUS1A0"; + width = 16; + height = 32; + } + 805 + { + title = "Bush"; + sprite = "BUS2A0"; + width = 16; + height = 32; + } + 806 + { + title = "GFZ Tree"; + sprite = "TRE1A0"; + width = 20; + height = 128; + } + 807 + { + title = "GFZ Berry Tree"; + sprite = "TRE1B0"; + width = 20; + height = 128; + } + 808 + { + title = "GFZ Cherry Tree"; + sprite = "TRE1C0"; + width = 20; + height = 128; + } + 809 + { + title = "Checkered Tree"; + sprite = "TRE2A0"; + width = 20; + height = 200; + } + 810 + { + title = "Checkered Tree (Sunset)"; + sprite = "TRE2B0"; + width = 20; + height = 200; + } + 811 + { + title = "Polygon Tree"; + sprite = "TRE4A0"; + width = 20; + height = 200; + } + 812 + { + title = "Bush Tree"; + sprite = "TRE5A0"; + width = 20; + height = 200; + } + 813 + { + title = "Red Bush Tree"; + sprite = "TRE5B0"; + width = 20; + height = 200; + } + } + + technohill + { + color = 2; // Green + title = "Techno Hill"; + + 900 + { + title = "THZ Steam Flower"; + sprite = "THZPA0"; + width = 8; + height = 32; + } + 901 + { + title = "Alarm"; + sprite = "ALRMA0"; + width = 8; + height = 16; + hangs = 1; + } + 902 + { + title = "THZ Spin Flower (Red)"; + sprite = "FWR5A0"; + width = 16; + height = 64; + } + 903 + { + title = "THZ Spin Flower (Yellow)"; + sprite = "FWR6A0"; + width = 16; + height = 64; + } + 904 + { + arrow = 1; + title = "Whistlebush"; + sprite = "THZTA0"; + width = 16; + height = 64; + } + } + + deepsea + { + color = 2; // Green + title = "Deep Sea"; + + 1000 + { + arrow = 1; + blocking = 2; + title = "Gargoyle"; + sprite = "GARGA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1009 + { + arrow = 1; + blocking = 2; + title = "Gargoyle (Big)"; + sprite = "GARGB1"; + width = 32; + height = 80; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1001 + { + title = "Seaweed"; + sprite = "SEWEA0"; + width = 24; + height = 56; + } + 1002 + { + title = "Dripping Water"; + sprite = "DRIPD0"; + width = 8; + height = 16; + hangs = 1; + angletext = "Dripping delay"; + fixedrotation = 1; + } + 1003 + { + title = "Coral (Green)"; + sprite = "CORLA0"; + width = 29; + height = 40; + } + 1004 + { + title = "Coral (Red)"; + sprite = "CORLB0"; + width = 30; + height = 53; + } + 1005 + { + title = "Coral (Orange)"; + sprite = "CORLC0"; + width = 28; + height = 41; + } + 1006 + { + title = "Blue Crystal"; + sprite = "BCRYA1"; + width = 8; + height = 16; + } + 1007 + { + title = "Kelp"; + sprite = "KELPA0"; + width = 16; + height = 292; + flags4text = "[4] Double size"; + } + 1008 + { + title = "Stalagmite (DSZ1)"; + sprite = "DSTGA0"; + width = 8; + height = 116; + flags4text = "[4] Double size"; + } + 1010 + { + arrow = 1; + title = "Light Beam"; + sprite = "LIBEARAL"; + width = 16; + height = 16; + } + 1011 + { + title = "Stalagmite (DSZ2)"; + sprite = "DSTGB0"; + width = 8; + height = 116; + flags4text = "[4] Double size"; + } + 1012 + { + arrow = 1; + title = "Big Floating Mine"; + width = 28; + height = 56; + sprite = "BMNEA1"; + } + 1013 + { + title = "Animated Kelp"; + sprite = "ALGAA0"; + width = 48; + height = 120; + } + 1014 + { + title = "Large Coral (Brown)"; + sprite = "CORLD0"; + width = 56; + height = 112; + } + 1015 + { + title = "Large Coral (Beige)"; + sprite = "CORLE0"; + width = 56; + height = 112; + } + } + + castleeggman + { + color = 2; // Green + title = "Castle Eggman"; + + 1100 + { + title = "Chain (Decorative)"; + sprite = "CHANA0"; + width = 4; + height = 128; + hangs = 1; + } + 1101 + { + title = "Torch"; + sprite = "FLAMA0E0"; + width = 8; + height = 32; + flags1text = "[1] Add corona"; + } + 1102 + { + arrow = 1; + blocking = 2; + title = "Eggman Statue"; + sprite = "ESTAA1"; + width = 32; + height = 240; + flags1text = "[1] Solid gold"; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1103 + { + title = "CEZ Flower"; + sprite = "FWR4A0"; + width = 16; + height = 40; + } + 1104 + { + title = "Mace Spawnpoint"; + sprite = "SMCEA0"; + width = 17; + height = 34; + flags4text = "[4] No sounds"; + flags8text = "[8] Double size"; + angletext = "Tag"; + parametertext = "Spokes"; + fixedrotation = 1; + tagthing = true; + } + 1105 + { + title = "Chain with Maces Spawnpoint"; + sprite = "SMCEA0"; + width = 17; + height = 34; + flags4text = "[4] No sounds"; + flags8text = "[8] Double size"; + angletext = "Tag"; + parametertext = "Spokes"; + fixedrotation = 1; + tagthing = true; + } + 1106 + { + title = "Chained Spring Spawnpoint"; + sprite = "YSPBA0"; + width = 17; + height = 34; + flags4text = "[4] No sounds"; + flags8text = "[8] Red spring"; + angletext = "Tag"; + parametertext = "Spokes"; + fixedrotation = 1; + tagthing = true; + } + 1107 + { + title = "Chain Spawnpoint"; + sprite = "BMCHB0"; + width = 17; + height = 34; + flags8text = "[8] Double size"; + angletext = "Tag"; + parametertext = "Spokes"; + fixedrotation = 1; + tagthing = true; + } + 1108 + { + arrow = 1; + title = "Hidden Chain Spawnpoint"; + sprite = "SMCHA0"; + width = 17; + height = 34; + flags8text = "[8] Double size"; + } + 1109 + { + title = "Firebar Spawnpoint"; + sprite = "BFBRA0"; + width = 17; + height = 34; + flags4text = "[4] No sounds"; + flags8text = "[8] Double size"; + angletext = "Tag"; + parametertext = "Spokes"; + fixedrotation = 1; + tagthing = true; + } + 1110 + { + title = "Custom Mace Spawnpoint"; + sprite = "SMCEA0"; + width = 17; + height = 34; + flags4text = "[4] No sounds"; + angletext = "Tag"; + parametertext = "Spokes"; + fixedrotation = 1; + tagthing = true; + } + 1111 + { + arrow = 1; + blocking = 2; + title = "Crawla Statue"; + sprite = "CSTAA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1112 + { + arrow = 1; + blocking = 2; + title = "Lance-a-Bot Statue"; + sprite = "CBBSA1"; + width = 32; + height = 72; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1114 + { + title = "Pine Tree"; + sprite = "PINEA0"; + width = 16; + height = 628; + } + 1115 + { + title = "CEZ Shrub (Small)"; + sprite = "CEZBA0"; + width = 16; + height = 24; + } + 1116 + { + title = "CEZ Shrub (Large)"; + sprite = "CEZBB0"; + width = 32; + height = 48; + } + 1117 + { + arrow = 1; + title = "Pole Banner (Red)"; + sprite = "BANRA0"; + width = 40; + height = 224; + } + 1118 + { + arrow = 1; + title = "Pole Banner (Blue)"; + sprite = "BANRA0"; + width = 40; + height = 224; + } + 1119 + { + title = "Candle"; + sprite = "CNDLA0"; + width = 8; + height = 48; + flags1text = "[1] Add corona"; + } + 1120 + { + title = "Candle Pricket"; + sprite = "CNDLB0"; + width = 8; + height = 176; + flags1text = "[1] Add corona"; + } + 1121 + { + title = "Flame Holder"; + sprite = "FLMHA0"; + width = 24; + height = 80; + flags1text = "[1] Add corona"; + flags4text = "[4] No flame"; + } + 1122 + { + title = "Fire Torch"; + sprite = "CTRCA0"; + width = 16; + height = 80; + } + 1123 + { + title = "Cannonball Launcher"; + sprite = "internal:cannonball"; + width = 8; + height = 16; + } + 1124 + { + blocking = 2; + title = "Cannonball"; + sprite = "CBLLA0"; + width = 20; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1125 + { + title = "Brambles"; + sprite = "CABRALAR"; + width = 48; + height = 32; + } + 1126 + { + title = "Invisible Lockon Object"; + sprite = "LCKNC0"; + width = 16; + height = 32; + } + 1127 + { + title = "Spectator Eggrobo"; + sprite = "EGR1A1"; + width = 20; + height = 72; + arrow = 1; + flags4text = "[4] Move right"; + flags8text = "[8] Move left"; + } + 1128 + { + arrow = 1; + title = "Waving Flag (Red)"; + sprite = "CFLGA0"; + width = 8; + height = 208; + } + 1129 + { + arrow = 1; + title = "Waving Flag (Blue)"; + sprite = "CFLGA0"; + width = 8; + height = 208; + } + } + + aridcanyon + { + color = 2; // Green + title = "Arid Canyon"; + + 1200 + { + title = "Tumbleweed (Big)"; + sprite = "BTBLA0"; + width = 24; + height = 48; + flags8text = "[8] Moves perpetually"; + } + 1201 + { + title = "Tumbleweed (Small)"; + sprite = "STBLA0"; + width = 12; + height = 24; + flags8text = "[8] Moves perpetually"; + } + 1202 + { + arrow = 1; + title = "Rock Spawner"; + sprite = "ROIAA0"; + width = 8; + height = 16; + angletext = "Tag"; + fixedrotation = 1; + tagthing = true; + } + 1203 + { + title = "Tiny Red Flower Cactus"; + sprite = "CACTA0"; + width = 13; + height = 24; + } + 1204 + { + title = "Small Red Flower Cactus"; + sprite = "CACTB0"; + width = 15; + height = 52; + } + 1205 + { + title = "Tiny Blue Flower Cactus"; + sprite = "CACTC0"; + width = 13; + height = 24; + } + 1206 + { + title = "Small Blue Flower Cactus"; + sprite = "CACTD0"; + width = 15; + height = 52; + } + 1207 + { + title = "Prickly Pear"; + sprite = "CACTE0"; + width = 32; + height = 96; + } + 1208 + { + title = "Barrel Cactus"; + sprite = "CACTF0"; + width = 20; + height = 128; + } + 1209 + { + title = "Tall Barrel Cactus"; + sprite = "CACTG0"; + width = 24; + height = 224; + } + 1210 + { + title = "Armed Cactus"; + sprite = "CACTH0"; + width = 24; + height = 256; + } + 1211 + { + title = "Ball Cactus"; + sprite = "CACTI0"; + width = 48; + height = 96; + } + 1212 + { + title = "Caution Sign"; + sprite = "WWSGAR"; + width = 22; + height = 64; + arrow = 1; + } + 1213 + { + title = "Cacti Sign"; + sprite = "WWS2AR"; + width = 22; + height = 64; + arrow = 1; + } + 1214 + { + title = "Sharp Turn Sign"; + sprite = "WWS3ALAR"; + width = 16; + height = 192; + arrow = 1; + } + 1215 + { + title = "Mine Oil Lamp"; + sprite = "OILLA0"; + width = 22; + height = 64; + hangs = 1; + } + 1216 + { + title = "TNT Barrel"; + sprite = "BARRA1"; + width = 24; + height = 63; + arrow = 1; + flags8text = "[8] Not pushable"; + } + 1217 + { + title = "TNT Proximity Shell"; + sprite = "REMTA0"; + width = 64; + height = 40; + } + 1218 + { + title = "Dust Devil"; + sprite = "TAZDCR"; + width = 80; + height = 416; + } + 1219 + { + title = "Minecart Spawner"; + sprite = "MCRTCLFR"; + width = 22; + height = 32; + arrow = 1; + } + 1220 + { + title = "Minecart Stopper"; + sprite = "MCRTIR"; + width = 32; + height = 32; + arrow = 1; + } + 1221 + { + title = "Minecart Saloon Door"; + sprite = "SALDARAL"; + width = 96; + height = 160; + arrow = 1; + flags8text = "[8] Allow non-minecart players"; + } + 1222 + { + title = "Train Cameo Spawner"; + sprite = "TRAEBRBL"; + width = 28; + height = 32; + } + 1223 + { + title = "Train Dust Spawner"; + sprite = "ADSTA0"; + width = 4; + height = 4; + } + 1224 + { + title = "Train Steam Spawner"; + sprite = "STEAA0"; + width = 4; + height = 4; + } + 1229 + { + title = "Minecart Switch Point"; + sprite = "internal:zoom"; + width = 8; + height = 16; + flags8text = "[8] Enable switching"; + } + 1230 + { + title = "Tiny Cactus"; + sprite = "CACTJ0"; + width = 13; + height = 28; + } + 1231 + { + title = "Small Cactus"; + sprite = "CACTK0"; + width = 15; + height = 60; + } + } + + redvolcano + { + color = 2; // Green + title = "Red Volcano"; + + 1300 + { + arrow = 1; + title = "Flame Jet (Horizontal)"; + sprite = "internal:flameh"; + width = 16; + height = 40; + flags8text = "[8] Waves vertically"; + angletext = "On/Off time"; + fixedrotation = 1; + parametertext = "Strength"; + } + 1301 + { + title = "Flame Jet (Vertical)"; + sprite = "internal:flamev"; + width = 16; + height = 40; + flags8text = "[8] Shoot downwards"; + angletext = "On/Off time"; + fixedrotation = 1; + parametertext = "Strength"; + } + 1302 + { + title = "Spinning Flame Jet (Counter-Clockwise)"; + sprite = "internal:flame2"; + width = 16; + height = 24; + } + 1303 + { + title = "Spinning Flame Jet (Clockwise)"; + sprite = "internal:flame1"; + width = 16; + height = 24; + } + 1304 + { + title = "Lavafall"; + sprite = "LFALF0"; + width = 30; + height = 32; + angletext = "Initial delay"; + fixedrotation = 1; + hangs = 1; + flags8text = "[8] Double size"; + } + 1305 + { + title = "Rollout Rock"; + sprite = "PUMIA1A5"; + width = 30; + height = 60; + flags8text = "[8] Non-buoyant"; + } + 1306 + { + title = "Big Fern"; + sprite = "JPLAB0"; + width = 32; + height = 48; + } + 1307 + { + title = "Jungle Palm"; + sprite = "JPLAC0"; + width = 32; + height = 48; + } + 1308 + { + title = "Torch Flower"; + sprite = "TFLOA0"; + width = 14; + height = 110; + } + 1309 + { + title = "RVZ1 Wall Vine (Long)"; + sprite = "WVINALAR"; + width = 1; + height = 288; + arrow = 1; + } + 1310 + { + title = "RVZ1 Wall Vine (Short)"; + sprite = "WVINBLBR"; + width = 1; + height = 288; + arrow = 1; + } + } + + botanicserenity + { + color = 2; // Green + title = "Botanic Serenity"; + width = 16; + height = 32; + sprite = "BSZ1A0"; + 1400 + { + title = "Tall Flower (Red)"; + sprite = "BSZ1A0"; + } + 1401 + { + title = "Tall Flower (Purple)"; + sprite = "BSZ1B0"; + } + 1402 + { + title = "Tall Flower (Blue)"; + sprite = "BSZ1C0"; + } + 1403 + { + title = "Tall Flower (Cyan)"; + sprite = "BSZ1D0"; + } + 1404 + { + title = "Tall Flower (Yellow)"; + sprite = "BSZ1E0"; + } + 1405 + { + title = "Tall Flower (Orange)"; + sprite = "BSZ1F0"; + } + 1410 + { + title = "Medium Flower (Red)"; + sprite = "BSZ2A0"; + } + 1411 + { + title = "Medium Flower (Purple)"; + sprite = "BSZ2B0"; + } + 1412 + { + title = "Medium Flower (Blue)"; + sprite = "BSZ2C0"; + } + 1413 + { + title = "Medium Flower (Cyan)"; + sprite = "BSZ2D0"; + } + 1414 + { + title = "Medium Flower (Yellow)"; + sprite = "BSZ2E0"; + } + 1415 + { + title = "Medium Flower (Orange)"; + sprite = "BSZ2F0"; + } + 1420 + { + title = "Short Flower (Red)"; + sprite = "BSZ3A0"; + } + 1421 + { + title = "Short Flower (Purple)"; + sprite = "BSZ3B0"; + } + 1422 + { + title = "Short Flower (Blue)"; + sprite = "BSZ3C0"; + } + 1423 + { + title = "Short Flower (Cyan)"; + sprite = "BSZ3D0"; + } + 1424 + { + title = "Short Flower (Yellow)"; + sprite = "BSZ3E0"; + } + 1425 + { + title = "Short Flower (Orange)"; + sprite = "BSZ3F0"; + } + 1430 + { + title = "Tulip (Red)"; + sprite = "BST1A0"; + } + 1431 + { + title = "Tulip (Purple)"; + sprite = "BST2A0"; + } + 1432 + { + title = "Tulip (Blue)"; + sprite = "BST3A0"; + } + 1433 + { + title = "Tulip (Cyan)"; + sprite = "BST4A0"; + } + 1434 + { + title = "Tulip (Yellow)"; + sprite = "BST5A0"; + } + 1435 + { + title = "Tulip (Orange)"; + sprite = "BST6A0"; + } + 1440 + { + title = "Cluster (Red)"; + sprite = "BSZ5A0"; + } + 1441 + { + title = "Cluster (Purple)"; + sprite = "BSZ5B0"; + } + 1442 + { + title = "Cluster (Blue)"; + sprite = "BSZ5C0"; + } + 1443 + { + title = "Cluster (Cyan)"; + sprite = "BSZ5D0"; + } + 1444 + { + title = "Cluster (Yellow)"; + sprite = "BSZ5E0"; + } + 1445 + { + title = "Cluster (Orange)"; + sprite = "BSZ5F0"; + } + 1450 + { + title = "Bush (Red)"; + sprite = "BSZ6A0"; + } + 1451 + { + title = "Bush (Purple)"; + sprite = "BSZ6B0"; + } + 1452 + { + title = "Bush (Blue)"; + sprite = "BSZ6C0"; + } + 1453 + { + title = "Bush (Cyan)"; + sprite = "BSZ6D0"; + } + 1454 + { + title = "Bush (Yellow)"; + sprite = "BSZ6E0"; + } + 1455 + { + title = "Bush (Orange)"; + sprite = "BSZ6F0"; + } + 1460 + { + title = "Vine (Red)"; + sprite = "BSZ7A0"; + } + 1461 + { + title = "Vine (Purple)"; + sprite = "BSZ7B0"; + } + 1462 + { + title = "Vine (Blue)"; + sprite = "BSZ7C0"; + } + 1463 + { + title = "Vine (Cyan)"; + sprite = "BSZ7D0"; + } + 1464 + { + title = "Vine (Yellow)"; + sprite = "BSZ7E0"; + } + 1465 + { + title = "Vine (Orange)"; + sprite = "BSZ7F0"; + } + 1470 + { + title = "BSZ Shrub"; + sprite = "BSZ8A0"; + } + 1471 + { + title = "BSZ Clover"; + sprite = "BSZ8B0"; + } + 1473 + { + title = "Palm Tree (Big)"; + width = 16; + height = 160; + sprite = "BSZ8D0"; + } + 1475 + { + title = "Palm Tree (Small)"; + width = 16; + height = 80; + sprite = "BSZ8F0"; + } + } + + azuretemple + { + color = 2; // Green + title = "Azure Temple"; + + 1500 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle"; + sprite = "BGARA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1501 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle (Up)"; + sprite = "BGARA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1502 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle (Down)"; + sprite = "BGARA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1503 + { + arrow = 1; + blocking = 2; + title = "Glaregoyle (Long)"; + sprite = "BGARA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1504 + { + title = "ATZ Target"; + sprite = "RCRYB0"; + width = 24; + height = 32; + } + 1505 + { + title = "Green Flame"; + sprite = "CFLMA0E0"; + width = 8; + height = 32; + } + 1506 + { + arrow = 1; + blocking = 2; + title = "Blue Gargoyle"; + sprite = "BGARD1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + } + + dreamhill + { + color = 2; // Green + title = "Dream Hill"; + + 1600 + { + title = "Spring Tree"; + sprite = "TRE6A0"; + width = 16; + height = 32; + } + 1601 + { + title = "Shleep"; + sprite = "SHLPA0"; + width = 24; + height = 32; + } + 1602 + { + title = "Nightopian"; + sprite = "NTPNA1"; + width = 16; + height = 40; + } + } + + nightstrk + { + color = 16; // Light Pink + title = "NiGHTS Track & Basics"; + width = 8; + height = 4096; + sprite = "UNKNA0"; + fixedrotation = 1; + + 1700 + { + title = "Axis"; + sprite = "internal:axis1"; + circle = 1; + unflippable = true; + ignoreZ = true; + flagsvaluetext = "Order"; + angletext = "Radius/Direction"; + parametertext = "Mare"; + } + 1701 + { + title = "Axis Transfer"; + sprite = "internal:axis2"; + unflippable = true; + ignoreZ = true; + flagsvaluetext = "Order"; + parametertext = "Mare"; + } + 1702 + { + title = "Axis Transfer Line"; + sprite = "internal:axis3"; + unflippable = true; + ignoreZ = true; + flagsvaluetext = "Order"; + parametertext = "Mare"; + } + 1703 + { + title = "Ideya Drone"; + sprite = "NDRNA1"; + width = 16; + height = 56; + flags1text = "[1] Align player to middle"; + flags4text = "[4] Align player to top"; + flags8text = "[8] Die upon time up"; + angletext = "Time limit"; + fixedrotation = 1; + parametertext = "Height"; + } + 1710 + { + title = "Ideya Capture"; + sprite = "CAPSA0"; + width = 72; + height = 144; + angletext = "Spheres"; + parametertext = "Mare"; + } + } + + nights + { + color = 13; // Pink + title = "NiGHTS Items"; + width = 16; + height = 32; + 1704 + { + arrow = 1; + title = "NiGHTS Bumper"; + sprite = "NBMPG3G7"; + width = 32; + height = 64; + unflippable = true; + flagsvaluetext = "Pitch"; + angletext = "Yaw"; + } + 1705 + { + arrow = 1; + title = "Hoop (Generic)"; + sprite = "internal:nightshoop"; + width = 80; + height = 160; + unflippable = true; + centerHitbox = true; + flagsvaluetext = "Height"; + angletext = "Pitch/Yaw"; + parametertext = "Degrees?"; + } + 1706 + { + title = "Blue Sphere"; + sprite = "SPHRA0"; + width = 16; + height = 24; + flags8height = 24; + flags8text = "[8] Float"; + } + 1707 + { + title = "Super Paraloop"; + sprite = "NPRUA0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1708 + { + title = "Drill Refill"; + sprite = "NPRUB0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1709 + { + title = "Nightopian Helper"; + sprite = "NPRUC0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1711 + { + title = "Extra Time"; + sprite = "NPRUD0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1712 + { + title = "Link Freeze"; + sprite = "NPRUE0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1713 + { + arrow = 1; + title = "Hoop (Customizable)"; + flags1text = "[1] Radius +16"; + flags2text = "[2] Radius +32"; + flags4text = "[4] Radius +64"; + flags8text = "[8] Radius +128"; + sprite = "internal:nightshoop"; + width = 80; + height = 160; + unflippable = true; + centerHitbox = true; + angletext = "Pitch/Yaw"; + parametertext = "Degrees?"; + } + 1714 + { + title = "Ideya Anchor Point"; + sprite = "internal:axis1"; + width = 8; + height = 16; + parametertext = "Ideya"; + } + } + + mario + { + color = 6; // Brown + title = "Mario"; + + 1800 + { + title = "Coin"; + sprite = "COINA0"; + width = 16; + height = 24; + flags8height = 24; + flags8text = "[8] Float"; + } + 1801 + { + arrow = 1; + title = "Goomba"; + sprite = "GOOMA0"; + width = 24; + height = 32; + } + 1802 + { + arrow = 1; + title = "Goomba (Blue)"; + sprite = "BGOMA0"; + width = 24; + height = 32; + } + 1803 + { + title = "Fire Flower"; + sprite = "FFWRB0"; + width = 16; + height = 32; + } + 1804 + { + title = "Koopa Shell"; + sprite = "SHLLA1"; + width = 16; + height = 20; + } + 1805 + { + title = "Puma (Jumping Fireball)"; + sprite = "PUMAA0"; + width = 8; + height = 16; + angletext = "Jump strength"; + fixedrotation = 1; + } + 1806 + { + title = "King Bowser"; + sprite = "KOOPA0"; + width = 16; + height = 48; + } + 1807 + { + title = "Axe"; + sprite = "MAXEA0"; + width = 8; + height = 16; + } + 1808 + { + title = "Bush (Short)"; + sprite = "MUS1A0"; + width = 16; + height = 32; + } + 1809 + { + title = "Bush (Tall)"; + sprite = "MUS2A0"; + width = 16; + height = 32; + } + 1810 + { + title = "Toad"; + sprite = "TOADA0"; + width = 8; + height = 32; + } + } + + christmasdisco + { + color = 2; // Green + title = "Christmas & Disco"; + + 1850 + { + title = "Christmas Pole"; + sprite = "XMS1A0"; + width = 16; + height = 40; + } + 1851 + { + title = "Candy Cane"; + sprite = "XMS2A0"; + width = 8; + height = 32; + } + 1852 + { + blocking = 2; + title = "Snowman"; + sprite = "XMS3A0"; + width = 16; + height = 64; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1853 + { + blocking = 2; + title = "Snowman (With Hat)"; + sprite = "XMS3B0"; + width = 16; + height = 80; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1854 + { + title = "Lamp Post"; + sprite = "XMS4A0"; + width = 8; + height = 120; + } + 1855 + { + title = "Lamp Post (Snow)"; + sprite = "XMS4B0"; + width = 8; + height = 120; + } + 1856 + { + title = "Hanging Star"; + sprite = "XMS5A0"; + width = 4; + height = 80; + hangs = 1; + } + 1857 + { + title = "Berry Bush (Snow)"; + sprite = "BUS1B0"; + width = 16; + height = 32; + } + 1858 + { + title = "Bush (Snow)"; + sprite = "BUS2B0"; + width = 16; + height = 32; + } + 1859 + { + title = "Blueberry Bush (Snow)"; + sprite = "BUS3B0"; + width = 16; + height = 32; + } + 1875 + { + title = "Disco Ball"; + sprite = "DBALA0"; + width = 16; + height = 54; + hangs = 1; + } + 1876 + { + arrow = 1; + blocking = 2; + title = "Eggman Disco Statue"; + sprite = "ESTAB1"; + width = 20; + height = 96; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + } + + stalagmites + { + color = 2; // Green + title = "Stalagmites"; + width = 16; + height = 40; + + 1900 + { + title = "Brown Stalagmite (Tall)"; + sprite = "STLGA0"; + width = 16; + height = 40; + } + 1901 + { + title = "Brown Stalagmite"; + sprite = "STLGB0"; + width = 16; + height = 40; + } + 1902 + { + title = "Orange Stalagmite (Tall)"; + sprite = "STLGC0"; + width = 16; + height = 40; + } + 1903 + { + title = "Orange Stalagmite"; + sprite = "STLGD0"; + width = 16; + height = 40; + } + 1904 + { + title = "Red Stalagmite (Tall)"; + sprite = "STLGE0"; + width = 16; + height = 40; + } + 1905 + { + title = "Red Stalagmite"; + sprite = "STLGF0"; + width = 16; + height = 40; + } + 1906 + { + title = "Gray Stalagmite (Tall)"; + sprite = "STLGG0"; + width = 24; + height = 96; + } + 1907 + { + title = "Gray Stalagmite"; + sprite = "STLGH0"; + width = 16; + height = 40; + } + 1908 + { + title = "Blue Stalagmite (Tall)"; + sprite = "STLGI0"; + width = 16; + height = 40; + } + 1909 + { + title = "Blue Stalagmite"; + sprite = "STLGJ0"; + width = 16; + height = 40; + } + } + + hauntedheights + { + color = 2; // Green + title = "Haunted Heights"; + + 2000 + { + title = "Smashing Spikeball"; + sprite = "FMCEA0"; + width = 18; + height = 28; + angletext = "Initial delay"; + fixedrotation = 1; + } + 2001 + { + title = "HHZ Grass"; + sprite = "HHZMA0"; + width = 16; + height = 40; + } + 2002 + { + title = "HHZ Tentacle 1"; + sprite = "HHZMB0"; + width = 16; + height = 40; + } + 2003 + { + title = "HHZ Tentacle 2"; + sprite = "HHZMC0"; + width = 16; + height = 40; + } + 2004 + { + title = "HHZ Stalagmite (Tall)"; + sprite = "HHZME0"; + width = 16; + height = 40; + } + 2005 + { + title = "HHZ Stalagmite (Short)"; + sprite = "HHZMF0"; + width = 16; + height = 40; + } + 2006 + { + title = "Jack-o'-lantern 1"; + sprite = "PUMKA0"; + width = 16; + height = 40; + flags1text = "[1] Don't flicker"; + } + 2007 + { + title = "Jack-o'-lantern 2"; + sprite = "PUMKB0"; + width = 16; + height = 40; + flags1text = "[1] Don't flicker"; + } + 2008 + { + title = "Jack-o'-lantern 3"; + sprite = "PUMKC0"; + width = 16; + height = 40; + flags1text = "[1] Don't flicker"; + } + 2009 + { + title = "Purple Mushroom"; + sprite = "SHRMD0"; + width = 16; + height = 48; + } + 2010 + { + title = "HHZ Tree"; + sprite = "HHPLC0"; + width = 12; + height = 40; + } + } + + frozenhillside + { + color = 2; // Green + title = "Frozen Hillside"; + + 2100 + { + title = "Ice Shard (Small)"; + sprite = "FHZIA0"; + width = 8; + height = 32; + } + 2101 + { + title = "Ice Shard (Large)"; + sprite = "FHZIB0"; + width = 8; + height = 32; + } + 2102 + { + title = "Crystal Tree (Aqua)"; + sprite = "TRE3A0"; + width = 20; + height = 200; + } + 2103 + { + title = "Crystal Tree (Pink)"; + sprite = "TRE3B0"; + width = 20; + height = 200; + } + 2104 + { + title = "Amy Cameo"; + sprite = "ROSYA1"; + width = 16; + height = 48; + flags1text = "[1] Grayscale mode"; + } + 2105 + { + title = "Mistletoe"; + sprite = "XMS6A0"; + width = 52; + height = 106; + hangs = 1; + } + } + + tutorial + { + color = 2; // Green + title = "Tutorial"; + + 799 + { + title = "Tutorial Plant"; + sprite = "TUPFH0"; + width = 40; + height = 144; + parametertext = "Start frame"; + } + } + + flickies + { + color = 3; // Teal + title = "Flickies"; + width = 8; + height = 20; + flags1text = "[1] Move aimlessly"; + flags4text = "[4] No movement"; + flags8text = "[8] Hop"; + angletext = "Radius"; + fixedrotation = 1; + + 2200 + { + title = "Bluebird"; + sprite = "FL01A1"; + } + 2201 + { + title = "Rabbit"; + sprite = "FL02A1"; + } + 2202 + { + title = "Chicken"; + sprite = "FL03A1"; + } + 2203 + { + title = "Seal"; + sprite = "FL04A1"; + } + 2204 + { + title = "Pig"; + sprite = "FL05A1"; + } + 2205 + { + title = "Chipmunk"; + sprite = "FL06A1"; + } + 2206 + { + title = "Penguin"; + sprite = "FL07A1"; + } + 2207 + { + title = "Fish"; + sprite = "FL08A1"; + parametertext = "Color"; + } + 2208 + { + title = "Ram"; + sprite = "FL09A1"; + } + 2209 + { + title = "Puffin"; + sprite = "FL10A1"; + } + 2210 + { + title = "Cow"; + sprite = "FL11A1"; + } + 2211 + { + title = "Rat"; + sprite = "FL12A1"; + } + 2212 + { + title = "Bear"; + sprite = "FL13A1"; + } + 2213 + { + title = "Dove"; + sprite = "FL14A1"; + } + 2214 + { + title = "Cat"; + sprite = "FL15A1"; + } + 2215 + { + title = "Canary"; + sprite = "FL16A1"; + } + 2216 + { + title = "Spider"; + sprite = "FS01A1"; + } + 2217 + { + title = "Bat"; + sprite = "FS02A0"; + } + } +} + +//Default things filters +thingsfilters +{ + + filter0 + { + name = "Player starts"; + category = "starts"; + type = -1; + } + + + filter1 + { + name = "Enemies"; + category = "enemies"; + type = -1; + + } + + + filter2 + { + name = "NiGHTS Track"; + category = "nightstrk"; + type = -1; + + } + + + filter3 + { + name = "Normal Gravity"; + category = ""; + type = -1; + + fields + { + 2 = false; + } + + } + + + filter4 + { + name = "Reverse Gravity"; + category = ""; + type = -1; + + fields + { + 2 = true; + } + + } +} diff --git a/libs/SDL2/WhatsNew.txt b/libs/SDL2/WhatsNew.txt index 4e17d25aaab278221b4c0d038f4c6bb11cf40b96..28f60c98ad8f279f8fd62bdd56e99e13798a0452 100644 --- a/libs/SDL2/WhatsNew.txt +++ b/libs/SDL2/WhatsNew.txt @@ -1,28 +1,9 @@ This is a list of major changes in SDL's version history. ---------------------------------------------------------------------------- -2.30.0: ---------------------------------------------------------------------------- - -General: -* Added support for 2 bits-per-pixel indexed surface formats -* Added the function SDL_GameControllerGetSteamHandle() to get the Steam API handle for a controller, if available -* Added the event SDL_CONTROLLERSTEAMHANDLEUPDATED which is sent when the Steam API handle for a controller changes. This could also change the name, VID, and PID of the controller. -* Added the environment variable SDL_LOGGING to control default log output - -macOS: -* Added the hint SDL_HINT_JOYSTICK_IOKIT to control whether the IOKit controller driver should be used -* Added the hint SDL_HINT_JOYSTICK_MFI to control whether the GCController controller driver should be used -* Added the hint SDL_HINT_RENDER_METAL_PREFER_LOW_POWER_DEVICE to choose whether high or low power GPU should be used for rendering, in the case where there are multiple GPUs available - -Xbox: -* Added the function SDL_GDKGetDefaultUser() - --------------------------------------------------------------------------- 2.28.2: --------------------------------------------------------------------------- - General: * Added the hint SDL_HINT_JOYSTICK_WGI to control whether to use Windows.Gaming.Input for controllers diff --git a/libs/SDL2/docs/README-android.md b/libs/SDL2/docs/README-android.md index 6b4307839102ab6b47bdabaaf7bafdd8a9123845..f08493529c577e38b8906dcc019b8e4da3a8571c 100644 --- a/libs/SDL2/docs/README-android.md +++ b/libs/SDL2/docs/README-android.md @@ -72,7 +72,7 @@ done in the build directory for the app! For more complex projects, follow these instructions: 1. Get the source code for SDL and copy the 'android-project' directory located at SDL/android-project to a suitable location. Also make sure to rename it to your project name (In these examples: YOURPROJECT). - + (The 'android-project' directory can basically be seen as a sort of starting point for the android-port of your project. It contains the glue code between the Android Java 'frontend' and the SDL code 'backend'. It also contains some standard behaviour, like how events should be handled, which you will be able to change.) 2. Move or [symlink](https://en.wikipedia.org/wiki/Symbolic_link) the SDL directory into the "YOURPROJECT/app/jni" directory diff --git a/libs/SDL2/docs/README-dynapi.md b/libs/SDL2/docs/README-dynapi.md index 6d447eab6906c5dc61842dee8331e0a6959b46d8..8eb6fb21e54d4b7ab829f28901f4c7e138c6c963 100644 --- a/libs/SDL2/docs/README-dynapi.md +++ b/libs/SDL2/docs/README-dynapi.md @@ -35,7 +35,7 @@ SDL now has, internally, a table of function pointers. So, this is what SDL_Init now looks like: ```c -Uint32 SDL_Init(Uint32 flags) +UInt32 SDL_Init(Uint32 flags) { return jump_table.SDL_Init(flags); } @@ -100,7 +100,7 @@ a shared library of its own). If so, it loads that library and looks for and calls a single function: ```c -Sint32 SDL_DYNAPI_entry(Uint32 version, void *table, Uint32 tablesize); +SInt32 SDL_DYNAPI_entry(Uint32 version, void *table, Uint32 tablesize); ``` That function takes a version number (more on that in a moment), the address of diff --git a/libs/SDL2/docs/README-emscripten.md b/libs/SDL2/docs/README-emscripten.md index cefad99c4ee80e78a7ff3230f89e7749b3f644d5..f952b08e43c3d0cc0173578daef6eef84856b1b0 100644 --- a/libs/SDL2/docs/README-emscripten.md +++ b/libs/SDL2/docs/README-emscripten.md @@ -1,187 +1,27 @@ # Emscripten -## The state of things +(This documentation is not very robust; we will update and expand this later.) -(As of September 2023, but things move quickly and we don't update this -document often.) - -In modern times, all the browsers you probably care about (Chrome, Firefox, -Edge, and Safari, on Windows, macOS, Linux, iOS and Android), support some -reasonable base configurations: - -- WebAssembly (don't bother with asm.js any more) -- WebGL (which will look like OpenGL ES 2 or 3 to your app). -- Threads (see caveats, though!) -- Game controllers -- Autoupdating (so you can assume they have a recent version of the browser) - -All this to say we're at the point where you don't have to make a lot of -concessions to get even a fairly complex SDL-based game up and running. - - -## RTFM - -This document is a quick rundown of some high-level details. The -documentation at [emscripten.org](https://emscripten.org/) is vast -and extremely detailed for a wide variety of topics, and you should at -least skim through it at some point. - - -## Porting your app to Emscripten - -Many many things just need some simple adjustments and they'll compile -like any other C/C++ code, as long as SDL was handling the platform-specific -work for your program. - -First, you probably need this in at least one of your source files: - -```c -#ifdef __EMSCRIPTEN__ -#include <emscripten.h> -#endif -``` - -Second: assembly language code has to go. Replace it with C. You can even use -[x86 SIMD intrinsic functions in Emscripten](https://emscripten.org/docs/porting/simd.html)! - -Third: Middleware has to go. If you have a third-party library you link -against, you either need an Emscripten port of it, or the source code to it -to compile yourself, or you need to remove it. - -Fourth: You still start in a function called main(), but you need to get out of -it and into a function that gets called repeatedly, and returns quickly, -called a mainloop. - -Somewhere in your program, you probably have something that looks like a more -complicated version of this: - -```c -void main(void) -{ - initialize_the_game(); - while (game_is_still_running) { - check_for_new_input(); - think_about_stuff(); - draw_the_next_frame(); - } - deinitialize_the_game(); -} -``` - -This will not work on Emscripten, because the main thread needs to be free -to do stuff and can't sit in this loop forever. So Emscripten lets you set up -a [mainloop](https://emscripten.org/docs/porting/emscripten-runtime-environment.html#browser-main-loop). - -```c -static void mainloop(void) /* this will run often, possibly at the monitor's refresh rate */ -{ - if (!game_is_still_running) { - deinitialize_the_game(); - #ifdef __EMSCRIPTEN__ - emscripten_cancel_main_loop(); /* this should "kill" the app. */ - #else - exit(0); - #endif - } - - check_for_new_input(); - think_about_stuff(); - draw_the_next_frame(); -} - -void main(void) -{ - initialize_the_game(); - #ifdef __EMSCRIPTEN__ - emscripten_set_main_loop(mainloop, 0, 1); - #else - while (1) { mainloop(); } - #endif -} -``` - -Basically, `emscripten_set_main_loop(mainloop, 0, 1);` says "run -`mainloop` over and over until I end the program." The function will -run, and return, freeing the main thread for other tasks, and then -run again when it's time. The `1` parameter does some magic to make -your main() function end immediately; this is useful because you -don't want any shutdown code that might be sitting below this code -to actually run if main() were to continue on, since we're just -getting started. - -There's a lot of little details that are beyond the scope of this -document, but that's the biggest intial set of hurdles to porting -your app to the web. - - -## Do you need threads? - -If you plan to use threads, they work on all major browsers now. HOWEVER, -they bring with them a lot of careful considerations. Rendering _must_ -be done on the main thread. This is a general guideline for many -platforms, but a hard requirement on the web. - -Many other things also must happen on the main thread; often times SDL -and Emscripten make efforts to "proxy" work to the main thread that -must be there, but you have to be careful (and read more detailed -documentation than this for the finer points). - -Even when using threads, your main thread needs to set an Emscripten -mainloop that runs quickly and returns, or things will fail to work -correctly. - -You should definitely read [Emscripten's pthreads docs](https://emscripten.org/docs/porting/pthreads.html) -for all the finer points. Mostly SDL's thread API will work as expected, -but is built on pthreads, so it shares the same little incompatibilities -that are documented there, such as where you can use a mutex, and when -a thread will start running, etc. - - -IMPORTANT: You have to decide to either build something that uses -threads or something that doesn't; you can't have one build -that works everywhere. This is an Emscripten (or maybe WebAssembly? -Or just web browsers in general?) limitation. If you aren't using -threads, it's easier to not enable them at all, at build time. - -If you use threads, you _have to_ run from a web server that has -[COOP/COEP headers set correctly](https://web.dev/why-coop-coep/) -or your program will fail to start at all. - -If building with threads, `__EMSCRIPTEN_PTHREADS__` will be defined -for checking with the C preprocessor, so you can build something -different depending on what sort of build you're compiling. - - -## Audio - -Audio works as expected at the API level, but not exactly like other -platforms. - -You'll only see a single default audio device. Audio capture also works; -if the browser pops up a prompt to ask for permission to access the -microphone, the SDL_OpenAudioDevice call will succeed and start producing -silence at a regular interval. Once the user approves the request, real -audio data will flow. If the user denies it, the app is not informed and -will just continue to receive silence. +## A quick note about audio Modern web browsers will not permit web pages to produce sound before the -user has interacted with them (clicked or tapped on them, usually); this is -for several reasons, not the least of which being that no one likes when a -random browser tab suddenly starts making noise and the user has to scramble -to figure out which and silence it. - -SDL will allow you to open the audio device for playback in this -circumstance, and your audio callback will fire, but SDL will throw the audio -data away until the user interacts with the page. This helps apps that depend -on the audio callback to make progress, and also keeps audio playback in sync -once the app is finally allowed to make noise. - -There are two reasonable ways to deal with the silence at the app level: -if you are writing some sort of media player thing, where the user expects -there to be a volume control when you mouseover the canvas, just default -that control to a muted state; if the user clicks on the control to unmute -it, on this first click, open the audio device. This allows the media to -play at start, and the user can reasonably opt-in to listening. +user has interacted with them; this is for several reasons, not the least +of which being that no one likes when a random browser tab suddenly starts +making noise and the user has to scramble to figure out which and silence +it. + +To solve this, most browsers will refuse to let a web app use the audio +subsystem at all before the user has interacted with (clicked on) the page +in a meaningful way. SDL-based apps also have to deal with this problem; if +the user hasn't interacted with the page, SDL_OpenAudioDevice will fail. + +There are two reasonable ways to deal with this: if you are writing some +sort of media player thing, where the user expects there to be a volume +control when you mouseover the canvas, just default that control to a muted +state; if the user clicks on the control to unmute it, on this first click, +open the audio device. This allows the media to play at start, the user can +reasonably opt-in to listening, and you never get access denied to the audio +device. Many games do not have this sort of UI, and are more rigid about starting audio along with everything else at the start of the process. For these, your @@ -196,179 +36,41 @@ Please see the discussion at https://github.com/libsdl-org/SDL/issues/6385 for some Javascript code to steal for this approach. -## Rendering - -If you use SDL's 2D render API, it will use GLES2 internally, which -Emscripten will turn into WebGL calls. You can also use OpenGL ES 2 -directly by creating a GL context and drawing into it. - -Calling SDL_RenderPresent (or SDL_GL_SwapWindow) will not actually -present anything on the screen until your return from your mainloop -function. - - ## Building SDL/emscripten -First: do you _really_ need to build SDL from source? - -If you aren't developing SDL itself, have a desire to mess with its source -code, or need something on the bleeding edge, don't build SDL. Just use -Emscripten's packaged version! - -Compile and link your app with `-sUSE_SDL=2` and it'll use a build of -SDL packaged with Emscripten. This comes from the same source code and -fixes the Emscripten project makes to SDL are generally merged into SDL's -revision control, so often this is much easier for app developers. - -`-sUSE_SDL=1` will select Emscripten's JavaScript reimplementation of SDL -1.2 instead; if you need SDL 1.2, this might be fine, but we generally -recommend you don't use SDL 1.2 in modern times. - - -If you want to build SDL, though... - SDL currently requires at least Emscripten 3.1.35 to build. Newer versions are likely to work, as well. Build: -This works on Linux/Unix and macOS. Please send comments about Windows. - -Make sure you've [installed emsdk](https://emscripten.org/docs/getting_started/downloads.html) -first, and run `source emsdk_env.sh` at the command line so it finds the -tools. - -(These configure options might be overkill, but this has worked for me.) - -```bash -cd SDL -mkdir build -cd build -emconfigure ../configure --host=wasm32-unknown-emscripten --disable-pthreads --disable-assembly --disable-cpuinfo CFLAGS="-sUSE_SDL=0 -O3" -emmake make -j4 -``` - -If you want to build with thread support, something like this works: - -```bash -emconfigure ../configure --host=wasm32-unknown-emscripten --enable-pthreads --disable-assembly --disable-cpuinfo CFLAGS="-sUSE_SDL=0 -O3 -pthread" LDFLAGS="-pthread" -``` + $ mkdir build + $ cd build + $ emconfigure ../configure --host=asmjs-unknown-emscripten --disable-assembly --disable-threads --disable-cpuinfo CFLAGS="-O2" + $ emmake make Or with cmake: -```bash -mkdir build -cd build -emcmake cmake .. -emmake make -j4 -``` + $ mkdir build + $ cd build + $ emcmake cmake .. + $ emmake make To build one of the tests: -```bash -cd test/ -emcc -O2 --js-opts 0 -g4 testdraw2.c -I../include ../build/.libs/libSDL2.a ../build/libSDL2_test.a -o a.html -``` - -## Building your app - -You need to compile with `emcc` instead of `gcc` or `clang` or whatever, but -mostly it uses the same command line arguments as Clang. - -Link against the SDL/build/.libs/libSDL2.a file you generated by building SDL, -link with `-sUSE_SDL=2` to use Emscripten's prepackaged SDL2 build. - -Usually you would produce a binary like this: - -```bash -gcc -o mygame mygame.c # or whatever -``` - -But for Emscripten, you want to output something else: - -```bash -emcc -o index.html mygame.c -``` - -This will produce several files...support Javascript and WebAssembly (.wasm) -files. The `-o index.html` will produce a simple HTML page that loads and -runs your app. You will (probably) eventually want to replace or customize -that file and do `-o index.js` instead to just build the code pieces. - -If you're working on a program of any serious size, you'll likely need to -link with `-sALLOW_MEMORY_GROWTH=1 -sMAXIMUM_MEMORY=1gb` to get access -to more memory. If using pthreads, you'll need the `-sMAXIMUM_MEMORY=1gb` -or the app will fail to start on iOS browsers, but this might be a bug that -goes away in the future. - - -## Data files - -Your game probably has data files. Here's how to access them. - -Filesystem access works like a Unix filesystem; you have a single directory -tree, possibly interpolated from several mounted locations, no drive letters, -'/' for a path separator. You can access them with standard file APIs like -open() or fopen() or SDL_RWops. You can read or write from the filesystem. - -By default, you probably have a "MEMFS" filesystem (all files are stored in -memory, but access to them is immediate and doesn't need to block). There are -other options, like "IDBFS" (files are stored in a local database, so they -don't need to be in RAM all the time and they can persist between runs of the -program, but access is not synchronous). You can mix and match these file -systems, mounting a MEMFS filesystem at one place and idbfs elsewhere, etc, -but that's beyond the scope of this document. Please refer to Emscripten's -[page on the topic](https://emscripten.org/docs/porting/files/file_systems_overview.html) -for more info. - -The _easiest_ (but not the best) way to get at your data files is to embed -them in the app itself. Emscripten's linker has support for automating this. - -```bash -emcc -o index.html loopwave.c --embed-file=../test/sample.wav@/sounds/sample.wav -``` - -This will pack ../test/sample.wav in your app, and make it available at -"/sounds/sample.wav" at runtime. Emscripten makes sure this data is available -before your main() function runs, and since it's in MEMFS, you can just -read it like you do on other platforms. `--embed-file` can also accept a -directory to pack an entire tree, and you can specify the argument multiple -times to pack unrelated things into the final installation. - -Note that this is absolutely the best approach if you have a few small -files to include and shouldn't worry about the issue further. However, if you -have hundreds of megabytes and/or thousands of files, this is not so great, -since the user will download it all every time they load your page, and it -all has to live in memory at runtime. - -[Emscripten's documentation on the matter](https://emscripten.org/docs/porting/files/packaging_files.html) -gives other options and details, and is worth a read. - - -## Debugging - -Debugging web apps is a mixed bag. You should compile and link with -`-gsource-map`, which embeds a ton of source-level debugging information into -the build, and make sure _the app source code is available on the web server_, -which is often a scary proposition for various reasons. - -When you debug from the browser's tools and hit a breakpoint, you can step -through the actual C/C++ source code, though, which can be nice. - -If you try debugging in Firefox and it doesn't work well for no apparent -reason, try Chrome, and vice-versa. These tools are still relatively new, -and improving all the time. - -SDL_Log() (or even plain old printf) will write to the Javascript console, -and honestly I find printf-style debugging to be easier than setting up a build -for proper debugging, so use whatever tools work best for you. + $ cd test/ + $ emcc -O2 --js-opts 0 -g4 testdraw2.c -I../include ../build/.libs/libSDL2.a ../build/libSDL2_test.a -o a.html +Uses GLES2 renderer or software -## Questions? +Some other SDL2 libraries can be easily built (assuming SDL2 is installed somewhere): -Please give us feedback on this document at [the SDL bug tracker](https://github.com/libsdl-org/SDL/issues). -If something is wrong or unclear, we want to know! +SDL_mixer (http://www.libsdl.org/projects/SDL_mixer/): + $ EMCONFIGURE_JS=1 emconfigure ../configure + build as usual... +SDL_gfx (http://cms.ferzkopp.net/index.php/software/13-sdl-gfx): + $ EMCONFIGURE_JS=1 emconfigure ../configure --disable-mmx + build as usual... diff --git a/libs/SDL2/docs/README-gdk.md b/libs/SDL2/docs/README-gdk.md index 7997c065ba4cdfc95d8274a76e8ad9548c2632df..903265f32f720276f19758ae62341dd836ecf01a 100644 --- a/libs/SDL2/docs/README-gdk.md +++ b/libs/SDL2/docs/README-gdk.md @@ -3,7 +3,7 @@ GDK This port allows SDL applications to run via Microsoft's Game Development Kit (GDK). -Windows (GDK) and Xbox One/Xbox Series (GDKX) are both supported and all the required code is included in this public SDL release. However, only licensed Xbox developers have access to the GDKX libraries which will allow you to build the Xbox targets. +Windows (GDK) and Xbox One/Xbox Series (GDKX) are supported. Although most of the Xbox code is included in the public SDL source code, NDA access is required for a small number of source files. If you have access to GDKX, these required Xbox files are posted on the GDK forums [here](https://forums.xboxlive.com/questions/130003/). Requirements @@ -11,7 +11,6 @@ Requirements * Microsoft Visual Studio 2022 (in theory, it should also work in 2017 or 2019, but this has not been tested) * Microsoft GDK June 2022 or newer (public release [here](https://github.com/microsoft/GDK/releases/tag/June_2022)) -* For Xbox, you will need the corresponding GDKX version (licensed developers only) * To publish a package or successfully authenticate a user, you will need to create an app id/configure services in Partner Center. However, for local testing purposes (without authenticating on Xbox Live), the identifiers used by the GDK test programs in the included solution will work. @@ -30,12 +29,6 @@ The Windows GDK port supports the full set of Win32 APIs, renderers, controllers * Global task queue callbacks are dispatched during `SDL_PumpEvents` (which is also called internally if using `SDL_PollEvent`). * You can get the handle of the global task queue through `SDL_GDKGetTaskQueue`, if needed. When done with the queue, be sure to use `XTaskQueueCloseHandle` to decrement the reference count (otherwise it will cause a resource leak). -* Single-player games have some additional features available: - * Call `SDL_GDKGetDefaultUser` to get the default XUserHandle pointer. - * `SDL_GetPrefPath` still works, but only for single-player titles. - - These functions mostly wrap around async APIs, and thus should be treated as synchronous alternatives. Also note that the single-player functions return on any OS errors, so be sure to validate the return values! - * What doesn't work: * Compilation with anything other than through the included Visual C++ solution file @@ -146,20 +139,6 @@ To create the package: 6. Once the package is installed, you can run it from the start menu. 7. As with when running from Visual Studio, if you need to test any Xbox Live functionality you must switch to the correct sandbox. -Xbox GDKX Setup ---------------------- -In general, the same process in the Windows GDK instructions work. There are just a few additional notes: -* For Xbox One consoles, use the Gaming.Xbox.XboxOne.x64 target -* For Xbox Series consoles, use the Gaming.Xbox.Scarlett.x64 target -* The Xbox One target sets the `__XBOXONE__` define and the Xbox Series target sets the `__XBOXSERIES__` define -* You don't need to link against the Xbox.Services Thunks lib nor include that dll in your package (it doesn't exist for Xbox) -* The shader blobs for Xbox are created in a pre-build step for the Xbox targets, rather than included in the source (due to NDA and version compatability reasons) -* To create a package, use: - `makepkg pack /f PackageLayout.xml /lt /d . /pd Package` -* To install the package, use: - `xbapp install [PACKAGE].xvc` -* For some reason, if you make changes that require SDL2.dll to build, and you are running through the debugger (instead of a package), you have to rebuild your .exe target for the debugger to recognize the dll has changed and needs to be transferred to the console again -* While there are successful releases of Xbox titles using this port, it is not as extensively tested as other targets Troubleshooting --------------- diff --git a/libs/SDL2/docs/README-ios.md b/libs/SDL2/docs/README-ios.md index 8fb90de46e207dfa8eff542da9d6c0fd79fbdeda..f5a3a83bfc881ff3485a6b0affef7cc74277159c 100644 --- a/libs/SDL2/docs/README-ios.md +++ b/libs/SDL2/docs/README-ios.md @@ -273,7 +273,7 @@ e.g. { ... initialize game ... - #ifdef __IPHONEOS__ + #if __IPHONEOS__ // Initialize the Game Center for scoring and matchmaking InitGameCenter(); diff --git a/libs/SDL2/i686-w64-mingw32/bin/SDL2.dll b/libs/SDL2/i686-w64-mingw32/bin/SDL2.dll index 3265fb2f3de9e06460e7c6a73a83236b494b89fd..573225caba5abb279c844c438de4d6de2f6a10f1 100755 Binary files a/libs/SDL2/i686-w64-mingw32/bin/SDL2.dll and b/libs/SDL2/i686-w64-mingw32/bin/SDL2.dll differ diff --git a/libs/SDL2/i686-w64-mingw32/bin/sdl2-config b/libs/SDL2/i686-w64-mingw32/bin/sdl2-config index fc399f745b16661bc38552d9e2d9c0d20ffc6cad..aa99b065a5ac2c3562b73473774a39e46236a58b 100755 --- a/libs/SDL2/i686-w64-mingw32/bin/sdl2-config +++ b/libs/SDL2/i686-w64-mingw32/bin/sdl2-config @@ -43,7 +43,7 @@ while test $# -gt 0; do echo $exec_prefix ;; --version) - echo 2.30.0 + echo 2.28.5 ;; --cflags) echo -I${prefix}/include/SDL2 -Dmain=SDL_main diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL.h index 20c903b2fe4f60836b397cb19af7e07ca19f3071..9ba8f68c6e7966906d5832985a0f4ebc400a8878 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_assert.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_assert.h index a396d4e02ed20041a742e22ffb4efaa68995db03..7ce823ec5433f2d168889d7ac9239cd9f6ac6171 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_assert.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_assert.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_atomic.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_atomic.h index 1fa18f49fe078348ec235adca77cbb6374a62e25..1dd816a3826e307f8b7cb436ce95edd28cee7a5c 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_atomic.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_atomic.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -209,7 +209,7 @@ typedef void (*SDL_KernelMemoryBarrierFunc)(); #if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) || defined(__ARM_ARCH_8A__) #define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory") #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory") -#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) +#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_5TE__) #ifdef __thumb__ /* The mcr instruction isn't available in thumb mode, use real functions */ #define SDL_MEMORY_BARRIER_USES_FUNCTION diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_audio.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_audio.h index bd8e7ab6fa6d8336bf78fe732726782105f65dfe..ccd35982df124d75a8007791bce88da405c76a75 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_audio.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_audio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_bits.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_bits.h index 83e8a78c783c473184dd1674279fbdb4caafab8e..81161ae5f30633f2d708e9b7806ba005bdd9c21a 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_bits.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_bits.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_blendmode.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_blendmode.h index 09d01477d8db63ecf6e9de2483472b9d17641567..4ecbe50785e9d37fcd57325a5301df6d25237997 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_blendmode.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_blendmode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -65,8 +65,8 @@ typedef enum typedef enum { SDL_BLENDOPERATION_ADD = 0x1, /**< dst + src: supported by all renderers */ - SDL_BLENDOPERATION_SUBTRACT = 0x2, /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */ - SDL_BLENDOPERATION_REV_SUBTRACT = 0x3, /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */ + SDL_BLENDOPERATION_SUBTRACT = 0x2, /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */ + SDL_BLENDOPERATION_REV_SUBTRACT = 0x3, /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */ SDL_BLENDOPERATION_MINIMUM = 0x4, /**< min(dst, src) : supported by D3D9, D3D11 */ SDL_BLENDOPERATION_MAXIMUM = 0x5 /**< max(dst, src) : supported by D3D9, D3D11 */ } SDL_BlendOperation; diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_clipboard.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_clipboard.h index bd4b044c6dd4ec0f0ed298f4333d3aed79702001..7c351fbb9c98aacbbf9136b3373b04ad321fe456 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_clipboard.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_clipboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_config.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_config.h index dba78086016e4d11489ccdb27cda9972ec0d862d..01322c1829401fecea1b72889dfe4d313c5f0175 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_config.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_config.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_cpuinfo.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_cpuinfo.h index 2a9dd380c2e7b8d4ba5f6e8aec4c13d5becd565d..ed5e97915e314132f76df1747f76a5633dbd2b44 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_cpuinfo.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_cpuinfo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_egl.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_egl.h index a4276e6810b2fe059720cb2fe81e234e599e663c..6f51c0831afb94f82f03f92fdec39c622b0b3858 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_egl.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_egl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_endian.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_endian.h index 591ccac4256adc9f17c7ba0234ff745e1fb71a31..71bc06729b6425ad9a4a96ca12e430409fb50514 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_endian.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_endian.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_error.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_error.h index 2df6463ad92f2183c0ac3c936bf1277bdef02e22..31c22616ccb0f276d3cab3caef4a769c5381b0ae 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_error.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_error.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_events.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_events.h index eccbba2553b4fce528c41741b15d7419597afcf6..9d097031805f33ff18e0a9bf381e22fb0f662dd0 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_events.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_events.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -131,8 +131,6 @@ typedef enum SDL_CONTROLLERTOUCHPADMOTION, /**< Game controller touchpad finger was moved */ SDL_CONTROLLERTOUCHPADUP, /**< Game controller touchpad finger was lifted */ SDL_CONTROLLERSENSORUPDATE, /**< Game controller sensor was updated */ - SDL_CONTROLLERUPDATECOMPLETE_RESERVED_FOR_SDL3, - SDL_CONTROLLERSTEAMHANDLEUPDATED, /**< Game controller Steam handle has changed */ /* Touch events */ SDL_FINGERDOWN = 0x700, @@ -448,7 +446,7 @@ typedef struct SDL_ControllerButtonEvent */ typedef struct SDL_ControllerDeviceEvent { - Uint32 type; /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, ::SDL_CONTROLLERDEVICEREMAPPED, or ::SDL_CONTROLLERSTEAMHANDLEUPDATED */ + Uint32 type; /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, or ::SDL_CONTROLLERDEVICEREMAPPED */ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Sint32 which; /**< The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event */ } SDL_ControllerDeviceEvent; @@ -582,6 +580,15 @@ typedef struct SDL_QuitEvent Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ } SDL_QuitEvent; +/** + * \brief OS Specific event + */ +typedef struct SDL_OSEvent +{ + Uint32 type; /**< ::SDL_QUIT */ + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ +} SDL_OSEvent; + /** * \brief A user-defined event type (event.user.*) */ diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_filesystem.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_filesystem.h index 07498898d3238d6b7c824761c46421e46991c84d..4cad657ec86e7b245a4a3046effd2ed783085932 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_filesystem.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_filesystem.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -64,7 +64,7 @@ extern "C" { * directory of the application as it is uncommon to store resources outside * the executable. As such it is not a writable directory. * - * The returned path is guaranteed to end with a path separator ('\\' on + * The returned path is guaranteed to end with a path separator ('\' on * Windows, '/' on most other platforms). * * The pointer returned is owned by the caller. Please call SDL_free() on the @@ -120,7 +120,7 @@ extern DECLSPEC char *SDLCALL SDL_GetBasePath(void); * - ...only use letters, numbers, and spaces. Avoid punctuation like "Game * Name 2: Bad Guy's Revenge!" ... "Game Name 2" is sufficient. * - * The returned path is guaranteed to end with a path separator ('\\' on + * The returned path is guaranteed to end with a path separator ('\' on * Windows, '/' on most other platforms). * * The pointer returned is owned by the caller. Please call SDL_free() on the diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_gamecontroller.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_gamecontroller.h index 281fa356c63f58cfa5701ff6ae80f1d83c0f6aa8..140054d36ee625c57be7cc976087691b8746f7f4 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_gamecontroller.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_gamecontroller.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -73,8 +73,7 @@ typedef enum SDL_CONTROLLER_TYPE_NVIDIA_SHIELD, SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT, SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT, - SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR, - SDL_CONTROLLER_TYPE_MAX + SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR } SDL_GameControllerType; typedef enum @@ -524,20 +523,6 @@ extern DECLSPEC Uint16 SDLCALL SDL_GameControllerGetFirmwareVersion(SDL_GameCont */ extern DECLSPEC const char * SDLCALL SDL_GameControllerGetSerial(SDL_GameController *gamecontroller); -/** - * Get the Steam Input handle of an opened controller, if available. - * - * Returns an InputHandle_t for the controller that can be used with Steam Input API: - * https://partner.steamgames.com/doc/api/ISteamInput - * - * \param gamecontroller the game controller object to query. - * \returns the gamepad handle, or 0 if unavailable. - * - * \since This function is available since SDL 2.30.0. - */ -extern DECLSPEC Uint64 SDLCALL SDL_GameControllerGetSteamHandle(SDL_GameController *gamecontroller); - - /** * Check if a controller has been opened and is currently connected. * @@ -613,9 +598,7 @@ extern DECLSPEC void SDLCALL SDL_GameControllerUpdate(void); * and are centered within ~8000 of zero, though advanced UI will allow users to set * or autodetect the dead zone, which varies between controllers. * - * Trigger axis values range from 0 (released) to SDL_JOYSTICK_AXIS_MAX - * (fully pressed) when reported by SDL_GameControllerGetAxis(). Note that this is not the - * same range that will be reported by the lower-level SDL_GetJoystickAxis(). + * Trigger axis values range from 0 to SDL_JOYSTICK_AXIS_MAX. */ typedef enum { @@ -704,13 +687,8 @@ SDL_GameControllerHasAxis(SDL_GameController *gamecontroller, SDL_GameController * * The axis indices start at index 0. * - * For thumbsticks, the state is a value ranging from -32768 (up/left) - * to 32767 (down/right). - * - * Triggers range from 0 when released to 32767 when fully pressed, and - * never return a negative value. Note that this differs from the value - * reported by the lower-level SDL_GetJoystickAxis(), which normally uses - * the full range. + * The state is a value ranging from -32768 to 32767. Triggers, however, range + * from 0 to 32767 (they never return a negative value). * * \param gamecontroller a game controller * \param axis an axis index (one of the SDL_GameControllerAxis values) diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_gesture.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_gesture.h index 4fffa5f3e87df75d287da5c6ed0e795ab49d7768..db70b4dd843d983dea8988a60b12f92a739faa0a 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_gesture.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_gesture.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_guid.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_guid.h index 7daa5f1f585c3d7482108e915ea0ea8fa263751b..d964223c62ca79b46bdb6aa69ba9ed4e256d1f9b 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_guid.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_guid.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_haptic.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_haptic.h index c9ed847df02387a5f4d5f5fd02055695cd46a5e6..2462a1e47b3731a20f68af4a2d0d9cdfa5c76e59 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_haptic.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_haptic.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_hidapi.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_hidapi.h index b9d8ffac3881e2a297da348e8afb832b0b4afea9..0575100357798a4b34365b5f37d0ef57d1cf831c 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_hidapi.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_hidapi.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_hints.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_hints.h index e775a6509bc0e4834be32411ddadd1cfd0f2a99b..00beef51e29ed9e610182c7db3d88da70a98230f 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_hints.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_hints.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -631,110 +631,6 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS" -/** - * A variable containing a list of arcade stick style controllers. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES "SDL_JOYSTICK_ARCADESTICK_DEVICES" - -/** - * A variable containing a list of devices that are not arcade stick style controllers. This will override SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES and the built in device list. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES_EXCLUDED "SDL_JOYSTICK_ARCADESTICK_DEVICES_EXCLUDED" - -/** - * A variable containing a list of devices that should not be considerd joysticks. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_BLACKLIST_DEVICES "SDL_JOYSTICK_BLACKLIST_DEVICES" - -/** - * A variable containing a list of devices that should be considered joysticks. This will override SDL_HINT_JOYSTICK_BLACKLIST_DEVICES and the built in device list. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_BLACKLIST_DEVICES_EXCLUDED "SDL_JOYSTICK_BLACKLIST_DEVICES_EXCLUDED" - -/** - * A variable containing a list of flightstick style controllers. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES "SDL_JOYSTICK_FLIGHTSTICK_DEVICES" - -/** - * A variable containing a list of devices that are not flightstick style controllers. This will override SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES and the built in device list. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES_EXCLUDED "SDL_JOYSTICK_FLIGHTSTICK_DEVICES_EXCLUDED" - -/** - * A variable containing a list of devices known to have a GameCube form factor. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_GAMECUBE_DEVICES "SDL_JOYSTICK_GAMECUBE_DEVICES" - -/** - * A variable containing a list of devices known not to have a GameCube form factor. This will override SDL_HINT_JOYSTICK_GAMECUBE_DEVICES and the built in device list. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_GAMECUBE_DEVICES_EXCLUDED "SDL_JOYSTICK_GAMECUBE_DEVICES_EXCLUDED" - /** * \brief A variable controlling whether the HIDAPI joystick drivers should be used. * @@ -943,17 +839,6 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_HIDAPI_STEAM "SDL_JOYSTICK_HIDAPI_STEAM" -/** - * \brief A variable controlling whether the HIDAPI driver for the Steam Deck builtin controller should be used. - * - * This variable can be set to the following values: - * "0" - HIDAPI driver is not used - * "1" - HIDAPI driver is used - * - * The default is the value of SDL_HINT_JOYSTICK_HIDAPI - */ -#define SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK "SDL_JOYSTICK_HIDAPI_STEAMDECK" - /** * \brief A variable controlling whether the HIDAPI driver for Nintendo Switch controllers should be used. * @@ -1080,24 +965,6 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED "SDL_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED" -/** - * A variable controlling whether IOKit should be used for controller handling. - * - * This variable can be set to the following values: - * "0" - IOKit is not used - * "1" - IOKit is used (the default) - */ -#define SDL_HINT_JOYSTICK_IOKIT "SDL_JOYSTICK_IOKIT" - -/** - * A variable controlling whether GCController should be used for controller handling. - * - * This variable can be set to the following values: - * "0" - GCController is not used - * "1" - GCController is used (the default) - */ -#define SDL_HINT_JOYSTICK_MFI "SDL_JOYSTICK_MFI" - /** * \brief A variable controlling whether the RAWINPUT joystick drivers should be used for better handling XInput-capable devices. * @@ -1140,32 +1007,6 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_THREAD "SDL_JOYSTICK_THREAD" -/** - * A variable containing a list of throttle style controllers. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_THROTTLE_DEVICES "SDL_JOYSTICK_THROTTLE_DEVICES" - -/** - * A variable containing a list of devices that are not throttle style controllers. This will override SDL_HINT_JOYSTICK_THROTTLE_DEVICES and the built in device list. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_THROTTLE_DEVICES_EXCLUDED "SDL_JOYSTICK_THROTTLE_DEVICES_EXCLUDED" - /** * \brief A variable controlling whether Windows.Gaming.Input should be used for controller handling. * @@ -1175,45 +1016,6 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_WGI "SDL_JOYSTICK_WGI" -/** - * A variable containing a list of wheel style controllers. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_WHEEL_DEVICES "SDL_JOYSTICK_WHEEL_DEVICES" - -/** - * A variable containing a list of devices that are not wheel style controllers. This will override SDL_HINT_JOYSTICK_WHEEL_DEVICES and the built in device list. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_WHEEL_DEVICES_EXCLUDED "SDL_JOYSTICK_WHEEL_DEVICES_EXCLUDED" - -/** - * A variable containing a list of devices known to have all axes centered at zero. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_ZERO_CENTERED_DEVICES "SDL_JOYSTICK_ZERO_CENTERED_DEVICES" - /** * \brief Determines whether SDL enforces that DRM master is required in order * to initialize the KMSDRM video backend. @@ -1282,22 +1084,6 @@ extern "C" { */ #define SDL_HINT_LINUX_JOYSTICK_DEADZONES "SDL_LINUX_JOYSTICK_DEADZONES" -/** - * \brief A variable controlling the default SDL log levels. - * - * This variable is a comma separated set of category=level tokens that define the default logging levels for SDL applications. - * - * The category can be a numeric category, one of "app", "error", "assert", "system", "audio", "video", "render", "input", "test", or `*` for any unspecified category. - * - * The level can be a numeric level, one of "verbose", "debug", "info", "warn", "error", "critical", or "quiet" to disable that category. - * - * You can omit the category if you want to set the logging level for all categories. - * - * If this hint isn't set, the default log levels are equivalent to: - * "app=info,assert=warn,test=verbose,*=error" - */ -#define SDL_HINT_LOGGING "SDL_LOGGING" - /** * \brief When set don't force the SDL app to become a foreground process * @@ -1699,32 +1485,6 @@ extern "C" { */ #define SDL_HINT_RENDER_METAL_PREFER_LOW_POWER_DEVICE "SDL_RENDER_METAL_PREFER_LOW_POWER_DEVICE" -/** - * A variable containing a list of ROG gamepad capable mice. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_ROG_GAMEPAD_MICE "SDL_ROG_GAMEPAD_MICE" - -/** - * A variable containing a list of devices that are not ROG gamepad capable mice. This will override SDL_HINT_ROG_GAMEPAD_MICE and the built in device list. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_ROG_GAMEPAD_MICE_EXCLUDED "SDL_ROG_GAMEPAD_MICE_EXCLUDED" - /** * \brief A variable controlling if VSYNC is automatically disable if doesn't reach the enough FPS * @@ -2682,22 +2442,6 @@ extern "C" { */ #define SDL_HINT_TRACKPAD_IS_TOUCH_ONLY "SDL_TRACKPAD_IS_TOUCH_ONLY" -/** - * Cause SDL to call dbus_shutdown() on quit. - * - * This is useful as a debug tool to validate memory leaks, but shouldn't ever - * be set in production applications, as other libraries used by the application - * might use dbus under the hood and this cause cause crashes if they continue - * after SDL_Quit(). - * - * This variable can be set to the following values: - * "0" - SDL will not call dbus_shutdown() on quit (default) - * "1" - SDL will call dbus_shutdown() on quit - * - * This hint is available since SDL 2.30.0. - */ -#define SDL_HINT_SHUTDOWN_DBUS_ON_QUIT "SDL_SHUTDOWN_DBUS_ON_QUIT" - /** * \brief An enumeration of hint priorities diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_joystick.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_joystick.h index 561e01099cede911e349969024f9b84bad658c2d..b9b4f622800d7a59285523c1407578ee130c0e32 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_joystick.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_joystick.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_keyboard.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_keyboard.h index 03c7b5a3705af4eb25d296049af1fe23ffd0b7d3..86a37ad1a241688e3ee3e658a824e5a78cba2918 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_keyboard.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_keyboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -298,10 +298,8 @@ extern DECLSPEC void SDLCALL SDL_ClearComposition(void); extern DECLSPEC SDL_bool SDLCALL SDL_IsTextInputShown(void); /** - * Set the rectangle used to type Unicode text inputs. Native input methods - * will place a window with word suggestions near it, without covering the - * text being inputted. - * + * Set the rectangle used to type Unicode text inputs. + * * To start text input in a given location, this function is intended to be * called before SDL_StartTextInput, although some platforms support moving * the rectangle even while text input (and a composition) is active. diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_keycode.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_keycode.h index 57a71bd79694d749d3702af58f3813540fb678d8..7106223027e75886652f3a2efd179d82561e350c 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_keycode.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_keycode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_loadso.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_loadso.h index 4edc22e9e756c9f69fde1aced4679b63dc228e37..ca59b681cb45d9684223aaa6ab7287e809ced5f2 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_loadso.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_loadso.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_locale.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_locale.h index 0b6118f0ef8669930b2ce0aa5d4e9628381ae2df..482dbefe765fce9fe2e4248cc5e57e56e71b39b1 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_locale.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_locale.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_log.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_log.h index bd030c6d2d5f27ece4b3a74bd80d8f9b5708d05b..da733c4023d9c9f8ed62668e22ddb00c9f5c1fd4 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_log.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_log.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -59,7 +59,7 @@ extern "C" { * By default the application category is enabled at the INFO level, * the assert category is enabled at the WARN level, test is enabled * at the VERBOSE level and all other categories are enabled at the - * ERROR level. + * CRITICAL level. */ typedef enum { @@ -352,7 +352,7 @@ extern DECLSPEC void SDLCALL SDL_LogMessage(int category, */ extern DECLSPEC void SDLCALL SDL_LogMessageV(int category, SDL_LogPriority priority, - SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(3); + const char *fmt, va_list ap); /** * The prototype for the log output callback function. diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_main.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_main.h index a66c84b4e5fbc2b45a5deca02e42b08e00ef1c66..5cc8e5913a4e705548739f0718d4878392c8a90e 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_main.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_main.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_messagebox.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_messagebox.h index 5ace6f2ddee1f8172416650c6fbdcd77e0a11ba9..7896fd1291f9211584447abcb4ab3edf320bc389 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_messagebox.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_messagebox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_metal.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_metal.h index 50f7b2aeb45211ce457bf9c6dc268eb86caa6be6..f36e34878cef20b686f7800fe112a5bd99f6a3b3 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_metal.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_metal.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_misc.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_misc.h index 113ba7a15693dea7e8fd65d4000fd0fb5ca75c18..13ed9c771835f15abdd16c53b5cf39d999159c65 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_misc.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_misc.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_mouse.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_mouse.h index 687ff122d2c4fc2ba8616dc9fe30fb9764690100..aa07575738a5640c65e5f5dbc4a55661fe0a093e 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_mouse.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_mouse.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_mutex.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_mutex.h index eaa21f293f51721c44eb07d1623fb291f3fb7ada..e679d380890ea02d7a05021152aa183646fa178c 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_mutex.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_mutex.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_name.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_name.h index 71e9354550f913f1b76dccb0386a19d51dcd164a..5c3e07ab7d3e4a04fa436767527aa3e570a25d25 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_name.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_name.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengl.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengl.h index 2bb38c5c0e994443e99ce7b2ac3888d4beed435a..0ba89127ace681fa97744e94bad4728c59be9b53 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengl.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengles.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengles.h index 7e9a1ab8d4d037d06954b6ddd0df8684fb1a3db4..f4465eaa9da8ba3009fa4f3ee51eeecd0689283b 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengles.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengles.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengles2.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengles2.h index 96971344d1b863777ef6a567d321167ebeff4765..5e3b717def6cafa080adb200245e9528f0bf7cbc 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengles2.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengles2.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_pixels.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_pixels.h index 44757cdcf4b7fdae9c499d8c773c2c5fe28e60d7..9abd57b42014a89b2761608bea2ae802ef9e8515 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_pixels.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_pixels.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -61,10 +61,7 @@ typedef enum SDL_PIXELTYPE_ARRAYU16, SDL_PIXELTYPE_ARRAYU32, SDL_PIXELTYPE_ARRAYF16, - SDL_PIXELTYPE_ARRAYF32, - - /* This must be at the end of the list to avoid breaking the existing ABI */ - SDL_PIXELTYPE_INDEX2 + SDL_PIXELTYPE_ARRAYF32 } SDL_PixelType; /** Bitmap pixel order, high bit -> low bit. */ @@ -137,7 +134,6 @@ typedef enum #define SDL_ISPIXELFORMAT_INDEXED(format) \ (!SDL_ISPIXELFORMAT_FOURCC(format) && \ ((SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX1) || \ - (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX2) || \ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX4) || \ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX8))) @@ -181,12 +177,6 @@ typedef enum SDL_PIXELFORMAT_INDEX1MSB = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX1, SDL_BITMAPORDER_1234, 0, 1, 0), - SDL_PIXELFORMAT_INDEX2LSB = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX2, SDL_BITMAPORDER_4321, 0, - 2, 0), - SDL_PIXELFORMAT_INDEX2MSB = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX2, SDL_BITMAPORDER_1234, 0, - 2, 0), SDL_PIXELFORMAT_INDEX4LSB = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX4, SDL_BITMAPORDER_4321, 0, 4, 0), @@ -286,19 +276,11 @@ typedef enum SDL_PIXELFORMAT_ARGB32 = SDL_PIXELFORMAT_ARGB8888, SDL_PIXELFORMAT_BGRA32 = SDL_PIXELFORMAT_BGRA8888, SDL_PIXELFORMAT_ABGR32 = SDL_PIXELFORMAT_ABGR8888, - SDL_PIXELFORMAT_RGBX32 = SDL_PIXELFORMAT_RGBX8888, - SDL_PIXELFORMAT_XRGB32 = SDL_PIXELFORMAT_XRGB8888, - SDL_PIXELFORMAT_BGRX32 = SDL_PIXELFORMAT_BGRX8888, - SDL_PIXELFORMAT_XBGR32 = SDL_PIXELFORMAT_XBGR8888, #else SDL_PIXELFORMAT_RGBA32 = SDL_PIXELFORMAT_ABGR8888, SDL_PIXELFORMAT_ARGB32 = SDL_PIXELFORMAT_BGRA8888, SDL_PIXELFORMAT_BGRA32 = SDL_PIXELFORMAT_ARGB8888, SDL_PIXELFORMAT_ABGR32 = SDL_PIXELFORMAT_RGBA8888, - SDL_PIXELFORMAT_RGBX32 = SDL_PIXELFORMAT_XBGR8888, - SDL_PIXELFORMAT_XRGB32 = SDL_PIXELFORMAT_BGRX8888, - SDL_PIXELFORMAT_BGRX32 = SDL_PIXELFORMAT_XRGB8888, - SDL_PIXELFORMAT_XBGR32 = SDL_PIXELFORMAT_RGBX8888, #endif SDL_PIXELFORMAT_YV12 = /**< Planar mode: Y + V + U (3 planes) */ diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_platform.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_platform.h index 6e67b4577a3d040835a83fdc5e6332a33cc0bab5..d2a7e052d7b19051d020bb240856fbe6080e1af8 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_platform.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_platform.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -166,12 +166,6 @@ #define WINAPI_FAMILY_WINRT 0 #endif /* HAVE_WINAPIFAMILY_H */ -#if (HAVE_WINAPIFAMILY_H) && defined(WINAPI_FAMILY_PHONE_APP) -#define SDL_WINAPI_FAMILY_PHONE (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) -#else -#define SDL_WINAPI_FAMILY_PHONE 0 -#endif - #if WINAPI_FAMILY_WINRT #undef __WINRT__ #define __WINRT__ 1 diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_power.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_power.h index 0520065cebbb135035665cf95402a2b15b381d1a..1d75704c421c42b244f68b93edda5694f73d5c31 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_power.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_power.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_quit.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_quit.h index 3f69dc9f26011db121417874daa9ccbb1043f708..d8ceb894369194b5a0da17b8b4117ebf2edf0a88 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_quit.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_quit.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_rect.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_rect.h index 5ce1f0b4517fa856ad7ee07e8c14fdf2f33f7c7a..9611a311ce83bc165a1ea968a51d4f968f9557d3 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_rect.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_rect.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_render.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_render.h index b7135bb9dd46e73b4de07762cda78cc6b292bf3e..2d3f07366209ba01531b878102b28599b256725f 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_render.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_render.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -42,7 +42,7 @@ * of the many good 3D engines. * * These functions must be called from the main thread. - * See this bug for details: https://github.com/libsdl-org/SDL/issues/986 + * See this bug for details: http://bugzilla.libsdl.org/show_bug.cgi?id=1995 */ #ifndef SDL_render_h_ diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_revision.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_revision.h index ee42f8421d75d3d1e8a00051725414503c7ff132..4455a08b6289e407412cfb0c59b8d8022ea49d98 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_revision.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_revision.h @@ -1,7 +1,7 @@ /* Generated by updaterev.sh, do not edit */ #ifdef SDL_VENDOR_INFO -#define SDL_REVISION "SDL-release-2.30.0-0-g859844eae (" SDL_VENDOR_INFO ")" +#define SDL_REVISION "SDL-release-2.28.5-0-g15ead9a40 (" SDL_VENDOR_INFO ")" #else -#define SDL_REVISION "SDL-release-2.30.0-0-g859844eae" +#define SDL_REVISION "SDL-release-2.28.5-0-g15ead9a40" #endif #define SDL_REVISION_NUMBER 0 diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_rwops.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_rwops.h index 9dd99f92b1541ba73386aeed906b16d4db415d17..8615cb542959def634d4a634cd24f24d3a5104a6 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_rwops.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_rwops.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_scancode.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_scancode.h index fe13d5b7aaad9378e49005640b0c7641cf0512dc..a960a7991c61accff7874c9c75d92099b350b858 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_scancode.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_scancode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_sensor.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_sensor.h index 8b89ef6a526d45f11d7b3ac64234519df2164b22..9ecce44b17be8469a1572afe95b2ff8a323045bf 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_sensor.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_sensor.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_shape.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_shape.h index 4783cf290e95eec1a2e5b3f3a2ee5b7f94dcbf33..f66babc011339d5729fee081235f8f57815275c2 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_shape.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_shape.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_stdinc.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_stdinc.h index 0035a357cf8e70d0e201413e726b149db96acfd3..182ed86ee371194ec6f45229626fa395472d0f8d 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_stdinc.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_stdinc.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -257,7 +257,7 @@ typedef uint64_t Uint64; #define SDL_PRIs64 PRIs64 #elif defined(__WIN32__) || defined(__GDK__) #define SDL_PRIs64 "I64d" -#elif defined(__LP64__) && !defined(__APPLE__) +#elif defined(__LINUX__) && defined(__LP64__) #define SDL_PRIs64 "ld" #else #define SDL_PRIs64 "lld" @@ -268,7 +268,7 @@ typedef uint64_t Uint64; #define SDL_PRIu64 PRIu64 #elif defined(__WIN32__) || defined(__GDK__) #define SDL_PRIu64 "I64u" -#elif defined(__LP64__) && !defined(__APPLE__) +#elif defined(__LINUX__) && defined(__LP64__) #define SDL_PRIu64 "lu" #else #define SDL_PRIu64 "llu" @@ -279,7 +279,7 @@ typedef uint64_t Uint64; #define SDL_PRIx64 PRIx64 #elif defined(__WIN32__) || defined(__GDK__) #define SDL_PRIx64 "I64x" -#elif defined(__LP64__) && !defined(__APPLE__) +#elif defined(__LINUX__) && defined(__LP64__) #define SDL_PRIx64 "lx" #else #define SDL_PRIx64 "llx" @@ -290,7 +290,7 @@ typedef uint64_t Uint64; #define SDL_PRIX64 PRIX64 #elif defined(__WIN32__) || defined(__GDK__) #define SDL_PRIX64 "I64X" -#elif defined(__LP64__) && !defined(__APPLE__) +#elif defined(__LINUX__) && defined(__LP64__) #define SDL_PRIX64 "lX" #else #define SDL_PRIX64 "llX" @@ -336,9 +336,7 @@ typedef uint64_t Uint64; #define SDL_PRINTF_FORMAT_STRING #define SDL_SCANF_FORMAT_STRING #define SDL_PRINTF_VARARG_FUNC( fmtargnumber ) -#define SDL_PRINTF_VARARG_FUNCV( fmtargnumber ) #define SDL_SCANF_VARARG_FUNC( fmtargnumber ) -#define SDL_SCANF_VARARG_FUNCV( fmtargnumber ) #else #if defined(_MSC_VER) && (_MSC_VER >= 1600) /* VS 2010 and above */ #include <sal.h> @@ -364,14 +362,10 @@ typedef uint64_t Uint64; #endif #if defined(__GNUC__) #define SDL_PRINTF_VARARG_FUNC( fmtargnumber ) __attribute__ (( format( __printf__, fmtargnumber, fmtargnumber+1 ))) -#define SDL_PRINTF_VARARG_FUNCV( fmtargnumber ) __attribute__(( format( __printf__, fmtargnumber, 0 ))) #define SDL_SCANF_VARARG_FUNC( fmtargnumber ) __attribute__ (( format( __scanf__, fmtargnumber, fmtargnumber+1 ))) -#define SDL_SCANF_VARARG_FUNCV( fmtargnumber ) __attribute__(( format( __scanf__, fmtargnumber, 0 ))) #else #define SDL_PRINTF_VARARG_FUNC( fmtargnumber ) -#define SDL_PRINTF_VARARG_FUNCV( fmtargnumber ) #define SDL_SCANF_VARARG_FUNC( fmtargnumber ) -#define SDL_SCANF_VARARG_FUNCV( fmtargnumber ) #endif #endif /* SDL_DISABLE_ANALYZE_MACROS */ @@ -609,11 +603,11 @@ extern DECLSPEC int SDLCALL SDL_strcasecmp(const char *str1, const char *str2); extern DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *str2, size_t len); extern DECLSPEC int SDLCALL SDL_sscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, ...) SDL_SCANF_VARARG_FUNC(2); -extern DECLSPEC int SDLCALL SDL_vsscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, va_list ap) SDL_SCANF_VARARG_FUNCV(2); +extern DECLSPEC int SDLCALL SDL_vsscanf(const char *text, const char *fmt, va_list ap); extern DECLSPEC int SDLCALL SDL_snprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, ... ) SDL_PRINTF_VARARG_FUNC(3); -extern DECLSPEC int SDLCALL SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(3); +extern DECLSPEC int SDLCALL SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, const char *fmt, va_list ap); extern DECLSPEC int SDLCALL SDL_asprintf(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); -extern DECLSPEC int SDLCALL SDL_vasprintf(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(2); +extern DECLSPEC int SDLCALL SDL_vasprintf(char **strp, const char *fmt, va_list ap); #ifndef HAVE_M_PI #ifndef M_PI @@ -694,8 +688,8 @@ extern DECLSPEC size_t SDLCALL SDL_iconv(SDL_iconv_t cd, const char **inbuf, size_t * outbytesleft); /** - * This function converts a buffer or string between encodings in one pass, - * returning a string that must be freed with SDL_free() or NULL on error. + * This function converts a buffer or string between encodings in one pass, returning a + * string that must be freed with SDL_free() or NULL on error. * * \since This function is available since SDL 2.0.0. */ @@ -704,8 +698,8 @@ extern DECLSPEC char *SDLCALL SDL_iconv_string(const char *tocode, const char *inbuf, size_t inbytesleft); #define SDL_iconv_utf8_locale(S) SDL_iconv_string("", "UTF-8", S, SDL_strlen(S)+1) -#define SDL_iconv_utf8_ucs2(S) (Uint16 *)SDL_iconv_string("UCS-2", "UTF-8", S, SDL_strlen(S)+1) -#define SDL_iconv_utf8_ucs4(S) (Uint32 *)SDL_iconv_string("UCS-4", "UTF-8", S, SDL_strlen(S)+1) +#define SDL_iconv_utf8_ucs2(S) (Uint16 *)SDL_iconv_string("UCS-2-INTERNAL", "UTF-8", S, SDL_strlen(S)+1) +#define SDL_iconv_utf8_ucs4(S) (Uint32 *)SDL_iconv_string("UCS-4-INTERNAL", "UTF-8", S, SDL_strlen(S)+1) #define SDL_iconv_wchar_utf8(S) SDL_iconv_string("UTF-8", "WCHAR_T", (char *)S, (SDL_wcslen(S)+1)*sizeof(wchar_t)) /* force builds using Clang's static analysis tools to use literal C runtime diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_surface.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_surface.h index ceeb86bd867e8a657626b20ed45f89cd5637f798..d6ee615c59f0a48bc284fde0b75b0dbb3ee9bee2 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_surface.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_surface.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_system.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_system.h index ddae4f8cc1f9ca980837f403101aca74fd7ddd5d..4b7eaddcc0ed9b2033de7ccf7cc00de8a5f58a9d 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_system.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_system.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -593,8 +593,7 @@ extern DECLSPEC void SDLCALL SDL_OnApplicationDidChangeStatusBarOrientation(void /* Functions used only by GDK */ #if defined(__GDK__) -typedef struct XTaskQueueObject *XTaskQueueHandle; -typedef struct XUser *XUserHandle; +typedef struct XTaskQueueObject * XTaskQueueHandle; /** * Gets a reference to the global async task queue handle for GDK, @@ -611,20 +610,6 @@ typedef struct XUser *XUserHandle; */ extern DECLSPEC int SDLCALL SDL_GDKGetTaskQueue(XTaskQueueHandle * outTaskQueue); -/** - * Gets a reference to the default user handle for GDK. - * - * This is effectively a synchronous version of XUserAddAsync, which always - * prefers the default user and allows a sign-in UI. - * - * \param outUserHandle a pointer to be filled in with the default user - * handle. - * \returns 0 if success, -1 if any error occurs. - * - * \since This function is available since SDL 2.28.0. - */ -extern DECLSPEC int SDLCALL SDL_GDKGetDefaultUser(XUserHandle * outUserHandle); - #endif /* Ends C function definitions when using C++ */ diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_syswm.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_syswm.h index 7b8bd6ef996571bbba2e5f1e139a0c9292c88146..b35734deb334508c6fbfcc0b635417a9d2841052 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_syswm.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_syswm.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test.h index e5acbee4e31782003083624c56f9d40eac5743bc..80daaafbd9b5dc1e4dfa8f48f5fa97e19caab062 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_assert.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_assert.h index 4f983350a3944145e8c42be3453d894bba8a1270..341e490facee39061766d2fa4b85c154870611dd 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_assert.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_assert.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_common.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_common.h index d977e463f117149f7d27cf3ec35fe65a735557a2..6de63cad6f8b08a5f4f28b9b2e5de0dc65da6b71 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_common.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_common.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_compare.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_compare.h index 61a38d09051145431d107793aadffba516e08d92..5fce25ca1856cef2790a13d1895dbdd95cb8a4ad 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_compare.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_compare.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_crc32.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_crc32.h index e3478318dc069a6087e6dffd23b424764bf96f04..bf34782103a218ef811e65a356ab6f900201aa54 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_crc32.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_crc32.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_font.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_font.h index 620c82116b3f3418cde5195a27e7e2247f19c88e..18a82ffc80f16a989cf37da79ed06a3e5279ff37 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_font.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_font.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_fuzzer.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_fuzzer.h index a847ccb01ca25d80ffa7b4e36f9a2a8f12f7fa6f..cfe6a14f2a0288bd57cd00d642b4dd9c609a8c21 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_fuzzer.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_fuzzer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_harness.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_harness.h index bd9e4f8de070ae4ac730e1414b8f4ca951252008..26231dcd6bce9e72d54ddbef532a278762634948 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_harness.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_harness.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_images.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_images.h index b5bcb0a0000c49ff42d35284df2c859c9a577ca9..1211371755fdfd7bed0953fe1322fdcb639637a3 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_images.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_images.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_log.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_log.h index ea9ae5e1ca1d9b5170d336b5f770f9c530fdb893..a27ffc209a95ca3dd105b08dbe8ca4509245fe4c 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_log.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_log.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_md5.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_md5.h index 3764b042569eb63323ef6a589a5f3252147d4476..538c7ae3e09caa78990f738337bfbf2db9a86459 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_md5.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_md5.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_memory.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_memory.h index 9bd143252cefbdff77396b68ea54132b1859f16f..f959177d2336b5cf649d4d12a41cf76bf7a52578 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_memory.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_memory.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_random.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_random.h index 344646aa8b24a589b63482528441afbd296f88f8..0035a8030ad2cc4751a87d5aea3c032cd3c4944f 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_random.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_random.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_thread.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_thread.h index dc7f5363aadce39089dd1399963e541d416028b8..b829bbad5dc08bc47f02c64efc24ac97556ac603 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_thread.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_thread.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_timer.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_timer.h index 8123e432f1e5065b67bf51277110fbd7caf886fd..98f9ad16c647e8ecca4829b0629ae15e767f895e 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_timer.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_timer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_touch.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_touch.h index f6a5db413df92d8b253614ef723f546b581354b9..c12d4a1c8174997225ba25fe087bfb794e094f48 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_touch.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_touch.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_types.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_types.h index e8d33c651371bd2fd29b155f135461f66f6681bb..b5d7192ff2e95a994229a90e668ab003e16e5cab 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_types.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_types.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_version.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_version.h index 02143ff7a114e9cbe2a6113aa9d7726e2532808d..7585eece563127330f3e236174f55615d9f03ddf 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_version.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_version.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -58,8 +58,8 @@ typedef struct SDL_version /* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL */ #define SDL_MAJOR_VERSION 2 -#define SDL_MINOR_VERSION 30 -#define SDL_PATCHLEVEL 0 +#define SDL_MINOR_VERSION 28 +#define SDL_PATCHLEVEL 5 /** * Macro to determine SDL version program was compiled against. diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_video.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_video.h index fa47d30991df03867c400da2fe80bb32d93457a8..c8b2d7a0d871e1f84cf4bf52f3583f8f5aaaf727 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_video.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_video.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -1278,8 +1278,7 @@ extern DECLSPEC int SDLCALL SDL_SetWindowFullscreen(SDL_Window * window, /** * Return whether the window has a surface associated with it. * - * \returns SDL_TRUE if there is a surface associated with the window, or - * SDL_FALSE otherwise. + * \returns SDL_TRUE if there is a surface associated with the window, or SDL_FALSE otherwise. * * \since This function is available since SDL 2.28.0. * @@ -1341,11 +1340,6 @@ extern DECLSPEC int SDLCALL SDL_UpdateWindowSurface(SDL_Window * window); * * This function is equivalent to the SDL 1.2 API SDL_UpdateRects(). * - * Note that this function will update _at least_ the rectangles specified, - * but this is only intended as an optimization; in practice, this might - * update more of the screen (or all of the screen!), depending on what - * method SDL uses to send pixels to the system. - * * \param window the window to update * \param rects an array of SDL_Rect structures representing areas of the * surface to copy, in pixels diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/begin_code.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/begin_code.h index a47a7d2b6413cbb4f5dcd7534123477697ef71a3..4142ffeba928866354f51bedf3d1b1a9b8a4c3d9 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/begin_code.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/begin_code.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -36,8 +36,6 @@ #ifndef SDL_DEPRECATED # if defined(__GNUC__) && (__GNUC__ >= 4) /* technically, this arrived in gcc 3.1, but oh well. */ # define SDL_DEPRECATED __attribute__((deprecated)) -# elif defined(_MSC_VER) -# define SDL_DEPRECATED __declspec(deprecated) # else # define SDL_DEPRECATED # endif diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/close_code.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/close_code.h index 50a0e6f3b4462c5197bd15d7d22e6a8f36204b46..b5ff3e2049b666eeeb923d234b7179722fd8d6c3 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/close_code.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/close_code.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/i686-w64-mingw32/lib/cmake/SDL2/sdl2-config-version.cmake b/libs/SDL2/i686-w64-mingw32/lib/cmake/SDL2/sdl2-config-version.cmake index 82dfeab129e3a872175ac18a1cbc351c980616de..0e63829954166a1b637f058307f6202b00ceabfd 100644 --- a/libs/SDL2/i686-w64-mingw32/lib/cmake/SDL2/sdl2-config-version.cmake +++ b/libs/SDL2/i686-w64-mingw32/lib/cmake/SDL2/sdl2-config-version.cmake @@ -1,6 +1,6 @@ # sdl2 cmake project-config-version input for ./configure scripts -set(PACKAGE_VERSION "2.30.0") +set(PACKAGE_VERSION "2.28.5") if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) set(PACKAGE_VERSION_COMPATIBLE FALSE) diff --git a/libs/SDL2/i686-w64-mingw32/lib/libSDL2.a b/libs/SDL2/i686-w64-mingw32/lib/libSDL2.a index 927fd51a7831c0199014df3cded1936616f9646f..57a097cbf8cbaadbd9f4efc8dfa0713565d033e6 100644 Binary files a/libs/SDL2/i686-w64-mingw32/lib/libSDL2.a and b/libs/SDL2/i686-w64-mingw32/lib/libSDL2.a differ diff --git a/libs/SDL2/i686-w64-mingw32/lib/libSDL2.dll.a b/libs/SDL2/i686-w64-mingw32/lib/libSDL2.dll.a index 65add3aa8ad6b86458e828f962ca7983646f90f6..64f541cd81bb3f2f6fee7c7586c3b7b3642e4623 100755 Binary files a/libs/SDL2/i686-w64-mingw32/lib/libSDL2.dll.a and b/libs/SDL2/i686-w64-mingw32/lib/libSDL2.dll.a differ diff --git a/libs/SDL2/i686-w64-mingw32/lib/libSDL2.la b/libs/SDL2/i686-w64-mingw32/lib/libSDL2.la index 0f885324bd25a2452dc75f22a396e0eec70da66f..9687a5e29ec997fa88c2d51441df70e238d27f34 100644 --- a/libs/SDL2/i686-w64-mingw32/lib/libSDL2.la +++ b/libs/SDL2/i686-w64-mingw32/lib/libSDL2.la @@ -23,9 +23,9 @@ dependency_libs=' -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 - weak_library_names='' # Version information for libSDL2. -current=3000 -age=3000 -revision=0 +current=2800 +age=2800 +revision=5 # Is this an already installed library? installed=yes @@ -38,4 +38,4 @@ dlopen='' dlpreopen='' # Directory that this library needs to be installed in: -libdir='/Users/valve/release/SDL2/SDL2-2.30.0/i686-w64-mingw32/lib' +libdir='/Users/valve/release/SDL2/SDL2-2.28.5/i686-w64-mingw32/lib' diff --git a/libs/SDL2/i686-w64-mingw32/lib/libSDL2_test.a b/libs/SDL2/i686-w64-mingw32/lib/libSDL2_test.a index 4fcf88772ba06e0d0cc02f1e8fd0f905a36f07d5..71c766c1ccf58fd2323ea5a507d1221e8c767a8a 100644 Binary files a/libs/SDL2/i686-w64-mingw32/lib/libSDL2_test.a and b/libs/SDL2/i686-w64-mingw32/lib/libSDL2_test.a differ diff --git a/libs/SDL2/i686-w64-mingw32/lib/libSDL2_test.la b/libs/SDL2/i686-w64-mingw32/lib/libSDL2_test.la index b048909ca631a480743e77826f6d322c692a7e11..2e2e296e9d3c5b0fc557a76f84293487c4e682d2 100644 --- a/libs/SDL2/i686-w64-mingw32/lib/libSDL2_test.la +++ b/libs/SDL2/i686-w64-mingw32/lib/libSDL2_test.la @@ -38,4 +38,4 @@ dlopen='' dlpreopen='' # Directory that this library needs to be installed in: -libdir='/Users/valve/release/SDL2/SDL2-2.30.0/i686-w64-mingw32/lib' +libdir='/Users/valve/release/SDL2/SDL2-2.28.5/i686-w64-mingw32/lib' diff --git a/libs/SDL2/i686-w64-mingw32/lib/libSDL2main.a b/libs/SDL2/i686-w64-mingw32/lib/libSDL2main.a index 79a835a40b0de416b029df168a79f7acf56bff90..9f64593a652ae9047b6f00e42ddb788e161cd889 100644 Binary files a/libs/SDL2/i686-w64-mingw32/lib/libSDL2main.a and b/libs/SDL2/i686-w64-mingw32/lib/libSDL2main.a differ diff --git a/libs/SDL2/i686-w64-mingw32/lib/libSDL2main.la b/libs/SDL2/i686-w64-mingw32/lib/libSDL2main.la index 128a7f5b1428e0b7bad4749a25bfc3f740f87aac..6e12ee786d756ee65beadcbeee116d651646c20d 100644 --- a/libs/SDL2/i686-w64-mingw32/lib/libSDL2main.la +++ b/libs/SDL2/i686-w64-mingw32/lib/libSDL2main.la @@ -38,4 +38,4 @@ dlopen='' dlpreopen='' # Directory that this library needs to be installed in: -libdir='/Users/valve/release/SDL2/SDL2-2.30.0/i686-w64-mingw32/lib' +libdir='/Users/valve/release/SDL2/SDL2-2.28.5/i686-w64-mingw32/lib' diff --git a/libs/SDL2/i686-w64-mingw32/lib/pkgconfig/sdl2.pc b/libs/SDL2/i686-w64-mingw32/lib/pkgconfig/sdl2.pc index e28b4803f2b37135dc3b092041761e6fc95b43f5..d52c268ea653f08574bd8df4292a8dc3c1e1a3e1 100644 --- a/libs/SDL2/i686-w64-mingw32/lib/pkgconfig/sdl2.pc +++ b/libs/SDL2/i686-w64-mingw32/lib/pkgconfig/sdl2.pc @@ -1,13 +1,13 @@ # sdl pkg-config source file -prefix=/usr/local/i686-w64-mingw32 +prefix=/i686-w64-mingw32 exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include Name: sdl2 Description: Simple DirectMedia Layer is a cross-platform multimedia library designed to provide low level access to audio, keyboard, mouse, joystick, 3D hardware via OpenGL, and 2D video framebuffer. -Version: 2.30.0 +Version: 2.28.5 Requires.private: Conflicts: Libs: -L${libdir} -lmingw32 -lSDL2main -lSDL2 -mwindows diff --git a/libs/SDL2/i686-w64-mingw32/share/aclocal/sdl2.m4 b/libs/SDL2/i686-w64-mingw32/share/aclocal/sdl2.m4 index 274753b118aaf3184843800cc2297b9de568891b..75b60f6ea9338d050b32fd19b5214ef9c1024afa 100644 --- a/libs/SDL2/i686-w64-mingw32/share/aclocal/sdl2.m4 +++ b/libs/SDL2/i686-w64-mingw32/share/aclocal/sdl2.m4 @@ -9,9 +9,8 @@ # * also look for SDL2.framework under Mac OS X # * removed HP/UX 9 support. # * updated for newer autoconf. -# * (v3) use $PKG_CONFIG for pkg-config cross-compiling support -# serial 3 +# serial 2 dnl AM_PATH_SDL2([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS @@ -55,7 +54,7 @@ AC_ARG_VAR(SDL2_FRAMEWORK, [Path to SDL2.framework]) if test "x$sdl_pc" = xyes ; then no_sdl="" - SDL2_CONFIG="$PKG_CONFIG sdl2" + SDL2_CONFIG="pkg-config sdl2" else as_save_PATH="$PATH" if test "x$prefix" != xNONE && test "$cross_compiling" != yes; then diff --git a/libs/SDL2/include/SDL.h b/libs/SDL2/include/SDL.h index 20c903b2fe4f60836b397cb19af7e07ca19f3071..9ba8f68c6e7966906d5832985a0f4ebc400a8878 100644 --- a/libs/SDL2/include/SDL.h +++ b/libs/SDL2/include/SDL.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_assert.h b/libs/SDL2/include/SDL_assert.h index a396d4e02ed20041a742e22ffb4efaa68995db03..7ce823ec5433f2d168889d7ac9239cd9f6ac6171 100644 --- a/libs/SDL2/include/SDL_assert.h +++ b/libs/SDL2/include/SDL_assert.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_atomic.h b/libs/SDL2/include/SDL_atomic.h index 1fa18f49fe078348ec235adca77cbb6374a62e25..1dd816a3826e307f8b7cb436ce95edd28cee7a5c 100644 --- a/libs/SDL2/include/SDL_atomic.h +++ b/libs/SDL2/include/SDL_atomic.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -209,7 +209,7 @@ typedef void (*SDL_KernelMemoryBarrierFunc)(); #if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) || defined(__ARM_ARCH_8A__) #define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory") #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory") -#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) +#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_5TE__) #ifdef __thumb__ /* The mcr instruction isn't available in thumb mode, use real functions */ #define SDL_MEMORY_BARRIER_USES_FUNCTION diff --git a/libs/SDL2/include/SDL_audio.h b/libs/SDL2/include/SDL_audio.h index bd8e7ab6fa6d8336bf78fe732726782105f65dfe..ccd35982df124d75a8007791bce88da405c76a75 100644 --- a/libs/SDL2/include/SDL_audio.h +++ b/libs/SDL2/include/SDL_audio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_bits.h b/libs/SDL2/include/SDL_bits.h index 83e8a78c783c473184dd1674279fbdb4caafab8e..81161ae5f30633f2d708e9b7806ba005bdd9c21a 100644 --- a/libs/SDL2/include/SDL_bits.h +++ b/libs/SDL2/include/SDL_bits.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_blendmode.h b/libs/SDL2/include/SDL_blendmode.h index 09d01477d8db63ecf6e9de2483472b9d17641567..4ecbe50785e9d37fcd57325a5301df6d25237997 100644 --- a/libs/SDL2/include/SDL_blendmode.h +++ b/libs/SDL2/include/SDL_blendmode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -65,8 +65,8 @@ typedef enum typedef enum { SDL_BLENDOPERATION_ADD = 0x1, /**< dst + src: supported by all renderers */ - SDL_BLENDOPERATION_SUBTRACT = 0x2, /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */ - SDL_BLENDOPERATION_REV_SUBTRACT = 0x3, /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */ + SDL_BLENDOPERATION_SUBTRACT = 0x2, /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */ + SDL_BLENDOPERATION_REV_SUBTRACT = 0x3, /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */ SDL_BLENDOPERATION_MINIMUM = 0x4, /**< min(dst, src) : supported by D3D9, D3D11 */ SDL_BLENDOPERATION_MAXIMUM = 0x5 /**< max(dst, src) : supported by D3D9, D3D11 */ } SDL_BlendOperation; diff --git a/libs/SDL2/include/SDL_clipboard.h b/libs/SDL2/include/SDL_clipboard.h index bd4b044c6dd4ec0f0ed298f4333d3aed79702001..7c351fbb9c98aacbbf9136b3373b04ad321fe456 100644 --- a/libs/SDL2/include/SDL_clipboard.h +++ b/libs/SDL2/include/SDL_clipboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_config.h b/libs/SDL2/include/SDL_config.h index dba78086016e4d11489ccdb27cda9972ec0d862d..01322c1829401fecea1b72889dfe4d313c5f0175 100644 --- a/libs/SDL2/include/SDL_config.h +++ b/libs/SDL2/include/SDL_config.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_cpuinfo.h b/libs/SDL2/include/SDL_cpuinfo.h index 2a9dd380c2e7b8d4ba5f6e8aec4c13d5becd565d..ed5e97915e314132f76df1747f76a5633dbd2b44 100644 --- a/libs/SDL2/include/SDL_cpuinfo.h +++ b/libs/SDL2/include/SDL_cpuinfo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_egl.h b/libs/SDL2/include/SDL_egl.h index a4276e6810b2fe059720cb2fe81e234e599e663c..6f51c0831afb94f82f03f92fdec39c622b0b3858 100644 --- a/libs/SDL2/include/SDL_egl.h +++ b/libs/SDL2/include/SDL_egl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_endian.h b/libs/SDL2/include/SDL_endian.h index 591ccac4256adc9f17c7ba0234ff745e1fb71a31..71bc06729b6425ad9a4a96ca12e430409fb50514 100644 --- a/libs/SDL2/include/SDL_endian.h +++ b/libs/SDL2/include/SDL_endian.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_error.h b/libs/SDL2/include/SDL_error.h index 2df6463ad92f2183c0ac3c936bf1277bdef02e22..31c22616ccb0f276d3cab3caef4a769c5381b0ae 100644 --- a/libs/SDL2/include/SDL_error.h +++ b/libs/SDL2/include/SDL_error.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_events.h b/libs/SDL2/include/SDL_events.h index eccbba2553b4fce528c41741b15d7419597afcf6..9d097031805f33ff18e0a9bf381e22fb0f662dd0 100644 --- a/libs/SDL2/include/SDL_events.h +++ b/libs/SDL2/include/SDL_events.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -131,8 +131,6 @@ typedef enum SDL_CONTROLLERTOUCHPADMOTION, /**< Game controller touchpad finger was moved */ SDL_CONTROLLERTOUCHPADUP, /**< Game controller touchpad finger was lifted */ SDL_CONTROLLERSENSORUPDATE, /**< Game controller sensor was updated */ - SDL_CONTROLLERUPDATECOMPLETE_RESERVED_FOR_SDL3, - SDL_CONTROLLERSTEAMHANDLEUPDATED, /**< Game controller Steam handle has changed */ /* Touch events */ SDL_FINGERDOWN = 0x700, @@ -448,7 +446,7 @@ typedef struct SDL_ControllerButtonEvent */ typedef struct SDL_ControllerDeviceEvent { - Uint32 type; /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, ::SDL_CONTROLLERDEVICEREMAPPED, or ::SDL_CONTROLLERSTEAMHANDLEUPDATED */ + Uint32 type; /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, or ::SDL_CONTROLLERDEVICEREMAPPED */ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Sint32 which; /**< The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event */ } SDL_ControllerDeviceEvent; @@ -582,6 +580,15 @@ typedef struct SDL_QuitEvent Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ } SDL_QuitEvent; +/** + * \brief OS Specific event + */ +typedef struct SDL_OSEvent +{ + Uint32 type; /**< ::SDL_QUIT */ + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ +} SDL_OSEvent; + /** * \brief A user-defined event type (event.user.*) */ diff --git a/libs/SDL2/include/SDL_filesystem.h b/libs/SDL2/include/SDL_filesystem.h index 07498898d3238d6b7c824761c46421e46991c84d..4cad657ec86e7b245a4a3046effd2ed783085932 100644 --- a/libs/SDL2/include/SDL_filesystem.h +++ b/libs/SDL2/include/SDL_filesystem.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -64,7 +64,7 @@ extern "C" { * directory of the application as it is uncommon to store resources outside * the executable. As such it is not a writable directory. * - * The returned path is guaranteed to end with a path separator ('\\' on + * The returned path is guaranteed to end with a path separator ('\' on * Windows, '/' on most other platforms). * * The pointer returned is owned by the caller. Please call SDL_free() on the @@ -120,7 +120,7 @@ extern DECLSPEC char *SDLCALL SDL_GetBasePath(void); * - ...only use letters, numbers, and spaces. Avoid punctuation like "Game * Name 2: Bad Guy's Revenge!" ... "Game Name 2" is sufficient. * - * The returned path is guaranteed to end with a path separator ('\\' on + * The returned path is guaranteed to end with a path separator ('\' on * Windows, '/' on most other platforms). * * The pointer returned is owned by the caller. Please call SDL_free() on the diff --git a/libs/SDL2/include/SDL_gamecontroller.h b/libs/SDL2/include/SDL_gamecontroller.h index 281fa356c63f58cfa5701ff6ae80f1d83c0f6aa8..140054d36ee625c57be7cc976087691b8746f7f4 100644 --- a/libs/SDL2/include/SDL_gamecontroller.h +++ b/libs/SDL2/include/SDL_gamecontroller.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -73,8 +73,7 @@ typedef enum SDL_CONTROLLER_TYPE_NVIDIA_SHIELD, SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT, SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT, - SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR, - SDL_CONTROLLER_TYPE_MAX + SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR } SDL_GameControllerType; typedef enum @@ -524,20 +523,6 @@ extern DECLSPEC Uint16 SDLCALL SDL_GameControllerGetFirmwareVersion(SDL_GameCont */ extern DECLSPEC const char * SDLCALL SDL_GameControllerGetSerial(SDL_GameController *gamecontroller); -/** - * Get the Steam Input handle of an opened controller, if available. - * - * Returns an InputHandle_t for the controller that can be used with Steam Input API: - * https://partner.steamgames.com/doc/api/ISteamInput - * - * \param gamecontroller the game controller object to query. - * \returns the gamepad handle, or 0 if unavailable. - * - * \since This function is available since SDL 2.30.0. - */ -extern DECLSPEC Uint64 SDLCALL SDL_GameControllerGetSteamHandle(SDL_GameController *gamecontroller); - - /** * Check if a controller has been opened and is currently connected. * @@ -613,9 +598,7 @@ extern DECLSPEC void SDLCALL SDL_GameControllerUpdate(void); * and are centered within ~8000 of zero, though advanced UI will allow users to set * or autodetect the dead zone, which varies between controllers. * - * Trigger axis values range from 0 (released) to SDL_JOYSTICK_AXIS_MAX - * (fully pressed) when reported by SDL_GameControllerGetAxis(). Note that this is not the - * same range that will be reported by the lower-level SDL_GetJoystickAxis(). + * Trigger axis values range from 0 to SDL_JOYSTICK_AXIS_MAX. */ typedef enum { @@ -704,13 +687,8 @@ SDL_GameControllerHasAxis(SDL_GameController *gamecontroller, SDL_GameController * * The axis indices start at index 0. * - * For thumbsticks, the state is a value ranging from -32768 (up/left) - * to 32767 (down/right). - * - * Triggers range from 0 when released to 32767 when fully pressed, and - * never return a negative value. Note that this differs from the value - * reported by the lower-level SDL_GetJoystickAxis(), which normally uses - * the full range. + * The state is a value ranging from -32768 to 32767. Triggers, however, range + * from 0 to 32767 (they never return a negative value). * * \param gamecontroller a game controller * \param axis an axis index (one of the SDL_GameControllerAxis values) diff --git a/libs/SDL2/include/SDL_gesture.h b/libs/SDL2/include/SDL_gesture.h index 4fffa5f3e87df75d287da5c6ed0e795ab49d7768..db70b4dd843d983dea8988a60b12f92a739faa0a 100644 --- a/libs/SDL2/include/SDL_gesture.h +++ b/libs/SDL2/include/SDL_gesture.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_guid.h b/libs/SDL2/include/SDL_guid.h index 7daa5f1f585c3d7482108e915ea0ea8fa263751b..d964223c62ca79b46bdb6aa69ba9ed4e256d1f9b 100644 --- a/libs/SDL2/include/SDL_guid.h +++ b/libs/SDL2/include/SDL_guid.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_haptic.h b/libs/SDL2/include/SDL_haptic.h index c9ed847df02387a5f4d5f5fd02055695cd46a5e6..2462a1e47b3731a20f68af4a2d0d9cdfa5c76e59 100644 --- a/libs/SDL2/include/SDL_haptic.h +++ b/libs/SDL2/include/SDL_haptic.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_hidapi.h b/libs/SDL2/include/SDL_hidapi.h index b9d8ffac3881e2a297da348e8afb832b0b4afea9..0575100357798a4b34365b5f37d0ef57d1cf831c 100644 --- a/libs/SDL2/include/SDL_hidapi.h +++ b/libs/SDL2/include/SDL_hidapi.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_hints.h b/libs/SDL2/include/SDL_hints.h index e775a6509bc0e4834be32411ddadd1cfd0f2a99b..00beef51e29ed9e610182c7db3d88da70a98230f 100644 --- a/libs/SDL2/include/SDL_hints.h +++ b/libs/SDL2/include/SDL_hints.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -631,110 +631,6 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS" -/** - * A variable containing a list of arcade stick style controllers. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES "SDL_JOYSTICK_ARCADESTICK_DEVICES" - -/** - * A variable containing a list of devices that are not arcade stick style controllers. This will override SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES and the built in device list. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES_EXCLUDED "SDL_JOYSTICK_ARCADESTICK_DEVICES_EXCLUDED" - -/** - * A variable containing a list of devices that should not be considerd joysticks. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_BLACKLIST_DEVICES "SDL_JOYSTICK_BLACKLIST_DEVICES" - -/** - * A variable containing a list of devices that should be considered joysticks. This will override SDL_HINT_JOYSTICK_BLACKLIST_DEVICES and the built in device list. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_BLACKLIST_DEVICES_EXCLUDED "SDL_JOYSTICK_BLACKLIST_DEVICES_EXCLUDED" - -/** - * A variable containing a list of flightstick style controllers. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES "SDL_JOYSTICK_FLIGHTSTICK_DEVICES" - -/** - * A variable containing a list of devices that are not flightstick style controllers. This will override SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES and the built in device list. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES_EXCLUDED "SDL_JOYSTICK_FLIGHTSTICK_DEVICES_EXCLUDED" - -/** - * A variable containing a list of devices known to have a GameCube form factor. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_GAMECUBE_DEVICES "SDL_JOYSTICK_GAMECUBE_DEVICES" - -/** - * A variable containing a list of devices known not to have a GameCube form factor. This will override SDL_HINT_JOYSTICK_GAMECUBE_DEVICES and the built in device list. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_GAMECUBE_DEVICES_EXCLUDED "SDL_JOYSTICK_GAMECUBE_DEVICES_EXCLUDED" - /** * \brief A variable controlling whether the HIDAPI joystick drivers should be used. * @@ -943,17 +839,6 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_HIDAPI_STEAM "SDL_JOYSTICK_HIDAPI_STEAM" -/** - * \brief A variable controlling whether the HIDAPI driver for the Steam Deck builtin controller should be used. - * - * This variable can be set to the following values: - * "0" - HIDAPI driver is not used - * "1" - HIDAPI driver is used - * - * The default is the value of SDL_HINT_JOYSTICK_HIDAPI - */ -#define SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK "SDL_JOYSTICK_HIDAPI_STEAMDECK" - /** * \brief A variable controlling whether the HIDAPI driver for Nintendo Switch controllers should be used. * @@ -1080,24 +965,6 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED "SDL_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED" -/** - * A variable controlling whether IOKit should be used for controller handling. - * - * This variable can be set to the following values: - * "0" - IOKit is not used - * "1" - IOKit is used (the default) - */ -#define SDL_HINT_JOYSTICK_IOKIT "SDL_JOYSTICK_IOKIT" - -/** - * A variable controlling whether GCController should be used for controller handling. - * - * This variable can be set to the following values: - * "0" - GCController is not used - * "1" - GCController is used (the default) - */ -#define SDL_HINT_JOYSTICK_MFI "SDL_JOYSTICK_MFI" - /** * \brief A variable controlling whether the RAWINPUT joystick drivers should be used for better handling XInput-capable devices. * @@ -1140,32 +1007,6 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_THREAD "SDL_JOYSTICK_THREAD" -/** - * A variable containing a list of throttle style controllers. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_THROTTLE_DEVICES "SDL_JOYSTICK_THROTTLE_DEVICES" - -/** - * A variable containing a list of devices that are not throttle style controllers. This will override SDL_HINT_JOYSTICK_THROTTLE_DEVICES and the built in device list. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_THROTTLE_DEVICES_EXCLUDED "SDL_JOYSTICK_THROTTLE_DEVICES_EXCLUDED" - /** * \brief A variable controlling whether Windows.Gaming.Input should be used for controller handling. * @@ -1175,45 +1016,6 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_WGI "SDL_JOYSTICK_WGI" -/** - * A variable containing a list of wheel style controllers. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_WHEEL_DEVICES "SDL_JOYSTICK_WHEEL_DEVICES" - -/** - * A variable containing a list of devices that are not wheel style controllers. This will override SDL_HINT_JOYSTICK_WHEEL_DEVICES and the built in device list. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_WHEEL_DEVICES_EXCLUDED "SDL_JOYSTICK_WHEEL_DEVICES_EXCLUDED" - -/** - * A variable containing a list of devices known to have all axes centered at zero. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_ZERO_CENTERED_DEVICES "SDL_JOYSTICK_ZERO_CENTERED_DEVICES" - /** * \brief Determines whether SDL enforces that DRM master is required in order * to initialize the KMSDRM video backend. @@ -1282,22 +1084,6 @@ extern "C" { */ #define SDL_HINT_LINUX_JOYSTICK_DEADZONES "SDL_LINUX_JOYSTICK_DEADZONES" -/** - * \brief A variable controlling the default SDL log levels. - * - * This variable is a comma separated set of category=level tokens that define the default logging levels for SDL applications. - * - * The category can be a numeric category, one of "app", "error", "assert", "system", "audio", "video", "render", "input", "test", or `*` for any unspecified category. - * - * The level can be a numeric level, one of "verbose", "debug", "info", "warn", "error", "critical", or "quiet" to disable that category. - * - * You can omit the category if you want to set the logging level for all categories. - * - * If this hint isn't set, the default log levels are equivalent to: - * "app=info,assert=warn,test=verbose,*=error" - */ -#define SDL_HINT_LOGGING "SDL_LOGGING" - /** * \brief When set don't force the SDL app to become a foreground process * @@ -1699,32 +1485,6 @@ extern "C" { */ #define SDL_HINT_RENDER_METAL_PREFER_LOW_POWER_DEVICE "SDL_RENDER_METAL_PREFER_LOW_POWER_DEVICE" -/** - * A variable containing a list of ROG gamepad capable mice. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_ROG_GAMEPAD_MICE "SDL_ROG_GAMEPAD_MICE" - -/** - * A variable containing a list of devices that are not ROG gamepad capable mice. This will override SDL_HINT_ROG_GAMEPAD_MICE and the built in device list. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_ROG_GAMEPAD_MICE_EXCLUDED "SDL_ROG_GAMEPAD_MICE_EXCLUDED" - /** * \brief A variable controlling if VSYNC is automatically disable if doesn't reach the enough FPS * @@ -2682,22 +2442,6 @@ extern "C" { */ #define SDL_HINT_TRACKPAD_IS_TOUCH_ONLY "SDL_TRACKPAD_IS_TOUCH_ONLY" -/** - * Cause SDL to call dbus_shutdown() on quit. - * - * This is useful as a debug tool to validate memory leaks, but shouldn't ever - * be set in production applications, as other libraries used by the application - * might use dbus under the hood and this cause cause crashes if they continue - * after SDL_Quit(). - * - * This variable can be set to the following values: - * "0" - SDL will not call dbus_shutdown() on quit (default) - * "1" - SDL will call dbus_shutdown() on quit - * - * This hint is available since SDL 2.30.0. - */ -#define SDL_HINT_SHUTDOWN_DBUS_ON_QUIT "SDL_SHUTDOWN_DBUS_ON_QUIT" - /** * \brief An enumeration of hint priorities diff --git a/libs/SDL2/include/SDL_joystick.h b/libs/SDL2/include/SDL_joystick.h index 561e01099cede911e349969024f9b84bad658c2d..b9b4f622800d7a59285523c1407578ee130c0e32 100644 --- a/libs/SDL2/include/SDL_joystick.h +++ b/libs/SDL2/include/SDL_joystick.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_keyboard.h b/libs/SDL2/include/SDL_keyboard.h index 03c7b5a3705af4eb25d296049af1fe23ffd0b7d3..86a37ad1a241688e3ee3e658a824e5a78cba2918 100644 --- a/libs/SDL2/include/SDL_keyboard.h +++ b/libs/SDL2/include/SDL_keyboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -298,10 +298,8 @@ extern DECLSPEC void SDLCALL SDL_ClearComposition(void); extern DECLSPEC SDL_bool SDLCALL SDL_IsTextInputShown(void); /** - * Set the rectangle used to type Unicode text inputs. Native input methods - * will place a window with word suggestions near it, without covering the - * text being inputted. - * + * Set the rectangle used to type Unicode text inputs. + * * To start text input in a given location, this function is intended to be * called before SDL_StartTextInput, although some platforms support moving * the rectangle even while text input (and a composition) is active. diff --git a/libs/SDL2/include/SDL_keycode.h b/libs/SDL2/include/SDL_keycode.h index 57a71bd79694d749d3702af58f3813540fb678d8..7106223027e75886652f3a2efd179d82561e350c 100644 --- a/libs/SDL2/include/SDL_keycode.h +++ b/libs/SDL2/include/SDL_keycode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_loadso.h b/libs/SDL2/include/SDL_loadso.h index 4edc22e9e756c9f69fde1aced4679b63dc228e37..ca59b681cb45d9684223aaa6ab7287e809ced5f2 100644 --- a/libs/SDL2/include/SDL_loadso.h +++ b/libs/SDL2/include/SDL_loadso.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_locale.h b/libs/SDL2/include/SDL_locale.h index 0b6118f0ef8669930b2ce0aa5d4e9628381ae2df..482dbefe765fce9fe2e4248cc5e57e56e71b39b1 100644 --- a/libs/SDL2/include/SDL_locale.h +++ b/libs/SDL2/include/SDL_locale.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_log.h b/libs/SDL2/include/SDL_log.h index bd030c6d2d5f27ece4b3a74bd80d8f9b5708d05b..da733c4023d9c9f8ed62668e22ddb00c9f5c1fd4 100644 --- a/libs/SDL2/include/SDL_log.h +++ b/libs/SDL2/include/SDL_log.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -59,7 +59,7 @@ extern "C" { * By default the application category is enabled at the INFO level, * the assert category is enabled at the WARN level, test is enabled * at the VERBOSE level and all other categories are enabled at the - * ERROR level. + * CRITICAL level. */ typedef enum { @@ -352,7 +352,7 @@ extern DECLSPEC void SDLCALL SDL_LogMessage(int category, */ extern DECLSPEC void SDLCALL SDL_LogMessageV(int category, SDL_LogPriority priority, - SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(3); + const char *fmt, va_list ap); /** * The prototype for the log output callback function. diff --git a/libs/SDL2/include/SDL_main.h b/libs/SDL2/include/SDL_main.h index a66c84b4e5fbc2b45a5deca02e42b08e00ef1c66..5cc8e5913a4e705548739f0718d4878392c8a90e 100644 --- a/libs/SDL2/include/SDL_main.h +++ b/libs/SDL2/include/SDL_main.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_messagebox.h b/libs/SDL2/include/SDL_messagebox.h index 5ace6f2ddee1f8172416650c6fbdcd77e0a11ba9..7896fd1291f9211584447abcb4ab3edf320bc389 100644 --- a/libs/SDL2/include/SDL_messagebox.h +++ b/libs/SDL2/include/SDL_messagebox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_metal.h b/libs/SDL2/include/SDL_metal.h index 50f7b2aeb45211ce457bf9c6dc268eb86caa6be6..f36e34878cef20b686f7800fe112a5bd99f6a3b3 100644 --- a/libs/SDL2/include/SDL_metal.h +++ b/libs/SDL2/include/SDL_metal.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_misc.h b/libs/SDL2/include/SDL_misc.h index 113ba7a15693dea7e8fd65d4000fd0fb5ca75c18..13ed9c771835f15abdd16c53b5cf39d999159c65 100644 --- a/libs/SDL2/include/SDL_misc.h +++ b/libs/SDL2/include/SDL_misc.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_mouse.h b/libs/SDL2/include/SDL_mouse.h index 687ff122d2c4fc2ba8616dc9fe30fb9764690100..aa07575738a5640c65e5f5dbc4a55661fe0a093e 100644 --- a/libs/SDL2/include/SDL_mouse.h +++ b/libs/SDL2/include/SDL_mouse.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_mutex.h b/libs/SDL2/include/SDL_mutex.h index eaa21f293f51721c44eb07d1623fb291f3fb7ada..e679d380890ea02d7a05021152aa183646fa178c 100644 --- a/libs/SDL2/include/SDL_mutex.h +++ b/libs/SDL2/include/SDL_mutex.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_name.h b/libs/SDL2/include/SDL_name.h index 71e9354550f913f1b76dccb0386a19d51dcd164a..5c3e07ab7d3e4a04fa436767527aa3e570a25d25 100644 --- a/libs/SDL2/include/SDL_name.h +++ b/libs/SDL2/include/SDL_name.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_opengl.h b/libs/SDL2/include/SDL_opengl.h index 2bb38c5c0e994443e99ce7b2ac3888d4beed435a..0ba89127ace681fa97744e94bad4728c59be9b53 100644 --- a/libs/SDL2/include/SDL_opengl.h +++ b/libs/SDL2/include/SDL_opengl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_opengles.h b/libs/SDL2/include/SDL_opengles.h index 7e9a1ab8d4d037d06954b6ddd0df8684fb1a3db4..f4465eaa9da8ba3009fa4f3ee51eeecd0689283b 100644 --- a/libs/SDL2/include/SDL_opengles.h +++ b/libs/SDL2/include/SDL_opengles.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_opengles2.h b/libs/SDL2/include/SDL_opengles2.h index 96971344d1b863777ef6a567d321167ebeff4765..5e3b717def6cafa080adb200245e9528f0bf7cbc 100644 --- a/libs/SDL2/include/SDL_opengles2.h +++ b/libs/SDL2/include/SDL_opengles2.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_pixels.h b/libs/SDL2/include/SDL_pixels.h index 44757cdcf4b7fdae9c499d8c773c2c5fe28e60d7..9abd57b42014a89b2761608bea2ae802ef9e8515 100644 --- a/libs/SDL2/include/SDL_pixels.h +++ b/libs/SDL2/include/SDL_pixels.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -61,10 +61,7 @@ typedef enum SDL_PIXELTYPE_ARRAYU16, SDL_PIXELTYPE_ARRAYU32, SDL_PIXELTYPE_ARRAYF16, - SDL_PIXELTYPE_ARRAYF32, - - /* This must be at the end of the list to avoid breaking the existing ABI */ - SDL_PIXELTYPE_INDEX2 + SDL_PIXELTYPE_ARRAYF32 } SDL_PixelType; /** Bitmap pixel order, high bit -> low bit. */ @@ -137,7 +134,6 @@ typedef enum #define SDL_ISPIXELFORMAT_INDEXED(format) \ (!SDL_ISPIXELFORMAT_FOURCC(format) && \ ((SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX1) || \ - (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX2) || \ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX4) || \ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX8))) @@ -181,12 +177,6 @@ typedef enum SDL_PIXELFORMAT_INDEX1MSB = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX1, SDL_BITMAPORDER_1234, 0, 1, 0), - SDL_PIXELFORMAT_INDEX2LSB = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX2, SDL_BITMAPORDER_4321, 0, - 2, 0), - SDL_PIXELFORMAT_INDEX2MSB = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX2, SDL_BITMAPORDER_1234, 0, - 2, 0), SDL_PIXELFORMAT_INDEX4LSB = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX4, SDL_BITMAPORDER_4321, 0, 4, 0), @@ -286,19 +276,11 @@ typedef enum SDL_PIXELFORMAT_ARGB32 = SDL_PIXELFORMAT_ARGB8888, SDL_PIXELFORMAT_BGRA32 = SDL_PIXELFORMAT_BGRA8888, SDL_PIXELFORMAT_ABGR32 = SDL_PIXELFORMAT_ABGR8888, - SDL_PIXELFORMAT_RGBX32 = SDL_PIXELFORMAT_RGBX8888, - SDL_PIXELFORMAT_XRGB32 = SDL_PIXELFORMAT_XRGB8888, - SDL_PIXELFORMAT_BGRX32 = SDL_PIXELFORMAT_BGRX8888, - SDL_PIXELFORMAT_XBGR32 = SDL_PIXELFORMAT_XBGR8888, #else SDL_PIXELFORMAT_RGBA32 = SDL_PIXELFORMAT_ABGR8888, SDL_PIXELFORMAT_ARGB32 = SDL_PIXELFORMAT_BGRA8888, SDL_PIXELFORMAT_BGRA32 = SDL_PIXELFORMAT_ARGB8888, SDL_PIXELFORMAT_ABGR32 = SDL_PIXELFORMAT_RGBA8888, - SDL_PIXELFORMAT_RGBX32 = SDL_PIXELFORMAT_XBGR8888, - SDL_PIXELFORMAT_XRGB32 = SDL_PIXELFORMAT_BGRX8888, - SDL_PIXELFORMAT_BGRX32 = SDL_PIXELFORMAT_XRGB8888, - SDL_PIXELFORMAT_XBGR32 = SDL_PIXELFORMAT_RGBX8888, #endif SDL_PIXELFORMAT_YV12 = /**< Planar mode: Y + V + U (3 planes) */ diff --git a/libs/SDL2/include/SDL_platform.h b/libs/SDL2/include/SDL_platform.h index 6e67b4577a3d040835a83fdc5e6332a33cc0bab5..d2a7e052d7b19051d020bb240856fbe6080e1af8 100644 --- a/libs/SDL2/include/SDL_platform.h +++ b/libs/SDL2/include/SDL_platform.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -166,12 +166,6 @@ #define WINAPI_FAMILY_WINRT 0 #endif /* HAVE_WINAPIFAMILY_H */ -#if (HAVE_WINAPIFAMILY_H) && defined(WINAPI_FAMILY_PHONE_APP) -#define SDL_WINAPI_FAMILY_PHONE (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) -#else -#define SDL_WINAPI_FAMILY_PHONE 0 -#endif - #if WINAPI_FAMILY_WINRT #undef __WINRT__ #define __WINRT__ 1 diff --git a/libs/SDL2/include/SDL_power.h b/libs/SDL2/include/SDL_power.h index 0520065cebbb135035665cf95402a2b15b381d1a..1d75704c421c42b244f68b93edda5694f73d5c31 100644 --- a/libs/SDL2/include/SDL_power.h +++ b/libs/SDL2/include/SDL_power.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_quit.h b/libs/SDL2/include/SDL_quit.h index 3f69dc9f26011db121417874daa9ccbb1043f708..d8ceb894369194b5a0da17b8b4117ebf2edf0a88 100644 --- a/libs/SDL2/include/SDL_quit.h +++ b/libs/SDL2/include/SDL_quit.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_rect.h b/libs/SDL2/include/SDL_rect.h index 5ce1f0b4517fa856ad7ee07e8c14fdf2f33f7c7a..9611a311ce83bc165a1ea968a51d4f968f9557d3 100644 --- a/libs/SDL2/include/SDL_rect.h +++ b/libs/SDL2/include/SDL_rect.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_render.h b/libs/SDL2/include/SDL_render.h index b7135bb9dd46e73b4de07762cda78cc6b292bf3e..2d3f07366209ba01531b878102b28599b256725f 100644 --- a/libs/SDL2/include/SDL_render.h +++ b/libs/SDL2/include/SDL_render.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -42,7 +42,7 @@ * of the many good 3D engines. * * These functions must be called from the main thread. - * See this bug for details: https://github.com/libsdl-org/SDL/issues/986 + * See this bug for details: http://bugzilla.libsdl.org/show_bug.cgi?id=1995 */ #ifndef SDL_render_h_ diff --git a/libs/SDL2/include/SDL_revision.h b/libs/SDL2/include/SDL_revision.h index ee42f8421d75d3d1e8a00051725414503c7ff132..4455a08b6289e407412cfb0c59b8d8022ea49d98 100644 --- a/libs/SDL2/include/SDL_revision.h +++ b/libs/SDL2/include/SDL_revision.h @@ -1,7 +1,7 @@ /* Generated by updaterev.sh, do not edit */ #ifdef SDL_VENDOR_INFO -#define SDL_REVISION "SDL-release-2.30.0-0-g859844eae (" SDL_VENDOR_INFO ")" +#define SDL_REVISION "SDL-release-2.28.5-0-g15ead9a40 (" SDL_VENDOR_INFO ")" #else -#define SDL_REVISION "SDL-release-2.30.0-0-g859844eae" +#define SDL_REVISION "SDL-release-2.28.5-0-g15ead9a40" #endif #define SDL_REVISION_NUMBER 0 diff --git a/libs/SDL2/include/SDL_rwops.h b/libs/SDL2/include/SDL_rwops.h index 9dd99f92b1541ba73386aeed906b16d4db415d17..8615cb542959def634d4a634cd24f24d3a5104a6 100644 --- a/libs/SDL2/include/SDL_rwops.h +++ b/libs/SDL2/include/SDL_rwops.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_scancode.h b/libs/SDL2/include/SDL_scancode.h index fe13d5b7aaad9378e49005640b0c7641cf0512dc..a960a7991c61accff7874c9c75d92099b350b858 100644 --- a/libs/SDL2/include/SDL_scancode.h +++ b/libs/SDL2/include/SDL_scancode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_sensor.h b/libs/SDL2/include/SDL_sensor.h index 8b89ef6a526d45f11d7b3ac64234519df2164b22..9ecce44b17be8469a1572afe95b2ff8a323045bf 100644 --- a/libs/SDL2/include/SDL_sensor.h +++ b/libs/SDL2/include/SDL_sensor.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_shape.h b/libs/SDL2/include/SDL_shape.h index 4783cf290e95eec1a2e5b3f3a2ee5b7f94dcbf33..f66babc011339d5729fee081235f8f57815275c2 100644 --- a/libs/SDL2/include/SDL_shape.h +++ b/libs/SDL2/include/SDL_shape.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_stdinc.h b/libs/SDL2/include/SDL_stdinc.h index 0035a357cf8e70d0e201413e726b149db96acfd3..182ed86ee371194ec6f45229626fa395472d0f8d 100644 --- a/libs/SDL2/include/SDL_stdinc.h +++ b/libs/SDL2/include/SDL_stdinc.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -257,7 +257,7 @@ typedef uint64_t Uint64; #define SDL_PRIs64 PRIs64 #elif defined(__WIN32__) || defined(__GDK__) #define SDL_PRIs64 "I64d" -#elif defined(__LP64__) && !defined(__APPLE__) +#elif defined(__LINUX__) && defined(__LP64__) #define SDL_PRIs64 "ld" #else #define SDL_PRIs64 "lld" @@ -268,7 +268,7 @@ typedef uint64_t Uint64; #define SDL_PRIu64 PRIu64 #elif defined(__WIN32__) || defined(__GDK__) #define SDL_PRIu64 "I64u" -#elif defined(__LP64__) && !defined(__APPLE__) +#elif defined(__LINUX__) && defined(__LP64__) #define SDL_PRIu64 "lu" #else #define SDL_PRIu64 "llu" @@ -279,7 +279,7 @@ typedef uint64_t Uint64; #define SDL_PRIx64 PRIx64 #elif defined(__WIN32__) || defined(__GDK__) #define SDL_PRIx64 "I64x" -#elif defined(__LP64__) && !defined(__APPLE__) +#elif defined(__LINUX__) && defined(__LP64__) #define SDL_PRIx64 "lx" #else #define SDL_PRIx64 "llx" @@ -290,7 +290,7 @@ typedef uint64_t Uint64; #define SDL_PRIX64 PRIX64 #elif defined(__WIN32__) || defined(__GDK__) #define SDL_PRIX64 "I64X" -#elif defined(__LP64__) && !defined(__APPLE__) +#elif defined(__LINUX__) && defined(__LP64__) #define SDL_PRIX64 "lX" #else #define SDL_PRIX64 "llX" @@ -336,9 +336,7 @@ typedef uint64_t Uint64; #define SDL_PRINTF_FORMAT_STRING #define SDL_SCANF_FORMAT_STRING #define SDL_PRINTF_VARARG_FUNC( fmtargnumber ) -#define SDL_PRINTF_VARARG_FUNCV( fmtargnumber ) #define SDL_SCANF_VARARG_FUNC( fmtargnumber ) -#define SDL_SCANF_VARARG_FUNCV( fmtargnumber ) #else #if defined(_MSC_VER) && (_MSC_VER >= 1600) /* VS 2010 and above */ #include <sal.h> @@ -364,14 +362,10 @@ typedef uint64_t Uint64; #endif #if defined(__GNUC__) #define SDL_PRINTF_VARARG_FUNC( fmtargnumber ) __attribute__ (( format( __printf__, fmtargnumber, fmtargnumber+1 ))) -#define SDL_PRINTF_VARARG_FUNCV( fmtargnumber ) __attribute__(( format( __printf__, fmtargnumber, 0 ))) #define SDL_SCANF_VARARG_FUNC( fmtargnumber ) __attribute__ (( format( __scanf__, fmtargnumber, fmtargnumber+1 ))) -#define SDL_SCANF_VARARG_FUNCV( fmtargnumber ) __attribute__(( format( __scanf__, fmtargnumber, 0 ))) #else #define SDL_PRINTF_VARARG_FUNC( fmtargnumber ) -#define SDL_PRINTF_VARARG_FUNCV( fmtargnumber ) #define SDL_SCANF_VARARG_FUNC( fmtargnumber ) -#define SDL_SCANF_VARARG_FUNCV( fmtargnumber ) #endif #endif /* SDL_DISABLE_ANALYZE_MACROS */ @@ -609,11 +603,11 @@ extern DECLSPEC int SDLCALL SDL_strcasecmp(const char *str1, const char *str2); extern DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *str2, size_t len); extern DECLSPEC int SDLCALL SDL_sscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, ...) SDL_SCANF_VARARG_FUNC(2); -extern DECLSPEC int SDLCALL SDL_vsscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, va_list ap) SDL_SCANF_VARARG_FUNCV(2); +extern DECLSPEC int SDLCALL SDL_vsscanf(const char *text, const char *fmt, va_list ap); extern DECLSPEC int SDLCALL SDL_snprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, ... ) SDL_PRINTF_VARARG_FUNC(3); -extern DECLSPEC int SDLCALL SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(3); +extern DECLSPEC int SDLCALL SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, const char *fmt, va_list ap); extern DECLSPEC int SDLCALL SDL_asprintf(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); -extern DECLSPEC int SDLCALL SDL_vasprintf(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(2); +extern DECLSPEC int SDLCALL SDL_vasprintf(char **strp, const char *fmt, va_list ap); #ifndef HAVE_M_PI #ifndef M_PI @@ -694,8 +688,8 @@ extern DECLSPEC size_t SDLCALL SDL_iconv(SDL_iconv_t cd, const char **inbuf, size_t * outbytesleft); /** - * This function converts a buffer or string between encodings in one pass, - * returning a string that must be freed with SDL_free() or NULL on error. + * This function converts a buffer or string between encodings in one pass, returning a + * string that must be freed with SDL_free() or NULL on error. * * \since This function is available since SDL 2.0.0. */ @@ -704,8 +698,8 @@ extern DECLSPEC char *SDLCALL SDL_iconv_string(const char *tocode, const char *inbuf, size_t inbytesleft); #define SDL_iconv_utf8_locale(S) SDL_iconv_string("", "UTF-8", S, SDL_strlen(S)+1) -#define SDL_iconv_utf8_ucs2(S) (Uint16 *)SDL_iconv_string("UCS-2", "UTF-8", S, SDL_strlen(S)+1) -#define SDL_iconv_utf8_ucs4(S) (Uint32 *)SDL_iconv_string("UCS-4", "UTF-8", S, SDL_strlen(S)+1) +#define SDL_iconv_utf8_ucs2(S) (Uint16 *)SDL_iconv_string("UCS-2-INTERNAL", "UTF-8", S, SDL_strlen(S)+1) +#define SDL_iconv_utf8_ucs4(S) (Uint32 *)SDL_iconv_string("UCS-4-INTERNAL", "UTF-8", S, SDL_strlen(S)+1) #define SDL_iconv_wchar_utf8(S) SDL_iconv_string("UTF-8", "WCHAR_T", (char *)S, (SDL_wcslen(S)+1)*sizeof(wchar_t)) /* force builds using Clang's static analysis tools to use literal C runtime diff --git a/libs/SDL2/include/SDL_surface.h b/libs/SDL2/include/SDL_surface.h index ceeb86bd867e8a657626b20ed45f89cd5637f798..d6ee615c59f0a48bc284fde0b75b0dbb3ee9bee2 100644 --- a/libs/SDL2/include/SDL_surface.h +++ b/libs/SDL2/include/SDL_surface.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_system.h b/libs/SDL2/include/SDL_system.h index ddae4f8cc1f9ca980837f403101aca74fd7ddd5d..4b7eaddcc0ed9b2033de7ccf7cc00de8a5f58a9d 100644 --- a/libs/SDL2/include/SDL_system.h +++ b/libs/SDL2/include/SDL_system.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -593,8 +593,7 @@ extern DECLSPEC void SDLCALL SDL_OnApplicationDidChangeStatusBarOrientation(void /* Functions used only by GDK */ #if defined(__GDK__) -typedef struct XTaskQueueObject *XTaskQueueHandle; -typedef struct XUser *XUserHandle; +typedef struct XTaskQueueObject * XTaskQueueHandle; /** * Gets a reference to the global async task queue handle for GDK, @@ -611,20 +610,6 @@ typedef struct XUser *XUserHandle; */ extern DECLSPEC int SDLCALL SDL_GDKGetTaskQueue(XTaskQueueHandle * outTaskQueue); -/** - * Gets a reference to the default user handle for GDK. - * - * This is effectively a synchronous version of XUserAddAsync, which always - * prefers the default user and allows a sign-in UI. - * - * \param outUserHandle a pointer to be filled in with the default user - * handle. - * \returns 0 if success, -1 if any error occurs. - * - * \since This function is available since SDL 2.28.0. - */ -extern DECLSPEC int SDLCALL SDL_GDKGetDefaultUser(XUserHandle * outUserHandle); - #endif /* Ends C function definitions when using C++ */ diff --git a/libs/SDL2/include/SDL_syswm.h b/libs/SDL2/include/SDL_syswm.h index 7b8bd6ef996571bbba2e5f1e139a0c9292c88146..b35734deb334508c6fbfcc0b635417a9d2841052 100644 --- a/libs/SDL2/include/SDL_syswm.h +++ b/libs/SDL2/include/SDL_syswm.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_test.h b/libs/SDL2/include/SDL_test.h index e5acbee4e31782003083624c56f9d40eac5743bc..80daaafbd9b5dc1e4dfa8f48f5fa97e19caab062 100644 --- a/libs/SDL2/include/SDL_test.h +++ b/libs/SDL2/include/SDL_test.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_test_assert.h b/libs/SDL2/include/SDL_test_assert.h index 4f983350a3944145e8c42be3453d894bba8a1270..341e490facee39061766d2fa4b85c154870611dd 100644 --- a/libs/SDL2/include/SDL_test_assert.h +++ b/libs/SDL2/include/SDL_test_assert.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_test_common.h b/libs/SDL2/include/SDL_test_common.h index d977e463f117149f7d27cf3ec35fe65a735557a2..6de63cad6f8b08a5f4f28b9b2e5de0dc65da6b71 100644 --- a/libs/SDL2/include/SDL_test_common.h +++ b/libs/SDL2/include/SDL_test_common.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_test_compare.h b/libs/SDL2/include/SDL_test_compare.h index 61a38d09051145431d107793aadffba516e08d92..5fce25ca1856cef2790a13d1895dbdd95cb8a4ad 100644 --- a/libs/SDL2/include/SDL_test_compare.h +++ b/libs/SDL2/include/SDL_test_compare.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_test_crc32.h b/libs/SDL2/include/SDL_test_crc32.h index e3478318dc069a6087e6dffd23b424764bf96f04..bf34782103a218ef811e65a356ab6f900201aa54 100644 --- a/libs/SDL2/include/SDL_test_crc32.h +++ b/libs/SDL2/include/SDL_test_crc32.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_test_font.h b/libs/SDL2/include/SDL_test_font.h index 620c82116b3f3418cde5195a27e7e2247f19c88e..18a82ffc80f16a989cf37da79ed06a3e5279ff37 100644 --- a/libs/SDL2/include/SDL_test_font.h +++ b/libs/SDL2/include/SDL_test_font.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_test_fuzzer.h b/libs/SDL2/include/SDL_test_fuzzer.h index a847ccb01ca25d80ffa7b4e36f9a2a8f12f7fa6f..cfe6a14f2a0288bd57cd00d642b4dd9c609a8c21 100644 --- a/libs/SDL2/include/SDL_test_fuzzer.h +++ b/libs/SDL2/include/SDL_test_fuzzer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_test_harness.h b/libs/SDL2/include/SDL_test_harness.h index bd9e4f8de070ae4ac730e1414b8f4ca951252008..26231dcd6bce9e72d54ddbef532a278762634948 100644 --- a/libs/SDL2/include/SDL_test_harness.h +++ b/libs/SDL2/include/SDL_test_harness.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_test_images.h b/libs/SDL2/include/SDL_test_images.h index b5bcb0a0000c49ff42d35284df2c859c9a577ca9..1211371755fdfd7bed0953fe1322fdcb639637a3 100644 --- a/libs/SDL2/include/SDL_test_images.h +++ b/libs/SDL2/include/SDL_test_images.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_test_log.h b/libs/SDL2/include/SDL_test_log.h index ea9ae5e1ca1d9b5170d336b5f770f9c530fdb893..a27ffc209a95ca3dd105b08dbe8ca4509245fe4c 100644 --- a/libs/SDL2/include/SDL_test_log.h +++ b/libs/SDL2/include/SDL_test_log.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_test_md5.h b/libs/SDL2/include/SDL_test_md5.h index 3764b042569eb63323ef6a589a5f3252147d4476..538c7ae3e09caa78990f738337bfbf2db9a86459 100644 --- a/libs/SDL2/include/SDL_test_md5.h +++ b/libs/SDL2/include/SDL_test_md5.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_test_memory.h b/libs/SDL2/include/SDL_test_memory.h index 9bd143252cefbdff77396b68ea54132b1859f16f..f959177d2336b5cf649d4d12a41cf76bf7a52578 100644 --- a/libs/SDL2/include/SDL_test_memory.h +++ b/libs/SDL2/include/SDL_test_memory.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_test_random.h b/libs/SDL2/include/SDL_test_random.h index 344646aa8b24a589b63482528441afbd296f88f8..0035a8030ad2cc4751a87d5aea3c032cd3c4944f 100644 --- a/libs/SDL2/include/SDL_test_random.h +++ b/libs/SDL2/include/SDL_test_random.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_thread.h b/libs/SDL2/include/SDL_thread.h index dc7f5363aadce39089dd1399963e541d416028b8..b829bbad5dc08bc47f02c64efc24ac97556ac603 100644 --- a/libs/SDL2/include/SDL_thread.h +++ b/libs/SDL2/include/SDL_thread.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_timer.h b/libs/SDL2/include/SDL_timer.h index 8123e432f1e5065b67bf51277110fbd7caf886fd..98f9ad16c647e8ecca4829b0629ae15e767f895e 100644 --- a/libs/SDL2/include/SDL_timer.h +++ b/libs/SDL2/include/SDL_timer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_touch.h b/libs/SDL2/include/SDL_touch.h index f6a5db413df92d8b253614ef723f546b581354b9..c12d4a1c8174997225ba25fe087bfb794e094f48 100644 --- a/libs/SDL2/include/SDL_touch.h +++ b/libs/SDL2/include/SDL_touch.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_types.h b/libs/SDL2/include/SDL_types.h index e8d33c651371bd2fd29b155f135461f66f6681bb..b5d7192ff2e95a994229a90e668ab003e16e5cab 100644 --- a/libs/SDL2/include/SDL_types.h +++ b/libs/SDL2/include/SDL_types.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/include/SDL_version.h b/libs/SDL2/include/SDL_version.h index 02143ff7a114e9cbe2a6113aa9d7726e2532808d..7585eece563127330f3e236174f55615d9f03ddf 100644 --- a/libs/SDL2/include/SDL_version.h +++ b/libs/SDL2/include/SDL_version.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -58,8 +58,8 @@ typedef struct SDL_version /* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL */ #define SDL_MAJOR_VERSION 2 -#define SDL_MINOR_VERSION 30 -#define SDL_PATCHLEVEL 0 +#define SDL_MINOR_VERSION 28 +#define SDL_PATCHLEVEL 5 /** * Macro to determine SDL version program was compiled against. diff --git a/libs/SDL2/include/SDL_video.h b/libs/SDL2/include/SDL_video.h index fa47d30991df03867c400da2fe80bb32d93457a8..c8b2d7a0d871e1f84cf4bf52f3583f8f5aaaf727 100644 --- a/libs/SDL2/include/SDL_video.h +++ b/libs/SDL2/include/SDL_video.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -1278,8 +1278,7 @@ extern DECLSPEC int SDLCALL SDL_SetWindowFullscreen(SDL_Window * window, /** * Return whether the window has a surface associated with it. * - * \returns SDL_TRUE if there is a surface associated with the window, or - * SDL_FALSE otherwise. + * \returns SDL_TRUE if there is a surface associated with the window, or SDL_FALSE otherwise. * * \since This function is available since SDL 2.28.0. * @@ -1341,11 +1340,6 @@ extern DECLSPEC int SDLCALL SDL_UpdateWindowSurface(SDL_Window * window); * * This function is equivalent to the SDL 1.2 API SDL_UpdateRects(). * - * Note that this function will update _at least_ the rectangles specified, - * but this is only intended as an optimization; in practice, this might - * update more of the screen (or all of the screen!), depending on what - * method SDL uses to send pixels to the system. - * * \param window the window to update * \param rects an array of SDL_Rect structures representing areas of the * surface to copy, in pixels diff --git a/libs/SDL2/include/begin_code.h b/libs/SDL2/include/begin_code.h index a47a7d2b6413cbb4f5dcd7534123477697ef71a3..4142ffeba928866354f51bedf3d1b1a9b8a4c3d9 100644 --- a/libs/SDL2/include/begin_code.h +++ b/libs/SDL2/include/begin_code.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -36,8 +36,6 @@ #ifndef SDL_DEPRECATED # if defined(__GNUC__) && (__GNUC__ >= 4) /* technically, this arrived in gcc 3.1, but oh well. */ # define SDL_DEPRECATED __attribute__((deprecated)) -# elif defined(_MSC_VER) -# define SDL_DEPRECATED __declspec(deprecated) # else # define SDL_DEPRECATED # endif diff --git a/libs/SDL2/include/close_code.h b/libs/SDL2/include/close_code.h index 50a0e6f3b4462c5197bd15d7d22e6a8f36204b46..b5ff3e2049b666eeeb923d234b7179722fd8d6c3 100644 --- a/libs/SDL2/include/close_code.h +++ b/libs/SDL2/include/close_code.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/lib/x64/SDL2.dll b/libs/SDL2/lib/x64/SDL2.dll index 878760628d4855ee65934869a1f47050b6920678..e26bcb1c3be11930053e594bc070df85b68d7b89 100644 Binary files a/libs/SDL2/lib/x64/SDL2.dll and b/libs/SDL2/lib/x64/SDL2.dll differ diff --git a/libs/SDL2/lib/x64/SDL2.lib b/libs/SDL2/lib/x64/SDL2.lib index 7257de6383ca5732a50a1df3f41f2447a2625d1c..99c5321cab958bb4c2e43583c7866a69972923f7 100644 Binary files a/libs/SDL2/lib/x64/SDL2.lib and b/libs/SDL2/lib/x64/SDL2.lib differ diff --git a/libs/SDL2/lib/x64/SDL2main.lib b/libs/SDL2/lib/x64/SDL2main.lib index 1981305fc5bc2ea865b5f35d02eb0d2e9659e265..241e7c3c8e8e4f6b088e07adfeeb34867b347343 100644 Binary files a/libs/SDL2/lib/x64/SDL2main.lib and b/libs/SDL2/lib/x64/SDL2main.lib differ diff --git a/libs/SDL2/lib/x64/SDL2test.lib b/libs/SDL2/lib/x64/SDL2test.lib index 0255ad475e4deec32f313495ba1c4d3db4f51ee1..1fa2ecb04e8eb3287df625803c3d0c426a7a268a 100644 Binary files a/libs/SDL2/lib/x64/SDL2test.lib and b/libs/SDL2/lib/x64/SDL2test.lib differ diff --git a/libs/SDL2/lib/x86/SDL2.dll b/libs/SDL2/lib/x86/SDL2.dll index 3265fb2f3de9e06460e7c6a73a83236b494b89fd..573225caba5abb279c844c438de4d6de2f6a10f1 100644 Binary files a/libs/SDL2/lib/x86/SDL2.dll and b/libs/SDL2/lib/x86/SDL2.dll differ diff --git a/libs/SDL2/lib/x86/SDL2.lib b/libs/SDL2/lib/x86/SDL2.lib index 0ac84d292be475cdf212bc9f5f34e843b633f48c..b35ba62a2807cb26a2ed8f29224d9744d6031ece 100644 Binary files a/libs/SDL2/lib/x86/SDL2.lib and b/libs/SDL2/lib/x86/SDL2.lib differ diff --git a/libs/SDL2/lib/x86/SDL2main.lib b/libs/SDL2/lib/x86/SDL2main.lib index 7cd691b62e67bffb3ae0f5348f14bef1f70782e3..eccce234347008bc5fa8c36005eef964df44447d 100644 Binary files a/libs/SDL2/lib/x86/SDL2main.lib and b/libs/SDL2/lib/x86/SDL2main.lib differ diff --git a/libs/SDL2/lib/x86/SDL2test.lib b/libs/SDL2/lib/x86/SDL2test.lib index 36ce4e0a59a7b4af853822ce0ed669959363fd85..21892ca9c737b69ac39e8d8b4a417c9ec1f2d961 100644 Binary files a/libs/SDL2/lib/x86/SDL2test.lib and b/libs/SDL2/lib/x86/SDL2test.lib differ diff --git a/libs/SDL2/test/CMakeLists.txt b/libs/SDL2/test/CMakeLists.txt index f048d51f9edcdfe1ed55ee2667606a07c4bc53a5..52a268561cb3ff21c7dc5d1318e808c6e503e702 100644 --- a/libs/SDL2/test/CMakeLists.txt +++ b/libs/SDL2/test/CMakeLists.txt @@ -7,55 +7,18 @@ include(CMakePushCheckState) set(SDL_TEST_EXECUTABLES) set(SDL_TESTS_NONINTERACTIVE) -set(SDL_TESTS_NEEDS_RESOURCES) +set(SDL_TESTS_NEEDS_ESOURCES) macro(add_sdl_test_executable TARGET) cmake_parse_arguments(AST "NONINTERACTIVE;NEEDS_RESOURCES" "" "" ${ARGN}) - if(ANDROID) - add_library(${TARGET} SHARED ${AST_UNPARSED_ARGUMENTS}) - else() - add_executable(${TARGET} ${AST_UNPARSED_ARGUMENTS}) - endif() + add_executable(${TARGET} ${AST_UNPARSED_ARGUMENTS}) list(APPEND SDL_TEST_EXECUTABLES ${TARGET}) if(AST_NONINTERACTIVE) list(APPEND SDL_TESTS_NONINTERACTIVE ${TARGET}) endif() if(AST_NEEDS_RESOURCES) - list(APPEND SDL_TESTS_NEEDS_RESOURCES ${TARGET}) - endif() - - if(HAVE_GCC_WDOCUMENTATION) - target_compile_options(${TARGET} PRIVATE "-Wdocumentation") - if(HAVE_GCC_WERROR_DOCUMENTATION) - target_compile_options(${TARGET} PRIVATE "-Werror=documentation") - endif() - endif() - - if(HAVE_GCC_WDOCUMENTATION_UNKNOWN_COMMAND) - if(SDL_WERROR) - if(HAVE_GCC_WERROR_DOCUMENTATION_UNKNOWN_COMMAND) - target_compile_options(${TARGET} PRIVATE "-Werror=documentation-unknown-command") - endif() - endif() - target_compile_options(${TARGET} PRIVATE "-Wdocumentation-unknown-command") - endif() - - if(HAVE_GCC_COMMENT_BLOCK_COMMANDS) - target_compile_options(${TARGET} PRIVATE "-fcomment-block-commands=threadsafety") - target_compile_options(${TARGET} PRIVATE "-fcomment-block-commands=deprecated") - else() - if(HAVE_CLANG_COMMENT_BLOCK_COMMANDS) - target_compile_options(${TARGET} PRIVATE "/clang:-fcomment-block-commands=threadsafety") - target_compile_options(${TARGET} PRIVATE "/clang:-fcomment-block-commands=deprecated") - endif() - endif() - - if(USE_GCC OR USE_CLANG) - check_c_compiler_flag(-fno-fast-math HAVE_GCC_FNO_FAST_MATH) - if(HAVE_GCC_FNO_FAST_MATH) - target_compile_options(${TARGET} PRIVATE -fno-fast-math) - endif() + list(APPEND SDL_TESTS_NEEDS_ESOURCES ${TARGET}) endif() endmacro() @@ -90,7 +53,7 @@ if(PSP) psppower ) elseif(PS2) - link_libraries( +link_libraries( SDL2main SDL2_test SDL2-static @@ -98,7 +61,7 @@ elseif(PS2) gskit dmakit ps2_drivers - ) +) else() link_libraries(SDL2::SDL2test SDL2::SDL2-static) endif() @@ -128,7 +91,7 @@ if(NOT MSVC OR NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64") endif() if (OPENGL_FOUND) - add_definitions(-DHAVE_OPENGL) +add_definitions(-DHAVE_OPENGL) endif() add_sdl_test_executable(checkkeys checkkeys.c) @@ -140,7 +103,7 @@ add_sdl_test_executable(testresample NEEDS_RESOURCES testresample.c) add_sdl_test_executable(testaudioinfo testaudioinfo.c) file(GLOB TESTAUTOMATION_SOURCE_FILES testautomation*.c) -add_sdl_test_executable(testautomation NONINTERACTIVE NEEDS_RESOURCES ${TESTAUTOMATION_SOURCE_FILES}) +add_sdl_test_executable(testautomation NEEDS_RESOURCES ${TESTAUTOMATION_SOURCE_FILES}) add_sdl_test_executable(testmultiaudio NEEDS_RESOURCES testmultiaudio.c testutils.c) add_sdl_test_executable(testaudiohotplug NEEDS_RESOURCES testaudiohotplug.c testutils.c) add_sdl_test_executable(testaudiocapture testaudiocapture.c) @@ -254,18 +217,18 @@ endif() cmake_pop_check_state() if(SDL_DUMMYAUDIO) - list(APPEND SDL_TESTS_NONINTERACTIVE - testaudioinfo - testsurround - ) + list(APPEND SDL_TESTS_NONINTERACTIVE + testaudioinfo + testsurround + ) endif() if(SDL_DUMMYVIDEO) - list(APPEND SDL_TESTS_NONINTERACTIVE - testkeys - testbounds - testdisplayinfo - ) + list(APPEND SDL_TESTS_NONINTERACTIVE + testkeys + testbounds + testdisplayinfo + ) endif() if(OPENGL_FOUND) @@ -291,7 +254,7 @@ file(COPY ${RESOURCE_FILES} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) if(PSP) # Build EBOOT files if building for PSP set(BUILD_EBOOT - ${SDL_TESTS_NEEDS_RESOURCES} + ${SDL_TESTS_NEEDS_ESOURCES} testatomic testaudiocapture testaudioinfo @@ -400,41 +363,14 @@ if(RISCOS) endforeach() endif() -if(CMAKE_RUNTIME_OUTPUT_DIRECTORY) - set(test_bin_dir "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") - if(NOT IS_ABSOLUTE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") - set(test_bin_dir "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_RUNTIME_OUTPUT_DIRECTORY}") - endif() -else() - set(test_bin_dir "${CMAKE_CURRENT_BINARY_DIR}") -endif() -if(NOT CMAKE_VERSION VERSION_LESS 3.20) - get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) - set(test_bin_dir "${test_bin_dir}$<$<BOOL:${is_multi_config}>:/$<CONFIG>>") -endif() - -set(RESOURCE_FILES_BINDIR) -foreach(resource_file IN LISTS RESOURCE_FILES) - get_filename_component(res_file_name ${resource_file} NAME) - set(resource_file_bindir "${test_bin_dir}/${res_file_name}") - add_custom_command(OUTPUT "${resource_file_bindir}" - COMMAND "${CMAKE_COMMAND}" -E copy "${resource_file}" "${resource_file_bindir}" - DEPENDS "${resource_file}" - ) - list(APPEND RESOURCE_FILES_BINDIR "${resource_file_bindir}") -endforeach() -add_custom_target(copy-sdl-test-resources - DEPENDS "${RESOURCE_FILES_BINDIR}" -) - foreach(APP IN LISTS SDL_TESTS_NEEDS_RESOURCES) - if(PSP OR PS2) - foreach(RESOURCE_FILE ${RESOURCE_FILES}) + foreach(RESOURCE_FILE ${RESOURCE_FILES}) + if(PSP OR PS2) add_custom_command(TARGET ${APP} POST_BUILD COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${RESOURCE_FILE} $<TARGET_FILE_DIR:${APP}>/sdl-${APP}) - endforeach() - else() - add_dependencies(${APP} copy-sdl-test-resources) - endif() + else() + add_custom_command(TARGET ${APP} POST_BUILD COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${RESOURCE_FILE} $<TARGET_FILE_DIR:${APP}>) + endif() + endforeach(RESOURCE_FILE) if(APPLE) # Make sure resource files get installed into macOS/iOS .app bundles. target_sources(${APP} PRIVATE "${RESOURCE_FILES}") @@ -491,7 +427,6 @@ foreach(TESTCASE ${SDL_TESTS_NONINTERACTIVE}) endif() endforeach() -set_tests_properties(testautomation PROPERTIES TIMEOUT 120) set_tests_properties(testthread PROPERTIES TIMEOUT 40) set_tests_properties(testtimer PROPERTIES TIMEOUT 60) if(TARGET testfilesystem_pre) @@ -511,11 +446,6 @@ if(SDL_INSTALL_TESTS) DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/installed-tests/SDL2 ) endif() - if(MSVC) - foreach(test ${SDL_TEST_EXECUTABLES}) - SDL_install_pdb(${test} "${CMAKE_INSTALL_LIBEXECDIR}/installed-tests/SDL2") - endforeach() - endif() install( FILES ${RESOURCE_FILES} DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/installed-tests/SDL2 diff --git a/libs/SDL2/test/Makefile.in b/libs/SDL2/test/Makefile.in index 76331d67fdd50191f211345a8a7c6a2df0b93b31..93df6360e847c37a1bde5845d4031bb91289d116 100644 --- a/libs/SDL2/test/Makefile.in +++ b/libs/SDL2/test/Makefile.in @@ -95,7 +95,7 @@ installedtestsmetadir = $(datadir)/installed-tests/SDL2 generatetestmeta: rm -f *.test - set -e; for exe in $(TESTS); do \ + set -e; for exe in $(noninteractive) $(needs_audio) $(needs_display); do \ sed \ -e 's#@installedtestsdir@#$(installedtestsdir)#g' \ -e "s#@exe@#$$exe#g" \ @@ -141,7 +141,6 @@ testautomation$(EXE): $(srcdir)/testautomation.c \ $(srcdir)/testautomation_hints.c \ $(srcdir)/testautomation_joystick.c \ $(srcdir)/testautomation_keyboard.c \ - $(srcdir)/testautomation_log.c \ $(srcdir)/testautomation_main.c \ $(srcdir)/testautomation_math.c \ $(srcdir)/testautomation_mouse.c \ @@ -152,7 +151,6 @@ testautomation$(EXE): $(srcdir)/testautomation.c \ $(srcdir)/testautomation_rwops.c \ $(srcdir)/testautomation_sdltest.c \ $(srcdir)/testautomation_stdlib.c \ - $(srcdir)/testautomation_subsystems.c \ $(srcdir)/testautomation_surface.c \ $(srcdir)/testautomation_syswm.c \ $(srcdir)/testautomation_timer.c \ @@ -387,12 +385,8 @@ distclean: clean rm -f config.status config.cache config.log rm -rf $(srcdir)/autom4te* -TESTS = \ +noninteractive = \ testatomic$(EXE) \ - testaudioinfo$(EXE) \ - testautomation$(EXE) \ - testbounds$(EXE) \ - testdisplayinfo$(EXE) \ testerror$(EXE) \ testevdev$(EXE) \ testfilesystem$(EXE) \ @@ -401,12 +395,23 @@ TESTS = \ testplatform$(EXE) \ testpower$(EXE) \ testqsort$(EXE) \ - testsurround$(EXE) \ testthread$(EXE) \ testtimer$(EXE) \ testver$(EXE) \ $(NULL) +needs_audio = \ + testaudioinfo$(EXE) \ + testsurround$(EXE) \ + $(NULL) + +needs_display = \ + testbounds$(EXE) \ + testdisplayinfo$(EXE) \ + $(NULL) + +TESTS = $(noninteractive) $(needs_audio) $(needs_display) + check: @set -e; \ status=0; \ diff --git a/libs/SDL2/test/acinclude.m4 b/libs/SDL2/test/acinclude.m4 index ebee8238ab63e78847963d6d9e7225510cb3cd7e..0fdf353ea29a56e196bfd3340ebb6a9ab1491259 100644 --- a/libs/SDL2/test/acinclude.m4 +++ b/libs/SDL2/test/acinclude.m4 @@ -5,6 +5,8 @@ # stolen from Manish Singh # Shamelessly stolen from Owen Taylor +# serial 2 + dnl AM_PATH_SDL2([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS dnl @@ -43,7 +45,7 @@ AC_ARG_ENABLE(sdltest, [ --disable-sdltest Do not try to compile and run if test "x$sdl_pc" = xyes ; then no_sdl="" - SDL2_CONFIG="$PKG_CONFIG sdl2" + SDL2_CONFIG="pkg-config sdl2" else as_save_PATH="$PATH" if test "x$prefix" != xNONE && test "$cross_compiling" != yes; then diff --git a/libs/SDL2/test/checkkeys.c b/libs/SDL2/test/checkkeys.c index f546900c5079422e7515e4d0a1f8a49986021321..4efdc721e1a0928299bf0d7dfc26f56c8d01cbfb 100644 --- a/libs/SDL2/test/checkkeys.c +++ b/libs/SDL2/test/checkkeys.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -269,14 +269,14 @@ int main(int argc, char *argv[]) window = SDL_CreateWindow("CheckKeys Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, 0); - if (!window) { + if (window == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create 640x480 window: %s\n", SDL_GetError()); quit(2); } renderer = SDL_CreateRenderer(window, -1, 0); - if (!renderer) { + if (renderer == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError()); quit(2); @@ -284,7 +284,7 @@ int main(int argc, char *argv[]) textwin = SDLTest_TextWindowCreate(0, 0, 640, 480); -#ifdef __IPHONEOS__ +#if __IPHONEOS__ /* Creating the context creates the view, which we need to show keyboard */ SDL_GL_CreateContext(window); #endif diff --git a/libs/SDL2/test/checkkeysthreads.c b/libs/SDL2/test/checkkeysthreads.c index efd654875f935d6e5465444ce4af9b0400d9a6b8..3db5dd2dc7a2b27455faa1e46e30dfd4182c867a 100644 --- a/libs/SDL2/test/checkkeysthreads.c +++ b/libs/SDL2/test/checkkeysthreads.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -254,7 +254,7 @@ int main(int argc, char *argv[]) window = SDL_CreateWindow("CheckKeys Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, 0); - if (!window) { + if (window == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create 640x480 window: %s\n", SDL_GetError()); quit(2); @@ -266,7 +266,7 @@ int main(int argc, char *argv[]) renderer = SDL_CreateRenderer(window, -1, 0); SDL_RenderPresent(renderer); -#ifdef __IPHONEOS__ +#if __IPHONEOS__ /* Creating the context creates the view, which we need to show keyboard */ SDL_GL_CreateContext(window); #endif diff --git a/libs/SDL2/test/configure b/libs/SDL2/test/configure index 8ea80bc27ea2d4150880e42d505f24c77cfa6c0c..c71abe48977ffe5ff68d0b8c6f0cc82fb836aa69 100755 --- a/libs/SDL2/test/configure +++ b/libs/SDL2/test/configure @@ -3966,7 +3966,7 @@ fi if test "x$sdl_pc" = xyes ; then no_sdl="" - SDL2_CONFIG="$PKG_CONFIG sdl2" + SDL2_CONFIG="pkg-config sdl2" else as_save_PATH="$PATH" if test "x$prefix" != xNONE && test "$cross_compiling" != yes; then diff --git a/libs/SDL2/test/controllermap.c b/libs/SDL2/test/controllermap.c index 982a9fb6fd9c562f59060f099a03b327fca4161a..cfb0effaced81512761061bbf918bfa57d0d8636 100644 --- a/libs/SDL2/test/controllermap.c +++ b/libs/SDL2/test/controllermap.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -288,8 +288,7 @@ ConfigureBinding(const SDL_GameControllerExtendedBind *pBinding) SDL_Log("Configuring button binding for button %d\n", pBinding->value.button); break; case SDL_CONTROLLER_BINDTYPE_AXIS: - SDL_Log("Configuring axis binding for axis %d %d/%d committed = %s\n", pBinding->value.axis.axis, pBinding->value.axis.axis_min, pBinding->value.axis.axis_max, - pBinding->committed ? "true" : "false"); + SDL_Log("Configuring axis binding for axis %d %d/%d committed = %s\n", pBinding->value.axis.axis, pBinding->value.axis.axis_min, pBinding->value.axis.axis_max, pBinding->committed ? "true" : "false"); break; case SDL_CONTROLLER_BINDTYPE_HAT: SDL_Log("Configuring hat binding for hat %d %d\n", pBinding->value.hat.hat, pBinding->value.hat.hat_mask); @@ -730,13 +729,13 @@ int main(int argc, char *argv[]) window = SDL_CreateWindow("Game Controller Map", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, 0); - if (!window) { + if (window == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError()); return 2; } screen = SDL_CreateRenderer(window, -1, 0); - if (!screen) { + if (screen == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError()); return 2; } @@ -767,7 +766,7 @@ int main(int argc, char *argv[]) name = SDL_JoystickNameForIndex(i); SDL_Log("Joystick %d: %s\n", i, name ? name : "Unknown Joystick"); joystick = SDL_JoystickOpen(i); - if (!joystick) { + if (joystick == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_JoystickOpen(%d) failed: %s\n", i, SDL_GetError()); } else { @@ -793,7 +792,7 @@ int main(int argc, char *argv[]) } } joystick = SDL_JoystickOpen(joystick_index); - if (!joystick) { + if (joystick == NULL) { SDL_Log("Couldn't open joystick %d: %s\n", joystick_index, SDL_GetError()); } else { WatchJoystick(joystick); diff --git a/libs/SDL2/test/loopwave.c b/libs/SDL2/test/loopwave.c index 15f13658c5ea09759f86bca41a3d768129c3829c..156767c20fabc335f0cd54b450cf0eedcf70f7f2 100644 --- a/libs/SDL2/test/loopwave.c +++ b/libs/SDL2/test/loopwave.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -127,7 +127,7 @@ int main(int argc, char *argv[]) filename = GetResourceFilename(argc > 1 ? argv[1] : NULL, "sample.wav"); - if (!filename) { + if (filename == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s\n", SDL_GetError()); quit(1); } diff --git a/libs/SDL2/test/loopwavequeue.c b/libs/SDL2/test/loopwavequeue.c index 01b6ece3e39c3e9921d99054c521fbe4603ed4e2..70dd072d29ec2f8a7aee1c7efe0d43b9c6a34206 100644 --- a/libs/SDL2/test/loopwavequeue.c +++ b/libs/SDL2/test/loopwavequeue.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -21,7 +21,7 @@ #include "SDL.h" -#ifdef HAVE_SIGNAL_H +#if HAVE_SIGNAL_H #include <signal.h> #endif @@ -84,7 +84,7 @@ int main(int argc, char *argv[]) filename = GetResourceFilename(argc > 1 ? argv[1] : NULL, "sample.wav"); - if (!filename) { + if (filename == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s\n", SDL_GetError()); quit(1); } @@ -97,7 +97,7 @@ int main(int argc, char *argv[]) wave.spec.callback = NULL; /* we'll push audio. */ -#ifdef HAVE_SIGNAL_H +#if HAVE_SIGNAL_H /* Set the signals */ #ifdef SIGHUP (void)signal(SIGHUP, poked); diff --git a/libs/SDL2/test/testatomic.c b/libs/SDL2/test/testatomic.c index 1a599101ec339e7a06d9fd6508449c42750a9f9f..15a7a6a7d94ca86fdf7d4430aadabf16b9cfc055 100644 --- a/libs/SDL2/test/testatomic.c +++ b/libs/SDL2/test/testatomic.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -234,8 +234,7 @@ static void RunEpicTest() v = SDL_AtomicGet(&good); SDL_Log("Atomic %d Non-Atomic %d\n", v, bad); SDL_assert(v == Expect); - /* We can't guarantee that bad != Expect, this would happen on a single core system, for example. */ - /*SDL_assert(bad != Expect);*/ + SDL_assert(bad != Expect); } /* End atomic operation test */ diff --git a/libs/SDL2/test/testaudiocapture.c b/libs/SDL2/test/testaudiocapture.c index 523385b3ae48472a256727bc9adf94ce5f7d48dc..a8fdf5ec5ca300c5dfd8c63d95d89cf7ef05b588 100644 --- a/libs/SDL2/test/testaudiocapture.c +++ b/libs/SDL2/test/testaudiocapture.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/test/testaudiohotplug.c b/libs/SDL2/test/testaudiohotplug.c index 354d4644f3c0e14e9113c62ea1dd2736b18002ed..e4bd9ac096f6c679c07a81cde0aeb93b3c1c9b80 100644 --- a/libs/SDL2/test/testaudiohotplug.c +++ b/libs/SDL2/test/testaudiohotplug.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -17,7 +17,7 @@ #include <stdio.h> #include <stdlib.h> -#ifdef HAVE_SIGNAL_H +#if HAVE_SIGNAL_H #include <signal.h> #endif @@ -96,7 +96,7 @@ iteration() int index = e.adevice.which; int iscapture = e.adevice.iscapture; const char *name = SDL_GetAudioDeviceName(index, iscapture); - if (name) { + if (name != NULL) { SDL_Log("New %s audio device at index %u: %s\n", devtypestr(iscapture), (unsigned int)index, name); } else { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Got new %s device at index %u, but failed to get the name: %s\n", @@ -152,7 +152,7 @@ int main(int argc, char *argv[]) filename = GetResourceFilename(argc > 1 ? argv[1] : NULL, "sample.wav"); - if (!filename) { + if (filename == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s\n", SDL_GetError()); quit(1); } @@ -163,7 +163,7 @@ int main(int argc, char *argv[]) quit(1); } -#ifdef HAVE_SIGNAL_H +#if HAVE_SIGNAL_H /* Set the signals */ #ifdef SIGHUP (void)signal(SIGHUP, poked); diff --git a/libs/SDL2/test/testaudioinfo.c b/libs/SDL2/test/testaudioinfo.c index ec4b86470d707bb46305a6807545d58aa5ba500b..ae59cbcc8611302408a4676681099e7990a10f4f 100644 --- a/libs/SDL2/test/testaudioinfo.c +++ b/libs/SDL2/test/testaudioinfo.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -29,7 +29,7 @@ print_devices(int iscapture) int i; for (i = 0; i < n; i++) { const char *name = SDL_GetAudioDeviceName(i, iscapture); - if (name) { + if (name != NULL) { SDL_Log(" %d: %s\n", i, name); } else { SDL_Log(" %d Error: %s\n", i, SDL_GetError()); @@ -81,7 +81,7 @@ int main(int argc, char **argv) if (SDL_GetDefaultAudioInfo(&deviceName, &spec, 0) < 0) { SDL_Log("Error when calling SDL_GetDefaultAudioInfo: %s\n", SDL_GetError()); } else { - SDL_Log("Default Output Name: %s\n", deviceName ? deviceName : "unknown"); + SDL_Log("Default Output Name: %s\n", deviceName != NULL ? deviceName : "unknown"); SDL_free(deviceName); SDL_Log("Sample Rate: %d\n", spec.freq); SDL_Log("Channels: %d\n", spec.channels); @@ -91,7 +91,7 @@ int main(int argc, char **argv) if (SDL_GetDefaultAudioInfo(&deviceName, &spec, 1) < 0) { SDL_Log("Error when calling SDL_GetDefaultAudioInfo: %s\n", SDL_GetError()); } else { - SDL_Log("Default Capture Name: %s\n", deviceName ? deviceName : "unknown"); + SDL_Log("Default Capture Name: %s\n", deviceName != NULL ? deviceName : "unknown"); SDL_free(deviceName); SDL_Log("Sample Rate: %d\n", spec.freq); SDL_Log("Channels: %d\n", spec.channels); diff --git a/libs/SDL2/test/testautomation.c b/libs/SDL2/test/testautomation.c index 3b5fad808ac8794e00dc0fd0f70c114885f66496..2150ed246be139f2f5740ea73f5aec07442d56ef 100644 --- a/libs/SDL2/test/testautomation.c +++ b/libs/SDL2/test/testautomation.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -41,7 +41,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (!state) { + if (state == NULL) { return 1; } diff --git a/libs/SDL2/test/testautomation_audio.c b/libs/SDL2/test/testautomation_audio.c index 16ab753e9787d320c9d6e49fb38fa78e4107bdd6..bd586314f9543b23a845239d71fde76e49a4bd51 100644 --- a/libs/SDL2/test/testautomation_audio.c +++ b/libs/SDL2/test/testautomation_audio.c @@ -52,42 +52,6 @@ void SDLCALL _audio_testCallback(void *userdata, Uint8 *stream, int len) _audio_testCallbackLength += len; } -#if defined(__linux__) -/* Linux builds can include many audio drivers, but some are very - * obscure and typically unsupported on modern systems. They will - * be skipped in tests that run against all included drivers, as - * they are basically guaranteed to fail. - */ -static SDL_bool DriverIsProblematic(const char *driver) -{ - static const char *driverList[] = { - /* Omnipresent in Linux builds, but deprecated since 2002, - * very rarely used on Linux nowadays, and is almost certainly - * guaranteed to fail. - */ - "dsp", - - /* OpenBSD sound API. Can be used on Linux, but very rare. */ - "sndio", - - /* Always fails on initialization and/or opening a device. - * Does anyone or anything actually use this? - */ - "nas" - }; - - int i; - - for (i = 0; i < SDL_arraysize(driverList); ++i) { - if (SDL_strcmp(driver, driverList[i]) == 0) { - return SDL_TRUE; - } - } - - return SDL_FALSE; -} -#endif - /* Test case functions */ /** @@ -119,43 +83,20 @@ int audio_initQuitAudio() int result; int i, iMax; const char *audioDriver; - const char *hint = SDL_GetHint(SDL_HINT_AUDIODRIVER); /* Stop SDL audio subsystem */ SDL_QuitSubSystem(SDL_INIT_AUDIO); SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)"); - /* Was a specific driver requested? */ - audioDriver = SDL_GetHint(SDL_HINT_AUDIODRIVER); - - if (audioDriver == NULL) { - /* Loop over all available audio drivers */ - iMax = SDL_GetNumAudioDrivers(); - SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers()"); - SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax); - } else { - /* A specific driver was requested for testing */ - iMax = 1; - } + /* Loop over all available audio drivers */ + iMax = SDL_GetNumAudioDrivers(); + SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers()"); + SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax); for (i = 0; i < iMax; i++) { - if (audioDriver == NULL) { - audioDriver = SDL_GetAudioDriver(i); - SDLTest_AssertPass("Call to SDL_GetAudioDriver(%d)", i); - SDLTest_Assert(audioDriver != NULL, "Audio driver name is not NULL"); - SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver); /* NOLINT(clang-analyzer-core.NullDereference): Checked for NULL above */ - -#if defined(__linux__) - if (DriverIsProblematic(audioDriver)) { - SDLTest_Log("Audio driver '%s' flagged as problematic: skipping init/quit test (set SDL_AUDIODRIVER=%s to force)", audioDriver, audioDriver); - audioDriver = NULL; - continue; - } -#endif - } - - if (hint && SDL_strcmp(audioDriver, hint) != 0) { - continue; - } + audioDriver = SDL_GetAudioDriver(i); + SDLTest_AssertPass("Call to SDL_GetAudioDriver(%d)", i); + SDLTest_Assert(audioDriver != NULL, "Audio driver name is not NULL"); + SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver); /* NOLINT(clang-analyzer-core.NullDereference): Checked for NULL above */ /* Call Init */ result = SDL_AudioInit(audioDriver); @@ -165,8 +106,6 @@ int audio_initQuitAudio() /* Call Quit */ SDL_AudioQuit(); SDLTest_AssertPass("Call to SDL_AudioQuit()"); - - audioDriver = NULL; } /* NULL driver specification */ @@ -201,43 +140,20 @@ int audio_initOpenCloseQuitAudio() int i, iMax, j, k; const char *audioDriver; SDL_AudioSpec desired; - const char *hint = SDL_GetHint(SDL_HINT_AUDIODRIVER); /* Stop SDL audio subsystem */ SDL_QuitSubSystem(SDL_INIT_AUDIO); SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)"); - /* Was a specific driver requested? */ - audioDriver = SDL_GetHint(SDL_HINT_AUDIODRIVER); - - if (audioDriver == NULL) { - /* Loop over all available audio drivers */ - iMax = SDL_GetNumAudioDrivers(); - SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers()"); - SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax); - } else { - /* A specific driver was requested for testing */ - iMax = 1; - } + /* Loop over all available audio drivers */ + iMax = SDL_GetNumAudioDrivers(); + SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers()"); + SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax); for (i = 0; i < iMax; i++) { - if (audioDriver == NULL) { - audioDriver = SDL_GetAudioDriver(i); - SDLTest_AssertPass("Call to SDL_GetAudioDriver(%d)", i); - SDLTest_Assert(audioDriver != NULL, "Audio driver name is not NULL"); - SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver); /* NOLINT(clang-analyzer-core.NullDereference): Checked for NULL above */ - -#if defined(__linux__) - if (DriverIsProblematic(audioDriver)) { - SDLTest_Log("Audio driver '%s' flagged as problematic: skipping device open/close test (set SDL_AUDIODRIVER=%s to force)", audioDriver, audioDriver); - audioDriver = NULL; - continue; - } -#endif - } - - if (hint && SDL_strcmp(audioDriver, hint) != 0) { - continue; - } + audioDriver = SDL_GetAudioDriver(i); + SDLTest_AssertPass("Call to SDL_GetAudioDriver(%d)", i); + SDLTest_Assert(audioDriver != NULL, "Audio driver name is not NULL"); + SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver); /* NOLINT(clang-analyzer-core.NullDereference): Checked for NULL above */ /* Change specs */ for (j = 0; j < 2; j++) { @@ -247,17 +163,6 @@ int audio_initOpenCloseQuitAudio() SDLTest_AssertPass("Call to SDL_AudioInit('%s')", audioDriver); SDLTest_AssertCheck(result == 0, "Validate result value; expected: 0 got: %d", result); - /* Check for output devices */ - result = SDL_GetNumAudioDevices(SDL_FALSE); - SDLTest_AssertPass("Call to SDL_GetNumAudioDevices(SDL_FALSE)"); - SDLTest_AssertCheck(result >= 0, "Validate result value; expected: >=0 got: %d", result); - if (result <= 0) { - SDLTest_Log("No output devices for '%s': skipping device open/close test", audioDriver); - SDL_AudioQuit(); - SDLTest_AssertPass("Call to SDL_AudioQuit()"); - break; - } - /* Set spec */ SDL_memset(&desired, 0, sizeof(desired)); switch (j) { @@ -302,10 +207,7 @@ int audio_initOpenCloseQuitAudio() } } /* spec loop */ - - audioDriver = NULL; - - } /* driver loop */ + } /* driver loop */ /* Restart audio again */ _audioSetUp(NULL); @@ -327,43 +229,20 @@ int audio_pauseUnpauseAudio() int originalCounter; const char *audioDriver; SDL_AudioSpec desired; - const char *hint = SDL_GetHint(SDL_HINT_AUDIODRIVER); /* Stop SDL audio subsystem */ SDL_QuitSubSystem(SDL_INIT_AUDIO); SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)"); - /* Was a specific driver requested? */ - audioDriver = SDL_GetHint(SDL_HINT_AUDIODRIVER); - - if (audioDriver == NULL) { - /* Loop over all available audio drivers */ - iMax = SDL_GetNumAudioDrivers(); - SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers()"); - SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax); - } else { - /* A specific driver was requested for testing */ - iMax = 1; - } + /* Loop over all available audio drivers */ + iMax = SDL_GetNumAudioDrivers(); + SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers()"); + SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax); for (i = 0; i < iMax; i++) { - if (audioDriver == NULL) { - audioDriver = SDL_GetAudioDriver(i); - SDLTest_AssertPass("Call to SDL_GetAudioDriver(%d)", i); - SDLTest_Assert(audioDriver != NULL, "Audio driver name is not NULL"); - SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver); /* NOLINT(clang-analyzer-core.NullDereference): Checked for NULL above */ - -#if defined(__linux__) - if (DriverIsProblematic(audioDriver)) { - SDLTest_Log("Audio driver '%s' flagged as problematic: skipping pause/unpause test (set SDL_AUDIODRIVER=%s to force)", audioDriver, audioDriver); - audioDriver = NULL; - continue; - } -#endif - } - - if (hint && SDL_strcmp(audioDriver, hint) != 0) { - continue; - } + audioDriver = SDL_GetAudioDriver(i); + SDLTest_AssertPass("Call to SDL_GetAudioDriver(%d)", i); + SDLTest_Assert(audioDriver != NULL, "Audio driver name is not NULL"); + SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver); /* NOLINT(clang-analyzer-core.NullDereference): Checked for NULL above */ /* Change specs */ for (j = 0; j < 2; j++) { @@ -373,16 +252,6 @@ int audio_pauseUnpauseAudio() SDLTest_AssertPass("Call to SDL_AudioInit('%s')", audioDriver); SDLTest_AssertCheck(result == 0, "Validate result value; expected: 0 got: %d", result); - result = SDL_GetNumAudioDevices(SDL_FALSE); - SDLTest_AssertPass("Call to SDL_GetNumAudioDevices(SDL_FALSE)"); - SDLTest_AssertCheck(result >= 0, "Validate result value; expected: >=0 got: %d", result); - if (result <= 0) { - SDLTest_Log("No output devices for '%s': skipping pause/unpause test", audioDriver); - SDL_AudioQuit(); - SDLTest_AssertPass("Call to SDL_AudioQuit()"); - break; - } - /* Set spec */ SDL_memset(&desired, 0, sizeof(desired)); switch (j) { @@ -457,10 +326,7 @@ int audio_pauseUnpauseAudio() SDLTest_AssertPass("Call to SDL_AudioQuit()"); } /* spec loop */ - - audioDriver = NULL; - - } /* driver loop */ + } /* driver loop */ /* Restart audio again */ _audioSetUp(NULL); @@ -1159,8 +1025,8 @@ int audio_resampleLoss() SDLTest_AssertPass("Test resampling of %i s %i Hz %f phase sine wave from sampling rate of %i Hz to %i Hz", spec->time, spec->freq, spec->phase, spec->rate_in, spec->rate_out); - ret = SDL_BuildAudioCVT(&cvt, AUDIO_F32SYS, 1, spec->rate_in, AUDIO_F32SYS, 1, spec->rate_out); - SDLTest_AssertPass("Call to SDL_BuildAudioCVT(&cvt, AUDIO_F32SYS, 1, %i, AUDIO_F32SYS, 1, %i)", spec->rate_in, spec->rate_out); + ret = SDL_BuildAudioCVT(&cvt, AUDIO_F32, 1, spec->rate_in, AUDIO_F32, 1, spec->rate_out); + SDLTest_AssertPass("Call to SDL_BuildAudioCVT(&cvt, AUDIO_F32, 1, %i, AUDIO_F32, 1, %i)", spec->rate_in, spec->rate_out); SDLTest_AssertCheck(ret == 1, "Expected SDL_BuildAudioCVT to succeed and conversion to be needed."); if (ret != 1) { return TEST_ABORTED; diff --git a/libs/SDL2/test/testautomation_clipboard.c b/libs/SDL2/test/testautomation_clipboard.c index ce8ea1bd3da8b68c43bb5131ef21df588b9c1adc..dbe1ef8e4007293f633b38f9048714eb8d8e943d 100644 --- a/libs/SDL2/test/testautomation_clipboard.c +++ b/libs/SDL2/test/testautomation_clipboard.c @@ -84,7 +84,7 @@ int clipboard_testSetClipboardText(void *arg) char *textRef = SDLTest_RandomAsciiString(); char *text = SDL_strdup(textRef); int result; - result = SDL_SetClipboardText(text); + result = SDL_SetClipboardText((const char *)text); SDLTest_AssertPass("Call to SDL_SetClipboardText succeeded"); SDLTest_AssertCheck( result == 0, @@ -112,7 +112,7 @@ int clipboard_testSetPrimarySelectionText(void *arg) char *textRef = SDLTest_RandomAsciiString(); char *text = SDL_strdup(textRef); int result; - result = SDL_SetPrimarySelectionText(text); + result = SDL_SetPrimarySelectionText((const char *)text); SDLTest_AssertPass("Call to SDL_SetPrimarySelectionText succeeded"); SDLTest_AssertCheck( result == 0, @@ -149,7 +149,7 @@ int clipboard_testClipboardTextFunctions(void *arg) boolResult = SDL_HasClipboardText(); SDLTest_AssertPass("Call to SDL_HasClipboardText succeeded"); if (boolResult == SDL_TRUE) { - intResult = SDL_SetClipboardText(NULL); + intResult = SDL_SetClipboardText((const char *)NULL); SDLTest_AssertPass("Call to SDL_SetClipboardText(NULL) succeeded"); SDLTest_AssertCheck( intResult == 0, @@ -176,7 +176,7 @@ int clipboard_testClipboardTextFunctions(void *arg) charResult[0] == '\0', /* NOLINT(clang-analyzer-core.NullDereference): Checked for NULL above */ "Verify SDL_GetClipboardText returned string with length 0, got length %i", (int)SDL_strlen(charResult)); - intResult = SDL_SetClipboardText(text); + intResult = SDL_SetClipboardText((const char *)text); SDLTest_AssertPass("Call to SDL_SetClipboardText succeeded"); SDLTest_AssertCheck( intResult == 0, @@ -227,7 +227,7 @@ int clipboard_testPrimarySelectionTextFunctions(void *arg) boolResult = SDL_HasPrimarySelectionText(); SDLTest_AssertPass("Call to SDL_HasPrimarySelectionText succeeded"); if (boolResult == SDL_TRUE) { - intResult = SDL_SetPrimarySelectionText(NULL); + intResult = SDL_SetPrimarySelectionText((const char *)NULL); SDLTest_AssertPass("Call to SDL_SetPrimarySelectionText(NULL) succeeded"); SDLTest_AssertCheck( intResult == 0, @@ -254,7 +254,7 @@ int clipboard_testPrimarySelectionTextFunctions(void *arg) charResult[0] == '\0', /* NOLINT(clang-analyzer-core.NullDereference): Checked for NULL above */ "Verify SDL_GetPrimarySelectionText returned string with length 0, got length %i", (int)SDL_strlen(charResult)); - intResult = SDL_SetPrimarySelectionText(text); + intResult = SDL_SetPrimarySelectionText((const char *)text); SDLTest_AssertPass("Call to SDL_SetPrimarySelectionText succeeded"); SDLTest_AssertCheck( intResult == 0, diff --git a/libs/SDL2/test/testautomation_events.c b/libs/SDL2/test/testautomation_events.c index d4babdafcefeefc4692dc7b5d155f18ad0f4368e..6d0f3ff533789aa55415ecd125f051c951ec38e8 100644 --- a/libs/SDL2/test/testautomation_events.c +++ b/libs/SDL2/test/testautomation_events.c @@ -68,10 +68,6 @@ int events_pushPumpAndPollUserevent(void *arg) SDLTest_AssertPass("Call to SDL_PollEvent()"); SDLTest_AssertCheck(result == 1, "Check result from SDL_PollEvent, expected: 1, got: %d", result); - /* Need to finish getting all events and sentinel, otherwise other tests that rely on event are in bad state */ - while (SDL_PollEvent(&event2)) { - } - return TEST_COMPLETED; } diff --git a/libs/SDL2/test/testautomation_guid.c b/libs/SDL2/test/testautomation_guid.c index 81e60e8f4ba9f9baaa87234f8a663877866b7d2c..cf99dea8139a8e6f7d84703f4e08e2d8abd74f9f 100644 --- a/libs/SDL2/test/testautomation_guid.c +++ b/libs/SDL2/test/testautomation_guid.c @@ -125,7 +125,7 @@ TestGuidToString(void *arg) SDL_GUIDToString(guid, guid_str, size); /* Check bytes before guid_str_buf */ - expected_prefix = fill_char | (fill_char << 8) | (fill_char << 16) | (((Uint32)fill_char) << 24); + expected_prefix = fill_char | (fill_char << 8) | (fill_char << 16) | (fill_char << 24); SDL_memcpy(&actual_prefix, guid_str_buf, 4); SDLTest_AssertCheck(expected_prefix == actual_prefix, "String buffer memory before output untouched, expected: %" SDL_PRIu32 ", got: %" SDL_PRIu32 ", at size=%d", expected_prefix, actual_prefix, size); diff --git a/libs/SDL2/test/testautomation_keyboard.c b/libs/SDL2/test/testautomation_keyboard.c index 5ed9207bca5f685aca864e8093dd9bc553eeab29..0d459d0b2dd1c9d7e7fa91abfca5668c2fb9bfe7 100644 --- a/libs/SDL2/test/testautomation_keyboard.c +++ b/libs/SDL2/test/testautomation_keyboard.c @@ -463,34 +463,32 @@ int keyboard_setTextInputRect(void *arg) */ int keyboard_setTextInputRectNegative(void *arg) { - int platform_sets_error_message = SDL_strcmp(SDL_GetCurrentVideoDriver(), "windows") == 0 || - SDL_strcmp(SDL_GetCurrentVideoDriver(), "android") == 0 || - SDL_strcmp(SDL_GetCurrentVideoDriver(), "cococa") == 0; /* Some platforms set also an error message; prepare for checking it */ +#if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_ANDROID || SDL_VIDEO_DRIVER_COCOA const char *expectedError = "Parameter 'rect' is invalid"; const char *error; SDL_ClearError(); SDLTest_AssertPass("Call to SDL_ClearError()"); +#endif /* NULL refRect */ SDL_SetTextInputRect(NULL); SDLTest_AssertPass("Call to SDL_SetTextInputRect(NULL)"); /* Some platforms set also an error message; so check it */ - - if (platform_sets_error_message) { - error = SDL_GetError(); - SDLTest_AssertPass("Call to SDL_GetError()"); - SDLTest_AssertCheck(error != NULL, "Validate that error message was not NULL"); - if (error != NULL) { - SDLTest_AssertCheck(SDL_strcmp(error, expectedError) == 0, - "Validate error message, expected: '%s', got: '%s'", expectedError, error); - } +#if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_ANDROID || SDL_VIDEO_DRIVER_COCOA + error = SDL_GetError(); + SDLTest_AssertPass("Call to SDL_GetError()"); + SDLTest_AssertCheck(error != NULL, "Validate that error message was not NULL"); + if (error != NULL) { + SDLTest_AssertCheck(SDL_strcmp(error, expectedError) == 0, + "Validate error message, expected: '%s', got: '%s'", expectedError, error); } SDL_ClearError(); SDLTest_AssertPass("Call to SDL_ClearError()"); +#endif return TEST_COMPLETED; } diff --git a/libs/SDL2/test/testautomation_log.c b/libs/SDL2/test/testautomation_log.c deleted file mode 100644 index 4edb487ea31028e86391c14ad5cd0e6927c4bfc0..0000000000000000000000000000000000000000 --- a/libs/SDL2/test/testautomation_log.c +++ /dev/null @@ -1,209 +0,0 @@ -/** - * Log test suite - */ -#include "SDL.h" -#include "SDL_test.h" - - -static SDL_LogOutputFunction original_function; -static void *original_userdata; - -static void SDLCALL TestLogOutput(void *userdata, int category, SDL_LogPriority priority, const char *message) -{ - int *message_count = (int *)userdata; - ++(*message_count); -} - -static void EnableTestLog(int *message_count) -{ - *message_count = 0; - SDL_LogGetOutputFunction(&original_function, &original_userdata); - SDL_LogSetOutputFunction(TestLogOutput, message_count); -} - -static void DisableTestLog() -{ - SDL_LogSetOutputFunction(original_function, original_userdata); -} - -/* Fixture */ - -/* Test case functions */ - -/** - * Check SDL_HINT_LOGGING functionality - */ -static int log_testHint(void *arg) -{ - int count; - - SDL_SetHint(SDL_HINT_LOGGING, NULL); - SDLTest_AssertPass("SDL_SetHint(SDL_HINT_LOGGING, NULL)"); - { - EnableTestLog(&count); - SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "test"); - DisableTestLog(); - SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, \"test\")"); - SDLTest_AssertCheck(count == 1, "Check result value, expected: 1, got: %d", count); - - EnableTestLog(&count); - SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG, "test"); - DisableTestLog(); - SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG, \"test\")"); - SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count); - } - - SDL_SetHint(SDL_HINT_LOGGING, "debug"); - SDLTest_AssertPass("SDL_SetHint(SDL_HINT_LOGGING, \"debug\")"); - { - EnableTestLog(&count); - SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG, "test"); - DisableTestLog(); - SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG, \"test\")"); - SDLTest_AssertCheck(count == 1, "Check result value, expected: 1, got: %d", count); - - EnableTestLog(&count); - SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_VERBOSE, "test"); - DisableTestLog(); - SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_VERBOSE, \"test\")"); - SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count); - } - - SDL_SetHint(SDL_HINT_LOGGING, "system=debug"); - SDLTest_AssertPass("SDL_SetHint(SDL_HINT_LOGGING, \"system=debug\")"); - { - EnableTestLog(&count); - SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG, "test"); - DisableTestLog(); - SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG, \"test\")"); - SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count); - - EnableTestLog(&count); - SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_DEBUG, "test"); - DisableTestLog(); - SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_DEBUG, \"test\")"); - SDLTest_AssertCheck(count == 1, "Check result value, expected: 1, got: %d", count); - - EnableTestLog(&count); - SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_VERBOSE, "test"); - DisableTestLog(); - SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_VERBOSE, \"test\")"); - SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count); - } - - SDL_SetHint(SDL_HINT_LOGGING, "app=warn,system=debug,assert=quiet,*=info"); - SDLTest_AssertPass("SDL_SetHint(SDL_HINT_LOGGING, \"app=warn,system=debug,assert=quiet,*=info\")"); - { - EnableTestLog(&count); - SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "test"); - DisableTestLog(); - SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, \"test\")"); - SDLTest_AssertCheck(count == 1, "Check result value, expected: 1, got: %d", count); - - EnableTestLog(&count); - SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "test"); - DisableTestLog(); - SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, \"test\")"); - SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count); - - EnableTestLog(&count); - SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_DEBUG, "test"); - DisableTestLog(); - SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_DEBUG, \"test\")"); - SDLTest_AssertCheck(count == 1, "Check result value, expected: 1, got: %d", count); - - EnableTestLog(&count); - SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_VERBOSE, "test"); - DisableTestLog(); - SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_VERBOSE, \"test\")"); - SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count); - - EnableTestLog(&count); - SDL_LogMessage(SDL_LOG_CATEGORY_ASSERT, SDL_LOG_PRIORITY_CRITICAL, "test"); - DisableTestLog(); - SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_ASSERT, SDL_LOG_PRIORITY_CRITICAL, \"test\")"); - SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count); - - EnableTestLog(&count); - SDL_LogMessage(SDL_LOG_CATEGORY_CUSTOM, SDL_LOG_PRIORITY_INFO, "test"); - DisableTestLog(); - SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_CUSTOM, SDL_LOG_PRIORITY_INFO, \"test\")"); - SDLTest_AssertCheck(count == 1, "Check result value, expected: 1, got: %d", count); - - EnableTestLog(&count); - SDL_LogMessage(SDL_LOG_CATEGORY_CUSTOM, SDL_LOG_PRIORITY_DEBUG, "test"); - DisableTestLog(); - SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_CUSTOM, SDL_LOG_PRIORITY_DEBUG, \"test\")"); - SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count); - - } - - SDL_SetHint(SDL_HINT_LOGGING, "0=4,3=2,2=0,*=3"); - SDLTest_AssertPass("SDL_SetHint(SDL_HINT_LOGGING, \"0=4,3=2,2=0,*=3\")"); - { - EnableTestLog(&count); - SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "test"); - DisableTestLog(); - SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, \"test\")"); - SDLTest_AssertCheck(count == 1, "Check result value, expected: 1, got: %d", count); - - EnableTestLog(&count); - SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "test"); - DisableTestLog(); - SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, \"test\")"); - SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count); - - EnableTestLog(&count); - SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_DEBUG, "test"); - DisableTestLog(); - SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_DEBUG, \"test\")"); - SDLTest_AssertCheck(count == 1, "Check result value, expected: 1, got: %d", count); - - EnableTestLog(&count); - SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_VERBOSE, "test"); - DisableTestLog(); - SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_PRIORITY_VERBOSE, \"test\")"); - SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count); - - EnableTestLog(&count); - SDL_LogMessage(SDL_LOG_CATEGORY_ASSERT, SDL_LOG_PRIORITY_CRITICAL, "test"); - DisableTestLog(); - SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_ASSERT, SDL_LOG_PRIORITY_CRITICAL, \"test\")"); - SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count); - - EnableTestLog(&count); - SDL_LogMessage(SDL_LOG_CATEGORY_CUSTOM, SDL_LOG_PRIORITY_INFO, "test"); - DisableTestLog(); - SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_CUSTOM, SDL_LOG_PRIORITY_INFO, \"test\")"); - SDLTest_AssertCheck(count == 1, "Check result value, expected: 1, got: %d", count); - - EnableTestLog(&count); - SDL_LogMessage(SDL_LOG_CATEGORY_CUSTOM, SDL_LOG_PRIORITY_DEBUG, "test"); - DisableTestLog(); - SDLTest_AssertPass("SDL_LogMessage(SDL_LOG_CATEGORY_CUSTOM, SDL_LOG_PRIORITY_DEBUG, \"test\")"); - SDLTest_AssertCheck(count == 0, "Check result value, expected: 0, got: %d", count); - - } - - return TEST_COMPLETED; -} - -/* ================= Test References ================== */ - -/* Log test cases */ -static const SDLTest_TestCaseReference logTestHint = { - (SDLTest_TestCaseFp)log_testHint, "log_testHint", "Check SDL_HINT_LOGGING functionality", TEST_ENABLED -}; - -/* Sequence of Log test cases */ -static const SDLTest_TestCaseReference *logTests[] = { - &logTestHint, NULL -}; - -/* Timer test suite (global) */ -SDLTest_TestSuiteReference logTestSuite = { - "Log", - NULL, - logTests, - NULL -}; diff --git a/libs/SDL2/test/testautomation_main.c b/libs/SDL2/test/testautomation_main.c index 78572d1a432c8e5ede6da0b600eaf82b1d9e4c94..ed72e0d950b6cef988091f12083ca4468d5fbcbe 100644 --- a/libs/SDL2/test/testautomation_main.c +++ b/libs/SDL2/test/testautomation_main.c @@ -9,6 +9,34 @@ #include "SDL.h" #include "SDL_test.h" +/* ! + * \brief Tests SDL_Init() and SDL_Quit() of Joystick and Haptic subsystems + * \sa + * http://wiki.libsdl.org/SDL_Init + * http://wiki.libsdl.org/SDL_Quit + */ +static int main_testInitQuitJoystickHaptic(void *arg) +{ +#if defined SDL_JOYSTICK_DISABLED || defined SDL_HAPTIC_DISABLED + return TEST_SKIPPED; +#else + int enabled_subsystems; + int initialized_subsystems = SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC; + + SDLTest_AssertCheck(SDL_Init(initialized_subsystems) == 0, "SDL_Init multiple systems."); + + enabled_subsystems = SDL_WasInit(initialized_subsystems); + SDLTest_AssertCheck(enabled_subsystems == initialized_subsystems, "SDL_WasInit(SDL_INIT_EVERYTHING) contains all systems (%i)", enabled_subsystems); + + SDL_Quit(); + + enabled_subsystems = SDL_WasInit(initialized_subsystems); + SDLTest_AssertCheck(enabled_subsystems == 0, "SDL_Quit should shut down everything (%i)", enabled_subsystems); + + return TEST_COMPLETED; +#endif +} + /* ! * \brief Tests SDL_InitSubSystem() and SDL_QuitSubSystem() * \sa @@ -126,18 +154,22 @@ main_testSetError(void *arg) #endif static const SDLTest_TestCaseReference mainTest1 = { - (SDLTest_TestCaseFp)main_testInitQuitSubSystem, "main_testInitQuitSubSystem", "Tests SDL_InitSubSystem/QuitSubSystem", TEST_ENABLED + (SDLTest_TestCaseFp)main_testInitQuitJoystickHaptic, "main_testInitQuitJoystickHaptic", "Tests SDL_Init/Quit of Joystick and Haptic subsystem", TEST_ENABLED }; static const SDLTest_TestCaseReference mainTest2 = { - (SDLTest_TestCaseFp)main_testImpliedJoystickInit, "main_testImpliedJoystickInit", "Tests that init for gamecontroller properly implies joystick", TEST_ENABLED + (SDLTest_TestCaseFp)main_testInitQuitSubSystem, "main_testInitQuitSubSystem", "Tests SDL_InitSubSystem/QuitSubSystem", TEST_ENABLED }; static const SDLTest_TestCaseReference mainTest3 = { - (SDLTest_TestCaseFp)main_testImpliedJoystickQuit, "main_testImpliedJoystickQuit", "Tests that quit for gamecontroller doesn't quit joystick if you inited it explicitly", TEST_ENABLED + (SDLTest_TestCaseFp)main_testImpliedJoystickInit, "main_testImpliedJoystickInit", "Tests that init for gamecontroller properly implies joystick", TEST_ENABLED }; static const SDLTest_TestCaseReference mainTest4 = { + (SDLTest_TestCaseFp)main_testImpliedJoystickQuit, "main_testImpliedJoystickQuit", "Tests that quit for gamecontroller doesn't quit joystick if you inited it explicitly", TEST_ENABLED +}; + +static const SDLTest_TestCaseReference mainTest5 = { (SDLTest_TestCaseFp)main_testSetError, "main_testSetError", "Tests that SDL_SetError() handles arbitrarily large strings", TEST_ENABLED }; @@ -147,6 +179,7 @@ static const SDLTest_TestCaseReference *mainTests[] = { &mainTest2, &mainTest3, &mainTest4, + &mainTest5, NULL }; @@ -157,3 +190,5 @@ SDLTest_TestSuiteReference mainTestSuite = { mainTests, NULL }; + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/libs/SDL2/test/testautomation_math.c b/libs/SDL2/test/testautomation_math.c index ef9b40b3d32d1633720466e31b6f673151624688..87637c01db69bca39685c0d8543d3791cf4ca87f 100644 --- a/libs/SDL2/test/testautomation_math.c +++ b/libs/SDL2/test/testautomation_math.c @@ -49,12 +49,6 @@ typedef struct double expected; } dd_to_d; -#define DD_TO_D_CASE(IDX, X, Y, E) do { \ - cases[IDX].x_input = (X); \ - cases[IDX].y_input = (Y); \ - cases[IDX].expected = (E); \ - } while (0) - /* NB: You cannot create an array of these structures containing INFINITY or NAN. On platforms such as OS/2, they are defined as 'extern const double' making them @@ -70,10 +64,10 @@ typedef double(SDLCALL *dd_to_d_func)(double, double); * \brief Runs all the cases on a given function with a signature double -> double. * The result is expected to be exact. * - * \param func_name a printable name for the tested function. - * \param func the function to call. - * \param cases an array of all the cases. - * \param cases_size the size of the cases array. + * \param func_name, a printable name for the tested function. + * \param func, the function to call. + * \param cases, an array of all the cases. + * \param cases_size, the size of the cases array. */ static int helper_dtod(const char *func_name, d_to_d_func func, @@ -82,7 +76,7 @@ helper_dtod(const char *func_name, d_to_d_func func, Uint32 i; for (i = 0; i < cases_size; i++) { const double result = func(cases[i].input); - SDLTest_AssertCheck((result - cases[i].expected) < FLT_EPSILON, + SDLTest_AssertCheck(result == cases[i].expected, "%s(%f), expected %f, got %f", func_name, cases[i].input, @@ -96,10 +90,10 @@ helper_dtod(const char *func_name, d_to_d_func func, * \brief Runs all the cases on a given function with a signature double -> double. * Checks if the result between expected +/- EPSILON. * - * \param func_name a printable name for the tested function. - * \param func the function to call. - * \param cases an array of all the cases. - * \param cases_size the size of the cases array. + * \param func_name, a printable name for the tested function. + * \param func, the function to call. + * \param cases, an array of all the cases. + * \param cases_size, the size of the cases array. */ static int helper_dtod_inexact(const char *func_name, d_to_d_func func, @@ -108,15 +102,8 @@ helper_dtod_inexact(const char *func_name, d_to_d_func func, Uint32 i; for (i = 0; i < cases_size; i++) { const double result = func(cases[i].input); - double diff = result - cases[i].expected; - double max_err = (cases[i].expected + 1.) * EPSILON; - if (diff < 0) { - diff = -diff; - } - if (max_err < 0) { - max_err = -max_err; - } - SDLTest_AssertCheck(diff <= max_err, + SDLTest_AssertCheck(result >= cases[i].expected - EPSILON && + result <= cases[i].expected + EPSILON, "%s(%f), expected [%f,%f], got %f", func_name, cases[i].input, @@ -132,10 +119,10 @@ helper_dtod_inexact(const char *func_name, d_to_d_func func, * \brief Runs all the cases on a given function with a signature * (double, double) -> double. The result is expected to be exact. * - * \param func_name a printable name for the tested function. - * \param func the function to call. - * \param cases an array of all the cases. - * \param cases_size the size of the cases array. + * \param func_name, a printable name for the tested function. + * \param func, the function to call. + * \param cases, an array of all the cases. + * \param cases_size, the size of the cases array. */ static int helper_ddtod(const char *func_name, dd_to_d_func func, @@ -144,8 +131,6 @@ helper_ddtod(const char *func_name, dd_to_d_func func, Uint32 i; for (i = 0; i < cases_size; i++) { const double result = func(cases[i].x_input, cases[i].y_input); - /* By using the result as input, the compiler is less likely to use higher precision floating point number */ - (void)SDL_sin(result); SDLTest_AssertCheck(result == cases[i].expected, "%s(%f,%f), expected %f, got %f", func_name, @@ -160,10 +145,10 @@ helper_ddtod(const char *func_name, dd_to_d_func func, * \brief Runs all the cases on a given function with a signature * (double, double) -> double. Checks if the result between expected +/- EPSILON. * - * \param func_name a printable name for the tested function. - * \param func the function to call. - * \param cases an array of all the cases. - * \param cases_size the size of the cases array. + * \param func_name, a printable name for the tested function. + * \param func, the function to call. + * \param cases, an array of all the cases. + * \param cases_size, the size of the cases array. */ static int helper_ddtod_inexact(const char *func_name, dd_to_d_func func, @@ -172,16 +157,8 @@ helper_ddtod_inexact(const char *func_name, dd_to_d_func func, Uint32 i; for (i = 0; i < cases_size; i++) { const double result = func(cases[i].x_input, cases[i].y_input); - double diff = result - cases[i].expected; - double max_err = (cases[i].expected + 1.) * EPSILON; - if (diff < 0) { - diff = -diff; - } - if (max_err < 0) { - max_err = -max_err; - } - - SDLTest_AssertCheck(diff <= max_err, + SDLTest_AssertCheck(result >= cases[i].expected - EPSILON && + result <= cases[i].expected + EPSILON, "%s(%f,%f), expected [%f,%f], got %f", func_name, cases[i].x_input, cases[i].y_input, @@ -199,8 +176,8 @@ helper_ddtod_inexact(const char *func_name, dd_to_d_func func, * This function is only meant to test functions that returns the input value if it is * integral: f(x) -> x for x in N. * - * \param func_name a printable name for the tested function. - * \param func the function to call. + * \param func_name, a printable name for the tested function. + * \param func, the function to call. */ static int helper_range(const char *func_name, d_to_d_func func) @@ -1161,7 +1138,7 @@ log_baseCases(void *args) 1.0, 0.0, result); result = SDL_log(EULER); - SDLTest_AssertCheck((result - 1.) < FLT_EPSILON, + SDLTest_AssertCheck(1.0 == result, "Log(%f), expected %f, got %f", EULER, 1.0, result); @@ -1669,16 +1646,14 @@ static int pow_regularCases(void *args) { const dd_to_d regular_cases[] = { -#if 0 /* These tests fail when using the Mingw C runtime, we'll disable them for now */ { -391.25, -2.0, 0.00000653267870448815438463212659780943170062528224661946296691894531250 }, { -72.3, 12.0, 20401381050275984310272.0 }, -#endif { -5.0, 3.0, -125.0 }, { 3.0, 2.5, 15.58845726811989607085706666111946105957031250 }, { 39.23, -1.5, 0.0040697950366865498147972424192175822099670767784118652343750 }, { 478.972, 12.125, 315326359630449587856007411793920.0 } }; - return helper_ddtod_inexact("Pow", SDL_pow, regular_cases, SDL_arraysize(regular_cases)); + return helper_ddtod("Pow", SDL_pow, regular_cases, SDL_arraysize(regular_cases)); } /** @@ -2006,24 +1981,24 @@ static int cos_precisionTest(void *args) { const d_to_d precision_cases[] = { - { M_PI * 1.0 / 10.0, 0.9510565162951535 }, - { M_PI * 2.0 / 10.0, 0.8090169943749475 }, - { M_PI * 3.0 / 10.0, 0.5877852522924731 }, - { M_PI * 4.0 / 10.0, 0.30901699437494745 }, + { M_PI * 1.0 / 10.0, 0.9510565162 }, + { M_PI * 2.0 / 10.0, 0.8090169943 }, + { M_PI * 3.0 / 10.0, 0.5877852522 }, + { M_PI * 4.0 / 10.0, 0.3090169943 }, { M_PI * 5.0 / 10.0, 0.0 }, - { M_PI * 6.0 / 10.0, -0.30901699437494734 }, - { M_PI * 7.0 / 10.0, -0.587785252292473 }, - { M_PI * 8.0 / 10.0, -0.8090169943749473 }, - { M_PI * 9.0 / 10.0, -0.9510565162951535 }, - { M_PI * -1.0 / 10.0, 0.9510565162951535 }, - { M_PI * -2.0 / 10.0, 0.8090169943749475 }, - { M_PI * -3.0 / 10.0, 0.5877852522924731 }, - { M_PI * -4.0 / 10.0, 0.30901699437494745 }, + { M_PI * 6.0 / 10.0, -0.3090169943 }, + { M_PI * 7.0 / 10.0, -0.5877852522 }, + { M_PI * 8.0 / 10.0, -0.8090169943 }, + { M_PI * 9.0 / 10.0, -0.9510565162 }, + { M_PI * -1.0 / 10.0, 0.9510565162 }, + { M_PI * -2.0 / 10.0, 0.8090169943 }, + { M_PI * -3.0 / 10.0, 0.5877852522 }, + { M_PI * -4.0 / 10.0, 0.3090169943 }, { M_PI * -5.0 / 10.0, 0.0 }, - { M_PI * -6.0 / 10.0, -0.30901699437494734 }, - { M_PI * -7.0 / 10.0, -0.587785252292473 }, - { M_PI * -8.0 / 10.0, -0.8090169943749473 }, - { M_PI * -9.0 / 10.0, -0.9510565162951535 } + { M_PI * -6.0 / 10.0, -0.3090169943 }, + { M_PI * -7.0 / 10.0, -0.5877852522 }, + { M_PI * -8.0 / 10.0, -0.8090169943 }, + { M_PI * -9.0 / 10.0, -0.9510565162 } }; return helper_dtod_inexact("Cos", SDL_cos, precision_cases, SDL_arraysize(precision_cases)); } @@ -2124,23 +2099,23 @@ static int sin_precisionTest(void *args) { const d_to_d precision_cases[] = { - { M_PI * 1.0 / 10.0, 0.3090169943749474 }, - { M_PI * 2.0 / 10.0, 0.5877852522924731 }, - { M_PI * 3.0 / 10.0, 0.8090169943749475 }, - { M_PI * 4.0 / 10.0, 0.9510565162951535 }, - { M_PI * 6.0 / 10.0, 0.9510565162951536 }, - { M_PI * 7.0 / 10.0, 0.8090169943749475 }, - { M_PI * 8.0 / 10.0, 0.5877852522924732 }, - { M_PI * 9.0 / 10.0, 0.3090169943749475 }, + { M_PI * 1.0 / 10.0, 0.3090169943 }, + { M_PI * 2.0 / 10.0, 0.5877852522 }, + { M_PI * 3.0 / 10.0, 0.8090169943 }, + { M_PI * 4.0 / 10.0, 0.9510565162 }, + { M_PI * 6.0 / 10.0, 0.9510565162 }, + { M_PI * 7.0 / 10.0, 0.8090169943 }, + { M_PI * 8.0 / 10.0, 0.5877852522 }, + { M_PI * 9.0 / 10.0, 0.3090169943 }, { M_PI, 0.0 }, - { M_PI * -1.0 / 10.0, -0.3090169943749474 }, - { M_PI * -2.0 / 10.0, -0.5877852522924731 }, - { M_PI * -3.0 / 10.0, -0.8090169943749475 }, - { M_PI * -4.0 / 10.0, -0.9510565162951535 }, - { M_PI * -6.0 / 10.0, -0.9510565162951536 }, - { M_PI * -7.0 / 10.0, -0.8090169943749475 }, - { M_PI * -8.0 / 10.0, -0.5877852522924732 }, - { M_PI * -9.0 / 10.0, -0.3090169943749475 }, + { M_PI * -1.0 / 10.0, -0.3090169943 }, + { M_PI * -2.0 / 10.0, -0.5877852522 }, + { M_PI * -3.0 / 10.0, -0.8090169943 }, + { M_PI * -4.0 / 10.0, -0.9510565162 }, + { M_PI * -6.0 / 10.0, -0.9510565162 }, + { M_PI * -7.0 / 10.0, -0.8090169943 }, + { M_PI * -8.0 / 10.0, -0.5877852522 }, + { M_PI * -9.0 / 10.0, -0.3090169943 }, { -M_PI, 0.0 }, }; return helper_dtod_inexact("Sin", SDL_sin, precision_cases, SDL_arraysize(precision_cases)); @@ -2240,26 +2215,26 @@ static int tan_precisionTest(void *args) { const d_to_d precision_cases[] = { - { M_PI * 1.0 / 11.0, 0.29362649293836673 }, - { M_PI * 2.0 / 11.0, 0.642660977168331 }, - { M_PI * 3.0 / 11.0, 1.1540615205330094 }, - { M_PI * 4.0 / 11.0, 2.189694562989681 }, - { M_PI * 5.0 / 11.0, 6.9551527717734745 }, - { M_PI * 6.0 / 11.0, -6.955152771773481 }, - { M_PI * 7.0 / 11.0, -2.189694562989682 }, - { M_PI * 8.0 / 11.0, -1.1540615205330096 }, - { M_PI * 9.0 / 11.0, -0.6426609771683314 }, - { M_PI * 10.0 / 11.0, -0.2936264929383667 }, - { M_PI * -1.0 / 11.0, -0.29362649293836673 }, - { M_PI * -2.0 / 11.0, -0.642660977168331 }, - { M_PI * -3.0 / 11.0, -1.1540615205330094 }, - { M_PI * -4.0 / 11.0, -2.189694562989681 }, - { M_PI * -5.0 / 11.0, -6.9551527717734745 }, - { M_PI * -6.0 / 11.0, 6.955152771773481 }, - { M_PI * -7.0 / 11.0, 2.189694562989682 }, - { M_PI * -8.0 / 11.0, 1.1540615205330096 }, - { M_PI * -9.0 / 11.0, 0.6426609771683314 }, - { M_PI * -10.0 / 11.0, 0.2936264929383667 } + { M_PI * 1.0 / 11.0, 0.2936264929 }, + { M_PI * 2.0 / 11.0, 0.6426609771 }, + { M_PI * 3.0 / 11.0, 1.1540615205 }, + { M_PI * 4.0 / 11.0, 2.1896945629 }, + { M_PI * 5.0 / 11.0, 6.9551527717 }, + { M_PI * 6.0 / 11.0, -6.9551527717 }, + { M_PI * 7.0 / 11.0, -2.1896945629 }, + { M_PI * 8.0 / 11.0, -1.1540615205 }, + { M_PI * 9.0 / 11.0, -0.6426609771 }, + { M_PI * 10.0 / 11.0, -0.2936264929 }, + { M_PI * -1.0 / 11.0, -0.2936264929 }, + { M_PI * -2.0 / 11.0, -0.6426609771 }, + { M_PI * -3.0 / 11.0, -1.1540615205 }, + { M_PI * -4.0 / 11.0, -2.1896945629 }, + { M_PI * -5.0 / 11.0, -6.9551527717 }, + { M_PI * -6.0 / 11.0, 6.9551527717 }, + { M_PI * -7.0 / 11.0, 2.1896945629 }, + { M_PI * -8.0 / 11.0, 1.1540615205 }, + { M_PI * -9.0 / 11.0, 0.6426609771 }, + { M_PI * -10.0 / 11.0, 0.2936264929 } }; return helper_dtod_inexact("Tan", SDL_tan, precision_cases, SDL_arraysize(precision_cases)); } @@ -2281,7 +2256,7 @@ acos_limitCases(void *args) 1.0, 0.0, result); result = SDL_acos(-1.0); - SDLTest_AssertCheck(SDL_fabs(M_PI - result) <= EPSILON, + SDLTest_AssertCheck(M_PI == result, "Acos(%f), expected %f, got %f", -1.0, M_PI, result); @@ -2368,12 +2343,12 @@ asin_limitCases(void *args) double result; result = SDL_asin(1.0); - SDLTest_AssertCheck(SDL_fabs(M_PI / 2.0 - result) <= EPSILON, + SDLTest_AssertCheck(M_PI / 2.0 == result, "Asin(%f), expected %f, got %f", 1.0, M_PI / 2.0, result); result = SDL_asin(-1.0); - SDLTest_AssertCheck(SDL_fabs(-M_PI / 2.0 - result) <= EPSILON, + SDLTest_AssertCheck(-M_PI / 2.0 == result, "Asin(%f), expected %f, got %f", -1.0, -M_PI / 2.0, result); @@ -2424,26 +2399,26 @@ static int asin_precisionTest(void *args) { const d_to_d precision_cases[] = { - { 0.9, 1.1197695149986342 }, - { 0.8, 0.9272952180016123 }, - { 0.7, 0.775397496610753 }, - { 0.6, 0.6435011087932844 }, - { 0.5, 0.5235987755982989 }, - { 0.4, 0.41151684606748806 }, - { 0.3, 0.3046926540153976 }, - { 0.2, 0.20135792079033074 }, - { 0.1, 0.10016742116155977 }, + { 0.9, 1.1197695149 }, + { 0.8, 0.9272952180 }, + { 0.7, 0.7753974966 }, + { 0.6, 0.6435011087 }, + { 0.5, 0.5235987755 }, + { 0.4, 0.4115168460 }, + { 0.3, 0.3046926540 }, + { 0.2, 0.2013579207 }, + { 0.1, 0.1001674211 }, { 0.0, 0.0 }, { -0.0, -0.0 }, - { -0.1, -0.10016742116155977 }, - { -0.2, -0.20135792079033074 }, - { -0.3, -0.3046926540153976 }, - { -0.4, -0.41151684606748806 }, - { -0.5, -0.5235987755982989 }, - { -0.6, -0.6435011087932844 }, - { -0.7, -0.775397496610753 }, - { -0.8, -0.9272952180016123 }, - { -0.9, -1.1197695149986342 } + { -0.1, -0.1001674211 }, + { -0.2, -0.2013579207 }, + { -0.3, -0.3046926540 }, + { -0.4, -0.4115168460 }, + { -0.5, -0.5235987755 }, + { -0.6, -0.6435011087 }, + { -0.7, -0.7753974966 }, + { -0.8, -0.9272952180 }, + { -0.9, -1.1197695149 } }; return helper_dtod_inexact("Asin", SDL_asin, precision_cases, SDL_arraysize(precision_cases)); } @@ -2518,24 +2493,24 @@ static int atan_precisionTest(void *args) { const d_to_d precision_cases[] = { - { 6.313751514675041, 1.413716694115407 }, - { 3.0776835371752527, 1.2566370614359172 }, - { 1.9626105055051504, 1.0995574287564276 }, - { 1.3763819204711734, 0.9424777960769379 }, - { 1.0, 0.7853981633974483 }, - { 0.7265425280053609, 0.6283185307179586 }, - { 0.5095254494944288, 0.47123889803846897 }, - { 0.3249196962329063, 0.3141592653589793 }, - { 0.15838444032453627, 0.15707963267948966 }, - { -0.15838444032453627, -0.15707963267948966 }, - { -0.3249196962329063, -0.3141592653589793 }, - { -0.5095254494944288, -0.47123889803846897 }, - { -0.7265425280053609, -0.6283185307179586 }, - { -1.0, -0.7853981633974483 }, - { -1.3763819204711734, -0.9424777960769379 }, - { -1.9626105055051504, -1.0995574287564276 }, - { -3.0776835371752527, -1.2566370614359172 }, - { -6.313751514675041, -1.413716694115407 }, + { 6.313751514675041, 1.4137166941 }, + { 3.0776835371752527, 1.2566370614 }, + { 1.9626105055051504, 1.0995574287 }, + { 1.3763819204711734, 0.9424777960 }, + { 1.0, 0.7853981633 }, + { 0.7265425280053609, 0.6283185307 }, + { 0.5095254494944288, 0.4712388980 }, + { 0.3249196962329063, 0.3141592653 }, + { 0.15838444032453627, 0.1570796326 }, + { -0.15838444032453627, -0.1570796326 }, + { -0.3249196962329063, -0.3141592653 }, + { -0.5095254494944288, -0.4712388980 }, + { -0.7265425280053609, -0.6283185307 }, + { -1.0, -0.7853981633 }, + { -1.3763819204711734, -0.9424777960 }, + { -1.9626105055051504, -1.0995574287 }, + { -3.0776835371752527, -1.2566370614 }, + { -6.313751514675041, -1.4137166941 }, }; return helper_dtod_inexact("Atan", SDL_atan, precision_cases, SDL_arraysize(precision_cases)); } @@ -2560,7 +2535,7 @@ atan2_bothZeroCases(void *args) { 0.0, -0.0, M_PI }, { -0.0, -0.0, -M_PI }, }; - return helper_ddtod_inexact("SDL_atan2", SDL_atan2, cases, SDL_arraysize(cases)); + return helper_ddtod("SDL_atan2", SDL_atan2, cases, SDL_arraysize(cases)); } /** @@ -2579,7 +2554,7 @@ atan2_yZeroCases(void *args) { -0.0, 1.0, -0.0 }, { -0.0, -1.0, -M_PI } }; - return helper_ddtod_inexact("SDL_atan2", SDL_atan2, cases, SDL_arraysize(cases)); + return helper_ddtod("SDL_atan2", SDL_atan2, cases, SDL_arraysize(cases)); } /** @@ -2595,7 +2570,7 @@ atan2_xZeroCases(void *args) { 1.0, -0.0, M_PI / 2.0 }, { -1.0, -0.0, -M_PI / 2.0 } }; - return helper_ddtod_inexact("SDL_atan2", SDL_atan2, cases, SDL_arraysize(cases)); + return helper_ddtod("SDL_atan2", SDL_atan2, cases, SDL_arraysize(cases)); } /* Infinity cases */ @@ -2611,12 +2586,29 @@ atan2_xZeroCases(void *args) static int atan2_bothInfCases(void *args) { - dd_to_d cases[4]; - DD_TO_D_CASE(0, INFINITY, INFINITY, 1.0 * M_PI / 4.0); - DD_TO_D_CASE(1, INFINITY, -INFINITY, 3.0 * M_PI / 4.0); - DD_TO_D_CASE(2, -INFINITY, INFINITY, -1.0 * M_PI / 4.0); - DD_TO_D_CASE(3, -INFINITY, -INFINITY, -3.0 * M_PI / 4.0); - return helper_ddtod("SDL_atan2(bothInfCases)", SDL_atan2, cases, SDL_arraysize(cases)); + double result; + + result = SDL_atan2(INFINITY, INFINITY); + SDLTest_AssertCheck(M_PI / 4.0 == result, + "Atan2(%f,%f), expected %f, got %f", + INFINITY, INFINITY, M_PI / 4.0, result); + + result = SDL_atan2(INFINITY, -INFINITY); + SDLTest_AssertCheck(3.0 * M_PI / 4.0 == result, + "Atan2(%f,%f), expected %f, got %f", + INFINITY, -INFINITY, 3.0 * M_PI / 4.0, result); + + result = SDL_atan2(-INFINITY, INFINITY); + SDLTest_AssertCheck(-M_PI / 4.0 == result, + "Atan2(%f,%f), expected %f, got %f", + -INFINITY, INFINITY, -M_PI / 4.0, result); + + result = SDL_atan2(-INFINITY, -INFINITY); + SDLTest_AssertCheck(-3.0 * M_PI / 4.0 == result, + "Atan2(%f,%f), expected %f, got %f", + -INFINITY, -INFINITY, -3.0 * M_PI / 4.0, result); + + return TEST_COMPLETED; } /** @@ -2626,12 +2618,29 @@ atan2_bothInfCases(void *args) static int atan2_yInfCases(void *args) { - dd_to_d cases[4]; - DD_TO_D_CASE(0, INFINITY, 1.0, 1.0 * M_PI / 2.0); - DD_TO_D_CASE(1, INFINITY, -1.0, 1.0 * M_PI / 2.0); - DD_TO_D_CASE(2, -INFINITY, 1.0, -1.0 * M_PI / 2.0); - DD_TO_D_CASE(3, -INFINITY, -1.0, -1.0 * M_PI / 2.0); - return helper_ddtod("SDL_atan2(atan2_yInfCases)", SDL_atan2, cases, SDL_arraysize(cases)); + double result; + + result = SDL_atan2(INFINITY, 1.0); + SDLTest_AssertCheck(M_PI / 2.0 == result, + "Atan2(%f,%f), expected %f, got %f", + INFINITY, 1.0, M_PI / 2.0, result); + + result = SDL_atan2(INFINITY, -1.0); + SDLTest_AssertCheck(M_PI / 2.0 == result, + "Atan2(%f,%f), expected %f, got %f", + INFINITY, -1.0, M_PI / 2.0, result); + + result = SDL_atan2(-INFINITY, 1.0); + SDLTest_AssertCheck(-M_PI / 2.0 == result, + "Atan2(%f,%f), expected %f, got %f", + -INFINITY, 1.0, -M_PI / 2.0, result); + + result = SDL_atan2(-INFINITY, -1.0); + SDLTest_AssertCheck(-M_PI / 2.0 == result, + "Atan2(%f,%f), expected %f, got %f", + -INFINITY, -1.0, -M_PI / 2.0, result); + + return TEST_COMPLETED; } /** @@ -2643,12 +2652,29 @@ atan2_yInfCases(void *args) static int atan2_xInfCases(void *args) { - dd_to_d cases[4]; - DD_TO_D_CASE(0, 1.0, INFINITY, 0.0); - DD_TO_D_CASE(1, -1.0, INFINITY, -0.0); - DD_TO_D_CASE(2, 1.0, -INFINITY, M_PI); - DD_TO_D_CASE(3, -1.0, -INFINITY, -M_PI); - return helper_ddtod("atan2_xInfCases(atan2_yInfCases)", SDL_atan2, cases, SDL_arraysize(cases)); + double result; + + result = SDL_atan2(1.0, INFINITY); + SDLTest_AssertCheck(0.0 == result, + "Atan2(%f,%f), expected %f, got %f", + 1.0, INFINITY, 0.0, result); + + result = SDL_atan2(-1.0, INFINITY); + SDLTest_AssertCheck(-0.0 == result, + "Atan2(%f,%f), expected %f, got %f", + -1.0, INFINITY, -0.0, result); + + result = SDL_atan2(1.0, -INFINITY); + SDLTest_AssertCheck(M_PI == result, + "Atan2(%f,%f), expected %f, got %f", + 1.0, -INFINITY, M_PI, result); + + result = SDL_atan2(-1.0, -INFINITY); + SDLTest_AssertCheck(-M_PI == result, + "Atan2(%f,%f), expected %f, got %f", + -1.0, -INFINITY, -M_PI, result); + + return TEST_COMPLETED; } /* Miscelanious cases */ diff --git a/libs/SDL2/test/testautomation_mouse.c b/libs/SDL2/test/testautomation_mouse.c index 19b1a9f58ca74fd19151fe289ff7becd89f78053..22a437801814c435d6aacf2cd0949424dd0509be 100644 --- a/libs/SDL2/test/testautomation_mouse.c +++ b/libs/SDL2/test/testautomation_mouse.c @@ -423,7 +423,7 @@ SDL_Window *_createMouseSuiteTestWindow() */ void _destroyMouseSuiteTestWindow(SDL_Window *window) { - if (window) { + if (window != NULL) { SDL_DestroyWindow(window); window = NULL; SDLTest_AssertPass("SDL_DestroyWindow()"); @@ -458,7 +458,7 @@ int mouse_warpMouseInWindow(void *arg) yPositions[5] = h + 1; /* Create test window */ window = _createMouseSuiteTestWindow(); - if (!window) { + if (window == NULL) { return TEST_ABORTED; } @@ -503,7 +503,6 @@ int mouse_getMouseFocus(void *arg) int x, y; SDL_Window *window; SDL_Window *focusWindow; - const SDL_bool video_driver_is_wayland = !SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland"); /* Get focus - focus non-deterministic */ focusWindow = SDL_GetMouseFocus(); @@ -511,37 +510,32 @@ int mouse_getMouseFocus(void *arg) /* Create test window */ window = _createMouseSuiteTestWindow(); - if (!window) { + if (window == NULL) { return TEST_ABORTED; } - /* Wayland explicitly disallows warping the mouse pointer, so this test must be skipped. */ - if (!video_driver_is_wayland) { - /* Mouse to random position inside window */ - x = SDLTest_RandomIntegerInRange(1, w - 1); - y = SDLTest_RandomIntegerInRange(1, h - 1); - SDL_WarpMouseInWindow(window, x, y); - SDLTest_AssertPass("SDL_WarpMouseInWindow(...,%i,%i)", x, y); - - /* Pump events to update focus state */ - SDL_Delay(100); - SDL_PumpEvents(); - SDLTest_AssertPass("SDL_PumpEvents()"); - - /* Get focus with explicit window setup - focus deterministic */ - focusWindow = SDL_GetMouseFocus(); - SDLTest_AssertPass("SDL_GetMouseFocus()"); - SDLTest_AssertCheck(focusWindow != NULL, "Check returned window value is not NULL"); - SDLTest_AssertCheck(focusWindow == window, "Check returned window value is test window"); - - /* Mouse to random position outside window */ - x = SDLTest_RandomIntegerInRange(-9, -1); - y = SDLTest_RandomIntegerInRange(-9, -1); - SDL_WarpMouseInWindow(window, x, y); - SDLTest_AssertPass("SDL_WarpMouseInWindow(...,%i,%i)", x, y); - } else { - SDLTest_Log("Skipping mouse warp focus tests: Wayland does not support warping the mouse pointer"); - } + /* Mouse to random position inside window */ + x = SDLTest_RandomIntegerInRange(1, w - 1); + y = SDLTest_RandomIntegerInRange(1, h - 1); + SDL_WarpMouseInWindow(window, x, y); + SDLTest_AssertPass("SDL_WarpMouseInWindow(...,%i,%i)", x, y); + + /* Pump events to update focus state */ + SDL_Delay(100); + SDL_PumpEvents(); + SDLTest_AssertPass("SDL_PumpEvents()"); + + /* Get focus with explicit window setup - focus deterministic */ + focusWindow = SDL_GetMouseFocus(); + SDLTest_AssertPass("SDL_GetMouseFocus()"); + SDLTest_AssertCheck(focusWindow != NULL, "Check returned window value is not NULL"); + SDLTest_AssertCheck(focusWindow == window, "Check returned window value is test window"); + + /* Mouse to random position outside window */ + x = SDLTest_RandomIntegerInRange(-9, -1); + y = SDLTest_RandomIntegerInRange(-9, -1); + SDL_WarpMouseInWindow(window, x, y); + SDLTest_AssertPass("SDL_WarpMouseInWindow(...,%i,%i)", x, y); /* Clean up test window */ _destroyMouseSuiteTestWindow(window); diff --git a/libs/SDL2/test/testautomation_pixels.c b/libs/SDL2/test/testautomation_pixels.c index 12cf632490c757cb4d01cc4be5f5fb7821037052..d5440e5b4db47dc16bc46458096a054fad7df037 100644 --- a/libs/SDL2/test/testautomation_pixels.c +++ b/libs/SDL2/test/testautomation_pixels.c @@ -14,8 +14,6 @@ const int _numRGBPixelFormats = 31; Uint32 _RGBPixelFormats[] = { SDL_PIXELFORMAT_INDEX1LSB, SDL_PIXELFORMAT_INDEX1MSB, - SDL_PIXELFORMAT_INDEX2LSB, - SDL_PIXELFORMAT_INDEX2MSB, SDL_PIXELFORMAT_INDEX4LSB, SDL_PIXELFORMAT_INDEX4MSB, SDL_PIXELFORMAT_INDEX8, @@ -49,8 +47,6 @@ Uint32 _RGBPixelFormats[] = { const char *_RGBPixelFormatsVerbose[] = { "SDL_PIXELFORMAT_INDEX1LSB", "SDL_PIXELFORMAT_INDEX1MSB", - "SDL_PIXELFORMAT_INDEX2LSB", - "SDL_PIXELFORMAT_INDEX2MSB", "SDL_PIXELFORMAT_INDEX4LSB", "SDL_PIXELFORMAT_INDEX4MSB", "SDL_PIXELFORMAT_INDEX8", diff --git a/libs/SDL2/test/testautomation_platform.c b/libs/SDL2/test/testautomation_platform.c index bd2aabed68eab34137fbac4799093d15d26b86e1..ac85eef23a9b29ed992739f7e7dcb3488bf0901d 100644 --- a/libs/SDL2/test/testautomation_platform.c +++ b/libs/SDL2/test/testautomation_platform.c @@ -386,7 +386,7 @@ int platform_testSetErrorEmptyInput(void *arg) int platform_testSetErrorInvalidInput(void *arg) { int result; - const char *invalidError = ""; + const char *invalidError = NULL; const char *probeError = "Testing"; char *lastError; size_t len; diff --git a/libs/SDL2/test/testautomation_render.c b/libs/SDL2/test/testautomation_render.c index 45198a826ee1a775868371295ccdf9546062f9f3..74b96314609b1bda041a908d168d3d9f8e0c17cc 100644 --- a/libs/SDL2/test/testautomation_render.c +++ b/libs/SDL2/test/testautomation_render.c @@ -43,7 +43,6 @@ static int _isSupported(int code); void InitCreateRenderer(void *arg) { int posX = 100, posY = 100, width = 320, height = 240; - int renderer_flags = SDL_RENDERER_ACCELERATED; renderer = NULL; window = SDL_CreateWindow("render_testCreateRenderer", posX, posY, width, height, 0); SDLTest_AssertPass("SDL_CreateWindow()"); @@ -52,11 +51,7 @@ void InitCreateRenderer(void *arg) return; } - if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "dummy") == 0) { - renderer_flags = 0; - } - - renderer = SDL_CreateRenderer(window, -1, renderer_flags); + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); SDLTest_AssertPass("SDL_CreateRenderer()"); SDLTest_AssertCheck(renderer != NULL, "Check SDL_CreateRenderer result"); if (renderer == NULL) { @@ -70,13 +65,13 @@ void InitCreateRenderer(void *arg) */ void CleanupDestroyRenderer(void *arg) { - if (renderer) { + if (renderer != NULL) { SDL_DestroyRenderer(renderer); renderer = NULL; SDLTest_AssertPass("SDL_DestroyRenderer()"); } - if (window) { + if (window != NULL) { SDL_DestroyWindow(window); window = NULL; SDLTest_AssertPass("SDL_DestroyWindow"); @@ -943,12 +938,12 @@ _loadTestFace(void) SDL_Texture *tface; face = SDLTest_ImageFace(); - if (!face) { + if (face == NULL) { return NULL; } tface = SDL_CreateTextureFromSurface(renderer, face); - if (!tface) { + if (tface == NULL) { SDLTest_LogError("SDL_CreateTextureFromSurface() failed with error: %s", SDL_GetError()); } @@ -975,7 +970,7 @@ _hasTexColor(void) /* Get test face. */ tface = _loadTestFace(); - if (!tface) { + if (tface == NULL) { return 0; } @@ -1019,7 +1014,7 @@ _hasTexAlpha(void) /* Get test face. */ tface = _loadTestFace(); - if (!tface) { + if (tface == NULL) { return 0; } @@ -1048,7 +1043,7 @@ _hasTexAlpha(void) /** * @brief Compares screen pixels with image pixels. Helper function. * - * @param referenceSurface Image to compare against. + * @param s Image to compare against. * * \sa * http://wiki.libsdl.org/SDL_RenderReadPixels diff --git a/libs/SDL2/test/testautomation_stdlib.c b/libs/SDL2/test/testautomation_stdlib.c index ed9f13ea35d981f8e31f9496037423d82de995b8..a75e4570b5ea22999585bdc19409d0092cf9eb39 100644 --- a/libs/SDL2/test/testautomation_stdlib.c +++ b/libs/SDL2/test/testautomation_stdlib.c @@ -53,7 +53,7 @@ int stdlib_snprintf(void *arg) int result; int predicted; char text[1024]; - const char *expected, *expected2, *expected3, *expected4, *expected5; + const char *expected; size_t size; result = SDL_snprintf(text, sizeof(text), "%s", "foo"); @@ -175,61 +175,6 @@ int stdlib_snprintf(void *arg) SDLTest_AssertCheck(SDL_strcmp(text, expected) == 0, "Check text, expected: '%s', got: '%s'", expected, text); SDLTest_AssertCheck(result == 7, "Check result value, expected: 7, got: %d", result); - result = SDL_snprintf(text, sizeof(text), "%p", (void *)0x1234abcd); - expected = "0x1234abcd"; - expected2 = "1234ABCD"; - expected3 = "000000001234ABCD"; - expected4 = "1234abcd"; - expected5 = "000000001234abcd"; - SDLTest_AssertPass("Call to SDL_snprintf(text, sizeof(text), \"%%p\", 0x1234abcd)"); - SDLTest_AssertCheck(SDL_strcmp(text, expected) == 0 || - SDL_strcmp(text, expected2) == 0 || - SDL_strcmp(text, expected3) == 0 || - SDL_strcmp(text, expected4) == 0 || - SDL_strcmp(text, expected5) == 0, - "Check text, expected: '%s', got: '%s'", expected, text); - SDLTest_AssertCheck(result == SDL_strlen(expected) || - result == SDL_strlen(expected2) || - result == SDL_strlen(expected3) || - result == SDL_strlen(expected4) || - result == SDL_strlen(expected5), - "Check result value, expected: %d, got: %d", (int)SDL_strlen(expected), result); - - result = SDL_snprintf(text, sizeof(text), "A %p B", (void *)0x1234abcd); - expected = "A 0x1234abcd B"; - expected2 = "A 1234ABCD B"; - expected3 = "A 000000001234ABCD B"; - expected4 = "A 1234abcd B"; - expected5 = "A 000000001234abcd B"; - SDLTest_AssertPass("Call to SDL_snprintf(text, sizeof(text), \"A %%p B\", 0x1234abcd)"); - SDLTest_AssertCheck(SDL_strcmp(text, expected) == 0 || - SDL_strcmp(text, expected2) == 0 || - SDL_strcmp(text, expected3) == 0 || - SDL_strcmp(text, expected4) == 0 || - SDL_strcmp(text, expected5) == 0, - "Check text, expected: '%s', got: '%s'", expected, text); - SDLTest_AssertCheck(result == SDL_strlen(expected) || - result == SDL_strlen(expected2) || - result == SDL_strlen(expected3) || - result == SDL_strlen(expected4) || - result == SDL_strlen(expected5), - "Check result value, expected: %d, got: %d", (int)SDL_strlen(expected), result); - - if (sizeof(void *) >= 8) { - result = SDL_snprintf(text, sizeof(text), "%p", (void *)0x1ba07bddf60L); - expected = "0x1ba07bddf60"; - expected2 = "000001BA07BDDF60"; - expected3 = "000001ba07bddf60"; - SDLTest_AssertPass("Call to SDL_snprintf(text, sizeof(text), \"%%p\", 0x1ba07bddf60)"); - SDLTest_AssertCheck(SDL_strcmp(text, expected) == 0 || - SDL_strcmp(text, expected2) == 0 || - SDL_strcmp(text, expected3) == 0, - "Check text, expected: '%s', got: '%s'", expected, text); - SDLTest_AssertCheck(result == SDL_strlen(expected) || - result == SDL_strlen(expected2) || - result == SDL_strlen(expected3), - "Check result value, expected: %d, got: %d", (int)SDL_strlen(expected), result); - } return TEST_COMPLETED; } @@ -262,10 +207,10 @@ int stdlib_getsetenv(void *arg) text = SDL_getenv(name); SDLTest_AssertPass("Call to SDL_getenv('%s')", name); - if (text) { + if (text != NULL) { SDLTest_Log("Expected: NULL, Got: '%s' (%i)", text, (int)SDL_strlen(text)); } - } while (text); + } while (text != NULL); /* Create random values to set */ value1 = SDLTest_RandomAsciiStringOfSize(10); diff --git a/libs/SDL2/test/testautomation_subsystems.c b/libs/SDL2/test/testautomation_subsystems.c deleted file mode 100644 index d25edeeb7ce82624e90ad5da35783e05e8e79ceb..0000000000000000000000000000000000000000 --- a/libs/SDL2/test/testautomation_subsystems.c +++ /dev/null @@ -1,239 +0,0 @@ -/** - * Subsystem test suite - */ - -#include "SDL.h" -#include "SDL_test.h" - -/* ================= Test Case Implementation ================== */ - -/* Fixture */ - -static void subsystemsSetUp(void *arg) -{ - /* Reset each one of the SDL subsystems */ - /* CHECKME: can we use SDL_Quit here, or this will break the flow of tests? */ - SDL_Quit(); - /* Alternate variant without SDL_Quit: - while (SDL_WasInit(SDL_INIT_EVERYTHING) != 0) { - SDL_QuitSubSystem(SDL_INIT_EVERYTHING); - } - */ - SDLTest_AssertPass("Reset all subsystems before subsystems test"); - SDLTest_AssertCheck(SDL_WasInit(SDL_INIT_EVERYTHING) == 0, "Check result from SDL_WasInit(SDL_INIT_EVERYTHING)"); -} - -static void subsystemsTearDown(void *arg) -{ - /* Reset each one of the SDL subsystems */ - SDL_Quit(); - - SDLTest_AssertPass("Cleanup of subsystems test completed"); -} - -/* Test case functions */ - -/** - * \brief Inits and Quits particular subsystem, checking its Init status. - * - * \sa SDL_InitSubSystem - * \sa SDL_QuitSubSystem - * - */ -static int subsystems_referenceCount() -{ - const int system = SDL_INIT_VIDEO; - int result; - /* Ensure that we start with a non-initialized subsystem. */ - SDLTest_AssertCheck(SDL_WasInit(system) == 0, "Check result from SDL_WasInit(0x%x)", system); - - /* Init subsystem once, and quit once */ - SDL_InitSubSystem(system); - SDLTest_AssertPass("Call to SDL_InitSubSystem(0x%x)", system); - result = SDL_WasInit(system); - SDLTest_AssertCheck(result == system, "Check result from SDL_WasInit(0x%x), expected: 0x%x, got: 0x%x", system, system, result); - - SDL_QuitSubSystem(system); - SDLTest_AssertPass("Call to SDL_QuitSubSystem(0x%x)", system); - result = SDL_WasInit(system); - SDLTest_AssertCheck(result == 0, "Check result from SDL_WasInit(0x%x), expected: 0, got: 0x%x", system, result); - - /* Init subsystem number of times, then decrement reference count until it's disposed of. */ - SDL_InitSubSystem(system); - SDL_InitSubSystem(system); - SDL_InitSubSystem(system); - SDLTest_AssertPass("Call to SDL_InitSubSystem(0x%x) x3 times", system); - result = SDL_WasInit(system); - SDLTest_AssertCheck(result == system, "Check result from SDL_WasInit(0x%x), expected: 0x%x, got: 0x%x", system, system, result); - - SDL_QuitSubSystem(system); - SDLTest_AssertPass("Call to SDL_QuitSubSystem(0x%x) x1", system); - result = SDL_WasInit(system); - SDLTest_AssertCheck(result == system, "Check result from SDL_WasInit(0x%x), expected: 0x%x, got: 0x%x", system, system, result); - SDL_QuitSubSystem(system); - SDLTest_AssertPass("Call to SDL_QuitSubSystem(0x%x) x2", system); - result = SDL_WasInit(system); - SDLTest_AssertCheck(result == system, "Check result from SDL_WasInit(0x%x), expected: 0x%x, got: 0x%x", system, system, result); - SDL_QuitSubSystem(system); - SDLTest_AssertPass("Call to SDL_QuitSubSystem(0x%x) x3", system); - result = SDL_WasInit(system); - SDLTest_AssertCheck(result == 0, "Check result from SDL_WasInit(0x%x), expected: 0, got: 0x%x", system, result); - - return TEST_COMPLETED; -} - -/** - * \brief Inits and Quits subsystems that have another as dependency; - * check that the dependency is not removed before the last of its dependents. - * - * \sa SDL_InitSubSystem - * \sa SDL_QuitSubSystem - * - */ -static int subsystems_dependRefCountInitAllQuitByOne() -{ - int result; - /* Ensure that we start with reset subsystems. */ - SDLTest_AssertCheck(SDL_WasInit(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_EVENTS) == 0, - "Check result from SDL_WasInit(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_EVENTS)"); - - /* Following should init SDL_INIT_EVENTS and give it +3 ref counts. */ - SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK); - SDLTest_AssertPass("Call to SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK)"); - result = SDL_WasInit(SDL_INIT_EVENTS); - SDLTest_AssertCheck(result == SDL_INIT_EVENTS, "Check result from SDL_WasInit(SDL_INIT_EVENTS), expected: 0x4000, got: 0x%x", result); - - /* Quit systems one by one. */ - SDL_QuitSubSystem(SDL_INIT_VIDEO); - SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_VIDEO)"); - result = SDL_WasInit(SDL_INIT_EVENTS); - SDLTest_AssertCheck(result == SDL_INIT_EVENTS, "Check result from SDL_WasInit(SDL_INIT_EVENTS), expected: 0x4000, got: 0x%x", result); - SDL_QuitSubSystem(SDL_INIT_AUDIO); - SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)"); - result = SDL_WasInit(SDL_INIT_EVENTS); - SDLTest_AssertCheck(result == SDL_INIT_EVENTS, "Check result from SDL_WasInit(SDL_INIT_EVENTS), expected: 0x4000, got: 0x%x", result); - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_JOYSTICK)"); - result = SDL_WasInit(SDL_INIT_EVENTS); - SDLTest_AssertCheck(result == 0, "Check result from SDL_WasInit(SDL_INIT_EVENTS), expected: 0, got: 0x%x", result); - - return TEST_COMPLETED; -} - -/** - * \brief Inits and Quits subsystems that have another as dependency; - * check that the dependency is not removed before the last of its dependents. - * - * \sa SDL_InitSubSystem - * \sa SDL_QuitSubSystem - * - */ -static int subsystems_dependRefCountInitByOneQuitAll() -{ - int result; - /* Ensure that we start with reset subsystems. */ - SDLTest_AssertCheck(SDL_WasInit(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_EVENTS) == 0, - "Check result from SDL_WasInit(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_EVENTS)"); - - /* Following should init SDL_INIT_EVENTS and give it +3 ref counts. */ - SDL_InitSubSystem(SDL_INIT_VIDEO); - SDLTest_AssertPass("Call to SDL_InitSubSystem(SDL_INIT_VIDEO)"); - result = SDL_WasInit(SDL_INIT_EVENTS); - SDLTest_AssertCheck(result == SDL_INIT_EVENTS, "Check result from SDL_WasInit(SDL_INIT_EVENTS), expected: 0x4000, got: 0x%x", result); - SDL_InitSubSystem(SDL_INIT_AUDIO); - SDLTest_AssertPass("Call to SDL_InitSubSystem(SDL_INIT_AUDIO)"); - SDL_InitSubSystem(SDL_INIT_JOYSTICK); - SDLTest_AssertPass("Call to SDL_InitSubSystem(SDL_INIT_JOYSTICK)"); - - /* Quit systems all at once. */ - SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK); - SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK)"); - result = SDL_WasInit(SDL_INIT_EVENTS); - SDLTest_AssertCheck(result == 0, "Check result from SDL_WasInit(SDL_INIT_EVENTS), expected: 0, got: 0x%x", result); - - return TEST_COMPLETED; -} - -/** - * \brief Inits and Quits subsystems that have another as dependency, - * but also inits that dependency explicitly, giving it extra ref count. - * Check that the dependency is not removed before the last reference is gone. - * - * \sa SDL_InitSubSystem - * \sa SDL_QuitSubSystem - * - */ -static int subsystems_dependRefCountWithExtraInit() -{ - int result; - /* Ensure that we start with reset subsystems. */ - SDLTest_AssertCheck(SDL_WasInit(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_EVENTS) == 0, - "Check result from SDL_WasInit(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_EVENTS)"); - - /* Init EVENTS explicitly, +1 ref count. */ - SDL_InitSubSystem(SDL_INIT_EVENTS); - SDLTest_AssertPass("Call to SDL_InitSubSystem(SDL_INIT_EVENTS)"); - result = SDL_WasInit(SDL_INIT_EVENTS); - SDLTest_AssertCheck(result == SDL_INIT_EVENTS, "Check result from SDL_WasInit(SDL_INIT_EVENTS), expected: 0x4000, got: 0x%x", result); - /* Following should init SDL_INIT_EVENTS and give it +3 ref counts. */ - SDL_InitSubSystem(SDL_INIT_VIDEO); - SDLTest_AssertPass("Call to SDL_InitSubSystem(SDL_INIT_VIDEO)"); - SDL_InitSubSystem(SDL_INIT_AUDIO); - SDLTest_AssertPass("Call to SDL_InitSubSystem(SDL_INIT_AUDIO)"); - SDL_InitSubSystem(SDL_INIT_JOYSTICK); - SDLTest_AssertPass("Call to SDL_InitSubSystem(SDL_INIT_JOYSTICK)"); - - /* Quit EVENTS explicitly, -1 ref count. */ - SDL_QuitSubSystem(SDL_INIT_EVENTS); - SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_EVENTS)"); - result = SDL_WasInit(SDL_INIT_EVENTS); - SDLTest_AssertCheck(result == SDL_INIT_EVENTS, "Check result from SDL_WasInit(SDL_INIT_EVENTS), expected: 0x4000, got: 0x%x", result); - - /* Quit systems one by one. */ - SDL_QuitSubSystem(SDL_INIT_VIDEO); - SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_VIDEO)"); - result = SDL_WasInit(SDL_INIT_EVENTS); - SDLTest_AssertCheck(result == SDL_INIT_EVENTS, "Check result from SDL_WasInit(SDL_INIT_EVENTS), expected: 0x4000, got: 0x%x", result); - SDL_QuitSubSystem(SDL_INIT_AUDIO); - SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)"); - result = SDL_WasInit(SDL_INIT_EVENTS); - SDLTest_AssertCheck(result == SDL_INIT_EVENTS, "Check result from SDL_WasInit(SDL_INIT_EVENTS), expected: 0x4000, got: 0x%x", result); - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); - SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_JOYSTICK)"); - result = SDL_WasInit(SDL_INIT_EVENTS); - SDLTest_AssertCheck(result == 0, "Check result from SDL_WasInit(SDL_INIT_EVENTS), expected: 0, got: 0x%x", result); - - return TEST_COMPLETED; -} - -/* ================= Test References ================== */ - -/* Subsystems test cases */ -static const SDLTest_TestCaseReference subsystemsTest1 = { - (SDLTest_TestCaseFp)subsystems_referenceCount, "subsystems_referenceCount", "Makes sure that subsystem stays until number of quits matches inits.", TEST_ENABLED -}; - -static const SDLTest_TestCaseReference subsystemsTest2 = { - (SDLTest_TestCaseFp)subsystems_dependRefCountInitAllQuitByOne, "subsystems_dependRefCountInitAllQuitByOne", "Check reference count of subsystem dependencies.", TEST_ENABLED -}; - -static const SDLTest_TestCaseReference subsystemsTest3 = { - (SDLTest_TestCaseFp)subsystems_dependRefCountInitByOneQuitAll, "subsystems_dependRefCountInitByOneQuitAll", "Check reference count of subsystem dependencies.", TEST_ENABLED -}; - -static const SDLTest_TestCaseReference subsystemsTest4 = { - (SDLTest_TestCaseFp)subsystems_dependRefCountWithExtraInit, "subsystems_dependRefCountWithExtraInit", "Check reference count of subsystem dependencies.", TEST_ENABLED -}; - -/* Sequence of Events test cases */ -static const SDLTest_TestCaseReference *subsystemsTests[] = { - &subsystemsTest1, &subsystemsTest2, &subsystemsTest3, &subsystemsTest4, NULL -}; - -/* Events test suite (global) */ -SDLTest_TestSuiteReference subsystemsTestSuite = { - "Subsystems", - subsystemsSetUp, - subsystemsTests, - subsystemsTearDown -}; diff --git a/libs/SDL2/test/testautomation_suites.h b/libs/SDL2/test/testautomation_suites.h index 95528f271fbeb9bf1367ccad218e56fed015a3f0..6fdcd83889dfa28f521d3a4dc27e0951860b707a 100644 --- a/libs/SDL2/test/testautomation_suites.h +++ b/libs/SDL2/test/testautomation_suites.h @@ -16,7 +16,6 @@ extern SDLTest_TestSuiteReference guidTestSuite; extern SDLTest_TestSuiteReference hintsTestSuite; extern SDLTest_TestSuiteReference joystickTestSuite; extern SDLTest_TestSuiteReference keyboardTestSuite; -extern SDLTest_TestSuiteReference logTestSuite; extern SDLTest_TestSuiteReference mainTestSuite; extern SDLTest_TestSuiteReference mathTestSuite; extern SDLTest_TestSuiteReference mouseTestSuite; @@ -27,7 +26,6 @@ extern SDLTest_TestSuiteReference renderTestSuite; extern SDLTest_TestSuiteReference rwopsTestSuite; extern SDLTest_TestSuiteReference sdltestTestSuite; extern SDLTest_TestSuiteReference stdlibTestSuite; -extern SDLTest_TestSuiteReference subsystemsTestSuite; extern SDLTest_TestSuiteReference surfaceTestSuite; extern SDLTest_TestSuiteReference syswmTestSuite; extern SDLTest_TestSuiteReference timerTestSuite; @@ -42,7 +40,6 @@ SDLTest_TestSuiteReference *testSuites[] = { &hintsTestSuite, &joystickTestSuite, &keyboardTestSuite, - &logTestSuite, &mainTestSuite, &mathTestSuite, &mouseTestSuite, @@ -57,7 +54,6 @@ SDLTest_TestSuiteReference *testSuites[] = { &syswmTestSuite, &timerTestSuite, &videoTestSuite, - &subsystemsTestSuite, /* run last, not interfere with other test enviroment */ NULL }; diff --git a/libs/SDL2/test/testautomation_surface.c b/libs/SDL2/test/testautomation_surface.c index fcc4bc14cb7af0bd6925a89ce7a7f973fa0b233a..41aa24142c0c6e56bea354ec9fe1d6c6d98c8ee7 100644 --- a/libs/SDL2/test/testautomation_surface.c +++ b/libs/SDL2/test/testautomation_surface.c @@ -668,34 +668,6 @@ int surface_testOverflow(void *arg) surface != NULL ? "(success)" : SDL_GetError()); SDL_FreeSurface(surface); - /* SDL_PIXELFORMAT_INDEX2* needs 1 byte per 4 pixels. */ - surface = SDL_CreateRGBSurfaceWithFormatFrom(buf, 12, 1, 2, 3, SDL_PIXELFORMAT_INDEX2LSB); - SDLTest_AssertCheck(surface != NULL, "12px * 2 bits per px fits in 3 bytes: %s", - surface != NULL ? "(success)" : SDL_GetError()); - SDL_FreeSurface(surface); - surface = SDL_CreateRGBSurfaceFrom(buf, 12, 1, 2, 3, 0, 0, 0, 0); - SDLTest_AssertCheck(surface != NULL, "12px * 2 bits per px fits in 3 bytes: %s", - surface != NULL ? "(success)" : SDL_GetError()); - SDL_FreeSurface(surface); - - surface = SDL_CreateRGBSurfaceWithFormatFrom(buf, 13, 1, 2, 3, SDL_PIXELFORMAT_INDEX2LSB); - SDLTest_AssertCheck(surface == NULL, "Should detect pitch < width * bpp (%d)", surface ? surface->pitch : 0); - SDLTest_AssertCheck(SDL_strcmp(SDL_GetError(), expectedError) == 0, - "Expected \"%s\", got \"%s\"", expectedError, SDL_GetError()); - surface = SDL_CreateRGBSurfaceFrom(buf, 13, 1, 2, 3, 0, 0, 0, 0); - SDLTest_AssertCheck(surface == NULL, "Should detect pitch < width * bpp"); - SDLTest_AssertCheck(SDL_strcmp(SDL_GetError(), expectedError) == 0, - "Expected \"%s\", got \"%s\"", expectedError, SDL_GetError()); - - surface = SDL_CreateRGBSurfaceWithFormatFrom(buf, 13, 1, 2, 4, SDL_PIXELFORMAT_INDEX2LSB); - SDLTest_AssertCheck(surface != NULL, "13px * 2 bits per px fits in 4 bytes: %s", - surface != NULL ? "(success)" : SDL_GetError()); - SDL_FreeSurface(surface); - surface = SDL_CreateRGBSurfaceFrom(buf, 13, 1, 2, 4, 0, 0, 0, 0); - SDLTest_AssertCheck(surface != NULL, "13px * 2 bits per px fits in 4 bytes: %s", - surface != NULL ? "(success)" : SDL_GetError()); - SDL_FreeSurface(surface); - /* SDL_PIXELFORMAT_INDEX1* needs 1 byte per 8 pixels. */ surface = SDL_CreateRGBSurfaceWithFormatFrom(buf, 16, 1, 1, 2, SDL_PIXELFORMAT_INDEX1LSB); SDLTest_AssertCheck(surface != NULL, "16px * 1 bit per px fits in 2 bytes: %s", @@ -765,26 +737,19 @@ int surface_testOverflow(void *arg) "Expected \"%s\", got \"%s\"", expectedError, SDL_GetError()); if (sizeof(size_t) == 4 && sizeof(int) >= 4) { - SDL_ClearError(); expectedError = "Out of memory"; - /* 0x5555'5555 * 3bpp = 0xffff'ffff which fits in size_t, but adding - * alignment padding makes it overflow */ - surface = SDL_CreateRGBSurfaceWithFormat(0, 0x55555555, 1, 24, SDL_PIXELFORMAT_RGB24); + surface = SDL_CreateRGBSurfaceWithFormat(0, SDL_MAX_SINT32, 1, 8, SDL_PIXELFORMAT_INDEX8); SDLTest_AssertCheck(surface == NULL, "Should detect overflow in width + alignment"); SDLTest_AssertCheck(SDL_strcmp(SDL_GetError(), expectedError) == 0, "Expected \"%s\", got \"%s\"", expectedError, SDL_GetError()); - SDL_ClearError(); - /* 0x4000'0000 * 4bpp = 0x1'0000'0000 which (just) overflows */ - surface = SDL_CreateRGBSurfaceWithFormat(0, 0x40000000, 1, 32, SDL_PIXELFORMAT_ARGB8888); + surface = SDL_CreateRGBSurfaceWithFormat(0, SDL_MAX_SINT32 / 2, 1, 32, SDL_PIXELFORMAT_ARGB8888); SDLTest_AssertCheck(surface == NULL, "Should detect overflow in width * bytes per pixel"); SDLTest_AssertCheck(SDL_strcmp(SDL_GetError(), expectedError) == 0, "Expected \"%s\", got \"%s\"", expectedError, SDL_GetError()); - SDL_ClearError(); surface = SDL_CreateRGBSurfaceWithFormat(0, (1 << 29) - 1, (1 << 29) - 1, 8, SDL_PIXELFORMAT_INDEX8); SDLTest_AssertCheck(surface == NULL, "Should detect overflow in width * height"); SDLTest_AssertCheck(SDL_strcmp(SDL_GetError(), expectedError) == 0, "Expected \"%s\", got \"%s\"", expectedError, SDL_GetError()); - SDL_ClearError(); surface = SDL_CreateRGBSurfaceWithFormat(0, (1 << 15) + 1, (1 << 15) + 1, 32, SDL_PIXELFORMAT_ARGB8888); SDLTest_AssertCheck(surface == NULL, "Should detect overflow in width * height * bytes per pixel"); SDLTest_AssertCheck(SDL_strcmp(SDL_GetError(), expectedError) == 0, diff --git a/libs/SDL2/test/testautomation_timer.c b/libs/SDL2/test/testautomation_timer.c index a7160e76c05e73bffa47af306ef3cb841e95a2c4..1002a36eba79cc6388fc78d17c3cbdfd2283f2bf 100644 --- a/libs/SDL2/test/testautomation_timer.c +++ b/libs/SDL2/test/testautomation_timer.c @@ -94,10 +94,7 @@ int timer_delayAndGetTicks(void *arg) SDLTest_AssertCheck(result2 > 0, "Check result value, expected: >0, got: %" SDL_PRIu32, result2); difference = result2 - result; SDLTest_AssertCheck(difference > (testDelay - marginOfError), "Check difference, expected: >%" SDL_PRIu32 ", got: %" SDL_PRIu32, testDelay - marginOfError, difference); -#if 0 - /* Disabled because this might fail on non-interactive systems. Moved to testtimer. */ SDLTest_AssertCheck(difference < (testDelay + marginOfError), "Check difference, expected: <%" SDL_PRIu32 ", got: %" SDL_PRIu32, testDelay + marginOfError, difference); -#endif return TEST_COMPLETED; } diff --git a/libs/SDL2/test/testautomation_video.c b/libs/SDL2/test/testautomation_video.c index dd8f1c5c25b85a6278b30ec40d367cb15807e9e3..aa9e7b92b360ede7df22884aa60db0c1823582f8 100644 --- a/libs/SDL2/test/testautomation_video.c +++ b/libs/SDL2/test/testautomation_video.c @@ -28,7 +28,6 @@ SDL_Window *_createVideoSuiteTestWindow(const char *title) SDL_Window *window; int x, y, w, h; SDL_WindowFlags flags; - SDL_bool needs_renderer = SDL_FALSE; /* Standard window */ x = SDLTest_RandomIntegerInRange(1, 100); @@ -41,35 +40,6 @@ SDL_Window *_createVideoSuiteTestWindow(const char *title) SDLTest_AssertPass("Call to SDL_CreateWindow('Title',%d,%d,%d,%d,%d)", x, y, w, h, flags); SDLTest_AssertCheck(window != NULL, "Validate that returned window struct is not NULL"); - /* Wayland and XWayland windows require that a frame be presented before they are fully mapped and visible onscreen. - * This is required for the mouse/keyboard grab tests to pass. - */ - if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0) { - needs_renderer = SDL_TRUE; - } else if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) { - /* Try to detect if the x11 driver is running under XWayland */ - const char *session_type = SDL_getenv("XDG_SESSION_TYPE"); - if (session_type && SDL_strcasecmp(session_type, "wayland") == 0) { - needs_renderer = SDL_TRUE; - } - } - - if (needs_renderer) { - SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0); - if (renderer) { - SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF); - SDL_RenderClear(renderer); - SDL_RenderPresent(renderer); - - /* Some desktops don't display the window immediately after presentation, - * so delay to give the window time to actually appear on the desktop. - */ - SDL_Delay(100); - } else { - SDLTest_Log("Unable to create a renderer, some tests may fail on Wayland/XWayland"); - } - } - return window; } @@ -78,7 +48,7 @@ SDL_Window *_createVideoSuiteTestWindow(const char *title) */ void _destroyVideoSuiteTestWindow(SDL_Window *window) { - if (window) { + if (window != NULL) { SDL_DestroyWindow(window); window = NULL; SDLTest_AssertPass("Call to SDL_DestroyWindow()"); @@ -308,8 +278,6 @@ int video_createWindowVariousFlags(void *arg) break; case 2: flags = SDL_WINDOW_OPENGL; - /* Skip - not every video driver supports OpenGL; comment out next line to run test */ - continue; break; case 3: flags = SDL_WINDOW_SHOWN; @@ -608,7 +576,7 @@ int video_getWindowDisplayMode(void *arg) /* Call against new test window */ window = _createVideoSuiteTestWindow(title); - if (window) { + if (window != NULL) { result = SDL_GetWindowDisplayMode(window, &mode); SDLTest_AssertPass("Call to SDL_GetWindowDisplayMode()"); SDLTest_AssertCheck(result == 0, "Validate result value; expected: 0, got: %d", result); @@ -702,7 +670,7 @@ video_getWindowGammaRamp(void *arg) /* Call against new test window */ window = _createVideoSuiteTestWindow(title); - if (!window) return TEST_ABORTED; + if (window == NULL) return TEST_ABORTED; /* Retrieve no channel */ result = SDL_GetWindowGammaRamp(window, NULL, NULL, NULL); @@ -852,33 +820,13 @@ int video_getSetWindowGrab(void *arg) const char *title = "video_getSetWindowGrab Test Window"; SDL_Window *window; SDL_bool originalMouseState, originalKeyboardState; - SDL_bool hasFocusGained = SDL_FALSE; /* Call against new test window */ window = _createVideoSuiteTestWindow(title); - if (!window) { + if (window == NULL) { return TEST_ABORTED; } - /* Need to raise the window to have and SDL_EVENT_WINDOW_FOCUS_GAINED, - * so that the window gets the flags SDL_WINDOW_INPUT_FOCUS, - * so that it can be "grabbed" */ - SDL_RaiseWindow(window); - - { - SDL_Event evt; - SDL_zero(evt); - while (SDL_PollEvent(&evt)) { - if (evt.type == SDL_WINDOWEVENT) { - if (evt.window.event == SDL_WINDOWEVENT_FOCUS_GAINED) { - hasFocusGained = SDL_TRUE; - } - } - } - } - - SDLTest_AssertCheck(hasFocusGained == SDL_TRUE, "Expected window with focus"); - /* Get state */ originalMouseState = SDL_GetWindowMouseGrab(window); SDLTest_AssertPass("Call to SDL_GetWindowMouseGrab()"); @@ -1019,7 +967,7 @@ int video_getWindowId(void *arg) /* Call against new test window */ window = _createVideoSuiteTestWindow(title); - if (!window) { + if (window == NULL) { return TEST_ABORTED; } @@ -1074,7 +1022,7 @@ int video_getWindowPixelFormat(void *arg) /* Call against new test window */ window = _createVideoSuiteTestWindow(title); - if (!window) { + if (window == NULL) { return TEST_ABORTED; } @@ -1137,58 +1085,28 @@ int video_getSetWindowPosition(void *arg) { const char *title = "video_getSetWindowPosition Test Window"; SDL_Window *window; - int maxxVariation, maxyVariation; int xVariation, yVariation; int referenceX, referenceY; int currentX, currentY; int desiredX, desiredY; - SDL_Rect display_bounds; - - if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0) { - SDLTest_Log("Skipping test: wayland does not support window positioning"); - return TEST_SKIPPED; - } /* Call against new test window */ window = _createVideoSuiteTestWindow(title); - if (!window) { + if (window == NULL) { return TEST_ABORTED; } - if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) { - /* The X11 server allows arbitrary window placement, but compositing - * window managers such as GNOME and KDE force windows to be within - * desktop bounds. - */ - maxxVariation = 2; - maxyVariation = 2; - - SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(window), &display_bounds); - } else if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "cocoa") == 0) { - /* Platform doesn't allow windows with negative Y desktop bounds */ - maxxVariation = 4; - maxyVariation = 3; - - SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(window), &display_bounds); - } else { - /* Platform allows windows to be placed out of bounds */ - maxxVariation = 4; - maxyVariation = 4; - - SDL_GetDisplayBounds(SDL_GetWindowDisplayIndex(window), &display_bounds); - } - - for (xVariation = 0; xVariation < maxxVariation; xVariation++) { - for (yVariation = 0; yVariation < maxyVariation; yVariation++) { + for (xVariation = 0; xVariation < 4; xVariation++) { + for (yVariation = 0; yVariation < 4; yVariation++) { switch (xVariation) { default: case 0: /* Zero X Position */ - desiredX = display_bounds.x > 0 ? display_bounds.x : 0; + desiredX = 0; break; case 1: /* Random X position inside screen */ - desiredX = SDLTest_RandomIntegerInRange(display_bounds.x + 1, display_bounds.x + 100); + desiredX = SDLTest_RandomIntegerInRange(1, 100); break; case 2: /* Random X position outside screen (positive) */ @@ -1203,15 +1121,15 @@ int video_getSetWindowPosition(void *arg) switch (yVariation) { default: case 0: - /* Zero Y Position */ - desiredY = display_bounds.y > 0 ? display_bounds.y : 0; + /* Zero X Position */ + desiredY = 0; break; case 1: - /* Random Y position inside screen */ - desiredY = SDLTest_RandomIntegerInRange(display_bounds.y + 1, display_bounds.y + 100); + /* Random X position inside screen */ + desiredY = SDLTest_RandomIntegerInRange(1, 100); break; case 2: - /* Random Y position outside screen (positive) */ + /* Random X position outside screen (positive) */ desiredY = SDLTest_RandomIntegerInRange(10000, 11000); break; case 3: @@ -1337,7 +1255,7 @@ int video_getSetWindowSize(void *arg) int desiredW, desiredH; /* Get display bounds for size range */ - result = SDL_GetDisplayUsableBounds(0, &display); + result = SDL_GetDisplayBounds(0, &display); SDLTest_AssertPass("SDL_GetDisplayBounds()"); SDLTest_AssertCheck(result == 0, "Verify return value; expected: 0, got: %d", result); if (result != 0) { @@ -1346,20 +1264,19 @@ int video_getSetWindowSize(void *arg) /* Call against new test window */ window = _createVideoSuiteTestWindow(title); - if (!window) { + if (window == NULL) { return TEST_ABORTED; } - if (SDL_strcmp(SDL_GetCurrentVideoDriver(), "windows") == 0 || - SDL_strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0) { - /* Platform clips window size to screen size */ - maxwVariation = 4; - maxhVariation = 4; - } else { - /* Platform allows window size >= screen size */ - maxwVariation = 5; - maxhVariation = 5; - } +#ifdef __WIN32__ + /* Platform clips window size to screen size */ + maxwVariation = 4; + maxhVariation = 4; +#else + /* Platform allows window size >= screen size */ + maxwVariation = 5; + maxhVariation = 5; +#endif for (wVariation = 0; wVariation < maxwVariation; wVariation++) { for (hVariation = 0; hVariation < maxhVariation; hVariation++) { @@ -1438,6 +1355,7 @@ int video_getSetWindowSize(void *arg) } } + /* Get just width */ currentW = desiredW + 1; SDL_GetWindowSize(window, ¤tW, NULL); @@ -1529,7 +1447,7 @@ int video_getSetWindowMinimumSize(void *arg) /* Call against new test window */ window = _createVideoSuiteTestWindow(title); - if (!window) { + if (window == NULL) { return TEST_ABORTED; } @@ -1671,7 +1589,7 @@ int video_getSetWindowMaximumSize(void *arg) /* Call against new test window */ window = _createVideoSuiteTestWindow(title); - if (!window) { + if (window == NULL) { return TEST_ABORTED; } @@ -1809,30 +1727,30 @@ int video_getSetWindowData(void *arg) /* Call against new test window */ window = _createVideoSuiteTestWindow(title); - if (!window) { + if (window == NULL) { return TEST_ABORTED; } /* Create testdata */ datasize = SDLTest_RandomIntegerInRange(1, 32); referenceUserdata = SDLTest_RandomAsciiStringOfSize(datasize); - if (!referenceUserdata) { + if (referenceUserdata == NULL) { returnValue = TEST_ABORTED; goto cleanup; } userdata = SDL_strdup(referenceUserdata); - if (!userdata) { + if (userdata == NULL) { returnValue = TEST_ABORTED; goto cleanup; } datasize = SDLTest_RandomIntegerInRange(1, 32); referenceUserdata2 = SDLTest_RandomAsciiStringOfSize(datasize); - if (!referenceUserdata2) { + if (referenceUserdata2 == NULL) { returnValue = TEST_ABORTED; goto cleanup; } userdata2 = SDL_strdup(referenceUserdata2); - if (!userdata2) { + if (userdata2 == NULL) { returnValue = TEST_ABORTED; goto cleanup; } @@ -2017,11 +1935,6 @@ int video_setWindowCenteredOnDisplay(void *arg) SDL_Rect display0, display1; displayNum = SDL_GetNumVideoDisplays(); - SDLTest_AssertPass("SDL_GetNumVideoDisplays()"); - SDLTest_AssertCheck(displayNum >= 1, "Validate result (current: %d, expected >= 1)", displayNum); - if (displayNum <= 0) { - return TEST_ABORTED; - } /* Get display bounds */ result = SDL_GetDisplayBounds(0 % displayNum, &display0); @@ -2046,7 +1959,6 @@ int video_setWindowCenteredOnDisplay(void *arg) int currentDisplay; int expectedDisplay; SDL_Rect expectedDisplayRect; - SDL_bool video_driver_is_wayland = SDL_strcmp(SDL_GetCurrentVideoDriver(), "wayland") == 0; /* xVariation is the display we start on */ expectedDisplay = xVariation % displayNum; @@ -2058,46 +1970,20 @@ int video_setWindowCenteredOnDisplay(void *arg) expectedX = (expectedDisplayRect.x + ((expectedDisplayRect.w - w) / 2)); expectedY = (expectedDisplayRect.y + ((expectedDisplayRect.h - h) / 2)); - window = SDL_CreateWindow(title, x, y, w, h, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_BORDERLESS); + window = SDL_CreateWindow(title, x, y, w, h, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI); SDLTest_AssertPass("Call to SDL_CreateWindow('Title',%d,%d,%d,%d,SHOWN)", x, y, w, h); SDLTest_AssertCheck(window != NULL, "Validate that returned window struct is not NULL"); - /* Wayland windows require that a frame be presented before they are fully mapped and visible onscreen. */ - if (video_driver_is_wayland) { - SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0); - - if (renderer) { - SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF); - SDL_RenderClear(renderer); - SDL_RenderPresent(renderer); - - /* Some desktops don't display the window immediately after presentation, - * so delay to give the window time to actually appear on the desktop. - */ - SDL_Delay(100); - } else { - SDLTest_Log("Unable to create a renderer, tests may fail under Wayland"); - } - } - /* Check the window is centered on the requested display */ currentDisplay = SDL_GetWindowDisplayIndex(window); SDL_GetWindowSize(window, ¤tW, ¤tH); SDL_GetWindowPosition(window, ¤tX, ¤tY); - if (!video_driver_is_wayland) { - SDLTest_AssertCheck(currentDisplay == expectedDisplay, "Validate display index (current: %d, expected: %d)", currentDisplay, expectedDisplay); - } else { - SDLTest_Log("Skipping display index validation: Wayland driver does not support window positioning"); - } + SDLTest_AssertCheck(currentDisplay == expectedDisplay, "Validate display index (current: %d, expected: %d)", currentDisplay, expectedDisplay); SDLTest_AssertCheck(currentW == w, "Validate width (current: %d, expected: %d)", currentW, w); SDLTest_AssertCheck(currentH == h, "Validate height (current: %d, expected: %d)", currentH, h); - if (!video_driver_is_wayland) { - SDLTest_AssertCheck(currentX == expectedX, "Validate x (current: %d, expected: %d)", currentX, expectedX); - SDLTest_AssertCheck(currentY == expectedY, "Validate y (current: %d, expected: %d)", currentY, expectedY); - } else { - SDLTest_Log("Skipping window position validation: Wayland driver does not support window positioning"); - } + SDLTest_AssertCheck(currentX == expectedX, "Validate x (current: %d, expected: %d)", currentX, expectedX); + SDLTest_AssertCheck(currentY == expectedY, "Validate y (current: %d, expected: %d)", currentY, expectedY); /* Enter fullscreen desktop */ result = SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); @@ -2108,19 +1994,11 @@ int video_setWindowCenteredOnDisplay(void *arg) SDL_GetWindowSize(window, ¤tW, ¤tH); SDL_GetWindowPosition(window, ¤tX, ¤tY); - if (!video_driver_is_wayland) { - SDLTest_AssertCheck(currentDisplay == expectedDisplay, "Validate display index (current: %d, expected: %d)", currentDisplay, expectedDisplay); - } else { - SDLTest_Log("Skipping display index validation: Wayland driver does not support window positioning"); - } + SDLTest_AssertCheck(currentDisplay == expectedDisplay, "Validate display index (current: %d, expected: %d)", currentDisplay, expectedDisplay); SDLTest_AssertCheck(currentW == expectedDisplayRect.w, "Validate width (current: %d, expected: %d)", currentW, expectedDisplayRect.w); SDLTest_AssertCheck(currentH == expectedDisplayRect.h, "Validate height (current: %d, expected: %d)", currentH, expectedDisplayRect.h); - if (!video_driver_is_wayland) { - SDLTest_AssertCheck(currentX == expectedDisplayRect.x, "Validate x (current: %d, expected: %d)", currentX, expectedDisplayRect.x); - SDLTest_AssertCheck(currentY == expectedDisplayRect.y, "Validate y (current: %d, expected: %d)", currentY, expectedDisplayRect.y); - } else { - SDLTest_Log("Skipping window position validation: Wayland driver does not support window positioning"); - } + SDLTest_AssertCheck(currentX == expectedDisplayRect.x, "Validate x (current: %d, expected: %d)", currentX, expectedDisplayRect.x); + SDLTest_AssertCheck(currentY == expectedDisplayRect.y, "Validate y (current: %d, expected: %d)", currentY, expectedDisplayRect.y); /* Leave fullscreen desktop */ result = SDL_SetWindowFullscreen(window, 0); @@ -2131,19 +2009,11 @@ int video_setWindowCenteredOnDisplay(void *arg) SDL_GetWindowSize(window, ¤tW, ¤tH); SDL_GetWindowPosition(window, ¤tX, ¤tY); - if (!video_driver_is_wayland) { - SDLTest_AssertCheck(currentDisplay == expectedDisplay, "Validate display index (current: %d, expected: %d)", currentDisplay, expectedDisplay); - } else { - SDLTest_Log("Skipping display index validation: Wayland driver does not support window positioning"); - } + SDLTest_AssertCheck(currentDisplay == expectedDisplay, "Validate display index (current: %d, expected: %d)", currentDisplay, expectedDisplay); SDLTest_AssertCheck(currentW == w, "Validate width (current: %d, expected: %d)", currentW, w); SDLTest_AssertCheck(currentH == h, "Validate height (current: %d, expected: %d)", currentH, h); - if (!video_driver_is_wayland) { - SDLTest_AssertCheck(currentX == expectedX, "Validate x (current: %d, expected: %d)", currentX, expectedX); - SDLTest_AssertCheck(currentY == expectedY, "Validate y (current: %d, expected: %d)", currentY, expectedY); - } else { - SDLTest_Log("Skipping window position validation: Wayland driver does not support window positioning"); - } + SDLTest_AssertCheck(currentX == expectedX, "Validate x (current: %d, expected: %d)", currentX, expectedX); + SDLTest_AssertCheck(currentY == expectedY, "Validate y (current: %d, expected: %d)", currentY, expectedY); /* Center on display yVariation, and check window properties */ @@ -2159,19 +2029,11 @@ int video_setWindowCenteredOnDisplay(void *arg) SDL_GetWindowSize(window, ¤tW, ¤tH); SDL_GetWindowPosition(window, ¤tX, ¤tY); - if (!video_driver_is_wayland) { - SDLTest_AssertCheck(currentDisplay == expectedDisplay, "Validate display index (current: %d, expected: %d)", currentDisplay, expectedDisplay); - } else { - SDLTest_Log("Skipping display index validation: Wayland driver does not support window positioning"); - } + SDLTest_AssertCheck(currentDisplay == expectedDisplay, "Validate display index (current: %d, expected: %d)", currentDisplay, expectedDisplay); SDLTest_AssertCheck(currentW == w, "Validate width (current: %d, expected: %d)", currentW, w); SDLTest_AssertCheck(currentH == h, "Validate height (current: %d, expected: %d)", currentH, h); - if (!video_driver_is_wayland) { - SDLTest_AssertCheck(currentX == expectedX, "Validate x (current: %d, expected: %d)", currentX, expectedX); - SDLTest_AssertCheck(currentY == expectedY, "Validate y (current: %d, expected: %d)", currentY, expectedY); - } else { - SDLTest_Log("Skipping window position validation: Wayland driver does not support window positioning"); - } + SDLTest_AssertCheck(currentX == expectedX, "Validate x (current: %d, expected: %d)", currentX, expectedX); + SDLTest_AssertCheck(currentY == expectedY, "Validate y (current: %d, expected: %d)", currentY, expectedY); /* Clean up */ _destroyVideoSuiteTestWindow(window); diff --git a/libs/SDL2/test/testbounds.c b/libs/SDL2/test/testbounds.c index 9bd73ac962d18dbf97e1a750f975401ba1aa1f81..42213f5464b899db0aa4c24a7572059726cd4156 100644 --- a/libs/SDL2/test/testbounds.c +++ b/libs/SDL2/test/testbounds.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/test/testcustomcursor.c b/libs/SDL2/test/testcustomcursor.c index aec3c78aa3e2b44971f3af7117cb710d521375b4..dc1c3718cc8618e9b70facc4b3d544895e678bd0 100644 --- a/libs/SDL2/test/testcustomcursor.c +++ b/libs/SDL2/test/testcustomcursor.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -242,7 +242,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (!state) { + if (state == NULL) { return 1; } for (i = 1; i < argc;) { diff --git a/libs/SDL2/test/testdisplayinfo.c b/libs/SDL2/test/testdisplayinfo.c index 9740ab174287834a84f0edc583c6ce2d67705528..66cc5d875a4207164c9a5c3470df885ad2a2b7e8 100644 --- a/libs/SDL2/test/testdisplayinfo.c +++ b/libs/SDL2/test/testdisplayinfo.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -20,7 +20,7 @@ static void print_mode(const char *prefix, const SDL_DisplayMode *mode) { - if (!mode) { + if (mode == NULL) { return; } diff --git a/libs/SDL2/test/testdraw2.c b/libs/SDL2/test/testdraw2.c index 43aa1843b18160cfe490614cae9ec63be84ee88e..f660c284584a15abf7e2b9ea119f50cefd6906d0 100644 --- a/libs/SDL2/test/testdraw2.c +++ b/libs/SDL2/test/testdraw2.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -227,7 +227,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (!state) { + if (state == NULL) { return 1; } for (i = 1; i < argc;) { diff --git a/libs/SDL2/test/testdrawchessboard.c b/libs/SDL2/test/testdrawchessboard.c index 4dffe06bd764ac01b1bec5c03eb2e3669669e781..8ff21a4c4ee5e619cff05c71de2b22700518b504 100644 --- a/libs/SDL2/test/testdrawchessboard.c +++ b/libs/SDL2/test/testdrawchessboard.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -50,7 +50,6 @@ void DrawChessBoard() SDL_RenderFillRect(renderer, &rect); } } - SDL_RenderPresent(renderer); } void loop() @@ -107,13 +106,13 @@ int main(int argc, char *argv[]) /* Create window and renderer for given surface */ window = SDL_CreateWindow("Chess Board", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_RESIZABLE); - if (!window) { + if (window == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Window creation fail : %s\n", SDL_GetError()); return 1; } surface = SDL_GetWindowSurface(window); renderer = SDL_CreateSoftwareRenderer(surface); - if (!renderer) { + if (renderer == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Render creation for surface fail : %s\n", SDL_GetError()); return 1; } diff --git a/libs/SDL2/test/testdropfile.c b/libs/SDL2/test/testdropfile.c index 2184f062eed782593db2aafaa4d2122142953faa..b80633365603688e07757835c21c376ed88fb9bb 100644 --- a/libs/SDL2/test/testdropfile.c +++ b/libs/SDL2/test/testdropfile.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -35,7 +35,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (!state) { + if (state == NULL) { return 1; } diff --git a/libs/SDL2/test/testerror.c b/libs/SDL2/test/testerror.c index 25874d1ea78f75d3e181a1c352bac77c63433077..f3f11b661736b83c7a5a007b13b599970424d79c 100644 --- a/libs/SDL2/test/testerror.c +++ b/libs/SDL2/test/testerror.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -65,7 +65,7 @@ int main(int argc, char *argv[]) alive = 1; thread = SDL_CreateThread(ThreadFunc, NULL, "#1"); - if (!thread) { + if (thread == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create thread: %s\n", SDL_GetError()); quit(1); } diff --git a/libs/SDL2/test/testevdev.c b/libs/SDL2/test/testevdev.c index 67124ae0f461e3c133b6a55678898b8eac1c3aef..e61579158748b06d5dadb6811175b7f20a82ecf1 100644 --- a/libs/SDL2/test/testevdev.c +++ b/libs/SDL2/test/testevdev.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> Copyright (C) 2020-2022 Collabora Ltd. This software is provided 'as-is', without any express or implied @@ -18,7 +18,7 @@ static int run_test(void); -#if defined(HAVE_LIBUDEV_H) || defined(SDL_JOYSTICK_LINUX) +#if HAVE_LIBUDEV_H || defined(SDL_JOYSTICK_LINUX) #include <stdint.h> diff --git a/libs/SDL2/test/testfile.c b/libs/SDL2/test/testfile.c index a35da02bd714fbbd02f549443d0907ae2abb2263..40d52ca22b13e81bbb1b3377bcf415b4b56440c8 100644 --- a/libs/SDL2/test/testfile.c +++ b/libs/SDL2/test/testfile.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -107,25 +107,25 @@ int main(int argc, char *argv[]) RWOP_ERR_QUIT(rwops); } rwops = SDL_RWFromFile(FBASENAME2, "wb"); - if (!rwops) { + if (rwops == NULL) { RWOP_ERR_QUIT(rwops); } rwops->close(rwops); unlink(FBASENAME2); rwops = SDL_RWFromFile(FBASENAME2, "wb+"); - if (!rwops) { + if (rwops == NULL) { RWOP_ERR_QUIT(rwops); } rwops->close(rwops); unlink(FBASENAME2); rwops = SDL_RWFromFile(FBASENAME2, "ab"); - if (!rwops) { + if (rwops == NULL) { RWOP_ERR_QUIT(rwops); } rwops->close(rwops); unlink(FBASENAME2); rwops = SDL_RWFromFile(FBASENAME2, "ab+"); - if (!rwops) { + if (rwops == NULL) { RWOP_ERR_QUIT(rwops); } rwops->close(rwops); @@ -136,7 +136,7 @@ int main(int argc, char *argv[]) test : w mode, r mode, w+ mode */ rwops = SDL_RWFromFile(FBASENAME1, "wb"); /* write only */ - if (!rwops) { + if (rwops == NULL) { RWOP_ERR_QUIT(rwops); } if (1 != rwops->write(rwops, "1234567890", 10, 1)) { @@ -158,7 +158,7 @@ int main(int argc, char *argv[]) rwops->close(rwops); rwops = SDL_RWFromFile(FBASENAME1, "rb"); /* read mode, file must exists */ - if (!rwops) { + if (rwops == NULL) { RWOP_ERR_QUIT(rwops); } if (0 != rwops->seek(rwops, 0L, RW_SEEK_SET)) { @@ -196,7 +196,7 @@ int main(int argc, char *argv[]) /* test 3: same with w+ mode */ rwops = SDL_RWFromFile(FBASENAME1, "wb+"); /* write + read + truncation */ - if (!rwops) { + if (rwops == NULL) { RWOP_ERR_QUIT(rwops); } if (1 != rwops->write(rwops, "1234567890", 10, 1)) { @@ -247,7 +247,7 @@ int main(int argc, char *argv[]) /* test 4: same in r+ mode */ rwops = SDL_RWFromFile(FBASENAME1, "rb+"); /* write + read + file must exists, no truncation */ - if (!rwops) { + if (rwops == NULL) { RWOP_ERR_QUIT(rwops); } if (1 != rwops->write(rwops, "1234567890", 10, 1)) { @@ -298,7 +298,7 @@ int main(int argc, char *argv[]) /* test5 : append mode */ rwops = SDL_RWFromFile(FBASENAME1, "ab+"); /* write + read + append */ - if (!rwops) { + if (rwops == NULL) { RWOP_ERR_QUIT(rwops); } if (1 != rwops->write(rwops, "1234567890", 10, 1)) { diff --git a/libs/SDL2/test/testfilesystem.c b/libs/SDL2/test/testfilesystem.c index af0bd9f05a38189296ad3f4a8dbe17a129773064..f452d7761ff2908b1c2f10ce85d33a618d40a021 100644 --- a/libs/SDL2/test/testfilesystem.c +++ b/libs/SDL2/test/testfilesystem.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -28,7 +28,7 @@ int main(int argc, char *argv[]) } base_path = SDL_GetBasePath(); - if (!base_path) { + if (base_path == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't find base path: %s\n", SDL_GetError()); } else { @@ -37,7 +37,7 @@ int main(int argc, char *argv[]) } pref_path = SDL_GetPrefPath("libsdl", "test_filesystem"); - if (!pref_path) { + if (pref_path == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't find pref path: %s\n", SDL_GetError()); } else { @@ -46,7 +46,7 @@ int main(int argc, char *argv[]) } pref_path = SDL_GetPrefPath(NULL, "test_filesystem"); - if (!pref_path) { + if (pref_path == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't find pref path without organization: %s\n", SDL_GetError()); } else { diff --git a/libs/SDL2/test/testfilesystem_pre.c b/libs/SDL2/test/testfilesystem_pre.c index 11615abd281f53417eeeae9441d663477492f773..dba8b51fb67545b52f2fa1bd45264632d797c0bd 100644 --- a/libs/SDL2/test/testfilesystem_pre.c +++ b/libs/SDL2/test/testfilesystem_pre.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/test/testgamecontroller.c b/libs/SDL2/test/testgamecontroller.c index 52d3b2d853ba3085770633391dd0cfc6c1ecb560..e2bdebdec5fda45b7ae5d635d8d47ce60577ffec 100644 --- a/libs/SDL2/test/testgamecontroller.c +++ b/libs/SDL2/test/testgamecontroller.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -109,7 +109,7 @@ static SDL_GameControllerButton virtual_button_active = SDL_CONTROLLER_BUTTON_IN static void UpdateWindowTitle() { - if (!window) { + if (window == NULL) { return; } @@ -201,13 +201,13 @@ static void AddController(int device_index, SDL_bool verbose) } controller = SDL_GameControllerOpen(device_index); - if (!controller) { + if (controller == NULL) { SDL_Log("Couldn't open controller: %s\n", SDL_GetError()); return; } controllers = (SDL_GameController **)SDL_realloc(gamecontrollers, (num_controllers + 1) * sizeof(*controllers)); - if (!controllers) { + if (controllers == NULL) { SDL_GameControllerClose(controller); return; } @@ -221,7 +221,6 @@ static void AddController(int device_index, SDL_bool verbose) const char *name = SDL_GameControllerName(gamecontroller); const char *path = SDL_GameControllerPath(gamecontroller); SDL_Log("Opened game controller %s%s%s\n", name, path ? ", " : "", path ? path : ""); - SDL_Log("Mapping: %s\n", SDL_GameControllerMapping(gamecontroller)); } firmware_version = SDL_GameControllerGetFirmwareVersion(gamecontroller); @@ -414,7 +413,7 @@ static void OpenVirtualController() SDL_Log("Couldn't open virtual device: %s\n", SDL_GetError()); } else { virtual_joystick = SDL_JoystickOpen(virtual_index); - if (!virtual_joystick) { + if (virtual_joystick == NULL) { SDL_Log("Couldn't open virtual device: %s\n", SDL_GetError()); } } @@ -625,8 +624,7 @@ void loop(void *arg) if (event.type == SDL_CONTROLLERBUTTONDOWN) { SetController(event.cbutton.which); } - SDL_Log("Controller %" SDL_PRIs32 " button %s %s\n", event.cbutton.which, SDL_GameControllerGetStringForButton((SDL_GameControllerButton)event.cbutton.button), - event.cbutton.state ? "pressed" : "released"); + SDL_Log("Controller %" SDL_PRIs32 " button %s %s\n", event.cbutton.which, SDL_GameControllerGetStringForButton((SDL_GameControllerButton)event.cbutton.button), event.cbutton.state ? "pressed" : "released"); /* Cycle PS5 trigger effects when the microphone button is pressed */ if (event.type == SDL_CONTROLLERBUTTONDOWN && @@ -898,13 +896,13 @@ int main(int argc, char *argv[]) window = SDL_CreateWindow("Game Controller Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, 0); - if (!window) { + if (window == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError()); return 2; } screen = SDL_CreateRenderer(window, -1, 0); - if (!screen) { + if (screen == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError()); SDL_DestroyWindow(window); return 2; @@ -922,7 +920,7 @@ int main(int argc, char *argv[]) button_texture = LoadTexture(screen, "button.bmp", SDL_TRUE, NULL, NULL); axis_texture = LoadTexture(screen, "axis.bmp", SDL_TRUE, NULL, NULL); - if (!background_front || !background_back || !button_texture || !axis_texture) { + if (background_front == NULL || background_back == NULL || button_texture == NULL || axis_texture == NULL) { SDL_DestroyRenderer(screen); SDL_DestroyWindow(window); return 2; diff --git a/libs/SDL2/test/testgeometry.c b/libs/SDL2/test/testgeometry.c index e09c38332f8b6fb8e23b6cf4a90624f77784272a..9742a14162a79937010dc8315e07b993c4cccfeb 100644 --- a/libs/SDL2/test/testgeometry.c +++ b/libs/SDL2/test/testgeometry.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -172,7 +172,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (!state) { + if (state == NULL) { return 1; } for (i = 1; i < argc;) { @@ -216,7 +216,7 @@ int main(int argc, char *argv[]) /* Create the windows, initialize the renderers, and load the textures */ sprites = (SDL_Texture **)SDL_malloc(state->num_windows * sizeof(*sprites)); - if (!sprites) { + if (sprites == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n"); quit(2); } diff --git a/libs/SDL2/test/testgesture.c b/libs/SDL2/test/testgesture.c index 9870b6059c43d1072902db7bce5fc90fe8010302..f37635f3319d38f4c67b583c1ff6556ebeeb9060 100644 --- a/libs/SDL2/test/testgesture.c +++ b/libs/SDL2/test/testgesture.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -131,7 +131,7 @@ DrawScreen(SDL_Window *window) SDL_Surface *screen = SDL_GetWindowSurface(window); int i; - if (!screen) { + if (screen == NULL) { return; } @@ -251,7 +251,7 @@ loop(void) break; case SDL_DOLLARRECORD: - SDL_Log("Recorded gesture: %" SDL_PRIs64, event.dgesture.gestureId); + SDL_Log("Recorded gesture: %" SDL_PRIs64 "", event.dgesture.gestureId); break; } } @@ -272,7 +272,7 @@ loop(void) int main(int argc, char *argv[]) { state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (!state) { + if (state == NULL) { return 1; } diff --git a/libs/SDL2/test/testgl2.c b/libs/SDL2/test/testgl2.c index d14ae1675183b466eddf201bb571c826c2aa2985..b58798c32295ee8fd08e591782055666a6d33f12 100644 --- a/libs/SDL2/test/testgl2.c +++ b/libs/SDL2/test/testgl2.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -40,11 +40,11 @@ static GL_Context ctx; static int LoadContext(GL_Context *data) { -#ifdef SDL_VIDEO_DRIVER_UIKIT +#if SDL_VIDEO_DRIVER_UIKIT #define __SDL_NOGETPROCADDR__ -#elif defined(SDL_VIDEO_DRIVER_ANDROID) +#elif SDL_VIDEO_DRIVER_ANDROID #define __SDL_NOGETPROCADDR__ -#elif defined(SDL_VIDEO_DRIVER_PANDORA) +#elif SDL_VIDEO_DRIVER_PANDORA #define __SDL_NOGETPROCADDR__ #endif @@ -205,11 +205,6 @@ Render() ctx.glRotatef(5.0, 1.0, 1.0, 1.0); } -static void LogSwapInterval(void) -{ - SDL_Log("Swap Interval : %d\n", SDL_GL_GetSwapInterval()); -} - int main(int argc, char *argv[]) { int fsaa, accel; @@ -231,7 +226,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (!state) { + if (state == NULL) { return 1; } for (i = 1; i < argc;) { @@ -305,9 +300,7 @@ int main(int argc, char *argv[]) SDL_GetCurrentDisplayMode(0, &mode); SDL_Log("Screen BPP : %" SDL_PRIu32 "\n", SDL_BITSPERPIXEL(mode.format)); - - LogSwapInterval(); - + SDL_Log("Swap Interval : %d\n", SDL_GL_GetSwapInterval()); SDL_GetWindowSize(state->windows[0], &dw, &dh); SDL_Log("Window Size : %d,%d\n", dw, dh); SDL_GL_GetDrawableSize(state->windows[0], &dw, &dh); @@ -415,7 +408,6 @@ int main(int argc, char *argv[]) SDL_GL_MakeCurrent(state->windows[i], context); if (update_swap_interval) { SDL_GL_SetSwapInterval(swap_interval); - LogSwapInterval(); } SDL_GL_GetDrawableSize(state->windows[i], &w, &h); ctx.glViewport(0, 0, w, h); diff --git a/libs/SDL2/test/testgles.c b/libs/SDL2/test/testgles.c index b1577cd8ef23b79f38c48721920aa078cdb01172..498dbce5c2e161c2c0919008766a2ec2942d69d0 100644 --- a/libs/SDL2/test/testgles.c +++ b/libs/SDL2/test/testgles.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -34,7 +34,7 @@ quit(int rc) { int i; - if (context) { + if (context != NULL) { for (i = 0; i < state->num_windows; i++) { if (context[i]) { SDL_GL_DeleteContext(context[i]); @@ -114,7 +114,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (!state) { + if (state == NULL) { return 1; } for (i = 1; i < argc;) { @@ -169,7 +169,7 @@ int main(int argc, char *argv[]) } context = (SDL_GLContext *)SDL_calloc(state->num_windows, sizeof(*context)); - if (!context) { + if (context == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n"); quit(2); } diff --git a/libs/SDL2/test/testgles2.c b/libs/SDL2/test/testgles2.c index bafc524ef4be767ba1c6b533d566696668513492..656e5e6111104fa07d4151d0c2b7b2641989e9d5 100644 --- a/libs/SDL2/test/testgles2.c +++ b/libs/SDL2/test/testgles2.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -65,11 +65,11 @@ static GLES2_Context ctx; static int LoadContext(GLES2_Context *data) { -#ifdef SDL_VIDEO_DRIVER_UIKIT +#if SDL_VIDEO_DRIVER_UIKIT #define __SDL_NOGETPROCADDR__ -#elif defined(SDL_VIDEO_DRIVER_ANDROID) +#elif SDL_VIDEO_DRIVER_ANDROID #define __SDL_NOGETPROCADDR__ -#elif defined(SDL_VIDEO_DRIVER_PANDORA) +#elif SDL_VIDEO_DRIVER_PANDORA #define __SDL_NOGETPROCADDR__ #endif @@ -96,7 +96,7 @@ quit(int rc) { int i; - if (context) { + if (context != NULL) { for (i = 0; i < state->num_windows; i++) { if (context[i]) { SDL_GL_DeleteContext(context[i]); @@ -636,7 +636,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (!state) { + if (state == NULL) { return 1; } for (i = 1; i < argc;) { @@ -696,7 +696,7 @@ int main(int argc, char *argv[]) } context = (SDL_GLContext *)SDL_calloc(state->num_windows, sizeof(*context)); - if (!context) { + if (context == NULL) { SDL_Log("Out of memory!\n"); quit(2); } @@ -893,9 +893,9 @@ int main(int argc, char *argv[]) SDL_Log("%2.2f frames per second\n", ((double)frames * 1000) / (now - then)); } -#if !defined(__ANDROID__) && !defined(__NACL__) +#if !defined(__ANDROID__) && !defined(__NACL__) quit(0); -#endif +#endif return 0; } diff --git a/libs/SDL2/test/testgles2_sdf.c b/libs/SDL2/test/testgles2_sdf.c index 3b15f7298f0a77a07d859c88aea34192784aed42..91f49064a60802cfb98df1e5f88087704ea91c60 100644 --- a/libs/SDL2/test/testgles2_sdf.c +++ b/libs/SDL2/test/testgles2_sdf.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -63,11 +63,11 @@ static GLES2_Context ctx; static int LoadContext(GLES2_Context *data) { -#ifdef SDL_VIDEO_DRIVER_UIKIT +#if SDL_VIDEO_DRIVER_UIKIT #define __SDL_NOGETPROCADDR__ -#elif defined(SDL_VIDEO_DRIVER_ANDROID) +#elif SDL_VIDEO_DRIVER_ANDROID #define __SDL_NOGETPROCADDR__ -#elif defined(SDL_VIDEO_DRIVER_PANDORA) +#elif SDL_VIDEO_DRIVER_PANDORA #define __SDL_NOGETPROCADDR__ #endif @@ -94,7 +94,7 @@ quit(int rc) { int i; - if (context) { + if (context != NULL) { for (i = 0; i < state->num_windows; i++) { if (context[i]) { SDL_GL_DeleteContext(context[i]); @@ -445,7 +445,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (!state) { + if (state == NULL) { return 1; } for (i = 1; i < argc;) { @@ -502,7 +502,7 @@ int main(int argc, char *argv[]) } context = (SDL_GLContext *)SDL_calloc(state->num_windows, sizeof(*context)); - if (!context) { + if (context == NULL) { SDL_Log("Out of memory!\n"); quit(2); } @@ -543,17 +543,17 @@ int main(int argc, char *argv[]) #if 1 path = GetNearbyFilename(f); - if (!path) { + if (path == NULL) { path = SDL_strdup(f); } - if (!path) { + if (path == NULL) { SDL_Log("out of memory\n"); exit(-1); } tmp = SDL_LoadBMP(path); - if (!tmp) { + if (tmp == NULL) { SDL_Log("missing image file: %s", path); exit(-1); } else { diff --git a/libs/SDL2/test/testhaptic.c b/libs/SDL2/test/testhaptic.c index 56602cafb43d8b1fe5a9c02af04f0f70df241b59..fa41863767a94e7444a48794bd80eaa9e0ee7e05 100644 --- a/libs/SDL2/test/testhaptic.c +++ b/libs/SDL2/test/testhaptic.c @@ -16,8 +16,6 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ #include "SDL.h" -#include <stdlib.h> - #ifndef SDL_HAPTIC_DISABLED static SDL_Haptic *haptic; @@ -71,7 +69,7 @@ int main(int argc, char **argv) SDL_Log("%d Haptic devices detected.\n", SDL_NumHaptics()); if (SDL_NumHaptics() > 0) { /* We'll just use index or the first force feedback device found */ - if (!name) { + if (name == NULL) { i = (index != -1) ? index : 0; } /* Try to find matching device */ @@ -90,7 +88,7 @@ int main(int argc, char **argv) } haptic = SDL_HapticOpen(i); - if (!haptic) { + if (haptic == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to create the haptic device: %s\n", SDL_GetError()); return 1; @@ -281,7 +279,7 @@ int main(int argc, char **argv) } /* Quit */ - if (haptic) { + if (haptic != NULL) { SDL_HapticClose(haptic); } SDL_Quit(); diff --git a/libs/SDL2/test/testhittesting.c b/libs/SDL2/test/testhittesting.c index 94c5ea9aea4b3ae5bab76fce7c1fa62cce92eaa2..92ddf8c42c69711285b094b6e7cd8b2e2af52eed 100644 --- a/libs/SDL2/test/testhittesting.c +++ b/libs/SDL2/test/testhittesting.c @@ -106,7 +106,7 @@ int main(int argc, char **argv) if (e.key.keysym.sym == SDLK_ESCAPE) { done = 1; } else if (e.key.keysym.sym == SDLK_x) { - if (!areas) { + if (areas == NULL) { areas = drag_areas; numareas = SDL_arraysize(drag_areas); } else { diff --git a/libs/SDL2/test/testhotplug.c b/libs/SDL2/test/testhotplug.c index aca1741d7c141818ab3960f447e813d4b054c698..1ac73a7fbb682bf75632d2f6bbf077b7b8f1cd1c 100644 --- a/libs/SDL2/test/testhotplug.c +++ b/libs/SDL2/test/testhotplug.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -68,7 +68,7 @@ int main(int argc, char *argv[]) keepGoing = SDL_FALSE; break; case SDL_JOYDEVICEADDED: - if (joystick) { + if (joystick != NULL) { SDL_Log("Only one joystick supported by this test\n"); } else { joystick = SDL_JoystickOpen(event.jdevice.which); diff --git a/libs/SDL2/test/testiconv.c b/libs/SDL2/test/testiconv.c index fcdd72892f198256290292f3b9c8c3062eb8b3cc..b2d13a6aa538165044d20aa2ca3c182dd4f53d19 100644 --- a/libs/SDL2/test/testiconv.c +++ b/libs/SDL2/test/testiconv.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -61,7 +61,7 @@ int main(int argc, char *argv[]) fname = GetResourceFilename(argc > 1 ? argv[1] : NULL, "utf8.txt"); file = fopen(fname, "rb"); - if (!file) { + if (file == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to open %s\n", fname); return 1; } diff --git a/libs/SDL2/test/testime.c b/libs/SDL2/test/testime.c index fb5756dcba58b7daf0637773ad6e7c6f2189040c..51f685b1eb4a4eaedfe8ee51d670646b386b220d 100644 --- a/libs/SDL2/test/testime.c +++ b/libs/SDL2/test/testime.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -29,7 +29,7 @@ #ifdef HAVE_SDL_TTF #ifdef __MACOSX__ #define DEFAULT_FONT "/System/Library/Fonts/华文细黑.ttf" -#elif defined(__WIN32__) +#elif __WIN32__ /* Some japanese font present on at least Windows 8.1. */ #define DEFAULT_FONT "C:\\Windows\\Fonts\\yugothic.ttf" #else @@ -97,7 +97,7 @@ static Uint8 validate_hex(const char *cp, size_t len, Uint32 *np) } n = (n << 4) | c; } - if (np) { + if (np != NULL) { *np = n; } return 1; @@ -116,7 +116,7 @@ static int unifont_init(const char *fontname) /* Allocate memory for the glyph data so the file can be closed after initialization. */ unifontGlyph = (struct UnifontGlyph *)SDL_malloc(unifontGlyphSize); - if (!unifontGlyph) { + if (unifontGlyph == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to allocate %d KiB for glyph data.\n", (int)(unifontGlyphSize + 1023) / 1024); return -1; } @@ -124,20 +124,20 @@ static int unifont_init(const char *fontname) /* Allocate memory for texture pointers for all renderers. */ unifontTexture = (SDL_Texture **)SDL_malloc(unifontTextureSize); - if (!unifontTexture) { + if (unifontTexture == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to allocate %d KiB for texture pointer data.\n", (int)(unifontTextureSize + 1023) / 1024); return -1; } SDL_memset(unifontTexture, 0, unifontTextureSize); filename = GetResourceFilename(NULL, fontname); - if (!filename) { + if (filename == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory\n"); return -1; } hexFile = SDL_RWFromFile(filename, "rb"); SDL_free(filename); - if (!hexFile) { + if (hexFile == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to open font file: %s\n", fontname); return -1; } @@ -269,7 +269,7 @@ static int unifont_load_texture(Uint32 textureID) } textureRGBA = (Uint8 *)SDL_malloc(UNIFONT_TEXTURE_SIZE); - if (!textureRGBA) { + if (textureRGBA == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to allocate %d MiB for a texture.\n", UNIFONT_TEXTURE_SIZE / 1024 / 1024); return -1; } @@ -324,7 +324,7 @@ static Sint32 unifont_draw_glyph(Uint32 codepoint, int rendererID, SDL_Rect *dst } } texture = unifontTexture[UNIFONT_NUM_TEXTURES * rendererID + textureID]; - if (texture) { + if (texture != NULL) { const Uint32 cInTex = codepoint % UNIFONT_GLYPHS_IN_TEXTURE; srcrect.x = cInTex % UNIFONT_GLYPHS_IN_ROW * 16; srcrect.y = cInTex / UNIFONT_GLYPHS_IN_ROW * 16; @@ -338,12 +338,12 @@ static void unifont_cleanup() int i, j; for (i = 0; i < state->num_windows; ++i) { SDL_Renderer *renderer = state->renderers[i]; - if (state->windows[i] == NULL || !renderer) { + if (state->windows[i] == NULL || renderer == NULL) { continue; } for (j = 0; j < UNIFONT_NUM_TEXTURES; j++) { SDL_Texture *tex = unifontTexture[UNIFONT_NUM_TEXTURES * i + j]; - if (tex) { + if (tex != NULL) { SDL_DestroyTexture(tex); } } @@ -530,7 +530,7 @@ void _Redraw(int rendererID) if (cursor) { char *p = utf8_advance(markedText, cursor); char c = 0; - if (!p) { + if (p == NULL) { p = &markedText[SDL_strlen(markedText)]; } @@ -626,7 +626,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (!state) { + if (state == NULL) { return 1; } for (i = 1; i < argc; i++) { @@ -660,7 +660,7 @@ int main(int argc, char *argv[]) TTF_Init(); font = TTF_OpenFont(fontname, DEFAULT_PTSIZE); - if (!font) { + if (font == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to find font: %s\n", TTF_GetError()); return -1; } diff --git a/libs/SDL2/test/testintersections.c b/libs/SDL2/test/testintersections.c index bb95fbe937fba37cc601b3eaee89f4c393691e13..f24d9fbf52ece7a61ee44a3aad92e13cbed177ab 100644 --- a/libs/SDL2/test/testintersections.c +++ b/libs/SDL2/test/testintersections.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -289,7 +289,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (!state) { + if (state == NULL) { return 1; } for (i = 1; i < argc;) { diff --git a/libs/SDL2/test/testjoystick.c b/libs/SDL2/test/testjoystick.c index 38985804943f16abba680f8f40570927aab76a91..adb31dc14fe0ee7811c54b49675112a3e7d62134 100644 --- a/libs/SDL2/test/testjoystick.c +++ b/libs/SDL2/test/testjoystick.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -117,7 +117,7 @@ void loop(void *arg) case SDL_JOYDEVICEADDED: SDL_Log("Joystick device %d added.\n", (int)event.jdevice.which); - if (!joystick) { + if (joystick == NULL) { joystick = SDL_JoystickOpen(event.jdevice.which); if (joystick) { PrintJoystick(joystick); @@ -296,13 +296,13 @@ int main(int argc, char *argv[]) window = SDL_CreateWindow("Joystick Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, 0); - if (!window) { + if (window == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError()); return SDL_FALSE; } screen = SDL_CreateRenderer(window, -1, 0); - if (!screen) { + if (screen == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError()); SDL_DestroyWindow(window); return SDL_FALSE; diff --git a/libs/SDL2/test/testkeys.c b/libs/SDL2/test/testkeys.c index c7b120b4f52979bcb935f81c593ab6dd770bc251..f80f0b9dccec1d367f98e6964e4a1b5b43259c84 100644 --- a/libs/SDL2/test/testkeys.c +++ b/libs/SDL2/test/testkeys.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/test/testloadso.c b/libs/SDL2/test/testloadso.c index fa6923b97a59181cc84fe848ac990564614d95dc..f404a6813372976a10752428ff7afcac04a18757 100644 --- a/libs/SDL2/test/testloadso.c +++ b/libs/SDL2/test/testloadso.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -53,13 +53,13 @@ int main(int argc, char *argv[]) } lib = SDL_LoadObject(libname); - if (!lib) { + if (lib == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_LoadObject('%s') failed: %s\n", libname, SDL_GetError()); retval = 3; } else { fn = (fntype)SDL_LoadFunction(lib, symname); - if (!fn) { + if (fn == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_LoadFunction('%s') failed: %s\n", symname, SDL_GetError()); retval = 4; diff --git a/libs/SDL2/test/testlocale.c b/libs/SDL2/test/testlocale.c index 6e371ca10175aebb6e63c5da64cd8b076143755c..f8ff1a37b0307792241544ceff4a1cbdab3ddb86 100644 --- a/libs/SDL2/test/testlocale.c +++ b/libs/SDL2/test/testlocale.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -17,7 +17,7 @@ static void log_locales(void) { SDL_Locale *locales = SDL_GetPreferredLocales(); - if (!locales) { + if (locales == NULL) { SDL_Log("Couldn't determine locales: %s", SDL_GetError()); } else { SDL_Locale *l; diff --git a/libs/SDL2/test/testlock.c b/libs/SDL2/test/testlock.c index 1af8846fac1d6b89764bb7b632c5846fd68dff10..544ec322b000af3bad5444226ad7eaa9b6db88df 100644 --- a/libs/SDL2/test/testlock.c +++ b/libs/SDL2/test/testlock.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -106,7 +106,7 @@ int main(int argc, char *argv[]) SDL_AtomicSet(&doterminate, 0); mutex = SDL_CreateMutex(); - if (!mutex) { + if (mutex == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create mutex: %s\n", SDL_GetError()); exit(1); } diff --git a/libs/SDL2/test/testmessage.c b/libs/SDL2/test/testmessage.c index d3de67ee7660234e40d18647ed82d6b6ef797c0d..f805f8301a89adc8996bb87e3a3f97a4a6d953a5 100644 --- a/libs/SDL2/test/testmessage.c +++ b/libs/SDL2/test/testmessage.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/test/testmouse.c b/libs/SDL2/test/testmouse.c index 0583ead5a1d61569baf34390e85d2e718b1b8ca5..d1c4edc06b606b401588422af3dc9193fbed2373 100644 --- a/libs/SDL2/test/testmouse.c +++ b/libs/SDL2/test/testmouse.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -83,7 +83,7 @@ void DrawObject(SDL_Renderer *renderer, Object *object) void DrawObjects(SDL_Renderer *renderer) { Object *next = objects; - while (next) { + while (next != NULL) { DrawObject(renderer, next); next = next->next; } @@ -93,7 +93,7 @@ void AppendObject(Object *object) { if (objects) { Object *next = objects; - while (next->next) { + while (next->next != NULL) { next = next->next; } next->next = object; @@ -130,7 +130,7 @@ void loop(void *arg) break; case SDL_MOUSEMOTION: - if (!active) { + if (active == NULL) { break; } @@ -139,7 +139,7 @@ void loop(void *arg) break; case SDL_MOUSEBUTTONDOWN: - if (!active) { + if (active == NULL) { active = SDL_calloc(1, sizeof(*active)); active->x1 = active->x2 = event.button.x; active->y1 = active->y2 = event.button.y; @@ -173,7 +173,7 @@ void loop(void *arg) break; case SDL_MOUSEBUTTONUP: - if (!active) { + if (active == NULL) { break; } @@ -266,13 +266,13 @@ int main(int argc, char *argv[]) window = SDL_CreateWindow("Mouse Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, 0); - if (!window) { + if (window == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError()); return SDL_FALSE; } renderer = SDL_CreateRenderer(window, -1, 0); - if (!renderer) { + if (renderer == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError()); SDL_DestroyWindow(window); return SDL_FALSE; diff --git a/libs/SDL2/test/testmultiaudio.c b/libs/SDL2/test/testmultiaudio.c index 593942038c370dee0f4b3af188577b0bc55dbdbe..2fd352b52e6394ad8ee76747372772995e27735f 100644 --- a/libs/SDL2/test/testmultiaudio.c +++ b/libs/SDL2/test/testmultiaudio.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/test/testnative.c b/libs/SDL2/test/testnative.c index ad47e4a07db5de2ff73e8cf7a1788cde77499d2f..e803b822dd2dca9bde6c4aba3bd23181f67d6caa 100644 --- a/libs/SDL2/test/testnative.c +++ b/libs/SDL2/test/testnative.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -47,7 +47,7 @@ static void quit(int rc) { SDL_VideoQuit(); - if (native_window && factory) { + if (native_window != NULL && factory != NULL) { factory->DestroyNativeWindow(native_window); } exit(rc); @@ -119,19 +119,19 @@ int main(int argc, char *argv[]) break; } } - if (!factory) { + if (factory == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't find native window code for %s driver\n", driver); quit(2); } SDL_Log("Creating native window for %s driver\n", driver); native_window = factory->CreateNativeWindow(WINDOW_W, WINDOW_H); - if (!native_window) { + if (native_window == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create native window\n"); quit(3); } window = SDL_CreateWindowFrom(native_window); - if (!window) { + if (window == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create SDL window: %s\n", SDL_GetError()); quit(4); } @@ -139,7 +139,7 @@ int main(int argc, char *argv[]) /* Create the renderer */ renderer = SDL_CreateRenderer(window, -1, 0); - if (!renderer) { + if (renderer == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError()); quit(5); } @@ -149,7 +149,7 @@ int main(int argc, char *argv[]) SDL_RenderClear(renderer); sprite = LoadTexture(renderer, "icon.bmp", SDL_TRUE, NULL, NULL); - if (!sprite) { + if (sprite == NULL) { quit(6); } @@ -158,7 +158,7 @@ int main(int argc, char *argv[]) SDL_QueryTexture(sprite, NULL, NULL, &sprite_w, &sprite_h); positions = (SDL_Rect *)SDL_malloc(NUM_SPRITES * sizeof(SDL_Rect)); velocities = (SDL_Rect *)SDL_malloc(NUM_SPRITES * sizeof(SDL_Rect)); - if (!positions || !velocities) { + if (positions == NULL || velocities == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n"); quit(2); } diff --git a/libs/SDL2/test/testnative.h b/libs/SDL2/test/testnative.h index e2643902e89e6e4d8d785436ac31109d6752fb10..2ba9005866fa9301d1ca179207df1f11aa424e28 100644 --- a/libs/SDL2/test/testnative.h +++ b/libs/SDL2/test/testnative.h @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/test/testnativeos2.c b/libs/SDL2/test/testnativeos2.c index bbdbe9025eece64d2640ec8caba3f82f65fe2c0c..e0f249121aa967d416bd39ce16ea005664ddd9c8 100644 --- a/libs/SDL2/test/testnativeos2.c +++ b/libs/SDL2/test/testnativeos2.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/test/testnativew32.c b/libs/SDL2/test/testnativew32.c index dfd0b63f4761e8730fd64e2f62d5c74a20e68b4b..e1574583db4e01e91294bebc7cc9c96cdc813d23 100644 --- a/libs/SDL2/test/testnativew32.c +++ b/libs/SDL2/test/testnativew32.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -66,7 +66,7 @@ CreateWindowNative(int w, int h) CreateWindow("SDL Test", "", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, w, h, NULL, NULL, GetModuleHandle(NULL), NULL); - if (!hwnd) { + if (hwnd == NULL) { MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK); return 0; diff --git a/libs/SDL2/test/testnativex11.c b/libs/SDL2/test/testnativex11.c index a891f466ea66d966888b7beb3b58f8bcafe58385..95dc3d64473fd22a7b94bd22a00c0933f71b0d7d 100644 --- a/libs/SDL2/test/testnativex11.c +++ b/libs/SDL2/test/testnativex11.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/test/testoffscreen.c b/libs/SDL2/test/testoffscreen.c index 09ef7fcdd772b3474bf46e12e8767562ae98584b..fa511e8cef688213c692a64c4d8bb8feb15c2560 100644 --- a/libs/SDL2/test/testoffscreen.c +++ b/libs/SDL2/test/testoffscreen.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -115,14 +115,14 @@ int main(int argc, char *argv[]) SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, 0); - if (!window) { + if (window == NULL) { SDL_Log("Couldn't create window: %s\n", SDL_GetError()); return SDL_FALSE; } renderer = SDL_CreateRenderer(window, -1, 0); - if (!renderer) { + if (renderer == NULL) { SDL_Log("Couldn't create renderer: %s\n", SDL_GetError()); return SDL_FALSE; diff --git a/libs/SDL2/test/testoverlay2.c b/libs/SDL2/test/testoverlay2.c index ccfa8e5b4024071ebf6cbcea307d9deaa653fd0b..a5dba68633b767526b81ad88aaf73e64d50b0757 100644 --- a/libs/SDL2/test/testoverlay2.c +++ b/libs/SDL2/test/testoverlay2.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -311,21 +311,21 @@ int main(int argc, char **argv) } RawMooseData = (Uint8 *)SDL_malloc(MOOSEFRAME_SIZE * MOOSEFRAMES_COUNT); - if (!RawMooseData) { + if (RawMooseData == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Can't allocate memory for movie !\n"); quit(1); } /* load the trojan moose images */ filename = GetResourceFilename(NULL, "moose.dat"); - if (!filename) { + if (filename == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory\n"); SDL_free(RawMooseData); return -1; } handle = SDL_RWFromFile(filename, "rb"); SDL_free(filename); - if (!handle) { + if (handle == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Can't find the file moose.dat !\n"); SDL_free(RawMooseData); quit(2); @@ -343,21 +343,21 @@ int main(int argc, char **argv) SDL_WINDOWPOS_UNDEFINED, window_w, window_h, SDL_WINDOW_RESIZABLE); - if (!window) { + if (window == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create window: %s\n", SDL_GetError()); SDL_free(RawMooseData); quit(4); } renderer = SDL_CreateRenderer(window, -1, 0); - if (!renderer) { + if (renderer == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create renderer: %s\n", SDL_GetError()); SDL_free(RawMooseData); quit(4); } MooseTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, MOOSEPIC_W, MOOSEPIC_H); - if (!MooseTexture) { + if (MooseTexture == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create texture: %s\n", SDL_GetError()); SDL_free(RawMooseData); quit(5); diff --git a/libs/SDL2/test/testplatform.c b/libs/SDL2/test/testplatform.c index 353758a7dac2c7b33ac102150811d577fd70b8d8..7e89d2f8199186b9b222c06fc6b81ae780a1bb88 100644 --- a/libs/SDL2/test/testplatform.c +++ b/libs/SDL2/test/testplatform.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -366,7 +366,7 @@ int Test64Bit(SDL_bool verbose) LL_Test *t; int failed = 0; - for (t = LL_Tests; t->routine; t++) { + for (t = LL_Tests; t->routine != NULL; t++) { unsigned long long result = 0; unsigned int *al = (unsigned int *)&t->a; unsigned int *bl = (unsigned int *)&t->b; diff --git a/libs/SDL2/test/testpower.c b/libs/SDL2/test/testpower.c index 1c13b4dbaf5893a75c9ccf85ab94cedc057b70ae..af60258d792c72f79aa20cbe84141bc897f2063b 100644 --- a/libs/SDL2/test/testpower.c +++ b/libs/SDL2/test/testpower.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/test/testqsort.c b/libs/SDL2/test/testqsort.c index 9c1f7646d95c0c7876363617c6511a9ddd2cd25f..271671e91cd10f9fe811143eecc6eb6df63e1109 100644 --- a/libs/SDL2/test/testqsort.c +++ b/libs/SDL2/test/testqsort.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/test/testrelative.c b/libs/SDL2/test/testrelative.c index 3f777cd83d8782b93b098e3ede095e4535d03fc8..88ed0bf5ab111e6af91ba598f5abe1d7d5cdd99b 100644 --- a/libs/SDL2/test/testrelative.c +++ b/libs/SDL2/test/testrelative.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -91,7 +91,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (!state) { + if (state == NULL) { return 1; } for (i = 1; i < argc; ++i) { diff --git a/libs/SDL2/test/testrendercopyex.c b/libs/SDL2/test/testrendercopyex.c index 832101aa376b2ec7acca61a7dd93169f2825df90..de7bc019a37b8567c3c7a4f7bdcfa38c6a8167d3 100644 --- a/libs/SDL2/test/testrendercopyex.c +++ b/libs/SDL2/test/testrendercopyex.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -121,7 +121,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (!state) { + if (state == NULL) { return 1; } diff --git a/libs/SDL2/test/testrendertarget.c b/libs/SDL2/test/testrendertarget.c index 9693df4f84fb902cc3a714abe66b1dfb3cfc982d..1ae609987436cb6c63054eedd3e8ecdb06bdafcf 100644 --- a/libs/SDL2/test/testrendertarget.c +++ b/libs/SDL2/test/testrendertarget.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -138,7 +138,7 @@ Draw(DrawState *s) SDL_RenderGetViewport(s->renderer, &viewport); target = SDL_CreateTexture(s->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, viewport.w, viewport.h); - if (!target) { + if (target == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create render target texture: %s\n", SDL_GetError()); return SDL_FALSE; } @@ -214,7 +214,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (!state) { + if (state == NULL) { return 1; } for (i = 1; i < argc;) { diff --git a/libs/SDL2/test/testresample.c b/libs/SDL2/test/testresample.c index 21ff8e170ce5194dc7e6a76b5703144e18a9dfea..8bb603ac20671f831dc34cff99d1efb20aed5f18 100644 --- a/libs/SDL2/test/testresample.c +++ b/libs/SDL2/test/testresample.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -57,7 +57,7 @@ int main(int argc, char **argv) cvt.len = len; cvt.buf = (Uint8 *)SDL_malloc((size_t)len * cvt.len_mult); - if (!cvt.buf) { + if (cvt.buf == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory.\n"); SDL_FreeWAV(data); SDL_Quit(); @@ -75,7 +75,7 @@ int main(int argc, char **argv) /* write out a WAV header... */ io = SDL_RWFromFile(argv[2], "wb"); - if (!io) { + if (io == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "fopen('%s') failed: %s\n", argv[2], SDL_GetError()); SDL_free(cvt.buf); SDL_FreeWAV(data); diff --git a/libs/SDL2/test/testrumble.c b/libs/SDL2/test/testrumble.c index 401b7605e293a4a7e4fa571173d5a671ee7f4265..d6288d59230b19876b50f856d7415b11ac6ebb07 100644 --- a/libs/SDL2/test/testrumble.c +++ b/libs/SDL2/test/testrumble.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -71,7 +71,7 @@ int main(int argc, char **argv) SDL_Log("%d Haptic devices detected.\n", SDL_NumHaptics()); if (SDL_NumHaptics() > 0) { /* We'll just use index or the first force feedback device found */ - if (!name) { + if (name == NULL) { i = (index != -1) ? index : 0; } /* Try to find matching device */ @@ -90,7 +90,7 @@ int main(int argc, char **argv) } haptic = SDL_HapticOpen(i); - if (!haptic) { + if (haptic == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to create the haptic device: %s\n", SDL_GetError()); return 1; @@ -129,7 +129,7 @@ int main(int argc, char **argv) SDL_Delay(2000); /* Quit */ - if (haptic) { + if (haptic != NULL) { SDL_HapticClose(haptic); } SDL_Quit(); diff --git a/libs/SDL2/test/testscale.c b/libs/SDL2/test/testscale.c index 3659c91490783b9bca1464881b91e31e126e53b6..dca3d09600afeb568b26d769f7e57ab656f681ec 100644 --- a/libs/SDL2/test/testscale.c +++ b/libs/SDL2/test/testscale.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -111,7 +111,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (!state) { + if (state == NULL) { return 1; } diff --git a/libs/SDL2/test/testsem.c b/libs/SDL2/test/testsem.c index 5740833f43082b210b3e7da783192209706ba38a..c0036e882f613fcc03aa9af42f6339cfd1ead698 100644 --- a/libs/SDL2/test/testsem.c +++ b/libs/SDL2/test/testsem.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/test/testsensor.c b/libs/SDL2/test/testsensor.c index 2b9af5835ffd40f24e92cc7252691e0b03fc40f0..3da7e015e7f8228d7b147cce26dded573ea5c331 100644 --- a/libs/SDL2/test/testsensor.c +++ b/libs/SDL2/test/testsensor.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -36,7 +36,7 @@ static const char *GetSensorTypeString(SDL_SensorType type) static void HandleSensorEvent(SDL_SensorEvent *event) { SDL_Sensor *sensor = SDL_SensorFromInstanceID(event->which); - if (!sensor) { + if (sensor == NULL) { SDL_Log("Couldn't get sensor for sensor event\n"); return; } @@ -78,7 +78,7 @@ int main(int argc, char **argv) if (SDL_SensorGetDeviceType(i) != SDL_SENSOR_UNKNOWN) { SDL_Sensor *sensor = SDL_SensorOpen(i); - if (!sensor) { + if (sensor == NULL) { SDL_Log("Couldn't open sensor %" SDL_PRIs32 ": %s\n", SDL_SensorGetDeviceInstanceID(i), SDL_GetError()); } else { ++num_opened; diff --git a/libs/SDL2/test/testshader.c b/libs/SDL2/test/testshader.c index 48535dca78d2d0b8ad501748208cd4b3e2269171..2371fcefbc87258db1e7a95a0349819d3edac15f 100644 --- a/libs/SDL2/test/testshader.c +++ b/libs/SDL2/test/testshader.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -109,36 +109,36 @@ static ShaderData shaders[NUM_SHADERS] = { "}" }, }; -static PFNGLATTACHOBJECTARBPROC pglAttachObjectARB; -static PFNGLCOMPILESHADERARBPROC pglCompileShaderARB; -static PFNGLCREATEPROGRAMOBJECTARBPROC pglCreateProgramObjectARB; -static PFNGLCREATESHADEROBJECTARBPROC pglCreateShaderObjectARB; -static PFNGLDELETEOBJECTARBPROC pglDeleteObjectARB; -static PFNGLGETINFOLOGARBPROC pglGetInfoLogARB; -static PFNGLGETOBJECTPARAMETERIVARBPROC pglGetObjectParameterivARB; -static PFNGLGETUNIFORMLOCATIONARBPROC pglGetUniformLocationARB; -static PFNGLLINKPROGRAMARBPROC pglLinkProgramARB; -static PFNGLSHADERSOURCEARBPROC pglShaderSourceARB; -static PFNGLUNIFORM1IARBPROC pglUniform1iARB; -static PFNGLUSEPROGRAMOBJECTARBPROC pglUseProgramObjectARB; +static PFNGLATTACHOBJECTARBPROC glAttachObjectARB; +static PFNGLCOMPILESHADERARBPROC glCompileShaderARB; +static PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB; +static PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB; +static PFNGLDELETEOBJECTARBPROC glDeleteObjectARB; +static PFNGLGETINFOLOGARBPROC glGetInfoLogARB; +static PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB; +static PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB; +static PFNGLLINKPROGRAMARBPROC glLinkProgramARB; +static PFNGLSHADERSOURCEARBPROC glShaderSourceARB; +static PFNGLUNIFORM1IARBPROC glUniform1iARB; +static PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB; static SDL_bool CompileShader(GLhandleARB shader, const char *source) { GLint status = 0; - pglShaderSourceARB(shader, 1, &source, NULL); - pglCompileShaderARB(shader); - pglGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &status); + glShaderSourceARB(shader, 1, &source, NULL); + glCompileShaderARB(shader); + glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &status); if (status == 0) { GLint length = 0; char *info; - pglGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length); + glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length); info = (char *)SDL_malloc((size_t)length + 1); - if (!info) { + if (info == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!"); } else { - pglGetInfoLogARB(shader, length, NULL, info); + glGetInfoLogARB(shader, length, NULL, info); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to compile shader:\n%s\n%s", source, info); SDL_free(info); } @@ -152,21 +152,21 @@ static SDL_bool LinkProgram(ShaderData *data) { GLint status = 0; - pglAttachObjectARB(data->program, data->vert_shader); - pglAttachObjectARB(data->program, data->frag_shader); - pglLinkProgramARB(data->program); + glAttachObjectARB(data->program, data->vert_shader); + glAttachObjectARB(data->program, data->frag_shader); + glLinkProgramARB(data->program); - pglGetObjectParameterivARB(data->program, GL_OBJECT_LINK_STATUS_ARB, &status); + glGetObjectParameterivARB(data->program, GL_OBJECT_LINK_STATUS_ARB, &status); if (status == 0) { GLint length = 0; char *info; - pglGetObjectParameterivARB(data->program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length); + glGetObjectParameterivARB(data->program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length); info = (char *)SDL_malloc((size_t)length + 1); - if (!info) { + if (info == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!"); } else { - pglGetInfoLogARB(data->program, length, NULL, info); + glGetInfoLogARB(data->program, length, NULL, info); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to link program:\n%s", info); SDL_free(info); } @@ -185,16 +185,16 @@ static SDL_bool CompileShaderProgram(ShaderData *data) glGetError(); /* Create one program object to rule them all */ - data->program = pglCreateProgramObjectARB(); + data->program = glCreateProgramObjectARB(); /* Create the vertex shader */ - data->vert_shader = pglCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); + data->vert_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); if (!CompileShader(data->vert_shader, data->vert_source)) { return SDL_FALSE; } /* Create the fragment shader */ - data->frag_shader = pglCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); + data->frag_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); if (!CompileShader(data->frag_shader, data->frag_source)) { return SDL_FALSE; } @@ -205,16 +205,16 @@ static SDL_bool CompileShaderProgram(ShaderData *data) } /* Set up some uniform variables */ - pglUseProgramObjectARB(data->program); + glUseProgramObjectARB(data->program); for (i = 0; i < num_tmus_bound; ++i) { char tex_name[5]; (void)SDL_snprintf(tex_name, SDL_arraysize(tex_name), "tex%d", i); - location = pglGetUniformLocationARB(data->program, tex_name); + location = glGetUniformLocationARB(data->program, tex_name); if (location >= 0) { - pglUniform1iARB(location, i); + glUniform1iARB(location, i); } } - pglUseProgramObjectARB(0); + glUseProgramObjectARB(0); return (glGetError() == GL_NO_ERROR) ? SDL_TRUE : SDL_FALSE; } @@ -222,9 +222,9 @@ static SDL_bool CompileShaderProgram(ShaderData *data) static void DestroyShaderProgram(ShaderData *data) { if (shaders_supported) { - pglDeleteObjectARB(data->vert_shader); - pglDeleteObjectARB(data->frag_shader); - pglDeleteObjectARB(data->program); + glDeleteObjectARB(data->vert_shader); + glDeleteObjectARB(data->frag_shader); + glDeleteObjectARB(data->program); } } @@ -238,30 +238,30 @@ static SDL_bool InitShaders() SDL_GL_ExtensionSupported("GL_ARB_shading_language_100") && SDL_GL_ExtensionSupported("GL_ARB_vertex_shader") && SDL_GL_ExtensionSupported("GL_ARB_fragment_shader")) { - pglAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)SDL_GL_GetProcAddress("glAttachObjectARB"); - pglCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)SDL_GL_GetProcAddress("glCompileShaderARB"); - pglCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)SDL_GL_GetProcAddress("glCreateProgramObjectARB"); - pglCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)SDL_GL_GetProcAddress("glCreateShaderObjectARB"); - pglDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)SDL_GL_GetProcAddress("glDeleteObjectARB"); - pglGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)SDL_GL_GetProcAddress("glGetInfoLogARB"); - pglGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)SDL_GL_GetProcAddress("glGetObjectParameterivARB"); - pglGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)SDL_GL_GetProcAddress("glGetUniformLocationARB"); - pglLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)SDL_GL_GetProcAddress("glLinkProgramARB"); - pglShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)SDL_GL_GetProcAddress("glShaderSourceARB"); - pglUniform1iARB = (PFNGLUNIFORM1IARBPROC)SDL_GL_GetProcAddress("glUniform1iARB"); - pglUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)SDL_GL_GetProcAddress("glUseProgramObjectARB"); - if (pglAttachObjectARB && - pglCompileShaderARB && - pglCreateProgramObjectARB && - pglCreateShaderObjectARB && - pglDeleteObjectARB && - pglGetInfoLogARB && - pglGetObjectParameterivARB && - pglGetUniformLocationARB && - pglLinkProgramARB && - pglShaderSourceARB && - pglUniform1iARB && - pglUseProgramObjectARB) { + glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)SDL_GL_GetProcAddress("glAttachObjectARB"); + glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)SDL_GL_GetProcAddress("glCompileShaderARB"); + glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)SDL_GL_GetProcAddress("glCreateProgramObjectARB"); + glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)SDL_GL_GetProcAddress("glCreateShaderObjectARB"); + glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)SDL_GL_GetProcAddress("glDeleteObjectARB"); + glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)SDL_GL_GetProcAddress("glGetInfoLogARB"); + glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)SDL_GL_GetProcAddress("glGetObjectParameterivARB"); + glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)SDL_GL_GetProcAddress("glGetUniformLocationARB"); + glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)SDL_GL_GetProcAddress("glLinkProgramARB"); + glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)SDL_GL_GetProcAddress("glShaderSourceARB"); + glUniform1iARB = (PFNGLUNIFORM1IARBPROC)SDL_GL_GetProcAddress("glUniform1iARB"); + glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)SDL_GL_GetProcAddress("glUseProgramObjectARB"); + if (glAttachObjectARB && + glCompileShaderARB && + glCreateProgramObjectARB && + glCreateShaderObjectARB && + glDeleteObjectARB && + glGetInfoLogARB && + glGetObjectParameterivARB && + glGetUniformLocationARB && + glLinkProgramARB && + glShaderSourceARB && + glUniform1iARB && + glUseProgramObjectARB) { shaders_supported = SDL_TRUE; } } @@ -329,7 +329,7 @@ SDL_GL_LoadTexture(SDL_Surface *surface, GLfloat *texcoord) 0x00FF0000, 0x0000FF00, 0x000000FF #endif ); - if (!image) { + if (image == NULL) { return 0; } @@ -420,7 +420,7 @@ void DrawGLScene(SDL_Window *window, GLuint texture, GLfloat *texcoord) glBindTexture(GL_TEXTURE_2D, texture); glColor3f(1.0f, 1.0f, 1.0f); if (shaders_supported) { - pglUseProgramObjectARB(shaders[current_shader].program); + glUseProgramObjectARB(shaders[current_shader].program); } glBegin(GL_QUADS); /* start drawing a polygon (4 sided) */ @@ -435,7 +435,7 @@ void DrawGLScene(SDL_Window *window, GLuint texture, GLfloat *texcoord) glEnd(); /* done with the polygon */ if (shaders_supported) { - pglUseProgramObjectARB(0); + glUseProgramObjectARB(0); } glDisable(GL_TEXTURE_2D); @@ -462,7 +462,7 @@ int main(int argc, char **argv) /* Create a 640x480 OpenGL screen */ window = SDL_CreateWindow("Shader Demo", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_OPENGL); - if (!window) { + if (window == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to create OpenGL window: %s\n", SDL_GetError()); SDL_Quit(); exit(2); @@ -475,7 +475,7 @@ int main(int argc, char **argv) } surface = SDL_LoadBMP("icon.bmp"); - if (!surface) { + if (surface == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to load icon.bmp: %s\n", SDL_GetError()); SDL_Quit(); exit(3); diff --git a/libs/SDL2/test/testshape.c b/libs/SDL2/test/testshape.c index 112ec0c60b41eb018ab56745e3b02368c7365ccc..4e3c12cdddaff878c525db7e2fe7f0846ba84464 100644 --- a/libs/SDL2/test/testshape.c +++ b/libs/SDL2/test/testshape.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -71,7 +71,7 @@ int main(int argc, char **argv) num_pictures = argc - 1; pictures = (LoadedPicture *)SDL_malloc(sizeof(LoadedPicture) * num_pictures); - if (!pictures) { + if (pictures == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not allocate memory."); exit(1); } @@ -106,7 +106,7 @@ int main(int argc, char **argv) SHAPED_WINDOW_DIMENSION, SHAPED_WINDOW_DIMENSION, 0); SDL_SetWindowPosition(window, SHAPED_WINDOW_X, SHAPED_WINDOW_Y); - if (!window) { + if (window == NULL) { for (i = 0; i < num_pictures; i++) { SDL_FreeSurface(pictures[i].surface); } @@ -116,7 +116,7 @@ int main(int argc, char **argv) exit(-4); } renderer = SDL_CreateRenderer(window, -1, 0); - if (!renderer) { + if (renderer == NULL) { SDL_DestroyWindow(window); for (i = 0; i < num_pictures; i++) { SDL_FreeSurface(pictures[i].surface); diff --git a/libs/SDL2/test/testsprite2.c b/libs/SDL2/test/testsprite2.c index 71b565678b211b9fd3dfbf7f86642726de565c9a..89037fd09c5538ce360b20e51a9a7e137a74c9f8 100644 --- a/libs/SDL2/test/testsprite2.c +++ b/libs/SDL2/test/testsprite2.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -392,30 +392,22 @@ void MoveSprites(SDL_Renderer *renderer, SDL_Texture *sprite) SDL_RenderPresent(renderer); } -static void MoveAllSprites() -{ - int i; - - for (i = 0; i < state->num_windows; ++i) { - if (state->windows[i] == NULL) { - continue; - } - MoveSprites(state->renderers[i], sprites[i]); - } -} - void loop() { Uint32 now; + int i; SDL_Event event; /* Check for events */ while (SDL_PollEvent(&event)) { SDLTest_CommonEvent(state, &event, &done); } - - MoveAllSprites(); - + for (i = 0; i < state->num_windows; ++i) { + if (state->windows[i] == NULL) { + continue; + } + MoveSprites(state->renderers[i], sprites[i]); + } #ifdef __EMSCRIPTEN__ if (done) { emscripten_cancel_main_loop(); @@ -434,14 +426,6 @@ void loop() } } -static int SDLCALL ExposeEventWatcher(void *userdata, SDL_Event *event) -{ - if (event->type == SDL_WINDOWEVENT && event->window.event == SDL_WINDOWEVENT_EXPOSED) { - MoveAllSprites(); - } - return 0; -} - int main(int argc, char *argv[]) { int i; @@ -453,7 +437,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (!state) { + if (state == NULL) { return 1; } @@ -541,7 +525,7 @@ int main(int argc, char *argv[]) /* Create the windows, initialize the renderers, and load the textures */ sprites = (SDL_Texture **)SDL_malloc(state->num_windows * sizeof(*sprites)); - if (!sprites) { + if (sprites == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n"); quit(2); } @@ -557,7 +541,7 @@ int main(int argc, char *argv[]) /* Allocate memory for the sprite info */ positions = (SDL_Rect *)SDL_malloc(num_sprites * sizeof(SDL_Rect)); velocities = (SDL_Rect *)SDL_malloc(num_sprites * sizeof(SDL_Rect)); - if (!positions || !velocities) { + if (positions == NULL || velocities == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n"); quit(2); } @@ -584,9 +568,6 @@ int main(int argc, char *argv[]) } } - /* Add an event watcher to redraw from within modal window resize/move loops */ - SDL_AddEventWatch(ExposeEventWatcher, NULL); - /* Main render loop */ frames = 0; next_fps_check = SDL_GetTicks() + fps_check_delay; diff --git a/libs/SDL2/test/testspriteminimal.c b/libs/SDL2/test/testspriteminimal.c index b81101eb5d05b2f97b1eff26f83a53f150bd6827..16b4fa4a368516051461123af39d1927bfbe9556 100644 --- a/libs/SDL2/test/testspriteminimal.c +++ b/libs/SDL2/test/testspriteminimal.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -109,7 +109,7 @@ int main(int argc, char *argv[]) sprite = LoadTexture(renderer, "icon.bmp", SDL_TRUE, &sprite_w, &sprite_h); - if (!sprite) { + if (sprite == NULL) { quit(2); } diff --git a/libs/SDL2/test/teststreaming.c b/libs/SDL2/test/teststreaming.c index 45202a7797d148253ed5008fcb96bde4aa59797f..15c1aefea39d8bec6cdbf34aa5fb638af46fd18c 100644 --- a/libs/SDL2/test/teststreaming.c +++ b/libs/SDL2/test/teststreaming.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -141,13 +141,13 @@ int main(int argc, char **argv) /* load the moose images */ filename = GetResourceFilename(NULL, "moose.dat"); - if (!filename) { + if (filename == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory\n"); return -1; } handle = SDL_RWFromFile(filename, "rb"); SDL_free(filename); - if (!handle) { + if (handle == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Can't find the file moose.dat !\n"); quit(2); } @@ -160,19 +160,19 @@ int main(int argc, char **argv) SDL_WINDOWPOS_UNDEFINED, MOOSEPIC_W * 4, MOOSEPIC_H * 4, SDL_WINDOW_RESIZABLE); - if (!window) { + if (window == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create window: %s\n", SDL_GetError()); quit(3); } renderer = SDL_CreateRenderer(window, -1, 0); - if (!renderer) { + if (renderer == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create renderer: %s\n", SDL_GetError()); quit(4); } MooseTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, MOOSEPIC_W, MOOSEPIC_H); - if (!MooseTexture) { + if (MooseTexture == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create texture: %s\n", SDL_GetError()); quit(5); } diff --git a/libs/SDL2/test/testsurround.c b/libs/SDL2/test/testsurround.c index b7dc7d7818cce50b7a30d7d1ce6da87ba34cbb99..b28436977edbc6a6ddda47f6203aac74c8a23339 100644 --- a/libs/SDL2/test/testsurround.c +++ b/libs/SDL2/test/testsurround.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/test/testthread.c b/libs/SDL2/test/testthread.c index 5ceac05ffac38ef8b45f6c0d21a51e78ff28e85c..f6d967560f7c12f62259d9024f742d8166f1482c 100644 --- a/libs/SDL2/test/testthread.c +++ b/libs/SDL2/test/testthread.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -114,7 +114,7 @@ int main(int argc, char *argv[]) alive = 1; thread = SDL_CreateThread(ThreadFunc, "One", "#1"); - if (!thread) { + if (thread == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create thread: %s\n", SDL_GetError()); quit(1); } @@ -128,7 +128,7 @@ int main(int argc, char *argv[]) alive = 1; (void)signal(SIGTERM, killed); thread = SDL_CreateThread(ThreadFunc, "Two", "#2"); - if (!thread) { + if (thread == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create thread: %s\n", SDL_GetError()); quit(1); } diff --git a/libs/SDL2/test/testtimer.c b/libs/SDL2/test/testtimer.c index eea9730c534ec5f9a21b2e06c4d4faa4c99f2954..54a903ad087dc0d30e21de7b6ab6c9d2ff3d843a 100644 --- a/libs/SDL2/test/testtimer.c +++ b/libs/SDL2/test/testtimer.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -18,38 +18,9 @@ #include <stdio.h> #include "SDL.h" -#include "SDL_test.h" #define DEFAULT_RESOLUTION 1 -static int test_sdl_delay_within_bounds(void) { - const int testDelay = 100; - const int marginOfError = 25; - Uint64 result; - Uint64 result2; - Sint64 difference; - - SDLTest_ResetAssertSummary(); - - /* Get ticks count - should be non-zero by now */ - result = SDL_GetTicks(); - SDLTest_AssertPass("Call to SDL_GetTicks()"); - SDLTest_AssertCheck(result > 0, "Check result value, expected: >0, got: %" SDL_PRIu64, result); - - /* Delay a bit longer and measure ticks and verify difference */ - SDL_Delay(testDelay); - SDLTest_AssertPass("Call to SDL_Delay(%d)", testDelay); - result2 = SDL_GetTicks(); - SDLTest_AssertPass("Call to SDL_GetTicks()"); - SDLTest_AssertCheck(result2 > 0, "Check result value, expected: >0, got: %" SDL_PRIu64, result2); - difference = result2 - result; - SDLTest_AssertCheck(difference > (testDelay - marginOfError), "Check difference, expected: >%d, got: %" SDL_PRIu64, testDelay - marginOfError, difference); - /* Disabled because this might fail on non-interactive systems. */ - SDLTest_AssertCheck(difference < (testDelay + marginOfError), "Check difference, expected: <%d, got: %" SDL_PRIu64, testDelay + marginOfError, difference); - - return SDLTest_AssertSummaryToTestResult() == TEST_RESULT_PASSED ? 0 : 1; -} - static int ticks = 0; static Uint32 SDLCALL @@ -68,43 +39,15 @@ callback(Uint32 interval, void *param) int main(int argc, char *argv[]) { - int i; - int desired = -1; + int i, desired; SDL_TimerID t1, t2, t3; Uint64 start64, now64; Uint32 start32, now32; Uint64 start, now; - SDL_bool run_interactive_tests = SDL_FALSE; - int return_code = 0; /* Enable standard application logging */ SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); - /* Parse commandline */ - for (i = 1; i < argc;) { - int consumed = 0; - - if (!consumed) { - if (SDL_strcmp(argv[i], "--interactive") == 0) { - run_interactive_tests = SDL_TRUE; - consumed = 1; - } else if (desired < 0) { - char *endptr; - - desired = SDL_strtoul(argv[i], &endptr, 0); - if (desired != 0 && endptr != argv[i] && *endptr == '\0') { - consumed = 1; - } - } - } - if (consumed <= 0) { - SDL_Log("Usage: %s [--interactive] [interval]", argv[0]); - return 1; - } - - i += consumed; - } - if (SDL_Init(SDL_INIT_TIMER) < 0) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError()); return 1; @@ -131,11 +74,14 @@ int main(int argc, char *argv[]) } } - if (desired < 0) { + /* Start the timer */ + desired = 0; + if (argv[1]) { + desired = SDL_atoi(argv[1]); + } + if (desired == 0) { desired = DEFAULT_RESOLUTION; } - - /* Start the timer */ t1 = SDL_AddTimer(desired, ticktock, NULL); /* Wait 10 seconds */ @@ -156,17 +102,14 @@ int main(int argc, char *argv[]) t1 = SDL_AddTimer(100, callback, (void *)1); if (!t1) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create timer 1: %s\n", SDL_GetError()); - return_code = 1; } t2 = SDL_AddTimer(50, callback, (void *)2); if (!t2) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create timer 2: %s\n", SDL_GetError()); - return_code = 1; } t3 = SDL_AddTimer(233, callback, (void *)3); if (!t3) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create timer 3: %s\n", SDL_GetError()); - return_code = 1; } /* Wait 10 seconds */ @@ -198,11 +141,8 @@ int main(int argc, char *argv[]) now32 = SDL_GetTicks(); SDL_Log("Delay 1 second = %d ms in ticks, %d ms in ticks64, %f ms according to performance counter\n", (int)(now32 - start32), (int)(now64 - start64), (double)((now - start) * 1000) / SDL_GetPerformanceFrequency()); - if (run_interactive_tests) { - return_code |= test_sdl_delay_within_bounds(); - } SDL_Quit(); - return return_code; + return 0; } /* vi: set ts=4 sw=4 expandtab: */ diff --git a/libs/SDL2/test/testurl.c b/libs/SDL2/test/testurl.c index 2008186f3a69f442af4486752b1fe715d721d9b9..ef22083ffb91081f1e7e94d4e1d13ed643021a62 100644 --- a/libs/SDL2/test/testurl.c +++ b/libs/SDL2/test/testurl.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/test/testutils.c b/libs/SDL2/test/testutils.c index 3b76ea8331f15704ef6bea2cfbb2cfec14d59913..20efef027a37afa5864494ba014c91bd9bbe7d1a 100644 --- a/libs/SDL2/test/testutils.c +++ b/libs/SDL2/test/testutils.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> Copyright 2022 Collabora Ltd. This software is provided 'as-is', without any express or implied @@ -28,13 +28,13 @@ GetNearbyFilename(const char *file) base = SDL_GetBasePath(); - if (base) { + if (base != NULL) { SDL_RWops *rw; size_t len = SDL_strlen(base) + SDL_strlen(file) + 1; path = SDL_malloc(len); - if (!path) { + if (path == NULL) { SDL_free(base); SDL_OutOfMemory(); return NULL; @@ -54,7 +54,7 @@ GetNearbyFilename(const char *file) } path = SDL_strdup(file); - if (!path) { + if (path == NULL) { SDL_OutOfMemory(); } return path; @@ -72,10 +72,10 @@ GetNearbyFilename(const char *file) char * GetResourceFilename(const char *user_specified, const char *def) { - if (user_specified) { + if (user_specified != NULL) { char *ret = SDL_strdup(user_specified); - if (!ret) { + if (ret == NULL) { SDL_OutOfMemory(); } @@ -105,12 +105,12 @@ LoadTexture(SDL_Renderer *renderer, const char *file, SDL_bool transparent, path = GetNearbyFilename(file); - if (path) { + if (path != NULL) { file = path; } temp = SDL_LoadBMP(file); - if (!temp) { + if (temp == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s", file, SDL_GetError()); } else { /* Set transparent pixel as the pixel at (0,0) */ @@ -137,16 +137,16 @@ LoadTexture(SDL_Renderer *renderer, const char *file, SDL_bool transparent, } } - if (width_out) { + if (width_out != NULL) { *width_out = temp->w; } - if (height_out) { + if (height_out != NULL) { *height_out = temp->h; } texture = SDL_CreateTextureFromSurface(renderer, temp); - if (!texture) { + if (texture == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture: %s\n", SDL_GetError()); } } diff --git a/libs/SDL2/test/testutils.h b/libs/SDL2/test/testutils.h index a10aaadd311ba2f815f20facc99e7c287c1e46b4..1f69673ce0d7a73f34a2f2f8fffac1c2f5145db3 100644 --- a/libs/SDL2/test/testutils.h +++ b/libs/SDL2/test/testutils.h @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> Copyright 2022 Collabora Ltd. This software is provided 'as-is', without any express or implied diff --git a/libs/SDL2/test/testver.c b/libs/SDL2/test/testver.c index 409b1f12f3967d81759bec4566963874a5cf381a..eeecb14a69d535562b9d44e1f533cea386a5d40a 100644 --- a/libs/SDL2/test/testver.c +++ b/libs/SDL2/test/testver.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/test/testviewport.c b/libs/SDL2/test/testviewport.c index ee76a3782f9b612a3e2859382ee22dd8981e0943..932f24832549ec434cbfac027ddbf6374fb9f158 100644 --- a/libs/SDL2/test/testviewport.c +++ b/libs/SDL2/test/testviewport.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -152,7 +152,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (!state) { + if (state == NULL) { return 1; } @@ -180,7 +180,7 @@ int main(int argc, char *argv[]) sprite = LoadTexture(state->renderers[0], "icon.bmp", SDL_TRUE, &sprite_w, &sprite_h); - if (!sprite) { + if (sprite == NULL) { quit(2); } diff --git a/libs/SDL2/test/testvulkan.c b/libs/SDL2/test/testvulkan.c index 8a4ac893491e4192a8fcd61ad6e7d1a6d1face31..acdde28fd2e8a66666a4c8e7f608d3949829b220 100644 --- a/libs/SDL2/test/testvulkan.c +++ b/libs/SDL2/test/testvulkan.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -236,7 +236,7 @@ static void createInstance(void) quit(2); } extensions = (const char **)SDL_malloc(sizeof(const char *) * extensionCount); - if (!extensions) { + if (extensions == NULL) { SDL_OutOfMemory(); quit(2); } @@ -312,7 +312,7 @@ static void findPhysicalDevice(void) quit(2); } physicalDevices = (VkPhysicalDevice *)SDL_malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount); - if (!physicalDevices) { + if (physicalDevices == NULL) { SDL_OutOfMemory(); quit(2); } @@ -346,7 +346,7 @@ static void findPhysicalDevice(void) SDL_free(queueFamiliesProperties); queueFamiliesPropertiesAllocatedSize = queueFamiliesCount; queueFamiliesProperties = (VkQueueFamilyProperties *)SDL_malloc(sizeof(VkQueueFamilyProperties) * queueFamiliesPropertiesAllocatedSize); - if (!queueFamiliesProperties) { + if (queueFamiliesProperties == NULL) { SDL_free(physicalDevices); SDL_free(deviceExtensions); SDL_OutOfMemory(); @@ -408,7 +408,7 @@ static void findPhysicalDevice(void) SDL_free(deviceExtensions); deviceExtensionsAllocatedSize = deviceExtensionCount; deviceExtensions = SDL_malloc(sizeof(VkExtensionProperties) * deviceExtensionsAllocatedSize); - if (!deviceExtensions) { + if (deviceExtensions == NULL) { SDL_free(physicalDevices); SDL_free(queueFamiliesProperties); SDL_OutOfMemory(); @@ -929,7 +929,7 @@ static void initVulkan(void) SDL_Vulkan_LoadLibrary(NULL); vulkanContexts = (VulkanContext *)SDL_calloc(state->num_windows, sizeof(VulkanContext)); - if (!vulkanContexts) { + if (vulkanContexts == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!"); quit(2); } @@ -1092,7 +1092,7 @@ int main(int argc, char **argv) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (!state) { + if (state == NULL) { return 1; } diff --git a/libs/SDL2/test/testwm2.c b/libs/SDL2/test/testwm2.c index 5236a7f5b97c2562fbc9514edac8704623cabcc4..7fc189bd75357a61a0215685d0c7b6731b733595 100644 --- a/libs/SDL2/test/testwm2.c +++ b/libs/SDL2/test/testwm2.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -208,7 +208,7 @@ void loop() } if (event.type == SDL_MOUSEBUTTONUP) { SDL_Window *window = SDL_GetMouseFocus(); - if (highlighted_mode != -1 && window) { + if (highlighted_mode != -1 && window != NULL) { const int display_index = SDL_GetWindowDisplayIndex(window); SDL_DisplayMode mode; if (0 != SDL_GetDisplayMode(display_index, highlighted_mode, &mode)) { @@ -223,7 +223,7 @@ void loop() for (i = 0; i < state->num_windows; ++i) { SDL_Window *window = state->windows[i]; SDL_Renderer *renderer = state->renderers[i]; - if (window && renderer) { + if (window != NULL && renderer != NULL) { int y = 0; SDL_Rect viewport, menurect; @@ -262,7 +262,7 @@ int main(int argc, char *argv[]) /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); - if (!state) { + if (state == NULL) { return 1; } diff --git a/libs/SDL2/test/testyuv.c b/libs/SDL2/test/testyuv.c index e9038ed0d3df28b49aa046f215800e92d73267a1..e7373a8b129e9e97dc89e5c0ed4360a60e3799f5 100644 --- a/libs/SDL2/test/testyuv.c +++ b/libs/SDL2/test/testyuv.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -75,7 +75,7 @@ static SDL_bool verify_yuv_data(Uint32 format, const Uint8 *yuv, int yuv_pitch, SDL_bool result = SDL_FALSE; rgb = (Uint8 *)SDL_malloc(size); - if (!rgb) { + if (rgb == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory"); return SDL_FALSE; } @@ -126,7 +126,7 @@ static int run_automated_tests(int pattern_size, int extra_pitch) int yuv1_pitch, yuv2_pitch; int result = -1; - if (!pattern || !yuv1 || !yuv2) { + if (pattern == NULL || yuv1 == NULL || yuv2 == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't allocate test surfaces"); goto done; } @@ -327,7 +327,7 @@ int main(int argc, char **argv) filename = "testyuv.bmp"; } original = SDL_ConvertSurfaceFormat(SDL_LoadBMP(filename), SDL_PIXELFORMAT_RGB24, 0); - if (!original) { + if (original == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", filename, SDL_GetError()); return 3; } @@ -339,7 +339,7 @@ int main(int argc, char **argv) pitch = CalculateYUVPitch(yuv_format, original->w); converted = SDL_CreateRGBSurfaceWithFormat(0, original->w, original->h, 0, rgb_format); - if (!converted) { + if (converted == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create converted surface: %s\n", SDL_GetError()); return 3; } @@ -356,13 +356,13 @@ int main(int argc, char **argv) SDL_WINDOWPOS_UNDEFINED, original->w, original->h, 0); - if (!window) { + if (window == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError()); return 4; } renderer = SDL_CreateRenderer(window, -1, 0); - if (!renderer) { + if (renderer == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create renderer: %s\n", SDL_GetError()); return 4; } diff --git a/libs/SDL2/test/testyuv_cvt.c b/libs/SDL2/test/testyuv_cvt.c index d78e5b196451e986f4b693f40c28cd363c89f85d..3bd2df3ff027da50e999b6f686df07daaf7959c8 100644 --- a/libs/SDL2/test/testyuv_cvt.c +++ b/libs/SDL2/test/testyuv_cvt.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/test/testyuv_cvt.h b/libs/SDL2/test/testyuv_cvt.h index fa736be3c3b2a2ccb403f59cad2ab9294e5904e7..781b632ea7f1de61124d2a42cd5152a31aca8076 100644 --- a/libs/SDL2/test/testyuv_cvt.h +++ b/libs/SDL2/test/testyuv_cvt.h @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/test/torturethread.c b/libs/SDL2/test/torturethread.c index b612cda497766416e0a94ab469988685fb1b908f..1976800f0aeb957add2173a5a9fde7e4dd8fcebe 100644 --- a/libs/SDL2/test/torturethread.c +++ b/libs/SDL2/test/torturethread.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/test/watcom.mif b/libs/SDL2/test/watcom.mif index b81dad831e372d992a2b09f79a63123dcc9a01f6..2189fd49c2760eb453cee0929796d53651ae417e 100644 --- a/libs/SDL2/test/watcom.mif +++ b/libs/SDL2/test/watcom.mif @@ -53,13 +53,12 @@ TASRCS = testautomation.c & testautomation_audio.c testautomation_clipboard.c & testautomation_events.c testautomation_guid.c & testautomation_hints.c testautomation_joystick.c & - testautomation_keyboard.c testautomation_log.c & - testautomation_main.c testautomation_math.c & - testautomation_mouse.c testautomation_pixels.c & - testautomation_platform.c testautomation_rect.c & - testautomation_render.c testautomation_rwops.c & - testautomation_sdltest.c testautomation_stdlib.c & - testautomation_subsystems.c testautomation_surface.c & + testautomation_keyboard.c testautomation_main.c & + testautomation_math.c testautomation_mouse.c & + testautomation_pixels.c testautomation_platform.c & + testautomation_rect.c testautomation_render.c & + testautomation_rwops.c testautomation_sdltest.c & + testautomation_stdlib.c testautomation_surface.c & testautomation_syswm.c testautomation_timer.c & testautomation_video.c @@ -70,6 +69,8 @@ TNOBJS = $(TNSRCS:.c=.obj) all: testutils.lib $(TARGETS) +.c: ../src/test + .obj.exe: wlink SYS $(SYSTEM) libpath $(LIBPATH) lib {$(LIBS)} op q op el file {$<} name $@ @@ -81,9 +82,6 @@ testvulkan.obj: testvulkan.c # new vulkan headers result in lots of W202 warnings wcc386 $(CFLAGS) -wcd=202 -fo=$^@ $< -testautomation_stdlib.obj: testautomation_stdlib.c - wcc386 $(CFLAGS) -wcd=201 -fo=$^@ $< - testautomation.exe: $(TAOBJS) wlink SYS $(SYSTEM) libpath $(LIBPATH) lib {$(LIBS)} op q op el file {$<} name $@ diff --git a/libs/SDL2/x86_64-w64-mingw32/bin/SDL2.dll b/libs/SDL2/x86_64-w64-mingw32/bin/SDL2.dll index 878760628d4855ee65934869a1f47050b6920678..e26bcb1c3be11930053e594bc070df85b68d7b89 100755 Binary files a/libs/SDL2/x86_64-w64-mingw32/bin/SDL2.dll and b/libs/SDL2/x86_64-w64-mingw32/bin/SDL2.dll differ diff --git a/libs/SDL2/x86_64-w64-mingw32/bin/sdl2-config b/libs/SDL2/x86_64-w64-mingw32/bin/sdl2-config index c1368c020946c7c021bb63e3274e2c9e9eef87ad..65b2fd1996fb92edafa69f4922236005d1e9bef3 100755 --- a/libs/SDL2/x86_64-w64-mingw32/bin/sdl2-config +++ b/libs/SDL2/x86_64-w64-mingw32/bin/sdl2-config @@ -43,7 +43,7 @@ while test $# -gt 0; do echo $exec_prefix ;; --version) - echo 2.30.0 + echo 2.28.5 ;; --cflags) echo -I${prefix}/include/SDL2 -Dmain=SDL_main diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL.h index 20c903b2fe4f60836b397cb19af7e07ca19f3071..9ba8f68c6e7966906d5832985a0f4ebc400a8878 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_assert.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_assert.h index a396d4e02ed20041a742e22ffb4efaa68995db03..7ce823ec5433f2d168889d7ac9239cd9f6ac6171 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_assert.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_assert.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_atomic.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_atomic.h index 1fa18f49fe078348ec235adca77cbb6374a62e25..1dd816a3826e307f8b7cb436ce95edd28cee7a5c 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_atomic.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_atomic.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -209,7 +209,7 @@ typedef void (*SDL_KernelMemoryBarrierFunc)(); #if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) || defined(__ARM_ARCH_8A__) #define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory") #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory") -#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) +#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_5TE__) #ifdef __thumb__ /* The mcr instruction isn't available in thumb mode, use real functions */ #define SDL_MEMORY_BARRIER_USES_FUNCTION diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_audio.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_audio.h index bd8e7ab6fa6d8336bf78fe732726782105f65dfe..ccd35982df124d75a8007791bce88da405c76a75 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_audio.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_audio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_bits.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_bits.h index 83e8a78c783c473184dd1674279fbdb4caafab8e..81161ae5f30633f2d708e9b7806ba005bdd9c21a 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_bits.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_bits.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_blendmode.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_blendmode.h index 09d01477d8db63ecf6e9de2483472b9d17641567..4ecbe50785e9d37fcd57325a5301df6d25237997 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_blendmode.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_blendmode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -65,8 +65,8 @@ typedef enum typedef enum { SDL_BLENDOPERATION_ADD = 0x1, /**< dst + src: supported by all renderers */ - SDL_BLENDOPERATION_SUBTRACT = 0x2, /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */ - SDL_BLENDOPERATION_REV_SUBTRACT = 0x3, /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */ + SDL_BLENDOPERATION_SUBTRACT = 0x2, /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */ + SDL_BLENDOPERATION_REV_SUBTRACT = 0x3, /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */ SDL_BLENDOPERATION_MINIMUM = 0x4, /**< min(dst, src) : supported by D3D9, D3D11 */ SDL_BLENDOPERATION_MAXIMUM = 0x5 /**< max(dst, src) : supported by D3D9, D3D11 */ } SDL_BlendOperation; diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_clipboard.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_clipboard.h index bd4b044c6dd4ec0f0ed298f4333d3aed79702001..7c351fbb9c98aacbbf9136b3373b04ad321fe456 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_clipboard.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_clipboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_config.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_config.h index dba78086016e4d11489ccdb27cda9972ec0d862d..01322c1829401fecea1b72889dfe4d313c5f0175 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_config.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_config.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_cpuinfo.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_cpuinfo.h index 2a9dd380c2e7b8d4ba5f6e8aec4c13d5becd565d..ed5e97915e314132f76df1747f76a5633dbd2b44 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_cpuinfo.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_cpuinfo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_egl.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_egl.h index a4276e6810b2fe059720cb2fe81e234e599e663c..6f51c0831afb94f82f03f92fdec39c622b0b3858 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_egl.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_egl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_endian.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_endian.h index 591ccac4256adc9f17c7ba0234ff745e1fb71a31..71bc06729b6425ad9a4a96ca12e430409fb50514 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_endian.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_endian.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_error.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_error.h index 2df6463ad92f2183c0ac3c936bf1277bdef02e22..31c22616ccb0f276d3cab3caef4a769c5381b0ae 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_error.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_error.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_events.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_events.h index eccbba2553b4fce528c41741b15d7419597afcf6..9d097031805f33ff18e0a9bf381e22fb0f662dd0 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_events.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_events.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -131,8 +131,6 @@ typedef enum SDL_CONTROLLERTOUCHPADMOTION, /**< Game controller touchpad finger was moved */ SDL_CONTROLLERTOUCHPADUP, /**< Game controller touchpad finger was lifted */ SDL_CONTROLLERSENSORUPDATE, /**< Game controller sensor was updated */ - SDL_CONTROLLERUPDATECOMPLETE_RESERVED_FOR_SDL3, - SDL_CONTROLLERSTEAMHANDLEUPDATED, /**< Game controller Steam handle has changed */ /* Touch events */ SDL_FINGERDOWN = 0x700, @@ -448,7 +446,7 @@ typedef struct SDL_ControllerButtonEvent */ typedef struct SDL_ControllerDeviceEvent { - Uint32 type; /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, ::SDL_CONTROLLERDEVICEREMAPPED, or ::SDL_CONTROLLERSTEAMHANDLEUPDATED */ + Uint32 type; /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, or ::SDL_CONTROLLERDEVICEREMAPPED */ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Sint32 which; /**< The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event */ } SDL_ControllerDeviceEvent; @@ -582,6 +580,15 @@ typedef struct SDL_QuitEvent Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ } SDL_QuitEvent; +/** + * \brief OS Specific event + */ +typedef struct SDL_OSEvent +{ + Uint32 type; /**< ::SDL_QUIT */ + Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ +} SDL_OSEvent; + /** * \brief A user-defined event type (event.user.*) */ diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_filesystem.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_filesystem.h index 07498898d3238d6b7c824761c46421e46991c84d..4cad657ec86e7b245a4a3046effd2ed783085932 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_filesystem.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_filesystem.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -64,7 +64,7 @@ extern "C" { * directory of the application as it is uncommon to store resources outside * the executable. As such it is not a writable directory. * - * The returned path is guaranteed to end with a path separator ('\\' on + * The returned path is guaranteed to end with a path separator ('\' on * Windows, '/' on most other platforms). * * The pointer returned is owned by the caller. Please call SDL_free() on the @@ -120,7 +120,7 @@ extern DECLSPEC char *SDLCALL SDL_GetBasePath(void); * - ...only use letters, numbers, and spaces. Avoid punctuation like "Game * Name 2: Bad Guy's Revenge!" ... "Game Name 2" is sufficient. * - * The returned path is guaranteed to end with a path separator ('\\' on + * The returned path is guaranteed to end with a path separator ('\' on * Windows, '/' on most other platforms). * * The pointer returned is owned by the caller. Please call SDL_free() on the diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_gamecontroller.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_gamecontroller.h index 281fa356c63f58cfa5701ff6ae80f1d83c0f6aa8..140054d36ee625c57be7cc976087691b8746f7f4 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_gamecontroller.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_gamecontroller.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -73,8 +73,7 @@ typedef enum SDL_CONTROLLER_TYPE_NVIDIA_SHIELD, SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT, SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT, - SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR, - SDL_CONTROLLER_TYPE_MAX + SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR } SDL_GameControllerType; typedef enum @@ -524,20 +523,6 @@ extern DECLSPEC Uint16 SDLCALL SDL_GameControllerGetFirmwareVersion(SDL_GameCont */ extern DECLSPEC const char * SDLCALL SDL_GameControllerGetSerial(SDL_GameController *gamecontroller); -/** - * Get the Steam Input handle of an opened controller, if available. - * - * Returns an InputHandle_t for the controller that can be used with Steam Input API: - * https://partner.steamgames.com/doc/api/ISteamInput - * - * \param gamecontroller the game controller object to query. - * \returns the gamepad handle, or 0 if unavailable. - * - * \since This function is available since SDL 2.30.0. - */ -extern DECLSPEC Uint64 SDLCALL SDL_GameControllerGetSteamHandle(SDL_GameController *gamecontroller); - - /** * Check if a controller has been opened and is currently connected. * @@ -613,9 +598,7 @@ extern DECLSPEC void SDLCALL SDL_GameControllerUpdate(void); * and are centered within ~8000 of zero, though advanced UI will allow users to set * or autodetect the dead zone, which varies between controllers. * - * Trigger axis values range from 0 (released) to SDL_JOYSTICK_AXIS_MAX - * (fully pressed) when reported by SDL_GameControllerGetAxis(). Note that this is not the - * same range that will be reported by the lower-level SDL_GetJoystickAxis(). + * Trigger axis values range from 0 to SDL_JOYSTICK_AXIS_MAX. */ typedef enum { @@ -704,13 +687,8 @@ SDL_GameControllerHasAxis(SDL_GameController *gamecontroller, SDL_GameController * * The axis indices start at index 0. * - * For thumbsticks, the state is a value ranging from -32768 (up/left) - * to 32767 (down/right). - * - * Triggers range from 0 when released to 32767 when fully pressed, and - * never return a negative value. Note that this differs from the value - * reported by the lower-level SDL_GetJoystickAxis(), which normally uses - * the full range. + * The state is a value ranging from -32768 to 32767. Triggers, however, range + * from 0 to 32767 (they never return a negative value). * * \param gamecontroller a game controller * \param axis an axis index (one of the SDL_GameControllerAxis values) diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_gesture.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_gesture.h index 4fffa5f3e87df75d287da5c6ed0e795ab49d7768..db70b4dd843d983dea8988a60b12f92a739faa0a 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_gesture.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_gesture.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_guid.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_guid.h index 7daa5f1f585c3d7482108e915ea0ea8fa263751b..d964223c62ca79b46bdb6aa69ba9ed4e256d1f9b 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_guid.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_guid.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_haptic.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_haptic.h index c9ed847df02387a5f4d5f5fd02055695cd46a5e6..2462a1e47b3731a20f68af4a2d0d9cdfa5c76e59 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_haptic.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_haptic.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_hidapi.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_hidapi.h index b9d8ffac3881e2a297da348e8afb832b0b4afea9..0575100357798a4b34365b5f37d0ef57d1cf831c 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_hidapi.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_hidapi.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_hints.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_hints.h index e775a6509bc0e4834be32411ddadd1cfd0f2a99b..00beef51e29ed9e610182c7db3d88da70a98230f 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_hints.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_hints.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -631,110 +631,6 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS" -/** - * A variable containing a list of arcade stick style controllers. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES "SDL_JOYSTICK_ARCADESTICK_DEVICES" - -/** - * A variable containing a list of devices that are not arcade stick style controllers. This will override SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES and the built in device list. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES_EXCLUDED "SDL_JOYSTICK_ARCADESTICK_DEVICES_EXCLUDED" - -/** - * A variable containing a list of devices that should not be considerd joysticks. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_BLACKLIST_DEVICES "SDL_JOYSTICK_BLACKLIST_DEVICES" - -/** - * A variable containing a list of devices that should be considered joysticks. This will override SDL_HINT_JOYSTICK_BLACKLIST_DEVICES and the built in device list. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_BLACKLIST_DEVICES_EXCLUDED "SDL_JOYSTICK_BLACKLIST_DEVICES_EXCLUDED" - -/** - * A variable containing a list of flightstick style controllers. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES "SDL_JOYSTICK_FLIGHTSTICK_DEVICES" - -/** - * A variable containing a list of devices that are not flightstick style controllers. This will override SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES and the built in device list. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES_EXCLUDED "SDL_JOYSTICK_FLIGHTSTICK_DEVICES_EXCLUDED" - -/** - * A variable containing a list of devices known to have a GameCube form factor. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_GAMECUBE_DEVICES "SDL_JOYSTICK_GAMECUBE_DEVICES" - -/** - * A variable containing a list of devices known not to have a GameCube form factor. This will override SDL_HINT_JOYSTICK_GAMECUBE_DEVICES and the built in device list. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_GAMECUBE_DEVICES_EXCLUDED "SDL_JOYSTICK_GAMECUBE_DEVICES_EXCLUDED" - /** * \brief A variable controlling whether the HIDAPI joystick drivers should be used. * @@ -943,17 +839,6 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_HIDAPI_STEAM "SDL_JOYSTICK_HIDAPI_STEAM" -/** - * \brief A variable controlling whether the HIDAPI driver for the Steam Deck builtin controller should be used. - * - * This variable can be set to the following values: - * "0" - HIDAPI driver is not used - * "1" - HIDAPI driver is used - * - * The default is the value of SDL_HINT_JOYSTICK_HIDAPI - */ -#define SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK "SDL_JOYSTICK_HIDAPI_STEAMDECK" - /** * \brief A variable controlling whether the HIDAPI driver for Nintendo Switch controllers should be used. * @@ -1080,24 +965,6 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED "SDL_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED" -/** - * A variable controlling whether IOKit should be used for controller handling. - * - * This variable can be set to the following values: - * "0" - IOKit is not used - * "1" - IOKit is used (the default) - */ -#define SDL_HINT_JOYSTICK_IOKIT "SDL_JOYSTICK_IOKIT" - -/** - * A variable controlling whether GCController should be used for controller handling. - * - * This variable can be set to the following values: - * "0" - GCController is not used - * "1" - GCController is used (the default) - */ -#define SDL_HINT_JOYSTICK_MFI "SDL_JOYSTICK_MFI" - /** * \brief A variable controlling whether the RAWINPUT joystick drivers should be used for better handling XInput-capable devices. * @@ -1140,32 +1007,6 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_THREAD "SDL_JOYSTICK_THREAD" -/** - * A variable containing a list of throttle style controllers. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_THROTTLE_DEVICES "SDL_JOYSTICK_THROTTLE_DEVICES" - -/** - * A variable containing a list of devices that are not throttle style controllers. This will override SDL_HINT_JOYSTICK_THROTTLE_DEVICES and the built in device list. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_THROTTLE_DEVICES_EXCLUDED "SDL_JOYSTICK_THROTTLE_DEVICES_EXCLUDED" - /** * \brief A variable controlling whether Windows.Gaming.Input should be used for controller handling. * @@ -1175,45 +1016,6 @@ extern "C" { */ #define SDL_HINT_JOYSTICK_WGI "SDL_JOYSTICK_WGI" -/** - * A variable containing a list of wheel style controllers. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_WHEEL_DEVICES "SDL_JOYSTICK_WHEEL_DEVICES" - -/** - * A variable containing a list of devices that are not wheel style controllers. This will override SDL_HINT_JOYSTICK_WHEEL_DEVICES and the built in device list. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_WHEEL_DEVICES_EXCLUDED "SDL_JOYSTICK_WHEEL_DEVICES_EXCLUDED" - -/** - * A variable containing a list of devices known to have all axes centered at zero. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_JOYSTICK_ZERO_CENTERED_DEVICES "SDL_JOYSTICK_ZERO_CENTERED_DEVICES" - /** * \brief Determines whether SDL enforces that DRM master is required in order * to initialize the KMSDRM video backend. @@ -1282,22 +1084,6 @@ extern "C" { */ #define SDL_HINT_LINUX_JOYSTICK_DEADZONES "SDL_LINUX_JOYSTICK_DEADZONES" -/** - * \brief A variable controlling the default SDL log levels. - * - * This variable is a comma separated set of category=level tokens that define the default logging levels for SDL applications. - * - * The category can be a numeric category, one of "app", "error", "assert", "system", "audio", "video", "render", "input", "test", or `*` for any unspecified category. - * - * The level can be a numeric level, one of "verbose", "debug", "info", "warn", "error", "critical", or "quiet" to disable that category. - * - * You can omit the category if you want to set the logging level for all categories. - * - * If this hint isn't set, the default log levels are equivalent to: - * "app=info,assert=warn,test=verbose,*=error" - */ -#define SDL_HINT_LOGGING "SDL_LOGGING" - /** * \brief When set don't force the SDL app to become a foreground process * @@ -1699,32 +1485,6 @@ extern "C" { */ #define SDL_HINT_RENDER_METAL_PREFER_LOW_POWER_DEVICE "SDL_RENDER_METAL_PREFER_LOW_POWER_DEVICE" -/** - * A variable containing a list of ROG gamepad capable mice. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_ROG_GAMEPAD_MICE "SDL_ROG_GAMEPAD_MICE" - -/** - * A variable containing a list of devices that are not ROG gamepad capable mice. This will override SDL_HINT_ROG_GAMEPAD_MICE and the built in device list. - * - * The format of the string is a comma separated list of USB VID/PID pairs - * in hexadecimal form, e.g. - * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD - * - * The variable can also take the form of @file, in which case the named - * file will be loaded and interpreted as the value of the variable. - */ -#define SDL_HINT_ROG_GAMEPAD_MICE_EXCLUDED "SDL_ROG_GAMEPAD_MICE_EXCLUDED" - /** * \brief A variable controlling if VSYNC is automatically disable if doesn't reach the enough FPS * @@ -2682,22 +2442,6 @@ extern "C" { */ #define SDL_HINT_TRACKPAD_IS_TOUCH_ONLY "SDL_TRACKPAD_IS_TOUCH_ONLY" -/** - * Cause SDL to call dbus_shutdown() on quit. - * - * This is useful as a debug tool to validate memory leaks, but shouldn't ever - * be set in production applications, as other libraries used by the application - * might use dbus under the hood and this cause cause crashes if they continue - * after SDL_Quit(). - * - * This variable can be set to the following values: - * "0" - SDL will not call dbus_shutdown() on quit (default) - * "1" - SDL will call dbus_shutdown() on quit - * - * This hint is available since SDL 2.30.0. - */ -#define SDL_HINT_SHUTDOWN_DBUS_ON_QUIT "SDL_SHUTDOWN_DBUS_ON_QUIT" - /** * \brief An enumeration of hint priorities diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_joystick.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_joystick.h index 561e01099cede911e349969024f9b84bad658c2d..b9b4f622800d7a59285523c1407578ee130c0e32 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_joystick.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_joystick.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_keyboard.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_keyboard.h index 03c7b5a3705af4eb25d296049af1fe23ffd0b7d3..86a37ad1a241688e3ee3e658a824e5a78cba2918 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_keyboard.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_keyboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -298,10 +298,8 @@ extern DECLSPEC void SDLCALL SDL_ClearComposition(void); extern DECLSPEC SDL_bool SDLCALL SDL_IsTextInputShown(void); /** - * Set the rectangle used to type Unicode text inputs. Native input methods - * will place a window with word suggestions near it, without covering the - * text being inputted. - * + * Set the rectangle used to type Unicode text inputs. + * * To start text input in a given location, this function is intended to be * called before SDL_StartTextInput, although some platforms support moving * the rectangle even while text input (and a composition) is active. diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_keycode.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_keycode.h index 57a71bd79694d749d3702af58f3813540fb678d8..7106223027e75886652f3a2efd179d82561e350c 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_keycode.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_keycode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_loadso.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_loadso.h index 4edc22e9e756c9f69fde1aced4679b63dc228e37..ca59b681cb45d9684223aaa6ab7287e809ced5f2 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_loadso.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_loadso.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_locale.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_locale.h index 0b6118f0ef8669930b2ce0aa5d4e9628381ae2df..482dbefe765fce9fe2e4248cc5e57e56e71b39b1 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_locale.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_locale.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_log.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_log.h index bd030c6d2d5f27ece4b3a74bd80d8f9b5708d05b..da733c4023d9c9f8ed62668e22ddb00c9f5c1fd4 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_log.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_log.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -59,7 +59,7 @@ extern "C" { * By default the application category is enabled at the INFO level, * the assert category is enabled at the WARN level, test is enabled * at the VERBOSE level and all other categories are enabled at the - * ERROR level. + * CRITICAL level. */ typedef enum { @@ -352,7 +352,7 @@ extern DECLSPEC void SDLCALL SDL_LogMessage(int category, */ extern DECLSPEC void SDLCALL SDL_LogMessageV(int category, SDL_LogPriority priority, - SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(3); + const char *fmt, va_list ap); /** * The prototype for the log output callback function. diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_main.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_main.h index a66c84b4e5fbc2b45a5deca02e42b08e00ef1c66..5cc8e5913a4e705548739f0718d4878392c8a90e 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_main.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_main.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_messagebox.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_messagebox.h index 5ace6f2ddee1f8172416650c6fbdcd77e0a11ba9..7896fd1291f9211584447abcb4ab3edf320bc389 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_messagebox.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_messagebox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_metal.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_metal.h index 50f7b2aeb45211ce457bf9c6dc268eb86caa6be6..f36e34878cef20b686f7800fe112a5bd99f6a3b3 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_metal.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_metal.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_misc.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_misc.h index 113ba7a15693dea7e8fd65d4000fd0fb5ca75c18..13ed9c771835f15abdd16c53b5cf39d999159c65 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_misc.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_misc.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_mouse.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_mouse.h index 687ff122d2c4fc2ba8616dc9fe30fb9764690100..aa07575738a5640c65e5f5dbc4a55661fe0a093e 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_mouse.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_mouse.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_mutex.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_mutex.h index eaa21f293f51721c44eb07d1623fb291f3fb7ada..e679d380890ea02d7a05021152aa183646fa178c 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_mutex.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_mutex.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_name.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_name.h index 71e9354550f913f1b76dccb0386a19d51dcd164a..5c3e07ab7d3e4a04fa436767527aa3e570a25d25 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_name.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_name.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengl.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengl.h index 2bb38c5c0e994443e99ce7b2ac3888d4beed435a..0ba89127ace681fa97744e94bad4728c59be9b53 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengl.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengles.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengles.h index 7e9a1ab8d4d037d06954b6ddd0df8684fb1a3db4..f4465eaa9da8ba3009fa4f3ee51eeecd0689283b 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengles.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengles.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengles2.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengles2.h index 96971344d1b863777ef6a567d321167ebeff4765..5e3b717def6cafa080adb200245e9528f0bf7cbc 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengles2.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengles2.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_pixels.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_pixels.h index 44757cdcf4b7fdae9c499d8c773c2c5fe28e60d7..9abd57b42014a89b2761608bea2ae802ef9e8515 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_pixels.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_pixels.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -61,10 +61,7 @@ typedef enum SDL_PIXELTYPE_ARRAYU16, SDL_PIXELTYPE_ARRAYU32, SDL_PIXELTYPE_ARRAYF16, - SDL_PIXELTYPE_ARRAYF32, - - /* This must be at the end of the list to avoid breaking the existing ABI */ - SDL_PIXELTYPE_INDEX2 + SDL_PIXELTYPE_ARRAYF32 } SDL_PixelType; /** Bitmap pixel order, high bit -> low bit. */ @@ -137,7 +134,6 @@ typedef enum #define SDL_ISPIXELFORMAT_INDEXED(format) \ (!SDL_ISPIXELFORMAT_FOURCC(format) && \ ((SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX1) || \ - (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX2) || \ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX4) || \ (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX8))) @@ -181,12 +177,6 @@ typedef enum SDL_PIXELFORMAT_INDEX1MSB = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX1, SDL_BITMAPORDER_1234, 0, 1, 0), - SDL_PIXELFORMAT_INDEX2LSB = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX2, SDL_BITMAPORDER_4321, 0, - 2, 0), - SDL_PIXELFORMAT_INDEX2MSB = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX2, SDL_BITMAPORDER_1234, 0, - 2, 0), SDL_PIXELFORMAT_INDEX4LSB = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX4, SDL_BITMAPORDER_4321, 0, 4, 0), @@ -286,19 +276,11 @@ typedef enum SDL_PIXELFORMAT_ARGB32 = SDL_PIXELFORMAT_ARGB8888, SDL_PIXELFORMAT_BGRA32 = SDL_PIXELFORMAT_BGRA8888, SDL_PIXELFORMAT_ABGR32 = SDL_PIXELFORMAT_ABGR8888, - SDL_PIXELFORMAT_RGBX32 = SDL_PIXELFORMAT_RGBX8888, - SDL_PIXELFORMAT_XRGB32 = SDL_PIXELFORMAT_XRGB8888, - SDL_PIXELFORMAT_BGRX32 = SDL_PIXELFORMAT_BGRX8888, - SDL_PIXELFORMAT_XBGR32 = SDL_PIXELFORMAT_XBGR8888, #else SDL_PIXELFORMAT_RGBA32 = SDL_PIXELFORMAT_ABGR8888, SDL_PIXELFORMAT_ARGB32 = SDL_PIXELFORMAT_BGRA8888, SDL_PIXELFORMAT_BGRA32 = SDL_PIXELFORMAT_ARGB8888, SDL_PIXELFORMAT_ABGR32 = SDL_PIXELFORMAT_RGBA8888, - SDL_PIXELFORMAT_RGBX32 = SDL_PIXELFORMAT_XBGR8888, - SDL_PIXELFORMAT_XRGB32 = SDL_PIXELFORMAT_BGRX8888, - SDL_PIXELFORMAT_BGRX32 = SDL_PIXELFORMAT_XRGB8888, - SDL_PIXELFORMAT_XBGR32 = SDL_PIXELFORMAT_RGBX8888, #endif SDL_PIXELFORMAT_YV12 = /**< Planar mode: Y + V + U (3 planes) */ diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_platform.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_platform.h index 6e67b4577a3d040835a83fdc5e6332a33cc0bab5..d2a7e052d7b19051d020bb240856fbe6080e1af8 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_platform.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_platform.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -166,12 +166,6 @@ #define WINAPI_FAMILY_WINRT 0 #endif /* HAVE_WINAPIFAMILY_H */ -#if (HAVE_WINAPIFAMILY_H) && defined(WINAPI_FAMILY_PHONE_APP) -#define SDL_WINAPI_FAMILY_PHONE (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) -#else -#define SDL_WINAPI_FAMILY_PHONE 0 -#endif - #if WINAPI_FAMILY_WINRT #undef __WINRT__ #define __WINRT__ 1 diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_power.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_power.h index 0520065cebbb135035665cf95402a2b15b381d1a..1d75704c421c42b244f68b93edda5694f73d5c31 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_power.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_power.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_quit.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_quit.h index 3f69dc9f26011db121417874daa9ccbb1043f708..d8ceb894369194b5a0da17b8b4117ebf2edf0a88 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_quit.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_quit.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_rect.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_rect.h index 5ce1f0b4517fa856ad7ee07e8c14fdf2f33f7c7a..9611a311ce83bc165a1ea968a51d4f968f9557d3 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_rect.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_rect.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_render.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_render.h index b7135bb9dd46e73b4de07762cda78cc6b292bf3e..2d3f07366209ba01531b878102b28599b256725f 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_render.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_render.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -42,7 +42,7 @@ * of the many good 3D engines. * * These functions must be called from the main thread. - * See this bug for details: https://github.com/libsdl-org/SDL/issues/986 + * See this bug for details: http://bugzilla.libsdl.org/show_bug.cgi?id=1995 */ #ifndef SDL_render_h_ diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_revision.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_revision.h index ee42f8421d75d3d1e8a00051725414503c7ff132..4455a08b6289e407412cfb0c59b8d8022ea49d98 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_revision.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_revision.h @@ -1,7 +1,7 @@ /* Generated by updaterev.sh, do not edit */ #ifdef SDL_VENDOR_INFO -#define SDL_REVISION "SDL-release-2.30.0-0-g859844eae (" SDL_VENDOR_INFO ")" +#define SDL_REVISION "SDL-release-2.28.5-0-g15ead9a40 (" SDL_VENDOR_INFO ")" #else -#define SDL_REVISION "SDL-release-2.30.0-0-g859844eae" +#define SDL_REVISION "SDL-release-2.28.5-0-g15ead9a40" #endif #define SDL_REVISION_NUMBER 0 diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_rwops.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_rwops.h index 9dd99f92b1541ba73386aeed906b16d4db415d17..8615cb542959def634d4a634cd24f24d3a5104a6 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_rwops.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_rwops.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_scancode.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_scancode.h index fe13d5b7aaad9378e49005640b0c7641cf0512dc..a960a7991c61accff7874c9c75d92099b350b858 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_scancode.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_scancode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_sensor.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_sensor.h index 8b89ef6a526d45f11d7b3ac64234519df2164b22..9ecce44b17be8469a1572afe95b2ff8a323045bf 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_sensor.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_sensor.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_shape.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_shape.h index 4783cf290e95eec1a2e5b3f3a2ee5b7f94dcbf33..f66babc011339d5729fee081235f8f57815275c2 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_shape.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_shape.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_stdinc.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_stdinc.h index 0035a357cf8e70d0e201413e726b149db96acfd3..182ed86ee371194ec6f45229626fa395472d0f8d 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_stdinc.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_stdinc.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -257,7 +257,7 @@ typedef uint64_t Uint64; #define SDL_PRIs64 PRIs64 #elif defined(__WIN32__) || defined(__GDK__) #define SDL_PRIs64 "I64d" -#elif defined(__LP64__) && !defined(__APPLE__) +#elif defined(__LINUX__) && defined(__LP64__) #define SDL_PRIs64 "ld" #else #define SDL_PRIs64 "lld" @@ -268,7 +268,7 @@ typedef uint64_t Uint64; #define SDL_PRIu64 PRIu64 #elif defined(__WIN32__) || defined(__GDK__) #define SDL_PRIu64 "I64u" -#elif defined(__LP64__) && !defined(__APPLE__) +#elif defined(__LINUX__) && defined(__LP64__) #define SDL_PRIu64 "lu" #else #define SDL_PRIu64 "llu" @@ -279,7 +279,7 @@ typedef uint64_t Uint64; #define SDL_PRIx64 PRIx64 #elif defined(__WIN32__) || defined(__GDK__) #define SDL_PRIx64 "I64x" -#elif defined(__LP64__) && !defined(__APPLE__) +#elif defined(__LINUX__) && defined(__LP64__) #define SDL_PRIx64 "lx" #else #define SDL_PRIx64 "llx" @@ -290,7 +290,7 @@ typedef uint64_t Uint64; #define SDL_PRIX64 PRIX64 #elif defined(__WIN32__) || defined(__GDK__) #define SDL_PRIX64 "I64X" -#elif defined(__LP64__) && !defined(__APPLE__) +#elif defined(__LINUX__) && defined(__LP64__) #define SDL_PRIX64 "lX" #else #define SDL_PRIX64 "llX" @@ -336,9 +336,7 @@ typedef uint64_t Uint64; #define SDL_PRINTF_FORMAT_STRING #define SDL_SCANF_FORMAT_STRING #define SDL_PRINTF_VARARG_FUNC( fmtargnumber ) -#define SDL_PRINTF_VARARG_FUNCV( fmtargnumber ) #define SDL_SCANF_VARARG_FUNC( fmtargnumber ) -#define SDL_SCANF_VARARG_FUNCV( fmtargnumber ) #else #if defined(_MSC_VER) && (_MSC_VER >= 1600) /* VS 2010 and above */ #include <sal.h> @@ -364,14 +362,10 @@ typedef uint64_t Uint64; #endif #if defined(__GNUC__) #define SDL_PRINTF_VARARG_FUNC( fmtargnumber ) __attribute__ (( format( __printf__, fmtargnumber, fmtargnumber+1 ))) -#define SDL_PRINTF_VARARG_FUNCV( fmtargnumber ) __attribute__(( format( __printf__, fmtargnumber, 0 ))) #define SDL_SCANF_VARARG_FUNC( fmtargnumber ) __attribute__ (( format( __scanf__, fmtargnumber, fmtargnumber+1 ))) -#define SDL_SCANF_VARARG_FUNCV( fmtargnumber ) __attribute__(( format( __scanf__, fmtargnumber, 0 ))) #else #define SDL_PRINTF_VARARG_FUNC( fmtargnumber ) -#define SDL_PRINTF_VARARG_FUNCV( fmtargnumber ) #define SDL_SCANF_VARARG_FUNC( fmtargnumber ) -#define SDL_SCANF_VARARG_FUNCV( fmtargnumber ) #endif #endif /* SDL_DISABLE_ANALYZE_MACROS */ @@ -609,11 +603,11 @@ extern DECLSPEC int SDLCALL SDL_strcasecmp(const char *str1, const char *str2); extern DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *str2, size_t len); extern DECLSPEC int SDLCALL SDL_sscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, ...) SDL_SCANF_VARARG_FUNC(2); -extern DECLSPEC int SDLCALL SDL_vsscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, va_list ap) SDL_SCANF_VARARG_FUNCV(2); +extern DECLSPEC int SDLCALL SDL_vsscanf(const char *text, const char *fmt, va_list ap); extern DECLSPEC int SDLCALL SDL_snprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, ... ) SDL_PRINTF_VARARG_FUNC(3); -extern DECLSPEC int SDLCALL SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(3); +extern DECLSPEC int SDLCALL SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, const char *fmt, va_list ap); extern DECLSPEC int SDLCALL SDL_asprintf(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); -extern DECLSPEC int SDLCALL SDL_vasprintf(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(2); +extern DECLSPEC int SDLCALL SDL_vasprintf(char **strp, const char *fmt, va_list ap); #ifndef HAVE_M_PI #ifndef M_PI @@ -694,8 +688,8 @@ extern DECLSPEC size_t SDLCALL SDL_iconv(SDL_iconv_t cd, const char **inbuf, size_t * outbytesleft); /** - * This function converts a buffer or string between encodings in one pass, - * returning a string that must be freed with SDL_free() or NULL on error. + * This function converts a buffer or string between encodings in one pass, returning a + * string that must be freed with SDL_free() or NULL on error. * * \since This function is available since SDL 2.0.0. */ @@ -704,8 +698,8 @@ extern DECLSPEC char *SDLCALL SDL_iconv_string(const char *tocode, const char *inbuf, size_t inbytesleft); #define SDL_iconv_utf8_locale(S) SDL_iconv_string("", "UTF-8", S, SDL_strlen(S)+1) -#define SDL_iconv_utf8_ucs2(S) (Uint16 *)SDL_iconv_string("UCS-2", "UTF-8", S, SDL_strlen(S)+1) -#define SDL_iconv_utf8_ucs4(S) (Uint32 *)SDL_iconv_string("UCS-4", "UTF-8", S, SDL_strlen(S)+1) +#define SDL_iconv_utf8_ucs2(S) (Uint16 *)SDL_iconv_string("UCS-2-INTERNAL", "UTF-8", S, SDL_strlen(S)+1) +#define SDL_iconv_utf8_ucs4(S) (Uint32 *)SDL_iconv_string("UCS-4-INTERNAL", "UTF-8", S, SDL_strlen(S)+1) #define SDL_iconv_wchar_utf8(S) SDL_iconv_string("UTF-8", "WCHAR_T", (char *)S, (SDL_wcslen(S)+1)*sizeof(wchar_t)) /* force builds using Clang's static analysis tools to use literal C runtime diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_surface.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_surface.h index ceeb86bd867e8a657626b20ed45f89cd5637f798..d6ee615c59f0a48bc284fde0b75b0dbb3ee9bee2 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_surface.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_surface.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_system.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_system.h index ddae4f8cc1f9ca980837f403101aca74fd7ddd5d..4b7eaddcc0ed9b2033de7ccf7cc00de8a5f58a9d 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_system.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_system.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -593,8 +593,7 @@ extern DECLSPEC void SDLCALL SDL_OnApplicationDidChangeStatusBarOrientation(void /* Functions used only by GDK */ #if defined(__GDK__) -typedef struct XTaskQueueObject *XTaskQueueHandle; -typedef struct XUser *XUserHandle; +typedef struct XTaskQueueObject * XTaskQueueHandle; /** * Gets a reference to the global async task queue handle for GDK, @@ -611,20 +610,6 @@ typedef struct XUser *XUserHandle; */ extern DECLSPEC int SDLCALL SDL_GDKGetTaskQueue(XTaskQueueHandle * outTaskQueue); -/** - * Gets a reference to the default user handle for GDK. - * - * This is effectively a synchronous version of XUserAddAsync, which always - * prefers the default user and allows a sign-in UI. - * - * \param outUserHandle a pointer to be filled in with the default user - * handle. - * \returns 0 if success, -1 if any error occurs. - * - * \since This function is available since SDL 2.28.0. - */ -extern DECLSPEC int SDLCALL SDL_GDKGetDefaultUser(XUserHandle * outUserHandle); - #endif /* Ends C function definitions when using C++ */ diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_syswm.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_syswm.h index 7b8bd6ef996571bbba2e5f1e139a0c9292c88146..b35734deb334508c6fbfcc0b635417a9d2841052 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_syswm.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_syswm.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test.h index e5acbee4e31782003083624c56f9d40eac5743bc..80daaafbd9b5dc1e4dfa8f48f5fa97e19caab062 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_assert.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_assert.h index 4f983350a3944145e8c42be3453d894bba8a1270..341e490facee39061766d2fa4b85c154870611dd 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_assert.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_assert.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_common.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_common.h index d977e463f117149f7d27cf3ec35fe65a735557a2..6de63cad6f8b08a5f4f28b9b2e5de0dc65da6b71 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_common.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_common.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_compare.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_compare.h index 61a38d09051145431d107793aadffba516e08d92..5fce25ca1856cef2790a13d1895dbdd95cb8a4ad 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_compare.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_compare.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_crc32.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_crc32.h index e3478318dc069a6087e6dffd23b424764bf96f04..bf34782103a218ef811e65a356ab6f900201aa54 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_crc32.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_crc32.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_font.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_font.h index 620c82116b3f3418cde5195a27e7e2247f19c88e..18a82ffc80f16a989cf37da79ed06a3e5279ff37 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_font.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_font.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_fuzzer.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_fuzzer.h index a847ccb01ca25d80ffa7b4e36f9a2a8f12f7fa6f..cfe6a14f2a0288bd57cd00d642b4dd9c609a8c21 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_fuzzer.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_fuzzer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_harness.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_harness.h index bd9e4f8de070ae4ac730e1414b8f4ca951252008..26231dcd6bce9e72d54ddbef532a278762634948 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_harness.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_harness.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_images.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_images.h index b5bcb0a0000c49ff42d35284df2c859c9a577ca9..1211371755fdfd7bed0953fe1322fdcb639637a3 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_images.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_images.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_log.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_log.h index ea9ae5e1ca1d9b5170d336b5f770f9c530fdb893..a27ffc209a95ca3dd105b08dbe8ca4509245fe4c 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_log.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_log.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_md5.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_md5.h index 3764b042569eb63323ef6a589a5f3252147d4476..538c7ae3e09caa78990f738337bfbf2db9a86459 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_md5.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_md5.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_memory.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_memory.h index 9bd143252cefbdff77396b68ea54132b1859f16f..f959177d2336b5cf649d4d12a41cf76bf7a52578 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_memory.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_memory.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_random.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_random.h index 344646aa8b24a589b63482528441afbd296f88f8..0035a8030ad2cc4751a87d5aea3c032cd3c4944f 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_random.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_random.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_thread.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_thread.h index dc7f5363aadce39089dd1399963e541d416028b8..b829bbad5dc08bc47f02c64efc24ac97556ac603 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_thread.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_thread.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_timer.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_timer.h index 8123e432f1e5065b67bf51277110fbd7caf886fd..98f9ad16c647e8ecca4829b0629ae15e767f895e 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_timer.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_timer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_touch.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_touch.h index f6a5db413df92d8b253614ef723f546b581354b9..c12d4a1c8174997225ba25fe087bfb794e094f48 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_touch.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_touch.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_types.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_types.h index e8d33c651371bd2fd29b155f135461f66f6681bb..b5d7192ff2e95a994229a90e668ab003e16e5cab 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_types.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_types.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_version.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_version.h index 02143ff7a114e9cbe2a6113aa9d7726e2532808d..7585eece563127330f3e236174f55615d9f03ddf 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_version.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_version.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -58,8 +58,8 @@ typedef struct SDL_version /* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL */ #define SDL_MAJOR_VERSION 2 -#define SDL_MINOR_VERSION 30 -#define SDL_PATCHLEVEL 0 +#define SDL_MINOR_VERSION 28 +#define SDL_PATCHLEVEL 5 /** * Macro to determine SDL version program was compiled against. diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_video.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_video.h index fa47d30991df03867c400da2fe80bb32d93457a8..c8b2d7a0d871e1f84cf4bf52f3583f8f5aaaf727 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_video.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_video.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -1278,8 +1278,7 @@ extern DECLSPEC int SDLCALL SDL_SetWindowFullscreen(SDL_Window * window, /** * Return whether the window has a surface associated with it. * - * \returns SDL_TRUE if there is a surface associated with the window, or - * SDL_FALSE otherwise. + * \returns SDL_TRUE if there is a surface associated with the window, or SDL_FALSE otherwise. * * \since This function is available since SDL 2.28.0. * @@ -1341,11 +1340,6 @@ extern DECLSPEC int SDLCALL SDL_UpdateWindowSurface(SDL_Window * window); * * This function is equivalent to the SDL 1.2 API SDL_UpdateRects(). * - * Note that this function will update _at least_ the rectangles specified, - * but this is only intended as an optimization; in practice, this might - * update more of the screen (or all of the screen!), depending on what - * method SDL uses to send pixels to the system. - * * \param window the window to update * \param rects an array of SDL_Rect structures representing areas of the * surface to copy, in pixels diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/begin_code.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/begin_code.h index a47a7d2b6413cbb4f5dcd7534123477697ef71a3..4142ffeba928866354f51bedf3d1b1a9b8a4c3d9 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/begin_code.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/begin_code.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -36,8 +36,6 @@ #ifndef SDL_DEPRECATED # if defined(__GNUC__) && (__GNUC__ >= 4) /* technically, this arrived in gcc 3.1, but oh well. */ # define SDL_DEPRECATED __attribute__((deprecated)) -# elif defined(_MSC_VER) -# define SDL_DEPRECATED __declspec(deprecated) # else # define SDL_DEPRECATED # endif diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/close_code.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/close_code.h index 50a0e6f3b4462c5197bd15d7d22e6a8f36204b46..b5ff3e2049b666eeeb923d234b7179722fd8d6c3 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/close_code.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/close_code.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/libs/SDL2/x86_64-w64-mingw32/lib/cmake/SDL2/sdl2-config-version.cmake b/libs/SDL2/x86_64-w64-mingw32/lib/cmake/SDL2/sdl2-config-version.cmake index 82dfeab129e3a872175ac18a1cbc351c980616de..0e63829954166a1b637f058307f6202b00ceabfd 100644 --- a/libs/SDL2/x86_64-w64-mingw32/lib/cmake/SDL2/sdl2-config-version.cmake +++ b/libs/SDL2/x86_64-w64-mingw32/lib/cmake/SDL2/sdl2-config-version.cmake @@ -1,6 +1,6 @@ # sdl2 cmake project-config-version input for ./configure scripts -set(PACKAGE_VERSION "2.30.0") +set(PACKAGE_VERSION "2.28.5") if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) set(PACKAGE_VERSION_COMPATIBLE FALSE) diff --git a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.a b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.a index fff83b8b3db5a7be3ce74c842f901582e8a29598..0fe5391a1457715205263c169f6199cfd7a26ec2 100644 Binary files a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.a and b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.a differ diff --git a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.dll.a b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.dll.a index 1f54d8f34958501767792bc277a6c2f7f3a828b0..25300e1d3568ca89696333347fd0c1eb601b3302 100755 Binary files a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.dll.a and b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.dll.a differ diff --git a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.la b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.la index df09985eecb4c61047fea2011b410ad516ffd9dc..3c735a348a8379c56e2f8b53b4905b29266dda31 100644 --- a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.la +++ b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.la @@ -23,9 +23,9 @@ dependency_libs=' -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 - weak_library_names='' # Version information for libSDL2. -current=3000 -age=3000 -revision=0 +current=2800 +age=2800 +revision=5 # Is this an already installed library? installed=yes @@ -38,4 +38,4 @@ dlopen='' dlpreopen='' # Directory that this library needs to be installed in: -libdir='/Users/valve/release/SDL2/SDL2-2.30.0/x86_64-w64-mingw32/lib' +libdir='/Users/valve/release/SDL2/SDL2-2.28.5/x86_64-w64-mingw32/lib' diff --git a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2_test.a b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2_test.a index 3b5999fa2aae9fe8d71d98fcf51eae363805304e..9bb1d7d3c074500270d16864353095287a72ee4c 100644 Binary files a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2_test.a and b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2_test.a differ diff --git a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2_test.la b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2_test.la index d9f34a788284fda81547bb405c2803b203d59518..0a5cd1126d4ee14755bb6f5ec9ed24d5a0b2d564 100644 --- a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2_test.la +++ b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2_test.la @@ -38,4 +38,4 @@ dlopen='' dlpreopen='' # Directory that this library needs to be installed in: -libdir='/Users/valve/release/SDL2/SDL2-2.30.0/x86_64-w64-mingw32/lib' +libdir='/Users/valve/release/SDL2/SDL2-2.28.5/x86_64-w64-mingw32/lib' diff --git a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2main.a b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2main.a index ded236c5b08c906f09b8fb2f33ce36f8b8c2c887..0845ae4c7decda341463762ac5c1538ff81bf6ec 100644 Binary files a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2main.a and b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2main.a differ diff --git a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2main.la b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2main.la index 3adf979fed9fad1451a5bc86340a4584e9a048b9..13216dfb375f77d09919ccb939b710e6c5b21dcb 100644 --- a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2main.la +++ b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2main.la @@ -38,4 +38,4 @@ dlopen='' dlpreopen='' # Directory that this library needs to be installed in: -libdir='/Users/valve/release/SDL2/SDL2-2.30.0/x86_64-w64-mingw32/lib' +libdir='/Users/valve/release/SDL2/SDL2-2.28.5/x86_64-w64-mingw32/lib' diff --git a/libs/SDL2/x86_64-w64-mingw32/lib/pkgconfig/sdl2.pc b/libs/SDL2/x86_64-w64-mingw32/lib/pkgconfig/sdl2.pc index a23ea3051df62f15caaf2a636329ad8625620928..56b88c4ef1dc3b7eae2a7cc3f5cd4232bc793c52 100644 --- a/libs/SDL2/x86_64-w64-mingw32/lib/pkgconfig/sdl2.pc +++ b/libs/SDL2/x86_64-w64-mingw32/lib/pkgconfig/sdl2.pc @@ -1,13 +1,13 @@ # sdl pkg-config source file -prefix=/usr/local/x86_64-w64-mingw32 +prefix=/x86_64-w64-mingw32 exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${prefix}/include Name: sdl2 Description: Simple DirectMedia Layer is a cross-platform multimedia library designed to provide low level access to audio, keyboard, mouse, joystick, 3D hardware via OpenGL, and 2D video framebuffer. -Version: 2.30.0 +Version: 2.28.5 Requires.private: Conflicts: Libs: -L${libdir} -lmingw32 -lSDL2main -lSDL2 -mwindows diff --git a/libs/SDL2/x86_64-w64-mingw32/share/aclocal/sdl2.m4 b/libs/SDL2/x86_64-w64-mingw32/share/aclocal/sdl2.m4 index 274753b118aaf3184843800cc2297b9de568891b..75b60f6ea9338d050b32fd19b5214ef9c1024afa 100644 --- a/libs/SDL2/x86_64-w64-mingw32/share/aclocal/sdl2.m4 +++ b/libs/SDL2/x86_64-w64-mingw32/share/aclocal/sdl2.m4 @@ -9,9 +9,8 @@ # * also look for SDL2.framework under Mac OS X # * removed HP/UX 9 support. # * updated for newer autoconf. -# * (v3) use $PKG_CONFIG for pkg-config cross-compiling support -# serial 3 +# serial 2 dnl AM_PATH_SDL2([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS @@ -55,7 +54,7 @@ AC_ARG_VAR(SDL2_FRAMEWORK, [Path to SDL2.framework]) if test "x$sdl_pc" = xyes ; then no_sdl="" - SDL2_CONFIG="$PKG_CONFIG sdl2" + SDL2_CONFIG="pkg-config sdl2" else as_save_PATH="$PATH" if test "x$prefix" != xNONE && test "$cross_compiling" != yes; then diff --git a/libs/miniupnpc/include/igd_desc_parse.h b/libs/miniupnpc/include/miniupnpc/igd_desc_parse.h similarity index 100% rename from libs/miniupnpc/include/igd_desc_parse.h rename to libs/miniupnpc/include/miniupnpc/igd_desc_parse.h diff --git a/libs/miniupnpc/include/miniupnpc.h b/libs/miniupnpc/include/miniupnpc/miniupnpc.h similarity index 100% rename from libs/miniupnpc/include/miniupnpc.h rename to libs/miniupnpc/include/miniupnpc/miniupnpc.h diff --git a/libs/miniupnpc/include/miniupnpc_declspec.h b/libs/miniupnpc/include/miniupnpc/miniupnpc_declspec.h similarity index 100% rename from libs/miniupnpc/include/miniupnpc_declspec.h rename to libs/miniupnpc/include/miniupnpc/miniupnpc_declspec.h diff --git a/libs/miniupnpc/include/miniupnpctypes.h b/libs/miniupnpc/include/miniupnpc/miniupnpctypes.h similarity index 100% rename from libs/miniupnpc/include/miniupnpctypes.h rename to libs/miniupnpc/include/miniupnpc/miniupnpctypes.h diff --git a/libs/miniupnpc/include/miniwget.h b/libs/miniupnpc/include/miniupnpc/miniwget.h similarity index 100% rename from libs/miniupnpc/include/miniwget.h rename to libs/miniupnpc/include/miniupnpc/miniwget.h diff --git a/libs/miniupnpc/include/portlistingparse.h b/libs/miniupnpc/include/miniupnpc/portlistingparse.h similarity index 100% rename from libs/miniupnpc/include/portlistingparse.h rename to libs/miniupnpc/include/miniupnpc/portlistingparse.h diff --git a/libs/miniupnpc/include/upnpcommands.h b/libs/miniupnpc/include/miniupnpc/upnpcommands.h similarity index 100% rename from libs/miniupnpc/include/upnpcommands.h rename to libs/miniupnpc/include/miniupnpc/upnpcommands.h diff --git a/libs/miniupnpc/include/upnpdev.h b/libs/miniupnpc/include/miniupnpc/upnpdev.h similarity index 100% rename from libs/miniupnpc/include/upnpdev.h rename to libs/miniupnpc/include/miniupnpc/upnpdev.h diff --git a/libs/miniupnpc/include/upnperrors.h b/libs/miniupnpc/include/miniupnpc/upnperrors.h similarity index 100% rename from libs/miniupnpc/include/upnperrors.h rename to libs/miniupnpc/include/miniupnpc/upnperrors.h diff --git a/libs/miniupnpc/include/upnpreplyparse.h b/libs/miniupnpc/include/miniupnpc/upnpreplyparse.h similarity index 100% rename from libs/miniupnpc/include/upnpreplyparse.h rename to libs/miniupnpc/include/miniupnpc/upnpreplyparse.h diff --git a/scripts/arm64-osx-1015.cmake b/scripts/arm64-osx-1015.cmake new file mode 100644 index 0000000000000000000000000000000000000000..224430bc1fe787c70db8480cf86e84f1e8bcb637 --- /dev/null +++ b/scripts/arm64-osx-1015.cmake @@ -0,0 +1,7 @@ +set(VCPKG_TARGET_ARCHITECTURE arm64) +set(VCPKG_OSX_DEPLOYMENT_TARGET 10.15) +set(VCPKG_CRT_LINKAGE dynamic) +set(VCPKG_LIBRARY_LINKAGE static) + +set(VCPKG_CMAKE_SYSTEM_NAME Darwin) +set(VCPKG_OSX_ARCHITECTURES arm64) diff --git a/scripts/make-macos-universal.sh b/scripts/make-macos-universal.sh new file mode 100755 index 0000000000000000000000000000000000000000..f1b17516c16fec2d333e5bfc9e3cc9fbfadb0499 --- /dev/null +++ b/scripts/make-macos-universal.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# Makes a fused macOS Universal app bundle in the arm64 release preset dir +# Only works if in master branch or in source tarball + +set -e + +rm -rf "build/ninja-x64_osx_vcpkg-release" +rm -rf "build/ninja-arm64_osx_vcpkg-release" +cmake --preset ninja-x64_osx_vcpkg-release -DVCPKG_OVERLAY_TRIPLETS=scripts/ -DVCPKG_TARGET_TRIPLET=x64-osx-1015 -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 "-DSRB2_SDL2_EXE_NAME=srb2" +cmake --build --preset ninja-x64_osx_vcpkg-release +cmake --preset ninja-arm64_osx_vcpkg-release -DVCPKG_OVERLAY_TRIPLETS=scripts/ -DVCPKG_TARGET_TRIPLET=arm64-osx-1015 -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 "-DSRB2_SDL2_EXE_NAME=srb2" +cmake --build --preset ninja-arm64_osx_vcpkg-release + +mkdir -p build/dist +rm -rf "build/dist/Sonic Robo Blast 2.app" "build/dist/srb2.app" + +cp -r build/ninja-arm64_osx_vcpkg-release/bin/srb2.app build/dist/ + +lipo -create \ + -output "build/dist/srb2.app/Contents/MacOS/srb2" \ + build/ninja-x64_osx_vcpkg-release/bin/srb2.app/Contents/MacOS/srb2 \ + build/ninja-arm64_osx_vcpkg-release/bin/srb2.app/Contents/MacOS/srb2 + +mv build/dist/srb2.app "build/dist/Sonic Robo Blast 2.app" diff --git a/scripts/x64-osx-1015.cmake b/scripts/x64-osx-1015.cmake new file mode 100644 index 0000000000000000000000000000000000000000..5f0c7b66e0e4c1c9969ed6963ddcc99cef9db64c --- /dev/null +++ b/scripts/x64-osx-1015.cmake @@ -0,0 +1,7 @@ +set(VCPKG_TARGET_ARCHITECTURE x64) +set(VCPKG_OSX_DEPLOYMENT_TARGET 10.15) +set(VCPKG_CRT_LINKAGE dynamic) +set(VCPKG_LIBRARY_LINKAGE static) + +set(VCPKG_CMAKE_SYSTEM_NAME Darwin) +set(VCPKG_OSX_ARCHITECTURES x86_64) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a7527461597db16e43f7a3ea83bb5f34497268c6..2cfb56f6e9645b126320f1242da095737ac866d5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -134,10 +134,13 @@ 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}") + if("${SRB2_CONFIG_STATIC_STDLIB}") # On MinGW with internal libraries, link the standard library statically target_link_options(SRB2SDL2 PRIVATE "-static") endif() + if(CMAKE_SIZEOF_VOID_P EQUAL 4) + target_link_options(SRB2SDL2 PRIVATE "-Wl,--large-address-aware") + endif() endif() target_compile_features(SRB2SDL2 PRIVATE c_std_11 cxx_std_17) @@ -154,6 +157,10 @@ if (UNIX) target_compile_definitions(SRB2SDL2 PRIVATE -DUNIXCOMMON) endif() +if (BSD MATCHES "FreeBSD") + target_compile_definitions(SRB2SDL2 PRIVATE -DFREEBSD) +endif() + if(CMAKE_COMPILER_IS_GNUCC) find_program(OBJCOPY objcopy) endif() @@ -165,23 +172,25 @@ if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") endif() endif() +if("${CMAKE_SYSTEM_NAME}" MATCHES "Haiku") + target_compile_definitions(SRB2SDL2 PRIVATE -DNOEXECINFO) + target_link_libraries(SRB2SDL2 PRIVATE network) +endif() + if("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin") target_compile_definitions(SRB2SDL2 PRIVATE -DMACOSX) endif() -target_link_libraries(SRB2SDL2 PRIVATE gme) -target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_GME) -if(NOT "${SRB2_CONFIG_SYSTEM_LIBRARIES}") - # this sucks but gme doesn't use modern cmake to delineate public headers - target_include_directories(SRB2SDL2 PRIVATE "${libgme_SOURCE_DIR}") +if("${SRB2_CONFIG_USE_GME}") + target_link_libraries(SRB2SDL2 PRIVATE gme) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_GME) + if(NOT "${SRB2_CONFIG_SYSTEM_LIBRARIES}") + # this sucks but gme doesn't use modern cmake to delineate public headers + target_include_directories(SRB2SDL2 PRIVATE "${libgme_SOURCE_DIR}") + endif() endif() -target_link_libraries(SRB2SDL2 PRIVATE openmpt) -target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_OPENMPT) - -target_link_libraries(SRB2SDL2 PRIVATE ZLIB::ZLIB PNG::PNG CURL::libcurl) -target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_ZLIB -DHAVE_PNG -DHAVE_CURL -D_LARGEFILE64_SOURCE) -target_sources(SRB2SDL2 PRIVATE apng.c) +target_compile_definitions(SRB2SDL2 PRIVATE -D_LARGEFILE64_SOURCE) set(SRB2_HAVE_THREADS ON) target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_THREADS) @@ -225,9 +234,12 @@ endif() # Compatibility flag with later versions of GCC # We should really fix our code to not need this -if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|x64|amd64|AMD64|em64t|EM64T)") - target_compile_options(SRB2SDL2 PRIVATE -mno-ms-bitfields) +if (NOT SRB2_CONFIG_FORCE_NO_MS_BITFIELDS) + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + check_cxx_compiler_flag("-mno-ms-bitfields" HAS_NO_MS_BITFIELDS) + if(HAS_NO_MS_BITFIELDS) + target_compile_options(SRB2SDL2 PRIVATE -mno-ms-bitfields) + endif() endif() endif() @@ -239,6 +251,7 @@ target_compile_options(SRB2SDL2 PRIVATE # This is a direct translation from versions.mk $<$<AND:$<COMPILE_LANGUAGE:C>,$<C_COMPILER_ID:GNU>>: -Wall + -Wextra -Wno-trigraphs -W # Was controlled by RELAXWARNINGS -Wfloat-equal @@ -306,11 +319,7 @@ target_compile_options(SRB2SDL2 PRIVATE $<$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,8.1.0>: -Wno-error=format-overflow - -Wno-error=stringop-truncation - -Wno-error=stringop-overflow -Wno-format-overflow - -Wno-stringop-truncation - -Wno-stringop-overflow -Wno-error=multistatement-macros > @@ -323,7 +332,9 @@ target_compile_options(SRB2SDL2 PRIVATE $<$<AND:$<COMPILE_LANGUAGE:C>,$<OR:$<C_COMPILER_ID:AppleClang>,$<C_COMPILER_ID:Clang>>>: -Wall -Wno-absolute-value + -Wextra -Wno-trigraphs + -Wconditional-uninitialized -Wno-error=non-literal-null-conversion -Wno-error=constant-conversion -Wno-error=unused-but-set-variable @@ -340,6 +351,9 @@ target_compile_options(SRB2SDL2 PRIVATE # C++, GNU, Clang and Apple Clang $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<OR:$<C_COMPILER_ID:GNU>,$<C_COMPILER_ID:AppleClang>,$<C_COMPILER_ID:Clang>>>: -Wall + -Wextra + -Wno-trigraphs + -Wconditional-uninitialized > # C++, MSVC @@ -395,8 +409,66 @@ if(SRB2_CONFIG_PROFILEMODE AND "${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") endif() add_subdirectory(sdl) -if(SRB2_CONFIG_ENABLE_TESTS) - add_subdirectory(tests) + +if(TARGET ZLIB::ZLIB) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_ZLIB) + message(STATUS "Zlib Found") +else() + message(STATUS "No Zlib Found") +endif() + +if(TARGET PNG::PNG) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_PNG) + target_sources(SRB2SDL2 PRIVATE apng.c ${libapng_HEADER}) + target_include_directories(SRB2SDL2 PRIVATE ${libapng_INCLUDE_DIRS} ${libpng_BINARY_DIR}) + #message(STATUS "libpng inc DIRS at ${libapng_INCLUDE_DIRS}") + #message(STATUS "libpng bin DIRS at ${libpng_BINARY_DIR}") + #message(STATUS "png.h at ${libapng_HEADER}") + message(STATUS "libpng Found") +else() + message(STATUS "No libpng Found") +endif() + +if(TARGET PNG::PNG AND TARGET ZLIB::ZLIB) +#libpng links zlib too? +target_link_libraries(SRB2SDL2 PRIVATE PNG::PNG) +endif() + +if(NOT TARGET PNG::PNG AND TARGET ZLIB::ZLIB) +#got no libpng? we need zlib +target_link_libraries(SRB2SDL2 PRIVATE ZLIB::ZLIB) +endif() + +if(TARGET gme::gme) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_GME) + target_link_libraries(SRB2SDL2 PRIVATE gme::gme) + message(STATUS "libgme Found") +else() + message(STATUS "No libgme Found") +endif() + +if(TARGET libopenmpt::libopenmpt) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_OPENMPT) + target_link_libraries(SRB2SDL2 PRIVATE libopenmpt::libopenmpt) + message(STATUS "libopenmpt Found") +else() + message(STATUS "No libopenmpt Found") +endif() + +if(TARGET CURL::libcurl) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_CURL) + target_link_libraries(SRB2SDL2 PRIVATE CURL::libcurl) + message(STATUS "libcurl Found") +else() + message(STATUS "No libcurl Found") +endif() + +if(TARGET miniupnpc::miniupnpc) + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_MINIUPNPC) + target_link_libraries(SRB2SDL2 PRIVATE miniupnpc::miniupnpc) + message(STATUS "miniupnpc Found") +else() + message(STATUS "No miniupnpc Found") endif() # strip debug symbols into separate file when using gcc. diff --git a/src/Makefile b/src/Makefile index 6dba19c2418d9ee465b435b40332245762ecd21f..40037834d3b2831f92a9897ea51336060addfc24 100644 --- a/src/Makefile +++ b/src/Makefile @@ -47,8 +47,6 @@ # HAVE_MINIUPNPC=1 - Enable automated port forwarding. # Already enabled by default for 32-bit # Windows. -# NOPNG=1 - Disable PNG graphics support. (TODO: double -# check netplay compatible.) # NOCURL=1 - Disable libcurl--HTTP capability. # NOGME=1 - Disable game music emu, retro VGM support. # NOOPENMPT=1 - Disable module (tracker) music support. @@ -69,8 +67,6 @@ # NOEXECINFO=1 - Disable stack trace dump support # DEBUGMODE=1 - Enable various debugging capabilities. # Also disables optimizations. -# NOZLIB=1 - Disable some compression capability. Implies -# NOPNG=1. # # Development flags: # diff --git a/src/Makefile.d/dedicated.mk b/src/Makefile.d/dedicated.mk new file mode 100644 index 0000000000000000000000000000000000000000..698ea553191a84775acf23c45715ba8fee6d0862 --- /dev/null +++ b/src/Makefile.d/dedicated.mk @@ -0,0 +1,24 @@ +makedir:=$(makedir)/Dedicated + +sources+=$(call List,dedicated/Sourcefile) + +opts+=-DDEDICATED + +ifdef FREEBSD +# on FreeBSD, we have to link to libpthread explicitly +libs+=-lpthread +endif + +ifdef MINGW +libs+=-mconsole +endif + +ifndef NOTHREADS +opts+=-DHAVE_THREADS +sources+=dedicated/i_threads.c +endif + +NOOPENMPT=1 +NOGME=1 +NOHW=1 +NOUPNP=1 diff --git a/src/Makefile.d/detect.mk b/src/Makefile.d/detect.mk index 9e27369462b00c407f02cb95dbda22ef284a91d1..853ad3d6df728d7c69ea64b204cf099547f59e45 100644 --- a/src/Makefile.d/detect.mk +++ b/src/Makefile.d/detect.mk @@ -4,7 +4,6 @@ # Previously featured:\ PANDORA\ - HAIKU\ DUMMY\ DJGPPDOS\ SOLARIS\ @@ -17,6 +16,7 @@ all_systems:=\ UNIX\ LINUX\ FREEBSD\ + HAIKU\ # check for user specified system ifeq (,$(filter $(all_systems),$(.VARIABLES))) @@ -35,6 +35,8 @@ system:=$(shell uname -s) ifeq ($(system),Linux) new_system:=LINUX +else ifeq ($(system),Haiku) +new_system:=HAIKU else $(error \ diff --git a/src/Makefile.d/features.mk b/src/Makefile.d/features.mk index d132ecc9e69517a3536eccad071fd5841ebb2a91..59806862d50d884329ab5183d1061b15987c9d01 100644 --- a/src/Makefile.d/features.mk +++ b/src/Makefile.d/features.mk @@ -22,8 +22,6 @@ ifndef NOMD5 sources+=md5.c endif -ifndef NOZLIB -ifndef NOPNG ifdef PNG_PKGCONFIG $(eval $(call Use_pkg_config,PNG_PKGCONFIG)) else @@ -36,8 +34,6 @@ opts+=-D_LARGEFILE64_SOURCE endif opts+=-DHAVE_PNG sources+=apng.c -endif -endif ifndef NOCURL CURLCONFIG?=curl-config diff --git a/src/Makefile.d/haiku.mk b/src/Makefile.d/haiku.mk new file mode 100644 index 0000000000000000000000000000000000000000..6742ec75b58f992a916a99752c72ca827f4dab5e --- /dev/null +++ b/src/Makefile.d/haiku.mk @@ -0,0 +1,71 @@ +# +# Makefile options for Haiku +# + +opts+=-DUNIXCOMMON -DLUA_USE_POSIX + +ifndef DEDICATED +ifndef DUMMY +SDL?=1 +DEDICATED?=0 +endif +endif + +NOEXECINFO=1 + +ifeq (${SDL},1) +EXENAME?=srb2haiku +else ifeq (${DEDICATED},1) +EXENAME?=srb2haikud +endif + +ifndef NONET +libs+=-lnetwork +endif + +define _set = +$(1)_CFLAGS?=$($(1)_opts) +$(1)_LDFLAGS?=$($(1)_libs) +endef + +lib:=../libs/gme +LIBGME_opts:=-I$(lib)/include +LIBGME_libs:=-l:libgme.so.0 +$(eval $(call _set,LIBGME)) + +lib:=../libs/libopenmpt +LIBOPENMPT_opts:=-I$(lib)/inc +LIBOPENMPT_libs:=-l:libopenmpt.so.0 +$(eval $(call _set,LIBOPENMPT)) + +ifdef SDL +lib:=../libs/SDL2_mixer +mixer_opts:=-I$(lib)/include +mixer_libs:=-l:libSDL2_mixer-2.0.so.0 + +lib:=../libs/SDL2 +SDL_opts:=-I$(lib)/include $(mixer_opts) +SDL_libs:=$(mixer_libs) -l:libSDL2-2.0.so.0 +$(eval $(call _set,SDL)) +endif + +lib:=../libs/zlib +ZLIB_opts:=-I$(lib) +ZLIB_libs:=-l:libz.so.1 +$(eval $(call _set,ZLIB)) + +ifndef PNG_CONFIG +PNG_opts:= +PNG_libs:=-l:libpng16.so.16 +$(eval $(call _set,PNG)) +endif + +lib:=../libs/curl +CURL_opts:=-I$(lib)/include +CURL_libs:=-l:libcurl.so.4 +$(eval $(call _set,CURL)) + +lib:=../libs/miniupnpc +MINIUPNPC_opts:=-I$(lib)/include +MINIUPNPC_libs:=-l:libminiupnpc.so.17 +$(eval $(call _set,MINIUPNPC)) diff --git a/src/Makefile.d/nix.mk b/src/Makefile.d/nix.mk index 9adf3f0f14fdc2b052e48053cabedee48a1a7edd..d06544667118ad8cde12d7f41f286e8c9a561a1b 100644 --- a/src/Makefile.d/nix.mk +++ b/src/Makefile.d/nix.mk @@ -2,8 +2,6 @@ # Makefile options for unices (linux, bsd...) # -EXENAME?=lsdl2srb2 - opts+=-DUNIXCOMMON -DLUA_USE_POSIX # Use -rdynamic so a backtrace log shows function names # instead of addresses @@ -14,7 +12,20 @@ opts+=-I/usr/X11R6/include libs+=-L/usr/X11R6/lib endif +ifndef DEDICATED +ifndef DUMMY SDL?=1 +DEDICATED?=0 +endif +endif + +ifeq (${SDL},1) +EXENAME?=lsdl2srb2 +endif + +ifeq (${DEDICATED},1) +EXENAME?=lsrb2d +endif # In common usage. ifdef LINUX diff --git a/src/Makefile.d/platform.mk b/src/Makefile.d/platform.mk index d19143e4cf6040dc161b201553db3942b123ee39..d5423a397384922689260546b71948447846f3e1 100644 --- a/src/Makefile.d/platform.mk +++ b/src/Makefile.d/platform.mk @@ -35,6 +35,10 @@ endif else ifdef FREEBSD UNIX=1 platform=freebsd +else ifdef HAIKU +# Give Haiku its own configuration, since it +# isn't actually UNIX. +include Makefile.d/haiku.mk else ifdef SOLARIS # FIXME: UNTESTED UNIX=1 platform=solaris @@ -65,6 +69,8 @@ endif ifeq ($(SDL), 1) include Makefile.d/sdl.mk +else ifeq ($(DEDICATED), 1) +include Makefile.d/dedicated.mk else include Makefile.d/dummy.mk endif diff --git a/src/Makefile.d/sdl.mk b/src/Makefile.d/sdl.mk index a1bfa33038bbacebada85790a7565fceb9440985..d5e83989c2d1955146a8c228c15034d9f2b9e091 100644 --- a/src/Makefile.d/sdl.mk +++ b/src/Makefile.d/sdl.mk @@ -33,11 +33,13 @@ else opts+=-DHAVE_MIXER sources+=sdl/mixer_sound.c - ifdef HAVE_MIXERX - opts+=-DHAVE_MIXERX - libs+=-lSDL2_mixer_ext - else - libs+=-lSDL2_mixer + ifndef HAIKU # Haiku has a special import path + ifdef HAVE_MIXERX + opts+=-DHAVE_MIXERX + libs+=-lSDL2_mixer_ext + else + libs+=-lSDL2_mixer + endif endif endif diff --git a/src/Makefile.d/versions.mk b/src/Makefile.d/versions.mk index b639ad9a13cb45a898d5c3d5b9d773b3203c2daf..7c130d90846ab6f4199eb618ee918fdb6999e5cc 100644 --- a/src/Makefile.d/versions.mk +++ b/src/Makefile.d/versions.mk @@ -135,11 +135,7 @@ ifdef GCC71 endif ifdef GCC81 WFLAGS+=-Wno-error=format-overflow - WFLAGS+=-Wno-error=stringop-truncation - WFLAGS+=-Wno-error=stringop-overflow WFLAGS+=-Wno-format-overflow - WFLAGS+=-Wno-stringop-truncation - WFLAGS+=-Wno-stringop-overflow WFLAGS+=-Wno-error=multistatement-macros endif diff --git a/src/Makefile.d/win32.mk b/src/Makefile.d/win32.mk index 3e60e2416318f752a45261d14d9c349205fdb8ac..51523a212463172ebdffec37e3a798c8fad5a850 100644 --- a/src/Makefile.d/win32.mk +++ b/src/Makefile.d/win32.mk @@ -17,7 +17,11 @@ sources+=win32/Srb2win.rc opts+=-DSTDC_HEADERS libs+=-ladvapi32 -lkernel32 -lmsvcrt -luser32 +ifndef DEDICATED +ifndef DUMMY SDL?=1 +endif +endif ifndef NOHW opts+=-DUSE_WGL_SWAP diff --git a/src/am_map.c b/src/am_map.c index df3a45cfff504e046ddaa6ecc03cf9f9d548e45f..36b62f2f9b0157c58a2becd8b55624302d29ae0b 100644 --- a/src/am_map.c +++ b/src/am_map.c @@ -1076,6 +1076,9 @@ static inline void AM_drawPlayers(void) if (!playeringame[i] || players[i].spectator) continue; + if (!players[i].mo) + continue; + p = &players[i]; if (p->skincolor > 0) color = R_GetTranslationColormap(TC_DEFAULT, p->skincolor, GTC_CACHE)[GREENS + 8]; diff --git a/src/android/i_video.c b/src/android/i_video.c index bf0decb74118385ff2b776d8d470e5ea3a03a2ba..896a5b899c008197df570376d2e0c406a1a8351e 100644 --- a/src/android/i_video.c +++ b/src/android/i_video.c @@ -11,8 +11,6 @@ rendermode_t rendermode = render_soft; rendermode_t chosenrendermode = render_none; -boolean highcolor = false; - boolean allow_fullscreen = false; diff --git a/src/apng.c b/src/apng.c index 11d3ab9f58ea9c26530374b7b18d8454fd367ed8..cfb1473a40269703985bc727cafd5f27f2c14f02 100644 --- a/src/apng.c +++ b/src/apng.c @@ -71,7 +71,7 @@ apng_create_info_struct (png_structp pngp) { apng_infop ainfop; (void)pngp; - if (( ainfop = calloc(sizeof (apng_info),1) )) + if (( ainfop = calloc(1,sizeof (apng_info)) )) { apng_set_write_fn(pngp, ainfop, 0, 0, 0, 0, 0); apng_set_set_acTL_fn(pngp, ainfop, 0); diff --git a/src/b_bot.c b/src/b_bot.c index c8228e840f751b676a00e920cde61dcb8f06311c..97dcd1078dfd91f9c5caf03c352420cbc98198de 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2007-2016 by John "JTE" Muniz. -// Copyright (C) 2011-2023 by Sonic Team Junior. +// Copyright (C) 2011-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -387,7 +387,8 @@ void B_BuildTiccmd(player_t *player, ticcmd_t *cmd) } // Bot AI isn't programmed in analog. - CV_SetValue(&cv_analog[1], false); + if (!dedicated) + CV_SetValue(&cv_analog[1], false); // Let Lua scripts build ticcmds if (LUA_HookTiccmd(player, cmd, HOOK(BotTiccmd))) @@ -589,8 +590,9 @@ void B_RespawnBot(INT32 playernum) } else P_SetMobjState(tails, S_PLAY_FALL); - P_SetScale(tails, sonic->scale); + P_SetScale(tails, sonic->scale, false); tails->destscale = sonic->destscale; + tails->old_scale = sonic->old_scale; } void B_HandleFlightIndicator(player_t *player) diff --git a/src/blua/lauxlib.h b/src/blua/lauxlib.h index c5ea45a1cbc4c4612909107b4e3fdd5d8f88de0d..87844f4057720b36442a22ee3b419717ce756025 100644 --- a/src/blua/lauxlib.h +++ b/src/blua/lauxlib.h @@ -31,6 +31,26 @@ LUALIB_API void (luaL_setn) (lua_State *L, int t, int n); /* extra error code for `luaL_load' */ #define LUA_ERRFILE (LUA_ERRERR+1) +/* Compiler-specific attributes and other macros */ + +#ifdef __GNUC__ // __attribute__ ((X)) + + #if ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) && defined (__MINGW32__) // MinGW, >= GCC 4.1 + #if 0 //defined (__USE_MINGW_ANSI_STDIO) && __USE_MINGW_ANSI_STDIO > 0 + #define FUNCREPORT __attribute__ ((format(gnu_printf, 2, 3))) + #elif (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) // >= GCC 4.4 + #define FUNCREPORT __attribute__ ((format(ms_printf, 2, 3))) + #else + #define FUNCREPORT __attribute__ ((format(printf, 2, 3))) + #endif + #else + #define FUNCREPORT __attribute__ ((format(printf, 2, 3))) + #endif +#endif + +#ifndef FUNCREPORT +#define FUNCREPORT +#endif typedef struct luaL_Reg { const char *name; @@ -65,7 +85,7 @@ LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); LUALIB_API void (luaL_where) (lua_State *L, int lvl); -LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); +LUALIB_API FUNCREPORT int (luaL_error) (lua_State *L, const char *fmt, ...); LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, const char *const lst[]); diff --git a/src/blua/lvm.c b/src/blua/lvm.c index b74fef4ee3d72d3081fdb11776ab759c337020f3..627685b389dcdea401dffc72ed02ef061394a1b6 100644 --- a/src/blua/lvm.c +++ b/src/blua/lvm.c @@ -134,7 +134,7 @@ void luaV_gettable (lua_State *L, TValue *t, TValue *key, StkId val) { void luaV_settable (lua_State *L, TValue *t, TValue *key, StkId val) { int loop; for (loop = 0; loop < MAXTAGLOOP; loop++) { - TValue *tm; + TValue *tm = NULL; if (ttistable(t)) { /* `t' is a table? */ Table *h = hvalue(t); TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ diff --git a/src/byteptr.h b/src/byteptr.h index 8ab359c4c4d9d00a0f613a86588b96a46112cd68..61cefd350b758835a1b5b0c0f2853d04e95c2954 100644 --- a/src/byteptr.h +++ b/src/byteptr.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -11,9 +11,6 @@ /// \brief Macros to read/write from/to a UINT8 *, /// used for packet creation and such -#if defined (__alpha__) || defined (__arm__) || defined (__mips__) || defined (__ia64__) || defined (__clang__) -#define DEALIGNED -#endif #include "endian.h" @@ -21,7 +18,6 @@ // // Little-endian machines // -#ifdef DEALIGNED #define WRITEUINT8(p,b) do { UINT8 *p_tmp = (void *)p; const UINT8 tv = ( UINT8)(b); memcpy(p, &tv, sizeof( UINT8)); p_tmp++; p = (void *)p_tmp; } while (0) #define WRITESINT8(p,b) do { SINT8 *p_tmp = (void *)p; const SINT8 tv = ( UINT8)(b); memcpy(p, &tv, sizeof( UINT8)); p_tmp++; p = (void *)p_tmp; } while (0) #define WRITEINT16(p,b) do { INT16 *p_tmp = (void *)p; const INT16 tv = ( INT16)(b); memcpy(p, &tv, sizeof( INT16)); p_tmp++; p = (void *)p_tmp; } while (0) @@ -31,20 +27,8 @@ #define WRITECHAR(p,b) do { char *p_tmp = (void *)p; const char tv = ( char)(b); memcpy(p, &tv, sizeof( char)); p_tmp++; p = (void *)p_tmp; } while (0) #define WRITEFIXED(p,b) do { fixed_t *p_tmp = (void *)p; const fixed_t tv = (fixed_t)(b); memcpy(p, &tv, sizeof(fixed_t)); p_tmp++; p = (void *)p_tmp; } while (0) #define WRITEANGLE(p,b) do { angle_t *p_tmp = (void *)p; const angle_t tv = (angle_t)(b); memcpy(p, &tv, sizeof(angle_t)); p_tmp++; p = (void *)p_tmp; } while (0) -#else -#define WRITEUINT8(p,b) do { UINT8 *p_tmp = ( UINT8 *)p; *p_tmp = ( UINT8)(b); p_tmp++; p = (void *)p_tmp; } while (0) -#define WRITESINT8(p,b) do { SINT8 *p_tmp = ( SINT8 *)p; *p_tmp = ( SINT8)(b); p_tmp++; p = (void *)p_tmp; } while (0) -#define WRITEINT16(p,b) do { INT16 *p_tmp = ( INT16 *)p; *p_tmp = ( INT16)(b); p_tmp++; p = (void *)p_tmp; } while (0) -#define WRITEUINT16(p,b) do { UINT16 *p_tmp = ( UINT16 *)p; *p_tmp = ( UINT16)(b); p_tmp++; p = (void *)p_tmp; } while (0) -#define WRITEINT32(p,b) do { INT32 *p_tmp = ( INT32 *)p; *p_tmp = ( INT32)(b); p_tmp++; p = (void *)p_tmp; } while (0) -#define WRITEUINT32(p,b) do { UINT32 *p_tmp = ( UINT32 *)p; *p_tmp = ( UINT32)(b); p_tmp++; p = (void *)p_tmp; } while (0) -#define WRITECHAR(p,b) do { char *p_tmp = ( char *)p; *p_tmp = ( char)(b); p_tmp++; p = (void *)p_tmp; } while (0) -#define WRITEFIXED(p,b) do { fixed_t *p_tmp = (fixed_t *)p; *p_tmp = (fixed_t)(b); p_tmp++; p = (void *)p_tmp; } while (0) -#define WRITEANGLE(p,b) do { angle_t *p_tmp = (angle_t *)p; *p_tmp = (angle_t)(b); p_tmp++; p = (void *)p_tmp; } while (0) -#endif #ifdef __GNUC__ -#ifdef DEALIGNED #define READUINT8(p) ({ UINT8 *p_tmp = (void *)p; UINT8 b; memcpy(&b, p, sizeof( UINT8)); p_tmp++; p = (void *)p_tmp; b; }) #define READSINT8(p) ({ SINT8 *p_tmp = (void *)p; SINT8 b; memcpy(&b, p, sizeof( SINT8)); p_tmp++; p = (void *)p_tmp; b; }) #define READINT16(p) ({ INT16 *p_tmp = (void *)p; INT16 b; memcpy(&b, p, sizeof( INT16)); p_tmp++; p = (void *)p_tmp; b; }) @@ -55,17 +39,6 @@ #define READFIXED(p) ({ fixed_t *p_tmp = (void *)p; fixed_t b; memcpy(&b, p, sizeof(fixed_t)); p_tmp++; p = (void *)p_tmp; b; }) #define READANGLE(p) ({ angle_t *p_tmp = (void *)p; angle_t b; memcpy(&b, p, sizeof(angle_t)); p_tmp++; p = (void *)p_tmp; b; }) #else -#define READUINT8(p) ({ UINT8 *p_tmp = ( UINT8 *)p; UINT8 b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; }) -#define READSINT8(p) ({ SINT8 *p_tmp = ( SINT8 *)p; SINT8 b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; }) -#define READINT16(p) ({ INT16 *p_tmp = ( INT16 *)p; INT16 b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; }) -#define READUINT16(p) ({ UINT16 *p_tmp = ( UINT16 *)p; UINT16 b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; }) -#define READINT32(p) ({ INT32 *p_tmp = ( INT32 *)p; INT32 b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; }) -#define READUINT32(p) ({ UINT32 *p_tmp = ( UINT32 *)p; UINT32 b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; }) -#define READCHAR(p) ({ char *p_tmp = ( char *)p; char b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; }) -#define READFIXED(p) ({ fixed_t *p_tmp = (fixed_t *)p; fixed_t b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; }) -#define READANGLE(p) ({ angle_t *p_tmp = (angle_t *)p; angle_t b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; }) -#endif -#else #define READUINT8(p) *(( UINT8 *)p)++ #define READSINT8(p) *(( SINT8 *)p)++ #define READINT16(p) *(( INT16 *)p)++ @@ -148,8 +121,6 @@ FUNCINLINE static ATTRINLINE UINT32 readulong(void *ptr) #define READANGLE(p) ({ angle_t *p_tmp = (angle_t *)p; angle_t b = readulong(p); p_tmp++; p = (void *)p_tmp; b; }) #endif //SRB2_BIG_ENDIAN -#undef DEALIGNED - #define WRITESTRINGN(p, s, n) { \ size_t tmp_i; \ \ diff --git a/src/command.c b/src/command.c index 87d4f893fe6683cd21e93a8663dd71b30dce57af..ab6cfc08af7c4cde9f756d868b02e42ffd29229d 100644 --- a/src/command.c +++ b/src/command.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -648,7 +648,7 @@ static void COM_ExecuteString(char *ptext) { if ((com_flags & COM_LUA) && !(cmd->flags & COM_LUA)) { - CONS_Alert(CONS_WARNING, "Command '%s' cannot be run from Lua.\n", cmd->name); + CONS_Alert(CONS_WARNING, "Command '%s' cannot be run from a script.\n", cmd->name); return; } @@ -705,7 +705,7 @@ static void add_alias(char *newname, char *newcmd) { if (!stricmp(newname, a->name)) { - Z_Free(a->value); // Free old cmd + Z_Free(a->value); // Free old cmd a->value = newcmd; return; } @@ -809,49 +809,60 @@ static void COM_CEchoDuration_f(void) /** Executes a script file. */ -static void COM_Exec_f(void) +boolean COM_ExecFile(const char *scriptname, com_flags_t flags, boolean silent) { UINT8 *buf = NULL; char filename[256]; - if (COM_Argc() < 2 || COM_Argc() > 3) - { - CONS_Printf(M_GetText("exec <filename>: run a script file\n")); - return; - } - - if (!D_CheckPathAllowed(COM_Argv(1), "tried to exec")) - return; + if (!D_CheckPathAllowed(scriptname, "tried to exec")) + return false; // load file // Try with Argv passed verbatim first, for back compat - FIL_ReadFile(COM_Argv(1), &buf); + FIL_ReadFile(scriptname, &buf); if (!buf) { // Now try by searching the file path // filename is modified with the full found path - strcpy(filename, COM_Argv(1)); + strlcpy(filename, scriptname, sizeof(filename)); if (findfile(filename, NULL, true) != FS_NOTFOUND) FIL_ReadFile(filename, &buf); if (!buf) - { - if (!COM_CheckParm("-noerror")) - CONS_Printf(M_GetText("couldn't execute file %s\n"), COM_Argv(1)); - return; - } + return false; } - if (!COM_CheckParm("-silent")) - CONS_Printf(M_GetText("executing %s\n"), COM_Argv(1)); + if (!silent) + CONS_Printf(M_GetText("Executing %s\n"), scriptname); // insert text file into the command buffer - COM_BufAddTextEx((char *)buf, com_flags); - COM_BufAddTextEx("\n", com_flags); + COM_BufAddTextEx((char *)buf, flags); + COM_BufAddTextEx("\n", flags); // free buffer Z_Free(buf); + + return true; +} + +static void COM_Exec_f(void) +{ + boolean silent; + + if (COM_Argc() < 2 || COM_Argc() > 3) + { + CONS_Printf(M_GetText("exec <filename>: run a script file\n")); + return; + } + + silent = COM_CheckParm("-silent"); + + if (COM_ExecFile(COM_Argv(1), com_flags, silent)) + return; + + if (!COM_CheckParm("-noerror")) + CONS_Printf(M_GetText("Couldn't execute file %s\n"), COM_Argv(1)); } /** Delays execution of the rest of the commands until the next frame. @@ -1722,8 +1733,7 @@ badinput: static boolean serverloading = false; -static consvar_t * -ReadNetVar (UINT8 **p, char **return_value, boolean *return_stealth) +static consvar_t *ReadNetVar(save_t *p, char **return_value, boolean *return_stealth) { UINT16 netid; char *val; @@ -1731,10 +1741,10 @@ ReadNetVar (UINT8 **p, char **return_value, boolean *return_stealth) consvar_t *cvar; - netid = READUINT16 (*p); - val = (char *)*p; - SKIPSTRING (*p); - stealth = READUINT8 (*p); + netid = P_ReadUINT16(p); + val = (char *)&p->buf[p->pos]; + P_SkipString(p); + stealth = P_ReadUINT8(p); cvar = CV_FindNetVar(netid); @@ -1752,8 +1762,7 @@ ReadNetVar (UINT8 **p, char **return_value, boolean *return_stealth) } #ifdef OLD22DEMOCOMPAT -static consvar_t * -ReadOldDemoVar (UINT8 **p, char **return_value, boolean *return_stealth) +static consvar_t *ReadOldDemoVar(save_t *p, char **return_value, boolean *return_stealth) { UINT16 id; char *val; @@ -1761,10 +1770,10 @@ ReadOldDemoVar (UINT8 **p, char **return_value, boolean *return_stealth) old_demo_var_t *demovar; - id = READUINT16 (*p); - val = (char *)*p; - SKIPSTRING (*p); - stealth = READUINT8 (*p); + id = P_ReadUINT16(p); + val = (char *)&p->buf[p->pos]; + P_SkipString(p); + stealth = P_ReadUINT8(p); demovar = CV_FindOldDemoVar(id); @@ -1783,8 +1792,7 @@ ReadOldDemoVar (UINT8 **p, char **return_value, boolean *return_stealth) } #endif/*OLD22DEMOCOMPAT*/ -static consvar_t * -ReadDemoVar (UINT8 **p, char **return_value, boolean *return_stealth) +static consvar_t *ReadDemoVar(save_t *p, char **return_value, boolean *return_stealth) { char *name; char *val; @@ -1792,11 +1800,11 @@ ReadDemoVar (UINT8 **p, char **return_value, boolean *return_stealth) consvar_t *cvar; - name = (char *)*p; - SKIPSTRING (*p); - val = (char *)*p; - SKIPSTRING (*p); - stealth = READUINT8 (*p); + name = (char *)&p->buf[p->pos]; + P_SkipString(p); + val = (char *)&p->buf[p->pos]; + P_SkipString(p); + stealth = P_ReadUINT8(p); cvar = CV_FindVar(name); @@ -1826,41 +1834,46 @@ static void Got_NetVar(UINT8 **p, INT32 playernum) return; } - cvar = ReadNetVar(p, &svalue, &stealth); + save_t save_p; + save_p.buf = *p; + save_p.size = MAXTEXTCMD; + save_p.pos = 0; + cvar = ReadNetVar(&save_p, &svalue, &stealth); + *p = &save_p.buf[save_p.pos]; if (cvar) Setvalue(cvar, svalue, stealth); } -void CV_SaveVars(UINT8 **p, boolean in_demo) +void CV_SaveVars(save_t *p, boolean in_demo) { consvar_t *cvar; - UINT8 *count_p = *p; + UINT8 *count_p = &p->buf[p->pos]; UINT16 count = 0; // send only changed cvars ... // the client will reset all netvars to default before loading - WRITEUINT16(*p, 0x0000); + P_WriteUINT16(p, 0x0000); for (cvar = consvar_vars; cvar; cvar = cvar->next) if ((cvar->flags & CV_NETVAR) && !CV_IsSetToDefault(cvar)) { if (in_demo) { - WRITESTRING(*p, cvar->name); + P_WriteString(p, cvar->name); } else { - WRITEUINT16(*p, cvar->netid); + P_WriteUINT16(p, cvar->netid); } - WRITESTRING(*p, cvar->string); - WRITEUINT8(*p, false); + P_WriteString(p, cvar->string); + P_WriteUINT8(p, false); ++count; } WRITEUINT16(count_p, count); } -static void CV_LoadVars(UINT8 **p, - consvar_t *(*got)(UINT8 **p, char **ret_value, boolean *ret_stealth)) +static void CV_LoadVars(save_t *p, + consvar_t *(*got)(save_t *p, char **ret_value, boolean *ret_stealth)) { const boolean store = (client || demoplayback); @@ -1888,7 +1901,7 @@ static void CV_LoadVars(UINT8 **p, } } - count = READUINT16(*p); + count = P_ReadUINT16(p); while (count--) { cvar = (*got)(p, &val, &stealth); @@ -1921,19 +1934,19 @@ void CV_RevertNetVars(void) } } -void CV_LoadNetVars(UINT8 **p) +void CV_LoadNetVars(save_t *p) { CV_LoadVars(p, ReadNetVar); } #ifdef OLD22DEMOCOMPAT -void CV_LoadOldDemoVars(UINT8 **p) +void CV_LoadOldDemoVars(save_t *p) { CV_LoadVars(p, ReadOldDemoVar); } #endif -void CV_LoadDemoVars(UINT8 **p) +void CV_LoadDemoVars(save_t *p) { CV_LoadVars(p, ReadDemoVar); } @@ -1986,13 +1999,13 @@ static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth) if (!var->string) I_Error("CV_Set: %s no string set!\n", var->name); #endif - if (!var || !var->string || !value || !stricmp(var->string, value)) + if (!var || !var->string || !value || (var->can_change == NULL && !stricmp(var->string, value))) return; // no changes if (var->flags & CV_NETVAR) { // send the value of the variable - UINT8 buf[128]; + UINT8 buf[512]; UINT8 *p = buf; // Loading from a config in a netgame? Set revert value. @@ -2060,16 +2073,15 @@ void CV_StealthSet(consvar_t *var, const char *value) */ static void CV_SetValueMaybeStealth(consvar_t *var, INT32 value, boolean stealth) { - char val[SKINNAMESIZE+1]; + char val[SKINNAMESIZE+1] = "None"; if (var == &cv_forceskin) // Special handling. { const char *tmpskin = NULL; - if ((value < 0) || (value >= numskins)) - tmpskin = "None"; - else + if (value >= 0 && value < numskins) tmpskin = skins[value]->name; - strncpy(val, tmpskin, SKINNAMESIZE); + if (tmpskin) + memcpy(val, tmpskin, SKINNAMESIZE); } else sprintf(val, "%d", value); @@ -2492,7 +2504,7 @@ static boolean CV_Command(void) if (CV_Immutable(v)) { - CONS_Alert(CONS_WARNING, "Variable '%s' cannot be changed from Lua.\n", v->name); + CONS_Alert(CONS_WARNING, "Variable '%s' cannot be changed from a script.\n", v->name); return true; } diff --git a/src/command.h b/src/command.h index f0dc62418a8815abfa9e7c9b84d9357aac406b73..70342a78512783e6ea3bf3fc2122bee21d074099 100644 --- a/src/command.h +++ b/src/command.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -15,6 +15,7 @@ #include <stdio.h> #include "doomdef.h" +#include "p_saveg.h" //=================================== // Command buffer & command execution @@ -65,6 +66,9 @@ void COM_ImmedExecute(const char *ptext); // Execute commands in buffer, flush them void COM_BufExecute(void); +// Executes a script from a file +boolean COM_ExecFile(const char *scriptname, com_flags_t flags, boolean silent); + // As above; and progress the wait timer. void COM_BufTicker(void); @@ -218,19 +222,19 @@ void CV_AddValue(consvar_t *var, INT32 increment); void CV_SaveVariables(FILE *f); // load/save gamesate (load and save option and for network join in game) -void CV_SaveVars(UINT8 **p, boolean in_demo); +void CV_SaveVars(save_t *p, boolean in_demo); #define CV_SaveNetVars(p) CV_SaveVars(p, false) -void CV_LoadNetVars(UINT8 **p); +void CV_LoadNetVars(save_t *p); // then revert after leaving a netgame void CV_RevertNetVars(void); #define CV_SaveDemoVars(p) CV_SaveVars(p, true) -void CV_LoadDemoVars(UINT8 **p); +void CV_LoadDemoVars(save_t *p); #ifdef OLD22DEMOCOMPAT -void CV_LoadOldDemoVars(UINT8 **p); +void CV_LoadOldDemoVars(save_t *p); #endif // reset cheat netvars after cheats is deactivated diff --git a/src/config.h.in b/src/config.h.in index 6d49a698934bf8b498f6bfb402bbaa7f8ff93191..0f24cfc4466e3b8387777ba68a1b83ead3f3dbc3 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -40,12 +40,14 @@ * 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 + * Last updated 2025 / 01 / 16 - v2.2.14 - main assets + * Last updated 2025 / 01 / 24 - v2.2.15 - main assets */ -#define ASSET_HASH_SRB2_PK3 "ad911f29a28a18968ee5b2d11c2acb39" -#define ASSET_HASH_ZONES_PK3 "1c8adf8d079ecb87d00081f158acf3c7" -#define ASSET_HASH_PLAYER_DTA "2e7aaae8a6b1b77d90ffe7606ceadb6c" +#define ASSET_HASH_SRB2_PK3 "3182ce524acc2072ddaa81acf4b6a9aa" +#define ASSET_HASH_ZONES_PK3 "88ff4c300851ccdb0406698eadd89907" +#define ASSET_HASH_CHARACTERS_PK3 "5c5936b8a690e007c0939bd0785a41fb" #ifdef USE_PATCH_DTA -#define ASSET_HASH_PATCH_PK3 "3c7b73f34af7e9a7bceb2d5260f76172" +#define ASSET_HASH_PATCH_PK3 "00000000000000000000000000000000" #endif #endif diff --git a/src/console.c b/src/console.c index 93b9fb54d022d71b0917c6a4cd351d2acda4d1e1..50ecfec9c28fa11a9395907478dbb93d9d416a24 100644 --- a/src/console.c +++ b/src/console.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -70,14 +70,9 @@ static boolean consoleready; // console prompt is ready INT32 con_destlines; // vid lines used by console at final position static INT32 con_curlines; // vid lines currently used by console - INT32 con_clipviewtop; // (useless) - 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 - // console text output static char *con_line; // console text output current line static size_t con_cx; // cursor position in current line @@ -120,7 +115,7 @@ static void CONS_backcolor_Change(void); #ifdef macintosh #define CON_BUFFERSIZE 4096 // my compiler can't handle local vars >32k #else -#define CON_BUFFERSIZE 16384 +#define CON_BUFFERSIZE 32768 #endif static char con_buffer[CON_BUFFERSIZE]; @@ -220,7 +215,7 @@ static char *bindtable[NUMINPUTS]; static void CONS_Bind_f(void) { size_t na; - char *newcmd; + char *newcmd = NULL; //size_t newlen = 0; unsigned int i; INT32 key; @@ -473,9 +468,6 @@ void CON_Init(void) Lock_state(); - //note: CON_Ticker should always execute at least once before D_Display() - con_clipviewtop = -1; // -1 does not clip - con_hudlines = atoi(cons_hudlines.defaultvalue); Unlock_state(); @@ -751,7 +743,6 @@ void CON_ToggleOff(void) con_curlines = 0; CON_ClearHUD(); con_forcepic = 0; - con_clipviewtop = -1; // remove console clipping of view I_UpdateMouseGrab(); @@ -800,18 +791,6 @@ void CON_Ticker(void) CON_ChangeHeight(); } - // 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 - { - if (con_curlines > 0) - con_clipviewtop = con_curlines - viewwindowy - 1 - 10; - // NOTE: BIG HACK::SUBTRACT 10, SO THAT WATER DON'T COPY LINES OF THE CONSOLE - // WINDOW!!! (draw some more lines behind the bottom of the console) - if (con_clipviewtop < 0) - con_clipviewtop = -1; // maybe not necessary, provided it's < 0 - } - // check if console ready for prompt if (con_destlines >= minheight) consoleready = true; @@ -882,12 +861,6 @@ static void CON_InputDelSelection(void) Lock_state(); - if (!input_cur) - { - Unlock_state(); - return; - } - if (input_cur > input_sel) { start = input_sel; @@ -949,8 +922,6 @@ static void CON_InputDelChar(void) // boolean CON_Responder(event_t *ev) { - static UINT8 consdown = false; // console is treated differently due to rare usage - // sequential completions a la 4dos static char completioncmd[80 + sizeof("find ")] = "find "; static char *completion = &completioncmd[sizeof("find ")-1]; @@ -970,32 +941,28 @@ boolean CON_Responder(event_t *ev) // let go keyup events, don't eat them if (ev->type != ev_keydown && ev->type != ev_text && ev->type != ev_console) { - if (ev->key == gamecontrol[GC_CONSOLE][0] || ev->key == gamecontrol[GC_CONSOLE][1]) - consdown = false; return false; } key = ev->key; // check for console toggle key - if (ev->type != ev_console) + if (ev->type == ev_keydown) { if (modeattacking || metalrecording || marathonmode) return false; - if (ev->type == ev_keydown && ((key == gamecontrol[GC_CONSOLE][0] || key == gamecontrol[GC_CONSOLE][1]) && !shiftdown)) + if ((key == gamecontrol[GC_CONSOLE][0] || key == gamecontrol[GC_CONSOLE][1]) && !shiftdown) { - if (consdown) // ignore repeat - return true; + I_SetTextInputMode(con_destlines == 0); // inverse, since this is changed next tic. consoletoggle = true; - consdown = true; return true; } // check other keys only if console prompt is active if (!consoleready && key < NUMINPUTS) // metzgermeister: boundary check!! { - if (ev->type == ev_keydown && !menuactive && bindtable[key]) + if (!menuactive && bindtable[key]) { COM_BufAddText(bindtable[key]); COM_BufAddText("\n"); @@ -1007,14 +974,14 @@ boolean CON_Responder(event_t *ev) // escape key toggle off console if (key == KEY_ESCAPE) { + I_SetTextInputMode(false); consoletoggle = true; return true; } } - - if (ev->type == ev_text) + else if (ev->type == ev_text) { - if (!consoletoggle) + if (!consoletoggle && consoleready) CON_InputAddChar(key); return true; } @@ -1063,7 +1030,7 @@ boolean CON_Responder(event_t *ev) } else if (key == KEY_BACKSPACE) { - if (ctrldown) + if (ctrldown && input_cur != 0) { input_sel = M_JumpWordReverse(inputlines[inputline], input_cur); CON_InputDelSelection(); @@ -1121,7 +1088,9 @@ boolean CON_Responder(event_t *ev) if (key == 'x' || key == 'X') { - if (input_sel > input_cur) + if (input_sel == input_cur) // Don't replace the clipboard without a text selection + return true; + else if (input_sel > input_cur) I_ClipboardCopy(&inputlines[inputline][input_cur], input_sel-input_cur); else I_ClipboardCopy(&inputlines[inputline][input_sel], input_cur-input_sel); @@ -1131,7 +1100,9 @@ boolean CON_Responder(event_t *ev) } else if (key == 'c' || key == 'C') { - if (input_sel > input_cur) + if (input_sel == input_cur) // Don't replace the clipboard without a text selection + return true; + else if (input_sel > input_cur) I_ClipboardCopy(&inputlines[inputline][input_cur], input_sel-input_cur); else I_ClipboardCopy(&inputlines[inputline][input_sel], input_cur-input_sel); @@ -1339,6 +1310,8 @@ boolean CON_Responder(event_t *ev) if (input_sel != input_cur) CON_InputDelSelection(); + if (ev->type == ev_console) + CON_InputAddChar(key); return true; } @@ -1356,9 +1329,6 @@ static void CON_Linefeed(void) con_line = &con_buffer[(con_cy%con_totallines)*con_width]; memset(con_line, ' ', con_width); - - // make sure the view borders are refreshed if hud messages scroll - con_hudupdate = true; // see HU_Erase() } // Outputs text into the console text buffer @@ -1735,11 +1705,11 @@ static void CON_DrawHudlines(void) } if (c >= con_width) break; - if (*p < HU_FONTSTART) + if (*p < FONTSTART) ;//charwidth = 4 * con_scalefactor; else { - //charwidth = (hu_font['A'-HU_FONTSTART]->width) * con_scalefactor; + //charwidth = (hu_font.chars['A'-FONTSTART]->width) * con_scalefactor; V_DrawCharacter(x, y, (INT32)(*p) | charflags | cv_constextsize.value | V_NOSCALESTART, true); } } @@ -1747,9 +1717,6 @@ static void CON_DrawHudlines(void) //V_DrawCharacter(x, y, (p[c]&0xff) | cv_constextsize.value | V_NOSCALESTART, true); y += charheight; } - - // top screen lines that might need clearing when view is reduced - con_clearlines = y; // this is handled by HU_Erase(); } // Lactozilla: Draws the console's background picture. @@ -1761,12 +1728,12 @@ static void CON_DrawBackpic(void) // Get the lumpnum for CONSBACK, STARTUP (Only during game startup) or fallback into MISSING. if (con_startup) - piclump = W_CheckNumForName("STARTUP"); + piclump = W_CheckNumForPatchName("STARTUP"); else - piclump = W_CheckNumForName("CONSBACK"); + piclump = W_CheckNumForPatchName("CONSBACK"); if (piclump == LUMPERROR) - piclump = W_GetNumForName("MISSING"); + piclump = W_GetNumForPatchName("MISSING"); // Cache the patch. con_backpic = W_CachePatchNum(piclump, PU_PATCH); @@ -1815,10 +1782,6 @@ static void CON_DrawConsole(void) if (con_curlines <= 0) return; - //FIXME: refresh borders only when console bg is translucent - con_clearlines = con_curlines; // clear console draw from view borders - con_hudupdate = true; // always refresh while console is on - // draw console background if (cons_backpic.value || con_forcepic) CON_DrawBackpic(); diff --git a/src/console.h b/src/console.h index f22f8dcbc18e595b6fb57b942bca8c0eb3cf15e2..2af01f1a3af8bdd50901eabaa5b301107741e213 100644 --- a/src/console.h +++ b/src/console.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -34,14 +34,9 @@ extern boolean con_startup; // needs explicit screen refresh until we are in the main game loop extern boolean con_refresh; -// top clip value for view render: do not draw part of view hidden by console -extern INT32 con_clipviewtop; - // 0 means console if off, or moving out extern INT32 con_destlines; -extern INT32 con_clearlines; // lines of top of screen to refresh -extern boolean con_hudupdate; // hud messages have changed, need refresh extern UINT32 con_scalefactor; // console text scale factor extern consvar_t cons_backcolor; diff --git a/src/d_main.c b/src/d_main.c index 663817b779657809201e0c082bd52e24b5535b09..d75a4d5013d9a92e7abccad7211721b3fa1f00b5 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2025 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -408,13 +408,11 @@ static void D_Display(void) case GS_LEVEL: if (!gametic) break; - HU_Erase(); AM_Drawer(); break; case GS_INTERMISSION: Y_IntermissionDrawer(); - HU_Erase(); HU_Drawer(); break; @@ -429,13 +427,11 @@ static void D_Display(void) case GS_ENDING: F_EndingDrawer(); - HU_Erase(); HU_Drawer(); break; case GS_CUTSCENE: F_CutsceneDrawer(); - HU_Erase(); HU_Drawer(); break; @@ -445,7 +441,6 @@ static void D_Display(void) case GS_EVALUATION: F_GameEvaluationDrawer(); - HU_Erase(); HU_Drawer(); break; @@ -455,7 +450,6 @@ static void D_Display(void) case GS_CREDITS: F_CreditDrawer(); - HU_Erase(); HU_Drawer(); break; @@ -465,7 +459,6 @@ static void D_Display(void) { // I don't think HOM from nothing drawing is independent... F_WaitingPlayersDrawer(); - HU_Erase(); HU_Drawer(); } case GS_DEDICATEDSERVER: @@ -480,11 +473,21 @@ static void D_Display(void) { wipegamestate = gamestate; - // clean up border stuff - // see if the border needs to be initially drawn if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction && curbghide && (!hidetitlemap))) { // draw the view directly + if (cv_debug) + { + r_renderwalls = cv_renderwalls.value; + r_renderfloors = cv_renderfloors.value; + r_renderthings = cv_renderthings.value; + } + else + { + r_renderwalls = true; + r_renderfloors = true; + r_renderthings = true; + } if (!automapactive && !dedicated && cv_renderview.value) { @@ -506,23 +509,21 @@ static void D_Display(void) // render the second screen if (splitscreen && players[secondarydisplayplayer].mo) { - #ifdef HWRENDER - if (rendermode != render_soft) + viewwindowy = vid.height / 2; + +#ifdef HWRENDER + if (rendermode == render_opengl) HWR_RenderPlayerView(1, &players[secondarydisplayplayer]); else - #endif +#endif if (rendermode != render_none) { - viewwindowy = vid.height / 2; - M_Memcpy(ylookup, ylookup2, viewheight*sizeof (ylookup[0])); - topleft = screens[0] + viewwindowy*vid.width + viewwindowx; R_RenderPlayerView(&players[secondarydisplayplayer]); - - viewwindowy = 0; - M_Memcpy(ylookup, ylookup1, viewheight*sizeof (ylookup[0])); } + + viewwindowy = 0; } // Image postprocessing effect @@ -678,13 +679,13 @@ static void D_Display(void) s[sizeof s - 1] = '\0'; snprintf(s, sizeof s - 1, "get %d b/s", getbps); - V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-40, V_YELLOWMAP, s); + V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-40, V_YELLOWMAP, s); snprintf(s, sizeof s - 1, "send %d b/s", sendbps); - V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-30, V_YELLOWMAP, s); + V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-30, V_YELLOWMAP, s); snprintf(s, sizeof s - 1, "GameMiss %.2f%%", gamelostpercent); - V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-20, V_YELLOWMAP, s); + V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-20, V_YELLOWMAP, s); snprintf(s, sizeof s - 1, "SysMiss %.2f%%", lostpercent); - V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-ST_HEIGHT-10, V_YELLOWMAP, s); + V_DrawRightAlignedString(BASEVIDWIDTH, BASEVIDHEIGHT-10, V_YELLOWMAP, s); } if (cv_perfstats.value) @@ -757,9 +758,9 @@ void D_SRB2Loop(void) /* Smells like a hack... Don't fade Sonic's ass into the title screen. */ if (gamestate != GS_TITLESCREEN) { - gstartuplumpnum = W_CheckNumForName("STARTUP"); + gstartuplumpnum = W_CheckNumForPatchName("STARTUP"); if (gstartuplumpnum == LUMPERROR) - gstartuplumpnum = W_GetNumForName("MISSING"); + gstartuplumpnum = W_GetNumForPatchName("MISSING"); V_DrawScaledPatch(0, 0, 0, W_CachePatchNum(gstartuplumpnum, PU_PATCH)); } @@ -982,7 +983,7 @@ void D_StartTitle(void) emeralds = 0; memset(&luabanks, 0, sizeof(luabanks)); lastmaploaded = 0; - pickedchar = R_SkinAvailable(cv_defaultskin.string); + pickedchar = R_SkinAvailable(cv_skin.string); // In case someone exits out at the same time they start a time attack run, // reset modeattacking @@ -1023,7 +1024,7 @@ void D_StartTitle(void) #define REALLOC_FILE_LIST \ if (list->files == NULL) \ { \ - list->files = calloc(sizeof(list->files), 2); \ + list->files = calloc(2, sizeof(list->files)); \ list->numfiles = 1; \ } \ else \ @@ -1178,8 +1179,8 @@ static void IdentifyVersion(void) // Add the maps D_AddFile(&startupwadfiles, va(pandf,srb2waddir, "zones.pk3")); - // Add the players - D_AddFile(&startupwadfiles, va(pandf,srb2waddir, "player.dta")); + // Add the characters + D_AddFile(&startupwadfiles, va(pandf,srb2waddir, "characters.pk3")); #ifdef USE_PATCH_DTA // Add our crappy patches to fix our bugs @@ -1198,7 +1199,7 @@ static void IdentifyVersion(void) I_Error("File "str" has been modified with non-music/sound lumps"); \ } - MUSICTEST("music.dta") + MUSICTEST("music.pk3") //MUSICTEST("patch_music.pk3") } #endif @@ -1249,7 +1250,7 @@ void D_SRB2Main(void) // Print GPL notice for our console users (Linux) CONS_Printf( "\n\nSonic Robo Blast 2\n" - "Copyright (C) 1998-2023 by Sonic Team Junior\n\n" + "Copyright (C) 1998-2025 by Sonic Team Junior\n\n" "This program comes with ABSOLUTELY NO WARRANTY.\n\n" "This is free software, and you are welcome to redistribute it\n" "and/or modify it under the terms of the GNU General Public License\n" @@ -1295,7 +1296,7 @@ void D_SRB2Main(void) #endif // for dedicated server -#if !defined (_WINDOWS) //already check in win_main.c +#if !defined (_WINDOWS) && !defined (DEDICATED) //already check in win_main.c dedicated = M_CheckParm("-dedicated") != 0; #endif @@ -1430,7 +1431,7 @@ void D_SRB2Main(void) // Make backups of some SOCcable tables. P_BackupTables(); - mainwads = 3; // doesn't include music.dta + mainwads = 3; // doesn't include music.pk3 #ifdef USE_PATCH_DTA mainwads++; #endif @@ -1445,11 +1446,11 @@ void D_SRB2Main(void) // Check MD5s of autoloaded files W_VerifyFileMD5(0, ASSET_HASH_SRB2_PK3); // srb2.pk3 W_VerifyFileMD5(1, ASSET_HASH_ZONES_PK3); // zones.pk3 - W_VerifyFileMD5(2, ASSET_HASH_PLAYER_DTA); // player.dta + W_VerifyFileMD5(2, ASSET_HASH_CHARACTERS_PK3); // characters.pk3 #ifdef USE_PATCH_DTA W_VerifyFileMD5(3, ASSET_HASH_PATCH_PK3); // patch.pk3 #endif - // don't check music.dta because people like to modify it, and it doesn't matter if they do + // don't check music.pk3 because people like to modify it, and it doesn't matter if they do // ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for. #endif //ifndef DEVELOP @@ -1512,9 +1513,7 @@ void D_SRB2Main(void) G_LoadGameData(clientGamedata); M_CopyGameData(serverGamedata, clientGamedata); -#if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL) VID_PrepareModeList(); // Regenerate Modelist according to cv_fullscreen -#endif // set user default mode or mode set at cmdline SCR_CheckDefaultMode(); @@ -1536,7 +1535,7 @@ void D_SRB2Main(void) I_Error("Cannot find a map remotely named '%s'\n", word); else { - if (!M_CheckParm("-server")) + if (!(M_CheckParm("-server") || dedicated)) G_SetUsedCheats(true); autostart = true; } @@ -1601,7 +1600,7 @@ void D_SRB2Main(void) { if (!M_IsNextParm()) I_Error("usage: -room <room_id>\nCheck the Master Server's webpage for room ID numbers.\n"); - ms_RoomId = atoi(M_GetNextParm()); + CV_SetValue(&cv_masterserver_room_id, atoi(M_GetNextParm())); #ifdef UPDATE_ALERT GetMODVersion_Console(); @@ -1843,17 +1842,21 @@ static boolean check_top_dir(const char **path, const char *top) return true; } -static int cmp_strlen_desc(const void *a, const void *b) +static int cmp_strlen_desc(const void *A, const void *B) { - return ((int)strlen(*(const char*const*)b) - (int)strlen(*(const char*const*)a)); + const char *pA = A; + const char *pB = B; + size_t As = strlen(pA); + size_t Bs = strlen(pB); + return ((int)Bs - (int)As); } boolean D_IsPathAllowed(const char *path) { - const char *paths[] = { + char *paths[] = { srb2home, srb2path, - cv_addons_folder.string + cv_addons_folder.zstring }; const size_t n_paths = sizeof paths / sizeof *paths; diff --git a/src/d_player.h b/src/d_player.h index 26f17a1a09e114a1d73887acd19338c1245b14a0..cdb547d3b863147798fe28cd5100ed54be0f23c0 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -45,14 +45,15 @@ typedef enum SF_MARIODAMAGE = SF_NOJUMPDAMAGE|SF_STOMPDAMAGE, // The Mario method of being able to damage enemies, etc. SF_MACHINE = 1<<10, // Beep boop. Are you a robot? SF_DASHMODE = 1<<11, // Sonic Advance 2 style top speed increase? - SF_FASTEDGE = 1<<12, // Faster edge teeter? - SF_MULTIABILITY = 1<<13, // Revenge of Final Demo. - SF_NONIGHTSROTATION = 1<<14, // Disable sprite rotation for NiGHTS - SF_NONIGHTSSUPER = 1<<15, // Disable super colors for NiGHTS (if you have SF_SUPER) - SF_NOSUPERSPRITES = 1<<16, // Don't use super sprites while super - SF_NOSUPERJUMPBOOST = 1<<17, // Disable the jump boost given while super (i.e. Knuckles) - SF_CANBUSTWALLS = 1<<18, // Can naturally bust walls on contact? (i.e. Knuckles) - SF_NOSHIELDABILITY = 1<<19, // Disable shield abilities + SF_FASTWAIT = 1<<12, // Faster wait animation? + SF_FASTEDGE = 1<<13, // Faster edge teeter? + SF_MULTIABILITY = 1<<14, // Revenge of Final Demo. + SF_NONIGHTSROTATION = 1<<15, // Disable sprite rotation for NiGHTS + SF_NONIGHTSSUPER = 1<<16, // Disable super colors for NiGHTS (if you have SF_SUPER) + SF_NOSUPERSPRITES = 1<<17, // Don't use super sprites while super + SF_NOSUPERJUMPBOOST = 1<<18, // Disable the jump boost given while super (i.e. Knuckles) + SF_CANBUSTWALLS = 1<<19, // Can naturally bust walls on contact? (i.e. Knuckles) + SF_NOSHIELDABILITY = 1<<20, // Disable shield abilities // free up to and including 1<<31 } skinflags_t; @@ -158,10 +159,6 @@ typedef enum PF_FORCESTRAFE = 1<<28, // Turning inputs are translated into strafing inputs PF_CANCARRY = 1<<29, // Can carry another player? PF_FINISHED = 1<<30, // The player finished the level. NOT the same as exiting - - // True if shield button down last tic - // This may be the final flag, but 2.3 could free up the others - PF_SHIELDDOWN = 1<<31, // up to 1<<31 is free } pflags_t; @@ -373,6 +370,16 @@ typedef enum AI_SPINFOLLOW } aistatetype_t; +// NiGHTS text +typedef enum +{ + NTV_NONE = 0, + NTV_GETSPHERES, + NTV_GETMORESPHERES, + NTV_BONUSTIMESTART, + NTV_BONUSTIMEEND, +} nightstextvar_t; + // ======================================================================== // PLAYER STRUCTURE @@ -572,7 +579,8 @@ typedef struct player_s // Statistical purposes. tic_t marebegunat; // Leveltime when mare begun tic_t startedtime; // Time which you started this mare with. - tic_t finishedtime; // Time it took you to finish the mare (used for display) + tic_t finishedtime; // The time it took to destroy the capsule on this mare (used for bonus time display) + tic_t lastmaretime; // The time it took to complete the last mare (used for rank display) tic_t lapbegunat; // Leveltime when lap begun tic_t lapstartedtime; // Time which you started this lap with. INT16 finishedspheres; // The spheres you had left upon finishing the mare @@ -587,7 +595,7 @@ typedef struct player_s UINT8 totalmarebonuslap; // total mare bonus lap INT32 maxlink; // maximum link obtained UINT8 texttimer; // nights_texttime should not be local - UINT8 textvar; // which line of NiGHTS text to show -- let's not use cheap hacks + UINT8 textvar; // which line of NiGHTS text to show -- see nightstextvar_t INT16 lastsidehit, lastlinehit; @@ -603,6 +611,7 @@ typedef struct player_s boolean spectator; boolean outofcoop; boolean removing; + boolean muted; UINT8 bot; struct player_s *botleader; UINT16 lastbuttons; diff --git a/src/d_think.h b/src/d_think.h index 58912458783a2f3b2187e50ebaf00a667a0e0a78..76c1bb5b8af11a5557bab32705897445e699ca5b 100644 --- a/src/d_think.h +++ b/src/d_think.h @@ -51,6 +51,8 @@ typedef struct thinker_s // killough 11/98: count of how many other objects reference // this one using pointers. Used for garbage collection. INT32 references; + + boolean removing; boolean cachable; #ifdef PARANOIA diff --git a/src/d_ticcmd.h b/src/d_ticcmd.h index 43eb0f00b8df58da69c2dc7123d274d69070c104..2481ed738b23769a546fef840500d10ba7b024f5 100644 --- a/src/d_ticcmd.h +++ b/src/d_ticcmd.h @@ -26,23 +26,20 @@ // Button/action code definitions. typedef enum { - // First 3 bits are weapon change info, DO NOT USE! - BT_WEAPONMASK = 0x07, //our first three bits. - - BT_SHIELD = 1<<3, // shield or super action + // First 4 bits are weapon change info, DO NOT USE! + BT_WEAPONMASK = 0x0F, //our first four bits. - BT_WEAPONNEXT = 1<<4, // select next weapon - BT_WEAPONPREV = 1<<5, // select previous weapon + BT_WEAPONNEXT = 1<<4, + BT_WEAPONPREV = 1<<5, + + BT_ATTACK = 1<<6, // shoot rings + BT_SPIN = 1<<7, + BT_CAMLEFT = 1<<8, // turn camera left + BT_CAMRIGHT = 1<<9, // turn camera right + BT_TOSSFLAG = 1<<10, + BT_JUMP = 1<<11, + BT_FIRENORMAL = 1<<12, // Fire a normal ring no matter what - BT_ATTACK = 1<<6, // shoot rings - BT_SPIN = 1<<7, // spin action - BT_CAMLEFT = 1<<8, // turn camera left - BT_CAMRIGHT = 1<<9, // turn camera right - BT_TOSSFLAG = 1<<10, // toss flag or emeralds - BT_JUMP = 1<<11, // jump action - BT_FIRENORMAL = 1<<12, // fire a normal ring no matter what - - // custom lua buttons BT_CUSTOM1 = 1<<13, BT_CUSTOM2 = 1<<14, BT_CUSTOM3 = 1<<15, diff --git a/src/dedicated/Sourcefile b/src/dedicated/Sourcefile new file mode 100644 index 0000000000000000000000000000000000000000..2f5dd1a597f38268f583a9bfa1b6da84b1bff69d --- /dev/null +++ b/src/dedicated/Sourcefile @@ -0,0 +1,5 @@ +i_net.c +i_system.c +i_main.c +i_video.c +i_sound.c diff --git a/src/dedicated/i_main.c b/src/dedicated/i_main.c new file mode 100644 index 0000000000000000000000000000000000000000..c79aea96db33d6d7a7fa849e739246f8385a13db --- /dev/null +++ b/src/dedicated/i_main.c @@ -0,0 +1,189 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1993-1996 by id Software, Inc. +// 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 d_main.c +/// \brief Main program, simply calls D_SRB2Main and D_SRB2Loop, the high level loop. + +#include "../doomdef.h" +#include "../m_argv.h" +#include "../d_main.h" +#include "../m_misc.h"/* path shit */ +#include "../i_system.h" +#include "../netcode/d_clisrv.h" + +#if defined (__GNUC__) || defined (__unix__) +#include <unistd.h> +#endif + +#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) +#include <errno.h> +#endif + +#include "time.h" // For log timestamps + +#ifdef LOGMESSAGES +FILE *logstream = NULL; +char logfilename[1024]; +#endif + +#ifndef DOXYGEN +#ifndef O_TEXT +#define O_TEXT 0 +#endif + +#ifndef O_SEQUENTIAL +#define O_SEQUENTIAL 0 +#endif +#endif + +#if defined (_WIN32) +#include "../win32/win_dbg.h" +typedef BOOL (WINAPI *p_IsDebuggerPresent)(VOID); +#endif + +#ifdef LOGMESSAGES +static void InitLogging(void) +{ + const char *logdir = NULL; + time_t my_time; + struct tm * timeinfo; + const char *format; + const char *reldir; + int left; + boolean fileabs; +#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) + const char *link; +#endif + + logdir = D_Home(); + + my_time = time(NULL); + timeinfo = localtime(&my_time); + + if (M_CheckParm("-logfile") && M_IsNextParm()) + { + format = M_GetNextParm(); + fileabs = M_IsPathAbsolute(format); + } + else + { + format = "log-%Y-%m-%d_%H-%M-%S.txt"; + fileabs = false; + } + + if (fileabs) + { + strftime(logfilename, sizeof logfilename, format, timeinfo); + } + else + { + if (M_CheckParm("-logdir") && M_IsNextParm()) + reldir = M_GetNextParm(); + else + reldir = "logs"; + + if (M_IsPathAbsolute(reldir)) + { + left = snprintf(logfilename, sizeof logfilename, + "%s"PATHSEP, reldir); + } + else +#ifdef DEFAULTDIR + if (logdir) + { + left = snprintf(logfilename, sizeof logfilename, + "%s"PATHSEP DEFAULTDIR PATHSEP"%s"PATHSEP, logdir, reldir); + } + else +#endif/*DEFAULTDIR*/ + { + left = snprintf(logfilename, sizeof logfilename, + "."PATHSEP"%s"PATHSEP, reldir); + } + + strftime(&logfilename[left], sizeof logfilename - left, + format, timeinfo); + } + + M_MkdirEachUntil(logfilename, + M_PathParts(logdir) - 1, + M_PathParts(logfilename) - 1, 0755); + +#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) + logstream = fopen(logfilename, "w"); +#ifdef DEFAULTDIR + if (logdir) + link = va("%s/"DEFAULTDIR"/latest-log.txt", logdir); + else +#endif/*DEFAULTDIR*/ + link = "latest-log.txt"; + unlink(link); + if (symlink(logfilename, link) == -1) + { + I_OutputMsg("Error symlinking latest-log.txt: %s\n", strerror(errno)); + } +#else/*defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)*/ + logstream = fopen("latest-log.txt", "wt+"); +#endif/*defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)*/ +} +#endif + + +/** \brief The main function + + \param argc number of arg + \param *argv string table + + \return int +*/ +#if defined (__GNUC__) && (__GNUC__ >= 4) +#pragma GCC diagnostic ignored "-Wmissing-noreturn" +#endif + +int main(int argc, char **argv) +{ + myargc = argc; + myargv = argv; /// \todo pull out path to exe from this string + + dedicated = true; + +#ifdef LOGMESSAGES + if (!M_CheckParm("-nolog")) + InitLogging(); +#endif/*LOGMESSAGES*/ + + //I_OutputMsg("I_StartupSystem() ...\n"); + I_StartupSystem(); +#if defined (_WIN32) + LoadLibraryA("exchndl.dll"); +#ifndef __MINGW32__ + prevExceptionFilter = SetUnhandledExceptionFilter(RecordExceptionInfo); +#endif +#endif + + // startup SRB2 + CONS_Printf("Setting up SRB2...\n"); + D_SRB2Main(); +#ifdef LOGMESSAGES + if (!M_CheckParm("-nolog")) + CONS_Printf("Logfile: %s\n", logfilename); +#endif + CONS_Printf("Entering main game loop...\n"); + // never return + D_SRB2Loop(); + +#ifdef BUGTRAP + // This is safe even if BT didn't start. + ShutdownBugTrap(); +#endif + + // return to OS + return 0; +} diff --git a/src/dedicated/i_net.c b/src/dedicated/i_net.c new file mode 100644 index 0000000000000000000000000000000000000000..38049796e22e1980a84bb1fe3166e62827cf03ec --- /dev/null +++ b/src/dedicated/i_net.c @@ -0,0 +1,7 @@ +#include "../netcode/i_net.h" + +boolean I_InitNetwork(void) +{ + // NOTE: this is no longer used. + return false; +} diff --git a/src/dedicated/i_sound.c b/src/dedicated/i_sound.c new file mode 100644 index 0000000000000000000000000000000000000000..36e3d1ebbb28d94dfd9db178950bc906ea6e01e2 --- /dev/null +++ b/src/dedicated/i_sound.c @@ -0,0 +1,214 @@ +#include "../i_sound.h" + +UINT8 sound_started = 0; + +void *I_GetSfx(sfxinfo_t *sfx) +{ + (void)sfx; + return NULL; +} + +void I_FreeSfx(sfxinfo_t *sfx) +{ + (void)sfx; +} + +void I_StartupSound(void){} + +void I_ShutdownSound(void){} + +void I_UpdateSound(void){}; + +// +// SFX I/O +// + +INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel) +{ + (void)id; + (void)vol; + (void)sep; + (void)pitch; + (void)priority; + (void)channel; + return -1; +} + +void I_StopSound(INT32 handle) +{ + (void)handle; +} + +boolean I_SoundIsPlaying(INT32 handle) +{ + (void)handle; + return false; +} + +void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch) +{ + (void)handle; + (void)vol; + (void)sep; + (void)pitch; +} + +void I_SetSfxVolume(UINT8 volume) +{ + (void)volume; +} + +/// ------------------------ +// MUSIC SYSTEM +/// ------------------------ + +void I_InitMusic(void){} + +void I_ShutdownMusic(void){} + +/// ------------------------ +// MUSIC PROPERTIES +/// ------------------------ + +musictype_t I_SongType(void) +{ + return MU_NONE; +} + +boolean I_SongPlaying(void) +{ + return false; +} + +boolean I_SongPaused(void) +{ + return false; +} + +/// ------------------------ +// MUSIC EFFECTS +/// ------------------------ + +boolean I_SetSongSpeed(float speed) +{ + (void)speed; + return false; +} + +/// ------------------------ +// MUSIC SEEKING +/// ------------------------ + +UINT32 I_GetSongLength(void) +{ + return 0; +} + +boolean I_SetSongLoopPoint(UINT32 looppoint) +{ + (void)looppoint; + return false; +} + +UINT32 I_GetSongLoopPoint(void) +{ + return 0; +} + +boolean I_SetSongPosition(UINT32 position) +{ + (void)position; + return false; +} + +UINT32 I_GetSongPosition(void) +{ + return 0; +} + +/// ------------------------ +// MUSIC PLAYBACK +/// ------------------------ + +boolean I_LoadSong(char *data, size_t len) +{ + (void)data; + (void)len; + return -1; +} + +void I_UnloadSong(void) +{ +} + +boolean I_PlaySong(boolean looping) +{ + (void)looping; + return false; +} + +void I_StopSong(void) +{ +} + +void I_PauseSong(void) +{ +} + +void I_ResumeSong(void) +{ +} + +void I_SetMusicVolume(UINT8 volume) +{ + (void)volume; +} + +boolean I_SetSongTrack(INT32 track) +{ + (void)track; + return false; +} + +/// ------------------------ +// MUSIC FADING +/// ------------------------ + +void I_SetInternalMusicVolume(UINT8 volume) +{ + (void)volume; +} + +void I_StopFadingSong(void) +{ +} + +boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void)) +{ + (void)target_volume; + (void)source_volume; + (void)ms; + (void)callback; + return false; +} + +boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)) +{ + (void)target_volume; + (void)ms; + (void)callback; + return false; +} + +boolean I_FadeOutStopSong(UINT32 ms) +{ + (void)ms; + return false; +} + +boolean I_FadeInPlaySong(UINT32 ms, boolean looping) +{ + (void)ms; + (void)looping; + return false; +} diff --git a/src/dedicated/i_system.c b/src/dedicated/i_system.c new file mode 100644 index 0000000000000000000000000000000000000000..643e24f5afb677f450dab073097388661c35c98a --- /dev/null +++ b/src/dedicated/i_system.c @@ -0,0 +1,1575 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// +// Copyright (C) 1993-1996 by id Software, Inc. +// Portions Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 2014-2025 by Sonic Team Junior. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Changes by Graue <graue@oceanbase.org> are in the public domain. +// +//----------------------------------------------------------------------------- +/// \file +/// \brief SRB2 system stuff for dedicated servers + +#include <signal.h> + +#ifdef _WIN32 +#define RPC_NO_WINDOWS_H +#include <windows.h> +#include "../doomtype.h" +typedef BOOL (WINAPI *p_GetDiskFreeSpaceExA)(LPCSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER); +typedef BOOL (WINAPI *p_IsProcessorFeaturePresent) (DWORD); +typedef DWORD (WINAPI *p_timeGetTime) (void); +typedef UINT (WINAPI *p_timeEndPeriod) (UINT); +typedef HANDLE (WINAPI *p_OpenFileMappingA) (DWORD, BOOL, LPCSTR); +typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); + +// This is for RtlGenRandom. +#define SystemFunction036 NTAPI SystemFunction036 +#include <ntsecapi.h> +#undef SystemFunction036 + +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifdef __GNUC__ +#include <unistd.h> +#elif defined (_MSC_VER) +#include <direct.h> +#endif +#if defined (__unix__) || defined (UNIXCOMMON) +#include <fcntl.h> +#endif + +#include <stdio.h> +#ifdef _WIN32 +#include <conio.h> +#endif + +#ifdef _MSC_VER +#pragma warning(disable : 4214 4244) +#endif + +#ifdef _MSC_VER +#pragma warning(default : 4214 4244) +#endif + +#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) +#if defined (__linux__) || defined (__HAIKU__) +#include <sys/statvfs.h> +#else +#include <sys/statvfs.h> +#include <sys/param.h> +#include <sys/mount.h> +/*For meminfo*/ +#include <sys/types.h> +#ifdef FREEBSD +#include <kvm.h> +#endif +#include <nlist.h> +#include <sys/sysctl.h> +#endif +#endif + +#if defined (__linux__) || defined (UNIXCOMMON) +#ifndef NOTERMIOS +#include <termios.h> +#include <sys/ioctl.h> // ioctl +#define HAVE_TERMIOS +#endif +#endif + +#if defined(UNIXCOMMON) +#include <poll.h> +#endif + +#if defined (__unix__) || (defined (UNIXCOMMON) && !defined (__APPLE__)) +#include <errno.h> +#include <sys/wait.h> +#ifndef __HAIKU__ // haiku's crash dialog is just objectively better +#define NEWSIGNALHANDLER +#endif +#endif + +#ifndef NOMUMBLE +#ifdef __linux__ // need -lrt +#include <sys/mman.h> +#ifdef MAP_FAILED +#define HAVE_SHM +#endif +#include <wchar.h> +#endif + +#ifdef _WIN32 +#define HAVE_MUMBLE +#define WINMUMBLE +#elif defined (HAVE_SHM) +#define HAVE_MUMBLE +#endif +#endif // NOMUMBLE + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +#ifdef __APPLE__ +#include "macosx/mac_resources.h" +#endif + +#ifndef errno +#include <errno.h> +#endif + +#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) +#ifndef NOEXECINFO +#include <execinfo.h> +#endif +#include <time.h> +#define UNIXBACKTRACE +#endif + +// Locations to directly check for srb2.pk3 in +const char *wadDefaultPaths[] = { +#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) + "/usr/local/share/games/SRB2", + "/usr/local/games/SRB2", + "/usr/share/games/SRB2", + "/usr/games/SRB2", +#elif defined (_WIN32) + "c:\\games\\srb2", + "\\games\\srb2", +#endif + NULL +}; + +// Folders to recurse through looking for srb2.pk3 +const char *wadSearchPaths[] = { +#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) + "/usr/local/games", + "/usr/games", + "/usr/local", +#elif defined (_WIN32) + "c:\\games", + "\\games", +#endif + NULL +}; + +/** \brief WAD file to look for +*/ +#define WADKEYWORD1 "srb2.pk3" +/** \brief holds wad path +*/ +static char returnWadPath[256]; + +//Alam_GBC: SDL + +#include "../doomdef.h" +#include "../m_misc.h" +#include "../i_time.h" +#include "../i_video.h" +#include "../i_sound.h" +#include "../i_system.h" +#include "../i_threads.h" +#include "../screen.h" //vid.WndParent +#include "../netcode/d_net.h" +#include "../netcode/commands.h" +#include "../g_game.h" +#include "../filesrch.h" + +#include "../i_joy.h" + +#include "../m_argv.h" + +#include "../r_main.h" // Frame interpolation/uncapped +#include "../r_fps.h" + +#ifdef MAC_ALERT +#include "macosx/mac_alert.h" +#endif + +#include "../d_main.h" + +#if !defined(NOMUMBLE) && defined(HAVE_MUMBLE) +// Mumble context string +#include "../netcode/d_clisrv.h" +#include "../byteptr.h" +#endif + +#define MAX_EXIT_FUNCS 32 + +// A little more than the minimum sleep duration on Windows. +// May be incorrect for other platforms, but we don't currently have a way to +// query the scheduler granularity. SDL will do what's needed to make this as +// low as possible though. +#define MIN_SLEEP_DURATION_MS 2.1 + +UINT8 graphics_started = 0; + +UINT8 keyboard_started = 0; + +static boolean consolevent = false; +#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) +static boolean framebuffer = false; +#endif + +static size_t num_exit_funcs; +static void (*exit_funcs[MAX_EXIT_FUNCS])(void); + +static boolean is_quitting = false; + +#ifdef __linux__ +#define MEMINFO_FILE "/proc/meminfo" +#define MEMTOTAL "MemTotal:" +#define MEMAVAILABLE "MemAvailable:" +#define MEMFREE "MemFree:" +#define CACHED "Cached:" +#define BUFFERS "Buffers:" +#define SHMEM "Shmem:" + +/* Parse the contents of /proc/meminfo (in buf), return value of "name" + * (example: MemTotal) */ +static long get_entry(const char* name, const char* buf) +{ + long val; + char* hit = strstr(buf, name); + if (hit == NULL) { + return -1; + } + + errno = 0; + val = strtol(hit + strlen(name), NULL, 10); + if (errno != 0) { + CONS_Alert(CONS_ERROR, M_GetText("get_entry: strtol() failed: %s\n"), strerror(errno)); + return -1; + } + return val; +} +#endif + +size_t I_GetFreeMem(size_t *total) +{ +#ifdef FREEBSD + u_int v_free_count, v_page_size, v_page_count; + size_t size = sizeof(v_free_count); + sysctlbyname("vm.stats.vm.v_free_count", &v_free_count, &size, NULL, 0); + size = sizeof(v_page_size); + sysctlbyname("vm.stats.vm.v_page_size", &v_page_size, &size, NULL, 0); + size = sizeof(v_page_count); + sysctlbyname("vm.stats.vm.v_page_count", &v_page_count, &size, NULL, 0); + + if (total) + *total = v_page_count * v_page_size; + return v_free_count * v_page_size; +#elif defined (SOLARIS) + /* Just guess */ + if (total) + *total = 32 << 20; + return 32 << 20; +#elif defined (_WIN32) + MEMORYSTATUS info; + + info.dwLength = sizeof (MEMORYSTATUS); + GlobalMemoryStatus( &info ); + if (total) + *total = (size_t)info.dwTotalPhys; + return (size_t)info.dwAvailPhys; +#elif defined (__linux__) + /* Linux */ + char buf[1024]; + char *memTag; + size_t freeKBytes; + size_t totalKBytes; + INT32 n; + INT32 meminfo_fd = -1; + long Cached; + long MemFree; + long Buffers; + long Shmem; + long MemAvailable = -1; + + meminfo_fd = open(MEMINFO_FILE, O_RDONLY); + n = read(meminfo_fd, buf, 1023); + close(meminfo_fd); + + if (n < 0) + { + // Error + if (total) + *total = 0L; + return 0; + } + + buf[n] = '\0'; + if ((memTag = strstr(buf, MEMTOTAL)) == NULL) + { + // Error + if (total) + *total = 0L; + return 0; + } + + memTag += sizeof (MEMTOTAL); + totalKBytes = (size_t)atoi(memTag); + + if ((memTag = strstr(buf, MEMAVAILABLE)) == NULL) + { + Cached = get_entry(CACHED, buf); + MemFree = get_entry(MEMFREE, buf); + Buffers = get_entry(BUFFERS, buf); + Shmem = get_entry(SHMEM, buf); + MemAvailable = Cached + MemFree + Buffers - Shmem; + + if (MemAvailable == -1) + { + // Error + if (total) + *total = 0L; + return 0; + } + freeKBytes = MemAvailable; + } + else + { + memTag += sizeof (MEMAVAILABLE); + freeKBytes = atoi(memTag); + } + + if (total) + *total = totalKBytes << 10; + return freeKBytes << 10; +#else + // Guess 48 MB. + if (total) + *total = 48<<20; + return 48<<20; +#endif +} + +void I_Sleep(UINT32 ms) +{ +#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) + struct timespec ts = { + .tv_sec = ms / 1000, + .tv_nsec = ms % 1000 * 1000000, + }; + int status; + do status = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts); + while (status == EINTR); +#elif defined (_WIN32) + Sleep(ms); +#else + (void)ms; +#warning No sleep function for this system! +#endif +} + +void I_SleepDuration(precise_t duration) +{ +#if defined(__linux__) || defined(__FreeBSD__) || defined(__HAIKU__) + UINT64 precision = I_GetPrecisePrecision(); + precise_t dest = I_GetPreciseTime() + duration; + precise_t slack = (precision / 5000); // 0.2 ms slack + if (duration > slack) + { + duration -= slack; + struct timespec ts = { + .tv_sec = duration / precision, + .tv_nsec = duration * 1000000000 / precision % 1000000000, + }; + int status; + do status = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts); + while (status == EINTR); + } + + // busy-wait the rest + while (((INT64)dest - (INT64)I_GetPreciseTime()) > 0); +#else + UINT64 precision = I_GetPrecisePrecision(); + INT32 sleepvalue = cv_sleep.value; + UINT64 delaygranularity; + precise_t cur; + precise_t dest; + + { + double gran = round(((double)(precision / 1000) * sleepvalue * MIN_SLEEP_DURATION_MS)); + delaygranularity = (UINT64)gran; + } + + cur = I_GetPreciseTime(); + dest = cur + duration; + + // the reason this is not dest > cur is because the precise counter may wrap + // two's complement arithmetic is our friend here, though! + // e.g. cur 0xFFFFFFFFFFFFFFFE = -2, dest 0x0000000000000001 = 1 + // 0x0000000000000001 - 0xFFFFFFFFFFFFFFFE = 3 + while ((INT64)(dest - cur) > 0) + { + // If our cv_sleep value exceeds the remaining sleep duration, use the + // hard sleep function. + if (sleepvalue > 0 && (dest - cur) > delaygranularity) + { + I_Sleep(sleepvalue); + } + + // Otherwise, this is a spinloop. + + cur = I_GetPreciseTime(); + } +#endif +} + +precise_t I_GetPreciseTime(void) +{ +#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (precise_t)ts.tv_sec * 1000000000 + ts.tv_nsec; +#elif defined (_WIN32) + LARGE_INTEGER counter; + QueryPerformanceCounter(&counter); + return (precise_t)counter.QuadPart; +#else + return 0; +#endif +} + +UINT64 I_GetPrecisePrecision(void) +{ +#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) + return 1000000000; +#elif defined (_WIN32) + LARGE_INTEGER frequency; + QueryPerformanceFrequency(&frequency); + return (UINT64)frequency.QuadPart; +#else + return 1000000; +#endif +} + +void I_GetEvent(void){} + +static ticcmd_t emptycmd; + +ticcmd_t *I_BaseTiccmd(void) +{ + return &emptycmd; +} + +ticcmd_t *I_BaseTiccmd2(void) +{ + // dedicated servers don't do 2 player. + return NULL; +} + +FUNCNORETURN static void I_QuitStatus(int status) +{ + if (is_quitting) + abort(); + + is_quitting = true; + M_SaveConfig(NULL); //save game config, cvars.. + D_SaveBan(); // save the ban list + G_SaveGameData(clientGamedata); // Tails 12-08-2002 + //added:16-02-98: when recording a demo, should exit using 'q' key, + // but sometimes we forget and use 'F10'.. so save here too. + + // FIXME: can a dedicated server even record demos? + if (demorecording) + G_CheckDemoStatus(); + if (metalrecording) + G_StopMetalRecording(false); + + D_QuitNetGame(); + CL_AbortDownloadResume(); + M_FreePlayerSetupColors(); + I_ShutdownSystem(); + W_Shutdown(); + exit(status); +} + +void I_Quit(void) +{ + I_QuitStatus(0); +} + +void I_Error(const char *error, ...) +{ + va_list argptr; + char *buffer; + size_t buflen; + + // Display error message in the console before we start shutting it down + va_start(argptr, error); + buflen = vsnprintf(NULL, 0, error, argptr); + va_end(argptr); + + // do it proper with an actual malloc + // (stop abusing the stackbuffer ffs ヽ(。_°)ノ) + buffer = malloc(buflen+1); + va_start(argptr, error); + vsprintf(buffer, error, argptr); + va_end(argptr); + I_OutputMsg("\nI_Error(): %s\n", buffer); + free(buffer); + // --- + + I_QuitStatus(-1); +} + +void I_Tactile(FFType Type, const JoyFF_t *Effect) +{ + (void)Type; + (void)Effect; +} + +void I_Tactile2(FFType Type, const JoyFF_t *Effect) +{ + (void)Type; + (void)Effect; +} + +void I_JoyScale(void){} + +void I_JoyScale2(void){} + +void I_InitJoystick(void){} + +void I_InitJoystick2(void){} + +INT32 I_NumJoys(void) +{ + return 0; +} + +const char *I_GetJoyName(INT32 joyindex) +{ + (void)joyindex; + return NULL; +} + +#ifndef NOMUMBLE +#ifdef HAVE_MUMBLE +// Best Mumble positional audio settings: +// Minimum distance 3.0 m +// Bloom 175% +// Maximum distance 80.0 m +// Minimum volume 50% +#define DEG2RAD (0.017453292519943295769236907684883l) // TAU/360 or PI/180 +#define MUMBLEUNIT (64.0f) // FRACUNITS in a Meter + +static struct { + UINT32 uiVersion; +#ifdef WINMUMBLE + DWORD uiTick; +#else + UINT32 uiTick; +#endif + float fAvatarPosition[3]; + float fAvatarFront[3]; + float fAvatarTop[3]; // defaults to Y-is-up (only used for leaning) + wchar_t name[256]; // game name + float fCameraPosition[3]; + float fCameraFront[3]; + float fCameraTop[3]; // defaults to Y-is-up (only used for leaning) + wchar_t identity[256]; // player id + UINT32 context_len; + unsigned char context[256]; // server/team + wchar_t description[2048]; // game description +} *mumble = NULL; +#endif // HAVE_MUMBLE + +static void I_SetupMumble(void) +{ +#ifdef WINMUMBLE + HANDLE hMap = OpenFileMappingW(FILE_MAP_ALL_ACCESS, FALSE, L"MumbleLink"); + if (!hMap) + return; + + mumble = MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(*mumble)); + if (!mumble) + CloseHandle(hMap); +#elif defined (HAVE_SHM) + int shmfd; + char memname[256]; + + snprintf(memname, 256, "/MumbleLink.%d", getuid()); + shmfd = shm_open(memname, O_RDWR, S_IRUSR | S_IWUSR); + + if(shmfd < 0) + return; + + mumble = mmap(NULL, sizeof(*mumble), PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0); + if (mumble == MAP_FAILED) + mumble = NULL; +#endif +} +#undef WINMUMBLE +#endif // NOMUMBLE + +void I_UpdateMumble(const mobj_t *mobj, const listener_t listener) +{ +#ifdef HAVE_MUMBLE + // DO NOT BE DECEIVED BY THIS OLD CODE! + // despite being untouched for years, it still works as intended after testing. + // (i strongly recommend a game of hide & seek with the mumble integration; hilarities are ensured) + double angle; + fixed_t anglef; + + if (!mumble) + return; + + if(mumble->uiVersion != 2) { + wcsncpy(mumble->name, L"SRB2 "VERSIONSTRINGW, 256); + wcsncpy(mumble->description, L"Sonic Robo Blast 2 with integrated Mumble Link support.", 2048); + mumble->uiVersion = 2; + } + mumble->uiTick++; + + if (!netgame || gamestate != GS_LEVEL) { // Zero out, but never delink. + mumble->fAvatarPosition[0] = mumble->fAvatarPosition[1] = mumble->fAvatarPosition[2] = 0.0f; + mumble->fAvatarFront[0] = 1.0f; + mumble->fAvatarFront[1] = mumble->fAvatarFront[2] = 0.0f; + mumble->fCameraPosition[0] = mumble->fCameraPosition[1] = mumble->fCameraPosition[2] = 0.0f; + mumble->fCameraFront[0] = 1.0f; + mumble->fCameraFront[1] = mumble->fCameraFront[2] = 0.0f; + return; + } + + { + UINT8 *p = mumble->context; + WRITEMEM(p, server_context, 8); + WRITEINT16(p, gamemap); + mumble->context_len = (UINT32)(p - mumble->context); + } + + if (mobj) { + mumble->fAvatarPosition[0] = FIXED_TO_FLOAT(mobj->x) / MUMBLEUNIT; + mumble->fAvatarPosition[1] = FIXED_TO_FLOAT(mobj->z) / MUMBLEUNIT; + mumble->fAvatarPosition[2] = FIXED_TO_FLOAT(mobj->y) / MUMBLEUNIT; + + anglef = AngleFixed(mobj->angle); + angle = FIXED_TO_FLOAT(anglef)*DEG2RAD; + mumble->fAvatarFront[0] = (float)cos(angle); + mumble->fAvatarFront[1] = 0.0f; + mumble->fAvatarFront[2] = (float)sin(angle); + } else { + mumble->fAvatarPosition[0] = mumble->fAvatarPosition[1] = mumble->fAvatarPosition[2] = 0.0f; + mumble->fAvatarFront[0] = 1.0f; + mumble->fAvatarFront[1] = mumble->fAvatarFront[2] = 0.0f; + } + + mumble->fCameraPosition[0] = FIXED_TO_FLOAT(listener.x) / MUMBLEUNIT; + mumble->fCameraPosition[1] = FIXED_TO_FLOAT(listener.z) / MUMBLEUNIT; + mumble->fCameraPosition[2] = FIXED_TO_FLOAT(listener.y) / MUMBLEUNIT; + + anglef = AngleFixed(listener.angle); + angle = FIXED_TO_FLOAT(anglef)*DEG2RAD; + mumble->fCameraFront[0] = (float)cos(angle); + mumble->fCameraFront[1] = 0.0f; + mumble->fCameraFront[2] = (float)sin(angle); +#else + (void)mobj; + (void)listener; +#endif // HAVE_MUMBLE +} + +void I_StartupMouse(void){} + +void I_StartupMouse2(void){} + +INT32 I_GetKey(void) +{ + return 0; +} + +void I_StartupTimer(void){} + +void I_AddExitFunc(void (*func)()) +{ + I_Assert(num_exit_funcs < sizeof(exit_funcs) / sizeof(exit_funcs[0])); + exit_funcs[num_exit_funcs++] = func; +} + +void I_RemoveExitFunc(void (*func)()) +{ + // NOTE: this isn't even used, so no need implementing this. + (void)func; +} + +#ifdef HAVE_TERMIOS +typedef struct +{ + size_t cursor; + char buffer[256]; +} feild_t; + +static feild_t tty_con; + +// lock to prevent clearing partial lines, since not everything +// printed ends on a newline. +static boolean ttycon_ateol = true; +// some key codes that the terminal may be using +// TTimo NOTE: I'm not sure how relevant this is +static INT32 tty_erase; +static INT32 tty_eof; + +static struct termios tty_tc; + +// ============================================================= +// tty console routines +// NOTE: if the user is editing a line when something gets printed to the early console then it won't look good +// so we provide tty_Clear and tty_Show to be called before and after a stdout or stderr output +// ============================================================= + +// flush stdin, I suspect some terminals are sending a LOT of garbage +// FIXME TTimo relevant? +#if 0 +static inline void tty_FlushIn(void) +{ + char key; + while (read(STDIN_FILENO, &key, 1)!=-1); +} +#endif + +// do a backspace +// TTimo NOTE: it seems on some terminals just sending '\b' is not enough +// so for now, in any case we send "\b \b" .. yeah well .. +// (there may be a way to find out if '\b' alone would work though) +// Hanicef NOTE: using \b this way is unreliable because of terminal state, +// it's better to use \r to reset the cursor to the beginning of the +// line and clear from there. +static void tty_Back(void) +{ + write(STDOUT_FILENO, "\r", 1); + if (tty_con.cursor>0) + { + write(STDOUT_FILENO, tty_con.buffer, tty_con.cursor); + } + write(STDOUT_FILENO, " \b", 2); +} + +static void tty_Clear(void) +{ + size_t i; + write(STDOUT_FILENO, "\r", 1); + if (tty_con.cursor>0) + { + for (i=0; i<tty_con.cursor; i++) + { + write(STDOUT_FILENO, " ", 1); + } + write(STDOUT_FILENO, "\r", 1); + } +} + +// never exit without calling this, or your terminal will be left in a pretty bad state +static void I_ShutdownConsole(void) +{ + if (consolevent) + { + I_OutputMsg("Shutdown tty console\n"); + consolevent = false; + tcsetattr (STDIN_FILENO, TCSADRAIN, &tty_tc); + } +} + +static void I_StartupConsole(void) +{ + struct termios tc; + + // TTimo + // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=390 (404) + // then SIGTTIN or SIGTOU is emitted, if not catched, turns into a SIGSTP + signal(SIGTTIN, SIG_IGN); + signal(SIGTTOU, SIG_IGN); + + consolevent = !M_CheckParm("-noconsole"); + framebuffer = M_CheckParm("-framebuffer"); + + if (framebuffer) + consolevent = false; + + if (!consolevent) return; + + if (isatty(STDIN_FILENO)!=1) + { + I_OutputMsg("stdin is not a tty, tty console mode failed\n"); + consolevent = false; + return; + } + memset(&tty_con, 0x00, sizeof(tty_con)); + tcgetattr (0, &tty_tc); + tty_erase = tty_tc.c_cc[VERASE]; + tty_eof = tty_tc.c_cc[VEOF]; + tc = tty_tc; + /* + ECHO: don't echo input characters + ICANON: enable canonical mode. This enables the special + characters EOF, EOL, EOL2, ERASE, KILL, REPRINT, + STATUS, and WERASE, and buffers by lines. + ISIG: when any of the characters INTR, QUIT, SUSP, or + DSUSP are received, generate the corresponding signal + */ + tc.c_lflag &= ~(ECHO | ICANON); + /* + ISTRIP strip off bit 8 + INPCK enable input parity checking + */ + tc.c_iflag &= ~(ISTRIP | INPCK); + tc.c_cc[VMIN] = 0; //1? + tc.c_cc[VTIME] = 0; + tcsetattr (0, TCSADRAIN, &tc); +} + +static void I_GetConsoleEvents(void) +{ + // we use this when sending back commands + event_t ev = {0}; + char key = 0; + struct pollfd pfd = + { + .fd = STDIN_FILENO, + .events = POLLIN, + .revents = 0, + }; + + if (!consolevent) + return; + + for (;;) + { + if (poll(&pfd, 1, 0) < 1 || !(pfd.revents & POLLIN)) + return; + + ev.type = ev_console; + ev.key = 0; + if (read(STDIN_FILENO, &key, 1) == -1 || !key) + return; + + // we have something + // backspace? + // NOTE TTimo testing a lot of values .. seems it's the only way to get it to work everywhere + if ((key == tty_erase) || (key == 127) || (key == 8)) + { + if (tty_con.cursor > 0) + { + tty_con.cursor--; + tty_con.buffer[tty_con.cursor] = '\0'; + tty_Back(); + } + ev.key = KEY_BACKSPACE; + } + else if (key < ' ') // check if this is a control char + { + if (key == '\n') + { + tty_Clear(); + tty_con.cursor = 0; + ev.key = KEY_ENTER; + } + else if (key == 0x4) // ^D, aka EOF + { + // shut down, most unix programs behave this way + I_Quit(); + } + else continue; + } + else if (tty_con.cursor < sizeof(tty_con.buffer)) + { + // push regular character + ev.key = tty_con.buffer[tty_con.cursor] = key; + tty_con.cursor++; + // print the current line (this is differential) + write(STDOUT_FILENO, &key, 1); + } + if (ev.key) D_PostEvent(&ev); + //tty_FlushIn(); + } +} + +#elif defined (_WIN32) +static BOOL I_ReadyConsole(HANDLE ci) +{ + DWORD gotinput; + if (ci == INVALID_HANDLE_VALUE) return FALSE; + if (WaitForSingleObject(ci,0) != WAIT_OBJECT_0) return FALSE; + if (GetFileType(ci) != FILE_TYPE_CHAR) return FALSE; + if (!GetConsoleMode(ci, &gotinput)) return FALSE; + return (GetNumberOfConsoleInputEvents(ci, &gotinput) && gotinput); +} + +static boolean entering_con_command = false; + +static void Impl_HandleKeyboardConsoleEvent(KEY_EVENT_RECORD evt, HANDLE co) +{ + event_t event; + CONSOLE_SCREEN_BUFFER_INFO CSBI; + DWORD t; + + memset(&event,0x00,sizeof (event)); + + if (evt.bKeyDown) + { + event.type = ev_console; + entering_con_command = true; + switch (evt.wVirtualKeyCode) + { + case VK_ESCAPE: + case VK_TAB: + event.key = KEY_NULL; + break; + case VK_RETURN: + entering_con_command = false; + /* FALLTHRU */ + default: + //event.key = MapVirtualKey(evt.wVirtualKeyCode,2); // convert in to char + event.key = evt.uChar.AsciiChar; + } + if (co != INVALID_HANDLE_VALUE && GetFileType(co) == FILE_TYPE_CHAR && GetConsoleMode(co, &t)) + { + if (event.key && event.key != KEY_LSHIFT && event.key != KEY_RSHIFT) + { +#ifdef _UNICODE + WriteConsole(co, &evt.uChar.UnicodeChar, 1, &t, NULL); +#else + WriteConsole(co, &evt.uChar.AsciiChar, 1 , &t, NULL); +#endif + } + if (evt.wVirtualKeyCode == VK_BACK + && GetConsoleScreenBufferInfo(co,&CSBI)) + { + WriteConsoleOutputCharacterA(co, " ",1, CSBI.dwCursorPosition, &t); + } + } + } + if (event.key) D_PostEvent(&event); +} + +static void I_GetConsoleEvents(void) +{ + HANDLE ci = GetStdHandle(STD_INPUT_HANDLE); + HANDLE co = GetStdHandle(STD_OUTPUT_HANDLE); + INPUT_RECORD input; + DWORD t; + + while (I_ReadyConsole(ci) && ReadConsoleInput(ci, &input, 1, &t) && t) + { + switch (input.EventType) + { + case KEY_EVENT: + Impl_HandleKeyboardConsoleEvent(input.Event.KeyEvent, co); + break; + case MOUSE_EVENT: + case WINDOW_BUFFER_SIZE_EVENT: + case MENU_EVENT: + case FOCUS_EVENT: + break; + } + } +} + +static void I_StartupConsole(void) +{ + HANDLE ci, co; + BOOL gotConsole = AllocConsole(); + consolevent = !M_CheckParm("-noconsole"); + if (gotConsole) + { + SetConsoleTitleA("SRB2 Console"); + consolevent = true; + } + + //Let get the real console HANDLE, because Mingw's Bash is bad! + ci = CreateFile(TEXT("CONIN$") , GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + co = CreateFile(TEXT("CONOUT$"), GENERIC_WRITE|GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (ci != INVALID_HANDLE_VALUE) + { + const DWORD CM = ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT; + SetStdHandle(STD_INPUT_HANDLE, ci); + if (GetFileType(ci) == FILE_TYPE_CHAR) + SetConsoleMode(ci, CM); //default mode but no ENABLE_MOUSE_INPUT + } + if (co != INVALID_HANDLE_VALUE) + { + SetStdHandle(STD_OUTPUT_HANDLE, co); + SetStdHandle(STD_ERROR_HANDLE, co); + } +} +static inline void I_ShutdownConsole(void){} +#else +static void I_GetConsoleEvents(void){} +static inline void I_StartupConsole(void) +{ + consolevent = !M_CheckParm("-noconsole"); + framebuffer = M_CheckParm("-framebuffer"); + + if (framebuffer) + consolevent = false; +} +static inline void I_ShutdownConsole(void){} +#endif + +void I_OutputMsg(const char *fmt, ...) +{ + size_t len; + char *txt; + va_list argptr; + + va_start(argptr,fmt); + len = vsnprintf(NULL, 0, fmt, argptr); + va_end(argptr); + if (len == 0) + return; + + txt = malloc(len+1); + va_start(argptr,fmt); + vsprintf(txt, fmt, argptr); + va_end(argptr); + +#if defined (_WIN32) && defined (_MSC_VER) + OutputDebugStringA(txt); +#endif + +#ifdef LOGMESSAGES + if (logstream) + { + fwrite(txt, len, 1, logstream); + fflush(logstream); + } +#endif + +#if defined (_WIN32) +#ifdef DEBUGFILE + if (debugfile != stderr) +#endif + { + HANDLE co = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD bytesWritten; + + if (co == INVALID_HANDLE_VALUE) + { + free(txt); + return; + } + + if (GetFileType(co) == FILE_TYPE_CHAR && GetConsoleMode(co, &bytesWritten)) + { + static COORD coordNextWrite = {0,0}; + LPVOID oldLines = NULL; + INT oldLength; + CONSOLE_SCREEN_BUFFER_INFO csbi; + + // Save the lines that we're going to obliterate. + GetConsoleScreenBufferInfo(co, &csbi); + oldLength = csbi.dwSize.X * (csbi.dwCursorPosition.Y - coordNextWrite.Y) + csbi.dwCursorPosition.X - coordNextWrite.X; + + if (oldLength > 0) + { + LPVOID blank = malloc(oldLength); + if (!blank) + { + free(txt); + return; + } + memset(blank, ' ', oldLength); // Blank out. + oldLines = malloc(oldLength*sizeof(TCHAR)); + if (!oldLines) + { + free(blank); + free(txt); + return; + } + + ReadConsoleOutputCharacter(co, oldLines, oldLength, coordNextWrite, &bytesWritten); + + // Move to where we what to print - which is where we would've been, + // had console input not been in the way, + SetConsoleCursorPosition(co, coordNextWrite); + + WriteConsoleA(co, blank, oldLength, &bytesWritten, NULL); + free(blank); + + // And back to where we want to print again. + SetConsoleCursorPosition(co, coordNextWrite); + } + + // Actually write the string now! + WriteConsoleA(co, txt, (DWORD)len, &bytesWritten, NULL); + + // Next time, output where we left off. + GetConsoleScreenBufferInfo(co, &csbi); + coordNextWrite = csbi.dwCursorPosition; + + // Restore what was overwritten. + if (oldLines && entering_con_command) + WriteConsole(co, oldLines, oldLength, &bytesWritten, NULL); + if (oldLines) free(oldLines); + } + else // Redirected to a file. + WriteFile(co, txt, (DWORD)len, &bytesWritten, NULL); + } +#else +#ifdef HAVE_TERMIOS + if (consolevent && ttycon_ateol) + { + tty_Clear(); + ttycon_ateol = false; + } +#endif + + if (!framebuffer) + fprintf(stderr, "%s", txt); +#ifdef HAVE_TERMIOS + if (consolevent && txt[len-1] == '\n') + { + write(STDOUT_FILENO, tty_con.buffer, tty_con.cursor); + ttycon_ateol = true; + } +#endif + + // 2004-03-03 AJR Since not all messages end in newline, some were getting displayed late. + if (!framebuffer) + fflush(stderr); + +#endif + free(txt); +} + +void I_OsPolling(void) +{ + if (consolevent) + I_GetConsoleEvents(); +} + +FUNCNORETURN static ATTRNORETURN void quit_handler(int num) +{ + (void)num; + // FIXME: set a flag to quit later. + // this is risky since some functions can softlock in a signal handler: https://www.unix.com/man-page/posix/7/signal-safety/ + I_Quit(); +} + +static void I_RegisterSignals (void) +{ +#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) + // signal is deprecated, long live sigaction + struct sigaction sig; + sigemptyset(&sig.sa_mask); + sig.sa_flags = 0; + sig.sa_handler = quit_handler; + sigaction(SIGINT, &sig, NULL); + sig.sa_handler = quit_handler; + sigaction(SIGTERM, &sig, NULL); +#else + signal(SIGINT, quit_handler); + signal(SIGBREAK, quit_handler); + signal(SIGTERM, quit_handler); +#endif +} + +INT32 I_StartupSystem(void) +{ +#ifdef HAVE_THREADS + I_start_threads(); + I_AddExitFunc(I_stop_threads); +#endif + I_StartupConsole(); + I_RegisterSignals(); +#ifndef NOMUMBLE + I_SetupMumble(); +#endif + return 0; +} + +void I_ShutdownSystem(void) +{ + INT32 c; + + I_ShutdownConsole(); + + for (c = MAX_QUIT_FUNCS-1; c >= 0; c--) + if (exit_funcs[c]) + (*exit_funcs[c])(); +#ifdef LOGMESSAGES + if (logstream) + { + I_OutputMsg("I_ShutdownSystem(): end of logstream.\n"); + fclose(logstream); + logstream = NULL; + } +#endif +} + +void I_GetDiskFreeSpace(INT64* freespace) +{ +#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) + struct statvfs stfs; + if (statvfs(srb2home, &stfs) == -1) + { + *freespace = INT32_MAX; + return; + } + *freespace = stfs.f_bavail * stfs.f_bsize; +#elif defined (_WIN32) + static p_GetDiskFreeSpaceExA pfnGetDiskFreeSpaceEx = NULL; + static boolean testwin95 = false; + ULARGE_INTEGER usedbytes, lfreespace; + + if (!testwin95) + { + pfnGetDiskFreeSpaceEx = (p_GetDiskFreeSpaceExA)(LPVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetDiskFreeSpaceExA"); + testwin95 = true; + } + if (pfnGetDiskFreeSpaceEx) + { + if (pfnGetDiskFreeSpaceEx(srb2home, &lfreespace, &usedbytes, NULL)) + *freespace = lfreespace.QuadPart; + else + *freespace = INT32_MAX; + } + else + { + DWORD SectorsPerCluster, BytesPerSector, NumberOfFreeClusters, TotalNumberOfClusters; + GetDiskFreeSpace(NULL, &SectorsPerCluster, &BytesPerSector, + &NumberOfFreeClusters, &TotalNumberOfClusters); + *freespace = BytesPerSector*SectorsPerCluster*NumberOfFreeClusters; + } +#else // Dummy for platform independent; 1GB should be enough + *freespace = 1024*1024*1024; +#endif +} + +char *I_GetUserName(void) +{ + static char username[MAXPLAYERNAME+1]; + char *p; +#ifdef _WIN32 + DWORD i = MAXPLAYERNAME; + + if (!GetUserNameA(username, &i)) +#endif + { + p = I_GetEnv("USER"); + if (!p) + { + p = I_GetEnv("user"); + if (!p) + { + p = I_GetEnv("USERNAME"); + if (!p) + { + p = I_GetEnv("username"); + if (!p) + { + return NULL; + } + } + } + } + strncpy(username, p, MAXPLAYERNAME); + } + + + if (strcmp(username, "") != 0) + return username; + return NULL; // dummy for platform independent version +} + +INT32 I_mkdir(const char *dirname, INT32 unixright) +{ +//[segabor] +#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) || defined (__CYGWIN__) + return mkdir(dirname, unixright); +#elif defined (_WIN32) + UNREFERENCED_PARAMETER(unixright); /// \todo should implement ntright under nt... + return CreateDirectoryA(dirname, NULL); +#else + (void)dirname; + (void)unixright; + return false; +#endif +} + +const CPUInfoFlags *I_CPUInfo(void) +{ + return NULL; +} + +static boolean isWadPathOk(const char *path) +{ + char *wad3path = malloc(256); + + if (!wad3path) + return false; + + sprintf(wad3path, pandf, path, WADKEYWORD1); + + if (FIL_ReadFileOK(wad3path)) + { + free(wad3path); + return true; + } + + free(wad3path); + return false; +} + +static void pathonly(char *s) +{ + size_t j; + + for (j = strlen(s); j != (size_t)-1; j--) + if ((s[j] == '\\') || (s[j] == ':') || (s[j] == '/')) + { + if (s[j] == ':') s[j+1] = 0; + else s[j] = 0; + return; + } +} + +static const char *searchWad(const char *searchDir) +{ + static char tempsw[256] = ""; + filestatus_t fstemp; + + strcpy(tempsw, WADKEYWORD1); + fstemp = filesearch(tempsw,searchDir,NULL,true,20); + if (fstemp == FS_FOUND) + { + pathonly(tempsw); + return tempsw; + } + + return NULL; +} + +#define CHECKWADPATH(ret) \ +do { \ + I_OutputMsg(",%s", ret); \ + if (isWadPathOk(ret)) \ + return ret; \ +} while (0) + +#define SEARCHWAD(str) \ +do { \ + WadPath = searchWad(str); \ + if (WadPath) \ + return WadPath; \ +} while (0) + +static const char *locateWad(void) +{ + const char *envstr; + const char *WadPath; + int i; + + I_OutputMsg("SRB2WADDIR"); + // does SRB2WADDIR exist? + if (((envstr = I_GetEnv("SRB2WADDIR")) != NULL) && isWadPathOk(envstr)) + return envstr; + +#ifndef NOCWD + // examine current dir + strcpy(returnWadPath, "."); + I_OutputMsg(",%s", returnWadPath); + if (isWadPathOk(returnWadPath)) + return NULL; +#endif + +#ifdef __APPLE__ + OSX_GetResourcesPath(returnWadPath); + CHECKWADPATH(returnWadPath); +#endif + + // examine default dirs + for (i = 0; wadDefaultPaths[i]; i++) + { + strcpy(returnWadPath, wadDefaultPaths[i]); + CHECKWADPATH(returnWadPath); + } + +#ifndef NOHOME + // find in $HOME + if ((envstr = I_GetEnv("HOME")) != NULL) + { + char *tmp = malloc(strlen(envstr) + 1 + sizeof(DEFAULTDIR)); + strcpy(tmp, envstr); + strcat(tmp, "/"); + strcat(tmp, DEFAULTDIR); + CHECKWADPATH(tmp); + free(tmp); + } +#endif + + // search paths + for (i = 0; wadSearchPaths[i]; i++) + { + I_OutputMsg(", in:%s", wadSearchPaths[i]); + SEARCHWAD(wadSearchPaths[i]); + } + + // if nothing was found + return NULL; +} + +const char *I_LocateWad(void) +{ + const char *waddir; + + I_OutputMsg("Looking for WADs in: "); + // FIXME: should we go for a command parameter instead for dedicated servers? + waddir = locateWad(); + I_OutputMsg("\n"); + + if (waddir) + { + // change to the directory where we found srb2.pk3 +#if defined (_WIN32) + waddir = _fullpath(NULL, waddir, MAX_PATH); + SetCurrentDirectoryA(waddir); +#else + waddir = realpath(waddir, NULL); + if (chdir(waddir) == -1) + I_OutputMsg("Couldn't change working directory\n"); +#endif + } + return waddir; +} + +void I_GetJoystickEvents(void){} + +void I_GetJoystick2Events(void){} + +void I_GetMouseEvents(void){} + +void I_UpdateMouseGrab(void){} + +char *I_GetEnv(const char *name) +{ + return getenv(name); +} + +INT32 I_PutEnv(char *name) +{ + return putenv(name); +} + +INT32 I_ClipboardCopy(const char *data, size_t size) +{ + (void)data; + (void)size; + return -1; +} + +const char *I_ClipboardPaste(void) +{ + return NULL; +} + +size_t I_GetRandomBytes(char *destination, size_t count) +{ +#if defined (__unix__) || defined (UNIXCOMMON) || defined(__APPLE__) + 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; +#elif defined (_WIN32) + if (RtlGenRandom(destination, count)) + return count; + + I_OutputMsg("I_GetRandomBytes(): couldn't get any random bytes"); + return 0; +#else + #warning SDL I_GetRandomBytes is not implemented on this platform. + return 0; +#endif +} + +void I_RegisterSysCommands(void){} + +char const *I_GetSysName(void) +{ + // reference: https://sourceforge.net/p/predef/wiki/OperatingSystems/ +#if defined(_WIN32) || defined(__CYGWIN__) + return "Windows"; +#elif defined(__APPLE__) + return "Mac OS"; +#elif defined(__linux__) + return "Linux"; +#elif defined(__FreeBSD__) + return "FreeBSD"; +#elif defined(__OpenBSD__) + return "OpenBSD"; +#elif defined(__NetBSD__) + return "NetBSD"; +#elif defined(__DragonFly__) + return "DragonFly BSD"; +#elif defined(__gnu_hurd__) + return "GNU Hurd"; // for anyone mental enough to set up an SRB2 server on GNU Hurd +#elif defined(__hpux) + return "HP-UX"; +#elif defined(EPLAN9) + return "Plan 9"; +#elif defined(__HAIKU__) + return "Haiku"; +#elif defined(__BEOS__) + return "BeOS"; +#elif defined(__minix) + return "Minix"; +#elif defined(__sun) +#if defined(__SVR4) || defined(__srv4__) + return "Solaris"; // this would be so cursed... +#else + return "SunOS"; +#endif +#elif defined(_AIX) + return "AIX"; +#elif defined(__SYLLABLE__) + return "SyllableOS"; // RIP SyllableOS, i still miss you ;-; +#else + return "Unknown"; +#endif +} + +void I_GetCursorPosition(INT32 *x, INT32 *y) +{ + (void)x; + (void)y; +} + +void I_SetTextInputMode(boolean active) +{ + (void)active; +} + +boolean I_GetTextInputMode(void) +{ + return false; +} + +#include "../sdl/dosstr.c" diff --git a/src/dedicated/i_threads.c b/src/dedicated/i_threads.c new file mode 100644 index 0000000000000000000000000000000000000000..55c0a069e5d3f42e03c8286d4862f87e9c8f4a8e --- /dev/null +++ b/src/dedicated/i_threads.c @@ -0,0 +1,359 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2020-2023 by James R. +// +// 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 i_threads.c +/// \brief Multithreading abstraction + +#if defined (__unix__) || (!defined(__APPLE__) && defined (UNIXCOMMON)) + +#include <pthread.h> + +#include "../i_threads.h" +#include "../doomdef.h" +#include "../doomtype.h" + +typedef struct thread_s thread_t; + +struct thread_s +{ + thread_t *next; + void *userdata; + I_thread_fn func; + pthread_t thread; +}; + +// we use a linked list to avoid moving memory blocks when allocating new threads. +static thread_t *thread_list; +static pthread_mutex_t thread_lock = PTHREAD_MUTEX_INITIALIZER; + +static void *HandleThread(void *data) +{ + thread_t *thread = data; + thread->func(thread->userdata); + + pthread_mutex_lock(&thread_lock); + thread->func = NULL; + pthread_mutex_unlock(&thread_lock); + return NULL; +} + +void I_spawn_thread(const char *name, I_thread_fn entry, void *userdata) +{ + thread_t *thread; + (void)name; + pthread_mutex_lock(&thread_lock); + thread = thread_list; + while (thread != NULL) + { + if (thread->func == NULL) + { + // join with the exited thread to release it's resources. + pthread_join(thread->thread, NULL); + break; + } + thread = thread->next; + } + if (thread == NULL) + { + thread = malloc(sizeof(thread_t)); + thread->next = thread_list; + thread_list = thread; + } + + thread->func = entry; + thread->userdata = userdata; + pthread_create(&thread->thread, NULL, HandleThread, thread); + pthread_mutex_unlock(&thread_lock); +} + +int I_thread_is_stopped(void) +{ + thread_t *thread; + pthread_mutex_lock(&thread_lock); + thread = thread_list; + while (thread != NULL) + { + if (thread->func != NULL) + { + pthread_mutex_unlock(&thread_lock); + return false; + } + thread = thread->next; + } + pthread_mutex_unlock(&thread_lock); + return true; +} + +void I_start_threads(void) +{ +} + +void I_stop_threads(void) +{ + thread_t *thread = thread_list; + while (thread != NULL) + { + // join with all threads here, since finished threads haven't been awaited yet. + pthread_join(thread->thread, NULL); + thread = thread->next; + } +} + +void I_lock_mutex(I_mutex *anchor) +{ + pthread_mutex_lock(&thread_lock); + if (*anchor == NULL) + { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + + // SRB2 relies on lock recursion, so we need a mutex configured for that. + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + *anchor = malloc(sizeof(pthread_mutex_t)); + pthread_mutex_init(*anchor, &attr); + pthread_mutexattr_destroy(&attr); + } + pthread_mutex_unlock(&thread_lock); + pthread_mutex_lock(*anchor); +} + +void I_unlock_mutex(I_mutex id) +{ + pthread_mutex_unlock(id); +} + +void I_hold_cond(I_cond *cond_anchor, I_mutex mutex_id) +{ + I_Assert(mutex_id != NULL); + pthread_mutex_lock(&thread_lock); + if (*cond_anchor == NULL) + { + *cond_anchor = malloc(sizeof(pthread_cond_t)); + pthread_cond_init(*cond_anchor, NULL); + } + pthread_mutex_unlock(&thread_lock); + pthread_cond_wait(*cond_anchor, mutex_id); +} + +void I_wake_one_cond(I_cond *anchor) +{ + pthread_mutex_lock(&thread_lock); + if (*anchor == NULL) + { + *anchor = malloc(sizeof(pthread_cond_t)); + pthread_cond_init(*anchor, NULL); + } + pthread_mutex_unlock(&thread_lock); + pthread_cond_signal(*anchor); +} + +void I_wake_all_cond(I_cond *anchor) +{ + pthread_mutex_lock(&thread_lock); + if (*anchor == NULL) + { + *anchor = malloc(sizeof(pthread_cond_t)); + pthread_cond_init(*anchor, NULL); + } + pthread_mutex_unlock(&thread_lock); + pthread_cond_broadcast(*anchor); +} +#elif defined (_WIN32) +#include <windows.h> + +#include "../i_threads.h" +#include "../doomdef.h" +#include "../doomtype.h" + +typedef struct thread_s thread_t; + +struct thread_s +{ + thread_t *next; + void *userdata; + I_thread_fn func; + HANDLE thread; + DWORD thread_id; +}; + +// we use a linked list to avoid moving memory blocks when allocating new threads. +static thread_t *thread_list; +static CRITICAL_SECTION thread_lock; + +static DWORD __stdcall HandleThread(void *data) +{ + thread_t *thread = data; + thread->func(thread->userdata); + + EnterCriticalSection(&thread_lock); + thread->func = NULL; + LeaveCriticalSection(&thread_lock); + return 0; +} + +void I_spawn_thread(const char *name, I_thread_fn entry, void *userdata) +{ + thread_t *thread; + (void)name; + EnterCriticalSection(&thread_lock); + thread = thread_list; + while (thread != NULL) + { + if (thread->func == NULL) + { + CloseHandle(thread->thread); + break; + } + thread = thread->next; + } + if (thread == NULL) + { + thread = malloc(sizeof(thread_t)); + thread->next = thread_list; + thread_list = thread; + } + + thread->func = entry; + thread->userdata = userdata; + thread->thread = CreateThread(NULL, 0, HandleThread, thread, 0, &thread->thread_id); + LeaveCriticalSection(&thread_lock); +} + +int I_thread_is_stopped(void) +{ + thread_t *thread; + EnterCriticalSection(&thread_lock); + thread = thread_list; + while (thread != NULL) + { + if (thread->func != NULL) + { + LeaveCriticalSection(&thread_lock); + return false; + } + thread = thread->next; + } + LeaveCriticalSection(&thread_lock); + return true; +} + +void I_start_threads(void) +{ + InitializeCriticalSection(&thread_lock); +} + +void I_stop_threads(void) +{ + thread_t *thread = thread_list; + while (thread != NULL) + { + WaitForSingleObject(thread->thread, INFINITE); + CloseHandle(thread->thread); + thread = thread->next; + } + DeleteCriticalSection(&thread_lock); +} + +void I_lock_mutex(I_mutex *anchor) +{ + EnterCriticalSection(&thread_lock); + if (*anchor == NULL) + { + *anchor = malloc(sizeof(CRITICAL_SECTION)); + InitializeCriticalSection(*anchor); + } + LeaveCriticalSection(&thread_lock); + EnterCriticalSection(*anchor); +} + +void I_unlock_mutex(I_mutex id) +{ + LeaveCriticalSection(id); +} + +void I_hold_cond(I_cond *cond_anchor, I_mutex mutex_id) +{ + I_Assert(mutex_id != NULL); + EnterCriticalSection(&thread_lock); + if (*cond_anchor == NULL) + { + *cond_anchor = malloc(sizeof(CONDITION_VARIABLE)); + InitializeConditionVariable(*cond_anchor); + } + LeaveCriticalSection(&thread_lock); + SleepConditionVariableCS(*cond_anchor, mutex_id, INFINITE); +} + +void I_wake_one_cond(I_cond *anchor) +{ + EnterCriticalSection(&thread_lock); + if (*anchor == NULL) + { + *anchor = malloc(sizeof(CONDITION_VARIABLE)); + InitializeConditionVariable(*anchor); + } + LeaveCriticalSection(&thread_lock); + WakeConditionVariable(*anchor); +} + +void I_wake_all_cond(I_cond *anchor) +{ + EnterCriticalSection(&thread_lock); + if (*anchor == NULL) + { + *anchor = malloc(sizeof(CONDITION_VARIABLE)); + InitializeConditionVariable(*anchor); + } + LeaveCriticalSection(&thread_lock); + WakeAllConditionVariable(*anchor); +} +#else +void I_spawn_thread(const char *name, I_thread_fn entry, void *userdata) +{ + (void)name; + entry(userdata); +} + +int I_thread_is_stopped(void) +{ +} + +void I_start_threads(void) +{ +} + +void I_stop_threads(void) +{ +} + +void I_lock_mutex(I_mutex *anchor) +{ + (void)anchor; +} + +void I_unlock_mutex(I_mutex id) +{ + (void)id; +} + +void I_hold_cond(I_cond *cond_anchor, I_mutex mutex_id) +{ + (void)cond_anchor; + (void)mutex_id; +} + +void I_wake_one_cond(I_cond *anchor) +{ + (void)anchor; +} + +void I_wake_all_cond(I_cond *anchor) +{ + (void)anchor; +} +#endif diff --git a/src/dedicated/i_video.c b/src/dedicated/i_video.c new file mode 100644 index 0000000000000000000000000000000000000000..19f2d0cbd51bba44266ca0b92627b542cb8c948b --- /dev/null +++ b/src/dedicated/i_video.c @@ -0,0 +1,78 @@ +#include "../doomdef.h" +#include "../command.h" +#include "../i_video.h" + +rendermode_t rendermode = render_none; +rendermode_t chosenrendermode = render_none; + +boolean allow_fullscreen = false; + +consvar_t cv_vidwait = CVAR_INIT ("vid_wait", "On", CV_SAVE, CV_OnOff, NULL); + +void I_StartupGraphics(void){} +void I_ShutdownGraphics(void){} + +void VID_StartupOpenGL(void){} + +void I_SetPalette(RGBA_t *palette) +{ + (void)palette; +} + +INT32 VID_NumModes(void) +{ + return 0; +} + +INT32 VID_GetModeForSize(INT32 w, INT32 h) +{ + (void)w; + (void)h; + return 0; +} + +void VID_PrepareModeList(void){} + +INT32 VID_SetMode(INT32 modenum) +{ + (void)modenum; + return 0; +} + +boolean VID_CheckRenderer(void) +{ + return false; +} + +void VID_CheckGLLoaded(rendermode_t oldrender) +{ + (void)oldrender; +} + +const char *VID_GetModeName(INT32 modenum) +{ + (void)modenum; + return NULL; +} + +UINT32 I_GetRefreshRate(void) { return 35; } + +void I_UpdateNoBlit(void){} + +void I_FinishUpdate(void){} + +void I_UpdateNoVsync(void) {} + +void I_WaitVBL(INT32 count) +{ + (void)count; +} + +void I_ReadScreen(UINT8 *scr) +{ + (void)scr; +} + +void I_BeginRead(void){} + +void I_EndRead(void){} diff --git a/src/deh_lua.c b/src/deh_lua.c index 3600c3554da059091e513c559f7a9e80cff72de2..48f737a1ff5c6587414b2efe2edbc566c9c25034 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -27,6 +27,12 @@ static inline int lib_freeslot(lua_State *L) if (!lua_lumploading) return luaL_error(L, "This function cannot be called from within a hook or coroutine!"); + if (!deh_loaded) + { + initfreeslots(); + deh_loaded = true; + } + while (n-- > 0) { s = Z_StrDup(luaL_checkstring(L,1)); @@ -58,24 +64,19 @@ static inline int lib_freeslot(lua_State *L) } else if (fastcmp(type, "SPR")) { - char wad; spritenum_t j; - lua_getfield(L, LUA_REGISTRYINDEX, "WAD"); - wad = (char)lua_tointeger(L, -1); - lua_pop(L, 1); + + if (strlen(word) > MAXSPRITENAME) + return luaL_error(L, "Sprite name is longer than %d characters\n", MAXSPRITENAME); + for (j = SPR_FIRSTFREESLOT; j <= SPR_LASTFREESLOT; j++) { - if (used_spr[(j-SPR_FIRSTFREESLOT)/8] & (1<<(j%8))) - { - if (!sprnames[j][4] && memcmp(sprnames[j],word,4)==0) - sprnames[j][4] = wad; + if (in_bit_array(used_spr, j - SPR_FIRSTFREESLOT)) continue; // Already allocated, next. - } // Found a free slot! CONS_Printf("Sprite SPR_%s allocated.\n",word); - 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. + strcpy(sprnames[j], word); + set_bit_array(used_spr, j - SPR_FIRSTFREESLOT); // 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); @@ -454,17 +455,19 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word) } else if (fastncmp("SPR_",word,4)) { p = word+4; - for (i = 0; i < NUMSPRITES; i++) - if (!sprnames[i][4] && fastncmp(p,sprnames[i],4)) { - // 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); + i = R_GetSpriteNumByName(p); + if (i != NUMSPRITES) + { + // 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; + } + else if (mathlib) + return luaL_error(L, "sprite '%s' could not be found.\n", word); return 0; } else if (fastncmp("SPR2_",word,5)) { @@ -601,7 +604,7 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word) { CacheAndPushConstant(L, word, (lua_Integer)BT_SPIN); return 1; - } + } for (i = 0; INT_CONST[i].n; i++) if (fastcmp(word,INT_CONST[i].n)) { @@ -729,18 +732,18 @@ static inline int lib_getenum(lua_State *L) // 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"; + char fullname[4 + MAXSPRITENAME + 1] = "SPR_"; if (!gL) return; - strncpy(&fullname[4], name, 4); + strcpy(&fullname[4], name); lua_pushstring(gL, fullname); lua_rawget(gL, LUA_GLOBALSINDEX); if (!lua_isnil(gL, -1)) { - lua_pushstring(gL, name); + lua_pushstring(gL, fullname); lua_pushinteger(gL, value); lua_rawset(gL, LUA_GLOBALSINDEX); } diff --git a/src/deh_soc.c b/src/deh_soc.c index 41eb28a90f91f77c3672b7b35ea919f9a0edf6ef..343beb3012676b93256af35c0bd57ff6ba7e9076 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2025 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -286,6 +286,7 @@ void readPlayer(MYFILE *f, INT32 num) } if (playertext) { + // PLAYERTEXT is really weird, so this doesn't use deh_strlcpy. strlcpy(description[num].notes, playertext, NOTE_SIZE); strlcat(description[num].notes, myhashfgets(playertext, NOTE_SIZE, f), NOTE_SIZE); @@ -324,7 +325,8 @@ void readPlayer(MYFILE *f, INT32 num) if (fastcmp(word, "PICNAME")) { SLOTFOUND - strncpy(description[num].picname, word2, 8); + deh_strlcpy(description[num].picname, word2, sizeof description[num].picname, + va("Character %d: picname", num)); } else if (fastcmp(word, "DISPLAYNAME")) { @@ -345,7 +347,8 @@ void readPlayer(MYFILE *f, INT32 num) cur = strchr(cur, '#'); } - strlcpy(description[num].displayname, stringvalue, sizeof description[num].displayname); + deh_strlcpy(description[num].displayname, stringvalue, sizeof description[num].displayname, + va("Character %d: displayname", num)); } else if (fastcmp(word, "OPPOSITECOLOR") || fastcmp(word, "OPPOSITECOLOUR")) { @@ -355,7 +358,8 @@ void readPlayer(MYFILE *f, INT32 num) else if (fastcmp(word, "NAMETAG") || fastcmp(word, "TAGNAME")) { SLOTFOUND - strncpy(description[num].nametag, word2, 8); + deh_strlcpy(description[num].nametag, word2, sizeof description[num].nametag, + va("Character %d: nametag", num)); } else if (fastcmp(word, "TAGTEXTCOLOR") || fastcmp(word, "TAGTEXTCOLOUR")) { @@ -387,7 +391,8 @@ void readPlayer(MYFILE *f, INT32 num) { // Send to free slot. SLOTFOUND - strlcpy(description[num].skinname, word2, sizeof description[num].skinname); + deh_strlcpy(description[num].skinname, word2, sizeof description[num].skinname, + va("Character %d: skinname", num)); strlwr(description[num].skinname); } else if (!failure) @@ -405,7 +410,6 @@ void readfreeslots(MYFILE *f) { char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); char *word,*type; - char *tmp; int i; do @@ -415,10 +419,13 @@ void readfreeslots(MYFILE *f) if (s[0] == '\n') break; - tmp = strchr(s, '#'); - if (tmp) - *tmp = '\0'; - if (s == tmp) + char *hashtag = strchr(s, '#'); + char *space = strchr(s, ' '); + if (hashtag) + *hashtag = '\0'; + if (space) + *space = '\0'; + if (s == hashtag || s == space) continue; // Skip comment lines, but don't break. type = strtok(s, "_"); @@ -440,18 +447,16 @@ void readfreeslots(MYFILE *f) S_AddSoundFx(word, false, 0, false); else if (fastcmp(type, "SPR")) { + if (strlen(word) > MAXSPRITENAME) + I_Error("Sprite name is longer than %d characters\n", MAXSPRITENAME); + for (i = SPR_FIRSTFREESLOT; i <= SPR_LASTFREESLOT; i++) { - if (used_spr[(i-SPR_FIRSTFREESLOT)/8] & (1<<(i%8))) - { - if (!sprnames[i][4] && memcmp(sprnames[i],word,4)==0) - sprnames[i][4] = (char)f->wad; + if (in_bit_array(used_spr, i - SPR_FIRSTFREESLOT)) continue; // Already allocated, next. - } // Found a free slot! - 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. + strcpy(sprnames[i], word); + set_bit_array(used_spr, i - SPR_FIRSTFREESLOT); // Okay, this sprite slot has been named now. // Lua needs to update the value in _G if it exists LUA_UpdateSprName(word, i); break; @@ -1163,7 +1168,7 @@ void readgametype(MYFILE *f, char *gtname) INT16 newgtrankingstype = -1; int newgtinttype = 0; char gtdescription[441]; - char gtconst[MAXLINELEN]; + char gtconst[MAXLINELEN+1]; // Empty strings. gtdescription[0] = '\0'; @@ -1196,6 +1201,7 @@ void readgametype(MYFILE *f, char *gtname) } if (descr) { + // DESCRIPTION is really weird, so this doesn't use deh_strlcpy. strlcpy(gtdescription, descr, sizeof (gtdescription)); strlcat(gtdescription, myhashfgets(descr, sizeof (gtdescription), f), @@ -1402,7 +1408,7 @@ void readlevelheader(MYFILE *f, INT32 num) { deh_strlcpy(mapheaderinfo[num-1]->lvlttl, word2, sizeof(mapheaderinfo[num-1]->lvlttl), va("Level header %d: levelname", num)); - strlcpy(mapheaderinfo[num-1]->selectheading, word2, sizeof(mapheaderinfo[num-1]->selectheading)); // not deh_ so only complains once + strlcpy(mapheaderinfo[num-1]->selectheading, word2, sizeof(mapheaderinfo[num-1]->selectheading)); // not deh_strlcpy so only complains once continue; } // CHEAP HACK: move this over here for lowercase subtitles @@ -1445,10 +1451,10 @@ void readlevelheader(MYFILE *f, INT32 num) // Newly allocated modoption = &mapheaderinfo[num-1]->customopts[j]; - strncpy(modoption->option, word, 31); - modoption->option[31] = '\0'; - strncpy(modoption->value, word2, 255); - modoption->value[255] = '\0'; + deh_strlcpy(modoption->option, word, sizeof(modoption->option), + va("Level header %d: custom option %d key", num, j)); + deh_strlcpy(modoption->value, word2, sizeof(modoption->value), + va("Level header %d: custom option %d value", num, j)); continue; } @@ -1543,6 +1549,12 @@ void readlevelheader(MYFILE *f, INT32 num) P_AddGradesForMare((INT16)(num-1), mare-1, word2); } + // NiGHTS time limits (per mare) + else if (fastncmp(word, "NIGHTSTIME", 10)) + { + P_AddNiGHTSTimes((INT16)(num-1), word2); + } + // Strings that can be truncated else if (fastcmp(word, "SELECTHEADING")) { @@ -1620,7 +1632,7 @@ void readlevelheader(MYFILE *f, INT32 num) else if (fastcmp(word, "KEYWORDS")) { deh_strlcpy(mapheaderinfo[num-1]->keywords, word2, - sizeof(mapheaderinfo[num-1]->keywords), va("Level header %d: keywords", num)); + sizeof(mapheaderinfo[num-1]->keywords), va("Level header %d: keywords", num)); } else if (fastcmp(word, "MUSIC")) { @@ -1669,7 +1681,8 @@ void readlevelheader(MYFILE *f, INT32 num) } else if (fastcmp(word, "FORCECHARACTER")) { - strlcpy(mapheaderinfo[num-1]->forcecharacter, word2, SKINNAMESIZE+1); + deh_strlcpy(mapheaderinfo[num-1]->forcecharacter, word2, sizeof mapheaderinfo[num-1]->forcecharacter, + va("Level header %d: forcecharacter", num)); strlwr(mapheaderinfo[num-1]->forcecharacter); // skin names are lowercase } else if (fastcmp(word, "WEATHER")) @@ -1677,7 +1690,10 @@ void readlevelheader(MYFILE *f, INT32 num) else if (fastcmp(word, "SKYNUM")) mapheaderinfo[num-1]->skynum = (INT16)i; else if (fastcmp(word, "INTERSCREEN")) - strncpy(mapheaderinfo[num-1]->interscreen, word2, 8); + { + deh_strlcpy(mapheaderinfo[num-1]->interscreen, word2, sizeof mapheaderinfo[num-1]->interscreen, + va("Level header %d: interscreen", num)); + } else if (fastcmp(word, "PRECUTSCENENUM")) mapheaderinfo[num-1]->precutscenenum = (UINT8)i; else if (fastcmp(word, "CUTSCENENUM")) @@ -1979,14 +1995,17 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum) picid = (UINT8)atoi(word + 3); if (picid > 8 || picid == 0) { - deh_warning("CutSceneScene %d: unknown word '%s'", num, word); + deh_warning("Cutscene %d, scene %d: pic number %d out of range (1 - %d)", + num + 1, scenenum + 1, picid, 8); continue; } --picid; if (fastcmp(word+4, "NAME")) { - strncpy(cutscenes[num]->scene[scenenum].picname[picid], word2, 8); + deh_strlcpy(cutscenes[num]->scene[scenenum].picname[picid], word2, + sizeof cutscenes[num]->scene[scenenum].picname[picid], + va("Cutscene %d, scene %d, pic %d: name", num + 1, scenenum + 1, picid + 1)); } else if (fastcmp(word+4, "HIRES")) { @@ -2005,12 +2024,13 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum) cutscenes[num]->scene[scenenum].ycoord[picid] = usi; } else - deh_warning("CutSceneScene %d: unknown word '%s'", num, word); + deh_warning("Cutscene %d, scene %d: unknown word '%s'", num + 1, scenenum + 1, word); } else if (fastcmp(word, "MUSIC")) { - strncpy(cutscenes[num]->scene[scenenum].musswitch, word2, 7); - cutscenes[num]->scene[scenenum].musswitch[6] = 0; + deh_strlcpy(cutscenes[num]->scene[scenenum].musswitch, word2, + sizeof cutscenes[num]->scene[scenenum].musswitch, + va("Cutscene %d, scene %d: music", num + 1, scenenum + 1)); } else if (fastcmp(word, "MUSICTRACK")) { @@ -2045,7 +2065,7 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum) cutscenes[num]->scene[scenenum].fadecolor = (UINT8)i; } else - deh_warning("CutSceneScene %d: unknown word '%s'", num, word); + deh_warning("Cutscene %d, scene %d: unknown word '%s'", num + 1, scenenum + 1, word); } } while (!myfeof(f)); // finish when the line is empty @@ -2103,11 +2123,10 @@ void readcutscene(MYFILE *f, INT32 num) readcutscenescene(f, num, value - 1); } else - deh_warning("Scene number %d out of range (1 - 128)", value); - + deh_warning("Cutscene %d: scene number %d out of range (1 - 128)", num + 1, value); } else - deh_warning("Cutscene %d: unknown word '%s', Scene <num> expected.", num, word); + deh_warning("Cutscene %d: unknown word '%s', Scene <num> expected.", num + 1, word); } } while (!myfeof(f)); // finish when the line is empty @@ -2228,7 +2247,8 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum) for (picid = 0; picid < MAX_PROMPT_PICS; picid++) { - strncpy(textprompts[num]->page[pagenum].picname[picid], textprompts[num]->page[metapagenum].picname[picid], 8); + // Doesn't use deh_strlcpy because it's not copying input. + strlcpy(textprompts[num]->page[pagenum].picname[picid], textprompts[num]->page[metapagenum].picname[picid], sizeof textprompts[num]->page[pagenum].picname[picid]); textprompts[num]->page[pagenum].pichires[picid] = textprompts[num]->page[metapagenum].pichires[picid]; textprompts[num]->page[pagenum].picduration[picid] = textprompts[num]->page[metapagenum].picduration[picid]; textprompts[num]->page[pagenum].xcoord[picid] = textprompts[num]->page[metapagenum].xcoord[picid]; @@ -2241,14 +2261,17 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum) picid = (UINT8)atoi(word + 3); if (picid > MAX_PROMPT_PICS || picid == 0) { - deh_warning("textpromptscene %d: unknown word '%s'", num, word); + deh_warning("Text prompt %d, page %d: pic number %d out of range (1 - %d)", + num + 1, pagenum + 1, picid, MAX_PROMPT_PICS); continue; } --picid; if (fastcmp(word+4, "NAME")) { - strncpy(textprompts[num]->page[pagenum].picname[picid], word2, 8); + deh_strlcpy(textprompts[num]->page[pagenum].picname[picid], word2, + sizeof textprompts[num]->page[pagenum].picname[picid], + va("Text prompt %d, page %d, pic %d: name", num + 1, pagenum + 1, picid + 1)); } else if (fastcmp(word+4, "HIRES")) { @@ -2267,12 +2290,16 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum) textprompts[num]->page[pagenum].ycoord[picid] = usi; } else - deh_warning("textpromptscene %d: unknown word '%s'", num, word); + { + deh_warning("Text prompt %d, page %d: unknown word '%s'", + num + 1, pagenum + 1, word); + } } else if (fastcmp(word, "MUSIC")) { - strncpy(textprompts[num]->page[pagenum].musswitch, word2, 7); - textprompts[num]->page[pagenum].musswitch[6] = 0; + deh_strlcpy(textprompts[num]->page[pagenum].musswitch, word2, + sizeof textprompts[num]->page[pagenum].musswitch, + va("Text prompt %d, page %d: music", num + 1, pagenum + 1)); } else if (fastcmp(word, "MUSICTRACK")) { @@ -2287,30 +2314,35 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum) { if (*word2 != '\0') { - INT32 j; + size_t j; // HACK: Add yellow control char now // so the drawing function doesn't call it repeatedly - char name[34]; + char name[32 + 2]; name[0] = '\x82'; // color yellow - name[1] = 0; - strncat(name, word2, 33); - name[33] = 0; + + // So that we still get a warning. + deh_strlcpy(name + 1, word2, (sizeof(name)) - 1, + va("Text prompt %d, page %d: name", num + 1, pagenum + 1)); // Replace _ with ' ' - for (j = 0; j < 32 && name[j]; j++) + for (j = 1; j < sizeof(name) && name[j]; j++) { if (name[j] == '_') name[j] = ' '; } - strncpy(textprompts[num]->page[pagenum].name, name, 32); + strlcpy(textprompts[num]->page[pagenum].name, name, sizeof(textprompts[num]->page[pagenum].name)); } else *textprompts[num]->page[pagenum].name = '\0'; } else if (fastcmp(word, "ICON")) - strncpy(textprompts[num]->page[pagenum].iconname, word2, 8); + { + deh_strlcpy(textprompts[num]->page[pagenum].iconname, word2, + sizeof textprompts[num]->page[pagenum].iconname, + va("Text prompt %d, page %d: icon", num + 1, pagenum + 1)); + } else if (fastcmp(word, "ICONALIGN")) textprompts[num]->page[pagenum].rightside = (i || word2[0] == 'R'); else if (fastcmp(word, "ICONFLIP")) @@ -2377,8 +2409,9 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum) { UINT8 metapagenum = usi - 1; - strncpy(textprompts[num]->page[pagenum].name, textprompts[num]->page[metapagenum].name, 32); - strncpy(textprompts[num]->page[pagenum].iconname, textprompts[num]->page[metapagenum].iconname, 8); + // Doesn't use deh_strlcpy because it's not copying input. + strlcpy(textprompts[num]->page[pagenum].name, textprompts[num]->page[metapagenum].name, sizeof textprompts[num]->page[pagenum].name); + strlcpy(textprompts[num]->page[pagenum].iconname, textprompts[num]->page[metapagenum].iconname, sizeof textprompts[num]->page[pagenum].iconname); textprompts[num]->page[pagenum].rightside = textprompts[num]->page[metapagenum].rightside; textprompts[num]->page[pagenum].iconflip = textprompts[num]->page[metapagenum].iconflip; textprompts[num]->page[pagenum].lines = textprompts[num]->page[metapagenum].lines; @@ -2393,17 +2426,25 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum) } } else if (fastcmp(word, "TAG")) - strncpy(textprompts[num]->page[pagenum].tag, word2, 33); + { + deh_strlcpy(textprompts[num]->page[pagenum].tag, word2, + sizeof textprompts[num]->page[pagenum].tag, + va("Text prompt %d, page %d: tag", num + 1, pagenum + 1)); + } else if (fastcmp(word, "NEXTPROMPT")) textprompts[num]->page[pagenum].nextprompt = usi; else if (fastcmp(word, "NEXTPAGE")) textprompts[num]->page[pagenum].nextpage = usi; else if (fastcmp(word, "NEXTTAG")) - strncpy(textprompts[num]->page[pagenum].nexttag, word2, 33); + { + deh_strlcpy(textprompts[num]->page[pagenum].nexttag, word2, + sizeof textprompts[num]->page[pagenum].nexttag, + va("Text prompt %d, page %d: nexttag", num + 1, pagenum + 1)); + } else if (fastcmp(word, "TIMETONEXT")) textprompts[num]->page[pagenum].timetonext = get_number(word2); else - deh_warning("PromptPage %d: unknown word '%s'", num, word); + deh_warning("Text prompt %d, page %d: unknown word '%s'", num + 1, pagenum + 1, word); } } while (!myfeof(f)); // finish when the line is empty @@ -2463,11 +2504,11 @@ void readtextprompt(MYFILE *f, INT32 num) readtextpromptpage(f, num, value - 1); } else - deh_warning("Page number %d out of range (1 - %d)", value, MAX_PAGES); + deh_warning("Prompt %d: page number %d out of range (1 - %d)", num + 1, value, MAX_PAGES); } else - deh_warning("Prompt %d: unknown word '%s', Page <num> expected.", num, word); + deh_warning("Prompt %d: unknown word '%s', Page <num> expected.", num + 1, word); } } while (!myfeof(f)); // finish when the line is empty @@ -2516,7 +2557,8 @@ void readmenu(MYFILE *f, INT32 num) if (fastcmp(word, "BACKGROUNDNAME")) { - strncpy(menupres[num].bgname, word2, 8); + deh_strlcpy(menupres[num].bgname, word2, + sizeof menupres[num].bgname, va("Menu %d: backgroundname", num)); titlechanged = true; } else if (fastcmp(word, "HIDEBACKGROUND")) @@ -2559,7 +2601,8 @@ void readmenu(MYFILE *f, INT32 num) } else if (fastcmp(word, "TITLEPICSNAME")) { - strncpy(menupres[num].ttname, word2, 9); + deh_strlcpy(menupres[num].ttname, word2, + sizeof menupres[num].ttname, va("Menu %d: titlepicsname", num)); titlechanged = true; } else if (fastcmp(word, "TITLEPICSX")) @@ -2595,8 +2638,8 @@ void readmenu(MYFILE *f, INT32 num) } else if (fastcmp(word, "MUSIC")) { - strncpy(menupres[num].musname, word2, 7); - menupres[num].musname[6] = 0; + deh_strlcpy(menupres[num].musname, word2, + sizeof menupres[num].musname, va("Menu %d: music", num)); titlechanged = true; } else if (fastcmp(word, "MUSICTRACK")) @@ -2785,7 +2828,7 @@ void readframe(MYFILE *f, INT32 num) size_t z; boolean found = false; size_t actionlen = strlen(word2) + 1; - char *actiontocompare = calloc(actionlen, 1); + char *actiontocompare = calloc(1, actionlen); strcpy(actiontocompare, word2); strupr(actiontocompare); @@ -3578,22 +3621,20 @@ void readmaincfg(MYFILE *f) if (fastcmp(word, "EXECCFG")) { if (strchr(word2, '.')) - COM_BufAddText(va("exec %s\n", word2)); + COM_ExecFile(word2, COM_LUA, false); else { lumpnum_t lumpnum; char newname[9]; - strncpy(newname, word2, 8); - - newname[8] = '\0'; + deh_strlcpy(newname, word2, sizeof newname, va("Maincfg: execcfg")); lumpnum = W_CheckNumForName(newname); if (lumpnum == LUMPERROR || W_LumpLength(lumpnum) == 0) CONS_Debug(DBG_SETUP, "SOC Error: script lump %s not found/not valid.\n", newname); else - COM_BufInsertText(W_CacheLumpNum(lumpnum, PU_CACHE)); + COM_BufInsertTextEx(W_CacheLumpNum(lumpnum, PU_CACHE), COM_LUA); } } @@ -3794,7 +3835,7 @@ void readmaincfg(MYFILE *f) } else if (fastcmp(word, "TITLEPICSNAME")) { - strncpy(ttname, word2, 9); + deh_strlcpy(ttname, word2, sizeof ttname, va("Maincfg: titlepicsname")); titlechanged = true; } else if (fastcmp(word, "TITLEPICSX")) @@ -3878,8 +3919,12 @@ void readmaincfg(MYFILE *f) savemoddata = true; // Also save a time attack folder - filenamelen = strlen(gamedatafilename)-4; // Strip off the extension - strncpy(timeattackfolder, gamedatafilename, min(filenamelen, sizeof (timeattackfolder))); + filenamelen = strlen(gamedatafilename); // Strip off the extension + if (filenamelen >= 4) + filenamelen -= 4; + if (filenamelen >= sizeof(timeattackfolder)) + filenamelen = sizeof(timeattackfolder)-1; + strncpy(timeattackfolder, gamedatafilename, filenamelen); timeattackfolder[min(filenamelen, sizeof (timeattackfolder) - 1)] = '\0'; strcpy(savegamename, timeattackfolder); @@ -3900,7 +3945,7 @@ void readmaincfg(MYFILE *f) } else if (fastcmp(word, "CUSTOMVERSION")) { - strlcpy(customversionstring, word2, sizeof (customversionstring)); + deh_strlcpy(customversionstring, word2, sizeof customversionstring, va("Maincfg: customversion")); //titlechanged = true; } else if (fastcmp(word, "BOOTMAP")) @@ -3915,6 +3960,7 @@ void readmaincfg(MYFILE *f) value = get_number(word2); bootmap = (INT16)value; + bootmapchanged = true; //titlechanged = true; } else if (fastcmp(word, "STARTCHAR")) @@ -4172,9 +4218,9 @@ spritenum_t get_sprite(const char *word) return atoi(word); if (fastncmp("SPR_",word,4)) word += 4; // take off the SPR_ - for (i = 0; i < NUMSPRITES; i++) - if (!sprnames[i][4] && memcmp(word,sprnames[i],4)==0) - return i; + i = R_GetSpriteNumByName(word); + if (i != NUMSPRITES) + return i; deh_warning("Couldn't find sprite named 'SPR_%s'",word); return SPR_NULL; } diff --git a/src/deh_tables.c b/src/deh_tables.c index fa86518e2e0eaf51555d6ee334a97cad22b3afa3..d7146325352fe35a873d4bcfe2229e394e0346c0 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -31,7 +31,7 @@ char *FREE_STATES[NUMSTATEFREESLOTS]; char *FREE_MOBJS[NUMMOBJFREESLOTS]; char *FREE_SKINCOLORS[NUMCOLORFREESLOTS]; -UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway. +bitarray_t used_spr[BIT_ARRAY_SIZE(NUMSPRITEFREESLOTS)]; // Sprite freeslots in use const char NIGHTSGRADE_LIST[] = { 'F', // GRADE_F @@ -1081,11 +1081,11 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_FANG_FIRE1", "S_FANG_FIRE2", "S_FANG_FIRE3", - "S_FANG_FIRE4", "S_FANG_FIREREPEAT", "S_FANG_LOBSHOT0", "S_FANG_LOBSHOT1", "S_FANG_LOBSHOT2", + "S_FANG_LOBSHOT3", "S_FANG_WAIT1", "S_FANG_WAIT2", "S_FANG_WALLHIT", @@ -1107,6 +1107,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_FANG_PINCHLOBSHOT2", "S_FANG_PINCHLOBSHOT3", "S_FANG_PINCHLOBSHOT4", + "S_FANG_PINCHLOBSHOT5", "S_FANG_DIE1", "S_FANG_DIE2", "S_FANG_DIE3", @@ -2245,6 +2246,10 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_LAMPPOST2", // with snow "S_HANGSTAR", "S_MISTLETOE", + "S_SSZTREE", + "S_SSZTREE_BRANCH", + "S_SSZTREE2", + "S_SSZTREE2_BRANCH", // Xmas GFZ bushes "S_XMASBLUEBERRYBUSH", "S_XMASBERRYBUSH", @@ -2252,11 +2257,9 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi // FHZ "S_FHZICE1", "S_FHZICE2", - "S_ROSY_IDLE1", - "S_ROSY_IDLE2", - "S_ROSY_IDLE3", - "S_ROSY_IDLE4", + "S_ROSY_IDLE", "S_ROSY_JUMP", + "S_ROSY_FALL", "S_ROSY_WALK", "S_ROSY_HUG", "S_ROSY_PAIN", @@ -2365,6 +2368,9 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_DBALL5", "S_DBALL6", "S_EGGSTATUE2", + "S_GINE", + "S_PPAL", + "S_PPEL", // Shield Orb "S_ARMA1", @@ -3249,6 +3255,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_MARIOBUSH2", "S_TOAD", + // Nights-specific stuff "S_NIGHTSDRONE_MAN1", "S_NIGHTSDRONE_MAN2", @@ -3552,6 +3559,12 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_YELLOWBRICKDEBRIS", "S_NAMECHECK", + + // LJ Knuckles + "S_OLDK_STND", + "S_OLDK_DIE0", + "S_OLDK_DIE1", + "S_OLDK_DIE2", }; // RegEx to generate this from info.h: ^\tMT_([^,]+), --> \t"MT_\1", @@ -4023,6 +4036,10 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_LAMPPOST2", // with snow "MT_HANGSTAR", "MT_MISTLETOE", + "MT_SSZTREE", + "MT_SSZTREE_BRANCH", + "MT_SSZTREE2", + "MT_SSZTREE2_BRANCH", // Xmas GFZ bushes "MT_XMASBLUEBERRYBUSH", "MT_XMASBERRYBUSH", @@ -4102,6 +4119,9 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t // Misc scenery "MT_DBALL", "MT_EGGSTATUE2", + "MT_GINE", + "MT_PPAL", + "MT_PPEL", // Powerup Indicators "MT_ELEMENTAL_ORB", // Elemental shield mobj @@ -4329,6 +4349,8 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_NAMECHECK", "MT_RAY", + + "MT_OLDK", }; const char *const MOBJFLAG_LIST[] = { @@ -4483,6 +4505,8 @@ const char *const PLAYERFLAG_LIST[] = { "CANCARRY", // Can carry? "FINISHED", + "SHIELDDOWN", // Shield has been pressed. + NULL // stop loop here. }; @@ -4834,6 +4858,7 @@ const char *const POWERS_LIST[] = { const char *const HUDITEMS_LIST[] = { "LIVES", + "INPUT", "RINGS", "RINGSNUM", @@ -5095,6 +5120,10 @@ struct int_const_s const INT_CONST[] = { {"RF_SHADOWEFFECTS",RF_SHADOWEFFECTS}, {"RF_DROPSHADOW",RF_DROPSHADOW}, + // Animation flags + {"SPR2F_MASK",SPR2F_MASK}, + {"SPR2F_SUPER",SPR2F_SUPER}, + // Level flags {"LF_SCRIPTISFILE",LF_SCRIPTISFILE}, {"LF_SPEEDMUSIC",LF_SPEEDMUSIC}, @@ -5229,6 +5258,7 @@ struct int_const_s const INT_CONST[] = { {"SF_MARIODAMAGE",SF_MARIODAMAGE}, {"SF_MACHINE",SF_MACHINE}, {"SF_DASHMODE",SF_DASHMODE}, + {"SF_FASTWAIT",SF_FASTWAIT}, {"SF_FASTEDGE",SF_FASTEDGE}, {"SF_MULTIABILITY",SF_MULTIABILITY}, {"SF_NONIGHTSROTATION",SF_NONIGHTSROTATION}, @@ -5577,8 +5607,7 @@ struct int_const_s const INT_CONST[] = { {"ROTAXIS_Z",ROTAXIS_Z}, // Buttons (ticcmd_t) - {"BT_WEAPONMASK",BT_WEAPONMASK}, //our first three bits. - {"BT_SHIELD",BT_SHIELD}, + {"BT_WEAPONMASK",BT_WEAPONMASK}, //our first four bits. {"BT_WEAPONNEXT",BT_WEAPONNEXT}, {"BT_WEAPONPREV",BT_WEAPONPREV}, {"BT_ATTACK",BT_ATTACK}, // shoot rings @@ -5758,7 +5787,9 @@ struct int_const_s const INT_CONST[] = { {"GC_WEPSLOT5",GC_WEPSLOT5}, {"GC_WEPSLOT6",GC_WEPSLOT6}, {"GC_WEPSLOT7",GC_WEPSLOT7}, - {"GC_SHIELD",GC_SHIELD}, + {"GC_WEPSLOT8",GC_WEPSLOT8}, + {"GC_WEPSLOT9",GC_WEPSLOT9}, + {"GC_WEPSLOT10",GC_WEPSLOT10}, {"GC_FIRE",GC_FIRE}, {"GC_FIRENORMAL",GC_FIRENORMAL}, {"GC_TOSSFLAG",GC_TOSSFLAG}, @@ -5798,6 +5829,10 @@ struct int_const_s const INT_CONST[] = { {"MB_SCROLLUP",MB_SCROLLUP}, {"MB_SCROLLDOWN",MB_SCROLLDOWN}, + // screen.h constants + {"BASEVIDWIDTH",BASEVIDWIDTH}, + {"BASEVIDHEIGHT",BASEVIDHEIGHT}, + {NULL,0} }; diff --git a/src/deh_tables.h b/src/deh_tables.h index 42716f9b4bd271c98aca83737f419670d862d7e5..94af2fa52ed89180d61a3c6eed0468229a727f34 100644 --- a/src/deh_tables.h +++ b/src/deh_tables.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -23,13 +23,13 @@ extern char *FREE_STATES[NUMSTATEFREESLOTS]; extern char *FREE_MOBJS[NUMMOBJFREESLOTS]; extern char *FREE_SKINCOLORS[NUMCOLORFREESLOTS]; -extern UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite freeslot in use! I would use ceil() here if I could, but it only saves 1 byte of memory anyway. +extern bitarray_t used_spr[BIT_ARRAY_SIZE(NUMSPRITEFREESLOTS)]; // Sprite freeslots in use #define initfreeslots() {\ - memset(FREE_STATES,0,sizeof(char *) * NUMSTATEFREESLOTS);\ - memset(FREE_MOBJS,0,sizeof(char *) * NUMMOBJFREESLOTS);\ - memset(FREE_SKINCOLORS,0,sizeof(char *) * NUMCOLORFREESLOTS);\ - memset(used_spr,0,sizeof(UINT8) * ((NUMSPRITEFREESLOTS / 8) + 1));\ + memset(FREE_STATES, 0, sizeof(FREE_STATES));\ + memset(FREE_MOBJS, 0, sizeof(FREE_MOBJS));\ + memset(FREE_SKINCOLORS, 0, sizeof(FREE_SKINCOLORS));\ + memset(used_spr, 0, sizeof(used_spr));\ memset(actionsoverridden, LUA_REFNIL, sizeof(actionsoverridden));\ } diff --git a/src/dehacked.c b/src/dehacked.c index 2050a117f67128dae4e40b992e5a49f1538457d7..470e468a0ba01c2d6bdda441dad3b195111cab2c 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -20,6 +20,7 @@ boolean deh_loaded = false; boolean gamedataadded = false; boolean titlechanged = false; boolean introchanged = false; +boolean bootmapchanged = false; static int dbg_line; static INT32 deh_num_warning = 0; @@ -192,11 +193,14 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) INT32 i; if (!deh_loaded) + { initfreeslots(); + deh_loaded = true; + } deh_num_warning = 0; - gamedataadded = titlechanged = introchanged = false; + gamedataadded = titlechanged = introchanged = bootmapchanged = false; // it doesn't test the version of SRB2 and version of dehacked file dbg_line = -1; // start at -1 so the first line is 0. @@ -587,7 +591,12 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) if (gamestate == GS_TITLESCREEN) { - if (introchanged) + if (bootmapchanged && bootmap) + { + menuactive = false; + D_MapChange(bootmap, gametype, ultimatemode, true, 0, false, false); + } + else if (introchanged) { menuactive = false; I_UpdateMouseGrab(); @@ -605,14 +614,10 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) if (deh_num_warning) { CONS_Printf(M_GetText("%d warning%s in the SOC lump\n"), deh_num_warning, deh_num_warning == 1 ? "" : "s"); - if (devparm) { + if (devparm) I_Error("%s%s",va(M_GetText("%d warning%s in the SOC lump\n"), deh_num_warning, deh_num_warning == 1 ? "" : "s"), M_GetText("See log.txt for details.\n")); - //while (!I_GetKey()) - //I_OsPolling(); - } } - deh_loaded = true; Z_Free(s); } diff --git a/src/dehacked.h b/src/dehacked.h index d985b14b031d648b35f991d03e6797ab72f52137..e7b9b46566411f51654f2b60270ff745b28b18c2 100644 --- a/src/dehacked.h +++ b/src/dehacked.h @@ -39,6 +39,7 @@ extern boolean deh_loaded; extern boolean gamedataadded; extern boolean titlechanged; extern boolean introchanged; +extern boolean bootmapchanged; #define MAX_ACTION_RECURSION 30 extern const char *luaactions[MAX_ACTION_RECURSION]; diff --git a/src/doomdef.h b/src/doomdef.h index 4c843f9e2f07ad58439d2dcd3200726e6d62fa4d..81ab7bbfb5505507f3df07b6b5709b6d4f995e81 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -82,6 +82,7 @@ #include "version.h" #include "doomtype.h" +#include <assert.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> @@ -167,7 +168,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 @@ -244,12 +245,12 @@ extern char logfilename[1024]; #define MAXPLAYERNAME 21 #define PLAYERSMASK (MAXPLAYERS-1) -// Don't make MAXSKINS higher than 256, since skin numbers are used with an -// UINT8 in various parts of the codebase. If you do anyway, the data type -// of those variables will have to be changed into at least an UINT16. +// Don't make MAXSKINS higher than 255, since skin numbers are used with an UINT8 in +// various parts of the codebase, and one number is reserved. If you do anyway, +// the data type of those variables will have to be changed into at least an UINT16. // This change must affect code such as demo recording and playback, // and the structure of some networking packets and commands. -#define MAXSKINS 256 +#define MAXSKINS 255 #define MAXCHARACTERSLOTS (MAXSKINS * 3) // Should be higher than MAXSKINS. #define COLORRAMPSIZE 16 @@ -552,7 +553,7 @@ void *M_Memcpy(void* dest, const void* src, size_t n); char *va(const char *format, ...) FUNCPRINTF; char *M_GetToken(const char *inputString); void M_UnGetToken(void); -void M_TokenizerOpen(const char *inputString); +void M_TokenizerOpen(const char *inputString, size_t len); void M_TokenizerClose(void); const char *M_TokenizerRead(UINT32 i); const char *M_TokenizerReadZDoom(UINT32 i); @@ -648,6 +649,7 @@ UINT32 quickncasehash (const char *p, size_t n) #else #define I_Assert(e) ((void)0) #endif +#define I_StaticAssert(e) static_assert(e, "Static assertion failed: " #e) // The character that separates pathnames. Forward slash on // most systems, but reverse solidus (\) on Windows. @@ -709,13 +711,6 @@ extern int /// Experimental attempts at preventing MF_PAPERCOLLISION objects from getting stuck in walls. //#define PAPER_COLLISIONCORRECTION -/// FINALLY some real clipping that doesn't make walls dissappear AND speeds the game up -/// (that was the original comment from SRB2CB, sadly it is a lie and actually slows game down) -/// on the bright side it fixes some weird issues with translucent walls -/// \note SRB2CB port. -/// SRB2CB itself ported this from PrBoom+ -#define NEWCLIP - /// OpenGL shaders #define GL_SHADERS diff --git a/src/doomstat.h b/src/doomstat.h index 6a2d6acf00f816804c1ec8830b69c9848deadcbe..b5b2984407cc7cf03d213de8cb70f3bab720fc88 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2025 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -165,7 +165,7 @@ extern boolean exitfadestarted; typedef struct { UINT8 numpics; - char picname[8][8]; + char picname[8][8+1]; UINT8 pichires[8]; char *text; UINT16 xcoord[8]; @@ -209,19 +209,19 @@ typedef struct UINT8 picmode; // sequence mode after displaying last pic, 0 = persist, 1 = loop, 2 = destroy UINT8 pictoloop; // if picmode == loop, which pic to loop to? UINT8 pictostart; // initial pic number to show - char picname[MAX_PROMPT_PICS][8]; + char picname[MAX_PROMPT_PICS][8+1]; UINT8 pichires[MAX_PROMPT_PICS]; UINT16 xcoord[MAX_PROMPT_PICS]; // gfx UINT16 ycoord[MAX_PROMPT_PICS]; // gfx UINT16 picduration[MAX_PROMPT_PICS]; - char musswitch[7]; + char musswitch[6+1]; UINT16 musswitchflags; UINT8 musicloop; - char tag[33]; // page tag - char name[34]; // narrator name, extra char for color - char iconname[8]; // narrator icon lump + char tag[32+1]; // page tag + char name[32+2]; // narrator name, extra char for color + char iconname[8+1]; // narrator icon lump boolean rightside; // narrator side, false = left, true = right boolean iconflip; // narrator flip icon horizontally UINT8 hidehud; // hide hud, 0 = show all, 1 = hide depending on prompt position (top/bottom), 2 = hide all @@ -233,7 +233,7 @@ typedef struct sfxenum_t textsfx; // sfx_ id for printing text UINT8 nextprompt; // next prompt to jump to, one-based. 0 = current prompt UINT8 nextpage; // next page to jump to, one-based. 0 = next page within prompt->numpages - char nexttag[33]; // next tag to jump to. If set, this overrides nextprompt and nextpage. + char nexttag[32+1]; // next tag to jump to. If set, this overrides nextprompt and nextpage. INT32 timetonext; // time in tics to jump to next page automatically. 0 = don't jump automatically char *text; } textpage_t; @@ -287,8 +287,8 @@ typedef struct // (This is not ifdeffed so the map header structure can stay identical, just in case.) typedef struct { - char option[32]; // 31 usable characters - char value[256]; // 255 usable characters. If this seriously isn't enough then wtf. + char option[31+1]; // 31 usable characters + char value[255+1]; // 255 usable characters. If this seriously isn't enough then wtf. } customoption_t; /** Map header information. @@ -296,69 +296,70 @@ typedef struct typedef struct { // The original eight, plus one. - char lvlttl[22]; ///< Level name without "Zone". (21 character limit instead of 32, 21 characters can display on screen max anyway) - char subttl[33]; ///< Subtitle for level - UINT8 actnum; ///< Act number or 0 for none. - UINT32 typeoflevel; ///< Combination of typeoflevel flags. - INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end. - INT16 marathonnext; ///< See nextlevel, but for Marathon mode. Necessary to support hub worlds ala SUGOI. - char keywords[33]; ///< Keywords separated by space to search for. 32 characters. - char musname[7]; ///< Music track to play. "" for no music. - UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore. - UINT32 muspos; ///< Music position to jump to. - char forcecharacter[17]; ///< (SKINNAMESIZE+1) Skin to switch to or "" to disable. - UINT8 weather; ///< 0 = sunny day, 1 = storm, 2 = snow, 3 = rain, 4 = blank, 5 = thunder w/o rain, 6 = rain w/o lightning, 7 = heat wave. - INT16 skynum; ///< Sky number to use. - INT16 skybox_scalex; ///< Skybox X axis scale. (0 = no movement, 1 = 1:1 movement, 16 = 16:1 slow movement, -4 = 1:4 fast movement, etc.) - INT16 skybox_scaley; ///< Skybox Y axis scale. - INT16 skybox_scalez; ///< Skybox Z axis scale. + char lvlttl[21+1]; ///< Level name without "Zone". (21 character limit instead of 32, 21 characters can display on screen max anyway) + char subttl[32+1]; ///< Subtitle for level + UINT8 actnum; ///< Act number or 0 for none. + UINT32 typeoflevel; ///< Combination of typeoflevel flags. + INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end. + INT16 marathonnext; ///< See nextlevel, but for Marathon mode. Necessary to support hub worlds ala SUGOI. + char keywords[32+1]; ///< Keywords separated by space to search for. 32 characters. + char musname[6+1]; ///< Music track to play. "" for no music. + UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore. + UINT32 muspos; ///< Music position to jump to. + char forcecharacter[16+1]; ///< (SKINNAMESIZE+1) Skin to switch to or "" to disable. + UINT8 weather; ///< 0 = sunny day, 1 = storm, 2 = snow, 3 = rain, 4 = blank, 5 = thunder w/o rain, 6 = rain w/o lightning, 7 = heat wave. + INT16 skynum; ///< Sky number to use. + INT16 skybox_scalex; ///< Skybox X axis scale. (0 = no movement, 1 = 1:1 movement, 16 = 16:1 slow movement, -4 = 1:4 fast movement, etc.) + INT16 skybox_scaley; ///< Skybox Y axis scale. + INT16 skybox_scalez; ///< Skybox Z axis scale. // Extra information. - char interscreen[8]; ///< 320x200 patch to display at intermission. - char runsoc[33]; ///< SOC to execute at start of level (32 character limit instead of 63) - char scriptname[33]; ///< Script to use when the map is switched to. (32 character limit instead of 191) - UINT8 precutscenenum; ///< Cutscene number to play BEFORE a level starts. - UINT8 cutscenenum; ///< Cutscene number to use, 0 for none. - INT16 countdown; ///< Countdown until level end? - UINT16 palette; ///< PAL lump to use on this map - UINT8 numlaps; ///< Number of laps in circuit mode, unless overridden. - SINT8 unlockrequired; ///< Is an unlockable required to play this level? -1 if no. - UINT8 levelselect; ///< Is this map available in the level select? If so, which map list is it available in? - SINT8 bonustype; ///< What type of bonus does this level have? (-1 for null.) - SINT8 maxbonuslives; ///< How many bonus lives to award at Intermission? (-1 for unlimited.) - - UINT16 levelflags; ///< LF_flags: merged booleans into one UINT16 for space, see below - UINT8 menuflags; ///< LF2_flags: options that affect record attack / nights mode menus - - char selectheading[22]; ///< Level select heading. Allows for controllable grouping. - UINT16 startrings; ///< Number of rings players start with. - INT32 sstimer; ///< Timer for special stages. - UINT32 ssspheres; ///< Sphere requirement in special stages. - fixed_t gravity; ///< Map-wide gravity. + char interscreen[8+1]; ///< 320x200 patch to display at intermission. + char runsoc[32+1]; ///< SOC to execute at start of level (32 character limit instead of 63) + char scriptname[32+1]; ///< Script to use when the map is switched to. (32 character limit instead of 191) + UINT8 precutscenenum; ///< Cutscene number to play BEFORE a level starts. + UINT8 cutscenenum; ///< Cutscene number to use, 0 for none. + INT16 countdown; ///< Countdown until level end? + UINT16 palette; ///< PAL lump to use on this map + UINT8 numlaps; ///< Number of laps in circuit mode, unless overridden. + SINT8 unlockrequired; ///< Is an unlockable required to play this level? -1 if no. + UINT8 levelselect; ///< Is this map available in the level select? If so, which map list is it available in? + SINT8 bonustype; ///< What type of bonus does this level have? (-1 for null.) + SINT8 maxbonuslives; ///< How many bonus lives to award at Intermission? (-1 for unlimited.) + + UINT16 levelflags; ///< LF_flags: merged booleans into one UINT16 for space, see below + UINT8 menuflags; ///< LF2_flags: options that affect record attack / nights mode menus + + char selectheading[21+1]; ///< Level select heading. Allows for controllable grouping. + UINT16 startrings; ///< Number of rings players start with. + INT32 sstimer; ///< Timer for special stages. + UINT32 ssspheres; ///< Sphere requirement in special stages. + fixed_t gravity; ///< Map-wide gravity. + UINT16 nightstimer[8]; ///< Per-mare time limits for NiGHTS stages. // Title card. - char ltzzpatch[9]; ///< Zig zag patch. - char ltzztext[9]; ///< Zig zag text. - char ltactdiamond[9]; ///< Act diamond. + char ltzzpatch[8+1]; ///< Zig zag patch. + char ltzztext[8+1]; ///< Zig zag text. + char ltactdiamond[8+1]; ///< Act diamond. // Freed animals stuff. - UINT8 numFlickies; ///< Internal. For freed flicky support. - mobjtype_t *flickies; ///< List of freeable flickies in this level. Allocated dynamically for space reasons. Be careful. + UINT8 numFlickies; ///< Internal. For freed flicky support. + mobjtype_t *flickies; ///< List of freeable flickies in this level. Allocated dynamically for space reasons. Be careful. // NiGHTS stuff. - UINT8 numGradedMares; ///< Internal. For grade support. - nightsgrades_t *grades; ///< NiGHTS grades. Allocated dynamically for space reasons. Be careful. + UINT8 numGradedMares; ///< Internal. For grade support. + nightsgrades_t *grades; ///< NiGHTS grades. Allocated dynamically for space reasons. Be careful. // Music stuff. - UINT32 musinterfadeout; ///< Fade out level music on intermission screen in milliseconds - char musintername[7]; ///< Intermission screen music. + UINT32 musinterfadeout; ///< Fade out level music on intermission screen in milliseconds + char musintername[6+1]; ///< Intermission screen music. - char muspostbossname[7]; ///< Post-bossdeath music. + char muspostbossname[6+1]; ///< Post-bossdeath music. UINT16 muspostbosstrack; ///< Post-bossdeath track. UINT32 muspostbosspos; ///< Post-bossdeath position UINT32 muspostbossfadein; ///< Post-bossdeath fade-in milliseconds. - SINT8 musforcereset; ///< Force resetmusic (-1 for default; 0 for force off; 1 for force on) + SINT8 musforcereset; ///< Force resetmusic (-1 for default; 0 for force off; 1 for force on) // Lua stuff. // (This is not ifdeffed so the map header structure can stay identical, just in case.) @@ -638,6 +639,7 @@ extern boolean singletics; extern consvar_t cv_timetic; // display high resolution timer extern consvar_t cv_powerupdisplay; // display powerups +extern consvar_t cv_showinput; // display input viewer outside of time attack extern consvar_t cv_showinputjoy; // display joystick in time attack extern consvar_t cv_forceskin; // force clients to use the server's skin extern consvar_t cv_downloading; // allow clients to downloading WADs. diff --git a/src/doomtype.h b/src/doomtype.h index 4070e346a1b13dd516a91504f056cebc4defb20d..415669ac479e928250d429bad545d34eff2770d5 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -108,6 +108,7 @@ char *nongnu_strcasestr(const char *in, const char *what); int startswith (const char *base, const char *tag); int endswith (const char *base, const char *tag); +char *xstrtok(char *line, const char *delims); #if defined (_WIN32) || defined (__HAIKU__) #define HAVE_DOSSTR_FUNCS diff --git a/src/dummy/i_system.c b/src/dummy/i_system.c index fe33cfe3ef46bdfecf38b3187d3946242b601551..99bfa9f363ca04c9281b17b0cffeda5cc4314586 100644 --- a/src/dummy/i_system.c +++ b/src/dummy/i_system.c @@ -206,5 +206,20 @@ void I_GetCursorPosition(INT32 *x, INT32 *y) (void)y; } +const char *I_GetSysName(void) +{ + return NULL; +} + +void I_SetTextInputMode(boolean active) +{ + (void)active; +} + +boolean I_GetTextInputMode(void) +{ + return false; +} + #include "../sdl/dosstr.c" diff --git a/src/dummy/i_video.c b/src/dummy/i_video.c index bb796b6767a1d55990209ba46cd8245377b013d9..2c998117accb71be25850438bdac2ee6c4db0509 100644 --- a/src/dummy/i_video.c +++ b/src/dummy/i_video.c @@ -5,8 +5,6 @@ rendermode_t rendermode = render_none; rendermode_t chosenrendermode = render_none; -boolean highcolor = false; - boolean allow_fullscreen = false; consvar_t cv_vidwait = CVAR_INIT ("vid_wait", "On", CV_SAVE, CV_OnOff, NULL); diff --git a/src/f_finale.c b/src/f_finale.c index cb64618535659f329bb357f65c2cec0bbe006b2d..c6d957292138915a6def4b975648e81e708cfd5a 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -229,6 +229,7 @@ static UINT8 cutscene_boostspeed = 0; char stjrintro[9] = "STJRI000"; static huddrawlist_h luahuddrawlist_title; +static huddrawlist_h luahuddrawlist_continue[2]; // // This alters the text string cutscene_disptext. @@ -297,7 +298,7 @@ static void F_NewCutscene(const char *basetext) cutscene_basetext = basetext; memset(cutscene_disptext,0,sizeof(cutscene_disptext)); cutscene_writeptr = cutscene_baseptr = 0; - cutscene_textspeed = 9; + cutscene_textspeed = 8; cutscene_textcount = TICRATE/2; } @@ -313,22 +314,22 @@ const char *introtext[NUMINTROSCENES]; static tic_t introscenetime[NUMINTROSCENES] = { 5*TICRATE, // STJr Presents - 11*TICRATE + (TICRATE/2), // Two months had passed since... - 15*TICRATE + (TICRATE/2), // As it was about to drain the rings... - 14*TICRATE, // What Sonic, Tails, and Knuckles... - 18*TICRATE, // About once every year, a strange... - 19*TICRATE + (TICRATE/2), // Curses! Eggman yelled. That ridiculous... - 19*TICRATE + (TICRATE/4), // It was only later that he had an idea... - 10*TICRATE + (TICRATE/2), // Before beginning his scheme, Eggman decided to give Sonic... - 16*TICRATE, // We're ready to fire in 15 seconds, the robot said... - 16*TICRATE, // Meanwhile, Sonic was tearing across the zones... + 10*TICRATE + (TICRATE/2), // Two months had passed since... + 12*TICRATE + ((TICRATE/4) * 3), // As it was about to drain the rings... + 12*TICRATE + (TICRATE/4), // What Sonic, Tails, and Knuckles... + 16*TICRATE, // About once every year, a strange... + 20*TICRATE + (TICRATE/2), // Curses! Eggman yelled. That ridiculous... + 18*TICRATE + (TICRATE/4), // It was only later that he had an idea... + 9*TICRATE + (TICRATE/2), // Before beginning his scheme, Eggman decided to give Sonic... + 14*TICRATE, // We're ready to fire in 15 seconds, the robot said... + 14*TICRATE + (TICRATE/2), // Meanwhile, Sonic was tearing across the zones... 16*TICRATE + (TICRATE/2), // Sonic knew he was getting closer to the city... - 17*TICRATE, // Greenflower City was gone... - 7*TICRATE, // You're not quite as dead as we thought, huh?... + 11*TICRATE + (TICRATE/2), // Greenflower City was gone... + 8*TICRATE, // You're not quite as dead as we thought, huh?... 8*TICRATE, // We'll see... let's give you a quick warm up... 18*TICRATE + (TICRATE/2), // Eggman took this as his cue and blasted off... - 16*TICRATE, // Easy! We go find Eggman and stop his... - 25*TICRATE, // I'm just finding what mission obje... + 15*TICRATE, // Easy! We go find Eggman and stop his... + 23*TICRATE, // I'm just finding what mission obje... }; // custom intros @@ -1064,12 +1065,12 @@ static const char *credits[] = { "Julio \"Chaos Zero 64\" Guir", "\"Hanicef\"", "\"Hannu_Hanhi\"", // For many OpenGL performance improvements! + "\"hazepastel\"", "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\"", @@ -1079,6 +1080,7 @@ static const char *credits[] = { "Louis-Antoine \"LJ Sonic\" de Moulins", // de Rochefort doesn't quite fit on the screen sorry lol "John \"JTE\" Muniz", "Colin \"Sonict\" Pfaff", + "\"Radicalicious\"", "James \"james\" Robert Roman", "Sean \"Sryder13\" Ryder", "Ehab \"Wolfy\" Saeed", @@ -1102,7 +1104,8 @@ static const char *credits[] = { "\"ChrispyPixels\"", "Paul \"Boinciel\" Clempson", "Sally \"TehRealSalt\" Cochenour", - "\"Dave Lite\"", + "\"DaJumpJump\"", // New Ringslinger graphics (2.2.14) + "\"DeltaSanic\"", "Desmond \"Blade\" DesJardins", "Sherman \"CoatRack\" DesJardins", "\"DirkTheHusky\"", @@ -1118,6 +1121,7 @@ static const char *credits[] = { "Alice \"Alacroix\" de Lemos", "Logan \"Hyperchaotix\" McCloud", "Alexander \"DrTapeworm\" Moench-Ford", + "\"orbitalviolet\"", // summit showdown hehehehe (aka Evertone) "Andrew \"Senku Niola\" Moran", "\"MotorRoach\"", "Phillip \"TelosTurntable\" Robinson", @@ -1126,6 +1130,7 @@ static const char *credits[] = { "David \"Instant Sonic\" Spencer Jr.", "\"SSNTails\"", "Daniel \"Inazuma\" Trinh", + "Samuel \"Spectorious\" Tuttle", "\"VelocitOni\"", "Jarrett \"JEV3\" Voight", "", @@ -1134,6 +1139,7 @@ static const char *credits[] = { "Victor \"VAdaPEGA\" Ara\x1Fjo", // Araújo "Malcolm \"RedXVI\" Brown", "Dave \"DemonTomatoDave\" Bulmer", + "Dan Cidoni", // aka Krabs "Paul \"Boinciel\" Clempson", "\"Cyan Helkaraxe\"", "Claire \"clairebun\" Ellis", @@ -1152,24 +1158,30 @@ static const char *credits[] = { "Colette \"fickleheart\" Bordelon", "Hank \"FuriousFox\" Brannock", "Matthew \"Fawfulfan\" Chapman", + "Dan Cidoni", // aka Krabs "Paul \"Boinciel\" Clempson", "Sally \"TehRealSalt\" Cochenour", "Desmond \"Blade\" DesJardins", "Sherman \"CoatRack\" DesJardins", "Ben \"Mystic\" Geyer", "Nathan \"Jazz\" Giroux", + "\"GomaTheMascar\"", "Vivian \"toaster\" Grannell", "James \"SeventhSentinel\" Hall", "Kepa \"Nev3r\" Iceta", "Thomas \"Shadow Hog\" Igoe", + "Mujamel \"MK\" Khan", "\"Kaito Sinclaire\"", "Alexander \"DrTapeworm\" Moench-Ford", + "\"Radicalicious\"", "\"Revan\"", "Anna \"QueenDelta\" Sandlin", "Wessel \"sphere\" Smit", "\"SSNTails\"", + "Aaron \"Othius\" Stojkov", "Rob Tisdell", "\"Torgo\"", + "Samuel \"Spectorious\" Tuttle", "Jarrett \"JEV3\" Voight", "Johnny \"Sonikku\" Wallbank", "Marco \"mazmazz\" Zafra", @@ -1281,6 +1293,9 @@ void F_CreditDrawer(void) UINT8 colornum; const UINT8 *colormap; + // compensation for y on non-green resolutions, used to prevent text from disappearing before reaching the top + UINT16 compy = (vid.height - (BASEVIDHEIGHT * vid.dup)) / 2; + if (players[consoleplayer].skincolor) colornum = players[consoleplayer].skincolor; else @@ -1312,17 +1327,17 @@ void F_CreditDrawer(void) y += 80<<FRACBITS; break; case 1: - if (y>>FRACBITS > -20) + if (y>>FRACBITS > -20-compy) V_DrawCreditString((160 - (V_CreditStringWidth(&credits[i][1])>>1))<<FRACBITS, y, 0, &credits[i][1]); y += 30<<FRACBITS; break; case 2: - if (y>>FRACBITS > -10) + if (y>>FRACBITS > -10-compy) V_DrawStringAtFixed((BASEVIDWIDTH-V_StringWidth(&credits[i][1], V_ALLOWLOWERCASE|V_YELLOWMAP))<<FRACBITS>>1, y, V_ALLOWLOWERCASE|V_YELLOWMAP, &credits[i][1]); y += 12<<FRACBITS; break; default: - if (y>>FRACBITS > -10) + if (y>>FRACBITS > -10-compy) V_DrawStringAtFixed(32<<FRACBITS, y, V_ALLOWLOWERCASE, credits[i]); y += 12<<FRACBITS; break; @@ -2332,7 +2347,7 @@ void F_SkyScroll(const char *patchname) } #define LOADTTGFX(arr, name, maxf) \ -lumpnum = W_CheckNumForName(name); \ +lumpnum = W_CheckNumForPatchName(name); \ if (lumpnum != LUMPERROR) \ { \ arr[0] = W_CachePatchName(name, PU_PATCH_LOWPRIORITY); \ @@ -2346,7 +2361,7 @@ else if (strlen(name) <= 6) \ { \ sprintf(&lumpname[cnt], "%.2hu", (UINT16)(i+1)); \ lumpname[8] = 0; \ - lumpnum = W_CheckNumForName(lumpname); \ + lumpnum = W_CheckNumForPatchName(lumpname); \ if (lumpnum != LUMPERROR) \ arr[i] = W_CachePatchName(lumpname, PU_PATCH_LOWPRIORITY); \ else \ @@ -3431,7 +3446,7 @@ void F_TitleScreenTicker(boolean run) { for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -3527,11 +3542,16 @@ void F_TitleDemoTicker(void) // ========== static skin_t *contskins[2]; -static UINT8 cont_spr2[2][6]; +static UINT16 cont_spr2[2][6]; static UINT8 *contcolormaps[2]; +static player_t *contPlayers[2]; +static skincolornum_t contColors[2]; // it's possible to change your skincolor in the continue screen, so this is for Lua to identify the skincolor that was used to cache the colormap +static boolean contOverrides[2]; void F_StartContinue(void) { + UINT8 i; + I_Assert(!netgame && !multiplayer); if (continuesInSession && players[consoleplayer].continues <= 0) @@ -3554,9 +3574,12 @@ void F_StartContinue(void) S_ChangeMusicInternal("_conti", false); S_StopSounds(); + contPlayers[0] = &players[consoleplayer]; contskins[0] = skins[players[consoleplayer].skin]; + cont_spr2[0][0] = P_GetSkinSprite2(contskins[0], SPR2_CNT1, NULL); cont_spr2[0][2] = contskins[0]->contangle & 7; + contColors[0] = players[consoleplayer].skincolor; contcolormaps[0] = R_GetTranslationColormap(players[consoleplayer].skin, players[consoleplayer].skincolor, GTC_CACHE); cont_spr2[0][4] = contskins[0]->sprites[cont_spr2[0][0]].numframes; cont_spr2[0][5] = max(1, contskins[0]->contspeed); @@ -3570,9 +3593,12 @@ void F_StartContinue(void) else // HACK secondplaya = 1; + contPlayers[1] = &players[secondplaya]; contskins[1] = skins[players[secondplaya].skin]; + cont_spr2[1][0] = P_GetSkinSprite2(contskins[1], SPR2_CNT4, NULL); cont_spr2[1][2] = (contskins[1]->contangle >> 3) & 7; + contColors[1] = players[secondplaya].skincolor; contcolormaps[1] = R_GetTranslationColormap(players[secondplaya].skin, players[secondplaya].skincolor, GTC_CACHE); cont_spr2[1][4] = contskins[1]->sprites[cont_spr2[1][0]].numframes; if (cont_spr2[1][0] == SPR2_CNT4) @@ -3592,6 +3618,58 @@ void F_StartContinue(void) timetonext = (11*TICRATE)+11; continuetime = 0; + + // allocate and/or clear Lua continue screen draw lists + for (i = 0; i < 2; i++) + { + if (!LUA_HUD_IsDrawListValid(luahuddrawlist_continue[i])) + { + LUA_HUD_DestroyDrawList(luahuddrawlist_continue[i]); + luahuddrawlist_continue[i] = LUA_HUD_CreateDrawList(); + } + LUA_HUD_ClearDrawList(luahuddrawlist_continue[i]); + contOverrides[i] = false; + } +} + +static void F_DestroyContinueDrawLists(void) +{ + UINT8 i; + for (i = 0; i < 2; i++) + { + LUA_HUD_DestroyDrawList(luahuddrawlist_continue[i]); + luahuddrawlist_continue[i] = NULL; + contOverrides[i] = false; + } +} + +static void F_DrawContinueCharacter(INT32 dx, INT32 dy, UINT8 n) +{ + spritedef_t *sprdef; + spriteframe_t *sprframe; + patch_t *patch; + + if (renderisnewtic) + { + LUA_HUD_ClearDrawList(luahuddrawlist_continue[n]); + contOverrides[n] = LUA_HookCharacterHUD + ( + HUD_HOOK(continue), luahuddrawlist_continue[n], contPlayers[n], + dx, dy, contskins[n]->highresscale, + (INT32)(contskins[n]->skinnum), cont_spr2[n][0], cont_spr2[n][1], cont_spr2[n][2] + 1, contColors[n], // add 1 to rotation to convert internal angle numbers (0-7) to WAD editor angle numbers (1-8) + imcontinuing ? continuetime : timetonext, imcontinuing + ); + } + + LUA_HUD_DrawList(luahuddrawlist_continue[n]); + + if (contOverrides[n] == true) + return; + + sprdef = &contskins[n]->sprites[cont_spr2[n][0]]; + sprframe = &sprdef->spriteframes[cont_spr2[n][1]]; + patch = W_CachePatchNum(sprframe->lumppat[cont_spr2[n][2]], PU_PATCH_LOWPRIORITY); + V_DrawFixedPatch((dx), (dy), contskins[n]->highresscale, (sprframe->flip & (1<<cont_spr2[n][2])) ? V_FLIP : 0, patch, contcolormaps[n]); } // @@ -3600,8 +3678,6 @@ void F_StartContinue(void) // void F_ContinueDrawer(void) { - spritedef_t *sprdef; - spriteframe_t *sprframe; patch_t *patch; INT32 i, x = (BASEVIDWIDTH>>1), ncontinues = players[consoleplayer].continues; char numbuf[9] = "CONTNUM*"; @@ -3646,7 +3722,7 @@ void F_ContinueDrawer(void) else if (ncontinues > 10) { if (!(continuetime & 1) || continuetime > 17) - V_DrawContinueIcon(x, 68, 0, players[consoleplayer].skin, players[consoleplayer].skincolor); + V_DrawContinueIcon(x, 68, 0, contskins[0]->skinnum, contColors[0]); V_DrawScaledPatch(x+12, 66, 0, stlivex); V_DrawRightAlignedString(x+38, 64, 0, va("%d",(imcontinuing ? ncontinues-1 : ncontinues))); @@ -3660,7 +3736,7 @@ void F_ContinueDrawer(void) { if (i == (ncontinues/2) && ((continuetime & 1) || continuetime > 17)) continue; - V_DrawContinueIcon(x - (i*30), 68, 0, players[consoleplayer].skin, players[consoleplayer].skincolor); + V_DrawContinueIcon(x - (i*30), 68, 0, contskins[0]->skinnum, contColors[0]); } x = BASEVIDWIDTH>>1; } @@ -3700,21 +3776,12 @@ void F_ContinueDrawer(void) else if (lift[0] > TICRATE+5) lift[0] = TICRATE+5; -#define drawchar(dx, dy, n) {\ - sprdef = &contskins[n]->sprites[cont_spr2[n][0]];\ - sprframe = &sprdef->spriteframes[cont_spr2[n][1]];\ - patch = W_CachePatchNum(sprframe->lumppat[cont_spr2[n][2]], PU_PATCH_LOWPRIORITY);\ - V_DrawFixedPatch((dx), (dy), contskins[n]->highresscale, (sprframe->flip & (1<<cont_spr2[n][2])) ? V_FLIP : 0, patch, contcolormaps[n]);\ - } - if (offsy < 0) - drawchar((BASEVIDWIDTH<<(FRACBITS-1))-offsx, ((140-lift[0])<<FRACBITS)-offsy, 0); + F_DrawContinueCharacter((BASEVIDWIDTH<<(FRACBITS-1))-offsx, ((140-lift[0])<<FRACBITS)-offsy, 0); if (contskins[1]) - drawchar((BASEVIDWIDTH<<(FRACBITS-1))+offsx, ((140-lift[1])<<FRACBITS)+offsy, 1); + F_DrawContinueCharacter((BASEVIDWIDTH<<(FRACBITS-1))+offsx, ((140-lift[1])<<FRACBITS)+offsy, 1); if (offsy >= 0) - drawchar((BASEVIDWIDTH<<(FRACBITS-1))-offsx, ((140-lift[0])<<FRACBITS)-offsy, 0); - -#undef drawchar + F_DrawContinueCharacter((BASEVIDWIDTH<<(FRACBITS-1))-offsx, ((140-lift[0])<<FRACBITS)-offsy, 0); if (timetonext > (11*TICRATE)) V_DrawFadeScreen(31, timetonext-(11*TICRATE)); @@ -3730,6 +3797,7 @@ void F_ContinueTicker(void) { if (!(--timetonext)) { + F_DestroyContinueDrawLists(); Command_ExitGame_f(); return; } @@ -3739,6 +3807,7 @@ void F_ContinueTicker(void) { if (++continuetime == 3*TICRATE) { + F_DestroyContinueDrawLists(); G_Continue(); return; } @@ -4058,7 +4127,7 @@ static void F_GetPageTextGeometry(UINT8 *pagelines, boolean *rightside, INT32 *b // reuse: // cutnum -> promptnum // scenenum -> pagenum - lumpnum_t iconlump = W_CheckNumForName(textprompts[cutnum]->page[scenenum].iconname); + lumpnum_t iconlump = W_CheckNumForPatchName(textprompts[cutnum]->page[scenenum].iconname); *pagelines = textprompts[cutnum]->page[scenenum].lines ? textprompts[cutnum]->page[scenenum].lines : 4; *rightside = (iconlump != LUMPERROR && textprompts[cutnum]->page[scenenum].rightside); @@ -4384,11 +4453,10 @@ void F_GetPromptPageByNamedTag(const char *tag, INT32 *promptnum, INT32 *pagenum if (!tag || !tag[0]) return; - strncpy(suffixedtag, tag, 33); - suffixedtag[32] = 0; + strncpy(suffixedtag, tag, sizeof(suffixedtag)-1); if (tutorialmode) - suffixed = F_GetTextPromptTutorialTag(suffixedtag, 33); + suffixed = F_GetTextPromptTutorialTag(suffixedtag, sizeof(suffixedtag)-1); for (*promptnum = 0 + tutorialpromptnum; *promptnum < MAX_PROMPTS; (*promptnum)++) { @@ -4451,7 +4519,7 @@ void F_TextPromptDrawer(void) if (!promptactive) return; - iconlump = W_CheckNumForName(textprompts[cutnum]->page[scenenum].iconname); + iconlump = W_CheckNumForPatchName(textprompts[cutnum]->page[scenenum].iconname); F_GetPageTextGeometry(&pagelines, &rightside, &boxh, &texth, &texty, &namey, &chevrony, &textx, &textr); // Draw gfx first diff --git a/src/f_finale.h b/src/f_finale.h index cb71775d05fc109aa4c3468c19cfe381eff72635..e12a81cc62509543b26a443a4f3e954d64a8d851 100644 --- a/src/f_finale.h +++ b/src/f_finale.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -96,7 +96,7 @@ typedef enum extern ttmode_enum ttmode; extern UINT8 ttscale; // ttmode user vars -extern char ttname[9]; +extern char ttname[8+1]; extern INT16 ttx; extern INT16 tty; extern INT16 ttloop; diff --git a/src/f_wipe.c b/src/f_wipe.c index 4bcfb029b2ed1815e895ff126127bb628c6709fb..1ea32d0ebe92e6fdcfda930356cb36959c7acb91 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -569,7 +569,7 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu) if (rendermode == render_opengl) { // send in the wipe type and wipe frame because we need to cache the graphic - HWR_DoTintedWipe(wipetype, wipeframe-1); + HWR_DoWipe(wipetype, wipeframe-1); } else #endif diff --git a/src/filesrch.c b/src/filesrch.c index 6429b6fa2f13b49979c7e5efa1614bf47cac02be..7f104f8cac58ba1e109605b5b0598f14b3a86ce6 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -444,12 +444,11 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name); #if defined(__linux__) || defined(__FreeBSD__) - if (dent->d_type == DT_UNKNOWN) - if (lstat(searchpath,&fsstat) == 0 && S_ISDIR(fsstat.st_mode)) + if (dent->d_type == DT_UNKNOWN || dent->d_type == DT_LNK) + if (stat(searchpath,&fsstat) == 0 && S_ISDIR(fsstat.st_mode)) dent->d_type = DT_DIR; // Linux and FreeBSD has a special field for file type on dirent, so use that to speed up lookups. - // FIXME: should we also follow symlinks? if (dent->d_type == DT_DIR && depthleft) #else if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat @@ -699,6 +698,15 @@ static void initdirpath(char *dirpath, size_t *dirpathindex, int depthleft) dirpathindex[depthleft]--; } +//sortdir by name? +static int lumpnamecompare(const void *A, const void *B) +{ + const lumpinfo_t *pA = A; + const lumpinfo_t *pB = B; + return strcmp((pA->fullname), (pB->fullname)); + +} + lumpinfo_t *getdirectoryfiles(const char *path, UINT16 *nlmp, UINT16 *nfolders) { DIR **dirhandle; @@ -889,6 +897,9 @@ lumpinfo_t *getdirectoryfiles(const char *path, UINT16 *nlmp, UINT16 *nfolders) free(dirpathindex); free(dirhandle); + //sort files and directories + qsort (lumpinfo, numlumps, sizeof(lumpinfo_t), lumpnamecompare); + (*nlmp) = numlumps; return lumpinfo; } @@ -1179,13 +1190,13 @@ boolean preparefilemenu(boolean samedepth) size_t i; if (filenamebuf == NULL) - filenamebuf = calloc(sizeof(char) * MAX_WADPATH, numwadfiles); + filenamebuf = calloc(numwadfiles, sizeof(char) * MAX_WADPATH); for (i = 0; i < numwadfiles; i++) { if (!filenamebuf[i][0]) { - strncpy(filenamebuf[i], wadfiles[i]->filename, MAX_WADPATH); + strncpy(filenamebuf[i], wadfiles[i]->filename, MAX_WADPATH-1); filenamebuf[i][MAX_WADPATH - 1] = '\0'; nameonly(filenamebuf[i]); } diff --git a/src/g_demo.c b/src/g_demo.c index f64f34168efd8286ba21199841be95bc60fceb3d..479020905ee9bb12f78fda614b4da70d13c75bbc 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -67,6 +67,8 @@ static UINT8 *metalbuffer = NULL; static UINT8 *metal_p; static UINT16 metalversion; +consvar_t cv_resyncdemo = CVAR_INIT("resyncdemo", "On", 0, CV_OnOff, NULL); + // extra data stuff (events registered this frame while recording) static struct { UINT8 flags; // EZT flags @@ -409,7 +411,7 @@ void G_WriteGhostTic(mobj_t *ghost) { oldghost.sprite2 = ghost->sprite2; ziptic |= GZT_SPR2; - WRITEUINT8(demo_p,oldghost.sprite2); + WRITEUINT16(demo_p,oldghost.sprite2); } // Check for sprite set changes @@ -509,7 +511,7 @@ void G_WriteGhostTic(mobj_t *ghost) temp = ghost->player->followmobj->z-ghost->z; WRITEFIXED(demo_p,temp); if (followtic & FZT_SKIN) - WRITEUINT8(demo_p,ghost->player->followmobj->sprite2); + WRITEUINT16(demo_p,ghost->player->followmobj->sprite2); WRITEUINT16(demo_p,ghost->player->followmobj->sprite); WRITEUINT8(demo_p,(ghost->player->followmobj->frame & FF_FRAMEMASK)); WRITEUINT16(demo_p,ghost->player->followmobj->color); @@ -545,6 +547,9 @@ void G_ConsGhostTic(void) testmo = players[0].mo; + if (P_MobjWasRemoved(testmo)) + return; // No valid mobj exists, probably because of unexpected quit + // Grab ghost data. ziptic = READUINT8(demo_p); if (ziptic & GZT_XYZ) @@ -571,7 +576,7 @@ void G_ConsGhostTic(void) if (ziptic & GZT_FRAME) demo_p++; if (ziptic & GZT_SPR2) - demo_p++; + demo_p += (demoversion < 0x0011) ? sizeof(UINT8) : sizeof(UINT16); if (ziptic & GZT_EXTRA) { // But wait, there's more! @@ -605,7 +610,7 @@ void G_ConsGhostTic(void) mobj = NULL; for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mobj = (mobj_t *)th; if (mobj->type == (mobjtype_t)type && mobj->x == x && mobj->y == y && mobj->z == z) @@ -640,7 +645,7 @@ void G_ConsGhostTic(void) // momx, momy and momz demo_p += (demoversion < 0x000e) ? sizeof(INT16) * 3 : sizeof(fixed_t) * 3; if (followtic & FZT_SKIN) - demo_p++; + demo_p += (demoversion < 0x0011) ? sizeof(UINT8) : sizeof(UINT16); demo_p += sizeof(UINT16); demo_p++; demo_p += (demoversion==0x000c) ? 1 : sizeof(UINT16); @@ -660,11 +665,14 @@ void G_ConsGhostTic(void) CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); demosynced = false; - P_UnsetThingPosition(testmo); - testmo->x = oldghost.x; - testmo->y = oldghost.y; - P_SetThingPosition(testmo); - testmo->z = oldghost.z; + if (cv_resyncdemo.value) + { + P_UnsetThingPosition(testmo); + testmo->x = oldghost.x; + testmo->y = oldghost.y; + P_SetThingPosition(testmo); + testmo->z = oldghost.z; + } } if (*demo_p == DEMOMARKER) @@ -722,7 +730,7 @@ void G_GhostTicker(void) if (ziptic & GZT_FRAME) g->oldmo.frame = READUINT8(g->p); if (ziptic & GZT_SPR2) - g->oldmo.sprite2 = READUINT8(g->p); + g->oldmo.sprite2 = (g->version < 0x0011) ? READUINT8(g->p) : READUINT16(g->p); // Update ghost P_UnsetThingPosition(g->mo); @@ -771,7 +779,7 @@ void G_GhostTicker(void) { g->mo->destscale = READFIXED(g->p); if (g->mo->destscale != g->mo->scale) - P_SetScale(g->mo, g->mo->destscale); + P_SetScale(g->mo, g->mo->destscale, false); } if (xziptic & EZT_THOKMASK) { // Let's only spawn ONE of these per frame, thanks. @@ -810,7 +818,7 @@ void G_GhostTicker(void) mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<<FF_TRANSSHIFT; mobj->color = g->mo->color; mobj->skin = g->mo->skin; - P_SetScale(mobj, (mobj->destscale = g->mo->scale)); + P_SetScale(mobj, g->mo->scale, true); if (type == MT_THOK) // spintrail-specific modification for MT_THOK { @@ -926,7 +934,7 @@ void G_GhostTicker(void) else follow->destscale = g->mo->destscale; if (follow->destscale != follow->scale) - P_SetScale(follow, follow->destscale); + P_SetScale(follow, follow->destscale, false); P_UnsetThingPosition(follow); temp = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p); @@ -937,7 +945,7 @@ void G_GhostTicker(void) follow->z = g->mo->z + temp; P_SetThingPosition(follow); if (followtic & FZT_SKIN) - follow->sprite2 = READUINT8(g->p); + follow->sprite2 = (g->version < 0x0011) ? READUINT8(g->p) : READUINT16(g->p); else follow->sprite2 = 0; follow->sprite = READUINT16(g->p); @@ -1052,7 +1060,7 @@ void G_ReadMetalTic(mobj_t *metal) oldmetal.frame = G_ConvertOldFrameFlags(oldmetal.frame); } if (ziptic & GZT_SPR2) - oldmetal.sprite2 = READUINT8(metal_p); + oldmetal.sprite2 = (metalversion < 0x0011) ? READUINT8(metal_p) : READUINT16(metal_p); // Set movement, position, and angle // oldmetal contains where you're supposed to be. @@ -1079,7 +1087,7 @@ void G_ReadMetalTic(mobj_t *metal) { metal->destscale = READFIXED(metal_p); if (metal->destscale != metal->scale) - P_SetScale(metal, metal->destscale); + P_SetScale(metal, metal->destscale, false); } if (xziptic & EZT_THOKMASK) { // Let's only spawn ONE of these per frame, thanks. @@ -1117,7 +1125,7 @@ void G_ReadMetalTic(mobj_t *metal) mobj->angle = metal->angle; mobj->color = metal->color; mobj->skin = metal->skin; - P_SetScale(mobj, (mobj->destscale = metal->scale)); + P_SetScale(mobj, metal->scale, true); if (type == MT_THOK) // spintrail-specific modification for MT_THOK { @@ -1184,7 +1192,7 @@ void G_ReadMetalTic(mobj_t *metal) else follow->destscale = metal->destscale; if (follow->destscale != follow->scale) - P_SetScale(follow, follow->destscale); + P_SetScale(follow, follow->destscale, false); P_UnsetThingPosition(follow); temp = (metalversion < 0x000e) ? READINT16(metal_p)<<8 : READFIXED(metal_p); @@ -1195,7 +1203,7 @@ void G_ReadMetalTic(mobj_t *metal) follow->z = metal->z + temp; P_SetThingPosition(follow); if (followtic & FZT_SKIN) - follow->sprite2 = READUINT8(metal_p); + follow->sprite2 = (metalversion < 0x0011) ? READUINT8(metal_p) : READUINT16(metal_p); else follow->sprite2 = 0; follow->sprite = READUINT16(metal_p); @@ -1203,7 +1211,7 @@ void G_ReadMetalTic(mobj_t *metal) if (metalversion < 0x000f) follow->frame = G_ConvertOldFrameFlags(follow->frame); follow->angle = metal->angle; - follow->color = (metalversion==0x000c) ? READUINT8(metal_p) : READUINT16(metal_p); + follow->color = (metalversion == 0x000c) ? READUINT8(metal_p) : READUINT16(metal_p); if (!(followtic & FZT_SPAWNED)) { @@ -1304,7 +1312,7 @@ void G_WriteMetalTic(mobj_t *metal) { oldmetal.sprite2 = metal->sprite2; ziptic |= GZT_SPR2; - WRITEUINT8(demo_p,oldmetal.sprite2); + WRITEUINT16(demo_p,oldmetal.sprite2); } // Check for sprite set changes @@ -1379,7 +1387,7 @@ void G_WriteMetalTic(mobj_t *metal) temp = metal->player->followmobj->z-metal->z; WRITEFIXED(demo_p,temp); if (followtic & FZT_SKIN) - WRITEUINT8(demo_p,metal->player->followmobj->sprite2); + WRITEUINT16(demo_p,metal->player->followmobj->sprite2); WRITEUINT16(demo_p,metal->player->followmobj->sprite); WRITEUINT32(demo_p,metal->player->followmobj->frame); // NOT & FF_FRAMEMASK here, so 32 bits WRITEUINT16(demo_p,metal->player->followmobj->color); @@ -1442,6 +1450,7 @@ void G_BeginRecording(void) char *filename; UINT16 totalfiles; UINT8 *m; + save_t savebuffer; if (demo_p) return; @@ -1591,7 +1600,11 @@ void G_BeginRecording(void) } // Save netvar data - CV_SaveDemoVars(&demo_p); + savebuffer.buf = demo_p; + savebuffer.size = demoend - demo_p; + savebuffer.pos = 0; + CV_SaveDemoVars(&savebuffer); + demo_p = &savebuffer.buf[savebuffer.pos]; memset(&oldcmd,0,sizeof(oldcmd)); memset(&oldghost,0,sizeof(oldghost)); @@ -1650,7 +1663,7 @@ static void G_LoadDemoExtraFiles(UINT8 **pp, UINT16 this_demo_version) UINT16 totalfiles; char filename[MAX_WADPATH]; UINT8 md5sum[16]; - filestatus_t ncs; + filestatus_t ncs = FS_NOTFOUND; boolean toomany = false; boolean alreadyloaded; UINT16 i, j; @@ -2224,10 +2237,24 @@ void G_DoPlayDemo(char *defdemoname) // net var data #ifdef OLD22DEMOCOMPAT if (demoversion < 0x000d) - CV_LoadOldDemoVars(&demo_p); + { + save_t savebuffer; + savebuffer.buf = demo_p; + savebuffer.size = demoend - demo_p; + savebuffer.pos = 0; + CV_LoadOldDemoVars(&savebuffer); + demo_p = &savebuffer.buf[savebuffer.pos]; + } else #endif - CV_LoadDemoVars(&demo_p); + { + save_t savebuffer; + savebuffer.buf = demo_p; + savebuffer.size = demoend - demo_p; + savebuffer.pos = 0; + CV_LoadDemoVars(&savebuffer); + demo_p = &savebuffer.buf[savebuffer.pos]; + } // Sigh ... it's an empty demo. if (*demo_p == DEMOMARKER) @@ -2603,10 +2630,10 @@ void G_AddGhost(char *defdemoname) } gh->oldmo.color = gh->mo->color; - gh->mo->state = states+S_PLAY_STND; + gh->mo->state = &states[S_PLAY_STND]; gh->mo->sprite = gh->mo->state->sprite; - gh->mo->sprite2 = (gh->mo->state->frame & FF_FRAMEMASK); - //gh->mo->frame = tr_trans30<<FF_TRANSSHIFT; + gh->mo->sprite2 = P_GetStateSprite2(gh->mo->state); + gh->mo->frame = (gh->mo->state->frame & ~FF_FRAMEMASK) | P_GetSprite2StateFrame(gh->mo->state); gh->mo->flags2 |= MF2_DONTDRAW; gh->fadein = (9-3)*6; // fade from invisible to trans30 over as close to 35 tics as possible gh->mo->tics = -1; @@ -2665,7 +2692,7 @@ void G_DoPlayMetal(void) // find metal sonic for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo = (mobj_t *)th; diff --git a/src/g_demo.h b/src/g_demo.h index e8c0c8d956187161ea5bbaffe9c145c764a40ba4..d7c68287170f6f76a66f14b8980150167872cea0 100644 --- a/src/g_demo.h +++ b/src/g_demo.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -35,6 +35,7 @@ typedef enum } demo_file_override_e; extern demo_file_override_e demofileoverride; +extern consvar_t cv_resyncdemo; // Quit after playing a demo from cmdline. extern boolean singledemo; diff --git a/src/g_game.c b/src/g_game.c index bf2691be6cc949f2144f6848312d2dc1d7a3fcb7..23ba9f39ed4ea8338342e013cafbfa8065a37798 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -256,8 +256,6 @@ boolean precache = true; // if true, load all graphics at start INT16 prevmap, nextmap; -static UINT8 *savebuffer; - // Analog Control static void UserAnalog_OnChange(void); static void UserAnalog2_OnChange(void); @@ -1337,7 +1335,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) #if NUM_WEAPONS > 10 "Add extra inputs to g_input.h/gamecontrols_e" #endif - //use the three avaliable bits to determine the weapon. + //use the four avaliable bits to determine the weapon. cmd->buttons &= ~BT_WEAPONMASK; for (i = 0; i < NUM_WEAPONS; ++i) if (PLAYERINPUTDOWN(ssplayer, GC_WEPSLOT1 + i)) @@ -1355,14 +1353,9 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) axis = PlayerJoyAxis(ssplayer, JA_FIRENORMAL); if (PLAYERINPUTDOWN(ssplayer, GC_FIRENORMAL) || (usejoystick && axis > 0)) cmd->buttons |= BT_FIRENORMAL; - - // Toss flag button + if (PLAYERINPUTDOWN(ssplayer, GC_TOSSFLAG)) cmd->buttons |= BT_TOSSFLAG; - - // Shield button - if (PLAYERINPUTDOWN(ssplayer, GC_SHIELD)) - cmd->buttons |= BT_SHIELD; // Lua scriptable buttons if (PLAYERINPUTDOWN(ssplayer, GC_CUSTOM1)) @@ -1377,6 +1370,13 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) if (PLAYERINPUTDOWN(ssplayer, GC_SPIN) || (usejoystick && axis > 0)) cmd->buttons |= BT_SPIN; + if (gamestate == GS_INTRO) // prevent crash in intro + { + cmd->angleturn = ticcmd_oldangleturn[forplayer]; + cmd->aiming = G_ClipAimingPitch(myaiming); + return; + } + // Centerview can be a toggle in simple mode! { static boolean last_centerviewdown[2], centerviewhold[2]; // detect taps for toggle behavior @@ -1411,7 +1411,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) ticcmd_centerviewdown[forplayer] = true; } - else if (ticcmd_centerviewdown[forplayer]) + else if (ticcmd_centerviewdown[forplayer] || (leveltime < 5)) { if (controlstyle == CS_SIMPLE) { @@ -1426,6 +1426,9 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) { if ( P_MobjWasRemoved(ticcmd_ztargetfocus[forplayer]) || + (leveltime < 5) || + (player->playerstate != PST_LIVE) || + player->exiting || !ticcmd_ztargetfocus[forplayer]->health || (ticcmd_ztargetfocus[forplayer]->type == MT_EGGMOBILE3 && !ticcmd_ztargetfocus[forplayer]->movecount) // Sea Egg is moving around underground and shouldn't be tracked ) @@ -1457,7 +1460,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) P_SetTarget(&newtarget->target, ticcmd_ztargetfocus[forplayer]); newtarget->drawonlyforplayer = player; // Hide it from the other player in splitscreen, and yourself when spectating - if (player->mo && P_AproxDistance( + if (player->mo && R_PointToDist2(0, 0, player->mo->x - ticcmd_ztargetfocus[forplayer]->x, player->mo->y - ticcmd_ztargetfocus[forplayer]->y ) > 50*player->mo->scale) @@ -1920,6 +1923,8 @@ void G_DoLoadLevel(boolean resetplayer) // void G_StartTitleCard(void) { + ST_stopTitleCard(); + // The title card has been disabled for this map. // Oh well. if (!G_IsTitleCardAvailable()) @@ -2608,6 +2613,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) boolean spectator; boolean outofcoop; boolean removing; + boolean muted; INT16 bot; SINT8 pity; INT16 rings; @@ -2625,6 +2631,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) spectator = players[player].spectator; outofcoop = players[player].outofcoop; removing = players[player].removing; + muted = players[player].muted; pflags = (players[player].pflags & (PF_FLIPCAM|PF_ANALOGMODE|PF_DIRECTIONCHAR|PF_AUTOBRAKE|PF_TAGIT|PF_GAMETYPEOVER)); playerangleturn = players[player].angleturn; oldrelangleturn = players[player].oldrelangleturn; @@ -2702,6 +2709,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->spectator = spectator; p->outofcoop = outofcoop; p->removing = removing; + p->muted = muted; p->angleturn = playerangleturn; p->oldrelangleturn = oldrelangleturn; @@ -2758,7 +2766,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->pflags |= PF_SPINDOWN; p->pflags |= PF_ATTACKDOWN; p->pflags |= PF_JUMPDOWN; - p->pflags |= PF_SHIELDDOWN; p->playerstate = PST_LIVE; p->panim = PA_IDLE; // standing animation @@ -3053,7 +3060,7 @@ void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo) // scan all thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -3336,13 +3343,13 @@ void G_AddPlayer(INT32 playernum) p->playerstate = PST_REBORN; - p->height = mobjinfo[MT_PLAYER].height; + p->height = skins[p->skin]->height; if (G_GametypeUsesLives() || ((netgame || multiplayer) && (gametyperules & GTR_FRIENDLY))) p->lives = cv_startinglives.value; if ((countplayers && !notexiting) || G_IsSpecialStage(gamemap)) - P_DoPlayerExit(p); + P_DoPlayerExit(p, false); } boolean G_EnoughPlayersFinished(void) @@ -3875,12 +3882,13 @@ static INT16 RandMap(UINT32 tolflags, INT16 pprevmap) // // G_UpdateVisited // -static void G_UpdateVisited(gamedata_t *data, player_t *player, boolean silent) +static void G_UpdateVisited(gamedata_t *data, player_t *player, boolean global) { // Update visitation flags? if (!demoplayback && G_CoopGametype() // Campaign mode - && !stagefailed) // Did not fail the stage + && !stagefailed // Did not fail the stage + && (global || player->pflags & PF_FINISHED)) // Actually beat the stage { UINT8 earnedEmblems; UINT16 totalrings = 0; @@ -3918,12 +3926,12 @@ static void G_UpdateVisited(gamedata_t *data, player_t *player, boolean silent) data->mapvisited[gamemap-1] |= MV_ALLEMERALDS; } - if ((earnedEmblems = M_CompletionEmblems(data)) && !silent) + if ((earnedEmblems = M_CompletionEmblems(data)) && !global) { CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for level completion.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : ""); } - if (silent) + if (global) { M_CheckLevelEmblems(data); } @@ -4011,7 +4019,7 @@ INT16 G_GetNextMap(boolean ignoretokens, boolean silent) INT32 i; INT16 newmapnum; boolean spec = G_IsSpecialStage(gamemap); - + // go to next level // newmapnum is 0-based, unlike gamemap if (nextmapoverride != 0) @@ -4115,7 +4123,7 @@ INT16 G_GetNextMap(boolean ignoretokens, boolean silent) if (spec && (!gottoken || ignoretokens) && !nextmapoverride) newmapnum = lastmap; // Exiting from a special stage? Go back to the game. Tails 08-11-2001 - + if (!(gametyperules & GTR_CAMPAIGN)) { if (cv_advancemap.value == 0) // Stay on same map. @@ -4123,7 +4131,7 @@ INT16 G_GetNextMap(boolean ignoretokens, boolean silent) else if (cv_advancemap.value == 2) // Go to random map. newmapnum = RandMap(G_TOLFlag(gametype_to_use), prevmap); } - + return newmapnum; } @@ -4133,7 +4141,7 @@ INT16 G_GetNextMap(boolean ignoretokens, boolean silent) static void G_DoCompleted(void) { INT32 i; - + tokenlist = 0; // Reset the list if (modeattacking && pausedelay) @@ -4161,7 +4169,7 @@ static void G_DoCompleted(void) //Get and set prevmap/nextmap prevmap = (INT16)(gamemap-1); nextmap = G_GetNextMap(false, false); - + automapactive = false; // We are committed to this map now. @@ -4379,7 +4387,7 @@ void G_LoadGameSettings(void) // Loads the main data file, which stores information such as emblems found, etc. void G_LoadGameData(gamedata_t *data) { - size_t length; + save_t savebuffer; INT32 i, j; UINT32 versionID; @@ -4421,18 +4429,18 @@ void G_LoadGameData(gamedata_t *data) return; } - length = FIL_ReadFile(va(pandf, srb2home, gamedatafilename), &savebuffer); - if (!length) + savebuffer.size = FIL_ReadFile(va(pandf, srb2home, gamedatafilename), &savebuffer.buf); + if (!savebuffer.size) { // No gamedata. We can save a new one. data->loaded = true; return; } - save_p = savebuffer; + savebuffer.pos = 0; // Version check - versionID = READUINT32(save_p); + versionID = P_ReadUINT32(&savebuffer); if (versionID != GAMEDATA_ID #ifdef COMPAT_GAMEDATA_ID // backwards compat behavior && versionID != COMPAT_GAMEDATA_ID @@ -4443,8 +4451,7 @@ void G_LoadGameData(gamedata_t *data) if (strcmp(srb2home,".")) gdfolder = srb2home; - Z_Free(savebuffer); - save_p = NULL; + Z_Free(savebuffer.buf); I_Error("Game data is from another version of SRB2.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder); } @@ -4456,14 +4463,14 @@ void G_LoadGameData(gamedata_t *data) } #endif - data->totalplaytime = READUINT32(save_p); + data->totalplaytime = P_ReadUINT32(&savebuffer); #ifdef COMPAT_GAMEDATA_ID if (versionID == COMPAT_GAMEDATA_ID) { // We'll temporarily use the old condition when loading an older file. // The proper mod-specific hash will get saved in afterwards. - boolean modded = READUINT8(save_p); + boolean modded = P_ReadUINT8(&savebuffer); if (modded && !savemoddata) { @@ -4483,13 +4490,13 @@ void G_LoadGameData(gamedata_t *data) strcpy(currentfilename, gamedatafilename); STRBUFCPY(backupfilename, strcat(currentfilename, bak)); - FIL_WriteFile(va(pandf, srb2home, backupfilename), savebuffer, length); + FIL_WriteFile(va(pandf, srb2home, backupfilename), &savebuffer.buf, savebuffer.size); } else #endif { // Quick & dirty hash for what mod this save file is for. - UINT32 modID = READUINT32(save_p); + UINT32 modID = P_ReadUINT32(&savebuffer); UINT32 expectedID = quickncasehash(timeattackfolder, sizeof timeattackfolder); if (modID != expectedID) @@ -4501,50 +4508,50 @@ void G_LoadGameData(gamedata_t *data) // TODO put another cipher on these things? meh, I don't care... for (i = 0; i < NUMMAPS; i++) - if ((data->mapvisited[i] = READUINT8(save_p)) > MV_MAX) + if ((data->mapvisited[i] = P_ReadUINT8(&savebuffer)) > MV_MAX) goto datacorrupt; // To save space, use one bit per collected/achieved/unlocked flag for (i = 0; i < max_emblems;) { - rtemp = READUINT8(save_p); + rtemp = P_ReadUINT8(&savebuffer); for (j = 0; j < 8 && j+i < max_emblems; ++j) data->collected[j+i] = ((rtemp >> j) & 1); i += j; } for (i = 0; i < max_extraemblems;) { - rtemp = READUINT8(save_p); + rtemp = P_ReadUINT8(&savebuffer); for (j = 0; j < 8 && j+i < max_extraemblems; ++j) data->extraCollected[j+i] = ((rtemp >> j) & 1); i += j; } for (i = 0; i < max_unlockables;) { - rtemp = READUINT8(save_p); + rtemp = P_ReadUINT8(&savebuffer); for (j = 0; j < 8 && j+i < max_unlockables; ++j) data->unlocked[j+i] = ((rtemp >> j) & 1); i += j; } for (i = 0; i < max_conditionsets;) { - rtemp = READUINT8(save_p); + rtemp = P_ReadUINT8(&savebuffer); for (j = 0; j < 8 && j+i < max_conditionsets; ++j) data->achieved[j+i] = ((rtemp >> j) & 1); i += j; } - data->timesBeaten = READUINT32(save_p); - data->timesBeatenWithEmeralds = READUINT32(save_p); - data->timesBeatenUltimate = READUINT32(save_p); + data->timesBeaten = P_ReadUINT32(&savebuffer); + data->timesBeatenWithEmeralds = P_ReadUINT32(&savebuffer); + data->timesBeatenUltimate = P_ReadUINT32(&savebuffer); // Main records for (i = 0; i < NUMMAPS; ++i) { - recscore = READUINT32(save_p); - rectime = (tic_t)READUINT32(save_p); - recrings = READUINT16(save_p); - save_p++; // compat + recscore = P_ReadUINT32(&savebuffer); + rectime = (tic_t)P_ReadUINT32(&savebuffer); + recrings = P_ReadUINT16(&savebuffer); + P_ReadUINT8(&savebuffer); // compat if (recrings > 10000 || recscore > MAXSCORE) goto datacorrupt; @@ -4561,16 +4568,16 @@ void G_LoadGameData(gamedata_t *data) // Nights records for (i = 0; i < NUMMAPS; ++i) { - if ((recmares = READUINT8(save_p)) == 0) + if ((recmares = P_ReadUINT8(&savebuffer)) == 0) continue; G_AllocNightsRecordData((INT16)i, data); for (curmare = 0; curmare < (recmares+1); ++curmare) { - data->nightsrecords[i]->score[curmare] = READUINT32(save_p); - data->nightsrecords[i]->grade[curmare] = READUINT8(save_p); - data->nightsrecords[i]->time[curmare] = (tic_t)READUINT32(save_p); + data->nightsrecords[i]->score[curmare] = P_ReadUINT32(&savebuffer); + data->nightsrecords[i]->grade[curmare] = P_ReadUINT8(&savebuffer); + data->nightsrecords[i]->time[curmare] = (tic_t)P_ReadUINT32(&savebuffer); if (data->nightsrecords[i]->grade[curmare] > GRADE_S) { @@ -4582,8 +4589,7 @@ void G_LoadGameData(gamedata_t *data) } // done - Z_Free(savebuffer); - save_p = NULL; + Z_Free(savebuffer.buf); // Don't consider loaded until it's a success! // It used to do this much earlier, but this would cause the gamedata to @@ -4604,8 +4610,7 @@ void G_LoadGameData(gamedata_t *data) if (strcmp(srb2home,".")) gdfolder = srb2home; - Z_Free(savebuffer); - save_p = NULL; + Z_Free(savebuffer.buf); I_Error("Corrupt game data file.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder); } @@ -4615,41 +4620,44 @@ void G_LoadGameData(gamedata_t *data) // Saves the main data file, which stores information such as emblems found, etc. void G_SaveGameData(gamedata_t *data) { - UINT8 *data_p; + save_t savebuffer; - size_t length; INT32 i, j; UINT8 btemp; INT32 curmare; + if (!data) + return; // data struct not valid + if (!data->loaded) return; // If never loaded (-nodata), don't save - data_p = savebuffer = (UINT8 *)malloc(GAMEDATASIZE); - if (!data_p) + savebuffer.size = GAMEDATASIZE; + savebuffer.buf = (UINT8 *)malloc(savebuffer.size); + if (!savebuffer.buf) { CONS_Alert(CONS_ERROR, M_GetText("No more free memory for saving game data\n")); return; } + savebuffer.pos = 0; if (usedCheats) { - free(savebuffer); - savebuffer = NULL; + free(savebuffer.buf); return; } // Version test - WRITEUINT32(data_p, GAMEDATA_ID); + P_WriteUINT32(&savebuffer, GAMEDATA_ID); - WRITEUINT32(data_p, data->totalplaytime); + P_WriteUINT32(&savebuffer, data->totalplaytime); - WRITEUINT32(data_p, quickncasehash(timeattackfolder, sizeof timeattackfolder)); + P_WriteUINT32(&savebuffer, quickncasehash(timeattackfolder, sizeof timeattackfolder)); // TODO put another cipher on these things? meh, I don't care... for (i = 0; i < NUMMAPS; i++) - WRITEUINT8(data_p, (data->mapvisited[i] & MV_MAX)); + P_WriteUINT8(&savebuffer, (data->mapvisited[i] & MV_MAX)); // To save space, use one bit per collected/achieved/unlocked flag for (i = 0; i < MAXEMBLEMS;) @@ -4657,7 +4665,7 @@ void G_SaveGameData(gamedata_t *data) btemp = 0; for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j) btemp |= (data->collected[j+i] << j); - WRITEUINT8(data_p, btemp); + P_WriteUINT8(&savebuffer, btemp); i += j; } for (i = 0; i < MAXEXTRAEMBLEMS;) @@ -4665,7 +4673,7 @@ void G_SaveGameData(gamedata_t *data) btemp = 0; for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j) btemp |= (data->extraCollected[j+i] << j); - WRITEUINT8(data_p, btemp); + P_WriteUINT8(&savebuffer, btemp); i += j; } for (i = 0; i < MAXUNLOCKABLES;) @@ -4673,7 +4681,7 @@ void G_SaveGameData(gamedata_t *data) btemp = 0; for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j) btemp |= (data->unlocked[j+i] << j); - WRITEUINT8(data_p, btemp); + P_WriteUINT8(&savebuffer, btemp); i += j; } for (i = 0; i < MAXCONDITIONSETS;) @@ -4681,30 +4689,30 @@ void G_SaveGameData(gamedata_t *data) btemp = 0; for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j) btemp |= (data->achieved[j+i] << j); - WRITEUINT8(data_p, btemp); + P_WriteUINT8(&savebuffer, btemp); i += j; } - WRITEUINT32(data_p, data->timesBeaten); - WRITEUINT32(data_p, data->timesBeatenWithEmeralds); - WRITEUINT32(data_p, data->timesBeatenUltimate); + P_WriteUINT32(&savebuffer, data->timesBeaten); + P_WriteUINT32(&savebuffer, data->timesBeatenWithEmeralds); + P_WriteUINT32(&savebuffer, data->timesBeatenUltimate); // Main records for (i = 0; i < NUMMAPS; i++) { if (data->mainrecords[i]) { - WRITEUINT32(data_p, data->mainrecords[i]->score); - WRITEUINT32(data_p, data->mainrecords[i]->time); - WRITEUINT16(data_p, data->mainrecords[i]->rings); + P_WriteUINT32(&savebuffer, data->mainrecords[i]->score); + P_WriteUINT32(&savebuffer, data->mainrecords[i]->time); + P_WriteUINT16(&savebuffer, data->mainrecords[i]->rings); } else { - WRITEUINT32(data_p, 0); - WRITEUINT32(data_p, 0); - WRITEUINT16(data_p, 0); + P_WriteUINT32(&savebuffer, 0); + P_WriteUINT32(&savebuffer, 0); + P_WriteUINT16(&savebuffer, 0); } - WRITEUINT8(data_p, 0); // compat + P_WriteUINT8(&savebuffer, 0); // compat } // NiGHTS records @@ -4712,25 +4720,22 @@ void G_SaveGameData(gamedata_t *data) { if (!data->nightsrecords[i] || !data->nightsrecords[i]->nummares) { - WRITEUINT8(data_p, 0); + P_WriteUINT8(&savebuffer, 0); continue; } - WRITEUINT8(data_p, data->nightsrecords[i]->nummares); + P_WriteUINT8(&savebuffer, data->nightsrecords[i]->nummares); for (curmare = 0; curmare < (data->nightsrecords[i]->nummares + 1); ++curmare) { - WRITEUINT32(data_p, data->nightsrecords[i]->score[curmare]); - WRITEUINT8(data_p, data->nightsrecords[i]->grade[curmare]); - WRITEUINT32(data_p, data->nightsrecords[i]->time[curmare]); + P_WriteUINT32(&savebuffer, data->nightsrecords[i]->score[curmare]); + P_WriteUINT8(&savebuffer, data->nightsrecords[i]->grade[curmare]); + P_WriteUINT32(&savebuffer, data->nightsrecords[i]->time[curmare]); } } - length = data_p - savebuffer; - - FIL_WriteFile(va(pandf, srb2home, gamedatafilename), savebuffer, length); - free(savebuffer); - savebuffer = NULL; + FIL_WriteFile(va(pandf, srb2home, gamedatafilename), savebuffer.buf, savebuffer.pos); + free(savebuffer.buf); } #define VERSIONSIZE 16 @@ -4741,7 +4746,7 @@ void G_SaveGameData(gamedata_t *data) // void G_LoadGame(UINT32 slot, INT16 mapoverride) { - size_t length; + save_t savebuffer; char vcheck[VERSIONSIZE]; char savename[255]; @@ -4758,18 +4763,18 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) else sprintf(savename, savegamename, slot); - length = FIL_ReadFile(savename, &savebuffer); - if (!length) + savebuffer.size = FIL_ReadFile(savename, &savebuffer.buf); + if (!savebuffer.size) { CONS_Printf(M_GetText("Couldn't read file %s\n"), savename); return; } - save_p = savebuffer; + savebuffer.pos = 0; memset(vcheck, 0, sizeof (vcheck)); sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION); - if (strcmp((const char *)save_p, (const char *)vcheck)) + if (strcmp((const char *)&savebuffer.buf[savebuffer.pos], (const char *)vcheck)) { #ifdef SAVEGAME_OTHERVERSIONS M_StartMessage(M_GetText("Save game from different version.\nYou can load this savegame, but\nsaving afterwards will be disabled.\n\nDo you want to continue anyway?\n\n(Press 'Y' to confirm)\n"), @@ -4779,15 +4784,14 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) M_ClearMenus(true); // so ESC backs out to title M_StartMessage(M_GetText("Save game from different version\n\nPress ESC\n"), NULL, MM_NOTHING); Command_ExitGame_f(); - Z_Free(savebuffer); - save_p = savebuffer = NULL; + Z_Free(savebuffer.buf); // no cheating! memset(&savedata, 0, sizeof(savedata)); #endif return; // bad version } - save_p += VERSIONSIZE; + savebuffer.pos += VERSIONSIZE; // if (demoplayback) // reset game engine // G_StopDemo(); @@ -4796,13 +4800,12 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) // automapactive = false; // dearchive all the modifications - if (!P_LoadGame(mapoverride)) + if (!P_LoadGame(&savebuffer, mapoverride)) { M_ClearMenus(true); // so ESC backs out to title M_StartMessage(M_GetText("Savegame file corrupted\n\nPress ESC\n"), NULL, MM_NOTHING); Command_ExitGame_f(); - Z_Free(savebuffer); - save_p = savebuffer = NULL; + Z_Free(savebuffer.buf); // no cheating! memset(&savedata, 0, sizeof(savedata)); @@ -4810,13 +4813,12 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) } if (marathonmode) { - marathontime = READUINT32(save_p); - marathonmode |= READUINT8(save_p); + marathontime = P_ReadUINT32(&savebuffer); + marathonmode |= P_ReadUINT8(&savebuffer); } // done - Z_Free(savebuffer); - save_p = savebuffer = NULL; + Z_Free(savebuffer.buf); displayplayer = consoleplayer; multiplayer = splitscreen = false; @@ -4834,6 +4836,7 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) // void G_SaveGame(UINT32 slot, INT16 mapnum) { + save_t savebuffer; boolean saved; char savename[256] = ""; const char *backup; @@ -4847,33 +4850,32 @@ void G_SaveGame(UINT32 slot, INT16 mapnum) gameaction = ga_nothing; { char name[VERSIONSIZE]; - size_t length; - save_p = savebuffer = (UINT8 *)malloc(SAVEGAMESIZE); - if (!save_p) + savebuffer.size = SAVEGAMESIZE; + savebuffer.buf = (UINT8 *)malloc(savebuffer.size); + if (!savebuffer.buf) { CONS_Alert(CONS_ERROR, M_GetText("No more free memory for saving game data\n")); return; } + savebuffer.pos = 0; memset(name, 0, sizeof (name)); sprintf(name, (marathonmode ? "back-up %d" : "version %d"), VERSION); - WRITEMEM(save_p, name, VERSIONSIZE); + P_WriteMem(&savebuffer, name, VERSIONSIZE); - P_SaveGame(mapnum); + P_SaveGame(&savebuffer, mapnum); if (marathonmode) { UINT32 writetime = marathontime; if (!(marathonmode & MA_INGAME)) writetime += TICRATE*5; // live event backup penalty because we don't know how long it takes to get to the next map - WRITEUINT32(save_p, writetime); - WRITEUINT8(save_p, (marathonmode & ~MA_INIT)); + P_WriteUINT32(&savebuffer, writetime); + P_WriteUINT8(&savebuffer, (marathonmode & ~MA_INIT)); } - length = save_p - savebuffer; - saved = FIL_WriteFile(backup, savebuffer, length); - free(savebuffer); - save_p = savebuffer = NULL; + saved = FIL_WriteFile(backup, savebuffer.buf, savebuffer.pos); + free(savebuffer.buf); } gameaction = ga_nothing; @@ -4885,11 +4887,10 @@ void G_SaveGame(UINT32 slot, INT16 mapnum) } #define BADSAVE goto cleanup; -#define CHECKPOS if (save_p >= end_p) BADSAVE void G_SaveGameOver(UINT32 slot, boolean modifylives) { + save_t savebuffer; boolean saved = false; - size_t length; char vcheck[VERSIONSIZE]; char savename[255]; const char *backup; @@ -4900,42 +4901,38 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives) sprintf(savename, savegamename, slot); backup = va("%s",savename); - length = FIL_ReadFile(savename, &savebuffer); - if (!length) + savebuffer.size = FIL_ReadFile(savename, &savebuffer.buf); + if (!savebuffer.size) { CONS_Printf(M_GetText("Couldn't read file %s\n"), savename); return; } + savebuffer.pos = 0; + { char temp[sizeof(timeattackfolder)]; - UINT8 *end_p = savebuffer + length; UINT8 *lives_p; SINT8 pllives; #ifdef NEWSKINSAVES INT16 backwardsCompat = 0; #endif - save_p = savebuffer; // Version check memset(vcheck, 0, sizeof (vcheck)); sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION); - if (strcmp((const char *)save_p, (const char *)vcheck)) BADSAVE - save_p += VERSIONSIZE; + if (strcmp((const char *)&savebuffer.buf[savebuffer.pos], (const char *)vcheck)) BADSAVE + savebuffer.pos += VERSIONSIZE; // P_UnArchiveMisc() - (void)READINT16(save_p); - CHECKPOS - (void)READUINT16(save_p); // emeralds - CHECKPOS - READSTRINGN(save_p, temp, sizeof(temp)); // mod it belongs to + (void)P_ReadINT16(&savebuffer); + (void)P_ReadUINT16(&savebuffer); // emeralds + P_ReadStringN(&savebuffer, temp, sizeof(temp)); // mod it belongs to if (strcmp(temp, timeattackfolder)) BADSAVE // P_UnArchivePlayer() - CHECKPOS #ifdef NEWSKINSAVES - backwardsCompat = READUINT16(save_p); - CHECKPOS + backwardsCompat = P_ReadUINT16(&savebuffer); if (backwardsCompat == NEWSKINSAVES) // New save, read skin names #endif @@ -4943,47 +4940,37 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives) char ourSkinName[SKINNAMESIZE+1]; char botSkinName[SKINNAMESIZE+1]; - READSTRINGN(save_p, ourSkinName, SKINNAMESIZE); - CHECKPOS + P_ReadStringN(&savebuffer, ourSkinName, SKINNAMESIZE); - READSTRINGN(save_p, botSkinName, SKINNAMESIZE); - CHECKPOS + P_ReadStringN(&savebuffer, botSkinName, SKINNAMESIZE); } - WRITEUINT8(save_p, numgameovers); - CHECKPOS + P_WriteUINT8(&savebuffer, numgameovers); - lives_p = save_p; - pllives = READSINT8(save_p); // lives - CHECKPOS + lives_p = &savebuffer.buf[savebuffer.pos]; + pllives = P_ReadSINT8(&savebuffer); // lives if (modifylives && pllives < startinglivesbalance[numgameovers]) { - pllives = startinglivesbalance[numgameovers]; - WRITESINT8(lives_p, pllives); + *lives_p = startinglivesbalance[numgameovers]; } - (void)READINT32(save_p); // Score - CHECKPOS - (void)READINT32(save_p); // continues + (void)P_ReadINT32(&savebuffer); // Score + (void)P_ReadINT32(&savebuffer); // continues // File end marker check - CHECKPOS - switch (READUINT8(save_p)) + switch (P_ReadUINT8(&savebuffer)) { case 0xb7: { UINT8 i, banksinuse; - CHECKPOS - banksinuse = READUINT8(save_p); - CHECKPOS + banksinuse = P_ReadUINT8(&savebuffer); if (banksinuse > NUM_LUABANKS) BADSAVE for (i = 0; i < banksinuse; i++) { - (void)READINT32(save_p); - CHECKPOS + (void)P_ReadINT32(&savebuffer); } - if (READUINT8(save_p) != 0x1d) + if (P_ReadUINT8(&savebuffer) != 0x1d) BADSAVE } case 0x1d: @@ -4993,7 +4980,7 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives) } // done - saved = FIL_WriteFile(backup, savebuffer, length); + saved = FIL_WriteFile(backup, savebuffer.buf, savebuffer.size); } cleanup: @@ -5001,11 +4988,9 @@ cleanup: CONS_Printf(M_GetText("Game saved.\n")); else if (!saved) CONS_Alert(CONS_ERROR, M_GetText("Error while writing to %s for save slot %u, base: %s\n"), backup, slot, (marathonmode ? liveeventbackup : savegamename)); - Z_Free(savebuffer); - save_p = savebuffer = NULL; + Z_Free(savebuffer.buf); } -#undef CHECKPOS #undef BADSAVE // @@ -5402,7 +5387,7 @@ void G_FreeMapSearch(mapsearchfreq_t *freq, INT32 freqc) INT32 G_FindMapByNameOrCode(const char *mapname, char **realmapnamep) { boolean usemapcode = false; - INT32 newmapnum; + INT32 newmapnum = -1; size_t mapnamelen = strlen(mapname); char *p; diff --git a/src/g_game.h b/src/g_game.h index 80a815f02d00a572972412901c72877e8f80de49..f72ea6b41b1b29b4b263b9039c0ad588bc78de17 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/g_input.c b/src/g_input.c index 3f1be37ba3f588fb2f3b2f6012ae7bf29c397b98..4fbdf5e7586d41c4dd09f0a5e5c3e2aafa67c99d 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -576,7 +576,9 @@ static const char *gamecontrolname[NUM_GAMECONTROLS] = "weapon5", "weapon6", "weapon7", - "shield", + "weapon8", + "weapon9", + "weapon10", "fire", "firenormal", "tossflag", @@ -691,7 +693,6 @@ void G_DefineDefaultControls(void) gamecontroldefault[gcs_fps][GC_CENTERVIEW ][0] = KEY_LCTRL; gamecontroldefault[gcs_fps][GC_JUMP ][0] = KEY_SPACE; gamecontroldefault[gcs_fps][GC_SPIN ][0] = KEY_LSHIFT; - gamecontroldefault[gcs_fps][GC_SHIELD ][0] = KEY_LALT; gamecontroldefault[gcs_fps][GC_FIRE ][0] = KEY_RCTRL; gamecontroldefault[gcs_fps][GC_FIRE ][1] = KEY_MOUSE1+0; gamecontroldefault[gcs_fps][GC_FIRENORMAL ][0] = KEY_RALT; @@ -712,7 +713,6 @@ void G_DefineDefaultControls(void) gamecontroldefault[gcs_platform][GC_CENTERVIEW ][0] = KEY_END; gamecontroldefault[gcs_platform][GC_JUMP ][0] = KEY_SPACE; gamecontroldefault[gcs_platform][GC_SPIN ][0] = KEY_LSHIFT; - gamecontroldefault[gcs_platform][GC_SHIELD ][0] = KEY_LALT; gamecontroldefault[gcs_platform][GC_FIRE ][0] = 's'; gamecontroldefault[gcs_platform][GC_FIRE ][1] = KEY_MOUSE1+0; gamecontroldefault[gcs_platform][GC_FIRENORMAL ][0] = 'w'; @@ -728,6 +728,9 @@ void G_DefineDefaultControls(void) gamecontroldefault[i][GC_WEPSLOT5 ][0] = '5'; gamecontroldefault[i][GC_WEPSLOT6 ][0] = '6'; gamecontroldefault[i][GC_WEPSLOT7 ][0] = '7'; + gamecontroldefault[i][GC_WEPSLOT8 ][0] = '8'; + gamecontroldefault[i][GC_WEPSLOT9 ][0] = '9'; + gamecontroldefault[i][GC_WEPSLOT10 ][0] = '0'; gamecontroldefault[i][GC_TOSSFLAG ][0] = '\''; gamecontroldefault[i][GC_CAMTOGGLE ][0] = 'v'; gamecontroldefault[i][GC_CAMRESET ][0] = 'r'; @@ -746,15 +749,15 @@ void G_DefineDefaultControls(void) gamecontroldefault[i][GC_CUSTOM1 ][1] = KEY_JOY1+1; // B gamecontroldefault[i][GC_CUSTOM2 ][1] = KEY_JOY1+3; // Y gamecontroldefault[i][GC_CUSTOM3 ][1] = KEY_JOY1+8; // Left Stick - gamecontroldefault[i][GC_SHIELD ][1] = KEY_JOY1+4; // LB + gamecontroldefault[i][GC_CAMTOGGLE ][1] = KEY_JOY1+4; // LB gamecontroldefault[i][GC_CENTERVIEW ][1] = KEY_JOY1+5; // RB - gamecontroldefault[i][GC_SCORES ][1] = KEY_JOY1+6; // Back + gamecontroldefault[i][GC_SCREENSHOT ][1] = KEY_JOY1+6; // Back gamecontroldefault[i][GC_SYSTEMMENU ][0] = KEY_JOY1+7; // Start gamecontroldefault[i][GC_WEAPONPREV ][1] = KEY_HAT1+2; // D-Pad Left gamecontroldefault[i][GC_WEAPONNEXT ][1] = KEY_HAT1+3; // D-Pad Right gamecontroldefault[i][GC_VIEWPOINTNEXT][1] = KEY_JOY1+9; // Right Stick gamecontroldefault[i][GC_TOSSFLAG ][1] = KEY_HAT1+0; // D-Pad Up - gamecontroldefault[i][GC_CAMTOGGLE ][1] = KEY_HAT1+1; // D-Pad Down + gamecontroldefault[i][GC_SCORES ][1] = KEY_HAT1+1; // D-Pad Down // Second player controls only have joypad defaults gamecontrolbisdefault[i][GC_JUMP ][1] = KEY_2JOY1+0; // A @@ -762,15 +765,15 @@ void G_DefineDefaultControls(void) gamecontrolbisdefault[i][GC_CUSTOM1 ][1] = KEY_2JOY1+1; // B gamecontrolbisdefault[i][GC_CUSTOM2 ][1] = KEY_2JOY1+3; // Y gamecontrolbisdefault[i][GC_CUSTOM3 ][1] = KEY_2JOY1+8; // Left Stick - gamecontrolbisdefault[i][GC_SHIELD ][1] = KEY_2JOY1+4; // LB + gamecontrolbisdefault[i][GC_CAMTOGGLE ][1] = KEY_2JOY1+4; // LB gamecontrolbisdefault[i][GC_CENTERVIEW ][1] = KEY_2JOY1+5; // RB - //gamecontrolbisdefault[i][GC_SCORES ][1] = KEY_2JOY1+6; // Back + gamecontrolbisdefault[i][GC_SCREENSHOT ][1] = KEY_2JOY1+6; // Back //gamecontrolbisdefault[i][GC_SYSTEMMENU ][0] = KEY_2JOY1+7; // Start gamecontrolbisdefault[i][GC_WEAPONPREV ][1] = KEY_2HAT1+2; // D-Pad Left gamecontrolbisdefault[i][GC_WEAPONNEXT ][1] = KEY_2HAT1+3; // D-Pad Right gamecontrolbisdefault[i][GC_VIEWPOINTNEXT][1] = KEY_2JOY1+9; // Right Stick gamecontrolbisdefault[i][GC_TOSSFLAG ][1] = KEY_2HAT1+0; // D-Pad Up - gamecontrolbisdefault[i][GC_CAMTOGGLE ][1] = KEY_2HAT1+1; // D-Pad Down + //gamecontrolbisdefault[i][GC_SCORES ][1] = KEY_2HAT1+1; // D-Pad Down } } @@ -1001,7 +1004,6 @@ static void setcontrol(INT32 (*gc)[2]) // TODO: 2.3: Delete the "use" alias namectrl = (stricmp(COM_Argv(1), "use")) ? COM_Argv(1) : "spin"; - for (numctrl = 0; numctrl < NUM_GAMECONTROLS && stricmp(namectrl, gamecontrolname[numctrl]); numctrl++) diff --git a/src/g_input.h b/src/g_input.h index 48c103076667df50884767685386b98bd4865a02..e9c909e6e2c222360086874ddb27e2495b4e0381 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -74,7 +74,9 @@ typedef enum GC_WEPSLOT5, GC_WEPSLOT6, GC_WEPSLOT7, - GC_SHIELD, + GC_WEPSLOT8, + GC_WEPSLOT9, + GC_WEPSLOT10, GC_FIRE, GC_FIRENORMAL, GC_TOSSFLAG, diff --git a/src/hardware/CMakeLists.txt b/src/hardware/CMakeLists.txt index e7819aba97e2065d36f6f920d4725d7b294505f3..3b6135c1d768a732944d2a18b4e0d41f7fb8c461 100644 --- a/src/hardware/CMakeLists.txt +++ b/src/hardware/CMakeLists.txt @@ -10,5 +10,6 @@ target_sources(SRB2SDL2 PRIVATE hw_md3load.c hw_model.c hw_batching.c + hw_shaders.c r_opengl/r_opengl.c ) diff --git a/src/hardware/Sourcefile b/src/hardware/Sourcefile index 6c374621d7b1de61f2b5a5c6fd9171f0685eccbf..4fa61470f26616ccb0dd311b4d08045054f23921 100644 --- a/src/hardware/Sourcefile +++ b/src/hardware/Sourcefile @@ -9,4 +9,5 @@ hw_md2load.c hw_md3load.c hw_model.c hw_batching.c +hw_shaders.c r_opengl/r_opengl.c diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c index a640a9917ad169cbeb8a141e6741614081d251df..5d1af10e2a35e073472e9e4d6cbd90e31bdaec40 100644 --- a/src/hardware/hw_batching.c +++ b/src/hardware/hw_batching.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2023 by Sonic Team Junior. +// Copyright (C) 2020-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -76,7 +76,7 @@ void HWR_SetCurrentTexture(GLMipmap_t *texture) // If batching is enabled, this function collects the polygon data and the chosen texture // for later use in HWR_RenderBatches. Otherwise the rendering backend is used to // render the polygon immediately. -void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial) +void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader_target, boolean horizonSpecial) { if (currently_batching) { @@ -114,7 +114,7 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt polygonArray[polygonArraySize].numVerts = iNumPts; polygonArray[polygonArraySize].polyFlags = PolyFlags; polygonArray[polygonArraySize].texture = current_texture; - polygonArray[polygonArraySize].shader = shader; + polygonArray[polygonArraySize].shader = (shader_target != SHADER_NONE) ? HWR_GetShaderFromTarget(shader_target) : shader_target; polygonArray[polygonArraySize].horizonSpecial = horizonSpecial; // default to polygonArraySize so we don't lose order on horizon lines // (yes, it's supposed to be negative, since we're sorting in that direction) @@ -134,7 +134,7 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt DIGEST(hash, pSurf->PolyColor.rgba); if (cv_glshaders.value && gl_shadersavailable) { - DIGEST(hash, shader); + DIGEST(hash, shader_target); DIGEST(hash, pSurf->TintColor.rgba); DIGEST(hash, pSurf->FadeColor.rgba); DIGEST(hash, pSurf->LightInfo.light_level); @@ -151,10 +151,9 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt } else { - if (shader) - HWD.pfnSetShader(shader); - HWD.pfnDrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags); - } + HWD.pfnSetShader((shader_target != SHADER_NONE) ? HWR_GetShaderFromTarget(shader_target) : shader_target); + HWD.pfnDrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags); + } } static int comparePolygons(const void *p1, const void *p2) @@ -312,7 +311,6 @@ void HWR_RenderBatches(void) int nextIndex = polygonIndexArray[polygonReadPos]; if (polygonArray[index].hash != polygonArray[nextIndex].hash) { - changeState = true; nextShader = polygonArray[nextIndex].shader; nextTexture = polygonArray[nextIndex].texture; nextPolyFlags = polygonArray[nextIndex].polyFlags; @@ -321,14 +319,17 @@ void HWR_RenderBatches(void) nextTexture = 0; if (currentShader != nextShader && cv_glshaders.value && gl_shadersavailable) { + changeState = true; changeShader = true; } if (currentTexture != nextTexture) { + changeState = true; changeTexture = true; } if (currentPolyFlags != nextPolyFlags) { + changeState = true; changePolyFlags = true; } if (cv_glshaders.value && gl_shadersavailable) @@ -340,6 +341,7 @@ void HWR_RenderBatches(void) currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start || currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end) { + changeState = true; changeSurfaceInfo = true; } } @@ -347,6 +349,7 @@ void HWR_RenderBatches(void) { if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba) { + changeState = true; changeSurfaceInfo = true; } } diff --git a/src/hardware/hw_batching.h b/src/hardware/hw_batching.h index df1a4c38be5ceeea84fb61fa22ad31b8a8063dea..4214ca410c071994bb1e16576e5f4d6c4ebfb311 100644 --- a/src/hardware/hw_batching.h +++ b/src/hardware/hw_batching.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2023 by Sonic Team Junior. +// Copyright (C) 2020-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index 58e16d62361a9ca3f87479ea273343c7c36065bc..b71bf7007e03ab2cdb7d229d84aa5a57deb8cc8c 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -32,6 +32,14 @@ INT32 patchformat = GL_TEXFMT_AP_88; // use alpha for holes INT32 textureformat = GL_TEXFMT_P_8; // use chromakey for hole +RGBA_t mapPalette[256] = {0}; // the palette for the currently loaded level or menu etc. + +// Returns a pointer to the palette which should be used for caching textures. +RGBA_t *HWR_GetTexturePalette(void) +{ + return HWR_ShouldUsePaletteRendering() ? mapPalette : pLocalPalette; +} + static INT32 format2bpp(GLTextureFormat_t format) { if (format == GL_TEXFMT_RGBA) @@ -49,7 +57,7 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm INT32 pblockheight, INT32 blockmodulo, fixed_t yfracstep, fixed_t scale_y, texpatch_t *originPatch, INT32 patchheight, - INT32 bpp) + INT32 bpp, RGBA_t *palette) { fixed_t yfrac, position, count; UINT8 *dest; @@ -90,13 +98,11 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm if (position + count >= pblockheight) count = pblockheight - position; - dest = block + (position*blockmodulo); - while (count > 0) + for (dest = block + (position*blockmodulo); count > 0; count--, dest += blockmodulo, yfrac += yfracstep) { - count--; - texel = source[yfrac>>FRACBITS]; alpha = 0xFF; + // Make pixel transparent if chroma keyed if ((mipmap->flags & TF_CHROMAKEYED) && (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX)) alpha = 0x00; @@ -107,13 +113,22 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm switch (bpp) { case 2: + { + texelu16 = *((UINT16*)dest); if ((originPatch != NULL) && (originPatch->style != AST_COPY)) - texel = ASTBlendPaletteIndexes(*(dest+1), texel, originPatch->style, originPatch->alpha); + { + if (originPatch->style == AST_TRANSLUCENT && originPatch->alpha < ASTTextureBlendingThreshold[0]) + continue; + if (!(texelu16 & 0xFF00) && originPatch->alpha <= ASTTextureBlendingThreshold[1]) + continue; + texel = ASTBlendPaletteIndexes(texelu16 & 0xFF, texel, originPatch->style, originPatch->alpha); + } texelu16 = (UINT16)((alpha<<8) | texel); memcpy(dest, &texelu16, sizeof(UINT16)); break; + } case 3: - colortemp = V_GetColor(texel); + colortemp = palette[texel]; if ((originPatch != NULL) && (originPatch->style != AST_COPY)) { RGBA_t rgbatexel; @@ -123,7 +138,7 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); break; case 4: - colortemp = V_GetColor(texel); + colortemp = palette[texel]; colortemp.s.alpha = alpha; if ((originPatch != NULL) && (originPatch->style != AST_COPY)) { @@ -141,9 +156,6 @@ static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipm *dest = texel; break; } - - dest += blockmodulo; - yfrac += yfracstep; } } } @@ -152,7 +164,7 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, INT32 pblockheight, INT32 blockmodulo, fixed_t yfracstep, fixed_t scale_y, texpatch_t *originPatch, INT32 patchheight, - INT32 bpp) + INT32 bpp, RGBA_t *palette) { fixed_t yfrac, position, count; UINT8 *dest; @@ -194,13 +206,11 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, if (position + count >= pblockheight) count = pblockheight - position; - dest = block + (position*blockmodulo); - while (count > 0) + for (dest = block + (position*blockmodulo); count > 0; count--, dest += blockmodulo, yfrac -= yfracstep) { - count--; - texel = source[yfrac>>FRACBITS]; alpha = 0xFF; + // Make pixel transparent if chroma keyed if ((mipmap->flags & TF_CHROMAKEYED) && (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX)) alpha = 0x00; @@ -211,13 +221,20 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, switch (bpp) { case 2: + texelu16 = *((UINT16*)dest); if ((originPatch != NULL) && (originPatch->style != AST_COPY)) - texel = ASTBlendPaletteIndexes(*(dest+1), texel, originPatch->style, originPatch->alpha); + { + if (originPatch->style == AST_TRANSLUCENT && originPatch->alpha < ASTTextureBlendingThreshold[0]) + continue; + if (!(texelu16 & 0xFF00) && originPatch->alpha <= ASTTextureBlendingThreshold[1]) + continue; + texel = ASTBlendPaletteIndexes(texelu16 & 0xFF, texel, originPatch->style, originPatch->alpha); + } texelu16 = (UINT16)((alpha<<8) | texel); memcpy(dest, &texelu16, sizeof(UINT16)); break; case 3: - colortemp = V_GetColor(texel); + colortemp = palette[texel]; if ((originPatch != NULL) && (originPatch->style != AST_COPY)) { RGBA_t rgbatexel; @@ -227,7 +244,7 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); break; case 4: - colortemp = V_GetColor(texel); + colortemp = palette[texel]; colortemp.s.alpha = alpha; if ((originPatch != NULL) && (originPatch->style != AST_COPY)) { @@ -245,9 +262,6 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, *dest = texel; break; } - - dest += blockmodulo; - yfrac -= yfracstep; } } } @@ -269,10 +283,13 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap, UINT8 *block = mipmap->data; INT32 bpp; INT32 blockmodulo; + RGBA_t *palette; if (pwidth <= 0 || pheight <= 0) return; + palette = HWR_GetTexturePalette(); + ncols = pwidth; // source advance @@ -298,7 +315,7 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap, pblockheight, blockmodulo, yfracstep, scale_y, NULL, pheight, // not that pheight is going to get used anyway... - bpp); + bpp, palette); } } @@ -317,16 +334,19 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, INT32 bpp; INT32 blockmodulo; INT32 width, height; + RGBA_t *palette; // Column drawing function pointer. static void (*ColumnDrawerPointer)(const column_t *patchcol, UINT8 *block, GLMipmap_t *mipmap, INT32 pblockheight, INT32 blockmodulo, fixed_t yfracstep, fixed_t scale_y, texpatch_t *originPatch, INT32 patchheight, - INT32 bpp); + INT32 bpp, RGBA_t *palette); if (texture->width <= 0 || texture->height <= 0) return; + palette = HWR_GetTexturePalette(); + ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawFlippedColumnInCache : HWR_DrawColumnInCache; x1 = patch->originx; @@ -386,7 +406,7 @@ static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, pblockheight, blockmodulo, yfracstep, scale_y, patch, height, - bpp); + bpp, palette); } } @@ -419,7 +439,7 @@ static UINT8 *MakeBlock(GLMipmap_t *grMipmap) // Create a composite texture from patches, adapt the texture size to a power of 2 // height and width for the hardware texture cache. // -static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex) +static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex, GLMipmap_t *mipmap) { UINT8 *block; texture_t *texture; @@ -427,50 +447,13 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex) INT32 blockwidth, blockheight, blocksize; INT32 i; - boolean skyspecial = false; //poor hack for Legacy large skies.. texture = textures[texnum]; - // hack the Legacy skies.. - if (texture->name[0] == 'S' && - texture->name[1] == 'K' && - texture->name[2] == 'Y' && - (texture->name[4] == 0 || - texture->name[5] == 0) - ) - { - skyspecial = true; - grtex->mipmap.flags = TF_WRAPXY; // don't use the chromakey for sky - } - else - grtex->mipmap.flags = TF_CHROMAKEYED | TF_WRAPXY; - - grtex->mipmap.width = (UINT16)texture->width; - grtex->mipmap.height = (UINT16)texture->height; - grtex->mipmap.format = textureformat; - blockwidth = texture->width; blockheight = texture->height; - blocksize = (blockwidth * blockheight); - block = MakeBlock(&grtex->mipmap); - - if (skyspecial) //Hurdler: not efficient, but better than holes in the sky (and it's done only at level loading) - { - INT32 j; - RGBA_t col; - - col = V_GetColor(HWR_PATCHES_CHROMAKEY_COLORINDEX); - for (j = 0; j < blockheight; j++) - { - for (i = 0; i < blockwidth; i++) - { - block[4*(j*blockwidth+i)+0] = col.s.red; - block[4*(j*blockwidth+i)+1] = col.s.green; - block[4*(j*blockwidth+i)+2] = col.s.blue; - block[4*(j*blockwidth+i)+3] = 0xff; - } - } - } + blocksize = blockwidth * blockheight; + block = MakeBlock(mipmap); // Composite the columns together. for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++) @@ -500,19 +483,19 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex) realpatch = W_CachePatchNumPwad(wadnum, lumpnum, PU_PATCH); } - HWR_DrawTexturePatchInCache(&grtex->mipmap, blockwidth, blockheight, texture, patch, realpatch); + HWR_DrawTexturePatchInCache(mipmap, blockwidth, blockheight, texture, patch, realpatch); if (free_patch) Patch_Free(realpatch); } //Hurdler: not efficient at all but I don't remember exactly how HWR_DrawPatchInCache works :( - if (format2bpp(grtex->mipmap.format)==4) + if (format2bpp(mipmap->format)==4) { for (i = 3; i < blocksize*4; i += 4) // blocksize*4 because blocksize doesn't include the bpp { if (block[i] == 0) { - grtex->mipmap.flags |= TF_TRANSPARENT; + mipmap->flags |= TF_TRANSPARENT; break; } } @@ -641,8 +624,6 @@ void HWR_FreeTextureColormaps(patch_t *patch) Z_Free(next->data); if (next->colormap) Z_Free(next->colormap); - next->data = NULL; - next->colormap = NULL; HWD.pfnDeleteTexture(next); // Free the old colormap mipmap from memory. @@ -694,12 +675,24 @@ void HWR_InitMapTextures(void) gl_maptexturesloaded = false; } -static void FreeMapTexture(GLMapTexture_t *tex) +static void DeleteTextureMipmap(GLMipmap_t *grMipmap, boolean delete_mipmap) { - HWD.pfnDeleteTexture(&tex->mipmap); - if (tex->mipmap.data) - Z_Free(tex->mipmap.data); - tex->mipmap.data = NULL; + HWD.pfnDeleteTexture(grMipmap); + + if (delete_mipmap) + Z_Free(grMipmap->data); +} + +static void FreeMapTexture(GLMapTexture_t *tex, boolean delete_chromakeys) +{ + if (tex->mipmap.nextcolormap) + { + DeleteTextureMipmap(tex->mipmap.nextcolormap, delete_chromakeys); + free(tex->mipmap.nextcolormap); + tex->mipmap.nextcolormap = NULL; + } + + DeleteTextureMipmap(&tex->mipmap, true); } void HWR_FreeMapTextures(void) @@ -708,8 +701,8 @@ void HWR_FreeMapTextures(void) for (i = 0; i < gl_numtextures; i++) { - FreeMapTexture(&gl_textures[i]); - FreeMapTexture(&gl_flats[i]); + FreeMapTexture(&gl_textures[i], true); + FreeMapTexture(&gl_flats[i], false); } // now the heap don't have any 'user' pointing to our @@ -739,57 +732,74 @@ void HWR_LoadMapTextures(size_t pnumtextures) gl_maptexturesloaded = true; } -void HWR_SetPalette(RGBA_t *palette) -{ - HWD.pfnSetPalette(palette); - - // hardware driver will flush there own cache if cache is non paletized - // now flush data texture cache so 32 bit texture are recomputed - if (patchformat == GL_TEXFMT_RGBA || textureformat == GL_TEXFMT_RGBA) - { - Z_FreeTag(PU_HWRCACHE); - Z_FreeTag(PU_HWRCACHE_UNLOCKED); - } -} - // -------------------------------------------------------------------------- // Make sure texture is downloaded and set it as the source // -------------------------------------------------------------------------- -GLMapTexture_t *HWR_GetTexture(INT32 tex) +GLMapTexture_t *HWR_GetTexture(INT32 tex, boolean chromakeyed) { - GLMapTexture_t *grtex; + if (tex < 0 || tex >= (signed)gl_numtextures) + { #ifdef PARANOIA - if ((unsigned)tex >= gl_numtextures) - I_Error("HWR_GetTexture: tex >= numtextures\n"); + I_Error("HWR_GetTexture: Invalid texture ID %d", tex); +#else + tex = 0; #endif + } - // Every texture in memory, stored in the - // hardware renderer's bit depth format. Wow! - grtex = &gl_textures[tex]; + GLMapTexture_t *grtex = &gl_textures[tex]; - // Generate texture if missing from the cache - if (!grtex->mipmap.data && !grtex->mipmap.downloaded) - HWR_GenerateTexture(tex, grtex); + GLMipmap_t *grMipmap = &grtex->mipmap; + GLMipmap_t *originalMipmap = grMipmap; - // If hardware does not have the texture, then call pfnSetTexture to upload it - if (!grtex->mipmap.downloaded) - HWD.pfnSetTexture(&grtex->mipmap); - HWR_SetCurrentTexture(&grtex->mipmap); + if (!originalMipmap->downloaded) + { + originalMipmap->flags = TF_WRAPXY; + originalMipmap->width = (UINT16)textures[tex]->width; + originalMipmap->height = (UINT16)textures[tex]->height; + originalMipmap->format = textureformat; + } - // The system-memory data can be purged now. - Z_ChangeTag(grtex->mipmap.data, PU_HWRCACHE_UNLOCKED); + // If chroma-keyed, create or use a different mipmap for the variant + if (chromakeyed && !textures[tex]->transparency) + { + // Allocate it if it wasn't already + if (!originalMipmap->nextcolormap) + { + GLMipmap_t *newMipmap = calloc(1, sizeof (*grMipmap)); + if (newMipmap == NULL) + I_Error("%s: Out of memory", "HWR_GetTexture"); + + newMipmap->flags = originalMipmap->flags | TF_CHROMAKEYED; + newMipmap->width = originalMipmap->width; + newMipmap->height = originalMipmap->height; + newMipmap->format = originalMipmap->format; + originalMipmap->nextcolormap = newMipmap; + } + + // Generate, upload and bind the variant texture instead of the original one + grMipmap = originalMipmap->nextcolormap; + } + + if (!grMipmap->data) + HWR_GenerateTexture(tex, grtex, grMipmap); + + if (!grMipmap->downloaded) + HWD.pfnSetTexture(grMipmap); + HWR_SetCurrentTexture(grMipmap); + + Z_ChangeTag(grMipmap->data, PU_HWRCACHE_UNLOCKED); return grtex; } -static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) +static void HWR_CacheRawFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) { size_t size = W_LumpLength(flatlumpnum); UINT16 pflatsize = R_GetFlatSize(size); // setup the texture info grMipmap->format = GL_TEXFMT_P_8; - grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; + grMipmap->flags = TF_WRAPXY; grMipmap->width = pflatsize; grMipmap->height = pflatsize; @@ -810,7 +820,7 @@ void HWR_GetRawFlat(lumpnum_t flatlumpnum) patch = HWR_GetCachedGLPatch(flatlumpnum); grmip = ((GLPatch_t *)Patch_AllocateHardwarePatch(patch))->mipmap; if (!grmip->downloaded && !grmip->data) - HWR_CacheFlat(grmip, flatlumpnum); + HWR_CacheRawFlat(grmip, flatlumpnum); // If hardware does not have the texture, then call pfnSetTexture to upload it if (!grmip->downloaded) @@ -821,40 +831,70 @@ void HWR_GetRawFlat(lumpnum_t flatlumpnum) Z_ChangeTag(grmip->data, PU_HWRCACHE_UNLOCKED); } -void HWR_GetLevelFlat(levelflat_t *levelflat) +static void MakeLevelFlatMipmap(GLMipmap_t *grMipmap, INT32 texturenum, UINT16 flags) { - if (levelflat->type == LEVELFLAT_NONE) + grMipmap->format = GL_TEXFMT_P_8; + grMipmap->flags = flags; + + grMipmap->width = (UINT16)textures[texturenum]->width; + grMipmap->height = (UINT16)textures[texturenum]->height; +} + +void HWR_GetLevelFlat(levelflat_t *levelflat, boolean chromakeyed) +{ + if (levelflat->type == LEVELFLAT_NONE || levelflat->texture_id < 0) { HWR_SetCurrentTexture(NULL); return; } INT32 texturenum = texturetranslation[levelflat->texture_id]; - if (texturenum <= 0) - { - HWR_SetCurrentTexture(NULL); - return; - } GLMapTexture_t *grtex = &gl_flats[texturenum]; + GLMipmap_t *grMipmap = &grtex->mipmap; + GLMipmap_t *originalMipmap = grMipmap; + + if (!originalMipmap->downloaded) + MakeLevelFlatMipmap(originalMipmap, texturenum, TF_WRAPXY); - if (!grMipmap->data && !grMipmap->downloaded) + if (!originalMipmap->data) { - grMipmap->format = GL_TEXFMT_P_8; - grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; + size_t size = originalMipmap->width * originalMipmap->height; + memcpy(Z_Malloc(size, PU_HWRCACHE, &originalMipmap->data), R_GetFlatForTexture(texturenum), size); + } + + // If chroma-keyed, create or use a different mipmap for the variant + if (chromakeyed) + { + if (!originalMipmap->data) + { + HWR_SetCurrentTexture(NULL); + return; + } - grMipmap->width = (UINT16)textures[texturenum]->width; - grMipmap->height = (UINT16)textures[texturenum]->height; + // Allocate it if it wasn't already + if (!originalMipmap->nextcolormap) + { + GLMipmap_t *newMipmap = calloc(1, sizeof (*grMipmap)); + if (newMipmap == NULL) + I_Error("%s: Out of memory", "HWR_GetLevelFlat"); + MakeLevelFlatMipmap(newMipmap, texturenum, TF_WRAPXY | TF_CHROMAKEYED); + originalMipmap->nextcolormap = newMipmap; + } - size_t size = grMipmap->width * grMipmap->height; - memcpy(Z_Malloc(size, PU_HWRCACHE, &grMipmap->data), R_GetFlatForTexture(texturenum), size); + // Upload and bind the variant texture instead of the original one + grMipmap = originalMipmap->nextcolormap; + + // Use the original texture's pixel data + // It can just be a pointer to it, since the r_opengl backend deals with the pixels + // that are supposed to be transparent. + grMipmap->data = originalMipmap->data; } if (!grMipmap->downloaded) - HWD.pfnSetTexture(&grtex->mipmap); - - HWR_SetCurrentTexture(&grtex->mipmap); + HWD.pfnSetTexture(grMipmap); + HWR_SetCurrentTexture(grMipmap); Z_ChangeTag(grMipmap->data, PU_HWRCACHE_UNLOCKED); } @@ -997,6 +1037,7 @@ static void HWR_DrawFadeMaskInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32 UINT8 *flat; UINT8 *dest, *src, texel; RGBA_t col; + RGBA_t *palette = HWR_GetTexturePalette(); // Place the flats data into flat W_ReadLump(fademasklumpnum, Z_Malloc(W_LumpLength(fademasklumpnum), @@ -1014,7 +1055,7 @@ static void HWR_DrawFadeMaskInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32 { // fademask bpp is always 1, and is used just for alpha texel = src[(posx)>>FRACBITS]; - col = V_GetColor(texel); + col = palette[texel]; *dest = col.s.red; // take the red level of the colour and use it for alpha, as fademasks do dest++; @@ -1086,4 +1127,210 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum) Z_ChangeTag(grmip->data, PU_HWRCACHE_UNLOCKED); } +// ================================================= +// PALETTE HANDLING +// ================================================= + +void HWR_SetPalette(RGBA_t *palette) +{ + if (HWR_ShouldUsePaletteRendering()) + { + // set the palette for palette postprocessing + + if (cv_glpalettedepth.value == 16) + { + // crush to 16-bit rgb565, like software currently does in the standard configuration + // Note: Software's screenshots have the 24-bit palette, but the screen gets + // the 16-bit version! For making comparison screenshots either use an external screenshot + // tool or set the palette depth to 24 bits. + RGBA_t crushed_palette[256]; + int i; + for (i = 0; i < 256; i++) + { + float fred = (float)(palette[i].s.red >> 3); + float fgreen = (float)(palette[i].s.green >> 2); + float fblue = (float)(palette[i].s.blue >> 3); + crushed_palette[i].s.red = (UINT8)(fred / 31.0f * 255.0f); + crushed_palette[i].s.green = (UINT8)(fgreen / 63.0f * 255.0f); + crushed_palette[i].s.blue = (UINT8)(fblue / 31.0f * 255.0f); + crushed_palette[i].s.alpha = 255; + } + HWD.pfnSetScreenPalette(crushed_palette); + } + else + { + HWD.pfnSetScreenPalette(palette); + } + + // this part is responsible for keeping track of the palette OUTSIDE of a level. + if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction))) + HWR_SetMapPalette(); + } + else + { + // set the palette for the textures + HWD.pfnSetTexturePalette(palette); + // reset mapPalette so next call to HWR_SetMapPalette will update everything correctly + memset(mapPalette, 0, sizeof(mapPalette)); + // hardware driver will flush there own cache if cache is non paletized + // now flush data texture cache so 32 bit texture are recomputed + if (patchformat == GL_TEXFMT_RGBA || textureformat == GL_TEXFMT_RGBA) + { + Z_FreeTag(PU_HWRCACHE); + Z_FreeTag(PU_HWRCACHE_UNLOCKED); + } + } +} + +static void HWR_SetPaletteLookup(RGBA_t *palette) +{ + int r, g, b; + UINT8 *lut = Z_Malloc( + HWR_PALETTE_LUT_SIZE*HWR_PALETTE_LUT_SIZE*HWR_PALETTE_LUT_SIZE*sizeof(UINT8), + PU_STATIC, NULL); +#define STEP_SIZE (256/HWR_PALETTE_LUT_SIZE) + for (b = 0; b < HWR_PALETTE_LUT_SIZE; b++) + { + for (g = 0; g < HWR_PALETTE_LUT_SIZE; g++) + { + for (r = 0; r < HWR_PALETTE_LUT_SIZE; r++) + { + lut[b*HWR_PALETTE_LUT_SIZE*HWR_PALETTE_LUT_SIZE+g*HWR_PALETTE_LUT_SIZE+r] = + NearestPaletteColor(r*STEP_SIZE, g*STEP_SIZE, b*STEP_SIZE, palette); + } + } + } +#undef STEP_SIZE + HWD.pfnSetPaletteLookup(lut); + Z_Free(lut); +} + +// Updates mapPalette to reflect the loaded level or other game state. +// Textures are flushed if needed. +// Call this function only in palette rendering mode. +void HWR_SetMapPalette(void) +{ + RGBA_t RGBA_converted[256]; + RGBA_t *palette; + int i; + + if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction))) + { + // outside of a level, pMasterPalette should have PLAYPAL ready for us + palette = pMasterPalette; + } + else + { + // in a level pMasterPalette might have a flash palette, but we + // want the map's original palette. + lumpnum_t lumpnum = W_GetNumForName(GetPalette()); + size_t palsize = W_LumpLength(lumpnum); + UINT8 *RGB_data; + if (palsize < 768) // 256 * 3 + I_Error("HWR_SetMapPalette: A programmer assumed palette lumps are at least 768 bytes long, but apparently this was a wrong assumption!\n"); + RGB_data = W_CacheLumpNum(lumpnum, PU_CACHE); + // we got the RGB palette now, but we need it in RGBA format. + for (i = 0; i < 256; i++) + { + RGBA_converted[i].s.red = *(RGB_data++); + RGBA_converted[i].s.green = *(RGB_data++); + RGBA_converted[i].s.blue = *(RGB_data++); + RGBA_converted[i].s.alpha = 255; + } + palette = RGBA_converted; + } + + // check if the palette has changed from the previous one + if (memcmp(mapPalette, palette, sizeof(mapPalette))) + { + memcpy(mapPalette, palette, sizeof(mapPalette)); + // in palette rendering mode, this means that all rgba textures now have wrong colors + // and the lookup table is outdated + HWR_SetPaletteLookup(mapPalette); + HWD.pfnSetTexturePalette(mapPalette); + if (patchformat == GL_TEXFMT_RGBA || textureformat == GL_TEXFMT_RGBA) + { + Z_FreeTag(PU_HWRCACHE); + Z_FreeTag(PU_HWRCACHE_UNLOCKED); + } + } +} + +// Creates a hardware lighttable from the supplied lighttable. +// Returns the id of the hw lighttable, usable in FSurfaceInfo. +UINT32 HWR_CreateLightTable(UINT8 *lighttable, RGBA_t *hw_lighttable) +{ + UINT32 i; + RGBA_t *palette = HWR_GetTexturePalette(); + + // To make the palette index -> RGBA mapping easier for the shader, + // the hardware lighttable is composed of RGBA colors instead of palette indices. + for (i = 0; i < 256 * 32; i++) + hw_lighttable[i] = palette[lighttable[i]]; + + return HWD.pfnCreateLightTable(hw_lighttable); +} + +// Updates a hardware lighttable of a given id from the supplied lighttable. +void HWR_UpdateLightTable(UINT32 id, UINT8 *lighttable, RGBA_t *hw_lighttable) +{ + UINT32 i; + RGBA_t *palette = HWR_GetTexturePalette(); + + for (i = 0; i < 256 * 32; i++) + hw_lighttable[i] = palette[lighttable[i]]; + + HWD.pfnUpdateLightTable(id, hw_lighttable); +} + +// get hwr lighttable id for colormap, create it if it doesn't already exist +UINT32 HWR_GetLightTableID(extracolormap_t *colormap) +{ + boolean default_colormap = false; + if (!colormap) + { + colormap = R_GetDefaultColormap(); // a place to store the hw lighttable id + // alternatively could just store the id in a global variable if there are issues + default_colormap = true; + } + + UINT8 *colormap_pointer; + + if (default_colormap) + colormap_pointer = colormaps; // don't actually use the data from the "default colormap" + else + colormap_pointer = colormap->colormap; + + // create hw lighttable if there isn't one + if (colormap->gl_lighttable.data == NULL) + { + Z_Malloc(256 * 32 * sizeof(RGBA_t), PU_HWRLIGHTTABLEDATA, &colormap->gl_lighttable.data); + } + + // Generate the texture for this light table + if (!colormap->gl_lighttable.id) + { + colormap->gl_lighttable.id = HWR_CreateLightTable(colormap_pointer, colormap->gl_lighttable.data); + } + // Update the texture if it was directly changed by a script + else if (colormap->gl_lighttable.needs_update) + { + HWR_UpdateLightTable(colormap->gl_lighttable.id, colormap_pointer, colormap->gl_lighttable.data); + } + + colormap->gl_lighttable.needs_update = false; + + return colormap->gl_lighttable.id; +} + +// Note: all hardware lighttable ids assigned before this +// call become invalid and must not be used. +void HWR_ClearLightTables(void) +{ + Z_FreeTag(PU_HWRLIGHTTABLEDATA); + + if (vid.glstate == VID_GL_LIBRARY_LOADED) + HWD.pfnClearLightTables(); +} + #endif //HWRENDER diff --git a/src/hardware/hw_clip.c b/src/hardware/hw_clip.c index 86e0c58d25a72956dd9b10d6950baf10fd731ae1..74268423f5526c8d2c8733775b9f2ca60fb6141e 100644 --- a/src/hardware/hw_clip.c +++ b/src/hardware/hw_clip.c @@ -320,16 +320,13 @@ void gld_clipper_Clear(void) #define RMUL (1.6f/1.333333f) -angle_t gld_FrustumAngle(angle_t tiltangle) +angle_t gld_FrustumAngle(float render_fov, angle_t tiltangle) { double floatangle; angle_t a1; float tilt = (float)fabs(((double)(int)tiltangle) / ANG1); - // NEWCLIP TODO: SRB2CBTODO: make a global render_fov for this function - - float render_fov = FIXED_TO_FLOAT(cv_fov.value); float render_fovratio = (float)BASEVIDWIDTH / (float)BASEVIDHEIGHT; // SRB2CBTODO: NEWCLIPTODO: Is this right? float render_multiplier = 64.0f / render_fovratio / RMUL; diff --git a/src/hardware/hw_clip.h b/src/hardware/hw_clip.h index 27a2ed1efa2de4b9f6d54278a5052fb03c4a1d46..e3bb4c3193ca0094871f15d89e892a8c769d14d0 100644 --- a/src/hardware/hw_clip.h +++ b/src/hardware/hw_clip.h @@ -17,7 +17,7 @@ boolean gld_clipper_SafeCheckRange(angle_t startAngle, angle_t endAngle); void gld_clipper_SafeAddClipRange(angle_t startangle, angle_t endangle); void gld_clipper_Clear(void); -angle_t gld_FrustumAngle(angle_t tiltangle); +angle_t gld_FrustumAngle(float render_fov, angle_t tiltangle); #ifdef HAVE_SPHEREFRUSTRUM void gld_FrustrumSetup(void); boolean gld_SphereInFrustum(float x, float y, float z, float radius); diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 3b660cc70c36515dab60b4ae3eabb914b5de7d5d..77d7133b67112ec6498ebcf79d3c6432952d38c3 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -18,6 +18,12 @@ #define ZCLIP_PLANE 4.0f // Used for the actual game drawing #define NZCLIP_PLANE 0.9f // Seems to be only used for the HUD and screen textures +// The width/height/depth of the palette lookup table used by palette rendering. +// Changing this also requires changing the shader code! +// Also assumed to be a power of two in some parts of the code. +// 64 seems to work perfectly for the vanilla palette. +#define HWR_PALETTE_LUT_SIZE 64 + // ========================================================================== // SIMPLE TYPES // ========================================================================== @@ -122,33 +128,31 @@ typedef struct } FOutVector; #ifdef GL_SHADERS -// Predefined shader types + +// Shader targets used to render specific types of geometry. +// A shader target is resolved to an actual shader with HWR_GetShaderFromTarget. +// The shader returned may be a base shader or a custom shader. enum { SHADER_NONE = -1, - SHADER_DEFAULT = 0, - SHADER_FLOOR, + SHADER_FLOOR = 0, SHADER_WALL, SHADER_SPRITE, - SHADER_MODEL, SHADER_MODEL_LIGHTING, + SHADER_MODEL, SHADER_WATER, SHADER_FOG, SHADER_SKY, + SHADER_PALETTE_POSTPROCESS, + SHADER_UI_COLORMAP_FADE, + SHADER_UI_TINTED_WIPE, - NUMBASESHADERS, + NUMSHADERTARGETS }; // Maximum amount of shader programs -// Must be higher than NUMBASESHADERS -#define HWR_MAXSHADERS 16 - -// Shader sources (vertex and fragment) -typedef struct -{ - char *vertex; - char *fragment; -} shadersource_t; +// Must be at least NUMSHADERTARGETS*2 to fit base and custom shaders for each shader target. +#define HWR_MAXSHADERS NUMSHADERTARGETS*2 // Custom shader reference table typedef struct @@ -242,7 +246,7 @@ enum ETextureFlags TF_WRAPX = 0x00000001, // wrap around X TF_WRAPY = 0x00000002, // wrap around Y TF_WRAPXY = TF_WRAPY|TF_WRAPX, // very common so use alias is more easy - TF_CHROMAKEYED = 0x00000010, + TF_CHROMAKEYED = 0x00000010, // Used only for flats with pixels that have palette index 255 TF_TRANSPARENT = 0x00000040, // texture with some alpha == 0 }; @@ -272,11 +276,15 @@ struct FSurfaceInfo RGBA_t PolyColor; RGBA_t TintColor; RGBA_t FadeColor; + UINT32 LightTableId; FLightInfo LightInfo; }; typedef struct FSurfaceInfo FSurfaceInfo; -//Hurdler: added for backward compatibility +#define GL_DEFAULTMIX 0x00000000 +#define GL_DEFAULTFOG 0xFF000000 + +// Various settings and states for the rendering backend. enum hwdsetspecialstate { HWD_SET_MODEL_LIGHTING = 1, @@ -289,15 +297,13 @@ enum hwdsetspecialstate typedef enum hwdsetspecialstate hwdspecialstate_t; -// Lactozilla: Shader options -enum hwdshaderoption +enum hwdshaderstage { - HWD_SHADEROPTION_OFF, - HWD_SHADEROPTION_ON, - HWD_SHADEROPTION_NOCUSTOM, + HWD_SHADERSTAGE_VERTEX, + HWD_SHADERSTAGE_FRAGMENT, }; -typedef enum hwdshaderoption hwdshaderoption_t; +typedef enum hwdshaderstage hwdshaderstage_t; // Lactozilla: Shader info // Generally set at the start of the frame. @@ -318,5 +324,18 @@ enum hwdfiltermode HWD_SET_TEXTUREFILTER_MIXED3, }; +// Screen texture slots +enum hwdscreentexture +{ + HWD_SCREENTEXTURE_WIPE_START, // source image for the wipe/fade effect + HWD_SCREENTEXTURE_WIPE_END, // destination image for the wipe/fade effect + HWD_SCREENTEXTURE_GENERIC1, // underwater/heat effect, intermission background + HWD_SCREENTEXTURE_GENERIC2, // palette-based colormap fade, screen before palette rendering's postprocessing + HWD_SCREENTEXTURE_GENERIC3, // screen after palette rendering's postprocessing + NUMSCREENTEXTURES, // (generic3 is unused if palette rendering is disabled) +}; + +typedef enum hwdscreentexture hwdscreentexture_t; + #endif //_HWR_DEFS_ diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index ba1f339d0fe9af16d7eee7ab0f73d7558de0936e..369f59ac2bfe59ccd567b3e77477394594e8d3cc 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -22,7 +22,6 @@ #include "hw_drv.h" #include "../m_misc.h" //FIL_WriteFile() -#include "../r_draw.h" //viewborderlump #include "../r_main.h" #include "../w_wad.h" #include "../z_zone.h" @@ -30,13 +29,10 @@ #include "../st_stuff.h" #include "../p_local.h" // stplyr #include "../g_game.h" // players +#include "../f_finale.h" // fade color factors #include <fcntl.h> -#include "../i_video.h" // for rendermode != render_glide - -#ifndef O_BINARY -#define O_BINARY 0 -#endif +#include "../i_video.h" #if defined(_MSC_VER) #pragma pack(1) @@ -62,63 +58,6 @@ static UINT8 softwaretranstogl[11] = { 0, 25, 51, 76,102,127,153,178,204,229 static UINT8 softwaretranstogl_hi[11] = { 0, 51,102,153,204,255,255,255,255,255,255}; static UINT8 softwaretranstogl_lo[11] = { 0, 12, 24, 36, 48, 60, 71, 83, 95,111,127}; -// -// -----------------+ -// HWR_DrawPatch : Draw a 'tile' graphic -// Notes : x,y : positions relative to the original Doom resolution -// : textes(console+score) + menus + status bar -// -----------------+ -void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option) -{ - FOutVector v[4]; - FBITFIELD flags; - GLPatch_t *hwrPatch; - -// 3--2 -// | /| -// |/ | -// 0--1 - float sdup = FIXED_TO_FLOAT(vid.fdup)*2.0f; - float pdup = FIXED_TO_FLOAT(vid.fdup)*2.0f; - - // make patch ready in hardware cache - HWR_GetPatch(gpatch); - hwrPatch = ((GLPatch_t *)gpatch->hardware); - - switch (option & V_SCALEPATCHMASK) - { - case V_NOSCALEPATCH: - pdup = 2.0f; - break; - case V_SMALLSCALEPATCH: - pdup = 2.0f * FIXED_TO_FLOAT(vid.fsmalldup); - break; - case V_MEDSCALEPATCH: - pdup = 2.0f * FIXED_TO_FLOAT(vid.fmeddup); - break; - } - - if (option & V_NOSCALESTART) - sdup = 2.0f; - - v[0].x = v[3].x = (x*sdup-(gpatch->leftoffset)*pdup)/vid.width - 1; - v[2].x = v[1].x = (x*sdup+(gpatch->width-gpatch->leftoffset)*pdup)/vid.width - 1; - v[0].y = v[1].y = 1-(y*sdup-(gpatch->topoffset)*pdup)/vid.height; - v[2].y = v[3].y = 1-(y*sdup+(gpatch->height-gpatch->topoffset)*pdup)/vid.height; - - v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - - v[0].s = v[3].s = 0.0f; - v[2].s = v[1].s = hwrPatch->max_s; - v[0].t = v[1].t = 0.0f; - v[2].t = v[3].t = hwrPatch->max_t; - - flags = PF_Translucent|PF_NoDepthTest; - - // clip it since it is used for bunny scroll in doom I - HWD.pfnDrawPolygon(NULL, v, 4, flags); -} - void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap) { FOutVector v[4]; @@ -707,6 +646,7 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength) { FOutVector v[4]; FSurfaceInfo Surf; + FBITFIELD poly_flags = PF_NoTexture|PF_Modulated|PF_NoDepthTest; v[0].x = v[3].x = -1.0f; v[2].x = v[1].x = 1.0f; @@ -719,17 +659,59 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength) v[0].t = v[1].t = 1.0f; v[2].t = v[3].t = 0.0f; - if (color & 0xFF00) // Do COLORMAP fade. + if (color & 0xFF00) // Special fade options { - Surf.PolyColor.rgba = UINT2RGBA(0x01010160); - Surf.PolyColor.s.alpha = (strength*8); + UINT16 option = color & 0x0F00; + if (option == 0x0A00 || option == 0x0B00) // Tinted fades + { + INT32 r, g, b; + int fade = strength * 8; + + r = FADEREDFACTOR*fade/10; + g = FADEGREENFACTOR*fade/10; + b = FADEBLUEFACTOR*fade/10; + + Surf.PolyColor.s.red = min(r, 255); + Surf.PolyColor.s.green = min(g, 255); + Surf.PolyColor.s.blue = min(b, 255); + Surf.PolyColor.s.alpha = 255; + + if (option == 0x0A00) // Tinted subtractive fade + poly_flags |= PF_ReverseSubtract; + else if (option == 0x0B00) // Tinted additive fade + poly_flags |= PF_Additive; + } + else // COLORMAP fade + { + if (HWR_ShouldUsePaletteRendering()) + { + const hwdscreentexture_t scr_tex = HWD_SCREENTEXTURE_GENERIC2; + + Surf.LightTableId = HWR_GetLightTableID(NULL); + Surf.LightInfo.light_level = strength; + HWD.pfnMakeScreenTexture(scr_tex); + HWD.pfnSetShader(HWR_GetShaderFromTarget(SHADER_UI_COLORMAP_FADE)); + HWD.pfnDrawScreenTexture(scr_tex, &Surf, PF_ColorMapped|PF_NoDepthTest); + HWD.pfnUnSetShader(); + + return; + } + else + { + Surf.PolyColor.rgba = UINT2RGBA(0x01010160); + Surf.PolyColor.s.alpha = (strength*8); + poly_flags |= PF_Translucent; + } + } } else // Do TRANSMAP** fade. { - Surf.PolyColor.rgba = V_GetColor(color).rgba; + RGBA_t *palette = HWR_GetTexturePalette(); + Surf.PolyColor.rgba = palette[color&0xFF].rgba; Surf.PolyColor.s.alpha = softwaretranstogl[strength]; + poly_flags |= PF_Translucent; } - HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); + HWD.pfnDrawPolygon(&Surf, v, 4, poly_flags); } // -----------------+ @@ -897,7 +879,8 @@ void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 ac } else // Do TRANSMAP** fade. { - Surf.PolyColor.rgba = V_GetColor(actualcolor).rgba; + RGBA_t *palette = HWR_GetTexturePalette(); + Surf.PolyColor.rgba = palette[actualcolor&0xFF].rgba; Surf.PolyColor.s.alpha = softwaretranstogl[strength]; } HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); @@ -960,136 +943,6 @@ void HWR_DrawTutorialBack(UINT32 color, INT32 boxheight) HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } - -// ========================================================================== -// R_DRAW.C STUFF -// ========================================================================== - -// ------------------ -// HWR_DrawViewBorder -// Fill the space around the view window with a Doom flat texture, draw the -// beveled edges. -// 'clearlines' is useful to clear the heads up messages, when the view -// window is reduced, it doesn't refresh all the view borders. -// ------------------ -void HWR_DrawViewBorder(INT32 clearlines) -{ - INT32 x, y; - INT32 top, side; - INT32 baseviewwidth, baseviewheight; - INT32 basewindowx, basewindowy; - patch_t *patch; - -// if (gl_viewwidth == vid.width) -// return; - - if (!clearlines) - clearlines = BASEVIDHEIGHT; // refresh all - - // calc view size based on original game resolution - baseviewwidth = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewwidth), vid.fdup)); //(cv_viewsize.value * BASEVIDWIDTH/10)&~7; - baseviewheight = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewheight), vid.fdup)); - top = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_baseviewwindowy), vid.fdup)); - side = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewwindowx), vid.fdup)); - - // top - HWR_DrawFlatFill(0, 0, - BASEVIDWIDTH, (top < clearlines ? top : clearlines), - st_borderpatchnum); - - // left - if (top < clearlines) - HWR_DrawFlatFill(0, top, side, - (clearlines-top < baseviewheight ? clearlines-top : baseviewheight), - st_borderpatchnum); - - // right - if (top < clearlines) - HWR_DrawFlatFill(side + baseviewwidth, top, side, - (clearlines-top < baseviewheight ? clearlines-top : baseviewheight), - st_borderpatchnum); - - // bottom - if (top + baseviewheight < clearlines) - HWR_DrawFlatFill(0, top + baseviewheight, - BASEVIDWIDTH, BASEVIDHEIGHT, st_borderpatchnum); - - // - // draw the view borders - // - - basewindowx = (BASEVIDWIDTH - baseviewwidth)>>1; - if (baseviewwidth == BASEVIDWIDTH) - basewindowy = 0; - else - basewindowy = top; - - // top edge - if (clearlines > basewindowy - 8) - { - patch = W_CachePatchNum(viewborderlump[BRDR_T], PU_PATCH); - for (x = 0; x < baseviewwidth; x += 8) - HWR_DrawPatch(patch, basewindowx + x, basewindowy - 8, - 0); - } - - // bottom edge - if (clearlines > basewindowy + baseviewheight) - { - patch = W_CachePatchNum(viewborderlump[BRDR_B], PU_PATCH); - for (x = 0; x < baseviewwidth; x += 8) - HWR_DrawPatch(patch, basewindowx + x, - basewindowy + baseviewheight, 0); - } - - // left edge - if (clearlines > basewindowy) - { - patch = W_CachePatchNum(viewborderlump[BRDR_L], PU_PATCH); - for (y = 0; y < baseviewheight && basewindowy + y < clearlines; - y += 8) - { - HWR_DrawPatch(patch, basewindowx - 8, basewindowy + y, - 0); - } - } - - // right edge - if (clearlines > basewindowy) - { - patch = W_CachePatchNum(viewborderlump[BRDR_R], PU_PATCH); - for (y = 0; y < baseviewheight && basewindowy+y < clearlines; - y += 8) - { - HWR_DrawPatch(patch, basewindowx + baseviewwidth, - basewindowy + y, 0); - } - } - - // Draw beveled corners. - if (clearlines > basewindowy - 8) - HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_TL], - PU_PATCH), - basewindowx - 8, basewindowy - 8, 0); - - if (clearlines > basewindowy - 8) - HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_TR], - PU_PATCH), - basewindowx + baseviewwidth, basewindowy - 8, 0); - - if (clearlines > basewindowy+baseviewheight) - HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_BL], - PU_PATCH), - basewindowx - 8, basewindowy + baseviewheight, 0); - - if (clearlines > basewindowy + baseviewheight) - HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_BR], - PU_PATCH), - basewindowx + baseviewwidth, - basewindowy + baseviewheight, 0); -} - - // ========================================================================== // AM_MAP.C DRAWING STUFF // ========================================================================== @@ -1102,8 +955,9 @@ void HWR_drawAMline(const fline_t *fl, INT32 color) { F2DCoord v1, v2; RGBA_t color_rgba; + RGBA_t *palette = HWR_GetTexturePalette(); - color_rgba = V_GetColor(color); + color_rgba = palette[color&0xFF]; v1.x = ((float)fl->a.x-(vid.width/2.0f))*(2.0f/vid.width); v1.y = ((float)fl->a.y-(vid.height/2.0f))*(2.0f/vid.height); @@ -1288,6 +1142,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) FOutVector v[4]; FSurfaceInfo Surf; float fx, fy, fw, fh; + RGBA_t *palette = HWR_GetTexturePalette(); UINT8 alphalevel = ((color & V_ALPHAMASK) >> V_ALPHASHIFT); UINT8 perplayershuffle = 0; @@ -1374,7 +1229,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) { if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) { - RGBA_t rgbaColour = V_GetColor(color); + RGBA_t rgbaColour = palette[color&0xFF]; FRGBAFloat clearColour; clearColour.red = (float)rgbaColour.s.red / 255; clearColour.green = (float)rgbaColour.s.green / 255; @@ -1451,7 +1306,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) v[0].t = v[1].t = 0.0f; v[2].t = v[3].t = 1.0f; - Surf.PolyColor = V_GetColor(color); + Surf.PolyColor = palette[color&0xFF]; if (alphalevel) { @@ -1499,7 +1354,7 @@ static inline boolean saveTGA(const char *file_name, void *buffer, INT32 i; UINT8 *buf8 = buffer; - fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); + fd = open(file_name, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd < 0) return false; @@ -1539,11 +1394,12 @@ static inline boolean saveTGA(const char *file_name, void *buffer, UINT8 *HWR_GetScreenshot(void) { UINT8 *buf = malloc(vid.width * vid.height * 3 * sizeof (*buf)); + int tex = HWR_ShouldUsePaletteRendering() ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2; if (!buf) return NULL; // returns 24bit 888 RGB - HWD.pfnReadRect(0, 0, vid.width, vid.height, vid.width * 3, (void *)buf); + HWD.pfnReadScreenTexture(tex, (void *)buf); return buf; } @@ -1551,6 +1407,7 @@ boolean HWR_Screenshot(const char *pathname) { boolean ret; UINT8 *buf = malloc(vid.width * vid.height * 3 * sizeof (*buf)); + int tex = HWR_ShouldUsePaletteRendering() ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2; if (!buf) { @@ -1559,7 +1416,7 @@ boolean HWR_Screenshot(const char *pathname) } // returns 24bit 888 RGB - HWD.pfnReadRect(0, 0, vid.width, vid.height, vid.width * 3, (void *)buf); + HWD.pfnReadScreenTexture(tex, (void *)buf); #ifdef USE_PNG ret = M_SavePNG(pathname, buf, vid.width, vid.height, NULL); diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index 1c4cd99ab03d34498fa13d132a01ef53af9e6e61..a5fdc00a47c17e6b5cbeba5d074554a66672cde7 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -29,10 +29,7 @@ EXPORT boolean HWRAPI(Init) (void); #ifndef HAVE_SDL EXPORT void HWRAPI(Shutdown) (void); #endif -#ifdef _WINDOWS -EXPORT void HWRAPI(GetModeList) (vmode_t **pvidmodes, INT32 *numvidmodes); -#endif -EXPORT void HWRAPI(SetPalette) (RGBA_t *ppal); +EXPORT void HWRAPI(SetTexturePalette) (RGBA_t *ppal); EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl); EXPORT void HWRAPI(Draw2DLine) (F2DCoord *v1, F2DCoord *v2, RGBA_t Color); EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags); @@ -43,11 +40,10 @@ EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFl EXPORT void HWRAPI(SetTexture) (GLMipmap_t *TexInfo); EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *TexInfo); EXPORT void HWRAPI(DeleteTexture) (GLMipmap_t *TexInfo); -EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data); +EXPORT void HWRAPI(ReadScreenTexture) (int tex, UINT8 *dst_data); EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip); EXPORT void HWRAPI(ClearMipMapCache) (void); -//Hurdler: added for backward compatibility EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value); //Hurdler: added for new development @@ -57,24 +53,27 @@ EXPORT void HWRAPI(SetTransform) (FTransform *ptransform); EXPORT INT32 HWRAPI(GetTextureUsed) (void); EXPORT void HWRAPI(FlushScreenTextures) (void); -EXPORT void HWRAPI(StartScreenWipe) (void); -EXPORT void HWRAPI(EndScreenWipe) (void); -EXPORT void HWRAPI(DoScreenWipe) (void); -EXPORT void HWRAPI(DrawIntermissionBG) (void); -EXPORT void HWRAPI(MakeScreenTexture) (void); -EXPORT void HWRAPI(MakeScreenFinalTexture) (void); -EXPORT void HWRAPI(DrawScreenFinalTexture) (int width, int height); +EXPORT void HWRAPI(DoScreenWipe) (int wipeStart, int wipeEnd, FSurfaceInfo *surf, FBITFIELD polyFlags); +EXPORT void HWRAPI(DrawScreenTexture) (int tex, FSurfaceInfo *surf, FBITFIELD polyflags); +EXPORT void HWRAPI(MakeScreenTexture) (int tex); +EXPORT void HWRAPI(DrawScreenFinalTexture) (int tex, int width, int height); #define SCREENVERTS 10 EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]); -EXPORT boolean HWRAPI(CompileShaders) (void); -EXPORT void HWRAPI(CleanShaders) (void); -EXPORT void HWRAPI(SetShader) (int type); +EXPORT boolean HWRAPI(InitShaders) (void); +EXPORT void HWRAPI(LoadShader) (int slot, char *code, hwdshaderstage_t stage); +EXPORT boolean HWRAPI(CompileShader) (int slot); +EXPORT void HWRAPI(SetShader) (int slot); EXPORT void HWRAPI(UnSetShader) (void); EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value); -EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boolean isfragment); + +EXPORT void HWRAPI(SetPaletteLookup)(UINT8 *lut); +EXPORT UINT32 HWRAPI(CreateLightTable)(RGBA_t *hw_lighttable); +EXPORT void HWRAPI(UpdateLightTable)(UINT32 id, RGBA_t *hw_lighttable); +EXPORT void HWRAPI(ClearLightTables)(void); +EXPORT void HWRAPI(SetScreenPalette)(RGBA_t *palette); // ========================================================================== // HWR DRIVER OBJECT, FOR CLIENT PROGRAM @@ -85,7 +84,7 @@ EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boole struct hwdriver_s { Init pfnInit; - SetPalette pfnSetPalette; + SetTexturePalette pfnSetTexturePalette; FinishUpdate pfnFinishUpdate; Draw2DLine pfnDraw2DLine; DrawPolygon pfnDrawPolygon; @@ -96,10 +95,10 @@ struct hwdriver_s SetTexture pfnSetTexture; UpdateTexture pfnUpdateTexture; DeleteTexture pfnDeleteTexture; - ReadRect pfnReadRect; + ReadScreenTexture pfnReadScreenTexture; GClipRect pfnGClipRect; ClearMipMapCache pfnClearMipMapCache; - SetSpecialState pfnSetSpecialState;//Hurdler: added for backward compatibility + SetSpecialState pfnSetSpecialState; DrawModel pfnDrawModel; CreateModelVBOs pfnCreateModelVBOs; SetTransform pfnSetTransform; @@ -112,21 +111,24 @@ struct hwdriver_s #endif PostImgRedraw pfnPostImgRedraw; FlushScreenTextures pfnFlushScreenTextures; - StartScreenWipe pfnStartScreenWipe; - EndScreenWipe pfnEndScreenWipe; DoScreenWipe pfnDoScreenWipe; - DrawIntermissionBG pfnDrawIntermissionBG; + DrawScreenTexture pfnDrawScreenTexture; MakeScreenTexture pfnMakeScreenTexture; - MakeScreenFinalTexture pfnMakeScreenFinalTexture; DrawScreenFinalTexture pfnDrawScreenFinalTexture; - CompileShaders pfnCompileShaders; - CleanShaders pfnCleanShaders; + InitShaders pfnInitShaders; + LoadShader pfnLoadShader; + CompileShader pfnCompileShader; SetShader pfnSetShader; UnSetShader pfnUnSetShader; SetShaderInfo pfnSetShaderInfo; - LoadCustomShader pfnLoadCustomShader; + + SetPaletteLookup pfnSetPaletteLookup; + CreateLightTable pfnCreateLightTable; + UpdateLightTable pfnUpdateLightTable; + ClearLightTables pfnClearLightTables; + SetScreenPalette pfnSetScreenPalette; }; extern struct hwdriver_s hwdriver; diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index fbb02f46322c614107fc5523884e7081064c5c4a..bf9f7da3b4c126154fed2faf81761f348fbeed63 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -107,6 +107,8 @@ void HWR_FreeExtraSubsectors(void); // -------- // hw_cache.c // -------- +RGBA_t *HWR_GetTexturePalette(void); + void HWR_InitMapTextures(void); void HWR_LoadMapTextures(size_t pnumtextures); void HWR_FreeMapTextures(void); @@ -117,10 +119,9 @@ patch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum); void HWR_GetPatch(patch_t *patch); void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap); void HWR_GetFadeMask(lumpnum_t fademasklumpnum); -patch_t *HWR_GetPic(lumpnum_t lumpnum); -GLMapTexture_t *HWR_GetTexture(INT32 tex); -void HWR_GetLevelFlat(levelflat_t *levelflat); +GLMapTexture_t *HWR_GetTexture(INT32 tex, boolean chromakeyed); +void HWR_GetLevelFlat(levelflat_t *levelflat, boolean chromakeyed); void HWR_GetRawFlat(lumpnum_t flatlumpnum); void HWR_FreeTexture(patch_t *patch); @@ -131,6 +132,11 @@ void HWR_FreeColormapCache(void); void HWR_UnlockCachedPatch(GLPatch_t *gpatch); void HWR_SetPalette(RGBA_t *palette); +void HWR_SetMapPalette(void); +UINT32 HWR_CreateLightTable(UINT8 *lighttable, RGBA_t *hw_lighttable); +void HWR_UpdateLightTable(UINT32 id, UINT8 *lighttable, RGBA_t *hw_lighttable); +UINT32 HWR_GetLightTableID(extracolormap_t *colormap); +void HWR_ClearLightTables(void); // -------- @@ -139,4 +145,18 @@ void HWR_SetPalette(RGBA_t *palette); extern INT32 patchformat; extern INT32 textureformat; +// -------- +// hw_shaders.c +// -------- +boolean HWR_InitShaders(void); +void HWR_CompileShaders(void); + +int HWR_GetShaderFromTarget(int shader_target); + +void HWR_LoadAllCustomShaders(void); +void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3); +const char *HWR_GetShaderName(INT32 shader); + +extern customshaderxlat_t shaderxlat[]; + #endif //_HW_GLOB_ diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index bcfdfa960d7b723ecb0be2437667bcf09b1030e9..9011ff05ec855c45291c95946adf110365c2839b 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -395,6 +395,8 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_XMS4 &lspr[NOLIGHT], // SPR_XMS5 &lspr[NOLIGHT], // SPR_XMS6 + &lspr[NOLIGHT], // SPR_SNTT + &lspr[NOLIGHT], // SPR_SSTT &lspr[NOLIGHT], // SPR_FHZI &lspr[NOLIGHT], // SPR_ROSY @@ -428,6 +430,8 @@ light_t *t_lspr[NUMSPRITES] = // Misc Scenery &lspr[NOLIGHT], // SPR_STLG &lspr[NOLIGHT], // SPR_DBAL + &lspr[NOLIGHT], // SPR_GINE + &lspr[NOLIGHT], // SPR_PPAL // Powerup Indicators &lspr[NOLIGHT], // SPR_ARMA @@ -614,6 +618,9 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_GWLG &lspr[NOLIGHT], // SPR_GWLR + // LJ Knuckles + &lspr[NOLIGHT], // SPR_OLDK, + // Free slots &lspr[NOLIGHT], &lspr[NOLIGHT], @@ -1055,7 +1062,7 @@ void HWR_DoCoronasLighting(FOutVector *outVerts, gl_vissprite_t *spr) light[3].y = cy+size*1.33f+p_lspr->light_yoffset; light[3].s = 0.0f; light[3].t = 1.0f; - HWR_GetPic(coronalumpnum); /// \todo use different coronas + // HWR_GetPic(coronalumpnum); /// \todo use different coronas HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Corona | PF_NoDepthTest); } @@ -1071,7 +1078,7 @@ void HWR_DrawCoronas(void) if (!cv_glcoronas.value || dynlights->nb <= 0 || coronalumpnum == LUMPERROR) return; - HWR_GetPic(coronalumpnum); /// \todo use different coronas + // HWR_GetPic(coronalumpnum); /// \todo use different coronas for (j = 0;j < dynlights->nb;j++) { FOutVector light[4]; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index fee1987683817c6183027f2095632ba8e5bdbec2..a5befe112c60bc704e58b3c3467944b2dd1ed971 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -19,8 +19,10 @@ #include "hw_light.h" #include "hw_drv.h" #include "hw_batching.h" +#include "hw_md2.h" +#include "hw_clip.h" -#include "../i_video.h" // for rendermode == render_glide +#include "../i_video.h" #include "../v_video.h" #include "../p_local.h" #include "../p_setup.h" @@ -42,15 +44,6 @@ #include "../r_translation.h" #include "../d_main.h" #include "../p_slopes.h" -#include "hw_md2.h" - -#ifdef NEWCLIP -#include "hw_clip.h" -#endif - -#define R_FAKEFLOORS -#define HWPRECIP -//#define POLYSKY // ========================================================================== // the hardware driver object @@ -61,95 +54,27 @@ struct hwdriver_s hwdriver; // PROTOS // ========================================================================== - static void HWR_AddSprites(sector_t *sec); 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_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, boolean chromakeyed, extracolormap_t *planecolormap); void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap); -boolean drawsky = true; - -// ========================================================================== -// VIEW GLOBALS -// ========================================================================== -// Fineangles in the SCREENWIDTH wide window. -#define FIELDOFVIEW ANGLE_90 -#define ABS(x) ((x) < 0 ? -(x) : (x)) - -static angle_t gl_clipangle; - -// The viewangletox[viewangle + FINEANGLES/4] lookup -// maps the visible view angles to screen X coordinates, -// flattening the arc to a flat projection plane. -// There will be many angles mapped to the same X. -static INT32 gl_viewangletox[FINEANGLES/2]; - -// The xtoviewangleangle[] table maps a screen pixel -// to the lowest viewangle that maps back to x ranges -// from clipangle to -clipangle. -static angle_t gl_xtoviewangle[MAXVIDWIDTH+1]; +static boolean drawsky = true; // ========================================================================== // GLOBALS // ========================================================================== -// uncomment to remove the plane rendering -#define DOPLANES -//#define DOWALLS - -// test of drawing sky by polygons like in software with visplane, unfortunately -// this doesn't work since we must have z for pixel and z for texture (not like now with z = oow) -//#define POLYSKY - -// test change fov when looking up/down but bsp projection messup :( -//#define NOCRAPPYMLOOK - -// base values set at SetViewSize -static float gl_basecentery; - -float gl_baseviewwindowy, gl_basewindowcentery; -float gl_viewwidth, gl_viewheight; // viewport clipping boundaries (screen coords) -float gl_viewwindowx; - -static float gl_centerx, gl_centery; -static float gl_viewwindowy; // top left corner of view window -static float gl_windowcenterx; // center of view window, for projection -static float gl_windowcentery; - -static float gl_pspritexscale, gl_pspriteyscale; - static seg_t *gl_curline; static side_t *gl_sidedef; static line_t *gl_linedef; static sector_t *gl_frontsector; static sector_t *gl_backsector; -// -------------------------------------------------------------------------- -// STUFF FOR THE PROJECTION CODE -// -------------------------------------------------------------------------- - -FTransform atransform; -// duplicates of the main code, set after R_SetupFrame() passed them into sharedstruct, -// copied here for local use -static fixed_t dup_viewx, dup_viewy, dup_viewz; -static angle_t dup_viewangle; - -static float gl_viewx, gl_viewy, gl_viewz; -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 -static float gl_fovlud; - -static angle_t gl_aimingangle; -static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean skybox); - // Render stats ps_metric_t ps_hw_skyboxtime = {0}; ps_metric_t ps_hw_nodesorttime = {0}; @@ -170,13 +95,35 @@ ps_metric_t ps_hw_batchdrawtime = {0}; boolean gl_init = false; boolean gl_maploaded = false; -boolean gl_shadersavailable = true; +boolean gl_sessioncommandsadded = false; +// false if shaders have not been initialized yet, or if shaders are not available +boolean gl_shadersavailable = false; + +// Whether the internal state is set to palette rendering or not. +static boolean gl_palette_rendering_state = false; + +// -------------------------------------------------------------------------- +// STUFF FOR THE PROJECTION CODE +// -------------------------------------------------------------------------- + +FTransform atransform; + +static float gl_viewx, gl_viewy, gl_viewz; +float gl_viewsin, gl_viewcos; + +// For HWR_RotateSpritePolyToAim +static float gl_viewludsin, gl_viewludcos; +static float gl_fovlud; + +static angle_t gl_aimingangle; +static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean skybox); // ========================================================================== // Lighting // ========================================================================== -static boolean HWR_UseShader(void) +// Returns true if shaders can be used. +boolean HWR_UseShader(void) { return (cv_glshaders.value && gl_shadersavailable); } @@ -242,6 +189,11 @@ void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *col Surface->LightInfo.light_level = light_level; Surface->LightInfo.fade_start = (colormap != NULL) ? colormap->fadestart : 0; Surface->LightInfo.fade_end = (colormap != NULL) ? colormap->fadeend : 31; + + if (HWR_ShouldUsePaletteRendering()) + Surface->LightTableId = HWR_GetLightTableID(colormap); + else + Surface->LightTableId = 0; } UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap) // Let's see if this can work @@ -357,12 +309,47 @@ static FUINT HWR_CalcSlopeLight(FUINT lightnum, angle_t dir, fixed_t delta) return (FUINT)finallight; } +static UINT8 HWR_SideLightLevel(side_t *side, INT16 base_lightlevel) +{ + return max(0, min(255, side->light + + ((side->lightabsolute) ? 0 : base_lightlevel))); +} + +/* TODO: implement per-texture lighting +static UINT8 HWR_TopLightLevel(side_t *side, INT16 base_lightlevel) +{ + return max(0, min(255, side->light_top + + ((side->lightabsolute_top) ? 0 : HWR_SideLightLevel(side, base_lightlevel)))); +} + +static UINT8 HWR_MidLightLevel(side_t *side, INT16 base_lightlevel) +{ + return max(0, min(255, side->light_mid + + ((side->lightabsolute_mid) ? 0 : HWR_SideLightLevel(side, base_lightlevel)))); +} + +static UINT8 HWR_BottomLightLevel(side_t *side, INT16 base_lightlevel) +{ + return max(0, min(255, side->light_bottom + + ((side->lightabsolute_bottom) ? 0 : HWR_SideLightLevel(side, base_lightlevel)))); +} +*/ + +static UINT8 HWR_FloorLightLevel(sector_t *sector, INT16 base_lightlevel) +{ + return max(0, min(255, sector->floorlightlevel + + ((sector->floorlightabsolute) ? 0 : base_lightlevel))); +} + +static UINT8 HWR_CeilingLightLevel(sector_t *sector, INT16 base_lightlevel) +{ + return max(0, min(255, sector->ceilinglightlevel + + ((sector->ceilinglightabsolute) ? 0 : base_lightlevel))); +} // ========================================================================== // FLOOR/CEILING GENERATION FROM SUBSECTORS // ========================================================================== -#ifdef DOPLANES - // -----------------+ // HWR_RenderPlane : Render a floor or ceiling convex polygon // -----------------+ @@ -372,7 +359,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool FOutVector *v3d; polyvertex_t *pv; pslope_t *slope = NULL; - INT32 shader = SHADER_DEFAULT; + INT32 shader = SHADER_NONE; size_t nrPlaneVerts; INT32 i; @@ -389,6 +376,9 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; + if (!r_renderfloors) + return; + // no convex poly were generated for this subsector if (!xsub->planepoly) return; @@ -551,7 +541,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool for (i = 0; i < subsector->numlines; i++, line++) { - if (!line->glseg && line->linedef->special == SPECIAL_HORIZON_LINE && R_PointOnSegSide(dup_viewx, dup_viewy, line) == 0) + if (!line->glseg && line->linedef->special == SPECIAL_HORIZON_LINE && R_PointOnSegSide(viewx, viewy, line) == 0) { P_ClosestPointOnLine(viewx, viewy, line->linedef, &v); dist = FIXED_TO_FLOAT(R_PointToDist(v.x, v.y)); @@ -630,52 +620,6 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool #endif } -#ifdef POLYSKY -// this don't draw anything it only update the z-buffer so there isn't problem with -// wall/things upper that sky (map12) -static void HWR_RenderSkyPlane(extrasubsector_t *xsub, fixed_t fixedheight) -{ - polyvertex_t *pv; - float height; //constant y for all points on the convex flat polygon - FOutVector *v3d; - INT32 nrPlaneVerts; //verts original define of convex flat polygon - INT32 i; - - // no convex poly were generated for this subsector - if (!xsub->planepoly) - return; - - height = FIXED_TO_FLOAT(fixedheight); - - pv = xsub->planepoly->pts; - nrPlaneVerts = xsub->planepoly->numpts; - - if (nrPlaneVerts < 3) // not even a triangle? - return; - - if (nrPlaneVerts > MAXPLANEVERTICES) // FIXME: exceeds plVerts size - { - CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, MAXPLANEVERTICES); - return; - } - - // transform - v3d = planeVerts; - for (i = 0; i < nrPlaneVerts; i++,v3d++,pv++) - { - v3d->s = 0.0f; - v3d->t = 0.0f; - v3d->x = pv->x; - v3d->y = height; - v3d->z = pv->y; - } - - HWD.pfnDrawPolygon(NULL, planeVerts, nrPlaneVerts, PF_Invisible|PF_NoTexture|PF_Occlude); -} -#endif //polysky - -#endif //doplanes - FBITFIELD HWR_GetBlendModeFlag(INT32 style) { switch (style) @@ -759,7 +703,10 @@ static void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, I // static void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap) { - INT32 shader = SHADER_DEFAULT; + INT32 shader = SHADER_NONE; + + if (!r_renderwalls) + return; HWR_Lighting(pSurf, lightlevel, wallcolormap); @@ -776,41 +723,6 @@ static void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIEL // BSP, CULL, ETC.. // ========================================================================== -// return the frac from the interception of the clipping line -// (in fact a clipping plane that has a constant, so can clip with simple 2d) -// with the wall segment -// -#ifndef NEWCLIP -static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2) -{ - float num, den; - float v1x, v1y, v1dx, v1dy, v2dx, v2dy; - angle_t pclipangle = gl_xtoviewangle[x]; - - // a segment of a polygon - v1x = v1->x; - v1y = v1->y; - v1dx = (v2->x - v1->x); - v1dy = (v2->y - v1->y); - - // the clipping line - pclipangle = pclipangle + dup_viewangle; //back to normal angle (non-relative) - v2dx = FIXED_TO_FLOAT(FINECOSINE(pclipangle>>ANGLETOFINESHIFT)); - v2dy = FIXED_TO_FLOAT(FINESINE(pclipangle>>ANGLETOFINESHIFT)); - - den = v2dy*v1dx - v2dx*v1dy; - if (den == 0) - return -1; // parallel - - // calc the frac along the polygon segment, - //num = (v2x - v1x)*v2dy + (v1y - v2y)*v2dx; - //num = -v1x * v2dy + v1y * v2dx; - num = (gl_viewx - v1x)*v2dy + (v1y - gl_viewy)*v2dx; - - return num / den; -} -#endif - // SoM: split up and light walls according to the lightlist. // This may also include leaving out parts of the wall that can't be seen static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, FSurfaceInfo* Surf, INT32 cutflag, ffloor_t *pfloor, FBITFIELD polyflags) @@ -830,10 +742,14 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, fixed_t v2x = FloatToFixed(wallVerts[1].x); fixed_t v2y = FloatToFixed(wallVerts[1].z); + FUINT lightnum = HWR_SideLightLevel(gl_sidedef, sector->lightlevel); const UINT8 alpha = Surf->PolyColor.s.alpha; - FUINT lightnum = HWR_CalcWallLight(sector->lightlevel, v1x, v1y, v2x, v2y); + lightnum = HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y); extracolormap_t *colormap = NULL; + if (!r_renderwalls) + return; + realtop = top = wallVerts[3].y; realbot = bot = wallVerts[0].y; diff = top - bot; @@ -872,13 +788,15 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, { if (pfloor && (pfloor->fofflags & FOF_FOG)) { - lightnum = HWR_CalcWallLight(pfloor->master->frontsector->lightlevel, v1x, v1y, v2x, v2y); + lightnum = HWR_SideLightLevel(gl_sidedef, pfloor->master->frontsector->lightlevel); colormap = pfloor->master->frontsector->extra_colormap; + lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y); } else { - lightnum = HWR_CalcWallLight(*list[i].lightlevel, v1x, v1y, v2x, v2y); + lightnum = HWR_SideLightLevel(gl_sidedef, *list[i].lightlevel); colormap = *list[i].extra_colormap; + lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y); } } @@ -998,7 +916,7 @@ static void HWR_DrawSkyWall(FOutVector *wallVerts, FSurfaceInfo *Surf) // PF_Occlude is set in HWR_ProjectWall to draw into the depth buffer } -// Returns true if the midtexture is visible, and false if... it isn't... +// Returns true if the midtexture is visible, false if not static boolean HWR_BlendMidtextureSurface(FSurfaceInfo *pSurf) { FUINT blendmode = PF_Masked; @@ -1034,14 +952,204 @@ static boolean HWR_BlendMidtextureSurface(FSurfaceInfo *pSurf) return true; } -// -// HWR_ProcessSeg -// A portion or all of a wall segment will be drawn, from startfrac to endfrac, -// where 0 is the start of the segment, 1 the end of the segment -// Anything between means the wall segment has been clipped with solidsegs, -// reducing wall overdraw to a minimum -// -static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom +static void HWR_RenderMidtexture(INT32 gl_midtexture, float cliplow, float cliphigh, fixed_t worldtop, fixed_t worldbottom, fixed_t worldhigh, fixed_t worldlow, fixed_t worldtopslope, fixed_t worldbottomslope, fixed_t worldhighslope, fixed_t worldlowslope, UINT32 lightnum, FOutVector *inWallVerts) +{ + sector_t *front, *back; + FOutVector wallVerts[4]; + + FSurfaceInfo Surf; + Surf.PolyColor.s.alpha = 255; + + // Determine if it's visible + if (!HWR_BlendMidtextureSurface(&Surf)) + return; + + if (gl_linedef->frontsector->heightsec != -1) + front = §ors[gl_linedef->frontsector->heightsec]; + else + front = gl_linedef->frontsector; + + if (gl_linedef->backsector->heightsec != -1) + back = §ors[gl_linedef->backsector->heightsec]; + else + back = gl_linedef->backsector; + + fixed_t texheight = FixedDiv(textureheight[gl_midtexture], abs(gl_sidedef->scaley_mid)); + INT32 repeats; + + if (gl_sidedef->repeatcnt) + repeats = 1 + gl_sidedef->repeatcnt; + else if (gl_linedef->flags & ML_WRAPMIDTEX) + { + fixed_t high, low; + + if (front->ceilingheight > back->ceilingheight) + high = back->ceilingheight; + else + high = front->ceilingheight; + + if (front->floorheight > back->floorheight) + low = front->floorheight; + else + low = back->floorheight; + + repeats = (high - low) / texheight; + if ((high - low) % texheight) + repeats++; // tile an extra time to fill the gap -- Monster Iestyn + } + else + repeats = 1; + + GLMapTexture_t *grTex = HWR_GetTexture(gl_midtexture, true); + float xscale = FixedToFloat(gl_sidedef->scalex_mid); + float yscale = FixedToFloat(gl_sidedef->scaley_mid); + + // SoM: a little note: popentop and popenbottom + // record the limits the texture can be displayed in. + // polytop and polybottom, are the ideal (i.e. unclipped) + // heights of the polygon, and h & l, are the final (clipped) + // poly coords. + fixed_t popentop, popenbottom, polytop, polybottom, lowcut, highcut; + fixed_t popentopslope, popenbottomslope, polytopslope, polybottomslope, lowcutslope, highcutslope; + + // NOTE: With polyobjects, whenever you need to check the properties of the polyobject sector it belongs to, + // you must use the linedef's backsector to be correct + // From CB + if (gl_curline->polyseg) + { + // Change this when polyobjects support slopes + popentop = popentopslope = back->ceilingheight; + popenbottom = popenbottomslope = back->floorheight; + } + else + { + popentop = min(worldtop, worldhigh); + popenbottom = max(worldbottom, worldlow); + popentopslope = min(worldtopslope, worldhighslope); + popenbottomslope = max(worldbottomslope, worldlowslope); + } + + // Find the wall's coordinates + fixed_t midtexheight = texheight * repeats; + + fixed_t rowoffset = FixedDiv(gl_sidedef->rowoffset + gl_sidedef->offsety_mid, abs(gl_sidedef->scaley_mid)); + + // Texture is not skewed + if (gl_linedef->flags & ML_NOSKEW) + { + // Peg it to the floor + if (gl_linedef->flags & ML_MIDPEG) + { + polybottom = max(gl_frontsector->floorheight, gl_backsector->floorheight) + rowoffset; + polytop = polybottom + midtexheight; + } + // Peg it to the ceiling + else + { + polytop = min(gl_frontsector->ceilingheight, gl_backsector->ceilingheight) + rowoffset; + polybottom = polytop - midtexheight; + } + + // The right side's coordinates are the the same as the left side + polytopslope = polytop; + polybottomslope = polybottom; + } + // Skew the texture, but peg it to the floor + else if (gl_linedef->flags & ML_MIDPEG) + { + polybottom = popenbottom + rowoffset; + polytop = polybottom + midtexheight; + polybottomslope = popenbottomslope + rowoffset; + polytopslope = polybottomslope + midtexheight; + } + // Skew it according to the ceiling's slope + else + { + polytop = popentop + rowoffset; + polybottom = polytop - midtexheight; + polytopslope = popentopslope + rowoffset; + polybottomslope = polytopslope - midtexheight; + } + + // The cut-off values of a linedef can always be constant, since every line has an absoulute front and or back sector + if (gl_curline->polyseg) + { + lowcut = polybottom; + highcut = polytop; + lowcutslope = polybottomslope; + highcutslope = polytopslope; + } + else + { + lowcut = popenbottom; + highcut = popentop; + lowcutslope = popenbottomslope; + highcutslope = popentopslope; + } + + fixed_t h = min(highcut, polytop); + fixed_t l = max(polybottom, lowcut); + fixed_t hS = min(highcutslope, polytopslope); + fixed_t lS = max(polybottomslope, lowcutslope); + + // PEGGING + fixed_t texturevpeg, texturevpegslope; + + if (gl_linedef->flags & ML_MIDPEG) + { + texturevpeg = midtexheight - h + polybottom; + texturevpegslope = midtexheight - hS + polybottomslope; + } + else + { + texturevpeg = polytop - h; + texturevpegslope = polytopslope - hS; + } + + memcpy(wallVerts, inWallVerts, sizeof(wallVerts)); + + // Left side + wallVerts[3].t = texturevpeg * yscale * grTex->scaleY; + wallVerts[0].t = (h - l + texturevpeg) * yscale * grTex->scaleY; + wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + gl_sidedef->textureoffset + gl_sidedef->offsetx_mid) * grTex->scaleX; + + // Right side + wallVerts[2].t = texturevpegslope * yscale * grTex->scaleY; + wallVerts[1].t = (hS - lS + texturevpegslope) * yscale * grTex->scaleY; + wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + gl_sidedef->textureoffset + gl_sidedef->offsetx_mid) * grTex->scaleX; + + // set top/bottom coords + // Take the texture peg into account, rather than changing the offsets past + // where the polygon might not be. + wallVerts[3].y = FIXED_TO_FLOAT(h); + wallVerts[0].y = FIXED_TO_FLOAT(l); + wallVerts[2].y = FIXED_TO_FLOAT(hS); + wallVerts[1].y = FIXED_TO_FLOAT(lS); + + // TODO: Actually use the surface's flags so that I don't have to do this + FUINT blendmode = Surf.PolyFlags; + + // Render midtextures on two-sided lines with a z-buffer offset. + // This will cause the midtexture appear on top, if a FOF overlaps with it. + blendmode |= PF_Decal; + + extracolormap_t *colormap = gl_frontsector->extra_colormap; + + if (gl_frontsector->numlights) + { + if (!(blendmode & PF_Masked)) + HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FOF_TRANSLUCENT, NULL, blendmode); + else + HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FOF_CUTLEVEL, NULL, blendmode); + } + else if (!(blendmode & PF_Masked)) + HWR_AddTransparentWall(wallVerts, &Surf, gl_midtexture, blendmode, false, lightnum, colormap); + else + HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap); +} + +// Sort of like GLWall::Process in GZDoom +static void HWR_ProcessSeg(void) { FOutVector wallVerts[4]; v2d_t vs, ve; // start, end vertices of 2d line (view from above) @@ -1105,12 +1213,12 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[2].z = wallVerts[1].z = ve.y; // x offset the texture - fixed_t texturehpeg = gl_sidedef->textureoffset + gl_curline->offset; - float cliplow = (float)texturehpeg; - float cliphigh = (float)(texturehpeg + (gl_curline->flength*FRACUNIT)); + float cliplow = (float)gl_curline->offset; + float cliphigh = cliplow + (gl_curline->flength * FRACUNIT); - FUINT lightnum = HWR_CalcWallLight(gl_frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); + FUINT lightnum = HWR_SideLightLevel(gl_sidedef, gl_frontsector->lightlevel); extracolormap_t *colormap = gl_frontsector->extra_colormap; + lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y); FSurfaceInfo Surf; Surf.PolyColor.s.alpha = 255; @@ -1122,6 +1230,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if (gl_backsector) { INT32 gl_toptexture = 0, gl_bottomtexture = 0; + fixed_t texturevpeg; SLOPEPARAMS(gl_backsector->c_slope, worldhigh, worldhighslope, gl_backsector->ceilingheight) @@ -1150,31 +1259,47 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // check TOP TEXTURE if ((worldhighslope < worldtopslope || worldhigh < worldtop) && gl_toptexture) { - grTex = HWR_GetTexture(gl_toptexture); - xscale = FixedToFloat(gl_sidedef->scalex_top); - yscale = FixedToFloat(gl_sidedef->scaley_top); + grTex = HWR_GetTexture(gl_toptexture, false); + xscale = FixedToFloat(abs(gl_sidedef->scalex_top)); + yscale = FixedToFloat(abs(gl_sidedef->scaley_top)); + + fixed_t offsetx_top = gl_sidedef->textureoffset + gl_sidedef->offsetx_top; + + float left = cliplow * xscale; + float right = cliphigh * xscale; + if (gl_sidedef->scalex_top < 0) + { + left = -left; + right = -right; + offsetx_top = -offsetx_top; + } - fixed_t texheight = FixedDiv(textureheight[gl_toptexture], gl_sidedef->scaley_top); + fixed_t texheight = textureheight[gl_toptexture]; + fixed_t texheightscaled = FixedDiv(texheight, abs(gl_sidedef->scaley_top)); // PEGGING + // FIXME: This is probably not correct? if (gl_linedef->flags & ML_DONTPEGTOP) texturevpeg = 0; else if (gl_linedef->flags & ML_SKEWTD) texturevpeg = worldhigh + texheight - worldtop; else - texturevpeg = gl_backsector->ceilingheight + texheight - gl_frontsector->ceilingheight; + texturevpeg = gl_backsector->ceilingheight + texheightscaled - gl_frontsector->ceilingheight; texturevpeg *= yscale; - texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_top; + if (gl_sidedef->scaley_top < 0) + texturevpeg -= gl_sidedef->rowoffset + gl_sidedef->offsety_top; + else + 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 %= texheight; + texturevpeg %= texheightscaled; wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; wallVerts[0].t = wallVerts[1].t = (texturevpeg + (gl_frontsector->ceilingheight - gl_backsector->ceilingheight) * yscale) * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + gl_sidedef->offsetx_top) * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + gl_sidedef->offsetx_top) * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = (left + offsetx_top) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = (right + offsetx_top) * grTex->scaleX; // Adjust t value for sloped walls if (!(gl_linedef->flags & ML_SKEWTD)) @@ -1199,6 +1324,14 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[2].t = wallVerts[1].t - (worldtopslope - worldhighslope) * yscale * grTex->scaleY; } + if (gl_sidedef->scaley_top < 0) + { + wallVerts[0].t = -wallVerts[0].t; + wallVerts[1].t = -wallVerts[1].t; + wallVerts[2].t = -wallVerts[2].t; + wallVerts[3].t = -wallVerts[3].t; + } + // set top/bottom coords wallVerts[3].y = FIXED_TO_FLOAT(worldtop); wallVerts[0].y = FIXED_TO_FLOAT(worldhigh); @@ -1216,9 +1349,20 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // check BOTTOM TEXTURE if ((worldlowslope > worldbottomslope || worldlow > worldbottom) && gl_bottomtexture) { - grTex = HWR_GetTexture(gl_bottomtexture); - xscale = FixedToFloat(gl_sidedef->scalex_bottom); - yscale = FixedToFloat(gl_sidedef->scaley_bottom); + grTex = HWR_GetTexture(gl_bottomtexture, false); + xscale = FixedToFloat(abs(gl_sidedef->scalex_bottom)); + yscale = FixedToFloat(abs(gl_sidedef->scaley_bottom)); + + fixed_t offsetx_bottom = gl_sidedef->textureoffset + gl_sidedef->offsetx_bottom; + + float left = cliplow * xscale; + float right = cliphigh * xscale; + if (gl_sidedef->scalex_bottom < 0) + { + left = -left; + right = -right; + offsetx_bottom = -offsetx_bottom; + } // PEGGING if (!(gl_linedef->flags & ML_DONTPEGBOTTOM)) @@ -1230,15 +1374,18 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom texturevpeg *= yscale; - texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_bottom; + if (gl_sidedef->scaley_bottom < 0) + texturevpeg -= gl_sidedef->rowoffset + gl_sidedef->offsety_bottom; + else + texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_bottom; // 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 %= FixedDiv(textureheight[gl_bottomtexture], gl_sidedef->scaley_bottom); + texturevpeg %= FixedDiv(textureheight[gl_bottomtexture], abs(gl_sidedef->scaley_bottom)); wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; wallVerts[0].t = wallVerts[1].t = (texturevpeg + (gl_backsector->floorheight - gl_frontsector->floorheight) * yscale) * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + gl_sidedef->offsetx_bottom) * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + gl_sidedef->offsetx_bottom) * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = (left + offsetx_bottom) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = (right + offsetx_bottom) * grTex->scaleX; // Adjust t value for sloped walls if (!(gl_linedef->flags & ML_SKEWTD)) @@ -1262,6 +1409,14 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[1].t = (texturevpeg + (worldlowslope - worldbottomslope) * yscale) * grTex->scaleY; } + if (gl_sidedef->scaley_bottom < 0) + { + wallVerts[0].t = -wallVerts[0].t; + wallVerts[1].t = -wallVerts[1].t; + wallVerts[2].t = -wallVerts[2].t; + wallVerts[3].t = -wallVerts[3].t; + } + // set top/bottom coords wallVerts[3].y = FIXED_TO_FLOAT(worldlow); wallVerts[0].y = FIXED_TO_FLOAT(worldbottom); @@ -1276,241 +1431,59 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap); } - // Render midtexture if there's one. Determine if it's visible first, though - if (gl_midtexture && HWR_BlendMidtextureSurface(&Surf)) - { - sector_t *front, *back; - fixed_t texheight = FixedDiv(textureheight[gl_midtexture], gl_sidedef->scaley_mid); - INT32 repeats; - - if (gl_linedef->frontsector->heightsec != -1) - front = §ors[gl_linedef->frontsector->heightsec]; - else - front = gl_linedef->frontsector; - - if (gl_linedef->backsector->heightsec != -1) - back = §ors[gl_linedef->backsector->heightsec]; - else - back = gl_linedef->backsector; + // Render midtexture if there's one + if (gl_midtexture) + HWR_RenderMidtexture(gl_midtexture, cliplow, cliphigh, worldtop, worldbottom, worldhigh, worldlow, worldtopslope, worldbottomslope, worldhighslope, worldlowslope, lightnum, wallVerts); - if (gl_sidedef->repeatcnt) - repeats = 1 + gl_sidedef->repeatcnt; - else if (gl_linedef->flags & ML_WRAPMIDTEX) + if (!gl_curline->polyseg) // Don't do it for polyobjects + { + // Sky culling + // No longer so much a mess as before! + if (gl_frontsector->ceilingpic == skyflatnum + && gl_backsector->ceilingpic != skyflatnum) // don't cull if back sector is also sky { - fixed_t high, low; - - if (front->ceilingheight > back->ceilingheight) - high = back->ceilingheight; - else - high = front->ceilingheight; - - if (front->floorheight > back->floorheight) - low = front->floorheight; - else - low = back->floorheight; - - repeats = (high - low) / texheight; - if ((high - low) % texheight) - repeats++; // tile an extra time to fill the gap -- Monster Iestyn + wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(INT32_MAX); // draw to top of map space + wallVerts[0].y = FIXED_TO_FLOAT(worldtop); + wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope); + HWR_DrawSkyWall(wallVerts, &Surf); } - else - repeats = 1; - grTex = HWR_GetTexture(gl_midtexture); + if (gl_frontsector->floorpic == skyflatnum + && gl_backsector->floorpic != skyflatnum) // same thing here + { + wallVerts[3].y = FIXED_TO_FLOAT(worldbottom); + wallVerts[2].y = FIXED_TO_FLOAT(worldbottomslope); + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(INT32_MIN); // draw to bottom of map space + HWR_DrawSkyWall(wallVerts, &Surf); + } + } + } + else + { + // Single sided line... Deal only with the middletexture (if one exists) + if (gl_midtexture && gl_linedef->special != SPECIAL_HORIZON_LINE) // (Ignore horizon line for OGL) + { + grTex = HWR_GetTexture(gl_midtexture, false); xscale = FixedToFloat(gl_sidedef->scalex_mid); yscale = FixedToFloat(gl_sidedef->scaley_mid); - // SoM: a little note: popentop and popenbottom - // record the limits the texture can be displayed in. - // polytop and polybottom, are the ideal (i.e. unclipped) - // heights of the polygon, and h & l, are the final (clipped) - // poly coords. - fixed_t popentop, popenbottom, polytop, polybottom, lowcut, highcut; - fixed_t popentopslope, popenbottomslope, polytopslope, polybottomslope, lowcutslope, highcutslope; - - // NOTE: With polyobjects, whenever you need to check the properties of the polyobject sector it belongs to, - // you must use the linedef's backsector to be correct - // From CB - if (gl_curline->polyseg) - { - popentop = popentopslope = back->ceilingheight; - popenbottom = popenbottomslope = back->floorheight; - } + fixed_t texturevpeg; + + // PEGGING + if ((gl_linedef->flags & (ML_DONTPEGBOTTOM|ML_NOSKEW)) == (ML_DONTPEGBOTTOM|ML_NOSKEW)) + texturevpeg = (gl_frontsector->floorheight + textureheight[gl_sidedef->midtexture] - gl_frontsector->ceilingheight) * yscale; + else if (gl_linedef->flags & ML_DONTPEGBOTTOM) + texturevpeg = (worldbottom + textureheight[gl_sidedef->midtexture] - worldtop) * yscale; else - { - popentop = min(worldtop, worldhigh); - popenbottom = max(worldbottom, worldlow); - popentopslope = min(worldtopslope, worldhighslope); - popenbottomslope = max(worldbottomslope, worldlowslope); - } + // top of texture at top + texturevpeg = 0; - // Find the wall's coordinates - fixed_t midtexheight = texheight * repeats; + texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_mid; - fixed_t rowoffset = FixedDiv(gl_sidedef->rowoffset + gl_sidedef->offsety_mid, gl_sidedef->scaley_mid); - - // Texture is not skewed - if (gl_linedef->flags & ML_NOSKEW) - { - // Peg it to the floor - if (gl_linedef->flags & ML_MIDPEG) - { - polybottom = max(front->floorheight, back->floorheight) + rowoffset; - polytop = polybottom + midtexheight; - } - // Peg it to the ceiling - else - { - polytop = min(front->ceilingheight, back->ceilingheight) + rowoffset; - polybottom = polytop - midtexheight; - } - - // The right side's coordinates are the the same as the left side - polytopslope = polytop; - polybottomslope = polybottom; - } - // Skew the texture, but peg it to the floor - else if (gl_linedef->flags & ML_MIDPEG) - { - polybottom = popenbottom + rowoffset; - polytop = polybottom + midtexheight; - polybottomslope = popenbottomslope + rowoffset; - polytopslope = polybottomslope + midtexheight; - } - // Skew it according to the ceiling's slope - else - { - polytop = popentop + rowoffset; - polybottom = polytop - midtexheight; - polytopslope = popentopslope + rowoffset; - polybottomslope = polytopslope - midtexheight; - } - - // CB - // NOTE: With polyobjects, whenever you need to check the properties of the polyobject sector it belongs to, - // you must use the linedef's backsector to be correct - if (gl_curline->polyseg) - { - lowcut = polybottom; - highcut = polytop; - lowcutslope = polybottomslope; - highcutslope = polytopslope; - } - else - { - // The cut-off values of a linedef can always be constant, since every line has an absoulute front and or back sector - lowcut = popenbottom; - highcut = popentop; - lowcutslope = popenbottomslope; - highcutslope = popentopslope; - } - - h = min(highcut, polytop); - l = max(polybottom, lowcut); - hS = min(highcutslope, polytopslope); - lS = max(polybottomslope, lowcutslope); - - // PEGGING - fixed_t texturevpegslope; - - if (gl_linedef->flags & ML_MIDPEG) - { - texturevpeg = midtexheight - h + polybottom; - texturevpegslope = midtexheight - hS + polybottomslope; - } - else - { - texturevpeg = polytop - h; - texturevpegslope = polytopslope - hS; - } - - // Left side - wallVerts[3].t = texturevpeg * yscale * grTex->scaleY; - wallVerts[0].t = (h - l + texturevpeg) * yscale * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + gl_sidedef->offsetx_mid) * grTex->scaleX; - - // Right side - wallVerts[2].t = texturevpegslope * yscale * grTex->scaleY; - wallVerts[1].t = (hS - lS + texturevpegslope) * yscale * grTex->scaleY; - wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + gl_sidedef->offsetx_mid) * grTex->scaleX; - - // set top/bottom coords - // Take the texture peg into account, rather than changing the offsets past - // where the polygon might not be. - wallVerts[3].y = FIXED_TO_FLOAT(h); - wallVerts[0].y = FIXED_TO_FLOAT(l); - wallVerts[2].y = FIXED_TO_FLOAT(hS); - wallVerts[1].y = FIXED_TO_FLOAT(lS); - - // TODO: Actually use the surface's flags so that I don't have to do this - FUINT blendmode = Surf.PolyFlags; - - // Render midtextures on two-sided lines with a z-buffer offset. - // This will cause the midtexture appear on top, if a FOF overlaps with it. - blendmode |= PF_Decal; - - if (gl_frontsector->numlights) - { - if (!(blendmode & PF_Masked)) - HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FOF_TRANSLUCENT, NULL, blendmode); - else - HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FOF_CUTLEVEL, NULL, blendmode); - } - else if (!(blendmode & PF_Masked)) - HWR_AddTransparentWall(wallVerts, &Surf, gl_midtexture, blendmode, false, lightnum, colormap); - else - HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap); - } - - // Sky culling - // No longer so much a mess as before! - if (!gl_curline->polyseg) // Don't do it for polyobjects - { - if (gl_frontsector->ceilingpic == skyflatnum - && gl_backsector->ceilingpic != skyflatnum) // don't cull if back sector is also sky - { - wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(INT32_MAX); // draw to top of map space - wallVerts[0].y = FIXED_TO_FLOAT(worldtop); - wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope); - HWR_DrawSkyWall(wallVerts, &Surf); - } - - if (gl_frontsector->floorpic == skyflatnum - && gl_backsector->floorpic != skyflatnum) // same thing here - { - wallVerts[3].y = FIXED_TO_FLOAT(worldbottom); - wallVerts[2].y = FIXED_TO_FLOAT(worldbottomslope); - wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(INT32_MIN); // draw to bottom of map space - HWR_DrawSkyWall(wallVerts, &Surf); - } - } - } - else - { - // Single sided line... Deal only with the middletexture (if one exists) - if (gl_midtexture && gl_linedef->special != SPECIAL_HORIZON_LINE) // (Ignore horizon line for OGL) - { - grTex = HWR_GetTexture(gl_midtexture); - xscale = FixedToFloat(gl_sidedef->scalex_mid); - yscale = FixedToFloat(gl_sidedef->scaley_mid); - - fixed_t texturevpeg; - - // PEGGING - if ((gl_linedef->flags & (ML_DONTPEGBOTTOM|ML_NOSKEW)) == (ML_DONTPEGBOTTOM|ML_NOSKEW)) - texturevpeg = (gl_frontsector->floorheight + textureheight[gl_sidedef->midtexture] - gl_frontsector->ceilingheight) * yscale; - else if (gl_linedef->flags & ML_DONTPEGBOTTOM) - texturevpeg = (worldbottom + textureheight[gl_sidedef->midtexture] - worldtop) * yscale; - else - // top of texture at top - texturevpeg = 0; - - texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_mid; - - 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 * xscale) + gl_sidedef->offsetx_mid) * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + gl_sidedef->offsetx_mid) * grTex->scaleX; + 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 * xscale) + gl_sidedef->textureoffset + gl_sidedef->offsetx_mid) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + gl_sidedef->textureoffset + gl_sidedef->offsetx_mid) * grTex->scaleX; // Texture correction for slopes if (gl_linedef->flags & ML_NOSKEW) { @@ -1573,8 +1546,9 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // Used for height comparisons and etc across FOFs and slopes fixed_t high1, highslope1, low1, lowslope1; + fixed_t texturehpeg = gl_sidedef->textureoffset + gl_sidedef->offsetx_mid; + INT32 texnum; - line_t * newline = NULL; // Multi-Property FOF lowcut = max(worldbottom, worldlow); highcut = min(worldtop, worldhigh); @@ -1608,16 +1582,14 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope)) continue; - side_t *side = &sides[rover->master->sidenum[0]]; + side_t *side = R_GetFFloorSide(gl_curline->linedef, rover, gl_backsector); boolean do_texture_skew; boolean dont_peg_bottom; if (rover->master->flags & ML_TFERLINE) { - size_t linenum = gl_curline->linedef-gl_backsector->lines[0]; - newline = rover->master->frontsector->lines[0] + linenum; - side = &sides[newline->sidenum[0]]; + line_t *newline = R_GetFFloorLine(gl_curline->linedef, rover, gl_backsector); do_texture_skew = newline->flags & ML_SKEWTD; dont_peg_bottom = newline->flags & ML_DONTPEGBOTTOM; } @@ -1665,7 +1637,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // -- Monster Iestyn 26/06/18 fixed_t texturevpeg = side->rowoffset + side->offsety_mid; - grTex = HWR_GetTexture(texnum); + grTex = HWR_GetTexture(texnum, true); xscale = FixedToFloat(side->scalex_mid); yscale = FixedToFloat(side->scaley_mid); @@ -1695,20 +1667,21 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom } } - wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + side->offsetx_mid) * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + side->offsetx_mid) * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + texturehpeg + side->offsetx_mid) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + texturehpeg + side->offsetx_mid) * grTex->scaleX; } + FBITFIELD blendmode; + if (rover->fofflags & FOF_FOG) { - FBITFIELD blendmode; - blendmode = PF_Fog|PF_NoTexture; - lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); + lightnum = HWR_SideLightLevel(gl_sidedef, rover->master->frontsector->lightlevel); colormap = rover->master->frontsector->extra_colormap; + lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y); - Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap); + Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(HWR_SideLightLevel(gl_sidedef, rover->master->frontsector->lightlevel), rover->master->frontsector->extra_colormap); if (gl_frontsector->numlights) HWR_SplitWall(gl_frontsector, wallVerts, 0, &Surf, rover->fofflags, rover, blendmode); @@ -1717,9 +1690,9 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom } else { - FBITFIELD blendmode = PF_Masked; + blendmode = PF_Masked; - if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) + if ((rover->fofflags & FOF_TRANSLUCENT && !((rover->fofflags & FOF_SPLAT) && rover->alpha >= 255)) || rover->blend) { blendmode = rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent; Surf.PolyColor.s.alpha = max(0, min(rover->alpha, 255)); @@ -1765,13 +1738,21 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope)) continue; - side_t *side = &sides[rover->master->sidenum[0]]; + side_t *side = R_GetFFloorSide(gl_curline->linedef, rover, gl_backsector); + + boolean do_texture_skew; + boolean dont_peg_bottom; if (rover->master->flags & ML_TFERLINE) { - size_t linenum = gl_curline->linedef-gl_backsector->lines[0]; - newline = rover->master->frontsector->lines[0] + linenum; - side = &sides[newline->sidenum[0]]; + line_t *newline = R_GetFFloorLine(gl_curline->linedef, rover, gl_backsector); + do_texture_skew = newline->flags & ML_SKEWTD; + dont_peg_bottom = newline->flags & ML_DONTPEGBOTTOM; + } + else + { + do_texture_skew = rover->master->flags & ML_SKEWTD; + dont_peg_bottom = gl_curline->linedef->flags & ML_DONTPEGBOTTOM; } texnum = R_GetTextureNum(side->midtexture); @@ -1808,27 +1789,54 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom } else { - grTex = HWR_GetTexture(texnum); + // Wow, how was this missing from OpenGL for so long? + // ...Oh well, anyway, Lower Unpegged now changes pegging of FOFs like in software + // -- Monster Iestyn 26/06/18 + fixed_t texturevpeg = side->rowoffset + side->offsety_mid; + + grTex = HWR_GetTexture(texnum, true); xscale = FixedToFloat(side->scalex_mid); yscale = FixedToFloat(side->scaley_mid); - fixed_t diff = (*rover->topheight - h) * yscale; + if (!do_texture_skew) // no skewing + { + if (dont_peg_bottom) + texturevpeg -= (*rover->topheight - *rover->bottomheight) * yscale; - wallVerts[3].t = wallVerts[2].t = (diff + side->rowoffset + side->offsety_mid) * grTex->scaleY; - wallVerts[0].t = wallVerts[1].t = (((h - l) * yscale) + (diff + side->rowoffset + side->offsety_mid)) * grTex->scaleY; + wallVerts[3].t = (((*rover->topheight - h) * yscale) + texturevpeg) * grTex->scaleY; + wallVerts[2].t = (((*rover->topheight - hS) * yscale) + texturevpeg) * grTex->scaleY; + wallVerts[0].t = (((*rover->topheight - l) * yscale) + texturevpeg) * grTex->scaleY; + wallVerts[1].t = (((*rover->topheight - lS) * yscale) + texturevpeg) * grTex->scaleY; + } + else + { + if (!dont_peg_bottom) // skew by top + { + wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; + wallVerts[0].t = (((h - l) * yscale) + texturevpeg) * grTex->scaleY; + wallVerts[1].t = (((hS - lS) * yscale) + texturevpeg) * grTex->scaleY; + } + else // skew by bottom + { + wallVerts[0].t = wallVerts[1].t = texturevpeg * grTex->scaleY; + wallVerts[3].t = wallVerts[0].t - ((h - l) * yscale) * grTex->scaleY; + wallVerts[2].t = wallVerts[1].t - ((hS - lS) * yscale) * grTex->scaleY; + } + } - wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + side->offsetx_mid) * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + side->offsetx_mid) * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + texturehpeg + side->offsetx_mid) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + texturehpeg + side->offsetx_mid) * grTex->scaleX; } + FBITFIELD blendmode; + if (rover->fofflags & FOF_FOG) { - FBITFIELD blendmode; - blendmode = PF_Fog|PF_NoTexture; - lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); + lightnum = HWR_SideLightLevel(gl_sidedef, rover->master->frontsector->lightlevel); colormap = rover->master->frontsector->extra_colormap; + lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y); Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap); @@ -1839,9 +1847,9 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom } else { - FBITFIELD blendmode = PF_Masked; + blendmode = PF_Masked; - if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) + if ((rover->fofflags & FOF_TRANSLUCENT && !((rover->fofflags & FOF_SPLAT) && rover->alpha >= 255)) || rover->blend) { blendmode = rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent; Surf.PolyColor.s.alpha = max(0, min(rover->alpha, 255)); @@ -1868,8 +1876,8 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // // e6y: Check whether the player can look beyond this line // -#ifdef NEWCLIP -boolean checkforemptylines = true; +static boolean checkforemptylines = true; + // Don't modify anything here, just check // Kalaron: Modified for sloped linedefs static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacksector) @@ -1961,295 +1969,6 @@ static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacks return false; } -#else -//Hurdler: just like in r_bsp.c -#if 1 -#define MAXSEGS MAXVIDWIDTH/2+1 -#else -//Alam_GBC: Or not (may cause overflow) -#define MAXSEGS 128 -#endif - -// hw_newend is one past the last valid seg -static cliprange_t * hw_newend; -static cliprange_t gl_solidsegs[MAXSEGS]; - -// needs fix: walls are incorrectly clipped one column less -static consvar_t cv_glclipwalls = CVAR_INIT ("gr_clipwalls", "Off", 0, CV_OnOff, NULL); - -static void printsolidsegs(void) -{ - cliprange_t * start; - if (!hw_newend) - return; - for (start = gl_solidsegs;start != hw_newend;start++) - { - CONS_Debug(DBG_RENDER, "%d-%d|",start->first,start->last); - } - CONS_Debug(DBG_RENDER, "\n\n"); -} - -// -// -// -static void HWR_ClipSolidWallSegment(INT32 first, INT32 last) -{ - cliprange_t *next, *start; - float lowfrac, highfrac; - boolean poorhack = false; - - // Find the first range that touches the range - // (adjacent pixels are touching). - start = gl_solidsegs; - while (start->last < first-1) - start++; - - if (first < start->first) - { - if (last < start->first-1) - { - // Post is entirely visible (above start), - // so insert a new clippost. - HWR_StoreWallRange(first, last); - - next = hw_newend; - hw_newend++; - - while (next != start) - { - *next = *(next-1); - next--; - } - - next->first = first; - next->last = last; - printsolidsegs(); - return; - } - - // There is a fragment above *start. - if (!cv_glclipwalls.value) - { - if (!poorhack) HWR_StoreWallRange(first, last); - poorhack = true; - } - else - { - highfrac = HWR_ClipViewSegment(start->first+1, (polyvertex_t *)gl_curline->pv1, (polyvertex_t *)gl_curline->pv2); - HWR_StoreWallRange(0, highfrac); - } - // Now adjust the clip size. - start->first = first; - } - - // Bottom contained in start? - if (last <= start->last) - { - printsolidsegs(); - return; - } - next = start; - while (last >= (next+1)->first-1) - { - // There is a fragment between two posts. - if (!cv_glclipwalls.value) - { - if (!poorhack) HWR_StoreWallRange(first,last); - poorhack = true; - } - else - { - lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gl_curline->pv1, (polyvertex_t *)gl_curline->pv2); - highfrac = HWR_ClipViewSegment((next+1)->first+1, (polyvertex_t *)gl_curline->pv1, (polyvertex_t *)gl_curline->pv2); - HWR_StoreWallRange(lowfrac, highfrac); - } - next++; - - if (last <= next->last) - { - // Bottom is contained in next. - // Adjust the clip size. - start->last = next->last; - goto crunch; - } - } - - if (first == next->first+1) // 1 line texture - { - if (!cv_glclipwalls.value) - { - if (!poorhack) HWR_StoreWallRange(first,last); - poorhack = true; - } - else - HWR_StoreWallRange(0, 1); - } - else - { - // There is a fragment after *next. - if (!cv_glclipwalls.value) - { - if (!poorhack) HWR_StoreWallRange(first,last); - poorhack = true; - } - else - { - lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gl_curline->pv1, (polyvertex_t *)gl_curline->pv2); - HWR_StoreWallRange(lowfrac, 1); - } - } - - // Adjust the clip size. - start->last = last; - - // Remove start+1 to next from the clip list, - // because start now covers their area. -crunch: - if (next == start) - { - printsolidsegs(); - // Post just extended past the bottom of one post. - return; - } - - - while (next++ != hw_newend) - { - // Remove a post. - *++start = *next; - } - - hw_newend = start; - printsolidsegs(); -} - -// -// handle LineDefs with upper and lower texture (windows) -// -static void HWR_ClipPassWallSegment(INT32 first, INT32 last) -{ - cliprange_t *start; - float lowfrac, highfrac; - //to allow noclipwalls but still solidseg reject of non-visible walls - boolean poorhack = false; - - // Find the first range that touches the range - // (adjacent pixels are touching). - start = gl_solidsegs; - while (start->last < first - 1) - start++; - - if (first < start->first) - { - if (last < start->first-1) - { - // Post is entirely visible (above start). - HWR_StoreWallRange(0, 1); - return; - } - - // There is a fragment above *start. - if (!cv_glclipwalls.value) - { //20/08/99: Changed by Hurdler (taken from faB's code) - if (!poorhack) HWR_StoreWallRange(0, 1); - poorhack = true; - } - else - { - highfrac = HWR_ClipViewSegment(min(start->first + 1, - start->last), (polyvertex_t *)gl_curline->pv1, - (polyvertex_t *)gl_curline->pv2); - HWR_StoreWallRange(0, highfrac); - } - } - - // Bottom contained in start? - if (last <= start->last) - return; - - while (last >= (start+1)->first-1) - { - // There is a fragment between two posts. - if (!cv_glclipwalls.value) - { - if (!poorhack) HWR_StoreWallRange(0, 1); - poorhack = true; - } - else - { - lowfrac = HWR_ClipViewSegment(max(start->last-1,start->first), (polyvertex_t *)gl_curline->pv1, (polyvertex_t *)gl_curline->pv2); - highfrac = HWR_ClipViewSegment(min((start+1)->first+1,(start+1)->last), (polyvertex_t *)gl_curline->pv1, (polyvertex_t *)gl_curline->pv2); - HWR_StoreWallRange(lowfrac, highfrac); - } - start++; - - if (last <= start->last) - return; - } - - if (first == start->first+1) // 1 line texture - { - if (!cv_glclipwalls.value) - { - if (!poorhack) HWR_StoreWallRange(0, 1); - poorhack = true; - } - else - HWR_StoreWallRange(0, 1); - } - else - { - // There is a fragment after *next. - if (!cv_glclipwalls.value) - { - if (!poorhack) HWR_StoreWallRange(0,1); - poorhack = true; - } - else - { - lowfrac = HWR_ClipViewSegment(max(start->last - 1, - start->first), (polyvertex_t *)gl_curline->pv1, - (polyvertex_t *)gl_curline->pv2); - HWR_StoreWallRange(lowfrac, 1); - } - } -} - -// -------------------------------------------------------------------------- -// HWR_ClipToSolidSegs check if it is hide by wall (solidsegs) -// -------------------------------------------------------------------------- -static boolean HWR_ClipToSolidSegs(INT32 first, INT32 last) -{ - cliprange_t * start; - - // Find the first range that touches the range - // (adjacent pixels are touching). - start = gl_solidsegs; - while (start->last < first-1) - start++; - - if (first < start->first) - return true; - - // Bottom contained in start? - if (last <= start->last) - return false; - - return true; -} - -// -// HWR_ClearClipSegs -// -static void HWR_ClearClipSegs(void) -{ - gl_solidsegs[0].first = -0x7fffffff; - gl_solidsegs[0].last = -1; - gl_solidsegs[1].first = vid.width; //viewwidth; - gl_solidsegs[1].last = 0x7fffffff; - hw_newend = gl_solidsegs+2; -} -#endif // NEWCLIP // -----------------+ // HWR_AddLine : Clips the given segment and adds any visible pieces to the line list. @@ -2259,11 +1978,6 @@ static void HWR_ClearClipSegs(void) static void HWR_AddLine(seg_t * line) { angle_t angle1, angle2; -#ifndef NEWCLIP - INT32 x1, x2; - angle_t span, tspan; - boolean bothceilingssky = false, bothfloorssky = false; -#endif // SoM: Backsector needs to be run through R_FakeFlat static sector_t tempsec; @@ -2299,8 +2013,7 @@ static void HWR_AddLine(seg_t * line) angle1 = R_PointToAngle64(v1x, v1y); angle2 = R_PointToAngle64(v2x, v2y); -#ifdef NEWCLIP - // PrBoom: Back side, i.e. backface culling - read: endAngle >= startAngle! + // PrBoom: Back side, i.e. backface culling - read: endAngle >= startAngle! if (angle2 - angle1 < ANGLE_180) return; @@ -2312,91 +2025,10 @@ static void HWR_AddLine(seg_t * line) } checkforemptylines = true; -#else - // Clip to view edges. - span = angle1 - angle2; - - // backface culling : span is < ANGLE_180 if ang1 > ang2 : the seg is facing - if (span >= ANGLE_180) - return; - - // Global angle needed by segcalc. - //rw_angle1 = angle1; - angle1 -= dup_viewangle; - angle2 -= dup_viewangle; - - tspan = angle1 + gl_clipangle; - if (tspan > 2*gl_clipangle) - { - tspan -= 2*gl_clipangle; - - // Totally off the left edge? - if (tspan >= span) - return; - - angle1 = gl_clipangle; - } - tspan = gl_clipangle - angle2; - if (tspan > 2*gl_clipangle) - { - tspan -= 2*gl_clipangle; - - // Totally off the left edge? - if (tspan >= span) - return; - - angle2 = (angle_t)-(signed)gl_clipangle; - } - -#if 0 - { - float fx1,fx2,fy1,fy2; - //BP: test with a better projection than viewangletox[R_PointToAngle(angle)] - // do not enable this at release 4 mul and 2 div - fx1 = ((polyvertex_t *)(line->pv1))->x-gl_viewx; - fy1 = ((polyvertex_t *)(line->pv1))->y-gl_viewy; - fy2 = (fx1 * gl_viewcos + fy1 * gl_viewsin); - if (fy2 < 0) - // the point is back - fx1 = 0; - else - fx1 = gl_windowcenterx + (fx1 * gl_viewsin - fy1 * gl_viewcos) * gl_centerx / fy2; - - fx2 = ((polyvertex_t *)(line->pv2))->x-gl_viewx; - fy2 = ((polyvertex_t *)(line->pv2))->y-gl_viewy; - fy1 = (fx2 * gl_viewcos + fy2 * gl_viewsin); - if (fy1 < 0) - // the point is back - fx2 = vid.width; - else - fx2 = gl_windowcenterx + (fx2 * gl_viewsin - fy2 * gl_viewcos) * gl_centerx / fy1; - - x1 = fx1+0.5f; - x2 = fx2+0.5f; - } -#else - // The seg is in the view range, - // but not necessarily visible. - angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT; - angle2 = (angle2+ANGLE_90)>>ANGLETOFINESHIFT; - - x1 = gl_viewangletox[angle1]; - x2 = gl_viewangletox[angle2]; -#endif - // Does not cross a pixel? -// if (x1 == x2) -/* { - // BP: HERE IS THE MAIN PROBLEM ! - //CONS_Debug(DBG_RENDER, "tineline\n"); - return; - } -*/ -#endif gl_backsector = line->backsector; bothceilingssky = bothfloorssky = false; -#ifdef NEWCLIP if (!line->backsector) { gld_clipper_SafeAddClipRange(angle2, angle1); @@ -2439,115 +2071,6 @@ static void HWR_AddLine(seg_t * line) } HWR_ProcessSeg(); // Doesn't need arguments because they're defined globally :D - return; -#else - // Single sided line? - if (!gl_backsector) - goto clipsolid; - - gl_backsector = R_FakeFlat(gl_backsector, &tempsec, NULL, NULL, true); - - if (gl_backsector->ceilingpic == skyflatnum && gl_frontsector->ceilingpic == skyflatnum) - bothceilingssky = true; - if (gl_backsector->floorpic == skyflatnum && gl_frontsector->floorpic == skyflatnum) - bothfloorssky = true; - - if (bothceilingssky && bothfloorssky) // everything's sky? let's save us a bit of time then - { - if (!line->polyseg && - !line->sidedef->midtexture - && ((!gl_frontsector->ffloors && !gl_backsector->ffloors) - || Tag_Compare(&gl_frontsector->tags, &gl_backsector->tags))) - return; // line is empty, don't even bother - - goto clippass; // treat like wide open window instead - } - - if (gl_frontsector->f_slope || gl_frontsector->c_slope || gl_backsector->f_slope || gl_backsector->c_slope) - { - fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends - fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends - -#define SLOPEPARAMS(slope, end1, end2, normalheight) \ - end1 = P_GetZAt(slope, v1x, v1y, normalheight); \ - end2 = P_GetZAt(slope, v2x, v2y, normalheight); - - SLOPEPARAMS(gl_frontsector->f_slope, frontf1, frontf2, gl_frontsector-> floorheight) - SLOPEPARAMS(gl_frontsector->c_slope, frontc1, frontc2, gl_frontsector->ceilingheight) - SLOPEPARAMS( gl_backsector->f_slope, backf1, backf2, gl_backsector-> floorheight) - SLOPEPARAMS( gl_backsector->c_slope, backc1, backc2, gl_backsector->ceilingheight) -#undef SLOPEPARAMS - // if both ceilings are skies, consider it always "open" - // same for floors - if (!bothceilingssky && !bothfloorssky) - { - // Closed door. - if ((backc1 <= frontf1 && backc2 <= frontf2) - || (backf1 >= frontc1 && backf2 >= frontc2)) - { - goto clipsolid; - } - - // Check for automap fix. - if (backc1 <= backf1 && backc2 <= backf2 - && ((backc1 >= frontc1 && backc2 >= frontc2) || gl_curline->sidedef->toptexture) - && ((backf1 <= frontf1 && backf2 >= frontf2) || gl_curline->sidedef->bottomtexture)) - goto clipsolid; - } - - // Window. - if (!bothceilingssky) // ceilings are always the "same" when sky - if (backc1 != frontc1 || backc2 != frontc2) - goto clippass; - if (!bothfloorssky) // floors are always the "same" when sky - if (backf1 != frontf1 || backf2 != frontf2) - goto clippass; - } - else - { - // if both ceilings are skies, consider it always "open" - // same for floors - if (!bothceilingssky && !bothfloorssky) - { - // Closed door. - if (gl_backsector->ceilingheight <= gl_frontsector->floorheight || - gl_backsector->floorheight >= gl_frontsector->ceilingheight) - goto clipsolid; - - // Check for automap fix. - if (gl_backsector->ceilingheight <= gl_backsector->floorheight - && ((gl_backsector->ceilingheight >= gl_frontsector->ceilingheight) || gl_curline->sidedef->toptexture) - && ((gl_backsector->floorheight <= gl_backsector->floorheight) || gl_curline->sidedef->bottomtexture)) - goto clipsolid; - } - - // Window. - if (!bothceilingssky) // ceilings are always the "same" when sky - if (gl_backsector->ceilingheight != gl_frontsector->ceilingheight) - goto clippass; - if (!bothfloorssky) // floors are always the "same" when sky - if (gl_backsector->floorheight != gl_frontsector->floorheight) - goto clippass; - } - - // Reject empty lines used for triggers and special events. - // Identical floor and ceiling on both sides, - // identical light levels on both sides, - // and no middle texture. - if (R_IsEmptyLine(gl_curline, gl_frontsector, gl_backsector)) - return; - -clippass: - if (x1 == x2) - { x2++;x1 -= 2; } - HWR_ClipPassWallSegment(x1, x2-1); - return; - -clipsolid: - if (x1 == x2) - goto clippass; - HWR_ClipSolidWallSegment(x1, x2-1); -#endif } // HWR_CheckBBox @@ -2562,23 +2085,19 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord) INT32 boxpos; fixed_t px1, py1, px2, py2; angle_t angle1, angle2; -#ifndef NEWCLIP - INT32 sx1, sx2; - angle_t span, tspan; -#endif // Find the corners of the box // that define the edges from current viewpoint. - if (dup_viewx <= bspcoord[BOXLEFT]) + if (viewx <= bspcoord[BOXLEFT]) boxpos = 0; - else if (dup_viewx < bspcoord[BOXRIGHT]) + else if (viewx < bspcoord[BOXRIGHT]) boxpos = 1; else boxpos = 2; - if (dup_viewy >= bspcoord[BOXTOP]) + if (viewy >= bspcoord[BOXTOP]) boxpos |= 0; - else if (dup_viewy > bspcoord[BOXBOTTOM]) + else if (viewy > bspcoord[BOXBOTTOM]) boxpos |= 1<<2; else boxpos |= 2<<2; @@ -2591,59 +2110,9 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord) px2 = bspcoord[checkcoord[boxpos][2]]; py2 = bspcoord[checkcoord[boxpos][3]]; -#ifdef NEWCLIP angle1 = R_PointToAngle64(px1, py1); angle2 = R_PointToAngle64(px2, py2); return gld_clipper_SafeCheckRange(angle2, angle1); -#else - // check clip list for an open space - angle1 = R_PointToAngle2(dup_viewx>>1, dup_viewy>>1, px1>>1, py1>>1) - dup_viewangle; - angle2 = R_PointToAngle2(dup_viewx>>1, dup_viewy>>1, px2>>1, py2>>1) - dup_viewangle; - - span = angle1 - angle2; - - // Sitting on a line? - if (span >= ANGLE_180) - return true; - - tspan = angle1 + gl_clipangle; - - if (tspan > 2*gl_clipangle) - { - tspan -= 2*gl_clipangle; - - // Totally off the left edge? - if (tspan >= span) - return false; - - angle1 = gl_clipangle; - } - tspan = gl_clipangle - angle2; - if (tspan > 2*gl_clipangle) - { - tspan -= 2*gl_clipangle; - - // Totally off the left edge? - if (tspan >= span) - return false; - - angle2 = (angle_t)-(signed)gl_clipangle; - } - - // Find the first clippost - // that touches the source post - // (adjacent pixels are touching). - angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT; - angle2 = (angle2+ANGLE_90)>>ANGLETOFINESHIFT; - sx1 = gl_viewangletox[angle1]; - sx2 = gl_viewangletox[angle2]; - - // Does not cross a pixel. - if (sx1 == sx2) - return false; - - return HWR_ClipToSolidSegs(sx1, sx2 - 1); -#endif } // @@ -2656,36 +2125,14 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord) static inline void HWR_AddPolyObjectSegs(void) { size_t i, j; - seg_t *gl_fakeline = Z_Calloc(sizeof(seg_t), PU_STATIC, NULL); - polyvertex_t *pv1 = Z_Calloc(sizeof(polyvertex_t), PU_STATIC, NULL); - polyvertex_t *pv2 = Z_Calloc(sizeof(polyvertex_t), PU_STATIC, NULL); // Sort through all the polyobjects for (i = 0; i < numpolys; ++i) { // Render the polyobject's lines for (j = 0; j < po_ptrs[i]->segCount; ++j) - { - // Copy the info of a polyobject's seg, then convert it to OpenGL floating point - M_Memcpy(gl_fakeline, po_ptrs[i]->segs[j], sizeof(seg_t)); - - // Now convert the line to float and add it to be rendered - pv1->x = FIXED_TO_FLOAT(gl_fakeline->v1->x); - pv1->y = FIXED_TO_FLOAT(gl_fakeline->v1->y); - pv2->x = FIXED_TO_FLOAT(gl_fakeline->v2->x); - pv2->y = FIXED_TO_FLOAT(gl_fakeline->v2->y); - - gl_fakeline->pv1 = pv1; - gl_fakeline->pv2 = pv2; - - HWR_AddLine(gl_fakeline); - } + HWR_AddLine(po_ptrs[i]->segs[j]); } - - // Free temporary data no longer needed - Z_Free(pv2); - Z_Free(pv1); - Z_Free(gl_fakeline); } static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, @@ -2694,7 +2141,7 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, { FSurfaceInfo Surf; FOutVector *v3d; - INT32 shader = SHADER_DEFAULT; + INT32 shader = SHADER_NONE; size_t nrPlaneVerts = polysector->numVertices; INT32 i; @@ -2710,13 +2157,8 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; - if (nrPlaneVerts < 3) // Not even a triangle? + if (!r_renderfloors || nrPlaneVerts < 3) // Not even a triangle? return; - else if (nrPlaneVerts > (size_t)UINT16_MAX) // FIXME: exceeds plVerts size - { - CONS_Debug(DBG_RENDER, "polygon size of %s exceeds max value of %d vertices\n", sizeu1(nrPlaneVerts), UINT16_MAX); - return; - } // Allocate plane-vertex buffer if we need to if (!planeVerts || nrPlaneVerts > numAllocedPlaneVerts) @@ -2859,7 +2301,7 @@ static void HWR_AddPolyObjectPlanes(void) } else { - HWR_GetLevelFlat(&levelflats[polyobjsector->floorpic]); + HWR_GetLevelFlat(&levelflats[polyobjsector->floorpic], false); HWR_RenderPolyObjectPlane(po_ptrs[i], false, polyobjsector->floorheight, PF_Occlude, (light == -1 ? gl_frontsector->lightlevel : *gl_frontsector->lightlist[light].lightlevel), &levelflats[polyobjsector->floorpic], polyobjsector, 255, (light == -1 ? gl_frontsector->extra_colormap : *gl_frontsector->lightlist[light].extra_colormap)); @@ -2882,7 +2324,7 @@ static void HWR_AddPolyObjectPlanes(void) } else { - HWR_GetLevelFlat(&levelflats[polyobjsector->ceilingpic]); + HWR_GetLevelFlat(&levelflats[polyobjsector->ceilingpic], false); HWR_RenderPolyObjectPlane(po_ptrs[i], true, polyobjsector->ceilingheight, PF_Occlude, (light == -1 ? gl_frontsector->lightlevel : *gl_frontsector->lightlist[light].lightlevel), &levelflats[polyobjsector->ceilingpic], polyobjsector, 255, (light == -1 ? gl_frontsector->extra_colormap : *gl_frontsector->lightlist[light].extra_colormap)); @@ -3005,15 +2447,14 @@ static void HWR_Subsector(size_t num) sub->sector->extra_colormap = gl_frontsector->extra_colormap; // render floor ? -#ifdef DOPLANES // yeah, easy backface cull! :) - if (cullFloorHeight < dup_viewz) + if (cullFloorHeight < viewz) { if (gl_frontsector->floorpic != skyflatnum) { if (sub->validcount != validcount) { - HWR_GetLevelFlat(&levelflats[gl_frontsector->floorpic]); + HWR_GetLevelFlat(&levelflats[gl_frontsector->floorpic], false); HWR_RenderPlane(sub, &extrasubsectors[num], false, // Hack to make things continue to work around slopes. locFloorHeight == cullFloorHeight ? locFloorHeight : gl_frontsector->floorheight, @@ -3021,21 +2462,15 @@ static void HWR_Subsector(size_t num) PF_Occlude, floorlightlevel, &levelflats[gl_frontsector->floorpic], NULL, 255, floorcolormap); } } - else - { -#ifdef POLYSKY - HWR_RenderSkyPlane(&extrasubsectors[num], locFloorHeight); -#endif - } } - if (cullCeilingHeight > dup_viewz) + if (cullCeilingHeight > viewz) { if (gl_frontsector->ceilingpic != skyflatnum) { if (sub->validcount != validcount) { - HWR_GetLevelFlat(&levelflats[gl_frontsector->ceilingpic]); + HWR_GetLevelFlat(&levelflats[gl_frontsector->ceilingpic], false); HWR_RenderPlane(sub, &extrasubsectors[num], true, // Hack to make things continue to work around slopes. locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gl_frontsector->ceilingheight, @@ -3043,21 +2478,12 @@ static void HWR_Subsector(size_t num) PF_Occlude, ceilinglightlevel, &levelflats[gl_frontsector->ceilingpic], NULL, 255, ceilingcolormap); } } - else - { -#ifdef POLYSKY - HWR_RenderSkyPlane(&extrasubsectors[num], locCeilingHeight); -#endif - } } -#ifndef POLYSKY // Moved here because before, when above the ceiling and the floor does not have the sky flat, it doesn't draw the sky if (gl_frontsector->ceilingpic == skyflatnum || gl_frontsector->floorpic == skyflatnum) drawsky = true; -#endif -#ifdef R_FAKEFLOORS if (gl_frontsector->ffloors) { /// \todo fix light, xoffs, yoffs, extracolormap ? @@ -3070,14 +2496,14 @@ static void HWR_Subsector(size_t num) continue; if (sub->validcount == validcount) continue; - + // rendering heights for bottom and top planes bottomCullHeight = P_GetFFloorBottomZAt(rover, viewx, viewy); topCullHeight = P_GetFFloorTopZAt(rover, viewx, viewy); - + if (gl_frontsector->cullheight) { - if (HWR_DoCulling(gl_frontsector->cullheight, viewsector->cullheight, gl_viewz, FIXED_TO_FLOAT(bottomCullHeight), FIXED_TO_FLOAT(topCullHeight))) + if (HWR_DoCulling(gl_frontsector->cullheight, viewsector->cullheight, gl_viewz, FIXED_TO_FLOAT(*rover->bottomheight), FIXED_TO_FLOAT(*rover->topheight))) continue; } @@ -3086,43 +2512,44 @@ static void HWR_Subsector(size_t num) if (centerHeight <= locCeilingHeight && centerHeight >= locFloorHeight && - ((dup_viewz < bottomCullHeight && (rover->fofflags & FOF_BOTHPLANES || !(rover->fofflags & FOF_INVERTPLANES))) || - (dup_viewz > bottomCullHeight && (rover->fofflags & FOF_BOTHPLANES || rover->fofflags & FOF_INVERTPLANES)))) + ((viewz < bottomCullHeight && (rover->fofflags & FOF_BOTHPLANES || !(rover->fofflags & FOF_INVERTPLANES))) || + (viewz > bottomCullHeight && (rover->fofflags & FOF_BOTHPLANES || rover->fofflags & FOF_INVERTPLANES)))) { if (rover->fofflags & FOF_FOG) { UINT8 alpha; - light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < bottomCullHeight ? true : false); - alpha = HWR_FogBlockAlpha(*gl_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap); + light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < bottomCullHeight ? true : false); + alpha = HWR_FogBlockAlpha(HWR_FloorLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), rover->master->frontsector->extra_colormap); HWR_AddTransparentFloor(0, &extrasubsectors[num], false, *rover->bottomheight, - *gl_frontsector->lightlist[light].lightlevel, + HWR_FloorLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), alpha, rover->master->frontsector, PF_Fog|PF_NoTexture, - true, rover->master->frontsector->extra_colormap); + true, false, rover->master->frontsector->extra_colormap); } - else if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) // SoM: Flags are more efficient + else if ((rover->fofflags & FOF_TRANSLUCENT && !((rover->fofflags & FOF_SPLAT) && rover->alpha >= 255)) || rover->blend) // SoM: Flags are more efficient { - light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < bottomCullHeight ? true : false); + light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < bottomCullHeight ? true : false); HWR_AddTransparentFloor(&levelflats[*rover->bottompic], &extrasubsectors[num], false, *rover->bottomheight, - *gl_frontsector->lightlist[light].lightlevel, + HWR_FloorLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), 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); + false, rover->fofflags & FOF_SPLAT, *gl_frontsector->lightlist[light].extra_colormap); } else { - HWR_GetLevelFlat(&levelflats[*rover->bottompic]); - light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < bottomCullHeight ? true : false); - HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &levelflats[*rover->bottompic], - rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap); + HWR_GetLevelFlat(&levelflats[*rover->bottompic], rover->fofflags & FOF_SPLAT); + light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < bottomCullHeight ? true : false); + HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, + HWR_FloorLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), + &levelflats[*rover->bottompic], rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap); } } @@ -3131,49 +2558,48 @@ static void HWR_Subsector(size_t num) if (centerHeight >= locFloorHeight && centerHeight <= locCeilingHeight && - ((dup_viewz > topCullHeight && (rover->fofflags & FOF_BOTHPLANES || !(rover->fofflags & FOF_INVERTPLANES))) || - (dup_viewz < topCullHeight && (rover->fofflags & FOF_BOTHPLANES || rover->fofflags & FOF_INVERTPLANES)))) + ((viewz > topCullHeight && (rover->fofflags & FOF_BOTHPLANES || !(rover->fofflags & FOF_INVERTPLANES))) || + (viewz < topCullHeight && (rover->fofflags & FOF_BOTHPLANES || rover->fofflags & FOF_INVERTPLANES)))) { if (rover->fofflags & FOF_FOG) { UINT8 alpha; - light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < topCullHeight ? true : false); - alpha = HWR_FogBlockAlpha(*gl_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap); + light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < topCullHeight ? true : false); + alpha = HWR_FogBlockAlpha(HWR_CeilingLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), rover->master->frontsector->extra_colormap); HWR_AddTransparentFloor(0, &extrasubsectors[num], true, *rover->topheight, - *gl_frontsector->lightlist[light].lightlevel, + HWR_CeilingLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), alpha, rover->master->frontsector, PF_Fog|PF_NoTexture, - true, rover->master->frontsector->extra_colormap); + true, false, rover->master->frontsector->extra_colormap); } - else if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) + else if ((rover->fofflags & FOF_TRANSLUCENT && !((rover->fofflags & FOF_SPLAT) && rover->alpha >= 255)) || rover->blend) { - light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < topCullHeight ? true : false); + light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < topCullHeight ? true : false); HWR_AddTransparentFloor(&levelflats[*rover->toppic], &extrasubsectors[num], true, *rover->topheight, - *gl_frontsector->lightlist[light].lightlevel, + HWR_CeilingLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), 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); + false, rover->fofflags & FOF_SPLAT, *gl_frontsector->lightlist[light].extra_colormap); } else { - HWR_GetLevelFlat(&levelflats[*rover->toppic]); - light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < topCullHeight ? true : false); - HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &levelflats[*rover->toppic], - rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap); + HWR_GetLevelFlat(&levelflats[*rover->toppic], rover->fofflags & FOF_SPLAT); + light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < topCullHeight ? true : false); + HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, + HWR_CeilingLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), + &levelflats[*rover->toppic], rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap); } } } } -#endif -#endif //doplanes // Draw all the polyobjects in this subsector if (sub->polyList) @@ -3205,10 +2631,10 @@ static void HWR_Subsector(size_t num) } } -// Hurder ici se passe les choses INT32�essantes! -// on vient de tracer le sol et le plafond -// on trace �pr�ent d'abord les sprites et ensuite les murs -// hurdler: faux: on ajoute seulement les sprites, le murs sont trac� d'abord + // Hurdler: here interesting things are happening! + // we have just drawn the floor and ceiling + // we now draw the sprites first and then the walls + // hurdler: false: we only add the sprites, the walls are drawn first if (line) { // draw sprites first, coz they are clipped to the solidsegs of @@ -3240,59 +2666,11 @@ static void HWR_Subsector(size_t num) // traversing subtree recursively. // Just call with BSP root. -#ifdef coolhack -//t;b;l;r -static fixed_t hackbbox[4]; -//BOXTOP, -//BOXBOTTOM, -//BOXLEFT, -//BOXRIGHT -static boolean HWR_CheckHackBBox(fixed_t *bb) -{ - if (bb[BOXTOP] < hackbbox[BOXBOTTOM]) //y up - return false; - if (bb[BOXBOTTOM] > hackbbox[BOXTOP]) - return false; - if (bb[BOXLEFT] > hackbbox[BOXRIGHT]) - return false; - if (bb[BOXRIGHT] < hackbbox[BOXLEFT]) - return false; - return true; -} -#endif - // BP: big hack for a test in lighning ref : 1249753487AB fixed_t *hwbbox; static void HWR_RenderBSPNode(INT32 bspnum) { - /*//GZDoom code - if(bspnum == -1) - { - HWR_Subsector(subsectors); - return; - } - while(!((size_t)bspnum&(~NF_SUBSECTOR))) // Keep going until found a subsector - { - node_t *bsp = &nodes[bspnum]; - - // Decide which side the view point is on - INT32 side = R_PointOnSide(dup_viewx, dup_viewy, bsp); - - // Recursively divide front space (toward the viewer) - HWR_RenderBSPNode(bsp->children[side]); - - // Possibly divide back space (away from viewer) - side ^= 1; - - if (!HWR_CheckBBox(bsp->bbox[side])) - return; - - bspnum = bsp->children[side]; - } - - HWR_Subsector(bspnum-1); -*/ node_t *bsp = &nodes[bspnum]; // Decide which side the view point is on @@ -3317,7 +2695,7 @@ static void HWR_RenderBSPNode(INT32 bspnum) } // Decide which side the view point is on. - side = R_PointOnSide(dup_viewx, dup_viewy, bsp); + side = R_PointOnSide(viewx, viewy, bsp); // BP: big hack for a test in lighning ref : 1249753487AB hwbbox = bsp->bbox[side]; @@ -3329,103 +2707,9 @@ static void HWR_RenderBSPNode(INT32 bspnum) if (HWR_CheckBBox(bsp->bbox[side^1])) { // BP: big hack for a test in lighning ref : 1249753487AB - hwbbox = bsp->bbox[side^1]; - HWR_RenderBSPNode(bsp->children[side^1]); - } -} - -/* -// -// Clear 'stack' of subsectors to draw -// -static void HWR_ClearDrawSubsectors(void) -{ - gl_drawsubsector_p = gl_drawsubsectors; -} - -// -// Draw subsectors pushed on the drawsubsectors 'stack', back to front -// -static void HWR_RenderSubsectors(void) -{ - while (gl_drawsubsector_p > gl_drawsubsectors) - { - HWR_RenderBSPNode( - lastsubsec->nextsubsec = bspnum & (~NF_SUBSECTOR); - } -} -*/ - -// ========================================================================== -// FROM R_MAIN.C -// ========================================================================== - -//BP : exactely the same as R_InitTextureMapping -void HWR_InitTextureMapping(void) -{ - angle_t i; - INT32 x; - INT32 t; - fixed_t focallength; - fixed_t grcenterx; - fixed_t grcenterxfrac; - INT32 grviewwidth; - -#define clipanglefov (FIELDOFVIEW>>ANGLETOFINESHIFT) - - grviewwidth = vid.width; - grcenterx = grviewwidth/2; - grcenterxfrac = grcenterx<<FRACBITS; - - // Use tangent table to generate viewangletox: - // viewangletox will give the next greatest x - // after the view angle. - // - // Calc focallength - // so FIELDOFVIEW angles covers SCREENWIDTH. - focallength = FixedDiv(grcenterxfrac, - FINETANGENT(FINEANGLES/4+clipanglefov/2)); - - for (i = 0; i < FINEANGLES/2; i++) - { - if (FINETANGENT(i) > FRACUNIT*2) - t = -1; - else if (FINETANGENT(i) < -FRACUNIT*2) - t = grviewwidth+1; - else - { - t = FixedMul(FINETANGENT(i), focallength); - t = (grcenterxfrac - t+FRACUNIT-1)>>FRACBITS; - - if (t < -1) - t = -1; - else if (t > grviewwidth+1) - t = grviewwidth+1; - } - gl_viewangletox[i] = t; - } - - // Scan viewangletox[] to generate xtoviewangle[]: - // xtoviewangle will give the smallest view angle - // that maps to x. - for (x = 0; x <= grviewwidth; x++) - { - i = 0; - while (gl_viewangletox[i]>x) - i++; - gl_xtoviewangle[x] = (i<<ANGLETOFINESHIFT) - ANGLE_90; - } - - // Take out the fencepost cases from viewangletox. - for (i = 0; i < FINEANGLES/2; i++) - { - if (gl_viewangletox[i] == -1) - gl_viewangletox[i] = 0; - else if (gl_viewangletox[i] == grviewwidth+1) - gl_viewangletox[i] = grviewwidth; + hwbbox = bsp->bbox[side^1]; + HWR_RenderBSPNode(bsp->children[side^1]); } - - gl_clipangle = gl_xtoviewangle[0]; } // ========================================================================== @@ -3527,7 +2811,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) float fscale; float fx; float fy; float offset; extracolormap_t *colormap = NULL; FBITFIELD blendmode = PF_Translucent|PF_Modulated; - INT32 shader = SHADER_DEFAULT; + INT32 shader = SHADER_NONE; UINT8 i; INT32 heightsec, phs; SINT8 flip = P_MobjFlip(thing); @@ -3647,7 +2931,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) } HWR_Lighting(&sSurf, 0, colormap); - sSurf.PolyColor.s.alpha = alpha; + sSurf.PolyColor.s.alpha = FixedMul(thing->alpha, alpha); if (HWR_UseShader()) { @@ -3735,7 +3019,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) boolean lightset = true; FBITFIELD blend = 0; FBITFIELD occlusion; - INT32 shader = SHADER_DEFAULT; + INT32 shader = SHADER_NONE; boolean use_linkdraw_hack = false; UINT8 alpha; @@ -3822,10 +3106,15 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) // co-ordinates memcpy(wallVerts, baseWallVerts, sizeof(baseWallVerts)); + fixed_t newalpha = spr->mobj->alpha; + // if sprite has linkdraw, then dont write to z-buffer (by not using PF_Occlude) // this will result in sprites drawn afterwards to be drawn on top like intended when using linkdraw. if ((spr->mobj->flags2 & MF2_LINKDRAW) && spr->mobj->tracer) + { + newalpha = spr->mobj->tracer->alpha; occlusion = 0; + } else occlusion = PF_Occlude; @@ -3862,6 +3151,8 @@ static void HWR_SplitSprite(gl_vissprite_t *spr) if (!occlusion) use_linkdraw_hack = true; } + Surf.PolyColor.s.alpha = FixedMul(newalpha, Surf.PolyColor.s.alpha); + if (HWR_UseShader()) { shader = SHADER_SPRITE; @@ -4058,7 +3349,7 @@ static void HWR_DrawBoundingBox(gl_vissprite_t *vis) 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); } @@ -4306,15 +3597,19 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) } { - INT32 shader = SHADER_DEFAULT; + INT32 shader = SHADER_NONE; FBITFIELD blend = 0; FBITFIELD occlusion; boolean use_linkdraw_hack = false; + fixed_t newalpha = spr->mobj->alpha; // if sprite has linkdraw, then dont write to z-buffer (by not using PF_Occlude) // this will result in sprites drawn afterwards to be drawn on top like intended when using linkdraw. if ((spr->mobj->flags2 & MF2_LINKDRAW) && spr->mobj->tracer) + { occlusion = 0; + newalpha = spr->mobj->tracer->alpha; + } else occlusion = PF_Occlude; @@ -4351,6 +3646,8 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) if (!occlusion) use_linkdraw_hack = true; } + Surf.PolyColor.s.alpha = FixedMul(newalpha, Surf.PolyColor.s.alpha); + if (spr->renderflags & RF_SHADOWEFFECTS) { INT32 alpha = Surf.PolyColor.s.alpha; @@ -4376,11 +3673,10 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) } } -#ifdef HWPRECIP // Sprite drawer for precipitation static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) { - INT32 shader = SHADER_DEFAULT; + INT32 shader = SHADER_NONE; FBITFIELD blend = 0; FOutVector wallVerts[4]; patch_t *gpatch; @@ -4477,7 +3773,6 @@ static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated, shader, false); } -#endif // -------------------------------------------------------------------------- // Sort vissprites by distance @@ -4604,6 +3899,7 @@ typedef struct sector_t *FOFSector; FBITFIELD blend; boolean fogplane; + boolean chromakeyed; extracolormap_t *planecolormap; INT32 drawcount; } planeinfo_t; @@ -4645,7 +3941,7 @@ static INT32 drawcount = 0; #define MAX_TRANSPARENTFLOOR 512 // This will likely turn into a copy of HWR_Add3DWater and replace it. -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_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, boolean chromakeyed, extracolormap_t *planecolormap) { static size_t allocedplanes = 0; @@ -4661,13 +3957,14 @@ void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boo planeinfo[numplanes].isceiling = isceiling; planeinfo[numplanes].fixedheight = fixedheight; - planeinfo[numplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? 255 : lightlevel; + planeinfo[numplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? lightlevel : 255; // TODO: 2.3: Make transparent FOF planes always use light level planeinfo[numplanes].levelflat = levelflat; planeinfo[numplanes].xsub = xsub; planeinfo[numplanes].alpha = alpha; planeinfo[numplanes].FOFSector = FOFSector; planeinfo[numplanes].blend = blend; planeinfo[numplanes].fogplane = fogplane; + planeinfo[numplanes].chromakeyed = chromakeyed; planeinfo[numplanes].planecolormap = planecolormap; planeinfo[numplanes].drawcount = drawcount++; @@ -4692,7 +3989,7 @@ void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polyse polyplaneinfo[numpolyplanes].isceiling = isceiling; polyplaneinfo[numpolyplanes].fixedheight = fixedheight; - polyplaneinfo[numpolyplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? 255 : lightlevel; + polyplaneinfo[numpolyplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? lightlevel : 255; // TODO: 2.3: Make transparent polyobject planes always use light level polyplaneinfo[numpolyplanes].levelflat = levelflat; polyplaneinfo[numpolyplanes].polysector = polysector; polyplaneinfo[numpolyplanes].alpha = alpha; @@ -4741,7 +4038,7 @@ static int CompareDrawNodePlanes(const void *p1, const void *p2) size_t n2 = *(const size_t*)p2; if (!sortnode[n1].plane) I_Error("CompareDrawNodePlanes: Uh.. This isn't a plane! (n1)"); if (!sortnode[n2].plane) I_Error("CompareDrawNodePlanes: Uh.. This isn't a plane! (n2)"); - return ABS(sortnode[n2].plane->fixedheight - viewz) - ABS(sortnode[n1].plane->fixedheight - viewz); + return abs(sortnode[n2].plane->fixedheight - viewz) - abs(sortnode[n1].plane->fixedheight - viewz); } // @@ -4825,7 +4122,6 @@ static void HWR_CreateDrawNodes(void) // Okay! Let's draw it all! Woo! HWD.pfnSetTransform(&atransform); - HWD.pfnSetShader(SHADER_DEFAULT); for (i = 0; i < p; i++) { @@ -4835,7 +4131,7 @@ static void HWR_CreateDrawNodes(void) gl_frontsector = NULL; if (!(sortnode[sortindex[i]].plane->blend & PF_NoTexture)) - HWR_GetLevelFlat(sortnode[sortindex[i]].plane->levelflat); + HWR_GetLevelFlat(sortnode[sortindex[i]].plane->levelflat, sortnode[sortindex[i]].plane->chromakeyed); HWR_RenderPlane(NULL, sortnode[sortindex[i]].plane->xsub, sortnode[sortindex[i]].plane->isceiling, sortnode[sortindex[i]].plane->fixedheight, sortnode[sortindex[i]].plane->blend, sortnode[sortindex[i]].plane->lightlevel, sortnode[sortindex[i]].plane->levelflat, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->planecolormap); } @@ -4844,15 +4140,17 @@ static void HWR_CreateDrawNodes(void) // We aren't traversing the BSP tree, so make gl_frontsector null to avoid crashes. gl_frontsector = NULL; + polyobj_t *po = sortnode[sortindex[i]].polyplane->polysector; + if (!(sortnode[sortindex[i]].polyplane->blend & PF_NoTexture)) - HWR_GetLevelFlat(sortnode[sortindex[i]].polyplane->levelflat); - HWR_RenderPolyObjectPlane(sortnode[sortindex[i]].polyplane->polysector, sortnode[sortindex[i]].polyplane->isceiling, sortnode[sortindex[i]].polyplane->fixedheight, sortnode[sortindex[i]].polyplane->blend, sortnode[sortindex[i]].polyplane->lightlevel, + HWR_GetLevelFlat(sortnode[sortindex[i]].polyplane->levelflat, po->flags & POF_SPLAT); + HWR_RenderPolyObjectPlane(po, sortnode[sortindex[i]].polyplane->isceiling, sortnode[sortindex[i]].polyplane->fixedheight, sortnode[sortindex[i]].polyplane->blend, sortnode[sortindex[i]].polyplane->lightlevel, sortnode[sortindex[i]].polyplane->levelflat, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap); } else if (sortnode[sortindex[i]].wall) { if (!(sortnode[sortindex[i]].wall->blend & PF_NoTexture)) - HWR_GetTexture(sortnode[sortindex[i]].wall->texnum); + HWR_GetTexture(sortnode[sortindex[i]].wall->texnum, true); HWR_RenderWall(sortnode[sortindex[i]].wall->wallVerts, &sortnode[sortindex[i]].wall->Surf, sortnode[sortindex[i]].wall->blend, sortnode[sortindex[i]].wall->fogwall, sortnode[sortindex[i]].wall->lightlevel, sortnode[sortindex[i]].wall->wallcolormap); } @@ -4884,12 +4182,9 @@ static void HWR_DrawSprites(void) gl_vissprite_t *spr = gl_vsprorder[i]; if (spr->bbox) HWR_DrawBoundingBox(spr); - else -#ifdef HWPRECIP - if (spr->precip) + else if (spr->precip) HWR_DrawPrecipitationSprite(spr); else -#endif { if (spr->mobj && spr->mobj->shadowscale && cv_shadow.value && !skipshadow) { @@ -4960,9 +4255,7 @@ static UINT8 sectorlight; static void HWR_AddSprites(sector_t *sec) { mobj_t *thing; -#ifdef HWPRECIP precipmobj_t *precipthing; -#endif fixed_t limit_dist, hoop_limit_dist; // BSP is traversed by subsector. @@ -4995,7 +4288,6 @@ static void HWR_AddSprites(sector_t *sec) } } -#ifdef HWPRECIP // no, no infinite draw distance for precipitation. this option at zero is supposed to turn it off if ((limit_dist = (fixed_t)cv_drawdist_precip.value << FRACBITS)) { @@ -5005,7 +4297,6 @@ static void HWR_AddSprites(sector_t *sec) HWR_ProjectPrecipitationSprite(precipthing); } } -#endif } // -------------------------------------------------------------------------- @@ -5058,6 +4349,9 @@ static void HWR_ProjectSprite(mobj_t *thing) // uncapped/interpolation interpmobjstate_t interp = {0}; + if (!r_renderthings) + return; + if (!thing) return; @@ -5134,9 +4428,9 @@ static void HWR_ProjectSprite(mobj_t *thing) //Fab : 02-08-98: 'skin' override spritedef currently used for skin if (thing->skin && thing->sprite == SPR_PLAY) { - sprdef = &((skin_t *)thing->skin)->sprites[thing->sprite2]; + sprdef = P_GetSkinSpritedef(thing->skin, thing->sprite2); #ifdef ROTSPRITE - sprinfo = &((skin_t *)thing->skin)->sprinfo[thing->sprite2]; + sprinfo = P_GetSkinSpriteInfo(thing->skin, thing->sprite2); #endif } else @@ -5502,7 +4796,6 @@ static void HWR_ProjectSprite(mobj_t *thing) vis->angle = interp.angle; } -#ifdef HWPRECIP // Precipitation projector for hardware mode static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) { @@ -5631,7 +4924,6 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) thing->precipflags |= PCF_THUNK; } } -#endif static void HWR_ProjectBoundingBox(mobj_t *thing) { @@ -5838,53 +5130,31 @@ static void HWR_DrawSkyBackground(player_t *player) HWD.pfnSetBlend(PF_Translucent|PF_NoDepthTest|PF_Modulated); + HWR_GetTexture(texturetranslation[skytexture], false); + if (cv_glskydome.value) { FTransform dometransform; - const float fpov = FixedToFloat(R_GetPlayerFov(player)); - postimg_t *type; - if (splitscreen && player == &players[secondarydisplayplayer]) - type = &postimgtype2; - else - type = &postimgtype; + memcpy(&dometransform, &atransform, sizeof(FTransform)); - memset(&dometransform, 0x00, sizeof(FTransform)); + dometransform.x = 0.0; + dometransform.y = 0.0; + dometransform.z = 0.0; //04/01/2000: Hurdler: added for T&L // It should replace all other gl_viewxxx when finished HWR_SetTransformAiming(&dometransform, player, false); dometransform.angley = (float)((viewangle-ANGLE_270)>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); - if (*type == postimg_flip) - dometransform.flip = true; - else - dometransform.flip = false; - - dometransform.scalex = 1; - dometransform.scaley = (float)vid.width/vid.height; - dometransform.scalez = 1; - dometransform.fovxangle = fpov; // Tails - dometransform.fovyangle = fpov; // Tails - if (player->viewrollangle != 0) - { - 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; - - HWR_GetTexture(texturetranslation[skytexture]); - if (gl_sky.texture != texturetranslation[skytexture]) { HWR_ClearSkyDome(); HWR_BuildSkyDome(); } - HWD.pfnSetShader(SHADER_SKY); // sky shader + if (HWR_UseShader()) + HWD.pfnSetShader(HWR_GetShaderFromTarget(SHADER_SKY)); HWD.pfnSetTransform(&dometransform); HWD.pfnRenderSkyDome(&gl_sky); } @@ -5896,7 +5166,6 @@ static void HWR_DrawSkyBackground(player_t *player) float aspectratio; float angleturn; - HWR_GetTexture(texturetranslation[skytexture]); aspectratio = (float)vid.width/(float)vid.height; //Hurdler: the sky is the only texture who need 4.0f instead of 1.0 @@ -5921,7 +5190,7 @@ static void HWR_DrawSkyBackground(player_t *player) // software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly // The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture - angle = (dup_viewangle + gl_xtoviewangle[0]); + angle = (viewangle + xtoviewangle[0]); dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f); @@ -5970,8 +5239,6 @@ static void HWR_DrawSkyBackground(player_t *player) HWD.pfnUnSetShader(); HWD.pfnDrawPolygon(NULL, v, 4, 0); } - - HWD.pfnSetShader(SHADER_DEFAULT); } @@ -5987,10 +5254,10 @@ static inline void HWR_ClearView(void) /// \bug faB - enable depth mask, disable color mask - HWD.pfnGClipRect((INT32)gl_viewwindowx, - (INT32)gl_viewwindowy, - (INT32)(gl_viewwindowx + gl_viewwidth), - (INT32)(gl_viewwindowy + gl_viewheight), + HWD.pfnGClipRect((INT32)viewwindowx, + (INT32)viewwindowy, + (INT32)(viewwindowx + viewwidth), + (INT32)(viewwindowy + viewheight), ZCLIP_PLANE); HWD.pfnClearBuffer(false, true, 0); @@ -6005,32 +5272,6 @@ static inline void HWR_ClearView(void) // -----------------+ void HWR_SetViewSize(void) { - // setup view size - gl_viewwidth = (float)vid.width; - gl_viewheight = (float)vid.height; - - if (splitscreen) - gl_viewheight /= 2; - - gl_centerx = gl_viewwidth / 2; - gl_basecentery = gl_viewheight / 2; //note: this is (gl_centerx * gl_viewheight / gl_viewwidth) - - gl_viewwindowx = (vid.width - gl_viewwidth) / 2; - gl_windowcenterx = (float)(vid.width / 2); - if (fabsf(gl_viewwidth - vid.width) < 1.0E-36f) - { - gl_baseviewwindowy = 0; - gl_basewindowcentery = gl_viewheight / 2; // window top left corner at 0,0 - } - else - { - gl_baseviewwindowy = (vid.height-gl_viewheight) / 2; - gl_basewindowcentery = (float)(vid.height / 2); - } - - gl_pspritexscale = gl_viewwidth / BASEVIDWIDTH; - gl_pspriteyscale = ((vid.height*gl_pspritexscale*BASEVIDWIDTH)/BASEVIDHEIGHT)/vid.width; - HWD.pfnFlushScreenTextures(); } @@ -6043,7 +5284,9 @@ static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean if (cv_glshearing.value == 1 || (cv_glshearing.value == 2 && R_IsViewpointThirdPerson(player, skybox))) { fixed_t fixedaiming = AIMINGTODY(aimingangle); - trans->viewaiming = FIXED_TO_FLOAT(fixedaiming); + trans->viewaiming = FIXED_TO_FLOAT(fixedaiming) * ((float)vid.width / vid.height) / ((float)BASEVIDWIDTH / BASEVIDHEIGHT); + if (splitscreen) + trans->viewaiming *= 2.125; // splitscreen adjusts fov with 0.8, so compensate (but only halfway, since splitscreen means only half the screen is used) trans->shearing = true; gl_aimingangle = 0; } @@ -6061,21 +5304,11 @@ static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean // static void HWR_SetShaderState(void) { - hwdshaderoption_t state = cv_glshaders.value; - - if (!cv_glallowshaders.value) - state = (cv_glshaders.value == HWD_SHADEROPTION_ON ? HWD_SHADEROPTION_NOCUSTOM : cv_glshaders.value); - - HWD.pfnSetSpecialState(HWD_SET_SHADERS, (INT32)state); - HWD.pfnSetShader(SHADER_DEFAULT); + HWD.pfnSetSpecialState(HWD_SET_SHADERS, (INT32)HWR_UseShader()); } -// ========================================================================== -// Same as rendering the player view, but from the skybox object -// ========================================================================== -void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) +static void HWR_SetupView(player_t *player, INT32 viewnumber, float fpov, boolean skybox) { - const float fpov = FixedToFloat(R_GetPlayerFov(player)); postimg_t *type; if (splitscreen && player == &players[secondarydisplayplayer]) @@ -6083,6 +5316,7 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) else type = &postimgtype; + if (!HWR_ShouldUsePaletteRendering()) { // do we really need to save player (is it not the same)? player_t *saved_player = stplyr; @@ -6091,55 +5325,41 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) stplyr = saved_player; #ifdef ALAM_LIGHTING HWR_SetLights(viewnumber); +#else + (void)viewnumber; #endif } // note: sets viewangle, viewx, viewy, viewz - R_SkyboxFrame(player); - - // copy view cam position for local use - dup_viewx = viewx; - dup_viewy = viewy; - dup_viewz = viewz; - dup_viewangle = viewangle; - - // set window position - gl_centery = gl_basecentery; - gl_viewwindowy = gl_baseviewwindowy; - gl_windowcentery = gl_basewindowcentery; - if (splitscreen && viewnumber == 1) - { - gl_viewwindowy += (vid.height/2); - gl_windowcentery += (vid.height/2); - } - - // check for new console commands. - NetUpdate(); + if (skybox) + R_SkyboxFrame(player); + else + R_SetupFrame(player); - gl_viewx = FIXED_TO_FLOAT(dup_viewx); - gl_viewy = FIXED_TO_FLOAT(dup_viewy); - gl_viewz = FIXED_TO_FLOAT(dup_viewz); - gl_viewsin = FIXED_TO_FLOAT(viewsin); - gl_viewcos = FIXED_TO_FLOAT(viewcos); + gl_viewx = FixedToFloat(viewx); + gl_viewy = FixedToFloat(viewy); + gl_viewz = FixedToFloat(viewz); + gl_viewsin = FixedToFloat(viewsin); + gl_viewcos = FixedToFloat(viewcos); //04/01/2000: Hurdler: added for T&L // It should replace all other gl_viewxxx when finished memset(&atransform, 0x00, sizeof(FTransform)); - HWR_SetTransformAiming(&atransform, player, true); + HWR_SetTransformAiming(&atransform, player, skybox); atransform.angley = (float)(viewangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); - gl_viewludsin = FIXED_TO_FLOAT(FINECOSINE(gl_aimingangle>>ANGLETOFINESHIFT)); - gl_viewludcos = FIXED_TO_FLOAT(-FINESINE(gl_aimingangle>>ANGLETOFINESHIFT)); + gl_viewludsin = FixedToFloat(FINECOSINE(gl_aimingangle>>ANGLETOFINESHIFT)); + gl_viewludcos = FixedToFloat(-FINESINE(gl_aimingangle>>ANGLETOFINESHIFT)); if (*type == postimg_flip) atransform.flip = true; else atransform.flip = false; - atransform.x = gl_viewx; // FIXED_TO_FLOAT(viewx) - atransform.y = gl_viewy; // FIXED_TO_FLOAT(viewy) - atransform.z = gl_viewz; // FIXED_TO_FLOAT(viewz) + atransform.x = gl_viewx; + atransform.y = gl_viewy; + atransform.z = gl_viewz; atransform.scalex = 1; atransform.scaley = (float)vid.width/vid.height; atransform.scalez = 1; @@ -6149,7 +5369,7 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) if (player->viewrollangle != 0) { fixed_t rol = AngleFixed(player->viewrollangle); - atransform.rollangle = FIXED_TO_FLOAT(rol); + atransform.rollangle = FixedToFloat(rol); atransform.roll = true; atransform.rollx = 1.0f; atransform.rollz = 0.0f; @@ -6157,6 +5377,19 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) atransform.splitscreen = splitscreen; gl_fovlud = (float)(1.0l/tan((double)(fpov*M_PIl/360l))); +} + +// ========================================================================== +// Same as rendering the player view, but from the skybox object +// ========================================================================== +void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) +{ + const float fpov = FixedToFloat(R_GetPlayerFov(player)); + + HWR_SetupView(player, viewnumber, fpov, true); + + // check for new console commands. + NetUpdate(); //------------------------------------------------------------------------ HWR_ClearView(); @@ -6171,19 +5404,15 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) drawcount = 0; -#ifdef NEWCLIP if (rendermode == render_opengl) { - angle_t a1 = gld_FrustumAngle(gl_aimingangle); + angle_t a1 = gld_FrustumAngle(fpov, gl_aimingangle); gld_clipper_Clear(); gld_clipper_SafeAddClipRange(viewangle + a1, viewangle - a1); #ifdef HAVE_SPHEREFRUSTRUM gld_FrustrumSetup(); #endif } -#else - HWR_ClearClipSegs(); -#endif //04/01/2000: Hurdler: added for T&L // Actually it only works on Walls and Planes @@ -6248,17 +5477,11 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) { const float fpov = FixedToFloat(R_GetPlayerFov(player)); - postimg_t *type; const boolean skybox = (skyboxmo[0] && cv_skybox.value); // True if there's a skybox object and skyboxes are on FRGBAFloat ClearColor; - if (splitscreen && player == &players[secondarydisplayplayer]) - type = &postimgtype2; - else - type = &postimgtype; - ClearColor.red = 0.0f; ClearColor.green = 0.0f; ClearColor.blue = 0.0f; @@ -6275,82 +5498,13 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) HWR_RenderSkyboxView(viewnumber, player); // This is drawn before everything else so it is placed behind PS_STOP_TIMING(ps_hw_skyboxtime); - { - // do we really need to save player (is it not the same)? - player_t *saved_player = stplyr; - stplyr = player; - ST_doPaletteStuff(); - stplyr = saved_player; -#ifdef ALAM_LIGHTING - HWR_SetLights(viewnumber); -#endif - } + HWR_SetupView(player, viewnumber, fpov, false); - // note: sets viewangle, viewx, viewy, viewz - R_SetupFrame(player); framecount++; // timedemo - // copy view cam position for local use - dup_viewx = viewx; - dup_viewy = viewy; - dup_viewz = viewz; - dup_viewangle = viewangle; - - // set window position - gl_centery = gl_basecentery; - gl_viewwindowy = gl_baseviewwindowy; - gl_windowcentery = gl_basewindowcentery; - if (splitscreen && viewnumber == 1) - { - gl_viewwindowy += (vid.height/2); - gl_windowcentery += (vid.height/2); - } - // check for new console commands. NetUpdate(); - gl_viewx = FIXED_TO_FLOAT(dup_viewx); - gl_viewy = FIXED_TO_FLOAT(dup_viewy); - gl_viewz = FIXED_TO_FLOAT(dup_viewz); - gl_viewsin = FIXED_TO_FLOAT(viewsin); - gl_viewcos = FIXED_TO_FLOAT(viewcos); - - //04/01/2000: Hurdler: added for T&L - // It should replace all other gl_viewxxx when finished - memset(&atransform, 0x00, sizeof(FTransform)); - - HWR_SetTransformAiming(&atransform, player, false); - atransform.angley = (float)(viewangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); - - gl_viewludsin = FIXED_TO_FLOAT(FINECOSINE(gl_aimingangle>>ANGLETOFINESHIFT)); - gl_viewludcos = FIXED_TO_FLOAT(-FINESINE(gl_aimingangle>>ANGLETOFINESHIFT)); - - if (*type == postimg_flip) - atransform.flip = true; - else - atransform.flip = false; - - atransform.x = gl_viewx; // FIXED_TO_FLOAT(viewx) - atransform.y = gl_viewy; // FIXED_TO_FLOAT(viewy) - atransform.z = gl_viewz; // FIXED_TO_FLOAT(viewz) - atransform.scalex = 1; - atransform.scaley = (float)vid.width/vid.height; - atransform.scalez = 1; - - atransform.fovxangle = fpov; // Tails - atransform.fovyangle = fpov; // Tails - if (player->viewrollangle != 0) - { - 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; - - gl_fovlud = (float)(1.0l/tan((double)(fpov*M_PIl/360l))); - //------------------------------------------------------------------------ HWR_ClearView(); // Clears the depth buffer and resets the view I believe @@ -6364,19 +5518,15 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) drawcount = 0; -#ifdef NEWCLIP if (rendermode == render_opengl) { - angle_t a1 = gld_FrustumAngle(gl_aimingangle); + angle_t a1 = gld_FrustumAngle(fpov, gl_aimingangle); gld_clipper_Clear(); gld_clipper_SafeAddClipRange(viewangle + a1, viewangle - a1); #ifdef HAVE_SPHEREFRUSTRUM gld_FrustrumSetup(); #endif } -#else - HWR_ClearClipSegs(); -#endif //04/01/2000: Hurdler: added for T&L // Actually it only works on Walls and Planes @@ -6451,6 +5601,56 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) HWD.pfnGClipRect(0, 0, vid.width, vid.height, NZCLIP_PLANE); } +// Returns whether palette rendering is "actually enabled." +// Can't have palette rendering if shaders are disabled. +boolean HWR_ShouldUsePaletteRendering(void) +{ + return (pMasterPalette != NULL && cv_glpaletterendering.value && HWR_UseShader()); +} + +// enable or disable palette rendering state depending on settings and availability +// called when relevant settings change +// shader recompilation is done in the cvar callback +static void HWR_TogglePaletteRendering(void) +{ + // which state should we go to? + if (HWR_ShouldUsePaletteRendering()) + { + // are we not in that state already? + if (!gl_palette_rendering_state) + { + gl_palette_rendering_state = true; + + // The textures will still be converted to RGBA by r_opengl. + // This however makes hw_cache use paletted blending for composite textures! + // (patchformat is not touched) + textureformat = GL_TEXFMT_AP_88; + + HWR_SetMapPalette(); + HWR_SetPalette(pLocalPalette); + + // If the r_opengl "texture palette" stays the same during this switch, these textures + // will not be cleared out. However they are still out of date since the + // composite texture blending method has changed. Therefore they need to be cleared. + HWR_LoadMapTextures(numtextures); + } + } + else + { + // are we not in that state already? + if (gl_palette_rendering_state) + { + gl_palette_rendering_state = false; + textureformat = GL_TEXFMT_RGBA; + HWR_SetPalette(pLocalPalette); + // If the r_opengl "texture palette" stays the same during this switch, these textures + // will not be cleared out. However they are still out of date since the + // composite texture blending method has changed. Therefore they need to be cleared. + HWR_LoadMapTextures(numtextures); + } + } +} + void HWR_LoadLevel(void) { #ifdef ALAM_LIGHTING @@ -6464,6 +5664,9 @@ void HWR_LoadLevel(void) HWR_ClearSkyDome(); HWR_BuildSkyDome(); + if (HWR_ShouldUsePaletteRendering()) + HWR_SetMapPalette(); + gl_maploaded = true; } @@ -6471,13 +5674,17 @@ void HWR_LoadLevel(void) // 3D ENGINE COMMANDS // ========================================================================== -static CV_PossibleValue_t glshaders_cons_t[] = {{HWD_SHADEROPTION_OFF, "Off"}, {HWD_SHADEROPTION_ON, "On"}, {HWD_SHADEROPTION_NOCUSTOM, "Ignore custom shaders"}, {0, NULL}}; +static CV_PossibleValue_t glshaders_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Ignore custom shaders"}, {0, NULL}}; static CV_PossibleValue_t glmodelinterpolation_cons_t[] = {{0, "Off"}, {1, "Sometimes"}, {2, "Always"}, {0, NULL}}; static CV_PossibleValue_t glfakecontrast_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Smooth"}, {0, NULL}}; static CV_PossibleValue_t glshearing_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Third-person"}, {0, NULL}}; static void CV_glfiltermode_OnChange(void); static void CV_glanisotropic_OnChange(void); +static void CV_glmodellighting_OnChange(void); +static void CV_glpaletterendering_OnChange(void); +static void CV_glpalettedepth_OnChange(void); +static void CV_glshaders_OnChange(void); static CV_PossibleValue_t glfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSAMPLED, "Nearest"}, {HWD_SET_TEXTUREFILTER_BILINEAR, "Bilinear"}, {HWD_SET_TEXTUREFILTER_TRILINEAR, "Trilinear"}, @@ -6487,8 +5694,7 @@ static CV_PossibleValue_t glfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSA {0, NULL}}; CV_PossibleValue_t glanisotropicmode_cons_t[] = {{1, "MIN"}, {16, "MAX"}, {0, NULL}}; -consvar_t cv_glshaders = CVAR_INIT ("gr_shaders", "On", CV_SAVE, glshaders_cons_t, NULL); -consvar_t cv_glallowshaders = CVAR_INIT ("gr_allowclientshaders", "On", CV_NETVAR, CV_OnOff, NULL); +consvar_t cv_glshaders = CVAR_INIT ("gr_shaders", "On", CV_SAVE|CV_CALL, glshaders_cons_t, CV_glshaders_OnChange); #ifdef ALAM_LIGHTING consvar_t cv_gldynamiclighting = CVAR_INIT ("gr_dynamiclighting", "On", CV_SAVE, CV_OnOff, NULL); @@ -6499,7 +5705,7 @@ consvar_t cv_glcoronasize = CVAR_INIT ("gr_coronasize", "1", CV_SAVE|CV_FLOAT, 0 consvar_t cv_glmodels = CVAR_INIT ("gr_models", "Off", CV_SAVE, CV_OnOff, NULL); consvar_t cv_glmodelinterpolation = CVAR_INIT ("gr_modelinterpolation", "Sometimes", CV_SAVE, glmodelinterpolation_cons_t, NULL); -consvar_t cv_glmodellighting = CVAR_INIT ("gr_modellighting", "Off", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_glmodellighting = CVAR_INIT ("gr_modellighting", "Off", CV_SAVE|CV_CALL, CV_OnOff, CV_glmodellighting_OnChange); consvar_t cv_glshearing = CVAR_INIT ("gr_shearing", "Off", CV_SAVE, glshearing_cons_t, NULL); consvar_t cv_glspritebillboarding = CVAR_INIT ("gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL); @@ -6514,18 +5720,61 @@ consvar_t cv_glsolvetjoin = CVAR_INIT ("gr_solvetjoin", "On", 0, CV_OnOff, NULL) consvar_t cv_glbatching = CVAR_INIT ("gr_batching", "On", 0, CV_OnOff, NULL); +static CV_PossibleValue_t glpalettedepth_cons_t[] = {{16, "16 bits"}, {24, "24 bits"}, {0, NULL}}; + +consvar_t cv_glpaletterendering = CVAR_INIT ("gr_paletterendering", "On", CV_SAVE|CV_CALL, CV_OnOff, CV_glpaletterendering_OnChange); +consvar_t cv_glpalettedepth = CVAR_INIT ("gr_palettedepth", "16 bits", CV_SAVE|CV_CALL, glpalettedepth_cons_t, CV_glpalettedepth_OnChange); + +#define ONLY_IF_GL_LOADED if (vid.glstate != VID_GL_LIBRARY_LOADED) return; consvar_t cv_glwireframe = CVAR_INIT ("gr_wireframe", "Off", 0, CV_OnOff, NULL); static void CV_glfiltermode_OnChange(void) { - if (rendermode == render_opengl) - HWD.pfnSetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_glfiltermode.value); + ONLY_IF_GL_LOADED + HWD.pfnSetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_glfiltermode.value); } static void CV_glanisotropic_OnChange(void) { - if (rendermode == render_opengl) - HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_glanisotropicmode.value); + ONLY_IF_GL_LOADED + HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_glanisotropicmode.value); +} + +static void CV_glmodellighting_OnChange(void) +{ + ONLY_IF_GL_LOADED + // if shaders have been compiled, then they now need to be recompiled. + if (gl_shadersavailable) + HWR_CompileShaders(); +} + +static void CV_glpaletterendering_OnChange(void) +{ + ONLY_IF_GL_LOADED + if (gl_shadersavailable) + { + HWR_CompileShaders(); + HWR_TogglePaletteRendering(); + } +} + +static void CV_glpalettedepth_OnChange(void) +{ + ONLY_IF_GL_LOADED + // refresh the screen palette + if (HWR_ShouldUsePaletteRendering()) + HWR_SetPalette(pLocalPalette); +} + +static void CV_glshaders_OnChange(void) +{ + ONLY_IF_GL_LOADED + HWR_SetShaderState(); + if (cv_glpaletterendering.value) + { + // can't do palette rendering without shaders, so update the state if needed + HWR_TogglePaletteRendering(); + } } //added by Hurdler: console varibale that are saved @@ -6545,9 +5794,9 @@ void HWR_AddCommands(void) CV_RegisterVar(&cv_glskydome); CV_RegisterVar(&cv_glspritebillboarding); CV_RegisterVar(&cv_glfakecontrast); + CV_RegisterVar(&cv_glslopecontrast); CV_RegisterVar(&cv_glshearing); CV_RegisterVar(&cv_glshaders); - CV_RegisterVar(&cv_glallowshaders); CV_RegisterVar(&cv_glfiltermode); CV_RegisterVar(&cv_glanisotropicmode); @@ -6555,11 +5804,9 @@ void HWR_AddCommands(void) CV_RegisterVar(&cv_glbatching); + CV_RegisterVar(&cv_glpaletterendering); + CV_RegisterVar(&cv_glpalettedepth); CV_RegisterVar(&cv_glwireframe); - -#ifndef NEWCLIP - CV_RegisterVar(&cv_glclipwalls); -#endif } // -------------------------------------------------------------------------- @@ -6571,6 +5818,8 @@ void HWR_Startup(void) { CONS_Printf("HWR_Startup()...\n"); + textureformat = patchformat = GL_TEXFMT_RGBA; + HWR_InitPolyPool(); HWR_InitMapTextures(); HWR_InitModels(); @@ -6578,14 +5827,12 @@ void HWR_Startup(void) HWR_InitLight(); #endif + gl_shadersavailable = HWR_InitShaders(); + HWR_SetShaderState(); HWR_LoadAllCustomShaders(); - if (!HWR_CompileShaders()) - gl_shadersavailable = false; + HWR_TogglePaletteRendering(); } - if (rendermode == render_opengl) - textureformat = patchformat = GL_TEXFMT_RGBA; - gl_init = true; } @@ -6649,6 +5896,9 @@ void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, INT32 te { static size_t allocedwalls = 0; + if (!r_renderwalls) + return; + // Force realloc if buffer has been freed if (!wallinfo) allocedwalls = 0; @@ -6675,7 +5925,10 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, FBITFIELD blendmode = blend; UINT8 alpha = pSurf->PolyColor.s.alpha; // retain the alpha - INT32 shader = SHADER_DEFAULT; + INT32 shader = SHADER_NONE; + + if (!r_renderwalls) + return; // Lighting is done here instead so that fog isn't drawn incorrectly on transparent walls after sorting HWR_Lighting(pSurf, lightlevel, wallcolormap); @@ -6720,7 +5973,7 @@ void HWR_DoPostProcessor(player_t *player) // Armageddon Blast Flash! // Could this even be considered postprocessor? - if (player->flashcount) + if (player->flashcount && !HWR_ShouldUsePaletteRendering()) { FOutVector v[4]; FSurfaceInfo Surf; @@ -6745,7 +5998,7 @@ void HWR_DoPostProcessor(player_t *player) // Capture the screen for intermission and screen waving if(gamestate != GS_INTERMISSION) - HWD.pfnMakeScreenTexture(); + HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_GENERIC1); if (splitscreen) // Not supported in splitscreen - someone want to add support? return; @@ -6766,7 +6019,7 @@ void HWR_DoPostProcessor(player_t *player) if (*type == postimg_water) { WAVELENGTH = 5; - AMPLITUDE = 20; + AMPLITUDE = 40; FREQUENCY = 8; } else @@ -6789,7 +6042,7 @@ void HWR_DoPostProcessor(player_t *player) // Capture the screen again for screen waving on the intermission if(gamestate != GS_INTERMISSION) - HWD.pfnMakeScreenTexture(); + HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_GENERIC1); } // Flipping of the screen isn't done here anymore } @@ -6797,18 +6050,18 @@ void HWR_DoPostProcessor(player_t *player) void HWR_StartScreenWipe(void) { //CONS_Debug(DBG_RENDER, "In HWR_StartScreenWipe()\n"); - HWD.pfnStartScreenWipe(); + HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_WIPE_START); } void HWR_EndScreenWipe(void) { //CONS_Debug(DBG_RENDER, "In HWR_EndScreenWipe()\n"); - HWD.pfnEndScreenWipe(); + HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_WIPE_END); } void HWR_DrawIntermissionBG(void) { - HWD.pfnDrawIntermissionBG(); + HWD.pfnDrawScreenTexture(HWD_SCREENTEXTURE_GENERIC1, NULL, 0); } // @@ -6853,201 +6106,40 @@ void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum) return; HWR_GetFadeMask(wipelumpnum); - HWD.pfnDoScreenWipe(); -} + if (wipestyle == WIPESTYLE_COLORMAP && HWR_UseShader()) + { + FSurfaceInfo surf = {0}; + FBITFIELD polyflags = PF_Modulated|PF_NoDepthTest; -void HWR_DoTintedWipe(UINT8 wipenum, UINT8 scrnnum) -{ - // It does the same thing - HWR_DoWipe(wipenum, scrnnum); + polyflags |= (wipestyleflags & WSF_TOWHITE) ? PF_Additive : PF_ReverseSubtract; + surf.PolyColor.s.red = FADEREDFACTOR; + surf.PolyColor.s.green = FADEGREENFACTOR; + surf.PolyColor.s.blue = FADEBLUEFACTOR; + // polycolor alpha communicates fadein / fadeout to the shader and the backend + surf.PolyColor.s.alpha = (wipestyleflags & WSF_FADEIN) ? 255 : 0; + + HWD.pfnSetShader(HWR_GetShaderFromTarget(SHADER_UI_TINTED_WIPE)); + HWD.pfnDoScreenWipe(HWD_SCREENTEXTURE_WIPE_START, HWD_SCREENTEXTURE_WIPE_END, + &surf, polyflags); + HWD.pfnUnSetShader(); + } + else + { + HWD.pfnDoScreenWipe(HWD_SCREENTEXTURE_WIPE_START, HWD_SCREENTEXTURE_WIPE_END, + NULL, 0); + } } void HWR_MakeScreenFinalTexture(void) { - HWD.pfnMakeScreenFinalTexture(); + int tex = HWR_ShouldUsePaletteRendering() ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2; + HWD.pfnMakeScreenTexture(tex); } void HWR_DrawScreenFinalTexture(int width, int height) { - HWD.pfnDrawScreenFinalTexture(width, height); -} - -static inline UINT16 HWR_FindShaderDefs(UINT16 wadnum) -{ - UINT16 i; - lumpinfo_t *lump_p; - - lump_p = wadfiles[wadnum]->lumpinfo; - for (i = 0; i < wadfiles[wadnum]->numlumps; i++, lump_p++) - if (memcmp(lump_p->name, "SHADERS", 7) == 0) - return i; - - return INT16_MAX; -} - -boolean HWR_CompileShaders(void) -{ - return HWD.pfnCompileShaders(); -} - -customshaderxlat_t shaderxlat[] = -{ - {"Flat", SHADER_FLOOR}, - {"WallTexture", SHADER_WALL}, - {"Sprite", SHADER_SPRITE}, - {"Model", SHADER_MODEL}, - {"ModelLighting", SHADER_MODEL_LIGHTING}, - {"WaterRipple", SHADER_WATER}, - {"Fog", SHADER_FOG}, - {"Sky", SHADER_SKY}, - {NULL, 0}, -}; - -void HWR_LoadAllCustomShaders(void) -{ - INT32 i; - - // read every custom shader - for (i = 0; i < numwadfiles; i++) - HWR_LoadCustomShadersFromFile(i, W_FileHasFolders(wadfiles[i])); -} - -void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3) -{ - UINT16 lump; - char *shaderdef, *line; - char *stoken; - char *value; - size_t size; - int linenum = 1; - int shadertype = 0; - int i; - - lump = HWR_FindShaderDefs(wadnum); - if (lump == INT16_MAX) - return; - - shaderdef = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE); - size = W_LumpLengthPwad(wadnum, lump); - - line = Z_Malloc(size+1, PU_STATIC, NULL); - M_Memcpy(line, shaderdef, size); - line[size] = '\0'; - - stoken = strtok(line, "\r\n "); - while (stoken) - { - if ((stoken[0] == '/' && stoken[1] == '/') - || (stoken[0] == '#'))// skip comments - { - stoken = strtok(NULL, "\r\n"); - goto skip_field; - } - - if (!stricmp(stoken, "GLSL")) - { - value = strtok(NULL, "\r\n "); - if (!value) - { - CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); - stoken = strtok(NULL, "\r\n"); // skip end of line - goto skip_lump; - } - - if (!stricmp(value, "VERTEX")) - shadertype = 1; - else if (!stricmp(value, "FRAGMENT")) - shadertype = 2; - -skip_lump: - stoken = strtok(NULL, "\r\n "); - linenum++; - } - else - { - value = strtok(NULL, "\r\n= "); - if (!value) - { - CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: Missing shader target (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); - stoken = strtok(NULL, "\r\n"); // skip end of line - goto skip_field; - } - - if (!shadertype) - { - CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); - Z_Free(line); - return; - } - - for (i = 0; shaderxlat[i].type; i++) - { - if (!stricmp(shaderxlat[i].type, stoken)) - { - size_t shader_size; - char *shader_source; - char *shader_lumpname; - UINT16 shader_lumpnum; - - if (PK3) - { - shader_lumpname = Z_Malloc(strlen(value) + 12, PU_STATIC, NULL); - strcpy(shader_lumpname, "Shaders/sh_"); - strcat(shader_lumpname, value); - shader_lumpnum = W_CheckNumForFullNamePK3(shader_lumpname, wadnum, 0); - } - else - { - shader_lumpname = Z_Malloc(strlen(value) + 4, PU_STATIC, NULL); - strcpy(shader_lumpname, "SH_"); - strcat(shader_lumpname, value); - shader_lumpnum = W_CheckNumForNamePwad(shader_lumpname, wadnum, 0); - } - - if (shader_lumpnum == INT16_MAX) - { - CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: Missing shader source %s (file %s, line %d)\n", shader_lumpname, wadfiles[wadnum]->filename, linenum); - Z_Free(shader_lumpname); - continue; - } - - shader_size = W_LumpLengthPwad(wadnum, shader_lumpnum); - shader_source = Z_Malloc(shader_size, PU_STATIC, NULL); - W_ReadLumpPwad(wadnum, shader_lumpnum, shader_source); - - HWD.pfnLoadCustomShader(shaderxlat[i].id, shader_source, shader_size, (shadertype == 2)); - - Z_Free(shader_source); - Z_Free(shader_lumpname); - } - } - -skip_field: - stoken = strtok(NULL, "\r\n= "); - linenum++; - } - } - - Z_Free(line); - return; -} - -const char *HWR_GetShaderName(INT32 shader) -{ - INT32 i; - - if (shader) - { - for (i = 0; shaderxlat[i].type; i++) - { - if (shaderxlat[i].id == shader) - return shaderxlat[i].type; - } - - return "Unknown"; - } - - return "Default"; + int tex = HWR_ShouldUsePaletteRendering() ? HWD_SCREENTEXTURE_GENERIC3 : HWD_SCREENTEXTURE_GENERIC2; + HWD.pfnDrawScreenFinalTexture(tex, width, height); } #endif // HWRENDER diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 0639bcffeb6446989575bfffb44490433f8473c6..2277c32f3c07b6162148b5b3e56b8ac81dac351b 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -35,11 +35,8 @@ void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player); void HWR_RenderPlayerView(INT32 viewnumber, player_t *player); void HWR_ClearSkyDome(void); void HWR_BuildSkyDome(void); -void HWR_DrawViewBorder(INT32 clearlines); void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum); -void HWR_InitTextureMapping(void); void HWR_SetViewSize(void); -void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option); void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap); void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); void HWR_MakePatch(const patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap); @@ -48,7 +45,6 @@ void HWR_CreateStaticLightmaps(INT32 bspnum); void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color); void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 actualcolor, UINT8 strength); void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT32 actualcolor); // Lat: separate flags from color since color needs to be an uint to work right. -void HWR_DrawPic(INT32 x,INT32 y,lumpnum_t lumpnum); UINT8 *HWR_GetScreenshot(void); boolean HWR_Screenshot(const char *pathname); @@ -61,11 +57,11 @@ void HWR_StartScreenWipe(void); void HWR_EndScreenWipe(void); void HWR_DrawIntermissionBG(void); void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum); -void HWR_DoTintedWipe(UINT8 wipenum, UINT8 scrnnum); void HWR_MakeScreenFinalTexture(void); void HWR_DrawScreenFinalTexture(int width, int height); // This stuff is put here so models can use them +boolean HWR_UseShader(void); void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap); UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work @@ -74,13 +70,7 @@ FBITFIELD HWR_GetBlendModeFlag(INT32 style); FBITFIELD HWR_SurfaceBlend(INT32 style, INT32 transtablenum, FSurfaceInfo *pSurf); FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf); -boolean HWR_CompileShaders(void); - -void HWR_LoadAllCustomShaders(void); -void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3); -const char *HWR_GetShaderName(INT32 shader); - -extern customshaderxlat_t shaderxlat[]; +boolean HWR_ShouldUsePaletteRendering(void); extern CV_PossibleValue_t glanisotropicmode_cons_t[]; @@ -103,21 +93,17 @@ extern consvar_t cv_glspritebillboarding; extern consvar_t cv_glskydome; extern consvar_t cv_glfakecontrast; extern consvar_t cv_glslopecontrast; - extern consvar_t cv_glbatching; +extern consvar_t cv_glpaletterendering; +extern consvar_t cv_glpalettedepth; extern consvar_t cv_glwireframe; -extern float gl_viewwidth, gl_viewheight, gl_baseviewwindowy; - -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 extern ps_metric_t ps_hw_skyboxtime; extern ps_metric_t ps_hw_nodesorttime; diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 9797a93312e2df6159f64ef472abe1beb5f2f024..931867142200338b7635d7b04307df587eafa129 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -390,8 +390,6 @@ static void md2_loadTexture(md2_t *model) if (!grPatch->mipmap->downloaded && !grPatch->mipmap->data) { int w = 0, h = 0; - UINT32 size; - RGBA_t *image; #ifdef HAVE_PNG grPatch->mipmap->format = PNG_Load(filename, &w, &h, grPatch); @@ -412,13 +410,19 @@ static void md2_loadTexture(md2_t *model) grPatch->mipmap->width = (UINT16)w; grPatch->mipmap->height = (UINT16)h; - // Lactozilla: Apply colour cube - image = grPatch->mipmap->data; - size = w*h; - while (size--) + // for palette rendering, color cube is applied in post-processing instead of here + if (!HWR_ShouldUsePaletteRendering()) { - V_CubeApply(&image->s.red, &image->s.green, &image->s.blue); - image++; + UINT32 size; + RGBA_t *image; + // Lactozilla: Apply colour cube + image = grPatch->mipmap->data; + size = w*h; + while (size--) + { + V_CubeApply(&image->s.red, &image->s.green, &image->s.blue); + image++; + } } } HWD.pfnSetTexture(grPatch->mipmap); @@ -567,19 +571,15 @@ void HWR_LoadModels(void) } // Add sprite models. - // Must be 4 characters long exactly. Otherwise, it's not a sprite name. - if (len == 4) + for (i = 0; i < numsprites; i++) { - for (i = 0; i < numsprites; i++) + if (stricmp(name, sprnames[i]) == 0) { - if (stricmp(name, sprnames[i]) == 0) - { - md2_models[i].scale = scale; - md2_models[i].offset = offset; - md2_models[i].found = true; - strcpy(md2_models[i].filename, filename); - goto modelfound; - } + md2_models[i].scale = scale; + md2_models[i].offset = offset; + md2_models[i].found = true; + strcpy(md2_models[i].filename, filename); + goto modelfound; } } @@ -1074,30 +1074,47 @@ static boolean HWR_CanInterpolateSprite2(modelspr2frames_t *spr2frame) return spr2frame->interpolate; } -// -// HWR_GetModelSprite2 (see P_GetSkinSprite2) -// For non-super players, tries each sprite2's immediate predecessor until it finds one with a number of frames or ends up at standing. -// For super players, does the same as above - but tries the super equivalent for each sprite2 before the non-super version. -// - -static UINT8 HWR_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *player) +static modelspr2frames_t *HWR_GetModelSprite2Frames(md2_t *md2, UINT16 spr2) { - UINT8 super = 0, i = 0; + if (!md2 || !md2->model) + return NULL; - if (!md2 || !md2->model || !md2->model->spr2frames || !skin) - return 0; + boolean is_super = spr2 & SPR2F_SUPER; + + spr2 &= SPR2F_MASK; + + if (spr2 >= free_spr2) + return NULL; + + if (is_super) + { + modelspr2frames_t *frames = md2->model->superspr2frames; + if (frames && md2->model->superspr2frames[spr2].numframes) + return &md2->model->superspr2frames[spr2]; + } + + if (md2->model->spr2frames[spr2].numframes) + return &md2->model->spr2frames[spr2]; + + return NULL; +} - if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2) +static UINT16 HWR_GetModelSprite2Num(md2_t *md2, skin_t *skin, UINT16 spr2, player_t *player) +{ + UINT16 super = 0; + UINT8 i = 0; + + if (!md2 || !md2->model || !skin) return 0; - while (!md2->model->spr2frames[spr2].numframes + while (!HWR_GetModelSprite2Frames(md2, spr2) && spr2 != SPR2_STND - && ++i != 32) // recursion limiter + && ++i < 32) // recursion limiter { - if (spr2 & FF_SPR2SUPER) + if (spr2 & SPR2F_SUPER) { - super = FF_SPR2SUPER; - spr2 &= ~FF_SPR2SUPER; + super = SPR2F_SUPER; + spr2 &= ~SPR2F_SUPER; continue; } @@ -1126,7 +1143,7 @@ static UINT8 HWR_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t } if (i >= 32) // probably an infinite loop... - return 0; + spr2 = 0; return spr2; } @@ -1137,6 +1154,9 @@ static void adjustTextureCoords(model_t *model, patch_t *patch) int i; GLPatch_t *gpatch = ((GLPatch_t *)patch->hardware); + if (!gpatch) + return; + for (i = 0; i < model->numMeshes; i++) { int j; @@ -1173,6 +1193,90 @@ static void adjustTextureCoords(model_t *model, patch_t *patch) model->max_t = gpatch->max_t; } +static INT32 GetAnimDuration(mobj_t *mobj) //part of p_mobj's setplayermobjstate logic, used to make sure that anim durations are actually correct when the speed gets adjusted on players +{ + player_t *player = mobj->player; + INT32 tics = mobj->state->tics; + + if (!(mobj->frame & FF_ANIMATE) && mobj->anim_duration) //set manually by something through lua + return mobj->anim_duration; + + if (!player && mobj->type == MT_TAILSOVERLAY && mobj->tracer) //so tails overlays interpolate properly + player = mobj->tracer->player; + if (player) + { + if (player->panim == PA_EDGE && (player->charflags & SF_FASTEDGE)) + tics = 2; + else if (player->powers[pw_tailsfly] && (!(player->mo->eflags & MFE_UNDERWATER) || (mobj->type == MT_PLAYER))) //tailsoverlay does not get adjusted from these rules when underwater + { + if (player->fly1 > 0) + tics = 1; + else if (!(player->mo->eflags & MFE_UNDERWATER)) + tics = 2; + else + tics = 4; + } + else if (!(disableSpeedAdjust || player->charflags & SF_NOSPEEDADJUST)) + { + fixed_t speed;// = FixedDiv(player->speed, FixedMul(mobj->scale, player->mo->movefactor)); + if (player->panim == PA_FALL) + { + speed = FixedDiv(abs(mobj->momz), mobj->scale); + if (speed < 10<<FRACBITS) + tics = 4; + else if (speed < 20<<FRACBITS) + tics = 3; + else if (speed < 30<<FRACBITS) + tics = 2; + else + tics = 1; + } + else if (player->panim == PA_ABILITY2 && player->charability2 == CA2_SPINDASH) + { + fixed_t step = (player->maxdash - player->mindash)/4; + speed = (player->dashspeed - player->mindash); + if (speed > 3*step) + tics = 1; + else if (speed > step) + tics = 2; + else + tics = 3; + } + else + { + speed = FixedDiv(player->speed, FixedMul(mobj->scale, player->mo->movefactor)); + if (player->panim == PA_ROLL || player->panim == PA_JUMP) + { + if (speed > 16<<FRACBITS) + tics = 1; + else + tics = 2; + } + else if (P_IsObjectOnGround(mobj) || ((player->charability == CA_FLOAT || player->charability == CA_SLOWFALL) && player->secondjump == 1) || player->powers[pw_super]) // Only if on the ground or superflying. + { + if (player->panim == PA_WALK) + { + if (speed > 12<<FRACBITS) + tics = 2; + else if (speed > 6<<FRACBITS) + tics = 3; + else + tics = 4; + } + else if ((player->panim == PA_RUN) || (player->panim == PA_DASH)) + { + if (speed > 52<<FRACBITS) + tics = 1; + else + tics = 2; + } + } + } + } + } + return tics; +} + // // HWR_DrawModel // @@ -1184,7 +1288,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) char filename[64]; INT32 frame = 0; INT32 nextFrame = -1; - UINT8 spr2 = 0; + modelspr2frames_t *spr2frames = NULL; FTransform p; FSurfaceInfo Surf; @@ -1246,12 +1350,13 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) { patch_t *gpatch, *blendgpatch; GLPatch_t *hwrPatch = NULL, *hwrBlendPatch = NULL; - float durs = (float)spr->mobj->state->tics; + float durs = GetAnimDuration(spr->mobj); float tics = (float)spr->mobj->tics; const boolean papersprite = (R_ThingIsPaperSprite(spr->mobj) && !R_ThingIsFloorSprite(spr->mobj)); const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !R_ThingVerticallyFlipped(spr->mobj)); const UINT8 hflip = (UINT8)(!(spr->mobj->mirrored) != !R_ThingHorizontallyFlipped(spr->mobj)); spritedef_t *sprdef; + UINT16 spr2 = 0; spriteframe_t *sprframe; INT32 mod; interpmobjstate_t interp; @@ -1266,8 +1371,13 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) } // Apparently people don't like jump frames like that, so back it goes - //if (tics > durs) - //durs = tics; + if (tics > durs) + durs = tics; + + // Make linkdraw objects use their tracer's alpha value + fixed_t newalpha = spr->mobj->alpha; + if ((spr->mobj->flags2 & MF2_LINKDRAW) && spr->mobj->tracer) + newalpha = spr->mobj->tracer->alpha; INT32 blendmode; if (spr->mobj->frame & FF_BLENDMASK) @@ -1283,6 +1393,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) Surf.PolyFlags = HWR_GetBlendModeFlag(blendmode); } + Surf.PolyColor.s.alpha = FixedMul(newalpha, Surf.PolyColor.s.alpha); + // don't forget to enable the depth test because we can't do this // like before: model polygons are not sorted @@ -1414,18 +1526,28 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) tics = (float)spr->mobj->anim_duration; } + if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) + sprdef = P_GetSkinSpritedef(spr->mobj->skin, spr->mobj->sprite2); + else + sprdef = &sprites[spr->mobj->sprite]; + frame = (spr->mobj->frame & FF_FRAMEMASK); - if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY && md2->model->spr2frames) + if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) { - spr2 = HWR_GetModelSprite2(md2, spr->mobj->skin, spr->mobj->sprite2, spr->mobj->player); - mod = md2->model->spr2frames[spr2].numframes; + spr2 = HWR_GetModelSprite2Num(md2, spr->mobj->skin, spr->mobj->sprite2, spr->mobj->player); + spr2frames = HWR_GetModelSprite2Frames(md2, spr2); + } + if (spr2frames) + { + spritedef_t *defaultdef = P_GetSkinSpritedef(spr->mobj->skin, spr2); + mod = spr2frames->numframes; #ifndef DONTHIDEDIFFANIMLENGTH // by default, different anim length is masked by the mod - if (mod > (INT32)((skin_t *)spr->mobj->skin)->sprites[spr2].numframes) - mod = ((skin_t *)spr->mobj->skin)->sprites[spr2].numframes; + if (mod > (INT32)defaultdef->numframes) + mod = defaultdef->numframes; #endif if (!mod) mod = 1; - frame = md2->model->spr2frames[spr2].frames[frame%mod]; + frame = spr2frames->frames[frame % mod]; } else { @@ -1445,13 +1567,18 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) if (durs > INTERPOLERATION_LIMIT) durs = INTERPOLERATION_LIMIT; - if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY && md2->model->spr2frames) + if (spr2frames) { - if (HWR_CanInterpolateSprite2(&md2->model->spr2frames[spr2]) + UINT16 next_spr2 = P_GetStateSprite2(&states[spr->mobj->state->nextstate]); + + // Add or remove SPR2F_SUPER based on certain conditions + next_spr2 = P_ApplySuperFlagToSprite2(next_spr2, spr->mobj); + + if (HWR_CanInterpolateSprite2(spr2frames) && (spr->mobj->frame & FF_ANIMATE || (spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite == SPR_PLAY - && ((P_GetSkinSprite2(spr->mobj->skin, (((spr->mobj->player && spr->mobj->player->powers[pw_super]) ? FF_SPR2SUPER : 0)|states[spr->mobj->state->nextstate].frame) & FF_FRAMEMASK, spr->mobj->player) == spr->mobj->sprite2))))) + && ((P_GetSkinSprite2(spr->mobj->skin, next_spr2, spr->mobj->player) == spr->mobj->sprite2))))) { nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1; if (nextFrame >= mod) @@ -1462,7 +1589,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) nextFrame = 0; } if (frame || !(spr->mobj->state->frame & FF_SPR2ENDSTATE)) - nextFrame = md2->model->spr2frames[spr2].frames[nextFrame]; + nextFrame = spr2frames->frames[nextFrame]; else nextFrame = -1; } @@ -1498,11 +1625,6 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) else p.z = FIXED_TO_FLOAT(interp.z); - if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) - sprdef = &((skin_t *)spr->mobj->skin)->sprites[spr->mobj->sprite2]; - else - sprdef = &sprites[spr->mobj->sprite]; - sprframe = &sprdef->spriteframes[spr->mobj->frame & FF_FRAMEMASK]; if (sprframe->rotate || papersprite) @@ -1550,7 +1672,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) p.flip = atransform.flip; p.mirror = atransform.mirror; - HWD.pfnSetShader(SHADER_MODEL); // model shader + if (HWR_UseShader()) + HWD.pfnSetShader(HWR_GetShaderFromTarget(SHADER_MODEL)); { float this_scale = FIXED_TO_FLOAT(interp.scale); @@ -1568,7 +1691,6 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, md2->scale * xs, md2->scale * ys, flip, hflip, &Surf); } } - return true; } diff --git a/src/hardware/hw_model.c b/src/hardware/hw_model.c index 0d656f35ad8e72673134f1bf53f561842b280f49..5856473e4c9855c6416f97843cd476fde2c587d2 100644 --- a/src/hardware/hw_model.c +++ b/src/hardware/hw_model.c @@ -292,6 +292,7 @@ void LoadModelSprite2(model_t *model) { INT32 i; modelspr2frames_t *spr2frames = NULL; + modelspr2frames_t *superspr2frames = NULL; INT32 numframes = model->meshes[0].numFrames; char *framename = model->frameNames; @@ -335,25 +336,33 @@ void LoadModelSprite2(model_t *model) spr2idx = 0; while (spr2idx < free_spr2) { + modelspr2frames_t *frames = NULL; if (!memcmp(spr2names[spr2idx], name, 4)) { if (!spr2frames) - spr2frames = (modelspr2frames_t*)Z_Calloc(sizeof(modelspr2frames_t)*NUMPLAYERSPRITES*2, PU_STATIC, NULL); + spr2frames = (modelspr2frames_t*)Z_Calloc(sizeof(modelspr2frames_t)*NUMPLAYERSPRITES, PU_STATIC, NULL); + frames = spr2frames; + if (super) - spr2idx |= FF_SPR2SUPER; + { + if (!superspr2frames) + superspr2frames = (modelspr2frames_t*)Z_Calloc(sizeof(modelspr2frames_t)*NUMPLAYERSPRITES, PU_STATIC, NULL); + frames = superspr2frames; + } + if (framechars[0]) { frame = atoi(framechars); - if (spr2frames[spr2idx].numframes < frame+1) - spr2frames[spr2idx].numframes = frame+1; + if (frames[spr2idx].numframes < frame+1) + frames[spr2idx].numframes = frame+1; } else { - frame = spr2frames[spr2idx].numframes; - spr2frames[spr2idx].numframes++; + frame = frames[spr2idx].numframes; + frames[spr2idx].numframes++; } - spr2frames[spr2idx].frames[frame] = i; - spr2frames[spr2idx].interpolate = interpolate; + frames[spr2idx].frames[frame] = i; + frames[spr2idx].interpolate = interpolate; break; } spr2idx++; @@ -366,7 +375,10 @@ void LoadModelSprite2(model_t *model) if (model->spr2frames) Z_Free(model->spr2frames); + if (model->superspr2frames) + Z_Free(model->superspr2frames); model->spr2frames = spr2frames; + model->superspr2frames = superspr2frames; } // diff --git a/src/hardware/hw_model.h b/src/hardware/hw_model.h index f057271df1397f528a615f93331480f620586417..5eb649b173303d72dba16a46c0793ab4d29f351c 100644 --- a/src/hardware/hw_model.h +++ b/src/hardware/hw_model.h @@ -101,6 +101,7 @@ typedef struct model_s char *frameNames; boolean interpolate[256]; modelspr2frames_t *spr2frames; + modelspr2frames_t *superspr2frames; // the max_s and max_t values that the uvs are currently adjusted to // (if a sprite is used as a texture) diff --git a/src/hardware/hw_shaders.c b/src/hardware/hw_shaders.c new file mode 100644 index 0000000000000000000000000000000000000000..fde67375f016e8132004ee14231cc31e575f5a30 --- /dev/null +++ b/src/hardware/hw_shaders.c @@ -0,0 +1,737 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2021-2024 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 hw_shaders.c +/// \brief Handles the shaders used by the game. + +#ifdef HWRENDER + +#include "hw_glob.h" +#include "hw_drv.h" +#include "hw_shaders.h" +#include "../z_zone.h" + +// ================ +// Shader sources +// ================ + +static struct { + const char *vertex; + const char *fragment; +} const gl_shadersources[] = { + // Floor shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_FLOOR_FRAGMENT_SHADER}, + + // Wall shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_WALL_FRAGMENT_SHADER}, + + // Sprite shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_WALL_FRAGMENT_SHADER}, + + // Model shader + {GLSL_MODEL_VERTEX_SHADER, GLSL_MODEL_FRAGMENT_SHADER}, + + // Water shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_WATER_FRAGMENT_SHADER}, + + // Fog shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_FOG_FRAGMENT_SHADER}, + + // Sky shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SKY_FRAGMENT_SHADER}, + + // Palette postprocess shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_PALETTE_POSTPROCESS_FRAGMENT_SHADER}, + + // UI colormap fade shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_UI_COLORMAP_FADE_FRAGMENT_SHADER}, + + // UI tinted wipe shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_UI_TINTED_WIPE_FRAGMENT_SHADER}, + + {NULL, NULL}, +}; + +typedef struct +{ + int base_shader; // index of base shader_t + int custom_shader; // index of custom shader_t +} shadertarget_t; + +typedef struct +{ + char *vertex; + char *fragment; + boolean compiled; +} shader_t; // these are in an array and accessed by indices + +// the array has NUMSHADERTARGETS entries for base shaders and for custom shaders +// the array could be expanded in the future to fit "dynamic" custom shaders that +// aren't fixed to shader targets +static shader_t gl_shaders[NUMSHADERTARGETS*2]; + +static shadertarget_t gl_shadertargets[NUMSHADERTARGETS]; + +#define WHITESPACE_CHARS " \t" + +#define MODEL_LIGHTING_DEFINE "#define SRB2_MODEL_LIGHTING" +#define PALETTE_RENDERING_DEFINE "#define SRB2_PALETTE_RENDERING" + +// Initialize shader variables and the backend's shader system. Load the base shaders. +// Returns false if shaders cannot be used. +boolean HWR_InitShaders(void) +{ + int i; + + if (!HWD.pfnInitShaders()) + return false; + + for (i = 0; i < NUMSHADERTARGETS; i++) + { + // set up string pointers for base shaders + gl_shaders[i].vertex = Z_StrDup(gl_shadersources[i].vertex); + gl_shaders[i].fragment = Z_StrDup(gl_shadersources[i].fragment); + // set shader target indices to correct values + gl_shadertargets[i].base_shader = i; + gl_shadertargets[i].custom_shader = -1; + } + + HWR_CompileShaders(); + + return true; +} + +// helper function: strstr but returns an int with the substring position +// returns INT32_MAX if not found +static INT32 strstr_int(const char *str1, const char *str2) +{ + char *location = strstr(str1, str2); + if (location) + return location - str1; + else + return INT32_MAX; +} + +// Creates a preprocessed copy of the shader according to the current graphics settings +// Returns a pointer to the results on success and NULL on failure. +// Remember memory management of the returned string. +static char *HWR_PreprocessShader(char *original) +{ + const char *line_ending = "\n"; + int line_ending_len; + char *read_pos = original; + int original_len = strlen(original); + int distance_to_end = original_len; + int new_len; + char *new_shader; + char *write_pos; + char shader_glsl_version[3]; + int version_pos = -1; + int version_len = 0; + + if (strstr(original, "\r\n")) + { + line_ending = "\r\n"; + // check if all line endings are same + while ((read_pos = strchr(read_pos, '\n'))) + { + read_pos--; + if (*read_pos != '\r') + { + // this file contains mixed CRLF and LF line endings. + // treating it as a LF file during parsing should keep + // the results sane enough as long as the gpu driver is fine + // with these kinds of weirdly formatted shader sources. + line_ending = "\n"; + break; + } + read_pos += 2; + } + read_pos = original; + } + + line_ending_len = strlen(line_ending); + + // Find the #version directive, if it exists. Also don't get fooled if it's + // inside a comment. Copy the version digits so they can be used in the preamble. + // Time for some string parsing :D + +#define STARTSWITH(str, with_what) !strncmp(str, with_what, sizeof(with_what)-1) +#define ADVANCE(amount) read_pos += (amount); distance_to_end -= (amount); + while (true) + { + // we're at the start of a line or at the end of a block comment. + // first get any possible whitespace out of the way + int whitespace_len = strspn(read_pos, WHITESPACE_CHARS); + if (whitespace_len == distance_to_end) + break; // we got to the end + ADVANCE(whitespace_len) + + if (STARTSWITH(read_pos, "#version")) + { + // found a version directive (and it's not inside a comment) + // now locate, verify and read the version number + int version_number_len; + version_pos = read_pos - original; + ADVANCE(sizeof("#version") - 1) + whitespace_len = strspn(read_pos, WHITESPACE_CHARS); + if (!whitespace_len) + { + CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Syntax error in #version. Expected space after #version, but got other text.\n"); + return NULL; + } + else if (whitespace_len == distance_to_end) + { + CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Syntax error in #version. Expected version number, but got end of file.\n"); + return NULL; + } + ADVANCE(whitespace_len) + version_number_len = strspn(read_pos, "0123456789"); + if (!version_number_len) + { + CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Syntax error in #version. Expected version number, but got other text.\n"); + return NULL; + } + else if (version_number_len != 3) + { + CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Syntax error in #version. Expected version with 3 digits, but got %d digits.\n", version_number_len); + return NULL; + } + M_Memcpy(shader_glsl_version, read_pos, 3); + ADVANCE(version_number_len) + version_len = (read_pos - original) - version_pos; + whitespace_len = strspn(read_pos, WHITESPACE_CHARS); + ADVANCE(whitespace_len) + if (STARTSWITH(read_pos, "es")) + { + CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Support for ES shaders is not implemented.\n"); + return NULL; + } + break; + } + else + { + // go to next newline or end of next block comment if it starts before the newline + // and is not inside a line comment + INT32 newline_pos = strstr_int(read_pos, line_ending); + INT32 line_comment_pos; + INT32 block_comment_pos; + // optimization: temporarily put a null at the line ending, so strstr does not needlessly + // look past it since we're only interested in the current line + if (newline_pos != INT32_MAX) + read_pos[newline_pos] = '\0'; + line_comment_pos = strstr_int(read_pos, "//"); + block_comment_pos = strstr_int(read_pos, "/*"); + // restore the line ending, remove the null we just put there + if (newline_pos != INT32_MAX) + read_pos[newline_pos] = line_ending[0]; + if (line_comment_pos < block_comment_pos) + { + // line comment found, skip rest of the line + if (newline_pos != INT32_MAX) + { + ADVANCE(newline_pos + line_ending_len) + } + else + { + // we got to the end + break; + } + } + else if (block_comment_pos < line_comment_pos) + { + // block comment found, skip past it + INT32 block_comment_end; + ADVANCE(block_comment_pos + 2) + block_comment_end = strstr_int(read_pos, "*/"); + if (block_comment_end == INT32_MAX) + { + // could also leave insertion_pos at 0 and let the GLSL compiler + // output an error message for this broken comment + CONS_Alert(CONS_ERROR, "HWR_PreprocessShader: Encountered unclosed block comment in shader.\n"); + return NULL; + } + ADVANCE(block_comment_end + 2) + } + else if (newline_pos == INT32_MAX) + { + // we got to the end + break; + } + else + { + // nothing special on this line, move to the next one + ADVANCE(newline_pos + line_ending_len) + } + } + } +#undef STARTSWITH +#undef ADVANCE + +#define ADD_TO_LEN(def) new_len += sizeof(def) - 1 + line_ending_len; + + // Calculate length of modified shader. + new_len = original_len; + if (cv_glmodellighting.value) + ADD_TO_LEN(MODEL_LIGHTING_DEFINE) + if (cv_glpaletterendering.value) + ADD_TO_LEN(PALETTE_RENDERING_DEFINE) + +#undef ADD_TO_LEN + +#define VERSION_PART "#version " + + if (new_len != original_len) + { + if (version_pos != -1) + new_len += sizeof(VERSION_PART) - 1 + 3 + line_ending_len; + new_len += sizeof("#line 0") - 1 + line_ending_len; + } + + // Allocate memory for modified shader. + new_shader = Z_Malloc(new_len + 1, PU_STATIC, NULL); + + read_pos = original; + write_pos = new_shader; + + if (new_len != original_len && version_pos != -1) + { + strcpy(write_pos, VERSION_PART); + write_pos += sizeof(VERSION_PART) - 1; + M_Memcpy(write_pos, shader_glsl_version, 3); + write_pos += 3; + strcpy(write_pos, line_ending); + write_pos += line_ending_len; + } + +#undef VERSION_PART + +#define WRITE_DEFINE(define) \ + { \ + strcpy(write_pos, define); \ + write_pos += sizeof(define) - 1; \ + strcpy(write_pos, line_ending); \ + write_pos += line_ending_len; \ + } + + // Write the defines. + if (cv_glmodellighting.value) + WRITE_DEFINE(MODEL_LIGHTING_DEFINE) + if (cv_glpaletterendering.value) + WRITE_DEFINE(PALETTE_RENDERING_DEFINE) + +#undef WRITE_DEFINE + + // Write a #line directive, so compiler errors will report line numbers from the + // original shader without our preamble lines. + if (new_len != original_len) + { + // line numbering in the #line directive is different for versions 110-150 + if (version_pos == -1 || shader_glsl_version[0] == '1') + strcpy(write_pos, "#line 0"); + else + strcpy(write_pos, "#line 1"); + write_pos += sizeof("#line 0") - 1; + strcpy(write_pos, line_ending); + write_pos += line_ending_len; + } + + // Copy the original shader. + M_Memcpy(write_pos, read_pos, original_len); + + // Erase the original #version directive, if it exists and was copied. + if (new_len != original_len && version_pos != -1) + memset(write_pos + version_pos, ' ', version_len); + + // Terminate the new string. + new_shader[new_len] = '\0'; + + return new_shader; +} + +// preprocess and compile shader at gl_shaders[index] +static void HWR_CompileShader(int index) +{ + char *vertex_source = gl_shaders[index].vertex; + char *fragment_source = gl_shaders[index].fragment; + + if (vertex_source) + { + char *preprocessed = HWR_PreprocessShader(vertex_source); + if (!preprocessed) return; + HWD.pfnLoadShader(index, preprocessed, HWD_SHADERSTAGE_VERTEX); + } + if (fragment_source) + { + char *preprocessed = HWR_PreprocessShader(fragment_source); + if (!preprocessed) return; + HWD.pfnLoadShader(index, preprocessed, HWD_SHADERSTAGE_FRAGMENT); + } + + gl_shaders[index].compiled = HWD.pfnCompileShader(index); +} + +// compile or recompile shaders +void HWR_CompileShaders(void) +{ + int i; + + for (i = 0; i < NUMSHADERTARGETS; i++) + { + int custom_index = gl_shadertargets[i].custom_shader; + HWR_CompileShader(i); + if (!gl_shaders[i].compiled) + CONS_Alert(CONS_ERROR, "HWR_CompileShaders: Compilation failed for base %s shader!\n", shaderxlat[i].type); + if (custom_index != -1) + { + HWR_CompileShader(custom_index); + if (!gl_shaders[custom_index].compiled) + CONS_Alert(CONS_ERROR, "HWR_CompileShaders: Recompilation failed for the custom %s shader! See the console messages above for more information.\n", shaderxlat[i].type); + } + } +} + +int HWR_GetShaderFromTarget(int shader_target) +{ + int custom_shader = gl_shadertargets[shader_target].custom_shader; + // use custom shader if following are true + // - custom shader exists + // - custom shader has been compiled successfully + // - custom shaders are enabled + // - custom shaders are allowed by the server + if (custom_shader != -1 && gl_shaders[custom_shader].compiled && + cv_glshaders.value == 1 && cv_glallowshaders.value) + return custom_shader; + else + return gl_shadertargets[shader_target].base_shader; +} + +static inline UINT16 HWR_FindShaderDefs(UINT16 wadnum) +{ + UINT16 i; + lumpinfo_t *lump_p; + + lump_p = wadfiles[wadnum]->lumpinfo; + for (i = 0; i < wadfiles[wadnum]->numlumps; i++, lump_p++) + if (memcmp(lump_p->name, "SHADERS", 7) == 0) + return i; + + return INT16_MAX; +} + +customshaderxlat_t shaderxlat[] = +{ + {"Flat", SHADER_FLOOR}, + {"WallTexture", SHADER_WALL}, + {"Sprite", SHADER_SPRITE}, + {"Model", SHADER_MODEL}, + {"WaterRipple", SHADER_WATER}, + {"Fog", SHADER_FOG}, + {"Sky", SHADER_SKY}, + {"PalettePostprocess", SHADER_PALETTE_POSTPROCESS}, + {"UIColormapFade", SHADER_UI_COLORMAP_FADE}, + {"UITintedWipe", SHADER_UI_TINTED_WIPE}, + {NULL, 0}, +}; + +void HWR_LoadAllCustomShaders(void) +{ + INT32 i; + + // read every custom shader + for (i = 0; i < numwadfiles; i++) + HWR_LoadCustomShadersFromFile(i, W_FileHasFolders(wadfiles[i])); +} + +static const char version_directives[][14] = { + "#version 330\n", + "#version 150\n", + "#version 140\n", + "#version 130\n", + "#version 120\n", + "#version 110\n", +}; + +static boolean HWR_VersionDirectiveExists(const char* source) +{ + return strncmp(source, "#version", 8) == 0; +} + +static char* HWR_PrependVersionDirective(const char* source, UINT32 version_index) +{ + const UINT32 version_len = sizeof(version_directives[version_index]) - 1; + const UINT32 source_len = strlen(source); + + char* result = Z_Malloc(source_len + version_len + 1, PU_STATIC, NULL); + strcpy(result, version_directives[version_index]); + strcpy(result + version_len, source); + + return result; +} + +static void HWR_ReplaceVersionInplace(char* shader, UINT32 version_index) +{ + shader[9] = version_directives[version_index][9]; + shader[10] = version_directives[version_index][10]; + shader[11] = version_directives[version_index][11]; +} + +static boolean HWR_CheckVersionDirectives(const char* vert, const char* frag) +{ + return HWR_VersionDirectiveExists(vert) && HWR_VersionDirectiveExists(frag); +} + +static void HWR_TryToCompileShaderWithImplicitVersion(INT32 shader_index, INT32 shaderxlat_id) +{ + char* vert_shader = gl_shaders[shader_index].vertex; + char* frag_shader = gl_shaders[shader_index].fragment; + + boolean vert_shader_version_exists = HWR_VersionDirectiveExists(vert_shader); + boolean frag_shader_version_exists = HWR_VersionDirectiveExists(frag_shader); + + if(!vert_shader_version_exists) { + CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: vertex shader '%s' is missing a #version directive\n", HWR_GetShaderName(shaderxlat_id)); + } + + if(!frag_shader_version_exists) { + CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: fragment shader '%s' is missing a #version directive\n", HWR_GetShaderName(shaderxlat_id)); + } + + // try to compile as is + HWR_CompileShader(shader_index); + if (gl_shaders[shader_index].compiled) + return; + + // try each version directive + for(UINT32 i = 0; i < sizeof(version_directives) / sizeof(version_directives[0]); ++i) { + CONS_Alert(CONS_NOTICE, "HWR_TryToCompileShaderWithImplicitVersion: Trying %s\n", version_directives[i]); + + if(!vert_shader_version_exists) { + // first time reallocation would have to be made + + if(i == 0) { + void* old = (void*)gl_shaders[shader_index].vertex; + vert_shader = gl_shaders[shader_index].vertex = HWR_PrependVersionDirective(vert_shader, i); + Z_Free(old); + } else { + HWR_ReplaceVersionInplace(vert_shader, i); + } + } + + if(!frag_shader_version_exists) { + if(i == 0) { + void* old = (void*)gl_shaders[shader_index].fragment; + frag_shader = gl_shaders[shader_index].fragment = HWR_PrependVersionDirective(frag_shader, i); + Z_Free(old); + } else { + HWR_ReplaceVersionInplace(frag_shader, i); + } + } + + HWR_CompileShader(shader_index); + if (gl_shaders[shader_index].compiled) { + CONS_Alert(CONS_NOTICE, "HWR_TryToCompileShaderWithImplicitVersion: Compiled with %s\n", + version_directives[i]); + CONS_Alert(CONS_WARNING, "Implicit GLSL version is used. Correct behavior is not guaranteed\n"); + return; + } + } +} + +void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3) +{ + UINT16 lump; + char *shaderdef, *line; + char *stoken; + char *value; + size_t size; + int linenum = 1; + int shadertype = 0; + int i; + boolean modified_shaders[NUMSHADERTARGETS] = {0}; + + if (!gl_shadersavailable) + return; + + lump = HWR_FindShaderDefs(wadnum); + if (lump == INT16_MAX) + return; + + shaderdef = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE); + size = W_LumpLengthPwad(wadnum, lump); + + line = Z_Malloc(size+1, PU_STATIC, NULL); + M_Memcpy(line, shaderdef, size); + line[size] = '\0'; + + stoken = strtok(line, "\r\n "); + while (stoken) + { + if ((stoken[0] == '/' && stoken[1] == '/') + || (stoken[0] == '#'))// skip comments + { + stoken = strtok(NULL, "\r\n"); + goto skip_field; + } + + if (!stricmp(stoken, "GLSL")) + { + value = strtok(NULL, "\r\n "); + if (!value) + { + CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); + stoken = strtok(NULL, "\r\n"); // skip end of line + goto skip_lump; + } + + if (!stricmp(value, "VERTEX")) + shadertype = 1; + else if (!stricmp(value, "FRAGMENT")) + shadertype = 2; + +skip_lump: + stoken = strtok(NULL, "\r\n "); + linenum++; + } + else + { + value = strtok(NULL, "\r\n= "); + if (!value) + { + CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: Missing shader target (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); + stoken = strtok(NULL, "\r\n"); // skip end of line + goto skip_field; + } + + if (!shadertype) + { + CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); + Z_Free(line); + return; + } + + for (i = 0; shaderxlat[i].type; i++) + { + if (!stricmp(shaderxlat[i].type, stoken)) + { + size_t shader_string_length; + char *shader_source; + char *shader_lumpname; + UINT16 shader_lumpnum; + int shader_index; // index in gl_shaders + + if (PK3) + { + shader_lumpname = Z_Malloc(strlen(value) + 12, PU_STATIC, NULL); + strcpy(shader_lumpname, "Shaders/sh_"); + strcat(shader_lumpname, value); + shader_lumpnum = W_CheckNumForFullNamePK3(shader_lumpname, wadnum, 0); + } + else + { + shader_lumpname = Z_Malloc(strlen(value) + 4, PU_STATIC, NULL); + strcpy(shader_lumpname, "SH_"); + strcat(shader_lumpname, value); + shader_lumpnum = W_CheckNumForNamePwad(shader_lumpname, wadnum, 0); + } + + if (shader_lumpnum == INT16_MAX) + { + CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: Missing shader source %s (file %s, line %d)\n", shader_lumpname, wadfiles[wadnum]->filename, linenum); + Z_Free(shader_lumpname); + continue; + } + + shader_string_length = W_LumpLengthPwad(wadnum, shader_lumpnum) + 1; + shader_source = Z_Malloc(shader_string_length, PU_STATIC, NULL); + W_ReadLumpPwad(wadnum, shader_lumpnum, shader_source); + shader_source[shader_string_length-1] = '\0'; + + shader_index = shaderxlat[i].id + NUMSHADERTARGETS; + if (!modified_shaders[shaderxlat[i].id]) + { + // this will clear any old custom shaders from previously loaded files + // Z_Free checks if the pointer is NULL! + Z_Free(gl_shaders[shader_index].vertex); + gl_shaders[shader_index].vertex = NULL; + Z_Free(gl_shaders[shader_index].fragment); + gl_shaders[shader_index].fragment = NULL; + } + modified_shaders[shaderxlat[i].id] = true; + + if (shadertype == 1) + { + if (gl_shaders[shader_index].vertex) + { + CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: %s is overwriting another %s vertex shader from the same addon! (file %s, line %d)\n", shader_lumpname, shaderxlat[i].type, wadfiles[wadnum]->filename, linenum); + Z_Free(gl_shaders[shader_index].vertex); + } + gl_shaders[shader_index].vertex = shader_source; + } + else + { + if (gl_shaders[shader_index].fragment) + { + CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: %s is overwriting another %s fragment shader from the same addon! (file %s, line %d)\n", shader_lumpname, shaderxlat[i].type, wadfiles[wadnum]->filename, linenum); + Z_Free(gl_shaders[shader_index].fragment); + } + gl_shaders[shader_index].fragment = shader_source; + } + + Z_Free(shader_lumpname); + } + } + +skip_field: + stoken = strtok(NULL, "\r\n= "); + linenum++; + } + } + + for (i = 0; i < NUMSHADERTARGETS; i++) + { + if (modified_shaders[i]) + { + int shader_index = i + NUMSHADERTARGETS; // index to gl_shaders + gl_shadertargets[i].custom_shader = shader_index; + // if only one stage (vertex/fragment) is defined, the other one + // is copied from the base shaders. + if (!gl_shaders[shader_index].fragment) + gl_shaders[shader_index].fragment = Z_StrDup(gl_shadersources[i].fragment); + if (!gl_shaders[shader_index].vertex) + gl_shaders[shader_index].vertex = Z_StrDup(gl_shadersources[i].vertex); + + if(!HWR_CheckVersionDirectives(gl_shaders[shader_index].vertex, gl_shaders[shader_index].fragment)) { + HWR_TryToCompileShaderWithImplicitVersion(shader_index, i); + } else { + HWR_CompileShader(shader_index); + } + + if (!gl_shaders[shader_index].compiled) + CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: A compilation error occured for the %s shader in file %s. See the console messages above for more information.\n", shaderxlat[i].type, wadfiles[wadnum]->filename); + } + } + + Z_Free(line); + return; +} + +const char *HWR_GetShaderName(INT32 shader) +{ + INT32 i; + + for (i = 0; shaderxlat[i].type; i++) + { + if (shaderxlat[i].id == shader) + return shaderxlat[i].type; + } + + return "Unknown"; +} + +#endif // HWRENDER diff --git a/src/hardware/hw_shaders.h b/src/hardware/hw_shaders.h new file mode 100644 index 0000000000000000000000000000000000000000..38a2d991191dc7531fb2e72e70b3b5946e98b245 --- /dev/null +++ b/src/hardware/hw_shaders.h @@ -0,0 +1,424 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2021-2024 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 hw_shaders.h +/// \brief Handles the shaders used by the game. + +#ifndef _HW_SHADERS_H_ +#define _HW_SHADERS_H_ + +#include "../doomtype.h" + +// ================ +// Vertex shaders +// ================ + +// +// Generic vertex shader +// + +#define GLSL_DEFAULT_VERTEX_SHADER \ + "void main()\n" \ + "{\n" \ + "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ + "gl_FrontColor = gl_Color;\n" \ + "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ + "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ + "}\0" + +// replicates the way fixed function lighting is used by the model lighting option, +// stores the lighting result to gl_Color +// (ambient lighting of 0.75 and diffuse lighting from above) +#define GLSL_MODEL_VERTEX_SHADER \ + "void main()\n" \ + "{\n" \ + "#ifdef SRB2_MODEL_LIGHTING\n" \ + "float nDotVP = dot(gl_Normal, vec3(0, 1, 0));\n" \ + "float light = min(0.75 + max(nDotVP, 0.0), 1.0);\n" \ + "gl_FrontColor = vec4(light, light, light, 1.0);\n" \ + "#else\n" \ + "gl_FrontColor = gl_Color;\n" \ + "#endif\n" \ + "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ + "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ + "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ + "}\0" + +// ================== +// Fragment shaders +// ================== + +// +// Generic fragment shader +// + +#define GLSL_DEFAULT_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "void main(void) {\n" \ + "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \ + "}\0" + +// +// Software fragment shader +// + +// Include GLSL_FLOOR_FUDGES or GLSL_WALL_FUDGES or define the fudges in shaders that use this macro. +#define GLSL_DOOM_COLORMAP \ + "float R_DoomColormap(float light, float z)\n" \ + "{\n" \ + "float lightnum = clamp(light / 17.0, 0.0, 15.0);\n" \ + "float lightz = clamp(z / 16.0, 0.0, 127.0);\n" \ + "float startmap = (15.0 - lightnum) * 4.0;\n" \ + "float scale = 160.0 / (lightz + 1.0);\n" \ + "float cap = (155.0 - light) * 0.26;\n" \ + "return max(startmap * STARTMAP_FUDGE - scale * 0.5 * SCALE_FUDGE, cap);\n" \ + "}\n" +// lighting cap adjustment: +// first num (155.0), increase to make it start to go dark sooner +// second num (0.26), increase to make it go dark faster + +#define GLSL_DOOM_LIGHT_EQUATION \ + "float R_DoomLightingEquation(float light)\n" \ + "{\n" \ + "float z = gl_FragCoord.z / gl_FragCoord.w;\n" \ + "float colormap = floor(R_DoomColormap(light, z)) + 0.5;\n" \ + "return clamp(colormap, 0.0, 31.0) / 32.0;\n" \ + "}\n" + +#define GLSL_SOFTWARE_TINT_EQUATION \ + "if (tint_color.a > 0.0) {\n" \ + "float color_bright = sqrt((base_color.r * base_color.r) + (base_color.g * base_color.g) + (base_color.b * base_color.b));\n" \ + "float strength = sqrt(tint_color.a);\n" \ + "final_color.r = clamp((color_bright * (tint_color.r * strength)) + (base_color.r * (1.0 - strength)), 0.0, 1.0);\n" \ + "final_color.g = clamp((color_bright * (tint_color.g * strength)) + (base_color.g * (1.0 - strength)), 0.0, 1.0);\n" \ + "final_color.b = clamp((color_bright * (tint_color.b * strength)) + (base_color.b * (1.0 - strength)), 0.0, 1.0);\n" \ + "}\n" + +#define GLSL_SOFTWARE_FADE_EQUATION \ + "float darkness = R_DoomLightingEquation(lighting);\n" \ + "if (fade_start != 0.0 || fade_end != 31.0) {\n" \ + "float fs = fade_start / 31.0;\n" \ + "float fe = fade_end / 31.0;\n" \ + "float fd = fe - fs;\n" \ + "darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \ + "}\n" \ + "final_color = mix(final_color, fade_color, darkness);\n" + +#define GLSL_PALETTE_RENDERING \ + "float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \ + "float z = gl_FragCoord.z / gl_FragCoord.w;\n" \ + "float light_y = clamp(floor(R_DoomColormap(lighting, z)), 0.0, 31.0);\n" \ + "vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (light_y + 0.5) / 32.0);\n" \ + "vec4 final_color = texture2D(lighttable_tex, lighttable_coord);\n" \ + "final_color.a = texel.a * poly_color.a;\n" \ + "gl_FragColor = final_color;\n" \ + +#define GLSL_SOFTWARE_FRAGMENT_SHADER \ + "#ifdef SRB2_PALETTE_RENDERING\n" \ + "uniform sampler2D tex;\n" \ + "uniform sampler3D palette_lookup_tex;\n" \ + "uniform sampler2D lighttable_tex;\n" \ + "uniform vec4 poly_color;\n" \ + "uniform float lighting;\n" \ + GLSL_DOOM_COLORMAP \ + "void main(void) {\n" \ + "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + GLSL_PALETTE_RENDERING \ + "}\n" \ + "#else\n" \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "uniform vec4 tint_color;\n" \ + "uniform vec4 fade_color;\n" \ + "uniform float lighting;\n" \ + "uniform float fade_start;\n" \ + "uniform float fade_end;\n" \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + "vec4 base_color = texel * poly_color;\n" \ + "vec4 final_color = base_color;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "final_color.a = texel.a * poly_color.a;\n" \ + "gl_FragColor = final_color;\n" \ + "}\n" \ + "#endif\0" + +// hand tuned adjustments for light level calculation +#define GLSL_FLOOR_FUDGES \ + "#define STARTMAP_FUDGE 1.06\n" \ + "#define SCALE_FUDGE 1.15\n" + +#define GLSL_WALL_FUDGES \ + "#define STARTMAP_FUDGE 1.05\n" \ + "#define SCALE_FUDGE 2.2\n" + +#define GLSL_FLOOR_FRAGMENT_SHADER \ + GLSL_FLOOR_FUDGES \ + GLSL_SOFTWARE_FRAGMENT_SHADER + +#define GLSL_WALL_FRAGMENT_SHADER \ + GLSL_WALL_FUDGES \ + GLSL_SOFTWARE_FRAGMENT_SHADER + +// same as above but multiplies results with the lighting value from the +// accompanying vertex shader (stored in gl_Color) if model lighting is enabled +#define GLSL_MODEL_FRAGMENT_SHADER \ + GLSL_WALL_FUDGES \ + "#ifdef SRB2_PALETTE_RENDERING\n" \ + "uniform sampler2D tex;\n" \ + "uniform sampler3D palette_lookup_tex;\n" \ + "uniform sampler2D lighttable_tex;\n" \ + "uniform vec4 poly_color;\n" \ + "uniform float lighting;\n" \ + GLSL_DOOM_COLORMAP \ + "void main(void) {\n" \ + "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + "#ifdef SRB2_MODEL_LIGHTING\n" \ + "texel *= gl_Color;\n" \ + "#endif\n" \ + GLSL_PALETTE_RENDERING \ + "}\n" \ + "#else\n" \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "uniform vec4 tint_color;\n" \ + "uniform vec4 fade_color;\n" \ + "uniform float lighting;\n" \ + "uniform float fade_start;\n" \ + "uniform float fade_end;\n" \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + "vec4 base_color = texel * poly_color;\n" \ + "vec4 final_color = base_color;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "#ifdef SRB2_MODEL_LIGHTING\n" \ + "final_color *= gl_Color;\n" \ + "#endif\n" \ + "final_color.a = texel.a * poly_color.a;\n" \ + "gl_FragColor = final_color;\n" \ + "}\n" \ + "#endif\0" + +// +// Water surface shader +// +// Mostly guesstimated, rather than the rest being built off Software science. +// Still needs to distort things underneath/around the water... +// + +#define GLSL_WATER_TEXEL \ + "float water_z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \ + "float a = -pi * (water_z * freq) + (leveltime * speed);\n" \ + "float sdistort = sin(a) * amp;\n" \ + "float cdistort = cos(a) * amp;\n" \ + "vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n" + +#define GLSL_WATER_FRAGMENT_SHADER \ + GLSL_FLOOR_FUDGES \ + "const float freq = 0.025;\n" \ + "const float amp = 0.025;\n" \ + "const float speed = 2.0;\n" \ + "const float pi = 3.14159;\n" \ + "#ifdef SRB2_PALETTE_RENDERING\n" \ + "uniform sampler2D tex;\n" \ + "uniform sampler3D palette_lookup_tex;\n" \ + "uniform sampler2D lighttable_tex;\n" \ + "uniform vec4 poly_color;\n" \ + "uniform float lighting;\n" \ + "uniform float leveltime;\n" \ + GLSL_DOOM_COLORMAP \ + "void main(void) {\n" \ + GLSL_WATER_TEXEL \ + GLSL_PALETTE_RENDERING \ + "}\n" \ + "#else\n" \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "uniform vec4 tint_color;\n" \ + "uniform vec4 fade_color;\n" \ + "uniform float lighting;\n" \ + "uniform float fade_start;\n" \ + "uniform float fade_end;\n" \ + "uniform float leveltime;\n" \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + GLSL_WATER_TEXEL \ + "vec4 base_color = texel * poly_color;\n" \ + "vec4 final_color = base_color;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "final_color.a = texel.a * poly_color.a;\n" \ + "gl_FragColor = final_color;\n" \ + "}\n" \ + "#endif\0" + +// +// Fog block shader +// +// Alpha of the planes themselves are still slightly off -- see HWR_FogBlockAlpha +// + +// The floor fudges are used, but should the wall fudges be used instead? or something inbetween? +// or separate values for floors and walls? (need to change more than this shader for that) +#define GLSL_FOG_FRAGMENT_SHADER \ + GLSL_FLOOR_FUDGES \ + "uniform vec4 tint_color;\n" \ + "uniform vec4 fade_color;\n" \ + "uniform float lighting;\n" \ + "uniform float fade_start;\n" \ + "uniform float fade_end;\n" \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + "vec4 base_color = gl_Color;\n" \ + "vec4 final_color = base_color;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "gl_FragColor = final_color;\n" \ + "}\0" + +// +// Sky fragment shader +// Modulates poly_color with gl_Color +// +#define GLSL_SKY_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "void main(void) {\n" \ + "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \ + "}\0" + +// Shader for the palette rendering postprocess step +#define GLSL_PALETTE_POSTPROCESS_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform sampler3D palette_lookup_tex;\n" \ + "uniform sampler1D palette_tex;\n" \ + "void main(void) {\n" \ + "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + "float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \ + "float palette_coord = (tex_pal_idx + 0.5) / 256.0;\n" \ + "vec4 final_color = texture1D(palette_tex, palette_coord);\n" \ + "gl_FragColor = final_color;\n" \ + "}\0" + +// Applies a palettized colormap fade to tex +#define GLSL_UI_COLORMAP_FADE_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform float lighting;\n" \ + "uniform sampler3D palette_lookup_tex;\n" \ + "uniform sampler2D lighttable_tex;\n" \ + "void main(void) {\n" \ + "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + "float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \ + "vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (lighting + 0.5) / 32.0);\n" \ + "gl_FragColor = texture2D(lighttable_tex, lighttable_coord);\n" \ + "}\0" + +// For wipes that use additive and subtractive blending. +// alpha_factor = 31 * 8 / 10 = 24.8 +// Calculated based on the use of the "fade" variable from the GETCOLOR macro +// in r_data.c:R_CreateFadeColormaps. +// However this value created some ugliness in fades to white (special stage entry) +// while palette rendering is enabled, so I raised the value just a bit. +#define GLSL_UI_TINTED_WIPE_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "const float alpha_factor = 24.875;\n" \ + "void main(void) {\n" \ + "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + "vec4 final_color = poly_color;\n" \ + "float alpha = texel.a;\n" \ + "if (final_color.a >= 0.5)\n" \ + "alpha = 1.0 - alpha;\n" \ + "alpha *= alpha_factor;\n" \ + "final_color *= alpha;\n" \ + "final_color.a = 1.0;\n" \ + "gl_FragColor = final_color;\n" \ + "}\0" + +// +// Generic vertex shader +// + +#define GLSL_FALLBACK_VERTEX_SHADER \ + "void main()\n" \ + "{\n" \ + "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ + "gl_FrontColor = gl_Color;\n" \ + "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ + "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ + "}\0" + +// +// Generic fragment shader +// + +#define GLSL_FALLBACK_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "void main(void) {\n" \ + "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \ + "}\0" + +// +// Software fragment shader +// + +#define GLSL_SOFTWARE_FADE_EQUATION \ + "float darkness = R_DoomLightingEquation(lighting);\n" \ + "if (fade_start != 0.0 || fade_end != 31.0) {\n" \ + "float fs = fade_start / 31.0;\n" \ + "float fe = fade_end / 31.0;\n" \ + "float fd = fe - fs;\n" \ + "darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \ + "}\n" \ + "final_color = mix(final_color, fade_color, darkness);\n" + +// same as above but multiplies results with the lighting value from the +// accompanying vertex shader (stored in gl_Color) +#define GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "uniform vec4 tint_color;\n" \ + "uniform vec4 fade_color;\n" \ + "uniform float lighting;\n" \ + "uniform float fade_start;\n" \ + "uniform float fade_end;\n" \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + "vec4 base_color = texel * poly_color;\n" \ + "vec4 final_color = base_color;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "final_color *= gl_Color;\n" \ + "final_color.a = texel.a * poly_color.a;\n" \ + "gl_FragColor = final_color;\n" \ + "}\0" + +// +// Sky fragment shader +// Modulates poly_color with gl_Color +// +#define GLSL_SKY_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "void main(void) {\n" \ + "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \ + "}\0" + +#endif diff --git a/src/hardware/r_opengl/ogl_win.c b/src/hardware/r_opengl/ogl_win.c index c9bf601442a5531b35d0ac629730aa83978d17a6..ec8fc9bdb8b77f99f03b97af7df9cbdedea864f4 100644 --- a/src/hardware/r_opengl/ogl_win.c +++ b/src/hardware/r_opengl/ogl_win.c @@ -117,7 +117,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, // handle to DLL module #define pwglDeleteContext wglDeleteContext; #define pwglMakeCurrent wglMakeCurrent; #else -static HMODULE OGL32, GLU32; +static HMODULE OGL32; typedef void *(WINAPI *PFNwglGetProcAddress) (const char *); static PFNwglGetProcAddress pwglGetProcAddress; typedef HGLRC (WINAPI *PFNwglCreateContext) (HDC hdc); @@ -132,13 +132,6 @@ static PFNwglMakeCurrent pwglMakeCurrent; void *GetGLFunc(const char *proc) { void *func = NULL; - if (strncmp(proc, "glu", 3) == 0) - { - if (GLU32) - func = GetProcAddress(GLU32, proc); - else - return NULL; - } if (pwglGetProcAddress) func = pwglGetProcAddress(proc); if (!func) @@ -155,8 +148,6 @@ boolean LoadGL(void) if (!OGL32) return 0; - GLU32 = LoadLibrary("GLU32.DLL"); - pwglGetProcAddress = GetGLFunc("wglGetProcAddress"); pwglCreateContext = GetGLFunc("wglCreateContext"); pwglDeleteContext = GetGLFunc("wglDeleteContext"); @@ -528,7 +519,6 @@ EXPORT void HWRAPI(Shutdown) (void) ReleaseDC(hWnd, hDC); hDC = NULL; } - FreeLibrary(GLU32); FreeLibrary(OGL32); GL_DBG_Printf ("HWRAPI Shutdown(DONE)\n"); } diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index ea831e41dee3b7afff7eed47d4ead3f858870648..02a32957a2b940ac15490c0e83fb57658da24c5e 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -24,6 +24,7 @@ #include "../../r_local.h" // For rendertimefrac, used for the leveltime shader uniform #include "r_opengl.h" #include "r_vbo.h" +#include "../hw_shaders.h" #if defined (HWRENDER) && !defined (NOROPENGL) @@ -35,12 +36,21 @@ struct GLRGBAFloat GLfloat alpha; }; typedef struct GLRGBAFloat GLRGBAFloat; -static const GLubyte white[4] = { 255, 255, 255, 255 }; + +// lighttable list item +struct LTListItem +{ + UINT32 id; + struct LTListItem *next; +}; +typedef struct LTListItem LTListItem; // ========================================================================== // CONSTANTS // ========================================================================== +static const GLubyte white[4] = { 255, 255, 255, 255 }; + // With OpenGL 1.1+, the first texture should be 1 static GLuint NOTEXTURE_NUM = 0; @@ -56,6 +66,7 @@ static float NEAR_CLIPPING_PLANE = NZCLIP_PLANE; static GLuint tex_downloaded = 0; +static GLuint lt_downloaded = 0; // currently bound lighttable texture static GLfloat fov = 90.0f; static FBITFIELD CurrentPolyFlags; @@ -66,7 +77,15 @@ static FTextureInfo *TexCacheHead = NULL; static RGBA_t *textureBuffer = NULL; static size_t textureBufferSize = 0; -RGBA_t myPaletteData[256]; +// Linked list of all lighttables. +static LTListItem *LightTablesTail = NULL; +static LTListItem *LightTablesHead = NULL; + +static RGBA_t screenPalette[256] = {0}; // the palette for the postprocessing step in palette rendering +static GLuint screenPaletteTex = 0; // 1D texture containing the screen palette +static GLuint paletteLookupTex = 0; // 3D texture containing RGB -> palette index lookup table +RGBA_t myPaletteData[256]; // the palette for converting textures to RGBA + GLint screen_width = 0; // used by Draw2DLine() GLint screen_height = 0; GLbyte screen_depth = 0; @@ -77,6 +96,7 @@ static GLint min_filter = GL_LINEAR; static GLint mag_filter = GL_LINEAR; static GLint anisotropic_filter = 0; static boolean model_lighting = false; +boolean supportMipMap = false; const GLubyte *gl_version = NULL; const GLubyte *gl_renderer = NULL; @@ -91,10 +111,7 @@ static GLint viewport[4]; // flush all of the stored textures, leaving them unavailable at times such as between levels // These need to start at 0 and be set to their number, and be reset to 0 when deleted so that intel GPUs // can know when the textures aren't there, as textures are always considered resident in their virtual memory -static GLuint screentexture = 0; -static GLuint startScreenWipe = 0; -static GLuint endScreenWipe = 0; -static GLuint finalScreenTexture = 0; +static GLuint screenTextures[NUMSCREENTEXTURES] = {0}; // shortcut for ((float)1/i) static const GLfloat byte2float[256] = { @@ -164,7 +181,7 @@ FUNCPRINTF void GL_DBG_Printf(const char *format, ...) // GL_MSG_Warning : Raises a warning. // -----------------+ -static void GL_MSG_Warning(const char *format, ...) +FUNCPRINTF static void GL_MSG_Warning(const char *format, ...) { char str[4096] = ""; va_list arglist; @@ -187,7 +204,7 @@ static void GL_MSG_Warning(const char *format, ...) // GL_MSG_Error : Raises an error. // -----------------+ -static void GL_MSG_Error(const char *format, ...) +FUNCPRINTF static void GL_MSG_Error(const char *format, ...) { char str[4096] = ""; va_list arglist; @@ -378,10 +395,14 @@ typedef void (APIENTRY * PFNglTexEnvi) (GLenum target, GLenum pname, GLint param static PFNglTexEnvi pglTexEnvi; typedef void (APIENTRY * PFNglTexParameteri) (GLenum target, GLenum pname, GLint param); static PFNglTexParameteri pglTexParameteri; +typedef void (APIENTRY * PFNglTexImage1D) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +static PFNglTexImage1D pglTexImage1D; typedef void (APIENTRY * PFNglTexImage2D) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); static PFNglTexImage2D pglTexImage2D; typedef void (APIENTRY * PFNglTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); static PFNglTexSubImage2D pglTexSubImage2D; +typedef void (APIENTRY * PFNglGetTexImage) (GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); +static PFNglGetTexImage pglGetTexImage; /* 1.1 functions */ /* texture objects */ //GL_EXT_texture_object @@ -397,9 +418,10 @@ static PFNglCopyTexImage2D pglCopyTexImage2D; typedef void (APIENTRY * PFNglCopyTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); static PFNglCopyTexSubImage2D pglCopyTexSubImage2D; #endif -/* GLU functions */ -typedef GLint (APIENTRY * PFNgluBuild2DMipmaps) (GLenum target, GLint internalFormat, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *data); -static PFNgluBuild2DMipmaps pgluBuild2DMipmaps; + +/* 1.2 functions for 3D textures */ +typedef void (APIENTRY * PFNglTexImage3D) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +static PFNglTexImage3D pglTexImage3D; /* 1.3 functions for multitexturing */ typedef void (APIENTRY *PFNglActiveTexture) (GLenum); @@ -445,6 +467,9 @@ static PFNglBlendEquation pglBlendEquation; #ifndef GL_TEXTURE1 #define GL_TEXTURE1 0x84C1 #endif +#ifndef GL_TEXTURE2 +#define GL_TEXTURE2 0x84C2 +#endif /* 1.5 Parms */ #ifndef GL_ARRAY_BUFFER @@ -517,8 +542,10 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglTexEnvi, glTexEnvi) GETOPENGLFUNC(pglTexParameteri, glTexParameteri) + GETOPENGLFUNC(pglTexImage1D, glTexImage1D) GETOPENGLFUNC(pglTexImage2D, glTexImage2D) GETOPENGLFUNC(pglTexSubImage2D, glTexSubImage2D) + GETOPENGLFUNC(pglGetTexImage, glGetTexImage) GETOPENGLFUNC(pglGenTextures, glGenTextures) GETOPENGLFUNC(pglDeleteTextures, glDeleteTextures) @@ -534,7 +561,7 @@ boolean SetupGLfunc(void) } static boolean gl_shadersenabled = false; -static hwdshaderoption_t gl_allowshaders = HWD_SHADEROPTION_OFF; +static INT32 gl_allowshaders = 0; #ifdef GL_SHADERS typedef GLuint (APIENTRY *PFNglCreateShader) (GLenum); @@ -592,7 +619,12 @@ typedef enum gluniform_fade_start, gluniform_fade_end, - // misc. (custom shaders) + // palette rendering + gluniform_palette_tex, // 1d texture containing a palette + gluniform_palette_lookup_tex, // 3d texture containing the rgb->index lookup table + gluniform_lighttable_tex, // 2d texture containing a light table + + // misc. gluniform_leveltime, gluniform_max, @@ -600,14 +632,15 @@ typedef enum typedef struct gl_shader_s { + char *vertex_shader; + char *fragment_shader; GLuint program; GLint uniforms[gluniform_max+1]; - boolean custom; } gl_shader_t; static gl_shader_t gl_shaders[HWR_MAXSHADERS]; -static gl_shader_t gl_usershaders[HWR_MAXSHADERS]; -static shadersource_t gl_customshaders[HWR_MAXSHADERS]; + +static gl_shader_t gl_fallback_shader; // 09102020 typedef struct gl_shaderstate_s @@ -623,253 +656,19 @@ static gl_shaderstate_t gl_shaderstate; static float shader_leveltime = 0; // Lactozilla: Shader functions -static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i, const GLchar *vert_shader, const GLchar *frag_shader); +static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i); static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum); static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade); static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; -// ================ -// Vertex shaders -// ================ - -// -// Generic vertex shader -// - -#define GLSL_DEFAULT_VERTEX_SHADER \ - "void main()\n" \ - "{\n" \ - "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ - "gl_FrontColor = gl_Color;\n" \ - "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ - "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ - "}\0" - -// replicates the way fixed function lighting is used by the model lighting option, -// stores the lighting result to gl_Color -// (ambient lighting of 0.75 and diffuse lighting from above) -#define GLSL_MODEL_LIGHTING_VERTEX_SHADER \ - "void main()\n" \ - "{\n" \ - "float nDotVP = dot(gl_Normal, vec3(0, 1, 0));\n" \ - "float light = 0.75 + max(nDotVP, 0.0);\n" \ - "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ - "gl_FrontColor = vec4(light, light, light, 1.0);\n" \ - "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ - "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ - "}\0" - -// ================== -// Fragment shaders -// ================== - -// -// Generic fragment shader -// - -#define GLSL_DEFAULT_FRAGMENT_SHADER \ - "uniform sampler2D tex;\n" \ - "uniform vec4 poly_color;\n" \ - "void main(void) {\n" \ - "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \ - "}\0" - -// -// Software fragment shader -// - -#define GLSL_DOOM_COLORMAP \ - "float R_DoomColormap(float light, float z)\n" \ - "{\n" \ - "float lightnum = clamp(light / 17.0, 0.0, 15.0);\n" \ - "float lightz = clamp(z / 16.0, 0.0, 127.0);\n" \ - "float startmap = (15.0 - lightnum) * 4.0;\n" \ - "float scale = 160.0 / (lightz + 1.0);\n" \ - "return startmap - scale * 0.5;\n" \ - "}\n" - -#define GLSL_DOOM_LIGHT_EQUATION \ - "float R_DoomLightingEquation(float light)\n" \ - "{\n" \ - "float z = gl_FragCoord.z / gl_FragCoord.w;\n" \ - "float colormap = floor(R_DoomColormap(light, z)) + 0.5;\n" \ - "return clamp(colormap, 0.0, 31.0) / 32.0;\n" \ - "}\n" - -#define GLSL_SOFTWARE_TINT_EQUATION \ - "if (tint_color.a > 0.0) {\n" \ - "float color_bright = sqrt((base_color.r * base_color.r) + (base_color.g * base_color.g) + (base_color.b * base_color.b));\n" \ - "float strength = sqrt(tint_color.a);\n" \ - "final_color.r = clamp((color_bright * (tint_color.r * strength)) + (base_color.r * (1.0 - strength)), 0.0, 1.0);\n" \ - "final_color.g = clamp((color_bright * (tint_color.g * strength)) + (base_color.g * (1.0 - strength)), 0.0, 1.0);\n" \ - "final_color.b = clamp((color_bright * (tint_color.b * strength)) + (base_color.b * (1.0 - strength)), 0.0, 1.0);\n" \ - "}\n" - -#define GLSL_SOFTWARE_FADE_EQUATION \ - "float darkness = R_DoomLightingEquation(lighting);\n" \ - "if (fade_start != 0.0 || fade_end != 31.0) {\n" \ - "float fs = fade_start / 31.0;\n" \ - "float fe = fade_end / 31.0;\n" \ - "float fd = fe - fs;\n" \ - "darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \ - "}\n" \ - "final_color = mix(final_color, fade_color, darkness);\n" - -#define GLSL_SOFTWARE_FRAGMENT_SHADER \ - "uniform sampler2D tex;\n" \ - "uniform vec4 poly_color;\n" \ - "uniform vec4 tint_color;\n" \ - "uniform vec4 fade_color;\n" \ - "uniform float lighting;\n" \ - "uniform float fade_start;\n" \ - "uniform float fade_end;\n" \ - GLSL_DOOM_COLORMAP \ - GLSL_DOOM_LIGHT_EQUATION \ - "void main(void) {\n" \ - "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ - "vec4 base_color = texel * poly_color;\n" \ - "vec4 final_color = base_color;\n" \ - GLSL_SOFTWARE_TINT_EQUATION \ - GLSL_SOFTWARE_FADE_EQUATION \ - "final_color.a = texel.a * poly_color.a;\n" \ - "gl_FragColor = final_color;\n" \ - "}\0" - -// same as above but multiplies results with the lighting value from the -// accompanying vertex shader (stored in gl_Color) -#define GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER \ - "uniform sampler2D tex;\n" \ - "uniform vec4 poly_color;\n" \ - "uniform vec4 tint_color;\n" \ - "uniform vec4 fade_color;\n" \ - "uniform float lighting;\n" \ - "uniform float fade_start;\n" \ - "uniform float fade_end;\n" \ - GLSL_DOOM_COLORMAP \ - GLSL_DOOM_LIGHT_EQUATION \ - "void main(void) {\n" \ - "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ - "vec4 base_color = texel * poly_color;\n" \ - "vec4 final_color = base_color;\n" \ - GLSL_SOFTWARE_TINT_EQUATION \ - GLSL_SOFTWARE_FADE_EQUATION \ - "final_color *= gl_Color;\n" \ - "final_color.a = texel.a * poly_color.a;\n" \ - "gl_FragColor = final_color;\n" \ - "}\0" - -// -// Water surface shader -// -// Mostly guesstimated, rather than the rest being built off Software science. -// Still needs to distort things underneath/around the water... -// - -#define GLSL_WATER_FRAGMENT_SHADER \ - "uniform sampler2D tex;\n" \ - "uniform vec4 poly_color;\n" \ - "uniform vec4 tint_color;\n" \ - "uniform vec4 fade_color;\n" \ - "uniform float lighting;\n" \ - "uniform float fade_start;\n" \ - "uniform float fade_end;\n" \ - "uniform float leveltime;\n" \ - "const float freq = 0.025;\n" \ - "const float amp = 0.025;\n" \ - "const float speed = 2.0;\n" \ - "const float pi = 3.14159;\n" \ - GLSL_DOOM_COLORMAP \ - GLSL_DOOM_LIGHT_EQUATION \ - "void main(void) {\n" \ - "float z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \ - "float a = -pi * (z * freq) + (leveltime * speed);\n" \ - "float sdistort = sin(a) * amp;\n" \ - "float cdistort = cos(a) * amp;\n" \ - "vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n" \ - "vec4 base_color = texel * poly_color;\n" \ - "vec4 final_color = base_color;\n" \ - GLSL_SOFTWARE_TINT_EQUATION \ - GLSL_SOFTWARE_FADE_EQUATION \ - "final_color.a = texel.a * poly_color.a;\n" \ - "gl_FragColor = final_color;\n" \ - "}\0" - -// -// Fog block shader -// -// Alpha of the planes themselves are still slightly off -- see HWR_FogBlockAlpha -// - -#define GLSL_FOG_FRAGMENT_SHADER \ - "uniform vec4 tint_color;\n" \ - "uniform vec4 fade_color;\n" \ - "uniform float lighting;\n" \ - "uniform float fade_start;\n" \ - "uniform float fade_end;\n" \ - GLSL_DOOM_COLORMAP \ - GLSL_DOOM_LIGHT_EQUATION \ - "void main(void) {\n" \ - "vec4 base_color = gl_Color;\n" \ - "vec4 final_color = base_color;\n" \ - GLSL_SOFTWARE_TINT_EQUATION \ - GLSL_SOFTWARE_FADE_EQUATION \ - "gl_FragColor = final_color;\n" \ - "}\0" - -// -// Sky fragment shader -// Modulates poly_color with gl_Color -// -#define GLSL_SKY_FRAGMENT_SHADER \ - "uniform sampler2D tex;\n" \ - "uniform vec4 poly_color;\n" \ - "void main(void) {\n" \ - "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \ - "}\0" - -// ================ -// Shader sources -// ================ - -static struct { - const char *vertex; - const char *fragment; -} const gl_shadersources[] = { - // Default shader - {GLSL_DEFAULT_VERTEX_SHADER, GLSL_DEFAULT_FRAGMENT_SHADER}, - - // Floor shader - {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER}, - - // Wall shader - {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER}, - - // Sprite shader - {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER}, - - // Model shader - {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER}, - - // Model shader + diffuse lighting from above - {GLSL_MODEL_LIGHTING_VERTEX_SHADER, GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER}, - - // Water shader - {GLSL_DEFAULT_VERTEX_SHADER, GLSL_WATER_FRAGMENT_SHADER}, - - // Fog shader - {GLSL_DEFAULT_VERTEX_SHADER, GLSL_FOG_FRAGMENT_SHADER}, - - // Sky shader - {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SKY_FRAGMENT_SHADER}, - - {NULL, NULL}, -}; - #endif // GL_SHADERS void SetupGLFunc4(void) { + /* 1.2 funcs */ + pglTexImage3D = GetGLFunc("glTexImage3D"); + /* 1.3 funcs */ pglActiveTexture = GetGLFunc("glActiveTexture"); pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2f"); pglClientActiveTexture = GetGLFunc("glClientActiveTexture"); @@ -907,64 +706,77 @@ void SetupGLFunc4(void) pglUniform3fv = GetGLFunc("glUniform3fv"); pglGetUniformLocation = GetGLFunc("glGetUniformLocation"); #endif - - // GLU - pgluBuild2DMipmaps = GetGLFunc("gluBuild2DMipmaps"); } -EXPORT boolean HWRAPI(CompileShaders) (void) +EXPORT boolean HWRAPI(InitShaders) (void) { #ifdef GL_SHADERS - GLint i; - if (!pglUseProgram) return false; - gl_customshaders[SHADER_DEFAULT].vertex = NULL; - gl_customshaders[SHADER_DEFAULT].fragment = NULL; + gl_fallback_shader.vertex_shader = Z_StrDup(GLSL_FALLBACK_VERTEX_SHADER); + gl_fallback_shader.fragment_shader = Z_StrDup(GLSL_FALLBACK_FRAGMENT_SHADER); - for (i = 0; gl_shadersources[i].vertex && gl_shadersources[i].fragment; i++) + if (!Shader_CompileProgram(&gl_fallback_shader, -1)) { - gl_shader_t *shader, *usershader; - const GLchar *vert_shader = gl_shadersources[i].vertex; - const GLchar *frag_shader = gl_shadersources[i].fragment; + GL_MSG_Error("Failed to compile the fallback shader program!\n"); + return false; + } - if (i >= HWR_MAXSHADERS) - break; + return true; +#else + return false; +#endif +} - shader = &gl_shaders[i]; - usershader = &gl_usershaders[i]; +EXPORT void HWRAPI(LoadShader) (int slot, char *code, hwdshaderstage_t stage) +{ +#ifdef GL_SHADERS + gl_shader_t *shader; - if (shader->program) - pglDeleteProgram(shader->program); - if (usershader->program) - pglDeleteProgram(usershader->program); + if (slot < 0 || slot >= HWR_MAXSHADERS) + I_Error("LoadShader: Invalid slot %d", slot); - shader->program = 0; - usershader->program = 0; + shader = &gl_shaders[slot]; - if (!Shader_CompileProgram(shader, i, vert_shader, frag_shader)) - shader->program = 0; +#define LOADSHADER(source) { \ + if (shader->source) \ + Z_Free(shader->source); \ + shader->source = code; \ + } - // Compile custom shader - if ((i == SHADER_DEFAULT) || !(gl_customshaders[i].vertex || gl_customshaders[i].fragment)) - continue; + if (stage == HWD_SHADERSTAGE_VERTEX) + LOADSHADER(vertex_shader) + else if (stage == HWD_SHADERSTAGE_FRAGMENT) + LOADSHADER(fragment_shader) + else + I_Error("LoadShader: invalid shader stage"); - // 18032019 - if (gl_customshaders[i].vertex) - vert_shader = gl_customshaders[i].vertex; - if (gl_customshaders[i].fragment) - frag_shader = gl_customshaders[i].fragment; +#undef LOADSHADER +#else + (void)slot; + (void)code; + (void)stage; +#endif +} - if (!Shader_CompileProgram(usershader, i, vert_shader, frag_shader)) - { - GL_MSG_Warning("CompileShaders: Could not compile custom shader program for %s\n", HWR_GetShaderName(i)); - usershader->program = 0; - } - } +EXPORT boolean HWRAPI(CompileShader) (int slot) +{ +#ifdef GL_SHADERS + if (slot < 0 || slot >= HWR_MAXSHADERS) + I_Error("CompileShader: Invalid slot %d", slot); - return true; + if (Shader_CompileProgram(&gl_shaders[slot], slot)) + { + return true; + } + else + { + gl_shaders[slot].program = 0; + return false; + } #else + (void)slot; return false; #endif } @@ -991,90 +803,36 @@ EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value) #endif } -// -// Custom shader loading -// -EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boolean isfragment) -{ -#ifdef GL_SHADERS - shadersource_t *shader; - - if (!pglUseProgram) - return; - - if (number < 1 || number > HWR_MAXSHADERS) - I_Error("LoadCustomShader: cannot load shader %d (min 1, max %d)", number, HWR_MAXSHADERS); - else if (code == NULL) - I_Error("LoadCustomShader: empty shader"); - - shader = &gl_customshaders[number]; - -#define COPYSHADER(source) { \ - if (shader->source) \ - free(shader->source); \ - shader->source = malloc(size+1); \ - strncpy(shader->source, code, size); \ - shader->source[size] = 0; \ - } - - if (isfragment) - COPYSHADER(fragment) - else - COPYSHADER(vertex) - -#else - (void)number; - (void)shader; - (void)size; - (void)fragment; -#endif -} - -EXPORT void HWRAPI(SetShader) (int type) +EXPORT void HWRAPI(SetShader) (int slot) { #ifdef GL_SHADERS - if (type == SHADER_NONE) + if (slot == SHADER_NONE) { UnSetShader(); return; } - - if (gl_allowshaders != HWD_SHADEROPTION_OFF) + if (gl_allowshaders) { - gl_shader_t *shader = gl_shaderstate.current; + gl_shader_t *next_shader = &gl_shaders[slot]; // the gl_shader_t we are going to switch to - // If using model lighting, set the appropriate shader. - // However don't override a custom shader. - if (type == SHADER_MODEL && model_lighting - && !(gl_shaders[SHADER_MODEL].custom && !gl_shaders[SHADER_MODEL_LIGHTING].custom)) - type = SHADER_MODEL_LIGHTING; + if (!next_shader->program) + next_shader = &gl_fallback_shader; // unusable shader, use fallback instead - if ((shader == NULL) || (GLuint)type != gl_shaderstate.type) + // update gl_shaderstate if an actual shader switch is needed + if (gl_shaderstate.current != next_shader) { - gl_shader_t *baseshader = &gl_shaders[type]; - gl_shader_t *usershader = &gl_usershaders[type]; - - if (usershader->program) - shader = (gl_allowshaders == HWD_SHADEROPTION_NOCUSTOM) ? baseshader : usershader; - else - shader = baseshader; - - gl_shaderstate.current = shader; - gl_shaderstate.type = type; + gl_shaderstate.current = next_shader; + gl_shaderstate.program = next_shader->program; + gl_shaderstate.type = slot; gl_shaderstate.changed = true; } - if (gl_shaderstate.program != shader->program) - { - gl_shaderstate.program = shader->program; - gl_shaderstate.changed = true; - } + gl_shadersenabled = true; - gl_shadersenabled = (shader->program != 0); return; } #else - (void)type; + (void)slot; #endif gl_shadersenabled = false; } @@ -1082,36 +840,20 @@ EXPORT void HWRAPI(SetShader) (int type) EXPORT void HWRAPI(UnSetShader) (void) { #ifdef GL_SHADERS - gl_shaderstate.current = NULL; - gl_shaderstate.type = 0; - gl_shaderstate.program = 0; + if (gl_shadersenabled) // don't repeatedly call glUseProgram if not needed + { + gl_shaderstate.current = NULL; + gl_shaderstate.type = 0; + gl_shaderstate.program = 0; - if (pglUseProgram) - pglUseProgram(0); + if (pglUseProgram) + pglUseProgram(0); + } #endif gl_shadersenabled = false; } -EXPORT void HWRAPI(CleanShaders) (void) -{ - INT32 i; - - for (i = 1; i < HWR_MAXSHADERS; i++) - { - shadersource_t *shader = &gl_customshaders[i]; - - if (shader->vertex) - free(shader->vertex); - - if (shader->fragment) - free(shader->fragment); - - shader->vertex = NULL; - shader->fragment = NULL; - } -} - // -----------------+ // SetNoTexture : Disable texture // -----------------+ @@ -1407,55 +1149,38 @@ EXPORT void HWRAPI(ClearMipMapCache) (void) } -// -----------------+ -// ReadRect : Read a rectangle region of the truecolor framebuffer -// : store pixels as 16bit 565 RGB -// Returns : 16bit 565 RGB pixel array stored in dst_data -// -----------------+ -EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, - INT32 dst_stride, UINT16 * dst_data) +// Writes screen texture tex into dst_data. +// Pixel format is 24-bit RGB. Row order is top to bottom. +// Dimensions are screen_width * screen_height. +EXPORT void HWRAPI(ReadScreenTexture) (int tex, UINT8 *dst_data) { INT32 i; - // GL_DBG_Printf ("ReadRect()\n"); - if (dst_stride == width*3) - { - GLubyte*top = (GLvoid*)dst_data, *bottom = top + dst_stride * (height - 1); - GLubyte *row = malloc(dst_stride); - if (!row) return; - pglPixelStorei(GL_PACK_ALIGNMENT, 1); - pglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, dst_data); - pglPixelStorei(GL_UNPACK_ALIGNMENT, 1); - for(i = 0; i < height/2; i++) - { - memcpy(row, top, dst_stride); - memcpy(top, bottom, dst_stride); - memcpy(bottom, row, dst_stride); - top += dst_stride; - bottom -= dst_stride; - } - free(row); - } - else - { - INT32 j; - GLubyte *image = malloc(width*height*3*sizeof (*image)); - if (!image) return; - pglPixelStorei(GL_PACK_ALIGNMENT, 1); - pglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, image); - pglPixelStorei(GL_UNPACK_ALIGNMENT, 1); - for (i = height-1; i >= 0; i--) - { - for (j = 0; j < width; j++) - { - dst_data[(height-1-i)*width+j] = - (UINT16)( - ((image[(i*width+j)*3]>>3)<<11) | - ((image[(i*width+j)*3+1]>>2)<<5) | - ((image[(i*width+j)*3+2]>>3))); - } - } - free(image); - } + int dst_stride = screen_width * 3; // stride between rows of image data + GLubyte*top = (GLvoid*)dst_data, *bottom = top + dst_stride * (screen_height - 1); + GLubyte *row; + row = malloc(dst_stride); + if (!row) return; + // at the time this function is called, generic2 can be found drawn on the framebuffer + // if some other screen texture is needed, draw it to the framebuffer + // and draw generic2 back after reading the framebuffer. + // this hack is for some reason **much** faster than the simple solution of using glGetTexImage. + if (tex != HWD_SCREENTEXTURE_GENERIC2) + DrawScreenTexture(tex, NULL, 0); + pglPixelStorei(GL_PACK_ALIGNMENT, 1); + pglReadPixels(0, 0, screen_width, screen_height, GL_RGB, GL_UNSIGNED_BYTE, dst_data); + if (tex != HWD_SCREENTEXTURE_GENERIC2) + DrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2, NULL, 0); + // Flip image upside down. + // In other words, convert OpenGL's "bottom->top" row order into "top->bottom". + for(i = 0; i < screen_height/2; i++) + { + memcpy(row, top, dst_stride); + memcpy(top, bottom, dst_stride); + memcpy(bottom, row, dst_stride); + top += dst_stride; + bottom -= dst_stride; + } + free(row); } @@ -1887,7 +1612,8 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); if (MipMap) { - pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + pglTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + pglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); if (pTexInfo->flags & TF_TRANSPARENT) pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff @@ -1908,7 +1634,8 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); if (MipMap) { - pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + pglTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); if (pTexInfo->flags & TF_TRANSPARENT) pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff @@ -1928,7 +1655,8 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) { if (MipMap) { - pgluBuild2DMipmaps(GL_TEXTURE_2D, textureformatGL, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + pglTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + pglTexImage2D(GL_TEXTURE_2D, 0, textureformatGL, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); // Control the mipmap level of detail pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); // the lower the number, the higer the detail if (pTexInfo->flags & TF_TRANSPARENT) @@ -2071,69 +1799,91 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF #endif } -static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i, const GLchar *vert_shader, const GLchar *frag_shader) +static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i) { - GLuint gl_vertShader, gl_fragShader; + GLuint gl_vertShader = 0; + GLuint gl_fragShader = 0; GLint result; + const GLchar *vert_shader = shader->vertex_shader; + const GLchar *frag_shader = shader->fragment_shader; - // - // Load and compile vertex shader - // - gl_vertShader = pglCreateShader(GL_VERTEX_SHADER); - if (!gl_vertShader) + if (shader->program) + pglDeleteProgram(shader->program); + + if (!vert_shader && !frag_shader) { - GL_MSG_Error("Shader_CompileProgram: Error creating vertex shader %s\n", HWR_GetShaderName(i)); + GL_MSG_Error("Shader_CompileProgram: Missing shaders for shader program %s\n", HWR_GetShaderName(i)); return false; } - pglShaderSource(gl_vertShader, 1, &vert_shader, NULL); - pglCompileShader(gl_vertShader); - - // check for compile errors - pglGetShaderiv(gl_vertShader, GL_COMPILE_STATUS, &result); - if (result == GL_FALSE) + if (vert_shader) { - Shader_CompileError("Error compiling vertex shader", gl_vertShader, i); - pglDeleteShader(gl_vertShader); - return false; + // + // Load and compile vertex shader + // + gl_vertShader = pglCreateShader(GL_VERTEX_SHADER); + if (!gl_vertShader) + { + GL_MSG_Error("Shader_CompileProgram: Error creating vertex shader %s\n", HWR_GetShaderName(i)); + return false; + } + + pglShaderSource(gl_vertShader, 1, &vert_shader, NULL); + pglCompileShader(gl_vertShader); + + // check for compile errors + pglGetShaderiv(gl_vertShader, GL_COMPILE_STATUS, &result); + if (result == GL_FALSE) + { + Shader_CompileError("Error compiling vertex shader", gl_vertShader, i); + pglDeleteShader(gl_vertShader); + return false; + } } - // - // Load and compile fragment shader - // - gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER); - if (!gl_fragShader) + if (frag_shader) { - GL_MSG_Error("Shader_CompileProgram: Error creating fragment shader %s\n", HWR_GetShaderName(i)); - pglDeleteShader(gl_vertShader); - pglDeleteShader(gl_fragShader); - return false; - } + // + // Load and compile fragment shader + // + gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER); + if (!gl_fragShader) + { + GL_MSG_Error("Shader_CompileProgram: Error creating fragment shader %s\n", HWR_GetShaderName(i)); + pglDeleteShader(gl_vertShader); + pglDeleteShader(gl_fragShader); + return false; + } - pglShaderSource(gl_fragShader, 1, &frag_shader, NULL); - pglCompileShader(gl_fragShader); + pglShaderSource(gl_fragShader, 1, &frag_shader, NULL); + pglCompileShader(gl_fragShader); - // check for compile errors - pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result); - if (result == GL_FALSE) - { - Shader_CompileError("Error compiling fragment shader", gl_fragShader, i); - pglDeleteShader(gl_vertShader); - pglDeleteShader(gl_fragShader); - return false; + // check for compile errors + pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result); + if (result == GL_FALSE) + { + Shader_CompileError("Error compiling fragment shader", gl_fragShader, i); + pglDeleteShader(gl_vertShader); + pglDeleteShader(gl_fragShader); + return false; + } } shader->program = pglCreateProgram(); - pglAttachShader(shader->program, gl_vertShader); - pglAttachShader(shader->program, gl_fragShader); + if (vert_shader) + pglAttachShader(shader->program, gl_vertShader); + if (frag_shader) + pglAttachShader(shader->program, gl_fragShader); pglLinkProgram(shader->program); // check link status pglGetProgramiv(shader->program, GL_LINK_STATUS, &result); // delete the shader objects - pglDeleteShader(gl_vertShader); - pglDeleteShader(gl_fragShader); + if (vert_shader) + pglDeleteShader(gl_vertShader); + if (frag_shader) + pglDeleteShader(gl_fragShader); // couldn't link? if (result != GL_TRUE) @@ -2154,11 +1904,31 @@ static boolean Shader_CompileProgram(gl_shader_t *shader, GLint i, const GLchar shader->uniforms[gluniform_fade_start] = GETUNI("fade_start"); shader->uniforms[gluniform_fade_end] = GETUNI("fade_end"); - // misc. (custom shaders) - shader->uniforms[gluniform_leveltime] = GETUNI("leveltime"); + // palette rendering + shader->uniforms[gluniform_palette_tex] = GETUNI("palette_tex"); + shader->uniforms[gluniform_palette_lookup_tex] = GETUNI("palette_lookup_tex"); + shader->uniforms[gluniform_lighttable_tex] = GETUNI("lighttable_tex"); + // misc. + shader->uniforms[gluniform_leveltime] = GETUNI("leveltime"); #undef GETUNI + // set permanent uniform values +#define UNIFORM_1(uniform, a, function) \ + if (uniform != -1) \ + function (uniform, a); + + pglUseProgram(shader->program); + + // texture unit numbers for the samplers used for palette rendering + UNIFORM_1(shader->uniforms[gluniform_palette_tex], 2, pglUniform1i); + UNIFORM_1(shader->uniforms[gluniform_palette_lookup_tex], 1, pglUniform1i); + UNIFORM_1(shader->uniforms[gluniform_lighttable_tex], 2, pglUniform1i); + + // restore gl shader state + pglUseProgram(gl_shaderstate.program); +#undef UNIFORM_1 + return true; } @@ -2182,6 +1952,7 @@ static void Shader_CompileError(const char *message, GLuint program, INT32 shade } // code that is common between DrawPolygon and DrawIndexedTriangles +// DrawScreenTexture also can use this function for fancier screen texture drawing // the corona thing is there too, i have no idea if that stuff works with DrawIndexedTriangles and batching static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD PolyFlags) { @@ -2221,6 +1992,14 @@ static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD fade.green = byte2float[pSurf->FadeColor.s.green]; fade.blue = byte2float[pSurf->FadeColor.s.blue]; fade.alpha = byte2float[pSurf->FadeColor.s.alpha]; + + if (pSurf->LightTableId && pSurf->LightTableId != lt_downloaded) + { + pglActiveTexture(GL_TEXTURE2); + pglBindTexture(GL_TEXTURE_2D, pSurf->LightTableId); + pglActiveTexture(GL_TEXTURE0); + lt_downloaded = pSurf->LightTableId; + } } } @@ -2413,9 +2192,6 @@ EXPORT void HWRAPI(RenderSkyDome) (gl_sky_t *sky) pglDisableClientState(GL_COLOR_ARRAY); } -// ========================================================================== -// -// ========================================================================== EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) { switch (IdState) @@ -2425,7 +2201,7 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) break; case HWD_SET_SHADERS: - gl_allowshaders = (hwdshaderoption_t)Value; + gl_allowshaders = Value; break; case HWD_SET_TEXTUREFILTERMODE: @@ -2463,7 +2239,7 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) mag_filter = GL_LINEAR; min_filter = GL_NEAREST; } - if (!pgluBuild2DMipmaps) + if (!supportMipMap) { MipMap = GL_FALSE; min_filter = GL_LINEAR; @@ -2784,6 +2560,14 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, float duration, float else if (Surface->PolyColor.s.alpha == 0xFF) flags |= (PF_Occlude | PF_Masked); + if (Surface->LightTableId && Surface->LightTableId != lt_downloaded) + { + pglActiveTexture(GL_TEXTURE2); + pglBindTexture(GL_TEXTURE_2D, Surface->LightTableId); + pglActiveTexture(GL_TEXTURE0); + lt_downloaded = Surface->LightTableId; + } + SetBlend(flags); Shader_SetUniforms(Surface, &poly, &tint, &fade); @@ -3071,7 +2855,7 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) INT32 x, y; float float_x, float_y, float_nextx, float_nexty; float xfix, yfix; - INT32 texsize = 2048; + INT32 texsize = 512; const float blackBack[16] = { @@ -3081,11 +2865,9 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) 16.0f, -16.0f, 6.0f }; - // Use a power of two texture, dammit - if(screen_width <= 1024) - texsize = 1024; - if(screen_width <= 512) - texsize = 512; + // look for power of two that is large enough for the screen + while (texsize < screen_width || texsize < screen_height) + texsize <<= 1; // X/Y stretch fix for all resolutions(!) xfix = (float)(texsize)/((float)((screen_width)/(float)(SCREENVERTS-1))); @@ -3159,84 +2941,16 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) // a new size EXPORT void HWRAPI(FlushScreenTextures) (void) { - pglDeleteTextures(1, &screentexture); - pglDeleteTextures(1, &startScreenWipe); - pglDeleteTextures(1, &endScreenWipe); - pglDeleteTextures(1, &finalScreenTexture); - screentexture = 0; - startScreenWipe = 0; - endScreenWipe = 0; - finalScreenTexture = 0; -} - -// Create Screen to fade from -EXPORT void HWRAPI(StartScreenWipe) (void) -{ - INT32 texsize = 2048; - boolean firstTime = (startScreenWipe == 0); - - // Use a power of two texture, dammit - if(screen_width <= 512) - texsize = 512; - else if(screen_width <= 1024) - texsize = 1024; - - // Create screen texture - if (firstTime) - pglGenTextures(1, &startScreenWipe); - pglBindTexture(GL_TEXTURE_2D, startScreenWipe); - - if (firstTime) - { - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - Clamp2D(GL_TEXTURE_WRAP_S); - Clamp2D(GL_TEXTURE_WRAP_T); - pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); - } - else - pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize); - - tex_downloaded = startScreenWipe; -} - -// Create Screen to fade to -EXPORT void HWRAPI(EndScreenWipe)(void) -{ - INT32 texsize = 2048; - boolean firstTime = (endScreenWipe == 0); - - // Use a power of two texture, dammit - if(screen_width <= 512) - texsize = 512; - else if(screen_width <= 1024) - texsize = 1024; - - // Create screen texture - if (firstTime) - pglGenTextures(1, &endScreenWipe); - pglBindTexture(GL_TEXTURE_2D, endScreenWipe); - - if (firstTime) - { - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - Clamp2D(GL_TEXTURE_WRAP_S); - Clamp2D(GL_TEXTURE_WRAP_T); - pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); - } - else - pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize); - - tex_downloaded = endScreenWipe; + int i; + pglDeleteTextures(NUMSCREENTEXTURES, screenTextures); + for (i = 0; i < NUMSCREENTEXTURES; i++) + screenTextures[i] = 0; } - -// Draw the last scene under the intermission -EXPORT void HWRAPI(DrawIntermissionBG)(void) +EXPORT void HWRAPI(DrawScreenTexture)(int tex, FSurfaceInfo *surf, FBITFIELD polyflags) { float xfix, yfix; - INT32 texsize = 2048; + INT32 texsize = 512; const float screenVerts[12] = { @@ -3248,10 +2962,9 @@ EXPORT void HWRAPI(DrawIntermissionBG)(void) float fix[8]; - if(screen_width <= 1024) - texsize = 1024; - if(screen_width <= 512) - texsize = 512; + // look for power of two that is large enough for the screen + while (texsize < screen_width || texsize < screen_height) + texsize <<= 1; xfix = 1/((float)(texsize)/((float)((screen_width)))); yfix = 1/((float)(texsize)/((float)((screen_height)))); @@ -3270,20 +2983,23 @@ EXPORT void HWRAPI(DrawIntermissionBG)(void) pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - pglBindTexture(GL_TEXTURE_2D, screentexture); - pglColor4ubv(white); + pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]); + PreparePolygon(surf, NULL, surf ? polyflags : (PF_NoDepthTest)); + if (!surf) + pglColor4ubv(white); pglTexCoordPointer(2, GL_FLOAT, 0, fix); pglVertexPointer(3, GL_FLOAT, 0, screenVerts); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); - tex_downloaded = screentexture; + tex_downloaded = screenTextures[tex]; } // Do screen fades! -EXPORT void HWRAPI(DoScreenWipe)(void) +EXPORT void HWRAPI(DoScreenWipe)(int wipeStart, int wipeEnd, FSurfaceInfo *surf, + FBITFIELD polyFlags) { - INT32 texsize = 2048; + INT32 texsize = 512; float xfix, yfix; INT32 fademaskdownloaded = tex_downloaded; // the fade mask that has been set @@ -3306,11 +3022,15 @@ EXPORT void HWRAPI(DoScreenWipe)(void) 1.0f, 1.0f }; - // Use a power of two texture, dammit - if(screen_width <= 1024) - texsize = 1024; - if(screen_width <= 512) - texsize = 512; + int firstScreen; + if (surf && surf->PolyColor.s.alpha == 255) + firstScreen = wipeEnd; // it's a tinted fade-in, we need wipeEnd + else + firstScreen = wipeStart; + + // look for power of two that is large enough for the screen + while (texsize < screen_width || texsize < screen_height) + texsize <<= 1; xfix = 1/((float)(texsize)/((float)((screen_width)))); yfix = 1/((float)(texsize)/((float)((screen_height)))); @@ -3332,91 +3052,71 @@ EXPORT void HWRAPI(DoScreenWipe)(void) SetBlend(PF_Modulated|PF_NoDepthTest); pglEnable(GL_TEXTURE_2D); - // Draw the original screen - pglBindTexture(GL_TEXTURE_2D, startScreenWipe); + pglBindTexture(GL_TEXTURE_2D, screenTextures[firstScreen]); pglColor4ubv(white); pglTexCoordPointer(2, GL_FLOAT, 0, fix); pglVertexPointer(3, GL_FLOAT, 0, screenVerts); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); - SetBlend(PF_Modulated|PF_Translucent|PF_NoDepthTest); - - // Draw the end screen that fades in - pglActiveTexture(GL_TEXTURE0); - pglEnable(GL_TEXTURE_2D); - pglBindTexture(GL_TEXTURE_2D, endScreenWipe); - pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - - pglActiveTexture(GL_TEXTURE1); - pglEnable(GL_TEXTURE_2D); - pglBindTexture(GL_TEXTURE_2D, fademaskdownloaded); - - pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - // const float defaultST[8] + if (surf) + { + // Draw fade mask to screen using surf and polyFlags + // Used for colormap/tinted wipes. + pglBindTexture(GL_TEXTURE_2D, fademaskdownloaded); + pglTexCoordPointer(2, GL_FLOAT, 0, defaultST); + pglVertexPointer(3, GL_FLOAT, 0, screenVerts); + PreparePolygon(surf, NULL, polyFlags); + pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); + } + else // Blend wipeEnd into screen with the fade mask + { + SetBlend(PF_Modulated|PF_Translucent|PF_NoDepthTest); - pglClientActiveTexture(GL_TEXTURE0); - pglTexCoordPointer(2, GL_FLOAT, 0, fix); - pglVertexPointer(3, GL_FLOAT, 0, screenVerts); - pglClientActiveTexture(GL_TEXTURE1); - pglEnableClientState(GL_TEXTURE_COORD_ARRAY); - pglTexCoordPointer(2, GL_FLOAT, 0, defaultST); - pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); + // Draw the end screen that fades in + pglActiveTexture(GL_TEXTURE0); + pglEnable(GL_TEXTURE_2D); + pglBindTexture(GL_TEXTURE_2D, screenTextures[wipeEnd]); + pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - pglDisable(GL_TEXTURE_2D); // disable the texture in the 2nd texture unit - pglDisableClientState(GL_TEXTURE_COORD_ARRAY); + pglActiveTexture(GL_TEXTURE1); + pglEnable(GL_TEXTURE_2D); + pglBindTexture(GL_TEXTURE_2D, fademaskdownloaded); - pglActiveTexture(GL_TEXTURE0); - pglClientActiveTexture(GL_TEXTURE0); - tex_downloaded = endScreenWipe; -} + pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); -// Create a texture from the screen. -EXPORT void HWRAPI(MakeScreenTexture) (void) -{ - INT32 texsize = 2048; - boolean firstTime = (screentexture == 0); + // const float defaultST[8] - // Use a power of two texture, dammit - if(screen_width <= 512) - texsize = 512; - else if(screen_width <= 1024) - texsize = 1024; + pglClientActiveTexture(GL_TEXTURE0); + pglTexCoordPointer(2, GL_FLOAT, 0, fix); + pglVertexPointer(3, GL_FLOAT, 0, screenVerts); + pglClientActiveTexture(GL_TEXTURE1); + pglEnableClientState(GL_TEXTURE_COORD_ARRAY); + pglTexCoordPointer(2, GL_FLOAT, 0, defaultST); + pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); - // Create screen texture - if (firstTime) - pglGenTextures(1, &screentexture); - pglBindTexture(GL_TEXTURE_2D, screentexture); + pglDisable(GL_TEXTURE_2D); // disable the texture in the 2nd texture unit + pglDisableClientState(GL_TEXTURE_COORD_ARRAY); - if (firstTime) - { - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - Clamp2D(GL_TEXTURE_WRAP_S); - Clamp2D(GL_TEXTURE_WRAP_T); - pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0); + pglActiveTexture(GL_TEXTURE0); + pglClientActiveTexture(GL_TEXTURE0); + tex_downloaded = screenTextures[wipeEnd]; } - else - pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize); - - tex_downloaded = screentexture; } -EXPORT void HWRAPI(MakeScreenFinalTexture) (void) +// Create a texture from the screen. +EXPORT void HWRAPI(MakeScreenTexture) (int tex) { - INT32 texsize = 2048; - boolean firstTime = (finalScreenTexture == 0); + INT32 texsize = 512; + boolean firstTime = (screenTextures[tex] == 0); - // Use a power of two texture, dammit - if(screen_width <= 512) - texsize = 512; - else if(screen_width <= 1024) - texsize = 1024; + // look for power of two that is large enough for the screen + while (texsize < screen_width || texsize < screen_height) + texsize <<= 1; // Create screen texture if (firstTime) - pglGenTextures(1, &finalScreenTexture); - pglBindTexture(GL_TEXTURE_2D, finalScreenTexture); + pglGenTextures(1, &screenTextures[tex]); + pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]); if (firstTime) { @@ -3429,24 +3129,23 @@ EXPORT void HWRAPI(MakeScreenFinalTexture) (void) else pglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, texsize, texsize); - tex_downloaded = finalScreenTexture; + tex_downloaded = screenTextures[tex]; } -EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) +EXPORT void HWRAPI(DrawScreenFinalTexture)(int tex, int width, int height) { float xfix, yfix; float origaspect, newaspect; float xoff = 1, yoff = 1; // xoffset and yoffset for the polygon to have black bars around the screen FRGBAFloat clearColour; - INT32 texsize = 2048; + INT32 texsize = 512; float off[12]; float fix[8]; - if(screen_width <= 1024) - texsize = 1024; - if(screen_width <= 512) - texsize = 512; + // look for power of two that is large enough for the screen + while (texsize < screen_width || texsize < screen_height) + texsize <<= 1; xfix = 1/((float)(texsize)/((float)((screen_width)))); yfix = 1/((float)(texsize)/((float)((screen_height)))); @@ -3493,7 +3192,8 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) clearColour.red = clearColour.green = clearColour.blue = 0; clearColour.alpha = 1; ClearBuffer(true, false, &clearColour); - pglBindTexture(GL_TEXTURE_2D, finalScreenTexture); + SetBlend(PF_NoDepthTest); + pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]); pglColor4ubv(white); @@ -3501,7 +3201,110 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) pglVertexPointer(3, GL_FLOAT, 0, off); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); - tex_downloaded = finalScreenTexture; + tex_downloaded = screenTextures[tex]; +} + +EXPORT void HWRAPI(SetPaletteLookup)(UINT8 *lut) +{ + GLenum internalFormat; + if (gl_version[0] == '1' || gl_version[0] == '2') + { + // if the OpenGL version is below 3.0, then the GL_R8 format may not be available. + // so use GL_LUMINANCE8 instead to get a single component 8-bit format + // (it is possible to have access to shaders even in some OpenGL 1.x systems, + // so palette rendering can still possibly be achieved there) + internalFormat = GL_LUMINANCE8; + } + else + { + internalFormat = GL_R8; + } + if (!paletteLookupTex) + pglGenTextures(1, &paletteLookupTex); + pglActiveTexture(GL_TEXTURE1); + pglBindTexture(GL_TEXTURE_3D, paletteLookupTex); + pglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexImage3D(GL_TEXTURE_3D, 0, internalFormat, HWR_PALETTE_LUT_SIZE, HWR_PALETTE_LUT_SIZE, HWR_PALETTE_LUT_SIZE, + 0, GL_RED, GL_UNSIGNED_BYTE, lut); + pglActiveTexture(GL_TEXTURE0); +} + +EXPORT UINT32 HWRAPI(CreateLightTable)(RGBA_t *hw_lighttable) +{ + LTListItem *item = malloc(sizeof(LTListItem)); + if (!LightTablesTail) + { + LightTablesHead = LightTablesTail = item; + } + else + { + LightTablesTail->next = item; + LightTablesTail = item; + } + item->next = NULL; + pglGenTextures(1, &item->id); + pglBindTexture(GL_TEXTURE_2D, item->id); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, hw_lighttable); + + // restore previously bound texture + pglBindTexture(GL_TEXTURE_2D, tex_downloaded); + + return item->id; +} + +EXPORT void HWRAPI(UpdateLightTable)(UINT32 id, RGBA_t *hw_lighttable) +{ + LTListItem *item = LightTablesHead; + while (item && item->id != id) + item = item->next; + + if (item) + { + pglBindTexture(GL_TEXTURE_2D, item->id); + + // Just update it + pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 32, GL_RGBA, GL_UNSIGNED_BYTE, hw_lighttable); + + // restore previously bound texture + pglBindTexture(GL_TEXTURE_2D, tex_downloaded); + } +} + +// Delete light table textures, ids given before become invalid and must not be used. +EXPORT void HWRAPI(ClearLightTables)(void) +{ + while (LightTablesHead) + { + LTListItem *item = LightTablesHead; + pglDeleteTextures(1, (GLuint *)&item->id); + LightTablesHead = item->next; + free(item); + } + + LightTablesTail = NULL; + + // we no longer have a bound light table (if we had one), we just deleted it! + lt_downloaded = 0; +} + +// This palette is used for the palette rendering postprocessing step. +EXPORT void HWRAPI(SetScreenPalette)(RGBA_t *palette) +{ + if (memcmp(screenPalette, palette, sizeof(screenPalette))) + { + memcpy(screenPalette, palette, sizeof(screenPalette)); + if (!screenPaletteTex) + pglGenTextures(1, &screenPaletteTex); + pglActiveTexture(GL_TEXTURE2); + pglBindTexture(GL_TEXTURE_1D, screenPaletteTex); + pglTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, palette); + pglActiveTexture(GL_TEXTURE0); + } } #endif //HWRENDER diff --git a/src/hardware/r_opengl/r_opengl.h b/src/hardware/r_opengl/r_opengl.h index f44e0818bbeff0cae3160cd788d67b11587e7961..197f75ea8931735b3e10b80e68a6ae47a5a736f5 100644 --- a/src/hardware/r_opengl/r_opengl.h +++ b/src/hardware/r_opengl/r_opengl.h @@ -35,7 +35,6 @@ #else #include <GL/gl.h> -#include <GL/glu.h> #ifdef STATIC_OPENGL // Because of the 1.3 functions, you'll need GLext to compile it if static #define GL_GLEXT_PROTOTYPES @@ -46,6 +45,7 @@ #define _CREATE_DLL_ // necessary for Unix AND Windows #include "../../doomdef.h" #include "../hw_drv.h" +#include "../../z_zone.h" // ========================================================================== // DEFINITIONS @@ -126,6 +126,7 @@ extern GLint screen_width; extern GLint screen_height; extern GLbyte screen_depth; extern GLint maximumAnisotropy; +extern boolean supportMipMap; /** \brief OpenGL flags for video driver */ diff --git a/src/hu_stuff.c b/src/hu_stuff.c index bb2b837fcb299e8b0003eaa24764302d2e5bf7ee..7f2560bcc4adc2f398d87aa8066119ee9ec3b455 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -29,7 +29,7 @@ #include "i_video.h" #include "i_system.h" -#include "st_stuff.h" // ST_HEIGHT +#include "st_stuff.h" #include "r_local.h" #include "keys.h" @@ -61,21 +61,22 @@ #define HU_CSAY 2 // Server CECHOes to everyone. //------------------------------------------- -// heads up font +// Fonts & stuff //------------------------------------------- -patch_t *hu_font[HU_FONTSIZE]; -patch_t *tny_font[HU_FONTSIZE]; +// Font definitions +fontdef_t hu_font; +fontdef_t tny_font; +fontdef_t cred_font; +fontdef_t lt_font; +fontdef_t ntb_font; +fontdef_t nto_font; + +// Numbers patch_t *tallnum[10]; // 0-9 patch_t *nightsnum[10]; // 0-9 - -// Level title and credits fonts -patch_t *lt_font[LT_FONTSIZE]; -patch_t *cred_font[CRED_FONTSIZE]; patch_t *ttlnum[10]; // act numbers (0-9) - -// Name tag fonts -patch_t *ntb_font[NT_FONTSIZE]; -patch_t *nto_font[NT_FONTSIZE]; +patch_t *tallminus; +patch_t *tallinfin; static player_t *plr; boolean chat_on; // entering a chat message? @@ -91,8 +92,6 @@ patch_t *bflagico; patch_t *rmatcico; patch_t *bmatcico; patch_t *tagico; -patch_t *tallminus; -patch_t *tallinfin; //------------------------------------------- // coop hud @@ -188,53 +187,26 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum); void HU_LoadGraphics(void) { char buffer[9]; - INT32 i, j; + INT32 i; if (dedicated) return; - j = HU_FONTSTART; - for (i = 0; i < HU_FONTSIZE; i++, j++) - { - // cache the heads-up font for entire game execution - sprintf(buffer, "STCFN%.3d", j); - if (W_CheckNumForName(buffer) == LUMPERROR) - hu_font[i] = NULL; - else - hu_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); - - // tiny version of the heads-up font - sprintf(buffer, "TNYFN%.3d", j); - if (W_CheckNumForName(buffer) == LUMPERROR) - tny_font[i] = NULL; - else - tny_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); - } - - j = LT_FONTSTART; - for (i = 0; i < LT_FONTSIZE; i++) - { - sprintf(buffer, "LTFNT%.3d", j); - j++; - - if (W_CheckNumForName(buffer) == LUMPERROR) - lt_font[i] = NULL; - else - lt_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); - } - - // cache the credits font for entire game execution (why not?) - j = CRED_FONTSTART; - for (i = 0; i < CRED_FONTSIZE; i++) - { - sprintf(buffer, "CRFNT%.3d", j); - j++; - - if (W_CheckNumForName(buffer) == LUMPERROR) - cred_font[i] = NULL; - else - cred_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); - } + // Cache fonts + HU_LoadFontCharacters(&hu_font, "STCFN"); + HU_LoadFontCharacters(&tny_font, "TNYFN"); + HU_LoadFontCharacters(&cred_font, "CRFNT"); + HU_LoadFontCharacters(<_font, "LTFNT"); + HU_LoadFontCharacters(&ntb_font, "NTFNT"); + HU_LoadFontCharacters(&nto_font, "NTFNO"); + + // For each font, set kerning, space width, character width and line spacing + HU_SetFontProperties(&hu_font, 0, 4, 8, 12); + HU_SetFontProperties(&tny_font, 0, 2, 4, 12); + HU_SetFontProperties(&cred_font, 0, 16, 16, 16); + HU_SetFontProperties(<_font, 0, 16, 20, 16); + HU_SetFontProperties(&ntb_font, 2, 4, 20, 21); + HU_SetFontProperties(&nto_font, 0, 4, 20, 21); //cache numbers too! for (i = 0; i < 10; i++) @@ -243,45 +215,14 @@ void HU_LoadGraphics(void) tallnum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); sprintf(buffer, "NGTNUM%d", i); nightsnum[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); + sprintf(buffer, "TTL%.2d", i); + ttlnum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); } // minus for negative tallnums tallminus = (patch_t *)W_CachePatchName("STTMINUS", PU_HUDGFX); tallinfin = (patch_t *)W_CachePatchName("STTINFIN", PU_HUDGFX); - // cache act numbers for level titles - for (i = 0; i < 10; i++) - { - sprintf(buffer, "TTL%.2d", i); - ttlnum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); - } - - // cache the base name tag font for entire game execution - j = NT_FONTSTART; - for (i = 0; i < NT_FONTSIZE; i++) - { - sprintf(buffer, "NTFNT%.3d", j); - j++; - - if (W_CheckNumForName(buffer) == LUMPERROR) - ntb_font[i] = NULL; - else - ntb_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); - } - - // cache the outline name tag font for entire game execution - j = NT_FONTSTART; - for (i = 0; i < NT_FONTSIZE; i++) - { - sprintf(buffer, "NTFNO%.3d", j); - j++; - - if (W_CheckNumForName(buffer) == LUMPERROR) - nto_font[i] = NULL; - else - nto_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); - } - // cache the crosshairs, don't bother to know which one is being used, // just cache all 3, they're so small anyway. for (i = 0; i < HU_CROSSHAIRS; i++) @@ -323,6 +264,29 @@ void HU_LoadGraphics(void) //emeraldpics[2][7] = W_CachePatchName("EMBOX8", PU_HUDGFX); -- unused } +void HU_LoadFontCharacters(fontdef_t *font, const char *prefix) +{ + char buffer[9]; + INT32 i, j = FONTSTART; + + for (i = 0; i < FONTSIZE; i++, j++) + { + sprintf(buffer, "%.5s%.3d", prefix, j); + if (W_CheckNumForPatchName(buffer) == LUMPERROR) + font->chars[i] = NULL; + else + font->chars[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); + } +} + +void HU_SetFontProperties(fontdef_t *font, INT32 kerning, UINT32 spacewidth, UINT32 charwidth, UINT32 linespacing) +{ + font->kerning = kerning; + font->spacewidth = spacewidth; + font->charwidth = charwidth; + font->linespacing = linespacing; +} + // Initialise Heads up // once at game startup. // @@ -465,9 +429,12 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) numwords = COM_Argc() - usedargs; I_Assert(numwords > 0); - if (CHAT_MUTE) // TODO: Per Player mute. + if (CHAT_MUTE) { - HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false); + if (cv_mute.value) + HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false); + else + HU_AddChatText(va("%s>ERROR: You have been muted. You can't say anything.", "\x85"), false); return; } @@ -496,10 +463,10 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) // what we're gonna do now is check if the player exists // with that logic, characters 4 and 5 are our numbers: const char *newmsg; - char playernum[3]; + char playernum[3+1]; INT32 spc = 1; // used if playernum[1] is a space. - strncpy(playernum, msg+3, 3); + strncpy(playernum, msg+3, sizeof(playernum)-1); // check for undesirable characters in our "number" if (((playernum[0] < '0') || (playernum[0] > '9')) || ((playernum[1] < '0') || (playernum[1] > '9'))) { @@ -620,8 +587,47 @@ static void Command_CSay_f(void) DoSayCommand(0, 1, HU_CSAY); } -static tic_t spam_tokens[MAXPLAYERS]; -static tic_t spam_tics[MAXPLAYERS]; +UINT8 spam_tokens[MAXPLAYERS] = { 1 }; // fill the buffer with 1 so the motd can be sent. +tic_t spam_tics[MAXPLAYERS]; + +static const char *GetChatColorFromSkinColor(INT32 skincolor) +{ + const char *textcolor = NULL; + UINT16 chatcolor = skincolors[skincolor].chatcolor; + if (!chatcolor || chatcolor%0x1000 || chatcolor>V_INVERTMAP) + textcolor = "\x80"; + else if (chatcolor == V_MAGENTAMAP) + textcolor = "\x81"; + else if (chatcolor == V_YELLOWMAP) + textcolor = "\x82"; + else if (chatcolor == V_GREENMAP) + textcolor = "\x83"; + else if (chatcolor == V_BLUEMAP) + textcolor = "\x84"; + else if (chatcolor == V_REDMAP) + textcolor = "\x85"; + else if (chatcolor == V_GRAYMAP) + textcolor = "\x86"; + else if (chatcolor == V_ORANGEMAP) + textcolor = "\x87"; + else if (chatcolor == V_SKYMAP) + textcolor = "\x88"; + else if (chatcolor == V_PURPLEMAP) + textcolor = "\x89"; + else if (chatcolor == V_AQUAMAP) + textcolor = "\x8a"; + else if (chatcolor == V_PERIDOTMAP) + textcolor = "\x8b"; + else if (chatcolor == V_AZUREMAP) + textcolor = "\x8c"; + else if (chatcolor == V_BROWNMAP) + textcolor = "\x8d"; + else if (chatcolor == V_ROSYMAP) + textcolor = "\x8e"; + else if (chatcolor == V_INVERTMAP) + textcolor = "\x8f"; + return textcolor; +} /** Receives a message, processing an ::XD_SAY command. * \sa DoSayCommand @@ -632,6 +638,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) SINT8 target; UINT8 flags; const char *dispname; + char buf[HU_MAXMSGLEN + 1]; char *msg; boolean action = false; char *ptr; @@ -641,12 +648,12 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) target = READSINT8(*p); flags = READUINT8(*p); - msg = (char *)*p; - SKIPSTRINGL(*p, HU_MAXMSGLEN + 1); + msg = buf; + READSTRINGL(*p, msg, HU_MAXMSGLEN + 1); - if ((cv_mute.value || flags & (HU_CSAY|HU_SERVER_SAY)) && playernum != serverplayer && !(IsPlayerAdmin(playernum))) + if ((cv_mute.value || players[playernum].muted || flags & (HU_CSAY|HU_SERVER_SAY)) && playernum != serverplayer && !(IsPlayerAdmin(playernum))) { - CONS_Alert(CONS_WARNING, cv_mute.value ? + CONS_Alert(CONS_WARNING, (cv_mute.value || players[playernum].muted) ? M_GetText("Illegal say command received from %s while muted\n") : M_GetText("Illegal csay command received from non-admin %s\n"), player_names[playernum]); if (server) @@ -682,14 +689,12 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) else spam_tokens[playernum] -= 1; - // run the lua hook even if we were supposed to eat the msg, netgame consistency goes first. + if (spam_eatmsg) + return; // don't proceed if we were supposed to eat the message. if (LUA_HookPlayerMsg(playernum, target, flags, msg)) return; - if (spam_eatmsg) - return; // don't proceed if we were supposed to eat the message. - // If it's a CSAY, just CECHO and be done with it. if (flags & HU_CSAY) { @@ -744,51 +749,27 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) { if (players[playernum].ctfteam == 1) // red { - cstart = "\x85"; - textcolor = "\x85"; + cstart = textcolor = GetChatColorFromSkinColor(skincolor_redteam); } else // blue { - cstart = "\x84"; - textcolor = "\x84"; + cstart = textcolor = GetChatColorFromSkinColor(skincolor_blueteam); } } else { - UINT16 chatcolor = skincolors[players[playernum].skincolor].chatcolor; - - if (!chatcolor || chatcolor%0x1000 || chatcolor>V_INVERTMAP) - cstart = "\x80"; - else if (chatcolor == V_MAGENTAMAP) - cstart = "\x81"; - else if (chatcolor == V_YELLOWMAP) - cstart = "\x82"; - else if (chatcolor == V_GREENMAP) - cstart = "\x83"; - else if (chatcolor == V_BLUEMAP) - cstart = "\x84"; - else if (chatcolor == V_REDMAP) - cstart = "\x85"; - else if (chatcolor == V_GRAYMAP) - cstart = "\x86"; - else if (chatcolor == V_ORANGEMAP) - cstart = "\x87"; - else if (chatcolor == V_SKYMAP) - cstart = "\x88"; - else if (chatcolor == V_PURPLEMAP) - cstart = "\x89"; - else if (chatcolor == V_AQUAMAP) - cstart = "\x8a"; - else if (chatcolor == V_PERIDOTMAP) - cstart = "\x8b"; - else if (chatcolor == V_AZUREMAP) - cstart = "\x8c"; - else if (chatcolor == V_BROWNMAP) - cstart = "\x8d"; - else if (chatcolor == V_ROSYMAP) - cstart = "\x8e"; - else if (chatcolor == V_INVERTMAP) - cstart = "\x8f"; + cstart = GetChatColorFromSkinColor(players[playernum].skincolor); + if (G_GametypeHasTeams()) + { + if (players[playernum].ctfteam == 1) // red + { + cstart = GetChatColorFromSkinColor(skincolor_redteam); + } + else // blue + { + cstart = GetChatColorFromSkinColor(skincolor_blueteam); + } + } } prefix = cstart; @@ -962,14 +943,17 @@ static void HU_sendChatMessage(void) // last minute mute check if (CHAT_MUTE) { - HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false); + if (cv_mute.value) + HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false); + else + HU_AddChatText(va("%s>ERROR: You have been muted. You can't say anything.", "\x85"), false); return; } if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm { INT32 spc = 1; // used if playernum[1] is a space. - char playernum[3]; + char playernum[3+1]; const char *newmsg; // what we're gonna do now is check if the player exists @@ -982,7 +966,7 @@ static void HU_sendChatMessage(void) return; } - strncpy(playernum, msg+3, 3); + strncpy(playernum, msg+3, sizeof(playernum)-1); // check for undesirable characters in our "number" if (!(isdigit(playernum[0]) && isdigit(playernum[1]))) { @@ -1029,6 +1013,7 @@ static void HU_sendChatMessage(void) void HU_clearChatChars(void) { memset(w_chat, '\0', sizeof(w_chat)); + I_SetTextInputMode(false); chat_on = false; c_input = 0; @@ -1078,6 +1063,7 @@ boolean HU_Responder(event_t *ev) if ((ev->key == gamecontrol[GC_TALKKEY][0] || ev->key == gamecontrol[GC_TALKKEY][1]) && netgame && !OLD_MUTE) // check for old chat mute, still let the players open the chat incase they want to scroll otherwise. { + I_SetTextInputMode(true); chat_on = true; chat_on_first_event = false; w_chat[0] = 0; @@ -1089,6 +1075,7 @@ boolean HU_Responder(event_t *ev) if ((ev->key == gamecontrol[GC_TEAMKEY][0] || ev->key == gamecontrol[GC_TEAMKEY][1]) && netgame && !OLD_MUTE) { + I_SetTextInputMode(true); chat_on = true; chat_on_first_event = false; w_chat[0] = 0; @@ -1111,7 +1098,7 @@ boolean HU_Responder(event_t *ev) if (ev->type == ev_text) { - if ((c < HU_FONTSTART || c > HU_FONTEND || !hu_font[c-HU_FONTSTART]) + if ((c < FONTSTART || c > FONTEND || !hu_font.chars[c-FONTSTART]) && c != ' ') // Allow spaces, of course { return false; @@ -1163,6 +1150,7 @@ boolean HU_Responder(event_t *ev) if (!CHAT_MUTE) HU_sendChatMessage(); + I_SetTextInputMode(false); chat_on = false; c_input = 0; // reset input cursor chat_scrollmedown = true; // you hit enter, so you might wanna autoscroll to see what you just sent. :) @@ -1173,6 +1161,7 @@ boolean HU_Responder(event_t *ev) || c == gamecontrol[GC_TEAMKEY][0] || c == gamecontrol[GC_TEAMKEY][1]) && c >= KEY_MOUSE1)) // If it's not a keyboard key, then the chat button is used as a toggle. { + I_SetTextInputMode(false); chat_on = false; c_input = 0; // reset input cursor I_UpdateMouseGrab(); @@ -1230,199 +1219,98 @@ boolean HU_Responder(event_t *ev) // HEADS UP DRAWING //====================================================================== -// Precompile a wordwrapped string to any given width. -// This is a muuuch better method than V_WORDWRAP. -// again stolen and modified a bit from video.c, don't mind me, will need to rearrange this one day. -// this one is simplified for the chat drawer. -static char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) -{ - INT32 c; - size_t chw, i, lastusablespace = 0; - size_t slen; - char *newstring = Z_StrDup(string); - INT32 spacewidth = (vid.width < 640) ? 8 : 4, charwidth = (vid.width < 640) ? 8 : 4; - - slen = strlen(string); - x = 0; - - for (i = 0; i < slen; ++i) - { - c = newstring[i]; - if ((UINT8)c >= 0x80 && (UINT8)c <= 0x89) //color parsing! -Inuyasha 2.16.09 - continue; - - if (c == '\n') - { - x = 0; - lastusablespace = 0; - continue; - } - - if (!(option & V_ALLOWLOWERCASE)) - c = toupper(c); - c -= HU_FONTSTART; - - if (c < 0 || c >= HU_FONTSIZE || !hu_font[c]) - { - chw = spacewidth; - lastusablespace = i; - } - else - chw = charwidth; - - x += chw; - - if (lastusablespace != 0 && x > w) - { - //CONS_Printf("Wrap at index %d\n", i); - newstring[lastusablespace] = '\n'; - i = lastusablespace+1; - lastusablespace = 0; - x = 0; - } - } - return newstring; -} - - // 30/7/18: chaty is now the distance at which the lowest point of the chat will be drawn if that makes any sense. INT16 chatx = 13, chaty = 169; // let's use this as our coordinates -// chat stuff by VincyTM LOL XD! - // HU_DrawMiniChat static void HU_drawMiniChat(void) { - INT32 x = chatx+2; + INT32 x = chatx+2, y; + INT32 chatheight = 0; INT32 charwidth = 4, charheight = 6; INT32 boxw = cv_chatwidth.value; INT32 dx = 0, dy = 0; - size_t i = chat_nummsg_min; - boolean prev_linereturn = false; // a hack to prevent double \n while I have no idea why they happen in the first place. - - INT32 msglines = 0; - // process all messages once without rendering anything or doing anything fancy so that we know how many lines each message has... - INT32 y; + boolean prev_linereturn = false; if (!chat_nummsg_min) return; // needless to say it's useless to do anything if we don't have anything to draw. - /*if (splitscreen > 1) - boxw = max(64, boxw/2);*/ - - for (; i>0; i--) + for (size_t i = chat_nummsg_min; i > 0; i--) { - char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i-1]); - size_t j = 0; - INT32 linescount = 0; - - while(msg[j]) // iterate through msg + char *msg = V_ChatWordWrap(0, boxw-charwidth-2, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE|V_MONOSPACE, chat_mini[i-1]); + for(size_t j = 0; msg[j]; j++) // iterate through msg { - if (msg[j] < HU_FONTSTART) // don't draw + if (msg[j] == '\n') // get back down. { - if (msg[j] == '\n') // get back down. + if (!prev_linereturn) { - ++j; - if (!prev_linereturn) - { - linescount += 1; - dx = 0; - } - prev_linereturn = true; - continue; - } - else if (msg[j] & 0x80) // stolen from video.c, nice. - { - ++j; - continue; + chatheight += charheight; + dx = 0; } - - ++j; - } - else - { - j++; + prev_linereturn = true; } - prev_linereturn = false; - dx += charwidth; - if (dx >= boxw) + else if (msg[j] >= FONTSTART) { - dx = 0; - linescount += 1; + prev_linereturn = false; + + dx += charwidth; + + if (dx >= boxw-charwidth-2) + { + dx = 0; + chatheight += charheight; + prev_linereturn = true; + } } } - dy = 0; dx = 0; - msglines += linescount+1; + chatheight += charheight; if (msg) Z_Free(msg); } - y = chaty - charheight*(msglines+1); - - /*if (splitscreen) - { - y -= BASEVIDHEIGHT/2; - if (splitscreen > 1) - y += 16; - }*/ - - dx = 0; - dy = 0; - i = 0; + y = chaty - (chatheight + charheight); prev_linereturn = false; - for (; i<=(chat_nummsg_min-1); i++) // iterate through our hot messages + for (size_t i = 0; i < chat_nummsg_min; i++) // iterate through our hot messages { - INT32 clrflag = 0; INT32 timer = ((cv_chattime.value*TICRATE)-chat_timers[i]) - cv_chattime.value*TICRATE+9; // see below... INT32 transflag = (timer >= 0 && timer <= 9) ? (timer*V_10TRANS) : 0; // you can make bad jokes out of this one. - size_t j = 0; - char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_mini[i]); // get the current message, and word wrap it. + char *msg = V_ChatWordWrap(0, boxw-charwidth-2, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE|V_MONOSPACE, chat_mini[i]); // get the current message, and word wrap it. UINT8 *colormap = NULL; - while(msg[j]) // iterate through msg + for(size_t j = 0; msg[j]; j++) // iterate through msg { - if (msg[j] < HU_FONTSTART) // don't draw + if (msg[j] == '\n') // get back down. { - if (msg[j] == '\n') // get back down. + if (!prev_linereturn) { - ++j; - if (!prev_linereturn) - { - dy += charheight; - dx = 0; - } - prev_linereturn = true; - continue; - } - else if (msg[j] & 0x80) // stolen from video.c, nice. - { - clrflag = ((msg[j] & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK; - colormap = V_GetStringColormap(clrflag); - ++j; - continue; + dy += charheight; + dx = 0; } - - ++j; + prev_linereturn = true; } - else + else if (msg[j] & 0x80) // get colormap + colormap = V_GetStringColormap(((msg[j] & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK); + else if (msg[j] >= FONTSTART) { + prev_linereturn = false; + if (cv_chatbacktint.value) // on request of wolfy V_DrawFillConsoleMap(x + dx + 2, y+dy, charwidth, charheight, 239|V_SNAPTOBOTTOM|V_SNAPTOLEFT); - V_DrawChatCharacter(x + dx + 2, y+dy, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|transflag, true, colormap); - } + V_DrawChatCharacter(x + dx + 2, y+dy, msg[j] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_MONOSPACE|transflag, true, colormap); + dx += charwidth; - dx += charwidth; - prev_linereturn = false; - if (dx >= boxw) - { - dx = 0; - dy += charheight; + if (dx >= boxw-charwidth-2) + { + dx = 0; + dy += charheight; + prev_linereturn = true; + } } } dy += charheight; @@ -1434,7 +1322,6 @@ static void HU_drawMiniChat(void) // decrement addy and make that shit smooth: addy /= 2; - } // HU_DrawChatLog @@ -1447,6 +1334,7 @@ static void HU_drawChatLog(INT32 offset) UINT32 i = 0; INT32 chat_topy, chat_bottomy; boolean atbottom = false; + boolean prev_linereturn = false; // make sure that our scroll position isn't "illegal"; if (chat_scroll > chat_maxscroll) @@ -1479,44 +1367,39 @@ static void HU_drawChatLog(INT32 offset) for (i=0; i<chat_nummsg_log; i++) // iterate through our chatlog { - INT32 clrflag = 0; - INT32 j = 0; - char *msg = CHAT_WordWrap(x+2, boxw-(charwidth*2), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, chat_log[i]); // get the current message, and word wrap it. + char *msg = V_ChatWordWrap(0, boxw-charwidth-2, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE|V_MONOSPACE, chat_log[i]); // get the current message, and word wrap it. UINT8 *colormap = NULL; - while(msg[j]) // iterate through msg + for(size_t j = 0; msg[j]; j++) // iterate through msg { - if (msg[j] < HU_FONTSTART) // don't draw + if (msg[j] == '\n') // get back down. { - if (msg[j] == '\n') // get back down. + if (!prev_linereturn) { - ++j; dy += charheight; dx = 0; - continue; - } - else if (msg[j] & 0x80) // stolen from video.c, nice. - { - clrflag = ((msg[j] & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK; - colormap = V_GetStringColormap(clrflag); - ++j; - continue; } - - ++j; + prev_linereturn = true; } + else if (msg[j] & 0x80) // get colormap + colormap = V_GetStringColormap(((msg[j] & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK); else { - if ((y+dy+2 >= chat_topy) && (y+dy < (chat_bottomy))) - V_DrawChatCharacter(x + dx + 2, y+dy+2, msg[j++] |V_SNAPTOBOTTOM|V_SNAPTOLEFT, true, colormap); - else - j++; // don't forget to increment this or we'll get stuck in the limbo. - } + prev_linereturn = false; - dx += charwidth; - if (dx >= boxw-charwidth-2 && i<chat_nummsg_log && msg[j] >= HU_FONTSTART) // end of message shouldn't count, nor should invisible characters!!!! - { - dx = 0; - dy += charheight; + if (msg[j] >= FONTSTART) + { + if ((y+dy+2 >= chat_topy) && (y+dy < (chat_bottomy))) + V_DrawChatCharacter(x + dx + 2, y+dy+2, msg[j] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_MONOSPACE, true, colormap); + + dx += charwidth; + } + + if (dx >= boxw-charwidth-2 && i < chat_nummsg_log) // end of message shouldn't count, nor should invisible characters!!!! + { + dx = 0; + dy += charheight; + prev_linereturn = true; + } } } dy += charheight; @@ -1526,30 +1409,25 @@ static void HU_drawChatLog(INT32 offset) Z_Free(msg); } - if (((chat_scroll >= chat_maxscroll) || (chat_scrollmedown)) && !(justscrolleddown || justscrolledup || chat_scrolltime)) // was already at the bottom of the page before new maxscroll calculation and was NOT scrolling. - { atbottom = true; // we should scroll - } + chat_scrollmedown = false; - // getmaxscroll through a lazy hack. We do all these loops, - // so let's not do more loops that are gonna lag the game more. :P + // getmaxscroll through a lazy hack. We do all these loops, so let's not do more loops that are gonna lag the game more. :P chat_maxscroll = max(dy / charheight - cv_chatheight.value, 0); // if we're not bound by the time, autoscroll for next frame: if (atbottom) chat_scroll = chat_maxscroll; - // draw arrows to indicate that we can (or not) scroll. - // account for Y = -1 offset in tinyfont + // draw arrows to indicate that we can (or not) scroll, accounting for Y = -1 offset in tinyfont if (chat_scroll > 0) V_DrawThinString(chatx-8, ((justscrolledup) ? (chat_topy-1) : (chat_topy)) - 1, V_SNAPTOBOTTOM | V_SNAPTOLEFT | V_YELLOWMAP, "\x1A"); // up arrow if (chat_scroll < chat_maxscroll) V_DrawThinString(chatx-8, chat_bottomy-((justscrolleddown) ? 5 : 6) - 1, V_SNAPTOBOTTOM | V_SNAPTOLEFT | V_YELLOWMAP, "\x1B"); // down arrow - justscrolleddown = false; - justscrolledup = false; + justscrolleddown = justscrolledup = false; } // @@ -1567,7 +1445,6 @@ static void HU_DrawChat(void) INT32 cflag = 0; const char *ntalk = "Say: ", *ttalk = "Team: "; const char *talk = ntalk; - const char *mute = "Chat has been muted."; #ifdef NETSPLITSCREEN if (splitscreen) @@ -1582,35 +1459,24 @@ static void HU_DrawChat(void) #endif if (teamtalk) - { talk = ttalk; -#if 0 - if (players[consoleplayer].ctfteam == 1) - t = 0x500; // Red - else if (players[consoleplayer].ctfteam == 2) - t = 0x400; // Blue -#endif - } if (CHAT_MUTE) { - talk = mute; + if (cv_mute.value) + talk = "Chat has been muted."; + else + talk = "You have been muted."; typelines = 1; cflag = V_GRAYMAP; // set text in gray if chat is muted. } V_DrawFillConsoleMap(chatx, y-1, boxw, (typelines*charheight), 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); - while (talk[i]) + for (i = 0; talk[i]; i++) { - if (talk[i] < HU_FONTSTART) - ++i; - else - { + if (talk[i] >= FONTSTART) V_DrawChatCharacter(chatx + c + 2, y, talk[i] |V_SNAPTOBOTTOM|V_SNAPTOLEFT|cflag, true, V_GetStringColormap(talk[i]|cflag)); - i++; - } - c += charwidth; } @@ -1621,13 +1487,12 @@ static void HU_DrawChat(void) return; } - i = 0; typelines = 1; if ((strlen(w_chat) == 0 || c_input == 0) && hu_tick < 4) V_DrawChatCharacter(chatx + 2 + c, y+1, '_' |V_SNAPTOBOTTOM|V_SNAPTOLEFT|t, true, NULL); - while (w_chat[i]) + for (i = 0; w_chat[i]; i++) { boolean skippedline = false; if (c_input == (i+1)) @@ -1644,14 +1509,11 @@ static void HU_DrawChat(void) } } - //Hurdler: isn't it better like that? - if (w_chat[i] < HU_FONTSTART) - ++i; - else - V_DrawChatCharacter(chatx + c + 2, y, w_chat[i++] | V_SNAPTOBOTTOM|V_SNAPTOLEFT | t, true, NULL); + if (w_chat[i] >= FONTSTART) + V_DrawChatCharacter(chatx + c + 2, y, w_chat[i] | V_SNAPTOBOTTOM|V_SNAPTOLEFT | t, true, NULL); c += charwidth; - if (c > boxw-(charwidth*2) && !skippedline) + if (c > boxw-charwidth && !skippedline) { c = 0; y += charheight; @@ -1673,47 +1535,31 @@ static void HU_DrawChat(void) } #endif - i = 0; - for(i=0; (i<MAXPLAYERS); i++) + for(i=0; i<MAXPLAYERS; i++) { // filter: (code needs optimization pls help I'm bad with C) if (w_chat[3]) { - char playernum[3]; + char playernum[3+1]; UINT32 n; // right, that's half important: (w_chat[4] may be a space since /pm0 msg is perfectly acceptable!) if ( ( ((w_chat[3] != 0) && ((w_chat[3] < '0') || (w_chat[3] > '9'))) || ((w_chat[4] != 0) && (((w_chat[4] < '0') || (w_chat[4] > '9'))))) && (w_chat[4] != ' ')) break; - strncpy(playernum, w_chat+3, 3); + strncpy(playernum, w_chat+3, sizeof(playernum)-1); + playernum[3] = 0; n = atoi(playernum); // turn that into a number // special cases: - - if ((n == 0) && !(w_chat[4] == '0')) - { - if (!(i<10)) - continue; - } - else if ((n == 1) && !(w_chat[3] == '0')) - { - if (!((i == 1) || ((i >= 10) && (i <= 19)))) - continue; - } - else if ((n == 2) && !(w_chat[3] == '0')) - { - if (!((i == 2) || ((i >= 20) && (i <= 29)))) - continue; - } - else if ((n == 3) && !(w_chat[3] == '0')) - { - if (!((i == 3) || ((i >= 30) && (i <= 31)))) - continue; - } + if ((n == 0) && !(w_chat[4] == '0') && (!(i<10))) + continue; + else if ((n == 1) && !(w_chat[3] == '0') && (!((i == 1) || ((i >= 10) && (i <= 19))))) + continue; + else if ((n == 2) && !(w_chat[3] == '0') && (!((i == 2) || ((i >= 20) && (i <= 29))))) + continue; + else if ((n == 3) && !(w_chat[3] == '0') && (!((i == 3) || ((i >= 30) && (i <= 31))))) + continue; else // general case. - { - if (i != n) - continue; - } + if (i != n) continue; } if (playeringame[i]) @@ -1744,41 +1590,22 @@ static void HU_DrawChat_Old(void) size_t i = 0; const char *ntalk = "Say: ", *ttalk = "Say-Team: "; const char *talk = ntalk; - INT32 charwidth = 8 * con_scalefactor; //(hu_font['A'-HU_FONTSTART]->width) * con_scalefactor; - INT32 charheight = 8 * con_scalefactor; //(hu_font['A'-HU_FONTSTART]->height) * con_scalefactor; + INT32 charwidth = 8 * con_scalefactor, charheight = 8 * con_scalefactor; if (teamtalk) - { talk = ttalk; -#if 0 - if (players[consoleplayer].ctfteam == 1) - t = 0x500; // Red - else if (players[consoleplayer].ctfteam == 2) - t = 0x400; // Blue -#endif - } - while (talk[i]) + for (i = 0; talk[i]; i++) { - if (talk[i] < HU_FONTSTART) - { - ++i; - //charwidth = 4 * con_scalefactor; - } - else - { - //charwidth = (hu_font[talk[i]-HU_FONTSTART]->width) * con_scalefactor; - V_DrawCharacter(HU_INPUTX + c, y, talk[i++] | cv_constextsize.value | V_NOSCALESTART, true); - } + if (talk[i] >= FONTSTART) + V_DrawCharacter(HU_INPUTX + c, y, talk[i] | cv_constextsize.value | V_NOSCALESTART, true); c += charwidth; } if ((strlen(w_chat) == 0 || c_input == 0) && hu_tick < 4) V_DrawCharacter(HU_INPUTX+c, y+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, true); - i = 0; - while (w_chat[i]) + for (i = 0; w_chat[i]; i++) { - if (c_input == (i+1) && hu_tick < 4) { INT32 cursorx = (HU_INPUTX+c+charwidth < vid.width) ? (HU_INPUTX + c + charwidth) : (HU_INPUTX); // we may have to go down. @@ -1786,17 +1613,8 @@ static void HU_DrawChat_Old(void) V_DrawCharacter(cursorx, cursory+2*con_scalefactor, '_' |cv_constextsize.value | V_NOSCALESTART|t, true); } - //Hurdler: isn't it better like that? - if (w_chat[i] < HU_FONTSTART) - { - ++i; - //charwidth = 4 * con_scalefactor; - } - else - { - //charwidth = (hu_font[w_chat[i]-HU_FONTSTART]->width) * con_scalefactor; - V_DrawCharacter(HU_INPUTX + c, y, w_chat[i++] | cv_constextsize.value | V_NOSCALESTART | t, true); - } + if (w_chat[i] >= FONTSTART) + V_DrawCharacter(HU_INPUTX + c, y, w_chat[i] | cv_constextsize.value | V_NOSCALESTART | t, true); c += charwidth; if (c >= vid.width) @@ -1805,9 +1623,6 @@ static void HU_DrawChat_Old(void) y += charheight; } } - - if (hu_tick < 4) - V_DrawCharacter(HU_INPUTX + c, y, '_' | cv_constextsize.value |V_NOSCALESTART|t, true); } // Draw crosshairs at the exact center of the view. @@ -1893,21 +1708,6 @@ static void HU_DrawCEcho(void) } } -static void HU_drawGametype(void) -{ - const char *strvalue = NULL; - - if (gametype < 0 || gametype >= gametypecount) - return; // not a valid gametype??? - - strvalue = Gametype_Names[gametype]; - - if (splitscreen) - V_DrawString(4, 184, 0, strvalue); - else - V_DrawString(4, 192, 0, strvalue); -} - // // demo info stuff // @@ -2044,76 +1844,6 @@ void HU_Drawer(void) } } -//====================================================================== -// HUD MESSAGES CLEARING FROM SCREEN -//====================================================================== - -// Clear old messages from the borders around the view window -// (only for reduced view, refresh the borders when needed) -// -// startline: y coord to start clear, -// clearlines: how many lines to clear. -// -static INT32 oldclearlines; - -void HU_Erase(void) -{ - INT32 topline, bottomline; - INT32 y, yoffset; - -#ifdef HWRENDER - // clear hud msgs on double buffer (OpenGL mode) - boolean secondframe; - static INT32 secondframelines; -#endif - - if (con_clearlines == oldclearlines && !con_hudupdate && !chat_on) - return; - -#ifdef HWRENDER - // clear the other frame in double-buffer modes - secondframe = (con_clearlines != oldclearlines); - if (secondframe) - secondframelines = oldclearlines; -#endif - - // clear the message lines that go away, so use _oldclearlines_ - bottomline = oldclearlines; - oldclearlines = con_clearlines; - if (chat_on && OLDCHAT) - if (bottomline < 8) - bottomline = 8; // only do it for consolechat. consolechat is gay. - - if (automapactive || viewwindowx == 0) // hud msgs don't need to be cleared - return; - - // software mode copies view border pattern & beveled edges from the backbuffer - if (rendermode == render_soft) - { - topline = 0; - for (y = topline, yoffset = y*vid.width; y < bottomline; y++, yoffset += vid.width) - { - if (y < viewwindowy || y >= viewwindowy + viewheight) - R_VideoErase(yoffset, vid.width); // erase entire line - else - { - R_VideoErase(yoffset, viewwindowx); // erase left border - // erase right border - R_VideoErase(yoffset + viewwindowx + viewwidth, viewwindowx); - } - } - con_hudupdate = false; // if it was set.. - } -#ifdef HWRENDER - else if (rendermode != render_none) - { - // refresh just what is needed from the view borders - HWR_DrawViewBorder(secondframelines); - con_hudupdate = secondframe; - } -#endif -} - //====================================================================== // IN-LEVEL MULTIPLAYER RANKINGS //====================================================================== @@ -2328,13 +2058,13 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer) greycheck = greycheckdef; supercheck = supercheckdef; - if (tab[i].color == skincolor_redteam) //red + if (players[tab[i].num].ctfteam == 1) //red { redplayers++; x = 14 + (BASEVIDWIDTH/2); y = (redplayers * 9) + 20; } - else if (tab[i].color == skincolor_blueteam) //blue + else if (players[tab[i].num].ctfteam == 2) //blue { blueplayers++; x = 14; @@ -2416,7 +2146,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) if (players[tab[i].num].spectator) continue; //ignore them. - if (tab[i].color == skincolor_redteam) //red + if (players[tab[i].num].ctfteam == 1) //red { if (redplayers++ > 8) { @@ -2424,7 +2154,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) break; // don't make more loops than we need to. } } - else if (tab[i].color == skincolor_blueteam) //blue + else if (players[tab[i].num].ctfteam == 2) //blue { if (blueplayers++ > 8) { @@ -2455,14 +2185,14 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) if (players[tab[i].num].spectator) continue; //ignore them. - if (tab[i].color == skincolor_redteam) //red + if (players[tab[i].num].ctfteam == 1) //red { if (redplayers++ > 8) continue; x = 32 + (BASEVIDWIDTH/2); y = (redplayers * 16) + 16; } - else if (tab[i].color == skincolor_blueteam) //blue + else if (players[tab[i].num].ctfteam == 2) //blue { if (blueplayers++ > 8) continue; @@ -2776,53 +2506,20 @@ static inline void HU_DrawSpectatorTicker(void) { int i; int length = 0, height = 174; - int totallength = 0, templength = 0; + int totallength = 0; for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].spectator) totallength += (signed)strlen(player_names[i]) * 8 + 16; - length -= (leveltime % (totallength + BASEVIDWIDTH)); - length += BASEVIDWIDTH; + length -= (leveltime % (totallength + (vid.width / vid.dup))); + length += (vid.width / vid.dup); for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].spectator) { - char *pos; - char initial[MAXPLAYERNAME+1]; - char current[MAXPLAYERNAME+1]; - - strcpy(initial, player_names[i]); - pos = initial; - - if (length >= -((signed)strlen(player_names[i]) * 8 + 16) && length <= BASEVIDWIDTH) - { - if (length < 0) - { - UINT8 eatenchars = (UINT8)(abs(length) / 8 + 1); - - if (eatenchars <= strlen(initial)) - { - // Eat one letter off the left side, - // then compensate the drawing position. - pos += eatenchars; - strcpy(current, pos); - templength = length % 8 + 8; - } - else - { - strcpy(current, " "); - templength = length; - } - } - else - { - strcpy(current, initial); - templength = length; - } - - V_DrawString(templength, height + 8, V_TRANSLUCENT|V_ALLOWLOWERCASE, current); - } + if (length >= -((signed)strlen(player_names[i]) * 8 + 16) && length <= (vid.width / vid.dup)) + V_DrawString(length, height + 8, V_TRANSLUCENT|V_ALLOWLOWERCASE|V_SNAPTOLEFT, player_names[i]); length += (signed)strlen(player_names[i]) * 8 + 16; } @@ -2839,7 +2536,8 @@ static void HU_DrawRankings(void) UINT32 whiteplayer; // draw the current gametype in the lower right - HU_drawGametype(); + if (gametype >= 0 && gametype < gametypecount) + V_DrawString(4, splitscreen ? 184 : 192, 0, Gametype_Names[gametype]); if (gametyperules & (GTR_TIMELIMIT|GTR_POINTLIMIT)) { @@ -3052,7 +2750,7 @@ void HU_DoCEcho(const char *msg) { I_OutputMsg("%s\n", msg); // print to log - strncpy(cechotext, msg, sizeof(cechotext)); + strncpy(cechotext, msg, sizeof(cechotext)-1); strncat(cechotext, "\\", sizeof(cechotext) - strlen(cechotext) - 1); cechotext[sizeof(cechotext) - 1] = '\0'; cechotimer = cechoduration; diff --git a/src/hu_stuff.h b/src/hu_stuff.h index 8647e4500cb2ce1ebf76015dbcc9031a0b5f4082..2618d873b1392b7d9ac30d0d5ea2e3e2e4cd81da 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -19,33 +19,34 @@ #include "r_defs.h" //------------------------------------ -// heads up font +// Fonts & stuff //------------------------------------ -#define HU_FONTSTART '\x16' // the first font character -#define HU_FONTEND '~' - -#define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1) - -// Level title font -#define LT_FONTSTART '!' // the first font characters -#define LT_FONTEND 'z' // the last font characters -#define LT_FONTSIZE (LT_FONTEND - LT_FONTSTART + 1) - -#define CRED_FONTSTART '!' // the first font character -#define CRED_FONTEND 'Z' // the last font character -#define CRED_FONTSIZE (CRED_FONTEND - CRED_FONTSTART + 1) - -// Name tag font -// Used by base and outline font set -#define NT_FONTSTART '!' // the first font character -#define NT_FONTEND 'Z' // the last font character -#define NT_FONTSIZE (NT_FONTEND - NT_FONTSTART + 1) +#define FONTSTART '\x16' // the first font character +#define FONTEND '~' +#define FONTSIZE (FONTEND - FONTSTART + 1) #define HU_CROSSHAIRS 3 // maximum of 9 - see HU_Init(); extern char *shiftxform; // english translation shift table extern char english_shiftxform[]; +typedef struct +{ + patch_t *chars[FONTSIZE]; + INT32 kerning; + UINT32 spacewidth; + UINT32 charwidth; + UINT32 linespacing; +} fontdef_t; + +extern fontdef_t hu_font, tny_font, cred_font, lt_font; +extern fontdef_t ntb_font, nto_font; +extern patch_t *tallnum[10]; +extern patch_t *nightsnum[10]; +extern patch_t *ttlnum[10]; +extern patch_t *tallminus; +extern patch_t *tallinfin; + //------------------------------------ // sorted player lines //------------------------------------ @@ -69,8 +70,8 @@ typedef struct #else #define OLDCHAT (cv_consolechat.value == 1 || dedicated || vid.width < 640 || splitscreen) #endif -#define CHAT_MUTE (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) // this still allows to open the chat but not to type. That's used for scrolling and whatnot. -#define OLD_MUTE (OLDCHAT && cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) // this is used to prevent oldchat from opening when muted. +#define CHAT_MUTE ((cv_mute.value || players[consoleplayer].muted) && !(server || IsPlayerAdmin(consoleplayer))) // this still allows to open the chat but not to type. That's used for scrolling and whatnot. +#define OLD_MUTE (OLDCHAT && (cv_mute.value || players[consoleplayer].muted) && !(server || IsPlayerAdmin(consoleplayer))) // this is used to prevent oldchat from opening when muted. // some functions void HU_AddChatText(const char *text, boolean playsound); @@ -78,22 +79,15 @@ void HU_AddChatText(const char *text, boolean playsound); // set true when entering a chat message extern boolean chat_on; -extern patch_t *hu_font[HU_FONTSIZE], *tny_font[HU_FONTSIZE]; -extern patch_t *tallnum[10]; -extern patch_t *nightsnum[10]; -extern patch_t *lt_font[LT_FONTSIZE]; -extern patch_t *cred_font[CRED_FONTSIZE]; -extern patch_t *ntb_font[NT_FONTSIZE]; -extern patch_t *nto_font[NT_FONTSIZE]; -extern patch_t *ttlnum[10]; +extern UINT8 spam_tokens[MAXPLAYERS]; +extern tic_t spam_tics[MAXPLAYERS]; + extern patch_t *emeraldpics[3][8]; extern patch_t *rflagico; extern patch_t *bflagico; extern patch_t *rmatcico; extern patch_t *bmatcico; extern patch_t *tagico; -extern patch_t *tallminus; -extern patch_t *tallinfin; extern patch_t *tokenicon; // set true whenever the tab rankings are being shown for any reason @@ -103,6 +97,8 @@ extern boolean hu_showscores; void HU_Init(void); void HU_LoadGraphics(void); +void HU_LoadFontCharacters(fontdef_t *font, const char *prefix); +void HU_SetFontProperties(fontdef_t *font, INT32 kerning, UINT32 spacewidth, UINT32 charwidth, UINT32 linespacing); // reset heads up when consoleplayer respawns. void HU_Start(void); @@ -111,7 +107,6 @@ boolean HU_Responder(event_t *ev); void HU_Ticker(void); void HU_Drawer(void); char HU_dequeueChatChar(void); -void HU_Erase(void); void HU_clearChatChars(void); void HU_drawPing(INT32 x, INT32 y, UINT32 ping, boolean notext, INT32 flags); // Lat': Ping drawer for scoreboard. void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer); diff --git a/src/i_system.h b/src/i_system.h index 834dd4091487b295fd1faed9d11018e498d79b12..5348caf4d39e72575c17ecdf4d2c7825bf5fb3c4 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -335,4 +335,16 @@ void I_GetCursorPosition(INT32 *x, INT32 *y); */ void I_SetMouseGrab(boolean grab); +/** \brief Returns the system name. +*/ +const char *I_GetSysName(void); + +/** \brief Sets text input mode. When enabled, keyboard inputs will respect dead keys. + */ +void I_SetTextInputMode(boolean active); + +/** \brief Retrieves current text input mode. + */ +boolean I_GetTextInputMode(void); + #endif diff --git a/src/i_video.h b/src/i_video.h index 8efca5f9ab28da6312755d9e11a6c8791149f26b..f3bbc90b92a61215f1421a5ca4c074cd85ae0875 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -40,10 +40,6 @@ extern rendermode_t rendermode; */ extern rendermode_t chosenrendermode; -/** \brief use highcolor modes if true -*/ -extern boolean highcolor; - /** \brief setup video mode */ void I_StartupGraphics(void); @@ -108,8 +104,8 @@ void VID_CheckGLLoaded(rendermode_t oldrender); \return name of video mode */ const char *VID_GetModeName(INT32 modenum); -void VID_PrepareModeList(void); /// note hack for SDL +void VID_PrepareModeList(void); /** \brief can video system do fullscreen */ diff --git a/src/info.c b/src/info.c index 5790dd7c56ce3ee5f625f63581903a6d185a3a73..4d3468e10fac23edeeea539cdac550ad9ab6057a 100644 --- a/src/info.c +++ b/src/info.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -26,9 +26,10 @@ #include "hardware/hw_light.h" #endif + // Hey, moron! If you change this table, don't forget about the sprite enum in info.h and the sprite lights in hw_light.c! // For the sake of constant merge conflicts, let's spread this out -char sprnames[NUMSPRITES + 1][5] = +char sprnames[NUMSPRITES + 1][MAXSPRITENAME + 1] = { "NULL", // invisible object "UNKN", @@ -305,6 +306,8 @@ char sprnames[NUMSPRITES + 1][5] = "XMS4", // Lamppost "XMS5", // Hanging Star "XMS6", // Mistletoe + "SNTT", // Silver Shiver tree + "SSTT", // Silver Shiver tree with snow "FHZI", // FHZ ice "ROSY", @@ -338,6 +341,8 @@ char sprnames[NUMSPRITES + 1][5] = // Misc Scenery "STLG", // Stalagmites "DBAL", // Disco + "GINE", // Crystalline Heights tree + "PPAL", // Pristine Shores palm trees // Powerup Indicators "ARMA", // Armageddon Shield Orb @@ -523,9 +528,12 @@ char sprnames[NUMSPRITES + 1][5] = // Gravity Well Objects "GWLG", "GWLR", + + // LJ Knuckles + "OLDK", }; -char spr2names[NUMPLAYERSPRITES][5] = +char spr2names[NUMPLAYERSPRITES][MAXSPRITENAME + 1] = { "STND", "WAIT", @@ -592,6 +600,17 @@ char spr2names[NUMPLAYERSPRITES][5] = "TALB", "TALC", + "MSC0", + "MSC1", + "MSC2", + "MSC3", + "MSC4", + "MSC5", + "MSC6", + "MSC7", + "MSC8", + "MSC9", + "CNT1", "CNT2", "CNT3", @@ -648,13 +667,13 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { 0, // SPR2_TRNS, - FF_SPR2SUPER|SPR2_STND, // SPR2_NSTD, - FF_SPR2SUPER|SPR2_FALL, // SPR2_NFLT, + SPR2_STND, // SPR2_NSTD, + SPR2_FALL, // SPR2_NFLT, 0, // SPR2_NFLY, (will never be referenced unless skin 0 lacks this) SPR2_NFLY, // SPR2_NDRL, - FF_SPR2SUPER|SPR2_STUN, // SPR2_NSTN, + SPR2_STUN, // SPR2_NSTN, SPR2_NSTN, // SPR2_NPUL, - FF_SPR2SUPER|SPR2_ROLL, // SPR2_NATK, + SPR2_ROLL, // SPR2_NATK, 0, // SPR2_TAL0, (this will look mighty stupid but oh well) SPR2_TAL0, // SPR2_TAL1, @@ -670,6 +689,17 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { SPR2_TAL0, // SPR2_TALB, SPR2_TAL6, // SPR2_TALC, + 0, // SPR2_MSC0, + 0, // SPR2_MSC1, + 0, // SPR2_MSC2, + 0, // SPR2_MSC3, + 0, // SPR2_MSC4, + 0, // SPR2_MSC5, + 0, // SPR2_MSC6, + 0, // SPR2_MSC7, + 0, // SPR2_MSC8, + 0, // SPR2_MSC9, + SPR2_WAIT, // SPR2_CNT1, SPR2_FALL, // SPR2_CNT2, SPR2_SPNG, // SPR2_CNT3, @@ -691,3309 +721,3322 @@ state_t states[NUMSTATES] = // (or tr_trans10<<FF_TRANSSHIFT if you want to make it hard on yourself) // Keep this comment directly above S_NULL. - {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NULL - {SPR_UNKN, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_UNKNOWN - {SPR_NULL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_INVISIBLE - - {SPR_UNKN, FF_FULLBRIGHT, -1, {A_InfoState}, 0, 0, S_NULL}, // S_SPAWNSTATE - {SPR_UNKN, FF_FULLBRIGHT, -1, {A_InfoState}, 1, 0, S_NULL}, // S_SEESTATE - {SPR_UNKN, FF_FULLBRIGHT, -1, {A_InfoState}, 2, 0, S_NULL}, // S_MELEESTATE - {SPR_UNKN, FF_FULLBRIGHT, -1, {A_InfoState}, 3, 0, S_NULL}, // S_MISSILESTATE - {SPR_UNKN, FF_FULLBRIGHT, -1, {A_InfoState}, 4, 0, S_NULL}, // S_DEATHSTATE - {SPR_UNKN, FF_FULLBRIGHT, -1, {A_InfoState}, 5, 0, S_NULL}, // S_XDEATHSTATE - {SPR_UNKN, FF_FULLBRIGHT, -1, {A_InfoState}, 6, 0, S_NULL}, // S_RAISESTATE + {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL, 0}, // S_NULL + {SPR_UNKN, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL, 0}, // S_UNKNOWN + {SPR_NULL, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_INVISIBLE + + {SPR_UNKN, FF_FULLBRIGHT, -1, {A_InfoState}, 0, 0, S_NULL, 0}, // S_SPAWNSTATE + {SPR_UNKN, FF_FULLBRIGHT, -1, {A_InfoState}, 1, 0, S_NULL, 0}, // S_SEESTATE + {SPR_UNKN, FF_FULLBRIGHT, -1, {A_InfoState}, 2, 0, S_NULL, 0}, // S_MELEESTATE + {SPR_UNKN, FF_FULLBRIGHT, -1, {A_InfoState}, 3, 0, S_NULL, 0}, // S_MISSILESTATE + {SPR_UNKN, FF_FULLBRIGHT, -1, {A_InfoState}, 4, 0, S_NULL, 0}, // S_DEATHSTATE + {SPR_UNKN, FF_FULLBRIGHT, -1, {A_InfoState}, 5, 0, S_NULL, 0}, // S_XDEATHSTATE + {SPR_UNKN, FF_FULLBRIGHT, -1, {A_InfoState}, 6, 0, S_NULL, 0}, // S_RAISESTATE // Thok - {SPR_THOK, FF_TRANS50, 8, {NULL}, 0, 0, S_NULL}, // S_THOK + {SPR_THOK, FF_TRANS50, 8, {NULL}, 0, 0, S_NULL, 0}, // S_THOK // Player - {SPR_PLAY, SPR2_STND|FF_ANIMATE, 105, {NULL}, 0, 7, S_PLAY_WAIT}, // S_PLAY_STND - {SPR_PLAY, SPR2_WAIT|FF_ANIMATE, -1, {NULL}, 0, 16, S_NULL}, // S_PLAY_WAIT - {SPR_PLAY, SPR2_WALK, 4, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_WALK - {SPR_PLAY, SPR2_SKID, 1, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_SKID - {SPR_PLAY, SPR2_RUN , 2, {NULL}, 0, 0, S_PLAY_RUN}, // S_PLAY_RUN - {SPR_PLAY, SPR2_DASH, 2, {NULL}, 0, 0, S_PLAY_DASH}, // S_PLAY_DASH - {SPR_PLAY, SPR2_PAIN|FF_ANIMATE, 350, {NULL}, 0, 4, S_PLAY_FALL}, // S_PLAY_PAIN - {SPR_PLAY, SPR2_STUN|FF_ANIMATE, 350, {NULL}, 0, 4, S_PLAY_FALL}, // S_PLAY_STUN - {SPR_PLAY, SPR2_DEAD|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL}, // S_PLAY_DEAD - {SPR_PLAY, SPR2_DRWN|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL}, // S_PLAY_DRWN - {SPR_PLAY, SPR2_ROLL, 1, {NULL}, 0, 0, S_PLAY_ROLL}, // S_PLAY_ROLL - {SPR_PLAY, SPR2_GASP|FF_ANIMATE, 14, {NULL}, 0, 4, S_PLAY_WALK}, // S_PLAY_GASP - {SPR_PLAY, SPR2_JUMP, 1, {NULL}, 0, 0, S_PLAY_JUMP}, // S_PLAY_JUMP - {SPR_PLAY, SPR2_SPNG, 2, {NULL}, 0, 0, S_PLAY_SPRING}, // S_PLAY_SPRING - {SPR_PLAY, SPR2_FALL, 2, {NULL}, 0, 0, S_PLAY_FALL}, // S_PLAY_FALL - {SPR_PLAY, SPR2_EDGE, 12, {NULL}, 0, 0, S_PLAY_EDGE}, // S_PLAY_EDGE - {SPR_PLAY, SPR2_RIDE, 4, {NULL}, 0, 0, S_PLAY_RIDE}, // S_PLAY_RIDE + {SPR_PLAY, SPR2_STND|FF_ANIMATE, 105, {NULL}, 0, 7, S_PLAY_WAIT, 0}, // S_PLAY_STND + {SPR_PLAY, SPR2_WAIT, 16, {NULL}, 0, 0, S_PLAY_WAIT, 0}, // S_PLAY_WAIT + {SPR_PLAY, SPR2_WALK, 4, {NULL}, 0, 0, S_PLAY_WALK, 0}, // S_PLAY_WALK + {SPR_PLAY, SPR2_SKID, 1, {NULL}, 0, 0, S_PLAY_WALK, 0}, // S_PLAY_SKID + {SPR_PLAY, SPR2_RUN , 2, {NULL}, 0, 0, S_PLAY_RUN, 0}, // S_PLAY_RUN + {SPR_PLAY, SPR2_DASH, 2, {NULL}, 0, 0, S_PLAY_DASH, 0}, // S_PLAY_DASH + {SPR_PLAY, SPR2_PAIN|FF_ANIMATE, 350, {NULL}, 0, 4, S_PLAY_FALL, 0}, // S_PLAY_PAIN + {SPR_PLAY, SPR2_STUN|FF_ANIMATE, 350, {NULL}, 0, 4, S_PLAY_FALL, 0}, // S_PLAY_STUN + {SPR_PLAY, SPR2_DEAD|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL, 0}, // S_PLAY_DEAD + {SPR_PLAY, SPR2_DRWN|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL, 0}, // S_PLAY_DRWN + {SPR_PLAY, SPR2_ROLL, 1, {NULL}, 0, 0, S_PLAY_ROLL, 0}, // S_PLAY_ROLL + {SPR_PLAY, SPR2_GASP|FF_ANIMATE, 14, {NULL}, 0, 4, S_PLAY_WALK, 0}, // S_PLAY_GASP + {SPR_PLAY, SPR2_JUMP, 1, {NULL}, 0, 0, S_PLAY_JUMP, 0}, // S_PLAY_JUMP + {SPR_PLAY, SPR2_SPNG, 2, {NULL}, 0, 0, S_PLAY_SPRING, 0}, // S_PLAY_SPRING + {SPR_PLAY, SPR2_FALL, 2, {NULL}, 0, 0, S_PLAY_FALL, 0}, // S_PLAY_FALL + {SPR_PLAY, SPR2_EDGE, 12, {NULL}, 0, 0, S_PLAY_EDGE, 0}, // S_PLAY_EDGE + {SPR_PLAY, SPR2_RIDE, 4, {NULL}, 0, 0, S_PLAY_RIDE, 0}, // S_PLAY_RIDE // CA2_SPINDASH - {SPR_PLAY, SPR2_SPIN, 2, {NULL}, 0, 0, S_PLAY_SPINDASH}, // S_PLAY_SPINDASH + {SPR_PLAY, SPR2_SPIN, 2, {NULL}, 0, 0, S_PLAY_SPINDASH, 0}, // S_PLAY_SPINDASH // CA_FLY/CA_SWIM - {SPR_PLAY, SPR2_FLY , 2, {NULL}, 0, 0, S_PLAY_FLY}, // S_PLAY_FLY - {SPR_PLAY, SPR2_SWIM, 4, {NULL}, 0, 0, S_PLAY_SWIM}, // S_PLAY_SWIM - {SPR_PLAY, SPR2_TIRE, 12, {NULL}, 0, 0, S_PLAY_FLY_TIRED}, // S_PLAY_FLY_TIRED + {SPR_PLAY, SPR2_FLY , 2, {NULL}, 0, 0, S_PLAY_FLY, 0}, // S_PLAY_FLY + {SPR_PLAY, SPR2_SWIM, 4, {NULL}, 0, 0, S_PLAY_SWIM, 0}, // S_PLAY_SWIM + {SPR_PLAY, SPR2_TIRE, 12, {NULL}, 0, 0, S_PLAY_FLY_TIRED, 0}, // S_PLAY_FLY_TIRED // CA_GLIDEANDCLIMB - {SPR_PLAY, SPR2_GLID, 2, {NULL}, 0, 0, S_PLAY_GLIDE}, // S_PLAY_GLIDE - {SPR_PLAY, SPR2_LAND, 7, {NULL}, 0, 0, S_PLAY_STND}, // S_PLAY_GLIDE_LANDING - {SPR_PLAY, SPR2_CLNG|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL}, // S_PLAY_CLING - {SPR_PLAY, SPR2_CLMB, 5, {NULL}, 0, 0, S_PLAY_CLIMB}, // S_PLAY_CLIMB + {SPR_PLAY, SPR2_GLID, 2, {NULL}, 0, 0, S_PLAY_GLIDE, 0}, // S_PLAY_GLIDE + {SPR_PLAY, SPR2_LAND, 7, {NULL}, 0, 0, S_PLAY_STND, 0}, // S_PLAY_GLIDE_LANDING + {SPR_PLAY, SPR2_CLNG|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL, 0}, // S_PLAY_CLING + {SPR_PLAY, SPR2_CLMB, 5, {NULL}, 0, 0, S_PLAY_CLIMB, 0}, // S_PLAY_CLIMB // CA_FLOAT/CA_SLOWFALL - {SPR_PLAY, SPR2_FLT , 7, {NULL}, 0, 0, S_PLAY_FLOAT}, // S_PLAY_FLOAT - {SPR_PLAY, SPR2_FRUN, 7, {NULL}, 0, 0, S_PLAY_FLOAT_RUN}, // S_PLAY_FLOAT_RUN + {SPR_PLAY, SPR2_FLT , 7, {NULL}, 0, 0, S_PLAY_FLOAT, 0}, // S_PLAY_FLOAT + {SPR_PLAY, SPR2_FRUN, 7, {NULL}, 0, 0, S_PLAY_FLOAT_RUN, 0}, // S_PLAY_FLOAT_RUN // CA_BOUNCE - {SPR_PLAY, SPR2_BNCE|FF_ANIMATE, -1, {NULL}, 0, 0, S_NULL}, // S_PLAY_BOUNCE - {SPR_PLAY, SPR2_LAND|FF_SPR2ENDSTATE, 2, {NULL}, S_PLAY_BOUNCE, 0, S_PLAY_BOUNCE_LANDING}, // S_PLAY_BOUNCE_LANDING + {SPR_PLAY, SPR2_BNCE|FF_ANIMATE, -1, {NULL}, 0, 0, S_NULL, 0}, // S_PLAY_BOUNCE + {SPR_PLAY, SPR2_LAND|FF_SPR2ENDSTATE, 2, {NULL}, S_PLAY_BOUNCE, 0, S_PLAY_BOUNCE_LANDING, 0}, // S_PLAY_BOUNCE_LANDING // CA2_GUNSLINGER - {SPR_PLAY, SPR2_FIRE|FF_SPR2ENDSTATE, 2, {NULL}, S_PLAY_FIRE_FINISH, 0, S_PLAY_FIRE}, // S_PLAY_FIRE - {SPR_PLAY, SPR2_FIRE, 15, {NULL}, S_PLAY_STND, 0, S_PLAY_STND}, // S_PLAY_FIRE_FINISH + {SPR_PLAY, SPR2_FIRE|FF_SPR2ENDSTATE, 2, {NULL}, S_PLAY_FIRE_FINISH, 0, S_PLAY_FIRE, 0}, // S_PLAY_FIRE + {SPR_PLAY, SPR2_FIRE, 15, {NULL}, S_PLAY_STND, 0, S_PLAY_STND, 0}, // S_PLAY_FIRE_FINISH // CA_TWINSPIN - {SPR_PLAY, SPR2_TWIN|FF_SPR2ENDSTATE, 2, {NULL}, S_PLAY_JUMP, 0, S_PLAY_TWINSPIN}, // S_PLAY_TWINSPIN + {SPR_PLAY, SPR2_TWIN|FF_SPR2ENDSTATE, 2, {NULL}, S_PLAY_JUMP, 0, S_PLAY_TWINSPIN, 0}, // S_PLAY_TWINSPIN // CA2_MELEE - {SPR_PLAY, SPR2_MLEE|FF_SPR2ENDSTATE, 2, {NULL}, S_PLAY_MELEE_FINISH, 0, S_PLAY_MELEE}, // S_PLAY_MELEE - {SPR_PLAY, SPR2_MLEE, 70, {NULL}, 0, 0, S_PLAY_FALL}, // S_PLAY_MELEE_FINISH - {SPR_PLAY, SPR2_MLEL, 35, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_MELEE_LANDING + {SPR_PLAY, SPR2_MLEE|FF_SPR2ENDSTATE, 2, {NULL}, S_PLAY_MELEE_FINISH, 0, S_PLAY_MELEE, 0}, // S_PLAY_MELEE + {SPR_PLAY, SPR2_MLEE, 70, {NULL}, 0, 0, S_PLAY_FALL, 0}, // S_PLAY_MELEE_FINISH + {SPR_PLAY, SPR2_MLEL, 35, {NULL}, 0, 0, S_PLAY_WALK, 0}, // S_PLAY_MELEE_LANDING // SF_SUPER - {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER|FF_ANIMATE, 7, {NULL}, 0, 4, S_PLAY_SUPER_TRANS2}, // S_PLAY_SUPER_TRANS1 - {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS3}, // S_PLAY_SUPER_TRANS2 - {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_PLAY_SUPER_TRANS4}, // S_PLAY_SUPER_TRANS3 - {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_PLAY_SUPER_TRANS5}, // S_PLAY_SUPER_TRANS4 - {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_PLAY_SUPER_TRANS6}, // S_PLAY_SUPER_TRANS5 - {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER|FF_FULLBRIGHT, 19, {A_FadeOverlay}, 0, 0, S_PLAY_FALL}, // S_PLAY_SUPER_TRANS6 + {SPR_PLAY, SPR2_TRNS|SPR2F_SUPER|FF_ANIMATE, 7, {NULL}, 0, 4, S_PLAY_SUPER_TRANS2, 0}, // S_PLAY_SUPER_TRANS1 + {SPR_PLAY, SPR2_TRNS|SPR2F_SUPER, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS3, 0}, // S_PLAY_SUPER_TRANS2 + {SPR_PLAY, SPR2_TRNS|SPR2F_SUPER|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_PLAY_SUPER_TRANS4, 0}, // S_PLAY_SUPER_TRANS3 + {SPR_PLAY, SPR2_TRNS|SPR2F_SUPER|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_PLAY_SUPER_TRANS5, 0}, // S_PLAY_SUPER_TRANS4 + {SPR_PLAY, SPR2_TRNS|SPR2F_SUPER|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_PLAY_SUPER_TRANS6, 0}, // S_PLAY_SUPER_TRANS5 + {SPR_PLAY, SPR2_TRNS|SPR2F_SUPER|FF_FULLBRIGHT, 19, {A_FadeOverlay}, 0, 0, S_PLAY_FALL, 0}, // S_PLAY_SUPER_TRANS6 - {SPR_NULL, 0, -1, {NULL}, 0, 0, S_OBJPLACE_DUMMY}, //S_OBJPLACE_DUMMY + {SPR_NULL, 0, -1, {NULL}, 0, 0, S_OBJPLACE_DUMMY, 0}, //S_OBJPLACE_DUMMY // 1-Up box sprites (uses player sprite) - {SPR_PLAY, SPR2_LIFE, 2, {NULL}, 0, 18, S_PLAY_BOX2}, // S_PLAY_BOX1 - {SPR_NULL, 0, 1, {NULL}, 0, 18, S_PLAY_BOX1}, // S_PLAY_BOX2 - {SPR_PLAY, SPR2_LIFE, 4, {NULL}, 0, 4, S_PLAY_ICON2}, // S_PLAY_ICON1 - {SPR_NULL, 0, 12, {NULL}, 0, 4, S_PLAY_ICON3}, // S_PLAY_ICON2 - {SPR_PLAY, SPR2_LIFE, 20, {NULL}, 0, 4, S_NULL}, // S_PLAY_ICON3 + {SPR_PLAY, SPR2_LIFE, 2, {NULL}, 0, 18, S_PLAY_BOX2, 0}, // S_PLAY_BOX1 + {SPR_NULL, 0, 1, {NULL}, 0, 18, S_PLAY_BOX1, 0}, // S_PLAY_BOX2 + {SPR_PLAY, SPR2_LIFE, 4, {NULL}, 0, 4, S_PLAY_ICON2, 0}, // S_PLAY_ICON1 + {SPR_NULL, 0, 12, {NULL}, 0, 4, S_PLAY_ICON3, 0}, // S_PLAY_ICON2 + {SPR_PLAY, SPR2_LIFE, 20, {NULL}, 0, 4, S_NULL, 0}, // S_PLAY_ICON3 // Level end sign (uses player sprite) - {SPR_PLAY, SPR2_SIGN|FF_PAPERSPRITE, 2, {NULL}, 0, 29, S_PLAY_SIGN}, // S_PLAY_SIGN + {SPR_PLAY, SPR2_SIGN|FF_PAPERSPRITE, 2, {NULL}, 0, 29, S_PLAY_SIGN, 0}, // S_PLAY_SIGN // NiGHTS Player, transforming - {SPR_PLAY, SPR2_TRNS|FF_ANIMATE, 7, {NULL}, 0, 4, S_PLAY_NIGHTS_TRANS2}, // S_PLAY_NIGHTS_TRANS1 - {SPR_PLAY, SPR2_TRNS, 3, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS3}, // S_PLAY_NIGHTS_TRANS2 - {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS4}, // S_PLAY_NIGHTS_TRANS3 - {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS5}, // S_PLAY_NIGHTS_TRANS4 - {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS6}, // S_PLAY_NIGHTS_TRANS5 - {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 21, {A_FadeOverlay}, 2, 0, S_PLAY_NIGHTS_FLOAT}, // S_PLAY_NIGHTS_TRANS5 + {SPR_PLAY, SPR2_TRNS|FF_ANIMATE, 7, {NULL}, 0, 4, S_PLAY_NIGHTS_TRANS2, 0}, // S_PLAY_NIGHTS_TRANS1 + {SPR_PLAY, SPR2_TRNS, 3, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS3, 0}, // S_PLAY_NIGHTS_TRANS2 + {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS4, 0}, // S_PLAY_NIGHTS_TRANS3 + {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS5, 0}, // S_PLAY_NIGHTS_TRANS4 + {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS6, 0}, // S_PLAY_NIGHTS_TRANS5 + {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 21, {A_FadeOverlay}, 2, 0, S_PLAY_NIGHTS_FLOAT, 0}, // S_PLAY_NIGHTS_TRANS5 // NiGHTS Player - {SPR_PLAY, SPR2_NSTD, 7, {NULL}, 0, 0, S_PLAY_NIGHTS_STAND}, // S_PLAY_NIGHTS_STAND - {SPR_PLAY, SPR2_NFLT, 7, {NULL}, 0, 0, S_PLAY_NIGHTS_FLOAT}, // S_PLAY_NIGHTS_FLOAT - {SPR_PLAY, SPR2_NFLY, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLY}, // S_PLAY_NIGHTS_FLY - {SPR_PLAY, SPR2_NDRL, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILL}, // S_PLAY_NIGHTS_DRILL - {SPR_PLAY, SPR2_NSTN, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_STUN}, // S_PLAY_NIGHTS_STUN - {SPR_PLAY, SPR2_NPUL, 1, {NULL}, 0, 0, S_PLAY_NIGHTS_PULL}, // S_PLAY_NIGHTS_PULL - {SPR_PLAY, SPR2_NATK, 1, {NULL}, 0, 0, S_PLAY_NIGHTS_ATTACK}, // S_PLAY_NIGHTS_ATTACK + {SPR_PLAY, SPR2_NSTD, 7, {NULL}, 0, 0, S_PLAY_NIGHTS_STAND, 0}, // S_PLAY_NIGHTS_STAND + {SPR_PLAY, SPR2_NFLT, 7, {NULL}, 0, 0, S_PLAY_NIGHTS_FLOAT, 0}, // S_PLAY_NIGHTS_FLOAT + {SPR_PLAY, SPR2_NFLY, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLY, 0}, // S_PLAY_NIGHTS_FLY + {SPR_PLAY, SPR2_NDRL, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILL, 0}, // S_PLAY_NIGHTS_DRILL + {SPR_PLAY, SPR2_NSTN, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_STUN, 0}, // S_PLAY_NIGHTS_STUN + {SPR_PLAY, SPR2_NPUL, 1, {NULL}, 0, 0, S_PLAY_NIGHTS_PULL, 0}, // S_PLAY_NIGHTS_PULL + {SPR_PLAY, SPR2_NATK, 1, {NULL}, 0, 0, S_PLAY_NIGHTS_ATTACK, 0}, // S_PLAY_NIGHTS_ATTACK // c: - {SPR_PLAY, SPR2_TAL0|FF_SPR2MIDSTART, 5, {NULL}, 0, 0, S_TAILSOVERLAY_STAND}, // S_TAILSOVERLAY_STAND - {SPR_PLAY, SPR2_TAL1|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_0DEGREES}, // S_TAILSOVERLAY_0DEGREES - {SPR_PLAY, SPR2_TAL2|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_PLUS30DEGREES}, // S_TAILSOVERLAY_PLUS30DEGREES - {SPR_PLAY, SPR2_TAL3|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_PLUS60DEGREES}, // S_TAILSOVERLAY_PLUS60DEGREES - {SPR_PLAY, SPR2_TAL4|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_MINUS30DEGREES}, // S_TAILSOVERLAY_MINUS30DEGREES - {SPR_PLAY, SPR2_TAL5|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_MINUS60DEGREES}, // S_TAILSOVERLAY_MINUS60DEGREES - {SPR_PLAY, SPR2_TAL6|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_RUN}, // S_TAILSOVERLAY_RUN - {SPR_PLAY, SPR2_TAL7|FF_SPR2MIDSTART, 4, {NULL}, 0, 0, S_TAILSOVERLAY_FLY}, // S_TAILSOVERLAY_FLY - {SPR_PLAY, SPR2_TAL8|FF_SPR2MIDSTART, 4, {NULL}, 0, 0, S_TAILSOVERLAY_TIRE}, // S_TAILSOVERLAY_TIRE - {SPR_PLAY, SPR2_TAL9|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_PAIN}, // S_TAILSOVERLAY_PAIN - {SPR_PLAY, SPR2_TALA|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_GASP}, // S_TAILSOVERLAY_GASP - {SPR_PLAY, SPR2_TALB , 35, {NULL}, 0, 0, S_TAILSOVERLAY_EDGE}, // S_TAILSOVERLAY_EDGE - {SPR_PLAY, SPR2_TALC|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_DASH}, // S_TAILSOVERLAY_DASH + {SPR_PLAY, SPR2_TAL0|FF_SPR2MIDSTART, 5, {NULL}, 0, 0, S_TAILSOVERLAY_STAND, 0}, // S_TAILSOVERLAY_STAND + {SPR_PLAY, SPR2_TAL1|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_0DEGREES, 0}, // S_TAILSOVERLAY_0DEGREES + {SPR_PLAY, SPR2_TAL2|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_PLUS30DEGREES, 0}, // S_TAILSOVERLAY_PLUS30DEGREES + {SPR_PLAY, SPR2_TAL3|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_PLUS60DEGREES, 0}, // S_TAILSOVERLAY_PLUS60DEGREES + {SPR_PLAY, SPR2_TAL4|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_MINUS30DEGREES, 0}, // S_TAILSOVERLAY_MINUS30DEGREES + {SPR_PLAY, SPR2_TAL5|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_MINUS60DEGREES, 0}, // S_TAILSOVERLAY_MINUS60DEGREES + {SPR_PLAY, SPR2_TAL6|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_RUN, 0}, // S_TAILSOVERLAY_RUN + {SPR_PLAY, SPR2_TAL7|FF_SPR2MIDSTART, 4, {NULL}, 0, 0, S_TAILSOVERLAY_FLY, 0}, // S_TAILSOVERLAY_FLY + {SPR_PLAY, SPR2_TAL8|FF_SPR2MIDSTART, 4, {NULL}, 0, 0, S_TAILSOVERLAY_TIRE, 0}, // S_TAILSOVERLAY_TIRE + {SPR_PLAY, SPR2_TAL9|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_PAIN, 0}, // S_TAILSOVERLAY_PAIN + {SPR_PLAY, SPR2_TALA|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_GASP, 0}, // S_TAILSOVERLAY_GASP + {SPR_PLAY, SPR2_TALB , 35, {NULL}, 0, 0, S_TAILSOVERLAY_EDGE, 0}, // S_TAILSOVERLAY_EDGE + {SPR_PLAY, SPR2_TALC|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_DASH, 0}, // S_TAILSOVERLAY_DASH // [: - {SPR_JETF, 3|FF_ANIMATE|FF_FULLBRIGHT, 2, {NULL}, 1, 1, S_JETFUME1}, // S_JETFUMEFLASH + {SPR_JETF, 3|FF_ANIMATE|FF_FULLBRIGHT, 2, {NULL}, 1, 1, S_JETFUME1, 0}, // S_JETFUMEFLASH // Blue Crawla - {SPR_POSS, 0, 5, {A_Look}, 0, 0, S_POSS_STND}, // S_POSS_STND - {SPR_POSS, 0, 3, {A_Chase}, 0, 0, S_POSS_RUN2}, // S_POSS_RUN1 - {SPR_POSS, 1, 3, {A_Chase}, 0, 0, S_POSS_RUN3}, // S_POSS_RUN2 - {SPR_POSS, 2, 3, {A_Chase}, 0, 0, S_POSS_RUN4}, // S_POSS_RUN3 - {SPR_POSS, 3, 3, {A_Chase}, 0, 0, S_POSS_RUN5}, // S_POSS_RUN4 - {SPR_POSS, 4, 3, {A_Chase}, 0, 0, S_POSS_RUN6}, // S_POSS_RUN5 - {SPR_POSS, 5, 3, {A_Chase}, 0, 0, S_POSS_RUN1}, // S_POSS_RUN6 + {SPR_POSS, 0, 5, {A_Look}, 0, 0, S_POSS_STND, 0}, // S_POSS_STND + {SPR_POSS, 0, 3, {A_Chase}, 0, 0, S_POSS_RUN2, 0}, // S_POSS_RUN1 + {SPR_POSS, 1, 3, {A_Chase}, 0, 0, S_POSS_RUN3, 0}, // S_POSS_RUN2 + {SPR_POSS, 2, 3, {A_Chase}, 0, 0, S_POSS_RUN4, 0}, // S_POSS_RUN3 + {SPR_POSS, 3, 3, {A_Chase}, 0, 0, S_POSS_RUN5, 0}, // S_POSS_RUN4 + {SPR_POSS, 4, 3, {A_Chase}, 0, 0, S_POSS_RUN6, 0}, // S_POSS_RUN5 + {SPR_POSS, 5, 3, {A_Chase}, 0, 0, S_POSS_RUN1, 0}, // S_POSS_RUN6 // Red Crawla - {SPR_SPOS, 0, 5, {A_Look}, 0, 0, S_SPOS_STND}, // S_SPOS_STND - {SPR_SPOS, 0, 1, {A_Chase}, 0, 0, S_SPOS_RUN2}, // S_SPOS_RUN1 - {SPR_SPOS, 1, 1, {A_Chase}, 0, 0, S_SPOS_RUN3}, // S_SPOS_RUN2 - {SPR_SPOS, 2, 1, {A_Chase}, 0, 0, S_SPOS_RUN4}, // S_SPOS_RUN3 - {SPR_SPOS, 3, 1, {A_Chase}, 0, 0, S_SPOS_RUN5}, // S_SPOS_RUN4 - {SPR_SPOS, 4, 1, {A_Chase}, 0, 0, S_SPOS_RUN6}, // S_SPOS_RUN5 - {SPR_SPOS, 5, 1, {A_Chase}, 0, 0, S_SPOS_RUN1}, // S_SPOS_RUN6 + {SPR_SPOS, 0, 5, {A_Look}, 0, 0, S_SPOS_STND, 0}, // S_SPOS_STND + {SPR_SPOS, 0, 1, {A_Chase}, 0, 0, S_SPOS_RUN2, 0}, // S_SPOS_RUN1 + {SPR_SPOS, 1, 1, {A_Chase}, 0, 0, S_SPOS_RUN3, 0}, // S_SPOS_RUN2 + {SPR_SPOS, 2, 1, {A_Chase}, 0, 0, S_SPOS_RUN4, 0}, // S_SPOS_RUN3 + {SPR_SPOS, 3, 1, {A_Chase}, 0, 0, S_SPOS_RUN5, 0}, // S_SPOS_RUN4 + {SPR_SPOS, 4, 1, {A_Chase}, 0, 0, S_SPOS_RUN6, 0}, // S_SPOS_RUN5 + {SPR_SPOS, 5, 1, {A_Chase}, 0, 0, S_SPOS_RUN1, 0}, // S_SPOS_RUN6 // Greenflower Fish - {SPR_FISH, 1, 1, {NULL}, 0, 0, S_FISH2}, // S_FISH1 - {SPR_FISH, 1, 1, {A_FishJump}, 0, 0, S_FISH1}, // S_FISH2 - {SPR_FISH, 0, 1, {NULL}, 0, 0, S_FISH4}, // S_FISH3 - {SPR_FISH, 0, 1, {A_FishJump}, 0, 0, S_FISH3}, // S_FISH4 + {SPR_FISH, 1, 1, {NULL}, 0, 0, S_FISH2, 0}, // S_FISH1 + {SPR_FISH, 1, 1, {A_FishJump}, 0, 0, S_FISH1, 0}, // S_FISH2 + {SPR_FISH, 0, 1, {NULL}, 0, 0, S_FISH4, 0}, // S_FISH3 + {SPR_FISH, 0, 1, {A_FishJump}, 0, 0, S_FISH3, 0}, // S_FISH4 // Gold Buzz - {SPR_BUZZ, 0, 2, {A_Look}, 0, 0, S_BUZZLOOK2}, // S_BUZZLOOK1 - {SPR_BUZZ, 1, 2, {A_Look}, 0, 0, S_BUZZLOOK1}, // S_BUZZLOOK2 - {SPR_BUZZ, 0, 2, {A_BuzzFly}, sfx_buzz4, 0, S_BUZZFLY2}, // S_BUZZFLY1 - {SPR_BUZZ, 1, 2, {A_BuzzFly}, 0, 0, S_BUZZFLY1}, // S_BUZZFLY2 + {SPR_BUZZ, 0, 2, {A_Look}, 0, 0, S_BUZZLOOK2, 0}, // S_BUZZLOOK1 + {SPR_BUZZ, 1, 2, {A_Look}, 0, 0, S_BUZZLOOK1, 0}, // S_BUZZLOOK2 + {SPR_BUZZ, 0, 2, {A_BuzzFly}, sfx_buzz4, 0, S_BUZZFLY2, 0}, // S_BUZZFLY1 + {SPR_BUZZ, 1, 2, {A_BuzzFly}, 0, 0, S_BUZZFLY1, 0}, // S_BUZZFLY2 // Red Buzz - {SPR_RBUZ, 0, 2, {A_Look}, 0, 0, S_RBUZZLOOK2}, // S_RBUZZLOOK1 - {SPR_RBUZ, 1, 2, {A_Look}, 0, 0, S_RBUZZLOOK1}, // S_RBUZZLOOK2 - {SPR_RBUZ, 0, 2, {A_BuzzFly}, sfx_buzz4, 0, S_RBUZZFLY2}, // S_RBUZZFLY1 - {SPR_RBUZ, 1, 2, {A_BuzzFly}, 0, 0, S_RBUZZFLY1}, // S_RBUZZFLY2 + {SPR_RBUZ, 0, 2, {A_Look}, 0, 0, S_RBUZZLOOK2, 0}, // S_RBUZZLOOK1 + {SPR_RBUZ, 1, 2, {A_Look}, 0, 0, S_RBUZZLOOK1, 0}, // S_RBUZZLOOK2 + {SPR_RBUZ, 0, 2, {A_BuzzFly}, sfx_buzz4, 0, S_RBUZZFLY2, 0}, // S_RBUZZFLY1 + {SPR_RBUZ, 1, 2, {A_BuzzFly}, 0, 0, S_RBUZZFLY1, 0}, // S_RBUZZFLY2 // Jetty-Syn Bomber - {SPR_JETB, 0, 4, {A_Look}, 0, 0, S_JETBLOOK2}, // S_JETBLOOK1 - {SPR_JETB, 1, 4, {A_Look}, 0, 0, S_JETBLOOK1}, // S_JETBLOOK2 - {SPR_JETB, 0, 1, {A_JetbThink}, 0, 0, S_JETBZOOM2}, // S_JETBZOOM1 - {SPR_JETB, 1, 1, {A_JetbThink}, 0, 0, S_JETBZOOM1}, // S_JETBZOOM2 + {SPR_JETB, 0, 4, {A_Look}, 0, 0, S_JETBLOOK2, 0}, // S_JETBLOOK1 + {SPR_JETB, 1, 4, {A_Look}, 0, 0, S_JETBLOOK1, 0}, // S_JETBLOOK2 + {SPR_JETB, 0, 1, {A_JetbThink}, 0, 0, S_JETBZOOM2, 0}, // S_JETBZOOM1 + {SPR_JETB, 1, 1, {A_JetbThink}, 0, 0, S_JETBZOOM1, 0}, // S_JETBZOOM2 // Jetty-Syn Gunner - {SPR_JETG, 0, 4, {A_Look}, 0, 0, S_JETGLOOK2}, // S_JETGLOOK1 - {SPR_JETG, 1, 4, {A_Look}, 0, 0, S_JETGLOOK1}, // S_JETGLOOK2 - {SPR_JETG, 0, 1, {A_JetgThink}, 0, 0, S_JETGZOOM2}, // S_JETGZOOM1 - {SPR_JETG, 1, 1, {A_JetgThink}, 0, 0, S_JETGZOOM1}, // S_JETGZOOM2 - {SPR_JETG, 2, 1, {A_JetgShoot}, 0, 0, S_JETGSHOOT2}, // S_JETGSHOOT1 - {SPR_JETG, 3, 1, {NULL}, 0, 0, S_JETGZOOM1}, // S_JETGSHOOT2 + {SPR_JETG, 0, 4, {A_Look}, 0, 0, S_JETGLOOK2, 0}, // S_JETGLOOK1 + {SPR_JETG, 1, 4, {A_Look}, 0, 0, S_JETGLOOK1, 0}, // S_JETGLOOK2 + {SPR_JETG, 0, 1, {A_JetgThink}, 0, 0, S_JETGZOOM2, 0}, // S_JETGZOOM1 + {SPR_JETG, 1, 1, {A_JetgThink}, 0, 0, S_JETGZOOM1, 0}, // S_JETGZOOM2 + {SPR_JETG, 2, 1, {A_JetgShoot}, 0, 0, S_JETGSHOOT2, 0}, // S_JETGSHOOT1 + {SPR_JETG, 3, 1, {NULL}, 0, 0, S_JETGZOOM1, 0}, // S_JETGSHOOT2 // Crawla Commander - {SPR_CCOM, 0, 1, {A_CrawlaCommanderThink}, 0, 15*FRACUNIT, S_CCOMMAND2}, // S_CCOMMAND1 - {SPR_CCOM, 1, 1, {A_CrawlaCommanderThink}, 0, 15*FRACUNIT, S_CCOMMAND1}, // S_CCOMMAND2 - {SPR_CCOM, 2, 1, {A_CrawlaCommanderThink}, 0, 15*FRACUNIT, S_CCOMMAND4}, // S_CCOMMAND3 - {SPR_CCOM, 3, 1, {A_CrawlaCommanderThink}, 0, 15*FRACUNIT, S_CCOMMAND3}, // S_CCOMMAND4 + {SPR_CCOM, 0, 1, {A_CrawlaCommanderThink}, 0, 15*FRACUNIT, S_CCOMMAND2, 0}, // S_CCOMMAND1 + {SPR_CCOM, 1, 1, {A_CrawlaCommanderThink}, 0, 15*FRACUNIT, S_CCOMMAND1, 0}, // S_CCOMMAND2 + {SPR_CCOM, 2, 1, {A_CrawlaCommanderThink}, 0, 15*FRACUNIT, S_CCOMMAND4, 0}, // S_CCOMMAND3 + {SPR_CCOM, 3, 1, {A_CrawlaCommanderThink}, 0, 15*FRACUNIT, S_CCOMMAND3, 0}, // S_CCOMMAND4 // Deton - {SPR_DETN, 0, 35, {A_Look}, 0, 0, S_DETON1}, // S_DETON1 - {SPR_DETN, 0, 1, {A_DetonChase}, 0, 0, S_DETON3}, // S_DETON2 - {SPR_DETN, 1, 1, {A_DetonChase}, 0, 0, S_DETON4}, // S_DETON3 - {SPR_DETN, 2, 1, {A_DetonChase}, 0, 0, S_DETON5}, // S_DETON4 - {SPR_DETN, 3, 1, {A_DetonChase}, 0, 0, S_DETON6}, // S_DETON5 - {SPR_DETN, 4, 1, {A_DetonChase}, 0, 0, S_DETON7}, // S_DETON6 - {SPR_DETN, 5, 1, {A_DetonChase}, 0, 0, S_DETON8}, // S_DETON7 - {SPR_DETN, 6, 1, {A_DetonChase}, 0, 0, S_DETON9}, // S_DETON8 - {SPR_DETN, 7, 1, {A_DetonChase}, 0, 0, S_DETON10}, // S_DETON9 - {SPR_DETN, 6, 1, {A_DetonChase}, 0, 0, S_DETON11}, // S_DETON10 - {SPR_DETN, 5, 1, {A_DetonChase}, 0, 0, S_DETON12}, // S_DETON11 - {SPR_DETN, 4, 1, {A_DetonChase}, 0, 0, S_DETON13}, // S_DETON12 - {SPR_DETN, 3, 1, {A_DetonChase}, 0, 0, S_DETON14}, // S_DETON13 - {SPR_DETN, 2, 1, {A_DetonChase}, 0, 0, S_DETON15}, // S_DETON14 - {SPR_DETN, 1, 1, {A_DetonChase}, 0, 0, S_DETON2}, // S_DETON15 + {SPR_DETN, 0, 35, {A_Look}, 0, 0, S_DETON1, 0}, // S_DETON1 + {SPR_DETN, 0, 1, {A_DetonChase}, 0, 0, S_DETON3, 0}, // S_DETON2 + {SPR_DETN, 1, 1, {A_DetonChase}, 0, 0, S_DETON4, 0}, // S_DETON3 + {SPR_DETN, 2, 1, {A_DetonChase}, 0, 0, S_DETON5, 0}, // S_DETON4 + {SPR_DETN, 3, 1, {A_DetonChase}, 0, 0, S_DETON6, 0}, // S_DETON5 + {SPR_DETN, 4, 1, {A_DetonChase}, 0, 0, S_DETON7, 0}, // S_DETON6 + {SPR_DETN, 5, 1, {A_DetonChase}, 0, 0, S_DETON8, 0}, // S_DETON7 + {SPR_DETN, 6, 1, {A_DetonChase}, 0, 0, S_DETON9, 0}, // S_DETON8 + {SPR_DETN, 7, 1, {A_DetonChase}, 0, 0, S_DETON10, 0}, // S_DETON9 + {SPR_DETN, 6, 1, {A_DetonChase}, 0, 0, S_DETON11, 0}, // S_DETON10 + {SPR_DETN, 5, 1, {A_DetonChase}, 0, 0, S_DETON12, 0}, // S_DETON11 + {SPR_DETN, 4, 1, {A_DetonChase}, 0, 0, S_DETON13, 0}, // S_DETON12 + {SPR_DETN, 3, 1, {A_DetonChase}, 0, 0, S_DETON14, 0}, // S_DETON13 + {SPR_DETN, 2, 1, {A_DetonChase}, 0, 0, S_DETON15, 0}, // S_DETON14 + {SPR_DETN, 1, 1, {A_DetonChase}, 0, 0, S_DETON2, 0}, // S_DETON15 // Skim Mine Dropper - {SPR_SKIM, 0, 1, {A_SkimChase}, 0, 0, S_SKIM2}, // S_SKIM1 - {SPR_SKIM, 0, 1, {A_SkimChase}, 0, 0, S_SKIM1}, // S_SKIM2 - {SPR_SKIM, 0, 14, {NULL}, 0, 0, S_SKIM4}, // S_SKIM3 - {SPR_SKIM, 0, 14, {A_DropMine}, 0, 0, S_SKIM1}, // S_SKIM4 + {SPR_SKIM, 0, 1, {A_SkimChase}, 0, 0, S_SKIM2, 0}, // S_SKIM1 + {SPR_SKIM, 0, 1, {A_SkimChase}, 0, 0, S_SKIM1, 0}, // S_SKIM2 + {SPR_SKIM, 0, 14, {NULL}, 0, 0, S_SKIM4, 0}, // S_SKIM3 + {SPR_SKIM, 0, 14, {A_DropMine}, 0, 0, S_SKIM1, 0}, // S_SKIM4 // THZ Turret - {SPR_TRET, FF_FULLBRIGHT, 105, {A_TurretStop}, 0, 0, S_TURRETFIRE}, // S_TURRET - {SPR_TRET, FF_FULLBRIGHT, 105, {A_TurretFire}, 0, 0, S_TURRET}, // S_TURRETFIRE - {SPR_TRET, FF_FULLBRIGHT|1, 7, {A_Pain}, 0, 0, S_TURRETSHOCK2}, // S_TURRETSHOCK1 - {SPR_TRET, FF_FULLBRIGHT|2, 7, {NULL}, 0, 0, S_TURRETSHOCK3}, // S_TURRETSHOCK2 - {SPR_TRET, FF_FULLBRIGHT|3, 7, {NULL}, 0, 0, S_TURRETSHOCK4}, // S_TURRETSHOCK3 - {SPR_TRET, FF_FULLBRIGHT|4, 7, {NULL}, 0, 0, S_TURRETSHOCK5}, // S_TURRETSHOCK4 - {SPR_TRET, FF_FULLBRIGHT|1, 7, {NULL}, 0, 0, S_TURRETSHOCK6}, // S_TURRETSHOCK5 - {SPR_TRET, FF_FULLBRIGHT|2, 7, {A_Pain}, 0, 0, S_TURRETSHOCK7}, // S_TURRETSHOCK6 - {SPR_TRET, FF_FULLBRIGHT|3, 7, {NULL}, 0, 0, S_TURRETSHOCK8}, // S_TURRETSHOCK7 - {SPR_TRET, FF_FULLBRIGHT|4, 7, {NULL}, 0, 0, S_TURRETSHOCK9}, // S_TURRETSHOCK8 - {SPR_TRET, FF_FULLBRIGHT|4, 7, {A_LinedefExecuteFromArg}, 0, 0, S_XPLD1}, // S_TURRETSHOCK9 - - {SPR_TURR, 0, 1, {A_Look}, 1, 0, S_TURRETPOPDOWN8}, // S_TURRETLOOK - {SPR_TURR, 0, 0, {A_FaceTarget}, 0, 0, S_TURRETPOPUP1}, // S_TURRETSEE - {SPR_TURR, 1, 2, {A_Pain}, 0, 0, S_TURRETPOPUP2}, // S_TURRETPOPUP1 - {SPR_TURR, 2, 2, {NULL}, 0, 0, S_TURRETPOPUP3}, // S_TURRETPOPUP2 - {SPR_TURR, 3, 2, {NULL}, 0, 0, S_TURRETPOPUP4}, // S_TURRETPOPUP3 - {SPR_TURR, 4, 2, {NULL}, 0, 0, S_TURRETPOPUP5}, // S_TURRETPOPUP4 - {SPR_TURR, 5, 2, {NULL}, 0, 0, S_TURRETPOPUP6}, // S_TURRETPOPUP5 - {SPR_TURR, 6, 2, {NULL}, 0, 0, S_TURRETPOPUP7}, // S_TURRETPOPUP6 - {SPR_TURR, 7, 2, {NULL}, 0, 0, S_TURRETPOPUP8}, // S_TURRETPOPUP7 - {SPR_TURR, 8, 14,{NULL}, 0, 0, S_TURRETSHOOT}, // S_TURRETPOPUP8 - {SPR_TURR, 8, 14,{A_JetgShoot}, 0, 0, S_TURRETPOPDOWN1}, // S_TURRETSHOOT - {SPR_TURR, 7, 2, {A_Pain}, 0, 0, S_TURRETPOPDOWN2}, // S_TURRETPOPDOWN1 - {SPR_TURR, 6, 2, {NULL}, 0, 0, S_TURRETPOPDOWN3}, // S_TURRETPOPDOWN2 - {SPR_TURR, 5, 2, {NULL}, 0, 0, S_TURRETPOPDOWN4}, // S_TURRETPOPDOWN3 - {SPR_TURR, 4, 2, {NULL}, 0, 0, S_TURRETPOPDOWN5}, // S_TURRETPOPDOWN4 - {SPR_TURR, 3, 2, {NULL}, 0, 0, S_TURRETPOPDOWN6}, // S_TURRETPOPDOWN5 - {SPR_TURR, 2, 2, {NULL}, 0, 0, S_TURRETPOPDOWN7}, // S_TURRETPOPDOWN6 - {SPR_TURR, 1, 2, {NULL}, 0, 0, S_TURRETPOPDOWN8}, // S_TURRETPOPDOWN7 - {SPR_TURR, 0, 69,{A_SetTics}, 0, 1, S_TURRETLOOK}, // S_TURRETPOPDOWN8 + {SPR_TRET, FF_FULLBRIGHT, 105, {A_TurretStop}, 0, 0, S_TURRETFIRE, 0}, // S_TURRET + {SPR_TRET, FF_FULLBRIGHT, 105, {A_TurretFire}, 0, 0, S_TURRET, 0}, // S_TURRETFIRE + {SPR_TRET, FF_FULLBRIGHT|1, 7, {A_Pain}, 0, 0, S_TURRETSHOCK2, 0}, // S_TURRETSHOCK1 + {SPR_TRET, FF_FULLBRIGHT|2, 7, {NULL}, 0, 0, S_TURRETSHOCK3, 0}, // S_TURRETSHOCK2 + {SPR_TRET, FF_FULLBRIGHT|3, 7, {NULL}, 0, 0, S_TURRETSHOCK4, 0}, // S_TURRETSHOCK3 + {SPR_TRET, FF_FULLBRIGHT|4, 7, {NULL}, 0, 0, S_TURRETSHOCK5, 0}, // S_TURRETSHOCK4 + {SPR_TRET, FF_FULLBRIGHT|1, 7, {NULL}, 0, 0, S_TURRETSHOCK6, 0}, // S_TURRETSHOCK5 + {SPR_TRET, FF_FULLBRIGHT|2, 7, {A_Pain}, 0, 0, S_TURRETSHOCK7, 0}, // S_TURRETSHOCK6 + {SPR_TRET, FF_FULLBRIGHT|3, 7, {NULL}, 0, 0, S_TURRETSHOCK8, 0}, // S_TURRETSHOCK7 + {SPR_TRET, FF_FULLBRIGHT|4, 7, {NULL}, 0, 0, S_TURRETSHOCK9, 0}, // S_TURRETSHOCK8 + {SPR_TRET, FF_FULLBRIGHT|4, 7, {A_LinedefExecuteFromArg}, 0, 0, S_XPLD1, 0}, // S_TURRETSHOCK9 + + {SPR_TURR, 0, 1, {A_Look}, 1, 0, S_TURRETPOPDOWN8, 0}, // S_TURRETLOOK + {SPR_TURR, 0, 0, {A_FaceTarget}, 0, 0, S_TURRETPOPUP1, 0}, // S_TURRETSEE + {SPR_TURR, 1, 2, {A_Pain}, 0, 0, S_TURRETPOPUP2, 0}, // S_TURRETPOPUP1 + {SPR_TURR, 2, 2, {NULL}, 0, 0, S_TURRETPOPUP3, 0}, // S_TURRETPOPUP2 + {SPR_TURR, 3, 2, {NULL}, 0, 0, S_TURRETPOPUP4, 0}, // S_TURRETPOPUP3 + {SPR_TURR, 4, 2, {NULL}, 0, 0, S_TURRETPOPUP5, 0}, // S_TURRETPOPUP4 + {SPR_TURR, 5, 2, {NULL}, 0, 0, S_TURRETPOPUP6, 0}, // S_TURRETPOPUP5 + {SPR_TURR, 6, 2, {NULL}, 0, 0, S_TURRETPOPUP7, 0}, // S_TURRETPOPUP6 + {SPR_TURR, 7, 2, {NULL}, 0, 0, S_TURRETPOPUP8, 0}, // S_TURRETPOPUP7 + {SPR_TURR, 8, 14,{NULL}, 0, 0, S_TURRETSHOOT, 0}, // S_TURRETPOPUP8 + {SPR_TURR, 8, 14,{A_JetgShoot}, 0, 0, S_TURRETPOPDOWN1, 0}, // S_TURRETSHOOT + {SPR_TURR, 7, 2, {A_Pain}, 0, 0, S_TURRETPOPDOWN2, 0}, // S_TURRETPOPDOWN1 + {SPR_TURR, 6, 2, {NULL}, 0, 0, S_TURRETPOPDOWN3, 0}, // S_TURRETPOPDOWN2 + {SPR_TURR, 5, 2, {NULL}, 0, 0, S_TURRETPOPDOWN4, 0}, // S_TURRETPOPDOWN3 + {SPR_TURR, 4, 2, {NULL}, 0, 0, S_TURRETPOPDOWN5, 0}, // S_TURRETPOPDOWN4 + {SPR_TURR, 3, 2, {NULL}, 0, 0, S_TURRETPOPDOWN6, 0}, // S_TURRETPOPDOWN5 + {SPR_TURR, 2, 2, {NULL}, 0, 0, S_TURRETPOPDOWN7, 0}, // S_TURRETPOPDOWN6 + {SPR_TURR, 1, 2, {NULL}, 0, 0, S_TURRETPOPDOWN8, 0}, // S_TURRETPOPDOWN7 + {SPR_TURR, 0, 69,{A_SetTics}, 0, 1, S_TURRETLOOK, 0}, // S_TURRETPOPDOWN8 // Spincushion - {SPR_SHRP, 0, 2, {A_Look}, 0, 0, S_SPINCUSHION_LOOK}, // S_SPINCUSHION_LOOK - {SPR_SHRP, 1, 2, {A_SharpChase}, 0, 0, S_SPINCUSHION_CHASE2}, // S_SPINCUSHION_CHASE1 - {SPR_SHRP, 2, 2, {A_SharpChase}, 0, 0, S_SPINCUSHION_CHASE3}, // S_SPINCUSHION_CHASE2 - {SPR_SHRP, 3, 2, {A_SharpChase}, 0, 0, S_SPINCUSHION_CHASE4}, // S_SPINCUSHION_CHASE3 - {SPR_SHRP, 0, 2, {A_SharpChase}, 0, 0, S_SPINCUSHION_CHASE1}, // S_SPINCUSHION_CHASE4 - {SPR_SHRP, 0, 2, {NULL}, 0, 0, S_SPINCUSHION_AIM2}, // S_SPINCUSHION_AIM1 - {SPR_SHRP, 4, 2, {NULL}, 0, 0, S_SPINCUSHION_AIM3}, // S_SPINCUSHION_AIM2 - {SPR_SHRP, 5, 2, {A_SetObjectFlags}, MF_PAIN, 2, S_SPINCUSHION_AIM4}, // S_SPINCUSHION_AIM3 - {SPR_SHRP, 6, 16, {A_MultiShotDist}, (MT_DUST<<16)|6, -32, S_SPINCUSHION_AIM5}, // S_SPINCUSHION_AIM4 - {SPR_SHRP, 6, 0, {A_PlaySound}, sfx_shrpgo, 1, S_SPINCUSHION_SPIN1}, // S_SPINCUSHION_AIM5 - {SPR_SHRP, 6, 1, {A_SharpSpin}, 0, 0, S_SPINCUSHION_SPIN2}, // S_SPINCUSHION_SPIN1 - {SPR_SHRP, 8, 1, {A_SharpSpin}, 0, 0, S_SPINCUSHION_SPIN3}, // S_SPINCUSHION_SPIN2 - {SPR_SHRP, 7, 1, {A_SharpSpin}, 0, 0, S_SPINCUSHION_SPIN4}, // S_SPINCUSHION_SPIN3 - {SPR_SHRP, 8, 1, {A_SharpSpin}, MT_SPINDUST, 0, S_SPINCUSHION_SPIN1}, // S_SPINCUSHION_SPIN4 - {SPR_SHRP, 6, 1, {A_PlaySound}, sfx_s3k69, 1, S_SPINCUSHION_STOP2}, // S_SPINCUSHION_STOP1 - {SPR_SHRP, 6, 4, {A_SharpDecel}, 0, 0, S_SPINCUSHION_STOP2}, // S_SPINCUSHION_STOP2 - {SPR_SHRP, 5, 4, {A_FaceTarget}, 0, 0, S_SPINCUSHION_STOP4}, // S_SPINCUSHION_STOP3 - {SPR_SHRP, 4, 4, {A_SetObjectFlags}, MF_PAIN, 1, S_SPINCUSHION_LOOK}, // S_SPINCUSHION_STOP4 + {SPR_SHRP, 0, 2, {A_Look}, 0, 0, S_SPINCUSHION_LOOK, 0}, // S_SPINCUSHION_LOOK + {SPR_SHRP, 1, 2, {A_SharpChase}, 0, 0, S_SPINCUSHION_CHASE2, 0}, // S_SPINCUSHION_CHASE1 + {SPR_SHRP, 2, 2, {A_SharpChase}, 0, 0, S_SPINCUSHION_CHASE3, 0}, // S_SPINCUSHION_CHASE2 + {SPR_SHRP, 3, 2, {A_SharpChase}, 0, 0, S_SPINCUSHION_CHASE4, 0}, // S_SPINCUSHION_CHASE3 + {SPR_SHRP, 0, 2, {A_SharpChase}, 0, 0, S_SPINCUSHION_CHASE1, 0}, // S_SPINCUSHION_CHASE4 + {SPR_SHRP, 0, 2, {NULL}, 0, 0, S_SPINCUSHION_AIM2, 0}, // S_SPINCUSHION_AIM1 + {SPR_SHRP, 4, 2, {NULL}, 0, 0, S_SPINCUSHION_AIM3, 0}, // S_SPINCUSHION_AIM2 + {SPR_SHRP, 5, 2, {A_SetObjectFlags}, MF_PAIN, 2, S_SPINCUSHION_AIM4, 0}, // S_SPINCUSHION_AIM3 + {SPR_SHRP, 6, 16, {A_MultiShotDist}, (MT_DUST<<16)|6, -32, S_SPINCUSHION_AIM5, 0}, // S_SPINCUSHION_AIM4 + {SPR_SHRP, 6, 0, {A_PlaySound}, sfx_shrpgo, 1, S_SPINCUSHION_SPIN1, 0}, // S_SPINCUSHION_AIM5 + {SPR_SHRP, 6, 1, {A_SharpSpin}, 0, 0, S_SPINCUSHION_SPIN2, 0}, // S_SPINCUSHION_SPIN1 + {SPR_SHRP, 8, 1, {A_SharpSpin}, 0, 0, S_SPINCUSHION_SPIN3, 0}, // S_SPINCUSHION_SPIN2 + {SPR_SHRP, 7, 1, {A_SharpSpin}, 0, 0, S_SPINCUSHION_SPIN4, 0}, // S_SPINCUSHION_SPIN3 + {SPR_SHRP, 8, 1, {A_SharpSpin}, MT_SPINDUST, 0, S_SPINCUSHION_SPIN1, 0}, // S_SPINCUSHION_SPIN4 + {SPR_SHRP, 6, 1, {A_PlaySound}, sfx_s3k69, 1, S_SPINCUSHION_STOP2, 0}, // S_SPINCUSHION_STOP1 + {SPR_SHRP, 6, 4, {A_SharpDecel}, 0, 0, S_SPINCUSHION_STOP2, 0}, // S_SPINCUSHION_STOP2 + {SPR_SHRP, 5, 4, {A_FaceTarget}, 0, 0, S_SPINCUSHION_STOP4, 0}, // S_SPINCUSHION_STOP3 + {SPR_SHRP, 4, 4, {A_SetObjectFlags}, MF_PAIN, 1, S_SPINCUSHION_LOOK, 0}, // S_SPINCUSHION_STOP4 // Crushstacean - {SPR_CRAB, 0, 3, {A_CrushstaceanWalk}, 0, S_CRUSHSTACEAN_ROAMPAUSE, S_CRUSHSTACEAN_ROAM2}, // S_CRUSHSTACEAN_ROAM1 - {SPR_CRAB, 1, 3, {A_CrushstaceanWalk}, 0, S_CRUSHSTACEAN_ROAMPAUSE, S_CRUSHSTACEAN_ROAM3}, // S_CRUSHSTACEAN_ROAM2 - {SPR_CRAB, 0, 3, {A_CrushstaceanWalk}, 0, S_CRUSHSTACEAN_ROAMPAUSE, S_CRUSHSTACEAN_ROAM4}, // S_CRUSHSTACEAN_ROAM3 - {SPR_CRAB, 2, 3, {A_CrushstaceanWalk}, 0, S_CRUSHSTACEAN_ROAMPAUSE, S_CRUSHSTACEAN_ROAM1}, // S_CRUSHSTACEAN_ROAM4 - {SPR_CRAB, 0, 40, {NULL}, 0, 0, S_CRUSHSTACEAN_ROAM1}, // S_CRUSHSTACEAN_ROAMPAUSE - {SPR_CRAB, 0, 10, {NULL}, 0, 0, S_CRUSHSTACEAN_PUNCH2}, // S_CRUSHSTACEAN_PUNCH1 - {SPR_CRAB, 0, -1, {A_CrushstaceanPunch}, 0, 0, S_CRUSHSTACEAN_ROAMPAUSE}, // S_CRUSHSTACEAN_PUNCH2 - {SPR_CRAB, 3, 1, {A_CrushclawAim}, 40, 20, S_CRUSHCLAW_AIM}, // S_CRUSHCLAW_AIM - {SPR_CRAB, 3, 1, {A_CrushclawLaunch}, 0, S_CRUSHCLAW_STAY, S_CRUSHCLAW_OUT}, // S_CRUSHCLAW_OUT - {SPR_CRAB, 3, 10, {NULL}, 0, 0, S_CRUSHCLAW_IN}, // S_CRUSHCLAW_STAY - {SPR_CRAB, 3, 1, {A_CrushclawLaunch}, 1, S_CRUSHCLAW_WAIT, S_CRUSHCLAW_IN}, // S_CRUSHCLAW_IN - {SPR_CRAB, 3, 37, {NULL}, 0, 0, S_CRUSHCLAW_AIM}, // S_CRUSHCLAW_WAIT - {SPR_CRAB, 4, -1, {NULL}, 0, 0, S_NULL}, // S_CRUSHCHAIN + {SPR_CRAB, 0, 3, {A_CrushstaceanWalk}, 0, S_CRUSHSTACEAN_ROAMPAUSE, S_CRUSHSTACEAN_ROAM2, 0}, // S_CRUSHSTACEAN_ROAM1 + {SPR_CRAB, 1, 3, {A_CrushstaceanWalk}, 0, S_CRUSHSTACEAN_ROAMPAUSE, S_CRUSHSTACEAN_ROAM3, 0}, // S_CRUSHSTACEAN_ROAM2 + {SPR_CRAB, 0, 3, {A_CrushstaceanWalk}, 0, S_CRUSHSTACEAN_ROAMPAUSE, S_CRUSHSTACEAN_ROAM4, 0}, // S_CRUSHSTACEAN_ROAM3 + {SPR_CRAB, 2, 3, {A_CrushstaceanWalk}, 0, S_CRUSHSTACEAN_ROAMPAUSE, S_CRUSHSTACEAN_ROAM1, 0}, // S_CRUSHSTACEAN_ROAM4 + {SPR_CRAB, 0, 40, {NULL}, 0, 0, S_CRUSHSTACEAN_ROAM1, 0}, // S_CRUSHSTACEAN_ROAMPAUSE + {SPR_CRAB, 0, 10, {NULL}, 0, 0, S_CRUSHSTACEAN_PUNCH2, 0}, // S_CRUSHSTACEAN_PUNCH1 + {SPR_CRAB, 0, -1, {A_CrushstaceanPunch}, 0, 0, S_CRUSHSTACEAN_ROAMPAUSE, 0}, // S_CRUSHSTACEAN_PUNCH2 + {SPR_CRAB, 3, 1, {A_CrushclawAim}, 40, 20, S_CRUSHCLAW_AIM, 0}, // S_CRUSHCLAW_AIM + {SPR_CRAB, 3, 1, {A_CrushclawLaunch}, 0, S_CRUSHCLAW_STAY, S_CRUSHCLAW_OUT, 0}, // S_CRUSHCLAW_OUT + {SPR_CRAB, 3, 10, {NULL}, 0, 0, S_CRUSHCLAW_IN, 0}, // S_CRUSHCLAW_STAY + {SPR_CRAB, 3, 1, {A_CrushclawLaunch}, 1, S_CRUSHCLAW_WAIT, S_CRUSHCLAW_IN, 0}, // S_CRUSHCLAW_IN + {SPR_CRAB, 3, 37, {NULL}, 0, 0, S_CRUSHCLAW_AIM, 0}, // S_CRUSHCLAW_WAIT + {SPR_CRAB, 4, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CRUSHCHAIN // Banpyura - {SPR_CR2B, 0, 3, {A_CrushstaceanWalk}, 0, S_BANPYURA_ROAMPAUSE, S_BANPYURA_ROAM2}, // S_BANPYURA_ROAM1 - {SPR_CR2B, 1, 3, {A_CrushstaceanWalk}, 0, S_BANPYURA_ROAMPAUSE, S_BANPYURA_ROAM3}, // S_BANPYURA_ROAM2 - {SPR_CR2B, 0, 3, {A_CrushstaceanWalk}, 0, S_BANPYURA_ROAMPAUSE, S_BANPYURA_ROAM4}, // S_BANPYURA_ROAM3 - {SPR_CR2B, 2, 3, {A_CrushstaceanWalk}, 0, S_BANPYURA_ROAMPAUSE, S_BANPYURA_ROAM1}, // S_BANPYURA_ROAM4 - {SPR_CR2B, 0, 40, {NULL}, 0, 0, S_BANPYURA_ROAM1}, // S_BANPYURA_ROAMPAUSE - - {SPR_CSPR, 0, 1, {A_CrushclawAim}, 50, 20, S_CDIAG1}, // S_CDIAG1 - {SPR_CSPR, 1, 1, {A_Pain}, 0, 0, S_CDIAG3}, // S_CDIAG2 - {SPR_CSPR, 2, 1, {A_CrushclawAim}, 50, 20, S_CDIAG4}, // S_CDIAG3 - {SPR_CSPR, 3, 1, {A_CrushclawAim}, 50, 20, S_CDIAG5}, // S_CDIAG4 - {SPR_CSPR, 4, 1, {A_CrushclawAim}, 50, 20, S_CDIAG6}, // S_CDIAG5 - {SPR_CSPR, 3, 1, {A_CrushclawAim}, 50, 20, S_CDIAG7}, // S_CDIAG6 - {SPR_CSPR, 2, 1, {A_CrushclawAim}, 50, 20, S_CDIAG8}, // S_CDIAG7 - {SPR_CSPR, 1, 1, {A_CrushclawAim}, 50, 20, S_CDIAG1}, // S_CDIAG8 + {SPR_CR2B, 0, 3, {A_CrushstaceanWalk}, 0, S_BANPYURA_ROAMPAUSE, S_BANPYURA_ROAM2, 0}, // S_BANPYURA_ROAM1 + {SPR_CR2B, 1, 3, {A_CrushstaceanWalk}, 0, S_BANPYURA_ROAMPAUSE, S_BANPYURA_ROAM3, 0}, // S_BANPYURA_ROAM2 + {SPR_CR2B, 0, 3, {A_CrushstaceanWalk}, 0, S_BANPYURA_ROAMPAUSE, S_BANPYURA_ROAM4, 0}, // S_BANPYURA_ROAM3 + {SPR_CR2B, 2, 3, {A_CrushstaceanWalk}, 0, S_BANPYURA_ROAMPAUSE, S_BANPYURA_ROAM1, 0}, // S_BANPYURA_ROAM4 + {SPR_CR2B, 0, 40, {NULL}, 0, 0, S_BANPYURA_ROAM1, 0}, // S_BANPYURA_ROAMPAUSE + + {SPR_CSPR, 0, 1, {A_CrushclawAim}, 50, 20, S_CDIAG1, 0}, // S_CDIAG1 + {SPR_CSPR, 1, 1, {A_Pain}, 0, 0, S_CDIAG3, 0}, // S_CDIAG2 + {SPR_CSPR, 2, 1, {A_CrushclawAim}, 50, 20, S_CDIAG4, 0}, // S_CDIAG3 + {SPR_CSPR, 3, 1, {A_CrushclawAim}, 50, 20, S_CDIAG5, 0}, // S_CDIAG4 + {SPR_CSPR, 4, 1, {A_CrushclawAim}, 50, 20, S_CDIAG6, 0}, // S_CDIAG5 + {SPR_CSPR, 3, 1, {A_CrushclawAim}, 50, 20, S_CDIAG7, 0}, // S_CDIAG6 + {SPR_CSPR, 2, 1, {A_CrushclawAim}, 50, 20, S_CDIAG8, 0}, // S_CDIAG7 + {SPR_CSPR, 1, 1, {A_CrushclawAim}, 50, 20, S_CDIAG1, 0}, // S_CDIAG8 // Jet Jaw - {SPR_JJAW, 0, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM2}, // S_JETJAW_ROAM1 - {SPR_JJAW, 0, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM3}, // S_JETJAW_ROAM2 - {SPR_JJAW, 0, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM4}, // S_JETJAW_ROAM3 - {SPR_JJAW, 0, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM5}, // S_JETJAW_ROAM4 - {SPR_JJAW, 1, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM6}, // S_JETJAW_ROAM5 - {SPR_JJAW, 1, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM7}, // S_JETJAW_ROAM6 - {SPR_JJAW, 1, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM8}, // S_JETJAW_ROAM7 - {SPR_JJAW, 1, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM1}, // S_JETJAW_ROAM8 - {SPR_JJAW, 0, 1, {A_DualAction}, S_JETJAW_CHOMP16, S_JETJAW_SOUND, S_JETJAW_CHOMP2}, // S_JETJAW_CHOMP1 - {SPR_JJAW, 0, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP3}, // S_JETJAW_CHOMP2 - {SPR_JJAW, 0, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP4}, // S_JETJAW_CHOMP3 - {SPR_JJAW, 0, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP5}, // S_JETJAW_CHOMP4 - {SPR_JJAW, 1, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP6}, // S_JETJAW_CHOMP5 - {SPR_JJAW, 1, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP7}, // S_JETJAW_CHOMP6 - {SPR_JJAW, 1, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP8}, // S_JETJAW_CHOMP7 - {SPR_JJAW, 1, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP9}, // S_JETJAW_CHOMP8 - {SPR_JJAW, 2, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP10}, // S_JETJAW_CHOMP9 - {SPR_JJAW, 2, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP11}, // S_JETJAW_CHOMP10 - {SPR_JJAW, 2, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP12}, // S_JETJAW_CHOMP11 - {SPR_JJAW, 2, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP13}, // S_JETJAW_CHOMP12 - {SPR_JJAW, 3, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP14}, // S_JETJAW_CHOMP13 - {SPR_JJAW, 3, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP15}, // S_JETJAW_CHOMP14 - {SPR_JJAW, 3, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP16}, // S_JETJAW_CHOMP15 - {SPR_JJAW, 3, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP1}, // S_JETJAW_CHOMP16 - {SPR_JJAW, 0, 1, {A_PlayAttackSound}, 0, 0, S_JETJAW_SOUND}, // S_JETJAW_SOUND + {SPR_JJAW, 0, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM2, 0}, // S_JETJAW_ROAM1 + {SPR_JJAW, 0, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM3, 0}, // S_JETJAW_ROAM2 + {SPR_JJAW, 0, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM4, 0}, // S_JETJAW_ROAM3 + {SPR_JJAW, 0, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM5, 0}, // S_JETJAW_ROAM4 + {SPR_JJAW, 1, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM6, 0}, // S_JETJAW_ROAM5 + {SPR_JJAW, 1, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM7, 0}, // S_JETJAW_ROAM6 + {SPR_JJAW, 1, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM8, 0}, // S_JETJAW_ROAM7 + {SPR_JJAW, 1, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM1, 0}, // S_JETJAW_ROAM8 + {SPR_JJAW, 0, 1, {A_DualAction}, S_JETJAW_CHOMP16, S_JETJAW_SOUND, S_JETJAW_CHOMP2, 0}, // S_JETJAW_CHOMP1 + {SPR_JJAW, 0, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP3, 0}, // S_JETJAW_CHOMP2 + {SPR_JJAW, 0, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP4, 0}, // S_JETJAW_CHOMP3 + {SPR_JJAW, 0, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP5, 0}, // S_JETJAW_CHOMP4 + {SPR_JJAW, 1, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP6, 0}, // S_JETJAW_CHOMP5 + {SPR_JJAW, 1, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP7, 0}, // S_JETJAW_CHOMP6 + {SPR_JJAW, 1, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP8, 0}, // S_JETJAW_CHOMP7 + {SPR_JJAW, 1, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP9, 0}, // S_JETJAW_CHOMP8 + {SPR_JJAW, 2, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP10, 0}, // S_JETJAW_CHOMP9 + {SPR_JJAW, 2, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP11, 0}, // S_JETJAW_CHOMP10 + {SPR_JJAW, 2, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP12, 0}, // S_JETJAW_CHOMP11 + {SPR_JJAW, 2, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP13, 0}, // S_JETJAW_CHOMP12 + {SPR_JJAW, 3, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP14, 0}, // S_JETJAW_CHOMP13 + {SPR_JJAW, 3, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP15, 0}, // S_JETJAW_CHOMP14 + {SPR_JJAW, 3, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP16, 0}, // S_JETJAW_CHOMP15 + {SPR_JJAW, 3, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP1, 0}, // S_JETJAW_CHOMP16 + {SPR_JJAW, 0, 1, {A_PlayAttackSound}, 0, 0, S_JETJAW_SOUND, 0}, // S_JETJAW_SOUND // Snailer - {SPR_SNLR, 0, 1, {A_SnailerThink}, 0, 0, S_SNAILER1}, // S_SNAILER1 - {SPR_BOM1, 0, 0, {A_FlickySpawn}, 1<<17, 0, S_XPLD1}, // S_SNAILER_FLICKY + {SPR_SNLR, 0, 1, {A_SnailerThink}, 0, 0, S_SNAILER1, 0}, // S_SNAILER1 + {SPR_BOM1, 0, 0, {A_FlickySpawn}, 1<<17, 0, S_XPLD1, 0}, // S_SNAILER_FLICKY // Vulture - {SPR_VLTR, 4, 35, {A_Look}, 1, 0, S_VULTURE_STND}, // S_VULTURE_STND - {SPR_VLTR, 4, 3, {A_VultureHover}, 0, 0, S_VULTURE_DRIFT}, // S_VULTURE_DRIFT - {SPR_VLTR, 0, 6, {A_VultureBlast}, 0, 0, S_VULTURE_ZOOM2}, // S_VULTURE_ZOOM1 - {SPR_VLTR, 0, 3, {A_VultureFly}, 0, 0, S_VULTURE_ZOOM2}, // S_VULTURE_ZOOM2 - {SPR_VLTR, 0, 3*TICRATE, {NULL}, 0, 0, S_VULTURE_DRIFT}, // S_VULTURE_STUNNED + {SPR_VLTR, 4, 35, {A_Look}, 1, 0, S_VULTURE_STND, 0}, // S_VULTURE_STND + {SPR_VLTR, 4, 3, {A_VultureHover}, 0, 0, S_VULTURE_DRIFT, 0}, // S_VULTURE_DRIFT + {SPR_VLTR, 0, 6, {A_VultureBlast}, 0, 0, S_VULTURE_ZOOM2, 0}, // S_VULTURE_ZOOM1 + {SPR_VLTR, 0, 3, {A_VultureFly}, 0, 0, S_VULTURE_ZOOM2, 0}, // S_VULTURE_ZOOM2 + {SPR_VLTR, 0, 3*TICRATE, {NULL}, 0, 0, S_VULTURE_DRIFT, 0}, // S_VULTURE_STUNNED // Pointy - {SPR_PNTY, 0, 1, {A_PointyThink}, 0, 0, S_POINTY1}, // S_POINTY1 + {SPR_PNTY, 0, 1, {A_PointyThink}, 0, 0, S_POINTY1, 0}, // S_POINTY1 // Pointy Ball - {SPR_PNTY, 1, 1, {A_CheckBuddy}, 0, 0, S_POINTYBALL1}, // S_POINTYBALL1 + {SPR_PNTY, 1, 1, {A_CheckBuddy}, 0, 0, S_POINTYBALL1, 0}, // S_POINTYBALL1 // Robo-Hood - {SPR_ARCH, 0, 4, {A_Look}, 2048<<FRACBITS, 0, S_ROBOHOOD_LOOK}, // S_ROBOHOOD_LOOK - {SPR_ARCH, 0, 1, {A_HoodThink}, 0, 0, S_ROBOHOOD_STAND}, // S_ROBOHOOD_STAND - {SPR_ARCH, 2, TICRATE, {A_PlayActiveSound}, 0, 0, S_ROBOHOOD_FIRE2}, // S_ROBOHOOD_FIRE1 - {SPR_ARCH, 2, 20, {A_HoodFire}, MT_ARROW, 0, S_ROBOHOOD_STAND}, // S_ROBOHOOD_FIRE2 - {SPR_ARCH, 1, 1, {A_FaceTarget}, 0, 0, S_ROBOHOOD_JUMP2}, // S_ROBOHOOD_JUMP1 - {SPR_ARCH, 1, 1, {A_BunnyHop}, 4, -10, S_ROBOHOOD_JUMP3}, // S_ROBOHOOD_JUMP2 - {SPR_ARCH, 1, 1, {A_HoodFall}, 0, 0, S_ROBOHOOD_JUMP3}, // S_ROBOHOOD_JUMP3 + {SPR_ARCH, 0, 4, {A_Look}, 2048<<FRACBITS, 0, S_ROBOHOOD_LOOK, 0}, // S_ROBOHOOD_LOOK + {SPR_ARCH, 0, 1, {A_HoodThink}, 0, 0, S_ROBOHOOD_STAND, 0}, // S_ROBOHOOD_STAND + {SPR_ARCH, 2, TICRATE, {A_PlayActiveSound}, 0, 0, S_ROBOHOOD_FIRE2, 0}, // S_ROBOHOOD_FIRE1 + {SPR_ARCH, 2, 20, {A_HoodFire}, MT_ARROW, 0, S_ROBOHOOD_STAND, 0}, // S_ROBOHOOD_FIRE2 + {SPR_ARCH, 1, 1, {A_FaceTarget}, 0, 0, S_ROBOHOOD_JUMP2, 0}, // S_ROBOHOOD_JUMP1 + {SPR_ARCH, 1, 1, {A_BunnyHop}, 4, -10, S_ROBOHOOD_JUMP3, 0}, // S_ROBOHOOD_JUMP2 + {SPR_ARCH, 1, 1, {A_HoodFall}, 0, 0, S_ROBOHOOD_JUMP3, 0}, // S_ROBOHOOD_JUMP3 // Castlebot Facestabber - {SPR_CBFS, 0, 1, {A_Chase}, 0, 0, S_FACESTABBER_STND2}, // S_FACESTABBER_STND1 - {SPR_CBFS, 1, 1, {A_Chase}, 0, 0, S_FACESTABBER_STND3}, // S_FACESTABBER_STND2 - {SPR_CBFS, 2, 1, {A_Chase}, 0, 0, S_FACESTABBER_STND4}, // S_FACESTABBER_STND3 - {SPR_CBFS, 3, 1, {A_Chase}, 0, 0, S_FACESTABBER_STND5}, // S_FACESTABBER_STND4 - {SPR_CBFS, 4, 1, {A_Chase}, 0, 0, S_FACESTABBER_STND6}, // S_FACESTABBER_STND5 - {SPR_CBFS, 5, 1, {A_Chase}, 0, 0, S_FACESTABBER_STND1}, // S_FACESTABBER_STND6 - {SPR_CBFS, 0, 1, {A_FaceStabRev}, 20, S_FACESTABBER_CHARGE2, S_FACESTABBER_CHARGE1}, // S_FACESTABBER_CHARGE1 - {SPR_CBFS, 0, 0, {A_FaceTarget}, 0, 0, S_FACESTABBER_CHARGE3}, // S_FACESTABBER_CHARGE2 - {SPR_CBFS, 7, 1, {A_FaceStabHurl}, 6, S_FACESTABBER_CHARGE4, S_FACESTABBER_CHARGE3}, // S_FACESTABBER_CHARGE3 - {SPR_CBFS, 7, 1, {A_FaceStabMiss}, 0, S_FACESTABBER_STND1, S_FACESTABBER_CHARGE4}, // S_FACESTABBER_CHARGE4 - {SPR_CBFS, 0, 35, {A_Pain}, 0, 0, S_FACESTABBER_STND1}, // S_FACESTABBER_PAIN - {SPR_CBFS, 0, 2, {A_BossScream}, 1, 0, S_FACESTABBER_DIE2}, // S_FACESTABBER_DIE1 - {SPR_NULL, 0, 2, {A_BossScream}, 1, 0, S_FACESTABBER_DIE3}, // S_FACESTABBER_DIE2 - {SPR_NULL, 0, 0, {A_Repeat}, 7, S_FACESTABBER_DIE1, S_XPLD_FLICKY}, // S_FACESTABBER_DIE3 - - {SPR_STAB, FF_PAPERSPRITE|FF_TRANS50|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_FACESTABBERSPEAR + {SPR_CBFS, 0, 1, {A_Chase}, 0, 0, S_FACESTABBER_STND2, 0}, // S_FACESTABBER_STND1 + {SPR_CBFS, 1, 1, {A_Chase}, 0, 0, S_FACESTABBER_STND3, 0}, // S_FACESTABBER_STND2 + {SPR_CBFS, 2, 1, {A_Chase}, 0, 0, S_FACESTABBER_STND4, 0}, // S_FACESTABBER_STND3 + {SPR_CBFS, 3, 1, {A_Chase}, 0, 0, S_FACESTABBER_STND5, 0}, // S_FACESTABBER_STND4 + {SPR_CBFS, 4, 1, {A_Chase}, 0, 0, S_FACESTABBER_STND6, 0}, // S_FACESTABBER_STND5 + {SPR_CBFS, 5, 1, {A_Chase}, 0, 0, S_FACESTABBER_STND1, 0}, // S_FACESTABBER_STND6 + {SPR_CBFS, 0, 1, {A_FaceStabRev}, 20, S_FACESTABBER_CHARGE2, S_FACESTABBER_CHARGE1, 0}, // S_FACESTABBER_CHARGE1 + {SPR_CBFS, 0, 0, {A_FaceTarget}, 0, 0, S_FACESTABBER_CHARGE3, 0}, // S_FACESTABBER_CHARGE2 + {SPR_CBFS, 7, 1, {A_FaceStabHurl}, 6, S_FACESTABBER_CHARGE4, S_FACESTABBER_CHARGE3, 0}, // S_FACESTABBER_CHARGE3 + {SPR_CBFS, 7, 1, {A_FaceStabMiss}, 0, S_FACESTABBER_STND1, S_FACESTABBER_CHARGE4, 0}, // S_FACESTABBER_CHARGE4 + {SPR_CBFS, 0, 35, {A_Pain}, 0, 0, S_FACESTABBER_STND1, 0}, // S_FACESTABBER_PAIN + {SPR_CBFS, 0, 2, {A_BossScream}, 1, 0, S_FACESTABBER_DIE2, 0}, // S_FACESTABBER_DIE1 + {SPR_NULL, 0, 2, {A_BossScream}, 1, 0, S_FACESTABBER_DIE3, 0}, // S_FACESTABBER_DIE2 + {SPR_NULL, 0, 0, {A_Repeat}, 7, S_FACESTABBER_DIE1, S_XPLD_FLICKY, 0}, // S_FACESTABBER_DIE3 + + {SPR_STAB, FF_PAPERSPRITE|FF_TRANS50|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL, 0}, // S_FACESTABBERSPEAR // Egg Guard - {SPR_SPSH, 0, 1, {A_Look}, 0, 0, S_EGGGUARD_STND}, // S_EGGGUARD_STND - {SPR_SPSH, 1, 3, {A_GuardChase}, 0, 0, S_EGGGUARD_WALK2}, // S_EGGGUARD_WALK1 - {SPR_SPSH, 2, 3, {A_GuardChase}, 0, 0, S_EGGGUARD_WALK3}, // S_EGGGUARD_WALK2 - {SPR_SPSH, 3, 3, {A_GuardChase}, 0, 0, S_EGGGUARD_WALK4}, // S_EGGGUARD_WALK3 - {SPR_SPSH, 4, 3, {A_GuardChase}, 0, 0, S_EGGGUARD_WALK1}, // S_EGGGUARD_WALK4 - {SPR_SPSH, 5, 5, {NULL}, 0, 0, S_EGGGUARD_MAD2}, // S_EGGGUARD_MAD1 - {SPR_SPSH, 6, 5, {NULL}, 0, 0, S_EGGGUARD_MAD3}, // S_EGGGUARD_MAD2 - {SPR_SPSH, 7, 15, {NULL}, 0, 0, S_EGGGUARD_RUN1}, // S_EGGGUARD_MAD3 - {SPR_SPSH, 8, 1, {A_GuardChase}, 0, 0, S_EGGGUARD_RUN2}, // S_EGGGUARD_RUN1 - {SPR_SPSH, 9, 1, {A_GuardChase}, 0, 0, S_EGGGUARD_RUN3}, // S_EGGGUARD_RUN2 - {SPR_SPSH, 10, 1, {A_GuardChase}, 0, 0, S_EGGGUARD_RUN4}, // S_EGGGUARD_RUN3 - {SPR_SPSH, 11, 1, {A_GuardChase}, 0, 0, S_EGGGUARD_RUN1}, // S_EGGGUARD_RUN4 - - {SPR_ESHI, 0, 8, {A_EggShield}, 0, 0, S_EGGSHIELD}, // S_EGGSHIELD - {SPR_ESHI, 0, TICRATE/2, {NULL}, 0, 0, S_NULL}, // S_EGGSHIELDBREAK + {SPR_SPSH, 0, 1, {A_Look}, 0, 0, S_EGGGUARD_STND, 0}, // S_EGGGUARD_STND + {SPR_SPSH, 1, 3, {A_GuardChase}, 0, 0, S_EGGGUARD_WALK2, 0}, // S_EGGGUARD_WALK1 + {SPR_SPSH, 2, 3, {A_GuardChase}, 0, 0, S_EGGGUARD_WALK3, 0}, // S_EGGGUARD_WALK2 + {SPR_SPSH, 3, 3, {A_GuardChase}, 0, 0, S_EGGGUARD_WALK4, 0}, // S_EGGGUARD_WALK3 + {SPR_SPSH, 4, 3, {A_GuardChase}, 0, 0, S_EGGGUARD_WALK1, 0}, // S_EGGGUARD_WALK4 + {SPR_SPSH, 5, 5, {NULL}, 0, 0, S_EGGGUARD_MAD2, 0}, // S_EGGGUARD_MAD1 + {SPR_SPSH, 6, 5, {NULL}, 0, 0, S_EGGGUARD_MAD3, 0}, // S_EGGGUARD_MAD2 + {SPR_SPSH, 7, 15, {NULL}, 0, 0, S_EGGGUARD_RUN1, 0}, // S_EGGGUARD_MAD3 + {SPR_SPSH, 8, 1, {A_GuardChase}, 0, 0, S_EGGGUARD_RUN2, 0}, // S_EGGGUARD_RUN1 + {SPR_SPSH, 9, 1, {A_GuardChase}, 0, 0, S_EGGGUARD_RUN3, 0}, // S_EGGGUARD_RUN2 + {SPR_SPSH, 10, 1, {A_GuardChase}, 0, 0, S_EGGGUARD_RUN4, 0}, // S_EGGGUARD_RUN3 + {SPR_SPSH, 11, 1, {A_GuardChase}, 0, 0, S_EGGGUARD_RUN1, 0}, // S_EGGGUARD_RUN4 + + {SPR_ESHI, 0, 8, {A_EggShield}, 0, 0, S_EGGSHIELD, 0}, // S_EGGSHIELD + {SPR_ESHI, 0, TICRATE/2, {NULL}, 0, 0, S_NULL, 0}, // S_EGGSHIELDBREAK // Green Snapper - {SPR_GSNP, 0, TICRATE, {NULL}, 0, 0, S_SNAPPER_SPAWN2}, // S_SNAPPER_SPAWN - {SPR_GSNP, 0, 2, {A_SnapperSpawn}, MT_SNAPPER_LEG, MT_SNAPPER_HEAD, S_GSNAPPER_STND}, // S_SNAPPER_SPAWN2 - {SPR_GSNP, 0, 1, {A_SnapperThinker}, 0, 0, S_GSNAPPER_STND}, // S_GSNAPPER_STND - {SPR_GSNP, 0, 2, {A_Chase}, 0, 0, S_GSNAPPER2}, // S_GSNAPPER1 - {SPR_GSNP, 1, 2, {A_Chase}, 0, 0, S_GSNAPPER3}, // S_GSNAPPER2 - {SPR_GSNP, 2, 2, {A_Chase}, 0, 0, S_GSNAPPER4}, // S_GSNAPPER3 - {SPR_GSNP, 3, 2, {A_Chase}, 0, 0, S_GSNAPPER1}, // S_GSNAPPER4 - {SPR_GSNP, 0, 0, {A_KillSegments}, 0, 0, S_XPLD_FLICKY}, // S_SNAPPER_XPLD - {SPR_GSNL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SNAPPER_LEG - {SPR_GSNL, 1, -1, {NULL}, 0, 0, S_NULL}, // S_SNAPPER_LEGRAISE - {SPR_GSNH, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SNAPPER_HEAD + {SPR_GSNP, 0, TICRATE, {NULL}, 0, 0, S_SNAPPER_SPAWN2, 0}, // S_SNAPPER_SPAWN + {SPR_GSNP, 0, 2, {A_SnapperSpawn}, MT_SNAPPER_LEG, MT_SNAPPER_HEAD, S_GSNAPPER_STND, 0}, // S_SNAPPER_SPAWN2 + {SPR_GSNP, 0, 1, {A_SnapperThinker}, 0, 0, S_GSNAPPER_STND, 0}, // S_GSNAPPER_STND + {SPR_GSNP, 0, 2, {A_Chase}, 0, 0, S_GSNAPPER2, 0}, // S_GSNAPPER1 + {SPR_GSNP, 1, 2, {A_Chase}, 0, 0, S_GSNAPPER3, 0}, // S_GSNAPPER2 + {SPR_GSNP, 2, 2, {A_Chase}, 0, 0, S_GSNAPPER4, 0}, // S_GSNAPPER3 + {SPR_GSNP, 3, 2, {A_Chase}, 0, 0, S_GSNAPPER1, 0}, // S_GSNAPPER4 + {SPR_GSNP, 0, 0, {A_KillSegments}, 0, 0, S_XPLD_FLICKY, 0}, // S_SNAPPER_XPLD + {SPR_GSNL, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SNAPPER_LEG + {SPR_GSNL, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SNAPPER_LEGRAISE + {SPR_GSNH, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SNAPPER_HEAD // Minus - {SPR_MNUD, 0, 1, {NULL}, 0, 0, S_MINUS_STND}, // S_MINUS_INIT (required for objectplace to work) - {SPR_NULL, 0, 10, {A_Look}, 0, 0, S_MINUS_STND}, // S_MINUS_STND - {SPR_NULL, 0, 1, {A_MinusDigging}, 1, 0, S_MINUS_DIGGING2}, // S_MINUS_DIGGING1 - {SPR_NULL, 0, 1, {A_MinusDigging}, 0, 0, S_MINUS_DIGGING3}, // S_MINUS_DIGGING2 - {SPR_NULL, 0, 1, {A_MinusDigging}, 0, 0, S_MINUS_DIGGING4}, // S_MINUS_DIGGING3 - {SPR_NULL, 0, 1, {A_MinusDigging}, 0, 0, S_MINUS_DIGGING1}, // S_MINUS_DIGGING4 - {SPR_NULL, 0, 25, {NULL}, 0, 0, S_MINUS_POPUP}, // S_MINUS_BURST0 - {SPR_MNUD, FF_ANIMATE, 5, {NULL}, 1, 2, S_MINUS_BURST2}, // S_MINUS_BURST1 - {SPR_MNUD, 1|FF_ANIMATE, 5, {NULL}, 1, 2, S_MINUS_BURST3}, // S_MINUS_BURST2 - {SPR_MNUD, 2|FF_ANIMATE, 5, {NULL}, 1, 2, S_MINUS_BURST4}, // S_MINUS_BURST3 - {SPR_MNUD, 3|FF_ANIMATE, 5, {NULL}, 1, 2, S_MINUS_BURST5}, // S_MINUS_BURST4 - {SPR_MNUD, 4|FF_ANIMATE, 5, {NULL}, 1, 2, S_MINUSDIRT2}, // S_MINUS_BURST5 - {SPR_MNUS, 3, 1, {A_MinusPopup}, 0, 0, S_MINUS_AERIAL1}, // S_MINUS_POPUP - {SPR_MNUS, 0, 1, {A_MinusCheck}, 0, 1, S_MINUS_AERIAL2}, // S_MINUS_AERIAL1 - {SPR_MNUS, 1, 1, {A_MinusCheck}, 0, 1, S_MINUS_AERIAL3}, // S_MINUS_AERIAL2 - {SPR_MNUS, 2, 1, {A_MinusCheck}, 0, 1, S_MINUS_AERIAL4}, // S_MINUS_AERIAL3 - {SPR_MNUS, 3, 1, {A_MinusCheck}, 0, 1, S_MINUS_AERIAL1}, // S_MINUS_AERIAL4 - - {SPR_MNUD, FF_ANIMATE, 6, {NULL}, 1, 5, S_MINUSDIRT2}, // S_MINUSDIRT1 - {SPR_MNUD, 5, 8, {NULL}, 3, 5, S_MINUSDIRT3}, // S_MINUSDIRT2 - {SPR_MNUD, 4, 8, {NULL}, 3, 5, S_MINUSDIRT4}, // S_MINUSDIRT3 - {SPR_MNUD, 3, 8, {NULL}, 3, 5, S_MINUSDIRT5}, // S_MINUSDIRT4 - {SPR_MNUD, 2, 8, {NULL}, 3, 5, S_MINUSDIRT6}, // S_MINUSDIRT5 - {SPR_MNUD, 1, 8, {NULL}, 3, 5, S_MINUSDIRT7}, // S_MINUSDIRT6 - {SPR_MNUD, 0, 8, {NULL}, 3, 5, S_NULL}, // S_MINUSDIRT7 + {SPR_MNUD, 0, 1, {NULL}, 0, 0, S_MINUS_STND, 0}, // S_MINUS_INIT (required for objectplace to work) + {SPR_NULL, 0, 10, {A_Look}, 0, 0, S_MINUS_STND, 0}, // S_MINUS_STND + {SPR_NULL, 0, 1, {A_MinusDigging}, 1, 0, S_MINUS_DIGGING2, 0}, // S_MINUS_DIGGING1 + {SPR_NULL, 0, 1, {A_MinusDigging}, 0, 0, S_MINUS_DIGGING3, 0}, // S_MINUS_DIGGING2 + {SPR_NULL, 0, 1, {A_MinusDigging}, 0, 0, S_MINUS_DIGGING4, 0}, // S_MINUS_DIGGING3 + {SPR_NULL, 0, 1, {A_MinusDigging}, 0, 0, S_MINUS_DIGGING1, 0}, // S_MINUS_DIGGING4 + {SPR_NULL, 0, 25, {NULL}, 0, 0, S_MINUS_POPUP, 0}, // S_MINUS_BURST0 + {SPR_MNUD, FF_ANIMATE, 5, {NULL}, 1, 2, S_MINUS_BURST2, 0}, // S_MINUS_BURST1 + {SPR_MNUD, 1|FF_ANIMATE, 5, {NULL}, 1, 2, S_MINUS_BURST3, 0}, // S_MINUS_BURST2 + {SPR_MNUD, 2|FF_ANIMATE, 5, {NULL}, 1, 2, S_MINUS_BURST4, 0}, // S_MINUS_BURST3 + {SPR_MNUD, 3|FF_ANIMATE, 5, {NULL}, 1, 2, S_MINUS_BURST5, 0}, // S_MINUS_BURST4 + {SPR_MNUD, 4|FF_ANIMATE, 5, {NULL}, 1, 2, S_MINUSDIRT2, 0}, // S_MINUS_BURST5 + {SPR_MNUS, 3, 1, {A_MinusPopup}, 0, 0, S_MINUS_AERIAL1, 0}, // S_MINUS_POPUP + {SPR_MNUS, 0, 1, {A_MinusCheck}, 0, 1, S_MINUS_AERIAL2, 0}, // S_MINUS_AERIAL1 + {SPR_MNUS, 1, 1, {A_MinusCheck}, 0, 1, S_MINUS_AERIAL3, 0}, // S_MINUS_AERIAL2 + {SPR_MNUS, 2, 1, {A_MinusCheck}, 0, 1, S_MINUS_AERIAL4, 0}, // S_MINUS_AERIAL3 + {SPR_MNUS, 3, 1, {A_MinusCheck}, 0, 1, S_MINUS_AERIAL1, 0}, // S_MINUS_AERIAL4 + + {SPR_MNUD, FF_ANIMATE, 6, {NULL}, 1, 5, S_MINUSDIRT2, 0}, // S_MINUSDIRT1 + {SPR_MNUD, 5, 8, {NULL}, 3, 5, S_MINUSDIRT3, 0}, // S_MINUSDIRT2 + {SPR_MNUD, 4, 8, {NULL}, 3, 5, S_MINUSDIRT4, 0}, // S_MINUSDIRT3 + {SPR_MNUD, 3, 8, {NULL}, 3, 5, S_MINUSDIRT5, 0}, // S_MINUSDIRT4 + {SPR_MNUD, 2, 8, {NULL}, 3, 5, S_MINUSDIRT6, 0}, // S_MINUSDIRT5 + {SPR_MNUD, 1, 8, {NULL}, 3, 5, S_MINUSDIRT7, 0}, // S_MINUSDIRT6 + {SPR_MNUD, 0, 8, {NULL}, 3, 5, S_NULL, 0}, // S_MINUSDIRT7 // Spring Shell - {SPR_SSHL, 0, 4, {A_Look}, 0, 0, S_SSHELL_STND}, // S_SSHELL_STND - {SPR_SSHL, 0, 4, {A_Chase}, 0, 0, S_SSHELL_RUN2}, // S_SSHELL_RUN1 - {SPR_SSHL, 1, 4, {A_Chase}, 0, 0, S_SSHELL_RUN3}, // S_SSHELL_RUN2 - {SPR_SSHL, 2, 4, {A_Chase}, 0, 0, S_SSHELL_RUN4}, // S_SSHELL_RUN3 - {SPR_SSHL, 3, 4, {A_Chase}, 0, 0, S_SSHELL_RUN1}, // S_SSHELL_RUN4 - {SPR_SSHL, 7, 4, {A_Pain}, 0, 0, S_SSHELL_SPRING2}, // S_SSHELL_SPRING1 - {SPR_SSHL, 6, 1, {NULL}, 0, 0, S_SSHELL_SPRING3}, // S_SSHELL_SPRING2 - {SPR_SSHL, 5, 1, {NULL}, 0, 0, S_SSHELL_SPRING4}, // S_SSHELL_SPRING3 - {SPR_SSHL, 4, 1, {NULL}, 0, 0, S_SSHELL_RUN1}, // S_SSHELL_SPRING4 + {SPR_SSHL, 0, 4, {A_Look}, 0, 0, S_SSHELL_STND, 0}, // S_SSHELL_STND + {SPR_SSHL, 0, 4, {A_Chase}, 0, 0, S_SSHELL_RUN2, 0}, // S_SSHELL_RUN1 + {SPR_SSHL, 1, 4, {A_Chase}, 0, 0, S_SSHELL_RUN3, 0}, // S_SSHELL_RUN2 + {SPR_SSHL, 2, 4, {A_Chase}, 0, 0, S_SSHELL_RUN4, 0}, // S_SSHELL_RUN3 + {SPR_SSHL, 3, 4, {A_Chase}, 0, 0, S_SSHELL_RUN1, 0}, // S_SSHELL_RUN4 + {SPR_SSHL, 7, 4, {A_Pain}, 0, 0, S_SSHELL_SPRING2, 0}, // S_SSHELL_SPRING1 + {SPR_SSHL, 6, 1, {NULL}, 0, 0, S_SSHELL_SPRING3, 0}, // S_SSHELL_SPRING2 + {SPR_SSHL, 5, 1, {NULL}, 0, 0, S_SSHELL_SPRING4, 0}, // S_SSHELL_SPRING3 + {SPR_SSHL, 4, 1, {NULL}, 0, 0, S_SSHELL_RUN1, 0}, // S_SSHELL_SPRING4 // Spring Shell (yellow) - {SPR_SSHL, 8, 4, {A_Look}, 0, 0, S_YSHELL_STND}, // S_YSHELL_STND - {SPR_SSHL, 8, 4, {A_Chase}, 0, 0, S_YSHELL_RUN2}, // S_YSHELL_RUN1 - {SPR_SSHL, 9, 4, {A_Chase}, 0, 0, S_YSHELL_RUN3}, // S_YSHELL_RUN2 - {SPR_SSHL, 10, 4, {A_Chase}, 0, 0, S_YSHELL_RUN4}, // S_YSHELL_RUN3 - {SPR_SSHL, 11, 4, {A_Chase}, 0, 0, S_YSHELL_RUN1}, // S_YSHELL_RUN4 - {SPR_SSHL, 15, 4, {A_Pain}, 0, 0, S_YSHELL_SPRING2}, // S_YSHELL_SPRING1 - {SPR_SSHL, 14, 1, {NULL}, 0, 0, S_YSHELL_SPRING3}, // S_YSHELL_SPRING2 - {SPR_SSHL, 13, 1, {NULL}, 0, 0, S_YSHELL_SPRING4}, // S_YSHELL_SPRING3 - {SPR_SSHL, 12, 1, {NULL}, 0, 0, S_YSHELL_RUN1}, // S_YSHELL_SPRING4 + {SPR_SSHL, 8, 4, {A_Look}, 0, 0, S_YSHELL_STND, 0}, // S_YSHELL_STND + {SPR_SSHL, 8, 4, {A_Chase}, 0, 0, S_YSHELL_RUN2, 0}, // S_YSHELL_RUN1 + {SPR_SSHL, 9, 4, {A_Chase}, 0, 0, S_YSHELL_RUN3, 0}, // S_YSHELL_RUN2 + {SPR_SSHL, 10, 4, {A_Chase}, 0, 0, S_YSHELL_RUN4, 0}, // S_YSHELL_RUN3 + {SPR_SSHL, 11, 4, {A_Chase}, 0, 0, S_YSHELL_RUN1, 0}, // S_YSHELL_RUN4 + {SPR_SSHL, 15, 4, {A_Pain}, 0, 0, S_YSHELL_SPRING2, 0}, // S_YSHELL_SPRING1 + {SPR_SSHL, 14, 1, {NULL}, 0, 0, S_YSHELL_SPRING3, 0}, // S_YSHELL_SPRING2 + {SPR_SSHL, 13, 1, {NULL}, 0, 0, S_YSHELL_SPRING4, 0}, // S_YSHELL_SPRING3 + {SPR_SSHL, 12, 1, {NULL}, 0, 0, S_YSHELL_RUN1, 0}, // S_YSHELL_SPRING4 // Unidus - {SPR_UNID, 0, 4, {A_Look}, 0, 0, S_UNIDUS_STND}, // S_UNIDUS_STND - {SPR_UNID, 0, 1, {A_Chase}, 0, 0, S_UNIDUS_RUN }, // S_UNIDUS_RUN - {SPR_UNID, 1, 1, {A_UnidusBall}, 1, 0, S_UNIDUS_BALL}, // S_UNIDUS_BALL + {SPR_UNID, 0, 4, {A_Look}, 0, 0, S_UNIDUS_STND, 0}, // S_UNIDUS_STND + {SPR_UNID, 0, 1, {A_Chase}, 0, 0, S_UNIDUS_RUN , 0}, // S_UNIDUS_RUN + {SPR_UNID, 1, 1, {A_UnidusBall}, 1, 0, S_UNIDUS_BALL, 0}, // S_UNIDUS_BALL // Canarivore - {SPR_CANA, 0, 5, {A_Look}, 1200*FRACUNIT+1, 1, S_CANARIVORE_LOOK}, // S_CANARIVORE_LOOK - {SPR_CANA, 0, 3, {A_PlaySound}, sfx_s3k76, 1, S_CANARIVORE_AWAKEN2}, // S_CANARIVORE_AWAKEN1 - {SPR_CANA, 1, 5, {NULL}, 0, 0, S_CANARIVORE_AWAKEN3}, // S_CANARIVORE_AWAKEN2 - {SPR_CANA, 2, 8, {NULL}, 0, 0, S_CANARIVORE_GAS1}, // S_CANARIVORE_AWAKEN3 - {SPR_CANA, 2, 15, {A_PlaySound}, sfx_s3k93, 1, S_CANARIVORE_GAS2}, // S_CANARIVORE_GAS1 - {SPR_CANA, 1, 4, {NULL}, 0, 0, S_CANARIVORE_GAS3}, // S_CANARIVORE_GAS2 - {SPR_CANA, 2, 0, {A_PlaySound}, sfx_s3k97, 1, S_CANARIVORE_GAS4}, // S_CANARIVORE_GAS3 - {SPR_CANA, 2, 5, {A_CanarivoreGas}, MT_CANARIVORE_GAS, 0, S_CANARIVORE_GAS5}, // S_CANARIVORE_GAS4 - {SPR_CANA, 1, 5, {NULL}, 0, 0, S_CANARIVORE_GASREPEAT}, // S_CANARIVORE_GAS5 - {SPR_CANA, 2, 0, {A_Repeat}, 6, S_CANARIVORE_GAS4, S_CANARIVORE_CLOSE1}, // S_CANARIVORE_GASREPEAT - {SPR_CANA, 1, 8, {NULL}, 0, 0, S_CANARIVORE_CLOSE2}, // S_CANARIVORE_CLOSE1 - {SPR_CANA, 0, 90, {NULL}, sfx_s3k5d, 1, S_CANARIVORE_LOOK}, // S_CANARIVORE_CLOSE2 - - {SPR_CANG, 0|FF_TRANS90, 2, {NULL}, 0, 0, S_CANARIVOREGAS_2}, // S_CANARIVOREGAS_1 - {SPR_CANG, 0|FF_TRANS30, 2*TICRATE, {A_SetRandomTics}, 2, TICRATE, S_CANARIVOREGAS_3}, // S_CANARIVOREGAS_2 - {SPR_CANG, 0|FF_TRANS40, 10, {NULL}, 0, 0, S_CANARIVOREGAS_4}, // S_CANARIVOREGAS_3 - {SPR_CANG, 0|FF_TRANS50, 10, {NULL}, 0, 0, S_CANARIVOREGAS_5}, // S_CANARIVOREGAS_4 - {SPR_CANG, 0|FF_TRANS60, 10, {NULL}, 0, 0, S_CANARIVOREGAS_6}, // S_CANARIVOREGAS_5 - {SPR_CANG, 0|FF_TRANS70, 10, {NULL}, 0, 0, S_CANARIVOREGAS_7}, // S_CANARIVOREGAS_6 - {SPR_CANG, 0|FF_TRANS80, 10, {NULL}, 0, 0, S_CANARIVOREGAS_8}, // S_CANARIVOREGAS_7 - {SPR_CANG, 0|FF_TRANS90, 10, {NULL}, 0, 0, S_NULL}, // S_CANARIVOREGAS_8 + {SPR_CANA, 0, 5, {A_Look}, 1200*FRACUNIT+1, 1, S_CANARIVORE_LOOK, 0}, // S_CANARIVORE_LOOK + {SPR_CANA, 0, 3, {A_PlaySound}, sfx_s3k76, 1, S_CANARIVORE_AWAKEN2, 0}, // S_CANARIVORE_AWAKEN1 + {SPR_CANA, 1, 5, {NULL}, 0, 0, S_CANARIVORE_AWAKEN3, 0}, // S_CANARIVORE_AWAKEN2 + {SPR_CANA, 2, 8, {NULL}, 0, 0, S_CANARIVORE_GAS1, 0}, // S_CANARIVORE_AWAKEN3 + {SPR_CANA, 2, 15, {A_PlaySound}, sfx_s3k93, 1, S_CANARIVORE_GAS2, 0}, // S_CANARIVORE_GAS1 + {SPR_CANA, 1, 4, {NULL}, 0, 0, S_CANARIVORE_GAS3, 0}, // S_CANARIVORE_GAS2 + {SPR_CANA, 2, 0, {A_PlaySound}, sfx_s3k97, 1, S_CANARIVORE_GAS4, 0}, // S_CANARIVORE_GAS3 + {SPR_CANA, 2, 5, {A_CanarivoreGas}, MT_CANARIVORE_GAS, 0, S_CANARIVORE_GAS5, 0}, // S_CANARIVORE_GAS4 + {SPR_CANA, 1, 5, {NULL}, 0, 0, S_CANARIVORE_GASREPEAT, 0}, // S_CANARIVORE_GAS5 + {SPR_CANA, 2, 0, {A_Repeat}, 6, S_CANARIVORE_GAS4, S_CANARIVORE_CLOSE1, 0}, // S_CANARIVORE_GASREPEAT + {SPR_CANA, 1, 8, {NULL}, 0, 0, S_CANARIVORE_CLOSE2, 0}, // S_CANARIVORE_CLOSE1 + {SPR_CANA, 0, 90, {NULL}, sfx_s3k5d, 1, S_CANARIVORE_LOOK, 0}, // S_CANARIVORE_CLOSE2 + + {SPR_CANG, 0|FF_TRANS90, 2, {NULL}, 0, 0, S_CANARIVOREGAS_2, 0}, // S_CANARIVOREGAS_1 + {SPR_CANG, 0|FF_TRANS30, 2*TICRATE, {A_SetRandomTics}, 2, TICRATE, S_CANARIVOREGAS_3, 0}, // S_CANARIVOREGAS_2 + {SPR_CANG, 0|FF_TRANS40, 10, {NULL}, 0, 0, S_CANARIVOREGAS_4, 0}, // S_CANARIVOREGAS_3 + {SPR_CANG, 0|FF_TRANS50, 10, {NULL}, 0, 0, S_CANARIVOREGAS_5, 0}, // S_CANARIVOREGAS_4 + {SPR_CANG, 0|FF_TRANS60, 10, {NULL}, 0, 0, S_CANARIVOREGAS_6, 0}, // S_CANARIVOREGAS_5 + {SPR_CANG, 0|FF_TRANS70, 10, {NULL}, 0, 0, S_CANARIVOREGAS_7, 0}, // S_CANARIVOREGAS_6 + {SPR_CANG, 0|FF_TRANS80, 10, {NULL}, 0, 0, S_CANARIVOREGAS_8, 0}, // S_CANARIVOREGAS_7 + {SPR_CANG, 0|FF_TRANS90, 10, {NULL}, 0, 0, S_NULL, 0}, // S_CANARIVOREGAS_8 // Pyre Fly - {SPR_PYRE, FF_ANIMATE, -1, {NULL}, 3, 2, S_NULL}, // S_PYREFLY_FLY - {SPR_PYRE, 4|FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 3, 2, S_NULL}, // S_PYREFLY_BURN - {SPR_FLAM, FF_FULLBRIGHT, 10, {NULL}, 0, 0, S_PYREFIRE2}, // S_PYREFIRE1 - {SPR_FLAM, 1|FF_FULLBRIGHT, 10, {A_FireShrink}, 0, 16, S_NULL}, // S_PYREFIRE2 + {SPR_PYRE, FF_ANIMATE, -1, {NULL}, 3, 2, S_NULL, 0}, // S_PYREFLY_FLY + {SPR_PYRE, 4|FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 3, 2, S_NULL, 0}, // S_PYREFLY_BURN + {SPR_FLAM, FF_FULLBRIGHT, 10, {NULL}, 0, 0, S_PYREFIRE2, 0}, // S_PYREFIRE1 + {SPR_FLAM, 1|FF_FULLBRIGHT, 10, {A_FireShrink}, 0, 16, S_NULL, 0}, // S_PYREFIRE2 // Pterabyte - {SPR_NULL, 0, -1, {A_SpawnPterabytes}, 0, 0, S_PTERABYTESPAWNER}, // S_PTERABYTESPAWNER - {SPR_NULL, 0, 1, {A_PterabyteHover}, 0, 0, S_PTERABYTEWAYPOINT}, // S_PTERABYTEWAYPOINT - {SPR_PTER, 0, 6, {NULL}, 0, 0, S_PTERABYTE_FLY2}, // S_PTERABYTE_FLY1 - {SPR_PTER, 1, 2, {NULL}, 0, 0, S_PTERABYTE_FLY3}, // S_PTERABYTE_FLY2 - {SPR_PTER, 2, 6, {NULL}, 0, 0, S_PTERABYTE_FLY4}, // S_PTERABYTE_FLY3 - {SPR_PTER, 3, 2, {NULL}, 0, 0, S_PTERABYTE_FLY1}, // S_PTERABYTE_FLY4 - {SPR_PTER, 4, 1, {NULL}, 0, 0, S_PTERABYTE_SWOOPDOWN}, // S_PTERABYTE_SWOOPDOWN - {SPR_PTER, 0, 1, {NULL}, 0, 0, S_PTERABYTE_SWOOPUP}, // S_PTERABYTE_SWOOPUP + {SPR_NULL, 0, -1, {A_SpawnPterabytes}, 0, 0, S_PTERABYTESPAWNER, 0}, // S_PTERABYTESPAWNER + {SPR_NULL, 0, 1, {A_PterabyteHover}, 0, 0, S_PTERABYTEWAYPOINT, 0}, // S_PTERABYTEWAYPOINT + {SPR_PTER, 0, 6, {NULL}, 0, 0, S_PTERABYTE_FLY2, 0}, // S_PTERABYTE_FLY1 + {SPR_PTER, 1, 2, {NULL}, 0, 0, S_PTERABYTE_FLY3, 0}, // S_PTERABYTE_FLY2 + {SPR_PTER, 2, 6, {NULL}, 0, 0, S_PTERABYTE_FLY4, 0}, // S_PTERABYTE_FLY3 + {SPR_PTER, 3, 2, {NULL}, 0, 0, S_PTERABYTE_FLY1, 0}, // S_PTERABYTE_FLY4 + {SPR_PTER, 4, 1, {NULL}, 0, 0, S_PTERABYTE_SWOOPDOWN, 0}, // S_PTERABYTE_SWOOPDOWN + {SPR_PTER, 0, 1, {NULL}, 0, 0, S_PTERABYTE_SWOOPUP, 0}, // S_PTERABYTE_SWOOPUP // Dragonbomber - {SPR_DRAB, 0, -1, {A_DragonbomberSpawn}, 6, 0, S_NULL}, // S_DRAGONBOMBER - {SPR_DRAB, FF_PAPERSPRITE|7, 1, {A_DragonWing}, 0, 0, S_DRAGONWING2}, // S_DRAGONWING1 - {SPR_DRAB, FF_PAPERSPRITE|8, 1, {A_DragonWing}, 0, 0, S_DRAGONWING3}, // S_DRAGONWING2 - {SPR_DRAB, FF_PAPERSPRITE|9, 1, {A_DragonWing}, 0, 0, S_DRAGONWING4}, // S_DRAGONWING3 - {SPR_DRAB, FF_PAPERSPRITE|10, 1, {A_DragonWing}, 0, 0, S_DRAGONWING1}, // S_DRAGONWING4 - {SPR_DRAB, 1, 1, {A_DragonSegment}, 0, 0, S_DRAGONTAIL_LOADED}, // S_DRAGONTAIL_LOADED - {SPR_DRAB, 2, 1, {A_DragonSegment}, 0, 0, S_DRAGONTAIL_EMPTYLOOP}, // S_DRAGONTAIL_EMPTY - {SPR_DRAB, 2, 0, {A_Repeat}, 3*TICRATE, S_DRAGONTAIL_EMPTY, S_DRAGONTAIL_RELOAD}, // S_DRAGONTAIL_EMPTYLOOP - {SPR_DRAB, 1, 0, {A_PlayActiveSound}, 0, 0, S_DRAGONTAIL_LOADED}, // S_DRAGONTAIL_RELOAD - {SPR_DRAB, 3, 1, {A_MinusCheck}, S_DRAGONMINE_LAND1, 0, S_DRAGONMINE}, // S_DRAGONMINE - {SPR_DRAB, 4, 0, {A_PlayActiveSound}, 0, 0, S_DRAGONMINE_LAND2}, // S_DRAGONMINE_LAND1 - {SPR_DRAB, 4, 2, {A_Thrust}, 0, 1, S_DRAGONMINE_SLOWFLASH1}, // S_DRAGONMINE_LAND2 - {SPR_DRAB, 5, 11, {NULL}, 0, 0, S_DRAGONMINE_SLOWFLASH2}, // S_DRAGONMINE_SLOWFLASH1 - {SPR_DRAB, FF_FULLBRIGHT|6, 1, {A_PlayAttackSound}, 0, 0, S_DRAGONMINE_SLOWLOOP}, // S_DRAGONMINE_SLOWFLASH2 - {SPR_DRAB, 5, 0, {A_Repeat}, 4, S_DRAGONMINE_SLOWFLASH1, S_DRAGONMINE_FASTFLASH1}, // S_DRAGONMINE_SLOWLOOP - {SPR_DRAB, 5, 3, {NULL}, 0, 0, S_DRAGONMINE_FASTFLASH2}, // S_DRAGONMINE_FASTFLASH1 - {SPR_DRAB, FF_FULLBRIGHT|6, 1, {A_PlayAttackSound}, 0, 0, S_DRAGONMINE_FASTLOOP}, // S_DRAGONMINE_FASTFLASH2 - {SPR_DRAB, 5, 0, {A_Repeat}, 5, S_DRAGONMINE_FASTFLASH1, S_DEATHSTATE}, // S_DRAGONMINE_FASTLOOP + {SPR_DRAB, 0, -1, {A_DragonbomberSpawn}, 6, 0, S_NULL, 0}, // S_DRAGONBOMBER + {SPR_DRAB, FF_PAPERSPRITE|7, 1, {A_DragonWing}, 0, 0, S_DRAGONWING2, 0}, // S_DRAGONWING1 + {SPR_DRAB, FF_PAPERSPRITE|8, 1, {A_DragonWing}, 0, 0, S_DRAGONWING3, 0}, // S_DRAGONWING2 + {SPR_DRAB, FF_PAPERSPRITE|9, 1, {A_DragonWing}, 0, 0, S_DRAGONWING4, 0}, // S_DRAGONWING3 + {SPR_DRAB, FF_PAPERSPRITE|10, 1, {A_DragonWing}, 0, 0, S_DRAGONWING1, 0}, // S_DRAGONWING4 + {SPR_DRAB, 1, 1, {A_DragonSegment}, 0, 0, S_DRAGONTAIL_LOADED, 0}, // S_DRAGONTAIL_LOADED + {SPR_DRAB, 2, 1, {A_DragonSegment}, 0, 0, S_DRAGONTAIL_EMPTYLOOP, 0}, // S_DRAGONTAIL_EMPTY + {SPR_DRAB, 2, 0, {A_Repeat}, 3*TICRATE, S_DRAGONTAIL_EMPTY, S_DRAGONTAIL_RELOAD, 0}, // S_DRAGONTAIL_EMPTYLOOP + {SPR_DRAB, 1, 0, {A_PlayActiveSound}, 0, 0, S_DRAGONTAIL_LOADED, 0}, // S_DRAGONTAIL_RELOAD + {SPR_DRAB, 3, 1, {A_MinusCheck}, S_DRAGONMINE_LAND1, 0, S_DRAGONMINE, 0}, // S_DRAGONMINE + {SPR_DRAB, 4, 0, {A_PlayActiveSound}, 0, 0, S_DRAGONMINE_LAND2, 0}, // S_DRAGONMINE_LAND1 + {SPR_DRAB, 4, 2, {A_Thrust}, 0, 1, S_DRAGONMINE_SLOWFLASH1, 0}, // S_DRAGONMINE_LAND2 + {SPR_DRAB, 5, 11, {NULL}, 0, 0, S_DRAGONMINE_SLOWFLASH2, 0}, // S_DRAGONMINE_SLOWFLASH1 + {SPR_DRAB, FF_FULLBRIGHT|6, 1, {A_PlayAttackSound}, 0, 0, S_DRAGONMINE_SLOWLOOP, 0}, // S_DRAGONMINE_SLOWFLASH2 + {SPR_DRAB, 5, 0, {A_Repeat}, 4, S_DRAGONMINE_SLOWFLASH1, S_DRAGONMINE_FASTFLASH1, 0}, // S_DRAGONMINE_SLOWLOOP + {SPR_DRAB, 5, 3, {NULL}, 0, 0, S_DRAGONMINE_FASTFLASH2, 0}, // S_DRAGONMINE_FASTFLASH1 + {SPR_DRAB, FF_FULLBRIGHT|6, 1, {A_PlayAttackSound}, 0, 0, S_DRAGONMINE_FASTLOOP, 0}, // S_DRAGONMINE_FASTFLASH2 + {SPR_DRAB, 5, 0, {A_Repeat}, 5, S_DRAGONMINE_FASTFLASH1, S_DEATHSTATE, 0}, // S_DRAGONMINE_FASTLOOP // Boss Explosion - {SPR_BOM2, FF_FULLBRIGHT|FF_ANIMATE, (5*7), {NULL}, 6, 5, S_NULL}, // S_BOSSEXPLODE + {SPR_BOM2, FF_FULLBRIGHT|FF_ANIMATE, (5*7), {NULL}, 6, 5, S_NULL, 0}, // S_BOSSEXPLODE // S3&K Boss Explosion - {SPR_BOM3, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_SONIC3KBOSSEXPLOSION2}, // S_SONIC3KBOSSEXPLOSION1 - {SPR_BOM3, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_SONIC3KBOSSEXPLOSION3}, // S_SONIC3KBOSSEXPLOSION2 - {SPR_BOM3, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_SONIC3KBOSSEXPLOSION4}, // S_SONIC3KBOSSEXPLOSION3 - {SPR_BOM3, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_SONIC3KBOSSEXPLOSION5}, // S_SONIC3KBOSSEXPLOSION4 - {SPR_BOM3, FF_FULLBRIGHT|4, 3, {NULL}, 0, 0, S_SONIC3KBOSSEXPLOSION6}, // S_SONIC3KBOSSEXPLOSION5 - {SPR_BOM3, FF_FULLBRIGHT|5, 4, {NULL}, 0, 0, S_NULL}, // S_SONIC3KBOSSEXPLOSION6 + {SPR_BOM3, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_SONIC3KBOSSEXPLOSION2, 0}, // S_SONIC3KBOSSEXPLOSION1 + {SPR_BOM3, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_SONIC3KBOSSEXPLOSION3, 0}, // S_SONIC3KBOSSEXPLOSION2 + {SPR_BOM3, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_SONIC3KBOSSEXPLOSION4, 0}, // S_SONIC3KBOSSEXPLOSION3 + {SPR_BOM3, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_SONIC3KBOSSEXPLOSION5, 0}, // S_SONIC3KBOSSEXPLOSION4 + {SPR_BOM3, FF_FULLBRIGHT|4, 3, {NULL}, 0, 0, S_SONIC3KBOSSEXPLOSION6, 0}, // S_SONIC3KBOSSEXPLOSION5 + {SPR_BOM3, FF_FULLBRIGHT|5, 4, {NULL}, 0, 0, S_NULL, 0}, // S_SONIC3KBOSSEXPLOSION6 - {SPR_JETF, FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 2, 1, S_NULL}, // S_JETFUME1 + {SPR_JETF, FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 2, 1, S_NULL, 0}, // S_JETFUME1 // Boss 1 - {SPR_EGGM, 0, 1, {A_Boss1Chase}, 0, 0, S_EGGMOBILE_STND}, // S_EGGMOBILE_STND - {SPR_EGGM, FF_ANIMATE|17, 35, {A_FaceTarget}, 1, 2, S_EGGMOBILE_STND}, // S_EGGMOBILE_ROFL - {SPR_EGGM, 1, 3, {A_FaceTarget}, 0, 0, S_EGGMOBILE_LATK2}, // S_EGGMOBILE_LATK1 - {SPR_EGGM, 2, 15, {NULL}, 0, 0, S_EGGMOBILE_LATK3}, // S_EGGMOBILE_LATK2 - {SPR_EGGM, 3, 2, {NULL}, 0, 0, S_EGGMOBILE_LATK4}, // S_EGGMOBILE_LATK3 - {SPR_EGGM, 4, 2, {A_FaceTarget}, 0, 0, S_EGGMOBILE_LATK5}, // S_EGGMOBILE_LATK4 - {SPR_EGGM, 6, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_LATK6}, // S_EGGMOBILE_LATK5 - {SPR_EGGM, 5, 1, {A_Boss1Laser}, MT_LASER, 0, S_EGGMOBILE_LATK7}, // S_EGGMOBILE_LATK6 - {SPR_EGGM, 6, 1, {A_Boss1Laser}, MT_LASER, (1<<16), S_EGGMOBILE_LATK8}, // S_EGGMOBILE_LATK7 - {SPR_EGGM, 5, 0, {A_Repeat}, 45, S_EGGMOBILE_LATK6, S_EGGMOBILE_LATK9}, // S_EGGMOBILE_LATK8 - {SPR_EGGM, 8, 2, {NULL}, 0, 0, S_EGGMOBILE_ROFL}, // S_EGGMOBILE_LATK9 - {SPR_EGGM, 9, 3, {A_FaceTarget}, 0, 0, S_EGGMOBILE_RATK2}, // S_EGGMOBILE_RATK1 - {SPR_EGGM, 10, 15, {NULL}, 0, 0, S_EGGMOBILE_RATK3}, // S_EGGMOBILE_RATK2 - {SPR_EGGM, 11, 2, {NULL}, 0, 0, S_EGGMOBILE_RATK4}, // S_EGGMOBILE_RATK3 - {SPR_EGGM, 12, 2, {A_FaceTarget}, 0, 0, S_EGGMOBILE_RATK5}, // S_EGGMOBILE_RATK4 - {SPR_EGGM, 14, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_RATK6}, // S_EGGMOBILE_RATK5 - {SPR_EGGM, 13, 1, {A_Boss1Laser}, MT_LASER, 1, S_EGGMOBILE_RATK7}, // S_EGGMOBILE_RATK6 - {SPR_EGGM, 14, 1, {A_Boss1Laser}, MT_LASER, 1|(1<<16), S_EGGMOBILE_RATK8}, // S_EGGMOBILE_RATK7 - {SPR_EGGM, 13, 0, {A_Repeat}, 45, S_EGGMOBILE_RATK6, S_EGGMOBILE_RATK9}, // S_EGGMOBILE_RATK8 - {SPR_EGGM, 16, 2, {NULL}, 0, 0, S_EGGMOBILE_ROFL}, // S_EGGMOBILE_RATK9 - {SPR_EGGM, 0, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_PANIC2}, // S_EGGMOBILE_PANIC1 - {SPR_EGGM, FF_ANIMATE|1, 16, {A_FaceTarget}, 3, 4, S_EGGMOBILE_PANIC3}, // S_EGGMOBILE_PANIC2 - {SPR_EGGM, 7, 1, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC4}, // S_EGGMOBILE_PANIC3 - {SPR_EGGM, 6, 1, {A_Boss1Laser}, MT_LASER, 2|(1<<16), S_EGGMOBILE_PANIC5}, // S_EGGMOBILE_PANIC4 - {SPR_EGGM, 6, 0, {A_Repeat}, 45, S_EGGMOBILE_PANIC3, S_EGGMOBILE_PANIC6}, // S_EGGMOBILE_PANIC5 - {SPR_EGGM, 0, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_PANIC7}, // S_EGGMOBILE_PANIC6 - {SPR_EGGM, FF_ANIMATE|9, 16, {A_FaceTarget}, 3, 4, S_EGGMOBILE_PANIC8}, // S_EGGMOBILE_PANIC7 - {SPR_EGGM, 15, 1, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC9}, // S_EGGMOBILE_PANIC8 - {SPR_EGGM, 14, 1, {A_Boss1Laser}, MT_LASER, 2|(1<<16), S_EGGMOBILE_PANIC10}, // S_EGGMOBILE_PANIC9 - {SPR_EGGM, 14, 0, {A_Repeat}, 45, S_EGGMOBILE_PANIC8, S_EGGMOBILE_PANIC11}, // S_EGGMOBILE_PANIC10 - {SPR_EGGM, 0, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_PANIC12}, // S_EGGMOBILE_PANIC11 - {SPR_EGGM, FF_ANIMATE|1, 16, {A_FaceTarget}, 3, 4, S_EGGMOBILE_PANIC13}, // S_EGGMOBILE_PANIC12 - {SPR_EGGM, 7, 1, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC14}, // S_EGGMOBILE_PANIC13 - {SPR_EGGM, 6, 1, {A_Boss1Laser}, MT_LASER, 2|(1<<16), S_EGGMOBILE_PANIC15}, // S_EGGMOBILE_PANIC14 - {SPR_EGGM, 6, 0, {A_Repeat}, 45, S_EGGMOBILE_PANIC13, S_EGGMOBILE_ROFL}, // S_EGGMOBILE_PANIC15 - {SPR_EGGM, 19, 24, {A_Pain}, 0, 0, S_EGGMOBILE_PAIN2}, // S_EGGMOBILE_PAIN - {SPR_EGGM, 19, 16, {A_SkullAttack}, 3, 1, S_EGGMOBILE_STND}, // S_EGGMOBILE_PAIN2 - {SPR_EGGM, 20, 2, {A_Fall}, 17, 0, S_EGGMOBILE_DIE2}, // S_EGGMOBILE_DIE1 - {SPR_EGGM, 20, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_DIE3}, // S_EGGMOBILE_DIE2 - {SPR_EGGM, 20, 0, {A_Repeat}, 17, S_EGGMOBILE_DIE2, S_EGGMOBILE_DIE4}, // S_EGGMOBILE_DIE3 - {SPR_EGGM, 20, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_EGGMOBILE_DIE4 - {SPR_EGGM, 21, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_FLEE2}, // S_EGGMOBILE_FLEE1 - {SPR_EGGM, 22, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_FLEE1}, // S_EGGMOBILE_FLEE2 - {SPR_UNID, 1, 1, {A_UnidusBall}, 2, 0, S_EGGMOBILE_BALL}, // S_EGGMOBILE_BALL - {SPR_NULL, 0, 1, {A_FocusTarget}, 0, 0, S_EGGMOBILE_TARGET}, // S_EGGMOBILE_TARGET - - {SPR_EGLZ, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSEGLZ1 - {SPR_EGLZ, 1, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSEGLZ2 + {SPR_EGGM, 0, 1, {A_Boss1Chase}, 0, 0, S_EGGMOBILE_STND, 0}, // S_EGGMOBILE_STND + {SPR_EGGM, FF_ANIMATE|17, 35, {A_FaceTarget}, 1, 2, S_EGGMOBILE_STND, 0}, // S_EGGMOBILE_ROFL + {SPR_EGGM, 1, 3, {A_FaceTarget}, 0, 0, S_EGGMOBILE_LATK2, 0}, // S_EGGMOBILE_LATK1 + {SPR_EGGM, 2, 15, {NULL}, 0, 0, S_EGGMOBILE_LATK3, 0}, // S_EGGMOBILE_LATK2 + {SPR_EGGM, 3, 2, {NULL}, 0, 0, S_EGGMOBILE_LATK4, 0}, // S_EGGMOBILE_LATK3 + {SPR_EGGM, 4, 2, {A_FaceTarget}, 0, 0, S_EGGMOBILE_LATK5, 0}, // S_EGGMOBILE_LATK4 + {SPR_EGGM, 6, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_LATK6, 0}, // S_EGGMOBILE_LATK5 + {SPR_EGGM, 5, 1, {A_Boss1Laser}, MT_LASER, 0, S_EGGMOBILE_LATK7, 0}, // S_EGGMOBILE_LATK6 + {SPR_EGGM, 6, 1, {A_Boss1Laser}, MT_LASER, (1<<16), S_EGGMOBILE_LATK8, 0}, // S_EGGMOBILE_LATK7 + {SPR_EGGM, 5, 0, {A_Repeat}, 45, S_EGGMOBILE_LATK6, S_EGGMOBILE_LATK9, 0}, // S_EGGMOBILE_LATK8 + {SPR_EGGM, 8, 2, {NULL}, 0, 0, S_EGGMOBILE_ROFL, 0}, // S_EGGMOBILE_LATK9 + {SPR_EGGM, 9, 3, {A_FaceTarget}, 0, 0, S_EGGMOBILE_RATK2, 0}, // S_EGGMOBILE_RATK1 + {SPR_EGGM, 10, 15, {NULL}, 0, 0, S_EGGMOBILE_RATK3, 0}, // S_EGGMOBILE_RATK2 + {SPR_EGGM, 11, 2, {NULL}, 0, 0, S_EGGMOBILE_RATK4, 0}, // S_EGGMOBILE_RATK3 + {SPR_EGGM, 12, 2, {A_FaceTarget}, 0, 0, S_EGGMOBILE_RATK5, 0}, // S_EGGMOBILE_RATK4 + {SPR_EGGM, 14, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_RATK6, 0}, // S_EGGMOBILE_RATK5 + {SPR_EGGM, 13, 1, {A_Boss1Laser}, MT_LASER, 1, S_EGGMOBILE_RATK7, 0}, // S_EGGMOBILE_RATK6 + {SPR_EGGM, 14, 1, {A_Boss1Laser}, MT_LASER, 1|(1<<16), S_EGGMOBILE_RATK8, 0}, // S_EGGMOBILE_RATK7 + {SPR_EGGM, 13, 0, {A_Repeat}, 45, S_EGGMOBILE_RATK6, S_EGGMOBILE_RATK9, 0}, // S_EGGMOBILE_RATK8 + {SPR_EGGM, 16, 2, {NULL}, 0, 0, S_EGGMOBILE_ROFL, 0}, // S_EGGMOBILE_RATK9 + {SPR_EGGM, 0, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_PANIC2, 0}, // S_EGGMOBILE_PANIC1 + {SPR_EGGM, FF_ANIMATE|1, 16, {A_FaceTarget}, 3, 4, S_EGGMOBILE_PANIC3, 0}, // S_EGGMOBILE_PANIC2 + {SPR_EGGM, 7, 1, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC4, 0}, // S_EGGMOBILE_PANIC3 + {SPR_EGGM, 6, 1, {A_Boss1Laser}, MT_LASER, 2|(1<<16), S_EGGMOBILE_PANIC5, 0}, // S_EGGMOBILE_PANIC4 + {SPR_EGGM, 6, 0, {A_Repeat}, 45, S_EGGMOBILE_PANIC3, S_EGGMOBILE_PANIC6, 0}, // S_EGGMOBILE_PANIC5 + {SPR_EGGM, 0, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_PANIC7, 0}, // S_EGGMOBILE_PANIC6 + {SPR_EGGM, FF_ANIMATE|9, 16, {A_FaceTarget}, 3, 4, S_EGGMOBILE_PANIC8, 0}, // S_EGGMOBILE_PANIC7 + {SPR_EGGM, 15, 1, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC9, 0}, // S_EGGMOBILE_PANIC8 + {SPR_EGGM, 14, 1, {A_Boss1Laser}, MT_LASER, 2|(1<<16), S_EGGMOBILE_PANIC10, 0}, // S_EGGMOBILE_PANIC9 + {SPR_EGGM, 14, 0, {A_Repeat}, 45, S_EGGMOBILE_PANIC8, S_EGGMOBILE_PANIC11, 0}, // S_EGGMOBILE_PANIC10 + {SPR_EGGM, 0, 0, {A_PrepareRepeat}, 45, 0, S_EGGMOBILE_PANIC12, 0}, // S_EGGMOBILE_PANIC11 + {SPR_EGGM, FF_ANIMATE|1, 16, {A_FaceTarget}, 3, 4, S_EGGMOBILE_PANIC13, 0}, // S_EGGMOBILE_PANIC12 + {SPR_EGGM, 7, 1, {A_Boss1Laser}, MT_LASER, 2, S_EGGMOBILE_PANIC14, 0}, // S_EGGMOBILE_PANIC13 + {SPR_EGGM, 6, 1, {A_Boss1Laser}, MT_LASER, 2|(1<<16), S_EGGMOBILE_PANIC15, 0}, // S_EGGMOBILE_PANIC14 + {SPR_EGGM, 6, 0, {A_Repeat}, 45, S_EGGMOBILE_PANIC13, S_EGGMOBILE_ROFL, 0}, // S_EGGMOBILE_PANIC15 + {SPR_EGGM, 19, 24, {A_Pain}, 0, 0, S_EGGMOBILE_PAIN2, 0}, // S_EGGMOBILE_PAIN + {SPR_EGGM, 19, 16, {A_SkullAttack}, 3, 1, S_EGGMOBILE_STND, 0}, // S_EGGMOBILE_PAIN2 + {SPR_EGGM, 20, 2, {A_Fall}, 17, 0, S_EGGMOBILE_DIE2, 0}, // S_EGGMOBILE_DIE1 + {SPR_EGGM, 20, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_DIE3, 0}, // S_EGGMOBILE_DIE2 + {SPR_EGGM, 20, 0, {A_Repeat}, 17, S_EGGMOBILE_DIE2, S_EGGMOBILE_DIE4, 0}, // S_EGGMOBILE_DIE3 + {SPR_EGGM, 20, -1, {A_BossDeath}, 0, 0, S_NULL, 0}, // S_EGGMOBILE_DIE4 + {SPR_EGGM, 21, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_FLEE2, 0}, // S_EGGMOBILE_FLEE1 + {SPR_EGGM, 22, 2, {A_BossScream}, 0, 0, S_EGGMOBILE_FLEE1, 0}, // S_EGGMOBILE_FLEE2 + {SPR_UNID, 1, 1, {A_UnidusBall}, 2, 0, S_EGGMOBILE_BALL, 0}, // S_EGGMOBILE_BALL + {SPR_NULL, 0, 1, {A_FocusTarget}, 0, 0, S_EGGMOBILE_TARGET, 0}, // S_EGGMOBILE_TARGET + + {SPR_EGLZ, 0, 35, {NULL}, 0, 0, S_NULL, 0}, // S_BOSSEGLZ1 + {SPR_EGLZ, 1, 35, {NULL}, 0, 0, S_NULL, 0}, // S_BOSSEGLZ2 // Boss 2 - {SPR_EGGN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGMOBILE2_STND - {SPR_EGGN, 1, 4, {NULL}, 0, 0, S_EGGMOBILE2_POGO2}, // S_EGGMOBILE2_POGO1 - {SPR_EGGN, 0, 2, {A_Boss2PogoTarget}, 9*FRACUNIT, 8*FRACUNIT, S_EGGMOBILE2_POGO3}, // S_EGGMOBILE2_POGO2 - {SPR_EGGN, 1, 2, {NULL}, 0, 0, S_EGGMOBILE2_POGO4}, // S_EGGMOBILE2_POGO3 - {SPR_EGGN, 2, -1, {NULL}, 0, 0, S_NULL}, // S_EGGMOBILE2_POGO4 - {SPR_EGGN, 1, 4, {NULL}, 0, 0, S_EGGMOBILE2_POGO6}, // S_EGGMOBILE2_POGO5 - {SPR_EGGN, 0, 2, {A_Boss2PogoTarget}, 7*FRACUNIT, 8*FRACUNIT, S_EGGMOBILE2_POGO7}, // S_EGGMOBILE2_POGO6 - {SPR_EGGN, 1, 2, {NULL}, 0, 0, S_EGGMOBILE2_POGO4}, // S_EGGMOBILE2_POGO7 - {SPR_EGGN, 3, 24, {A_Boss2TakeDamage}, 24+TICRATE, 0, S_EGGMOBILE2_STND}, // S_EGGMOBILE2_PAIN - {SPR_EGGN, 4, 24, {A_Boss2TakeDamage}, 24+TICRATE, 0, S_EGGMOBILE2_POGO4}, // S_EGGMOBILE2_PAIN2 - {SPR_EGGN, 5, 2, {A_Fall}, 0, 0, S_EGGMOBILE2_DIE2}, // S_EGGMOBILE2_DIE1 - {SPR_EGGN, 5, 2, {A_BossScream}, 0, 0, S_EGGMOBILE2_DIE3}, // S_EGGMOBILE2_DIE2 - {SPR_EGGN, 5, 0, {A_Repeat}, 17, S_EGGMOBILE2_DIE2, S_EGGMOBILE2_DIE4}, // S_EGGMOBILE2_DIE3 - {SPR_EGGN, 5, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_EGGMOBILE2_DIE4 - {SPR_EGGN, 6, 2, {A_BossScream}, 0, 0, S_EGGMOBILE2_FLEE2}, // S_EGGMOBILE2_FLEE1 - {SPR_EGGN, 7, 2, {A_BossScream}, 0, 0, S_EGGMOBILE2_FLEE1}, // S_EGGMOBILE2_FLEE2 - - {SPR_TANK, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSTANK1 - {SPR_TANK, 1, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSTANK2 - {SPR_TANK, 2, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSSPIGOT + {SPR_EGGN, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EGGMOBILE2_STND + {SPR_EGGN, 1, 4, {NULL}, 0, 0, S_EGGMOBILE2_POGO2, 0}, // S_EGGMOBILE2_POGO1 + {SPR_EGGN, 0, 2, {A_Boss2PogoTarget}, 9*FRACUNIT, 8*FRACUNIT, S_EGGMOBILE2_POGO3, 0}, // S_EGGMOBILE2_POGO2 + {SPR_EGGN, 1, 2, {NULL}, 0, 0, S_EGGMOBILE2_POGO4, 0}, // S_EGGMOBILE2_POGO3 + {SPR_EGGN, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EGGMOBILE2_POGO4 + {SPR_EGGN, 1, 4, {NULL}, 0, 0, S_EGGMOBILE2_POGO6, 0}, // S_EGGMOBILE2_POGO5 + {SPR_EGGN, 0, 2, {A_Boss2PogoTarget}, 7*FRACUNIT, 8*FRACUNIT, S_EGGMOBILE2_POGO7, 0}, // S_EGGMOBILE2_POGO6 + {SPR_EGGN, 1, 2, {NULL}, 0, 0, S_EGGMOBILE2_POGO4, 0}, // S_EGGMOBILE2_POGO7 + {SPR_EGGN, 3, 24, {A_Boss2TakeDamage}, 24+TICRATE, 0, S_EGGMOBILE2_STND, 0}, // S_EGGMOBILE2_PAIN + {SPR_EGGN, 4, 24, {A_Boss2TakeDamage}, 24+TICRATE, 0, S_EGGMOBILE2_POGO4, 0}, // S_EGGMOBILE2_PAIN2 + {SPR_EGGN, 5, 2, {A_Fall}, 0, 0, S_EGGMOBILE2_DIE2, 0}, // S_EGGMOBILE2_DIE1 + {SPR_EGGN, 5, 2, {A_BossScream}, 0, 0, S_EGGMOBILE2_DIE3, 0}, // S_EGGMOBILE2_DIE2 + {SPR_EGGN, 5, 0, {A_Repeat}, 17, S_EGGMOBILE2_DIE2, S_EGGMOBILE2_DIE4, 0}, // S_EGGMOBILE2_DIE3 + {SPR_EGGN, 5, -1, {A_BossDeath}, 0, 0, S_NULL, 0}, // S_EGGMOBILE2_DIE4 + {SPR_EGGN, 6, 2, {A_BossScream}, 0, 0, S_EGGMOBILE2_FLEE2, 0}, // S_EGGMOBILE2_FLEE1 + {SPR_EGGN, 7, 2, {A_BossScream}, 0, 0, S_EGGMOBILE2_FLEE1, 0}, // S_EGGMOBILE2_FLEE2 + + {SPR_TANK, 0, 35, {NULL}, 0, 0, S_NULL, 0}, // S_BOSSTANK1 + {SPR_TANK, 1, 35, {NULL}, 0, 0, S_NULL, 0}, // S_BOSSTANK2 + {SPR_TANK, 2, 35, {NULL}, 0, 0, S_NULL, 0}, // S_BOSSSPIGOT // Boss 2 Goop - {SPR_GOOP, 0, 2, {A_SpawnObjectRelative}, 0, MT_GOOPTRAIL, S_GOOP2}, // S_GOOP1 - {SPR_GOOP, 1, 2, {A_SpawnObjectRelative}, 0, MT_GOOPTRAIL, S_GOOP1}, // S_GOOP2 - {SPR_GOOP, 2, -1, {NULL}, 0, 0, S_NULL}, // S_GOOP3 - {SPR_GOOP, FF_ANIMATE|3, 11, {NULL}, 2, 6, S_NULL}, // S_GOOPTRAIL + {SPR_GOOP, 0, 2, {A_SpawnObjectRelative}, 0, MT_GOOPTRAIL, S_GOOP2, 0}, // S_GOOP1 + {SPR_GOOP, 1, 2, {A_SpawnObjectRelative}, 0, MT_GOOPTRAIL, S_GOOP1, 0}, // S_GOOP2 + {SPR_GOOP, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_GOOP3 + {SPR_GOOP, FF_ANIMATE|3, 11, {NULL}, 2, 6, S_NULL, 0}, // S_GOOPTRAIL // Boss 3 - {SPR_EGGO, 0, 1, {NULL}, 0, 0, S_EGGMOBILE3_STND}, // S_EGGMOBILE3_STND - {SPR_EGGO, FF_ANIMATE, 24, {NULL}, 1, 2, S_EGGMOBILE3_ATK2}, // S_EGGMOBILE3_SHOCK - {SPR_EGGO, 6|FF_ANIMATE, 24, {NULL}, 1, 2, S_EGGMOBILE3_ATK2}, // S_EGGMOBILE3_ATK1 - {SPR_EGGO, 2, 2, {NULL}, 0, 0, S_EGGMOBILE3_ATK3A}, // S_EGGMOBILE3_ATK2 - {SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 2, S_EGGMOBILE3_ATK3B}, // S_EGGMOBILE3_ATK3A - {SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 4, S_EGGMOBILE3_ATK3C}, // S_EGGMOBILE3_ATK3B - {SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 3, S_EGGMOBILE3_ATK3D}, // S_EGGMOBILE3_ATK3C - {SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 5, S_EGGMOBILE3_ATK4}, // S_EGGMOBILE3_ATK3D - {SPR_EGGO, 4, 2, {NULL}, 0, 0, S_EGGMOBILE3_ATK5}, // S_EGGMOBILE3_ATK4 - {SPR_EGGO, 5, 2, {NULL}, 0, 0, S_EGGMOBILE3_ROFL}, // S_EGGMOBILE3_ATK5 - {SPR_EGGO, 6|FF_ANIMATE, 60, {NULL}, 1, 2, S_EGGMOBILE3_STND}, // S_EGGMOBILE3_ROFL - {SPR_EGGO, 8, 1, {A_Boss3TakeDamage}, 0, 0, S_EGGMOBILE3_PAIN2}, // S_EGGMOBILE3_PAIN - {SPR_EGGO, 8, 23, {A_Pain}, 0, 0, S_EGGMOBILE3_STND}, // S_EGGMOBILE3_PAIN2 - {SPR_EGGO, 9, 2, {A_Fall}, 0, 0, S_EGGMOBILE3_DIE2}, // S_EGGMOBILE3_DIE1 - {SPR_EGGO, 9, 2, {A_BossScream}, 0, 0, S_EGGMOBILE3_DIE3}, // S_EGGMOBILE3_DIE2 - {SPR_EGGO, 9, 0, {A_Repeat}, 17, S_EGGMOBILE3_DIE2, S_EGGMOBILE3_DIE4}, // S_EGGMOBILE3_DIE3 - {SPR_EGGO, 9, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_EGGMOBILE3_DIE4 - {SPR_EGGO, 10, 2, {A_BossScream}, 0, 0, S_EGGMOBILE3_FLEE2}, // S_EGGMOBILE3_FLEE1 - {SPR_EGGO, 11, 2, {A_BossScream}, 0, 0, S_EGGMOBILE3_FLEE1}, // S_EGGMOBILE3_FLEE2 + {SPR_EGGO, 0, 1, {NULL}, 0, 0, S_EGGMOBILE3_STND, 0}, // S_EGGMOBILE3_STND + {SPR_EGGO, FF_ANIMATE, 24, {NULL}, 1, 2, S_EGGMOBILE3_ATK2, 0}, // S_EGGMOBILE3_SHOCK + {SPR_EGGO, 6|FF_ANIMATE, 24, {NULL}, 1, 2, S_EGGMOBILE3_ATK2, 0}, // S_EGGMOBILE3_ATK1 + {SPR_EGGO, 2, 2, {NULL}, 0, 0, S_EGGMOBILE3_ATK3A, 0}, // S_EGGMOBILE3_ATK2 + {SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 2, S_EGGMOBILE3_ATK3B, 0}, // S_EGGMOBILE3_ATK3A + {SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 4, S_EGGMOBILE3_ATK3C, 0}, // S_EGGMOBILE3_ATK3B + {SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 3, S_EGGMOBILE3_ATK3D, 0}, // S_EGGMOBILE3_ATK3C + {SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 5, S_EGGMOBILE3_ATK4, 0}, // S_EGGMOBILE3_ATK3D + {SPR_EGGO, 4, 2, {NULL}, 0, 0, S_EGGMOBILE3_ATK5, 0}, // S_EGGMOBILE3_ATK4 + {SPR_EGGO, 5, 2, {NULL}, 0, 0, S_EGGMOBILE3_ROFL, 0}, // S_EGGMOBILE3_ATK5 + {SPR_EGGO, 6|FF_ANIMATE, 60, {NULL}, 1, 2, S_EGGMOBILE3_STND, 0}, // S_EGGMOBILE3_ROFL + {SPR_EGGO, 8, 1, {A_Boss3TakeDamage}, 0, 0, S_EGGMOBILE3_PAIN2, 0}, // S_EGGMOBILE3_PAIN + {SPR_EGGO, 8, 23, {A_Pain}, 0, 0, S_EGGMOBILE3_STND, 0}, // S_EGGMOBILE3_PAIN2 + {SPR_EGGO, 9, 2, {A_Fall}, 0, 0, S_EGGMOBILE3_DIE2, 0}, // S_EGGMOBILE3_DIE1 + {SPR_EGGO, 9, 2, {A_BossScream}, 0, 0, S_EGGMOBILE3_DIE3, 0}, // S_EGGMOBILE3_DIE2 + {SPR_EGGO, 9, 0, {A_Repeat}, 17, S_EGGMOBILE3_DIE2, S_EGGMOBILE3_DIE4, 0}, // S_EGGMOBILE3_DIE3 + {SPR_EGGO, 9, -1, {A_BossDeath}, 0, 0, S_NULL, 0}, // S_EGGMOBILE3_DIE4 + {SPR_EGGO, 10, 2, {A_BossScream}, 0, 0, S_EGGMOBILE3_FLEE2, 0}, // S_EGGMOBILE3_FLEE1 + {SPR_EGGO, 11, 2, {A_BossScream}, 0, 0, S_EGGMOBILE3_FLEE1, 0}, // S_EGGMOBILE3_FLEE2 // Boss 3 Pinch - {SPR_FAKE, 0, 1, {NULL}, 0, 0, S_FAKEMOBILE}, // S_FAKEMOBILE_INIT - {SPR_FAKE, 0, 1, {A_Boss3Path}, 0, 0, S_FAKEMOBILE}, // S_FAKEMOBILE - {SPR_FAKE, 0, 22, {NULL}, 0, 0, S_FAKEMOBILE_ATK2}, // S_FAKEMOBILE_ATK1 - {SPR_FAKE, 0, 2, {NULL}, 0, 0, S_FAKEMOBILE_ATK3A}, // S_FAKEMOBILE_ATK2 - {SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 2, S_FAKEMOBILE_ATK3B}, // S_FAKEMOBILE_ATK3A - {SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 4, S_FAKEMOBILE_ATK3C}, // S_FAKEMOBILE_ATK3B - {SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 3, S_FAKEMOBILE_ATK3D}, // S_FAKEMOBILE_ATK3C - {SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 5, S_FAKEMOBILE}, // S_FAKEMOBILE_ATK3D - {SPR_FAKE, 1, 1, {NULL}, 0, 0, S_FAKEMOBILE_DIE2}, // S_FAKEMOBILE_DIE1 - {SPR_NULL, 0, 1, {NULL}, 0, 0, S_FAKEMOBILE_DIE1}, // S_FAKEMOBILE_DIE2 - - {SPR_SEBH, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSSEBH1 - {SPR_SEBH, 1, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSSEBH2 + {SPR_FAKE, 0, 1, {NULL}, 0, 0, S_FAKEMOBILE, 0}, // S_FAKEMOBILE_INIT + {SPR_FAKE, 0, 1, {A_Boss3Path}, 0, 0, S_FAKEMOBILE, 0}, // S_FAKEMOBILE + {SPR_FAKE, 0, 22, {NULL}, 0, 0, S_FAKEMOBILE_ATK2, 0}, // S_FAKEMOBILE_ATK1 + {SPR_FAKE, 0, 2, {NULL}, 0, 0, S_FAKEMOBILE_ATK3A, 0}, // S_FAKEMOBILE_ATK2 + {SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 2, S_FAKEMOBILE_ATK3B, 0}, // S_FAKEMOBILE_ATK3A + {SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 4, S_FAKEMOBILE_ATK3C, 0}, // S_FAKEMOBILE_ATK3B + {SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 3, S_FAKEMOBILE_ATK3D, 0}, // S_FAKEMOBILE_ATK3C + {SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 5, S_FAKEMOBILE, 0}, // S_FAKEMOBILE_ATK3D + {SPR_FAKE, 1, 1, {NULL}, 0, 0, S_FAKEMOBILE_DIE2, 0}, // S_FAKEMOBILE_DIE1 + {SPR_NULL, 0, 1, {NULL}, 0, 0, S_FAKEMOBILE_DIE1, 0}, // S_FAKEMOBILE_DIE2 + + {SPR_SEBH, 0, 35, {NULL}, 0, 0, S_NULL, 0}, // S_BOSSSEBH1 + {SPR_SEBH, 1, 35, {NULL}, 0, 0, S_NULL, 0}, // S_BOSSSEBH2 // Boss 3 Shockwave - {SPR_SHCK, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_ANIMATE, 8, {A_Boss3ShockThink}, 4, 2, S_SHOCKWAVE2}, // S_SHOCKWAVE1 - {SPR_SHCK, 3|FF_FULLBRIGHT|FF_PAPERSPRITE|FF_ANIMATE, 8, {A_Boss3ShockThink}, 4, 2, S_SHOCKWAVE1}, // S_SHOCKWAVE2 + {SPR_SHCK, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_ANIMATE, 8, {A_Boss3ShockThink}, 4, 2, S_SHOCKWAVE2, 0}, // S_SHOCKWAVE1 + {SPR_SHCK, 3|FF_FULLBRIGHT|FF_PAPERSPRITE|FF_ANIMATE, 8, {A_Boss3ShockThink}, 4, 2, S_SHOCKWAVE1, 0}, // S_SHOCKWAVE2 // Boss 4 - {SPR_EGGP, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGMOBILE4_STND - {SPR_EGGP, 1, 3, {NULL}, 0, 0, S_EGGMOBILE4_LATK2}, // S_EGGMOBILE4_LATK1 - {SPR_EGGP, 2, 15, {NULL}, 0, 0, S_EGGMOBILE4_LATK3}, // S_EGGMOBILE4_LATK2 - {SPR_EGGP, 3, 2, {NULL}, 0, 0, S_EGGMOBILE4_LATK4}, // S_EGGMOBILE4_LATK3 - {SPR_EGGP, 4, 2, {NULL}, 0, 0, S_EGGMOBILE4_LATK5}, // S_EGGMOBILE4_LATK4 - {SPR_EGGP, 5, 50, {A_Boss4Reverse}, sfx_mswing, 0, S_EGGMOBILE4_LATK6}, // S_EGGMOBILE4_LATK5 - {SPR_EGGP, 6, 2, {NULL}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_LATK6 - {SPR_EGGP, 7, 3, {NULL}, 0, 0, S_EGGMOBILE4_RATK2}, // S_EGGMOBILE4_RATK1 - {SPR_EGGP, 8, 15, {NULL}, 0, 0, S_EGGMOBILE4_RATK3}, // S_EGGMOBILE4_RATK2 - {SPR_EGGP, 9, 2, {NULL}, 0, 0, S_EGGMOBILE4_RATK4}, // S_EGGMOBILE4_RATK3 - {SPR_EGGP,10, 2, {NULL}, 0, 0, S_EGGMOBILE4_RATK5}, // S_EGGMOBILE4_RATK4 - {SPR_EGGP,11,150, {A_Boss4SpeedUp}, sfx_mswing, 0, S_EGGMOBILE4_RATK6}, // S_EGGMOBILE4_RATK5 - {SPR_EGGP,12, 2, {NULL}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_RATK6 - {SPR_EGGP,13, 20, {A_Boss4Raise}, sfx_doord1, 0, S_EGGMOBILE4_RAISE2}, // S_EGGMOBILE4_RAISE1 - {SPR_EGGP,15|FF_ANIMATE, -1, {NULL}, 1, 10, S_NULL}, // S_EGGMOBILE4_RAISE2 - {SPR_EGGP,13, 0, {A_Boss4Reverse}, sfx_alarm, sfx_s3k60, S_EGGMOBILE4_PAIN2}, // S_EGGMOBILE4_PAIN1 - {SPR_EGGP,13, 24, {A_Pain}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_PAIN2 - {SPR_EGGP,14, 2, {A_Fall}, 0, 0, S_EGGMOBILE4_DIE2}, // S_EGGMOBILE4_DIE1 - {SPR_EGGP,14, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_DIE3}, // S_EGGMOBILE4_DIE2 - {SPR_EGGP,14, 0, {A_Repeat}, 17, S_EGGMOBILE4_DIE2, S_EGGMOBILE4_DIE4}, // S_EGGMOBILE4_DIE3 - {SPR_EGGP,14, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_EGGMOBILE4_DIE4 - {SPR_EGGP,15, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_FLEE2}, // S_EGGMOBILE4_FLEE1 - {SPR_EGGP,16, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_FLEE1}, // S_EGGMOBILE4_FLEE2 - {SPR_BMCE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGMOBILE4_MACE - {SPR_BMCE, 0, 2, {A_BossScream}, 1, 0, S_EGGMOBILE4_MACE_DIE2}, // S_EGGMOBILE4_MACE_DIE1 - {SPR_NULL, 0, 2, {A_BossScream}, 1, 0, S_EGGMOBILE4_MACE_DIE3}, // S_EGGMOBILE4_MACE_DIE2 - {SPR_NULL, 0, 0, {A_Repeat}, 7, S_EGGMOBILE4_MACE_DIE1, S_SONIC3KBOSSEXPLOSION1}, // S_EGGMOBILE4_MACE_DIE3 + {SPR_EGGP, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EGGMOBILE4_STND + {SPR_EGGP, 1, 3, {NULL}, 0, 0, S_EGGMOBILE4_LATK2, 0}, // S_EGGMOBILE4_LATK1 + {SPR_EGGP, 2, 15, {NULL}, 0, 0, S_EGGMOBILE4_LATK3, 0}, // S_EGGMOBILE4_LATK2 + {SPR_EGGP, 3, 2, {NULL}, 0, 0, S_EGGMOBILE4_LATK4, 0}, // S_EGGMOBILE4_LATK3 + {SPR_EGGP, 4, 2, {NULL}, 0, 0, S_EGGMOBILE4_LATK5, 0}, // S_EGGMOBILE4_LATK4 + {SPR_EGGP, 5, 50, {A_Boss4Reverse}, sfx_mswing, 0, S_EGGMOBILE4_LATK6, 0}, // S_EGGMOBILE4_LATK5 + {SPR_EGGP, 6, 2, {NULL}, 0, 0, S_EGGMOBILE4_STND, 0}, // S_EGGMOBILE4_LATK6 + {SPR_EGGP, 7, 3, {NULL}, 0, 0, S_EGGMOBILE4_RATK2, 0}, // S_EGGMOBILE4_RATK1 + {SPR_EGGP, 8, 15, {NULL}, 0, 0, S_EGGMOBILE4_RATK3, 0}, // S_EGGMOBILE4_RATK2 + {SPR_EGGP, 9, 2, {NULL}, 0, 0, S_EGGMOBILE4_RATK4, 0}, // S_EGGMOBILE4_RATK3 + {SPR_EGGP,10, 2, {NULL}, 0, 0, S_EGGMOBILE4_RATK5, 0}, // S_EGGMOBILE4_RATK4 + {SPR_EGGP,11,150, {A_Boss4SpeedUp}, sfx_mswing, 0, S_EGGMOBILE4_RATK6, 0}, // S_EGGMOBILE4_RATK5 + {SPR_EGGP,12, 2, {NULL}, 0, 0, S_EGGMOBILE4_STND, 0}, // S_EGGMOBILE4_RATK6 + {SPR_EGGP,13, 20, {A_Boss4Raise}, sfx_doord1, 0, S_EGGMOBILE4_RAISE2, 0}, // S_EGGMOBILE4_RAISE1 + {SPR_EGGP,15|FF_ANIMATE, -1, {NULL}, 1, 10, S_NULL, 0}, // S_EGGMOBILE4_RAISE2 + {SPR_EGGP,13, 0, {A_Boss4Reverse}, sfx_alarm, sfx_s3k60, S_EGGMOBILE4_PAIN2, 0}, // S_EGGMOBILE4_PAIN1 + {SPR_EGGP,13, 24, {A_Pain}, 0, 0, S_EGGMOBILE4_STND, 0}, // S_EGGMOBILE4_PAIN2 + {SPR_EGGP,14, 2, {A_Fall}, 0, 0, S_EGGMOBILE4_DIE2, 0}, // S_EGGMOBILE4_DIE1 + {SPR_EGGP,14, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_DIE3, 0}, // S_EGGMOBILE4_DIE2 + {SPR_EGGP,14, 0, {A_Repeat}, 17, S_EGGMOBILE4_DIE2, S_EGGMOBILE4_DIE4, 0}, // S_EGGMOBILE4_DIE3 + {SPR_EGGP,14, -1, {A_BossDeath}, 0, 0, S_NULL, 0}, // S_EGGMOBILE4_DIE4 + {SPR_EGGP,15, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_FLEE2, 0}, // S_EGGMOBILE4_FLEE1 + {SPR_EGGP,16, 2, {A_BossScream}, 0, 0, S_EGGMOBILE4_FLEE1, 0}, // S_EGGMOBILE4_FLEE2 + {SPR_BMCE, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EGGMOBILE4_MACE + {SPR_BMCE, 0, 2, {A_BossScream}, 1, 0, S_EGGMOBILE4_MACE_DIE2, 0}, // S_EGGMOBILE4_MACE_DIE1 + {SPR_NULL, 0, 2, {A_BossScream}, 1, 0, S_EGGMOBILE4_MACE_DIE3, 0}, // S_EGGMOBILE4_MACE_DIE2 + {SPR_NULL, 0, 0, {A_Repeat}, 7, S_EGGMOBILE4_MACE_DIE1, S_SONIC3KBOSSEXPLOSION1, 0}, // S_EGGMOBILE4_MACE_DIE3 // Boss 4 jet flame - {SPR_EFIR, FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 1, 1, S_NULL}, // S_JETFLAME + {SPR_EFIR, FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 1, 1, S_NULL, 0}, // S_JETFLAME // Boss 4 Spectator Eggrobo - {SPR_EGR1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGROBO1_STND - {SPR_EGR1, 5, 2, {NULL}, 0, 0, S_EGGROBO1_BSLAP2}, // S_EGGROBO1_BSLAP1 - {SPR_EGR1, FF_ANIMATE|6, 35, {NULL}, 1, 2, S_EGGROBO1_STND}, // S_EGGROBO1_BSLAP2 - {SPR_EGR1, FF_ANIMATE|3, -1, {NULL}, 1, 2, S_NULL}, // S_EGGROBO1_PISSED + {SPR_EGR1, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EGGROBO1_STND + {SPR_EGR1, 5, 2, {NULL}, 0, 0, S_EGGROBO1_BSLAP2, 0}, // S_EGGROBO1_BSLAP1 + {SPR_EGR1, FF_ANIMATE|6, 35, {NULL}, 1, 2, S_EGGROBO1_STND, 0}, // S_EGGROBO1_BSLAP2 + {SPR_EGR1, FF_ANIMATE|3, -1, {NULL}, 1, 2, S_NULL, 0}, // S_EGGROBO1_PISSED // Boss 4 Spectator Eggrobo jet flame - {SPR_EFIR, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_NULL}, // S_EGGROBOJET + {SPR_EFIR, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EGGROBOJET // Boss 5 - {SPR_NULL, 0, 2, {A_CheckFlags2}, MF2_AMBUSH, S_FANG_IDLE0, S_FANG_INTRO0}, // S_FANG_SETUP - - {SPR_NULL, 0, 2, {NULL}, 0, 0, S_FANG_INTRO1}, // S_FANG_INTRO0 - {SPR_NULL, 0, 2, {A_Boss5MakeJunk}, -S_FANG_CLONE1, 0, S_FANG_INTRO2}, // S_FANG_INTRO1 - {SPR_NULL, 0, 0, {A_Repeat}, 25, S_FANG_INTRO1, S_FANG_INTRO3}, // S_FANG_INTRO2 - {SPR_NULL, 0, 0, {A_Boss5MakeJunk}, 0, 1, S_FANG_INTRO4}, // S_FANG_INTRO3 - {SPR_FANG, 30, 1, {A_ZThrust}, 9, (1<<16)|1, S_FANG_INTRO5}, // S_FANG_INTRO4 - {SPR_FANG, 27, 1, {A_Boss5CheckOnGround}, S_FANG_INTRO9, 0, S_FANG_INTRO6}, // S_FANG_INTRO5 - {SPR_FANG, 28, 1, {A_Boss5CheckOnGround}, S_FANG_INTRO9, 0, S_FANG_INTRO7}, // S_FANG_INTRO6 - {SPR_FANG, 29, 1, {A_Boss5CheckOnGround}, S_FANG_INTRO9, 0, S_FANG_INTRO8}, // S_FANG_INTRO7 - {SPR_FANG, 30, 1, {A_Boss5CheckOnGround}, S_FANG_INTRO9, 0, S_FANG_INTRO5}, // S_FANG_INTRO8 - {SPR_FANG, 23|FF_ANIMATE, 50, {NULL}, 1, 4, S_FANG_INTRO10}, // S_FANG_INTRO9 - {SPR_FANG, 25, 5, {NULL}, 0, 0, S_FANG_INTRO11}, // S_FANG_INTRO10 - {SPR_FANG, 26, 2, {A_Boss5MakeJunk}, S_BROKENROBOTD, 2, S_FANG_INTRO12}, // S_FANG_INTRO11 - {SPR_FANG, 31|FF_ANIMATE, 50, {NULL}, 3, 4, S_FANG_IDLE1}, // S_FANG_INTRO12 - - {SPR_FANG, 11, 2, {A_Boss5MakeJunk}, 0, -1, S_FANG_CLONE2}, // S_FANG_CLONE1 - {SPR_FANG, 11, 0, {A_Repeat}, 49, S_FANG_CLONE1, S_FANG_CLONE3}, // S_FANG_INTRO2 - {SPR_FANG, 12, 0, {A_SetObjectFlags}, MF_NOGRAVITY, 1, S_FANG_CLONE4}, // S_FANG_CLONE3 - {SPR_FANG, 12, 1, {A_Boss5CheckOnGround}, S_FANG_IDLE0, 0, S_FANG_CLONE4}, // S_FANG_CLONE4 - - {SPR_FANG, 0, 0, {A_SetObjectFlags}, MF_NOCLIPTHING, 1, S_FANG_IDLE1}, // S_FANG_IDLE0 - {SPR_FANG, 2, 16, {A_Look}, 1, 0, S_FANG_IDLE2}, // S_FANG_IDLE1 - {SPR_FANG, 3, 16, {A_Look}, 1, 0, S_FANG_IDLE3}, // S_FANG_IDLE2 - {SPR_FANG, 3, 16, {A_Look}, 1, 0, S_FANG_IDLE4}, // S_FANG_IDLE3 - {SPR_FANG, 3, 16, {A_Look}, 1, 0, S_FANG_IDLE5}, // S_FANG_IDLE4 - {SPR_FANG, 2, 16, {A_Look}, 1, 0, S_FANG_IDLE6}, // S_FANG_IDLE5 - {SPR_FANG, 1, 16, {A_Look}, 1, 0, S_FANG_IDLE7}, // S_FANG_IDLE6 - {SPR_FANG, 1, 16, {A_Look}, 1, 0, S_FANG_IDLE8}, // S_FANG_IDLE7 - {SPR_FANG, 1, 16, {A_Look}, 1, 0, S_FANG_IDLE1}, // S_FANG_IDLE8 - - {SPR_FANG, 14, 0, {A_DoNPCPain}, FRACUNIT, 0, S_FANG_PAIN2}, // S_FANG_PAIN1 - {SPR_FANG, 14, 1, {A_Boss5CheckOnGround}, S_FANG_PATHINGSTART1, S_FANG_PINCHPATHINGSTART1, S_FANG_PAIN2}, // S_FANG_PAIN2 - - {SPR_FANG, 8, 0, {A_Boss5ExtraRepeat}, 5, 4, S_FANG_PATHINGSTART2}, // S_FANG_PATHINGSTART1 - {SPR_FANG, 8, 0, {A_PlayActiveSound}, 0, 0, S_FANG_PATHING}, // S_FANG_PATHINGSTART2 - {SPR_FANG, 8, 0, {A_Boss5FindWaypoint}, 0, 0, S_FANG_BOUNCE1}, // S_FANG_PATHING - - {SPR_FANG, 8, 2, {A_Thrust}, 0, 1, S_FANG_BOUNCE2}, // S_FANG_BOUNCE1 - {SPR_FANG, 9, 2, {NULL}, 0, 0, S_FANG_BOUNCE3}, // S_FANG_BOUNCE2 - {SPR_FANG, 10, 1, {A_Boss5Jump}, 0, 0, S_FANG_BOUNCE4}, // S_FANG_BOUNCE3 - {SPR_FANG, 10, 1, {A_Boss5CheckFalling}, S_FANG_CHECKPATH1, S_FANG_FALL1, S_FANG_BOUNCE4}, // S_FANG_BOUNCE4 - - {SPR_FANG, 12, 1, {A_Boss5CheckOnGround}, S_FANG_CHECKPATH1, 0, S_FANG_FALL2}, // S_FANG_FALL1 - {SPR_FANG, 13, 1, {A_Boss5CheckOnGround}, S_FANG_CHECKPATH1, 0, S_FANG_FALL1}, // S_FANG_FALL2 - - {SPR_FANG, 8, 0, {A_Boss5Calm}, 0, 0, S_FANG_CHECKPATH2}, // S_FANG_CHECKPATH1 - {SPR_FANG, 8, 0, {A_Repeat}, 0, S_FANG_PATHINGCONT1, S_FANG_SKID1}, // S_FANG_CHECKPATH2 - - {SPR_FANG, 9, 0, {A_Boss5PinchShot}, MT_FBOMB, -16, S_FANG_PATHINGCONT2}, // S_FANG_PATHINGCONT1 - {SPR_FANG, 9, 0, {A_PlayActiveSound}, 0, 0, S_FANG_PATHINGCONT3}, // S_FANG_PATHINGCONT2 - {SPR_FANG, 9, 2, {A_Thrust}, 0, 1, S_FANG_PATHING}, // S_FANG_PATHINGCONT3 - - {SPR_FANG, 4, 0, {A_PlayAttackSound}, 0, 0, S_FANG_SKID2}, // S_FANG_SKID1 - {SPR_FANG, 4, 1, {A_DoNPCSkid}, S_FANG_SKID3, 0, S_FANG_SKID2}, // S_FANG_SKID2 - {SPR_FANG, 4, 10, {NULL}, 0, 0, S_FANG_CHOOSEATTACK}, // S_FANG_SKID3 - - {SPR_FANG, 0, 0, {A_RandomState}, S_FANG_LOBSHOT0, S_FANG_FIRESTART1, S_NULL}, // S_FANG_CHOOSEATTACK - - {SPR_FANG, 5, 0, {A_PrepareRepeat}, 3, 0, S_FANG_FIRESTART2}, // S_FANG_FIRESTART1 // Reset loop - {SPR_FANG, 5, 18, {A_LookForBetter}, 1, 0, S_FANG_FIRE1}, // S_FANG_FIRESTART2 - {SPR_FANG, 5, 5, {A_FireShot}, MT_CORK, -16, S_FANG_FIRE2}, // S_FANG_FIRE1 // Start of loop - {SPR_FANG, 6, 5, {NULL}, 0, 0, S_FANG_FIRE3}, // S_FANG_FIRE2 - {SPR_FANG, 7, 5, {NULL}, 0, 0, S_FANG_FIRE4}, // S_FANG_FIRE3 - {SPR_FANG, 5, 5, {NULL}, 2, 0, S_FANG_FIREREPEAT}, // S_FANG_FIRE4 - {SPR_FANG, 5, 0, {A_Repeat}, 3, S_FANG_FIRE1, S_FANG_WAIT1}, // S_FANG_FIREREPEAT // End of loop - - {SPR_FANG, 18, 16, {A_LookForBetter}, 1, 0, S_FANG_LOBSHOT1}, // S_FANG_LOBSHOT0 - {SPR_FANG, 19, 2, {A_LookForBetter}, 1, 0, S_FANG_LOBSHOT2}, // S_FANG_LOBSHOT1 - {SPR_FANG, 20, 18, {A_BrakLobShot}, MT_FBOMB, 32+(1<<16), S_FANG_WAIT1}, // S_FANG_LOBSHOT2 - - {SPR_FANG, FF_ANIMATE|15, 70, {NULL}, 1, 5, S_FANG_WAIT2}, // S_FANG_WAIT1 - {SPR_FANG, 0, 35, {A_Look}, 1, 0, S_FANG_IDLE1}, // S_FANG_WAIT2 - - {SPR_FANG, 12, 1, {A_Boss5CheckOnGround}, S_FANG_PATHINGSTART2, S_FANG_PINCHPATHINGSTART1, S_FANG_WALLHIT}, // S_FANG_WALLHIT - - {SPR_FANG, 8, 0, {A_PrepareRepeat}, 1, 0, S_FANG_PINCHPATHINGSTART2}, // S_FANG_PINCHPATHINGSTART1 - {SPR_FANG, 8, 0, {A_PlayActiveSound}, 0, 0, S_FANG_PINCHPATHING}, // S_FANG_PINCHPATHINGSTART2 - {SPR_FANG, 8, 0, {A_Boss5FindWaypoint}, 1, 0, S_FANG_PINCHBOUNCE0}, // S_FANG_PINCHPATHING - {SPR_FANG, 8, 0, {A_SetObjectFlags}, MF_NOCLIP|MF_NOCLIPHEIGHT, 2, S_FANG_PINCHBOUNCE1}, // S_FANG_PINCHBOUNCE0 - {SPR_FANG, 8, 2, {A_Thrust}, 0, 1, S_FANG_PINCHBOUNCE2}, // S_FANG_PINCHBOUNCE1 - {SPR_FANG, 9, 2, {NULL}, 0, 0, S_FANG_PINCHBOUNCE3}, // S_FANG_PINCHBOUNCE2 - {SPR_FANG, 10, 2, {A_Boss5Jump}, 0, 0, S_FANG_PINCHBOUNCE4}, // S_FANG_PINCHBOUNCE3 - {SPR_FANG, 10, 1, {A_Boss5CheckFalling}, S_FANG_PINCHSKID1, S_FANG_PINCHFALL0, S_FANG_PINCHBOUNCE4}, // S_FANG_PINCHBOUNCE4 - {SPR_FANG, 12, 0, {A_SetObjectFlags}, MF_NOCLIP|MF_NOCLIPHEIGHT, 1, S_FANG_PINCHFALL1}, // S_FANG_PINCHFALL0 - {SPR_FANG, 12, 1, {A_Boss5CheckOnGround}, S_FANG_PINCHSKID1, 0, S_FANG_PINCHFALL2}, // S_FANG_PINCHFALL1 - {SPR_FANG, 13, 1, {A_Boss5CheckOnGround}, S_FANG_PINCHSKID1, 0, S_FANG_PINCHFALL1}, // S_FANG_PINCHFALL2 - {SPR_FANG, 4, 0, {A_PlayAttackSound}, 0, 0, S_FANG_PINCHSKID2}, // S_FANG_PINCHSKID1 - {SPR_FANG, 4, 1, {A_DoNPCSkid}, S_FANG_PINCHLOBSHOT0, 0, S_FANG_PINCHSKID2}, // S_FANG_PINCHSKID2 - {SPR_FANG, 18, 16, {A_FaceTarget}, 3, 0, S_FANG_PINCHLOBSHOT1}, // S_FANG_PINCHLOBSHOT0 - {SPR_FANG, 19, 2, {A_FaceTarget}, 3, 0, S_FANG_PINCHLOBSHOT2}, // S_FANG_PINCHLOBSHOT1 - {SPR_FANG, 20, 30, {A_Boss5MakeItRain}, MT_FBOMB, -16, S_FANG_PINCHLOBSHOT3}, // S_FANG_PINCHLOBSHOT2 - {SPR_FANG, 20, 18, {A_LinedefExecuteFromArg}, 4, 0, S_FANG_PINCHLOBSHOT4}, // S_FANG_PINCHLOBSHOT3 - {SPR_FANG, 0, 0, {A_Boss5Calm}, 0, 0, S_FANG_PATHINGSTART1}, // S_FANG_PINCHLOBSHOT4 - - {SPR_FANG, 21, 0, {A_DoNPCPain}, 0, 0, S_FANG_DIE2}, // S_FANG_DIE1 - {SPR_FANG, 21, 1, {A_Boss5CheckOnGround}, S_FANG_DIE3, 0, S_FANG_DIE2}, // S_FANG_DIE2 - - {SPR_FANG, 22, 0, {A_Scream}, 0, 0, S_FANG_DIE4}, // S_FANG_DIE3 - {SPR_FANG, 22, -1, {A_SetFuse}, 70, 0, S_FANG_DIE5}, // S_FANG_DIE4 - - {SPR_FANG, 11, 0, {A_PlaySound}, sfx_jump, 0, S_FANG_DIE6}, // S_FANG_DIE5 - {SPR_FANG, 11, 1, {A_ZThrust}, 6, (1<<16)|1, S_FANG_DIE7}, // S_FANG_DIE6 - {SPR_FANG, 11, 1, {A_Boss5CheckFalling}, S_FANG_FLEEPATHING1, S_FANG_DIE8, S_FANG_DIE7}, // S_FANG_DIE7 - {SPR_FANG, 12, 1, {A_Boss5CheckOnGround}, S_FANG_FLEEPATHING1, 0, S_FANG_DIE8}, // S_FANG_DIE8 - - {SPR_FANG, 9, 0, {A_PlayActiveSound}, 0, 0, S_FANG_FLEEPATHING2}, // S_FANG_FLEEPATHING1 - {SPR_FANG, 8, 2, {A_Boss5FindWaypoint}, 2, 0, S_FANG_FLEEBOUNCE1}, // S_FANG_FLEEPATHING2 - {SPR_FANG, 9, 2, {NULL}, 0, 0, S_FANG_FLEEBOUNCE2}, // S_FANG_FLEEBOUNCE1 - {SPR_FANG, 10, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_FANG_FLEEBOUNCE2 - - {SPR_FANG, 17, 7*TICRATE, {NULL}, 0, 0, S_NULL}, // S_FANG_KO - - {SPR_NULL, 0, -1, {A_RandomStateRange}, S_BROKENROBOTA, S_BROKENROBOTF, S_NULL}, // S_BROKENROBOTRANDOM - {SPR_BRKN, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 3, 4, S_NULL}, // S_BROKENROBOTA - {SPR_BRKN, 4|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 3, 4, S_NULL}, // S_BROKENROBOTB - {SPR_BRKN, 8|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 3, 4, S_NULL}, // S_BROKENROBOTC - {SPR_BRKN, 12|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 3, 4, S_NULL}, // S_BROKENROBOTD - {SPR_BRKN, 16|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 3, 4, S_NULL}, // S_BROKENROBOTE - {SPR_BRKN, 20|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 3, 4, S_NULL}, // S_BROKENROBOTF - - {SPR_WHAT, FF_ANIMATE|FF_FULLBRIGHT, 4, {NULL}, 1, 2, S_ALART2}, // S_ALART1 - {SPR_WHAT, 2|FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 1, 2, S_NULL}, // S_ALART2 - - {SPR_VWRE, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_VWREF - {SPR_VWRE, 1|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_VWREB - - {SPR_PROJ, FF_TRANS20|FF_FULLBRIGHT, 4, {NULL}, 0, 0, S_PROJECTORLIGHT2}, // S_PROJECTORLIGHT1 - {SPR_PROJ, 1|FF_TRANS40|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_PROJECTORLIGHT3}, // S_PROJECTORLIGHT2 - {SPR_PROJ, 2|FF_TRANS20|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_PROJECTORLIGHT4}, // S_PROJECTORLIGHT3 - {SPR_PROJ, 3|FF_TRANS40|FF_FULLBRIGHT, 2, {A_Repeat}, 39, S_PROJECTORLIGHT2, S_PROJECTORLIGHT5}, // S_PROJECTORLIGHT4 - {SPR_PROJ, 4|FF_TRANS60|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_PROJECTORLIGHT5 - - {SPR_FBOM, 0, 1, {A_GhostMe}, 0, 0, S_FBOMB2}, // S_FBOMB1 - {SPR_FBOM, 1, 1, {A_GhostMe}, 0, 0, S_FBOMB1}, // S_FBOMB2 - {SPR_BARX, 0|FF_FULLBRIGHT, 3, {A_SetObjectFlags}, MF_NOCLIP|MF_NOGRAVITY|MF_NOBLOCKMAP, 0, S_FBOMB_EXPL2}, // S_FBOMB_EXPL1 - {SPR_BARX, 1|FF_FULLBRIGHT, 2, {A_Boss5BombExplode}, MT_TNTDUST, 0, S_FBOMB_EXPL3}, // S_FBOMB_EXPL2 - {SPR_BARX, 1|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_FBOMB_EXPL4}, // S_FBOMB_EXPL3 - {SPR_BARX, 2|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FBOMB_EXPL5}, // S_FBOMB_EXPL4 - {SPR_BARX, 3|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FBOMB_EXPL6}, // S_FBOMB_EXPL5 - {SPR_NULL, 0, 2*TICRATE, {NULL}, 0, 0, S_NULL}, // S_FBOMB_EXPL6 - {SPR_BARD, 0|FF_TRANS90, 2, {NULL}, 0, 0, S_TNTDUST_2}, // S_TNTDUST_1 - {SPR_BARD, 0|FF_TRANS30, 2*TICRATE, {A_SetRandomTics}, 2, TICRATE, S_TNTDUST_3}, // S_TNTDUST_2 - {SPR_BARD, 0|FF_TRANS40, 10, {NULL}, 0, 0, S_TNTDUST_4}, // S_TNTDUST_3 - {SPR_BARD, 0|FF_TRANS50, 10, {NULL}, 0, 0, S_TNTDUST_5}, // S_TNTDUST_4 - {SPR_BARD, 0|FF_TRANS60, 10, {NULL}, 0, 0, S_TNTDUST_6}, // S_TNTDUST_5 - {SPR_BARD, 0|FF_TRANS70, 10, {NULL}, 0, 0, S_TNTDUST_7}, // S_TNTDUST_6 - {SPR_BARD, 0|FF_TRANS80, 10, {NULL}, 0, 0, S_TNTDUST_8}, // S_TNTDUST_7 - {SPR_BARD, 0|FF_TRANS90, 10, {NULL}, 0, 0, S_NULL}, // S_TNTDUST_8 - {SPR_FSGN, 0|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_FSGNA - {SPR_FSGN, 1|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_FSGNB - {SPR_FSGN, 2|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_FSGNC - {SPR_FSGN, 3|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_FSGND + {SPR_NULL, 0, 2, {A_CheckFlags2}, MF2_AMBUSH, S_FANG_IDLE0, S_FANG_INTRO0, 0}, // S_FANG_SETUP + + {SPR_NULL, 0, 2, {NULL}, 0, 0, S_FANG_INTRO1, 0}, // S_FANG_INTRO0 + {SPR_NULL, 0, 2, {A_Boss5MakeJunk}, -S_FANG_CLONE1, 0, S_FANG_INTRO2, 0}, // S_FANG_INTRO1 + {SPR_NULL, 0, 0, {A_Repeat}, 25, S_FANG_INTRO1, S_FANG_INTRO3, 0}, // S_FANG_INTRO2 + {SPR_NULL, 0, 0, {A_Boss5MakeJunk}, 0, 1, S_FANG_INTRO4, 0}, // S_FANG_INTRO3 + {SPR_PLAY, SPR2_ROLL, 1, {A_ZThrust}, 9, (1<<16)|1, S_FANG_INTRO5, 0}, // S_FANG_INTRO4 + {SPR_PLAY, SPR2_ROLL, 1, {A_Boss5CheckOnGround}, S_FANG_INTRO9, 0, S_FANG_INTRO6, 0}, // S_FANG_INTRO5 + {SPR_PLAY, SPR2_ROLL, 1, {A_Boss5CheckOnGround}, S_FANG_INTRO9, 0, S_FANG_INTRO7, 0}, // S_FANG_INTRO6 + {SPR_PLAY, SPR2_ROLL, 1, {A_Boss5CheckOnGround}, S_FANG_INTRO9, 0, S_FANG_INTRO8, 0}, // S_FANG_INTRO7 + {SPR_PLAY, SPR2_ROLL, 1, {A_Boss5CheckOnGround}, S_FANG_INTRO9, 0, S_FANG_INTRO5, 0}, // S_FANG_INTRO8 + {SPR_PLAY, SPR2_MSC0|FF_ANIMATE, 50, {NULL}, 0, 4, S_FANG_INTRO10, 0}, // S_FANG_INTRO9 + {SPR_PLAY, SPR2_MSC1, 5, {NULL}, 0, 0, S_FANG_INTRO11, 0}, // S_FANG_INTRO10 + {SPR_PLAY, SPR2_MSC2, 2, {A_Boss5MakeJunk}, S_BROKENROBOTD, 2, S_FANG_INTRO12, 0}, // S_FANG_INTRO11 + {SPR_PLAY, SPR2_CNT1|FF_ANIMATE, 50, {NULL}, 0, 4, S_FANG_IDLE1, 0}, // S_FANG_INTRO12 + + {SPR_PLAY, SPR2_SPNG, 2, {A_Boss5MakeJunk}, 0, -1, S_FANG_CLONE2, 0}, // S_FANG_CLONE1 + {SPR_PLAY, SPR2_SPNG, 0, {A_Repeat}, 49, S_FANG_CLONE1, S_FANG_CLONE3, 0}, // S_FANG_CLONE2 + {SPR_PLAY, SPR2_FALL, 0, {A_SetObjectFlags}, MF_NOGRAVITY, 1, S_FANG_CLONE4, 0}, // S_FANG_CLONE3 + {SPR_PLAY, SPR2_FALL, 1, {A_Boss5CheckOnGround}, S_FANG_IDLE0, 0, S_FANG_CLONE4, 0}, // S_FANG_CLONE4 + + {SPR_PLAY, 0, 0, {A_SetObjectFlags}, MF_NOCLIPTHING, 1, S_FANG_IDLE1, 0}, // S_FANG_IDLE0 + {SPR_PLAY, SPR2_WAIT, 16, {A_Look}, 1, 0, S_FANG_IDLE2, 0}, // S_FANG_IDLE1 + {SPR_PLAY, SPR2_WAIT, 16, {A_Look}, 1, 0, S_FANG_IDLE3, 0}, // S_FANG_IDLE2 + {SPR_PLAY, SPR2_WAIT, 16, {A_Look}, 1, 0, S_FANG_IDLE4, 0}, // S_FANG_IDLE3 + {SPR_PLAY, SPR2_WAIT, 16, {A_Look}, 1, 0, S_FANG_IDLE5, 0}, // S_FANG_IDLE4 + {SPR_PLAY, SPR2_WAIT, 16, {A_Look}, 1, 0, S_FANG_IDLE6, 0}, // S_FANG_IDLE5 + {SPR_PLAY, SPR2_WAIT, 16, {A_Look}, 1, 0, S_FANG_IDLE7, 0}, // S_FANG_IDLE6 + {SPR_PLAY, SPR2_WAIT, 16, {A_Look}, 1, 0, S_FANG_IDLE8, 0}, // S_FANG_IDLE7 + {SPR_PLAY, SPR2_WAIT, 16, {A_Look}, 1, 0, S_FANG_IDLE1, 0}, // S_FANG_IDLE8 + + {SPR_PLAY, 0, 0, {A_DoNPCPain}, FRACUNIT, 0, S_FANG_PAIN2, 0}, // S_FANG_PAIN1 + {SPR_PLAY, SPR2_PAIN, 1, {A_Boss5CheckOnGround}, S_FANG_PATHINGSTART1, S_FANG_PINCHPATHINGSTART1, S_FANG_PAIN2, 0}, // S_FANG_PAIN2 + + {SPR_PLAY, 0, 0, {A_Boss5ExtraRepeat}, 5, 4, S_FANG_PATHINGSTART2, 0}, // S_FANG_PATHINGSTART1 + {SPR_PLAY, 0, 0, {A_PlayActiveSound}, 0, 0, S_FANG_PATHING, 0}, // S_FANG_PATHINGSTART2 + {SPR_PLAY, 0, 0, {A_Boss5FindWaypoint}, 0, 0, S_FANG_BOUNCE1, 0}, // S_FANG_PATHING + + {SPR_PLAY, SPR2_LAND, 2, {A_Thrust}, 0, 1, S_FANG_BOUNCE2, 0}, // S_FANG_BOUNCE1 + {SPR_PLAY, SPR2_LAND, 2, {NULL}, 0, 0, S_FANG_BOUNCE3, 0}, // S_FANG_BOUNCE2 + {SPR_PLAY, SPR2_LAND, 1, {A_Boss5Jump}, 0, 0, S_FANG_BOUNCE4, 0}, // S_FANG_BOUNCE3 + {SPR_PLAY, SPR2_BNCE, 1, {A_Boss5CheckFalling}, S_FANG_CHECKPATH1, S_FANG_FALL1, S_FANG_BOUNCE4, 0}, // S_FANG_BOUNCE4 + + {SPR_PLAY, SPR2_FALL, 1, {A_Boss5CheckOnGround}, S_FANG_CHECKPATH1, 0, S_FANG_FALL2, 0}, // S_FANG_FALL1 + {SPR_PLAY, SPR2_FALL, 1, {A_Boss5CheckOnGround}, S_FANG_CHECKPATH1, 0, S_FANG_FALL1, 0}, // S_FANG_FALL2 + + {SPR_PLAY, 0, 0, {A_Boss5Calm}, 0, 0, S_FANG_CHECKPATH2, 0}, // S_FANG_CHECKPATH1 + {SPR_PLAY, 0, 0, {A_Repeat}, 0, S_FANG_PATHINGCONT1, S_FANG_SKID1, 0}, // S_FANG_CHECKPATH2 + + {SPR_PLAY, 0, 0, {A_Boss5PinchShot}, MT_FBOMB, -16, S_FANG_PATHINGCONT2, 0}, // S_FANG_PATHINGCONT1 + {SPR_PLAY, 0, 0, {A_PlayActiveSound}, 0, 0, S_FANG_PATHINGCONT3, 0}, // S_FANG_PATHINGCONT2 + {SPR_PLAY, SPR2_LAND, 2, {A_Thrust}, 0, 1, S_FANG_PATHING, 0}, // S_FANG_PATHINGCONT3 + + {SPR_PLAY, 0, 0, {A_PlayAttackSound}, 0, 0, S_FANG_SKID2, 0}, // S_FANG_SKID1 + {SPR_PLAY, SPR2_SKID, 1, {A_DoNPCSkid}, S_FANG_SKID3, 0, S_FANG_SKID2, 0}, // S_FANG_SKID2 + {SPR_PLAY, SPR2_SKID, 10, {NULL}, 0, 0, S_FANG_CHOOSEATTACK, 0}, // S_FANG_SKID3 + + {SPR_PLAY, 0, 0, {A_RandomState}, S_FANG_LOBSHOT0, S_FANG_FIRESTART1, S_NULL, 0}, // S_FANG_CHOOSEATTACK + + {SPR_PLAY, 0, 0, {A_PrepareRepeat}, 3, 0, S_FANG_FIRESTART2, 0}, // S_FANG_FIRESTART1 // Reset loop + {SPR_PLAY, SPR2_FIRE, 18, {A_LookForBetter}, 1, 0, S_FANG_FIRE1, 0}, // S_FANG_FIRESTART2 + {SPR_PLAY, SPR2_FIRE, 2, {A_FireShot}, MT_CORK, -16, S_FANG_FIRE2, 0}, // S_FANG_FIRE1 // Start of loop + {SPR_PLAY, SPR2_FIRE, 2, {NULL}, 0, 0, S_FANG_FIRE3, 0}, // S_FANG_FIRE2 + {SPR_PLAY, SPR2_FIRE, 16, {NULL}, 0, 0, S_FANG_FIREREPEAT, 0}, // S_FANG_FIRE3 + {SPR_PLAY, 0, 0, {A_Repeat}, 3, S_FANG_FIRE1, S_FANG_WAIT1, 0}, // S_FANG_FIREREPEAT // End of loop + + {SPR_PLAY, SPR2_MSC3, 14, {A_LookForBetter}, 1, 0, S_FANG_LOBSHOT1, 0}, // S_FANG_LOBSHOT0 + {SPR_PLAY, SPR2_MSC3, 2, {A_LookForBetter}, 1, 0, S_FANG_LOBSHOT2, 0}, // S_FANG_LOBSHOT1 + {SPR_PLAY, SPR2_MSC3, 2, {A_LookForBetter}, 1, 0, S_FANG_LOBSHOT3, 0}, // S_FANG_LOBSHOT2 + {SPR_PLAY, SPR2_MSC3, 18, {A_BrakLobShot}, MT_FBOMB, 32+(1<<16), S_FANG_WAIT1, 0}, // S_FANG_LOBSHOT3 + + {SPR_PLAY, SPR2_MLEL|FF_ANIMATE, 70, {NULL}, 0, 5, S_FANG_WAIT2, 0}, // S_FANG_WAIT1 + {SPR_PLAY, SPR2_STND, 35, {A_Look}, 1, 0, S_FANG_IDLE1, 0}, // S_FANG_WAIT2 + + {SPR_PLAY, SPR2_FALL, 1, {A_Boss5CheckOnGround}, S_FANG_PATHINGSTART2, S_FANG_PINCHPATHINGSTART1, S_FANG_WALLHIT, 0}, // S_FANG_WALLHIT + + {SPR_PLAY, 0, 0, {A_PrepareRepeat}, 1, 0, S_FANG_PINCHPATHINGSTART2, 0}, // S_FANG_PINCHPATHINGSTART1 + {SPR_PLAY, 0, 0, {A_PlayActiveSound}, 0, 0, S_FANG_PINCHPATHING, 0}, // S_FANG_PINCHPATHINGSTART2 + {SPR_PLAY, 0, 0, {A_Boss5FindWaypoint}, 1, 0, S_FANG_PINCHBOUNCE0, 0}, // S_FANG_PINCHPATHING + {SPR_PLAY, 0, 0, {A_SetObjectFlags}, MF_NOCLIP|MF_NOCLIPHEIGHT, 2, S_FANG_PINCHBOUNCE1, 0}, // S_FANG_PINCHBOUNCE0 + {SPR_PLAY, SPR2_LAND, 2, {A_Thrust}, 0, 1, S_FANG_PINCHBOUNCE2, 0}, // S_FANG_PINCHBOUNCE1 + {SPR_PLAY, SPR2_LAND, 2, {NULL}, 0, 0, S_FANG_PINCHBOUNCE3, 0}, // S_FANG_PINCHBOUNCE2 + {SPR_PLAY, SPR2_LAND, 2, {A_Boss5Jump}, 0, 0, S_FANG_PINCHBOUNCE4, 0}, // S_FANG_PINCHBOUNCE3 + {SPR_PLAY, SPR2_BNCE, 1, {A_Boss5CheckFalling}, S_FANG_PINCHSKID1, S_FANG_PINCHFALL0, S_FANG_PINCHBOUNCE4, 0}, // S_FANG_PINCHBOUNCE4 + {SPR_PLAY, 0, 0, {A_SetObjectFlags}, MF_NOCLIP|MF_NOCLIPHEIGHT, 1, S_FANG_PINCHFALL1, 0}, // S_FANG_PINCHFALL0 + {SPR_PLAY, SPR2_FALL, 1, {A_Boss5CheckOnGround}, S_FANG_PINCHSKID1, 0, S_FANG_PINCHFALL2, 0}, // S_FANG_PINCHFALL1 + {SPR_PLAY, SPR2_FALL, 1, {A_Boss5CheckOnGround}, S_FANG_PINCHSKID1, 0, S_FANG_PINCHFALL1, 0}, // S_FANG_PINCHFALL2 + {SPR_PLAY, 0, 0, {A_PlayAttackSound}, 0, 0, S_FANG_PINCHSKID2, 0}, // S_FANG_PINCHSKID1 + {SPR_PLAY, SPR2_SKID, 1, {A_DoNPCSkid}, S_FANG_PINCHLOBSHOT0, 0, S_FANG_PINCHSKID2, 0}, // S_FANG_PINCHSKID2 + {SPR_PLAY, SPR2_MSC3, 16, {A_FaceTarget}, 1, 5, S_FANG_PINCHLOBSHOT1, 0}, // S_FANG_PINCHLOBSHOT0 + {SPR_PLAY, SPR2_MSC3, 2, {A_FaceTarget}, 3, 0, S_FANG_PINCHLOBSHOT2, 0}, // S_FANG_PINCHLOBSHOT1 + {SPR_PLAY, SPR2_MSC3, 2, {A_FaceTarget}, 3, 0, S_FANG_PINCHLOBSHOT3, 0}, // S_FANG_PINCHLOBSHOT2 + {SPR_PLAY, SPR2_MSC3, 30, {A_Boss5MakeItRain}, MT_FBOMB, -16, S_FANG_PINCHLOBSHOT4, 0}, // S_FANG_PINCHLOBSHOT3 + {SPR_PLAY, SPR2_STND, 18, {A_LinedefExecuteFromArg}, 4, 0, S_FANG_PINCHLOBSHOT5, 0}, // S_FANG_PINCHLOBSHOT4 + {SPR_PLAY, 0, 0, {A_Boss5Calm}, 0, 0, S_FANG_PATHINGSTART1, 0}, // S_FANG_PINCHLOBSHOT5 + + {SPR_PLAY, 0, 0, {A_DoNPCPain}, 0, 0, S_FANG_DIE2, 0}, // S_FANG_DIE1 + {SPR_PLAY, SPR2_MSC4, 1, {A_Boss5CheckOnGround}, S_FANG_DIE3, 0, S_FANG_DIE2, 0}, // S_FANG_DIE2 + + {SPR_PLAY, 0, 0, {A_Scream}, 0, 0, S_FANG_DIE4, 0}, // S_FANG_DIE3 + {SPR_PLAY, SPR2_MSC5, -1, {A_SetFuse}, 70, 0, S_FANG_DIE5, 0}, // S_FANG_DIE4 + + {SPR_PLAY, 0, 0, {A_PlaySound}, sfx_jump, 0, S_FANG_DIE6, 0}, // S_FANG_DIE5 + {SPR_PLAY, SPR2_JUMP, 1, {A_ZThrust}, 6, (1<<16)|1, S_FANG_DIE7, 0}, // S_FANG_DIE6 + {SPR_PLAY, SPR2_JUMP, 1, {A_Boss5CheckFalling}, S_FANG_FLEEPATHING1, S_FANG_DIE8, S_FANG_DIE7, 0}, // S_FANG_DIE7 + {SPR_PLAY, SPR2_FALL, 1, {A_Boss5CheckOnGround}, S_FANG_FLEEPATHING1, 0, S_FANG_DIE8, 0}, // S_FANG_DIE8 + + {SPR_PLAY, 0, 0, {A_PlayActiveSound}, 0, 0, S_FANG_FLEEPATHING2, 0}, // S_FANG_FLEEPATHING1 + {SPR_PLAY, SPR2_LAND, 2, {A_Boss5FindWaypoint}, 2, 0, S_FANG_FLEEBOUNCE1, 0}, // S_FANG_FLEEPATHING2 + {SPR_PLAY, SPR2_LAND, 2, {NULL}, 0, 0, S_FANG_FLEEBOUNCE2, 0}, // S_FANG_FLEEBOUNCE1 + {SPR_PLAY, SPR2_LAND, -1, {A_BossDeath}, 0, 0, S_NULL, 0}, // S_FANG_FLEEBOUNCE2 + + {SPR_PLAY, SPR2_DEAD, 7*TICRATE, {NULL}, 0, 0, S_NULL, 0}, // S_FANG_KO + + {SPR_NULL, 0, -1, {A_RandomStateRange}, S_BROKENROBOTA, S_BROKENROBOTF, S_NULL, 0}, // S_BROKENROBOTRANDOM + {SPR_BRKN, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 3, 4, S_NULL, 0}, // S_BROKENROBOTA + {SPR_BRKN, 4|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 3, 4, S_NULL, 0}, // S_BROKENROBOTB + {SPR_BRKN, 8|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 3, 4, S_NULL, 0}, // S_BROKENROBOTC + {SPR_BRKN, 12|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 3, 4, S_NULL, 0}, // S_BROKENROBOTD + {SPR_BRKN, 16|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 3, 4, S_NULL, 0}, // S_BROKENROBOTE + {SPR_BRKN, 20|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 3, 4, S_NULL, 0}, // S_BROKENROBOTF + + {SPR_WHAT, FF_ANIMATE|FF_FULLBRIGHT, 4, {NULL}, 1, 2, S_ALART2, 0}, // S_ALART1 + {SPR_WHAT, 2|FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 1, 2, S_NULL, 0}, // S_ALART2 + + {SPR_VWRE, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL, 0}, // S_VWREF + {SPR_VWRE, 1|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL, 0}, // S_VWREB + + {SPR_PROJ, FF_TRANS20|FF_FULLBRIGHT, 4, {NULL}, 0, 0, S_PROJECTORLIGHT2, 0}, // S_PROJECTORLIGHT1 + {SPR_PROJ, 1|FF_TRANS40|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_PROJECTORLIGHT3, 0}, // S_PROJECTORLIGHT2 + {SPR_PROJ, 2|FF_TRANS20|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_PROJECTORLIGHT4, 0}, // S_PROJECTORLIGHT3 + {SPR_PROJ, 3|FF_TRANS40|FF_FULLBRIGHT, 2, {A_Repeat}, 39, S_PROJECTORLIGHT2, S_PROJECTORLIGHT5, 0}, // S_PROJECTORLIGHT4 + {SPR_PROJ, 4|FF_TRANS60|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL, 0}, // S_PROJECTORLIGHT5 + + {SPR_FBOM, 0, 1, {A_GhostMe}, 0, 0, S_FBOMB2, 0}, // S_FBOMB1 + {SPR_FBOM, 1, 1, {A_GhostMe}, 0, 0, S_FBOMB1, 0}, // S_FBOMB2 + {SPR_BARX, 0|FF_FULLBRIGHT, 3, {A_SetObjectFlags}, MF_NOCLIP|MF_NOGRAVITY|MF_NOBLOCKMAP, 0, S_FBOMB_EXPL2, 0}, // S_FBOMB_EXPL1 + {SPR_BARX, 1|FF_FULLBRIGHT, 2, {A_Boss5BombExplode}, MT_TNTDUST, 0, S_FBOMB_EXPL3, 0}, // S_FBOMB_EXPL2 + {SPR_BARX, 1|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_FBOMB_EXPL4, 0}, // S_FBOMB_EXPL3 + {SPR_BARX, 2|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FBOMB_EXPL5, 0}, // S_FBOMB_EXPL4 + {SPR_BARX, 3|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_FBOMB_EXPL6, 0}, // S_FBOMB_EXPL5 + {SPR_NULL, 0, 2*TICRATE, {NULL}, 0, 0, S_NULL, 0}, // S_FBOMB_EXPL6 + {SPR_BARD, 0|FF_TRANS90, 2, {NULL}, 0, 0, S_TNTDUST_2, 0}, // S_TNTDUST_1 + {SPR_BARD, 0|FF_TRANS30, 2*TICRATE, {A_SetRandomTics}, 2, TICRATE, S_TNTDUST_3, 0}, // S_TNTDUST_2 + {SPR_BARD, 0|FF_TRANS40, 10, {NULL}, 0, 0, S_TNTDUST_4, 0}, // S_TNTDUST_3 + {SPR_BARD, 0|FF_TRANS50, 10, {NULL}, 0, 0, S_TNTDUST_5, 0}, // S_TNTDUST_4 + {SPR_BARD, 0|FF_TRANS60, 10, {NULL}, 0, 0, S_TNTDUST_6, 0}, // S_TNTDUST_5 + {SPR_BARD, 0|FF_TRANS70, 10, {NULL}, 0, 0, S_TNTDUST_7, 0}, // S_TNTDUST_6 + {SPR_BARD, 0|FF_TRANS80, 10, {NULL}, 0, 0, S_TNTDUST_8, 0}, // S_TNTDUST_7 + {SPR_BARD, 0|FF_TRANS90, 10, {NULL}, 0, 0, S_NULL, 0}, // S_TNTDUST_8 + {SPR_FSGN, 0|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL, 0}, // S_FSGNA + {SPR_FSGN, 1|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL, 0}, // S_FSGNB + {SPR_FSGN, 2|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL, 0}, // S_FSGNC + {SPR_FSGN, 3|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL, 0}, // S_FSGND // Black Eggman (Boss 7) - {SPR_BRAK, 0, 1, {A_SetReactionTime}, 0, 0, S_BLACKEGG_STND2}, // S_BLACKEGG_STND - {SPR_BRAK, 0, 7, {A_Look}, 1, 0, S_BLACKEGG_STND2}, // S_BLACKEGG_STND2 - {SPR_BRAK, 1, 7, {NULL}, 0, 0, S_BLACKEGG_WALK2}, // S_BLACKEGG_WALK1 - {SPR_BRAK, 2, 7, {NULL}, 0, 0, S_BLACKEGG_WALK3}, // S_BLACKEGG_WALK2 - {SPR_BRAK, 3, 7, {A_PlaySound}, sfx_bestep, 0, S_BLACKEGG_WALK4}, // S_BLACKEGG_WALK3 - {SPR_BRAK, 4, 7, {NULL}, 0, 0, S_BLACKEGG_WALK5}, // S_BLACKEGG_WALK4 - {SPR_BRAK, 5, 7, {NULL}, 0, 0, S_BLACKEGG_WALK6}, // S_BLACKEGG_WALK5 - {SPR_BRAK, 6, 7, {A_PlaySound}, sfx_bestp2, 0, S_BLACKEGG_WALK1}, // S_BLACKEGG_WALK6 - {SPR_BRAK, 7, 3, {NULL}, 0, 0, S_BLACKEGG_SHOOT2}, // S_BLACKEGG_SHOOT1 - {SPR_BRAK, 24, 1, {A_PlaySound}, sfx_befire, 0, S_BLACKEGG_SHOOT1}, // S_BLACKEGG_SHOOT2 - - {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN2}, // S_BLACKEGG_PAIN1 - {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN3}, // S_BLACKEGG_PAIN2 - {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN4}, // S_BLACKEGG_PAIN3 - {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN5}, // S_BLACKEGG_PAIN4 - {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN6}, // S_BLACKEGG_PAIN5 - {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN7}, // S_BLACKEGG_PAIN6 - {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN8}, // S_BLACKEGG_PAIN7 - {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN9}, // S_BLACKEGG_PAIN8 - {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN10}, // S_BLACKEGG_PAIN9 - {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN11}, // S_BLACKEGG_PAIN10 - {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN12}, // S_BLACKEGG_PAIN11 - {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN13}, // S_BLACKEGG_PAIN12 - {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN14}, // S_BLACKEGG_PAIN13 - {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN15}, // S_BLACKEGG_PAIN14 - {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN16}, // S_BLACKEGG_PAIN15 - {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN17}, // S_BLACKEGG_PAIN16 - {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN18}, // S_BLACKEGG_PAIN17 - {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN19}, // S_BLACKEGG_PAIN18 - {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN20}, // S_BLACKEGG_PAIN19 - {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN21}, // S_BLACKEGG_PAIN20 - {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN22}, // S_BLACKEGG_PAIN21 - {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN23}, // S_BLACKEGG_PAIN22 - {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN24}, // S_BLACKEGG_PAIN23 - {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN25}, // S_BLACKEGG_PAIN24 - {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN26}, // S_BLACKEGG_PAIN25 - {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN27}, // S_BLACKEGG_PAIN26 - {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN28}, // S_BLACKEGG_PAIN27 - {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN29}, // S_BLACKEGG_PAIN28 - {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN30}, // S_BLACKEGG_PAIN29 - {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN31}, // S_BLACKEGG_PAIN30 - {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN32}, // S_BLACKEGG_PAIN31 - {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN33}, // S_BLACKEGG_PAIN32 - {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN34}, // S_BLACKEGG_PAIN33 - {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN35}, // S_BLACKEGG_PAIN34 - {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_WALK1}, // S_BLACKEGG_PAIN35 - - {SPR_BRAK, 9, 20, {NULL}, 0, 0, S_BLACKEGG_HITFACE2}, // S_BLACKEGG_HITFACE1 - {SPR_BRAK, 10, 2, {NULL}, 0, 0, S_BLACKEGG_HITFACE3}, // S_BLACKEGG_HITFACE2 - {SPR_BRAK, 11, 2, {NULL}, 0, 0, S_BLACKEGG_HITFACE4}, // S_BLACKEGG_HITFACE3 - {SPR_BRAK, 12,14, {NULL}, 0, 0, S_BLACKEGG_PAIN1}, // S_BLACKEGG_HITFACE4 - - {SPR_BRAK, 13, 14, {NULL}, 0, 0, S_BLACKEGG_DIE2}, // S_BLACKEGG_DIE1 - {SPR_BRAK, 14, 7, {NULL}, 0, 0, S_BLACKEGG_DIE3}, // S_BLACKEGG_DIE2 - {SPR_BRAK, 15, 5, {NULL}, 0, 0, S_BLACKEGG_DIE4}, // S_BLACKEGG_DIE3 - {SPR_BRAK, 16, 3, {A_PlaySound}, sfx_bgxpld, 0, S_BLACKEGG_DIE5}, // S_BLACKEGG_DIE4 - {SPR_BRAK, 17, -1, {NULL}, 0, 0, S_BLACKEGG_DIE5}, // S_BLACKEGG_DIE5 - - {SPR_BRAK, 18, 14, {NULL}, 0, 0, S_BLACKEGG_MISSILE2}, // S_BLACKEGG_MISSILE1 - {SPR_BRAK, 19, 5, {NULL}, 0, 0, S_BLACKEGG_MISSILE3}, // S_BLACKEGG_MISSILE2 - {SPR_BRAK, 20, 35, {A_Boss7FireMissiles}, MT_BLACKEGGMAN_MISSILE, sfx_beshot, S_BLACKEGG_JUMP1}, // S_BLACKEGG_MISSILE3 - - {SPR_BRAK, 21, -1, {NULL}, 0, 0, S_BLACKEGG_STND}, // S_BLACKEGG_GOOP - - {SPR_BRAK, 22, 14, {A_PlaySound}, sfx_belnch, 0, S_BLACKEGG_JUMP2}, // S_BLACKEGG_JUMP1 - {SPR_BRAK, 23, -1, {NULL}, 0, 0, S_BLACKEGG_WALK1}, // S_BLACKEGG_JUMP2 - - {SPR_BRAK, 21, 3*TICRATE, {NULL}, 0, 0, S_BLACKEGG_DESTROYPLAT2}, // S_BLACKEGG_DESTROYPLAT1 - {SPR_BRAK, 21, 1, {A_PlaySound}, sfx_s3k54, 0, S_BLACKEGG_DESTROYPLAT3}, // S_BLACKEGG_DESTROYPLAT2 - {SPR_BRAK, 21, 14, {A_LinedefExecuteFromArg}, 5, 0, S_BLACKEGG_STND}, // S_BLACKEGG_DESTROYPLAT3 - - {SPR_NULL, 0, 1, {A_CapeChase}, (160 - 20) << 16, 0, S_BLACKEGG_HELPER}, // S_BLACKEGG_HELPER - - {SPR_BGOO, FF_TRANS50 , 2, {NULL}, 0, 0, S_BLACKEGG_GOOP2}, // S_BLACKEGG_GOOP1 - {SPR_BGOO, FF_TRANS50|1, 2, {NULL}, 0, 0, S_BLACKEGG_GOOP1}, // S_BLACKEGG_GOOP2 - {SPR_BGOO, FF_TRANS50|2, 6*TICRATE, {A_GoopSplat}, 0, 0, S_BLACKEGG_GOOP4}, // S_BLACKEGG_GOOP3 - {SPR_BGOO, FF_TRANS60|2, 4, {NULL}, 0, 0, S_BLACKEGG_GOOP5}, // S_BLACKEGG_GOOP4 - {SPR_BGOO, FF_TRANS70|2, 4, {NULL}, 0, 0, S_BLACKEGG_GOOP6}, // S_BLACKEGG_GOOP5 - {SPR_BGOO, FF_TRANS80|2, 4, {NULL}, 0, 0, S_BLACKEGG_GOOP7}, // S_BLACKEGG_GOOP6 - {SPR_BGOO, FF_TRANS90|2, 4, {NULL}, 0, 0, S_NULL}, // S_BLACKEGG_GOOP7 - - {SPR_BMSL, 0, 1, {NULL}, 0, 0, S_BLACKEGG_MISSILE}, // S_BLACKEGG_MISSILE + {SPR_BRAK, 0, 1, {A_SetReactionTime}, 0, 0, S_BLACKEGG_STND2, 0}, // S_BLACKEGG_STND + {SPR_BRAK, 0, 7, {A_Look}, 1, 0, S_BLACKEGG_STND2, 0}, // S_BLACKEGG_STND2 + {SPR_BRAK, 1, 7, {NULL}, 0, 0, S_BLACKEGG_WALK2, 0}, // S_BLACKEGG_WALK1 + {SPR_BRAK, 2, 7, {NULL}, 0, 0, S_BLACKEGG_WALK3, 0}, // S_BLACKEGG_WALK2 + {SPR_BRAK, 3, 7, {A_PlaySound}, sfx_bestep, 0, S_BLACKEGG_WALK4, 0}, // S_BLACKEGG_WALK3 + {SPR_BRAK, 4, 7, {NULL}, 0, 0, S_BLACKEGG_WALK5, 0}, // S_BLACKEGG_WALK4 + {SPR_BRAK, 5, 7, {NULL}, 0, 0, S_BLACKEGG_WALK6, 0}, // S_BLACKEGG_WALK5 + {SPR_BRAK, 6, 7, {A_PlaySound}, sfx_bestp2, 0, S_BLACKEGG_WALK1, 0}, // S_BLACKEGG_WALK6 + {SPR_BRAK, 7, 3, {NULL}, 0, 0, S_BLACKEGG_SHOOT2, 0}, // S_BLACKEGG_SHOOT1 + {SPR_BRAK, 24, 1, {A_PlaySound}, sfx_befire, 0, S_BLACKEGG_SHOOT1, 0}, // S_BLACKEGG_SHOOT2 + + {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN2, 0}, // S_BLACKEGG_PAIN1 + {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN3, 0}, // S_BLACKEGG_PAIN2 + {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN4, 0}, // S_BLACKEGG_PAIN3 + {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN5, 0}, // S_BLACKEGG_PAIN4 + {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN6, 0}, // S_BLACKEGG_PAIN5 + {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN7, 0}, // S_BLACKEGG_PAIN6 + {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN8, 0}, // S_BLACKEGG_PAIN7 + {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN9, 0}, // S_BLACKEGG_PAIN8 + {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN10, 0}, // S_BLACKEGG_PAIN9 + {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN11, 0}, // S_BLACKEGG_PAIN10 + {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN12, 0}, // S_BLACKEGG_PAIN11 + {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN13, 0}, // S_BLACKEGG_PAIN12 + {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN14, 0}, // S_BLACKEGG_PAIN13 + {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN15, 0}, // S_BLACKEGG_PAIN14 + {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN16, 0}, // S_BLACKEGG_PAIN15 + {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN17, 0}, // S_BLACKEGG_PAIN16 + {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN18, 0}, // S_BLACKEGG_PAIN17 + {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN19, 0}, // S_BLACKEGG_PAIN18 + {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN20, 0}, // S_BLACKEGG_PAIN19 + {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN21, 0}, // S_BLACKEGG_PAIN20 + {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN22, 0}, // S_BLACKEGG_PAIN21 + {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN23, 0}, // S_BLACKEGG_PAIN22 + {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN24, 0}, // S_BLACKEGG_PAIN23 + {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN25, 0}, // S_BLACKEGG_PAIN24 + {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN26, 0}, // S_BLACKEGG_PAIN25 + {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN27, 0}, // S_BLACKEGG_PAIN26 + {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN28, 0}, // S_BLACKEGG_PAIN27 + {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN29, 0}, // S_BLACKEGG_PAIN28 + {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN30, 0}, // S_BLACKEGG_PAIN29 + {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN31, 0}, // S_BLACKEGG_PAIN30 + {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN32, 0}, // S_BLACKEGG_PAIN31 + {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN33, 0}, // S_BLACKEGG_PAIN32 + {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN34, 0}, // S_BLACKEGG_PAIN33 + {SPR_BRAK, 25, 1, {NULL}, 0, 0, S_BLACKEGG_PAIN35, 0}, // S_BLACKEGG_PAIN34 + {SPR_BRAK, 8, 1, {NULL}, 0, 0, S_BLACKEGG_WALK1, 0}, // S_BLACKEGG_PAIN35 + + {SPR_BRAK, 9, 20, {NULL}, 0, 0, S_BLACKEGG_HITFACE2, 0}, // S_BLACKEGG_HITFACE1 + {SPR_BRAK, 10, 2, {NULL}, 0, 0, S_BLACKEGG_HITFACE3, 0}, // S_BLACKEGG_HITFACE2 + {SPR_BRAK, 11, 2, {NULL}, 0, 0, S_BLACKEGG_HITFACE4, 0}, // S_BLACKEGG_HITFACE3 + {SPR_BRAK, 12,14, {NULL}, 0, 0, S_BLACKEGG_PAIN1, 0}, // S_BLACKEGG_HITFACE4 + + {SPR_BRAK, 13, 14, {NULL}, 0, 0, S_BLACKEGG_DIE2, 0}, // S_BLACKEGG_DIE1 + {SPR_BRAK, 14, 7, {NULL}, 0, 0, S_BLACKEGG_DIE3, 0}, // S_BLACKEGG_DIE2 + {SPR_BRAK, 15, 5, {NULL}, 0, 0, S_BLACKEGG_DIE4, 0}, // S_BLACKEGG_DIE3 + {SPR_BRAK, 16, 3, {A_PlaySound}, sfx_bgxpld, 0, S_BLACKEGG_DIE5, 0}, // S_BLACKEGG_DIE4 + {SPR_BRAK, 17, -1, {NULL}, 0, 0, S_BLACKEGG_DIE5, 0}, // S_BLACKEGG_DIE5 + + {SPR_BRAK, 18, 14, {NULL}, 0, 0, S_BLACKEGG_MISSILE2, 0}, // S_BLACKEGG_MISSILE1 + {SPR_BRAK, 19, 5, {NULL}, 0, 0, S_BLACKEGG_MISSILE3, 0}, // S_BLACKEGG_MISSILE2 + {SPR_BRAK, 20, 35, {A_Boss7FireMissiles}, MT_BLACKEGGMAN_MISSILE, sfx_beshot, S_BLACKEGG_JUMP1, 0}, // S_BLACKEGG_MISSILE3 + + {SPR_BRAK, 21, -1, {NULL}, 0, 0, S_BLACKEGG_STND, 0}, // S_BLACKEGG_GOOP + + {SPR_BRAK, 22, 14, {A_PlaySound}, sfx_belnch, 0, S_BLACKEGG_JUMP2, 0}, // S_BLACKEGG_JUMP1 + {SPR_BRAK, 23, -1, {NULL}, 0, 0, S_BLACKEGG_WALK1, 0}, // S_BLACKEGG_JUMP2 + + {SPR_BRAK, 21, 3*TICRATE, {NULL}, 0, 0, S_BLACKEGG_DESTROYPLAT2, 0}, // S_BLACKEGG_DESTROYPLAT1 + {SPR_BRAK, 21, 1, {A_PlaySound}, sfx_s3k54, 0, S_BLACKEGG_DESTROYPLAT3, 0}, // S_BLACKEGG_DESTROYPLAT2 + {SPR_BRAK, 21, 14, {A_LinedefExecuteFromArg}, 5, 0, S_BLACKEGG_STND, 0}, // S_BLACKEGG_DESTROYPLAT3 + + {SPR_NULL, 0, 1, {A_CapeChase}, (160 - 20) << 16, 0, S_BLACKEGG_HELPER, 0}, // S_BLACKEGG_HELPER + + {SPR_BGOO, FF_TRANS50 , 2, {NULL}, 0, 0, S_BLACKEGG_GOOP2, 0}, // S_BLACKEGG_GOOP1 + {SPR_BGOO, FF_TRANS50|1, 2, {NULL}, 0, 0, S_BLACKEGG_GOOP1, 0}, // S_BLACKEGG_GOOP2 + {SPR_BGOO, FF_TRANS50|2, 6*TICRATE, {A_GoopSplat}, 0, 0, S_BLACKEGG_GOOP4, 0}, // S_BLACKEGG_GOOP3 + {SPR_BGOO, FF_TRANS60|2, 4, {NULL}, 0, 0, S_BLACKEGG_GOOP5, 0}, // S_BLACKEGG_GOOP4 + {SPR_BGOO, FF_TRANS70|2, 4, {NULL}, 0, 0, S_BLACKEGG_GOOP6, 0}, // S_BLACKEGG_GOOP5 + {SPR_BGOO, FF_TRANS80|2, 4, {NULL}, 0, 0, S_BLACKEGG_GOOP7, 0}, // S_BLACKEGG_GOOP6 + {SPR_BGOO, FF_TRANS90|2, 4, {NULL}, 0, 0, S_NULL, 0}, // S_BLACKEGG_GOOP7 + + {SPR_BMSL, 0, 1, {NULL}, 0, 0, S_BLACKEGG_MISSILE, 0}, // S_BLACKEGG_MISSILE // New Very-Last-Minute 2.1 Brak Eggman (Cy-Brak-demon) - {SPR_BRAK, 0, 10, {A_Look}, 0, 0, S_CYBRAKDEMON_IDLE}, // S_CYBRAKDEMON_IDLE - {SPR_BRAK, 1, 8, {A_BrakChase}, 3, 0, S_CYBRAKDEMON_WALK2}, // S_CYBRAKDEMON_WALK1 - {SPR_BRAK, 2, 8, {A_BrakChase}, 3, 0, S_CYBRAKDEMON_WALK3}, // S_CYBRAKDEMON_WALK2 - {SPR_BRAK, 3, 8, {A_BrakChase}, 3, sfx_bestep, S_CYBRAKDEMON_WALK4}, // S_CYBRAKDEMON_WALK3 - {SPR_BRAK, 4, 8, {A_BrakChase}, 3, 0, S_CYBRAKDEMON_WALK5}, // S_CYBRAKDEMON_WALK4 - {SPR_BRAK, 5, 8, {A_BrakChase}, 3, 0, S_CYBRAKDEMON_WALK6}, // S_CYBRAKDEMON_WALK5 - {SPR_BRAK, 6, 8, {A_BrakChase}, 3, sfx_bestp2, S_CYBRAKDEMON_WALK1}, // S_CYBRAKDEMON_WALK6 - {SPR_BRAK, 7, 6, {A_RandomState}, S_CYBRAKDEMON_MISSILE_ATTACK1, S_CYBRAKDEMON_FLAME_ATTACK1, S_CYBRAKDEMON_MISSILE_ATTACK1}, // S_CYBRAKDEMON_CHOOSE_ATTACK1 - {SPR_BRAK, 7, 6, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_MISSILE_ATTACK2}, // S_CYBRAKDEMON_MISSILE_ATTACK1 // Aim - {SPR_BRAK, 26 + FF_FULLBRIGHT, 12, {A_BrakFireShot}, MT_CYBRAKDEMON_MISSILE, 128, S_CYBRAKDEMON_MISSILE_ATTACK3}, // S_CYBRAKDEMON_MISSILE_ATTACK2 // Fire - {SPR_BRAK, 7, 12, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_MISSILE_ATTACK4}, // S_CYBRAKDEMON_MISSILE_ATTACK3 // Aim - {SPR_BRAK, 26 + FF_FULLBRIGHT, 12, {A_BrakFireShot}, MT_CYBRAKDEMON_MISSILE, 128, S_CYBRAKDEMON_MISSILE_ATTACK5}, // S_CYBRAKDEMON_MISSILE_ATTACK4 // Fire - {SPR_BRAK, 7, 12, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_MISSILE_ATTACK6}, // S_CYBRAKDEMON_MISSILE_ATTACK5 // Aim - {SPR_BRAK, 26 + FF_FULLBRIGHT, 12, {A_BrakFireShot}, MT_CYBRAKDEMON_MISSILE, 128, S_CYBRAKDEMON_FINISH_ATTACK1}, // S_CYBRAKDEMON_MISSILE_ATTACK6 // Fire - {SPR_BRAK, 7, 1, {A_Repeat}, 1, S_CYBRAKDEMON_FLAME_ATTACK1, S_CYBRAKDEMON_FLAME_ATTACK2}, // S_CYBRAKDEMON_FLAME_ATTACK1 // Reset - {SPR_BRAK, 7, 6, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_FLAME_ATTACK3}, // S_CYBRAKDEMON_FLAME_ATTACK2 // Aim - {SPR_BRAK, 26 + FF_FULLBRIGHT, 2, {A_BrakFireShot}, MT_CYBRAKDEMON_FLAMESHOT, 128, S_CYBRAKDEMON_FLAME_ATTACK4}, // S_CYBRAKDEMON_FLAME_ATTACK3 // Fire - {SPR_BRAK, 7, 1, {A_Repeat}, 30, S_CYBRAKDEMON_FLAME_ATTACK3, S_CYBRAKDEMON_FINISH_ATTACK1}, // S_CYBRAKDEMON_FLAME_ATTACK4 // Loop - {SPR_BRAK, 0, 6, {A_RandomState}, S_CYBRAKDEMON_VILE_ATTACK1, S_CYBRAKDEMON_NAPALM_ATTACK1, S_CYBRAKDEMON_MISSILE_ATTACK1}, // S_CYBRAKDEMON_CHOOSE_ATTACK2 - {SPR_BRAK, 20, 0, {A_LinedefExecuteFromArg}, 5, 0, S_CYBRAKDEMON_VILE_ATTACK2}, // S_CYBRAKDEMON_VILE_ATTACK1 - {SPR_BRAK, 20, 24, {A_VileTarget}, MT_CYBRAKDEMON_TARGET_RETICULE, 1, S_CYBRAKDEMON_VILE_ATTACK3}, // S_CYBRAKDEMON_VILE_ATTACK2 - {SPR_BRAK, 19, 8, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_VILE_ATTACK4}, // S_CYBRAKDEMON_VILE_ATTACK3 - {SPR_BRAK, 18, 8, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_VILE_ATTACK5}, // S_CYBRAKDEMON_VILE_ATTACK4 - {SPR_BRAK, 8, 32, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_VILE_ATTACK6}, // S_CYBRAKDEMON_VILE_ATTACK5 - {SPR_BRAK, 20 + FF_FULLBRIGHT, 28, {A_VileAttack}, sfx_brakrx, MT_CYBRAKDEMON_VILE_EXPLOSION + (1<<16), S_CYBRAKDEMON_FINISH_ATTACK1}, // S_CYBRAKDEMON_VILE_ATTACK6 - {SPR_BRAK, 0, 6, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_NAPALM_ATTACK2}, // S_CYBRAKDEMON_NAPALM_ATTACK1 - {SPR_BRAK, 21 + FF_FULLBRIGHT, 8, {A_BrakLobShot}, MT_CYBRAKDEMON_NAPALM_BOMB_LARGE, 96, S_CYBRAKDEMON_NAPALM_ATTACK3}, // S_CYBRAKDEMON_NAPALM_ATTACK2 - {SPR_BRAK, 0, 8, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_FINISH_ATTACK1}, // S_CYBRAKDEMON_NAPALM_ATTACK3 - {SPR_BRAK, 0, 0, {A_SetObjectFlags2}, MF2_FRET, 1, S_CYBRAKDEMON_FINISH_ATTACK2}, // S_CYBRAKDEMON_FINISH_ATTACK1 // If just attacked, remove MF2_FRET w/out going back to spawnstate - {SPR_BRAK, 0, 0, {A_SetReactionTime}, 0, 0, S_CYBRAKDEMON_WALK1}, // S_CYBRAKDEMON_FINISH_ATTACK2 // If just attacked, remove MF2_FRET w/out going back to spawnstate - {SPR_BRAK, 18, 24, {A_Pain}, 0, 0, S_CYBRAKDEMON_PAIN2}, // S_CYBRAKDEMON_PAIN1 - {SPR_BRAK, 18, 0, {A_CheckHealth}, 3, S_CYBRAKDEMON_PAIN3, S_CYBRAKDEMON_CHOOSE_ATTACK1}, // S_CYBRAKDEMON_PAIN2 - {SPR_BRAK, 18, 0, {A_LinedefExecuteFromArg}, 4, 0, S_CYBRAKDEMON_CHOOSE_ATTACK1}, // S_CYBRAKDEMON_PAIN3 - {SPR_BRAK, 18, 1, {A_Repeat}, 1, S_CYBRAKDEMON_DIE1, S_CYBRAKDEMON_DIE2}, // S_CYBRAKDEMON_DIE1 - {SPR_BRAK, 18, 2, {A_BossScream}, 2, 0, S_CYBRAKDEMON_DIE3}, // S_CYBRAKDEMON_DIE2 - {SPR_BRAK, 18, 0, {A_Repeat}, 52, S_CYBRAKDEMON_DIE2, S_CYBRAKDEMON_DIE4}, // S_CYBRAKDEMON_DIE3 - {SPR_BRAK, 13, 34, {A_BossDeath}, 0, 0, S_CYBRAKDEMON_DIE5}, // S_CYBRAKDEMON_DIE4 - {SPR_BRAK, 14, 34, {NULL}, 0, 0, S_CYBRAKDEMON_DIE6}, // S_CYBRAKDEMON_DIE5 - {SPR_BRAK, 15, 34, {NULL}, 0, 0, S_CYBRAKDEMON_DIE7}, // S_CYBRAKDEMON_DIE6 - {SPR_BRAK, 16, 34, {NULL}, 0, 0, S_CYBRAKDEMON_DIE8}, // S_CYBRAKDEMON_DIE7 - {SPR_BRAK, 17, 34, {NULL}, sfx_befall, 0, S_CYBRAKDEMON_DIE8}, // S_CYBRAKDEMON_DIE8 - {SPR_BRAK, 0, 0, {A_SetObjectFlags}, MF_SPECIAL|MF_SHOOTABLE, 2, S_CYBRAKDEMON_IDLE}, // S_CYBRAKDEMON_DEINVINCIBLERIZE - {SPR_BRAK, 0, 0, {A_SetObjectFlags}, MF_SPECIAL|MF_SHOOTABLE, 1, S_CYBRAKDEMON_IDLE}, // S_CYBRAKDEMON_INVINCIBLERIZE - - {SPR_RCKT, 0 + FF_FULLBRIGHT, 1, {A_SetObjectFlags2}, MF2_RAILRING, 2, S_CYBRAKDEMONMISSILE}, // S_CYBRAKDEMONMISSILE - {SPR_RCKT, 1 + FF_FULLBRIGHT, 8, {A_Explode}, 0, 0, S_CYBRAKDEMONMISSILE_EXPLODE2}, // S_CYBRAKDEMONMISSILE_EXPLODE1 //TODO: set missile mobj's "damage" to an appropriate radius - {SPR_RCKT, 2 + FF_FULLBRIGHT, 6, {A_NapalmScatter}, MT_CYBRAKDEMON_NAPALM_FLAMES + (6<<16), 32 + (16<<16), S_CYBRAKDEMONMISSILE_EXPLODE3}, // S_CYBRAKDEMONMISSILE_EXPLODE2 - {SPR_RCKT, 3 + FF_FULLBRIGHT, 4, {NULL}, 0, 0, S_NULL}, // S_CYBRAKDEMONMISSILE_EXPLODE3 - - {SPR_FLME, FF_FULLBRIGHT , 15, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY2}, // S_CYBRAKDEMONFLAMESHOT_FLY1 - {SPR_FLME, FF_FULLBRIGHT|1, 15, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY3}, // S_CYBRAKDEMONFLAMESHOT_FLY2 - {SPR_FLME, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY3}, // S_CYBRAKDEMONFLAMESHOT_FLY3 - {SPR_FLME, FF_FULLBRIGHT|2, 0, {A_SpawnObjectRelative}, 0, MT_CYBRAKDEMON_FLAMEREST, S_NULL}, // S_CYBRAKDEMONFLAMESHOT_DIE - - {SPR_FLAM, FF_FULLBRIGHT, 1, {A_SetFuse}, 10*TICRATE, 0, S_FLAMEREST}, // S_CYBRAKDEMONFLAMEREST - - {SPR_ELEC, 0 + FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_INIT2}, // S_CYBRAKDEMONELECTRICBARRIER_INIT1 - {SPR_ELEC, 0 + FF_FULLBRIGHT, 0, {A_RemoteAction}, -1, S_CYBRAKDEMON_INVINCIBLERIZE, S_CYBRAKDEMONELECTRICBARRIER_PLAYSOUND}, // S_CYBRAKDEMONELECTRICBARRIER_INIT2 - {SPR_ELEC, 0 + FF_FULLBRIGHT, 0, {A_PlayActiveSound}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER1}, // S_CYBRAKDEMONELECTRICBARRIER_PLAYSOUND - {SPR_ELEC, 0 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER2}, // S_CYBRAKDEMONELECTRICBARRIER1 - {SPR_ELEC, 0 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER3}, // S_CYBRAKDEMONELECTRICBARRIER2 - {SPR_ELEC, 1 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER4}, // S_CYBRAKDEMONELECTRICBARRIER3 - {SPR_ELEC, 1 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER5}, // S_CYBRAKDEMONELECTRICBARRIER4 - {SPR_ELEC, 2 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER6}, // S_CYBRAKDEMONELECTRICBARRIER5 - {SPR_ELEC, 2 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER7}, // S_CYBRAKDEMONELECTRICBARRIER6 - {SPR_ELEC, 3 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER8}, // S_CYBRAKDEMONELECTRICBARRIER7 - {SPR_ELEC, 3 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER9}, // S_CYBRAKDEMONELECTRICBARRIER8 - {SPR_ELEC, 4 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER10}, // S_CYBRAKDEMONELECTRICBARRIER9 - {SPR_ELEC, 4 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER11}, // S_CYBRAKDEMONELECTRICBARRIER10 - {SPR_ELEC, 5 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER12}, // S_CYBRAKDEMONELECTRICBARRIER11 - {SPR_ELEC, 5 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER13}, // S_CYBRAKDEMONELECTRICBARRIER12 - {SPR_ELEC, 6 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER14}, // S_CYBRAKDEMONELECTRICBARRIER13 - {SPR_ELEC, 6 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER15}, // S_CYBRAKDEMONELECTRICBARRIER14 - {SPR_ELEC, 7 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER16}, // S_CYBRAKDEMONELECTRICBARRIER15 - {SPR_ELEC, 7 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER17}, // S_CYBRAKDEMONELECTRICBARRIER16 - {SPR_ELEC, 8 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER18}, // S_CYBRAKDEMONELECTRICBARRIER17 - {SPR_ELEC, 8 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER19}, // S_CYBRAKDEMONELECTRICBARRIER18 - {SPR_ELEC, 9 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER20}, // S_CYBRAKDEMONELECTRICBARRIER19 - {SPR_ELEC, 9 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER21}, // S_CYBRAKDEMONELECTRICBARRIER20 - {SPR_ELEC, 10 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER22}, // S_CYBRAKDEMONELECTRICBARRIER21 - {SPR_ELEC, 10 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER23}, // S_CYBRAKDEMONELECTRICBARRIER22 - {SPR_ELEC, 11 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER24}, // S_CYBRAKDEMONELECTRICBARRIER23 - {SPR_ELEC, 11 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_PLAYSOUND}, // S_CYBRAKDEMONELECTRICBARRIER24 - {SPR_NULL, 0, 0, {A_RemoteAction}, -1, S_CYBRAKDEMON_DEINVINCIBLERIZE, S_CYBRAKDEMONELECTRICBARRIER_DIE2}, // S_CYBRAKDEMONELECTRICBARRIER_DIE1 - {SPR_NULL, 0, 0, {A_SetObjectFlags}, MF_PUSHABLE|MF_FIRE|MF_PAIN, 1, S_CYBRAKDEMONELECTRICBARRIER_DIE3}, // S_CYBRAKDEMONELECTRICBARRIER_DIE2 - {SPR_NULL, 0, 20*TICRATE, {A_Scream}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMSUCCESS}, // S_CYBRAKDEMONELECTRICBARRIER_DIE3 - {SPR_NULL, 0, 0, {A_CheckRandom}, 10, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMSUCCESS, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMFAIL}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMCHECK, - {SPR_NULL, 0, 0, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMCHOOSE}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMSUCCESS, - {SPR_NULL, 0, 0, {A_RandomStateRange}, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM12, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM1}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMCHOOSE, - {SPR_ELEC, 0 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM1, - {SPR_ELEC, 1 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM2, - {SPR_ELEC, 2 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM3, - {SPR_ELEC, 3 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM4, - {SPR_ELEC, 4 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM5, - {SPR_ELEC, 5 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM6, - {SPR_ELEC, 6 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM7, - {SPR_ELEC, 7 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM8, - {SPR_ELEC, 8 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM9, - {SPR_ELEC, 9 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM10, - {SPR_ELEC, 10 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM11, - {SPR_ELEC, 11 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM12, - {SPR_NULL, 0, 1, {NULL}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMFAIL, - {SPR_NULL, 0, 0, {A_Repeat}, 5*TICRATE, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMCHECK, S_CYBRAKDEMONELECTRICBARRIER_REVIVE1}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP, - {SPR_NULL, 0, 0, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_REVIVE2}, // S_CYBRAKDEMONELECTRICBARRIER_REVIVE1 - {SPR_NULL, 0, 0, {A_SpawnFreshCopy}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_REVIVE3}, // S_CYBRAKDEMONELECTRICBARRIER_REVIVE2 - {SPR_NULL, 0, TICRATE, {A_PlaySound}, sfx_s3k79, 0, S_NULL}, // S_CYBRAKDEMONELECTRICBARRIER_REVIVE3 - - {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT , 1, {A_VileFire}, sfx_s3k9d, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE2}, // S_CYBRAKDEMONTARGETRETICULE1 - {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|6, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE3}, // S_CYBRAKDEMONTARGETRETICULE2 - {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|1, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE4}, // S_CYBRAKDEMONTARGETRETICULE3 - {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|6, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE5}, // S_CYBRAKDEMONTARGETRETICULE4 - {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|2, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE6}, // S_CYBRAKDEMONTARGETRETICULE5 - {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|6, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE7}, // S_CYBRAKDEMONTARGETRETICULE6 - {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|3, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE8}, // S_CYBRAKDEMONTARGETRETICULE7 - {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|6, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE9}, // S_CYBRAKDEMONTARGETRETICULE8 - {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|4, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE10}, // S_CYBRAKDEMONTARGETRETICULE9 - {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|6, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE11}, // S_CYBRAKDEMONTARGETRETICULE10 - {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|5, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE12}, // S_CYBRAKDEMONTARGETRETICULE11 - {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|6, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE13}, // S_CYBRAKDEMONTARGETRETICULE12 - {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT , 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE14}, // S_CYBRAKDEMONTARGETRETICULE13 - {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|6, 1, {A_Repeat}, 6, S_CYBRAKDEMONTARGETRETICULE2, S_NULL}, // S_CYBRAKDEMONTARGETRETICULE14 - - {SPR_HOOP, FF_TRANS50|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_CYBRAKDEMONTARGETDOT - - {SPR_NPLM, 0, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMBOMBLARGE_FLY2}, //S_CYBRAKDEMONNAPALMBOMBLARGE_FLY1, - {SPR_NPLM, 1, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMBOMBLARGE_FLY3}, //S_CYBRAKDEMONNAPALMBOMBLARGE_FLY2, - {SPR_NPLM, 2, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMBOMBLARGE_FLY4}, //S_CYBRAKDEMONNAPALMBOMBLARGE_FLY3, - {SPR_NPLM, 3, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMBOMBLARGE_FLY1}, //S_CYBRAKDEMONNAPALMBOMBLARGE_FLY4, - {SPR_NPLM, 0, 1, {A_Explode}, 0, 0, S_CYBRAKDEMONNAPALMBOMBLARGE_DIE2}, //S_CYBRAKDEMONNAPALMBOMBLARGE_DIE1, // Explode - {SPR_NPLM, 0, 1, {A_NapalmScatter}, MT_CYBRAKDEMON_NAPALM_BOMB_SMALL + (6<<16), 256 + (48<<16), S_CYBRAKDEMONNAPALMBOMBLARGE_DIE3}, //S_CYBRAKDEMONNAPALMBOMBLARGE_DIE2, // Outer ring - {SPR_NPLM, 0, 1, {A_NapalmScatter}, MT_CYBRAKDEMON_NAPALM_BOMB_SMALL + (1<<16), 32<<16, S_CYBRAKDEMONNAPALMBOMBLARGE_DIE4}, //S_CYBRAKDEMONNAPALMBOMBLARGE_DIE3, // Center - {SPR_NULL, 0, 81, {A_Scream}, 0, 0, S_NULL}, //S_CYBRAKDEMONNAPALMBOMBLARGE_DIE4, // Sound - - {SPR_MNPL, 0, 1, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMBOMBSMALL}, //S_CYBRAKDEMONNAPALMBOMBSMALL, - {SPR_MNPL, 0, 1, {A_Explode}, 0, 0, S_CYBRAKDEMONNAPALMBOMBSMALL_DIE2}, //S_CYBRAKDEMONNAPALMBOMBSMALL_DIE1, // Explode - {SPR_MNPL, 0, 1, {A_NapalmScatter}, MT_CYBRAKDEMON_NAPALM_FLAMES + (12<<16), 128 + (40<<16), S_CYBRAKDEMONNAPALMBOMBSMALL_DIE3}, //S_CYBRAKDEMONNAPALMBOMBSMALL_DIE2, // Outer ring - {SPR_MNPL, 0, 1, {A_NapalmScatter}, MT_CYBRAKDEMON_NAPALM_FLAMES + (8<<16), 64 + (32<<16), S_CYBRAKDEMONNAPALMBOMBSMALL_DIE4}, //S_CYBRAKDEMONNAPALMBOMBSMALL_DIE3, // Inner ring - {SPR_MNPL, 0, 1, {A_NapalmScatter}, MT_CYBRAKDEMON_NAPALM_FLAMES + (1<<16), 24<<16, S_CYBRAKDEMONNAPALMBOMBSMALL_DIE5}, //S_CYBRAKDEMONNAPALMBOMBSMALL_DIE4, // Center - {SPR_NULL, 0, 24, {A_Scream}, 0, 0, S_NULL}, //S_CYBRAKDEMONNAPALMBOMBSMALL_DIE5, // Sound - - {SPR_SFLM, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY2}, //S_CYBRAKDEMONNAPALMFLAME_FLY1, - {SPR_SFLM, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY3}, //S_CYBRAKDEMONNAPALMFLAME_FLY2, - {SPR_SFLM, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY4}, //S_CYBRAKDEMONNAPALMFLAME_FLY3, - {SPR_SFLM, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY5}, //S_CYBRAKDEMONNAPALMFLAME_FLY4, - {SPR_SFLM, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY6}, //S_CYBRAKDEMONNAPALMFLAME_FLY5, - {SPR_SFLM, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY1}, //S_CYBRAKDEMONNAPALMFLAME_FLY6, - {SPR_SFLM, FF_FULLBRIGHT, 0, {A_SpawnObjectRelative}, 0, MT_CYBRAKDEMON_FLAMEREST, S_NULL}, //S_CYBRAKDEMONNAPALMFLAME_DIE, - - {SPR_NULL, 0, 1, {A_SetFuse}, TICRATE, 0, S_CYBRAKDEMONVILEEXPLOSION2}, //S_CYBRAKDEMONVILEEXPLOSION1, - {SPR_NULL, 0, 0, {A_ScoreRise}, 0, 0, S_CYBRAKDEMONVILEEXPLOSION3}, //S_CYBRAKDEMONVILEEXPLOSION2, - {SPR_NULL, 0, 1, {A_BossScream}, 0, 0, S_CYBRAKDEMONVILEEXPLOSION1}, //S_CYBRAKDEMONVILEEXPLOSION3, + {SPR_BRAK, 0, 10, {A_Look}, 0, 0, S_CYBRAKDEMON_IDLE, 0}, // S_CYBRAKDEMON_IDLE + {SPR_BRAK, 1, 8, {A_BrakChase}, 3, 0, S_CYBRAKDEMON_WALK2, 0}, // S_CYBRAKDEMON_WALK1 + {SPR_BRAK, 2, 8, {A_BrakChase}, 3, 0, S_CYBRAKDEMON_WALK3, 0}, // S_CYBRAKDEMON_WALK2 + {SPR_BRAK, 3, 8, {A_BrakChase}, 3, sfx_bestep, S_CYBRAKDEMON_WALK4, 0}, // S_CYBRAKDEMON_WALK3 + {SPR_BRAK, 4, 8, {A_BrakChase}, 3, 0, S_CYBRAKDEMON_WALK5, 0}, // S_CYBRAKDEMON_WALK4 + {SPR_BRAK, 5, 8, {A_BrakChase}, 3, 0, S_CYBRAKDEMON_WALK6, 0}, // S_CYBRAKDEMON_WALK5 + {SPR_BRAK, 6, 8, {A_BrakChase}, 3, sfx_bestp2, S_CYBRAKDEMON_WALK1, 0}, // S_CYBRAKDEMON_WALK6 + {SPR_BRAK, 7, 6, {A_RandomState}, S_CYBRAKDEMON_MISSILE_ATTACK1, S_CYBRAKDEMON_FLAME_ATTACK1, S_CYBRAKDEMON_MISSILE_ATTACK1, 0}, // S_CYBRAKDEMON_CHOOSE_ATTACK1 + {SPR_BRAK, 7, 6, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_MISSILE_ATTACK2, 0}, // S_CYBRAKDEMON_MISSILE_ATTACK1 // Aim + {SPR_BRAK, 26 + FF_FULLBRIGHT, 12, {A_BrakFireShot}, MT_CYBRAKDEMON_MISSILE, 128, S_CYBRAKDEMON_MISSILE_ATTACK3, 0}, // S_CYBRAKDEMON_MISSILE_ATTACK2 // Fire + {SPR_BRAK, 7, 12, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_MISSILE_ATTACK4, 0}, // S_CYBRAKDEMON_MISSILE_ATTACK3 // Aim + {SPR_BRAK, 26 + FF_FULLBRIGHT, 12, {A_BrakFireShot}, MT_CYBRAKDEMON_MISSILE, 128, S_CYBRAKDEMON_MISSILE_ATTACK5, 0}, // S_CYBRAKDEMON_MISSILE_ATTACK4 // Fire + {SPR_BRAK, 7, 12, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_MISSILE_ATTACK6, 0}, // S_CYBRAKDEMON_MISSILE_ATTACK5 // Aim + {SPR_BRAK, 26 + FF_FULLBRIGHT, 12, {A_BrakFireShot}, MT_CYBRAKDEMON_MISSILE, 128, S_CYBRAKDEMON_FINISH_ATTACK1, 0}, // S_CYBRAKDEMON_MISSILE_ATTACK6 // Fire + {SPR_BRAK, 7, 1, {A_Repeat}, 1, S_CYBRAKDEMON_FLAME_ATTACK1, S_CYBRAKDEMON_FLAME_ATTACK2, 0}, // S_CYBRAKDEMON_FLAME_ATTACK1 // Reset + {SPR_BRAK, 7, 6, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_FLAME_ATTACK3, 0}, // S_CYBRAKDEMON_FLAME_ATTACK2 // Aim + {SPR_BRAK, 26 + FF_FULLBRIGHT, 2, {A_BrakFireShot}, MT_CYBRAKDEMON_FLAMESHOT, 128, S_CYBRAKDEMON_FLAME_ATTACK4, 0}, // S_CYBRAKDEMON_FLAME_ATTACK3 // Fire + {SPR_BRAK, 7, 1, {A_Repeat}, 30, S_CYBRAKDEMON_FLAME_ATTACK3, S_CYBRAKDEMON_FINISH_ATTACK1, 0}, // S_CYBRAKDEMON_FLAME_ATTACK4 // Loop + {SPR_BRAK, 0, 6, {A_RandomState}, S_CYBRAKDEMON_VILE_ATTACK1, S_CYBRAKDEMON_NAPALM_ATTACK1, S_CYBRAKDEMON_MISSILE_ATTACK1, 0}, // S_CYBRAKDEMON_CHOOSE_ATTACK2 + {SPR_BRAK, 20, 0, {A_LinedefExecuteFromArg}, 5, 0, S_CYBRAKDEMON_VILE_ATTACK2, 0}, // S_CYBRAKDEMON_VILE_ATTACK1 + {SPR_BRAK, 20, 24, {A_VileTarget}, MT_CYBRAKDEMON_TARGET_RETICULE, 1, S_CYBRAKDEMON_VILE_ATTACK3, 0}, // S_CYBRAKDEMON_VILE_ATTACK2 + {SPR_BRAK, 19, 8, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_VILE_ATTACK4, 0}, // S_CYBRAKDEMON_VILE_ATTACK3 + {SPR_BRAK, 18, 8, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_VILE_ATTACK5, 0}, // S_CYBRAKDEMON_VILE_ATTACK4 + {SPR_BRAK, 8, 32, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_VILE_ATTACK6, 0}, // S_CYBRAKDEMON_VILE_ATTACK5 + {SPR_BRAK, 20 + FF_FULLBRIGHT, 28, {A_VileAttack}, sfx_brakrx, MT_CYBRAKDEMON_VILE_EXPLOSION + (1<<16), S_CYBRAKDEMON_FINISH_ATTACK1, 0}, // S_CYBRAKDEMON_VILE_ATTACK6 + {SPR_BRAK, 0, 6, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_NAPALM_ATTACK2, 0}, // S_CYBRAKDEMON_NAPALM_ATTACK1 + {SPR_BRAK, 21 + FF_FULLBRIGHT, 8, {A_BrakLobShot}, MT_CYBRAKDEMON_NAPALM_BOMB_LARGE, 96, S_CYBRAKDEMON_NAPALM_ATTACK3, 0}, // S_CYBRAKDEMON_NAPALM_ATTACK2 + {SPR_BRAK, 0, 8, {A_FaceTarget}, 0, 0, S_CYBRAKDEMON_FINISH_ATTACK1, 0}, // S_CYBRAKDEMON_NAPALM_ATTACK3 + {SPR_BRAK, 0, 0, {A_SetObjectFlags2}, MF2_FRET, 1, S_CYBRAKDEMON_FINISH_ATTACK2, 0}, // S_CYBRAKDEMON_FINISH_ATTACK1 // If just attacked, remove MF2_FRET w/out going back to spawnstate + {SPR_BRAK, 0, 0, {A_SetReactionTime}, 0, 0, S_CYBRAKDEMON_WALK1, 0}, // S_CYBRAKDEMON_FINISH_ATTACK2 // If just attacked, remove MF2_FRET w/out going back to spawnstate + {SPR_BRAK, 18, 24, {A_Pain}, 0, 0, S_CYBRAKDEMON_PAIN2, 0}, // S_CYBRAKDEMON_PAIN1 + {SPR_BRAK, 18, 0, {A_CheckHealth}, 3, S_CYBRAKDEMON_PAIN3, S_CYBRAKDEMON_CHOOSE_ATTACK1, 0}, // S_CYBRAKDEMON_PAIN2 + {SPR_BRAK, 18, 0, {A_LinedefExecuteFromArg}, 4, 0, S_CYBRAKDEMON_CHOOSE_ATTACK1, 0}, // S_CYBRAKDEMON_PAIN3 + {SPR_BRAK, 18, 1, {A_Repeat}, 1, S_CYBRAKDEMON_DIE1, S_CYBRAKDEMON_DIE2, 0}, // S_CYBRAKDEMON_DIE1 + {SPR_BRAK, 18, 2, {A_BossScream}, 2, 0, S_CYBRAKDEMON_DIE3, 0}, // S_CYBRAKDEMON_DIE2 + {SPR_BRAK, 18, 0, {A_Repeat}, 52, S_CYBRAKDEMON_DIE2, S_CYBRAKDEMON_DIE4, 0}, // S_CYBRAKDEMON_DIE3 + {SPR_BRAK, 13, 34, {A_BossDeath}, 0, 0, S_CYBRAKDEMON_DIE5, 0}, // S_CYBRAKDEMON_DIE4 + {SPR_BRAK, 14, 34, {NULL}, 0, 0, S_CYBRAKDEMON_DIE6, 0}, // S_CYBRAKDEMON_DIE5 + {SPR_BRAK, 15, 34, {NULL}, 0, 0, S_CYBRAKDEMON_DIE7, 0}, // S_CYBRAKDEMON_DIE6 + {SPR_BRAK, 16, 34, {NULL}, 0, 0, S_CYBRAKDEMON_DIE8, 0}, // S_CYBRAKDEMON_DIE7 + {SPR_BRAK, 17, 34, {NULL}, sfx_befall, 0, S_CYBRAKDEMON_DIE8, 0}, // S_CYBRAKDEMON_DIE8 + {SPR_BRAK, 0, 0, {A_SetObjectFlags}, MF_SPECIAL|MF_SHOOTABLE, 2, S_CYBRAKDEMON_IDLE, 0}, // S_CYBRAKDEMON_DEINVINCIBLERIZE + {SPR_BRAK, 0, 0, {A_SetObjectFlags}, MF_SPECIAL|MF_SHOOTABLE, 1, S_CYBRAKDEMON_IDLE, 0}, // S_CYBRAKDEMON_INVINCIBLERIZE + + {SPR_RCKT, 0 + FF_FULLBRIGHT, 1, {A_SetObjectFlags2}, MF2_RAILRING, 2, S_CYBRAKDEMONMISSILE, 0}, // S_CYBRAKDEMONMISSILE + {SPR_RCKT, 1 + FF_FULLBRIGHT, 8, {A_Explode}, 0, 0, S_CYBRAKDEMONMISSILE_EXPLODE2, 0}, // S_CYBRAKDEMONMISSILE_EXPLODE1 //TODO: set missile mobj's "damage" to an appropriate radius + {SPR_RCKT, 2 + FF_FULLBRIGHT, 6, {A_NapalmScatter}, MT_CYBRAKDEMON_NAPALM_FLAMES + (6<<16), 32 + (16<<16), S_CYBRAKDEMONMISSILE_EXPLODE3, 0}, // S_CYBRAKDEMONMISSILE_EXPLODE2 + {SPR_RCKT, 3 + FF_FULLBRIGHT, 4, {NULL}, 0, 0, S_NULL, 0}, // S_CYBRAKDEMONMISSILE_EXPLODE3 + + {SPR_FLME, FF_FULLBRIGHT , 15, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY2, 0}, // S_CYBRAKDEMONFLAMESHOT_FLY1 + {SPR_FLME, FF_FULLBRIGHT|1, 15, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY3, 0}, // S_CYBRAKDEMONFLAMESHOT_FLY2 + {SPR_FLME, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY3, 0}, // S_CYBRAKDEMONFLAMESHOT_FLY3 + {SPR_FLME, FF_FULLBRIGHT|2, 0, {A_SpawnObjectRelative}, 0, MT_CYBRAKDEMON_FLAMEREST, S_NULL, 0}, // S_CYBRAKDEMONFLAMESHOT_DIE + + {SPR_FLAM, FF_FULLBRIGHT, 1, {A_SetFuse}, 10*TICRATE, 0, S_FLAMEREST, 0}, // S_CYBRAKDEMONFLAMEREST + + {SPR_ELEC, 0 + FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_INIT2, 0}, // S_CYBRAKDEMONELECTRICBARRIER_INIT1 + {SPR_ELEC, 0 + FF_FULLBRIGHT, 0, {A_RemoteAction}, -1, S_CYBRAKDEMON_INVINCIBLERIZE, S_CYBRAKDEMONELECTRICBARRIER_PLAYSOUND, 0}, // S_CYBRAKDEMONELECTRICBARRIER_INIT2 + {SPR_ELEC, 0 + FF_FULLBRIGHT, 0, {A_PlayActiveSound}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER1, 0}, // S_CYBRAKDEMONELECTRICBARRIER_PLAYSOUND + {SPR_ELEC, 0 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER2, 0}, // S_CYBRAKDEMONELECTRICBARRIER1 + {SPR_ELEC, 0 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER3, 0}, // S_CYBRAKDEMONELECTRICBARRIER2 + {SPR_ELEC, 1 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER4, 0}, // S_CYBRAKDEMONELECTRICBARRIER3 + {SPR_ELEC, 1 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER5, 0}, // S_CYBRAKDEMONELECTRICBARRIER4 + {SPR_ELEC, 2 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER6, 0}, // S_CYBRAKDEMONELECTRICBARRIER5 + {SPR_ELEC, 2 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER7, 0}, // S_CYBRAKDEMONELECTRICBARRIER6 + {SPR_ELEC, 3 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER8, 0}, // S_CYBRAKDEMONELECTRICBARRIER7 + {SPR_ELEC, 3 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER9, 0}, // S_CYBRAKDEMONELECTRICBARRIER8 + {SPR_ELEC, 4 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER10, 0}, // S_CYBRAKDEMONELECTRICBARRIER9 + {SPR_ELEC, 4 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER11, 0}, // S_CYBRAKDEMONELECTRICBARRIER10 + {SPR_ELEC, 5 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER12, 0}, // S_CYBRAKDEMONELECTRICBARRIER11 + {SPR_ELEC, 5 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER13, 0}, // S_CYBRAKDEMONELECTRICBARRIER12 + {SPR_ELEC, 6 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER14, 0}, // S_CYBRAKDEMONELECTRICBARRIER13 + {SPR_ELEC, 6 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER15, 0}, // S_CYBRAKDEMONELECTRICBARRIER14 + {SPR_ELEC, 7 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER16, 0}, // S_CYBRAKDEMONELECTRICBARRIER15 + {SPR_ELEC, 7 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER17, 0}, // S_CYBRAKDEMONELECTRICBARRIER16 + {SPR_ELEC, 8 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER18, 0}, // S_CYBRAKDEMONELECTRICBARRIER17 + {SPR_ELEC, 8 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER19, 0}, // S_CYBRAKDEMONELECTRICBARRIER18 + {SPR_ELEC, 9 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER20, 0}, // S_CYBRAKDEMONELECTRICBARRIER19 + {SPR_ELEC, 9 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER21, 0}, // S_CYBRAKDEMONELECTRICBARRIER20 + {SPR_ELEC, 10 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER22, 0}, // S_CYBRAKDEMONELECTRICBARRIER21 + {SPR_ELEC, 10 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER23, 0}, // S_CYBRAKDEMONELECTRICBARRIER22 + {SPR_ELEC, 11 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER24, 0}, // S_CYBRAKDEMONELECTRICBARRIER23 + {SPR_ELEC, 11 + FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_PLAYSOUND, 0}, // S_CYBRAKDEMONELECTRICBARRIER24 + {SPR_NULL, 0, 0, {A_RemoteAction}, -1, S_CYBRAKDEMON_DEINVINCIBLERIZE, S_CYBRAKDEMONELECTRICBARRIER_DIE2, 0}, // S_CYBRAKDEMONELECTRICBARRIER_DIE1 + {SPR_NULL, 0, 0, {A_SetObjectFlags}, MF_PUSHABLE|MF_FIRE|MF_PAIN, 1, S_CYBRAKDEMONELECTRICBARRIER_DIE3, 0}, // S_CYBRAKDEMONELECTRICBARRIER_DIE2 + {SPR_NULL, 0, 20*TICRATE, {A_Scream}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMSUCCESS, 0}, // S_CYBRAKDEMONELECTRICBARRIER_DIE3 + {SPR_NULL, 0, 0, {A_CheckRandom}, 10, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMSUCCESS, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMFAIL, 0}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMCHECK, + {SPR_NULL, 0, 0, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMCHOOSE, 0}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMSUCCESS, + {SPR_NULL, 0, 0, {A_RandomStateRange}, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM12, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM1, 0}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMCHOOSE, + {SPR_ELEC, 0 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP, 0}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM1, + {SPR_ELEC, 1 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP, 0}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM2, + {SPR_ELEC, 2 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP, 0}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM3, + {SPR_ELEC, 3 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP, 0}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM4, + {SPR_ELEC, 4 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP, 0}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM5, + {SPR_ELEC, 5 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP, 0}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM6, + {SPR_ELEC, 6 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP, 0}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM7, + {SPR_ELEC, 7 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP, 0}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM8, + {SPR_ELEC, 8 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP, 0}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM9, + {SPR_ELEC, 9 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP, 0}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM10, + {SPR_ELEC, 10 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP, 0}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM11, + {SPR_ELEC, 11 + FF_FULLBRIGHT, 1, {A_PlaySound}, sfx_s3k5c, 1, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP, 0}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOM12, + {SPR_NULL, 0, 1, {NULL}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP, 0}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMFAIL, + {SPR_NULL, 0, 0, {A_Repeat}, 5*TICRATE, S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMCHECK, S_CYBRAKDEMONELECTRICBARRIER_REVIVE1, 0}, // S_CYBRAKDEMONELECTRICBARRIER_SPARK_RANDOMLOOP, + {SPR_NULL, 0, 0, {A_CapeChase}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_REVIVE2, 0}, // S_CYBRAKDEMONELECTRICBARRIER_REVIVE1 + {SPR_NULL, 0, 0, {A_SpawnFreshCopy}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_REVIVE3, 0}, // S_CYBRAKDEMONELECTRICBARRIER_REVIVE2 + {SPR_NULL, 0, TICRATE, {A_PlaySound}, sfx_s3k79, 0, S_NULL, 0}, // S_CYBRAKDEMONELECTRICBARRIER_REVIVE3 + + {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT , 1, {A_VileFire}, sfx_s3k9d, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE2, 0}, // S_CYBRAKDEMONTARGETRETICULE1 + {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|6, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE3, 0}, // S_CYBRAKDEMONTARGETRETICULE2 + {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|1, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE4, 0}, // S_CYBRAKDEMONTARGETRETICULE3 + {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|6, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE5, 0}, // S_CYBRAKDEMONTARGETRETICULE4 + {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|2, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE6, 0}, // S_CYBRAKDEMONTARGETRETICULE5 + {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|6, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE7, 0}, // S_CYBRAKDEMONTARGETRETICULE6 + {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|3, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE8, 0}, // S_CYBRAKDEMONTARGETRETICULE7 + {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|6, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE9, 0}, // S_CYBRAKDEMONTARGETRETICULE8 + {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|4, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE10, 0}, // S_CYBRAKDEMONTARGETRETICULE9 + {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|6, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE11, 0}, // S_CYBRAKDEMONTARGETRETICULE10 + {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|5, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE12, 0}, // S_CYBRAKDEMONTARGETRETICULE11 + {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|6, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE13, 0}, // S_CYBRAKDEMONTARGETRETICULE12 + {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT , 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE14, 0}, // S_CYBRAKDEMONTARGETRETICULE13 + {SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|6, 1, {A_Repeat}, 6, S_CYBRAKDEMONTARGETRETICULE2, S_NULL, 0}, // S_CYBRAKDEMONTARGETRETICULE14 + + {SPR_HOOP, FF_TRANS50|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL, 0}, // S_CYBRAKDEMONTARGETDOT + + {SPR_NPLM, 0, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMBOMBLARGE_FLY2, 0}, //S_CYBRAKDEMONNAPALMBOMBLARGE_FLY1, + {SPR_NPLM, 1, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMBOMBLARGE_FLY3, 0}, //S_CYBRAKDEMONNAPALMBOMBLARGE_FLY2, + {SPR_NPLM, 2, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMBOMBLARGE_FLY4, 0}, //S_CYBRAKDEMONNAPALMBOMBLARGE_FLY3, + {SPR_NPLM, 3, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMBOMBLARGE_FLY1, 0}, //S_CYBRAKDEMONNAPALMBOMBLARGE_FLY4, + {SPR_NPLM, 0, 1, {A_Explode}, 0, 0, S_CYBRAKDEMONNAPALMBOMBLARGE_DIE2, 0}, //S_CYBRAKDEMONNAPALMBOMBLARGE_DIE1, // Explode + {SPR_NPLM, 0, 1, {A_NapalmScatter}, MT_CYBRAKDEMON_NAPALM_BOMB_SMALL + (6<<16), 256 + (48<<16), S_CYBRAKDEMONNAPALMBOMBLARGE_DIE3, 0}, //S_CYBRAKDEMONNAPALMBOMBLARGE_DIE2, // Outer ring + {SPR_NPLM, 0, 1, {A_NapalmScatter}, MT_CYBRAKDEMON_NAPALM_BOMB_SMALL + (1<<16), 32<<16, S_CYBRAKDEMONNAPALMBOMBLARGE_DIE4, 0}, //S_CYBRAKDEMONNAPALMBOMBLARGE_DIE3, // Center + {SPR_NULL, 0, 81, {A_Scream}, 0, 0, S_NULL, 0}, //S_CYBRAKDEMONNAPALMBOMBLARGE_DIE4, // Sound + + {SPR_MNPL, 0, 1, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMBOMBSMALL, 0}, //S_CYBRAKDEMONNAPALMBOMBSMALL, + {SPR_MNPL, 0, 1, {A_Explode}, 0, 0, S_CYBRAKDEMONNAPALMBOMBSMALL_DIE2, 0}, //S_CYBRAKDEMONNAPALMBOMBSMALL_DIE1, // Explode + {SPR_MNPL, 0, 1, {A_NapalmScatter}, MT_CYBRAKDEMON_NAPALM_FLAMES + (12<<16), 128 + (40<<16), S_CYBRAKDEMONNAPALMBOMBSMALL_DIE3, 0}, //S_CYBRAKDEMONNAPALMBOMBSMALL_DIE2, // Outer ring + {SPR_MNPL, 0, 1, {A_NapalmScatter}, MT_CYBRAKDEMON_NAPALM_FLAMES + (8<<16), 64 + (32<<16), S_CYBRAKDEMONNAPALMBOMBSMALL_DIE4, 0}, //S_CYBRAKDEMONNAPALMBOMBSMALL_DIE3, // Inner ring + {SPR_MNPL, 0, 1, {A_NapalmScatter}, MT_CYBRAKDEMON_NAPALM_FLAMES + (1<<16), 24<<16, S_CYBRAKDEMONNAPALMBOMBSMALL_DIE5, 0}, //S_CYBRAKDEMONNAPALMBOMBSMALL_DIE4, // Center + {SPR_NULL, 0, 24, {A_Scream}, 0, 0, S_NULL, 0}, //S_CYBRAKDEMONNAPALMBOMBSMALL_DIE5, // Sound + + {SPR_SFLM, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY2, 0}, //S_CYBRAKDEMONNAPALMFLAME_FLY1, + {SPR_SFLM, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY3, 0}, //S_CYBRAKDEMONNAPALMFLAME_FLY2, + {SPR_SFLM, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY4, 0}, //S_CYBRAKDEMONNAPALMFLAME_FLY3, + {SPR_SFLM, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY5, 0}, //S_CYBRAKDEMONNAPALMFLAME_FLY4, + {SPR_SFLM, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY6, 0}, //S_CYBRAKDEMONNAPALMFLAME_FLY5, + {SPR_SFLM, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY1, 0}, //S_CYBRAKDEMONNAPALMFLAME_FLY6, + {SPR_SFLM, FF_FULLBRIGHT, 0, {A_SpawnObjectRelative}, 0, MT_CYBRAKDEMON_FLAMEREST, S_NULL, 0}, //S_CYBRAKDEMONNAPALMFLAME_DIE, + + {SPR_NULL, 0, 1, {A_SetFuse}, TICRATE, 0, S_CYBRAKDEMONVILEEXPLOSION2, 0}, //S_CYBRAKDEMONVILEEXPLOSION1, + {SPR_NULL, 0, 0, {A_ScoreRise}, 0, 0, S_CYBRAKDEMONVILEEXPLOSION3, 0}, //S_CYBRAKDEMONVILEEXPLOSION2, + {SPR_NULL, 0, 1, {A_BossScream}, 0, 0, S_CYBRAKDEMONVILEEXPLOSION1, 0}, //S_CYBRAKDEMONVILEEXPLOSION3, // Metal Sonic - {SPR_PLAY, SPR2_STND, -1, {NULL}, 0, 0, S_METALSONIC_RACE}, // S_METALSONIC_RACE - - {SPR_METL, 4, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_FLOAT - {SPR_METL, 16|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR - {SPR_METL, 15, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN - {SPR_METL, 17, 20, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE - {SPR_METL, 18, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_GATHER - {SPR_METL, 6|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 1, 2, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH - {SPR_METL, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 1, 2, S_METALSONIC_FLOAT}, // S_METALSONIC_BOUNCE - {SPR_METL, 14, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_BADBOUNCE - {SPR_METL, 17, -1, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_SHOOT - {SPR_METL, 15, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_PAIN - {SPR_METL, 17, 2, {A_Fall}, 0, 0, S_METALSONIC_DEATH2},// S_METALSONIC_DEATH1 - {SPR_METL, 17, 4, {A_BossScream}, 0, 0, S_METALSONIC_DEATH3},// S_METALSONIC_DEATH2 - {SPR_METL, 17, 0, {A_Repeat}, 17, S_METALSONIC_DEATH2, S_METALSONIC_DEATH4}, // S_METALSONIC_DEATH3 - {SPR_METL, 17, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH4 - {SPR_METL, 15, 1, {A_BossScream}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1 - {SPR_METL, 15, 7, {NULL}, 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE2 - - {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|FF_ANIMATE, -1, {NULL}, 11, 1, S_NULL}, // S_MSSHIELD_F1 - {SPR_MSCF, FF_FULLBRIGHT|FF_ANIMATE|12, -1, {NULL}, 8, 2, S_NULL}, // S_MSSHIELD_F2 + {SPR_PLAY, SPR2_STND, -1, {NULL}, 0, 0, S_METALSONIC_RACE, 0}, // S_METALSONIC_RACE + + {SPR_PLAY, SPR2_WALK, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT, 0}, // S_METALSONIC_FLOAT + {SPR_PLAY, SPR2_MSC1|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_METALSONIC_STUN, 0}, // S_METALSONIC_VECTOR + {SPR_PLAY, SPR2_MSC0, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT, 0},// S_METALSONIC_STUN + {SPR_PLAY, SPR2_SPNG, 20, {NULL}, 0, 0, S_METALSONIC_GATHER, 0}, // S_METALSONIC_RAISE + {SPR_PLAY, SPR2_MSC2, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT, 0}, // S_METALSONIC_GATHER + {SPR_PLAY, SPR2_DASH|FF_FULLBRIGHT, -1, {NULL}, 1, 2, S_METALSONIC_BOUNCE, 0}, // S_METALSONIC_DASH + {SPR_PLAY, SPR2_MSC2|FF_FULLBRIGHT, -1, {NULL}, 1, 2, S_METALSONIC_FLOAT, 0}, // S_METALSONIC_BOUNCE + {SPR_PLAY, SPR2_PAIN, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT, 0}, // S_METALSONIC_BADBOUNCE + {SPR_PLAY, SPR2_SPNG, -1, {NULL}, 0, 0, S_METALSONIC_GATHER, 0}, // S_METALSONIC_SHOOT + {SPR_PLAY, SPR2_FLT, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT, 0}, // S_METALSONIC_PAIN + {SPR_PLAY, SPR2_SPNG, 2, {A_Fall}, 0, 0, S_METALSONIC_DEATH2, 0}, // S_METALSONIC_DEATH1 + {SPR_PLAY, SPR2_SPNG, 4, {A_BossScream}, 0, 0, S_METALSONIC_DEATH3, 0}, // S_METALSONIC_DEATH2 + {SPR_PLAY, SPR2_SPNG, 0, {A_Repeat}, 17, S_METALSONIC_DEATH2, S_METALSONIC_DEATH4, 0}, // S_METALSONIC_DEATH3 + {SPR_PLAY, SPR2_SPNG, -1, {A_BossDeath}, 0, 0, S_NULL, 0}, // S_METALSONIC_DEATH4 + {SPR_PLAY, SPR2_FLT, 1, {A_BossScream}, 0, 0, S_METALSONIC_FLEE2, 0}, // S_METALSONIC_FLEE1 + {SPR_PLAY, SPR2_FLT, 7, {NULL}, 0, 0, S_METALSONIC_FLEE1, 0}, // S_METALSONIC_FLEE2 + + {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|FF_ANIMATE, -1, {NULL}, 11, 1, S_NULL, 0}, // S_MSSHIELD_F1 + {SPR_MSCF, FF_FULLBRIGHT|FF_ANIMATE|12, -1, {NULL}, 8, 2, S_NULL, 0}, // S_MSSHIELD_F2 // Ring - {SPR_RING, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 23, 1, S_RING}, // S_RING + {SPR_RING, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 23, 1, S_RING, 0}, // S_RING // Blue Sphere for special stages - {SPR_SPHR, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_BLUESPHERE - {SPR_SPHR, FF_FULLBRIGHT + {SPR_SPHR, FF_SEMIBRIGHT, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BLUESPHERE + {SPR_SPHR, FF_SEMIBRIGHT #ifdef MANIASPHERES |FF_ANIMATE|FF_RANDOMANIM #endif - , -1, {NULL}, 1, 4, S_NULL}, // S_BLUESPHEREBONUS - {SPR_SPHR, 0, 20, {NULL}, 0, 0, S_NULL}, // S_BLUESPHERESPARK + , -1, {NULL}, 1, 4, S_NULL, 0}, // S_BLUESPHEREBONUS + {SPR_SPHR, 0, 20, {NULL}, 0, 0, S_NULL, 0}, // S_BLUESPHERESPARK // Bomb Sphere - {SPR_SPHR, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_BOMBSPHERE2}, // S_BOMBSPHERE1 - {SPR_SPHR, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_BOMBSPHERE3}, // S_BOMBSPHERE2 - {SPR_SPHR, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_BOMBSPHERE4}, // S_BOMBSPHERE3 - {SPR_SPHR, FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_BOMBSPHERE1}, // S_BOMBSPHERE4 + {SPR_SPHR, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_BOMBSPHERE2, 0}, // S_BOMBSPHERE1 + {SPR_SPHR, FF_SEMIBRIGHT|4, 1, {NULL}, 0, 0, S_BOMBSPHERE3, 0}, // S_BOMBSPHERE2 + {SPR_SPHR, FF_SEMIBRIGHT|5, 2, {NULL}, 0, 0, S_BOMBSPHERE4, 0}, // S_BOMBSPHERE3 + {SPR_SPHR, FF_SEMIBRIGHT|4, 1, {NULL}, 0, 0, S_BOMBSPHERE1, 0}, // S_BOMBSPHERE4 // NiGHTS Chip - {SPR_NCHP, FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 15, 2, S_NULL}, // S_NIGHTSCHIP - {SPR_NCHP, FF_FULLBRIGHT|FF_ANIMATE|16, -1, {NULL}, 15, 2, S_NULL}, // S_NIGHTSCHIPBONUS + {SPR_NCHP, FF_SEMIBRIGHT|FF_ANIMATE, -1, {NULL}, 15, 2, S_NULL, 0}, // S_NIGHTSCHIP + {SPR_NCHP, FF_SEMIBRIGHT|FF_ANIMATE|16, -1, {NULL}, 15, 2, S_NULL, 0}, // S_NIGHTSCHIPBONUS // NiGHTS Star - {SPR_NSTR, FF_ANIMATE, -1, {NULL}, 14, 2, S_NULL}, // S_NIGHTSSTAR - {SPR_NSTR, 15, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSSTARXMAS + {SPR_NSTR, FF_ANIMATE, -1, {NULL}, 14, 2, S_NULL, 0}, // S_NIGHTSSTAR + {SPR_NSTR, 15, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSSTARXMAS // Gravity Well sprites for Egg Rock's Special Stage - {SPR_GWLG, FF_ANIMATE, -1, {NULL}, 2, 1, S_NULL}, // S_GRAVWELLGREEN - {SPR_GWLR, FF_ANIMATE, -1, {NULL}, 2, 1, S_NULL}, // S_GRAVWELLRED + {SPR_GWLG, FF_ANIMATE, -1, {NULL}, 2, 1, S_NULL, 0}, // S_GRAVWELLGREEN + {SPR_GWLR, FF_ANIMATE, -1, {NULL}, 2, 1, S_NULL, 0}, // S_GRAVWELLRED // Individual Team Rings (now with shield attracting action! =P) - {SPR_TRNG, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 23, 1, S_TEAMRING}, // S_TEAMRING + {SPR_TRNG, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 23, 1, S_TEAMRING, 0}, // S_TEAMRING // Special Stage Token - {SPR_TOKE, FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 19, 1, S_TOKEN}, // S_TOKEN + {SPR_TOKE, FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 19, 1, S_TOKEN, 0}, // S_TOKEN // CTF Flags - {SPR_RFLG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_REDFLAG - {SPR_BFLG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BLUEFLAG + {SPR_RFLG, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_REDFLAG + {SPR_BFLG, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BLUEFLAG // Emblem - {SPR_EMBM, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM1 - {SPR_EMBM, 1, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM2 - {SPR_EMBM, 2, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM3 - {SPR_EMBM, 3, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM4 - {SPR_EMBM, 4, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM5 - {SPR_EMBM, 5, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM6 - {SPR_EMBM, 6, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM7 - {SPR_EMBM, 7, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM8 - {SPR_EMBM, 8, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM9 - {SPR_EMBM, 9, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM10 - {SPR_EMBM, 10, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM11 - {SPR_EMBM, 11, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM12 - {SPR_EMBM, 12, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM13 - {SPR_EMBM, 13, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM14 - {SPR_EMBM, 14, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM15 - {SPR_EMBM, 15, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM16 - {SPR_EMBM, 16, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM17 - {SPR_EMBM, 17, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM18 - {SPR_EMBM, 18, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM19 - {SPR_EMBM, 19, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM20 - {SPR_EMBM, 20, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM21 - {SPR_EMBM, 21, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM22 - {SPR_EMBM, 22, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM23 - {SPR_EMBM, 23, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM24 - {SPR_EMBM, 24, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM25 - {SPR_EMBM, 25, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM26 + {SPR_EMBM, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM1 + {SPR_EMBM, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM2 + {SPR_EMBM, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM3 + {SPR_EMBM, 3, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM4 + {SPR_EMBM, 4, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM5 + {SPR_EMBM, 5, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM6 + {SPR_EMBM, 6, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM7 + {SPR_EMBM, 7, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM8 + {SPR_EMBM, 8, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM9 + {SPR_EMBM, 9, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM10 + {SPR_EMBM, 10, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM11 + {SPR_EMBM, 11, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM12 + {SPR_EMBM, 12, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM13 + {SPR_EMBM, 13, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM14 + {SPR_EMBM, 14, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM15 + {SPR_EMBM, 15, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM16 + {SPR_EMBM, 16, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM17 + {SPR_EMBM, 17, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM18 + {SPR_EMBM, 18, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM19 + {SPR_EMBM, 19, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM20 + {SPR_EMBM, 20, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM21 + {SPR_EMBM, 21, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM22 + {SPR_EMBM, 22, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM23 + {SPR_EMBM, 23, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM24 + {SPR_EMBM, 24, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM25 + {SPR_EMBM, 25, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EMBLEM26 // Chaos Emeralds - {SPR_CEMG, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG1 - {SPR_CEMG, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG2 - {SPR_CEMG, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG3 - {SPR_CEMG, FF_FULLBRIGHT|3, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG4 - {SPR_CEMG, FF_FULLBRIGHT|4, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG5 - {SPR_CEMG, FF_FULLBRIGHT|5, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG6 - {SPR_CEMG, FF_FULLBRIGHT|6, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG7 + {SPR_CEMG, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CEMG1 + {SPR_CEMG, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CEMG2 + {SPR_CEMG, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CEMG3 + {SPR_CEMG, FF_FULLBRIGHT|3, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CEMG4 + {SPR_CEMG, FF_FULLBRIGHT|4, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CEMG5 + {SPR_CEMG, FF_FULLBRIGHT|5, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CEMG6 + {SPR_CEMG, FF_FULLBRIGHT|6, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CEMG7 // Emerald hunt shards - {SPR_SHRD, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SHRD1 - {SPR_SHRD, 1, -1, {NULL}, 0, 0, S_NULL}, // S_SHRD2 - {SPR_SHRD, 2, -1, {NULL}, 0, 0, S_NULL}, // S_SHRD3 + {SPR_SHRD, FF_SEMIBRIGHT, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SHRD1 + {SPR_SHRD, FF_SEMIBRIGHT|1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SHRD2 + {SPR_SHRD, FF_SEMIBRIGHT|2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SHRD3 // Bubble Source - {SPR_BBLS, 0, 8, {A_BubbleSpawn}, 2048, 0, S_BUBBLES2}, // S_BUBBLES1 - {SPR_BBLS, 1, 8, {A_BubbleCheck}, 0, 0, S_BUBBLES3}, // S_BUBBLES2 - {SPR_BBLS, 2, 8, {A_BubbleSpawn}, 2048, 0, S_BUBBLES4}, // S_BUBBLES3 - {SPR_BBLS, 3, 8, {A_BubbleCheck}, 0, 0, S_BUBBLES1}, // S_BUBBLES4 + {SPR_BBLS, 0, 8, {A_BubbleSpawn}, 2048, 0, S_BUBBLES2, 0}, // S_BUBBLES1 + {SPR_BBLS, 1, 8, {A_BubbleCheck}, 0, 0, S_BUBBLES3, 0}, // S_BUBBLES2 + {SPR_BBLS, 2, 8, {A_BubbleSpawn}, 2048, 0, S_BUBBLES4, 0}, // S_BUBBLES3 + {SPR_BBLS, 3, 8, {A_BubbleCheck}, 0, 0, S_BUBBLES1, 0}, // S_BUBBLES4 // Level End Sign - {SPR_SIGN, 0, -1, {A_SignPlayer}, -3, 0, S_NULL}, // S_SIGN - {SPR_SIGN, 0, 1, {A_SignSpin}, 30, 0, S_SIGNSPIN2}, // S_SIGNSPIN1 - {SPR_SIGN, 0, 0, {A_Repeat}, 4, S_SIGNSPIN1, S_SIGNSPIN3}, // S_SIGNSPIN2 - {SPR_SIGN, 0, 0, {A_SignPlayer}, -2, 0, S_SIGNSPIN4}, // S_SIGNSPIN3 - {SPR_SIGN, 0, 1, {A_SignSpin}, 30, 0, S_SIGNSPIN5}, // S_SIGNSPIN4 - {SPR_SIGN, 0, 0, {A_Repeat}, 4, S_SIGNSPIN4, S_SIGNSPIN6}, // S_SIGNSPIN5 - {SPR_SIGN, 0, 0, {A_SignPlayer}, -3, 0, S_SIGNSPIN1}, // S_SIGNSPIN6 - {SPR_SIGN, 0, 1, {A_SignPlayer}, -1, 0, S_SIGNSLOW}, // S_SIGNPLAYER - {SPR_SIGN, 0, 1, {A_SignSpin}, 30, 0, S_SIGNSLOW}, // S_SIGNSLOW - {SPR_SIGN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SIGNSTOP - {SPR_SIGN, FF_PAPERSPRITE| 2, -1, {NULL}, 0, 0, S_NULL}, // S_SIGNBOARD - {SPR_SIGN, FF_PAPERSPRITE| 1, -1, {NULL}, 0, 29, S_NULL}, // S_EGGMANSIGN - {SPR_SIGN, FF_PAPERSPRITE|18, -1, {NULL}, 0, 29, S_NULL}, // S_CLEARSIGN + {SPR_SIGN, 0, -1, {A_SignPlayer}, -3, 0, S_NULL, 0}, // S_SIGN + {SPR_SIGN, 0, 1, {A_SignSpin}, 30, 0, S_SIGNSPIN2, 0}, // S_SIGNSPIN1 + {SPR_SIGN, 0, 0, {A_Repeat}, 4, S_SIGNSPIN1, S_SIGNSPIN3, 0}, // S_SIGNSPIN2 + {SPR_SIGN, 0, 0, {A_SignPlayer}, -2, 0, S_SIGNSPIN4, 0}, // S_SIGNSPIN3 + {SPR_SIGN, 0, 1, {A_SignSpin}, 30, 0, S_SIGNSPIN5, 0}, // S_SIGNSPIN4 + {SPR_SIGN, 0, 0, {A_Repeat}, 4, S_SIGNSPIN4, S_SIGNSPIN6, 0}, // S_SIGNSPIN5 + {SPR_SIGN, 0, 0, {A_SignPlayer}, -3, 0, S_SIGNSPIN1, 0}, // S_SIGNSPIN6 + {SPR_SIGN, 0, 1, {A_SignPlayer}, -1, 0, S_SIGNSLOW, 0}, // S_SIGNPLAYER + {SPR_SIGN, 0, 1, {A_SignSpin}, 30, 0, S_SIGNSLOW, 0}, // S_SIGNSLOW + {SPR_SIGN, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SIGNSTOP + {SPR_SIGN, FF_PAPERSPRITE| 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SIGNBOARD + {SPR_SIGN, FF_PAPERSPRITE| 1, -1, {NULL}, 0, 29, S_NULL, 0}, // S_EGGMANSIGN + {SPR_SIGN, FF_PAPERSPRITE|18, -1, {NULL}, 0, 29, S_NULL, 0}, // S_CLEARSIGN // Spike Ball - {SPR_SPIK, 0, 1, {NULL}, 0, 0, S_SPIKEBALL2}, // S_SPIKEBALL1 - {SPR_SPIK, 1, 1, {NULL}, 0, 0, S_SPIKEBALL3}, // S_SPIKEBALL2 - {SPR_SPIK, 2, 1, {NULL}, 0, 0, S_SPIKEBALL4}, // S_SPIKEBALL3 - {SPR_SPIK, 3, 1, {NULL}, 0, 0, S_SPIKEBALL5}, // S_SPIKEBALL4 - {SPR_SPIK, 4, 1, {NULL}, 0, 0, S_SPIKEBALL6}, // S_SPIKEBALL5 - {SPR_SPIK, 5, 1, {NULL}, 0, 0, S_SPIKEBALL7}, // S_SPIKEBALL6 - {SPR_SPIK, 6, 1, {NULL}, 0, 0, S_SPIKEBALL8}, // S_SPIKEBALL7 - {SPR_SPIK, 7, 1, {NULL}, 0, 0, S_SPIKEBALL1}, // S_SPIKEBALL8 + {SPR_SPIK, 0, 1, {NULL}, 0, 0, S_SPIKEBALL2, 0}, // S_SPIKEBALL1 + {SPR_SPIK, 1, 1, {NULL}, 0, 0, S_SPIKEBALL3, 0}, // S_SPIKEBALL2 + {SPR_SPIK, 2, 1, {NULL}, 0, 0, S_SPIKEBALL4, 0}, // S_SPIKEBALL3 + {SPR_SPIK, 3, 1, {NULL}, 0, 0, S_SPIKEBALL5, 0}, // S_SPIKEBALL4 + {SPR_SPIK, 4, 1, {NULL}, 0, 0, S_SPIKEBALL6, 0}, // S_SPIKEBALL5 + {SPR_SPIK, 5, 1, {NULL}, 0, 0, S_SPIKEBALL7, 0}, // S_SPIKEBALL6 + {SPR_SPIK, 6, 1, {NULL}, 0, 0, S_SPIKEBALL8, 0}, // S_SPIKEBALL7 + {SPR_SPIK, 7, 1, {NULL}, 0, 0, S_SPIKEBALL1, 0}, // S_SPIKEBALL8 // Elemental Shield's Spawn - {SPR_SFLM, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SPINFIRE2}, // S_SPINFIRE1 - {SPR_SFLM, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_SPINFIRE3}, // S_SPINFIRE2 - {SPR_SFLM, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_SPINFIRE4}, // S_SPINFIRE3 - {SPR_SFLM, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_SPINFIRE5}, // S_SPINFIRE4 - {SPR_SFLM, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_SPINFIRE6}, // S_SPINFIRE5 - {SPR_SFLM, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_SPINFIRE1}, // S_SPINFIRE6 - - {SPR_TFLM, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE2}, // S_TEAM_SPINFIRE1 - {SPR_TFLM, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE3}, // S_TEAM_SPINFIRE2 - {SPR_TFLM, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE4}, // S_TEAM_SPINFIRE3 - {SPR_TFLM, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE5}, // S_TEAM_SPINFIRE4 - {SPR_TFLM, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE6}, // S_TEAM_SPINFIRE5 - {SPR_TFLM, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE1}, // S_TEAM_SPINFIRE6 + {SPR_SFLM, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SPINFIRE2, 0}, // S_SPINFIRE1 + {SPR_SFLM, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_SPINFIRE3, 0}, // S_SPINFIRE2 + {SPR_SFLM, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_SPINFIRE4, 0}, // S_SPINFIRE3 + {SPR_SFLM, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_SPINFIRE5, 0}, // S_SPINFIRE4 + {SPR_SFLM, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_SPINFIRE6, 0}, // S_SPINFIRE5 + {SPR_SFLM, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_SPINFIRE1, 0}, // S_SPINFIRE6 + + {SPR_TFLM, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE2, 0}, // S_TEAM_SPINFIRE1 + {SPR_TFLM, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE3, 0}, // S_TEAM_SPINFIRE2 + {SPR_TFLM, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE4, 0}, // S_TEAM_SPINFIRE3 + {SPR_TFLM, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE5, 0}, // S_TEAM_SPINFIRE4 + {SPR_TFLM, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE6, 0}, // S_TEAM_SPINFIRE5 + {SPR_TFLM, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_TEAM_SPINFIRE1, 0}, // S_TEAM_SPINFIRE6 // Floor Spike - {SPR_USPK, 0,-1, {A_SpikeRetract}, 1, 0, S_SPIKE2}, // S_SPIKE1 -- Fully extended - {SPR_USPK, 1, 2, {A_Pain}, 0, 0, S_SPIKE3}, // S_SPIKE2 - {SPR_USPK, 2, 2, {NULL}, 0, 0, S_SPIKE4}, // S_SPIKE3 - {SPR_USPK, 3,-1, {A_SpikeRetract}, 0, 0, S_SPIKE5}, // S_SPIKE4 -- Fully retracted - {SPR_USPK, 2, 2, {A_Pain}, 0, 0, S_SPIKE6}, // S_SPIKE5 - {SPR_USPK, 1, 2, {NULL}, 0, 0, S_SPIKE1}, // S_SPIKE6 - {SPR_USPK, 4,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED1 -- Busted spike particles - {SPR_USPK, 5,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED2 + {SPR_USPK, 0,-1, {A_SpikeRetract}, 1, 0, S_SPIKE2, 0}, // S_SPIKE1 -- Fully extended + {SPR_USPK, 1, 2, {A_Pain}, 0, 0, S_SPIKE3, 0}, // S_SPIKE2 + {SPR_USPK, 2, 2, {NULL}, 0, 0, S_SPIKE4, 0}, // S_SPIKE3 + {SPR_USPK, 3,-1, {A_SpikeRetract}, 0, 0, S_SPIKE5, 0}, // S_SPIKE4 -- Fully retracted + {SPR_USPK, 2, 2, {A_Pain}, 0, 0, S_SPIKE6, 0}, // S_SPIKE5 + {SPR_USPK, 1, 2, {NULL}, 0, 0, S_SPIKE1, 0}, // S_SPIKE6 + {SPR_USPK, 4,-1, {NULL}, 0, 0, S_NULL, 0}, // S_SPIKED1 -- Busted spike particles + {SPR_USPK, 5,-1, {NULL}, 0, 0, S_NULL, 0}, // S_SPIKED2 // Wall Spike - {SPR_WSPK, 0|FF_PAPERSPRITE,-1, {A_SpikeRetract}, 1, 0, S_WALLSPIKE2}, // S_WALLSPIKE1 -- Fully extended - {SPR_WSPK, 1|FF_PAPERSPRITE, 2, {A_Pain}, 0, 0, S_WALLSPIKE3}, // S_WALLSPIKE2 - {SPR_WSPK, 2|FF_PAPERSPRITE, 2, {NULL}, 0, 0, S_WALLSPIKE4}, // S_WALLSPIKE3 - {SPR_WSPK, 3|FF_PAPERSPRITE,-1, {A_SpikeRetract}, 0, 0, S_WALLSPIKE5}, // S_WALLSPIKE4 -- Fully retracted - {SPR_WSPK, 2|FF_PAPERSPRITE, 2, {A_Pain}, 0, 0, S_WALLSPIKE6}, // S_WALLSPIKE5 - {SPR_WSPK, 1|FF_PAPERSPRITE, 2, {NULL}, 0, 0, S_WALLSPIKE1}, // S_WALLSPIKE6 - {SPR_WSPB, 0|FF_PAPERSPRITE,-1, {NULL}, 0, 0, S_NULL}, // S_WALLSPIKEBASE -- Base - {SPR_WSPK, 4,-1, {NULL}, 0, 0, S_NULL}, // S_WALLSPIKED1 -- Busted spike particles - {SPR_WSPK, 5,-1, {NULL}, 0, 0, S_NULL}, // S_WALLSPIKED2 + {SPR_WSPK, 0|FF_PAPERSPRITE,-1, {A_SpikeRetract}, 1, 0, S_WALLSPIKE2, 0}, // S_WALLSPIKE1 -- Fully extended + {SPR_WSPK, 1|FF_PAPERSPRITE, 2, {A_Pain}, 0, 0, S_WALLSPIKE3, 0}, // S_WALLSPIKE2 + {SPR_WSPK, 2|FF_PAPERSPRITE, 2, {NULL}, 0, 0, S_WALLSPIKE4, 0}, // S_WALLSPIKE3 + {SPR_WSPK, 3|FF_PAPERSPRITE,-1, {A_SpikeRetract}, 0, 0, S_WALLSPIKE5, 0}, // S_WALLSPIKE4 -- Fully retracted + {SPR_WSPK, 2|FF_PAPERSPRITE, 2, {A_Pain}, 0, 0, S_WALLSPIKE6, 0}, // S_WALLSPIKE5 + {SPR_WSPK, 1|FF_PAPERSPRITE, 2, {NULL}, 0, 0, S_WALLSPIKE1, 0}, // S_WALLSPIKE6 + {SPR_WSPB, 0|FF_PAPERSPRITE,-1, {NULL}, 0, 0, S_NULL, 0}, // S_WALLSPIKEBASE -- Base + {SPR_WSPK, 4,-1, {NULL}, 0, 0, S_NULL, 0}, // S_WALLSPIKED1 -- Busted spike particles + {SPR_WSPK, 5,-1, {NULL}, 0, 0, S_NULL, 0}, // S_WALLSPIKED2 // Starpost - {SPR_STPT, 0 , -1, {NULL}, 0, 0, S_NULL}, // S_STARPOST_IDLE - {SPR_STPT, FF_ANIMATE|17, -1, {NULL}, 5, 1, S_NULL}, // S_STARPOST_FLASH - {SPR_STPT, FF_ANIMATE|13, 2, {NULL}, 1, 1, S_STARPOST_SPIN}, // S_STARPOST_STARTSPIN - {SPR_STPT, FF_ANIMATE|1 , 23, {NULL}, 11, 1, S_STARPOST_ENDSPIN}, // S_STARPOST_SPIN - {SPR_STPT, FF_ANIMATE|15, 2, {NULL}, 1, 1, S_STARPOST_FLASH}, // S_STARPOST_ENDSPIN + {SPR_STPT, 0 , -1, {NULL}, 0, 0, S_NULL, 0}, // S_STARPOST_IDLE + {SPR_STPT, FF_ANIMATE|17, -1, {NULL}, 5, 1, S_NULL, 0}, // S_STARPOST_FLASH + {SPR_STPT, FF_ANIMATE|13, 2, {NULL}, 1, 1, S_STARPOST_SPIN, 0}, // S_STARPOST_STARTSPIN + {SPR_STPT, FF_ANIMATE|1 , 23, {NULL}, 11, 1, S_STARPOST_ENDSPIN, 0}, // S_STARPOST_SPIN + {SPR_STPT, FF_ANIMATE|15, 2, {NULL}, 1, 1, S_STARPOST_FLASH, 0}, // S_STARPOST_ENDSPIN // Big floating mine - {SPR_BMNE, 0, 2, {A_Look}, ((224<<FRACBITS)|1), 0, S_BIGMINE_IDLE}, // S_BIGMINE_IDLE - {SPR_BMNE, 1, 2, {A_MineRange}, 112, 0, S_BIGMINE_ALERT2}, // S_BIGMINE_ALERT1 - {SPR_BMNE, 2, 2, {A_MineRange}, 112, 0, S_BIGMINE_ALERT3}, // S_BIGMINE_ALERT2 - {SPR_BMNE, 0, 1, {A_Look}, ((224<<FRACBITS)|1), 1, S_BIGMINE_IDLE}, // S_BIGMINE_ALERT3 - {SPR_BMNE, 3, 25, {A_Pain}, 0, 0, S_BIGMINE_SET2}, // S_BIGMINE_SET1 - {SPR_BMNE, 3, 10, {A_SetObjectFlags}, MF_SHOOTABLE, 1, S_BIGMINE_SET3}, // S_BIGMINE_SET1 - {SPR_BMNE, 3, 1, {A_MineExplode}, 0, 0, S_BIGMINE_BLAST1}, // S_BIGMINE_SET3 - {SPR_BMNB, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_BIGMINE_BLAST2}, // S_BIGMINE_BLAST1 - {SPR_BMNB, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_BIGMINE_BLAST3}, // S_BIGMINE_BLAST2 - {SPR_BMNB, 2|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_BIGMINE_BLAST4}, // S_BIGMINE_BLAST3 - {SPR_BMNB, 3|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_BIGMINE_BLAST5}, // S_BIGMINE_BLAST4 - {SPR_NULL, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BIGMINE_BLAST5 + {SPR_BMNE, 0, 2, {A_Look}, ((224<<FRACBITS)|1), 0, S_BIGMINE_IDLE, 0}, // S_BIGMINE_IDLE + {SPR_BMNE, 1, 2, {A_MineRange}, 112, 0, S_BIGMINE_ALERT2, 0}, // S_BIGMINE_ALERT1 + {SPR_BMNE, 2, 2, {A_MineRange}, 112, 0, S_BIGMINE_ALERT3, 0}, // S_BIGMINE_ALERT2 + {SPR_BMNE, 0, 1, {A_Look}, ((224<<FRACBITS)|1), 1, S_BIGMINE_IDLE, 0}, // S_BIGMINE_ALERT3 + {SPR_BMNE, 3, 25, {A_Pain}, 0, 0, S_BIGMINE_SET2, 0}, // S_BIGMINE_SET1 + {SPR_BMNE, 3, 10, {A_SetObjectFlags}, MF_SHOOTABLE, 1, S_BIGMINE_SET3, 0}, // S_BIGMINE_SET1 + {SPR_BMNE, 3, 1, {A_MineExplode}, 0, 0, S_BIGMINE_BLAST1, 0}, // S_BIGMINE_SET3 + {SPR_BMNB, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_BIGMINE_BLAST2, 0}, // S_BIGMINE_BLAST1 + {SPR_BMNB, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_BIGMINE_BLAST3, 0}, // S_BIGMINE_BLAST2 + {SPR_BMNB, 2|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_BIGMINE_BLAST4, 0}, // S_BIGMINE_BLAST3 + {SPR_BMNB, 3|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_BIGMINE_BLAST5, 0}, // S_BIGMINE_BLAST4 + {SPR_NULL, 0, 35, {NULL}, 0, 0, S_NULL, 0}, // S_BIGMINE_BLAST5 // Cannon launcher - {SPR_NULL, 0, 1, {A_FindTarget}, MT_PLAYER, 0, S_CANNONLAUNCHER2}, // S_CANNONLAUNCHER1 - {SPR_NULL, 0, 1, {A_LobShot}, MT_CANNONBALL, 4*TICRATE, S_CANNONLAUNCHER3}, // S_CANNONLAUNCHER2 - {SPR_NULL, 0, 2, {A_SetRandomTics}, TICRATE/2, 3*TICRATE, S_CANNONLAUNCHER1}, // S_CANNONLAUNCHER3 + {SPR_NULL, 0, 1, {A_FindTarget}, MT_PLAYER, 0, S_CANNONLAUNCHER2, 0}, // S_CANNONLAUNCHER1 + {SPR_NULL, 0, 1, {A_LobShot}, MT_CANNONBALL, 4*TICRATE, S_CANNONLAUNCHER3, 0}, // S_CANNONLAUNCHER2 + {SPR_NULL, 0, 2, {A_SetRandomTics}, TICRATE/2, 3*TICRATE, S_CANNONLAUNCHER1, 0}, // S_CANNONLAUNCHER3 // Monitor Miscellany - {SPR_NSPK, 0, 16, {NULL}, 0, 0, S_BOXSPARKLE2}, // S_BOXSPARKLE1 - {SPR_NSPK, 1, 12, {NULL}, 0, 0, S_BOXSPARKLE3}, // S_BOXSPARKLE2 - {SPR_NSPK, 2, 8, {NULL}, 0, 0, S_BOXSPARKLE4}, // S_BOXSPARKLE3 - {SPR_NSPK, 3, 4, {NULL}, 0, 0, S_NULL}, // S_BOXSPARKLE4 - - {SPR_MSTV, 0, 1, {NULL}, 0, 0, S_SPAWNSTATE}, // S_BOX_FLICKER - {SPR_MSTV, 0, 4, {A_MonitorPop}, 0, 0, S_BOX_POP2}, // S_BOX_POP1 - {SPR_MSTV, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BOX_POP2 - - {SPR_XLTV, 0, 1, {NULL}, 0, 0, S_SPAWNSTATE}, // S_GOLDBOX_FLICKER - {SPR_XLTV, 1, 89, {A_GoldMonitorPop}, 0, 0, S_GOLDBOX_OFF2}, // S_GOLDBOX_OFF1 - {SPR_XLTV, 2, 4, {A_PlayAttackSound}, 0, 0, S_GOLDBOX_OFF3}, // S_GOLDBOX_OFF2 - {SPR_XLTV, 3, 4, {NULL}, 0, 0, S_GOLDBOX_OFF4}, // S_GOLDBOX_OFF3 - {SPR_XLTV, 4, 4, {NULL}, 0, 0, S_GOLDBOX_OFF5}, // S_GOLDBOX_OFF4 - {SPR_XLTV, 5, 2, {NULL}, 0, 0, S_GOLDBOX_OFF6}, // S_GOLDBOX_OFF5 - {SPR_XLTV, 6, 2, {NULL}, 0, 0, S_GOLDBOX_OFF7}, // S_GOLDBOX_OFF6 - {SPR_XLTV, 6, 0, {A_GoldMonitorRestore}, 0, 0, S_SPAWNSTATE}, // S_GOLDBOX_OFF7 + {SPR_NSPK, 0, 16, {NULL}, 0, 0, S_BOXSPARKLE2, 0}, // S_BOXSPARKLE1 + {SPR_NSPK, 1, 12, {NULL}, 0, 0, S_BOXSPARKLE3, 0}, // S_BOXSPARKLE2 + {SPR_NSPK, 2, 8, {NULL}, 0, 0, S_BOXSPARKLE4, 0}, // S_BOXSPARKLE3 + {SPR_NSPK, 3, 4, {NULL}, 0, 0, S_NULL, 0}, // S_BOXSPARKLE4 + + {SPR_MSTV, 0, 1, {NULL}, 0, 0, S_SPAWNSTATE, 0}, // S_BOX_FLICKER + {SPR_MSTV, 0, 4, {A_MonitorPop}, 0, 0, S_BOX_POP2, 0}, // S_BOX_POP1 + {SPR_MSTV, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BOX_POP2 + + {SPR_XLTV, 0, 1, {NULL}, 0, 0, S_SPAWNSTATE, 0}, // S_GOLDBOX_FLICKER + {SPR_XLTV, 1, 89, {A_GoldMonitorPop}, 0, 0, S_GOLDBOX_OFF2, 0}, // S_GOLDBOX_OFF1 + {SPR_XLTV, 2, 4, {A_PlayAttackSound}, 0, 0, S_GOLDBOX_OFF3, 0}, // S_GOLDBOX_OFF2 + {SPR_XLTV, 3, 4, {NULL}, 0, 0, S_GOLDBOX_OFF4, 0}, // S_GOLDBOX_OFF3 + {SPR_XLTV, 4, 4, {NULL}, 0, 0, S_GOLDBOX_OFF5, 0}, // S_GOLDBOX_OFF4 + {SPR_XLTV, 5, 2, {NULL}, 0, 0, S_GOLDBOX_OFF6, 0}, // S_GOLDBOX_OFF5 + {SPR_XLTV, 6, 2, {NULL}, 0, 0, S_GOLDBOX_OFF7, 0}, // S_GOLDBOX_OFF6 + {SPR_XLTV, 6, 0, {A_GoldMonitorRestore}, 0, 0, S_SPAWNSTATE, 0}, // S_GOLDBOX_OFF7 // Monitor States (one per box) - {SPR_TVMY, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_MYSTERY_BOX - {SPR_TVRI, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_RING_BOX - {SPR_TVPI, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_PITY_BOX - {SPR_TVAT, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_ATTRACT_BOX - {SPR_TVFO, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_FORCE_BOX - {SPR_TVAR, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_ARMAGEDDON_BOX - {SPR_TVWW, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_WHIRLWIND_BOX - {SPR_TVEL, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_ELEMENTAL_BOX - {SPR_TVSS, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_SNEAKERS_BOX - {SPR_TVIV, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_INVULN_BOX - {SPR_TV1U, 0, 2, {A_1upThinker}, 0, 0, S_BOX_FLICKER}, // S_1UP_BOX - {SPR_TVEG, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_EGGMAN_BOX - {SPR_TVMX, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_MIXUP_BOX - {SPR_TVGV, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_GRAVITY_BOX - {SPR_TVRC, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_RECYCLER_BOX - {SPR_TV1K, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_SCORE1K_BOX - {SPR_TVTK, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_SCORE10K_BOX - {SPR_TVFL, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_FLAMEAURA_BOX - {SPR_TVBB, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_BUBBLEWRAP_BOX - {SPR_TVZP, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_THUNDERCOIN_BOX + {SPR_TVMY, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER, 0}, // S_MYSTERY_BOX + {SPR_TVRI, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER, 0}, // S_RING_BOX + {SPR_TVPI, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER, 0}, // S_PITY_BOX + {SPR_TVAT, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER, 0}, // S_ATTRACT_BOX + {SPR_TVFO, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER, 0}, // S_FORCE_BOX + {SPR_TVAR, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER, 0}, // S_ARMAGEDDON_BOX + {SPR_TVWW, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER, 0}, // S_WHIRLWIND_BOX + {SPR_TVEL, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER, 0}, // S_ELEMENTAL_BOX + {SPR_TVSS, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER, 0}, // S_SNEAKERS_BOX + {SPR_TVIV, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER, 0}, // S_INVULN_BOX + {SPR_TV1U, 0, 2, {A_1upThinker}, 0, 0, S_BOX_FLICKER, 0}, // S_1UP_BOX + {SPR_TVEG, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER, 0}, // S_EGGMAN_BOX + {SPR_TVMX, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER, 0}, // S_MIXUP_BOX + {SPR_TVGV, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER, 0}, // S_GRAVITY_BOX + {SPR_TVRC, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER, 0}, // S_RECYCLER_BOX + {SPR_TV1K, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER, 0}, // S_SCORE1K_BOX + {SPR_TVTK, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER, 0}, // S_SCORE10K_BOX + {SPR_TVFL, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER, 0}, // S_FLAMEAURA_BOX + {SPR_TVBB, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER, 0}, // S_BUBBLEWRAP_BOX + {SPR_TVZP, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER, 0}, // S_THUNDERCOIN_BOX // Gold Repeat Monitor States (one per box) - {SPR_TVPI, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_PITY_GOLDBOX - {SPR_TVAT, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_ATTRACT_GOLDBOX - {SPR_TVFO, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_FORCE_GOLDBOX - {SPR_TVAR, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_ARMAGEDDON_GOLDBOX - {SPR_TVWW, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_WHIRLWIND_GOLDBOX - {SPR_TVEL, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_ELEMENTAL_GOLDBOX - {SPR_TVSS, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_SNEAKERS_GOLDBOX - {SPR_TVIV, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_INVULN_GOLDBOX - {SPR_TVEG, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_EGGMAN_GOLDBOX - {SPR_TVGV, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_GRAVITY_GOLDBOX - {SPR_TVFL, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_FLAMEAURA_GOLDBOX - {SPR_TVBB, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_BUBBLEWRAP_GOLDBOX - {SPR_TVZP, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_THUNDERCOIN_GOLDBOX + {SPR_TVPI, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER, 0}, // S_PITY_GOLDBOX + {SPR_TVAT, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER, 0}, // S_ATTRACT_GOLDBOX + {SPR_TVFO, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER, 0}, // S_FORCE_GOLDBOX + {SPR_TVAR, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER, 0}, // S_ARMAGEDDON_GOLDBOX + {SPR_TVWW, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER, 0}, // S_WHIRLWIND_GOLDBOX + {SPR_TVEL, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER, 0}, // S_ELEMENTAL_GOLDBOX + {SPR_TVSS, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER, 0}, // S_SNEAKERS_GOLDBOX + {SPR_TVIV, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER, 0}, // S_INVULN_GOLDBOX + {SPR_TVEG, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER, 0}, // S_EGGMAN_GOLDBOX + {SPR_TVGV, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER, 0}, // S_GRAVITY_GOLDBOX + {SPR_TVFL, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER, 0}, // S_FLAMEAURA_GOLDBOX + {SPR_TVBB, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER, 0}, // S_BUBBLEWRAP_GOLDBOX + {SPR_TVZP, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER, 0}, // S_THUNDERCOIN_GOLDBOX // Team Ring Boxes (these are special) - {SPR_TRRI, 0, 2, {NULL}, 0, 0, S_RING_REDBOX2}, // S_RING_REDBOX1 - {SPR_TRRI, 1, 1, {NULL}, 0, 0, S_RING_REDBOX1}, // S_RING_REDBOX2 - {SPR_TRRI, 1, 4, {A_MonitorPop}, 0, 0, S_REDBOX_POP2}, // S_REDBOX_POP1 - {SPR_TRRI, 2, -1, {NULL}, 0, 0, S_NULL}, // S_REDBOX_POP2 + {SPR_TRRI, 0, 2, {NULL}, 0, 0, S_RING_REDBOX2, 0}, // S_RING_REDBOX1 + {SPR_TRRI, 1, 1, {NULL}, 0, 0, S_RING_REDBOX1, 0}, // S_RING_REDBOX2 + {SPR_TRRI, 1, 4, {A_MonitorPop}, 0, 0, S_REDBOX_POP2, 0}, // S_REDBOX_POP1 + {SPR_TRRI, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_REDBOX_POP2 - {SPR_TBRI, 0, 2, {NULL}, 0, 0, S_RING_BLUEBOX2}, // S_RING_BLUEBOX1 - {SPR_TBRI, 1, 1, {NULL}, 0, 0, S_RING_BLUEBOX1}, // S_RING_BLUEBOX2 - {SPR_TBRI, 1, 4, {A_MonitorPop}, 0, 0, S_BLUEBOX_POP2}, // S_BLUEBOX_POP1 - {SPR_TBRI, 2, -1, {NULL}, 0, 0, S_NULL}, // S_BLUEBOX_POP2 + {SPR_TBRI, 0, 2, {NULL}, 0, 0, S_RING_BLUEBOX2, 0}, // S_RING_BLUEBOX1 + {SPR_TBRI, 1, 1, {NULL}, 0, 0, S_RING_BLUEBOX1, 0}, // S_RING_BLUEBOX2 + {SPR_TBRI, 1, 4, {A_MonitorPop}, 0, 0, S_BLUEBOX_POP2, 0}, // S_BLUEBOX_POP1 + {SPR_TBRI, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BLUEBOX_POP2 // Box Icons -- 2 states each, animation and action - {SPR_TVRI, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_RING_ICON2}, // S_RING_ICON1 - {SPR_TVRI, 2, 18, {A_RingBox}, 0, 0, S_NULL}, // S_RING_ICON2 + {SPR_TVRI, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_RING_ICON2, 0}, // S_RING_ICON1 + {SPR_TVRI, 2, 18, {A_RingBox}, 0, 0, S_NULL, 0}, // S_RING_ICON2 - {SPR_TVPI, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_PITY_ICON2}, // S_PITY_ICON1 - {SPR_TVPI, 2, 18, {A_GiveShield}, SH_PITY, 0, S_NULL}, // S_PITY_ICON2 + {SPR_TVPI, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_PITY_ICON2, 0}, // S_PITY_ICON1 + {SPR_TVPI, 2, 18, {A_GiveShield}, SH_PITY, 0, S_NULL, 0}, // S_PITY_ICON2 - {SPR_TVAT, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_ATTRACT_ICON2}, // S_ATTRACT_ICON1 - {SPR_TVAT, 2, 18, {A_GiveShield}, SH_ATTRACT, 0, S_NULL}, // S_ATTRACT_ICON2 + {SPR_TVAT, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_ATTRACT_ICON2, 0}, // S_ATTRACT_ICON1 + {SPR_TVAT, 2, 18, {A_GiveShield}, SH_ATTRACT, 0, S_NULL, 0}, // S_ATTRACT_ICON2 - {SPR_TVFO, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_FORCE_ICON2}, // S_FORCE_ICON1 - {SPR_TVFO, 2, 18, {A_GiveShield}, SH_FORCE|1, 0, S_NULL}, // S_FORCE_ICON2 + {SPR_TVFO, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_FORCE_ICON2, 0}, // S_FORCE_ICON1 + {SPR_TVFO, 2, 18, {A_GiveShield}, SH_FORCE|1, 0, S_NULL, 0}, // S_FORCE_ICON2 - {SPR_TVAR, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_ARMAGEDDON_ICON2}, // S_ARMAGEDDON_ICON1 - {SPR_TVAR, 2, 18, {A_GiveShield}, SH_ARMAGEDDON, 0, S_NULL}, // S_ARMAGEDDON_ICON2 + {SPR_TVAR, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_ARMAGEDDON_ICON2, 0}, // S_ARMAGEDDON_ICON1 + {SPR_TVAR, 2, 18, {A_GiveShield}, SH_ARMAGEDDON, 0, S_NULL, 0}, // S_ARMAGEDDON_ICON2 - {SPR_TVWW, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_WHIRLWIND_ICON2}, // S_WHIRLWIND_ICON1 - {SPR_TVWW, 2, 18, {A_GiveShield}, SH_WHIRLWIND, 0, S_NULL}, // S_WHIRLWIND_ICON2 + {SPR_TVWW, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_WHIRLWIND_ICON2, 0}, // S_WHIRLWIND_ICON1 + {SPR_TVWW, 2, 18, {A_GiveShield}, SH_WHIRLWIND, 0, S_NULL, 0}, // S_WHIRLWIND_ICON2 - {SPR_TVEL, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_ELEMENTAL_ICON2}, // S_ELEMENTAL_ICON1 - {SPR_TVEL, 2, 18, {A_GiveShield}, SH_ELEMENTAL, 0, S_NULL}, // S_ELEMENTAL_ICON2 + {SPR_TVEL, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_ELEMENTAL_ICON2, 0}, // S_ELEMENTAL_ICON1 + {SPR_TVEL, 2, 18, {A_GiveShield}, SH_ELEMENTAL, 0, S_NULL, 0}, // S_ELEMENTAL_ICON2 - {SPR_TVSS, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_SNEAKERS_ICON2}, // S_SNEAKERS_ICON1 - {SPR_TVSS, 2, 18, {A_SuperSneakers}, 0, 0, S_NULL}, // S_SNEAKERS_ICON2 + {SPR_TVSS, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_SNEAKERS_ICON2, 0}, // S_SNEAKERS_ICON1 + {SPR_TVSS, 2, 18, {A_SuperSneakers}, 0, 0, S_NULL, 0}, // S_SNEAKERS_ICON2 - {SPR_TVIV, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_INVULN_ICON2}, // S_INVULN_ICON1 - {SPR_TVIV, 2, 18, {A_Invincibility}, 0, 0, S_NULL}, // S_INVULN_ICON2 + {SPR_TVIV, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_INVULN_ICON2, 0}, // S_INVULN_ICON1 + {SPR_TVIV, 2, 18, {A_Invincibility}, 0, 0, S_NULL, 0}, // S_INVULN_ICON2 - {SPR_TV1U, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_1UP_ICON2}, // S_1UP_ICON1 - {SPR_TV1U, 2, 18, {A_ExtraLife}, 0, 0, S_NULL}, // S_1UP_ICON2 + {SPR_TV1U, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_1UP_ICON2, 0}, // S_1UP_ICON1 + {SPR_TV1U, 2, 18, {A_ExtraLife}, 0, 0, S_NULL, 0}, // S_1UP_ICON2 - {SPR_TVEG, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_EGGMAN_ICON2}, // S_EGGMAN_ICON1 - {SPR_TVEG, 2, 18, {A_EggmanBox}, 0, 0, S_NULL}, // S_EGGMAN_ICON2 + {SPR_TVEG, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_EGGMAN_ICON2, 0}, // S_EGGMAN_ICON1 + {SPR_TVEG, 2, 18, {A_EggmanBox}, 0, 0, S_NULL, 0}, // S_EGGMAN_ICON2 - {SPR_TVMX, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_MIXUP_ICON2}, // S_MIXUP_ICON1 - {SPR_TVMX, 2, 18, {A_MixUp}, 0, 0, S_NULL}, // S_MIXUP_ICON2 + {SPR_TVMX, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_MIXUP_ICON2, 0}, // S_MIXUP_ICON1 + {SPR_TVMX, 2, 18, {A_MixUp}, 0, 0, S_NULL, 0}, // S_MIXUP_ICON2 - {SPR_TVGV, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_GRAVITY_ICON2}, // S_GRAVITY_ICON1 - {SPR_TVGV, 2, 18, {A_GravityBox}, 0, 0, S_NULL}, // S_GRAVITY_ICON2 + {SPR_TVGV, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_GRAVITY_ICON2, 0}, // S_GRAVITY_ICON1 + {SPR_TVGV, 2, 18, {A_GravityBox}, 0, 0, S_NULL, 0}, // S_GRAVITY_ICON2 - {SPR_TVRC, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_RECYCLER_ICON2}, // S_RECYCLER_ICON1 - {SPR_TVRC, 2, 18, {A_RecyclePowers}, 0, 0, S_NULL}, // S_RECYCLER_ICON2 + {SPR_TVRC, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_RECYCLER_ICON2, 0}, // S_RECYCLER_ICON1 + {SPR_TVRC, 2, 18, {A_RecyclePowers}, 0, 0, S_NULL, 0}, // S_RECYCLER_ICON2 - {SPR_TV1K, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_SCORE1K_ICON2}, // S_SCORE1K_ICON1 - {SPR_TV1K, 2, 18, {A_AwardScore}, 0, 0, S_NULL}, // S_SCORE1K_ICON2 + {SPR_TV1K, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_SCORE1K_ICON2, 0}, // S_SCORE1K_ICON1 + {SPR_TV1K, 2, 18, {A_AwardScore}, 0, 0, S_NULL, 0}, // S_SCORE1K_ICON2 - {SPR_TVTK, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_SCORE10K_ICON2}, // S_SCORE10K_ICON1 - {SPR_TVTK, 2, 18, {A_AwardScore}, 0, 0, S_NULL}, // S_SCORE10K_ICON2 + {SPR_TVTK, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_SCORE10K_ICON2, 0}, // S_SCORE10K_ICON1 + {SPR_TVTK, 2, 18, {A_AwardScore}, 0, 0, S_NULL, 0}, // S_SCORE10K_ICON2 - {SPR_TVFL, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_FLAMEAURA_ICON2}, // S_FLAMEAURA_ICON1 - {SPR_TVFL, 2, 18, {A_GiveShield}, SH_FLAMEAURA, 0, S_NULL}, // S_FLAMEAURA_ICON2 + {SPR_TVFL, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_FLAMEAURA_ICON2, 0}, // S_FLAMEAURA_ICON1 + {SPR_TVFL, 2, 18, {A_GiveShield}, SH_FLAMEAURA, 0, S_NULL, 0}, // S_FLAMEAURA_ICON2 - {SPR_TVBB, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_BUBBLEWRAP_ICON2}, // S_BUBBLEWRAP_ICON1 - {SPR_TVBB, 2, 18, {A_GiveShield}, SH_BUBBLEWRAP, 0, S_NULL}, // S_BUBBLEWRAP_ICON2 + {SPR_TVBB, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_BUBBLEWRAP_ICON2, 0}, // S_BUBBLEWRAP_ICON1 + {SPR_TVBB, 2, 18, {A_GiveShield}, SH_BUBBLEWRAP, 0, S_NULL, 0}, // S_BUBBLEWRAP_ICON2 - {SPR_TVZP, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_THUNDERCOIN_ICON2}, // S_THUNDERCOIN_ICON1 - {SPR_TVZP, 2, 18, {A_GiveShield}, SH_THUNDERCOIN, 0, S_NULL}, // S_THUNDERCOIN_ICON2 + {SPR_TVZP, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_THUNDERCOIN_ICON2, 0}, // S_THUNDERCOIN_ICON1 + {SPR_TVZP, 2, 18, {A_GiveShield}, SH_THUNDERCOIN, 0, S_NULL, 0}, // S_THUNDERCOIN_ICON2 // --- - {SPR_MISL, FF_FULLBRIGHT, 1, {A_SmokeTrailer}, MT_SMOKE, 0, S_ROCKET}, // S_ROCKET + {SPR_MISL, FF_FULLBRIGHT, 1, {A_SmokeTrailer}, MT_SMOKE, 0, S_ROCKET, 0}, // S_ROCKET - {SPR_LASR, FF_FULLBRIGHT|0, 2, {NULL}, 0, 0, S_NULL}, // S_LASER - {SPR_LASR, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_NULL}, // S_LASER2 - {SPR_LASR, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_NULL}, // S_LASERFLASH + {SPR_LASR, FF_FULLBRIGHT|0, 2, {NULL}, 0, 0, S_NULL, 0}, // S_LASER + {SPR_LASR, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_NULL, 0}, // S_LASER2 + {SPR_LASR, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_NULL, 0}, // S_LASERFLASH - {SPR_LASF, FF_FULLBRIGHT|0, 2, {NULL}, 0, 0, S_LASERFLAME2}, // S_LASERFLAME1 - {SPR_LASF, FF_FULLBRIGHT|1, 1, {A_ChangeHeight}, 156*FRACUNIT, 3, S_LASERFLAME3}, // S_LASERFLAME2 - {SPR_LASF, FF_FULLBRIGHT|2, 0, {A_ChangeHeight}, 32*FRACUNIT, 3, S_LASERFLAME4}, // S_LASERFLAME3 - {SPR_LASF, FF_ANIMATE|FF_PAPERSPRITE|FF_FULLBRIGHT|2, 4, {NULL}, 1, 2, S_LASERFLAME5}, // S_LASERFLAME4 - {SPR_LASF, FF_ANIMATE|FF_PAPERSPRITE|FF_FULLBRIGHT|4, 28, {NULL}, 2, 2, S_NULL}, // S_LASERFLAME5 + {SPR_LASF, FF_FULLBRIGHT|0, 2, {NULL}, 0, 0, S_LASERFLAME2, 0}, // S_LASERFLAME1 + {SPR_LASF, FF_FULLBRIGHT|1, 1, {A_ChangeHeight}, 156*FRACUNIT, 3, S_LASERFLAME3, 0}, // S_LASERFLAME2 + {SPR_LASF, FF_FULLBRIGHT|2, 0, {A_ChangeHeight}, 32*FRACUNIT, 3, S_LASERFLAME4, 0}, // S_LASERFLAME3 + {SPR_LASF, FF_ANIMATE|FF_PAPERSPRITE|FF_FULLBRIGHT|2, 4, {NULL}, 1, 2, S_LASERFLAME5, 0}, // S_LASERFLAME4 + {SPR_LASF, FF_ANIMATE|FF_PAPERSPRITE|FF_FULLBRIGHT|4, 28, {NULL}, 2, 2, S_NULL, 0}, // S_LASERFLAME5 - {SPR_TORP, 0, 1, {A_SmokeTrailer}, MT_SMOKE, 0, S_TORPEDO}, // S_TORPEDO + {SPR_TORP, 0, 1, {A_SmokeTrailer}, MT_SMOKE, 0, S_TORPEDO, 0}, // S_TORPEDO - {SPR_ENRG, FF_FULLBRIGHT|FF_TRANS30, 1, {NULL}, 0, 0, S_ENERGYBALL2}, // S_ENERGYBALL1 - {SPR_NULL, 0, 1, {NULL}, 0, 0, S_ENERGYBALL1}, // S_ENERGYBALL2 + {SPR_ENRG, FF_FULLBRIGHT|FF_TRANS30, 1, {NULL}, 0, 0, S_ENERGYBALL2, 0}, // S_ENERGYBALL1 + {SPR_NULL, 0, 1, {NULL}, 0, 0, S_ENERGYBALL1, 0}, // S_ENERGYBALL2 // Skim Mine (also dropped by Jetty-Syn bomber) - {SPR_MINE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_MINE1 - {SPR_MINE, 1, 1, {A_Fall}, 0, 0, S_MINE_BOOM2}, // S_MINE_BOOM1 - {SPR_MINE, 2, 3, {A_Scream}, 0, 0, S_MINE_BOOM3}, // S_MINE_BOOM2 - {SPR_MINE, 3, 3, {A_Explode}, 0, 0, S_MINE_BOOM4}, // S_MINE_BOOM3 - {SPR_MINE, 4, 3, {NULL}, 0, 0, S_NULL}, // S_MINE_BOOM4 + {SPR_MINE, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_MINE1 + {SPR_MINE, 1, 1, {A_Fall}, 0, 0, S_MINE_BOOM2, 0}, // S_MINE_BOOM1 + {SPR_MINE, 2, 3, {A_Scream}, 0, 0, S_MINE_BOOM3, 0}, // S_MINE_BOOM2 + {SPR_MINE, 3, 3, {A_Explode}, 0, 0, S_MINE_BOOM4, 0}, // S_MINE_BOOM3 + {SPR_MINE, 4, 3, {NULL}, 0, 0, S_NULL, 0}, // S_MINE_BOOM4 // Jetty-Syn Bullet - {SPR_JBUL, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_JETBULLET2}, // S_JETBULLET1 - {SPR_JBUL, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_JETBULLET1}, // S_JETBULLET2 + {SPR_JBUL, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_JETBULLET2, 0}, // S_JETBULLET1 + {SPR_JBUL, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_JETBULLET1, 0}, // S_JETBULLET2 - {SPR_TRLS, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_TURRETLASER}, // S_TURRETLASER - {SPR_TRLS, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_TURRETLASEREXPLODE2}, // S_TURRETLASEREXPLODE1 - {SPR_TRLS, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_NULL}, // S_TURRETLASEREXPLODE2 + {SPR_TRLS, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_TURRETLASER, 0}, // S_TURRETLASER + {SPR_TRLS, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_TURRETLASEREXPLODE2, 0}, // S_TURRETLASEREXPLODE1 + {SPR_TRLS, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_NULL, 0}, // S_TURRETLASEREXPLODE2 - {SPR_CBLL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CANNONBALL1 + {SPR_CBLL, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CANNONBALL1 - {SPR_AROW, 0, -1, {NULL}, 0, 0, S_NULL}, // S_ARROW - {SPR_AROW, FF_ANIMATE, TICRATE, {A_ArrowBonks}, 7, 2, S_NULL}, // S_ARROWBONK + {SPR_AROW, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_ARROW + {SPR_AROW, FF_ANIMATE, TICRATE, {A_ArrowBonks}, 7, 2, S_NULL, 0}, // S_ARROWBONK - {SPR_CFIR, FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 5, 2, S_NULL}, // S_DEMONFIRE + {SPR_CFIR, FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 5, 2, S_NULL, 0}, // S_DEMONFIRE - {SPR_LETR, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_LETTER + {SPR_LETR, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL, 0}, // S_LETTER // Tutorial scenery - {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|0, 3, {NULL}, 0, 0, S_TUTORIALLEAF2}, // S_TUTORIALLEAF1 - {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|1, 3, {NULL}, 0, 0, S_TUTORIALLEAF3}, // S_TUTORIALLEAF2 - {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|2, 3, {NULL}, 0, 0, S_TUTORIALLEAF4}, // S_TUTORIALLEAF3 - {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|3, 3, {NULL}, 0, 0, S_TUTORIALLEAF5}, // S_TUTORIALLEAF4 - {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|4, 3, {NULL}, 0, 0, S_TUTORIALLEAF6}, // S_TUTORIALLEAF5 - {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|5, 3, {NULL}, 0, 0, S_TUTORIALLEAF7}, // S_TUTORIALLEAF6 - {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|6, 3, {NULL}, 0, 0, S_TUTORIALLEAF8}, // S_TUTORIALLEAF7 - {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|7, 3, {NULL}, 0, 0, S_TUTORIALLEAF9}, // S_TUTORIALLEAF8 - {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|7, 3, {NULL}, 0, 0, S_TUTORIALLEAF10}, // S_TUTORIALLEAF9 - {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|6, 3, {NULL}, 0, 0, S_TUTORIALLEAF11}, // S_TUTORIALLEAF10 - {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|5, 3, {NULL}, 0, 0, S_TUTORIALLEAF12}, // S_TUTORIALLEAF11 - {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|4, 3, {NULL}, 0, 0, S_TUTORIALLEAF13}, // S_TUTORIALLEAF12 - {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|3, 3, {NULL}, 0, 0, S_TUTORIALLEAF14}, // S_TUTORIALLEAF13 - {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|2, 3, {NULL}, 0, 0, S_TUTORIALLEAF15}, // S_TUTORIALLEAF14 - {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|1, 3, {NULL}, 0, 0, S_TUTORIALLEAF16}, // S_TUTORIALLEAF15 - {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|0, 3, {NULL}, 0, 0, S_TUTORIALLEAF1}, // S_TUTORIALLEAF16 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|0, 3, {NULL}, 0, 0, S_TUTORIALFLOWER2}, // S_TUTORIALFLOWER1 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|1, 3, {NULL}, 0, 0, S_TUTORIALFLOWER3}, // S_TUTORIALFLOWER2 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|2, 3, {NULL}, 0, 0, S_TUTORIALFLOWER4}, // S_TUTORIALFLOWER3 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|3, 3, {NULL}, 0, 0, S_TUTORIALFLOWER5}, // S_TUTORIALFLOWER4 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|4, 3, {NULL}, 0, 0, S_TUTORIALFLOWER6}, // S_TUTORIALFLOWER5 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|5, 3, {NULL}, 0, 0, S_TUTORIALFLOWER7}, // S_TUTORIALFLOWER6 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|6, 3, {NULL}, 0, 0, S_TUTORIALFLOWER8}, // S_TUTORIALFLOWER7 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|7, 3, {NULL}, 0, 0, S_TUTORIALFLOWER9}, // S_TUTORIALFLOWER8 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|7, 3, {NULL}, 0, 0, S_TUTORIALFLOWER10}, // S_TUTORIALFLOWER9 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|6, 3, {NULL}, 0, 0, S_TUTORIALFLOWER11}, // S_TUTORIALFLOWER10 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|5, 3, {NULL}, 0, 0, S_TUTORIALFLOWER12}, // S_TUTORIALFLOWER11 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|4, 3, {NULL}, 0, 0, S_TUTORIALFLOWER13}, // S_TUTORIALFLOWER12 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|3, 3, {NULL}, 0, 0, S_TUTORIALFLOWER14}, // S_TUTORIALFLOWER13 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|2, 3, {NULL}, 0, 0, S_TUTORIALFLOWER15}, // S_TUTORIALFLOWER14 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|1, 3, {NULL}, 0, 0, S_TUTORIALFLOWER16}, // S_TUTORIALFLOWER15 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|0, 3, {NULL}, 0, 0, S_TUTORIALFLOWER1}, // S_TUTORIALFLOWER16 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|0, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF2}, // S_TUTORIALFLOWERF1 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|1, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF3}, // S_TUTORIALFLOWERF2 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|2, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF4}, // S_TUTORIALFLOWERF3 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|3, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF5}, // S_TUTORIALFLOWERF4 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|4, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF6}, // S_TUTORIALFLOWERF5 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|5, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF7}, // S_TUTORIALFLOWERF6 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|6, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF8}, // S_TUTORIALFLOWERF7 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|7, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF9}, // S_TUTORIALFLOWERF8 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|7, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF10}, // S_TUTORIALFLOWERF9 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|6, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF11}, // S_TUTORIALFLOWERF10 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|5, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF12}, // S_TUTORIALFLOWERF11 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|4, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF13}, // S_TUTORIALFLOWERF12 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|3, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF14}, // S_TUTORIALFLOWERF13 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|2, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF15}, // S_TUTORIALFLOWERF14 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|1, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF16}, // S_TUTORIALFLOWERF15 - {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|0, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF1}, // S_TUTORIALFLOWERF16 + {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|0, 3, {NULL}, 0, 0, S_TUTORIALLEAF2, 0}, // S_TUTORIALLEAF1 + {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|1, 3, {NULL}, 0, 0, S_TUTORIALLEAF3, 0}, // S_TUTORIALLEAF2 + {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|2, 3, {NULL}, 0, 0, S_TUTORIALLEAF4, 0}, // S_TUTORIALLEAF3 + {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|3, 3, {NULL}, 0, 0, S_TUTORIALLEAF5, 0}, // S_TUTORIALLEAF4 + {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|4, 3, {NULL}, 0, 0, S_TUTORIALLEAF6, 0}, // S_TUTORIALLEAF5 + {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|5, 3, {NULL}, 0, 0, S_TUTORIALLEAF7, 0}, // S_TUTORIALLEAF6 + {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|6, 3, {NULL}, 0, 0, S_TUTORIALLEAF8, 0}, // S_TUTORIALLEAF7 + {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|7, 3, {NULL}, 0, 0, S_TUTORIALLEAF9, 0}, // S_TUTORIALLEAF8 + {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|7, 3, {NULL}, 0, 0, S_TUTORIALLEAF10, 0}, // S_TUTORIALLEAF9 + {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|6, 3, {NULL}, 0, 0, S_TUTORIALLEAF11, 0}, // S_TUTORIALLEAF10 + {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|5, 3, {NULL}, 0, 0, S_TUTORIALLEAF12, 0}, // S_TUTORIALLEAF11 + {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|4, 3, {NULL}, 0, 0, S_TUTORIALLEAF13, 0}, // S_TUTORIALLEAF12 + {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|3, 3, {NULL}, 0, 0, S_TUTORIALLEAF14, 0}, // S_TUTORIALLEAF13 + {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|2, 3, {NULL}, 0, 0, S_TUTORIALLEAF15, 0}, // S_TUTORIALLEAF14 + {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|1, 3, {NULL}, 0, 0, S_TUTORIALLEAF16, 0}, // S_TUTORIALLEAF15 + {SPR_TUPL, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|0, 3, {NULL}, 0, 0, S_TUTORIALLEAF1, 0}, // S_TUTORIALLEAF16 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|0, 3, {NULL}, 0, 0, S_TUTORIALFLOWER2, 0}, // S_TUTORIALFLOWER1 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|1, 3, {NULL}, 0, 0, S_TUTORIALFLOWER3, 0}, // S_TUTORIALFLOWER2 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|2, 3, {NULL}, 0, 0, S_TUTORIALFLOWER4, 0}, // S_TUTORIALFLOWER3 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|3, 3, {NULL}, 0, 0, S_TUTORIALFLOWER5, 0}, // S_TUTORIALFLOWER4 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|4, 3, {NULL}, 0, 0, S_TUTORIALFLOWER6, 0}, // S_TUTORIALFLOWER5 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|5, 3, {NULL}, 0, 0, S_TUTORIALFLOWER7, 0}, // S_TUTORIALFLOWER6 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|6, 3, {NULL}, 0, 0, S_TUTORIALFLOWER8, 0}, // S_TUTORIALFLOWER7 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|7, 3, {NULL}, 0, 0, S_TUTORIALFLOWER9, 0}, // S_TUTORIALFLOWER8 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|7, 3, {NULL}, 0, 0, S_TUTORIALFLOWER10, 0}, // S_TUTORIALFLOWER9 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|6, 3, {NULL}, 0, 0, S_TUTORIALFLOWER11, 0}, // S_TUTORIALFLOWER10 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|5, 3, {NULL}, 0, 0, S_TUTORIALFLOWER12, 0}, // S_TUTORIALFLOWER11 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|4, 3, {NULL}, 0, 0, S_TUTORIALFLOWER13, 0}, // S_TUTORIALFLOWER12 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|3, 3, {NULL}, 0, 0, S_TUTORIALFLOWER14, 0}, // S_TUTORIALFLOWER13 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|2, 3, {NULL}, 0, 0, S_TUTORIALFLOWER15, 0}, // S_TUTORIALFLOWER14 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|1, 3, {NULL}, 0, 0, S_TUTORIALFLOWER16, 0}, // S_TUTORIALFLOWER15 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_PAPERSPRITE|0, 3, {NULL}, 0, 0, S_TUTORIALFLOWER1, 0}, // S_TUTORIALFLOWER16 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|0, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF2, 0}, // S_TUTORIALFLOWERF1 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|1, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF3, 0}, // S_TUTORIALFLOWERF2 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|2, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF4, 0}, // S_TUTORIALFLOWERF3 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|3, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF5, 0}, // S_TUTORIALFLOWERF4 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|4, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF6, 0}, // S_TUTORIALFLOWERF5 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|5, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF7, 0}, // S_TUTORIALFLOWERF6 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|6, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF8, 0}, // S_TUTORIALFLOWERF7 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|7, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF9, 0}, // S_TUTORIALFLOWERF8 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|7, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF10, 0}, // S_TUTORIALFLOWERF9 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|6, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF11, 0}, // S_TUTORIALFLOWERF10 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|5, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF12, 0}, // S_TUTORIALFLOWERF11 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|4, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF13, 0}, // S_TUTORIALFLOWERF12 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|3, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF14, 0}, // S_TUTORIALFLOWERF13 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|2, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF15, 0}, // S_TUTORIALFLOWERF14 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|1, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF16, 0}, // S_TUTORIALFLOWERF15 + {SPR_TUPF, FF_SEMIBRIGHT|FF_ADD|FF_FLOORSPRITE|0, 3, {NULL}, 0, 0, S_TUTORIALFLOWERF1, 0}, // S_TUTORIALFLOWERF16 // GFZ flowers - {SPR_FWR1, FF_ANIMATE, -1, {NULL}, 7, 3, S_NULL}, // S_GFZFLOWERA - {SPR_FWR2, FF_ANIMATE, -1, {NULL}, 19, 3, S_NULL}, // S_GFZFLOWERB - {SPR_FWR3, FF_ANIMATE, -1, {NULL}, 11, 4, S_NULL}, // S_GFZFLOWERC + {SPR_FWR1, FF_ANIMATE, -1, {NULL}, 7, 3, S_NULL, 0}, // S_GFZFLOWERA + {SPR_FWR2, FF_ANIMATE, -1, {NULL}, 19, 3, S_NULL, 0}, // S_GFZFLOWERB + {SPR_FWR3, FF_ANIMATE, -1, {NULL}, 11, 4, S_NULL, 0}, // S_GFZFLOWERC - {SPR_BUS3, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BLUEBERRYBUSH - {SPR_BUS1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BERRYBUSH - {SPR_BUS2, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BUSH + {SPR_BUS3, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BLUEBERRYBUSH + {SPR_BUS1, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BERRYBUSH + {SPR_BUS2, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BUSH // Trees - {SPR_TRE1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_GFZTREE - {SPR_TRE1, 1, -1, {NULL}, 0, 0, S_NULL}, // S_GFZBERRYTREE - {SPR_TRE1, 2, -1, {NULL}, 0, 0, S_NULL}, // S_GFZCHERRYTREE - {SPR_TRE2, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CHECKERTREE - {SPR_TRE2, 1, -1, {NULL}, 0, 0, S_NULL}, // S_CHECKERSUNSETTREE - {SPR_TRE3, 0, -1, {NULL}, 0, 0, S_NULL}, // S_FHZTREE - {SPR_TRE3, 1, -1, {NULL}, 0, 0, S_NULL}, // S_FHZPINKTREE - {SPR_TRE4, 0, -1, {NULL}, 0, 0, S_NULL}, // S_POLYGONTREE - {SPR_TRE5, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BUSHTREE - {SPR_TRE5, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BUSHREDTREE - {SPR_TRE6, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SPRINGTREE + {SPR_TRE1, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_GFZTREE + {SPR_TRE1, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_GFZBERRYTREE + {SPR_TRE1, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_GFZCHERRYTREE + {SPR_TRE2, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CHECKERTREE + {SPR_TRE2, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CHECKERSUNSETTREE + {SPR_TRE3, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_FHZTREE + {SPR_TRE3, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_FHZPINKTREE + {SPR_TRE4, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_POLYGONTREE + {SPR_TRE5, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BUSHTREE + {SPR_TRE5, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BUSHREDTREE + {SPR_TRE6, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SPRINGTREE // THZ flowers - {SPR_THZP, FF_ANIMATE, -1, {NULL}, 7, 4, S_NULL}, // S_THZFLOWERA - {SPR_FWR5, FF_ANIMATE, -1, {NULL}, 19, 2, S_NULL}, // S_THZFLOWERB - {SPR_FWR6, FF_ANIMATE, -1, {NULL}, 19, 2, S_NULL}, // S_THZFLOWERC + {SPR_THZP, FF_ANIMATE, -1, {NULL}, 7, 4, S_NULL, 0}, // S_THZFLOWERA + {SPR_FWR5, FF_ANIMATE, -1, {NULL}, 19, 2, S_NULL, 0}, // S_THZFLOWERB + {SPR_FWR6, FF_ANIMATE, -1, {NULL}, 19, 2, S_NULL, 0}, // S_THZFLOWERC // THZ Steam Whistle tree/bush - {SPR_THZT, 0, -1, {NULL}, 0, 0, S_NULL}, // S_THZTREE - {SPR_THZT, 1|FF_PAPERSPRITE, 40, {NULL}, 0, 0, S_THZTREEBRANCH2}, // S_THZTREEBRANCH1 - {SPR_THZT, 2|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH3}, // S_THZTREEBRANCH2 - {SPR_THZT, 3|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH4}, // S_THZTREEBRANCH3 - {SPR_THZT, 4|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH5}, // S_THZTREEBRANCH4 - {SPR_THZT, 5|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH6}, // S_THZTREEBRANCH5 - {SPR_THZT, 6|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH7}, // S_THZTREEBRANCH6 - {SPR_THZT, 7|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH8}, // S_THZTREEBRANCH7 - {SPR_THZT, 8|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH9}, // S_THZTREEBRANCH8 - {SPR_THZT, 9|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH10}, // S_THZTREEBRANCH9 - {SPR_THZT, 10|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH11}, // S_THZTREEBRANCH10 - {SPR_THZT, 11|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH12}, // S_THZTREEBRANCH11 - {SPR_THZT, 12|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH13}, // S_THZTREEBRANCH12 - {SPR_THZT, 13|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH1}, // S_THZTREEBRANCH13 + {SPR_THZT, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_THZTREE + {SPR_THZT, 1|FF_PAPERSPRITE, 40, {NULL}, 0, 0, S_THZTREEBRANCH2, 0}, // S_THZTREEBRANCH1 + {SPR_THZT, 2|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH3, 0}, // S_THZTREEBRANCH2 + {SPR_THZT, 3|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH4, 0}, // S_THZTREEBRANCH3 + {SPR_THZT, 4|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH5, 0}, // S_THZTREEBRANCH4 + {SPR_THZT, 5|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH6, 0}, // S_THZTREEBRANCH5 + {SPR_THZT, 6|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH7, 0}, // S_THZTREEBRANCH6 + {SPR_THZT, 7|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH8, 0}, // S_THZTREEBRANCH7 + {SPR_THZT, 8|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH9, 0}, // S_THZTREEBRANCH8 + {SPR_THZT, 9|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH10, 0}, // S_THZTREEBRANCH9 + {SPR_THZT, 10|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH11, 0}, // S_THZTREEBRANCH10 + {SPR_THZT, 11|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH12, 0}, // S_THZTREEBRANCH11 + {SPR_THZT, 12|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH13, 0}, // S_THZTREEBRANCH12 + {SPR_THZT, 13|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_THZTREEBRANCH1, 0}, // S_THZTREEBRANCH13 // THZ Alarm - {SPR_ALRM, FF_FULLBRIGHT, 35, {A_Scream}, 0, 0, S_ALARM1}, // S_ALARM1 + {SPR_ALRM, FF_FULLBRIGHT, 35, {A_Scream}, 0, 0, S_ALARM1, 0}, // S_ALARM1 // Deep Sea Gargoyle - {SPR_GARG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_GARGOYLE - {SPR_GARG, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BIGGARGOYLE + {SPR_GARG, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_GARGOYLE + {SPR_GARG, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BIGGARGOYLE // DSZ Seaweed - {SPR_SEWE, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 26, 3, S_SEAWEED1}, // S_SEAWEED1 - {SPR_SEWE, 1, 5, {NULL}, 0, 0, S_SEAWEED3}, // S_SEAWEED2 - {SPR_SEWE, 2, 5, {NULL}, 0, 0, S_SEAWEED4}, // S_SEAWEED3 - {SPR_SEWE, 3, 5, {NULL}, 0, 0, S_SEAWEED5}, // S_SEAWEED4 - {SPR_SEWE, 4, 5, {NULL}, 0, 0, S_SEAWEED6}, // S_SEAWEED5 - {SPR_SEWE, 5, 5, {NULL}, 0, 0, S_SEAWEED1}, // S_SEAWEED6 + {SPR_SEWE, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 26, 3, S_SEAWEED1, 0}, // S_SEAWEED1 + {SPR_SEWE, 1, 5, {NULL}, 0, 0, S_SEAWEED3, 0}, // S_SEAWEED2 + {SPR_SEWE, 2, 5, {NULL}, 0, 0, S_SEAWEED4, 0}, // S_SEAWEED3 + {SPR_SEWE, 3, 5, {NULL}, 0, 0, S_SEAWEED5, 0}, // S_SEAWEED4 + {SPR_SEWE, 4, 5, {NULL}, 0, 0, S_SEAWEED6, 0}, // S_SEAWEED5 + {SPR_SEWE, 5, 5, {NULL}, 0, 0, S_SEAWEED1, 0}, // S_SEAWEED6 // Dripping water - {SPR_NULL, FF_TRANS30 , 3*TICRATE, {NULL}, 0, 0, S_DRIPA2}, // S_DRIPA1 - {SPR_DRIP, FF_TRANS30 , 2, {NULL}, 0, 0, S_DRIPA3}, // S_DRIPA2 - {SPR_DRIP, FF_TRANS30|1, 2, {NULL}, 0, 0, S_DRIPA4}, // S_DRIPA3 - {SPR_DRIP, FF_TRANS30|2, 2, {A_SpawnObjectRelative}, 0, MT_WATERDROP, S_DRIPA1}, // S_DRIPA4 - {SPR_DRIP, FF_TRANS30|3, -1, {NULL}, 0, 0, S_DRIPB1}, // S_DRIPB1 - {SPR_DRIP, FF_TRANS30|4, 1, {NULL}, 0, 0, S_DRIPC2}, // S_DRIPC1 - {SPR_DRIP, FF_TRANS30|5, 1, {NULL}, 0, 0, S_NULL}, // S_DRIPC2 + {SPR_NULL, FF_TRANS30 , 3*TICRATE, {NULL}, 0, 0, S_DRIPA2, 0}, // S_DRIPA1 + {SPR_DRIP, FF_TRANS30 , 2, {NULL}, 0, 0, S_DRIPA3, 0}, // S_DRIPA2 + {SPR_DRIP, FF_TRANS30|1, 2, {NULL}, 0, 0, S_DRIPA4, 0}, // S_DRIPA3 + {SPR_DRIP, FF_TRANS30|2, 2, {A_SpawnObjectRelative}, 0, MT_WATERDROP, S_DRIPA1, 0}, // S_DRIPA4 + {SPR_DRIP, FF_TRANS30|3, -1, {NULL}, 0, 0, S_DRIPB1, 0}, // S_DRIPB1 + {SPR_DRIP, FF_TRANS30|4, 1, {NULL}, 0, 0, S_DRIPC2, 0}, // S_DRIPC1 + {SPR_DRIP, FF_TRANS30|5, 1, {NULL}, 0, 0, S_NULL, 0}, // S_DRIPC2 // Coral - {SPR_CORL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL1 - {SPR_CORL, 1, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL2 - {SPR_CORL, 2, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL3 - {SPR_CORL, 3, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL4 - {SPR_CORL, 4, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL5 + {SPR_CORL, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CORAL1 + {SPR_CORL, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CORAL2 + {SPR_CORL, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CORAL3 + {SPR_CORL, 3, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CORAL4 + {SPR_CORL, 4, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CORAL5 // Blue Crystal - {SPR_BCRY, FF_TRANS30, -1, {NULL}, 0, 0, S_NULL}, // S_BLUECRYSTAL1 + {SPR_BCRY, FF_TRANS30, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BLUECRYSTAL1 // Kelp - {SPR_KELP, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KELP + {SPR_KELP, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_KELP // Animated algae - {SPR_ALGA, 0, 1, {A_ConnectToGround}, MT_ANIMALGAESEG, 0, S_ANIMALGAETOP2}, // S_ANIMALGAETOP1 - {SPR_ALGA, 0|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 11, 4, S_NULL}, // S_ANIMALGAETOP2 - {SPR_ALGB, 0|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 11, 4, S_NULL}, // S_ANIMALGAESEG + {SPR_ALGA, 0, 1, {A_ConnectToGround}, MT_ANIMALGAESEG, 0, S_ANIMALGAETOP2, 0}, // S_ANIMALGAETOP1 + {SPR_ALGA, 0|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 11, 4, S_NULL, 0}, // S_ANIMALGAETOP2 + {SPR_ALGB, 0|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 11, 4, S_NULL, 0}, // S_ANIMALGAESEG // DSZ Stalagmites - {SPR_DSTG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_DSZSTALAGMITE - {SPR_DSTG, 1, -1, {NULL}, 0, 0, S_NULL}, // S_DSZ2STALAGMITE + {SPR_DSTG, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_DSZSTALAGMITE + {SPR_DSTG, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_DSZ2STALAGMITE // DSZ Light beam - {SPR_LIBE, 0|FF_TRANS80|FF_FULLBRIGHT|FF_PAPERSPRITE, 4, {A_LightBeamReset}, 0, 0, S_LIGHTBEAM2}, // S_LIGHTBEAM1 - {SPR_LIBE, 0|FF_TRANS70|FF_FULLBRIGHT|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_LIGHTBEAM3}, // S_LIGHTBEAM2 - {SPR_LIBE, 0|FF_TRANS60|FF_FULLBRIGHT|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_LIGHTBEAM4}, // S_LIGHTBEAM3 - {SPR_LIBE, 0|FF_TRANS50|FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {NULL}, 0, 0, S_LIGHTBEAM5}, // S_LIGHTBEAM4 - {SPR_LIBE, 0|FF_TRANS40|FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {NULL}, 0, 0, S_LIGHTBEAM6}, // S_LIGHTBEAM5 - {SPR_LIBE, 0|FF_TRANS30|FF_FULLBRIGHT|FF_PAPERSPRITE, 9, {NULL}, 0, 0, S_LIGHTBEAM7}, // S_LIGHTBEAM6 - {SPR_LIBE, 0|FF_TRANS40|FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {NULL}, 0, 0, S_LIGHTBEAM8}, // S_LIGHTBEAM7 - {SPR_LIBE, 0|FF_TRANS50|FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {NULL}, 0, 0, S_LIGHTBEAM9}, // S_LIGHTBEAM8 - {SPR_LIBE, 0|FF_TRANS60|FF_FULLBRIGHT|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_LIGHTBEAM10}, // S_LIGHTBEAM9 - {SPR_LIBE, 0|FF_TRANS70|FF_FULLBRIGHT|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_LIGHTBEAM11}, // S_LIGHTBEAM10 - {SPR_LIBE, 0|FF_TRANS80|FF_FULLBRIGHT|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_LIGHTBEAM12}, // S_LIGHTBEAM11 - {SPR_NULL, 0, 2, {A_SetRandomTics}, 4, 35, S_LIGHTBEAM1}, // S_LIGHTBEAM12 + {SPR_LIBE, 0|FF_TRANS80|FF_FULLBRIGHT|FF_PAPERSPRITE, 4, {A_LightBeamReset}, 0, 0, S_LIGHTBEAM2, 0}, // S_LIGHTBEAM1 + {SPR_LIBE, 0|FF_TRANS70|FF_FULLBRIGHT|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_LIGHTBEAM3, 0}, // S_LIGHTBEAM2 + {SPR_LIBE, 0|FF_TRANS60|FF_FULLBRIGHT|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_LIGHTBEAM4, 0}, // S_LIGHTBEAM3 + {SPR_LIBE, 0|FF_TRANS50|FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {NULL}, 0, 0, S_LIGHTBEAM5, 0}, // S_LIGHTBEAM4 + {SPR_LIBE, 0|FF_TRANS40|FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {NULL}, 0, 0, S_LIGHTBEAM6, 0}, // S_LIGHTBEAM5 + {SPR_LIBE, 0|FF_TRANS30|FF_FULLBRIGHT|FF_PAPERSPRITE, 9, {NULL}, 0, 0, S_LIGHTBEAM7, 0}, // S_LIGHTBEAM6 + {SPR_LIBE, 0|FF_TRANS40|FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {NULL}, 0, 0, S_LIGHTBEAM8, 0}, // S_LIGHTBEAM7 + {SPR_LIBE, 0|FF_TRANS50|FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {NULL}, 0, 0, S_LIGHTBEAM9, 0}, // S_LIGHTBEAM8 + {SPR_LIBE, 0|FF_TRANS60|FF_FULLBRIGHT|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_LIGHTBEAM10, 0}, // S_LIGHTBEAM9 + {SPR_LIBE, 0|FF_TRANS70|FF_FULLBRIGHT|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_LIGHTBEAM11, 0}, // S_LIGHTBEAM10 + {SPR_LIBE, 0|FF_TRANS80|FF_FULLBRIGHT|FF_PAPERSPRITE, 4, {NULL}, 0, 0, S_LIGHTBEAM12, 0}, // S_LIGHTBEAM11 + {SPR_NULL, 0, 2, {A_SetRandomTics}, 4, 35, S_LIGHTBEAM1, 0}, // S_LIGHTBEAM12 // CEZ Chain - {SPR_CHAN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZCHAIN + {SPR_CHAN, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CEZCHAIN // Flame - {SPR_FLAM, FF_FULLBRIGHT|FF_ANIMATE, 3*8, {A_FlameParticle}, 7, 3, S_FLAME}, // S_FLAME - {SPR_FLAM, FF_FULLBRIGHT|FF_ANIMATE|8, TICRATE, {NULL}, 3, 3, S_NULL}, // S_FLAMEPARTICLE - {SPR_FLAM, FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 7, 3, S_NULL}, // S_FLAMEREST + {SPR_FLAM, FF_FULLBRIGHT|FF_ANIMATE, 3*8, {A_FlameParticle}, 7, 3, S_FLAME, 0}, // S_FLAME + {SPR_FLAM, FF_FULLBRIGHT|FF_ANIMATE|8, TICRATE, {NULL}, 3, 3, S_NULL, 0}, // S_FLAMEPARTICLE + {SPR_FLAM, FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 7, 3, S_NULL, 0}, // S_FLAMEREST // Eggman statue - {SPR_ESTA, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGSTATUE1 + {SPR_ESTA, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EGGSTATUE1 // Hidden sling appears - {SPR_NULL, 0, -1, {NULL}, 0, 0, S_SLING2}, // S_SLING1 - {SPR_NULL, 0, -1, {A_SlingAppear}, 0, 0, S_NULL}, // S_SLING2 + {SPR_NULL, 0, -1, {NULL}, 0, 0, S_SLING2, 0}, // S_SLING1 + {SPR_NULL, 0, -1, {A_SlingAppear}, 0, 0, S_NULL, 0}, // S_SLING2 // CEZ maces and chains - {SPR_SMCH, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SMALLMACECHAIN - {SPR_BMCH, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BIGMACECHAIN - {SPR_SMCE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SMALLMACE - {SPR_BMCE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BIGMACE - {SPR_SMCH, 1, -1, {NULL}, 0, 0, S_NULL}, // S_SMALLGRABCHAIN - {SPR_BMCH, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BIGGRABCHAIN + {SPR_SMCH, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SMALLMACECHAIN + {SPR_BMCH, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BIGMACECHAIN + {SPR_SMCE, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SMALLMACE + {SPR_BMCE, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BIGMACE + {SPR_SMCH, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SMALLGRABCHAIN + {SPR_BMCH, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BIGGRABCHAIN // Blue spring on a ball - {SPR_BSPB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BLUESPRINGBALL - {SPR_BSPB, 4, 4, {A_Pain}, 0, 0, S_BLUESPRINGBALL3}, // S_BLUESPRINGBALL2 - {SPR_BSPB, 3, 1, {NULL}, 0, 0, S_BLUESPRINGBALL4}, // S_BLUESPRINGBALL3 - {SPR_BSPB, 2, 1, {NULL}, 0, 0, S_BLUESPRINGBALL5}, // S_BLUESPRINGBALL4 - {SPR_BSPB, 1, 1, {NULL}, 0, 0, S_BLUESPRINGBALL}, // S_BLUESPRINGBALL5 + {SPR_BSPB, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BLUESPRINGBALL + {SPR_BSPB, 4, 4, {A_Pain}, 0, 0, S_BLUESPRINGBALL3, 0}, // S_BLUESPRINGBALL2 + {SPR_BSPB, 3, 1, {NULL}, 0, 0, S_BLUESPRINGBALL4, 0}, // S_BLUESPRINGBALL3 + {SPR_BSPB, 2, 1, {NULL}, 0, 0, S_BLUESPRINGBALL5, 0}, // S_BLUESPRINGBALL4 + {SPR_BSPB, 1, 1, {NULL}, 0, 0, S_BLUESPRINGBALL, 0}, // S_BLUESPRINGBALL5 // Yellow spring on a ball - {SPR_YSPB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_YELLOWSPRINGBALL - {SPR_YSPB, 4, 4, {A_Pain}, 0, 0, S_YELLOWSPRINGBALL3}, // S_YELLOWSPRINGBALL2 - {SPR_YSPB, 3, 1, {NULL}, 0, 0, S_YELLOWSPRINGBALL4}, // S_YELLOWSPRINGBALL3 - {SPR_YSPB, 2, 1, {NULL}, 0, 0, S_YELLOWSPRINGBALL5}, // S_YELLOWSPRINGBALL4 - {SPR_YSPB, 1, 1, {NULL}, 0, 0, S_YELLOWSPRINGBALL}, // S_YELLOWSPRINGBALL5 + {SPR_YSPB, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_YELLOWSPRINGBALL + {SPR_YSPB, 4, 4, {A_Pain}, 0, 0, S_YELLOWSPRINGBALL3, 0}, // S_YELLOWSPRINGBALL2 + {SPR_YSPB, 3, 1, {NULL}, 0, 0, S_YELLOWSPRINGBALL4, 0}, // S_YELLOWSPRINGBALL3 + {SPR_YSPB, 2, 1, {NULL}, 0, 0, S_YELLOWSPRINGBALL5, 0}, // S_YELLOWSPRINGBALL4 + {SPR_YSPB, 1, 1, {NULL}, 0, 0, S_YELLOWSPRINGBALL, 0}, // S_YELLOWSPRINGBALL5 // Red spring on a ball - {SPR_RSPB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_REDSPRINGBALL - {SPR_RSPB, 4, 4, {A_Pain}, 0, 0, S_REDSPRINGBALL3}, // S_REDSPRINGBALL2 - {SPR_RSPB, 3, 1, {NULL}, 0, 0, S_REDSPRINGBALL4}, // S_REDSPRINGBALL3 - {SPR_RSPB, 2, 1, {NULL}, 0, 0, S_REDSPRINGBALL5}, // S_REDSPRINGBALL4 - {SPR_RSPB, 1, 1, {NULL}, 0, 0, S_REDSPRINGBALL}, // S_REDSPRINGBALL5 + {SPR_RSPB, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_REDSPRINGBALL + {SPR_RSPB, 4, 4, {A_Pain}, 0, 0, S_REDSPRINGBALL3, 0}, // S_REDSPRINGBALL2 + {SPR_RSPB, 3, 1, {NULL}, 0, 0, S_REDSPRINGBALL4, 0}, // S_REDSPRINGBALL3 + {SPR_RSPB, 2, 1, {NULL}, 0, 0, S_REDSPRINGBALL5, 0}, // S_REDSPRINGBALL4 + {SPR_RSPB, 1, 1, {NULL}, 0, 0, S_REDSPRINGBALL, 0}, // S_REDSPRINGBALL5 // Small Firebar - {SPR_SFBR, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_SMALLFIREBAR2}, // S_SMALLFIREBAR1 - {SPR_SFBR, FF_FULLBRIGHT| 1, 1, {NULL}, 0, 0, S_SMALLFIREBAR3}, // S_SMALLFIREBAR2 - {SPR_SFBR, FF_FULLBRIGHT| 2, 1, {A_FlameParticle}, 0, 0, S_SMALLFIREBAR4}, // S_SMALLFIREBAR3 - {SPR_SFBR, FF_FULLBRIGHT| 3, 1, {NULL}, 0, 0, S_SMALLFIREBAR5}, // S_SMALLFIREBAR4 - {SPR_SFBR, FF_FULLBRIGHT| 4, 1, {NULL}, 0, 0, S_SMALLFIREBAR6}, // S_SMALLFIREBAR5 - {SPR_SFBR, FF_FULLBRIGHT| 5, 1, {NULL}, 0, 0, S_SMALLFIREBAR7}, // S_SMALLFIREBAR6 - {SPR_SFBR, FF_FULLBRIGHT| 6, 1, {A_FlameParticle}, 0, 0, S_SMALLFIREBAR8}, // S_SMALLFIREBAR7 - {SPR_SFBR, FF_FULLBRIGHT| 7, 1, {NULL}, 0, 0, S_SMALLFIREBAR9}, // S_SMALLFIREBAR8 - {SPR_SFBR, FF_FULLBRIGHT| 8, 1, {NULL}, 0, 0, S_SMALLFIREBAR10}, // S_SMALLFIREBAR9 - {SPR_SFBR, FF_FULLBRIGHT| 9, 1, {NULL}, 0, 0, S_SMALLFIREBAR11}, // S_SMALLFIREBAR10 - {SPR_SFBR, FF_FULLBRIGHT|10, 1, {A_FlameParticle}, 0, 0, S_SMALLFIREBAR12}, // S_SMALLFIREBAR11 - {SPR_SFBR, FF_FULLBRIGHT|11, 1, {NULL}, 0, 0, S_SMALLFIREBAR13}, // S_SMALLFIREBAR12 - {SPR_SFBR, FF_FULLBRIGHT|12, 1, {NULL}, 0, 0, S_SMALLFIREBAR14}, // S_SMALLFIREBAR13 - {SPR_SFBR, FF_FULLBRIGHT|13, 1, {NULL}, 0, 0, S_SMALLFIREBAR15}, // S_SMALLFIREBAR14 - {SPR_SFBR, FF_FULLBRIGHT|14, 1, {A_FlameParticle}, 0, 0, S_SMALLFIREBAR16}, // S_SMALLFIREBAR15 - {SPR_SFBR, FF_FULLBRIGHT|15, 1, {NULL}, 0, 0, S_SMALLFIREBAR1}, // S_SMALLFIREBAR16 + {SPR_SFBR, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_SMALLFIREBAR2, 0}, // S_SMALLFIREBAR1 + {SPR_SFBR, FF_FULLBRIGHT| 1, 1, {NULL}, 0, 0, S_SMALLFIREBAR3, 0}, // S_SMALLFIREBAR2 + {SPR_SFBR, FF_FULLBRIGHT| 2, 1, {A_FlameParticle}, 0, 0, S_SMALLFIREBAR4, 0}, // S_SMALLFIREBAR3 + {SPR_SFBR, FF_FULLBRIGHT| 3, 1, {NULL}, 0, 0, S_SMALLFIREBAR5, 0}, // S_SMALLFIREBAR4 + {SPR_SFBR, FF_FULLBRIGHT| 4, 1, {NULL}, 0, 0, S_SMALLFIREBAR6, 0}, // S_SMALLFIREBAR5 + {SPR_SFBR, FF_FULLBRIGHT| 5, 1, {NULL}, 0, 0, S_SMALLFIREBAR7, 0}, // S_SMALLFIREBAR6 + {SPR_SFBR, FF_FULLBRIGHT| 6, 1, {A_FlameParticle}, 0, 0, S_SMALLFIREBAR8, 0}, // S_SMALLFIREBAR7 + {SPR_SFBR, FF_FULLBRIGHT| 7, 1, {NULL}, 0, 0, S_SMALLFIREBAR9, 0}, // S_SMALLFIREBAR8 + {SPR_SFBR, FF_FULLBRIGHT| 8, 1, {NULL}, 0, 0, S_SMALLFIREBAR10, 0}, // S_SMALLFIREBAR9 + {SPR_SFBR, FF_FULLBRIGHT| 9, 1, {NULL}, 0, 0, S_SMALLFIREBAR11, 0}, // S_SMALLFIREBAR10 + {SPR_SFBR, FF_FULLBRIGHT|10, 1, {A_FlameParticle}, 0, 0, S_SMALLFIREBAR12, 0}, // S_SMALLFIREBAR11 + {SPR_SFBR, FF_FULLBRIGHT|11, 1, {NULL}, 0, 0, S_SMALLFIREBAR13, 0}, // S_SMALLFIREBAR12 + {SPR_SFBR, FF_FULLBRIGHT|12, 1, {NULL}, 0, 0, S_SMALLFIREBAR14, 0}, // S_SMALLFIREBAR13 + {SPR_SFBR, FF_FULLBRIGHT|13, 1, {NULL}, 0, 0, S_SMALLFIREBAR15, 0}, // S_SMALLFIREBAR14 + {SPR_SFBR, FF_FULLBRIGHT|14, 1, {A_FlameParticle}, 0, 0, S_SMALLFIREBAR16, 0}, // S_SMALLFIREBAR15 + {SPR_SFBR, FF_FULLBRIGHT|15, 1, {NULL}, 0, 0, S_SMALLFIREBAR1, 0}, // S_SMALLFIREBAR16 // Big Firebar - {SPR_BFBR, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_BIGFIREBAR2}, // S_BIGFIREBAR1 - {SPR_BFBR, FF_FULLBRIGHT| 1, 1, {NULL}, 0, 0, S_BIGFIREBAR3}, // S_BIGFIREBAR2 - {SPR_BFBR, FF_FULLBRIGHT| 2, 1, {A_FlameParticle}, 0, 0, S_BIGFIREBAR4}, // S_BIGFIREBAR3 - {SPR_BFBR, FF_FULLBRIGHT| 3, 1, {NULL}, 0, 0, S_BIGFIREBAR5}, // S_BIGFIREBAR4 - {SPR_BFBR, FF_FULLBRIGHT| 4, 1, {NULL}, 0, 0, S_BIGFIREBAR6}, // S_BIGFIREBAR5 - {SPR_BFBR, FF_FULLBRIGHT| 5, 1, {NULL}, 0, 0, S_BIGFIREBAR7}, // S_BIGFIREBAR6 - {SPR_BFBR, FF_FULLBRIGHT| 6, 1, {A_FlameParticle}, 0, 0, S_BIGFIREBAR8}, // S_BIGFIREBAR7 - {SPR_BFBR, FF_FULLBRIGHT| 7, 1, {NULL}, 0, 0, S_BIGFIREBAR9}, // S_BIGFIREBAR8 - {SPR_BFBR, FF_FULLBRIGHT| 8, 1, {NULL}, 0, 0, S_BIGFIREBAR10}, // S_BIGFIREBAR9 - {SPR_BFBR, FF_FULLBRIGHT| 9, 1, {NULL}, 0, 0, S_BIGFIREBAR11}, // S_BIGFIREBAR10 - {SPR_BFBR, FF_FULLBRIGHT|10, 1, {A_FlameParticle}, 0, 0, S_BIGFIREBAR12}, // S_BIGFIREBAR11 - {SPR_BFBR, FF_FULLBRIGHT|11, 1, {NULL}, 0, 0, S_BIGFIREBAR13}, // S_BIGFIREBAR12 - {SPR_BFBR, FF_FULLBRIGHT|12, 1, {NULL}, 0, 0, S_BIGFIREBAR14}, // S_BIGFIREBAR13 - {SPR_BFBR, FF_FULLBRIGHT|13, 1, {NULL}, 0, 0, S_BIGFIREBAR15}, // S_BIGFIREBAR14 - {SPR_BFBR, FF_FULLBRIGHT|14, 1, {A_FlameParticle}, 0, 0, S_BIGFIREBAR16}, // S_BIGFIREBAR15 - {SPR_BFBR, FF_FULLBRIGHT|15, 1, {NULL}, 0, 0, S_BIGFIREBAR1}, // S_BIGFIREBAR16 + {SPR_BFBR, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_BIGFIREBAR2, 0}, // S_BIGFIREBAR1 + {SPR_BFBR, FF_FULLBRIGHT| 1, 1, {NULL}, 0, 0, S_BIGFIREBAR3, 0}, // S_BIGFIREBAR2 + {SPR_BFBR, FF_FULLBRIGHT| 2, 1, {A_FlameParticle}, 0, 0, S_BIGFIREBAR4, 0}, // S_BIGFIREBAR3 + {SPR_BFBR, FF_FULLBRIGHT| 3, 1, {NULL}, 0, 0, S_BIGFIREBAR5, 0}, // S_BIGFIREBAR4 + {SPR_BFBR, FF_FULLBRIGHT| 4, 1, {NULL}, 0, 0, S_BIGFIREBAR6, 0}, // S_BIGFIREBAR5 + {SPR_BFBR, FF_FULLBRIGHT| 5, 1, {NULL}, 0, 0, S_BIGFIREBAR7, 0}, // S_BIGFIREBAR6 + {SPR_BFBR, FF_FULLBRIGHT| 6, 1, {A_FlameParticle}, 0, 0, S_BIGFIREBAR8, 0}, // S_BIGFIREBAR7 + {SPR_BFBR, FF_FULLBRIGHT| 7, 1, {NULL}, 0, 0, S_BIGFIREBAR9, 0}, // S_BIGFIREBAR8 + {SPR_BFBR, FF_FULLBRIGHT| 8, 1, {NULL}, 0, 0, S_BIGFIREBAR10, 0}, // S_BIGFIREBAR9 + {SPR_BFBR, FF_FULLBRIGHT| 9, 1, {NULL}, 0, 0, S_BIGFIREBAR11, 0}, // S_BIGFIREBAR10 + {SPR_BFBR, FF_FULLBRIGHT|10, 1, {A_FlameParticle}, 0, 0, S_BIGFIREBAR12, 0}, // S_BIGFIREBAR11 + {SPR_BFBR, FF_FULLBRIGHT|11, 1, {NULL}, 0, 0, S_BIGFIREBAR13, 0}, // S_BIGFIREBAR12 + {SPR_BFBR, FF_FULLBRIGHT|12, 1, {NULL}, 0, 0, S_BIGFIREBAR14, 0}, // S_BIGFIREBAR13 + {SPR_BFBR, FF_FULLBRIGHT|13, 1, {NULL}, 0, 0, S_BIGFIREBAR15, 0}, // S_BIGFIREBAR14 + {SPR_BFBR, FF_FULLBRIGHT|14, 1, {A_FlameParticle}, 0, 0, S_BIGFIREBAR16, 0}, // S_BIGFIREBAR15 + {SPR_BFBR, FF_FULLBRIGHT|15, 1, {NULL}, 0, 0, S_BIGFIREBAR1, 0}, // S_BIGFIREBAR16 - {SPR_FWR4, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZFLOWER - {SPR_BANR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZPOLE + {SPR_FWR4, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CEZFLOWER + {SPR_BANR, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CEZPOLE - {SPR_BANR, FF_PAPERSPRITE|1, -1, {NULL}, 0, 0, S_NULL}, // S_CEZBANNER1 - {SPR_BANR, FF_PAPERSPRITE|2, -1, {NULL}, 0, 0, S_NULL}, // S_CEZBANNER2 + {SPR_BANR, FF_PAPERSPRITE|1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CEZBANNER1 + {SPR_BANR, FF_PAPERSPRITE|2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CEZBANNER2 - {SPR_PINE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_PINETREE - {SPR_CEZB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZBUSH1 - {SPR_CEZB, 1, -1, {NULL}, 0, 0, S_NULL}, // S_CEZBUSH2 + {SPR_PINE, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_PINETREE + {SPR_CEZB, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CEZBUSH1 + {SPR_CEZB, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CEZBUSH2 - {SPR_CNDL, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_CANDLE - {SPR_CNDL, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_NULL}, // S_CANDLEPRICKET + {SPR_CNDL, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CANDLE + {SPR_CNDL, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CANDLEPRICKET - {SPR_FLMH, 0, -1, {NULL}, 0, 0, S_NULL}, // S_FLAMEHOLDER + {SPR_FLMH, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_FLAMEHOLDER - {SPR_CTRC, FF_FULLBRIGHT|FF_ANIMATE, 8*3, {A_FlameParticle}, 3, 3, S_FIRETORCH}, // S_FIRETORCH + {SPR_CTRC, FF_FULLBRIGHT|FF_ANIMATE, 8*3, {A_FlameParticle}, 3, 3, S_FIRETORCH, 0}, // S_FIRETORCH - {SPR_CFLG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_WAVINGFLAG - {SPR_CFLG, FF_PAPERSPRITE|1, -1, {NULL}, 0, 0, S_NULL}, // S_WAVINGFLAGSEG1 - {SPR_CFLG, FF_PAPERSPRITE|2, -1, {NULL}, 0, 0, S_NULL}, // S_WAVINGFLAGSEG2 + {SPR_CFLG, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_WAVINGFLAG + {SPR_CFLG, FF_PAPERSPRITE|1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_WAVINGFLAGSEG1 + {SPR_CFLG, FF_PAPERSPRITE|2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_WAVINGFLAGSEG2 - {SPR_CSTA, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CRAWLASTATUE + {SPR_CSTA, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CRAWLASTATUE - {SPR_CBBS, 0, -1, {NULL}, 0, 0, S_NULL}, // S_FACESTABBERSTATUE + {SPR_CBBS, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_FACESTABBERSTATUE - {SPR_CBBS, 0, 5, {A_Look}, 768*FRACUNIT, 0, S_SUSPICIOUSFACESTABBERSTATUE_WAIT}, // S_SUSPICIOUSFACESTABBERSTATUE_WAIT - {SPR_CBBS, FF_ANIMATE, 23, {NULL}, 6, 1, S_SUSPICIOUSFACESTABBERSTATUE_BURST2}, // S_SUSPICIOUSFACESTABBERSTATUE_BURST1 - {SPR_NULL, 0, 40, {A_StatueBurst}, MT_FACESTABBER, S_FACESTABBER_CHARGE2, S_NULL}, // S_SUSPICIOUSFACESTABBERSTATUE_BURST2 + {SPR_CBBS, 0, 5, {A_Look}, 768*FRACUNIT, 0, S_SUSPICIOUSFACESTABBERSTATUE_WAIT, 0}, // S_SUSPICIOUSFACESTABBERSTATUE_WAIT + {SPR_CBBS, FF_ANIMATE, 23, {NULL}, 6, 1, S_SUSPICIOUSFACESTABBERSTATUE_BURST2, 0}, // S_SUSPICIOUSFACESTABBERSTATUE_BURST1 + {SPR_NULL, 0, 40, {A_StatueBurst}, MT_FACESTABBER, S_FACESTABBER_CHARGE2, S_NULL, 0}, // S_SUSPICIOUSFACESTABBERSTATUE_BURST2 - {SPR_CABR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BRAMBLES + {SPR_CABR, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BRAMBLES // Big Tumbleweed - {SPR_BTBL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BIGTUMBLEWEED - {SPR_BTBL, 0, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL2}, // S_BIGTUMBLEWEED_ROLL1 - {SPR_BTBL, 1, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL3}, // S_BIGTUMBLEWEED_ROLL2 - {SPR_BTBL, 2, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL4}, // S_BIGTUMBLEWEED_ROLL3 - {SPR_BTBL, 3, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL5}, // S_BIGTUMBLEWEED_ROLL4 - {SPR_BTBL, 4, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL6}, // S_BIGTUMBLEWEED_ROLL5 - {SPR_BTBL, 5, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL7}, // S_BIGTUMBLEWEED_ROLL6 - {SPR_BTBL, 6, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL8}, // S_BIGTUMBLEWEED_ROLL7 - {SPR_BTBL, 7, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL1}, // S_BIGTUMBLEWEED_ROLL8 + {SPR_BTBL, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BIGTUMBLEWEED + {SPR_BTBL, 0, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL2, 0}, // S_BIGTUMBLEWEED_ROLL1 + {SPR_BTBL, 1, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL3, 0}, // S_BIGTUMBLEWEED_ROLL2 + {SPR_BTBL, 2, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL4, 0}, // S_BIGTUMBLEWEED_ROLL3 + {SPR_BTBL, 3, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL5, 0}, // S_BIGTUMBLEWEED_ROLL4 + {SPR_BTBL, 4, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL6, 0}, // S_BIGTUMBLEWEED_ROLL5 + {SPR_BTBL, 5, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL7, 0}, // S_BIGTUMBLEWEED_ROLL6 + {SPR_BTBL, 6, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL8, 0}, // S_BIGTUMBLEWEED_ROLL7 + {SPR_BTBL, 7, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL1, 0}, // S_BIGTUMBLEWEED_ROLL8 // Little Tumbleweed - {SPR_STBL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_LITTLETUMBLEWEED - {SPR_STBL, 0, 5, {NULL}, 0, 0, S_LITTLETUMBLEWEED_ROLL2}, // S_LITTLETUMBLEWEED_ROLL1 - {SPR_STBL, 1, 5, {NULL}, 0, 0, S_LITTLETUMBLEWEED_ROLL3}, // S_LITTLETUMBLEWEED_ROLL2 - {SPR_STBL, 2, 5, {NULL}, 0, 0, S_LITTLETUMBLEWEED_ROLL4}, // S_LITTLETUMBLEWEED_ROLL3 - {SPR_STBL, 3, 5, {NULL}, 0, 0, S_LITTLETUMBLEWEED_ROLL5}, // S_LITTLETUMBLEWEED_ROLL4 - {SPR_STBL, 4, 5, {NULL}, 0, 0, S_LITTLETUMBLEWEED_ROLL6}, // S_LITTLETUMBLEWEED_ROLL5 - {SPR_STBL, 5, 5, {NULL}, 0, 0, S_LITTLETUMBLEWEED_ROLL7}, // S_LITTLETUMBLEWEED_ROLL6 - {SPR_STBL, 6, 5, {NULL}, 0, 0, S_LITTLETUMBLEWEED_ROLL8}, // S_LITTLETUMBLEWEED_ROLL7 - {SPR_STBL, 7, 5, {NULL}, 0, 0, S_LITTLETUMBLEWEED_ROLL1}, // S_LITTLETUMBLEWEED_ROLL8 + {SPR_STBL, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_LITTLETUMBLEWEED + {SPR_STBL, 0, 5, {NULL}, 0, 0, S_LITTLETUMBLEWEED_ROLL2, 0}, // S_LITTLETUMBLEWEED_ROLL1 + {SPR_STBL, 1, 5, {NULL}, 0, 0, S_LITTLETUMBLEWEED_ROLL3, 0}, // S_LITTLETUMBLEWEED_ROLL2 + {SPR_STBL, 2, 5, {NULL}, 0, 0, S_LITTLETUMBLEWEED_ROLL4, 0}, // S_LITTLETUMBLEWEED_ROLL3 + {SPR_STBL, 3, 5, {NULL}, 0, 0, S_LITTLETUMBLEWEED_ROLL5, 0}, // S_LITTLETUMBLEWEED_ROLL4 + {SPR_STBL, 4, 5, {NULL}, 0, 0, S_LITTLETUMBLEWEED_ROLL6, 0}, // S_LITTLETUMBLEWEED_ROLL5 + {SPR_STBL, 5, 5, {NULL}, 0, 0, S_LITTLETUMBLEWEED_ROLL7, 0}, // S_LITTLETUMBLEWEED_ROLL6 + {SPR_STBL, 6, 5, {NULL}, 0, 0, S_LITTLETUMBLEWEED_ROLL8, 0}, // S_LITTLETUMBLEWEED_ROLL7 + {SPR_STBL, 7, 5, {NULL}, 0, 0, S_LITTLETUMBLEWEED_ROLL1, 0}, // S_LITTLETUMBLEWEED_ROLL8 // Cacti - {SPR_CACT, 0, -1, {A_ConnectToGround}, MT_CACTITINYSEG, 0, S_NULL}, // S_CACTI1 - {SPR_CACT, 1, -1, {A_ConnectToGround}, MT_CACTISMALLSEG, 0, S_NULL}, // S_CACTI2 - {SPR_CACT, 2, -1, {A_ConnectToGround}, MT_CACTITINYSEG, 0, S_NULL}, // S_CACTI3 - {SPR_CACT, 3, -1, {A_ConnectToGround}, MT_CACTISMALLSEG, 0, S_NULL}, // S_CACTI4 - {SPR_CACT, 4, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI5 - {SPR_CACT, 5, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI6 - {SPR_CACT, 6, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI7 - {SPR_CACT, 7, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI8 - {SPR_CACT, 8, -1, {NULL}, 0, 0, S_NULL}, // S_CACTI9 - {SPR_CACT, 9, -1, {A_ConnectToGround}, MT_CACTITINYSEG, 0, S_NULL}, // S_CACTI10 - {SPR_CACT, 10, -1, {A_ConnectToGround}, MT_CACTISMALLSEG, 0, S_NULL}, // S_CACTI11 - {SPR_CACT, 11, -1, {NULL}, 0, 0, S_NULL}, // S_CACTITINYSEG - {SPR_CACT, 12, -1, {NULL}, 0, 0, S_NULL}, // S_CACTISMALLSEG + {SPR_CACT, 0, -1, {A_ConnectToGround}, MT_CACTITINYSEG, 0, S_NULL, 0}, // S_CACTI1 + {SPR_CACT, 1, -1, {A_ConnectToGround}, MT_CACTISMALLSEG, 0, S_NULL, 0}, // S_CACTI2 + {SPR_CACT, 2, -1, {A_ConnectToGround}, MT_CACTITINYSEG, 0, S_NULL, 0}, // S_CACTI3 + {SPR_CACT, 3, -1, {A_ConnectToGround}, MT_CACTISMALLSEG, 0, S_NULL, 0}, // S_CACTI4 + {SPR_CACT, 4, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CACTI5 + {SPR_CACT, 5, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CACTI6 + {SPR_CACT, 6, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CACTI7 + {SPR_CACT, 7, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CACTI8 + {SPR_CACT, 8, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CACTI9 + {SPR_CACT, 9, -1, {A_ConnectToGround}, MT_CACTITINYSEG, 0, S_NULL, 0}, // S_CACTI10 + {SPR_CACT, 10, -1, {A_ConnectToGround}, MT_CACTISMALLSEG, 0, S_NULL, 0}, // S_CACTI11 + {SPR_CACT, 11, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CACTITINYSEG + {SPR_CACT, 12, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CACTISMALLSEG // Warning Signs - {SPR_WWSG, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_ARIDSIGN_CAUTION - {SPR_WWS2, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_ARIDSIGN_CACTI - {SPR_WWS3, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_ARIDSIGN_SHARPTURN + {SPR_WWSG, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL, 0}, // S_ARIDSIGN_CAUTION + {SPR_WWS2, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL, 0}, // S_ARIDSIGN_CACTI + {SPR_WWS3, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL, 0}, // S_ARIDSIGN_SHARPTURN // Oil lamp - {SPR_OILL, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_OILLAMP - {SPR_OILF, FF_TRANS90|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_OILLAMPFLARE + {SPR_OILL, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL, 0}, // S_OILLAMP + {SPR_OILF, FF_TRANS90|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL, 0}, // S_OILLAMPFLARE // TNT barrel - {SPR_BARR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_TNTBARREL_STND1 - {SPR_BARX, 0, 0, {A_RollAngle}, 0, 1, S_TNTBARREL_EXPL2}, // S_TNTBARREL_EXPL1 - {SPR_BARX, 0|FF_FULLBRIGHT, 3, {A_SetObjectFlags}, MF_NOCLIP|MF_NOGRAVITY|MF_NOBLOCKMAP, 0, S_TNTBARREL_EXPL3}, // S_TNTBARREL_EXPL2 - {SPR_BARX, 1|FF_FULLBRIGHT, 2, {A_TNTExplode}, MT_TNTDUST, 0, S_TNTBARREL_EXPL4}, // S_TNTBARREL_EXPL3 - {SPR_BARX, 1|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_TNTBARREL_EXPL5}, // S_TNTBARREL_EXPL4 - {SPR_BARX, 2|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_TNTBARREL_EXPL6}, // S_TNTBARREL_EXPL5 - {SPR_BARX, 3|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_TNTBARREL_EXPL7}, // S_TNTBARREL_EXPL6 - {SPR_NULL, 0, 35, {NULL}, 0, 0, S_NULL}, // S_TNTBARREL_EXPL7 + {SPR_BARR, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_TNTBARREL_STND1 + {SPR_BARX, 0, 0, {A_RollAngle}, 0, 1, S_TNTBARREL_EXPL2, 0}, // S_TNTBARREL_EXPL1 + {SPR_BARX, 0|FF_FULLBRIGHT, 3, {A_SetObjectFlags}, MF_NOCLIP|MF_NOGRAVITY|MF_NOBLOCKMAP, 0, S_TNTBARREL_EXPL3, 0}, // S_TNTBARREL_EXPL2 + {SPR_BARX, 1|FF_FULLBRIGHT, 2, {A_TNTExplode}, MT_TNTDUST, 0, S_TNTBARREL_EXPL4, 0}, // S_TNTBARREL_EXPL3 + {SPR_BARX, 1|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_TNTBARREL_EXPL5, 0}, // S_TNTBARREL_EXPL4 + {SPR_BARX, 2|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_TNTBARREL_EXPL6, 0}, // S_TNTBARREL_EXPL5 + {SPR_BARX, 3|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_TNTBARREL_EXPL7, 0}, // S_TNTBARREL_EXPL6 + {SPR_NULL, 0, 35, {NULL}, 0, 0, S_NULL, 0}, // S_TNTBARREL_EXPL7 #ifndef ROTSPRITE - {SPR_BARR, 1|FF_ANIMATE, -1, {NULL}, 7, 2, S_NULL}, // S_TNTBARREL_FLYING + {SPR_BARR, 1|FF_ANIMATE, -1, {NULL}, 7, 2, S_NULL, 0}, // S_TNTBARREL_FLYING #else - {SPR_BARR, 1, 1, {A_RollAngle}, 14, 0, S_TNTBARREL_FLYING}, // S_TNTBARREL_FLYING + {SPR_BARR, 1, 1, {A_RollAngle}, 14, 0, S_TNTBARREL_FLYING, 0}, // S_TNTBARREL_FLYING #endif // TNT proximity shell - {SPR_REMT, 0, 10, {A_Look}, 33554433, 0, S_PROXIMITY_TNT}, // S_PROXIMITY_TNT - {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_PROXIMITY_TNT_TRIGGER2}, // S_PROXIMITY_TNT_TRIGGER1 - {SPR_REMT, 0, 16, {NULL}, 0, 0, S_PROXIMITY_TNT_TRIGGER3}, // S_PROXIMITY_TNT_TRIGGER2 - {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_PROXIMITY_TNT_TRIGGER4}, // S_PROXIMITY_TNT_TRIGGER3 - {SPR_REMT, 0, 16, {NULL}, 0, 0, S_PROXIMITY_TNT_TRIGGER5}, // S_PROXIMITY_TNT_TRIGGER4 - {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_PROXIMITY_TNT_TRIGGER6}, // S_PROXIMITY_TNT_TRIGGER5 - {SPR_REMT, 0, 4, {NULL}, 0, 0, S_PROXIMITY_TNT_TRIGGER7}, // S_PROXIMITY_TNT_TRIGGER6 - {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_PROXIMITY_TNT_TRIGGER8}, // S_PROXIMITY_TNT_TRIGGER7 - {SPR_REMT, 0, 4, {NULL}, 0, 0, S_PROXIMITY_TNT_TRIGGER9}, // S_PROXIMITY_TNT_TRIGGER8 - {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_PROXIMITY_TNT_TRIGGER10}, // S_PROXIMITY_TNT_TRIGGER9 - {SPR_REMT, 0, 4, {NULL}, 0, 0, S_PROXIMITY_TNT_TRIGGER11}, // S_PROXIMITY_TNT_TRIGGER10 - {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_PROXIMITY_TNT_TRIGGER12}, // S_PROXIMITY_TNT_TRIGGER11 - {SPR_REMT, 0, 4, {NULL}, 0, 0, S_PROXIMITY_TNT_TRIGGER13}, // S_PROXIMITY_TNT_TRIGGER12 - {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_PROXIMITY_TNT_TRIGGER14}, // S_PROXIMITY_TNT_TRIGGER13 - {SPR_REMT, 0, 2, {NULL}, 0, 0, S_PROXIMITY_TNT_TRIGGER15}, // S_PROXIMITY_TNT_TRIGGER14 - {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_PROXIMITY_TNT_TRIGGER16}, // S_PROXIMITY_TNT_TRIGGER15 - {SPR_REMT, 0, 2, {NULL}, 0, 0, S_PROXIMITY_TNT_TRIGGER17}, // S_PROXIMITY_TNT_TRIGGER16 - {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_PROXIMITY_TNT_TRIGGER18}, // S_PROXIMITY_TNT_TRIGGER17 - {SPR_REMT, 0, 2, {NULL}, 0, 0, S_PROXIMITY_TNT_TRIGGER19}, // S_PROXIMITY_TNT_TRIGGER18 - {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_PROXIMITY_TNT_TRIGGER20}, // S_PROXIMITY_TNT_TRIGGER19 - {SPR_REMT, 0, 2, {NULL}, 0, 0, S_PROXIMITY_TNT_TRIGGER21}, // S_PROXIMITY_TNT_TRIGGER20 - {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_PROXIMITY_TNT_TRIGGER22}, // S_PROXIMITY_TNT_TRIGGER21 - {SPR_REMT, 0, 2, {NULL}, 0, 0, S_PROXIMITY_TNT_TRIGGER23}, // S_PROXIMITY_TNT_TRIGGER22 - {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_TNTBARREL_EXPL1}, // S_PROXIMITY_TNT_TRIGGER23 + {SPR_REMT, 0, 10, {A_Look}, 33554433, 0, S_PROXIMITY_TNT, 0}, // S_PROXIMITY_TNT + {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_PROXIMITY_TNT_TRIGGER2, 0}, // S_PROXIMITY_TNT_TRIGGER1 + {SPR_REMT, 0, 16, {NULL}, 0, 0, S_PROXIMITY_TNT_TRIGGER3, 0}, // S_PROXIMITY_TNT_TRIGGER2 + {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_PROXIMITY_TNT_TRIGGER4, 0}, // S_PROXIMITY_TNT_TRIGGER3 + {SPR_REMT, 0, 16, {NULL}, 0, 0, S_PROXIMITY_TNT_TRIGGER5, 0}, // S_PROXIMITY_TNT_TRIGGER4 + {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_PROXIMITY_TNT_TRIGGER6, 0}, // S_PROXIMITY_TNT_TRIGGER5 + {SPR_REMT, 0, 4, {NULL}, 0, 0, S_PROXIMITY_TNT_TRIGGER7, 0}, // S_PROXIMITY_TNT_TRIGGER6 + {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_PROXIMITY_TNT_TRIGGER8, 0}, // S_PROXIMITY_TNT_TRIGGER7 + {SPR_REMT, 0, 4, {NULL}, 0, 0, S_PROXIMITY_TNT_TRIGGER9, 0}, // S_PROXIMITY_TNT_TRIGGER8 + {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_PROXIMITY_TNT_TRIGGER10, 0}, // S_PROXIMITY_TNT_TRIGGER9 + {SPR_REMT, 0, 4, {NULL}, 0, 0, S_PROXIMITY_TNT_TRIGGER11, 0}, // S_PROXIMITY_TNT_TRIGGER10 + {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_PROXIMITY_TNT_TRIGGER12, 0}, // S_PROXIMITY_TNT_TRIGGER11 + {SPR_REMT, 0, 4, {NULL}, 0, 0, S_PROXIMITY_TNT_TRIGGER13, 0}, // S_PROXIMITY_TNT_TRIGGER12 + {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_PROXIMITY_TNT_TRIGGER14, 0}, // S_PROXIMITY_TNT_TRIGGER13 + {SPR_REMT, 0, 2, {NULL}, 0, 0, S_PROXIMITY_TNT_TRIGGER15, 0}, // S_PROXIMITY_TNT_TRIGGER14 + {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_PROXIMITY_TNT_TRIGGER16, 0}, // S_PROXIMITY_TNT_TRIGGER15 + {SPR_REMT, 0, 2, {NULL}, 0, 0, S_PROXIMITY_TNT_TRIGGER17, 0}, // S_PROXIMITY_TNT_TRIGGER16 + {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_PROXIMITY_TNT_TRIGGER18, 0}, // S_PROXIMITY_TNT_TRIGGER17 + {SPR_REMT, 0, 2, {NULL}, 0, 0, S_PROXIMITY_TNT_TRIGGER19, 0}, // S_PROXIMITY_TNT_TRIGGER18 + {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_PROXIMITY_TNT_TRIGGER20, 0}, // S_PROXIMITY_TNT_TRIGGER19 + {SPR_REMT, 0, 2, {NULL}, 0, 0, S_PROXIMITY_TNT_TRIGGER21, 0}, // S_PROXIMITY_TNT_TRIGGER20 + {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_PROXIMITY_TNT_TRIGGER22, 0}, // S_PROXIMITY_TNT_TRIGGER21 + {SPR_REMT, 0, 2, {NULL}, 0, 0, S_PROXIMITY_TNT_TRIGGER23, 0}, // S_PROXIMITY_TNT_TRIGGER22 + {SPR_REMT, 1|FF_FULLBRIGHT, 1, {A_PlayActiveSound}, 0, 0, S_TNTBARREL_EXPL1, 0}, // S_PROXIMITY_TNT_TRIGGER23 // Dust devil - {SPR_NULL, 0, 1, {A_DustDevilThink}, 0, 0, S_DUSTDEVIL}, //S_DUSTDEVIL - {SPR_TAZD, 1|FF_PAPERSPRITE|FF_TRANS70, 2 * TICRATE, {NULL}, 0, 0, S_DUSTLAYER2}, // S_DUSTLAYER1 - {SPR_TAZD, 1|FF_PAPERSPRITE|FF_TRANS70, 5, {NULL}, 0, 0, S_DUSTLAYER3}, // S_DUSTLAYER2 - {SPR_TAZD, 1|FF_PAPERSPRITE|FF_TRANS80, 5, {NULL}, 0, 0, S_DUSTLAYER4}, // S_DUSTLAYER3 - {SPR_TAZD, 1|FF_PAPERSPRITE|FF_TRANS80, 5, {NULL}, 0, 0, S_DUSTLAYER5}, // S_DUSTLAYER4 - {SPR_TAZD, 1|FF_PAPERSPRITE|FF_TRANS90, 5, {NULL}, 0, 0, S_NULL}, // S_DUSTLAYER5 - {SPR_ADST, 0|FF_ANIMATE, 24, {NULL}, 3, 8, S_NULL}, // S_ARIDDUST1 - {SPR_ADST, 3|FF_ANIMATE, 24, {NULL}, 3, 8, S_NULL}, // S_ARIDDUST2 - {SPR_ADST, 6|FF_ANIMATE, 24, {NULL}, 3, 8, S_NULL}, // S_ARIDDUST3 + {SPR_NULL, 0, 1, {A_DustDevilThink}, 0, 0, S_DUSTDEVIL, 0}, //S_DUSTDEVIL + {SPR_TAZD, 1|FF_PAPERSPRITE|FF_TRANS70, 2 * TICRATE, {NULL}, 0, 0, S_DUSTLAYER2, 0}, // S_DUSTLAYER1 + {SPR_TAZD, 1|FF_PAPERSPRITE|FF_TRANS70, 5, {NULL}, 0, 0, S_DUSTLAYER3, 0}, // S_DUSTLAYER2 + {SPR_TAZD, 1|FF_PAPERSPRITE|FF_TRANS80, 5, {NULL}, 0, 0, S_DUSTLAYER4, 0}, // S_DUSTLAYER3 + {SPR_TAZD, 1|FF_PAPERSPRITE|FF_TRANS80, 5, {NULL}, 0, 0, S_DUSTLAYER5, 0}, // S_DUSTLAYER4 + {SPR_TAZD, 1|FF_PAPERSPRITE|FF_TRANS90, 5, {NULL}, 0, 0, S_NULL, 0}, // S_DUSTLAYER5 + {SPR_ADST, 0|FF_ANIMATE, 24, {NULL}, 3, 8, S_NULL, 0}, // S_ARIDDUST1 + {SPR_ADST, 3|FF_ANIMATE, 24, {NULL}, 3, 8, S_NULL, 0}, // S_ARIDDUST2 + {SPR_ADST, 6|FF_ANIMATE, 24, {NULL}, 3, 8, S_NULL, 0}, // S_ARIDDUST3 // Minecart - {SPR_NULL, 0, 1, {NULL}, 0, 0, S_MINECART_IDLE}, // S_MINECART_IDLE - {SPR_NULL, 0, 0, {A_KillSegments}, 0, 0, S_TNTBARREL_EXPL4}, // S_MINECART_DTH1 - {SPR_MCRT, 8|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_MINECARTEND - {SPR_MCRT, 0|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_MINECARTSEG_FRONT - {SPR_MCRT, 1|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_MINECARTSEG_BACK - {SPR_MCRT, 2|FF_PAPERSPRITE|FF_ANIMATE, -1, {NULL}, 2, 3, S_NULL}, // S_MINECARTSEG_LEFT - {SPR_MCRT, 5|FF_PAPERSPRITE|FF_ANIMATE, -1, {NULL}, 2, 3, S_NULL}, // S_MINECARTSEG_RIGHT - {SPR_LCKN, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_MINECARTSIDEMARK1 - {SPR_LCKN, 0|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_MINECARTSIDEMARK2 - {SPR_MCSP, FF_FULLBRIGHT, 1, {A_MinecartSparkThink}, 0, 0, S_MINECARTSPARK}, // S_MINECARTSPARK + {SPR_NULL, 0, 1, {NULL}, 0, 0, S_MINECART_IDLE, 0}, // S_MINECART_IDLE + {SPR_NULL, 0, 0, {A_KillSegments}, 0, 0, S_TNTBARREL_EXPL4, 0}, // S_MINECART_DTH1 + {SPR_MCRT, 8|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL, 0}, // S_MINECARTEND + {SPR_MCRT, 0|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL, 0}, // S_MINECARTSEG_FRONT + {SPR_MCRT, 1|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL, 0}, // S_MINECARTSEG_BACK + {SPR_MCRT, 2|FF_PAPERSPRITE|FF_ANIMATE, -1, {NULL}, 2, 3, S_NULL, 0}, // S_MINECARTSEG_LEFT + {SPR_MCRT, 5|FF_PAPERSPRITE|FF_ANIMATE, -1, {NULL}, 2, 3, S_NULL, 0}, // S_MINECARTSEG_RIGHT + {SPR_LCKN, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL, 0}, // S_MINECARTSIDEMARK1 + {SPR_LCKN, 0|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL, 0}, // S_MINECARTSIDEMARK2 + {SPR_MCSP, FF_FULLBRIGHT, 1, {A_MinecartSparkThink}, 0, 0, S_MINECARTSPARK, 0}, // S_MINECARTSPARK // Saloon door - {SPR_SALD, 0|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_SALOONDOOR - {SPR_NULL, 0, -1, {A_SaloonDoorSpawn}, MT_SALOONDOOR, 48, S_NULL}, // S_SALOONDOORCENTER + {SPR_SALD, 0|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SALOONDOOR + {SPR_NULL, 0, -1, {A_SaloonDoorSpawn}, MT_SALOONDOOR, 48, S_NULL, 0}, // S_SALOONDOORCENTER // Train cameo - {SPR_NULL, 0, -1, {NULL}, 0, 0, S_TRAINCAMEOSPAWNER_2}, // S_TRAINCAMEOSPAWNER_1 - {SPR_NULL, 0, 14, {A_TrainCameo}, 20, 18, S_TRAINCAMEOSPAWNER_3}, // S_TRAINCAMEOSPAWNER_2 - {SPR_NULL, 0, 1, {A_Repeat}, 1, 0, S_TRAINCAMEOSPAWNER_4}, // S_TRAINCAMEOSPAWNER_3 - {SPR_NULL, 0, 18, {A_TrainCameo2}, 20, 44, S_TRAINCAMEOSPAWNER_5}, // S_TRAINCAMEOSPAWNER_4 - {SPR_NULL, 0, 1, {A_Repeat}, 5, S_TRAINCAMEOSPAWNER_4, S_NULL}, // S_TRAINCAMEOSPAWNER_5 - {SPR_NULL, 0, 2, {A_SmokeTrailer}, MT_SMOKE, 0, S_TRAINPUFFMAKER}, // S_TRAINPUFFMAKER + {SPR_NULL, 0, -1, {NULL}, 0, 0, S_TRAINCAMEOSPAWNER_2, 0}, // S_TRAINCAMEOSPAWNER_1 + {SPR_NULL, 0, 14, {A_TrainCameo}, 20, 18, S_TRAINCAMEOSPAWNER_3, 0}, // S_TRAINCAMEOSPAWNER_2 + {SPR_NULL, 0, 1, {A_Repeat}, 1, 0, S_TRAINCAMEOSPAWNER_4, 0}, // S_TRAINCAMEOSPAWNER_3 + {SPR_NULL, 0, 18, {A_TrainCameo2}, 20, 44, S_TRAINCAMEOSPAWNER_5, 0}, // S_TRAINCAMEOSPAWNER_4 + {SPR_NULL, 0, 1, {A_Repeat}, 5, S_TRAINCAMEOSPAWNER_4, S_NULL, 0}, // S_TRAINCAMEOSPAWNER_5 + {SPR_NULL, 0, 2, {A_SmokeTrailer}, MT_SMOKE, 0, S_TRAINPUFFMAKER, 0}, // S_TRAINPUFFMAKER - {SPR_ADST, FF_TRANS50, -1, {NULL}, 0, 0, S_NULL}, // S_TRAINDUST - {SPR_STEA, FF_TRANS50, -1, {NULL}, 0, 0, S_NULL}, // S_TRAINSTEAM + {SPR_ADST, FF_TRANS50, -1, {NULL}, 0, 0, S_NULL, 0}, // S_TRAINDUST + {SPR_STEA, FF_TRANS50, -1, {NULL}, 0, 0, S_NULL, 0}, // S_TRAINSTEAM // Flame jet - {SPR_NULL, 0, 2*TICRATE, {NULL}, 0, 0, S_FLAMEJETSTART}, // S_FLAMEJETSTND - {SPR_NULL, 0, 3*TICRATE, {A_ToggleFlameJet}, 0, 0, S_FLAMEJETSTOP}, // S_FLAMEJETSTART - {SPR_NULL, 0, 1, {A_ToggleFlameJet}, 0, 0, S_FLAMEJETSTND}, // S_FLAMEJETSTOP - {SPR_FLME, FF_FULLBRIGHT , 4, {NULL}, 0, 0, S_FLAMEJETFLAME2}, // S_FLAMEJETFLAME1 - {SPR_FLME, FF_FULLBRIGHT|1, 5, {NULL}, 0, 0, S_FLAMEJETFLAME3}, // S_FLAMEJETFLAME2 - {SPR_FLME, FF_FULLBRIGHT|2, 11, {NULL}, 0, 0, S_NULL}, // S_FLAMEJETFLAME3 - {SPR_FLME, FF_FULLBRIGHT|3, 4, {NULL}, 0, 0, S_FLAMEJETFLAME5}, // S_FLAMEJETFLAME4 - {SPR_FLME, FF_FULLBRIGHT|4, 5, {NULL}, 0, 0, S_FLAMEJETFLAME6}, // S_FLAMEJETFLAME5 - {SPR_FLME, FF_FULLBRIGHT|5, 11, {NULL}, 0, 0, S_NULL}, // S_FLAMEJETFLAME6 - {SPR_FLME, FF_FULLBRIGHT|6, 4, {NULL}, 0, 0, S_FLAMEJETFLAME8}, // S_FLAMEJETFLAME7 - {SPR_FLME, FF_FULLBRIGHT|7, 5, {NULL}, 0, 0, S_FLAMEJETFLAME9}, // S_FLAMEJETFLAME8 - {SPR_FLME, FF_FULLBRIGHT|8, 11, {NULL}, 0, 0, S_NULL}, // S_FLAMEJETFLAME9 + {SPR_NULL, 0, 2*TICRATE, {NULL}, 0, 0, S_FLAMEJETSTART, 0}, // S_FLAMEJETSTND + {SPR_NULL, 0, 3*TICRATE, {A_ToggleFlameJet}, 0, 0, S_FLAMEJETSTOP, 0}, // S_FLAMEJETSTART + {SPR_NULL, 0, 1, {A_ToggleFlameJet}, 0, 0, S_FLAMEJETSTND, 0}, // S_FLAMEJETSTOP + {SPR_FLME, FF_FULLBRIGHT , 4, {NULL}, 0, 0, S_FLAMEJETFLAME2, 0}, // S_FLAMEJETFLAME1 + {SPR_FLME, FF_FULLBRIGHT|1, 5, {NULL}, 0, 0, S_FLAMEJETFLAME3, 0}, // S_FLAMEJETFLAME2 + {SPR_FLME, FF_FULLBRIGHT|2, 11, {NULL}, 0, 0, S_NULL, 0}, // S_FLAMEJETFLAME3 + {SPR_FLME, FF_FULLBRIGHT|3, 4, {NULL}, 0, 0, S_FLAMEJETFLAME5, 0}, // S_FLAMEJETFLAME4 + {SPR_FLME, FF_FULLBRIGHT|4, 5, {NULL}, 0, 0, S_FLAMEJETFLAME6, 0}, // S_FLAMEJETFLAME5 + {SPR_FLME, FF_FULLBRIGHT|5, 11, {NULL}, 0, 0, S_NULL, 0}, // S_FLAMEJETFLAME6 + {SPR_FLME, FF_FULLBRIGHT|6, 4, {NULL}, 0, 0, S_FLAMEJETFLAME8, 0}, // S_FLAMEJETFLAME7 + {SPR_FLME, FF_FULLBRIGHT|7, 5, {NULL}, 0, 0, S_FLAMEJETFLAME9, 0}, // S_FLAMEJETFLAME8 + {SPR_FLME, FF_FULLBRIGHT|8, 11, {NULL}, 0, 0, S_NULL, 0}, // S_FLAMEJETFLAME9 // Spinning flame jets // A: Counter-clockwise - {SPR_NULL, 0, 1, {A_TrapShot}, MT_FLAMEJETFLAMEB, -(16<<16)|(1<<15)|64, S_FJSPINAXISA2}, // S_FJSPINAXISA1 - {SPR_NULL, 0, 2, {A_ChangeAngleRelative}, 6, 6, S_FJSPINAXISA1}, // S_FJSPINAXISA2 + {SPR_NULL, 0, 1, {A_TrapShot}, MT_FLAMEJETFLAMEB, -(16<<16)|(1<<15)|64, S_FJSPINAXISA2, 0}, // S_FJSPINAXISA1 + {SPR_NULL, 0, 2, {A_ChangeAngleRelative}, 6, 6, S_FJSPINAXISA1, 0}, // S_FJSPINAXISA2 // B: Clockwise - {SPR_NULL, 0, 1, {A_TrapShot}, MT_FLAMEJETFLAMEB, -(16<<16)|(1<<15)|64, S_FJSPINAXISB2}, // S_FJSPINAXISB1 - {SPR_NULL, 0, 2, {A_ChangeAngleRelative}, -6, -6, S_FJSPINAXISB1}, // S_FJSPINAXISB2 + {SPR_NULL, 0, 1, {A_TrapShot}, MT_FLAMEJETFLAMEB, -(16<<16)|(1<<15)|64, S_FJSPINAXISB2, 0}, // S_FJSPINAXISB1 + {SPR_NULL, 0, 2, {A_ChangeAngleRelative}, -6, -6, S_FJSPINAXISB1, 0}, // S_FJSPINAXISB2 // Blade's flame - {SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40, 1, {A_MoveRelative}, 0, 5, S_FLAMEJETFLAMEB2}, // S_FLAMEJETFLAMEB1 - {SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40, 1, {A_MoveRelative}, 0, 7, S_FLAMEJETFLAMEB3}, // S_FLAMEJETFLAMEB2 - {SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|FF_ANIMATE, (12*7), {NULL}, 7, 12, S_NULL}, // S_FLAMEJETFLAMEB3 + {SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40, 1, {A_MoveRelative}, 0, 5, S_FLAMEJETFLAMEB2, 0}, // S_FLAMEJETFLAMEB1 + {SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40, 1, {A_MoveRelative}, 0, 7, S_FLAMEJETFLAMEB3, 0}, // S_FLAMEJETFLAMEB2 + {SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|FF_ANIMATE, (12*7), {NULL}, 7, 12, S_NULL, 0}, // S_FLAMEJETFLAMEB3 // Lavafall - {SPR_LFAL, 5, 1, {NULL}, 0, 0, S_LAVAFALL_DORMANT}, // S_LAVAFALL_DORMANT - {SPR_LFAL, 6|FF_ANIMATE, 4, {A_LavafallRocks}, 1, 2, S_LAVAFALL_TELL}, // S_LAVAFALL_TELL - {SPR_LFAL, 9|FF_FULLBRIGHT|FF_ANIMATE, 2, {A_LavafallLava}, 1, 1, S_LAVAFALL_SHOOT}, // S_LAVAFALL_SHOOT - {SPR_LFAL, FF_FULLBRIGHT, 1, {A_FallingLavaCheck}, 0, 0, S_LAVAFALL_LAVA2}, // S_LAVAFALL_LAVA1 - {SPR_LFAL, FF_FULLBRIGHT, 1, {A_FallingLavaCheck}, 0, 0, S_LAVAFALL_LAVA1}, // S_LAVAFALL_LAVA2 - {SPR_LFAL, 2|FF_FULLBRIGHT|FF_ANIMATE, 9, {NULL}, 2, 3, S_NULL}, // S_LAVAFALL_LAVA3 - {SPR_LFAL, 11|FF_ANIMATE|FF_RANDOMANIM, 12, {NULL}, 3, 3, S_LAVAFALLROCK}, // S_LAVAFALLROCK + {SPR_LFAL, 5, 1, {NULL}, 0, 0, S_LAVAFALL_DORMANT, 0}, // S_LAVAFALL_DORMANT + {SPR_LFAL, 6|FF_ANIMATE, 4, {A_LavafallRocks}, 1, 2, S_LAVAFALL_TELL, 0}, // S_LAVAFALL_TELL + {SPR_LFAL, 9|FF_FULLBRIGHT|FF_ANIMATE, 2, {A_LavafallLava}, 1, 1, S_LAVAFALL_SHOOT, 0}, // S_LAVAFALL_SHOOT + {SPR_LFAL, FF_FULLBRIGHT, 1, {A_FallingLavaCheck}, 0, 0, S_LAVAFALL_LAVA2, 0}, // S_LAVAFALL_LAVA1 + {SPR_LFAL, FF_FULLBRIGHT, 1, {A_FallingLavaCheck}, 0, 0, S_LAVAFALL_LAVA1, 0}, // S_LAVAFALL_LAVA2 + {SPR_LFAL, 2|FF_FULLBRIGHT|FF_ANIMATE, 9, {NULL}, 2, 3, S_NULL, 0}, // S_LAVAFALL_LAVA3 + {SPR_LFAL, 11|FF_ANIMATE|FF_RANDOMANIM, 12, {NULL}, 3, 3, S_LAVAFALLROCK, 0}, // S_LAVAFALLROCK // Rollout Rock - {SPR_NULL, 0, 1, {A_RolloutSpawn}, 256*FRACUNIT, MT_ROLLOUTROCK, S_ROLLOUTSPAWN}, // S_ROLLOUTSPAWN - {SPR_PUMI, 0, 1, {A_RolloutRock}, 63*FRACUNIT/64, 7*FRACUNIT/10, S_ROLLOUTROCK}, // S_ROLLOUTROCK + {SPR_NULL, 0, 1, {A_RolloutSpawn}, 256*FRACUNIT, MT_ROLLOUTROCK, S_ROLLOUTSPAWN, 0}, // S_ROLLOUTSPAWN + {SPR_PUMI, 0, 1, {A_RolloutRock}, 63*FRACUNIT/64, 7*FRACUNIT/10, S_ROLLOUTROCK, 0}, // S_ROLLOUTROCK // RVZ scenery - {SPR_JPLA, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_BIGFERNLEAF - {SPR_JPLA, 1, 1, {NULL}, 0, 0, S_BIGFERN2}, // S_BIGFERN1 - {SPR_JPLA, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BIGFERN2 - {SPR_JPLA, 2, -1, {NULL}, 0, 0, S_NULL}, // S_JUNGLEPALM - {SPR_TFLO, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_TORCHFLOWER}, // S_TORCHFLOWER - {SPR_WVIN, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_WALLVINE_LONG - {SPR_WVIN, 1|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_WALLVINE_SHORT + {SPR_JPLA, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BIGFERNLEAF + {SPR_JPLA, 1, 1, {NULL}, 0, 0, S_BIGFERN2, 0}, // S_BIGFERN1 + {SPR_JPLA, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BIGFERN2 + {SPR_JPLA, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_JUNGLEPALM + {SPR_TFLO, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_TORCHFLOWER, 0}, // S_TORCHFLOWER + {SPR_WVIN, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL, 0}, // S_WALLVINE_LONG + {SPR_WVIN, 1|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL, 0}, // S_WALLVINE_SHORT // Glaregoyles - {SPR_BGAR, 0, 22, {NULL}, 0, 0, S_GLAREGOYLE_CHARGE}, // S_GLAREGOYLE - {SPR_BGAR, 2, 6, {NULL}, 0, 0, S_GLAREGOYLE_BLINK}, // S_GLAREGOYLE_CHARGE - {SPR_BGAR, FF_ANIMATE|1, 18, {NULL}, 1, 3, S_GLAREGOYLE_HOLD}, // S_GLAREGOYLE_BLINK - {SPR_BGAR, 1, 9, {NULL}, 0, 0, S_GLAREGOYLE_FIRE}, // S_GLAREGOYLE_HOLD - {SPR_BGAR, 1, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_GLAREGOYLE_LOOP}, // S_GLAREGOYLE_FIRE - {SPR_BGAR, 1, 0, {A_Repeat}, 3, S_GLAREGOYLE_FIRE, S_GLAREGOYLE_COOLDOWN}, // S_GLAREGOYLE_LOOP - {SPR_BGAR, FF_ANIMATE|1, 15, {NULL}, 1, 9, S_GLAREGOYLE}, // S_GLAREGOYLE_COOLDOWN - - {SPR_BGAR, 0, 22, {NULL}, 0, 0, S_GLAREGOYLEUP_CHARGE}, // S_GLAREGOYLEUP - {SPR_BGAR, 2, 6, {NULL}, 0, 0, S_GLAREGOYLEUP_BLINK}, // S_GLAREGOYLEUP_CHARGE - {SPR_BGAR, FF_ANIMATE|1, 18, {NULL}, 1, 3, S_GLAREGOYLEUP_HOLD}, // S_GLAREGOYLEUP_BLINK - {SPR_BGAR, 1, 9, {NULL}, 0, 0, S_GLAREGOYLEUP_FIRE}, // S_GLAREGOYLEUP_HOLD - {SPR_BGAR, 1, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+45, S_GLAREGOYLEUP_LOOP}, // S_GLAREGOYLEUP_FIRE - {SPR_BGAR, 1, 0, {A_Repeat}, 3, S_GLAREGOYLEUP_FIRE, S_GLAREGOYLEUP_COOLDOWN}, // S_GLAREGOYLEUP_LOOP - {SPR_BGAR, FF_ANIMATE|1, 15, {NULL}, 1, 9, S_GLAREGOYLEUP}, // S_GLAREGOYLEUP_COOLDOWN - - {SPR_BGAR, 0, 22, {NULL}, 0, 0, S_GLAREGOYLEDOWN_CHARGE}, // S_GLAREGOYLEDOWN - {SPR_BGAR, 2, 6, {NULL}, 0, 0, S_GLAREGOYLEDOWN_BLINK}, // S_GLAREGOYLEDOWN_CHARGE - {SPR_BGAR, FF_ANIMATE|1, 18, {NULL}, 1, 3, S_GLAREGOYLEDOWN_HOLD}, // S_GLAREGOYLEDOWN_BLINK - {SPR_BGAR, 1, 9, {NULL}, 0, 0, S_GLAREGOYLEDOWN_FIRE}, // S_GLAREGOYLEDOWN_HOLD - {SPR_BGAR, 1, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+315, S_GLAREGOYLEDOWN_LOOP}, // S_GLAREGOYLEDOWN_FIRE - {SPR_BGAR, 1, 0, {A_Repeat}, 3, S_GLAREGOYLEDOWN_FIRE, S_GLAREGOYLEDOWN_COOLDOWN}, // S_GLAREGOYLEDOWN_LOOP - {SPR_BGAR, FF_ANIMATE|1, 15, {NULL}, 1, 9, S_GLAREGOYLEDOWN}, // S_GLAREGOYLEDOWN_COOLDOWN - - {SPR_BGAR, 0, 90, {NULL}, 0, 0, S_GLAREGOYLELONG_CHARGE}, // S_GLAREGOYLELONG - {SPR_BGAR, 2, 6, {NULL}, 0, 0, S_GLAREGOYLELONG_BLINK}, // S_GLAREGOYLELONG_CHARGE - {SPR_BGAR, FF_ANIMATE|1, 18, {NULL}, 1, 3, S_GLAREGOYLELONG_HOLD}, // S_GLAREGOYLELONG_BLINK - {SPR_BGAR, 1, 9, {NULL}, 0, 0, S_GLAREGOYLELONG_FIRE}, // S_GLAREGOYLELONG_HOLD - {SPR_BGAR, 1, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_GLAREGOYLELONG_LOOP}, // S_GLAREGOYLELONG_FIRE - {SPR_BGAR, 1, 0, {A_Repeat}, 5, S_GLAREGOYLELONG_FIRE, S_GLAREGOYLELONG_COOLDOWN}, // S_GLAREGOYLELONG_LOOP - {SPR_BGAR, FF_ANIMATE|1, 15, {NULL}, 1, 9, S_GLAREGOYLELONG}, // S_GLAREGOYLELONG_COOLDOWN + {SPR_BGAR, 0, 22, {NULL}, 0, 0, S_GLAREGOYLE_CHARGE, 0}, // S_GLAREGOYLE + {SPR_BGAR, 2, 6, {NULL}, 0, 0, S_GLAREGOYLE_BLINK, 0}, // S_GLAREGOYLE_CHARGE + {SPR_BGAR, FF_ANIMATE|1, 18, {NULL}, 1, 3, S_GLAREGOYLE_HOLD, 0}, // S_GLAREGOYLE_BLINK + {SPR_BGAR, 1, 9, {NULL}, 0, 0, S_GLAREGOYLE_FIRE, 0}, // S_GLAREGOYLE_HOLD + {SPR_BGAR, 1, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_GLAREGOYLE_LOOP, 0}, // S_GLAREGOYLE_FIRE + {SPR_BGAR, 1, 0, {A_Repeat}, 3, S_GLAREGOYLE_FIRE, S_GLAREGOYLE_COOLDOWN, 0}, // S_GLAREGOYLE_LOOP + {SPR_BGAR, FF_ANIMATE|1, 15, {NULL}, 1, 9, S_GLAREGOYLE, 0}, // S_GLAREGOYLE_COOLDOWN + + {SPR_BGAR, 0, 22, {NULL}, 0, 0, S_GLAREGOYLEUP_CHARGE, 0}, // S_GLAREGOYLEUP + {SPR_BGAR, 2, 6, {NULL}, 0, 0, S_GLAREGOYLEUP_BLINK, 0}, // S_GLAREGOYLEUP_CHARGE + {SPR_BGAR, FF_ANIMATE|1, 18, {NULL}, 1, 3, S_GLAREGOYLEUP_HOLD, 0}, // S_GLAREGOYLEUP_BLINK + {SPR_BGAR, 1, 9, {NULL}, 0, 0, S_GLAREGOYLEUP_FIRE, 0}, // S_GLAREGOYLEUP_HOLD + {SPR_BGAR, 1, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+45, S_GLAREGOYLEUP_LOOP, 0}, // S_GLAREGOYLEUP_FIRE + {SPR_BGAR, 1, 0, {A_Repeat}, 3, S_GLAREGOYLEUP_FIRE, S_GLAREGOYLEUP_COOLDOWN, 0}, // S_GLAREGOYLEUP_LOOP + {SPR_BGAR, FF_ANIMATE|1, 15, {NULL}, 1, 9, S_GLAREGOYLEUP, 0}, // S_GLAREGOYLEUP_COOLDOWN + + {SPR_BGAR, 0, 22, {NULL}, 0, 0, S_GLAREGOYLEDOWN_CHARGE, 0}, // S_GLAREGOYLEDOWN + {SPR_BGAR, 2, 6, {NULL}, 0, 0, S_GLAREGOYLEDOWN_BLINK, 0}, // S_GLAREGOYLEDOWN_CHARGE + {SPR_BGAR, FF_ANIMATE|1, 18, {NULL}, 1, 3, S_GLAREGOYLEDOWN_HOLD, 0}, // S_GLAREGOYLEDOWN_BLINK + {SPR_BGAR, 1, 9, {NULL}, 0, 0, S_GLAREGOYLEDOWN_FIRE, 0}, // S_GLAREGOYLEDOWN_HOLD + {SPR_BGAR, 1, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16)+315, S_GLAREGOYLEDOWN_LOOP, 0}, // S_GLAREGOYLEDOWN_FIRE + {SPR_BGAR, 1, 0, {A_Repeat}, 3, S_GLAREGOYLEDOWN_FIRE, S_GLAREGOYLEDOWN_COOLDOWN, 0}, // S_GLAREGOYLEDOWN_LOOP + {SPR_BGAR, FF_ANIMATE|1, 15, {NULL}, 1, 9, S_GLAREGOYLEDOWN, 0}, // S_GLAREGOYLEDOWN_COOLDOWN + + {SPR_BGAR, 0, 90, {NULL}, 0, 0, S_GLAREGOYLELONG_CHARGE, 0}, // S_GLAREGOYLELONG + {SPR_BGAR, 2, 6, {NULL}, 0, 0, S_GLAREGOYLELONG_BLINK, 0}, // S_GLAREGOYLELONG_CHARGE + {SPR_BGAR, FF_ANIMATE|1, 18, {NULL}, 1, 3, S_GLAREGOYLELONG_HOLD, 0}, // S_GLAREGOYLELONG_BLINK + {SPR_BGAR, 1, 9, {NULL}, 0, 0, S_GLAREGOYLELONG_FIRE, 0}, // S_GLAREGOYLELONG_HOLD + {SPR_BGAR, 1, 1, {A_TrapShot}, (16<<16)+MT_DEMONFIRE, (30<<16), S_GLAREGOYLELONG_LOOP, 0}, // S_GLAREGOYLELONG_FIRE + {SPR_BGAR, 1, 0, {A_Repeat}, 5, S_GLAREGOYLELONG_FIRE, S_GLAREGOYLELONG_COOLDOWN, 0}, // S_GLAREGOYLELONG_LOOP + {SPR_BGAR, FF_ANIMATE|1, 15, {NULL}, 1, 9, S_GLAREGOYLELONG, 0}, // S_GLAREGOYLELONG_COOLDOWN // Target/Red Crystal - {SPR_RCRY, 0, -1, {NULL}, 0, 0, S_TARGET_IDLE}, // S_TARGET_IDLE - {SPR_RCRY, FF_FULLBRIGHT|1, 0, {A_PlaySound}, sfx_ding, 1, S_TARGET_HIT2}, // S_TARGET_HIT1 - {SPR_RCRY, FF_FULLBRIGHT|1, 45, {A_SetObjectFlags}, MF_PUSHABLE, 2, S_TARGET_RESPAWN}, // S_TARGET_HIT2 - {SPR_RCRY, 1, 0, {A_SpawnObjectRelative}, 0, MT_TARGET, S_NULL}, // S_TARGET_RESPAWN - {SPR_RCRY, FF_FULLBRIGHT|1, -1, {A_SetObjectFlags}, MF_PUSHABLE, 1, S_TARGET_ALLDONE}, // S_TARGET_ALLDONE + {SPR_RCRY, 0, -1, {NULL}, 0, 0, S_TARGET_IDLE, 0}, // S_TARGET_IDLE + {SPR_RCRY, FF_FULLBRIGHT|1, 0, {A_PlaySound}, sfx_ding, 1, S_TARGET_HIT2, 0}, // S_TARGET_HIT1 + {SPR_RCRY, FF_FULLBRIGHT|1, 45, {A_SetObjectFlags}, MF_PUSHABLE, 2, S_TARGET_RESPAWN, 0}, // S_TARGET_HIT2 + {SPR_RCRY, 1, 0, {A_SpawnObjectRelative}, 0, MT_TARGET, S_NULL, 0}, // S_TARGET_RESPAWN + {SPR_RCRY, FF_FULLBRIGHT|1, -1, {A_SetObjectFlags}, MF_PUSHABLE, 1, S_TARGET_ALLDONE, 0}, // S_TARGET_ALLDONE // Green flame - {SPR_CFLM, FF_FULLBRIGHT|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 3, S_GREENFLAME}, // S_GREENFLAME + {SPR_CFLM, FF_FULLBRIGHT|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 3, S_GREENFLAME, 0}, // S_GREENFLAME // ATZ Blue Gargoyle - {SPR_BGAR, 3, -1, {NULL}, 0, 0, S_NULL}, // S_BLUEGARGOYLE + {SPR_BGAR, 3, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BLUEGARGOYLE // Stalagmites - {SPR_STLG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_STG0 - {SPR_STLG, 1, -1, {NULL}, 0, 0, S_NULL}, // S_STG1 - {SPR_STLG, 2, -1, {NULL}, 0, 0, S_NULL}, // S_STG2 - {SPR_STLG, 3, -1, {NULL}, 0, 0, S_NULL}, // S_STG3 - {SPR_STLG, 4, -1, {NULL}, 0, 0, S_NULL}, // S_STG4 - {SPR_STLG, 5, -1, {NULL}, 0, 0, S_NULL}, // S_STG5 - {SPR_STLG, 6, -1, {NULL}, 0, 0, S_NULL}, // S_STG6 - {SPR_STLG, 7, -1, {NULL}, 0, 0, S_NULL}, // S_STG7 - {SPR_STLG, 8, -1, {NULL}, 0, 0, S_NULL}, // S_STG8 - {SPR_STLG, 9, -1, {NULL}, 0, 0, S_NULL}, // S_STG9 + {SPR_STLG, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_STG0 + {SPR_STLG, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_STG1 + {SPR_STLG, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_STG2 + {SPR_STLG, 3, -1, {NULL}, 0, 0, S_NULL, 0}, // S_STG3 + {SPR_STLG, 4, -1, {NULL}, 0, 0, S_NULL, 0}, // S_STG4 + {SPR_STLG, 5, -1, {NULL}, 0, 0, S_NULL, 0}, // S_STG5 + {SPR_STLG, 6, -1, {NULL}, 0, 0, S_NULL, 0}, // S_STG6 + {SPR_STLG, 7, -1, {NULL}, 0, 0, S_NULL, 0}, // S_STG7 + {SPR_STLG, 8, -1, {NULL}, 0, 0, S_NULL, 0}, // S_STG8 + {SPR_STLG, 9, -1, {NULL}, 0, 0, S_NULL, 0}, // S_STG9 // Xmas-specific stuff - {SPR_XMS1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_XMASPOLE - {SPR_XMS2, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CANDYCANE - {SPR_XMS3, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SNOWMAN - {SPR_XMS3, 1, -1, {NULL}, 0, 0, S_NULL}, // S_SNOWMANHAT - {SPR_XMS4, 0, -1, {NULL}, 0, 0, S_NULL}, // S_LAMPPOST1 - {SPR_XMS4, 1, -1, {NULL}, 0, 0, S_NULL}, // S_LAMPPOST2 - {SPR_XMS5, 0, -1, {NULL}, 0, 0, S_NULL}, // S_HANGSTAR - {SPR_XMS6, 0, -1, {NULL}, 0, 0, S_NULL}, // S_MISTLETOE + {SPR_XMS1, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_XMASPOLE + {SPR_XMS2, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CANDYCANE + {SPR_XMS3, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SNOWMAN + {SPR_XMS3, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SNOWMANHAT + {SPR_XMS4, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_LAMPPOST1 + {SPR_XMS4, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_LAMPPOST2 + {SPR_XMS5, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_HANGSTAR + {SPR_XMS6, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_MISTLETOE + {SPR_SNTT, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SSZTREE + {SPR_SNTT, 1|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SSZTREE_BRANCH + {SPR_SSTT, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SSZTREE2 + {SPR_SSTT, 1|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SSZTREE2_BRANCH // Xmas GFZ bushes - {SPR_BUS3, 1, -1, {NULL}, 0, 0, S_NULL}, // S_XMASBLUEBERRYBUSH - {SPR_BUS1, 1, -1, {NULL}, 0, 0, S_NULL}, // S_XMASBERRYBUSH - {SPR_BUS2, 1, -1, {NULL}, 0, 0, S_NULL}, // S_XMASBUSH + {SPR_BUS3, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_XMASBLUEBERRYBUSH + {SPR_BUS1, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_XMASBERRYBUSH + {SPR_BUS2, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_XMASBUSH // FHZ - {SPR_FHZI, 0, -1, {NULL}, 0, 0, S_NULL}, // S_FHZICE1 - {SPR_FHZI, 1, -1, {NULL}, 0, 0, S_NULL}, // S_FHZICE2 - {SPR_ROSY, 16, 8, {NULL}, 0, 0, S_ROSY_IDLE2}, // S_ROSY_IDLE1 - {SPR_ROSY, 17, 4, {NULL}, 0, 0, S_ROSY_IDLE3}, // S_ROSY_IDLE2 - {SPR_ROSY, 18, 8, {NULL}, 0, 0, S_ROSY_IDLE4}, // S_ROSY_IDLE3 - {SPR_ROSY, 17, 4, {NULL}, 0, 0, S_ROSY_IDLE1}, // S_ROSY_IDLE4 - {SPR_ROSY, 14, -1, {NULL}, 1, 0, S_NULL}, // S_ROSY_JUMP - {SPR_ROSY, 5, -1, {NULL}, 7, 0, S_NULL}, // S_ROSY_WALK - {SPR_ROSY, 19, -1, {NULL}, 0, 0, S_NULL}, // S_ROSY_HUG - {SPR_ROSY, 13, -1, {NULL}, 0, 0, S_NULL}, // S_ROSY_PAIN - {SPR_ROSY, 1|FF_ANIMATE, -1, {NULL}, 3, 16, S_NULL}, // S_ROSY_STND - {SPR_ROSY, 20|FF_ANIMATE, TICRATE, {NULL}, 3, 4, S_ROSY_WALK}, // S_ROSY_UNHAPPY + {SPR_FHZI, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_FHZICE1 + {SPR_FHZI, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_FHZICE2 + // Amy FHZ cameo + {SPR_PLAY, SPR2_CNT1|FF_ANIMATE, -1, {NULL}, 0, 0, S_NULL, 0}, // S_ROSY_IDLE + {SPR_PLAY, SPR2_MSC0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_ROSY_JUMP + {SPR_PLAY, SPR2_MSC1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_ROSY_FALL + {SPR_PLAY, SPR2_WALK, -1, {NULL}, 7, 0, S_NULL, 0}, // S_ROSY_WALK + {SPR_PLAY, SPR2_MSC2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_ROSY_HUG + {SPR_PLAY, SPR2_PAIN, -1, {NULL}, 0, 0, S_NULL, 0}, // S_ROSY_PAIN + {SPR_PLAY, SPR2_WAIT|FF_ANIMATE, -1, {NULL}, 0, 5, S_NULL, 0}, // S_ROSY_STND + {SPR_PLAY, SPR2_MSC3|FF_ANIMATE, TICRATE, {NULL}, 0, 4, S_ROSY_WALK, 0}, // S_ROSY_UNHAPPY // Halloween Scenery // Pumpkins - {SPR_PUMK, 0, -1, {NULL}, 0, 0, S_NULL}, // S_JACKO1 - {SPR_PUMK, 3|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO1OVERLAY_2}, // S_JACKO1OVERLAY_1 - {SPR_PUMK, 4|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO1OVERLAY_3}, // S_JACKO1OVERLAY_2 - {SPR_PUMK, 5|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO1OVERLAY_4}, // S_JACKO1OVERLAY_3 - {SPR_PUMK, 4|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO1OVERLAY_1}, // S_JACKO1OVERLAY_4 - {SPR_PUMK, 1, -1, {NULL}, 0, 0, S_NULL}, // S_JACKO2 - {SPR_PUMK, 6|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO2OVERLAY_2}, // S_JACKO2OVERLAY_1 - {SPR_PUMK, 7|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO2OVERLAY_3}, // S_JACKO2OVERLAY_2 - {SPR_PUMK, 8|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO2OVERLAY_4}, // S_JACKO2OVERLAY_3 - {SPR_PUMK, 7|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO2OVERLAY_1}, // S_JACKO2OVERLAY_4 - {SPR_PUMK, 2, -1, {NULL}, 0, 0, S_NULL}, // S_JACKO3 - {SPR_PUMK, 9|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO3OVERLAY_2}, // S_JACKO3OVERLAY_1 - {SPR_PUMK, 10|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO3OVERLAY_3}, // S_JACKO3OVERLAY_2 - {SPR_PUMK, 11|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO3OVERLAY_4}, // S_JACKO3OVERLAY_3 - {SPR_PUMK, 10|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO3OVERLAY_1}, // S_JACKO3OVERLAY_4 + {SPR_PUMK, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_JACKO1 + {SPR_PUMK, 3|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO1OVERLAY_2, 0}, // S_JACKO1OVERLAY_1 + {SPR_PUMK, 4|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO1OVERLAY_3, 0}, // S_JACKO1OVERLAY_2 + {SPR_PUMK, 5|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO1OVERLAY_4, 0}, // S_JACKO1OVERLAY_3 + {SPR_PUMK, 4|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO1OVERLAY_1, 0}, // S_JACKO1OVERLAY_4 + {SPR_PUMK, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_JACKO2 + {SPR_PUMK, 6|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO2OVERLAY_2, 0}, // S_JACKO2OVERLAY_1 + {SPR_PUMK, 7|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO2OVERLAY_3, 0}, // S_JACKO2OVERLAY_2 + {SPR_PUMK, 8|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO2OVERLAY_4, 0}, // S_JACKO2OVERLAY_3 + {SPR_PUMK, 7|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO2OVERLAY_1, 0}, // S_JACKO2OVERLAY_4 + {SPR_PUMK, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_JACKO3 + {SPR_PUMK, 9|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO3OVERLAY_2, 0}, // S_JACKO3OVERLAY_1 + {SPR_PUMK, 10|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO3OVERLAY_3, 0}, // S_JACKO3OVERLAY_2 + {SPR_PUMK, 11|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO3OVERLAY_4, 0}, // S_JACKO3OVERLAY_3 + {SPR_PUMK, 10|FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_JACKO3OVERLAY_1, 0}, // S_JACKO3OVERLAY_4 // Dr Seuss Trees - {SPR_HHPL, 2, -1, {A_ConnectToGround}, MT_HHZTREE_PART, 0, S_NULL}, // S_HHZTREE_TOP, - {SPR_HHPL, 1, -1, {NULL}, 0, 0, S_NULL}, // S_HHZTREE_TRUNK, - {SPR_HHPL, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_HHZTREE_LEAF, + {SPR_HHPL, 2, -1, {A_ConnectToGround}, MT_HHZTREE_PART, 0, S_NULL, 0}, // S_HHZTREE_TOP, + {SPR_HHPL, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_HHZTREE_TRUNK, + {SPR_HHPL, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL, 0}, // S_HHZTREE_LEAF, // Mushroom - {SPR_SHRM, 4, 3, {NULL}, 0, 0, S_HHZSHROOM_2}, // S_HHZSHROOM_1, - {SPR_SHRM, 3, 3, {NULL}, 0, 0, S_HHZSHROOM_3}, // S_HHZSHROOM_2, - {SPR_SHRM, 2, 2, {NULL}, 0, 0, S_HHZSHROOM_4}, // S_HHZSHROOM_3, - {SPR_SHRM, 1, 1, {NULL}, 0, 0, S_HHZSHROOM_5}, // S_HHZSHROOM_4, - {SPR_SHRM, 0, 1, {NULL}, 0, 0, S_HHZSHROOM_6}, // S_HHZSHROOM_5, - {SPR_SHRM, 1, 4, {NULL}, 0, 0, S_HHZSHROOM_7}, // S_HHZSHROOM_6, - {SPR_SHRM, 2, 2, {NULL}, 0, 0, S_HHZSHROOM_8}, // S_HHZSHROOM_7, - {SPR_SHRM, 3, 3, {NULL}, 0, 0, S_HHZSHROOM_9}, // S_HHZSHROOM_8, - {SPR_SHRM, 4, 3, {NULL}, 0, 0, S_HHZSHROOM_10}, // S_HHZSHROOM_9, - {SPR_SHRM, 3, 3, {NULL}, 0, 0, S_HHZSHROOM_11}, // S_HHZSHROOM_10, - {SPR_SHRM, 5, 2, {NULL}, 0, 0, S_HHZSHROOM_12}, // S_HHZSHROOM_11, - {SPR_SHRM, 6, 1, {NULL}, 0, 0, S_HHZSHROOM_13}, // S_HHZSHROOM_12, - {SPR_SHRM, 7, 1, {NULL}, 0, 0, S_HHZSHROOM_14}, // S_HHZSHROOM_13, - {SPR_SHRM, 6, 4, {NULL}, 0, 0, S_HHZSHROOM_15}, // S_HHZSHROOM_14, - {SPR_SHRM, 5, 2, {NULL}, 0, 0, S_HHZSHROOM_16}, // S_HHZSHROOM_15, - {SPR_SHRM, 3, 3, {NULL}, 0, 0, S_HHZSHROOM_1}, // S_HHZSHROOM_16, + {SPR_SHRM, 4, 3, {NULL}, 0, 0, S_HHZSHROOM_2, 0}, // S_HHZSHROOM_1, + {SPR_SHRM, 3, 3, {NULL}, 0, 0, S_HHZSHROOM_3, 0}, // S_HHZSHROOM_2, + {SPR_SHRM, 2, 2, {NULL}, 0, 0, S_HHZSHROOM_4, 0}, // S_HHZSHROOM_3, + {SPR_SHRM, 1, 1, {NULL}, 0, 0, S_HHZSHROOM_5, 0}, // S_HHZSHROOM_4, + {SPR_SHRM, 0, 1, {NULL}, 0, 0, S_HHZSHROOM_6, 0}, // S_HHZSHROOM_5, + {SPR_SHRM, 1, 4, {NULL}, 0, 0, S_HHZSHROOM_7, 0}, // S_HHZSHROOM_6, + {SPR_SHRM, 2, 2, {NULL}, 0, 0, S_HHZSHROOM_8, 0}, // S_HHZSHROOM_7, + {SPR_SHRM, 3, 3, {NULL}, 0, 0, S_HHZSHROOM_9, 0}, // S_HHZSHROOM_8, + {SPR_SHRM, 4, 3, {NULL}, 0, 0, S_HHZSHROOM_10, 0}, // S_HHZSHROOM_9, + {SPR_SHRM, 3, 3, {NULL}, 0, 0, S_HHZSHROOM_11, 0}, // S_HHZSHROOM_10, + {SPR_SHRM, 5, 2, {NULL}, 0, 0, S_HHZSHROOM_12, 0}, // S_HHZSHROOM_11, + {SPR_SHRM, 6, 1, {NULL}, 0, 0, S_HHZSHROOM_13, 0}, // S_HHZSHROOM_12, + {SPR_SHRM, 7, 1, {NULL}, 0, 0, S_HHZSHROOM_14, 0}, // S_HHZSHROOM_13, + {SPR_SHRM, 6, 4, {NULL}, 0, 0, S_HHZSHROOM_15, 0}, // S_HHZSHROOM_14, + {SPR_SHRM, 5, 2, {NULL}, 0, 0, S_HHZSHROOM_16, 0}, // S_HHZSHROOM_15, + {SPR_SHRM, 3, 3, {NULL}, 0, 0, S_HHZSHROOM_1, 0}, // S_HHZSHROOM_16, // Misc - {SPR_HHZM, 0, -1, {NULL}, 0, 0, S_NULL}, // S_HHZGRASS, - {SPR_HHZM, 1, -1, {NULL}, 0, 0, S_NULL}, // S_HHZTENT1, - {SPR_HHZM, 2, -1, {NULL}, 0, 0, S_NULL}, // S_HHZTENT2, - {SPR_HHZM, 4, -1, {NULL}, 0, 0, S_NULL}, // S_HHZSTALAGMITE_TALL, - {SPR_HHZM, 5, -1, {NULL}, 0, 0, S_NULL}, // S_HHZSTALAGMITE_SHORT, + {SPR_HHZM, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_HHZGRASS, + {SPR_HHZM, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_HHZTENT1, + {SPR_HHZM, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_HHZTENT2, + {SPR_HHZM, 4, -1, {NULL}, 0, 0, S_NULL, 0}, // S_HHZSTALAGMITE_TALL, + {SPR_HHZM, 5, -1, {NULL}, 0, 0, S_NULL, 0}, // S_HHZSTALAGMITE_SHORT, // Loads of Botanic Serenity bullshit - {SPR_BSZ1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BSZTALLFLOWER_RED - {SPR_BSZ1, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BSZTALLFLOWER_PURPLE - {SPR_BSZ1, 2, -1, {NULL}, 0, 0, S_NULL}, // S_BSZTALLFLOWER_BLUE - {SPR_BSZ1, 3, -1, {NULL}, 0, 0, S_NULL}, // S_BSZTALLFLOWER_CYAN - {SPR_BSZ1, 4, -1, {NULL}, 0, 0, S_NULL}, // S_BSZTALLFLOWER_YELLOW - {SPR_BSZ1, 5, -1, {NULL}, 0, 0, S_NULL}, // S_BSZTALLFLOWER_ORANGE - {SPR_BSZ2, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BSZFLOWER_RED - {SPR_BSZ2, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BSZFLOWER_PURPLE - {SPR_BSZ2, 2, -1, {NULL}, 0, 0, S_NULL}, // S_BSZFLOWER_BLUE - {SPR_BSZ2, 3, -1, {NULL}, 0, 0, S_NULL}, // S_BSZFLOWER_CYAN - {SPR_BSZ2, 4, -1, {NULL}, 0, 0, S_NULL}, // S_BSZFLOWER_YELLOW - {SPR_BSZ2, 5, -1, {NULL}, 0, 0, S_NULL}, // S_BSZFLOWER_ORANGE - {SPR_BSZ3, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BSZSHORTFLOWER_RED - {SPR_BSZ3, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BSZSHORTFLOWER_PURPLE - {SPR_BSZ3, 2, -1, {NULL}, 0, 0, S_NULL}, // S_BSZSHORTFLOWER_BLUE - {SPR_BSZ3, 3, -1, {NULL}, 0, 0, S_NULL}, // S_BSZSHORTFLOWER_CYAN - {SPR_BSZ3, 4, -1, {NULL}, 0, 0, S_NULL}, // S_BSZSHORTFLOWER_YELLOW - {SPR_BSZ3, 5, -1, {NULL}, 0, 0, S_NULL}, // S_BSZSHORTFLOWER_ORANGE - {SPR_BST1, FF_ANIMATE, -1, {NULL}, 11, 4, S_NULL}, // S_BSZTULIP_RED - {SPR_BST2, FF_ANIMATE, -1, {NULL}, 11, 4, S_NULL}, // S_BSZTULIP_PURPLE - {SPR_BST3, FF_ANIMATE, -1, {NULL}, 11, 4, S_NULL}, // S_BSZTULIP_BLUE - {SPR_BST4, FF_ANIMATE, -1, {NULL}, 11, 4, S_NULL}, // S_BSZTULIP_CYAN - {SPR_BST5, FF_ANIMATE, -1, {NULL}, 11, 4, S_NULL}, // S_BSZTULIP_YELLOW - {SPR_BST6, FF_ANIMATE, -1, {NULL}, 11, 4, S_NULL}, // S_BSZTULIP_ORANGE - {SPR_BSZ5, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BSZCLUSTER_RED - {SPR_BSZ5, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BSZCLUSTER_PURPLE - {SPR_BSZ5, 2, -1, {NULL}, 0, 0, S_NULL}, // S_BSZCLUSTER_BLUE - {SPR_BSZ5, 3, -1, {NULL}, 0, 0, S_NULL}, // S_BSZCLUSTER_CYAN - {SPR_BSZ5, 4, -1, {NULL}, 0, 0, S_NULL}, // S_BSZCLUSTER_YELLOW - {SPR_BSZ5, 5, -1, {NULL}, 0, 0, S_NULL}, // S_BSZCLUSTER_ORANGE - {SPR_BSZ6, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BSZBUSH_RED - {SPR_BSZ6, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BSZBUSH_PURPLE - {SPR_BSZ6, 2, -1, {NULL}, 0, 0, S_NULL}, // S_BSZBUSH_BLUE - {SPR_BSZ6, 3, -1, {NULL}, 0, 0, S_NULL}, // S_BSZBUSH_CYAN - {SPR_BSZ6, 4, -1, {NULL}, 0, 0, S_NULL}, // S_BSZBUSH_YELLOW - {SPR_BSZ6, 5, -1, {NULL}, 0, 0, S_NULL}, // S_BSZBUSH_ORANGE - {SPR_BSZ7, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BSZVINE_RED - {SPR_BSZ7, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BSZVINE_PURPLE - {SPR_BSZ7, 2, -1, {NULL}, 0, 0, S_NULL}, // S_BSZVINE_BLUE - {SPR_BSZ7, 3, -1, {NULL}, 0, 0, S_NULL}, // S_BSZVINE_CYAN - {SPR_BSZ7, 4, -1, {NULL}, 0, 0, S_NULL}, // S_BSZVINE_YELLOW - {SPR_BSZ7, 5, -1, {NULL}, 0, 0, S_NULL}, // S_BSZVINE_ORANGE - {SPR_BSZ8, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BSZSHRUB - {SPR_BSZ8, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BSZCLOVER - {SPR_BSZ8, 2, -1, {NULL}, 0, 0, S_NULL}, // S_BIG_PALMTREE_TRUNK - {SPR_BSZ8, 3, -1, {A_ConnectToGround}, MT_BIG_PALMTREE_TRUNK, 0, S_NULL}, // S_BIG_PALMTREE_TOP - {SPR_BSZ8, 4, -1, {NULL}, 0, 0, S_NULL}, // S_PALMTREE_TRUNK - {SPR_BSZ8, 5, -1, {A_ConnectToGround}, MT_PALMTREE_TRUNK, 0, S_NULL}, // S_PALMTREE_TOP + {SPR_BSZ1, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZTALLFLOWER_RED + {SPR_BSZ1, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZTALLFLOWER_PURPLE + {SPR_BSZ1, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZTALLFLOWER_BLUE + {SPR_BSZ1, 3, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZTALLFLOWER_CYAN + {SPR_BSZ1, 4, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZTALLFLOWER_YELLOW + {SPR_BSZ1, 5, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZTALLFLOWER_ORANGE + {SPR_BSZ2, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZFLOWER_RED + {SPR_BSZ2, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZFLOWER_PURPLE + {SPR_BSZ2, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZFLOWER_BLUE + {SPR_BSZ2, 3, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZFLOWER_CYAN + {SPR_BSZ2, 4, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZFLOWER_YELLOW + {SPR_BSZ2, 5, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZFLOWER_ORANGE + {SPR_BSZ3, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZSHORTFLOWER_RED + {SPR_BSZ3, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZSHORTFLOWER_PURPLE + {SPR_BSZ3, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZSHORTFLOWER_BLUE + {SPR_BSZ3, 3, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZSHORTFLOWER_CYAN + {SPR_BSZ3, 4, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZSHORTFLOWER_YELLOW + {SPR_BSZ3, 5, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZSHORTFLOWER_ORANGE + {SPR_BST1, FF_ANIMATE, -1, {NULL}, 11, 4, S_NULL, 0}, // S_BSZTULIP_RED + {SPR_BST2, FF_ANIMATE, -1, {NULL}, 11, 4, S_NULL, 0}, // S_BSZTULIP_PURPLE + {SPR_BST3, FF_ANIMATE, -1, {NULL}, 11, 4, S_NULL, 0}, // S_BSZTULIP_BLUE + {SPR_BST4, FF_ANIMATE, -1, {NULL}, 11, 4, S_NULL, 0}, // S_BSZTULIP_CYAN + {SPR_BST5, FF_ANIMATE, -1, {NULL}, 11, 4, S_NULL, 0}, // S_BSZTULIP_YELLOW + {SPR_BST6, FF_ANIMATE, -1, {NULL}, 11, 4, S_NULL, 0}, // S_BSZTULIP_ORANGE + {SPR_BSZ5, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZCLUSTER_RED + {SPR_BSZ5, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZCLUSTER_PURPLE + {SPR_BSZ5, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZCLUSTER_BLUE + {SPR_BSZ5, 3, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZCLUSTER_CYAN + {SPR_BSZ5, 4, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZCLUSTER_YELLOW + {SPR_BSZ5, 5, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZCLUSTER_ORANGE + {SPR_BSZ6, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZBUSH_RED + {SPR_BSZ6, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZBUSH_PURPLE + {SPR_BSZ6, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZBUSH_BLUE + {SPR_BSZ6, 3, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZBUSH_CYAN + {SPR_BSZ6, 4, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZBUSH_YELLOW + {SPR_BSZ6, 5, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZBUSH_ORANGE + {SPR_BSZ7, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZVINE_RED + {SPR_BSZ7, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZVINE_PURPLE + {SPR_BSZ7, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZVINE_BLUE + {SPR_BSZ7, 3, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZVINE_CYAN + {SPR_BSZ7, 4, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZVINE_YELLOW + {SPR_BSZ7, 5, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZVINE_ORANGE + {SPR_BSZ8, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZSHRUB + {SPR_BSZ8, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BSZCLOVER + {SPR_BSZ8, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BIG_PALMTREE_TRUNK + {SPR_BSZ8, 3, -1, {A_ConnectToGround}, MT_BIG_PALMTREE_TRUNK, 0, S_NULL, 0}, // S_BIG_PALMTREE_TOP + {SPR_BSZ8, 4, -1, {NULL}, 0, 0, S_NULL, 0}, // S_PALMTREE_TRUNK + {SPR_BSZ8, 5, -1, {A_ConnectToGround}, MT_PALMTREE_TRUNK, 0, S_NULL, 0}, // S_PALMTREE_TOP // Disco ball - {SPR_DBAL, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_DBALL2}, // S_DBALL1 - {SPR_DBAL, FF_FULLBRIGHT|1, 5, {NULL}, 0, 0, S_DBALL3}, // S_DBALL2 - {SPR_DBAL, FF_FULLBRIGHT|2, 5, {NULL}, 0, 0, S_DBALL4}, // S_DBALL3 - {SPR_DBAL, FF_FULLBRIGHT|3, 5, {NULL}, 0, 0, S_DBALL5}, // S_DBALL4 - {SPR_DBAL, FF_FULLBRIGHT|4, 5, {NULL}, 0, 0, S_DBALL6}, // S_DBALL5 - {SPR_DBAL, FF_FULLBRIGHT|5, 5, {NULL}, 0, 0, S_DBALL1}, // S_DBALL6 + {SPR_DBAL, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_DBALL2, 0}, // S_DBALL1 + {SPR_DBAL, FF_FULLBRIGHT|1, 5, {NULL}, 0, 0, S_DBALL3, 0}, // S_DBALL2 + {SPR_DBAL, FF_FULLBRIGHT|2, 5, {NULL}, 0, 0, S_DBALL4, 0}, // S_DBALL3 + {SPR_DBAL, FF_FULLBRIGHT|3, 5, {NULL}, 0, 0, S_DBALL5, 0}, // S_DBALL4 + {SPR_DBAL, FF_FULLBRIGHT|4, 5, {NULL}, 0, 0, S_DBALL6, 0}, // S_DBALL5 + {SPR_DBAL, FF_FULLBRIGHT|5, 5, {NULL}, 0, 0, S_DBALL1, 0}, // S_DBALL6 + + {SPR_ESTA, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EGGSTATUE2 - {SPR_ESTA, 1, -1, {NULL}, 0, 0, S_NULL}, // S_EGGSTATUE2 + {SPR_GINE, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_GINE + {SPR_PPAL, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_PPAL + {SPR_PPAL, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_PPEL // Shield Orb - {SPR_ARMA, FF_TRANS40 , 2, {NULL}, 0, 0, S_ARMA2 }, // S_ARMA1 - {SPR_ARMA, FF_TRANS40| 1, 2, {NULL}, 0, 0, S_ARMA3 }, // S_ARMA2 - {SPR_ARMA, FF_TRANS40| 2, 2, {NULL}, 0, 0, S_ARMA4 }, // S_ARMA3 - {SPR_ARMA, FF_TRANS40| 3, 2, {NULL}, 0, 0, S_ARMA5 }, // S_ARMA4 - {SPR_ARMA, FF_TRANS40| 4, 2, {NULL}, 0, 0, S_ARMA6 }, // S_ARMA5 - {SPR_ARMA, FF_TRANS40| 5, 2, {NULL}, 0, 0, S_ARMA7 }, // S_ARMA6 - {SPR_ARMA, FF_TRANS40| 6, 2, {NULL}, 0, 0, S_ARMA8 }, // S_ARMA7 - {SPR_ARMA, FF_TRANS40| 7, 2, {NULL}, 0, 0, S_ARMA9 }, // S_ARMA8 - {SPR_ARMA, FF_TRANS40| 8, 2, {NULL}, 0, 0, S_ARMA10}, // S_ARMA9 - {SPR_ARMA, FF_TRANS40| 9, 2, {NULL}, 0, 0, S_ARMA11}, // S_ARMA10 - {SPR_ARMA, FF_TRANS40|10, 2, {NULL}, 0, 0, S_ARMA12}, // S_ARMA11 - {SPR_ARMA, FF_TRANS40|11, 2, {NULL}, 0, 0, S_ARMA13}, // S_ARMA12 - {SPR_ARMA, FF_TRANS40|12, 2, {NULL}, 0, 0, S_ARMA14}, // S_ARMA13 - {SPR_ARMA, FF_TRANS40|13, 2, {NULL}, 0, 0, S_ARMA15}, // S_ARMA14 - {SPR_ARMA, FF_TRANS40|14, 2, {NULL}, 0, 0, S_ARMA16}, // S_ARMA15 - {SPR_ARMA, FF_TRANS40|15, 2, {NULL}, 0, 0, S_ARMA1 }, // S_ARMA16 - - {SPR_ARMF, FF_FULLBRIGHT , 2, {NULL}, 0, 0, S_ARMF2 }, // S_ARMF1 - {SPR_ARMF, FF_FULLBRIGHT| 1, 2, {NULL}, 0, 0, S_ARMF3 }, // S_ARMF2 - {SPR_ARMF, FF_FULLBRIGHT| 2, 2, {NULL}, 0, 0, S_ARMF4 }, // S_ARMF3 - {SPR_ARMF, FF_FULLBRIGHT| 3, 2, {NULL}, 0, 0, S_ARMF5 }, // S_ARMF4 - {SPR_ARMF, FF_FULLBRIGHT| 4, 2, {NULL}, 0, 0, S_ARMF6 }, // S_ARMF5 - {SPR_ARMF, FF_FULLBRIGHT| 5, 2, {NULL}, 0, 0, S_ARMF7 }, // S_ARMF6 - {SPR_ARMF, FF_FULLBRIGHT| 6, 2, {NULL}, 0, 0, S_ARMF8 }, // S_ARMF7 - {SPR_ARMF, FF_FULLBRIGHT| 7, 2, {NULL}, 0, 0, S_ARMF9 }, // S_ARMF8 - {SPR_ARMF, FF_FULLBRIGHT| 8, 2, {NULL}, 0, 0, S_ARMF10}, // S_ARMF9 - {SPR_ARMF, FF_FULLBRIGHT| 9, 2, {NULL}, 0, 0, S_ARMF11}, // S_ARMF10 - {SPR_ARMF, FF_FULLBRIGHT|10, 2, {NULL}, 0, 0, S_ARMF12}, // S_ARMF11 - {SPR_ARMF, FF_FULLBRIGHT|11, 2, {NULL}, 0, 0, S_ARMF13}, // S_ARMF12 - {SPR_ARMF, FF_FULLBRIGHT|12, 2, {NULL}, 0, 0, S_ARMF14}, // S_ARMF13 - {SPR_ARMF, FF_FULLBRIGHT|13, 2, {NULL}, 0, 0, S_ARMF15}, // S_ARMF14 - {SPR_ARMF, FF_FULLBRIGHT|14, 2, {NULL}, 0, 0, S_ARMF16}, // S_ARMF15 - {SPR_ARMF, FF_FULLBRIGHT|15, 2, {NULL}, 0, 0, S_ARMF17}, // S_ARMF16 - {SPR_ARMB, FF_FULLBRIGHT , 2, {NULL}, 0, 0, S_ARMF18}, // S_ARMF17 - {SPR_ARMB, FF_FULLBRIGHT| 1, 2, {NULL}, 0, 0, S_ARMF19}, // S_ARMF18 - {SPR_ARMB, FF_FULLBRIGHT| 2, 2, {NULL}, 0, 0, S_ARMF20}, // S_ARMF19 - {SPR_ARMB, FF_FULLBRIGHT| 3, 2, {NULL}, 0, 0, S_ARMF21}, // S_ARMF20 - {SPR_ARMB, FF_FULLBRIGHT| 4, 2, {NULL}, 0, 0, S_ARMF22}, // S_ARMF21 - {SPR_ARMB, FF_FULLBRIGHT| 5, 2, {NULL}, 0, 0, S_ARMF23}, // S_ARMF22 - {SPR_ARMB, FF_FULLBRIGHT| 6, 2, {NULL}, 0, 0, S_ARMF24}, // S_ARMF23 - {SPR_ARMB, FF_FULLBRIGHT| 7, 2, {NULL}, 0, 0, S_ARMF25}, // S_ARMF24 - {SPR_ARMB, FF_FULLBRIGHT| 8, 2, {NULL}, 0, 0, S_ARMF26}, // S_ARMF25 - {SPR_ARMB, FF_FULLBRIGHT| 9, 2, {NULL}, 0, 0, S_ARMF27}, // S_ARMF26 - {SPR_ARMB, FF_FULLBRIGHT|10, 2, {NULL}, 0, 0, S_ARMF28}, // S_ARMF27 - {SPR_ARMB, FF_FULLBRIGHT|11, 2, {NULL}, 0, 0, S_ARMF29}, // S_ARMF28 - {SPR_ARMB, FF_FULLBRIGHT|12, 2, {NULL}, 0, 0, S_ARMF30}, // S_ARMF29 - {SPR_ARMB, FF_FULLBRIGHT|13, 2, {NULL}, 0, 0, S_ARMF31}, // S_ARMF30 - {SPR_ARMB, FF_FULLBRIGHT|14, 2, {NULL}, 0, 0, S_ARMF32}, // S_ARMF31 - {SPR_ARMB, FF_FULLBRIGHT|15, 2, {NULL}, 0, 0, S_ARMF1 }, // S_ARMF32 - - {SPR_ARMB, FF_FULLBRIGHT , 2, {NULL}, 1, 0, S_ARMB2 }, // S_ARMB1 - {SPR_ARMB, FF_FULLBRIGHT| 1, 2, {NULL}, 1, 0, S_ARMB3 }, // S_ARMB2 - {SPR_ARMB, FF_FULLBRIGHT| 2, 2, {NULL}, 1, 0, S_ARMB4 }, // S_ARMB3 - {SPR_ARMB, FF_FULLBRIGHT| 3, 2, {NULL}, 1, 0, S_ARMB5 }, // S_ARMB4 - {SPR_ARMB, FF_FULLBRIGHT| 4, 2, {NULL}, 1, 0, S_ARMB6 }, // S_ARMB5 - {SPR_ARMB, FF_FULLBRIGHT| 5, 2, {NULL}, 1, 0, S_ARMB7 }, // S_ARMB6 - {SPR_ARMB, FF_FULLBRIGHT| 6, 2, {NULL}, 1, 0, S_ARMB8 }, // S_ARMB7 - {SPR_ARMB, FF_FULLBRIGHT| 7, 2, {NULL}, 1, 0, S_ARMB9 }, // S_ARMB8 - {SPR_ARMB, FF_FULLBRIGHT| 8, 2, {NULL}, 1, 0, S_ARMB10}, // S_ARMB9 - {SPR_ARMB, FF_FULLBRIGHT| 9, 2, {NULL}, 1, 0, S_ARMB11}, // S_ARMB10 - {SPR_ARMB, FF_FULLBRIGHT|10, 2, {NULL}, 1, 0, S_ARMB12}, // S_ARMB11 - {SPR_ARMB, FF_FULLBRIGHT|11, 2, {NULL}, 1, 0, S_ARMB13}, // S_ARMB12 - {SPR_ARMB, FF_FULLBRIGHT|12, 2, {NULL}, 1, 0, S_ARMB14}, // S_ARMB13 - {SPR_ARMB, FF_FULLBRIGHT|13, 2, {NULL}, 1, 0, S_ARMB15}, // S_ARMB14 - {SPR_ARMB, FF_FULLBRIGHT|14, 2, {NULL}, 1, 0, S_ARMB16}, // S_ARMB15 - {SPR_ARMB, FF_FULLBRIGHT|15, 2, {NULL}, 1, 0, S_ARMB17}, // S_ARMB16 - {SPR_ARMF, FF_FULLBRIGHT , 2, {NULL}, 1, 0, S_ARMB18}, // S_ARMB17 - {SPR_ARMF, FF_FULLBRIGHT| 1, 2, {NULL}, 1, 0, S_ARMB19}, // S_ARMB18 - {SPR_ARMF, FF_FULLBRIGHT| 2, 2, {NULL}, 1, 0, S_ARMB20}, // S_ARMB19 - {SPR_ARMF, FF_FULLBRIGHT| 3, 2, {NULL}, 1, 0, S_ARMB21}, // S_ARMB20 - {SPR_ARMF, FF_FULLBRIGHT| 4, 2, {NULL}, 1, 0, S_ARMB22}, // S_ARMB21 - {SPR_ARMF, FF_FULLBRIGHT| 5, 2, {NULL}, 1, 0, S_ARMB23}, // S_ARMB22 - {SPR_ARMF, FF_FULLBRIGHT| 6, 2, {NULL}, 1, 0, S_ARMB24}, // S_ARMB23 - {SPR_ARMF, FF_FULLBRIGHT| 7, 2, {NULL}, 1, 0, S_ARMB25}, // S_ARMB24 - {SPR_ARMF, FF_FULLBRIGHT| 8, 2, {NULL}, 1, 0, S_ARMB26}, // S_ARMB25 - {SPR_ARMF, FF_FULLBRIGHT| 9, 2, {NULL}, 1, 0, S_ARMB27}, // S_ARMB26 - {SPR_ARMF, FF_FULLBRIGHT|10, 2, {NULL}, 1, 0, S_ARMB28}, // S_ARMB27 - {SPR_ARMF, FF_FULLBRIGHT|11, 2, {NULL}, 1, 0, S_ARMB29}, // S_ARMB28 - {SPR_ARMF, FF_FULLBRIGHT|12, 2, {NULL}, 1, 0, S_ARMB30}, // S_ARMB29 - {SPR_ARMF, FF_FULLBRIGHT|13, 2, {NULL}, 1, 0, S_ARMB31}, // S_ARMB30 - {SPR_ARMF, FF_FULLBRIGHT|14, 2, {NULL}, 1, 0, S_ARMB32}, // S_ARMB31 - {SPR_ARMF, FF_FULLBRIGHT|15, 2, {NULL}, 1, 0, S_ARMB1 }, // S_ARMB32 - - {SPR_WIND, FF_TRANS70 , 2, {NULL}, 0, 0, S_WIND2}, // S_WIND1 - {SPR_WIND, FF_TRANS70|1, 2, {NULL}, 0, 0, S_WIND3}, // S_WIND2 - {SPR_WIND, FF_TRANS70|2, 2, {NULL}, 0, 0, S_WIND4}, // S_WIND3 - {SPR_WIND, FF_TRANS70|3, 2, {NULL}, 0, 0, S_WIND5}, // S_WIND4 - {SPR_WIND, FF_TRANS70|4, 2, {NULL}, 0, 0, S_WIND6}, // S_WIND5 - {SPR_WIND, FF_TRANS70|5, 2, {NULL}, 0, 0, S_WIND7}, // S_WIND6 - {SPR_WIND, FF_TRANS70|6, 2, {NULL}, 0, 0, S_WIND8}, // S_WIND7 - {SPR_WIND, FF_TRANS70|7, 2, {NULL}, 0, 0, S_WIND1}, // S_WIND8 - - {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40 , 2, {NULL}, 0, 0, S_MAGN2 }, // S_MAGN1 - {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 1, 2, {NULL}, 0, 0, S_MAGN3 }, // S_MAGN2 - {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 2, 2, {NULL}, 0, 0, S_MAGN4 }, // S_MAGN3 - {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 3, 2, {NULL}, 0, 0, S_MAGN5 }, // S_MAGN4 - {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 4, 2, {NULL}, 0, 0, S_MAGN6 }, // S_MAGN5 - {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 5, 2, {NULL}, 0, 0, S_MAGN7 }, // S_MAGN6 - {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 6, 2, {NULL}, 0, 0, S_MAGN8 }, // S_MAGN7 - {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 7, 2, {NULL}, 0, 0, S_MAGN9 }, // S_MAGN8 - {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 8, 2, {NULL}, 0, 0, S_MAGN10}, // S_MAGN9 - {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 9, 2, {NULL}, 0, 0, S_MAGN11}, // S_MAGN10 - {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40|10, 2, {NULL}, 0, 0, S_MAGN12}, // S_MAGN11 - {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40|11, 2, {NULL}, 0, 0, S_MAGN1 }, // S_MAGN12 - - {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS10|12, 2, {NULL}, 0, 0, S_MAGN1 }, // S_MAGN13 - - {SPR_FORC, FF_TRANS50 , 3, {NULL}, 0, 0, S_FORC2 }, // S_FORC1 - {SPR_FORC, FF_TRANS50|1, 3, {NULL}, 0, 0, S_FORC3 }, // S_FORC2 - {SPR_FORC, FF_TRANS50|2, 3, {NULL}, 0, 0, S_FORC4 }, // S_FORC3 - {SPR_FORC, FF_TRANS50|3, 3, {NULL}, 0, 0, S_FORC5 }, // S_FORC4 - {SPR_FORC, FF_TRANS50|4, 3, {NULL}, 0, 0, S_FORC6 }, // S_FORC5 - {SPR_FORC, FF_TRANS50|5, 3, {NULL}, 0, 0, S_FORC7 }, // S_FORC6 - {SPR_FORC, FF_TRANS50|6, 3, {NULL}, 0, 0, S_FORC8 }, // S_FORC7 - {SPR_FORC, FF_TRANS50|7, 3, {NULL}, 0, 0, S_FORC9 }, // S_FORC8 - {SPR_FORC, FF_TRANS50|8, 3, {NULL}, 0, 0, S_FORC10}, // S_FORC9 - {SPR_FORC, FF_TRANS50|9, 3, {NULL}, 0, 0, S_FORC1 }, // S_FORC10 - - {SPR_FORC, FF_TRANS50|10, 3, {NULL}, 0, 0, S_FORC12}, // S_FORC11 - {SPR_FORC, FF_TRANS50|11, 3, {NULL}, 0, 0, S_FORC13}, // S_FORC12 - {SPR_FORC, FF_TRANS50|12, 3, {NULL}, 0, 0, S_FORC14}, // S_FORC13 - {SPR_FORC, FF_TRANS50|13, 3, {NULL}, 0, 0, S_FORC15}, // S_FORC14 - {SPR_FORC, FF_TRANS50|14, 3, {NULL}, 0, 0, S_FORC16}, // S_FORC15 - {SPR_FORC, FF_TRANS50|15, 3, {NULL}, 0, 0, S_FORC17}, // S_FORC16 - {SPR_FORC, FF_TRANS50|16, 3, {NULL}, 0, 0, S_FORC18}, // S_FORC17 - {SPR_FORC, FF_TRANS50|17, 3, {NULL}, 0, 0, S_FORC19}, // S_FORC18 - {SPR_FORC, FF_TRANS50|18, 3, {NULL}, 0, 0, S_FORC20}, // S_FORC19 - {SPR_FORC, FF_TRANS50|19, 3, {NULL}, 0, 0, S_FORC11}, // S_FORC20 - - {SPR_FORC, FF_TRANS50|20, -1, {NULL}, 0, 0, S_NULL}, // S_FORC21 - - {SPR_ELEM, FF_TRANS50 , 4, {NULL}, 0, 0, S_ELEM2 }, // S_ELEM1 - {SPR_ELEM, FF_TRANS50| 1, 4, {NULL}, 0, 0, S_ELEM3 }, // S_ELEM2 - {SPR_ELEM, FF_TRANS50| 2, 4, {NULL}, 0, 0, S_ELEM4 }, // S_ELEM3 - {SPR_ELEM, FF_TRANS50| 3, 4, {NULL}, 0, 0, S_ELEM5 }, // S_ELEM4 - {SPR_ELEM, FF_TRANS50| 4, 4, {NULL}, 0, 0, S_ELEM6 }, // S_ELEM5 - {SPR_ELEM, FF_TRANS50| 5, 4, {NULL}, 0, 0, S_ELEM7 }, // S_ELEM6 - {SPR_ELEM, FF_TRANS50| 6, 4, {NULL}, 0, 0, S_ELEM8 }, // S_ELEM7 - {SPR_ELEM, FF_TRANS50| 7, 4, {NULL}, 0, 0, S_ELEM9 }, // S_ELEM8 - {SPR_ELEM, FF_TRANS50| 8, 4, {NULL}, 0, 0, S_ELEM10}, // S_ELEM9 - {SPR_ELEM, FF_TRANS50| 9, 4, {NULL}, 0, 0, S_ELEM11}, // S_ELEM10 - {SPR_ELEM, FF_TRANS50|10, 4, {NULL}, 0, 0, S_ELEM12}, // S_ELEM11 - {SPR_ELEM, FF_TRANS50|11, 4, {NULL}, 0, 0, S_ELEM1 }, // S_ELEM12 - - {SPR_NULL, 0, 1, {NULL}, 0, 0, S_ELEM14}, // S_ELEM13 - {SPR_ELEM, FF_TRANS50|11, 1, {NULL}, 0, 0, S_ELEM1 }, // S_ELEM14 - - {SPR_ELEM, FF_FULLBRIGHT|12, 3, {NULL}, 0, 0, S_ELEMF2 }, // S_ELEMF1 - {SPR_ELEM, FF_FULLBRIGHT|13, 3, {NULL}, 0, 0, S_ELEMF3 }, // S_ELEMF2 - {SPR_ELEM, FF_FULLBRIGHT|14, 3, {NULL}, 0, 0, S_ELEMF4 }, // S_ELEMF3 - {SPR_ELEM, FF_FULLBRIGHT|15, 3, {NULL}, 0, 0, S_ELEMF5 }, // S_ELEMF4 - {SPR_ELEM, FF_FULLBRIGHT|16, 3, {NULL}, 0, 0, S_ELEMF6 }, // S_ELEMF5 - {SPR_ELEM, FF_FULLBRIGHT|17, 3, {NULL}, 0, 0, S_ELEMF7 }, // S_ELEMF6 - {SPR_ELEM, FF_FULLBRIGHT|18, 3, {NULL}, 0, 0, S_ELEMF8 }, // S_ELEMF7 - {SPR_ELEM, FF_FULLBRIGHT|19, 3, {NULL}, 0, 0, S_ELEMF1 }, // S_ELEMF8 - - {SPR_ELEM, FF_FULLBRIGHT|20, 1, {NULL}, 0, 0, S_ELEMF10}, // S_ELEMF9 - {SPR_NULL, 0, 1, {NULL}, 0, 0, S_ELEMF1 }, // S_ELEMF10 - - {SPR_PITY, FF_TRANS30 , 2, {NULL}, 0, 0, S_PITY2}, // S_PITY1 - {SPR_PITY, FF_TRANS30| 1, 2, {NULL}, 0, 0, S_PITY3}, // S_PITY2 - {SPR_PITY, FF_TRANS30| 2, 2, {NULL}, 0, 0, S_PITY4}, // S_PITY3 - {SPR_PITY, FF_TRANS30| 3, 2, {NULL}, 0, 0, S_PITY5}, // S_PITY4 - {SPR_PITY, FF_TRANS30| 4, 2, {NULL}, 0, 0, S_PITY6}, // S_PITY5 - {SPR_PITY, FF_TRANS30| 5, 2, {NULL}, 0, 0, S_PITY7}, // S_PITY6 - {SPR_PITY, FF_TRANS30| 6, 2, {NULL}, 0, 0, S_PITY8}, // S_PITY7 - {SPR_PITY, FF_TRANS30| 7, 2, {NULL}, 0, 0, S_PITY9}, // S_PITY8 - {SPR_PITY, FF_TRANS30| 8, 2, {NULL}, 0, 0, S_PITY10}, // S_PITY9 - {SPR_PITY, FF_TRANS30| 9, 2, {NULL}, 0, 0, S_PITY11}, // S_PITY10 - {SPR_PITY, FF_TRANS30|10, 2, {NULL}, 0, 0, S_PITY12}, // S_PITY11 - {SPR_PITY, FF_TRANS30|11, 2, {NULL}, 0, 0, S_PITY1}, // S_PITY12 - - {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40 , 2, {NULL}, 0, 0, S_FIRS2}, // S_FIRS1 - {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|1, 2, {NULL}, 0, 0, S_FIRS3}, // S_FIRS2 - {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|2, 2, {NULL}, 0, 0, S_FIRS4}, // S_FIRS3 - {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|3, 2, {NULL}, 0, 0, S_FIRS5}, // S_FIRS4 - {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|4, 2, {NULL}, 0, 0, S_FIRS6}, // S_FIRS5 - {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|5, 2, {NULL}, 0, 0, S_FIRS7}, // S_FIRS6 - {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|6, 2, {NULL}, 0, 0, S_FIRS8}, // S_FIRS7 - {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|7, 2, {NULL}, 0, 0, S_FIRS9}, // S_FIRS8 - {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|8, 2, {NULL}, 0, 0, S_FIRS1}, // S_FIRS9 - - {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|18, 1, {NULL}, 0, 0, S_FIRS11}, // S_FIRS10 - {SPR_NULL, 0, 1, {NULL}, 0, 0, S_FIRS1 }, // S_FIRS11 - - {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40| 9, 2, {NULL}, 0, 0, S_FIRSB2}, // S_FIRSB1 - {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|10, 2, {NULL}, 0, 0, S_FIRSB3}, // S_FIRSB2 - {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|11, 2, {NULL}, 0, 0, S_FIRSB4}, // S_FIRSB3 - {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|12, 2, {NULL}, 0, 0, S_FIRSB5}, // S_FIRSB4 - {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|13, 2, {NULL}, 0, 0, S_FIRSB6}, // S_FIRSB5 - {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|14, 2, {NULL}, 0, 0, S_FIRSB7}, // S_FIRSB6 - {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|15, 2, {NULL}, 0, 0, S_FIRSB8}, // S_FIRSB7 - {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|16, 2, {NULL}, 0, 0, S_FIRSB9}, // S_FIRSB8 - {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|17, 2, {NULL}, 0, 0, S_FIRSB1}, // S_FIRSB9 - - {SPR_NULL, 0, 2, {NULL}, 0, 0, S_FIRSB1 }, // S_FIRSB10 - - {SPR_BUBS, FF_TRANS30 , 3, {NULL}, 0, 0, S_BUBS2}, // S_BUBS1 - {SPR_BUBS, FF_TRANS30|1, 3, {NULL}, 0, 0, S_BUBS3}, // S_BUBS2 - {SPR_BUBS, FF_TRANS30|2, 3, {NULL}, 0, 0, S_BUBS4}, // S_BUBS3 - {SPR_BUBS, FF_TRANS30|3, 3, {NULL}, 0, 0, S_BUBS5}, // S_BUBS4 - {SPR_BUBS, FF_TRANS30|4, 3, {NULL}, 0, 0, S_BUBS6}, // S_BUBS5 - {SPR_BUBS, FF_TRANS30|5, 3, {NULL}, 0, 0, S_BUBS7}, // S_BUBS6 - {SPR_BUBS, FF_TRANS30|6, 3, {NULL}, 0, 0, S_BUBS8}, // S_BUBS7 - {SPR_BUBS, FF_TRANS30|7, 3, {NULL}, 0, 0, S_BUBS9}, // S_BUBS8 - {SPR_BUBS, FF_TRANS30|8, 3, {NULL}, 0, 0, S_BUBS1}, // S_BUBS9 - - {SPR_NULL, 0, 3, {NULL}, 0, 0, S_BUBS1}, // S_BUBS10 - {SPR_NULL, 0, 4*3, {NULL}, 0, 0, S_BUBS1}, // S_BUBS11 - - {SPR_BUBS, FF_TRANS30| 9, 3, {NULL}, 0, 0, S_BUBSB2}, // S_BUBSB1 - {SPR_BUBS, FF_TRANS30|10, 3, {NULL}, 0, 0, S_BUBSB3}, // S_BUBSB2 - {SPR_BUBS, FF_TRANS30|11, 3, {NULL}, 0, 0, S_BUBSB4}, // S_BUBSB3 - {SPR_BUBS, FF_TRANS30|10, 3, {NULL}, 0, 0, S_BUBSB1}, // S_BUBSB4 - - {SPR_BUBS, FF_TRANS30|12, 3, {NULL}, 0, 0, S_BUBSB3}, // S_BUBSB5 - {SPR_BUBS, FF_TRANS30|13, 3, {NULL}, 0, 0, S_BUBSB5}, // S_BUBSB6 - - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20 , 2, {NULL}, 0, 0, S_ZAPS2 }, // S_ZAPS1 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 1, 2, {NULL}, 0, 0, S_ZAPS3 }, // S_ZAPS2 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 2, 2, {NULL}, 0, 0, S_ZAPS4 }, // S_ZAPS3 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 3, 2, {NULL}, 0, 0, S_ZAPS5 }, // S_ZAPS4 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 4, 2, {NULL}, 0, 0, S_ZAPS6 }, // S_ZAPS5 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 5, 2, {NULL}, 0, 0, S_ZAPS7 }, // S_ZAPS6 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 6, 2, {NULL}, 0, 0, S_ZAPS8 }, // S_ZAPS7 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 7, 2, {NULL}, 0, 0, S_ZAPS9 }, // S_ZAPS8 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 8, 2, {NULL}, 0, 0, S_ZAPS10}, // S_ZAPS9 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 9, 2, {NULL}, 0, 0, S_ZAPS11}, // S_ZAPS10 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20|10, 2, {NULL}, 0, 0, S_ZAPS12}, // S_ZAPS11 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20|11, 2, {NULL}, 0, 0, S_ZAPS13}, // S_ZAPS12 - {SPR_NULL, 0, 9*2, {NULL}, 0, 0, S_ZAPS14}, // S_ZAPS13 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 9, 2, {NULL}, 0, 0, S_ZAPS15}, // S_ZAPS14 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20|10, 2, {NULL}, 0, 0, S_ZAPS16}, // S_ZAPS15 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20|11, 2, {NULL}, 0, 0, S_ZAPS1 }, // S_ZAPS16 - - {SPR_NULL, 0, 12*2, {NULL}, 0, 0, S_ZAPSB2 }, // S_ZAPSB1 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 8, 2, {NULL}, 0, 0, S_ZAPSB3 }, // S_ZAPSB2 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 7, 2, {NULL}, 0, 0, S_ZAPSB4 }, // S_ZAPSB3 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 6, 2, {NULL}, 0, 0, S_ZAPSB5 }, // S_ZAPSB4 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 5, 2, {NULL}, 0, 0, S_ZAPSB6 }, // S_ZAPSB5 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 4, 2, {NULL}, 0, 0, S_ZAPSB7 }, // S_ZAPSB6 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 3, 2, {NULL}, 0, 0, S_ZAPSB8 }, // S_ZAPSB7 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 2, 2, {NULL}, 0, 0, S_ZAPSB9 }, // S_ZAPSB8 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 1, 2, {NULL}, 0, 0, S_ZAPSB10}, // S_ZAPSB9 - {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20 , 2, {NULL}, 0, 0, S_ZAPSB11}, // S_ZAPSB10 - {SPR_NULL, 0, 15*2, {NULL}, 0, 0, S_ZAPSB2 }, // S_ZAPSB11 + {SPR_ARMA, FF_TRANS40 , 2, {NULL}, 0, 0, S_ARMA2 , 0}, // S_ARMA1 + {SPR_ARMA, FF_TRANS40| 1, 2, {NULL}, 0, 0, S_ARMA3 , 0}, // S_ARMA2 + {SPR_ARMA, FF_TRANS40| 2, 2, {NULL}, 0, 0, S_ARMA4 , 0}, // S_ARMA3 + {SPR_ARMA, FF_TRANS40| 3, 2, {NULL}, 0, 0, S_ARMA5 , 0}, // S_ARMA4 + {SPR_ARMA, FF_TRANS40| 4, 2, {NULL}, 0, 0, S_ARMA6 , 0}, // S_ARMA5 + {SPR_ARMA, FF_TRANS40| 5, 2, {NULL}, 0, 0, S_ARMA7 , 0}, // S_ARMA6 + {SPR_ARMA, FF_TRANS40| 6, 2, {NULL}, 0, 0, S_ARMA8 , 0}, // S_ARMA7 + {SPR_ARMA, FF_TRANS40| 7, 2, {NULL}, 0, 0, S_ARMA9 , 0}, // S_ARMA8 + {SPR_ARMA, FF_TRANS40| 8, 2, {NULL}, 0, 0, S_ARMA10, 0}, // S_ARMA9 + {SPR_ARMA, FF_TRANS40| 9, 2, {NULL}, 0, 0, S_ARMA11, 0}, // S_ARMA10 + {SPR_ARMA, FF_TRANS40|10, 2, {NULL}, 0, 0, S_ARMA12, 0}, // S_ARMA11 + {SPR_ARMA, FF_TRANS40|11, 2, {NULL}, 0, 0, S_ARMA13, 0}, // S_ARMA12 + {SPR_ARMA, FF_TRANS40|12, 2, {NULL}, 0, 0, S_ARMA14, 0}, // S_ARMA13 + {SPR_ARMA, FF_TRANS40|13, 2, {NULL}, 0, 0, S_ARMA15, 0}, // S_ARMA14 + {SPR_ARMA, FF_TRANS40|14, 2, {NULL}, 0, 0, S_ARMA16, 0}, // S_ARMA15 + {SPR_ARMA, FF_TRANS40|15, 2, {NULL}, 0, 0, S_ARMA1 , 0}, // S_ARMA16 + + {SPR_ARMF, FF_FULLBRIGHT , 2, {NULL}, 0, 0, S_ARMF2 , 0}, // S_ARMF1 + {SPR_ARMF, FF_FULLBRIGHT| 1, 2, {NULL}, 0, 0, S_ARMF3 , 0}, // S_ARMF2 + {SPR_ARMF, FF_FULLBRIGHT| 2, 2, {NULL}, 0, 0, S_ARMF4 , 0}, // S_ARMF3 + {SPR_ARMF, FF_FULLBRIGHT| 3, 2, {NULL}, 0, 0, S_ARMF5 , 0}, // S_ARMF4 + {SPR_ARMF, FF_FULLBRIGHT| 4, 2, {NULL}, 0, 0, S_ARMF6 , 0}, // S_ARMF5 + {SPR_ARMF, FF_FULLBRIGHT| 5, 2, {NULL}, 0, 0, S_ARMF7 , 0}, // S_ARMF6 + {SPR_ARMF, FF_FULLBRIGHT| 6, 2, {NULL}, 0, 0, S_ARMF8 , 0}, // S_ARMF7 + {SPR_ARMF, FF_FULLBRIGHT| 7, 2, {NULL}, 0, 0, S_ARMF9 , 0}, // S_ARMF8 + {SPR_ARMF, FF_FULLBRIGHT| 8, 2, {NULL}, 0, 0, S_ARMF10, 0}, // S_ARMF9 + {SPR_ARMF, FF_FULLBRIGHT| 9, 2, {NULL}, 0, 0, S_ARMF11, 0}, // S_ARMF10 + {SPR_ARMF, FF_FULLBRIGHT|10, 2, {NULL}, 0, 0, S_ARMF12, 0}, // S_ARMF11 + {SPR_ARMF, FF_FULLBRIGHT|11, 2, {NULL}, 0, 0, S_ARMF13, 0}, // S_ARMF12 + {SPR_ARMF, FF_FULLBRIGHT|12, 2, {NULL}, 0, 0, S_ARMF14, 0}, // S_ARMF13 + {SPR_ARMF, FF_FULLBRIGHT|13, 2, {NULL}, 0, 0, S_ARMF15, 0}, // S_ARMF14 + {SPR_ARMF, FF_FULLBRIGHT|14, 2, {NULL}, 0, 0, S_ARMF16, 0}, // S_ARMF15 + {SPR_ARMF, FF_FULLBRIGHT|15, 2, {NULL}, 0, 0, S_ARMF17, 0}, // S_ARMF16 + {SPR_ARMB, FF_FULLBRIGHT , 2, {NULL}, 0, 0, S_ARMF18, 0}, // S_ARMF17 + {SPR_ARMB, FF_FULLBRIGHT| 1, 2, {NULL}, 0, 0, S_ARMF19, 0}, // S_ARMF18 + {SPR_ARMB, FF_FULLBRIGHT| 2, 2, {NULL}, 0, 0, S_ARMF20, 0}, // S_ARMF19 + {SPR_ARMB, FF_FULLBRIGHT| 3, 2, {NULL}, 0, 0, S_ARMF21, 0}, // S_ARMF20 + {SPR_ARMB, FF_FULLBRIGHT| 4, 2, {NULL}, 0, 0, S_ARMF22, 0}, // S_ARMF21 + {SPR_ARMB, FF_FULLBRIGHT| 5, 2, {NULL}, 0, 0, S_ARMF23, 0}, // S_ARMF22 + {SPR_ARMB, FF_FULLBRIGHT| 6, 2, {NULL}, 0, 0, S_ARMF24, 0}, // S_ARMF23 + {SPR_ARMB, FF_FULLBRIGHT| 7, 2, {NULL}, 0, 0, S_ARMF25, 0}, // S_ARMF24 + {SPR_ARMB, FF_FULLBRIGHT| 8, 2, {NULL}, 0, 0, S_ARMF26, 0}, // S_ARMF25 + {SPR_ARMB, FF_FULLBRIGHT| 9, 2, {NULL}, 0, 0, S_ARMF27, 0}, // S_ARMF26 + {SPR_ARMB, FF_FULLBRIGHT|10, 2, {NULL}, 0, 0, S_ARMF28, 0}, // S_ARMF27 + {SPR_ARMB, FF_FULLBRIGHT|11, 2, {NULL}, 0, 0, S_ARMF29, 0}, // S_ARMF28 + {SPR_ARMB, FF_FULLBRIGHT|12, 2, {NULL}, 0, 0, S_ARMF30, 0}, // S_ARMF29 + {SPR_ARMB, FF_FULLBRIGHT|13, 2, {NULL}, 0, 0, S_ARMF31, 0}, // S_ARMF30 + {SPR_ARMB, FF_FULLBRIGHT|14, 2, {NULL}, 0, 0, S_ARMF32, 0}, // S_ARMF31 + {SPR_ARMB, FF_FULLBRIGHT|15, 2, {NULL}, 0, 0, S_ARMF1 , 0}, // S_ARMF32 + + {SPR_ARMB, FF_FULLBRIGHT , 2, {NULL}, 1, 0, S_ARMB2 , 0}, // S_ARMB1 + {SPR_ARMB, FF_FULLBRIGHT| 1, 2, {NULL}, 1, 0, S_ARMB3 , 0}, // S_ARMB2 + {SPR_ARMB, FF_FULLBRIGHT| 2, 2, {NULL}, 1, 0, S_ARMB4 , 0}, // S_ARMB3 + {SPR_ARMB, FF_FULLBRIGHT| 3, 2, {NULL}, 1, 0, S_ARMB5 , 0}, // S_ARMB4 + {SPR_ARMB, FF_FULLBRIGHT| 4, 2, {NULL}, 1, 0, S_ARMB6 , 0}, // S_ARMB5 + {SPR_ARMB, FF_FULLBRIGHT| 5, 2, {NULL}, 1, 0, S_ARMB7 , 0}, // S_ARMB6 + {SPR_ARMB, FF_FULLBRIGHT| 6, 2, {NULL}, 1, 0, S_ARMB8 , 0}, // S_ARMB7 + {SPR_ARMB, FF_FULLBRIGHT| 7, 2, {NULL}, 1, 0, S_ARMB9 , 0}, // S_ARMB8 + {SPR_ARMB, FF_FULLBRIGHT| 8, 2, {NULL}, 1, 0, S_ARMB10, 0}, // S_ARMB9 + {SPR_ARMB, FF_FULLBRIGHT| 9, 2, {NULL}, 1, 0, S_ARMB11, 0}, // S_ARMB10 + {SPR_ARMB, FF_FULLBRIGHT|10, 2, {NULL}, 1, 0, S_ARMB12, 0}, // S_ARMB11 + {SPR_ARMB, FF_FULLBRIGHT|11, 2, {NULL}, 1, 0, S_ARMB13, 0}, // S_ARMB12 + {SPR_ARMB, FF_FULLBRIGHT|12, 2, {NULL}, 1, 0, S_ARMB14, 0}, // S_ARMB13 + {SPR_ARMB, FF_FULLBRIGHT|13, 2, {NULL}, 1, 0, S_ARMB15, 0}, // S_ARMB14 + {SPR_ARMB, FF_FULLBRIGHT|14, 2, {NULL}, 1, 0, S_ARMB16, 0}, // S_ARMB15 + {SPR_ARMB, FF_FULLBRIGHT|15, 2, {NULL}, 1, 0, S_ARMB17, 0}, // S_ARMB16 + {SPR_ARMF, FF_FULLBRIGHT , 2, {NULL}, 1, 0, S_ARMB18, 0}, // S_ARMB17 + {SPR_ARMF, FF_FULLBRIGHT| 1, 2, {NULL}, 1, 0, S_ARMB19, 0}, // S_ARMB18 + {SPR_ARMF, FF_FULLBRIGHT| 2, 2, {NULL}, 1, 0, S_ARMB20, 0}, // S_ARMB19 + {SPR_ARMF, FF_FULLBRIGHT| 3, 2, {NULL}, 1, 0, S_ARMB21, 0}, // S_ARMB20 + {SPR_ARMF, FF_FULLBRIGHT| 4, 2, {NULL}, 1, 0, S_ARMB22, 0}, // S_ARMB21 + {SPR_ARMF, FF_FULLBRIGHT| 5, 2, {NULL}, 1, 0, S_ARMB23, 0}, // S_ARMB22 + {SPR_ARMF, FF_FULLBRIGHT| 6, 2, {NULL}, 1, 0, S_ARMB24, 0}, // S_ARMB23 + {SPR_ARMF, FF_FULLBRIGHT| 7, 2, {NULL}, 1, 0, S_ARMB25, 0}, // S_ARMB24 + {SPR_ARMF, FF_FULLBRIGHT| 8, 2, {NULL}, 1, 0, S_ARMB26, 0}, // S_ARMB25 + {SPR_ARMF, FF_FULLBRIGHT| 9, 2, {NULL}, 1, 0, S_ARMB27, 0}, // S_ARMB26 + {SPR_ARMF, FF_FULLBRIGHT|10, 2, {NULL}, 1, 0, S_ARMB28, 0}, // S_ARMB27 + {SPR_ARMF, FF_FULLBRIGHT|11, 2, {NULL}, 1, 0, S_ARMB29, 0}, // S_ARMB28 + {SPR_ARMF, FF_FULLBRIGHT|12, 2, {NULL}, 1, 0, S_ARMB30, 0}, // S_ARMB29 + {SPR_ARMF, FF_FULLBRIGHT|13, 2, {NULL}, 1, 0, S_ARMB31, 0}, // S_ARMB30 + {SPR_ARMF, FF_FULLBRIGHT|14, 2, {NULL}, 1, 0, S_ARMB32, 0}, // S_ARMB31 + {SPR_ARMF, FF_FULLBRIGHT|15, 2, {NULL}, 1, 0, S_ARMB1 , 0}, // S_ARMB32 + + {SPR_WIND, FF_TRANS70 , 2, {NULL}, 0, 0, S_WIND2, 0}, // S_WIND1 + {SPR_WIND, FF_TRANS70|1, 2, {NULL}, 0, 0, S_WIND3, 0}, // S_WIND2 + {SPR_WIND, FF_TRANS70|2, 2, {NULL}, 0, 0, S_WIND4, 0}, // S_WIND3 + {SPR_WIND, FF_TRANS70|3, 2, {NULL}, 0, 0, S_WIND5, 0}, // S_WIND4 + {SPR_WIND, FF_TRANS70|4, 2, {NULL}, 0, 0, S_WIND6, 0}, // S_WIND5 + {SPR_WIND, FF_TRANS70|5, 2, {NULL}, 0, 0, S_WIND7, 0}, // S_WIND6 + {SPR_WIND, FF_TRANS70|6, 2, {NULL}, 0, 0, S_WIND8, 0}, // S_WIND7 + {SPR_WIND, FF_TRANS70|7, 2, {NULL}, 0, 0, S_WIND1, 0}, // S_WIND8 + + {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40 , 2, {NULL}, 0, 0, S_MAGN2 , 0}, // S_MAGN1 + {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 1, 2, {NULL}, 0, 0, S_MAGN3 , 0}, // S_MAGN2 + {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 2, 2, {NULL}, 0, 0, S_MAGN4 , 0}, // S_MAGN3 + {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 3, 2, {NULL}, 0, 0, S_MAGN5 , 0}, // S_MAGN4 + {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 4, 2, {NULL}, 0, 0, S_MAGN6 , 0}, // S_MAGN5 + {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 5, 2, {NULL}, 0, 0, S_MAGN7 , 0}, // S_MAGN6 + {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 6, 2, {NULL}, 0, 0, S_MAGN8 , 0}, // S_MAGN7 + {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 7, 2, {NULL}, 0, 0, S_MAGN9 , 0}, // S_MAGN8 + {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 8, 2, {NULL}, 0, 0, S_MAGN10, 0}, // S_MAGN9 + {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 9, 2, {NULL}, 0, 0, S_MAGN11, 0}, // S_MAGN10 + {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40|10, 2, {NULL}, 0, 0, S_MAGN12, 0}, // S_MAGN11 + {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40|11, 2, {NULL}, 0, 0, S_MAGN1 , 0}, // S_MAGN12 + + {SPR_MAGN, FF_FULLBRIGHT|FF_TRANS10|12, 2, {NULL}, 0, 0, S_MAGN1 , 0}, // S_MAGN13 + + {SPR_FORC, FF_TRANS50 , 3, {NULL}, 0, 0, S_FORC2 , 0}, // S_FORC1 + {SPR_FORC, FF_TRANS50|1, 3, {NULL}, 0, 0, S_FORC3 , 0}, // S_FORC2 + {SPR_FORC, FF_TRANS50|2, 3, {NULL}, 0, 0, S_FORC4 , 0}, // S_FORC3 + {SPR_FORC, FF_TRANS50|3, 3, {NULL}, 0, 0, S_FORC5 , 0}, // S_FORC4 + {SPR_FORC, FF_TRANS50|4, 3, {NULL}, 0, 0, S_FORC6 , 0}, // S_FORC5 + {SPR_FORC, FF_TRANS50|5, 3, {NULL}, 0, 0, S_FORC7 , 0}, // S_FORC6 + {SPR_FORC, FF_TRANS50|6, 3, {NULL}, 0, 0, S_FORC8 , 0}, // S_FORC7 + {SPR_FORC, FF_TRANS50|7, 3, {NULL}, 0, 0, S_FORC9 , 0}, // S_FORC8 + {SPR_FORC, FF_TRANS50|8, 3, {NULL}, 0, 0, S_FORC10, 0}, // S_FORC9 + {SPR_FORC, FF_TRANS50|9, 3, {NULL}, 0, 0, S_FORC1 , 0}, // S_FORC10 + + {SPR_FORC, FF_TRANS50|10, 3, {NULL}, 0, 0, S_FORC12, 0}, // S_FORC11 + {SPR_FORC, FF_TRANS50|11, 3, {NULL}, 0, 0, S_FORC13, 0}, // S_FORC12 + {SPR_FORC, FF_TRANS50|12, 3, {NULL}, 0, 0, S_FORC14, 0}, // S_FORC13 + {SPR_FORC, FF_TRANS50|13, 3, {NULL}, 0, 0, S_FORC15, 0}, // S_FORC14 + {SPR_FORC, FF_TRANS50|14, 3, {NULL}, 0, 0, S_FORC16, 0}, // S_FORC15 + {SPR_FORC, FF_TRANS50|15, 3, {NULL}, 0, 0, S_FORC17, 0}, // S_FORC16 + {SPR_FORC, FF_TRANS50|16, 3, {NULL}, 0, 0, S_FORC18, 0}, // S_FORC17 + {SPR_FORC, FF_TRANS50|17, 3, {NULL}, 0, 0, S_FORC19, 0}, // S_FORC18 + {SPR_FORC, FF_TRANS50|18, 3, {NULL}, 0, 0, S_FORC20, 0}, // S_FORC19 + {SPR_FORC, FF_TRANS50|19, 3, {NULL}, 0, 0, S_FORC11, 0}, // S_FORC20 + + {SPR_FORC, FF_TRANS50|20, -1, {NULL}, 0, 0, S_NULL, 0}, // S_FORC21 + + {SPR_ELEM, FF_TRANS50 , 4, {NULL}, 0, 0, S_ELEM2 , 0}, // S_ELEM1 + {SPR_ELEM, FF_TRANS50| 1, 4, {NULL}, 0, 0, S_ELEM3 , 0}, // S_ELEM2 + {SPR_ELEM, FF_TRANS50| 2, 4, {NULL}, 0, 0, S_ELEM4 , 0}, // S_ELEM3 + {SPR_ELEM, FF_TRANS50| 3, 4, {NULL}, 0, 0, S_ELEM5 , 0}, // S_ELEM4 + {SPR_ELEM, FF_TRANS50| 4, 4, {NULL}, 0, 0, S_ELEM6 , 0}, // S_ELEM5 + {SPR_ELEM, FF_TRANS50| 5, 4, {NULL}, 0, 0, S_ELEM7 , 0}, // S_ELEM6 + {SPR_ELEM, FF_TRANS50| 6, 4, {NULL}, 0, 0, S_ELEM8 , 0}, // S_ELEM7 + {SPR_ELEM, FF_TRANS50| 7, 4, {NULL}, 0, 0, S_ELEM9 , 0}, // S_ELEM8 + {SPR_ELEM, FF_TRANS50| 8, 4, {NULL}, 0, 0, S_ELEM10, 0}, // S_ELEM9 + {SPR_ELEM, FF_TRANS50| 9, 4, {NULL}, 0, 0, S_ELEM11, 0}, // S_ELEM10 + {SPR_ELEM, FF_TRANS50|10, 4, {NULL}, 0, 0, S_ELEM12, 0}, // S_ELEM11 + {SPR_ELEM, FF_TRANS50|11, 4, {NULL}, 0, 0, S_ELEM1 , 0}, // S_ELEM12 + + {SPR_NULL, 0, 1, {NULL}, 0, 0, S_ELEM14, 0}, // S_ELEM13 + {SPR_ELEM, FF_TRANS50|11, 1, {NULL}, 0, 0, S_ELEM1 , 0}, // S_ELEM14 + + {SPR_ELEM, FF_FULLBRIGHT|12, 3, {NULL}, 0, 0, S_ELEMF2 , 0}, // S_ELEMF1 + {SPR_ELEM, FF_FULLBRIGHT|13, 3, {NULL}, 0, 0, S_ELEMF3 , 0}, // S_ELEMF2 + {SPR_ELEM, FF_FULLBRIGHT|14, 3, {NULL}, 0, 0, S_ELEMF4 , 0}, // S_ELEMF3 + {SPR_ELEM, FF_FULLBRIGHT|15, 3, {NULL}, 0, 0, S_ELEMF5 , 0}, // S_ELEMF4 + {SPR_ELEM, FF_FULLBRIGHT|16, 3, {NULL}, 0, 0, S_ELEMF6 , 0}, // S_ELEMF5 + {SPR_ELEM, FF_FULLBRIGHT|17, 3, {NULL}, 0, 0, S_ELEMF7 , 0}, // S_ELEMF6 + {SPR_ELEM, FF_FULLBRIGHT|18, 3, {NULL}, 0, 0, S_ELEMF8 , 0}, // S_ELEMF7 + {SPR_ELEM, FF_FULLBRIGHT|19, 3, {NULL}, 0, 0, S_ELEMF1 , 0}, // S_ELEMF8 + + {SPR_ELEM, FF_FULLBRIGHT|20, 1, {NULL}, 0, 0, S_ELEMF10, 0}, // S_ELEMF9 + {SPR_NULL, 0, 1, {NULL}, 0, 0, S_ELEMF1 , 0}, // S_ELEMF10 + + {SPR_PITY, FF_TRANS30 , 2, {NULL}, 0, 0, S_PITY2, 0}, // S_PITY1 + {SPR_PITY, FF_TRANS30| 1, 2, {NULL}, 0, 0, S_PITY3, 0}, // S_PITY2 + {SPR_PITY, FF_TRANS30| 2, 2, {NULL}, 0, 0, S_PITY4, 0}, // S_PITY3 + {SPR_PITY, FF_TRANS30| 3, 2, {NULL}, 0, 0, S_PITY5, 0}, // S_PITY4 + {SPR_PITY, FF_TRANS30| 4, 2, {NULL}, 0, 0, S_PITY6, 0}, // S_PITY5 + {SPR_PITY, FF_TRANS30| 5, 2, {NULL}, 0, 0, S_PITY7, 0}, // S_PITY6 + {SPR_PITY, FF_TRANS30| 6, 2, {NULL}, 0, 0, S_PITY8, 0}, // S_PITY7 + {SPR_PITY, FF_TRANS30| 7, 2, {NULL}, 0, 0, S_PITY9, 0}, // S_PITY8 + {SPR_PITY, FF_TRANS30| 8, 2, {NULL}, 0, 0, S_PITY10, 0}, // S_PITY9 + {SPR_PITY, FF_TRANS30| 9, 2, {NULL}, 0, 0, S_PITY11, 0}, // S_PITY10 + {SPR_PITY, FF_TRANS30|10, 2, {NULL}, 0, 0, S_PITY12, 0}, // S_PITY11 + {SPR_PITY, FF_TRANS30|11, 2, {NULL}, 0, 0, S_PITY1, 0}, // S_PITY12 + + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40 , 2, {NULL}, 0, 0, S_FIRS2, 0}, // S_FIRS1 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|1, 2, {NULL}, 0, 0, S_FIRS3, 0}, // S_FIRS2 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|2, 2, {NULL}, 0, 0, S_FIRS4, 0}, // S_FIRS3 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|3, 2, {NULL}, 0, 0, S_FIRS5, 0}, // S_FIRS4 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|4, 2, {NULL}, 0, 0, S_FIRS6, 0}, // S_FIRS5 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|5, 2, {NULL}, 0, 0, S_FIRS7, 0}, // S_FIRS6 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|6, 2, {NULL}, 0, 0, S_FIRS8, 0}, // S_FIRS7 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|7, 2, {NULL}, 0, 0, S_FIRS9, 0}, // S_FIRS8 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|8, 2, {NULL}, 0, 0, S_FIRS1, 0}, // S_FIRS9 + + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|18, 1, {NULL}, 0, 0, S_FIRS11, 0}, // S_FIRS10 + {SPR_NULL, 0, 1, {NULL}, 0, 0, S_FIRS1 , 0}, // S_FIRS11 + + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40| 9, 2, {NULL}, 0, 0, S_FIRSB2, 0}, // S_FIRSB1 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|10, 2, {NULL}, 0, 0, S_FIRSB3, 0}, // S_FIRSB2 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|11, 2, {NULL}, 0, 0, S_FIRSB4, 0}, // S_FIRSB3 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|12, 2, {NULL}, 0, 0, S_FIRSB5, 0}, // S_FIRSB4 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|13, 2, {NULL}, 0, 0, S_FIRSB6, 0}, // S_FIRSB5 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|14, 2, {NULL}, 0, 0, S_FIRSB7, 0}, // S_FIRSB6 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|15, 2, {NULL}, 0, 0, S_FIRSB8, 0}, // S_FIRSB7 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|16, 2, {NULL}, 0, 0, S_FIRSB9, 0}, // S_FIRSB8 + {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|17, 2, {NULL}, 0, 0, S_FIRSB1, 0}, // S_FIRSB9 + + {SPR_NULL, 0, 2, {NULL}, 0, 0, S_FIRSB1 , 0}, // S_FIRSB10 + + {SPR_BUBS, FF_TRANS30 , 3, {NULL}, 0, 0, S_BUBS2, 0}, // S_BUBS1 + {SPR_BUBS, FF_TRANS30|1, 3, {NULL}, 0, 0, S_BUBS3, 0}, // S_BUBS2 + {SPR_BUBS, FF_TRANS30|2, 3, {NULL}, 0, 0, S_BUBS4, 0}, // S_BUBS3 + {SPR_BUBS, FF_TRANS30|3, 3, {NULL}, 0, 0, S_BUBS5, 0}, // S_BUBS4 + {SPR_BUBS, FF_TRANS30|4, 3, {NULL}, 0, 0, S_BUBS6, 0}, // S_BUBS5 + {SPR_BUBS, FF_TRANS30|5, 3, {NULL}, 0, 0, S_BUBS7, 0}, // S_BUBS6 + {SPR_BUBS, FF_TRANS30|6, 3, {NULL}, 0, 0, S_BUBS8, 0}, // S_BUBS7 + {SPR_BUBS, FF_TRANS30|7, 3, {NULL}, 0, 0, S_BUBS9, 0}, // S_BUBS8 + {SPR_BUBS, FF_TRANS30|8, 3, {NULL}, 0, 0, S_BUBS1, 0}, // S_BUBS9 + + {SPR_NULL, 0, 3, {NULL}, 0, 0, S_BUBS1, 0}, // S_BUBS10 + {SPR_NULL, 0, 4*3, {NULL}, 0, 0, S_BUBS1, 0}, // S_BUBS11 + + {SPR_BUBS, FF_TRANS30| 9, 3, {NULL}, 0, 0, S_BUBSB2, 0}, // S_BUBSB1 + {SPR_BUBS, FF_TRANS30|10, 3, {NULL}, 0, 0, S_BUBSB3, 0}, // S_BUBSB2 + {SPR_BUBS, FF_TRANS30|11, 3, {NULL}, 0, 0, S_BUBSB4, 0}, // S_BUBSB3 + {SPR_BUBS, FF_TRANS30|10, 3, {NULL}, 0, 0, S_BUBSB1, 0}, // S_BUBSB4 + + {SPR_BUBS, FF_TRANS30|12, 3, {NULL}, 0, 0, S_BUBSB3, 0}, // S_BUBSB5 + {SPR_BUBS, FF_TRANS30|13, 3, {NULL}, 0, 0, S_BUBSB5, 0}, // S_BUBSB6 + + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20 , 2, {NULL}, 0, 0, S_ZAPS2 , 0}, // S_ZAPS1 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 1, 2, {NULL}, 0, 0, S_ZAPS3 , 0}, // S_ZAPS2 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 2, 2, {NULL}, 0, 0, S_ZAPS4 , 0}, // S_ZAPS3 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 3, 2, {NULL}, 0, 0, S_ZAPS5 , 0}, // S_ZAPS4 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 4, 2, {NULL}, 0, 0, S_ZAPS6 , 0}, // S_ZAPS5 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 5, 2, {NULL}, 0, 0, S_ZAPS7 , 0}, // S_ZAPS6 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 6, 2, {NULL}, 0, 0, S_ZAPS8 , 0}, // S_ZAPS7 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 7, 2, {NULL}, 0, 0, S_ZAPS9 , 0}, // S_ZAPS8 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 8, 2, {NULL}, 0, 0, S_ZAPS10, 0}, // S_ZAPS9 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 9, 2, {NULL}, 0, 0, S_ZAPS11, 0}, // S_ZAPS10 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20|10, 2, {NULL}, 0, 0, S_ZAPS12, 0}, // S_ZAPS11 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20|11, 2, {NULL}, 0, 0, S_ZAPS13, 0}, // S_ZAPS12 + {SPR_NULL, 0, 9*2, {NULL}, 0, 0, S_ZAPS14, 0}, // S_ZAPS13 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 9, 2, {NULL}, 0, 0, S_ZAPS15, 0}, // S_ZAPS14 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20|10, 2, {NULL}, 0, 0, S_ZAPS16, 0}, // S_ZAPS15 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20|11, 2, {NULL}, 0, 0, S_ZAPS1 , 0}, // S_ZAPS16 + + {SPR_NULL, 0, 12*2, {NULL}, 0, 0, S_ZAPSB2 , 0}, // S_ZAPSB1 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 8, 2, {NULL}, 0, 0, S_ZAPSB3 , 0}, // S_ZAPSB2 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 7, 2, {NULL}, 0, 0, S_ZAPSB4 , 0}, // S_ZAPSB3 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 6, 2, {NULL}, 0, 0, S_ZAPSB5 , 0}, // S_ZAPSB4 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 5, 2, {NULL}, 0, 0, S_ZAPSB6 , 0}, // S_ZAPSB5 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 4, 2, {NULL}, 0, 0, S_ZAPSB7 , 0}, // S_ZAPSB6 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 3, 2, {NULL}, 0, 0, S_ZAPSB8 , 0}, // S_ZAPSB7 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 2, 2, {NULL}, 0, 0, S_ZAPSB9 , 0}, // S_ZAPSB8 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 1, 2, {NULL}, 0, 0, S_ZAPSB10, 0}, // S_ZAPSB9 + {SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20 , 2, {NULL}, 0, 0, S_ZAPSB11, 0}, // S_ZAPSB10 + {SPR_NULL, 0, 15*2, {NULL}, 0, 0, S_ZAPSB2 , 0}, // S_ZAPSB11 // Thunder spark - {SPR_SSPK, FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 1, 2, S_NULL}, // S_THUNDERCOIN_SPARK + {SPR_SSPK, FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 1, 2, S_NULL, 0}, // S_THUNDERCOIN_SPARK // Invincibility Sparkles - {SPR_IVSP, FF_ANIMATE|FF_FULLBRIGHT, 32, {NULL}, 31, 1, S_NULL}, // S_IVSP + {SPR_IVSP, FF_ANIMATE|FF_FULLBRIGHT, 32, {NULL}, 31, 1, S_NULL, 0}, // S_IVSP // Super Sonic Spark - {SPR_SSPK, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SSPK2}, // S_SSPK1 - {SPR_SSPK, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SSPK3}, // S_SSPK2 - {SPR_SSPK, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SSPK4}, // S_SSPK3 - {SPR_SSPK, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SSPK5}, // S_SSPK4 - {SPR_SSPK, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_SSPK5 + {SPR_SSPK, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SSPK2, 0}, // S_SSPK1 + {SPR_SSPK, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SSPK3, 0}, // S_SSPK2 + {SPR_SSPK, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SSPK4, 0}, // S_SSPK3 + {SPR_SSPK, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SSPK5, 0}, // S_SSPK4 + {SPR_SSPK, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL, 0}, // S_SSPK5 // Flicky-sized bubble - {SPR_FBUB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_FLICKY_BUBBLE + {SPR_FBUB, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_FLICKY_BUBBLE // Bluebird - {SPR_FL01, 0, 2, {A_FlickyCheck}, S_FLICKY_01_FLAP1, S_FLICKY_01_FLAP1, S_FLICKY_01_OUT}, // S_FLICKY_01_OUT - {SPR_FL01, 1, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_01_FLAP2}, // S_FLICKY_01_FLAP1 - {SPR_FL01, 2, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_01_FLAP3}, // S_FLICKY_01_FLAP2 - {SPR_FL01, 3, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_01_FLAP1}, // S_FLICKY_01_FLAP3 - {SPR_FL01, FF_ANIMATE|1, -1, {NULL}, 2, 3, S_NULL}, // S_FLICKY_01_STAND - {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_01, 384*FRACUNIT, S_FLICKY_01_CENTER}, // S_FLICKY_01_CENTER + {SPR_FL01, 0, 2, {A_FlickyCheck}, S_FLICKY_01_FLAP1, S_FLICKY_01_FLAP1, S_FLICKY_01_OUT, 0}, // S_FLICKY_01_OUT + {SPR_FL01, 1, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_01_FLAP2, 0}, // S_FLICKY_01_FLAP1 + {SPR_FL01, 2, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_01_FLAP3, 0}, // S_FLICKY_01_FLAP2 + {SPR_FL01, 3, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_01_FLAP1, 0}, // S_FLICKY_01_FLAP3 + {SPR_FL01, FF_ANIMATE|1, -1, {NULL}, 2, 3, S_NULL, 0}, // S_FLICKY_01_STAND + {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_01, 384*FRACUNIT, S_FLICKY_01_CENTER, 0}, // S_FLICKY_01_CENTER // Rabbit - {SPR_FL02, 0, 2, {A_FlickyCheck}, S_FLICKY_02_AIM, 0, S_FLICKY_02_OUT}, // S_FLICKY_02_OUT - {SPR_FL02, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_02_HOP}, // S_FLICKY_02_AIM - {SPR_FL02, 1, 1, {A_FlickyHop}, 6*FRACUNIT, 4*FRACUNIT, S_FLICKY_02_UP}, // S_FLICKY_02_HOP - {SPR_FL02, 2, 2, {A_FlickyCheck}, S_FLICKY_02_AIM, S_FLICKY_02_DOWN, S_FLICKY_02_UP}, // S_FLICKY_02_UP - {SPR_FL02, 3, 2, {A_FlickyCheck}, S_FLICKY_02_AIM, 0, S_FLICKY_02_DOWN}, // S_FLICKY_02_DOWN - {SPR_FL02, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_02_STAND - {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_02, 384*FRACUNIT, S_FLICKY_02_CENTER}, // S_FLICKY_02_CENTER + {SPR_FL02, 0, 2, {A_FlickyCheck}, S_FLICKY_02_AIM, 0, S_FLICKY_02_OUT, 0}, // S_FLICKY_02_OUT + {SPR_FL02, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_02_HOP, 0}, // S_FLICKY_02_AIM + {SPR_FL02, 1, 1, {A_FlickyHop}, 6*FRACUNIT, 4*FRACUNIT, S_FLICKY_02_UP, 0}, // S_FLICKY_02_HOP + {SPR_FL02, 2, 2, {A_FlickyCheck}, S_FLICKY_02_AIM, S_FLICKY_02_DOWN, S_FLICKY_02_UP, 0}, // S_FLICKY_02_UP + {SPR_FL02, 3, 2, {A_FlickyCheck}, S_FLICKY_02_AIM, 0, S_FLICKY_02_DOWN, 0}, // S_FLICKY_02_DOWN + {SPR_FL02, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL, 0}, // S_FLICKY_02_STAND + {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_02, 384*FRACUNIT, S_FLICKY_02_CENTER, 0}, // S_FLICKY_02_CENTER // Chicken - {SPR_FL03, 0, 2, {A_FlickyCheck}, S_FLICKY_03_AIM, S_FLICKY_03_FLAP1, S_FLICKY_03_OUT}, // S_FLICKY_03_OUT - {SPR_FL03, 1, 1, {A_FlickyAim}, ANGLE_45, 32*FRACUNIT, S_FLICKY_03_HOP}, // S_FLICKY_03_AIM - {SPR_FL03, 1, 1, {A_FlickyHop}, 7*FRACUNIT, 2*FRACUNIT, S_FLICKY_03_UP}, // S_FLICKY_03_HOP - {SPR_FL03, 2, 2, {A_FlickyFlutter}, S_FLICKY_03_HOP, S_FLICKY_03_FLAP1, S_FLICKY_03_UP}, // S_FLICKY_03_UP - {SPR_FL03, 3, 2, {A_FlickyFlutter}, S_FLICKY_03_HOP, 0, S_FLICKY_03_FLAP2}, // S_FLICKY_03_FLAP1 - {SPR_FL03, 4, 2, {A_FlickyFlutter}, S_FLICKY_03_HOP, 0, S_FLICKY_03_FLAP1}, // S_FLICKY_03_FLAP2 - {SPR_FL03, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_03_STAND - {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_03, 384*FRACUNIT, S_FLICKY_03_CENTER}, // S_FLICKY_03_CENTER + {SPR_FL03, 0, 2, {A_FlickyCheck}, S_FLICKY_03_AIM, S_FLICKY_03_FLAP1, S_FLICKY_03_OUT, 0}, // S_FLICKY_03_OUT + {SPR_FL03, 1, 1, {A_FlickyAim}, ANGLE_45, 32*FRACUNIT, S_FLICKY_03_HOP, 0}, // S_FLICKY_03_AIM + {SPR_FL03, 1, 1, {A_FlickyHop}, 7*FRACUNIT, 2*FRACUNIT, S_FLICKY_03_UP, 0}, // S_FLICKY_03_HOP + {SPR_FL03, 2, 2, {A_FlickyFlutter}, S_FLICKY_03_HOP, S_FLICKY_03_FLAP1, S_FLICKY_03_UP, 0}, // S_FLICKY_03_UP + {SPR_FL03, 3, 2, {A_FlickyFlutter}, S_FLICKY_03_HOP, 0, S_FLICKY_03_FLAP2, 0}, // S_FLICKY_03_FLAP1 + {SPR_FL03, 4, 2, {A_FlickyFlutter}, S_FLICKY_03_HOP, 0, S_FLICKY_03_FLAP1, 0}, // S_FLICKY_03_FLAP2 + {SPR_FL03, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL, 0}, // S_FLICKY_03_STAND + {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_03, 384*FRACUNIT, S_FLICKY_03_CENTER, 0}, // S_FLICKY_03_CENTER // Seal - {SPR_FL04, 0, 2, {A_FlickyCheck}, S_FLICKY_04_AIM, 0, S_FLICKY_04_OUT}, // S_FLICKY_04_OUT - {SPR_FL04, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_04_HOP}, // S_FLICKY_04_AIM - {SPR_FL04, 1, 1, {A_FlickyHop}, 3*FRACUNIT, 2*FRACUNIT, S_FLICKY_04_UP}, // S_FLICKY_04_HOP - {SPR_FL04, 2, 4, {A_FlickyCheck}, S_FLICKY_04_AIM, S_FLICKY_04_DOWN, S_FLICKY_04_UP}, // S_FLICKY_04_UP - {SPR_FL04, 3, 4, {A_FlickyCheck}, S_FLICKY_04_AIM, 0, S_FLICKY_04_DOWN}, // S_FLICKY_04_DOWN - {SPR_FL04, 3, 4, {A_FlickyFly}, 2*FRACUNIT, 48*FRACUNIT, S_FLICKY_04_SWIM2}, // S_FLICKY_04_SWIM1 - {SPR_FL04, 4, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_04_SWIM1, S_FLICKY_04_SWIM3}, // S_FLICKY_04_SWIM2 - {SPR_FL04, 3, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_04_SWIM1, S_FLICKY_04_SWIM4}, // S_FLICKY_04_SWIM3 - {SPR_FL04, 5, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_04_SWIM1, S_FLICKY_04_SWIM1}, // S_FLICKY_04_SWIM4 - {SPR_FL04, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_04_STAND - {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_04, 384*FRACUNIT, S_FLICKY_04_CENTER}, // S_FLICKY_04_CENTER + {SPR_FL04, 0, 2, {A_FlickyCheck}, S_FLICKY_04_AIM, 0, S_FLICKY_04_OUT, 0}, // S_FLICKY_04_OUT + {SPR_FL04, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_04_HOP, 0}, // S_FLICKY_04_AIM + {SPR_FL04, 1, 1, {A_FlickyHop}, 3*FRACUNIT, 2*FRACUNIT, S_FLICKY_04_UP, 0}, // S_FLICKY_04_HOP + {SPR_FL04, 2, 4, {A_FlickyCheck}, S_FLICKY_04_AIM, S_FLICKY_04_DOWN, S_FLICKY_04_UP, 0}, // S_FLICKY_04_UP + {SPR_FL04, 3, 4, {A_FlickyCheck}, S_FLICKY_04_AIM, 0, S_FLICKY_04_DOWN, 0}, // S_FLICKY_04_DOWN + {SPR_FL04, 3, 4, {A_FlickyFly}, 2*FRACUNIT, 48*FRACUNIT, S_FLICKY_04_SWIM2, 0}, // S_FLICKY_04_SWIM1 + {SPR_FL04, 4, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_04_SWIM1, S_FLICKY_04_SWIM3, 0}, // S_FLICKY_04_SWIM2 + {SPR_FL04, 3, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_04_SWIM1, S_FLICKY_04_SWIM4, 0}, // S_FLICKY_04_SWIM3 + {SPR_FL04, 5, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_04_SWIM1, S_FLICKY_04_SWIM1, 0}, // S_FLICKY_04_SWIM4 + {SPR_FL04, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL, 0}, // S_FLICKY_04_STAND + {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_04, 384*FRACUNIT, S_FLICKY_04_CENTER, 0}, // S_FLICKY_04_CENTER // Pig - {SPR_FL05, 0, 2, {A_FlickyCheck}, S_FLICKY_05_AIM, 0, S_FLICKY_05_OUT}, // S_FLICKY_05_OUT - {SPR_FL05, 1, 1, {A_FlickyAim}, ANG20, 32*FRACUNIT, S_FLICKY_05_HOP}, // S_FLICKY_05_AIM - {SPR_FL05, 1, 1, {A_FlickyHop}, 4*FRACUNIT, 3*FRACUNIT, S_FLICKY_05_UP}, // S_FLICKY_05_HOP - {SPR_FL05, 2, 2, {A_FlickyCheck}, S_FLICKY_05_AIM, S_FLICKY_05_DOWN, S_FLICKY_05_UP}, // S_FLICKY_05_UP - {SPR_FL05, 3, 2, {A_FlickyCheck}, S_FLICKY_05_AIM, 0, S_FLICKY_05_DOWN}, // S_FLICKY_05_DOWN - {SPR_FL05, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_05_STAND - {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_05, 384*FRACUNIT, S_FLICKY_05_CENTER}, // S_FLICKY_05_CENTER + {SPR_FL05, 0, 2, {A_FlickyCheck}, S_FLICKY_05_AIM, 0, S_FLICKY_05_OUT, 0}, // S_FLICKY_05_OUT + {SPR_FL05, 1, 1, {A_FlickyAim}, ANG20, 32*FRACUNIT, S_FLICKY_05_HOP, 0}, // S_FLICKY_05_AIM + {SPR_FL05, 1, 1, {A_FlickyHop}, 4*FRACUNIT, 3*FRACUNIT, S_FLICKY_05_UP, 0}, // S_FLICKY_05_HOP + {SPR_FL05, 2, 2, {A_FlickyCheck}, S_FLICKY_05_AIM, S_FLICKY_05_DOWN, S_FLICKY_05_UP, 0}, // S_FLICKY_05_UP + {SPR_FL05, 3, 2, {A_FlickyCheck}, S_FLICKY_05_AIM, 0, S_FLICKY_05_DOWN, 0}, // S_FLICKY_05_DOWN + {SPR_FL05, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL, 0}, // S_FLICKY_05_STAND + {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_05, 384*FRACUNIT, S_FLICKY_05_CENTER, 0}, // S_FLICKY_05_CENTER // Chipmunk - {SPR_FL06, 0, 2, {A_FlickyCheck}, S_FLICKY_06_AIM, 0, S_FLICKY_06_OUT}, // S_FLICKY_06_OUT - {SPR_FL06, 1, 1, {A_FlickyAim}, ANGLE_90, 32*FRACUNIT, S_FLICKY_06_HOP}, // S_FLICKY_06_AIM - {SPR_FL06, 1, 1, {A_FlickyHop}, 5*FRACUNIT, 6*FRACUNIT, S_FLICKY_06_UP}, // S_FLICKY_06_HOP - {SPR_FL06, 2, 2, {A_FlickyCheck}, S_FLICKY_06_AIM, S_FLICKY_06_DOWN, S_FLICKY_06_UP}, // S_FLICKY_06_UP - {SPR_FL06, 3, 2, {A_FlickyCheck}, S_FLICKY_06_AIM, 0, S_FLICKY_06_DOWN}, // S_FLICKY_06_DOWN - {SPR_FL06, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_06_STAND - {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_06, 384*FRACUNIT, S_FLICKY_06_CENTER}, // S_FLICKY_06_CENTER + {SPR_FL06, 0, 2, {A_FlickyCheck}, S_FLICKY_06_AIM, 0, S_FLICKY_06_OUT, 0}, // S_FLICKY_06_OUT + {SPR_FL06, 1, 1, {A_FlickyAim}, ANGLE_90, 32*FRACUNIT, S_FLICKY_06_HOP, 0}, // S_FLICKY_06_AIM + {SPR_FL06, 1, 1, {A_FlickyHop}, 5*FRACUNIT, 6*FRACUNIT, S_FLICKY_06_UP, 0}, // S_FLICKY_06_HOP + {SPR_FL06, 2, 2, {A_FlickyCheck}, S_FLICKY_06_AIM, S_FLICKY_06_DOWN, S_FLICKY_06_UP, 0}, // S_FLICKY_06_UP + {SPR_FL06, 3, 2, {A_FlickyCheck}, S_FLICKY_06_AIM, 0, S_FLICKY_06_DOWN, 0}, // S_FLICKY_06_DOWN + {SPR_FL06, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL, 0}, // S_FLICKY_06_STAND + {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_06, 384*FRACUNIT, S_FLICKY_06_CENTER, 0}, // S_FLICKY_06_CENTER // Penguin - {SPR_FL07, 0, 2, {A_FlickyCheck}, S_FLICKY_07_AIML, 0, S_FLICKY_07_OUT}, // S_FLICKY_07_OUT - {SPR_FL07, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_07_HOPL}, // S_FLICKY_07_AIML - {SPR_FL07, 1, 1, {A_FlickyHop}, 4*FRACUNIT, 2*FRACUNIT, S_FLICKY_07_UPL}, // S_FLICKY_07_HOPL - {SPR_FL07, 2, 4, {A_FlickyCheck}, S_FLICKY_07_AIMR, S_FLICKY_07_DOWNL, S_FLICKY_07_UPL}, // S_FLICKY_07_UPL - {SPR_FL07, 1, 4, {A_FlickyCheck}, S_FLICKY_07_AIMR, 0, S_FLICKY_07_DOWNL}, // S_FLICKY_07_DOWNL - {SPR_FL07, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_07_HOPR}, // S_FLICKY_07_AIMR - {SPR_FL07, 1, 1, {A_FlickyHop}, 4*FRACUNIT, 2*FRACUNIT, S_FLICKY_07_UPR}, // S_FLICKY_07_HOPR - {SPR_FL07, 3, 4, {A_FlickyCheck}, S_FLICKY_07_AIML, S_FLICKY_07_DOWNR, S_FLICKY_07_UPR}, // S_FLICKY_07_UPR - {SPR_FL07, 1, 4, {A_FlickyCheck}, S_FLICKY_07_AIML, 0, S_FLICKY_07_DOWNR}, // S_FLICKY_07_DOWNR - {SPR_FL07, 4, 4, {A_FlickyFly}, 3*FRACUNIT, 72*FRACUNIT, S_FLICKY_07_SWIM2}, // S_FLICKY_07_SWIM1 - {SPR_FL07, 5, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_07_SWIM1, S_FLICKY_07_SWIM3}, // S_FLICKY_07_SWIM2 - {SPR_FL07, 6, 4, {A_FlickyCoast}, 2*FRACUNIT, S_FLICKY_07_SWIM1, S_FLICKY_07_SWIM3}, // S_FLICKY_07_SWIM3 - {SPR_FL07, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_07_STAND - {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_07, 384*FRACUNIT, S_FLICKY_07_CENTER}, // S_FLICKY_07_CENTER + {SPR_FL07, 0, 2, {A_FlickyCheck}, S_FLICKY_07_AIML, 0, S_FLICKY_07_OUT, 0}, // S_FLICKY_07_OUT + {SPR_FL07, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_07_HOPL, 0}, // S_FLICKY_07_AIML + {SPR_FL07, 1, 1, {A_FlickyHop}, 4*FRACUNIT, 2*FRACUNIT, S_FLICKY_07_UPL, 0}, // S_FLICKY_07_HOPL + {SPR_FL07, 2, 4, {A_FlickyCheck}, S_FLICKY_07_AIMR, S_FLICKY_07_DOWNL, S_FLICKY_07_UPL, 0}, // S_FLICKY_07_UPL + {SPR_FL07, 1, 4, {A_FlickyCheck}, S_FLICKY_07_AIMR, 0, S_FLICKY_07_DOWNL, 0}, // S_FLICKY_07_DOWNL + {SPR_FL07, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_07_HOPR, 0}, // S_FLICKY_07_AIMR + {SPR_FL07, 1, 1, {A_FlickyHop}, 4*FRACUNIT, 2*FRACUNIT, S_FLICKY_07_UPR, 0}, // S_FLICKY_07_HOPR + {SPR_FL07, 3, 4, {A_FlickyCheck}, S_FLICKY_07_AIML, S_FLICKY_07_DOWNR, S_FLICKY_07_UPR, 0}, // S_FLICKY_07_UPR + {SPR_FL07, 1, 4, {A_FlickyCheck}, S_FLICKY_07_AIML, 0, S_FLICKY_07_DOWNR, 0}, // S_FLICKY_07_DOWNR + {SPR_FL07, 4, 4, {A_FlickyFly}, 3*FRACUNIT, 72*FRACUNIT, S_FLICKY_07_SWIM2, 0}, // S_FLICKY_07_SWIM1 + {SPR_FL07, 5, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_07_SWIM1, S_FLICKY_07_SWIM3, 0}, // S_FLICKY_07_SWIM2 + {SPR_FL07, 6, 4, {A_FlickyCoast}, 2*FRACUNIT, S_FLICKY_07_SWIM1, S_FLICKY_07_SWIM3, 0}, // S_FLICKY_07_SWIM3 + {SPR_FL07, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL, 0}, // S_FLICKY_07_STAND + {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_07, 384*FRACUNIT, S_FLICKY_07_CENTER, 0}, // S_FLICKY_07_CENTER // Fish - {SPR_FL08, 0, 2, {A_FlickyCheck}, S_FLICKY_08_AIM, 0, S_FLICKY_08_OUT}, // S_FLICKY_08_OUT - {SPR_FL08, 2, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_08_HOP}, // S_FLICKY_08_AIM - {SPR_FL08, 2, 1, {A_FlickyFlounder}, 2*FRACUNIT, 1*FRACUNIT, S_FLICKY_08_FLAP1}, // S_FLICKY_08_HOP - {SPR_FL08, 0, 4, {A_FlickyCheck}, S_FLICKY_08_AIM, 0, S_FLICKY_08_FLAP2}, // S_FLICKY_08_FLAP1 - {SPR_FL08, 1, 4, {A_FlickyCheck}, S_FLICKY_08_AIM, 0, S_FLICKY_08_FLAP3}, // S_FLICKY_08_FLAP2 - {SPR_FL08, 0, 4, {A_FlickyCheck}, S_FLICKY_08_AIM, 0, S_FLICKY_08_FLAP4}, // S_FLICKY_08_FLAP3 - {SPR_FL08, 2, 4, {A_FlickyCheck}, S_FLICKY_08_AIM, 0, S_FLICKY_08_FLAP1}, // S_FLICKY_08_FLAP4 - {SPR_FL08, 0, 4, {A_FlickyFly}, 3*FRACUNIT, 64*FRACUNIT, S_FLICKY_08_SWIM2}, // S_FLICKY_08_SWIM1 - {SPR_FL08, 1, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_08_SWIM1, S_FLICKY_08_SWIM3}, // S_FLICKY_08_SWIM2 - {SPR_FL08, 0, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_08_SWIM1, S_FLICKY_08_SWIM4}, // S_FLICKY_08_SWIM3 - {SPR_FL08, 2, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_08_SWIM1, S_FLICKY_08_SWIM4}, // S_FLICKY_08_SWIM4 - {SPR_FL08, FF_ANIMATE, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_08_STAND - {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_08, 384*FRACUNIT, S_FLICKY_08_CENTER}, // S_FLICKY_08_CENTER + {SPR_FL08, 0, 2, {A_FlickyCheck}, S_FLICKY_08_AIM, 0, S_FLICKY_08_OUT, 0}, // S_FLICKY_08_OUT + {SPR_FL08, 2, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_08_HOP, 0}, // S_FLICKY_08_AIM + {SPR_FL08, 2, 1, {A_FlickyFlounder}, 2*FRACUNIT, 1*FRACUNIT, S_FLICKY_08_FLAP1, 0}, // S_FLICKY_08_HOP + {SPR_FL08, 0, 4, {A_FlickyCheck}, S_FLICKY_08_AIM, 0, S_FLICKY_08_FLAP2, 0}, // S_FLICKY_08_FLAP1 + {SPR_FL08, 1, 4, {A_FlickyCheck}, S_FLICKY_08_AIM, 0, S_FLICKY_08_FLAP3, 0}, // S_FLICKY_08_FLAP2 + {SPR_FL08, 0, 4, {A_FlickyCheck}, S_FLICKY_08_AIM, 0, S_FLICKY_08_FLAP4, 0}, // S_FLICKY_08_FLAP3 + {SPR_FL08, 2, 4, {A_FlickyCheck}, S_FLICKY_08_AIM, 0, S_FLICKY_08_FLAP1, 0}, // S_FLICKY_08_FLAP4 + {SPR_FL08, 0, 4, {A_FlickyFly}, 3*FRACUNIT, 64*FRACUNIT, S_FLICKY_08_SWIM2, 0}, // S_FLICKY_08_SWIM1 + {SPR_FL08, 1, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_08_SWIM1, S_FLICKY_08_SWIM3, 0}, // S_FLICKY_08_SWIM2 + {SPR_FL08, 0, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_08_SWIM1, S_FLICKY_08_SWIM4, 0}, // S_FLICKY_08_SWIM3 + {SPR_FL08, 2, 4, {A_FlickyCoast}, FRACUNIT, S_FLICKY_08_SWIM1, S_FLICKY_08_SWIM4, 0}, // S_FLICKY_08_SWIM4 + {SPR_FL08, FF_ANIMATE, -1, {NULL}, 2, 4, S_NULL, 0}, // S_FLICKY_08_STAND + {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_08, 384*FRACUNIT, S_FLICKY_08_CENTER, 0}, // S_FLICKY_08_CENTER // Ram - {SPR_FL09, 0, 2, {A_FlickyCheck}, S_FLICKY_09_AIM, 0, S_FLICKY_09_OUT}, // S_FLICKY_09_OUT - {SPR_FL09, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_09_HOP}, // S_FLICKY_09_AIM - {SPR_FL09, 1, 1, {A_FlickyHop}, 7*FRACUNIT, 2*FRACUNIT, S_FLICKY_09_UP}, // S_FLICKY_09_HOP - {SPR_FL09, 2, 2, {A_FlickyCheck}, S_FLICKY_09_AIM, S_FLICKY_09_DOWN, S_FLICKY_09_UP}, // S_FLICKY_09_UP - {SPR_FL09, 3, 2, {A_FlickyCheck}, S_FLICKY_09_AIM, 0, S_FLICKY_09_DOWN}, // S_FLICKY_09_DOWN - {SPR_FL09, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_09_STAND - {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_09, 384*FRACUNIT, S_FLICKY_09_CENTER}, // S_FLICKY_09_CENTER + {SPR_FL09, 0, 2, {A_FlickyCheck}, S_FLICKY_09_AIM, 0, S_FLICKY_09_OUT, 0}, // S_FLICKY_09_OUT + {SPR_FL09, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_09_HOP, 0}, // S_FLICKY_09_AIM + {SPR_FL09, 1, 1, {A_FlickyHop}, 7*FRACUNIT, 2*FRACUNIT, S_FLICKY_09_UP, 0}, // S_FLICKY_09_HOP + {SPR_FL09, 2, 2, {A_FlickyCheck}, S_FLICKY_09_AIM, S_FLICKY_09_DOWN, S_FLICKY_09_UP, 0}, // S_FLICKY_09_UP + {SPR_FL09, 3, 2, {A_FlickyCheck}, S_FLICKY_09_AIM, 0, S_FLICKY_09_DOWN, 0}, // S_FLICKY_09_DOWN + {SPR_FL09, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL, 0}, // S_FLICKY_09_STAND + {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_09, 384*FRACUNIT, S_FLICKY_09_CENTER, 0}, // S_FLICKY_09_CENTER // Puffin - {SPR_FL10, 0, 2, {A_FlickyCheck}, S_FLICKY_10_FLAP1, S_FLICKY_10_FLAP1, S_FLICKY_10_OUT}, // S_FLICKY_10_OUT - {SPR_FL10, 1, 3, {A_FlickySoar}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_10_FLAP2}, // S_FLICKY_10_FLAP1 - {SPR_FL10, 2, 3, {A_FlickySoar}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_10_FLAP1}, // S_FLICKY_10_FLAP2 - {SPR_FL10, FF_ANIMATE|1, -1, {NULL}, 1, 3, S_NULL}, // S_FLICKY_10_STAND - {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_10, 384*FRACUNIT, S_FLICKY_10_CENTER}, // S_FLICKY_10_CENTER + {SPR_FL10, 0, 2, {A_FlickyCheck}, S_FLICKY_10_FLAP1, S_FLICKY_10_FLAP1, S_FLICKY_10_OUT, 0}, // S_FLICKY_10_OUT + {SPR_FL10, 1, 3, {A_FlickySoar}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_10_FLAP2, 0}, // S_FLICKY_10_FLAP1 + {SPR_FL10, 2, 3, {A_FlickySoar}, 4*FRACUNIT, 16*FRACUNIT, S_FLICKY_10_FLAP1, 0}, // S_FLICKY_10_FLAP2 + {SPR_FL10, FF_ANIMATE|1, -1, {NULL}, 1, 3, S_NULL, 0}, // S_FLICKY_10_STAND + {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_10, 384*FRACUNIT, S_FLICKY_10_CENTER, 0}, // S_FLICKY_10_CENTER // Cow - {SPR_FL11, 0, 2, {A_FlickyCheck}, S_FLICKY_11_AIM, 0, S_FLICKY_11_OUT}, // S_FLICKY_11_OUT - {SPR_FL11, 1, 1, {A_FlickyAim}, ANGLE_90, 64*FRACUNIT, S_FLICKY_11_RUN1}, // S_FLICKY_11_AIM - {SPR_FL11, 1, 3, {A_FlickyHop}, FRACUNIT/2, 2*FRACUNIT, S_FLICKY_11_RUN2}, // S_FLICKY_11_RUN1 - {SPR_FL11, 2, 4, {A_FlickyHop}, FRACUNIT/2, 2*FRACUNIT, S_FLICKY_11_RUN3}, // S_FLICKY_11_RUN2 - {SPR_FL11, 3, 4, {A_FlickyHop}, FRACUNIT/2, 2*FRACUNIT, S_FLICKY_11_AIM}, // S_FLICKY_11_RUN3 - {SPR_FL11, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_11_STAND - {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_11, 384*FRACUNIT, S_FLICKY_11_CENTER}, // S_FLICKY_11_CENTER + {SPR_FL11, 0, 2, {A_FlickyCheck}, S_FLICKY_11_AIM, 0, S_FLICKY_11_OUT, 0}, // S_FLICKY_11_OUT + {SPR_FL11, 1, 1, {A_FlickyAim}, ANGLE_90, 64*FRACUNIT, S_FLICKY_11_RUN1, 0}, // S_FLICKY_11_AIM + {SPR_FL11, 1, 3, {A_FlickyHop}, FRACUNIT/2, 2*FRACUNIT, S_FLICKY_11_RUN2, 0}, // S_FLICKY_11_RUN1 + {SPR_FL11, 2, 4, {A_FlickyHop}, FRACUNIT/2, 2*FRACUNIT, S_FLICKY_11_RUN3, 0}, // S_FLICKY_11_RUN2 + {SPR_FL11, 3, 4, {A_FlickyHop}, FRACUNIT/2, 2*FRACUNIT, S_FLICKY_11_AIM, 0}, // S_FLICKY_11_RUN3 + {SPR_FL11, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL, 0}, // S_FLICKY_11_STAND + {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_11, 384*FRACUNIT, S_FLICKY_11_CENTER, 0}, // S_FLICKY_11_CENTER // Rat - {SPR_FL12, 0, 2, {A_FlickyCheck}, S_FLICKY_12_AIM, 0, S_FLICKY_12_OUT}, // S_FLICKY_12_OUT - {SPR_FL12, 1, 1, {A_FlickyAim}, ANGLE_90, 32*FRACUNIT, S_FLICKY_12_RUN1}, // S_FLICKY_12_AIM - {SPR_FL12, 1, 2, {A_FlickyHop}, 1, 12*FRACUNIT, S_FLICKY_12_RUN2}, // S_FLICKY_12_RUN1 - {SPR_FL12, 2, 3, {A_FlickyHop}, 1, 12*FRACUNIT, S_FLICKY_12_RUN3}, // S_FLICKY_12_RUN2 - {SPR_FL12, 3, 3, {A_FlickyHop}, 1, 12*FRACUNIT, S_FLICKY_12_AIM}, // S_FLICKY_12_RUN3 - {SPR_FL12, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_12_STAND - {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_12, 384*FRACUNIT, S_FLICKY_12_CENTER}, // S_FLICKY_12_CENTER + {SPR_FL12, 0, 2, {A_FlickyCheck}, S_FLICKY_12_AIM, 0, S_FLICKY_12_OUT, 0}, // S_FLICKY_12_OUT + {SPR_FL12, 1, 1, {A_FlickyAim}, ANGLE_90, 32*FRACUNIT, S_FLICKY_12_RUN1, 0}, // S_FLICKY_12_AIM + {SPR_FL12, 1, 2, {A_FlickyHop}, 1, 12*FRACUNIT, S_FLICKY_12_RUN2, 0}, // S_FLICKY_12_RUN1 + {SPR_FL12, 2, 3, {A_FlickyHop}, 1, 12*FRACUNIT, S_FLICKY_12_RUN3, 0}, // S_FLICKY_12_RUN2 + {SPR_FL12, 3, 3, {A_FlickyHop}, 1, 12*FRACUNIT, S_FLICKY_12_AIM, 0}, // S_FLICKY_12_RUN3 + {SPR_FL12, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL, 0}, // S_FLICKY_12_STAND + {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_12, 384*FRACUNIT, S_FLICKY_12_CENTER, 0}, // S_FLICKY_12_CENTER // Bear - {SPR_FL13, 0, 2, {A_FlickyCheck}, S_FLICKY_13_AIM, 0, S_FLICKY_13_OUT}, // S_FLICKY_13_OUT - {SPR_FL13, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_13_HOP}, // S_FLICKY_13_AIM - {SPR_FL13, 1, 1, {A_FlickyHop}, 5*FRACUNIT, 3*FRACUNIT, S_FLICKY_13_UP}, // S_FLICKY_13_HOP - {SPR_FL13, 2, 2, {A_FlickyCheck}, S_FLICKY_13_AIM, S_FLICKY_13_DOWN, S_FLICKY_13_UP}, // S_FLICKY_13_UP - {SPR_FL13, 3, 2, {A_FlickyCheck}, S_FLICKY_13_AIM, 0, S_FLICKY_13_DOWN}, // S_FLICKY_13_DOWN - {SPR_FL13, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_13_STAND - {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_13, 384*FRACUNIT, S_FLICKY_13_CENTER}, // S_FLICKY_13_CENTER + {SPR_FL13, 0, 2, {A_FlickyCheck}, S_FLICKY_13_AIM, 0, S_FLICKY_13_OUT, 0}, // S_FLICKY_13_OUT + {SPR_FL13, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_13_HOP, 0}, // S_FLICKY_13_AIM + {SPR_FL13, 1, 1, {A_FlickyHop}, 5*FRACUNIT, 3*FRACUNIT, S_FLICKY_13_UP, 0}, // S_FLICKY_13_HOP + {SPR_FL13, 2, 2, {A_FlickyCheck}, S_FLICKY_13_AIM, S_FLICKY_13_DOWN, S_FLICKY_13_UP, 0}, // S_FLICKY_13_UP + {SPR_FL13, 3, 2, {A_FlickyCheck}, S_FLICKY_13_AIM, 0, S_FLICKY_13_DOWN, 0}, // S_FLICKY_13_DOWN + {SPR_FL13, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL, 0}, // S_FLICKY_13_STAND + {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_13, 384*FRACUNIT, S_FLICKY_13_CENTER, 0}, // S_FLICKY_13_CENTER // Dove - {SPR_FL14, 0, 2, {A_FlickyCheck}, S_FLICKY_14_FLAP1, S_FLICKY_14_FLAP1, S_FLICKY_14_OUT}, // S_FLICKY_14_OUT - {SPR_FL14, 1, 3, {A_FlickySoar}, 4*FRACUNIT, 32*FRACUNIT, S_FLICKY_14_FLAP2}, // S_FLICKY_14_FLAP1 - {SPR_FL14, 2, 3, {A_FlickySoar}, 4*FRACUNIT, 32*FRACUNIT, S_FLICKY_14_FLAP3}, // S_FLICKY_14_FLAP2 - {SPR_FL14, 3, 3, {A_FlickySoar}, 4*FRACUNIT, 32*FRACUNIT, S_FLICKY_14_FLAP1}, // S_FLICKY_14_FLAP3 - {SPR_FL14, FF_ANIMATE|1, -1, {NULL}, 2, 3, S_NULL}, // S_FLICKY_14_STAND - {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_14, 384*FRACUNIT, S_FLICKY_14_CENTER}, // S_FLICKY_14_CENTER + {SPR_FL14, 0, 2, {A_FlickyCheck}, S_FLICKY_14_FLAP1, S_FLICKY_14_FLAP1, S_FLICKY_14_OUT, 0}, // S_FLICKY_14_OUT + {SPR_FL14, 1, 3, {A_FlickySoar}, 4*FRACUNIT, 32*FRACUNIT, S_FLICKY_14_FLAP2, 0}, // S_FLICKY_14_FLAP1 + {SPR_FL14, 2, 3, {A_FlickySoar}, 4*FRACUNIT, 32*FRACUNIT, S_FLICKY_14_FLAP3, 0}, // S_FLICKY_14_FLAP2 + {SPR_FL14, 3, 3, {A_FlickySoar}, 4*FRACUNIT, 32*FRACUNIT, S_FLICKY_14_FLAP1, 0}, // S_FLICKY_14_FLAP3 + {SPR_FL14, FF_ANIMATE|1, -1, {NULL}, 2, 3, S_NULL, 0}, // S_FLICKY_14_STAND + {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_14, 384*FRACUNIT, S_FLICKY_14_CENTER, 0}, // S_FLICKY_14_CENTER // Cat - {SPR_FL15, 0, 2, {A_FlickyCheck}, S_FLICKY_15_AIM, 0, S_FLICKY_15_OUT}, // S_FLICKY_15_OUT - {SPR_FL15, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_15_HOP}, // S_FLICKY_15_AIM - {SPR_FL15, 1, 1, {A_FlickyFlounder}, 2*FRACUNIT, 6*FRACUNIT, S_FLICKY_15_UP}, // S_FLICKY_15_HOP - {SPR_FL15, 2, 2, {A_FlickyCheck}, S_FLICKY_15_AIM, S_FLICKY_15_DOWN, S_FLICKY_15_UP}, // S_FLICKY_15_UP - {SPR_FL15, 3, 2, {A_FlickyCheck}, S_FLICKY_15_AIM, 0, S_FLICKY_15_DOWN}, // S_FLICKY_15_DOWN - {SPR_FL15, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_FLICKY_15_STAND - {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_15, 384*FRACUNIT, S_FLICKY_15_CENTER}, // S_FLICKY_15_CENTER + {SPR_FL15, 0, 2, {A_FlickyCheck}, S_FLICKY_15_AIM, 0, S_FLICKY_15_OUT, 0}, // S_FLICKY_15_OUT + {SPR_FL15, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_FLICKY_15_HOP, 0}, // S_FLICKY_15_AIM + {SPR_FL15, 1, 1, {A_FlickyFlounder}, 2*FRACUNIT, 6*FRACUNIT, S_FLICKY_15_UP, 0}, // S_FLICKY_15_HOP + {SPR_FL15, 2, 2, {A_FlickyCheck}, S_FLICKY_15_AIM, S_FLICKY_15_DOWN, S_FLICKY_15_UP, 0}, // S_FLICKY_15_UP + {SPR_FL15, 3, 2, {A_FlickyCheck}, S_FLICKY_15_AIM, 0, S_FLICKY_15_DOWN, 0}, // S_FLICKY_15_DOWN + {SPR_FL15, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL, 0}, // S_FLICKY_15_STAND + {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_15, 384*FRACUNIT, S_FLICKY_15_CENTER, 0}, // S_FLICKY_15_CENTER // Canary - {SPR_FL16, 0, 2, {A_FlickyHeightCheck}, S_FLICKY_16_FLAP1, 0, S_FLICKY_16_OUT}, // S_FLICKY_16_OUT - {SPR_FL16, 1, 3, {A_FlickyFly}, 4*FRACUNIT, 8*FRACUNIT, S_FLICKY_16_FLAP2}, // S_FLICKY_16_FLAP1 - {SPR_FL16, 2, 3, {A_SetObjectFlags}, MF_NOGRAVITY, 1, S_FLICKY_16_FLAP3}, // S_FLICKY_16_FLAP2 - {SPR_FL16, 3, 3, {A_FlickyHeightCheck}, S_FLICKY_16_FLAP1, 0, S_FLICKY_16_FLAP3}, // S_FLICKY_16_FLAP3 - {SPR_FL16, FF_ANIMATE|1, -1, {NULL}, 2, 3, S_NULL}, // S_FLICKY_16_STAND - {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_16, 384*FRACUNIT, S_FLICKY_16_CENTER}, // S_FLICKY_16_CENTER + {SPR_FL16, 0, 2, {A_FlickyHeightCheck}, S_FLICKY_16_FLAP1, 0, S_FLICKY_16_OUT, 0}, // S_FLICKY_16_OUT + {SPR_FL16, 1, 3, {A_FlickyFly}, 4*FRACUNIT, 8*FRACUNIT, S_FLICKY_16_FLAP2, 0}, // S_FLICKY_16_FLAP1 + {SPR_FL16, 2, 3, {A_SetObjectFlags}, MF_NOGRAVITY, 1, S_FLICKY_16_FLAP3, 0}, // S_FLICKY_16_FLAP2 + {SPR_FL16, 3, 3, {A_FlickyHeightCheck}, S_FLICKY_16_FLAP1, 0, S_FLICKY_16_FLAP3, 0}, // S_FLICKY_16_FLAP3 + {SPR_FL16, FF_ANIMATE|1, -1, {NULL}, 2, 3, S_NULL, 0}, // S_FLICKY_16_STAND + {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_FLICKY_16, 384*FRACUNIT, S_FLICKY_16_CENTER, 0}, // S_FLICKY_16_CENTER // Spider - {SPR_FS01, 0, 2, {A_FlickyCheck}, S_SECRETFLICKY_01_AIM, 0, S_SECRETFLICKY_01_OUT}, // S_SECRETFLICKY_01_OUT - {SPR_FS01, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_SECRETFLICKY_01_HOP}, // S_SECRETFLICKY_01_AIM - {SPR_FS01, 1, 1, {A_FlickyFlounder}, 2*FRACUNIT, 6*FRACUNIT, S_SECRETFLICKY_01_UP}, // S_SECRETFLICKY_01_HOP - {SPR_FS01, 2, 2, {A_FlickyCheck}, S_SECRETFLICKY_01_AIM, S_SECRETFLICKY_01_DOWN, S_SECRETFLICKY_01_UP}, // S_SECRETFLICKY_01_UP - {SPR_FS01, 3, 2, {A_FlickyCheck}, S_SECRETFLICKY_01_AIM, 0, S_SECRETFLICKY_01_DOWN}, // S_SECRETFLICKY_01_DOWN - {SPR_FS01, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL}, // S_SECRETFLICKY_01_STAND - {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_SECRETFLICKY_01, 384*FRACUNIT, S_SECRETFLICKY_01_CENTER}, // S_SECRETFLICKY_01_CENTER + {SPR_FS01, 0, 2, {A_FlickyCheck}, S_SECRETFLICKY_01_AIM, 0, S_SECRETFLICKY_01_OUT, 0}, // S_SECRETFLICKY_01_OUT + {SPR_FS01, 1, 1, {A_FlickyAim}, ANG30, 32*FRACUNIT, S_SECRETFLICKY_01_HOP, 0}, // S_SECRETFLICKY_01_AIM + {SPR_FS01, 1, 1, {A_FlickyFlounder}, 2*FRACUNIT, 6*FRACUNIT, S_SECRETFLICKY_01_UP, 0}, // S_SECRETFLICKY_01_HOP + {SPR_FS01, 2, 2, {A_FlickyCheck}, S_SECRETFLICKY_01_AIM, S_SECRETFLICKY_01_DOWN, S_SECRETFLICKY_01_UP, 0}, // S_SECRETFLICKY_01_UP + {SPR_FS01, 3, 2, {A_FlickyCheck}, S_SECRETFLICKY_01_AIM, 0, S_SECRETFLICKY_01_DOWN, 0}, // S_SECRETFLICKY_01_DOWN + {SPR_FS01, FF_ANIMATE|1, -1, {NULL}, 2, 4, S_NULL, 0}, // S_SECRETFLICKY_01_STAND + {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_SECRETFLICKY_01, 384*FRACUNIT, S_SECRETFLICKY_01_CENTER, 0}, // S_SECRETFLICKY_01_CENTER // Bat - {SPR_FS02, 0, 2, {A_FlickyHeightCheck}, S_SECRETFLICKY_02_FLAP1, S_SECRETFLICKY_02_FLAP1, S_SECRETFLICKY_02_OUT}, // S_SECRETFLICKY_02_OUT - {SPR_FS02, 1, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_SECRETFLICKY_02_FLAP2}, // S_SECRETFLICKY_02_FLAP1 - {SPR_FS02, 2, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_SECRETFLICKY_02_FLAP3}, // S_SECRETFLICKY_02_FLAP2 - {SPR_FS02, 3, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_SECRETFLICKY_02_FLAP1}, // S_SECRETFLICKY_02_FLAP3 - {SPR_FS02, FF_ANIMATE|1, -1, {NULL}, 2, 2, S_NULL}, // S_SECRETFLICKY_02_STAND - {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_SECRETFLICKY_02, 384*FRACUNIT, S_SECRETFLICKY_02_CENTER}, // S_SECRETFLICKY_02_CENTER + {SPR_FS02, 0, 2, {A_FlickyHeightCheck}, S_SECRETFLICKY_02_FLAP1, S_SECRETFLICKY_02_FLAP1, S_SECRETFLICKY_02_OUT, 0}, // S_SECRETFLICKY_02_OUT + {SPR_FS02, 1, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_SECRETFLICKY_02_FLAP2, 0}, // S_SECRETFLICKY_02_FLAP1 + {SPR_FS02, 2, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_SECRETFLICKY_02_FLAP3, 0}, // S_SECRETFLICKY_02_FLAP2 + {SPR_FS02, 3, 3, {A_FlickyFly}, 4*FRACUNIT, 16*FRACUNIT, S_SECRETFLICKY_02_FLAP1, 0}, // S_SECRETFLICKY_02_FLAP3 + {SPR_FS02, FF_ANIMATE|1, -1, {NULL}, 2, 2, S_NULL, 0}, // S_SECRETFLICKY_02_STAND + {SPR_NULL, 0, 15, {A_FlickyCenter}, MT_SECRETFLICKY_02, 384*FRACUNIT, S_SECRETFLICKY_02_CENTER, 0}, // S_SECRETFLICKY_02_CENTER // Fan - {SPR_FANS, 0, 1, {A_FanBubbleSpawn}, 2048, 0, S_FAN2}, // S_FAN - {SPR_FANS, 1, 1, {A_FanBubbleSpawn}, 1024, 0, S_FAN3}, // S_FAN2 - {SPR_FANS, 2, 1, {A_FanBubbleSpawn}, 512, 0, S_FAN4}, // S_FAN3 - {SPR_FANS, 3, 1, {A_FanBubbleSpawn}, 1024, 0, S_FAN5}, // S_FAN4 - {SPR_FANS, 4, 1, {A_FanBubbleSpawn}, 512, 0, S_FAN}, // S_FAN5 + {SPR_FANS, 0, 1, {A_FanBubbleSpawn}, 2048, 0, S_FAN2, 0}, // S_FAN + {SPR_FANS, 1, 1, {A_FanBubbleSpawn}, 1024, 0, S_FAN3, 0}, // S_FAN2 + {SPR_FANS, 2, 1, {A_FanBubbleSpawn}, 512, 0, S_FAN4, 0}, // S_FAN3 + {SPR_FANS, 3, 1, {A_FanBubbleSpawn}, 1024, 0, S_FAN5, 0}, // S_FAN4 + {SPR_FANS, 4, 1, {A_FanBubbleSpawn}, 512, 0, S_FAN, 0}, // S_FAN5 // Steam Riser - {SPR_STEM, 0, 2, {A_SetSolidSteam}, 0, 0, S_STEAM2}, // S_STEAM1 - {SPR_STEM, 1, 2, {A_UnsetSolidSteam}, 0, 0, S_STEAM3}, // S_STEAM2 - {SPR_STEM, 2, 2, {NULL}, 0, 0, S_STEAM4}, // S_STEAM3 - {SPR_STEM, 3, 2, {NULL}, 0, 0, S_STEAM5}, // S_STEAM4 - {SPR_STEM, 4, 2, {NULL}, 0, 0, S_STEAM6}, // S_STEAM5 - {SPR_STEM, 5, 2, {NULL}, 0, 0, S_STEAM7}, // S_STEAM6 - {SPR_STEM, 6, 2, {NULL}, 0, 0, S_STEAM8}, // S_STEAM7 - {SPR_NULL, 0, 18, {NULL}, 0, 0, S_STEAM1}, // S_STEAM8 + {SPR_STEM, 0, 2, {A_SetSolidSteam}, 0, 0, S_STEAM2, 0}, // S_STEAM1 + {SPR_STEM, 1, 2, {A_UnsetSolidSteam}, 0, 0, S_STEAM3, 0}, // S_STEAM2 + {SPR_STEM, 2, 2, {NULL}, 0, 0, S_STEAM4, 0}, // S_STEAM3 + {SPR_STEM, 3, 2, {NULL}, 0, 0, S_STEAM5, 0}, // S_STEAM4 + {SPR_STEM, 4, 2, {NULL}, 0, 0, S_STEAM6, 0}, // S_STEAM5 + {SPR_STEM, 5, 2, {NULL}, 0, 0, S_STEAM7, 0}, // S_STEAM6 + {SPR_STEM, 6, 2, {NULL}, 0, 0, S_STEAM8, 0}, // S_STEAM7 + {SPR_NULL, 0, 18, {NULL}, 0, 0, S_STEAM1, 0}, // S_STEAM8 // Bumpers - {SPR_BUMP, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 3, 4, S_NULL}, // S_BUMPER - {SPR_BUMP, FF_ANIMATE|4, 12, {A_Pain}, 1, 3, S_BUMPER}, //S_BUMPERHIT + {SPR_BUMP, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 3, 4, S_NULL, 0}, // S_BUMPER + {SPR_BUMP, FF_ANIMATE|4, 12, {A_Pain}, 1, 3, S_BUMPER, 0}, //S_BUMPERHIT // Balloons - {SPR_BLON, FF_ANIMATE, -1, {NULL}, 2, 5, S_NULL}, // S_BALLOON - {SPR_BLON, 3, 0, {A_RemoteDamage}, 0, 1, S_BALLOONPOP2}, // S_BALLOONPOP1 - {SPR_BLON, 3, 1, {A_Pain}, 0, 0, S_BALLOONPOP3}, // S_BALLOONPOP2 - {SPR_BLON, 4, 1, {NULL}, 0, 0, S_BALLOONPOP4}, // S_BALLOONPOP3 - {SPR_NULL, 0, TICRATE, {A_CheckFlags2}, MF2_AMBUSH, S_BALLOONPOP5, S_NULL}, // S_BALLOONPOP4 - {SPR_NULL, 0, 15*TICRATE, {NULL}, 0, 0, S_BALLOONPOP6}, // S_BALLOONPOP5 - {SPR_NULL, 0, 0, {A_SpawnFreshCopy}, 0, 0, S_NULL}, // S_BALLOONPOP6 + {SPR_BLON, FF_ANIMATE, -1, {NULL}, 2, 5, S_NULL, 0}, // S_BALLOON + {SPR_BLON, 3, 0, {A_RemoteDamage}, 0, 1, S_BALLOONPOP2, 0}, // S_BALLOONPOP1 + {SPR_BLON, 3, 1, {A_Pain}, 0, 0, S_BALLOONPOP3, 0}, // S_BALLOONPOP2 + {SPR_BLON, 4, 1, {NULL}, 0, 0, S_BALLOONPOP4, 0}, // S_BALLOONPOP3 + {SPR_NULL, 0, TICRATE, {A_CheckFlags2}, MF2_AMBUSH, S_BALLOONPOP5, S_NULL, 0}, // S_BALLOONPOP4 + {SPR_NULL, 0, 15*TICRATE, {NULL}, 0, 0, S_BALLOONPOP6, 0}, // S_BALLOONPOP5 + {SPR_NULL, 0, 0, {A_SpawnFreshCopy}, 0, 0, S_NULL, 0}, // S_BALLOONPOP6 // Yellow Spring - {SPR_SPRY, 0, -1, {NULL}, 0, 0, S_NULL}, // S_YELLOWSPRING - {SPR_SPRY, 4, 4, {A_Pain}, 0, 0, S_YELLOWSPRING3}, // S_YELLOWSPRING2 - {SPR_SPRY, 3, 1, {NULL}, 0, 0, S_YELLOWSPRING4}, // S_YELLOWSPRING3 - {SPR_SPRY, 2, 1, {NULL}, 0, 0, S_YELLOWSPRING5}, // S_YELLOWSPRING4 - {SPR_SPRY, 1, 1, {NULL}, 0, 0, S_YELLOWSPRING}, // S_YELLOWSPRING5 + {SPR_SPRY, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_YELLOWSPRING + {SPR_SPRY, 4, 4, {A_Pain}, 0, 0, S_YELLOWSPRING3, 0}, // S_YELLOWSPRING2 + {SPR_SPRY, 3, 1, {NULL}, 0, 0, S_YELLOWSPRING4, 0}, // S_YELLOWSPRING3 + {SPR_SPRY, 2, 1, {NULL}, 0, 0, S_YELLOWSPRING5, 0}, // S_YELLOWSPRING4 + {SPR_SPRY, 1, 1, {NULL}, 0, 0, S_YELLOWSPRING, 0}, // S_YELLOWSPRING5 // Red Spring - {SPR_SPRR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_REDSPRING - {SPR_SPRR, 4, 4, {A_Pain}, 0, 0, S_REDSPRING3}, // S_REDSPRING2 - {SPR_SPRR, 3, 1, {NULL}, 0, 0, S_REDSPRING4}, // S_REDSPRING3 - {SPR_SPRR, 2, 1, {NULL}, 0, 0, S_REDSPRING5}, // S_REDSPRING4 - {SPR_SPRR, 1, 1, {NULL}, 0, 0, S_REDSPRING}, // S_REDSPRING5 + {SPR_SPRR, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_REDSPRING + {SPR_SPRR, 4, 4, {A_Pain}, 0, 0, S_REDSPRING3, 0}, // S_REDSPRING2 + {SPR_SPRR, 3, 1, {NULL}, 0, 0, S_REDSPRING4, 0}, // S_REDSPRING3 + {SPR_SPRR, 2, 1, {NULL}, 0, 0, S_REDSPRING5, 0}, // S_REDSPRING4 + {SPR_SPRR, 1, 1, {NULL}, 0, 0, S_REDSPRING, 0}, // S_REDSPRING5 // Blue Spring - {SPR_SPRB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BLUESPRING - {SPR_SPRB, 4, 4, {A_Pain}, 0, 0, S_BLUESPRING3}, // S_BLUESPRING2 - {SPR_SPRB, 3, 1, {NULL}, 0, 0, S_BLUESPRING4}, // S_BLUESPRING3 - {SPR_SPRB, 2, 1, {NULL}, 0, 0, S_BLUESPRING5}, // S_BLUESPRING4 - {SPR_SPRB, 1, 1, {NULL}, 0, 0, S_BLUESPRING}, // S_BLUESPRING5 + {SPR_SPRB, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BLUESPRING + {SPR_SPRB, 4, 4, {A_Pain}, 0, 0, S_BLUESPRING3, 0}, // S_BLUESPRING2 + {SPR_SPRB, 3, 1, {NULL}, 0, 0, S_BLUESPRING4, 0}, // S_BLUESPRING3 + {SPR_SPRB, 2, 1, {NULL}, 0, 0, S_BLUESPRING5, 0}, // S_BLUESPRING4 + {SPR_SPRB, 1, 1, {NULL}, 0, 0, S_BLUESPRING, 0}, // S_BLUESPRING5 // Yellow Diagonal Spring - {SPR_YSPR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_YDIAG1 - {SPR_YSPR, 1, 1, {A_Pain}, 0, 0, S_YDIAG3}, // S_YDIAG2 - {SPR_YSPR, 2, 1, {NULL}, 0, 0, S_YDIAG4}, // S_YDIAG3 - {SPR_YSPR, 3, 1, {NULL}, 0, 0, S_YDIAG5}, // S_YDIAG4 - {SPR_YSPR, 4, 1, {NULL}, 0, 0, S_YDIAG6}, // S_YDIAG5 - {SPR_YSPR, 3, 1, {NULL}, 0, 0, S_YDIAG7}, // S_YDIAG6 - {SPR_YSPR, 2, 1, {NULL}, 0, 0, S_YDIAG8}, // S_YDIAG7 - {SPR_YSPR, 1, 1, {NULL}, 0, 0, S_YDIAG1}, // S_YDIAG8 + {SPR_YSPR, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_YDIAG1 + {SPR_YSPR, 1, 1, {A_Pain}, 0, 0, S_YDIAG3, 0}, // S_YDIAG2 + {SPR_YSPR, 2, 1, {NULL}, 0, 0, S_YDIAG4, 0}, // S_YDIAG3 + {SPR_YSPR, 3, 1, {NULL}, 0, 0, S_YDIAG5, 0}, // S_YDIAG4 + {SPR_YSPR, 4, 1, {NULL}, 0, 0, S_YDIAG6, 0}, // S_YDIAG5 + {SPR_YSPR, 3, 1, {NULL}, 0, 0, S_YDIAG7, 0}, // S_YDIAG6 + {SPR_YSPR, 2, 1, {NULL}, 0, 0, S_YDIAG8, 0}, // S_YDIAG7 + {SPR_YSPR, 1, 1, {NULL}, 0, 0, S_YDIAG1, 0}, // S_YDIAG8 // Red Diagonal Spring - {SPR_RSPR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_RDIAG1 - {SPR_RSPR, 1, 1, {A_Pain}, 0, 0, S_RDIAG3}, // S_RDIAG2 - {SPR_RSPR, 2, 1, {NULL}, 0, 0, S_RDIAG4}, // S_RDIAG3 - {SPR_RSPR, 3, 1, {NULL}, 0, 0, S_RDIAG5}, // S_RDIAG4 - {SPR_RSPR, 4, 1, {NULL}, 0, 0, S_RDIAG6}, // S_RDIAG5 - {SPR_RSPR, 3, 1, {NULL}, 0, 0, S_RDIAG7}, // S_RDIAG6 - {SPR_RSPR, 2, 1, {NULL}, 0, 0, S_RDIAG8}, // S_RDIAG7 - {SPR_RSPR, 1, 1, {NULL}, 0, 0, S_RDIAG1}, // S_RDIAG8 + {SPR_RSPR, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_RDIAG1 + {SPR_RSPR, 1, 1, {A_Pain}, 0, 0, S_RDIAG3, 0}, // S_RDIAG2 + {SPR_RSPR, 2, 1, {NULL}, 0, 0, S_RDIAG4, 0}, // S_RDIAG3 + {SPR_RSPR, 3, 1, {NULL}, 0, 0, S_RDIAG5, 0}, // S_RDIAG4 + {SPR_RSPR, 4, 1, {NULL}, 0, 0, S_RDIAG6, 0}, // S_RDIAG5 + {SPR_RSPR, 3, 1, {NULL}, 0, 0, S_RDIAG7, 0}, // S_RDIAG6 + {SPR_RSPR, 2, 1, {NULL}, 0, 0, S_RDIAG8, 0}, // S_RDIAG7 + {SPR_RSPR, 1, 1, {NULL}, 0, 0, S_RDIAG1, 0}, // S_RDIAG8 // Blue Diagonal Spring - {SPR_BSPR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BDIAG1 - {SPR_BSPR, 1, 1, {A_Pain}, 0, 0, S_BDIAG3}, // S_BDIAG2 - {SPR_BSPR, 2, 1, {NULL}, 0, 0, S_BDIAG4}, // S_BDIAG3 - {SPR_BSPR, 3, 1, {NULL}, 0, 0, S_BDIAG5}, // S_BDIAG4 - {SPR_BSPR, 4, 1, {NULL}, 0, 0, S_BDIAG6}, // S_BDIAG5 - {SPR_BSPR, 3, 1, {NULL}, 0, 0, S_BDIAG7}, // S_BDIAG6 - {SPR_BSPR, 2, 1, {NULL}, 0, 0, S_BDIAG8}, // S_BDIAG7 - {SPR_BSPR, 1, 1, {NULL}, 0, 0, S_BDIAG1}, // S_BDIAG8 + {SPR_BSPR, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BDIAG1 + {SPR_BSPR, 1, 1, {A_Pain}, 0, 0, S_BDIAG3, 0}, // S_BDIAG2 + {SPR_BSPR, 2, 1, {NULL}, 0, 0, S_BDIAG4, 0}, // S_BDIAG3 + {SPR_BSPR, 3, 1, {NULL}, 0, 0, S_BDIAG5, 0}, // S_BDIAG4 + {SPR_BSPR, 4, 1, {NULL}, 0, 0, S_BDIAG6, 0}, // S_BDIAG5 + {SPR_BSPR, 3, 1, {NULL}, 0, 0, S_BDIAG7, 0}, // S_BDIAG6 + {SPR_BSPR, 2, 1, {NULL}, 0, 0, S_BDIAG8, 0}, // S_BDIAG7 + {SPR_BSPR, 1, 1, {NULL}, 0, 0, S_BDIAG1, 0}, // S_BDIAG8 // Yellow Side Spring - {SPR_SSWY, 0, -1, {NULL}, 0, 0, S_NULL}, // S_YHORIZ1 - {SPR_SSWY, 1, 1, {A_Pain}, 0, 0, S_YHORIZ3}, // S_YHORIZ2 - {SPR_SSWY, 2, 1, {NULL}, 0, 0, S_YHORIZ4}, // S_YHORIZ3 - {SPR_SSWY, 3, 1, {NULL}, 0, 0, S_YHORIZ5}, // S_YHORIZ4 - {SPR_SSWY, 4, 1, {NULL}, 0, 0, S_YHORIZ6}, // S_YHORIZ5 - {SPR_SSWY, 3, 1, {NULL}, 0, 0, S_YHORIZ7}, // S_YHORIZ6 - {SPR_SSWY, 2, 1, {NULL}, 0, 0, S_YHORIZ8}, // S_YHORIZ7 - {SPR_SSWY, 1, 1, {NULL}, 0, 0, S_YHORIZ1}, // S_YHORIZ8 + {SPR_SSWY, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_YHORIZ1 + {SPR_SSWY, 1, 1, {A_Pain}, 0, 0, S_YHORIZ3, 0}, // S_YHORIZ2 + {SPR_SSWY, 2, 1, {NULL}, 0, 0, S_YHORIZ4, 0}, // S_YHORIZ3 + {SPR_SSWY, 3, 1, {NULL}, 0, 0, S_YHORIZ5, 0}, // S_YHORIZ4 + {SPR_SSWY, 4, 1, {NULL}, 0, 0, S_YHORIZ6, 0}, // S_YHORIZ5 + {SPR_SSWY, 3, 1, {NULL}, 0, 0, S_YHORIZ7, 0}, // S_YHORIZ6 + {SPR_SSWY, 2, 1, {NULL}, 0, 0, S_YHORIZ8, 0}, // S_YHORIZ7 + {SPR_SSWY, 1, 1, {NULL}, 0, 0, S_YHORIZ1, 0}, // S_YHORIZ8 // Red Side Spring - {SPR_SSWR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_RHORIZ1 - {SPR_SSWR, 1, 1, {A_Pain}, 0, 0, S_RHORIZ3}, // S_RHORIZ2 - {SPR_SSWR, 2, 1, {NULL}, 0, 0, S_RHORIZ4}, // S_RHORIZ3 - {SPR_SSWR, 3, 1, {NULL}, 0, 0, S_RHORIZ5}, // S_RHORIZ4 - {SPR_SSWR, 4, 1, {NULL}, 0, 0, S_RHORIZ6}, // S_RHORIZ5 - {SPR_SSWR, 3, 1, {NULL}, 0, 0, S_RHORIZ7}, // S_RHORIZ6 - {SPR_SSWR, 2, 1, {NULL}, 0, 0, S_RHORIZ8}, // S_RHORIZ7 - {SPR_SSWR, 1, 1, {NULL}, 0, 0, S_RHORIZ1}, // S_RHORIZ8 + {SPR_SSWR, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_RHORIZ1 + {SPR_SSWR, 1, 1, {A_Pain}, 0, 0, S_RHORIZ3, 0}, // S_RHORIZ2 + {SPR_SSWR, 2, 1, {NULL}, 0, 0, S_RHORIZ4, 0}, // S_RHORIZ3 + {SPR_SSWR, 3, 1, {NULL}, 0, 0, S_RHORIZ5, 0}, // S_RHORIZ4 + {SPR_SSWR, 4, 1, {NULL}, 0, 0, S_RHORIZ6, 0}, // S_RHORIZ5 + {SPR_SSWR, 3, 1, {NULL}, 0, 0, S_RHORIZ7, 0}, // S_RHORIZ6 + {SPR_SSWR, 2, 1, {NULL}, 0, 0, S_RHORIZ8, 0}, // S_RHORIZ7 + {SPR_SSWR, 1, 1, {NULL}, 0, 0, S_RHORIZ1, 0}, // S_RHORIZ8 // Blue Side Spring - {SPR_SSWB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BHORIZ1 - {SPR_SSWB, 1, 1, {A_Pain}, 0, 0, S_BHORIZ3}, // S_BHORIZ2 - {SPR_SSWB, 2, 1, {NULL}, 0, 0, S_BHORIZ4}, // S_BHORIZ3 - {SPR_SSWB, 3, 1, {NULL}, 0, 0, S_BHORIZ5}, // S_BHORIZ4 - {SPR_SSWB, 4, 1, {NULL}, 0, 0, S_BHORIZ6}, // S_BHORIZ5 - {SPR_SSWB, 3, 1, {NULL}, 0, 0, S_BHORIZ7}, // S_BHORIZ6 - {SPR_SSWB, 2, 1, {NULL}, 0, 0, S_BHORIZ8}, // S_BHORIZ7 - {SPR_SSWB, 1, 1, {NULL}, 0, 0, S_BHORIZ1}, // S_BHORIZ8 + {SPR_SSWB, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BHORIZ1 + {SPR_SSWB, 1, 1, {A_Pain}, 0, 0, S_BHORIZ3, 0}, // S_BHORIZ2 + {SPR_SSWB, 2, 1, {NULL}, 0, 0, S_BHORIZ4, 0}, // S_BHORIZ3 + {SPR_SSWB, 3, 1, {NULL}, 0, 0, S_BHORIZ5, 0}, // S_BHORIZ4 + {SPR_SSWB, 4, 1, {NULL}, 0, 0, S_BHORIZ6, 0}, // S_BHORIZ5 + {SPR_SSWB, 3, 1, {NULL}, 0, 0, S_BHORIZ7, 0}, // S_BHORIZ6 + {SPR_SSWB, 2, 1, {NULL}, 0, 0, S_BHORIZ8, 0}, // S_BHORIZ7 + {SPR_SSWB, 1, 1, {NULL}, 0, 0, S_BHORIZ1, 0}, // S_BHORIZ8 // Boosters - {SPR_NULL, 0, 1, {A_Pain}, 0, 0, S_INVISIBLE}, // S_BOOSTERSOUND - {SPR_BSTY, FF_ANIMATE, -1, {NULL}, 2, 1, S_NULL}, // S_YELLOWBOOSTERROLLER - {SPR_BSTY, 3|FF_PAPERSPRITE|FF_ANIMATE, -1, {NULL}, 2, 3, S_NULL}, // S_YELLOWBOOSTERSEG_LEFT - {SPR_BSTY, 6|FF_PAPERSPRITE|FF_ANIMATE, -1, {NULL}, 2, 3, S_NULL}, // S_YELLOWBOOSTERSEG_RIGHT - {SPR_BSTY, 9|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_YELLOWBOOSTERSEG_FACE - {SPR_BSTR, FF_ANIMATE, -1, {NULL}, 2, 1, S_NULL}, // S_REDBOOSTERROLLER - {SPR_BSTR, 3|FF_PAPERSPRITE|FF_ANIMATE, -1, {NULL}, 2, 3, S_NULL}, // S_REDBOOSTERSEG_LEFT - {SPR_BSTR, 6|FF_PAPERSPRITE|FF_ANIMATE, -1, {NULL}, 2, 3, S_NULL}, // S_REDBOOSTERSEG_RIGHT - {SPR_BSTR, 9|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_REDBOOSTERSEG_FACE + {SPR_NULL, 0, 1, {A_Pain}, 0, 0, S_INVISIBLE, 0}, // S_BOOSTERSOUND + {SPR_BSTY, FF_ANIMATE, -1, {NULL}, 2, 1, S_NULL, 0}, // S_YELLOWBOOSTERROLLER + {SPR_BSTY, 3|FF_PAPERSPRITE|FF_ANIMATE, -1, {NULL}, 2, 3, S_NULL, 0}, // S_YELLOWBOOSTERSEG_LEFT + {SPR_BSTY, 6|FF_PAPERSPRITE|FF_ANIMATE, -1, {NULL}, 2, 3, S_NULL, 0}, // S_YELLOWBOOSTERSEG_RIGHT + {SPR_BSTY, 9|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL, 0}, // S_YELLOWBOOSTERSEG_FACE + {SPR_BSTR, FF_ANIMATE, -1, {NULL}, 2, 1, S_NULL, 0}, // S_REDBOOSTERROLLER + {SPR_BSTR, 3|FF_PAPERSPRITE|FF_ANIMATE, -1, {NULL}, 2, 3, S_NULL, 0}, // S_REDBOOSTERSEG_LEFT + {SPR_BSTR, 6|FF_PAPERSPRITE|FF_ANIMATE, -1, {NULL}, 2, 3, S_NULL, 0}, // S_REDBOOSTERSEG_RIGHT + {SPR_BSTR, 9|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL, 0}, // S_REDBOOSTERSEG_FACE // Rain - {SPR_RAIN, FF_FULLBRIGHT|FF_TRANS50, -1, {NULL}, 0, 0, S_NULL}, // S_RAIN1 - {SPR_RAIN, FF_FULLBRIGHT|FF_TRANS50, 1, {NULL}, 0, 0, S_RAIN1}, // S_RAINRETURN + {SPR_RAIN, FF_FULLBRIGHT|FF_TRANS50, -1, {NULL}, 0, 0, S_NULL, 0}, // S_RAIN1 + {SPR_RAIN, FF_FULLBRIGHT|FF_TRANS50, 1, {NULL}, 0, 0, S_RAIN1, 0}, // S_RAINRETURN // Snowflake - {SPR_SNO1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SNOW1 - {SPR_SNO1, 1, -1, {NULL}, 0, 0, S_NULL}, // S_SNOW2 - {SPR_SNO1, 2, -1, {NULL}, 0, 0, S_NULL}, // S_SNOW3 + {SPR_SNO1, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SNOW1 + {SPR_SNO1, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SNOW2 + {SPR_SNO1, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SNOW3 // Water Splish - {SPR_SPLH, FF_TRANS50 , 2, {NULL}, 0, 0, S_SPLISH2}, // S_SPLISH1 - {SPR_SPLH, FF_TRANS50|1, 2, {NULL}, 0, 0, S_SPLISH3}, // S_SPLISH2 - {SPR_SPLH, FF_TRANS50|2, 2, {NULL}, 0, 0, S_SPLISH4}, // S_SPLISH3 - {SPR_SPLH, FF_TRANS50|3, 2, {NULL}, 0, 0, S_SPLISH5}, // S_SPLISH4 - {SPR_SPLH, FF_TRANS50|4, 2, {NULL}, 0, 0, S_SPLISH6}, // S_SPLISH5 - {SPR_SPLH, FF_TRANS50|5, 2, {NULL}, 0, 0, S_SPLISH7}, // S_SPLISH6 - {SPR_SPLH, FF_TRANS50|6, 2, {NULL}, 0, 0, S_SPLISH8}, // S_SPLISH7 - {SPR_SPLH, FF_TRANS50|7, 2, {NULL}, 0, 0, S_SPLISH9}, // S_SPLISH8 - {SPR_SPLH, FF_TRANS50|8, 2, {NULL}, 0, 0, S_NULL}, // S_SPLISH9 + {SPR_SPLH, FF_TRANS50 , 2, {NULL}, 0, 0, S_SPLISH2, 0}, // S_SPLISH1 + {SPR_SPLH, FF_TRANS50|1, 2, {NULL}, 0, 0, S_SPLISH3, 0}, // S_SPLISH2 + {SPR_SPLH, FF_TRANS50|2, 2, {NULL}, 0, 0, S_SPLISH4, 0}, // S_SPLISH3 + {SPR_SPLH, FF_TRANS50|3, 2, {NULL}, 0, 0, S_SPLISH5, 0}, // S_SPLISH4 + {SPR_SPLH, FF_TRANS50|4, 2, {NULL}, 0, 0, S_SPLISH6, 0}, // S_SPLISH5 + {SPR_SPLH, FF_TRANS50|5, 2, {NULL}, 0, 0, S_SPLISH7, 0}, // S_SPLISH6 + {SPR_SPLH, FF_TRANS50|6, 2, {NULL}, 0, 0, S_SPLISH8, 0}, // S_SPLISH7 + {SPR_SPLH, FF_TRANS50|7, 2, {NULL}, 0, 0, S_SPLISH9, 0}, // S_SPLISH8 + {SPR_SPLH, FF_TRANS50|8, 2, {NULL}, 0, 0, S_NULL, 0}, // S_SPLISH9 // Lava splish - {SPR_LSPL, FF_ANIMATE, 16, {NULL}, 7, 2, S_NULL}, // S_LAVASPLISH + {SPR_LSPL, FF_ANIMATE, 16, {NULL}, 7, 2, S_NULL, 0}, // S_LAVASPLISH // Water Splash - {SPR_SPLA, FF_TRANS50 , 3, {NULL}, 0, 0, S_SPLASH2}, // S_SPLASH1 - {SPR_SPLA, FF_TRANS70|1, 3, {NULL}, 0, 0, S_SPLASH3}, // S_SPLASH2 - {SPR_SPLA, FF_TRANS90|2, 3, {NULL}, 0, 0, S_RAINRETURN}, // S_SPLASH3 + {SPR_SPLA, FF_TRANS50 , 3, {NULL}, 0, 0, S_SPLASH2, 0}, // S_SPLASH1 + {SPR_SPLA, FF_TRANS70|1, 3, {NULL}, 0, 0, S_SPLASH3, 0}, // S_SPLASH2 + {SPR_SPLA, FF_TRANS90|2, 3, {NULL}, 0, 0, S_RAINRETURN, 0}, // S_SPLASH3 // Smoke - {SPR_SMOK, FF_TRANS50 , 4, {NULL}, 0, 0, S_SMOKE2}, // S_SMOKE1 - {SPR_SMOK, FF_TRANS50|1, 5, {NULL}, 0, 0, S_SMOKE3}, // S_SMOKE2 - {SPR_SMOK, FF_TRANS50|2, 6, {NULL}, 0, 0, S_SMOKE4}, // S_SMOKE3 - {SPR_SMOK, FF_TRANS50|3, 7, {NULL}, 0, 0, S_SMOKE5}, // S_SMOKE4 - {SPR_SMOK, FF_TRANS50|4, 8, {NULL}, 0, 0, S_NULL}, // S_SMOKE5 + {SPR_SMOK, FF_TRANS50 , 4, {NULL}, 0, 0, S_SMOKE2, 0}, // S_SMOKE1 + {SPR_SMOK, FF_TRANS50|1, 5, {NULL}, 0, 0, S_SMOKE3, 0}, // S_SMOKE2 + {SPR_SMOK, FF_TRANS50|2, 6, {NULL}, 0, 0, S_SMOKE4, 0}, // S_SMOKE3 + {SPR_SMOK, FF_TRANS50|3, 7, {NULL}, 0, 0, S_SMOKE5, 0}, // S_SMOKE4 + {SPR_SMOK, FF_TRANS50|4, 8, {NULL}, 0, 0, S_NULL, 0}, // S_SMOKE5 // Bubbles - {SPR_BUBL, FF_TRANS50, 1, {A_BubbleRise}, 0, 1024, S_SMALLBUBBLE}, // S_SMALLBUBBLE - {SPR_BUBL, FF_TRANS50|1, 1, {A_BubbleRise}, 0, 1024, S_MEDIUMBUBBLE}, // S_MEDIUMBUBBLE + {SPR_BUBL, FF_TRANS50, 1, {A_BubbleRise}, 0, 1024, S_SMALLBUBBLE, 0}, // S_SMALLBUBBLE + {SPR_BUBL, FF_TRANS50|1, 1, {A_BubbleRise}, 0, 1024, S_MEDIUMBUBBLE, 0}, // S_MEDIUMBUBBLE // Extra Large Bubble (breathable) - {SPR_BUBL, FF_TRANS50|FF_FULLBRIGHT|2, 8, {A_BubbleRise}, 0, 1024, S_LARGEBUBBLE2}, // S_LARGEBUBBLE1 - {SPR_BUBL, FF_TRANS50|FF_FULLBRIGHT|3, 8, {A_BubbleRise}, 0, 1024, S_EXTRALARGEBUBBLE}, // S_LARGEBUBBLE2 - {SPR_BUBL, FF_TRANS50|FF_FULLBRIGHT|4, 16, {A_BubbleRise}, 0, 1024, S_EXTRALARGEBUBBLE}, // S_EXTRALARGEBUBBLE + {SPR_BUBL, FF_TRANS50|FF_FULLBRIGHT|2, 8, {A_BubbleRise}, 0, 1024, S_LARGEBUBBLE2, 0}, // S_LARGEBUBBLE1 + {SPR_BUBL, FF_TRANS50|FF_FULLBRIGHT|3, 8, {A_BubbleRise}, 0, 1024, S_EXTRALARGEBUBBLE, 0}, // S_LARGEBUBBLE2 + {SPR_BUBL, FF_TRANS50|FF_FULLBRIGHT|4, 16, {A_BubbleRise}, 0, 1024, S_EXTRALARGEBUBBLE, 0}, // S_EXTRALARGEBUBBLE // Extra Large Bubble goes POP! - {SPR_BUBL, 5, 16, {NULL}, 0, 0, S_NULL}, // S_POP1 + {SPR_BUBL, 5, 16, {NULL}, 0, 0, S_NULL, 0}, // S_POP1 - {SPR_WZAP, FF_TRANS10|FF_ANIMATE|FF_RANDOMANIM, 4, {NULL}, 3, 2, S_NULL}, // S_WATERZAP + {SPR_WZAP, FF_TRANS10|FF_ANIMATE|FF_RANDOMANIM, 4, {NULL}, 3, 2, S_NULL, 0}, // S_WATERZAP // Spindash dust - {SPR_DUST, 0, 7, {NULL}, 0, 0, S_SPINDUST2}, // S_SPINDUST1 - {SPR_DUST, 1, 6, {NULL}, 0, 0, S_SPINDUST3}, // S_SPINDUST2 - {SPR_DUST, FF_TRANS30|2, 4, {NULL}, 0, 0, S_SPINDUST4}, // S_SPINDUST3 - {SPR_DUST, FF_TRANS60|3, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST4 - {SPR_BUBL, 0, 7, {NULL}, 0, 0, S_SPINDUST_BUBBLE2}, // S_SPINDUST_BUBBLE1 - {SPR_BUBL, 0, 6, {NULL}, 0, 0, S_SPINDUST_BUBBLE3}, // S_SPINDUST_BUBBLE2 - {SPR_BUBL, FF_TRANS30|0, 4, {NULL}, 0, 0, S_SPINDUST_BUBBLE4}, // S_SPINDUST_BUBBLE3 - {SPR_BUBL, FF_TRANS60|0, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST_BUBBLE4 - {SPR_FPRT, FF_FULLBRIGHT|0, 7, {NULL}, 0, 0, S_SPINDUST_FIRE2}, // S_SPINDUST_FIRE1 - {SPR_FPRT, FF_FULLBRIGHT|0, 6, {NULL}, 0, 0, S_SPINDUST_FIRE3}, // S_SPINDUST_FIRE2 - {SPR_FPRT, FF_FULLBRIGHT|FF_TRANS30|0, 4, {NULL}, 0, 0, S_SPINDUST_FIRE4}, // S_SPINDUST_FIRE3 - {SPR_FPRT, FF_FULLBRIGHT|FF_TRANS60|0, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST_FIRE4 - - - {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50, 2, {NULL}, 0, 0, S_FOG2}, // S_FOG1 - {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|1, 2, {NULL}, 0, 0, S_FOG3}, // S_FOG2 - {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|2, 2, {NULL}, 0, 0, S_FOG4}, // S_FOG3 - {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|3, 2, {NULL}, 0, 0, S_FOG5}, // S_FOG4 - {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|4, 2, {NULL}, 0, 0, S_FOG6}, // S_FOG5 - {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|5, 2, {NULL}, 0, 0, S_FOG7}, // S_FOG6 - {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|6, 2, {NULL}, 0, 0, S_FOG8}, // S_FOG7 - {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|7, 2, {NULL}, 0, 0, S_FOG9}, // S_FOG8 - {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|8, 2, {NULL}, 0, 0, S_FOG10}, // S_FOG9 - {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|9, 2, {NULL}, 0, 0, S_FOG11}, // S_FOG10 - {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|10, 2, {NULL}, 0, 0, S_FOG12}, // S_FOG11 - {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|11, 2, {NULL}, 0, 0, S_FOG13}, // S_FOG12 - {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|12, 2, {NULL}, 0, 0, S_FOG14}, // S_FOG13 - {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|13, 2, {NULL}, 0, 0, S_NULL}, // S_FOG14 + {SPR_DUST, 0, 7, {NULL}, 0, 0, S_SPINDUST2, 0}, // S_SPINDUST1 + {SPR_DUST, 1, 6, {NULL}, 0, 0, S_SPINDUST3, 0}, // S_SPINDUST2 + {SPR_DUST, FF_TRANS30|2, 4, {NULL}, 0, 0, S_SPINDUST4, 0}, // S_SPINDUST3 + {SPR_DUST, FF_TRANS60|3, 3, {NULL}, 0, 0, S_NULL, 0}, // S_SPINDUST4 + {SPR_BUBL, 0, 7, {NULL}, 0, 0, S_SPINDUST_BUBBLE2, 0}, // S_SPINDUST_BUBBLE1 + {SPR_BUBL, 0, 6, {NULL}, 0, 0, S_SPINDUST_BUBBLE3, 0}, // S_SPINDUST_BUBBLE2 + {SPR_BUBL, FF_TRANS30|0, 4, {NULL}, 0, 0, S_SPINDUST_BUBBLE4, 0}, // S_SPINDUST_BUBBLE3 + {SPR_BUBL, FF_TRANS60|0, 3, {NULL}, 0, 0, S_NULL, 0}, // S_SPINDUST_BUBBLE4 + {SPR_FPRT, FF_FULLBRIGHT|0, 7, {NULL}, 0, 0, S_SPINDUST_FIRE2, 0}, // S_SPINDUST_FIRE1 + {SPR_FPRT, FF_FULLBRIGHT|0, 6, {NULL}, 0, 0, S_SPINDUST_FIRE3, 0}, // S_SPINDUST_FIRE2 + {SPR_FPRT, FF_FULLBRIGHT|FF_TRANS30|0, 4, {NULL}, 0, 0, S_SPINDUST_FIRE4, 0}, // S_SPINDUST_FIRE3 + {SPR_FPRT, FF_FULLBRIGHT|FF_TRANS60|0, 3, {NULL}, 0, 0, S_NULL, 0}, // S_SPINDUST_FIRE4 + + + {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50, 2, {NULL}, 0, 0, S_FOG2, 0}, // S_FOG1 + {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|1, 2, {NULL}, 0, 0, S_FOG3, 0}, // S_FOG2 + {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|2, 2, {NULL}, 0, 0, S_FOG4, 0}, // S_FOG3 + {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|3, 2, {NULL}, 0, 0, S_FOG5, 0}, // S_FOG4 + {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|4, 2, {NULL}, 0, 0, S_FOG6, 0}, // S_FOG5 + {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|5, 2, {NULL}, 0, 0, S_FOG7, 0}, // S_FOG6 + {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|6, 2, {NULL}, 0, 0, S_FOG8, 0}, // S_FOG7 + {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|7, 2, {NULL}, 0, 0, S_FOG9, 0}, // S_FOG8 + {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|8, 2, {NULL}, 0, 0, S_FOG10, 0}, // S_FOG9 + {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|9, 2, {NULL}, 0, 0, S_FOG11, 0}, // S_FOG10 + {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|10, 2, {NULL}, 0, 0, S_FOG12, 0}, // S_FOG11 + {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|11, 2, {NULL}, 0, 0, S_FOG13, 0}, // S_FOG12 + {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|12, 2, {NULL}, 0, 0, S_FOG14, 0}, // S_FOG13 + {SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|13, 2, {NULL}, 0, 0, S_NULL, 0}, // S_FOG14 // Flower Seed - {SPR_SEED, FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 2, 2, S_NULL}, // S_SEED + {SPR_SEED, FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 2, 2, S_NULL, 0}, // S_SEED // Particle sprite - {SPR_PRTL, 0, 2*TICRATE, {NULL}, 0, 0, S_NULL}, // S_PARTICLE - - {SPR_SCOR, 0, 32, {A_ScoreRise}, 0, 0, S_NULL}, // S_SCRA - 100 - {SPR_SCOR, 1, 32, {A_ScoreRise}, 0, 0, S_NULL}, // S_SCRB - 200 - {SPR_SCOR, 2, 32, {A_ScoreRise}, 0, 0, S_NULL}, // S_SCRC - 500 - {SPR_SCOR, 3, 32, {A_ScoreRise}, 0, 0, S_NULL}, // S_SCRD - 1000 - {SPR_SCOR, 4, 32, {A_ScoreRise}, 0, 0, S_NULL}, // S_SCRE - 10000 - {SPR_SCOR, 5, 32, {A_ScoreRise}, 0, 0, S_NULL}, // S_SCRF - 400 (mario mode) - {SPR_SCOR, 6, 32, {A_ScoreRise}, 0, 0, S_NULL}, // S_SCRG - 800 (mario mode) - {SPR_SCOR, 7, 32, {A_ScoreRise}, 0, 0, S_NULL}, // S_SCRH - 2000 (mario mode) - {SPR_SCOR, 8, 32, {A_ScoreRise}, 0, 0, S_NULL}, // S_SCRI - 4000 (mario mode) - {SPR_SCOR, 9, 32, {A_ScoreRise}, 0, 0, S_NULL}, // S_SCRJ - 8000 (mario mode) - {SPR_SCOR, 10, 32, {A_ScoreRise}, 0, 0, S_NULL}, // S_SCRK - 1UP (mario mode) - {SPR_SCOR, 11, 32, {A_ScoreRise}, 0, 0, S_NULL}, // S_SCRL - 10 + {SPR_PRTL, 0, 2*TICRATE, {NULL}, 0, 0, S_NULL, 0}, // S_PARTICLE + + {SPR_SCOR, 0, 32, {A_ScoreRise}, 0, 0, S_NULL, 0}, // S_SCRA - 100 + {SPR_SCOR, 1, 32, {A_ScoreRise}, 0, 0, S_NULL, 0}, // S_SCRB - 200 + {SPR_SCOR, 2, 32, {A_ScoreRise}, 0, 0, S_NULL, 0}, // S_SCRC - 500 + {SPR_SCOR, 3, 32, {A_ScoreRise}, 0, 0, S_NULL, 0}, // S_SCRD - 1000 + {SPR_SCOR, 4, 32, {A_ScoreRise}, 0, 0, S_NULL, 0}, // S_SCRE - 10000 + {SPR_SCOR, 5, 32, {A_ScoreRise}, 0, 0, S_NULL, 0}, // S_SCRF - 400 (mario mode) + {SPR_SCOR, 6, 32, {A_ScoreRise}, 0, 0, S_NULL, 0}, // S_SCRG - 800 (mario mode) + {SPR_SCOR, 7, 32, {A_ScoreRise}, 0, 0, S_NULL, 0}, // S_SCRH - 2000 (mario mode) + {SPR_SCOR, 8, 32, {A_ScoreRise}, 0, 0, S_NULL, 0}, // S_SCRI - 4000 (mario mode) + {SPR_SCOR, 9, 32, {A_ScoreRise}, 0, 0, S_NULL, 0}, // S_SCRJ - 8000 (mario mode) + {SPR_SCOR, 10, 32, {A_ScoreRise}, 0, 0, S_NULL, 0}, // S_SCRK - 1UP (mario mode) + {SPR_SCOR, 11, 32, {A_ScoreRise}, 0, 0, S_NULL, 0}, // S_SCRL - 10 // Drowning Timer Numbers - {SPR_DRWN, 0, 40, {NULL}, 0, 0, S_NULL}, // S_ZERO1 - {SPR_DRWN, 1, 40, {NULL}, 0, 0, S_NULL}, // S_ONE1 - {SPR_DRWN, 2, 40, {NULL}, 0, 0, S_NULL}, // S_TWO1 - {SPR_DRWN, 3, 40, {NULL}, 0, 0, S_NULL}, // S_THREE1 - {SPR_DRWN, 4, 40, {NULL}, 0, 0, S_NULL}, // S_FOUR1 - {SPR_DRWN, 5, 40, {NULL}, 0, 0, S_NULL}, // S_FIVE1 - - {SPR_DRWN, 6, 40, {NULL}, 0, 0, S_NULL}, // S_ZERO2 - {SPR_DRWN, 7, 40, {NULL}, 0, 0, S_NULL}, // S_ONE2 - {SPR_DRWN, 8, 40, {NULL}, 0, 0, S_NULL}, // S_TWO2 - {SPR_DRWN, 9, 40, {NULL}, 0, 0, S_NULL}, // S_THREE2 - {SPR_DRWN, 10, 40, {NULL}, 0, 0, S_NULL}, // S_FOUR2 - {SPR_DRWN, 11, 40, {NULL}, 0, 0, S_NULL}, // S_FIVE2 + {SPR_DRWN, 0, 40, {NULL}, 0, 0, S_NULL, 0}, // S_ZERO1 + {SPR_DRWN, 1, 40, {NULL}, 0, 0, S_NULL, 0}, // S_ONE1 + {SPR_DRWN, 2, 40, {NULL}, 0, 0, S_NULL, 0}, // S_TWO1 + {SPR_DRWN, 3, 40, {NULL}, 0, 0, S_NULL, 0}, // S_THREE1 + {SPR_DRWN, 4, 40, {NULL}, 0, 0, S_NULL, 0}, // S_FOUR1 + {SPR_DRWN, 5, 40, {NULL}, 0, 0, S_NULL, 0}, // S_FIVE1 + + {SPR_DRWN, 6, 40, {NULL}, 0, 0, S_NULL, 0}, // S_ZERO2 + {SPR_DRWN, 7, 40, {NULL}, 0, 0, S_NULL, 0}, // S_ONE2 + {SPR_DRWN, 8, 40, {NULL}, 0, 0, S_NULL, 0}, // S_TWO2 + {SPR_DRWN, 9, 40, {NULL}, 0, 0, S_NULL, 0}, // S_THREE2 + {SPR_DRWN, 10, 40, {NULL}, 0, 0, S_NULL, 0}, // S_FOUR2 + {SPR_DRWN, 11, 40, {NULL}, 0, 0, S_NULL, 0}, // S_FIVE2 // Flight indicator - {SPR_FLII, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 4, S_NULL}, // S_FLIGHTINDICATOR + {SPR_FLII, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 4, S_NULL, 0}, // S_FLIGHTINDICATOR - {SPR_LCKN, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON1 - {SPR_LCKN, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON2 - {SPR_LCKN, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON3 - {SPR_LCKN, 3|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON4 + {SPR_LCKN, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL, 0}, // S_LOCKON1 + {SPR_LCKN, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL, 0}, // S_LOCKON2 + {SPR_LCKN, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL, 0}, // S_LOCKON3 + {SPR_LCKN, 3|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL, 0}, // S_LOCKON4 - {SPR_LCKN, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LOCKONINF1 - {SPR_LCKN, 1|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LOCKONINF2 - {SPR_LCKN, 2|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LOCKONINF3 - {SPR_LCKN, 3|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LOCKONINF4 + {SPR_LCKN, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL, 0}, // S_LOCKONINF1 + {SPR_LCKN, 1|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL, 0}, // S_LOCKONINF2 + {SPR_LCKN, 2|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL, 0}, // S_LOCKONINF3 + {SPR_LCKN, 3|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL, 0}, // S_LOCKONINF4 - {SPR_TTAG, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_NULL}, // S_TTAG + {SPR_TTAG, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_NULL, 0}, // S_TTAG // CTF Sign - {SPR_GFLG, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_NULL}, // S_GOTFLAG + {SPR_GFLG, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_NULL, 0}, // S_GOTFLAG // Finish flag - {SPR_FNSF, FF_TRANS30, -1, {NULL}, 0, 0, S_NULL}, // S_FINISHFLAG + {SPR_FNSF, FF_TRANS30, -1, {NULL}, 0, 0, S_NULL, 0}, // S_FINISHFLAG - {SPR_CORK, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CORK - {SPR_LHRT, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LHRT + {SPR_CORK, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_CORK + {SPR_LHRT, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL, 0}, // S_LHRT // Red Rings (thrown) - {SPR_RRNG, FF_FULLBRIGHT, 1, {A_ThrownRing}, 0, 0, S_RRNG2}, // S_RRNG1 - {SPR_RRNG, FF_FULLBRIGHT|1, 1, {A_ThrownRing}, 0, 0, S_RRNG3}, // S_RRNG2 - {SPR_RRNG, FF_FULLBRIGHT|2, 1, {A_ThrownRing}, 0, 0, S_RRNG4}, // S_RRNG3 - {SPR_RRNG, FF_FULLBRIGHT|3, 1, {A_ThrownRing}, 0, 0, S_RRNG5}, // S_RRNG4 - {SPR_RRNG, FF_FULLBRIGHT|4, 1, {A_ThrownRing}, 0, 0, S_RRNG6}, // S_RRNG5 - {SPR_RRNG, FF_FULLBRIGHT|5, 1, {A_ThrownRing}, 0, 0, S_RRNG7}, // S_RRNG6 - {SPR_RRNG, FF_FULLBRIGHT|6, 1, {A_ThrownRing}, 0, 0, S_RRNG1}, // S_RRNG7 + {SPR_RRNG, FF_FULLBRIGHT, 1, {A_ThrownRing}, 0, 0, S_RRNG2, 0}, // S_RRNG1 + {SPR_RRNG, FF_FULLBRIGHT|1, 1, {A_ThrownRing}, 0, 0, S_RRNG3, 0}, // S_RRNG2 + {SPR_RRNG, FF_FULLBRIGHT|2, 1, {A_ThrownRing}, 0, 0, S_RRNG4, 0}, // S_RRNG3 + {SPR_RRNG, FF_FULLBRIGHT|3, 1, {A_ThrownRing}, 0, 0, S_RRNG5, 0}, // S_RRNG4 + {SPR_RRNG, FF_FULLBRIGHT|4, 1, {A_ThrownRing}, 0, 0, S_RRNG6, 0}, // S_RRNG5 + {SPR_RRNG, FF_FULLBRIGHT|5, 1, {A_ThrownRing}, 0, 0, S_RRNG7, 0}, // S_RRNG6 + {SPR_RRNG, FF_FULLBRIGHT|6, 1, {A_ThrownRing}, 0, 0, S_RRNG1, 0}, // S_RRNG7 // Weapon Ring Ammo - {SPR_RNGB, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 34, 1, S_BOUNCERINGAMMO}, // S_BOUNCERINGAMMO - {SPR_RNGR, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 34, 1, S_RAILRINGAMMO}, // S_RAILRINGAMMO - {SPR_RNGI, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 34, 1, S_INFINITYRINGAMMO}, // S_INFINITYRINGAMMO - {SPR_RNGA, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 34, 1, S_AUTOMATICRINGAMMO}, // S_AUTOMATICRINGAMMO - {SPR_RNGE, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 34, 1, S_EXPLOSIONRINGAMMO}, // S_EXPLOSIONRINGAMMO - {SPR_RNGS, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 34, 1, S_SCATTERRINGAMMO}, // S_SCATTERRINGAMMO - {SPR_RNGG, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 34, 1, S_GRENADERINGAMMO}, // S_GRENADERINGAMMO + {SPR_RNGB, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 34, 1, S_BOUNCERINGAMMO, 0}, // S_BOUNCERINGAMMO + {SPR_RNGR, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 34, 1, S_RAILRINGAMMO, 0}, // S_RAILRINGAMMO + {SPR_RNGI, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 34, 1, S_INFINITYRINGAMMO, 0}, // S_INFINITYRINGAMMO + {SPR_RNGA, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 34, 1, S_AUTOMATICRINGAMMO, 0}, // S_AUTOMATICRINGAMMO + {SPR_RNGE, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 34, 1, S_EXPLOSIONRINGAMMO, 0}, // S_EXPLOSIONRINGAMMO + {SPR_RNGS, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 34, 1, S_SCATTERRINGAMMO, 0}, // S_SCATTERRINGAMMO + {SPR_RNGG, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 34, 1, S_GRENADERINGAMMO, 0}, // S_GRENADERINGAMMO // Bounce Ring Pickup - {SPR_PIKB, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 15, 1, S_BOUNCEPICKUP}, // S_BOUNCEPICKUP + {SPR_PIKB, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 15, 1, S_BOUNCEPICKUP, 0}, // S_BOUNCEPICKUP - {SPR_PIKB, 0, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE2}, // S_BOUNCEPICKUPFADE1 - {SPR_PIKB, 2, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE3}, // S_BOUNCEPICKUPFADE2 - {SPR_PIKB, 4, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE4}, // S_BOUNCEPICKUPFADE3 - {SPR_PIKB, 6, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE5}, // S_BOUNCEPICKUPFADE4 - {SPR_PIKB, 8, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE6}, // S_BOUNCEPICKUPFADE5 - {SPR_PIKB, 10, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE7}, // S_BOUNCEPICKUPFADE6 - {SPR_PIKB, 12, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE8}, // S_BOUNCEPICKUPFADE7 - {SPR_PIKB, 14, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE1}, // S_BOUNCEPICKUPFADE8 + {SPR_PIKB, 0, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE2, 0}, // S_BOUNCEPICKUPFADE1 + {SPR_PIKB, 2, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE3, 0}, // S_BOUNCEPICKUPFADE2 + {SPR_PIKB, 4, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE4, 0}, // S_BOUNCEPICKUPFADE3 + {SPR_PIKB, 6, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE5, 0}, // S_BOUNCEPICKUPFADE4 + {SPR_PIKB, 8, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE6, 0}, // S_BOUNCEPICKUPFADE5 + {SPR_PIKB, 10, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE7, 0}, // S_BOUNCEPICKUPFADE6 + {SPR_PIKB, 12, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE8, 0}, // S_BOUNCEPICKUPFADE7 + {SPR_PIKB, 14, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE1, 0}, // S_BOUNCEPICKUPFADE8 // Rail Ring Pickup - {SPR_PIKR, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 15, 1, S_RAILPICKUP}, // S_RAILPICKUP + {SPR_PIKR, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 15, 1, S_RAILPICKUP, 0}, // S_RAILPICKUP - {SPR_PIKR, 0, 1, {NULL}, 0, 0, S_RAILPICKUPFADE2}, // S_RAILPICKUPFADE1 - {SPR_PIKR, 2, 1, {NULL}, 0, 0, S_RAILPICKUPFADE3}, // S_RAILPICKUPFADE2 - {SPR_PIKR, 4, 1, {NULL}, 0, 0, S_RAILPICKUPFADE4}, // S_RAILPICKUPFADE3 - {SPR_PIKR, 6, 1, {NULL}, 0, 0, S_RAILPICKUPFADE5}, // S_RAILPICKUPFADE4 - {SPR_PIKR, 8, 1, {NULL}, 0, 0, S_RAILPICKUPFADE6}, // S_RAILPICKUPFADE5 - {SPR_PIKR, 10, 1, {NULL}, 0, 0, S_RAILPICKUPFADE7}, // S_RAILPICKUPFADE6 - {SPR_PIKR, 12, 1, {NULL}, 0, 0, S_RAILPICKUPFADE8}, // S_RAILPICKUPFADE7 - {SPR_PIKR, 14, 1, {NULL}, 0, 0, S_RAILPICKUPFADE1}, // S_RAILPICKUPFADE8 + {SPR_PIKR, 0, 1, {NULL}, 0, 0, S_RAILPICKUPFADE2, 0}, // S_RAILPICKUPFADE1 + {SPR_PIKR, 2, 1, {NULL}, 0, 0, S_RAILPICKUPFADE3, 0}, // S_RAILPICKUPFADE2 + {SPR_PIKR, 4, 1, {NULL}, 0, 0, S_RAILPICKUPFADE4, 0}, // S_RAILPICKUPFADE3 + {SPR_PIKR, 6, 1, {NULL}, 0, 0, S_RAILPICKUPFADE5, 0}, // S_RAILPICKUPFADE4 + {SPR_PIKR, 8, 1, {NULL}, 0, 0, S_RAILPICKUPFADE6, 0}, // S_RAILPICKUPFADE5 + {SPR_PIKR, 10, 1, {NULL}, 0, 0, S_RAILPICKUPFADE7, 0}, // S_RAILPICKUPFADE6 + {SPR_PIKR, 12, 1, {NULL}, 0, 0, S_RAILPICKUPFADE8, 0}, // S_RAILPICKUPFADE7 + {SPR_PIKR, 14, 1, {NULL}, 0, 0, S_RAILPICKUPFADE1, 0}, // S_RAILPICKUPFADE8 // Auto Ring Pickup - {SPR_PIKA, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 15, 1, S_AUTOPICKUP}, // S_AUTOPICKUP + {SPR_PIKA, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 15, 1, S_AUTOPICKUP, 0}, // S_AUTOPICKUP - {SPR_PIKA, 0, 1, {NULL}, 0, 0, S_AUTOPICKUPFADE2}, // S_AUTOPICKUPFADE1 - {SPR_PIKA, 2, 1, {NULL}, 0, 0, S_AUTOPICKUPFADE3}, // S_AUTOPICKUPFADE2 - {SPR_PIKA, 4, 1, {NULL}, 0, 0, S_AUTOPICKUPFADE4}, // S_AUTOPICKUPFADE3 - {SPR_PIKA, 6, 1, {NULL}, 0, 0, S_AUTOPICKUPFADE5}, // S_AUTOPICKUPFADE4 - {SPR_PIKA, 8, 1, {NULL}, 0, 0, S_AUTOPICKUPFADE6}, // S_AUTOPICKUPFADE5 - {SPR_PIKA, 10, 1, {NULL}, 0, 0, S_AUTOPICKUPFADE7}, // S_AUTOPICKUPFADE6 - {SPR_PIKA, 12, 1, {NULL}, 0, 0, S_AUTOPICKUPFADE8}, // S_AUTOPICKUPFADE7 - {SPR_PIKA, 14, 1, {NULL}, 0, 0, S_AUTOPICKUPFADE1}, // S_AUTOPICKUPFADE8 + {SPR_PIKA, 0, 1, {NULL}, 0, 0, S_AUTOPICKUPFADE2, 0}, // S_AUTOPICKUPFADE1 + {SPR_PIKA, 2, 1, {NULL}, 0, 0, S_AUTOPICKUPFADE3, 0}, // S_AUTOPICKUPFADE2 + {SPR_PIKA, 4, 1, {NULL}, 0, 0, S_AUTOPICKUPFADE4, 0}, // S_AUTOPICKUPFADE3 + {SPR_PIKA, 6, 1, {NULL}, 0, 0, S_AUTOPICKUPFADE5, 0}, // S_AUTOPICKUPFADE4 + {SPR_PIKA, 8, 1, {NULL}, 0, 0, S_AUTOPICKUPFADE6, 0}, // S_AUTOPICKUPFADE5 + {SPR_PIKA, 10, 1, {NULL}, 0, 0, S_AUTOPICKUPFADE7, 0}, // S_AUTOPICKUPFADE6 + {SPR_PIKA, 12, 1, {NULL}, 0, 0, S_AUTOPICKUPFADE8, 0}, // S_AUTOPICKUPFADE7 + {SPR_PIKA, 14, 1, {NULL}, 0, 0, S_AUTOPICKUPFADE1, 0}, // S_AUTOPICKUPFADE8 // Explode Ring Pickup - {SPR_PIKE, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 15, 1, S_EXPLODEPICKUP}, // S_EXPLODEPICKUP + {SPR_PIKE, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 15, 1, S_EXPLODEPICKUP, 0}, // S_EXPLODEPICKUP - {SPR_PIKE, 0, 1, {NULL}, 0, 0, S_EXPLODEPICKUPFADE2}, // S_EXPLODEPICKUPFADE1 - {SPR_PIKE, 2, 1, {NULL}, 0, 0, S_EXPLODEPICKUPFADE3}, // S_EXPLODEPICKUPFADE2 - {SPR_PIKE, 4, 1, {NULL}, 0, 0, S_EXPLODEPICKUPFADE4}, // S_EXPLODEPICKUPFADE3 - {SPR_PIKE, 6, 1, {NULL}, 0, 0, S_EXPLODEPICKUPFADE5}, // S_EXPLODEPICKUPFADE4 - {SPR_PIKE, 8, 1, {NULL}, 0, 0, S_EXPLODEPICKUPFADE6}, // S_EXPLODEPICKUPFADE5 - {SPR_PIKE, 10, 1, {NULL}, 0, 0, S_EXPLODEPICKUPFADE7}, // S_EXPLODEPICKUPFADE6 - {SPR_PIKE, 12, 1, {NULL}, 0, 0, S_EXPLODEPICKUPFADE8}, // S_EXPLODEPICKUPFADE7 - {SPR_PIKE, 14, 1, {NULL}, 0, 0, S_EXPLODEPICKUPFADE1}, // S_EXPLODEPICKUPFADE8 + {SPR_PIKE, 0, 1, {NULL}, 0, 0, S_EXPLODEPICKUPFADE2, 0}, // S_EXPLODEPICKUPFADE1 + {SPR_PIKE, 2, 1, {NULL}, 0, 0, S_EXPLODEPICKUPFADE3, 0}, // S_EXPLODEPICKUPFADE2 + {SPR_PIKE, 4, 1, {NULL}, 0, 0, S_EXPLODEPICKUPFADE4, 0}, // S_EXPLODEPICKUPFADE3 + {SPR_PIKE, 6, 1, {NULL}, 0, 0, S_EXPLODEPICKUPFADE5, 0}, // S_EXPLODEPICKUPFADE4 + {SPR_PIKE, 8, 1, {NULL}, 0, 0, S_EXPLODEPICKUPFADE6, 0}, // S_EXPLODEPICKUPFADE5 + {SPR_PIKE, 10, 1, {NULL}, 0, 0, S_EXPLODEPICKUPFADE7, 0}, // S_EXPLODEPICKUPFADE6 + {SPR_PIKE, 12, 1, {NULL}, 0, 0, S_EXPLODEPICKUPFADE8, 0}, // S_EXPLODEPICKUPFADE7 + {SPR_PIKE, 14, 1, {NULL}, 0, 0, S_EXPLODEPICKUPFADE1, 0}, // S_EXPLODEPICKUPFADE8 // Scatter Ring Pickup - {SPR_PIKS, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 15, 1, S_SCATTERPICKUP}, // S_SCATTERPICKUP + {SPR_PIKS, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 15, 1, S_SCATTERPICKUP, 0}, // S_SCATTERPICKUP - {SPR_PIKS, 0, 1, {NULL}, 0, 0, S_SCATTERPICKUPFADE2}, // S_SCATTERPICKUPFADE1 - {SPR_PIKS, 2, 1, {NULL}, 0, 0, S_SCATTERPICKUPFADE3}, // S_SCATTERPICKUPFADE2 - {SPR_PIKS, 4, 1, {NULL}, 0, 0, S_SCATTERPICKUPFADE4}, // S_SCATTERPICKUPFADE3 - {SPR_PIKS, 6, 1, {NULL}, 0, 0, S_SCATTERPICKUPFADE5}, // S_SCATTERPICKUPFADE4 - {SPR_PIKS, 8, 1, {NULL}, 0, 0, S_SCATTERPICKUPFADE6}, // S_SCATTERPICKUPFADE5 - {SPR_PIKS, 10, 1, {NULL}, 0, 0, S_SCATTERPICKUPFADE7}, // S_SCATTERPICKUPFADE6 - {SPR_PIKS, 12, 1, {NULL}, 0, 0, S_SCATTERPICKUPFADE8}, // S_SCATTERPICKUPFADE7 - {SPR_PIKS, 14, 1, {NULL}, 0, 0, S_SCATTERPICKUPFADE1}, // S_SCATTERPICKUPFADE8 + {SPR_PIKS, 0, 1, {NULL}, 0, 0, S_SCATTERPICKUPFADE2, 0}, // S_SCATTERPICKUPFADE1 + {SPR_PIKS, 2, 1, {NULL}, 0, 0, S_SCATTERPICKUPFADE3, 0}, // S_SCATTERPICKUPFADE2 + {SPR_PIKS, 4, 1, {NULL}, 0, 0, S_SCATTERPICKUPFADE4, 0}, // S_SCATTERPICKUPFADE3 + {SPR_PIKS, 6, 1, {NULL}, 0, 0, S_SCATTERPICKUPFADE5, 0}, // S_SCATTERPICKUPFADE4 + {SPR_PIKS, 8, 1, {NULL}, 0, 0, S_SCATTERPICKUPFADE6, 0}, // S_SCATTERPICKUPFADE5 + {SPR_PIKS, 10, 1, {NULL}, 0, 0, S_SCATTERPICKUPFADE7, 0}, // S_SCATTERPICKUPFADE6 + {SPR_PIKS, 12, 1, {NULL}, 0, 0, S_SCATTERPICKUPFADE8, 0}, // S_SCATTERPICKUPFADE7 + {SPR_PIKS, 14, 1, {NULL}, 0, 0, S_SCATTERPICKUPFADE1, 0}, // S_SCATTERPICKUPFADE8 // Grenade Ring Pickup - {SPR_PIKG, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 15, 1, S_GRENADEPICKUP}, // S_GRENADEPICKUP + {SPR_PIKG, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 15, 1, S_GRENADEPICKUP, 0}, // S_GRENADEPICKUP - {SPR_PIKG, 0, 1, {NULL}, 0, 0, S_GRENADEPICKUPFADE2}, // S_GRENADEPICKUPFADE1 - {SPR_PIKG, 2, 1, {NULL}, 0, 0, S_GRENADEPICKUPFADE3}, // S_GRENADEPICKUPFADE2 - {SPR_PIKG, 4, 1, {NULL}, 0, 0, S_GRENADEPICKUPFADE4}, // S_GRENADEPICKUPFADE3 - {SPR_PIKG, 6, 1, {NULL}, 0, 0, S_GRENADEPICKUPFADE5}, // S_GRENADEPICKUPFADE4 - {SPR_PIKG, 8, 1, {NULL}, 0, 0, S_GRENADEPICKUPFADE6}, // S_GRENADEPICKUPFADE5 - {SPR_PIKG, 10, 1, {NULL}, 0, 0, S_GRENADEPICKUPFADE7}, // S_GRENADEPICKUPFADE6 - {SPR_PIKG, 12, 1, {NULL}, 0, 0, S_GRENADEPICKUPFADE8}, // S_GRENADEPICKUPFADE7 - {SPR_PIKG, 14, 1, {NULL}, 0, 0, S_GRENADEPICKUPFADE1}, // S_GRENADEPICKUPFADE8 + {SPR_PIKG, 0, 1, {NULL}, 0, 0, S_GRENADEPICKUPFADE2, 0}, // S_GRENADEPICKUPFADE1 + {SPR_PIKG, 2, 1, {NULL}, 0, 0, S_GRENADEPICKUPFADE3, 0}, // S_GRENADEPICKUPFADE2 + {SPR_PIKG, 4, 1, {NULL}, 0, 0, S_GRENADEPICKUPFADE4, 0}, // S_GRENADEPICKUPFADE3 + {SPR_PIKG, 6, 1, {NULL}, 0, 0, S_GRENADEPICKUPFADE5, 0}, // S_GRENADEPICKUPFADE4 + {SPR_PIKG, 8, 1, {NULL}, 0, 0, S_GRENADEPICKUPFADE6, 0}, // S_GRENADEPICKUPFADE5 + {SPR_PIKG, 10, 1, {NULL}, 0, 0, S_GRENADEPICKUPFADE7, 0}, // S_GRENADEPICKUPFADE6 + {SPR_PIKG, 12, 1, {NULL}, 0, 0, S_GRENADEPICKUPFADE8, 0}, // S_GRENADEPICKUPFADE7 + {SPR_PIKG, 14, 1, {NULL}, 0, 0, S_GRENADEPICKUPFADE1, 0}, // S_GRENADEPICKUPFADE8 // Thrown Weapon Rings - {SPR_RNGB, FF_FULLBRIGHT , 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE2}, // S_THROWNBOUNCE1 - {SPR_RNGB, FF_FULLBRIGHT| 5, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE3}, // S_THROWNBOUNCE2 - {SPR_RNGB, FF_FULLBRIGHT|10, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE4}, // S_THROWNBOUNCE3 - {SPR_RNGB, FF_FULLBRIGHT|15, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE5}, // S_THROWNBOUNCE4 - {SPR_RNGB, FF_FULLBRIGHT|20, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE6}, // S_THROWNBOUNCE5 - {SPR_RNGB, FF_FULLBRIGHT|25, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE7}, // S_THROWNBOUNCE6 - {SPR_RNGB, FF_FULLBRIGHT|30, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE1}, // S_THROWNBOUNCE7 - - {SPR_RNGI, FF_FULLBRIGHT , 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY2}, // S_THROWNINFINITY1 - {SPR_RNGI, FF_FULLBRIGHT| 5, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY3}, // S_THROWNINFINITY2 - {SPR_RNGI, FF_FULLBRIGHT|10, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY4}, // S_THROWNINFINITY3 - {SPR_RNGI, FF_FULLBRIGHT|15, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY5}, // S_THROWNINFINITY4 - {SPR_RNGI, FF_FULLBRIGHT|20, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY6}, // S_THROWNINFINITY5 - {SPR_RNGI, FF_FULLBRIGHT|25, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY7}, // S_THROWNINFINITY6 - {SPR_RNGI, FF_FULLBRIGHT|30, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY1}, // S_THROWNINFINITY7 - - {SPR_TAUT, FF_FULLBRIGHT , 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC2}, // S_THROWNAUTOMATIC1 - {SPR_TAUT, FF_FULLBRIGHT|1, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC3}, // S_THROWNAUTOMATIC2 - {SPR_TAUT, FF_FULLBRIGHT|2, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC4}, // S_THROWNAUTOMATIC3 - {SPR_TAUT, FF_FULLBRIGHT|3, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC5}, // S_THROWNAUTOMATIC4 - {SPR_TAUT, FF_FULLBRIGHT|4, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC6}, // S_THROWNAUTOMATIC5 - {SPR_TAUT, FF_FULLBRIGHT|5, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC7}, // S_THROWNAUTOMATIC6 - {SPR_TAUT, FF_FULLBRIGHT|6, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC1}, // S_THROWNAUTOMATIC7 - - {SPR_RNGE, FF_FULLBRIGHT , 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION2}, // S_THROWNEXPLOSION1 - {SPR_RNGE, FF_FULLBRIGHT| 5, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION3}, // S_THROWNEXPLOSION2 - {SPR_RNGE, FF_FULLBRIGHT|10, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION4}, // S_THROWNEXPLOSION3 - {SPR_RNGE, FF_FULLBRIGHT|15, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION5}, // S_THROWNEXPLOSION4 - {SPR_RNGE, FF_FULLBRIGHT|20, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION6}, // S_THROWNEXPLOSION5 - {SPR_RNGE, FF_FULLBRIGHT|25, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION7}, // S_THROWNEXPLOSION6 - {SPR_RNGE, FF_FULLBRIGHT|30, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION1}, // S_THROWNEXPLOSION7 - - {SPR_TGRE, FF_FULLBRIGHT , 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE2}, // S_THROWNGRENADE1 - {SPR_TGRE, FF_FULLBRIGHT| 1, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE3}, // S_THROWNGRENADE2 - {SPR_TGRE, FF_FULLBRIGHT| 2, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE4}, // S_THROWNGRENADE3 - {SPR_TGRE, FF_FULLBRIGHT| 3, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE5}, // S_THROWNGRENADE4 - {SPR_TGRE, FF_FULLBRIGHT| 4, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE6}, // S_THROWNGRENADE5 - {SPR_TGRE, FF_FULLBRIGHT| 5, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE7}, // S_THROWNGRENADE6 - {SPR_TGRE, FF_FULLBRIGHT| 6, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE8}, // S_THROWNGRENADE7 - {SPR_TGRE, FF_FULLBRIGHT| 7, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE9}, // S_THROWNGRENADE8 - {SPR_TGRE, FF_FULLBRIGHT| 8, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE10}, // S_THROWNGRENADE9 - {SPR_TGRE, FF_FULLBRIGHT| 9, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE11}, // S_THROWNGRENADE10 - {SPR_TGRE, FF_FULLBRIGHT|10, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE12}, // S_THROWNGRENADE11 - {SPR_TGRE, FF_FULLBRIGHT|11, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE13}, // S_THROWNGRENADE12 - {SPR_TGRE, FF_FULLBRIGHT|12, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE14}, // S_THROWNGRENADE13 - {SPR_TGRE, FF_FULLBRIGHT|13, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE15}, // S_THROWNGRENADE14 - {SPR_TGRE, FF_FULLBRIGHT|14, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE16}, // S_THROWNGRENADE15 - {SPR_TGRE, FF_FULLBRIGHT|15, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE17}, // S_THROWNGRENADE16 - {SPR_TGRE, FF_FULLBRIGHT|16, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE18}, // S_THROWNGRENADE17 - {SPR_TGRE, FF_FULLBRIGHT|17, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE1}, // S_THROWNGRENADE18 - - {SPR_TSCR, FF_FULLBRIGHT, 1, {A_ThrownRing}, 0, 0, S_THROWNSCATTER}, // S_THROWNSCATTER - - {SPR_NULL, 0, 1, {A_RingExplode}, 0, 0, S_XPLD1}, // S_RINGEXPLODE + {SPR_RNGB, FF_FULLBRIGHT , 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE2, 0}, // S_THROWNBOUNCE1 + {SPR_RNGB, FF_FULLBRIGHT| 5, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE3, 0}, // S_THROWNBOUNCE2 + {SPR_RNGB, FF_FULLBRIGHT|10, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE4, 0}, // S_THROWNBOUNCE3 + {SPR_RNGB, FF_FULLBRIGHT|15, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE5, 0}, // S_THROWNBOUNCE4 + {SPR_RNGB, FF_FULLBRIGHT|20, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE6, 0}, // S_THROWNBOUNCE5 + {SPR_RNGB, FF_FULLBRIGHT|25, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE7, 0}, // S_THROWNBOUNCE6 + {SPR_RNGB, FF_FULLBRIGHT|30, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE1, 0}, // S_THROWNBOUNCE7 + + {SPR_RNGI, FF_FULLBRIGHT , 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY2, 0}, // S_THROWNINFINITY1 + {SPR_RNGI, FF_FULLBRIGHT| 5, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY3, 0}, // S_THROWNINFINITY2 + {SPR_RNGI, FF_FULLBRIGHT|10, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY4, 0}, // S_THROWNINFINITY3 + {SPR_RNGI, FF_FULLBRIGHT|15, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY5, 0}, // S_THROWNINFINITY4 + {SPR_RNGI, FF_FULLBRIGHT|20, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY6, 0}, // S_THROWNINFINITY5 + {SPR_RNGI, FF_FULLBRIGHT|25, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY7, 0}, // S_THROWNINFINITY6 + {SPR_RNGI, FF_FULLBRIGHT|30, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY1, 0}, // S_THROWNINFINITY7 + + {SPR_TAUT, FF_FULLBRIGHT , 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC2, 0}, // S_THROWNAUTOMATIC1 + {SPR_TAUT, FF_FULLBRIGHT|1, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC3, 0}, // S_THROWNAUTOMATIC2 + {SPR_TAUT, FF_FULLBRIGHT|2, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC4, 0}, // S_THROWNAUTOMATIC3 + {SPR_TAUT, FF_FULLBRIGHT|3, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC5, 0}, // S_THROWNAUTOMATIC4 + {SPR_TAUT, FF_FULLBRIGHT|4, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC6, 0}, // S_THROWNAUTOMATIC5 + {SPR_TAUT, FF_FULLBRIGHT|5, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC7, 0}, // S_THROWNAUTOMATIC6 + {SPR_TAUT, FF_FULLBRIGHT|6, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC1, 0}, // S_THROWNAUTOMATIC7 + + {SPR_RNGE, FF_FULLBRIGHT , 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION2, 0}, // S_THROWNEXPLOSION1 + {SPR_RNGE, FF_FULLBRIGHT| 5, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION3, 0}, // S_THROWNEXPLOSION2 + {SPR_RNGE, FF_FULLBRIGHT|10, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION4, 0}, // S_THROWNEXPLOSION3 + {SPR_RNGE, FF_FULLBRIGHT|15, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION5, 0}, // S_THROWNEXPLOSION4 + {SPR_RNGE, FF_FULLBRIGHT|20, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION6, 0}, // S_THROWNEXPLOSION5 + {SPR_RNGE, FF_FULLBRIGHT|25, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION7, 0}, // S_THROWNEXPLOSION6 + {SPR_RNGE, FF_FULLBRIGHT|30, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION1, 0}, // S_THROWNEXPLOSION7 + + {SPR_TGRE, FF_FULLBRIGHT , 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE2, 0}, // S_THROWNGRENADE1 + {SPR_TGRE, FF_FULLBRIGHT| 1, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE3, 0}, // S_THROWNGRENADE2 + {SPR_TGRE, FF_FULLBRIGHT| 2, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE4, 0}, // S_THROWNGRENADE3 + {SPR_TGRE, FF_FULLBRIGHT| 3, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE5, 0}, // S_THROWNGRENADE4 + {SPR_TGRE, FF_FULLBRIGHT| 4, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE6, 0}, // S_THROWNGRENADE5 + {SPR_TGRE, FF_FULLBRIGHT| 5, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE7, 0}, // S_THROWNGRENADE6 + {SPR_TGRE, FF_FULLBRIGHT| 6, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE8, 0}, // S_THROWNGRENADE7 + {SPR_TGRE, FF_FULLBRIGHT| 7, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE9, 0}, // S_THROWNGRENADE8 + {SPR_TGRE, FF_FULLBRIGHT| 8, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE10, 0}, // S_THROWNGRENADE9 + {SPR_TGRE, FF_FULLBRIGHT| 9, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE11, 0}, // S_THROWNGRENADE10 + {SPR_TGRE, FF_FULLBRIGHT|10, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE12, 0}, // S_THROWNGRENADE11 + {SPR_TGRE, FF_FULLBRIGHT|11, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE13, 0}, // S_THROWNGRENADE12 + {SPR_TGRE, FF_FULLBRIGHT|12, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE14, 0}, // S_THROWNGRENADE13 + {SPR_TGRE, FF_FULLBRIGHT|13, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE15, 0}, // S_THROWNGRENADE14 + {SPR_TGRE, FF_FULLBRIGHT|14, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE16, 0}, // S_THROWNGRENADE15 + {SPR_TGRE, FF_FULLBRIGHT|15, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE17, 0}, // S_THROWNGRENADE16 + {SPR_TGRE, FF_FULLBRIGHT|16, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE18, 0}, // S_THROWNGRENADE17 + {SPR_TGRE, FF_FULLBRIGHT|17, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE1, 0}, // S_THROWNGRENADE18 + + {SPR_TSCR, FF_FULLBRIGHT, 1, {A_ThrownRing}, 0, 0, S_THROWNSCATTER, 0}, // S_THROWNSCATTER + + {SPR_NULL, 0, 1, {A_RingExplode}, 0, 0, S_XPLD1, 0}, // S_RINGEXPLODE // Coin - {SPR_COIN, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_COIN2}, // S_COIN1 - {SPR_COIN, FF_FULLBRIGHT|1, 5, {NULL}, 0, 0, S_COIN3}, // S_COIN2 - {SPR_COIN, FF_FULLBRIGHT|2, 5, {NULL}, 0, 0, S_COIN1}, // S_COIN3 + {SPR_COIN, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_COIN2, 0}, // S_COIN1 + {SPR_COIN, FF_FULLBRIGHT|1, 5, {NULL}, 0, 0, S_COIN3, 0}, // S_COIN2 + {SPR_COIN, FF_FULLBRIGHT|2, 5, {NULL}, 0, 0, S_COIN1, 0}, // S_COIN3 // Coin Sparkle - {SPR_CPRK, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_COINSPARKLE2}, // S_COINSPARKLE1 - {SPR_CPRK, FF_FULLBRIGHT|1, 5, {NULL}, 0, 0, S_COINSPARKLE3}, // S_COINSPARKLE2 - {SPR_CPRK, FF_FULLBRIGHT|2, 5, {NULL}, 0, 0, S_COINSPARKLE4}, // S_COINSPARKLE3 - {SPR_CPRK, FF_FULLBRIGHT|3, 5, {NULL}, 0, 0, S_NULL}, // S_COINSPARKLE4 + {SPR_CPRK, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_COINSPARKLE2, 0}, // S_COINSPARKLE1 + {SPR_CPRK, FF_FULLBRIGHT|1, 5, {NULL}, 0, 0, S_COINSPARKLE3, 0}, // S_COINSPARKLE2 + {SPR_CPRK, FF_FULLBRIGHT|2, 5, {NULL}, 0, 0, S_COINSPARKLE4, 0}, // S_COINSPARKLE3 + {SPR_CPRK, FF_FULLBRIGHT|3, 5, {NULL}, 0, 0, S_NULL, 0}, // S_COINSPARKLE4 // Goomba - {SPR_GOOM, 0, 6, {A_Look}, 0, 0, S_GOOMBA1B}, // S_GOOMBA1 - {SPR_GOOM, 1, 6, {A_Look}, 0, 0, S_GOOMBA1}, // S_GOOMBA1B - {SPR_GOOM, 0, 3, {A_Chase}, 0, 0, S_GOOMBA3}, // S_GOOMBA2 - {SPR_GOOM, 0, 3, {A_Chase}, 0, 0, S_GOOMBA4}, // S_GOOMBA3 - {SPR_GOOM, 1, 3, {A_Chase}, 0, 0, S_GOOMBA5}, // S_GOOMBA4 - {SPR_GOOM, 1, 3, {A_Chase}, 0, 0, S_GOOMBA6}, // S_GOOMBA5 - {SPR_GOOM, 0, 3, {A_Chase}, 0, 0, S_GOOMBA7}, // S_GOOMBA6 - {SPR_GOOM, 0, 3, {A_Chase}, 0, 0, S_GOOMBA8}, // S_GOOMBA7 - {SPR_GOOM, 1, 3, {A_Chase}, 0, 0, S_GOOMBA9}, // S_GOOMBA8 - {SPR_GOOM, 1, 3, {A_Chase}, 0, 0, S_GOOMBA2}, // S_GOOMBA9 - {SPR_GOOM, 2, 16, {A_Scream}, 0, 0, S_NULL}, // S_GOOMBA_DEAD + {SPR_GOOM, 0, 6, {A_Look}, 0, 0, S_GOOMBA1B, 0}, // S_GOOMBA1 + {SPR_GOOM, 1, 6, {A_Look}, 0, 0, S_GOOMBA1, 0}, // S_GOOMBA1B + {SPR_GOOM, 0, 3, {A_Chase}, 0, 0, S_GOOMBA3, 0}, // S_GOOMBA2 + {SPR_GOOM, 0, 3, {A_Chase}, 0, 0, S_GOOMBA4, 0}, // S_GOOMBA3 + {SPR_GOOM, 1, 3, {A_Chase}, 0, 0, S_GOOMBA5, 0}, // S_GOOMBA4 + {SPR_GOOM, 1, 3, {A_Chase}, 0, 0, S_GOOMBA6, 0}, // S_GOOMBA5 + {SPR_GOOM, 0, 3, {A_Chase}, 0, 0, S_GOOMBA7, 0}, // S_GOOMBA6 + {SPR_GOOM, 0, 3, {A_Chase}, 0, 0, S_GOOMBA8, 0}, // S_GOOMBA7 + {SPR_GOOM, 1, 3, {A_Chase}, 0, 0, S_GOOMBA9, 0}, // S_GOOMBA8 + {SPR_GOOM, 1, 3, {A_Chase}, 0, 0, S_GOOMBA2, 0}, // S_GOOMBA9 + {SPR_GOOM, 2, 16, {A_Scream}, 0, 0, S_NULL, 0}, // S_GOOMBA_DEAD // Blue Goomba - {SPR_BGOM, 0, 6, {A_Look}, 0, 0, S_BLUEGOOMBA1B}, // BLUEGOOMBA1 - {SPR_BGOM, 1, 6, {A_Look}, 0, 0, S_BLUEGOOMBA1}, // BLUEGOOMBA1B - {SPR_BGOM, 0, 3, {A_Chase}, 0, 0, S_BLUEGOOMBA3}, // S_BLUEGOOMBA2 - {SPR_BGOM, 0, 3, {A_Chase}, 0, 0, S_BLUEGOOMBA4}, // S_BLUEGOOMBA3 - {SPR_BGOM, 1, 3, {A_Chase}, 0, 0, S_BLUEGOOMBA5}, // S_BLUEGOOMBA4 - {SPR_BGOM, 1, 3, {A_Chase}, 0, 0, S_BLUEGOOMBA6}, // S_BLUEGOOMBA5 - {SPR_BGOM, 0, 3, {A_Chase}, 0, 0, S_BLUEGOOMBA7}, // S_BLUEGOOMBA6 - {SPR_BGOM, 0, 3, {A_Chase}, 0, 0, S_BLUEGOOMBA8}, // S_BLUEGOOMBA7 - {SPR_BGOM, 1, 3, {A_Chase}, 0, 0, S_BLUEGOOMBA9}, // S_BLUEGOOMBA8 - {SPR_BGOM, 1, 3, {A_Chase}, 0, 0, S_BLUEGOOMBA2}, // S_BLUEGOOMBA9 - {SPR_BGOM, 2, 16, {A_Scream}, 0, 0, S_NULL}, // S_BLUEGOOMBA_DEAD + {SPR_BGOM, 0, 6, {A_Look}, 0, 0, S_BLUEGOOMBA1B, 0}, // S_BLUEGOOMBA1 + {SPR_BGOM, 1, 6, {A_Look}, 0, 0, S_BLUEGOOMBA1, 0}, // S_BLUEGOOMBA1B + {SPR_BGOM, 0, 3, {A_Chase}, 0, 0, S_BLUEGOOMBA3, 0}, // S_BLUEGOOMBA2 + {SPR_BGOM, 0, 3, {A_Chase}, 0, 0, S_BLUEGOOMBA4, 0}, // S_BLUEGOOMBA3 + {SPR_BGOM, 1, 3, {A_Chase}, 0, 0, S_BLUEGOOMBA5, 0}, // S_BLUEGOOMBA4 + {SPR_BGOM, 1, 3, {A_Chase}, 0, 0, S_BLUEGOOMBA6, 0}, // S_BLUEGOOMBA5 + {SPR_BGOM, 0, 3, {A_Chase}, 0, 0, S_BLUEGOOMBA7, 0}, // S_BLUEGOOMBA6 + {SPR_BGOM, 0, 3, {A_Chase}, 0, 0, S_BLUEGOOMBA8, 0}, // S_BLUEGOOMBA7 + {SPR_BGOM, 1, 3, {A_Chase}, 0, 0, S_BLUEGOOMBA9, 0}, // S_BLUEGOOMBA8 + {SPR_BGOM, 1, 3, {A_Chase}, 0, 0, S_BLUEGOOMBA2, 0}, // S_BLUEGOOMBA9 + {SPR_BGOM, 2, 16, {A_Scream}, 0, 0, S_NULL, 0}, // S_BLUEGOOMBA_DEAD // Fire Flower - {SPR_FFWR, 0, 3, {NULL}, 0, 0, S_FIREFLOWER2}, // S_FIREFLOWER1 - {SPR_FFWR, 1, 3, {NULL}, 0, 0, S_FIREFLOWER3}, // S_FIREFLOWER2 - {SPR_FFWR, 2, 3, {NULL}, 0, 0, S_FIREFLOWER4}, // S_FIREFLOWER3 - {SPR_FFWR, 3, 3, {NULL}, 0, 0, S_FIREFLOWER1}, // S_FIREFLOWER4 + {SPR_FFWR, 0, 3, {NULL}, 0, 0, S_FIREFLOWER2, 0}, // S_FIREFLOWER1 + {SPR_FFWR, 1, 3, {NULL}, 0, 0, S_FIREFLOWER3, 0}, // S_FIREFLOWER2 + {SPR_FFWR, 2, 3, {NULL}, 0, 0, S_FIREFLOWER4, 0}, // S_FIREFLOWER3 + {SPR_FFWR, 3, 3, {NULL}, 0, 0, S_FIREFLOWER1, 0}, // S_FIREFLOWER4 // Thrown Mario Fireball - {SPR_FBLL, FF_FULLBRIGHT, 1, {A_SpawnObjectRelative}, 0, MT_FIREBALLTRAIL, S_FIREBALL}, // S_FIREBALL - {SPR_FBLL, 1|FF_FULLBRIGHT|FF_TRANS50, 1, {A_SetScale}, FRACUNIT*3/4, 0, S_FIREBALLTRAIL2}, // S_FIREBALLTRAIL1 - {SPR_FBLL, 1|FF_FULLBRIGHT|FF_TRANS50, 8, {A_SetScale}, FRACUNIT/6, 1, S_NULL}, // S_FIREBALLTRAIL2 + {SPR_FBLL, FF_FULLBRIGHT, 1, {A_SpawnObjectRelative}, 0, MT_FIREBALLTRAIL, S_FIREBALL, 0}, // S_FIREBALL + {SPR_FBLL, 1|FF_FULLBRIGHT|FF_TRANS50, 1, {A_SetScale}, FRACUNIT*3/4, 0, S_FIREBALLTRAIL2, 0}, // S_FIREBALLTRAIL1 + {SPR_FBLL, 1|FF_FULLBRIGHT|FF_TRANS50, 8, {A_SetScale}, FRACUNIT/6, 1, S_NULL, 0}, // S_FIREBALLTRAIL2 // Turtle Shell - {SPR_SHLL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SHELL + {SPR_SHLL, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SHELL // Puma (Mario fireball) - {SPR_PUMA, FF_FULLBRIGHT|2, 1, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_START2}, // S_PUMA_START1 - {SPR_PUMA, FF_FULLBRIGHT|2, 1, {A_PlaySound}, sfx_s3k70, 1 + (1<<16), S_PUMA_UP1}, // S_PUMA_START2 - {SPR_PUMA, FF_FULLBRIGHT , 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_UP2}, // S_PUMA_UP1 - {SPR_PUMA, FF_FULLBRIGHT|1, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_UP3}, // S_PUMA_UP2 - {SPR_PUMA, FF_FULLBRIGHT|2, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_UP1}, // S_PUMA_UP3 - {SPR_PUMA, FF_FULLBRIGHT|3, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_DOWN2}, // S_PUMA_DOWN1 - {SPR_PUMA, FF_FULLBRIGHT|4, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_DOWN3}, // S_PUMA_DOWN2 - {SPR_PUMA, FF_FULLBRIGHT|5, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_DOWN1}, // S_PUMA_DOWN3 - - {SPR_PUMA, FF_FULLBRIGHT|FF_TRANS20|6, 4, {NULL}, 0, 0, S_PUMATRAIL2}, // S_PUMATRAIL1 - {SPR_PUMA, FF_FULLBRIGHT|FF_TRANS40|6, 5, {A_SetScale}, FRACUNIT, 1, S_PUMATRAIL3}, // S_PUMATRAIL2 - {SPR_PUMA, FF_FULLBRIGHT|FF_TRANS50|7, 4, {NULL}, 0, 0, S_PUMATRAIL4}, // S_PUMATRAIL3 - {SPR_PUMA, FF_FULLBRIGHT|FF_TRANS60|8, 3, {NULL}, 0, 0, S_NULL}, // S_PUMATRAIL4 + {SPR_PUMA, FF_FULLBRIGHT|2, 1, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_START2, 0}, // S_PUMA_START1 + {SPR_PUMA, FF_FULLBRIGHT|2, 1, {A_PlaySound}, sfx_s3k70, 1 + (1<<16), S_PUMA_UP1, 0}, // S_PUMA_START2 + {SPR_PUMA, FF_FULLBRIGHT , 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_UP2, 0}, // S_PUMA_UP1 + {SPR_PUMA, FF_FULLBRIGHT|1, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_UP3, 0}, // S_PUMA_UP2 + {SPR_PUMA, FF_FULLBRIGHT|2, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_UP1, 0}, // S_PUMA_UP3 + {SPR_PUMA, FF_FULLBRIGHT|3, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_DOWN2, 0}, // S_PUMA_DOWN1 + {SPR_PUMA, FF_FULLBRIGHT|4, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_DOWN3, 0}, // S_PUMA_DOWN2 + {SPR_PUMA, FF_FULLBRIGHT|5, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_DOWN1, 0}, // S_PUMA_DOWN3 + + {SPR_PUMA, FF_FULLBRIGHT|FF_TRANS20|6, 4, {NULL}, 0, 0, S_PUMATRAIL2, 0}, // S_PUMATRAIL1 + {SPR_PUMA, FF_FULLBRIGHT|FF_TRANS40|6, 5, {A_SetScale}, FRACUNIT, 1, S_PUMATRAIL3, 0}, // S_PUMATRAIL2 + {SPR_PUMA, FF_FULLBRIGHT|FF_TRANS50|7, 4, {NULL}, 0, 0, S_PUMATRAIL4, 0}, // S_PUMATRAIL3 + {SPR_PUMA, FF_FULLBRIGHT|FF_TRANS60|8, 3, {NULL}, 0, 0, S_NULL, 0}, // S_PUMATRAIL4 // Hammer - {SPR_HAMM, FF_ANIMATE, -1, {NULL}, 3, 3, S_NULL}, // S_HAMMER + {SPR_HAMM, FF_ANIMATE, -1, {NULL}, 3, 3, S_NULL, 0}, // S_HAMMER // Koopa - {SPR_KOOP, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KOOPA1 - {SPR_KOOP, 1, 24, {NULL}, 0, 0, S_KOOPA1}, // S_KOOPA2 + {SPR_KOOP, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_KOOPA1 + {SPR_KOOP, 1, 24, {NULL}, 0, 0, S_KOOPA1, 0}, // S_KOOPA2 - {SPR_BFLM, 0, 3,{NULL}, 0, 0, S_KOOPAFLAME2}, // S_KOOPAFLAME1 - {SPR_BFLM, 1, 3,{NULL}, 0, 0, S_KOOPAFLAME3}, // S_KOOPAFLAME2 - {SPR_BFLM, 2, 3,{NULL}, 0, 0, S_KOOPAFLAME1}, // S_KOOPAFLAME3 + {SPR_BFLM, 0, 3,{NULL}, 0, 0, S_KOOPAFLAME2, 0}, // S_KOOPAFLAME1 + {SPR_BFLM, 1, 3,{NULL}, 0, 0, S_KOOPAFLAME3, 0}, // S_KOOPAFLAME2 + {SPR_BFLM, 2, 3,{NULL}, 0, 0, S_KOOPAFLAME1, 0}, // S_KOOPAFLAME3 // Axe - {SPR_MAXE, 0, 3, {NULL}, 0, 0, S_AXE2}, // S_AXE1 - {SPR_MAXE, 1, 3, {NULL}, 0, 0, S_AXE3}, // S_AXE2 - {SPR_MAXE, 2, 3, {NULL}, 0, 0, S_AXE1}, // S_AXE3 + {SPR_MAXE, 0, 3, {NULL}, 0, 0, S_AXE2, 0}, // S_AXE1 + {SPR_MAXE, 1, 3, {NULL}, 0, 0, S_AXE3, 0}, // S_AXE2 + {SPR_MAXE, 2, 3, {NULL}, 0, 0, S_AXE1, 0}, // S_AXE3 - {SPR_MUS1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_MARIOBUSH1 - {SPR_MUS2, 0, -1, {NULL}, 0, 0, S_NULL}, // S_MARIOBUSH2 - {SPR_TOAD, 0, -1, {NULL}, 0, 0, S_NULL}, // S_TOAD + {SPR_MUS1, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_MARIOBUSH1 + {SPR_MUS2, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_MARIOBUSH2 + {SPR_TOAD, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_TOAD // Nights Drone - {SPR_NDRN, 0, -1, {NULL}, 0, 0, S_NIGHTSDRONE_MAN2}, // S_NIGHTSDRONE_MAN1 - {SPR_NDRN, 0, -1, {NULL}, 0, 0, S_NIGHTSDRONE_MAN1}, // S_NIGHTSDRONE_MAN2 + {SPR_NDRN, 0, -1, {NULL}, 0, 0, S_NIGHTSDRONE_MAN2, 0}, // S_NIGHTSDRONE_MAN1 + {SPR_NDRN, 0, -1, {NULL}, 0, 0, S_NIGHTSDRONE_MAN1, 0}, // S_NIGHTSDRONE_MAN2 // Sparkling point (RETURN TO THE GOAL, etc) - {SPR_IVSP, 0, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING2}, // S_NIGHTSDRONE_SPARKLING1 - {SPR_IVSP, 2, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING3}, // S_NIGHTSDRONE_SPARKLING2 - {SPR_IVSP, 4, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING4}, // S_NIGHTSDRONE_SPARKLING3 - {SPR_IVSP, 6, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING5}, // S_NIGHTSDRONE_SPARKLING4 - {SPR_IVSP, 8, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING6}, // S_NIGHTSDRONE_SPARKLING5 - {SPR_IVSP, 10, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING7}, // S_NIGHTSDRONE_SPARKLING6 - {SPR_IVSP, 12, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING8}, // S_NIGHTSDRONE_SPARKLING7 - {SPR_IVSP, 14, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING9}, // S_NIGHTSDRONE_SPARKLING8 - {SPR_IVSP, 16, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING10}, // S_NIGHTSDRONE_SPARKLING9 - {SPR_IVSP, 18, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING11}, // S_NIGHTSDRONE_SPARKLING10 - {SPR_IVSP, 20, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING12}, // S_NIGHTSDRONE_SPARKLING11 - {SPR_IVSP, 22, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING13}, // S_NIGHTSDRONE_SPARKLING12 - {SPR_IVSP, 24, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING14}, // S_NIGHTSDRONE_SPARKLING13 - {SPR_IVSP, 26, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING15}, // S_NIGHTSDRONE_SPARKLING14 - {SPR_IVSP, 28, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING16}, // S_NIGHTSDRONE_SPARKLING15 - {SPR_IVSP, 30, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING1}, // S_NIGHTSDRONE_SPARKLING16 + {SPR_IVSP, 0, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING2, 0}, // S_NIGHTSDRONE_SPARKLING1 + {SPR_IVSP, 2, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING3, 0}, // S_NIGHTSDRONE_SPARKLING2 + {SPR_IVSP, 4, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING4, 0}, // S_NIGHTSDRONE_SPARKLING3 + {SPR_IVSP, 6, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING5, 0}, // S_NIGHTSDRONE_SPARKLING4 + {SPR_IVSP, 8, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING6, 0}, // S_NIGHTSDRONE_SPARKLING5 + {SPR_IVSP, 10, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING7, 0}, // S_NIGHTSDRONE_SPARKLING6 + {SPR_IVSP, 12, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING8, 0}, // S_NIGHTSDRONE_SPARKLING7 + {SPR_IVSP, 14, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING9, 0}, // S_NIGHTSDRONE_SPARKLING8 + {SPR_IVSP, 16, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING10, 0}, // S_NIGHTSDRONE_SPARKLING9 + {SPR_IVSP, 18, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING11, 0}, // S_NIGHTSDRONE_SPARKLING10 + {SPR_IVSP, 20, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING12, 0}, // S_NIGHTSDRONE_SPARKLING11 + {SPR_IVSP, 22, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING13, 0}, // S_NIGHTSDRONE_SPARKLING12 + {SPR_IVSP, 24, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING14, 0}, // S_NIGHTSDRONE_SPARKLING13 + {SPR_IVSP, 26, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING15, 0}, // S_NIGHTSDRONE_SPARKLING14 + {SPR_IVSP, 28, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING16, 0}, // S_NIGHTSDRONE_SPARKLING15 + {SPR_IVSP, 30, 1, {A_GhostMe}, 0, 0, S_NIGHTSDRONE_SPARKLING1, 0}, // S_NIGHTSDRONE_SPARKLING16 // NiGHTS GOAL banner (inside the sparkles!) - {SPR_GOAL, 0, 4, {NULL}, 0, 0, S_NIGHTSDRONE_GOAL2}, // S_NIGHTSDRONE_GOAL1 - {SPR_GOAL, 1, 4, {NULL}, 0, 0, S_NIGHTSDRONE_GOAL3}, // S_NIGHTSDRONE_GOAL2 - {SPR_GOAL, 2, 4, {NULL}, 0, 0, S_NIGHTSDRONE_GOAL4}, // S_NIGHTSDRONE_GOAL3 - {SPR_GOAL, 3, 4, {NULL}, 0, 0, S_NIGHTSDRONE_GOAL1}, // S_NIGHTSDRONE_GOAL4 + {SPR_GOAL, 0, 4, {NULL}, 0, 0, S_NIGHTSDRONE_GOAL2, 0}, // S_NIGHTSDRONE_GOAL1 + {SPR_GOAL, 1, 4, {NULL}, 0, 0, S_NIGHTSDRONE_GOAL3, 0}, // S_NIGHTSDRONE_GOAL2 + {SPR_GOAL, 2, 4, {NULL}, 0, 0, S_NIGHTSDRONE_GOAL4, 0}, // S_NIGHTSDRONE_GOAL3 + {SPR_GOAL, 3, 4, {NULL}, 0, 0, S_NIGHTSDRONE_GOAL1, 0}, // S_NIGHTSDRONE_GOAL4 // Nights Sparkle - {SPR_NSPK, FF_FULLBRIGHT, 140, {NULL}, 0, 0, S_NIGHTSPARKLE2}, // S_NIGHTSPARKLE1 - {SPR_NSPK, FF_FULLBRIGHT|1, 7, {NULL}, 0, 0, S_NIGHTSPARKLE3}, // S_NIGHTSPARKLE2 - {SPR_NSPK, FF_FULLBRIGHT|2, 7, {NULL}, 0, 0, S_NIGHTSPARKLE4}, // S_NIGHTSPARKLE3 - {SPR_NSPK, FF_FULLBRIGHT|3, 7, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPARKLE4 + {SPR_NSPK, FF_FULLBRIGHT, 140, {NULL}, 0, 0, S_NIGHTSPARKLE2, 0}, // S_NIGHTSPARKLE1 + {SPR_NSPK, FF_FULLBRIGHT|1, 7, {NULL}, 0, 0, S_NIGHTSPARKLE3, 0}, // S_NIGHTSPARKLE2 + {SPR_NSPK, FF_FULLBRIGHT|2, 7, {NULL}, 0, 0, S_NIGHTSPARKLE4, 0}, // S_NIGHTSPARKLE3 + {SPR_NSPK, FF_FULLBRIGHT|3, 7, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSPARKLE4 // Red Sparkle - {SPR_NSPK, FF_FULLBRIGHT|4, 140, {NULL}, 0, 0, S_NIGHTSPARKLESUPER2}, // S_NIGHTSPARKLESUPER1 - {SPR_NSPK, FF_FULLBRIGHT|5, 7, {NULL}, 0, 0, S_NIGHTSPARKLESUPER3}, // S_NIGHTSPARKLESUPER2 - {SPR_NSPK, FF_FULLBRIGHT|6, 7, {NULL}, 0, 0, S_NIGHTSPARKLESUPER4}, // S_NIGHTSPARKLESUPER3 - {SPR_NSPK, FF_FULLBRIGHT|7, 7, {NULL}, 0, 0, S_NULL}, // S_NIGHTSPARKLESUPER4 + {SPR_NSPK, FF_FULLBRIGHT|4, 140, {NULL}, 0, 0, S_NIGHTSPARKLESUPER2, 0}, // S_NIGHTSPARKLESUPER1 + {SPR_NSPK, FF_FULLBRIGHT|5, 7, {NULL}, 0, 0, S_NIGHTSPARKLESUPER3, 0}, // S_NIGHTSPARKLESUPER2 + {SPR_NSPK, FF_FULLBRIGHT|6, 7, {NULL}, 0, 0, S_NIGHTSPARKLESUPER4, 0}, // S_NIGHTSPARKLESUPER3 + {SPR_NSPK, FF_FULLBRIGHT|7, 7, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSPARKLESUPER4 // Paraloop helper -- THIS IS WHAT DETERMINES THE TIMER NOW - {SPR_NULL, 0, 160, {NULL}, 0, 0, S_NULL}, // S_NIGHTSLOOPHELPER + {SPR_NULL, 0, 160, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSLOOPHELPER // NiGHTS bumper - {SPR_NBMP, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSBUMPER1 - {SPR_NBMP, 1, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSBUMPER2 - {SPR_NBMP, 2, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSBUMPER3 - {SPR_NBMP, 3, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSBUMPER4 - {SPR_NBMP, 4, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSBUMPER5 - {SPR_NBMP, 5, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSBUMPER6 - {SPR_NBMP, 6, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSBUMPER7 - {SPR_NBMP, 7, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSBUMPER8 - {SPR_NBMP, 8, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSBUMPER9 - {SPR_NBMP, 9, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSBUMPER10 - {SPR_NBMP, 10, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSBUMPER11 - {SPR_NBMP, 11, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSBUMPER12 - - {SPR_HOOP, 0, -1, {NULL}, 0, 0, S_NULL}, // S_HOOP - {SPR_HOOP, 1, -1, {NULL}, 0, 0, S_NULL}, // S_HOOP_XMASA - {SPR_HOOP, 2, -1, {NULL}, 0, 0, S_NULL}, // S_HOOP_XMASB - - {SPR_NSCR, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE10 - {SPR_NSCR, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE20 - {SPR_NSCR, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE30 - {SPR_NSCR, FF_FULLBRIGHT|3, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE40 - {SPR_NSCR, FF_FULLBRIGHT|4, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE50 - {SPR_NSCR, FF_FULLBRIGHT|5, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE60 - {SPR_NSCR, FF_FULLBRIGHT|6, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE70 - {SPR_NSCR, FF_FULLBRIGHT|7, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE80 - {SPR_NSCR, FF_FULLBRIGHT|8, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE90 - {SPR_NSCR, FF_FULLBRIGHT|9, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE100 - {SPR_NSCR, FF_FULLBRIGHT|10, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE10_2 - {SPR_NSCR, FF_FULLBRIGHT|11, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE20_2 - {SPR_NSCR, FF_FULLBRIGHT|12, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE30_2 - {SPR_NSCR, FF_FULLBRIGHT|13, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE40_2 - {SPR_NSCR, FF_FULLBRIGHT|14, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE50_2 - {SPR_NSCR, FF_FULLBRIGHT|15, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE60_2 - {SPR_NSCR, FF_FULLBRIGHT|16, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE70_2 - {SPR_NSCR, FF_FULLBRIGHT|17, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE80_2 - {SPR_NSCR, FF_FULLBRIGHT|18, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE90_2 - {SPR_NSCR, FF_FULLBRIGHT|19, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE100_2 + {SPR_NBMP, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSBUMPER1 + {SPR_NBMP, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSBUMPER2 + {SPR_NBMP, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSBUMPER3 + {SPR_NBMP, 3, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSBUMPER4 + {SPR_NBMP, 4, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSBUMPER5 + {SPR_NBMP, 5, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSBUMPER6 + {SPR_NBMP, 6, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSBUMPER7 + {SPR_NBMP, 7, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSBUMPER8 + {SPR_NBMP, 8, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSBUMPER9 + {SPR_NBMP, 9, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSBUMPER10 + {SPR_NBMP, 10, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSBUMPER11 + {SPR_NBMP, 11, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSBUMPER12 + + {SPR_HOOP, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_HOOP + {SPR_HOOP, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_HOOP_XMASA + {SPR_HOOP, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_HOOP_XMASB + + {SPR_NSCR, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSCORE10 + {SPR_NSCR, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSCORE20 + {SPR_NSCR, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSCORE30 + {SPR_NSCR, FF_FULLBRIGHT|3, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSCORE40 + {SPR_NSCR, FF_FULLBRIGHT|4, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSCORE50 + {SPR_NSCR, FF_FULLBRIGHT|5, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSCORE60 + {SPR_NSCR, FF_FULLBRIGHT|6, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSCORE70 + {SPR_NSCR, FF_FULLBRIGHT|7, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSCORE80 + {SPR_NSCR, FF_FULLBRIGHT|8, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSCORE90 + {SPR_NSCR, FF_FULLBRIGHT|9, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSCORE100 + {SPR_NSCR, FF_FULLBRIGHT|10, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSCORE10_2 + {SPR_NSCR, FF_FULLBRIGHT|11, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSCORE20_2 + {SPR_NSCR, FF_FULLBRIGHT|12, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSCORE30_2 + {SPR_NSCR, FF_FULLBRIGHT|13, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSCORE40_2 + {SPR_NSCR, FF_FULLBRIGHT|14, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSCORE50_2 + {SPR_NSCR, FF_FULLBRIGHT|15, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSCORE60_2 + {SPR_NSCR, FF_FULLBRIGHT|16, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSCORE70_2 + {SPR_NSCR, FF_FULLBRIGHT|17, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSCORE80_2 + {SPR_NSCR, FF_FULLBRIGHT|18, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSCORE90_2 + {SPR_NSCR, FF_FULLBRIGHT|19, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSCORE100_2 // NiGHTS Paraloop Powerups - {SPR_NPRU, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSSUPERLOOP - {SPR_NPRU, 1, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSDRILLREFILL - {SPR_NPRU, 2, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSHELPER - {SPR_NPRU, 3, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSEXTRATIME - {SPR_NPRU, 4, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSLINKFREEZE + {SPR_NPRU, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSSUPERLOOP + {SPR_NPRU, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSDRILLREFILL + {SPR_NPRU, 2, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSHELPER + {SPR_NPRU, 3, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSEXTRATIME + {SPR_NPRU, 4, -1, {NULL}, 0, 0, S_NULL, 0}, // S_NIGHTSLINKFREEZE - {SPR_CAPS, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGCAPSULE + {SPR_CAPS, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EGGCAPSULE // Orbiting Chaos Emeralds/Ideya for NiGHTS - {SPR_CEMG, FF_FULLBRIGHT, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM1}, // S_ORBITEM1 - {SPR_CEMG, FF_FULLBRIGHT|1, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM2}, // S_ORBITEM2 - {SPR_CEMG, FF_FULLBRIGHT|2, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM3}, // S_ORBITEM3 - {SPR_CEMG, FF_FULLBRIGHT|3, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM4}, // S_ORBITEM4 - {SPR_CEMG, FF_FULLBRIGHT|4, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM5}, // S_ORBITEM5 - {SPR_CEMG, FF_FULLBRIGHT|5, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM6}, // S_ORBITEM6 - {SPR_CEMG, FF_FULLBRIGHT|6, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM7}, // S_ORBITEM7 - {SPR_CEMG, FF_FULLBRIGHT|7, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM8 - {SPR_IDYA, FF_TRANS20|FF_FULLBRIGHT, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBIDYA1}, // S_ORBIDYA1 - {SPR_IDYA, FF_TRANS20|FF_FULLBRIGHT|1, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBIDYA2}, // S_ORBIDYA2 - {SPR_IDYA, FF_TRANS20|FF_FULLBRIGHT|2, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBIDYA3}, // S_ORBIDYA3 - {SPR_IDYA, FF_TRANS20|FF_FULLBRIGHT|3, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBIDYA4}, // S_ORBIDYA4 - {SPR_IDYA, FF_TRANS20|FF_FULLBRIGHT|4, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBIDYA5}, // S_ORBIDYA5 + {SPR_CEMG, FF_FULLBRIGHT, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM1, 0}, // S_ORBITEM1 + {SPR_CEMG, FF_FULLBRIGHT|1, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM2, 0}, // S_ORBITEM2 + {SPR_CEMG, FF_FULLBRIGHT|2, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM3, 0}, // S_ORBITEM3 + {SPR_CEMG, FF_FULLBRIGHT|3, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM4, 0}, // S_ORBITEM4 + {SPR_CEMG, FF_FULLBRIGHT|4, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM5, 0}, // S_ORBITEM5 + {SPR_CEMG, FF_FULLBRIGHT|5, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM6, 0}, // S_ORBITEM6 + {SPR_CEMG, FF_FULLBRIGHT|6, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM7, 0}, // S_ORBITEM7 + {SPR_CEMG, FF_FULLBRIGHT|7, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8, 0}, // S_ORBITEM8 + {SPR_IDYA, FF_TRANS20|FF_FULLBRIGHT, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBIDYA1, 0}, // S_ORBIDYA1 + {SPR_IDYA, FF_TRANS20|FF_FULLBRIGHT|1, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBIDYA2, 0}, // S_ORBIDYA2 + {SPR_IDYA, FF_TRANS20|FF_FULLBRIGHT|2, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBIDYA3, 0}, // S_ORBIDYA3 + {SPR_IDYA, FF_TRANS20|FF_FULLBRIGHT|3, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBIDYA4, 0}, // S_ORBIDYA4 + {SPR_IDYA, FF_TRANS20|FF_FULLBRIGHT|4, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBIDYA5, 0}, // S_ORBIDYA5 // Flicky helper for NiGHTS - {SPR_FL01, 1, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER2}, // S_NIGHTOPIANHELPER1 - {SPR_FL01, 1, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER3}, // S_NIGHTOPIANHELPER2 - {SPR_FL01, 1, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER4}, // S_NIGHTOPIANHELPER3 - {SPR_FL01, 2, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER5}, // S_NIGHTOPIANHELPER4 - {SPR_FL01, 2, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER6}, // S_NIGHTOPIANHELPER5 - {SPR_FL01, 2, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER7}, // S_NIGHTOPIANHELPER6 - {SPR_FL01, 3, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER8}, // S_NIGHTOPIANHELPER7 - {SPR_FL01, 3, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER9}, // S_NIGHTOPIANHELPER8 - {SPR_FL01, 3, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER1}, // S_NIGHTOPIANHELPER9 + {SPR_FL01, 1, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER2, 0}, // S_NIGHTOPIANHELPER1 + {SPR_FL01, 1, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER3, 0}, // S_NIGHTOPIANHELPER2 + {SPR_FL01, 1, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER4, 0}, // S_NIGHTOPIANHELPER3 + {SPR_FL01, 2, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER5, 0}, // S_NIGHTOPIANHELPER4 + {SPR_FL01, 2, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER6, 0}, // S_NIGHTOPIANHELPER5 + {SPR_FL01, 2, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER7, 0}, // S_NIGHTOPIANHELPER6 + {SPR_FL01, 3, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER8, 0}, // S_NIGHTOPIANHELPER7 + {SPR_FL01, 3, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER9, 0}, // S_NIGHTOPIANHELPER8 + {SPR_FL01, 3, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER1, 0}, // S_NIGHTOPIANHELPER9 // Nightopian - {SPR_NTPN, 0, 2, {A_Look}, 1, 1, S_PIAN_LOOK2}, // S_PIAN_LOOK1 - {SPR_NTPN, 1, 2, {A_Look}, 1, 1, S_PIAN_LOOK3}, // S_PIAN_LOOK2 - {SPR_NTPN, 2, 2, {A_Look}, 1, 1, S_PIAN_LOOK1}, // S_PIAN_LOOK3 - {SPR_NTPN, 0, 2, {A_JetgThink}, 0, 0, S_PIAN_FLY2}, // S_PIAN_FLY1 - {SPR_NTPN, 1, 2, {NULL}, 0, 0, S_PIAN_FLY3}, // S_PIAN_FLY2 - {SPR_NTPN, 2, 2, {NULL}, 0, 0, S_PIAN_FLY1}, // S_PIAN_FLY3 - {SPR_NTPN, 3|FF_ANIMATE, 24, {NULL}, 2, 2, S_PIAN_FLY1}, // S_PIAN_SING + {SPR_NTPN, 0, 2, {A_Look}, 1, 1, S_PIAN_LOOK2, 0}, // S_PIAN_LOOK1 + {SPR_NTPN, 1, 2, {A_Look}, 1, 1, S_PIAN_LOOK3, 0}, // S_PIAN_LOOK2 + {SPR_NTPN, 2, 2, {A_Look}, 1, 1, S_PIAN_LOOK1, 0}, // S_PIAN_LOOK3 + {SPR_NTPN, 0, 2, {A_JetgThink}, 0, 0, S_PIAN_FLY2, 0}, // S_PIAN_FLY1 + {SPR_NTPN, 1, 2, {NULL}, 0, 0, S_PIAN_FLY3, 0}, // S_PIAN_FLY2 + {SPR_NTPN, 2, 2, {NULL}, 0, 0, S_PIAN_FLY1, 0}, // S_PIAN_FLY3 + {SPR_NTPN, 3|FF_ANIMATE, 24, {NULL}, 2, 2, S_PIAN_FLY1, 0}, // S_PIAN_SING // Shleep - {SPR_SHLP, 0, 15, {NULL}, 0, 0, S_SHLEEP2}, // S_SHLEEP1 - {SPR_SHLP, 1, 15, {NULL}, 0, 0, S_SHLEEP3}, // S_SHLEEP2 - {SPR_SHLP, 2, 15, {NULL}, 0, 0, S_SHLEEP4}, // S_SHLEEP3 - {SPR_SHLP, 1, 15, {NULL}, 0, 0, S_SHLEEP1}, // S_SHLEEP4 - {SPR_SHLP, 3, 1, {A_Scream}, 0, 0, S_SHLEEPBOUNCE2}, // S_SHLEEPBOUNCE1 - {SPR_SHLP, 3, 1, {A_ZThrust}, 9, 0, S_SHLEEPBOUNCE3}, // S_SHLEEPBOUNCE2 - {SPR_SHLP, 3, 400, {A_SetObjectFlags}, MF_SLIDEME|MF_ENEMY|MF_BOUNCE|MF_NOCLIP|MF_NOCLIPHEIGHT, 0, S_NULL}, // S_SHLEEPBOUNCE3 + {SPR_SHLP, 0, 15, {NULL}, 0, 0, S_SHLEEP2, 0}, // S_SHLEEP1 + {SPR_SHLP, 1, 15, {NULL}, 0, 0, S_SHLEEP3, 0}, // S_SHLEEP2 + {SPR_SHLP, 2, 15, {NULL}, 0, 0, S_SHLEEP4, 0}, // S_SHLEEP3 + {SPR_SHLP, 1, 15, {NULL}, 0, 0, S_SHLEEP1, 0}, // S_SHLEEP4 + {SPR_SHLP, 3, 1, {A_Scream}, 0, 0, S_SHLEEPBOUNCE2, 0}, // S_SHLEEPBOUNCE1 + {SPR_SHLP, 3, 1, {A_ZThrust}, 9, 0, S_SHLEEPBOUNCE3, 0}, // S_SHLEEPBOUNCE2 + {SPR_SHLP, 3, 400, {A_SetObjectFlags}, MF_SLIDEME|MF_ENEMY|MF_BOUNCE|MF_NOCLIP|MF_NOCLIPHEIGHT, 0, S_NULL, 0}, // S_SHLEEPBOUNCE3 // Secret badniks and hazards, shhhh - {SPR_PENG, 0, 2, {A_Look}, 0, 0, S_PENGUINATOR_LOOK}, // S_PENGUINATOR_LOOK - {SPR_PENG, 0, 2, {A_Chase}, 0, 0, S_PENGUINATOR_WADDLE2}, // S_PENGUINATOR_WADDLE1 - {SPR_PENG, 1, 2, {A_Chase}, 0, 0, S_PENGUINATOR_WADDLE3}, // S_PENGUINATOR_WADDLE2 - {SPR_PENG, 0, 2, {A_Chase}, 0, 0, S_PENGUINATOR_WADDLE4}, // S_PENGUINATOR_WADDLE3 - {SPR_PENG, 2, 2, {A_Chase}, 0, 0, S_PENGUINATOR_WADDLE1}, // S_PENGUINATOR_WADDLE4 - {SPR_PENG, 0, 0, {A_FaceTarget}, 0, 0, S_PENGUINATOR_SLIDE2}, // S_PENGUINATOR_SLIDE1 - {SPR_PENG, 3, 5, {A_BunnyHop}, 4, 10, S_PENGUINATOR_SLIDE3}, // S_PENGUINATOR_SLIDE2 - {SPR_PENG, 4, 90, {A_PlayAttackSound}, 0, 0, S_PENGUINATOR_SLIDE4}, // S_PENGUINATOR_SLIDE3 - {SPR_PENG, 3, 5, {A_Thrust}, 0, 1, S_PENGUINATOR_SLIDE5}, // S_PENGUINATOR_SLIDE4 - {SPR_PENG, 0, 5, {A_FaceTarget}, 0, 0, S_PENGUINATOR_LOOK}, // S_PENGUINATOR_SLIDE5 - - {SPR_POPH, 0, 2, {A_Look}, (2048<<16)|1, 0, S_POPHAT_LOOK}, // S_POPHAT_LOOK - {SPR_POPH, 1, 0, {A_MultiShotDist}, (MT_SPINDUST<<16)|4, 24, S_POPHAT_SHOOT2}, // S_POPHAT_SHOOT1 - {SPR_POPH, 1, 2, {A_LobShot}, MT_POPSHOT, (70<<16)|60, S_POPHAT_SHOOT3}, // S_POPHAT_SHOOT2 - {SPR_POPH, 2, 1, {NULL}, 0, 0, S_POPHAT_SHOOT4}, // S_POPHAT_SHOOT3 - {SPR_POPH, 0, 57, {NULL}, 0, 0, S_POPHAT_LOOK}, // S_POPHAT_SHOOT4 - {SPR_POPH, 3, 3, {A_SpawnObjectRelative}, 0, MT_POPSHOT_TRAIL, S_POPSHOT}, // S_POPSHOT - {SPR_NULL, 0, 2, {NULL}, 0, 0, S_SPINDUST1}, // S_POPSHOT_TRAIL - - {SPR_HIVE, 0, 5, {A_Look}, 1, 1, S_HIVEELEMENTAL_LOOK}, // S_HIVEELEMENTAL_LOOK - {SPR_HIVE, 0, 14, {A_PlaySound}, sfx_s3k76, 1, S_HIVEELEMENTAL_PREPARE2}, // S_HIVEELEMENTAL_PREPARE1 - {SPR_HIVE, 0, 6, {A_PlaySound}, sfx_s3k8c, 1, S_HIVEELEMENTAL_SHOOT1}, // S_HIVEELEMENTAL_PREPARE2 - {SPR_HIVE, 1, 4, {A_WhoCaresIfYourSonIsABee}, (MT_BUMBLEBORE<<16)|4, (1<<16)|32, S_HIVEELEMENTAL_SHOOT2}, // S_HIVEELEMENTAL_SHOOT1 - {SPR_HIVE, 2, 2, {NULL}, 0, 0, S_HIVEELEMENTAL_DORMANT}, // S_HIVEELEMENTAL_SHOOT2 - {SPR_HIVE, 0, 5, {A_ParentTriesToSleep}, S_HIVEELEMENTAL_PREPARE1, 0, S_HIVEELEMENTAL_DORMANT}, // S_HIVEELEMENTAL_DORMANT - {SPR_HIVE, 3, 35, {A_Pain}, 0, 0, S_HIVEELEMENTAL_LOOK}, // S_HIVEELEMENTAL_PAIN - {SPR_HIVE, 3, 2, {A_BossScream}, 1, 0, S_HIVEELEMENTAL_DIE2}, // S_HIVEELEMENTAL_DIE1 - {SPR_NULL, 0, 2, {A_BossScream}, 1, 0, S_HIVEELEMENTAL_DIE3}, // S_HIVEELEMENTAL_DIE2 - {SPR_NULL, 0, 0, {A_Repeat}, 7, S_HIVEELEMENTAL_DIE1, S_XPLD_FLICKY}, // S_HIVEELEMENTAL_DIE3 - - {SPR_BUMB, 1, 10, {NULL}, 0, 0, S_BUMBLEBORE_LOOK1}, // S_BUMBLEBORE_SPAWN - {SPR_BUMB, 0, 4, {A_Look}, 1, 1, S_BUMBLEBORE_LOOK2}, // S_BUMBLEBORE_LOOK1 - {SPR_BUMB, 1, 4, {A_Look}, 1, 1, S_BUMBLEBORE_LOOK1}, // S_BUMBLEBORE_LOOK2 - {SPR_BUMB, 0, 4, {A_JetbThink}, 0, 0, S_BUMBLEBORE_FLY2}, // S_BUMBLEBORE_FLY1 - {SPR_BUMB, 1, 4, {A_JetbThink}, 0, 0, S_BUMBLEBORE_FLY1}, // S_BUMBLEBORE_FLY2 - {SPR_BUMB, 2|FF_FULLBRIGHT, 12, {A_ZThrust}, 4, (1<<16)|1, S_BUMBLEBORE_FALL1}, // S_BUMBLEBORE_RAISE - {SPR_BUMB, 2|FF_FULLBRIGHT, 0, {A_ZThrust}, -8, (1<<16)|1, S_BUMBLEBORE_FALL2}, // S_BUMBLEBORE_FALL1 - {SPR_BUMB, 2|FF_FULLBRIGHT, 300, {NULL}, 0, 0, S_BUMBLEBORE_DIE}, // S_BUMBLEBORE_FALL2 - {SPR_BUMB, 4, 3, {A_MultiShotDist}, (MT_DUST<<16)|6, -40, S_BUMBLEBORE_STUCK2}, // S_BUMBLEBORE_STUCK1 - {SPR_BUMB, 5, 120, {NULL}, 0, 0, S_BUMBLEBORE_DIE}, // S_BUMBLEBORE_STUCK2 - {SPR_BUMB, 5, 0, {A_CryingToMomma}, 0, 0, S_XPLD1}, // S_BUMBLEBORE_DIE - - {SPR_BBUZ, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BUGGLEIDLE - {SPR_BBUZ, FF_ANIMATE, -1, {NULL}, 1, 2, S_NULL}, // S_BUGGLEFLY - - {SPR_FMCE, 0, 20, {NULL}, 0, 0, S_SMASHSPIKE_EASE1}, // S_SMASHSPIKE_FLOAT - {SPR_FMCE, 0, 4, {A_ZThrust}, 4, (1<<16)|1, S_SMASHSPIKE_EASE2}, // S_SMASHSPIKE_EASE1 - {SPR_FMCE, 0, 4, {A_ZThrust}, 0, (1<<16)|1, S_SMASHSPIKE_FALL}, // S_SMASHSPIKE_EASE2 - {SPR_FMCE, 0, 2, {A_ZThrust}, -6, 1, S_SMASHSPIKE_FALL}, // S_SMASHSPIKE_FALL - {SPR_FMCE, 1, 2, {A_MultiShotDist}, (MT_DUST<<16)|10, -48, S_SMASHSPIKE_STOMP2}, // S_SMASHSPIKE_STOMP1 - {SPR_FMCE, 2, 14, {NULL}, 0, 0, S_SMASHSPIKE_RISE1}, // S_SMASHSPIKE_STOMP2 - {SPR_FMCE, 1, 2, {NULL}, 0, 0, S_SMASHSPIKE_RISE2}, // S_SMASHSPIKE_RISE1 - {SPR_FMCE, 0, 2, {A_ZThrust}, 6, (1<<16)|1, S_SMASHSPIKE_RISE2}, // S_SMASHSPIKE_RISE2 - - {SPR_CACO, 0, 5, {A_Look}, (1100<<16)|1, 0, S_CACO_LOOK}, // S_CACO_LOOK - {SPR_CACO, 1, 0, {A_MultiShotDist}, (MT_DUST<<16)|7, -48, S_CACO_WAKE2}, // S_CACO_WAKE1 - {SPR_CACO, 1, 10, {A_ZThrust}, 4, (1<<16)|1, S_CACO_WAKE3}, // S_CACO_WAKE2 - {SPR_CACO, 2, 8, {A_ZThrust}, 2, (1<<16)|1, S_CACO_WAKE4}, // S_CACO_WAKE3 - {SPR_CACO, 2, 4, {A_ZThrust}, 0, (1<<16)|1, S_CACO_ROAR}, // S_CACO_WAKE4 - {SPR_CACO, 2, 10, {A_PlayActiveSound}, 0, 0, S_CACO_CHASE}, // S_CACO_ROAR - {SPR_CACO, 2, 5, {A_JetChase}, 0, 0, S_CACO_CHASE_REPEAT}, // S_CACO_CHASE - {SPR_CACO, 2, 0, {A_Repeat}, 5, S_CACO_CHASE, S_CACO_RANDOM}, // S_CACO_CHASE_REPEAT - {SPR_CACO, 2, 0, {A_RandomState}, S_CACO_PREPARE_SOUND, S_CACO_CHASE, S_CACO_RANDOM}, // S_CACO_RANDOM - {SPR_CACO, 2, 8, {A_PlaySound}, sfx_s3k95, 1, S_CACO_PREPARE1}, // S_CACO_PREPARE_SOUND - {SPR_CACO, 3, 8, {NULL}, 0, 0, S_CACO_PREPARE2}, // S_CACO_PREPARE1 - {SPR_CACO, 4|FF_FULLBRIGHT, 8, {NULL}, 0, 0, S_CACO_PREPARE3}, // S_CACO_PREPARE2 - {SPR_CACO, 5|FF_FULLBRIGHT, 8, {NULL}, 0, 0, S_CACO_SHOOT_SOUND}, // S_CACO_PREPARE3 - {SPR_CACO, 4|FF_FULLBRIGHT, 0, {A_PlaySound}, sfx_s3k4e, 1, S_CACO_SHOOT1}, // S_CACO_SHOOT_SOUND - {SPR_CACO, 4|FF_FULLBRIGHT, 0, {A_SpawnParticleRelative}, 0, S_CACOFIRE_EXPLODE1, S_CACO_SHOOT2}, // S_CACO_SHOOT1 - {SPR_CACO, 4|FF_FULLBRIGHT, 6, {A_FireShot}, MT_CACOFIRE, -24, S_CACO_CLOSE}, // S_CACO_SHOOT2 - {SPR_CACO, 3, 15, {NULL}, 0, 0, S_CACO_CHASE}, // S_CACO_CLOSE - {SPR_CACO, 10, 0, {A_SetObjectFlags}, MF_NOBLOCKMAP, 0, S_CACO_DIE_GIB1}, // S_CACO_DIE_FLAGS - {SPR_CACO, 10, 0, {A_NapalmScatter}, (7<<16)|MT_CACOSHARD, (30<<16)|20, S_CACO_DIE_GIB2}, // S_CACO_DIE_GIB1 - {SPR_CACO, 10, 0, {A_NapalmScatter}, (10<<16)|MT_CACOSHARD, (24<<16)|32, S_CACO_DIE_SCREAM}, // S_CACO_DIE_GIB2 - {SPR_CACO, 10, 0, {A_Scream}, 0, 0, S_CACO_DIE_SHATTER}, // S_CACO_DIE_SCREAM - {SPR_CACO, 10, 0, {A_PlaySound}, sfx_pumpkn, 1, S_CACO_DIE_FALL}, // S_CACO_DIE_SHATTER - {SPR_CACO, 10, 250, {A_FlickySpawn}, (1<<16), 0, S_NULL}, // S_CACO_DIE_FALL - - {SPR_CACO, 6, 0, {A_RandomState}, S_CACOSHARD1_1, S_CACOSHARD2_1, S_NULL}, // S_CACOSHARD_RANDOMIZE - {SPR_CACO, 6, 3, {NULL}, 0, 0, S_CACOSHARD1_2}, // S_CACOSHARD1_1 - {SPR_CACO, 7, 3, {NULL}, 0, 0, S_CACOSHARD1_1}, // S_CACOSHARD1_2 - {SPR_CACO, 8, 3, {NULL}, 0, 0, S_CACOSHARD2_2}, // S_CACOSHARD2_1 - {SPR_CACO, 9, 3, {NULL}, 0, 0, S_CACOSHARD2_1}, // S_CACOSHARD2_2 - {SPR_BAL2, FF_FULLBRIGHT, 2, {A_GhostMe}, 0, 0, S_CACOFIRE2}, // S_CACOFIRE1 - {SPR_BAL2, 1|FF_FULLBRIGHT, 2, {A_GhostMe}, 0, 0, S_CACOFIRE3}, // S_CACOFIRE2 - {SPR_BAL2, FF_FULLBRIGHT, 0, {A_PlayActiveSound}, 0, 0, S_CACOFIRE1}, // S_CACOFIRE3 - {SPR_BAL2, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_CACOFIRE_EXPLODE2}, // S_CACOFIRE_EXPLODE1 - {SPR_BAL2, 3|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_CACOFIRE_EXPLODE3}, // S_CACOFIRE_EXPLODE2 - {SPR_BAL2, 4|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_CACOFIRE_EXPLODE4}, // S_CACOFIRE_EXPLODE3 - {SPR_BAL2, 5|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_CACOFIRE_EXPLODE4 - - {SPR_SBOB, 1, 10, {A_ZThrust}, -2, (1<<16)|1, S_SPINBOBERT_MOVE_UP}, // S_SPINBOBERT_MOVE_FLIPUP - {SPR_SBOB, 0, 45, {A_ZThrust}, 4, (1<<16)|1, S_SPINBOBERT_MOVE_FLIPDOWN}, // S_SPINBOBERT_MOVE_UP - {SPR_SBOB, 1, 10, {A_ZThrust}, 2, (1<<16)|1, S_SPINBOBERT_MOVE_DOWN}, // S_SPINBOBERT_MOVE_FLIPDOWN - {SPR_SBOB, 2, 45, {A_ZThrust}, -4, (1<<16)|1, S_SPINBOBERT_MOVE_FLIPUP}, // S_SPINBOBERT_MOVE_DOWN - {SPR_SBSK, FF_FULLBRIGHT, 1, {A_RotateSpikeBall}, 0, 0, S_SPINBOBERT_FIRE_GHOST}, // S_SPINBOBERT_FIRE_MOVE - {SPR_SBSK, FF_FULLBRIGHT, 0, {A_SpawnParticleRelative}, 0, S_SPINBOBERT_FIRE_TRAIL1, S_SPINBOBERT_FIRE_MOVE}, // S_SPINBOBERT_FIRE_GHOST - {SPR_SBFL, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SPINBOBERT_FIRE_TRAIL2}, // S_SPINBOBERT_FIRE_TRAIL1 - {SPR_SBFL, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SPINBOBERT_FIRE_TRAIL3}, // S_SPINBOBERT_FIRE_TRAIL2 - {SPR_SBFL, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_SPINBOBERT_FIRE_TRAIL3 - - {SPR_HBAT, 0, 5, {A_Look}, (900<<16)|1, 0, S_HANGSTER_LOOK}, // S_HANGSTER_LOOK - {SPR_HBAT, 1, 0, {A_MultiShotDist}, (MT_DUST<<16)|10, -34, S_HANGSTER_SWOOP2}, // S_HANGSTER_SWOOP1 - {SPR_HBAT, 1, 2, {A_ZThrust}, -8, (1<<16)|1, S_HANGSTER_SWOOP2}, // S_HANGSTER_SWOOP2 - {SPR_HBAT, 1, 6, {A_ZThrust}, -5, (1<<16), S_HANGSTER_ARC2}, // S_HANGSTER_ARC1 - {SPR_HBAT, 1, 5, {A_ZThrust}, -2, (1<<16), S_HANGSTER_ARC3}, // S_HANGSTER_ARC2 - {SPR_HBAT, 1, 1, {A_ZThrust}, 0, (1<<16), S_HANGSTER_FLY1}, // S_HANGSTER_ARC3 - {SPR_HBAT, 1, 4, {A_Thrust}, 6, 1, S_HANGSTER_FLY2}, // S_HANGSTER_FLY1 - {SPR_HBAT, 2, 1, {A_PlaySound}, sfx_s3k52, 1, S_HANGSTER_FLY3}, // S_HANGSTER_FLY2 - {SPR_HBAT, 3, 4, {A_Thrust}, 6, 1, S_HANGSTER_FLY4}, // S_HANGSTER_FLY3 - {SPR_HBAT, 2, 1, {A_Thrust}, 6, 1, S_HANGSTER_FLYREPEAT}, // S_HANGSTER_FLY4 - {SPR_HBAT, 2, 0, {A_Repeat}, 12, S_HANGSTER_FLY1, S_HANGSTER_ARCUP1}, // S_HANGSTER_FLYREPEAT - {SPR_HBAT, 1, 5, {A_ZThrust}, 2, (1<<16), S_HANGSTER_ARCUP2}, // S_HANGSTER_ARCUP1 - {SPR_HBAT, 1, 6, {A_ZThrust}, 5, (1<<16), S_HANGSTER_ARCUP3}, // S_HANGSTER_ARCUP2 - {SPR_HBAT, 1, 1, {A_ZThrust}, 0, (1<<16), S_HANGSTER_RETURN1}, // S_HANGSTER_ARCUP3 - {SPR_HBAT, 1, 1, {A_ZThrust}, 8, (1<<16), S_HANGSTER_RETURN2}, // S_HANGSTER_RETURN1 - {SPR_HBAT, 3, 1, {NULL}, 0, 0, S_HANGSTER_RETURN1}, // S_HANGSTER_RETURN2 - {SPR_HBAT, 0, 15, {NULL}, 0, 0, S_HANGSTER_LOOK}, // S_HANGSTER_RETURN3 - - {SPR_NULL, 0, 35, {NULL}, 0, 0, S_CRUMBLE2}, // S_CRUMBLE1 - {SPR_NULL, 0, 105, {A_Scream}, 0, 0, S_NULL}, // S_CRUMBLE2 + {SPR_PENG, 0, 2, {A_Look}, 0, 0, S_PENGUINATOR_LOOK, 0}, // S_PENGUINATOR_LOOK + {SPR_PENG, 0, 2, {A_Chase}, 0, 0, S_PENGUINATOR_WADDLE2, 0}, // S_PENGUINATOR_WADDLE1 + {SPR_PENG, 1, 2, {A_Chase}, 0, 0, S_PENGUINATOR_WADDLE3, 0}, // S_PENGUINATOR_WADDLE2 + {SPR_PENG, 0, 2, {A_Chase}, 0, 0, S_PENGUINATOR_WADDLE4, 0}, // S_PENGUINATOR_WADDLE3 + {SPR_PENG, 2, 2, {A_Chase}, 0, 0, S_PENGUINATOR_WADDLE1, 0}, // S_PENGUINATOR_WADDLE4 + {SPR_PENG, 0, 0, {A_FaceTarget}, 0, 0, S_PENGUINATOR_SLIDE2, 0}, // S_PENGUINATOR_SLIDE1 + {SPR_PENG, 3, 5, {A_BunnyHop}, 4, 10, S_PENGUINATOR_SLIDE3, 0}, // S_PENGUINATOR_SLIDE2 + {SPR_PENG, 4, 90, {A_PlayAttackSound}, 0, 0, S_PENGUINATOR_SLIDE4, 0}, // S_PENGUINATOR_SLIDE3 + {SPR_PENG, 3, 5, {A_Thrust}, 0, 1, S_PENGUINATOR_SLIDE5, 0}, // S_PENGUINATOR_SLIDE4 + {SPR_PENG, 0, 5, {A_FaceTarget}, 0, 0, S_PENGUINATOR_LOOK, 0}, // S_PENGUINATOR_SLIDE5 + + {SPR_POPH, 0, 2, {A_Look}, (2048<<16)|1, 0, S_POPHAT_LOOK, 0}, // S_POPHAT_LOOK + {SPR_POPH, 1, 0, {A_MultiShotDist}, (MT_SPINDUST<<16)|4, 24, S_POPHAT_SHOOT2, 0}, // S_POPHAT_SHOOT1 + {SPR_POPH, 1, 2, {A_LobShot}, MT_POPSHOT, (70<<16)|60, S_POPHAT_SHOOT3, 0}, // S_POPHAT_SHOOT2 + {SPR_POPH, 2, 1, {NULL}, 0, 0, S_POPHAT_SHOOT4, 0}, // S_POPHAT_SHOOT3 + {SPR_POPH, 0, 57, {NULL}, 0, 0, S_POPHAT_LOOK, 0}, // S_POPHAT_SHOOT4 + {SPR_POPH, 3, 3, {A_SpawnObjectRelative}, 0, MT_POPSHOT_TRAIL, S_POPSHOT, 0}, // S_POPSHOT + {SPR_NULL, 0, 2, {NULL}, 0, 0, S_SPINDUST1, 0}, // S_POPSHOT_TRAIL + + {SPR_HIVE, 0, 5, {A_Look}, 1, 1, S_HIVEELEMENTAL_LOOK, 0}, // S_HIVEELEMENTAL_LOOK + {SPR_HIVE, 0, 14, {A_PlaySound}, sfx_s3k76, 1, S_HIVEELEMENTAL_PREPARE2, 0}, // S_HIVEELEMENTAL_PREPARE1 + {SPR_HIVE, 0, 6, {A_PlaySound}, sfx_s3k8c, 1, S_HIVEELEMENTAL_SHOOT1, 0}, // S_HIVEELEMENTAL_PREPARE2 + {SPR_HIVE, 1, 4, {A_WhoCaresIfYourSonIsABee}, (MT_BUMBLEBORE<<16)|4, (1<<16)|32, S_HIVEELEMENTAL_SHOOT2, 0}, // S_HIVEELEMENTAL_SHOOT1 + {SPR_HIVE, 2, 2, {NULL}, 0, 0, S_HIVEELEMENTAL_DORMANT, 0}, // S_HIVEELEMENTAL_SHOOT2 + {SPR_HIVE, 0, 5, {A_ParentTriesToSleep}, S_HIVEELEMENTAL_PREPARE1, 0, S_HIVEELEMENTAL_DORMANT, 0}, // S_HIVEELEMENTAL_DORMANT + {SPR_HIVE, 3, 35, {A_Pain}, 0, 0, S_HIVEELEMENTAL_LOOK, 0}, // S_HIVEELEMENTAL_PAIN + {SPR_HIVE, 3, 2, {A_BossScream}, 1, 0, S_HIVEELEMENTAL_DIE2, 0}, // S_HIVEELEMENTAL_DIE1 + {SPR_NULL, 0, 2, {A_BossScream}, 1, 0, S_HIVEELEMENTAL_DIE3, 0}, // S_HIVEELEMENTAL_DIE2 + {SPR_NULL, 0, 0, {A_Repeat}, 7, S_HIVEELEMENTAL_DIE1, S_XPLD_FLICKY, 0}, // S_HIVEELEMENTAL_DIE3 + + {SPR_BUMB, 1, 10, {NULL}, 0, 0, S_BUMBLEBORE_LOOK1, 0}, // S_BUMBLEBORE_SPAWN + {SPR_BUMB, 0, 4, {A_Look}, 1, 1, S_BUMBLEBORE_LOOK2, 0}, // S_BUMBLEBORE_LOOK1 + {SPR_BUMB, 1, 4, {A_Look}, 1, 1, S_BUMBLEBORE_LOOK1, 0}, // S_BUMBLEBORE_LOOK2 + {SPR_BUMB, 0, 4, {A_JetbThink}, 0, 0, S_BUMBLEBORE_FLY2, 0}, // S_BUMBLEBORE_FLY1 + {SPR_BUMB, 1, 4, {A_JetbThink}, 0, 0, S_BUMBLEBORE_FLY1, 0}, // S_BUMBLEBORE_FLY2 + {SPR_BUMB, 2|FF_FULLBRIGHT, 12, {A_ZThrust}, 4, (1<<16)|1, S_BUMBLEBORE_FALL1, 0}, // S_BUMBLEBORE_RAISE + {SPR_BUMB, 2|FF_FULLBRIGHT, 0, {A_ZThrust}, -8, (1<<16)|1, S_BUMBLEBORE_FALL2, 0}, // S_BUMBLEBORE_FALL1 + {SPR_BUMB, 2|FF_FULLBRIGHT, 300, {NULL}, 0, 0, S_BUMBLEBORE_DIE, 0}, // S_BUMBLEBORE_FALL2 + {SPR_BUMB, 4, 3, {A_MultiShotDist}, (MT_DUST<<16)|6, -40, S_BUMBLEBORE_STUCK2, 0}, // S_BUMBLEBORE_STUCK1 + {SPR_BUMB, 5, 120, {NULL}, 0, 0, S_BUMBLEBORE_DIE, 0}, // S_BUMBLEBORE_STUCK2 + {SPR_BUMB, 5, 0, {A_CryingToMomma}, 0, 0, S_XPLD1, 0}, // S_BUMBLEBORE_DIE + + {SPR_BBUZ, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BUGGLEIDLE + {SPR_BBUZ, FF_ANIMATE, -1, {NULL}, 1, 2, S_NULL, 0}, // S_BUGGLEFLY + + {SPR_FMCE, 0, 20, {NULL}, 0, 0, S_SMASHSPIKE_EASE1, 0}, // S_SMASHSPIKE_FLOAT + {SPR_FMCE, 0, 4, {A_ZThrust}, 4, (1<<16)|1, S_SMASHSPIKE_EASE2, 0}, // S_SMASHSPIKE_EASE1 + {SPR_FMCE, 0, 4, {A_ZThrust}, 0, (1<<16)|1, S_SMASHSPIKE_FALL, 0}, // S_SMASHSPIKE_EASE2 + {SPR_FMCE, 0, 2, {A_ZThrust}, -6, 1, S_SMASHSPIKE_FALL, 0}, // S_SMASHSPIKE_FALL + {SPR_FMCE, 1, 2, {A_MultiShotDist}, (MT_DUST<<16)|10, -48, S_SMASHSPIKE_STOMP2, 0}, // S_SMASHSPIKE_STOMP1 + {SPR_FMCE, 2, 14, {NULL}, 0, 0, S_SMASHSPIKE_RISE1, 0}, // S_SMASHSPIKE_STOMP2 + {SPR_FMCE, 1, 2, {NULL}, 0, 0, S_SMASHSPIKE_RISE2, 0}, // S_SMASHSPIKE_RISE1 + {SPR_FMCE, 0, 2, {A_ZThrust}, 6, (1<<16)|1, S_SMASHSPIKE_RISE2, 0}, // S_SMASHSPIKE_RISE2 + + {SPR_CACO, 0, 5, {A_Look}, (1100<<16)|1, 0, S_CACO_LOOK, 0}, // S_CACO_LOOK + {SPR_CACO, 1, 0, {A_MultiShotDist}, (MT_DUST<<16)|7, -48, S_CACO_WAKE2, 0}, // S_CACO_WAKE1 + {SPR_CACO, 1, 10, {A_ZThrust}, 4, (1<<16)|1, S_CACO_WAKE3, 0}, // S_CACO_WAKE2 + {SPR_CACO, 2, 8, {A_ZThrust}, 2, (1<<16)|1, S_CACO_WAKE4, 0}, // S_CACO_WAKE3 + {SPR_CACO, 2, 4, {A_ZThrust}, 0, (1<<16)|1, S_CACO_ROAR, 0}, // S_CACO_WAKE4 + {SPR_CACO, 2, 10, {A_PlayActiveSound}, 0, 0, S_CACO_CHASE, 0}, // S_CACO_ROAR + {SPR_CACO, 2, 5, {A_JetChase}, 0, 0, S_CACO_CHASE_REPEAT, 0}, // S_CACO_CHASE + {SPR_CACO, 2, 0, {A_Repeat}, 5, S_CACO_CHASE, S_CACO_RANDOM, 0}, // S_CACO_CHASE_REPEAT + {SPR_CACO, 2, 0, {A_RandomState}, S_CACO_PREPARE_SOUND, S_CACO_CHASE, S_CACO_RANDOM, 0}, // S_CACO_RANDOM + {SPR_CACO, 2, 8, {A_PlaySound}, sfx_s3k95, 1, S_CACO_PREPARE1, 0}, // S_CACO_PREPARE_SOUND + {SPR_CACO, 3, 8, {NULL}, 0, 0, S_CACO_PREPARE2, 0}, // S_CACO_PREPARE1 + {SPR_CACO, 4|FF_FULLBRIGHT, 8, {NULL}, 0, 0, S_CACO_PREPARE3, 0}, // S_CACO_PREPARE2 + {SPR_CACO, 5|FF_FULLBRIGHT, 8, {NULL}, 0, 0, S_CACO_SHOOT_SOUND, 0}, // S_CACO_PREPARE3 + {SPR_CACO, 4|FF_FULLBRIGHT, 0, {A_PlaySound}, sfx_s3k4e, 1, S_CACO_SHOOT1, 0}, // S_CACO_SHOOT_SOUND + {SPR_CACO, 4|FF_FULLBRIGHT, 0, {A_SpawnParticleRelative}, 0, S_CACOFIRE_EXPLODE1, S_CACO_SHOOT2, 0}, // S_CACO_SHOOT1 + {SPR_CACO, 4|FF_FULLBRIGHT, 6, {A_FireShot}, MT_CACOFIRE, -24, S_CACO_CLOSE, 0}, // S_CACO_SHOOT2 + {SPR_CACO, 3, 15, {NULL}, 0, 0, S_CACO_CHASE, 0}, // S_CACO_CLOSE + {SPR_CACO, 10, 0, {A_SetObjectFlags}, MF_NOBLOCKMAP, 0, S_CACO_DIE_GIB1, 0}, // S_CACO_DIE_FLAGS + {SPR_CACO, 10, 0, {A_NapalmScatter}, (7<<16)|MT_CACOSHARD, (30<<16)|20, S_CACO_DIE_GIB2, 0}, // S_CACO_DIE_GIB1 + {SPR_CACO, 10, 0, {A_NapalmScatter}, (10<<16)|MT_CACOSHARD, (24<<16)|32, S_CACO_DIE_SCREAM, 0}, // S_CACO_DIE_GIB2 + {SPR_CACO, 10, 0, {A_Scream}, 0, 0, S_CACO_DIE_SHATTER, 0}, // S_CACO_DIE_SCREAM + {SPR_CACO, 10, 0, {A_PlaySound}, sfx_pumpkn, 1, S_CACO_DIE_FALL, 0}, // S_CACO_DIE_SHATTER + {SPR_CACO, 10, 250, {A_FlickySpawn}, (1<<16), 0, S_NULL, 0}, // S_CACO_DIE_FALL + + {SPR_CACO, 6, 0, {A_RandomState}, S_CACOSHARD1_1, S_CACOSHARD2_1, S_NULL, 0}, // S_CACOSHARD_RANDOMIZE + {SPR_CACO, 6, 3, {NULL}, 0, 0, S_CACOSHARD1_2, 0}, // S_CACOSHARD1_1 + {SPR_CACO, 7, 3, {NULL}, 0, 0, S_CACOSHARD1_1, 0}, // S_CACOSHARD1_2 + {SPR_CACO, 8, 3, {NULL}, 0, 0, S_CACOSHARD2_2, 0}, // S_CACOSHARD2_1 + {SPR_CACO, 9, 3, {NULL}, 0, 0, S_CACOSHARD2_1, 0}, // S_CACOSHARD2_2 + {SPR_BAL2, FF_FULLBRIGHT, 2, {A_GhostMe}, 0, 0, S_CACOFIRE2, 0}, // S_CACOFIRE1 + {SPR_BAL2, 1|FF_FULLBRIGHT, 2, {A_GhostMe}, 0, 0, S_CACOFIRE3, 0}, // S_CACOFIRE2 + {SPR_BAL2, FF_FULLBRIGHT, 0, {A_PlayActiveSound}, 0, 0, S_CACOFIRE1, 0}, // S_CACOFIRE3 + {SPR_BAL2, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_CACOFIRE_EXPLODE2, 0}, // S_CACOFIRE_EXPLODE1 + {SPR_BAL2, 3|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_CACOFIRE_EXPLODE3, 0}, // S_CACOFIRE_EXPLODE2 + {SPR_BAL2, 4|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_CACOFIRE_EXPLODE4, 0}, // S_CACOFIRE_EXPLODE3 + {SPR_BAL2, 5|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL, 0}, // S_CACOFIRE_EXPLODE4 + + {SPR_SBOB, 1, 10, {A_ZThrust}, -2, (1<<16)|1, S_SPINBOBERT_MOVE_UP, 0}, // S_SPINBOBERT_MOVE_FLIPUP + {SPR_SBOB, 0, 45, {A_ZThrust}, 4, (1<<16)|1, S_SPINBOBERT_MOVE_FLIPDOWN, 0}, // S_SPINBOBERT_MOVE_UP + {SPR_SBOB, 1, 10, {A_ZThrust}, 2, (1<<16)|1, S_SPINBOBERT_MOVE_DOWN, 0}, // S_SPINBOBERT_MOVE_FLIPDOWN + {SPR_SBOB, 2, 45, {A_ZThrust}, -4, (1<<16)|1, S_SPINBOBERT_MOVE_FLIPUP, 0}, // S_SPINBOBERT_MOVE_DOWN + {SPR_SBSK, FF_FULLBRIGHT, 1, {A_RotateSpikeBall}, 0, 0, S_SPINBOBERT_FIRE_GHOST, 0}, // S_SPINBOBERT_FIRE_MOVE + {SPR_SBSK, FF_FULLBRIGHT, 0, {A_SpawnParticleRelative}, 0, S_SPINBOBERT_FIRE_TRAIL1, S_SPINBOBERT_FIRE_MOVE, 0}, // S_SPINBOBERT_FIRE_GHOST + {SPR_SBFL, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SPINBOBERT_FIRE_TRAIL2, 0}, // S_SPINBOBERT_FIRE_TRAIL1 + {SPR_SBFL, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SPINBOBERT_FIRE_TRAIL3, 0}, // S_SPINBOBERT_FIRE_TRAIL2 + {SPR_SBFL, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL, 0}, // S_SPINBOBERT_FIRE_TRAIL3 + + {SPR_HBAT, 0, 5, {A_Look}, (900<<16)|1, 0, S_HANGSTER_LOOK, 0}, // S_HANGSTER_LOOK + {SPR_HBAT, 1, 0, {A_MultiShotDist}, (MT_DUST<<16)|10, -34, S_HANGSTER_SWOOP2, 0}, // S_HANGSTER_SWOOP1 + {SPR_HBAT, 1, 2, {A_ZThrust}, -8, (1<<16)|1, S_HANGSTER_SWOOP2, 0}, // S_HANGSTER_SWOOP2 + {SPR_HBAT, 1, 6, {A_ZThrust}, -5, (1<<16), S_HANGSTER_ARC2, 0}, // S_HANGSTER_ARC1 + {SPR_HBAT, 1, 5, {A_ZThrust}, -2, (1<<16), S_HANGSTER_ARC3, 0}, // S_HANGSTER_ARC2 + {SPR_HBAT, 1, 1, {A_ZThrust}, 0, (1<<16), S_HANGSTER_FLY1, 0}, // S_HANGSTER_ARC3 + {SPR_HBAT, 1, 4, {A_Thrust}, 6, 1, S_HANGSTER_FLY2, 0}, // S_HANGSTER_FLY1 + {SPR_HBAT, 2, 1, {A_PlaySound}, sfx_s3k52, 1, S_HANGSTER_FLY3, 0}, // S_HANGSTER_FLY2 + {SPR_HBAT, 3, 4, {A_Thrust}, 6, 1, S_HANGSTER_FLY4, 0}, // S_HANGSTER_FLY3 + {SPR_HBAT, 2, 1, {A_Thrust}, 6, 1, S_HANGSTER_FLYREPEAT, 0}, // S_HANGSTER_FLY4 + {SPR_HBAT, 2, 0, {A_Repeat}, 12, S_HANGSTER_FLY1, S_HANGSTER_ARCUP1, 0}, // S_HANGSTER_FLYREPEAT + {SPR_HBAT, 1, 5, {A_ZThrust}, 2, (1<<16), S_HANGSTER_ARCUP2, 0}, // S_HANGSTER_ARCUP1 + {SPR_HBAT, 1, 6, {A_ZThrust}, 5, (1<<16), S_HANGSTER_ARCUP3, 0}, // S_HANGSTER_ARCUP2 + {SPR_HBAT, 1, 1, {A_ZThrust}, 0, (1<<16), S_HANGSTER_RETURN1, 0}, // S_HANGSTER_ARCUP3 + {SPR_HBAT, 1, 1, {A_ZThrust}, 8, (1<<16), S_HANGSTER_RETURN2, 0}, // S_HANGSTER_RETURN1 + {SPR_HBAT, 3, 1, {NULL}, 0, 0, S_HANGSTER_RETURN1, 0}, // S_HANGSTER_RETURN2 + {SPR_HBAT, 0, 15, {NULL}, 0, 0, S_HANGSTER_LOOK, 0}, // S_HANGSTER_RETURN3 + + {SPR_NULL, 0, 35, {NULL}, 0, 0, S_CRUMBLE2, 0}, // S_CRUMBLE1 + {SPR_NULL, 0, 105, {A_Scream}, 0, 0, S_NULL, 0}, // S_CRUMBLE2 // Spark - {SPR_NULL, 0, 1, {A_ModuloToState}, 2, S_SPRK2, S_SPRK3}, // S_SPRK1 - {SPR_SPRK, FF_TRANS20|FF_ANIMATE|0, 18, {NULL}, 8, 2, S_NULL}, // S_SPRK2 - {SPR_SPRK, FF_TRANS20|FF_ANIMATE|9, 18, {NULL}, 8, 2, S_NULL}, // S_SPRK3 + {SPR_NULL, 0, 1, {A_ModuloToState}, 2, S_SPRK2, S_SPRK3, 0}, // S_SPRK1 + {SPR_SPRK, FF_TRANS20|FF_ANIMATE|0, 18, {NULL}, 8, 2, S_NULL, 0}, // S_SPRK2 + {SPR_SPRK, FF_TRANS20|FF_ANIMATE|9, 18, {NULL}, 8, 2, S_NULL, 0}, // S_SPRK3 // Robot Explosion - {SPR_BOM1, 0, 0, {A_FlickySpawn}, 0, 0, S_XPLD1}, // S_XPLD_FLICKY - {SPR_BOM1, 0, 2, {A_ShadowScream}, 0, 0, S_XPLD2}, // S_XPLD1 - {SPR_BOM1, 1, 2, {NULL}, 0, 0, S_XPLD3}, // S_XPLD2 - {SPR_BOM1, 2, 3, {NULL}, 0, 0, S_XPLD4}, // S_XPLD3 - {SPR_BOM1, 3, 3, {NULL}, 0, 0, S_XPLD5}, // S_XPLD4 - {SPR_BOM1, 4, 4, {NULL}, 0, 0, S_XPLD6}, // S_XPLD5 - {SPR_BOM1, 5, 4, {NULL}, 0, 0, S_NULL}, // S_XPLD6 + {SPR_BOM1, 0, 0, {A_FlickySpawn}, 0, 0, S_XPLD1, 0}, // S_XPLD_FLICKY + {SPR_BOM1, 0, 2, {A_ShadowScream}, 0, 0, S_XPLD2, 0}, // S_XPLD1 + {SPR_BOM1, 1, 2, {NULL}, 0, 0, S_XPLD3, 0}, // S_XPLD2 + {SPR_BOM1, 2, 3, {NULL}, 0, 0, S_XPLD4, 0}, // S_XPLD3 + {SPR_BOM1, 3, 3, {NULL}, 0, 0, S_XPLD5, 0}, // S_XPLD4 + {SPR_BOM1, 4, 4, {NULL}, 0, 0, S_XPLD6, 0}, // S_XPLD5 + {SPR_BOM1, 5, 4, {NULL}, 0, 0, S_NULL, 0}, // S_XPLD6 - {SPR_BOM1, FF_ANIMATE, 21, {NULL}, 5, 4, S_INVISIBLE}, // S_XPLD_EGGTRAP + {SPR_BOM1, FF_ANIMATE, 21, {NULL}, 5, 4, S_INVISIBLE, 0}, // S_XPLD_EGGTRAP // Underwater Explosion - {SPR_BOM4, 0, 3, {A_ShadowScream}, 0, 0, S_WPLD2}, // S_WPLD1 - {SPR_BOM4, 1, 3, {NULL}, 0, 0, S_WPLD3}, // S_WPLD2 - {SPR_BOM4, 2, 3, {NULL}, 0, 0, S_WPLD4}, // S_WPLD3 - {SPR_BOM4, 3, 3, {NULL}, 0, 0, S_WPLD5}, // S_WPLD4 - {SPR_BOM4, 4, 3, {NULL}, 0, 0, S_WPLD6}, // S_WPLD5 - {SPR_BOM4, 5, 3, {NULL}, 0, 0, S_NULL}, // S_WPLD6 - - {SPR_DUST, FF_TRANS40, 4, {NULL}, 0, 0, S_DUST2}, // S_DUST1 - {SPR_DUST, 1|FF_TRANS50, 5, {NULL}, 0, 0, S_DUST3}, // S_DUST2 - {SPR_DUST, 2|FF_TRANS60, 3, {NULL}, 0, 0, S_DUST4}, // S_DUST3 - {SPR_DUST, 3|FF_TRANS70, 2, {NULL}, 0, 0, S_NULL}, // S_DUST4 - - {SPR_NULL, 0, 1, {A_RockSpawn}, 0, 0, S_ROCKSPAWN}, // S_ROCKSPAWN - - {SPR_ROIA, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEA - {SPR_ROIB, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEB - {SPR_ROIC, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEC - {SPR_ROID, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLED - {SPR_ROIE, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEE - {SPR_ROIF, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEF - {SPR_ROIG, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEG - {SPR_ROIH, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEH - {SPR_ROII, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEI - {SPR_ROIJ, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEJ - {SPR_ROIK, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEK - {SPR_ROIL, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEL - {SPR_ROIM, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEM - {SPR_ROIN, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEN - {SPR_ROIO, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEO - {SPR_ROIP, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL}, // S_ROCKCRUMBLEP - - {SPR_GFZD, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 31, 1, S_NULL}, // S_GFZDEBRIS - {SPR_BRIC, FF_ANIMATE, -1, {A_DebrisRandom}, 7, 2, S_NULL}, // S_BRICKDEBRIS - {SPR_WDDB, FF_ANIMATE, -1, {A_DebrisRandom}, 7, 2, S_NULL}, // S_WOODDEBRIS - {SPR_BRIR, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 31, 1, S_NULL}, // S_REDBRICKDEBRIS - {SPR_BRIB, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 31, 1, S_NULL}, // S_BLUEBRICKDEBRIS - {SPR_BRIY, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 31, 1, S_NULL}, // S_YELLOWBRICKDEBRIS - - {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK + {SPR_BOM4, 0, 3, {A_ShadowScream}, 0, 0, S_WPLD2, 0}, // S_WPLD1 + {SPR_BOM4, 1, 3, {NULL}, 0, 0, S_WPLD3, 0}, // S_WPLD2 + {SPR_BOM4, 2, 3, {NULL}, 0, 0, S_WPLD4, 0}, // S_WPLD3 + {SPR_BOM4, 3, 3, {NULL}, 0, 0, S_WPLD5, 0}, // S_WPLD4 + {SPR_BOM4, 4, 3, {NULL}, 0, 0, S_WPLD6, 0}, // S_WPLD5 + {SPR_BOM4, 5, 3, {NULL}, 0, 0, S_NULL, 0}, // S_WPLD6 + + {SPR_DUST, FF_TRANS40, 4, {NULL}, 0, 0, S_DUST2, 0}, // S_DUST1 + {SPR_DUST, 1|FF_TRANS50, 5, {NULL}, 0, 0, S_DUST3, 0}, // S_DUST2 + {SPR_DUST, 2|FF_TRANS60, 3, {NULL}, 0, 0, S_DUST4, 0}, // S_DUST3 + {SPR_DUST, 3|FF_TRANS70, 2, {NULL}, 0, 0, S_NULL, 0}, // S_DUST4 + + {SPR_NULL, 0, 1, {A_RockSpawn}, 0, 0, S_ROCKSPAWN, 0}, // S_ROCKSPAWN + + {SPR_ROIA, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL, 0}, // S_ROCKCRUMBLEA + {SPR_ROIB, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL, 0}, // S_ROCKCRUMBLEB + {SPR_ROIC, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL, 0}, // S_ROCKCRUMBLEC + {SPR_ROID, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL, 0}, // S_ROCKCRUMBLED + {SPR_ROIE, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL, 0}, // S_ROCKCRUMBLEE + {SPR_ROIF, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL, 0}, // S_ROCKCRUMBLEF + {SPR_ROIG, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL, 0}, // S_ROCKCRUMBLEG + {SPR_ROIH, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL, 0}, // S_ROCKCRUMBLEH + {SPR_ROII, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL, 0}, // S_ROCKCRUMBLEI + {SPR_ROIJ, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL, 0}, // S_ROCKCRUMBLEJ + {SPR_ROIK, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL, 0}, // S_ROCKCRUMBLEK + {SPR_ROIL, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL, 0}, // S_ROCKCRUMBLEL + {SPR_ROIM, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL, 0}, // S_ROCKCRUMBLEM + {SPR_ROIN, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL, 0}, // S_ROCKCRUMBLEN + {SPR_ROIO, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL, 0}, // S_ROCKCRUMBLEO + {SPR_ROIP, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 7, 2, S_NULL, 0}, // S_ROCKCRUMBLEP + + {SPR_GFZD, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 31, 1, S_NULL, 0}, // S_GFZDEBRIS + {SPR_BRIC, FF_ANIMATE, -1, {A_DebrisRandom}, 7, 2, S_NULL, 0}, // S_BRICKDEBRIS + {SPR_WDDB, FF_ANIMATE, -1, {A_DebrisRandom}, 7, 2, S_NULL, 0}, // S_WOODDEBRIS + {SPR_BRIR, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 31, 1, S_NULL, 0}, // S_REDBRICKDEBRIS + {SPR_BRIB, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 31, 1, S_NULL, 0}, // S_BLUEBRICKDEBRIS + {SPR_BRIY, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 31, 1, S_NULL, 0}, // S_YELLOWBRICKDEBRIS + + {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL, 0}, // S_NAMECHECK + + {SPR_OLDK, FF_ANIMATE, -1, {NULL}, 1, 16, S_NULL, 0}, // S_OLDK_STND + {SPR_OLDK, 2, 0, {A_ForceWin}, 0, 0, S_OLDK_DIE1, 0}, // S_OLDK_DIE0 + {SPR_OLDK, 2, 0, {A_Scream}, 0, 0, S_OLDK_DIE2, 0}, // S_OLDK_DIE1 + {SPR_OLDK, 2, -1, {A_ZThrust}, 14, 1|(1<<16), S_NULL, 0}, // S_OLDK_DIE2 }; mobjinfo_t mobjinfo[NUMMOBJTYPES] = @@ -7493,12 +7536,12 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_steam1, // deathsound 0, // speed 32*FRACUNIT, // radius - 1*FRACUNIT, // height + 16*FRACUNIT, // height 0, // display offset 20*FRACUNIT, // mass 0, // damage sfx_None, // activesound - MF_SOLID, // flags + MF_SPECIAL, // flags S_NULL // raisestate }, @@ -14522,6 +14565,114 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_SSZTREE + 1860, // doomednum + S_SSZTREE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 256*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_None, // activesound + MF_SOLID|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_SSZTREE_BRANCH + -1, // doomednum + S_SSZTREE_BRANCH, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 256*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_SSZTREE2 + 1861, // doomednum + S_SSZTREE2, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 256*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_None, // activesound + MF_SOLID|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_SSZTREE2_BRANCH + -1, // doomednum + S_SSZTREE2_BRANCH, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 20*FRACUNIT, // radius + 256*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + S_NULL // raisestate + }, + { // MT_XMASBLUEBERRYBUSH 1859, // doomednum S_XMASBLUEBERRYBUSH, // spawnstate @@ -14659,7 +14810,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_ROSY 2104, // doomednum - S_ROSY_IDLE1, // spawnstate + S_ROSY_IDLE, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -16361,6 +16512,87 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_GINE + 3048, // doomednum + S_GINE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 32*FRACUNIT, // radius + 628*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_None, // activesound + MF_SOLID|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_PPAL + 3050, // doomednum + S_PPAL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 626*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_None, // activesound + MF_SOLID|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_PPEL + 3051, // doomednum + S_PPEL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 517*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_None, // activesound + MF_SOLID|MF_SCENERY, // flags + S_NULL // raisestate + }, + { // MT_ELEMENTAL_ORB -1, // doomednum S_ELEM1, // spawnstate @@ -21603,6 +21835,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags S_NULL // raisestate }, + + { // MT_OLDK + 666, // doomednum + S_OLDK_STND, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 32, // reactiontime + sfx_None, // attacksound + S_OLDK_DIE0, // painstate + 128, // painchance + sfx_s3k35, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_OLDK_DIE0, // deathstate + S_NULL, // xdeathstate + sfx_s3k35, // deathsound + 2*FRACUNIT, // speed + 32*FRACUNIT, // radius + 64*FRACUNIT, // height + 0, // display offset + 1000, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_SHOOTABLE|MF_NOGRAVITY|MF_BOSS, // flags + S_NULL // raisestate + }, }; skincolor_t skincolors[MAXSKINCOLORS] = { @@ -21638,15 +21897,15 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"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 + {"Lavender", {0xc0, 0xc0, 0xc1, 0xc1, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc4, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc7}, SKINCOLOR_HEADLIGHT, 8, 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 + {"Pepper", { 210, 32, 33, 34, 35, 35, 36, 37, 38, 39, 41, 43, 45, 45, 46, 47}, SKINCOLOR_GREEN, 10, V_REDMAP, true}, // SKINCOLOR_PEPPER + {"Red", {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x47, 0x2e, 0x2f}, SKINCOLOR_MASTER, 8, 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 {"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 @@ -21661,7 +21920,7 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"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 + {"Gold", {0x51, 0x51, 0x54, 0x54, 0x41, 0x42, 0x43, 0x43, 0x44, 0x45, 0x46, 0x3f, 0x2d, 0x2e, 0x2f, 0x2f}, SKINCOLOR_MAUVE, 8, 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 @@ -21671,19 +21930,19 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"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 + {"Headlight", { 0, 80, 81, 82, 73, 84, 64, 65, 91, 91, 124, 125, 126, 137, 138, 139}, SKINCOLOR_LAVENDER, 10, 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 + {"Green", {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f}, SKINCOLOR_PEPPER, 8, 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 {"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 + {"Jade", { 128, 120, 121, 122, 122, 113, 114, 114, 115, 116, 117, 118, 119, 110, 111, 30}, SKINCOLOR_ROSY, 7, 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 - {"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 + {"Master", { 0, 80, 88, 96, 112, 113, 99, 100, 124, 125, 126, 117, 107, 118, 119, 111}, SKINCOLOR_RED, 6, 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 + {"Aqua", {0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7e, 0x7e, 0x7f, 0x7f, 0x76, 0x77}, SKINCOLOR_TAFFY, 10, 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 @@ -21717,12 +21976,12 @@ skincolor_t skincolors[MAXSKINCOLORS] = { {"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 + {"Mauve", { 176, 177, 178, 192, 193, 194, 195, 195, 196, 185, 185, 186, 186, 187, 187, 253}, SKINCOLOR_GOLD, 4, 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 + {"Taffy", { 1, 176, 176, 177, 178, 179, 202, 203, 204, 204, 205, 206, 207, 44, 45, 46}, SKINCOLOR_AQUA, 1, V_ROSYMAP, true}, // SKINCOLOR_TAFFY + {"Rosy", {0xfc, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcb, 0xcc, 0xcc, 0xcd, 0xcd, 0xce, 0xce, 0xcf}, SKINCOLOR_JADE, 8, 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 @@ -21791,7 +22050,7 @@ void P_PatchInfoTables(void) INT32 i; char *tempname; -#if NUMSPRITEFREESLOTS > 1000 +#if NUMSPRITEFREESLOTS > 9999 //tempname numbering actually starts at SPR_FIRSTFREESLOT, so the limit is actually 9999 + SPR_FIRSTFREESLOT-1, but the preprocessor doesn't understand enums, so its left at 9999 for safety "Update P_PatchInfoTables, you big dumb head" #endif @@ -21799,8 +22058,8 @@ void P_PatchInfoTables(void) for (i = SPR_FIRSTFREESLOT; i <= SPR_LASTFREESLOT; i++) { tempname = sprnames[i]; - tempname[0] = 'F'; - tempname[1] = (char)('0' + (char)((i-SPR_FIRSTFREESLOT+1)/100)); + tempname[0] = (char)('0' + (char)((i-SPR_FIRSTFREESLOT+1)/1000)); + tempname[1] = (char)('0' + (char)(((i-SPR_FIRSTFREESLOT+1)/100)%10)); tempname[2] = (char)('0' + (char)(((i-SPR_FIRSTFREESLOT+1)/10)%10)); tempname[3] = (char)('0' + (char)((i-SPR_FIRSTFREESLOT+1)%10)); tempname[4] = '\0'; diff --git a/src/info.h b/src/info.h index 2362935f0629cf7304df3ea5a9f673f2aa3b3183..94b0aeb48111178e2262a1f1144c7ff623fb3a43 100644 --- a/src/info.h +++ b/src/info.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -298,283 +298,286 @@ enum actionnum NUMACTIONS }; +struct mobj_s; + // IMPORTANT NOTE: If you add/remove from this list of action // functions, don't forget to update them in deh_tables.c! -void A_Explode(); -void A_Pain(); -void A_Fall(); -void A_MonitorPop(); -void A_GoldMonitorPop(); -void A_GoldMonitorRestore(); -void A_GoldMonitorSparkle(); -void A_Look(); -void A_Chase(); -void A_FaceStabChase(); -void A_FaceStabRev(); -void A_FaceStabHurl(); -void A_FaceStabMiss(); -void A_StatueBurst(); -void A_FaceTarget(); -void A_FaceTracer(); -void A_Scream(); -void A_BossDeath(); -void A_SetShadowScale(); -void A_ShadowScream(); // MARIA!!!!!! -void A_CustomPower(); // Use this for a custom power -void A_GiveWeapon(); // Gives the player weapon(s) -void A_RingBox(); // Obtained Ring Box Tails -void A_Invincibility(); // Obtained Invincibility Box -void A_SuperSneakers(); // Obtained Super Sneakers Box -void A_BunnyHop(); // have bunny hop tails -void A_BubbleSpawn(); // Randomly spawn bubbles -void A_FanBubbleSpawn(); -void A_BubbleRise(); // Bubbles float to surface -void A_BubbleCheck(); // Don't draw if not underwater -void A_AwardScore(); -void A_ExtraLife(); // Extra Life -void A_GiveShield(); // Obtained Shield -void A_GravityBox(); -void A_ScoreRise(); // Rise the score logo -void A_AttractChase(); // Ring Chase -void A_DropMine(); // Drop Mine from Skim or Jetty-Syn Bomber -void A_FishJump(); // Fish Jump -void A_ThrownRing(); // Sparkle trail for red ring -void A_SetSolidSteam(); -void A_UnsetSolidSteam(); -void A_SignSpin(); -void A_SignPlayer(); -void A_OverlayThink(); -void A_JetChase(); -void A_JetbThink(); // Jetty-Syn Bomber Thinker -void A_JetgThink(); // Jetty-Syn Gunner Thinker -void A_JetgShoot(); // Jetty-Syn Shoot Function -void A_ShootBullet(); // JetgShoot without reactiontime setting -void A_MinusDigging(); -void A_MinusPopup(); -void A_MinusCheck(); -void A_ChickenCheck(); -void A_MouseThink(); // Mouse Thinker -void A_DetonChase(); // Deton Chaser -void A_CapeChase(); // Fake little Super Sonic cape -void A_RotateSpikeBall(); // Spike ball rotation -void A_SlingAppear(); -void A_UnidusBall(); -void A_RockSpawn(); -void A_SetFuse(); -void A_CrawlaCommanderThink(); // Crawla Commander -void A_SmokeTrailer(); -void A_RingExplode(); -void A_OldRingExplode(); -void A_MixUp(); -void A_RecyclePowers(); -void A_BossScream(); -void A_Boss2TakeDamage(); -void A_GoopSplat(); -void A_Boss2PogoSFX(); -void A_Boss2PogoTarget(); -void A_EggmanBox(); -void A_TurretFire(); -void A_SuperTurretFire(); -void A_TurretStop(); -void A_JetJawRoam(); -void A_JetJawChomp(); -void A_PointyThink(); -void A_CheckBuddy(); -void A_HoodFire(); -void A_HoodThink(); -void A_HoodFall(); -void A_ArrowBonks(); -void A_SnailerThink(); -void A_SharpChase(); -void A_SharpSpin(); -void A_SharpDecel(); -void A_CrushstaceanWalk(); -void A_CrushstaceanPunch(); -void A_CrushclawAim(); -void A_CrushclawLaunch(); -void A_VultureVtol(); -void A_VultureCheck(); -void A_VultureHover(); -void A_VultureBlast(); -void A_VultureFly(); -void A_SkimChase(); -void A_SkullAttack(); -void A_LobShot(); -void A_FireShot(); -void A_SuperFireShot(); -void A_BossFireShot(); -void A_Boss7FireMissiles(); -void A_Boss1Laser(); -void A_FocusTarget(); -void A_Boss4Reverse(); -void A_Boss4SpeedUp(); -void A_Boss4Raise(); -void A_SparkFollow(); -void A_BuzzFly(); -void A_GuardChase(); -void A_EggShield(); -void A_SetReactionTime(); -void A_Boss1Spikeballs(); -void A_Boss3TakeDamage(); -void A_Boss3Path(); -void A_Boss3ShockThink(); -void A_Shockwave(); -void A_LinedefExecute(); -void A_LinedefExecuteFromArg(); -void A_PlaySeeSound(); -void A_PlayAttackSound(); -void A_PlayActiveSound(); -void A_1upThinker(); -void A_BossZoom(); //Unused -void A_Boss1Chase(); -void A_Boss2Chase(); -void A_Boss2Pogo(); -void A_Boss7Chase(); -void A_BossJetFume(); -void A_SpawnObjectAbsolute(); -void A_SpawnObjectRelative(); -void A_ChangeAngleRelative(); -void A_ChangeAngleAbsolute(); -void A_RollAngle(); -void A_ChangeRollAngleRelative(); -void A_ChangeRollAngleAbsolute(); -void A_PlaySound(); -void A_FindTarget(); -void A_FindTracer(); -void A_SetTics(); -void A_SetRandomTics(); -void A_ChangeColorRelative(); -void A_ChangeColorAbsolute(); -void A_Dye(); -void A_SetTranslation(); -void A_MoveRelative(); -void A_MoveAbsolute(); -void A_Thrust(); -void A_ZThrust(); -void A_SetTargetsTarget(); -void A_SetObjectFlags(); -void A_SetObjectFlags2(); -void A_RandomState(); -void A_RandomStateRange(); -void A_StateRangeByAngle(); -void A_StateRangeByParameter(); -void A_DualAction(); -void A_RemoteAction(); -void A_ToggleFlameJet(); -void A_OrbitNights(); -void A_GhostMe(); -void A_SetObjectState(); -void A_SetObjectTypeState(); -void A_KnockBack(); -void A_PushAway(); -void A_RingDrain(); -void A_SplitShot(); -void A_MissileSplit(); -void A_MultiShot(); -void A_InstaLoop(); -void A_Custom3DRotate(); -void A_SearchForPlayers(); -void A_CheckRandom(); -void A_CheckTargetRings(); -void A_CheckRings(); -void A_CheckTotalRings(); -void A_CheckHealth(); -void A_CheckRange(); -void A_CheckHeight(); -void A_CheckTrueRange(); -void A_CheckThingCount(); -void A_CheckAmbush(); -void A_CheckCustomValue(); -void A_CheckCusValMemo(); -void A_SetCustomValue(); -void A_UseCusValMemo(); -void A_RelayCustomValue(); -void A_CusValAction(); -void A_ForceStop(); -void A_ForceWin(); -void A_SpikeRetract(); -void A_InfoState(); -void A_Repeat(); -void A_SetScale(); -void A_RemoteDamage(); -void A_HomingChase(); -void A_TrapShot(); -void A_VileTarget(); -void A_VileAttack(); -void A_VileFire(); -void A_BrakChase(); -void A_BrakFireShot(); -void A_BrakLobShot(); -void A_NapalmScatter(); -void A_SpawnFreshCopy(); -void A_FlickySpawn(); -void A_FlickyCenter(); -void A_FlickyAim(); -void A_FlickyFly(); -void A_FlickySoar(); -void A_FlickyCoast(); -void A_FlickyHop(); -void A_FlickyFlounder(); -void A_FlickyCheck(); -void A_FlickyHeightCheck(); -void A_FlickyFlutter(); -void A_FlameParticle(); -void A_FadeOverlay(); -void A_Boss5Jump(); -void A_LightBeamReset(); -void A_MineExplode(); -void A_MineRange(); -void A_ConnectToGround(); -void A_SpawnParticleRelative(); -void A_MultiShotDist(); -void A_WhoCaresIfYourSonIsABee(); -void A_ParentTriesToSleep(); -void A_CryingToMomma(); -void A_CheckFlags2(); -void A_Boss5FindWaypoint(); -void A_DoNPCSkid(); -void A_DoNPCPain(); -void A_PrepareRepeat(); -void A_Boss5ExtraRepeat(); -void A_Boss5Calm(); -void A_Boss5CheckOnGround(); -void A_Boss5CheckFalling(); -void A_Boss5PinchShot(); -void A_Boss5MakeItRain(); -void A_Boss5MakeJunk(); -void A_LookForBetter(); -void A_Boss5BombExplode(); -void A_DustDevilThink(); -void A_TNTExplode(); -void A_DebrisRandom(); -void A_TrainCameo(); -void A_TrainCameo2(); -void A_CanarivoreGas(); -void A_KillSegments(); -void A_SnapperSpawn(); -void A_SnapperThinker(); -void A_SaloonDoorSpawn(); -void A_MinecartSparkThink(); -void A_ModuloToState(); -void A_LavafallRocks(); -void A_LavafallLava(); -void A_FallingLavaCheck(); -void A_FireShrink(); -void A_SpawnPterabytes(); -void A_PterabyteHover(); -void A_RolloutSpawn(); -void A_RolloutRock(); -void A_DragonbomberSpawn(); -void A_DragonWing(); -void A_DragonSegment(); -void A_ChangeHeight(); +void A_Explode(struct mobj_s *actor); +void A_Pain(struct mobj_s *actor); +void A_Fall(struct mobj_s *actor); +void A_MonitorPop(struct mobj_s *actor); +void A_GoldMonitorPop(struct mobj_s *actor); +void A_GoldMonitorRestore(struct mobj_s *actor); +void A_GoldMonitorSparkle(struct mobj_s *actor); +void A_Look(struct mobj_s *actor); +void A_Chase(struct mobj_s *actor); +void A_FaceStabChase(struct mobj_s *actor); +void A_FaceStabRev(struct mobj_s *actor); +void A_FaceStabHurl(struct mobj_s *actor); +void A_FaceStabMiss(struct mobj_s *actor); +void A_StatueBurst(struct mobj_s *actor); +void A_FaceTarget(struct mobj_s *actor); +void A_FaceTracer(struct mobj_s *actor); +void A_Scream(struct mobj_s *actor); +void A_BossDeath(struct mobj_s *actor); +void A_SetShadowScale(struct mobj_s *actor); +void A_ShadowScream(struct mobj_s *actor); // MARIA!!!!!! +void A_CustomPower(struct mobj_s *actor); // Use this for a custom power +void A_GiveWeapon(struct mobj_s *actor); // Gives the player weapon(s) +void A_RingBox(struct mobj_s *actor); // Obtained Ring Box Tails +void A_Invincibility(struct mobj_s *actor); // Obtained Invincibility Box +void A_SuperSneakers(struct mobj_s *actor); // Obtained Super Sneakers Box +void A_BunnyHop(struct mobj_s *actor); // have bunny hop tails +void A_BubbleSpawn(struct mobj_s *actor); // Randomly spawn bubbles +void A_FanBubbleSpawn(struct mobj_s *actor); +void A_BubbleRise(struct mobj_s *actor); // Bubbles float to surface +void A_BubbleCheck(struct mobj_s *actor); // Don't draw if not underwater +void A_AwardScore(struct mobj_s *actor); +void A_ExtraLife(struct mobj_s *actor); // Extra Life +void A_GiveShield(struct mobj_s *actor); // Obtained Shield +void A_GravityBox(struct mobj_s *actor); +void A_ScoreRise(struct mobj_s *actor); // Rise the score logo +void A_AttractChase(struct mobj_s *actor); // Ring Chase +void A_DropMine(struct mobj_s *actor); // Drop Mine from Skim or Jetty-Syn Bomber +void A_FishJump(struct mobj_s *actor); // Fish Jump +void A_ThrownRing(struct mobj_s *actor); // Sparkle trail for red ring +void A_SetSolidSteam(struct mobj_s *actor); +void A_UnsetSolidSteam(struct mobj_s *actor); +void A_SignSpin(struct mobj_s *actor); +void A_SignPlayer(struct mobj_s *actor); +void A_OverlayThink(struct mobj_s *actor); +void A_JetChase(struct mobj_s *actor); +void A_JetbThink(struct mobj_s *actor); // Jetty-Syn Bomber Thinker +void A_JetgThink(struct mobj_s *actor); // Jetty-Syn Gunner Thinker +void A_JetgShoot(struct mobj_s *actor); // Jetty-Syn Shoot Function +void A_ShootBullet(struct mobj_s *actor); // JetgShoot without reactiontime setting +void A_MinusDigging(struct mobj_s *actor); +void A_MinusPopup(struct mobj_s *actor); +void A_MinusCheck(struct mobj_s *actor); +void A_ChickenCheck(struct mobj_s *actor); +void A_MouseThink(struct mobj_s *actor); // Mouse Thinker +void A_DetonChase(struct mobj_s *actor); // Deton Chaser +void A_CapeChase(struct mobj_s *actor); // Fake little Super Sonic cape +void A_RotateSpikeBall(struct mobj_s *actor); // Spike ball rotation +void A_SlingAppear(struct mobj_s *actor); +void A_UnidusBall(struct mobj_s *actor); +void A_RockSpawn(struct mobj_s *actor); +void A_SetFuse(struct mobj_s *actor); +void A_CrawlaCommanderThink(struct mobj_s *actor); // Crawla Commander +void A_SmokeTrailer(struct mobj_s *actor); +void A_RingExplode(struct mobj_s *actor); +void A_OldRingExplode(struct mobj_s *actor); +void A_MixUp(struct mobj_s *actor); +void A_RecyclePowers(struct mobj_s *actor); +void A_BossScream(struct mobj_s *actor); +void A_Boss2TakeDamage(struct mobj_s *actor); +void A_GoopSplat(struct mobj_s *actor); +void A_Boss2PogoSFX(struct mobj_s *actor); +void A_Boss2PogoTarget(struct mobj_s *actor); +void A_EggmanBox(struct mobj_s *actor); +void A_TurretFire(struct mobj_s *actor); +void A_SuperTurretFire(struct mobj_s *actor); +void A_TurretStop(struct mobj_s *actor); +void A_JetJawRoam(struct mobj_s *actor); +void A_JetJawChomp(struct mobj_s *actor); +void A_PointyThink(struct mobj_s *actor); +void A_CheckBuddy(struct mobj_s *actor); +void A_HoodFire(struct mobj_s *actor); +void A_HoodThink(struct mobj_s *actor); +void A_HoodFall(struct mobj_s *actor); +void A_ArrowBonks(struct mobj_s *actor); +void A_SnailerThink(struct mobj_s *actor); +void A_SharpChase(struct mobj_s *actor); +void A_SharpSpin(struct mobj_s *actor); +void A_SharpDecel(struct mobj_s *actor); +void A_CrushstaceanWalk(struct mobj_s *actor); +void A_CrushstaceanPunch(struct mobj_s *actor); +void A_CrushclawAim(struct mobj_s *actor); +void A_CrushclawLaunch(struct mobj_s *actor); +void A_VultureVtol(struct mobj_s *actor); +void A_VultureCheck(struct mobj_s *actor); +void A_VultureHover(struct mobj_s *actor); +void A_VultureBlast(struct mobj_s *actor); +void A_VultureFly(struct mobj_s *actor); +void A_SkimChase(struct mobj_s *actor); +void A_SkullAttack(struct mobj_s *actor); +void A_LobShot(struct mobj_s *actor); +void A_FireShot(struct mobj_s *actor); +void A_SuperFireShot(struct mobj_s *actor); +void A_BossFireShot(struct mobj_s *actor); +void A_Boss7FireMissiles(struct mobj_s *actor); +void A_Boss1Laser(struct mobj_s *actor); +void A_FocusTarget(struct mobj_s *actor); +void A_Boss4Reverse(struct mobj_s *actor); +void A_Boss4SpeedUp(struct mobj_s *actor); +void A_Boss4Raise(struct mobj_s *actor); +void A_SparkFollow(struct mobj_s *actor); +void A_BuzzFly(struct mobj_s *actor); +void A_GuardChase(struct mobj_s *actor); +void A_EggShield(struct mobj_s *actor); +void A_SetReactionTime(struct mobj_s *actor); +void A_Boss1Spikeballs(struct mobj_s *actor); +void A_Boss3TakeDamage(struct mobj_s *actor); +void A_Boss3Path(struct mobj_s *actor); +void A_Boss3ShockThink(struct mobj_s *actor); +void A_Shockwave(struct mobj_s *actor); +void A_LinedefExecute(struct mobj_s *actor); +void A_LinedefExecuteFromArg(struct mobj_s *actor); +void A_PlaySeeSound(struct mobj_s *actor); +void A_PlayAttackSound(struct mobj_s *actor); +void A_PlayActiveSound(struct mobj_s *actor); +void A_1upThinker(struct mobj_s *actor); +void A_BossZoom(struct mobj_s *actor); //Unused +void A_Boss1Chase(struct mobj_s *actor); +void A_Boss2Chase(struct mobj_s *actor); +void A_Boss2Pogo(struct mobj_s *actor); +void A_Boss7Chase(struct mobj_s *actor); +void A_BossJetFume(struct mobj_s *actor); +void A_SpawnObjectAbsolute(struct mobj_s *actor); +void A_SpawnObjectRelative(struct mobj_s *actor); +void A_ChangeAngleRelative(struct mobj_s *actor); +void A_ChangeAngleAbsolute(struct mobj_s *actor); +void A_RollAngle(struct mobj_s *actor); +void A_ChangeRollAngleRelative(struct mobj_s *actor); +void A_ChangeRollAngleAbsolute(struct mobj_s *actor); +void A_PlaySound(struct mobj_s *actor); +void A_FindTarget(struct mobj_s *actor); +void A_FindTracer(struct mobj_s *actor); +void A_SetTics(struct mobj_s *actor); +void A_SetRandomTics(struct mobj_s *actor); +void A_ChangeColorRelative(struct mobj_s *actor); +void A_ChangeColorAbsolute(struct mobj_s *actor); +void A_Dye(struct mobj_s *actor); +void A_SetTranslation(struct mobj_s *actor); +void A_MoveRelative(struct mobj_s *actor); +void A_MoveAbsolute(struct mobj_s *actor); +void A_Thrust(struct mobj_s *actor); +void A_ZThrust(struct mobj_s *actor); +void A_SetTargetsTarget(struct mobj_s *actor); +void A_SetObjectFlags(struct mobj_s *actor); +void A_SetObjectFlags2(struct mobj_s *actor); +void A_RandomState(struct mobj_s *actor); +void A_RandomStateRange(struct mobj_s *actor); +void A_StateRangeByAngle(struct mobj_s *actor); +void A_StateRangeByParameter(struct mobj_s *actor); +void A_DualAction(struct mobj_s *actor); +void A_RemoteAction(struct mobj_s *actor); +void A_ToggleFlameJet(struct mobj_s *actor); +void A_OrbitNights(struct mobj_s *actor); +void A_GhostMe(struct mobj_s *actor); +void A_SetObjectState(struct mobj_s *actor); +void A_SetObjectTypeState(struct mobj_s *actor); +void A_KnockBack(struct mobj_s *actor); +void A_PushAway(struct mobj_s *actor); +void A_RingDrain(struct mobj_s *actor); +void A_SplitShot(struct mobj_s *actor); +void A_MissileSplit(struct mobj_s *actor); +void A_MultiShot(struct mobj_s *actor); +void A_InstaLoop(struct mobj_s *actor); +void A_Custom3DRotate(struct mobj_s *actor); +void A_SearchForPlayers(struct mobj_s *actor); +void A_CheckRandom(struct mobj_s *actor); +void A_CheckTargetRings(struct mobj_s *actor); +void A_CheckRings(struct mobj_s *actor); +void A_CheckTotalRings(struct mobj_s *actor); +void A_CheckHealth(struct mobj_s *actor); +void A_CheckRange(struct mobj_s *actor); +void A_CheckHeight(struct mobj_s *actor); +void A_CheckTrueRange(struct mobj_s *actor); +void A_CheckThingCount(struct mobj_s *actor); +void A_CheckAmbush(struct mobj_s *actor); +void A_CheckCustomValue(struct mobj_s *actor); +void A_CheckCusValMemo(struct mobj_s *actor); +void A_SetCustomValue(struct mobj_s *actor); +void A_UseCusValMemo(struct mobj_s *actor); +void A_RelayCustomValue(struct mobj_s *actor); +void A_CusValAction(struct mobj_s *actor); +void A_ForceStop(struct mobj_s *actor); +void A_ForceWin(struct mobj_s *actor); +void A_SpikeRetract(struct mobj_s *actor); +void A_InfoState(struct mobj_s *actor); +void A_Repeat(struct mobj_s *actor); +void A_SetScale(struct mobj_s *actor); +void A_RemoteDamage(struct mobj_s *actor); +void A_HomingChase(struct mobj_s *actor); +void A_TrapShot(struct mobj_s *actor); +void A_VileTarget(struct mobj_s *actor); +void A_VileAttack(struct mobj_s *actor); +void A_VileFire(struct mobj_s *actor); +void A_BrakChase(struct mobj_s *actor); +void A_BrakFireShot(struct mobj_s *actor); +void A_BrakLobShot(struct mobj_s *actor); +void A_NapalmScatter(struct mobj_s *actor); +void A_SpawnFreshCopy(struct mobj_s *actor); +void A_FlickySpawn(struct mobj_s *actor); +void A_FlickyCenter(struct mobj_s *actor); +void A_FlickyAim(struct mobj_s *actor); +void A_FlickyFly(struct mobj_s *actor); +void A_FlickySoar(struct mobj_s *actor); +void A_FlickyCoast(struct mobj_s *actor); +void A_FlickyHop(struct mobj_s *actor); +void A_FlickyFlounder(struct mobj_s *actor); +void A_FlickyCheck(struct mobj_s *actor); +void A_FlickyHeightCheck(struct mobj_s *actor); +void A_FlickyFlutter(struct mobj_s *actor); +void A_FlameParticle(struct mobj_s *actor); +void A_FadeOverlay(struct mobj_s *actor); +void A_Boss5Jump(struct mobj_s *actor); +void A_LightBeamReset(struct mobj_s *actor); +void A_MineExplode(struct mobj_s *actor); +void A_MineRange(struct mobj_s *actor); +void A_ConnectToGround(struct mobj_s *actor); +void A_SpawnParticleRelative(struct mobj_s *actor); +void A_MultiShotDist(struct mobj_s *actor); +void A_WhoCaresIfYourSonIsABee(struct mobj_s *actor); +void A_ParentTriesToSleep(struct mobj_s *actor); +void A_CryingToMomma(struct mobj_s *actor); +void A_CheckFlags2(struct mobj_s *actor); +void A_Boss5FindWaypoint(struct mobj_s *actor); +void A_DoNPCSkid(struct mobj_s *actor); +void A_DoNPCPain(struct mobj_s *actor); +void A_PrepareRepeat(struct mobj_s *actor); +void A_Boss5ExtraRepeat(struct mobj_s *actor); +void A_Boss5Calm(struct mobj_s *actor); +void A_Boss5CheckOnGround(struct mobj_s *actor); +void A_Boss5CheckFalling(struct mobj_s *actor); +void A_Boss5PinchShot(struct mobj_s *actor); +void A_Boss5MakeItRain(struct mobj_s *actor); +void A_Boss5MakeJunk(struct mobj_s *actor); +void A_LookForBetter(struct mobj_s *actor); +void A_Boss5BombExplode(struct mobj_s *actor); +void A_DustDevilThink(struct mobj_s *actor); +void A_TNTExplode(struct mobj_s *actor); +void A_DebrisRandom(struct mobj_s *actor); +void A_TrainCameo(struct mobj_s *actor); +void A_TrainCameo2(struct mobj_s *actor); +void A_CanarivoreGas(struct mobj_s *actor); +void A_KillSegments(struct mobj_s *actor); +void A_SnapperSpawn(struct mobj_s *actor); +void A_SnapperThinker(struct mobj_s *actor); +void A_SaloonDoorSpawn(struct mobj_s *actor); +void A_MinecartSparkThink(struct mobj_s *actor); +void A_ModuloToState(struct mobj_s *actor); +void A_LavafallRocks(struct mobj_s *actor); +void A_LavafallLava(struct mobj_s *actor); +void A_FallingLavaCheck(struct mobj_s *actor); +void A_FireShrink(struct mobj_s *actor); +void A_SpawnPterabytes(struct mobj_s *actor); +void A_PterabyteHover(struct mobj_s *actor); +void A_RolloutSpawn(struct mobj_s *actor); +void A_RolloutRock(struct mobj_s *actor); +void A_DragonbomberSpawn(struct mobj_s *actor); +void A_DragonWing(struct mobj_s *actor); +void A_DragonSegment(struct mobj_s *actor); +void A_ChangeHeight(struct mobj_s *actor); extern int actionsoverridden[NUMACTIONS][MAX_ACTION_RECURSION]; // ratio of states to sprites to mobj types is roughly 6 : 1 : 1 -#define NUMMOBJFREESLOTS 512 +#define NUMMOBJFREESLOTS 1024 #define NUMSPRITEFREESLOTS NUMMOBJFREESLOTS #define NUMSTATEFREESLOTS (NUMMOBJFREESLOTS*8) +#define MAXSPRITENAME 64 // Hey, moron! If you change this table, don't forget about sprnames in info.c and the sprite lights in hw_light.c! typedef enum sprite @@ -854,6 +857,8 @@ typedef enum sprite SPR_XMS4, // Lamppost SPR_XMS5, // Hanging Star SPR_XMS6, // Mistletoe + SPR_SNTT, // Silver Shiver tree + SPR_SSTT, // Silver Shiver tree with snow SPR_FHZI, // FHZ Ice SPR_ROSY, @@ -887,6 +892,8 @@ typedef enum sprite // Misc Scenery SPR_STLG, // Stalagmites SPR_DBAL, // Disco + SPR_GINE, // Crystalline Heights tree + SPR_PPAL, // Pristine Shores palm trees // Powerup Indicators SPR_ARMA, // Armageddon Shield Orb @@ -1073,14 +1080,14 @@ typedef enum sprite SPR_GWLG, SPR_GWLR, + // LJ Knuckles + SPR_OLDK, + SPR_FIRSTFREESLOT, SPR_LASTFREESLOT = SPR_FIRSTFREESLOT + NUMSPRITEFREESLOTS - 1, NUMSPRITES } spritenum_t; -// Make sure to be conscious of FF_FRAMEMASK and the fact sprite2 is stored as a UINT8 whenever you change this table. -// Currently, FF_FRAMEMASK is 0xff, or 255 - but the second half is used by FF_SPR2SUPER, so the limitation is 0x7f. -// Since this is zero-based, there can be at most 128 different SPR2_'s without changing that. typedef enum playersprite { SPR2_STND = 0, @@ -1149,6 +1156,18 @@ typedef enum playersprite SPR2_TALB, SPR2_TALC, + // Misc slots + SPR2_MSC0, + SPR2_MSC1, + SPR2_MSC2, + SPR2_MSC3, + SPR2_MSC4, + SPR2_MSC5, + SPR2_MSC6, + SPR2_MSC7, + SPR2_MSC8, + SPR2_MSC9, + SPR2_CNT1, // continue disappointment SPR2_CNT2, // continue lift SPR2_CNT3, // continue spin @@ -1160,15 +1179,17 @@ typedef enum playersprite SPR2_XTRA, // stuff that isn't in-map - "would this ever need an md2 or variable length animation?" SPR2_FIRSTFREESLOT, - SPR2_LASTFREESLOT = 0x7f, + SPR2_LASTFREESLOT = 1024, // Do not make higher than SPR2F_MASK (currently 0x3FF) plus one NUMPLAYERSPRITES } playersprite_t; -// SPR2_XTRA -#define XTRA_LIFEPIC 0 // Life icon patch -#define XTRA_CHARSEL 1 // Character select picture -#define XTRA_CONTINUE 2 // Continue icon -#define XTRA_ENDING 3 // Ending finale patches +enum +{ + XTRA_LIFEPIC, + XTRA_CHARSEL, + XTRA_CONTINUE, + XTRA_ENDING +}; typedef enum state { @@ -1894,11 +1915,11 @@ typedef enum state S_FANG_FIRE1, S_FANG_FIRE2, S_FANG_FIRE3, - S_FANG_FIRE4, S_FANG_FIREREPEAT, S_FANG_LOBSHOT0, S_FANG_LOBSHOT1, S_FANG_LOBSHOT2, + S_FANG_LOBSHOT3, S_FANG_WAIT1, S_FANG_WAIT2, S_FANG_WALLHIT, @@ -1920,6 +1941,7 @@ typedef enum state S_FANG_PINCHLOBSHOT2, S_FANG_PINCHLOBSHOT3, S_FANG_PINCHLOBSHOT4, + S_FANG_PINCHLOBSHOT5, S_FANG_DIE1, S_FANG_DIE2, S_FANG_DIE3, @@ -3058,6 +3080,10 @@ typedef enum state S_LAMPPOST2, // with snow S_HANGSTAR, S_MISTLETOE, + S_SSZTREE, + S_SSZTREE_BRANCH, + S_SSZTREE2, + S_SSZTREE2_BRANCH, // Xmas GFZ bushes S_XMASBLUEBERRYBUSH, S_XMASBERRYBUSH, @@ -3065,11 +3091,9 @@ typedef enum state // FHZ S_FHZICE1, S_FHZICE2, - S_ROSY_IDLE1, - S_ROSY_IDLE2, - S_ROSY_IDLE3, - S_ROSY_IDLE4, + S_ROSY_IDLE, S_ROSY_JUMP, + S_ROSY_FALL, S_ROSY_WALK, S_ROSY_HUG, S_ROSY_PAIN, @@ -3178,6 +3202,9 @@ typedef enum state S_DBALL5, S_DBALL6, S_EGGSTATUE2, + S_GINE, + S_PPAL, + S_PPEL, // Shield Orb S_ARMA1, @@ -4062,6 +4089,7 @@ typedef enum state S_MARIOBUSH2, S_TOAD, + // Nights-specific stuff S_NIGHTSDRONE_MAN1, S_NIGHTSDRONE_MAN2, @@ -4366,6 +4394,12 @@ typedef enum state S_NAMECHECK, + // LJ Knuckles + S_OLDK_STND, + S_OLDK_DIE0, + S_OLDK_DIE1, + S_OLDK_DIE2, + S_FIRSTFREESLOT, S_LASTFREESLOT = S_FIRSTFREESLOT + NUMSTATEFREESLOTS - 1, NUMSTATES @@ -4380,11 +4414,12 @@ typedef struct INT32 var1; INT32 var2; statenum_t nextstate; + UINT16 sprite2; } state_t; extern state_t states[NUMSTATES]; -extern char sprnames[NUMSPRITES + 1][5]; -extern char spr2names[NUMPLAYERSPRITES][5]; +extern char sprnames[NUMSPRITES + 1][MAXSPRITENAME + 1]; +extern char spr2names[NUMPLAYERSPRITES][MAXSPRITENAME + 1]; extern playersprite_t spr2defaults[NUMPLAYERSPRITES]; extern state_t *astate; extern playersprite_t free_spr2; @@ -4856,6 +4891,10 @@ typedef enum mobj_type MT_LAMPPOST2, // with snow MT_HANGSTAR, MT_MISTLETOE, + MT_SSZTREE, + MT_SSZTREE_BRANCH, + MT_SSZTREE2, + MT_SSZTREE2_BRANCH, // Xmas GFZ bushes MT_XMASBLUEBERRYBUSH, MT_XMASBERRYBUSH, @@ -4935,6 +4974,9 @@ typedef enum mobj_type // Misc scenery MT_DBALL, MT_EGGSTATUE2, + MT_GINE, + MT_PPAL, + MT_PPEL, // Powerup Indicators MT_ELEMENTAL_ORB, // Elemental shield mobj @@ -5163,6 +5205,8 @@ typedef enum mobj_type MT_NAMECHECK, MT_RAY, // General purpose mobj + MT_OLDK, + MT_FIRSTFREESLOT, MT_LASTFREESLOT = MT_FIRSTFREESLOT + NUMMOBJFREESLOTS - 1, NUMMOBJTYPES diff --git a/src/lua_baselib.c b/src/lua_baselib.c index b70c63ece13cfc10daa1d621506b55a5671afa77..ecd1ee55e648019fb883917ca361cc45ba8847b2 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2023 by Sonic Team Junior. +// Copyright (C) 2012-2025 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -44,6 +44,21 @@ return luaL_error(L, "HUD rendering code should not call this function!");\ else if (hook_cmd_running)\ return luaL_error(L, "CMD building code should not call this function!"); +#define NOSPAWNNULL if (type >= NUMMOBJTYPES)\ +return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);\ +else if (type == MT_NULL)\ +{\ + if (!nospawnnull_seen) {\ + nospawnnull_seen = true;\ + CONS_Alert(CONS_WARNING,"Spawning an \"MT_NULL\" mobj is deprecated and will be removed.\nUse \"MT_RAY\" instead.\n");\ + }\ +type = MT_RAY;\ +} +static boolean nospawnnull_seen = false; // TODO: 2.3: Delete +// TODO: 2.3: Use the below NOSPAWNNULL define instead. P_SpawnMobj used to say "if MT_NULL, use MT_RAY instead", so the above define maintains Lua script compatibility until v2.3 +/*#define NOSPAWNNULL if (type <= MT_NULL || type >= NUMMOBJTYPES)\ +return luaL_error(L, "mobj type %d out of range (1 - %d)", type, NUMMOBJTYPES-1);*/ + boolean luaL_checkboolean(lua_State *L, int narg) { luaL_checktype(L, narg, LUA_TBOOLEAN); return lua_toboolean(L, narg); @@ -169,8 +184,10 @@ static const struct { {META_SKIN, "skin_t"}, {META_POWERS, "player_t.powers"}, {META_SOUNDSID, "skin_t.soundsid"}, - {META_SKINSPRITES, "skin_t.sprites"}, - {META_SKINSPRITESLIST, "skin_t.sprites[]"}, + + {META_SKINSPRITES, "skin_t.skinsprites"}, + {META_SKINSPRITESLIST, "skin_t.skinsprites[]"}, + {META_SKINSPRITESCOMPAT, "skin_t.sprites"}, // TODO: 2.3: Delete {META_VERTEX, "vertex_t"}, {META_LINE, "line_t"}, @@ -330,6 +347,18 @@ static int lib_reserveLuabanks(lua_State *L) return 1; } +static int lib_tofixed(lua_State *L) +{ + const char *arg = luaL_checkstring(L, 1); + char *end; + float f = strtof(arg, &end); + if (*end != '\0') + lua_pushnil(L); + else + lua_pushnumber(L, FLOAT_TO_FIXED(f)); + return 1; +} + // M_MENU ////////////// @@ -625,9 +654,8 @@ static int lib_pSpawnMobj(lua_State *L) mobjtype_t type = luaL_checkinteger(L, 4); NOHUD INLEVEL - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); - LUA_PushUserdata(L, P_SpawnMobj(x, y, z, type), META_MOBJ); + NOSPAWNNULL + LUA_PushUserdata(L, P_SpawnMobj(x, y, z, type, NULL), META_MOBJ); return 1; } @@ -640,10 +668,9 @@ static int lib_pSpawnMobjFromMobj(lua_State *L) mobjtype_t type = luaL_checkinteger(L, 5); NOHUD INLEVEL + NOSPAWNNULL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SpawnMobjFromMobj(actor, x, y, z, type), META_MOBJ); return 1; } @@ -661,17 +688,15 @@ static int lib_pRemoveMobj(lua_State *L) return 0; } -// P_IsValidSprite2 technically doesn't exist, and probably never should... but too much would need to be exposed to allow this to be checked by other methods. - static int lib_pIsValidSprite2(lua_State *L) { mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - UINT8 spr2 = (UINT8)luaL_checkinteger(L, 2); + UINT16 spr2 = (UINT16)luaL_checkinteger(L, 2); //HUDSAFE INLEVEL if (!mobj) return LUA_ErrInvalid(L, "mobj_t"); - lua_pushboolean(L, (mobj->skin && (((skin_t *)mobj->skin)->sprites[spr2].numframes))); + lua_pushboolean(L, mobj->skin && P_IsValidSprite2(mobj->skin, spr2)); return 1; } @@ -708,10 +733,9 @@ static int lib_pSpawnMissile(lua_State *L) mobjtype_t type = luaL_checkinteger(L, 3); NOHUD INLEVEL + NOSPAWNNULL if (!source || !dest) return LUA_ErrInvalid(L, "mobj_t"); - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SpawnMissile(source, dest, type), META_MOBJ); return 1; } @@ -726,10 +750,9 @@ static int lib_pSpawnXYZMissile(lua_State *L) fixed_t z = luaL_checkfixed(L, 6); NOHUD INLEVEL + NOSPAWNNULL if (!source || !dest) return LUA_ErrInvalid(L, "mobj_t"); - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SpawnXYZMissile(source, dest, type, x, y, z), META_MOBJ); return 1; } @@ -746,10 +769,9 @@ static int lib_pSpawnPointMissile(lua_State *L) fixed_t z = luaL_checkfixed(L, 8); NOHUD INLEVEL + NOSPAWNNULL if (!source) return LUA_ErrInvalid(L, "mobj_t"); - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SpawnPointMissile(source, xa, ya, za, type, x, y, z), META_MOBJ); return 1; } @@ -764,10 +786,9 @@ static int lib_pSpawnAlteredDirectionMissile(lua_State *L) INT32 shiftingAngle = (INT32)luaL_checkinteger(L, 5); NOHUD INLEVEL + NOSPAWNNULL if (!source) return LUA_ErrInvalid(L, "mobj_t"); - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SpawnAlteredDirectionMissile(source, type, x, y, z, shiftingAngle), META_MOBJ); return 1; } @@ -795,10 +816,9 @@ static int lib_pSPMAngle(lua_State *L) UINT32 flags2 = (UINT32)luaL_optinteger(L, 5, 0); NOHUD INLEVEL + NOSPAWNNULL if (!source) return LUA_ErrInvalid(L, "mobj_t"); - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SPMAngle(source, type, angle, allowaim, flags2), META_MOBJ); return 1; } @@ -810,10 +830,9 @@ static int lib_pSpawnPlayerMissile(lua_State *L) UINT32 flags2 = (UINT32)luaL_optinteger(L, 3, 0); NOHUD INLEVEL + NOSPAWNNULL if (!source) return LUA_ErrInvalid(L, "mobj_t"); - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SpawnPlayerMissile(source, type, flags2), META_MOBJ); return 1; } @@ -844,8 +863,7 @@ static int lib_pWeaponOrPanel(lua_State *L) { mobjtype_t type = luaL_checkinteger(L, 1); //HUDSAFE - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); + NOSPAWNNULL lua_pushboolean(L, P_WeaponOrPanel(type)); return 1; } @@ -888,8 +906,7 @@ static int lib_pSpawnParaloop(lua_State *L) boolean spawncenter = lua_optboolean(L, 9); NOHUD INLEVEL - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); + NOSPAWNNULL if (nstate >= NUMSTATES) return luaL_error(L, "state %d out of range (0 - %d)", nstate, NUMSTATES-1); P_SpawnParaloop(x, y, z, radius, number, type, nstate, rotangle, spawncenter); @@ -924,13 +941,14 @@ static int lib_pSetScale(lua_State *L) { mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); fixed_t newscale = luaL_checkfixed(L, 2); + boolean instant = lua_optboolean(L, 3); NOHUD INLEVEL if (!mobj) return LUA_ErrInvalid(L, "mobj_t"); if (newscale < FRACUNIT/100) newscale = FRACUNIT/100; - P_SetScale(mobj, newscale); + P_SetScale(mobj, newscale, instant); return 0; } @@ -1584,11 +1602,12 @@ static int lib_pDoPlayerFinish(lua_State *L) static int lib_pDoPlayerExit(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + boolean finishedflag = lua_opttrueboolean(L, 2); NOHUD INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); - P_DoPlayerExit(player); + P_DoPlayerExit(player, finishedflag); return 0; } @@ -1711,12 +1730,11 @@ static int lib_pResetCamera(lua_State *L) static int lib_pSuperReady(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - boolean transform = (boolean)lua_opttrueboolean(L, 2); //HUDSAFE INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); - lua_pushboolean(L, P_SuperReady(player, transform)); + lua_pushboolean(L, P_SuperReady(player)); return 1; } @@ -1761,10 +1779,9 @@ static int lib_pSpawnSpinMobj(lua_State *L) mobjtype_t type = luaL_checkinteger(L, 2); NOHUD INLEVEL + NOSPAWNNULL if (!player) return LUA_ErrInvalid(L, "player_t"); - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); P_SpawnSpinMobj(player, type); return 0; } @@ -1970,7 +1987,7 @@ static int lib_pLineIsBlocking(lua_State *L) return LUA_ErrInvalid(L, "mobj_t"); if (!line) return LUA_ErrInvalid(L, "line_t"); - + // P_LineOpening in P_LineIsBlocking sets these variables. // We want to keep their old values after so that whatever // map collision code uses them doesn't get messed up. @@ -1983,9 +2000,9 @@ static int lib_pLineIsBlocking(lua_State *L) pslope_t *oldopenbottomslope = openbottomslope; ffloor_t *oldopenfloorrover = openfloorrover; ffloor_t *oldopenceilingrover = openceilingrover; - + lua_pushboolean(L, P_LineIsBlocking(mo, line)); - + opentop = oldopentop; openbottom = oldopenbottom; openrange = oldopenrange; @@ -1995,7 +2012,7 @@ static int lib_pLineIsBlocking(lua_State *L) openbottomslope = oldopenbottomslope; openfloorrover = oldopenfloorrover; openceilingrover = oldopenceilingrover; - + return 1; } @@ -2496,6 +2513,17 @@ static int lib_pDoSuperTransformation(lua_State *L) return 0; } +static int lib_pDoSuperDetransformation(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + NOHUD + INLEVEL + if (!player) + return LUA_ErrInvalid(L, "player_t"); + P_DoSuperDetransformation(player); + return 0; +} + static int lib_pExplodeMissile(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); @@ -2710,12 +2738,11 @@ static int lib_pFadeLight(lua_State *L) static int lib_pIsFlagAtBase(lua_State *L) { - mobjtype_t flag = luaL_checkinteger(L, 1); + mobjtype_t type = luaL_checkinteger(L, 1); //HUDSAFE INLEVEL - if (flag >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", flag, NUMMOBJTYPES-1); - lua_pushboolean(L, P_IsFlagAtBase(flag)); + NOSPAWNNULL + lua_pushboolean(L, P_IsFlagAtBase(type)); return 1; } @@ -3016,6 +3043,9 @@ static int lib_rFrame2Char(lua_State *L) //HUDSAFE c[0] = R_Frame2Char(ch); + if (c[0] == '\xFF') + return luaL_error(L, "frame %u cannot be represented by a character", ch); + c[1] = 0; lua_pushstring(L, c); @@ -3023,6 +3053,9 @@ static int lib_rFrame2Char(lua_State *L) return 2; } +// R_SKINS +//////////// + // R_SetPlayerSkin technically doesn't exist either, although it's basically just SetPlayerSkin and SetPlayerSkinByNum handled in one place for convenience static int lib_rSetPlayerSkin(lua_State *L) { @@ -3085,6 +3118,47 @@ static int lib_rSkinUsable(lua_State *L) return 1; } +static int lib_pGetStateSprite2(lua_State *L) +{ + int statenum = luaL_checkinteger(L, 1); + if (statenum < 0 || statenum >= NUMSTATES) + return luaL_error(L, "state %d out of range (0 - %d)", statenum, NUMSTATES-1); + + lua_pushinteger(L, P_GetStateSprite2(&states[statenum])); + return 1; +} + +static int lib_pGetSprite2StateFrame(lua_State *L) +{ + int statenum = luaL_checkinteger(L, 1); + if (statenum < 0 || statenum >= NUMSTATES) + return luaL_error(L, "state %d out of range (0 - %d)", statenum, NUMSTATES-1); + + lua_pushinteger(L, P_GetSprite2StateFrame(&states[statenum])); + return 1; +} + +static int lib_pIsStateSprite2Super(lua_State *L) +{ + int statenum = luaL_checkinteger(L, 1); + if (statenum < 0 || statenum >= NUMSTATES) + return luaL_error(L, "state %d out of range (0 - %d)", statenum, NUMSTATES-1); + + lua_pushboolean(L, P_IsStateSprite2Super(&states[statenum])); + return 1; +} + +// Not a real function. Who cares? I know I don't. +static int lib_pGetSuperSprite2(lua_State *L) +{ + int animID = luaL_checkinteger(L, 1) & SPR2F_MASK; + if (animID < 0 || animID >= NUMPLAYERSPRITES) + return luaL_error(L, "sprite2 %d out of range (0 - %d)", animID, NUMPLAYERSPRITES-1); + + lua_pushinteger(L, animID | SPR2F_SUPER); + return 1; +} + // R_DATA //////////// @@ -3106,17 +3180,25 @@ static int lib_rTextureNumForName(lua_State *L) static int lib_rCheckTextureNameForNum(lua_State *L) { + char s[9]; INT32 num = (INT32)luaL_checkinteger(L, 1); //HUDSAFE - lua_pushstring(L, R_CheckTextureNameForNum(num)); + + M_Memcpy(s, R_CheckTextureNameForNum(num), 8); + s[8] = '\0'; + lua_pushstring(L, s); return 1; } static int lib_rTextureNameForNum(lua_State *L) { + char s[9]; INT32 num = (INT32)luaL_checkinteger(L, 1); //HUDSAFE - lua_pushstring(L, R_TextureNameForNum(num)); + + M_Memcpy(s, R_TextureNameForNum(num), 8); + s[8] = '\0'; + lua_pushstring(L, s); return 1; } @@ -3803,7 +3885,7 @@ static int lib_gAddPlayer(lua_State *L) player_t *newplayer; SINT8 skinnum = 0, bot; - for (i = 0; i < MAXPLAYERS; i++) + for (i = 1; i < MAXPLAYERS; i++) { if (!playeringame[i]) break; @@ -4272,6 +4354,7 @@ static luaL_Reg lib[] = { {"userdataMetatable", lib_userdataMetatable}, {"IsPlayerAdmin", lib_isPlayerAdmin}, {"reserveLuabanks", lib_reserveLuabanks}, + {"tofixed", lib_tofixed}, // m_menu {"M_MoveColorAfter",lib_pMoveColorAfter}, @@ -4449,6 +4532,7 @@ static luaL_Reg lib[] = { {"P_VectorInstaThrust",lib_pVectorInstaThrust}, {"P_SetMobjStateNF",lib_pSetMobjStateNF}, {"P_DoSuperTransformation",lib_pDoSuperTransformation}, + {"P_DoSuperDetransformation",lib_pDoSuperDetransformation}, {"P_ExplodeMissile",lib_pExplodeMissile}, {"P_MobjTouchingSectorSpecial",lib_pMobjTouchingSectorSpecial}, {"P_ThingOnSpecial3DFloor",lib_pThingOnSpecial3DFloor}, @@ -4489,7 +4573,13 @@ static luaL_Reg lib[] = { {"R_Char2Frame",lib_rChar2Frame}, {"R_Frame2Char",lib_rFrame2Char}, {"R_SetPlayerSkin",lib_rSetPlayerSkin}, + + // r_skins {"R_SkinUsable",lib_rSkinUsable}, + {"P_GetStateSprite2",lib_pGetStateSprite2}, + {"P_GetSprite2StateFrame",lib_pGetSprite2StateFrame}, + {"P_IsStateSprite2Super",lib_pIsStateSprite2Super}, + {"P_GetSuperSprite2",lib_pGetSuperSprite2}, // r_data {"R_CheckTextureNumForName",lib_rCheckTextureNumForName}, diff --git a/src/lua_blockmaplib.c b/src/lua_blockmaplib.c index 6b4b6229f68ffc869e1f6eccdd6999018d150ae0..f570c229b97b138d6d10e714c4c2cdd8175b1596 100644 --- a/src/lua_blockmaplib.c +++ b/src/lua_blockmaplib.c @@ -254,11 +254,10 @@ static int lib_searchBlockmap(lua_State *L) } else // mobj and function only - search around mobj's radius by default { - fixed_t radius = mobj->radius + MAXRADIUS; - x1 = mobj->x - radius; - x2 = mobj->x + radius; - y1 = mobj->y - radius; - y2 = mobj->y + radius; + x1 = mobj->x - mobj->radius; + x2 = mobj->x + mobj->radius; + y1 = mobj->y - mobj->radius; + y2 = mobj->y + mobj->radius; } lua_settop(L, 2); // pop everything except function, mobj @@ -312,17 +311,12 @@ static int lib_searchBlockmap(lua_State *L) continue; // our thing just found itself, so move on funcret = lib_searchBlockmap_Objects(L, mobj, itmobj); - if (funcret == 2) { - lua_pushboolean(L, false); - return 1; - } - else if (funcret == 1) - retval = false; - - if (P_MobjWasRemoved(mobj)) { + if (funcret == 2 || P_MobjWasRemoved(mobj)) { retval = false; break; } + else if (funcret == 1) + retval = false; } } while (itmobj != NULL); diff --git a/src/lua_colorlib.c b/src/lua_colorlib.c index 3fab589b23ab083df72ae8b7e9d42aa3ee29673c..2743635edfefe88348a93dc45aa26f77d4702067 100644 --- a/src/lua_colorlib.c +++ b/src/lua_colorlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2021-2022 by "Lactozilla". -// Copyright (C) 2014-2023 by Sonic Team Junior. +// Copyright (C) 2021-2024 by Lactozilla. +// Copyright (C) 2014-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -593,7 +593,7 @@ static int extracolormap_set(lua_State *L) || exc->fadergba != old_fade_rgba || exc->fadestart != old_fade_start || exc->fadeend != old_fade_end) - R_GenerateLightTable(exc, true); + R_UpdateLightTable(exc, true); return 0; } diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index aaa676526d1eac6adbad4ac5d8ba34e31388d2cd..b9b24307b0127b41fe0050106c4447ac5d3f7d55 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -31,11 +31,27 @@ return luaL_error(L, "HUD rendering code should not call this function!"); static consvar_t *this_cvar; +static void clear_lua_stack(void) +{ + if (gL) // check if Lua is actually turned on first, you dummmy -- Monster Iestyn 04/07/18 + lua_settop(gL, 0); // clear stack +} + void Got_Luacmd(UINT8 **cp, INT32 playernum) { UINT8 i, argc, flags; + const char *argv[256]; char buf[256]; + argc = READUINT8(*cp); + argv[0] = (const char*)*cp; + SKIPSTRINGN(*cp, 255); + for (i = 1; i < argc; i++) + { + argv[i] = (const char*)*cp; + SKIPSTRINGN(*cp, 255); + } + // don't use I_Assert here, goto the deny code below // to clean up and kick people who try nefarious exploits // like sending random junk lua commands to crash the server @@ -48,8 +64,7 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum) lua_getfield(gL, LUA_REGISTRYINDEX, "COM_Command"); // push COM_Command if (!lua_istable(gL, -1)) goto deny; - argc = READUINT8(*cp); - READSTRINGN(*cp, buf, 255); + strlcpy(buf, argv[0], 255); strlwr(buf); // must lowercase buffer lua_getfield(gL, -1, buf); // push command info table if (!lua_istable(gL, -1)) goto deny; @@ -75,10 +90,17 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum) lua_remove(gL, -2); // pop command info table + if (!lua_checkstack(gL, argc)) // player + command arguments + { + clear_lua_stack(); + CONS_Alert(CONS_WARNING, "lua command stack overflow from %s (%d, need %d more)\n", player_names[playernum], lua_gettop(gL), argc); + return; + } + LUA_PushUserdata(gL, &players[playernum], META_PLAYER); for (i = 1; i < argc; i++) { - READSTRINGN(*cp, buf, 255); + strlcpy(buf, argv[i], 255); lua_pushstring(gL, buf); } LUA_Call(gL, (int)argc, 0, 1); // argc is 1-based, so this will cover the player we passed too. @@ -86,8 +108,7 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum) deny: //must be hacked/buggy client - if (gL) // check if Lua is actually turned on first, you dummmy -- Monster Iestyn 04/07/18 - lua_settop(gL, 0); // clear stack + clear_lua_stack(); CONS_Alert(CONS_WARNING, M_GetText("Illegal lua command received from %s\n"), player_names[playernum]); if (server) @@ -173,6 +194,11 @@ void COM_Lua_f(void) I_Assert(lua_isfunction(gL, -1)); lua_remove(gL, -2); // pop command info table + if (!lua_checkstack(gL, COM_Argc() + 1)) + { + CONS_Alert(CONS_WARNING, "lua command stack overflow (%d, need %s more)\n", lua_gettop(gL), sizeu1(COM_Argc() + 1)); + return; + } LUA_PushUserdata(gL, &players[playernum], META_PLAYER); for (i = 1; i < COM_Argc(); i++) lua_pushstring(gL, COM_Argv(i)); diff --git a/src/lua_hook.h b/src/lua_hook.h index 026e5c4aaf97c54326a22d5de56f4e44cbddd09f..ce79cd1cb70a2e81f9d531ed15094e7cf42b1e75 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2023 by Sonic Team Junior. +// Copyright (C) 2012-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -72,6 +72,7 @@ automatically. X (MusicChange),\ X (PlayerHeight),/* override player height */\ X (PlayerCanEnterSpinGaps),\ + X (AddonLoaded),\ X (KeyDown),\ X (KeyUp),\ @@ -86,6 +87,8 @@ automatically. X (title),/* titlescreen */\ X (titlecard),\ X (intermission),\ + X (continue),\ + X (playersetup),\ /* I chose to access the hook enums through a macro as well. This could provide @@ -117,6 +120,13 @@ extern boolean hook_cmd_running; void LUA_HookVoid(int hook); void LUA_HookHUD(int hook, huddrawlist_h drawlist); +int LUA_HookCharacterHUD +( + int hook, huddrawlist_h drawlist, player_t *player, + fixed_t x, fixed_t y, fixed_t scale, + INT32 skinIndex, UINT8 sprite2, UINT8 frame, UINT8 rotation, skincolornum_t color, + INT32 ticker, boolean mode +); int LUA_HookMobj(mobj_t *, int hook); int LUA_Hook2Mobj(mobj_t *, mobj_t *, int hook); diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 529c189ff7883bbd377327ad5b44d2ae5af4e196..1bf3caf65fa502f70b447374b6b21600d6261c87 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2023 by Sonic Team Junior. +// Copyright (C) 2012-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -375,6 +375,17 @@ static boolean prepare_string_hook return false; } +static boolean prepare_hud_hook +( + Hook_State * hook, + int default_status, + int hook_type +){ + return init_hook_type(hook, default_status, + hook_type, 0, NULL, + hudHookIds[hook_type].numHooks); +} + static void init_hook_call ( Hook_State * hook, @@ -487,7 +498,40 @@ static int call_string_hooks(Hook_State *hook) static int call_mobj_type_hooks(Hook_State *hook, mobjtype_t mobj_type) { - return call_mapped(hook, &mobjHookIds[mobj_type][hook->hook_type]); + int numCalls = call_mapped(hook, &mobjHookIds[mobj_type][hook->hook_type]); + + if (numCalls > 0 && mobj_type == MT_NULL && ( + hook->hook_type == MOBJ_HOOK(MobjThinker ) + || hook->hook_type == MOBJ_HOOK(MobjCollide ) + || hook->hook_type == MOBJ_HOOK(MobjLineCollide) + || hook->hook_type == MOBJ_HOOK(MobjMoveCollide) + || hook->hook_type == MOBJ_HOOK(MobjFuse ) + || hook->hook_type == MOBJ_HOOK(MobjThinker ) + || hook->hook_type == MOBJ_HOOK(BossThinker ) + || hook->hook_type == MOBJ_HOOK(MobjMoveBlocked) + || hook->hook_type == MOBJ_HOOK(FollowMobj ) + )) + LUA_UsageWarning(L, va( + "%s hooks not attached to a specific mobj type are deprecated and will be removed.", + mobjHookNames[hook->hook_type]) + ); + + return numCalls; +} + +static void call_hud_hooks +( + Hook_State * hook, + int results, + Hook_Callback results_handler +){ + hud_running = true; // local hook + init_hook_call(hook, results, results_handler); + call_mapped(hook, &hudHookIds[hook->hook_type]); + hud_running = false; + + lua_pushnil(gL); + lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST"); } static int call_hooks @@ -648,23 +692,39 @@ int LUA_HookKey(event_t *event, int hook_type) void LUA_HookHUD(int hook_type, huddrawlist_h list) { - const hook_t * map = &hudHookIds[hook_type]; Hook_State hook; - if (map->numHooks > 0) + if (prepare_hud_hook(&hook, 0, hook_type)) { - start_hook_stack(); - begin_hook_values(&hook); - LUA_SetHudHook(hook_type, list); + call_hud_hooks(&hook, 0, res_none); + } +} - hud_running = true; // local hook - init_hook_call(&hook, 0, res_none); - call_mapped(&hook, map); - hud_running = false; - - lua_pushnil(gL); - lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST"); +int LUA_HookCharacterHUD +( + int hook_type, huddrawlist_h list, player_t *player, + fixed_t x, fixed_t y, fixed_t scale, + INT32 skinIndex, UINT8 sprite2, UINT8 frame, UINT8 rotation, skincolornum_t color, + INT32 ticker, boolean mode +){ + Hook_State hook; + if (prepare_hud_hook(&hook, false, hook_type)) + { + LUA_SetHudHook(hook_type, list); + LUA_PushUserdata(gL, player, META_PLAYER); + lua_pushfixed(gL, x); + lua_pushfixed(gL, y); + lua_pushfixed(gL, scale); + lua_pushstring(gL, skins[skinIndex]->name); + lua_pushinteger(gL, sprite2); + lua_pushinteger(gL, frame); + lua_pushinteger(gL, rotation); + lua_pushinteger(gL, color); + lua_pushinteger(gL, ticker); + lua_pushboolean(gL, mode); + call_hud_hooks(&hook, 1, res_true); } + return hook.status; } /* ========================================================================= @@ -709,7 +769,7 @@ static void hook_think_frame(int type) PS_SetThinkFrameHookInfo(hook_index, time_taken, ar.short_src); else if (type == 6) PS_SetPostThinkFrameHookInfo(hook_index, time_taken, ar.short_src); - + hook_index++; } } diff --git a/src/lua_hud.h b/src/lua_hud.h index ba102f2f4a13d6c1606e71b08b0198cd742d212b..ae938e28a9624ab8ced72337c83228daefcdf12f 100644 --- a/src/lua_hud.h +++ b/src/lua_hud.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2014-2016 by John "JTE" Muniz. -// Copyright (C) 2014-2023 by Sonic Team Junior. +// Copyright (C) 2014-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -19,11 +19,13 @@ enum hud { hud_stagetitle = 0, hud_textspectator, hud_crosshair, + hud_powerups, // Singleplayer / Co-op hud_score, hud_time, hud_rings, hud_lives, + hud_input, // Match / CTF / Tag / Ringslinger hud_weaponrings, hud_powerstones, diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 52a875e50c0c550f2c10dbb1acd56647955baf01..c8327658a64cf8b87f7ee281b266e85ef65c4e3e 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2014-2016 by John "JTE" Muniz. -// Copyright (C) 2014-2023 by Sonic Team Junior. +// Copyright (C) 2014-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -41,11 +41,13 @@ static const char *const hud_disable_options[] = { "stagetitle", "textspectator", "crosshair", + "powerups", "score", "time", "rings", "lives", + "input", "weaponrings", "powerstones", @@ -69,6 +71,10 @@ static const char *const hud_disable_options[] = { "intermissionemeralds", NULL}; +// you know, let's actually make sure that the table is synced. +// because fuck knows how many times this has happened at this point. :v +I_StaticAssert(sizeof(hud_disable_options) / sizeof(*hud_disable_options) == hud_MAX+1); + enum hudinfo { hudinfo_x = 0, hudinfo_y, @@ -486,9 +492,7 @@ static int libd_getSpritePatch(lua_State *L) else if (lua_isstring(L, 1)) // sprite prefix name given, e.g. "THOK" { const char *name = lua_tostring(L, 1); - for (i = 0; i < NUMSPRITES; i++) - if (fastcmp(name, sprnames[i])) - break; + i = R_GetSpriteNumByName(name); if (i >= NUMSPRITES) return 0; } @@ -550,7 +554,7 @@ static int libd_getSprite2Patch(lua_State *L) UINT8 angle = 0; spritedef_t *sprdef; spriteframe_t *sprframe; - boolean super = false; // add FF_SPR2SUPER to sprite2 if true + boolean super = false; // add SPR2F_SUPER to sprite2 if true HUDONLY // get skin first! @@ -577,11 +581,12 @@ static int libd_getSprite2Patch(lua_State *L) if (lua_isnumber(L, 1)) // sprite number given, e.g. SPR2_STND { j = lua_tonumber(L, 1); - if (j & FF_SPR2SUPER) // e.g. SPR2_STND|FF_SPR2SUPER + if (j & SPR2F_SUPER) // e.g. SPR2_STND|SPR2F_SUPER { super = true; - j &= ~FF_SPR2SUPER; // remove flag so the next check doesn't fail + j &= ~SPR2F_SUPER; // remove flag so the next check doesn't fail } + if (j >= free_spr2) return 0; } @@ -600,17 +605,19 @@ static int libd_getSprite2Patch(lua_State *L) if (lua_isboolean(L, 2)) // optional boolean for superness { - super = lua_toboolean(L, 2); // note: this can override FF_SPR2SUPER from sprite number + super = lua_toboolean(L, 2); // note: this can override SPR2F_SUPER from sprite number lua_remove(L, 2); // remove } // if it's not boolean then just assume it's the frame number if (super) - j |= FF_SPR2SUPER; + j |= SPR2F_SUPER; - j = P_GetSkinSprite2(skins[i], j, NULL); // feed skin and current sprite2 through to change sprite2 used if necessary + // If there is no "super" variation of this sprite, try with the normal one. + if (!P_IsValidSprite2(skins[i], j)) + j &= ~SPR2F_SUPER; - sprdef = &skins[i]->sprites[j]; + sprdef = P_GetSkinSpritedef(skins[i], j); // set frame number frame = luaL_optinteger(L, 2, 0); @@ -638,7 +645,7 @@ static int libd_getSprite2Patch(lua_State *L) INT32 rot = R_GetRollAngle(rollangle); if (rot) { - patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), &skins[i]->sprinfo[j], rot); + patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), P_GetSkinSpriteInfo(skins[i], j), rot); LUA_PushUserdata(L, rotsprite, META_PATCH); lua_pushboolean(L, false); lua_pushboolean(L, true); diff --git a/src/lua_hudlib_drawlist.c b/src/lua_hudlib_drawlist.c index c518ba52540ff874480d7cda2c8314a31987e993..358d615cfde8d1e26a0098737f8aaa5a39359b11 100644 --- a/src/lua_hudlib_drawlist.c +++ b/src/lua_hudlib_drawlist.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2014-2016 by John "JTE" Muniz. -// Copyright (C) 2014-2023 by Sonic Team Junior. +// Copyright (C) 2014-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -180,7 +180,8 @@ static const char *CopyString(huddrawlist_h list, const char* str) const char *old_offset = list->strbuf; size_t i; if (list->strbuf_capacity == 0) list->strbuf_capacity = 256; - else list->strbuf_capacity *= 2; + while (list->strbuf_capacity <= list->strbuf_len + lenstr + 1) + list->strbuf_capacity *= 2; list->strbuf = (char*) Z_Realloc(list->strbuf, sizeof(char) * list->strbuf_capacity, PU_STATIC, NULL); // align the string pointers to make sure old pointers don't point towards invalid addresses diff --git a/src/lua_infolib.c b/src/lua_infolib.c index b2730c5931f0c00db2eca2848827526661631084..a65ee23ebc913a62711e9960990c5935662b8dfd 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2023 by Sonic Team Junior. +// Copyright (C) 2012-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -88,12 +88,12 @@ static int lib_getSprname(lua_State *L) else if (lua_isstring(L, 1)) { const char *name = lua_tostring(L, 1); - for (i = 0; i < NUMSPRITES; i++) - if (fastcmp(name, sprnames[i])) - { - lua_pushinteger(L, i); - return 1; - } + i = R_GetSpriteNumByName(name); + if (i != NUMSPRITES) + { + lua_pushinteger(L, i); + return 1; + } } return 0; } @@ -165,7 +165,7 @@ static int lib_getSpr2default(lua_State *L) static int lib_setSpr2default(lua_State *L) { playersprite_t i; - UINT8 j = 0; + UINT16 j = 0; if (hud_running) return luaL_error(L, "Do not alter spr2defaults[] in HUD rendering code!"); @@ -242,25 +242,13 @@ static int lib_getSpriteInfo(lua_State *L) UINT32 i = NUMSPRITES; lua_remove(L, 1); - if (lua_isstring(L, 1)) + if (lua_type(L, 1) == LUA_TSTRING) { const char *name = lua_tostring(L, 1); - INT32 spr; - for (spr = 0; spr < NUMSPRITES; spr++) - { - if (fastcmp(name, sprnames[spr])) - { - i = spr; - break; - } - } - if (i == NUMSPRITES) - { - char *check; - i = strtol(name, &check, 10); - if (check == name || *check != '\0') - return luaL_error(L, "unknown sprite name %s", name); - } + INT32 spr = R_GetSpriteNumByName(name); + if (spr == NUMSPRITES) + return luaL_error(L, "unknown sprite name %s", name); + i = spr; } else i = luaL_checkinteger(L, 1); @@ -359,8 +347,8 @@ static int PopPivotTable(spriteinfo_t *info, lua_State *L, int stk) default: TYPEERROR("pivot frame", LUA_TNUMBER, lua_type(L, stk+1)); } - if ((idx < 0) || (idx >= 64)) - return luaL_error(L, "pivot frame %d out of range (0 - %d)", idx, 63); + if ((idx < 0) || (idx >= MAXFRAMENUM)) + return luaL_error(L, "pivot frame %d out of range (0 - %d)", idx, MAXFRAMENUM - 1); // the values in pivot[] are also tables if (PopPivotSubTable(info->pivot, L, stk+2, idx)) info->available = true; @@ -483,7 +471,7 @@ static int spriteinfo_set(lua_State *L) } } else - return luaL_error(L, va("Field %s does not exist in spriteinfo_t", field)); + return luaL_error(L, "Field %s does not exist in spriteinfo_t", field); return 0; } @@ -555,7 +543,7 @@ static int pivotlist_set(lua_State *L) static int pivotlist_num(lua_State *L) { - lua_pushinteger(L, 64); + lua_pushinteger(L, MAXFRAMENUM); return 1; } @@ -577,7 +565,7 @@ static int framepivot_get(lua_State *L) lua_pushinteger(L, 0); } else - return luaL_error(L, va("Field %s does not exist in spriteframepivot_t", field)); + return luaL_error(L, "Field %s does not exist in spriteframepivot_t", field); return 1; } @@ -604,7 +592,7 @@ static int framepivot_set(lua_State *L) else if (fastcmp("rotaxis", field)) LUA_UsageWarning(L, "\"rotaxis\" is deprecated and will be removed.") else - return luaL_error(L, va("Field %s does not exist in spriteframepivot_t", field)); + return luaL_error(L, "Field %s does not exist in spriteframepivot_t", field); return 0; } @@ -1663,7 +1651,7 @@ static void setRamp(lua_State *L, skincolor_t* c) { lua_pushnil(L); for (i=0; i<COLORRAMPSIZE; i++) { if (lua_objlen(L,-2)!=COLORRAMPSIZE) { - luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' must be %d entries long; got %d.", COLORRAMPSIZE, lua_objlen(L,-2)); + luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' must be %d entries long; got %d.", COLORRAMPSIZE, luaL_getn(L,-2)); break; } if (lua_next(L, -2) != 0) { @@ -1747,7 +1735,7 @@ static int lib_setSkinColor(lua_State *L) else if (i == 6 || (str && fastcmp(str,"accessible"))) { boolean v = lua_toboolean(L, 3); if (cnum < FIRSTSUPERCOLOR && v != skincolors[cnum].accessible) - CONS_Alert(CONS_WARNING, "skincolors[] index %d is a standard color; accessibility changes are prohibited.", cnum); + CONS_Alert(CONS_WARNING, "skincolors[] index %d is a standard color; accessibility changes are prohibited.\n", cnum); else info->accessible = v; } @@ -1842,7 +1830,7 @@ static int skincolor_set(lua_State *L) else if (fastcmp(field,"accessible")) { boolean v = lua_toboolean(L, 3); if (cnum < FIRSTSUPERCOLOR && v != skincolors[cnum].accessible) - CONS_Alert(CONS_WARNING, "skincolors[] index %d is a standard color; accessibility changes are prohibited.", cnum); + CONS_Alert(CONS_WARNING, "skincolors[] index %d is a standard color; accessibility changes are prohibited.\n", cnum); else info->accessible = v; } else diff --git a/src/lua_libs.h b/src/lua_libs.h index a90d8ac7fb800c426e7bef94538803366a835b8b..e1585f488a8a6205b1ee967dcfeffac125680fee 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2023 by Sonic Team Junior. +// Copyright (C) 2012-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -42,8 +42,9 @@ extern boolean ignoregameinputs; #define META_SKIN "SKIN_T*" #define META_POWERS "PLAYER_T*POWERS" #define META_SOUNDSID "SKIN_T*SOUNDSID" -#define META_SKINSPRITES "SKIN_T*SPRITES" -#define META_SKINSPRITESLIST "SKIN_T*SPRITES[]" +#define META_SKINSPRITES "SKIN_T*SKINSPRITES" +#define META_SKINSPRITESLIST "SKIN_T*SKINSPRITES[]" +#define META_SKINSPRITESCOMPAT "SKIN_T*SPRITES" // TODO: 2.3: Delete #define META_VERTEX "VERTEX_T*" #define META_LINE "LINE_T*" diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 6b489f22b1939941c0ebf83a5a3ae0b7e215de5a..c946b10ce220fd28e2415d46f68233fad4bc7f0b 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2023 by Sonic Team Junior. +// Copyright (C) 2012-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -213,6 +213,14 @@ enum side_e { side_sector, side_special, side_repeatcnt, + side_light, + side_light_top, + side_light_mid, + side_light_bottom, + side_lightabsolute, + side_lightabsolute_top, + side_lightabsolute_mid, + side_lightabsolute_bottom, side_text }; @@ -241,6 +249,14 @@ static const char *const side_opt[] = { "sector", "special", "repeatcnt", + "light", + "light_top", + "light_mid", + "light_bottom", + "lightabsolute", + "lightabsolute_top", + "lightabsolute_mid", + "lightabsolute_bottom", "text", NULL}; @@ -1311,6 +1327,30 @@ static int side_get(lua_State *L) case side_repeatcnt: lua_pushinteger(L, side->repeatcnt); return 1; + case side_light: + lua_pushinteger(L, side->light); + return 1; + case side_light_top: + lua_pushinteger(L, side->light_top); + return 1; + case side_light_mid: + lua_pushinteger(L, side->light_mid); + return 1; + case side_light_bottom: + lua_pushinteger(L, side->light_bottom); + return 1; + case side_lightabsolute: + lua_pushboolean(L, side->lightabsolute); + return 1; + case side_lightabsolute_top: + lua_pushboolean(L, side->lightabsolute_top); + return 1; + case side_lightabsolute_mid: + lua_pushboolean(L, side->lightabsolute_mid); + return 1; + case side_lightabsolute_bottom: + lua_pushboolean(L, side->lightabsolute_bottom); + return 1; // TODO: 2.3: Delete case side_text: { @@ -1413,6 +1453,30 @@ static int side_set(lua_State *L) case side_repeatcnt: side->repeatcnt = luaL_checkinteger(L, 3); break; + case side_light: + side->light = luaL_checkinteger(L, 3); + break; + case side_light_top: + side->light_top = luaL_checkinteger(L, 3); + break; + case side_light_mid: + side->light_mid = luaL_checkinteger(L, 3); + break; + case side_light_bottom: + side->light_bottom = luaL_checkinteger(L, 3); + break; + case side_lightabsolute: + side->lightabsolute = luaL_checkboolean(L, 3); + break; + case side_lightabsolute_top: + side->lightabsolute_top = luaL_checkboolean(L, 3); + break; + case side_lightabsolute_mid: + side->lightabsolute_mid = luaL_checkboolean(L, 3); + break; + case side_lightabsolute_bottom: + side->lightabsolute_bottom = luaL_checkboolean(L, 3); + break; } return 0; } diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 5a3f8ad114b9f1269e3a49b76cb4aa9dd76417ad..6bdebf774df50d0527e3f5713043e008f5c3e33e 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2023 by Sonic Team Junior. +// Copyright (C) 2012-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -69,6 +69,7 @@ enum mobj_e { mobj_color, mobj_translation, mobj_blendmode, + mobj_alpha, mobj_bnext, mobj_bprev, mobj_hnext, @@ -150,6 +151,7 @@ static const char *const mobj_opt[] = { "color", "translation", "blendmode", + "alpha", "bnext", "bprev", "hnext", @@ -196,12 +198,12 @@ static int mobj_get(lua_State *L) enum mobj_e field = Lua_optoption(L, 2, -1, mobj_fields_ref); lua_settop(L, 2); - if (!mo || !ISINLEVEL) { + if (P_MobjWasRemoved(mo) || !ISINLEVEL) { if (field == mobj_valid) { lua_pushboolean(L, 0); return 1; } - if (!mo) { + if (P_MobjWasRemoved(mo)) { return LUA_ErrInvalid(L, "mobj_t"); } else return luaL_error(L, "Do not access an mobj_t field outside a level!"); @@ -354,6 +356,9 @@ static int mobj_get(lua_State *L) case mobj_blendmode: lua_pushinteger(L, mo->blendmode); break; + case mobj_alpha: + lua_pushfixed(L, mo->alpha); + break; case mobj_bnext: if (mo->blocknode && mo->blocknode->bnext) { LUA_PushUserdata(L, mo->blocknode->bnext->mobj, META_MOBJ); @@ -564,7 +569,7 @@ static int mobj_set(lua_State *L) mo->frame = (UINT32)luaL_checkinteger(L, 3); break; case mobj_sprite2: - mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), (UINT8)luaL_checkinteger(L, 3), mo->player); + mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), (UINT16)luaL_checkinteger(L, 3), mo->player); break; case mobj_anim_duration: mo->anim_duration = (UINT16)luaL_checkinteger(L, 3); @@ -733,6 +738,16 @@ static int mobj_set(lua_State *L) mo->blendmode = blendmode; break; } + case mobj_alpha: + { + fixed_t alpha = luaL_checkfixed(L, 3); + if (alpha < 0) + alpha = 0; + else if (alpha > FRACUNIT) + alpha = FRACUNIT; + mo->alpha = alpha; + break; + } case mobj_bnext: return NOSETPOS; case mobj_bprev: @@ -762,7 +777,7 @@ static int mobj_set(lua_State *L) return luaL_error(L, "mobj.type %d out of range (0 - %d).", newtype, NUMMOBJTYPES-1); mo->type = newtype; mo->info = &mobjinfo[newtype]; - P_SetScale(mo, mo->scale); + P_SetScale(mo, mo->scale, false); break; } case mobj_info: @@ -836,9 +851,7 @@ static int mobj_set(lua_State *L) fixed_t scale = luaL_checkfixed(L, 3); if (scale < FRACUNIT/100) scale = FRACUNIT/100; - mo->destscale = scale; - P_SetScale(mo, scale); - mo->old_scale = scale; + P_SetScale(mo, scale, true); break; } case mobj_destscale: @@ -1003,6 +1016,9 @@ static int mapthing_get(lua_State *L) return 0; } + if (field == (enum mapthing_e)-1) + return LUA_ErrInvalid(L, "fields"); + switch (field) { case mapthing_valid: @@ -1061,7 +1077,7 @@ static int mapthing_get(lua_State *L) break; default: if (devparm) - return luaL_error(L, LUA_QL("mapthing_t") " has no field named " LUA_QS, field); + return luaL_error(L, "%s %s", LUA_QL("mapthing_t"), va("has no field named: %ui", field)); else return 0; } @@ -1078,6 +1094,9 @@ static int mapthing_set(lua_State *L) if (!mt) return luaL_error(L, "accessed mapthing_t doesn't exist anymore."); + if (field == (enum mapthing_e)-1) + return LUA_ErrInvalid(L, "fields"); + if (hud_running) return luaL_error(L, "Do not alter mapthing_t in HUD rendering code!"); if (hook_cmd_running) @@ -1135,7 +1154,7 @@ static int mapthing_set(lua_State *L) mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); break; default: - return luaL_error(L, LUA_QL("mapthing_t") " has no field named " LUA_QS, field); + return luaL_error(L, "%s %s", LUA_QL("mapthing_t"), va("has no field named: %ui", field)); } return 0; diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 2aae7288349c0f1dae5b9dc15d316dead69775c8..37b42fde5b907bd531514ce4376ddc5cb8680c18 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2023 by Sonic Team Junior. +// Copyright (C) 2012-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -190,6 +190,7 @@ enum player_e player_marelap, player_marebonuslap, player_marebegunat, + player_lastmaretime, player_startedtime, player_finishedtime, player_lapbegunat, @@ -337,6 +338,7 @@ static const char *const player_opt[] = { "marelap", "marebonuslap", "marebegunat", + "lastmaretime", "startedtime", "finishedtime", "lapbegunat", @@ -725,6 +727,9 @@ static int player_get(lua_State *L) case player_marebegunat: lua_pushinteger(L, plr->marebegunat); break; + case player_lastmaretime: + lua_pushinteger(L, plr->lastmaretime); + break; case player_startedtime: lua_pushinteger(L, plr->startedtime); break; @@ -1219,6 +1224,9 @@ static int player_set(lua_State *L) case player_marebegunat: plr->marebegunat = (tic_t)luaL_checkinteger(L, 3); break; + case player_lastmaretime: + plr->lastmaretime = (tic_t)luaL_checkinteger(L, 3); + break; case player_startedtime: plr->startedtime = (tic_t)luaL_checkinteger(L, 3); break; @@ -1423,8 +1431,8 @@ static int power_len(lua_State *L) return 1; } -#define NOFIELD luaL_error(L, LUA_QL("ticcmd_t") " has no field named " LUA_QS, field) -#define NOSET luaL_error(L, LUA_QL("ticcmd_t") " field " LUA_QS " should not be set directly.", ticcmd_opt[field]) +#define NOFIELD luaL_error(L, "%s %s", LUA_QL("ticcmd_t"), va("has no field named %ui", field)) +#define NOSET luaL_error(L, LUA_QL("ticcmd_t") " field %s should not be set directly.", ticcmd_opt[field]) enum ticcmd_e { @@ -1455,6 +1463,9 @@ static int ticcmd_get(lua_State *L) if (!cmd) return LUA_ErrInvalid(L, "player_t"); + if (field == (enum ticcmd_e)-1) + return LUA_ErrInvalid(L, "fields"); + switch (field) { case ticcmd_forwardmove: @@ -1489,6 +1500,9 @@ static int ticcmd_set(lua_State *L) if (!cmd) return LUA_ErrInvalid(L, "ticcmd_t"); + if (field == (enum ticcmd_e)-1) + return LUA_ErrInvalid(L, "fields"); + if (hud_running) return luaL_error(L, "Do not alter player_t in HUD rendering code!"); diff --git a/src/lua_script.c b/src/lua_script.c index b62fa675e2e7193da3a688d89d2f1cf377298a51..686555a16d6b09b98d839cefec0ac0fc876181ae 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2023 by Sonic Team Junior. +// Copyright (C) 2012-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -622,9 +622,6 @@ static inline boolean LUA_LoadFile(MYFILE *f, char *name) if (!gL) // Lua needs to be initialized LUA_ClearState(); - lua_pushinteger(gL, f->wad); - lua_setfield(gL, LUA_REGISTRYINDEX, "WAD"); - lua_pushcfunction(gL, LUA_GetErrorMessage); errorhandlerindex = lua_gettop(gL); @@ -1101,7 +1098,7 @@ static UINT8 GetUserdataArchType(int index) return ARCH_NULL; } -static UINT8 ArchiveValue(int TABLESINDEX, int myindex) +static UINT8 ArchiveValue(save_t *save_p, int TABLESINDEX, int myindex) { if (myindex < 0) myindex = lua_gettop(gL)+1+myindex; @@ -1109,34 +1106,34 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { case LUA_TNONE: case LUA_TNIL: - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); break; // This might be a problem. D: case LUA_TLIGHTUSERDATA: case LUA_TTHREAD: case LUA_TFUNCTION: - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); return 2; case LUA_TBOOLEAN: - WRITEUINT8(save_p, lua_toboolean(gL, myindex) ? ARCH_TRUE : ARCH_FALSE); + P_WriteUINT8(save_p, lua_toboolean(gL, myindex) ? ARCH_TRUE : ARCH_FALSE); break; case LUA_TNUMBER: { lua_Integer number = lua_tointeger(gL, myindex); if (number >= INT8_MIN && number <= INT8_MAX) { - WRITEUINT8(save_p, ARCH_INT8); - WRITESINT8(save_p, number); + P_WriteUINT8(save_p, ARCH_INT8); + P_WriteSINT8(save_p, number); } else if (number >= INT16_MIN && number <= INT16_MAX) { - WRITEUINT8(save_p, ARCH_INT16); - WRITEINT16(save_p, number); + P_WriteUINT8(save_p, ARCH_INT16); + P_WriteINT16(save_p, number); } else { - WRITEUINT8(save_p, ARCH_INT32); - WRITEFIXED(save_p, number); + P_WriteUINT8(save_p, ARCH_INT32); + P_WriteFixed(save_p, number); } break; } @@ -1147,23 +1144,23 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) UINT32 i = 0; // if you're wondering why we're writing a string to save_p this way, // it turns out that Lua can have embedded zeros ('\0') in the strings, - // so we can't use WRITESTRING as that cuts off when it finds a '\0'. + // so we can't use P_WriteString as that cuts off when it finds a '\0'. // Saving the size of the string also allows us to get the size of the string on the other end, // fixing the awful crashes previously encountered for reading strings longer than 1024 // (yes I know that's kind of a stupid thing to care about, but it'd be evil to trim or ignore them?) // -- Monster Iestyn 05/08/18 if (len < 255) { - WRITEUINT8(save_p, ARCH_SMALLSTRING); - WRITEUINT8(save_p, len); // save size of string + P_WriteUINT8(save_p, ARCH_SMALLSTRING); + P_WriteUINT8(save_p, len); // save size of string } else { - WRITEUINT8(save_p, ARCH_LARGESTRING); - WRITEUINT32(save_p, len); // save size of string + P_WriteUINT8(save_p, ARCH_LARGESTRING); + P_WriteUINT32(save_p, len); // save size of string } while (i < len) - WRITECHAR(save_p, s[i++]); // write chars individually, including the embedded zeros + P_WriteChar(save_p, s[i++]); // write chars individually, including the embedded zeros break; } case LUA_TTABLE: @@ -1189,13 +1186,13 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) if (t == 0) { CONS_Alert(CONS_ERROR, "Too many tables to archive!\n"); - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); return 0; } } - WRITEUINT8(save_p, ARCH_TABLE); - WRITEUINT16(save_p, t); + P_WriteUINT8(save_p, ARCH_TABLE); + P_WriteUINT16(save_p, t); if (!found) { @@ -1211,25 +1208,25 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) case ARCH_MOBJINFO: { mobjinfo_t *info = *((mobjinfo_t **)lua_touserdata(gL, myindex)); - WRITEUINT8(save_p, ARCH_MOBJINFO); - WRITEUINT16(save_p, info - mobjinfo); + P_WriteUINT8(save_p, ARCH_MOBJINFO); + P_WriteUINT16(save_p, info - mobjinfo); break; } case ARCH_STATE: { state_t *state = *((state_t **)lua_touserdata(gL, myindex)); - WRITEUINT8(save_p, ARCH_STATE); - WRITEUINT16(save_p, state - states); + P_WriteUINT8(save_p, ARCH_STATE); + P_WriteUINT16(save_p, state - states); break; } case ARCH_MOBJ: { mobj_t *mobj = *((mobj_t **)lua_touserdata(gL, myindex)); if (!mobj) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_MOBJ); - WRITEUINT32(save_p, mobj->mobjnum); + P_WriteUINT8(save_p, ARCH_MOBJ); + P_WriteUINT32(save_p, mobj->mobjnum); } break; } @@ -1237,10 +1234,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { player_t *player = *((player_t **)lua_touserdata(gL, myindex)); if (!player) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_PLAYER); - WRITEUINT8(save_p, player - players); + P_WriteUINT8(save_p, ARCH_PLAYER); + P_WriteUINT8(save_p, player - players); } break; } @@ -1248,10 +1245,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { mapthing_t *mapthing = *((mapthing_t **)lua_touserdata(gL, myindex)); if (!mapthing) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_MAPTHING); - WRITEUINT16(save_p, mapthing - mapthings); + P_WriteUINT8(save_p, ARCH_MAPTHING); + P_WriteUINT16(save_p, mapthing - mapthings); } break; } @@ -1259,10 +1256,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { vertex_t *vertex = *((vertex_t **)lua_touserdata(gL, myindex)); if (!vertex) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_VERTEX); - WRITEUINT16(save_p, vertex - vertexes); + P_WriteUINT8(save_p, ARCH_VERTEX); + P_WriteUINT16(save_p, vertex - vertexes); } break; } @@ -1270,10 +1267,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { line_t *line = *((line_t **)lua_touserdata(gL, myindex)); if (!line) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_LINE); - WRITEUINT16(save_p, line - lines); + P_WriteUINT8(save_p, ARCH_LINE); + P_WriteUINT16(save_p, line - lines); } break; } @@ -1281,10 +1278,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { side_t *side = *((side_t **)lua_touserdata(gL, myindex)); if (!side) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_SIDE); - WRITEUINT16(save_p, side - sides); + P_WriteUINT8(save_p, ARCH_SIDE); + P_WriteUINT16(save_p, side - sides); } break; } @@ -1292,10 +1289,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { subsector_t *subsector = *((subsector_t **)lua_touserdata(gL, myindex)); if (!subsector) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_SUBSECTOR); - WRITEUINT16(save_p, subsector - subsectors); + P_WriteUINT8(save_p, ARCH_SUBSECTOR); + P_WriteUINT16(save_p, subsector - subsectors); } break; } @@ -1303,10 +1300,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { sector_t *sector = *((sector_t **)lua_touserdata(gL, myindex)); if (!sector) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_SECTOR); - WRITEUINT16(save_p, sector - sectors); + P_WriteUINT8(save_p, ARCH_SECTOR); + P_WriteUINT16(save_p, sector - sectors); } break; } @@ -1315,10 +1312,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { seg_t *seg = *((seg_t **)lua_touserdata(gL, myindex)); if (!seg) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_SEG); - WRITEUINT16(save_p, seg - segs); + P_WriteUINT8(save_p, ARCH_SEG); + P_WriteUINT16(save_p, seg - segs); } break; } @@ -1326,10 +1323,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { node_t *node = *((node_t **)lua_touserdata(gL, myindex)); if (!node) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_NODE); - WRITEUINT16(save_p, node - nodes); + P_WriteUINT8(save_p, ARCH_NODE); + P_WriteUINT16(save_p, node - nodes); } break; } @@ -1338,16 +1335,16 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { ffloor_t *rover = *((ffloor_t **)lua_touserdata(gL, myindex)); if (!rover) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { UINT16 i = P_GetFFloorID(rover); if (i == UINT16_MAX) // invalid ID - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_FFLOOR); - WRITEUINT16(save_p, rover->target - sectors); - WRITEUINT16(save_p, i); + P_WriteUINT8(save_p, ARCH_FFLOOR); + P_WriteUINT16(save_p, rover->target - sectors); + P_WriteUINT16(save_p, i); } } break; @@ -1356,10 +1353,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { polyobj_t *polyobj = *((polyobj_t **)lua_touserdata(gL, myindex)); if (!polyobj) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_POLYOBJ); - WRITEUINT16(save_p, polyobj-PolyObjects); + P_WriteUINT8(save_p, ARCH_POLYOBJ); + P_WriteUINT16(save_p, polyobj-PolyObjects); } break; } @@ -1367,10 +1364,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { pslope_t *slope = *((pslope_t **)lua_touserdata(gL, myindex)); if (!slope) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_SLOPE); - WRITEUINT16(save_p, slope->id); + P_WriteUINT8(save_p, ARCH_SLOPE); + P_WriteUINT16(save_p, slope->id); } break; } @@ -1378,36 +1375,36 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { mapheader_t *header = *((mapheader_t **)lua_touserdata(gL, myindex)); if (!header) - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_MAPHEADER); - WRITEUINT16(save_p, header - *mapheaderinfo); + P_WriteUINT8(save_p, ARCH_MAPHEADER); + P_WriteUINT16(save_p, header - *mapheaderinfo); } break; } case ARCH_SKINCOLOR: { skincolor_t *info = *((skincolor_t **)lua_touserdata(gL, myindex)); - WRITEUINT8(save_p, ARCH_SKINCOLOR); - WRITEUINT16(save_p, info - skincolors); + P_WriteUINT8(save_p, ARCH_SKINCOLOR); + P_WriteUINT16(save_p, info - skincolors); break; } case ARCH_MOUSE: { mouse_t *m = *((mouse_t **)lua_touserdata(gL, myindex)); - WRITEUINT8(save_p, ARCH_MOUSE); - WRITEUINT8(save_p, m == &mouse ? 1 : 2); + P_WriteUINT8(save_p, ARCH_MOUSE); + P_WriteUINT8(save_p, m == &mouse ? 1 : 2); break; } case ARCH_SKIN: { skin_t *skin = *((skin_t **)lua_touserdata(gL, myindex)); - WRITEUINT8(save_p, ARCH_SKIN); - WRITEUINT8(save_p, skin->skinnum); // UINT8 because MAXSKINS must be <= 256 + P_WriteUINT8(save_p, ARCH_SKIN); + P_WriteUINT8(save_p, skin->skinnum); // UINT8 because MAXSKINS must be <= 256 break; } default: - WRITEUINT8(save_p, ARCH_NULL); + P_WriteUINT8(save_p, ARCH_NULL); return 2; } break; @@ -1415,14 +1412,14 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) return 0; } -static void ArchiveExtVars(void *pointer, const char *ptype) +static void ArchiveExtVars(save_t *save_p, void *pointer, const char *ptype) { int TABLESINDEX; UINT16 i; if (!gL) { if (fastcmp(ptype,"player")) // players must always be included, even if no vars - WRITEUINT16(save_p, 0); + P_WriteUINT16(save_p, 0); return; } @@ -1438,7 +1435,7 @@ static void ArchiveExtVars(void *pointer, const char *ptype) { // no extra values table lua_pop(gL, 1); if (fastcmp(ptype,"player")) // players must always be included, even if no vars - WRITEUINT16(save_p, 0); + P_WriteUINT16(save_p, 0); return; } @@ -1450,20 +1447,20 @@ static void ArchiveExtVars(void *pointer, const char *ptype) if (i == 0) { if (fastcmp(ptype,"player")) // always include players even if they have no extra variables - WRITEUINT16(save_p, 0); + P_WriteUINT16(save_p, 0); lua_pop(gL, 1); return; } if (fastcmp(ptype,"mobj")) // mobjs must write their mobjnum as a header - WRITEUINT32(save_p, ((mobj_t *)pointer)->mobjnum); - WRITEUINT16(save_p, i); + P_WriteUINT32(save_p, ((mobj_t *)pointer)->mobjnum); + P_WriteUINT16(save_p, i); lua_pushnil(gL); while (lua_next(gL, -2)) { I_Assert(lua_type(gL, -2) == LUA_TSTRING); - WRITESTRING(save_p, lua_tostring(gL, -2)); - if (ArchiveValue(TABLESINDEX, -1) == 2) + P_WriteString(save_p, lua_tostring(gL, -2)); + if (ArchiveValue(save_p, TABLESINDEX, -1) == 2) CONS_Alert(CONS_ERROR, "Type of value for %s entry '%s' (%s) could not be archived!\n", ptype, lua_tostring(gL, -2), luaL_typename(gL, -1)); lua_pop(gL, 1); } @@ -1471,16 +1468,19 @@ static void ArchiveExtVars(void *pointer, const char *ptype) lua_pop(gL, 1); } +// FIXME: remove and pass as local variable +static save_t *lua_save_p; + static int NetArchive(lua_State *L) { int TABLESINDEX = lua_upvalueindex(1); int i, n = lua_gettop(L); for (i = 1; i <= n; i++) - ArchiveValue(TABLESINDEX, i); + ArchiveValue(lua_save_p, TABLESINDEX, i); return n; } -static void ArchiveTables(void) +static void ArchiveTables(save_t *save_p) { int TABLESINDEX; UINT16 i, n; @@ -1499,14 +1499,14 @@ static void ArchiveTables(void) while (lua_next(gL, -2)) { // Write key - e = ArchiveValue(TABLESINDEX, -2); // key should be either a number or a string, ArchiveValue can handle this. + e = ArchiveValue(save_p, TABLESINDEX, -2); // key should be either a number or a string, ArchiveValue can handle this. if (e == 1) n++; // the table contained a new table we'll have to archive. :( else if (e == 2) // invalid key type (function, thread, lightuserdata, or anything we don't recognise) CONS_Alert(CONS_ERROR, "Index '%s' (%s) of table %d could not be archived!\n", lua_tostring(gL, -2), luaL_typename(gL, -2), i); // Write value - e = ArchiveValue(TABLESINDEX, -1); + e = ArchiveValue(save_p, TABLESINDEX, -1); if (e == 1) n++; // the table contained a new table we'll have to archive. :( else if (e == 2) // invalid value type @@ -1514,7 +1514,7 @@ static void ArchiveTables(void) lua_pop(gL, 1); } - WRITEUINT8(save_p, ARCH_TEND); + P_WriteUINT8(save_p, ARCH_TEND); // Write metatable ID if (lua_getmetatable(gL, -1)) @@ -1523,19 +1523,19 @@ static void ArchiveTables(void) lua_getfield(gL, LUA_REGISTRYINDEX, LREG_METATABLES); lua_pushvalue(gL, -2); lua_gettable(gL, -2); - WRITEUINT16(save_p, lua_isnil(gL, -1) ? 0 : lua_tointeger(gL, -1)); + P_WriteUINT16(save_p, lua_isnil(gL, -1) ? 0 : lua_tointeger(gL, -1)); lua_pop(gL, 3); } else - WRITEUINT16(save_p, 0); + P_WriteUINT16(save_p, 0); lua_pop(gL, 1); } } -static UINT8 UnArchiveValue(int TABLESINDEX) +static UINT8 UnArchiveValue(save_t *save_p, int TABLESINDEX) { - UINT8 type = READUINT8(save_p); + UINT8 type = P_ReadUINT8(save_p); switch (type) { case ARCH_NULL: @@ -1548,13 +1548,13 @@ static UINT8 UnArchiveValue(int TABLESINDEX) lua_pushboolean(gL, false); break; case ARCH_INT8: - lua_pushinteger(gL, READSINT8(save_p)); + lua_pushinteger(gL, P_ReadSINT8(save_p)); break; case ARCH_INT16: - lua_pushinteger(gL, READINT16(save_p)); + lua_pushinteger(gL, P_ReadINT16(save_p)); break; case ARCH_INT32: - lua_pushinteger(gL, READFIXED(save_p)); + lua_pushinteger(gL, P_ReadFixed(save_p)); break; case ARCH_SMALLSTRING: case ARCH_LARGESTRING: @@ -1565,23 +1565,23 @@ static UINT8 UnArchiveValue(int TABLESINDEX) // See my comments in the ArchiveValue function; // it's much the same for reading strings as writing them! - // (i.e. we can't use READSTRING either) + // (i.e. we can't use P_ReadString either) // -- Monster Iestyn 05/08/18 if (type == ARCH_SMALLSTRING) - len = READUINT8(save_p); // length of string, including embedded zeros + len = P_ReadUINT8(save_p); // length of string, including embedded zeros else - len = READUINT32(save_p); // length of string, including embedded zeros + len = P_ReadUINT32(save_p); // length of string, including embedded zeros value = malloc(len); // make temp buffer of size len // now read the actual string while (i < len) - value[i++] = READCHAR(save_p); // read chars individually, including the embedded zeros + value[i++] = P_ReadChar(save_p); // read chars individually, including the embedded zeros lua_pushlstring(gL, value, len); // push the string (note: this function supports embedded zeros) free(value); // free the buffer break; } case ARCH_TABLE: { - UINT16 tid = READUINT16(save_p); + UINT16 tid = P_ReadUINT16(save_p); lua_rawgeti(gL, TABLESINDEX, tid); if (lua_isnil(gL, -1)) { @@ -1594,69 +1594,69 @@ static UINT8 UnArchiveValue(int TABLESINDEX) break; } case ARCH_MOBJINFO: - LUA_PushUserdata(gL, &mobjinfo[READUINT16(save_p)], META_MOBJINFO); + LUA_PushUserdata(gL, &mobjinfo[P_ReadUINT16(save_p)], META_MOBJINFO); break; case ARCH_STATE: - LUA_PushUserdata(gL, &states[READUINT16(save_p)], META_STATE); + LUA_PushUserdata(gL, &states[P_ReadUINT16(save_p)], META_STATE); break; case ARCH_MOBJ: - LUA_PushUserdata(gL, P_FindNewPosition(READUINT32(save_p)), META_MOBJ); + LUA_PushUserdata(gL, P_FindNewPosition(P_ReadUINT32(save_p)), META_MOBJ); break; case ARCH_PLAYER: - LUA_PushUserdata(gL, &players[READUINT8(save_p)], META_PLAYER); + LUA_PushUserdata(gL, &players[P_ReadUINT8(save_p)], META_PLAYER); break; case ARCH_MAPTHING: - LUA_PushUserdata(gL, &mapthings[READUINT16(save_p)], META_MAPTHING); + LUA_PushUserdata(gL, &mapthings[P_ReadUINT16(save_p)], META_MAPTHING); break; case ARCH_VERTEX: - LUA_PushUserdata(gL, &vertexes[READUINT16(save_p)], META_VERTEX); + LUA_PushUserdata(gL, &vertexes[P_ReadUINT16(save_p)], META_VERTEX); break; case ARCH_LINE: - LUA_PushUserdata(gL, &lines[READUINT16(save_p)], META_LINE); + LUA_PushUserdata(gL, &lines[P_ReadUINT16(save_p)], META_LINE); break; case ARCH_SIDE: - LUA_PushUserdata(gL, &sides[READUINT16(save_p)], META_SIDE); + LUA_PushUserdata(gL, &sides[P_ReadUINT16(save_p)], META_SIDE); break; case ARCH_SUBSECTOR: - LUA_PushUserdata(gL, &subsectors[READUINT16(save_p)], META_SUBSECTOR); + LUA_PushUserdata(gL, &subsectors[P_ReadUINT16(save_p)], META_SUBSECTOR); break; case ARCH_SECTOR: - LUA_PushUserdata(gL, §ors[READUINT16(save_p)], META_SECTOR); + LUA_PushUserdata(gL, §ors[P_ReadUINT16(save_p)], META_SECTOR); break; #ifdef HAVE_LUA_SEGS case ARCH_SEG: - LUA_PushUserdata(gL, &segs[READUINT16(save_p)], META_SEG); + LUA_PushUserdata(gL, &segs[P_ReadUINT16(save_p)], META_SEG); break; case ARCH_NODE: - LUA_PushUserdata(gL, &nodes[READUINT16(save_p)], META_NODE); + LUA_PushUserdata(gL, &nodes[P_ReadUINT16(save_p)], META_NODE); break; #endif case ARCH_FFLOOR: { - sector_t *sector = §ors[READUINT16(save_p)]; - UINT16 id = READUINT16(save_p); + sector_t *sector = §ors[P_ReadUINT16(save_p)]; + UINT16 id = P_ReadUINT16(save_p); ffloor_t *rover = P_GetFFloorByID(sector, id); if (rover) LUA_PushUserdata(gL, rover, META_FFLOOR); break; } case ARCH_POLYOBJ: - LUA_PushUserdata(gL, &PolyObjects[READUINT16(save_p)], META_POLYOBJ); + LUA_PushUserdata(gL, &PolyObjects[P_ReadUINT16(save_p)], META_POLYOBJ); break; case ARCH_SLOPE: - LUA_PushUserdata(gL, P_SlopeById(READUINT16(save_p)), META_SLOPE); + LUA_PushUserdata(gL, P_SlopeById(P_ReadUINT16(save_p)), META_SLOPE); break; case ARCH_MAPHEADER: - LUA_PushUserdata(gL, mapheaderinfo[READUINT16(save_p)], META_MAPHEADER); + LUA_PushUserdata(gL, mapheaderinfo[P_ReadUINT16(save_p)], META_MAPHEADER); break; case ARCH_SKINCOLOR: - LUA_PushUserdata(gL, &skincolors[READUINT16(save_p)], META_SKINCOLOR); + LUA_PushUserdata(gL, &skincolors[P_ReadUINT16(save_p)], META_SKINCOLOR); break; case ARCH_MOUSE: - LUA_PushUserdata(gL, READUINT16(save_p) == 1 ? &mouse : &mouse2, META_MOUSE); + LUA_PushUserdata(gL, P_ReadUINT16(save_p) == 1 ? &mouse : &mouse2, META_MOUSE); break; case ARCH_SKIN: - LUA_PushUserdata(gL, skins[READUINT8(save_p)], META_SKIN); + LUA_PushUserdata(gL, skins[P_ReadUINT8(save_p)], META_SKIN); break; case ARCH_TEND: return 1; @@ -1664,10 +1664,10 @@ static UINT8 UnArchiveValue(int TABLESINDEX) return 0; } -static void UnArchiveExtVars(void *pointer) +static void UnArchiveExtVars(save_t *save_p, void *pointer) { int TABLESINDEX; - UINT16 field_count = READUINT16(save_p); + UINT16 field_count = P_ReadUINT16(save_p); UINT16 i; char field[1024]; @@ -1680,8 +1680,8 @@ static void UnArchiveExtVars(void *pointer) for (i = 0; i < field_count; i++) { - READSTRING(save_p, field); - UnArchiveValue(TABLESINDEX); + P_ReadString(save_p, field); + UnArchiveValue(save_p, TABLESINDEX); lua_setfield(gL, -2, field); } @@ -1698,11 +1698,11 @@ static int NetUnArchive(lua_State *L) int TABLESINDEX = lua_upvalueindex(1); int i, n = lua_gettop(L); for (i = 1; i <= n; i++) - UnArchiveValue(TABLESINDEX); + UnArchiveValue(lua_save_p, TABLESINDEX); return n; } -static void UnArchiveTables(void) +static void UnArchiveTables(save_t *save_p) { int TABLESINDEX; UINT16 i, n; @@ -1719,13 +1719,13 @@ static void UnArchiveTables(void) lua_rawgeti(gL, TABLESINDEX, i); while (true) { - UINT8 e = UnArchiveValue(TABLESINDEX); // read key + UINT8 e = UnArchiveValue(save_p, TABLESINDEX); // read key if (e == 1) // End of table break; else if (e == 2) // Key contains a new table n++; - if (UnArchiveValue(TABLESINDEX) == 2) // read value + if (UnArchiveValue(save_p, TABLESINDEX) == 2) // read value n++; if (lua_isnil(gL, -2)) // if key is nil (if a function etc was accidentally saved) @@ -1737,7 +1737,7 @@ static void UnArchiveTables(void) lua_rawset(gL, -3); } - metatableid = READUINT16(save_p); + metatableid = P_ReadUINT16(save_p); if (metatableid) { // setmetatable(table, registry.metatables[metatableid]) @@ -1761,7 +1761,7 @@ void LUA_Step(void) lua_gc(gL, LUA_GCSTEP, 1); } -void LUA_Archive(void) +void LUA_Archive(save_t *save_p) { INT32 i; thinker_t *th; @@ -1774,29 +1774,30 @@ void LUA_Archive(void) if (!playeringame[i] && i > 0) // dedicated servers... continue; // all players in game will be archived, even if they just add a 0. - ArchiveExtVars(&players[i], "player"); + ArchiveExtVars(save_p, &players[i], "player"); } for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; // archive function will determine when to skip mobjs, // and write mobjnum in otherwise. - ArchiveExtVars(th, "mobj"); + ArchiveExtVars(save_p, th, "mobj"); } - WRITEUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum. + P_WriteUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum. + lua_save_p = save_p; LUA_HookNetArchive(NetArchive); // call the NetArchive hook in archive mode - ArchiveTables(); + ArchiveTables(save_p); if (gL) lua_pop(gL, 1); // pop tables } -void LUA_UnArchive(void) +void LUA_UnArchive(save_t *save_p) { UINT32 mobjnum; INT32 i; @@ -1809,23 +1810,24 @@ void LUA_UnArchive(void) { if (!playeringame[i] && i > 0) // dedicated servers... continue; - UnArchiveExtVars(&players[i]); + UnArchiveExtVars(save_p, &players[i]); } do { - mobjnum = READUINT32(save_p); // read a mobjnum + mobjnum = P_ReadUINT32(save_p); // read a mobjnum for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; if (((mobj_t *)th)->mobjnum != mobjnum) // find matching mobj continue; - UnArchiveExtVars(th); // apply variables + UnArchiveExtVars(save_p, th); // apply variables } } while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker. + lua_save_p = save_p; LUA_HookNetArchive(NetUnArchive); // call the NetArchive hook in unarchive mode - UnArchiveTables(); + UnArchiveTables(save_p); if (gL) lua_pop(gL, 1); // pop tables diff --git a/src/lua_script.h b/src/lua_script.h index 45d2a37ffd1a636f1e6aaf6848fa868a25fba74b..c5a5069ef1a392ab9010783dd48bde51367bf537 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2023 by Sonic Team Junior. +// Copyright (C) 2012-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -13,6 +13,7 @@ #ifndef LUA_SCRIPT_H #define LUA_SCRIPT_H +#include "p_saveg.h" #include "m_fixed.h" #include "doomtype.h" #include "d_player.h" @@ -52,8 +53,8 @@ void LUA_DumpFile(const char *filename); #endif fixed_t LUA_EvalMath(const char *word); void LUA_Step(void); -void LUA_Archive(void); -void LUA_UnArchive(void); +void LUA_Archive(save_t *save_p); +void LUA_UnArchive(save_t *save_p); int LUA_PushGlobals(lua_State *L, const char *word); int LUA_CheckGlobals(lua_State *L, const char *word); void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index e183d8dda4a08b4c64dcc2429937cf919d743f67..6650e60e6f353c3250644757c06d87ad1c1c7001 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2014-2016 by John "JTE" Muniz. -// Copyright (C) 2014-2023 by Sonic Team Junior. +// Copyright (C) 2014-2025 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -54,7 +54,9 @@ enum skin { skin_contspeed, skin_contangle, skin_soundsid, - skin_sprites, + skin_sprites, // TODO: 2.3: Delete + skin_skinsprites, + skin_supersprites, skin_natkcolor }; @@ -94,7 +96,9 @@ static const char *const skin_opt[] = { "contspeed", "contangle", "soundsid", - "sprites", + "sprites", // TODO: 2.3: Delete + "skinsprites", + "supersprites", "natkcolor", NULL}; @@ -217,9 +221,15 @@ static int skin_get(lua_State *L) case skin_soundsid: LUA_PushUserdata(L, skin->soundsid, META_SOUNDSID); break; - case skin_sprites: + case skin_sprites: // TODO: 2.3: Delete + LUA_PushUserdata(L, skin->sprites_compat, META_SKINSPRITESCOMPAT); + break; + case skin_skinsprites: LUA_PushUserdata(L, skin->sprites, META_SKINSPRITES); break; + case skin_supersprites: + LUA_PushUserdata(L, skin->super.sprites, META_SKINSPRITES); + break; case skin_natkcolor: lua_pushinteger(L, skin->natkcolor); break; @@ -333,34 +343,59 @@ static int soundsid_num(lua_State *L) return 1; } -enum spritesopt { - numframes = 0 -}; - -static const char *const sprites_opt[] = { - "numframes", - NULL}; - -// skin.sprites[i] -> sprites[i] +// skin.skinsprites[i] -> sprites[i] static int lib_getSkinSprite(lua_State *L) { spritedef_t *sksprites = *(spritedef_t **)luaL_checkudata(L, 1, META_SKINSPRITES); playersprite_t i = luaL_checkinteger(L, 2); + if (i < 0 || i >= NUMPLAYERSPRITES) + return luaL_error(L, "skin sprites index %d out of range (0 - %d)", i, NUMPLAYERSPRITES-1); + + LUA_PushUserdata(L, &sksprites[i], META_SKINSPRITESLIST); + return 1; +} + +// #skin.skinsprites -> NUMPLAYERSPRITES +static int lib_numSkinsSprites(lua_State *L) +{ + lua_pushinteger(L, NUMPLAYERSPRITES); + return 1; +} + +// TODO: 2.3: Delete +// skin.sprites[i] -> sprites[i] +static int lib_getSkinSpriteCompat(lua_State *L) +{ + spritedef_t *sksprites = *(spritedef_t **)luaL_checkudata(L, 1, META_SKINSPRITESCOMPAT); + INT32 i = luaL_checkinteger(L, 2) & (SPR2F_MASK | SPR2F_SUPER); + + if (i & SPR2F_SUPER) + i = (i & ~SPR2F_SUPER) + NUMPLAYERSPRITES; + if (i < 0 || i >= NUMPLAYERSPRITES*2) - return luaL_error(L, LUA_QL("skin_t") " field 'sprites' index %d out of range (0 - %d)", i, (NUMPLAYERSPRITES*2)-1); + return luaL_error(L, "skin sprites index %d out of range (0 - %d)", i, (NUMPLAYERSPRITES*2)-1); LUA_PushUserdata(L, &sksprites[i], META_SKINSPRITESLIST); return 1; } +// TODO: 2.3: Delete // #skin.sprites -> NUMPLAYERSPRITES*2 -static int lib_numSkinsSprites(lua_State *L) +static int lib_numSkinsSpritesCompat(lua_State *L) { lua_pushinteger(L, NUMPLAYERSPRITES*2); return 1; } +enum spritesopt { + numframes = 0 +}; + +static const char *const sprites_opt[] = { + "numframes", + NULL}; + static int sprite_get(lua_State *L) { spritedef_t *sprite = *(spritedef_t **)luaL_checkudata(L, 1, META_SKINSPRITESLIST); @@ -382,6 +417,7 @@ int LUA_SkinLib(lua_State *L) LUA_RegisterUserdataMetatable(L, META_SOUNDSID, soundsid_get, NULL, soundsid_num); LUA_RegisterUserdataMetatable(L, META_SKINSPRITES, lib_getSkinSprite, NULL, lib_numSkinsSprites); LUA_RegisterUserdataMetatable(L, META_SKINSPRITESLIST, sprite_get, NULL, NULL); + LUA_RegisterUserdataMetatable(L, META_SKINSPRITESCOMPAT, lib_getSkinSpriteCompat, NULL, lib_numSkinsSpritesCompat); // TODO: 2.3: Delete skin_fields_ref = Lua_CreateFieldTable(L, skin_opt); diff --git a/src/m_anigif.c b/src/m_anigif.c index 5bc7717e0f44a4293e52a8907c57b0cfda6eade5..5ebc4892c2d6af8c9a2a31f446d11ef39736306c 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 2013-2016 by Matthew "Kaito Sinclaire" Walsh. // Copyright (C) 2013 by "Ninji". -// Copyright (C) 2013-2023 by Sonic Team Junior. +// Copyright (C) 2013-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -21,6 +21,7 @@ #include "i_system.h" // I_GetPreciseTime #include "m_misc.h" #include "st_stuff.h" // st_palette +#include "doomstat.h" // singletics #ifdef HWRENDER #include "hardware/hw_main.h" @@ -604,7 +605,7 @@ static void GIF_framewrite(void) UINT16 delay = 0; INT32 startline; - if (gif_dynamicdelay ==(UINT8) 2) + if (gif_dynamicdelay ==(UINT8) 2 && !singletics) { // golden's attempt at creating a "dynamic delay" UINT16 mingifdelay = 10; // minimum gif delay in milliseconds (keep at 10 because gifs can't get more precise). @@ -617,7 +618,7 @@ static void GIF_framewrite(void) gif_delayus -= frames*(mingifdelay*1000); // remove frames by the amount of milliseconds they take. don't reset to 0, the microseconds help consistency. } } - else if (gif_dynamicdelay ==(UINT8) 1) + else if (gif_dynamicdelay ==(UINT8) 1 && !singletics) { float delayf = ceil(100.0f/NEWTICRATE); diff --git a/src/m_cheat.c b/src/m_cheat.c index e61db2c2ee3d49e58f570567ee576ba94d3959eb..21ecc3312f2c5fa82f865600518d2863589ca986 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -562,7 +562,7 @@ void Command_Teleport_f(void) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -1072,7 +1072,7 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo = (mobj_t *)th; @@ -1098,15 +1098,23 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c fixed_t fheight = P_GetSectorFloorZAt(sec, mt->x << FRACBITS, mt->y << FRACBITS); mt->z = (UINT16)((player->mo->z - fheight)>>FRACBITS); } + mt->angle = (INT16)(FixedInt(AngleFixed(player->mo->angle))); - mt->options = (mt->z << ZSHIFT) | (UINT16)cv_opflags.value; + mt->options = (UINT16)cv_opflags.value; mt->scale = player->mo->scale; mt->spritexscale = player->mo->spritexscale; mt->spriteyscale = player->mo->spriteyscale; memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args)); memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs)); mt->pitch = mt->roll = 0; + + // Ignore offsets + if (mt->type == mobjinfo[MT_EMBLEM].doomednum) + mt->args[1] = 1; + else if (!(mt->type == mobjinfo[MT_METALSONIC_RACE].doomednum || mt->type == mobjinfo[MT_ROSY].doomednum)) + mt->args[0] = 1; + return mt; } @@ -1424,14 +1432,22 @@ void OP_ObjectplaceMovement(player_t *player) // // Objectplace related commands. // -/*void Command_Writethings_f(void) +void Command_Writethings_f(void) { REQUIRE_INLEVEL; REQUIRE_SINGLEPLAYER; REQUIRE_OBJECTPLACE; - P_WriteThings(); -}*/ + if (COM_Argc() > 1) + { + P_WriteThings(COM_Argv(1)); + } + else + { + CONS_Printf(M_GetText("writethings <filename>: write out map things to a file, .txt or .lmp automatically appended.\n")); + return; + } +} void Command_ObjectPlace_f(void) { diff --git a/src/m_cheat.h b/src/m_cheat.h index f4ac01d842eba583da08a2d1634bd09ad11f1b84..6bd1546f85b9cf9d99656e5f3bd1b0d39cddb4ae 100644 --- a/src/m_cheat.h +++ b/src/m_cheat.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -26,7 +26,7 @@ void cht_Init(void); // ObjectPlace // void Command_ObjectPlace_f(void); -//void Command_Writethings_f(void); +void Command_Writethings_f(void); extern consvar_t cv_opflags, cv_ophoopflags, cv_mapthingnum, cv_speed; //extern consvar_t cv_snapto, cv_grid; diff --git a/src/m_cond.c b/src/m_cond.c index 5a5913297157e24ada893ca5fad77a4d38ffd3e3..9706f76c83e06c2537bf1d57051ed80f0b3f0f84 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 2012-2023 by Sonic Team Junior. +// Copyright (C) 2012-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -475,7 +475,7 @@ UINT8 M_MapLocked(INT32 mapnum, gamedata_t *data) // that's better than making dedicated server's lives hell. return false; } - + if (cv_debug || devparm) return false; // Unlock every level when in devmode. @@ -494,6 +494,12 @@ UINT8 M_MapLocked(INT32 mapnum, gamedata_t *data) UINT8 M_CampaignWarpIsCheat(INT32 gt, INT32 mapnum, gamedata_t *data) { + if (dedicated) + { + // See M_MapLocked; don't make dedicated servers annoying. + return false; + } + if (M_MapLocked(mapnum, data) == true) { // Warping to locked maps is definitely always a cheat diff --git a/src/m_easing.c b/src/m_easing.c index 48fe1efbc579aee27a0d20dc0dfb4900d447653d..60ca6e9b6328fff8ec7b0abb99d517dfe3a8dbbc 100644 --- a/src/m_easing.c +++ b/src/m_easing.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2023 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020-2023 by Lactozilla. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_easing.h b/src/m_easing.h index eaa5d67735e02b831371ba6700d3e10dc8049628..6884833af68cb5b3671dc0cea70cdf734ac03d6b 100644 --- a/src/m_easing.h +++ b/src/m_easing.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2023 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020-2023 by Lactozilla. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_fixed.c b/src/m_fixed.c index 19c1e80919315071fe40086dc93ec42b937ffb26..ace05fd3bd624b96320ccb1be6e4545094c4b32e 100644 --- a/src/m_fixed.c +++ b/src/m_fixed.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // Copyright (C) 2009 by Stephen McGranahan. // // This program is free software distributed under the diff --git a/src/m_fixed.h b/src/m_fixed.h index f40c7b30870baffdd978cec0ecb447b65f74ba6f..504b53a6eea3ba7d8070cdfd635662bb19628f8e 100644 --- a/src/m_fixed.h +++ b/src/m_fixed.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_menu.c b/src/m_menu.c index de23acbfb46b4402261cef08c54bd972d61553ec..37d191a0df84158e31d0d782d6f4b2d6b819eadc 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -3,7 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2011-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2025 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -184,6 +184,9 @@ static fixed_t char_scroll = 0; static tic_t keydown = 0; +// Lua +static huddrawlist_h luahuddrawlist_playersetup; + // // PROTOTYPES // @@ -260,7 +263,7 @@ static void M_ConfirmTeamScramble(INT32 choice); static void M_ConfirmTeamChange(INT32 choice); static void M_SecretsMenu(INT32 choice); static void M_SetupChoosePlayer(INT32 choice); -static UINT16 M_SetupChoosePlayerDirect(INT32 choice); +static INT32 M_SetupChoosePlayerDirect(INT32 choice); static void M_QuitSRB2(INT32 choice); menu_t SP_MainDef, OP_MainDef; menu_t MISC_ScrambleTeamDef, MISC_ChangeTeamDef; @@ -1070,7 +1073,6 @@ static menuitem_t OP_ChangeControlsMenu[] = {IT_CALL | IT_STRING2, NULL, "Move Right", M_ChangeControl, GC_STRAFERIGHT }, {IT_CALL | IT_STRING2, NULL, "Jump", M_ChangeControl, GC_JUMP }, {IT_CALL | IT_STRING2, NULL, "Spin", M_ChangeControl, GC_SPIN }, - {IT_CALL | IT_STRING2, NULL, "Shield", M_ChangeControl, GC_SHIELD }, {IT_HEADER, NULL, "Camera", NULL, 0}, {IT_SPACE, NULL, NULL, NULL, 0}, // padding {IT_CALL | IT_STRING2, NULL, "Look Up", M_ChangeControl, GC_LOOKUP }, @@ -1406,18 +1408,19 @@ static menuitem_t OP_OpenGLOptionsMenu[] = {IT_HEADER, NULL, "General", NULL, 51}, {IT_STRING|IT_CVAR, NULL, "Shaders", &cv_glshaders, 63}, - {IT_STRING|IT_CVAR, NULL, "Lack of perspective", &cv_glshearing, 73}, - {IT_STRING|IT_CVAR, NULL, "Field of view", &cv_fov, 83}, - - {IT_HEADER, NULL, "Miscellaneous", NULL, 102}, - {IT_STRING|IT_CVAR, NULL, "Bit depth", &cv_scr_depth, 114}, - {IT_STRING|IT_CVAR, NULL, "Texture filter", &cv_glfiltermode, 124}, - {IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_glanisotropicmode, 134}, + {IT_STRING|IT_CVAR, NULL, "Palette rendering", &cv_glpaletterendering, 73}, + {IT_STRING|IT_CVAR, NULL, "Lack of perspective", &cv_glshearing, 83}, + {IT_STRING|IT_CVAR, NULL, "Field of view", &cv_fov, 93}, + + {IT_HEADER, NULL, "Miscellaneous", NULL, 112}, + {IT_STRING|IT_CVAR, NULL, "Bit depth", &cv_scr_depth, 124}, + {IT_STRING|IT_CVAR, NULL, "Texture filter", &cv_glfiltermode, 134}, + {IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_glanisotropicmode, 144}, #ifdef ALAM_LIGHTING - {IT_SUBMENU|IT_STRING, NULL, "Lighting...", &OP_OpenGLLightingDef, 144}, + {IT_SUBMENU|IT_STRING, NULL, "Lighting...", &OP_OpenGLLightingDef, 154}, #endif #if defined (_WINDOWS) && (!(defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL))) - {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 154}, + {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 164}, #endif }; @@ -2094,6 +2097,12 @@ menu_t OP_PlaystyleDef = { 0, 0, 0, NULL }; +static void M_UpdateItemOn(void) +{ + I_SetTextInputMode((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_STRING || + (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_KEYHANDLER); +} + static void M_VideoOptions(INT32 choice) { (void)choice; @@ -2321,6 +2330,7 @@ void Nextmap_OnChange(void) { currentMenu->lastOn = itemOn; itemOn = nastart; + M_UpdateItemOn(); } } else if (currentMenu == &SP_TimeAttackDef) @@ -2370,6 +2380,7 @@ void Nextmap_OnChange(void) { currentMenu->lastOn = itemOn; itemOn = tastart; + M_UpdateItemOn(); } if (mapheaderinfo[cv_nextmap.value-1] && mapheaderinfo[cv_nextmap.value-1]->forcecharacter[0] != '\0') @@ -2691,7 +2702,7 @@ static boolean MIT_SetCurTitlePics(UINT32 menutype, INT32 level, INT32 *retval, curhidepics = menupres[menutype].hidetitlepics; curttmode = menupres[menutype].ttmode; curttscale = (menupres[menutype].ttscale != UINT8_MAX ? menupres[menutype].ttscale : ttscale); - strncpy(curttname, menupres[menutype].ttname, 9); + strncpy(curttname, menupres[menutype].ttname, sizeof(curttname)-1); curttx = (menupres[menutype].ttx != INT16_MAX ? menupres[menutype].ttx : ttx); curtty = (menupres[menutype].tty != INT16_MAX ? menupres[menutype].tty : tty); curttloop = (menupres[menutype].ttloop != INT16_MAX ? menupres[menutype].ttloop : ttloop); @@ -3120,6 +3131,7 @@ static void M_NextOpt(void) else itemOn++; } while (oldItemOn != itemOn && ( (currentMenu->menuitems[itemOn].status & IT_TYPE) & IT_SPACE )); + M_UpdateItemOn(); } static void M_PrevOpt(void) @@ -3132,6 +3144,7 @@ static void M_PrevOpt(void) else itemOn--; } while (oldItemOn != itemOn && ( (currentMenu->menuitems[itemOn].status & IT_TYPE) & IT_SPACE )); + M_UpdateItemOn(); } // lock out further input in a tic when important buttons are pressed @@ -3298,7 +3311,7 @@ boolean M_Responder(event_t *ev) if (ch == -1) return false; - else if (ch == gamecontrol[GC_SYSTEMMENU][0] || ch == gamecontrol[GC_SYSTEMMENU][1]) // allow remappable ESC key + else if (ev->type != ev_text && (ch == gamecontrol[GC_SYSTEMMENU][0] || ch == gamecontrol[GC_SYSTEMMENU][1])) // allow remappable ESC key ch = KEY_ESCAPE; // F-Keys @@ -3376,9 +3389,16 @@ boolean M_Responder(event_t *ev) // Handle menuitems which need a specific key handling if (routine && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_KEYHANDLER) { + // block text input if ctrl is held, to allow using ctrl+c ctrl+v and ctrl+x + if (ctrldown) + { + routine(ch); + return true; + } + // ignore ev_keydown events if the key maps to a character, since // the ev_text event will follow immediately after in that case. - if (ev->type == ev_keydown && ch >= 32 && ch <= 127) + if (ev->type == ev_keydown && ((ch >= 32 && ch <= 127) || (ch >= KEY_KEYPAD7 && ch <= KEY_KPADDEL))) return true; routine(ch); @@ -3406,7 +3426,7 @@ boolean M_Responder(event_t *ev) { // dirty hack: for customising controls, I want only buttons/keys, not moves if (ev->type == ev_mouse || ev->type == ev_mouse2 || ev->type == ev_joystick - || ev->type == ev_joystick2) + || ev->type == ev_joystick2 || ev->type == ev_text) return true; if (routine) { @@ -3425,7 +3445,7 @@ boolean M_Responder(event_t *ev) // ignore ev_keydown events if the key maps to a character, since // the ev_text event will follow immediately after in that case. if (ev->type == ev_keydown && ch >= 32 && ch <= 127) - return false; + return true; if (M_ChangeStringCvar(ch)) return true; @@ -3643,21 +3663,27 @@ void M_StartControlPanel(void) currentMenu = &MainDef; itemOn = singleplr; + M_UpdateItemOn(); } else if (modeattacking) { currentMenu = &MAPauseDef; MAPauseMenu[mapause_hints].status = (M_SecretUnlocked(SECRET_EMBLEMHINTS, clientGamedata)) ? (IT_STRING | IT_CALL) : (IT_DISABLED); itemOn = mapause_continue; + M_UpdateItemOn(); } else if (!(netgame || multiplayer)) // Single Player { - // Devmode unlocks Pandora's Box in the pause menu - boolean pandora = ((M_SecretUnlocked(SECRET_PANDORA, serverGamedata) || cv_debug || devparm) && !marathonmode); - - if (gamestate != GS_LEVEL || ultimatemode) // intermission, so gray out stuff. + // Devmode unlocks Pandora's Box and Level Select in the pause menu + boolean isforbidden = (marathonmode || ultimatemode); + boolean isdebug = ((cv_debug || devparm) && !isforbidden); + boolean pandora = ((M_SecretUnlocked(SECRET_PANDORA, serverGamedata) && !isforbidden) || isdebug); + boolean lselect = ((maplistoption != 0 && !isforbidden) || isdebug); + + if (gamestate != GS_LEVEL) // intermission, so gray out stuff. { SPauseMenu[spause_pandora].status = (pandora) ? (IT_GRAYEDOUT) : (IT_DISABLED); + SPauseMenu[spause_levelselect].status = (lselect) ? (IT_STRING | IT_CALL) : (IT_DISABLED); SPauseMenu[spause_retry].status = IT_GRAYEDOUT; } else @@ -3667,6 +3693,11 @@ void M_StartControlPanel(void) ++numlives; SPauseMenu[spause_pandora].status = (pandora) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + SPauseMenu[spause_levelselect].status = (lselect) ? (IT_STRING | IT_CALL) : (IT_DISABLED); + if (ultimatemode) + { + SPauseMenu[spause_retry].status = IT_GRAYEDOUT; + } // The list of things that can disable retrying is (was?) a little too complex // for me to want to use the short if statement syntax @@ -3676,13 +3707,6 @@ void M_StartControlPanel(void) SPauseMenu[spause_retry].status = (IT_STRING | IT_CALL); } - // We can always use level select though. :33 - // Guarantee it if we have either it unlocked or devmode is enabled - if ((maplistoption != 0 || M_SecretUnlocked(SECRET_LEVELSELECT, serverGamedata) || cv_debug || devparm) && !marathonmode) - SPauseMenu[spause_levelselect].status = (IT_STRING | IT_CALL); - else - SPauseMenu[spause_levelselect].status = (IT_DISABLED); - // And emblem hints. SPauseMenu[spause_hints].status = (M_SecretUnlocked(SECRET_EMBLEMHINTS, clientGamedata) && !marathonmode) ? (IT_STRING | IT_CALL) : (IT_DISABLED); @@ -3695,6 +3719,7 @@ void M_StartControlPanel(void) currentMenu = &SPauseDef; itemOn = spause_continue; + M_UpdateItemOn(); } else // multiplayer { @@ -3736,6 +3761,7 @@ void M_StartControlPanel(void) currentMenu = &MPauseDef; itemOn = mpause_continue; + M_UpdateItemOn(); } CON_ToggleOff(); // move away console @@ -3829,6 +3855,7 @@ void M_SetupNextMenu(menu_t *menudef) } } } + M_UpdateItemOn(); hidetitlemap = false; } @@ -4007,11 +4034,11 @@ static void M_DrawThermo(INT32 x, INT32 y, consvar_t *cv) lumpnum_t leftlump, rightlump, centerlump[2], cursorlump; patch_t *p; - leftlump = W_GetNumForName("M_THERML"); - rightlump = W_GetNumForName("M_THERMR"); - centerlump[0] = W_GetNumForName("M_THERMM"); - centerlump[1] = W_GetNumForName("M_THERMM"); - cursorlump = W_GetNumForName("M_THERMO"); + leftlump = W_GetNumForPatchName("M_THERML"); + rightlump = W_GetNumForPatchName("M_THERMR"); + centerlump[0] = W_GetNumForPatchName("M_THERMM"); + centerlump[1] = W_GetNumForPatchName("M_THERMM"); + cursorlump = W_GetNumForPatchName("M_THERMO"); V_DrawScaledPatch(xx, y, 0, p = W_CachePatchNum(leftlump,PU_PATCH)); xx += p->width - p->leftoffset; @@ -4098,53 +4125,6 @@ void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines) { // Solid color textbox. V_DrawFill(x+5, y+5, width*8+6, boxlines*8+6, 159); - //V_DrawFill(x+8, y+8, width*8, boxlines*8, 31); -/* - patch_t *p; - INT32 cx, cy, n; - INT32 step, boff; - - step = 8; - boff = 8; - - // draw left side - cx = x; - cy = y; - V_DrawScaledPatch(cx, cy, 0, W_CachePatchNum(viewborderlump[BRDR_TL], PU_PATCH)); - cy += boff; - p = W_CachePatchNum(viewborderlump[BRDR_L], PU_PATCH); - for (n = 0; n < boxlines; n++) - { - V_DrawScaledPatch(cx, cy, 0, p); - cy += step; - } - V_DrawScaledPatch(cx, cy, 0, W_CachePatchNum(viewborderlump[BRDR_BL], PU_PATCH)); - - // draw middle - V_DrawFlatFill(x + boff, y + boff, width*step, boxlines*step, st_borderpatchnum); - - cx += boff; - cy = y; - while (width > 0) - { - V_DrawScaledPatch(cx, cy, 0, W_CachePatchNum(viewborderlump[BRDR_T], PU_PATCH)); - V_DrawScaledPatch(cx, y + boff + boxlines*step, 0, W_CachePatchNum(viewborderlump[BRDR_B], PU_PATCH)); - width--; - cx += step; - } - - // draw right side - cy = y; - V_DrawScaledPatch(cx, cy, 0, W_CachePatchNum(viewborderlump[BRDR_TR], PU_PATCH)); - cy += boff; - p = W_CachePatchNum(viewborderlump[BRDR_R], PU_PATCH); - for (n = 0; n < boxlines; n++) - { - V_DrawScaledPatch(cx, cy, 0, p); - cy += step; - } - V_DrawScaledPatch(cx, cy, 0, W_CachePatchNum(viewborderlump[BRDR_BR], PU_PATCH)); -*/ } // @@ -4180,7 +4160,7 @@ static void M_DrawStaticBox(fixed_t x, fixed_t y, INT32 flags, fixed_t w, fixed_ temp = (gametic % temp) * h*2*FRACUNIT; // Which frame to draw V_DrawCroppedPatch(x*FRACUNIT, y*FRACUNIT, (w*FRACUNIT) / 160, (h*FRACUNIT) / 100, flags, patch, NULL, 0, temp, w*2*FRACUNIT, h*2*FRACUNIT); - + W_UnlockCachedPatch(patch); return; } @@ -4998,22 +4978,6 @@ static void M_DrawCenteredMenu(void) } } -// -// M_StringHeight -// -// Find string height from hu_font chars -// -static inline size_t M_StringHeight(const char *string) -{ - size_t h = 8, i; - - for (i = 0; i < strlen(string); i++) - if (string[i] == '\n') - h += 8; - - return h; -} - // ========================================================================== // Extraneous menu patching functions // ========================================================================== @@ -6131,56 +6095,16 @@ menu_t MessageDef = NULL }; - -void M_StartMessage(const char *string, void *routine, - menumessagetype_t itemtype) +void M_StartMessage(const char *string, void *routine, menumessagetype_t itemtype) { - size_t max = 0, start = 0, i, strlines; - static char *message = NULL; + static char *message; Z_Free(message); - message = Z_StrDup(string); + message = V_WordWrap(0,0,V_ALLOWLOWERCASE,string); DEBFILE(message); - // Rudementary word wrapping. - // Simple and effective. Does not handle nonuniform letter sizes, colors, etc. but who cares. - strlines = 0; - for (i = 0; message[i]; i++) - { - if (message[i] == ' ') - { - start = i; - max += 4; - } - else if (message[i] == '\n') - { - strlines = i; - start = 0; - max = 0; - continue; - } - else - max += 8; - - // Start trying to wrap if presumed length exceeds the screen width. - if (max >= BASEVIDWIDTH && start > 0) - { - message[start] = '\n'; - max -= (start-strlines)*8; - strlines = start; - start = 0; - } - } - - start = 0; - max = 0; - M_StartControlPanel(); // can't put menuactive to true - if (currentMenu == &MessageDef) // Prevent recursion - MessageDef.prevMenu = &MainDef; - else - MessageDef.prevMenu = currentMenu; - + MessageDef.prevMenu = (currentMenu == &MessageDef) ? &MainDef : currentMenu; // Prevent recursion MessageDef.menuitems[0].text = message; MessageDef.menuitems[0].alphaKey = (UINT8)itemtype; if (!routine && itemtype != MM_NOTHING) itemtype = MM_NOTHING; @@ -6199,51 +6123,18 @@ void M_StartMessage(const char *string, void *routine, MessageDef.menuitems[0].itemaction = routine; break; } - //added : 06-02-98: now draw a textbox around the message - // compute lenght max and the numbers of lines - for (strlines = 0; *(message+start); strlines++) - { - for (i = 0;i < strlen(message+start);i++) - { - if (*(message+start+i) == '\n') - { - if (i > max) - max = i; - start += i; - i = (size_t)-1; //added : 07-02-98 : damned! - start++; - break; - } - } + MessageDef.x = (INT16)((BASEVIDWIDTH - V_StringWidth(message, 0)-32)/2); + MessageDef.y = (INT16)((BASEVIDHEIGHT - V_StringHeight(message, V_RETURN8))/2); - if (i == strlen(message+start)) - start += i; - } - - MessageDef.x = (INT16)((BASEVIDWIDTH - 8*max-16)/2); - MessageDef.y = (INT16)((BASEVIDHEIGHT - M_StringHeight(message))/2); - - MessageDef.lastOn = (INT16)((strlines<<8)+max); - - //M_SetupNextMenu(); currentMenu = &MessageDef; itemOn = 0; + M_UpdateItemOn(); } -#define MAXMSGLINELEN 256 - static void M_DrawMessageMenu(void) { - INT32 y = currentMenu->y; - size_t i, start = 0; - INT16 max; - char string[MAXMSGLINELEN]; - INT32 mlines; const char *msg = currentMenu->menuitems[0].text; - mlines = currentMenu->lastOn>>8; - max = (INT16)((UINT8)(currentMenu->lastOn & 0xFF)*8); - // hack: draw RA background in RA menus if (gamestate == GS_TIMEATTACK) { @@ -6267,51 +6158,8 @@ static void M_DrawMessageMenu(void) V_DrawFadeScreen(0xFF00, curfadevalue); } - M_DrawTextBox(currentMenu->x, y - 8, (max+7)>>3, mlines); - - while (*(msg+start)) - { - size_t len = strlen(msg+start); - - for (i = 0; i < len; i++) - { - if (*(msg+start+i) == '\n') - { - memset(string, 0, MAXMSGLINELEN); - if (i >= MAXMSGLINELEN) - { - CONS_Printf("M_DrawMessageMenu: too long segment in %s\n", msg); - return; - } - else - { - strncpy(string,msg+start, i); - string[i] = '\0'; - start += i; - i = (size_t)-1; //added : 07-02-98 : damned! - start++; - } - break; - } - } - - if (i == strlen(msg+start)) - { - if (i >= MAXMSGLINELEN) - { - CONS_Printf("M_DrawMessageMenu: too long segment in %s\n", msg); - return; - } - else - { - strcpy(string, msg + start); - start += i; - } - } - - V_DrawString((BASEVIDWIDTH - V_StringWidth(string, 0))/2,y,V_ALLOWLOWERCASE,string); - y += 8; //hu_font[0]->height; - } + M_DrawTextBox(currentMenu->x, currentMenu->y - 8, 2+V_StringWidth(msg, 0)/8, V_StringHeight(msg, V_RETURN8)/8); + V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y, V_ALLOWLOWERCASE|V_RETURN8, msg); } // default message handler @@ -6355,6 +6203,7 @@ static void M_HandleImageDef(INT32 choice) if (itemOn >= (INT16)(currentMenu->numitems-1)) itemOn = 0; else itemOn++; + M_UpdateItemOn(); break; case KEY_LEFTARROW: @@ -6365,6 +6214,7 @@ static void M_HandleImageDef(INT32 choice) if (!itemOn) itemOn = currentMenu->numitems - 1; else itemOn--; + M_UpdateItemOn(); break; case KEY_ESCAPE: @@ -7154,7 +7004,10 @@ static void M_LevelSelectWarp(INT32 choice) if (currentMenu == &SP_LevelSelectDef || currentMenu == &SP_PauseLevelSelectDef) { if (cursaveslot > 0) // do we have a save slot to load? + { + CV_StealthSet(&cv_skin, DEFAULTSKIN); // already handled by loadgame so we don't want this G_LoadGame((UINT32)cursaveslot, startmap); // reload from SP save data: this is needed to keep score/lives/continues from reverting to defaults + } else // no save slot, start new game but keep the current skin { M_ClearMenus(true); @@ -7561,6 +7414,7 @@ static void M_EmblemHints(INT32 choice) SR_EmblemHintDef.prevMenu = currentMenu; M_SetupNextMenu(&SR_EmblemHintDef); itemOn = 2; // always start on back. + M_UpdateItemOn(); } static void M_DrawEmblemHints(void) @@ -7693,13 +7547,9 @@ static void M_PauseLevelSelect(INT32 choice) SP_PauseLevelSelectDef.prevMenu = currentMenu; levellistmode = LLM_LEVELSELECT; - // maplistoption is only specified if not set already - // and we have the level select unlocked so that it + // maplistoption is NOT specified, so that this // transfers the level select list from the menu // used to enter the game to the pause menu. - if (maplistoption == 0 && M_SecretUnlocked(SECRET_LEVELSELECT, serverGamedata)) - maplistoption = 1; - if (!M_PrepareLevelPlatter(-1, true)) { M_StartMessage(M_GetText("No selectable levels found.\n"),NULL,MM_NOTHING); @@ -7998,7 +7848,7 @@ static void M_DrawSoundTest(void) { V_DrawFill(165+140-9, y-4, 8, 16, 150); //V_DrawCharacter(165+140-8, y, '\x19' | V_YELLOWMAP, false); - V_DrawFixedPatch((165+140-9)<<FRACBITS, (y<<FRACBITS)-(bounce*4), FRACUNIT, 0, hu_font['\x19'-HU_FONTSTART], V_GetStringColormap(V_YELLOWMAP)); + V_DrawFixedPatch((165+140-9)<<FRACBITS, (y<<FRACBITS)-(bounce*4), FRACUNIT, 0, hu_font.chars['\x19'-FONTSTART], V_GetStringColormap(V_YELLOWMAP)); } } t++; @@ -8423,6 +8273,7 @@ static void M_StartTutorial(INT32 choice) gamecomplete = 0; cursaveslot = 0; maplistoption = 0; + CV_StealthSet(&cv_skin, DEFAULTSKIN); // tutorial accounts for sonic only G_DeferedInitNew(false, G_BuildMapName(tutorialmap), 0, false, false); } @@ -8522,7 +8373,7 @@ static void M_DrawLoadGameData(void) if (savegameinfo[savetodraw].lives == -42) col = 26; else if (savegameinfo[savetodraw].botskin == 3) // & knuckles - col = 105; + col = 106; else if (savegameinfo[savetodraw].botskin) // tailsbot or custom col = 134; else @@ -8582,7 +8433,17 @@ static void M_DrawLoadGameData(void) if (savegameinfo[savetodraw].lives == -42) V_DrawRightAlignedThinString(x + 79, y, V_GRAYMAP, "NEW GAME"); else if (savegameinfo[savetodraw].lives == -666) - V_DrawRightAlignedThinString(x + 79, y, V_REDMAP, "CAN'T LOAD!"); + { + if (savegameinfo[savetodraw].continuescore == -62) + { + V_DrawRightAlignedThinString(x + 79, y, V_REDMAP, "ADDON NOT LOADED"); + V_DrawRightAlignedThinString(x + 79, y-10, V_REDMAP, savegameinfo[savetodraw].skinname); + } + else + { + V_DrawRightAlignedThinString(x + 79, y, V_REDMAP, "CAN'T LOAD!"); + } + } else if (savegameinfo[savetodraw].gamemap & 8192) V_DrawRightAlignedThinString(x + 79, y, V_GREENMAP, "CLEAR!"); else @@ -8802,14 +8663,20 @@ static void M_LoadSelect(INT32 choice) M_NewGame(); } else if (savegameinfo[saveSlotSelected-1].gamemap & 8192) // Completed + { M_LoadGameLevelSelect(0); + } else + { + CV_StealthSet(&cv_skin, DEFAULTSKIN); // already handled by loadgame so we don't want this G_LoadGame((UINT32)saveSlotSelected, 0); + } cursaveslot = saveSlotSelected; } #define VERSIONSIZE 16 +#define MISSING { savegameinfo[slot].continuescore = -62; savegameinfo[slot].lives = -666; Z_Free(savebuffer); return; } #define BADSAVE { savegameinfo[slot].lives = -666; Z_Free(savebuffer); return; } #define CHECKPOS if (sav_p >= end_p) BADSAVE // Reads the save file to list lives, level, player, etc. @@ -8906,10 +8773,11 @@ static void M_ReadSavegameInfo(UINT32 slot) CHECKPOS READSTRINGN(sav_p, ourSkinName, SKINNAMESIZE); savegameinfo[slot].skinnum = R_SkinAvailable(ourSkinName); + STRBUFCPY(savegameinfo[slot].skinname, ourSkinName); if (savegameinfo[slot].skinnum >= numskins || !R_SkinUsable(-1, savegameinfo[slot].skinnum)) - BADSAVE + MISSING CHECKPOS READSTRINGN(sav_p, botSkinName, SKINNAMESIZE); @@ -8917,7 +8785,7 @@ static void M_ReadSavegameInfo(UINT32 slot) if (savegameinfo[slot].botskin-1 >= numskins || !R_SkinUsable(-1, savegameinfo[slot].botskin-1)) - BADSAVE + MISSING } CHECKPOS @@ -8962,6 +8830,7 @@ static void M_ReadSavegameInfo(UINT32 slot) } #undef CHECKPOS #undef BADSAVE +#undef MISSING // // M_ReadSaveStrings @@ -9225,7 +9094,7 @@ static void M_CacheCharacterSelectEntry(INT32 i, INT32 skinnum) description[i].namepic = W_CachePatchName(description[i].nametag, PU_PATCH); } -static UINT16 M_SetupChoosePlayerDirect(INT32 choice) +static INT32 M_SetupChoosePlayerDirect(INT32 choice) { INT32 skinnum, botskinnum; UINT16 i; @@ -9314,7 +9183,7 @@ static UINT16 M_SetupChoosePlayerDirect(INT32 choice) static void M_SetupChoosePlayer(INT32 choice) { - UINT16 skinset = M_SetupChoosePlayerDirect(choice); + INT32 skinset = M_SetupChoosePlayerDirect(choice); if (skinset != MAXCHARACTERSLOTS) { M_ChoosePlayer(skinset); @@ -9663,6 +9532,8 @@ static void M_ChoosePlayer(INT32 choice) //lastmapsaved = 0; gamecomplete = 0; + CV_StealthSet(&cv_skin, skins[skinnum]->name); + G_DeferedInitNew(ultmode, G_BuildMapName(startmap), skinnum, false, fromlevelselect); COM_BufAddText("dummyconsvar 1\n"); // G_DeferedInitNew doesn't do this @@ -10222,6 +10093,7 @@ static void M_TimeAttack(INT32 choice) Nextmap_OnChange(); itemOn = tastart; // "Start" is selected. + M_UpdateItemOn(); } // Drawing function for Nights Attack @@ -10338,7 +10210,7 @@ void M_DrawNightsAttackMenu(void) skinnumber = 0; //Default to Sonic else skinnumber = (cv_chooseskin.value-1); - + spritedef_t *sprdef = &skins[skinnumber]->sprites[SPR2_NFLY]; //Make our patch the selected character's NFLY sprite spritetimer = FixedInt(ntsatkdrawtimer/2) % skins[skinnumber]->sprites[SPR2_NFLY].numframes; //Make the sprite timer cycle though all the frames at 2 tics per frame spriteframe_t *sprframe = &sprdef->spriteframes[spritetimer]; //Our animation frame is equal to the number on the timer @@ -10351,11 +10223,14 @@ void M_DrawNightsAttackMenu(void) color = skins[skinnumber]->supercolor+4; else //If you don't go super in NiGHTS or at all, use prefcolor color = skins[skinnumber]->prefcolor; - + angle_t fa = (FixedAngle(((FixedInt(ntsatkdrawtimer * 4)) % 360)<<FRACBITS)>>ANGLETOFINESHIFT) & FINEMASK; + fixed_t scale = skins[skinnumber]->highresscale; + if (skins[skinnumber]->shieldscale) + scale = FixedDiv(scale, skins[skinnumber]->shieldscale); V_DrawFixedPatch(270<<FRACBITS, (186<<FRACBITS) - 8*FINESINE(fa), - FixedDiv(skins[skinnumber]->highresscale, skins[skinnumber]->shieldscale), + scale, (sprframe->flip & 1<<6) ? V_FLIP : 0, natksprite, R_GetTranslationColormap(TC_BLINK, color, GTC_CACHE)); @@ -10460,6 +10335,7 @@ static void M_NightsAttack(INT32 choice) Nextmap_OnChange(); itemOn = nastart; // "Start" is selected. + M_UpdateItemOn(); } // Player has selected the "START" from the nights attack screen @@ -10535,7 +10411,7 @@ static void M_StartTimeAttackReplay(INT32 choice) // Player has selected the "REPLAY" from the time attack screen static void M_ReplayTimeAttack(INT32 choice) { - const char *which; + const char *which = NULL; UINT8 error = DFILE_ERROR_NONE; if (currentMenu == &SP_ReplayDef) @@ -10779,6 +10655,7 @@ static void M_ModeAttackEndGame(INT32 choice) break; } itemOn = currentMenu->lastOn; + M_UpdateItemOn(); G_SetGamestate(GS_TIMEATTACK); modeattacking = ATTACKING_NONE; M_ChangeMenuMusic("_title", true); @@ -10860,6 +10737,7 @@ static void M_Marathon(INT32 choice) titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please M_SetupNextMenu(&SP_MarathonDef); itemOn = marathonstart; // "Start" is selected. + M_UpdateItemOn(); recatkdrawtimer = (50-8) * FRACUNIT; char_scroll = 0; } @@ -11250,7 +11128,7 @@ static void M_Refresh(INT32 choice) // note: this is the one case where 0 is a valid room number // because it corresponds to "All" - CL_UpdateServerList(!(ms_RoomId < 0), ms_RoomId); + CL_UpdateServerList(cv_masterserver_room_id.value >= 0, cv_masterserver_room_id.value); // first page of servers serverlistpage = 0; @@ -11281,7 +11159,8 @@ static void M_DrawRoomMenu(void) if (dot_frame < 0) dot_frame = 0; - strncpy(&text[dot_frame], "...", min(dots, 3 - dot_frame)); + if (dot_frame != 3) + strncpy(&text[dot_frame], "...", min(dots, 3 - dot_frame)); } frame += renderdeltatics; @@ -11335,7 +11214,7 @@ static void M_DrawConnectMenu(void) numPages = 1; // Room name - if (ms_RoomId < 0) + if (cv_masterserver_room_id.value < 0) V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ConnectMenu[mp_connect_room].alphaKey, V_YELLOWMAP, (itemOn == mp_connect_room) ? "<Select to change>" : "<Unlisted Mode>"); else @@ -11563,7 +11442,7 @@ static void M_ConnectMenu(INT32 choice) // first page of servers serverlistpage = 0; - if (ms_RoomId < 0) + if (cv_masterserver_room_id.value < 0) { M_RoomMenu(0); // Select a room instead of staring at an empty list // This prevents us from returning to the modified game alert. @@ -11572,6 +11451,7 @@ static void M_ConnectMenu(INT32 choice) else M_SetupNextMenu(&MP_ConnectDef); itemOn = 0; + M_UpdateItemOn(); M_Refresh(0); } @@ -11658,10 +11538,10 @@ static void M_ChooseRoom(INT32 choice) #endif if (choice == 0) - ms_RoomId = -1; + CV_SetValue(&cv_masterserver_room_id, -1); else { - ms_RoomId = roomIds[choice-1]; + CV_SetValue(&cv_masterserver_room_id, roomIds[choice-1]); menuRoomIndex = choice - 1; } @@ -11730,7 +11610,7 @@ static void M_DrawServerMenu(void) if (currentMenu == &MP_ServerDef) { M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight/2, "Server settings", true, false); - if (ms_RoomId < 0) + if (cv_masterserver_room_id.value < 0) V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey, V_YELLOWMAP, (itemOn == mp_server_room) ? "<Select to change>" : "<Unlisted Mode>"); else @@ -11826,11 +11706,12 @@ static void M_ServerOptions(INT32 choice) static void M_StartServerMenu(INT32 choice) { (void)choice; - ms_RoomId = -1; + CV_SetValue(&cv_masterserver_room_id, -1); levellistmode = LLM_CREATESERVER; Newgametype_OnChange(); M_SetupNextMenu(&MP_ServerDef); itemOn = 1; + M_UpdateItemOn(); } // ============== @@ -11997,8 +11878,7 @@ static void M_HandleConnectIP(INT32 choice) if ( ctrldown ) { switch (choice) { - case 'v': - case 'V': // ctrl+v, pasting + case 'v': // ctrl+v, pasting { const char *paste = I_ClipboardPaste(); @@ -12011,17 +11891,21 @@ static void M_HandleConnectIP(INT32 choice) break; } case KEY_INS: - case 'c': - case 'C': // ctrl+c, ctrl+insert, copying - I_ClipboardCopy(setupm_ip, l); - S_StartSound(NULL,sfx_menu1); // Tails + case 'c': // ctrl+c, ctrl+insert, copying + if (l != 0) // Don't replace the clipboard without any text + { + I_ClipboardCopy(setupm_ip, l); + S_StartSound(NULL,sfx_menu1); // Tails + } break; - case 'x': - case 'X': // ctrl+x, cutting - I_ClipboardCopy(setupm_ip, l); - S_StartSound(NULL,sfx_menu1); // Tails - setupm_ip[0] = 0; + case 'x': // ctrl+x, cutting + if (l != 0) // Don't replace the clipboard without any text + { + I_ClipboardCopy(setupm_ip, l); + S_StartSound(NULL,sfx_menu1); // Tails + setupm_ip[0] = 0; + } break; default: // otherwise do nothing @@ -12045,9 +11929,12 @@ static void M_HandleConnectIP(INT32 choice) break; } case KEY_DEL: // shift+delete, cutting - I_ClipboardCopy(setupm_ip, l); - S_StartSound(NULL,sfx_menu1); // Tails - setupm_ip[0] = 0; + if (l != 0) // Don't replace the clipboard without any text + { + I_ClipboardCopy(setupm_ip, l); + S_StartSound(NULL,sfx_menu1); // Tails + setupm_ip[0] = 0; + } break; default: // otherwise do nothing. break; @@ -12068,15 +11955,6 @@ static void M_HandleConnectIP(INT32 choice) setupm_ip[l] = (char)choice; setupm_ip[l+1] = 0; } - else if (choice >= 199 && choice <= 211 && choice != 202 && choice != 206) //numpad too! - { - char keypad_translation[] = {'7','8','9','-','4','5','6','+','1','2','3','0','.'}; - choice = keypad_translation[choice - 199]; - S_StartSound(NULL,sfx_menu1); // Tails - setupm_ip[l] = (char)choice; - setupm_ip[l+1] = 0; - } - break; } @@ -12097,9 +11975,22 @@ static void M_HandleConnectIP(INT32 choice) static fixed_t multi_tics; static UINT8 multi_frame; -static UINT8 multi_spr2; +static UINT16 multi_spr2; static boolean multi_paused; static boolean multi_invcolor; +static boolean multi_override; + +static spritedef_t *multi_followitem_sprdef; +static INT32 multi_followitem_skinnum; +static UINT8 multi_followitem_numframes; +static UINT8 multi_followitem_startframe; +static UINT8 multi_followitem_frame; +static fixed_t multi_followitem_duration; +static fixed_t multi_followitem_tics; +static fixed_t multi_followitem_scale; +static fixed_t multi_followitem_yoffset; + +#define MULTI_DURATION (4*FRACUNIT) // this is set before entering the MultiPlayer setup menu, // for either player 1 or 2 @@ -12244,9 +12135,92 @@ static menucolor_t *M_GridIndexToMenuColor(UINT16 index) } } +static void M_SetPlayerSetupFollowItem(void) +{ + const mobjtype_t followitem = skins[setupm_fakeskin]->followitem; + + switch (followitem) + { + case MT_TAILSOVERLAY: + { + const state_t *state = &states[S_TAILSOVERLAY_MINUS30DEGREES]; + const UINT8 sprite2 = P_GetSkinSprite2(skins[setupm_fakeskin], state->frame & FF_FRAMEMASK, NULL); + + if (state->sprite != SPR_PLAY) + break; + + multi_followitem_sprdef = &skins[setupm_fakeskin]->sprites[sprite2]; + multi_followitem_skinnum = setupm_fakeskin; + multi_followitem_numframes = multi_followitem_sprdef->numframes; + multi_followitem_startframe = 0; + multi_followitem_frame = multi_frame; + multi_followitem_duration = MULTI_DURATION; + multi_followitem_tics = multi_tics; + multi_followitem_scale = FRACUNIT; + multi_followitem_yoffset = 0; + + if ((state->frame & FF_SPR2MIDSTART) && (multi_followitem_numframes > 0) && M_RandomChance(FRACUNIT / 2)) + { + multi_followitem_frame += multi_followitem_numframes / 2; + } + break; + } + case MT_METALJETFUME: + { + const state_t *state = &states[S_JETFUME1]; + + if (!(state->frame & FF_ANIMATE)) + break; + + multi_followitem_sprdef = &sprites[state->sprite]; + multi_followitem_skinnum = TC_DEFAULT; + multi_followitem_numframes = state->var1 + 1; + multi_followitem_startframe = state->frame & FF_FRAMEMASK; + multi_followitem_frame = multi_followitem_startframe; + multi_followitem_duration = state->var2 * FRACUNIT; + multi_followitem_tics = multi_tics % multi_followitem_duration; + multi_followitem_scale = 2 * FRACUNIT / 3; + multi_followitem_yoffset = (skins[setupm_fakeskin]->height - FixedMul(mobjinfo[followitem].height, multi_followitem_scale)) >> 1; + break; + } + default: + multi_followitem_sprdef = NULL; + break; + } +} + +static void M_DrawPlayerSetupFollowItem(INT32 x, INT32 y, fixed_t scale, INT32 flags) +{ + spriteframe_t *sprframe; + patch_t *patch; + UINT8 *colormap; + + if (multi_followitem_sprdef == NULL) + return; + + if (multi_followitem_frame >= multi_followitem_startframe + multi_followitem_numframes) + multi_followitem_frame = multi_followitem_startframe; + + colormap = R_GetTranslationColormap(multi_followitem_skinnum, setupm_fakecolor->color, GTC_CACHE); + + sprframe = &multi_followitem_sprdef->spriteframes[multi_followitem_frame]; + patch = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); + if (sprframe->flip & 1) // Only for first sprite + flags |= V_FLIP; // This sprite is left/right flipped! + + x <<= FRACBITS; + y <<= FRACBITS; + y -= FixedMul(multi_followitem_yoffset, scale); + + scale = FixedMul(scale, multi_followitem_scale); + + V_DrawFixedPatch(x, y, scale, flags, patch, colormap); +} + static void M_DrawSetupMultiPlayerMenu(void) { INT32 x, y, cursory = 0, flags = 0; + fixed_t scale; spritedef_t *sprdef; spriteframe_t *sprframe; patch_t *patch; @@ -12296,11 +12270,24 @@ static void M_DrawSetupMultiPlayerMenu(void) y += 11; // anim the player in the box - multi_tics -= renderdeltatics; - while (!multi_paused && multi_tics <= 0) + if (!multi_paused) { - multi_frame++; - multi_tics += 4*FRACUNIT; + multi_tics -= renderdeltatics; + while (multi_tics <= 0) + { + multi_frame++; + multi_tics += MULTI_DURATION; + } + + if (multi_followitem_sprdef != NULL) + { + multi_followitem_tics -= renderdeltatics; + while (multi_followitem_tics <= 0) + { + multi_followitem_frame++; + multi_followitem_tics += multi_followitem_duration; + } + } } #define charw 74 @@ -12315,22 +12302,45 @@ static void M_DrawSetupMultiPlayerMenu(void) goto faildraw; // ok, draw player sprite for sure now - colormap = R_GetTranslationColormap(setupm_fakeskin, setupm_fakecolor->color, GTC_CACHE); - if (multi_frame >= sprdef->numframes) multi_frame = 0; + scale = skins[setupm_fakeskin]->highresscale; + if (skins[setupm_fakeskin]->shieldscale) + scale = FixedDiv(scale, skins[setupm_fakeskin]->shieldscale); + +#define chary (y+64) + + if (renderisnewtic) + { + LUA_HUD_ClearDrawList(luahuddrawlist_playersetup); + multi_override = LUA_HookCharacterHUD + ( + HUD_HOOK(playersetup), luahuddrawlist_playersetup, setupm_player, + x << FRACBITS, chary << FRACBITS, scale, + setupm_fakeskin, multi_spr2, multi_frame, 1, setupm_fakecolor->color, + (multi_tics >> FRACBITS) + 1, multi_paused + ); + } + + LUA_HUD_DrawList(luahuddrawlist_playersetup); + + if (multi_override == true) + goto colordraw; + + colormap = R_GetTranslationColormap(setupm_fakeskin, setupm_fakecolor->color, GTC_CACHE); + sprframe = &sprdef->spriteframes[multi_frame]; patch = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); if (sprframe->flip & 1) // Only for first sprite flags |= V_FLIP; // This sprite is left/right flipped! -#define chary (y+64) + M_DrawPlayerSetupFollowItem(x, chary, scale, flags & ~V_FLIP); V_DrawFixedPatch( x<<FRACBITS, chary<<FRACBITS, - FixedDiv(skins[setupm_fakeskin]->highresscale, skins[setupm_fakeskin]->shieldscale), + scale, flags, patch, colormap); goto colordraw; @@ -12518,6 +12528,20 @@ static void M_DrawColorRamp(INT32 x, INT32 y, INT32 w, INT32 h, skincolor_t colo V_DrawFill(x, y+(i*h), w, h, color.ramp[i]); } +static void M_InitPlayerSetupLua(void) +{ + // I'd really like to assume that the drawlist has been destroyed, + // but it appears M_ClearMenus has options not to call exit routines... + // so that doesn't seem safe to me?? + if (!LUA_HUD_IsDrawListValid(luahuddrawlist_playersetup)) + { + LUA_HUD_DestroyDrawList(luahuddrawlist_playersetup); + luahuddrawlist_playersetup = LUA_HUD_CreateDrawList(); + } + LUA_HUD_ClearDrawList(luahuddrawlist_playersetup); + multi_override = false; +} + // Handle 1P/2P MP Setup static void M_HandleSetupMultiPlayer(INT32 choice) { @@ -12563,6 +12587,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice) } while ((prev_setupm_fakeskin != setupm_fakeskin) && !(R_SkinUsable(-1, setupm_fakeskin))); multi_spr2 = P_GetSkinSprite2(skins[setupm_fakeskin], SPR2_WALK, NULL); + M_SetPlayerSetupFollowItem(); } else if (itemOn == 2) // player color { @@ -12603,6 +12628,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice) } while ((prev_setupm_fakeskin != setupm_fakeskin) && !(R_SkinUsable(-1, setupm_fakeskin))); multi_spr2 = P_GetSkinSprite2(skins[setupm_fakeskin], SPR2_WALK, NULL); + M_SetPlayerSetupFollowItem(); } else if (itemOn == 2) // player color { @@ -12723,7 +12749,7 @@ static void M_SetupMultiPlayer(INT32 choice) (void)choice; multi_frame = 0; - multi_tics = 4*FRACUNIT; + multi_tics = MULTI_DURATION; strcpy(setupm_name, cv_playername.string); @@ -12753,6 +12779,10 @@ static void M_SetupMultiPlayer(INT32 choice) MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER|IT_STRING); multi_spr2 = P_GetSkinSprite2(skins[setupm_fakeskin], SPR2_WALK, NULL); + M_SetPlayerSetupFollowItem(); + + // allocate and/or clear Lua player setup draw list + M_InitPlayerSetupLua(); MP_PlayerSetupDef.prevMenu = currentMenu; M_SetupNextMenu(&MP_PlayerSetupDef); @@ -12764,7 +12794,7 @@ static void M_SetupMultiPlayer2(INT32 choice) (void)choice; multi_frame = 0; - multi_tics = 4*FRACUNIT; + multi_tics = MULTI_DURATION; strcpy (setupm_name, cv_playername2.string); @@ -12794,6 +12824,10 @@ static void M_SetupMultiPlayer2(INT32 choice) MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER|IT_STRING); multi_spr2 = P_GetSkinSprite2(skins[setupm_fakeskin], SPR2_WALK, NULL); + M_SetPlayerSetupFollowItem(); + + // allocate and/or clear Lua player setup draw list + M_InitPlayerSetupLua(); MP_PlayerSetupDef.prevMenu = currentMenu; M_SetupNextMenu(&MP_PlayerSetupDef); @@ -12815,6 +12849,12 @@ static boolean M_QuitMultiPlayerMenu(void) // send color if changed if (setupm_fakecolor->color != setupm_cvcolor->value) COM_BufAddText (va("%s %d\n",setupm_cvcolor->name,setupm_fakecolor->color)); + + // de-allocate Lua player setup drawlist + LUA_HUD_DestroyDrawList(luahuddrawlist_playersetup); + luahuddrawlist_playersetup = NULL; + multi_override = false; + return true; } @@ -13082,7 +13122,10 @@ static void M_SetupScreenshotMenu(void) { item->status = IT_GRAYEDOUT; if ((currentMenu == &OP_ScreenshotOptionsDef) && (itemOn == op_screenshot_colorprofile)) // Can't select that + { itemOn = op_screenshot_storagelocation; + M_UpdateItemOn(); + } } else #endif @@ -13280,23 +13323,23 @@ static void M_Setup1PControlsMenu(INT32 choice) currentMenu->lastOn = itemOn; // Unhide the nine non-P2 controls and their headers - //OP_ChangeControlsMenu[19+0].status = IT_HEADER; - //OP_ChangeControlsMenu[19+1].status = IT_SPACE; + //OP_ChangeControlsMenu[18+0].status = IT_HEADER; + //OP_ChangeControlsMenu[18+1].status = IT_SPACE; // ... - OP_ChangeControlsMenu[19+2].status = IT_CALL|IT_STRING2; - OP_ChangeControlsMenu[19+3].status = IT_CALL|IT_STRING2; - OP_ChangeControlsMenu[19+4].status = IT_CALL|IT_STRING2; - OP_ChangeControlsMenu[19+5].status = IT_CALL|IT_STRING2; - OP_ChangeControlsMenu[19+6].status = IT_CALL|IT_STRING2; - //OP_ChangeControlsMenu[19+7].status = IT_CALL|IT_STRING2; - //OP_ChangeControlsMenu[19+8].status = IT_CALL|IT_STRING2; - OP_ChangeControlsMenu[19+9].status = IT_CALL|IT_STRING2; + OP_ChangeControlsMenu[18+2].status = IT_CALL|IT_STRING2; + OP_ChangeControlsMenu[18+3].status = IT_CALL|IT_STRING2; + OP_ChangeControlsMenu[18+4].status = IT_CALL|IT_STRING2; + OP_ChangeControlsMenu[18+5].status = IT_CALL|IT_STRING2; + OP_ChangeControlsMenu[18+6].status = IT_CALL|IT_STRING2; + //OP_ChangeControlsMenu[18+7].status = IT_CALL|IT_STRING2; + //OP_ChangeControlsMenu[18+8].status = IT_CALL|IT_STRING2; + OP_ChangeControlsMenu[18+9].status = IT_CALL|IT_STRING2; // ... - OP_ChangeControlsMenu[29+0].status = IT_HEADER; - OP_ChangeControlsMenu[29+1].status = IT_SPACE; + OP_ChangeControlsMenu[28+0].status = IT_HEADER; + OP_ChangeControlsMenu[28+1].status = IT_SPACE; // ... - OP_ChangeControlsMenu[29+2].status = IT_CALL|IT_STRING2; - OP_ChangeControlsMenu[29+3].status = IT_CALL|IT_STRING2; + OP_ChangeControlsMenu[28+2].status = IT_CALL|IT_STRING2; + OP_ChangeControlsMenu[28+3].status = IT_CALL|IT_STRING2; OP_ChangeControlsDef.prevMenu = &OP_P1ControlsDef; OP_ChangeControlsDef.menuid &= ~(((1 << MENUBITS) - 1) << MENUBITS); // remove second level @@ -13312,23 +13355,23 @@ static void M_Setup2PControlsMenu(INT32 choice) currentMenu->lastOn = itemOn; // Hide the nine non-P2 controls and their headers - //OP_ChangeControlsMenu[19+0].status = IT_GRAYEDOUT2; - //OP_ChangeControlsMenu[19+1].status = IT_GRAYEDOUT2; + //OP_ChangeControlsMenu[18+0].status = IT_GRAYEDOUT2; + //OP_ChangeControlsMenu[18+1].status = IT_GRAYEDOUT2; // ... - OP_ChangeControlsMenu[19+2].status = IT_GRAYEDOUT2; - OP_ChangeControlsMenu[19+3].status = IT_GRAYEDOUT2; - OP_ChangeControlsMenu[19+4].status = IT_GRAYEDOUT2; - OP_ChangeControlsMenu[19+5].status = IT_GRAYEDOUT2; - OP_ChangeControlsMenu[19+6].status = IT_GRAYEDOUT2; - //OP_ChangeControlsMenu[19+7].status = IT_GRAYEDOUT2; - //OP_ChangeControlsMenu[19+8].status = IT_GRAYEDOUT2; - OP_ChangeControlsMenu[19+9].status = IT_GRAYEDOUT2; + OP_ChangeControlsMenu[18+2].status = IT_GRAYEDOUT2; + OP_ChangeControlsMenu[18+3].status = IT_GRAYEDOUT2; + OP_ChangeControlsMenu[18+4].status = IT_GRAYEDOUT2; + OP_ChangeControlsMenu[18+5].status = IT_GRAYEDOUT2; + OP_ChangeControlsMenu[18+6].status = IT_GRAYEDOUT2; + //OP_ChangeControlsMenu[18+7].status = IT_GRAYEDOUT2; + //OP_ChangeControlsMenu[18+8].status = IT_GRAYEDOUT2; + OP_ChangeControlsMenu[18+9].status = IT_GRAYEDOUT2; // ... - OP_ChangeControlsMenu[29+0].status = IT_GRAYEDOUT2; - OP_ChangeControlsMenu[29+1].status = IT_GRAYEDOUT2; + OP_ChangeControlsMenu[28+0].status = IT_GRAYEDOUT2; + OP_ChangeControlsMenu[28+1].status = IT_GRAYEDOUT2; // ... - OP_ChangeControlsMenu[29+2].status = IT_GRAYEDOUT2; - OP_ChangeControlsMenu[29+3].status = IT_GRAYEDOUT2; + OP_ChangeControlsMenu[28+2].status = IT_GRAYEDOUT2; + OP_ChangeControlsMenu[28+3].status = IT_GRAYEDOUT2; OP_ChangeControlsDef.prevMenu = &OP_P2ControlsDef; OP_ChangeControlsDef.menuid &= ~(((1 << MENUBITS) - 1) << MENUBITS); // remove second level @@ -13672,23 +13715,14 @@ static void M_VideoModeMenu(INT32 choice) memset(modedescs, 0, sizeof(modedescs)); -#if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL) VID_PrepareModeList(); // FIXME: hack -#endif + vidm_nummodes = 0; vidm_selected = 0; nummodes = VID_NumModes(); -#ifdef _WINDOWS - // clean that later: skip windowed mode 0, video modes menu only shows FULL SCREEN modes - if (nummodes <= NUMSPECIALMODES) - i = 0; // unless we have nothing - else - i = NUMSPECIALMODES; -#else - // DOS does not skip mode 0, because mode 0 is ALWAYS present i = 0; -#endif + for (; i < nummodes && vidm_nummodes < MAXMODEDESCS; i++) { desc = VID_GetModeName(i); @@ -14138,6 +14172,33 @@ static INT32 quitsounds[] = sfx_chchng // Tails 11-09-99 }; +const char *QuitScreenMessages[3] = { + ( + "Design and content in\n" + "SRB2 is copyright\n" + "1998-2025 by STJr. All\n" + "original material in\n" + "this game is copyrighted\n" + "by their respective\n" + "owners, and no copyright\n" + "infringement is\n" + "intended. STJr's staff\n" + "make no profit\n" + "whatsoever (in\n" + "fact, we lose\n" + "money)." + ), + + ( + "THIS GAME SHOULD NOT BE SOLD!" + ), + + ( + "STJr is in no way affiliated\n" + "with SEGA or Sonic Team." + ) +}; + void M_QuitResponse(INT32 ch) { tic_t ptime; @@ -14159,6 +14220,9 @@ void M_QuitResponse(INT32 ch) while (ptime > I_GetTime()) { V_DrawScaledPatch(0, 0, 0, W_CachePatchName("GAMEQUIT", PU_PATCH)); // Demo 3 Quit Screen Tails 06-16-2001 + V_DrawCenteredString(2+(V_StringWidth(QuitScreenMessages[0], V_ALLOWLOWERCASE)/2), 4, V_ALLOWLOWERCASE, QuitScreenMessages[0]); + V_DrawCenteredString(160, 166, V_ALLOWLOWERCASE|V_REDMAP, QuitScreenMessages[1]); + V_DrawCenteredString(160, 176, V_ALLOWLOWERCASE, QuitScreenMessages[2]); I_FinishUpdate(); // Update the screen with the image Tails 06-19-2001 I_Sleep(cv_sleep.value); I_UpdateTime(cv_timescale.value); diff --git a/src/m_menu.h b/src/m_menu.h index 3cd2f66d37c78a2c6d7c6e14ff4e48c3f9cc56ec..dc8bef8b136e1d819e7680f5a7bca1e6cf8b94c1 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -3,7 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 2011-2016 by Matthew "Kaito Sinclaire" Walsh. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2025 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -143,7 +143,7 @@ typedef enum typedef struct { - char bgname[8]; // name for background gfx lump; lays over titlemap if this is set + char bgname[8+1]; // name for background gfx lump; lays over titlemap if this is set SINT8 fadestrength; // darken background when displaying this menu, strength 0-31 or -1 for undefined INT32 bgcolor; // fill color, overrides bg name. -1 means follow bg name rules. INT32 titlescrollxspeed; // background gfx scroll per menu; inherits global setting @@ -153,13 +153,13 @@ typedef struct SINT8 hidetitlepics; // hide title gfx per menu; -1 means undefined, inherits global setting ttmode_enum ttmode; // title wing animation mode; default TTMODE_OLD UINT8 ttscale; // scale of title wing gfx (FRACUNIT / ttscale); -1 means undefined, inherits global setting - char ttname[9]; // lump name of title wing gfx. If name length is <= 6, engine will attempt to load numbered frames (TTNAMExx) + char ttname[8+1]; // lump name of title wing gfx. If name length is <= 6, engine will attempt to load numbered frames (TTNAMExx) INT16 ttx; // X position of title wing INT16 tty; // Y position of title wing INT16 ttloop; // # frame to loop; -1 means dont loop UINT16 tttics; // # of tics per frame - char musname[7]; ///< Music track to play. "" for no music. + char musname[6+1]; ///< Music track to play. "" for no music. UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore. boolean muslooping; ///< Loop the music boolean musstop; ///< Don't play any music @@ -369,8 +369,8 @@ extern menu_t OP_JoystickSetDef; typedef struct { boolean used; - char notes[441]; - char picname[8]; + char notes[440+1]; + char picname[8+1]; char skinname[SKINNAMESIZE*2+2]; // skin&skin\0 patch_t *charpic; UINT8 prev; @@ -378,7 +378,7 @@ typedef struct char displayname[SKINNAMESIZE+1]; INT16 skinnum[2]; UINT16 oppositecolor; - char nametag[8]; + char nametag[8+1]; patch_t *namepic; UINT16 tagtextcolor; UINT16 tagoutlinecolor; @@ -421,6 +421,7 @@ typedef struct { char levelname[32]; UINT8 skinnum; + char skinname [SKINNAMESIZE+1]; UINT8 botskin; UINT8 numemeralds; UINT8 numgameovers; diff --git a/src/m_misc.c b/src/m_misc.c index 1b6a90c50acd6230cb9d8c56f99df7178926c777..24616e9db42e2b27bab8c4d359e5d92b3945f6d7 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1254,7 +1254,7 @@ void M_SaveFrame(void) // paranoia: should be unnecessary without singletics static tic_t oldtic = 0; - if (oldtic == I_GetTime()) + if (oldtic == I_GetTime() && !singletics) return; else oldtic = I_GetTime(); @@ -1978,9 +1978,9 @@ void M_UnGetToken(void) static tokenizer_t *globalTokenizer = NULL; -void M_TokenizerOpen(const char *inputString) +void M_TokenizerOpen(const char *inputString, size_t len) { - globalTokenizer = Tokenizer_Open(inputString, 2); + globalTokenizer = Tokenizer_Open(inputString, len, 2); } void M_TokenizerClose(void) @@ -2208,6 +2208,8 @@ int M_JumpWordReverse(const char *line, int offset) { int (*is)(int); int c; + if (offset == 0) // Don't let "--offset" later result in a negative value + return 0; c = line[--offset]; if (isspace(c)) is = isspace; diff --git a/src/m_misc.h b/src/m_misc.h index 04ac66ca65e1ff92d44172b12e1186cdaa04b648..63681094430950d90263165b052d9118e2240524 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_perfstats.c b/src/m_perfstats.c index b9948bdc0c3284a3473e7e6e8b95b2e3bd8fb568..33a774acfbb4ca9781ff62a177b93f9bffca28f8 100644 --- a/src/m_perfstats.c +++ b/src/m_perfstats.c @@ -453,7 +453,7 @@ static int PS_DrawPerfRows(int x, int y, int color, perfstatrow_t *rows) return draw_y; } -static void PS_UpdateMetricHistory(ps_metric_t *metric, boolean time_metric, boolean frame_metric, boolean set_user) +static void PS_UpdateMetricHistory(ps_metric_t *metric, boolean time_metric, boolean frame_metric) { int index = frame_metric ? ps_frame_index : ps_tick_index; @@ -461,7 +461,7 @@ static void PS_UpdateMetricHistory(ps_metric_t *metric, boolean time_metric, boo { // allocate history table int value_size = time_metric ? sizeof(precise_t) : sizeof(INT32); - void** memory_user = set_user ? &metric->history : NULL; + void** memory_user = &metric->history; metric->history = Z_Calloc(value_size * cv_ps_samplesize.value, PU_PERFSTATS, memory_user); @@ -491,7 +491,7 @@ static void PS_UpdateRowHistories(perfstatrow_t *rows, boolean frame_metric) for (row = rows; row->lores_label; row++) { if (PS_IsRowValid(row)) - PS_UpdateMetricHistory(row->metric, !!(row->flags & PS_TIME), frame_metric, true); + PS_UpdateMetricHistory(row->metric, !!(row->flags & PS_TIME), frame_metric); } } @@ -584,7 +584,7 @@ static void PS_CountThinkers(void) for (thinker = thlist[i].next; thinker != &thlist[i]; thinker = thinker->next) { ps_thinkercount.value.i++; - if (thinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (thinker->removing) ps_removecount.value.i++; else if (i == THINK_POLYOBJ) ps_polythcount.value.i++; @@ -649,17 +649,17 @@ void PS_UpdateTickStats(void) if (cv_perfstats.value == 3) { for (i = 0; i < thinkframe_hooks_length; i++) - PS_UpdateMetricHistory(&thinkframe_hooks[i].time_taken, true, false, false); + PS_UpdateMetricHistory(&thinkframe_hooks[i].time_taken, true, false); } else if (cv_perfstats.value == 4) { for (i = 0; i < prethinkframe_hooks_length; i++) - PS_UpdateMetricHistory(&prethinkframe_hooks[i].time_taken, true, false, false); + PS_UpdateMetricHistory(&prethinkframe_hooks[i].time_taken, true, false); } else if (cv_perfstats.value == 5) { for (i = 0; i < postthinkframe_hooks_length; i++) - PS_UpdateMetricHistory(&postthinkframe_hooks[i].time_taken, true, false, false); + PS_UpdateMetricHistory(&postthinkframe_hooks[i].time_taken, true, false); } } if (cv_perfstats.value) diff --git a/src/m_random.c b/src/m_random.c index 536fbfbbd1077abf6ae400bd4d8773a7574e4b08..a063e88f47ccc40f10ffa09d441016d3bd20c13b 100644 --- a/src/m_random.c +++ b/src/m_random.c @@ -193,9 +193,9 @@ INT32 M_RandomKey(INT32 a) */ INT32 M_RandomRange(INT32 a, INT32 b) { - if (b < a) + if (b < a) { - INT32 temp; + INT32 temp; temp = a; a = b; diff --git a/src/m_tokenizer.c b/src/m_tokenizer.c index f36f7f6f323133c51c4975992beea9919c27e4bd..09f8915a52b2c476036f560c773118b3d5f823ff 100644 --- a/src/m_tokenizer.c +++ b/src/m_tokenizer.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2013-2023 by Sonic Team Junior. +// Copyright (C) 2013-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -12,11 +12,18 @@ #include "m_tokenizer.h" #include "z_zone.h" -tokenizer_t *Tokenizer_Open(const char *inputString, unsigned numTokens) +tokenizer_t *Tokenizer_Open(const char *inputString, size_t len, unsigned numTokens) { tokenizer_t *tokenizer = Z_Malloc(sizeof(tokenizer_t), PU_STATIC, NULL); + const size_t lenpan = 2; - tokenizer->input = inputString; + tokenizer->zdup = malloc(len+lenpan); + for (size_t i = 0; i < lenpan; i++) + { + tokenizer->zdup[len+i] = 0x00; + } + + tokenizer->input = M_Memcpy(tokenizer->zdup, inputString, len); tokenizer->startPos = 0; tokenizer->endPos = 0; tokenizer->inputLength = 0; @@ -51,6 +58,7 @@ void Tokenizer_Close(tokenizer_t *tokenizer) Z_Free(tokenizer->token[i]); Z_Free(tokenizer->capacity); Z_Free(tokenizer->token); + free(tokenizer->zdup); Z_Free(tokenizer); } diff --git a/src/m_tokenizer.h b/src/m_tokenizer.h index f5111730194915c69fea455a53ba1da3cf66068b..4f03563a2da69c671edfc196ec478dc4715fa080 100644 --- a/src/m_tokenizer.h +++ b/src/m_tokenizer.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2013-2023 by Sonic Team Junior. +// Copyright (C) 2013-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -16,6 +16,7 @@ typedef struct Tokenizer { + char *zdup; const char *input; unsigned numTokens; UINT32 *capacity; @@ -29,7 +30,7 @@ typedef struct Tokenizer const char *(*get)(struct Tokenizer*, UINT32); } tokenizer_t; -tokenizer_t *Tokenizer_Open(const char *inputString, unsigned numTokens); +tokenizer_t *Tokenizer_Open(const char *inputString, size_t len, unsigned numTokens); void Tokenizer_Close(tokenizer_t *tokenizer); const char *Tokenizer_Read(tokenizer_t *tokenizer, UINT32 i); diff --git a/src/m_vector.c b/src/m_vector.c index 3132a869d458c83aac517ac609258b506b6395b8..1b04f8ae1461b6a11f34cc07e6765c3ea640b330 100644 --- a/src/m_vector.c +++ b/src/m_vector.c @@ -21,6 +21,32 @@ void DVector3_Load(dvector3_t *vec, double x, double y, double z) vec->z = z; } +void DVector3_Copy(dvector3_t *a_o, const dvector3_t *a_i) +{ + memcpy(a_o, a_i, sizeof(dvector3_t)); +} + +void DVector3_Add(const dvector3_t *a_i, const dvector3_t *a_c, dvector3_t *a_o) +{ + a_o->x = a_i->x + a_c->x; + a_o->y = a_i->y + a_c->y; + a_o->z = a_i->z + a_c->z; +} + +void DVector3_Subtract(const dvector3_t *a_i, const dvector3_t *a_c, dvector3_t *a_o) +{ + a_o->x = a_i->x - a_c->x; + a_o->y = a_i->y - a_c->y; + a_o->z = a_i->z - a_c->z; +} + +void DVector3_Multiply(const dvector3_t *a_i, double a_c, dvector3_t *a_o) +{ + a_o->x = a_i->x * a_c; + a_o->y = a_i->y * a_c; + a_o->z = a_i->z * a_c; +} + double DVector3_Magnitude(const dvector3_t *a_normal) { double xs = a_normal->x * a_normal->x; diff --git a/src/m_vector.h b/src/m_vector.h index 55669be037c9ce54ffd70bf3782225e913e1a1b4..1395744f2984050991923bfc714e5a3a028ccfe6 100644 --- a/src/m_vector.h +++ b/src/m_vector.h @@ -19,6 +19,10 @@ typedef struct } dvector3_t; void DVector3_Load(dvector3_t *vec, double x, double y, double z); +void DVector3_Copy(dvector3_t *a_o, const dvector3_t *a_i); +void DVector3_Add(const dvector3_t *a_i, const dvector3_t *a_c, dvector3_t *a_o); +void DVector3_Subtract(const dvector3_t *a_i, const dvector3_t *a_c, dvector3_t *a_o); +void DVector3_Multiply(const dvector3_t *a_i, double a_c, dvector3_t *a_o); double DVector3_Magnitude(const dvector3_t *a_normal); double DVector3_Normalize(dvector3_t *a_normal); void DVector3_Negate(dvector3_t *a_o); diff --git a/src/netcode/client_connection.c b/src/netcode/client_connection.c index 36ed718265b3cfa42acc3ef238c436882bb918a1..c740d53a6a3845539bfe0637771e78827ae8b055 100644 --- a/src/netcode/client_connection.c +++ b/src/netcode/client_connection.c @@ -307,7 +307,7 @@ boolean CL_SendJoin(void) else player2name = cv_playername2.zstring; - strncpy(netbuffer->u.clientcfg.names[0], cv_playername.zstring, MAXPLAYERNAME); + strncpy(netbuffer->u.clientcfg.names[0], cv_playername.zstring, sizeof(netbuffer->u.clientcfg.names[0])-1); strncpy(netbuffer->u.clientcfg.names[1], player2name, MAXPLAYERNAME); return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak)); @@ -546,6 +546,7 @@ static void AbortConnection(void) { Snake_Free(&snake); + CURLAbortFile(); D_QuitNetGame(); CL_Reset(); D_StartTitle(); @@ -1062,10 +1063,6 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic } } - // Rusty TODO: multithread - if (filedownload.http_running) - CURLGetFile(); - if (waitmore) break; // exit the case diff --git a/src/netcode/commands.c b/src/netcode/commands.c index 46dfbc741d9c8f036bf53e0ba6d77bed60ac39f3..8d6dab06b5da5628245f307a1519ef74a0ea9588 100644 --- a/src/netcode/commands.c +++ b/src/netcode/commands.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -41,6 +41,8 @@ typedef struct banreason_s static banreason_t *reasontail = NULL; //last entry, use prev static banreason_t *reasonhead = NULL; //1st entry, use next +static boolean bans_loaded = false; + void Ban_Add(const char *reason) { banreason_t *reasonlist = malloc(sizeof(*reasonlist)); @@ -85,6 +87,8 @@ void Ban_Load_File(boolean warning) if (!I_ClearBans) return; + bans_loaded = true; + f = fopen(va("%s"PATHSEP"%s", srb2home, "ban.txt"), "r"); if (!f) @@ -124,6 +128,12 @@ void D_SaveBan(void) const char *address, *mask; const char *path = va("%s"PATHSEP"%s", srb2home, "ban.txt"); + if (!bans_loaded) + { + // don't save bans if they were never loaded. + return; + } + if (!reasonhead) { remove(path); diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index d735e8132172e66a5c808ef572b7edca1ae8a8cc..6702e2591254349a9bd3dde6d08b7fa86ef7fb29 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -113,8 +113,11 @@ consvar_t cv_blamecfail = CVAR_INIT ("blamecfail", "Off", CV_SAVE|CV_NETVAR, CV_ static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, NULL}}; consvar_t cv_playbackspeed = CVAR_INIT ("playbackspeed", "1", 0, playbackspeed_cons_t, NULL); -consvar_t cv_idletime = CVAR_INIT ("idletime", "0", CV_SAVE, CV_Unsigned, NULL); -consvar_t cv_dedicatedidletime = CVAR_INIT ("dedicatedidletime", "10", CV_SAVE, CV_Unsigned, NULL); +consvar_t cv_dedicatedidletime = CVAR_INIT ("dedicatedidletime", "10", CV_SAVE|CV_NETVAR, CV_Unsigned, NULL); + +static CV_PossibleValue_t idleaction_cons_t[] = {{1, "Kick"}, {2, "Spectate"}, {0, NULL}}; +consvar_t cv_idleaction = CVAR_INIT ("idleaction", "Spectate", CV_SAVE|CV_NETVAR, idleaction_cons_t, NULL); +consvar_t cv_idletime = CVAR_INIT ("idletime", "3", CV_SAVE|CV_NETVAR, CV_Unsigned, NULL); consvar_t cv_httpsource = CVAR_INIT ("http_source", "", CV_SAVE, NULL, NULL); @@ -660,7 +663,7 @@ void D_QuitNetGame(void) if (netnodes[i].ingame) HSendPacket(i, true, 0, 0); #ifdef MASTERSERVER - if (serverrunning && ms_RoomId > 0) + if (serverrunning && cv_masterserver_room_id.value > 0) UnregisterServer(); #endif } @@ -794,7 +797,7 @@ void SV_SpawnServer(void) { I_NetOpenSocket(); #ifdef MASTERSERVER - if (ms_RoomId > 0) + if (cv_masterserver_room_id.value > 0) RegisterServer(); #endif } @@ -1360,19 +1363,33 @@ static void IdleUpdate(void) if (!server || !netgame) return; - for (i = 1; i < MAXPLAYERS; i++) + for (i = 0; i < MAXPLAYERS; i++) { - if (cv_idletime.value && playeringame[i] && playernode[i] != UINT8_MAX && !players[i].quittime && !players[i].spectator && !players[i].bot && !IsPlayerAdmin(i) && i != serverplayer) + if (playeringame[i] && playernode[i] != UINT8_MAX && !players[i].quittime && !players[i].spectator && !players[i].bot && gamestate == GS_LEVEL) { if (players[i].cmd.forwardmove || players[i].cmd.sidemove || players[i].cmd.buttons) players[i].lastinputtime = 0; else players[i].lastinputtime++; - if (players[i].lastinputtime > (tic_t)cv_idletime.value * TICRATE * 60) + if (cv_idletime.value && !IsPlayerAdmin(i) && i != serverplayer && !(players[i].pflags & PF_FINISHED) && players[i].lastinputtime > (tic_t)cv_idletime.value * TICRATE * 60) { players[i].lastinputtime = 0; - SendKick(i, KICK_MSG_IDLE | KICK_MSG_KEEP_BODY); + if (cv_idleaction.value == 2 && G_GametypeHasSpectators()) + { + changeteam_union NetPacket; + UINT16 usvalue; + NetPacket.value.l = NetPacket.value.b = 0; + NetPacket.packet.newteam = 0; + NetPacket.packet.playernum = i; + NetPacket.packet.verification = true; // This signals that it's a server change + usvalue = SHORT(NetPacket.value.l|NetPacket.value.b); + SendNetXCmd(XD_TEAMCHANGE, &usvalue, sizeof(usvalue)); + } + else if (cv_idleaction.value == 1) + { + SendKick(i, KICK_MSG_IDLE | KICK_MSG_KEEP_BODY); + } } } else @@ -1399,6 +1416,83 @@ static void IdleUpdate(void) } } +static void DedicatedIdleUpdate(INT32 *realtics) +{ + const tic_t dedicatedidletime = cv_dedicatedidletime.value * TICRATE; + static tic_t dedicatedidletimeprev = 0; + static tic_t dedicatedidle = 0; + + if (!server || !dedicated || gamestate != GS_LEVEL) + return; + + if (dedicatedidletime > 0) + { + INT32 i; + + boolean empty = true; + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i]) + { + empty = false; + break; + } + + if (empty) + { + 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 + { + dedicatedidle += (*realtics); + + if (dedicatedidle >= dedicatedidletime) + { + const char *idlereason = "at round start"; + if (leveltime > 3) + idlereason = va("for %d seconds", dedicatedidle / TICRATE); + + CONS_Printf("DEDICATED: No players %s, idling...\n", idlereason); + (*realtics) = 0; + dedicatedidle = dedicatedidletime; + } + } + } + else + { + if (dedicatedidle >= dedicatedidletime) + { + CONS_Printf("DEDICATED: Awakening from idle (Player detected...)\n"); + } + dedicatedidle = 0; + } + } + else + { + if (dedicatedidletimeprev > 0 && dedicatedidle >= dedicatedidletimeprev) + { + CONS_Printf("DEDICATED: Awakening from idle (Idle disabled...)\n"); + } + dedicatedidle = 0; + } + + dedicatedidletimeprev = dedicatedidletime; +} + // Handle timeouts to prevent definitive freezes from happenning static void HandleNodeTimeouts(void) { @@ -1475,69 +1569,7 @@ void NetUpdate(void) 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) - { - INT32 i; - - for (i = 1; i < MAXNETNODES; ++i) - if (netnodes[i].ingame) - { - 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; - } + DedicatedIdleUpdate(&realtics); gametime = nowtime; @@ -1784,7 +1816,7 @@ INT16 Consistancy(void) { for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo = (mobj_t *)th; diff --git a/src/netcode/d_clisrv.h b/src/netcode/d_clisrv.h index 5aac4693d2fdd166cee7a796166ba7c798e183c8..86af61e9e02eb9528b759ce635970a96e3a28ee4 100644 --- a/src/netcode/d_clisrv.h +++ b/src/netcode/d_clisrv.h @@ -73,7 +73,7 @@ extern UINT32 realpingtable[MAXPLAYERS]; extern UINT32 playerpingtable[MAXPLAYERS]; extern tic_t servermaxping; -extern consvar_t cv_netticbuffer, cv_resynchattempts, cv_blamecfail, cv_playbackspeed, cv_idletime, cv_dedicatedidletime; +extern consvar_t cv_netticbuffer, cv_resynchattempts, cv_blamecfail, cv_playbackspeed, cv_idletime, cv_idleaction, cv_dedicatedidletime; extern consvar_t cv_httpsource; // Used in d_net, the only dependence diff --git a/src/netcode/d_net.c b/src/netcode/d_net.c index 5a2e229d3f47c9eadf66729a1250a1d2b0719343..4860d8688b4a8b998b59523c6cf52502c69d10ca 100644 --- a/src/netcode/d_net.c +++ b/src/netcode/d_net.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -62,16 +62,11 @@ static doomdata_t reboundstore[MAXREBOUND]; static INT16 reboundsize[MAXREBOUND]; static INT32 rebound_head, rebound_tail; -/// \brief bandwith of netgame -INT32 net_bandwidth; - /// \brief max length per packet INT16 hardware_MAXPACKETLENGTH; boolean (*I_NetGet)(void) = NULL; void (*I_NetSend)(void) = NULL; -boolean (*I_NetCanSend)(void) = NULL; -boolean (*I_NetCanGet)(void) = NULL; void (*I_NetCloseSocket)(void) = NULL; void (*I_NetFreeNodenum)(INT32 nodenum) = NULL; SINT8 (*I_NetMakeNodewPort)(const char *address, const char* port) = NULL; @@ -940,7 +935,7 @@ void Command_Droprate(void) static boolean ShouldDropPacket(void) { return (packetdropquantity[netbuffer->packettype]) - || (packetdroprate != 0 && rand() < (RAND_MAX * (packetdroprate / 100.f))) || packetdroprate == 100; + || (packetdroprate != 0 && rand() < (((double)RAND_MAX) * (packetdroprate / 100.f))) || packetdroprate == 100; } #endif @@ -996,15 +991,7 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen netbuffer->ackreturn = 0; if (reliable) { - if (I_NetCanSend && !I_NetCanSend()) - { - if (netbuffer->packettype < PT_CANFAIL) - GetFreeAcknum(&netbuffer->ack, true); - - DEBFILE("HSendPacket: Out of bandwidth\n"); - return false; - } - else if (!GetFreeAcknum(&netbuffer->ack, false)) + if (!GetFreeAcknum(&netbuffer->ack, false)) return false; } else @@ -1156,7 +1143,7 @@ static void Internal_FreeNodenum(INT32 nodenum) char *I_NetSplitAddress(char *host, char **port) { - boolean v4 = (strchr(host, '.') != NULL); + boolean v4 = (host[0] != '['); host = strtok(host, v4 ? ":" : "[]"); @@ -1189,10 +1176,7 @@ void D_SetDoomcom(void) { if (doomcom) return; doomcom = Z_Calloc(sizeof (doomcom_t), PU_STATIC, NULL); - doomcom->id = DOOMCOM_ID; doomcom->numslots = doomcom->numnodes = 1; - doomcom->gametype = 0; - doomcom->consoleplayer = 0; doomcom->extratics = 0; } @@ -1211,13 +1195,11 @@ boolean D_CheckNetGame(void) I_NetGet = Internal_Get; I_NetSend = Internal_Send; - I_NetCanSend = NULL; I_NetCloseSocket = NULL; I_NetFreeNodenum = Internal_FreeNodenum; I_NetMakeNodewPort = NULL; hardware_MAXPACKETLENGTH = MAXPACKETLENGTH; - net_bandwidth = 30000; // I_InitNetwork sets doomcom and netgame // check and initialize the network driver multiplayer = false; @@ -1237,7 +1219,6 @@ boolean D_CheckNetGame(void) server = true; // WTF? server always true??? // no! The deault mode is server. Client is set elsewhere // when the client executes connect command. - doomcom->ticdup = 1; if (M_CheckParm("-extratic")) { @@ -1248,21 +1229,6 @@ boolean D_CheckNetGame(void) CONS_Printf(M_GetText("Set extratics to %d\n"), doomcom->extratics); } - if (M_CheckParm("-bandwidth")) - { - if (M_IsNextParm()) - { - net_bandwidth = atoi(M_GetNextParm()); - if (net_bandwidth < 1000) - net_bandwidth = 1000; - if (net_bandwidth > 100000) - hardware_MAXPACKETLENGTH = MAXPACKETLENGTH; - CONS_Printf(M_GetText("Network bandwidth set to %d\n"), net_bandwidth); - } - else - I_Error("usage: -bandwidth <byte_per_sec>"); - } - software_MAXPACKETLENGTH = hardware_MAXPACKETLENGTH; if (M_CheckParm("-packetsize")) { @@ -1282,8 +1248,6 @@ boolean D_CheckNetGame(void) if (netgame) multiplayer = true; - if (doomcom->id != DOOMCOM_ID) - I_Error("Doomcom buffer invalid!"); if (doomcom->numnodes > MAXNETNODES) I_Error("Too many nodes (%d), max:%d", doomcom->numnodes, MAXNETNODES); @@ -1293,7 +1257,7 @@ boolean D_CheckNetGame(void) if (M_CheckParm("-debugfile")) { char filename[21]; - INT32 k = doomcom->consoleplayer - 1; + INT32 k = consoleplayer - 1; if (M_IsNextParm()) k = atoi(M_GetNextParm()) - 1; while (!debugfile && k < MAXPLAYERS) @@ -1400,7 +1364,6 @@ void D_CloseConnection(void) I_NetGet = Internal_Get; I_NetSend = Internal_Send; - I_NetCanSend = NULL; I_NetCloseSocket = NULL; I_NetFreeNodenum = Internal_FreeNodenum; I_NetMakeNodewPort = NULL; diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c index 87f0110a9490d8a85e88c39d51d745ccede2af0d..94170fa0df401064f5c1a2f9569cfceb0b0c490e 100644 --- a/src/netcode/d_netcmd.c +++ b/src/netcode/d_netcmd.c @@ -149,6 +149,10 @@ static void Command_Teamchange_f(void); static void Command_Teamchange2_f(void); static void Command_ServerTeamChange_f(void); +static void Command_MutePlayer_f(void); +static void Command_UnmutePlayer_f(void); +static void Got_MutePlayer(UINT8 **cp, INT32 playernum); + static void Command_Clearscores_f(void); // Remote Administration @@ -209,6 +213,7 @@ static CV_PossibleValue_t matchboxes_cons_t[] = {{0, "Normal"}, {1, "Mystery"}, static CV_PossibleValue_t chances_cons_t[] = {{0, "MIN"}, {9, "MAX"}, {0, NULL}}; static CV_PossibleValue_t pause_cons_t[] = {{0, "Server"}, {1, "All"}, {0, NULL}}; +consvar_t cv_showinput = CVAR_INIT ("showinput", "Off", CV_ALLOWLUA, CV_OnOff, NULL); consvar_t cv_showinputjoy = CVAR_INIT ("showinputjoy", "Off", CV_ALLOWLUA, CV_OnOff, NULL); #ifdef NETGAME_DEVMODE @@ -386,13 +391,16 @@ static CV_PossibleValue_t perfstats_cons_t[] = { consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", CV_CALL, perfstats_cons_t, PS_PerfStats_OnChange); static CV_PossibleValue_t ps_samplesize_cons_t[] = { {1, "MIN"}, {1000, "MAX"}, {0, NULL}}; -consvar_t cv_ps_samplesize = CVAR_INIT ("ps_samplesize", "1", CV_CALL, ps_samplesize_cons_t, PS_SampleSize_OnChange); +consvar_t cv_ps_samplesize = CVAR_INIT ("ps_samplesize", "175", CV_CALL, ps_samplesize_cons_t, PS_SampleSize_OnChange); static CV_PossibleValue_t ps_descriptor_cons_t[] = { {1, "Average"}, {2, "SD"}, {3, "Minimum"}, {4, "Maximum"}, {0, NULL}}; consvar_t cv_ps_descriptor = CVAR_INIT ("ps_descriptor", "Average", 0, ps_descriptor_cons_t, NULL); consvar_t cv_freedemocamera = CVAR_INIT("freedemocamera", "Off", CV_SAVE, CV_OnOff, NULL); +// NOTE: this should be in hw_main.c, but we can't put it there as it breaks dedicated build +consvar_t cv_glallowshaders = CVAR_INIT ("gr_allowcustomshaders", "On", CV_NETVAR, CV_OnOff, NULL); + char timedemo_name[256]; boolean timedemo_csv; char timedemo_csv_id[256]; @@ -484,6 +492,10 @@ void D_RegisterServerCommands(void) RegisterNetXCmd(XD_TEAMCHANGE, Got_Teamchange); COM_AddCommand("serverchangeteam", Command_ServerTeamChange_f, COM_LUA); + RegisterNetXCmd(XD_MUTEPLAYER, Got_MutePlayer); + COM_AddCommand("muteplayer", Command_MutePlayer_f, COM_LUA); + COM_AddCommand("unmuteplayer", Command_UnmutePlayer_f, COM_LUA); + RegisterNetXCmd(XD_CLEARSCORES, Got_Clearscores); COM_AddCommand("clearscores", Command_Clearscores_f, COM_LUA); COM_AddCommand("map", Command_Map_f, COM_LUA); @@ -526,6 +538,8 @@ void D_RegisterServerCommands(void) // for master server connection AddMServCommands(); + CV_RegisterVar(&cv_glallowshaders); + // p_mobj.c CV_RegisterVar(&cv_itemrespawntime); CV_RegisterVar(&cv_itemrespawn); @@ -606,6 +620,7 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_blamecfail); CV_RegisterVar(&cv_dedicatedidletime); CV_RegisterVar(&cv_idletime); + CV_RegisterVar(&cv_idleaction); CV_RegisterVar(&cv_httpsource); COM_AddCommand("ping", Command_Ping_f, COM_LUA); @@ -657,6 +672,13 @@ void D_RegisterClientCommands(void) for (i = 0; i < MAXPLAYERS; i++) sprintf(player_names[i], "Player %d", 1 + i); + CV_RegisterVar(&cv_gravity); + CV_RegisterVar(&cv_tailspickup); + CV_RegisterVar(&cv_allowmlook); + CV_RegisterVar(&cv_flipcam); + CV_RegisterVar(&cv_flipcam2); + CV_RegisterVar(&cv_movebob); + if (dedicated) return; @@ -670,6 +692,7 @@ void D_RegisterClientCommands(void) COM_AddCommand("timedemo", Command_Timedemo_f, 0); COM_AddCommand("stopdemo", Command_Stopdemo_f, COM_LUA); COM_AddCommand("playintro", Command_Playintro_f, COM_LUA); + CV_RegisterVar(&cv_resyncdemo); COM_AddCommand("resetcamera", Command_ResetCamera_f, COM_LUA); @@ -731,6 +754,7 @@ void D_RegisterClientCommands(void) CV_RegisterVar(&cv_timetic); CV_RegisterVar(&cv_powerupdisplay); CV_RegisterVar(&cv_itemfinder); + CV_RegisterVar(&cv_showinput); CV_RegisterVar(&cv_showinputjoy); // time attack ghost options are also saved to config @@ -884,10 +908,6 @@ 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); @@ -903,13 +923,11 @@ void D_RegisterClientCommands(void) // ingame object placing COM_AddCommand("objectplace", Command_ObjectPlace_f, COM_LUA); - //COM_AddCommand("writethings", Command_Writethings_f); + COM_AddCommand("writethings", Command_Writethings_f, COM_LUA); CV_RegisterVar(&cv_speed); CV_RegisterVar(&cv_opflags); CV_RegisterVar(&cv_ophoopflags); CV_RegisterVar(&cv_mapthingnum); -// CV_RegisterVar(&cv_grid); -// CV_RegisterVar(&cv_snapto); CV_RegisterVar(&cv_freedemocamera); @@ -1290,7 +1308,7 @@ static void SendNameAndColor(void) SetColorLocal(consoleplayer, cv_playercolor.value); - if (splitscreen) + if (splitscreen || (!pickedchar && stricmp(cv_skin.string, skins[consoleplayer]->name) != 0)) SetSkinLocal(consoleplayer, R_SkinAvailable(cv_skin.string)); else SetSkinLocal(consoleplayer, pickedchar); @@ -1305,7 +1323,7 @@ static void SendNameAndColor(void) CV_StealthSet(&cv_playername, player_names[consoleplayer]); HU_AddChatText("\x85*You must wait to change your name again", false); } - else if (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) + else if ((cv_mute.value || players[consoleplayer].muted) && !(server || IsPlayerAdmin(consoleplayer))) CV_StealthSet(&cv_playername, player_names[consoleplayer]); else // Cleanup name if changing it CleanupPlayerName(consoleplayer, cv_playername.zstring); @@ -2480,6 +2498,91 @@ static void Command_Teamchange2_f(void) SendNetXCmd2(XD_TEAMCHANGE, &usvalue, sizeof(usvalue)); } +static void MutePlayer(boolean mute) +{ + UINT8 data[2]; + if (!(server || (IsPlayerAdmin(consoleplayer)))) + { + CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); + return; + } + + if (COM_Argc() < 2) + { + CONS_Printf(M_GetText("muteplayer <playername/playernum>: mute a player\n")); + return; + } + + data[0] = nametonum(COM_Argv(1)); + if (data[0] >= MAXPLAYERS || !playeringame[data[0]]) + { + CONS_Alert(CONS_NOTICE, M_GetText("There is no player %u!\n"), (unsigned int)data[0]); + return; + } + + if (players[data[0]].muted && mute) + { + CONS_Printf(M_GetText("%s is already muted!\n"), player_names[data[0]]); + return; + } + else if (!players[data[0]].muted && !mute) + { + CONS_Printf(M_GetText("%s is not muted!\n"), player_names[data[0]]); + return; + } + + data[1] = mute; + SendNetXCmd(XD_MUTEPLAYER, &data, sizeof(data)); +} + +static void Command_MutePlayer_f(void) +{ + MutePlayer(true); +} + +static void Command_UnmutePlayer_f(void) +{ + MutePlayer(false); +} + +static void Got_MutePlayer(UINT8 **cp, INT32 playernum) +{ + UINT8 player = READUINT8(*cp); + UINT8 muted = READUINT8(*cp); + if (playernum != serverplayer && !IsPlayerAdmin(playernum)) + { + CONS_Alert(CONS_WARNING, M_GetText("Illegal mute received from player %s\n"), player_names[playernum]); + if (server) + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); + return; + } + + if (player >= MAXPLAYERS || !playeringame[player]) + { + CONS_Alert(CONS_WARNING, M_GetText("Illegal mute received from player %s\n"), player_names[playernum]); + if (server) + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); + return; + } + + if (!players[player].muted && muted) + { + if (player == consoleplayer) + CONS_Printf(M_GetText("You have been muted.\n")); + else + CONS_Printf(M_GetText("%s has been muted.\n"), player_names[player]); + } + else if (players[player].muted && !muted) + { + if (player == consoleplayer) + CONS_Printf(M_GetText("You are no longer muted.\n")); + else + CONS_Printf(M_GetText("%s is no longer muted.\n"), player_names[player]); + } + + players[player].muted = muted; +} + static void Command_ServerTeamChange_f(void) { changeteam_union NetPacket; @@ -2499,11 +2602,11 @@ static void Command_ServerTeamChange_f(void) if (COM_Argc() < 3) { if (G_TagGametype()) - CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "it, notit, playing, or spectator"); + CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: switch player to a new team (%s)\n"), "it, notit, playing, or spectator"); else if (G_GametypeHasTeams()) - CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "red, blue or spectator"); + CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: switch player to a new team (%s)\n"), "red, blue or spectator"); else if (G_GametypeHasSpectators()) - CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "spectator or playing"); + CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: switch player to a new team (%s)\n"), "spectator or playing"); else CONS_Alert(CONS_NOTICE, M_GetText("This command cannot be used in this gametype.\n")); return; @@ -2551,19 +2654,19 @@ static void Command_ServerTeamChange_f(void) if (error) { if (G_TagGametype()) - CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "it, notit, playing, or spectator"); + CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: switch player to a new team (%s)\n"), "it, notit, playing, or spectator"); else if (G_GametypeHasTeams()) - CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "red, blue or spectator"); + CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: switch player to a new team (%s)\n"), "red, blue or spectator"); else if (G_GametypeHasSpectators()) - CONS_Printf(M_GetText("serverchangeteam <playernum> <team>: switch player to a new team (%s)\n"), "spectator or playing"); + CONS_Printf(M_GetText("serverchangeteam <playername/playernum> <team>: switch player to a new team (%s)\n"), "spectator or playing"); return; } - NetPacket.packet.playernum = atoi(COM_Argv(1)); + NetPacket.packet.playernum = nametonum(COM_Argv(1)); - if (!playeringame[NetPacket.packet.playernum]) + if (NetPacket.packet.playernum == -1 || !playeringame[NetPacket.packet.playernum]) { - CONS_Alert(CONS_NOTICE, M_GetText("There is no player %d!\n"), NetPacket.packet.playernum); + CONS_Alert(CONS_NOTICE, M_GetText("There is no player %s!\n"), COM_Argv(1)); return; } @@ -3002,13 +3105,16 @@ static void Command_Verify_f(void) if (COM_Argc() != 2) { - CONS_Printf(M_GetText("promote <playernum>: give admin privileges to a player\n")); + CONS_Printf(M_GetText("promote <playername/playernum>: give admin privileges to a player\n")); return; } - strlcpy(buf, COM_Argv(1), sizeof (buf)); - - playernum = atoi(buf); + playernum = nametonum(COM_Argv(1)); + if (playernum == -1) + { + CONS_Alert(CONS_NOTICE, M_GetText("There is no player %s!\n"), COM_Argv(1)); + return; + } temp = buf; @@ -3052,13 +3158,16 @@ static void Command_RemoveAdmin_f(void) if (COM_Argc() != 2) { - CONS_Printf(M_GetText("demote <playernum>: remove admin privileges from a player\n")); + CONS_Printf(M_GetText("demote <playername/playernum>: remove admin privileges from a player\n")); return; } - strlcpy(buf, COM_Argv(1), sizeof(buf)); - - playernum = atoi(buf); + playernum = nametonum(COM_Argv(1)); + if (playernum == -1) + { + CONS_Alert(CONS_NOTICE, M_GetText("There is no player %s!\n"), COM_Argv(1)); + return; + } temp = buf; @@ -3812,18 +3921,7 @@ static void Command_Version_f(void) #endif // OS - // Would be nice to use SDL_GetPlatform for this -#if defined (_WIN32) || defined (_WIN64) - CONS_Printf("Windows "); -#elif defined(__linux__) - CONS_Printf("Linux "); -#elif defined(MACOSX) - CONS_Printf("macOS "); -#elif defined(UNIXCOMMON) - CONS_Printf("Unix (Common) "); -#else - CONS_Printf("Other OS "); -#endif + CONS_Printf("%s ", I_GetSysName()); // Bitness if (sizeof(void*) == 4) @@ -4069,7 +4167,7 @@ static void ExitMove_OnChange(void) if (players[i].mo->target && players[i].mo->target->type == MT_SIGN) P_SetTarget(&players[i].mo->target, NULL); - if (players[i].pflags & PF_FINISHED) + if (players[i].pflags & PF_FINISHED && !(players[i].exiting)) P_GiveFinishFlags(&players[i]); } @@ -4516,7 +4614,7 @@ static void Command_ExitLevel_f(void) SendNetXCmd(XD_EXITLEVEL, NULL, 0); return; } - + // Allow exiting without cheating if at least one player beat the level // Consistent with just setting playersforexit to one if (splitscreen || multiplayer) @@ -4530,7 +4628,7 @@ static void Command_ExitLevel_f(void) continue; if (players[i].lives <= 0) continue; - + if ((players[i].pflags & PF_FINISHED) || players[i].exiting) { SendNetXCmd(XD_EXITLEVEL, NULL, 0); @@ -4538,7 +4636,7 @@ static void Command_ExitLevel_f(void) } } } - + // Only consider it a cheat if we're not allowed to go to the next map if (M_CampaignWarpIsCheat(gametype, G_GetNextMap(true, true) + 1, serverGamedata)) CONS_Alert(CONS_NOTICE, M_GetText("Cheats must be enabled to force exit to a locked level!\n")); @@ -4669,15 +4767,28 @@ static void Command_Cheats_f(void) CV_ResetCheatNetVars(); return; } + else if (COM_CheckParm("on")) + { + if (!(server || (IsPlayerAdmin(consoleplayer)))) + CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); + else + G_SetUsedCheats(false); + return; + } + + if (usedCheats) + CONS_Printf(M_GetText("Cheats are enabled, the game cannot be saved.\n")); + else + CONS_Printf(M_GetText("Cheats are disabled, the game can be saved.\n")); if (CV_CheatsEnabled()) { - CONS_Printf(M_GetText("At least one CHEAT-marked variable has been changed -- Cheats are enabled.\n")); + CONS_Printf(M_GetText("At least one CHEAT-marked variable has been changed.\n")); if (server || (IsPlayerAdmin(consoleplayer))) CONS_Printf(M_GetText("Type CHEATS OFF to reset all cheat variables to default.\n")); } else - CONS_Printf(M_GetText("No CHEAT-marked variables are changed -- Cheats are disabled.\n")); + CONS_Printf(M_GetText("No CHEAT-marked variables are changed.\n")); } #ifdef _DEBUG @@ -4686,12 +4797,11 @@ static void Command_Togglemodified_f(void) modifiedgame = !modifiedgame; } -extern UINT8 *save_p; static void Command_Archivetest_f(void) { - UINT8 *buf; UINT32 i, wrote; thinker_t *th; + save_t savebuffer; if (gamestate != GS_LEVEL) { CONS_Printf("This command only works in-game, you dummy.\n"); @@ -4705,28 +4815,29 @@ static void Command_Archivetest_f(void) ((mobj_t *)th)->mobjnum = i++; // allocate buffer - buf = save_p = ZZ_Alloc(1024); + savebuffer.size = 1024; + savebuffer.buf = malloc(savebuffer.size); + savebuffer.pos = 0; // test archive CONS_Printf("LUA_Archive...\n"); - LUA_Archive(); - WRITEUINT8(save_p, 0x7F); - wrote = (UINT32)(save_p-buf); + LUA_Archive(&savebuffer); + P_WriteUINT8(&savebuffer, 0x7F); + wrote = savebuffer.pos; // clear Lua state, so we can really see what happens! CONS_Printf("Clearing state!\n"); LUA_ClearExtVars(); // test unarchive - save_p = buf; CONS_Printf("LUA_UnArchive...\n"); - LUA_UnArchive(); - i = READUINT8(save_p); - if (i != 0x7F || wrote != (UINT32)(save_p-buf)) - CONS_Printf("Savegame corrupted. (write %u, read %u)\n", wrote, (UINT32)(save_p-buf)); + LUA_UnArchive(&savebuffer); + i = P_ReadUINT8(&savebuffer); + if (i != 0x7F || wrote != (UINT32)(savebuffer.pos)) + CONS_Printf("Savegame corrupted. (write %u, read %u)\n", wrote, (UINT32)(savebuffer.pos)); // free buffer - Z_Free(buf); + free(savebuffer.buf); CONS_Printf("Done. No crash.\n"); } #endif @@ -4775,7 +4886,7 @@ static void ForceSkin_OnChange(void) //Allows the player's name to be changed if cv_mute is off. static void Name_OnChange(void) { - if (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) + if ((cv_mute.value || players[consoleplayer].muted) && !(server || IsPlayerAdmin(consoleplayer))) { CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n")); CV_StealthSet(&cv_playername, player_names[consoleplayer]); @@ -4786,7 +4897,7 @@ static void Name_OnChange(void) static void Name2_OnChange(void) { - if (cv_mute.value) //Secondary player can't be admin. + if (cv_mute.value || players[consoleplayer].muted) //Secondary player can't be admin. { CONS_Alert(CONS_NOTICE, M_GetText("You may not change your name when chat is muted.\n")); CV_StealthSet(&cv_playername2, player_names[secondarydisplayplayer]); @@ -4797,11 +4908,13 @@ static void Name2_OnChange(void) static boolean Skin_CanChange(const char *valstr) { - (void)valstr; - if (!Playing()) return true; // do whatever you want + // You already are that skin. + if (stricmp(skins[players[consoleplayer].skin]->name, valstr) == 0) + return false; + if (!(multiplayer || netgame)) // In single player. return true; @@ -4816,11 +4929,13 @@ static boolean Skin_CanChange(const char *valstr) static boolean Skin2_CanChange(const char *valstr) { - (void)valstr; - if (!Playing() || !splitscreen) return true; // do whatever you want + // You already are that skin. + if (stricmp(skins[players[secondarydisplayplayer].skin]->name, valstr) == 0) + return false; + if (CanChangeSkin(secondarydisplayplayer) && !P_PlayerMoving(secondarydisplayplayer)) return true; else @@ -4836,6 +4951,8 @@ static boolean Skin2_CanChange(const char *valstr) */ static void Skin_OnChange(void) { + pickedchar = R_SkinAvailable(cv_skin.string); + if (!Playing()) return; diff --git a/src/netcode/d_netcmd.h b/src/netcode/d_netcmd.h index e30fa4a0245b1dd2b54617b1f7df4f3700c75188..c11575575fc025bcce4ad755651e3b77493233db 100644 --- a/src/netcode/d_netcmd.h +++ b/src/netcode/d_netcmd.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -94,7 +94,10 @@ extern consvar_t cv_inttime, cv_coopstarposts, cv_cooplives, cv_advancemap, cv_p extern consvar_t cv_overtime; extern consvar_t cv_startinglives; -// for F_finale.c +extern consvar_t cv_gravity, cv_movebob; +extern consvar_t cv_tailspickup; + +// for f_finale.c extern consvar_t cv_rollingdemos; extern consvar_t cv_ringslinger, cv_soundtest; @@ -105,7 +108,6 @@ extern consvar_t cv_maxping; extern consvar_t cv_pingtimeout; extern consvar_t cv_showping; - extern consvar_t cv_skipmapcheck; extern consvar_t cv_sleep; @@ -147,6 +149,7 @@ typedef enum XD_LUACMD, // 22 XD_LUAVAR, // 23 XD_LUAFILE, // 24 + XD_MUTEPLAYER, // 25 MAXNETXCMD } netxcmd_t; diff --git a/src/netcode/d_netfil.c b/src/netcode/d_netfil.c index 03ad8303e6571a477b9f107154d9ed3102ac58a9..bfb67838ff68e3831914e77dd029ffa19942eaac 100644 --- a/src/netcode/d_netfil.c +++ b/src/netcode/d_netfil.c @@ -95,6 +95,7 @@ static filetran_t transfer[MAXNETNODES]; INT32 fileneedednum; // Number of files needed to join the server fileneeded_t *fileneeded; // List of needed files static tic_t lasttimeackpacketsent = 0; +static I_mutex downloadmutex; char downloaddir[512] = "DOWNLOAD"; // For resuming failed downloads @@ -606,7 +607,7 @@ void AddLuaFileTransfer(const char *filename, const char *mode) prevnext = &((*prevnext)->next); // Allocate file transfer information and append it to the transfer list - filetransfer = malloc(sizeof(luafiletransfer_t)); + filetransfer = calloc(1, sizeof(luafiletransfer_t)); if (!filetransfer) I_Error("AddLuaFileTransfer: Out of memory\n"); *prevnext = filetransfer; @@ -1033,7 +1034,6 @@ void FileSendTicker(void) netbuffer->packettype = PT_FILEFRAGMENT; - // (((sendbytes-nowsentbyte)*TICRATE)/(I_GetTime()-starttime)<(UINT32)net_bandwidth) while (packetsent-- && filestosend != 0) { for (i = currentnode, j = 0; j < MAXNETNODES; @@ -1345,9 +1345,9 @@ void PT_FileFragment(SINT8 node, INT32 netconsole) if (!(strcmp(filename, "srb2.pk3") && strcmp(filename, "zones.pk3") - && strcmp(filename, "player.dta") + && strcmp(filename, "characters.pk3") && strcmp(filename, "patch.pk3") - && strcmp(filename, "music.dta") + && strcmp(filename, "music.pk3") )) I_Error("Tried to download \"%s\"", filename); @@ -1610,11 +1610,13 @@ boolean CURLPrepareFile(const char* url, int dfilenum) I_Error("Attempted to download files in -nodownload mode"); #endif - curl_global_init(CURL_GLOBAL_ALL); + if (!multi_handle) + { + curl_global_init(CURL_GLOBAL_ALL); + multi_handle = curl_multi_init(); + } http_handle = curl_easy_init(); - multi_handle = curl_multi_init(); - if (http_handle && multi_handle) { I_mkdir(downloaddir, 0755); @@ -1640,7 +1642,7 @@ boolean CURLPrepareFile(const char* url, int dfilenum) #endif // Set user agent, as some servers won't accept invalid user agents. - curl_easy_setopt(http_handle, CURLOPT_USERAGENT, va("Sonic Robo Blast 2/v%d.%d", VERSION, SUBVERSION)); + curl_easy_setopt(http_handle, CURLOPT_USERAGENT, va("Sonic Robo Blast 2/%s", VERSIONSTRING)); // Authenticate if the user so wishes login = CURLGetLogin(url, NULL); @@ -1673,6 +1675,8 @@ boolean CURLPrepareFile(const char* url, int dfilenum) filedownload.current = dfilenum; filedownload.http_running = true; + I_spawn_thread("http-download", (I_thread_fn)CURLGetFile, NULL); + return true; } @@ -1681,103 +1685,119 @@ boolean CURLPrepareFile(const char* url, int dfilenum) return false; } +void CURLAbortFile(void) +{ + filedownload.http_running = false; + + // lock and unlock to wait for the download thread to exit + I_lock_mutex(&downloadmutex); + I_unlock_mutex(downloadmutex); +} + void CURLGetFile(void) { + I_lock_mutex(&downloadmutex); CURLMcode mc; /* return code used by curl_multi_wait() */ CURLcode easyres; /* Return from easy interface */ - int numfds; CURLMsg *m; /* for picking up messages with the transfer status */ CURL *e; int msgs_left; /* how many messages are left */ const char *easy_handle_error; + boolean running = true; - if (curl_runninghandles) + while (running && filedownload.http_running) { - curl_multi_perform(multi_handle, &curl_runninghandles); + if (curl_runninghandles) + { + curl_multi_perform(multi_handle, &curl_runninghandles); - /* wait for activity, timeout or "nothing" */ - mc = curl_multi_wait(multi_handle, NULL, 0, 1000, &numfds); + /* wait for activity, timeout or "nothing" */ + mc = curl_multi_wait(multi_handle, NULL, 0, 1000, NULL); - if (mc != CURLM_OK) - { - CONS_Alert(CONS_WARNING, "curl_multi_wait() failed, code %d.\n", mc); - return; + if (mc != CURLM_OK) + { + CONS_Alert(CONS_WARNING, "curl_multi_wait() failed, code %d.\n", mc); + continue; + } + curl_curfile->currentsize = curl_dlnow; + curl_curfile->totalsize = curl_dltotal; } - curl_curfile->currentsize = curl_dlnow; - curl_curfile->totalsize = curl_dltotal; - } - /* See how the transfers went */ - while ((m = curl_multi_info_read(multi_handle, &msgs_left))) - { - if (m && (m->msg == CURLMSG_DONE)) + /* See how the transfers went */ + while ((m = curl_multi_info_read(multi_handle, &msgs_left))) { - e = m->easy_handle; - easyres = m->data.result; - - char *filename = Z_StrDup(curl_realname); - nameonly(filename); - - if (easyres != CURLE_OK) + if (m && (m->msg == CURLMSG_DONE)) { - long response_code = 0; + running = false; + e = m->easy_handle; + easyres = m->data.result; - if (easyres == CURLE_HTTP_RETURNED_ERROR) - curl_easy_getinfo(e, CURLINFO_RESPONSE_CODE, &response_code); + char *filename = Z_StrDup(curl_realname); + nameonly(filename); - if (response_code == 404) - curl_curfile->failed = FDOWNLOAD_FAIL_NOTFOUND; - else - curl_curfile->failed = FDOWNLOAD_FAIL_OTHER; - - easy_handle_error = (response_code) ? va("HTTP response code %ld", response_code) : curl_easy_strerror(easyres); - curl_curfile->status = FS_FALLBACK; - curl_curfile->currentsize = curl_origfilesize; - curl_curfile->totalsize = curl_origtotalfilesize; - filedownload.http_failed = true; - fclose(curl_curfile->file); - remove(curl_curfile->filename); - CONS_Alert(CONS_ERROR, M_GetText("Failed to download addon \"%s\" (%s)\n"), filename, easy_handle_error); - } - else - { - fclose(curl_curfile->file); + if (easyres != CURLE_OK) + { + long response_code = 0; - CONS_Printf(M_GetText("Finished download of \"%s\"\n"), filename); + if (easyres == CURLE_HTTP_RETURNED_ERROR) + curl_easy_getinfo(e, CURLINFO_RESPONSE_CODE, &response_code); - if (checkfilemd5(curl_curfile->filename, curl_curfile->md5sum) == FS_MD5SUMBAD) - { - CONS_Alert(CONS_WARNING, M_GetText("File \"%s\" does not match the version used by the server\n"), filename); + if (response_code == 404) + curl_curfile->failed = FDOWNLOAD_FAIL_NOTFOUND; + else + curl_curfile->failed = FDOWNLOAD_FAIL_OTHER; + + easy_handle_error = (response_code) ? va("HTTP response code %ld", response_code) : curl_easy_strerror(easyres); curl_curfile->status = FS_FALLBACK; - curl_curfile->failed = FDOWNLOAD_FAIL_MD5SUMBAD; + curl_curfile->currentsize = curl_origfilesize; + curl_curfile->totalsize = curl_origtotalfilesize; filedownload.http_failed = true; + fclose(curl_curfile->file); + remove(curl_curfile->filename); + CONS_Alert(CONS_ERROR, M_GetText("Failed to download addon \"%s\" (%s)\n"), filename, easy_handle_error); } else { - filedownload.completednum++; - filedownload.completedsize += curl_curfile->totalsize; - curl_curfile->status = FS_FOUND; + fclose(curl_curfile->file); + + CONS_Printf(M_GetText("Finished download of \"%s\"\n"), filename); + + if (checkfilemd5(curl_curfile->filename, curl_curfile->md5sum) == FS_MD5SUMBAD) + { + CONS_Alert(CONS_WARNING, M_GetText("File \"%s\" does not match the version used by the server\n"), filename); + curl_curfile->status = FS_FALLBACK; + curl_curfile->failed = FDOWNLOAD_FAIL_MD5SUMBAD; + filedownload.http_failed = true; + } + else + { + filedownload.completednum++; + filedownload.completedsize += curl_curfile->totalsize; + curl_curfile->status = FS_FOUND; + } } - } - Z_Free(filename); + Z_Free(filename); - curl_curfile->file = NULL; - filedownload.http_running = false; - filedownload.remaining--; - curl_multi_remove_handle(multi_handle, e); - curl_easy_cleanup(e); + curl_curfile->file = NULL; + filedownload.remaining--; + curl_multi_remove_handle(multi_handle, e); + curl_easy_cleanup(e); - if (!filedownload.remaining) - break; + if (!filedownload.remaining) + break; + } } } - if (!filedownload.remaining) + if (!filedownload.remaining || !filedownload.http_running) { curl_multi_cleanup(multi_handle); curl_global_cleanup(); + multi_handle = NULL; } + filedownload.http_running = false; + I_unlock_mutex(downloadmutex); } HTTP_login * diff --git a/src/netcode/d_netfil.h b/src/netcode/d_netfil.h index 4039b5e2d5cc4b0d81fbdc04e6d7c7bef46f724a..9f29d18bb79ff39dda69fffd68e2756f8d4f0db9 100644 --- a/src/netcode/d_netfil.h +++ b/src/netcode/d_netfil.h @@ -140,6 +140,7 @@ boolean CL_SendFileRequest(void); void PT_RequestFile(SINT8 node); boolean CURLPrepareFile(const char* url, int dfilenum); +void CURLAbortFile(void); void CURLGetFile(void); HTTP_login * CURLGetLogin (const char *url, HTTP_login ***return_prev_next); diff --git a/src/netcode/gamestate.c b/src/netcode/gamestate.c index f36347c6d88e94a444fb186937d2672cfe3a0df9..967e23650e141fd231a9a740588cc822b6b00c0b 100644 --- a/src/netcode/gamestate.c +++ b/src/netcode/gamestate.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -54,30 +54,25 @@ boolean SV_ResendingSavegameToAnyone(void) void SV_SendSaveGame(INT32 node, boolean resending) { size_t length, compressedlen; - UINT8 *savebuffer; + save_t savebuffer; UINT8 *compressedsave; UINT8 *buffertosend; // first save it in a malloced buffer - savebuffer = (UINT8 *)malloc(SAVEGAMESIZE); - if (!savebuffer) + savebuffer.size = SAVEGAMESIZE; + savebuffer.buf = (UINT8 *)malloc(savebuffer.size); + if (!savebuffer.buf) { CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); return; } // Leave room for the uncompressed length. - save_p = savebuffer + sizeof(UINT32); + savebuffer.pos = sizeof(UINT32); - P_SaveNetGame(resending); + P_SaveNetGame(&savebuffer, resending); - length = save_p - savebuffer; - if (length > SAVEGAMESIZE) - { - free(savebuffer); - save_p = NULL; - I_Error("Savegame buffer overrun"); - } + length = savebuffer.pos; // Allocate space for compressed save: one byte fewer than for the // uncompressed data to ensure that the compression is worthwhile. @@ -85,15 +80,16 @@ void SV_SendSaveGame(INT32 node, boolean resending) if (!compressedsave) { CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); + free(savebuffer.buf); return; } // Attempt to compress it. - if((compressedlen = lzf_compress(savebuffer + sizeof(UINT32), length - sizeof(UINT32), compressedsave + sizeof(UINT32), length - sizeof(UINT32) - 1))) + if((compressedlen = lzf_compress(savebuffer.buf + sizeof(UINT32), length - sizeof(UINT32), compressedsave + sizeof(UINT32), length - sizeof(UINT32) - 1))) { // Compressing succeeded; send compressed data - free(savebuffer); + free(savebuffer.buf); // State that we're compressed. buffertosend = compressedsave; @@ -107,12 +103,12 @@ void SV_SendSaveGame(INT32 node, boolean resending) free(compressedsave); // State that we're not compressed - buffertosend = savebuffer; - WRITEUINT32(savebuffer, 0); + buffertosend = savebuffer.buf; + savebuffer.pos = 0; + P_WriteUINT32(&savebuffer, 0); } AddRamToSendQueue(node, buffertosend, length, SF_RAM, 0); - save_p = NULL; // Remember when we started sending the savegame so we can handle timeouts netnodes[node].sendingsavegame = true; @@ -125,8 +121,7 @@ static consvar_t cv_dumpconsistency = CVAR_INIT ("dumpconsistency", "Off", CV_SA void SV_SavedGame(void) { - size_t length; - UINT8 *savebuffer; + save_t savebuffer; char tmpsave[256]; if (!cv_dumpconsistency.value) @@ -135,29 +130,22 @@ void SV_SavedGame(void) sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); // first save it in a malloced buffer - save_p = savebuffer = (UINT8 *)malloc(SAVEGAMESIZE); - if (!save_p) + savebuffer.size = SAVEGAMESIZE; + savebuffer.buf = (UINT8 *)malloc(savebuffer.size); + if (!savebuffer.buf) { CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n")); return; } + savebuffer.pos = 0; - P_SaveNetGame(false); - - length = save_p - savebuffer; - if (length > SAVEGAMESIZE) - { - free(savebuffer); - save_p = NULL; - I_Error("Savegame buffer overrun"); - } + P_SaveNetGame(&savebuffer, false); // then save it! - if (!FIL_WriteFile(tmpsave, savebuffer, length)) + if (!FIL_WriteFile(tmpsave, savebuffer.buf, savebuffer.pos)) CONS_Printf(M_GetText("Didn't save %s for netgame"), tmpsave); - free(savebuffer); - save_p = NULL; + free(savebuffer.pos); } #undef TMPSAVENAME @@ -167,33 +155,34 @@ void SV_SavedGame(void) void CL_LoadReceivedSavegame(boolean reloading) { - UINT8 *savebuffer = NULL; - size_t length, decompressedlen; + save_t savebuffer; + size_t decompressedlen; char tmpsave[256]; FreeFileNeeded(); sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home); - length = FIL_ReadFile(tmpsave, &savebuffer); + savebuffer.size = FIL_ReadFile(tmpsave, &savebuffer.buf); + savebuffer.pos = 0; - CONS_Printf(M_GetText("Loading savegame length %s\n"), sizeu1(length)); - if (!length) + CONS_Printf(M_GetText("Loading savegame length %s\n"), sizeu1(savebuffer.size)); + if (!savebuffer.size) { I_Error("Can't read savegame sent"); return; } - save_p = savebuffer; - // Decompress saved game if necessary. - decompressedlen = READUINT32(save_p); + decompressedlen = P_ReadUINT32(&savebuffer); if(decompressedlen > 0) { UINT8 *decompressedbuffer = Z_Malloc(decompressedlen, PU_STATIC, NULL); - lzf_decompress(save_p, length - sizeof(UINT32), decompressedbuffer, decompressedlen); - Z_Free(savebuffer); - save_p = savebuffer = decompressedbuffer; + lzf_decompress(savebuffer.buf + sizeof(UINT32), savebuffer.size - sizeof(UINT32), decompressedbuffer, decompressedlen); + Z_Free(savebuffer.buf); + savebuffer.buf = decompressedbuffer; + savebuffer.size = decompressedlen; + savebuffer.pos = 0; } paused = false; @@ -203,7 +192,7 @@ void CL_LoadReceivedSavegame(boolean reloading) automapactive = false; // load a base level - if (P_LoadNetGame(reloading)) + if (P_LoadNetGame(&savebuffer, reloading)) { const UINT8 actnum = mapheaderinfo[gamemap-1]->actnum; CONS_Printf(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap)); @@ -219,8 +208,7 @@ void CL_LoadReceivedSavegame(boolean reloading) } // done - Z_Free(savebuffer); - save_p = NULL; + Z_Free(savebuffer.buf); if (unlink(tmpsave) == -1) CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), tmpsave); consistancy[gametic%BACKUPTICS] = Consistancy(); diff --git a/src/netcode/http-mserv.c b/src/netcode/http-mserv.c index 2b52380cf506f00f119dc01b5f0ab3b47ff4e6f6..8ce20af956008d2e522a08dc0aa98756174252d8 100644 --- a/src/netcode/http-mserv.c +++ b/src/netcode/http-mserv.c @@ -134,7 +134,7 @@ HMS_on_read (char *s, size_t _1, size_t n, void *userdata) return n; } -static struct HMS_buffer * +FUNCDEBUG static struct HMS_buffer * HMS_connect (int proto, const char *format, ...) { va_list ap; @@ -426,7 +426,7 @@ HMS_register (void) char *title; - hms = HMS_connect(PROTO_V4, "rooms/%d/register", ms_RoomId); + hms = HMS_connect(PROTO_V4, "rooms/%d/register", cv_masterserver_room_id.value); if (! hms) return 0; @@ -462,7 +462,7 @@ HMS_register (void) if (!hms_allow_ipv6) return ok; - hms = HMS_connect(PROTO_V6, "rooms/%d/register", ms_RoomId); + hms = HMS_connect(PROTO_V6, "rooms/%d/register", cv_masterserver_room_id.value); if (! hms) return 0; @@ -486,20 +486,23 @@ int HMS_unlist (void) { struct HMS_buffer *hms; - int ok; + int ok = 0; - hms = HMS_connect(PROTO_V4, "servers/%s/unlist", hms_server_token); + if (hms_server_token) + { + hms = HMS_connect(PROTO_V4, "servers/%s/unlist", hms_server_token); - if (! hms) - return 0; + if (! hms) + return 0; - curl_easy_setopt(hms->curl, CURLOPT_POST, 1); - curl_easy_setopt(hms->curl, CURLOPT_POSTFIELDSIZE, 0); + curl_easy_setopt(hms->curl, CURLOPT_POST, 1); + curl_easy_setopt(hms->curl, CURLOPT_POSTFIELDSIZE, 0); - ok = HMS_do(hms); - HMS_end(hms); + ok = HMS_do(hms); + HMS_end(hms); - free(hms_server_token); + free(hms_server_token); + } #ifndef NO_IPV6 if (hms_server_token_ipv6 && hms_allow_ipv6) @@ -526,18 +529,13 @@ int HMS_update (void) { struct HMS_buffer *hms; - int ok; + int ok = 0; char post[256]; char *title; - hms = HMS_connect(PROTO_V4, "servers/%s/update", hms_server_token); - - if (! hms) - return 0; - - title = curl_easy_escape(hms->curl, cv_servername.string, 0); + title = curl_easy_escape(NULL, cv_servername.string, 0); snprintf(post, sizeof post, "title=%s", @@ -546,10 +544,18 @@ HMS_update (void) curl_free(title); - curl_easy_setopt(hms->curl, CURLOPT_POSTFIELDS, post); + if (hms_server_token) + { + hms = HMS_connect(PROTO_V4, "servers/%s/update", hms_server_token); - ok = HMS_do(hms); - HMS_end(hms); + if (! hms) + return 0; + + curl_easy_setopt(hms->curl, CURLOPT_POSTFIELDS, post); + + ok = HMS_do(hms); + HMS_end(hms); + } #ifndef NO_IPV6 if (hms_server_token_ipv6 && hms_allow_ipv6) diff --git a/src/netcode/i_net.h b/src/netcode/i_net.h index 09b842296c313cdd43623cfecd1d8da64534397b..a2039bd1902197d1c812f7490fad3e1493f60588 100644 --- a/src/netcode/i_net.h +++ b/src/netcode/i_net.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -32,7 +32,6 @@ #define INETPACKETLENGTH 1024 extern INT16 hardware_MAXPACKETLENGTH; -extern INT32 net_bandwidth; // in byte/s #if defined(_MSC_VER) #pragma pack(1) @@ -40,36 +39,17 @@ extern INT32 net_bandwidth; // in byte/s typedef struct { - /// Supposed to be DOOMCOM_ID - INT32 id; - - /// SRB2 executes an INT32 to execute commands. - INT16 intnum; - /// Communication between SRB2 and the driver. - /// Is CMD_SEND or CMD_GET. - INT16 command; /// Is dest for send, set by get (-1 = no packet). INT16 remotenode; - /// Number of bytes in doomdata to be sent INT16 datalength; /// Info common to all nodes. /// Console is always node 0. INT16 numnodes; - /// Flag: 1 = no duplication, 2-5 = dup for slow nets. - INT16 ticdup; /// Flag: 1 = send a backup tic in every packet. INT16 extratics; - /// kind of game - INT16 gametype; - /// Flag: -1 = new game, 0-5 = load savegame - INT16 savegame; - /// currect map - INT16 map; - - /// Info specific to this node. - INT16 consoleplayer; + /// Number of "slots": the highest player number in use plus one. INT16 numslots; @@ -87,18 +67,10 @@ extern doomcom_t *doomcom; */ extern boolean (*I_NetGet)(void); -/** \brief ask to driver if there is data waiting -*/ -extern boolean (*I_NetCanGet)(void); - /** \brief send packet within doomcom struct */ extern void (*I_NetSend)(void); -/** \brief ask to driver if all is ok to send data now -*/ -extern boolean (*I_NetCanSend)(void); - /** \brief close a connection \param nodenum node to be closed diff --git a/src/netcode/i_tcp.c b/src/netcode/i_tcp.c index 6d9a2725a3c65fb93e3f1f3b89e47dcf0464ad05..256d9992eff6acdd614ac9bf99428e459884fe2a 100644 --- a/src/netcode/i_tcp.c +++ b/src/netcode/i_tcp.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -37,6 +37,7 @@ #endif #include "../doomdef.h" +#include "../z_zone.h" #ifdef USE_WINSOCK1 #include <winsock.h> @@ -87,6 +88,10 @@ #undef EHOSTUNREACH #endif #define EHOSTUNREACH WSAEHOSTUNREACH + #ifdef ENETUNREACH + #undef ENETUNREACH + #endif + #define ENETUNREACH WSAENETUNREACH #ifndef IOC_VENDOR #define IOC_VENDOR 0x18000000 #endif @@ -114,20 +119,12 @@ typedef union } mysockaddr_t; #ifdef HAVE_MINIUPNPC - #ifdef MINIUPNP_STATICLIB - #include "miniwget.h" - #include "miniupnpc.h" - #include "upnpcommands.h" - #else - #include "miniupnpc/miniwget.h" - #include "miniupnpc/miniupnpc.h" - #include "miniupnpc/upnpcommands.h" - #endif - static boolean UPNP_support = true; + #include "miniupnpc/miniwget.h" + #include "miniupnpc/miniupnpc.h" + #include "miniupnpc/upnpcommands.h" + static boolean UPNP_support = true; #endif // HAVE_MINIUPNC -#define MAXBANS 100 - #include "../i_system.h" #include "i_net.h" #include "d_net.h" @@ -146,7 +143,6 @@ typedef union #endif #include "i_addrinfo.h" -#define SELECTTEST #define DEFAULTPORT "5029" #ifdef USE_WINSOCK @@ -175,8 +171,8 @@ static mysockaddr_t clientaddress[MAXNETNODES+1]; static mysockaddr_t broadcastaddress[MAXNETNODES+1]; static size_t broadcastaddresses = 0; static boolean nodeconnected[MAXNETNODES+1]; -static mysockaddr_t banned[MAXBANS]; -static UINT8 bannedmask[MAXBANS]; +static mysockaddr_t *banned; +static UINT8 *bannedmask; static size_t numbans = 0; static boolean SOCK_bannednode[MAXNETNODES+1]; /// \note do we really need the +1? @@ -265,7 +261,7 @@ static const char* inet_ntopA(short af, const void *cp, char *buf, socklen_t len #ifdef HAVE_MINIUPNPC // based on old XChat patch static void I_ShutdownUPnP(void); static void I_InitUPnP(void); -I_mutex upnp_mutex; +static I_mutex upnp_mutex; static struct UPNPUrls urls; static struct IGDdatas data; static char lanaddr[64]; @@ -300,7 +296,11 @@ init_upnpc_once(struct upnpdata *upnpuserdata) int upnp_error = -2; int scope_id = 0; int status_code = 0; - CONS_Printf(M_GetText("Looking for UPnP Internet Gateway Device\n")); + + memset(&urls, 0, sizeof(struct UPNPUrls)); + memset(&data, 0, sizeof(struct IGDdatas)); + + I_OutputMsg(M_GetText("Looking for UPnP Internet Gateway Device\n")); devlist = upnpDiscoverDevices(deviceTypes, 500, NULL, NULL, 0, false, 2, &upnp_error, 0); if (devlist) { @@ -316,39 +316,41 @@ init_upnpc_once(struct upnpdata *upnpuserdata) if (!dev) dev = devlist; /* defaulting to first device */ - CONS_Printf(M_GetText("Found UPnP device:\n desc: %s\n st: %s\n"), + I_OutputMsg(M_GetText("Found UPnP device:\n desc: %s\n st: %s\n"), dev->descURL, dev->st); +#if (MINIUPNPC_API_VERSION >= 18) + UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr), NULL, 0); +#else UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); - CONS_Printf(M_GetText("Local LAN IP address: %s\n"), lanaddr); +#endif + I_OutputMsg(M_GetText("Local LAN IP address: %s\n"), lanaddr); descXML = miniwget(dev->descURL, &descXMLsize, scope_id, &status_code); if (descXML) { parserootdesc(descXML, descXMLsize, &data); free(descXML); descXML = NULL; - memset(&urls, 0, sizeof(struct UPNPUrls)); - memset(&data, 0, sizeof(struct IGDdatas)); GetUPNPUrls(&urls, &data, dev->descURL, status_code); I_AddExitFunc(I_ShutdownUPnP); } freeUPNPDevlist(devlist); - I_unlock_mutex(upnp_mutex); } else if (upnp_error == UPNPDISCOVER_SOCKET_ERROR) { - CONS_Printf(M_GetText("No UPnP devices discovered\n")); + I_OutputMsg(M_GetText("No UPnP devices discovered\n")); } + I_unlock_mutex(upnp_mutex); upnpuserdata->upnpc_started =1; } static inline void I_UPnP_add(const char * addr, const char *port, const char * servicetype) { + if (!urls.controlURL || urls.controlURL[0] == '\0') + return; I_lock_mutex(&upnp_mutex); if (addr == NULL) addr = lanaddr; - if (!urls.controlURL || urls.controlURL[0] == '\0') - return; UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, port, port, addr, "SRB2", servicetype, NULL, NULL); I_unlock_mutex(upnp_mutex); @@ -356,9 +358,9 @@ static inline void I_UPnP_add(const char * addr, const char *port, const char * static inline void I_UPnP_rem(const char *port, const char * servicetype) { - I_lock_mutex(&upnp_mutex); if (!urls.controlURL || urls.controlURL[0] == '\0') return; + I_lock_mutex(&upnp_mutex); UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port, servicetype, NULL); I_unlock_mutex(upnp_mutex); @@ -628,56 +630,6 @@ static boolean SOCK_Get(void) return false; } -// check if we can send (do not go over the buffer) - -static fd_set masterset; - -#ifdef SELECTTEST -static boolean FD_CPY(fd_set *src, fd_set *dst, SOCKET_TYPE *fd, size_t len) -{ - boolean testset = false; - FD_ZERO(dst); - for (size_t i = 0; i < len;i++) - { - if(fd[i] != (SOCKET_TYPE)ERRSOCKET && - FD_ISSET(fd[i], src) && !FD_ISSET(fd[i], dst)) // no checking for dups - { - FD_SET(fd[i], dst); - testset = true; - } - } - return testset; -} - -static boolean SOCK_CanSend(void) -{ - struct timeval timeval_for_select = {0, 0}; - fd_set tset; - int wselect; - - if(!FD_CPY(&masterset, &tset, mysockets, mysocketses)) - return false; - wselect = select(255, NULL, &tset, NULL, &timeval_for_select); - if (wselect >= 1) - return true; - return false; -} - -static boolean SOCK_CanGet(void) -{ - struct timeval timeval_for_select = {0, 0}; - fd_set tset; - int rselect; - - if(!FD_CPY(&masterset, &tset, mysockets, mysocketses)) - return false; - rselect = select(255, &tset, NULL, NULL, &timeval_for_select); - if (rselect >= 1) - return true; - return false; -} -#endif - static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr) { socklen_t d4 = (socklen_t)sizeof(struct sockaddr_in); @@ -685,7 +637,6 @@ static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr socklen_t d6 = (socklen_t)sizeof(struct sockaddr_in6); #endif socklen_t d, da = (socklen_t)sizeof(mysockaddr_t); - ssize_t status; switch (sockaddr->any.sa_family) { @@ -696,14 +647,11 @@ static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr default: d = da; break; } - status = sendto(socket, (char *)&doomcom->data, doomcom->datalength, 0, &sockaddr->any, d); - if (status == -1) - { - CONS_Alert(CONS_WARNING, "Unable to send packet to %s: %s\n", SOCK_AddrToStr(sockaddr), strerror(errno)); - } - return status; + return sendto(socket, (char *)&doomcom->data, doomcom->datalength, 0, &sockaddr->any, d); } +#define ALLOWEDERROR(x) ((x) == ECONNREFUSED || (x) == EWOULDBLOCK || (x) == EHOSTUNREACH || (x) == ENETUNREACH) + static void SOCK_Send(void) { ssize_t c = ERRSOCKET; @@ -718,19 +666,25 @@ static void SOCK_Send(void) for (size_t j = 0; j < broadcastaddresses; j++) { if (myfamily[i] == broadcastaddress[j].any.sa_family) - SOCK_SendToAddr(mysockets[i], &broadcastaddress[j]); + { + c = SOCK_SendToAddr(mysockets[i], &broadcastaddress[j]); + if (c == ERRSOCKET && !ALLOWEDERROR(errno)) + break; + } } } - return; } else if (nodesocket[doomcom->remotenode] == (SOCKET_TYPE)ERRSOCKET) { for (size_t i = 0; i < mysocketses; i++) { if (myfamily[i] == clientaddress[doomcom->remotenode].any.sa_family) - SOCK_SendToAddr(mysockets[i], &clientaddress[doomcom->remotenode]); + { + c = SOCK_SendToAddr(mysockets[i], &clientaddress[doomcom->remotenode]); + if (c == ERRSOCKET && !ALLOWEDERROR(errno)) + break; + } } - return; } else { @@ -740,12 +694,14 @@ static void SOCK_Send(void) if (c == ERRSOCKET) { int e = errno; // save error code so it can't be modified later - if (e != ECONNREFUSED && e != EWOULDBLOCK && e != EHOSTUNREACH) + if (!ALLOWEDERROR(e)) I_Error("SOCK_Send, error sending to node %d (%s) #%u: %s", doomcom->remotenode, SOCK_GetNodeAddress(doomcom->remotenode), e, strerror(e)); } } +#undef ALLOWEDERROR + static void SOCK_FreeNodenum(INT32 numnode) { // can't disconnect from self :) @@ -915,7 +871,6 @@ static boolean UDP_Socket(void) mysockets[s] = ERRSOCKET; for (s = 0; s < MAXNETNODES+1; s++) nodesocket[s] = ERRSOCKET; - FD_ZERO(&masterset); s = 0; memset(&hints, 0x00, sizeof (hints)); @@ -942,7 +897,6 @@ static boolean UDP_Socket(void) mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen); if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET) { - FD_SET(mysockets[s], &masterset); myfamily[s] = hints.ai_family; s++; } @@ -963,7 +917,6 @@ static boolean UDP_Socket(void) mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen); if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET) { - FD_SET(mysockets[s], &masterset); myfamily[s] = hints.ai_family; s++; #ifdef HAVE_MINIUPNPC @@ -996,7 +949,6 @@ static boolean UDP_Socket(void) mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen); if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET) { - FD_SET(mysockets[s], &masterset); myfamily[s] = hints.ai_family; s++; } @@ -1017,7 +969,6 @@ static boolean UDP_Socket(void) mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen); if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET) { - FD_SET(mysockets[s], &masterset); myfamily[s] = hints.ai_family; s++; } @@ -1132,10 +1083,10 @@ boolean I_InitTcpDriver(void) { I_AddExitFunc(I_ShutdownTcpDriver); #ifdef HAVE_MINIUPNPC - if (M_CheckParm("-noUPnP")) - UPNP_support = false; - else + if (M_CheckParm("-useUPnP")) I_InitUPnP(); + else + UPNP_support = false; #endif } return init_tcp_driver; @@ -1143,16 +1094,13 @@ boolean I_InitTcpDriver(void) static void SOCK_CloseSocket(void) { - for (size_t i=0; i < MAXNETNODES+1; i++) + for (size_t i=0; i < mysocketses; i++) { - if (mysockets[i] != (SOCKET_TYPE)ERRSOCKET - && FD_ISSET(mysockets[i], &masterset)) - { - FD_CLR(mysockets[i], &masterset); + if (mysockets[i] != (SOCKET_TYPE)ERRSOCKET) close(mysockets[i]); - } mysockets[i] = ERRSOCKET; } + mysocketses = 0; } void I_ShutdownTcpDriver(void) @@ -1204,11 +1152,7 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) // test ip address of server for (i = 0; i < mysocketses; ++i) { - /* 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) + if (runp->ai_addr->sa_family == myfamily[i]) { memcpy(&clientaddress[newnode], runp->ai_addr, runp->ai_addrlen); break; @@ -1238,12 +1182,6 @@ static boolean SOCK_OpenSocket(void) I_NetFreeNodenum = SOCK_FreeNodenum; I_NetMakeNodewPort = SOCK_NetMakeNodewPort; -#ifdef SELECTTEST - // seem like not work with libsocket : ( - I_NetCanSend = SOCK_CanSend; - I_NetCanGet = SOCK_CanGet; -#endif - // build the socket but close it first SOCK_CloseSocket(); return UDP_Socket(); @@ -1253,9 +1191,9 @@ static boolean SOCK_Ban(INT32 node) { if (node > MAXNETNODES) return false; - if (numbans == MAXBANS) - return false; + banned = Z_Realloc(banned, sizeof(*banned) * (numbans+1), PU_STATIC, NULL); + bannedmask = Z_Realloc(bannedmask, sizeof(*bannedmask) * (numbans+1), PU_STATIC, NULL); M_Memcpy(&banned[numbans], &clientaddress[node], sizeof (mysockaddr_t)); if (banned[numbans].any.sa_family == AF_INET) { @@ -1266,7 +1204,7 @@ static boolean SOCK_Ban(INT32 node) else if (banned[numbans].any.sa_family == AF_INET6) { banned[numbans].ip6.sin6_port = 0; - bannedmask[numbans] = 128; + bannedmask[numbans] = 64; } #endif numbans++; @@ -1278,7 +1216,7 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask) struct my_addrinfo *ai, *runp, hints; int gaie; - if (numbans == MAXBANS || !address) + if (!address) return false; memset(&hints, 0x00, sizeof(hints)); @@ -1293,15 +1231,17 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask) runp = ai; - while(runp != NULL && numbans != MAXBANS) + while(runp != NULL) { + banned = Z_Realloc(banned, sizeof(*banned) * (numbans+1), PU_STATIC, NULL); + bannedmask = Z_Realloc(bannedmask, sizeof(*bannedmask) * (numbans+1), PU_STATIC, NULL); memcpy(&banned[numbans], runp->ai_addr, runp->ai_addrlen); if (mask) bannedmask[numbans] = (UINT8)atoi(mask); #ifdef HAVE_IPV6 else if (runp->ai_family == AF_INET6) - bannedmask[numbans] = 128; + bannedmask[numbans] = 64; #endif else bannedmask[numbans] = 32; @@ -1310,7 +1250,7 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask) bannedmask[numbans] = 32; #ifdef HAVE_IPV6 else if (bannedmask[numbans] > 128 && runp->ai_family == AF_INET6) - bannedmask[numbans] = 128; + bannedmask[numbans] = 64; #endif numbans++; runp = runp->ai_next; @@ -1324,6 +1264,10 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask) static void SOCK_ClearBans(void) { numbans = 0; + Z_Free(banned); + banned = NULL; + Z_Free(bannedmask); + bannedmask = NULL; } boolean I_InitTcpNetwork(void) @@ -1378,7 +1322,6 @@ boolean I_InitTcpNetwork(void) // FIXME: // ??? and now ? // server on a big modem ??? 4*isdn - net_bandwidth = 16000; hardware_MAXPACKETLENGTH = INETPACKETLENGTH; ret = true; @@ -1407,7 +1350,6 @@ boolean I_InitTcpNetwork(void) // so we're on a LAN COM_BufAddText("connect any\n"); - net_bandwidth = 800000; hardware_MAXPACKETLENGTH = MAXPACKETLENGTH; } } diff --git a/src/netcode/mserv.c b/src/netcode/mserv.c index 3acacd24c164471057ca3ffa7a6225f8ba95d2f3..f17db4b6e32e59a08a7ac5c9c3a44e867c0ffff2 100644 --- a/src/netcode/mserv.c +++ b/src/netcode/mserv.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // Copyright (C) 2020-2023 by James R. // // This program is free software distributed under the @@ -50,9 +50,12 @@ static void Command_Listserv_f(void); #endif/*MASTERSERVER*/ +static boolean ServerName_CanChange (const char*); + static void Update_parameters (void); static void MasterServer_OnChange(void); +static void RoomId_OnChange(void); static CV_PossibleValue_t masterserver_update_rate_cons_t[] = { {2, "MIN"}, @@ -61,11 +64,13 @@ static CV_PossibleValue_t masterserver_update_rate_cons_t[] = { }; consvar_t cv_masterserver = CVAR_INIT ("masterserver", "https://ds.ms.srb2.org/MS/0", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange); -consvar_t cv_servername = CVAR_INIT ("servername", "SRB2 server", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, NULL, Update_parameters); +consvar_t cv_servername = CVAR_INIT_WITH_CALLBACKS ("servername", "SRB2 server", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, NULL, Update_parameters, ServerName_CanChange); consvar_t cv_masterserver_update_rate = CVAR_INIT ("masterserver_update_rate", "15", CV_SAVE|CV_CALL|CV_NOINIT, masterserver_update_rate_cons_t, Update_parameters); +CV_PossibleValue_t cv_masterserver_room_values[] = {{-1, "MIN"}, {999999999, "MAX"}, {0, NULL}}; +consvar_t cv_masterserver_room_id = CVAR_INIT ("masterserver_room_id", "-1", CV_CALL, cv_masterserver_room_values, RoomId_OnChange); -INT16 ms_RoomId = -1; +static INT16 ms_RoomId = -1; #if defined (MASTERSERVER) && defined (HAVE_THREADS) int ms_QueryId; @@ -90,6 +95,7 @@ void AddMServCommands(void) { CV_RegisterVar(&cv_masterserver); CV_RegisterVar(&cv_masterserver_update_rate); + CV_RegisterVar(&cv_masterserver_room_id); CV_RegisterVar(&cv_masterserver_timeout); CV_RegisterVar(&cv_masterserver_debug); CV_RegisterVar(&cv_masterserver_token); @@ -444,7 +450,7 @@ void UnregisterServer(void) static boolean Online (void) { - return ( serverrunning && ms_RoomId > 0 ); + return ( serverrunning && cv_masterserver_room_id.value > 0 ); } static inline void SendPingToMasterServer(void) @@ -497,6 +503,15 @@ Set_api (const char *api) #endif/*MASTERSERVER*/ +static boolean ServerName_CanChange(const char* newvalue) +{ + if (strlen(newvalue) < MAXSERVERNAME) + return true; + + CONS_Alert(CONS_NOTICE, "The server name must be shorter than %d characters\n", MAXSERVERNAME); + return false; +} + static void Update_parameters (void) { @@ -523,6 +538,17 @@ Update_parameters (void) #endif/*MASTERSERVER*/ } +static void RoomId_OnChange(void) +{ + if (ms_RoomId != cv_masterserver_room_id.value) + { + UnregisterServer(); + ms_RoomId = cv_masterserver_room_id.value; + if (Online()) + RegisterServer(); + } +} + static void MasterServer_OnChange(void) { #ifdef MASTERSERVER diff --git a/src/netcode/mserv.h b/src/netcode/mserv.h index 0bc8c8e6b878a415887e2a9613188d3ceac30956..ed3c9b27b8f6d9f52b1c8cc4e2640b5501653dff 100644 --- a/src/netcode/mserv.h +++ b/src/netcode/mserv.h @@ -66,15 +66,11 @@ typedef struct extern consvar_t cv_masterserver, cv_servername; extern consvar_t cv_masterserver_update_rate; +extern consvar_t cv_masterserver_room_id; extern consvar_t cv_masterserver_timeout; extern consvar_t cv_masterserver_debug; extern consvar_t cv_masterserver_token; -// < 0 to not connect (usually -1) (offline mode) -// == 0 to show all rooms, not a valid hosting room -// anything else is whatever room the MS assigns to that number (online mode) -extern INT16 ms_RoomId; - #ifdef HAVE_THREADS extern int ms_QueryId; extern I_mutex ms_QueryId_mutex; diff --git a/src/netcode/server_connection.c b/src/netcode/server_connection.c index bbabc8f1dc9a5d82030159a281c2ffae137d1054..f4601e4acac08a187b982f8e286e9e53d46b2396 100644 --- a/src/netcode/server_connection.c +++ b/src/netcode/server_connection.c @@ -115,12 +115,12 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) netbuffer->u.serverinfo.refusereason = GetRefuseReason(node); strncpy(netbuffer->u.serverinfo.gametypename, Gametype_Names[gametype], - sizeof netbuffer->u.serverinfo.gametypename); + sizeof(netbuffer->u.serverinfo.gametypename)-1); netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame; netbuffer->u.serverinfo.cheatsenabled = CV_CheatsEnabled(); netbuffer->u.serverinfo.flags = (dedicated ? SV_DEDICATED : 0); strncpy(netbuffer->u.serverinfo.servername, cv_servername.string, - MAXSERVERNAME); + sizeof(netbuffer->u.serverinfo.servername)-1); strncpy(netbuffer->u.serverinfo.mapname, G_BuildMapName(gamemap), 7); M_Memcpy(netbuffer->u.serverinfo.mapmd5, mapmd5, 16); @@ -184,7 +184,9 @@ static void SV_SendPlayerInfo(INT32 node) } netbuffer->u.playerinfo[i].num = i; - strncpy(netbuffer->u.playerinfo[i].name, (const char *)&player_names[i], MAXPLAYERNAME+1); + memset(netbuffer->u.playerinfo[i].name, 0x00, sizeof(netbuffer->u.playerinfo[i].name)); + memcpy(netbuffer->u.playerinfo[i].name, player_names[i], sizeof(player_names[i])); + netbuffer->u.playerinfo[i].name[MAXPLAYERNAME] = '\0'; //fetch IP address diff --git a/src/p_enemy.c b/src/p_enemy.c index 5314de8abfa7807fee22d2f2e08dde8d50ac33ec..29fcf50c2d0fdd432f448fc5a7e088ef11899a79 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -54,276 +54,6 @@ static dirtype_t diags[] = DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST }; -//Real Prototypes to A_* -void A_Fall(mobj_t *actor); -void A_Look(mobj_t *actor); -void A_Chase(mobj_t *actor); -void A_FaceStabChase(mobj_t *actor); -void A_FaceStabRev(mobj_t *actor); -void A_FaceStabHurl(mobj_t *actor); -void A_FaceStabMiss(mobj_t *actor); -void A_StatueBurst(mobj_t *actor); -void A_JetJawRoam(mobj_t *actor); -void A_JetJawChomp(mobj_t *actor); -void A_PointyThink(mobj_t *actor); -void A_CheckBuddy(mobj_t *actor); -void A_HoodFire(mobj_t *actor); -void A_HoodThink(mobj_t *actor); -void A_HoodFall(mobj_t *actor); -void A_ArrowBonks(mobj_t *actor); -void A_SnailerThink(mobj_t *actor); -void A_SharpChase(mobj_t *actor); -void A_SharpSpin(mobj_t *actor); -void A_SharpDecel(mobj_t *actor); -void A_CrushstaceanWalk(mobj_t *actor); -void A_CrushstaceanPunch(mobj_t *actor); -void A_CrushclawAim(mobj_t *actor); -void A_CrushclawLaunch(mobj_t *actor); -void A_VultureVtol(mobj_t *actor); -void A_VultureCheck(mobj_t *actor); -void A_VultureHover(mobj_t *actor); -void A_VultureBlast(mobj_t *actor); -void A_VultureFly(mobj_t *actor); -void A_SkimChase(mobj_t *actor); -void A_FaceTarget(mobj_t *actor); -void A_FaceTracer(mobj_t *actor); -void A_LobShot(mobj_t *actor); -void A_FireShot(mobj_t *actor); -void A_SuperFireShot(mobj_t *actor); -void A_BossFireShot(mobj_t *actor); -void A_Boss7FireMissiles(mobj_t *actor); -void A_Boss1Laser(mobj_t *actor); -void A_FocusTarget(mobj_t *actor); -void A_Boss4Reverse(mobj_t *actor); -void A_Boss4SpeedUp(mobj_t *actor); -void A_Boss4Raise(mobj_t *actor); -void A_SkullAttack(mobj_t *actor); -void A_BossZoom(mobj_t *actor); -void A_BossScream(mobj_t *actor); -void A_Scream(mobj_t *actor); -void A_Pain(mobj_t *actor); -void A_1upThinker(mobj_t *actor); -void A_MonitorPop(mobj_t *actor); -void A_GoldMonitorPop(mobj_t *actor); -void A_GoldMonitorRestore(mobj_t *actor); -void A_GoldMonitorSparkle(mobj_t *actor); -void A_Explode(mobj_t *actor); -void A_BossDeath(mobj_t *actor); -void A_SetShadowScale(mobj_t *actor); -void A_ShadowScream(mobj_t *actor); -void A_CustomPower(mobj_t *actor); -void A_GiveWeapon(mobj_t *actor); -void A_RingBox(mobj_t *actor); -void A_Invincibility(mobj_t *actor); -void A_SuperSneakers(mobj_t *actor); -void A_AwardScore(mobj_t *actor); -void A_ExtraLife(mobj_t *actor); -void A_GiveShield(mobj_t *actor); -void A_GravityBox(mobj_t *actor); -void A_ScoreRise(mobj_t *actor); -void A_BunnyHop(mobj_t *actor); -void A_BubbleSpawn(mobj_t *actor); -void A_FanBubbleSpawn(mobj_t *actor); -void A_BubbleRise(mobj_t *actor); -void A_BubbleCheck(mobj_t *actor); -void A_AttractChase(mobj_t *actor); -void A_DropMine(mobj_t *actor); -void A_FishJump(mobj_t *actor); -void A_ThrownRing(mobj_t *actor); -void A_SetSolidSteam(mobj_t *actor); -void A_UnsetSolidSteam(mobj_t *actor); -void A_SignSpin(mobj_t *actor); -void A_SignPlayer(mobj_t *actor); -void A_OverlayThink(mobj_t *actor); -void A_JetChase(mobj_t *actor); -void A_JetbThink(mobj_t *actor); -void A_JetgShoot(mobj_t *actor); -void A_JetgThink(mobj_t *actor); -void A_ShootBullet(mobj_t *actor); -void A_MinusDigging(mobj_t *actor); -void A_MinusPopup(mobj_t *actor); -void A_MinusCheck(mobj_t *actor); -void A_ChickenCheck(mobj_t *actor); -void A_MouseThink(mobj_t *actor); -void A_DetonChase(mobj_t *actor); -void A_CapeChase(mobj_t *actor); -void A_RotateSpikeBall(mobj_t *actor); -void A_SlingAppear(mobj_t *actor); -void A_UnidusBall(mobj_t *actor); -void A_RockSpawn(mobj_t *actor); -void A_SetFuse(mobj_t *actor); -void A_CrawlaCommanderThink(mobj_t *actor); -void A_RingExplode(mobj_t *actor); -void A_OldRingExplode(mobj_t *actor); -void A_MixUp(mobj_t *actor); -void A_RecyclePowers(mobj_t *actor); -void A_Boss2TakeDamage(mobj_t *actor); -void A_Boss7Chase(mobj_t *actor); -void A_GoopSplat(mobj_t *actor); -void A_Boss2PogoSFX(mobj_t *actor); -void A_Boss2PogoTarget(mobj_t *actor); -void A_EggmanBox(mobj_t *actor); -void A_TurretFire(mobj_t *actor); -void A_SuperTurretFire(mobj_t *actor); -void A_TurretStop(mobj_t *actor); -void A_SparkFollow(mobj_t *actor); -void A_BuzzFly(mobj_t *actor); -void A_GuardChase(mobj_t *actor); -void A_EggShield(mobj_t *actor); -void A_SetReactionTime(mobj_t *actor); -void A_Boss1Spikeballs(mobj_t *actor); -void A_Boss3TakeDamage(mobj_t *actor); -void A_Boss3Path(mobj_t *actor); -void A_Boss3ShockThink(mobj_t *actor); -void A_Shockwave(mobj_t *actor); -void A_LinedefExecute(mobj_t *actor); -void A_LinedefExecuteFromArg(mobj_t *actor); -void A_PlaySeeSound(mobj_t *actor); -void A_PlayAttackSound(mobj_t *actor); -void A_PlayActiveSound(mobj_t *actor); -void A_SmokeTrailer(mobj_t *actor); -void A_SpawnObjectAbsolute(mobj_t *actor); -void A_SpawnObjectRelative(mobj_t *actor); -void A_ChangeAngleRelative(mobj_t *actor); -void A_ChangeAngleAbsolute(mobj_t *actor); -void A_RollAngle(mobj_t *actor); -void A_ChangeRollAngleRelative(mobj_t *actor); -void A_ChangeRollAngleAbsolute(mobj_t *actor); -void A_PlaySound(mobj_t *actor); -void A_FindTarget(mobj_t *actor); -void A_FindTracer(mobj_t *actor); -void A_SetTics(mobj_t *actor); -void A_SetRandomTics(mobj_t *actor); -void A_ChangeColorRelative(mobj_t *actor); -void A_ChangeColorAbsolute(mobj_t *actor); -void A_Dye(mobj_t *actor); -void A_SetTranslation(mobj_t *actor); -void A_MoveRelative(mobj_t *actor); -void A_MoveAbsolute(mobj_t *actor); -void A_Thrust(mobj_t *actor); -void A_ZThrust(mobj_t *actor); -void A_SetTargetsTarget(mobj_t *actor); -void A_SetObjectFlags(mobj_t *actor); -void A_SetObjectFlags2(mobj_t *actor); -void A_RandomState(mobj_t *actor); -void A_RandomStateRange(mobj_t *actor); -void A_StateRangeByAngle(mobj_t *actor); -void A_StateRangeByParameter(mobj_t *actor); -void A_DualAction(mobj_t *actor); -void A_RemoteAction(mobj_t *actor); -void A_ToggleFlameJet(mobj_t *actor); -void A_OrbitNights(mobj_t *actor); -void A_GhostMe(mobj_t *actor); -void A_SetObjectState(mobj_t *actor); -void A_SetObjectTypeState(mobj_t *actor); -void A_KnockBack(mobj_t *actor); -void A_PushAway(mobj_t *actor); -void A_RingDrain(mobj_t *actor); -void A_SplitShot(mobj_t *actor); -void A_MissileSplit(mobj_t *actor); -void A_MultiShot(mobj_t *actor); -void A_InstaLoop(mobj_t *actor); -void A_Custom3DRotate(mobj_t *actor); -void A_SearchForPlayers(mobj_t *actor); -void A_CheckRandom(mobj_t *actor); -void A_CheckTargetRings(mobj_t *actor); -void A_CheckRings(mobj_t *actor); -void A_CheckTotalRings(mobj_t *actor); -void A_CheckHealth(mobj_t *actor); -void A_CheckRange(mobj_t *actor); -void A_CheckHeight(mobj_t *actor); -void A_CheckTrueRange(mobj_t *actor); -void A_CheckThingCount(mobj_t *actor); -void A_CheckAmbush(mobj_t *actor); -void A_CheckCustomValue(mobj_t *actor); -void A_CheckCusValMemo(mobj_t *actor); -void A_SetCustomValue(mobj_t *actor); -void A_UseCusValMemo(mobj_t *actor); -void A_RelayCustomValue(mobj_t *actor); -void A_CusValAction(mobj_t *actor); -void A_ForceStop(mobj_t *actor); -void A_ForceWin(mobj_t *actor); -void A_SpikeRetract(mobj_t *actor); -void A_InfoState(mobj_t *actor); -void A_Repeat(mobj_t *actor); -void A_SetScale(mobj_t *actor); -void A_RemoteDamage(mobj_t *actor); -void A_HomingChase(mobj_t *actor); -void A_TrapShot(mobj_t *actor); -void A_Boss1Chase(mobj_t *actor); -void A_Boss2Chase(mobj_t *actor); -void A_Boss2Pogo(mobj_t *actor); -void A_BossJetFume(mobj_t *actor); -void A_VileTarget(mobj_t *actor); -void A_VileAttack(mobj_t *actor); -void A_VileFire(mobj_t *actor); -void A_BrakChase(mobj_t *actor); -void A_BrakFireShot(mobj_t *actor); -void A_BrakLobShot(mobj_t *actor); -void A_NapalmScatter(mobj_t *actor); -void A_SpawnFreshCopy(mobj_t *actor); -void A_FlickySpawn(mobj_t *actor); -void A_FlickyCenter(mobj_t *actor); -void A_FlickyAim(mobj_t *actor); -void A_FlickyFly(mobj_t *actor); -void A_FlickySoar(mobj_t *actor); -void A_FlickyCoast(mobj_t *actor); -void A_FlickyHop(mobj_t *actor); -void A_FlickyFlounder(mobj_t *actor); -void A_FlickyCheck(mobj_t *actor); -void A_FlickyHeightCheck(mobj_t *actor); -void A_FlickyFlutter(mobj_t *actor); -void A_FlameParticle(mobj_t *actor); -void A_FadeOverlay(mobj_t *actor); -void A_Boss5Jump(mobj_t *actor); -void A_LightBeamReset(mobj_t *actor); -void A_MineExplode(mobj_t *actor); -void A_MineRange(mobj_t *actor); -void A_ConnectToGround(mobj_t *actor); -void A_SpawnParticleRelative(mobj_t *actor); -void A_MultiShotDist(mobj_t *actor); -void A_WhoCaresIfYourSonIsABee(mobj_t *actor); -void A_ParentTriesToSleep(mobj_t *actor); -void A_CryingToMomma(mobj_t *actor); -void A_CheckFlags2(mobj_t *actor); -void A_Boss5FindWaypoint(mobj_t *actor); -void A_DoNPCSkid(mobj_t *actor); -void A_DoNPCPain(mobj_t *actor); -void A_PrepareRepeat(mobj_t *actor); -void A_Boss5ExtraRepeat(mobj_t *actor); -void A_Boss5Calm(mobj_t *actor); -void A_Boss5CheckOnGround(mobj_t *actor); -void A_Boss5CheckFalling(mobj_t *actor); -void A_Boss5PinchShot(mobj_t *actor); -void A_Boss5MakeItRain(mobj_t *actor); -void A_Boss5MakeJunk(mobj_t *actor); -void A_LookForBetter(mobj_t *actor); -void A_Boss5BombExplode(mobj_t *actor); -void A_DustDevilThink(mobj_t *actor); -void A_TNTExplode(mobj_t *actor); -void A_DebrisRandom(mobj_t *actor); -void A_TrainCameo(mobj_t *actor); -void A_TrainCameo2(mobj_t *actor); -void A_CanarivoreGas(mobj_t *actor); -void A_KillSegments(mobj_t *actor); -void A_SnapperSpawn(mobj_t *actor); -void A_SnapperThinker(mobj_t *actor); -void A_SaloonDoorSpawn(mobj_t *actor); -void A_MinecartSparkThink(mobj_t *actor); -void A_ModuloToState(mobj_t *actor); -void A_LavafallRocks(mobj_t *actor); -void A_LavafallLava(mobj_t *actor); -void A_FallingLavaCheck(mobj_t *actor); -void A_FireShrink(mobj_t *actor); -void A_SpawnPterabytes(mobj_t *actor); -void A_PterabyteHover(mobj_t *actor); -void A_RolloutSpawn(mobj_t *actor); -void A_RolloutRock(mobj_t *actor); -void A_DragonbomberSpawn(mobj_t *actor); -void A_DragonWing(mobj_t *actor); -void A_DragonSegment(mobj_t *actor); -void A_ChangeHeight(mobj_t *actor); - //for p_enemy.c // @@ -541,7 +271,7 @@ boolean P_Move(mobj_t *actor, fixed_t speed) if (!P_TryMove(actor, tryx, tryy, false)) { - if (actor->flags & MF_FLOAT && floatok) + if (!P_MobjWasRemoved(actor) && actor->flags & MF_FLOAT && floatok) { // must adjust height if (actor->z < tmfloorz) @@ -585,6 +315,7 @@ void P_NewChaseDir(mobj_t *actor) dirtype_t d[3]; dirtype_t tdir = DI_NODIR, olddir, turnaround; + I_Assert(!P_MobjWasRemoved(actor)); I_Assert(actor->target != NULL); I_Assert(!P_MobjWasRemoved(actor->target)); @@ -623,7 +354,7 @@ void P_NewChaseDir(mobj_t *actor) dirtype_t newdir = diags[((deltay < 0)<<1) + (deltax > 0)]; actor->movedir = newdir; - if ((newdir != turnaround) && P_TryWalk(actor)) + if ((newdir != turnaround) && (P_TryWalk(actor) || P_MobjWasRemoved(actor))) return; } @@ -644,7 +375,7 @@ void P_NewChaseDir(mobj_t *actor) { actor->movedir = d[1]; - if (P_TryWalk(actor)) + if (P_TryWalk(actor) || P_MobjWasRemoved(actor)) return; // either moved forward or attacked } @@ -652,7 +383,7 @@ void P_NewChaseDir(mobj_t *actor) { actor->movedir = d[2]; - if (P_TryWalk(actor)) + if (P_TryWalk(actor) || P_MobjWasRemoved(actor)) return; } @@ -661,7 +392,7 @@ void P_NewChaseDir(mobj_t *actor) { actor->movedir =olddir; - if (P_TryWalk(actor)) + if (P_TryWalk(actor) || P_MobjWasRemoved(actor)) return; } @@ -674,7 +405,7 @@ void P_NewChaseDir(mobj_t *actor) { actor->movedir = tdir; - if (P_TryWalk(actor)) + if (P_TryWalk(actor) || P_MobjWasRemoved(actor)) return; } } @@ -687,7 +418,7 @@ void P_NewChaseDir(mobj_t *actor) { actor->movedir = tdir; - if (P_TryWalk(actor)) + if (P_TryWalk(actor) || P_MobjWasRemoved(actor)) return; } } @@ -697,7 +428,7 @@ void P_NewChaseDir(mobj_t *actor) { actor->movedir = turnaround; - if (P_TryWalk(actor)) + if (P_TryWalk(actor) || P_MobjWasRemoved(actor)) return; } @@ -1100,7 +831,7 @@ nomissile: return; // got a new target // chase towards player - if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) + if (--actor->movecount < 0 || (!P_Move(actor, actor->info->speed) && !P_MobjWasRemoved(actor))) P_NewChaseDir(actor); } @@ -1188,7 +919,7 @@ nomissile: return; // got a new target // chase towards player - if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) + if (--actor->movecount < 0 || (!P_Move(actor, actor->info->speed) && !P_MobjWasRemoved(actor))) P_NewChaseDir(actor); } @@ -1221,8 +952,7 @@ static void P_FaceStabFlume(mobj_t *actor) if (P_MobjWasRemoved(flume)) return; - flume->destscale = actor->scale*3; - P_SetScale(flume, flume->destscale); + P_SetScale(flume, 3*actor->scale, true); P_SetTarget(&flume->target, actor); flume->sprite = SPR_JETF; flume->frame = FF_FULLBRIGHT; @@ -1267,7 +997,8 @@ void A_FaceStabRev(mobj_t *actor) else { P_TryMove(actor, actor->x - P_ReturnThrustX(actor, actor->angle, 2<<FRACBITS), actor->y - P_ReturnThrustY(actor, actor->angle, 2<<FRACBITS), false); - P_FaceStabFlume(actor); + if (!P_MobjWasRemoved(actor)) + P_FaceStabFlume(actor); } } } @@ -1333,16 +1064,30 @@ void A_FaceStabHurl(mobj_t *actor) while (step > 0) { - if (!hwork->hnext) + if (P_MobjWasRemoved(hwork->hnext)) P_SetTarget(&hwork->hnext, P_SpawnMobjFromMobj(actor, 0, 0, 0, MT_FACESTABBERSPEAR)); + if (!P_MobjWasRemoved(hwork->hnext)) { hwork = hwork->hnext; hwork->angle = actor->angle + ANGLE_90; - hwork->destscale = FixedSqrt(step*basesize); - P_SetScale(hwork, hwork->destscale); + P_SetScale(hwork, FixedSqrt(step*basesize), true); hwork->fuse = 2; P_MoveOrigin(hwork, actor->x + xo*(15-step), actor->y + yo*(15-step), actor->z + (actor->height - hwork->height)/2 + (P_MobjFlip(actor)*(8<<FRACBITS))); + if (P_MobjWasRemoved(hwork)) + { + // if one of the sections are removed, erase the entire damn thing. + mobj_t *hnext = actor->hnext; + hwork = actor; + do + { + hnext = hwork->hnext; + P_RemoveMobj(hwork); + hwork = hnext; + } + while (!P_MobjWasRemoved(hwork)); + return; + } } step -= NUMGRADS; } @@ -1359,11 +1104,14 @@ void A_FaceStabHurl(mobj_t *actor) #undef NUMGRADS #undef NUMSTEPS } + if (P_MobjWasRemoved(actor)) + return; } } P_SetMobjState(actor, locvar2); - actor->reactiontime = actor->info->reactiontime; + if (!P_MobjWasRemoved(actor)) + actor->reactiontime = actor->info->reactiontime; } // Function: A_FaceStabMiss @@ -1393,6 +1141,8 @@ void A_FaceStabMiss(mobj_t *actor) actor->y + P_ReturnThrustY(actor, actor->angle, actor->extravalue2<<FRACBITS), false)) { + if (P_MobjWasRemoved(actor)) + return; actor->extravalue2 = 0; P_SetMobjState(actor, locvar2); } @@ -1425,6 +1175,8 @@ void A_StatueBurst(mobj_t *actor) P_SetTarget(&new->target, actor->target); if (locvar2) P_SetMobjState(new, (statenum_t)locvar2); + if (P_MobjWasRemoved(new)) + return; S_StartSound(new, new->info->attacksound); S_StopSound(actor); S_StartSound(actor, sfx_s3k96); @@ -1520,7 +1272,7 @@ void A_JetJawChomp(mobj_t *actor) } // chase towards player - if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) + if (--actor->movecount < 0 || (!P_Move(actor, actor->info->speed) && !P_MobjWasRemoved(actor))) P_NewChaseDir(actor); } @@ -1941,14 +1693,15 @@ void A_SharpChase(mobj_t *actor) } // chase towards player - if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) + if (--actor->movecount < 0 || (!P_Move(actor, actor->info->speed) && !P_MobjWasRemoved(actor))) P_NewChaseDir(actor); } else { actor->threshold = actor->info->painchance; P_SetMobjState(actor, actor->info->missilestate); - S_StartSound(actor, actor->info->attacksound); + if (!P_MobjWasRemoved(actor)) + S_StartSound(actor, actor->info->attacksound); } } @@ -2034,6 +1787,8 @@ void A_CrushstaceanWalk(mobj_t *actor) false) || (actor->reactiontime-- <= 0)) { + if (P_MobjWasRemoved(actor)) + return; actor->flags2 ^= MF2_AMBUSH; P_SetTarget(&actor->target, NULL); P_SetMobjState(actor, locvar2); @@ -2215,6 +1970,8 @@ void A_CrushclawLaunch(mobj_t *actor) true) && !locvar1) { + if (P_MobjWasRemoved(actor)) + return; actor->extravalue1 = 0; actor->extravalue2 = FixedHypot(actor->x - actor->target->x, actor->y - actor->target->y)>>FRACBITS; P_SetMobjState(actor, locvar2); @@ -2223,6 +1980,8 @@ void A_CrushclawLaunch(mobj_t *actor) } else { + if (P_MobjWasRemoved(actor)) + return; actor->z = actor->target->z; if ((!locvar1 && (actor->extravalue2 > 256)) || (locvar1 && (actor->extravalue2 < 16))) { @@ -2455,7 +2214,7 @@ void A_VultureBlast(mobj_t *actor) if (P_MobjWasRemoved(dust)) continue; - P_SetScale(dust, 4*FRACUNIT); + P_SetScale(dust, 4*FRACUNIT, true); dust->destscale = FRACUNIT; dust->scalespeed = 4*FRACUNIT/TICRATE; dust->fuse = TICRATE; @@ -2525,7 +2284,7 @@ void A_VultureFly(mobj_t *actor) dust = P_SpawnMobj(actor->x + P_RandomFixed() - FRACUNIT/2, actor->y + P_RandomFixed() - FRACUNIT/2, actor->z + actor->height/2 + P_RandomFixed() - FRACUNIT/2, MT_PARTICLE); if (!P_MobjWasRemoved(dust)) { - P_SetScale(dust, 2*FRACUNIT); + P_SetScale(dust, 2*FRACUNIT, true); dust->destscale = FRACUNIT/3; dust->scalespeed = FRACUNIT/40; dust->fuse = TICRATE*2; @@ -2648,7 +2407,7 @@ nomissile: return; // got a new target // chase towards player - if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) + if (--actor->movecount < 0 || (!P_Move(actor, actor->info->speed) && !P_MobjWasRemoved(actor))) P_NewChaseDir(actor); } @@ -2734,15 +2493,9 @@ void A_LobShot(mobj_t *actor) return; if (actor->type == MT_BLACKEGGMAN) - { - shot->destscale = actor->scale/2; - P_SetScale(shot, actor->scale/2); - } + P_SetScale(shot, actor->scale/2, true); else - { - shot->destscale = actor->scale; - P_SetScale(shot, actor->scale); - } + P_SetScale(shot, actor->scale, true); P_SetTarget(&shot->target, actor); // where it came from @@ -3187,8 +2940,7 @@ void A_Boss1Laser(mobj_t *actor) if (!P_MobjWasRemoved(point)) { point->angle = actor->angle; - point->destscale = actor->scale; - P_SetScale(point, point->destscale); + P_SetScale(point, actor->scale, true); P_SetTarget(&point->target, actor); P_MobjCheckWater(point); if (point->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) @@ -3199,7 +2951,8 @@ void A_Boss1Laser(mobj_t *actor) mobj_t *steam = P_SpawnMobj(x, y, point->watertop - size*mobjinfo[MT_DUST].height, MT_DUST); if (P_MobjWasRemoved(steam)) continue; - P_SetScale(steam, size*actor->scale); + P_SetScale(steam, size*actor->scale, false); + steam->old_scale = steam->scale; P_SetObjectMomZ(steam, FRACUNIT + 2*P_RandomFixed(), true); P_InstaThrust(steam, FixedAngle(P_RandomKey(360)*FRACUNIT), 2*P_RandomFixed()); if (point->info->painsound) @@ -3572,8 +3325,7 @@ void A_BossScream(mobj_t *actor) return; if (actor->eflags & MFE_VERTICALFLIP) mo->flags2 |= MF2_OBJECTFLIP; - mo->destscale = actor->scale; - P_SetScale(mo, mo->destscale); + P_SetScale(mo, actor->scale, true); if (actor->info->deathsound) S_StartSound(mo, actor->info->deathsound); } @@ -3992,7 +3744,7 @@ static void P_DoBossVictory(mobj_t *mo) // scan the remaining thinkers to see if all bosses are dead for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -4017,7 +3769,7 @@ static void P_DoBossVictory(mobj_t *mo) { if (!playeringame[i]) continue; - P_DoPlayerExit(&players[i]); + P_DoPlayerExit(&players[i], true); } } else @@ -4166,9 +3918,11 @@ static void P_DoBoss5Death(mobj_t *mo) MT_FSGNB); if (!P_MobjWasRemoved(pole)) { - P_SetScale(pole, (pole->destscale = 2*FRACUNIT)); + P_SetScale(pole, 2*FRACUNIT, true); + pole->angle = mo->tracer->angle; pole->momx = P_ReturnThrustX(pole, pole->angle, speed); pole->momy = P_ReturnThrustY(pole, pole->angle, speed); + P_SetTarget(&pole->tracer, P_SpawnMobj( pole->x, pole->y, pole->z - 256*FRACUNIT, @@ -4176,8 +3930,8 @@ static void P_DoBoss5Death(mobj_t *mo) if (!P_MobjWasRemoved(pole->tracer)) { pole->tracer->flags |= MF_NOCLIPTHING; - P_SetScale(pole->tracer, (pole->tracer->destscale = 2*FRACUNIT)); - pole->angle = pole->tracer->angle = mo->tracer->angle; + P_SetScale(pole->tracer, 2*FRACUNIT, true); + pole->tracer->angle = mo->tracer->angle; pole->tracer->momx = pole->momx; pole->tracer->momy = pole->momy; @@ -4715,10 +4469,7 @@ void A_BubbleSpawn(mobj_t *actor) bubble = P_SpawnMobj(actor->x, actor->y, actor->z + (actor->height / 2), MT_MEDIUMBUBBLE); if (bubble) - { - bubble->destscale = actor->scale; - P_SetScale(bubble, actor->scale); - } + P_SetScale(bubble, actor->scale, true); } // Function: A_FanBubbleSpawn @@ -4761,10 +4512,7 @@ void A_FanBubbleSpawn(mobj_t *actor) bubble = P_SpawnMobj(actor->x, actor->y, hz, MT_MEDIUMBUBBLE); if (bubble) - { - bubble->destscale = actor->scale; - P_SetScale(bubble, actor->scale); - } + P_SetScale(bubble, actor->scale, true); } // Function: A_BubbleRise @@ -4847,7 +4595,7 @@ void A_AttractChase(mobj_t *actor) else actor->flags2 &= ~MF2_DONTDRAW; - // Turn flingrings back into regular rings if attracted. + // Turn rings into flingrings if shield is lost or out of range if (actor->tracer && actor->tracer->player && !(actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRIC) && actor->info->reactiontime && actor->type != (mobjtype_t)actor->info->reactiontime) { @@ -4879,8 +4627,9 @@ void A_AttractChase(mobj_t *actor) // If a FlingRing gets attracted by a shield, change it into a normal ring. if (actor->type == (mobjtype_t)actor->info->reactiontime) { - P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->painchance); - P_RemoveMobj(actor); + actor->type = mobjinfo[actor->type].painchance; // Become the regular version of the fling object. + actor->flags = mobjinfo[actor->type].flags; // Reset actor flags. + P_SetMobjState(actor, actor->info->spawnstate); // Go to regular object's spawn state. return; } @@ -5041,8 +4790,7 @@ void A_ThrownRing(mobj_t *actor) P_SetTarget(&ring->target, actor); ring->color = actor->color; //copy color */ - ring->destscale = actor->scale; - P_SetScale(ring, actor->scale); + P_SetScale(ring, actor->scale, true); } } @@ -5177,7 +4925,7 @@ void A_SetSolidSteam(mobj_t *actor) return; actor->flags &= ~MF_NOCLIP; - actor->flags |= MF_SOLID; + actor->flags |= MF_SPECIAL; if (!(actor->flags2 & MF2_AMBUSH)) { if (P_RandomChance(FRACUNIT/8)) @@ -5207,7 +4955,7 @@ void A_UnsetSolidSteam(mobj_t *actor) if (LUA_CallAction(A_UNSETSOLIDSTEAM, actor)) return; - actor->flags &= ~MF_SOLID; + actor->flags &= ~MF_SPECIAL; actor->flags |= MF_NOCLIP; } @@ -5621,8 +5369,7 @@ void A_JetbThink(mobj_t *actor) if (!P_MobjWasRemoved(bomb)) { P_SetTarget(&bomb->target, actor); - bomb->destscale = actor->scale; - P_SetScale(bomb, actor->scale); + P_SetScale(bomb, actor->scale, true); actor->reactiontime = TICRATE; // one second S_StartSound(actor, actor->info->attacksound); } @@ -5788,7 +5535,11 @@ void A_MinusDigging(mobj_t *actor) if (P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) < actor->radius*2) { P_SetMobjState(actor, actor->info->meleestate); + if (P_MobjWasRemoved(actor)) + return; P_TryMove(actor, actor->target->x, actor->target->y, false); + if (P_MobjWasRemoved(actor)) + return; S_StartSound(actor, actor->info->attacksound); // Spawn growing dirt pile. @@ -5796,7 +5547,10 @@ void A_MinusDigging(mobj_t *actor) if (P_MobjWasRemoved(par)) return; P_SetMobjState(par, actor->info->raisestate); - P_SetScale(par, actor->scale*2); + if (P_MobjWasRemoved(par)) + return; + P_SetScale(par, actor->scale*2, false); + par->old_scale = par->scale; if (actor->eflags & MFE_VERTICALFLIP) par->eflags |= MFE_VERTICALFLIP; return; @@ -5809,6 +5563,8 @@ void A_MinusDigging(mobj_t *actor) // Move var1 = 3; A_Chase(actor); + if (P_MobjWasRemoved(actor)) + return; // Carry over shit, maybe if (P_MobjWasRemoved(actor->tracer) || !actor->tracer->health) @@ -5832,7 +5588,7 @@ void A_MinusDigging(mobj_t *actor) { if (P_TryMove(actor->tracer, actor->x, actor->y, false)) actor->tracer->z = mz; - else + else if (!P_MobjWasRemoved(actor)) P_SetTarget(&actor->tracer, NULL); } } @@ -5866,7 +5622,8 @@ void A_MinusPopup(mobj_t *actor) continue; P_Thrust(rock, ani*i, FRACUNIT); P_SetObjectMomZ(rock, 3*FRACUNIT, false); - P_SetScale(rock, rock->scale/3); + P_SetScale(rock, rock->scale/3, false); + rock->old_scale = rock->scale; } P_RadiusAttack(actor, actor, 2*actor->radius, 0, true); if (actor->tracer) @@ -5905,7 +5662,8 @@ void A_MinusCheck(mobj_t *actor) continue; P_Thrust(rock, ani*i, FRACUNIT); P_SetObjectMomZ(rock, 3*FRACUNIT, false); - P_SetScale(rock, rock->scale/3); + P_SetScale(rock, rock->scale/3, false); + rock->old_scale = rock->scale; } } } @@ -6691,7 +6449,7 @@ void A_RingExplode(mobj_t *actor) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -7304,7 +7062,7 @@ nomissile: // chase towards player if (P_AproxDistance(actor->target->x-actor->x, actor->target->y-actor->y) > actor->radius+actor->target->radius) { - if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) + if (--actor->movecount < 0 || (!P_Move(actor, actor->info->speed) && !P_MobjWasRemoved(actor))) P_NewChaseDir(actor); } // too close, don't want to chase. @@ -7661,7 +7419,7 @@ void A_Boss7Chase(mobj_t *actor) if (leveltime & 1) { // chase towards player - if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) + if (--actor->movecount < 0 || (!P_Move(actor, actor->info->speed) && !P_MobjWasRemoved(actor))) P_NewChaseDir(actor); } } @@ -8119,6 +7877,8 @@ void A_GuardChase(mobj_t *actor) false) && speed > 0) // can't be the same check as previous so that P_TryMove gets to happen. { + if (P_MobjWasRemoved(actor)) + return; INT32 direction = actor->spawnpoint ? actor->spawnpoint->args[0] : TMGD_BACK; switch (direction) @@ -8135,6 +7895,8 @@ void A_GuardChase(mobj_t *actor) break; } } + if (P_MobjWasRemoved(actor)) + return; if (actor->extravalue1 < actor->info->speed) actor->extravalue1++; @@ -8171,7 +7933,11 @@ void A_GuardChase(mobj_t *actor) // chase towards player if (--actor->movecount < 0 || !P_Move(actor, (actor->flags2 & MF2_AMBUSH) ? actor->info->speed * 2 : actor->info->speed)) { + if (P_MobjWasRemoved(actor)) + return; P_NewChaseDir(actor); + if (P_MobjWasRemoved(actor)) + return; actor->movecount += 5; // Increase tics before change in direction allowed. } } @@ -8226,8 +7992,9 @@ void A_EggShield(mobj_t *actor) else actor->z = actor->target->z; + P_SetScale(actor, actor->target->scale, false); actor->destscale = actor->target->destscale; - P_SetScale(actor, actor->target->scale); + actor->old_scale = actor->target->old_scale; actor->floorz = actor->target->floorz; actor->ceilingz = actor->target->ceilingz; @@ -8508,7 +8275,7 @@ void A_Boss3ShockThink(mobj_t *actor) P_SetTarget(&snew->target, actor->target); snew->fuse = actor->fuse; - P_SetScale(snew, actor->scale); + P_SetScale(snew, actor->scale, true); snew->destscale = actor->destscale; snew->scalespeed = actor->scalespeed; @@ -8565,7 +8332,7 @@ void A_Shockwave(mobj_t *actor) ang += interval; sprev = shock; } - + S_StartSound(actor, shock->info->seesound); } @@ -8641,6 +8408,9 @@ void A_PlaySeeSound(mobj_t *actor) if (LUA_CallAction(A_PLAYSEESOUND, actor)) return; + if (P_MobjWasRemoved(actor)) + return; + if (actor->info->seesound) S_StartScreamSound(actor, actor->info->seesound); } @@ -8707,8 +8477,7 @@ void A_SmokeTrailer(mobj_t *actor) if (P_MobjWasRemoved(th)) return; P_SetObjectMomZ(th, FRACUNIT, false); - th->destscale = actor->scale; - P_SetScale(th, actor->scale); + P_SetScale(th, actor->scale, true); th->tics -= P_RandomByte() & 3; if (th->tics < 1) th->tics = 1; @@ -8987,7 +8756,7 @@ void A_FindTarget(mobj_t *actor) // scan the thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -9051,7 +8820,7 @@ void A_FindTracer(mobj_t *actor) // scan the thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -9472,8 +9241,7 @@ void A_BossJetFume(mobj_t *actor) if (!P_MobjWasRemoved(filler)) { P_SetTarget(&filler->target, actor); - filler->destscale = actor->scale; - P_SetScale(filler, filler->destscale); + P_SetScale(filler, actor->scale, true); if (actor->eflags & MFE_VERTICALFLIP) filler->flags2 |= MF2_OBJECTFLIP; filler->fuse = 56; @@ -9490,8 +9258,7 @@ void A_BossJetFume(mobj_t *actor) if (!P_MobjWasRemoved(filler)) { P_SetTarget(&filler->target, actor); - filler->destscale = actor->scale; - P_SetScale(filler, filler->destscale); + P_SetScale(filler, actor->scale, true); if (actor->eflags & MFE_VERTICALFLIP) filler->flags2 |= MF2_OBJECTFLIP; filler->fuse = 57; @@ -9504,7 +9271,7 @@ void A_BossJetFume(mobj_t *actor) { P_SetTarget(&filler->target, actor); filler->destscale = actor->scale; - P_SetScale(filler, filler->destscale); + P_SetScale(filler, actor->scale, true); if (actor->eflags & MFE_VERTICALFLIP) filler->flags2 |= MF2_OBJECTFLIP; filler->fuse = 58; @@ -9525,8 +9292,7 @@ void A_BossJetFume(mobj_t *actor) filler = P_SpawnMobj(jetx, jety, jetz, MT_PROPELLER); P_SetTarget(&filler->target, actor); - filler->destscale = actor->scale; - P_SetScale(filler, filler->destscale); + P_SetScale(filler, actor->scale, true); if (actor->eflags & MFE_VERTICALFLIP) filler->flags2 |= MF2_OBJECTFLIP; filler->angle = actor->angle - ANGLE_180; @@ -9541,7 +9307,7 @@ void A_BossJetFume(mobj_t *actor) P_SetTarget(&filler->target, actor); filler->fuse = 59; P_SetTarget(&actor->tracer, filler); - P_SetScale(filler, (filler->destscale = actor->scale/3)); + P_SetScale(filler, actor->scale/3, true); if (actor->eflags & MFE_VERTICALFLIP) filler->flags2 |= MF2_OBJECTFLIP; filler->color = SKINCOLOR_ICY; @@ -9560,8 +9326,7 @@ void A_BossJetFume(mobj_t *actor) { P_SetTarget(&filler->target, actor); // Boss 4 already uses its tracer for other things - filler->destscale = actor->scale; - P_SetScale(filler, filler->destscale); + P_SetScale(filler, actor->scale, true); if (actor->eflags & MFE_VERTICALFLIP) filler->flags2 |= MF2_OBJECTFLIP; } @@ -9583,8 +9348,7 @@ void A_BossJetFume(mobj_t *actor) { filler->movefactor = movefactor; P_SetTarget(&filler->target, actor); - filler->destscale = actor->scale; - P_SetScale(filler, filler->destscale); + P_SetScale(filler, actor->scale, true); if (actor->eflags & MFE_VERTICALFLIP) filler->flags2 |= MF2_OBJECTFLIP; } @@ -9734,7 +9498,7 @@ void A_RemoteAction(mobj_t *actor) // scan the thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -9830,12 +9594,13 @@ void A_ToggleFlameJet(mobj_t* actor) // var1 = Angle adjustment (aka orbit speed) // var2: // Bits 1-10: height offset, max 1023 -// Bits 11-16: X radius factor (max 63, default 20) +// Bits 11-16: X radius factor (max 63, default 32) // Bit 17: set if object is Nightopian Helper // Bit 18: set to define X/Y/Z rotation factor -// Bits 19-20: Unused +// Bit 19: set to not sync scale to player +// Bit 20: Unused // Bits 21-26: Y radius factor (max 63, default 32) -// Bits 27-32: Z radius factor (max 63, default 32) +// Bits 27-32: Z radius factor (max 63, default 20) // // If MF_GRENADEBOUNCE is flagged on mobj, use actor->threshold to define X/Y/Z radius factor, max 1023 each: // Bits 1-10: X factor @@ -9876,6 +9641,12 @@ void A_OrbitNights(mobj_t* actor) } else { + if (!donotrescale) + { + P_SetScale(actor, actor->target->scale, true); + actor->old_scale = actor->target->old_scale; + } + actor->extravalue1 += var1; P_UnsetThingPosition(actor); { @@ -9903,9 +9674,6 @@ void A_OrbitNights(mobj_t* actor) else actor->flags2 &= ~MF2_DONTDRAW; } - - if (!donotrescale && actor->destscale != actor->target->destscale) - actor->destscale = actor->target->destscale; } } @@ -9993,7 +9761,7 @@ void A_SetObjectTypeState(mobj_t *actor) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -10623,7 +10391,7 @@ void A_CheckThingCount(mobj_t *actor) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -11004,7 +10772,7 @@ void A_ForceWin(mobj_t *actor) { if (!playeringame[i]) continue; - P_DoPlayerExit(&players[i]); + P_DoPlayerExit(&players[i], true); } } @@ -11154,9 +10922,10 @@ void A_SetScale(mobj_t *actor) return; } - target->destscale = locvar1; // destination scale - if (!(locvar2 & 65535)) - P_SetScale(target, locvar1); // this instantly changes current scale to var1 if used, if not destscale will alter scale to var1 anyway + if ((locvar2 & 65535) == 0) + P_SetScale(target, locvar1, true); // this instantly changes current scale to var1 if used, if not destscale will alter scale to var1 over time + else + target->destscale = locvar1; // destination scale } // Function: A_RemoteDamage @@ -11300,8 +11069,7 @@ void A_TrapShot(mobj_t *actor) if (actor->eflags & MFE_VERTICALFLIP) missile->flags2 |= MF2_OBJECTFLIP; - missile->destscale = actor->scale; - P_SetScale(missile, actor->scale); + P_SetScale(missile, actor->scale, true); if (missile->info->seesound) S_StartSound(missile, missile->info->seesound); @@ -11375,8 +11143,7 @@ void A_VileTarget(mobj_t *actor) fog->eflags |= MFE_VERTICALFLIP; fog->flags2 |= MF2_OBJECTFLIP; } - fog->destscale = actor->target->scale; - P_SetScale(fog, fog->destscale); + P_SetScale(fog, actor->target->scale, true); P_SetTarget(&actor->tracer, fog); P_SetTarget(&fog->target, actor); @@ -11409,8 +11176,7 @@ void A_VileTarget(mobj_t *actor) fog->eflags |= MFE_VERTICALFLIP; fog->flags2 |= MF2_OBJECTFLIP; } - fog->destscale = players[i].mo->scale; - P_SetScale(fog, fog->destscale); + P_SetScale(fog, players[i].mo->scale, true); if (players[i].mo == actor->target) // We only care to track the fog targeting who we REALLY hate right now P_SetTarget(&actor->tracer, fog); @@ -11567,8 +11333,8 @@ void A_VileFire(mobj_t *actor) return; // keep to same scale and gravity as tracer ALWAYS - actor->destscale = dest->scale; - P_SetScale(actor, actor->destscale); + P_SetScale(actor, dest->scale, true); + actor->old_scale = dest->old_scale; if (dest->eflags & MFE_VERTICALFLIP) { actor->eflags |= MFE_VERTICALFLIP; @@ -11735,7 +11501,13 @@ void A_BrakChase(mobj_t *actor) // chase towards player if (--actor->movecount < 0 || !P_Move(actor, actor->info->speed)) + { + if (P_MobjWasRemoved(actor)) + return; P_NewChaseDir(actor); + if (P_MobjWasRemoved(actor)) + return; + } // Optionally play a sound effect if (locvar2 > 0 && locvar2 < NUMSFX) @@ -12748,8 +12520,7 @@ void A_LightBeamReset(mobj_t *actor) if (LUA_CallAction(A_LIGHTBEAMRESET, actor)) return; - actor->destscale = FRACUNIT + P_SignedRandom()*FRACUNIT/256; - P_SetScale(actor, actor->destscale); + P_SetScale(actor, FRACUNIT + P_SignedRandom()*FRACUNIT/256, true); if (!actor->spawnpoint) return; // this can't work properly welp @@ -13314,6 +13085,8 @@ void A_DoNPCSkid(mobj_t *actor) if ((FixedHypot(actor->momx, actor->momy) < locvar2) || !P_TryMove(actor, actor->x + actor->momx, actor->y + actor->momy, false)) { + if (P_MobjWasRemoved(actor)) + return; actor->momx = actor->momy = 0; P_SetMobjState(actor, locvar1); return; @@ -13334,7 +13107,7 @@ void A_DoNPCSkid(mobj_t *actor) { particle->tics = 10; - P_SetScale(particle, 2*actor->scale/3); + P_SetScale(particle, 2*actor->scale/3, true); particle->destscale = actor->scale; P_SetObjectMomZ(particle, FRACUNIT, false); } @@ -13757,7 +13530,7 @@ static void P_DustRing(mobjtype_t mobjtype, UINT32 div, fixed_t x, fixed_t y, fi continue; dust->angle = ang*i + ANGLE_90; - P_SetScale(dust, FixedMul(initscale, scale)); + P_SetScale(dust, FixedMul(initscale, scale), true); dust->destscale = FixedMul(4*FRACUNIT + P_RandomFixed(), scale); dust->scalespeed = scale/24; P_Thrust(dust, ang*i, speed + FixedMul(P_RandomFixed(), scale)); @@ -13856,6 +13629,8 @@ static boolean PIT_DustDevilLaunch(mobj_t *thing) y = dustdevil->y; } P_TryMove(thing, x - thing->momx, y - thing->momy, true); + if (P_MobjWasRemoved(thing)) + return false; } else { //Player on the top of the tornado. @@ -13896,7 +13671,8 @@ void A_DustDevilThink(mobj_t *actor) while (layer && !P_MobjWasRemoved(layer)) { angle_t fa = layer->angle >> ANGLETOFINESHIFT; P_MoveOrigin(layer, layer->x + 5 * FixedMul(scale, FINECOSINE(fa)), layer->y + 5 * FixedMul(scale, FINESINE(fa)), layer->z); - layer->scale = scale; + P_SetScale(layer, scale, true); + layer->old_scale = actor->old_scale; layer->angle += ANG10 / 2; layer->momx = actor->momx; layer->momy = actor->momy; @@ -13910,8 +13686,7 @@ void A_DustDevilThink(mobj_t *actor) if (!P_MobjWasRemoved(dust)) { P_SetMobjState(dust, dust->info->spawnstate + P_RandomRange(0, 2)); - dust->destscale = scale * 3; - P_SetScale(dust, dust->destscale); + P_SetScale(dust, 3 * scale, true); } } @@ -13930,6 +13705,7 @@ void A_DustDevilThink(mobj_t *actor) layer = P_SpawnMobj(px, py, pz, MT_DUSTLAYER); if (P_MobjWasRemoved(layer)) continue; + P_SetScale(layer, scale, true); layer->momz = 5 * scale; layer->angle = ANGLE_90 + ANGLE_90*i; layer->extravalue1 = TICRATE * 3; @@ -14260,6 +14036,8 @@ static void P_SnapperLegPlace(mobj_t *mo) seg->z = mo->z + ((mo->eflags & MFE_VERTICALFLIP) ? (((mo->height<<1)/3) - seg->height) : mo->height/3); P_TryMove(seg, mo->x + FixedMul(c, rad) + necklen*c, mo->y + FixedMul(s, rad) + necklen*s, true); + if (P_MobjWasRemoved(seg)) + return; seg->angle = a; // Move as many legs as available. @@ -14281,6 +14059,8 @@ static void P_SnapperLegPlace(mobj_t *mo) y = s*o2 - c*o1; seg->z = mo->z + (((mo->eflags & MFE_VERTICALFLIP) ? (mo->height - seg->height) : 0)); P_TryMove(seg, mo->x + x, mo->y + y, true); + if (P_MobjWasRemoved(seg)) + return; P_SetMobjState(seg, seg->info->raisestate); } else @@ -14424,6 +14204,8 @@ void A_SnapperThinker(mobj_t *actor) s = FINESINE(fa); P_TryMove(actor, actor->x + c*speed, actor->y + s*speed, false); + if (P_MobjWasRemoved(actor)) + return; // The snapper spawns dust if going fast! if (actor->reactiontime < 4) @@ -14544,8 +14326,7 @@ void A_MinecartSparkThink(mobj_t *actor) continue; trail->tics = 2; trail->sprite = actor->sprite; - P_SetScale(trail, trail->scale/4); - trail->destscale = trail->scale; + P_SetScale(trail, trail->scale/4, true); } } @@ -14614,7 +14395,7 @@ void A_LavafallLava(mobj_t *actor) if (LUA_CallAction(A_LAVAFALLLAVA, actor)) return; - if ((40 - actor->fuse) % (2*(actor->scale >> FRACBITS))) + if ((40 - actor->fuse) % max(2*(actor->scale >> FRACBITS), 1)) // avoid crashes if actor->scale < FRACUNIT return; // Don't spawn lava unless a player is nearby. @@ -14668,8 +14449,16 @@ void A_FireShrink(mobj_t *actor) if (LUA_CallAction(A_FIRESHRINK, actor)) return; - actor->destscale = locvar1; - actor->scalespeed = FRACUNIT/locvar2; + if (locvar2 == 0) + { + P_SetScale(actor, locvar1, true); + actor->scalespeed = FRACUNIT/12; // Reset scalespeed to the default + } + else + { + actor->destscale = locvar1; + actor->scalespeed = FRACUNIT/locvar2; + } } // Function: A_SpawnPterabytes @@ -14799,12 +14588,18 @@ void A_RolloutRock(mobj_t *actor) if (!actor->tracer || P_MobjWasRemoved(actor->tracer) || !actor->tracer->health) actor->flags |= MF_PUSHABLE; + else if (actor->tracer->eflags & MFE_VERTICALFLIP) + { + actor->flags2 |= MF2_OBJECTFLIP; + actor->eflags |= MFE_VERTICALFLIP; + } else { - actor->flags2 = (actor->flags2 & ~MF2_OBJECTFLIP) | (actor->tracer->flags2 & MF2_OBJECTFLIP); - actor->eflags = (actor->eflags & ~MFE_VERTICALFLIP) | (actor->tracer->eflags & MFE_VERTICALFLIP); + actor->flags2 &= ~MF2_OBJECTFLIP; + actor->eflags &= ~MFE_VERTICALFLIP; } + actor->friction = FRACUNIT; // turns out riding on solids sucks, so let's just make it easier on ourselves if (actor->eflags & MFE_JUSTHITFLOOR) diff --git a/src/p_inter.c b/src/p_inter.c index d8765e7a2b4bde8358ba5188155a18c1c64a01df..27e612154dc87c1b88fec2e42e890af0d27c382e 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -101,7 +101,7 @@ void P_ClearStarPost(INT32 postnum) // scan the thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -130,7 +130,7 @@ void P_ResetStarposts(void) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; post = (mobj_t *)th; @@ -392,17 +392,50 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } } + // Ignore multihits in "ouchie" mode + if (special->flags & (MF_ENEMY | MF_BOSS) && special->flags2 & MF2_FRET) + return; + player = toucher->player; - I_Assert(player != NULL); // Only players can touch stuff! - if (player->spectator) - return; + if (player) + { + if (player->spectator) + return; - // Ignore multihits in "ouchie" mode - if (special->flags & (MF_ENEMY|MF_BOSS) && special->flags2 & MF2_FRET) - return; + // Some hooks may assume that the toucher is a player, so we keep it in here. + if (LUA_HookTouchSpecial(special, toucher) || P_MobjWasRemoved(special)) + return; + } + + if (player || (toucher->flags & MF_PUSHABLE)) // Special area for objects that are interactable by both player AND MF_PUSHABLE. + { + if (special->type == MT_STEAM) + { + if (player && player->mo->state == &states[player->mo->info->painstate]) // can't use gas jets when player is in pain! + return; - if (LUA_HookTouchSpecial(special, toucher) || P_MobjWasRemoved(special)) + fixed_t speed = special->info->mass; // gas jets use this for the vertical thrust + SINT8 flipval = P_MobjFlip(special); // virtually everything here centers around the thruster's gravity, not the object's! + + if (special->state != &states[S_STEAM1]) // Only when it bursts + return; + + toucher->eflags |= MFE_SPRUNG; + toucher->momz = flipval * FixedMul(speed, FixedSqrt(FixedMul(special->scale, toucher->scale))); // scale the speed with both objects' scales, just like with springs! + + if (player) + { + P_ResetPlayer(player); + if (player->panim != PA_FALL) + P_SetMobjState(toucher, S_PLAY_FALL); + } + + return; // Don't collect it! + } + } + + if (!player) // Only players can touch stuff! return; // 0 = none, 1 = elemental pierce, 2 = bubble bounce @@ -505,14 +538,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1) && (!(player->powers[pw_strong] & STR_HEAVY))) { fixed_t setmomz = -toucher->momz; // Store this, momz get changed by P_DoJump within P_DoBubbleBounce - + if (elementalpierce == 2) // Reset bubblewrap, part 1 P_DoBubbleBounce(player); toucher->momz = setmomz; if (elementalpierce == 2) // Reset bubblewrap, part 2 { boolean underwater = toucher->eflags & MFE_UNDERWATER; - + if (underwater) toucher->momz /= 2; toucher->momz -= (toucher->momz/(underwater ? 8 : 4)); // Cap the height! @@ -803,7 +836,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) { clientGamedata->collected[special->health-1] = true; M_UpdateUnlockablesAndExtraEmblems(clientGamedata); - G_SaveGameData(clientGamedata); + if (!prevCollected) // don't thrash the disk and wreak performance. + G_SaveGameData(clientGamedata); } if (netgame) @@ -969,7 +1003,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // scan the thinkers to find the corresponding anchorpoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -1063,7 +1097,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // scan the remaining thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -1113,7 +1147,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // in from the paraloop. Isn't this just so efficient? for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -1332,7 +1366,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } break; case MT_NIGHTSEXTRATIME: - if ((player->bot && player->bot != BOT_MPAI) || !(player->powers[pw_carry] == CR_NIGHTSMODE)) + if ((player->bot && player->bot != BOT_MPAI) || !(player->powers[pw_carry] == CR_NIGHTSMODE || (G_IsSpecialStage(gamemap) && !(maptol & TOL_NIGHTS)))) return; if (!G_IsSpecialStage(gamemap)) { @@ -1344,7 +1378,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) else { for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].powers[pw_carry] == CR_NIGHTSMODE) + if (playeringame[i] && (player->powers[pw_carry] == CR_NIGHTSMODE || (G_IsSpecialStage(gamemap) && !(maptol & TOL_NIGHTS)))) { players[i].nightstime += special->info->speed; players[i].startedtime += special->info->speed; @@ -1397,11 +1431,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) i = 0; for (; special->type == MT_HOOP; special = special->hnext) { - special->fuse = 11; - special->movedir = i; - special->extravalue1 = special->target->extravalue1; - special->extravalue2 = special->target->extravalue2; - special->target->threshold = 4242; + if (!P_MobjWasRemoved(special->target)) + { + special->fuse = 11; + special->movedir = i; + special->extravalue1 = special->target->extravalue1; + special->extravalue2 = special->target->extravalue2; + special->target->threshold = 4242; + } i++; } // Make the collision detectors disappear. @@ -1485,7 +1522,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // scan the remaining thinkers to find koopa for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -1878,6 +1915,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) toucher->tracer->flags2 = (toucher->tracer->flags2 & ~MF2_AMBUSH) | destambush; } return; + default: // SOC or script pickup if (player->bot && player->bot != BOT_MPAI) return; @@ -1982,7 +2020,7 @@ void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -2530,8 +2568,14 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget { P_SetTarget(&target->target, source); source->player->numboxes++; - if (cv_itemrespawn.value && gametype != GT_COOP && (modifiedgame || netgame || multiplayer)) - target->fuse = cv_itemrespawntime.value*TICRATE + 2; // Random box generation + // Set respawn + if (!(target->flags2 & MF2_DONTRESPAWN)) + { + if (!(netgame || multiplayer)) + target->fuse = atoi(cv_itemrespawntime.defaultvalue)*TICRATE + 2; + else if (cv_itemrespawn.value) + target->fuse = cv_itemrespawntime.value*TICRATE + 2; + } } // Award Score Tails @@ -2765,8 +2809,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget mo = P_SpawnMobj(target->x, target->y, target->z, MT_EXTRALARGEBUBBLE); if (P_MobjWasRemoved(mo)) break; - mo->destscale = target->scale; - P_SetScale(mo, mo->destscale); + P_SetScale(mo, target->scale, true); P_SetMobjState(mo, mo->info->raisestate); break; @@ -2827,7 +2870,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget // scan the thinkers to make sure all the old pinch dummies are gone on death for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo = (mobj_t *)th; @@ -3598,7 +3641,7 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source) if (player->nightstime > 5*TICRATE) player->nightstime -= 5*TICRATE; else - player->nightstime = 0; + player->nightstime = 1; } P_DoPlayerPain(player, inflictor, source); @@ -3744,6 +3787,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (player->powers[pw_carry] == CR_NIGHTSMODE) // NiGHTS damage handling { + if (player->powers[pw_flashing]) + return false; if (!force) { if (source == target) @@ -3761,6 +3806,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (G_IsSpecialStage(gamemap) && !(damagetype & DMG_DEATHMASK)) { + if (player->powers[pw_flashing]) + return false; + if (LUA_HookMobjDamage(target, inflictor, source, damage, damagetype)) + return true; P_SpecialStageDamage(player, inflictor, source); return true; } @@ -3957,8 +4006,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) mo->fuse = 8*TICRATE; P_SetTarget(&mo->target, player->mo); - mo->destscale = player->mo->scale; - P_SetScale(mo, player->mo->scale); + P_SetScale(mo, player->mo->scale, true); // Angle offset by player angle, then slightly offset by amount of rings fa = ((i*FINEANGLES/16) + va - ((num_rings-1)*FINEANGLES/32)) & FINEMASK; @@ -4094,8 +4142,7 @@ void P_PlayerWeaponPanelBurst(player_t *player) mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT); P_SetTarget(&mo->target, player->mo); mo->fuse = 12*TICRATE; - mo->destscale = player->mo->scale; - P_SetScale(mo, player->mo->scale); + P_SetScale(mo, player->mo->scale, true); // Angle offset by player angle fa = ((i*FINEANGLES/16) + (player->mo->angle>>ANGLETOFINESHIFT)) & FINEMASK; @@ -4183,8 +4230,7 @@ void P_PlayerWeaponAmmoBurst(player_t *player) player->powers[power] = 0; mo->fuse = 12*TICRATE; - mo->destscale = player->mo->scale; - P_SetScale(mo, player->mo->scale); + P_SetScale(mo, player->mo->scale, true); // Angle offset by player angle fa = ((i*FINEANGLES/16) + (player->mo->angle>>ANGLETOFINESHIFT)) & FINEMASK; @@ -4231,8 +4277,7 @@ void P_PlayerWeaponPanelOrAmmoBurst(player_t *player) mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT); \ P_SetTarget(&mo->target, player->mo); \ mo->fuse = 12*TICRATE; \ - mo->destscale = player->mo->scale; \ - P_SetScale(mo, player->mo->scale); \ + P_SetScale(mo, player->mo->scale, true); \ mo->momx = FixedMul(FINECOSINE(fa),ns); \ if (!(twodlevel || (player->mo->flags2 & MF2_TWOD))) \ mo->momy = FixedMul(FINESINE(fa),ns); \ @@ -4254,8 +4299,7 @@ void P_PlayerWeaponPanelOrAmmoBurst(player_t *player) mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT); \ P_SetTarget(&mo->target, player->mo); \ mo->fuse = 12*TICRATE; \ - mo->destscale = player->mo->scale; \ - P_SetScale(mo, player->mo->scale); \ + P_SetScale(mo, player->mo->scale, true); \ mo->momx = FixedMul(FINECOSINE(fa),ns); \ if (!(twodlevel || (player->mo->flags2 & MF2_TWOD))) \ mo->momy = FixedMul(FINESINE(fa),ns); \ diff --git a/src/p_local.h b/src/p_local.h index 3b61b92295363a8d0ec789ce7920cb94cf417c2d..85a31cf8982114068b0da41c7a59971d011929ba 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -39,11 +39,6 @@ // Convenience macro to fix issue with collision along bottom/left edges of blockmap -Red #define BMBOUNDFIX(xl, xh, yl, yh) {if (xl > xh) xl = 0; if (yl > yh) yl = 0;} -// MAXRADIUS is for precalculated sector block boxes -// the spider demon is larger, -// but we do not have any moving sectors nearby -#define MAXRADIUS (32*FRACUNIT) - // max Z move up or down without jumping // above this, a height difference is considered as a 'dropoff' #define MAXSTEPMOVE (24*FRACUNIT) @@ -189,7 +184,7 @@ void P_DoPityCheck(player_t *player); void P_PlayerThink(player_t *player); void P_PlayerAfterThink(player_t *player); void P_DoPlayerFinish(player_t *player); -void P_DoPlayerExit(player_t *player); +void P_DoPlayerExit(player_t *player, boolean finishedflag); void P_NightserizePlayer(player_t *player, INT32 ptime); void P_InstaThrust(mobj_t *mo, angle_t angle, fixed_t move); @@ -203,7 +198,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet); void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius); void P_Earthquake(mobj_t *inflictor, mobj_t *source, fixed_t radius); boolean P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user -boolean P_SuperReady(player_t *player, boolean transform); +boolean P_SuperReady(player_t *player); void P_DoJump(player_t *player, boolean soundandstate, boolean allowflip); void P_DoSpinDashDust(player_t *player); #define P_AnalogMove(player) (P_ControlStyle(player) == CS_LMAOGALOG) @@ -283,7 +278,6 @@ void P_PlayJingleMusic(player_t *player, const char *musname, UINT16 musflags, b extern mapthing_t *itemrespawnque[ITEMQUESIZE]; extern tic_t itemrespawntime[ITEMQUESIZE]; extern size_t iquehead, iquetail; -extern consvar_t cv_gravity, cv_movebob; mobjtype_t P_GetMobjtype(UINT16 mthingtype); @@ -295,7 +289,6 @@ void P_RecalcPrecipInSector(sector_t *sector); void P_PrecipitationEffects(void); void P_RemoveMobj(mobj_t *th); -boolean P_MobjWasRemoved(mobj_t *th); void P_RemoveSavegameMobj(mobj_t *th); boolean P_SetMobjState(mobj_t *mobj, statenum_t state); void P_RunShields(void); @@ -307,22 +300,26 @@ boolean P_CheckSkyHit(mobj_t *mo, line_t *line); void P_PushableThinker(mobj_t *mobj); void P_SceneryThinker(mobj_t *mobj); - -fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect); -fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect); -#define P_GetFloorZ(mobj, sector, x, y, line) P_MobjFloorZ(mobj, sector, NULL, x, y, line, false, false) -#define P_GetCeilingZ(mobj, sector, x, y, line) P_MobjCeilingZ(mobj, sector, NULL, x, y, line, true, false) -#define P_GetFOFTopZ(mobj, sector, fof, x, y, line) P_MobjCeilingZ(mobj, sectors + fof->secnum, sector, x, y, line, false, false) -#define P_GetFOFBottomZ(mobj, sector, fof, x, y, line) P_MobjFloorZ(mobj, sectors + fof->secnum, sector, x, y, line, true, false) -#define P_GetSpecialBottomZ(mobj, src, bound) P_MobjFloorZ(mobj, src, bound, mobj->x, mobj->y, NULL, src != bound, true) -#define P_GetSpecialTopZ(mobj, src, bound) P_MobjCeilingZ(mobj, src, bound, mobj->x, mobj->y, NULL, src == bound, true) - -fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect); -fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect); -#define P_CameraGetFloorZ(mobj, sector, x, y, line) P_CameraFloorZ(mobj, sector, NULL, x, y, line, false, false) -#define P_CameraGetCeilingZ(mobj, sector, x, y, line) P_CameraCeilingZ(mobj, sector, NULL, x, y, line, true, false) -#define P_CameraGetFOFTopZ(mobj, sector, fof, x, y, line) P_CameraCeilingZ(mobj, sectors + fof->secnum, sector, x, y, line, false, false) -#define P_CameraGetFOFBottomZ(mobj, sector, fof, x, y, line) P_CameraFloorZ(mobj, sectors + fof->secnum, sector, x, y, line, true, false) +// This does not need to be added to Lua. +// To test it in Lua, check mobj.valid +FUNCINLINE static ATTRINLINE boolean P_MobjWasRemoved(mobj_t *mobj) +{ + return mobj == NULL || mobj->thinker.function.acp1 != (actionf_p1)P_MobjThinker; +} + +fixed_t P_MobjFloorZ(sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, fixed_t radius, line_t *line, boolean lowest, boolean perfect); +fixed_t P_MobjCeilingZ(sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, fixed_t radius, line_t *line, boolean lowest, boolean perfect); +#define P_GetFloorZ(mobj, sector, x, y, line) P_MobjFloorZ(sector, NULL, x, y, mobj->radius, line, false, false) +#define P_GetCeilingZ(mobj, sector, x, y, line) P_MobjCeilingZ(sector, NULL, x, y, mobj->radius, line, true, false) +#define P_GetFOFTopZ(mobj, sector, fof, x, y, line) P_MobjCeilingZ(sectors + fof->secnum, sector, x, y, mobj->radius, line, false, false) +#define P_GetFOFBottomZ(mobj, sector, fof, x, y, line) P_MobjFloorZ(sectors + fof->secnum, sector, x, y, mobj->radius, line, true, false) +#define P_GetSpecialBottomZ(mobj, src, bound) P_MobjFloorZ(src, bound, mobj->x, mobj->y, mobj->radius, NULL, src != bound, true) +#define P_GetSpecialTopZ(mobj, src, bound) P_MobjCeilingZ(src, bound, mobj->x, mobj->y, mobj->radius, NULL, src == bound, true) + +#define P_CameraGetFloorZ(mobj, sector, x, y, line) P_MobjFloorZ(sector, NULL, x, y, mobj->radius, line, false, false) +#define P_CameraGetCeilingZ(mobj, sector, x, y, line) P_MobjCeilingZ(sector, NULL, x, y, mobj->radius, line, true, false) +#define P_CameraGetFOFTopZ(mobj, sector, fof, x, y, line) P_MobjCeilingZ(sectors + fof->secnum, sector, x, y, mobj->radius, line, false, false) +#define P_CameraGetFOFBottomZ(mobj, sector, fof, x, y, line) P_MobjFloorZ(sectors + fof->secnum, sector, x, y, mobj->radius, line, true, false) boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover); boolean P_CheckDeathPitCollide(mobj_t *mo); @@ -552,6 +549,7 @@ void P_ThrustEvenIn2D(mobj_t *mo, angle_t angle, fixed_t move); void P_VectorInstaThrust(fixed_t xa, fixed_t xb, fixed_t xc, fixed_t ya, fixed_t yb, fixed_t yc, fixed_t za, fixed_t zb, fixed_t zc, fixed_t momentum, mobj_t *mo); void P_DoSuperTransformation(player_t *player, boolean giverings); +void P_DoSuperDetransformation(player_t *player); void P_ExplodeMissile(mobj_t *mo); void P_CheckGravity(mobj_t *mo, boolean affect); void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope); diff --git a/src/p_map.c b/src/p_map.c index 7887c117de56907d7a51eccb3715ec0a32e14d61..fce17f8c4bb2357eb9d789a46261119e67f9e946 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -36,6 +36,9 @@ #include "m_perfstats.h" // ps_checkposition_calls +// Formerly called MAXRADIUS +#define MAXTRYMOVE (32*FRACUNIT) + fixed_t tmbbox[4]; mobj_t *tmthing; static INT32 tmflags; @@ -389,7 +392,6 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) { INT32 pflags; UINT8 secondjump; - boolean washoming; if (spring->flags & MF_ENEMY) // Spring shells P_SetTarget(&spring->target, object); @@ -421,7 +423,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) { boolean wasSpindashing = object->player->dashspeed > 0 && (object->player->charability2 == CA2_SPINDASH); - pflags = object->player->pflags & (PF_STARTJUMP | PF_JUMPED | PF_NOJUMPDAMAGE | PF_SPINNING | PF_THOKKED | PF_BOUNCING); // I still need these. + pflags = object->player->pflags & (PF_STARTJUMP | PF_JUMPED | PF_NOJUMPDAMAGE | PF_SPINNING | PF_BOUNCING); // I still need these. if (wasSpindashing) // Ensure we're in the rolling state, and not spindash. P_SetMobjState(object, S_PLAY_ROLL); @@ -433,7 +435,6 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) } } secondjump = object->player->secondjump; - washoming = object->player->homing; P_ResetPlayer(object->player); if (spring->info->painchance == 1) // For all those ancient, SOC'd abilities. @@ -445,8 +446,6 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) { object->player->pflags |= (pflags &~ PF_STARTJUMP); object->player->secondjump = secondjump; - if (washoming) - object->player->pflags &= ~PF_THOKKED; } else if (!vertispeed) { @@ -502,72 +501,56 @@ springstate: return final; } -static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object) +static void P_DoFan(mobj_t *fan, mobj_t *object) { player_t *p = object->player; // will be NULL if not a player fixed_t zdist; // distance between bottoms - fixed_t speed = spring->info->mass; // conveniently, both fans and gas jets use this for the vertical thrust - SINT8 flipval = P_MobjFlip(spring); // virtually everything here centers around the thruster's gravity, not the object's! + fixed_t speed = fan->info->mass; // fans use this for the vertical thrust + SINT8 flipval = P_MobjFlip(fan); // virtually everything here centers around the thruster's gravity, not the object's! - if (p && object->state == &states[object->info->painstate]) // can't use fans and gas jets when player is in pain! + if (p && object->state == &states[object->info->painstate]) // can't use fans when player is in pain! return; // is object's top below thruster's position? if not, calculate distance between their bottoms - if (spring->eflags & MFE_VERTICALFLIP) + if (fan->eflags & MFE_VERTICALFLIP) { - if (object->z > spring->z + spring->height) + if (object->z > fan->z + fan->height) return; - zdist = (spring->z + spring->height) - (object->z + object->height); + zdist = (fan->z + fan->height) - (object->z + object->height); } else { - if (object->z + object->height < spring->z) + if (object->z + object->height < fan->z) return; - zdist = object->z - spring->z; + zdist = object->z - fan->z; } object->standingslope = NULL; // No launching off at silly angles for you. - switch (spring->type) + switch (fan->type) { case MT_FAN: // fan - if (zdist > (spring->health << FRACBITS)) // max z distance determined by health (set by map thing args[0]) + if (zdist > (fan->health << FRACBITS)) // max z distance determined by health (set by map thing args[0]) break; - if (flipval*object->momz >= FixedMul(speed, spring->scale)) // if object's already moving faster than your best, don't bother + if (flipval*object->momz >= FixedMul(speed, fan->scale)) // if object's already moving faster than your best, don't bother break; if (p && (p->climbing || p->pflags & PF_GLIDING)) // doesn't affect Knux when he's using his abilities! break; - object->momz += flipval*FixedMul(speed/4, spring->scale); + object->momz += flipval*FixedMul(speed/4, fan->scale); // limit the speed if too high - if (flipval*object->momz > FixedMul(speed, spring->scale)) - object->momz = flipval*FixedMul(speed, spring->scale); + if (flipval*object->momz > FixedMul(speed, fan->scale)) + object->momz = flipval*FixedMul(speed, fan->scale); if (p && !p->powers[pw_tailsfly] && !p->powers[pw_carry]) // doesn't reset anim for Tails' flight { P_ResetPlayer(p); P_SetMobjState(object, S_PLAY_FALL); - P_SetTarget(&object->tracer, spring); + P_SetTarget(&object->tracer, fan); p->powers[pw_carry] = CR_FAN; } break; - case MT_STEAM: // Steam - if (zdist > FixedMul(16*FRACUNIT, spring->scale)) - break; - if (spring->state != &states[S_STEAM1]) // Only when it bursts - break; - - object->eflags |= MFE_SPRUNG; - object->momz = flipval*FixedMul(speed, FixedSqrt(FixedMul(spring->scale, object->scale))); // scale the speed with both objects' scales, just like with springs! - - if (p) - { - P_ResetPlayer(p); - if (p->panim != PA_FALL) - P_SetMobjState(object, S_PLAY_FALL); - } - break; default: break; } @@ -1043,7 +1026,6 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) if ((thing->flags & MF_PUSHABLE) // not carrying a player && (tmthing->player->powers[pw_carry] == CR_NONE) // player is not already riding something && !(tmthing->player->powers[pw_ignorelatch] & (1<<15)) - && ((tmthing->eflags & MFE_VERTICALFLIP) == (thing->eflags & MFE_VERTICALFLIP)) && (P_MobjFlip(tmthing)*tmthing->momz <= 0) && ((!(tmthing->eflags & MFE_VERTICALFLIP) && abs(thing->z + thing->height - tmthing->z) < (thing->height>>2)) || (tmthing->eflags & MFE_VERTICALFLIP && abs(tmthing->z + tmthing->height - thing->z) < (thing->height>>2)))) @@ -1057,6 +1039,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) P_SetTarget(&tmthing->tracer, thing); if (!P_IsObjectOnGround(thing)) thing->momz += tmthing->momz; + return CHECKTHING_COLLIDE; } } @@ -1278,8 +1261,9 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) if (tmthing->type != MT_SHELL && tmthing->target && tmthing->target->type == thing->type) { - // Don't hit same species as originator. - if (thing == tmthing->target) + // Don't hit yourself, and if a player, don't hit bots + if (thing == tmthing->target + || (thing->player && tmthing->target->player && (thing->player->bot == BOT_2PAI || thing->player->bot == BOT_2PHUMAN))) return CHECKTHING_IGNORE; if (thing->type != MT_PLAYER) @@ -1484,13 +1468,13 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) } // check for special pickup - if (thing->flags & MF_SPECIAL && tmthing->player) + if (thing->flags & MF_SPECIAL && (tmthing->player || (tmthing->flags & MF_PUSHABLE))) // MF_PUSHABLE added for steam jets { P_TouchSpecialThing(thing, tmthing, true); // can remove thing return CHECKTHING_COLLIDE; } // check again for special pickup - if (tmthing->flags & MF_SPECIAL && thing->player) + if (tmthing->flags & MF_SPECIAL && (thing->player || (thing->flags & MF_PUSHABLE))) // MF_PUSHABLE added for steam jets { P_TouchSpecialThing(tmthing, thing, true); // can remove thing return CHECKTHING_COLLIDE; @@ -1578,15 +1562,15 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) if (thing->flags & MF_PUSHABLE) { - if (tmthing->type == MT_FAN || tmthing->type == MT_STEAM) - P_DoFanAndGasJet(tmthing, thing); + if (tmthing->type == MT_FAN) + P_DoFan(tmthing, thing); } if (tmthing->flags & MF_PUSHABLE) { - if (thing->type == MT_FAN || thing->type == MT_STEAM) + if (thing->type == MT_FAN) { - P_DoFanAndGasJet(thing, tmthing); + P_DoFan(thing, tmthing); return CHECKTHING_COLLIDE; } else if (thing->flags & MF_SPRING) @@ -1679,8 +1663,8 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) } } - if (tmthing->type == MT_FAN || tmthing->type == MT_STEAM) - P_DoFanAndGasJet(tmthing, thing); + if (tmthing->type == MT_FAN) + P_DoFan(tmthing, thing); } if (tmthing->player) // Is the moving/interacting object the player? @@ -1688,8 +1672,8 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) if (!tmthing->health) return CHECKTHING_IGNORE; - if (thing->type == MT_FAN || thing->type == MT_STEAM) - P_DoFanAndGasJet(thing, tmthing); + if (thing->type == MT_FAN) + P_DoFan(thing, tmthing); else if (thing->flags & MF_SPRING && tmthing->player->powers[pw_carry] != CR_MINECART) { if ( thing->z <= tmthing->z + tmthing->height @@ -1755,8 +1739,8 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) // not solid not blocked unsigned collide = CHECKTHING_NOCOLLIDE; - if ((tmthing->flags & MF_SPRING || tmthing->type == MT_STEAM || tmthing->type == MT_SPIKE || tmthing->type == MT_WALLSPIKE) && (thing->player)) - ; // springs, gas jets and springs should never be able to step up onto a player + if ((tmthing->flags & MF_SPRING || tmthing->type == MT_SPIKE || tmthing->type == MT_WALLSPIKE) && (thing->player)) + ; // springs and spikes should never be able to step up onto a player // z checking at last // Treat noclip things as non-solid! else if ((thing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID @@ -2184,15 +2168,10 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) } } - // The bounding box is extended by MAXRADIUS - // because mobj_ts are grouped into mapblocks - // based on their origin point, and can overlap - // into adjacent blocks by up to MAXRADIUS units. - - xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; - xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; - yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; - yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; + xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; BMBOUNDFIX(xl, xh, yl, yh); @@ -2412,11 +2391,6 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) } } - // The bounding box is extended by MAXRADIUS - // because mobj_ts are grouped into mapblocks - // based on their origin point, and can overlap - // into adjacent blocks by up to MAXRADIUS units. - xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; @@ -2521,6 +2495,9 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) floatok = false; + if (dedicated) // this crashes so don't even try it + return false; + if (twodlevel || (thiscam == &camera && players[displayplayer].mo && (players[displayplayer].mo->flags2 & MF2_TWOD)) || (thiscam == &camera2 && players[secondarydisplayplayer].mo && (players[secondarydisplayplayer].mo->flags2 & MF2_TWOD))) @@ -2544,16 +2521,16 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) } do { - if (x-tryx > MAXRADIUS) - tryx += MAXRADIUS; - else if (x-tryx < -MAXRADIUS) - tryx -= MAXRADIUS; + if (x-tryx > MAXTRYMOVE) + tryx += MAXTRYMOVE; + else if (x-tryx < -MAXTRYMOVE) + tryx -= MAXTRYMOVE; else tryx = x; - if (y-tryy > MAXRADIUS) - tryy += MAXRADIUS; - else if (y-tryy < -MAXRADIUS) - tryy -= MAXRADIUS; + if (y-tryy > MAXTRYMOVE) + tryy += MAXTRYMOVE; + else if (y-tryy < -MAXTRYMOVE) + tryy -= MAXTRYMOVE; else tryy = y; @@ -2699,7 +2676,7 @@ increment_move floatok = false; // This makes sure that there are no freezes from computing extremely small movements. - // Originally was MAXRADIUS/2, but that can cause some bad inconsistencies for small players. + // Originally was MAXTRYMOVE/2, but that can cause some bad inconsistencies for small players. radius = max(radius, thing->scale); // And we also have to prevent Big Large (tm) movements, as those can skip too far @@ -2734,7 +2711,7 @@ increment_move tryy = y; } - if (!P_CheckPosition(thing, tryx, tryy)) + if (!P_CheckPosition(thing, tryx, tryy) || P_MobjWasRemoved(thing)) return false; // solid wall or thing if (!(thing->flags & MF_NOCLIP)) @@ -2888,10 +2865,10 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) { INT32 xl, xh, yl, yh; - yh = (unsigned)(thing->y + MAXRADIUS - bmaporgy)>>MAPBLOCKSHIFT; - yl = (unsigned)(thing->y - MAXRADIUS - bmaporgy)>>MAPBLOCKSHIFT; - xh = (unsigned)(thing->x + MAXRADIUS - bmaporgx)>>MAPBLOCKSHIFT; - xl = (unsigned)(thing->x - MAXRADIUS - bmaporgx)>>MAPBLOCKSHIFT; + yh = (unsigned)(thing->y + thing->radius - bmaporgy)>>MAPBLOCKSHIFT; + yl = (unsigned)(thing->y - thing->radius - bmaporgy)>>MAPBLOCKSHIFT; + xh = (unsigned)(thing->x + thing->radius - bmaporgx)>>MAPBLOCKSHIFT; + xl = (unsigned)(thing->x - thing->radius - bmaporgx)>>MAPBLOCKSHIFT; BMBOUNDFIX(xl, xh, yl, yh); @@ -2958,24 +2935,25 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y) { fixed_t tryx, tryy; + I_Assert(!P_MobjWasRemoved(thing)); tryx = thing->x; tryy = thing->y; do { - if (x-tryx > MAXRADIUS) - tryx += MAXRADIUS; - else if (x-tryx < -MAXRADIUS) - tryx -= MAXRADIUS; + if (x-tryx > MAXTRYMOVE) + tryx += MAXTRYMOVE; + else if (x-tryx < -MAXTRYMOVE) + tryx -= MAXTRYMOVE; else tryx = x; - if (y-tryy > MAXRADIUS) - tryy += MAXRADIUS; - else if (y-tryy < -MAXRADIUS) - tryy -= MAXRADIUS; + if (y-tryy > MAXTRYMOVE) + tryy += MAXTRYMOVE; + else if (y-tryy < -MAXTRYMOVE) + tryy -= MAXTRYMOVE; else tryy = y; - if (!P_CheckPosition(thing, tryx, tryy)) + if (!P_CheckPosition(thing, tryx, tryy) || P_MobjWasRemoved(thing)) return false; // solid wall or thing if (!(thing->flags & MF_NOCLIP)) @@ -3714,6 +3692,12 @@ static void P_CheckLavaWall(mobj_t *mo, sector_t *sec) } } +static inline void P_StairStepSlideMove(mobj_t *mo) +{ + if (!P_TryMove(mo, mo->x, mo->y + mo->momy, true) && !P_MobjWasRemoved(mo)) //Allow things to drop off. + P_TryMove(mo, mo->x + mo->momx, mo->y, true); +} + // // P_SlideMove // The momx / momy move is bad, so try to slide @@ -3735,6 +3719,8 @@ void P_SlideMove(mobj_t *mo) memset(&junk, 0x00, sizeof(junk)); + I_Assert(!P_MobjWasRemoved(mo)); + if (tmhitthing && mo->z + mo->height > tmhitthing->z && mo->z < tmhitthing->z + tmhitthing->height) { // Don't mess with your momentum if it's a pushable object. Pushables do their own crazy things already. @@ -3869,7 +3855,10 @@ void P_SlideMove(mobj_t *mo) retry: if ((++hitcount == 3) || papercol) - goto stairstep; // don't loop forever + { + P_StairStepSlideMove(mo); + return; + } // trace along the three leading corners if (mo->momx > 0) @@ -3921,9 +3910,7 @@ papercollision: if (bestslidefrac == FRACUNIT+1) { // the move must have hit the middle, so stairstep -stairstep: - if (!P_TryMove(mo, mo->x, mo->y + mo->momy, true)) //Allow things to drop off. - P_TryMove(mo, mo->x + mo->momx, mo->y, true); + P_StairStepSlideMove(mo); return; } @@ -3935,7 +3922,13 @@ stairstep: newy = FixedMul(mo->momy, bestslidefrac); if (!P_TryMove(mo, mo->x + newx, mo->y + newy, true)) - goto stairstep; + { + if (!P_MobjWasRemoved(mo)) + P_StairStepSlideMove(mo); + return; + } + if (P_MobjWasRemoved(mo)) + return; } // Now continue along the wall. @@ -3964,33 +3957,37 @@ stairstep: mo->momy = tmymove; } + const fixed_t tmradius = mo->radius > 8 ? mo->radius : 8; + do { - if (tmxmove > mo->radius) { - newx = mo->x + mo->radius; - tmxmove -= mo->radius; - } else if (tmxmove < -mo->radius) { - newx = mo->x - mo->radius; - tmxmove += mo->radius; + if (tmxmove > tmradius) { + newx = mo->x + tmradius; + tmxmove -= tmradius; + } else if (tmxmove < -tmradius) { + newx = mo->x - tmradius; + tmxmove += tmradius; } else { newx = mo->x + tmxmove; tmxmove = 0; } - if (tmymove > mo->radius) { - newy = mo->y + mo->radius; - tmymove -= mo->radius; - } else if (tmymove < -mo->radius) { - newy = mo->y - mo->radius; - tmymove += mo->radius; + if (tmymove > tmradius) { + newy = mo->y + tmradius; + tmymove -= tmradius; + } else if (tmymove < -tmradius) { + newy = mo->y - tmradius; + tmymove += tmradius; } else { newy = mo->y + tmymove; tmymove = 0; } if (!P_TryMove(mo, newx, newy, true)) { - if (success) + if (success || P_MobjWasRemoved(mo)) return; // Good enough!! else goto retry; } + if (P_MobjWasRemoved(mo)) + return; success = true; } while(tmxmove || tmymove); } @@ -4211,7 +4208,8 @@ void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 dama INT32 xl, xh, yl, yh; fixed_t dist; - dist = FixedMul(damagedist, spot->scale) + MAXRADIUS; + dist = FixedMul(damagedist, spot->scale); + yh = (unsigned)(spot->y + dist - bmaporgy)>>MAPBLOCKSHIFT; yl = (unsigned)(spot->y - dist - bmaporgy)>>MAPBLOCKSHIFT; xh = (unsigned)(spot->x + dist - bmaporgx)>>MAPBLOCKSHIFT; @@ -4381,15 +4379,15 @@ static boolean P_CheckSectorPolyObjects(sector_t *sector, boolean realcrush, boo { mobj_t *mo; blocknode_t *block; + blocknode_t *next = NULL; if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) continue; - block = blocklinks[y * bmapwidth + x]; - - for (; block; block = block->mnext) + for (block = blocklinks[y * bmapwidth + x]; block != NULL; block = next) { mo = block->mobj; + next = block->mnext; // Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect if (!P_MobjInsidePolyobj(po, mo)) diff --git a/src/p_maputl.c b/src/p_maputl.c index 758a71ca343b86c4c07181f1e0ef31b52dc7dfdf..5398fd7a4c584022e8f33bb49312a176207e74b8 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -500,8 +500,24 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) INT32 texnum = R_GetTextureNum(side->midtexture); // make sure the texture is actually valid if (texnum) { + fixed_t scaley = abs(side->scaley_mid); + fixed_t offsetvalue = FixedDiv(side->rowoffset + side->offsety_mid, scaley); + fixed_t midopentop, midopenbottom; + + if (linedef->flags & ML_NOSKEW) + { + // Use the sector's actual heights if the midtexture is not skewed + midopentop = min(front->ceilingheight, back->ceilingheight); + midopenbottom = max(front->floorheight, back->floorheight); + } + else + { + midopentop = opentop; + midopenbottom = openbottom; + } + // Get the midtexture's height - texheight = textures[texnum]->height << FRACBITS; + texheight = FixedDiv(textureheight[texnum], scaley); // Set texbottom and textop to the Z coordinates of the texture's boundaries #if 0 @@ -509,26 +525,26 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) // on non-solid polyobjects should NEVER happen in the future if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) { if (linedef->flags & ML_WRAPMIDTEX && !side->repeatcnt) { // "infinite" repeat - texbottom = back->floorheight + side->rowoffset + side->offsety_mid; - textop = back->ceilingheight + side->rowoffset + side->offsety_mid; + texbottom = back->floorheight + offsetvalue; + textop = back->ceilingheight + offsetvalue; } else if (linedef->flags & ML_MIDTEX) { - texbottom = back->floorheight + side->rowoffset + side->offsety_mid; + texbottom = back->floorheight + offsetvalue; textop = texbottom + texheight*(side->repeatcnt+1); } else { - textop = back->ceilingheight + side->rowoffset + side->offsety_mid; + textop = back->ceilingheight + offsetvalue; texbottom = textop - texheight*(side->repeatcnt+1); } } else #endif { if (linedef->flags & ML_WRAPMIDTEX && !side->repeatcnt) { // "infinite" repeat - texbottom = openbottom + side->rowoffset + side->offsety_mid; - textop = opentop + side->rowoffset + side->offsety_mid; + texbottom = midopenbottom + offsetvalue; + textop = midopentop + offsetvalue; } else if (linedef->flags & ML_MIDPEG) { - texbottom = openbottom + side->rowoffset + side->offsety_mid; + texbottom = midopenbottom + offsetvalue; textop = texbottom + texheight*(side->repeatcnt+1); } else { - textop = opentop + side->rowoffset + side->offsety_mid; + textop = midopentop + offsetvalue; texbottom = textop - texheight*(side->repeatcnt+1); } } @@ -539,11 +555,21 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) delta2 = abs(thingtop - texmid); if (delta1 > delta2) { // Below - if (opentop > texbottom) + if (opentop > texbottom) { opentop = texbottom; + if (linedef->flags & ML_NOSKEW) + opentopslope = NULL; // Object is not actually on a slope + else + opentopslope = linedef->midtexslope; + } } else { // Above - if (openbottom < textop) + if (openbottom < textop) { openbottom = textop; + if (linedef->flags & ML_NOSKEW) + openbottomslope = NULL; // Object is not actually on a slope + else + openbottomslope = linedef->midtexslope; + } } } } @@ -1026,20 +1052,20 @@ boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean (*func)(line_t *)) // boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean (*func)(mobj_t *)) { - mobj_t *mobj; - blocknode_t *block; + blocknode_t *block, *next = NULL; if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) return true; // Check interaction with the objects in the blockmap. - for (block = blocklinks[y*bmapwidth + x]; block; block = block->mnext) + for (block = blocklinks[y*bmapwidth + x]; block != NULL; block = next) { - mobj = block->mobj; + next = block->mnext; // We want to note our reference to mnext here! - if (!func(mobj)) + if (!func(block->mobj)) return false; - if (P_MobjWasRemoved(tmthing)) // func just broke blockmap chain, cannot continue. + + if (P_MobjWasRemoved(tmthing)) // func just popped our tmthing, cannot continue. return true; } @@ -1095,8 +1121,6 @@ bthingit_t *P_NewBlockThingsIterator(int x1, int y1, int x2, int y2) return NULL; block = GetBlockmapBlock(x1, y1); - if (!block) - return NULL; if (freeiters != NULL) { @@ -1188,12 +1212,12 @@ mobj_t *P_BlockThingsIteratorNext(bthingit_t *it, boolean centeronly) if (!it->dynhash) { it->dynhashcapacity = 50; - Z_Calloc(it->dynhashcapacity * sizeof(it->dynhashcapacity), PU_LEVEL, &it->dynhash); + Z_Calloc(it->dynhashcapacity * sizeof(*it->dynhash), PU_LEVEL, &it->dynhash); } if (it->dynhashcount == it->dynhashcapacity) { it->dynhashcapacity *= 2; - it->dynhash = Z_Realloc(it->dynhash, it->dynhashcapacity * sizeof(it->dynhashcapacity), PU_LEVEL, &it->dynhash); + it->dynhash = Z_Realloc(it->dynhash, it->dynhashcapacity * sizeof(*it->dynhash), PU_LEVEL, &it->dynhash); } i = (int)it->dynhashcount; it->dynhashcount++; diff --git a/src/p_maputl.h b/src/p_maputl.h index e894c08a2461caf82397c569549e5bd3213ae3b7..67f7fd086a3c4ec11109ead24048ad118256c2d1 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_mobj.c b/src/p_mobj.c index 6035a19ab290c0e454ce415451985b3c26d4ed7a..ec107ff711dbe8792b3e0f35cc8642893491fa23 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -85,16 +85,26 @@ void P_AddCachedAction(mobj_t *mobj, INT32 statenum) // static void P_SetupStateAnimation(mobj_t *mobj, state_t *st) { - INT32 animlength = (mobj->sprite == SPR_PLAY && mobj->skin) - ? (INT32)(((skin_t *)mobj->skin)->sprites[mobj->sprite2].numframes) - 1 - : st->var1; + INT32 animlength; + + if (mobj->sprite == SPR_PLAY && mobj->skin) + { + spritedef_t *spritedef = P_GetSkinSpritedef(mobj->skin, mobj->sprite2); + animlength = (INT32)(spritedef->numframes) - 1; + } + else + animlength = st->var1; if (!(st->frame & FF_ANIMATE)) + { + mobj->anim_duration = 0; return; + } if (animlength <= 0 || st->var2 == 0) { mobj->frame &= ~FF_ANIMATE; + mobj->anim_duration = 0; return; // Crash/stupidity prevention } @@ -138,35 +148,19 @@ FUNCINLINE static ATTRINLINE void P_CycleStateAnimation(mobj_t *mobj) } // sprite2 version of above - if (mobj->skin && (((++mobj->frame) & FF_FRAMEMASK) >= (UINT32)(((skin_t *)mobj->skin)->sprites[mobj->sprite2].numframes))) - mobj->frame &= ~FF_FRAMEMASK; -} - -// -// P_CycleMobjState -// -static void P_CycleMobjState(mobj_t *mobj) -{ - // state animations - P_CycleStateAnimation(mobj); - - // cycle through states, - // calling action functions at transitions - if (mobj->tics != -1) + if (mobj->skin) { - mobj->tics--; - - // you can cycle through multiple states in a tic - if (!mobj->tics && mobj->state) - if (!P_SetMobjState(mobj, mobj->state->nextstate)) - return; // freed itself + spritedef_t *spritedef = P_GetSkinSpritedef(mobj->skin, mobj->sprite2); + UINT32 anim_length = (UINT32)(spritedef->numframes); + if (((++mobj->frame) & FF_FRAMEMASK) >= anim_length) + mobj->frame &= ~FF_FRAMEMASK; } } // -// P_CycleMobjState for players. +// P_CycleMobjState // -static void P_CyclePlayerMobjState(mobj_t *mobj) +static void P_CycleMobjState(mobj_t *mobj) { // state animations P_CycleStateAnimation(mobj); @@ -329,8 +323,10 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) mobj->state = st; mobj->tics = st->tics; - // Adjust the player's animation speed to match their velocity. - if (player->panim == PA_EDGE && (player->charflags & SF_FASTEDGE)) + // Adjust the player's animation speed + if (mobj->state-states == S_PLAY_WAIT && (player->charflags & SF_FASTWAIT)) + mobj->tics = 5; + else if (player->panim == PA_EDGE && (player->charflags & SF_FASTEDGE)) mobj->tics = 2; else if (!(disableSpeedAdjust || player->charflags & SF_NOSPEEDADJUST)) { @@ -395,31 +391,23 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) { skin_t *skin = ((skin_t *)mobj->skin); UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1; - UINT8 numframes, spr2; + UINT8 numframes; + UINT16 spr2; if (skin) { - UINT16 stateframe = st->frame; + spr2 = P_GetStateSprite2(st); - // Add/Remove FF_SPR2SUPER based on certain conditions - if (player->charflags & SF_NOSUPERSPRITES) - stateframe = stateframe & ~FF_SPR2SUPER; - else if (player->powers[pw_super]) - stateframe = stateframe | FF_SPR2SUPER; + // Add or remove SPR2F_SUPER based on certain conditions + spr2 = P_ApplySuperFlagToSprite2(spr2, mobj); - if (stateframe & FF_SPR2SUPER) - { - if (mobj->eflags & MFE_FORCENOSUPER) - stateframe = stateframe & ~FF_SPR2SUPER; - } - else if (mobj->eflags & MFE_FORCESUPER) - stateframe = stateframe | FF_SPR2SUPER; + // Get the needed sprite2 and frame number + spr2 = P_GetSkinSprite2(skin, spr2, mobj->player); - // Get the sprite2 and frame number - spr2 = P_GetSkinSprite2(skin, (stateframe & FF_FRAMEMASK), mobj->player); - numframes = skin->sprites[spr2].numframes; + spritedef_t *sprdef = P_GetSkinSpritedef(skin, spr2); + numframes = sprdef->numframes; - if (state == S_PLAY_STND && (spr2 & FF_SPR2SUPER) && skin->sprites[SPR2_WAIT|FF_SPR2SUPER].numframes == 0) + if (state == S_PLAY_STND && (spr2 & SPR2F_SUPER) && sprdef[SPR2_WAIT].numframes == 0) mobj->tics = -1; // If no super wait, don't wait at all } else @@ -432,12 +420,19 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) if (mobj->sprite != SPR_PLAY) { mobj->sprite = SPR_PLAY; - frame = 0; + frame = P_GetSprite2StateFrame(st); } else if (mobj->sprite2 != spr2) { - if ((st->frame & FF_SPR2MIDSTART) && numframes && P_RandomChance(FRACUNIT/2)) - frame = numframes/2; + if (st->frame & FF_SPR2MIDSTART) + { + if (numframes && P_RandomChance(FRACUNIT/2)) + frame = numframes/2; + else + frame = 0; + } + else if (numframes) + frame = P_GetSprite2StateFrame(st) % numframes; else frame = 0; } @@ -452,6 +447,7 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) { if (mobj->frame & FF_FRAMEMASK) mobj->frame--; + return P_SetPlayerMobjState(mobj, st->var1); } } @@ -539,26 +535,23 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state) { skin_t *skin = ((skin_t *)mobj->skin); UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1; - UINT8 numframes, spr2; + UINT8 numframes; + UINT16 spr2; if (skin) { - UINT16 stateframe = st->frame; + spr2 = P_GetStateSprite2(st); - // Add/Remove FF_SPR2SUPER based on certain conditions - if (stateframe & FF_SPR2SUPER) - { - if (mobj->eflags & MFE_FORCENOSUPER) - stateframe = stateframe & ~FF_SPR2SUPER; - } - else if (mobj->eflags & MFE_FORCESUPER) - stateframe = stateframe | FF_SPR2SUPER; + // Add or remove SPR2F_SUPER based on certain conditions + spr2 = P_ApplySuperFlagToSprite2(spr2, mobj); - // Get the sprite2 and frame number - spr2 = P_GetSkinSprite2(skin, (stateframe & FF_FRAMEMASK), NULL); - numframes = skin->sprites[spr2].numframes; + // Get the needed sprite2 and frame number + spr2 = P_GetSkinSprite2(skin, spr2, NULL); - if (state == S_PLAY_STND && (spr2 & FF_SPR2SUPER) && skin->sprites[SPR2_WAIT|FF_SPR2SUPER].numframes == 0) + spritedef_t *sprdef = P_GetSkinSpritedef(skin, spr2); + numframes = sprdef->numframes; + + if (state == S_PLAY_STND && (spr2 & SPR2F_SUPER) && sprdef[SPR2_WAIT].numframes == 0) mobj->tics = -1; // If no super wait, don't wait at all } else @@ -571,12 +564,19 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state) if (mobj->sprite != SPR_PLAY) { mobj->sprite = SPR_PLAY; - frame = 0; + frame = P_GetSprite2StateFrame(st); } else if (mobj->sprite2 != spr2) { - if ((st->frame & FF_SPR2MIDSTART) && numframes && P_RandomChance(FRACUNIT/2)) - frame = numframes/2; + if (st->frame & FF_SPR2MIDSTART) + { + if (numframes && P_RandomChance(FRACUNIT/2)) + frame = numframes/2; + else + frame = 0; + } + else if (numframes) + frame = P_GetSprite2StateFrame(st) % numframes; else frame = 0; } @@ -591,6 +591,7 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state) { if (mobj->frame & FF_FRAMEMASK) mobj->frame--; + return P_SetMobjState(mobj, st->var1); } } @@ -749,7 +750,7 @@ void P_EmeraldManager(void) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (think->removing) continue; mo = (mobj_t *)think; @@ -917,7 +918,7 @@ void P_ExplodeMissile(mobj_t *mo) explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); if (!P_MobjWasRemoved(explodemo)) { - P_SetScale(explodemo, mo->scale); + P_SetScale(explodemo, mo->scale, true); explodemo->destscale = mo->destscale; explodemo->momx += (P_RandomByte() % 32) * FixedMul(FRACUNIT/8, explodemo->scale); explodemo->momy += (P_RandomByte() % 32) * FixedMul(FRACUNIT/8, explodemo->scale); @@ -926,7 +927,7 @@ void P_ExplodeMissile(mobj_t *mo) explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); if (!P_MobjWasRemoved(explodemo)) { - P_SetScale(explodemo, mo->scale); + P_SetScale(explodemo, mo->scale, true); explodemo->destscale = mo->destscale; explodemo->momx += (P_RandomByte() % 64) * FixedMul(FRACUNIT/8, explodemo->scale); explodemo->momy -= (P_RandomByte() % 64) * FixedMul(FRACUNIT/8, explodemo->scale); @@ -935,7 +936,7 @@ void P_ExplodeMissile(mobj_t *mo) explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); if (!P_MobjWasRemoved(explodemo)) { - P_SetScale(explodemo, mo->scale); + P_SetScale(explodemo, mo->scale, true); explodemo->destscale = mo->destscale; explodemo->momx -= (P_RandomByte() % 128) * FixedMul(FRACUNIT/8, explodemo->scale); explodemo->momy += (P_RandomByte() % 128) * FixedMul(FRACUNIT/8, explodemo->scale); @@ -944,7 +945,7 @@ void P_ExplodeMissile(mobj_t *mo) explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); if (!P_MobjWasRemoved(explodemo)) { - P_SetScale(explodemo, mo->scale); + P_SetScale(explodemo, mo->scale, true); explodemo->destscale = mo->destscale; explodemo->momx -= (P_RandomByte() % 96) * FixedMul(FRACUNIT/8, explodemo->scale); explodemo->momy -= (P_RandomByte() % 96) * FixedMul(FRACUNIT/8, explodemo->scale); @@ -1092,9 +1093,8 @@ static fixed_t HighestOnLine(fixed_t radius, fixed_t x, fixed_t y, line_t *line, ); } -fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect) +fixed_t P_MobjFloorZ(sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, fixed_t radius, line_t *line, boolean lowest, boolean perfect) { - I_Assert(mobj != NULL); I_Assert(sector != NULL); if (sector->f_slope) { @@ -1103,14 +1103,14 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t // Get the corner of the object that should be the highest on the slope if (slope->d.x < 0) - testx = mobj->radius; + testx = radius; else - testx = -mobj->radius; + testx = -radius; if (slope->d.y < 0) - testy = mobj->radius; + testy = radius; else - testy = -mobj->radius; + testy = -radius; if ((slope->zdelta > 0) ^ !!(lowest)) { testx = -testx; @@ -1125,7 +1125,7 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t return P_GetSlopeZAt(slope, testx, testy); // If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point - if (perfect) { + if (perfect && boundsec) { size_t i; line_t *ld; fixed_t bbox[4]; @@ -1136,10 +1136,10 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t else finalheight = INT32_MIN; - bbox[BOXLEFT] = x-mobj->radius; - bbox[BOXRIGHT] = x+mobj->radius; - bbox[BOXTOP] = y+mobj->radius; - bbox[BOXBOTTOM] = y-mobj->radius; + bbox[BOXLEFT] = x-radius; + bbox[BOXRIGHT] = x+radius; + bbox[BOXTOP] = y+radius; + bbox[BOXBOTTOM] = y-radius; for (i = 0; i < boundsec->linecount; i++) { ld = boundsec->lines[i]; @@ -1151,9 +1151,9 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t continue; if (lowest) - finalheight = min(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, true)); + finalheight = min(finalheight, HighestOnLine(radius, x, y, ld, slope, true)); else - finalheight = max(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, false)); + finalheight = max(finalheight, HighestOnLine(radius, x, y, ld, slope, false)); } return finalheight; @@ -1164,14 +1164,13 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t if (line == NULL) return P_GetSlopeZAt(slope, x, y); - return HighestOnLine(mobj->radius, x, y, line, slope, lowest); + return HighestOnLine(radius, x, y, line, slope, lowest); } else // Well, that makes it easy. Just get the floor height return sector->floorheight; } -fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect) +fixed_t P_MobjCeilingZ(sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, fixed_t radius, line_t *line, boolean lowest, boolean perfect) { - I_Assert(mobj != NULL); I_Assert(sector != NULL); if (sector->c_slope) { @@ -1180,14 +1179,14 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed // Get the corner of the object that should be the highest on the slope if (slope->d.x < 0) - testx = mobj->radius; + testx = radius; else - testx = -mobj->radius; + testx = -radius; if (slope->d.y < 0) - testy = mobj->radius; + testy = radius; else - testy = -mobj->radius; + testy = -radius; if ((slope->zdelta > 0) ^ !!(lowest)) { testx = -testx; @@ -1202,7 +1201,7 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed return P_GetSlopeZAt(slope, testx, testy); // If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point - if (perfect) { + if (perfect && boundsec) { size_t i; line_t *ld; fixed_t bbox[4]; @@ -1213,10 +1212,10 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed else finalheight = INT32_MIN; - bbox[BOXLEFT] = x-mobj->radius; - bbox[BOXRIGHT] = x+mobj->radius; - bbox[BOXTOP] = y+mobj->radius; - bbox[BOXBOTTOM] = y-mobj->radius; + bbox[BOXLEFT] = x-radius; + bbox[BOXRIGHT] = x+radius; + bbox[BOXTOP] = y+radius; + bbox[BOXBOTTOM] = y-radius; for (i = 0; i < boundsec->linecount; i++) { ld = boundsec->lines[i]; @@ -1228,9 +1227,9 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed continue; if (lowest) - finalheight = min(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, true)); + finalheight = min(finalheight, HighestOnLine(radius, x, y, ld, slope, true)); else - finalheight = max(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, false)); + finalheight = max(finalheight, HighestOnLine(radius, x, y, ld, slope, false)); } return finalheight; @@ -1241,165 +1240,11 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed if (line == NULL) return P_GetSlopeZAt(slope, x, y); - return HighestOnLine(mobj->radius, x, y, line, slope, lowest); + return HighestOnLine(radius, x, y, line, slope, lowest); } else // Well, that makes it easy. Just get the ceiling height return sector->ceilingheight; } -// Now do the same as all above, but for cameras because apparently cameras are special? -fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect) -{ - I_Assert(mobj != NULL); - I_Assert(sector != NULL); - - if (sector->f_slope) { - fixed_t testx, testy; - pslope_t *slope = sector->f_slope; - - // Get the corner of the object that should be the highest on the slope - if (slope->d.x < 0) - testx = mobj->radius; - else - testx = -mobj->radius; - - if (slope->d.y < 0) - testy = mobj->radius; - else - testy = -mobj->radius; - - if ((slope->zdelta > 0) ^ !!(lowest)) { - testx = -testx; - testy = -testy; - } - - testx += x; - testy += y; - - // If the highest point is in the sector, then we have it easy! Just get the Z at that point - if (R_IsPointInSector(boundsec ? boundsec : sector, testx, testy)) - return P_GetSlopeZAt(slope, testx, testy); - - // If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point - if (perfect) { - size_t i; - line_t *ld; - fixed_t bbox[4]; - fixed_t finalheight; - - if (lowest) - finalheight = INT32_MAX; - else - finalheight = INT32_MIN; - - bbox[BOXLEFT] = x-mobj->radius; - bbox[BOXRIGHT] = x+mobj->radius; - bbox[BOXTOP] = y+mobj->radius; - bbox[BOXBOTTOM] = y-mobj->radius; - for (i = 0; i < boundsec->linecount; i++) { - ld = boundsec->lines[i]; - - if (bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || bbox[BOXLEFT] >= ld->bbox[BOXRIGHT] - || bbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || bbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) - continue; - - if (P_BoxOnLineSide(bbox, ld) != -1) - continue; - - if (lowest) - finalheight = min(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, true)); - else - finalheight = max(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, false)); - } - - return finalheight; - } - - // If we're just testing for base sector location (no collision line), just go for the center's spot... - // It'll get fixed when we test for collision anyway, and the final result can't be lower than this - if (line == NULL) - return P_GetSlopeZAt(slope, x, y); - - return HighestOnLine(mobj->radius, x, y, line, slope, lowest); - } else // Well, that makes it easy. Just get the floor height - return sector->floorheight; -} - -fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect) -{ - I_Assert(mobj != NULL); - I_Assert(sector != NULL); - - if (sector->c_slope) { - fixed_t testx, testy; - pslope_t *slope = sector->c_slope; - - // Get the corner of the object that should be the highest on the slope - if (slope->d.x < 0) - testx = mobj->radius; - else - testx = -mobj->radius; - - if (slope->d.y < 0) - testy = mobj->radius; - else - testy = -mobj->radius; - - if ((slope->zdelta > 0) ^ !!(lowest)) { - testx = -testx; - testy = -testy; - } - - testx += x; - testy += y; - - // If the highest point is in the sector, then we have it easy! Just get the Z at that point - if (R_IsPointInSector(boundsec ? boundsec : sector, testx, testy)) - return P_GetSlopeZAt(slope, testx, testy); - - // If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point - if (perfect) { - size_t i; - line_t *ld; - fixed_t bbox[4]; - fixed_t finalheight; - - if (lowest) - finalheight = INT32_MAX; - else - finalheight = INT32_MIN; - - bbox[BOXLEFT] = x-mobj->radius; - bbox[BOXRIGHT] = x+mobj->radius; - bbox[BOXTOP] = y+mobj->radius; - bbox[BOXBOTTOM] = y-mobj->radius; - for (i = 0; i < boundsec->linecount; i++) { - ld = boundsec->lines[i]; - - if (bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || bbox[BOXLEFT] >= ld->bbox[BOXRIGHT] - || bbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || bbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) - continue; - - if (P_BoxOnLineSide(bbox, ld) != -1) - continue; - - if (lowest) - finalheight = min(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, true)); - else - finalheight = max(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, false)); - } - - return finalheight; - } - - // If we're just testing for base sector location (no collision line), just go for the center's spot... - // It'll get fixed when we test for collision anyway, and the final result can't be lower than this - if (line == NULL) - return P_GetSlopeZAt(slope, x, y); - - return HighestOnLine(mobj->radius, x, y, line, slope, lowest); - } else // Well, that makes it easy. Just get the ceiling height - return sector->ceilingheight; -} static void P_PlayerFlip(mobj_t *mo) { if (!mo->player) @@ -1525,6 +1370,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) case MT_WATERDROP: case MT_CYBRAKDEMON: gravityadd >>= 1; + break; default: break; } @@ -2118,7 +1964,7 @@ void P_RingXYMovement(mobj_t *mo) I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); - if (!P_SceneryTryMove(mo, mo->x + mo->momx, mo->y + mo->momy)) + if (!P_SceneryTryMove(mo, mo->x + mo->momx, mo->y + mo->momy) && !P_MobjWasRemoved(mo)) P_SlideMove(mo); } @@ -2132,8 +1978,10 @@ void P_SceneryXYMovement(mobj_t *mo) oldx = mo->x; oldy = mo->y; - if (!P_SceneryTryMove(mo, mo->x + mo->momx, mo->y + mo->momy)) + if (!P_SceneryTryMove(mo, mo->x + mo->momx, mo->y + mo->momy) && !P_MobjWasRemoved(mo)) P_SlideMove(mo); + if (P_MobjWasRemoved(mo)) + return; if ((!(mo->eflags & MFE_VERTICALFLIP) && mo->z > mo->floorz) || (mo->eflags & MFE_VERTICALFLIP && mo->z+mo->height < mo->ceilingz)) return; // no friction when airborne @@ -2329,12 +2177,15 @@ boolean P_CheckDeathPitCollide(mobj_t *mo) if (mo->player && mo->player->pflags & PF_GODMODE) return false; - if (((mo->z <= mo->subsector->sector->floorheight + fixed_t sectorFloor = P_GetSpecialBottomZ(mo, mo->subsector->sector, mo->subsector->sector); + fixed_t sectorCeiling = P_GetSpecialTopZ(mo, mo->subsector->sector, mo->subsector->sector); + + if (((mo->z <= sectorFloor && ((mo->subsector->sector->flags & MSF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & MSF_FLIPSPECIAL_FLOOR)) - || (mo->z + mo->height >= mo->subsector->sector->ceilingheight - && ((mo->subsector->sector->flags & MSF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & MSF_FLIPSPECIAL_CEILING))) - && (mo->subsector->sector->damagetype == SD_DEATHPITTILT - || mo->subsector->sector->damagetype == SD_DEATHPITNOTILT)) + || (mo->z + mo->height >= sectorCeiling + && ((mo->subsector->sector->flags & MSF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & MSF_FLIPSPECIAL_CEILING))) + && (mo->subsector->sector->damagetype == SD_DEATHPITTILT + || mo->subsector->sector->damagetype == SD_DEATHPITNOTILT)) return true; return false; @@ -2380,7 +2231,7 @@ boolean P_ZMovement(mobj_t *mo) else if (!onground) P_SlopeLaunch(mo); } - + if (!mo->player && P_CheckDeathPitCollide(mo) && mo->health && !(mo->flags & MF_NOCLIPHEIGHT) && !(mo->flags2 & MF2_BOSSDEAD)) { @@ -3073,7 +2924,7 @@ boolean P_SceneryZMovement(mobj_t *mo) mo->eflags &= ~MFE_APPLYPMOMZ; } mo->z += mo->momz; - + if (!mo->player && P_CheckDeathPitCollide(mo) && mo->health && !(mo->flags & MF_NOCLIPHEIGHT) && !(mo->flags2 & MF2_BOSSDEAD)) { @@ -3108,8 +2959,7 @@ boolean P_SceneryZMovement(mobj_t *mo) continue; explodemo->momx += ((prandom & 0x0F) << (FRACBITS-2)) * (i & 2 ? -1 : 1); explodemo->momy += ((prandom & 0xF0) << (FRACBITS-6)) * (i & 1 ? -1 : 1); - explodemo->destscale = mo->scale; - P_SetScale(explodemo, mo->scale); + P_SetScale(explodemo, mo->scale, true); } if (mo->threshold != 42) // Don't make pop sound if threshold is 42. @@ -3135,7 +2985,7 @@ boolean P_SceneryZMovement(mobj_t *mo) mobj_t *flower = P_SpawnMobjFromMobj(mo, 0, 0, 0, flowertype); if (flower) { - P_SetScale(flower, mo->scale/16); + P_SetScale(flower, mo->scale/16, true); flower->destscale = mo->scale; flower->scalespeed = mo->scale/8; } @@ -3375,10 +3225,7 @@ void P_MobjCheckWater(mobj_t *mobj) else splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, splishtype); if (!P_MobjWasRemoved(splish)) - { - splish->destscale = mobj->scale; - P_SetScale(splish, mobj->scale); - } + P_SetScale(splish, mobj->scale, true); } // skipping stone! @@ -3417,10 +3264,7 @@ void P_MobjCheckWater(mobj_t *mobj) else splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, splishtype); if (!P_MobjWasRemoved(splish)) - { - splish->destscale = mobj->scale; - P_SetScale(splish, mobj->scale); - } + P_SetScale(splish, mobj->scale, true); } } @@ -3471,8 +3315,7 @@ void P_MobjCheckWater(mobj_t *mobj) else bubble->momz = 0; - bubble->destscale = mobj->scale; - P_SetScale(bubble, mobj->scale); + P_SetScale(bubble, mobj->scale, true); } } } @@ -3597,7 +3440,7 @@ void P_DestroyRobots(void) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (think->removing) continue; mo = (mobj_t *)think; @@ -3914,6 +3757,8 @@ static void P_PlayerMobjThinker(mobj_t *mobj) } else P_TryMove(mobj, mobj->x, mobj->y, true); + if (P_MobjWasRemoved(mobj)) + return; P_CheckCrumblingPlatforms(mobj); @@ -3922,7 +3767,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj) // always do the gravity bit now, that's simpler // BUT CheckPosition only if wasn't done before. - if (!(mobj->eflags & MFE_ONGROUND) || mobj->momz + if (mobj->momz || ((mobj->eflags & MFE_VERTICALFLIP) && mobj->z + mobj->height != mobj->ceilingz) || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z != mobj->floorz) || P_IsObjectInGoop(mobj)) @@ -3935,22 +3780,11 @@ static void P_PlayerMobjThinker(mobj_t *mobj) } else { -#if 0 // i don't know why this is here, it's causing a few undesired state glitches, and disabling it doesn't appear to negatively affect the game, but i don't want it gone permanently just in case some obscure bug crops up - if (!(mobj->player->powers[pw_carry] == CR_NIGHTSMODE)) // used for drilling - mobj->player->pflags &= ~PF_STARTJUMP; - mobj->player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); - if (mobj->player->secondjump || mobj->player->powers[pw_tailsfly]) - { - mobj->player->secondjump = 0; - mobj->player->powers[pw_tailsfly] = 0; - P_SetMobjState(mobj, S_PLAY_WALK); - } -#endif mobj->eflags &= ~MFE_JUSTHITFLOOR; } animonly: - P_CyclePlayerMobjState(mobj); + P_CycleMobjState(mobj); } static void CalculatePrecipFloor(precipmobj_t *mobj) @@ -4405,7 +4239,7 @@ static void P_Boss3Thinker(mobj_t *mobj) // this can happen if the boss was hurt earlier than expected for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -4708,6 +4542,8 @@ static void P_Boss4PinchSpikeballs(mobj_t *mobj, angle_t angle, fixed_t dz) { seg->z = bz + (dz*(9-s)); P_TryMove(seg, workx + (dx*s), worky + (dy*s), true); + if (P_MobjWasRemoved(seg)) + return; } angle += ANGLE_MAX/3; } @@ -4945,6 +4781,8 @@ static void P_Boss4Thinker(mobj_t *mobj) (mobj->spawnpoint->x<<FRACBITS) - P_ReturnThrustX(mobj, mobj->angle, mobj->movefactor), (mobj->spawnpoint->y<<FRACBITS) - P_ReturnThrustY(mobj, mobj->angle, mobj->movefactor), true); + if (P_MobjWasRemoved(mobj)) + return; P_Boss4PinchSpikeballs(mobj, FixedAngle(mobj->movecount), mobj->z - mobj->watertop - mobjinfo[MT_EGGMOBILE4_MACE].height - mobj->height/2); @@ -5136,8 +4974,7 @@ static void P_Boss7Thinker(mobj_t *mobj) mobj_t *smoke = P_SpawnMobj(mobj->x, mobj->y, mobj->z + mobj->height, MT_SMOKE); if (!P_MobjWasRemoved(smoke)) { - smoke->destscale = mobj->destscale; - P_SetScale(smoke, smoke->destscale); + P_SetScale(smoke, mobj->destscale, true); smoke->momz = FixedMul(FRACUNIT, smoke->scale); } } @@ -5491,7 +5328,7 @@ static void P_Boss9Thinker(mobj_t *mobj) // Build a hoop linked list of 'em! for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -5514,6 +5351,8 @@ static void P_Boss9Thinker(mobj_t *mobj) { P_InstaThrust(mobj, mobj->angle, -4*FRACUNIT); P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true); + if (P_MobjWasRemoved(mobj)) + return; mobj->momz -= gravity; if (mobj->z < mobj->watertop || mobj->z < (mobj->floorz + 16*FRACUNIT)) { @@ -5586,7 +5425,7 @@ static void P_Boss9Thinker(mobj_t *mobj) if (mobj->hprev) { mobj->hprev->destscale = FRACUNIT + (2*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2); - P_SetScale(mobj->hprev, mobj->hprev->destscale); + P_SetScale(mobj->hprev, mobj->hprev->destscale, false); P_MoveOrigin(mobj->hprev, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->hprev->height/2); mobj->hprev->momx = mobj->momx; @@ -5612,8 +5451,8 @@ static void P_Boss9Thinker(mobj_t *mobj) { S_StopSound(missile); if (mobj->extravalue1 >= 2) - P_SetScale(missile, FRACUNIT>>1); - missile->destscale = missile->scale>>1; + P_SetScale(missile, FRACUNIT/2, true); + missile->destscale = missile->scale/2; missile->fuse = TICRATE/2; missile->scalespeed = abs(missile->destscale - missile->scale)/missile->fuse; missile->z -= missile->height/2; @@ -5636,7 +5475,7 @@ static void P_Boss9Thinker(mobj_t *mobj) spread->angle = missile->angle+(ANGLE_11hh/2)*(i-2); P_InstaThrust(spread,spread->angle,-spread->info->speed); spread->momz = missile->momz; - P_SetScale(spread, missile->scale); + P_SetScale(spread, missile->scale, true); spread->destscale = missile->destscale; spread->scalespeed = missile->scalespeed; spread->fuse = missile->fuse; @@ -5660,7 +5499,7 @@ static void P_Boss9Thinker(mobj_t *mobj) spread = P_SpawnMissile(mobj, mobj->target, missile->type); if (P_MobjWasRemoved(spread)) continue; - P_SetScale(spread, missile->scale); + P_SetScale(spread, missile->scale, true); spread->destscale = missile->destscale; spread->fuse = missile->fuse; spread->z -= spread->height/2; @@ -5717,12 +5556,12 @@ static void P_Boss9Thinker(mobj_t *mobj) { if (mobj->health > mobj->info->damage) { - P_SetScale(missile, FRACUNIT/3); + P_SetScale(missile, FRACUNIT/3, true); missile->color = SKINCOLOR_MAGENTA; // sonic OVA/4 purple power } else { - P_SetScale(missile, FRACUNIT/5); + P_SetScale(missile, FRACUNIT/5, true); missile->color = SKINCOLOR_SUNSET; // sonic cd electric power } missile->destscale = missile->scale*2; @@ -5785,10 +5624,7 @@ static void P_Boss9Thinker(mobj_t *mobj) if (!P_MobjWasRemoved(missile)) { if (mobj->extravalue1 >= 2) - { - missile->destscale = FRACUNIT>>1; - P_SetScale(missile, missile->destscale); - } + P_SetScale(missile, FRACUNIT/2, true); missile->fuse = 3*TICRATE; missile->z -= missile->height/2; @@ -5807,8 +5643,7 @@ static void P_Boss9Thinker(mobj_t *mobj) spread->angle = missile->angle+(ANGLE_11hh/2)*(i-2); P_InstaThrust(spread,spread->angle,spread->info->speed); spread->momz = missile->momz; - spread->destscale = FRACUNIT>>1; - P_SetScale(spread, spread->destscale); + P_SetScale(spread, FRACUNIT/2, true); spread->fuse = missile->fuse; } P_InstaThrust(missile,missile->angle,missile->info->speed); @@ -5825,8 +5660,7 @@ static void P_Boss9Thinker(mobj_t *mobj) spread = P_SpawnMissile(mobj, mobj->target, missile->type); if (!P_MobjWasRemoved(spread)) { - spread->destscale = FRACUNIT>>1; - P_SetScale(spread, spread->destscale); + P_SetScale(spread, FRACUNIT/2, true); spread->fuse = missile->fuse; spread->z -= spread->height/2; } @@ -5862,6 +5696,8 @@ static void P_Boss9Thinker(mobj_t *mobj) P_InstaThrust(mobj, mobj->angle, 30*FRACUNIT); if (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true)) { // Hit a wall? Find a direction to bounce + if (P_MobjWasRemoved(mobj)) + return; mobj->threshold--; if (!mobj->threshold) { // failed bounce! S_StartSound(mobj, sfx_mspogo); @@ -5902,6 +5738,8 @@ static void P_Boss9Thinker(mobj_t *mobj) P_InstaThrust(mobj, mobj->angle, -speed); while (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true) && tries++ < 16) { + if (P_MobjWasRemoved(mobj)) + return; S_StartSound(mobj, sfx_mspogo); P_BounceMove(mobj); mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0); @@ -6086,8 +5924,12 @@ static void P_Boss9Thinker(mobj_t *mobj) whoosh->flags |= MF_NOCLIPHEIGHT; #endif - P_SetMobjState(mobj->tracer, S_JETFUMEFLASH); - P_SetScale(mobj->tracer, mobj->scale << 1); + if (!P_MobjWasRemoved(mobj->tracer)) + { + P_SetMobjState(mobj->tracer, S_JETFUMEFLASH); + P_SetScale(mobj->tracer, 2*mobj->scale, false); + mobj->tracer->old_scale = mobj->tracer->scale; + } } else { @@ -6188,7 +6030,7 @@ mobj_t *P_GetClosestAxis(mobj_t *source) // scan the thinkers to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -6422,28 +6264,24 @@ void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 numb // // Sets the sprite scaling // -void P_SetScale(mobj_t *mobj, fixed_t newscale) +void P_SetScale(mobj_t *mobj, fixed_t newscale, boolean instant) { - player_t *player; - fixed_t oldscale; - if (!mobj) return; - oldscale = mobj->scale; //keep for adjusting stuff below - - mobj->scale = newscale; - - mobj->radius = FixedMul(FixedDiv(mobj->radius, oldscale), newscale); - mobj->height = FixedMul(FixedDiv(mobj->height, oldscale), newscale); - - player = mobj->player; - - if (player) + if (mobj->player) { G_GhostAddScale(newscale); - player->viewheight = FixedMul(FixedDiv(player->viewheight, oldscale), newscale); // Nonono don't calculate viewheight elsewhere, this is the best place for it! + // Nonono don't calculate viewheight elsewhere, this is the best place for it! + mobj->player->viewheight = FixedMul(FixedDiv(mobj->player->viewheight, mobj->scale), newscale); } + + mobj->radius = FixedMul(FixedDiv(mobj->radius, mobj->scale), newscale); + mobj->height = FixedMul(FixedDiv(mobj->height, mobj->scale), newscale); + + mobj->scale = newscale; + if (instant) + mobj->destscale = mobj->old_scale = newscale; } void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on your target @@ -6798,9 +6636,21 @@ static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield) thing->flags |= MF_NOCLIPHEIGHT; thing->eflags = (thing->eflags & ~MFE_VERTICALFLIP)|(thing->target->eflags & MFE_VERTICALFLIP); - P_SetScale(thing, FixedMul(thing->target->scale, thing->target->player->shieldscale)); - thing->destscale = thing->scale; - thing->old_scale = FixedMul(thing->target->old_scale, thing->target->player->shieldscale); + //Set the shield's scale based on shieldscale, hide it if we're too small! + fixed_t scale = FixedMul(thing->target->scale, thing->target->player->shieldscale); + if (scale < 1) { + P_SetScale(thing, thing->target->scale, true); + thing->old_scale = thing->target->old_scale; + + thing->flags2 |= (MF2_DONTDRAW|MF2_JUSTATTACKED); //Hide and indicate we're hidden + } else { + P_SetScale(thing, scale, true); + thing->old_scale = FixedMul(thing->target->old_scale, thing->target->player->shieldscale); + + //Only unhide if we were hidden by the above code + if (thing->flags2 & MF2_JUSTATTACKED) + thing->flags2 &= ~(MF2_DONTDRAW|MF2_JUSTATTACKED); + } #define NewMH(mobj) mobj->height // Ugly mobj-height and player-height defines, for the sake of prettier code #define NewPH(player) P_GetPlayerHeight(player) @@ -6925,6 +6775,12 @@ void P_RunOverlays(void) else zoffs = 0; + // hide the overlay as well if we're part of a hidden shield + if ((mo->target->flags2 & (MF2_JUSTATTACKED|MF2_DONTDRAW)) == (MF2_JUSTATTACKED|MF2_DONTDRAW)) + mo->flags2 |= (MF2_DONTDRAW|MF2_JUSTATTACKED); + else if (mo->flags2 & MF2_JUSTATTACKED) + mo->flags2 &= ~(MF2_DONTDRAW|MF2_JUSTATTACKED); + P_UnsetThingPosition(mo); mo->x = mo->target->x; mo->y = mo->target->y; @@ -7147,11 +7003,11 @@ static void P_MobjScaleThink(mobj_t *mobj) correctionType = 2; // Correct Z position by moving down if (abs(mobj->scale - mobj->destscale) < mobj->scalespeed) - P_SetScale(mobj, mobj->destscale); + P_SetScale(mobj, mobj->destscale, false); else if (mobj->scale < mobj->destscale) - P_SetScale(mobj, mobj->scale + mobj->scalespeed); + P_SetScale(mobj, mobj->scale + mobj->scalespeed, false); else if (mobj->scale > mobj->destscale) - P_SetScale(mobj, mobj->scale - mobj->scalespeed); + P_SetScale(mobj, mobj->scale - mobj->scalespeed, false); if (correctionType == 1) mobj->z -= (mobj->height - oldheight)/2; @@ -7244,8 +7100,9 @@ static boolean P_DrownNumbersSceneryThink(mobj_t *mobj) mobj->x = mobj->target->x; mobj->y = mobj->target->y; + P_SetScale(mobj, mobj->target->scale, false); mobj->destscale = mobj->target->destscale; - P_SetScale(mobj, mobj->target->scale); + mobj->old_scale = mobj->target->old_scale; if (mobj->target->eflags & MFE_VERTICALFLIP) { @@ -7406,10 +7263,10 @@ static boolean P_ParticleGenSceneryThink(mobj_t *mobj) (mobjtype_t)mobj->threshold); if (!P_MobjWasRemoved(spawn)) { - P_SetScale(spawn, mobj->scale); - spawn->momz = FixedMul(mobj->movefactor, spawn->scale); + P_SetScale(spawn, mobj->scale, true); spawn->destscale = spawn->scale/100; spawn->scalespeed = spawn->scale/mobj->health; + spawn->momz = FixedMul(mobj->movefactor, spawn->scale); spawn->tics = (tic_t)mobj->health; spawn->flags2 |= (mobj->flags2 & MF2_OBJECTFLIP); spawn->angle += P_RandomKey(36)*ANG10; // irrelevant for default objects but might make sense for some custom ones @@ -7452,7 +7309,7 @@ static void P_RosySceneryThink(mobj_t *mobj) player = &players[i]; } - if (stat == S_ROSY_JUMP || stat == S_ROSY_PAIN) + if (stat == S_ROSY_JUMP || stat == S_ROSY_FALL || stat == S_ROSY_PAIN) { if (P_IsObjectOnGround(mobj)) { @@ -7463,16 +7320,16 @@ static void P_RosySceneryThink(mobj_t *mobj) stat = S_ROSY_WALK; P_SetMobjState(mobj, stat); } - else if (P_MobjFlip(mobj)*mobj->momz < 0) - mobj->frame = mobj->state->frame + mobj->state->var1; + else if (P_MobjFlip(mobj)*mobj->momz < 0 && stat == S_ROSY_JUMP) + P_SetMobjState(mobj, S_ROSY_FALL); } if (!player) { - if ((stat < S_ROSY_IDLE1 || stat > S_ROSY_IDLE4) && stat != S_ROSY_JUMP) + if (stat != S_ROSY_IDLE && stat != S_ROSY_JUMP && stat != S_ROSY_FALL) { mobj->momx = mobj->momy = 0; - P_SetMobjState(mobj, S_ROSY_IDLE1); + P_SetMobjState(mobj, S_ROSY_IDLE); } } else @@ -7486,13 +7343,11 @@ static void P_RosySceneryThink(mobj_t *mobj) switch (stat) { - case S_ROSY_IDLE1: - case S_ROSY_IDLE2: - case S_ROSY_IDLE3: - case S_ROSY_IDLE4: + case S_ROSY_IDLE: dojump = true; break; case S_ROSY_JUMP: + case S_ROSY_FALL: case S_ROSY_PAIN: // handled above break; @@ -7501,6 +7356,8 @@ static void P_RosySceneryThink(mobj_t *mobj) fixed_t x = mobj->x, y = mobj->y, z = mobj->z; angle_t angletoplayer = R_PointToAngle2(x, y, mobj->target->x, mobj->target->y); boolean allowed = P_TryMove(mobj, mobj->target->x, mobj->target->y, false); + if (P_MobjWasRemoved(mobj)) + return; P_UnsetThingPosition(mobj); mobj->x = x; @@ -7516,8 +7373,7 @@ static void P_RosySceneryThink(mobj_t *mobj) max = pdist; if ((--mobj->extravalue1) <= 0) { - if (++mobj->frame > mobj->state->frame + mobj->state->var1) - mobj->frame = mobj->state->frame; + P_SetMobjState(mobj, S_ROSY_WALK); if (mom > 12*mobj->scale) mobj->extravalue1 = 2; else if (mom > 6*mobj->scale) @@ -7627,8 +7483,7 @@ static void P_RosySceneryThink(mobj_t *mobj) mobj_t *cdlhrt = P_SpawnMobjFromMobj(mobj, 0, 0, mobj->height, MT_CDLHRT); if (!P_MobjWasRemoved(cdlhrt)) { - cdlhrt->destscale = (5*mobj->scale) >> 4; - P_SetScale(cdlhrt, cdlhrt->destscale); + P_SetScale(cdlhrt, (5*mobj->scale) >> 4, true); cdlhrt->fuse = (5*TICRATE) >> 1; cdlhrt->momz = mobj->scale; P_SetTarget(&cdlhrt->target, mobj); @@ -7882,8 +7737,9 @@ static void P_MobjSceneryThink(mobj_t *mobj) mobj->eflags |= (mobj->target->eflags & MFE_VERTICALFLIP); + P_SetScale(mobj, mobj->target->scale, false); mobj->destscale = mobj->target->destscale; - P_SetScale(mobj, mobj->target->scale); + mobj->old_scale = mobj->target->old_scale; if (!(mobj->eflags & MFE_VERTICALFLIP)) mobj->z = mobj->target->z + mobj->target->height + FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->target->scale); @@ -8033,7 +7889,9 @@ static void P_MobjSceneryThink(mobj_t *mobj) } P_SetThingPosition(mobj); - P_SetScale(mobj, mobj->target->scale); + P_SetScale(mobj, mobj->target->scale, false); + mobj->destscale = mobj->target->destscale; + mobj->old_scale = mobj->target->old_scale; } break; case MT_TUTORIALFLOWER: @@ -8064,7 +7922,8 @@ static void P_MobjSceneryThink(mobj_t *mobj) break; } - P_SceneryThinker(mobj); + if (!P_MobjWasRemoved(mobj)) + P_SceneryThinker(mobj); } static boolean P_MobjPushableThink(mobj_t *mobj) @@ -8190,6 +8049,10 @@ static boolean P_MobjBossThink(mobj_t *mobj) case MT_METALSONIC_BATTLE: P_Boss9Thinker(mobj); break; + case MT_OLDK: + if (mobj->health <= 0) + mobj->momz -= (2*FRACUNIT)/3; + break; default: // Generic SOC-made boss if (mobj->flags2 & MF2_SKULLFLY) P_SpawnGhostMobj(mobj); @@ -8474,8 +8337,8 @@ static void P_ArrowThink(mobj_t *mobj) if (!P_MobjWasRemoved(dust)) { dust->tics = 18; - dust->scalespeed = 4096; dust->destscale = FRACUNIT/32; + dust->scalespeed = FRACUNIT/16; } } } @@ -9466,10 +9329,10 @@ static void P_PointPushThink(mobj_t *mobj) radius = mobj->spawnpoint->args[0] << FRACBITS; pushmobj = mobj; - xl = (unsigned)(mobj->x - radius - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; - xh = (unsigned)(mobj->x + radius - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; - yl = (unsigned)(mobj->y - radius - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; - yh = (unsigned)(mobj->y + radius - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; + xl = (unsigned)(mobj->x - radius - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(mobj->x + radius - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(mobj->y - radius - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(mobj->y + radius - bmaporgy)>>MAPBLOCKSHIFT; P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_PushThing); } @@ -9886,9 +9749,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj) traindust->frame = P_RandomRange(0, 8)|FF_TRANS90; traindust->angle = mobj->angle; traindust->tics = TICRATE*4; + P_SetScale(traindust, FRACUNIT*6, true); traindust->destscale = FRACUNIT*64; traindust->scalespeed = FRACUNIT/24; - P_SetScale(traindust, FRACUNIT*6); } break; case MT_TRAINSTEAMSPAWNER: @@ -9899,9 +9762,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj) P_SetMobjState(steam, S_TRAINSTEAM); steam->frame = P_RandomRange(0, 1)|FF_TRANS90; steam->tics = TICRATE*8; + P_SetScale(steam, FRACUNIT*16, true); steam->destscale = FRACUNIT*64; steam->scalespeed = FRACUNIT/8; - P_SetScale(steam, FRACUNIT*16); steam->momx = P_SignedRandom()*32; steam->momy = -64*FRACUNIT; steam->momz = 2*FRACUNIT; @@ -10063,9 +9926,10 @@ static void P_MonitorFuseThink(mobj_t *mobj) { mobj_t *newmobj; - // Special case for ALL monitors. + // Special case for ALL monitors outside of co-op. // If a box's speed is nonzero, it's allowed to respawn as a WRM/SRM. - if (mobj->info->speed != 0 && (mobj->flags2 & (MF2_AMBUSH|MF2_STRONGBOX))) + if (!G_CoopGametype() && mobj->info->speed != 0 + && (mobj->flags2 & (MF2_AMBUSH|MF2_STRONGBOX))) { mobjtype_t spawnchance[64]; INT32 numchoices = 0, i = 0; @@ -10293,6 +10157,8 @@ void P_MobjThinker(mobj_t *mobj) P_SetTarget(&mobj->hnext, NULL); if (mobj->hprev && P_MobjWasRemoved(mobj->hprev)) P_SetTarget(&mobj->hprev, NULL); + if (mobj->dontdrawforviewmobj && P_MobjWasRemoved(mobj->dontdrawforviewmobj)) + P_SetTarget(&mobj->dontdrawforviewmobj, NULL); mobj->eflags &= ~(MFE_PUSHED|MFE_SPRUNG); @@ -10423,6 +10289,8 @@ void P_MobjThinker(mobj_t *mobj) || mobj->type == MT_CANNONBALLDECOR || mobj->type == MT_FALLINGROCK) { P_TryMove(mobj, mobj->x, mobj->y, true); // Sets mo->standingslope correctly + if (P_MobjWasRemoved(mobj)) + return; //if (mobj->standingslope) CONS_Printf("slope physics on mobj\n"); P_ButteredSlope(mobj); } @@ -10450,10 +10318,7 @@ void P_MobjThinker(mobj_t *mobj) } // Can end up here if a player dies. - if (mobj->player) - P_CyclePlayerMobjState(mobj); - else - P_CycleMobjState(mobj); + P_CycleMobjState(mobj); if (P_MobjWasRemoved(mobj)) return; @@ -10468,6 +10333,7 @@ void P_MobjThinker(mobj_t *mobj) case MT_GRENADEPICKUP: if (mobj->health == 0) // Fading tile { + // TODO: Maybe use mobj->alpha instead of messing with frame flags INT32 value = mobj->info->damage/10; value = mobj->fuse/value; value = 10-value; @@ -10524,6 +10390,8 @@ void P_PushableThinker(mobj_t *mobj) // it has to be pushable RIGHT NOW for this part to happen if (mobj->flags & MF_PUSHABLE && !(mobj->momx || mobj->momy)) P_TryMove(mobj, mobj->x, mobj->y, true); + if (P_MobjWasRemoved(mobj)) + return; if (mobj->type == MT_MINECART && mobj->health) { @@ -10740,6 +10608,19 @@ static fixed_t P_DefaultMobjShadowScale (mobj_t *thing) } } +static INT32 P_SetupNPC(mobj_t *mobj, const char *name) +{ + INT32 skinnum = R_SkinAvailable(name); + + if (skinnum != -1) + { + mobj->skin = skins[skinnum]; + mobj->color = skins[skinnum]->prefcolor; + } + + return skinnum; +} + // // P_SpawnMobj // @@ -10811,6 +10692,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) // Sprite rendering mobj->blendmode = AST_TRANSLUCENT; + mobj->alpha = FRACUNIT; mobj->spritexscale = mobj->spriteyscale = mobj->scale; mobj->spritexoffset = mobj->spriteyoffset = 0; mobj->floorspriteslope = NULL; @@ -10856,19 +10738,29 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) // Set shadowscale here, before spawn hook so that Lua can change it mobj->shadowscale = P_DefaultMobjShadowScale(mobj); - if (!(mobj->flags & MF_NOTHINK)) - P_AddThinker(THINK_MOBJ, &mobj->thinker); - + // A monitor can't respawn if we're not in multiplayer, + // or if we're in co-op and it's score or a 1up + if (mobj->flags & MF_MONITOR && (!(netgame || multiplayer) + || (G_CoopGametype() + && (mobj->type == MT_1UP_BOX + || mobj->type == MT_SCORE1K_BOX + || mobj->type == MT_SCORE10K_BOX) + ))) + mobj->flags2 |= MF2_DONTRESPAWN; if (type == MT_PLAYER) { // when spawning MT_PLAYER, set mobj->player before calling MobjSpawn hook to prevent P_RemoveMobj from succeeding on player mobj. va_start(args, type); mobj->player = va_arg(args, player_t *); - mobj->player->mo = mobj; + if (mobj->player) + mobj->player->mo = mobj; va_end(args); } + if (!(mobj->flags & MF_NOTHINK) || (titlemapinaction && mobj->type == MT_ALTVIEWMAN)) + P_AddThinker(THINK_MOBJ, &mobj->thinker); + // increment mobj reference, so we don't get a dangling reference in case MobjSpawn calls P_RemoveMobj mobj->thinker.references++; @@ -10891,7 +10783,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) if (titlemapinaction) mobj->flags &= ~MF_NOTHINK; break; case MT_LOCKONINF: - P_SetScale(mobj, (mobj->destscale = 3*mobj->scale)); + P_SetScale(mobj, 3*mobj->scale, true); break; case MT_CYBRAKDEMON_NAPALM_BOMB_LARGE: mobj->fuse = mobj->info->painchance; @@ -10902,8 +10794,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) if (P_MobjWasRemoved(spawn)) break; - spawn->destscale = mobj->scale; - P_SetScale(spawn, mobj->scale); + P_SetScale(spawn, mobj->scale, true); P_SetTarget(&spawn->target, mobj); } break; @@ -10920,8 +10811,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) if (P_MobjWasRemoved(spawn)) break; - spawn->destscale = mobj->scale; - P_SetScale(spawn, mobj->scale); + P_SetScale(spawn, mobj->scale, true); P_SetTarget(&mobj->tracer, spawn); P_SetTarget(&spawn->target, mobj); } @@ -10938,8 +10828,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) if (P_MobjWasRemoved(ball)) continue; - ball->destscale = mobj->scale; - P_SetScale(ball, mobj->scale); + P_SetScale(ball, mobj->scale, true); P_SetTarget(&ball->target, mobj); ball->movedir = FixedAngle(FixedMul(FixedDiv(i<<FRACBITS, mobj->info->damage<<FRACBITS), 360<<FRACBITS)); ball->threshold = ball->radius + mobj->radius + FixedMul(ball->info->painchance, ball->scale); @@ -10960,8 +10849,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) if (P_MobjWasRemoved(ball)) continue; - ball->destscale = mobj->scale; - P_SetScale(ball, mobj->scale); + P_SetScale(ball, mobj->scale, true); P_SetTarget(&lastball->tracer, ball); P_SetTarget(&ball->target, mobj); lastball = ball; @@ -11086,17 +10974,14 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) nummaprings++; break; case MT_METALSONIC_RACE: - mobj->skin = skins[5]; - /* FALLTHRU */ case MT_METALSONIC_BATTLE: - mobj->color = skins[5]->prefcolor; - sc = 5; + sc = P_SetupNPC(mobj, "metalsonic"); break; case MT_FANG: - sc = 4; + sc = P_SetupNPC(mobj, "fang"); break; case MT_ROSY: - sc = 3; + sc = P_SetupNPC(mobj, "amy"); break; case MT_CORK: mobj->flags2 |= MF2_SUPERFIRE; @@ -11126,13 +11011,6 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) mcsolid->angle = mobj->angle + ANGLE_90; } break; - case MT_TORCHFLOWER: - { - mobj_t *fire = P_SpawnMobjFromMobj(mobj, 0, 0, 46*FRACUNIT, MT_FLAME); - if (!P_MobjWasRemoved(fire)) - P_SetTarget(&mobj->target, fire); - break; - } case MT_PYREFLY: mobj->extravalue1 = (FixedHypot(mobj->x, mobj->y)/FRACUNIT) % 360; mobj->extravalue2 = 0; @@ -11173,7 +11051,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) if (mobj->skin) // correct inadequecies above. { - mobj->sprite2 = P_GetSkinSprite2(mobj->skin, (mobj->frame & FF_FRAMEMASK), NULL); + mobj->sprite2 = P_GetSkinSprite2(mobj->skin, P_GetStateSprite2(mobj->state), NULL); mobj->frame &= ~FF_FRAMEMASK; } @@ -11297,17 +11175,16 @@ tic_t itemrespawntime[ITEMQUESIZE]; size_t iquehead, iquetail; #ifdef PARANOIA -#define SCRAMBLE_REMOVED // Force debug build to crash when Removed mobj is accessed +#define SCRAMBLE_REMOVED // Force debug build to crash when a removed mobj is accessed #endif void P_RemoveMobj(mobj_t *mobj) { I_Assert(mobj != NULL); - if (P_MobjWasRemoved(mobj)) - return; // something already removing this mobj. + if (P_MobjWasRemoved(mobj) || mobj->thinker.removing) + return; // Something already removed or is removing this mobj. - mobj->thinker.function.acp1 = (actionf_p1)P_RemoveThinkerDelayed; // shh. no recursing. + mobj->thinker.removing = true; // Set earlier to avoid recursion. LUA_HookMobj(mobj, MOBJ_HOOK(MobjRemoved)); - mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; // needed for P_UnsetThingPosition, etc. to work. // Rings only, please! if (mobj->spawnpoint && @@ -11405,15 +11282,6 @@ void P_RemoveMobj(mobj_t *mobj) #endif } -// This does not need to be added to Lua. -// To test it in Lua, check mobj.valid -boolean P_MobjWasRemoved(mobj_t *mobj) -{ - if (mobj && mobj->thinker.function.acp1 == (actionf_p1)P_MobjThinker) - return false; - return true; -} - void P_RemovePrecipMobj(precipmobj_t *mobj) { // unlink from sector and block lists @@ -11820,7 +11688,7 @@ void P_SpawnPlayer(INT32 playernum) p->awayviewtics = 0; // set the scale to the mobj's destscale so settings get correctly set. if we don't, they sometimes don't. - P_SetScale(mobj, mobj->destscale); + P_SetScale(mobj, mobj->destscale, true); P_FlashPal(p, 0, 0); // Resets // Set bounds accurately. @@ -11889,7 +11757,7 @@ void P_AfterPlayerSpawn(INT32 playernum) if (CheckForReverseGravity) P_CheckGravity(mobj, false); - if (p->pflags & PF_FINISHED) + if (p->pflags & PF_FINISHED && !(p->exiting)) P_GiveFinishFlags(p); } @@ -11994,7 +11862,7 @@ void P_MovePlayerToStarpost(INT32 playernum) z = p->starpostz << FRACBITS; - P_SetScale(mobj, (mobj->destscale = abs(p->starpostscale))); + P_SetScale(mobj, abs(p->starpostscale), true); if (p->starpostscale < 0) { @@ -12977,7 +12845,7 @@ static boolean P_MapAlreadyHasStarPost(mobj_t *mobj) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -13102,8 +12970,8 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean if (P_MobjWasRemoved(corona)) break; - P_SetScale(corona, (corona->destscale = mobj->scale*3)); P_SetTarget(&mobj->tracer, corona); + P_SetScale(corona, 3*mobj->scale, true); } break; case MT_FLAMEHOLDER: @@ -13121,11 +12989,18 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean if (P_MobjWasRemoved(corona)) break; - P_SetScale(corona, (corona->destscale = flame->scale*3)); P_SetTarget(&flame->tracer, corona); + P_SetScale(corona, 3*flame->scale, true); } } break; + case MT_TORCHFLOWER: + { + mobj_t *fire = P_SpawnMobjFromMobj(mobj, 0, 0, 46*FRACUNIT, MT_FLAME); + if (!P_MobjWasRemoved(fire)) + P_SetTarget(&mobj->target, fire); + break; + } case MT_CANDLE: case MT_CANDLEPRICKET: if (mthing->args[0]) @@ -13210,10 +13085,8 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean case MT_DSZSTALAGMITE: case MT_DSZ2STALAGMITE: case MT_KELP: - if (mthing->args[0]) { // make mobj twice as big as normal - P_SetScale(mobj, 2*mobj->scale); // not 2*FRACUNIT in case of something like the old ERZ3 mode - mobj->destscale = mobj->scale; - } + if (mthing->args[0]) // make mobj twice as big as normal + P_SetScale(mobj, 2*mobj->scale, true); // not 2*FRACUNIT in case of something like the old ERZ3 mode break; case MT_THZTREE: { // Spawn the branches @@ -13266,6 +13139,32 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean banner->angle = mobjangle + ANGLE_90; } break; + case MT_SSZTREE: + { // Spawn the branches + INT32 i; + mobj_t *branch; + for (i = 0; i < 5; i++) + { + branch = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_SSZTREE_BRANCH); + if (P_MobjWasRemoved(branch)) + continue; + branch->angle = mobj->angle + FixedAngle(i*72*FRACUNIT); + } + } + break; + case MT_SSZTREE2: + { // Spawn the branches + INT32 i; + mobj_t *branch; + for (i = 0; i < 5; i++) + { + branch = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_SSZTREE2_BRANCH); + if (P_MobjWasRemoved(branch)) + continue; + branch->angle = mobj->angle + FixedAngle(i*72*FRACUNIT); + } + } + break; case MT_HHZTREE_TOP: { // Spawn the branches angle_t mobjangle = FixedAngle(mthing->angle << FRACBITS) & (ANGLE_90 - 1); @@ -13292,10 +13191,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean case MT_LAVAFALL: mobj->fuse = 30 + mthing->args[0]; if (mthing->args[1]) - { - P_SetScale(mobj, 2*mobj->scale); - mobj->destscale = mobj->scale; - } + P_SetScale(mobj, 2*mobj->scale, true); break; case MT_PYREFLY: //start on fire if args[0], otherwise behave normally @@ -13358,8 +13254,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean break; P_SetTarget(&elecmobj->target, mobj); elecmobj->angle = FixedAngle(mthing->angle << FRACBITS); - elecmobj->destscale = mobj->scale*2; - P_SetScale(elecmobj, elecmobj->destscale); + P_SetScale(elecmobj, 2*mobj->scale, true); } break; case MT_STARPOST: @@ -13417,8 +13312,8 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean return false; } base->angle = mobjangle + ANGLE_90; + P_SetScale(base, mobj->scale, true); base->destscale = mobj->destscale; - P_SetScale(base, mobj->scale); P_SetTarget(&base->target, mobj); P_SetTarget(&mobj->tracer, base); } @@ -13595,8 +13490,9 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y, return NULL; mobj->spawnpoint = mthing; - P_SetScale(mobj, FixedMul(mobj->scale, mthing->scale)); + P_SetScale(mobj, FixedMul(mobj->scale, mthing->scale), false); mobj->destscale = FixedMul(mobj->destscale, mthing->scale); + mobj->old_scale = FixedMul(mobj->old_scale, mthing->scale); mobj->spritexscale = mthing->spritexscale; mobj->spriteyscale = mthing->spriteyscale; @@ -14017,7 +13913,8 @@ boolean P_CheckMissileSpawn(mobj_t *th) if (!P_TryMove(th, th->x, th->y, true)) { - P_ExplodeMissile(th); + if (!P_MobjWasRemoved(th)) + P_ExplodeMissile(th); return false; } return true; @@ -14049,8 +13946,7 @@ mobj_t *P_SpawnXYZMissile(mobj_t *source, mobj_t *dest, mobjtype_t type, if (source->eflags & MFE_VERTICALFLIP) th->flags2 |= MF2_OBJECTFLIP; - th->destscale = source->scale; - P_SetScale(th, source->scale); + P_SetScale(th, source->scale, true); speed = FixedMul(th->info->speed, th->scale); @@ -14113,8 +14009,7 @@ mobj_t *P_SpawnAlteredDirectionMissile(mobj_t *source, mobjtype_t type, fixed_t if (source->eflags & MFE_VERTICALFLIP) th->flags2 |= MF2_OBJECTFLIP; - th->destscale = source->scale; - P_SetScale(th, source->scale); + P_SetScale(th, source->scale, true); speed = FixedMul(th->info->speed, th->scale); @@ -14180,8 +14075,7 @@ mobj_t *P_SpawnPointMissile(mobj_t *source, fixed_t xa, fixed_t ya, fixed_t za, if (source->eflags & MFE_VERTICALFLIP) th->flags2 |= MF2_OBJECTFLIP; - th->destscale = source->scale; - P_SetScale(th, source->scale); + P_SetScale(th, source->scale, true); speed = FixedMul(th->info->speed, th->scale); @@ -14252,8 +14146,7 @@ mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type) if (source->eflags & MFE_VERTICALFLIP) th->flags2 |= MF2_OBJECTFLIP; - th->destscale = source->scale; - P_SetScale(th, source->scale); + P_SetScale(th, source->scale, true); if (source->type == MT_METALSONIC_BATTLE && source->health < 4) speed = FixedMul(FixedMul(th->info->speed, 3*FRACUNIT/2), th->scale); @@ -14355,8 +14248,7 @@ mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle, UINT8 allowai if (source->eflags & MFE_VERTICALFLIP) th->flags2 |= MF2_OBJECTFLIP; - th->destscale = source->scale; - P_SetScale(th, source->scale); + P_SetScale(th, source->scale, true); th->flags2 |= flags2; @@ -14417,7 +14309,8 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo yofs = FixedMul(yofs, mobj->scale); zofs = FixedMul(zofs, mobj->scale); - newmobj = P_SpawnMobj(mobj->x + xofs, mobj->y + yofs, mobj->z + zofs, type); + newmobj = P_SpawnMobj(mobj->x + xofs, mobj->y + yofs, mobj->z + zofs, type, NULL); + if (!newmobj) return NULL; @@ -14438,8 +14331,8 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo newmobj->old_z2 = mobj->old_z2 + zofs; } + P_SetScale(newmobj, mobj->scale, false); newmobj->destscale = mobj->destscale; - P_SetScale(newmobj, mobj->scale); newmobj->old_x2 = mobj->old_x2 + xofs; newmobj->old_y2 = mobj->old_y2 + yofs; @@ -14468,9 +14361,13 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo newmobj->old_scale2 = mobj->old_scale2; newmobj->old_scale = mobj->old_scale; + newmobj->old_spritexscale2 = mobj->old_spritexscale2; newmobj->old_spritexscale = mobj->old_spritexscale; + newmobj->old_spriteyscale2 = mobj->old_spriteyscale2; newmobj->old_spriteyscale = mobj->old_spriteyscale; + newmobj->old_spritexoffset2 = mobj->old_spritexoffset2; newmobj->old_spritexoffset = mobj->old_spritexoffset; + newmobj->old_spriteyoffset2 = mobj->old_spriteyoffset2; newmobj->old_spriteyoffset = mobj->old_spriteyoffset; return newmobj; diff --git a/src/p_mobj.h b/src/p_mobj.h index f833415ed1d0af3ee377ed6d4ced943d2782f499..4a842766999d205eb46f15250034e523236302d5 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -308,15 +308,16 @@ typedef struct mobj_s angle_t spriteroll, old_spriteroll, old_spriteroll2; spritenum_t sprite; // used to find patch_t and flip value UINT32 frame; // frame number, plus bits see p_pspr.h - UINT8 sprite2; // player sprites + UINT16 sprite2; // player sprites UINT16 anim_duration; // for FF_ANIMATE states UINT32 renderflags; // render flags INT32 blendmode; // blend mode + fixed_t alpha; // alpha fixed_t spritexscale, spriteyscale; fixed_t spritexoffset, spriteyoffset; - fixed_t old_spritexscale, old_spriteyscale; - fixed_t old_spritexoffset, old_spriteyoffset; + fixed_t old_spritexscale, old_spriteyscale, old_spritexscale2, old_spriteyscale2; + fixed_t old_spritexoffset, old_spriteyoffset, old_spritexoffset2, old_spriteyoffset2; struct pslope_s *floorspriteslope; // The slope that the floorsprite is rotated by struct msecnode_s *touching_sectorlist; // a linked list of sectors where this object appears @@ -451,15 +452,16 @@ typedef struct precipmobj_s angle_t spriteroll, old_spriteroll, old_spriteroll2; spritenum_t sprite; // used to find patch_t and flip value UINT32 frame; // frame number, plus bits see p_pspr.h - UINT8 sprite2; // player sprites + UINT16 sprite2; // player sprites UINT16 anim_duration; // for FF_ANIMATE states UINT32 renderflags; // render flags INT32 blendmode; // blend mode + fixed_t alpha; // alpha fixed_t spritexscale, spriteyscale; fixed_t spritexoffset, spriteyoffset; - fixed_t old_spritexscale, old_spriteyscale; - fixed_t old_spritexoffset, old_spriteyoffset; + fixed_t old_spritexscale, old_spriteyscale, old_spritexscale2, old_spriteyscale2; + fixed_t old_spritexoffset, old_spriteyoffset, old_spritexoffset2, old_spriteyoffset2; struct pslope_s *floorspriteslope; // The slope that the floorsprite is rotated by struct mprecipsecnode_s *touching_sectorlist; // a linked list of sectors where this object appears @@ -527,7 +529,7 @@ void P_SnowThinker(precipmobj_t *mobj); void P_RainThinker(precipmobj_t *mobj); void P_NullPrecipThinker(precipmobj_t *mobj); void P_RemovePrecipMobj(precipmobj_t *mobj); -void P_SetScale(mobj_t *mobj, fixed_t newscale); +void P_SetScale(mobj_t *mobj, fixed_t newscale, boolean instant); void P_XYMovement(mobj_t *mo); void P_RingXYMovement(mobj_t *mo); void P_SceneryXYMovement(mobj_t *mo); @@ -537,6 +539,8 @@ boolean P_SceneryZMovement(mobj_t *mo); void P_PlayerZMovement(mobj_t *mo); void P_EmeraldManager(void); +mobj_t *P_FindNewPosition(UINT32 oldposition); + extern INT32 modulothing; #define MAXHUNTEMERALDS 64 diff --git a/src/p_polyobj.c b/src/p_polyobj.c index e779956e8d92092bf41a97db8efa5a7e7fd1d973..3d1a38d36ff9d9b8f7324df0b18029e35519870d 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2006 by James Haley -// Copyright (C) 2006-2023 by Sonic Team Junior. +// Copyright (C) 2006-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -878,15 +878,15 @@ static void Polyobj_carryThings(polyobj_t *po, fixed_t dx, fixed_t dy) { mobj_t *mo; blocknode_t *block; + blocknode_t *next = NULL; if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) continue; - block = blocklinks[y * bmapwidth + x]; - - for (; block; block = block->mnext) + for (block = blocklinks[y * bmapwidth + x]; block != NULL; block = next) { mo = block->mobj; + next = block->mnext; if (mo->lastlook == pomovecount) continue; @@ -927,11 +927,11 @@ static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line) if (!(po->flags & POF_SOLID)) return hitflags; - // adjust linedef bounding box to blockmap, extend by MAXRADIUS - linebox[BOXLEFT] = (unsigned)(line->bbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT; - linebox[BOXRIGHT] = (unsigned)(line->bbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT; - linebox[BOXBOTTOM] = (unsigned)(line->bbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT; - linebox[BOXTOP] = (unsigned)(line->bbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT; + // adjust linedef bounding box to blockmap + linebox[BOXLEFT] = (unsigned)(line->bbox[BOXLEFT] - bmaporgx) >> MAPBLOCKSHIFT; + linebox[BOXRIGHT] = (unsigned)(line->bbox[BOXRIGHT] - bmaporgx) >> MAPBLOCKSHIFT; + linebox[BOXBOTTOM] = (unsigned)(line->bbox[BOXBOTTOM] - bmaporgy) >> MAPBLOCKSHIFT; + linebox[BOXTOP] = (unsigned)(line->bbox[BOXTOP] - bmaporgy) >> MAPBLOCKSHIFT; // check all mobj blockmap cells the line contacts for (y = linebox[BOXBOTTOM]; y <= linebox[BOXTOP]; ++y) @@ -942,9 +942,11 @@ static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line) { mobj_t *mo = NULL; blocknode_t *block = blocklinks[y * bmapwidth + x]; + blocknode_t *next = NULL; - for (; block; block = block->mnext) + for (; block != NULL; block = next) { + next = block->mnext; mo = block->mobj; // Don't scroll objects that aren't affected by gravity @@ -1115,15 +1117,15 @@ static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta, { mobj_t *mo; blocknode_t *block; + blocknode_t *next = NULL; if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) continue; - block = blocklinks[y * bmapwidth + x]; - - for (; block; block = block->mnext) + for (block = blocklinks[y * bmapwidth + x]; block != NULL; block = next) { mo = block->mobj; + next = block->mnext; if (mo->lastlook == pomovecount) continue; @@ -1316,7 +1318,7 @@ void Polyobj_InitLevel(void) // the mobj_t pointers on a queue for use below. for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo = (mobj_t *)th; diff --git a/src/p_pspr.h b/src/p_pspr.h index 69e5eeeb3fc902e12782cf63672731aa5ebd0c36..5e1c1e05e8772c01d53871eca52d3b939fc66413 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -35,11 +35,11 @@ #pragma interface #endif -/// \brief Frame flags: only the frame number - 0 to 256 (Frames from 0 to 63, Sprite2 number uses 0 to 127 plus FF_SPR2SUPER) +/// \brief Frame flags: only the frame number - 0 to 256 (Frames from 0 to 255, Sprite2 number uses 0 to 127 plus FF_SPR2SUPER) #define FF_FRAMEMASK 0xff /// \brief Frame flags - SPR2: Super sprite2 -#define FF_SPR2SUPER 0x80 +#define FF_SPR2SUPER SPR2F_SUPER //TODO: 2.3: remove this backwards compat hack /// \brief Frame flags - SPR2: A change of state at the end of Sprite2 animation #define FF_SPR2ENDSTATE 0x100 /// \brief Frame flags - SPR2: 50% of starting in middle of Sprite2 animation @@ -97,6 +97,11 @@ /// \brief Frame flags - Animate: Start at a random place in the animation (mutually exclusive with above) #define FF_RANDOMANIM 0x40000000 +/// \brief Animation flags: Bits used for the animation ID +#define SPR2F_MASK 0x3FF +/// \brief Animation flags: "Super" flag +#define SPR2F_SUPER 0x400 + /** \brief translucency tables \todo add another asm routine which use the fg and bg indexes in the diff --git a/src/p_saveg.c b/src/p_saveg.c index 6c6548c567f195cfc7bbc884e1e45dea18afde1a..650622f59f8130a896257748eb56a4116e963f7e 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -35,9 +35,249 @@ #include "p_polyobj.h" #include "lua_script.h" #include "p_slopes.h" +#include "hu_stuff.h" savedata_t savedata; -UINT8 *save_p; + +#define ALLOC_SIZE(p, z) \ + if ((p)->pos + (z) > (p)->size) \ + { \ + while ((p)->pos + (z) > (p)->size) \ + (p)->size <<= 1; \ + (p)->buf = realloc((p)->buf, (p)->size); \ + } + +void P_WriteUINT8(save_t *p, UINT8 v) +{ + ALLOC_SIZE(p, sizeof(v)); + memcpy(&p->buf[p->pos], &v, sizeof(v)); + p->pos += sizeof(v); +} + +void P_WriteSINT8(save_t *p, SINT8 v) +{ + ALLOC_SIZE(p, sizeof(v)); + memcpy(&p->buf[p->pos], &v, sizeof(v)); + p->pos += sizeof(v); +} + +void P_WriteUINT16(save_t *p, UINT16 v) +{ + ALLOC_SIZE(p, sizeof(v)); + memcpy(&p->buf[p->pos], &v, sizeof(v)); + p->pos += sizeof(v); +} + +void P_WriteINT16(save_t *p, INT16 v) +{ + ALLOC_SIZE(p, sizeof(v)); + memcpy(&p->buf[p->pos], &v, sizeof(v)); + p->pos += sizeof(v); +} + +void P_WriteUINT32(save_t *p, UINT32 v) +{ + ALLOC_SIZE(p, sizeof(v)); + memcpy(&p->buf[p->pos], &v, sizeof(v)); + p->pos += sizeof(v); +} + +void P_WriteINT32(save_t *p, INT32 v) +{ + ALLOC_SIZE(p, sizeof(v)); + memcpy(&p->buf[p->pos], &v, sizeof(v)); + p->pos += sizeof(v); +} + +void P_WriteChar(save_t *p, char v) +{ + ALLOC_SIZE(p, sizeof(v)); + memcpy(&p->buf[p->pos], &v, sizeof(v)); + p->pos += sizeof(v); +} + +void P_WriteFixed(save_t *p, fixed_t v) +{ + ALLOC_SIZE(p, sizeof(v)); + memcpy(&p->buf[p->pos], &v, sizeof(v)); + p->pos += sizeof(v); +} + +void P_WriteAngle(save_t *p, angle_t v) +{ + ALLOC_SIZE(p, sizeof(v)); + memcpy(&p->buf[p->pos], &v, sizeof(v)); + p->pos += sizeof(v); +} + +void P_WriteStringN(save_t *p, char const *s, size_t n) +{ + size_t i; + + for (i = 0; i < n && s[i] != '\0'; i++) + P_WriteChar(p, s[i]); + + if (i < n) + P_WriteChar(p, '\0'); +} + +void P_WriteStringL(save_t *p, char const *s, size_t n) +{ + size_t i; + + for (i = 0; i < n - 1 && s[i] != '\0'; i++) + P_WriteChar(p, s[i]); + + P_WriteChar(p, '\0'); +} + +void P_WriteString(save_t *p, char const *s) +{ + size_t i; + + for (i = 0; s[i] != '\0'; i++) + P_WriteChar(p, s[i]); + + P_WriteChar(p, '\0'); +} + +void P_WriteMem(save_t *p, void const *s, size_t n) +{ + ALLOC_SIZE(p, n); + memcpy(&p->buf[p->pos], s, n); + p->pos += n; +} + +void P_SkipStringN(save_t *p, size_t n) +{ + size_t i; + for (i = 0; p->pos < p->size && i < n && P_ReadChar(p) != '\0'; i++); +} + +void P_SkipStringL(save_t *p, size_t n) +{ + P_SkipStringN(p, n); +} + +void P_SkipString(save_t *p) +{ + P_SkipStringN(p, SIZE_MAX); +} + +UINT8 P_ReadUINT8(save_t *p) +{ + UINT8 v; + if (p->pos + sizeof(v) > p->size) + return 0; + memcpy(&v, &p->buf[p->pos], sizeof(v)); + p->pos += sizeof(v); + return v; +} + +SINT8 P_ReadSINT8(save_t *p) +{ + SINT8 v; + if (p->pos + sizeof(v) > p->size) + return 0; + memcpy(&v, &p->buf[p->pos], sizeof(v)); + p->pos += sizeof(v); + return v; +} + +UINT16 P_ReadUINT16(save_t *p) +{ + UINT16 v; + if (p->pos + sizeof(v) > p->size) + return 0; + memcpy(&v, &p->buf[p->pos], sizeof(v)); + p->pos += sizeof(v); + return v; +} + +INT16 P_ReadINT16(save_t *p) +{ + INT16 v; + if (p->pos + sizeof(v) > p->size) + return 0; + memcpy(&v, &p->buf[p->pos], sizeof(v)); + p->pos += sizeof(v); + return v; +} + +UINT32 P_ReadUINT32(save_t *p) +{ + UINT32 v; + if (p->pos + sizeof(v) > p->size) + return 0; + memcpy(&v, &p->buf[p->pos], sizeof(v)); + p->pos += sizeof(v); + return v; +} + +INT32 P_ReadINT32(save_t *p) +{ + INT32 v; + if (p->pos + sizeof(v) > p->size) + return 0; + memcpy(&v, &p->buf[p->pos], sizeof(v)); + p->pos += sizeof(v); + return v; +} + +char P_ReadChar(save_t *p) +{ + char v; + if (p->pos + sizeof(v) > p->size) + return 0; + memcpy(&v, &p->buf[p->pos], sizeof(v)); + p->pos += sizeof(v); + return v; +} + +fixed_t P_ReadFixed(save_t *p) +{ + fixed_t v; + if (p->pos + sizeof(v) > p->size) + return 0; + memcpy(&v, &p->buf[p->pos], sizeof(v)); + p->pos += sizeof(v); + return v; +} + +angle_t P_ReadAngle(save_t *p) +{ + angle_t v; + if (p->pos + sizeof(v) > p->size) + return 0; + memcpy(&v, &p->buf[p->pos], sizeof(v)); + p->pos += sizeof(v); + return v; +} + +void P_ReadStringN(save_t *p, char *s, size_t n) +{ + size_t i; + for (i = 0; p->pos < p->size && i < n && (s[i] = P_ReadChar(p)) != '\0'; i++); + s[i] = '\0'; +} + +void P_ReadStringL(save_t *p, char *s, size_t n) +{ + P_ReadStringN(p, s, n - 1); +} + +void P_ReadString(save_t *p, char *s) +{ + P_ReadStringN(p, s, SIZE_MAX); +} + +void P_ReadMem(save_t *p, void *s, size_t n) +{ + if (p->pos + n > p->size) + return; + memcpy(s, &p->buf[p->pos], n); + p->pos += n; +} // Block UINT32s to attempt to ensure that the correct data is // being sent and received @@ -62,7 +302,7 @@ typedef enum DRONE = 0x80, } player_saveflags; -static inline void P_ArchivePlayer(void) +static inline void P_ArchivePlayer(save_t *save_p) { const player_t *player = &players[consoleplayer]; SINT8 pllives = player->lives; @@ -72,32 +312,32 @@ static inline void P_ArchivePlayer(void) #ifdef NEWSKINSAVES // Write a specific value into the old skininfo location. // If we read something other than this, it's an older save file that used skin numbers. - WRITEUINT16(save_p, NEWSKINSAVES); + P_WriteUINT16(save_p, NEWSKINSAVES); #endif // Write skin names, so that loading skins in different orders // doesn't change who the save file is for! - WRITESTRINGN(save_p, skins[player->skin]->name, SKINNAMESIZE); + P_WriteStringN(save_p, skins[player->skin]->name, SKINNAMESIZE); if (botskin != 0) { - WRITESTRINGN(save_p, skins[botskin-1]->name, SKINNAMESIZE); + P_WriteStringN(save_p, skins[botskin-1]->name, SKINNAMESIZE); } else { - WRITESTRINGN(save_p, "\0", SKINNAMESIZE); + P_WriteStringN(save_p, "\0", SKINNAMESIZE); } - WRITEUINT8(save_p, numgameovers); - WRITESINT8(save_p, pllives); - WRITEUINT32(save_p, player->score); - WRITEINT32(save_p, player->continues); + P_WriteUINT8(save_p, numgameovers); + P_WriteSINT8(save_p, pllives); + P_WriteUINT32(save_p, player->score); + P_WriteINT32(save_p, player->continues); } -static inline void P_UnArchivePlayer(void) +static inline void P_UnArchivePlayer(save_t *save_p) { #ifdef NEWSKINSAVES - INT16 backwardsCompat = READUINT16(save_p); + INT16 backwardsCompat = P_ReadUINT16(save_p); if (backwardsCompat != NEWSKINSAVES) { @@ -111,30 +351,30 @@ static inline void P_UnArchivePlayer(void) char ourSkinName[SKINNAMESIZE+1]; char botSkinName[SKINNAMESIZE+1]; - READSTRINGN(save_p, ourSkinName, SKINNAMESIZE); + P_ReadStringN(save_p, ourSkinName, SKINNAMESIZE); savedata.skin = R_SkinAvailable(ourSkinName); - READSTRINGN(save_p, botSkinName, SKINNAMESIZE); + P_ReadStringN(save_p, botSkinName, SKINNAMESIZE); savedata.botskin = R_SkinAvailable(botSkinName) + 1; } - savedata.numgameovers = READUINT8(save_p); - savedata.lives = READSINT8(save_p); - savedata.score = READUINT32(save_p); - savedata.continues = READINT32(save_p); + savedata.numgameovers = P_ReadUINT8(save_p); + savedata.lives = P_ReadSINT8(save_p); + savedata.score = P_ReadUINT32(save_p); + savedata.continues = P_ReadINT32(save_p); } -static void P_NetArchivePlayers(void) +static void P_NetArchivePlayers(save_t *save_p) { INT32 i, j; UINT16 flags; // size_t q; - WRITEUINT32(save_p, ARCHIVEBLOCK_PLAYERS); + P_WriteUINT32(save_p, ARCHIVEBLOCK_PLAYERS); for (i = 0; i < MAXPLAYERS; i++) { - WRITESINT8(save_p, (SINT8)adminplayers[i]); + P_WriteSINT8(save_p, (SINT8)adminplayers[i]); if (!playeringame[i]) continue; @@ -143,140 +383,142 @@ static void P_NetArchivePlayers(void) // no longer send ticcmds - WRITESTRINGN(save_p, player_names[i], MAXPLAYERNAME); - WRITEINT16(save_p, players[i].angleturn); - WRITEINT16(save_p, players[i].oldrelangleturn); - WRITEANGLE(save_p, players[i].aiming); - WRITEANGLE(save_p, players[i].drawangle); - WRITEANGLE(save_p, players[i].viewrollangle); - WRITEANGLE(save_p, players[i].awayviewaiming); - WRITEINT32(save_p, players[i].awayviewtics); - WRITEINT16(save_p, players[i].rings); - WRITEINT16(save_p, players[i].spheres); - - WRITESINT8(save_p, players[i].pity); - WRITEINT32(save_p, players[i].currentweapon); - WRITEINT32(save_p, players[i].ringweapons); - - WRITEUINT16(save_p, players[i].ammoremoval); - WRITEUINT32(save_p, players[i].ammoremovaltimer); - WRITEINT32(save_p, players[i].ammoremovaltimer); + P_WriteStringN(save_p, player_names[i], MAXPLAYERNAME); + P_WriteINT16(save_p, players[i].angleturn); + P_WriteINT16(save_p, players[i].oldrelangleturn); + P_WriteAngle(save_p, players[i].aiming); + P_WriteAngle(save_p, players[i].drawangle); + P_WriteAngle(save_p, players[i].viewrollangle); + P_WriteAngle(save_p, players[i].awayviewaiming); + P_WriteINT32(save_p, players[i].awayviewtics); + P_WriteINT16(save_p, players[i].rings); + P_WriteINT16(save_p, players[i].spheres); + + P_WriteSINT8(save_p, players[i].pity); + P_WriteINT32(save_p, players[i].currentweapon); + P_WriteINT32(save_p, players[i].ringweapons); + + P_WriteUINT16(save_p, players[i].ammoremoval); + P_WriteUINT32(save_p, players[i].ammoremovaltimer); + P_WriteINT32(save_p, players[i].ammoremovaltimer); for (j = 0; j < NUMPOWERS; j++) - WRITEUINT16(save_p, players[i].powers[j]); - - WRITEUINT8(save_p, players[i].playerstate); - WRITEUINT32(save_p, players[i].pflags); - WRITEUINT8(save_p, players[i].panim); - WRITEUINT8(save_p, players[i].stronganim); - WRITEUINT8(save_p, players[i].spectator); - - WRITEUINT16(save_p, players[i].flashpal); - WRITEUINT16(save_p, players[i].flashcount); - - WRITEUINT16(save_p, players[i].skincolor); - WRITEINT32(save_p, players[i].skin); - WRITEUINT32(save_p, players[i].availabilities); - WRITEUINT32(save_p, players[i].score); - WRITEUINT32(save_p, players[i].recordscore); - WRITEFIXED(save_p, players[i].dashspeed); - WRITESINT8(save_p, players[i].lives); - WRITESINT8(save_p, players[i].continues); - WRITESINT8(save_p, players[i].xtralife); - WRITEUINT8(save_p, players[i].gotcontinue); - WRITEFIXED(save_p, players[i].speed); - WRITEUINT8(save_p, players[i].secondjump); - WRITEUINT8(save_p, players[i].fly1); - WRITEUINT8(save_p, players[i].scoreadd); - WRITEUINT32(save_p, players[i].glidetime); - WRITEUINT8(save_p, players[i].climbing); - WRITEINT32(save_p, players[i].deadtimer); - WRITEUINT32(save_p, players[i].exiting); - WRITEUINT8(save_p, players[i].homing); - WRITEUINT32(save_p, players[i].dashmode); - WRITEUINT32(save_p, players[i].skidtime); + P_WriteUINT16(save_p, players[i].powers[j]); + + P_WriteUINT8(save_p, players[i].playerstate); + P_WriteUINT32(save_p, players[i].pflags); + P_WriteUINT8(save_p, players[i].panim); + P_WriteUINT8(save_p, players[i].stronganim); + P_WriteUINT8(save_p, players[i].spectator); + P_WriteUINT8(save_p, players[i].muted); + + P_WriteUINT16(save_p, players[i].flashpal); + P_WriteUINT16(save_p, players[i].flashcount); + + P_WriteUINT16(save_p, players[i].skincolor); + P_WriteINT32(save_p, players[i].skin); + P_WriteUINT32(save_p, players[i].availabilities); + P_WriteUINT32(save_p, players[i].score); + P_WriteUINT32(save_p, players[i].recordscore); + P_WriteFixed(save_p, players[i].dashspeed); + P_WriteSINT8(save_p, players[i].lives); + P_WriteSINT8(save_p, players[i].continues); + P_WriteSINT8(save_p, players[i].xtralife); + P_WriteUINT8(save_p, players[i].gotcontinue); + P_WriteFixed(save_p, players[i].speed); + P_WriteUINT8(save_p, players[i].secondjump); + P_WriteUINT8(save_p, players[i].fly1); + P_WriteUINT8(save_p, players[i].scoreadd); + P_WriteUINT32(save_p, players[i].glidetime); + P_WriteUINT8(save_p, players[i].climbing); + P_WriteINT32(save_p, players[i].deadtimer); + P_WriteUINT32(save_p, players[i].exiting); + P_WriteUINT8(save_p, players[i].homing); + P_WriteUINT32(save_p, players[i].dashmode); + P_WriteUINT32(save_p, players[i].skidtime); ////////// // Bots // ////////// - WRITEUINT8(save_p, players[i].bot); - WRITEUINT8(save_p, players[i].botmem.lastForward); - WRITEUINT8(save_p, players[i].botmem.lastBlocked); - WRITEUINT8(save_p, players[i].botmem.catchup_tics); - WRITEUINT8(save_p, players[i].botmem.thinkstate); - WRITEUINT8(save_p, players[i].removing); + P_WriteUINT8(save_p, players[i].bot); + P_WriteUINT8(save_p, players[i].botmem.lastForward); + P_WriteUINT8(save_p, players[i].botmem.lastBlocked); + P_WriteUINT8(save_p, players[i].botmem.catchup_tics); + P_WriteUINT8(save_p, players[i].botmem.thinkstate); + P_WriteUINT8(save_p, players[i].removing); - WRITEUINT8(save_p, players[i].blocked); - WRITEUINT16(save_p, players[i].lastbuttons); + P_WriteUINT8(save_p, players[i].blocked); + P_WriteUINT16(save_p, players[i].lastbuttons); //////////////////////////// // Conveyor Belt Movement // //////////////////////////// - WRITEFIXED(save_p, players[i].cmomx); // Conveyor momx - WRITEFIXED(save_p, players[i].cmomy); // Conveyor momy - WRITEFIXED(save_p, players[i].rmomx); // "Real" momx (momx - cmomx) - WRITEFIXED(save_p, players[i].rmomy); // "Real" momy (momy - cmomy) + P_WriteFixed(save_p, players[i].cmomx); // Conveyor momx + P_WriteFixed(save_p, players[i].cmomy); // Conveyor momy + P_WriteFixed(save_p, players[i].rmomx); // "Real" momx (momx - cmomx) + P_WriteFixed(save_p, players[i].rmomy); // "Real" momy (momy - cmomy) ///////////////////// // Race Mode Stuff // ///////////////////// - WRITEINT16(save_p, players[i].numboxes); - WRITEINT16(save_p, players[i].totalring); - WRITEUINT32(save_p, players[i].realtime); - WRITEUINT8(save_p, players[i].laps); + P_WriteINT16(save_p, players[i].numboxes); + P_WriteINT16(save_p, players[i].totalring); + P_WriteUINT32(save_p, players[i].realtime); + P_WriteUINT8(save_p, players[i].laps); //////////////////// // CTF Mode Stuff // //////////////////// - WRITEINT32(save_p, players[i].ctfteam); - WRITEUINT16(save_p, players[i].gotflag); - - WRITEINT32(save_p, players[i].weapondelay); - WRITEINT32(save_p, players[i].tossdelay); - - WRITEUINT32(save_p, players[i].starposttime); - WRITEINT16(save_p, players[i].starpostx); - WRITEINT16(save_p, players[i].starposty); - WRITEINT16(save_p, players[i].starpostz); - WRITEINT32(save_p, players[i].starpostnum); - WRITEANGLE(save_p, players[i].starpostangle); - WRITEFIXED(save_p, players[i].starpostscale); - - WRITEANGLE(save_p, players[i].angle_pos); - WRITEANGLE(save_p, players[i].old_angle_pos); - - WRITEINT32(save_p, players[i].flyangle); - WRITEUINT32(save_p, players[i].drilltimer); - WRITEINT32(save_p, players[i].linkcount); - WRITEUINT32(save_p, players[i].linktimer); - WRITEINT32(save_p, players[i].anotherflyangle); - WRITEUINT32(save_p, players[i].nightstime); - WRITEUINT32(save_p, players[i].bumpertime); - WRITEINT32(save_p, players[i].drillmeter); - WRITEUINT8(save_p, players[i].drilldelay); - WRITEUINT8(save_p, players[i].bonustime); - WRITEFIXED(save_p, players[i].oldscale); - WRITEUINT8(save_p, players[i].mare); - WRITEUINT8(save_p, players[i].marelap); - WRITEUINT8(save_p, players[i].marebonuslap); - WRITEUINT32(save_p, players[i].marebegunat); - WRITEUINT32(save_p, players[i].startedtime); - WRITEUINT32(save_p, players[i].finishedtime); - WRITEUINT32(save_p, players[i].lapbegunat); - WRITEUINT32(save_p, players[i].lapstartedtime); - WRITEINT16(save_p, players[i].finishedspheres); - WRITEINT16(save_p, players[i].finishedrings); - WRITEUINT32(save_p, players[i].marescore); - WRITEUINT32(save_p, players[i].lastmarescore); - WRITEUINT32(save_p, players[i].totalmarescore); - WRITEUINT8(save_p, players[i].lastmare); - WRITEUINT8(save_p, players[i].lastmarelap); - WRITEUINT8(save_p, players[i].lastmarebonuslap); - WRITEUINT8(save_p, players[i].totalmarelap); - WRITEUINT8(save_p, players[i].totalmarebonuslap); - WRITEINT32(save_p, players[i].maxlink); - WRITEUINT8(save_p, players[i].texttimer); - WRITEUINT8(save_p, players[i].textvar); + P_WriteINT32(save_p, players[i].ctfteam); + P_WriteUINT16(save_p, players[i].gotflag); + + P_WriteINT32(save_p, players[i].weapondelay); + P_WriteINT32(save_p, players[i].tossdelay); + + P_WriteUINT32(save_p, players[i].starposttime); + P_WriteINT16(save_p, players[i].starpostx); + P_WriteINT16(save_p, players[i].starposty); + P_WriteINT16(save_p, players[i].starpostz); + P_WriteINT32(save_p, players[i].starpostnum); + P_WriteAngle(save_p, players[i].starpostangle); + P_WriteFixed(save_p, players[i].starpostscale); + + P_WriteAngle(save_p, players[i].angle_pos); + P_WriteAngle(save_p, players[i].old_angle_pos); + + P_WriteINT32(save_p, players[i].flyangle); + P_WriteUINT32(save_p, players[i].drilltimer); + P_WriteINT32(save_p, players[i].linkcount); + P_WriteUINT32(save_p, players[i].linktimer); + P_WriteINT32(save_p, players[i].anotherflyangle); + P_WriteUINT32(save_p, players[i].nightstime); + P_WriteUINT32(save_p, players[i].bumpertime); + P_WriteINT32(save_p, players[i].drillmeter); + P_WriteUINT8(save_p, players[i].drilldelay); + P_WriteUINT8(save_p, players[i].bonustime); + P_WriteFixed(save_p, players[i].oldscale); + P_WriteUINT8(save_p, players[i].mare); + P_WriteUINT8(save_p, players[i].marelap); + P_WriteUINT8(save_p, players[i].marebonuslap); + P_WriteUINT32(save_p, players[i].marebegunat); + P_WriteUINT32(save_p, players[i].lastmaretime); + P_WriteUINT32(save_p, players[i].startedtime); + P_WriteUINT32(save_p, players[i].finishedtime); + P_WriteUINT32(save_p, players[i].lapbegunat); + P_WriteUINT32(save_p, players[i].lapstartedtime); + P_WriteINT16(save_p, players[i].finishedspheres); + P_WriteINT16(save_p, players[i].finishedrings); + P_WriteUINT32(save_p, players[i].marescore); + P_WriteUINT32(save_p, players[i].lastmarescore); + P_WriteUINT32(save_p, players[i].totalmarescore); + P_WriteUINT8(save_p, players[i].lastmare); + P_WriteUINT8(save_p, players[i].lastmarelap); + P_WriteUINT8(save_p, players[i].lastmarebonuslap); + P_WriteUINT8(save_p, players[i].totalmarelap); + P_WriteUINT8(save_p, players[i].totalmarebonuslap); + P_WriteINT32(save_p, players[i].maxlink); + P_WriteUINT8(save_p, players[i].texttimer); + P_WriteUINT8(save_p, players[i].textvar); if (players[i].capsule) flags |= CAPSULE; @@ -296,73 +538,73 @@ static void P_NetArchivePlayers(void) if (players[i].drone) flags |= DRONE; - WRITEINT16(save_p, players[i].lastsidehit); - WRITEINT16(save_p, players[i].lastlinehit); + P_WriteINT16(save_p, players[i].lastsidehit); + P_WriteINT16(save_p, players[i].lastlinehit); - WRITEUINT32(save_p, players[i].losstime); + P_WriteUINT32(save_p, players[i].losstime); - WRITEUINT8(save_p, players[i].timeshit); + P_WriteUINT8(save_p, players[i].timeshit); - WRITEINT32(save_p, players[i].onconveyor); + P_WriteINT32(save_p, players[i].onconveyor); - WRITEUINT32(save_p, players[i].jointime); - WRITEUINT32(save_p, players[i].quittime); + P_WriteUINT32(save_p, players[i].jointime); + P_WriteUINT32(save_p, players[i].quittime); - WRITEUINT16(save_p, flags); + P_WriteUINT16(save_p, flags); if (flags & CAPSULE) - WRITEUINT32(save_p, players[i].capsule->mobjnum); + P_WriteUINT32(save_p, players[i].capsule->mobjnum); if (flags & FIRSTAXIS) - WRITEUINT32(save_p, players[i].axis1->mobjnum); + P_WriteUINT32(save_p, players[i].axis1->mobjnum); if (flags & SECONDAXIS) - WRITEUINT32(save_p, players[i].axis2->mobjnum); + P_WriteUINT32(save_p, players[i].axis2->mobjnum); if (flags & AWAYVIEW) - WRITEUINT32(save_p, players[i].awayviewmobj->mobjnum); + P_WriteUINT32(save_p, players[i].awayviewmobj->mobjnum); if (flags & FOLLOW) - WRITEUINT32(save_p, players[i].followmobj->mobjnum); + P_WriteUINT32(save_p, players[i].followmobj->mobjnum); if (flags & DRONE) - WRITEUINT32(save_p, players[i].drone->mobjnum); - - WRITEFIXED(save_p, players[i].camerascale); - WRITEFIXED(save_p, players[i].shieldscale); - - WRITEUINT8(save_p, players[i].charability); - WRITEUINT8(save_p, players[i].charability2); - WRITEUINT32(save_p, players[i].charflags); - WRITEUINT32(save_p, (UINT32)players[i].thokitem); - WRITEUINT32(save_p, (UINT32)players[i].spinitem); - WRITEUINT32(save_p, (UINT32)players[i].revitem); - WRITEUINT32(save_p, (UINT32)players[i].followitem); - WRITEFIXED(save_p, players[i].actionspd); - WRITEFIXED(save_p, players[i].mindash); - WRITEFIXED(save_p, players[i].maxdash); - WRITEFIXED(save_p, players[i].normalspeed); - WRITEFIXED(save_p, players[i].runspeed); - WRITEUINT8(save_p, players[i].thrustfactor); - WRITEUINT8(save_p, players[i].accelstart); - WRITEUINT8(save_p, players[i].acceleration); - WRITEFIXED(save_p, players[i].jumpfactor); - WRITEFIXED(save_p, players[i].height); - WRITEFIXED(save_p, players[i].spinheight); + P_WriteUINT32(save_p, players[i].drone->mobjnum); + + P_WriteFixed(save_p, players[i].camerascale); + P_WriteFixed(save_p, players[i].shieldscale); + + P_WriteUINT8(save_p, players[i].charability); + P_WriteUINT8(save_p, players[i].charability2); + P_WriteUINT32(save_p, players[i].charflags); + P_WriteUINT32(save_p, (UINT32)players[i].thokitem); + P_WriteUINT32(save_p, (UINT32)players[i].spinitem); + P_WriteUINT32(save_p, (UINT32)players[i].revitem); + P_WriteUINT32(save_p, (UINT32)players[i].followitem); + P_WriteFixed(save_p, players[i].actionspd); + P_WriteFixed(save_p, players[i].mindash); + P_WriteFixed(save_p, players[i].maxdash); + P_WriteFixed(save_p, players[i].normalspeed); + P_WriteFixed(save_p, players[i].runspeed); + P_WriteUINT8(save_p, players[i].thrustfactor); + P_WriteUINT8(save_p, players[i].accelstart); + P_WriteUINT8(save_p, players[i].acceleration); + P_WriteFixed(save_p, players[i].jumpfactor); + P_WriteFixed(save_p, players[i].height); + P_WriteFixed(save_p, players[i].spinheight); } } -static void P_NetUnArchivePlayers(void) +static void P_NetUnArchivePlayers(save_t *save_p) { INT32 i, j; UINT16 flags; - if (READUINT32(save_p) != ARCHIVEBLOCK_PLAYERS) + if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_PLAYERS) I_Error("Bad $$$.sav at archive block Players"); for (i = 0; i < MAXPLAYERS; i++) { - adminplayers[i] = (INT32)READSINT8(save_p); + adminplayers[i] = (INT32)P_ReadSINT8(save_p); // Do NOT memset player struct to 0 // other areas may initialize data elsewhere @@ -372,196 +614,198 @@ static void P_NetUnArchivePlayers(void) // NOTE: sending tics should (hopefully) no longer be necessary - READSTRINGN(save_p, player_names[i], MAXPLAYERNAME); - players[i].angleturn = READINT16(save_p); - players[i].oldrelangleturn = READINT16(save_p); - players[i].aiming = READANGLE(save_p); - players[i].drawangle = READANGLE(save_p); - players[i].viewrollangle = READANGLE(save_p); - players[i].awayviewaiming = READANGLE(save_p); - players[i].awayviewtics = READINT32(save_p); - players[i].rings = READINT16(save_p); - players[i].spheres = READINT16(save_p); - - players[i].pity = READSINT8(save_p); - players[i].currentweapon = READINT32(save_p); - players[i].ringweapons = READINT32(save_p); - - players[i].ammoremoval = READUINT16(save_p); - players[i].ammoremovaltimer = READUINT32(save_p); - players[i].ammoremovalweapon = READINT32(save_p); + P_ReadStringN(save_p, player_names[i], MAXPLAYERNAME); + players[i].angleturn = P_ReadINT16(save_p); + players[i].oldrelangleturn = P_ReadINT16(save_p); + players[i].aiming = P_ReadAngle(save_p); + players[i].drawangle = P_ReadAngle(save_p); + players[i].viewrollangle = P_ReadAngle(save_p); + players[i].awayviewaiming = P_ReadAngle(save_p); + players[i].awayviewtics = P_ReadINT32(save_p); + players[i].rings = P_ReadINT16(save_p); + players[i].spheres = P_ReadINT16(save_p); + + players[i].pity = P_ReadSINT8(save_p); + players[i].currentweapon = P_ReadINT32(save_p); + players[i].ringweapons = P_ReadINT32(save_p); + + players[i].ammoremoval = P_ReadUINT16(save_p); + players[i].ammoremovaltimer = P_ReadUINT32(save_p); + players[i].ammoremovalweapon = P_ReadINT32(save_p); for (j = 0; j < NUMPOWERS; j++) - players[i].powers[j] = READUINT16(save_p); - - players[i].playerstate = READUINT8(save_p); - players[i].pflags = READUINT32(save_p); - players[i].panim = READUINT8(save_p); - players[i].stronganim = READUINT8(save_p); - players[i].spectator = READUINT8(save_p); - - players[i].flashpal = READUINT16(save_p); - players[i].flashcount = READUINT16(save_p); - - players[i].skincolor = READUINT16(save_p); - players[i].skin = READINT32(save_p); - players[i].availabilities = READUINT32(save_p); - players[i].score = READUINT32(save_p); - players[i].recordscore = READUINT32(save_p); - players[i].dashspeed = READFIXED(save_p); // dashing speed - players[i].lives = READSINT8(save_p); - players[i].continues = READSINT8(save_p); // continues that player has acquired - players[i].xtralife = READSINT8(save_p); // Ring Extra Life counter - players[i].gotcontinue = READUINT8(save_p); // got continue from stage - players[i].speed = READFIXED(save_p); // Player's speed (distance formula of MOMX and MOMY values) - players[i].secondjump = READUINT8(save_p); - players[i].fly1 = READUINT8(save_p); // Tails flying - players[i].scoreadd = READUINT8(save_p); // Used for multiple enemy attack bonus - players[i].glidetime = READUINT32(save_p); // Glide counter for thrust - players[i].climbing = READUINT8(save_p); // Climbing on the wall - players[i].deadtimer = READINT32(save_p); // End game if game over lasts too long - players[i].exiting = READUINT32(save_p); // Exitlevel timer - players[i].homing = READUINT8(save_p); // Are you homing? - players[i].dashmode = READUINT32(save_p); // counter for dashmode ability - players[i].skidtime = READUINT32(save_p); // Skid timer + players[i].powers[j] = P_ReadUINT16(save_p); + + players[i].playerstate = P_ReadUINT8(save_p); + players[i].pflags = P_ReadUINT32(save_p); + players[i].panim = P_ReadUINT8(save_p); + players[i].stronganim = P_ReadUINT8(save_p); + players[i].spectator = P_ReadUINT8(save_p); + players[i].muted = P_ReadUINT8(save_p); + + players[i].flashpal = P_ReadUINT16(save_p); + players[i].flashcount = P_ReadUINT16(save_p); + + players[i].skincolor = P_ReadUINT16(save_p); + players[i].skin = P_ReadINT32(save_p); + players[i].availabilities = P_ReadUINT32(save_p); + players[i].score = P_ReadUINT32(save_p); + players[i].recordscore = P_ReadUINT32(save_p); + players[i].dashspeed = P_ReadFixed(save_p); // dashing speed + players[i].lives = P_ReadSINT8(save_p); + players[i].continues = P_ReadSINT8(save_p); // continues that player has acquired + players[i].xtralife = P_ReadSINT8(save_p); // Ring Extra Life counter + players[i].gotcontinue = P_ReadUINT8(save_p); // got continue from stage + players[i].speed = P_ReadFixed(save_p); // Player's speed (distance formula of MOMX and MOMY values) + players[i].secondjump = P_ReadUINT8(save_p); + players[i].fly1 = P_ReadUINT8(save_p); // Tails flying + players[i].scoreadd = P_ReadUINT8(save_p); // Used for multiple enemy attack bonus + players[i].glidetime = P_ReadUINT32(save_p); // Glide counter for thrust + players[i].climbing = P_ReadUINT8(save_p); // Climbing on the wall + players[i].deadtimer = P_ReadINT32(save_p); // End game if game over lasts too long + players[i].exiting = P_ReadUINT32(save_p); // Exitlevel timer + players[i].homing = P_ReadUINT8(save_p); // Are you homing? + players[i].dashmode = P_ReadUINT32(save_p); // counter for dashmode ability + players[i].skidtime = P_ReadUINT32(save_p); // Skid timer ////////// // Bots // ////////// - players[i].bot = READUINT8(save_p); + players[i].bot = P_ReadUINT8(save_p); - players[i].botmem.lastForward = READUINT8(save_p); - players[i].botmem.lastBlocked = READUINT8(save_p); - players[i].botmem.catchup_tics = READUINT8(save_p); - players[i].botmem.thinkstate = READUINT8(save_p); - players[i].removing = READUINT8(save_p); + players[i].botmem.lastForward = P_ReadUINT8(save_p); + players[i].botmem.lastBlocked = P_ReadUINT8(save_p); + players[i].botmem.catchup_tics = P_ReadUINT8(save_p); + players[i].botmem.thinkstate = P_ReadUINT8(save_p); + players[i].removing = P_ReadUINT8(save_p); - players[i].blocked = READUINT8(save_p); - players[i].lastbuttons = READUINT16(save_p); + players[i].blocked = P_ReadUINT8(save_p); + players[i].lastbuttons = P_ReadUINT16(save_p); //////////////////////////// // Conveyor Belt Movement // //////////////////////////// - players[i].cmomx = READFIXED(save_p); // Conveyor momx - players[i].cmomy = READFIXED(save_p); // Conveyor momy - players[i].rmomx = READFIXED(save_p); // "Real" momx (momx - cmomx) - players[i].rmomy = READFIXED(save_p); // "Real" momy (momy - cmomy) + players[i].cmomx = P_ReadFixed(save_p); // Conveyor momx + players[i].cmomy = P_ReadFixed(save_p); // Conveyor momy + players[i].rmomx = P_ReadFixed(save_p); // "Real" momx (momx - cmomx) + players[i].rmomy = P_ReadFixed(save_p); // "Real" momy (momy - cmomy) ///////////////////// // Race Mode Stuff // ///////////////////// - players[i].numboxes = READINT16(save_p); // Number of item boxes obtained for Race Mode - players[i].totalring = READINT16(save_p); // Total number of rings obtained for Race Mode - players[i].realtime = READUINT32(save_p); // integer replacement for leveltime - players[i].laps = READUINT8(save_p); // Number of laps (optional) + players[i].numboxes = P_ReadINT16(save_p); // Number of item boxes obtained for Race Mode + players[i].totalring = P_ReadINT16(save_p); // Total number of rings obtained for Race Mode + players[i].realtime = P_ReadUINT32(save_p); // integer replacement for leveltime + players[i].laps = P_ReadUINT8(save_p); // Number of laps (optional) //////////////////// // CTF Mode Stuff // //////////////////// - players[i].ctfteam = READINT32(save_p); // 1 == Red, 2 == Blue - players[i].gotflag = READUINT16(save_p); // 1 == Red, 2 == Blue Do you have the flag? - - players[i].weapondelay = READINT32(save_p); - players[i].tossdelay = READINT32(save_p); - - players[i].starposttime = READUINT32(save_p); - players[i].starpostx = READINT16(save_p); - players[i].starposty = READINT16(save_p); - players[i].starpostz = READINT16(save_p); - players[i].starpostnum = READINT32(save_p); - players[i].starpostangle = READANGLE(save_p); - players[i].starpostscale = READFIXED(save_p); - - players[i].angle_pos = READANGLE(save_p); - players[i].old_angle_pos = READANGLE(save_p); - - players[i].flyangle = READINT32(save_p); - players[i].drilltimer = READUINT32(save_p); - players[i].linkcount = READINT32(save_p); - players[i].linktimer = READUINT32(save_p); - players[i].anotherflyangle = READINT32(save_p); - players[i].nightstime = READUINT32(save_p); - players[i].bumpertime = READUINT32(save_p); - players[i].drillmeter = READINT32(save_p); - players[i].drilldelay = READUINT8(save_p); - players[i].bonustime = (boolean)READUINT8(save_p); - players[i].oldscale = READFIXED(save_p); - players[i].mare = READUINT8(save_p); - players[i].marelap = READUINT8(save_p); - players[i].marebonuslap = READUINT8(save_p); - players[i].marebegunat = READUINT32(save_p); - players[i].startedtime = READUINT32(save_p); - players[i].finishedtime = READUINT32(save_p); - players[i].lapbegunat = READUINT32(save_p); - players[i].lapstartedtime = READUINT32(save_p); - players[i].finishedspheres = READINT16(save_p); - players[i].finishedrings = READINT16(save_p); - players[i].marescore = READUINT32(save_p); - players[i].lastmarescore = READUINT32(save_p); - players[i].totalmarescore = READUINT32(save_p); - players[i].lastmare = READUINT8(save_p); - players[i].lastmarelap = READUINT8(save_p); - players[i].lastmarebonuslap = READUINT8(save_p); - players[i].totalmarelap = READUINT8(save_p); - players[i].totalmarebonuslap = READUINT8(save_p); - players[i].maxlink = READINT32(save_p); - players[i].texttimer = READUINT8(save_p); - players[i].textvar = READUINT8(save_p); - - players[i].lastsidehit = READINT16(save_p); - players[i].lastlinehit = READINT16(save_p); - - players[i].losstime = READUINT32(save_p); - - players[i].timeshit = READUINT8(save_p); - - players[i].onconveyor = READINT32(save_p); - - players[i].jointime = READUINT32(save_p); - players[i].quittime = READUINT32(save_p); - - flags = READUINT16(save_p); + players[i].ctfteam = P_ReadINT32(save_p); // 1 == Red, 2 == Blue + players[i].gotflag = P_ReadUINT16(save_p); // 1 == Red, 2 == Blue Do you have the flag? + + players[i].weapondelay = P_ReadINT32(save_p); + players[i].tossdelay = P_ReadINT32(save_p); + + players[i].starposttime = P_ReadUINT32(save_p); + players[i].starpostx = P_ReadINT16(save_p); + players[i].starposty = P_ReadINT16(save_p); + players[i].starpostz = P_ReadINT16(save_p); + players[i].starpostnum = P_ReadINT32(save_p); + players[i].starpostangle = P_ReadAngle(save_p); + players[i].starpostscale = P_ReadFixed(save_p); + + players[i].angle_pos = P_ReadAngle(save_p); + players[i].old_angle_pos = P_ReadAngle(save_p); + + players[i].flyangle = P_ReadINT32(save_p); + players[i].drilltimer = P_ReadUINT32(save_p); + players[i].linkcount = P_ReadINT32(save_p); + players[i].linktimer = P_ReadUINT32(save_p); + players[i].anotherflyangle = P_ReadINT32(save_p); + players[i].nightstime = P_ReadUINT32(save_p); + players[i].bumpertime = P_ReadUINT32(save_p); + players[i].drillmeter = P_ReadINT32(save_p); + players[i].drilldelay = P_ReadUINT8(save_p); + players[i].bonustime = (boolean)P_ReadUINT8(save_p); + players[i].oldscale = P_ReadFixed(save_p); + players[i].mare = P_ReadUINT8(save_p); + players[i].marelap = P_ReadUINT8(save_p); + players[i].marebonuslap = P_ReadUINT8(save_p); + players[i].marebegunat = P_ReadUINT32(save_p); + players[i].lastmaretime = P_ReadUINT32(save_p); + players[i].startedtime = P_ReadUINT32(save_p); + players[i].finishedtime = P_ReadUINT32(save_p); + players[i].lapbegunat = P_ReadUINT32(save_p); + players[i].lapstartedtime = P_ReadUINT32(save_p); + players[i].finishedspheres = P_ReadINT16(save_p); + players[i].finishedrings = P_ReadINT16(save_p); + players[i].marescore = P_ReadUINT32(save_p); + players[i].lastmarescore = P_ReadUINT32(save_p); + players[i].totalmarescore = P_ReadUINT32(save_p); + players[i].lastmare = P_ReadUINT8(save_p); + players[i].lastmarelap = P_ReadUINT8(save_p); + players[i].lastmarebonuslap = P_ReadUINT8(save_p); + players[i].totalmarelap = P_ReadUINT8(save_p); + players[i].totalmarebonuslap = P_ReadUINT8(save_p); + players[i].maxlink = P_ReadINT32(save_p); + players[i].texttimer = P_ReadUINT8(save_p); + players[i].textvar = P_ReadUINT8(save_p); + + players[i].lastsidehit = P_ReadINT16(save_p); + players[i].lastlinehit = P_ReadINT16(save_p); + + players[i].losstime = P_ReadUINT32(save_p); + + players[i].timeshit = P_ReadUINT8(save_p); + + players[i].onconveyor = P_ReadINT32(save_p); + + players[i].jointime = P_ReadUINT32(save_p); + players[i].quittime = P_ReadUINT32(save_p); + + flags = P_ReadUINT16(save_p); if (flags & CAPSULE) - players[i].capsule = (mobj_t *)(size_t)READUINT32(save_p); + players[i].capsule = (mobj_t *)(size_t)P_ReadUINT32(save_p); if (flags & FIRSTAXIS) - players[i].axis1 = (mobj_t *)(size_t)READUINT32(save_p); + players[i].axis1 = (mobj_t *)(size_t)P_ReadUINT32(save_p); if (flags & SECONDAXIS) - players[i].axis2 = (mobj_t *)(size_t)READUINT32(save_p); + players[i].axis2 = (mobj_t *)(size_t)P_ReadUINT32(save_p); if (flags & AWAYVIEW) - players[i].awayviewmobj = (mobj_t *)(size_t)READUINT32(save_p); + players[i].awayviewmobj = (mobj_t *)(size_t)P_ReadUINT32(save_p); if (flags & FOLLOW) - players[i].followmobj = (mobj_t *)(size_t)READUINT32(save_p); + players[i].followmobj = (mobj_t *)(size_t)P_ReadUINT32(save_p); if (flags & DRONE) - players[i].drone = (mobj_t *)(size_t)READUINT32(save_p); + players[i].drone = (mobj_t *)(size_t)P_ReadUINT32(save_p); - players[i].camerascale = READFIXED(save_p); - players[i].shieldscale = READFIXED(save_p); + players[i].camerascale = P_ReadFixed(save_p); + players[i].shieldscale = P_ReadFixed(save_p); //SetPlayerSkinByNum(i, players[i].skin); - players[i].charability = READUINT8(save_p); - players[i].charability2 = READUINT8(save_p); - players[i].charflags = READUINT32(save_p); - players[i].thokitem = (mobjtype_t)READUINT32(save_p); - players[i].spinitem = (mobjtype_t)READUINT32(save_p); - players[i].revitem = (mobjtype_t)READUINT32(save_p); - players[i].followitem = (mobjtype_t)READUINT32(save_p); - players[i].actionspd = READFIXED(save_p); - players[i].mindash = READFIXED(save_p); - players[i].maxdash = READFIXED(save_p); - players[i].normalspeed = READFIXED(save_p); - players[i].runspeed = READFIXED(save_p); - players[i].thrustfactor = READUINT8(save_p); - players[i].accelstart = READUINT8(save_p); - players[i].acceleration = READUINT8(save_p); - players[i].jumpfactor = READFIXED(save_p); - players[i].height = READFIXED(save_p); - players[i].spinheight = READFIXED(save_p); + players[i].charability = P_ReadUINT8(save_p); + players[i].charability2 = P_ReadUINT8(save_p); + players[i].charflags = P_ReadUINT32(save_p); + players[i].thokitem = P_ReadUINT32(save_p); + players[i].spinitem = P_ReadUINT32(save_p); + players[i].revitem = P_ReadUINT32(save_p); + players[i].followitem = P_ReadUINT32(save_p); + players[i].actionspd = P_ReadFixed(save_p); + players[i].mindash = P_ReadFixed(save_p); + players[i].maxdash = P_ReadFixed(save_p); + players[i].normalspeed = P_ReadFixed(save_p); + players[i].runspeed = P_ReadFixed(save_p); + players[i].thrustfactor = P_ReadUINT8(save_p); + players[i].accelstart = P_ReadUINT8(save_p); + players[i].acceleration = P_ReadUINT8(save_p); + players[i].jumpfactor = P_ReadFixed(save_p); + players[i].height = P_ReadFixed(save_p); + players[i].spinheight = P_ReadFixed(save_p); players[i].viewheight = 41*players[i].height/48; // scale cannot be factored in at this point } @@ -664,12 +908,12 @@ static void ClearNetColormaps(void) net_colormaps = NULL; } -static void P_NetArchiveColormaps(void) +static void P_NetArchiveColormaps(save_t *save_p) { // We save and then we clean up our colormap mess extracolormap_t *exc, *exc_next; UINT32 i = 0; - WRITEUINT32(save_p, num_net_colormaps); // save for safety + P_WriteUINT32(save_p, num_net_colormaps); // save for safety for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next) { @@ -678,15 +922,15 @@ static void P_NetArchiveColormaps(void) if (!exc) exc = R_CreateDefaultColormap(false); - WRITEUINT8(save_p, exc->fadestart); - WRITEUINT8(save_p, exc->fadeend); - WRITEUINT8(save_p, exc->flags); + P_WriteUINT8(save_p, exc->fadestart); + P_WriteUINT8(save_p, exc->fadeend); + P_WriteUINT8(save_p, exc->flags); - WRITEINT32(save_p, exc->rgba); - WRITEINT32(save_p, exc->fadergba); + P_WriteINT32(save_p, exc->rgba); + P_WriteINT32(save_p, exc->fadergba); #ifdef EXTRACOLORMAPLUMPS - WRITESTRINGN(save_p, exc->lumpname, 9); + P_WriteStringN(save_p, exc->lumpname, 9); #endif exc_next = exc->next; @@ -698,7 +942,7 @@ static void P_NetArchiveColormaps(void) net_colormaps = NULL; } -static void P_NetUnArchiveColormaps(void) +static void P_NetUnArchiveColormaps(save_t *save_p) { // When we reach this point, we already populated our list with // dummy colormaps. Now that we are loading the color data, @@ -706,7 +950,7 @@ static void P_NetUnArchiveColormaps(void) extracolormap_t *exc, *existing_exc, *exc_next = NULL; UINT32 i = 0; - num_net_colormaps = READUINT32(save_p); + num_net_colormaps = P_ReadUINT32(save_p); for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next) { @@ -716,15 +960,15 @@ static void P_NetUnArchiveColormaps(void) char lumpname[9]; #endif - fadestart = READUINT8(save_p); - fadeend = READUINT8(save_p); - flags = READUINT8(save_p); + fadestart = P_ReadUINT8(save_p); + fadeend = P_ReadUINT8(save_p); + flags = P_ReadUINT8(save_p); - rgba = READINT32(save_p); - fadergba = READINT32(save_p); + rgba = P_ReadINT32(save_p); + fadergba = P_ReadINT32(save_p); #ifdef EXTRACOLORMAPLUMPS - READSTRINGN(save_p, lumpname, 9); + P_ReadStringN(save_p, lumpname, 9); if (lumpname[0]) { @@ -800,29 +1044,29 @@ static void P_NetUnArchiveColormaps(void) net_colormaps = NULL; } -static void P_NetArchiveWaypoints(void) +static void P_NetArchiveWaypoints(save_t *save_p) { INT32 i, j; for (i = 0; i < NUMWAYPOINTSEQUENCES; i++) { - WRITEUINT16(save_p, numwaypoints[i]); + P_WriteUINT16(save_p, numwaypoints[i]); for (j = 0; j < numwaypoints[i]; j++) - WRITEUINT32(save_p, waypoints[i][j] ? waypoints[i][j]->mobjnum : 0); + P_WriteUINT32(save_p, waypoints[i][j] ? waypoints[i][j]->mobjnum : 0); } } -static void P_NetUnArchiveWaypoints(void) +static void P_NetUnArchiveWaypoints(save_t *save_p) { INT32 i, j; UINT32 mobjnum; for (i = 0; i < NUMWAYPOINTSEQUENCES; i++) { - numwaypoints[i] = READUINT16(save_p); + numwaypoints[i] = P_ReadUINT16(save_p); for (j = 0; j < numwaypoints[i]; j++) { - mobjnum = READUINT32(save_p); + mobjnum = P_ReadUINT32(save_p); waypoints[i][j] = (mobjnum == 0) ? NULL : P_FindNewPosition(mobjnum); } } @@ -915,7 +1159,11 @@ enum LD_SDMIDLIGHT = 1<<19, LD_SDBOTLIGHT = 1<<20, LD_SDREPEATCNT = 1<<21, - LD_SDFLAGS = 1<<22 + LD_SDFLAGS = 1<<22, + LD_SDLIGHTABS = 1<<23, + LD_SDTOPLIGHTABS = 1<<24, + LD_SDMIDLIGHTABS = 1<<25, + LD_SDBOTLIGHTABS = 1<<26 }; static boolean P_AreArgsEqual(const line_t *li, const line_t *spawnli) @@ -965,7 +1213,7 @@ static boolean CheckFFloorDiff(const sector_t *ss) // Special case: save the stats of all modified ffloors along with their ffloor "number"s // we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed -static void ArchiveFFloors(const sector_t *ss) +static void ArchiveFFloors(save_t *save_p, const sector_t *ss) { size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc ffloor_t *rover; @@ -980,19 +1228,19 @@ static void ArchiveFFloors(const sector_t *ss) if (fflr_diff) { - WRITEUINT16(save_p, j); // save ffloor "number" - WRITEUINT8(save_p, fflr_diff); + P_WriteUINT16(save_p, j); // save ffloor "number" + P_WriteUINT8(save_p, fflr_diff); if (fflr_diff & FD_FLAGS) - WRITEUINT32(save_p, rover->fofflags); + P_WriteUINT32(save_p, rover->fofflags); if (fflr_diff & FD_ALPHA) - WRITEINT16(save_p, rover->alpha); + P_WriteINT16(save_p, rover->alpha); } j++; } - WRITEUINT16(save_p, 0xffff); + P_WriteUINT16(save_p, 0xffff); } -static void UnArchiveFFloors(const sector_t *ss) +static void UnArchiveFFloors(save_t *save_p, const sector_t *ss) { UINT16 j = 0; // number of current ffloor in loop UINT16 fflr_i; // saved ffloor "number" of next modified ffloor @@ -1003,7 +1251,7 @@ static void UnArchiveFFloors(const sector_t *ss) if (!rover) // it is assumed sectors[i].ffloors actually exists, but just in case... I_Error("Sector does not have any ffloors!"); - fflr_i = READUINT16(save_p); // get first modified ffloor's number ready + fflr_i = P_ReadUINT16(save_p); // get first modified ffloor's number ready for (;;) // for some reason the usual for (rover = x; ...) thing doesn't work here? { if (fflr_i == 0xffff) // end of modified ffloors list, let's stop already @@ -1018,21 +1266,21 @@ static void UnArchiveFFloors(const sector_t *ss) continue; } - fflr_diff = READUINT8(save_p); + fflr_diff = P_ReadUINT8(save_p); if (fflr_diff & FD_FLAGS) - rover->fofflags = READUINT32(save_p); + rover->fofflags = P_ReadUINT32(save_p); if (fflr_diff & FD_ALPHA) - rover->alpha = READINT16(save_p); + rover->alpha = P_ReadINT16(save_p); - fflr_i = READUINT16(save_p); // get next ffloor "number" ready + fflr_i = P_ReadUINT16(save_p); // get next ffloor "number" ready j++; rover = rover->next; } } -static void ArchiveSectors(void) +static void ArchiveSectors(save_t *save_p) { size_t i, j; const sector_t *ss = sectors; @@ -1126,102 +1374,102 @@ static void ArchiveSectors(void) if (diff) { - WRITEUINT32(save_p, i); - WRITEUINT8(save_p, diff); + P_WriteUINT32(save_p, i); + P_WriteUINT8(save_p, diff); if (diff & SD_DIFF2) - WRITEUINT8(save_p, diff2); + P_WriteUINT8(save_p, diff2); if (diff2 & SD_DIFF3) - WRITEUINT8(save_p, diff3); + P_WriteUINT8(save_p, diff3); if (diff3 & SD_DIFF4) - WRITEUINT8(save_p, diff4); + P_WriteUINT8(save_p, diff4); if (diff4 & SD_DIFF5) - WRITEUINT8(save_p, diff5); + P_WriteUINT8(save_p, diff5); if (diff & SD_FLOORHT) - WRITEFIXED(save_p, ss->floorheight); + P_WriteFixed(save_p, ss->floorheight); if (diff & SD_CEILHT) - WRITEFIXED(save_p, ss->ceilingheight); + P_WriteFixed(save_p, ss->ceilingheight); if (diff & SD_FLOORPIC) - WRITEMEM(save_p, levelflats[ss->floorpic].name, 8); + P_WriteMem(save_p, levelflats[ss->floorpic].name, 8); if (diff & SD_CEILPIC) - WRITEMEM(save_p, levelflats[ss->ceilingpic].name, 8); + P_WriteMem(save_p, levelflats[ss->ceilingpic].name, 8); if (diff & SD_LIGHT) - WRITEINT16(save_p, ss->lightlevel); + P_WriteINT16(save_p, ss->lightlevel); if (diff & SD_SPECIAL) - WRITEINT16(save_p, ss->special); + P_WriteINT16(save_p, ss->special); if (diff2 & SD_FXOFFS) - WRITEFIXED(save_p, ss->floorxoffset); + P_WriteFixed(save_p, ss->floorxoffset); if (diff2 & SD_FYOFFS) - WRITEFIXED(save_p, ss->flooryoffset); + P_WriteFixed(save_p, ss->flooryoffset); if (diff2 & SD_CXOFFS) - WRITEFIXED(save_p, ss->ceilingxoffset); + P_WriteFixed(save_p, ss->ceilingxoffset); if (diff2 & SD_CYOFFS) - WRITEFIXED(save_p, ss->ceilingyoffset); + P_WriteFixed(save_p, ss->ceilingyoffset); if (diff2 & SD_FLOORANG) - WRITEANGLE(save_p, ss->floorangle); + P_WriteAngle(save_p, ss->floorangle); if (diff2 & SD_CEILANG) - WRITEANGLE(save_p, ss->ceilingangle); + P_WriteAngle(save_p, ss->ceilingangle); if (diff2 & SD_TAG) { - WRITEUINT32(save_p, ss->tags.count); + P_WriteUINT32(save_p, ss->tags.count); for (j = 0; j < ss->tags.count; j++) - WRITEINT16(save_p, ss->tags.tags[j]); + P_WriteINT16(save_p, ss->tags.tags[j]); } if (diff3 & SD_COLORMAP) - WRITEUINT32(save_p, CheckAddNetColormapToList(ss->extra_colormap)); + P_WriteUINT32(save_p, CheckAddNetColormapToList(ss->extra_colormap)); // returns existing index if already added, or appends to net_colormaps and returns new index if (diff3 & SD_CRUMBLESTATE) - WRITEINT32(save_p, ss->crumblestate); + P_WriteINT32(save_p, ss->crumblestate); if (diff3 & SD_FLOORLIGHT) { - WRITEINT16(save_p, ss->floorlightlevel); - WRITEUINT8(save_p, ss->floorlightabsolute); + P_WriteINT16(save_p, ss->floorlightlevel); + P_WriteUINT8(save_p, ss->floorlightabsolute); } if (diff3 & SD_CEILLIGHT) { - WRITEINT16(save_p, ss->ceilinglightlevel); - WRITEUINT8(save_p, ss->ceilinglightabsolute); + P_WriteINT16(save_p, ss->ceilinglightlevel); + P_WriteUINT8(save_p, ss->ceilinglightabsolute); } if (diff3 & SD_FLAG) - WRITEUINT32(save_p, ss->flags); + P_WriteUINT32(save_p, ss->flags); if (diff3 & SD_SPECIALFLAG) - WRITEUINT32(save_p, ss->specialflags); + P_WriteUINT32(save_p, ss->specialflags); if (diff4 & SD_DAMAGETYPE) - WRITEUINT8(save_p, ss->damagetype); + P_WriteUINT8(save_p, ss->damagetype); if (diff4 & SD_TRIGGERTAG) - WRITEINT16(save_p, ss->triggertag); + P_WriteINT16(save_p, ss->triggertag); if (diff4 & SD_TRIGGERER) - WRITEUINT8(save_p, ss->triggerer); + P_WriteUINT8(save_p, ss->triggerer); if (diff4 & SD_FXSCALE) - WRITEFIXED(save_p, ss->floorxscale); + P_WriteFixed(save_p, ss->floorxscale); if (diff4 & SD_FYSCALE) - WRITEFIXED(save_p, ss->flooryscale); + P_WriteFixed(save_p, ss->flooryscale); if (diff4 & SD_CXSCALE) - WRITEFIXED(save_p, ss->ceilingxscale); + P_WriteFixed(save_p, ss->ceilingxscale); if (diff4 & SD_CYSCALE) - WRITEFIXED(save_p, ss->ceilingyscale); + P_WriteFixed(save_p, ss->ceilingyscale); if (diff5 & SD_GRAVITY) - WRITEFIXED(save_p, ss->gravity); + P_WriteFixed(save_p, ss->gravity); if (diff5 & SD_FLOORPORTAL) - WRITEUINT32(save_p, ss->portal_floor); + P_WriteUINT32(save_p, ss->portal_floor); if (diff5 & SD_CEILPORTAL) - WRITEUINT32(save_p, ss->portal_ceiling); + P_WriteUINT32(save_p, ss->portal_ceiling); if (diff & SD_FFLOORS) - ArchiveFFloors(ss); + ArchiveFFloors(save_p, ss); } } - WRITEUINT32(save_p, 0xffffffff); + P_WriteUINT32(save_p, 0xffffffff); } -static void UnArchiveSectors(void) +static void UnArchiveSectors(save_t *save_p) { UINT32 i; UINT16 j; UINT8 diff, diff2, diff3, diff4, diff5; for (;;) { - i = READUINT32(save_p); + i = P_ReadUINT32(save_p); if (i == 0xffffffff) break; @@ -1229,58 +1477,58 @@ static void UnArchiveSectors(void) if (i > numsectors) I_Error("Invalid sector number %u from server (expected end at %s)", i, sizeu1(numsectors)); - diff = READUINT8(save_p); + diff = P_ReadUINT8(save_p); if (diff & SD_DIFF2) - diff2 = READUINT8(save_p); + diff2 = P_ReadUINT8(save_p); else diff2 = 0; if (diff2 & SD_DIFF3) - diff3 = READUINT8(save_p); + diff3 = P_ReadUINT8(save_p); else diff3 = 0; if (diff3 & SD_DIFF4) - diff4 = READUINT8(save_p); + diff4 = P_ReadUINT8(save_p); else diff4 = 0; if (diff4 & SD_DIFF5) - diff5 = READUINT8(save_p); + diff5 = P_ReadUINT8(save_p); else diff5 = 0; if (diff & SD_FLOORHT) - sectors[i].floorheight = READFIXED(save_p); + sectors[i].floorheight = P_ReadFixed(save_p); if (diff & SD_CEILHT) - sectors[i].ceilingheight = READFIXED(save_p); + sectors[i].ceilingheight = P_ReadFixed(save_p); if (diff & SD_FLOORPIC) { - sectors[i].floorpic = P_AddLevelFlatRuntime((char *)save_p); - save_p += 8; + sectors[i].floorpic = P_AddLevelFlatRuntime((char *)&save_p->buf[save_p->pos]); + save_p->pos += 8; } if (diff & SD_CEILPIC) { - sectors[i].ceilingpic = P_AddLevelFlatRuntime((char *)save_p); - save_p += 8; + sectors[i].ceilingpic = P_AddLevelFlatRuntime((char *)&save_p->buf[save_p->pos]); + save_p->pos += 8; } if (diff & SD_LIGHT) - sectors[i].lightlevel = READINT16(save_p); + sectors[i].lightlevel = P_ReadINT16(save_p); if (diff & SD_SPECIAL) - sectors[i].special = READINT16(save_p); + sectors[i].special = P_ReadINT16(save_p); if (diff2 & SD_FXOFFS) - sectors[i].floorxoffset = READFIXED(save_p); + sectors[i].floorxoffset = P_ReadFixed(save_p); if (diff2 & SD_FYOFFS) - sectors[i].flooryoffset = READFIXED(save_p); + sectors[i].flooryoffset = P_ReadFixed(save_p); if (diff2 & SD_CXOFFS) - sectors[i].ceilingxoffset = READFIXED(save_p); + sectors[i].ceilingxoffset = P_ReadFixed(save_p); if (diff2 & SD_CYOFFS) - sectors[i].ceilingyoffset = READFIXED(save_p); + sectors[i].ceilingyoffset = P_ReadFixed(save_p); if (diff2 & SD_FLOORANG) - sectors[i].floorangle = READANGLE(save_p); + sectors[i].floorangle = P_ReadAngle(save_p); if (diff2 & SD_CEILANG) - sectors[i].ceilingangle = READANGLE(save_p); + sectors[i].ceilingangle = P_ReadAngle(save_p); if (diff2 & SD_TAG) { - size_t ncount = READUINT32(save_p); + size_t ncount = P_ReadUINT32(save_p); // Remove entries from global lists. for (j = 0; j < sectors[i].tags.count; j++) @@ -1294,7 +1542,7 @@ static void UnArchiveSectors(void) } for (j = 0; j < ncount; j++) - sectors[i].tags.tags[j] = READINT16(save_p); + sectors[i].tags.tags[j] = P_ReadINT16(save_p); // Add new entries. for (j = 0; j < sectors[i].tags.count; j++) @@ -1303,49 +1551,49 @@ static void UnArchiveSectors(void) if (diff3 & SD_COLORMAP) - sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(save_p)); + sectors[i].extra_colormap = GetNetColormapFromList(P_ReadUINT32(save_p)); if (diff3 & SD_CRUMBLESTATE) - sectors[i].crumblestate = READINT32(save_p); + sectors[i].crumblestate = P_ReadINT32(save_p); if (diff3 & SD_FLOORLIGHT) { - sectors[i].floorlightlevel = READINT16(save_p); - sectors[i].floorlightabsolute = READUINT8(save_p); + sectors[i].floorlightlevel = P_ReadINT16(save_p); + sectors[i].floorlightabsolute = P_ReadUINT8(save_p); } if (diff3 & SD_CEILLIGHT) { - sectors[i].ceilinglightlevel = READINT16(save_p); - sectors[i].ceilinglightabsolute = READUINT8(save_p); + sectors[i].ceilinglightlevel = P_ReadINT16(save_p); + sectors[i].ceilinglightabsolute = P_ReadUINT8(save_p); } if (diff3 & SD_FLAG) { - sectors[i].flags = READUINT32(save_p); + sectors[i].flags = P_ReadUINT32(save_p); CheckForReverseGravity |= (sectors[i].flags & MSF_GRAVITYFLIP); } if (diff3 & SD_SPECIALFLAG) - sectors[i].specialflags = READUINT32(save_p); + sectors[i].specialflags = P_ReadUINT32(save_p); if (diff4 & SD_DAMAGETYPE) - sectors[i].damagetype = READUINT8(save_p); + sectors[i].damagetype = P_ReadUINT8(save_p); if (diff4 & SD_TRIGGERTAG) - sectors[i].triggertag = READINT16(save_p); + sectors[i].triggertag = P_ReadINT16(save_p); if (diff4 & SD_TRIGGERER) - sectors[i].triggerer = READUINT8(save_p); + sectors[i].triggerer = P_ReadUINT8(save_p); if (diff4 & SD_FXSCALE) - sectors[i].floorxscale = READFIXED(save_p); + sectors[i].floorxscale = P_ReadFixed(save_p); if (diff4 & SD_FYSCALE) - sectors[i].flooryscale = READFIXED(save_p); + sectors[i].flooryscale = P_ReadFixed(save_p); if (diff4 & SD_CXSCALE) - sectors[i].ceilingxscale = READFIXED(save_p); + sectors[i].ceilingxscale = P_ReadFixed(save_p); if (diff4 & SD_CYSCALE) - sectors[i].ceilingyscale = READFIXED(save_p); + sectors[i].ceilingyscale = P_ReadFixed(save_p); if (diff5 & SD_GRAVITY) - sectors[i].gravity = READFIXED(save_p); + sectors[i].gravity = P_ReadFixed(save_p); if (diff5 & SD_FLOORPORTAL) - sectors[i].portal_floor = READUINT32(save_p); + sectors[i].portal_floor = P_ReadUINT32(save_p); if (diff5 & SD_CEILPORTAL) - sectors[i].portal_ceiling = READUINT32(save_p); + sectors[i].portal_ceiling = P_ReadUINT32(save_p); if (diff & SD_FFLOORS) - UnArchiveFFloors(§ors[i]); + UnArchiveFFloors(save_p, §ors[i]); } } @@ -1389,52 +1637,84 @@ static UINT32 GetSideDiff(const side_t *si, const side_t *spawnsi) diff |= LD_SDBOTSCALEY; if (si->repeatcnt != spawnsi->repeatcnt) diff |= LD_SDREPEATCNT; + if (si->light != spawnsi->light) + diff |= LD_SDLIGHT; + if (si->light_top != spawnsi->light_top) + diff |= LD_SDTOPLIGHT; + if (si->light_mid != spawnsi->light_mid) + diff |= LD_SDMIDLIGHT; + if (si->light_bottom != spawnsi->light_bottom) + diff |= LD_SDBOTLIGHT; + if (si->lightabsolute != spawnsi->lightabsolute) + diff |= LD_SDLIGHTABS; + if (si->lightabsolute_top != spawnsi->lightabsolute_top) + diff |= LD_SDTOPLIGHTABS; + if (si->lightabsolute_mid != spawnsi->lightabsolute_mid) + diff |= LD_SDMIDLIGHTABS; + if (si->lightabsolute_bottom != spawnsi->lightabsolute_bottom) + diff |= LD_SDBOTLIGHTABS; return diff; } -static void ArchiveSide(const side_t *si, UINT32 diff) +static void ArchiveSide(save_t *save_p, const side_t *si, UINT32 diff) { - WRITEUINT32(save_p, diff); + P_WriteUINT32(save_p, diff); if (diff & LD_SDTEXOFFX) - WRITEFIXED(save_p, si->textureoffset); + P_WriteFixed(save_p, si->textureoffset); if (diff & LD_SDTEXOFFY) - WRITEFIXED(save_p, si->rowoffset); + P_WriteFixed(save_p, si->rowoffset); if (diff & LD_SDTOPTEX) - WRITEINT32(save_p, si->toptexture); + P_WriteINT32(save_p, si->toptexture); if (diff & LD_SDBOTTEX) - WRITEINT32(save_p, si->bottomtexture); + P_WriteINT32(save_p, si->bottomtexture); if (diff & LD_SDMIDTEX) - WRITEINT32(save_p, si->midtexture); + P_WriteINT32(save_p, si->midtexture); if (diff & LD_SDTOPOFFX) - WRITEFIXED(save_p, si->offsetx_top); + P_WriteFixed(save_p, si->offsetx_top); if (diff & LD_SDMIDOFFX) - WRITEFIXED(save_p, si->offsetx_mid); + P_WriteFixed(save_p, si->offsetx_mid); if (diff & LD_SDBOTOFFX) - WRITEFIXED(save_p, si->offsetx_bottom); + P_WriteFixed(save_p, si->offsetx_bottom); if (diff & LD_SDTOPOFFY) - WRITEFIXED(save_p, si->offsety_top); + P_WriteFixed(save_p, si->offsety_top); if (diff & LD_SDMIDOFFY) - WRITEFIXED(save_p, si->offsety_mid); + P_WriteFixed(save_p, si->offsety_mid); if (diff & LD_SDBOTOFFY) - WRITEFIXED(save_p, si->offsety_bottom); + P_WriteFixed(save_p, si->offsety_bottom); if (diff & LD_SDTOPSCALEX) - WRITEFIXED(save_p, si->scalex_top); + P_WriteFixed(save_p, si->scalex_top); if (diff & LD_SDMIDSCALEX) - WRITEFIXED(save_p, si->scalex_mid); + P_WriteFixed(save_p, si->scalex_mid); if (diff & LD_SDBOTSCALEX) - WRITEFIXED(save_p, si->scalex_bottom); + P_WriteFixed(save_p, si->scalex_bottom); if (diff & LD_SDTOPSCALEY) - WRITEFIXED(save_p, si->scaley_top); + P_WriteFixed(save_p, si->scaley_top); if (diff & LD_SDMIDSCALEY) - WRITEFIXED(save_p, si->scaley_mid); + P_WriteFixed(save_p, si->scaley_mid); if (diff & LD_SDBOTSCALEY) - WRITEFIXED(save_p, si->scaley_bottom); + P_WriteFixed(save_p, si->scaley_bottom); if (diff & LD_SDREPEATCNT) - WRITEINT16(save_p, si->repeatcnt); -} - -static void ArchiveLines(void) + P_WriteINT16(save_p, si->repeatcnt); + if (diff & LD_SDLIGHT) + P_WriteINT16(save_p, si->light); + if (diff & LD_SDTOPLIGHT) + P_WriteINT16(save_p, si->light_top); + if (diff & LD_SDMIDLIGHT) + P_WriteINT16(save_p, si->light_mid); + if (diff & LD_SDBOTLIGHT) + P_WriteINT16(save_p, si->light_bottom); + if (diff & LD_SDLIGHTABS) + P_WriteUINT8(save_p, si->lightabsolute); + if (diff & LD_SDTOPLIGHTABS) + P_WriteUINT8(save_p, si->lightabsolute_top); + if (diff & LD_SDMIDLIGHTABS) + P_WriteUINT8(save_p, si->lightabsolute_mid); + if (diff & LD_SDBOTLIGHTABS) + P_WriteUINT8(save_p, si->lightabsolute_bottom); +} + +static void ArchiveLines(save_t *save_p) { size_t i; const line_t *li = lines; @@ -1484,21 +1764,21 @@ static void ArchiveLines(void) if (diff) { - WRITEUINT32(save_p, i); - WRITEUINT8(save_p, diff); + P_WriteUINT32(save_p, i); + P_WriteUINT8(save_p, diff); if (diff & LD_DIFF2) - WRITEUINT8(save_p, diff2); + P_WriteUINT8(save_p, diff2); if (diff & LD_FLAG) - WRITEINT16(save_p, li->flags); + P_WriteINT16(save_p, li->flags); if (diff & LD_SPECIAL) - WRITEINT16(save_p, li->special); + P_WriteINT16(save_p, li->special); if (diff & LD_CLLCOUNT) - WRITEINT16(save_p, li->callcount); + P_WriteINT16(save_p, li->callcount); if (diff & LD_ARGS) { UINT8 j; for (j = 0; j < NUMLINEARGS; j++) - WRITEINT32(save_p, li->args[j]); + P_WriteINT32(save_p, li->args[j]); } if (diff & LD_STRINGARGS) { @@ -1509,72 +1789,88 @@ static void ArchiveLines(void) if (!li->stringargs[j]) { - WRITEINT32(save_p, 0); + P_WriteINT32(save_p, 0); continue; } len = strlen(li->stringargs[j]); - WRITEINT32(save_p, len); + P_WriteINT32(save_p, len); for (k = 0; k < len; k++) - WRITECHAR(save_p, li->stringargs[j][k]); + P_WriteChar(save_p, li->stringargs[j][k]); } } if (diff & LD_SIDE1) - ArchiveSide(&sides[li->sidenum[0]], side1diff); + ArchiveSide(save_p, &sides[li->sidenum[0]], side1diff); if (diff & LD_SIDE2) - ArchiveSide(&sides[li->sidenum[1]], side2diff); + ArchiveSide(save_p, &sides[li->sidenum[1]], side2diff); if (diff2 & LD_EXECUTORDELAY) - WRITEINT32(save_p, li->executordelay); + P_WriteINT32(save_p, li->executordelay); if (diff2 & LD_TRANSFPORTAL) - WRITEUINT32(save_p, li->secportal); + P_WriteUINT32(save_p, li->secportal); } } - WRITEUINT32(save_p, 0xffffffff); + P_WriteUINT32(save_p, 0xffffffff); } -static void UnArchiveSide(side_t *si) +static void UnArchiveSide(save_t *save_p, side_t *si) { - UINT32 diff = READUINT32(save_p); + UINT32 diff = P_ReadUINT32(save_p); if (diff & LD_SDTEXOFFX) - si->textureoffset = READFIXED(save_p); + si->textureoffset = P_ReadFixed(save_p); if (diff & LD_SDTEXOFFY) - si->rowoffset = READFIXED(save_p); + si->rowoffset = P_ReadFixed(save_p); if (diff & LD_SDTOPTEX) - si->toptexture = READINT32(save_p); + si->toptexture = P_ReadINT32(save_p); if (diff & LD_SDBOTTEX) - si->bottomtexture = READINT32(save_p); + si->bottomtexture = P_ReadINT32(save_p); if (diff & LD_SDMIDTEX) - si->midtexture = READINT32(save_p); + si->midtexture = P_ReadINT32(save_p); if (diff & LD_SDTOPOFFX) - si->offsetx_top = READFIXED(save_p); + si->offsetx_top = P_ReadFixed(save_p); if (diff & LD_SDMIDOFFX) - si->offsetx_mid = READFIXED(save_p); + si->offsetx_mid = P_ReadFixed(save_p); if (diff & LD_SDBOTOFFX) - si->offsetx_bottom = READFIXED(save_p); + si->offsetx_bottom = P_ReadFixed(save_p); if (diff & LD_SDTOPOFFY) - si->offsety_top = READFIXED(save_p); + si->offsety_top = P_ReadFixed(save_p); if (diff & LD_SDMIDOFFY) - si->offsety_mid = READFIXED(save_p); + si->offsety_mid = P_ReadFixed(save_p); if (diff & LD_SDBOTOFFY) - si->offsety_bottom = READFIXED(save_p); + si->offsety_bottom = P_ReadFixed(save_p); if (diff & LD_SDTOPSCALEX) - si->scalex_top = READFIXED(save_p); + si->scalex_top = P_ReadFixed(save_p); if (diff & LD_SDMIDSCALEX) - si->scalex_mid = READFIXED(save_p); + si->scalex_mid = P_ReadFixed(save_p); if (diff & LD_SDBOTSCALEX) - si->scalex_bottom = READFIXED(save_p); + si->scalex_bottom = P_ReadFixed(save_p); if (diff & LD_SDTOPSCALEY) - si->scaley_top = READFIXED(save_p); + si->scaley_top = P_ReadFixed(save_p); if (diff & LD_SDMIDSCALEY) - si->scaley_mid = READFIXED(save_p); + si->scaley_mid = P_ReadFixed(save_p); if (diff & LD_SDBOTSCALEY) - si->scaley_bottom = READFIXED(save_p); + si->scaley_bottom = P_ReadFixed(save_p); if (diff & LD_SDREPEATCNT) - si->repeatcnt = READINT16(save_p); -} - -static void UnArchiveLines(void) + si->repeatcnt = P_ReadINT16(save_p); + if (diff & LD_SDLIGHT) + si->light = P_ReadINT16(save_p); + if (diff & LD_SDTOPLIGHT) + si->light_top = P_ReadINT16(save_p); + if (diff & LD_SDMIDLIGHT) + si->light_mid = P_ReadINT16(save_p); + if (diff & LD_SDBOTLIGHT) + si->light_bottom = P_ReadINT16(save_p); + if (diff & LD_SDLIGHTABS) + si->lightabsolute = P_ReadUINT8(save_p); + if (diff & LD_SDTOPLIGHTABS) + si->lightabsolute_top = P_ReadUINT8(save_p); + if (diff & LD_SDMIDLIGHTABS) + si->lightabsolute_mid = P_ReadUINT8(save_p); + if (diff & LD_SDBOTLIGHTABS) + si->lightabsolute_bottom = P_ReadUINT8(save_p); +} + +static void UnArchiveLines(save_t *save_p) { UINT32 i; line_t *li; @@ -1582,38 +1878,38 @@ static void UnArchiveLines(void) for (;;) { - i = READUINT32(save_p); + i = P_ReadUINT32(save_p); if (i == 0xffffffff) break; if (i > numlines) I_Error("Invalid line number %u from server", i); - diff = READUINT8(save_p); + diff = P_ReadUINT8(save_p); if (diff & LD_DIFF2) - diff2 = READUINT8(save_p); + diff2 = P_ReadUINT8(save_p); else diff2 = 0; li = &lines[i]; if (diff & LD_FLAG) - li->flags = READINT16(save_p); + li->flags = P_ReadINT16(save_p); if (diff & LD_SPECIAL) - li->special = READINT16(save_p); + li->special = P_ReadINT16(save_p); if (diff & LD_CLLCOUNT) - li->callcount = READINT16(save_p); + li->callcount = P_ReadINT16(save_p); if (diff & LD_ARGS) { UINT8 j; for (j = 0; j < NUMLINEARGS; j++) - li->args[j] = READINT32(save_p); + li->args[j] = P_ReadINT32(save_p); } if (diff & LD_STRINGARGS) { UINT8 j; for (j = 0; j < NUMLINESTRINGARGS; j++) { - size_t len = READINT32(save_p); + size_t len = P_ReadINT32(save_p); size_t k; if (!len) @@ -1625,38 +1921,38 @@ static void UnArchiveLines(void) li->stringargs[j] = Z_Realloc(li->stringargs[j], len + 1, PU_LEVEL, NULL); for (k = 0; k < len; k++) - li->stringargs[j][k] = READCHAR(save_p); + li->stringargs[j][k] = P_ReadChar(save_p); li->stringargs[j][len] = '\0'; } } if (diff & LD_SIDE1) - UnArchiveSide(&sides[li->sidenum[0]]); + UnArchiveSide(save_p, &sides[li->sidenum[0]]); if (diff & LD_SIDE2) - UnArchiveSide(&sides[li->sidenum[1]]); + UnArchiveSide(save_p, &sides[li->sidenum[1]]); if (diff2 & LD_EXECUTORDELAY) - li->executordelay = READINT32(save_p); + li->executordelay = P_ReadINT32(save_p); if (diff2 & LD_TRANSFPORTAL) - li->secportal = READUINT32(save_p); + li->secportal = P_ReadUINT32(save_p); } } -static void P_NetArchiveWorld(void) +static void P_NetArchiveWorld(save_t *save_p) { // initialize colormap vars because paranoia ClearNetColormaps(); - WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD); + P_WriteUINT32(save_p, ARCHIVEBLOCK_WORLD); - ArchiveSectors(); - ArchiveLines(); + ArchiveSectors(save_p); + ArchiveLines(save_p); R_ClearTextureNumCache(false); } -static void P_NetUnArchiveWorld(void) +static void P_NetUnArchiveWorld(save_t *save_p) { UINT16 i; - if (READUINT32(save_p) != ARCHIVEBLOCK_WORLD) + if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_WORLD) I_Error("Bad $$$.sav at archive block World"); // initialize colormap vars because paranoia @@ -1670,8 +1966,8 @@ static void P_NetUnArchiveWorld(void) num_ffloors++; } - UnArchiveSectors(); - UnArchiveLines(); + UnArchiveSectors(save_p); + UnArchiveLines(save_p); } // @@ -1742,7 +2038,8 @@ typedef enum MD2_DISPOFFSET = 1<<23, MD2_DRAWONLYFORPLAYER = 1<<24, MD2_DONTDRAWFORVIEWMOBJ = 1<<25, - MD2_TRANSLATION = 1<<26 + MD2_TRANSLATION = 1<<26, + MD2_ALPHA = 1<<27 } mobj_diff2_t; typedef enum @@ -1821,7 +2118,7 @@ static UINT32 SaveSlope(const pslope_t *slope) return 0xFFFFFFFF; } -static void SaveMobjThinker(const thinker_t *th, const UINT8 type) +static void SaveMobjThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const mobj_t *mobj = (const mobj_t *)th; UINT32 diff; @@ -1880,7 +2177,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff |= MD_TICS; if (mobj->sprite != mobj->state->sprite) diff |= MD_SPRITE; - if (mobj->sprite == SPR_PLAY && mobj->sprite2 != (mobj->state->frame&FF_FRAMEMASK)) + if (mobj->sprite == SPR_PLAY && mobj->sprite2 != P_GetStateSprite2(mobj->state)) diff |= MD_SPRITE; if (mobj->frame != mobj->state->frame) diff |= MD_FRAME; @@ -1985,6 +2282,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff2 |= MD2_DONTDRAWFORVIEWMOBJ; if (mobj->dispoffset != mobj->info->dispoffset) diff2 |= MD2_DISPOFFSET; + if (mobj->alpha != FRACUNIT) + diff2 |= MD2_ALPHA; if (diff2 != 0) diff |= MD_MORE; @@ -1993,28 +2292,28 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) if (mobj->type == MT_HOOPCENTER) diff = MD_SPAWNPOINT; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, diff); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, diff); if (diff & MD_MORE) - WRITEUINT32(save_p, diff2); + P_WriteUINT32(save_p, diff2); // save pointer, at load time we will search this pointer to reinitilize pointers - WRITEUINT32(save_p, (size_t)mobj); + P_WriteUINT32(save_p, (size_t)mobj); - WRITEFIXED(save_p, mobj->z); // Force this so 3dfloor problems don't arise. - WRITEFIXED(save_p, mobj->floorz); - WRITEFIXED(save_p, mobj->ceilingz); + P_WriteFixed(save_p, mobj->z); // Force this so 3dfloor problems don't arise. + P_WriteFixed(save_p, mobj->floorz); + P_WriteFixed(save_p, mobj->ceilingz); if (diff2 & MD2_FLOORROVER) { - WRITEUINT32(save_p, SaveSector(mobj->floorrover->target)); - WRITEUINT16(save_p, P_GetFFloorID(mobj->floorrover)); + P_WriteUINT32(save_p, SaveSector(mobj->floorrover->target)); + P_WriteUINT16(save_p, P_GetFFloorID(mobj->floorrover)); } if (diff2 & MD2_CEILINGROVER) { - WRITEUINT32(save_p, SaveSector(mobj->ceilingrover->target)); - WRITEUINT16(save_p, P_GetFFloorID(mobj->ceilingrover)); + P_WriteUINT32(save_p, SaveSector(mobj->ceilingrover->target)); + P_WriteUINT16(save_p, P_GetFFloorID(mobj->ceilingrover)); } if (diff & MD_SPAWNPOINT) @@ -2023,647 +2322,649 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) for (z = 0; z < nummapthings; z++) if (&mapthings[z] == mobj->spawnpoint) - WRITEUINT16(save_p, z); + P_WriteUINT16(save_p, z); if (mobj->type == MT_HOOPCENTER) return; } if (diff & MD_TYPE) - WRITEUINT32(save_p, mobj->type); + P_WriteUINT32(save_p, mobj->type); if (diff & MD_POS) { - WRITEFIXED(save_p, mobj->x); - WRITEFIXED(save_p, mobj->y); - WRITEANGLE(save_p, mobj->angle); - WRITEANGLE(save_p, mobj->pitch); - WRITEANGLE(save_p, mobj->roll); + P_WriteFixed(save_p, mobj->x); + P_WriteFixed(save_p, mobj->y); + P_WriteAngle(save_p, mobj->angle); + P_WriteAngle(save_p, mobj->pitch); + P_WriteAngle(save_p, mobj->roll); } if (diff & MD_MOM) { - WRITEFIXED(save_p, mobj->momx); - WRITEFIXED(save_p, mobj->momy); - WRITEFIXED(save_p, mobj->momz); - WRITEFIXED(save_p, mobj->pmomz); + P_WriteFixed(save_p, mobj->momx); + P_WriteFixed(save_p, mobj->momy); + P_WriteFixed(save_p, mobj->momz); + P_WriteFixed(save_p, mobj->pmomz); } if (diff & MD_RADIUS) - WRITEFIXED(save_p, mobj->radius); + P_WriteFixed(save_p, mobj->radius); if (diff & MD_HEIGHT) - WRITEFIXED(save_p, mobj->height); + P_WriteFixed(save_p, mobj->height); if (diff & MD_FLAGS) - WRITEUINT32(save_p, mobj->flags); + P_WriteUINT32(save_p, mobj->flags); if (diff & MD_FLAGS2) - WRITEUINT32(save_p, mobj->flags2); + P_WriteUINT32(save_p, mobj->flags2); if (diff & MD_HEALTH) - WRITEINT32(save_p, mobj->health); + P_WriteINT32(save_p, mobj->health); if (diff & MD_RTIME) - WRITEINT32(save_p, mobj->reactiontime); + P_WriteINT32(save_p, mobj->reactiontime); if (diff & MD_STATE) - WRITEUINT16(save_p, mobj->state-states); + P_WriteUINT16(save_p, mobj->state-states); if (diff & MD_TICS) - WRITEINT32(save_p, mobj->tics); + P_WriteINT32(save_p, mobj->tics); if (diff & MD_SPRITE) { - WRITEUINT16(save_p, mobj->sprite); + P_WriteUINT16(save_p, mobj->sprite); if (mobj->sprite == SPR_PLAY) - WRITEUINT8(save_p, mobj->sprite2); + P_WriteUINT16(save_p, mobj->sprite2); } if (diff & MD_FRAME) { - WRITEUINT32(save_p, mobj->frame); - WRITEUINT16(save_p, mobj->anim_duration); + P_WriteUINT32(save_p, mobj->frame); + P_WriteUINT16(save_p, mobj->anim_duration); } if (diff & MD_EFLAGS) - WRITEUINT16(save_p, mobj->eflags); + P_WriteUINT16(save_p, mobj->eflags); if (diff & MD_PLAYER) - WRITEUINT8(save_p, mobj->player-players); + P_WriteUINT8(save_p, mobj->player-players); if (diff & MD_MOVEDIR) - WRITEANGLE(save_p, mobj->movedir); + P_WriteAngle(save_p, mobj->movedir); if (diff & MD_MOVECOUNT) - WRITEINT32(save_p, mobj->movecount); + P_WriteINT32(save_p, mobj->movecount); if (diff & MD_THRESHOLD) - WRITEINT32(save_p, mobj->threshold); + P_WriteINT32(save_p, mobj->threshold); if (diff & MD_LASTLOOK) - WRITEINT32(save_p, mobj->lastlook); + P_WriteINT32(save_p, mobj->lastlook); if (diff & MD_TARGET) - WRITEUINT32(save_p, mobj->target->mobjnum); + P_WriteUINT32(save_p, mobj->target->mobjnum); if (diff & MD_TRACER) - WRITEUINT32(save_p, mobj->tracer->mobjnum); + P_WriteUINT32(save_p, mobj->tracer->mobjnum); if (diff & MD_FRICTION) - WRITEFIXED(save_p, mobj->friction); + P_WriteFixed(save_p, mobj->friction); if (diff & MD_MOVEFACTOR) - WRITEFIXED(save_p, mobj->movefactor); + P_WriteFixed(save_p, mobj->movefactor); if (diff & MD_FUSE) - WRITEINT32(save_p, mobj->fuse); + P_WriteINT32(save_p, mobj->fuse); if (diff & MD_WATERTOP) - WRITEFIXED(save_p, mobj->watertop); + P_WriteFixed(save_p, mobj->watertop); if (diff & MD_WATERBOTTOM) - WRITEFIXED(save_p, mobj->waterbottom); + P_WriteFixed(save_p, mobj->waterbottom); if (diff & MD_SCALE) - WRITEFIXED(save_p, mobj->scale); + P_WriteFixed(save_p, mobj->scale); if (diff & MD_DSCALE) - WRITEFIXED(save_p, mobj->destscale); + P_WriteFixed(save_p, mobj->destscale); if (diff2 & MD2_SCALESPEED) - WRITEFIXED(save_p, mobj->scalespeed); + P_WriteFixed(save_p, mobj->scalespeed); if (diff2 & MD2_CUSVAL) - WRITEINT32(save_p, mobj->cusval); + P_WriteINT32(save_p, mobj->cusval); if (diff2 & MD2_CVMEM) - WRITEINT32(save_p, mobj->cvmem); + P_WriteINT32(save_p, mobj->cvmem); if (diff2 & MD2_SKIN) - WRITEUINT8(save_p, (UINT8)(((skin_t *)mobj->skin)->skinnum)); + P_WriteUINT8(save_p, (UINT8)(((skin_t *)mobj->skin)->skinnum)); if (diff2 & MD2_COLOR) - WRITEUINT16(save_p, mobj->color); + P_WriteUINT16(save_p, mobj->color); if (diff2 & MD2_EXTVAL1) - WRITEINT32(save_p, mobj->extravalue1); + P_WriteINT32(save_p, mobj->extravalue1); if (diff2 & MD2_EXTVAL2) - WRITEINT32(save_p, mobj->extravalue2); + P_WriteINT32(save_p, mobj->extravalue2); if (diff2 & MD2_HNEXT) - WRITEUINT32(save_p, mobj->hnext->mobjnum); + P_WriteUINT32(save_p, mobj->hnext->mobjnum); if (diff2 & MD2_HPREV) - WRITEUINT32(save_p, mobj->hprev->mobjnum); + P_WriteUINT32(save_p, mobj->hprev->mobjnum); if (diff2 & MD2_SLOPE) - WRITEUINT16(save_p, mobj->standingslope->id); + P_WriteUINT16(save_p, mobj->standingslope->id); if (diff2 & MD2_COLORIZED) - WRITEUINT8(save_p, mobj->colorized); + P_WriteUINT8(save_p, mobj->colorized); if (diff2 & MD2_MIRRORED) - WRITEUINT8(save_p, mobj->mirrored); + P_WriteUINT8(save_p, mobj->mirrored); if (diff2 & MD2_SPRITEROLL) - WRITEANGLE(save_p, mobj->spriteroll); + P_WriteAngle(save_p, mobj->spriteroll); if (diff2 & MD2_SHADOWSCALE) - WRITEFIXED(save_p, mobj->shadowscale); + P_WriteFixed(save_p, mobj->shadowscale); if (diff2 & MD2_RENDERFLAGS) - WRITEUINT32(save_p, mobj->renderflags); + P_WriteUINT32(save_p, mobj->renderflags); if (diff2 & MD2_BLENDMODE) - WRITEINT32(save_p, mobj->blendmode); + P_WriteINT32(save_p, mobj->blendmode); if (diff2 & MD2_SPRITEXSCALE) - WRITEFIXED(save_p, mobj->spritexscale); + P_WriteFixed(save_p, mobj->spritexscale); if (diff2 & MD2_SPRITEYSCALE) - WRITEFIXED(save_p, mobj->spriteyscale); + P_WriteFixed(save_p, mobj->spriteyscale); if (diff2 & MD2_SPRITEXOFFSET) - WRITEFIXED(save_p, mobj->spritexoffset); + P_WriteFixed(save_p, mobj->spritexoffset); if (diff2 & MD2_SPRITEYOFFSET) - WRITEFIXED(save_p, mobj->spriteyoffset); + P_WriteFixed(save_p, mobj->spriteyoffset); if (diff2 & MD2_FLOORSPRITESLOPE) { pslope_t *slope = mobj->floorspriteslope; - WRITEFIXED(save_p, slope->zdelta); - WRITEANGLE(save_p, slope->zangle); - WRITEANGLE(save_p, slope->xydirection); + P_WriteFixed(save_p, slope->zdelta); + P_WriteAngle(save_p, slope->zangle); + P_WriteAngle(save_p, slope->xydirection); - WRITEFIXED(save_p, slope->o.x); - WRITEFIXED(save_p, slope->o.y); - WRITEFIXED(save_p, slope->o.z); + P_WriteFixed(save_p, slope->o.x); + P_WriteFixed(save_p, slope->o.y); + P_WriteFixed(save_p, slope->o.z); - WRITEFIXED(save_p, slope->d.x); - WRITEFIXED(save_p, slope->d.y); + P_WriteFixed(save_p, slope->d.x); + P_WriteFixed(save_p, slope->d.y); - WRITEFIXED(save_p, slope->normal.x); - WRITEFIXED(save_p, slope->normal.y); - WRITEFIXED(save_p, slope->normal.z); + P_WriteFixed(save_p, slope->normal.x); + P_WriteFixed(save_p, slope->normal.y); + P_WriteFixed(save_p, slope->normal.z); } if (diff2 & MD2_DRAWONLYFORPLAYER) - WRITEUINT8(save_p, mobj->drawonlyforplayer-players); + P_WriteUINT8(save_p, mobj->drawonlyforplayer-players); if (diff2 & MD2_DONTDRAWFORVIEWMOBJ) - WRITEUINT32(save_p, mobj->dontdrawforviewmobj->mobjnum); + P_WriteUINT32(save_p, mobj->dontdrawforviewmobj->mobjnum); if (diff2 & MD2_DISPOFFSET) - WRITEINT32(save_p, mobj->dispoffset); + P_WriteINT32(save_p, mobj->dispoffset); if (diff2 & MD2_TRANSLATION) - WRITEUINT16(save_p, mobj->translation); + P_WriteUINT16(save_p, mobj->translation); + if (diff2 & MD2_ALPHA) + P_WriteFixed(save_p, mobj->alpha); - WRITEUINT32(save_p, mobj->mobjnum); + P_WriteUINT32(save_p, mobj->mobjnum); } -static void SaveNoEnemiesThinker(const thinker_t *th, const UINT8 type) +static void SaveNoEnemiesThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const noenemies_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveLine(ht->sourceline)); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveLine(ht->sourceline)); } -static void SaveBounceCheeseThinker(const thinker_t *th, const UINT8 type) +static void SaveBounceCheeseThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const bouncecheese_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveLine(ht->sourceline)); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEFIXED(save_p, ht->speed); - WRITEFIXED(save_p, ht->distance); - WRITEFIXED(save_p, ht->floorwasheight); - WRITEFIXED(save_p, ht->ceilingwasheight); - WRITECHAR(save_p, ht->low); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveLine(ht->sourceline)); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteFixed(save_p, ht->speed); + P_WriteFixed(save_p, ht->distance); + P_WriteFixed(save_p, ht->floorwasheight); + P_WriteFixed(save_p, ht->ceilingwasheight); + P_WriteChar(save_p, ht->low); } -static void SaveContinuousFallThinker(const thinker_t *th, const UINT8 type) +static void SaveContinuousFallThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const continuousfall_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEFIXED(save_p, ht->speed); - WRITEINT32(save_p, ht->direction); - WRITEFIXED(save_p, ht->floorstartheight); - WRITEFIXED(save_p, ht->ceilingstartheight); - WRITEFIXED(save_p, ht->destheight); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteFixed(save_p, ht->speed); + P_WriteINT32(save_p, ht->direction); + P_WriteFixed(save_p, ht->floorstartheight); + P_WriteFixed(save_p, ht->ceilingstartheight); + P_WriteFixed(save_p, ht->destheight); } -static void SaveMarioBlockThinker(const thinker_t *th, const UINT8 type) +static void SaveMarioBlockThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const mariothink_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEFIXED(save_p, ht->speed); - WRITEINT32(save_p, ht->direction); - WRITEFIXED(save_p, ht->floorstartheight); - WRITEFIXED(save_p, ht->ceilingstartheight); - WRITEINT16(save_p, ht->tag); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteFixed(save_p, ht->speed); + P_WriteINT32(save_p, ht->direction); + P_WriteFixed(save_p, ht->floorstartheight); + P_WriteFixed(save_p, ht->ceilingstartheight); + P_WriteINT16(save_p, ht->tag); } -static void SaveMarioCheckThinker(const thinker_t *th, const UINT8 type) +static void SaveMarioCheckThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const mariocheck_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveLine(ht->sourceline)); - WRITEUINT32(save_p, SaveSector(ht->sector)); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveLine(ht->sourceline)); + P_WriteUINT32(save_p, SaveSector(ht->sector)); } -static void SaveThwompThinker(const thinker_t *th, const UINT8 type) +static void SaveThwompThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const thwomp_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveLine(ht->sourceline)); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEFIXED(save_p, ht->crushspeed); - WRITEFIXED(save_p, ht->retractspeed); - WRITEINT32(save_p, ht->direction); - WRITEFIXED(save_p, ht->floorstartheight); - WRITEFIXED(save_p, ht->ceilingstartheight); - WRITEINT32(save_p, ht->delay); - WRITEINT16(save_p, ht->tag); - WRITEUINT16(save_p, ht->sound); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveLine(ht->sourceline)); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteFixed(save_p, ht->crushspeed); + P_WriteFixed(save_p, ht->retractspeed); + P_WriteINT32(save_p, ht->direction); + P_WriteFixed(save_p, ht->floorstartheight); + P_WriteFixed(save_p, ht->ceilingstartheight); + P_WriteINT32(save_p, ht->delay); + P_WriteINT16(save_p, ht->tag); + P_WriteUINT16(save_p, ht->sound); } -static void SaveFloatThinker(const thinker_t *th, const UINT8 type) +static void SaveFloatThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const floatthink_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveLine(ht->sourceline)); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEINT16(save_p, ht->tag); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveLine(ht->sourceline)); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteINT16(save_p, ht->tag); } -static void SaveEachTimeThinker(const thinker_t *th, const UINT8 type) +static void SaveEachTimeThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const eachtime_t *ht = (const void *)th; size_t i; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveLine(ht->sourceline)); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveLine(ht->sourceline)); for (i = 0; i < MAXPLAYERS; i++) { - WRITECHAR(save_p, ht->playersInArea[i]); + P_WriteChar(save_p, ht->playersInArea[i]); } - WRITECHAR(save_p, ht->triggerOnExit); + P_WriteChar(save_p, ht->triggerOnExit); } -static void SaveRaiseThinker(const thinker_t *th, const UINT8 type) +static void SaveRaiseThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const raise_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT16(save_p, ht->tag); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEFIXED(save_p, ht->ceilingbottom); - WRITEFIXED(save_p, ht->ceilingtop); - WRITEFIXED(save_p, ht->basespeed); - WRITEFIXED(save_p, ht->extraspeed); - WRITEUINT8(save_p, ht->shaketimer); - WRITEUINT8(save_p, ht->flags); + P_WriteUINT8(save_p, type); + P_WriteINT16(save_p, ht->tag); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteFixed(save_p, ht->ceilingbottom); + P_WriteFixed(save_p, ht->ceilingtop); + P_WriteFixed(save_p, ht->basespeed); + P_WriteFixed(save_p, ht->extraspeed); + P_WriteUINT8(save_p, ht->shaketimer); + P_WriteUINT8(save_p, ht->flags); } -static void SaveCeilingThinker(const thinker_t *th, const UINT8 type) +static void SaveCeilingThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const ceiling_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT8(save_p, ht->type); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEFIXED(save_p, ht->bottomheight); - WRITEFIXED(save_p, ht->topheight); - WRITEFIXED(save_p, ht->speed); - WRITEFIXED(save_p, ht->delay); - WRITEFIXED(save_p, ht->delaytimer); - WRITEUINT8(save_p, ht->crush); - WRITEINT32(save_p, ht->texture); - WRITEINT32(save_p, ht->direction); - WRITEINT16(save_p, ht->tag); - WRITEFIXED(save_p, ht->origspeed); - WRITEFIXED(save_p, ht->sourceline); -} - -static void SaveFloormoveThinker(const thinker_t *th, const UINT8 type) + P_WriteUINT8(save_p, type); + P_WriteUINT8(save_p, ht->type); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteFixed(save_p, ht->bottomheight); + P_WriteFixed(save_p, ht->topheight); + P_WriteFixed(save_p, ht->speed); + P_WriteFixed(save_p, ht->delay); + P_WriteFixed(save_p, ht->delaytimer); + P_WriteUINT8(save_p, ht->crush); + P_WriteINT32(save_p, ht->texture); + P_WriteINT32(save_p, ht->direction); + P_WriteINT16(save_p, ht->tag); + P_WriteFixed(save_p, ht->origspeed); + P_WriteFixed(save_p, ht->sourceline); +} + +static void SaveFloormoveThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const floormove_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT8(save_p, ht->type); - WRITEUINT8(save_p, ht->crush); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEINT32(save_p, ht->direction); - WRITEINT32(save_p, ht->texture); - WRITEFIXED(save_p, ht->floordestheight); - WRITEFIXED(save_p, ht->speed); - WRITEFIXED(save_p, ht->origspeed); - WRITEFIXED(save_p, ht->delay); - WRITEFIXED(save_p, ht->delaytimer); - WRITEINT16(save_p, ht->tag); - WRITEFIXED(save_p, ht->sourceline); -} - -static void SaveLightflashThinker(const thinker_t *th, const UINT8 type) + P_WriteUINT8(save_p, type); + P_WriteUINT8(save_p, ht->type); + P_WriteUINT8(save_p, ht->crush); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteINT32(save_p, ht->direction); + P_WriteINT32(save_p, ht->texture); + P_WriteFixed(save_p, ht->floordestheight); + P_WriteFixed(save_p, ht->speed); + P_WriteFixed(save_p, ht->origspeed); + P_WriteFixed(save_p, ht->delay); + P_WriteFixed(save_p, ht->delaytimer); + P_WriteINT16(save_p, ht->tag); + P_WriteFixed(save_p, ht->sourceline); +} + +static void SaveLightflashThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const lightflash_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEINT32(save_p, ht->maxlight); - WRITEINT32(save_p, ht->minlight); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteINT32(save_p, ht->maxlight); + P_WriteINT32(save_p, ht->minlight); } -static void SaveStrobeThinker(const thinker_t *th, const UINT8 type) +static void SaveStrobeThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const strobe_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEINT32(save_p, ht->count); - WRITEINT16(save_p, ht->minlight); - WRITEINT16(save_p, ht->maxlight); - WRITEINT32(save_p, ht->darktime); - WRITEINT32(save_p, ht->brighttime); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteINT32(save_p, ht->count); + P_WriteINT16(save_p, ht->minlight); + P_WriteINT16(save_p, ht->maxlight); + P_WriteINT32(save_p, ht->darktime); + P_WriteINT32(save_p, ht->brighttime); } -static void SaveGlowThinker(const thinker_t *th, const UINT8 type) +static void SaveGlowThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const glow_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEINT16(save_p, ht->minlight); - WRITEINT16(save_p, ht->maxlight); - WRITEINT16(save_p, ht->direction); - WRITEINT16(save_p, ht->speed); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteINT16(save_p, ht->minlight); + P_WriteINT16(save_p, ht->maxlight); + P_WriteINT16(save_p, ht->direction); + P_WriteINT16(save_p, ht->speed); } -static inline void SaveFireflickerThinker(const thinker_t *th, const UINT8 type) +static inline void SaveFireflickerThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const fireflicker_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEINT32(save_p, ht->count); - WRITEINT32(save_p, ht->resetcount); - WRITEINT16(save_p, ht->maxlight); - WRITEINT16(save_p, ht->minlight); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteINT32(save_p, ht->count); + P_WriteINT32(save_p, ht->resetcount); + P_WriteINT16(save_p, ht->maxlight); + P_WriteINT16(save_p, ht->minlight); } -static void SaveElevatorThinker(const thinker_t *th, const UINT8 type) +static void SaveElevatorThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const elevator_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT8(save_p, ht->type); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEUINT32(save_p, SaveSector(ht->actionsector)); - WRITEINT32(save_p, ht->direction); - WRITEFIXED(save_p, ht->floordestheight); - WRITEFIXED(save_p, ht->ceilingdestheight); - WRITEFIXED(save_p, ht->speed); - WRITEFIXED(save_p, ht->origspeed); - WRITEFIXED(save_p, ht->low); - WRITEFIXED(save_p, ht->high); - WRITEFIXED(save_p, ht->distance); - WRITEFIXED(save_p, ht->delay); - WRITEFIXED(save_p, ht->delaytimer); - WRITEFIXED(save_p, ht->floorwasheight); - WRITEFIXED(save_p, ht->ceilingwasheight); - WRITEUINT32(save_p, SaveLine(ht->sourceline)); -} - -static void SaveCrumbleThinker(const thinker_t *th, const UINT8 type) + P_WriteUINT8(save_p, type); + P_WriteUINT8(save_p, ht->type); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteUINT32(save_p, SaveSector(ht->actionsector)); + P_WriteINT32(save_p, ht->direction); + P_WriteFixed(save_p, ht->floordestheight); + P_WriteFixed(save_p, ht->ceilingdestheight); + P_WriteFixed(save_p, ht->speed); + P_WriteFixed(save_p, ht->origspeed); + P_WriteFixed(save_p, ht->low); + P_WriteFixed(save_p, ht->high); + P_WriteFixed(save_p, ht->distance); + P_WriteFixed(save_p, ht->delay); + P_WriteFixed(save_p, ht->delaytimer); + P_WriteFixed(save_p, ht->floorwasheight); + P_WriteFixed(save_p, ht->ceilingwasheight); + P_WriteUINT32(save_p, SaveLine(ht->sourceline)); +} + +static void SaveCrumbleThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const crumble_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveLine(ht->sourceline)); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEUINT32(save_p, SaveSector(ht->actionsector)); - WRITEUINT32(save_p, SavePlayer(ht->player)); // was dummy - WRITEINT32(save_p, ht->direction); - WRITEINT32(save_p, ht->origalpha); - WRITEINT32(save_p, ht->timer); - WRITEFIXED(save_p, ht->speed); - WRITEFIXED(save_p, ht->floorwasheight); - WRITEFIXED(save_p, ht->ceilingwasheight); - WRITEUINT8(save_p, ht->flags); -} - -static inline void SaveScrollThinker(const thinker_t *th, const UINT8 type) + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveLine(ht->sourceline)); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteUINT32(save_p, SaveSector(ht->actionsector)); + P_WriteUINT32(save_p, SavePlayer(ht->player)); // was dummy + P_WriteINT32(save_p, ht->direction); + P_WriteINT32(save_p, ht->origalpha); + P_WriteINT32(save_p, ht->timer); + P_WriteFixed(save_p, ht->speed); + P_WriteFixed(save_p, ht->floorwasheight); + P_WriteFixed(save_p, ht->ceilingwasheight); + P_WriteUINT8(save_p, ht->flags); +} + +static inline void SaveScrollThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const scroll_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEFIXED(save_p, ht->dx); - WRITEFIXED(save_p, ht->dy); - WRITEINT32(save_p, ht->affectee); - WRITEINT32(save_p, ht->control); - WRITEFIXED(save_p, ht->last_height); - WRITEFIXED(save_p, ht->vdx); - WRITEFIXED(save_p, ht->vdy); - WRITEINT32(save_p, ht->accel); - WRITEINT32(save_p, ht->exclusive); - WRITEUINT8(save_p, ht->type); + P_WriteUINT8(save_p, type); + P_WriteFixed(save_p, ht->dx); + P_WriteFixed(save_p, ht->dy); + P_WriteINT32(save_p, ht->affectee); + P_WriteINT32(save_p, ht->control); + P_WriteFixed(save_p, ht->last_height); + P_WriteFixed(save_p, ht->vdx); + P_WriteFixed(save_p, ht->vdy); + P_WriteINT32(save_p, ht->accel); + P_WriteINT32(save_p, ht->exclusive); + P_WriteUINT8(save_p, ht->type); } -static inline void SaveFrictionThinker(const thinker_t *th, const UINT8 type) +static inline void SaveFrictionThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const friction_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->friction); - WRITEINT32(save_p, ht->movefactor); - WRITEINT32(save_p, ht->affectee); - WRITEINT32(save_p, ht->referrer); - WRITEUINT8(save_p, ht->roverfriction); + P_WriteUINT8(save_p, type); + P_WriteINT32(save_p, ht->friction); + P_WriteINT32(save_p, ht->movefactor); + P_WriteINT32(save_p, ht->affectee); + P_WriteINT32(save_p, ht->referrer); + P_WriteUINT8(save_p, ht->roverfriction); } -static inline void SavePusherThinker(const thinker_t *th, const UINT8 type) +static inline void SavePusherThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const pusher_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT8(save_p, ht->type); - WRITEFIXED(save_p, ht->x_mag); - WRITEFIXED(save_p, ht->y_mag); - WRITEFIXED(save_p, ht->z_mag); - WRITEINT32(save_p, ht->affectee); - WRITEUINT8(save_p, ht->roverpusher); - WRITEINT32(save_p, ht->referrer); - WRITEINT32(save_p, ht->exclusive); - WRITEINT32(save_p, ht->slider); + P_WriteUINT8(save_p, type); + P_WriteUINT8(save_p, ht->type); + P_WriteFixed(save_p, ht->x_mag); + P_WriteFixed(save_p, ht->y_mag); + P_WriteFixed(save_p, ht->z_mag); + P_WriteINT32(save_p, ht->affectee); + P_WriteUINT8(save_p, ht->roverpusher); + P_WriteINT32(save_p, ht->referrer); + P_WriteINT32(save_p, ht->exclusive); + P_WriteINT32(save_p, ht->slider); } -static void SaveLaserThinker(const thinker_t *th, const UINT8 type) +static void SaveLaserThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const laserthink_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT16(save_p, ht->tag); - WRITEUINT32(save_p, SaveLine(ht->sourceline)); - WRITEUINT8(save_p, ht->nobosses); + P_WriteUINT8(save_p, type); + P_WriteINT16(save_p, ht->tag); + P_WriteUINT32(save_p, SaveLine(ht->sourceline)); + P_WriteUINT8(save_p, ht->nobosses); } -static void SaveLightlevelThinker(const thinker_t *th, const UINT8 type) +static void SaveLightlevelThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const lightlevel_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEINT16(save_p, ht->sourcelevel); - WRITEINT16(save_p, ht->destlevel); - WRITEFIXED(save_p, ht->fixedcurlevel); - WRITEFIXED(save_p, ht->fixedpertic); - WRITEINT32(save_p, ht->timer); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteINT16(save_p, ht->sourcelevel); + P_WriteINT16(save_p, ht->destlevel); + P_WriteFixed(save_p, ht->fixedcurlevel); + P_WriteFixed(save_p, ht->fixedpertic); + P_WriteINT32(save_p, ht->timer); } -static void SaveExecutorThinker(const thinker_t *th, const UINT8 type) +static void SaveExecutorThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const executor_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveLine(ht->line)); - WRITEUINT32(save_p, SaveMobjnum(ht->caller)); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEINT32(save_p, ht->timer); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveLine(ht->line)); + P_WriteUINT32(save_p, SaveMobjnum(ht->caller)); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteINT32(save_p, ht->timer); } -static void SaveDisappearThinker(const thinker_t *th, const UINT8 type) +static void SaveDisappearThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const disappear_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, ht->appeartime); - WRITEUINT32(save_p, ht->disappeartime); - WRITEUINT32(save_p, ht->offset); - WRITEUINT32(save_p, ht->timer); - WRITEINT32(save_p, ht->affectee); - WRITEINT32(save_p, ht->sourceline); - WRITEINT32(save_p, ht->exists); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, ht->appeartime); + P_WriteUINT32(save_p, ht->disappeartime); + P_WriteUINT32(save_p, ht->offset); + P_WriteUINT32(save_p, ht->timer); + P_WriteINT32(save_p, ht->affectee); + P_WriteINT32(save_p, ht->sourceline); + P_WriteINT32(save_p, ht->exists); } -static void SaveFadeThinker(const thinker_t *th, const UINT8 type) +static void SaveFadeThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const fade_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc)); - WRITEUINT32(save_p, ht->sectornum); - WRITEUINT32(save_p, ht->ffloornum); - WRITEINT32(save_p, ht->alpha); - WRITEINT16(save_p, ht->sourcevalue); - WRITEINT16(save_p, ht->destvalue); - WRITEINT16(save_p, ht->destlightlevel); - WRITEINT16(save_p, ht->speed); - WRITEUINT8(save_p, (UINT8)ht->ticbased); - WRITEINT32(save_p, ht->timer); - WRITEUINT8(save_p, ht->doexists); - WRITEUINT8(save_p, ht->dotranslucent); - WRITEUINT8(save_p, ht->dolighting); - WRITEUINT8(save_p, ht->docolormap); - WRITEUINT8(save_p, ht->docollision); - WRITEUINT8(save_p, ht->doghostfade); - WRITEUINT8(save_p, ht->exactalpha); -} - -static void SaveFadeColormapThinker(const thinker_t *th, const UINT8 type) + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc)); + P_WriteUINT32(save_p, ht->sectornum); + P_WriteUINT32(save_p, ht->ffloornum); + P_WriteINT32(save_p, ht->alpha); + P_WriteINT16(save_p, ht->sourcevalue); + P_WriteINT16(save_p, ht->destvalue); + P_WriteINT16(save_p, ht->destlightlevel); + P_WriteINT16(save_p, ht->speed); + P_WriteUINT8(save_p, (UINT8)ht->ticbased); + P_WriteINT32(save_p, ht->timer); + P_WriteUINT8(save_p, ht->doexists); + P_WriteUINT8(save_p, ht->dotranslucent); + P_WriteUINT8(save_p, ht->dolighting); + P_WriteUINT8(save_p, ht->docolormap); + P_WriteUINT8(save_p, ht->docollision); + P_WriteUINT8(save_p, ht->doghostfade); + P_WriteUINT8(save_p, ht->exactalpha); +} + +static void SaveFadeColormapThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const fadecolormap_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEUINT32(save_p, CheckAddNetColormapToList(ht->source_exc)); - WRITEUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc)); - WRITEUINT8(save_p, (UINT8)ht->ticbased); - WRITEINT32(save_p, ht->duration); - WRITEINT32(save_p, ht->timer); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveSector(ht->sector)); + P_WriteUINT32(save_p, CheckAddNetColormapToList(ht->source_exc)); + P_WriteUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc)); + P_WriteUINT8(save_p, (UINT8)ht->ticbased); + P_WriteINT32(save_p, ht->duration); + P_WriteINT32(save_p, ht->timer); } -static void SavePlaneDisplaceThinker(const thinker_t *th, const UINT8 type) +static void SavePlaneDisplaceThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const planedisplace_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->affectee); - WRITEINT32(save_p, ht->control); - WRITEFIXED(save_p, ht->last_height); - WRITEFIXED(save_p, ht->speed); - WRITEUINT8(save_p, ht->type); + P_WriteUINT8(save_p, type); + P_WriteINT32(save_p, ht->affectee); + P_WriteINT32(save_p, ht->control); + P_WriteFixed(save_p, ht->last_height); + P_WriteFixed(save_p, ht->speed); + P_WriteUINT8(save_p, ht->type); } -static inline void SaveDynamicLineSlopeThinker(const thinker_t *th, const UINT8 type) +static inline void SaveDynamicLineSlopeThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const dynlineplanethink_t* ht = (const void*)th; - WRITEUINT8(save_p, type); - WRITEUINT8(save_p, ht->type); - WRITEUINT32(save_p, SaveSlope(ht->slope)); - WRITEUINT32(save_p, SaveLine(ht->sourceline)); - WRITEFIXED(save_p, ht->extent); + P_WriteUINT8(save_p, type); + P_WriteUINT8(save_p, ht->type); + P_WriteUINT32(save_p, SaveSlope(ht->slope)); + P_WriteUINT32(save_p, SaveLine(ht->sourceline)); + P_WriteFixed(save_p, ht->extent); } -static inline void SaveDynamicVertexSlopeThinker(const thinker_t *th, const UINT8 type) +static inline void SaveDynamicVertexSlopeThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { size_t i; const dynvertexplanethink_t* ht = (const void*)th; - WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveSlope(ht->slope)); + P_WriteUINT8(save_p, type); + P_WriteUINT32(save_p, SaveSlope(ht->slope)); for (i = 0; i < 3; i++) - WRITEUINT32(save_p, SaveSector(ht->secs[i])); - WRITEMEM(save_p, ht->vex, sizeof(ht->vex)); - WRITEMEM(save_p, ht->origsecheights, sizeof(ht->origsecheights)); - WRITEMEM(save_p, ht->origvecheights, sizeof(ht->origvecheights)); - WRITEUINT8(save_p, ht->relative); + P_WriteUINT32(save_p, SaveSector(ht->secs[i])); + P_WriteMem(save_p, ht->vex, sizeof(ht->vex)); + P_WriteMem(save_p, ht->origsecheights, sizeof(ht->origsecheights)); + P_WriteMem(save_p, ht->origvecheights, sizeof(ht->origvecheights)); + P_WriteUINT8(save_p, ht->relative); } -static inline void SavePolyrotatetThinker(const thinker_t *th, const UINT8 type) +static inline void SavePolyrotatetThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const polyrotate_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->polyObjNum); - WRITEINT32(save_p, ht->speed); - WRITEINT32(save_p, ht->distance); - WRITEUINT8(save_p, ht->turnobjs); + P_WriteUINT8(save_p, type); + P_WriteINT32(save_p, ht->polyObjNum); + P_WriteINT32(save_p, ht->speed); + P_WriteINT32(save_p, ht->distance); + P_WriteUINT8(save_p, ht->turnobjs); } -static void SavePolymoveThinker(const thinker_t *th, const UINT8 type) +static void SavePolymoveThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const polymove_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->polyObjNum); - WRITEINT32(save_p, ht->speed); - WRITEFIXED(save_p, ht->momx); - WRITEFIXED(save_p, ht->momy); - WRITEINT32(save_p, ht->distance); - WRITEANGLE(save_p, ht->angle); + P_WriteUINT8(save_p, type); + P_WriteINT32(save_p, ht->polyObjNum); + P_WriteINT32(save_p, ht->speed); + P_WriteFixed(save_p, ht->momx); + P_WriteFixed(save_p, ht->momy); + P_WriteINT32(save_p, ht->distance); + P_WriteAngle(save_p, ht->angle); } -static void SavePolywaypointThinker(const thinker_t *th, UINT8 type) +static void SavePolywaypointThinker(save_t *save_p, const thinker_t *th, UINT8 type) { const polywaypoint_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->polyObjNum); - WRITEINT32(save_p, ht->speed); - WRITEINT32(save_p, ht->sequence); - WRITEINT32(save_p, ht->pointnum); - WRITEINT32(save_p, ht->direction); - WRITEUINT8(save_p, ht->returnbehavior); - WRITEUINT8(save_p, ht->continuous); - WRITEUINT8(save_p, ht->stophere); + P_WriteUINT8(save_p, type); + P_WriteINT32(save_p, ht->polyObjNum); + P_WriteINT32(save_p, ht->speed); + P_WriteINT32(save_p, ht->sequence); + P_WriteINT32(save_p, ht->pointnum); + P_WriteINT32(save_p, ht->direction); + P_WriteUINT8(save_p, ht->returnbehavior); + P_WriteUINT8(save_p, ht->continuous); + P_WriteUINT8(save_p, ht->stophere); } -static void SavePolyslidedoorThinker(const thinker_t *th, const UINT8 type) +static void SavePolyslidedoorThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const polyslidedoor_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->polyObjNum); - WRITEINT32(save_p, ht->delay); - WRITEINT32(save_p, ht->delayCount); - WRITEINT32(save_p, ht->initSpeed); - WRITEINT32(save_p, ht->speed); - WRITEINT32(save_p, ht->initDistance); - WRITEINT32(save_p, ht->distance); - WRITEUINT32(save_p, ht->initAngle); - WRITEUINT32(save_p, ht->angle); - WRITEUINT32(save_p, ht->revAngle); - WRITEFIXED(save_p, ht->momx); - WRITEFIXED(save_p, ht->momy); - WRITEUINT8(save_p, ht->closing); -} - -static void SavePolyswingdoorThinker(const thinker_t *th, const UINT8 type) + P_WriteUINT8(save_p, type); + P_WriteINT32(save_p, ht->polyObjNum); + P_WriteINT32(save_p, ht->delay); + P_WriteINT32(save_p, ht->delayCount); + P_WriteINT32(save_p, ht->initSpeed); + P_WriteINT32(save_p, ht->speed); + P_WriteINT32(save_p, ht->initDistance); + P_WriteINT32(save_p, ht->distance); + P_WriteUINT32(save_p, ht->initAngle); + P_WriteUINT32(save_p, ht->angle); + P_WriteUINT32(save_p, ht->revAngle); + P_WriteFixed(save_p, ht->momx); + P_WriteFixed(save_p, ht->momy); + P_WriteUINT8(save_p, ht->closing); +} + +static void SavePolyswingdoorThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const polyswingdoor_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->polyObjNum); - WRITEINT32(save_p, ht->delay); - WRITEINT32(save_p, ht->delayCount); - WRITEINT32(save_p, ht->initSpeed); - WRITEINT32(save_p, ht->speed); - WRITEINT32(save_p, ht->initDistance); - WRITEINT32(save_p, ht->distance); - WRITEUINT8(save_p, ht->closing); + P_WriteUINT8(save_p, type); + P_WriteINT32(save_p, ht->polyObjNum); + P_WriteINT32(save_p, ht->delay); + P_WriteINT32(save_p, ht->delayCount); + P_WriteINT32(save_p, ht->initSpeed); + P_WriteINT32(save_p, ht->speed); + P_WriteINT32(save_p, ht->initDistance); + P_WriteINT32(save_p, ht->distance); + P_WriteUINT8(save_p, ht->closing); } -static void SavePolydisplaceThinker(const thinker_t *th, const UINT8 type) +static void SavePolydisplaceThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const polydisplace_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->polyObjNum); - WRITEUINT32(save_p, SaveSector(ht->controlSector)); - WRITEFIXED(save_p, ht->dx); - WRITEFIXED(save_p, ht->dy); - WRITEFIXED(save_p, ht->oldHeights); + P_WriteUINT8(save_p, type); + P_WriteINT32(save_p, ht->polyObjNum); + P_WriteUINT32(save_p, SaveSector(ht->controlSector)); + P_WriteFixed(save_p, ht->dx); + P_WriteFixed(save_p, ht->dy); + P_WriteFixed(save_p, ht->oldHeights); } -static void SavePolyrotdisplaceThinker(const thinker_t *th, const UINT8 type) +static void SavePolyrotdisplaceThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const polyrotdisplace_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->polyObjNum); - WRITEUINT32(save_p, SaveSector(ht->controlSector)); - WRITEFIXED(save_p, ht->rotscale); - WRITEUINT8(save_p, ht->turnobjs); - WRITEFIXED(save_p, ht->oldHeights); + P_WriteUINT8(save_p, type); + P_WriteINT32(save_p, ht->polyObjNum); + P_WriteUINT32(save_p, SaveSector(ht->controlSector)); + P_WriteFixed(save_p, ht->rotscale); + P_WriteUINT8(save_p, ht->turnobjs); + P_WriteFixed(save_p, ht->oldHeights); } -static void SavePolyfadeThinker(const thinker_t *th, const UINT8 type) +static void SavePolyfadeThinker(save_t *save_p, const thinker_t *th, const UINT8 type) { const polyfade_t *ht = (const void *)th; - WRITEUINT8(save_p, type); - WRITEINT32(save_p, ht->polyObjNum); - WRITEINT32(save_p, ht->sourcevalue); - WRITEINT32(save_p, ht->destvalue); - WRITEUINT8(save_p, (UINT8)ht->docollision); - WRITEUINT8(save_p, (UINT8)ht->doghostfade); - WRITEUINT8(save_p, (UINT8)ht->ticbased); - WRITEINT32(save_p, ht->duration); - WRITEINT32(save_p, ht->timer); + P_WriteUINT8(save_p, type); + P_WriteINT32(save_p, ht->polyObjNum); + P_WriteINT32(save_p, ht->sourcevalue); + P_WriteINT32(save_p, ht->destvalue); + P_WriteUINT8(save_p, (UINT8)ht->docollision); + P_WriteUINT8(save_p, (UINT8)ht->doghostfade); + P_WriteUINT8(save_p, (UINT8)ht->ticbased); + P_WriteINT32(save_p, ht->duration); + P_WriteINT32(save_p, ht->timer); } -static void P_NetArchiveThinkers(void) +static void P_NetArchiveThinkers(save_t *save_p) { const thinker_t *th; UINT32 i; - WRITEUINT32(save_p, ARCHIVEBLOCK_THINKERS); + P_WriteUINT32(save_p, ARCHIVEBLOCK_THINKERS); for (i = 0; i < NUM_THINKERLISTS; i++) { @@ -2671,13 +2972,12 @@ static void P_NetArchiveThinkers(void) // save off the current thinkers for (th = thlist[i].next; th != &thlist[i]; th = th->next) { - if (!(th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed - || th->function.acp1 == (actionf_p1)P_NullPrecipThinker)) + if (!(th->removing || th->function.acp1 == (actionf_p1)P_NullPrecipThinker)) numsaved++; if (th->function.acp1 == (actionf_p1)P_MobjThinker) { - SaveMobjThinker(th, tc_mobj); + SaveMobjThinker(save_p, th, tc_mobj); continue; } #ifdef PARANOIA @@ -2685,213 +2985,213 @@ static void P_NetArchiveThinkers(void) #endif else if (th->function.acp1 == (actionf_p1)T_MoveCeiling) { - SaveCeilingThinker(th, tc_ceiling); + SaveCeilingThinker(save_p, th, tc_ceiling); continue; } else if (th->function.acp1 == (actionf_p1)T_CrushCeiling) { - SaveCeilingThinker(th, tc_crushceiling); + SaveCeilingThinker(save_p, th, tc_crushceiling); continue; } else if (th->function.acp1 == (actionf_p1)T_MoveFloor) { - SaveFloormoveThinker(th, tc_floor); + SaveFloormoveThinker(save_p, th, tc_floor); continue; } else if (th->function.acp1 == (actionf_p1)T_LightningFlash) { - SaveLightflashThinker(th, tc_flash); + SaveLightflashThinker(save_p, th, tc_flash); continue; } else if (th->function.acp1 == (actionf_p1)T_StrobeFlash) { - SaveStrobeThinker(th, tc_strobe); + SaveStrobeThinker(save_p, th, tc_strobe); continue; } else if (th->function.acp1 == (actionf_p1)T_Glow) { - SaveGlowThinker(th, tc_glow); + SaveGlowThinker(save_p, th, tc_glow); continue; } else if (th->function.acp1 == (actionf_p1)T_FireFlicker) { - SaveFireflickerThinker(th, tc_fireflicker); + SaveFireflickerThinker(save_p, th, tc_fireflicker); continue; } else if (th->function.acp1 == (actionf_p1)T_MoveElevator) { - SaveElevatorThinker(th, tc_elevator); + SaveElevatorThinker(save_p, th, tc_elevator); continue; } else if (th->function.acp1 == (actionf_p1)T_ContinuousFalling) { - SaveContinuousFallThinker(th, tc_continuousfalling); + SaveContinuousFallThinker(save_p, th, tc_continuousfalling); continue; } else if (th->function.acp1 == (actionf_p1)T_ThwompSector) { - SaveThwompThinker(th, tc_thwomp); + SaveThwompThinker(save_p, th, tc_thwomp); continue; } else if (th->function.acp1 == (actionf_p1)T_NoEnemiesSector) { - SaveNoEnemiesThinker(th, tc_noenemies); + SaveNoEnemiesThinker(save_p, th, tc_noenemies); continue; } else if (th->function.acp1 == (actionf_p1)T_EachTimeThinker) { - SaveEachTimeThinker(th, tc_eachtime); + SaveEachTimeThinker(save_p, th, tc_eachtime); continue; } else if (th->function.acp1 == (actionf_p1)T_RaiseSector) { - SaveRaiseThinker(th, tc_raisesector); + SaveRaiseThinker(save_p, th, tc_raisesector); continue; } else if (th->function.acp1 == (actionf_p1)T_CameraScanner) { - SaveElevatorThinker(th, tc_camerascanner); + SaveElevatorThinker(save_p, th, tc_camerascanner); continue; } else if (th->function.acp1 == (actionf_p1)T_Scroll) { - SaveScrollThinker(th, tc_scroll); + SaveScrollThinker(save_p, th, tc_scroll); continue; } else if (th->function.acp1 == (actionf_p1)T_Friction) { - SaveFrictionThinker(th, tc_friction); + SaveFrictionThinker(save_p, th, tc_friction); continue; } else if (th->function.acp1 == (actionf_p1)T_Pusher) { - SavePusherThinker(th, tc_pusher); + SavePusherThinker(save_p, th, tc_pusher); continue; } else if (th->function.acp1 == (actionf_p1)T_BounceCheese) { - SaveBounceCheeseThinker(th, tc_bouncecheese); + SaveBounceCheeseThinker(save_p, th, tc_bouncecheese); continue; } else if (th->function.acp1 == (actionf_p1)T_StartCrumble) { - SaveCrumbleThinker(th, tc_startcrumble); + SaveCrumbleThinker(save_p, th, tc_startcrumble); continue; } else if (th->function.acp1 == (actionf_p1)T_MarioBlock) { - SaveMarioBlockThinker(th, tc_marioblock); + SaveMarioBlockThinker(save_p, th, tc_marioblock); continue; } else if (th->function.acp1 == (actionf_p1)T_MarioBlockChecker) { - SaveMarioCheckThinker(th, tc_marioblockchecker); + SaveMarioCheckThinker(save_p, th, tc_marioblockchecker); continue; } else if (th->function.acp1 == (actionf_p1)T_FloatSector) { - SaveFloatThinker(th, tc_floatsector); + SaveFloatThinker(save_p, th, tc_floatsector); continue; } else if (th->function.acp1 == (actionf_p1)T_LaserFlash) { - SaveLaserThinker(th, tc_laserflash); + SaveLaserThinker(save_p, th, tc_laserflash); continue; } else if (th->function.acp1 == (actionf_p1)T_LightFade) { - SaveLightlevelThinker(th, tc_lightfade); + SaveLightlevelThinker(save_p, th, tc_lightfade); continue; } else if (th->function.acp1 == (actionf_p1)T_ExecutorDelay) { - SaveExecutorThinker(th, tc_executor); + SaveExecutorThinker(save_p, th, tc_executor); continue; } else if (th->function.acp1 == (actionf_p1)T_Disappear) { - SaveDisappearThinker(th, tc_disappear); + SaveDisappearThinker(save_p, th, tc_disappear); continue; } else if (th->function.acp1 == (actionf_p1)T_Fade) { - SaveFadeThinker(th, tc_fade); + SaveFadeThinker(save_p, th, tc_fade); continue; } else if (th->function.acp1 == (actionf_p1)T_FadeColormap) { - SaveFadeColormapThinker(th, tc_fadecolormap); + SaveFadeColormapThinker(save_p, th, tc_fadecolormap); continue; } else if (th->function.acp1 == (actionf_p1)T_PlaneDisplace) { - SavePlaneDisplaceThinker(th, tc_planedisplace); + SavePlaneDisplaceThinker(save_p, th, tc_planedisplace); continue; } else if (th->function.acp1 == (actionf_p1)T_PolyObjRotate) { - SavePolyrotatetThinker(th, tc_polyrotate); + SavePolyrotatetThinker(save_p, th, tc_polyrotate); continue; } else if (th->function.acp1 == (actionf_p1)T_PolyObjMove) { - SavePolymoveThinker(th, tc_polymove); + SavePolymoveThinker(save_p, th, tc_polymove); continue; } else if (th->function.acp1 == (actionf_p1)T_PolyObjWaypoint) { - SavePolywaypointThinker(th, tc_polywaypoint); + SavePolywaypointThinker(save_p, th, tc_polywaypoint); continue; } else if (th->function.acp1 == (actionf_p1)T_PolyDoorSlide) { - SavePolyslidedoorThinker(th, tc_polyslidedoor); + SavePolyslidedoorThinker(save_p, th, tc_polyslidedoor); continue; } else if (th->function.acp1 == (actionf_p1)T_PolyDoorSwing) { - SavePolyswingdoorThinker(th, tc_polyswingdoor); + SavePolyswingdoorThinker(save_p, th, tc_polyswingdoor); continue; } else if (th->function.acp1 == (actionf_p1)T_PolyObjFlag) { - SavePolymoveThinker(th, tc_polyflag); + SavePolymoveThinker(save_p, th, tc_polyflag); continue; } else if (th->function.acp1 == (actionf_p1)T_PolyObjDisplace) { - SavePolydisplaceThinker(th, tc_polydisplace); + SavePolydisplaceThinker(save_p, th, tc_polydisplace); continue; } else if (th->function.acp1 == (actionf_p1)T_PolyObjRotDisplace) { - SavePolyrotdisplaceThinker(th, tc_polyrotdisplace); + SavePolyrotdisplaceThinker(save_p, th, tc_polyrotdisplace); continue; } else if (th->function.acp1 == (actionf_p1)T_PolyObjFade) { - SavePolyfadeThinker(th, tc_polyfade); + SavePolyfadeThinker(save_p, th, tc_polyfade); continue; } else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeLine) { - SaveDynamicLineSlopeThinker(th, tc_dynslopeline); + SaveDynamicLineSlopeThinker(save_p, th, tc_dynslopeline); continue; } else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeVert) { - SaveDynamicVertexSlopeThinker(th, tc_dynslopevert); + SaveDynamicVertexSlopeThinker(save_p, th, tc_dynslopevert); continue; } #ifdef PARANOIA else - I_Assert(th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed); // wait garbage collection + I_Assert(th->removing); // wait garbage collection #endif } CONS_Debug(DBG_NETPLAY, "%u thinkers saved in list %d\n", numsaved, i); - WRITEUINT8(save_p, tc_end); + P_WriteUINT8(save_p, tc_end); } } @@ -2906,7 +3206,7 @@ mobj_t *P_FindNewPosition(UINT32 oldposition) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mobj = (mobj_t *)th; @@ -2955,7 +3255,7 @@ static inline pslope_t *LoadSlope(UINT32 slopeid) return NULL; } -static thinker_t* LoadMobjThinker(actionf_p1 thinker) +static thinker_t* LoadMobjThinker(save_t *save_p, actionf_p1 thinker) { thinker_t *next; mobj_t *mobj; @@ -2965,35 +3265,35 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) fixed_t z, floorz, ceilingz; ffloor_t *floorrover = NULL, *ceilingrover = NULL; - diff = READUINT32(save_p); + diff = P_ReadUINT32(save_p); if (diff & MD_MORE) - diff2 = READUINT32(save_p); + diff2 = P_ReadUINT32(save_p); else diff2 = 0; - next = (void *)(size_t)READUINT32(save_p); + next = (void *)(size_t)P_ReadUINT32(save_p); - z = READFIXED(save_p); // Force this so 3dfloor problems don't arise. - floorz = READFIXED(save_p); - ceilingz = READFIXED(save_p); + z = P_ReadFixed(save_p); // Force this so 3dfloor problems don't arise. + floorz = P_ReadFixed(save_p); + ceilingz = P_ReadFixed(save_p); if (diff2 & MD2_FLOORROVER) { - sector_t *sec = LoadSector(READUINT32(save_p)); - UINT16 id = READUINT16(save_p); + sector_t *sec = LoadSector(P_ReadUINT32(save_p)); + UINT16 id = P_ReadUINT16(save_p); floorrover = P_GetFFloorByID(sec, id); } if (diff2 & MD2_CEILINGROVER) { - sector_t *sec = LoadSector(READUINT32(save_p)); - UINT16 id = READUINT16(save_p); + sector_t *sec = LoadSector(P_ReadUINT32(save_p)); + UINT16 id = P_ReadUINT16(save_p); ceilingrover = P_GetFFloorByID(sec, id); } if (diff & MD_SPAWNPOINT) { - UINT16 spawnpointnum = READUINT16(save_p); + UINT16 spawnpointnum = P_ReadUINT16(save_p); if (mapthings[spawnpointnum].type == 1713) // NiGHTS Hoop special case { @@ -3019,7 +3319,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->ceilingrover = ceilingrover; if (diff & MD_TYPE) - mobj->type = READUINT32(save_p); + mobj->type = P_ReadUINT32(save_p); else { for (i = 0; i < NUMMOBJTYPES; i++) @@ -3038,11 +3338,11 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->info = &mobjinfo[mobj->type]; if (diff & MD_POS) { - mobj->x = READFIXED(save_p); - mobj->y = READFIXED(save_p); - mobj->angle = READANGLE(save_p); - mobj->pitch = READANGLE(save_p); - mobj->roll = READANGLE(save_p); + mobj->x = P_ReadFixed(save_p); + mobj->y = P_ReadFixed(save_p); + mobj->angle = P_ReadAngle(save_p); + mobj->pitch = P_ReadAngle(save_p); + mobj->roll = P_ReadAngle(save_p); } else { @@ -3054,57 +3354,57 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) } if (diff & MD_MOM) { - mobj->momx = READFIXED(save_p); - mobj->momy = READFIXED(save_p); - mobj->momz = READFIXED(save_p); - mobj->pmomz = READFIXED(save_p); + mobj->momx = P_ReadFixed(save_p); + mobj->momy = P_ReadFixed(save_p); + mobj->momz = P_ReadFixed(save_p); + mobj->pmomz = P_ReadFixed(save_p); } // otherwise they're zero, and the memset took care of it if (diff & MD_RADIUS) - mobj->radius = READFIXED(save_p); + mobj->radius = P_ReadFixed(save_p); else mobj->radius = mobj->info->radius; if (diff & MD_HEIGHT) - mobj->height = READFIXED(save_p); + mobj->height = P_ReadFixed(save_p); else mobj->height = mobj->info->height; if (diff & MD_FLAGS) - mobj->flags = READUINT32(save_p); + mobj->flags = P_ReadUINT32(save_p); else mobj->flags = mobj->info->flags; if (diff & MD_FLAGS2) - mobj->flags2 = READUINT32(save_p); + mobj->flags2 = P_ReadUINT32(save_p); if (diff & MD_HEALTH) - mobj->health = READINT32(save_p); + mobj->health = P_ReadINT32(save_p); else mobj->health = mobj->info->spawnhealth; if (diff & MD_RTIME) - mobj->reactiontime = READINT32(save_p); + mobj->reactiontime = P_ReadINT32(save_p); else mobj->reactiontime = mobj->info->reactiontime; if (diff & MD_STATE) - mobj->state = &states[READUINT16(save_p)]; + mobj->state = &states[P_ReadUINT16(save_p)]; else mobj->state = &states[mobj->info->spawnstate]; if (diff & MD_TICS) - mobj->tics = READINT32(save_p); + mobj->tics = P_ReadINT32(save_p); else mobj->tics = mobj->state->tics; if (diff & MD_SPRITE) { - mobj->sprite = READUINT16(save_p); + mobj->sprite = P_ReadUINT16(save_p); if (mobj->sprite == SPR_PLAY) - mobj->sprite2 = READUINT8(save_p); + mobj->sprite2 = P_ReadUINT16(save_p); } else { mobj->sprite = mobj->state->sprite; if (mobj->sprite == SPR_PLAY) - mobj->sprite2 = mobj->state->frame&FF_FRAMEMASK; + mobj->sprite2 = P_GetStateSprite2(mobj->state); } if (diff & MD_FRAME) { - mobj->frame = READUINT32(save_p); - mobj->anim_duration = READUINT16(save_p); + mobj->frame = P_ReadUINT32(save_p); + mobj->anim_duration = P_ReadUINT16(save_p); } else { @@ -3112,128 +3412,132 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->anim_duration = (UINT16)mobj->state->var2; } if (diff & MD_EFLAGS) - mobj->eflags = READUINT16(save_p); + mobj->eflags = P_ReadUINT16(save_p); if (diff & MD_PLAYER) { - i = READUINT8(save_p); + i = P_ReadUINT8(save_p); mobj->player = &players[i]; mobj->player->mo = mobj; } if (diff & MD_MOVEDIR) - mobj->movedir = READANGLE(save_p); + mobj->movedir = P_ReadAngle(save_p); if (diff & MD_MOVECOUNT) - mobj->movecount = READINT32(save_p); + mobj->movecount = P_ReadINT32(save_p); if (diff & MD_THRESHOLD) - mobj->threshold = READINT32(save_p); + mobj->threshold = P_ReadINT32(save_p); if (diff & MD_LASTLOOK) - mobj->lastlook = READINT32(save_p); + mobj->lastlook = P_ReadINT32(save_p); else mobj->lastlook = -1; if (diff & MD_TARGET) - mobj->target = (mobj_t *)(size_t)READUINT32(save_p); + mobj->target = (mobj_t *)(size_t)P_ReadUINT32(save_p); if (diff & MD_TRACER) - mobj->tracer = (mobj_t *)(size_t)READUINT32(save_p); + mobj->tracer = (mobj_t *)(size_t)P_ReadUINT32(save_p); if (diff & MD_FRICTION) - mobj->friction = READFIXED(save_p); + mobj->friction = P_ReadFixed(save_p); else mobj->friction = ORIG_FRICTION; if (diff & MD_MOVEFACTOR) - mobj->movefactor = READFIXED(save_p); + mobj->movefactor = P_ReadFixed(save_p); else mobj->movefactor = FRACUNIT; if (diff & MD_FUSE) - mobj->fuse = READINT32(save_p); + mobj->fuse = P_ReadINT32(save_p); if (diff & MD_WATERTOP) - mobj->watertop = READFIXED(save_p); + mobj->watertop = P_ReadFixed(save_p); if (diff & MD_WATERBOTTOM) - mobj->waterbottom = READFIXED(save_p); + mobj->waterbottom = P_ReadFixed(save_p); if (diff & MD_SCALE) - mobj->scale = READFIXED(save_p); + mobj->scale = P_ReadFixed(save_p); else mobj->scale = FRACUNIT; if (diff & MD_DSCALE) - mobj->destscale = READFIXED(save_p); + mobj->destscale = P_ReadFixed(save_p); else mobj->destscale = mobj->scale; if (diff2 & MD2_SCALESPEED) - mobj->scalespeed = READFIXED(save_p); + mobj->scalespeed = P_ReadFixed(save_p); else mobj->scalespeed = FRACUNIT/12; if (diff2 & MD2_CUSVAL) - mobj->cusval = READINT32(save_p); + mobj->cusval = P_ReadINT32(save_p); if (diff2 & MD2_CVMEM) - mobj->cvmem = READINT32(save_p); + mobj->cvmem = P_ReadINT32(save_p); if (diff2 & MD2_SKIN) - mobj->skin = skins[READUINT8(save_p)]; + mobj->skin = skins[P_ReadUINT8(save_p)]; if (diff2 & MD2_COLOR) - mobj->color = READUINT16(save_p); + mobj->color = P_ReadUINT16(save_p); if (diff2 & MD2_EXTVAL1) - mobj->extravalue1 = READINT32(save_p); + mobj->extravalue1 = P_ReadINT32(save_p); if (diff2 & MD2_EXTVAL2) - mobj->extravalue2 = READINT32(save_p); + mobj->extravalue2 = P_ReadINT32(save_p); if (diff2 & MD2_HNEXT) - mobj->hnext = (mobj_t *)(size_t)READUINT32(save_p); + mobj->hnext = (mobj_t *)(size_t)P_ReadUINT32(save_p); if (diff2 & MD2_HPREV) - mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p); + mobj->hprev = (mobj_t *)(size_t)P_ReadUINT32(save_p); if (diff2 & MD2_SLOPE) - mobj->standingslope = P_SlopeById(READUINT16(save_p)); + mobj->standingslope = P_SlopeById(P_ReadUINT16(save_p)); if (diff2 & MD2_COLORIZED) - mobj->colorized = READUINT8(save_p); + mobj->colorized = P_ReadUINT8(save_p); if (diff2 & MD2_MIRRORED) - mobj->mirrored = READUINT8(save_p); + mobj->mirrored = P_ReadUINT8(save_p); if (diff2 & MD2_SPRITEROLL) - mobj->spriteroll = READANGLE(save_p); + mobj->spriteroll = P_ReadAngle(save_p); if (diff2 & MD2_SHADOWSCALE) - mobj->shadowscale = READFIXED(save_p); + mobj->shadowscale = P_ReadFixed(save_p); if (diff2 & MD2_RENDERFLAGS) - mobj->renderflags = READUINT32(save_p); + mobj->renderflags = P_ReadUINT32(save_p); if (diff2 & MD2_BLENDMODE) - mobj->blendmode = READINT32(save_p); + mobj->blendmode = P_ReadINT32(save_p); else mobj->blendmode = AST_TRANSLUCENT; if (diff2 & MD2_SPRITEXSCALE) - mobj->spritexscale = READFIXED(save_p); + mobj->spritexscale = P_ReadFixed(save_p); else mobj->spritexscale = FRACUNIT; if (diff2 & MD2_SPRITEYSCALE) - mobj->spriteyscale = READFIXED(save_p); + mobj->spriteyscale = P_ReadFixed(save_p); else mobj->spriteyscale = FRACUNIT; if (diff2 & MD2_SPRITEXOFFSET) - mobj->spritexoffset = READFIXED(save_p); + mobj->spritexoffset = P_ReadFixed(save_p); if (diff2 & MD2_SPRITEYOFFSET) - mobj->spriteyoffset = READFIXED(save_p); + mobj->spriteyoffset = P_ReadFixed(save_p); if (diff2 & MD2_FLOORSPRITESLOPE) { pslope_t *slope = (pslope_t *)P_CreateFloorSpriteSlope(mobj); - slope->zdelta = READFIXED(save_p); - slope->zangle = READANGLE(save_p); - slope->xydirection = READANGLE(save_p); + slope->zdelta = P_ReadFixed(save_p); + slope->zangle = P_ReadAngle(save_p); + slope->xydirection = P_ReadAngle(save_p); - slope->o.x = READFIXED(save_p); - slope->o.y = READFIXED(save_p); - slope->o.z = READFIXED(save_p); + slope->o.x = P_ReadFixed(save_p); + slope->o.y = P_ReadFixed(save_p); + slope->o.z = P_ReadFixed(save_p); - slope->d.x = READFIXED(save_p); - slope->d.y = READFIXED(save_p); + slope->d.x = P_ReadFixed(save_p); + slope->d.y = P_ReadFixed(save_p); - slope->normal.x = READFIXED(save_p); - slope->normal.y = READFIXED(save_p); - slope->normal.z = READFIXED(save_p); + slope->normal.x = P_ReadFixed(save_p); + slope->normal.y = P_ReadFixed(save_p); + slope->normal.z = P_ReadFixed(save_p); slope->moved = true; } if (diff2 & MD2_DRAWONLYFORPLAYER) - mobj->drawonlyforplayer = &players[READUINT8(save_p)]; + mobj->drawonlyforplayer = &players[P_ReadUINT8(save_p)]; if (diff2 & MD2_DONTDRAWFORVIEWMOBJ) - mobj->dontdrawforviewmobj = (mobj_t *)(size_t)READUINT32(save_p); + mobj->dontdrawforviewmobj = (mobj_t *)(size_t)P_ReadUINT32(save_p); if (diff2 & MD2_DISPOFFSET) - mobj->dispoffset = READINT32(save_p); + mobj->dispoffset = P_ReadINT32(save_p); else mobj->dispoffset = mobj->info->dispoffset; if (diff2 & MD2_TRANSLATION) - mobj->translation = READUINT16(save_p); + mobj->translation = P_ReadUINT16(save_p); + if (diff2 & MD2_ALPHA) + mobj->alpha = P_ReadFixed(save_p); + else + mobj->alpha = FRACUNIT; if (diff & MD_REDFLAG) { @@ -3249,7 +3553,7 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) // set sprev, snext, bprev, bnext, subsector P_SetThingPosition(mobj); - mobj->mobjnum = READUINT32(save_p); + mobj->mobjnum = P_ReadUINT32(save_p); if (mobj->player) { @@ -3278,25 +3582,25 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) return &mobj->thinker; } -static thinker_t* LoadNoEnemiesThinker(actionf_p1 thinker) +static thinker_t* LoadNoEnemiesThinker(save_t *save_p, actionf_p1 thinker) { noenemies_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sourceline = LoadLine(READUINT32(save_p)); + ht->sourceline = LoadLine(P_ReadUINT32(save_p)); return &ht->thinker; } -static thinker_t* LoadBounceCheeseThinker(actionf_p1 thinker) +static thinker_t* LoadBounceCheeseThinker(save_t *save_p, actionf_p1 thinker) { bouncecheese_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sourceline = LoadLine(READUINT32(save_p)); - ht->sector = LoadSector(READUINT32(save_p)); - ht->speed = READFIXED(save_p); - ht->distance = READFIXED(save_p); - ht->floorwasheight = READFIXED(save_p); - ht->ceilingwasheight = READFIXED(save_p); - ht->low = READCHAR(save_p); + ht->sourceline = LoadLine(P_ReadUINT32(save_p)); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->speed = P_ReadFixed(save_p); + ht->distance = P_ReadFixed(save_p); + ht->floorwasheight = P_ReadFixed(save_p); + ht->ceilingwasheight = P_ReadFixed(save_p); + ht->low = P_ReadChar(save_p); if (ht->sector) ht->sector->ceilingdata = ht; @@ -3304,16 +3608,16 @@ static thinker_t* LoadBounceCheeseThinker(actionf_p1 thinker) return &ht->thinker; } -static thinker_t* LoadContinuousFallThinker(actionf_p1 thinker) +static thinker_t* LoadContinuousFallThinker(save_t *save_p, actionf_p1 thinker) { continuousfall_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save_p)); - ht->speed = READFIXED(save_p); - ht->direction = READINT32(save_p); - ht->floorstartheight = READFIXED(save_p); - ht->ceilingstartheight = READFIXED(save_p); - ht->destheight = READFIXED(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->speed = P_ReadFixed(save_p); + ht->direction = P_ReadINT32(save_p); + ht->floorstartheight = P_ReadFixed(save_p); + ht->ceilingstartheight = P_ReadFixed(save_p); + ht->destheight = P_ReadFixed(save_p); if (ht->sector) { @@ -3324,16 +3628,16 @@ static thinker_t* LoadContinuousFallThinker(actionf_p1 thinker) return &ht->thinker; } -static thinker_t* LoadMarioBlockThinker(actionf_p1 thinker) +static thinker_t* LoadMarioBlockThinker(save_t *save_p, actionf_p1 thinker) { mariothink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save_p)); - ht->speed = READFIXED(save_p); - ht->direction = READINT32(save_p); - ht->floorstartheight = READFIXED(save_p); - ht->ceilingstartheight = READFIXED(save_p); - ht->tag = READINT16(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->speed = P_ReadFixed(save_p); + ht->direction = P_ReadINT32(save_p); + ht->floorstartheight = P_ReadFixed(save_p); + ht->ceilingstartheight = P_ReadFixed(save_p); + ht->tag = P_ReadINT16(save_p); if (ht->sector) { @@ -3344,29 +3648,29 @@ static thinker_t* LoadMarioBlockThinker(actionf_p1 thinker) return &ht->thinker; } -static thinker_t* LoadMarioCheckThinker(actionf_p1 thinker) +static thinker_t* LoadMarioCheckThinker(save_t *save_p, actionf_p1 thinker) { mariocheck_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sourceline = LoadLine(READUINT32(save_p)); - ht->sector = LoadSector(READUINT32(save_p)); + ht->sourceline = LoadLine(P_ReadUINT32(save_p)); + ht->sector = LoadSector(P_ReadUINT32(save_p)); return &ht->thinker; } -static thinker_t* LoadThwompThinker(actionf_p1 thinker) +static thinker_t* LoadThwompThinker(save_t *save_p, actionf_p1 thinker) { thwomp_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sourceline = LoadLine(READUINT32(save_p)); - ht->sector = LoadSector(READUINT32(save_p)); - ht->crushspeed = READFIXED(save_p); - ht->retractspeed = READFIXED(save_p); - ht->direction = READINT32(save_p); - ht->floorstartheight = READFIXED(save_p); - ht->ceilingstartheight = READFIXED(save_p); - ht->delay = READINT32(save_p); - ht->tag = READINT16(save_p); - ht->sound = READUINT16(save_p); + ht->sourceline = LoadLine(P_ReadUINT32(save_p)); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->crushspeed = P_ReadFixed(save_p); + ht->retractspeed = P_ReadFixed(save_p); + ht->direction = P_ReadINT32(save_p); + ht->floorstartheight = P_ReadFixed(save_p); + ht->ceilingstartheight = P_ReadFixed(save_p); + ht->delay = P_ReadINT32(save_p); + ht->tag = P_ReadINT16(save_p); + ht->sound = P_ReadUINT16(save_p); if (ht->sector) { @@ -3377,163 +3681,163 @@ static thinker_t* LoadThwompThinker(actionf_p1 thinker) return &ht->thinker; } -static thinker_t* LoadFloatThinker(actionf_p1 thinker) +static thinker_t* LoadFloatThinker(save_t *save_p, actionf_p1 thinker) { floatthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sourceline = LoadLine(READUINT32(save_p)); - ht->sector = LoadSector(READUINT32(save_p)); - ht->tag = READINT16(save_p); + ht->sourceline = LoadLine(P_ReadUINT32(save_p)); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->tag = P_ReadINT16(save_p); return &ht->thinker; } -static thinker_t* LoadEachTimeThinker(actionf_p1 thinker) +static thinker_t* LoadEachTimeThinker(save_t *save_p, actionf_p1 thinker) { size_t i; eachtime_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sourceline = LoadLine(READUINT32(save_p)); + ht->sourceline = LoadLine(P_ReadUINT32(save_p)); for (i = 0; i < MAXPLAYERS; i++) { - ht->playersInArea[i] = READCHAR(save_p); + ht->playersInArea[i] = P_ReadChar(save_p); } - ht->triggerOnExit = READCHAR(save_p); + ht->triggerOnExit = P_ReadChar(save_p); return &ht->thinker; } -static thinker_t* LoadRaiseThinker(actionf_p1 thinker) +static thinker_t* LoadRaiseThinker(save_t *save_p, actionf_p1 thinker) { raise_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->tag = READINT16(save_p); - ht->sector = LoadSector(READUINT32(save_p)); - ht->ceilingbottom = READFIXED(save_p); - ht->ceilingtop = READFIXED(save_p); - ht->basespeed = READFIXED(save_p); - ht->extraspeed = READFIXED(save_p); - ht->shaketimer = READUINT8(save_p); - ht->flags = READUINT8(save_p); + ht->tag = P_ReadINT16(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->ceilingbottom = P_ReadFixed(save_p); + ht->ceilingtop = P_ReadFixed(save_p); + ht->basespeed = P_ReadFixed(save_p); + ht->extraspeed = P_ReadFixed(save_p); + ht->shaketimer = P_ReadUINT8(save_p); + ht->flags = P_ReadUINT8(save_p); return &ht->thinker; } -static thinker_t* LoadCeilingThinker(actionf_p1 thinker) +static thinker_t* LoadCeilingThinker(save_t *save_p, actionf_p1 thinker) { ceiling_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->type = READUINT8(save_p); - ht->sector = LoadSector(READUINT32(save_p)); - ht->bottomheight = READFIXED(save_p); - ht->topheight = READFIXED(save_p); - ht->speed = READFIXED(save_p); - ht->delay = READFIXED(save_p); - ht->delaytimer = READFIXED(save_p); - ht->crush = READUINT8(save_p); - ht->texture = READINT32(save_p); - ht->direction = READINT32(save_p); - ht->tag = READINT16(save_p); - ht->origspeed = READFIXED(save_p); - ht->sourceline = READFIXED(save_p); + ht->type = P_ReadUINT8(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->bottomheight = P_ReadFixed(save_p); + ht->topheight = P_ReadFixed(save_p); + ht->speed = P_ReadFixed(save_p); + ht->delay = P_ReadFixed(save_p); + ht->delaytimer = P_ReadFixed(save_p); + ht->crush = P_ReadUINT8(save_p); + ht->texture = P_ReadINT32(save_p); + ht->direction = P_ReadINT32(save_p); + ht->tag = P_ReadINT16(save_p); + ht->origspeed = P_ReadFixed(save_p); + ht->sourceline = P_ReadFixed(save_p); if (ht->sector) ht->sector->ceilingdata = ht; return &ht->thinker; } -static thinker_t* LoadFloormoveThinker(actionf_p1 thinker) +static thinker_t* LoadFloormoveThinker(save_t *save_p, actionf_p1 thinker) { floormove_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->type = READUINT8(save_p); - ht->crush = READUINT8(save_p); - ht->sector = LoadSector(READUINT32(save_p)); - ht->direction = READINT32(save_p); - ht->texture = READINT32(save_p); - ht->floordestheight = READFIXED(save_p); - ht->speed = READFIXED(save_p); - ht->origspeed = READFIXED(save_p); - ht->delay = READFIXED(save_p); - ht->delaytimer = READFIXED(save_p); - ht->tag = READINT16(save_p); - ht->sourceline = READFIXED(save_p); + ht->type = P_ReadUINT8(save_p); + ht->crush = P_ReadUINT8(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->direction = P_ReadINT32(save_p); + ht->texture = P_ReadINT32(save_p); + ht->floordestheight = P_ReadFixed(save_p); + ht->speed = P_ReadFixed(save_p); + ht->origspeed = P_ReadFixed(save_p); + ht->delay = P_ReadFixed(save_p); + ht->delaytimer = P_ReadFixed(save_p); + ht->tag = P_ReadINT16(save_p); + ht->sourceline = P_ReadFixed(save_p); if (ht->sector) ht->sector->floordata = ht; return &ht->thinker; } -static thinker_t* LoadLightflashThinker(actionf_p1 thinker) +static thinker_t* LoadLightflashThinker(save_t *save_p, actionf_p1 thinker) { lightflash_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save_p)); - ht->maxlight = READINT32(save_p); - ht->minlight = READINT32(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->maxlight = P_ReadINT32(save_p); + ht->minlight = P_ReadINT32(save_p); if (ht->sector) ht->sector->lightingdata = ht; return &ht->thinker; } -static thinker_t* LoadStrobeThinker(actionf_p1 thinker) +static thinker_t* LoadStrobeThinker(save_t *save_p, actionf_p1 thinker) { strobe_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save_p)); - ht->count = READINT32(save_p); - ht->minlight = READINT16(save_p); - ht->maxlight = READINT16(save_p); - ht->darktime = READINT32(save_p); - ht->brighttime = READINT32(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->count = P_ReadINT32(save_p); + ht->minlight = P_ReadINT16(save_p); + ht->maxlight = P_ReadINT16(save_p); + ht->darktime = P_ReadINT32(save_p); + ht->brighttime = P_ReadINT32(save_p); if (ht->sector) ht->sector->lightingdata = ht; return &ht->thinker; } -static thinker_t* LoadGlowThinker(actionf_p1 thinker) +static thinker_t* LoadGlowThinker(save_t *save_p, actionf_p1 thinker) { glow_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save_p)); - ht->minlight = READINT16(save_p); - ht->maxlight = READINT16(save_p); - ht->direction = READINT16(save_p); - ht->speed = READINT16(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->minlight = P_ReadINT16(save_p); + ht->maxlight = P_ReadINT16(save_p); + ht->direction = P_ReadINT16(save_p); + ht->speed = P_ReadINT16(save_p); if (ht->sector) ht->sector->lightingdata = ht; return &ht->thinker; } -static thinker_t* LoadFireflickerThinker(actionf_p1 thinker) +static thinker_t* LoadFireflickerThinker(save_t *save_p, actionf_p1 thinker) { fireflicker_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save_p)); - ht->count = READINT32(save_p); - ht->resetcount = READINT32(save_p); - ht->maxlight = READINT16(save_p); - ht->minlight = READINT16(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->count = P_ReadINT32(save_p); + ht->resetcount = P_ReadINT32(save_p); + ht->maxlight = P_ReadINT16(save_p); + ht->minlight = P_ReadINT16(save_p); if (ht->sector) ht->sector->lightingdata = ht; return &ht->thinker; } -static thinker_t* LoadElevatorThinker(actionf_p1 thinker, boolean setplanedata) +static thinker_t* LoadElevatorThinker(save_t *save_p, actionf_p1 thinker, boolean setplanedata) { elevator_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->type = READUINT8(save_p); - ht->sector = LoadSector(READUINT32(save_p)); - ht->actionsector = LoadSector(READUINT32(save_p)); - ht->direction = READINT32(save_p); - ht->floordestheight = READFIXED(save_p); - ht->ceilingdestheight = READFIXED(save_p); - ht->speed = READFIXED(save_p); - ht->origspeed = READFIXED(save_p); - ht->low = READFIXED(save_p); - ht->high = READFIXED(save_p); - ht->distance = READFIXED(save_p); - ht->delay = READFIXED(save_p); - ht->delaytimer = READFIXED(save_p); - ht->floorwasheight = READFIXED(save_p); - ht->ceilingwasheight = READFIXED(save_p); - ht->sourceline = LoadLine(READUINT32(save_p)); + ht->type = P_ReadUINT8(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->actionsector = LoadSector(P_ReadUINT32(save_p)); + ht->direction = P_ReadINT32(save_p); + ht->floordestheight = P_ReadFixed(save_p); + ht->ceilingdestheight = P_ReadFixed(save_p); + ht->speed = P_ReadFixed(save_p); + ht->origspeed = P_ReadFixed(save_p); + ht->low = P_ReadFixed(save_p); + ht->high = P_ReadFixed(save_p); + ht->distance = P_ReadFixed(save_p); + ht->delay = P_ReadFixed(save_p); + ht->delaytimer = P_ReadFixed(save_p); + ht->floorwasheight = P_ReadFixed(save_p); + ht->ceilingwasheight = P_ReadFixed(save_p); + ht->sourceline = LoadLine(P_ReadUINT32(save_p)); if (ht->sector && setplanedata) { @@ -3544,21 +3848,21 @@ static thinker_t* LoadElevatorThinker(actionf_p1 thinker, boolean setplanedata) return &ht->thinker; } -static thinker_t* LoadCrumbleThinker(actionf_p1 thinker) +static thinker_t* LoadCrumbleThinker(save_t *save_p, actionf_p1 thinker) { crumble_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sourceline = LoadLine(READUINT32(save_p)); - ht->sector = LoadSector(READUINT32(save_p)); - ht->actionsector = LoadSector(READUINT32(save_p)); - ht->player = LoadPlayer(READUINT32(save_p)); - ht->direction = READINT32(save_p); - ht->origalpha = READINT32(save_p); - ht->timer = READINT32(save_p); - ht->speed = READFIXED(save_p); - ht->floorwasheight = READFIXED(save_p); - ht->ceilingwasheight = READFIXED(save_p); - ht->flags = READUINT8(save_p); + ht->sourceline = LoadLine(P_ReadUINT32(save_p)); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->actionsector = LoadSector(P_ReadUINT32(save_p)); + ht->player = LoadPlayer(P_ReadUINT32(save_p)); + ht->direction = P_ReadINT32(save_p); + ht->origalpha = P_ReadINT32(save_p); + ht->timer = P_ReadINT32(save_p); + ht->speed = P_ReadFixed(save_p); + ht->floorwasheight = P_ReadFixed(save_p); + ht->ceilingwasheight = P_ReadFixed(save_p); + ht->flags = P_ReadUINT8(save_p); if (ht->sector) ht->sector->floordata = ht; @@ -3566,123 +3870,123 @@ static thinker_t* LoadCrumbleThinker(actionf_p1 thinker) return &ht->thinker; } -static thinker_t* LoadScrollThinker(actionf_p1 thinker) +static thinker_t* LoadScrollThinker(save_t *save_p, actionf_p1 thinker) { scroll_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->dx = READFIXED(save_p); - ht->dy = READFIXED(save_p); - ht->affectee = READINT32(save_p); - ht->control = READINT32(save_p); - ht->last_height = READFIXED(save_p); - ht->vdx = READFIXED(save_p); - ht->vdy = READFIXED(save_p); - ht->accel = READINT32(save_p); - ht->exclusive = READINT32(save_p); - ht->type = READUINT8(save_p); + ht->dx = P_ReadFixed(save_p); + ht->dy = P_ReadFixed(save_p); + ht->affectee = P_ReadINT32(save_p); + ht->control = P_ReadINT32(save_p); + ht->last_height = P_ReadFixed(save_p); + ht->vdx = P_ReadFixed(save_p); + ht->vdy = P_ReadFixed(save_p); + ht->accel = P_ReadINT32(save_p); + ht->exclusive = P_ReadINT32(save_p); + ht->type = P_ReadUINT8(save_p); return &ht->thinker; } -static inline thinker_t* LoadFrictionThinker(actionf_p1 thinker) +static inline thinker_t* LoadFrictionThinker(save_t *save_p, actionf_p1 thinker) { friction_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->friction = READINT32(save_p); - ht->movefactor = READINT32(save_p); - ht->affectee = READINT32(save_p); - ht->referrer = READINT32(save_p); - ht->roverfriction = READUINT8(save_p); + ht->friction = P_ReadINT32(save_p); + ht->movefactor = P_ReadINT32(save_p); + ht->affectee = P_ReadINT32(save_p); + ht->referrer = P_ReadINT32(save_p); + ht->roverfriction = P_ReadUINT8(save_p); return &ht->thinker; } -static thinker_t* LoadPusherThinker(actionf_p1 thinker) +static thinker_t* LoadPusherThinker(save_t *save_p, actionf_p1 thinker) { pusher_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->type = READUINT8(save_p); - ht->x_mag = READFIXED(save_p); - ht->y_mag = READFIXED(save_p); - ht->z_mag = READFIXED(save_p); - ht->affectee = READINT32(save_p); - ht->roverpusher = READUINT8(save_p); - ht->referrer = READINT32(save_p); - ht->exclusive = READINT32(save_p); - ht->slider = READINT32(save_p); + ht->type = P_ReadUINT8(save_p); + ht->x_mag = P_ReadFixed(save_p); + ht->y_mag = P_ReadFixed(save_p); + ht->z_mag = P_ReadFixed(save_p); + ht->affectee = P_ReadINT32(save_p); + ht->roverpusher = P_ReadUINT8(save_p); + ht->referrer = P_ReadINT32(save_p); + ht->exclusive = P_ReadINT32(save_p); + ht->slider = P_ReadINT32(save_p); return &ht->thinker; } -static inline thinker_t* LoadLaserThinker(actionf_p1 thinker) +static inline thinker_t* LoadLaserThinker(save_t *save_p, actionf_p1 thinker) { laserthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->tag = READINT16(save_p); - ht->sourceline = LoadLine(READUINT32(save_p)); - ht->nobosses = READUINT8(save_p); + ht->tag = P_ReadINT16(save_p); + ht->sourceline = LoadLine(P_ReadUINT32(save_p)); + ht->nobosses = P_ReadUINT8(save_p); return &ht->thinker; } -static inline thinker_t* LoadLightlevelThinker(actionf_p1 thinker) +static inline thinker_t* LoadLightlevelThinker(save_t *save_p, actionf_p1 thinker) { lightlevel_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save_p)); - ht->sourcelevel = READINT16(save_p); - ht->destlevel = READINT16(save_p); - ht->fixedcurlevel = READFIXED(save_p); - ht->fixedpertic = READFIXED(save_p); - ht->timer = READINT32(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->sourcelevel = P_ReadINT16(save_p); + ht->destlevel = P_ReadINT16(save_p); + ht->fixedcurlevel = P_ReadFixed(save_p); + ht->fixedpertic = P_ReadFixed(save_p); + ht->timer = P_ReadINT32(save_p); if (ht->sector) ht->sector->lightingdata = ht; return &ht->thinker; } -static inline thinker_t* LoadExecutorThinker(actionf_p1 thinker) +static inline thinker_t* LoadExecutorThinker(save_t *save_p, actionf_p1 thinker) { executor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->line = LoadLine(READUINT32(save_p)); - ht->caller = LoadMobj(READUINT32(save_p)); - ht->sector = LoadSector(READUINT32(save_p)); - ht->timer = READINT32(save_p); + ht->line = LoadLine(P_ReadUINT32(save_p)); + ht->caller = LoadMobj(P_ReadUINT32(save_p)); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->timer = P_ReadINT32(save_p); return &ht->thinker; } -static inline thinker_t* LoadDisappearThinker(actionf_p1 thinker) +static inline thinker_t* LoadDisappearThinker(save_t *save_p, actionf_p1 thinker) { disappear_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->appeartime = READUINT32(save_p); - ht->disappeartime = READUINT32(save_p); - ht->offset = READUINT32(save_p); - ht->timer = READUINT32(save_p); - ht->affectee = READINT32(save_p); - ht->sourceline = READINT32(save_p); - ht->exists = READINT32(save_p); + ht->appeartime = P_ReadUINT32(save_p); + ht->disappeartime = P_ReadUINT32(save_p); + ht->offset = P_ReadUINT32(save_p); + ht->timer = P_ReadUINT32(save_p); + ht->affectee = P_ReadINT32(save_p); + ht->sourceline = P_ReadINT32(save_p); + ht->exists = P_ReadINT32(save_p); return &ht->thinker; } -static inline thinker_t* LoadFadeThinker(actionf_p1 thinker) +static inline thinker_t* LoadFadeThinker(save_t *save_p, actionf_p1 thinker) { sector_t *ss; fade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->dest_exc = GetNetColormapFromList(READUINT32(save_p)); - ht->sectornum = READUINT32(save_p); - ht->ffloornum = READUINT32(save_p); - ht->alpha = READINT32(save_p); - ht->sourcevalue = READINT16(save_p); - ht->destvalue = READINT16(save_p); - ht->destlightlevel = READINT16(save_p); - ht->speed = READINT16(save_p); - ht->ticbased = (boolean)READUINT8(save_p); - ht->timer = READINT32(save_p); - ht->doexists = READUINT8(save_p); - ht->dotranslucent = READUINT8(save_p); - ht->dolighting = READUINT8(save_p); - ht->docolormap = READUINT8(save_p); - ht->docollision = READUINT8(save_p); - ht->doghostfade = READUINT8(save_p); - ht->exactalpha = READUINT8(save_p); + ht->dest_exc = GetNetColormapFromList(P_ReadUINT32(save_p)); + ht->sectornum = P_ReadUINT32(save_p); + ht->ffloornum = P_ReadUINT32(save_p); + ht->alpha = P_ReadINT32(save_p); + ht->sourcevalue = P_ReadINT16(save_p); + ht->destvalue = P_ReadINT16(save_p); + ht->destlightlevel = P_ReadINT16(save_p); + ht->speed = P_ReadINT16(save_p); + ht->ticbased = (boolean)P_ReadUINT8(save_p); + ht->timer = P_ReadINT32(save_p); + ht->doexists = P_ReadUINT8(save_p); + ht->dotranslucent = P_ReadUINT8(save_p); + ht->dolighting = P_ReadUINT8(save_p); + ht->docolormap = P_ReadUINT8(save_p); + ht->docollision = P_ReadUINT8(save_p); + ht->doghostfade = P_ReadUINT8(save_p); + ht->exactalpha = P_ReadUINT8(save_p); ss = LoadSector(ht->sectornum); if (ss) @@ -3703,176 +4007,176 @@ static inline thinker_t* LoadFadeThinker(actionf_p1 thinker) return &ht->thinker; } -static inline thinker_t* LoadFadeColormapThinker(actionf_p1 thinker) +static inline thinker_t* LoadFadeColormapThinker(save_t *save_p, actionf_p1 thinker) { fadecolormap_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save_p)); - ht->source_exc = GetNetColormapFromList(READUINT32(save_p)); - ht->dest_exc = GetNetColormapFromList(READUINT32(save_p)); - ht->ticbased = (boolean)READUINT8(save_p); - ht->duration = READINT32(save_p); - ht->timer = READINT32(save_p); + ht->sector = LoadSector(P_ReadUINT32(save_p)); + ht->source_exc = GetNetColormapFromList(P_ReadUINT32(save_p)); + ht->dest_exc = GetNetColormapFromList(P_ReadUINT32(save_p)); + ht->ticbased = (boolean)P_ReadUINT8(save_p); + ht->duration = P_ReadINT32(save_p); + ht->timer = P_ReadINT32(save_p); if (ht->sector) ht->sector->fadecolormapdata = ht; return &ht->thinker; } -static inline thinker_t* LoadPlaneDisplaceThinker(actionf_p1 thinker) +static inline thinker_t* LoadPlaneDisplaceThinker(save_t *save_p, actionf_p1 thinker) { planedisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->affectee = READINT32(save_p); - ht->control = READINT32(save_p); - ht->last_height = READFIXED(save_p); - ht->speed = READFIXED(save_p); - ht->type = READUINT8(save_p); + ht->affectee = P_ReadINT32(save_p); + ht->control = P_ReadINT32(save_p); + ht->last_height = P_ReadFixed(save_p); + ht->speed = P_ReadFixed(save_p); + ht->type = P_ReadUINT8(save_p); return &ht->thinker; } -static inline thinker_t* LoadDynamicLineSlopeThinker(actionf_p1 thinker) +static inline thinker_t* LoadDynamicLineSlopeThinker(save_t *save_p, actionf_p1 thinker) { dynlineplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->type = READUINT8(save_p); - ht->slope = LoadSlope(READUINT32(save_p)); - ht->sourceline = LoadLine(READUINT32(save_p)); - ht->extent = READFIXED(save_p); + ht->type = P_ReadUINT8(save_p); + ht->slope = LoadSlope(P_ReadUINT32(save_p)); + ht->sourceline = LoadLine(P_ReadUINT32(save_p)); + ht->extent = P_ReadFixed(save_p); return &ht->thinker; } -static inline thinker_t* LoadDynamicVertexSlopeThinker(actionf_p1 thinker) +static inline thinker_t* LoadDynamicVertexSlopeThinker(save_t *save_p, actionf_p1 thinker) { size_t i; dynvertexplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->slope = LoadSlope(READUINT32(save_p)); + ht->slope = LoadSlope(P_ReadUINT32(save_p)); for (i = 0; i < 3; i++) - ht->secs[i] = LoadSector(READUINT32(save_p)); - READMEM(save_p, ht->vex, sizeof(ht->vex)); - READMEM(save_p, ht->origsecheights, sizeof(ht->origsecheights)); - READMEM(save_p, ht->origvecheights, sizeof(ht->origvecheights)); - ht->relative = READUINT8(save_p); + ht->secs[i] = LoadSector(P_ReadUINT32(save_p)); + P_ReadMem(save_p, ht->vex, sizeof(ht->vex)); + P_ReadMem(save_p, ht->origsecheights, sizeof(ht->origsecheights)); + P_ReadMem(save_p, ht->origvecheights, sizeof(ht->origvecheights)); + ht->relative = P_ReadUINT8(save_p); return &ht->thinker; } -static inline thinker_t* LoadPolyrotatetThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolyrotatetThinker(save_t *save_p, actionf_p1 thinker) { polyrotate_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save_p); - ht->speed = READINT32(save_p); - ht->distance = READINT32(save_p); - ht->turnobjs = READUINT8(save_p); + ht->polyObjNum = P_ReadINT32(save_p); + ht->speed = P_ReadINT32(save_p); + ht->distance = P_ReadINT32(save_p); + ht->turnobjs = P_ReadUINT8(save_p); return &ht->thinker; } -static thinker_t* LoadPolymoveThinker(actionf_p1 thinker) +static thinker_t* LoadPolymoveThinker(save_t *save_p, actionf_p1 thinker) { polymove_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save_p); - ht->speed = READINT32(save_p); - ht->momx = READFIXED(save_p); - ht->momy = READFIXED(save_p); - ht->distance = READINT32(save_p); - ht->angle = READANGLE(save_p); + ht->polyObjNum = P_ReadINT32(save_p); + ht->speed = P_ReadINT32(save_p); + ht->momx = P_ReadFixed(save_p); + ht->momy = P_ReadFixed(save_p); + ht->distance = P_ReadINT32(save_p); + ht->angle = P_ReadAngle(save_p); return &ht->thinker; } -static inline thinker_t* LoadPolywaypointThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolywaypointThinker(save_t *save_p, actionf_p1 thinker) { polywaypoint_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save_p); - ht->speed = READINT32(save_p); - ht->sequence = READINT32(save_p); - ht->pointnum = READINT32(save_p); - ht->direction = READINT32(save_p); - ht->returnbehavior = READUINT8(save_p); - ht->continuous = READUINT8(save_p); - ht->stophere = READUINT8(save_p); + ht->polyObjNum = P_ReadINT32(save_p); + ht->speed = P_ReadINT32(save_p); + ht->sequence = P_ReadINT32(save_p); + ht->pointnum = P_ReadINT32(save_p); + ht->direction = P_ReadINT32(save_p); + ht->returnbehavior = P_ReadUINT8(save_p); + ht->continuous = P_ReadUINT8(save_p); + ht->stophere = P_ReadUINT8(save_p); return &ht->thinker; } -static inline thinker_t* LoadPolyslidedoorThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolyslidedoorThinker(save_t *save_p, actionf_p1 thinker) { polyslidedoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save_p); - ht->delay = READINT32(save_p); - ht->delayCount = READINT32(save_p); - ht->initSpeed = READINT32(save_p); - ht->speed = READINT32(save_p); - ht->initDistance = READINT32(save_p); - ht->distance = READINT32(save_p); - ht->initAngle = READUINT32(save_p); - ht->angle = READUINT32(save_p); - ht->revAngle = READUINT32(save_p); - ht->momx = READFIXED(save_p); - ht->momy = READFIXED(save_p); - ht->closing = READUINT8(save_p); + ht->polyObjNum = P_ReadINT32(save_p); + ht->delay = P_ReadINT32(save_p); + ht->delayCount = P_ReadINT32(save_p); + ht->initSpeed = P_ReadINT32(save_p); + ht->speed = P_ReadINT32(save_p); + ht->initDistance = P_ReadINT32(save_p); + ht->distance = P_ReadINT32(save_p); + ht->initAngle = P_ReadUINT32(save_p); + ht->angle = P_ReadUINT32(save_p); + ht->revAngle = P_ReadUINT32(save_p); + ht->momx = P_ReadFixed(save_p); + ht->momy = P_ReadFixed(save_p); + ht->closing = P_ReadUINT8(save_p); return &ht->thinker; } -static inline thinker_t* LoadPolyswingdoorThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolyswingdoorThinker(save_t *save_p, actionf_p1 thinker) { polyswingdoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save_p); - ht->delay = READINT32(save_p); - ht->delayCount = READINT32(save_p); - ht->initSpeed = READINT32(save_p); - ht->speed = READINT32(save_p); - ht->initDistance = READINT32(save_p); - ht->distance = READINT32(save_p); - ht->closing = READUINT8(save_p); + ht->polyObjNum = P_ReadINT32(save_p); + ht->delay = P_ReadINT32(save_p); + ht->delayCount = P_ReadINT32(save_p); + ht->initSpeed = P_ReadINT32(save_p); + ht->speed = P_ReadINT32(save_p); + ht->initDistance = P_ReadINT32(save_p); + ht->distance = P_ReadINT32(save_p); + ht->closing = P_ReadUINT8(save_p); return &ht->thinker; } -static inline thinker_t* LoadPolydisplaceThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolydisplaceThinker(save_t *save_p, actionf_p1 thinker) { polydisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save_p); - ht->controlSector = LoadSector(READUINT32(save_p)); - ht->dx = READFIXED(save_p); - ht->dy = READFIXED(save_p); - ht->oldHeights = READFIXED(save_p); + ht->polyObjNum = P_ReadINT32(save_p); + ht->controlSector = LoadSector(P_ReadUINT32(save_p)); + ht->dx = P_ReadFixed(save_p); + ht->dy = P_ReadFixed(save_p); + ht->oldHeights = P_ReadFixed(save_p); return &ht->thinker; } -static inline thinker_t* LoadPolyrotdisplaceThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolyrotdisplaceThinker(save_t *save_p, actionf_p1 thinker) { polyrotdisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save_p); - ht->controlSector = LoadSector(READUINT32(save_p)); - ht->rotscale = READFIXED(save_p); - ht->turnobjs = READUINT8(save_p); - ht->oldHeights = READFIXED(save_p); + ht->polyObjNum = P_ReadINT32(save_p); + ht->controlSector = LoadSector(P_ReadUINT32(save_p)); + ht->rotscale = P_ReadFixed(save_p); + ht->turnobjs = P_ReadUINT8(save_p); + ht->oldHeights = P_ReadFixed(save_p); return &ht->thinker; } -static thinker_t* LoadPolyfadeThinker(actionf_p1 thinker) +static thinker_t* LoadPolyfadeThinker(save_t *save_p, actionf_p1 thinker) { polyfade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - ht->polyObjNum = READINT32(save_p); - ht->sourcevalue = READINT32(save_p); - ht->destvalue = READINT32(save_p); - ht->docollision = (boolean)READUINT8(save_p); - ht->doghostfade = (boolean)READUINT8(save_p); - ht->ticbased = (boolean)READUINT8(save_p); - ht->duration = READINT32(save_p); - ht->timer = READINT32(save_p); + ht->polyObjNum = P_ReadINT32(save_p); + ht->sourcevalue = P_ReadINT32(save_p); + ht->destvalue = P_ReadINT32(save_p); + ht->docollision = (boolean)P_ReadUINT8(save_p); + ht->doghostfade = (boolean)P_ReadUINT8(save_p); + ht->ticbased = (boolean)P_ReadUINT8(save_p); + ht->duration = P_ReadINT32(save_p); + ht->timer = P_ReadINT32(save_p); return &ht->thinker; } -static void P_NetUnArchiveThinkers(void) +static void P_NetUnArchiveThinkers(save_t *save_p) { thinker_t *currentthinker; thinker_t *next; @@ -3881,7 +4185,7 @@ static void P_NetUnArchiveThinkers(void) UINT32 i; UINT32 numloaded = 0; - if (READUINT32(save_p) != ARCHIVEBLOCK_THINKERS) + if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_THINKERS) I_Error("Bad $$$.sav at archive block Thinkers"); // remove all the current thinkers @@ -3919,7 +4223,7 @@ static void P_NetUnArchiveThinkers(void) for (;;) { thinker_t* th = NULL; - tclass = READUINT8(save_p); + tclass = P_ReadUINT8(save_p); if (tclass == tc_end) break; // leave the saved thinker reading loop @@ -3928,167 +4232,167 @@ static void P_NetUnArchiveThinkers(void) switch (tclass) { case tc_mobj: - th = LoadMobjThinker((actionf_p1)P_MobjThinker); + th = LoadMobjThinker(save_p, (actionf_p1)P_MobjThinker); break; case tc_ceiling: - th = LoadCeilingThinker((actionf_p1)T_MoveCeiling); + th = LoadCeilingThinker(save_p, (actionf_p1)T_MoveCeiling); break; case tc_crushceiling: - th = LoadCeilingThinker((actionf_p1)T_CrushCeiling); + th = LoadCeilingThinker(save_p, (actionf_p1)T_CrushCeiling); break; case tc_floor: - th = LoadFloormoveThinker((actionf_p1)T_MoveFloor); + th = LoadFloormoveThinker(save_p, (actionf_p1)T_MoveFloor); break; case tc_flash: - th = LoadLightflashThinker((actionf_p1)T_LightningFlash); + th = LoadLightflashThinker(save_p, (actionf_p1)T_LightningFlash); break; case tc_strobe: - th = LoadStrobeThinker((actionf_p1)T_StrobeFlash); + th = LoadStrobeThinker(save_p, (actionf_p1)T_StrobeFlash); break; case tc_glow: - th = LoadGlowThinker((actionf_p1)T_Glow); + th = LoadGlowThinker(save_p, (actionf_p1)T_Glow); break; case tc_fireflicker: - th = LoadFireflickerThinker((actionf_p1)T_FireFlicker); + th = LoadFireflickerThinker(save_p, (actionf_p1)T_FireFlicker); break; case tc_elevator: - th = LoadElevatorThinker((actionf_p1)T_MoveElevator, true); + th = LoadElevatorThinker(save_p, (actionf_p1)T_MoveElevator, true); break; case tc_continuousfalling: - th = LoadContinuousFallThinker((actionf_p1)T_ContinuousFalling); + th = LoadContinuousFallThinker(save_p, (actionf_p1)T_ContinuousFalling); break; case tc_thwomp: - th = LoadThwompThinker((actionf_p1)T_ThwompSector); + th = LoadThwompThinker(save_p, (actionf_p1)T_ThwompSector); break; case tc_noenemies: - th = LoadNoEnemiesThinker((actionf_p1)T_NoEnemiesSector); + th = LoadNoEnemiesThinker(save_p, (actionf_p1)T_NoEnemiesSector); break; case tc_eachtime: - th = LoadEachTimeThinker((actionf_p1)T_EachTimeThinker); + th = LoadEachTimeThinker(save_p, (actionf_p1)T_EachTimeThinker); break; case tc_raisesector: - th = LoadRaiseThinker((actionf_p1)T_RaiseSector); + th = LoadRaiseThinker(save_p, (actionf_p1)T_RaiseSector); break; case tc_camerascanner: - th = LoadElevatorThinker((actionf_p1)T_CameraScanner, false); + th = LoadElevatorThinker(save_p, (actionf_p1)T_CameraScanner, false); break; case tc_bouncecheese: - th = LoadBounceCheeseThinker((actionf_p1)T_BounceCheese); + th = LoadBounceCheeseThinker(save_p, (actionf_p1)T_BounceCheese); break; case tc_startcrumble: - th = LoadCrumbleThinker((actionf_p1)T_StartCrumble); + th = LoadCrumbleThinker(save_p, (actionf_p1)T_StartCrumble); break; case tc_marioblock: - th = LoadMarioBlockThinker((actionf_p1)T_MarioBlock); + th = LoadMarioBlockThinker(save_p, (actionf_p1)T_MarioBlock); break; case tc_marioblockchecker: - th = LoadMarioCheckThinker((actionf_p1)T_MarioBlockChecker); + th = LoadMarioCheckThinker(save_p, (actionf_p1)T_MarioBlockChecker); break; case tc_floatsector: - th = LoadFloatThinker((actionf_p1)T_FloatSector); + th = LoadFloatThinker(save_p, (actionf_p1)T_FloatSector); break; case tc_laserflash: - th = LoadLaserThinker((actionf_p1)T_LaserFlash); + th = LoadLaserThinker(save_p, (actionf_p1)T_LaserFlash); break; case tc_lightfade: - th = LoadLightlevelThinker((actionf_p1)T_LightFade); + th = LoadLightlevelThinker(save_p, (actionf_p1)T_LightFade); break; case tc_executor: - th = LoadExecutorThinker((actionf_p1)T_ExecutorDelay); + th = LoadExecutorThinker(save_p, (actionf_p1)T_ExecutorDelay); restoreNum = true; break; case tc_disappear: - th = LoadDisappearThinker((actionf_p1)T_Disappear); + th = LoadDisappearThinker(save_p, (actionf_p1)T_Disappear); break; case tc_fade: - th = LoadFadeThinker((actionf_p1)T_Fade); + th = LoadFadeThinker(save_p, (actionf_p1)T_Fade); break; case tc_fadecolormap: - th = LoadFadeColormapThinker((actionf_p1)T_FadeColormap); + th = LoadFadeColormapThinker(save_p, (actionf_p1)T_FadeColormap); break; case tc_planedisplace: - th = LoadPlaneDisplaceThinker((actionf_p1)T_PlaneDisplace); + th = LoadPlaneDisplaceThinker(save_p, (actionf_p1)T_PlaneDisplace); break; case tc_polyrotate: - th = LoadPolyrotatetThinker((actionf_p1)T_PolyObjRotate); + th = LoadPolyrotatetThinker(save_p, (actionf_p1)T_PolyObjRotate); break; case tc_polymove: - th = LoadPolymoveThinker((actionf_p1)T_PolyObjMove); + th = LoadPolymoveThinker(save_p, (actionf_p1)T_PolyObjMove); break; case tc_polywaypoint: - th = LoadPolywaypointThinker((actionf_p1)T_PolyObjWaypoint); + th = LoadPolywaypointThinker(save_p, (actionf_p1)T_PolyObjWaypoint); break; case tc_polyslidedoor: - th = LoadPolyslidedoorThinker((actionf_p1)T_PolyDoorSlide); + th = LoadPolyslidedoorThinker(save_p, (actionf_p1)T_PolyDoorSlide); break; case tc_polyswingdoor: - th = LoadPolyswingdoorThinker((actionf_p1)T_PolyDoorSwing); + th = LoadPolyswingdoorThinker(save_p, (actionf_p1)T_PolyDoorSwing); break; case tc_polyflag: - th = LoadPolymoveThinker((actionf_p1)T_PolyObjFlag); + th = LoadPolymoveThinker(save_p, (actionf_p1)T_PolyObjFlag); break; case tc_polydisplace: - th = LoadPolydisplaceThinker((actionf_p1)T_PolyObjDisplace); + th = LoadPolydisplaceThinker(save_p, (actionf_p1)T_PolyObjDisplace); break; case tc_polyrotdisplace: - th = LoadPolyrotdisplaceThinker((actionf_p1)T_PolyObjRotDisplace); + th = LoadPolyrotdisplaceThinker(save_p, (actionf_p1)T_PolyObjRotDisplace); break; case tc_polyfade: - th = LoadPolyfadeThinker((actionf_p1)T_PolyObjFade); + th = LoadPolyfadeThinker(save_p, (actionf_p1)T_PolyObjFade); break; case tc_dynslopeline: - th = LoadDynamicLineSlopeThinker((actionf_p1)T_DynamicSlopeLine); + th = LoadDynamicLineSlopeThinker(save_p, (actionf_p1)T_DynamicSlopeLine); break; case tc_dynslopevert: - th = LoadDynamicVertexSlopeThinker((actionf_p1)T_DynamicSlopeVert); + th = LoadDynamicVertexSlopeThinker(save_p, (actionf_p1)T_DynamicSlopeVert); break; case tc_scroll: - th = LoadScrollThinker((actionf_p1)T_Scroll); + th = LoadScrollThinker(save_p, (actionf_p1)T_Scroll); break; case tc_friction: - th = LoadFrictionThinker((actionf_p1)T_Friction); + th = LoadFrictionThinker(save_p, (actionf_p1)T_Friction); break; case tc_pusher: - th = LoadPusherThinker((actionf_p1)T_Pusher); + th = LoadPusherThinker(save_p, (actionf_p1)T_Pusher); break; default: @@ -4128,29 +4432,29 @@ static void P_NetUnArchiveThinkers(void) #define PD_FLAGS 0x01 #define PD_TRANS 0x02 -static inline void P_ArchivePolyObj(polyobj_t *po) +static inline void P_ArchivePolyObj(save_t *save_p, polyobj_t *po) { UINT8 diff = 0; - WRITEINT32(save_p, po->id); - WRITEANGLE(save_p, po->angle); + P_WriteINT32(save_p, po->id); + P_WriteAngle(save_p, po->angle); - WRITEFIXED(save_p, po->spawnSpot.x); - WRITEFIXED(save_p, po->spawnSpot.y); + P_WriteFixed(save_p, po->spawnSpot.x); + P_WriteFixed(save_p, po->spawnSpot.y); if (po->flags != po->spawnflags) diff |= PD_FLAGS; if (po->translucency != po->spawntrans) diff |= PD_TRANS; - WRITEUINT8(save_p, diff); + P_WriteUINT8(save_p, diff); if (diff & PD_FLAGS) - WRITEINT32(save_p, po->flags); + P_WriteINT32(save_p, po->flags); if (diff & PD_TRANS) - WRITEINT32(save_p, po->translucency); + P_WriteINT32(save_p, po->translucency); } -static inline void P_UnArchivePolyObj(polyobj_t *po) +static inline void P_UnArchivePolyObj(save_t *save_p, polyobj_t *po) { INT32 id; UINT32 angle; @@ -4162,19 +4466,19 @@ static inline void P_UnArchivePolyObj(polyobj_t *po) // when they first start to run. po->thinker = NULL; - id = READINT32(save_p); + id = P_ReadINT32(save_p); - angle = READANGLE(save_p); + angle = P_ReadAngle(save_p); - x = READFIXED(save_p); - y = READFIXED(save_p); + x = P_ReadFixed(save_p); + y = P_ReadFixed(save_p); - diff = READUINT8(save_p); + diff = P_ReadUINT8(save_p); if (diff & PD_FLAGS) - po->flags = READINT32(save_p); + po->flags = P_ReadINT32(save_p); if (diff & PD_TRANS) - po->translucency = READINT32(save_p); + po->translucency = P_ReadINT32(save_p); // if the object is bad or isn't in the id hash, we can do nothing more // with it, so return now @@ -4185,33 +4489,33 @@ static inline void P_UnArchivePolyObj(polyobj_t *po) Polyobj_MoveOnLoad(po, angle, x, y); } -static inline void P_ArchivePolyObjects(void) +static inline void P_ArchivePolyObjects(save_t *save_p) { INT32 i; - WRITEUINT32(save_p, ARCHIVEBLOCK_POBJS); + P_WriteUINT32(save_p, ARCHIVEBLOCK_POBJS); // save number of polyobjects - WRITEINT32(save_p, numPolyObjects); + P_WriteINT32(save_p, numPolyObjects); for (i = 0; i < numPolyObjects; ++i) - P_ArchivePolyObj(&PolyObjects[i]); + P_ArchivePolyObj(save_p, &PolyObjects[i]); } -static inline void P_UnArchivePolyObjects(void) +static inline void P_UnArchivePolyObjects(save_t *save_p) { INT32 i, numSavedPolys; - if (READUINT32(save_p) != ARCHIVEBLOCK_POBJS) + if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_POBJS) I_Error("Bad $$$.sav at archive block Pobjs"); - numSavedPolys = READINT32(save_p); + numSavedPolys = P_ReadINT32(save_p); if (numSavedPolys != numPolyObjects) I_Error("P_UnArchivePolyObjects: polyobj count inconsistency\n"); for (i = 0; i < numSavedPolys; ++i) - P_UnArchivePolyObj(&PolyObjects[i]); + P_UnArchivePolyObj(save_p, &PolyObjects[i]); } static inline void P_FinishMobjs(void) @@ -4223,7 +4527,7 @@ static inline void P_FinishMobjs(void) for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ]; currentthinker = currentthinker->next) { - if (currentthinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (currentthinker->removing) continue; mobj = (mobj_t *)currentthinker; @@ -4241,7 +4545,7 @@ static void P_RelinkPointers(void) for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ]; currentthinker = currentthinker->next) { - if (currentthinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (currentthinker->removing) continue; mobj = (mobj_t *)currentthinker; @@ -4329,11 +4633,11 @@ static void P_RelinkPointers(void) } } -static inline void P_NetArchiveSpecials(void) +static inline void P_NetArchiveSpecials(save_t *save_p) { size_t i, z; - WRITEUINT32(save_p, ARCHIVEBLOCK_SPECIALS); + P_WriteUINT32(save_p, ARCHIVEBLOCK_SPECIALS); // itemrespawn queue for deathmatch i = iquetail; @@ -4343,53 +4647,54 @@ static inline void P_NetArchiveSpecials(void) { if (&mapthings[z] == itemrespawnque[i]) { - WRITEUINT32(save_p, z); + P_WriteUINT32(save_p, z); break; } } - WRITEUINT32(save_p, itemrespawntime[i]); + P_WriteUINT32(save_p, itemrespawntime[i]); i = (i + 1) & (ITEMQUESIZE-1); } // end delimiter - WRITEUINT32(save_p, 0xffffffff); + P_WriteUINT32(save_p, 0xffffffff); // Sky number - WRITEINT32(save_p, globallevelskynum); + P_WriteINT32(save_p, globallevelskynum); // Current global weather type - WRITEUINT8(save_p, globalweather); + P_WriteUINT8(save_p, globalweather); if (metalplayback) // Is metal sonic running? { - WRITEUINT8(save_p, 0x01); - G_SaveMetal(&save_p); + UINT8 *p = &save_p->buf[save_p->pos+1]; + P_WriteUINT8(save_p, 0x01); + G_SaveMetal(&p); } else - WRITEUINT8(save_p, 0x00); + P_WriteUINT8(save_p, 0x00); } -static void P_NetUnArchiveSpecials(void) +static void P_NetUnArchiveSpecials(save_t *save_p) { size_t i; INT32 j; - if (READUINT32(save_p) != ARCHIVEBLOCK_SPECIALS) + if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_SPECIALS) I_Error("Bad $$$.sav at archive block Specials"); // BP: added save itemrespawn queue for deathmatch iquetail = iquehead = 0; - while ((i = READUINT32(save_p)) != 0xffffffff) + while ((i = P_ReadUINT32(save_p)) != 0xffffffff) { itemrespawnque[iquehead] = &mapthings[i]; - itemrespawntime[iquehead++] = READINT32(save_p); + itemrespawntime[iquehead++] = P_ReadINT32(save_p); } - j = READINT32(save_p); + j = P_ReadINT32(save_p); if (j != globallevelskynum) P_SetupLevelSky(j, true); - globalweather = READUINT8(save_p); + globalweather = P_ReadUINT8(save_p); if (globalweather) { @@ -4404,14 +4709,17 @@ static void P_NetUnArchiveSpecials(void) P_SwitchWeather(globalweather); } - if (READUINT8(save_p) == 0x01) // metal sonic - G_LoadMetal(&save_p); + if (P_ReadUINT8(save_p) == 0x01) // metal sonic + { + UINT8 *p = &save_p->buf[save_p->pos]; + G_LoadMetal(&p); + } } // ======================================================================= // Misc // ======================================================================= -static inline void P_ArchiveMisc(INT16 mapnum) +static inline void P_ArchiveMisc(save_t *save_p, INT16 mapnum) { //lastmapsaved = mapnum; lastmaploaded = mapnum; @@ -4419,16 +4727,16 @@ static inline void P_ArchiveMisc(INT16 mapnum) if (gamecomplete) mapnum |= 8192; - WRITEINT16(save_p, mapnum); - WRITEUINT16(save_p, emeralds+357); - WRITESTRINGN(save_p, timeattackfolder, sizeof(timeattackfolder)); + P_WriteINT16(save_p, mapnum); + P_WriteUINT16(save_p, emeralds+357); + P_WriteStringN(save_p, timeattackfolder, sizeof(timeattackfolder)); } -static inline void P_UnArchiveSPGame(INT16 mapoverride) +static inline void P_UnArchiveSPGame(save_t *save_p, INT16 mapoverride) { char testname[sizeof(timeattackfolder)]; - gamemap = READINT16(save_p); + gamemap = P_ReadINT16(save_p); if (mapoverride != 0) { @@ -4449,9 +4757,9 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride) tokenlist = 0; token = 0; - savedata.emeralds = READUINT16(save_p)-357; + savedata.emeralds = P_ReadUINT16(save_p)-357; - READSTRINGN(save_p, testname, sizeof(testname)); + P_ReadStringN(save_p, testname, sizeof(testname)); if (strcmp(testname, timeattackfolder)) { @@ -4465,100 +4773,106 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride) playeringame[consoleplayer] = true; } -static void P_NetArchiveMisc(boolean resending) +static void P_NetArchiveMisc(save_t *save_p, boolean resending) { INT32 i; - WRITEUINT32(save_p, ARCHIVEBLOCK_MISC); + P_WriteUINT32(save_p, ARCHIVEBLOCK_MISC); if (resending) - WRITEUINT32(save_p, gametic); - WRITEINT16(save_p, gamemap); + P_WriteUINT32(save_p, gametic); + P_WriteINT16(save_p, gamemap); if (gamestate != GS_LEVEL) - WRITEINT16(save_p, GS_WAITINGPLAYERS); // nice hack to put people back into waitingplayers + P_WriteINT16(save_p, GS_WAITINGPLAYERS); // nice hack to put people back into waitingplayers else - WRITEINT16(save_p, gamestate); - WRITEINT16(save_p, gametype); + P_WriteINT16(save_p, gamestate); + P_WriteINT16(save_p, gametype); { UINT32 pig = 0; for (i = 0; i < MAXPLAYERS; i++) pig |= (playeringame[i] != 0)<<i; - WRITEUINT32(save_p, pig); + P_WriteUINT32(save_p, pig); } - WRITEUINT32(save_p, P_GetRandSeed()); + P_WriteUINT32(save_p, P_GetRandSeed()); - WRITEUINT32(save_p, tokenlist); + P_WriteUINT32(save_p, tokenlist); - WRITEUINT32(save_p, leveltime); - WRITEUINT32(save_p, ssspheres); - WRITEINT16(save_p, lastmap); - WRITEUINT16(save_p, bossdisabled); + P_WriteUINT32(save_p, leveltime); + P_WriteUINT32(save_p, ssspheres); + P_WriteINT16(save_p, lastmap); + P_WriteUINT16(save_p, bossdisabled); - WRITEUINT16(save_p, emeralds); + P_WriteUINT16(save_p, emeralds); { UINT8 globools = 0; if (stagefailed) globools |= 1; if (stoppedclock) globools |= (1<<1); - WRITEUINT8(save_p, globools); + P_WriteUINT8(save_p, globools); } - WRITEUINT32(save_p, token); - WRITEINT32(save_p, sstimer); - WRITEUINT32(save_p, bluescore); - WRITEUINT32(save_p, redscore); + P_WriteUINT32(save_p, token); + P_WriteINT32(save_p, sstimer); + P_WriteUINT32(save_p, bluescore); + P_WriteUINT32(save_p, redscore); - WRITEUINT16(save_p, skincolor_redteam); - WRITEUINT16(save_p, skincolor_blueteam); - WRITEUINT16(save_p, skincolor_redring); - WRITEUINT16(save_p, skincolor_bluering); + P_WriteUINT16(save_p, skincolor_redteam); + P_WriteUINT16(save_p, skincolor_blueteam); + P_WriteUINT16(save_p, skincolor_redring); + P_WriteUINT16(save_p, skincolor_bluering); - WRITEINT32(save_p, modulothing); + P_WriteINT32(save_p, modulothing); - WRITEINT16(save_p, autobalance); - WRITEINT16(save_p, teamscramble); + P_WriteINT16(save_p, autobalance); + P_WriteINT16(save_p, teamscramble); for (i = 0; i < MAXPLAYERS; i++) - WRITEINT16(save_p, scrambleplayers[i]); + P_WriteINT16(save_p, scrambleplayers[i]); for (i = 0; i < MAXPLAYERS; i++) - WRITEINT16(save_p, scrambleteams[i]); + P_WriteINT16(save_p, scrambleteams[i]); - WRITEINT16(save_p, scrambletotal); - WRITEINT16(save_p, scramblecount); + P_WriteINT16(save_p, scrambletotal); + P_WriteINT16(save_p, scramblecount); - WRITEUINT32(save_p, countdown); - WRITEUINT32(save_p, countdown2); + P_WriteUINT32(save_p, countdown); + P_WriteUINT32(save_p, countdown2); - WRITEFIXED(save_p, gravity); + P_WriteFixed(save_p, gravity); - WRITEUINT32(save_p, countdowntimer); - WRITEUINT8(save_p, countdowntimeup); + P_WriteUINT32(save_p, countdowntimer); + P_WriteUINT8(save_p, countdowntimeup); - WRITEUINT32(save_p, hidetime); + P_WriteUINT32(save_p, hidetime); // Is it paused? if (paused) - WRITEUINT8(save_p, 0x2f); + P_WriteUINT8(save_p, 0x2f); else - WRITEUINT8(save_p, 0x2e); + P_WriteUINT8(save_p, 0x2e); + + for (i = 0; i < MAXPLAYERS; i++) + { + P_WriteUINT8(save_p, spam_tokens[i]); + P_WriteUINT32(save_p, spam_tics[i]); + } } -static inline boolean P_NetUnArchiveMisc(boolean reloading) +static inline boolean P_NetUnArchiveMisc(save_t *save_p, boolean reloading) { INT32 i; - if (READUINT32(save_p) != ARCHIVEBLOCK_MISC) + if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_MISC) I_Error("Bad $$$.sav at archive block Misc"); if (reloading) - gametic = READUINT32(save_p); + gametic = P_ReadUINT32(save_p); - gamemap = READINT16(save_p); + gamemap = P_ReadINT16(save_p); // gamemap changed; we assume that its map header is always valid, // so make it so @@ -4569,12 +4883,12 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading) // normally sets this flag mapmusflags |= MUSIC_RELOADRESET; - G_SetGamestate(READINT16(save_p)); + G_SetGamestate(P_ReadINT16(save_p)); - gametype = READINT16(save_p); + gametype = P_ReadINT16(save_p); { - UINT32 pig = READUINT32(save_p); + UINT32 pig = P_ReadUINT32(save_p); for (i = 0; i < MAXPLAYERS; i++) { playeringame[i] = (pig & (1<<i)) != 0; @@ -4582,9 +4896,9 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading) } } - P_SetRandSeed(READUINT32(save_p)); + P_SetRandSeed(P_ReadUINT32(save_p)); - tokenlist = READUINT32(save_p); + tokenlist = P_ReadUINT32(save_p); if (!P_LoadLevel(true, reloading)) { @@ -4593,83 +4907,89 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading) } // get the time - leveltime = READUINT32(save_p); - ssspheres = READUINT32(save_p); - lastmap = READINT16(save_p); - bossdisabled = READUINT16(save_p); + leveltime = P_ReadUINT32(save_p); + ssspheres = P_ReadUINT32(save_p); + lastmap = P_ReadINT16(save_p); + bossdisabled = P_ReadUINT16(save_p); - emeralds = READUINT16(save_p); + emeralds = P_ReadUINT16(save_p); { - UINT8 globools = READUINT8(save_p); + UINT8 globools = P_ReadUINT8(save_p); stagefailed = !!(globools & 1); stoppedclock = !!(globools & (1<<1)); } - token = READUINT32(save_p); - sstimer = READINT32(save_p); - bluescore = READUINT32(save_p); - redscore = READUINT32(save_p); + token = P_ReadUINT32(save_p); + sstimer = P_ReadINT32(save_p); + bluescore = P_ReadUINT32(save_p); + redscore = P_ReadUINT32(save_p); - skincolor_redteam = READUINT16(save_p); - skincolor_blueteam = READUINT16(save_p); - skincolor_redring = READUINT16(save_p); - skincolor_bluering = READUINT16(save_p); + skincolor_redteam = P_ReadUINT16(save_p); + skincolor_blueteam = P_ReadUINT16(save_p); + skincolor_redring = P_ReadUINT16(save_p); + skincolor_bluering = P_ReadUINT16(save_p); - modulothing = READINT32(save_p); + modulothing = P_ReadINT32(save_p); - autobalance = READINT16(save_p); - teamscramble = READINT16(save_p); + autobalance = P_ReadINT16(save_p); + teamscramble = P_ReadINT16(save_p); for (i = 0; i < MAXPLAYERS; i++) - scrambleplayers[i] = READINT16(save_p); + scrambleplayers[i] = P_ReadINT16(save_p); for (i = 0; i < MAXPLAYERS; i++) - scrambleteams[i] = READINT16(save_p); + scrambleteams[i] = P_ReadINT16(save_p); - scrambletotal = READINT16(save_p); - scramblecount = READINT16(save_p); + scrambletotal = P_ReadINT16(save_p); + scramblecount = P_ReadINT16(save_p); - countdown = READUINT32(save_p); - countdown2 = READUINT32(save_p); + countdown = P_ReadUINT32(save_p); + countdown2 = P_ReadUINT32(save_p); - gravity = READFIXED(save_p); + gravity = P_ReadFixed(save_p); - countdowntimer = (tic_t)READUINT32(save_p); - countdowntimeup = (boolean)READUINT8(save_p); + countdowntimer = (tic_t)P_ReadUINT32(save_p); + countdowntimeup = (boolean)P_ReadUINT8(save_p); - hidetime = READUINT32(save_p); + hidetime = P_ReadUINT32(save_p); // Is it paused? - if (READUINT8(save_p) == 0x2f) + if (P_ReadUINT8(save_p) == 0x2f) paused = true; + for (i = 0; i < MAXPLAYERS; i++) + { + spam_tokens[i] = P_ReadUINT8(save_p); + spam_tics[i] = P_ReadUINT32(save_p); + } + return true; } -static inline void P_NetArchiveEmblems(void) +static inline void P_NetArchiveEmblems(save_t *save_p) { gamedata_t *data = serverGamedata; INT32 i, j; UINT8 btemp; INT32 curmare; - WRITEUINT32(save_p, ARCHIVEBLOCK_EMBLEMS); + P_WriteUINT32(save_p, ARCHIVEBLOCK_EMBLEMS); // These should be synchronized before savegame loading by the wad files being the same anyway, // but just in case, for now, we'll leave them here for testing. It would be very bad if they mismatch. - WRITEUINT8(save_p, (UINT8)savemoddata); - WRITEINT32(save_p, numemblems); - WRITEINT32(save_p, numextraemblems); + P_WriteUINT8(save_p, (UINT8)savemoddata); + P_WriteINT32(save_p, numemblems); + P_WriteINT32(save_p, numextraemblems); // The rest of this is lifted straight from G_SaveGameData in g_game.c // TODO: Optimize this to only send information about emblems, unlocks, etc. which actually exist // There is no need to go all the way up to MAXEMBLEMS when wads are guaranteed to be the same. - WRITEUINT32(save_p, data->totalplaytime); + P_WriteUINT32(save_p, data->totalplaytime); // TODO put another cipher on these things? meh, I don't care... for (i = 0; i < NUMMAPS; i++) - WRITEUINT8(save_p, (data->mapvisited[i] & MV_MAX)); + P_WriteUINT8(save_p, (data->mapvisited[i] & MV_MAX)); // To save space, use one bit per collected/achieved/unlocked flag for (i = 0; i < MAXEMBLEMS;) @@ -4677,7 +4997,7 @@ static inline void P_NetArchiveEmblems(void) btemp = 0; for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j) btemp |= (data->collected[j+i] << j); - WRITEUINT8(save_p, btemp); + P_WriteUINT8(save_p, btemp); i += j; } for (i = 0; i < MAXEXTRAEMBLEMS;) @@ -4685,7 +5005,7 @@ static inline void P_NetArchiveEmblems(void) btemp = 0; for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j) btemp |= (data->extraCollected[j+i] << j); - WRITEUINT8(save_p, btemp); + P_WriteUINT8(save_p, btemp); i += j; } for (i = 0; i < MAXUNLOCKABLES;) @@ -4693,7 +5013,7 @@ static inline void P_NetArchiveEmblems(void) btemp = 0; for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j) btemp |= (data->unlocked[j+i] << j); - WRITEUINT8(save_p, btemp); + P_WriteUINT8(save_p, btemp); i += j; } for (i = 0; i < MAXCONDITIONSETS;) @@ -4701,28 +5021,28 @@ static inline void P_NetArchiveEmblems(void) btemp = 0; for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j) btemp |= (data->achieved[j+i] << j); - WRITEUINT8(save_p, btemp); + P_WriteUINT8(save_p, btemp); i += j; } - WRITEUINT32(save_p, data->timesBeaten); - WRITEUINT32(save_p, data->timesBeatenWithEmeralds); - WRITEUINT32(save_p, data->timesBeatenUltimate); + P_WriteUINT32(save_p, data->timesBeaten); + P_WriteUINT32(save_p, data->timesBeatenWithEmeralds); + P_WriteUINT32(save_p, data->timesBeatenUltimate); // Main records for (i = 0; i < NUMMAPS; i++) { if (data->mainrecords[i]) { - WRITEUINT32(save_p, data->mainrecords[i]->score); - WRITEUINT32(save_p, data->mainrecords[i]->time); - WRITEUINT16(save_p, data->mainrecords[i]->rings); + P_WriteUINT32(save_p, data->mainrecords[i]->score); + P_WriteUINT32(save_p, data->mainrecords[i]->time); + P_WriteUINT16(save_p, data->mainrecords[i]->rings); } else { - WRITEUINT32(save_p, 0); - WRITEUINT32(save_p, 0); - WRITEUINT16(save_p, 0); + P_WriteUINT32(save_p, 0); + P_WriteUINT32(save_p, 0); + P_WriteUINT16(save_p, 0); } } @@ -4731,43 +5051,43 @@ static inline void P_NetArchiveEmblems(void) { if (!data->nightsrecords[i] || !data->nightsrecords[i]->nummares) { - WRITEUINT8(save_p, 0); + P_WriteUINT8(save_p, 0); continue; } - WRITEUINT8(save_p, data->nightsrecords[i]->nummares); + P_WriteUINT8(save_p, data->nightsrecords[i]->nummares); for (curmare = 0; curmare < (data->nightsrecords[i]->nummares + 1); ++curmare) { - WRITEUINT32(save_p, data->nightsrecords[i]->score[curmare]); - WRITEUINT8(save_p, data->nightsrecords[i]->grade[curmare]); - WRITEUINT32(save_p, data->nightsrecords[i]->time[curmare]); + P_WriteUINT32(save_p, data->nightsrecords[i]->score[curmare]); + P_WriteUINT8(save_p, data->nightsrecords[i]->grade[curmare]); + P_WriteUINT32(save_p, data->nightsrecords[i]->time[curmare]); } } // Mid-map stuff - WRITEUINT32(save_p, unlocktriggers); + P_WriteUINT32(save_p, unlocktriggers); for (i = 0; i < MAXPLAYERS; i++) { if (!ntemprecords[i].nummares) { - WRITEUINT8(save_p, 0); + P_WriteUINT8(save_p, 0); continue; } - WRITEUINT8(save_p, ntemprecords[i].nummares); + P_WriteUINT8(save_p, ntemprecords[i].nummares); for (curmare = 0; curmare < (ntemprecords[i].nummares + 1); ++curmare) { - WRITEUINT32(save_p, ntemprecords[i].score[curmare]); - WRITEUINT8(save_p, ntemprecords[i].grade[curmare]); - WRITEUINT32(save_p, ntemprecords[i].time[curmare]); + P_WriteUINT32(save_p, ntemprecords[i].score[curmare]); + P_WriteUINT8(save_p, ntemprecords[i].grade[curmare]); + P_WriteUINT32(save_p, ntemprecords[i].time[curmare]); } } } -static inline void P_NetUnArchiveEmblems(void) +static inline void P_NetUnArchiveEmblems(save_t *save_p) { gamedata_t *data = serverGamedata; INT32 i, j; @@ -4778,14 +5098,14 @@ static inline void P_NetUnArchiveEmblems(void) UINT8 recmares; INT32 curmare; - if (READUINT32(save_p) != ARCHIVEBLOCK_EMBLEMS) + if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_EMBLEMS) I_Error("Bad $$$.sav at archive block Emblems"); - savemoddata = (boolean)READUINT8(save_p); // this one is actually necessary because savemoddata stays false otherwise for some reason. + savemoddata = (boolean)P_ReadUINT8(save_p); // this one is actually necessary because savemoddata stays false otherwise for some reason. - if (numemblems != READINT32(save_p)) + if (numemblems != P_ReadINT32(save_p)) I_Error("Bad $$$.sav dearchiving Emblems (numemblems mismatch)"); - if (numextraemblems != READINT32(save_p)) + if (numextraemblems != P_ReadINT32(save_p)) I_Error("Bad $$$.sav dearchiving Emblems (numextraemblems mismatch)"); // This shouldn't happen, but if something really fucked up happens and you transfer @@ -4800,53 +5120,53 @@ static inline void P_NetUnArchiveEmblems(void) // TODO: Optimize this to only read information about emblems, unlocks, etc. which actually exist // There is no need to go all the way up to MAXEMBLEMS when wads are guaranteed to be the same. - data->totalplaytime = READUINT32(save_p); + data->totalplaytime = P_ReadUINT32(save_p); // TODO put another cipher on these things? meh, I don't care... for (i = 0; i < NUMMAPS; i++) - if ((data->mapvisited[i] = READUINT8(save_p)) > MV_MAX) + if ((data->mapvisited[i] = P_ReadUINT8(save_p)) > MV_MAX) I_Error("Bad $$$.sav dearchiving Emblems (invalid visit flags)"); // To save space, use one bit per collected/achieved/unlocked flag for (i = 0; i < MAXEMBLEMS;) { - rtemp = READUINT8(save_p); + rtemp = P_ReadUINT8(save_p); for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j) data->collected[j+i] = ((rtemp >> j) & 1); i += j; } for (i = 0; i < MAXEXTRAEMBLEMS;) { - rtemp = READUINT8(save_p); + rtemp = P_ReadUINT8(save_p); for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j) data->extraCollected[j+i] = ((rtemp >> j) & 1); i += j; } for (i = 0; i < MAXUNLOCKABLES;) { - rtemp = READUINT8(save_p); + rtemp = P_ReadUINT8(save_p); for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j) data->unlocked[j+i] = ((rtemp >> j) & 1); i += j; } for (i = 0; i < MAXCONDITIONSETS;) { - rtemp = READUINT8(save_p); + rtemp = P_ReadUINT8(save_p); for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j) data->achieved[j+i] = ((rtemp >> j) & 1); i += j; } - data->timesBeaten = READUINT32(save_p); - data->timesBeatenWithEmeralds = READUINT32(save_p); - data->timesBeatenUltimate = READUINT32(save_p); + data->timesBeaten = P_ReadUINT32(save_p); + data->timesBeatenWithEmeralds = P_ReadUINT32(save_p); + data->timesBeatenUltimate = P_ReadUINT32(save_p); // Main records for (i = 0; i < NUMMAPS; ++i) { - recscore = READUINT32(save_p); - rectime = (tic_t)READUINT32(save_p); - recrings = READUINT16(save_p); + recscore = P_ReadUINT32(save_p); + rectime = (tic_t)P_ReadUINT32(save_p); + recrings = P_ReadUINT16(save_p); if (recrings > 10000 || recscore > MAXSCORE) I_Error("Bad $$$.sav dearchiving Emblems (invalid score)"); @@ -4863,16 +5183,16 @@ static inline void P_NetUnArchiveEmblems(void) // Nights records for (i = 0; i < NUMMAPS; ++i) { - if ((recmares = READUINT8(save_p)) == 0) + if ((recmares = P_ReadUINT8(save_p)) == 0) continue; G_AllocNightsRecordData((INT16)i, data); for (curmare = 0; curmare < (recmares+1); ++curmare) { - data->nightsrecords[i]->score[curmare] = READUINT32(save_p); - data->nightsrecords[i]->grade[curmare] = READUINT8(save_p); - data->nightsrecords[i]->time[curmare] = (tic_t)READUINT32(save_p); + data->nightsrecords[i]->score[curmare] = P_ReadUINT32(save_p); + data->nightsrecords[i]->grade[curmare] = P_ReadUINT8(save_p); + data->nightsrecords[i]->time[curmare] = (tic_t)P_ReadUINT32(save_p); if (data->nightsrecords[i]->grade[curmare] > GRADE_S) { @@ -4884,18 +5204,18 @@ static inline void P_NetUnArchiveEmblems(void) } // Mid-map stuff - unlocktriggers = READUINT32(save_p); + unlocktriggers = P_ReadUINT32(save_p); for (i = 0; i < MAXPLAYERS; ++i) { - if ((recmares = READUINT8(save_p)) == 0) + if ((recmares = P_ReadUINT8(save_p)) == 0) continue; for (curmare = 0; curmare < (recmares+1); ++curmare) { - ntemprecords[i].score[curmare] = READUINT32(save_p); - ntemprecords[i].grade[curmare] = READUINT8(save_p); - ntemprecords[i].time[curmare] = (tic_t)READUINT32(save_p); + ntemprecords[i].score[curmare] = P_ReadUINT32(save_p); + ntemprecords[i].grade[curmare] = P_ReadUINT8(save_p); + ntemprecords[i].time[curmare] = (tic_t)P_ReadUINT32(save_p); if (ntemprecords[i].grade[curmare] > GRADE_S) { @@ -4907,37 +5227,37 @@ static inline void P_NetUnArchiveEmblems(void) } } -static void P_NetArchiveSectorPortals(void) +static void P_NetArchiveSectorPortals(save_t *save_p) { - WRITEUINT32(save_p, ARCHIVEBLOCK_SECPORTALS); + P_WriteUINT32(save_p, ARCHIVEBLOCK_SECPORTALS); - WRITEUINT32(save_p, secportalcount); + P_WriteUINT32(save_p, secportalcount); for (size_t i = 0; i < secportalcount; i++) { UINT8 type = secportals[i].type; - WRITEUINT8(save_p, type); - WRITEFIXED(save_p, secportals[i].origin.x); - WRITEFIXED(save_p, secportals[i].origin.y); + P_WriteUINT8(save_p, type); + P_WriteUINT8(save_p, secportals[i].ceiling ? 1 : 0); + P_WriteUINT32(save_p, SaveSector(secportals[i].target)); switch (type) { case SECPORTAL_LINE: - WRITEUINT32(save_p, SaveLine(secportals[i].line.start)); - WRITEUINT32(save_p, SaveLine(secportals[i].line.dest)); + P_WriteUINT32(save_p, SaveLine(secportals[i].line.start)); + P_WriteUINT32(save_p, SaveLine(secportals[i].line.dest)); break; case SECPORTAL_PLANE: case SECPORTAL_HORIZON: case SECPORTAL_FLOOR: case SECPORTAL_CEILING: - WRITEUINT32(save_p, SaveSector(secportals[i].sector)); + P_WriteUINT32(save_p, SaveSector(secportals[i].sector)); break; case SECPORTAL_OBJECT: - if (secportals[i].mobj && !P_MobjWasRemoved(secportals[i].mobj)) - SaveMobjnum(secportals[i].mobj); + if (!P_MobjWasRemoved(secportals[i].mobj)) + P_WriteUINT32(save_p, SaveMobjnum(secportals[i].mobj)); else - WRITEUINT32(save_p, 0); + P_WriteUINT32(save_p, 0); break; default: break; @@ -4945,15 +5265,15 @@ static void P_NetArchiveSectorPortals(void) } } -static void P_NetUnArchiveSectorPortals(void) +static void P_NetUnArchiveSectorPortals(save_t *save_p) { - if (READUINT32(save_p) != ARCHIVEBLOCK_SECPORTALS) + if (P_ReadUINT32(save_p) != ARCHIVEBLOCK_SECPORTALS) I_Error("Bad $$$.sav at archive block Secportals"); Z_Free(secportals); P_InitSectorPortals(); - UINT32 count = READUINT32(save_p); + UINT32 count = P_ReadUINT32(save_p); for (UINT32 i = 0; i < count; i++) { @@ -4961,24 +5281,24 @@ static void P_NetUnArchiveSectorPortals(void) sectorportal_t *secportal = &secportals[id]; - secportal->type = READUINT8(save_p); - secportal->origin.x = READFIXED(save_p); - secportal->origin.y = READFIXED(save_p); + secportal->type = P_ReadUINT8(save_p); + secportal->ceiling = (P_ReadUINT8(save_p) != 0) ? true : false; + secportal->target = LoadSector(P_ReadUINT32(save_p)); switch (secportal->type) { case SECPORTAL_LINE: - secportal->line.start = LoadLine(READUINT32(save_p)); - secportal->line.dest = LoadLine(READUINT32(save_p)); + secportal->line.start = LoadLine(P_ReadUINT32(save_p)); + secportal->line.dest = LoadLine(P_ReadUINT32(save_p)); break; case SECPORTAL_PLANE: case SECPORTAL_HORIZON: case SECPORTAL_FLOOR: case SECPORTAL_CEILING: - secportal->sector = LoadSector(READUINT32(save_p)); + secportal->sector = LoadSector(P_ReadUINT32(save_p)); break; case SECPORTAL_OBJECT: - id = READUINT32(save_p); + id = P_ReadUINT32(save_p); secportal->mobj = (id == 0) ? NULL : P_FindNewPosition(id); break; default: @@ -4987,7 +5307,7 @@ static void P_NetUnArchiveSectorPortals(void) } } -static inline void P_ArchiveLuabanksAndConsistency(void) +static inline void P_ArchiveLuabanksAndConsistency(save_t *save_p) { UINT8 i, banksinuse = NUM_LUABANKS; @@ -4996,30 +5316,30 @@ static inline void P_ArchiveLuabanksAndConsistency(void) if (banksinuse) { - WRITEUINT8(save_p, 0xb7); // luabanks marker - WRITEUINT8(save_p, banksinuse); + P_WriteUINT8(save_p, 0xb7); // luabanks marker + P_WriteUINT8(save_p, banksinuse); for (i = 0; i < banksinuse; i++) - WRITEINT32(save_p, luabanks[i]); + P_WriteINT32(save_p, luabanks[i]); } - WRITEUINT8(save_p, 0x1d); // consistency marker + P_WriteUINT8(save_p, 0x1d); // consistency marker } -static inline boolean P_UnArchiveLuabanksAndConsistency(void) +static inline boolean P_UnArchiveLuabanksAndConsistency(save_t *save_p) { - switch (READUINT8(save_p)) + switch (P_ReadUINT8(save_p)) { case 0xb7: // luabanks marker { - UINT8 i, banksinuse = READUINT8(save_p); + UINT8 i, banksinuse = P_ReadUINT8(save_p); if (banksinuse > NUM_LUABANKS) { CONS_Alert(CONS_ERROR, M_GetText("Corrupt Luabanks! (Too many banks in use)\n")); return false; } for (i = 0; i < banksinuse; i++) - luabanks[i] = READINT32(save_p); - if (READUINT8(save_p) != 0x1d) // consistency marker + luabanks[i] = P_ReadINT32(save_p); + if (P_ReadUINT8(save_p) != 0x1d) // consistency marker { CONS_Alert(CONS_ERROR, M_GetText("Corrupt Luabanks! (Failed consistency check)\n")); return false; @@ -5035,27 +5355,27 @@ static inline boolean P_UnArchiveLuabanksAndConsistency(void) return true; } -void P_SaveGame(INT16 mapnum) +void P_SaveGame(save_t *save_p, INT16 mapnum) { - P_ArchiveMisc(mapnum); - P_ArchivePlayer(); - P_ArchiveLuabanksAndConsistency(); + P_ArchiveMisc(save_p, mapnum); + P_ArchivePlayer(save_p); + P_ArchiveLuabanksAndConsistency(save_p); } -void P_SaveNetGame(boolean resending) +void P_SaveNetGame(save_t *save_p, boolean resending) { thinker_t *th; mobj_t *mobj; INT32 i = 1; // don't start from 0, it'd be confused with a blank pointer otherwise - CV_SaveNetVars(&save_p); - P_NetArchiveMisc(resending); - P_NetArchiveEmblems(); + CV_SaveNetVars(save_p); + P_NetArchiveMisc(save_p, resending); + P_NetArchiveEmblems(save_p); // Assign the mobjnumber for pointer tracking for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mobj = (mobj_t *)th; @@ -5064,32 +5384,32 @@ void P_SaveNetGame(boolean resending) mobj->mobjnum = i++; } - P_NetArchivePlayers(); + P_NetArchivePlayers(save_p); if (gamestate == GS_LEVEL) { - P_NetArchiveWorld(); - P_ArchivePolyObjects(); - P_NetArchiveThinkers(); - P_NetArchiveSpecials(); - P_NetArchiveColormaps(); - P_NetArchiveWaypoints(); - P_NetArchiveSectorPortals(); + P_NetArchiveWorld(save_p); + P_ArchivePolyObjects(save_p); + P_NetArchiveThinkers(save_p); + P_NetArchiveSpecials(save_p); + P_NetArchiveColormaps(save_p); + P_NetArchiveWaypoints(save_p); + P_NetArchiveSectorPortals(save_p); } - LUA_Archive(); + LUA_Archive(save_p); - P_ArchiveLuabanksAndConsistency(); + P_ArchiveLuabanksAndConsistency(save_p); } -boolean P_LoadGame(INT16 mapoverride) +boolean P_LoadGame(save_t *save_p, INT16 mapoverride) { if (gamestate == GS_INTERMISSION) Y_EndIntermission(); G_SetGamestate(GS_NULL); // should be changed in P_UnArchiveMisc - P_UnArchiveSPGame(mapoverride); - P_UnArchivePlayer(); + P_UnArchiveSPGame(save_p, mapoverride); + P_UnArchivePlayer(save_p); - if (!P_UnArchiveLuabanksAndConsistency()) + if (!P_UnArchiveLuabanksAndConsistency(save_p)) return false; // Only do this after confirming savegame is ok @@ -5099,26 +5419,26 @@ boolean P_LoadGame(INT16 mapoverride) return true; } -boolean P_LoadNetGame(boolean reloading) +boolean P_LoadNetGame(save_t *save_p, boolean reloading) { - CV_LoadNetVars(&save_p); - if (!P_NetUnArchiveMisc(reloading)) + CV_LoadNetVars(save_p); + if (!P_NetUnArchiveMisc(save_p, reloading)) return false; - P_NetUnArchiveEmblems(); - P_NetUnArchivePlayers(); + P_NetUnArchiveEmblems(save_p); + P_NetUnArchivePlayers(save_p); if (gamestate == GS_LEVEL) { - P_NetUnArchiveWorld(); - P_UnArchivePolyObjects(); - P_NetUnArchiveThinkers(); - P_NetUnArchiveSpecials(); - P_NetUnArchiveColormaps(); - P_NetUnArchiveWaypoints(); - P_NetUnArchiveSectorPortals(); + P_NetUnArchiveWorld(save_p); + P_UnArchivePolyObjects(save_p); + P_NetUnArchiveThinkers(save_p); + P_NetUnArchiveSpecials(save_p); + P_NetUnArchiveColormaps(save_p); + P_NetUnArchiveWaypoints(save_p); + P_NetUnArchiveSectorPortals(save_p); P_RelinkPointers(); P_FinishMobjs(); } - LUA_UnArchive(); + LUA_UnArchive(save_p); // This is stupid and hacky, but maybe it'll work! P_SetRandSeed(P_GetInitSeed()); @@ -5129,5 +5449,5 @@ boolean P_LoadNetGame(boolean reloading) // precipitation when loading a netgame save. Instead, precip has to be spawned here. // This is done in P_NetUnArchiveSpecials now. - return P_UnArchiveLuabanksAndConsistency(); + return P_UnArchiveLuabanksAndConsistency(save_p); } diff --git a/src/p_saveg.h b/src/p_saveg.h index 545008e7efc6af656fe94864a4ebcf8ea28e5f27..05e82190aeb27bb8aa62f5bf4a2b2c8b889759fb 100644 --- a/src/p_saveg.h +++ b/src/p_saveg.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -18,17 +18,24 @@ #pragma interface #endif +#include "tables.h" + #define NEWSKINSAVES (INT16_MAX) // TODO: 2.3: Delete (Purely for backwards compatibility) // Persistent storage/archiving. // These are the load / save game routines. -void P_SaveGame(INT16 mapnum); -void P_SaveNetGame(boolean resending); -boolean P_LoadGame(INT16 mapoverride); -boolean P_LoadNetGame(boolean reloading); +typedef struct +{ + unsigned char *buf; + size_t size; + size_t pos; +} save_t; -mobj_t *P_FindNewPosition(UINT32 oldposition); +void P_SaveGame(save_t *save_p, INT16 mapnum); +void P_SaveNetGame(save_t *save_p, boolean resending); +boolean P_LoadGame(save_t *save_p, INT16 mapoverride); +boolean P_LoadNetGame(save_t *save_p, boolean reloading); typedef struct { @@ -42,6 +49,37 @@ typedef struct } savedata_t; extern savedata_t savedata; -extern UINT8 *save_p; + +void P_WriteUINT8(save_t *p, UINT8 v); +void P_WriteSINT8(save_t *p, SINT8 v); +void P_WriteUINT16(save_t *p, UINT16 v); +void P_WriteINT16(save_t *p, INT16 v); +void P_WriteUINT32(save_t *p, UINT32 v); +void P_WriteINT32(save_t *p, INT32 v); +void P_WriteChar(save_t *p, char v); +void P_WriteFixed(save_t *p, fixed_t v); +void P_WriteAngle(save_t *p, angle_t v); +void P_WriteStringN(save_t *p, char const *s, size_t n); +void P_WriteStringL(save_t *p, char const *s, size_t n); +void P_WriteString(save_t *p, char const *s); +void P_WriteMem(save_t *p, void const *s, size_t n); + +void P_SkipStringN(save_t *p, size_t n); +void P_SkipStringL(save_t *p, size_t n); +void P_SkipString(save_t *p); + +UINT8 P_ReadUINT8(save_t *p); +SINT8 P_ReadSINT8(save_t *p); +UINT16 P_ReadUINT16(save_t *p); +INT16 P_ReadINT16(save_t *p); +UINT32 P_ReadUINT32(save_t *p); +INT32 P_ReadINT32(save_t *p); +char P_ReadChar(save_t *p); +fixed_t P_ReadFixed(save_t *p); +angle_t P_ReadAngle(save_t *p); +void P_ReadStringN(save_t *p, char *s, size_t n); +void P_ReadStringL(save_t *p, char *s, size_t n); +void P_ReadString(save_t *p, char *s); +void P_ReadMem(save_t *p, void *s, size_t n); #endif diff --git a/src/p_setup.c b/src/p_setup.c index 1d985beb4f07399a40607f1ec8f32f480df0e65c..c2b8f2db2e367cc23fcdb704f23fe572360eea81 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -358,6 +358,8 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) mapheaderinfo[num]->marathonnext = 0; mapheaderinfo[num]->startrings = 0; mapheaderinfo[num]->sstimer = 90; + for (UINT8 n = 0; n < 8; n++) + mapheaderinfo[num]->nightstimer[n] = 0; mapheaderinfo[num]->ssspheres = 1; mapheaderinfo[num]->gravity = FRACUNIT/2; mapheaderinfo[num]->keywords[0] = '\0'; @@ -525,6 +527,29 @@ UINT32 P_GetScoreForGradeOverall(INT16 map, UINT8 grade) return score; } +void P_AddNiGHTSTimes(INT16 i, char *gtext) +{ + char *spos = gtext; + + for (UINT8 n = 0; n < 8; n++) + { + if (spos != NULL) + { + mapheaderinfo[i]->nightstimer[n] = atoi(spos); + CONS_Debug(DBG_SETUP, "%u ", atoi(spos)); + // Grab next comma + spos = strchr(spos, ','); + if (spos) + ++spos; + } + else + { + mapheaderinfo[i]->nightstimer[n] = 0; + } + } + +} + // // levelflats // @@ -585,17 +610,17 @@ Ploadflat (levelflat_t *levelflat, const char *flatname, boolean resize) // Look for a flat int texturenum = R_CheckFlatNumForName(levelflat->name); - if (texturenum <= 0) + if (texturenum < 0) { // If we can't find a flat, try looking for a texture! texturenum = R_CheckTextureNumForName(levelflat->name); - if (texturenum <= 0) + if (texturenum < 0) { // Use "not found" texture texturenum = R_CheckTextureNumForName("REDWALL"); // Give up? - if (texturenum <= 0) + if (texturenum < 0) { levelflat->type = LEVELFLAT_NONE; texturenum = -1; @@ -667,7 +692,7 @@ void P_ReloadRings(void) // scan the thinkers to find rings/spheres/hoops to unset for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo = (mobj_t *)th; @@ -725,7 +750,7 @@ void P_SwitchSpheresBonusMode(boolean bonustime) // scan the thinkers to find spheres to switch for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo = (mobj_t *)th; @@ -806,13 +831,15 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum) static void P_SpawnEmeraldHunt(void) { - INT32 emer[3], num[MAXHUNTEMERALDS], i, randomkey; + INT32 emer[3], num[MAXHUNTEMERALDS], i, amount, randomkey; fixed_t x, y, z; for (i = 0; i < numhuntemeralds; i++) num[i] = i; - for (i = 0; i < 3; i++) + amount = min(numhuntemeralds, 3); + + for (i = 0; i < amount; i++) { // generate random index, shuffle afterwards randomkey = P_RandomKey(numhuntemeralds--); @@ -877,14 +904,32 @@ static void P_SpawnMapThings(boolean spawnemblems) P_SpawnEmeraldHunt(); } +static void P_WriteTextmap_Things(FILE *f, const mapthing_t *wmapthings); // proto + // Experimental groovy write function! -/*void P_WriteThings(void) +void P_WriteThings(const char *filepath) { size_t i, length; mapthing_t *mt; UINT8 *savebuffer, *savebuf_p; INT16 temp; + if (udmf) + { + FILE *f = fopen(va("%s.txt", filepath), "w"); + if (!f) + { + CONS_Alert(CONS_ERROR, M_GetText("Couldn't write to file %s\n"), filepath); + return; + } + + P_WriteTextmap_Things(f, mapthings); + fclose(f); + + CONS_Printf(M_GetText("%s.txt saved.\n"), filepath); + return; + } + savebuf_p = savebuffer = (UINT8 *)malloc(nummapthings * sizeof (mapthing_t)); if (!savebuf_p) @@ -908,12 +953,12 @@ static void P_SpawnMapThings(boolean spawnemblems) length = savebuf_p - savebuffer; - FIL_WriteFile(va("newthings%d.lmp", gamemap), savebuffer, length); + FIL_WriteFile(va("%s.lmp", filepath), savebuffer, length); free(savebuffer); savebuf_p = NULL; - CONS_Printf(M_GetText("newthings%d.lmp saved.\n"), gamemap); -}*/ + CONS_Printf(M_GetText("%s.lmp saved.\n"), filepath); +} // // MAP LOADING FUNCTIONS @@ -1070,6 +1115,8 @@ static void P_InitializeLinedef(line_t *ld) ld->callcount = 0; ld->secportal = UINT32_MAX; + ld->midtexslope = NULL; + // cph 2006/09/30 - fix sidedef errors right away. // cph 2002/07/20 - these errors are fatal if not fixed, so apply them for (j = 0; j < 2; j++) @@ -1320,6 +1367,9 @@ static void P_LoadSidedefs(UINT8 *data) sd->scalex_top = sd->scalex_mid = sd->scalex_bottom = FRACUNIT; sd->scaley_top = sd->scaley_mid = sd->scaley_bottom = FRACUNIT; + sd->light = sd->light_top = sd->light_mid = sd->light_bottom = 0; + sd->lightabsolute = sd->lightabsolute_top = sd->lightabsolute_mid = sd->lightabsolute_bottom = false; + P_SetSidedefSector(i, (UINT16)SHORT(msd->sector)); // Special info stored in texture fields! @@ -1507,11 +1557,41 @@ static void P_LoadThings(UINT8 *data) } // Stores positions for relevant map data spread through a TEXTMAP. -UINT32 mapthingsPos[UINT16_MAX]; -UINT32 linesPos[UINT16_MAX]; -UINT32 sidesPos[UINT16_MAX]; -UINT32 vertexesPos[UINT16_MAX]; -UINT32 sectorsPos[UINT16_MAX]; +typedef struct textmap_block_s +{ + UINT32 *pos; + size_t capacity; +} textmap_block_t; + +static textmap_block_t mapthingBlocks; +static textmap_block_t linedefBlocks; +static textmap_block_t sidedefBlocks; +static textmap_block_t vertexBlocks; +static textmap_block_t sectorBlocks; + +static void TextmapStorePos(textmap_block_t *blocks, size_t *count) +{ + size_t locCount = (*count) + 1; + + if (blocks->pos == NULL) + { + // Initial capacity (half of the former one.) + blocks->capacity = UINT16_MAX / 2; + + Z_Calloc(sizeof(blocks->pos) * blocks->capacity, PU_LEVEL, &blocks->pos); + } + else if (locCount >= blocks->capacity) + { + // If we hit the list's capacity, make space for 1024 more blocks + blocks->capacity += 1024; + + Z_Realloc(blocks->pos, sizeof(blocks->pos) * blocks->capacity, PU_LEVEL, &blocks->pos); + } + + blocks->pos[locCount - 1] = M_TokenizerGetEndPos(); + + (*count) = locCount; +} // Determine total amount of map data in TEXTMAP. static boolean TextmapCount(size_t size) @@ -1525,6 +1605,12 @@ static boolean TextmapCount(size_t size) numvertexes = 0; numsectors = 0; + if(!tkn) + { + CONS_Alert(CONS_ERROR, "No text in lump!\n"); + return true; + } + // Look for namespace at the beginning. if (!fastcmp(tkn, "namespace")) { @@ -1549,15 +1635,15 @@ static boolean TextmapCount(size_t size) brackets++; // Check for valid fields. else if (fastcmp(tkn, "thing")) - mapthingsPos[nummapthings++] = M_TokenizerGetEndPos(); + TextmapStorePos(&mapthingBlocks, &nummapthings); else if (fastcmp(tkn, "linedef")) - linesPos[numlines++] = M_TokenizerGetEndPos(); + TextmapStorePos(&linedefBlocks, &numlines); else if (fastcmp(tkn, "sidedef")) - sidesPos[numsides++] = M_TokenizerGetEndPos(); + TextmapStorePos(&sidedefBlocks, &numsides); else if (fastcmp(tkn, "vertex")) - vertexesPos[numvertexes++] = M_TokenizerGetEndPos(); + TextmapStorePos(&vertexBlocks, &numvertexes); else if (fastcmp(tkn, "sector")) - sectorsPos[numsectors++] = M_TokenizerGetEndPos(); + TextmapStorePos(§orBlocks, &numsectors); else CONS_Alert(CONS_NOTICE, "Unknown field '%s'.\n", tkn); } @@ -1810,6 +1896,10 @@ static void ParseTextmapSectorParameter(UINT32 i, const char *param, const char sectors[i].specialflags |= SSF_JUMPFLIP; else if (fastcmp(param, "gravityoverride") && fastcmp("true", val)) sectors[i].specialflags |= SSF_GRAVITYOVERRIDE; + else if (fastcmp(param, "nophysics_floor") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_NOPHYSICSFLOOR; + else if (fastcmp(param, "nophysics_ceiling") && fastcmp("true", val)) + sectors[i].specialflags |= SSF_NOPHYSICSCEILING; else if (fastcmp(param, "friction")) sectors[i].friction = FLOAT_TO_FIXED(atof(val)); else if (fastcmp(param, "gravity")) @@ -1890,6 +1980,22 @@ static void ParseTextmapSidedefParameter(UINT32 i, const char *param, const char P_SetSidedefSector(i, atol(val)); else if (fastcmp(param, "repeatcnt")) sides[i].repeatcnt = atol(val); + else if (fastcmp(param, "light")) + sides[i].light = atol(val); + else if (fastcmp(param, "light_top")) + sides[i].light_top = atol(val); + else if (fastcmp(param, "light_mid")) + sides[i].light_mid = atol(val); + else if (fastcmp(param, "light_bottom")) + sides[i].light_bottom = atol(val); + else if (fastcmp(param, "lightabsolute") && fastcmp("true", val)) + sides[i].lightabsolute = true; + else if (fastcmp(param, "lightabsolute_top") && fastcmp("true", val)) + sides[i].lightabsolute_top = true; + else if (fastcmp(param, "lightabsolute_mid") && fastcmp("true", val)) + sides[i].lightabsolute_mid = true; + else if (fastcmp(param, "lightabsolute_bottom") && fastcmp("true", val)) + sides[i].lightabsolute_bottom = true; } static void ParseTextmapLinedefParameter(UINT32 i, const char *param, const char *val) @@ -2144,6 +2250,60 @@ typedef struct mapthing_t *angleanchor; } sectorspecialthings_t; +static void P_WriteTextmap_Things(FILE *f, const mapthing_t *wmapthings) +{ + size_t i, j; + mtag_t firsttag; + + // Actual writing + for (i = 0; i < nummapthings; i++) + { + fprintf(f, "thing // %s\n", sizeu1(i)); + fprintf(f, "{\n"); + firsttag = Tag_FGet(&wmapthings[i].tags); + if (firsttag != 0) + fprintf(f, "id = %d;\n", firsttag); + if (wmapthings[i].tags.count > 1) + { + fprintf(f, "moreids = \""); + for (j = 1; j < wmapthings[i].tags.count; j++) + { + if (j > 1) + fprintf(f, " "); + fprintf(f, "%d", wmapthings[i].tags.tags[j]); + } + fprintf(f, "\";\n"); + } + fprintf(f, "x = %d;\n", wmapthings[i].x); + fprintf(f, "y = %d;\n", wmapthings[i].y); + if (wmapthings[i].z != 0) + fprintf(f, "height = %d;\n", wmapthings[i].z); + fprintf(f, "angle = %d;\n", wmapthings[i].angle); + if (wmapthings[i].pitch != 0) + fprintf(f, "pitch = %d;\n", wmapthings[i].pitch); + if (wmapthings[i].roll != 0) + fprintf(f, "roll = %d;\n", wmapthings[i].roll); + if (wmapthings[i].type != 0) + fprintf(f, "type = %d;\n", wmapthings[i].type); + if (wmapthings[i].spritexscale != FRACUNIT) + fprintf(f, "scalex = %f;\n", FIXED_TO_FLOAT(wmapthings[i].spritexscale)); + if (wmapthings[i].spriteyscale != FRACUNIT) + fprintf(f, "scaley = %f;\n", FIXED_TO_FLOAT(wmapthings[i].spriteyscale)); + if (wmapthings[i].scale != FRACUNIT) + fprintf(f, "mobjscale = %f;\n", FIXED_TO_FLOAT(wmapthings[i].scale)); + if (wmapthings[i].options & MTF_OBJECTFLIP) + fprintf(f, "flip = true;\n"); + for (j = 0; j < NUMMAPTHINGARGS; j++) + if (wmapthings[i].args[j] != 0) + fprintf(f, "arg%s = %d;\n", sizeu1(j), wmapthings[i].args[j]); + for (j = 0; j < NUMMAPTHINGSTRINGARGS; j++) + if (mapthings[i].stringargs[j]) + fprintf(f, "stringarg%s = \"%s\";\n", sizeu1(j), mapthings[i].stringargs[j]); + fprintf(f, "}\n"); + fprintf(f, "\n"); + } +} + static void P_WriteTextmap(void) { size_t i, j; @@ -2411,52 +2571,7 @@ static void P_WriteTextmap(void) } fprintf(f, "namespace = \"srb2\";\n"); - for (i = 0; i < nummapthings; i++) - { - fprintf(f, "thing // %s\n", sizeu1(i)); - fprintf(f, "{\n"); - firsttag = Tag_FGet(&wmapthings[i].tags); - if (firsttag != 0) - fprintf(f, "id = %d;\n", firsttag); - if (wmapthings[i].tags.count > 1) - { - fprintf(f, "moreids = \""); - for (j = 1; j < wmapthings[i].tags.count; j++) - { - if (j > 1) - fprintf(f, " "); - fprintf(f, "%d", wmapthings[i].tags.tags[j]); - } - fprintf(f, "\";\n"); - } - fprintf(f, "x = %d;\n", wmapthings[i].x); - fprintf(f, "y = %d;\n", wmapthings[i].y); - if (wmapthings[i].z != 0) - fprintf(f, "height = %d;\n", wmapthings[i].z); - fprintf(f, "angle = %d;\n", wmapthings[i].angle); - if (wmapthings[i].pitch != 0) - fprintf(f, "pitch = %d;\n", wmapthings[i].pitch); - if (wmapthings[i].roll != 0) - fprintf(f, "roll = %d;\n", wmapthings[i].roll); - if (wmapthings[i].type != 0) - fprintf(f, "type = %d;\n", wmapthings[i].type); - if (wmapthings[i].spritexscale != FRACUNIT) - fprintf(f, "scalex = %f;\n", FIXED_TO_FLOAT(wmapthings[i].spritexscale)); - if (wmapthings[i].spriteyscale != FRACUNIT) - fprintf(f, "scaley = %f;\n", FIXED_TO_FLOAT(wmapthings[i].spriteyscale)); - if (wmapthings[i].scale != FRACUNIT) - fprintf(f, "mobjscale = %f;\n", FIXED_TO_FLOAT(wmapthings[i].scale)); - if (wmapthings[i].options & MTF_OBJECTFLIP) - fprintf(f, "flip = true;\n"); - for (j = 0; j < NUMMAPTHINGARGS; j++) - if (wmapthings[i].args[j] != 0) - fprintf(f, "arg%s = %d;\n", sizeu1(j), wmapthings[i].args[j]); - for (j = 0; j < NUMMAPTHINGSTRINGARGS; j++) - if (mapthings[i].stringargs[j]) - fprintf(f, "stringarg%s = \"%s\";\n", sizeu1(j), mapthings[i].stringargs[j]); - fprintf(f, "}\n"); - fprintf(f, "\n"); - } + P_WriteTextmap_Things(f, wmapthings); for (i = 0; i < numvertexes; i++) { @@ -2608,6 +2723,22 @@ static void P_WriteTextmap(void) fprintf(f, "texturemiddle = \"%.*s\";\n", 8, textures[wsides[i].midtexture]->name); if (wsides[i].repeatcnt != 0) fprintf(f, "repeatcnt = %d;\n", wsides[i].repeatcnt); + if (wsides[i].light != 0) + fprintf(f, "light = %d;\n", wsides[i].light); + if (wsides[i].light_top != 0) + fprintf(f, "light_top = %d;\n", wsides[i].light_top); + if (wsides[i].light_mid != 0) + fprintf(f, "light_mid = %d;\n", wsides[i].light_mid); + if (wsides[i].light_bottom != 0) + fprintf(f, "light_bottom = %d;\n", wsides[i].light_bottom); + if (wsides[i].lightabsolute) + fprintf(f, "lightabsolute = true;\n"); + if (wsides[i].lightabsolute_top) + fprintf(f, "lightabsolute_top = true;\n"); + if (wsides[i].lightabsolute_mid) + fprintf(f, "lightabsolute_mid = true;\n"); + if (wsides[i].lightabsolute_bottom) + fprintf(f, "lightabsolute_bottom = true;\n"); fprintf(f, "}\n"); fprintf(f, "\n"); } @@ -2667,13 +2798,18 @@ static void P_WriteTextmap(void) fprintf(f, "rotationfloor = %f;\n", FIXED_TO_FLOAT(AngleFixed(wsectors[i].floorangle))); if (wsectors[i].ceilingangle != 0) fprintf(f, "rotationceiling = %f;\n", FIXED_TO_FLOAT(AngleFixed(wsectors[i].ceilingangle))); - if (wsectors[i].extra_colormap) + if (wsectors[i].extra_colormap) { INT32 lightcolor = P_RGBAToColor(wsectors[i].extra_colormap->rgba); UINT8 lightalpha = R_GetRgbaA(wsectors[i].extra_colormap->rgba); INT32 fadecolor = P_RGBAToColor(wsectors[i].extra_colormap->fadergba); UINT8 fadealpha = R_GetRgbaA(wsectors[i].extra_colormap->fadergba); + // For now, convert alpha from new (0-255) to old 'A-Z' (0-25) range + // TODO: remove this limitation in a backwards-compatible way (UDMF versioning?) + lightalpha /= 10; + fadealpha /= 10; + if (lightcolor != 0) fprintf(f, "lightcolor = %d;\n", lightcolor); if (lightalpha != 25) @@ -2859,7 +2995,7 @@ static void P_LoadTextmap(void) side_t *sd; mapthing_t *mt; - CONS_Alert(CONS_NOTICE, "UDMF support is still a work-in-progress; its specs and features are prone to change until it is fully implemented.\n"); + //CONS_Alert(CONS_NOTICE, "UDMF support is still a work-in-progress; its specs and features are prone to change until it is fully implemented.\n"); /// Given the UDMF specs, some fields are given a default value. /// If an element's field has a default value set, it is omitted @@ -2873,7 +3009,7 @@ static void P_LoadTextmap(void) vt->floorzset = vt->ceilingzset = false; vt->floorz = vt->ceilingz = 0; - TextmapParse(vertexesPos[i], i, ParseTextmapVertexParameter); + TextmapParse(vertexBlocks.pos[i], i, ParseTextmapVertexParameter); if (vt->x == INT32_MAX) I_Error("P_LoadTextmap: vertex %s has no x value set!\n", sizeu1(i)); @@ -2930,15 +3066,16 @@ static void P_LoadTextmap(void) textmap_planefloor.defined = 0; textmap_planeceiling.defined = 0; - TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter); + TextmapParse(sectorBlocks.pos[i], i, ParseTextmapSectorParameter); P_InitializeSector(sc); if (textmap_colormap.used) { - // Convert alpha values from old 0-25 (A-Z) range to 0-255 range + // Convert alpha values from old 'A-Z' (0-25) range to new UINT8 (0-255) range + // TODO: remove this limitation in a backwards-compatible way (UDMF versioning?) UINT8 lightalpha = (textmap_colormap.lightalpha * 102) / 10; UINT8 fadealpha = (textmap_colormap.fadealpha * 102) / 10; - + INT32 rgba = P_ColorToRGBA(textmap_colormap.lightcolor, lightalpha); INT32 fadergba = P_ColorToRGBA(textmap_colormap.fadecolor, fadealpha); sc->extra_colormap = sc->spawn_extra_colormap = R_CreateColormap(rgba, fadergba, textmap_colormap.fadestart, textmap_colormap.fadeend, textmap_colormap.flags); @@ -2948,13 +3085,17 @@ static void P_LoadTextmap(void) { sc->f_slope = P_MakeSlopeViaEquationConstants(textmap_planefloor.a, textmap_planefloor.b, textmap_planefloor.c, textmap_planefloor.d); sc->hasslope = true; + if (sc->specialflags & SSF_NOPHYSICSFLOOR) + sc->f_slope->flags |= SL_NOPHYSICS; } if (textmap_planeceiling.defined == (PD_A|PD_B|PD_C|PD_D)) { sc->c_slope = P_MakeSlopeViaEquationConstants(textmap_planeceiling.a, textmap_planeceiling.b, textmap_planeceiling.c, textmap_planeceiling.d); sc->hasslope = true; - } + if (sc->specialflags & SSF_NOPHYSICSCEILING) + sc->c_slope->flags |= SL_NOPHYSICS; + } TextmapFixFlatOffsets(sc); } @@ -2974,7 +3115,7 @@ static void P_LoadTextmap(void) ld->sidenum[0] = NO_SIDEDEF; ld->sidenum[1] = NO_SIDEDEF; - TextmapParse(linesPos[i], i, ParseTextmapLinedefParameter); + TextmapParse(linedefBlocks.pos[i], i, ParseTextmapLinedefParameter); if (!ld->v1) I_Error("P_LoadTextmap: linedef %s has no v1 value set!\n", sizeu1(i)); @@ -3000,8 +3141,10 @@ static void P_LoadTextmap(void) sd->bottomtexture = R_TextureNumForName("-"); sd->sector = NULL; sd->repeatcnt = 0; + sd->light = sd->light_top = sd->light_mid = sd->light_bottom = 0; + sd->lightabsolute = sd->lightabsolute_top = sd->lightabsolute_mid = sd->lightabsolute_bottom = false; - TextmapParse(sidesPos[i], i, ParseTextmapSidedefParameter); + TextmapParse(sidedefBlocks.pos[i], i, ParseTextmapSidedefParameter); if (!sd->sector) I_Error("P_LoadTextmap: sidedef %s has no sector value set!\n", sizeu1(i)); @@ -3025,7 +3168,7 @@ static void P_LoadTextmap(void) memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs)); mt->mobj = NULL; - TextmapParse(mapthingsPos[i], i, ParseTextmapThingParameter); + TextmapParse(mapthingBlocks.pos[i], i, ParseTextmapThingParameter); } } @@ -3109,7 +3252,12 @@ static boolean P_LoadMapData(const virtres_t *virt) if (udmf) // Count how many entries for each type we got in textmap. { virtlump_t *textmap = vres_Find(virt, "TEXTMAP"); - M_TokenizerOpen((char *)textmap->data); + if (textmap->size == 0) + { + CONS_Alert(CONS_ERROR, "Emtpy TEXTMAP Lump!\n"); + return false; + } + M_TokenizerOpen((char *)textmap->data, textmap->size); if (!TextmapCount(textmap->size)) { M_TokenizerClose(); @@ -3290,8 +3438,6 @@ static void P_InitializeSeg(seg_t *seg) seg->lightmaps = NULL; // list of static lightmap for this seg #endif - seg->numlights = 0; - seg->rlights = NULL; seg->polyseg = NULL; seg->dontrenderme = false; } @@ -3340,13 +3486,13 @@ typedef enum { } nodetype_t; // Find out the BSP format. -static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata) +static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata, char signature[4 + 1]) { boolean supported[NUMNODETYPES] = {0}; nodetype_t nodetype = NT_UNSUPPORTED; - char signature[4 + 1]; *nodedata = NULL; + signature[0] = signature[4] = '\0'; if (udmf) { @@ -3355,7 +3501,7 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata) if (virtznodes && virtznodes->size) { *nodedata = virtznodes->data; - supported[NT_XGLN] = supported[NT_XGL3] = true; + supported[NT_XGLN] = supported[NT_XGL2] = supported[NT_XGL3] = true; } } else @@ -3377,9 +3523,9 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata) virtssectors = vres_Find(virt, "SSECTORS"); if (virtssectors && virtssectors->size) - { // Possibly GL nodes: NODES ignored, SSECTORS takes precedence as nodes lump, (It is confusing yeah) and has a signature. + { // Possibly GL nodes: NODES ignored, SSECTORS takes precedence as nodes lump (it is confusing, yeah), and has a signature. *nodedata = virtssectors->data; - supported[NT_XGLN] = supported[NT_ZGLN] = supported[NT_XGL3] = true; + supported[NT_XGLN] = supported[NT_ZGLN] = supported[NT_XGL2] = supported[NT_XGL3] = true; } else { // Possibly ZDoom extended nodes: SSECTORS is empty, NODES has a signature. @@ -3399,19 +3545,42 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata) } M_Memcpy(signature, *nodedata, 4); - signature[4] = '\0'; (*nodedata) += 4; - if (!strcmp(signature, "XNOD")) - nodetype = NT_XNOD; - else if (!strcmp(signature, "ZNOD")) - nodetype = NT_ZNOD; - else if (!strcmp(signature, "XGLN")) - nodetype = NT_XGLN; - else if (!strcmp(signature, "ZGLN")) - nodetype = NT_ZGLN; - else if (!strcmp(signature, "XGL3")) - nodetype = NT_XGL3; + // Identify node format from its starting signature. + if (memcmp(&signature[1], "NOD", 3) == 0) // ZDoom extended nodes + { + if (signature[0] == 'X') + { + nodetype = NT_XNOD; // Uncompressed + } + else if (signature[0] == 'Z') + { + nodetype = NT_ZNOD; // Compressed + } + } + else if (memcmp(&signature[1], "GL", 2) == 0) // GL nodes + { + switch (signature[0]) + { + case 'X': // Uncompressed + switch (signature[3]) + { + case 'N': nodetype = NT_XGLN; break; // GL nodes + case '2': nodetype = NT_XGL2; break; // Version 2 GL nodes + case '3': nodetype = NT_XGL3; break; // Version 3 GL nodes + } + break; + case 'Z': // Compressed + switch (signature[3]) + { + case 'N': nodetype = NT_ZGLN; break; // GL nodes (compressed) + case '2': nodetype = NT_ZGL2; break; // Version 2 GL nodes (compressed) + case '3': nodetype = NT_ZGL3; break; // Version 3 GL nodes (compressed) + } + break; + } + } return supported[nodetype] ? nodetype : NT_UNSUPPORTED; } @@ -3423,7 +3592,6 @@ static boolean P_LoadExtraVertices(UINT8 **data) UINT32 xtrvrtx = READUINT32((*data)); line_t* ld = lines; vertex_t *oldpos = vertexes; - ssize_t offset; size_t i; if (numvertexes != origvrtx) // If native vertex count doesn't match node original vertex count, bail out (broken data?). @@ -3438,12 +3606,11 @@ static boolean P_LoadExtraVertices(UINT8 **data) // If extra vertexes were generated, reallocate the vertex array and fix the pointers. numvertexes += xtrvrtx; vertexes = Z_Realloc(vertexes, numvertexes*sizeof(*vertexes), PU_LEVEL, NULL); - offset = (size_t)(vertexes - oldpos); for (i = 0, ld = lines; i < numlines; i++, ld++) { - ld->v1 += offset; - ld->v2 += offset; + ld->v1 = &vertexes[ld->v1 - oldpos]; + ld->v2 = &vertexes[ld->v2 - oldpos]; } // Read extra vertex data. @@ -3481,6 +3648,7 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype switch (nodetype) { case NT_XGLN: + case NT_XGL2: case NT_XGL3: for (m = 0; m < (size_t)subsectors[i].numlines; m++, k++) { @@ -3492,7 +3660,7 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype READUINT32((*data)); // partner, can be ignored by software renderer - if (nodetype == NT_XGL3) + if (nodetype != NT_XGLN) { UINT32 linenum = READUINT32((*data)); if (linenum != 0xFFFFFFFF && linenum >= numlines) @@ -3603,8 +3771,9 @@ static void P_LoadExtendedNodes(UINT8 **data, nodetype_t nodetype) static void P_LoadMapBSP(const virtres_t *virt) { + char signature[4 + 1]; UINT8 *nodedata = NULL; - nodetype_t nodetype = P_GetNodetype(virt, &nodedata); + nodetype_t nodetype = P_GetNodetype(virt, &nodedata, signature); switch (nodetype) { @@ -3636,6 +3805,7 @@ static void P_LoadMapBSP(const virtres_t *virt) } case NT_XNOD: case NT_XGLN: + case NT_XGL2: case NT_XGL3: if (!P_LoadExtraVertices(&nodedata)) return; @@ -3644,10 +3814,13 @@ static void P_LoadMapBSP(const virtres_t *virt) P_LoadExtendedNodes(&nodedata, nodetype); break; default: - CONS_Alert(CONS_WARNING, "Unsupported BSP format detected.\n"); - return; + if (isprint(signature[0]) && isprint(signature[1]) && isprint(signature[2]) && isprint(signature[3])) + { + I_Error("Unsupported BSP format '%s' detected!\n", signature); + return; + } + I_Error("Unknown BSP format detected!\n"); } - return; } // Split from P_LoadBlockMap for convenience @@ -7160,7 +7333,7 @@ void P_RespawnThings(void) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (think->removing) continue; P_RemoveMobj((mobj_t *)think); } @@ -7196,11 +7369,11 @@ static void P_RunLevelScript(const char *scriptname) return; } - COM_BufInsertText(W_CacheLumpNum(lumpnum, PU_CACHE)); + COM_BufInsertTextEx(W_CacheLumpNum(lumpnum, PU_CACHE), COM_LUA); } else { - COM_BufAddText(va("exec %s\n", scriptname)); + COM_ExecFile(scriptname, COM_LUA, false); } COM_BufExecute(); // Run it! } @@ -7472,20 +7645,20 @@ static void P_InitCamera(void) CV_SetValue(&cv_analog[1], 0); displayplayer = consoleplayer; // Start with your OWN view, please! - } - if (twodlevel) - { - CV_SetValue(&cv_analog[0], false); - CV_SetValue(&cv_analog[1], false); - } - else - { - if (cv_useranalog[0].value) - CV_SetValue(&cv_analog[0], true); + if (twodlevel) + { + CV_SetValue(&cv_analog[0], false); + CV_SetValue(&cv_analog[1], false); + } + else + { + if (cv_useranalog[0].value) + CV_SetValue(&cv_analog[0], true); - if ((splitscreen && cv_useranalog[1].value) || botingame) - CV_SetValue(&cv_analog[1], true); + if ((splitscreen && cv_useranalog[1].value) || botingame) + CV_SetValue(&cv_analog[1], true); + } } } @@ -7680,6 +7853,10 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) maptol = mapheaderinfo[gamemap-1]->typeoflevel; gametyperules = gametypedefaultrules[gametype]; + // clear the target on map change, since the object will be invalidated + P_SetTarget(&ticcmd_ztargetfocus[0], NULL); + P_SetTarget(&ticcmd_ztargetfocus[1], NULL); + CON_Drawer(); // let the user know what we are going to do I_FinishUpdate(); // page flip or blit buffer @@ -7829,6 +8006,9 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) // Free GPU textures before freeing patches. if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED)) HWR_ClearAllTextures(); + + // Delete light table textures + HWR_ClearLightTables(); #endif Patch_FreeTag(PU_PATCH_LOWPRIORITY); diff --git a/src/p_setup.h b/src/p_setup.h index f9e51024d2dbcf55f61bd193d1e32edc278a31be..6b0218854362085c0ae77220d984b567096e2d93 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -71,7 +71,7 @@ boolean P_AddFolder(const char *folderpath); boolean P_RunSOC(const char *socfilename); void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num); void P_LoadMusicsRange(UINT16 wadnum, UINT16 first, UINT16 num); -//void P_WriteThings(void); +void P_WriteThings(const char *filepath); size_t P_PrecacheLevelFlats(void); void P_AllocMapHeader(INT16 i); @@ -87,5 +87,6 @@ UINT8 P_GetGrade(UINT32 pscore, INT16 map, UINT8 mare); UINT8 P_HasGrades(INT16 map, UINT8 mare); UINT32 P_GetScoreForGrade(INT16 map, UINT8 mare, UINT8 grade); UINT32 P_GetScoreForGradeOverall(INT16 map, UINT8 grade); +void P_AddNiGHTSTimes(INT16 i, char *gtext); #endif diff --git a/src/p_slopes.c b/src/p_slopes.c index e75d36edefe8d8484cb0c9bebb4d02d5f1b1e174..7390329369b4b5dfbb9b084e4396234f99b1fb57 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2009 by Stephen McGranahan. -// Copyright (C) 2015-2023 by Sonic Team Junior. +// Copyright (C) 2015-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -28,6 +28,8 @@ pslope_t *slopelist = NULL; UINT16 slopecount = 0; +static void P_UpdateMidtextureSlopesForSector(sector_t *sector); + // Calculate line normal void P_CalculateSlopeNormal(pslope_t *slope) { @@ -180,7 +182,7 @@ void T_DynamicSlopeLine (dynlineplanethink_t* th) pslope_t* slope = th->slope; line_t* srcline = th->sourceline; - fixed_t zdelta; + fixed_t zdelta, oldoz = slope->o.z; switch(th->type) { case DP_FRONTFLOOR: @@ -207,11 +209,14 @@ void T_DynamicSlopeLine (dynlineplanethink_t* th) return; } - if (slope->zdelta != FixedDiv(zdelta, th->extent)) { + if (slope->zdelta != FixedDiv(zdelta, th->extent) || oldoz != slope->o.z) { slope->zdelta = FixedDiv(zdelta, th->extent); slope->zangle = R_PointToAngle2(0, 0, th->extent, -zdelta); slope->moved = true; P_CalculateSlopeNormal(slope); + P_UpdateMidtextureSlopesForSector(srcline->frontsector); + if (srcline->backsector) + P_UpdateMidtextureSlopesForSector(srcline->backsector); } } @@ -232,6 +237,12 @@ void T_DynamicSlopeVert (dynvertexplanethink_t* th) } ReconfigureViaVertexes(th->slope, th->vex[0], th->vex[1], th->vex[2]); + + for (i = 0; i < 3; i++) + { + if (th->secs[i]) + P_UpdateMidtextureSlopesForSector(th->secs[i]); + } } static inline void P_AddDynLineSlopeThinker (pslope_t* slope, dynplanetype_t type, line_t* sourceline, fixed_t extent) @@ -758,6 +769,111 @@ pslope_t *P_MakeSlopeViaEquationConstants(const double a, const double b, const return ret; } +static pslope_t *P_GetReferenceSlopeForMidtexture(line_t *line) +{ + if (line->flags & ML_MIDPEG) + { + // Line has ML_MIDPEG, so use the floor slope + fixed_t frontheight = P_GetSectorFloorZAt(line->frontsector, line->v1->x, line->v1->y); + fixed_t backheight = P_GetSectorFloorZAt(line->backsector, line->v1->x, line->v1->y); + + if (frontheight > backheight) + { + return line->frontsector->f_slope; + } + else + { + return line->backsector->f_slope; + } + } + else + { + // Line does not have ML_MIDPEG, so use the ceiling slope + fixed_t frontheight = P_GetSectorCeilingZAt(line->frontsector, line->v1->x, line->v1->y); + fixed_t backheight = P_GetSectorCeilingZAt(line->backsector, line->v1->x, line->v1->y); + + if (frontheight < backheight) + { + return line->frontsector->c_slope; + } + else + { + return line->backsector->c_slope; + } + } + + return NULL; +} + +// Updates a slope for a solid midtexture based on the slope of the sector it's in. +static void P_UpdateSolidMidtextureSlope(line_t *line, pslope_t *ref) +{ + pslope_t *slope = line->midtexslope; + + if (ref == NULL) + return; + + // Set origin + vector3_t origin; + origin.x = line->v1->x; + origin.y = line->v1->y; + origin.z = P_GetSlopeZAt(ref, origin.x, origin.y); + FV3_Copy(&slope->o, &origin); + + // Get where the line ends + vector3_t point; + point.x = line->v2->x; + point.y = line->v2->y; + point.z = P_GetSlopeZAt(ref, point.x, point.y); + + // Get length of the line + fixed_t extent = R_PointToDist2(0, 0, line->dx, line->dy); + + // Precalculate variables + slope->zdelta = FixedDiv(origin.z - point.z, extent); + slope->zangle = R_PointToAngle2(0, origin.z, extent, point.z); + slope->xydirection = line->angle; + + // Precalculate the direction + vector2_t dir; + dir.x = FixedMul(FINECOSINE(slope->zangle >> ANGLETOFINESHIFT), FINECOSINE((slope->xydirection+ANGLE_180) >> ANGLETOFINESHIFT)); + dir.y = FixedMul(FINECOSINE(slope->zangle >> ANGLETOFINESHIFT), FINESINE((slope->xydirection+ANGLE_180) >> ANGLETOFINESHIFT)); + FV2_Copy(&slope->d, &dir); + + P_CalculateSlopeNormal(slope); + + // Calling P_CalculateSlopeVectors is not necessary. + slope->moved = true; +} + +// Goes through every line in the sector and updates the midtexture slope if it is present +static void P_UpdateMidtextureSlopesForSector(sector_t *sector) +{ + for (size_t i = 0; i < sector->linecount; i++) + { + if (sector->lines[i]->midtexslope != NULL) + P_UpdateSolidMidtextureSlope(sector->lines[i], P_GetReferenceSlopeForMidtexture(sector->lines[i])); + } +} + +// Creates a solid midtexture slope for the line if possible +static void P_CreateSolidMidtextureSlope(line_t *line) +{ + if (line->backsector == NULL) // Ignore single-sided lines (of course) + return; + + if ((line->flags & ML_MIDSOLID) == 0) // Ignore if the midtexture is not solid + return; + + pslope_t *ref = P_GetReferenceSlopeForMidtexture(line); + if (ref) + { + line->midtexslope = Slope_Add(ref->flags & SL_NOPHYSICS); + + P_UpdateSolidMidtextureSlope(line, ref); + } +} + /// Initializes and reads the slopes from the map data. void P_SpawnSlopes(const boolean fromsave) { size_t i; @@ -785,14 +901,21 @@ void P_SpawnSlopes(const boolean fromsave) { /// Copies slopes from tagged sectors via line specials. /// \note Doesn't actually copy, but instead they share the same pointers. + // Also, creates midtexture slopes. for (i = 0; i < numlines; i++) - switch (lines[i].special) + { + line_t *line = &lines[i]; + + switch (line->special) { case 720: - P_CopySectorSlope(&lines[i]); + P_CopySectorSlope(line); default: break; } + + P_CreateSolidMidtextureSlope(line); + } } /// Initializes slopes. @@ -810,10 +933,10 @@ void P_InitSlopes(void) // Returns the height of the sloped plane at (x, y) as a fixed_t fixed_t P_GetSlopeZAt(const pslope_t *slope, fixed_t x, fixed_t y) { - fixed_t dist = FixedMul(x - slope->o.x, slope->d.x) + - FixedMul(y - slope->o.y, slope->d.y); + fixed_t dist = FixedMul(x - slope->o.x, slope->d.x) / 2 + + FixedMul(y - slope->o.y, slope->d.y) / 2; - return slope->o.z + FixedMul(dist, slope->zdelta); + return slope->o.z + FixedMul(dist, slope->zdelta) * 2; } // Like P_GetSlopeZAt but falls back to z if slope is NULL diff --git a/src/p_slopes.h b/src/p_slopes.h index fdc07f67e257ba05eef35fc481c3be3a0ebdfd7c..39b7ba56dbf2119e730b145e90d76bb18e9d7e70 100644 --- a/src/p_slopes.h +++ b/src/p_slopes.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2009 by Stephen McGranahan. -// Copyright (C) 2015-2023 by Sonic Team Junior. +// Copyright (C) 2015-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_spec.c b/src/p_spec.c index 37036d095cb7f7934ebcb4473f22152312e6356c..93809cbb4b68118e4fc4032186c5e772435daba2 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -363,7 +363,7 @@ void P_ParseAnimationDefintion(SINT8 istexture) // Increase the size to make room for the new animation definition maxanims++; animdefs = (animdef_t *)Z_Realloc(animdefs, sizeof(animdef_t)*(maxanims + 1), PU_STATIC, NULL); - strncpy(animdefs[i].startname, animdefsToken, 9); + strncpy(animdefs[i].startname, animdefsToken, sizeof(animdefs[i].startname)-1); } // animdefs[i].startname is now set to animdefsToken either way. @@ -2405,11 +2405,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) y = line->args[3] << FRACBITS; z = line->args[4] << FRACBITS; - P_UnsetThingPosition(mo); - mo->x += x; - mo->y += y; - mo->z += z; - P_SetThingPosition(mo); + P_SetOrigin(mo, mo->x + x, mo->y + y, mo->z + z); if (mo->player) { @@ -2417,6 +2413,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) P_SetOrigin(bot, bot->x + x, bot->y + y, bot->z + z); if (splitscreen && mo->player == &players[secondarydisplayplayer] && camera2.chase) { + camera2.reset = true; camera2.x += x; camera2.y += y; camera2.z += z; @@ -2424,6 +2421,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } else if (camera.chase && mo->player == &players[displayplayer]) { + camera.reset = true; camera.x += x; camera.y += y; camera.z += z; @@ -2548,7 +2546,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) char *text = Z_Malloc(len + 1, PU_CACHE, NULL); memcpy(text, lump, len); text[len] = '\0'; - COM_BufInsertText(text); + COM_BufInsertTextEx(text, COM_LUA); Z_Free(text); } } @@ -3605,7 +3603,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { if (!playeringame[i]) continue; - P_DoPlayerExit(&players[i]); + P_DoPlayerExit(&players[i], true); } } } @@ -3644,7 +3642,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (mo2->type != MT_EGGTRAP) continue; - if (mo2->thinker.function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (mo2->thinker.removing) continue; P_KillMobj(mo2, NULL, mo, 0); @@ -3659,7 +3657,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { if (!playeringame[i]) continue; - P_DoPlayerExit(&players[i]); + P_DoPlayerExit(&players[i], true); } } } @@ -3684,7 +3682,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 466: // Set level failure state { - if (line->args[1]) + if (line->args[0]) { stagefailed = false; CONS_Debug(DBG_GAMELOGIC, "Stage can be completed successfully!\n"); @@ -3856,7 +3854,7 @@ void P_SetupSignExit(player_t *player) // spin all signposts in the level then. for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (think->removing) continue; thing = (mobj_t *)think; @@ -3894,7 +3892,7 @@ boolean P_IsFlagAtBase(mobjtype_t flag) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (think->removing) continue; mo = (mobj_t *)think; @@ -4397,7 +4395,7 @@ static void P_ProcessEggCapsule(player_t *player, sector_t *sector) // The chimps are my friends.. heeheeheheehehee..... - LouisJM for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; if (mo2->type != MT_EGGTRAP) @@ -4421,7 +4419,7 @@ static void P_ProcessEggCapsule(player_t *player, sector_t *sector) { if (!playeringame[i]) continue; - P_DoPlayerExit(&players[i]); + P_DoPlayerExit(&players[i], true); } } @@ -4731,7 +4729,7 @@ static void P_ProcessFinishLine(player_t *player) HU_DoCEcho("FINISHED!"); } - P_DoPlayerExit(player); + P_DoPlayerExit(player, true); } } @@ -6238,7 +6236,7 @@ static void P_DoPortalCopyFromLine(sector_t *dest_sector, int plane_type, int ta } } -static sectorportal_t *P_SectorGetPortalOrCreate(sector_t *sector, UINT32 *num, UINT32 *result) +static sectorportal_t *P_SectorGetPortalOrCreate(sector_t *sector, UINT32 *num, UINT32 *result, boolean ceiling) { sectorportal_t *secportal = NULL; @@ -6246,8 +6244,8 @@ static sectorportal_t *P_SectorGetPortalOrCreate(sector_t *sector, UINT32 *num, { *num = P_NewSectorPortal(); secportal = &secportals[*num]; - secportal->origin.x = sector->soundorg.x; - secportal->origin.y = sector->soundorg.y; + secportal->target = sector; + secportal->ceiling = ceiling; *result = *num; } else @@ -6261,12 +6259,12 @@ static sectorportal_t *P_SectorGetPortalOrCreate(sector_t *sector, UINT32 *num, static sectorportal_t *P_SectorGetFloorPortalOrCreate(sector_t *sector, UINT32 *result) { - return P_SectorGetPortalOrCreate(sector, §or->portal_floor, result); + return P_SectorGetPortalOrCreate(sector, §or->portal_floor, result, false); } static sectorportal_t *P_SectorGetCeilingPortalOrCreate(sector_t *sector, UINT32 *result) { - return P_SectorGetPortalOrCreate(sector, §or->portal_ceiling, result); + return P_SectorGetPortalOrCreate(sector, §or->portal_ceiling, result, true); } static void P_CopySectorPortalToLines(UINT32 portal_num, int sector_tag) diff --git a/src/p_spec.h b/src/p_spec.h index b9c3a2ca3c2055481b54cd2d2fce3217df244fe7..ba08781b636cdb0042368c5ff90b5fa0db8c193c 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/p_tick.c b/src/p_tick.c index 4ab388486db62be9d1fa36d9289ac2b043219e47..db8688484ac3dbcf56fafc293af6bc995190e0f9 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -162,7 +162,7 @@ void Command_CountMobjs_f(void) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; if (((mobj_t *)th)->type == i) @@ -182,7 +182,7 @@ void Command_CountMobjs_f(void) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; if (((mobj_t *)th)->type == i) @@ -348,6 +348,7 @@ void P_RemoveThinkerDelayed(thinker_t *thinker) void P_RemoveThinker(thinker_t *thinker) { LUA_InvalidateUserdata(thinker); + thinker->removing = true; thinker->function.acp1 = (actionf_p1)P_RemoveThinkerDelayed; } @@ -564,6 +565,12 @@ void P_DoTeamscrambling(void) CV_SetValue(&cv_teamscramble, 0); } + +// +// P_DoSpecialStageStuff() +// +// For old-style (non-NiGHTS) special stages +// static inline void P_DoSpecialStageStuff(void) { boolean stillalive = false; @@ -601,7 +608,15 @@ static inline void P_DoSpecialStageStuff(void) if (--players[i].nightstime > 6) { if (P_IsLocalPlayer(&players[i]) && oldnightstime > 10*TICRATE && players[i].nightstime <= 10*TICRATE) - S_ChangeMusicInternal("_drown", false); + { + if (mapheaderinfo[gamemap-1]->levelflags & LF_MIXNIGHTSCOUNTDOWN) + { + S_FadeMusic(0, 10*MUSICRATE); + S_StartSound(NULL, sfx_timeup); // that creepy "out of time" music from NiGHTS. + } + else + S_ChangeMusicInternal("_drown", false); + } stillalive = true; } else if (!players[i].exiting) @@ -844,7 +859,7 @@ void P_Ticker(boolean run) if (quake.time) --quake.time; - if (metalplayback) + if (!P_MobjWasRemoved(metalplayback)) G_ReadMetalTic(metalplayback); if (metalrecording) G_WriteMetalTic(players[consoleplayer].mo); diff --git a/src/p_user.c b/src/p_user.c index 200b7673659eb4f4975cb76723c998da7f3c449c..7cc9c02ae722cb539126e0a14b160f7faef00754 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -435,7 +435,7 @@ UINT8 P_FindLowestMare(void) // to find the egg capsule with the lowest mare for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -488,7 +488,7 @@ boolean P_TransferToNextMare(player_t *player) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -539,7 +539,7 @@ static mobj_t *P_FindAxis(INT32 mare, INT32 axisnum) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -574,7 +574,7 @@ static mobj_t *P_FindAxisTransfer(INT32 mare, INT32 axisnum, mobjtype_t type) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -615,7 +615,7 @@ void P_TransferToAxis(player_t *player, INT32 axisnum) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -669,7 +669,7 @@ static void P_DeNightserizePlayer(player_t *player) player->powers[pw_carry] = CR_NIGHTSFALL; player->powers[pw_underwater] = 0; - player->pflags &= ~(PF_SPINDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_SHIELDDOWN|PF_STARTDASH|PF_GLIDING|PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED|PF_SPINNING|PF_DRILLING|PF_TRANSFERTOCLOSEST); + player->pflags &= ~(PF_SPINDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_STARTDASH|PF_GLIDING|PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED|PF_SPINNING|PF_DRILLING|PF_TRANSFERTOCLOSEST); player->secondjump = 0; player->homing = 0; player->climbing = 0; @@ -716,7 +716,7 @@ static void P_DeNightserizePlayer(player_t *player) // Check to see if the player should be killed. for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -776,7 +776,7 @@ static void P_DeNightserizePlayer(player_t *player) // NiGHTS Time! void P_NightserizePlayer(player_t *player, INT32 nighttime) { - UINT8 oldmare, oldmarelap, oldmarebonuslap; + UINT8 oldmare, oldmarelap, oldmarebonuslap, newmare; // Bots can't be NiGHTSerized, silly!1 :P if (player->bot) @@ -797,7 +797,12 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) } } - player->pflags &= ~(PF_SPINDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_SHIELDDOWN|PF_STARTDASH|PF_GLIDING|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED|PF_SHIELDABILITY|PF_SPINNING|PF_DRILLING); + // Use mare-specific time limit if specified + newmare = P_FindLowestMare(); + if (mapheaderinfo[gamemap-1]->nightstimer[newmare] > 0) + nighttime = mapheaderinfo[gamemap-1]->nightstimer[newmare]; + + player->pflags &= ~(PF_SPINDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_STARTDASH|PF_GLIDING|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED|PF_SHIELDABILITY|PF_SPINNING|PF_DRILLING); player->homing = 0; player->mo->fuse = 0; player->speed = 0; @@ -867,7 +872,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) continue; players[i].texttimer = (3 * TICRATE) - 10; - players[i].textvar = 4; // Score and grades + players[i].textvar = NTV_BONUSTIMEEND; // Score and grades players[i].lastmare = players[i].mare; players[i].lastmarelap = players[i].marelap; players[i].lastmarebonuslap = players[i].marebonuslap; @@ -885,7 +890,8 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) } // Add score to leaderboards now - G_AddTempNightsRecords(player, players[i].marescore, leveltime - player->marebegunat, players[i].mare + 1); + player->lastmaretime = leveltime - player->marebegunat; + G_AddTempNightsRecords(player, players[i].marescore, player->lastmaretime, players[i].mare + 1); // transfer scores anyway players[i].totalmarescore += players[i].marescore; @@ -893,7 +899,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) players[i].marescore = 0; players[i].spheres = players[i].rings = 0; - P_DoPlayerExit(&players[i]); + P_DoPlayerExit(&players[i], true); } } else if (oldmare != player->mare) @@ -906,12 +912,13 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) player->lastmarelap = oldmarelap; player->lastmarebonuslap = oldmarebonuslap; player->texttimer = 4*TICRATE; - player->textvar = 4; // Score and grades + player->textvar = NTV_BONUSTIMEEND; // Score and grades player->finishedspheres = (INT16)(player->spheres); player->finishedrings = (INT16)(player->rings); // Add score to temp leaderboards - G_AddTempNightsRecords(player, player->marescore, leveltime - player->marebegunat, (UINT8)(oldmare + 1)); + player->lastmaretime = leveltime - player->marebegunat; + G_AddTempNightsRecords(player, player->marescore, player->lastmaretime, (UINT8)(oldmare + 1)); // Starting a new mare, transfer scores player->totalmarescore += player->marescore; @@ -924,7 +931,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) } else { - player->textvar = 5; // Nothing, just tells it to go to the GET n RINGS/SPHERES text in a bit + player->textvar = NTV_NONE; // Nothing, just tells it to go to the GET n RINGS/SPHERES text in a bit player->texttimer = 40; // Don't show before title card @@ -969,6 +976,9 @@ pflags_t P_GetJumpFlags(player_t *player) // boolean P_PlayerInPain(player_t *player) { + if (P_MobjWasRemoved(player->mo)) + return false; + // no silly, sliding isn't pain if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing]) return true; @@ -1082,6 +1092,13 @@ void P_ResetPlayer(player_t *player) if (player->mo->tracer && !P_MobjWasRemoved(player->mo->tracer)) { player->mo->tracer->flags |= MF_PUSHABLE; + + // goose the mom a little bit to trigger gravity to process for a tic + if (player->mo->tracer->eflags & MFE_VERTICALFLIP) + player->mo->tracer->momz -= 1; + else + player->mo->tracer->momz += 1; + P_SetTarget(&player->mo->tracer->tracer, NULL); } P_SetTarget(&player->mo->tracer, NULL); @@ -1345,6 +1362,8 @@ void P_DoSuperTransformation(player_t *player, boolean giverings) if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOSSMUSIC) && P_IsLocalPlayer(player)) P_PlayJingle(player, JT_SUPER); + S_StartSound(NULL, sfx_supert); //let all players hear it -mattw_cfi + player->mo->momx = player->mo->momy = player->mo->momz = player->cmomx = player->cmomy = player->rmomx = player->rmomy = 0; // Transformation animation @@ -1361,11 +1380,8 @@ void P_DoSuperTransformation(player_t *player, boolean giverings) player->powers[pw_sneakers] = 0; } - if (G_CoopGametype()) - S_StartSound(player->mo, sfx_supert); //only hear it near yourself in co-op - else + if (!G_CoopGametype()) { - S_StartSound(NULL, sfx_supert); //let all players hear it -mattw_cfi HU_SetCEchoFlags(0); HU_SetCEchoDuration(5); HU_DoCEcho(va("%s\\is now super.\\\\\\\\", player_names[player-players])); @@ -1378,7 +1394,7 @@ void P_DoSuperTransformation(player_t *player, boolean giverings) // P_DoSuperDetransformation // // Detransform into regular Sonic! -static void P_DoSuperDetransformation(player_t *player) +void P_DoSuperDetransformation(player_t *player) { player->powers[pw_emeralds] = 0; // lost the power stones P_SpawnGhostMobj(player->mo); @@ -1882,7 +1898,7 @@ void P_SpawnShieldOrb(player_t *player) // blaze through the thinkers to see if an orb already exists! for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; shieldobj = (mobj_t *)th; @@ -2038,8 +2054,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) P_SetTarget(&ghost->target, mobj); P_SetTarget(&ghost->dontdrawforviewmobj, mobj); // Hide the ghost in first-person - P_SetScale(ghost, mobj->scale); - ghost->destscale = mobj->scale; + P_SetScale(ghost, mobj->scale, true); if (mobj->eflags & MFE_VERTICALFLIP) { @@ -2065,6 +2080,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->renderflags = mobj->renderflags; ghost->blendmode = mobj->blendmode; + ghost->alpha = mobj->alpha; ghost->spritexscale = mobj->spritexscale; ghost->spriteyscale = mobj->spriteyscale; @@ -2098,6 +2114,11 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->old_pitch = mobj->old_pitch2; ghost->old_roll = mobj->old_roll2; ghost->old_spriteroll = mobj->old_spriteroll2; + ghost->old_spritexscale = mobj->old_spritexscale2; + ghost->old_spriteyscale = mobj->old_spriteyscale2; + ghost->old_spritexoffset = mobj->old_spritexoffset2; + ghost->old_spriteyoffset = mobj->old_spriteyoffset2; + ghost->old_scale = mobj->old_scale2; return ghost; } @@ -2153,7 +2174,7 @@ void P_SpawnThokMobj(player_t *player) mobj->eflags |= (player->mo->eflags & MFE_VERTICALFLIP); // scale - P_SetScale(mobj, (mobj->destscale = player->mo->scale)); + P_SetScale(mobj, player->mo->scale, true); if (type == MT_THOK) // spintrail-specific modification for MT_THOK { @@ -2217,8 +2238,7 @@ void P_SpawnSpinMobj(player_t *player, mobjtype_t type) mobj->eflags |= (player->mo->eflags & MFE_VERTICALFLIP); // scale - P_SetScale(mobj, player->mo->scale); - mobj->destscale = player->mo->scale; + P_SetScale(mobj, player->mo->scale, true); if (type == MT_THOK) // spintrail-specific modification for MT_THOK { @@ -2264,7 +2284,7 @@ void P_DoPlayerFinish(player_t *player) // P_DoPlayerExit // // Player exits the map via sector trigger -void P_DoPlayerExit(player_t *player) +void P_DoPlayerExit(player_t *player, boolean finishedflag) { if (player->exiting) return; @@ -2285,7 +2305,11 @@ void P_DoPlayerExit(player_t *player) player->exiting = (14*TICRATE)/5 + 1; } else + { player->exiting = (14*TICRATE)/5 + 2; // Accidental death safeguard??? + if (finishedflag) + player->pflags |= PF_FINISHED; // Give PF_FINISHED as proof of a true finish + } //player->pflags &= ~PF_GLIDING; if (player->climbing) @@ -2358,7 +2382,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) if (dorollstuff) { if ((player->charability2 == CA2_SPINDASH) && !((player->pflags & (PF_SPINNING|PF_THOKKED)) == PF_THOKKED) && !(player->charability == CA_THOK && player->secondjump) - && (player->cmd.buttons & BT_SPIN) && (FixedHypot(player->mo->momx, player->mo->momy) > (5*player->mo->scale))) + && (player->cmd.buttons & BT_SPIN) && (FixedHypot(player->mo->momx, player->mo->momy) >= (5*player->mo->scale))) player->pflags = (player->pflags|PF_SPINNING) & ~PF_THOKKED; else if (!(player->pflags & PF_STARTDASH)) player->pflags &= ~PF_SPINNING; @@ -3037,9 +3061,8 @@ static void P_CheckUnderwaterAndSpaceTimer(player_t *player) P_SetMobjState(numbermobj, numbermobj->info->spawnstate+timeleft); P_SetTarget(&numbermobj->target, player->mo); + P_SetScale(numbermobj, player->mo->scale, true); numbermobj->threshold = 40; - numbermobj->destscale = player->mo->scale; - P_SetScale(numbermobj, player->mo->scale); } } } @@ -3101,10 +3124,7 @@ static void P_CheckInvincibilityTimer(player_t *player) { mobj_t *sparkle = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_IVSP); if (!P_MobjWasRemoved(sparkle)) - { - sparkle->destscale = player->mo->scale; - P_SetScale(sparkle, player->mo->scale); - } + P_SetScale(sparkle, player->mo->scale, true); } // Resume normal music stuff. @@ -3179,8 +3199,7 @@ static void P_DoBubbleBreath(player_t *player) if (bubble) { bubble->threshold = 42; - bubble->destscale = player->mo->scale; - P_SetScale(bubble, bubble->destscale); + P_SetScale(bubble, player->mo->scale, true); } // Tails stirs up the water while flying in it @@ -3202,20 +3221,14 @@ static void P_DoBubbleBreath(player_t *player) player->mo->y + stirwatery, stirwaterz, MT_SMALLBUBBLE); if (!P_MobjWasRemoved(bubble)) - { - bubble->destscale = player->mo->scale; - P_SetScale(bubble,bubble->destscale); - } + P_SetScale(bubble, player->mo->scale, true); bubble = P_SpawnMobj( player->mo->x - stirwaterx, player->mo->y - stirwatery, stirwaterz, MT_SMALLBUBBLE); if (!P_MobjWasRemoved(bubble)) - { - bubble->destscale = player->mo->scale; - P_SetScale(bubble,bubble->destscale); - } + P_SetScale(bubble, player->mo->scale, true); } } @@ -4185,16 +4198,6 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd) I_Assert(player != NULL); I_Assert(!P_MobjWasRemoved(player->mo)); - - // Toss a flag - if (cmd->buttons & BT_TOSSFLAG && G_GametypeHasTeams() - && !(player->powers[pw_super]) && !(player->tossdelay)) - { - if (!(player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) - P_PlayerEmeraldBurst(player, true); // Toss emeralds - else - P_PlayerFlagBurst(player, true); - } if (!(cmd->buttons & (BT_ATTACK|BT_FIRENORMAL))) { @@ -4204,10 +4207,9 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd) return; } - if (player->pflags & PF_ATTACKDOWN || player->climbing) + if (player->pflags & PF_ATTACKDOWN || player->climbing || (G_TagGametype() && !(player->pflags & PF_TAGIT))) return; - // Fire a fireball if we have the Fire Flower powerup! if (((player->powers[pw_shield] & SH_STACK) == SH_FIREFLOWER) && !(player->weapondelay)) { player->pflags |= PF_ATTACKDOWN; @@ -4219,8 +4221,7 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd) return; } - // No ringslinging outside of ringslinger! - if (!G_RingSlingerGametype() || player->weapondelay || (G_TagGametype() && !(player->pflags & PF_TAGIT))) + if (!G_RingSlingerGametype() || player->weapondelay) return; player->pflags |= PF_ATTACKDOWN; @@ -4398,7 +4399,34 @@ static void P_DoSuperStuff(player_t *player) // If you're super and not Sonic, de-superize! if (!(ALL7EMERALDS(emeralds) && player->charflags & SF_SUPER)) { - P_DoSuperDetransformation(player); + player->powers[pw_super] = 0; + P_SetMobjState(player->mo, S_PLAY_STND); + if (P_IsLocalPlayer(player)) + { + music_stack_noposition = true; // HACK: Do not reposition next music + music_stack_fadeout = MUSICRATE/2; // HACK: Fade out current music + } + P_RestoreMusic(player); + P_SpawnShieldOrb(player); + + // Restore color + if ((player->powers[pw_shield] & SH_STACK) == SH_FIREFLOWER) + { + player->mo->color = SKINCOLOR_WHITE; + G_GhostAddColor(GHC_FIREFLOWER); + } + else + { + player->mo->color = P_GetPlayerColor(player); + G_GhostAddColor(GHC_NORMAL); + } + + if (!G_CoopGametype()) + { + HU_SetCEchoFlags(0); + HU_SetCEchoDuration(5); + HU_DoCEcho(va("%s\\is no longer super.\\\\\\\\", player_names[player-players])); + } return; } @@ -4420,45 +4448,33 @@ static void P_DoSuperStuff(player_t *player) { spark = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SUPERSPARK); if (!P_MobjWasRemoved(spark)) - { - spark->destscale = player->mo->scale; - P_SetScale(spark, player->mo->scale); - } + P_SetScale(spark, player->mo->scale, true); } // Ran out of rings while super! if (player->rings <= 0 || player->exiting) + { P_DoSuperDetransformation(player); + } } } // // P_SuperReady // -// Returns true if player is ready to transform or detransform +// Returns true if player is ready to turn super, duh // -boolean P_SuperReady(player_t *player, boolean transform) +boolean P_SuperReady(player_t *player) { - if (!transform && - (player->powers[pw_super] < TICRATE*3/2 - || !G_CoopGametype())) // No turning back in competitive! - return false; - else if (transform - && (player->powers[pw_super] - || !ALL7EMERALDS(emeralds) - || !(player->rings >= 50))) - return false; - - if (player->mo + if (!player->powers[pw_super] + && !player->powers[pw_invulnerability] && !player->powers[pw_tailsfly] - && !player->powers[pw_carry] && (player->charflags & SF_SUPER) - && !P_PlayerInPain(player) - && !player->climbing - && !(player->pflags & (PF_FULLSTASIS|PF_THOKKED|PF_STARTDASH|PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY)) - && ((player->pflags & PF_JUMPED) || (P_IsObjectOnGround(player->mo) && (player->panim == PA_IDLE || player->panim == PA_EDGE - || player->panim == PA_WALK || player->panim == PA_RUN || (player->charflags & SF_DASHMODE && player->panim == PA_DASH)))) - && !(maptol & TOL_NIGHTS)) + && (player->pflags & PF_JUMPED) + && !(player->powers[pw_shield] & SH_NOSTACK) + && !(maptol & TOL_NIGHTS) + && ALL7EMERALDS(emeralds) + && (player->rings >= 50)) return true; return false; @@ -4556,6 +4572,13 @@ void P_DoJump(player_t *player, boolean soundandstate, boolean allowflip) player->mo->momz += player->mo->tracer->momz; if (!P_IsObjectOnGround(player->mo->tracer)) P_SetObjectMomZ(player->mo->tracer, -9*FRACUNIT, true); + + // goose the mom a little bit to trigger gravity to process for a tic + if (player->mo->tracer->eflags & MFE_VERTICALFLIP) + player->mo->tracer->momz -= 1; + else + player->mo->tracer->momz += 1; + player->mo->tracer->flags |= MF_PUSHABLE; P_SetTarget(&player->mo->tracer->tracer, NULL); } @@ -4673,8 +4696,7 @@ void P_DoSpinDashDust(player_t *player) P_SetMobjState(particle, S_SPINDUST_FIRE1); P_SetTarget(&particle->target, player->mo); - particle->destscale = (2*player->mo->scale)/3; - P_SetScale(particle, particle->destscale); + P_SetScale(particle, (2*player->mo->scale)/3, true); if (player->mo->eflags & MFE_VERTICALFLIP) // readjust z position if needed particle->z = player->mo->z + player->mo->height - particle->height; prandom[0] = P_RandomFixed()<<2; // P_RandomByte()<<10 @@ -4732,7 +4754,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) // Revving else if ((cmd->buttons & BT_SPIN) && (player->pflags & PF_STARTDASH)) { - if (player->speed > 5*player->mo->scale) + if (player->speed >= 5*player->mo->scale) { player->pflags &= ~PF_STARTDASH; P_SetMobjState(player->mo, S_PLAY_ROLL); @@ -4772,9 +4794,8 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) if (!player->spectator) S_StartSound(player->mo, sfx_spin); } - else // Catapult the player from a spindash rev! - if (onground && !(player->pflags & PF_SPINDOWN) && (player->pflags & PF_STARTDASH) && (player->pflags & PF_SPINNING)) + else if (onground && !(player->pflags & PF_SPINDOWN) && (player->pflags & PF_STARTDASH) && (player->pflags & PF_SPINNING)) { player->pflags &= ~PF_STARTDASH; if (player->powers[pw_carry] == CR_BRAKGOOP) @@ -4973,7 +4994,7 @@ void P_DoJumpShield(player_t *player) } else { - player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); + player->pflags |= PF_NOJUMPDAMAGE; P_SetMobjState(player->mo, S_PLAY_FALL); S_StartSound(player->mo, sfx_wdjump); } @@ -5073,7 +5094,7 @@ void P_TwinSpinRejuvenate(player_t *player, mobjtype_t type) if (!P_MobjWasRemoved(missile)) { P_SetTarget(&missile->target, player->mo); - P_SetScale(missile, (missile->destscale >>= 1)); + P_SetScale(missile, missile->destscale/2, true); missile->angle = ang + movang; missile->fuse = TICRATE/2; missile->extravalue2 = (99*FRACUNIT)/100; @@ -5106,7 +5127,7 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -5158,7 +5179,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock { mobj_t *lockonshield = NULL; - if ((player->powers[pw_shield] & SH_NOSTACK) && !player->powers[pw_super] && !(player->pflags & PF_SHIELDDOWN) + if ((player->powers[pw_shield] & SH_NOSTACK) && !player->powers[pw_super] && !(player->pflags & PF_SPINDOWN) && ((!(player->pflags & PF_THOKKED) || (((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP || (player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT) && player->secondjump == UINT8_MAX) ))) // thokked is optional if you're bubblewrapped / 3dblasted { if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT && !(player->charflags & SF_NOSHIELDABILITY)) @@ -5188,7 +5209,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock } } } - if ((!(player->charflags & SF_NOSHIELDABILITY)) && (cmd->buttons & BT_SHIELD && !LUA_HookPlayer(player, HOOK(ShieldSpecial)))) // Shield button effects + if ((!(player->charflags & SF_NOSHIELDABILITY)) && (cmd->buttons & BT_SPIN && !LUA_HookPlayer(player, HOOK(ShieldSpecial)))) // Spin button effects { // Force stop if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE) @@ -5310,45 +5331,52 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) ; else if (P_PlayerShieldThink(player, cmd, lockonthok, visual)) ; - else if ((cmd->buttons & BT_SPIN) && !LUA_HookPlayer(player, HOOK(JumpSpinSpecial))) + else if ((cmd->buttons & BT_SPIN)) { - switch (player->charability) + if (!(player->pflags & PF_SPINDOWN) && P_SuperReady(player)) { - case CA_THOK: - if (player->powers[pw_super]) // Super Sonic float - { - if ((player->speed > 5*player->mo->scale) // FixedMul(5<<FRACBITS, player->mo->scale), but scale is FRACUNIT-based - && (P_MobjFlip(player->mo)*player->mo->momz <= 0)) + // If you can turn super and aren't already, + // and you don't have a shield, do it! + P_DoSuperTransformation(player, false); + } + else if (!LUA_HookPlayer(player, HOOK(JumpSpinSpecial))) + switch (player->charability) + { + case CA_THOK: + if (player->powers[pw_super]) // Super Sonic float { - if (player->panim != PA_RUN && player->panim != PA_WALK) + if ((player->speed > 5*player->mo->scale) // FixedMul(5<<FRACBITS, player->mo->scale), but scale is FRACUNIT-based + && (P_MobjFlip(player->mo)*player->mo->momz <= 0)) { - if (player->speed >= FixedMul(player->runspeed, player->mo->scale)) - P_SetMobjState(player->mo, S_PLAY_FLOAT_RUN); - else - P_SetMobjState(player->mo, S_PLAY_FLOAT); - } + if (player->panim != PA_RUN && player->panim != PA_WALK) + { + if (player->speed >= FixedMul(player->runspeed, player->mo->scale)) + P_SetMobjState(player->mo, S_PLAY_FLOAT_RUN); + else + P_SetMobjState(player->mo, S_PLAY_FLOAT); + } - player->mo->momz = 0; - player->pflags &= ~(PF_STARTJUMP|PF_SPINNING); - player->secondjump = 1; + player->mo->momz = 0; + player->pflags &= ~(PF_STARTJUMP|PF_SPINNING); + player->secondjump = 1; + } } - } - break; - case CA_TELEKINESIS: - if (!(player->pflags & (PF_THOKKED|PF_SPINDOWN)) || (player->charflags & SF_MULTIABILITY)) - { - P_Telekinesis(player, - -FixedMul(player->actionspd, player->mo->scale), // -ve thrust (pulling towards player) - FixedMul(384*FRACUNIT, player->mo->scale)); - } - break; - case CA_TWINSPIN: - if ((player->charability2 == CA2_MELEE) && (!(player->pflags & (PF_THOKKED|PF_SPINDOWN)) || player->charflags & SF_MULTIABILITY)) - P_DoTwinSpin(player); - break; - default: - break; - } + break; + case CA_TELEKINESIS: + if (!(player->pflags & (PF_THOKKED|PF_SPINDOWN)) || (player->charflags & SF_MULTIABILITY)) + { + P_Telekinesis(player, + -FixedMul(player->actionspd, player->mo->scale), // -ve thrust (pulling towards player) + FixedMul(384*FRACUNIT, player->mo->scale)); + } + break; + case CA_TWINSPIN: + if ((player->charability2 == CA2_MELEE) && (!(player->pflags & (PF_THOKKED|PF_SPINDOWN)) || player->charflags & SF_MULTIABILITY)) + P_DoTwinSpin(player); + break; + default: + break; + } } } @@ -5411,6 +5439,12 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) } else if (player->pflags & PF_SLIDING || ((gametyperules & GTR_TEAMFLAGS) && player->gotflag) || player->pflags & PF_SHIELDABILITY) ; + /*else if (P_SuperReady(player)) + { + // If you can turn super and aren't already, + // and you don't have a shield, do it! + P_DoSuperTransformation(player, false); + }*/ else if (player->pflags & PF_JUMPED) { if (!LUA_HookPlayer(player, HOOK(AbilitySpecial))) @@ -6465,7 +6499,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad // Find next waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -6501,7 +6535,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad { for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -6530,7 +6564,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad { for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -7015,7 +7049,7 @@ static void P_DoNiGHTSCapsule(player_t *player) { players[i].bonustime = true; players[i].texttimer = 4*TICRATE; - players[i].textvar = 1; // Time Bonus + players[i].textvar = NTV_BONUSTIMESTART; // Time Bonus players[i].finishedtime = players[i].nightstime; if (!G_IsSpecialStage(gamemap)) P_AddPlayerScore(&players[i], (players[i].finishedtime/TICRATE) * 100); @@ -7099,12 +7133,12 @@ static void P_DoNiGHTSCapsule(player_t *player) { S_StartScreamSound(player->mo, sfx_lose); player->texttimer = 4*TICRATE; - player->textvar = 3; // Get more rings! + player->textvar = NTV_GETMORESPHERES; // Get more spheres/chips! player->capsule->reactiontime = 0; player->capsule->extravalue1 = player->capsule->cvmem =\ player->capsule->cusval = player->capsule->movecount =\ player->capsule->lastlook = player->capsule->extravalue2 = -1; - P_RunNightsCapsuleTouchExecutors(player->mo, false, false); // run capsule exit executors, and we lacked rings + P_RunNightsCapsuleTouchExecutors(player->mo, false, false); // run capsule exit executors, and we lacked spheres/chips } } } @@ -7262,7 +7296,7 @@ static void P_NiGHTSMovement(player_t *player) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -7413,9 +7447,8 @@ static void P_NiGHTSMovement(player_t *player) firstmobj = P_SpawnMobj(player->mo->x + P_ReturnThrustX(player->mo, player->mo->angle+ANGLE_90, spawndist), player->mo->y + P_ReturnThrustY(player->mo, player->mo->angle+ANGLE_90, spawndist), z, MT_NIGHTSPARKLE); if (!P_MobjWasRemoved(firstmobj)) { - firstmobj->destscale = player->mo->scale; P_SetTarget(&firstmobj->target, player->mo); - P_SetScale(firstmobj, player->mo->scale); + P_SetScale(firstmobj, player->mo->scale, true); // Superloop turns sparkles red if (player->powers[pw_nights_superloop]) P_SetMobjState(firstmobj, mobjinfo[MT_NIGHTSPARKLE].seestate); @@ -7423,10 +7456,8 @@ static void P_NiGHTSMovement(player_t *player) secondmobj = P_SpawnMobj(player->mo->x + P_ReturnThrustX(player->mo, player->mo->angle-ANGLE_90, spawndist), player->mo->y + P_ReturnThrustY(player->mo, player->mo->angle-ANGLE_90, spawndist), z, MT_NIGHTSPARKLE); if (!P_MobjWasRemoved(secondmobj)) { - secondmobj->destscale = player->mo->scale; P_SetTarget(&secondmobj->target, player->mo); - P_SetScale(secondmobj, player->mo->scale); - + P_SetScale(secondmobj, player->mo->scale, true); // Superloop turns sparkles red if (player->powers[pw_nights_superloop]) P_SetMobjState(secondmobj, mobjinfo[MT_NIGHTSPARKLE].seestate); @@ -7441,7 +7472,7 @@ static void P_NiGHTSMovement(player_t *player) { helpermobj->fuse = player->mo->fuse = leveltime; P_SetTarget(&helpermobj->target, player->mo); - P_SetScale(helpermobj, player->mo->scale); + P_SetScale(helpermobj, player->mo->scale, false); } } @@ -7641,8 +7672,7 @@ static void P_NiGHTSMovement(player_t *player) water->flags2 |= MF2_OBJECTFLIP; water->eflags |= MFE_VERTICALFLIP; } - water->destscale = player->mo->scale; - P_SetScale(water, player->mo->scale); + P_SetScale(water, player->mo->scale, true); } } @@ -7885,8 +7915,7 @@ void P_ElementalFire(player_t *player, boolean cropcircle) P_SetTarget(&flame->target, player->mo); flame->angle = travelangle + i*(ANGLE_MAX/numangles); flame->fuse = TICRATE*7; // takes about an extra second to hit the ground - flame->destscale = player->mo->scale; - P_SetScale(flame, player->mo->scale); + P_SetScale(flame, player->mo->scale, true); if (!(player->mo->flags2 & MF2_OBJECTFLIP) != !(player->powers[pw_gravityboots])) // take gravity boots into account flame->flags2 |= MF2_OBJECTFLIP; flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); @@ -7923,8 +7952,7 @@ void P_ElementalFire(player_t *player, boolean cropcircle) P_SetTarget(&flame->target, player->mo); flame->angle = travelangle; flame->fuse = TICRATE*6; - flame->destscale = player->mo->scale; - P_SetScale(flame, player->mo->scale); + P_SetScale(flame, player->mo->scale, true); if (!(player->mo->flags2 & MF2_OBJECTFLIP) != !(player->powers[pw_gravityboots])) // take gravity boots into account flame->flags2 |= MF2_OBJECTFLIP; flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); @@ -7972,8 +8000,7 @@ void P_SpawnSkidDust(player_t *player, fixed_t radius, boolean sound) } particle->tics = 10; - particle->destscale = (2*mo->scale)/3; - P_SetScale(particle, particle->destscale); + P_SetScale(particle, (2*mo->scale)/3, true); P_SetObjectMomZ(particle, FRACUNIT, false); if (mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) // overrides fire version @@ -8168,7 +8195,7 @@ void P_MovePlayer(player_t *player) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -8562,8 +8589,7 @@ void P_MovePlayer(player_t *player) water->flags2 |= MF2_OBJECTFLIP; water->eflags |= MFE_VERTICALFLIP; } - water->destscale = player->mo->scale; - P_SetScale(water, player->mo->scale); + P_SetScale(water, player->mo->scale, true); } } @@ -8774,32 +8800,19 @@ void P_MovePlayer(player_t *player) && player->panim == PA_IDLE && !(player->powers[pw_carry])) P_DoTeeter(player); - // Check for fire and shield buttons - if (!player->exiting && !(player->pflags & PF_STASIS)) + // Toss a flag + if (G_GametypeHasTeams() && (cmd->buttons & BT_TOSSFLAG) && !(player->powers[pw_super]) && !(player->tossdelay)) { - // Check for fire buttons - P_DoFiring(player, cmd); - - // Release the shield button - if (!(cmd->buttons & BT_SHIELD)) - player->pflags &= ~PF_SHIELDDOWN; - - // Shield button behavior - // Check P_PlayerShieldThink for actual shields! - else if (!(player->pflags & PF_SHIELDDOWN)) - { - // Transform into super if we can! - if (P_SuperReady(player, true)) - P_DoSuperTransformation(player, false); - - // Detransform from super if we can! - else if (P_SuperReady(player, false)) - P_DoSuperDetransformation(player); - - player->pflags |= PF_SHIELDDOWN; - } + if (!(player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) + P_PlayerEmeraldBurst(player, true); // Toss emeralds + else + P_PlayerFlagBurst(player, true); } + // check for fire + if (!player->exiting) + P_DoFiring(player, cmd); + { boolean atspinheight = false; fixed_t oldheight = player->mo->height; @@ -8817,6 +8830,8 @@ void P_MovePlayer(player_t *player) player->mo->height = P_GetPlayerSpinHeight(player); atspinheight = true; } + else if (player->powers[pw_carry] == CR_PLAYER || player->powers[pw_carry] == CR_PTERABYTE) // You're slightly shorter while being carried + player->mo->height = FixedDiv(P_GetPlayerHeight(player), FixedDiv(14*FRACUNIT,10*FRACUNIT)); else player->mo->height = P_GetPlayerHeight(player); @@ -9147,7 +9162,7 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (think->removing) continue; mo = (mobj_t *)think; @@ -9245,7 +9260,7 @@ mobj_t *P_LookForFocusTarget(player_t *player, mobj_t *exclude, SINT8 direction, for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (think->removing) continue; mo = (mobj_t *)think; @@ -9364,7 +9379,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (think->removing) continue; mo = (mobj_t *)think; @@ -9510,7 +9525,7 @@ void P_FindEmerald(void) // to find all emeralds for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -9813,9 +9828,10 @@ static CV_PossibleValue_t CV_CamSpeed[] = {{0, "MIN"}, {1*FRACUNIT, "MAX"}, {0, static CV_PossibleValue_t rotation_cons_t[] = {{1, "MIN"}, {25, "MAX"}, {0, NULL}}; static CV_PossibleValue_t CV_CamRotate[] = {{-720, "MIN"}, {720, "MAX"}, {0, NULL}}; static CV_PossibleValue_t multiplier_cons_t[] = {{0, "MIN"}, {3*FRACUNIT, "MAX"}, {0, NULL}}; +static CV_PossibleValue_t campos_cons_t[] = { {INT32_MIN, "MIN"}, {INT32_MAX, "MAX"}, {0, NULL} }; -consvar_t cv_cam_dist = CVAR_INIT ("cam_curdist", "160", CV_FLOAT|CV_ALLOWLUA, NULL, NULL); -consvar_t cv_cam_height = CVAR_INIT ("cam_curheight", "25", CV_FLOAT|CV_ALLOWLUA, NULL, NULL); +consvar_t cv_cam_dist = CVAR_INIT ("cam_curdist", "160", CV_FLOAT|CV_ALLOWLUA, campos_cons_t, NULL); +consvar_t cv_cam_height = CVAR_INIT ("cam_curheight", "25", CV_FLOAT|CV_ALLOWLUA, campos_cons_t, NULL); consvar_t cv_cam_still = CVAR_INIT ("cam_still", "Off", CV_ALLOWLUA, CV_OnOff, NULL); consvar_t cv_cam_speed = CVAR_INIT ("cam_speed", "0.3", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, CV_CamSpeed, NULL); consvar_t cv_cam_rotate = CVAR_INIT ("cam_rotate", "0", CV_CALL|CV_NOINIT|CV_ALLOWLUA, CV_CamRotate, CV_CamRotate_OnChange); @@ -9823,8 +9839,8 @@ consvar_t cv_cam_rotspeed = CVAR_INIT ("cam_rotspeed", "10", CV_SAVE|CV_ALLOWLUA consvar_t cv_cam_turnmultiplier = CVAR_INIT ("cam_turnmultiplier", "0.75", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, multiplier_cons_t, NULL); consvar_t cv_cam_orbit = CVAR_INIT ("cam_orbit", "Off", CV_SAVE|CV_ALLOWLUA, CV_OnOff, NULL); consvar_t cv_cam_adjust = CVAR_INIT ("cam_adjust", "On", CV_SAVE|CV_ALLOWLUA, CV_OnOff, NULL); -consvar_t cv_cam2_dist = CVAR_INIT ("cam2_curdist", "160", CV_FLOAT|CV_ALLOWLUA, NULL, NULL); -consvar_t cv_cam2_height = CVAR_INIT ("cam2_curheight", "25", CV_FLOAT|CV_ALLOWLUA, NULL, NULL); +consvar_t cv_cam2_dist = CVAR_INIT ("cam2_curdist", "160", CV_FLOAT|CV_ALLOWLUA, campos_cons_t, NULL); +consvar_t cv_cam2_height = CVAR_INIT ("cam2_curheight", "25", CV_FLOAT|CV_ALLOWLUA, campos_cons_t, NULL); consvar_t cv_cam2_still = CVAR_INIT ("cam2_still", "Off", CV_ALLOWLUA, CV_OnOff, NULL); consvar_t cv_cam2_speed = CVAR_INIT ("cam2_speed", "0.3", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, CV_CamSpeed, NULL); consvar_t cv_cam2_rotate = CVAR_INIT ("cam2_rotate", "0", CV_CALL|CV_NOINIT|CV_ALLOWLUA, CV_CamRotate, CV_CamRotate2_OnChange); @@ -9836,23 +9852,23 @@ consvar_t cv_cam2_adjust = CVAR_INIT ("cam2_adjust", "On", CV_SAVE|CV_ALLOWLUA, // [standard vs simple][p1 or p2] consvar_t cv_cam_savedist[2][2] = { { // standard - CVAR_INIT ("cam_dist", "192", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCamDist), - CVAR_INIT ("cam2_dist", "192", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCam2Dist), + CVAR_INIT ("cam_dist", "192", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, campos_cons_t, CV_UpdateCamDist), + CVAR_INIT ("cam2_dist", "192", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, campos_cons_t, CV_UpdateCam2Dist), }, { // simple - CVAR_INIT ("cam_simpledist", "256", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCamDist), - CVAR_INIT ("cam2_simpledist", "256", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCam2Dist), + CVAR_INIT ("cam_simpledist", "256", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, campos_cons_t, CV_UpdateCamDist), + CVAR_INIT ("cam2_simpledist", "256", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, campos_cons_t, CV_UpdateCam2Dist), } }; consvar_t cv_cam_saveheight[2][2] = { { // standard - CVAR_INIT ("cam_height", "40", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCamDist), - CVAR_INIT ("cam2_height", "40", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCam2Dist), + CVAR_INIT ("cam_height", "40", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, campos_cons_t, CV_UpdateCamDist), + CVAR_INIT ("cam2_height", "40", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, campos_cons_t, CV_UpdateCam2Dist), }, { // simple - CVAR_INIT ("cam_simpleheight", "60", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCamDist), - CVAR_INIT ("cam2_simpleheight", "60", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, NULL, CV_UpdateCam2Dist), + CVAR_INIT ("cam_simpleheight", "60", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, campos_cons_t, CV_UpdateCamDist), + CVAR_INIT ("cam2_simpleheight", "60", CV_FLOAT|CV_SAVE|CV_CALL|CV_ALLOWLUA, campos_cons_t, CV_UpdateCam2Dist), } }; @@ -10910,7 +10926,7 @@ static mobj_t *P_GetAxis(INT32 num) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mobj = (mobj_t *)th; @@ -10995,8 +11011,7 @@ static void P_SpawnSparks(mobj_t *mo, angle_t maindir) spark->momz = mo->momz + r3; P_Thrust(spark, R_PointToAngle2(mo->x, mo->y, spark->x, spark->y), 8*FRACUNIT); - P_SetScale(spark, FRACUNIT/4); - spark->destscale = spark->scale; + P_SetScale(spark, FRACUNIT/4, true); spark->fuse = TICRATE/3; } @@ -11101,7 +11116,8 @@ static void P_MinecartThink(player_t *player) fa = (minecart->angle >> ANGLETOFINESHIFT) & FINEMASK; if (!P_TryMove(minecart, minecart->x + FINECOSINE(fa), minecart->y + FINESINE(fa), true)) { - P_KillMobj(minecart, NULL, NULL, 0); + if (!P_MobjWasRemoved(minecart)) + P_KillMobj(minecart, NULL, NULL, 0); return; } @@ -11302,7 +11318,7 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails) fixed_t backwards = -1*FRACUNIT; boolean doswim = (player->panim == PA_ABILITY && (player->mo->eflags & MFE_UNDERWATER)); boolean doroll = (player->panim == PA_ROLL || (player->panim == PA_JUMP && !(player->charflags & SF_NOJUMPSPIN)) || doswim); - angle_t rollangle; + angle_t rollangle = 0; boolean panimchange; INT32 ticnum = 0; statenum_t chosenstate; @@ -11429,10 +11445,10 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails) } else { - if (tails->state != states+chosenstate) + if (tails->state != &states[chosenstate]) { if (states[chosenstate].sprite == SPR_PLAY) - tails->sprite2 = P_GetSkinSprite2(((skin_t *)tails->skin), (states[chosenstate].frame & FF_FRAMEMASK), player); + tails->sprite2 = P_GetSkinSprite2(((skin_t *)tails->skin), P_GetStateSprite2(&states[chosenstate]), player); P_SetMobjState(tails, chosenstate); } } @@ -11467,8 +11483,9 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails) tails->threshold = player->mo->z; tails->movecount = player->panim; tails->angle = horizangle; - P_SetScale(tails, player->mo->scale); + P_SetScale(tails, player->mo->scale, false); tails->destscale = player->mo->destscale; + tails->old_scale = player->mo->old_scale; tails->radius = player->mo->radius; tails->height = player->mo->height; zoffs = FixedMul(zoffs, tails->scale); @@ -11535,6 +11552,9 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume) return; } + if (player->skidtime) // Rotate during metal sonic's new skid animation + angle += ANGLE_90; + if (underwater) // No fume underwater; spawn bubbles instead! { fume->movedir += FixedAngle(FixedDiv(2 * player->speed, 3 * mo->scale)); @@ -11559,7 +11579,9 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume) y = mo->y + radiusY + FixedMul(offsetH, factorY); z = mo->z + heightoffset + offsetV; bubble = P_SpawnMobj(x, y, z, MT_SMALLBUBBLE); - bubble->scale = mo->scale >> 1; + P_SetScale(bubble, mo->scale/2, true); + bubble->destscale = mo->scale; + bubble->scalespeed = FixedMul(bubble->scalespeed, mo->scale); P_SetTarget(&bubble->dontdrawforviewmobj, mo); // Hide the bubble in first-person } @@ -11580,7 +11602,7 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume) if (stat == fume->info->spawnstate) // If currently inivisble, activate! { P_SetMobjState(fume, (stat = fume->info->seestate)); - P_SetScale(fume, mo->scale); + P_SetScale(fume, mo->scale, false); resetinterp = true; } @@ -11595,7 +11617,7 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume) if (dashmode == DASHMODE_THRESHOLD && dashmode > (tic_t)fume->movecount) // If just about to enter dashmode, play the startup animation again { P_SetMobjState(fume, (stat = fume->info->seestate)); - P_SetScale(fume, mo->scale << 1); + P_SetScale(fume, 2*mo->scale, true); } fume->flags2 = (fume->flags2 & ~MF2_DONTDRAW) | (mo->flags2 & MF2_DONTDRAW); fume->destscale = (mo->scale + FixedDiv(player->speed, player->normalspeed)) / (underwater ? 6 : 3); @@ -11906,7 +11928,7 @@ void P_PlayerThink(player_t *player) if (((gametyperules & GTR_FRIENDLY) && cv_exitmove.value) && !G_EnoughPlayersFinished()) player->exiting = 0; else - P_DoPlayerExit(player); + P_DoPlayerExit(player, false); } // check water content, set stuff in mobj @@ -11955,7 +11977,7 @@ void P_PlayerThink(player_t *player) } // Synchronizes the "real" amount of time spent in the level. - if (!player->exiting && !stoppedclock) + if (!player->exiting && !(player->pflags & PF_FINISHED) && !stoppedclock) { if (gametyperules & GTR_RACE) { @@ -11989,7 +12011,7 @@ void P_PlayerThink(player_t *player) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -12084,7 +12106,7 @@ void P_PlayerThink(player_t *player) // deez New User eXperiences. { angle_t oldang = player->drawangle, diff = 0; - UINT8 factor; + UINT8 factor = 0; // Directionchar! // Camera angle stuff. if (player->exiting // no control, no modification @@ -12130,6 +12152,10 @@ void P_PlayerThink(player_t *player) case CR_DUSTDEVIL: player->drawangle += ANG20; break; + case CR_FAN: + if (player->pflags & PF_ANALOGMODE) // Don't impact drawangle in any special way when on a fan + player->drawangle = player->mo->angle; + break; /* -- in case we wanted to have the camera freely movable during zoom tubes case CR_ZOOMTUBE:*/ case CR_ROPEHANG: @@ -12450,13 +12476,13 @@ void P_PlayerThink(player_t *player) if (player->texttimer) { --player->texttimer; - if (!player->texttimer && !player->exiting && player->textvar >= 4) + if (!player->texttimer && !player->exiting && (player->textvar == NTV_NONE || player->textvar == NTV_BONUSTIMEEND)) { player->texttimer = 4*TICRATE; - player->textvar = 2; // GET n RINGS! + player->textvar = NTV_GETSPHERES; // GET n SPHERES/CHIPS! - if (player->capsule && player->capsule->health != player->capsule->spawnpoint->angle) - player->textvar++; // GET n MORE RINGS! + if (!P_MobjWasRemoved(player->capsule) && player->capsule->health != player->capsule->spawnpoint->args[1]) + player->textvar = NTV_GETMORESPHERES; // GET n MORE SPHERES/CHIPS! } } @@ -12824,9 +12850,9 @@ void P_PlayerAfterThink(player_t *player) else { if (tails->player) - P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->player->drawangle, 4*FRACUNIT), tails->y + P_ReturnThrustY(tails, tails->player->drawangle, 4*FRACUNIT), true); + P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->player->drawangle, 4*tails->scale), tails->y + P_ReturnThrustY(tails, tails->player->drawangle, 4*tails->scale), true); else - P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->angle, 4*FRACUNIT), tails->y + P_ReturnThrustY(tails, tails->angle, 4*FRACUNIT), true); + P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->angle, 4*tails->scale), tails->y + P_ReturnThrustY(tails, tails->angle, 4*tails->scale), true); player->mo->momx = tails->momx; player->mo->momy = tails->momy; player->mo->momz = tails->momz; @@ -12840,7 +12866,7 @@ void P_PlayerAfterThink(player_t *player) P_SetPlayerAngle(player, player->mo->angle); } - if (P_AproxDistance(player->mo->x - tails->x, player->mo->y - tails->y) > player->mo->radius) + if (P_AproxDistance(player->mo->x - tails->x, player->mo->y - tails->y) > tails->radius) player->powers[pw_carry] = CR_NONE; if (player->powers[pw_carry] == CR_PLAYER) @@ -13061,7 +13087,7 @@ void P_PlayerAfterThink(player_t *player) player->mo->momy = ptera->momy; player->mo->momz = ptera->momz; - if (P_AproxDistance(player->mo->x - ptera->x - ptera->watertop, player->mo->y - ptera->y - ptera->waterbottom) > player->mo->radius) + if (P_AproxDistance(player->mo->x - ptera->x - ptera->watertop, player->mo->y - ptera->y - ptera->waterbottom) > ptera->radius) goto dropoff; ptera->watertop >>= 1; @@ -13194,7 +13220,7 @@ void P_ForceLocalAngle(player_t *player, angle_t angle) boolean P_PlayerFullbright(player_t *player) { return (player->powers[pw_super] - || ((player->powers[pw_carry] == CR_NIGHTSMODE && (((skin_t *)player->mo->skin)->flags & (SF_SUPER|SF_NONIGHTSSUPER)) == SF_SUPER) // Super colours? Super bright! + || ((player->powers[pw_carry] == CR_NIGHTSMODE && (player->charflags & (SF_SUPER|SF_NONIGHTSSUPER)) == SF_SUPER) // Super colours? Super bright! && (player->exiting || !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1] && player->mo->state < &states[S_PLAY_NIGHTS_TRANS6])))); // Note the < instead of <= diff --git a/src/r_bbox.c b/src/r_bbox.c index 8ccad2bb58186098810f299405fc0f4d23fa9b5a..93fa2dca28c4a1f923c69ff4f44958c7e583310c 100644 --- a/src/r_bbox.c +++ b/src/r_bbox.c @@ -275,7 +275,7 @@ boolean R_ThingBoundingBoxVisible(mobj_t *thing) switch (thing->type) { default: - // First person / awayviewmobj -- rendering a bbox + // First person / awayviewmobj -- rendering a bbox // too close to the viewpoint causes anomalies // and these are exactly on the viewpoint! if (thing != r_viewmobj) diff --git a/src/r_bsp.c b/src/r_bsp.c index 918dc40b0f721a73badb9549d8e656a98fedf54c..ad27b9bf8162a39bef6a5ddfa75c3e681c5632ca 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -230,6 +230,18 @@ static INT32 R_DoorClosed(void) && (backsector->floorheight <= frontsector->floorheight || curline->sidedef->bottomtexture); } +static UINT8 R_FloorLightLevel(sector_t *sector, INT16 base_lightlevel) +{ + return max(0, min(255, sector->floorlightlevel + + ((sector->floorlightabsolute) ? 0 : base_lightlevel))); +} + +static UINT8 R_CeilingLightLevel(sector_t *sector, INT16 base_lightlevel) +{ + return max(0, min(255, sector->ceilinglightlevel + + ((sector->ceilinglightabsolute) ? 0 : base_lightlevel))); +} + // // If player's view height is underneath fake floor, lower the // drawn ceiling to be just under the floor height, and replace @@ -312,11 +324,11 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, tempsec->lightlevel = s->lightlevel; if (floorlightlevel) - *floorlightlevel = s->floorlightsec == -1 ? (s->floorlightabsolute ? s->floorlightlevel : max(0, min(255, s->lightlevel + s->floorlightlevel))) + *floorlightlevel = s->floorlightsec == -1 ? (s->floorlightabsolute ? s->floorlightlevel : max(0, min(255, s->lightlevel + s->floorlightlevel))) : sectors[s->floorlightsec].lightlevel; if (ceilinglightlevel) - *ceilinglightlevel = s->ceilinglightsec == -1 ? (s->ceilinglightabsolute ? s->ceilinglightlevel : max(0, min(255, s->lightlevel + s->ceilinglightlevel))) + *ceilinglightlevel = s->ceilinglightsec == -1 ? (s->ceilinglightabsolute ? s->ceilinglightlevel : max(0, min(255, s->lightlevel + s->ceilinglightlevel))) : sectors[s->ceilinglightsec].lightlevel; } else if (heightsec != -1 && viewz >= sectors[heightsec].ceilingheight @@ -356,11 +368,11 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, tempsec->lightlevel = s->lightlevel; if (floorlightlevel) - *floorlightlevel = s->floorlightsec == -1 ? (s->floorlightabsolute ? s->floorlightlevel : max(0, min(255, s->lightlevel + s->floorlightlevel))) + *floorlightlevel = s->floorlightsec == -1 ? (s->floorlightabsolute ? s->floorlightlevel : max(0, min(255, s->lightlevel + s->floorlightlevel))) : sectors[s->floorlightsec].lightlevel; if (ceilinglightlevel) - *ceilinglightlevel = s->ceilinglightsec == -1 ? (s->ceilinglightabsolute ? s->ceilinglightlevel : max(0, min(255, s->lightlevel + s->ceilinglightlevel))) + *ceilinglightlevel = s->ceilinglightsec == -1 ? (s->ceilinglightabsolute ? s->ceilinglightlevel : max(0, min(255, s->lightlevel + s->ceilinglightlevel))) : sectors[s->ceilinglightsec].lightlevel; } sec = tempsec; @@ -968,11 +980,10 @@ static void R_Subsector(size_t num) && ((viewz < heightcheck && (rover->fofflags & FOF_BOTHPLANES || !(rover->fofflags & FOF_INVERTPLANES))) || (viewz > heightcheck && (rover->fofflags & FOF_BOTHPLANES || rover->fofflags & FOF_INVERTPLANES)))) { - light = R_GetPlaneLight(frontsector, planecenterz, - viewz < heightcheck); + light = R_GetPlaneLight(frontsector, planecenterz, viewz < heightcheck); ffloor[numffloors].plane = R_FindPlane(rover->master->frontsector, *rover->bottomheight, *rover->bottompic, - *frontsector->lightlist[light].lightlevel, *rover->bottomxoffs, *rover->bottomyoffs, + R_FloorLightLevel(rover->master->frontsector, *frontsector->lightlist[light].lightlevel), *rover->bottomxoffs, *rover->bottomyoffs, *rover->bottomxscale, *rover->bottomyscale, *rover->bottomangle, *frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->b_slope, NULL); @@ -1002,7 +1013,7 @@ static void R_Subsector(size_t num) light = R_GetPlaneLight(frontsector, planecenterz, viewz < heightcheck); ffloor[numffloors].plane = R_FindPlane(rover->master->frontsector, *rover->topheight, *rover->toppic, - *frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs, + R_CeilingLightLevel(rover->master->frontsector, *frontsector->lightlist[light].lightlevel), *rover->topxoffs, *rover->topyoffs, *rover->topxscale, *rover->topyscale, *rover->topangle, *frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->t_slope, NULL); @@ -1382,10 +1393,9 @@ void R_RenderPortalHorizonLine(sector_t *sector) || frontsector->ceilingpic == skyflatnum || (frontsector->heightsec != -1 && sectors[frontsector->heightsec].floorpic == skyflatnum)) { - ceilingplane = R_FindPlane(frontsector, frontsector->ceilingheight, frontsector->ceilingpic, - ceilinglightlevel, frontsector->ceilingxoffset, frontsector->ceilingxscale, frontsector->ceilingyscale, - frontsector->ceilingyoffset, frontsector->ceilingangle, - ceilingcolormap, NULL, NULL, NULL, NULL); + ceilingplane = R_FindPlane(frontsector, frontsector->ceilingheight, frontsector->ceilingpic, ceilinglightlevel, + frontsector->ceilingxoffset, frontsector->ceilingyoffset, frontsector->ceilingxscale, frontsector->ceilingyscale, + frontsector->ceilingangle, ceilingcolormap, NULL, NULL, NULL, NULL); } else ceilingplane = NULL; diff --git a/src/r_data.c b/src/r_data.c index 0a13d27dbaf55f9e9092adeb0de4635523c96606..32faa07a8fb40370008218f2c4fa9ec3a4d3737b 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -31,6 +31,10 @@ #include "byteptr.h" #include "dehacked.h" +#ifdef HWRENDER +#include "hardware/hw_glob.h" // HWR_ClearLightTables +#endif + // // Graphics. // SRB2 graphics for walls and sprites @@ -50,10 +54,6 @@ lighttable_t *fadecolormap; // for debugging/info purposes size_t flatmemory, spritememory, texturememory; -// highcolor stuff -INT16 color8to16[256]; // remap color index to highcolor rgb value -INT16 *hicolormaps; // test a 32k colormap remaps high -> high - // Blends two pixels together, using the equation // that matches the specified alpha style. UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha) @@ -846,6 +846,15 @@ void R_GenerateLightTable(extracolormap_t *extra_colormap, boolean uselookup) } } +void R_UpdateLightTable(extracolormap_t *extra_colormap, boolean uselookup) +{ + R_GenerateLightTable(extra_colormap, uselookup); + +#ifdef HWRENDER + extra_colormap->gl_lighttable.needs_update = true; +#endif +} + extracolormap_t *R_CreateColormapFromLinedef(char *p1, char *p2, char *p3) { // default values @@ -1170,40 +1179,6 @@ const char *R_NameForColormap(extracolormap_t *extra_colormap) } #endif -// -// build a table for quick conversion from 8bpp to 15bpp -// - -// -// added "static inline" keywords, linking with the debug version -// of allegro, it have a makecol15 function of it's own, now -// with "static inline" keywords,it sloves this problem ;) -// -FUNCMATH static inline int makecol15(int r, int g, int b) -{ - return (((r >> 3) << 10) | ((g >> 3) << 5) | ((b >> 3))); -} - -static void R_Init8to16(void) -{ - UINT8 *palette; - int i; - - palette = W_CacheLumpName("PLAYPAL",PU_CACHE); - - for (i = 0; i < 256; i++) - { - // PLAYPAL uses 8 bit values - color8to16[i] = (INT16)makecol15(palette[0], palette[1], palette[2]); - palette += 3; - } - - // test a big colormap - hicolormaps = Z_Malloc(16384*sizeof(*hicolormaps), PU_STATIC, NULL); - for (i = 0; i < 16384; i++) - hicolormaps[i] = (INT16)(i<<1); -} - // // R_InitData // @@ -1212,12 +1187,6 @@ static void R_Init8to16(void) // void R_InitData(void) { - if (highcolor) - { - CONS_Printf("InitHighColor...\n"); - R_Init8to16(); - } - CONS_Printf("R_LoadParsedTranslations()...\n"); R_LoadParsedTranslations(); diff --git a/src/r_data.h b/src/r_data.h index 364f85b6d4b0cbdd09448144f0546db9bc661bfc..64abf6d83637ed8f54c7449f621ac52eb6aa9113 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -36,9 +36,6 @@ UINT8 ASTBlendPaletteIndexes(UINT8 background, UINT8 foreground, int style, UINT extern INT32 ASTTextureBlendingThreshold[2]; -extern INT16 color8to16[256]; // remap color index to highcolor -extern INT16 *hicolormaps; // remap high colors to high colors.. - extern CV_PossibleValue_t Color_cons_t[]; // I/O, setting up the stuff. @@ -93,6 +90,7 @@ typedef enum } textmapcolormapflags_t; void R_GenerateLightTable(extracolormap_t *extra_colormap, boolean uselookup); +void R_UpdateLightTable(extracolormap_t *extra_colormap, boolean uselookup); lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap); extracolormap_t * R_CreateColormapFromLinedef(char *p1, char *p2, char *p3); extracolormap_t* R_CreateColormap(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags); diff --git a/src/r_defs.h b/src/r_defs.h index d556b540f8a68794986e04da72c58e6d7af8f9a2..eac3e2d1f38752f9b3b2002f1a7ab3e3fe15975e 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -25,6 +25,10 @@ #include "screen.h" // MAXVIDWIDTH, MAXVIDHEIGHT +#ifdef HWRENDER +#include "m_aatree.h" +#endif + #include "taglist.h" // @@ -56,6 +60,8 @@ typedef UINT8 lighttable_t; #define CMF_FADEFULLBRIGHTSPRITES 1 #define CMF_FOG 4 +#define TEXTURE_255_IS_TRANSPARENT + // ExtraColormap type. Use for extra_colormaps from now on. typedef struct extracolormap_s { @@ -69,6 +75,14 @@ typedef struct extracolormap_s lighttable_t *colormap; +#ifdef HWRENDER + struct { + UINT32 id; // The id of the hardware lighttable. Zero means it does not exist yet. + RGBA_t *data; // The texture data of the hardware lighttable. + boolean needs_update; // If the colormap changed recently or not. + } gl_lighttable; +#endif + #ifdef EXTRACOLORMAPLUMPS lumpnum_t lump; // for colormap lump matching, init to LUMPERROR char lumpname[9]; // for netsyncing @@ -231,9 +245,8 @@ typedef struct sectorportal_s struct sector_s *sector; struct mobj_s *mobj; }; - struct { - fixed_t x, y; - } origin; + struct sector_s *target; + boolean ceiling; } sectorportal_t; typedef struct ffloor_s @@ -349,7 +362,7 @@ typedef struct pslope_s double dzdelta; - boolean moved : 1; + boolean moved; UINT8 flags; // Slope options } pslope_t; @@ -396,6 +409,8 @@ typedef enum SSF_ROPEHANG = 1<<18, SSF_JUMPFLIP = 1<<19, SSF_GRAVITYOVERRIDE = 1<<20, // combine with MSF_GRAVITYFLIP + SSF_NOPHYSICSFLOOR = 1<<21, + SSF_NOPHYSICSCEILING = 1<<22, } sectorspecialflags_t; typedef enum @@ -601,6 +616,8 @@ typedef struct line_s INT16 callcount; // no. of calls left before triggering, for the "X calls" linedef specials, defaults to 0 UINT32 secportal; // transferred sector portal + + struct pslope_s *midtexslope; } line_t; typedef struct @@ -618,6 +635,11 @@ typedef struct fixed_t scalex_top, scalex_mid, scalex_bottom; fixed_t scaley_top, scaley_mid, scaley_bottom; + // per-wall lighting for UDMF + // TODO: implement per-texture lighting + INT16 light, light_top, light_mid, light_bottom; + boolean lightabsolute, lightabsolute_top, lightabsolute_mid, lightabsolute_bottom; + // Texture indices. // We do not maintain names here. INT32 toptexture, bottomtexture, midtexture; @@ -742,9 +764,6 @@ typedef struct seg_s lightmap_t *lightmaps; // for static lightmap #endif - // Why slow things down by calculating lightlists for every thick side? - size_t numlights; - r_lightlist_t *rlights; polyobj_t *polyseg; boolean dontrenderme; boolean glseg; @@ -828,6 +847,7 @@ typedef struct drawseg_s INT16 *sprtopclip; INT16 *sprbottomclip; fixed_t *maskedtexturecol; + fixed_t *maskedtextureheight; // For handling sloped midtextures fixed_t *invscale; struct visplane_s *ffloorplanes[MAXFFLOORS]; @@ -839,20 +859,9 @@ typedef struct drawseg_s UINT8 portalpass; // if > 0 and <= portalrender, do not affect sprite clipping - fixed_t maskedtextureheight[MAXVIDWIDTH]; // For handling sloped midtextures - vertex_t leftpos, rightpos; // Used for rendering FOF walls with slopes } drawseg_t; -typedef enum -{ - PALETTE = 0, // 1 byte is the index in the doom palette (as usual) - INTENSITY = 1, // 1 byte intensity - INTENSITY_ALPHA = 2, // 2 byte: alpha then intensity - RGB24 = 3, // 24 bit rgb - RGBA32 = 4, // 32 bit rgba -} pic_mode_t; - #ifdef ROTSPRITE typedef struct { @@ -978,6 +987,8 @@ typedef struct #endif } spriteframe_t; +#define MAXFRAMENUM 256 + // // A sprite definition: a number of animation frames. // diff --git a/src/r_draw.c b/src/r_draw.c index 513a54f4aefff9ac0f57b916e6e0c12d7286e4c3..906398ec4972e53565cdcfa04deb51557956d39c 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -19,7 +19,6 @@ #include "doomstat.h" #include "r_local.h" #include "r_translation.h" -#include "st_stuff.h" // need ST_HEIGHT #include "i_video.h" #include "v_video.h" #include "m_misc.h" @@ -40,23 +39,6 @@ */ INT32 viewwidth, scaledviewwidth, viewheight, viewwindowx, viewwindowy; -/** \brief pointer to the start of each line of the screen, -*/ -UINT8 *ylookup[MAXVIDHEIGHT*4]; - -/** \brief pointer to the start of each line of the screen, for view1 (splitscreen) -*/ -UINT8 *ylookup1[MAXVIDHEIGHT*4]; - -/** \brief pointer to the start of each line of the screen, for view2 (splitscreen) -*/ -UINT8 *ylookup2[MAXVIDHEIGHT*4]; - -/** \brief x byte offset for columns inside the viewwindow, - so the first column starts at (SCRWIDTH - VIEWWIDTH)/2 -*/ -INT32 columnofs[MAXVIDWIDTH*4]; - UINT8 *topleft; // ========================================================================= @@ -67,8 +49,6 @@ lighttable_t *dc_colormap; INT32 dc_x = 0, dc_yl = 0, dc_yh = 0; fixed_t dc_iscale, dc_texturemid; -UINT8 dc_hires; // under MSVC boolean is a byte, while on other systems, it a bit, - // soo lets make it a byte on all system for the ASM code UINT8 *dc_source; // ----------------------- @@ -93,7 +73,7 @@ UINT8 *dc_transmap; // one of the translucency tables UINT8 *dc_translation; struct r_lightlist_s *dc_lightlist = NULL; -INT32 dc_numlights = 0, dc_maxlights, dc_texheight; +INT32 dc_numlights = 0, dc_maxlights, dc_texheight, dc_postlength; // ========================================================================= // SPAN DRAWING CODE STUFF @@ -677,7 +657,7 @@ UINT16 R_GetSuperColorByName(const char *name) void R_InitViewBuffer(INT32 width, INT32 height) { - INT32 i, bytesperpixel = vid.bpp; + INT32 bytesperpixel = vid.bpp; if (width > MAXVIDWIDTH) width = MAXVIDWIDTH; @@ -689,118 +669,13 @@ void R_InitViewBuffer(INT32 width, INT32 height) // Handle resize, e.g. smaller view windows with border and/or status bar. viewwindowx = (vid.width - width) >> 1; - // Column offset for those columns of the view window, but relative to the entire screen - for (i = 0; i < width; i++) - columnofs[i] = (viewwindowx + i) * bytesperpixel; - // Same with base row offset. if (width == vid.width) viewwindowy = 0; else viewwindowy = (vid.height - height) >> 1; - - // Precalculate all row offsets. - for (i = 0; i < height; i++) - { - ylookup[i] = ylookup1[i] = screens[0] + (i+viewwindowy)*vid.width*bytesperpixel; - ylookup2[i] = screens[0] + (i+(vid.height>>1))*vid.width*bytesperpixel; // for splitscreen - } } -/** \brief viewborder patches lump numbers -*/ -lumpnum_t viewborderlump[8]; - -/** \brief Store the lumpnumber of the viewborder patches -*/ - -void R_InitViewBorder(void) -{ - viewborderlump[BRDR_T] = W_GetNumForName("brdr_t"); - viewborderlump[BRDR_B] = W_GetNumForName("brdr_b"); - viewborderlump[BRDR_L] = W_GetNumForName("brdr_l"); - viewborderlump[BRDR_R] = W_GetNumForName("brdr_r"); - viewborderlump[BRDR_TL] = W_GetNumForName("brdr_tl"); - viewborderlump[BRDR_BL] = W_GetNumForName("brdr_bl"); - viewborderlump[BRDR_TR] = W_GetNumForName("brdr_tr"); - viewborderlump[BRDR_BR] = W_GetNumForName("brdr_br"); -} - -#if 0 -/** \brief R_FillBackScreen - - Fills the back screen with a pattern for variable screen sizes - Also draws a beveled edge. -*/ -void R_FillBackScreen(void) -{ - UINT8 *src, *dest; - patch_t *patch; - INT32 x, y, step, boff; - - // quickfix, don't cache lumps in both modes - if (rendermode != render_soft) - return; - - // draw pattern around the status bar too (when hires), - // so return only when in full-screen without status bar. - if (scaledviewwidth == vid.width && viewheight == vid.height) - return; - - src = scr_borderpatch; - dest = screens[1]; - - for (y = 0; y < vid.height; y++) - { - for (x = 0; x < vid.width/128; x++) - { - M_Memcpy (dest, src+((y&127)<<7), 128); - dest += 128; - } - - if (vid.width&127) - { - M_Memcpy(dest, src+((y&127)<<7), vid.width&127); - dest += (vid.width&127); - } - } - - // don't draw the borders when viewwidth is full vid.width. - if (scaledviewwidth == vid.width) - return; - - step = 8; - boff = 8; - - patch = W_CacheLumpNum(viewborderlump[BRDR_T], PU_CACHE); - for (x = 0; x < scaledviewwidth; x += step) - V_DrawPatch(viewwindowx + x, viewwindowy - boff, 1, patch); - - patch = W_CacheLumpNum(viewborderlump[BRDR_B], PU_CACHE); - for (x = 0; x < scaledviewwidth; x += step) - V_DrawPatch(viewwindowx + x, viewwindowy + viewheight, 1, patch); - - patch = W_CacheLumpNum(viewborderlump[BRDR_L], PU_CACHE); - for (y = 0; y < viewheight; y += step) - V_DrawPatch(viewwindowx - boff, viewwindowy + y, 1, patch); - - patch = W_CacheLumpNum(viewborderlump[BRDR_R],PU_CACHE); - for (y = 0; y < viewheight; y += step) - V_DrawPatch(viewwindowx + scaledviewwidth, viewwindowy + y, 1, - patch); - - // Draw beveled corners. - V_DrawPatch(viewwindowx - boff, viewwindowy - boff, 1, - W_CacheLumpNum(viewborderlump[BRDR_TL], PU_CACHE)); - V_DrawPatch(viewwindowx + scaledviewwidth, viewwindowy - boff, 1, - W_CacheLumpNum(viewborderlump[BRDR_TR], PU_CACHE)); - V_DrawPatch(viewwindowx - boff, viewwindowy + viewheight, 1, - W_CacheLumpNum(viewborderlump[BRDR_BL], PU_CACHE)); - V_DrawPatch(viewwindowx + scaledviewwidth, viewwindowy + viewheight, 1, - W_CacheLumpNum(viewborderlump[BRDR_BR], PU_CACHE)); -} -#endif - /** \brief The R_VideoErase function Copy a screen buffer. @@ -822,55 +697,6 @@ void R_VideoErase(size_t ofs, INT32 count) M_Memcpy(screens[0] + ofs, screens[1] + ofs, count); } -#if 0 -/** \brief The R_DrawViewBorder - - Draws the border around the view - for different size windows? -*/ -void R_DrawViewBorder(void) -{ - INT32 top, side, ofs; - - if (rendermode == render_none) - return; -#ifdef HWRENDER - if (rendermode != render_soft) - { - HWR_DrawViewBorder(0); - return; - } - else -#endif - -#ifdef DEBUG - fprintf(stderr,"RDVB: vidwidth %d vidheight %d scaledviewwidth %d viewheight %d\n", - vid.width, vid.height, scaledviewwidth, viewheight); -#endif - - if (scaledviewwidth == vid.width) - return; - - top = (vid.height - viewheight)>>1; - side = (vid.width - scaledviewwidth)>>1; - - // copy top and one line of left side - R_VideoErase(0, top*vid.width+side); - - // copy one line of right side and bottom - ofs = (viewheight+top)*vid.width - side; - R_VideoErase(ofs, top*vid.width + side); - - // copy sides using wraparound - ofs = top*vid.width + vid.width-side; - side <<= 1; - - // simpler using our VID_Blit routine - VID_BlitLinearScreen(screens[1] + ofs, screens[0] + ofs, side, viewheight - 1, - vid.width, vid.width); -} -#endif - // R_CalcTiltedLighting // Exactly what it says on the tin. I wish I wasn't too lazy to explain things properly. static INT32 tiltlighting[MAXVIDWIDTH]; @@ -912,11 +738,3 @@ static void R_CalcSlopeLight(void) #include "r_draw8.c" #include "r_draw8_npo2.c" - -// ========================================================================== -// INCLUDE 16bpp DRAWING CODE HERE -// ========================================================================== - -#ifdef HIGHCOLOR -#include "r_draw16.c" -#endif diff --git a/src/r_draw.h b/src/r_draw.h index 7eb001ebd360df404e57a5716d96aa73aa013219..d5c5b4e25d36ba375d365a2d13f0ba5fab19e3f3 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -19,10 +19,6 @@ // ------------------------------- // COMMON STUFF FOR 8bpp AND 16bpp // ------------------------------- -extern UINT8 *ylookup[MAXVIDHEIGHT*4]; -extern UINT8 *ylookup1[MAXVIDHEIGHT*4]; -extern UINT8 *ylookup2[MAXVIDHEIGHT*4]; -extern INT32 columnofs[MAXVIDWIDTH*4]; extern UINT8 *topleft; // ------------------------- @@ -32,7 +28,6 @@ extern UINT8 *topleft; extern lighttable_t *dc_colormap; extern INT32 dc_x, dc_yl, dc_yh; extern fixed_t dc_iscale, dc_texturemid; -extern UINT8 dc_hires; extern UINT8 *dc_source; // first pixel in a column @@ -46,8 +41,7 @@ extern UINT8 *dc_translation; extern struct r_lightlist_s *dc_lightlist; extern INT32 dc_numlights, dc_maxlights; -//Fix TUTIFRUTI -extern INT32 dc_texheight; +extern INT32 dc_texheight, dc_postlength; // ----------------------- // SPAN DRAWING CODE STUFF @@ -77,25 +71,6 @@ extern UINT32 nflatyshift; extern UINT32 nflatshiftup; extern UINT32 nflatmask; -/// \brief Top border -#define BRDR_T 0 -/// \brief Bottom border -#define BRDR_B 1 -/// \brief Left border -#define BRDR_L 2 -/// \brief Right border -#define BRDR_R 3 -/// \brief Topleft border -#define BRDR_TL 4 -/// \brief Topright border -#define BRDR_TR 5 -/// \brief Bottomleft border -#define BRDR_BL 6 -/// \brief Bottomright border -#define BRDR_BR 7 - -extern lumpnum_t viewborderlump[8]; - // ------------------------------------------------ // r_draw.c COMMON ROUTINES FOR BOTH 8bpp and 16bpp // ------------------------------------------------ @@ -169,17 +144,8 @@ boolean R_BlendLevelVisible(INT32 blendmode, INT32 alphalevel); extern boolean skincolor_modified[]; void R_InitViewBuffer(INT32 width, INT32 height); -void R_InitViewBorder(void); void R_VideoErase(size_t ofs, INT32 count); -// Rendering function. -#if 0 -void R_FillBackScreen(void); - -// If the view size is not full screen, draws a border around it. -void R_DrawViewBorder(void); -#endif - #define TRANSPARENTPIXEL 255 // ----------------- @@ -187,8 +153,12 @@ void R_DrawViewBorder(void); // ----------------- void R_DrawColumn_8(void); +void R_DrawColumnClamped_8(void); +void R_Draw2sMultiPatchColumn_8(void); void R_DrawShadeColumn_8(void); void R_DrawTranslucentColumn_8(void); +void R_DrawTranslucentColumnClamped_8(void); +void R_Draw2sMultiPatchTranslucentColumn_8(void); void R_DrawDropShadowColumn_8(void); void R_DrawTranslatedColumn_8(void); void R_DrawTranslatedTranslucentColumn_8(void); @@ -203,6 +173,7 @@ void R_DrawTiltedTranslucentSpan_8(void); void R_DrawSplat_8(void); void R_DrawTranslucentSplat_8(void); void R_DrawTiltedSplat_8(void); +void R_DrawTiltedTranslucentSplat_8(void); void R_DrawFloorSprite_8(void); void R_DrawTranslucentFloorSprite_8(void); @@ -224,6 +195,7 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void); void R_DrawSplat_NPO2_8(void); void R_DrawTranslucentSplat_NPO2_8(void); void R_DrawTiltedSplat_NPO2_8(void); +void R_DrawTiltedTranslucentSplat_NPO2_8(void); void R_DrawFloorSprite_NPO2_8(void); void R_DrawTranslucentFloorSprite_NPO2_8(void); @@ -240,17 +212,5 @@ void R_DrawTiltedTransSolidColorSpan_8(void); void R_DrawWaterSolidColorSpan_8(void); void R_DrawTiltedWaterSolidColorSpan_8(void); -// ------------------ -// 16bpp DRAWING CODE -// ------------------ - -#ifdef HIGHCOLOR -void R_DrawColumn_16(void); -void R_DrawWallColumn_16(void); -void R_DrawTranslucentColumn_16(void); -void R_DrawTranslatedColumn_16(void); -void R_DrawSpan_16(void); -#endif - // ========================================================================= #endif // __R_DRAW__ diff --git a/src/r_draw16.c b/src/r_draw16.c deleted file mode 100644 index 2ed5a2a8e3d267ab869c5a0c800423fe7eb68eba..0000000000000000000000000000000000000000 --- a/src/r_draw16.c +++ /dev/null @@ -1,214 +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 r_draw16.c -/// \brief 16bpp (HIGHCOLOR) span/column drawer functions -/// \note no includes because this is included as part of r_draw.c - -// ========================================================================== -// COLUMNS -// ========================================================================== - -/// \brief kick out the upper bit of each component (we're in 5 : 5 : 5) -#define HIMASK1 0x7bde - -/** \brief The R_DrawColumn_16 function - standard upto 128high posts column drawer -*/ -void R_DrawColumn_16(void) -{ - INT32 count; - INT16 *dest; - fixed_t frac, fracstep; - - count = dc_yh - dc_yl + 1; - - // Zero length, column does not exceed a pixel. - if (count <= 0) - return; - -#ifdef RANGECHECK - if (dc_x >= vid.width || dc_yl < 0 || dc_yh >= vid.height) - I_Error("R_DrawColumn_16: %d to %d at %d", dc_yl, dc_yh, dc_x); -#endif - - // Framebuffer destination address. - // Use ylookup LUT to avoid multiply with ScreenWidth. - // Use columnofs LUT for subwindows? - dest = (INT16 *)(void *)(ylookup[dc_yl] + columnofs[dc_x]); - - // Determine scaling, which is the only mapping to be done. - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl - centery)*fracstep; - - // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. - // This is as fast as it gets. - - do - { - // Re-map color indices from wall texture column using a lighting/special effects LUT. - *dest = hicolormaps[((INT16 *)(void *)dc_source)[(frac>>FRACBITS)&127]>>1]; - - dest += vid.width; - frac += fracstep; - } while (--count); -} - -/** \brief The R_DrawWallColumn_16 function - LAME cutnpaste: same as R_DrawColumn_16 but wraps around 256 - instead of 128 for the tall sky textures (256x240) -*/ -void R_DrawWallColumn_16(void) -{ - INT32 count; - INT16 *dest; - fixed_t frac, fracstep; - - count = dc_yh - dc_yl + 1; - - // Zero length, column does not exceed a pixel. - if (count <= 0) - return; - -#ifdef RANGECHECK - if (dc_x >= vid.width || dc_yl < 0 || dc_yh >= vid.height) - I_Error("R_DrawWallColumn_16: %d to %d at %d", dc_yl, dc_yh, dc_x); -#endif - - dest = (INT16 *)(void *)(ylookup[dc_yl] + columnofs[dc_x]); - - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl - centery)*fracstep; - - do - { - *dest = hicolormaps[((INT16 *)(void *)dc_source)[(frac>>FRACBITS)&255]>>1]; - - dest += vid.width; - frac += fracstep; - } while (--count); -} - -/** \brief The R_DrawTranslucentColumn_16 function - LAME cutnpaste: same as R_DrawColumn_16 but does - translucent -*/ -void R_DrawTranslucentColumn_16(void) -{ - INT32 count; - INT16 *dest; - fixed_t frac, fracstep; - - // check out coords for src* - if ((dc_yl < 0) || (dc_x >= vid.width)) - return; - - count = dc_yh - dc_yl; - if (count < 0) - return; - -#ifdef RANGECHECK - if (dc_x >= vid.width || dc_yl < 0 || dc_yh >= vid.height) - I_Error("R_DrawTranslucentColumn_16: %d to %d at %d", dc_yl, dc_yh, dc_x); -#endif - - // FIXME. As above. - dest = (INT16 *)(void *)(ylookup[dc_yl] + columnofs[dc_x]); - - // Looks familiar. - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl - centery)*fracstep; - - // Here we do an additional index re-mapping. - do - { - *dest = (INT16)((INT16)((color8to16[dc_source[frac>>FRACBITS]]>>1) & 0x39ce) - + (INT16)(((*dest & HIMASK1)) & 0x7fff)); - - dest += vid.width; - frac += fracstep; - } while (count--); -} - -/** \brief The R_DrawTranslatedColumn_16 function - ? -*/ -void R_DrawTranslatedColumn_16(void) -{ - INT32 count; - INT16 *dest; - fixed_t frac, fracstep; - - count = dc_yh - dc_yl; - if (count < 0) - return; - -#ifdef RANGECHECK - if (dc_x >= vid.width || dc_yl < 0 || dc_yh >= vid.height) - I_Error("R_DrawTranslatedColumn_16: %d to %d at %d", dc_yl, dc_yh, dc_x); -#endif - - dest = (INT16 *)(void *)(ylookup[dc_yl] + columnofs[dc_x]); - - // Looks familiar. - fracstep = dc_iscale; - frac = dc_texturemid + (dc_yl - centery)*fracstep; - - // Here we do an additional index re-mapping. - do - { - *dest = color8to16[dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]]; - dest += vid.width; - - frac += fracstep; - } while (count--); -} - -// ========================================================================== -// SPANS -// ========================================================================== - -/** \brief The R_*_16 function - Draws the actual span. -*/ -void R_DrawSpan_16(void) -{ - fixed_t xfrac, yfrac; - INT16 *dest; - INT32 count, spot; - -#ifdef RANGECHECK - if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= vid.width || ds_y > vid.height) - I_Error("R_DrawSpan_16: %d to %d at %d", ds_x1, ds_x2, ds_y); -#endif - - xfrac = ds_xfrac; - yfrac = ds_yfrac; - - dest = (INT16 *)(void *)(ylookup[ds_y] + columnofs[ds_x1]); - - // We do not check for zero spans here? - count = ds_x2 - ds_x1; - - if (count <= 0) // We do now! - return; - - do - { - // Current texture index in u, v. - spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63); - - // Lookup pixel from flat texture tile, re-index using light/colormap. - *dest++ = hicolormaps[((INT16 *)(void *)ds_source)[spot]>>1]; - - // Next step in u, v. - xfrac += ds_xstep; - yfrac += ds_ystep; - } while (count--); -} diff --git a/src/r_draw8.c b/src/r_draw8.c index 87545f41836761421f2cdf8694c07c88f6815612..c720f454e078d1f7857227eae01caa866d56d136 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -40,18 +40,13 @@ void R_DrawColumn_8(void) #endif // Framebuffer destination address. - // Use ylookup LUT to avoid multiply with ScreenWidth. - // Use columnofs LUT for subwindows? - - //dest = ylookup[dc_yl] + columnofs[dc_x]; dest = &topleft[dc_yl*vid.width + dc_x]; count++; // Determine scaling, which is the only mapping to be done. fracstep = dc_iscale; - //frac = dc_texturemid + (dc_yl - centery)*fracstep; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); + frac = dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep); // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. // This is as fast as it gets. @@ -105,6 +100,281 @@ void R_DrawColumn_8(void) } } +/** \brief The R_DrawColumnClamped_8 function + Same as R_DrawColumn_8, but prevents artifacts from showing up (caused by fixed-point imprecisions) +*/ +void R_DrawColumnClamped_8(void) +{ + INT32 count; + UINT8 *dest; + fixed_t frac; + fixed_t fracstep; + + count = dc_yh - dc_yl; + + if (count < 0) // Zero length, column does not exceed a pixel. + return; + +#ifdef RANGECHECK + if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + return; +#endif + + // Framebuffer destination address. + dest = &topleft[dc_yl*vid.width + dc_x]; + + count++; + + // Determine scaling, which is the only mapping to be done. + fracstep = dc_iscale; + frac = dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep); + + // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. + // This is as fast as it gets. + { + const UINT8 *source = dc_source; + const lighttable_t *colormap = dc_colormap; + INT32 heightmask = dc_texheight-1; + INT32 idx; + if (dc_texheight & heightmask) // not a power of 2 -- killough + { + heightmask++; + heightmask <<= FRACBITS; + + if (frac < 0) + while ((frac += heightmask) < 0); + else + while (frac >= heightmask) + frac -= heightmask; + + do + { + // Re-map color indices from wall texture column + // using a lighting/special effects LUT. + // heightmask is the Tutti-Frutti fix + idx = frac>>FRACBITS; + if (idx >= 0 && idx < dc_postlength) + *dest = colormap[source[idx]]; + dest += vid.width; + + // Avoid overflow. + if (fracstep > 0x7FFFFFFF - frac) + frac += fracstep - heightmask; + else + frac += fracstep; + + while (frac >= heightmask) + frac -= heightmask; + } while (--count); + } + else + { + while ((count -= 2) >= 0) // texture height is a power of 2 + { + idx = (frac>>FRACBITS) & heightmask; + if (idx >= 0 && idx < dc_postlength) + *dest = colormap[source[idx]]; + dest += vid.width; + frac += fracstep; + idx = (frac>>FRACBITS) & heightmask; + if (idx >= 0 && idx < dc_postlength) + *dest = colormap[source[idx]]; + dest += vid.width; + frac += fracstep; + } + if (count & 1) + { + idx = (frac>>FRACBITS) & heightmask; + if (idx >= 0 && idx < dc_postlength) + *dest = colormap[source[idx]]; + } + } + } +} + +void R_Draw2sMultiPatchColumn_8(void) +{ + INT32 count; + register UINT8 *dest; + register fixed_t frac; + fixed_t fracstep; + + count = dc_yh - dc_yl; + + if (count < 0) // Zero length, column does not exceed a pixel. + return; + +#ifdef RANGECHECK + if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + return; +#endif + + // Framebuffer destination address. + dest = &topleft[dc_yl*vid.width + dc_x]; + + count++; + + // Determine scaling, which is the only mapping to be done. + fracstep = dc_iscale; + frac = dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep); + + // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. + // This is as fast as it gets. + { + register const UINT8 *source = dc_source; + register const lighttable_t *colormap = dc_colormap; + register INT32 heightmask = dc_texheight-1; + register UINT8 val; + if (dc_texheight & heightmask) // not a power of 2 -- killough + { + heightmask++; + heightmask <<= FRACBITS; + + if (frac < 0) + while ((frac += heightmask) < 0); + else + while (frac >= heightmask) + frac -= heightmask; + + do + { + // Re-map color indices from wall texture column + // using a lighting/special effects LUT. + // heightmask is the Tutti-Frutti fix + val = source[frac>>FRACBITS]; + + if (val != TRANSPARENTPIXEL) + *dest = colormap[val]; + + dest += vid.width; + + // Avoid overflow. + if (fracstep > 0x7FFFFFFF - frac) + frac += fracstep - heightmask; + else + frac += fracstep; + + while (frac >= heightmask) + frac -= heightmask; + } while (--count); + } + else + { + while ((count -= 2) >= 0) // texture height is a power of 2 + { + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + *dest = colormap[val]; + dest += vid.width; + frac += fracstep; + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + *dest = colormap[val]; + dest += vid.width; + frac += fracstep; + } + if (count & 1) + { + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + *dest = colormap[val]; + } + } + } +} + +void R_Draw2sMultiPatchTranslucentColumn_8(void) +{ + INT32 count; + register UINT8 *dest; + register fixed_t frac; + fixed_t fracstep; + + count = dc_yh - dc_yl; + + if (count < 0) // Zero length, column does not exceed a pixel. + return; + +#ifdef RANGECHECK + if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + return; +#endif + + // Framebuffer destination address. + dest = &topleft[dc_yl*vid.width + dc_x]; + + count++; + + // Determine scaling, which is the only mapping to be done. + fracstep = dc_iscale; + frac = dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep); + + // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. + // This is as fast as it gets. + { + register const UINT8 *source = dc_source; + register const UINT8 *transmap = dc_transmap; + register const lighttable_t *colormap = dc_colormap; + register INT32 heightmask = dc_texheight-1; + register UINT8 val; + if (dc_texheight & heightmask) // not a power of 2 -- killough + { + heightmask++; + heightmask <<= FRACBITS; + + if (frac < 0) + while ((frac += heightmask) < 0); + else + while (frac >= heightmask) + frac -= heightmask; + + do + { + // Re-map color indices from wall texture column + // using a lighting/special effects LUT. + // heightmask is the Tutti-Frutti fix + val = source[frac>>FRACBITS]; + + if (val != TRANSPARENTPIXEL) + *dest = *(transmap + (colormap[val]<<8) + (*dest)); + + dest += vid.width; + + // Avoid overflow. + if (fracstep > 0x7FFFFFFF - frac) + frac += fracstep - heightmask; + else + frac += fracstep; + + while (frac >= heightmask) + frac -= heightmask; + } while (--count); + } + else + { + while ((count -= 2) >= 0) // texture height is a power of 2 + { + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + *dest = *(transmap + (colormap[val]<<8) + (*dest)); + dest += vid.width; + frac += fracstep; + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + *dest = *(transmap + (colormap[val]<<8) + (*dest)); + dest += vid.width; + frac += fracstep; + } + if (count & 1) + { + val = source[(frac>>FRACBITS) & heightmask]; + if (val != TRANSPARENTPIXEL) + *dest = *(transmap + (colormap[val]<<8) + (*dest)); + } + } + } +} + /** \brief The R_DrawShadeColumn_8 function Experiment to make software go faster. Taken from the Boom source */ @@ -127,14 +397,11 @@ void R_DrawShadeColumn_8(void) I_Error("R_DrawShadeColumn_8: %d to %d at %d", dc_yl, dc_yh, dc_x); #endif - // FIXME. As above. - //dest = ylookup[dc_yl] + columnofs[dc_x]; dest = &topleft[dc_yl*vid.width + dc_x]; // Looks familiar. fracstep = dc_iscale; - //frac = dc_texturemid + (dc_yl - centery)*fracstep; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); + frac = dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep); // Here we do an additional index re-mapping. do @@ -166,14 +433,11 @@ void R_DrawTranslucentColumn_8(void) I_Error("R_DrawTranslucentColumn_8: %d to %d at %d", dc_yl, dc_yh, dc_x); #endif - // FIXME. As above. - //dest = ylookup[dc_yl] + columnofs[dc_x]; dest = &topleft[dc_yl*vid.width + dc_x]; // Looks familiar. fracstep = dc_iscale; - //frac = dc_texturemid + (dc_yl - centery)*fracstep; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); + frac = dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep); // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. // This is as fast as it gets. @@ -223,6 +487,90 @@ void R_DrawTranslucentColumn_8(void) } } +/** \brief The R_DrawTranslucentColumnClamped_8 function + Same as R_DrawTranslucentColumn_8, but prevents artifacts from showing up (caused by fixed-point imprecisions) +*/ +void R_DrawTranslucentColumnClamped_8(void) +{ + INT32 count; + UINT8 *dest; + fixed_t frac, fracstep; + + count = dc_yh - dc_yl + 1; + + if (count <= 0) // Zero length, column does not exceed a pixel. + return; + +#ifdef RANGECHECK + if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height) + I_Error("R_DrawTranslucentColumnClamped_8: %d to %d at %d", dc_yl, dc_yh, dc_x); +#endif + + dest = &topleft[dc_yl*vid.width + dc_x]; + + // Looks familiar. + fracstep = dc_iscale; + frac = dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep); + + // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. + // This is as fast as it gets. + { + const UINT8 *source = dc_source; + const UINT8 *transmap = dc_transmap; + const lighttable_t *colormap = dc_colormap; + INT32 heightmask = dc_texheight - 1; + INT32 idx; + if (dc_texheight & heightmask) + { + heightmask++; + heightmask <<= FRACBITS; + + if (frac < 0) + while ((frac += heightmask) < 0) + ; + else + while (frac >= heightmask) + frac -= heightmask; + + do + { + // Re-map color indices from wall texture column + // using a lighting/special effects LUT. + // heightmask is the Tutti-Frutti fix + idx = frac>>FRACBITS; + if (idx >= 0 && idx < dc_postlength) + *dest = *(transmap + (colormap[source[idx]]<<8) + (*dest)); + dest += vid.width; + if ((frac += fracstep) >= heightmask) + frac -= heightmask; + } + while (--count); + } + else + { + while ((count -= 2) >= 0) // texture height is a power of 2 + { + idx = (frac>>FRACBITS)&heightmask; + if (idx >= 0 && idx < dc_postlength) + *dest = *(transmap + (colormap[source[idx]]<<8) + (*dest)); + dest += vid.width; + frac += fracstep; + idx = (frac>>FRACBITS)&heightmask; + if (idx >= 0 && idx < dc_postlength) + *dest = *(transmap + (colormap[source[idx]]<<8) + (*dest)); + dest += vid.width; + frac += fracstep; + } + if (count & 1) + { + idx = (frac>>FRACBITS)&heightmask; + if (idx >= 0 && idx < dc_postlength) + *dest = *(transmap + (colormap[source[idx]]<<8) + (*dest)); + } + } + } +} + // Hack: A cut-down copy of R_DrawTranslucentColumn_8 that does not read texture // data since something about calculating the texture reading address for drop shadows is broken. // dc_texturemid and dc_iscale get wrong values for drop shadows, however those are not strictly @@ -271,14 +619,11 @@ void R_DrawTranslatedTranslucentColumn_8(void) if (count <= 0) // Zero length, column does not exceed a pixel. return; - // FIXME. As above. - //dest = ylookup[dc_yl] + columnofs[dc_x]; dest = &topleft[dc_yl*vid.width + dc_x]; // Looks familiar. fracstep = dc_iscale; - //frac = dc_texturemid + (dc_yl - centery)*fracstep; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); + frac = dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep); // Inner loop that does the actual texture mapping, e.g. a DDA-like scaling. // This is as fast as it gets. @@ -347,14 +692,11 @@ void R_DrawTranslatedColumn_8(void) I_Error("R_DrawTranslatedColumn_8: %d to %d at %d", dc_yl, dc_yh, dc_x); #endif - // FIXME. As above. - //dest = ylookup[dc_yl] + columnofs[dc_x]; dest = &topleft[dc_yl*vid.width + dc_x]; // Looks familiar. fracstep = dc_iscale; - //frac = dc_texturemid + (dc_yl-centery)*fracstep; - frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires); + frac = dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep); // Here we do an additional index re-mapping. do @@ -410,7 +752,7 @@ void R_DrawSpan_8 (void) source = ds_source; colormap = ds_colormap; - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; if (dest+8 > deststop) return; @@ -489,7 +831,7 @@ void R_DrawTiltedSpan_8(void) R_CalcSlopeLight(); - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; source = ds_source; //colormap = ds_colormap; @@ -611,7 +953,7 @@ void R_DrawTiltedTranslucentSpan_8(void) R_CalcSlopeLight(); - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; source = ds_source; //colormap = ds_colormap; @@ -733,7 +1075,7 @@ void R_DrawTiltedWaterSpan_8(void) R_CalcSlopeLight(); - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; source = ds_source; //colormap = ds_colormap; @@ -854,7 +1196,7 @@ void R_DrawTiltedSplat_8(void) R_CalcSlopeLight(); - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; source = ds_source; //colormap = ds_colormap; @@ -959,6 +1301,136 @@ void R_DrawTiltedSplat_8(void) #endif } +void R_DrawTiltedTranslucentSplat_8(void) +{ + // x1, x2 = ds_x1, ds_x2 + int width = ds_x2 - ds_x1; + double iz, uz, vz; + UINT32 u, v; + int i; + + UINT8 *source; + UINT8 *colormap; + UINT8 *dest; + + UINT8 val; + + double startz, startu, startv; + double izstep, uzstep, vzstep; + double endz, endu, endv; + UINT32 stepu, stepv; + + iz = ds_sz.z + ds_sz.y*(centery-ds_y) + ds_sz.x*(ds_x1-centerx); + uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx); + vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx); + + R_CalcSlopeLight(); + + dest = &topleft[ds_y*vid.width + ds_x1]; + source = ds_source; + //colormap = ds_colormap; + +#if 0 // The "perfect" reference version of this routine. Pretty slow. + // Use it only to see how things are supposed to look. + i = 0; + do + { + double z = 1.f/iz; + u = (INT64)(uz*z); + v = (INT64)(vz*z); + + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + + dest++; + iz += ds_sz.x; + uz += ds_su.x; + vz += ds_sv.x; + } while (--width >= 0); +#else + startz = 1.f/iz; + startu = uz*startz; + startv = vz*startz; + + izstep = ds_sz.x * SPANSIZE; + uzstep = ds_su.x * SPANSIZE; + vzstep = ds_sv.x * SPANSIZE; + //x1 = 0; + width++; + + while (width >= SPANSIZE) + { + iz += izstep; + uz += uzstep; + vz += vzstep; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + stepu = (INT64)((endu - startu) * INVSPAN); + stepv = (INT64)((endv - startv) * INVSPAN); + u = (INT64)(startu); + v = (INT64)(startv); + + for (i = SPANSIZE-1; i >= 0; i--) + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + dest++; + u += stepu; + v += stepv; + } + startu = endu; + startv = endv; + width -= SPANSIZE; + } + if (width > 0) + { + if (width == 1) + { + u = (INT64)(startu); + v = (INT64)(startv); + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + } + else + { + double left = width; + iz += ds_sz.x * left; + uz += ds_su.x * left; + vz += ds_sv.x * left; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + left = 1.f/left; + stepu = (INT64)((endu - startu) * left); + stepv = (INT64)((endv - startv) * left); + u = (INT64)(startu); + v = (INT64)(startv); + + for (; width != 0; width--) + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + dest++; + u += stepu; + v += stepv; + } + } + } +#endif +} + /** \brief The R_DrawSplat_8 function Just like R_DrawSpan_8, but skips transparent pixels. */ @@ -991,7 +1463,7 @@ void R_DrawSplat_8 (void) source = ds_source; colormap = ds_colormap; - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; while (count >= 8) { @@ -1111,7 +1583,7 @@ void R_DrawTranslucentSplat_8 (void) source = ds_source; colormap = ds_colormap; - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; while (count >= 8) { @@ -1214,7 +1686,7 @@ void R_DrawFloorSprite_8 (void) source = (UINT16 *)ds_source; colormap = ds_colormap; translation = ds_translation; - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; while (count >= 8) { @@ -1325,7 +1797,7 @@ void R_DrawTranslucentFloorSprite_8 (void) source = (UINT16 *)ds_source; colormap = ds_colormap; translation = ds_translation; - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; while (count >= 8) { @@ -1420,7 +1892,7 @@ void R_DrawTiltedFloorSprite_8(void) uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx); vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx); - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; source = (UINT16 *)ds_source; colormap = ds_colormap; translation = ds_translation; @@ -1529,7 +2001,7 @@ void R_DrawTiltedTranslucentFloorSprite_8(void) uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx); vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx); - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; source = (UINT16 *)ds_source; colormap = ds_colormap; translation = ds_translation; @@ -1644,7 +2116,7 @@ void R_DrawTranslucentSpan_8 (void) source = ds_source; colormap = ds_colormap; - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; while (count >= 8) { @@ -1721,7 +2193,7 @@ void R_DrawWaterSpan_8(void) source = ds_source; colormap = ds_colormap; - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; count = ds_x2 - ds_x1 + 1; @@ -1784,7 +2256,6 @@ void R_DrawFogSpan_8(void) size_t count; colormap = ds_colormap; - //dest = ylookup[ds_y] + columnofs[ds_x1]; dest = &topleft[ds_y *vid.width + ds_x1]; count = ds_x2 - ds_x1 + 1; @@ -1814,7 +2285,7 @@ void R_DrawTiltedFogSpan_8(void) { int width = ds_x2 - ds_x1; - UINT8 *dest = ylookup[ds_y] + columnofs[ds_x1]; + UINT8 *dest = &topleft[ds_y*vid.width + ds_x1]; R_CalcSlopeLight(); @@ -1834,7 +2305,7 @@ void R_DrawSolidColorSpan_8(void) size_t count = (ds_x2 - ds_x1 + 1); UINT8 source = ds_colormap[ds_source[0]]; - UINT8 *dest = ylookup[ds_y] + columnofs[ds_x1]; + UINT8 *dest = &topleft[ds_y*vid.width + ds_x1]; memset(dest, source, count); } @@ -1847,7 +2318,7 @@ void R_DrawTransSolidColorSpan_8(void) size_t count = (ds_x2 - ds_x1 + 1); UINT8 source = ds_colormap[ds_source[0]]; - UINT8 *dest = ylookup[ds_y] + columnofs[ds_x1]; + UINT8 *dest = &topleft[ds_y*vid.width + ds_x1]; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; @@ -1866,7 +2337,7 @@ void R_DrawTiltedSolidColorSpan_8(void) int width = ds_x2 - ds_x1; UINT8 source = ds_source[0]; - UINT8 *dest = ylookup[ds_y] + columnofs[ds_x1]; + UINT8 *dest = &topleft[ds_y*vid.width + ds_x1]; R_CalcSlopeLight(); @@ -1885,7 +2356,7 @@ void R_DrawTiltedTransSolidColorSpan_8(void) int width = ds_x2 - ds_x1; UINT8 source = ds_source[0]; - UINT8 *dest = ylookup[ds_y] + columnofs[ds_x1]; + UINT8 *dest = &topleft[ds_y*vid.width + ds_x1]; R_CalcSlopeLight(); @@ -1904,7 +2375,7 @@ void R_DrawWaterSolidColorSpan_8(void) { UINT8 source = ds_source[0]; UINT8 *colormap = ds_colormap; - UINT8 *dest = ylookup[ds_y] + columnofs[ds_x1]; + UINT8 *dest = &topleft[ds_y*vid.width + ds_x1]; UINT8 *dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; size_t count = (ds_x2 - ds_x1 + 1); @@ -1925,7 +2396,7 @@ void R_DrawTiltedWaterSolidColorSpan_8(void) int width = ds_x2 - ds_x1; UINT8 source = ds_source[0]; - UINT8 *dest = ylookup[ds_y] + columnofs[ds_x1]; + UINT8 *dest = &topleft[ds_y*vid.width + ds_x1]; UINT8 *dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; R_CalcSlopeLight(); @@ -1957,9 +2428,6 @@ void R_DrawFogColumn_8(void) #endif // Framebuffer destination address. - // Use ylookup LUT to avoid multiply with ScreenWidth. - // Use columnofs LUT for subwindows? - //dest = ylookup[dc_yl] + columnofs[dc_x]; dest = &topleft[dc_yl*vid.width + dc_x]; // Determine scaling, which is the only mapping to be done. diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c index 78cde8a2ce195678333916f38a1b51bf5ba8e898..7fbb40d84956d342f1d675876f7dbcc9b2cd539b 100644 --- a/src/r_draw8_npo2.c +++ b/src/r_draw8_npo2.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -46,7 +46,7 @@ void R_DrawSpan_NPO2_8 (void) source = ds_source; colormap = ds_colormap; - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; if (dest+8 > deststop) return; @@ -120,7 +120,7 @@ void R_DrawTiltedSpan_NPO2_8(void) R_CalcSlopeLight(); - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; source = ds_source; //colormap = ds_colormap; @@ -309,7 +309,7 @@ void R_DrawTiltedTranslucentSpan_NPO2_8(void) R_CalcSlopeLight(); - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; source = ds_source; //colormap = ds_colormap; @@ -496,7 +496,7 @@ void R_DrawTiltedSplat_NPO2_8(void) R_CalcSlopeLight(); - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; source = ds_source; //colormap = ds_colormap; @@ -666,6 +666,204 @@ void R_DrawTiltedSplat_NPO2_8(void) #endif } +void R_DrawTiltedTranslucentSplat_NPO2_8(void) +{ + // x1, x2 = ds_x1, ds_x2 + int width = ds_x2 - ds_x1; + double iz, uz, vz; + UINT32 u, v; + int i; + + UINT8 *source; + UINT8 *colormap; + UINT8 *dest; + + UINT8 val; + + double startz, startu, startv; + double izstep, uzstep, vzstep; + double endz, endu, endv; + UINT32 stepu, stepv; + + struct libdivide_u32_t x_divider = libdivide_u32_gen(ds_flatwidth); + struct libdivide_u32_t y_divider = libdivide_u32_gen(ds_flatheight); + + iz = ds_sz.z + ds_sz.y*(centery-ds_y) + ds_sz.x*(ds_x1-centerx); + uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx); + vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx); + + R_CalcSlopeLight(); + + dest = &topleft[ds_y*vid.width + ds_x1]; + source = ds_source; + //colormap = ds_colormap; + +#if 0 // The "perfect" reference version of this routine. Pretty slow. + // Use it only to see how things are supposed to look. + i = 0; + do + { + double z = 1.f/iz; + u = (INT64)(uz*z); + v = (INT64)(vz*z); + + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; + if (y < 0) + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + + dest++; + iz += ds_sz.x; + uz += ds_su.x; + vz += ds_sv.x; + } while (--width >= 0); +#else + startz = 1.f/iz; + startu = uz*startz; + startv = vz*startz; + + izstep = ds_sz.x * SPANSIZE; + uzstep = ds_su.x * SPANSIZE; + vzstep = ds_sv.x * SPANSIZE; + //x1 = 0; + width++; + + while (width >= SPANSIZE) + { + iz += izstep; + uz += uzstep; + vz += vzstep; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + stepu = (INT64)((endu - startu) * INVSPAN); + stepv = (INT64)((endv - startv) * INVSPAN); + u = (INT64)(startu); + v = (INT64)(startv); + + for (i = SPANSIZE-1; i >= 0; i--) + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; + if (y < 0) + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + dest++; + u += stepu; + v += stepv; + } + startu = endu; + startv = endv; + width -= SPANSIZE; + } + if (width > 0) + { + if (width == 1) + { + u = (INT64)(startu); + v = (INT64)(startv); + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; + if (y < 0) + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + } + else + { + double left = width; + iz += ds_sz.x * left; + uz += ds_su.x * left; + vz += ds_sv.x * left; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + left = 1.f/left; + stepu = (INT64)((endu - startu) * left); + stepv = (INT64)((endv - startv) * left); + u = (INT64)(startu); + v = (INT64)(startv); + + for (; width != 0; width--) + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u) >> FRACBITS); + fixed_t y = (((fixed_t)v) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth; + else + x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth; + if (y < 0) + y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight; + else + y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + dest++; + u += stepu; + v += stepv; + } + } + } +#endif +} + /** \brief The R_DrawSplat_NPO2_8 function Just like R_DrawSpan_NPO2_8, but skips transparent pixels. */ @@ -690,7 +888,7 @@ void R_DrawSplat_NPO2_8 (void) source = ds_source; colormap = ds_colormap; - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; fixedwidth = ds_flatwidth << FRACBITS; fixedheight = ds_flatheight << FRACBITS; @@ -758,7 +956,7 @@ void R_DrawTranslucentSplat_NPO2_8 (void) source = ds_source; colormap = ds_colormap; - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; fixedwidth = ds_flatwidth << FRACBITS; fixedheight = ds_flatheight << FRACBITS; @@ -828,7 +1026,7 @@ void R_DrawFloorSprite_NPO2_8 (void) source = (UINT16 *)ds_source; colormap = ds_colormap; translation = ds_translation; - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; fixedwidth = ds_flatwidth << FRACBITS; fixedheight = ds_flatheight << FRACBITS; @@ -898,7 +1096,7 @@ void R_DrawTranslucentFloorSprite_NPO2_8 (void) source = (UINT16 *)ds_source; colormap = ds_colormap; translation = ds_translation; - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; fixedwidth = ds_flatwidth << FRACBITS; fixedheight = ds_flatheight << FRACBITS; @@ -971,7 +1169,7 @@ void R_DrawTiltedFloorSprite_NPO2_8(void) uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx); vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx); - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; source = (UINT16 *)ds_source; colormap = ds_colormap; translation = ds_translation; @@ -1127,7 +1325,7 @@ void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void) uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx); vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx); - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; source = (UINT16 *)ds_source; colormap = ds_colormap; translation = ds_translation; @@ -1278,7 +1476,7 @@ void R_DrawTranslucentSpan_NPO2_8 (void) source = ds_source; colormap = ds_colormap; - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; fixedwidth = ds_flatwidth << FRACBITS; fixedheight = ds_flatheight << FRACBITS; @@ -1342,7 +1540,7 @@ void R_DrawWaterSpan_NPO2_8(void) source = ds_source; colormap = ds_colormap; - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; fixedwidth = ds_flatwidth << FRACBITS; @@ -1414,7 +1612,7 @@ void R_DrawTiltedWaterSpan_NPO2_8(void) R_CalcSlopeLight(); - dest = ylookup[ds_y] + columnofs[ds_x1]; + dest = &topleft[ds_y*vid.width + ds_x1]; dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; source = ds_source; //colormap = ds_colormap; diff --git a/src/r_fps.c b/src/r_fps.c index 83fd0eec15f4c9fd0f41fa60104be022b9b4c7eb..71f6e59a7c465690f4acbc8c48522bb31fe8e225 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -3,7 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze, Andrey Budko (prboom) -// Copyright (C) 1999-2019 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -120,6 +120,19 @@ static vector3_t *R_LerpVector3(const vector3_t *from, const vector3_t *to, fixe return out; } +static double R_LerpDouble(double from, double to, double frac) +{ + return from + (frac * (to - from)); +} + +static dvector3_t *R_LerpDVector3(const dvector3_t *from, const dvector3_t *to, double frac, dvector3_t *out) +{ + DVector3_Subtract(to, from, out); + DVector3_Multiply(out, frac, out); + DVector3_Add(from, out, out); + return out; +} + // recalc necessary stuff for mouseaiming // slopes are already calculated for the full possible view (which is 4*viewheight). // 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out) @@ -497,6 +510,14 @@ void R_CreateInterpolator_DynSlope(thinker_t *thinker, pslope_t *slope) FV2_Copy(&interp->dynslope.bakd, &slope->d); interp->dynslope.oldzdelta = interp->dynslope.bakzdelta = slope->zdelta; + + DVector3_Copy(&interp->dynslope.oldorigin, &slope->dorigin); + DVector3_Copy(&interp->dynslope.bakorigin, &slope->dorigin); + + DVector3_Copy(&interp->dynslope.oldnormdir, &slope->dnormdir); + DVector3_Copy(&interp->dynslope.baknormdir, &slope->dnormdir); + + interp->dynslope.olddzdelta = interp->dynslope.bakdzdelta = slope->dzdelta; } void R_InitializeLevelInterpolators(void) @@ -561,6 +582,21 @@ static void UpdateLevelInterpolatorState(levelinterpolator_t *interp) FV3_Copy(&interp->dynslope.bako, &interp->dynslope.slope->o); FV2_Copy(&interp->dynslope.bakd, &interp->dynslope.slope->d); interp->dynslope.bakzdelta = interp->dynslope.slope->zdelta; + + DVector3_Copy(&interp->dynslope.oldorigin, &interp->dynslope.bakorigin); + DVector3_Copy(&interp->dynslope.oldnormdir, &interp->dynslope.baknormdir); + interp->dynslope.olddzdelta = interp->dynslope.bakdzdelta; + + if (interp->dynslope.slope->moved) + { + P_CalculateSlopeVectors(interp->dynslope.slope); + + interp->dynslope.slope->moved = false; + } + + DVector3_Copy(&interp->dynslope.bakorigin, &interp->dynslope.slope->dorigin); + DVector3_Copy(&interp->dynslope.baknormdir, &interp->dynslope.slope->dnormdir); + interp->dynslope.bakdzdelta = interp->dynslope.slope->dzdelta; break; } } @@ -646,7 +682,13 @@ void R_ApplyLevelInterpolators(fixed_t frac) R_LerpVector3(&interp->dynslope.oldo, &interp->dynslope.bako, frac, &interp->dynslope.slope->o); R_LerpVector2(&interp->dynslope.oldd, &interp->dynslope.bakd, frac, &interp->dynslope.slope->d); interp->dynslope.slope->zdelta = R_LerpFixed(interp->dynslope.oldzdelta, interp->dynslope.bakzdelta, frac); - interp->dynslope.slope->moved = true; + if (rendermode == render_soft) + { + double dfrac = FixedToDouble(frac); + R_LerpDVector3(&interp->dynslope.oldorigin, &interp->dynslope.bakorigin, dfrac, &interp->dynslope.slope->dorigin); + R_LerpDVector3(&interp->dynslope.oldnormdir, &interp->dynslope.baknormdir, dfrac, &interp->dynslope.slope->dnormdir); + interp->dynslope.slope->dzdelta = R_LerpDouble(interp->dynslope.olddzdelta, interp->dynslope.bakdzdelta, dfrac); + } break; } } @@ -704,6 +746,10 @@ void R_RestoreLevelInterpolators(void) FV3_Copy(&interp->dynslope.slope->o, &interp->dynslope.bako); FV2_Copy(&interp->dynslope.slope->d, &interp->dynslope.bakd); interp->dynslope.slope->zdelta = interp->dynslope.bakzdelta; + + DVector3_Copy(&interp->dynslope.slope->dorigin, &interp->dynslope.bakorigin); + DVector3_Copy(&interp->dynslope.slope->dnormdir, &interp->dynslope.baknormdir); + interp->dynslope.slope->dzdelta = interp->dynslope.bakdzdelta; break; } } @@ -817,6 +863,10 @@ void R_ResetMobjInterpolationState(mobj_t *mobj) mobj->old_roll2 = mobj->old_roll; mobj->old_spriteroll2 = mobj->old_spriteroll; mobj->old_scale2 = mobj->old_scale; + mobj->old_spritexscale2 = mobj->old_spritexscale; + mobj->old_spriteyscale2 = mobj->old_spriteyscale; + mobj->old_spritexoffset2 = mobj->old_spritexoffset; + mobj->old_spriteyoffset2 = mobj->old_spriteyoffset; mobj->old_x = mobj->x; mobj->old_y = mobj->y; mobj->old_z = mobj->z; @@ -853,6 +903,10 @@ void R_ResetPrecipitationMobjInterpolationState(precipmobj_t *mobj) mobj->old_pitch2 = mobj->old_pitch; mobj->old_roll2 = mobj->old_roll; mobj->old_spriteroll2 = mobj->old_spriteroll; + mobj->old_spritexscale2 = mobj->old_spritexscale; + mobj->old_spriteyscale2 = mobj->old_spriteyscale; + mobj->old_spritexoffset2 = mobj->old_spritexoffset; + mobj->old_spriteyoffset2 = mobj->old_spriteyoffset; mobj->old_x = mobj->x; mobj->old_y = mobj->y; mobj->old_z = mobj->z; diff --git a/src/r_fps.h b/src/r_fps.h index cd40b0a9a572b23b97bb9b2cc493ea6a34a243a7..ce64d19be442b2cc9bd2627b0787cb76538a6aa5 100644 --- a/src/r_fps.h +++ b/src/r_fps.h @@ -3,7 +3,7 @@ // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze, Andrey Budko (prboom) -// Copyright (C) 1999-2019 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -115,6 +115,9 @@ typedef struct levelinterpolator_s { vector3_t oldo, bako; vector2_t oldd, bakd; fixed_t oldzdelta, bakzdelta; + dvector3_t oldorigin, bakorigin; + dvector3_t oldnormdir, baknormdir; + double olddzdelta, bakdzdelta; } dynslope; }; } levelinterpolator_t; diff --git a/src/r_main.c b/src/r_main.c index aaab234ad1f168f2df77d2ed55b430b5cc3ff6fa..46bac9dc76a1886cb3ddc60167772312721b6a53 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -66,6 +66,10 @@ sector_t *viewsector; player_t *viewplayer; mobj_t *r_viewmobj; +boolean r_renderwalls; +boolean r_renderfloors; +boolean r_renderthings; + fixed_t rendertimefrac; fixed_t renderdeltatics; boolean renderisnewtic; @@ -149,8 +153,6 @@ consvar_t cv_flipcam2 = CVAR_INIT ("flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT, consvar_t cv_shadow = CVAR_INIT ("shadow", "On", CV_SAVE, CV_OnOff, NULL); consvar_t cv_skybox = CVAR_INIT ("skybox", "On", CV_SAVE, CV_OnOff, NULL); -consvar_t cv_ffloorclip = CVAR_INIT ("r_ffloorclip", "On", CV_SAVE, CV_OnOff, NULL); -consvar_t cv_spriteclip = CVAR_INIT ("r_spriteclip", "On", CV_SAVE, CV_OnOff, NULL); consvar_t cv_allowmlook = CVAR_INIT ("allowmlook", "Yes", CV_NETVAR|CV_ALLOWLUA, CV_YesNo, NULL); consvar_t cv_showhud = CVAR_INIT ("showhud", "Yes", CV_CALL|CV_ALLOWLUA, CV_YesNo, R_SetViewSize); consvar_t cv_translucenthud = CVAR_INIT ("translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL); @@ -161,11 +163,16 @@ consvar_t cv_drawdist_nights = CVAR_INIT ("drawdist_nights", "2048", CV_SAVE, dr consvar_t cv_drawdist_precip = CVAR_INIT ("drawdist_precip", "1024", CV_SAVE, drawdist_precip_cons_t, NULL); consvar_t cv_fov = CVAR_INIT ("fov", "90", CV_SAVE|CV_FLOAT|CV_CALL, fov_cons_t, Fov_OnChange); consvar_t cv_fovchange = CVAR_INIT ("fovchange", "Off", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_maxportals = CVAR_INIT ("maxportals", "2", CV_SAVE, maxportals_cons_t, NULL); -// Okay, whoever said homremoval causes a performance hit should be shot. -consvar_t cv_homremoval = CVAR_INIT ("homremoval", "No", CV_SAVE, homremoval_cons_t, NULL); +consvar_t cv_renderview = CVAR_INIT ("renderview", "On", 0, CV_OnOff, NULL); +consvar_t cv_renderwalls = CVAR_INIT ("r_renderwalls", "On", 0, CV_OnOff, NULL); +consvar_t cv_renderfloors = CVAR_INIT ("r_renderfloors", "On", 0, CV_OnOff, NULL); +consvar_t cv_renderthings = CVAR_INIT ("r_renderthings", "On", 0, CV_OnOff, NULL); +consvar_t cv_ffloorclip = CVAR_INIT ("r_ffloorclip", "On", 0, CV_OnOff, NULL); +consvar_t cv_spriteclip = CVAR_INIT ("r_spriteclip", "On", 0, CV_OnOff, NULL); -consvar_t cv_maxportals = CVAR_INIT ("maxportals", "2", CV_SAVE, maxportals_cons_t, NULL); +consvar_t cv_homremoval = CVAR_INIT ("homremoval", "No", CV_SAVE, homremoval_cons_t, NULL); consvar_t cv_renderstats = CVAR_INIT ("renderstats", "Off", 0, CV_OnOff, NULL); @@ -318,7 +325,6 @@ angle_t R_PointToAngle(fixed_t x, fixed_t y) } // This version uses 64-bit variables to avoid overflows with large values. -// Currently used only by OpenGL rendering. angle_t R_PointToAngle64(INT64 x, INT64 y) { return (y -= viewy, (x -= viewx) || y) ? @@ -384,56 +390,26 @@ fixed_t R_PointToDist(fixed_t x, fixed_t y) return R_PointToDist2(viewx, viewy, x, y); } -angle_t R_PointToAngleEx(INT32 x2, INT32 y2, INT32 x1, INT32 y1) +line_t *R_GetFFloorLine(const line_t *line, const ffloor_t *pfloor, const sector_t *sector) { - INT64 dx = x1-x2; - INT64 dy = y1-y2; - if (dx < INT32_MIN || dx > INT32_MAX || dy < INT32_MIN || dy > INT32_MAX) + if (pfloor->master->flags & ML_TFERLINE) { - x1 = (int)(dx / 2 + x2); - y1 = (int)(dy / 2 + y2); + size_t linenum = min((size_t)(line - sector->lines[0]), pfloor->master->frontsector->linecount); + return pfloor->master->frontsector->lines[0] + linenum; } - return (y1 -= y2, (x1 -= x2) || y1) ? - x1 >= 0 ? - y1 >= 0 ? - (x1 > y1) ? tantoangle[SlopeDivEx(y1,x1)] : // octant 0 - ANGLE_90-tantoangle[SlopeDivEx(x1,y1)] : // octant 1 - x1 > (y1 = -y1) ? 0-tantoangle[SlopeDivEx(y1,x1)] : // octant 8 - ANGLE_270+tantoangle[SlopeDivEx(x1,y1)] : // octant 7 - y1 >= 0 ? (x1 = -x1) > y1 ? ANGLE_180-tantoangle[SlopeDivEx(y1,x1)] : // octant 3 - ANGLE_90 + tantoangle[SlopeDivEx(x1,y1)] : // octant 2 - (x1 = -x1) > (y1 = -y1) ? ANGLE_180+tantoangle[SlopeDivEx(y1,x1)] : // octant 4 - ANGLE_270-tantoangle[SlopeDivEx(x1,y1)] : // octant 5 - 0; + else + return pfloor->master; } -// -// R_ScaleFromGlobalAngle -// Returns the texture mapping scale for the current line (horizontal span) -// at the given angle. -// rw_distance must be calculated first. -// -// killough 5/2/98: reformatted, cleaned up -// -// note: THIS IS USED ONLY FOR WALLS! -fixed_t R_ScaleFromGlobalAngle(angle_t visangle) +side_t *R_GetFFloorSide(const line_t *line, const ffloor_t *pfloor, const sector_t *sector) { - angle_t anglea = ANGLE_90 + (visangle-viewangle); - angle_t angleb = ANGLE_90 + (visangle-rw_normalangle); - fixed_t den = FixedMul(rw_distance, FINESINE(anglea>>ANGLETOFINESHIFT)); - // proff 11/06/98: Changed for high-res - fixed_t num = FixedMul(projectiony, FINESINE(angleb>>ANGLETOFINESHIFT)); - - if (den > num>>16) + if (pfloor->master->flags & ML_TFERLINE) { - num = FixedDiv(num, den); - if (num > 64*FRACUNIT) - return 64*FRACUNIT; - if (num < 256) - return 256; - return num; + line_t *newline = R_GetFFloorLine(line, pfloor, sector); + return &sides[newline->sidenum[0]]; } - return 64*FRACUNIT; + else + return &sides[pfloor->master->sidenum[0]]; } // @@ -1001,8 +977,6 @@ void R_Init(void) //I_OutputMsg("\nR_InitData"); R_InitData(); - //I_OutputMsg("\nR_InitViewBorder"); - R_InitViewBorder(); R_SetViewSize(); // setsizeneeded is set true // this is now done by SCR_Recalc() at the first mode set @@ -1121,7 +1095,7 @@ void R_SetupFrame(player_t *player) camera_t *thiscam; boolean chasecam = R_ViewpointHasChasecam(player); boolean ispaused = paused || P_AutoPause(); - + if (splitscreen && player == &players[secondarydisplayplayer] && player != &players[consoleplayer]) thiscam = &camera2; else @@ -1178,8 +1152,14 @@ void R_SetupFrame(player_t *player) if (quake.epicenter) { // Calculate 3D distance from epicenter, using the camera. - fixed_t xydist = R_PointToDist2(thiscam->x, thiscam->y, quake.epicenter->x, quake.epicenter->y); - fixed_t dist = R_PointToDist2(0, thiscam->z, xydist, quake.epicenter->z); + fixed_t xydist, dist; + if (P_MobjWasRemoved(r_viewmobj)) { + xydist = R_PointToDist2(thiscam->x, thiscam->y, quake.epicenter->x, quake.epicenter->y); + dist = R_PointToDist2(0, thiscam->z, xydist, quake.epicenter->z); + } else { + xydist = R_PointToDist2(r_viewmobj->x, r_viewmobj->y, quake.epicenter->x, quake.epicenter->y); + dist = R_PointToDist2(0, r_viewmobj->z, xydist, quake.epicenter->z); + } // More effect closer to epicenter, outside of radius = no effect if (!quake.radius || dist > quake.radius) @@ -1363,7 +1343,7 @@ void R_SkyboxFrame(player_t *player) newview->z += campos.z * -mh->skybox_scalez; } - if (r_viewmobj->subsector) + if (!P_MobjWasRemoved(r_viewmobj) && r_viewmobj->subsector) newview->sector = r_viewmobj->subsector->sector; else newview->sector = R_PointInSubsector(newview->x, newview->y)->sector; @@ -1395,7 +1375,7 @@ boolean R_ViewpointHasChasecam(player_t *player) chasecam = true; // force chasecam on else if (player->spectator) // no spectator chasecam chasecam = false; // force chasecam off - + if (chasecam && !thiscam->chase) { P_ResetCamera(player, thiscam); @@ -1406,7 +1386,7 @@ boolean R_ViewpointHasChasecam(player_t *player) P_ResetCamera(player, thiscam); thiscam->chase = false; } - + if (isplayer2) { R_SetViewContext(VIEWCONTEXT_PLAYER2); @@ -1454,6 +1434,9 @@ static void R_PortalFrame(portal_t *portal) viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT); viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); + if (!P_MobjWasRemoved(portal->viewmobj)) + r_viewmobj = portal->viewmobj; + portalclipstart = portal->start; portalclipend = portal->end; @@ -1646,17 +1629,11 @@ void R_RenderPlayerView(player_t *player) void R_RegisterEngineStuff(void) { - CV_RegisterVar(&cv_gravity); - CV_RegisterVar(&cv_tailspickup); - CV_RegisterVar(&cv_allowmlook); - CV_RegisterVar(&cv_homremoval); - CV_RegisterVar(&cv_flipcam); - CV_RegisterVar(&cv_flipcam2); - - // Enough for dedicated server + // Do nothing for dedicated server if (dedicated) return; + CV_RegisterVar(&cv_homremoval); CV_RegisterVar(&cv_translucency); CV_RegisterVar(&cv_drawdist); CV_RegisterVar(&cv_drawdist_nights); @@ -1669,6 +1646,13 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_shadow); CV_RegisterVar(&cv_skybox); + CV_RegisterVar(&cv_renderview); + CV_RegisterVar(&cv_renderhitboxinterpolation); + CV_RegisterVar(&cv_renderhitboxgldepth); + CV_RegisterVar(&cv_renderhitbox); + CV_RegisterVar(&cv_renderwalls); + CV_RegisterVar(&cv_renderfloors); + CV_RegisterVar(&cv_renderthings); CV_RegisterVar(&cv_ffloorclip); CV_RegisterVar(&cv_spriteclip); @@ -1707,8 +1691,6 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_maxportals); - CV_RegisterVar(&cv_movebob); - // Frame interpolation/uncapped CV_RegisterVar(&cv_fpscap); } diff --git a/src/r_main.h b/src/r_main.h index c7dc06c901d417885750238e6424f862ddd9e3d0..af7086e834a9e902da7f32e4413e64433c89bd0a 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -77,17 +77,18 @@ INT32 R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line); angle_t R_PointToAngle(fixed_t x, fixed_t y); angle_t R_PointToAngle64(INT64 x, INT64 y); angle_t R_PointToAngle2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1); -angle_t R_PointToAngleEx(INT32 x2, INT32 y2, INT32 x1, INT32 y1); fixed_t R_PointToDist(fixed_t x, fixed_t y); fixed_t R_PointToDist2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1); -fixed_t R_ScaleFromGlobalAngle(angle_t visangle); boolean R_IsPointInSector(sector_t *sector, fixed_t x, fixed_t y); subsector_t *R_PointInSubsector(fixed_t x, fixed_t y); subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y); boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixed_t bottomh, fixed_t toph); +line_t *R_GetFFloorLine(const line_t *line, const ffloor_t *pfloor, const sector_t *sector); +side_t *R_GetFFloorSide(const line_t *line, const ffloor_t *pfloor, const sector_t *sector); + // Render stats extern precise_t ps_prevframetime;// time when previous frame was rendered @@ -118,12 +119,18 @@ extern consvar_t cv_chasecam, cv_chasecam2; extern consvar_t cv_flipcam, cv_flipcam2; extern consvar_t cv_shadow; -extern consvar_t cv_ffloorclip, cv_spriteclip; extern consvar_t cv_translucency; extern consvar_t cv_drawdist, cv_drawdist_nights, cv_drawdist_precip; extern consvar_t cv_fov, cv_fovchange; extern consvar_t cv_skybox; -extern consvar_t cv_tailspickup; +extern consvar_t cv_renderview; +extern consvar_t cv_renderhitbox, cv_renderhitboxinterpolation, cv_renderhitboxgldepth; +extern consvar_t cv_renderwalls, cv_renderfloors, cv_renderthings; +extern consvar_t cv_ffloorclip, cv_spriteclip; + +extern boolean r_renderwalls; +extern boolean r_renderfloors; +extern boolean r_renderthings; // Called by startup code. void R_Init(void); diff --git a/src/r_patch.c b/src/r_patch.c index a6a9dc2ebcc0651c26f6faaede8bf7535f607c74..19e66404f1da18e82f5ec4076e5b61b83184feea 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2023 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020-2023 by Lactozilla. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_patch.h b/src/r_patch.h index f1a018c035a322a2a57f926e161fe97b66be5c2f..ff76254e84a5e204b75e3b2a1d83c69532ee4a31 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2023 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020-2024 by Lactozilla. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index b9106984970f728e83e567627daa4c1b9c478011..989665d74179854fcfac552814132671c3d00ed2 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2023 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020-2023 by Lactozilla. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_patchrotation.h b/src/r_patchrotation.h index a239ac5fa4dfb4220e3aeda3faebe2781e58b7ff..184d7ac13b5f7987cd63976d127165836e59b5b4 100644 --- a/src/r_patchrotation.h +++ b/src/r_patchrotation.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2020-2023 by Jaime "Lactozilla" Passos. +// Copyright (C) 2020-2023 by Lactozilla. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_picformats.c b/src/r_picformats.c index 7d7f1198d1805b24b715f78a339b07c952dd4e04..a45c143b01698de2abbb48f534f543a3a68d845e 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -2,8 +2,8 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 2005-2009 by Andrey "entryway" Budko. -// Copyright (C) 2018-2023 by Jaime "Lactozilla" Passos. -// Copyright (C) 2019-2023 by Sonic Team Junior. +// Copyright (C) 2018-2024 by Lactozilla. +// Copyright (C) 2019-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -376,7 +376,7 @@ void *Picture_PatchConvert( // Write columns for (INT32 x = 0; x < inwidth; x++) { - post_t *post; + post_t *post = NULL; size_t post_data_offset = 0; boolean was_opaque = false; @@ -1570,7 +1570,7 @@ static void R_ParseSpriteInfo(boolean spr2) spriteinfo_t *info; char *sprinfoToken; size_t sprinfoTokenLength; - char newSpriteName[5]; // no longer dynamically allocated + char newSpriteName[MAXSPRITENAME + 1]; // no longer dynamically allocated spritenum_t sprnum = NUMSPRITES; playersprite_t spr2num = NUMPLAYERSPRITES; INT32 i; @@ -1584,31 +1584,17 @@ static void R_ParseSpriteInfo(boolean spr2) I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite name should be"); } sprinfoTokenLength = strlen(sprinfoToken); - if (sprinfoTokenLength != 4) - { - I_Error("Error parsing SPRTINFO lump: Sprite name \"%s\" isn't 4 characters long",sprinfoToken); - } - else - { - memset(&newSpriteName, 0, 5); - M_Memcpy(newSpriteName, sprinfoToken, sprinfoTokenLength); - // ^^ we've confirmed that the token is == 4 characters so it will never overflow a 5 byte char buffer - strupr(newSpriteName); // Just do this now so we don't have to worry about it - } + if (sprinfoTokenLength > MAXSPRITENAME) + I_Error("Error parsing SPRTINFO lump: Sprite name \"%s\" is longer than %d characters", sprinfoToken, MAXSPRITENAME); + strcpy(newSpriteName, sprinfoToken); + strupr(newSpriteName); // Just do this now so we don't have to worry about it Z_Free(sprinfoToken); if (!spr2) { - for (i = 0; i <= NUMSPRITES; i++) - { - if (i == NUMSPRITES) - I_Error("Error parsing SPRTINFO lump: Unknown sprite name \"%s\"", newSpriteName); - if (!memcmp(newSpriteName,sprnames[i],4)) - { - sprnum = i; - break; - } - } + sprnum = R_GetSpriteNumByName(newSpriteName); + if (sprnum == NUMSPRITES) + I_Error("Error parsing SPRTINFO lump: Unknown sprite name \"%s\"", newSpriteName); } else { diff --git a/src/r_picformats.h b/src/r_picformats.h index 3ee9805d867f30cf8eec923285b24d0172038f18..123dda976c204787505fb1a90bad859fe39b836b 100644 --- a/src/r_picformats.h +++ b/src/r_picformats.h @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. -// Copyright (C) 2018-2023 by Jaime "Lactozilla" Passos. -// Copyright (C) 2019-2023 by Sonic Team Junior. +// Copyright (C) 2018-2024 by Lactozilla. +// Copyright (C) 2019-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -100,7 +100,7 @@ typedef struct typedef struct { - spriteframepivot_t pivot[64]; + spriteframepivot_t pivot[MAXFRAMENUM]; boolean available; } spriteinfo_t; diff --git a/src/r_plane.c b/src/r_plane.c index 4f9ce9ec84bdf7443a16b811504a30df674d78f7..a0de048ea8c6fe7eac8265d1cdfd3559d9bba1d6 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -83,7 +83,7 @@ static fixed_t planeheight; fixed_t yslopetab[MAXVIDHEIGHT*16]; fixed_t *yslope; -static fixed_t xoffs, yoffs; +static INT64 xoffs, yoffs; static dvector3_t slope_origin, slope_u, slope_v; static dvector3_t slope_lightu, slope_lightv; @@ -376,19 +376,25 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li visplane_t *check; unsigned hash; + float offset_xd = FixedToFloat(xoff) / FixedToFloat(xscale ? xscale : 1); + float offset_yd = FixedToFloat(yoff) / FixedToFloat(yscale ? yscale : 1); + + INT64 offset_x = offset_xd * FRACUNIT; + INT64 offset_y = offset_yd * FRACUNIT; + if (!slope) // Don't mess with this right now if a slope is involved { - xoff += FixedMul(viewx, xscale); - yoff -= FixedMul(viewy, yscale); + offset_x += viewx; + offset_y -= viewy; if (plangle != 0) { // Add the view offset, rotated by the plane angle. float ang = ANG2RAD(plangle); - float x = FixedToFloat(xoff); - float y = FixedToFloat(yoff); - xoff = FloatToFixed(x * cos(ang) + y * sin(ang)); - yoff = FloatToFixed(-x * sin(ang) + y * cos(ang)); + float x = offset_x / (float)FRACUNIT; + float y = offset_y / (float)FRACUNIT; + offset_x = (x * cos(ang) + y * sin(ang)) * FRACUNIT; + offset_y = (-x * sin(ang) + y * cos(ang)) * FRACUNIT; } } @@ -399,16 +405,19 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li float ang = ANG2RAD(polyobj->angle); float x = FixedToFloat(polyobj->centerPt.x); float y = FixedToFloat(polyobj->centerPt.y); - xoff -= FloatToFixed(x * cos(ang) + y * sin(ang)); - yoff -= FloatToFixed(x * sin(ang) - y * cos(ang)); + offset_x -= (x * cos(ang) + y * sin(ang)) * FRACUNIT; + offset_y -= (x * sin(ang) - y * cos(ang)) * FRACUNIT; } else { - xoff -= polyobj->centerPt.x; - yoff += polyobj->centerPt.y; + offset_x -= polyobj->centerPt.x; + offset_y += polyobj->centerPt.y; } } + offset_x = ((INT64)offset_x * xscale) / FRACUNIT; + offset_y = ((INT64)offset_y * yscale) / FRACUNIT; + // This appears to fix the Nimbus Ruins sky bug. if (picnum == skyflatnum && pfloor) { @@ -423,7 +432,7 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li { if (height == check->height && picnum == check->picnum && lightlevel == check->lightlevel - && xoff == check->xoffs && yoff == check->yoffs + && offset_x == check->xoffs && offset_y == check->yoffs && xscale == check->xscale && yscale == check->yscale && planecolormap == check->extra_colormap && check->viewx == viewx && check->viewy == viewy && check->viewz == viewz @@ -449,8 +458,8 @@ visplane_t *R_FindPlane(sector_t *sector, fixed_t height, INT32 picnum, INT32 li check->lightlevel = lightlevel; check->minx = vid.width; check->maxx = -1; - check->xoffs = xoff; - check->yoffs = yoff; + check->xoffs = offset_x; + check->yoffs = offset_y; check->xscale = xscale; check->yscale = yscale; check->extra_colormap = planecolormap; @@ -603,6 +612,9 @@ void R_DrawPlanes(void) visplane_t *pl; INT32 i; + if (!r_renderfloors) + return; + R_UpdatePlaneRipple(); for (i = 0; i < MAXVISPLANES; i++, pl++) @@ -626,7 +638,7 @@ static void R_DrawSkyPlane(visplane_t *pl) { INT32 texture = texturetranslation[skytexture]; - // Reset column drawer function (note: couldn't we just call walldrawerfunc directly?) + // Reset column drawer function (note: couldn't we just call colfuncs[BASEDRAWFUNC] directly?) // (that is, unless we'll need to switch drawers in future for some reason) colfunc = colfuncs[BASEDRAWFUNC]; @@ -655,13 +667,13 @@ static void R_DrawSkyPlane(visplane_t *pl) } // Returns the height of the sloped plane at (x, y) as a double -static double R_GetSlopeZAt(const pslope_t *slope, fixed_t x, fixed_t y) +static double R_GetSlopeZAt(const pslope_t *slope, INT64 x, INT64 y) { // If you want to reimplement this using just the equation constants, use this instead: // (d + a*x + b*y) * -(1.0 / c) - double px = FixedToDouble(x) - slope->dorigin.x; - double py = FixedToDouble(y) - slope->dorigin.y; + double px = (x / (double)FRACUNIT) - slope->dorigin.x; + double py = (y / (double)FRACUNIT) - slope->dorigin.y; double dist = (px * slope->dnormdir.x) + (py * slope->dnormdir.y); @@ -669,10 +681,10 @@ static double R_GetSlopeZAt(const pslope_t *slope, fixed_t x, fixed_t y) } // Sets the texture origin vector of the sloped plane. -static void R_SetSlopePlaneOrigin(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, fixed_t angle) +static void R_SetSlopePlaneOrigin(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, INT64 xoff, INT64 yoff, fixed_t angle) { - INT64 vx = (INT64)xpos + (INT64)xoff; - INT64 vy = (INT64)ypos - (INT64)yoff; + INT64 vx = (INT64)xpos + xoff; + INT64 vy = (INT64)ypos - yoff; float vxf = vx / (float)FRACUNIT; float vyf = vy / (float)FRACUNIT; @@ -699,7 +711,7 @@ void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, slope->moved = false; } - R_SetSlopePlaneOrigin(slope, xpos, ypos, zpos, xoff, yoff, angle); + R_SetSlopePlaneOrigin(slope, xpos, ypos, zpos, (INT64)xoff, (INT64)yoff, angle); height = R_GetSlopeZAt(slope, xpos, ypos); zeroheight = height - FixedToDouble(zpos); @@ -732,7 +744,7 @@ void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, } // This function calculates all of the vectors necessary for drawing a sloped and scaled plane. -void R_SetScaledSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle) +void R_SetScaledSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, INT64 xoff, INT64 yoff, angle_t angle, angle_t plangle) { double height, z_at_xy; float ang; @@ -833,9 +845,11 @@ static void CalcSlopePlaneVectors(visplane_t *pl, fixed_t xoff, fixed_t yoff) { if (!ds_fog && (pl->xscale != FRACUNIT || pl->yscale != FRACUNIT)) { + float offset_x = FixedToFloat(xoff) / FixedToFloat(pl->xscale ? pl->xscale : 1); + float offset_y = FixedToFloat(yoff) / FixedToFloat(pl->yscale ? pl->yscale : 1); R_SetScaledSlopePlane(pl->slope, pl->viewx, pl->viewy, pl->viewz, FixedDiv(FRACUNIT, pl->xscale), FixedDiv(FRACUNIT, pl->yscale), - FixedDiv(xoff, pl->xscale), FixedDiv(yoff, pl->yscale), pl->viewangle, pl->plangle); + (INT64)(offset_x * FRACUNIT), (INT64)(offset_y * FRACUNIT), pl->viewangle, pl->plangle); } else R_SetSlopePlane(pl->slope, pl->viewx, pl->viewy, pl->viewz, xoff, yoff, pl->viewangle, pl->plangle); @@ -907,7 +921,7 @@ void R_DrawSinglePlane(visplane_t *pl) if (pl->polyobj->translucency == 0 || (pl->extra_colormap && (pl->extra_colormap->flags & CMF_FOG))) light = (pl->lightlevel >> LIGHTSEGSHIFT); - else + else // TODO: 2.3: Make transparent polyobject planes always use light level light = LIGHTLEVELS-1; } else @@ -949,7 +963,7 @@ void R_DrawSinglePlane(visplane_t *pl) if ((spanfunctype == SPANDRAWFUNC_SPLAT) || (pl->extra_colormap && (pl->extra_colormap->flags & CMF_FOG))) light = (pl->lightlevel >> LIGHTSEGSHIFT); - else + else // TODO: 2.3: Make transparent FOF planes use light level instead of always being fullbright light = LIGHTLEVELS-1; } else if (pl->ffloor->fofflags & FOF_FOG) @@ -1076,6 +1090,9 @@ void R_DrawSinglePlane(visplane_t *pl) case SPANDRAWFUNC_SPLAT: spanfunctype = SPANDRAWFUNC_TILTEDSPLAT; break; + case SPANDRAWFUNC_TRANSSPLAT: + spanfunctype = SPANDRAWFUNC_TILTEDTRANSSPLAT; + break; case SPANDRAWFUNC_SOLID: spanfunctype = SPANDRAWFUNC_TILTEDSOLID; break; diff --git a/src/r_plane.h b/src/r_plane.h index 69620f25e07cadefee8242f23ad3a26a57ffbc9d..cd947750119b8446e0683bd4d62ae7b88fa9c1a7 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -48,7 +48,7 @@ typedef struct visplane_s UINT16 padbottomstart, bottom[MAXVIDWIDTH], padbottomend; INT32 high, low; // R_PlaneBounds should set these. - fixed_t xoffs, yoffs; // Scrolling flats. + INT64 xoffs, yoffs; // Scrolling flats. fixed_t xscale, yscale; sector_t *sector; @@ -85,7 +85,7 @@ void R_DrawSinglePlane(visplane_t *pl); // Calculates the slope vectors needed for tilted span drawing. void R_SetSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle); -void R_SetScaledSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, fixed_t xoff, fixed_t yoff, angle_t angle, angle_t plangle); +void R_SetScaledSlopePlane(pslope_t *slope, fixed_t xpos, fixed_t ypos, fixed_t zpos, fixed_t xs, fixed_t ys, INT64 xoff, INT64 yoff, angle_t angle, angle_t plangle); typedef struct planemgr_s { diff --git a/src/r_portal.c b/src/r_portal.c index 4d042cae38574bd54165d5b5850e8e18c5f31f33..957d574b2e9ebc3505a459adfee51c08270066ac 100644 --- a/src/r_portal.c +++ b/src/r_portal.c @@ -101,7 +101,7 @@ void Portal_ClipApply (const portal_t* portal) static portal_t* Portal_Add (const INT16 x1, const INT16 x2) { - portal_t *portal = Z_Malloc(sizeof(portal_t), PU_LEVEL, NULL); + portal_t *portal = Z_Calloc(sizeof(portal_t), PU_LEVEL, NULL); INT16 *ceilingclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL); INT16 *floorclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL); fixed_t *frontscalesave = Z_Malloc(sizeof(fixed_t)*(x2-x1 + 1), PU_LEVEL, NULL); @@ -117,7 +117,7 @@ static portal_t* Portal_Add (const INT16 x1, const INT16 x2) portal_cap->next = portal; portal_cap = portal; } - portal->next = NULL; + portal->clipline = -1; // Store clipping values so they can be restored once the portal is rendered. portal->ceilingclip = ceilingclipsave; @@ -142,11 +142,9 @@ void Portal_Remove (portal_t* portal) Z_Free(portal); } -static void Portal_GetViewpointForLine(portal_t *portal, line_t *start, line_t *dest) +static void Portal_GetViewpointForLine(portal_t *portal, line_t *start, line_t *dest, angle_t dangle) { // Offset the portal view by the linedef centers - angle_t dangle = R_PointToAngle2(0,0,dest->dx,dest->dy) - R_PointToAngle2(start->dx,start->dy,0,0); - fixed_t disttopoint; angle_t angtopoint; @@ -168,7 +166,6 @@ static void Portal_GetViewpointForLine(portal_t *portal, line_t *start, line_t * portal->viewx = dest_c.x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint); portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint); - portal->viewz = viewz + dest->frontsector->floorheight - start->frontsector->floorheight; portal->viewangle = viewangle + dangle; } @@ -189,12 +186,13 @@ void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, con line_t* start = &lines[line1]; line_t* dest = &lines[line2]; - Portal_GetViewpointForLine(portal, start, dest); + angle_t dangle = R_PointToAngle2(0,0,dest->dx,dest->dy) - R_PointToAngle2(start->dx,start->dy,0,0); + + Portal_GetViewpointForLine(portal, start, dest, dangle); + + portal->viewz = viewz + dest->frontsector->floorheight - start->frontsector->floorheight; portal->clipline = line2; - portal->is_skybox = false; - portal->is_horizon = false; - portal->horizon_sector = NULL; Portal_ClipRange(portal); @@ -317,10 +315,7 @@ static boolean Portal_AddSkybox (const visplane_t* plane) Portal_ClipVisplane(plane, portal); - portal->clipline = -1; portal->is_skybox = true; - portal->is_horizon = false; - portal->horizon_sector = NULL; Portal_GetViewpointForSkybox(portal); @@ -332,14 +327,28 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se fixed_t x, y, z; angle_t angle; + sector_t *target = secportal->target; + + fixed_t target_x = target->soundorg.x; + fixed_t target_y = target->soundorg.y; + fixed_t target_z; + + if (secportal->ceiling) + target_z = P_GetSectorCeilingZAt(target, target_x, target_y); + else + target_z = P_GetSectorFloorZAt(target, target_x, target_y); + switch (secportal->type) { case SECPORTAL_LINE: - Portal_GetViewpointForLine(portal, secportal->line.start, secportal->line.dest); + angle = secportal->line.dest->angle - secportal->line.start->angle; + Portal_GetViewpointForLine(portal, secportal->line.start, secportal->line.dest, angle); + portal->viewz = viewz; // Apparently it just works like that. Not going to question it. return; case SECPORTAL_OBJECT: - if (!secportal->mobj || P_MobjWasRemoved(secportal->mobj)) + if (P_MobjWasRemoved(secportal->mobj)) return; + portal->viewmobj = secportal->mobj; x = secportal->mobj->x; y = secportal->mobj->y; z = secportal->mobj->z; @@ -373,8 +382,9 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se return; } - fixed_t refx = secportal->origin.x - viewx; - fixed_t refy = secportal->origin.y - viewy; + fixed_t refx = target_x - viewx; + fixed_t refy = target_y - viewy; + fixed_t refz = target_z - viewz; // Rotate the X/Y to match the target angle if (angle != 0) @@ -387,7 +397,7 @@ static void Portal_GetViewpointForSecPortal(portal_t *portal, sectorportal_t *se portal->viewx = x - refx; portal->viewy = y - refy; - portal->viewz = z + viewz; + portal->viewz = z - refz; portal->viewangle = angle + viewangle; } @@ -413,11 +423,6 @@ static boolean Portal_AddSectorPortal (const visplane_t* plane) Portal_ClipVisplane(plane, portal); - portal->clipline = -1; - portal->is_horizon = false; - portal->is_skybox = false; - portal->horizon_sector = NULL; - Portal_GetViewpointForSecPortal(portal, secportal); return true; @@ -425,7 +430,7 @@ static boolean Portal_AddSectorPortal (const visplane_t* plane) /** Creates a transferred sector portal. */ -void Portal_AddTransferred (UINT32 secportalnum, const INT32 x1, const INT32 x2) +void Portal_AddTransferred (const UINT32 secportalnum, const INT32 x1, const INT32 x2) { if (secportalnum >= secportalcount) return; @@ -435,9 +440,6 @@ void Portal_AddTransferred (UINT32 secportalnum, const INT32 x1, const INT32 x2) return; portal_t* portal = Portal_Add(x1, x2); - portal->is_skybox = false; - portal->is_horizon = false; - portal->horizon_sector = NULL; if (secportal->type == SECPORTAL_SKYBOX) Portal_GetViewpointForSkybox(portal); diff --git a/src/r_portal.h b/src/r_portal.h index 2485e45a71afb5bc189525f140527c5bb03e2a21..5190885b7189c38b1b7b1b7b13f0519f1d455b0c 100644 --- a/src/r_portal.h +++ b/src/r_portal.h @@ -36,6 +36,8 @@ typedef struct portal_s boolean is_skybox; + mobj_t *viewmobj; + UINT8 pass; /**< Keeps track of the portal's recursion depth. */ INT32 clipline; /**< Optional clipline for line-based portals. */ @@ -58,7 +60,7 @@ extern INT32 portalclipstart, portalclipend; void Portal_InitList (void); void Portal_Remove (portal_t* portal); void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2); -void Portal_AddTransferred (UINT32 secportalnum, const INT32 x1, const INT32 x2); +void Portal_AddTransferred (const UINT32 secportalnum, const INT32 x1, const INT32 x2); void Portal_ClipRange (portal_t* portal); void Portal_ClipApply (const portal_t* portal); diff --git a/src/r_segs.c b/src/r_segs.c index 267c1d47d63ff32a56d6e6b0330783397dacfee3..4939d1fc8924af906c2aeff2f260e16fc06d8937 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -16,15 +16,10 @@ #include "r_sky.h" #include "r_portal.h" -#include "r_splats.h" #include "w_wad.h" #include "z_zone.h" -#include "netcode/d_netcmd.h" -#include "m_misc.h" -#include "p_local.h" // Camera... #include "p_slopes.h" -#include "console.h" // con_clipviewtop #include "taglist.h" // OPTIMIZE: closed two sided lines as single sided @@ -79,6 +74,8 @@ static fixed_t *maskedtextureheight = NULL; static fixed_t *thicksidecol = NULL; static fixed_t *invscale = NULL; +static boolean texcoltables; + //SoM: 3/23/2000: Use boom opening limit removal static size_t numopenings; static INT16 *openings, *lastopening; @@ -92,15 +89,129 @@ void R_ClearSegTables(void) curtexturecolumntable = texturecolumntable; } -// ========================================================================== -// R_RenderMaskedSegRange -// ========================================================================== - transnum_t R_GetLinedefTransTable(fixed_t alpha) { return (20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1); } +static UINT8 R_SideLightLevel(side_t *side, INT16 base_lightlevel) +{ + return max(0, min(255, side->light + + ((side->lightabsolute) ? 0 : base_lightlevel))); +} + +/* TODO: implement per-texture lighting +static UINT8 R_TopLightLevel(side_t *side, INT16 base_lightlevel) +{ + return max(0, min(255, side->light_top + + ((side->lightabsolute_top) ? 0 : R_SideLightLevel(side, base_lightlevel)))); +} + +static UINT8 R_MidLightLevel(side_t *side, INT16 base_lightlevel) +{ + return max(0, min(255, side->light_mid + + ((side->lightabsolute_mid) ? 0 : R_SideLightLevel(side, base_lightlevel)))); +} + +static UINT8 R_BottomLightLevel(side_t *side, INT16 base_lightlevel) +{ + return max(0, min(255, side->light_bottom + + ((side->lightabsolute_bottom) ? 0 : R_SideLightLevel(side, base_lightlevel)))); +} +*/ + +// If we have a multi-patch texture on a 2sided wall (rare) then we draw +// it using R_DrawColumn, else we draw it using R_DrawMaskedColumn, this +// way we don't have to store extra post_t info with each column for +// multi-patch textures. They are not normally needed as multi-patch +// textures don't have holes in it. At least not for now. +static void R_Render2sidedMultiPatchColumn(column_t *column, unsigned lengthcol) +{ + INT32 topscreen, bottomscreen; + + post_t *post = &column->posts[0]; + if (!post->length) + return; + + topscreen = sprtopscreen; + bottomscreen = topscreen + spryscale * lengthcol; + + dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS; + dc_yh = (bottomscreen-1)>>FRACBITS; + + if (windowtop != INT32_MAX && windowbottom != INT32_MAX) + { + dc_yl = ((windowtop + FRACUNIT)>>FRACBITS); + dc_yh = (windowbottom - 1)>>FRACBITS; + } + + if (dc_yh >= mfloorclip[dc_x]) + dc_yh = mfloorclip[dc_x] - 1; + if (dc_yl <= mceilingclip[dc_x]) + dc_yl = mceilingclip[dc_x] + 1; + + if (dc_yl >= vid.height || dc_yh < 0) + return; + + if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0) + { + dc_source = column->pixels + post->data_offset; + dc_postlength = post->length; + + if (colfunc == colfuncs[BASEDRAWFUNC]) + (colfuncs[COLDRAWFUNC_TWOSMULTIPATCH])(); + else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) + (colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS])(); + else + colfunc(); + } +} + +static void R_RenderFlipped2sidedMultiPatchColumn(column_t *column, unsigned lengthcol) +{ + INT32 topscreen, bottomscreen; + + void (*localcolfunc)(void); + + post_t *post = &column->posts[0]; + if (!post->length) + return; + + topscreen = sprtopscreen; + bottomscreen = topscreen + spryscale * lengthcol; + + dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS; + dc_yh = (bottomscreen-1)>>FRACBITS; + + if (windowtop != INT32_MAX && windowbottom != INT32_MAX) + { + dc_yl = ((windowtop + FRACUNIT)>>FRACBITS); + dc_yh = (windowbottom - 1)>>FRACBITS; + } + + if (dc_yh >= mfloorclip[dc_x]) + dc_yh = mfloorclip[dc_x] - 1; + if (dc_yl <= mceilingclip[dc_x]) + dc_yl = mceilingclip[dc_x] + 1; + + if (dc_yl >= vid.height || dc_yh < 0) + return; + + if (dc_yl <= dc_yh && dc_yh < vid.height && dc_yh > 0) + { + dc_postlength = post->length; + + if (colfunc == colfuncs[BASEDRAWFUNC]) + localcolfunc = colfuncs[COLDRAWFUNC_TWOSMULTIPATCH]; + else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) + localcolfunc = colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS]; + else + localcolfunc = colfunc; + + R_DrawFlippedPost(column->pixels + post->data_offset, post->length, localcolfunc); + } +} + void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) { size_t pindex; @@ -115,8 +226,13 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) INT32 times, repeats; INT64 overflow_test; INT32 range; + UINT8 vertflip; unsigned lengthcol; + fixed_t wall_scaley; + fixed_t scalestep; + fixed_t scale1; + // Calculate light table. // Use different light tables // for horizontal / vertical / diagonal. Diagonal? @@ -164,9 +280,17 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) colfunc = colfuncs[COLDRAWFUNC_FUZZY]; } - fixed_t wall_scaley = sidedef->scaley_mid; - fixed_t scalestep = FixedDiv(ds->scalestep, wall_scaley); - fixed_t scale1 = FixedDiv(ds->scale1, wall_scaley); + vertflip = textures[texnum]->flip & 2; + + wall_scaley = sidedef->scaley_mid; + if (wall_scaley < 0) + { + wall_scaley = -wall_scaley; + vertflip = !vertflip; + } + + scalestep = FixedDiv(ds->scalestep, wall_scaley); + scale1 = FixedDiv(ds->scale1, wall_scaley); range = max(ds->x2-ds->x1, 1); rw_scalestep = scalestep; @@ -175,7 +299,16 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) // Texture must be cached R_CheckTextureCache(texnum); - if (textures[texnum]->flip & 2) // vertically flipped? + // handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures + // are not stored per-column with post info in SRB2 + if (!textures[texnum]->transparency) + { + if (vertflip) // vertically flipped? + colfunc_2s = R_RenderFlipped2sidedMultiPatchColumn; + else + colfunc_2s = R_Render2sidedMultiPatchColumn; + } + else if (vertflip) // vertically flipped? colfunc_2s = R_DrawFlippedMaskedColumn; else colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture @@ -187,7 +320,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if (frontsector->numlights) { dc_numlights = frontsector->numlights; - if (dc_numlights >= dc_maxlights) + if (dc_numlights > dc_maxlights) { dc_maxlights = dc_numlights; dc_lightlist = Z_Realloc(dc_lightlist, sizeof (*dc_lightlist) * dc_maxlights, PU_STATIC, NULL); @@ -217,7 +350,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY]) || (rlight->flags & FOF_FOG) || (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG))) - lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); + lightnum = R_SideLightLevel(curline->sidedef, rlight->lightlevel) >> LIGHTSEGSHIFT; else lightnum = LIGHTLEVELS - 1; @@ -235,7 +368,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) { if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY]) || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))) - lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); + lightnum = R_SideLightLevel(curline->sidedef, frontsector->lightlevel) >> LIGHTSEGSHIFT; else lightnum = LIGHTLEVELS - 1; @@ -343,7 +476,6 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) { lighttable_t **xwalllights; - sprbotscreen = INT32_MAX; sprtopscreen = windowtop = (centeryfrac - FixedMul(dc_texturemid, spryscale)); realbot = FixedMul(textureheight[texnum], spryscale) + sprtopscreen; @@ -437,23 +569,75 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) } // Loop through R_DrawMaskedColumn calls +static fixed_t repeatscroll = 0; + static void R_DrawRepeatMaskedColumn(column_t *col, unsigned lengthcol) { - while (sprtopscreen < sprbotscreen) { + fixed_t topscreen = sprtopscreen; + fixed_t bottomscreen = sprbotscreen; + + fixed_t texheight = dc_texheight*spryscale; + + fixed_t scroll = -repeatscroll; + if (scroll < 0) + { + scroll = -FixedMul((abs(scroll) % (dc_texheight*FRACUNIT)), spryscale); + bottomscreen += texheight; // Draw an extra time + } + else if (scroll) + { + scroll = FixedMul(scroll % (dc_texheight*FRACUNIT), spryscale); + topscreen -= texheight; // Draw an extra time + } + + while (topscreen < bottomscreen) + { + sprtopscreen = topscreen + scroll; + R_DrawMaskedColumn(col, lengthcol); - if ((INT64)sprtopscreen + dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow - sprtopscreen = INT32_MAX; - else - sprtopscreen += dc_texheight*spryscale; + + if ((INT64)sprtopscreen + (INT64)dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow + break; + + topscreen += texheight; } + + sprtopscreen = sprbotscreen; } static void R_DrawRepeatFlippedMaskedColumn(column_t *col, unsigned lengthcol) { - do { + fixed_t topscreen = sprtopscreen; + fixed_t bottomscreen = sprbotscreen; + + fixed_t texheight = dc_texheight*spryscale; + + fixed_t scroll = -repeatscroll; + if (scroll < 0) + { + scroll = -FixedMul((abs(scroll) % (dc_texheight*FRACUNIT)), spryscale); + bottomscreen += texheight; // Draw an extra time + } + else if (scroll) + { + scroll = FixedMul(scroll % (dc_texheight*FRACUNIT), spryscale); + topscreen -= texheight; // Draw an extra time + } + + while (topscreen < bottomscreen) + { + sprtopscreen = topscreen + scroll; + sprbotscreen = bottomscreen + scroll; + R_DrawFlippedMaskedColumn(col, lengthcol); - sprtopscreen += dc_texheight*spryscale; - } while (sprtopscreen < sprbotscreen); + + if ((INT64)sprtopscreen + (INT64)dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow + break; + + topscreen += texheight; + } + + sprtopscreen = sprbotscreen; } // Returns true if a fake floor is translucent. @@ -469,6 +653,11 @@ static boolean R_IsFFloorTranslucent(visffloor_t *pfloor) return false; } +static fixed_t R_GetSlopeTextureSlide(pslope_t *slope, angle_t lineangle) +{ + return FixedMul(slope->zdelta, FINECOSINE((lineangle-slope->xydirection)>>ANGLETOFINESHIFT)); +} + // // R_RenderThickSideRange // Renders all the thick sides in the given range. @@ -484,9 +673,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) sector_t tempsec; INT32 templight; INT32 i, p; - fixed_t bottombounds = viewheight << FRACBITS; - fixed_t topbounds = (con_clipviewtop - 1) << FRACBITS; - fixed_t offsetvalue; lightlist_t *light; r_lightlist_t *rlight; INT32 range; @@ -495,13 +681,17 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) INT64 top_frac, top_step, bottom_frac, bottom_step; // skew FOF walls with slopes? fixed_t ffloortextureslide = 0; - INT32 oldx = -1; + fixed_t oldtexturecolumn = -1; fixed_t left_top, left_bottom; // needed here for slope skewing pslope_t *skewslope = NULL; boolean do_texture_skew; boolean dont_peg_bottom; + fixed_t wall_offsetx; fixed_t wall_scalex, wall_scaley; + UINT8 vertflip; unsigned lengthcol; + boolean fog = false; + boolean fuzzy = false; void (*colfunc_2s) (column_t *, unsigned); @@ -513,15 +703,11 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) curline = ds->curline; backsector = pfloor->target; frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector; - sidedef = &sides[pfloor->master->sidenum[0]]; - - colfunc = colfuncs[BASEDRAWFUNC]; + sidedef = R_GetFFloorSide(curline->linedef, pfloor, pfloor->target); if (pfloor->master->flags & ML_TFERLINE) { - size_t linenum = curline->linedef-backsector->lines[0]; - line_t *newline = pfloor->master->frontsector->lines[0] + linenum; - sidedef = &sides[newline->sidenum[0]]; + line_t *newline = R_GetFFloorLine(curline->linedef, pfloor, pfloor->target); do_texture_skew = newline->flags & ML_SKEWTD; dont_peg_bottom = newline->flags & ML_DONTPEGBOTTOM; } @@ -532,10 +718,11 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) } texnum = R_GetTextureNum(sidedef->midtexture); + vertflip = textures[texnum]->flip & 2; if (pfloor->fofflags & FOF_TRANSLUCENT) { - boolean fuzzy = true; + fuzzy = true; // Hacked up support for alpha value in software mode Tails 09-24-2002 // ...unhacked by toaster 04-01-2021, re-hacked a little by sphere 19-11-2021 @@ -548,17 +735,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) else if (!(dc_transmap = R_GetTranslucencyTable(trans)) || trans == 0) fuzzy = false; // Opaque } - - if (fuzzy) - colfunc = colfuncs[COLDRAWFUNC_FUZZY]; } else if (pfloor->fofflags & FOF_FOG) + { colfunc = colfuncs[COLDRAWFUNC_FOG]; + fog = true; + } range = max(ds->x2-ds->x1, 1); - //SoM: Moved these up here so they are available for my lightlist calculations - rw_scalestep = ds->scalestep; - spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; dc_numlights = 0; if (frontsector->numlights) @@ -640,9 +824,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // Check if the current light effects the colormap/lightlevel if (pfloor->fofflags & FOF_FOG) - rlight->lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT); + rlight->lightnum = R_SideLightLevel(curline->sidedef, pfloor->master->frontsector->lightlevel) >> LIGHTSEGSHIFT; else - rlight->lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); + rlight->lightnum = R_SideLightLevel(curline->sidedef, rlight->lightlevel) >> LIGHTSEGSHIFT; if (pfloor->fofflags & FOF_FOG || rlight->flags & FOF_FOG || (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG))) ; @@ -660,18 +844,17 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { // Get correct light level! if ((frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))) - lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); - else if (pfloor->fofflags & FOF_FOG) - lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT); - else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) + lightnum = R_SideLightLevel(curline->sidedef, frontsector->lightlevel) >> LIGHTSEGSHIFT; + else if (fog) + lightnum = R_SideLightLevel(curline->sidedef, pfloor->master->frontsector->lightlevel) >> LIGHTSEGSHIFT; + else if (fuzzy) lightnum = LIGHTLEVELS-1; else - lightnum = R_FakeFlat(frontsector, &tempsec, &templight, &templight, false) - ->lightlevel >> LIGHTSEGSHIFT; + lightnum = R_SideLightLevel(curline->sidedef, R_FakeFlat(frontsector, &tempsec, &templight, &templight, false)->lightlevel) >> LIGHTSEGSHIFT; if (pfloor->fofflags & FOF_FOG || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))); else if (curline->v1->y == curline->v2->y) - lightnum--; + lightnum--; else if (curline->v1->x == curline->v2->x) lightnum++; @@ -685,18 +868,33 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) wall_scalex = FixedDiv(FRACUNIT, sidedef->scalex_mid); wall_scaley = sidedef->scaley_mid; + if (wall_scaley < 0) + { + wall_scaley = -wall_scaley; + vertflip = !vertflip; + } + + //SoM: Moved these up here so they are available for my lightlist calculations + // Lactozilla: Moved them back down + // This uses floating point math now, because the fixed-point imprecisions + // become more severe the bigger the texture is scaled. + double dwall_scaley = FixedToDouble(wall_scaley); + double scalestep = FixedToDouble(ds->scalestep) / dwall_scaley; + double yscale = (FixedToDouble(ds->scale1) + (x1 - ds->x1)*scalestep) / dwall_scaley; thicksidecol = ffloortexturecolumn; + wall_offsetx = ds->offsetx + sidedef->offsetx_mid; + if (wall_scalex == FRACUNIT) { for (INT32 x = x1; x <= x2; x++) - thicksidecol[x] = ds->thicksidecol[x] + ds->offsetx; + thicksidecol[x] = ds->thicksidecol[x]; } else { for (INT32 x = x1; x <= x2; x++) - thicksidecol[x] = FixedDiv(ds->thicksidecol[x], wall_scalex) + ds->offsetx; + thicksidecol[x] = FixedDiv(ds->thicksidecol[x], wall_scalex); } mfloorclip = ds->sprbottomclip; @@ -715,7 +913,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) else dc_texturemid = FixedMul(*pfloor->topheight - viewz, wall_scaley); - offsetvalue = sidedef->rowoffset + sidedef->offsety_mid; + repeatscroll = sidedef->rowoffset + sidedef->offsety_mid; if (dont_peg_bottom) { @@ -725,24 +923,33 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) dc_texturemid = FixedMul(left_bottom, wall_scaley); } else - offsetvalue -= FixedMul(*pfloor->topheight - *pfloor->bottomheight, wall_scaley); + repeatscroll -= FixedMul(*pfloor->topheight - *pfloor->bottomheight, wall_scaley); } if (skewslope) { angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y); - ffloortextureslide = FixedMul(skewslope->zdelta, FINECOSINE((lineangle-skewslope->xydirection)>>ANGLETOFINESHIFT)); + ffloortextureslide = FixedMul(R_GetSlopeTextureSlide(skewslope, lineangle), wall_scaley); } - dc_texturemid += offsetvalue; + dc_texturemid += repeatscroll; // Texture must be cached R_CheckTextureCache(texnum); - if (textures[texnum]->flip & 2) // vertically flipped? + // handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures + // are not stored per-column with post info in SRB2 + if (!textures[texnum]->transparency) + { + if (vertflip) // vertically flipped? + colfunc_2s = R_RenderFlipped2sidedMultiPatchColumn; + else + colfunc_2s = R_Render2sidedMultiPatchColumn; + } + else if (vertflip) // vertically flipped? colfunc_2s = R_DrawRepeatFlippedMaskedColumn; else - colfunc_2s = R_DrawRepeatMaskedColumn; // render the usual 2sided single-patch packed texture + colfunc_2s = R_DrawRepeatMaskedColumn; lengthcol = textures[texnum]->height; @@ -773,9 +980,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // skew FOF walls if (ffloortextureslide) { - if (oldx != -1) - dc_texturemid += FixedMul(ffloortextureslide, thicksidecol[oldx]-thicksidecol[dc_x]); - oldx = dc_x; + if (oldtexturecolumn != -1) + dc_texturemid += FixedMul(ffloortextureslide, oldtexturecolumn-ds->thicksidecol[dc_x]); + oldtexturecolumn = ds->thicksidecol[dc_x]; } // Calculate bounds @@ -787,11 +994,13 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) else if (bottom_frac > (INT64)CLAMPMIN) sprbotscreen = windowbottom = (fixed_t)bottom_frac; else sprbotscreen = windowbottom = CLAMPMIN; + fixed_t bottomclip = sprbotscreen; + top_frac += top_step; bottom_frac += bottom_step; // SoM: If column is out of range, why bother with it?? - if (windowbottom < topbounds || windowtop > bottombounds) + if (windowbottom < 0 || windowtop > (viewheight << FRACBITS)) { if (dc_numlights) { @@ -803,14 +1012,40 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) rlight->botheight += rlight->botheightstep; } } - spryscale += rw_scalestep; + yscale += scalestep; continue; } - dc_iscale = FixedMul(0xffffffffu / (unsigned)spryscale, wall_scaley); - // Get data for the column - col = R_GetColumn(texnum, (thicksidecol[dc_x] >> FRACBITS)); + col = R_GetColumn(texnum, ((thicksidecol[dc_x] + wall_offsetx) >> FRACBITS)); + + spryscale = DoubleToFixed(yscale); + + // Eh. I tried fixing the scaling artifacts but it still wasn't perfect. + // So this checks if the column has gaps in it or not, and if it does, uses a version of the column drawers + // that prevents the artifacts from being visible. + // Note that if rendering fog then none of this matters because there's no texture mapping to be done + if (!fog) + { + dc_iscale = 0xffffffffu / (unsigned)spryscale; + + // Column has a single post and it matches the texture height, use regular column drawers + if (col->num_posts == 1 && col->posts[0].topdelta == 0 && col->posts[0].length == (unsigned)dc_texheight) + { + if (fuzzy) + colfunc = colfuncs[COLDRAWFUNC_FUZZY]; + else + colfunc = colfuncs[BASEDRAWFUNC]; + } + else + { + // Otherwise use column drawers with extra checks + if (fuzzy) + colfunc = colfuncs[COLDRAWFUNC_CLAMPEDTRANS]; + else + colfunc = colfuncs[COLDRAWFUNC_CLAMPED]; + } + } // SoM: New code does not rely on R_DrawColumnShadowed_8 which // will (hopefully) put less strain on the stack. @@ -819,14 +1054,13 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) lighttable_t **xwalllights; fixed_t height; fixed_t bheight = 0; - INT32 solid = 0; - INT32 lighteffect = 0; + boolean lighteffect = false; for (i = 0; i < dc_numlights; i++) { // Check if the current light effects the colormap/lightlevel rlight = &dc_lightlist[i]; - lighteffect = !(dc_lightlist[i].flags & FOF_NOSHADE); + lighteffect = !(rlight->flags & FOF_NOSHADE); if (lighteffect) { lightnum = rlight->lightnum; @@ -859,11 +1093,11 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) } } - solid = 0; // don't carry over solid-cutting flag from the previous light - // Check if the current light can cut the current 3D floor. + boolean solid = false; + if (rlight->flags & FOF_CUTSOLIDS && !(pfloor->fofflags & FOF_EXTRA)) - solid = 1; + solid = true; else if (rlight->flags & FOF_CUTEXTRA && pfloor->fofflags & FOF_EXTRA) { if (rlight->flags & FOF_EXTRA) @@ -871,13 +1105,13 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // The light is from an extra 3D floor... Check the flags so // there are no undesired cuts. if ((rlight->flags & (FOF_FOG|FOF_SWIMMABLE)) == (pfloor->fofflags & (FOF_FOG|FOF_SWIMMABLE))) - solid = 1; + solid = true; } else - solid = 1; + solid = true; } else - solid = 0; + solid = false; height = rlight->height; rlight->height += rlight->heightstep; @@ -893,14 +1127,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (lighteffect) dc_colormap = rlight->rcolormap; if (solid && windowtop < bheight) - windowtop = bheight; + sprtopscreen = windowtop = bheight; continue; } - windowbottom = height; - if (windowbottom >= sprbotscreen) + sprbotscreen = windowbottom = height; + if (windowbottom >= bottomclip) { - windowbottom = sprbotscreen; + sprbotscreen = windowbottom = bottomclip; // draw the texture colfunc_2s (col, lengthcol); for (i++; i < dc_numlights; i++) @@ -918,15 +1152,16 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) windowtop = bheight; else windowtop = windowbottom + 1; + sprtopscreen = windowtop; if (lighteffect) dc_colormap = rlight->rcolormap; } - windowbottom = sprbotscreen; + sprbotscreen = windowbottom = bottomclip; // draw the texture, if there is any space left if (windowtop < windowbottom) colfunc_2s (col, lengthcol); - spryscale += rw_scalestep; + yscale += scalestep; continue; } @@ -945,7 +1180,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // draw the texture colfunc_2s (col, lengthcol); - spryscale += rw_scalestep; + yscale += scalestep; } colfunc = colfuncs[BASEDRAWFUNC]; @@ -984,36 +1219,77 @@ static boolean R_FFloorCanClip(visffloor_t *pfloor) #define HEIGHTBITS 12 #define HEIGHTUNIT (1<<HEIGHTBITS) +static void R_DrawRegularWall(UINT8 *source, INT32 height) +{ + dc_source = source; + dc_texheight = height; + colfunc(); +} -//profile stuff --------------------------------------------------------- -//#define TIMING -#ifdef TIMING -#include "p5prof.h" -INT64 mycount; -INT64 mytotal = 0; -UINT32 nombre = 100000; -//static char runtest[10][80]; -#endif -//profile stuff --------------------------------------------------------- +static void R_DrawFlippedWall(UINT8 *source, INT32 height) +{ + dc_texheight = height; + R_DrawFlippedPost(source, (unsigned)height, colfunc); +} + +static void R_DrawNoWall(UINT8 *source, INT32 height) +{ + (void)source; + (void)height; +} static void R_RenderSegLoop (void) { angle_t angle; fixed_t textureoffset; - size_t pindex; - INT32 yl; - INT32 yh; + size_t pindex; + INT32 yl; + INT32 yh; - INT32 mid; + INT32 mid; fixed_t texturecolumn = 0; fixed_t toptexturecolumn = 0; fixed_t bottomtexturecolumn = 0; fixed_t oldtexturecolumn = -1; fixed_t oldtexturecolumn_top = -1; fixed_t oldtexturecolumn_bottom = -1; - INT32 top; - INT32 bottom; - INT32 i; + INT32 top; + INT32 bottom; + INT32 i; + + fixed_t topscaley = rw_toptexturescaley; + fixed_t midscaley = rw_midtexturescaley; + fixed_t bottomscaley = rw_bottomtexturescaley; + + void (*drawtop)(UINT8 *, INT32) = R_DrawRegularWall; + void (*drawmiddle)(UINT8 *, INT32) = R_DrawRegularWall; + void (*drawbottom)(UINT8 *, INT32) = R_DrawRegularWall; + + if (dc_numlights) + colfunc = colfuncs[COLDRAWFUNC_SHADOWED]; + + if (toptexture && topscaley < 0) + { + topscaley = -topscaley; + drawtop = R_DrawFlippedWall; + } + if (midtexture && midscaley < 0) + { + midscaley = -midscaley; + drawmiddle = R_DrawFlippedWall; + } + if (bottomtexture && bottomscaley < 0) + { + bottomscaley = -bottomscaley; + drawbottom = R_DrawFlippedWall; + } + + if (!r_renderwalls) + { + drawtop = R_DrawNoWall; + drawmiddle = R_DrawNoWall; + drawbottom = R_DrawNoWall; + } if (midtexture) R_CheckTextureCache(midtexture); @@ -1022,6 +1298,9 @@ static void R_RenderSegLoop (void) if (bottomtexture) R_CheckTextureCache(bottomtexture); + if (dc_numlights) + colfunc = colfuncs[COLDRAWFUNC_SHADOWED]; + for (; rw_x < rw_stopx; rw_x++) { // mark floor / ceiling areas @@ -1209,7 +1488,7 @@ static void R_RenderSegLoop (void) for (i = 0; i < dc_numlights; i++) { INT32 lightnum; - lightnum = (dc_lightlist[i].lightlevel >> LIGHTSEGSHIFT); + lightnum = R_SideLightLevel(curline->sidedef, dc_lightlist[i].lightlevel) >> LIGHTSEGSHIFT; if (dc_lightlist[i].extra_colormap) ; @@ -1234,8 +1513,6 @@ static void R_RenderSegLoop (void) dc_lightlist[i].rcolormap = dc_lightlist[i].extra_colormap->colormap + (xwalllights[pindex] - colormaps); else dc_lightlist[i].rcolormap = xwalllights[pindex]; - - colfunc = colfuncs[COLDRAWFUNC_SHADOWED]; } } @@ -1252,24 +1529,9 @@ static void R_RenderSegLoop (void) dc_yl = yl; dc_yh = yh; dc_texturemid = rw_midtexturemid; - dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, rw_midtexturescaley); - dc_source = R_GetColumn(midtexture, offset >> FRACBITS)->pixels; dc_texheight = textureheight[midtexture]>>FRACBITS; - - //profile stuff --------------------------------------------------------- -#ifdef TIMING - ProfZeroTimer(); -#endif - colfunc(); -#ifdef TIMING - RDMSR(0x10,&mycount); - mytotal += mycount; //64bit add - - if (nombre--==0) - I_Error("R_DrawColumn CPU Spy reports: 0x%d %d\n", *((INT32 *)&mytotal+1), - (INT32)mytotal); -#endif - //profile stuff --------------------------------------------------------- + dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, midscaley); + drawmiddle(R_GetColumn(midtexture, offset >> FRACBITS)->pixels, dc_texheight); // dont draw anything more for this column, since // a midtexture blocks the view @@ -1321,10 +1583,9 @@ static void R_RenderSegLoop (void) dc_yl = yl; dc_yh = mid; dc_texturemid = rw_toptexturemid; - dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, rw_toptexturescaley); - dc_source = R_GetColumn(toptexture, offset >> FRACBITS)->pixels; dc_texheight = textureheight[toptexture]>>FRACBITS; - colfunc(); + dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, topscaley); + drawtop(R_GetColumn(toptexture, offset >> FRACBITS)->pixels, dc_texheight); ceilingclip[rw_x] = (INT16)mid; } else if (!rw_ceilingmarked) // entirely off top of screen @@ -1334,8 +1595,8 @@ static void R_RenderSegLoop (void) ceilingclip[rw_x] = topclip; if (oldtexturecolumn_top != -1) - rw_toptexturemid += FixedMul(rw_toptextureslide, oldtexturecolumn_top-toptexturecolumn); - oldtexturecolumn_top = toptexturecolumn; + rw_toptexturemid += FixedMul(rw_toptextureslide, oldtexturecolumn_top-textureoffset); + oldtexturecolumn_top = textureoffset; } else if (markceiling && (!rw_ceilingmarked)) // no top wall ceilingclip[rw_x] = topclip; @@ -1369,10 +1630,9 @@ static void R_RenderSegLoop (void) dc_yl = mid; dc_yh = yh; dc_texturemid = rw_bottomtexturemid; - dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, rw_bottomtexturescaley); - dc_source = R_GetColumn(bottomtexture, offset >> FRACBITS)->pixels; dc_texheight = textureheight[bottomtexture]>>FRACBITS; - colfunc(); + dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, bottomscaley); + drawbottom(R_GetColumn(bottomtexture, offset >> FRACBITS)->pixels, dc_texheight); floorclip[rw_x] = (INT16)mid; } else if (!rw_floormarked) // entirely off bottom of screen @@ -1382,8 +1642,8 @@ static void R_RenderSegLoop (void) floorclip[rw_x] = bottomclip; if (oldtexturecolumn_bottom != -1) - rw_bottomtexturemid += FixedMul(rw_bottomtextureslide, oldtexturecolumn_bottom-bottomtexturecolumn); - oldtexturecolumn_bottom = bottomtexturecolumn; + rw_bottomtexturemid += FixedMul(rw_bottomtextureslide, oldtexturecolumn_bottom-textureoffset); + oldtexturecolumn_bottom = textureoffset; } else if (markfloor && (!rw_floormarked)) // no bottom wall floorclip[rw_x] = bottomclip; @@ -1407,11 +1667,14 @@ static void R_RenderSegLoop (void) { if (oldtexturecolumn != -1) { - rw_midtexturemid += FixedMul(rw_midtextureslide, oldtexturecolumn-texturecolumn); - rw_midtextureback += FixedMul(rw_midtexturebackslide, oldtexturecolumn-texturecolumn); + INT32 diff = oldtexturecolumn-textureoffset; + if (rw_invmidtexturescalex < 0) + diff = -diff; + rw_midtexturemid += FixedMul(rw_midtextureslide, diff); + rw_midtextureback += FixedMul(rw_midtexturebackslide, diff); } - oldtexturecolumn = texturecolumn; + oldtexturecolumn = textureoffset; } if (invscale) @@ -1505,7 +1768,7 @@ static void R_AllocClippingTables(size_t range) static void R_AllocTextureColumnTables(size_t range) { size_t pos = curtexturecolumntable - texturecolumntable; - size_t need = range * 3; + size_t need = range * 4; if (pos + need < texturecolumntablesize) return; @@ -1526,13 +1789,46 @@ static void R_AllocTextureColumnTables(size_t range) for (drawseg_t *ds = drawsegs; ds < ds_p; ds++) { // Check if it's in range of the tables - if (ds->maskedtexturecol + ds->x1 >= oldtable && ds->maskedtexturecol + ds->x1 <= oldlast) - ds->maskedtexturecol = (ds->maskedtexturecol - oldtable) + texturecolumntable; - if (ds->thicksidecol + ds->x1 >= oldtable && ds->thicksidecol + ds->x1 <= oldlast) - ds->thicksidecol = (ds->thicksidecol - oldtable) + texturecolumntable; - if (ds->invscale + ds->x1 >= oldtable && ds->invscale + ds->x1 <= oldlast) - ds->invscale = (ds->invscale - oldtable) + texturecolumntable; +#define CHECK(which) \ + if (which + ds->x1 >= oldtable && which + ds->x1 <= oldlast) \ + which = (which - oldtable) + texturecolumntable + + CHECK(ds->maskedtexturecol); + CHECK(ds->maskedtextureheight); + CHECK(ds->thicksidecol); + CHECK(ds->invscale); + +#undef CHECK + } +} + +// +// R_ScaleFromGlobalAngle +// Returns the texture mapping scale for the current line (horizontal span) +// at the given angle. +// rw_distance must be calculated first. +// +// killough 5/2/98: reformatted, cleaned up +// +// note: THIS IS USED ONLY FOR WALLS! +static fixed_t R_ScaleFromGlobalAngle(angle_t visangle) +{ + angle_t anglea = ANGLE_90 + (visangle-viewangle); + angle_t angleb = ANGLE_90 + (visangle-rw_normalangle); + fixed_t den = FixedMul(rw_distance, FINESINE(anglea>>ANGLETOFINESHIFT)); + // proff 11/06/98: Changed for high-res + fixed_t num = FixedMul(projectiony, FINESINE(angleb>>ANGLETOFINESHIFT)); + + if (den > num>>16) + { + num = FixedDiv(num, den); + if (num > 64*FRACUNIT) + return 64*FRACUNIT; + if (num < 256) + return 256; + return num; } + return 64*FRACUNIT; } // @@ -1706,11 +2002,14 @@ void R_StoreWallRange(INT32 start, INT32 stop) midtexture = toptexture = bottomtexture = maskedtexture = 0; ds_p->maskedtexturecol = NULL; + ds_p->maskedtextureheight = NULL; ds_p->numthicksides = numthicksides = 0; ds_p->thicksidecol = NULL; ds_p->invscale = NULL; ds_p->tsilheight = 0; + texcoltables = false; + numbackffloors = 0; for (i = 0; i < MAXFFLOORS; i++) @@ -1736,16 +2035,19 @@ void R_StoreWallRange(INT32 start, INT32 stop) angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y); if (frontsector->f_slope) - floorfrontslide = FixedMul(frontsector->f_slope->zdelta, FINECOSINE((lineangle-frontsector->f_slope->xydirection)>>ANGLETOFINESHIFT)); + floorfrontslide = R_GetSlopeTextureSlide(frontsector->f_slope, lineangle); if (frontsector->c_slope) - ceilingfrontslide = FixedMul(frontsector->c_slope->zdelta, FINECOSINE((lineangle-frontsector->c_slope->xydirection)>>ANGLETOFINESHIFT)); + ceilingfrontslide = R_GetSlopeTextureSlide(frontsector->c_slope, lineangle); - if (backsector && backsector->f_slope) - floorbackslide = FixedMul(backsector->f_slope->zdelta, FINECOSINE((lineangle-backsector->f_slope->xydirection)>>ANGLETOFINESHIFT)); + if (backsector) + { + if (backsector->f_slope) + floorbackslide = R_GetSlopeTextureSlide(backsector->f_slope, lineangle); - if (backsector && backsector->c_slope) - ceilingbackslide = FixedMul(backsector->c_slope->zdelta, FINECOSINE((lineangle-backsector->c_slope->xydirection)>>ANGLETOFINESHIFT)); + if (backsector->c_slope) + ceilingbackslide = R_GetSlopeTextureSlide(backsector->c_slope, lineangle); + } } rw_midtexturescalex = sidedef->scalex_mid; @@ -1761,26 +2063,27 @@ void R_StoreWallRange(INT32 start, INT32 stop) fixed_t rowoffset = sidedef->rowoffset + sidedef->offsety_mid; fixed_t texheight = textureheight[midtexture]; + fixed_t scaley = abs(rw_midtexturescaley); if (rw_midtexturescaley > 0) { if (linedef->flags & ML_NOSKEW) { if (linedef->flags & ML_DONTPEGBOTTOM) - rw_midtexturemid = FixedMul(frontsector->floorheight - viewz, rw_midtexturescaley) + texheight; + rw_midtexturemid = FixedMul(frontsector->floorheight - viewz, scaley) + texheight; else - rw_midtexturemid = FixedMul(frontsector->ceilingheight - viewz, rw_midtexturescaley); + rw_midtexturemid = FixedMul(frontsector->ceilingheight - viewz, scaley); } else if (linedef->flags & ML_DONTPEGBOTTOM) { - rw_midtexturemid = FixedMul(worldbottom, rw_midtexturescaley) + texheight; - rw_midtextureslide = floorfrontslide; + rw_midtexturemid = FixedMul(worldbottom, scaley) + texheight; + rw_midtextureslide = FixedMul(floorfrontslide, scaley); } else { // top of texture at top - rw_midtexturemid = FixedMul(worldtop, rw_midtexturescaley); - rw_midtextureslide = ceilingfrontslide; + rw_midtexturemid = FixedMul(worldtop, scaley); + rw_midtextureslide = FixedMul(ceilingfrontslide, scaley); } } else @@ -1791,20 +2094,20 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (linedef->flags & ML_NOSKEW) { if (linedef->flags & ML_DONTPEGBOTTOM) - rw_midtexturemid = FixedMul(frontsector->floorheight - viewz, rw_midtexturescaley); + rw_midtexturemid = FixedMul(frontsector->floorheight - viewz, scaley); else - rw_midtexturemid = FixedMul(frontsector->ceilingheight - viewz, rw_midtexturescaley) + texheight; + rw_midtexturemid = FixedMul(frontsector->ceilingheight - viewz, scaley) + texheight; } else if (linedef->flags & ML_DONTPEGBOTTOM) { - rw_midtexturemid = FixedMul(worldbottom, rw_midtexturescaley); - rw_midtextureslide = floorfrontslide; + rw_midtexturemid = FixedMul(worldbottom, scaley); + rw_midtextureslide = FixedMul(floorfrontslide, scaley); } else { // top of texture at top - rw_midtexturemid = FixedMul(worldtop, rw_midtexturescaley) + texheight; - rw_midtextureslide = ceilingfrontslide; + rw_midtexturemid = FixedMul(worldtop, scaley) + texheight; + rw_midtextureslide = FixedMul(ceilingfrontslide, scaley); } } @@ -2013,15 +2316,16 @@ void R_StoreWallRange(INT32 start, INT32 stop) { // top of texture at top rw_toptexturemid = worldtop; - rw_toptextureslide = ceilingfrontslide; + rw_toptextureslide = FixedMul(ceilingfrontslide, abs(rw_toptexturescaley)); } else { rw_toptexturemid = worldhigh + texheight; - rw_toptextureslide = ceilingbackslide; + rw_toptextureslide = FixedMul(ceilingbackslide, abs(rw_toptexturescaley)); } - rw_toptexturemid = FixedMul(rw_toptexturemid, rw_toptexturescaley); + rw_toptexturemid = FixedMul(rw_toptexturemid, abs(rw_toptexturescaley)); + rw_toptexturemid += toprowoffset; } // check BOTTOM TEXTURE @@ -2052,24 +2356,24 @@ void R_StoreWallRange(INT32 start, INT32 stop) // bottom of texture at bottom // top of texture at top rw_bottomtexturemid = worldbottom; - rw_bottomtextureslide = floorfrontslide; + rw_bottomtextureslide = FixedMul(floorfrontslide, abs(rw_bottomtexturescaley)); } else { // top of texture at top rw_bottomtexturemid = worldlow; - rw_bottomtextureslide = floorbackslide; + rw_bottomtextureslide = FixedMul(floorbackslide, abs(rw_bottomtexturescaley)); } - rw_bottomtexturemid = FixedMul(rw_bottomtexturemid, rw_bottomtexturescaley); + rw_bottomtexturemid = FixedMul(rw_bottomtexturemid, abs(rw_bottomtexturescaley)); + rw_bottomtexturemid += botrowoffset; } - rw_toptexturemid += toprowoffset; - rw_bottomtexturemid += botrowoffset; - // allocate space for masked texture tables R_AllocTextureColumnTables(rw_stopx - start); + texcoltables = true; + if (frontsector && backsector && !Tag_Compare(&frontsector->tags, &backsector->tags) && (backsector->ffloors || frontsector->ffloors)) { ffloor_t *rover; @@ -2268,7 +2572,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) ds_p->maskedtexturecol = maskedtexturecol = curtexturecolumntable - rw_x; curtexturecolumntable += rw_stopx - rw_x; - maskedtextureheight = ds_p->maskedtextureheight; // note to red, this == &(ds_p->maskedtextureheight[0]) + ds_p->maskedtextureheight = maskedtextureheight = curtexturecolumntable - rw_x; + curtexturecolumntable += rw_stopx - rw_x; maskedtexture = true; @@ -2310,13 +2615,14 @@ void R_StoreWallRange(INT32 start, INT32 stop) } } - rw_midtexturemid = FixedMul(rw_midtexturemid, rw_midtexturescaley); - rw_midtextureback = FixedMul(rw_midtextureback, rw_midtexturescaley); + rw_midtexturemid = FixedMul(rw_midtexturemid, abs(rw_midtexturescaley)); + rw_midtextureback = FixedMul(rw_midtextureback, abs(rw_midtexturescaley)); + + rw_midtextureslide = FixedMul(rw_midtextureslide, abs(rw_midtexturescaley)); + rw_midtexturebackslide = FixedMul(rw_midtexturebackslide, abs(rw_midtexturescaley)); rw_midtexturemid += sidedef->rowoffset + sidedef->offsety_mid; rw_midtextureback += sidedef->rowoffset + sidedef->offsety_mid; - - maskedtexture = true; } } @@ -2369,7 +2675,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) // use different light tables // for horizontal / vertical / diagonal // OPTIMIZE: get rid of LIGHTSEGSHIFT globally - lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); + lightnum = R_SideLightLevel(curline->sidedef, frontsector->lightlevel) >> LIGHTSEGSHIFT; if (curline->v1->y == curline->v2->y) lightnum--; @@ -2440,7 +2746,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (frontsector->numlights) { dc_numlights = frontsector->numlights; - if (dc_numlights >= dc_maxlights) + if (dc_numlights > dc_maxlights) { dc_maxlights = dc_numlights; dc_lightlist = Z_Realloc(dc_lightlist, sizeof (*dc_lightlist) * dc_maxlights, PU_STATIC, NULL); diff --git a/src/r_skins.c b/src/r_skins.c index 6b4aeefe1726e46ee3f169540d5e87ad15dc271e..f364273e8405189845a385fd918b0a95e79b6220 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -35,30 +35,86 @@ INT32 numskins = 0; skin_t **skins = NULL; -// -// P_GetSkinSprite2 -// For non-super players, tries each sprite2's immediate predecessor until it finds one with a number of frames or ends up at standing. -// For super players, does the same as above - but tries the super equivalent for each sprite2 before the non-super version. -// - -UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) +// Gets the animation ID of a state +UINT16 P_GetStateSprite2(state_t *state) { - UINT8 super = 0, i = 0; + if (state->sprite2) + return state->sprite2; + else + { + // Transform the state frame into an animation ID + UINT16 spr2 = state->frame & FF_FRAMEMASK; - if (!skin) + if (state->frame & SPR2F_SUPER) + spr2 |= SPR2F_SUPER; + + return spr2; + } +} + +// Gets the starting frame of an animation +UINT16 P_GetSprite2StateFrame(state_t *state) +{ + if (state->sprite2) + return state->frame & FF_FRAMEMASK; + else return 0; +} - if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2) +// Checks if a state should use the "super" variant of the animation +boolean P_IsStateSprite2Super(state_t *state) +{ + if (state->sprite2) + { + if (state->sprite2 & SPR2F_SUPER) + return true; + } + else if (state->frame & SPR2F_SUPER) + return true; + + return false; +} + +// Applies SPR2F_SUPER to an animation based on the actor's state +UINT16 P_ApplySuperFlagToSprite2(UINT16 spr2, mobj_t *mobj) +{ + if (mobj->player) + { + if (mobj->player->charflags & SF_NOSUPERSPRITES || (mobj->player->powers[pw_carry] == CR_NIGHTSMODE && (mobj->player->charflags & SF_NONIGHTSSUPER))) + spr2 &= ~SPR2F_SUPER; + else if (mobj->player->powers[pw_super] || (mobj->player->powers[pw_carry] == CR_NIGHTSMODE && (mobj->player->charflags & SF_SUPER))) + spr2 |= SPR2F_SUPER; + } + + if (spr2 & SPR2F_SUPER) + { + if (mobj->eflags & MFE_FORCENOSUPER) + spr2 &= ~SPR2F_SUPER; + } + else if (mobj->eflags & MFE_FORCESUPER) + spr2 |= SPR2F_SUPER; + + return spr2; +} + +// For non-super players, this tries each sprite2's immediate predecessor until it finds one with a number of frames or ends up at standing. +// For super players, does the same as above - but tries the super equivalent for each sprite2 before the non-super version. +UINT16 P_GetSkinSprite2(skin_t *skin, UINT16 spr2, player_t *player) +{ + UINT16 super = 0; + UINT8 i = 0; + + if (!skin) return 0; - while (!skin->sprites[spr2].numframes + while (!P_IsValidSprite2(skin, spr2) && spr2 != SPR2_STND && ++i < 32) // recursion limiter { - if (spr2 & FF_SPR2SUPER) + if (spr2 & SPR2F_SUPER) { - super = FF_SPR2SUPER; - spr2 &= ~FF_SPR2SUPER; + super = SPR2F_SUPER; + spr2 &= ~SPR2F_SUPER; continue; } @@ -92,6 +148,51 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) return spr2; } +// Gets the spritedef of a skin animation +spritedef_t *P_GetSkinSpritedef(skin_t *skin, UINT16 spr2) +{ + if (!skin) + return NULL; + + boolean is_super = spr2 & SPR2F_SUPER; + + spr2 &= SPR2F_MASK; + + if (spr2 >= free_spr2) + return NULL; + + if (is_super) + return &skin->super.sprites[spr2]; + else + return &skin->sprites[spr2]; +} + +// Gets the spriteinfo of a skin animation +spriteinfo_t *P_GetSkinSpriteInfo(skin_t *skin, UINT16 spr2) +{ + if (!skin) + return NULL; + + boolean is_super = spr2 & SPR2F_SUPER; + + spr2 &= SPR2F_MASK; + + if (spr2 >= free_spr2) + return NULL; + + if (is_super) + return &skin->super.sprinfo[spr2]; + else + return &skin->sprinfo[spr2]; +} + +// Checks if a skin animation is valid +boolean P_IsValidSprite2(skin_t *skin, UINT16 spr2) +{ + spritedef_t *sprdef = P_GetSkinSpritedef(skin, spr2); + return sprdef && sprdef->numframes; +} + static void Sk_SetDefaultValue(skin_t *skin) { INT32 i; @@ -376,7 +477,7 @@ static void SetSkin(player_t *player, INT32 skinnum) player->mo->skin = skin; if (newcolor) player->mo->color = newcolor; - P_SetScale(player->mo, player->mo->scale); + P_SetScale(player->mo, player->mo->scale, false); player->mo->radius = radius; P_SetMobjState(player->mo, player->mo->state-states); // Prevent visual errors when switching between skins with differing number of frames @@ -500,10 +601,10 @@ static UINT16 W_CheckForPatchSkinMarkerInPwad(UINT16 wadid, UINT16 startlump) return INT16_MAX; // not found } -static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, skin_t *skin, UINT8 start_spr2) +static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, skin_t *skin, UINT16 start_spr2) { UINT16 newlastlump; - UINT8 sprite2; + UINT16 sprite2; *lump += 1; // start after S_SKIN *lastlump = W_CheckNumForNamePwad("S_END",wadnum,*lump); // stop at S_END @@ -523,7 +624,7 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski newlastlump++; // load all sprite sets we are aware of... for super! for (sprite2 = start_spr2; sprite2 < free_spr2; sprite2++) - R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[FF_SPR2SUPER|sprite2], wadnum, newlastlump, *lastlump); + R_AddSingleSpriteDef(spr2names[sprite2], &skin->super.sprites[sprite2], wadnum, newlastlump, *lastlump, false); newlastlump--; *lastlump = newlastlump; // okay, make the normal sprite set loading end there @@ -531,10 +632,18 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski // load all sprite sets we are aware of... for normal stuff. for (sprite2 = start_spr2; sprite2 < free_spr2; sprite2++) - R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[sprite2], wadnum, *lump, *lastlump); + R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[sprite2], wadnum, *lump, *lastlump, false); if (skin->sprites[0].numframes == 0) CONS_Alert(CONS_ERROR, M_GetText("No frames found for sprite SPR2_%s\n"), spr2names[0]); + + // TODO: 2.3: Delete + memcpy(&skin->sprites_compat[start_spr2], + &skin->sprites[start_spr2], + sizeof(spritedef_t) * (free_spr2 - start_spr2)); + memcpy(&skin->sprites_compat[start_spr2 + NUMPLAYERSPRITES], + &skin->super.sprites[start_spr2], + sizeof(spritedef_t) * (free_spr2 - start_spr2)); } // returns whether found appropriate property diff --git a/src/r_skins.h b/src/r_skins.h index cc3b63cbed2c97de3fc312ad338d6f201edcd65b..645fea540c53dd26e61cc7f3a2e71ecc3c365d1a 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -80,9 +80,17 @@ typedef struct // specific sounds per skin sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table + spritedef_t sprites[NUMPLAYERSPRITES]; + spriteinfo_t sprinfo[NUMPLAYERSPRITES]; + // contains super versions too - spritedef_t sprites[NUMPLAYERSPRITES*2]; - spriteinfo_t sprinfo[NUMPLAYERSPRITES*2]; + struct { + spritedef_t sprites[NUMPLAYERSPRITES]; + spriteinfo_t sprinfo[NUMPLAYERSPRITES]; + } super; + + // TODO: 2.3: Delete + spritedef_t sprites_compat[NUMPLAYERSPRITES * 2]; } skin_t; /// Externs @@ -102,7 +110,14 @@ INT32 R_GetForcedSkin(INT32 playernum); void R_AddSkins(UINT16 wadnum, boolean mainfile); void R_PatchSkins(UINT16 wadnum, boolean mainfile); -UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player); +UINT16 P_GetStateSprite2(state_t *state); +UINT16 P_GetSprite2StateFrame(state_t *state); +UINT16 P_GetSkinSprite2(skin_t *skin, UINT16 spr2, player_t *player); +UINT16 P_ApplySuperFlagToSprite2(UINT16 spr2, mobj_t *mobj); +spritedef_t *P_GetSkinSpritedef(skin_t *skin, UINT16 spr2); +spriteinfo_t *P_GetSkinSpriteInfo(skin_t *skin, UINT16 spr2); +boolean P_IsValidSprite2(skin_t *skin, UINT16 spr2); +boolean P_IsStateSprite2Super(state_t *state); void R_RefreshSprite2(void); diff --git a/src/r_sky.c b/src/r_sky.c index 1b2c43d12b770bffba413bbbae8a84139aeb041f..ad7262c6e168d9a469e5189c41cb1c2b45438576 100644 --- a/src/r_sky.c +++ b/src/r_sky.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_splats.c b/src/r_splats.c index 027ccd720aed2902b7c096040548b95e3d3b369d..ce35a35b4c3ff24d1045a170a67d421310f837af 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -381,7 +381,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr if (pSplat->slope) { - R_SetScaledSlopePlane(pSplat->slope, vis->viewpoint.x, vis->viewpoint.y, vis->viewpoint.z, pSplat->xscale, pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewpoint.angle, pSplat->angle); + R_SetScaledSlopePlane(pSplat->slope, vis->viewpoint.x, vis->viewpoint.y, vis->viewpoint.z, (INT64)pSplat->xscale, (INT64)pSplat->yscale, -pSplat->verts[0].x, pSplat->verts[0].y, vis->viewpoint.angle, pSplat->angle); } else if (!ds_solidcolor) { diff --git a/src/r_textures.c b/src/r_textures.c index 27a9336319bdbb71a1d0d1c4747c5a0db73fb2b2..4c52f75ebe169607d8f367bf07c03bc7f2eb70af 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -147,9 +147,9 @@ static void R_DrawFlippedColumnInCache(column_t *column, UINT8 *cache, texpatch_ if (count > 0) { - for (; dest < cache + position + count; --source) + for (; dest < cache + position + count; --source, dest++, is_opaque++) { - *dest++ = *source; + *dest = *source; *is_opaque = true; } } @@ -191,8 +191,10 @@ static void R_DrawBlendColumnInCache(column_t *column, UINT8 *cache, texpatch_t if (count > 0) { - for (; dest < cache + position + count; source++, dest++) + for (; dest < cache + position + count; source++, dest++, is_opaque++) { + if (originPatch->alpha <= ASTTextureBlendingThreshold[1] && !(*is_opaque)) + continue; *dest = ASTBlendPaletteIndexes(*dest, *source, originPatch->style, originPatch->alpha); *is_opaque = true; } @@ -235,8 +237,10 @@ static void R_DrawBlendFlippedColumnInCache(column_t *column, UINT8 *cache, texp if (count > 0) { - for (; dest < cache + position + count; --source, dest++) + for (; dest < cache + position + count; --source, dest++, is_opaque++) { + if (originPatch->alpha <= ASTTextureBlendingThreshold[1] && !(*is_opaque)) + continue; *dest = ASTBlendPaletteIndexes(*dest, *source, originPatch->style, originPatch->alpha); *is_opaque = true; } @@ -291,7 +295,6 @@ UINT8 *R_GenerateTexture(size_t texnum) UINT16 lumpnum = patch->lump; UINT8 *pdata; softwarepatch_t *realpatch; - boolean holey = false; #ifndef NO_PNG_LUMPS UINT8 header[PNG_HEADER_SIZE]; @@ -306,9 +309,11 @@ UINT8 *R_GenerateTexture(size_t texnum) pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); realpatch = (softwarepatch_t *)pdata; + texture->transparency = false; + // Check the patch for holes. if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height)) - holey = true; + texture->transparency = true; else { UINT8 *colofs = (UINT8 *)realpatch->columnofs; @@ -328,12 +333,12 @@ UINT8 *R_GenerateTexture(size_t texnum) col = (doompost_t *)((UINT8 *)col + col->length + 4); } if (y < texture->height) - holey = true; // this texture is HOLEy! D: + texture->transparency = true; // this texture is HOLEy! D: } } // If the patch uses transparency, we have to save it this way. - if (holey) + if (texture->transparency) { texture->flip = patch->flip; @@ -374,6 +379,15 @@ UINT8 *R_GenerateTexture(size_t texnum) temp_columns = Z_Calloc(sizeof(column_t) * texture->width, PU_STATIC, NULL); temp_block = Z_Calloc(total_pixels, PU_STATIC, NULL); +#ifdef TEXTURE_255_IS_TRANSPARENT + texture->transparency = false; + + // Transparency hack + memset(temp_block, TRANSPARENTPIXEL, total_pixels); +#else + texture->transparency = true; +#endif + for (x = 0; x < texture->width; x++) { column_t *column = &temp_columns[x]; @@ -470,13 +484,27 @@ UINT8 *R_GenerateTexture(size_t texnum) // Now write the columns column_posts = Z_Calloc(sizeof(unsigned) * texture->width, PU_STATIC, NULL); +#ifdef TEXTURE_255_IS_TRANSPARENT + total_posts = texture->width; + temp_posts = Z_Realloc(temp_posts, sizeof(post_t) * total_posts, PU_CACHE, NULL); +#endif + for (x = 0; x < texture->width; x++) { - post_t *post; - boolean was_opaque = false; + post_t *post = NULL; column_t *column = &temp_columns[x]; +#ifdef TEXTURE_255_IS_TRANSPARENT + post = &temp_posts[x]; + post->topdelta = 0; + post->length = texture->height; + post->data_offset = 0; + column_posts[x] = x; + column->num_posts = 1; +#else + boolean was_opaque = false; + column_posts[x] = (unsigned)-1; for (INT32 y = 0; y < texture->height; y++) @@ -506,6 +534,7 @@ UINT8 *R_GenerateTexture(size_t texnum) post->length++; } +#endif } blocksize = (sizeof(column_t) * texture->width) + (sizeof(post_t) * total_posts) + (sizeof(UINT8) * total_pixels); @@ -817,8 +846,8 @@ Rloadflats (INT32 i, INT32 w) UINT8 *flatlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); if (Picture_PNGDimensions((UINT8 *)flatlump, &texw, &texh, NULL, NULL, lumplength)) { - width = (INT16)width; - height = (INT16)height; + width = (INT16)texw; + height = (INT16)texh; } else { @@ -1064,6 +1093,98 @@ void R_LoadTexturesPwad(UINT16 wadnum) R_FinishLoadingTextures(newtextures); } +static lumpnum_t W_GetTexPatchLumpNum(const char *name) +{ + // Flats as a texture patch crashes horribly, and flats + // can share the same name as textures. + + // But even if they worked, we want to prioritize: + // Patches -> Textures -> anything else + + enum + { + USE_PATCHES, + USE_TEXTURES, + USE__MAX, + }; + + lumpnum_t lump = LUMPERROR; + INT32 lump_type_it; + + + for (lump_type_it = 0; lump_type_it < USE__MAX; lump_type_it++) + { + INT32 i; + + for (i = numwadfiles - 1; i >= 0; i--) // Scan wad files backwards so patched lumps take precedent + { + lumpnum_t start = LUMPERROR; + lumpnum_t end = LUMPERROR; + + switch (wadfiles[i]->type) + { + case RET_WAD: + if (lump_type_it == USE_PATCHES) + { + if ((start = W_CheckNumForMarkerStartPwad("P_START", (UINT16)i, 0)) == INT16_MAX) + continue; + else if ((end = W_CheckNumForNamePwad("P_END", (UINT16)i, start)) == INT16_MAX) + continue; + } + else if (lump_type_it == USE_TEXTURES) + { + if ((start = W_CheckNumForMarkerStartPwad("TX_START", (UINT16)i, 0)) == INT16_MAX) + continue; + else if ((end = W_CheckNumForNamePwad("TX_END", (UINT16)i, start)) == INT16_MAX) + continue; + } + break; + case RET_PK3: + case RET_FOLDER: + if (lump_type_it == USE_PATCHES) + { + if ((start = W_CheckNumForFolderStartPK3("Patches/", i, 0)) == INT16_MAX) + continue; + if ((end = W_CheckNumForFolderEndPK3("Patches/", i, start)) == INT16_MAX) + continue; + } + else if (lump_type_it == USE_TEXTURES) + { + if ((start = W_CheckNumForFolderStartPK3("Textures/", i, 0)) == INT16_MAX) + continue; + if ((end = W_CheckNumForFolderEndPK3("Textures/", i, start)) == INT16_MAX) + continue; + } + break; + default: + continue; + } + + // Now find lump with specified name in that range. + lump = W_CheckNumForNamePwad(name, (UINT16)i, start); + if (lump < end) + { + lump += (i<<16); // found it, in our constraints + break; + } + lump = LUMPERROR; + } + + if (lump != LUMPERROR) + { + break; + } + } + + if (lump == LUMPERROR) + { + // Use whatever else you can find. + return W_CheckNumForPatchName(name); + } + + return lump; +} + static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) { char *texturesToken; @@ -1236,13 +1357,13 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) if (actuallyLoadPatch == true) { // Check lump exists - patchLumpNum = W_GetNumForName(patchName); + patchLumpNum = W_GetTexPatchLumpNum(patchName); // If so, allocate memory for texpatch_t and fill 'er up resultPatch = (texpatch_t *)Z_Malloc(sizeof(texpatch_t),PU_STATIC,NULL); resultPatch->originx = patchXPos; resultPatch->originy = patchYPos; - resultPatch->lump = patchLumpNum & 65535; - resultPatch->wad = patchLumpNum>>16; + resultPatch->lump = LUMPNUM(patchLumpNum); + resultPatch->wad = WADFILENUM(patchLumpNum); resultPatch->flip = flip; resultPatch->alpha = alpha; resultPatch->style = style; @@ -1595,7 +1716,7 @@ const char *R_CheckTextureNameForNum(INT32 num) { if (num > 0 && num < numtextures) return textures[num]->name; - + return "-"; } diff --git a/src/r_textures.h b/src/r_textures.h index eb68ec09f21d4fe8d847b048ac12ba9bd3a1817d..35db40d42b662553d89ed627247ee06d640e4bcd 100644 --- a/src/r_textures.h +++ b/src/r_textures.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -54,6 +54,7 @@ typedef struct char name[8]; UINT32 hash; UINT8 type; // TEXTURETYPE_* + boolean transparency; INT16 width, height; UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both void *flat; // The texture, as a flat. diff --git a/src/r_things.c b/src/r_things.c index d6ef72b9d29980134757df4547ffd03837379957..2c0529e47a572b8fcd5b7966fcb7652e13a6b03b 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -77,7 +77,7 @@ spriteinfo_t spriteinfo[NUMSPRITES]; spritedef_t *sprites; size_t numsprites; -static spriteframe_t sprtemp[64]; +static spriteframe_t sprtemp[MAXFRAMENUM]; static size_t maxframe; static const char *spritename; @@ -116,6 +116,14 @@ static INT32 drawsegs_xrange_count = 0; // // ========================================================================== +spritenum_t R_GetSpriteNumByName(const char *name) +{ + for (spritenum_t i = 0; i < NUMSPRITES; i++) + if (!strcmp(name, sprnames[i])) + return i; + return NUMSPRITES; +} + // // // @@ -128,10 +136,14 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch { char cn = R_Frame2Char(frame), cr = R_Rotation2Char(rotation); // for debugging + char framedescription[256]; + if (cn != '\xFF') + sprintf(framedescription, "%s frame %d (%c)", spritename, frame, cn); + else + sprintf(framedescription, "%s frame %d", spritename, frame); + INT32 r; - lumpnum_t lumppat = wad; - lumppat <<= 16; - lumppat += lump; + lumpnum_t lumppat = (wad << 16) + lump; if (maxframe ==(size_t)-1 || frame > maxframe) maxframe = frame; @@ -147,9 +159,9 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch { // the lump should be used for all rotations if (sprtemp[frame].rotate == SRF_SINGLE) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple rot = 0 lump\n", spritename, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has multiple rot = 0 lump\n", framedescription); else if (sprtemp[frame].rotate != SRF_NONE) // Let's bundle 1-8/16 and L/R rotations into one debug message. - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has rotations and a rot = 0 lump\n", spritename, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has rotations and a rot = 0 lump\n", framedescription); sprtemp[frame].rotate = SRF_SINGLE; for (r = 0; r < 16; r++) @@ -169,15 +181,15 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch if (sprtemp[frame].rotate == SRF_NONE) sprtemp[frame].rotate = SRF_SINGLE; else if (sprtemp[frame].rotate == SRF_SINGLE) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has L/R rotations and a rot = 0 lump\n", spritename, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has L/R rotations and a rot = 0 lump\n", framedescription); else if (sprtemp[frame].rotate == SRF_3D) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8 rotations\n", spritename, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has both L/R and 1-8 rotations\n", framedescription); else if (sprtemp[frame].rotate == SRF_3DGE) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-G rotations\n", spritename, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has both L/R and 1-G rotations\n", framedescription); else if ((sprtemp[frame].rotate & SRF_LEFT) && (rotation == ROT_L)) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple L rotations\n", spritename, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has multiple L rotations\n", framedescription); else if ((sprtemp[frame].rotate & SRF_RIGHT) && (rotation == ROT_R)) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple R rotations\n", spritename, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has multiple R rotations\n", framedescription); sprtemp[frame].rotate |= ((rotation == ROT_R) ? SRF_RIGHT : SRF_LEFT); if ((sprtemp[frame].rotate & SRF_2D) == SRF_2D) @@ -204,9 +216,9 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch if (sprtemp[frame].rotate == SRF_NONE) sprtemp[frame].rotate = SRF_SINGLE; else if (sprtemp[frame].rotate == SRF_SINGLE) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has 1-8/G rotations and a rot = 0 lump\n", spritename, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has 1-8/G rotations and a rot = 0 lump\n", framedescription); else if (sprtemp[frame].rotate & SRF_2D) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8/G rotations\n", spritename, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s has both L/R and 1-8/G rotations\n", framedescription); // make 0 based rotation--; @@ -226,7 +238,12 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch } if (sprtemp[frame].lumppat[rotation] != LUMPERROR) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %c%c has two lumps mapped to it\n", spritename, cn, cr); + { + if (cn != '\xFF') + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %d_%c (%c%c) has two lumps mapped to it\n", spritename, frame, cr, cn, cr); + else + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %d_%c has two lumps mapped to it\n", spritename, frame, cr); + } // lumppat & lumpid are the same for original Doom, but different // when using sprites in pwad : the lumppat points the new graphics @@ -238,24 +255,209 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch sprtemp[frame].flip &= ~(1<<rotation); } +static boolean GetFramesAndRotationsFromShortLumpName( + const char *name, + INT32 *ret_frame, + UINT8 *ret_rotation, + INT32 *ret_frame2, + UINT8 *ret_rotation2 +) +{ + size_t namelen = strlen(name); + + if (namelen != 6 && namelen != 8) + return false; + + *ret_frame = R_Char2Frame(name[4]); + *ret_rotation = R_Char2Rotation(name[5]); + if (*ret_frame >= 64 || *ret_rotation == 255) + return false; + + if (namelen == 8) + { + *ret_frame2 = R_Char2Frame(name[6]); + *ret_rotation2 = R_Char2Rotation(name[7]); + if (*ret_frame2 >= 64 || *ret_rotation2 == 255) + return false; + + // TRNSLATE is a valid but extremely unlikely sprite name: + // * The sprite name is "TRNS" + // * The frame is L, rotation A; mirrored to frame T, rotation E + // In the very unfortunate event that TRNSLATE is found between sprite lumps, + // this name check prevents it from being added as a sprite, when it actually isn't. + if (memcmp(name, "TRNSLATE", 8) == 0) + return false; + } + else + { + *ret_frame2 = -1; + *ret_rotation2 = 255; + } + + return true; +} + +static boolean GetSingleFrameAndRotation( + const char *name, + size_t len, + INT32 *ret_frame, + UINT8 *ret_rotation +) +{ + const char *underscore = strchr(name, '_'); + + // Found but past the part of the name we are parsing + if ((size_t)(underscore - name) >= len) + underscore = NULL; + + size_t framelen = underscore ? (size_t)(underscore - name) : len; + if (framelen < 1 || framelen > 4) + return false; + + char framepart[4 + 1]; // Max 9999 + strlcpy(framepart, name, framelen + 1); + + for (size_t i = 0; i < framelen; i++) + if (!isdigit(framepart[i])) + return false; + + *ret_frame = atoi(framepart); + *ret_rotation = underscore ? R_Char2Rotation(*(underscore + 1)) : 0; + if (*ret_frame >= MAXFRAMENUM || *ret_rotation == 255) + return false; + + return true; +} + +static boolean GetFramesAndRotationsFromLongLumpName( + const char *name, + INT32 *ret_frame, + UINT8 *ret_rotation, + INT32 *ret_frame2, + UINT8 *ret_rotation2 +) +{ + const char *plus = strchr(name, '+'); + + if (plus) + { + size_t len1 = plus - name; + + if (!GetSingleFrameAndRotation(name, len1, ret_frame, ret_rotation)) + return false; + if (!GetSingleFrameAndRotation(plus + 1, strlen(name) - len1 - 1, ret_frame2, ret_rotation2)) + return false; + } + else + { + if (!GetSingleFrameAndRotation(name, strlen(name), ret_frame, ret_rotation)) + return false; + + *ret_frame2 = -1; + *ret_rotation2 = 255; + } + + return true; +} + +static UINT8 GetOppositeRotation(UINT8 rotation, UINT8 flags) +{ + if (flags & ~SRF_3DMASK) + I_Error("GetOppositeRotation: rotation type not supported"); + + UINT8 numrotations = (flags == SRF_3D) ? 8 : 16; + return (rotation == 1) ? 1 : numrotations + 2 - rotation; +} + +static void MirrorMissingRotations(void) +{ + for (UINT32 framenum = 0; framenum < maxframe; framenum++) + { + spriteframe_t *frame = &sprtemp[framenum]; + + if (frame->rotate == SRF_NONE || !(frame->rotate & (SRF_3DMASK | SRF_2D))) + continue; + + UINT8 numrotations = frame->rotate == SRF_3D ? 8 : 16; + + for (UINT8 rotation = 1; rotation <= numrotations; rotation++) + { + if (frame->lumppat[rotation - 1] != LUMPERROR) + continue; + + UINT8 baserotation = GetOppositeRotation(rotation, frame->rotate); + UINT32 lumpnum = frame->lumppat[baserotation - 1]; + R_InstallSpriteLump(WADFILENUM(lumpnum), LUMPNUM(lumpnum), frame->lumpid[baserotation - 1], framenum, rotation, 1); + } + } +} + +// Some checks to help development +static void CheckFrame(const char *sprname) +{ + for (UINT32 frame = 0; frame < maxframe; frame++) + { + spriteframe_t *spriteframe = &sprtemp[frame]; + + char framedescription[256]; + if (frame < 64) + sprintf(framedescription, "%s frame %d (%c)", sprname, frame, R_Frame2Char(frame)); + else + sprintf(framedescription, "%s frame %d", sprname, frame); + + switch (spriteframe->rotate) + { + case SRF_NONE: + // no rotations were found for that frame at all + I_Error("R_AddSingleSpriteDef: No patches found for %s", framedescription); + break; + + case SRF_SINGLE: + // only the first rotation is needed + break; + + case SRF_2D: // both Left and Right rotations + // we test to see whether the left and right slots are present + if ((spriteframe->lumppat[2] == LUMPERROR) || (spriteframe->lumppat[6] == LUMPERROR)) + I_Error("R_AddSingleSpriteDef: Sprite %s is missing rotations (L-R mode)", + framedescription); + break; + + default: + { + // must have all 8/16 frames + UINT8 rotation = ((spriteframe->rotate & SRF_3DGE) ? 16 : 8); + while (rotation--) + { + // we test the patch lump, or the id lump whatever + // if it was not loaded the two are LUMPERROR + if (spriteframe->lumppat[rotation] == LUMPERROR) + I_Error("R_AddSingleSpriteDef: Sprite %s is missing rotations (1-%c mode)", + framedescription, ((spriteframe->rotate & SRF_3DGE) ? 'G' : '8')); + } + } + break; + } + } +} + // Install a single sprite, given its identifying name (4 chars) // // (originally part of R_AddSpriteDefs) // -// Pass: name of sprite : 4 chars +// Pass: name of sprite // spritedef_t // wadnum : wad number, indexes wadfiles[], where patches // for frames are found // startlump : first lump to search for sprite frames // endlump : AFTER the last lump to search +// longname : whether to use long sprite names or 4-char names // // Returns true if the sprite was succesfully added // -boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump) +boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump, boolean longname) { UINT16 l; - UINT8 frame; - UINT8 rotation; lumpinfo_t *lumpinfo; UINT16 numadded = 0; @@ -282,15 +484,23 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 for (l = startlump; l < endlump; l++) { - if (memcmp(lumpinfo[l].name,sprname,4)==0) + if (longname && W_IsLumpFolder(wadnum, l)) + I_Error("R_AddSingleSpriteDef: all frame lumps for a sprite should be contained inside a single folder\n"); + + // For long sprites, the startlump-endlump range only includes + // relevant lumps, so no check needed in that case + if (longname || (strlen(sprname) == 4 && !memcmp(lumpinfo[l].name, sprname, 4))) { INT16 width, height; INT16 topoffset, leftoffset; + INT32 frame, frame2; + UINT8 rotation, rotation2; - frame = R_Char2Frame(lumpinfo[l].name[4]); - rotation = R_Char2Rotation(lumpinfo[l].name[5]); + boolean good = longname ? + GetFramesAndRotationsFromLongLumpName(lumpinfo[l].longname, &frame, &rotation, &frame2, &rotation2) : + GetFramesAndRotationsFromShortLumpName(lumpinfo[l].name, &frame, &rotation, &frame2, &rotation2); - if (frame >= 64 || rotation == 255) // Give an actual NAME error -_-... + if (!good) // Give an actual NAME error -_-... { CONS_Alert(CONS_WARNING, M_GetText("Bad sprite name: %s\n"), W_CheckNameForNumPwad(wadnum,l)); continue; @@ -322,19 +532,8 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 //---------------------------------------------------- R_InstallSpriteLump(wadnum, l, numspritelumps, frame, rotation, 0); - - if (lumpinfo[l].name[6]) - { - frame = R_Char2Frame(lumpinfo[l].name[6]); - rotation = R_Char2Rotation(lumpinfo[l].name[7]); - - if (frame >= 64 || rotation == 255) // Give an actual NAME error -_-... - { - CONS_Alert(CONS_WARNING, M_GetText("Bad sprite name: %s\n"), W_CheckNameForNumPwad(wadnum,l)); - continue; - } - R_InstallSpriteLump(wadnum, l, numspritelumps, frame, rotation, 1); - } + if (frame2 != -1) + R_InstallSpriteLump(wadnum, l, numspritelumps, frame2, rotation2, 1); if (++numspritelumps >= max_spritelumps) { @@ -374,41 +573,10 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 maxframe++; - // - // some checks to help development - // - for (frame = 0; frame < maxframe; frame++) - { - switch (sprtemp[frame].rotate) - { - case SRF_NONE: - // no rotations were found for that frame at all - I_Error("R_AddSingleSpriteDef: No patches found for %.4s frame %c", sprname, R_Frame2Char(frame)); - break; + if (longname) + MirrorMissingRotations(); - case SRF_SINGLE: - // only the first rotation is needed - break; - - case SRF_2D: // both Left and Right rotations - // we test to see whether the left and right slots are present - if ((sprtemp[frame].lumppat[2] == LUMPERROR) || (sprtemp[frame].lumppat[6] == LUMPERROR)) - I_Error("R_AddSingleSpriteDef: Sprite %.4s frame %c is missing rotations (L-R mode)", - sprname, R_Frame2Char(frame)); - break; - - default: - // must have all 8/16 frames - rotation = ((sprtemp[frame].rotate & SRF_3DGE) ? 16 : 8); - while (rotation--) - // we test the patch lump, or the id lump whatever - // if it was not loaded the two are LUMPERROR - if (sprtemp[frame].lumppat[rotation] == LUMPERROR) - I_Error("R_AddSingleSpriteDef: Sprite %.4s frame %c is missing rotations (1-%c mode)", - sprname, R_Frame2Char(frame), ((sprtemp[frame].rotate & SRF_3DGE) ? 'G' : '8')); - break; - } - } + CheckFrame(sprname); // allocate space for the frames present and copy sprtemp to it if (spritedef->numframes && // has been allocated @@ -429,14 +597,10 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 return true; } -// -// Search for sprites replacements in a wad whose names are in namelist -// -void R_AddSpriteDefs(UINT16 wadnum) +static void AddShortSpriteDefs(UINT16 wadnum, size_t *ptr_spritesadded, size_t *ptr_framesadded) { - size_t i, addsprites = 0; + size_t i; UINT16 start, end; - char wadname[MAX_WADPATH]; // Find the sprites section in this resource file. switch (wadfiles[wadnum]->type) @@ -474,27 +638,90 @@ void R_AddSpriteDefs(UINT16 wadnum) return; } - // // scan through lumps, for each sprite, find all the sprite frames // for (i = 0; i < numsprites; i++) { - if (sprnames[i][4] && wadnum >= (UINT16)sprnames[i][4]) - continue; - - if (R_AddSingleSpriteDef(sprnames[i], &sprites[i], wadnum, start, end)) + if (R_AddSingleSpriteDef(sprnames[i], &sprites[i], wadnum, start, end, false)) { // if a new sprite was added (not just replaced) - addsprites++; + (*ptr_spritesadded)++; #ifndef ZDEBUG CONS_Debug(DBG_SETUP, "sprite %s set in pwad %d\n", sprnames[i], wadnum); #endif } } - nameonly(strcpy(wadname, wadfiles[wadnum]->filename)); - CONS_Printf(M_GetText("%s added %d frames in %s sprites\n"), wadname, end-start, sizeu1(addsprites)); + *ptr_framesadded += end - start; +} + +static void AddLongSpriteDefs(UINT16 wadnum, size_t *ptr_spritesadded, size_t *ptr_framesadded) +{ + if (!W_FileHasFolders(wadfiles[wadnum])) + return; + + UINT16 start = W_CheckNumForFolderStartPK3("LongSprites/", wadnum, 0); + UINT16 end = W_CheckNumForFolderEndPK3("LongSprites/", wadnum, start); + + if (start == INT16_MAX || end == INT16_MAX || start >= end) + return; + + size_t lumpnum = start; + + while (lumpnum < end) + { + if (W_IsLumpFolder(wadnum, lumpnum)) + { + lumpnum++; + continue; + } + + UINT16 folderstart, folderend; + char *folderpath = W_GetLumpFolderPathPK3(wadnum, lumpnum); + folderstart = lumpnum; + folderend = W_CheckNumForFolderEndPK3(folderpath, wadnum, lumpnum); + Z_Free(folderpath); + + spritenum_t sprnum; + char *sprname = W_GetLumpFolderNamePK3(wadnum, lumpnum); + strupr(sprname); + sprnum = R_GetSpriteNumByName(sprname); + + if (sprnum != NUMSPRITES && R_AddSingleSpriteDef(sprname, &sprites[sprnum], wadnum, folderstart, folderend, true)) + { + // A new sprite was added (not just replaced) + (*ptr_spritesadded)++; +#ifndef ZDEBUG + CONS_Debug(DBG_SETUP, "long sprite %s set in pwad %d\n", sprname, wadnum); +#endif + } + + Z_Free(sprname); + + lumpnum = folderend; + } + + *ptr_framesadded += end - start; +} + +// +// Search for sprites replacements in a wad whose names are in namelist +// +void R_AddSpriteDefs(UINT16 wadnum) +{ + char wadname[MAX_WADPATH]; + size_t spritesadded = 0; + size_t framesadded = 0; + + AddShortSpriteDefs(wadnum, &spritesadded, &framesadded); + AddLongSpriteDefs(wadnum, &spritesadded, &framesadded); + + if (spritesadded || framesadded) + { + nameonly(strcpy(wadname, wadfiles[wadnum]->filename)); + CONS_Printf(M_GetText("%s added %s frames in %s sprites\n"), wadname, sizeu1(framesadded), sizeu2(spritesadded)); + } } // @@ -620,8 +847,10 @@ void R_DrawMaskedColumn(column_t *column, unsigned lengthcol) { post_t *post = &column->posts[i]; + dc_postlength = post->length; + INT32 topscreen = sprtopscreen + spryscale*post->topdelta; - INT32 bottomscreen = topscreen + spryscale*post->length; + INT32 bottomscreen = topscreen + spryscale*dc_postlength; dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS; dc_yh = (bottomscreen-1)>>FRACBITS; @@ -658,12 +887,31 @@ void R_DrawMaskedColumn(column_t *column, unsigned lengthcol) static UINT8 *flippedcol = NULL; static size_t flippedcolsize = 0; +void R_DrawFlippedPost(UINT8 *source, unsigned length, void (*drawcolfunc)(void)) +{ + if (!length) + return; + + if (!flippedcolsize || length > flippedcolsize) + { + flippedcolsize = length; + flippedcol = Z_Realloc(flippedcol, length, PU_STATIC, NULL); + } + + dc_source = flippedcol; + + for (UINT8 *s = (UINT8 *)source, *d = flippedcol+length-1; d >= flippedcol; s++) + *d-- = *s; + + drawcolfunc(); +} + void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol) { INT32 topscreen; INT32 bottomscreen; fixed_t basetexturemid = dc_texturemid; - UINT8 *d,*s; + INT32 topdelta; for (unsigned i = 0; i < column->num_posts; i++) { @@ -671,10 +919,12 @@ void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol) if (!post->length) continue; - INT32 topdelta = lengthcol-post->length-post->topdelta; + dc_postlength = post->length; + + topdelta = lengthcol-dc_postlength-post->topdelta; topscreen = sprtopscreen + spryscale*topdelta; - bottomscreen = sprbotscreen == INT32_MAX ? topscreen + spryscale*post->length - : sprbotscreen + spryscale*post->length; + bottomscreen = sprbotscreen == INT32_MAX ? topscreen + spryscale*dc_postlength + : sprbotscreen + spryscale*dc_postlength; dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS; dc_yh = (bottomscreen-1)>>FRACBITS; @@ -698,18 +948,9 @@ void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol) if (dc_yl <= dc_yh && dc_yh > 0) { - if (post->length > flippedcolsize) - { - flippedcolsize = post->length; - flippedcol = Z_Realloc(flippedcol, flippedcolsize, PU_STATIC, NULL); - } - - for (s = column->pixels+post->data_offset+post->length, d = flippedcol; d < flippedcol+post->length; --s) - *d++ = *s; - dc_source = flippedcol; dc_texturemid = basetexturemid - (topdelta<<FRACBITS); - colfunc(); + R_DrawFlippedPost(column->pixels + post->data_offset, post->length, colfunc); } } @@ -727,7 +968,9 @@ UINT8 *R_GetTranslationForThing(mobj_t *mobj, skincolornum_t color, UINT16 trans if (color != SKINCOLOR_NONE) { // New colormap stuff for skins Tails 06-07-2002 - if (mobj->colorized) + if ((mobj->state-states == S_METALSONIC_DASH || mobj->state-states == S_METALSONIC_BOUNCE) && (((leveltime/2) & 1))) // Metal boss doing attack + skinnum = TC_DASHMODE; + else if (mobj->colorized) skinnum = TC_RAINBOW; else if (mobj->player && mobj->player->dashmode >= DASHMODE_THRESHOLD && (mobj->player->charflags & SF_DASHMODE) @@ -763,6 +1006,12 @@ UINT8 *R_GetTranslationForThing(mobj_t *mobj, skincolornum_t color, UINT16 trans return NULL; } +// Based off of R_GetLinedefTransTable +transnum_t R_GetThingTransTable(fixed_t alpha, transnum_t transmap) +{ + return (20*(FRACUNIT - ((alpha * (10 - transmap))/10) - 1) + FRACUNIT) >> (FRACBITS+1); +} + // // R_DrawVisSprite // mfloorclip and mceilingclip should also be set. @@ -941,7 +1190,6 @@ static void R_DrawVisSprite(vissprite_t *vis) } colfunc = colfuncs[BASEDRAWFUNC]; - dc_hires = 0; vis->x1 = x1; vis->x2 = x2; @@ -1269,6 +1517,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, floordiff = abs((isflipped ? interp.height : 0) + interp.z - groundz); trans = floordiff / (100*FRACUNIT) + 3; + trans = R_GetThingTransTable(thing->alpha, trans); if (trans >= 9) return; scalemul = FixedMul(FRACUNIT - floordiff/640, scale); @@ -1528,6 +1777,9 @@ static void R_ProjectSprite(mobj_t *thing) // uncapped/interpolation interpmobjstate_t interp = {0}; + if (!r_renderthings) + return; + // do interpolation if (R_UsingFrameInterpolation() && !paused) { @@ -1539,6 +1791,10 @@ static void R_ProjectSprite(mobj_t *thing) } this_scale = interp.scale; + + if (this_scale < 1) + return; + radius = interp.radius; // For drop shadows height = interp.height; // Ditto @@ -1567,20 +1823,22 @@ static void R_ProjectSprite(mobj_t *thing) // decide which patch to use for sprite relative to player #ifdef RANGECHECK if ((size_t)(thing->sprite) >= numsprites) - I_Error("R_ProjectSprite: invalid sprite number %d ", thing->sprite); + I_Error("R_ProjectSprite: invalid sprite number %d", thing->sprite); #endif - frame = thing->frame&FF_FRAMEMASK; + frame = thing->frame & FF_FRAMEMASK; //Fab : 02-08-98: 'skin' override spritedef currently used for skin if (thing->skin && thing->sprite == SPR_PLAY) { - sprdef = &((skin_t *)thing->skin)->sprites[thing->sprite2]; + sprdef = P_GetSkinSpritedef(thing->skin, thing->sprite2); #ifdef ROTSPRITE - sprinfo = &((skin_t *)thing->skin)->sprinfo[thing->sprite2]; + sprinfo = P_GetSkinSpriteInfo(thing->skin, thing->sprite2); #endif - if (frame >= sprdef->numframes) { - CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid skins[\"%s\"].sprites[%sSPR2_%s] frame %s\n"), ((skin_t *)thing->skin)->name, ((thing->sprite2 & FF_SPR2SUPER) ? "FF_SPR2SUPER|": ""), spr2names[(thing->sprite2 & ~FF_SPR2SUPER)], sizeu5(frame)); + + if (frame >= sprdef->numframes) + { + CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid skins[\"%s\"].sprites[SPR2_%s] %sframe %s\n"), ((skin_t *)thing->skin)->name, spr2names[thing->sprite2 & SPR2F_MASK], (thing->sprite2 & SPR2F_SUPER) ? "super ": "", sizeu5(frame)); thing->sprite = states[S_UNKNOWN].sprite; thing->frame = states[S_UNKNOWN].frame; sprdef = &sprites[thing->sprite]; @@ -1951,6 +2209,11 @@ static void R_ProjectSprite(mobj_t *thing) else trans = 0; + if ((oldthing->flags2 & MF2_LINKDRAW) && oldthing->tracer) + trans = R_GetThingTransTable(oldthing->tracer->alpha, trans); + else + trans = R_GetThingTransTable(oldthing->alpha, trans); + // Check if this sprite needs to be rendered like a shadow shadowdraw = (!!(thing->renderflags & RF_SHADOWDRAW) && !(papersprite || splat)); shadoweffects = (thing->renderflags & RF_SHADOWEFFECTS); @@ -2682,7 +2945,7 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps // Add the 3D floors, thicksides, and masked textures... for (ds = drawsegs + mask->drawsegs[1]; ds-- > drawsegs + mask->drawsegs[0];) { - if (ds->numthicksides) + if (ds->numthicksides && r_renderwalls) { for (i = 0; i < ds->numthicksides; i++) { @@ -2701,17 +2964,19 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps else { // Put it in! entry = R_CreateDrawNode(head); - entry->plane = plane; - entry->seg = ds; + if (r_renderwalls) + entry->seg = ds; + if (r_renderfloors) + entry->plane = plane; } ds->curline->polyseg->visplane = NULL; } - if (ds->maskedtexturecol) + if (ds->maskedtexturecol && r_renderwalls) { entry = R_CreateDrawNode(head); entry->seg = ds; } - if (ds->numffloorplanes) + if (ds->numffloorplanes && r_renderfloors) { for (i = 0; i < ds->numffloorplanes; i++) { @@ -3011,9 +3276,6 @@ void R_InitDrawNodes(void) // // R_DrawSprite // -//Fab : 26-04-98: -// NOTE : uses con_clipviewtop, so that when console is on, -// don't draw the part of sprites hidden under the console static void R_DrawSprite(vissprite_t *spr) { mfloorclip = spr->clipbot; @@ -3181,9 +3443,6 @@ static void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* port (lowscale < spr->sortscale && !R_PointOnSegSide (spr->gx, spr->gy, ds->curline))) { - // masked mid texture? - /*if (ds->maskedtexturecol) - R_RenderMaskedSegRange (ds, r1, r2);*/ // seg is behind sprite continue; } @@ -3415,6 +3674,7 @@ boolean R_ThingVisible (mobj_t *thing) (thing->sprite == SPR_NULL) || // Don't draw null-sprites (thing->flags2 & MF2_DONTDRAW) || // Don't draw MF2_LINKDRAW objects (thing->drawonlyforplayer && thing->drawonlyforplayer != viewplayer) || // Don't draw other players' personal objects + (!R_BlendLevelVisible(thing->blendmode, R_GetThingTransTable(thing->alpha, 0))) || (!P_MobjWasRemoved(r_viewmobj) && ( (r_viewmobj == thing) || // Don't draw first-person players or awayviewmobj objects (r_viewmobj->player && r_viewmobj->player->followmobj == thing) || // Don't draw first-person players' followmobj diff --git a/src/r_things.h b/src/r_things.h index 043b454b049cefa907c16f12c13751236db4b456..ae21d2404bc1793c569194f22ed0a8e815c89e46 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -27,7 +27,9 @@ #define FEETADJUST (4<<FRACBITS) // R_AddSingleSpriteDef -boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump); +spritenum_t R_GetSpriteNumByName(const char *name); + +boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump, boolean longname); //faB: find sprites in wadfile, replace existing, add new ones // (only sprites from namelist are added or replaced) @@ -48,6 +50,7 @@ extern fixed_t windowbottom; void R_DrawMaskedColumn(column_t *column, unsigned lengthcol); void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol); +void R_DrawFlippedPost(UINT8 *source, unsigned length, void (*drawcolfunc)(void)); // ---------------- // SPRITE RENDERING @@ -90,6 +93,7 @@ boolean R_ThingIsFullDark (mobj_t *thing); boolean R_ThingIsFlashing (mobj_t *thing); UINT8 *R_GetTranslationForThing(mobj_t *mobj, skincolornum_t color, UINT16 translation); +transnum_t R_GetThingTransTable(fixed_t alpha, transnum_t transmap); void R_ThingOffsetOverlay (mobj_t *thing, fixed_t *outx, fixed_t *outy); diff --git a/src/r_translation.c b/src/r_translation.c index 3b123f14ca1732e2e9605dad3153fd5f6d0e2338..53bb0e6a0fd12fa1291d697db462b647d8909503 100644 --- a/src/r_translation.c +++ b/src/r_translation.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2006 by Randy Heit. -// Copyright (C) 2023 by Sonic Team Junior. +// Copyright (C) 2023-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -556,7 +556,7 @@ static boolean ParseDecimal(tokenizer_t *sc, double *out) return M_StringToDecimal(tkn, out); } -static struct PaletteRemapParseResult *ThrowError(const char *format, ...) +FUNCPRINTF static struct PaletteRemapParseResult *ThrowError(const char *format, ...) { const size_t err_size = 512 * sizeof(char); @@ -784,15 +784,15 @@ static struct PaletteRemapParseResult *PaletteRemap_ParseString(tokenizer_t *sc) return NULL; } -static struct PaletteRemapParseResult *PaletteRemap_ParseTranslation(const char *translation) +static struct PaletteRemapParseResult *PaletteRemap_ParseTranslation(const char *translation, size_t len) { - tokenizer_t *sc = Tokenizer_Open(translation, 1); + tokenizer_t *sc = Tokenizer_Open(translation, len, 1); struct PaletteRemapParseResult *result = PaletteRemap_ParseString(sc); Tokenizer_Close(sc); return result; } -static void PrintError(const char *name, const char *format, ...) +FUNCDEBUG static void PrintError(const char *name, const char *format, ...) { char error[256]; @@ -918,7 +918,7 @@ void R_ParseTrnslate(INT32 wadNum, UINT16 lumpnum) text[lumpLength] = '\0'; Z_Free(lumpData); - sc = Tokenizer_Open(text, 1); + sc = Tokenizer_Open(text, lumpLength, 1); tkn = sc->get(sc, 0); struct NewTranslation *list = NULL; @@ -963,7 +963,7 @@ void R_ParseTrnslate(INT32 wadNum, UINT16 lumpnum) // Parse all of the translations do { - struct PaletteRemapParseResult *parse_result = PaletteRemap_ParseTranslation(tkn); + struct PaletteRemapParseResult *parse_result = PaletteRemap_ParseTranslation(tkn, strlen(tkn)); if (parse_result->error) { PrintError(name, "%s", parse_result->error); diff --git a/src/r_translation.h b/src/r_translation.h index 1eb40233d12070708d9bda26bfa8b53792235352..9cae1a6470d71ae76647a4c6f70b821d0f615d6a 100644 --- a/src/r_translation.h +++ b/src/r_translation.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2006 by Randy Heit. -// Copyright (C) 2023 by Sonic Team Junior. +// Copyright (C) 2023-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/s_sound.c b/src/s_sound.c index a579292ff3aa791176b389d686901799c47c89a1..0329c289ee104e56cf1c156683690d65455aeed5 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -1910,7 +1910,7 @@ static void S_AddMusicStackEntry(const char *mname, UINT16 mflags, boolean loopi if (!music_stacks) { music_stacks = Z_Calloc(sizeof (*mst), PU_MUSIC, NULL); - strncpy(music_stacks->musname, (status == JT_MASTER ? mname : (S_CheckQueue() ? queue_name : mapmusname)), 7); + strncpy(music_stacks->musname, (status == JT_MASTER ? mname : (S_CheckQueue() ? queue_name : mapmusname)), sizeof(music_stacks->musname)-1); music_stacks->musflags = (status == JT_MASTER ? mflags : (S_CheckQueue() ? queue_flags : mapmusflags)); music_stacks->looping = (status == JT_MASTER ? looping : (S_CheckQueue() ? queue_looping : true)); music_stacks->position = (status == JT_MASTER ? position : (S_CheckQueue() ? queue_position : S_GetMusicPosition())); @@ -2033,7 +2033,7 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst) if (result) { *entry = *result; - strncpy(entry->musname, result->musname, 7); + memcpy(entry->musname, result->musname, sizeof(entry->musname)); } // no result, just grab mapmusname @@ -2255,10 +2255,10 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 if (S_MusicDisabled()) return; - strncpy(newmusic, mmusic, 7); + strncpy(newmusic, mmusic, sizeof(newmusic)-1); + newmusic[6] = 0; if (LUA_HookMusicChange(music_name, &hook_param)) return; - newmusic[6] = 0; // No Music (empty string) if (newmusic[0] == 0) @@ -2494,11 +2494,11 @@ static void Command_Tunes_f(void) track = (UINT16)atoi(COM_Argv(2))-1; strncpy(mapmusname, tunearg, 7); + mapmusname[6] = 0; if (argc > 4) position = (UINT32)atoi(COM_Argv(4)); - mapmusname[6] = 0; mapmusflags = (track & MUSIC_TRACKMASK); mapmusposition = position; diff --git a/src/s_sound.h b/src/s_sound.h index 288859c8d233dc9696118ef1d93655f98be514b9..589060c8c2a45ce25deeee80db521a4673f39dc2 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -238,7 +238,7 @@ UINT32 S_GetMusicPosition(void); typedef struct musicstack_s { - char musname[7]; + char musname[7+1]; UINT16 musflags; boolean looping; UINT32 position; diff --git a/src/screen.c b/src/screen.c index 76f546402ef38e0a4882221945ff602de73aadf9..dc77a9a93a6395becb4ac9177625ae7f00c74cad 100644 --- a/src/screen.c +++ b/src/screen.c @@ -1,14 +1,14 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 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 screen.c -/// \brief Handles multiple resolutions, 8bpp/16bpp(highcolor) modes +/// \brief Handles multiple resolutions #include "doomdef.h" #include "doomstat.h" @@ -44,6 +44,8 @@ // SRB2Kart #include "r_fps.h" // R_GetFramerateCap +#include "lua_hud.h" // LUA_HudEnabled + // -------------------------------------------- // assembly or c drawer routines for 8bpp/16bpp // -------------------------------------------- @@ -70,8 +72,6 @@ consvar_t cv_scr_width_w = CVAR_INIT ("scr_width_w", "640", CV_SAVE, CV_Unsigned consvar_t cv_scr_height_w = CVAR_INIT ("scr_height_w", "400", CV_SAVE, CV_Unsigned, NULL); consvar_t cv_scr_depth = CVAR_INIT ("scr_depth", "16 bits", CV_SAVE, scr_depth_cons_t, NULL); -consvar_t cv_renderview = CVAR_INIT ("renderview", "On", 0, CV_OnOff, NULL); - CV_PossibleValue_t cv_renderer_t[] = { {1, "Software"}, #ifdef HWRENDER @@ -91,19 +91,15 @@ consvar_t cv_fullscreen = CVAR_INIT ("fullscreen", "Yes", CV_SAVE|CV_CALL, CV_Ye // ========================================================================= INT32 scr_bpp; // current video mode bytes per pixel -UINT8 *scr_borderpatch; // flat used to fill the reduced view borders set at ST_Init() // ========================================================================= -// Short and Tall sky drawer, for the current color mode -void (*walldrawerfunc)(void); - void SCR_SetDrawFuncs(void) { // - // setup the right draw routines for either 8bpp or 16bpp + // setup the right draw routines // - if (true)//vid.bpp == 1) //Always run in 8bpp. todo: remove all 16bpp code? + if (vid.bpp == 1) //Always run in 8bpp. { colfuncs[BASEDRAWFUNC] = R_DrawColumn_8; spanfuncs[BASEDRAWFUNC] = R_DrawSpan_8; @@ -116,6 +112,10 @@ void SCR_SetDrawFuncs(void) colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8; colfuncs[COLDRAWFUNC_SHADOWED] = R_DrawColumnShadowed_8; colfuncs[COLDRAWFUNC_TRANSTRANS] = R_DrawTranslatedTranslucentColumn_8; + colfuncs[COLDRAWFUNC_CLAMPED] = R_DrawColumnClamped_8; + colfuncs[COLDRAWFUNC_CLAMPEDTRANS] = R_DrawTranslucentColumnClamped_8; + colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8; + colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS] = R_Draw2sMultiPatchTranslucentColumn_8; colfuncs[COLDRAWFUNC_FOG] = R_DrawFogColumn_8; spanfuncs[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_8; @@ -124,6 +124,7 @@ void SCR_SetDrawFuncs(void) spanfuncs[SPANDRAWFUNC_SPLAT] = R_DrawSplat_8; spanfuncs[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_8; spanfuncs[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_8; + spanfuncs[SPANDRAWFUNC_TILTEDTRANSSPLAT] = R_DrawTiltedTranslucentSplat_8; spanfuncs[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_8; spanfuncs[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_8; spanfuncs[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_8; @@ -139,7 +140,6 @@ void SCR_SetDrawFuncs(void) spanfuncs[SPANDRAWFUNC_FOG] = R_DrawFogSpan_8; spanfuncs[SPANDRAWFUNC_TILTEDFOG] = R_DrawTiltedFogSpan_8; - // Lactozilla: Non-powers-of-two spanfuncs_npo2[BASEDRAWFUNC] = R_DrawSpan_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TILTED] = R_DrawTiltedSpan_NPO2_8; @@ -147,32 +147,16 @@ void SCR_SetDrawFuncs(void) spanfuncs_npo2[SPANDRAWFUNC_SPLAT] = R_DrawSplat_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_NPO2_8; + spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANSSPLAT] = R_DrawTiltedTranslucentSplat_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPRITE] = R_DrawTiltedFloorSprite_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANSSPRITE] = R_DrawTiltedTranslucentFloorSprite_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_WATER] = R_DrawWaterSpan_NPO2_8; spanfuncs_npo2[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedWaterSpan_NPO2_8; - } -/* else if (vid.bpp > 1) - { - I_OutputMsg("using highcolor mode\n"); - spanfunc = basespanfunc = R_DrawSpan_16; - transcolfunc = R_DrawTranslatedColumn_16; - transtransfunc = R_DrawTranslucentColumn_16; // No 16bit operation for this function - - colfunc = basecolfunc = R_DrawColumn_16; - shadecolfunc = NULL; // detect error if used somewhere.. - fuzzcolfunc = R_DrawTranslucentColumn_16; - walldrawerfunc = R_DrawWallColumn_16; - }*/ else I_Error("unknown bytes per pixel mode %d\n", vid.bpp); -/* - if (SCR_IsAspectCorrect(vid.width, vid.height)) - CONS_Alert(CONS_WARNING, M_GetText("Resolution is not aspect-correct!\nUse a multiple of %dx%d\n"), BASEVIDWIDTH, BASEVIDHEIGHT); -*/ } void SCR_SetMode(void) @@ -511,10 +495,9 @@ void SCR_ClosedCaptions(void) basey -= 42; else if (splitscreen) basey -= 8; - else if ((modeattacking == ATTACKING_NIGHTS) - || (!(maptol & TOL_NIGHTS) + else if (LUA_HudEnabled(hud_powerups) && ((cv_powerupdisplay.value == 2) // "Always" - || (cv_powerupdisplay.value == 1 && !camera.chase)))) // "First-person only" + || (cv_powerupdisplay.value == 1 && !camera.chase))) // "First-person only" basey -= 16; } diff --git a/src/screen.h b/src/screen.h index 64d92b9d3ef99cf3c4e066ddc5cc9e57edd94afd..3ce593a52e8595e7412eb9c20c29c91ba9c057bb 100644 --- a/src/screen.h +++ b/src/screen.h @@ -1,14 +1,14 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 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 screen.h -/// \brief Handles multiple resolutions, 8bpp/16bpp(highcolor) modes +/// \brief Handles multiple resolutions #ifndef __SCREEN_H__ #define __SCREEN_H__ @@ -30,10 +30,6 @@ #define NUMSCREENS 5 #endif -// Size of statusbar. -#define ST_HEIGHT 32 -#define ST_WIDTH 320 - // used now as a maximum video mode size for extra vesa modes. // we try to re-allocate a minimum of buffers for stability of the memory, @@ -61,7 +57,7 @@ typedef struct viddef_s UINT8 *direct; // linear frame buffer, or vga base mem. INT32 dup; // scale 1, 2, 3 value for menus & overlays INT32/*fixed_t*/ fdup; // same as dup, but exact value when aspect ratio isn't 320/200 - INT32 bpp; // BYTES per pixel: 1 = 256color, 2 = highcolor + INT32 bpp; // BYTES per pixel: 1 = 256color INT32 baseratio; // Used to get the correct value for lighting walls @@ -83,35 +79,6 @@ enum VID_GL_LIBRARY_ERROR = -1, }; -// internal additional info for vesa modes only -typedef struct -{ - INT32 vesamode; // vesa mode number plus LINEAR_MODE bit - void *plinearmem; // linear address of start of frame buffer -} vesa_extra_t; -// a video modes from the video modes list, -// note: video mode 0 is always standard VGA320x200. -typedef struct vmode_s -{ - struct vmode_s *pnext; - char *name; - UINT32 width, height; - UINT32 rowbytes; // bytes per scanline - UINT32 bytesperpixel; // 1 for 256c, 2 for highcolor - INT32 windowed; // if true this is a windowed mode - INT32 numpages; - vesa_extra_t *pextradata; // vesa mode extra data -#ifdef _WIN32 - INT32 (WINAPI *setmode)(viddef_t *lvid, struct vmode_s *pcurrentmode); -#else - INT32 (*setmode)(viddef_t *lvid, struct vmode_s *pcurrentmode); -#endif - INT32 misc; // misc for display driver (r_opengl.dll etc) -} vmode_t; - -#define NUMSPECIALMODES 4 -extern vmode_t specialmodes[NUMSPECIALMODES]; - // --------------------------------------------- // color mode dependent drawer function pointers // --------------------------------------------- @@ -126,6 +93,10 @@ enum COLDRAWFUNC_SHADE, COLDRAWFUNC_SHADOWED, COLDRAWFUNC_TRANSTRANS, + COLDRAWFUNC_CLAMPED, + COLDRAWFUNC_CLAMPEDTRANS, + COLDRAWFUNC_TWOSMULTIPATCH, + COLDRAWFUNC_TWOSMULTIPATCHTRANS, COLDRAWFUNC_FOG, COLDRAWFUNC_MAX @@ -144,6 +115,7 @@ enum SPANDRAWFUNC_SPLAT, SPANDRAWFUNC_TRANSSPLAT, SPANDRAWFUNC_TILTEDSPLAT, + SPANDRAWFUNC_TILTEDTRANSSPLAT, SPANDRAWFUNC_SPRITE, SPANDRAWFUNC_TRANSSPRITE, @@ -184,11 +156,9 @@ void SCR_ChangeRenderer(void); extern CV_PossibleValue_t cv_renderer_t[]; extern INT32 scr_bpp; -extern UINT8 *scr_borderpatch; // patch used to fill the view borders extern consvar_t cv_scr_width, cv_scr_height, cv_scr_width_w, cv_scr_height_w, cv_scr_depth, cv_fullscreen; -extern consvar_t cv_renderview, cv_renderer; -extern consvar_t cv_renderhitbox, cv_renderhitboxinterpolation, cv_renderhitboxgldepth; +extern consvar_t cv_renderer; // wait for page flipping to end or not extern consvar_t cv_vidwait; extern consvar_t cv_timescale; diff --git a/src/sdl/CMakeLists.txt b/src/sdl/CMakeLists.txt index 5aca04d120c39287eec5c2097aa6375e52eb27fb..8950846ee4f43cf794bd6d2505bbf039e6c71d2f 100644 --- a/src/sdl/CMakeLists.txt +++ b/src/sdl/CMakeLists.txt @@ -1,7 +1,6 @@ # Declare SDL2 interface sources target_sources(SRB2SDL2 PRIVATE - mixer_sound.c ogl_sdl.c i_threads.c i_net.c @@ -13,6 +12,164 @@ target_sources(SRB2SDL2 PRIVATE hwsym_sdl.c ) +# Compatibility flag with later versions of GCC +# We should really fix our code to not need this +if (NOT SRB2_CONFIG_FORCE_NO_MS_BITFIELDS) + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + check_cxx_compiler_flag("-mno-ms-bitfields" HAS_NO_MS_BITFIELDS) + if(HAS_NO_MS_BITFIELDS) + target_compile_options(SRB2SDL2 PRIVATE -mno-ms-bitfields) + endif() + endif() +endif() + +# Yes we know we use insecure CRT functions... +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + target_compile_definitions(SRB2SDL2 PRIVATE -D_CRT_SECURE_NO_WARNINGS) +endif() + +# Compiler warnings configuration +target_compile_options(SRB2SDL2 PRIVATE + # Using generator expressions to handle per-language compile options + + # C, GNU + # This is a direct translation from versions.mk + $<$<AND:$<COMPILE_LANGUAGE:C>,$<C_COMPILER_ID:GNU>>: + -Wall + -Wno-trigraphs + -W # Was controlled by RELAXWARNINGS + -Wfloat-equal + -Wundef + -Wpointer-arith + -Wbad-function-cast + -Wcast-qual + -Wcast-align # Was controlled by NOCASTALIGNWARN + -Wwrite-strings + -Wsign-compare + -Wmissing-prototypes + -Wmissing-declarations + -Wmissing-noreturn + -Winline + -Wformat-y2k + -Wformat-security + + $<$<VERSION_LESS:$<C_COMPILER_VERSION>,2.9.5>: + -Wno-div-by-zero + -Wendif-labels + -Wdisabled-optimization + > + + $<$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,4.0.0>: + -Wold-style-definition + -Wmissing-field-initializers + > + + $<$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,4.1.0>: + -Wshadow + > + + $<$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,4.3.0>: + -funit-at-a-time + -Wlogical-op + > + + $<$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,4.5.0>: + -Wlogical-op + -Wno-error=array-bounds + > + + $<$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,4.6.0>: + -Wno-suggest-attribute=noreturn + -Wno-error=suggest-attribute=noreturn + -Werror=vla + > + + $<$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,5.4.0>: + -Wno-logical-op + -Wno-error=logical-op + > + + $<$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,6.1.0>: + -Wno-tautological-compare + -Wno-error=tautological-compare + > + + $<$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,7.1.0>: + -Wno-error=format-overflow=2 + -Wimplicit-fallthrough=4 + > + + $<$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,8.1.0>: + -Wno-error=format-overflow + -Wno-error=stringop-truncation + -Wno-error=stringop-overflow + -Wno-format-overflow + -Wno-stringop-truncation + -Wno-stringop-overflow + -Wno-error=multistatement-macros + > + + $<$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,9.1.0>: + -Wno-error=address-of-packed-member + > + > + + # C, Clang and Apple Clang + $<$<AND:$<COMPILE_LANGUAGE:C>,$<OR:$<C_COMPILER_ID:AppleClang>,$<C_COMPILER_ID:Clang>>>: + -Wall + -Wno-absolute-value + -Wno-trigraphs + -Wno-error=non-literal-null-conversion + -Wno-error=constant-conversion + -Wno-unused-but-set-variable + -Wno-error=unused-but-set-variable + -Wno-shorten-64-to-32 + > + + # C, MSVC + $<$<AND:$<COMPILE_LANGUAGE:C>,$<C_COMPILER_ID:MSVC>>: + # All warnings at and before Visual Studio 2019 RTM + # https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warnings-by-compiler-version?view=msvc-170 + /Wv:19.20.27004.0 + > + + # C++, GNU, Clang and Apple Clang + $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<OR:$<C_COMPILER_ID:GNU>,$<C_COMPILER_ID:AppleClang>,$<C_COMPILER_ID:Clang>>>: + -Wall + -Wno-unused-function + -Wno-unused-but-set-variable + -Wno-unused-private-field + > + + # C++, MSVC + $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<C_COMPILER_ID:MSVC>>: + /Wv:19.20.27004.0 + > + + # GNU + $<$<C_COMPILER_ID:GNU>: + -fmax-errors=5 + > +) +if(SRB2_CONFIG_ERRORMODE) + target_compile_options(SRB2SDL2 PRIVATE + $<$<OR:$<C_COMPILER_ID:GNU>,$<C_COMPILER_ID:AppleClang>,$<C_COMPILER_ID:Clang>>: + -Werror + > + + $<$<C_COMPILER_ID:MSVC>: + /WX + > + ) +endif() + +# Link warnings configuration +target_link_options(SRB2SDL2 PRIVATE + $<$<C_COMPILER_ID:GNU>: + # -Wl,--as-needed - Was controlled by NOLDWARNING + > +) + if("${CMAKE_SYSTEM_NAME}" MATCHES Windows) target_sources(SRB2SDL2 PRIVATE ../win32/win_dbg.c @@ -62,12 +219,6 @@ if("${CMAKE_SYSTEM_NAME}" MATCHES Windows) target_link_libraries(SRB2SDL2 PRIVATE SDL2::SDL2main) endif() -if(NOT "${SRB2_CONFIG_SYSTEM_LIBRARIES}" AND NOT "${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}") - target_link_libraries(SRB2SDL2 PRIVATE SDL2::SDL2-static SDL2_mixer::SDL2_mixer-static) -else() - target_link_libraries(SRB2SDL2 PRIVATE SDL2::SDL2 SDL2_mixer::SDL2_mixer) -endif() - if("${CMAKE_SYSTEM_NAME}" MATCHES Linux) target_link_libraries(SRB2SDL2 PRIVATE m rt) endif() @@ -81,8 +232,84 @@ if("${CMAKE_SYSTEM_NAME}" MATCHES Windows) ) endif() -target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_MIXER -DSOUND=SOUND_MIXER) +find_package(SDL2 CONFIG REQUIRED) +find_package(SDL2 REQUIRED) +if(TARGET SDL2main) + target_link_libraries(SRB2SDL2 PRIVATE SDL2main) +endif() target_compile_definitions(SRB2SDL2 PRIVATE -DDIRECTFULLSCREEN -DHAVE_SDL) +target_include_directories(SRB2SDL2 PRIVATE ${SDL2_INCLUDE_DIR}) + +find_package(SDL2_mixer_ext CONFIG QUIET) +find_package(SDL2_mixer_ext QUIET) +if(TARGET SDL2_mixer_ext::SDL2_mixer_ext OR TARGET SDL2_mixer_ext::SDL2_mixer_ext_Static OR TARGET SDL2_mixer_ext OR TARGET SDL2_mixer_ext_Static) + if(NOT TARGET SDL2_mixer_ext::SDL2_mixer_ext_Static AND TARGET SDL2_mixer_ext_Static) + add_library(SDL2_mixer_ext::SDL2_mixer_ext_Static ALIAS SDL2_mixer_ext_Static) + endif() + if(NOT TARGET SDL2_mixer_ext::SDL2_mixer_ext AND TARGET SDL2_mixer_ext) + add_library(SDL2_mixer_ext::SDL2_mixer_ext ALIAS SDL2_mixer_ext) + endif() + if(TARGET SDL2_mixer_ext::SDL2_mixer_ext OR TARGET SDL2_mixer_ext::SDL2_mixer_ext_Static) + if(TARGET SDL2_mixer_ext::SDL2_mixer_ext_Static) + target_link_libraries(SRB2SDL2 PRIVATE SDL2_mixer_ext::SDL2_mixer_ext_Static) + else() + target_link_libraries(SRB2SDL2 PRIVATE SDL2_mixer_ext::SDL2_mixer_ext) + endif() + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_MIXER -DHAVE_MIXERX -DSOUND=SOUND_MIXER) + endif() +endif() + +if(TARGET SDL2_mixer_ext::SDL2_mixer_ext OR TARGET SDL2_mixer_ext::SDL2_mixer_ext_Static) + message(STATUS "SDL2_mixer_ext found, skipping SDL2_mixer") +else() + message(STATUS "SDL2_mixer_ext not found, going to try SDL2_mixer") + find_package(SDL2_mixer CONFIG QUIET) + find_package(SDL2_mixer QUIET) + if(TARGET SDL2_mixer::SDL2_mixer OR TARGET SDL2_mixer::SDL2_mixer-static OR TARGET SDL2_mixer OR TARGET SDL2_mixer_Static) + if(NOT TARGET SDL2_mixer::SDL2_mixer-static AND TARGET SDL2_mixer_Static) + add_library(SDL2_mixer::SDL2_mixer-static ALIAS SDL2_mixer_Static) + endif() + if(NOT TARGET SDL2_mixer::SDL2_mixer AND TARGET SDL2_mixer) + add_library(SDL2_mixer::SDL2_mixer ALIAS SDL2_mixer) + endif() + if(TARGET SDL2_mixer::SDL2_mixer OR TARGET SDL2_mixer::SDL2_mixer-static) + if(TARGET SDL2_mixer::SDL2_mixer-static) + target_link_libraries(SRB2SDL2 PRIVATE SDL2_mixer::SDL2_mixer-static) + else() + target_link_libraries(SRB2SDL2 PRIVATE SDL2_mixer::SDL2_mixer) + endif() + target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_MIXER -DSOUND=SOUND_MIXER) + endif() + endif() +endif() + +if(TARGET SDL2_mixer_ext::SDL2_mixer_ext OR TARGET SDL2_mixer_ext::SDL2_mixer_ext_Static OR TARGET SDL2_mixer::SDL2_mixer OR TARGET SDL2_mixer::SDL2_mixer-static) + target_sources(SRB2SDL2 PRIVATE mixer_sound.c) + target_link_libraries(SRB2SDL2 PRIVATE SDL2::SDL2) +else() + target_sources(SRB2SDL2 PRIVATE sdl_sound.c) + target_link_libraries(SRB2SDL2 PRIVATE SDL2::SDL2) +endif() + +if(TARGET SDL2::SDL2) + message(STATUS "SDL2 Found") +else() + message(STATUS "no SDL2 Found") +endif() + +if(TARGET SDL2::SDL2main) + message(STATUS "SDL2main Found") +else() + message(STATUS "No SDL2main Found") +endif() + +if(TARGET SDL2_mixer_ext::SDL2_mixer_ext OR TARGET SDL2_mixer_ext::SDL2_mixer_ext_Static) + message(STATUS "SDL2_mixer_ext Found") +elseif(TARGET SDL2_mixer::SDL2_mixer OR TARGET SDL2_mixer::SDL2_mixer-static) + message(STATUS "SDL2_mixer found") +else() + message(STATUS "no SDL2_mixer_ext or SDL2_mixer Found") +endif() #### Installation #### if("${CMAKE_SYSTEM_NAME}" MATCHES Darwin) diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index 4621700787f0c9b6395b5899730bc303a2699f1d..86ffa7082ac3210321a06c3b477ba3b6239947b9 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -165,7 +165,22 @@ <MultiProcessorCompilation>true</MultiProcessorCompilation> <MinimalRebuild>false</MinimalRebuild> <LanguageStandard>stdcpp17</LanguageStandard> + <PreprocessorDefinitions>HAVE_CURL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>..\..\libs\curl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> </ClCompile> + <CustomBuild> + <Command /> + </CustomBuild> + <CustomBuild> + <Message /> + </CustomBuild> + <CustomBuild> + <Outputs /> + </CustomBuild> + <Link> + <AdditionalDependencies>libcurl.dll.a;libz32.a;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalLibraryDirectories>..\..\libs\zlib\win32;..\..\libs\curl\lib32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ClCompile> @@ -175,8 +190,52 @@ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ClCompile> <DisableSpecificWarnings>4244;4267;4146;4003</DisableSpecificWarnings> + <PreprocessorDefinitions>HAVE_CURL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>..\..\libs\curl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <TreatWarningAsError>false</TreatWarningAsError> + </ClCompile> + <CustomBuild> + <Command /> + </CustomBuild> + <CustomBuild> + <Message /> + </CustomBuild> + <CustomBuild> + <Outputs /> + </CustomBuild> + <Link> + <AdditionalDependencies>libcurl.dll.a;libz32.a;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalLibraryDirectories>..\..\libs\zlib\win32;..\..\libs\curl\lib32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <TreatWarningAsError>false</TreatWarningAsError> </ClCompile> </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <MinimalRebuild>false</MinimalRebuild> + <DisableSpecificWarnings>4244;4267;4146</DisableSpecificWarnings> + <PreprocessorDefinitions>HAVE_CURL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>..\libs\curl\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalModuleDependencies>..\libs\curl\lib64;%(AdditionalModuleDependencies)</AdditionalModuleDependencies> + </ClCompile> + <Link> + <AdditionalDependencies>libcurl.a;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalLibraryDirectories>..\libs\curl\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <PreprocessorDefinitions>HAVE_CURL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + </ClCompile> + <Link> + <AdditionalDependencies>libcurl.a;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalLibraryDirectories>..\libs\curl\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + </Link> + </ItemDefinitionGroup> <ItemGroup> <ProjectReference Include="..\..\libs\libpng-src\projects\visualc10\libpng.vcxproj"> <Project>{72b01aca-7a1a-4f7b-acef-2607299cf052}</Project> @@ -314,7 +373,6 @@ <ClInclude Include="..\netcode\server_connection.h" /> <ClInclude Include="..\netcode\tic_command.h" /> <ClInclude Include="..\p5prof.h" /> - <ClInclude Include="..\p_haptic.h" /> <ClInclude Include="..\p_local.h" /> <ClInclude Include="..\p_maputl.h" /> <ClInclude Include="..\p_mobj.h" /> @@ -400,6 +458,7 @@ <ClCompile Include="..\blua\lmem.c" /> <ClCompile Include="..\blua\lobject.c" /> <ClCompile Include="..\blua\lopcodes.c" /> + <ClCompile Include="..\blua\loslib.c" /> <ClCompile Include="..\blua\lparser.c" /> <ClCompile Include="..\blua\lstate.c" /> <ClCompile Include="..\blua\lstring.c" /> @@ -437,7 +496,10 @@ <ClCompile Include="..\hardware\hw_md2load.c" /> <ClCompile Include="..\hardware\hw_md3load.c" /> <ClCompile Include="..\hardware\hw_model.c" /> + <ClCompile Include="..\hardware\hw_shaders.c" /> <ClCompile Include="..\hardware\r_opengl\r_opengl.c" /> + <ClCompile Include="..\lua_colorlib.c" /> + <ClCompile Include="..\r_bbox.c" /> <ClCompile Include="..\u_list.c" /> <ClCompile Include="..\hu_stuff.c" /> <ClCompile Include="..\info.c" /> @@ -495,7 +557,6 @@ <ClCompile Include="..\p_ceilng.c" /> <ClCompile Include="..\p_enemy.c" /> <ClCompile Include="..\p_floor.c" /> - <ClCompile Include="..\p_haptic.c" /> <ClCompile Include="..\p_inter.c" /> <ClCompile Include="..\p_lights.c" /> <ClCompile Include="..\p_map.c" /> @@ -513,9 +574,6 @@ <ClCompile Include="..\r_bsp.c" /> <ClCompile Include="..\r_data.c" /> <ClCompile Include="..\r_draw.c" /> - <ClCompile Include="..\r_draw16.c"> - <ExcludedFromBuild>true</ExcludedFromBuild> - </ClCompile> <ClCompile Include="..\r_draw8.c"> <ExcludedFromBuild>true</ExcludedFromBuild> </ClCompile> @@ -567,7 +625,6 @@ <ClCompile Include="IMG_xpm.c"> <ExcludedFromBuild>true</ExcludedFromBuild> </ClCompile> - <ClCompile Include="i_gamepad.c" /> <ClCompile Include="i_main.c" /> <ClCompile Include="i_net.c" /> <ClCompile Include="i_system.c" /> @@ -584,4 +641,4 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> -</Project> +</Project> \ No newline at end of file diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters index 59bb76b52089708abec222a46052d89f6b25ab6f..d2f9d018f2b3ef44e59def85634aa46ef24acd95 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj.filters +++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters @@ -255,9 +255,6 @@ <ClInclude Include="..\hardware\hw_model.h"> <Filter>Hw_Hardware</Filter> </ClInclude> - <ClInclude Include="..\hardware\u_list.h"> - <Filter>Hw_Hardware</Filter> - </ClInclude> <ClInclude Include="..\byteptr.h"> <Filter>I_Interface</Filter> </ClInclude> @@ -378,9 +375,6 @@ <ClInclude Include="..\netcode\gamestate.h"> <Filter>D_Doom</Filter> </ClInclude> - <ClInclude Include="..\netcode\http-mserv.h"> - <Filter>I_Interface</Filter> - </ClInclude> <ClInclude Include="..\netcode\i_addrinfo.h"> <Filter>I_Interface</Filter> </ClInclude> @@ -558,12 +552,16 @@ <ClInclude Include="..\r_fps.h"> <Filter>R_Rend</Filter> </ClInclude> - <ClInclude Include="..\p_haptic.h"> - <Filter>P_Play</Filter> - </ClInclude> <ClInclude Include="..\m_easing.h"> <Filter>M_Misc</Filter> </ClInclude> + <ClInclude Include="..\d_clisrv.h" /> + <ClInclude Include="..\d_net.h" /> + <ClInclude Include="..\d_netcmd.h" /> + <ClInclude Include="..\d_netfil.h" /> + <ClInclude Include="..\u_list.h" /> + <ClInclude Include="..\mserv.h" /> + <ClInclude Include="..\http-mserv.h" /> </ItemGroup> <ItemGroup> <CustomBuild Include="..\tmap.nas"> @@ -753,15 +751,15 @@ <ClCompile Include="..\hardware\hw_model.c"> <Filter>Hw_Hardware</Filter> </ClCompile> + <ClCompile Include="..\hardware\hw_shaders.c"> + <Filter>Hw_Hardware</Filter> + </ClCompile> <ClCompile Include="..\hardware\u_list.c"> <Filter>Hw_Hardware</Filter> </ClCompile> <ClCompile Include="..\filesrch.c"> <Filter>I_Interface</Filter> </ClCompile> - <ClCompile Include="..\i_tcp.c"> - <Filter>I_Interface</Filter> - </ClCompile> <ClCompile Include="..\lua_baselib.c"> <Filter>LUA</Filter> </ClCompile> @@ -984,9 +982,6 @@ <ClCompile Include="..\r_draw.c"> <Filter>R_Rend</Filter> </ClCompile> - <ClCompile Include="..\r_draw16.c"> - <Filter>R_Rend</Filter> - </ClCompile> <ClCompile Include="..\r_draw8.c"> <Filter>R_Rend</Filter> </ClCompile> @@ -1105,21 +1100,25 @@ <ClCompile Include="..\lua_hudlib_drawlist.c"> <Filter>LUA</Filter> </ClCompile> - <ClCompile Include="i_gamepad.c"> - <Filter>SDLApp</Filter> - </ClCompile> <ClCompile Include="..\i_time.c"> <Filter>I_Interface</Filter> </ClCompile> <ClCompile Include="..\r_fps.c"> <Filter>R_Rend</Filter> </ClCompile> - <ClCompile Include="..\p_haptic.c"> - <Filter>P_Play</Filter> - </ClCompile> <ClCompile Include="..\m_easing.c"> <Filter>M_Misc</Filter> </ClCompile> + <ClCompile Include="..\u_list.c" /> + <ClCompile Include="..\blua\loslib.c"> + <Filter>BLUA</Filter> + </ClCompile> + <ClCompile Include="..\lua_colorlib.c"> + <Filter>LUA</Filter> + </ClCompile> + <ClCompile Include="..\r_bbox.c"> + <Filter>R_Rend</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <Image Include="Srb2SDL.ico"> diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index 96e3d7d6926ef23771c8dcf489b4d8d2a16c0a1c..f561266017dd9fcf20b467b3c5e9323be7f5dbe2 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -74,7 +74,7 @@ void *hwSym(const char *funcName,void *handle) { void *funcPointer = NULL; #ifdef HWRENDER - if (0 == strcmp("SetPalette", funcName)) + if (0 == strcmp("SetTexturePalette", funcName)) funcPointer = &OglSdlSetPalette; GETFUNC(Init); @@ -87,7 +87,7 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(SetTexture); GETFUNC(UpdateTexture); GETFUNC(DeleteTexture); - GETFUNC(ReadRect); + GETFUNC(ReadScreenTexture); GETFUNC(GClipRect); GETFUNC(ClearMipMapCache); GETFUNC(SetSpecialState); @@ -97,21 +97,24 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(SetTransform); GETFUNC(PostImgRedraw); GETFUNC(FlushScreenTextures); - GETFUNC(StartScreenWipe); - GETFUNC(EndScreenWipe); GETFUNC(DoScreenWipe); - GETFUNC(DrawIntermissionBG); + GETFUNC(DrawScreenTexture); GETFUNC(MakeScreenTexture); - GETFUNC(MakeScreenFinalTexture); GETFUNC(DrawScreenFinalTexture); - GETFUNC(CompileShaders); - GETFUNC(CleanShaders); + GETFUNC(InitShaders); + GETFUNC(LoadShader); + GETFUNC(CompileShader); GETFUNC(SetShader); GETFUNC(UnSetShader); GETFUNC(SetShaderInfo); - GETFUNC(LoadCustomShader); + + GETFUNC(SetPaletteLookup); + GETFUNC(CreateLightTable); + GETFUNC(UpdateLightTable); + GETFUNC(ClearLightTables); + GETFUNC(SetScreenPalette); #else //HWRENDER if (0 == strcmp("FinishUpdate", funcName)) diff --git a/src/sdl/i_main.c b/src/sdl/i_main.c index f5fe9fb041b9f02057955afe072815e709b19dc3..b2177e563120fc76cf726353e5cad841e45b1762 100644 --- a/src/sdl/i_main.c +++ b/src/sdl/i_main.c @@ -186,6 +186,9 @@ int main(int argc, char **argv) #endif #endif + // disable text input right off the bat, since we don't need it at the start. + I_SetTextInputMode(false); + #ifdef LOGMESSAGES if (!M_CheckParm("-nolog")) InitLogging(); diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 847806270f78175624fd2fabcdcf32a0b9e0e29e..b2396e269b8d7cc456ee9f525aeda7991835cd4e 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -5,7 +5,7 @@ // // Copyright (C) 1993-1996 by id Software, Inc. // Portions Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 2014-2023 by Sonic Team Junior. +// Copyright (C) 2014-2025 by Sonic Team Junior. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -41,12 +41,6 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #include <ntsecapi.h> #undef SystemFunction036 -// A little more than the minimum sleep duration on Windows. -// May be incorrect for other platforms, but we don't currently have a way to -// query the scheduler granularity. SDL will do what's needed to make this as -// low as possible though. -#define MIN_SLEEP_DURATION_MS 2.1 - #endif #include <stdio.h> #include <stdlib.h> @@ -84,10 +78,11 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #include "SDL_cpuinfo.h" #define HAVE_SDLCPUINFO -#if defined (__unix__) || defined(__APPLE__) || (defined (UNIXCOMMON) && !defined (__HAIKU__)) -#if defined (__linux__) -#include <sys/vfs.h> +#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) +#if defined (__linux__) || defined (__HAIKU__) +#include <sys/statvfs.h> #else +#include <sys/statvfs.h> #include <sys/param.h> #include <sys/mount.h> /*For meminfo*/ @@ -100,7 +95,7 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #endif #endif -#if defined (__linux__) || (defined (UNIXCOMMON) && !defined (__HAIKU__)) +#if defined (__linux__) || defined (UNIXCOMMON) #ifndef NOTERMIOS #include <termios.h> #include <sys/ioctl.h> // ioctl @@ -108,11 +103,17 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #endif #endif +#if defined(UNIXCOMMON) +#include <poll.h> +#endif + #if defined (__unix__) || (defined (UNIXCOMMON) && !defined (__APPLE__)) #include <errno.h> #include <sys/wait.h> +#ifndef __HAIKU__ // haiku's crash dialog is just objectively better #define NEWSIGNALHANDLER #endif +#endif #ifndef NOMUMBLE #ifdef __linux__ // need -lrt @@ -221,6 +222,12 @@ static char returnWadPath[256]; #include "../byteptr.h" #endif +// A little more than the minimum sleep duration on Windows. +// May be incorrect for other platforms, but we don't currently have a way to +// query the scheduler granularity. SDL will do what's needed to make this as +// low as possible though. +#define MIN_SLEEP_DURATION_MS 2.1 + /** \brief The JoyReset function \param JoySet Joystick info to reset @@ -267,75 +274,86 @@ SDL_bool framebuffer = SDL_FALSE; UINT8 keyboard_started = false; #ifdef UNIXBACKTRACE -#define STDERR_WRITE(string) if (fd != -1) I_OutputMsg("%s", string) -#define CRASHLOG_WRITE(string) if (fd != -1) junk = write(fd, string, strlen(string)) -#define CRASHLOG_STDERR_WRITE(string) \ - if (fd != -1)\ - junk = write(fd, string, strlen(string));\ - I_OutputMsg("%s", string) + +static void bt_write_file(int fd, const char *string) { + ssize_t written = 0; + ssize_t sourcelen = strlen(string); + + while (fd != -1 && (written != -1 && errno != EINTR) && written < sourcelen) + written = write(fd, string, sourcelen); +} + +static void bt_write_stderr(const char *string) { + bt_write_file(STDERR_FILENO, string); +} + +static void bt_write_all(int fd, const char *string) { + bt_write_file(fd, string); + bt_write_file(STDERR_FILENO, string); +} static void write_backtrace(INT32 signal) { int fd = -1; -#ifndef NOEXECINFO - size_t size; -#endif time_t rawtime; struct tm timeinfo; - ssize_t junk; enum { BT_SIZE = 1024, STR_SIZE = 32 }; #ifndef NOEXECINFO - void *array[BT_SIZE]; + void *funcptrs[BT_SIZE]; + size_t bt_size; #endif char timestr[STR_SIZE]; - const char *error = "An error occurred within SRB2! Send this stack trace to someone who can help!\n"; - const char *error2 = "(Or find crash-log.txt in your SRB2 directory.)\n"; // Shown only to stderr. + const char *filename = va("%s" PATHSEP "%s", srb2home, "crash-log.txt"); - fd = open(va("%s" PATHSEP "%s", srb2home, "crash-log.txt"), O_CREAT|O_APPEND|O_RDWR, S_IRUSR|S_IWUSR); + fd = open(filename, O_CREAT|O_APPEND|O_RDWR, S_IRUSR|S_IWUSR); - if (fd == -1) - I_OutputMsg("\nWARNING: Couldn't open crash log for writing! Make sure your permissions are correct. Please save the below report!\n"); + if (fd == -1) // File handle error + bt_write_stderr("\nWARNING: Couldn't open crash log for writing! Make sure your permissions are correct. Please save the below report!\n"); // Get the current time as a string. time(&rawtime); localtime_r(&rawtime, &timeinfo); strftime(timestr, STR_SIZE, "%a, %d %b %Y %T %z", &timeinfo); - CRASHLOG_WRITE("------------------------\n"); // Nice looking seperator + bt_write_file(fd, "------------------------\n"); // Nice looking seperator - CRASHLOG_STDERR_WRITE("\n"); // Newline to look nice for both outputs. - CRASHLOG_STDERR_WRITE(error); // "Oops, SRB2 crashed" message - STDERR_WRITE(error2); // Tell the user where the crash log is. + bt_write_all(fd, "\n"); // Newline to look nice for both outputs. + bt_write_all(fd, "An error occurred within SRB2! Send this stack trace to someone who can help!\n"); + + if (fd != -1) // If the crash log exists, + bt_write_stderr("(Or find crash-log.txt in your SRB2 directory.)\n"); // tell the user where the crash log is. // Tell the log when we crashed. - CRASHLOG_WRITE("Time of crash: "); - CRASHLOG_WRITE(timestr); - CRASHLOG_WRITE("\n"); + bt_write_file(fd, "Time of crash: "); + bt_write_file(fd, timestr); + bt_write_file(fd, "\n"); // Give the crash log the cause and a nice 'Backtrace:' thing // The signal is given to the user when the parent process sees we crashed. - CRASHLOG_WRITE("Cause: "); - CRASHLOG_WRITE(strsignal(signal)); - CRASHLOG_WRITE("\n"); // Newline for the signal name + bt_write_file(fd, "Cause: "); + bt_write_file(fd, strsignal(signal)); + bt_write_file(fd, "\n"); // Newline for the signal name -#ifndef NOEXECINFO - CRASHLOG_STDERR_WRITE("\nBacktrace:\n"); +#ifdef NOEXECINFO + bt_write_all(fd, "\nNo Backtrace support\n"); +#else + bt_write_all(fd, "\nBacktrace:\n"); // Flood the output and log with the backtrace - size = backtrace(array, BT_SIZE); - backtrace_symbols_fd(array, size, fd); - backtrace_symbols_fd(array, size, STDERR_FILENO); + bt_size = backtrace(funcptrs, BT_SIZE); + backtrace_symbols_fd(funcptrs, bt_size, fd); + backtrace_symbols_fd(funcptrs, bt_size, STDERR_FILENO); #endif - CRASHLOG_WRITE("\n"); // Write another newline to the log so it looks nice :) - (void)junk; - close(fd); + bt_write_file(fd, "\n"); // Write another newline to the log so it looks nice :) + if (fd != -1) { + fsync(fd); // reaaaaally make sure we got that data written. + close(fd); + } } -#undef STDERR_WRITE -#undef CRASHLOG_WRITE -#undef CRASHLOG_STDERR_WRITE + #endif // UNIXBACKTRACE static void I_ReportSignal(int num, int coredumped) @@ -462,10 +480,9 @@ typedef struct feild_t tty_con; -// when printing general stuff to stdout stderr (Sys_Printf) -// we need to disable the tty console stuff -// this increments so we can recursively disable -static INT32 ttycon_hide = 0; +// lock to prevent clearing partial lines, since not everything +// printed ends on a newline. +static boolean ttycon_ateol = true; // some key codes that the terminal may be using // TTimo NOTE: I'm not sure how relevant this is static INT32 tty_erase; @@ -493,63 +510,31 @@ static inline void tty_FlushIn(void) // TTimo NOTE: it seems on some terminals just sending '\b' is not enough // so for now, in any case we send "\b \b" .. yeah well .. // (there may be a way to find out if '\b' alone would work though) +// Hanicef NOTE: using \b this way is unreliable because of terminal state, +// it's better to use \r to reset the cursor to the beginning of the +// line and clear from there. static void tty_Back(void) { - char key; - ssize_t d; - key = '\b'; - d = write(STDOUT_FILENO, &key, 1); - key = ' '; - d = write(STDOUT_FILENO, &key, 1); - key = '\b'; - d = write(STDOUT_FILENO, &key, 1); - (void)d; -} - -static void tty_Clear(void) -{ - size_t i; + write(STDOUT_FILENO, "\r", 1); if (tty_con.cursor>0) { - for (i=0; i<tty_con.cursor; i++) - { - tty_Back(); - } - } - -} - -// clear the display of the line currently edited -// bring cursor back to beginning of line -static inline void tty_Hide(void) -{ - //I_Assert(consolevent); - if (ttycon_hide) - { - ttycon_hide++; - return; + write(STDOUT_FILENO, tty_con.buffer, tty_con.cursor); } - tty_Clear(); - ttycon_hide++; + write(STDOUT_FILENO, " \b", 2); } -// show the current line -// FIXME TTimo need to position the cursor if needed?? -static inline void tty_Show(void) +static void tty_Clear(void) { size_t i; - ssize_t d; - //I_Assert(consolevent); - I_Assert(ttycon_hide>0); - ttycon_hide--; - if (ttycon_hide == 0 && tty_con.cursor) + write(STDOUT_FILENO, "\r", 1); + if (tty_con.cursor>0) { for (i=0; i<tty_con.cursor; i++) { - d = write(STDOUT_FILENO, tty_con.buffer+i, 1); + write(STDOUT_FILENO, " ", 1); } + write(STDOUT_FILENO, "\r", 1); } - (void)d; } // never exit without calling this, or your terminal will be left in a pretty bad state @@ -616,51 +601,65 @@ void I_GetConsoleEvents(void) // we use this when sending back commands event_t ev = {0}; char key = 0; - ssize_t d; + struct pollfd pfd = + { + .fd = STDIN_FILENO, + .events = POLLIN, + .revents = 0, + }; if (!consolevent) return; - ev.type = ev_console; - ev.key = 0; - if (read(STDIN_FILENO, &key, 1) == -1 || !key) - return; - - // we have something - // backspace? - // NOTE TTimo testing a lot of values .. seems it's the only way to get it to work everywhere - if ((key == tty_erase) || (key == 127) || (key == 8)) + for (;;) { - if (tty_con.cursor > 0) + if (poll(&pfd, 1, 0) < 1 || !(pfd.revents & POLLIN)) + return; + + ev.type = ev_console; + ev.key = 0; + if (read(STDIN_FILENO, &key, 1) == -1 || !key) + return; + + // we have something + // backspace? + // NOTE TTimo testing a lot of values .. seems it's the only way to get it to work everywhere + if ((key == tty_erase) || (key == 127) || (key == 8)) { - tty_con.cursor--; - tty_con.buffer[tty_con.cursor] = '\0'; - tty_Back(); + if (tty_con.cursor > 0) + { + tty_con.cursor--; + tty_con.buffer[tty_con.cursor] = '\0'; + tty_Back(); + } + ev.key = KEY_BACKSPACE; } - ev.key = KEY_BACKSPACE; - } - else if (key < ' ') // check if this is a control char - { - if (key == '\n') + else if (key < ' ') // check if this is a control char { - tty_Clear(); - tty_con.cursor = 0; - ev.key = KEY_ENTER; + if (key == '\n') + { + tty_Clear(); + tty_con.cursor = 0; + ev.key = KEY_ENTER; + } + else if (key == 0x4) // ^D, aka EOF + { + // shut down, most unix programs behave this way + I_Quit(); + } + else continue; } - else return; - } - else if (tty_con.cursor < sizeof (tty_con.buffer)) - { - // push regular character - ev.type = ev_text; - ev.key = tty_con.buffer[tty_con.cursor] = key; - tty_con.cursor++; - // print the current line (this is differential) - d = write(STDOUT_FILENO, &key, 1); + else if (tty_con.cursor < sizeof (tty_con.buffer)) + { + // push regular character + ev.key = tty_con.buffer[tty_con.cursor] = key; + tty_con.cursor++; + // print the current line (this is differential) + write(STDOUT_FILENO, &key, 1); + } + if (ev.key) D_PostEvent(&ev); + //tty_FlushIn(); } - if (ev.key) D_PostEvent(&ev); - //tty_FlushIn(); - (void)d; } #elif defined (_WIN32) @@ -855,9 +854,16 @@ static void I_RegisterChildSignals(void) void I_OutputMsg(const char *fmt, ...) { size_t len; - char txt[8192]; + char *txt; va_list argptr; + va_start(argptr,fmt); + len = vsnprintf(NULL, 0, fmt, argptr); + va_end(argptr); + if (len == 0) + return; + + txt = malloc(len+1); va_start(argptr,fmt); vsprintf(txt, fmt, argptr); va_end(argptr); @@ -891,7 +897,10 @@ void I_OutputMsg(const char *fmt, ...) DWORD bytesWritten; if (co == INVALID_HANDLE_VALUE) + { + free(txt); return; + } if (GetFileType(co) == FILE_TYPE_CHAR && GetConsoleMode(co, &bytesWritten)) { @@ -907,11 +916,16 @@ void I_OutputMsg(const char *fmt, ...) if (oldLength > 0) { LPVOID blank = malloc(oldLength); - if (!blank) return; + if (!blank) + { + free(txt); + return; + } memset(blank, ' ', oldLength); // Blank out. oldLines = malloc(oldLength*sizeof(TCHAR)); if (!oldLines) { + free(txt); free(blank); return; } @@ -946,18 +960,20 @@ void I_OutputMsg(const char *fmt, ...) } #else #ifdef HAVE_TERMIOS - if (consolevent) + if (consolevent && ttycon_ateol) { - tty_Hide(); + tty_Clear(); + ttycon_ateol = false; } #endif if (!framebuffer) fprintf(stderr, "%s", txt); #ifdef HAVE_TERMIOS - if (consolevent) + if (consolevent && txt[len-1] == '\n') { - tty_Show(); + write(STDOUT_FILENO, tty_con.buffer, tty_con.cursor); + ttycon_ateol = true; } #endif @@ -966,6 +982,7 @@ void I_OutputMsg(const char *fmt, ...) fflush(stderr); #endif + free(txt); } // @@ -1701,7 +1718,7 @@ const char *I_GetJoyName(INT32 joyindex) { tempname = SDL_JoystickNameForIndex(joyindex); if (tempname) - strncpy(joyname, tempname, 255); + strncpy(joyname, tempname, sizeof(joyname)-1); } return joyname; } @@ -2283,16 +2300,25 @@ void I_Sleep(UINT32 ms) void I_SleepDuration(precise_t duration) { -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(__linux__) || defined(__FreeBSD__) || defined(__HAIKU__) UINT64 precision = I_GetPrecisePrecision(); - struct timespec ts = { - .tv_sec = duration / precision, - .tv_nsec = duration * 1000000000 / precision % 1000000000, - }; - int status; - do status = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts); - while (status == EINTR); -#else + precise_t dest = I_GetPreciseTime() + duration; + precise_t slack = (precision / 5000); // 0.2 ms slack + if (duration > slack) + { + duration -= slack; + struct timespec ts = { + .tv_sec = duration / precision, + .tv_nsec = duration * 1000000000 / precision % 1000000000, + }; + int status; + do status = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts); + while (status == EINTR); + } + + // busy-wait the rest + while (((INT64)dest - (INT64)I_GetPreciseTime()) > 0); +#elif defined (MIN_SLEEP_DURATION_MS) UINT64 precision = I_GetPrecisePrecision(); INT32 sleepvalue = cv_sleep.value; UINT64 delaygranularity; @@ -2730,18 +2756,13 @@ void I_ShutdownSystem(void) void I_GetDiskFreeSpace(INT64 *freespace) { #if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) -#if defined (SOLARIS) || defined (__HAIKU__) - *freespace = INT32_MAX; - return; -#else // Both Linux and BSD have this, apparently. - struct statfs stfs; - if (statfs(srb2home, &stfs) == -1) + struct statvfs stfs; + if (statvfs(srb2home, &stfs) == -1) { *freespace = INT32_MAX; return; } *freespace = stfs.f_bavail * stfs.f_bsize; -#endif #elif defined (_WIN32) static p_GetDiskFreeSpaceExA pfnGetDiskFreeSpaceEx = NULL; static boolean testwin95 = false; @@ -2844,7 +2865,7 @@ size_t I_GetRandomBytes(char *destination, size_t count) { #if defined (__unix__) || defined (UNIXCOMMON) || defined(__APPLE__) FILE *rndsource; - size_t actual_bytes; + size_t actual_bytes = 0; if (!(rndsource = fopen("/dev/urandom", "r"))) if (!(rndsource = fopen("/dev/random", "r"))) @@ -2963,7 +2984,7 @@ static void pathonly(char *s) */ static const char *searchWad(const char *searchDir) { - static char tempsw[256] = ""; + static char tempsw[MAX_WADPATH] = ""; filestatus_t fstemp; strcpy(tempsw, WADKEYWORD1); @@ -2979,8 +3000,8 @@ static const char *searchWad(const char *searchDir) #define CHECKWADPATH(ret) \ do { \ - I_OutputMsg(",%s", returnWadPath); \ - if (isWadPathOk(returnWadPath)) \ + I_OutputMsg(",%s", ret); \ + if (isWadPathOk(ret)) \ return ret; \ } while (0) @@ -3009,7 +3030,9 @@ static const char *locateWad(void) #ifndef NOCWD // examine current dir strcpy(returnWadPath, "."); - CHECKWADPATH(NULL); + I_OutputMsg(",%s", returnWadPath); + if (isWadPathOk(returnWadPath)) + return NULL; #endif #ifdef __APPLE__ @@ -3026,9 +3049,16 @@ static const char *locateWad(void) #ifndef NOHOME // find in $HOME - I_OutputMsg(",HOME"); + I_OutputMsg(",HOME/" DEFAULTDIR); if ((envstr = I_GetEnv("HOME")) != NULL) - SEARCHWAD(envstr); + { + char *tmp = malloc(strlen(envstr) + 1 + sizeof(DEFAULTDIR)); + strcpy(tmp, envstr); + strcat(tmp, "/"); + strcat(tmp, DEFAULTDIR); + CHECKWADPATH(tmp); + free(tmp); + } #endif // search paths @@ -3054,8 +3084,10 @@ const char *I_LocateWad(void) { // change to the directory where we found srb2.pk3 #if defined (_WIN32) + waddir = _fullpath(NULL, waddir, MAX_PATH); SetCurrentDirectoryA(waddir); #else + waddir = realpath(waddir, NULL); if (chdir(waddir) == -1) I_OutputMsg("Couldn't change working directory\n"); #endif @@ -3256,4 +3288,24 @@ const CPUInfoFlags *I_CPUInfo(void) // note CPUAFFINITY code used to reside here void I_RegisterSysCommands(void) {} + +const char *I_GetSysName(void) +{ + return SDL_GetPlatform(); +} + + +void I_SetTextInputMode(boolean active) +{ + if (active) + SDL_StartTextInput(); + else + SDL_StopTextInput(); +} + +boolean I_GetTextInputMode(void) +{ + return SDL_IsTextInputActive(); +} + #endif diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index d3a602c05803fcd5d6aced670321aad5c723ea74..82583ccb4651ff8cbfc42be4a0f40ee54bd31d7d 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -87,7 +87,7 @@ #endif // maximum number of windowed modes (see windowedModes[][]) -#define MAXWINMODES (18) +#define MAXWINMODES (21) /** \brief */ @@ -100,8 +100,6 @@ static char vidModeName[33][32]; // allow 33 different modes rendermode_t rendermode = render_soft; rendermode_t chosenrendermode = render_none; // set by command line arguments -boolean highcolor = false; - static void VidWaitChanged(void); // synchronize page flipping with screen refresh @@ -159,7 +157,9 @@ static INT32 windowedModes[MAXWINMODES][2] = {1920,1080}, // 1.66 {1680,1050}, // 1.60,5.25 {1600,1200}, // 1.33 + {1600,1000}, // 1.60,5.00 {1600, 900}, // 1.66 + {1536, 864}, // 1.66,4.80 {1366, 768}, // 1.66 {1440, 900}, // 1.60,4.50 {1280,1024}, // 1.33? @@ -168,6 +168,7 @@ static INT32 windowedModes[MAXWINMODES][2] = {1280, 720}, // 1.66 {1152, 864}, // 1.33,3.60 {1024, 768}, // 1.33,3.20 + { 960, 600}, // 1.60,3.00 { 800, 600}, // 1.33,2.50 { 640, 480}, // 1.33,2.00 { 640, 400}, // 1.60,2.00 @@ -384,6 +385,8 @@ static INT32 Impl_SDL_Scancode_To_Keycode(SDL_Scancode code) static boolean ShouldIgnoreMouse(void) { + if (cv_alwaysgrabmouse.value) + return false; if (menuactive) return !M_MouseNeeded(); if (paused || con_destlines || chat_on) @@ -1297,6 +1300,14 @@ void I_FinishUpdate(void) #ifdef HWRENDER else if (rendermode == render_opengl) { + // Final postprocess step of palette rendering, after everything else has been drawn. + if (HWR_ShouldUsePaletteRendering()) + { + HWD.pfnMakeScreenTexture(HWD_SCREENTEXTURE_GENERIC2); + HWD.pfnSetShader(HWR_GetShaderFromTarget(SHADER_PALETTE_POSTPROCESS)); + HWD.pfnDrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2, NULL, 0); + HWD.pfnUnSetShader(); + } OglSdlFinishUpdate(cv_vidwait.value); } #endif @@ -1395,103 +1406,12 @@ INT32 VID_GetModeForSize(INT32 w, INT32 h) } } return -1; -#if 0 - INT32 matchMode = -1, i; - VID_PrepareModeList(); - if (USE_FULLSCREEN && numVidModes != -1) - { - for (i=firstEntry; i<numVidModes; i++) - { - if (modeList[i]->w == w && - modeList[i]->h == h) - { - matchMode = i; - break; - } - } - if (-1 == matchMode) // use smaller mode - { - w -= w%BASEVIDWIDTH; - h -= h%BASEVIDHEIGHT; - for (i=firstEntry; i<numVidModes; i++) - { - if (modeList[i]->w == w && - modeList[i]->h == h) - { - matchMode = i; - break; - } - } - if (-1 == matchMode) // use smallest mode - matchMode = numVidModes-1; - } - matchMode -= firstEntry; - } - else - { - for (i=0; i<MAXWINMODES; i++) - { - if (windowedModes[i][0] == w && - windowedModes[i][1] == h) - { - matchMode = i; - break; - } - } - if (-1 == matchMode) // use smaller mode - { - w -= w%BASEVIDWIDTH; - h -= h%BASEVIDHEIGHT; - for (i=0; i<MAXWINMODES; i++) - { - if (windowedModes[i][0] == w && - windowedModes[i][1] == h) - { - matchMode = i; - break; - } - } - if (-1 == matchMode) // use smallest mode - matchMode = MAXWINMODES-1; - } - } - return matchMode; -#endif } void VID_PrepareModeList(void) { // Under SDL2, we just use the windowed modes list, and scale in windowed fullscreen. allow_fullscreen = true; -#if 0 - INT32 i; - - firstEntry = 0; - -#ifdef HWRENDER - if (rendermode == render_opengl) - modeList = SDL_ListModes(NULL, SDL_OPENGL|SDL_FULLSCREEN); - else -#endif - modeList = SDL_ListModes(NULL, surfaceFlagsF|SDL_HWSURFACE); //Alam: At least hardware surface - - if (disable_fullscreen?0:cv_fullscreen.value) // only fullscreen needs preparation - { - if (-1 != numVidModes) - { - for (i=0; i<numVidModes; i++) - { - if (modeList[i]->w <= MAXVIDWIDTH && - modeList[i]->h <= MAXVIDHEIGHT) - { - firstEntry = i; - break; - } - } - } - } - allow_fullscreen = true; -#endif } static SDL_bool Impl_CreateContext(void) @@ -1789,7 +1709,7 @@ static void Impl_VideoSetupBuffer(void) vid.direct = NULL; if (vid.buffer) free(vid.buffer); - vid.buffer = calloc(vid.rowbytes*vid.height, NUMSCREENS); + vid.buffer = calloc(NUMSCREENS, vid.rowbytes*vid.height); if (!vid.buffer) { I_Error("%s", M_GetText("Not enough memory for video buffer\n")); @@ -1958,32 +1878,35 @@ void VID_StartupOpenGL(void) HWD.pfnSetTexture = hwSym("SetTexture",NULL); HWD.pfnUpdateTexture = hwSym("UpdateTexture",NULL); HWD.pfnDeleteTexture = hwSym("DeleteTexture",NULL); - HWD.pfnReadRect = hwSym("ReadRect",NULL); + HWD.pfnReadScreenTexture= hwSym("ReadScreenTexture",NULL); HWD.pfnGClipRect = hwSym("GClipRect",NULL); HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL); HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL); - HWD.pfnSetPalette = hwSym("SetPalette",NULL); + HWD.pfnSetTexturePalette= hwSym("SetTexturePalette",NULL); HWD.pfnGetTextureUsed = hwSym("GetTextureUsed",NULL); HWD.pfnDrawModel = hwSym("DrawModel",NULL); HWD.pfnCreateModelVBOs = hwSym("CreateModelVBOs",NULL); HWD.pfnSetTransform = hwSym("SetTransform",NULL); HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL); HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL); - HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL); - HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL); HWD.pfnDoScreenWipe = hwSym("DoScreenWipe",NULL); - HWD.pfnDrawIntermissionBG=hwSym("DrawIntermissionBG",NULL); + HWD.pfnDrawScreenTexture= hwSym("DrawScreenTexture",NULL); HWD.pfnMakeScreenTexture= hwSym("MakeScreenTexture",NULL); - HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL); HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL); - HWD.pfnCompileShaders = hwSym("CompileShaders",NULL); - HWD.pfnCleanShaders = hwSym("CleanShaders",NULL); + HWD.pfnInitShaders = hwSym("InitShaders",NULL); + HWD.pfnLoadShader = hwSym("LoadShader",NULL); + HWD.pfnCompileShader = hwSym("CompileShader",NULL); HWD.pfnSetShader = hwSym("SetShader",NULL); HWD.pfnUnSetShader = hwSym("UnSetShader",NULL); HWD.pfnSetShaderInfo = hwSym("SetShaderInfo",NULL); - HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL); + + HWD.pfnSetPaletteLookup = hwSym("SetPaletteLookup",NULL); + HWD.pfnCreateLightTable = hwSym("CreateLightTable",NULL); + HWD.pfnUpdateLightTable = hwSym("UpdateLightTable",NULL); + HWD.pfnClearLightTables = hwSym("ClearLightTables",NULL); + HWD.pfnSetScreenPalette = hwSym("SetScreenPalette",NULL); vid.glstate = HWD.pfnInit() ? VID_GL_LIBRARY_LOADED : VID_GL_LIBRARY_ERROR; // let load the OpenGL library @@ -2026,8 +1949,6 @@ void I_ShutdownGraphics(void) I_OutputMsg("shut down\n"); #ifdef HWRENDER - if (GLUhandle) - hwClose(GLUhandle); if (sdlglcontext) { SDL_GL_DeleteContext(sdlglcontext); diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index a5be3a754ce5a44b5c985f5881300d06a5ad07c7..8f2ca340879d5236822c534b2f9da57774a5356e 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -140,15 +140,18 @@ static void Midiplayer_Onchange(void) restart = true; } - if (stricmp(Mix_GetSoundFonts(), cv_midisoundfontpath.string)) + if (!Mix_GetSoundFonts() || stricmp(Mix_GetSoundFonts(), cv_midisoundfontpath.string)) { if (!Mix_SetSoundFonts(cv_midisoundfontpath.string)) // == 0 means error CONS_Alert(CONS_ERROR, "Sound font error: %s", Mix_GetError()); else restart = true; } - +#if SDL_MIXER_VERSION_ATLEAST(2,5,0) + Mix_SetTimidityCfg(cv_miditimiditypath.string); +#else Mix_Timidity_addToPathList(cv_miditimiditypath.string); +#endif if (restart) S_StartEx(true); @@ -159,7 +162,7 @@ static void MidiSoundfontPath_Onchange(void) if (Mix_GetMidiPlayer() != MIDI_Fluidsynth || (I_SongType() != MU_NONE && I_SongType() != MU_MID_EX)) return; - if (stricmp(Mix_GetSoundFonts(), cv_midisoundfontpath.string)) + if (!Mix_GetSoundFonts() || stricmp(Mix_GetSoundFonts(), cv_midisoundfontpath.string)) { char *miditoken; char *source = strdup(cv_midisoundfontpath.string); @@ -286,8 +289,12 @@ void I_StartupSound(void) #ifdef HAVE_MIXERX Mix_SetMidiPlayer(cv_midiplayer.value); Mix_SetSoundFonts(cv_midisoundfontpath.string); +#if SDL_MIXER_VERSION_ATLEAST(2,5,0) + Mix_SetTimidityCfg(cv_miditimiditypath.string); +#else Mix_Timidity_addToPathList(cv_miditimiditypath.string); #endif +#endif #if SDL_MIXER_VERSION_ATLEAST(1,2,11) Mix_Init(MIX_INIT_FLAC|MIX_INIT_MP3|MIX_INIT_OGG|MIX_INIT_MOD); #endif @@ -942,7 +949,12 @@ UINT32 I_GetSongLength(void) else { #ifdef HAVE_MIXERX +#if SDL_MIXER_VERSION_ATLEAST(2,5,0) + double xlength = Mix_MusicDuration(music); +#else double xlength = Mix_GetMusicTotalTime(music); +#endif + if (xlength >= 0) return (UINT32)(xlength*1000); #endif @@ -1198,10 +1210,14 @@ boolean I_LoadSong(char *data, size_t len) #ifdef HAVE_MIXERX if (Mix_GetMidiPlayer() != cv_midiplayer.value) Mix_SetMidiPlayer(cv_midiplayer.value); - if (stricmp(Mix_GetSoundFonts(), cv_midisoundfontpath.string)) + if (!Mix_GetSoundFonts() || stricmp(Mix_GetSoundFonts(), cv_midisoundfontpath.string)) Mix_SetSoundFonts(cv_midisoundfontpath.string); +#if SDL_MIXER_VERSION_ATLEAST(2,5,0) + Mix_SetTimidityCfg(cv_miditimiditypath.string); +#else Mix_Timidity_addToPathList(cv_miditimiditypath.string); // this overwrites previous custom path #endif +#endif #ifdef HAVE_OPENMPT /* diff --git a/src/sdl/ogl_sdl.c b/src/sdl/ogl_sdl.c index db0538195bbb6d98badb0fc27c5b0a9fac34fa81..c78b43ec4097cafad8420ceb7497e2883220a67e 100644 --- a/src/sdl/ogl_sdl.c +++ b/src/sdl/ogl_sdl.c @@ -70,18 +70,10 @@ PFNglGetString pglGetString; /** \brief SDL video display surface */ INT32 oglflags = 0; -void *GLUhandle = NULL; SDL_GLContext sdlglcontext = 0; void *GetGLFunc(const char *proc) { - if (strncmp(proc, "glu", 3) == 0) - { - if (GLUhandle) - return hwSym(proc, GLUhandle); - else - return NULL; - } return SDL_GL_GetProcAddress(proc); } @@ -89,7 +81,6 @@ boolean LoadGL(void) { #ifndef STATIC_OPENGL const char *OGLLibname = NULL; - const char *GLULibname = NULL; if (M_CheckParm("-OGLlib") && M_IsNextParm()) OGLLibname = M_GetNextParm(); @@ -102,43 +93,6 @@ boolean LoadGL(void) CONS_Printf("If you know what is the OpenGL library's name, use -OGLlib\n"); return 0; } - -#if 0 - GLULibname = "/proc/self/exe"; -#elif defined (_WIN32) - GLULibname = "GLU32.DLL"; -#elif defined (__MACH__) - GLULibname = "/System/Library/Frameworks/OpenGL.framework/Libraries/libGLU.dylib"; -#elif defined (macintos) - GLULibname = "OpenGLLibrary"; -#elif defined (__unix__) - GLULibname = "libGLU.so.1"; -#elif defined (__HAIKU__) - GLULibname = "libGLU.so"; -#else - GLULibname = NULL; -#endif - - if (M_CheckParm("-GLUlib") && M_IsNextParm()) - GLULibname = M_GetNextParm(); - - if (GLULibname) - { - GLUhandle = hwOpen(GLULibname); - if (GLUhandle) - return SetupGLfunc(); - else - { - CONS_Alert(CONS_ERROR, "Could not load GLU Library: %s\n", GLULibname); - if (!M_CheckParm ("-GLUlib")) - CONS_Alert(CONS_ERROR, "If you know what is the GLU library's name, use -GLUlib\n"); - } - } - else - { - CONS_Alert(CONS_ERROR, "Could not load GLU Library\n"); - CONS_Alert(CONS_ERROR, "If you know what is the GLU library's name, use -GLUlib\n"); - } #endif return SetupGLfunc(); } @@ -155,6 +109,7 @@ boolean OglSdlSurface(INT32 w, INT32 h) { INT32 cbpp = cv_scr_depth.value < 16 ? 16 : cv_scr_depth.value; static boolean first_init = false; + static int majorGL = 0, minorGL = 0; oglflags = 0; @@ -189,6 +144,12 @@ boolean OglSdlSurface(INT32 w, INT32 h) else maximumAnisotropy = 1; + if (sscanf((const char*)gl_version, "%d.%d", &majorGL, &minorGL) + && (!(majorGL == 1 && minorGL <= 3))) + supportMipMap = true; + else + supportMipMap = false; + SetupGLFunc4(); glanisotropicmode_cons_t[1].value = maximumAnisotropy; @@ -232,7 +193,9 @@ void OglSdlFinishUpdate(boolean waitvbl) // Sryder: We need to draw the final screen texture again into the other buffer in the original position so that // effects that want to take the old screen can do so after this - HWR_DrawScreenFinalTexture(realwidth, realheight); + // Generic2 has the screen image without palette rendering brightness adjustments. + // Using that here will prevent brightness adjustments being applied twice. + DrawScreenTexture(HWD_SCREENTEXTURE_GENERIC2, NULL, 0); } EXPORT void HWRAPI(OglSdlSetPalette) (RGBA_t *palette) diff --git a/src/sdl/ogl_sdl.h b/src/sdl/ogl_sdl.h index bd1d699ff44db27a4599bfb81d4f65e34ac7f858..87df5e5e6115334dd8705658d70f9f6e5b6706f8 100644 --- a/src/sdl/ogl_sdl.h +++ b/src/sdl/ogl_sdl.h @@ -19,8 +19,6 @@ #include "../v_video.h" -extern void *GLUhandle; - boolean OglSdlSurface(INT32 w, INT32 h); void OglSdlFinishUpdate(boolean vidwait); diff --git a/src/snake.c b/src/snake.c index 2349d5fdbfb6d66af7d4bc55df03b553052153c8..4219d5b8fa54ee69ce1b99167e697e935cd3483b 100644 --- a/src/snake.c +++ b/src/snake.c @@ -582,7 +582,7 @@ boolean Snake_JoyGrabber(void *opaque, event_t *ev) { snake_t *snake = opaque; - if (ev->type == ev_joystick && ev->key == 0) + if (snake != NULL && ev->type == ev_joystick && ev->key == 0) { snake->joyevents[snake->joyeventcount] = ev; snake->joyeventcount++; diff --git a/src/st_stuff.c b/src/st_stuff.c index f3a73ce2616186574f3b390ce96dd79b7f0f717f..4fdacd51ada1871c4a711f91749e0d9b39872796 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -134,10 +134,12 @@ static patch_t *minicaps; static patch_t *gotrflag; static patch_t *gotbflag; static patch_t *fnshico; +static patch_t *fireflower; hudinfo_t hudinfo[NUMHUDITEMS] = { { 16, 176, V_SNAPTOLEFT|V_SNAPTOBOTTOM}, // HUD_LIVES + { 16, 152, V_SNAPTOLEFT|V_SNAPTOBOTTOM}, // HUD_INPUT { 16, 42, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_RINGS { 96, 42, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_RINGSNUM @@ -226,8 +228,8 @@ void ST_doPaletteStuff(void) palette = 0; #ifdef HWRENDER - if (rendermode == render_opengl) - palette = 0; // No flashpals here in OpenGL + if (rendermode == render_opengl && !HWR_ShouldUsePaletteRendering()) + palette = 0; // Don't set the palette to a flashpal in OpenGL's truecolor mode #endif if (palette != st_palette) @@ -252,10 +254,6 @@ void ST_LoadGraphics(void) { int i; - // SRB2 border patch - // st_borderpatchnum = W_GetNumForName("GFZFLR01"); - // scr_borderpatch = W_CacheLumpNum(st_borderpatchnum, PU_HUDGFX); - // the original Doom uses 'STF' as base name for all face graphics // Graue 04-08-2004: face/name graphics are now indexed by skins // but load them in R_AddSkins, that gets called @@ -315,6 +313,8 @@ void ST_LoadGraphics(void) sneakers = W_CachePatchName("TVSSICON", PU_HUDGFX); gravboots = W_CachePatchName("TVGVICON", PU_HUDGFX); + fireflower = W_CachePatchName("GOTFFLOW", PU_HUDGFX); + tagico = W_CachePatchName("TAGICO", PU_HUDGFX); gotrflag = W_CachePatchName("GOTRFLAG", PU_HUDGFX); gotbflag = W_CachePatchName("GOTBFLAG", PU_HUDGFX); @@ -371,9 +371,11 @@ void ST_LoadFaceGraphics(INT32 skinnum) spritedef_t *sprdef = &skins[skinnum]->sprites[SPR2_XTRA]; spriteframe_t *sprframe = &sprdef->spriteframes[XTRA_LIFEPIC]; faceprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX); - if (skins[skinnum]->sprites[(SPR2_XTRA|FF_SPR2SUPER)].numframes > XTRA_LIFEPIC) + + spritedef_t *super_sprdef = P_GetSkinSpritedef(skins[skinnum], SPR2_XTRA|SPR2F_SUPER); + if (super_sprdef->numframes > XTRA_LIFEPIC) { - sprdef = &skins[skinnum]->sprites[SPR2_XTRA|FF_SPR2SUPER]; + sprdef = super_sprdef; sprframe = &sprdef->spriteframes[0]; superprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX); } @@ -507,7 +509,7 @@ static void ST_DrawNightsOverlayNum(fixed_t x /* right border */, fixed_t y, fix static void ST_drawDebugInfo(void) { INT32 height = 0, h = 8, w = 18, lowh; - void (*textfunc)(INT32, INT32, INT32, const char *); + fixed_t textscale = FRACUNIT/2; if (!(stplyr->mo && cv_debug)) return; @@ -516,12 +518,12 @@ static void ST_drawDebugInfo(void) if ((moviemode == MM_GIF && cv_gif_downscale.value) || vid.dup == 1) { - textfunc = V_DrawRightAlignedString; + textscale = FRACUNIT; lowh = ((vid.height/vid.dup) - 16); } else { - textfunc = V_DrawRightAlignedSmallString; + textscale = FRACUNIT/2; h /= 2; w /= 2; lowh = 0; @@ -532,10 +534,10 @@ static void ST_drawDebugInfo(void) V_DrawRightAlignedThinString(320, 8+lowh, VFLAGS|V_REDMAP, "SOME INFO NOT VISIBLE");\ return;\ }\ - textfunc(320, height, VFLAGS, str);\ + V_DrawAlignedFontString(320, height, VFLAGS, textscale, textscale, str, hu_font, alignright);\ height += h; -#define V_DrawDebugFlag(f, str) textfunc(width, height, VFLAGS|f, str);\ +#define V_DrawDebugFlag(f, str) V_DrawAlignedFontString(width, height, VFLAGS|f, textscale, textscale, str, hu_font, alignright);\ width -= w if (cv_debug & DBG_MEMORY) @@ -815,7 +817,7 @@ static inline void ST_drawRings(void) static void ST_drawLivesArea(void) { - INT32 v_colmap = V_YELLOWMAP, livescount; + INT32 v_colmap = V_YELLOWMAP, livescount = -1; boolean notgreyedout = false; if (!stplyr->skincolor) @@ -1038,32 +1040,39 @@ static void ST_drawInput(void) INT32 col; UINT8 offs; - INT32 x = hudinfo[HUD_LIVES].x, y = hudinfo[HUD_LIVES].y; + INT32 x = hudinfo[HUD_INPUT].x, y = hudinfo[HUD_INPUT].y; + + if (hu_showscores) + return; if (stplyr->powers[pw_carry] == CR_NIGHTSMODE) - y -= 16; + y += 8; + else if (modeattacking || !LUA_HudEnabled(hud_lives)) + y += 24; + else if (G_RingSlingerGametype() && LUA_HudEnabled(hud_powerstones)) + y -= 5; if (F_GetPromptHideHud(y)) return; // O backing - V_DrawFill(x, y-1, 16, 16, hudinfo[HUD_LIVES].f|20); - V_DrawFill(x, y+15, 16, 1, hudinfo[HUD_LIVES].f|29); + V_DrawFill(x, y-1, 16, 16, hudinfo[HUD_INPUT].f|20); + V_DrawFill(x, y+15, 16, 1, hudinfo[HUD_INPUT].f|29); if (cv_showinputjoy.value) // joystick render! { - /*V_DrawFill(x , y , 16, 1, hudinfo[HUD_LIVES].f|16); - V_DrawFill(x , y+15, 16, 1, hudinfo[HUD_LIVES].f|16); - V_DrawFill(x , y+ 1, 1, 14, hudinfo[HUD_LIVES].f|16); - V_DrawFill(x+15, y+ 1, 1, 14, hudinfo[HUD_LIVES].f|16); -- red's outline*/ + /*V_DrawFill(x , y , 16, 1, hudinfo[HUD_INPUT.f|16); + V_DrawFill(x , y+15, 16, 1, hudinfo[HUD_INPUT].f|16); + V_DrawFill(x , y+ 1, 1, 14, hudinfo[HUD_INPUT].f|16); + V_DrawFill(x+15, y+ 1, 1, 14, hudinfo[HUD_INPUT].f|16); -- red's outline*/ if (stplyr->cmd.sidemove || stplyr->cmd.forwardmove) { // joystick hole - V_DrawFill(x+5, y+4, 6, 6, hudinfo[HUD_LIVES].f|29); + V_DrawFill(x+5, y+4, 6, 6, hudinfo[HUD_INPUT].f|29); // joystick top V_DrawFill(x+3+stplyr->cmd.sidemove/12, y+2-stplyr->cmd.forwardmove/12, - 10, 10, hudinfo[HUD_LIVES].f|29); + 10, 10, hudinfo[HUD_INPUT].f|29); V_DrawFill(x+3+stplyr->cmd.sidemove/9, y+1-stplyr->cmd.forwardmove/9, 10, 10, accent); @@ -1071,10 +1080,10 @@ static void ST_drawInput(void) else { // just a limited, greyed out joystick top - V_DrawFill(x+3, y+11, 10, 1, hudinfo[HUD_LIVES].f|29); + V_DrawFill(x+3, y+11, 10, 1, hudinfo[HUD_INPUT].f|29); V_DrawFill(x+3, y+1, - 10, 10, hudinfo[HUD_LIVES].f|16); + 10, 10, hudinfo[HUD_INPUT].f|16); } } else // arrows! @@ -1088,10 +1097,10 @@ static void ST_drawInput(void) else { offs = 1; - col = hudinfo[HUD_LIVES].f|16; - V_DrawFill(x- 2, y+10, 6, 1, hudinfo[HUD_LIVES].f|29); - V_DrawFill(x+ 4, y+ 9, 1, 1, hudinfo[HUD_LIVES].f|29); - V_DrawFill(x+ 5, y+ 8, 1, 1, hudinfo[HUD_LIVES].f|29); + col = hudinfo[HUD_INPUT].f|16; + V_DrawFill(x- 2, y+10, 6, 1, hudinfo[HUD_INPUT].f|29); + V_DrawFill(x+ 4, y+ 9, 1, 1, hudinfo[HUD_INPUT].f|29); + V_DrawFill(x+ 5, y+ 8, 1, 1, hudinfo[HUD_INPUT].f|29); } V_DrawFill(x- 2, y+ 5-offs, 6, 6, col); V_DrawFill(x+ 4, y+ 6-offs, 1, 4, col); @@ -1106,12 +1115,12 @@ static void ST_drawInput(void) else { offs = 1; - col = hudinfo[HUD_LIVES].f|16; - V_DrawFill(x+ 5, y+ 3, 1, 1, hudinfo[HUD_LIVES].f|29); - V_DrawFill(x+ 6, y+ 4, 1, 1, hudinfo[HUD_LIVES].f|29); - V_DrawFill(x+ 7, y+ 5, 2, 1, hudinfo[HUD_LIVES].f|29); - V_DrawFill(x+ 9, y+ 4, 1, 1, hudinfo[HUD_LIVES].f|29); - V_DrawFill(x+10, y+ 3, 1, 1, hudinfo[HUD_LIVES].f|29); + col = hudinfo[HUD_INPUT].f|16; + V_DrawFill(x+ 5, y+ 3, 1, 1, hudinfo[HUD_INPUT].f|29); + V_DrawFill(x+ 6, y+ 4, 1, 1, hudinfo[HUD_INPUT].f|29); + V_DrawFill(x+ 7, y+ 5, 2, 1, hudinfo[HUD_INPUT].f|29); + V_DrawFill(x+ 9, y+ 4, 1, 1, hudinfo[HUD_INPUT].f|29); + V_DrawFill(x+10, y+ 3, 1, 1, hudinfo[HUD_INPUT].f|29); } V_DrawFill(x+ 5, y- 2-offs, 6, 6, col); V_DrawFill(x+ 6, y+ 4-offs, 4, 1, col); @@ -1126,10 +1135,10 @@ static void ST_drawInput(void) else { offs = 1; - col = hudinfo[HUD_LIVES].f|16; - V_DrawFill(x+12, y+10, 6, 1, hudinfo[HUD_LIVES].f|29); - V_DrawFill(x+11, y+ 9, 1, 1, hudinfo[HUD_LIVES].f|29); - V_DrawFill(x+10, y+ 8, 1, 1, hudinfo[HUD_LIVES].f|29); + col = hudinfo[HUD_INPUT].f|16; + V_DrawFill(x+12, y+10, 6, 1, hudinfo[HUD_INPUT].f|29); + V_DrawFill(x+11, y+ 9, 1, 1, hudinfo[HUD_INPUT].f|29); + V_DrawFill(x+10, y+ 8, 1, 1, hudinfo[HUD_INPUT].f|29); } V_DrawFill(x+12, y+ 5-offs, 6, 6, col); V_DrawFill(x+11, y+ 6-offs, 1, 4, col); @@ -1144,8 +1153,8 @@ static void ST_drawInput(void) else { offs = 1; - col = hudinfo[HUD_LIVES].f|16; - V_DrawFill(x+ 5, y+17, 6, 1, hudinfo[HUD_LIVES].f|29); + col = hudinfo[HUD_INPUT].f|16; + V_DrawFill(x+ 5, y+17, 6, 1, hudinfo[HUD_INPUT].f|29); } V_DrawFill(x+ 5, y+12-offs, 6, 6, col); V_DrawFill(x+ 6, y+11-offs, 4, 1, col); @@ -1161,16 +1170,16 @@ static void ST_drawInput(void) else\ {\ offs = 1;\ - col = hudinfo[HUD_LIVES].f|16;\ - V_DrawFill(x+16+(xoffs), y+9+(yoffs), 10, 1, hudinfo[HUD_LIVES].f|29);\ + col = hudinfo[HUD_INPUT].f|16;\ + V_DrawFill(x+16+(xoffs), y+9+(yoffs), 10, 1, hudinfo[HUD_INPUT].f|29);\ }\ V_DrawFill(x+16+(xoffs), y+(yoffs)-offs, 10, 10, col);\ - V_DrawCharacter(x+16+1+(xoffs), y+1+(yoffs)-offs, hudinfo[HUD_LIVES].f|symb, false) + V_DrawCharacter(x+16+1+(xoffs), y+1+(yoffs)-offs, hudinfo[HUD_INPUT].f|symb, false) drawbutt( 4,-3, BT_JUMP, 'J'); drawbutt(15,-3, BT_SPIN, 'S'); - V_DrawFill(x+16+4, y+8, 21, 10, hudinfo[HUD_LIVES].f|20); // sundial backing + V_DrawFill(x+16+4, y+8, 21, 10, hudinfo[HUD_INPUT].f|20); // sundial backing if (stplyr->mo) { UINT8 i, precision; @@ -1190,7 +1199,7 @@ static void ST_drawInput(void) { V_DrawFill(x+16+14-(i*xcomp)/precision, y+12-(i*ycomp)/precision, - 1, 1, hudinfo[HUD_LIVES].f|16); + 1, 1, hudinfo[HUD_INPUT].f|16); } if (ycomp <= 0) @@ -1207,7 +1216,7 @@ static void ST_drawInput(void) if (stplyr->pflags & PF_AUTOBRAKE) { V_DrawThinString(x, y, - hudinfo[HUD_LIVES].f| + hudinfo[HUD_INPUT].f| ((!stplyr->powers[pw_carry] && (stplyr->pflags & PF_APPLYAUTOBRAKE) && !(stplyr->cmd.sidemove || stplyr->cmd.forwardmove) @@ -1220,22 +1229,22 @@ static void ST_drawInput(void) switch (P_ControlStyle(stplyr)) { case CS_LMAOGALOG: - V_DrawThinString(x, y, hudinfo[HUD_LIVES].f, "ANALOG"); + V_DrawThinString(x, y, hudinfo[HUD_INPUT].f, "ANALOG"); y -= 8; break; case CS_SIMPLE: - V_DrawThinString(x, y, hudinfo[HUD_LIVES].f, "AUTOMATIC"); + V_DrawThinString(x, y, hudinfo[HUD_INPUT].f, "AUTOMATIC"); y -= 8; break; case CS_STANDARD: - V_DrawThinString(x, y, hudinfo[HUD_LIVES].f, "MANUAL"); + V_DrawThinString(x, y, hudinfo[HUD_INPUT].f, "MANUAL"); y -= 8; break; case CS_LEGACY: - V_DrawThinString(x, y, hudinfo[HUD_LIVES].f, "STRAFE"); + V_DrawThinString(x, y, hudinfo[HUD_INPUT].f, "STRAFE"); y -= 8; break; @@ -1244,9 +1253,11 @@ static void ST_drawInput(void) } } if (!demosynced) // should always be last, so it doesn't push anything else around - V_DrawThinString(x, y, hudinfo[HUD_LIVES].f|((leveltime & 4) ? V_YELLOWMAP : V_REDMAP), "BAD DEMO!!"); + V_DrawThinString(x, y, hudinfo[HUD_INPUT].f|((leveltime & 4) ? V_YELLOWMAP : V_REDMAP), "BAD DEMO!!"); } +static boolean lt_active = false; + static patch_t *lt_patches[3]; static INT32 lt_scroll = 0; static INT32 lt_mom = 0; @@ -1261,19 +1272,19 @@ tic_t lt_exitticker = 0, lt_endtime = 0; // static void ST_cacheLevelTitle(void) { -#define SETPATCH(default, warning, custom, idx) \ +#define SETPATCH(def, warning, custom, idx) \ { \ lumpnum_t patlumpnum = LUMPERROR; \ if (mapheaderinfo[gamemap-1]->custom[0] != '\0') \ { \ - patlumpnum = W_CheckNumForName(mapheaderinfo[gamemap-1]->custom); \ + patlumpnum = W_CheckNumForPatchName(mapheaderinfo[gamemap-1]->custom); \ if (patlumpnum != LUMPERROR) \ lt_patches[idx] = (patch_t *)W_CachePatchNum(patlumpnum, PU_HUDGFX); \ } \ if (patlumpnum == LUMPERROR) \ { \ if (!(mapheaderinfo[gamemap-1]->levelflags & LF_WARNINGTITLE)) \ - lt_patches[idx] = (patch_t *)W_CachePatchName(default, PU_HUDGFX); \ + lt_patches[idx] = (patch_t *)W_CachePatchName(def, PU_HUDGFX); \ else \ lt_patches[idx] = (patch_t *)W_CachePatchName(warning, PU_HUDGFX); \ } \ @@ -1295,6 +1306,7 @@ void ST_startTitleCard(void) ST_cacheLevelTitle(); // initialize HUD variables + lt_active = true; lt_ticker = lt_exitticker = lt_lasttic = 0; lt_endtime = 2*TICRATE + (10*NEWTICRATERATIO); lt_scroll = BASEVIDWIDTH * FRACUNIT; @@ -1303,21 +1315,11 @@ void ST_startTitleCard(void) } // -// What happens before drawing the title card. -// Which is just setting the HUD translucency. +// Stops the title card. // -void ST_preDrawTitleCard(void) +void ST_stopTitleCard(void) { - if (!G_IsTitleCardAvailable()) - return; - - if (lt_ticker >= (lt_endtime + TICRATE)) - return; - - if (!lt_exitticker) - st_translucency = 0; - else - st_translucency = max(0, min((INT32)lt_exitticker-4, cv_translucenthud.value)); + lt_active = false; } // @@ -1326,47 +1328,43 @@ void ST_preDrawTitleCard(void) // void ST_runTitleCard(void) { - boolean run = !(paused || P_AutoPause()); - - if (!G_IsTitleCardAvailable()) + if (!lt_active || ((paused || P_AutoPause()) && lt_ticker >= PRELEVELTIME)) return; - if (lt_ticker >= (lt_endtime + TICRATE)) - return; - - if (run || (lt_ticker < PRELEVELTIME)) + if (!lt_exitticker) { - // tick - lt_ticker++; - if (lt_ticker >= lt_endtime) - lt_exitticker++; + if (abs(lt_scroll) > FRACUNIT) + lt_scroll -= (lt_scroll>>2); + else + lt_scroll = 0; - // scroll to screen (level title) - if (!lt_exitticker) - { - if (abs(lt_scroll) > FRACUNIT) - lt_scroll -= (lt_scroll>>2); - else - lt_scroll = 0; - } - // scroll away from screen (level title) + if (abs(lt_zigzag) > FRACUNIT) + lt_zigzag -= (lt_zigzag>>2); else + lt_zigzag = 0; + } + else + { + lt_mom -= FRACUNIT*6; + + if (lt_scroll > -BASEVIDWIDTH * FRACUNIT * 2) { - lt_mom -= FRACUNIT*6; lt_scroll += lt_mom; } - // scroll to screen (zigzag) - if (!lt_exitticker) + if (lt_zigzag > -(lt_patches[1]->width)*FRACUNIT) { - if (abs(lt_zigzag) > FRACUNIT) - lt_zigzag -= (lt_zigzag>>2); - else - lt_zigzag = 0; - } - // scroll away from screen (zigzag) - else lt_zigzag += lt_mom; + } + } + + lt_ticker++; + lt_exitticker = max((signed)lt_ticker - (signed)lt_endtime, 0); + + if (lt_ticker >= (lt_endtime + TICRATE)) + { + lt_active = false; + return; } } @@ -1393,9 +1391,6 @@ void ST_drawTitleCard(void) colormap = R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE); - if (!G_IsTitleCardAvailable()) - return; - if (!LUA_HudEnabled(hud_stagetitle)) goto luahook; @@ -1476,13 +1471,14 @@ void ST_preLevelTitleCardDrawer(void) // void ST_drawWipeTitleCard(void) { + if (!lt_active) + return; + stplyr = &players[consoleplayer]; - ST_preDrawTitleCard(); ST_drawTitleCard(); if (splitscreen) { stplyr = &players[secondarydisplayplayer]; - ST_preDrawTitleCard(); ST_drawTitleCard(); } } @@ -1508,7 +1504,7 @@ static void ST_drawPowerupHUD(void) UINT16 invulntime = 0; INT32 offs = hudinfo[HUD_POWERUPS].x; const UINT8 q = ((splitscreen && stplyr == &players[secondarydisplayplayer]) ? 1 : 0); - static INT32 flagoffs[2] = {0, 0}, shieldoffs[2] = {0, 0}, finishoffs[2] = {0, 0}; + static INT32 flagoffs[2] = {0, 0}, shieldoffs[2] = {0, 0}, finishoffs[2] = {0, 0}, stackoffs[2] = {0,0}; if (F_GetPromptHideHud(hudinfo[HUD_POWERUPS].y)) return; @@ -1545,13 +1541,16 @@ static void ST_drawPowerupHUD(void) { shieldoffs[q] = ICONSEP; - if ((stplyr->powers[pw_shield] & SH_NOSTACK & ~SH_FORCEHP) == SH_FORCE) + if ((stplyr->powers[pw_shield] & SH_NOSTACK & ~SH_FORCEHP) == SH_FORCE + && (stplyr->powers[pw_shield] & SH_FORCEHP) > 0) // Special handling for >1HP Force Shields { - UINT8 i, max = (stplyr->powers[pw_shield] & SH_FORCEHP); - for (i = 0; i <= max; i++) - { - V_DrawSmallScaledPatch(offs-(i<<1), hudinfo[HUD_POWERUPS].y-(i<<1), (V_PERPLAYER|hudinfo[HUD_POWERUPS].f)|((i == max) ? V_HUDTRANS : V_HUDTRANSHALF), forceshield); - } + UINT8 max = (stplyr->powers[pw_shield] & SH_FORCEHP); + + V_DrawSmallScaledPatch(offs, hudinfo[HUD_POWERUPS].y, V_PERPLAYER|hudinfo[HUD_POWERUPS].f|V_HUDTRANSHALF, forceshield); + V_DrawSmallScaledPatch(offs-2, hudinfo[HUD_POWERUPS].y-2, V_PERPLAYER|hudinfo[HUD_POWERUPS].f|V_HUDTRANS, forceshield); + + if (max > 1) // if the shield has more than 2 hits, show the extra n hits as "+n" + V_DrawRightAlignedThinString(offs+16, hudinfo[HUD_POWERUPS].y, V_PERPLAYER|hudinfo[HUD_POWERUPS].f|V_HUDTRANS, va("+%d", max - 1)); } else { @@ -1561,6 +1560,7 @@ static void ST_drawPowerupHUD(void) case SH_ELEMENTAL: p = watershield; break; case SH_ARMAGEDDON: p = bombshield; break; case SH_ATTRACT: p = ringshield; break; + case SH_FORCE: p = forceshield; break; case SH_PITY: p = pityshield; break; case SH_PINK: p = pinkshield; break; case SH_FLAMEAURA: p = flameshield; break; @@ -1583,6 +1583,22 @@ static void ST_drawPowerupHUD(void) offs -= shieldoffs[q]; + //Fire Flower "shield" + if ((stplyr->powers[pw_shield] & SH_FIREFLOWER) == SH_FIREFLOWER) + { + stackoffs[q] = ICONSEP; + V_DrawSmallScaledPatch(offs, hudinfo[HUD_POWERUPS].y, V_PERPLAYER|hudinfo[HUD_POWERUPS].f|V_HUDTRANS, fireflower); + } + else if (stackoffs[q]) + { + if (stackoffs[q] > 1) + stackoffs[q] = 2*stackoffs[q]/3; + else + stackoffs[q] = 0; + } + + offs -= stackoffs[q]; + // --------- // CTF flags // --------- @@ -1727,22 +1743,23 @@ static void ST_drawNightsRecords(void) switch (stplyr->textvar) { - case 1: // A "Bonus Time Start" by any other name... + case NTV_BONUSTIMESTART: // A "Bonus Time Start" by any other name... { V_DrawCenteredString(BASEVIDWIDTH/2, 52, V_GREENMAP|aflag, M_GetText("GET TO THE GOAL!")); V_DrawCenteredString(BASEVIDWIDTH/2, 60, aflag, M_GetText("SCORE MULTIPLIER START!")); if (stplyr->finishedtime) { - V_DrawString(BASEVIDWIDTH/2 - 48, 140, aflag, "TIME:"); - V_DrawString(BASEVIDWIDTH/2 - 48, 148, aflag, "BONUS:"); - V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, 140, V_ORANGEMAP|aflag, va("%d", (stplyr->startedtime - stplyr->finishedtime)/TICRATE)); - V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, 148, V_ORANGEMAP|aflag, va("%d", (stplyr->finishedtime/TICRATE) * 100)); + tic_t maretime = stplyr->startedtime - stplyr->finishedtime; + V_DrawString(BASEVIDWIDTH/2 - 48, 140, V_YELLOWMAP|aflag, "TIME:"); + V_DrawString(BASEVIDWIDTH/2 - 48, 148, V_YELLOWMAP|aflag, "BONUS:"); + V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, 140, aflag, va("%i:%02i.%02i", G_TicsToMinutes(maretime,true), G_TicsToSeconds(maretime), G_TicsToCentiseconds(maretime))); + V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, 148, aflag, va("%d", (stplyr->finishedtime/TICRATE) * 100)); } break; } - case 2: // Get n Spheres - case 3: // Get n more Spheres + case NTV_GETSPHERES: // Get n Spheres + case NTV_GETMORESPHERES: // Get n more Spheres { if (!stplyr->capsule) return; @@ -1750,31 +1767,37 @@ static void ST_drawNightsRecords(void) // Yes, this string is an abomination. V_DrawCenteredString(BASEVIDWIDTH/2, 60, aflag, va(M_GetText("\x80GET\x82 %d\x80 %s%s%s!"), stplyr->capsule->health, - (stplyr->textvar == 3) ? M_GetText("MORE ") : "", + (stplyr->textvar == NTV_GETMORESPHERES) ? M_GetText("MORE ") : "", (G_IsSpecialStage(gamemap)) ? "SPHERE" : "CHIP", (stplyr->capsule->health > 1) ? "S" : "")); break; } - case 4: // End Bonus + case NTV_BONUSTIMEEND: // End Bonus { - V_DrawString(BASEVIDWIDTH/2 - 56, 140, aflag, (G_IsSpecialStage(gamemap)) ? "SPHERES:" : "CHIPS:"); - V_DrawString(BASEVIDWIDTH/2 - 56, 148, aflag, "BONUS:"); - V_DrawRightAlignedString(BASEVIDWIDTH/2 + 56, 140, V_ORANGEMAP|aflag, va("%d", stplyr->finishedspheres)); - V_DrawRightAlignedString(BASEVIDWIDTH/2 + 56, 148, V_ORANGEMAP|aflag, va("%d", stplyr->finishedspheres * 50)); - ST_DrawNightsOverlayNum((BASEVIDWIDTH/2 + 56)<<FRACBITS, 160<<FRACBITS, FRACUNIT, aflag, stplyr->lastmarescore, nightsnum, SKINCOLOR_AZURE); + V_DrawString(BASEVIDWIDTH/2 - 48, 132, V_YELLOWMAP|aflag, "TIME:"); + V_DrawString(BASEVIDWIDTH/2 - 48, 140, V_YELLOWMAP|aflag, (G_IsSpecialStage(gamemap)) ? "SPHERES:" : "CHIPS:"); + V_DrawString(BASEVIDWIDTH/2 - 48, 148, V_YELLOWMAP|aflag, "BONUS:"); + V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, 132, aflag, va("%i:%02i.%02i", G_TicsToMinutes(stplyr->lastmaretime,true), G_TicsToSeconds(stplyr->lastmaretime), G_TicsToCentiseconds(stplyr->lastmaretime))); + V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, 140, aflag, va("%d", stplyr->finishedspheres)); + V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, 148, aflag, va("%d", stplyr->finishedspheres * 50)); + ST_DrawNightsOverlayNum((BASEVIDWIDTH/2 + 48)<<FRACBITS, 160<<FRACBITS, FRACUNIT, aflag, stplyr->lastmarescore, nightsnum, SKINCOLOR_AZURE); + + // If this is a multi-mare map, display the mare number. + if (stplyr->lastmare || P_FindLowestMare() < UINT8_MAX) + V_DrawLevelActNum(BASEVIDWIDTH/2 - 80, 128 + 3, aflag, stplyr->lastmare + 1); // If new record, say so! if (!(netgame || multiplayer) && G_GetBestNightsScore(gamemap, stplyr->lastmare + 1, clientGamedata) <= stplyr->lastmarescore) { if (stplyr->texttimer & 16) - V_DrawCenteredString(BASEVIDWIDTH/2, 184, V_YELLOWMAP|aflag, "* NEW RECORD *"); + V_DrawCenteredString(BASEVIDWIDTH/2, 184, aflag, "\x85* \x82NEW RECORD \x85*\x80"); } if (P_HasGrades(gamemap, stplyr->lastmare + 1)) { UINT8 grade = P_GetGrade(stplyr->lastmarescore, gamemap, stplyr->lastmare); - if (modeattacking || grade >= GRADE_A) - V_DrawTranslucentPatch(BASEVIDWIDTH/2 + 60, 160, aflag, ngradeletters[grade]); + if (modeattacking || !G_IsSpecialStage(gamemap) || grade >= GRADE_A) + V_DrawTranslucentPatch(BASEVIDWIDTH/2 + 60, 128, aflag, ngradeletters[grade]); } break; } @@ -1884,7 +1907,7 @@ static void ST_drawNiGHTSHUD(void) // Link drawing if (!oldspecialstage // Don't display when the score is showing (it popping up for a split second when exiting a map is intentional) - && !(stplyr->texttimer && stplyr->textvar == 4) + && !(stplyr->texttimer && stplyr->textvar == NTV_BONUSTIMEEND) && LUA_HudEnabled(hud_nightslink) && ((cv_debug & DBG_NIGHTSBASIC) || stplyr->linkcount > 1)) // When debugging, show "0 Link". { @@ -1926,12 +1949,12 @@ static void ST_drawNiGHTSHUD(void) total_ringcount = stplyr->spheres; } - if (stplyr->capsule) + if (!P_MobjWasRemoved(stplyr->capsule)) { INT32 amount; const INT32 length = 88; - origamount = stplyr->capsule->spawnpoint->angle; + origamount = stplyr->capsule->spawnpoint->args[1]; I_Assert(origamount > 0); // should not happen now ST_DrawTopLeftOverlayPatch(72, 8, nbracket); @@ -2043,24 +2066,25 @@ static void ST_drawNiGHTSHUD(void) if (!stplyr->exiting && !oldspecialstage && LUA_HudEnabled(hud_nightsscore)) ST_DrawNightsOverlayNum(304<<FRACBITS, 14<<FRACBITS, FRACUNIT, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTORIGHT, stplyr->marescore, nightsnum, SKINCOLOR_AZURE); - // TODO give this its own section for Lua + // TODO: give this its own section for Lua + // TODO: on multi-mare maps, show time & grade for each completed mare if (!stplyr->exiting && LUA_HudEnabled(hud_nightsscore)) { if (modeattacking == ATTACKING_NIGHTS) { INT32 maretime = max(stplyr->realtime - stplyr->marebegunat, 0); -#define VFLAGS V_SNAPTOBOTTOM|V_SNAPTORIGHT|V_PERPLAYER|V_HUDTRANS - V_DrawScaledPatch(BASEVIDWIDTH-22, BASEVIDHEIGHT-20, VFLAGS, W_CachePatchName("NGRTIMER", PU_HUDGFX)); - V_DrawPaddedTallNum(BASEVIDWIDTH-22, BASEVIDHEIGHT-20, VFLAGS, G_TicsToCentiseconds(maretime), 2); - V_DrawScaledPatch(BASEVIDWIDTH-46, BASEVIDHEIGHT-20, VFLAGS, sboperiod); +#define VFLAGS V_SNAPTOTOP|V_SNAPTORIGHT|V_PERPLAYER|V_HUDTRANS + V_DrawScaledPatch(BASEVIDWIDTH-16, 40, VFLAGS, W_CachePatchName("NGRTIMER", PU_HUDGFX)); + V_DrawPaddedTallNum(BASEVIDWIDTH-16, 40, VFLAGS, G_TicsToCentiseconds(maretime), 2); + V_DrawScaledPatch(BASEVIDWIDTH-40, 40, VFLAGS, sboperiod); if (maretime < 60*TICRATE) - V_DrawTallNum(BASEVIDWIDTH-46, BASEVIDHEIGHT-20, VFLAGS, G_TicsToSeconds(maretime)); + V_DrawTallNum(BASEVIDWIDTH-40, 40, VFLAGS, G_TicsToSeconds(maretime)); else { - V_DrawPaddedTallNum(BASEVIDWIDTH-46, BASEVIDHEIGHT-20, VFLAGS, G_TicsToSeconds(maretime), 2); - V_DrawScaledPatch(BASEVIDWIDTH-70, BASEVIDHEIGHT-20, VFLAGS, sbocolon); - V_DrawTallNum(BASEVIDWIDTH-70, BASEVIDHEIGHT-20, VFLAGS, G_TicsToMinutes(maretime, true)); + V_DrawPaddedTallNum(BASEVIDWIDTH-40, 40, VFLAGS, G_TicsToSeconds(maretime), 2); + V_DrawScaledPatch(BASEVIDWIDTH-64, 40, VFLAGS, sbocolon); + V_DrawTallNum(BASEVIDWIDTH-64, 40, VFLAGS, G_TicsToMinutes(maretime, true)); } #undef VFLAGS } @@ -2630,7 +2654,7 @@ static boolean ST_doItemFinderIconsAndSound(void) // Scan thinkers to find emblem mobj with these ids for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + if (th->removing) continue; mo2 = (mobj_t *)th; @@ -2666,24 +2690,14 @@ static boolean ST_doItemFinderIconsAndSound(void) return true; } +static boolean drawstagetitle = false; + // // Draw the status bar overlay, customisable: the user chooses which // kind of information to overlay // static void ST_overlayDrawer(void) { - // Decide whether to draw the stage title or not - boolean stagetitle = false; - - // Check for a valid level title - // If the HUD is enabled - // And, if Lua is running, if the HUD library has the stage title enabled - if (G_IsTitleCardAvailable() && *mapheaderinfo[gamemap-1]->lvlttl != '\0' && !(hu_showscores && (netgame || multiplayer))) - { - stagetitle = true; - ST_preDrawTitleCard(); - } - // hu_showscores = auto hide score/time/rings when tab rankings are shown if (!(hu_showscores && (netgame || multiplayer))) { @@ -2801,14 +2815,14 @@ static void ST_overlayDrawer(void) || ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase)) { ST_drawFirstPersonHUD(); - if (cv_powerupdisplay.value) + if (cv_powerupdisplay.value && LUA_HudEnabled(hud_powerups)) ST_drawPowerupHUD(); // same as it ever was... } - else if (cv_powerupdisplay.value == 2) + else if (cv_powerupdisplay.value == 2 && LUA_HudEnabled(hud_powerups)) ST_drawPowerupHUD(); // same as it ever was... - + } - else if (!(netgame || multiplayer) && cv_powerupdisplay.value == 2) + else if (!(netgame || multiplayer) && cv_powerupdisplay.value == 2 && LUA_HudEnabled(hud_powerups)) ST_drawPowerupHUD(); // same as it ever was... if (!(netgame || multiplayer) || !hu_showscores) @@ -2823,13 +2837,13 @@ static void ST_overlayDrawer(void) } // draw level title Tails - if (stagetitle && (!WipeInAction) && (!WipeStageTitle)) + if (drawstagetitle && !WipeInAction && !WipeStageTitle) ST_drawTitleCard(); if (!hu_showscores && (netgame || multiplayer) && LUA_HudEnabled(hud_textspectator)) ST_drawTextHUD(); - if (modeattacking && !(demoplayback && hu_showscores)) + if ((cv_showinput.value && !players[displayplayer].spectator) || (modeattacking && !(demoplayback && hu_showscores))) ST_drawInput(); ST_drawDebugInfo(); @@ -2874,7 +2888,7 @@ void ST_Drawer(void) //25/08/99: Hurdler: palette changes is done for all players, // not only player1! That's why this part // of code is moved somewhere else. - if (rendermode == render_soft) + if (rendermode == render_soft || HWR_ShouldUsePaletteRendering()) #endif if (rendermode != render_none) ST_doPaletteStuff(); @@ -2894,7 +2908,22 @@ void ST_Drawer(void) } } - st_translucency = cv_translucenthud.value; + // Decide whether to draw the stage title or not + if (lt_active) + { + drawstagetitle = !(hu_showscores && (netgame || multiplayer)); + + if (!lt_exitticker) + st_translucency = 0; + else + st_translucency = max(0, min((INT32)lt_exitticker-4, cv_translucenthud.value)); + } + else + { + st_translucency = cv_translucenthud.value; + + drawstagetitle = false; + } if (st_overlay) { diff --git a/src/st_stuff.h b/src/st_stuff.h index 07dfac3eccf6095218bf0f4b16726c41a6f94fd5..a2fb8a0ed7328f27de43f750e32a3c9c7f390eae 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -49,9 +49,9 @@ void ST_doPaletteStuff(void); // title card void ST_startTitleCard(void); +void ST_stopTitleCard(void); void ST_runTitleCard(void); void ST_drawTitleCard(void); -void ST_preDrawTitleCard(void); void ST_preLevelTitleCardDrawer(void); void ST_drawWipeTitleCard(void); @@ -92,6 +92,7 @@ typedef struct typedef enum { HUD_LIVES, + HUD_INPUT, HUD_RINGS, HUD_RINGSNUM, diff --git a/src/string.c b/src/string.c index 2f16fa4c68a35fa287156f546fc2973e9d4ad426..79573283e10bee24ef70a394899c6f5585f67521 100644 --- a/src/string.c +++ b/src/string.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2006 by Graue. -// Copyright (C) 2006-2023 by Sonic Team Junior. +// Copyright (C) 2006-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -68,3 +68,26 @@ int endswith(const char *base, const char *tag) return !memcmp(&base[base_length - tag_length], tag, tag_length); } + +// strtok version that only skips over one delimiter at a time +char *xstrtok(char *line, const char *delims) +{ + static char *saveline = NULL; + char *p; + + if(line != NULL) + saveline = line; + + // see if we have reached the end of the line + if(saveline == NULL || *saveline == '\0') + return NULL; + + p = saveline; // save start of this token + + saveline += strcspn(saveline, delims); // get the number of non-delims characters, go past delimiter + + if(*saveline != '\0') // trash the delim if necessary + *saveline++ = '\0'; + + return p; +} diff --git a/src/tables.c b/src/tables.c index d0fb428ba8909653cc7f1d340caa9590f1373391..8e9075be259be149d1bb68686201973ccad70ae1 100644 --- a/src/tables.c +++ b/src/tables.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // Copyright (C) 2009 by Stephen McGranahan. // // This program is free software distributed under the diff --git a/src/tables.h b/src/tables.h index 2736f03e8d57e9d06e90493354302c5403a05f45..3c0dd2a81ff97a6ccc382716bf136a897b1c4e75 100644 --- a/src/tables.h +++ b/src/tables.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -81,7 +81,7 @@ extern angle_t tantoangle[SLOPERANGE+1]; // Utility function, called by R_PointToAngle. FUNCMATH unsigned SlopeDiv(unsigned num, unsigned den); -// Only called by R_PointToAngleEx +// Only called by R_PointToAngle64 UINT64 SlopeDivEx(unsigned int num, unsigned int den); // 360 - angle_t(ANGLE_45) = ANGLE_315 diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt deleted file mode 100644 index 28c4ce492f2d8b4e7590e3ac10f9ce6a95d98a0f..0000000000000000000000000000000000000000 --- a/src/tests/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -target_sources(srb2tests PRIVATE - boolcompat.cpp -) diff --git a/src/tests/boolcompat.cpp b/src/tests/boolcompat.cpp deleted file mode 100644 index fee40cd36f2bce34217a875024d6b41fe71adbd1..0000000000000000000000000000000000000000 --- a/src/tests/boolcompat.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include <catch2/catch_test_macros.hpp> - -#include "../doomtype.h" - -TEST_CASE("C++ bool is convertible to doomtype.h boolean") { - REQUIRE(static_cast<boolean>(true) == 1); - REQUIRE(static_cast<boolean>(false) == 0); -} diff --git a/src/v_video.c b/src/v_video.c index cb7db487e921b88e50fd0b6d97a6d3f631841c90..39a1001d199952077fc783875b4d104c819a8fcd 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -384,13 +384,14 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue) const char *R_GetPalname(UINT16 num) { - static char palname[9]; - char newpal[9] = "PLAYPAL"; + static char palname[8+1]; + char newpal[9] = "PLAYPAL\0"; if (num > 0 && num <= 10000) snprintf(newpal, 8, "PAL%04u", num-1); - strncpy(palname, newpal, 8); + strncpy(palname, newpal, sizeof(palname)-1); + palname[8] = 0; return palname; } @@ -1136,7 +1137,7 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) } #endif - + if (splitscreen && (c & V_PERPLAYER)) { @@ -1922,67 +1923,34 @@ UINT8 *V_GetStringColormap(INT32 colorflags) } } -// Writes a single character (draw WHITE if bit 7 set) +// Generalized character drawing function, combining console & chat functionality with a specified font. // -void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed) +void V_DrawFontCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, fixed_t scale, UINT8 *colormap, fontdef_t font) { INT32 w, flags; - const UINT8 *colormap = V_GetStringColormap(c); + const UINT8 *color = colormap ? colormap : V_GetStringColormap(c); flags = c & ~(V_CHARCOLORMASK | V_PARAMMASK); c &= 0x7f; - if (lowercaseallowed) - c -= HU_FONTSTART; - else - c = toupper(c) - HU_FONTSTART; - if (c < 0 || c >= HU_FONTSIZE || !hu_font[c]) + c = (lowercaseallowed ? c : toupper(c)) - FONTSTART; + if (c < 0 || c >= FONTSIZE || !font.chars[c]) return; - w = hu_font[c]->width; + w = FixedMul(font.chars[c]->width / 2, scale); // use normal sized characters if we're using a terribly low resolution. if (x + w > vid.width) return; - if (colormap != NULL) - V_DrawMappedPatch(x, y, flags, hu_font[c], colormap); - else - V_DrawScaledPatch(x, y, flags, hu_font[c]); + V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, scale, flags, font.chars[c], color); } -// Writes a single character for the chat. (draw WHITE if bit 7 set) -// Essentially the same as the above but it's small or big depending on what resolution you've chosen to huge.. +// Precompile a wordwrapped string to any given width, using a specified font. // -void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UINT8 *colormap) -{ - INT32 w, flags; - //const UINT8 *colormap = V_GetStringColormap(c); - - flags = c & ~(V_CHARCOLORMASK | V_PARAMMASK); - c &= 0x7f; - if (lowercaseallowed) - c -= HU_FONTSTART; - else - c = toupper(c) - HU_FONTSTART; - if (c < 0 || c >= HU_FONTSIZE || !hu_font[c]) - return; - - w = (vid.width < 640 ) ? ((hu_font[c]->width / 2)) : (hu_font[c]->width); // use normal sized characters if we're using a terribly low resolution. - if (x + w > vid.width) - return; - - V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, (vid.width < 640) ? (FRACUNIT) : (FRACUNIT/2), flags, hu_font[c], colormap); - - -} - -// Precompile a wordwrapped string to any given width. -// This is a muuuch better method than V_WORDWRAP. -char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) +char *V_FontWordWrap(INT32 x, INT32 w, INT32 option, fixed_t scale, const char *string, fontdef_t font) { int c; - size_t chw, i, lastusablespace = 0; - size_t slen; + size_t slen, chw, i, lastusablespace = 0; char *newstring = Z_StrDup(string); - INT32 spacewidth = 4, charwidth = 0; + INT32 spacewidth = font.spacewidth, charwidth = 0; slen = strlen(string); @@ -1994,10 +1962,10 @@ char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) switch (option & V_SPACINGMASK) { case V_MONOSPACE: - spacewidth = 8; + spacewidth = font.charwidth; /* FALLTHRU */ case V_OLDSPACING: - charwidth = 8; + charwidth = font.charwidth; break; case V_6WIDTHSPACE: spacewidth = 6; @@ -2018,69 +1986,77 @@ char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) continue; } - if (!(option & V_ALLOWLOWERCASE)) - c = toupper(c); - c -= HU_FONTSTART; - - if (c < 0 || c >= HU_FONTSIZE || !hu_font[c]) + c = (option & V_ALLOWLOWERCASE ? c : toupper(c)) - FONTSTART; + if (c < 0 || c >= FONTSIZE || !font.chars[c]) { chw = spacewidth; lastusablespace = i; } else - chw = (charwidth ? charwidth : hu_font[c]->width); + chw = (charwidth ? charwidth : font.chars[c]->width); - x += chw; + x += FixedMul(chw, scale); if (lastusablespace != 0 && x > w) { newstring[lastusablespace] = '\n'; i = lastusablespace; - lastusablespace = 0; - x = 0; + lastusablespace = x = 0; } } return newstring; } -// -// Write a string using the hu_font -// NOTE: the text is centered for screens larger than the base width -// -void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string) +// Draw a string, using a supplied font and scale. +// NOTE: The text is centered for screens larger than the base width. +void V_DrawFontString(INT32 x, INT32 y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font) +{ + V_DrawFontStringAtFixed((fixed_t)x<<FRACBITS, (fixed_t)y<<FRACBITS, option, pscale, vscale, string, font); +} + +void V_DrawAlignedFontString(INT32 x, INT32 y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font, enum string_align align) +{ + V_DrawAlignedFontStringAtFixed((fixed_t)x<<FRACBITS, (fixed_t)y<<FRACBITS, option, pscale, vscale, string, font, align); +} + +// Write a string, using a supplied font and scale, at fixed_t coordinates. +// NOTE: The text is centered for screens larger than the base width. +void V_DrawFontStringAtFixed(fixed_t x, fixed_t y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font) { - INT32 w, c, cx = x, cy = y, dup, scrwidth, center = 0, left = 0; + fixed_t cx = x, cy = y; + INT32 w, c, dupx, dupy, scrwidth, center = 0, left = 0; const char *ch = string; INT32 charflags = (option & V_CHARCOLORMASK); - const UINT8 *colormap = NULL; - INT32 spacewidth = 4, charwidth = 0; + INT32 spacewidth = font.spacewidth, charwidth = 0; INT32 lowercase = (option & V_ALLOWLOWERCASE); option &= ~V_FLIP; // which is also shared with V_ALLOWLOWERCASE... if (option & V_NOSCALESTART) { - dup = vid.dup; + dupx = vid.dup<<FRACBITS; + dupy = vid.dup<<FRACBITS; scrwidth = vid.width; } else { - dup = 1; - scrwidth = vid.width/vid.dup; - left = (scrwidth - BASEVIDWIDTH)/2; + dupx = pscale; + dupy = vscale; + scrwidth = FixedDiv(vid.width<<FRACBITS, vid.dup); + left = (scrwidth - (BASEVIDWIDTH << FRACBITS))/2; scrwidth -= left; } if (option & V_NOSCALEPATCH) scrwidth *= vid.dup; - switch (option & V_SPACINGMASK) + switch (option & V_SPACINGMASK) // TODO: 2.3: drop support for these crusty flags { case V_MONOSPACE: - spacewidth = 8; + spacewidth = font.charwidth; /* FALLTHRU */ case V_OLDSPACING: - charwidth = 8; + charwidth = font.charwidth; break; case V_6WIDTHSPACE: spacewidth = 6; @@ -2102,36 +2078,26 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string) if (*ch == '\n') { cx = x; - - if (option & V_RETURN8) - cy += 8*dup; - else - cy += 12*dup; - + cy += FixedMul(((option & V_RETURN8) ? 8 : font.linespacing)<<FRACBITS, dupy); continue; } - c = *ch; - if (!lowercase) - c = toupper(c); - c -= HU_FONTSTART; - - // character does not exist or is a space - if (c < 0 || c >= HU_FONTSIZE || !hu_font[c]) + c = (lowercase ? *ch : toupper(*ch)) - FONTSTART; + if (c < 0 || c >= FONTSIZE || !font.chars[c]) { - cx += spacewidth * dup; + cx += FixedMul((spacewidth<<FRACBITS), dupx); continue; } if (charwidth) { - w = charwidth * dup; - center = w/2 - hu_font[c]->width*dup/2; + w = FixedMul((charwidth<<FRACBITS), dupx); + center = w/2 - FixedMul(font.chars[c]->width<<FRACBITS, (dupx/2)); } else - w = hu_font[c]->width * dup; + w = FixedMul(font.chars[c]->width<<FRACBITS, dupx); - if (cx > scrwidth) + if ((cx>>FRACBITS) > scrwidth) continue; if (cx+left + w < 0) //left boundary check { @@ -2139,156 +2105,134 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string) continue; } - colormap = V_GetStringColormap(charflags); - V_DrawFixedPatch((cx + center)<<FRACBITS, cy<<FRACBITS, FRACUNIT, option, hu_font[c], colormap); + V_DrawStretchyFixedPatch(cx + center, cy, pscale, vscale, option, font.chars[c], V_GetStringColormap(charflags)); - cx += w; + cx += w + (font.kerning<<FRACBITS); } } -void V_DrawCenteredString(INT32 x, INT32 y, INT32 option, const char *string) +void V_DrawAlignedFontStringAtFixed(fixed_t x, fixed_t y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font, enum string_align align) { - x -= V_StringWidth(string, option)/2; - V_DrawString(x, y, option, string); -} + char *text = strdup(string); + char* line = xstrtok(text, "\n"); + fixed_t lx = x, ly = y; -void V_DrawRightAlignedString(INT32 x, INT32 y, INT32 option, const char *string) -{ - x -= V_StringWidth(string, option); - V_DrawString(x, y, option, string); -} + while (line) + { + switch(align) + { + case alignleft: + lx = x; + break; + case aligncenter: + lx = x - (V_FontStringWidth(line, option, font)*pscale) / 2; + break; + case alignright: + lx = x - (V_FontStringWidth(line, option, font)*pscale); + break; + } -// -// Write a string using the hu_font, 0.5x scale -// NOTE: the text is centered for screens larger than the base width -// -void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string) -{ - INT32 w, c, cx = x, cy = y, dup, scrwidth, center = 0, left = 0; - const char *ch = string; - INT32 charflags = 0; - const UINT8 *colormap = NULL; - INT32 spacewidth = 2, charwidth = 0; + V_DrawFontStringAtFixed(lx, ly, option, pscale, vscale, line, font); - INT32 lowercase = (option & V_ALLOWLOWERCASE); - option &= ~V_FLIP; // which is also shared with V_ALLOWLOWERCASE... + ly += FixedMul(((option & V_RETURN8) ? 8 : font.linespacing)<<FRACBITS, vscale); - if (option & V_NOSCALESTART) - { - dup = vid.dup; - scrwidth = vid.width; - } - else - { - dup = 1; - scrwidth = vid.width/vid.dup; - left = (scrwidth - BASEVIDWIDTH)/2; - scrwidth -= left; + line = xstrtok(NULL, "\n"); } +} - if (option & V_NOSCALEPATCH) - scrwidth *= vid.dup; +// Draws a tallnum. Replaces two functions in y_inter and st_stuff +void V_DrawTallNum(INT32 x, INT32 y, INT32 flags, INT32 num) +{ + INT32 w = tallnum[0]->width; + boolean neg; - charflags = (option & V_CHARCOLORMASK); + if (flags & (V_NOSCALESTART|V_NOSCALEPATCH)) + w *= vid.dup; - switch (option & V_SPACINGMASK) - { - case V_MONOSPACE: - spacewidth = 4; - /* FALLTHRU */ - case V_OLDSPACING: - charwidth = 4; - break; - case V_6WIDTHSPACE: - spacewidth = 3; - default: - break; - } + if ((neg = num < 0)) + num = -num; - for (;;ch++) + // draw the number + do { - if (!*ch) - break; - if (*ch & 0x80) //color parsing -x 2.16.09 - { - // manually set flags override color codes - if (!(option & V_CHARCOLORMASK)) - charflags = ((*ch & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK; - continue; - } - if (*ch == '\n') - { - cx = x; - - if (option & V_RETURN8) - cy += 4*dup; - else - cy += 6*dup; + x -= w; + V_DrawScaledPatch(x, y, flags, tallnum[num % 10]); + num /= 10; + } while (num); - continue; - } + // draw a minus sign if necessary + if (neg) + V_DrawScaledPatch(x - w, y, flags, tallminus); // Tails +} - c = *ch; - if (!lowercase) - c = toupper(c); - c -= HU_FONTSTART; +// Draws a number with a set number of digits. +// Does not handle negative numbers in a special way, don't try to feed it any. +void V_DrawPaddedTallNum(INT32 x, INT32 y, INT32 flags, INT32 num, INT32 digits) +{ + INT32 w = tallnum[0]->width; - if (c < 0 || c >= HU_FONTSIZE || !hu_font[c]) - { - cx += spacewidth * dup; - continue; - } + if (flags & (V_NOSCALESTART|V_NOSCALEPATCH)) + w *= vid.dup; - if (charwidth) - { - w = charwidth * dup; - center = w/2 - hu_font[c]->width*dup/4; - } - else - w = hu_font[c]->width * dup / 2; + if (num < 0) + num = -num; - if (cx > scrwidth) - continue; - if (cx+left + w < 0) //left boundary check - { - cx += w; - continue; - } + // draw the number + do + { + x -= w; + V_DrawScaledPatch(x, y, flags, tallnum[num % 10]); + num /= 10; + } while (--digits); +} - colormap = V_GetStringColormap(charflags); - V_DrawFixedPatch((cx + center)<<FRACBITS, cy<<FRACBITS, FRACUNIT/2, option, hu_font[c], colormap); +// Draw an act number for a level title +void V_DrawLevelActNum(INT32 x, INT32 y, INT32 flags, UINT8 num) +{ + if (num > 99) + return; // not supported - cx += w; + while (num > 0) + { + if (num > 9) // if there are two digits, draw second digit first + V_DrawScaledPatch(x + (V_LevelActNumWidth(num) - V_LevelActNumWidth(num%10)), y, flags, ttlnum[num%10]); + else + V_DrawScaledPatch(x, y, flags, ttlnum[num]); + num = num/10; } } -void V_DrawCenteredSmallString(INT32 x, INT32 y, INT32 option, const char *string) +// Returns the width of the act num patch(es) +INT16 V_LevelActNumWidth(UINT8 num) { - x -= V_SmallStringWidth(string, option)/2; - V_DrawSmallString(x, y, option, string); -} + INT16 result = 0; + if (num == 0) + result = ttlnum[num]->width; -void V_DrawRightAlignedSmallString(INT32 x, INT32 y, INT32 option, const char *string) -{ - x -= V_SmallStringWidth(string, option); - V_DrawSmallString(x, y, option, string); + while (num > 0 && num <= 99) + { + result = result + ttlnum[num%10]->width; + num = num/10; + } + + return result; } -// -// Write a string using the tny_font -// NOTE: the text is centered for screens larger than the base width -// -void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string) +// Draw a string using the nt_font +// Note that the outline is a seperate font set +static void V_DrawNameTagLine(INT32 x, INT32 y, INT32 option, fixed_t scale, UINT8 *basecolormap, UINT8 *outlinecolormap, const char *string) { - INT32 w, c, cx = x, cy = y, dup, scrwidth, left = 0; + fixed_t cx, cy, w; + INT32 c, dup, scrwidth, left = 0; const char *ch = string; - INT32 charflags = 0; - const UINT8 *colormap = NULL; - INT32 spacewidth = 2, charwidth = 0; - INT32 lowercase = (option & V_ALLOWLOWERCASE); - option &= ~V_FLIP; // which is also shared with V_ALLOWLOWERCASE... + if (option & V_CENTERNAMETAG) + x -= FixedInt(FixedMul((V_NameTagWidth(string)/2)*FRACUNIT, scale)); + option &= ~V_CENTERNAMETAG; // which is also shared with V_ALLOWLOWERCASE... + + cx = x<<FRACBITS; + cy = y<<FRACBITS; if (option & V_NOSCALESTART) { @@ -2306,773 +2250,54 @@ void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string) if (option & V_NOSCALEPATCH) scrwidth *= vid.dup; - charflags = (option & V_CHARCOLORMASK); - - switch (option & V_SPACINGMASK) - { - case V_MONOSPACE: - spacewidth = 5; - /* FALLTHRU */ - case V_OLDSPACING: - charwidth = 5; - break; - case V_6WIDTHSPACE: - spacewidth = 3; - default: - break; - } - for (;;ch++) { if (!*ch) break; - if (*ch & 0x80) //color parsing -x 2.16.09 - { - // manually set flags override color codes - if (!(option & V_CHARCOLORMASK)) - charflags = ((*ch & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK; - continue; - } if (*ch == '\n') { - cx = x; - - if (option & V_RETURN8) - cy += 8*dup; - else - cy += 12*dup; - + cx = x<<FRACBITS; + cy += FixedMul((ntb_font.linespacing * dup)*FRACUNIT, scale); continue; } - c = *ch; - if (!lowercase || !tny_font[c-HU_FONTSTART]) - c = toupper(c); - c -= HU_FONTSTART; - - if (c < 0 || c >= HU_FONTSIZE || !tny_font[c]) + c = toupper(*ch) - FONTSTART; + if (c < 0 || c >= FONTSIZE || !ntb_font.chars[c] || !nto_font.chars[c]) { - cx += spacewidth * dup; + cx += FixedMul((ntb_font.spacewidth * dup)*FRACUNIT, scale); continue; } - if (charwidth) - w = charwidth * dup; - else - w = tny_font[c]->width * dup; + w = FixedMul(((ntb_font.chars[c]->width)+ntb_font.kerning * dup) * FRACUNIT, scale); - if (cx > scrwidth) + if (FixedInt(cx) > scrwidth) continue; - if (cx+left + w < 0) //left boundary check + if (cx+(left*FRACUNIT) + w < 0) // left boundary check { cx += w; continue; } - colormap = V_GetStringColormap(charflags); - V_DrawFixedPatch(cx<<FRACBITS, cy<<FRACBITS, FRACUNIT, option, tny_font[c], colormap); + V_DrawFixedPatch(cx, cy, scale, option, nto_font.chars[c], outlinecolormap); + V_DrawFixedPatch(cx, cy, scale, option, ntb_font.chars[c], basecolormap); cx += w; } } -void V_DrawCenteredThinString(INT32 x, INT32 y, INT32 option, const char *string) -{ - x -= V_ThinStringWidth(string, option)/2; - V_DrawThinString(x, y, option, string); -} - -void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *string) -{ - x -= V_ThinStringWidth(string, option); - V_DrawThinString(x, y, option, string); -} - -// -// Write a string using the tny_font, 0.5x scale -// NOTE: the text is centered for screens larger than the base width -// -// Literally a wrapper. ~Golden -void V_DrawSmallThinString(INT32 x, INT32 y, INT32 option, const char *string) -{ - x <<= FRACBITS; - y <<= FRACBITS; - V_DrawSmallThinStringAtFixed((fixed_t)x, (fixed_t)y, option, string); -} - -void V_DrawCenteredSmallThinString(INT32 x, INT32 y, INT32 option, const char *string) -{ - x <<= FRACBITS; - y <<= FRACBITS; - V_DrawCenteredSmallThinStringAtFixed((fixed_t)x, (fixed_t)y, option, string); -} - -void V_DrawRightAlignedSmallThinString(INT32 x, INT32 y, INT32 option, const char *string) -{ - x <<= FRACBITS; - y <<= FRACBITS; - V_DrawRightAlignedSmallThinStringAtFixed((fixed_t)x, (fixed_t)y, option, string); -} - -// Draws a string at a fixed_t location. -void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) +// Looks familiar. +void V_DrawNameTag(INT32 x, INT32 y, INT32 option, fixed_t scale, UINT8 *basecolormap, UINT8 *outlinecolormap, const char *string) { - fixed_t cx = x, cy = y; - INT32 w, c, dup, scrwidth, center = 0, left = 0; - const char *ch = string; - INT32 charflags = 0; - const UINT8 *colormap = NULL; - INT32 spacewidth = 4, charwidth = 0; - - INT32 lowercase = (option & V_ALLOWLOWERCASE); - option &= ~V_FLIP; // which is also shared with V_ALLOWLOWERCASE... + const char *text = string; + const char *first_token = text; + char *last_token = strchr(text, '\n'); + const INT32 lbreakheight = 21; + INT32 ntlines; - if (option & V_NOSCALESTART) + if (option & V_CENTERNAMETAG) { - dup = vid.dup; - scrwidth = vid.width; - } - else - { - dup = 1; - scrwidth = vid.width/vid.dup; - left = (scrwidth - BASEVIDWIDTH)/2; - scrwidth -= left; - } - - if (option & V_NOSCALEPATCH) - scrwidth *= vid.dup; - - charflags = (option & V_CHARCOLORMASK); - - switch (option & V_SPACINGMASK) - { - case V_MONOSPACE: - spacewidth = 8; - /* FALLTHRU */ - case V_OLDSPACING: - charwidth = 8; - break; - case V_6WIDTHSPACE: - spacewidth = 6; - default: - break; - } - - for (;;ch++) - { - if (!*ch) - break; - if (*ch & 0x80) //color ignoring - { - // manually set flags override color codes - if (!(option & V_CHARCOLORMASK)) - charflags = ((*ch & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK; - continue; - } - if (*ch == '\n') - { - cx = x; - - if (option & V_RETURN8) - cy += (8*dup)<<FRACBITS; - else - cy += (12*dup)<<FRACBITS; - - continue; - } - - c = *ch; - if (!lowercase) - c = toupper(c); - c -= HU_FONTSTART; - - // character does not exist or is a space - if (c < 0 || c >= HU_FONTSIZE || !hu_font[c]) - { - cx += (spacewidth * dup)<<FRACBITS; - continue; - } - - if (charwidth) - { - w = charwidth * dup; - center = w/2 - hu_font[c]->width*(dup/2); - } - else - w = hu_font[c]->width * dup; - - if ((cx>>FRACBITS) > scrwidth) - continue; - if ((cx>>FRACBITS)+left + w < 0) //left boundary check - { - cx += w<<FRACBITS; - continue; - } - - colormap = V_GetStringColormap(charflags); - V_DrawFixedPatch(cx + (center<<FRACBITS), cy, FRACUNIT, option, hu_font[c], colormap); - - cx += w<<FRACBITS; - } -} - -void V_DrawCenteredStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) -{ - x -= (V_StringWidth(string, option) / 2)<<FRACBITS; - V_DrawStringAtFixed(x, y, option, string); -} - -void V_DrawRightAlignedStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) -{ - x -= V_StringWidth(string, option)<<FRACBITS; - V_DrawStringAtFixed(x, y, option, string); -} - -// Draws a small string at a fixed_t location. -void V_DrawSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) -{ - fixed_t cx = x, cy = y; - INT32 w, c, dup, scrwidth, center = 0, left = 0; - const char *ch = string; - INT32 charflags = 0; - const UINT8 *colormap = NULL; - INT32 spacewidth = 2, charwidth = 0; - - INT32 lowercase = (option & V_ALLOWLOWERCASE); - option &= ~V_FLIP; // which is also shared with V_ALLOWLOWERCASE... - - if (option & V_NOSCALESTART) - { - dup = vid.dup; - scrwidth = vid.width; - } - else - { - dup = 1; - scrwidth = vid.width/vid.dup; - left = (scrwidth - BASEVIDWIDTH)/2; - scrwidth -= left; - } - - if (option & V_NOSCALEPATCH) - scrwidth *= vid.dup; - - charflags = (option & V_CHARCOLORMASK); - - switch (option & V_SPACINGMASK) - { - case V_MONOSPACE: - spacewidth = 4; - /* FALLTHRU */ - case V_OLDSPACING: - charwidth = 4; - break; - case V_6WIDTHSPACE: - spacewidth = 3; - default: - break; - } - - for (;;ch++) - { - if (!*ch) - break; - if (*ch & 0x80) //color parsing -x 2.16.09 - { - // manually set flags override color codes - if (!(option & V_CHARCOLORMASK)) - charflags = ((*ch & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK; - continue; - } - if (*ch == '\n') - { - cx = x; - - if (option & V_RETURN8) - cy += (4*dup)<<FRACBITS; - else - cy += (6*dup)<<FRACBITS; - - continue; - } - - c = *ch; - if (!lowercase) - c = toupper(c); - c -= HU_FONTSTART; - - // character does not exist or is a space - if (c < 0 || c >= HU_FONTSIZE || !hu_font[c]) - { - cx += (spacewidth * dup)<<FRACBITS; - continue; - } - - if (charwidth) - { - w = charwidth * dup; - center = w/2 - hu_font[c]->width*(dup/4); - } - else - w = hu_font[c]->width * dup / 2; - - if ((cx>>FRACBITS) > scrwidth) - break; - if ((cx>>FRACBITS)+left + w < 0) //left boundary check - { - cx += w<<FRACBITS; - continue; - } - - colormap = V_GetStringColormap(charflags); - - V_DrawFixedPatch(cx + (center<<FRACBITS), cy, FRACUNIT/2, option, hu_font[c], colormap); - - cx += w<<FRACBITS; - } -} - -void V_DrawCenteredSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) -{ - x -= (V_SmallStringWidth(string, option) / 2)<<FRACBITS; - V_DrawSmallStringAtFixed(x, y, option, string); -} - -void V_DrawRightAlignedSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) -{ - x -= V_SmallStringWidth(string, option)<<FRACBITS; - V_DrawSmallStringAtFixed(x, y, option, string); -} - -// Draws a thin string at a fixed_t location. -void V_DrawThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) -{ - fixed_t cx = x, cy = y; - INT32 w, c, dup, scrwidth, center = 0, left = 0; - const char *ch = string; - INT32 charflags = 0; - const UINT8 *colormap = NULL; - INT32 spacewidth = 2, charwidth = 0; - - INT32 lowercase = (option & V_ALLOWLOWERCASE); - option &= ~V_FLIP; // which is also shared with V_ALLOWLOWERCASE... - - if (option & V_NOSCALESTART) - { - dup = vid.dup; - scrwidth = vid.width; - } - else - { - dup = 1; - scrwidth = vid.width/vid.dup; - left = (scrwidth - BASEVIDWIDTH)/2; - scrwidth -= left; - } - - if (option & V_NOSCALEPATCH) - scrwidth *= vid.dup; - - charflags = (option & V_CHARCOLORMASK); - - switch (option & V_SPACINGMASK) - { - case V_MONOSPACE: - spacewidth = 8; - /* FALLTHRU */ - case V_OLDSPACING: - charwidth = 8; - break; - case V_6WIDTHSPACE: - spacewidth = 6; - default: - break; - } - - for (;;ch++) - { - if (!*ch) - break; - if (*ch & 0x80) //color parsing -x 2.16.09 - { - // manually set flags override color codes - if (!(option & V_CHARCOLORMASK)) - charflags = ((*ch & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK; - continue; - } - if (*ch == '\n') - { - cx = x; - - if (option & V_RETURN8) - cy += (8*dup)<<FRACBITS; - else - cy += (12*dup)<<FRACBITS; - - continue; - } - - c = *ch; - if (!lowercase || !tny_font[c-HU_FONTSTART]) - c = toupper(c); - c -= HU_FONTSTART; - - // character does not exist or is a space - if (c < 0 || c >= HU_FONTSIZE || !tny_font[c]) - { - cx += (spacewidth * dup)<<FRACBITS; - continue; - } - - if (charwidth) - { - w = charwidth * dup; - center = w/2 - tny_font[c]->width*(dup/2); - } - else - w = tny_font[c]->width * dup; - - if ((cx>>FRACBITS) > scrwidth) - break; - if ((cx>>FRACBITS)+left + w < 0) //left boundary check - { - cx += w<<FRACBITS; - continue; - } - - colormap = V_GetStringColormap(charflags); - - V_DrawFixedPatch(cx + (center<<FRACBITS), cy, FRACUNIT, option, tny_font[c], colormap); - - cx += w<<FRACBITS; - } -} - -void V_DrawCenteredThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) -{ - x -= (V_ThinStringWidth(string, option) / 2)<<FRACBITS; - V_DrawThinStringAtFixed(x, y, option, string); -} - -void V_DrawRightAlignedThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) -{ - x -= V_ThinStringWidth(string, option)<<FRACBITS; - V_DrawThinStringAtFixed(x, y, option, string); -} - -// Draws a small string at a fixed_t location. -void V_DrawSmallThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) -{ - fixed_t cx = x, cy = y; - INT32 w, c, dup, scrwidth, center = 0, left = 0; - const char *ch = string; - INT32 charflags = 0; - const UINT8 *colormap = NULL; - INT32 spacewidth = 2<<FRACBITS, charwidth = 0; - - INT32 lowercase = (option & V_ALLOWLOWERCASE); - option &= ~V_FLIP; // which is also shared with V_ALLOWLOWERCASE... - - if (option & V_NOSCALESTART) - { - dup = vid.dup<<FRACBITS; - scrwidth = vid.width; - } - else - { - dup = FRACUNIT; - scrwidth = FixedDiv(vid.width<<FRACBITS, vid.dup); - left = ((scrwidth - (BASEVIDWIDTH<<FRACBITS))/2); - scrwidth -= left; - } - - if (option & V_NOSCALEPATCH) - scrwidth *= vid.dup; - - charflags = (option & V_CHARCOLORMASK); - - switch (option & V_SPACINGMASK) - { - case V_MONOSPACE: - spacewidth = 4<<FRACBITS; - /* FALLTHRU */ - case V_OLDSPACING: - charwidth = 4<<FRACBITS; - break; - case V_6WIDTHSPACE: - spacewidth = 3<<FRACBITS; - default: - break; - } - - for (;;ch++) - { - if (!*ch) - break; - if (*ch & 0x80) //color parsing -x 2.16.09 - { - // manually set flags override color codes - if (!(option & V_CHARCOLORMASK)) - charflags = ((*ch & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK; - continue; - } - if (*ch == '\n') - { - cx = x; - - if (option & V_RETURN8) - cy += 4*dup; - else - cy += 6*dup; - - continue; - } - - c = *ch; - if (!lowercase) - c = toupper(c); - c -= HU_FONTSTART; - - // character does not exist or is a space - if (c < 0 || c >= HU_FONTSIZE || !tny_font[c]) - { - cx += FixedMul(spacewidth, dup); - continue; - } - - if (charwidth) - { - w = FixedMul(charwidth, dup); - center = w/2 - tny_font[c]->width*(dup/4); - } - else - w = tny_font[c]->width * dup / 2; - - if (cx > scrwidth) - break; - if (cx+left + w < 0) //left boundary check - { - cx += w; - continue; - } - - colormap = V_GetStringColormap(charflags); - - V_DrawFixedPatch(cx + center, cy, FRACUNIT/2, option, tny_font[c], colormap); - - cx += w; - } -} - -void V_DrawCenteredSmallThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) -{ - x -= V_SmallThinStringWidth(string, option)/4; - V_DrawSmallThinStringAtFixed(x, y, option, string); -} - -void V_DrawRightAlignedSmallThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) -{ - x -= V_SmallThinStringWidth(string, option)/2; - V_DrawSmallThinStringAtFixed(x, y, option, string); -} - -// Draws a tallnum. Replaces two functions in y_inter and st_stuff -void V_DrawTallNum(INT32 x, INT32 y, INT32 flags, INT32 num) -{ - INT32 w = tallnum[0]->width; - boolean neg; - - if (flags & (V_NOSCALESTART|V_NOSCALEPATCH)) - w *= vid.dup; - - if ((neg = num < 0)) - num = -num; - - // draw the number - do - { - x -= w; - V_DrawScaledPatch(x, y, flags, tallnum[num % 10]); - num /= 10; - } while (num); - - // draw a minus sign if necessary - if (neg) - V_DrawScaledPatch(x - w, y, flags, tallminus); // Tails -} - -// Draws a number with a set number of digits. -// Does not handle negative numbers in a special way, don't try to feed it any. -void V_DrawPaddedTallNum(INT32 x, INT32 y, INT32 flags, INT32 num, INT32 digits) -{ - INT32 w = tallnum[0]->width; - - if (flags & (V_NOSCALESTART|V_NOSCALEPATCH)) - w *= vid.dup; - - if (num < 0) - num = -num; - - // draw the number - do - { - x -= w; - V_DrawScaledPatch(x, y, flags, tallnum[num % 10]); - num /= 10; - } while (--digits); -} - -// Draw an act number for a level title -void V_DrawLevelActNum(INT32 x, INT32 y, INT32 flags, UINT8 num) -{ - if (num > 99) - return; // not supported - - while (num > 0) - { - if (num > 9) // if there are two digits, draw second digit first - V_DrawScaledPatch(x + (V_LevelActNumWidth(num) - V_LevelActNumWidth(num%10)), y, flags, ttlnum[num%10]); - else - V_DrawScaledPatch(x, y, flags, ttlnum[num]); - num = num/10; - } -} - -// Write a string using the credit font -// NOTE: the text is centered for screens larger than the base width -// -void V_DrawCreditString(fixed_t x, fixed_t y, INT32 option, const char *string) -{ - INT32 w, c, dup, scrwidth = BASEVIDWIDTH; - fixed_t cx = x, cy = y; - const char *ch = string; - - // It's possible for string to be a null pointer - if (!string) - return; - - if (option & V_NOSCALESTART) - { - dup = vid.dup; - scrwidth = vid.width; - } - else - dup = 1; - - if (option & V_NOSCALEPATCH) - scrwidth *= vid.dup; - - for (;;) - { - c = *ch++; - if (!c) - break; - if (c == '\n') - { - cx = x; - cy += (12*dup)<<FRACBITS; - continue; - } - - c = toupper(c) - CRED_FONTSTART; - if (c < 0 || c >= CRED_FONTSIZE) - { - cx += (16*dup)<<FRACBITS; - continue; - } - - w = cred_font[c]->width * dup; - if ((cx>>FRACBITS) > scrwidth) - continue; - - V_DrawSciencePatch(cx, cy, option, cred_font[c], FRACUNIT); - cx += w<<FRACBITS; - } -} - -// Draw a string using the nt_font -// Note that the outline is a seperate font set -static void V_DrawNameTagLine(INT32 x, INT32 y, INT32 option, fixed_t scale, UINT8 *basecolormap, UINT8 *outlinecolormap, const char *string) -{ - fixed_t cx, cy, w; - INT32 c, dup, scrwidth, left = 0; - const char *ch = string; - - if (option & V_CENTERNAMETAG) - x -= FixedInt(FixedMul((V_NameTagWidth(string)/2)*FRACUNIT, scale)); - option &= ~V_CENTERNAMETAG; // which is also shared with V_ALLOWLOWERCASE... - - cx = x<<FRACBITS; - cy = y<<FRACBITS; - - if (option & V_NOSCALESTART) - { - dup = vid.dup; - scrwidth = vid.width; - } - else - { - dup = 1; - scrwidth = vid.width/vid.dup; - left = (scrwidth - BASEVIDWIDTH)/2; - scrwidth -= left; - } - - if (option & V_NOSCALEPATCH) - scrwidth *= vid.dup; - - for (;;ch++) - { - if (!*ch) - break; - if (*ch == '\n') - { - cx = x<<FRACBITS; - cy += FixedMul((21*dup)*FRACUNIT, scale); - continue; - } - - c = toupper(*ch); - c -= NT_FONTSTART; - - // character does not exist or is a space - if (c < 0 || c >= NT_FONTSIZE || !ntb_font[c] || !nto_font[c]) - { - cx += FixedMul((4 * dup)*FRACUNIT, scale); - continue; - } - - w = FixedMul(((ntb_font[c]->width)+2 * dup) * FRACUNIT, scale); - - if (FixedInt(cx) > scrwidth) - continue; - if (cx+(left*FRACUNIT) + w < 0) // left boundary check - { - cx += w; - continue; - } - - V_DrawFixedPatch(cx, cy, scale, option, nto_font[c], outlinecolormap); - V_DrawFixedPatch(cx, cy, scale, option, ntb_font[c], basecolormap); - - cx += w; - } -} - -// Looks familiar. -void V_DrawNameTag(INT32 x, INT32 y, INT32 option, fixed_t scale, UINT8 *basecolormap, UINT8 *outlinecolormap, const char *string) -{ - const char *text = string; - const char *first_token = text; - char *last_token = strchr(text, '\n'); - const INT32 lbreakheight = 21; - INT32 ntlines; - - if (option & V_CENTERNAMETAG) - { - ntlines = V_CountNameTagLines(string); - y -= FixedInt(FixedMul(((lbreakheight/2) * (ntlines-1))*FRACUNIT, scale)); + ntlines = V_CountNameTagLines(string); + y -= FixedInt(FixedMul(((lbreakheight/2) * (ntlines-1))*FRACUNIT, scale)); } // No line breaks? @@ -3169,193 +2394,20 @@ INT32 V_CountNameTagLines(const char *string) return ntlines; } -INT32 V_NameTagWidth(const char *string) -{ - INT32 c, w = 0; - size_t i; - - // It's possible for string to be a null pointer - if (!string) - return 0; - - for (i = 0; i < strlen(string); i++) - { - c = toupper(string[i]) - NT_FONTSTART; - if (c < 0 || c >= NT_FONTSIZE || !ntb_font[c] || !nto_font[c]) - w += 4; - else - w += (ntb_font[c]->width)+2; - } - - return w; -} - -// Find string width from cred_font chars -// -INT32 V_CreditStringWidth(const char *string) -{ - INT32 c, w = 0; - size_t i; - - // It's possible for string to be a null pointer - if (!string) - return 0; - - for (i = 0; i < strlen(string); i++) - { - c = toupper(string[i]) - CRED_FONTSTART; - if (c < 0 || c >= CRED_FONTSIZE) - w += 16; - else - w += cred_font[c]->width; - } - - return w; -} - -// Write a string using the level title font -// NOTE: the text is centered for screens larger than the base width -// -void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string) -{ - INT32 w, c, cx = x, cy = y, dup, scrwidth, left = 0; - const char *ch = string; - INT32 charflags = (option & V_CHARCOLORMASK); - const UINT8 *colormap = NULL; - - if (option & V_NOSCALESTART) - { - dup = vid.dup; - scrwidth = vid.width; - } - else - { - dup = 1; - scrwidth = vid.width/vid.dup; - left = (scrwidth - BASEVIDWIDTH)/2; - scrwidth -= left; - } - - if (option & V_NOSCALEPATCH) - scrwidth *= vid.dup; - - for (;;ch++) - { - if (!*ch) - break; - if (*ch & 0x80) //color parsing -x 2.16.09 - { - // manually set flags override color codes - if (!(option & V_CHARCOLORMASK)) - charflags = ((*ch & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK; - continue; - } - if (*ch == '\n') - { - cx = x; - cy += 12*dup; - continue; - } - - c = *ch - LT_FONTSTART; - if (c < 0 || c >= LT_FONTSIZE || !lt_font[c]) - { - cx += 16*dup; - continue; - } - - w = lt_font[c]->width * dup; - - if (cx > scrwidth) - continue; - if (cx+left + w < 0) //left boundary check - { - cx += w; - continue; - } - - colormap = V_GetStringColormap(charflags); - V_DrawFixedPatch(cx<<FRACBITS, cy<<FRACBITS, FRACUNIT, option, lt_font[c], colormap); - - cx += w; - } -} - -// Find string width from lt_font chars -// -INT32 V_LevelNameWidth(const char *string) -{ - INT32 c, w = 0; - size_t i; - - for (i = 0; i < strlen(string); i++) - { - if (string[i] & 0x80) - continue; - c = string[i] - LT_FONTSTART; - if (c < 0 || c >= LT_FONTSIZE || !lt_font[c]) - w += 16; - else - w += lt_font[c]->width; - } - - return w; -} - -// Find max height of the string -// -INT32 V_LevelNameHeight(const char *string) -{ - INT32 c, w = 0; - size_t i; - - for (i = 0; i < strlen(string); i++) - { - c = string[i] - LT_FONTSTART; - if (c < 0 || c >= LT_FONTSIZE || !lt_font[c]) - continue; - - if (lt_font[c]->height > w) - w = lt_font[c]->height; - } - - return w; -} - -// For ST_drawTitleCard -// Returns the width of the act num patch(es) -INT16 V_LevelActNumWidth(UINT8 num) -{ - INT16 result = 0; - - if (num == 0) - result = ttlnum[num]->width; - - while (num > 0 && num <= 99) - { - result = result + ttlnum[num%10]->width; - num = num/10; - } - - return result; -} - +// Find string width from supplied font characters & character width. // -// Find string width from hu_font chars -// -INT32 V_StringWidth(const char *string, INT32 option) +INT32 V_FontStringWidth(const char *string, INT32 option, fontdef_t font) { - INT32 c, w = 0; - INT32 spacewidth = 4, charwidth = 0; - size_t i; + INT32 c, w = 0, wline = 0; + INT32 spacewidth = font.spacewidth, charwidth = 0; switch (option & V_SPACINGMASK) { case V_MONOSPACE: - spacewidth = 8; + spacewidth = font.charwidth; /* FALLTHRU */ case V_OLDSPACING: - charwidth = 8; + charwidth = font.charwidth; break; case V_6WIDTHSPACE: spacewidth = 6; @@ -3363,16 +2415,24 @@ INT32 V_StringWidth(const char *string, INT32 option) break; } - for (i = 0; i < strlen(string); i++) + for (size_t i = 0; i < strlen(string); i++) { + if (string[i] == '\n') + { + if (wline < w) wline = w; + w = 0; + continue; + } if (string[i] & 0x80) continue; - c = toupper(string[i]) - HU_FONTSTART; - if (c < 0 || c >= HU_FONTSIZE || !hu_font[c]) + + c = (option & V_ALLOWLOWERCASE ? string[i] : toupper(string[i])) - FONTSTART; + if (c < 0 || c >= FONTSIZE || !font.chars[c]) w += spacewidth; else - w += (charwidth ? charwidth : hu_font[c]->width); + w += (charwidth ? charwidth : (font.chars[c]->width)) + font.kerning; } + w = max(wline, w); if (option & (V_NOSCALESTART|V_NOSCALEPATCH)) w *= vid.dup; @@ -3380,87 +2440,30 @@ INT32 V_StringWidth(const char *string, INT32 option) return w; } +// Find max string height from supplied font characters // -// Find string width from hu_font chars, 0.5x scale -// -INT32 V_SmallStringWidth(const char *string, INT32 option) +INT32 V_FontStringHeight(const char *string, INT32 option, fontdef_t font) { - INT32 c, w = 0; - INT32 spacewidth = 2, charwidth = 0; - size_t i; + INT32 c, h = 0, result = 0; - switch (option & V_SPACINGMASK) - { - case V_MONOSPACE: - spacewidth = 4; - /* FALLTHRU */ - case V_OLDSPACING: - charwidth = 4; - break; - case V_6WIDTHSPACE: - spacewidth = 3; - default: - break; - } - - for (i = 0; i < strlen(string); i++) + for (size_t i = 0; i < strlen(string); i++) { - if (string[i] & 0x80) + c = (option & V_ALLOWLOWERCASE ? string[i] : toupper(string[i])) - FONTSTART; + if (c < 0 || c >= FONTSIZE || !font.chars[c]) + { + if (string[i] == '\n') + { + result += (option & V_RETURN8) ? 8 : font.linespacing; + h = 0; + } continue; - c = toupper(string[i]) - HU_FONTSTART; - if (c < 0 || c >= HU_FONTSIZE || !hu_font[c]) - w += spacewidth; - else - w += (charwidth ? charwidth : (hu_font[c]->width / 2)); - } - - return w; -} - -// -// Find string width from tny_font chars -// -INT32 V_ThinStringWidth(const char *string, INT32 option) -{ - INT32 c, w = 0; - INT32 spacewidth = 2, charwidth = 0; - size_t i; - - switch (option & V_SPACINGMASK) - { - case V_MONOSPACE: - spacewidth = 5; - /* FALLTHRU */ - case V_OLDSPACING: - charwidth = 5; - break; - case V_6WIDTHSPACE: - spacewidth = 3; - default: - break; - } + } - for (i = 0; i < strlen(string); i++) - { - if (string[i] & 0x80) - continue; - c = toupper(string[i]) - HU_FONTSTART; - if (c < 0 || c >= HU_FONTSIZE || !tny_font[c]) - w += spacewidth; - else - w += (charwidth ? charwidth : tny_font[c]->width); + if (font.chars[c]->height > h) + h = font.chars[c]->height; } - return w; -} - -// -// Find string width from tny_font chars, 0.5x scale -// -INT32 V_SmallThinStringWidth(const char *string, INT32 option) -{ - INT32 w = V_ThinStringWidth(string, option)<<FRACBITS; - return w/2 + FRACUNIT; // +FRACUNIT because otherwise it's offset wrong. + return result + h; } boolean *heatshifter = NULL; diff --git a/src/v_video.h b/src/v_video.h index 5a3df5a4499588df56e4a6d152f1445f82a60926..bdab23e8ad6cbd0c5868525da6f91500742e7e0f 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -17,6 +17,7 @@ #include "doomdef.h" #include "doomtype.h" #include "r_defs.h" +#include "hu_stuff.h" //font arrays // // VIDEO @@ -191,86 +192,93 @@ void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, U void V_DrawFadeConsBack(INT32 plines); void V_DrawPromptBack(INT32 boxheight, INT32 color); - -// draw a single character -void V_DrawCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed); -// draw a single character, but for the chat -void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, UINT8 *colormap); - -UINT8 *V_GetStringColormap(INT32 colorflags); - -void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string); - -// wordwrap a string using the hu_font -char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string); UINT8 *V_GetStringColormap(INT32 colorflags); +// Generalized character drawing function, combining console & chat functionality with a specified font. +void V_DrawFontCharacter(INT32 x, INT32 y, INT32 c, boolean lowercaseallowed, fixed_t scale, UINT8 *colormap, fontdef_t font); +#define V_DrawCharacter(x,y,c,l) V_DrawFontCharacter(x,y,c,l,FRACUNIT,NULL,hu_font) +#define V_DrawChatCharacter(x,y,c,l,cm) V_DrawFontCharacter(x,y,c,l,FRACUNIT/2,cm,hu_font) + +// Precompile a wordwrapped string to any given width, using a specified font. +char *V_FontWordWrap(INT32 x, INT32 w, INT32 option, fixed_t scale, const char *string, fontdef_t font); +#define V_WordWrap(x,w,o,str) V_FontWordWrap(x, w, o, FRACUNIT, str, hu_font) +#define V_ChatWordWrap(x,w,o,str) V_FontWordWrap(x, w, o, FRACUNIT/2, str, hu_font) + +enum string_align { + alignleft = 0, + aligncenter, + alignright +}; + +// Draw a string, using a supplied font and scale. +void V_DrawFontString(INT32 x, INT32 y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font); +void V_DrawAlignedFontString(INT32 x, INT32 y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font, enum string_align align); +// Draw a string, using a supplied font and scale, at fixed_t coordinates. +void V_DrawFontStringAtFixed(fixed_t x, fixed_t y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font); +void V_DrawAlignedFontStringAtFixed(fixed_t x, fixed_t y, INT32 option, fixed_t pscale, fixed_t vscale, const char *string, fontdef_t font, enum string_align align); + +// Defines for old string drawers. // draw a string using the hu_font -void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string); -void V_DrawCenteredString(INT32 x, INT32 y, INT32 option, const char *string); -void V_DrawRightAlignedString(INT32 x, INT32 y, INT32 option, const char *string); - +#define V_DrawString(x,y,o,str) V_DrawFontString(x,y,o,FRACUNIT,FRACUNIT,str,hu_font) +#define V_DrawCenteredString(x,y,o,str) V_DrawAlignedFontString(x,y,o,FRACUNIT,FRACUNIT,str,hu_font,aligncenter) +#define V_DrawRightAlignedString(x,y,o,str) V_DrawAlignedFontString(x,y,o,FRACUNIT,FRACUNIT,str,hu_font,alignright) // draw a string using the hu_font, 0.5x scale -void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string); -void V_DrawCenteredSmallString(INT32 x, INT32 y, INT32 option, const char *string); -void V_DrawRightAlignedSmallString(INT32 x, INT32 y, INT32 option, const char *string); - -// draw a string using the tny_font -void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string); -void V_DrawCenteredThinString(INT32 x, INT32 y, INT32 option, const char *string); -void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *string); - +#define V_DrawSmallString(x,y,o,str) V_DrawFontString(x,y,o,FRACUNIT/2,FRACUNIT/2,str,hu_font) +#define V_DrawCenteredSmallString(x,y,o,str) V_DrawAlignedFontString(x,y,o,FRACUNIT/2,FRACUNIT/2,str,hu_font,aligncenter) +#define V_DrawRightAlignedSmallString(x,y,o,str) V_DrawAlignedFontString(x,y,o,FRACUNIT/2,FRACUNIT/2,str,hu_font,alignright) +// Write a string using the tny_font +#define V_DrawThinString(x,y,o,str) V_DrawFontString(x,y,o,FRACUNIT,FRACUNIT,str,tny_font) +#define V_DrawCenteredThinString(x,y,o,str) V_DrawAlignedFontString(x,y,o,FRACUNIT,FRACUNIT,str,tny_font,aligncenter) +#define V_DrawRightAlignedThinString(x,y,o,str) V_DrawAlignedFontString(x,y,o,FRACUNIT,FRACUNIT,str,tny_font,alignright) // draw a string using the tny_font, 0.5x scale -void V_DrawSmallThinString(INT32 x, INT32 y, INT32 option, const char *string); -void V_DrawCenteredSmallThinString(INT32 x, INT32 y, INT32 option, const char *string); -void V_DrawRightAlignedSmallThinString(INT32 x, INT32 y, INT32 option, const char *string); - +#define V_DrawSmallThinString(x,y,o,str) V_DrawFontString(x,y,o,FRACUNIT/2,FRACUNIT/2,str,tny_font) +#define V_DrawCenteredSmallThinString(x,y,o,str) V_DrawAlignedFontString(x,y,o,FRACUNIT/2,FRACUNIT/2,str,tny_font,aligncenter) +#define V_DrawRightAlignedSmallThinString(x,y,o,str) V_DrawAlignedFontString(x,y,o,FRACUNIT/2,FRACUNIT/2,str,tny_font,alignright) // draw a string using the hu_font at fixed_t coordinates -void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); -void V_DrawCenteredStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); -void V_DrawRightAlignedStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); - +#define V_DrawStringAtFixed(x,y,o,str) V_DrawFontStringAtFixed(x,y,o,FRACUNIT,FRACUNIT,str,hu_font) +#define V_DrawCenteredStringAtFixed(x,y,o,str) V_DrawAlignedFontStringAtFixed(x,y,o,FRACUNIT,FRACUNIT,str,hu_font,aligncenter) +#define V_DrawRightAlignedStringAtFixed(x,y,o,str) V_DrawAlignedFontStringAtFixed(x,y,o,FRACUNIT,FRACUNIT,str,hu_font,alignright) // draw a string using the hu_font at fixed_t coordinates, 0.5x scale -void V_DrawSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); -void V_DrawCenteredSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); -void V_DrawRightAlignedSmallStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); - +#define V_DrawSmallStringAtFixed(x,y,o,str) V_DrawFontStringAtFixed(x,y,o,FRACUNIT/2,FRACUNIT/2,str,hu_font) +#define V_DrawCenteredSmallStringAtFixed(x,y,o,str) V_DrawAlignedFontStringAtFixed(x,y,o,FRACUNIT/2,FRACUNIT/2,str,hu_font,aligncenter) +#define V_DrawRightAlignedSmallStringAtFixed(x,y,o,str) V_DrawAlignedFontStringAtFixed(x,y,o,FRACUNIT/2,FRACUNIT/2,str,hu_font,alignright) // draw a string using the tny_font at fixed_t coordinates -void V_DrawThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); -void V_DrawCenteredThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); -void V_DrawRightAlignedThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); - +#define V_DrawThinStringAtFixed(x,y,o,str) V_DrawFontStringAtFixed(x,y,o,FRACUNIT,FRACUNIT,str,tny_font) +#define V_DrawCenteredThinStringAtFixed(x,y,o,str) V_DrawAlignedFontStringAtFixed(x,y,o,FRACUNIT,FRACUNIT,str,tny_font,aligncenter) +#define V_DrawRightAlignedThinStringAtFixed(x,y,o,str) V_DrawAlignedFontStringAtFixed(x,y,o,FRACUNIT,FRACUNIT,str,tny_font,alignright) // draw a string using the tny_font at fixed_t coordinates, 0.5x scale -void V_DrawSmallThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); -void V_DrawCenteredSmallThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); -void V_DrawRightAlignedSmallThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); +#define V_DrawSmallThinStringAtFixed(x,y,o,str) V_DrawFontStringAtFixed(x,y,o,FRACUNIT/2,FRACUNIT/2,str,tny_font) +#define V_DrawCenteredSmallThinStringAtFixed(x,y,o,str) V_DrawAlignedFontStringAtFixed(x,y,o,FRACUNIT/2,FRACUNIT/2,str,tny_font,aligncenter) +#define V_DrawRightAlignedSmallThinStringAtFixed(x,y,o,str) V_DrawAlignedFontStringAtFixed(x,y,o,FRACUNIT/2,FRACUNIT/2,str,tny_font,alignright) +// draw a string using the credit font +#define V_DrawCreditString(x,y,o,str) V_DrawFontStringAtFixed(x,y,o,FRACUNIT,FRACUNIT,str,cred_font) +// draw a string using the level title font +#define V_DrawLevelTitle(x,y,o,str) V_DrawFontString(x,y,o|V_ALLOWLOWERCASE,FRACUNIT,FRACUNIT,str,lt_font) // Draw tall nums, used for menu, HUD, intermission void V_DrawTallNum(INT32 x, INT32 y, INT32 flags, INT32 num); void V_DrawPaddedTallNum(INT32 x, INT32 y, INT32 flags, INT32 num, INT32 digits); void V_DrawLevelActNum(INT32 x, INT32 y, INT32 flags, UINT8 num); - -// Find string width from lt_font chars -INT32 V_LevelNameWidth(const char *string); -INT32 V_LevelNameHeight(const char *string); INT16 V_LevelActNumWidth(UINT8 num); // act number width -void V_DrawCreditString(fixed_t x, fixed_t y, INT32 option, const char *string); -INT32 V_CreditStringWidth(const char *string); - // Draw a string using the nt_font void V_DrawNameTag(INT32 x, INT32 y, INT32 option, fixed_t scale, UINT8 *basecolormap, UINT8 *outlinecolormap, const char *string); INT32 V_CountNameTagLines(const char *string); -INT32 V_NameTagWidth(const char *string); - -// Find string width from hu_font chars -INT32 V_StringWidth(const char *string, INT32 option); -// Find string width from hu_font chars, 0.5x scale -INT32 V_SmallStringWidth(const char *string, INT32 option); -// Find string width from tny_font chars -INT32 V_ThinStringWidth(const char *string, INT32 option); -// Find string width from tny_font chars, 0.5x scale -INT32 V_SmallThinStringWidth(const char *string, INT32 option); + +// Find string width or height from supplied font chars +INT32 V_FontStringWidth(const char *string, INT32 option, fontdef_t font); +INT32 V_FontStringHeight(const char *string, INT32 option, fontdef_t font); + +// Defines for old string width functions. +#define V_StringWidth(str,o) V_FontStringWidth(str,o,hu_font) +#define V_SmallStringWidth(str,o) V_FontStringWidth(str,o,hu_font)/2 +#define V_ThinStringWidth(str,o) V_FontStringWidth(str,o,tny_font) +#define V_SmallThinStringWidth(str,o) V_FontStringWidth(str,o,tny_font)/2 +#define V_CreditStringWidth(str) V_FontStringWidth(str,0,cred_font) +#define V_NameTagWidth(str) V_FontStringWidth(str,0,ntb_font) +#define V_LevelNameWidth(str) V_FontStringWidth(str,V_ALLOWLOWERCASE,lt_font) +#define V_LevelNameHeight(str) V_FontStringHeight(str,0,lt_font) +#define V_StringHeight(str,o) V_FontStringHeight(str,o,hu_font) void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param); diff --git a/src/version.h b/src/version.h index 8d8f8978e7ea3cf593247a73a9460ed139193c10..8e69194cd20b98debe50bc67afb264a0bb2aec9b 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ -#define SRB2VERSION "2.2.14"/* this must be the first line, for cmake !! */ +#define SRB2VERSION "2.2.15"/* this must be the first line, for cmake !! */ // The Modification ID; must be obtained from a Master Server Admin ( https://mb.srb2.org/members/?key=ms_admin ). // DO NOT try to set this otherwise, or your modification will be unplayable through the Master Server. @@ -9,7 +9,7 @@ // it's only for detection of the version the player is using so the MS can alert them of an update. // Only set it higher, not lower, obviously. // Note that we use this to help keep internal testing in check; this is why v2.2.0 is not version "1". -#define MODVERSION 55 +#define MODVERSION 56 // Define this as a prerelease version suffix (pre#, RC#) -#define BETAVERSION "nightly" +//#define BETAVERSION "pre4" diff --git a/src/w_wad.c b/src/w_wad.c index 3a50646930e984762ffb720f2c2022edac075e33..50ba622a9b32f538b18d50dcdf29fbfd457f7355 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -65,6 +65,7 @@ #include "i_video.h" // rendermode #include "md5.h" #include "lua_script.h" +#include "lua_hook.h" #ifdef SCANTHINGS #include "p_setup.h" // P_ScanThings #endif @@ -98,6 +99,7 @@ typedef struct lumpnum_cache_s { char lumpname[32]; lumpnum_t lumpnum; + UINT32 hash; } lumpnum_cache_t; static lumpnum_cache_t lumpnumcache[LUMPNUMCACHESIZE]; @@ -306,12 +308,10 @@ static void W_LoadDehackedLumps(UINT16 wadnum, boolean mainfile) * \param resblock resulting MD5 checksum * \return 0 if MD5 checksum was made, and is at resblock, 1 if error was found */ + +#ifndef NOMD5 static INT32 W_MakeFileMD5(const char *filename, void *resblock) { -#ifdef NOMD5 - (void)filename; - memset(resblock, 0x00, 16); -#else FILE *fhandle; if ((fhandle = fopen(filename, "rb")) != NULL) @@ -328,9 +328,9 @@ static INT32 W_MakeFileMD5(const char *filename, void *resblock) fclose(fhandle); return 0; } -#endif return 1; } +#endif // Invalidates the cache of lump numbers. Call this whenever a wad is added. static void W_InvalidateLumpnumCache(void) @@ -821,10 +821,7 @@ static void W_ReadFileShaders(wadfile_t *wadfile) { #ifdef HWRENDER if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED)) - { HWR_LoadCustomShadersFromFile(numwadfiles - 1, W_FileHasFolders(wadfile)); - HWR_CompileShaders(); - } #else (void)wadfile; #endif @@ -1013,6 +1010,10 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup) break; } + lua_lumploading++; + LUA_HookVoid(HOOK(AddonLoaded)); + lua_lumploading--; + W_InvalidateLumpnumCache(); return wadfile->numlumps; } @@ -1171,7 +1172,13 @@ UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup) numwadfiles++; W_ReadFileShaders(wadfile); + W_LoadTrnslateLumps(numwadfiles - 1); W_LoadDehackedLumpsPK3(numwadfiles - 1, mainfile); + + lua_lumploading++; + LUA_HookVoid(HOOK(AddonLoaded)); + lua_lumploading--; + W_InvalidateLumpnumCache(); return wadfile->numlumps; @@ -1330,10 +1337,10 @@ UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlum /* SLADE is special and puts a single directory entry. Skip that. */ if (strlen(lump_p->fullname) == name_length) i++; - break; + return i; } } - return i; + return INT16_MAX; } // In a PK3 type of resource file, it looks for the next lumpinfo entry that doesn't share the specified pathfile. @@ -1351,6 +1358,47 @@ UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump) return i; } +char *W_GetLumpFolderPathPK3(UINT16 wad, UINT16 lump) +{ + const char *fullname = wadfiles[wad]->lumpinfo[lump].fullname; + + const char *slash = strrchr(fullname, '/'); + INT32 pathlen = slash ? slash - fullname : 0; + + char *path = Z_Calloc(pathlen + 1, PU_STATIC, NULL); + strncpy(path, fullname, pathlen); + + return path; +} + +char *W_GetLumpFolderNamePK3(UINT16 wad, UINT16 lump) +{ + const char *fullname = wadfiles[wad]->lumpinfo[lump].fullname; + size_t start, end; + + INT32 i = strlen(fullname); + + i--; + while (i >= 0 && fullname[i] != '/') + i--; + if (i < 0) + return NULL; + end = i; + + i--; + while (i >= 0 && fullname[i] != '/') + i--; + if (i < 0) + return NULL; + start = i + 1; + + size_t namelen = end - start; + char *foldername = Z_Calloc(namelen + 1, PU_STATIC, NULL); + strncpy(foldername, fullname + start, namelen); + + return foldername; +} + void W_GetFolderLumpsPwad(const char *name, UINT16 wad, UINT32 **list, UINT16 *list_capacity, UINT16 *numlumps) { size_t name_length = strlen(name); @@ -1436,6 +1484,63 @@ UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump) return INT16_MAX; } +static lumpnum_t CheckLumpInCache(const char *name, boolean longname) +{ + if (longname) + { + UINT32 hash = quickncasehash(name, 32); + + // Loop backwards so that we check most recent entries first + for (INT32 i = lumpnumcacheindex + LUMPNUMCACHESIZE; i > lumpnumcacheindex; i--) + { + if (lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].hash == hash + && stricmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name) == 0) + { + lumpnumcacheindex = i & (LUMPNUMCACHESIZE - 1); + return lumpnumcache[lumpnumcacheindex].lumpnum; + } + } + } + else + { + UINT32 hash = quickncasehash(name, 8); + + // Loop backwards so that we check most recent entries first + for (INT32 i = lumpnumcacheindex + LUMPNUMCACHESIZE; i > lumpnumcacheindex; i--) + { + if (lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].hash == hash + && lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname[8] == '\0' + && strnicmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name, 8) == 0) + { + lumpnumcacheindex = i & (LUMPNUMCACHESIZE - 1); + return lumpnumcache[lumpnumcacheindex].lumpnum; + } + } + } + + return LUMPERROR; +} + +static void AddLumpToCache(lumpnum_t lumpnum, const char *name, boolean longname) +{ + if (longname && strlen(name) >= 32) + return; + + lumpnumcacheindex = (lumpnumcacheindex + 1) & (LUMPNUMCACHESIZE - 1); + memset(lumpnumcache[lumpnumcacheindex].lumpname, '\0', 32); + if (longname) + { + strlcpy(lumpnumcache[lumpnumcacheindex].lumpname, name, 32); + lumpnumcache[lumpnumcacheindex].hash = quickncasehash(name, 32); + } + else + { + strncpy(lumpnumcache[lumpnumcacheindex].lumpname, name, 8); + lumpnumcache[lumpnumcacheindex].hash = quickncasehash(name, 8); + } + lumpnumcache[lumpnumcacheindex].lumpnum = lumpnum; +} + // // W_CheckNumForName // Returns LUMPERROR if name not found. @@ -1448,17 +1553,10 @@ lumpnum_t W_CheckNumForName(const char *name) if (!*name) // some doofus gave us an empty string? return LUMPERROR; - // Check the lumpnumcache first. Loop backwards so that we check - // most recent entries first - for (i = lumpnumcacheindex + LUMPNUMCACHESIZE; i > lumpnumcacheindex; i--) - { - if (!lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname[8] - && strncmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name, 8) == 0) - { - lumpnumcacheindex = i & (LUMPNUMCACHESIZE - 1); - return lumpnumcache[lumpnumcacheindex].lumpnum; - } - } + // Check the lumpnumcache first. + lumpnum_t cachenum = CheckLumpInCache(name, false); + if (cachenum != LUMPERROR) + return cachenum; // scan wad files backwards so patch lump files take precedence for (i = numwadfiles - 1; i >= 0; i--) @@ -1472,12 +1570,11 @@ lumpnum_t W_CheckNumForName(const char *name) else { // Update the cache. - lumpnumcacheindex = (lumpnumcacheindex + 1) & (LUMPNUMCACHESIZE - 1); - memset(lumpnumcache[lumpnumcacheindex].lumpname, '\0', 32); - strncpy(lumpnumcache[lumpnumcacheindex].lumpname, name, 8); - lumpnumcache[lumpnumcacheindex].lumpnum = (i<<16)+check; + lumpnum_t lumpnum = (i << 16) + check; - return lumpnumcache[lumpnumcacheindex].lumpnum; + AddLumpToCache(lumpnum, name, false); + + return lumpnum; } } @@ -1495,16 +1592,10 @@ lumpnum_t W_CheckNumForLongName(const char *name) if (!*name) // some doofus gave us an empty string? return LUMPERROR; - // Check the lumpnumcache first. Loop backwards so that we check - // most recent entries first - for (i = lumpnumcacheindex + LUMPNUMCACHESIZE; i > lumpnumcacheindex; i--) - { - if (strcmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name) == 0) - { - lumpnumcacheindex = i & (LUMPNUMCACHESIZE - 1); - return lumpnumcache[lumpnumcacheindex].lumpnum; - } - } + // Check the lumpnumcache first. + lumpnum_t cachenum = CheckLumpInCache(name, true); + if (cachenum != LUMPERROR) + return cachenum; // scan wad files backwards so patch lump files take precedence for (i = numwadfiles - 1; i >= 0; i--) @@ -1517,16 +1608,12 @@ lumpnum_t W_CheckNumForLongName(const char *name) if (check == INT16_MAX) return LUMPERROR; else { - if (strlen(name) < 32) - { - // Update the cache. - lumpnumcacheindex = (lumpnumcacheindex + 1) & (LUMPNUMCACHESIZE - 1); - memset(lumpnumcache[lumpnumcacheindex].lumpname, '\0', 32); - strlcpy(lumpnumcache[lumpnumcacheindex].lumpname, name, 32); - lumpnumcache[lumpnumcacheindex].lumpnum = (i << 16) + check; - } + // Update the cache. + lumpnum_t lumpnum = (i << 16) + check; - return (i << 16) + check; + AddLumpToCache(lumpnum, name, true); + + return lumpnum; } } @@ -1608,6 +1695,166 @@ lumpnum_t W_GetNumForLongName(const char *name) return i; } +// +// Same as W_CheckNumForNamePwad, but handles namespaces. +// +static UINT16 W_CheckNumForPatchNamePwad(const char *name, UINT16 wad, boolean longname) +{ + UINT16 i, start = INT16_MAX, end = INT16_MAX; + static char uname[8 + 1] = { 0 }; + UINT32 hash = 0; + lumpinfo_t *lump_p; + + if (!TestValidLump(wad,0)) + return INT16_MAX; + + if (!longname) + { + strlcpy(uname, name, sizeof uname); + strupr(uname); + hash = quickncasehash(uname, 8); + } + + // SRB2 doesn't have a specific namespace for graphics, which means someone can do weird things + // like placing graphics inside a namespace it doesn't make sense for them to be in, like Sounds/ or SOC/ + // So for now, this checks for lumps OUTSIDE of the flats namespace. + // When this situation changes, change the loops below to check for lumps INSIDE the namespaces to look in. + // TODO: cache namespace lump IDs + if (W_FileHasFolders(wadfiles[wad])) + { + start = W_CheckNumForFolderStartPK3("Flats/", wad, 0); + end = W_CheckNumForFolderEndPK3("Flats/", wad, start); + + // if the start and end is the same, the folder is empty + if (end <= start) + { + start = INT16_MAX; + end = INT16_MAX; + } + } + else + { + start = W_CheckNumForMarkerStartPwad("F_START", wad, 0); + end = W_CheckNumForNamePwad("F_END", wad, start); + if (end != INT16_MAX) + end++; + } + + lump_p = wadfiles[wad]->lumpinfo; + + if (start == INT16_MAX) + start = wadfiles[wad]->numlumps; + + for (i = 0; i < start; i++, lump_p++) + { + if ((!longname && lump_p->hash == hash && !strncmp(lump_p->name, uname, sizeof(uname) - 1)) + || (longname && stricmp(lump_p->longname, name) == 0)) + return i; + } + + if (end != INT16_MAX && start < end) + { + lump_p = wadfiles[wad]->lumpinfo + end; + + for (i = end; i < wadfiles[wad]->numlumps; i++, lump_p++) + { + if ((!longname && lump_p->hash == hash && !strncmp(lump_p->name, uname, sizeof(uname) - 1)) + || (longname && stricmp(lump_p->longname, name) == 0)) + return i; + } + } + + // not found. + return INT16_MAX; +} + +// +// W_CheckNumForPatchNameInternal +// Gets a lump number out of a patch name. Returns LUMPERROR if name not found. +// +static lumpnum_t W_CheckNumForPatchNameInternal(const char *name, boolean longname) +{ + INT32 i; + lumpnum_t check = INT16_MAX; + + if (!*name) // some doofus gave us an empty string? + return LUMPERROR; + + // Check the lumpnumcache first. + lumpnum_t cachenum = CheckLumpInCache(name, longname); + if (cachenum != LUMPERROR) + return cachenum; + + // scan wad files backwards so patch lump files take precedence + for (i = numwadfiles - 1; i >= 0; i--) + { + check = W_CheckNumForPatchNamePwad(name,(UINT16)i,longname); + if (check != INT16_MAX) + break; //found it + } + + if (check == INT16_MAX) return LUMPERROR; + else + { + // Update the cache. + lumpnum_t lumpnum = (i << 16) + check; + + AddLumpToCache(lumpnum, name, longname); + + return lumpnum; + } +} + +// +// W_CheckNumForPatchName +// Wrapper for W_CheckNumForPatchNameInternal(name, false). Returns LUMPERROR if name not found. +// +lumpnum_t W_CheckNumForPatchName(const char *name) +{ + return W_CheckNumForPatchNameInternal(name, false); +} + +// +// Like W_CheckNumForPatchName, but can find entries with long names. +// Wrapper for W_CheckNumForPatchNameInternal(name, true). Returns LUMPERROR if name not found. +// +lumpnum_t W_CheckNumForLongPatchName(const char *name) +{ + return W_CheckNumForPatchNameInternal(name, true); +} + +// +// W_GetNumForPatchName +// +// Calls W_CheckNumForPatchName, but bombs out if not found. +// +lumpnum_t W_GetNumForPatchName(const char *name) +{ + lumpnum_t i; + + i = W_CheckNumForPatchName(name); + + if (i == LUMPERROR) + I_Error("W_CheckNumForPatchName: %s not found!\n", name); + + return i; +} + +// +// Like W_GetNumForPatchName, but can find entries with long names +// +lumpnum_t W_GetNumForLongPatchName(const char *name) +{ + lumpnum_t i; + + i = W_CheckNumForLongPatchName(name); + + if (i == LUMPERROR) + I_Error("W_GetNumForLongPatchName: %s not found!\n", name); + + return i; +} + // // W_CheckNumForNameInBlock // Checks only in blocks from blockstart lump to blockend lump @@ -2252,10 +2499,10 @@ void *W_CachePatchName(const char *name, INT32 tag) { lumpnum_t num; - num = W_CheckNumForName(name); + num = W_CheckNumForPatchName(name); if (num == LUMPERROR) - return W_CachePatchNum(W_GetNumForName("MISSING"), tag); + return W_CachePatchNum(W_GetNumForPatchName("MISSING"), tag); return W_CachePatchNum(num, tag); } @@ -2263,10 +2510,10 @@ void *W_CachePatchLongName(const char *name, INT32 tag) { lumpnum_t num; - num = W_CheckNumForLongName(name); + num = W_CheckNumForLongPatchName(name); if (num == LUMPERROR) - return W_CachePatchNum(W_GetNumForLongName("MISSING"), tag); + return W_CachePatchNum(W_GetNumForLongPatchName("MISSING"), tag); return W_CachePatchNum(num, tag); } #ifndef NOMD5 @@ -2411,7 +2658,8 @@ static lumpchecklist_t folderblacklist[] = { {"Lua/", 4}, {"SOC/", 4}, - {"Sprites/", 8}, + {"Sprites/", 8}, + {"LongSprites/", 12}, {"Textures/", 9}, {"Patches/", 8}, {"Flats/", 6}, @@ -2707,7 +2955,7 @@ virtres_t* vres_GetMap(lumpnum_t lumpnum) UINT8 *wadData = W_CacheLumpNum(lumpnum, PU_LEVEL); filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs); numlumps = ((wadinfo_t *)wadData)->numlumps; - vlumps = Z_Malloc(sizeof(virtlump_t)*numlumps, PU_LEVEL, NULL); + vlumps = Z_Calloc(sizeof(virtlump_t)*numlumps, PU_LEVEL, NULL); // Build the lumps. for (i = 0; i < numlumps; i++) @@ -2731,7 +2979,7 @@ virtres_t* vres_GetMap(lumpnum_t lumpnum) break; numlumps++; - vlumps = Z_Malloc(sizeof(virtlump_t)*numlumps, PU_LEVEL, NULL); + vlumps = Z_Calloc(sizeof(virtlump_t)*numlumps, PU_LEVEL, NULL); for (i = 0; i < numlumps; i++, lumpnum++) { vlumps[i].size = W_LumpLength(lumpnum); diff --git a/src/w_wad.h b/src/w_wad.h index e043e4d62c82f061ce505c4ce6b6a2298d48a4ec..84aafa3a40e2e48f662c723d5a5854138806b5b0 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2023 by Sonic Team Junior. +// Copyright (C) 1999-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -180,6 +180,8 @@ UINT16 W_CheckNumForMarkerStartPwad(const char *name, UINT16 wad, UINT16 startlu UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump); UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlump); UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump); +char *W_GetLumpFolderPathPK3(UINT16 wad, UINT16 lump); +char *W_GetLumpFolderNamePK3(UINT16 wad, UINT16 lump); void W_GetFolderLumpsPwad(const char *name, UINT16 wad, UINT32 **list, UINT16 *list_capacity, UINT16 *numlumps); void W_GetFolderLumps(const char *name, UINT32 **list, UINT16 *list_capacity, UINT16 *numlumps); @@ -191,6 +193,12 @@ lumpnum_t W_CheckNumForName(const char *name); lumpnum_t W_CheckNumForLongName(const char *name); lumpnum_t W_GetNumForName(const char *name); // like W_CheckNumForName but I_Error on LUMPERROR lumpnum_t W_GetNumForLongName(const char *name); + +lumpnum_t W_CheckNumForPatchName(const char *name); +lumpnum_t W_CheckNumForLongPatchName(const char *name); +lumpnum_t W_GetNumForPatchName(const char *name); // like W_CheckNumForPatchName but I_Error on LUMPERROR +lumpnum_t W_GetNumForLongPatchName(const char *name); + lumpnum_t W_CheckNumForNameInBlock(const char *name, const char *blockstart, const char *blockend); UINT8 W_LumpExists(const char *name); // Lua uses this. diff --git a/src/win32/Srb2win.rc b/src/win32/Srb2win.rc index 46114f8717cc0a7396a7355084c25a2e704ac075..6fba9f9a8877e65fb99c91c2e24022926857beba 100644 --- a/src/win32/Srb2win.rc +++ b/src/win32/Srb2win.rc @@ -98,7 +98,7 @@ BEGIN VALUE "FileDescription", "Sonic Robo Blast 2\0" VALUE "FileVersion", VERSIONSTRING_RC VALUE "InternalName", "srb2\0" - VALUE "LegalCopyright", "Copyright 1998-2023 by Sonic Team Junior\0" + VALUE "LegalCopyright", "Copyright 1998-2025 by Sonic Team Junior\0" VALUE "LegalTrademarks", "Sonic the Hedgehog and related characters are trademarks of Sega.\0" VALUE "OriginalFilename", "srb2win.exe\0" VALUE "PrivateBuild", "\0" diff --git a/src/y_inter.c b/src/y_inter.c index 1f008eaf0363bb444b97fc24bc3e5f7872af605d..d7e644567eb14030e1bbb569434e1db460d8b56c 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2004-2023 by Sonic Team Junior. +// Copyright (C) 2004-2024 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -109,6 +109,7 @@ typedef union UINT16 *color[MAXPLAYERS]; // Winner's color # boolean spectator[MAXPLAYERS]; // Spectator list UINT8 *character[MAXPLAYERS]; // Winner's character # + INT32 ctfteam[MAXPLAYERS]; // Winner's ctfteam # INT32 num[MAXPLAYERS]; // Winner's player # char *name[MAXPLAYERS]; // Winner's name patch_t *result; // RESULT @@ -579,9 +580,9 @@ void Y_IntermissionDrawer(void) { if (LUA_HudEnabled(hud_intermissiontitletext)) { - const char *ringtext = "\x82" "get 50 rings then"; - const char *tut1text = "\x82" "press " "\x80" "shield"; - const char *tut2text = "\x82" "to " "\x80" "transform"; + const char *ringtext = "\x82" "50 rings, no shield"; + const char *tut1text = "\x82" "press " "\x80" "spin"; + const char *tut2text = "\x82" "mid-" "\x80" "jump"; ttheight = 8; V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1); ttheight += V_LevelNameHeight(data.spec.passed3) + 2; @@ -849,7 +850,7 @@ void Y_IntermissionDrawer(void) { UINT8 *colormap = R_GetTranslationColormap(*data.match.character[i], *data.match.color[i], GTC_CACHE); - if (*data.match.color[i] == SKINCOLOR_RED) //red + if (data.match.ctfteam[i] == 1) //red { if (redplayers++ > 9) continue; @@ -857,7 +858,7 @@ void Y_IntermissionDrawer(void) y = (redplayers * 16) + 32; V_DrawCenteredString(x+6, y, 0, va("%d", redplayers)); } - else if (*data.match.color[i] == SKINCOLOR_BLUE) //blue + else if (data.match.ctfteam[i] == 2) //blue { if (blueplayers++ > 9) continue; @@ -1129,7 +1130,7 @@ void Y_Ticker(void) else if (mapheaderinfo[gamemap-1]->musintername[0] && S_MusicExists(mapheaderinfo[gamemap-1]->musintername, !midi_disabled, !digital_disabled)) S_ChangeMusicInternal(mapheaderinfo[gamemap-1]->musintername, false); // don't loop it else - S_ChangeMusicInternal("_clear", false); // don't loop it + S_ChangeMusicInternal(stagefailed ? "CHFAIL" : "CHPASS", false); // don't loop it tallydonetic = -1; } @@ -1622,6 +1623,7 @@ static void Y_CalculateMatchWinners(void) boolean completed[MAXPLAYERS]; // Initialize variables + memset(data.match.ctfteam, 0, sizeof (data.match.ctfteam)); memset(data.match.scores, 0, sizeof (data.match.scores)); memset(data.match.color, 0, sizeof (data.match.color)); memset(data.match.character, 0, sizeof (data.match.character)); @@ -1642,8 +1644,15 @@ static void Y_CalculateMatchWinners(void) if (players[i].score >= data.match.scores[data.match.numplayers] && completed[i] == false) { + data.match.ctfteam[data.match.numplayers] = players[i].ctfteam; data.match.scores[data.match.numplayers] = players[i].score; data.match.color[data.match.numplayers] = &players[i].skincolor; + if (data.match.ctfteam[data.match.numplayers] == 1) // red team + data.match.color[data.match.numplayers] = &skincolor_redteam; + + if (data.match.ctfteam[data.match.numplayers] == 2) // blue team + data.match.color[data.match.numplayers] = &skincolor_blueteam; + data.match.character[data.match.numplayers] = &players[i].skin; data.match.name[data.match.numplayers] = player_names[i]; data.match.spectator[data.match.numplayers] = players[i].spectator; @@ -2043,7 +2052,7 @@ static void Y_AwardCoopBonuses(void) y_bonus_t localbonuses[4]; // set score/total first - data.coop.total = players[consoleplayer].recordscore; + data.coop.total = (players[consoleplayer].pflags & PF_FINISHED) ? players[consoleplayer].recordscore : 0; data.coop.score = players[consoleplayer].score; data.coop.gotperfbonus = -1; memset(data.coop.bonuses, 0, sizeof(data.coop.bonuses)); @@ -2060,7 +2069,12 @@ static void Y_AwardCoopBonuses(void) for (j = 0; j < 4; ++j) // Set bonuses { - (bonuses_list[bonusnum][j])(&players[i], &localbonuses[j]); + //Set the bonus, but only if we actually finished + if (players[i].pflags & PF_FINISHED) + (bonuses_list[bonusnum][j])(&players[i], &localbonuses[j]); + else + Y_SetNullBonus(&players[i], &localbonuses[j]); + players[i].score += localbonuses[j].points; if (players[i].score > MAXSCORE) players[i].score = MAXSCORE; diff --git a/src/z_zone.c b/src/z_zone.c index 5750f8ae016becd9c9548b690b0e7fd5b32ec7cb..0852fabaeac03f3751d33063cb14f63105678537 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -671,6 +671,7 @@ static void Command_Memfree_f(void) CONS_Printf(M_GetText("Cached textures : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRCACHE)>>10)); CONS_Printf(M_GetText("Texture colormaps : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHCOLMIPMAP)>>10)); CONS_Printf(M_GetText("Model textures : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRMODELTEXTURE)>>10)); + CONS_Printf(M_GetText("Light table textures : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRLIGHTTABLEDATA)>>10)); CONS_Printf(M_GetText("Plane polygons : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPLANE)>>10)); CONS_Printf(M_GetText("All GPU textures : %7d KB\n"), HWR_GetTextureUsed()>>10); } diff --git a/src/z_zone.h b/src/z_zone.h index ce7af4a159555e3a6c2be83e8d0eadcf8a7a69eb..56c540c3bb31a4a84e5f2403519455f3830583ee 100644 --- a/src/z_zone.h +++ b/src/z_zone.h @@ -55,6 +55,7 @@ enum PU_HWRPATCHINFO = 21, // Hardware GLPatch_t struct for OpenGL texture cache PU_HWRPATCHCOLMIPMAP = 22, // Hardware GLMipmap_t struct colormap variation of patch PU_HWRMODELTEXTURE = 23, // Hardware model texture + PU_HWRLIGHTTABLEDATA = 24, // Hardware light table data PU_HWRCACHE = 48, // static until unlocked PU_CACHE = 49, // static until unlocked diff --git a/thirdparty/00-SDL-Mixer-X-2.6.0-DISABLE_INSTALL.patch b/thirdparty/00-SDL-Mixer-X-2.6.0-DISABLE_INSTALL.patch new file mode 100644 index 0000000000000000000000000000000000000000..0e7f55f1b282300bbdb6d21a8abd67373fd45828 --- /dev/null +++ b/thirdparty/00-SDL-Mixer-X-2.6.0-DISABLE_INSTALL.patch @@ -0,0 +1,26 @@ +--- a/CMakeLists.txt 2023-11-22 22:42:53.000000000 -0500 ++++ b/CMakeLists.txt 2024-02-15 18:46:57.852076200 -0500 +@@ -45,6 +45,7 @@ + + option(SDL_MIXER_X_STATIC "Build static library of SDL Mixer X" ${SDL_MIXER_X_STATIC_ENABLED_BY_DEFAULT}) + option(SDL_MIXER_X_SHARED "Build shared library of SDL Mixer X" ${SDL_MIXER_X_SHARED_ENABLED_BY_DEFAULT}) ++ option(SDL_MIXER_X_DISABLE_INSTALL "Disable install of SDL Mixer X" OFF) + else() + set(SDL_MIXER_X_STATIC ON) + set(SDL_MIXER_X_SHARED OFF) +@@ -475,6 +476,7 @@ + add_subdirectory(examples) + endif() + ++if(NOT SDL_MIXER_X_DISABLE_INSTALL) + if(SDL_MIXER_X_STATIC AND NOT BUILD_AS_VB6_BINDING) + install(TARGETS SDL2_mixer_ext_Static + EXPORT SDL2MixerExtStaticTargets +@@ -500,6 +502,7 @@ + NAMESPACE SDL2_mixer_ext:: + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/SDL2_mixer_ext") + endif() ++endif() + + + if(BUILD_AS_VB6_BINDING) diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index f33b3bf3f836b86b98fda8e78f73ec5be19758d8..5114cbe2c81432173409cce5a113ea9305b5b23b 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -1,21 +1,2 @@ -macro(export) -endmacro() -if(SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES) - set(SRB2_INTERNAL_LIBRARY_TYPE SHARED) - set(NOT_SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES OFF) -else() - set(SRB2_INTERNAL_LIBRARY_TYPE STATIC) - set(NOT_SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES ON) -endif() - -if(NOT "${SRB2_CONFIG_SYSTEM_LIBRARIES}") - include("cpm-sdl2.cmake") - include("cpm-sdl2-mixer.cmake") - include("cpm-zlib.cmake") - include("cpm-png.cmake") - include("cpm-curl.cmake") - include("cpm-openmpt.cmake") -endif() - -include("cpm-libgme.cmake") +include("Ccache.cmake") diff --git a/thirdparty/Ccache.cmake b/thirdparty/Ccache.cmake new file mode 100644 index 0000000000000000000000000000000000000000..6ca0d9fa0615d8cf091992ed84bec7b4fef09144 --- /dev/null +++ b/thirdparty/Ccache.cmake @@ -0,0 +1,15 @@ +# Enable CCache +# (Set USE_CCACHE=ON to use, CCACHE_OPTIONS for options) +if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL Windows) + option(USE_CCACHE "Enable ccache support" OFF) + + if(USE_CCACHE) + find_program(CCACHE_TOOL_PATH ccache) + if(CCACHE_TOOL_PATH) + set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_TOOL_PATH} CACHE STRING "" FORCE) + set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_TOOL_PATH} CACHE STRING "" FORCE) + else() + message(WARNING "USE_CCACHE was set but ccache is not found (set CCACHE_TOOL_PATH)") + endif() + endif() +endif() \ No newline at end of file diff --git a/thirdparty/cpm-libgme.cmake b/thirdparty/cpm-libgme.cmake deleted file mode 100644 index f15bc3b31cb23ed7663ed950c14c1d6a0dc36567..0000000000000000000000000000000000000000 --- a/thirdparty/cpm-libgme.cmake +++ /dev/null @@ -1,16 +0,0 @@ -CPMAddPackage( - NAME libgme - VERSION 0.6.3 - URL "https://bitbucket.org/mpyne/game-music-emu/get/e76bdc0cb916e79aa540290e6edd0c445879d3ba.zip" - EXCLUDE_FROM_ALL ON - OPTIONS - "BUILD_SHARED_LIBS ${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}" - "ENABLE_UBSAN OFF" - "GME_YM2612_EMU MAME" -) - -if(libgme_ADDED) - target_compile_features(gme PRIVATE cxx_std_11) - # libgme's CMakeLists.txt already links this - #target_link_libraries(gme PRIVATE ZLIB::ZLIB) -endif() diff --git a/thirdparty/cpm-png.cmake b/thirdparty/cpm-png.cmake deleted file mode 100644 index f16ac037b0cc9c077f3ef315b67b430e68cf9b40..0000000000000000000000000000000000000000 --- a/thirdparty/cpm-png.cmake +++ /dev/null @@ -1,69 +0,0 @@ -CPMAddPackage( - NAME png - VERSION 1.6.38 - URL "https://github.com/glennrp/libpng/archive/refs/tags/v1.6.38.zip" - # png cmake build is broken on msys/mingw32 - DOWNLOAD_ONLY YES -) - -if(png_ADDED) - # Since png's cmake build is broken, we're going to create a target manually - set( - PNG_SOURCES - png.h - pngconf.h - pngpriv.h - pngdebug.h - pnginfo.h - pngstruct.h - png.c - pngerror.c - pngget.c - pngmem.c - pngpread.c - pngread.c - pngrio.c - pngrtran.c - pngrutil.c - pngset.c - pngtrans.c - pngwio.c - pngwrite.c - pngwtran.c - pngwutil.c - ) - list(TRANSFORM PNG_SOURCES PREPEND "${png_SOURCE_DIR}/") - - add_custom_command( - OUTPUT "${png_BINARY_DIR}/include/png.h" "${png_BINARY_DIR}/include/pngconf.h" - COMMAND ${CMAKE_COMMAND} -E copy "${png_SOURCE_DIR}/png.h" "${png_SOURCE_DIR}/pngconf.h" "${png_BINARY_DIR}/include" - DEPENDS "${png_SOURCE_DIR}/png.h" "${png_SOURCE_DIR}/pngconf.h" - VERBATIM - ) - add_custom_command( - OUTPUT "${png_BINARY_DIR}/include/pnglibconf.h" - COMMAND ${CMAKE_COMMAND} -E copy "${png_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt" "${png_BINARY_DIR}/include/pnglibconf.h" - DEPENDS "${png_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt" - VERBATIM - ) - list( - APPEND PNG_SOURCES - "${png_BINARY_DIR}/include/png.h" - "${png_BINARY_DIR}/include/pngconf.h" - "${png_BINARY_DIR}/include/pnglibconf.h" - ) - add_library(png "${SRB2_INTERNAL_LIBRARY_TYPE}" ${PNG_SOURCES}) - - # Disable ARM NEON since having it automatic breaks libpng external build on clang for some reason - target_compile_definitions(png PRIVATE -DPNG_ARM_NEON_OPT=0) - - # The png includes need to be available to consumers - target_include_directories(png PUBLIC "${png_BINARY_DIR}/include") - - # ... and these also need to be present only for png build - target_include_directories(png PRIVATE "${ZLIB_SOURCE_DIR}") - target_include_directories(png PRIVATE "${ZLIB_BINARY_DIR}") - target_include_directories(png PRIVATE "${png_BINARY_DIR}") - target_link_libraries(png PRIVATE ZLIB::ZLIB) - add_library(PNG::PNG ALIAS png) -endif() diff --git a/thirdparty/cpm-sdl2-mixer.cmake b/thirdparty/cpm-sdl2-mixer.cmake deleted file mode 100644 index b7dfeae0d3eab254651f0c5e6e69e7af0626012e..0000000000000000000000000000000000000000 --- a/thirdparty/cpm-sdl2-mixer.cmake +++ /dev/null @@ -1,22 +0,0 @@ -CPMAddPackage( - NAME SDL2_mixer - VERSION 2.6.2 - URL "https://github.com/libsdl-org/SDL_mixer/archive/refs/tags/release-2.6.2.zip" - EXCLUDE_FROM_ALL ON - OPTIONS - "BUILD_SHARED_LIBS ${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}" - "SDL2MIXER_INSTALL OFF" - "SDL2MIXER_DEPS_SHARED OFF" - "SDL2MIXER_SAMPLES OFF" - "SDL2MIXER_VENDORED ON" - "SDL2MIXER_FLAC ON" - "SDL2MIXER_FLAC_LIBFLAC OFF" - "SDL2MIXER_FLAC_DRFLAC ON" - "SDL2MIXER_MOD OFF" - "SDL2MIXER_MP3 ON" - "SDL2MIXER_MP3_DRMP3 ON" - "SDL2MIXER_MIDI ON" - "SDL2MIXER_OPUS OFF" - "SDL2MIXER_VORBIS STB" - "SDL2MIXER_WAVE ON" -) diff --git a/thirdparty/cpm-sdl2.cmake b/thirdparty/cpm-sdl2.cmake deleted file mode 100644 index 90e5bd0fe3e081cfd320fcf06ff23e9477492793..0000000000000000000000000000000000000000 --- a/thirdparty/cpm-sdl2.cmake +++ /dev/null @@ -1,28 +0,0 @@ -set( - internal_sdl2_options - - "BUILD_SHARED_LIBS ${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}" - "SDL_SHARED ${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}" - "SDL_STATIC ${NOT_SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}" - "SDL_TEST OFF" - "SDL2_DISABLE_INSTALL ON" -) - -if(${CMAKE_SYSTEM} MATCHES Windows) - list(APPEND internal_sdl2_options "SDL2_DISABLE_SDL2MAIN OFF") -endif() -if(${CMAKE_SYSTEM} MATCHES Darwin) - list(APPEND internal_sdl2_options "SDL2_DISABLE_SDL2MAIN OFF") -endif() -if(${CMAKE_SYSTEM} MATCHES Linux) - list(APPEND internal_sdl2_options "SDL2_DISABLE_SDL2MAIN ON") -endif() - -CPMAddPackage( - NAME SDL2 - VERSION 2.30.0 - GITHUB_REPOSITORY "libsdl-org/SDL" - GIT_TAG release-2.30.0 - EXCLUDE_FROM_ALL ON - OPTIONS ${internal_sdl2_options} -) diff --git a/thirdparty/cpm-zlib.cmake b/thirdparty/cpm-zlib.cmake deleted file mode 100644 index f0a2c33aee8c483d82b4ab26e1d0be2143fd9e16..0000000000000000000000000000000000000000 --- a/thirdparty/cpm-zlib.cmake +++ /dev/null @@ -1,18 +0,0 @@ -CPMAddPackage( - NAME zlib - VERSION 1.3.1 - GITHUB_REPOSITORY "madler/zlib" - GIT_TAG v1.3.1 - EXCLUDE_FROM_ALL - OPTIONS - "ZLIB_BUILD_EXAMPLES OFF" -) - -if(zlib_ADDED) - if(SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES) - add_library(ZLIB::ZLIB ALIAS zlib) - endif() - if(NOT_SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES) - add_library(ZLIB::ZLIB ALIAS zlibstatic) - endif() -endif() diff --git a/thirdparty/cpm-curl.cmake b/thirdparty/curl.cmake similarity index 55% rename from thirdparty/cpm-curl.cmake rename to thirdparty/curl.cmake index 3d8c6e61d46dee6f06f4e6d69beb09d1605f6584..7b6c3a299f951139fe18e0c25d18074d0deae300 100644 --- a/thirdparty/cpm-curl.cmake +++ b/thirdparty/curl.cmake @@ -1,8 +1,16 @@ +if(TARGET CURL::libcurl) + return() +endif() + +message(STATUS "Third-party: creating target 'CURL::libcurl'") + +set(CURL_ENABLE_EXPORT_TARGET OFF CACHE BOOL "" FORCE) + set( internal_curl_options "BUILD_CURL_EXE OFF" - "BUILD_SHARED_LIBS ${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}" + "BUILD_SHARED_LIBS OFF" "CURL_DISABLE_TESTS ON" "HTTP_ONLY ON" "CURL_DISABLE_CRYPTO_AUTH ON" @@ -26,10 +34,24 @@ if(${CMAKE_SYSTEM} MATCHES Linux) list(APPEND internal_curl_options "CURL_USE_OPENSSL ON") endif() -CPMAddPackage( - NAME curl - VERSION 7.86.0 - URL "https://github.com/curl/curl/archive/refs/tags/curl-7_86_0.zip" - EXCLUDE_FROM_ALL ON - OPTIONS ${internal_curl_options} -) +include(FetchContent) + +if (CURL_USE_THIRDPARTY) + FetchContent_Declare( + curl + VERSION 7.88.1 + GITHUB_REPOSITORY "curl/curl" + GIT_TAG curl-7_88_1 + EXCLUDE_FROM_ALL ON + OPTIONS ${internal_curl_options} + ) +else() + FetchContent_Declare( + curl + SOURCE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/curl/" + EXCLUDE_FROM_ALL ON + OPTIONS ${internal_curl_options} + ) +endif() + +FetchContent_MakeAvailable(curl) diff --git a/thirdparty/libapng.cmake b/thirdparty/libapng.cmake new file mode 100644 index 0000000000000000000000000000000000000000..f4bc50ff1d301b58bf91c44bfe40986c5c987654 --- /dev/null +++ b/thirdparty/libapng.cmake @@ -0,0 +1,38 @@ +if(TARGET libapng_static) + return() +endif() + +message(STATUS "Third-party: creating target 'libapng_static'") + +set(PNG_SHARED OFF CACHE BOOL "" FORCE) +set(PNG_BUILD_ZLIB ON CACHE BOOL "" FORCE) + +include(FetchContent) + + FetchContent_Declare( + libapng-local + SOURCE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/libapng/" + EXCLUDE_FROM_ALL ON + DOWNLOAD_ONLY YES + OPTION + "PNG_SHARED OFF" + "PNG_EXECUTABLES OFF" + "PNG_TESTS OFF" + "PNG_BUILD_ZLIB ON" + ) + +FetchContent_MakeAvailable(libapng-local) + +#add_custom_command( +#OUTPUT ${libapng-local_BINARY_DIR}/CMakeLists.txt +#COMMAND ${CMAKE_COMMAND} +# -Din_file:FILEPATH=${libapng-locall_SOURCE_DIR}/CMakeLists.txt +# -Dpatch_file:FILEPATH=${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/00-libapng-ZLIB.patch +# -Dout_file:FILEPATH=${libapng-local_BINARY_DIR}/CMakeLists.txt +# -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/PatchFile.cmake +#DEPENDS ${libapng-local_SOURCE_DIR}/CMakeLists.txt +#) + +set(libapng_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/libapng" "${libapng_BINARY_DIR}" CACHE PATH "" FORCE) + +set(libapng_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/libapng/png.h" "${CMAKE_CURRENT_SOURCE_DIR}/libapng/pngconf.h" CACHE PATH "" FORCE) diff --git a/thirdparty/cpm-openmpt.cmake b/thirdparty/libopenmpt.cmake similarity index 82% rename from thirdparty/cpm-openmpt.cmake rename to thirdparty/libopenmpt.cmake index 01f7ff75f64d915799e432f2923a2c7e8c344466..256b4c406b99b73bf96e9488316b1093515f65c9 100644 --- a/thirdparty/cpm-openmpt.cmake +++ b/thirdparty/libopenmpt.cmake @@ -1,13 +1,33 @@ -CPMAddPackage( - NAME openmpt - VERSION 0.4.30 - URL "https://github.com/OpenMPT/openmpt/archive/refs/tags/libopenmpt-0.4.30.zip" - DOWNLOAD_ONLY ON -) +if(TARGET libopenmpt) + #return() +endif() + +message(STATUS "Third-party: creating target 'libopenmpt'") + + +include(FetchContent) + +if (libopenmpt_USE_THIRDPARTY) + FetchContent_Declare( + libopenmpt-local + GITHUB_REPOSITORY openmpt + GIT_TAG libopenmpt-0.4.38 + version 0.4.38 + EXCLUDE_FROM_ALL ON + ) +else() + FetchContent_Declare( + libopenmpt-local + SOURCE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/libopenmpt/" + EXCLUDE_FROM_ALL ON + ) +endif() + +FetchContent_MakeAvailable(libopenmpt) -if(openmpt_ADDED) +if(aaaa-libopenmpt-local_ADDED) set( - openmpt_SOURCES + libopenmpt-local_SOURCES # minimp3 # -DMPT_WITH_MINIMP3 @@ -264,26 +284,26 @@ if(openmpt_ADDED) libopenmpt/libopenmpt_impl.cpp libopenmpt/libopenmpt_ext_impl.cpp ) - list(TRANSFORM openmpt_SOURCES PREPEND "${openmpt_SOURCE_DIR}/") + list(TRANSFORM libopenmpt-local_SOURCES PREPEND "${libopenmpt-local_SOURCE_DIR}/") # -DLIBOPENMPT_BUILD configure_file("openmpt_svn_version.h" "svn_version.h") - add_library(openmpt "${SRB2_INTERNAL_LIBRARY_TYPE}" ${openmpt_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/svn_version.h) + add_library(libopenmpt STATIC ${libopenmpt-local_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/svn_version.h) if("${CMAKE_C_COMPILER_ID}" STREQUAL GNU OR "${CMAKE_C_COMPILER_ID}" STREQUAL Clang OR "${CMAKE_C_COMPILER_ID}" STREQUAL AppleClang) - target_compile_options(openmpt PRIVATE "-g0") + target_compile_options(libopenmpt PRIVATE "-g0") endif() if("${CMAKE_SYSTEM_NAME}" STREQUAL Windows AND "${CMAKE_C_COMPILER_ID}" STREQUAL MSVC) - target_link_libraries(openmpt PRIVATE Rpcrt4) + target_link_libraries(libopenmpt PRIVATE Rpcrt4) endif() - target_compile_features(openmpt PRIVATE cxx_std_11) - target_compile_definitions(openmpt PRIVATE -DLIBOPENMPT_BUILD) + target_compile_features(libopenmpt PRIVATE cxx_std_11) + target_compile_definitions(libopenmpt PRIVATE -DLIBOPENMPT_BUILD) - target_include_directories(openmpt PRIVATE "${openmpt_SOURCE_DIR}/common") - target_include_directories(openmpt PRIVATE "${openmpt_SOURCE_DIR}/src") - target_include_directories(openmpt PRIVATE "${openmpt_SOURCE_DIR}/include") - target_include_directories(openmpt PRIVATE "${openmpt_SOURCE_DIR}") - target_include_directories(openmpt PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") + target_include_directories(libopenmpt PRIVATE "${libopenmpt-local_SOURCE_DIR}/common") + target_include_directories(libopenmpt PRIVATE "${libopenmpt-local_SOURCE_DIR}/src") + target_include_directories(libopenmpt PRIVATE "${libopenmpt-local_SOURCE_DIR}/include") + target_include_directories(libopenmpt PRIVATE "${libopenmpt-local_SOURCE_DIR}") + target_include_directories(libopenmpt PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") # I wish this wasn't necessary, but it is - target_include_directories(openmpt PUBLIC "${openmpt_SOURCE_DIR}") + target_include_directories(libopenmpt PUBLIC "${libopenmpt-local_SOURCE_DIR}") endif() diff --git a/thirdparty/libpng-1.6.40-apng.patch b/thirdparty/libpng-1.6.40-apng.patch new file mode 100644 index 0000000000000000000000000000000000000000..c5b870004ad2f7a82df6bbbc061c24cc8f5a5393 --- /dev/null +++ b/thirdparty/libpng-1.6.40-apng.patch @@ -0,0 +1,1728 @@ +diff -Naru libpng-1.6.40.org/png.h libpng-1.6.40/png.h +--- libpng-1.6.40.org/png.h 2023-09-10 11:12:23.044481879 +0900 ++++ libpng-1.6.40/png.h 2023-09-10 11:08:58.964075833 +0900 +@@ -330,6 +330,10 @@ + # include "pnglibconf.h" + #endif + ++#define PNG_APNG_SUPPORTED ++#define PNG_READ_APNG_SUPPORTED ++#define PNG_WRITE_APNG_SUPPORTED ++ + #ifndef PNG_VERSION_INFO_ONLY + /* Machine specific configuration. */ + # include "pngconf.h" +@@ -425,6 +429,17 @@ + * See pngconf.h for base types that vary by machine/system + */ + ++#ifdef PNG_APNG_SUPPORTED ++/* dispose_op flags from inside fcTL */ ++#define PNG_DISPOSE_OP_NONE 0x00U ++#define PNG_DISPOSE_OP_BACKGROUND 0x01U ++#define PNG_DISPOSE_OP_PREVIOUS 0x02U ++ ++/* blend_op flags from inside fcTL */ ++#define PNG_BLEND_OP_SOURCE 0x00U ++#define PNG_BLEND_OP_OVER 0x01U ++#endif /* PNG_APNG_SUPPORTED */ ++ + /* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +@@ -746,6 +761,10 @@ + #define PNG_INFO_sCAL 0x4000U /* ESR, 1.0.6 */ + #define PNG_INFO_IDAT 0x8000U /* ESR, 1.0.6 */ + #define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */ ++#ifdef PNG_APNG_SUPPORTED ++#define PNG_INFO_acTL 0x20000U ++#define PNG_INFO_fcTL 0x40000U ++#endif + + /* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using +@@ -783,6 +802,10 @@ + #ifdef PNG_PROGRESSIVE_READ_SUPPORTED + typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); + typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); ++#ifdef PNG_APNG_SUPPORTED ++typedef PNG_CALLBACK(void, *png_progressive_frame_ptr, (png_structp, ++ png_uint_32)); ++#endif + + /* The following callback receives png_uint_32 row_number, int pass for the + * png_bytep data of the row. When transforming an interlaced image the +@@ -3226,6 +3249,74 @@ + /******************************************************************************* + * END OF HARDWARE AND SOFTWARE OPTIONS + ******************************************************************************/ ++#ifdef PNG_APNG_SUPPORTED ++PNG_EXPORT(250, png_uint_32, png_get_acTL, (png_structp png_ptr, ++ png_infop info_ptr, png_uint_32 *num_frames, png_uint_32 *num_plays)); ++ ++PNG_EXPORT(251, png_uint_32, png_set_acTL, (png_structp png_ptr, ++ png_infop info_ptr, png_uint_32 num_frames, png_uint_32 num_plays)); ++ ++PNG_EXPORT(252, png_uint_32, png_get_num_frames, (png_structp png_ptr, ++ png_infop info_ptr)); ++ ++PNG_EXPORT(253, png_uint_32, png_get_num_plays, (png_structp png_ptr, ++ png_infop info_ptr)); ++ ++PNG_EXPORT(254, png_uint_32, png_get_next_frame_fcTL, ++ (png_structp png_ptr, png_infop info_ptr, png_uint_32 *width, ++ png_uint_32 *height, png_uint_32 *x_offset, png_uint_32 *y_offset, ++ png_uint_16 *delay_num, png_uint_16 *delay_den, png_byte *dispose_op, ++ png_byte *blend_op)); ++ ++PNG_EXPORT(255, png_uint_32, png_set_next_frame_fcTL, ++ (png_structp png_ptr, png_infop info_ptr, png_uint_32 width, ++ png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset, ++ png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, ++ png_byte blend_op)); ++ ++PNG_EXPORT(256, png_uint_32, png_get_next_frame_width, ++ (png_structp png_ptr, png_infop info_ptr)); ++PNG_EXPORT(257, png_uint_32, png_get_next_frame_height, ++ (png_structp png_ptr, png_infop info_ptr)); ++PNG_EXPORT(258, png_uint_32, png_get_next_frame_x_offset, ++ (png_structp png_ptr, png_infop info_ptr)); ++PNG_EXPORT(259, png_uint_32, png_get_next_frame_y_offset, ++ (png_structp png_ptr, png_infop info_ptr)); ++PNG_EXPORT(260, png_uint_16, png_get_next_frame_delay_num, ++ (png_structp png_ptr, png_infop info_ptr)); ++PNG_EXPORT(261, png_uint_16, png_get_next_frame_delay_den, ++ (png_structp png_ptr, png_infop info_ptr)); ++PNG_EXPORT(262, png_byte, png_get_next_frame_dispose_op, ++ (png_structp png_ptr, png_infop info_ptr)); ++PNG_EXPORT(263, png_byte, png_get_next_frame_blend_op, ++ (png_structp png_ptr, png_infop info_ptr)); ++PNG_EXPORT(264, png_byte, png_get_first_frame_is_hidden, ++ (png_structp png_ptr, png_infop info_ptr)); ++PNG_EXPORT(265, png_uint_32, png_set_first_frame_is_hidden, ++ (png_structp png_ptr, png_infop info_ptr, png_byte is_hidden)); ++ ++#ifdef PNG_READ_APNG_SUPPORTED ++PNG_EXPORT(266, void, png_read_frame_head, (png_structp png_ptr, ++ png_infop info_ptr)); ++#ifdef PNG_PROGRESSIVE_READ_SUPPORTED ++PNG_EXPORT(267, void, png_set_progressive_frame_fn, (png_structp png_ptr, ++ png_progressive_frame_ptr frame_info_fn, ++ png_progressive_frame_ptr frame_end_fn)); ++#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ ++#endif /* PNG_READ_APNG_SUPPORTED */ ++ ++#ifdef PNG_WRITE_APNG_SUPPORTED ++PNG_EXPORT(268, void, png_write_frame_head, (png_structp png_ptr, ++ png_infop info_ptr, png_bytepp row_pointers, ++ png_uint_32 width, png_uint_32 height, ++ png_uint_32 x_offset, png_uint_32 y_offset, ++ png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, ++ png_byte blend_op)); ++ ++PNG_EXPORT(269, void, png_write_frame_tail, (png_structp png_ptr, ++ png_infop info_ptr)); ++#endif /* PNG_WRITE_APNG_SUPPORTED */ ++#endif /* PNG_APNG_SUPPORTED */ + + /* Maintainer: Put new public prototypes here ^, in libpng.3, in project + * defs, and in scripts/symbols.def. +@@ -3235,7 +3326,11 @@ + * one to use is one more than this.) + */ + #ifdef PNG_EXPORT_LAST_ORDINAL ++#ifdef PNG_APNG_SUPPORTED ++ PNG_EXPORT_LAST_ORDINAL(269); ++#else + PNG_EXPORT_LAST_ORDINAL(249); ++#endif /* PNG_APNG_SUPPORTED */ + #endif + + #ifdef __cplusplus +diff -Naru libpng-1.6.40.org/pngget.c libpng-1.6.40/pngget.c +--- libpng-1.6.40.org/pngget.c 2023-09-10 11:09:32.954139030 +0900 ++++ libpng-1.6.40/pngget.c 2023-09-10 11:08:58.922075757 +0900 +@@ -1257,4 +1257,166 @@ + # endif + #endif + ++#ifdef PNG_APNG_SUPPORTED ++png_uint_32 PNGAPI ++png_get_acTL(png_structp png_ptr, png_infop info_ptr, ++ png_uint_32 *num_frames, png_uint_32 *num_plays) ++{ ++ png_debug1(1, "in %s retrieval function", "acTL"); ++ ++ if (png_ptr != NULL && info_ptr != NULL && ++ (info_ptr->valid & PNG_INFO_acTL) && ++ num_frames != NULL && num_plays != NULL) ++ { ++ *num_frames = info_ptr->num_frames; ++ *num_plays = info_ptr->num_plays; ++ return (1); ++ } ++ ++ return (0); ++} ++ ++png_uint_32 PNGAPI ++png_get_num_frames(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_get_num_frames()"); ++ ++ if (png_ptr != NULL && info_ptr != NULL) ++ return (info_ptr->num_frames); ++ return (0); ++} ++ ++png_uint_32 PNGAPI ++png_get_num_plays(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_get_num_plays()"); ++ ++ if (png_ptr != NULL && info_ptr != NULL) ++ return (info_ptr->num_plays); ++ return (0); ++} ++ ++png_uint_32 PNGAPI ++png_get_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr, ++ png_uint_32 *width, png_uint_32 *height, ++ png_uint_32 *x_offset, png_uint_32 *y_offset, ++ png_uint_16 *delay_num, png_uint_16 *delay_den, ++ png_byte *dispose_op, png_byte *blend_op) ++{ ++ png_debug1(1, "in %s retrieval function", "fcTL"); ++ ++ if (png_ptr != NULL && info_ptr != NULL && ++ (info_ptr->valid & PNG_INFO_fcTL) && ++ width != NULL && height != NULL && ++ x_offset != NULL && y_offset != NULL && ++ delay_num != NULL && delay_den != NULL && ++ dispose_op != NULL && blend_op != NULL) ++ { ++ *width = info_ptr->next_frame_width; ++ *height = info_ptr->next_frame_height; ++ *x_offset = info_ptr->next_frame_x_offset; ++ *y_offset = info_ptr->next_frame_y_offset; ++ *delay_num = info_ptr->next_frame_delay_num; ++ *delay_den = info_ptr->next_frame_delay_den; ++ *dispose_op = info_ptr->next_frame_dispose_op; ++ *blend_op = info_ptr->next_frame_blend_op; ++ return (1); ++ } ++ ++ return (0); ++} ++ ++png_uint_32 PNGAPI ++png_get_next_frame_width(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_get_next_frame_width()"); ++ ++ if (png_ptr != NULL && info_ptr != NULL) ++ return (info_ptr->next_frame_width); ++ return (0); ++} ++ ++png_uint_32 PNGAPI ++png_get_next_frame_height(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_get_next_frame_height()"); ++ ++ if (png_ptr != NULL && info_ptr != NULL) ++ return (info_ptr->next_frame_height); ++ return (0); ++} ++ ++png_uint_32 PNGAPI ++png_get_next_frame_x_offset(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_get_next_frame_x_offset()"); ++ ++ if (png_ptr != NULL && info_ptr != NULL) ++ return (info_ptr->next_frame_x_offset); ++ return (0); ++} ++ ++png_uint_32 PNGAPI ++png_get_next_frame_y_offset(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_get_next_frame_y_offset()"); ++ ++ if (png_ptr != NULL && info_ptr != NULL) ++ return (info_ptr->next_frame_y_offset); ++ return (0); ++} ++ ++png_uint_16 PNGAPI ++png_get_next_frame_delay_num(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_get_next_frame_delay_num()"); ++ ++ if (png_ptr != NULL && info_ptr != NULL) ++ return (info_ptr->next_frame_delay_num); ++ return (0); ++} ++ ++png_uint_16 PNGAPI ++png_get_next_frame_delay_den(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_get_next_frame_delay_den()"); ++ ++ if (png_ptr != NULL && info_ptr != NULL) ++ return (info_ptr->next_frame_delay_den); ++ return (0); ++} ++ ++png_byte PNGAPI ++png_get_next_frame_dispose_op(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_get_next_frame_dispose_op()"); ++ ++ if (png_ptr != NULL && info_ptr != NULL) ++ return (info_ptr->next_frame_dispose_op); ++ return (0); ++} ++ ++png_byte PNGAPI ++png_get_next_frame_blend_op(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_get_next_frame_blend_op()"); ++ ++ if (png_ptr != NULL && info_ptr != NULL) ++ return (info_ptr->next_frame_blend_op); ++ return (0); ++} ++ ++png_byte PNGAPI ++png_get_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_first_frame_is_hidden()"); ++ ++ if (png_ptr != NULL) ++ return (png_byte)(png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN); ++ ++ PNG_UNUSED(info_ptr) ++ ++ return 0; ++} ++#endif /* PNG_APNG_SUPPORTED */ + #endif /* READ || WRITE */ +diff -Naru libpng-1.6.40.org/pnginfo.h libpng-1.6.40/pnginfo.h +--- libpng-1.6.40.org/pnginfo.h 2022-11-24 08:37:51.507052183 +0900 ++++ libpng-1.6.40/pnginfo.h 2023-09-10 11:08:58.922075757 +0900 +@@ -263,5 +263,18 @@ + png_bytepp row_pointers; /* the image bits */ + #endif + ++#ifdef PNG_APNG_SUPPORTED ++ png_uint_32 num_frames; /* including default image */ ++ png_uint_32 num_plays; ++ png_uint_32 next_frame_width; ++ png_uint_32 next_frame_height; ++ png_uint_32 next_frame_x_offset; ++ png_uint_32 next_frame_y_offset; ++ png_uint_16 next_frame_delay_num; ++ png_uint_16 next_frame_delay_den; ++ png_byte next_frame_dispose_op; ++ png_byte next_frame_blend_op; ++#endif ++ + }; + #endif /* PNGINFO_H */ +diff -Naru libpng-1.6.40.org/pngpread.c libpng-1.6.40/pngpread.c +--- libpng-1.6.40.org/pngpread.c 2022-11-24 08:37:51.507052183 +0900 ++++ libpng-1.6.40/pngpread.c 2023-09-10 11:08:58.922075757 +0900 +@@ -195,6 +195,106 @@ + + chunk_name = png_ptr->chunk_name; + ++#ifdef PNG_READ_APNG_SUPPORTED ++ if (png_ptr->num_frames_read > 0 && ++ png_ptr->num_frames_read < info_ptr->num_frames) ++ { ++ if (chunk_name == png_IDAT) ++ { ++ /* Discard trailing IDATs for the first frame */ ++ if (png_ptr->mode & PNG_HAVE_fcTL || png_ptr->num_frames_read > 1) ++ png_error(png_ptr, "out of place IDAT"); ++ ++ if (png_ptr->push_length + 4 > png_ptr->buffer_size) ++ { ++ png_push_save_buffer(png_ptr); ++ return; ++ } ++ ++ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; ++ return; ++ } ++ else if (chunk_name == png_fdAT) ++ { ++ if (png_ptr->buffer_size < 4) ++ { ++ png_push_save_buffer(png_ptr); ++ return; ++ } ++ ++ png_ensure_sequence_number(png_ptr, 4); ++ ++ if (!(png_ptr->mode & PNG_HAVE_fcTL)) ++ { ++ /* Discard trailing fdATs for frames other than the first */ ++ if (png_ptr->num_frames_read < 2) ++ png_error(png_ptr, "out of place fdAT"); ++ ++ if (png_ptr->push_length + 4 > png_ptr->buffer_size) ++ { ++ png_push_save_buffer(png_ptr); ++ return; ++ } ++ ++ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; ++ return; ++ } ++ ++ else ++ { ++ /* frame data follows */ ++ png_ptr->idat_size = png_ptr->push_length - 4; ++ png_ptr->mode |= PNG_HAVE_IDAT; ++ png_ptr->process_mode = PNG_READ_IDAT_MODE; ++ ++ return; ++ } ++ } ++ ++ else if (chunk_name == png_fcTL) ++ { ++ if (png_ptr->push_length + 4 > png_ptr->buffer_size) ++ { ++ png_push_save_buffer(png_ptr); ++ return; ++ } ++ ++ png_read_reset(png_ptr); ++ png_ptr->mode &= ~PNG_HAVE_fcTL; ++ ++ png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length); ++ ++ if (!(png_ptr->mode & PNG_HAVE_fcTL)) ++ png_error(png_ptr, "missing required fcTL chunk"); ++ ++ png_read_reinit(png_ptr, info_ptr); ++ png_progressive_read_reset(png_ptr); ++ ++ if (png_ptr->frame_info_fn != NULL) ++ (*(png_ptr->frame_info_fn))(png_ptr, png_ptr->num_frames_read); ++ ++ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; ++ ++ return; ++ } ++ ++ else ++ { ++ if (png_ptr->push_length + 4 > png_ptr->buffer_size) ++ { ++ png_push_save_buffer(png_ptr); ++ return; ++ } ++ png_warning(png_ptr, "Skipped (ignored) a chunk " ++ "between APNG chunks"); ++ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; ++ return; ++ } ++ ++ return; ++ } ++#endif /* PNG_READ_APNG_SUPPORTED */ ++ + if (chunk_name == png_IDAT) + { + if ((png_ptr->mode & PNG_AFTER_IDAT) != 0) +@@ -261,6 +361,9 @@ + + else if (chunk_name == png_IDAT) + { ++#ifdef PNG_READ_APNG_SUPPORTED ++ png_have_info(png_ptr, info_ptr); ++#endif + png_ptr->idat_size = png_ptr->push_length; + png_ptr->process_mode = PNG_READ_IDAT_MODE; + png_push_have_info(png_ptr, info_ptr); +@@ -406,6 +509,30 @@ + png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); + } + #endif ++#ifdef PNG_READ_APNG_SUPPORTED ++ else if (chunk_name == png_acTL) ++ { ++ if (png_ptr->push_length + 4 > png_ptr->buffer_size) ++ { ++ png_push_save_buffer(png_ptr); ++ return; ++ } ++ ++ png_handle_acTL(png_ptr, info_ptr, png_ptr->push_length); ++ } ++ ++ else if (chunk_name == png_fcTL) ++ { ++ if (png_ptr->push_length + 4 > png_ptr->buffer_size) ++ { ++ png_push_save_buffer(png_ptr); ++ return; ++ } ++ ++ png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length); ++ } ++ ++#endif /* PNG_READ_APNG_SUPPORTED */ + + else + { +@@ -539,7 +666,11 @@ + png_byte chunk_tag[4]; + + /* TODO: this code can be commoned up with the same code in push_read */ ++#ifdef PNG_READ_APNG_SUPPORTED ++ PNG_PUSH_SAVE_BUFFER_IF_LT(12) ++#else + PNG_PUSH_SAVE_BUFFER_IF_LT(8) ++#endif + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); +@@ -547,17 +678,64 @@ + png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + ++#ifdef PNG_READ_APNG_SUPPORTED ++ if (png_ptr->chunk_name != png_fdAT && png_ptr->num_frames_read > 0) ++ { ++ if (png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) ++ { ++ png_ptr->process_mode = PNG_READ_CHUNK_MODE; ++ if (png_ptr->frame_end_fn != NULL) ++ (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read); ++ png_ptr->num_frames_read++; ++ return; ++ } ++ else ++ { ++ if (png_ptr->chunk_name == png_IEND) ++ png_error(png_ptr, "Not enough image data"); ++ if (png_ptr->push_length + 4 > png_ptr->buffer_size) ++ { ++ png_push_save_buffer(png_ptr); ++ return; ++ } ++ png_warning(png_ptr, "Skipping (ignoring) a chunk between " ++ "APNG chunks"); ++ png_crc_finish(png_ptr, png_ptr->push_length); ++ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; ++ return; ++ } ++ } ++ else ++#endif ++#ifdef PNG_READ_APNG_SUPPORTED ++ if (png_ptr->chunk_name != png_IDAT && png_ptr->num_frames_read == 0) ++#else + if (png_ptr->chunk_name != png_IDAT) ++#endif + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + + if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0) + png_error(png_ptr, "Not enough compressed data"); + ++#ifdef PNG_READ_APNG_SUPPORTED ++ if (png_ptr->frame_end_fn != NULL) ++ (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read); ++ png_ptr->num_frames_read++; ++#endif ++ + return; + } + + png_ptr->idat_size = png_ptr->push_length; ++ ++#ifdef PNG_READ_APNG_SUPPORTED ++ if (png_ptr->num_frames_read > 0) ++ { ++ png_ensure_sequence_number(png_ptr, 4); ++ png_ptr->idat_size -= 4; ++ } ++#endif + } + + if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0) +@@ -631,6 +809,15 @@ + if (!(buffer_length > 0) || buffer == NULL) + png_error(png_ptr, "No IDAT data (internal error)"); + ++#ifdef PNG_READ_APNG_SUPPORTED ++ /* If the app is not APNG-aware, decode only the first frame */ ++ if (!(png_ptr->apng_flags & PNG_APNG_APP) && png_ptr->num_frames_read > 0) ++ { ++ png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED; ++ return; ++ } ++#endif ++ + /* This routine must process all the data it has been given + * before returning, calling the row callback as required to + * handle the uncompressed results. +@@ -1085,6 +1272,18 @@ + png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer); + } + ++#ifdef PNG_READ_APNG_SUPPORTED ++void PNGAPI ++png_set_progressive_frame_fn(png_structp png_ptr, ++ png_progressive_frame_ptr frame_info_fn, ++ png_progressive_frame_ptr frame_end_fn) ++{ ++ png_ptr->frame_info_fn = frame_info_fn; ++ png_ptr->frame_end_fn = frame_end_fn; ++ png_ptr->apng_flags |= PNG_APNG_APP; ++} ++#endif ++ + png_voidp PNGAPI + png_get_progressive_ptr(png_const_structrp png_ptr) + { +diff -Naru libpng-1.6.40.org/pngpriv.h libpng-1.6.40/pngpriv.h +--- libpng-1.6.40.org/pngpriv.h 2023-09-10 11:09:32.954139030 +0900 ++++ libpng-1.6.40/pngpriv.h 2023-09-10 11:08:58.923075759 +0900 +@@ -628,6 +628,10 @@ + #define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000U /* Have another chunk after IDAT */ + #define PNG_WROTE_eXIf 0x4000U + #define PNG_IS_READ_STRUCT 0x8000U /* Else is a write struct */ ++#ifdef PNG_APNG_SUPPORTED ++#define PNG_HAVE_acTL 0x10000U ++#define PNG_HAVE_fcTL 0x20000U ++#endif + + /* Flags for the transformations the PNG library does on the image data */ + #define PNG_BGR 0x0001U +@@ -864,6 +868,16 @@ + #define png_tRNS PNG_U32(116, 82, 78, 83) + #define png_zTXt PNG_U32(122, 84, 88, 116) + ++#ifdef PNG_APNG_SUPPORTED ++#define png_acTL PNG_U32( 97, 99, 84, 76) ++#define png_fcTL PNG_U32(102, 99, 84, 76) ++#define png_fdAT PNG_U32(102, 100, 65, 84) ++ ++/* For png_struct.apng_flags: */ ++#define PNG_FIRST_FRAME_HIDDEN 0x0001U ++#define PNG_APNG_APP 0x0002U ++#endif ++ + /* The following will work on (signed char*) strings, whereas the get_uint_32 + * macro will fail on top-bit-set values because of the sign extension. + */ +@@ -1635,6 +1649,47 @@ + */ + #endif + ++#ifdef PNG_APNG_SUPPORTED ++PNG_INTERNAL_FUNCTION(void,png_ensure_fcTL_is_valid,(png_structp png_ptr, ++ png_uint_32 width, png_uint_32 height, ++ png_uint_32 x_offset, png_uint_32 y_offset, ++ png_uint_16 delay_num, png_uint_16 delay_den, ++ png_byte dispose_op, png_byte blend_op), PNG_EMPTY); ++ ++#ifdef PNG_READ_APNG_SUPPORTED ++PNG_INTERNAL_FUNCTION(void,png_handle_acTL,(png_structp png_ptr, png_infop info_ptr, ++ png_uint_32 length),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_handle_fcTL,(png_structp png_ptr, png_infop info_ptr, ++ png_uint_32 length),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_handle_fdAT,(png_structp png_ptr, png_infop info_ptr, ++ png_uint_32 length),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_have_info,(png_structp png_ptr, png_infop info_ptr),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_ensure_sequence_number,(png_structp png_ptr, ++ png_uint_32 length),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_read_reset,(png_structp png_ptr),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_read_reinit,(png_structp png_ptr, ++ png_infop info_ptr),PNG_EMPTY); ++#ifdef PNG_PROGRESSIVE_READ_SUPPORTED ++PNG_INTERNAL_FUNCTION(void,png_progressive_read_reset,(png_structp png_ptr),PNG_EMPTY); ++#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ ++#endif /* PNG_READ_APNG_SUPPORTED */ ++ ++#ifdef PNG_WRITE_APNG_SUPPORTED ++PNG_INTERNAL_FUNCTION(void,png_write_acTL,(png_structp png_ptr, ++ png_uint_32 num_frames, png_uint_32 num_plays),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_write_fcTL,(png_structp png_ptr, ++ png_uint_32 width, png_uint_32 height, ++ png_uint_32 x_offset, png_uint_32 y_offset, ++ png_uint_16 delay_num, png_uint_16 delay_den, ++ png_byte dispose_op, png_byte blend_op),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_write_fdAT,(png_structp png_ptr, ++ png_const_bytep data, png_size_t length),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_write_reset,(png_structp png_ptr),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_write_reinit,(png_structp png_ptr, ++ png_infop info_ptr, png_uint_32 width, png_uint_32 height),PNG_EMPTY); ++#endif /* PNG_WRITE_APNG_SUPPORTED */ ++#endif /* PNG_APNG_SUPPORTED */ ++ + /* Added at libpng version 1.4.0 */ + #ifdef PNG_COLORSPACE_SUPPORTED + /* These internal functions are for maintaining the colorspace structure within +diff -Naru libpng-1.6.40.org/pngread.c libpng-1.6.40/pngread.c +--- libpng-1.6.40.org/pngread.c 2022-11-24 08:37:51.508052181 +0900 ++++ libpng-1.6.40/pngread.c 2023-09-10 11:08:58.923075759 +0900 +@@ -161,6 +161,9 @@ + + else if (chunk_name == png_IDAT) + { ++#ifdef PNG_READ_APNG_SUPPORTED ++ png_have_info(png_ptr, info_ptr); ++#endif + png_ptr->idat_size = length; + break; + } +@@ -255,6 +258,17 @@ + png_handle_iTXt(png_ptr, info_ptr, length); + #endif + ++#ifdef PNG_READ_APNG_SUPPORTED ++ else if (chunk_name == png_acTL) ++ png_handle_acTL(png_ptr, info_ptr, length); ++ ++ else if (chunk_name == png_fcTL) ++ png_handle_fcTL(png_ptr, info_ptr, length); ++ ++ else if (chunk_name == png_fdAT) ++ png_handle_fdAT(png_ptr, info_ptr, length); ++#endif ++ + else + png_handle_unknown(png_ptr, info_ptr, length, + PNG_HANDLE_CHUNK_AS_DEFAULT); +@@ -262,6 +276,72 @@ + } + #endif /* SEQUENTIAL_READ */ + ++#ifdef PNG_READ_APNG_SUPPORTED ++void PNGAPI ++png_read_frame_head(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_byte have_chunk_after_DAT; /* after IDAT or after fdAT */ ++ ++ png_debug(0, "Reading frame head"); ++ ++ if (!(png_ptr->mode & PNG_HAVE_acTL)) ++ png_error(png_ptr, "attempt to png_read_frame_head() but " ++ "no acTL present"); ++ ++ /* do nothing for the main IDAT */ ++ if (png_ptr->num_frames_read == 0) ++ return; ++ ++ png_read_reset(png_ptr); ++ png_ptr->flags &= ~PNG_FLAG_ROW_INIT; ++ png_ptr->mode &= ~PNG_HAVE_fcTL; ++ ++ have_chunk_after_DAT = 0; ++ for (;;) ++ { ++ png_uint_32 length = png_read_chunk_header(png_ptr); ++ ++ if (png_ptr->chunk_name == png_IDAT) ++ { ++ /* discard trailing IDATs for the first frame */ ++ if (have_chunk_after_DAT || png_ptr->num_frames_read > 1) ++ png_error(png_ptr, "png_read_frame_head(): out of place IDAT"); ++ png_crc_finish(png_ptr, length); ++ } ++ ++ else if (png_ptr->chunk_name == png_fcTL) ++ { ++ png_handle_fcTL(png_ptr, info_ptr, length); ++ have_chunk_after_DAT = 1; ++ } ++ ++ else if (png_ptr->chunk_name == png_fdAT) ++ { ++ png_ensure_sequence_number(png_ptr, length); ++ ++ /* discard trailing fdATs for frames other than the first */ ++ if (!have_chunk_after_DAT && png_ptr->num_frames_read > 1) ++ png_crc_finish(png_ptr, length - 4); ++ else if(png_ptr->mode & PNG_HAVE_fcTL) ++ { ++ png_ptr->idat_size = length - 4; ++ png_ptr->mode |= PNG_HAVE_IDAT; ++ ++ break; ++ } ++ else ++ png_error(png_ptr, "png_read_frame_head(): out of place fdAT"); ++ } ++ else ++ { ++ png_warning(png_ptr, "Skipped (ignored) a chunk " ++ "between APNG chunks"); ++ png_crc_finish(png_ptr, length); ++ } ++ } ++} ++#endif /* PNG_READ_APNG_SUPPORTED */ ++ + /* Optional call to update the users info_ptr structure */ + void PNGAPI + png_read_update_info(png_structrp png_ptr, png_inforp info_ptr) +diff -Naru libpng-1.6.40.org/pngrutil.c libpng-1.6.40/pngrutil.c +--- libpng-1.6.40.org/pngrutil.c 2022-11-24 08:37:51.510052177 +0900 ++++ libpng-1.6.40/pngrutil.c 2023-09-10 11:08:58.923075759 +0900 +@@ -864,6 +864,11 @@ + filter_type = buf[11]; + interlace_type = buf[12]; + ++#ifdef PNG_READ_APNG_SUPPORTED ++ png_ptr->first_frame_width = width; ++ png_ptr->first_frame_height = height; ++#endif ++ + /* Set internal variables */ + png_ptr->width = width; + png_ptr->height = height; +@@ -2858,6 +2863,179 @@ + } + #endif + ++#ifdef PNG_READ_APNG_SUPPORTED ++void /* PRIVATE */ ++png_handle_acTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) ++{ ++ png_byte data[8]; ++ png_uint_32 num_frames; ++ png_uint_32 num_plays; ++ png_uint_32 didSet; ++ ++ png_debug(1, "in png_handle_acTL"); ++ ++ if (!(png_ptr->mode & PNG_HAVE_IHDR)) ++ { ++ png_error(png_ptr, "Missing IHDR before acTL"); ++ } ++ else if (png_ptr->mode & PNG_HAVE_IDAT) ++ { ++ png_warning(png_ptr, "Invalid acTL after IDAT skipped"); ++ png_crc_finish(png_ptr, length); ++ return; ++ } ++ else if (png_ptr->mode & PNG_HAVE_acTL) ++ { ++ png_warning(png_ptr, "Duplicate acTL skipped"); ++ png_crc_finish(png_ptr, length); ++ return; ++ } ++ else if (length != 8) ++ { ++ png_warning(png_ptr, "acTL with invalid length skipped"); ++ png_crc_finish(png_ptr, length); ++ return; ++ } ++ ++ png_crc_read(png_ptr, data, 8); ++ png_crc_finish(png_ptr, 0); ++ ++ num_frames = png_get_uint_31(png_ptr, data); ++ num_plays = png_get_uint_31(png_ptr, data + 4); ++ ++ /* the set function will do error checking on num_frames */ ++ didSet = png_set_acTL(png_ptr, info_ptr, num_frames, num_plays); ++ if(didSet) ++ png_ptr->mode |= PNG_HAVE_acTL; ++} ++ ++void /* PRIVATE */ ++png_handle_fcTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) ++{ ++ png_byte data[22]; ++ png_uint_32 width; ++ png_uint_32 height; ++ png_uint_32 x_offset; ++ png_uint_32 y_offset; ++ png_uint_16 delay_num; ++ png_uint_16 delay_den; ++ png_byte dispose_op; ++ png_byte blend_op; ++ ++ png_debug(1, "in png_handle_fcTL"); ++ ++ png_ensure_sequence_number(png_ptr, length); ++ ++ if (!(png_ptr->mode & PNG_HAVE_IHDR)) ++ { ++ png_error(png_ptr, "Missing IHDR before fcTL"); ++ } ++ else if (png_ptr->mode & PNG_HAVE_IDAT) ++ { ++ /* for any frames other then the first this message may be misleading, ++ * but correct. PNG_HAVE_IDAT is unset before the frame head is read ++ * i can't think of a better message */ ++ png_warning(png_ptr, "Invalid fcTL after IDAT skipped"); ++ png_crc_finish(png_ptr, length-4); ++ return; ++ } ++ else if (png_ptr->mode & PNG_HAVE_fcTL) ++ { ++ png_warning(png_ptr, "Duplicate fcTL within one frame skipped"); ++ png_crc_finish(png_ptr, length-4); ++ return; ++ } ++ else if (length != 26) ++ { ++ png_warning(png_ptr, "fcTL with invalid length skipped"); ++ png_crc_finish(png_ptr, length-4); ++ return; ++ } ++ ++ png_crc_read(png_ptr, data, 22); ++ png_crc_finish(png_ptr, 0); ++ ++ width = png_get_uint_31(png_ptr, data); ++ height = png_get_uint_31(png_ptr, data + 4); ++ x_offset = png_get_uint_31(png_ptr, data + 8); ++ y_offset = png_get_uint_31(png_ptr, data + 12); ++ delay_num = png_get_uint_16(data + 16); ++ delay_den = png_get_uint_16(data + 18); ++ dispose_op = data[20]; ++ blend_op = data[21]; ++ ++ if (png_ptr->num_frames_read == 0 && (x_offset != 0 || y_offset != 0)) ++ { ++ png_warning(png_ptr, "fcTL for the first frame must have zero offset"); ++ return; ++ } ++ ++ if (info_ptr != NULL) ++ { ++ if (png_ptr->num_frames_read == 0 && ++ (width != info_ptr->width || height != info_ptr->height)) ++ { ++ png_warning(png_ptr, "size in first frame's fcTL must match " ++ "the size in IHDR"); ++ return; ++ } ++ ++ /* The set function will do more error checking */ ++ png_set_next_frame_fcTL(png_ptr, info_ptr, width, height, ++ x_offset, y_offset, delay_num, delay_den, ++ dispose_op, blend_op); ++ ++ png_read_reinit(png_ptr, info_ptr); ++ ++ png_ptr->mode |= PNG_HAVE_fcTL; ++ } ++} ++ ++void /* PRIVATE */ ++png_have_info(png_structp png_ptr, png_infop info_ptr) ++{ ++ if((info_ptr->valid & PNG_INFO_acTL) && !(info_ptr->valid & PNG_INFO_fcTL)) ++ { ++ png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN; ++ info_ptr->num_frames++; ++ } ++} ++ ++void /* PRIVATE */ ++png_handle_fdAT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) ++{ ++ png_ensure_sequence_number(png_ptr, length); ++ ++ /* This function is only called from png_read_end(), png_read_info(), ++ * and png_push_read_chunk() which means that: ++ * - the user doesn't want to read this frame ++ * - or this is an out-of-place fdAT ++ * in either case it is safe to ignore the chunk with a warning */ ++ png_warning(png_ptr, "ignoring fdAT chunk"); ++ png_crc_finish(png_ptr, length - 4); ++ PNG_UNUSED(info_ptr) ++} ++ ++void /* PRIVATE */ ++png_ensure_sequence_number(png_structp png_ptr, png_uint_32 length) ++{ ++ png_byte data[4]; ++ png_uint_32 sequence_number; ++ ++ if (length < 4) ++ png_error(png_ptr, "invalid fcTL or fdAT chunk found"); ++ ++ png_crc_read(png_ptr, data, 4); ++ sequence_number = png_get_uint_31(png_ptr, data); ++ ++ if (sequence_number != png_ptr->next_seq_num) ++ png_error(png_ptr, "fcTL or fdAT chunk with out-of-order sequence " ++ "number found"); ++ ++ png_ptr->next_seq_num++; ++} ++#endif /* PNG_READ_APNG_SUPPORTED */ ++ + #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + /* Utility function for png_handle_unknown; set up png_ptr::unknown_chunk */ + static int +@@ -4166,7 +4344,38 @@ + { + uInt avail_in; + png_bytep buffer; ++#ifdef PNG_READ_APNG_SUPPORTED ++ png_uint_32 bytes_to_skip = 0; ++ ++ while (png_ptr->idat_size == 0 || bytes_to_skip != 0) ++ { ++ png_crc_finish(png_ptr, bytes_to_skip); ++ bytes_to_skip = 0; + ++ png_ptr->idat_size = png_read_chunk_header(png_ptr); ++ if (png_ptr->num_frames_read == 0) ++ { ++ if (png_ptr->chunk_name != png_IDAT) ++ png_error(png_ptr, "Not enough image data"); ++ } ++ else ++ { ++ if (png_ptr->chunk_name == png_IEND) ++ png_error(png_ptr, "Not enough image data"); ++ if (png_ptr->chunk_name != png_fdAT) ++ { ++ png_warning(png_ptr, "Skipped (ignored) a chunk " ++ "between APNG chunks"); ++ bytes_to_skip = png_ptr->idat_size; ++ continue; ++ } ++ ++ png_ensure_sequence_number(png_ptr, png_ptr->idat_size); ++ ++ png_ptr->idat_size -= 4; ++ } ++ } ++#else + while (png_ptr->idat_size == 0) + { + png_crc_finish(png_ptr, 0); +@@ -4178,7 +4387,7 @@ + if (png_ptr->chunk_name != png_IDAT) + png_error(png_ptr, "Not enough image data"); + } +- ++#endif /* PNG_READ_APNG_SUPPORTED */ + avail_in = png_ptr->IDAT_read_size; + + if (avail_in > png_ptr->idat_size) +@@ -4241,6 +4450,9 @@ + + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED; ++#ifdef PNG_READ_APNG_SUPPORTED ++ png_ptr->num_frames_read++; ++#endif + + if (png_ptr->zstream.avail_in > 0 || png_ptr->idat_size > 0) + png_chunk_benign_error(png_ptr, "Extra compressed data"); +@@ -4678,4 +4890,80 @@ + + png_ptr->flags |= PNG_FLAG_ROW_INIT; + } ++ ++#ifdef PNG_READ_APNG_SUPPORTED ++/* This function is to be called after the main IDAT set has been read and ++ * before a new IDAT is read. It resets some parts of png_ptr ++ * to make them usable by the read functions again */ ++void /* PRIVATE */ ++png_read_reset(png_structp png_ptr) ++{ ++ png_ptr->mode &= ~PNG_HAVE_IDAT; ++ png_ptr->mode &= ~PNG_AFTER_IDAT; ++ png_ptr->row_number = 0; ++ png_ptr->pass = 0; ++} ++ ++void /* PRIVATE */ ++png_read_reinit(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_ptr->width = info_ptr->next_frame_width; ++ png_ptr->height = info_ptr->next_frame_height; ++ png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width); ++ png_ptr->info_rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, ++ png_ptr->width); ++ if (png_ptr->prev_row) ++ memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); ++} ++ ++#ifdef PNG_PROGRESSIVE_READ_SUPPORTED ++/* same as png_read_reset() but for the progressive reader */ ++void /* PRIVATE */ ++png_progressive_read_reset(png_structp png_ptr) ++{ ++#ifdef PNG_READ_INTERLACING_SUPPORTED ++ /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ ++ ++ /* Start of interlace block */ ++ const int png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; ++ ++ /* Offset to next interlace block */ ++ const int png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; ++ ++ /* Start of interlace block in the y direction */ ++ const int png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; ++ ++ /* Offset to next interlace block in the y direction */ ++ const int png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; ++ ++ if (png_ptr->interlaced) ++ { ++ if (!(png_ptr->transformations & PNG_INTERLACE)) ++ png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - ++ png_pass_ystart[0]) / png_pass_yinc[0]; ++ else ++ png_ptr->num_rows = png_ptr->height; ++ ++ png_ptr->iwidth = (png_ptr->width + ++ png_pass_inc[png_ptr->pass] - 1 - ++ png_pass_start[png_ptr->pass]) / ++ png_pass_inc[png_ptr->pass]; ++ } ++ else ++#endif /* PNG_READ_INTERLACING_SUPPORTED */ ++ { ++ png_ptr->num_rows = png_ptr->height; ++ png_ptr->iwidth = png_ptr->width; ++ } ++ png_ptr->flags &= ~PNG_FLAG_ZSTREAM_ENDED; ++ if (inflateReset(&(png_ptr->zstream)) != Z_OK) ++ png_error(png_ptr, "inflateReset failed"); ++ png_ptr->zstream.avail_in = 0; ++ png_ptr->zstream.next_in = 0; ++ png_ptr->zstream.next_out = png_ptr->row_buf; ++ png_ptr->zstream.avail_out = (uInt)PNG_ROWBYTES(png_ptr->pixel_depth, ++ png_ptr->iwidth) + 1; ++} ++#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ ++#endif /* PNG_READ_APNG_SUPPORTED */ + #endif /* READ */ +diff -Naru libpng-1.6.40.org/pngset.c libpng-1.6.40/pngset.c +--- libpng-1.6.40.org/pngset.c 2023-09-10 11:09:32.954139030 +0900 ++++ libpng-1.6.40/pngset.c 2023-09-10 11:08:58.932075775 +0900 +@@ -280,6 +280,11 @@ + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); + + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width); ++ ++#ifdef PNG_APNG_SUPPORTED ++ /* for non-animated png. this may be overwritten from an acTL chunk later */ ++ info_ptr->num_frames = 1; ++#endif + } + + #ifdef PNG_oFFs_SUPPORTED +@@ -1149,6 +1154,147 @@ + } + #endif /* sPLT */ + ++#ifdef PNG_APNG_SUPPORTED ++png_uint_32 PNGAPI ++png_set_acTL(png_structp png_ptr, png_infop info_ptr, ++ png_uint_32 num_frames, png_uint_32 num_plays) ++{ ++ png_debug1(1, "in %s storage function", "acTL"); ++ ++ if (png_ptr == NULL || info_ptr == NULL) ++ { ++ png_warning(png_ptr, ++ "Call to png_set_acTL() with NULL png_ptr " ++ "or info_ptr ignored"); ++ return (0); ++ } ++ if (num_frames == 0) ++ { ++ png_warning(png_ptr, ++ "Ignoring attempt to set acTL with num_frames zero"); ++ return (0); ++ } ++ if (num_frames > PNG_UINT_31_MAX) ++ { ++ png_warning(png_ptr, ++ "Ignoring attempt to set acTL with num_frames > 2^31-1"); ++ return (0); ++ } ++ if (num_plays > PNG_UINT_31_MAX) ++ { ++ png_warning(png_ptr, ++ "Ignoring attempt to set acTL with num_plays " ++ "> 2^31-1"); ++ return (0); ++ } ++ ++ info_ptr->num_frames = num_frames; ++ info_ptr->num_plays = num_plays; ++ ++ info_ptr->valid |= PNG_INFO_acTL; ++ ++ return (1); ++} ++ ++/* delay_num and delay_den can hold any 16-bit values including zero */ ++png_uint_32 PNGAPI ++png_set_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr, ++ png_uint_32 width, png_uint_32 height, ++ png_uint_32 x_offset, png_uint_32 y_offset, ++ png_uint_16 delay_num, png_uint_16 delay_den, ++ png_byte dispose_op, png_byte blend_op) ++{ ++ png_debug1(1, "in %s storage function", "fcTL"); ++ ++ if (png_ptr == NULL || info_ptr == NULL) ++ { ++ png_warning(png_ptr, ++ "Call to png_set_fcTL() with NULL png_ptr or info_ptr " ++ "ignored"); ++ return (0); ++ } ++ ++ png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset, ++ delay_num, delay_den, dispose_op, blend_op); ++ ++ if (blend_op == PNG_BLEND_OP_OVER) ++ { ++ if (!(png_ptr->color_type & PNG_COLOR_MASK_ALPHA) && ++ !(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) ++ { ++ png_warning(png_ptr, "PNG_BLEND_OP_OVER is meaningless " ++ "and wasteful for opaque images, ignored"); ++ blend_op = PNG_BLEND_OP_SOURCE; ++ } ++ } ++ ++ info_ptr->next_frame_width = width; ++ info_ptr->next_frame_height = height; ++ info_ptr->next_frame_x_offset = x_offset; ++ info_ptr->next_frame_y_offset = y_offset; ++ info_ptr->next_frame_delay_num = delay_num; ++ info_ptr->next_frame_delay_den = delay_den; ++ info_ptr->next_frame_dispose_op = dispose_op; ++ info_ptr->next_frame_blend_op = blend_op; ++ ++ info_ptr->valid |= PNG_INFO_fcTL; ++ ++ return (1); ++} ++ ++void /* PRIVATE */ ++png_ensure_fcTL_is_valid(png_structp png_ptr, ++ png_uint_32 width, png_uint_32 height, ++ png_uint_32 x_offset, png_uint_32 y_offset, ++ png_uint_16 delay_num, png_uint_16 delay_den, ++ png_byte dispose_op, png_byte blend_op) ++{ ++ if (width == 0 || width > PNG_UINT_31_MAX) ++ png_error(png_ptr, "invalid width in fcTL (> 2^31-1)"); ++ if (height == 0 || height > PNG_UINT_31_MAX) ++ png_error(png_ptr, "invalid height in fcTL (> 2^31-1)"); ++ if (x_offset > PNG_UINT_31_MAX) ++ png_error(png_ptr, "invalid x_offset in fcTL (> 2^31-1)"); ++ if (y_offset > PNG_UINT_31_MAX) ++ png_error(png_ptr, "invalid y_offset in fcTL (> 2^31-1)"); ++ if (width + x_offset > png_ptr->first_frame_width || ++ height + y_offset > png_ptr->first_frame_height) ++ png_error(png_ptr, "dimensions of a frame are greater than" ++ "the ones in IHDR"); ++ ++ if (dispose_op != PNG_DISPOSE_OP_NONE && ++ dispose_op != PNG_DISPOSE_OP_BACKGROUND && ++ dispose_op != PNG_DISPOSE_OP_PREVIOUS) ++ png_error(png_ptr, "invalid dispose_op in fcTL"); ++ ++ if (blend_op != PNG_BLEND_OP_SOURCE && ++ blend_op != PNG_BLEND_OP_OVER) ++ png_error(png_ptr, "invalid blend_op in fcTL"); ++ ++ PNG_UNUSED(delay_num) ++ PNG_UNUSED(delay_den) ++} ++ ++png_uint_32 PNGAPI ++png_set_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr, ++ png_byte is_hidden) ++{ ++ png_debug(1, "in png_first_frame_is_hidden()"); ++ ++ if (png_ptr == NULL) ++ return 0; ++ ++ if (is_hidden) ++ png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN; ++ else ++ png_ptr->apng_flags &= ~PNG_FIRST_FRAME_HIDDEN; ++ ++ PNG_UNUSED(info_ptr) ++ ++ return 1; ++} ++#endif /* PNG_APNG_SUPPORTED */ ++ + #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED + static png_byte + check_location(png_const_structrp png_ptr, int location) +diff -Naru libpng-1.6.40.org/pngstruct.h libpng-1.6.40/pngstruct.h +--- libpng-1.6.40.org/pngstruct.h 2022-11-24 08:37:51.510052177 +0900 ++++ libpng-1.6.40/pngstruct.h 2023-09-10 11:08:58.924075760 +0900 +@@ -399,6 +399,27 @@ + png_byte filter_type; + #endif + ++#ifdef PNG_APNG_SUPPORTED ++ png_uint_32 apng_flags; ++ png_uint_32 next_seq_num; /* next fcTL/fdAT chunk sequence number */ ++ png_uint_32 first_frame_width; ++ png_uint_32 first_frame_height; ++ ++#ifdef PNG_READ_APNG_SUPPORTED ++ png_uint_32 num_frames_read; /* incremented after all image data of */ ++ /* a frame is read */ ++#ifdef PNG_PROGRESSIVE_READ_SUPPORTED ++ png_progressive_frame_ptr frame_info_fn; /* frame info read callback */ ++ png_progressive_frame_ptr frame_end_fn; /* frame data read callback */ ++#endif ++#endif ++ ++#ifdef PNG_WRITE_APNG_SUPPORTED ++ png_uint_32 num_frames_to_write; ++ png_uint_32 num_frames_written; ++#endif ++#endif /* PNG_APNG_SUPPORTED */ ++ + /* New members added in libpng-1.2.0 */ + + /* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ +diff -Naru libpng-1.6.40.org/pngtest.c libpng-1.6.40/pngtest.c +--- libpng-1.6.40.org/pngtest.c 2023-09-10 11:12:23.044481879 +0900 ++++ libpng-1.6.40/pngtest.c 2023-09-10 11:08:58.924075760 +0900 +@@ -875,6 +875,10 @@ + volatile int num_passes; + int pass; + int bit_depth, color_type; ++#ifdef PNG_APNG_SUPPORTED ++ png_uint_32 num_frames; ++ png_uint_32 num_plays; ++#endif + + row_buf = NULL; + error_parameters.file_name = inname; +@@ -1383,6 +1387,22 @@ + } + } + #endif ++ ++#ifdef PNG_APNG_SUPPORTED ++ if (png_get_valid(read_ptr, read_info_ptr, PNG_INFO_acTL)) ++ { ++ if (png_get_acTL(read_ptr, read_info_ptr, &num_frames, &num_plays)) ++ { ++ png_byte is_hidden; ++ pngtest_debug2("Handling acTL chunks (frames %ld, plays %ld)", ++ num_frames, num_plays); ++ png_set_acTL(write_ptr, write_info_ptr, num_frames, num_plays); ++ is_hidden = png_get_first_frame_is_hidden(read_ptr, read_info_ptr); ++ png_set_first_frame_is_hidden(write_ptr, write_info_ptr, is_hidden); ++ } ++ } ++#endif ++ + #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + { + png_unknown_chunkp unknowns; +@@ -1463,6 +1483,110 @@ + t_misc += (t_stop - t_start); + t_start = t_stop; + #endif ++#ifdef PNG_APNG_SUPPORTED ++ if (png_get_valid(read_ptr, read_info_ptr, PNG_INFO_acTL)) ++ { ++ png_uint_32 frame; ++ for (frame = 0; frame < num_frames; frame++) ++ { ++ png_uint_32 frame_width; ++ png_uint_32 frame_height; ++ png_uint_32 x_offset; ++ png_uint_32 y_offset; ++ png_uint_16 delay_num; ++ png_uint_16 delay_den; ++ png_byte dispose_op; ++ png_byte blend_op; ++ png_read_frame_head(read_ptr, read_info_ptr); ++ if (png_get_valid(read_ptr, read_info_ptr, PNG_INFO_fcTL)) ++ { ++ png_get_next_frame_fcTL(read_ptr, read_info_ptr, ++ &frame_width, &frame_height, ++ &x_offset, &y_offset, ++ &delay_num, &delay_den, ++ &dispose_op, &blend_op); ++ } ++ else ++ { ++ frame_width = width; ++ frame_height = height; ++ x_offset = 0; ++ y_offset = 0; ++ delay_num = 1; ++ delay_den = 1; ++ dispose_op = PNG_DISPOSE_OP_NONE; ++ blend_op = PNG_BLEND_OP_SOURCE; ++ } ++#ifdef PNG_WRITE_APNG_SUPPORTED ++ png_write_frame_head(write_ptr, write_info_ptr, (png_bytepp)&row_buf, ++ frame_width, frame_height, ++ x_offset, y_offset, ++ delay_num, delay_den, ++ dispose_op, blend_op); ++#endif ++ for (pass = 0; pass < num_passes; pass++) ++ { ++# ifdef calc_pass_height ++ png_uint_32 pass_height; ++ ++ if (num_passes == 7) /* interlaced */ ++ { ++ if (PNG_PASS_COLS(frame_width, pass) > 0) ++ pass_height = PNG_PASS_ROWS(frame_height, pass); ++ ++ else ++ pass_height = 0; ++ } ++ ++ else /* not interlaced */ ++ pass_height = frame_height; ++# else ++# define pass_height frame_height ++# endif ++ ++ pngtest_debug1("Writing row data for pass %d", pass); ++ for (y = 0; y < pass_height; y++) ++ { ++#ifndef SINGLE_ROWBUF_ALLOC ++ pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", pass, y); ++ ++ row_buf = (png_bytep)png_malloc(read_ptr, ++ png_get_rowbytes(read_ptr, read_info_ptr)); ++ ++ pngtest_debug2("\t0x%08lx (%lu bytes)", (unsigned long)row_buf, ++ (unsigned long)png_get_rowbytes(read_ptr, read_info_ptr)); ++ ++#endif /* !SINGLE_ROWBUF_ALLOC */ ++ png_read_rows(read_ptr, (png_bytepp)&row_buf, NULL, 1); ++ ++#ifdef PNG_WRITE_SUPPORTED ++#ifdef PNGTEST_TIMING ++ t_stop = (float)clock(); ++ t_decode += (t_stop - t_start); ++ t_start = t_stop; ++#endif ++ png_write_rows(write_ptr, (png_bytepp)&row_buf, 1); ++#ifdef PNGTEST_TIMING ++ t_stop = (float)clock(); ++ t_encode += (t_stop - t_start); ++ t_start = t_stop; ++#endif ++#endif /* PNG_WRITE_SUPPORTED */ ++ ++#ifndef SINGLE_ROWBUF_ALLOC ++ pngtest_debug2("Freeing row buffer (pass %d, y = %u)", pass, y); ++ png_free(read_ptr, row_buf); ++ row_buf = NULL; ++#endif /* !SINGLE_ROWBUF_ALLOC */ ++ } ++ } ++#ifdef PNG_WRITE_APNG_SUPPORTED ++ png_write_frame_tail(write_ptr, write_info_ptr); ++#endif ++ } ++ } ++ else ++#endif + for (pass = 0; pass < num_passes; pass++) + { + # ifdef calc_pass_height +diff -Naru libpng-1.6.40.org/pngwrite.c libpng-1.6.40/pngwrite.c +--- libpng-1.6.40.org/pngwrite.c 2023-09-10 11:09:32.955139032 +0900 ++++ libpng-1.6.40/pngwrite.c 2023-09-10 11:08:58.924075760 +0900 +@@ -128,6 +128,10 @@ + * the application continues writing the PNG. So check the 'invalid' + * flag here too. + */ ++#ifdef PNG_WRITE_APNG_SUPPORTED ++ if (info_ptr->valid & PNG_INFO_acTL) ++ png_write_acTL(png_ptr, info_ptr->num_frames, info_ptr->num_plays); ++#endif + #ifdef PNG_GAMMA_SUPPORTED + # ifdef PNG_WRITE_gAMA_SUPPORTED + if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && +@@ -373,6 +377,11 @@ + png_benign_error(png_ptr, "Wrote palette index exceeding num_palette"); + #endif + ++#ifdef PNG_WRITE_APNG_SUPPORTED ++ if (png_ptr->num_frames_written != png_ptr->num_frames_to_write) ++ png_error(png_ptr, "Not enough frames written"); ++#endif ++ + /* See if user wants us to write information chunks */ + if (info_ptr != NULL) + { +@@ -1475,6 +1484,43 @@ + } + #endif + ++#ifdef PNG_WRITE_APNG_SUPPORTED ++void PNGAPI ++png_write_frame_head(png_structp png_ptr, png_infop info_ptr, ++ png_bytepp row_pointers, png_uint_32 width, png_uint_32 height, ++ png_uint_32 x_offset, png_uint_32 y_offset, ++ png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, ++ png_byte blend_op) ++{ ++ png_debug(1, "in png_write_frame_head"); ++ ++ /* there is a chance this has been set after png_write_info was called, ++ * so it would be set but not written. is there a way to be sure? */ ++ if (!(info_ptr->valid & PNG_INFO_acTL)) ++ png_error(png_ptr, "png_write_frame_head(): acTL not set"); ++ ++ png_write_reset(png_ptr); ++ ++ png_write_reinit(png_ptr, info_ptr, width, height); ++ ++ if ( !(png_ptr->num_frames_written == 0 && ++ (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) ) ) ++ png_write_fcTL(png_ptr, width, height, x_offset, y_offset, ++ delay_num, delay_den, dispose_op, blend_op); ++ ++ PNG_UNUSED(row_pointers) ++} ++ ++void PNGAPI ++png_write_frame_tail(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_write_frame_tail"); ++ ++ png_ptr->num_frames_written++; ++ ++ PNG_UNUSED(info_ptr) ++} ++#endif /* PNG_WRITE_APNG_SUPPORTED */ + + #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED + /* Initialize the write structure - general purpose utility. */ +diff -Naru libpng-1.6.40.org/pngwutil.c libpng-1.6.40/pngwutil.c +--- libpng-1.6.40.org/pngwutil.c 2022-11-24 08:37:51.511052176 +0900 ++++ libpng-1.6.40/pngwutil.c 2023-09-10 11:08:58.952075811 +0900 +@@ -821,6 +821,11 @@ + /* Write the chunk */ + png_write_complete_chunk(png_ptr, png_IHDR, buf, 13); + ++#ifdef PNG_WRITE_APNG_SUPPORTED ++ png_ptr->first_frame_width = width; ++ png_ptr->first_frame_height = height; ++#endif ++ + if ((png_ptr->do_filter) == PNG_NO_FILTERS) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || +@@ -1002,8 +1007,17 @@ + optimize_cmf(data, png_image_size(png_ptr)); + #endif + +- if (size > 0) +- png_write_complete_chunk(png_ptr, png_IDAT, data, size); ++ if (size > 0) ++#ifdef PNG_WRITE_APNG_SUPPORTED ++ { ++ if (png_ptr->num_frames_written == 0) ++#endif ++ png_write_complete_chunk(png_ptr, png_IDAT, data, size); ++#ifdef PNG_WRITE_APNG_SUPPORTED ++ else ++ png_write_fdAT(png_ptr, data, size); ++ } ++#endif /* PNG_WRITE_APNG_SUPPORTED */ + png_ptr->mode |= PNG_HAVE_IDAT; + + png_ptr->zstream.next_out = data; +@@ -1050,7 +1064,17 @@ + #endif + + if (size > 0) ++#ifdef PNG_WRITE_APNG_SUPPORTED ++ { ++ if (png_ptr->num_frames_written == 0) ++#endif + png_write_complete_chunk(png_ptr, png_IDAT, data, size); ++#ifdef PNG_WRITE_APNG_SUPPORTED ++ else ++ png_write_fdAT(png_ptr, data, size); ++ } ++#endif /* PNG_WRITE_APNG_SUPPORTED */ ++ + png_ptr->zstream.avail_out = 0; + png_ptr->zstream.next_out = NULL; + png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT; +@@ -1885,6 +1909,82 @@ + } + #endif + ++#ifdef PNG_WRITE_APNG_SUPPORTED ++void /* PRIVATE */ ++png_write_acTL(png_structp png_ptr, ++ png_uint_32 num_frames, png_uint_32 num_plays) ++{ ++ png_byte buf[8]; ++ ++ png_debug(1, "in png_write_acTL"); ++ ++ png_ptr->num_frames_to_write = num_frames; ++ ++ if (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) ++ num_frames--; ++ ++ png_save_uint_32(buf, num_frames); ++ png_save_uint_32(buf + 4, num_plays); ++ ++ png_write_complete_chunk(png_ptr, png_acTL, buf, (png_size_t)8); ++} ++ ++void /* PRIVATE */ ++png_write_fcTL(png_structp png_ptr, png_uint_32 width, png_uint_32 height, ++ png_uint_32 x_offset, png_uint_32 y_offset, ++ png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, ++ png_byte blend_op) ++{ ++ png_byte buf[26]; ++ ++ png_debug(1, "in png_write_fcTL"); ++ ++ if (png_ptr->num_frames_written == 0 && (x_offset != 0 || y_offset != 0)) ++ png_error(png_ptr, "x and/or y offset for the first frame aren't 0"); ++ if (png_ptr->num_frames_written == 0 && ++ (width != png_ptr->first_frame_width || ++ height != png_ptr->first_frame_height)) ++ png_error(png_ptr, "width and/or height in the first frame's fcTL " ++ "don't match the ones in IHDR"); ++ ++ /* more error checking */ ++ png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset, ++ delay_num, delay_den, dispose_op, blend_op); ++ ++ png_save_uint_32(buf, png_ptr->next_seq_num); ++ png_save_uint_32(buf + 4, width); ++ png_save_uint_32(buf + 8, height); ++ png_save_uint_32(buf + 12, x_offset); ++ png_save_uint_32(buf + 16, y_offset); ++ png_save_uint_16(buf + 20, delay_num); ++ png_save_uint_16(buf + 22, delay_den); ++ buf[24] = dispose_op; ++ buf[25] = blend_op; ++ ++ png_write_complete_chunk(png_ptr, png_fcTL, buf, (png_size_t)26); ++ ++ png_ptr->next_seq_num++; ++} ++ ++void /* PRIVATE */ ++png_write_fdAT(png_structp png_ptr, ++ png_const_bytep data, png_size_t length) ++{ ++ png_byte buf[4]; ++ ++ png_write_chunk_header(png_ptr, png_fdAT, (png_uint_32)(4 + length)); ++ ++ png_save_uint_32(buf, png_ptr->next_seq_num); ++ png_write_chunk_data(png_ptr, buf, 4); ++ ++ png_write_chunk_data(png_ptr, data, length); ++ ++ png_write_chunk_end(png_ptr); ++ ++ png_ptr->next_seq_num++; ++} ++#endif /* PNG_WRITE_APNG_SUPPORTED */ ++ + /* Initializes the row writing capability of libpng */ + void /* PRIVATE */ + png_write_start_row(png_structrp png_ptr) +@@ -2778,4 +2878,39 @@ + } + #endif /* WRITE_FLUSH */ + } ++ ++#ifdef PNG_WRITE_APNG_SUPPORTED ++void /* PRIVATE */ ++png_write_reset(png_structp png_ptr) ++{ ++ png_ptr->row_number = 0; ++ png_ptr->pass = 0; ++ png_ptr->mode &= ~PNG_HAVE_IDAT; ++} ++ ++void /* PRIVATE */ ++png_write_reinit(png_structp png_ptr, png_infop info_ptr, ++ png_uint_32 width, png_uint_32 height) ++{ ++ if (png_ptr->num_frames_written == 0 && ++ (width != png_ptr->first_frame_width || ++ height != png_ptr->first_frame_height)) ++ png_error(png_ptr, "width and/or height in the first frame's fcTL " ++ "don't match the ones in IHDR"); ++ if (width > png_ptr->first_frame_width || ++ height > png_ptr->first_frame_height) ++ png_error(png_ptr, "width and/or height for a frame greater than" ++ "the ones in IHDR"); ++ ++ png_set_IHDR(png_ptr, info_ptr, width, height, ++ info_ptr->bit_depth, info_ptr->color_type, ++ info_ptr->interlace_type, info_ptr->compression_type, ++ info_ptr->filter_type); ++ ++ png_ptr->width = width; ++ png_ptr->height = height; ++ png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); ++ png_ptr->usr_width = png_ptr->width; ++} ++#endif /* PNG_WRITE_APNG_SUPPORTED */ + #endif /* WRITE */ +diff -Naru libpng-1.6.40.org/scripts/symbols.def libpng-1.6.40/scripts/symbols.def +--- libpng-1.6.40.org/scripts/symbols.def 2022-11-24 08:37:51.515052168 +0900 ++++ libpng-1.6.40/scripts/symbols.def 2023-09-10 11:08:58.925075762 +0900 +@@ -253,3 +253,23 @@ + png_set_eXIf @247 + png_get_eXIf_1 @248 + png_set_eXIf_1 @249 ++ png_get_acTL @250 ++ png_set_acTL @251 ++ png_get_num_frames @252 ++ png_get_num_plays @253 ++ png_get_next_frame_fcTL @254 ++ png_set_next_frame_fcTL @255 ++ png_get_next_frame_width @256 ++ png_get_next_frame_height @257 ++ png_get_next_frame_x_offset @258 ++ png_get_next_frame_y_offset @259 ++ png_get_next_frame_delay_num @260 ++ png_get_next_frame_delay_den @261 ++ png_get_next_frame_dispose_op @262 ++ png_get_next_frame_blend_op @263 ++ png_get_first_frame_is_hidden @264 ++ png_set_first_frame_is_hidden @265 ++ png_read_frame_head @266 ++ png_set_progressive_frame_fn @267 ++ png_write_frame_head @268 ++ png_write_frame_tail @269 diff --git a/thirdparty/openmpt_svn_version.h b/thirdparty/openmpt_svn_version.h deleted file mode 100644 index a45ed9f22449e7a4164bd2a7881c5ae52f805087..0000000000000000000000000000000000000000 --- a/thirdparty/openmpt_svn_version.h +++ /dev/null @@ -1,10 +0,0 @@ - -#pragma once -#define OPENMPT_VERSION_SVNVERSION "17963" -#define OPENMPT_VERSION_REVISION 17963 -#define OPENMPT_VERSION_DIRTY 0 -#define OPENMPT_VERSION_MIXEDREVISIONS 0 -#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.4.32" -#define OPENMPT_VERSION_DATE "2022-09-25T14:19:05.052596Z" -#define OPENMPT_VERSION_IS_PACKAGE 1 - diff --git a/thirdparty/sdl2-mixer-ext.cmake b/thirdparty/sdl2-mixer-ext.cmake new file mode 100644 index 0000000000000000000000000000000000000000..1998a7bd9217c2bdfd9da5f1b5de544e48cd6c5d --- /dev/null +++ b/thirdparty/sdl2-mixer-ext.cmake @@ -0,0 +1,38 @@ +if(TARGET SDL2_mixer_ext_Static) + return() +endif() + +message(STATUS "Third-party: creating target 'SDL2_mixer_ext::SDL2_mixer_ext'") + +set(SDL_MIXER_X_SHARED ${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES} CACHE BOOL "" FORCE) +set(SDL_MIXER_X_STATIC ${NOT_SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES} CACHE BOOL "" FORCE) +set(SDL_MIXER_X_DISABLE_INSTALL ON CACHE BOOL "" FORCE) +set(USE_SYSTEM_SDL2 ON CACHE BOOL "" FORCE) +set(SDL2_INCLUDE_PATH ${SDL2_INCLUDE_DIR} CACHE PATH "" FORCE) +set(USE_XMP OFF CACHE PATH "" FORCE) + +set( + internal_SDL2_mixer_ext_options + "SDL_MIXER_X_SHARED ${SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}" + "SDL_MIXER_X_STATIC ${NOT_SRB2_CONFIG_SHARED_INTERNAL_LIBRARIES}" + "SDL_MIXER_X_DISABLE_INSTALL ON" + "USE_SYSTEM_SDL2 ON" + "USE_XMP OFF" +) + +if(${CMAKE_SYSTEM} MATCHES Windows) + #list(APPEND internal_SDL2_mixer_ext_options "DOWNLOAD_AUDIO_CODECS_DEPENDENCY ON") + #set(DOWNLOAD_AUDIO_CODECS_DEPENDENCY ON CACHE BOOL "" FORCE) +endif() + +include(FetchContent) + + +FetchContent_Declare( + SDL2_mixer_ext + OPTIONS ${internal_SDL2_mixer_ext_options} + GIT_TAG "2.6.0-1" + GIT_REPOSITORY "https://github.com/STJr/SDL-Mixer-X.git" +) + +FetchContent_MakeAvailable(SDL2_mixer_ext) diff --git a/thirdparty/sdl2.cmake b/thirdparty/sdl2.cmake new file mode 100644 index 0000000000000000000000000000000000000000..16fbd7563b2f1c57a12a9202c3e89a69a2f9c191 --- /dev/null +++ b/thirdparty/sdl2.cmake @@ -0,0 +1,61 @@ +if(TARGET SDL2-static) + return() +endif() + +message(STATUS "Third-party: creating target 'SDL2::SDL2'") + +set(SDL_STATIC ON CACHE BOOL "" FORCE) +set(SDL_SHARED OFF CACHE BOOL "" FORCE) +set(SDL_TEST OFF CACHE BOOL "" FORCE) +set(SDL2_DISABLE_INSTALL OFF CACHE BOOL "" FORCE) + +set( + internal_sdl2_options + + "SDL_STATIC ON" + "SDL_SHARED OFF" + "SDL_TEST OFF" + "SDL2_DISABLE_INSTALL OFF" +) + +if(${CMAKE_SYSTEM} MATCHES Windows) + list(APPEND internal_sdl2_options "SDL2_DISABLE_SDL2MAIN OFF") + option(SDL2_DISABLE_SDL2MAIN "Disable building/installation of SDL2main" OFF) + set(SDL2_DISABLE_SDL2MAIN OFF CACHE BOOL "" FORCE) +endif() +if(${CMAKE_SYSTEM} MATCHES Darwin) + list(APPEND internal_sdl2_options "SDL2_DISABLE_SDL2MAIN OFF") + option(SDL2_DISABLE_SDL2MAIN "Disable building/installation of SDL2main" OFF) + set(SDL2_DISABLE_SDL2MAIN OFF CACHE BOOL "" FORCE) +endif() +if(${CMAKE_SYSTEM} MATCHES Linux) + list(APPEND internal_sdl2_options "SDL2_DISABLE_SDL2MAIN ON") + option(SDL2_DISABLE_SDL2MAIN "Disable building/installation of SDL2main" ON) + set(SDL2_DISABLE_SDL2MAIN ON CACHE BOOL "" FORCE) +endif() + +include(FetchContent) + +if (SDL2_USE_THIRDPARTY) + FetchContent_Declare( + SDL2 + VERSION 2.30.0 + GITHUB_REPOSITORY "libsdl-org/SDL" + GIT_TAG release-2.30.0 + OPTIONS ${internal_sdl2_options} + OVERRIDE_FIND_PACKAGE + ) +else() + FetchContent_Declare( + SDL2 + SOURCE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/SDL2/" + OPTIONS ${internal_sdl2_options} + OVERRIDE_FIND_PACKAGE + ) +endif() + +FetchContent_MakeAvailable(SDL2) + +set(SDL2_INCLUDE_DIR "${SDL2_BINARY_DIR}/include" CACHE PATH "" FORCE) +set(SDL2_LIBRARY "${SDL2_BINARY_DIR}/SDL2-staticd.lib" CACHE PATH "" FORCE) +set(SDL2_DIR ${SDL2_BINARY_DIR} CACHE PATH "" FORCE) diff --git a/thirdparty/vcpkg-overlays/.placeholder b/thirdparty/vcpkg-overlays/.placeholder new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/thirdparty/zlib.cmake b/thirdparty/zlib.cmake new file mode 100644 index 0000000000000000000000000000000000000000..50c567dda9e664632c709fc374276c401ee59203 --- /dev/null +++ b/thirdparty/zlib.cmake @@ -0,0 +1,35 @@ +if(TARGET ZLIB::ZLIB) + return() +endif() + +message(STATUS "Third-party: creating target 'ZLIB::ZLIB'") + +set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) + +include(FetchContent) + +if (zlib_USE_THIRDPARTY) + FetchContent_Declare( + ZLIB + GITHUB_REPOSITORY "madler/zlib" + GIT_TAG v1.3.1 + OVERRIDE_FIND_PACKAGE + OPTIONS + "ZLIB_BUILD_EXAMPLES OFF" + ) +else() + FetchContent_Declare( + ZLIB + SOURCE_DIR "${CMAKE_SOURCE_DIR}/thirdparty/zlib/" + OVERRIDE_FIND_PACKAGE + OPTIONS + "ZLIB_BUILD_EXAMPLES OFF" + ) +endif() + +FetchContent_MakeAvailable(ZLIB) + + +add_library(ZLIB::ZLIB ALIAS zlibstatic) + +set(ZLIB_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/zlib" "${zlib_BINARY_DIR}" CACHE PATH "" FORCE) diff --git a/vcpkg-configuration.json b/vcpkg-configuration.json new file mode 100644 index 0000000000000000000000000000000000000000..547114800f3088a704ec397b482c4bfed86cea3d --- /dev/null +++ b/vcpkg-configuration.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg-configuration.schema.json", + "overlay-ports": [ + "./thirdparty/vcpkg-overlays" + ] +} diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 0000000000000000000000000000000000000000..07c4244ad3affde086c98bd46867ae8cd0d02b18 --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,85 @@ +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", + "name": "srb2", + "version": "1.0.0", + "builtin-baseline": "c823fd3e57035b10d970a96da2796a2db55e5df5", + "dependencies": [ + "curl", + { + "name": "libgme", + "platform": "!(windows & mingw) & !native" + }, + { + "name": "libopenmpt", + "platform": "!(windows & mingw)" + }, + "libpng", + "miniupnpc", + "sdl2", + { + "name": "sdl2-mixer-ext", + "features": [ + { + "name": "cmd", + "platform": "linux" + }, + { + "name": "libflac", + "platform": "!(windows & mingw & !static)" + }, + { + "name": "libgme", + "platform": "!(windows & mingw) & !native" + }, + { + "name": "libmodplug", + "platform": "!(windows & mingw)" + }, + { + "name": "libopnmidi", + "platform": "!(windows & mingw)" + }, + { + "name": "libvorbis", + "platform": "!(windows & mingw & !static)" + }, + { + "name": "libxmp", + "platform": "!(windows & mingw)" + }, + { + "name": "mpg123", + "platform": "!(windows & mingw)" + }, + { + "name": "nativemidi", + "platform": "!(windows & mingw)" + }, + { + "name": "opusfile", + "platform": "!(windows & mingw)" + }, + { + "name": "pxtone", + "platform": "!(windows & mingw)" + }, + { + "name": "timidity", + "platform": "!(windows & mingw)" + }, + { + "name": "wavpack", + "platform": "!(windows & mingw)" + } + ] + }, + "zlib" + ], + "overrides": [ + { + "name": "sdl2", + "version": "2.28.5", + "port-version": 1 + } + ] +}