diff --git a/.gitignore b/.gitignore index 4ba05f7ca698b968eec6391857fa5ec68e1b422e..a3d823fa2182edef86c35ee2810560e5d8f7408e 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ Win32_LIB_ASM_Release /CMakeUserPresets.json /out /objs/VC10 +/thirdparty/vcpkg-overlays diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b21ce1b00313089705addb772b455a8308d21795..29f5ef5fff9f1bc4afb83006c65f54088762e6dc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,848 +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" +include: + - '.gitlab/ci/templates/*.yml' + - '.gitlab/ci/jobs/*.yml' - - - | - # 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" +workflow: + auto_cancel: + on_new_commit: interruptible - - - | - # ccache_config - echo -e "\e[0Ksection_start:`date +%s`:ccache_config[collapsed=true]\r\e[0KSetting up ccache config" - - mkdir --parents --verbose ~/.ccache/ - - touch ~/.ccache/ccache.conf - - | - # cache.conf - echo Adding ccache configution option - - | - # base_dir - echo base_dir = $PWD | tee --append ~/.ccache/ccache.conf - - | - # cache_dir - echo cache_dir = $PWD/ccache | tee --append ~/.ccache/ccache.conf - - | - # compiler_check - echo compiler_check = content | tee --append ~/.ccache/ccache.conf - - | - # stats_log - echo stats_log = $PWD/ccache_statslog | tee --append ~/.ccache/ccache.conf - - | - # max_size - echo max_size = 50M | tee --append ~/.ccache/ccache.conf - - | - # ccache_config - echo -e "\e[0Ksection_end:`date +%s`:ccache_config\r\e[0K" - - - - | - # cache_reset - echo -e "\e[0Ksection_start:`date +%s`:ccache_reset[collapsed=true]\r\e[0KResetting ccache statistics" - - ccache --zero-stats - - ccache --show-stats - - | - # ccache_reset - echo -e "\e[0Ksection_end:`date +%s`:ccache_reset\r\e[0K" - - artifacts: - paths: - - "bin/" - - "src/comptime.h" - name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-$CI_JOB_NAME_SLUG" - - after_script: - - - | - # apt_clean - echo -e "\e[0Ksection_start:`date +%s`:apt_clean[collapsed=true]\r\e[0KCleaning of unneeded APT packages" - - apt-get autoclean - - | - # apt_clean - echo -e "\e[0Ksection_end:`date +%s`:apt_clean\r\e[0K" - - - - | - # ccache_stats - echo -e "\e[0Ksection_start:`date +%s`:ccache_stats[collapsed=true]\r\e[0Kccache statistics:" - - ccache --show-stats - - ccache --show-log-stats || true - - | - # 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 oldstable:amd64: - extends: Debian stable:amd64 - - 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" - 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" - - - - | - # 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" - -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" - -Debian oldstable:arm64: - extends: Debian stable:arm64 - - 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" - 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" - - - - | - # 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" - -batocera:arm64: - extends: Debian stable:arm64 - - when: manual - - allow_failure: true - - artifacts: - paths: - - "bin/" - - "src/comptime.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" - - - - | - # 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" - -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: 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" - -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 - -Alpine 3 GCC: - stage: build - - when: on_success - - image: alpine:3 - - allow_failure: 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" - -Alpine 3 GCC Dedicated: - extends: Alpine 3 GCC - - artifacts: - paths: - - "bin/" - - "src/comptime.h" - expose_as: "Apline-3-Dedicated" - name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-Apline-3-Dedicated" - - 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 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" - -osxcross x86_64: - stage: build - - 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: - - - | - # 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" - - - - | - # make - echo -e "\e[0Ksection_start:`date +%s`:make[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" - -osxcross arm64: - stage: build - - when: manual - - allow_failure: true - +default: + interruptible: 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" - - - - | - # make - echo -e "\e[0Ksection_start:`date +%s`:make[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" + expire_in: 1 day diff --git a/.gitlab/ci/jobs/alpine-3-gcc-dedicated.yml b/.gitlab/ci/jobs/alpine-3-gcc-dedicated.yml new file mode 100644 index 0000000000000000000000000000000000000000..242ddd0eaa3f0e45504fa0fe258e08c63e0845df --- /dev/null +++ b/.gitlab/ci/jobs/alpine-3-gcc-dedicated.yml @@ -0,0 +1,34 @@ +Alpine 3 GCC Dedicated: + extends: Alpine 3 GCC + + artifacts: + paths: + - "bin/" + - "src/comptime.h" + expose_as: "Apline-3-Dedicated" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-Apline-3-Dedicated" + + 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 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.yml b/.gitlab/ci/jobs/alpine-3-gcc.yml new file mode 100644 index 0000000000000000000000000000000000000000..b3b12e40167a568e3ced2abc7a09ed0045e0cc99 --- /dev/null +++ b/.gitlab/ci/jobs/alpine-3-gcc.yml @@ -0,0 +1,135 @@ +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: + - "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" diff --git a/.gitlab/ci/jobs/batocera-arm64.yml b/.gitlab/ci/jobs/batocera-arm64.yml new file mode 100644 index 0000000000000000000000000000000000000000..3e43aa8753a0a1500abdc52e9f594863bd4b3691 --- /dev/null +++ b/.gitlab/ci/jobs/batocera-arm64.yml @@ -0,0 +1,38 @@ +batocera:arm64: + extends: Debian stable:arm64 + + when: manual + + allow_failure: true + + artifacts: + paths: + - "bin/" + - "src/comptime.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" + + - - | + # 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-amd64.yml b/.gitlab/ci/jobs/debian-oldstable-amd64.yml new file mode 100644 index 0000000000000000000000000000000000000000..3929ecdcd10f8f448072d2c859de6a7dd31d94c7 --- /dev/null +++ b/.gitlab/ci/jobs/debian-oldstable-amd64.yml @@ -0,0 +1,40 @@ +Debian oldstable:amd64: + extends: Debian stable:amd64 + + 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" + 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" + + - - | + # 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-arm64.yml b/.gitlab/ci/jobs/debian-oldstable-arm64.yml new file mode 100644 index 0000000000000000000000000000000000000000..b18d538cd0824041650f3f8a5361b7b07c85f206 --- /dev/null +++ b/.gitlab/ci/jobs/debian-oldstable-arm64.yml @@ -0,0 +1,40 @@ +Debian oldstable:arm64: + extends: Debian stable:arm64 + + 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" + 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" + + - - | + # 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-stable-amd64.yml b/.gitlab/ci/jobs/debian-stable-amd64.yml new file mode 100644 index 0000000000000000000000000000000000000000..4a757afe0d519f268bb4541cda49ba03a3181600 --- /dev/null +++ b/.gitlab/ci/jobs/debian-stable-amd64.yml @@ -0,0 +1,45 @@ +Debian stable:amd64: + extends: .srb2ci + + stage: build + + artifacts: + paths: + - "bin/" + - "src/comptime.h" + expose_as: "Debian amd64" + name: "$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA-x86-64" + + variables: + CC: x86_64-linux-gnu-gcc + LDFLAGS: -Wl,-fuse-ld=gold + OBJCOPY: x86_64-linux-gnu-objcopy + OBJDUMP: x86_64-linux-gnu-objdump + PKG_CONFIG_PATH: /usr/lib/x86_64-linux-gnu/pkgconfig + + 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-arm64.yml b/.gitlab/ci/jobs/debian-stable-arm64.yml new file mode 100644 index 0000000000000000000000000000000000000000..879391affebe7586e019e7bb7f8d77a0599983e2 --- /dev/null +++ b/.gitlab/ci/jobs/debian-stable-arm64.yml @@ -0,0 +1,45 @@ +Debian stable:arm64: + extends: .srb2ci + + 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" 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.yml b/.gitlab/ci/jobs/debian-stable-i386.yml new file mode 100644 index 0000000000000000000000000000000000000000..cd6206e55e9a497d7065d3ea652c1ed3c6bd8d23 --- /dev/null +++ b/.gitlab/ci/jobs/debian-stable-i386.yml @@ -0,0 +1,44 @@ +Debian stable:i386: + extends: .srb2ci + + 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" 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.yml b/.gitlab/ci/jobs/debian-testing-gcc-amd64.yml new file mode 100644 index 0000000000000000000000000000000000000000..10799b3053e45a3d98fcfa1f63281e36ebadae9d --- /dev/null +++ b/.gitlab/ci/jobs/debian-testing-gcc-amd64.yml @@ -0,0 +1,46 @@ +Debian testing GCC: + extends: .srb2ci + + 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" diff --git a/.gitlab/ci/jobs/macos-arm64.yml b/.gitlab/ci/jobs/macos-arm64.yml new file mode 100644 index 0000000000000000000000000000000000000000..3928413610a048460dfe05d0dfc8f92e9da76848 --- /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_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..818028e49a43624f3e29a357d7d7614ef4dd5118 --- /dev/null +++ b/.gitlab/ci/jobs/macos-x86_64.yml @@ -0,0 +1,40 @@ +osxcross x86_64: + extends: .srb2ci + + stage: build + + 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: + - - | + # 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" diff --git a/.gitlab/ci/jobs/windows-x64.yml b/.gitlab/ci/jobs/windows-x64.yml new file mode 100644 index 0000000000000000000000000000000000000000..da8d960bd1330229a2265ed9b015a487f1040e75 --- /dev/null +++ b/.gitlab/ci/jobs/windows-x64.yml @@ -0,0 +1,35 @@ +Windows x64: + extends: .srb2ci + + stage: build + + when: manual + + allow_failure: true + + 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" diff --git a/.gitlab/ci/jobs/windows-x86.yml b/.gitlab/ci/jobs/windows-x86.yml new file mode 100644 index 0000000000000000000000000000000000000000..311c767bbd9cd31d1063a248f68c0a6793dd47d5 --- /dev/null +++ b/.gitlab/ci/jobs/windows-x86.yml @@ -0,0 +1,35 @@ +Windows x86: + extends: .srb2ci + + 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 + 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/templates/srb2ci.yml b/.gitlab/ci/templates/srb2ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..3716d9df921407cb29081af301a5b6a3d92db459 --- /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" + - 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 358e62cc4d5bb72631cbcbe50f7b512a1e97da2a..3b08a9facc348aad76f77b55a5700b8929859333 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,6 @@ endif() set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") include(CMakeDependentOption) -include(cmake/CPM.cmake) file(STRINGS src/version.h SRB2_VERSION) string(REGEX MATCH "[0-9]+\\.[0-9.]+" SRB2_VERSION ${SRB2_VERSION}) @@ -46,28 +45,23 @@ 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) @@ -82,63 +76,27 @@ option(SRB2_CONFIG_ZDEBUG "Compile with ZDEBUG defined." OFF) option(SRB2_CONFIG_PROFILEMODE "Compile for profiling (GCC only)." OFF) set(SRB2_CONFIG_ASSET_DIRECTORY "" CACHE PATH "Path to directory that contains all asset files for the installer. If set, assets will be part of installation and cpack.") -if(SRB2_CONFIG_ENABLE_TESTS) - # https://github.com/catchorg/Catch2 - CPMAddPackage( - NAME Catch2 - VERSION 3.4.0 - GITHUB_REPOSITORY catchorg/Catch2 - OPTIONS - "CATCH_INSTALL_DOCS OFF" - ) - list(APPEND CMAKE_MODULE_PATH "${Catch2_SOURCE_DIR}/extras") - include(CTest) - include(Catch) - add_executable(srb2tests) - # To add tests, use target_sources to add individual test files to the target in subdirs. - target_link_libraries(srb2tests PRIVATE Catch2::Catch2 Catch2::Catch2WithMain) - target_compile_features(srb2tests PRIVATE c_std_11 cxx_std_17) - catch_discover_tests(srb2tests) -endif() +# 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/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..d7de22134831c1e0edc8b3b6e62ed42abd69287f --- /dev/null +++ b/cmake/Modules/Findlibopenmpt.cmake @@ -0,0 +1,37 @@ +include(LibFindMacros) + +libfind_pkg_check_modules(libopenmpt_PKGCONF openmpt) + +find_path(libopenmpt_INCLUDE_DIR + NAMES libopenmpt.h + PATHS + ${libopenmpt_PKGCONF_INCLUDE_DIRS} + "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/include/libopenmpt" + "/usr/include/libopenmpt" + "/usr/local/include/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/doc/specs/udmf_srb2.txt b/doc/specs/udmf_srb2.txt index c758d7e40f13d466afcfc689c679845fec71b906..d6d71a0d5f7217482422799a4e521714e604b204 100644 --- a/doc/specs/udmf_srb2.txt +++ b/doc/specs/udmf_srb2.txt @@ -126,7 +126,7 @@ Sonic Robo Blast 2 defines the following standardized fields: texturebottom = <string>; // Lower texture. Default = "-". texturemiddle = <string>; // Middle texture. Default = "-". - repeatcnt = <string>; // Number of middle texture repetitions. Default = 0 + repeatcnt = <integer>; // Number of middle texture repetitions. Default = 0. sector = <integer>; // Sector index. No valid default. @@ -228,6 +228,8 @@ Sonic Robo Blast 2 defines the following standardized fields: 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. diff --git a/extras/conf/udb/Includes/SRB222_common.cfg b/extras/conf/udb/Includes/SRB222_common.cfg index aee7a70e4e0a4b806d8c0a055d77f06fce476ea6..90c85cdea40827970a7b44222e9a2f6a5e2668f6 100644 --- a/extras/conf/udb/Includes/SRB222_common.cfg +++ b/extras/conf/udb/Includes/SRB222_common.cfg @@ -39,6 +39,7 @@ common defaulttexturescale = 1.0f; defaultflatscale = 1.0f; scaledtextureoffsets = true; + scaledflatoffsets = true; // Colormap/fade related options maxcolormapalpha = 25; diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg index e297f473fd46d2848f3835765988bb913147e84f..fc505fb6025b02782d1a309b247f569a63dd96fd 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,20 +87,17 @@ udmf 40 { title = "Visual Portal Between Tagged Linedefs"; - prefix = "(40)"; } 41 { title = "Horizon Effect"; id = "srb2_horizonline"; - prefix = "(41)"; } 63 { title = "Fake Floor/Ceiling Planes"; - prefix = "(63)"; arg0 { title = "Target sector tag"; @@ -120,7 +113,6 @@ udmf 2 { title = "Custom Exit"; - prefix = "(2)"; arg0 { title = "Next map"; @@ -144,7 +136,6 @@ udmf 3 { title = "Zoom Tube Parameters"; - prefix = "(3)"; arg0 { title = "Speed"; @@ -166,7 +157,6 @@ udmf 4 { title = "Speed Pad Parameters"; - prefix = "(4)"; arg0 { title = "Speed"; @@ -193,7 +183,6 @@ udmf 8 { title = "Set Camera Collision Planes"; - prefix = "(8)"; arg0 { title = "Target sector tag"; @@ -204,7 +193,6 @@ udmf 11 { title = "Rope Hang Parameters"; - prefix = "(11)"; arg0 { title = "Speed"; @@ -226,7 +214,6 @@ udmf 14 { title = "Bustable Block Parameters"; - prefix = "(14)"; arg0 { title = "Debris spacing"; @@ -252,13 +239,11 @@ udmf 15 { title = "Fan Particle Generator Heights"; - prefix = "(15)"; } 16 { title = "Minecart Parameters"; - prefix = "(16)"; arg0 { title = "Order"; @@ -268,7 +253,6 @@ udmf 64 { title = "Continuously Appearing/Disappearing FOF"; - prefix = "(64)"; arg0 { title = "Control linedef tag"; @@ -307,7 +291,6 @@ udmf 20 { title = "PolyObject First Line"; - prefix = "(20)"; arg0 { title = "PolyObject tag"; @@ -348,7 +331,6 @@ udmf 30 { title = "Waving PolyObject Flag"; - prefix = "(30)"; arg0 { title = "PolyObject tag"; @@ -369,7 +351,6 @@ udmf 31 { title = "Move PolyObject by Front Sector Displacement"; - prefix = "(31)"; arg0 { title = "PolyObject tag"; @@ -385,7 +366,6 @@ udmf 32 { title = "Rotate PolyObject by Front Sector Displacement"; - prefix = "(32)"; arg0 { title = "PolyObject tag"; @@ -421,7 +401,6 @@ udmf 52 { title = "Continuously Falling Sector"; - prefix = "(52)"; arg0 { title = "Speed"; @@ -442,7 +421,6 @@ udmf 53 { title = "Continuous Plane Mover (Slowdown)"; - prefix = "(53)"; arg0 { title = "Target sector tag"; @@ -477,7 +455,6 @@ udmf 56 { title = "Continuous Plane Mover (Constant)"; - prefix = "(56)"; arg0 { title = "Target sector tag"; @@ -512,7 +489,6 @@ udmf 60 { title = "Activate Moving Platform"; - prefix = "(60)"; arg0 { title = "Target sector tag"; @@ -542,7 +518,6 @@ udmf 61 { title = "Ceiling Crusher"; - prefix = "(61)"; arg0 { title = "Target sector tag"; @@ -573,7 +548,6 @@ udmf 66 { title = "Move Planes by Front Sector Displacement"; - prefix = "(66)"; arg0 { title = "Target sector tag"; @@ -600,7 +574,6 @@ udmf 70 { title = "Add Raise Thinker"; - prefix = "(70)"; arg0 { title = "Control linedef tag"; @@ -626,7 +599,6 @@ udmf 71 { title = "Add Air Bobbing Thinker"; - prefix = "(71)"; arg0 { title = "Control linedef tag"; @@ -652,7 +624,6 @@ udmf 72 { title = "Add Thwomp Thinker"; - prefix = "(72)"; arg0 { title = "Control linedef tag"; @@ -679,7 +650,6 @@ udmf 73 { title = "Add Laser Thinker"; - prefix = "(73)"; arg0 { title = "Control linedef tag"; @@ -696,7 +666,6 @@ udmf 74 { title = "Make FOF Bustable"; - prefix = "(74)"; arg0 { title = "Control linedef tag"; @@ -735,7 +704,6 @@ udmf 75 { title = "Make FOF Quicksand"; - prefix = "(75)"; arg0 { title = "Control linedef tag"; @@ -755,7 +723,6 @@ udmf 76 { title = "Make FOF Bouncy"; - prefix = "(76)"; arg0 { title = "Control linedef tag"; @@ -775,7 +742,6 @@ udmf 100 { title = "Solid"; - prefix = "(100)"; id = "srb2_fofsolid"; arg0 { @@ -819,7 +785,6 @@ udmf 120 { title = "Water"; - prefix = "(120)"; id = "srb2_fofwater"; arg0 { @@ -857,7 +822,6 @@ udmf 150 { title = "Air Bobbing"; - prefix = "(150)"; id = "srb2_fofsolidopaque"; arg0 { @@ -884,7 +848,6 @@ udmf 160 { title = "Water Bobbing"; - prefix = "(160)"; id = "srb2_fofsolidopaque"; arg0 { @@ -896,7 +859,6 @@ udmf 170 { title = "Crumbling"; - prefix = "(170)"; id = "srb2_fofcrumbling"; arg0 { @@ -939,7 +901,6 @@ udmf 190 { title = "Rising"; - prefix = "(190)"; id = "srb2_fofsolid"; arg0 { @@ -998,7 +959,6 @@ udmf 200 { title = "Light Block"; - prefix = "(200)"; id = "srb2_foflight"; arg0 { @@ -1016,7 +976,6 @@ udmf 202 { title = "Fog Block"; - prefix = "(202)"; id = "srb2_foffog"; arg0 { @@ -1028,7 +987,6 @@ udmf 220 { title = "Intangible"; - prefix = "(220)"; id = "srb2_fofintangible"; arg0 { @@ -1066,7 +1024,6 @@ udmf 223 { title = "Intangible, Invisible"; - prefix = "(223)"; id = "srb2_fofintangibleinvisible"; arg0 { @@ -1078,7 +1035,6 @@ udmf 250 { title = "Mario Block"; - prefix = "(250)"; id = "srb2_fofsolidopaque"; arg0 { @@ -1100,7 +1056,6 @@ udmf 251 { title = "Thwomp Block"; - prefix = "(251)"; id = "srb2_fofsolidopaque"; arg0 { @@ -1128,7 +1083,6 @@ udmf 254 { title = "Bustable Block"; - prefix = "(254)"; id = "srb2_fofbustable"; arg0 { @@ -1181,7 +1135,6 @@ udmf 257 { title = "Quicksand"; - prefix = "(257)"; id = "srb2_fofsolidopaque"; arg0 { @@ -1208,7 +1161,6 @@ udmf 258 { title = "Laser"; - prefix = "(258)"; id = "srb2_foflaser"; arg0 { @@ -1242,7 +1194,6 @@ udmf 259 { title = "Custom"; - prefix = "(259)"; id = "srb2_fofcustom"; arg0 { @@ -1307,7 +1258,6 @@ udmf 300 { title = "Basic"; - prefix = "(300)"; arg0 { title = "Trigger type"; @@ -1319,7 +1269,6 @@ udmf 303 { title = "Ring Count"; - prefix = "(303)"; arg0 { title = "Trigger type"; @@ -1347,7 +1296,6 @@ udmf 305 { title = "Character Ability"; - prefix = "(305)"; arg0 { title = "Trigger type"; @@ -1383,7 +1331,6 @@ udmf 308 { title = "Gametype"; - prefix = "(308)"; arg0 { title = "Trigger type"; @@ -1441,7 +1388,6 @@ udmf 309 { title = "CTF Team"; - prefix = "(309)"; arg0 { title = "Trigger type"; @@ -1459,7 +1405,6 @@ udmf 313 { title = "No More Enemies"; - prefix = "(313)"; arg0 { title = "Target sector tag"; @@ -1470,7 +1415,6 @@ udmf 314 { title = "Number of Pushables"; - prefix = "(314)"; arg0 { title = "Trigger type"; @@ -1492,7 +1436,6 @@ udmf 317 { title = "Condition Set Trigger"; - prefix = "(317)"; arg0 { title = "Trigger type"; @@ -1508,7 +1451,6 @@ udmf 319 { title = "Unlockable"; - prefix = "(319)"; arg0 { title = "Trigger type"; @@ -1524,7 +1466,6 @@ udmf 321 { title = "Trigger After X Calls"; - prefix = "(321)"; arg0 { title = "Trigger type"; @@ -1550,7 +1491,6 @@ udmf 323 { title = "NiGHTSerize"; - prefix = "(323)"; arg0 { title = "Trigger type"; @@ -1617,7 +1557,6 @@ udmf 325 { title = "De-NiGHTSerize"; - prefix = "(325)"; arg0 { title = "Trigger type"; @@ -1680,7 +1619,6 @@ udmf 327 { title = "NiGHTS Lap"; - prefix = "(327)"; arg0 { title = "Trigger type"; @@ -1732,7 +1670,6 @@ udmf 329 { title = "Ideya Capture Touch"; - prefix = "(329)"; arg0 { title = "Trigger type"; @@ -1800,7 +1737,6 @@ udmf 331 { title = "Player Skin"; - prefix = "(331)"; arg0 { title = "Trigger type"; @@ -1823,7 +1759,6 @@ udmf 334 { title = "Object Dye"; - prefix = "(334)"; arg0 { title = "Trigger type"; @@ -1846,7 +1781,6 @@ udmf 337 { title = "Emerald Check"; - prefix = "(337)"; arg0 { title = "Trigger type"; @@ -1879,7 +1813,6 @@ udmf 340 { title = "NiGHTS Mare"; - prefix = "(340)"; arg0 { title = "Trigger type"; @@ -1901,7 +1834,6 @@ udmf 343 { title = "Gravity Check"; - prefix = "(343)"; arg0 { title = "Trigger type"; @@ -1924,7 +1856,6 @@ udmf 399 { title = "Level Load"; - prefix = "(399)"; } } @@ -1935,7 +1866,6 @@ udmf 400 { title = "Set Tagged Sector's Heights/Textures"; - prefix = "(400)"; arg0 { title = "Target sector tag"; @@ -1958,7 +1888,6 @@ udmf 402 { title = "Copy Light Level to Tagged Sectors"; - prefix = "(402)"; arg0 { title = "Target sector tag"; @@ -1980,7 +1909,6 @@ udmf 408 { title = "Set Tagged Sector's Flats"; - prefix = "(408)"; arg0 { title = "Target sector tag"; @@ -1997,7 +1925,6 @@ udmf 409 { title = "Change Tagged Sector's Tag"; - prefix = "(409)"; arg0 { title = "Target sector tag"; @@ -2025,7 +1952,6 @@ udmf 410 { title = "Change Front Sector's Tag"; - prefix = "(410)"; arg0 { title = "Tag"; @@ -2048,7 +1974,6 @@ udmf 416 { title = "Start Adjustable Flickering Light"; - prefix = "(416)"; arg0 { title = "Target sector tag"; @@ -2077,7 +2002,6 @@ udmf 417 { title = "Start Adjustable Pulsating Light"; - prefix = "(417)"; arg0 { title = "Target sector tag"; @@ -2106,7 +2030,6 @@ udmf 418 { title = "Start Adjustable Blinking Light"; - prefix = "(418)"; arg0 { title = "Target sector tag"; @@ -2143,7 +2066,6 @@ udmf 420 { title = "Fade Light Level"; - prefix = "(420)"; arg0 { title = "Target sector tag"; @@ -2173,7 +2095,6 @@ udmf 421 { title = "Stop Lighting Effect"; - prefix = "(421)"; arg0 { title = "Target sector tag"; @@ -2184,7 +2105,6 @@ udmf 435 { title = "Change Plane Scroller Direction"; - prefix = "(435)"; arg0 { title = "Target sector tag"; @@ -2200,7 +2120,6 @@ udmf 467 { title = "Set Tagged Sector's Light Level"; - prefix = "(467)"; arg0 { title = "Target sector tag"; @@ -2232,7 +2151,6 @@ udmf 469 { title = "Change Tagged Sector's Gravity"; - prefix = "(469)"; arg0 { title = "Target sector tag"; @@ -2284,7 +2202,6 @@ udmf 403 { title = "Move Tagged Sector's Planes"; - prefix = "(403)"; arg0 { title = "Target sector tag"; @@ -2317,7 +2234,6 @@ udmf 405 { title = "Move Planes by Set Distance"; - prefix = "(405)"; arg0 { title = "Target sector tag"; @@ -2349,7 +2265,6 @@ udmf 411 { title = "Stop Plane Movement"; - prefix = "(411)"; arg0 { title = "Target sector tag"; @@ -2360,7 +2275,6 @@ udmf 428 { title = "Start Platform Movement"; - prefix = "(428)"; arg0 { title = "Target sector tag"; @@ -2394,7 +2308,6 @@ udmf 429 { title = "Crush Planes Once"; - prefix = "(429)"; arg0 { title = "Target sector tag"; @@ -2426,7 +2339,6 @@ udmf 412 { title = "Teleporter"; - prefix = "(412)"; arg0 { title = "Destination thing tag"; @@ -2461,7 +2373,6 @@ udmf 425 { title = "Change Object State"; - prefix = "(425)"; stringarg0 { title = "State"; @@ -2472,7 +2383,6 @@ udmf 426 { title = "Stop Object"; - prefix = "(426)"; arg0 { title = "Move to center?"; @@ -2484,7 +2394,6 @@ udmf 427 { title = "Award Score"; - prefix = "(427)"; arg0 { title = "Score"; @@ -2494,7 +2403,6 @@ udmf 432 { title = "Enable/Disable 2D Mode"; - prefix = "(432)"; arg0 { title = "Mode"; @@ -2510,7 +2418,6 @@ udmf 433 { title = "Enable/Disable Gravity Flip"; - prefix = "(433)"; arg0 { title = "Set gravity"; @@ -2546,7 +2453,6 @@ udmf 434 { title = "Award Power-Up"; - prefix = "(434)"; stringarg0 { title = "Power"; @@ -2562,7 +2468,6 @@ udmf 437 { title = "Disable Player Control"; - prefix = "(437)"; arg0 { title = "Time"; @@ -2578,7 +2483,6 @@ udmf 438 { title = "Change Object Size"; - prefix = "(438)"; arg0 { title = "Size (%)"; @@ -2589,7 +2493,6 @@ udmf 442 { title = "Change Object Type State"; - prefix = "(442)"; arg0 { title = "Target sector tag"; @@ -2620,7 +2523,6 @@ udmf 457 { title = "Track Object's Angle"; - prefix = "(457)"; arg0 { title = "Anchor tag"; @@ -2651,13 +2553,11 @@ udmf 458 { title = "Stop Tracking Object's Angle"; - prefix = "(458)"; } 460 { title = "Award Rings"; - prefix = "(460)"; arg0 { title = "Rings"; @@ -2671,7 +2571,6 @@ udmf 461 { title = "Spawn Object"; - prefix = "(461)"; arg0 { title = "X position"; @@ -2717,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"; @@ -2734,7 +2631,6 @@ udmf 464 { title = "Trigger Egg Capsule"; - prefix = "(464)"; arg0 { title = "Egg Capsule tag"; @@ -2751,7 +2647,6 @@ udmf 466 { title = "Set Level Failure State"; - prefix = "(466)"; arg0 { title = "State"; @@ -2772,7 +2667,6 @@ udmf 413 { title = "Change Music"; - prefix = "(413)"; arg0 { title = "Flags"; @@ -2823,7 +2717,6 @@ udmf 414 { title = "Play Sound Effect"; - prefix = "(414)"; arg0 { title = "Source"; @@ -2863,7 +2756,6 @@ udmf 415 { title = "Run Script"; - prefix = "(415)"; stringarg0 { title = "Lump name"; @@ -2874,7 +2766,6 @@ udmf 422 { title = "Switch to Cut-Away View"; - prefix = "(422)"; arg0 { title = "Viewpoint tag"; @@ -2889,7 +2780,6 @@ udmf 423 { title = "Change Sky"; - prefix = "(423)"; arg0 { title = "Sky number"; @@ -2905,7 +2795,6 @@ udmf 424 { title = "Change Weather"; - prefix = "(424)"; arg0 { title = "Weather"; @@ -2932,7 +2821,6 @@ udmf 436 { title = "Shatter FOF"; - prefix = "(436)"; arg0 { title = "Target sector tag"; @@ -2948,7 +2836,6 @@ udmf 439 { title = "Change Tagged Linedef's Textures"; - prefix = "(439)"; arg0 { title = "Target linedef tag"; @@ -2977,13 +2864,11 @@ udmf 440 { title = "Start Metal Sonic Race"; - prefix = "(440)"; } 441 { title = "Condition Set Trigger"; - prefix = "(441)"; arg0 { title = "Trigger number"; @@ -2993,7 +2878,6 @@ udmf 443 { title = "Call Lua Function"; - prefix = "(443)"; stringarg0 { title = "Function name"; @@ -3004,7 +2888,6 @@ udmf 444 { title = "Earthquake"; - prefix = "(444)"; arg0 { title = "Duration"; @@ -3018,7 +2901,6 @@ udmf 445 { title = "Make FOF Disappear/Reappear"; - prefix = "(445)"; arg0 { title = "Target sector tag"; @@ -3044,7 +2926,6 @@ udmf 446 { title = "Make FOF Crumble"; - prefix = "(446)"; arg0 { title = "Target sector tag"; @@ -3072,7 +2953,6 @@ udmf 447 { title = "Change Tagged Sector's Colormap"; - prefix = "(447)"; arg0 { title = "Target sector tag"; @@ -3108,7 +2988,6 @@ udmf 448 { title = "Change Skybox"; - prefix = "(448)"; arg0 { title = "Viewpoint thing tag"; @@ -3139,7 +3018,6 @@ udmf 449 { title = "Enable Bosses with Parameter"; - prefix = "(449)"; arg0 { title = "Boss ID"; @@ -3159,7 +3037,6 @@ udmf 450 { title = "Execute Linedef Executor (specific tag)"; - prefix = "(450)"; arg0 { title = "Trigger linedef tag"; @@ -3170,7 +3047,6 @@ udmf 451 { title = "Execute Linedef Executor (random tag in range)"; - prefix = "(451)"; arg0 { title = "Start of tag range"; @@ -3186,7 +3062,6 @@ udmf 452 { title = "Set FOF Translucency"; - prefix = "(452)"; arg0 { title = "Target sector tag"; @@ -3217,7 +3092,6 @@ udmf 453 { title = "Fade FOF"; - prefix = "(453)"; arg0 { title = "Target sector tag"; @@ -3260,7 +3134,6 @@ udmf 454 { title = "Stop Fading FOF"; - prefix = "(454)"; arg0 { title = "Target sector tag"; @@ -3282,7 +3155,6 @@ udmf 455 { title = "Fade Tagged Sector's Colormap"; - prefix = "(455)"; arg0 { title = "Target sector tag"; @@ -3324,7 +3196,6 @@ udmf 456 { title = "Stop Fading Tagged Sector's Colormap"; - prefix = "(456)"; arg0 { title = "Target sector tag"; @@ -3335,7 +3206,6 @@ udmf 459 { title = "Control Text Prompt"; - prefix = "(459)"; arg0 { title = "Prompt number"; @@ -3371,7 +3241,6 @@ udmf 465 { title = "Set Linedef Executor Delay"; - prefix = "(465)"; arg0 { title = "Linedef tag"; @@ -3392,7 +3261,6 @@ udmf 468 { title = "Change Linedef Argument"; - prefix = "(468)"; arg0 { title = "Linedef tag"; @@ -3422,7 +3290,6 @@ udmf 480 { title = "PolyObject Door Slide"; - prefix = "(480)"; arg0 { title = "PolyObject tag"; @@ -3446,7 +3313,6 @@ udmf 481 { title = "PolyObject Door Swing"; - prefix = "(481)"; arg0 { title = "PolyObject tag"; @@ -3471,7 +3337,6 @@ udmf 482 { title = "Move PolyObject"; - prefix = "(482)"; arg0 { title = "PolyObject tag"; @@ -3497,7 +3362,6 @@ udmf 484 { title = "Rotate PolyObject"; - prefix = "(484)"; arg0 { title = "PolyObject tag"; @@ -3531,7 +3395,6 @@ udmf 488 { title = "Move PolyObject by Waypoints"; - prefix = "(488)"; arg0 { title = "PolyObject tag"; @@ -3573,7 +3436,6 @@ udmf 489 { title = "Set PolyObject Visibility/Tangibility"; - prefix = "(489)"; arg0 { title = "PolyObject tag"; @@ -3606,7 +3468,6 @@ udmf 491 { title = "Set PolyObject Translucency"; - prefix = "(491)"; arg0 { title = "PolyObject tag"; @@ -3628,7 +3489,6 @@ udmf 492 { title = "Fade PolyObject Translucency"; - prefix = "(492)"; arg0 { title = "PolyObject tag"; @@ -3666,7 +3526,6 @@ udmf 500 { title = "Scroll Wall"; - prefix = "(500)"; arg0 { title = "Side"; @@ -3686,7 +3545,6 @@ udmf 502 { title = "Scroll Tagged Walls"; - prefix = "(502)"; arg0 { title = "Linedef tag"; @@ -3717,7 +3575,6 @@ udmf 510 { title = "Scroll Planes"; - prefix = "(510)"; arg0 { title = "Sector tag"; @@ -3755,7 +3612,6 @@ udmf 541 { title = "Wind/Current"; - prefix = "(541)"; arg0 { title = "Sector tag"; @@ -3800,7 +3656,6 @@ udmf 600 { title = "Copy Light Level to Tagged Sector's Planes"; - prefix = "(600)"; arg0 { title = "Target sector tag"; @@ -3817,7 +3672,6 @@ udmf 602 { title = "Adjustable Pulsating Light"; - prefix = "(602)"; arg0 { title = "Target sector tag"; @@ -3846,7 +3700,6 @@ udmf 603 { title = "Adjustable Flickering Light"; - prefix = "(603)"; arg0 { title = "Target sector tag"; @@ -3875,7 +3728,6 @@ udmf 604 { title = "Adjustable Blinking Light"; - prefix = "(604)"; arg0 { title = "Target sector tag"; @@ -3912,7 +3764,6 @@ udmf 606 { title = "Copy Colormap"; - prefix = "(606)"; arg0 { title = "Target sector tag"; @@ -3933,7 +3784,6 @@ udmf 700 { title = "Create Sector-Based Slope"; - prefix = "(700)"; id = "plane_align"; arg0 { @@ -3963,7 +3813,6 @@ udmf 704 { title = "Create Vertex-Based Slope"; - prefix = "(704)"; id = "srb2_vertexslope"; arg0 { @@ -4007,7 +3856,6 @@ udmf 720 { title = "Copy Slope"; - prefix = "(720)"; id = "plane_copy"; arg0 { @@ -4046,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 405d043c140995b4ed840528878cc6eda7c53346..37b01d7dd56eadaeb1eb3ae4759fb74efc79e61f 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"; @@ -586,6 +590,12 @@ universalfields 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 990f8dca9f505b57f1797c49ed0d8ae003d18d5d..c028f9439c493d156e1ded87f7a116cc4b14d9d7 100644 --- a/extras/conf/udb/Includes/SRB222_things.cfg +++ b/extras/conf/udb/Includes/SRB222_things.cfg @@ -3938,6 +3938,7 @@ udmf width = 30; height = 32; color = 17; + hangs = 1; arg0 { title = "Initial delay"; 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/src/CMakeLists.txt b/src/CMakeLists.txt index 486f4e913057af02c22a6acd6c554bd7b76801b3..20caecf7bd6a65a20631318799016da319d3f13d 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) @@ -182,12 +185,7 @@ if("${SRB2_CONFIG_USE_GME}") 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) @@ -403,8 +401,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/b_bot.c b/src/b_bot.c index af57d65ecf6e3c24e725ed38b9533b9ab6509763..6229cb1d61893b328e667ba357fbbefe333e51f4 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -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))) diff --git a/src/console.c b/src/console.c index b12a1ab846a26546a73ddea3580c8f086a37f7db..0c3eac4f793854dad336dc641a73874cea74d510 100644 --- a/src/console.c +++ b/src/console.c @@ -922,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]; @@ -943,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"); @@ -980,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; } @@ -1036,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(); @@ -1094,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); @@ -1104,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); @@ -1707,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); } } @@ -1730,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); diff --git a/src/d_main.c b/src/d_main.c index c139650d1eb039a057da10d063f392f33c94fac2..2405b01365ba8c47f4e54036839e7e704b6aaa4b 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -758,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)); } @@ -983,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 @@ -1842,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 098b4485ca5e602328a4b03b5e0c6719fe6d154b..95d2f609dab322189fcb3892d7beace6d0fd45dc 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -373,6 +373,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 +582,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 +598,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; diff --git a/src/dedicated/i_system.c b/src/dedicated/i_system.c index 858dfaf20234cb6898ffe008bce3c3f76e8b950b..413b366b865c035a08ece29008c30004ea58666e 100644 --- a/src/dedicated/i_system.c +++ b/src/dedicated/i_system.c @@ -1585,5 +1585,15 @@ void I_GetCursorPosition(INT32 *x, INT32 *y) (void)y; } +void I_SetTextInputMode(boolean active) +{ + (void)active; +} + +boolean I_GetTextInputMode(void) +{ + return false; +} + #include "../sdl/dosstr.c" diff --git a/src/deh_lua.c b/src/deh_lua.c index c056db82a7ca65c7bb9c1ba363708ce5880d253f..64fb52fc7423a7486c9d6736762fedd0fcde64ba 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -59,24 +59,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); @@ -455,17 +450,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)) { @@ -738,18 +735,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 beaf7cbf0cd4f861ce413fc9c504755a2b4965e8..dda3b2ef4b31352b1579623421cdc2733da56585 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -405,7 +405,6 @@ void readfreeslots(MYFILE *f) { char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); char *word,*type; - char *tmp; int i; do @@ -415,10 +414,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 +442,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; @@ -1543,6 +1543,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")) { @@ -4176,9 +4182,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 93a70b779c8c4c62e56a93dc1c78dc123bf51650..f113f6b19c8eb8b0a9c511406778db8bebd2e81d 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -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 @@ -5096,6 +5096,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}, @@ -5800,6 +5804,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..b6986adff0166c3132be5f70ca78c7835030998f 100644 --- a/src/deh_tables.h +++ b/src/deh_tables.h @@ -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/doomstat.h b/src/doomstat.h index c2fc963478b56682a03acf6d592398c134e861bc..bde2bacc72890d47b61a6085a26c5cda33dcfad0 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -335,6 +335,7 @@ typedef struct 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[8+1]; ///< Zig zag patch. diff --git a/src/doomtype.h b/src/doomtype.h index 4070e346a1b13dd516a91504f056cebc4defb20d..fa8616793e0aeab7bea18c77ef78a4520770b802 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -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 ecabe3576d3f15b06513315a945562076587aff5..99bfa9f363ca04c9281b17b0cffeda5cc4314586 100644 --- a/src/dummy/i_system.c +++ b/src/dummy/i_system.c @@ -211,5 +211,15 @@ 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/f_finale.c b/src/f_finale.c index c221ed52ffd3643d835848f98f30abc232c3b7da..810af4e82f3ea4f08d035b626a6afffef52a0467 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -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. @@ -2335,7 +2336,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); \ @@ -2349,7 +2350,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 \ @@ -3530,11 +3531,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) @@ -3557,9 +3563,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); @@ -3573,9 +3582,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) @@ -3595,6 +3607,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] - skins), 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]); } // @@ -3603,8 +3667,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*"; @@ -3649,7 +3711,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, (INT32)(&contskins[0] - skins), contColors[0]); V_DrawScaledPatch(x+12, 66, 0, stlivex); V_DrawRightAlignedString(x+38, 64, 0, va("%d",(imcontinuing ? ncontinues-1 : ncontinues))); @@ -3663,7 +3725,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, (INT32)(&contskins[0] - skins), contColors[0]); } x = BASEVIDWIDTH>>1; } @@ -3703,21 +3765,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)); @@ -3733,6 +3786,7 @@ void F_ContinueTicker(void) { if (!(--timetonext)) { + F_DestroyContinueDrawLists(); Command_ExitGame_f(); return; } @@ -3742,6 +3796,7 @@ void F_ContinueTicker(void) { if (++continuetime == 3*TICRATE) { + F_DestroyContinueDrawLists(); G_Continue(); return; } @@ -4061,7 +4116,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); @@ -4453,7 +4508,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/filesrch.c b/src/filesrch.c index 6429b6fa2f13b49979c7e5efa1614bf47cac02be..3a729a9c80ee4b80e7b1bcff9385f631651694d1 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -699,6 +699,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 +898,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; } @@ -1185,7 +1197,7 @@ boolean preparefilemenu(boolean samedepth) { 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 e445c4b5db017570095d97a2f805879954e96249..cfa34fc7e76c7978a52603fdd05f3e55d19f3e17 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -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 @@ -413,7 +415,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 @@ -513,7 +515,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); @@ -549,6 +551,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) @@ -575,7 +580,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! @@ -644,7 +649,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); @@ -664,11 +669,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) @@ -726,7 +734,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); @@ -941,7 +949,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); @@ -1056,7 +1064,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. @@ -1199,7 +1207,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); @@ -1207,7 +1215,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)) { @@ -1308,7 +1316,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 @@ -1383,7 +1391,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); @@ -2607,10 +2615,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; diff --git a/src/g_demo.h b/src/g_demo.h index e8c0c8d956187161ea5bbaffe9c145c764a40ba4..67f61f54de1166034d4376faa6ca340b39779e9d 100644 --- a/src/g_demo.h +++ b/src/g_demo.h @@ -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 8d19c9e7cb68df142e68e7d0277b2425153f9206..bf369d111bb2ea1da40514e1b2b6b5ad3845d0af 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1363,11 +1363,11 @@ 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 axis = PlayerJoyAxis(ssplayer, JA_SHIELD); if (PLAYERINPUTDOWN(ssplayer, GC_SHIELD) || (usejoystick && axis > 0)) @@ -1386,6 +1386,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_LEVEL) // not in a level, don't build anything else + { + 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 @@ -1420,7 +1427,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) { @@ -1435,6 +1442,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 ) @@ -1466,7 +1476,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) @@ -1714,7 +1724,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) // At this point, cmd doesn't contain the final angle yet, // So we need to temporarily transform it so Lua scripters // don't need to handle it differently than in other hooks. - if (addedtogame && gamestate == GS_LEVEL) + if (addedtogame) { INT16 extra = ticcmd_oldangleturn[forplayer] - player->oldrelangleturn; INT16 origangle = cmd->angleturn; @@ -4018,7 +4028,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) @@ -4122,7 +4132,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. @@ -4130,7 +4140,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; } @@ -4140,7 +4150,7 @@ INT16 G_GetNextMap(boolean ignoretokens, boolean silent) static void G_DoCompleted(void) { INT32 i; - + tokenlist = 0; // Reset the list if (modeattacking && pausedelay) @@ -4168,7 +4178,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. diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index bd8f316178dad3e48835e921c5cf7db0af734660..831c8d7c4bce2190311647ce4ec06ae7029593a3 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1533,14 +1533,14 @@ static void HWR_ProcessSeg(void) if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope)) continue; - side_t *side = R_GetFFloorSide(gl_curline, rover); + 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) { - line_t *newline = R_GetFFloorLine(gl_curline, rover); + 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; } @@ -1689,14 +1689,14 @@ static void HWR_ProcessSeg(void) if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope)) continue; - side_t *side = R_GetFFloorSide(gl_curline, rover); + 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) { - line_t *newline = R_GetFFloorLine(gl_curline, rover); + 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; } @@ -4364,9 +4364,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 @@ -5221,7 +5221,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; } @@ -5953,7 +5955,7 @@ void HWR_DoPostProcessor(player_t *player) if (*type == postimg_water) { WAVELENGTH = 5; - AMPLITUDE = 20; + AMPLITUDE = 40; FREQUENCY = 8; } else diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index ef0341bd5da7b73b5b9757a06a8eab2df521967f..0f466f051c6adc6f025444ca16e2bcb90b38ba71 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -571,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; } } @@ -1078,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; } @@ -1130,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; } @@ -1188,7 +1201,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; @@ -1256,6 +1269,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) 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; @@ -1418,18 +1432,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 { @@ -1449,13 +1473,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) @@ -1466,7 +1495,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; } @@ -1502,11 +1531,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) 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/hu_stuff.c b/src/hu_stuff.c index 13d499495535c4320aee7a498154cbfec9c256c2..d784c2358a82eecbff441d3e22d535b7b34ceaf5 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -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, 20); + 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. // @@ -1035,6 +999,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; @@ -1084,6 +1049,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; @@ -1095,6 +1061,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; @@ -1117,7 +1084,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; @@ -1169,6 +1136,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. :) @@ -1179,6 +1147,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(); @@ -1236,199 +1205,81 @@ 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; 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(chatx, boxw-charwidth, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, 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. - { - ++j; - if (!prev_linereturn) - { - linescount += 1; - dx = 0; - } - prev_linereturn = true; - continue; - } - else if (msg[j] & 0x80) // stolen from video.c, nice. - { - ++j; - continue; - } - - ++j; - } - else + if (msg[j] == '\n') // get back down. { - j++; + chatheight += charheight; + dx = 0; } - prev_linereturn = false; - dx += charwidth; - if (dx >= boxw) + else if (msg[j] >= FONTSTART) { - dx = 0; - linescount += 1; + dx += charwidth; + if (dx >= boxw) + { + dx = 0; + chatheight += charheight; + } } } - dy = 0; dx = 0; - msglines += linescount+1; + chatheight += charheight; if (msg) Z_Free(msg); } - y = chaty - charheight*(msglines+1); + y = chaty - (chatheight + charheight); - /*if (splitscreen) + for (size_t i = 0; i < chat_nummsg_min; i++) // iterate through our hot messages { - y -= BASEVIDHEIGHT/2; - if (splitscreen > 1) - y += 16; - }*/ - - dx = 0; - dy = 0; - i = 0; - prev_linereturn = false; - - for (; i<=(chat_nummsg_min-1); 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(chatx, boxw-charwidth, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, 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. - { - ++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; - } - - ++j; + dy += charheight; + dx = 0; } - else + else if (msg[j] & 0x80) // get colormap + colormap = V_GetStringColormap(((msg[j] & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK); + else if (msg[j] >= FONTSTART) { 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|transflag, true, colormap); - dx += charwidth; - prev_linereturn = false; - if (dx >= boxw) - { - dx = 0; - dy += charheight; + dx += charwidth; + if (dx >= boxw) + { + dx = 0; + dy += charheight; + } } } dy += charheight; @@ -1440,7 +1291,6 @@ static void HU_drawMiniChat(void) // decrement addy and make that shit smooth: addy /= 2; - } // HU_DrawChatLog @@ -1485,44 +1335,28 @@ 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(chatx, boxw-charwidth, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, 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. - { - ++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; + dy += charheight; + dx = 0; } - else + else if (msg[j] & 0x80) // get colormap + colormap = V_GetStringColormap(((msg[j] & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK); + else 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, true, colormap); - else - j++; // don't forget to increment this or we'll get stuck in the limbo. - } + V_DrawChatCharacter(x + dx + 2, y+dy+2, msg[j] |V_SNAPTOBOTTOM|V_SNAPTOLEFT, true, colormap); - 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; + 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; + } } } dy += charheight; @@ -1532,30 +1366,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; } // @@ -1587,15 +1416,7 @@ 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) { @@ -1609,16 +1430,10 @@ static void HU_DrawChat(void) 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; } @@ -1629,13 +1444,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)) @@ -1652,14 +1466,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; @@ -1681,8 +1492,7 @@ 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]) @@ -1697,32 +1507,16 @@ static void HU_DrawChat(void) 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]) @@ -1753,41 +1547,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. @@ -1795,17 +1570,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) @@ -1814,9 +1580,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. @@ -1902,21 +1665,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 // @@ -2267,13 +2015,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; @@ -2355,7 +2103,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) { @@ -2363,7 +2111,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) { @@ -2394,14 +2142,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; @@ -2778,7 +2526,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)) { diff --git a/src/hu_stuff.h b/src/hu_stuff.h index 9ca50e6e1b49e2b0f45b4e5d71a1fe70641693ca..ca77ed93002750d6cefa28584d8e4de7be3bfc65 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -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 //------------------------------------ @@ -78,22 +79,12 @@ 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 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 +94,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); diff --git a/src/i_system.h b/src/i_system.h index 3f0e05d127fa4ed5ce9aa8fbe89ff109773851f4..f4d169113c50b0ae5e2c1aca53b4d04f128658f4 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -339,4 +339,12 @@ void I_SetMouseGrab(boolean grab); */ 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/info.c b/src/info.c index 8dd1aac80679d17ae21b0fe43ad6b042d35ed627..d66c24af81aaafb851e6a83e699d2027add29cb5 100644 --- a/src/info.c +++ b/src/info.c @@ -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", @@ -525,7 +526,7 @@ char sprnames[NUMSPRITES + 1][5] = "GWLR", }; -char spr2names[NUMPLAYERSPRITES][5] = +char spr2names[NUMPLAYERSPRITES][MAXSPRITENAME + 1] = { "STND", "WAIT", @@ -691,3309 +692,3309 @@ 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|FF_ANIMATE, -1, {NULL}, 0, 16, S_NULL, 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_FANG, 30, 1, {A_ZThrust}, 9, (1<<16)|1, S_FANG_INTRO5, 0}, // S_FANG_INTRO4 + {SPR_FANG, 27, 1, {A_Boss5CheckOnGround}, S_FANG_INTRO9, 0, S_FANG_INTRO6, 0}, // S_FANG_INTRO5 + {SPR_FANG, 28, 1, {A_Boss5CheckOnGround}, S_FANG_INTRO9, 0, S_FANG_INTRO7, 0}, // S_FANG_INTRO6 + {SPR_FANG, 29, 1, {A_Boss5CheckOnGround}, S_FANG_INTRO9, 0, S_FANG_INTRO8, 0}, // S_FANG_INTRO7 + {SPR_FANG, 30, 1, {A_Boss5CheckOnGround}, S_FANG_INTRO9, 0, S_FANG_INTRO5, 0}, // S_FANG_INTRO8 + {SPR_FANG, 23|FF_ANIMATE, 50, {NULL}, 1, 4, S_FANG_INTRO10, 0}, // S_FANG_INTRO9 + {SPR_FANG, 25, 5, {NULL}, 0, 0, S_FANG_INTRO11, 0}, // S_FANG_INTRO10 + {SPR_FANG, 26, 2, {A_Boss5MakeJunk}, S_BROKENROBOTD, 2, S_FANG_INTRO12, 0}, // S_FANG_INTRO11 + {SPR_FANG, 31|FF_ANIMATE, 50, {NULL}, 3, 4, S_FANG_IDLE1, 0}, // S_FANG_INTRO12 + + {SPR_FANG, 11, 2, {A_Boss5MakeJunk}, 0, -1, S_FANG_CLONE2, 0}, // S_FANG_CLONE1 + {SPR_FANG, 11, 0, {A_Repeat}, 49, S_FANG_CLONE1, S_FANG_CLONE3, 0}, // S_FANG_INTRO2 + {SPR_FANG, 12, 0, {A_SetObjectFlags}, MF_NOGRAVITY, 1, S_FANG_CLONE4, 0}, // S_FANG_CLONE3 + {SPR_FANG, 12, 1, {A_Boss5CheckOnGround}, S_FANG_IDLE0, 0, S_FANG_CLONE4, 0}, // S_FANG_CLONE4 + + {SPR_FANG, 0, 0, {A_SetObjectFlags}, MF_NOCLIPTHING, 1, S_FANG_IDLE1, 0}, // S_FANG_IDLE0 + {SPR_FANG, 2, 16, {A_Look}, 1, 0, S_FANG_IDLE2, 0}, // S_FANG_IDLE1 + {SPR_FANG, 3, 16, {A_Look}, 1, 0, S_FANG_IDLE3, 0}, // S_FANG_IDLE2 + {SPR_FANG, 3, 16, {A_Look}, 1, 0, S_FANG_IDLE4, 0}, // S_FANG_IDLE3 + {SPR_FANG, 3, 16, {A_Look}, 1, 0, S_FANG_IDLE5, 0}, // S_FANG_IDLE4 + {SPR_FANG, 2, 16, {A_Look}, 1, 0, S_FANG_IDLE6, 0}, // S_FANG_IDLE5 + {SPR_FANG, 1, 16, {A_Look}, 1, 0, S_FANG_IDLE7, 0}, // S_FANG_IDLE6 + {SPR_FANG, 1, 16, {A_Look}, 1, 0, S_FANG_IDLE8, 0}, // S_FANG_IDLE7 + {SPR_FANG, 1, 16, {A_Look}, 1, 0, S_FANG_IDLE1, 0}, // S_FANG_IDLE8 + + {SPR_FANG, 14, 0, {A_DoNPCPain}, FRACUNIT, 0, S_FANG_PAIN2, 0}, // S_FANG_PAIN1 + {SPR_FANG, 14, 1, {A_Boss5CheckOnGround}, S_FANG_PATHINGSTART1, S_FANG_PINCHPATHINGSTART1, S_FANG_PAIN2, 0}, // S_FANG_PAIN2 + + {SPR_FANG, 8, 0, {A_Boss5ExtraRepeat}, 5, 4, S_FANG_PATHINGSTART2, 0}, // S_FANG_PATHINGSTART1 + {SPR_FANG, 8, 0, {A_PlayActiveSound}, 0, 0, S_FANG_PATHING, 0}, // S_FANG_PATHINGSTART2 + {SPR_FANG, 8, 0, {A_Boss5FindWaypoint}, 0, 0, S_FANG_BOUNCE1, 0}, // S_FANG_PATHING + + {SPR_FANG, 8, 2, {A_Thrust}, 0, 1, S_FANG_BOUNCE2, 0}, // S_FANG_BOUNCE1 + {SPR_FANG, 9, 2, {NULL}, 0, 0, S_FANG_BOUNCE3, 0}, // S_FANG_BOUNCE2 + {SPR_FANG, 10, 1, {A_Boss5Jump}, 0, 0, S_FANG_BOUNCE4, 0}, // S_FANG_BOUNCE3 + {SPR_FANG, 10, 1, {A_Boss5CheckFalling}, S_FANG_CHECKPATH1, S_FANG_FALL1, S_FANG_BOUNCE4, 0}, // S_FANG_BOUNCE4 + + {SPR_FANG, 12, 1, {A_Boss5CheckOnGround}, S_FANG_CHECKPATH1, 0, S_FANG_FALL2, 0}, // S_FANG_FALL1 + {SPR_FANG, 13, 1, {A_Boss5CheckOnGround}, S_FANG_CHECKPATH1, 0, S_FANG_FALL1, 0}, // S_FANG_FALL2 + + {SPR_FANG, 8, 0, {A_Boss5Calm}, 0, 0, S_FANG_CHECKPATH2, 0}, // S_FANG_CHECKPATH1 + {SPR_FANG, 8, 0, {A_Repeat}, 0, S_FANG_PATHINGCONT1, S_FANG_SKID1, 0}, // S_FANG_CHECKPATH2 + + {SPR_FANG, 9, 0, {A_Boss5PinchShot}, MT_FBOMB, -16, S_FANG_PATHINGCONT2, 0}, // S_FANG_PATHINGCONT1 + {SPR_FANG, 9, 0, {A_PlayActiveSound}, 0, 0, S_FANG_PATHINGCONT3, 0}, // S_FANG_PATHINGCONT2 + {SPR_FANG, 9, 2, {A_Thrust}, 0, 1, S_FANG_PATHING, 0}, // S_FANG_PATHINGCONT3 + + {SPR_FANG, 4, 0, {A_PlayAttackSound}, 0, 0, S_FANG_SKID2, 0}, // S_FANG_SKID1 + {SPR_FANG, 4, 1, {A_DoNPCSkid}, S_FANG_SKID3, 0, S_FANG_SKID2, 0}, // S_FANG_SKID2 + {SPR_FANG, 4, 10, {NULL}, 0, 0, S_FANG_CHOOSEATTACK, 0}, // S_FANG_SKID3 + + {SPR_FANG, 0, 0, {A_RandomState}, S_FANG_LOBSHOT0, S_FANG_FIRESTART1, S_NULL, 0}, // S_FANG_CHOOSEATTACK + + {SPR_FANG, 5, 0, {A_PrepareRepeat}, 3, 0, S_FANG_FIRESTART2, 0}, // S_FANG_FIRESTART1 // Reset loop + {SPR_FANG, 5, 18, {A_LookForBetter}, 1, 0, S_FANG_FIRE1, 0}, // S_FANG_FIRESTART2 + {SPR_FANG, 5, 5, {A_FireShot}, MT_CORK, -16, S_FANG_FIRE2, 0}, // S_FANG_FIRE1 // Start of loop + {SPR_FANG, 6, 5, {NULL}, 0, 0, S_FANG_FIRE3, 0}, // S_FANG_FIRE2 + {SPR_FANG, 7, 5, {NULL}, 0, 0, S_FANG_FIRE4, 0}, // S_FANG_FIRE3 + {SPR_FANG, 5, 5, {NULL}, 2, 0, S_FANG_FIREREPEAT, 0}, // S_FANG_FIRE4 + {SPR_FANG, 5, 0, {A_Repeat}, 3, S_FANG_FIRE1, S_FANG_WAIT1, 0}, // S_FANG_FIREREPEAT // End of loop + + {SPR_FANG, 18, 16, {A_LookForBetter}, 1, 0, S_FANG_LOBSHOT1, 0}, // S_FANG_LOBSHOT0 + {SPR_FANG, 19, 2, {A_LookForBetter}, 1, 0, S_FANG_LOBSHOT2, 0}, // S_FANG_LOBSHOT1 + {SPR_FANG, 20, 18, {A_BrakLobShot}, MT_FBOMB, 32+(1<<16), S_FANG_WAIT1, 0}, // S_FANG_LOBSHOT2 + + {SPR_FANG, FF_ANIMATE|15, 70, {NULL}, 1, 5, S_FANG_WAIT2, 0}, // S_FANG_WAIT1 + {SPR_FANG, 0, 35, {A_Look}, 1, 0, S_FANG_IDLE1, 0}, // S_FANG_WAIT2 + + {SPR_FANG, 12, 1, {A_Boss5CheckOnGround}, S_FANG_PATHINGSTART2, S_FANG_PINCHPATHINGSTART1, S_FANG_WALLHIT, 0}, // S_FANG_WALLHIT + + {SPR_FANG, 8, 0, {A_PrepareRepeat}, 1, 0, S_FANG_PINCHPATHINGSTART2, 0}, // S_FANG_PINCHPATHINGSTART1 + {SPR_FANG, 8, 0, {A_PlayActiveSound}, 0, 0, S_FANG_PINCHPATHING, 0}, // S_FANG_PINCHPATHINGSTART2 + {SPR_FANG, 8, 0, {A_Boss5FindWaypoint}, 1, 0, S_FANG_PINCHBOUNCE0, 0}, // S_FANG_PINCHPATHING + {SPR_FANG, 8, 0, {A_SetObjectFlags}, MF_NOCLIP|MF_NOCLIPHEIGHT, 2, S_FANG_PINCHBOUNCE1, 0}, // S_FANG_PINCHBOUNCE0 + {SPR_FANG, 8, 2, {A_Thrust}, 0, 1, S_FANG_PINCHBOUNCE2, 0}, // S_FANG_PINCHBOUNCE1 + {SPR_FANG, 9, 2, {NULL}, 0, 0, S_FANG_PINCHBOUNCE3, 0}, // S_FANG_PINCHBOUNCE2 + {SPR_FANG, 10, 2, {A_Boss5Jump}, 0, 0, S_FANG_PINCHBOUNCE4, 0}, // S_FANG_PINCHBOUNCE3 + {SPR_FANG, 10, 1, {A_Boss5CheckFalling}, S_FANG_PINCHSKID1, S_FANG_PINCHFALL0, S_FANG_PINCHBOUNCE4, 0}, // S_FANG_PINCHBOUNCE4 + {SPR_FANG, 12, 0, {A_SetObjectFlags}, MF_NOCLIP|MF_NOCLIPHEIGHT, 1, S_FANG_PINCHFALL1, 0}, // S_FANG_PINCHFALL0 + {SPR_FANG, 12, 1, {A_Boss5CheckOnGround}, S_FANG_PINCHSKID1, 0, S_FANG_PINCHFALL2, 0}, // S_FANG_PINCHFALL1 + {SPR_FANG, 13, 1, {A_Boss5CheckOnGround}, S_FANG_PINCHSKID1, 0, S_FANG_PINCHFALL1, 0}, // S_FANG_PINCHFALL2 + {SPR_FANG, 4, 0, {A_PlayAttackSound}, 0, 0, S_FANG_PINCHSKID2, 0}, // S_FANG_PINCHSKID1 + {SPR_FANG, 4, 1, {A_DoNPCSkid}, S_FANG_PINCHLOBSHOT0, 0, S_FANG_PINCHSKID2, 0}, // S_FANG_PINCHSKID2 + {SPR_FANG, 18, 16, {A_FaceTarget}, 3, 0, S_FANG_PINCHLOBSHOT1, 0}, // S_FANG_PINCHLOBSHOT0 + {SPR_FANG, 19, 2, {A_FaceTarget}, 3, 0, S_FANG_PINCHLOBSHOT2, 0}, // S_FANG_PINCHLOBSHOT1 + {SPR_FANG, 20, 30, {A_Boss5MakeItRain}, MT_FBOMB, -16, S_FANG_PINCHLOBSHOT3, 0}, // S_FANG_PINCHLOBSHOT2 + {SPR_FANG, 20, 18, {A_LinedefExecuteFromArg}, 4, 0, S_FANG_PINCHLOBSHOT4, 0}, // S_FANG_PINCHLOBSHOT3 + {SPR_FANG, 0, 0, {A_Boss5Calm}, 0, 0, S_FANG_PATHINGSTART1, 0}, // S_FANG_PINCHLOBSHOT4 + + {SPR_FANG, 21, 0, {A_DoNPCPain}, 0, 0, S_FANG_DIE2, 0}, // S_FANG_DIE1 + {SPR_FANG, 21, 1, {A_Boss5CheckOnGround}, S_FANG_DIE3, 0, S_FANG_DIE2, 0}, // S_FANG_DIE2 + + {SPR_FANG, 22, 0, {A_Scream}, 0, 0, S_FANG_DIE4, 0}, // S_FANG_DIE3 + {SPR_FANG, 22, -1, {A_SetFuse}, 70, 0, S_FANG_DIE5, 0}, // S_FANG_DIE4 + + {SPR_FANG, 11, 0, {A_PlaySound}, sfx_jump, 0, S_FANG_DIE6, 0}, // S_FANG_DIE5 + {SPR_FANG, 11, 1, {A_ZThrust}, 6, (1<<16)|1, S_FANG_DIE7, 0}, // S_FANG_DIE6 + {SPR_FANG, 11, 1, {A_Boss5CheckFalling}, S_FANG_FLEEPATHING1, S_FANG_DIE8, S_FANG_DIE7, 0}, // S_FANG_DIE7 + {SPR_FANG, 12, 1, {A_Boss5CheckOnGround}, S_FANG_FLEEPATHING1, 0, S_FANG_DIE8, 0}, // S_FANG_DIE8 + + {SPR_FANG, 9, 0, {A_PlayActiveSound}, 0, 0, S_FANG_FLEEPATHING2, 0}, // S_FANG_FLEEPATHING1 + {SPR_FANG, 8, 2, {A_Boss5FindWaypoint}, 2, 0, S_FANG_FLEEBOUNCE1, 0}, // S_FANG_FLEEPATHING2 + {SPR_FANG, 9, 2, {NULL}, 0, 0, S_FANG_FLEEBOUNCE2, 0}, // S_FANG_FLEEBOUNCE1 + {SPR_FANG, 10, -1, {A_BossDeath}, 0, 0, S_NULL, 0}, // S_FANG_FLEEBOUNCE2 + + {SPR_FANG, 17, 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_METL, 4, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT, 0}, // S_METALSONIC_FLOAT + {SPR_METL, 16|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_METALSONIC_STUN, 0}, // S_METALSONIC_VECTOR + {SPR_METL, 15, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT, 0}, // S_METALSONIC_STUN + {SPR_METL, 17, 20, {NULL}, 0, 0, S_METALSONIC_GATHER, 0},// S_METALSONIC_RAISE + {SPR_METL, 18, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT, 0}, // S_METALSONIC_GATHER + {SPR_METL, 6|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 1, 2, S_METALSONIC_BOUNCE, 0},// S_METALSONIC_DASH + {SPR_METL, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 1, 2, S_METALSONIC_FLOAT, 0}, // S_METALSONIC_BOUNCE + {SPR_METL, 14, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT, 0}, // S_METALSONIC_BADBOUNCE + {SPR_METL, 17, -1, {NULL}, 0, 0, S_METALSONIC_GATHER, 0},// S_METALSONIC_SHOOT + {SPR_METL, 15, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT, 0}, // S_METALSONIC_PAIN + {SPR_METL, 17, 2, {A_Fall}, 0, 0, S_METALSONIC_DEATH2, 0},// S_METALSONIC_DEATH1 + {SPR_METL, 17, 4, {A_BossScream}, 0, 0, S_METALSONIC_DEATH3, 0},// S_METALSONIC_DEATH2 + {SPR_METL, 17, 0, {A_Repeat}, 17, S_METALSONIC_DEATH2, S_METALSONIC_DEATH4, 0}, // S_METALSONIC_DEATH3 + {SPR_METL, 17, -1, {A_BossDeath}, 0, 0, S_NULL, 0}, // S_METALSONIC_DEATH4 + {SPR_METL, 15, 1, {A_BossScream}, 0, 0, S_METALSONIC_FLEE2, 0}, // S_METALSONIC_FLEE1 + {SPR_METL, 15, 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, -1, {NULL}, 0, 0, S_NULL, 0}, // S_BLUESPHERE {SPR_SPHR, FF_FULLBRIGHT #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_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_BOMBSPHERE3, 0}, // S_BOMBSPHERE2 + {SPR_SPHR, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_BOMBSPHERE4, 0}, // S_BOMBSPHERE3 + {SPR_SPHR, FF_FULLBRIGHT|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_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 15, 2, S_NULL, 0}, // S_NIGHTSCHIP + {SPR_NCHP, FF_FULLBRIGHT|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, 0, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SHRD1 + {SPR_SHRD, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_SHRD2 + {SPR_SHRD, 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 // 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 + {SPR_ROSY, 16, 8, {NULL}, 0, 0, S_ROSY_IDLE2, 0}, // S_ROSY_IDLE1 + {SPR_ROSY, 17, 4, {NULL}, 0, 0, S_ROSY_IDLE3, 0}, // S_ROSY_IDLE2 + {SPR_ROSY, 18, 8, {NULL}, 0, 0, S_ROSY_IDLE4, 0}, // S_ROSY_IDLE3 + {SPR_ROSY, 17, 4, {NULL}, 0, 0, S_ROSY_IDLE1, 0}, // S_ROSY_IDLE4 + {SPR_ROSY, 14, -1, {NULL}, 1, 0, S_NULL, 0}, // S_ROSY_JUMP + {SPR_ROSY, 5, -1, {NULL}, 7, 0, S_NULL, 0}, // S_ROSY_WALK + {SPR_ROSY, 19, -1, {NULL}, 0, 0, S_NULL, 0}, // S_ROSY_HUG + {SPR_ROSY, 13, -1, {NULL}, 0, 0, S_NULL, 0}, // S_ROSY_PAIN + {SPR_ROSY, 1|FF_ANIMATE, -1, {NULL}, 3, 16, S_NULL, 0}, // S_ROSY_STND + {SPR_ROSY, 20|FF_ANIMATE, TICRATE, {NULL}, 3, 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}, // S_EGGSTATUE2 + {SPR_ESTA, 1, -1, {NULL}, 0, 0, S_NULL, 0}, // S_EGGSTATUE2 // 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 }; mobjinfo_t mobjinfo[NUMMOBJTYPES] = @@ -7493,12 +7494,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 }, diff --git a/src/info.h b/src/info.h index e8963cd3cdbdb28d2a498bb95cb63b9b5376a354..0361f64281150bec03676bd1b8a4baa36a18de22 100644 --- a/src/info.h +++ b/src/info.h @@ -575,6 +575,7 @@ extern int actionsoverridden[NUMACTIONS][MAX_ACTION_RECURSION]; #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 @@ -1078,9 +1079,6 @@ typedef enum sprite 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, @@ -1160,15 +1158,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 { @@ -4380,11 +4380,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; diff --git a/src/lua_baselib.c b/src/lua_baselib.c index e75a911eef51f6f47b9d9bef756ca1401d9ac351..dc6a26c81cad44756c0af27c044de79c16ce69de 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -345,6 +345,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 ////////////// @@ -674,17 +686,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; } @@ -3032,6 +3042,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); @@ -3039,6 +3052,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) { @@ -3101,6 +3117,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 //////////// @@ -4288,6 +4345,7 @@ static luaL_Reg lib[] = { {"userdataMetatable", lib_userdataMetatable}, {"IsPlayerAdmin", lib_isPlayerAdmin}, {"reserveLuabanks", lib_reserveLuabanks}, + {"tofixed", lib_tofixed}, // m_menu {"M_MoveColorAfter",lib_pMoveColorAfter}, @@ -4506,7 +4564,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_hook.h b/src/lua_hook.h index 026e5c4aaf97c54326a22d5de56f4e44cbddd09f..17e0e99a0787d43fa12f817018b29acaac723495 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -86,6 +86,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 +119,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..54381e4aedc47a64d89190f5582c3c5856634ba6 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -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, @@ -490,6 +501,21 @@ static int call_mobj_type_hooks(Hook_State *hook, mobjtype_t mobj_type) return call_mapped(hook, &mobjHookIds[mobj_type][hook->hook_type]); } +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 ( Hook_State * hook, @@ -648,23 +674,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; } /* ========================================================================= diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 08e0367f9e2cd5a6c71eb0dcfaf57948194b0bea..d6771f1082a635e2bcb9e26ffb4349398113397c 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -492,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; } @@ -556,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! @@ -583,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; } @@ -606,17 +605,15 @@ 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 = P_GetSkinSprite2(skins[i], j, NULL); // feed skin and current sprite2 through to change sprite2 used if necessary + j |= SPR2F_SUPER; - sprdef = &skins[i]->sprites[j]; + sprdef = P_GetSkinSpritedef(skins[i], j); // set frame number frame = luaL_optinteger(L, 2, 0); @@ -644,7 +641,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..cb58e628ea005217c819ddea922f4952f70961f0 100644 --- a/src/lua_hudlib_drawlist.c +++ b/src/lua_hudlib_drawlist.c @@ -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 767477d0bac75e7b9bada5367cb223a37a33f8cd..511c20031f8ea82d74c70da608535146bfce8eb2 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -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; @@ -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; } @@ -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_mobjlib.c b/src/lua_mobjlib.c index 62b02ff3f679a50c7bd09df2807b8d11f5056276..de7065790abb137e82f505c961215ca6acb10429 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -564,7 +564,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); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index b6ef2579c131d8de29a521615cb6a74acc94f5a0..744a56f7fe528031dd0777c06da35067fb59dde4 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -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; diff --git a/src/lua_script.c b/src/lua_script.c index b62fa675e2e7193da3a688d89d2f1cf377298a51..057899555480383611652c552e41bf41398b0e2b 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -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); diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index e183d8dda4a08b4c64dcc2429937cf919d743f67..24d948a6735c3c723dcbf86c285a23c8367090dd 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -55,6 +55,7 @@ enum skin { skin_contangle, skin_soundsid, skin_sprites, + skin_supersprites, skin_natkcolor }; @@ -95,6 +96,7 @@ static const char *const skin_opt[] = { "contangle", "soundsid", "sprites", + "supersprites", "natkcolor", NULL}; @@ -220,6 +222,9 @@ static int skin_get(lua_State *L) case skin_sprites: 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; @@ -347,17 +352,17 @@ 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*2) - return luaL_error(L, LUA_QL("skin_t") " field 'sprites' index %d out of range (0 - %d)", i, (NUMPLAYERSPRITES*2)-1); + 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.sprites -> NUMPLAYERSPRITES*2 +// #skin.sprites -> NUMPLAYERSPRITES static int lib_numSkinsSprites(lua_State *L) { - lua_pushinteger(L, NUMPLAYERSPRITES*2); + lua_pushinteger(L, NUMPLAYERSPRITES); return 1; } diff --git a/src/m_menu.c b/src/m_menu.c index 7811a99ba3197ed9783431723dc4254fdf01f992..e0c240fecc773d2ef9f0931205f05a02315a74c2 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -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; @@ -2099,6 +2102,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; @@ -2326,6 +2335,7 @@ void Nextmap_OnChange(void) { currentMenu->lastOn = itemOn; itemOn = nastart; + M_UpdateItemOn(); } } else if (currentMenu == &SP_TimeAttackDef) @@ -2375,6 +2385,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') @@ -3125,6 +3136,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) @@ -3137,6 +3149,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 @@ -3648,18 +3661,20 @@ 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. { SPauseMenu[spause_pandora].status = (pandora) ? (IT_GRAYEDOUT) : (IT_DISABLED); @@ -3700,6 +3715,7 @@ void M_StartControlPanel(void) currentMenu = &SPauseDef; itemOn = spause_continue; + M_UpdateItemOn(); } else // multiplayer { @@ -3741,6 +3757,7 @@ void M_StartControlPanel(void) currentMenu = &MPauseDef; itemOn = mpause_continue; + M_UpdateItemOn(); } CON_ToggleOff(); // move away console @@ -3834,6 +3851,7 @@ void M_SetupNextMenu(menu_t *menudef) } } } + M_UpdateItemOn(); hidetitlemap = false; } @@ -4012,11 +4030,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; @@ -4138,7 +4156,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; } @@ -4956,22 +4974,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 // ========================================================================== @@ -6089,56 +6091,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; @@ -6157,51 +6119,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; - } - } - - 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); + MessageDef.x = (INT16)((BASEVIDWIDTH - V_StringWidth(message, 0)-32)/2); + MessageDef.y = (INT16)((BASEVIDHEIGHT - V_StringHeight(message, V_RETURN8))/2); - //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) { @@ -6225,51 +6154,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 @@ -6313,6 +6199,7 @@ static void M_HandleImageDef(INT32 choice) if (itemOn >= (INT16)(currentMenu->numitems-1)) itemOn = 0; else itemOn++; + M_UpdateItemOn(); break; case KEY_LEFTARROW: @@ -6323,6 +6210,7 @@ static void M_HandleImageDef(INT32 choice) if (!itemOn) itemOn = currentMenu->numitems - 1; else itemOn--; + M_UpdateItemOn(); break; case KEY_ESCAPE: @@ -7112,7 +7000,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); @@ -7519,6 +7410,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) @@ -7956,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++; @@ -8760,9 +8652,14 @@ 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; } @@ -9183,7 +9080,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; @@ -9272,7 +9169,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); @@ -9621,6 +9518,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 @@ -10180,6 +10079,7 @@ static void M_TimeAttack(INT32 choice) Nextmap_OnChange(); itemOn = tastart; // "Start" is selected. + M_UpdateItemOn(); } // Drawing function for Nights Attack @@ -10296,7 +10196,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 @@ -10309,11 +10209,11 @@ 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; V_DrawFixedPatch(270<<FRACBITS, (186<<FRACBITS) - 8*FINESINE(fa), - FixedDiv(skins[skinnumber]->highresscale, skins[skinnumber]->shieldscale), + FixedDiv(skins[skinnumber]->highresscale, skins[skinnumber]->shieldscale), (sprframe->flip & 1<<6) ? V_FLIP : 0, natksprite, R_GetTranslationColormap(TC_BLINK, color, GTC_CACHE)); @@ -10418,6 +10318,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 @@ -10737,6 +10638,7 @@ static void M_ModeAttackEndGame(INT32 choice) break; } itemOn = currentMenu->lastOn; + M_UpdateItemOn(); G_SetGamestate(GS_TIMEATTACK); modeattacking = ATTACKING_NONE; M_ChangeMenuMusic("_title", true); @@ -10818,6 +10720,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; } @@ -11531,6 +11434,7 @@ static void M_ConnectMenu(INT32 choice) else M_SetupNextMenu(&MP_ConnectDef); itemOn = 0; + M_UpdateItemOn(); M_Refresh(0); } @@ -11790,6 +11694,7 @@ static void M_StartServerMenu(INT32 choice) Newgametype_OnChange(); M_SetupNextMenu(&MP_ServerDef); itemOn = 1; + M_UpdateItemOn(); } // ============== @@ -11972,15 +11877,21 @@ static void M_HandleConnectIP(INT32 choice) case KEY_INS: case 'c': case 'C': // ctrl+c, ctrl+insert, copying - I_ClipboardCopy(setupm_ip, l); - S_StartSound(NULL,sfx_menu1); // Tails + 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; + 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 @@ -12004,9 +11915,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; @@ -12056,9 +11970,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 @@ -12203,9 +12130,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; @@ -12255,11 +12265,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 @@ -12274,17 +12297,38 @@ 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 = FixedDiv(skins[setupm_fakeskin]->highresscale, 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, @@ -12477,6 +12521,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) { @@ -12522,6 +12580,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 { @@ -12562,6 +12621,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 { @@ -12682,7 +12742,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); @@ -12712,6 +12772,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); @@ -12723,7 +12787,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); @@ -12753,6 +12817,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); @@ -12774,6 +12842,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; } @@ -13041,7 +13115,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 diff --git a/src/m_misc.c b/src/m_misc.c index 55c5485a149a2b2c43e48fab973c5ad898091036..a60bbea98d2e2b47cf3fea0dae652d26b6aa4763 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -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/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index d735e8132172e66a5c808ef572b7edca1ae8a8cc..2bf9d2dde7cb60266687282748142af5e676c917 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -1362,7 +1362,7 @@ static void IdleUpdate(void) for (i = 1; 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 (cv_idletime.value && playeringame[i] && playernode[i] != UINT8_MAX && !players[i].quittime && !players[i].spectator && !players[i].bot && !IsPlayerAdmin(i) && i != serverplayer && gamestate == GS_LEVEL) { if (players[i].cmd.forwardmove || players[i].cmd.sidemove || players[i].cmd.buttons) players[i].lastinputtime = 0; diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c index e073a863c90bbe88025fd6f7ed9f4d0decac23d0..f7b98c4dbaff55d58481b5c439623a92fcd4e4c4 100644 --- a/src/netcode/d_netcmd.c +++ b/src/netcode/d_netcmd.c @@ -691,6 +691,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); @@ -1308,7 +1309,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); @@ -4608,7 +4609,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) @@ -4622,7 +4623,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); @@ -4630,7 +4631,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")); @@ -4769,7 +4770,7 @@ static void Command_Cheats_f(void) G_SetUsedCheats(false); return; } - + if (usedCheats) CONS_Printf(M_GetText("Cheats are enabled, the game cannot be saved.\n")); else @@ -4941,6 +4942,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/i_tcp.c b/src/netcode/i_tcp.c index 04018d84a81a353e2470a9f0ccdc1ab7b35fc18d..3600c47c9e5ce4f253e7114c584e1d0023ec1afa 100644 --- a/src/netcode/i_tcp.c +++ b/src/netcode/i_tcp.c @@ -114,16 +114,10 @@ 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 diff --git a/src/p_enemy.c b/src/p_enemy.c index 428c023ff3e6333b7f62cda4e3f528762b1d606e..59934aa40d01291d7686097fca5c6ad2da1e2193 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -4189,8 +4189,10 @@ static void P_DoBoss5Death(mobj_t *mo) if (!P_MobjWasRemoved(pole)) { 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, @@ -4199,7 +4201,7 @@ static void P_DoBoss5Death(mobj_t *mo) { pole->tracer->flags |= MF_NOCLIPTHING; P_SetScale(pole->tracer, 2*FRACUNIT, true); - pole->angle = pole->tracer->angle = mo->tracer->angle; + pole->tracer->angle = mo->tracer->angle; pole->tracer->momx = pole->momx; pole->tracer->momy = pole->momy; @@ -4863,7 +4865,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) { @@ -4895,8 +4897,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; } @@ -5192,7 +5195,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)) @@ -5222,7 +5225,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; } @@ -14855,12 +14858,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 5534f7865c23afc2d70ceae209e6ea432f6223f8..e73cd1fce675ee17721e6236e7dc764ede8e9d69 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -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 @@ -1332,7 +1365,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 +1377,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; @@ -1881,6 +1914,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; @@ -3606,7 +3640,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); diff --git a/src/p_local.h b/src/p_local.h index 0bcd6da1dd7f42b5e56650d8a2cc70fd775f1e22..249c3cd4b6de5248140c00e2dfc2332081a5d00e 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -307,21 +307,19 @@ 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) +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); diff --git a/src/p_map.c b/src/p_map.c index 7b64fe3bb782de111f0b70053306ce851a1ea190..668a8ab6413ccda17adccf994c18e7f2dc58f58d 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -389,7 +389,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 +420,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 +432,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 +443,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 +498,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 +1023,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 +1036,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) P_SetTarget(&tmthing->tracer, thing); if (!P_IsObjectOnGround(thing)) thing->momz += tmthing->momz; + return CHECKTHING_COLLIDE; } } @@ -1484,13 +1464,13 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) } // check for special pickup - if (thing->flags & MF_SPECIAL && tmthing->player) + if (thing->flags & MF_SPECIAL) { 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) { P_TouchSpecialThing(tmthing, thing, true); // can remove thing return CHECKTHING_COLLIDE; @@ -1578,15 +1558,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 +1659,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 +1668,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 +1735,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 diff --git a/src/p_maputl.c b/src/p_maputl.c index 82b86471522ee3b2cbeebbedfb1e28c1c4438501..200b89cff93c815bac281c8b270ae4975de219c6 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -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,23 +1052,35 @@ 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; + mobj_t *bnext = NULL; + 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; block = next) { - mobj = block->mobj; + next = block->mnext; + if (next) + P_SetTarget(&bnext, next->mobj); // We want to note our reference to bnext here in case it is MF_NOTHINK and gets removed! - if (!func(mobj)) + if (!func(block->mobj)) + { + P_SetTarget(&bnext, NULL); return false; - if (P_MobjWasRemoved(tmthing)) // func just broke blockmap chain, cannot continue. + } + + if (P_MobjWasRemoved(tmthing) // func just popped our tmthing, cannot continue. + || (bnext && P_MobjWasRemoved(bnext))) // func just broke blockmap chain, cannot continue. + { + P_SetTarget(&bnext, NULL); return true; + } } + P_SetTarget(&bnext, NULL); + return true; } diff --git a/src/p_mobj.c b/src/p_mobj.c index 55be8e54fc4e36684e20279ac134d7de4772780f..fbbae5a1e4b5cb122ff353591b037a91f284ceef 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -85,9 +85,15 @@ 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); + } + else + animlength = st->var1; if (!(st->frame & FF_ANIMATE)) return; @@ -138,8 +144,13 @@ 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; + if (mobj->skin) + { + 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; + } } // @@ -395,31 +406,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 || (player->powers[pw_carry] == CR_NIGHTSMODE && (player->charflags & SF_NONIGHTSSUPER))) - stateframe = stateframe & ~FF_SPR2SUPER; - else if (player->powers[pw_super] || (player->powers[pw_carry] == CR_NIGHTSMODE && (player->charflags & SF_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 +435,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 +462,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 +550,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 needed sprite2 and frame number + spr2 = P_GetSkinSprite2(skin, spr2, NULL); - // Get the sprite2 and frame number - spr2 = P_GetSkinSprite2(skin, (stateframe & FF_FRAMEMASK), NULL); - 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 @@ -571,12 +579,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 +606,7 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state) { if (mobj->frame & FF_FRAMEMASK) mobj->frame--; + return P_SetMobjState(mobj, st->var1); } } @@ -1092,9 +1108,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 +1118,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 +1140,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 +1151,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 +1166,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 +1179,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 +1194,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 +1216,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 +1227,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 +1242,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 +1255,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 +1385,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) case MT_WATERDROP: case MT_CYBRAKDEMON: gravityadd >>= 1; + break; default: break; } @@ -2331,8 +2192,8 @@ boolean P_CheckDeathPitCollide(mobj_t *mo) if (mo->player && mo->player->pflags & PF_GODMODE) return false; - fixed_t sectorFloor = P_GetSectorFloorZAt(mo->subsector->sector, mo->x, mo->y); - fixed_t sectorCeiling = P_GetSectorCeilingZAt(mo->subsector->sector, mo->x, mo->y); + 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)) @@ -11193,7 +11054,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; } diff --git a/src/p_mobj.h b/src/p_mobj.h index fd75f75c6ef5e6022e55cfbe69a25043e1f0d6a5..2f013a2f30fac7f7d117cb190fcbc5bd1db17e54 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -308,7 +308,7 @@ 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 @@ -451,7 +451,7 @@ 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 diff --git a/src/p_pspr.h b/src/p_pspr.h index 69e5eeeb3fc902e12782cf63672731aa5ebd0c36..6510190f118fb639c52a22576dd911023d3b134c 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -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 c385bd8e1aff3a8b57b978e70ac1941878dcc764..5e4d6d0760441e6bc94c6815824b8b7e1ab38c80 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -261,6 +261,7 @@ static void P_NetArchivePlayers(void) WRITEUINT8(save_p, players[i].marelap); WRITEUINT8(save_p, players[i].marebonuslap); WRITEUINT32(save_p, players[i].marebegunat); + WRITEUINT32(save_p, players[i].lastmaretime); WRITEUINT32(save_p, players[i].startedtime); WRITEUINT32(save_p, players[i].finishedtime); WRITEUINT32(save_p, players[i].lapbegunat); @@ -492,6 +493,7 @@ static void P_NetUnArchivePlayers(void) players[i].marelap = READUINT8(save_p); players[i].marebonuslap = READUINT8(save_p); players[i].marebegunat = READUINT32(save_p); + players[i].lastmaretime = READUINT32(save_p); players[i].startedtime = READUINT32(save_p); players[i].finishedtime = READUINT32(save_p); players[i].lapbegunat = READUINT32(save_p); @@ -1882,7 +1884,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; @@ -2066,7 +2068,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) if (diff & MD_SPRITE) { WRITEUINT16(save_p, mobj->sprite); if (mobj->sprite == SPR_PLAY) - WRITEUINT8(save_p, mobj->sprite2); + WRITEUINT16(save_p, mobj->sprite2); } if (diff & MD_FRAME) { @@ -3096,12 +3098,12 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) if (diff & MD_SPRITE) { mobj->sprite = READUINT16(save_p); if (mobj->sprite == SPR_PLAY) - mobj->sprite2 = READUINT8(save_p); + mobj->sprite2 = 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) { diff --git a/src/p_setup.c b/src/p_setup.c index 93c4937c4d40118230bb128af9d4f345143816a0..c4b4a35b3610beeb973624035a4d5454f69f49db 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -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 // @@ -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--); @@ -1088,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++) @@ -1834,6 +1863,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")) @@ -2700,13 +2733,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) @@ -2968,7 +3006,8 @@ static void P_LoadTextmap(void) 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; @@ -2981,13 +3020,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); } diff --git a/src/p_setup.h b/src/p_setup.h index 61c445c6523ba28a589c54364bd644e701282110..da38d4c08b152f87fab59517706c3ccbc7544339 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -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..c2bacad9ed02ede75af92692d7b5e9ad0e6fb02d 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -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) { @@ -212,6 +214,9 @@ void T_DynamicSlopeLine (dynlineplanethink_t* th) 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_spec.c b/src/p_spec.c index 805817fb033c465b33059c24fbefb52432173444..78cf460632970ac108512f29f1fd2111aea5f462 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3684,7 +3684,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"); diff --git a/src/p_tick.c b/src/p_tick.c index 6d7d4fd969fb70964e4e0cf6663d26bd6d81e8a7..56e0fd897bfbba718885a1104224d1554790f227 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -564,6 +564,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 +607,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) diff --git a/src/p_user.c b/src/p_user.c index b69db5da814d2476616647d4bd3c4c7657a05491..7ad5bccbb58db303a28c9b3fe438b7effdea3c90 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -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,6 +797,11 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) } } + // 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_SHIELDDOWN|PF_STARTDASH|PF_GLIDING|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED|PF_SHIELDABILITY|PF_SPINNING|PF_DRILLING); player->homing = 0; player->mo->fuse = 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; @@ -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 @@ -1082,6 +1089,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); @@ -1400,7 +1414,7 @@ void P_DoSuperDetransformation(player_t *player) if (!G_CoopGametype()) player->powers[pw_flashing] = flashingtics-1; - if (player->mo->sprite2 & FF_SPR2SUPER) + if (player->mo->sprite2 & SPR2F_SUPER) P_SetMobjState(player->mo, player->mo->state-states); // Inform the netgame that the champion has fallen in the heat of battle. @@ -2365,7 +2379,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; @@ -4539,6 +4553,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); } @@ -4714,7 +4735,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); @@ -4754,9 +4775,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) @@ -7005,7 +7025,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); @@ -7089,12 +7109,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 } } } @@ -8759,7 +8779,7 @@ void P_MovePlayer(player_t *player) if (!(player->mo->momz || player->mo->momx || player->mo->momy) && !(player->mo->eflags & MFE_GOOWATER) && player->panim == PA_IDLE && !(player->powers[pw_carry])) P_DoTeeter(player); - + // Toss a flag if (G_GametypeHasTeams() && (cmd->buttons & BT_TOSSFLAG) && !(player->powers[pw_super]) && !(player->tossdelay)) { @@ -9801,9 +9821,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); @@ -9811,8 +9832,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); @@ -9824,23 +9845,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), } }; @@ -11417,10 +11438,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); } } @@ -12121,6 +12142,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: @@ -12447,13 +12472,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 (!P_MobjWasRemoved(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! } } diff --git a/src/r_defs.h b/src/r_defs.h index 7e92c92492a88527f2bf5685bf93797c0081494c..7a6f518ee26ca96a4a4df62f30ec7dc741855bcd 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -405,6 +405,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 @@ -610,6 +612,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 @@ -974,6 +978,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 86f7e488c8502516cc4f36bb04b7a516385fc5ed..feb4693bb4a9ab995a099b003caf6a40e8e610f5 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -74,7 +74,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 diff --git a/src/r_draw.h b/src/r_draw.h index 1a828312a7a922353a3ff5b969908dc61dcf0ee6..77588d7dede09edf30463c1cd749b268724a6882 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -41,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 @@ -154,8 +153,10 @@ void R_VideoErase(size_t ofs, INT32 count); // ----------------- void R_DrawColumn_8(void); +void R_DrawColumnClamped_8(void); void R_DrawShadeColumn_8(void); void R_DrawTranslucentColumn_8(void); +void R_DrawTranslucentColumnClamped_8(void); void R_DrawDropShadowColumn_8(void); void R_DrawTranslatedColumn_8(void); void R_DrawTranslatedTranslucentColumn_8(void); diff --git a/src/r_draw8.c b/src/r_draw8.c index 99fb71e289343034bc6327314da0e64b0d687dab..735127f88d12daafc0161ea080195ce66d4b3db1 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -100,6 +100,98 @@ 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]]; + } + } + } +} + /** \brief The R_DrawShadeColumn_8 function Experiment to make software go faster. Taken from the Boom source */ @@ -212,6 +304,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 diff --git a/src/r_main.c b/src/r_main.c index 4624392944a931b4178f84038de2982f9ff371cb..067b8abdbcf20d9918d582285b6efbe9374f453d 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -390,22 +390,22 @@ fixed_t R_PointToDist(fixed_t x, fixed_t y) return R_PointToDist2(viewx, viewy, x, y); } -line_t *R_GetFFloorLine(const seg_t *seg, const ffloor_t *pfloor) +line_t *R_GetFFloorLine(const line_t *line, const ffloor_t *pfloor, const sector_t *sector) { if (pfloor->master->flags & ML_TFERLINE) { - size_t linenum = seg->linedef - pfloor->target->lines[0]; + size_t linenum = min((size_t)(line - sector->lines[0]), pfloor->master->frontsector->linecount); return pfloor->master->frontsector->lines[0] + linenum; } else return pfloor->master; } -side_t *R_GetFFloorSide(const seg_t *seg, const ffloor_t *pfloor) +side_t *R_GetFFloorSide(const line_t *line, const ffloor_t *pfloor, const sector_t *sector) { if (pfloor->master->flags & ML_TFERLINE) { - line_t *newline = R_GetFFloorLine(seg, pfloor); + line_t *newline = R_GetFFloorLine(line, pfloor, sector); return &sides[newline->sidenum[0]]; } else diff --git a/src/r_main.h b/src/r_main.h index aedfeb6ad0f2ca2a0caaba771f38e44ad29e1142..64a69fffe64d0096241d2eca6c25b528069e8aaf 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -86,8 +86,8 @@ 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 seg_t *seg, const ffloor_t *pfloor); -side_t *R_GetFFloorSide(const seg_t *seg, const ffloor_t *pfloor); +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 diff --git a/src/r_picformats.c b/src/r_picformats.c index e4a59f2115d3833b3f5a76e38ff4a1cdd7d4ce30..d71657021b6e2cc91efe504b49286f459461095d 100644 --- a/src/r_picformats.c +++ b/src/r_picformats.c @@ -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..098f927a5619d74ca9813d37658d5bfb75bc8f04 100644 --- a/src/r_picformats.h +++ b/src/r_picformats.h @@ -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_segs.c b/src/r_segs.c index e07ced86a7c6002c7bd127c1e2867bdae5386419..75c95aa9345702b3dd989e57c3f2f20cc1499096 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -442,26 +442,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 + (INT64)dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow - sprtopscreen = INT32_MAX; - else - sprtopscreen += dc_texheight*spryscale; + break; + + topscreen += texheight; } + + sprtopscreen = sprbotscreen; } static void R_DrawRepeatFlippedMaskedColumn(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; + sprbotscreen = bottomscreen + scroll; + R_DrawFlippedMaskedColumn(col, lengthcol); + if ((INT64)sprtopscreen + (INT64)dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow - sprtopscreen = INT32_MAX; - else - sprtopscreen += dc_texheight*spryscale; + break; + + topscreen += texheight; } + + sprtopscreen = sprbotscreen; } // Returns true if a fake floor is translucent. @@ -497,7 +546,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) sector_t tempsec; INT32 templight; INT32 i, p; - fixed_t offsetvalue; lightlist_t *light; r_lightlist_t *rlight; INT32 range; @@ -515,6 +563,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) fixed_t wall_scalex, wall_scaley; UINT8 vertflip; unsigned lengthcol; + boolean fog = false; + boolean fuzzy = false; void (*colfunc_2s) (column_t *, unsigned); @@ -526,13 +576,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 = R_GetFFloorSide(curline, pfloor); - - colfunc = colfuncs[BASEDRAWFUNC]; + sidedef = R_GetFFloorSide(curline->linedef, pfloor, pfloor->target); if (pfloor->master->flags & ML_TFERLINE) { - line_t *newline = R_GetFFloorLine(curline, pfloor); + line_t *newline = R_GetFFloorLine(curline->linedef, pfloor, pfloor->target); do_texture_skew = newline->flags & ML_SKEWTD; dont_peg_bottom = newline->flags & ML_DONTPEGBOTTOM; } @@ -547,7 +595,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) 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 @@ -560,17 +608,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) @@ -673,9 +718,9 @@ 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) + else if (fog) lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT); - else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) + else if (fuzzy) lightnum = LIGHTLEVELS-1; else lightnum = R_FakeFlat(frontsector, &tempsec, &templight, &templight, false) @@ -703,6 +748,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) 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; @@ -734,7 +787,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) { @@ -744,7 +797,7 @@ 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) @@ -753,7 +806,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) ffloortextureslide = FixedMul(R_GetSlopeTextureSlide(skewslope, lineangle), wall_scaley); } - dc_texturemid += offsetvalue; + dc_texturemid += repeatscroll; // Texture must be cached R_CheckTextureCache(texnum); @@ -824,15 +877,41 @@ 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] + 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 = R_DrawTranslucentColumnClamped_8; + else + colfunc = R_DrawColumnClamped_8; + } + } + // SoM: New code does not rely on R_DrawColumnShadowed_8 which // will (hopefully) put less strain on the stack. if (dc_numlights) @@ -947,7 +1026,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (windowtop < windowbottom) colfunc_2s (col, lengthcol); - spryscale += rw_scalestep; + yscale += scalestep; continue; } @@ -966,7 +1045,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]; diff --git a/src/r_skins.c b/src/r_skins.c index 2029b4effb7184339f8ea2a906f28d0604447320..cd7d60b53e4c572630e26980309729a121d43cb7 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -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; +} + +// 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; - if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2) + 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; @@ -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,7 +632,7 @@ 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]); diff --git a/src/r_skins.h b/src/r_skins.h index cc3b63cbed2c97de3fc312ad338d6f201edcd65b..1f2c57472d23ffd3026f0370e591dcd18ad77193 100644 --- a/src/r_skins.h +++ b/src/r_skins.h @@ -80,9 +80,14 @@ 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; } skin_t; /// Externs @@ -102,7 +107,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_textures.c b/src/r_textures.c index 59cc114139c5abb24df0f47fa0dddd0e70ec8d72..5d3fe24db2c942647d514a92ad42a759d0b3c9f4 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -821,8 +821,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 { @@ -1068,6 +1068,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_GetNumForName(name); + } + + return lump; +} + static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) { char *texturesToken; @@ -1240,13 +1332,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; diff --git a/src/r_things.c b/src/r_things.c index 64226990961896ce934c5a9a42a1e8e8f967a497..fb9757a9ae077703433b2ad4bc8a3a1fc166d12b 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -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,201 @@ 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; + } + 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)) + 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], 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 +476,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 +524,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 +565,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; - - case SRF_SINGLE: - // only the first rotation is needed - break; + if (longname) + MirrorMissingRotations(); - 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 +589,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 +630,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 +839,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; @@ -690,10 +911,12 @@ void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol) if (!post->length) continue; - 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; @@ -1579,20 +1802,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]; diff --git a/src/r_things.h b/src/r_things.h index f68d75a837ef698bcb98fc4e6dc568f97bf8881a..3daf55c4235bc753aeb5f1c897856e6d9303338c 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -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) diff --git a/src/s_sound.c b/src/s_sound.c index aa049899ff602cf6a1f7af4c287d8f3673bf5597..32353a59c2d590dd8ea1f74b47399de0886684d0 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -2256,9 +2256,9 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 return; 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/sdl/CMakeLists.txt b/src/sdl/CMakeLists.txt index 5aca04d120c39287eec5c2097aa6375e52eb27fb..ee48fa2b154568889c50d4e0a6c8d97c5c2a7bf0 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,161 @@ 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 ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + target_compile_options(SRB2SDL2 PRIVATE -mno-ms-bitfields) +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 + -pedantic + -Wpedantic + -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 +216,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 +229,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/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 9f0fa0250a664dfe020d649ac65ccb347a63a3c8..8bae550b0b12c1cc40fa166d6dc9963946a4c11d 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -271,75 +271,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) @@ -2305,7 +2316,7 @@ void I_SleepDuration(precise_t duration) int status; do status = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts); while (status == EINTR); -#else +#elif defined (MIN_SLEEP_DURATION_MS) UINT64 precision = I_GetPrecisePrecision(); INT32 sleepvalue = cv_sleep.value; UINT64 delaygranularity; @@ -3275,4 +3286,18 @@ 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 76fe172fce0e27f46ceb491be5a43f1b3e72f770..249be61f69dd054824e6a21b755130226ccb4957 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -382,6 +382,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) diff --git a/src/st_stuff.c b/src/st_stuff.c index 083bb52243be4e69bfaa1faffc51d96cec1d620a..e088a448c129ed6e2392e8bcadf3cb62e9932525 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -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) @@ -1267,19 +1269,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); \ } \ @@ -1551,13 +1553,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 { @@ -1567,6 +1572,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; @@ -1749,22 +1755,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; @@ -1772,31 +1779,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; } @@ -1906,7 +1919,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". { @@ -1953,7 +1966,7 @@ static void ST_drawNiGHTSHUD(void) 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); diff --git a/src/string.c b/src/string.c index 2f16fa4c68a35fa287156f546fc2973e9d4ad426..b24e12e6e36fec3078aaae76bee7a765f9c30c8f 100644 --- a/src/string.c +++ b/src/string.c @@ -68,3 +68,27 @@ 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/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 355bdf860160dced8d8baad8679ba86c68ed4582..3beb435b58428491e5b62f3ce48ec35535c25f60 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1923,70 +1923,37 @@ 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); - + if (w == 0) w = BASEVIDWIDTH; w -= x; @@ -1995,814 +1962,104 @@ char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) switch (option & V_SPACINGMASK) { case V_MONOSPACE: - spacewidth = 8; - /* FALLTHRU */ - case V_OLDSPACING: - charwidth = 8; - break; - case V_6WIDTHSPACE: - spacewidth = 6; - default: - break; - } - - for (i = 0; i < slen; ++i) - { - c = newstring[i]; - if ((UINT8)c & 0x80) //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 ? charwidth : hu_font[c]->width); - - x += chw; - - if (lastusablespace != 0 && x > w) - { - newstring[lastusablespace] = '\n'; - i = lastusablespace; - lastusablespace = 0; - 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) -{ - INT32 w, c, cx = x, cy = y, dup, scrwidth, center = 0, left = 0; - const char *ch = string; - INT32 charflags = (option & V_CHARCOLORMASK); - const UINT8 *colormap = NULL; - INT32 spacewidth = 4, 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; - - 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; - 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; - - 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; - continue; - } - - if (charwidth) - { - w = charwidth * dup; - center = w/2 - hu_font[c]->width*dup/2; - } - else - w = hu_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 + center)<<FRACBITS, cy<<FRACBITS, FRACUNIT, option, hu_font[c], colormap); - - cx += w; - } -} - -void V_DrawCenteredString(INT32 x, INT32 y, INT32 option, const char *string) -{ - x -= V_StringWidth(string, option)/2; - V_DrawString(x, y, option, string); -} - -void V_DrawRightAlignedString(INT32 x, INT32 y, INT32 option, const char *string) -{ - x -= V_StringWidth(string, option); - V_DrawString(x, y, option, string); -} - -// -// 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; - - 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; - else - cy += 6*dup; - - continue; - } - - c = *ch; - if (!lowercase) - c = toupper(c); - c -= HU_FONTSTART; - - if (c < 0 || c >= HU_FONTSIZE || !hu_font[c]) - { - cx += spacewidth * dup; - 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 > scrwidth) - continue; - if (cx+left + w < 0) //left boundary check - { - cx += w; - continue; - } - - colormap = V_GetStringColormap(charflags); - V_DrawFixedPatch((cx + center)<<FRACBITS, cy<<FRACBITS, FRACUNIT/2, option, hu_font[c], colormap); - - cx += w; - } -} - -void V_DrawCenteredSmallString(INT32 x, INT32 y, INT32 option, const char *string) -{ - x -= V_SmallStringWidth(string, option)/2; - V_DrawSmallString(x, y, option, string); -} - - -void V_DrawRightAlignedSmallString(INT32 x, INT32 y, INT32 option, const char *string) -{ - x -= V_SmallStringWidth(string, option); - V_DrawSmallString(x, y, option, string); -} - -// -// 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) -{ - INT32 w, c, cx = x, cy = y, 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_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 = 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; - - 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]) - { - cx += spacewidth * dup; - continue; - } - - if (charwidth) - w = charwidth * dup; - else - w = tny_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, tny_font[c], colormap); - - 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) -{ - 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... - - 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 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; + default: + break; + } + for (i = 0; i < slen; ++i) + { + c = newstring[i]; + if ((UINT8)c & 0x80) //color parsing! -Inuyasha 2.16.09 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]) + if (c == '\n') { - cx += (spacewidth * dup)<<FRACBITS; + x = 0; + lastusablespace = 0; continue; } - if (charwidth) + c = (option & V_ALLOWLOWERCASE ? c : toupper(c)) - FONTSTART; + if (c < 0 || c >= FONTSIZE || !font.chars[c]) { - w = charwidth * dup; - center = w/2 - tny_font[c]->width*(dup/2); + chw = spacewidth; + lastusablespace = i; } else - w = tny_font[c]->width * dup; + chw = (charwidth ? charwidth : font.chars[c]->width); - if ((cx>>FRACBITS) > scrwidth) - break; - if ((cx>>FRACBITS)+left + w < 0) //left boundary check + x += FixedMul(chw, scale); + + if (lastusablespace != 0 && x > w) { - cx += w<<FRACBITS; - continue; + newstring[lastusablespace] = '\n'; + i = lastusablespace; + lastusablespace = x = 0; } - - colormap = V_GetStringColormap(charflags); - - V_DrawFixedPatch(cx + (center<<FRACBITS), cy, FRACUNIT, option, tny_font[c], colormap); - - cx += w<<FRACBITS; } + return newstring; } -void V_DrawCenteredThinStringAtFixed(fixed_t x, fixed_t 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) { - x -= (V_ThinStringWidth(string, option) / 2)<<FRACBITS; - V_DrawThinStringAtFixed(x, y, option, string); + V_DrawFontStringAtFixed((fixed_t)x<<FRACBITS, (fixed_t)y<<FRACBITS, option, pscale, vscale, string, font); } -void V_DrawRightAlignedThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) +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) { - x -= V_ThinStringWidth(string, option)<<FRACBITS; - V_DrawThinStringAtFixed(x, y, option, string); + V_DrawAlignedFontStringAtFixed((fixed_t)x<<FRACBITS, (fixed_t)y<<FRACBITS, option, pscale, vscale, string, font, align); } -// Draws a small string at a fixed_t location. -void V_DrawSmallThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) +// 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) { fixed_t cx = x, cy = y; - INT32 w, c, dup, scrwidth, center = 0, left = 0; + INT32 w, c, dupx, dupy, scrwidth, center = 0, left = 0; const char *ch = string; - INT32 charflags = 0; - const UINT8 *colormap = NULL; - INT32 spacewidth = 2<<FRACBITS, charwidth = 0; + INT32 charflags = (option & V_CHARCOLORMASK); + 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<<FRACBITS; + dupx = vid.dup<<FRACBITS; + dupy = vid.dup<<FRACBITS; scrwidth = vid.width; } else { - dup = FRACUNIT; + dupx = pscale; + dupy = vscale; scrwidth = FixedDiv(vid.width<<FRACBITS, vid.dup); - left = ((scrwidth - (BASEVIDWIDTH<<FRACBITS))/2); + left = (scrwidth - (BASEVIDWIDTH << FRACBITS))/2; scrwidth -= left; } if (option & V_NOSCALEPATCH) scrwidth *= vid.dup; - charflags = (option & V_CHARCOLORMASK); - - switch (option & V_SPACINGMASK) + switch (option & V_SPACINGMASK) // TODO: 2.3: drop support for these crusty flags { case V_MONOSPACE: - spacewidth = 4<<FRACBITS; + spacewidth = font.charwidth; /* FALLTHRU */ case V_OLDSPACING: - charwidth = 4<<FRACBITS; + charwidth = font.charwidth; break; case V_6WIDTHSPACE: - spacewidth = 3<<FRACBITS; + spacewidth = 6; default: break; } @@ -2821,61 +2078,66 @@ void V_DrawSmallThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char if (*ch == '\n') { cx = x; - - if (option & V_RETURN8) - cy += 4*dup; - else - cy += 6*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 || !tny_font[c]) + c = (lowercase ? *ch : toupper(*ch)) - FONTSTART; + if (c < 0 || c >= FONTSIZE || !font.chars[c]) { - cx += FixedMul(spacewidth, dup); + cx += FixedMul((spacewidth<<FRACBITS), dupx); continue; } if (charwidth) { - w = FixedMul(charwidth, dup); - center = w/2 - tny_font[c]->width*(dup/4); + w = FixedMul((charwidth<<FRACBITS), dupx); + center = w/2 - FixedMul(font.chars[c]->width<<FRACBITS, (dupx/2)); } else - w = tny_font[c]->width * dup / 2; + w = FixedMul(font.chars[c]->width<<FRACBITS, dupx); - if (cx > scrwidth) - break; + if ((cx>>FRACBITS) > scrwidth) + continue; 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); + V_DrawStretchyFixedPatch(cx + center, cy, pscale, vscale, option, font.chars[c], V_GetStringColormap(charflags)); - cx += w; + cx += w + (font.kerning<<FRACBITS); } } -void V_DrawCenteredSmallThinStringAtFixed(fixed_t x, fixed_t 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_SmallThinStringWidth(string, option)/4; - V_DrawSmallThinStringAtFixed(x, y, option, string); -} + char *text = strdup(string); + char* line = xstrtok(text, "\n"); + fixed_t lx = x, ly = y; -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); + 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; + } + + V_DrawFontStringAtFixed(lx, ly, option, pscale, vscale, line, font); + + ly += FixedMul(((option & V_RETURN8) ? 8 : font.linespacing)<<FRACBITS, vscale); + + line = xstrtok(NULL, "\n"); + } } // Draws a tallnum. Replaces two functions in y_inter and st_stuff @@ -2940,56 +2202,21 @@ void V_DrawLevelActNum(INT32 x, INT32 y, INT32 flags, UINT8 num) } } -// 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) +// Returns the width of the act num patch(es) +INT16 V_LevelActNumWidth(UINT8 num) { - INT32 w, c, dup, scrwidth = BASEVIDWIDTH; - fixed_t cx = x, cy = y; - const char *ch = string; + INT16 result = 0; - // It's possible for string to be a null pointer - if (!string) - return; + if (num == 0) + result = ttlnum[num]->width; - if (option & V_NOSCALESTART) + while (num > 0 && num <= 99) { - dup = vid.dup; - scrwidth = vid.width; + result = result + ttlnum[num%10]->width; + num = num/10; } - 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; - } + return result; } // Draw a string using the nt_font @@ -3030,21 +2257,18 @@ static void V_DrawNameTagLine(INT32 x, INT32 y, INT32 option, fixed_t scale, UIN if (*ch == '\n') { cx = x<<FRACBITS; - cy += FixedMul((21*dup)*FRACUNIT, scale); + cy += FixedMul((ntb_font.linespacing * 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]) + c = toupper(*ch) - FONTSTART; + if (c < 0 || c >= FONTSIZE || !ntb_font.chars[c] || !nto_font.chars[c]) { - cx += FixedMul((4 * dup)*FRACUNIT, scale); + cx += FixedMul((ntb_font.spacewidth * dup)*FRACUNIT, scale); continue; } - w = FixedMul(((ntb_font[c]->width)+2 * dup) * FRACUNIT, scale); + w = FixedMul(((ntb_font.chars[c]->width)+ntb_font.kerning * dup) * FRACUNIT, scale); if (FixedInt(cx) > scrwidth) continue; @@ -3054,8 +2278,8 @@ static void V_DrawNameTagLine(INT32 x, INT32 y, INT32 option, fixed_t scale, UIN continue; } - V_DrawFixedPatch(cx, cy, scale, option, nto_font[c], outlinecolormap); - V_DrawFixedPatch(cx, cy, scale, option, ntb_font[c], basecolormap); + V_DrawFixedPatch(cx, cy, scale, option, nto_font.chars[c], outlinecolormap); + V_DrawFixedPatch(cx, cy, scale, option, ntb_font.chars[c], basecolormap); cx += w; } @@ -3170,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; @@ -3364,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; @@ -3381,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; - - switch (option & V_SPACINGMASK) - { - case V_MONOSPACE: - spacewidth = 4; - /* FALLTHRU */ - case V_OLDSPACING: - charwidth = 4; - break; - case V_6WIDTHSPACE: - spacewidth = 3; - default: - break; - } + INT32 c, h = 0, result = 0; - 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..d37762466147ae843c8f0fba5218f4e8af3f6462 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -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/w_wad.c b/src/w_wad.c index 0666c4a600bcf20678f88539fb4055a0d5466992..cc7cdc20167d616083d86db652b05aa8eb182e5e 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -98,6 +98,7 @@ typedef struct lumpnum_cache_s { char lumpname[32]; lumpnum_t lumpnum; + UINT32 hash; } lumpnum_cache_t; static lumpnum_cache_t lumpnumcache[LUMPNUMCACHESIZE]; @@ -1349,6 +1350,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); @@ -1434,6 +1476,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. @@ -1446,17 +1545,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--) @@ -1470,12 +1562,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; + + AddLumpToCache(lumpnum, name, false); - return lumpnumcache[lumpnumcacheindex].lumpnum; + return lumpnum; } } @@ -1493,16 +1584,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--) @@ -1515,16 +1600,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; + + AddLumpToCache(lumpnum, name, true); - return (i << 16) + check; + return lumpnum; } } @@ -1606,6 +1687,159 @@ 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, end; + 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); + } + 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 @@ -2250,10 +2484,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); } @@ -2261,10 +2495,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 diff --git a/src/w_wad.h b/src/w_wad.h index e043e4d62c82f061ce505c4ce6b6a2298d48a4ec..3dcb9b6e8bbc6ee11669f473e9395a0006f84db0 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -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/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 19aa22c9b7a17613910dbdc9f28717e16e604986..5114cbe2c81432173409cce5a113ea9305b5b23b 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -1,23 +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() - -if("${SRB2_CONFIG_USE_GME}") - include("cpm-libgme.cmake") -endif() +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 0bb404e4c90fc6e9e5ff79314f0703a1aa4ae9a6..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.28.5 - GITHUB_REPOSITORY "libsdl-org/SDL" - GIT_TAG release-2.28.5 - 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..5c3aa26e35882d64ca8a6cf99517d28e9fc56dcc 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,25 @@ 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..a52b11584ae747630ed4c44af6282fb8cc9dea75 --- /dev/null +++ b/thirdparty/sdl2-mixer-ext.cmake @@ -0,0 +1,39 @@ +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..257609f775ae9f7c325665198f0e8804a5cb6030 --- /dev/null +++ b/thirdparty/zlib.cmake @@ -0,0 +1,36 @@ +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 + } + ] +}