From 6c68e4bf17e57d66d2f79b250f460c71aef76f77 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 6 Dec 2023 12:13:50 +0100 Subject: [PATCH 001/596] add alias to the zerotier library --- 3rdParty/libzt/CMakeLists.txt | 2 ++ CMakeLists.txt | 6 +----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/3rdParty/libzt/CMakeLists.txt b/3rdParty/libzt/CMakeLists.txt index 0f4ce16417f..ae45fae5a33 100644 --- a/3rdParty/libzt/CMakeLists.txt +++ b/3rdParty/libzt/CMakeLists.txt @@ -74,3 +74,5 @@ endif() if(MSVC) target_compile_definitions(libnatpmp_obj PRIVATE -DSTATICLIB) endif() + +add_library(zt ALIAS ${libzt_LIB_NAME}) diff --git a/CMakeLists.txt b/CMakeLists.txt index 35637c45008..9f57b39e636 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -830,11 +830,7 @@ if(TCPIP) target_link_libraries(${BIN_TARGET} PRIVATE asio) endif() if(ZEROTIER) - if(NOT ANDROID) - target_link_libraries(${BIN_TARGET} PRIVATE zt-static) - else() - target_link_libraries(${BIN_TARGET} PRIVATE zt-shared) - endif() + target_link_libraries(${BIN_TARGET} PRIVATE zt) endif() # Defines without value From 544c91cafe0358024be4a2b3275c90825d7ce66a Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 6 Dec 2023 12:17:47 +0100 Subject: [PATCH 002/596] adjust zerotier-build - switch to own repository - set build-name based on the built target - do not suppress warnings (libzt does it anyway...) - no need to set STATICLIB --- 3rdParty/libzt/CMakeLists.txt | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/3rdParty/libzt/CMakeLists.txt b/3rdParty/libzt/CMakeLists.txt index ae45fae5a33..dddd1696cb5 100644 --- a/3rdParty/libzt/CMakeLists.txt +++ b/3rdParty/libzt/CMakeLists.txt @@ -1,14 +1,26 @@ include(FetchContent_MakeAvailableExcludeFromAll) -set(BUILD_HOST_SELFTEST OFF) +set(BUILD_HOST_SELFTEST FALSE) +set(BUILD_STATIC_LIB TRUE) +set(BUILD_SHARED_LIB FALSE) +set(ALLOW_INSTALL_TARGET FALSE) +set(OMIT_JSON_SUPPORT TRUE) include(FetchContent) FetchContent_Declare(libzt - GIT_REPOSITORY https://github.com/diasurgical/libzt.git - GIT_TAG 47e38259e9c99ba2d8e7241515fa1b56cb538c8c) + #GIT_REPOSITORY https://github.com/diasurgical/libzt.git + #GIT_TAG 47e38259e9c99ba2d8e7241515fa1b56cb538c8c) + GIT_REPOSITORY https://github.com/pionere/libzt.git + GIT_TAG 9c5e17523dff33e63fef7bb17f667c2d944e6049) FetchContent_MakeAvailableExcludeFromAll(libzt) -if(NOT ANDROID) +#if(NOT ANDROID) +# set(libzt_LIB_NAME zt-static) +# #set(libzt_LIB_NAME zt-shared) +#else() +# set(libzt_LIB_NAME zt-shared) +#endif() +if(TARGET zt-static) set(libzt_LIB_NAME zt-static) else() set(libzt_LIB_NAME zt-shared) @@ -30,7 +42,7 @@ foreach( ) if(TARGET ${lib_name}) # External library, ignore all warnings - target_compile_options(${lib_name} PRIVATE -w) + #target_compile_options(${lib_name} PRIVATE -w) endif() endforeach(lib_name) @@ -71,8 +83,8 @@ if(MINGW_CROSS) target_link_libraries(${libzt_LIB_NAME} mingw_stdthreads) endif() -if(MSVC) - target_compile_definitions(libnatpmp_obj PRIVATE -DSTATICLIB) -endif() +#if(MSVC AND TARGET libnatpmp_obj) +# target_compile_definitions(libnatpmp_obj PRIVATE -DSTATICLIB) +#endif() add_library(zt ALIAS ${libzt_LIB_NAME}) From 44c0d49269b55c20ef5f4bc5e8ab35f489633e21 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 6 Dec 2023 12:25:13 +0100 Subject: [PATCH 003/596] add guard to sdl2_backports.h II. --- Source/utils/sdl_ptrs.h | 3 --- tools/patcher/utils/sdl_ptrs.h | 3 --- 2 files changed, 6 deletions(-) diff --git a/Source/utils/sdl_ptrs.h b/Source/utils/sdl_ptrs.h index e47f8dc7be6..35c9953cb76 100644 --- a/Source/utils/sdl_ptrs.h +++ b/Source/utils/sdl_ptrs.h @@ -7,11 +7,8 @@ #include #include -#ifdef USE_SDL1 #include "utils/sdl2_to_1_2_backports.h" -#else #include "utils/sdl2_backports.h" -#endif #include "../defs.h" diff --git a/tools/patcher/utils/sdl_ptrs.h b/tools/patcher/utils/sdl_ptrs.h index e47f8dc7be6..35c9953cb76 100644 --- a/tools/patcher/utils/sdl_ptrs.h +++ b/tools/patcher/utils/sdl_ptrs.h @@ -7,11 +7,8 @@ #include #include -#ifdef USE_SDL1 #include "utils/sdl2_to_1_2_backports.h" -#else #include "utils/sdl2_backports.h" -#endif #include "../defs.h" From fd7823916daa10d45ea84ad2e3b75af5faf15b17 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 7 Dec 2023 09:07:42 +0100 Subject: [PATCH 004/596] turn on zerotier by default --- .github/workflows/nightly.yml | 20 ++++++++++---------- 3rdParty/libzt/CMakeLists.txt | 2 +- CMakeLists.txt | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index a3be4214222..6ba11b98b6f 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -42,11 +42,11 @@ jobs: # x86 builds - name: diablo-x86 packages: 'sdl2:x86-windows libsodium:x86-windows' - cmakeargs: '-A Win32 -D_WIN32_WINNT=0x0501 -D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON' + cmakeargs: '-A Win32 -D_WIN32_WINNT=0x0600 -D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON' artifact: 'diablo-nightly-x86.zip' - name: hellfire-x86 packages: 'sdl2:x86-windows libsodium:x86-windows' - cmakeargs: '-A Win32 -D_WIN32_WINNT=0x0501 -D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON -D HELLFIRE=ON' + cmakeargs: '-A Win32 -D_WIN32_WINNT=0x0600 -D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON -D HELLFIRE=ON' artifact: 'hellfire-nightly-x86.zip' - name: hellmini-x86 packages: 'sdl2:x86-windows' @@ -546,16 +546,16 @@ jobs: #name: [diablo, hellfire] include: - name: diablo - cmakeargs: '' + cmakeargs: '-DZEROTIER=OFF' artifact: 'diablo-nightly-rg350.opk' - name: hellfire - cmakeargs: '-DHELLFIRE=ON' + cmakeargs: '-DZEROTIER=OFF -DHELLFIRE=ON' artifact: 'hellfire-nightly-rg350.opk' - name: diablo-rgp - cmakeargs: '-D USE_PATCH=ON' + cmakeargs: '-DZEROTIER=OFF -D USE_PATCH=ON' artifact: 'diablo-nightly-rg350p.opk' - name: hellfire-rgp - cmakeargs: '-D USE_PATCH=ON -DHELLFIRE=ON' + cmakeargs: '-DZEROTIER=OFF -D USE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-rg350p.opk' runs-on: ubuntu-22.04 steps: @@ -652,16 +652,16 @@ jobs: #name: [diablo, hellfire] include: - name: diablo - cmakeargs: '' + cmakeargs: '-DZEROTIER=OFF' artifact: 'diablo-nightly-retrofw.opk' - name: hellfire - cmakeargs: '-DHELLFIRE=ON' + cmakeargs: '-DZEROTIER=OFF -DHELLFIRE=ON' artifact: 'hellfire-nightly-retrofw.opk' - name: diablo-rtrp - cmakeargs: '-D USE_PATCH=ON' + cmakeargs: '-DZEROTIER=OFF -D USE_PATCH=ON' artifact: 'diablo-nightly-retrofwp.opk' - name: hellfire-rtrp - cmakeargs: '-D USE_PATCH=ON -DHELLFIRE=ON' + cmakeargs: '-DZEROTIER=OFF -D USE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-retrofwp.opk' runs-on: ubuntu-latest steps: diff --git a/3rdParty/libzt/CMakeLists.txt b/3rdParty/libzt/CMakeLists.txt index dddd1696cb5..1c4b99fdf0e 100644 --- a/3rdParty/libzt/CMakeLists.txt +++ b/3rdParty/libzt/CMakeLists.txt @@ -11,7 +11,7 @@ FetchContent_Declare(libzt #GIT_REPOSITORY https://github.com/diasurgical/libzt.git #GIT_TAG 47e38259e9c99ba2d8e7241515fa1b56cb538c8c) GIT_REPOSITORY https://github.com/pionere/libzt.git - GIT_TAG 9c5e17523dff33e63fef7bb17f667c2d944e6049) + GIT_TAG 08a848ae3363984edf27667222bc410ad2144f57) FetchContent_MakeAvailableExcludeFromAll(libzt) #if(NOT ANDROID) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f57b39e636..c68834f497d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -159,7 +159,7 @@ cmake_dependent_option(INET_MODE "Enable validation of network messages" OFF "NO cmake_dependent_option(ADAPTIVE_NETUPDATE "Build adaptive network support" ON "NOT NONET" OFF) cmake_dependent_option(NETENCRYPT "Encrypt network messages" ON "NOT NONET" OFF) cmake_dependent_option(TCPIP "Build with tcp/ip support" ON "NOT NONET" OFF) -cmake_dependent_option(ZEROTIER "Build with zerotier support" OFF "NOT NONET" OFF) +cmake_dependent_option(ZEROTIER "Build with zerotier support" ON "NOT NONET AND NOT HOSTONLY" OFF) cmake_dependent_option(NOHOSTING "Disable support for host-only games" ON "TCPIP" ON) cmake_dependent_option(HOSTONLY "Disable support for non host-only games" OFF "TCPIP AND NOT NOHOSTING" OFF) cmake_dependent_option(DISABLE_EXCEPTIONS "Disable exceptions" ON "NONET" OFF) From f7c2a353859936dcbf42702b546ae0f0d1d6a70c Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 8 Dec 2023 11:47:25 +0100 Subject: [PATCH 005/596] cosmetic --- .github/workflows/nightly.yml | 78 +++++++++++++++++------------------ 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 6ba11b98b6f..2af690e918e 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -42,28 +42,28 @@ jobs: # x86 builds - name: diablo-x86 packages: 'sdl2:x86-windows libsodium:x86-windows' - cmakeargs: '-A Win32 -D_WIN32_WINNT=0x0600 -D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON' + cmakeargs: '-A Win32 -D_WIN32_WINNT=0x0600 -DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON' artifact: 'diablo-nightly-x86.zip' - name: hellfire-x86 packages: 'sdl2:x86-windows libsodium:x86-windows' - cmakeargs: '-A Win32 -D_WIN32_WINNT=0x0600 -D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON -D HELLFIRE=ON' + cmakeargs: '-A Win32 -D_WIN32_WINNT=0x0600 -DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-x86.zip' - name: hellmini-x86 packages: 'sdl2:x86-windows' - cmakeargs: '-A Win32 -D_WIN32_WINNT=0x0501 -D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON -D HELLFIRE=ON -D HAS_JOYSTICK=OFF -D HAS_DPAD=OFF -D HAS_GAMECTRL=OFF -D HAS_TOUCHPAD=OFF -D HAS_KBCTRL=OFF -D NONET=ON -D NOSOUND=ON -D SCREEN_WIDTH=640 -D SCREEN_HEIGHT=480 -D NOWIDESCREEN=ON' + cmakeargs: '-A Win32 -D_WIN32_WINNT=0x0501 -DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON -DHAS_JOYSTICK=OFF -DHAS_DPAD=OFF -DHAS_GAMECTRL=OFF -DHAS_TOUCHPAD=OFF -DHAS_KBCTRL=OFF -DNONET=ON -DNOSOUND=ON -DSCREEN_WIDTH=640 -DSCREEN_HEIGHT=480 -DNOWIDESCREEN=ON' artifact: 'hellmini-nightly-x86.zip' - name: hellsrv-x86 packages: 'sdl2:x86-windows libsodium:x86-windows' - cmakeargs: '-A Win32 -D_WIN32_WINNT=0x0501 -D NOHOSTING=OFF -D HOSTONLY=ON -D INET_MODE=ON -D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON -D HELLFIRE=ON -D HAS_JOYSTICK=OFF -D HAS_DPAD=OFF -D HAS_GAMECTRL=OFF -D HAS_TOUCHPAD=OFF -D HAS_KBCTRL=OFF -D NOSOUND=ON -D SCREEN_WIDTH=640 -D SCREEN_HEIGHT=480 -D NOWIDESCREEN=ON' + cmakeargs: '-A Win32 -D_WIN32_WINNT=0x0501 -DNOHOSTING=OFF -DHOSTONLY=ON -DINET_MODE=ON -DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON -DHAS_JOYSTICK=OFF -DHAS_DPAD=OFF -DHAS_GAMECTRL=OFF -DHAS_TOUCHPAD=OFF -DHAS_KBCTRL=OFF -DNOSOUND=ON -DSCREEN_WIDTH=640 -DSCREEN_HEIGHT=480 -DNOWIDESCREEN=ON' artifact: 'hellsrv-nightly-x86.zip' # x64 builds - name: diablo packages: 'sdl2:x64-windows libsodium:x64-windows' - cmakeargs: '-D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON' + cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON' artifact: 'diablo-nightly-x64.zip' - name: hellfire packages: 'sdl2:x64-windows libsodium:x64-windows' - cmakeargs: '-D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON -D HELLFIRE=ON' + cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-x64.zip' steps: - uses: actions/checkout@v4 @@ -87,7 +87,7 @@ jobs: - name: Configure CMake shell: bash working-directory: ${{ env.buildDir }} - run: cmake .. ${{ matrix.cmakeargs }} -D CMAKE_BUILD_TYPE="Release" -D CMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake + run: cmake .. ${{ matrix.cmakeargs }} -DCMAKE_BUILD_TYPE="Release" -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake - name: Build working-directory: ${{ env.buildDir }} @@ -114,10 +114,10 @@ jobs: include: # x86 builds - name: diablo-x86 - cmakeargs: '-D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON' + cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON' artifact: 'diablo-nightly-mingw-x86.zip' - name: hellfire-x86 - cmakeargs: '-D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON -D HELLFIRE=ON' + cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-mingw-x86.zip' steps: - uses: actions/checkout@v4 @@ -134,7 +134,7 @@ jobs: - name: Configure CMake shell: bash working-directory: ${{github.workspace}} - run: cmake -S. -Bbuild ${{ matrix.cmakeargs }} -D CMAKE_BUILD_TYPE="Release" -D CMAKE_TOOLCHAIN_FILE=../CMake/mingwcc.toolchain.cmake + run: cmake -S. -Bbuild ${{ matrix.cmakeargs }} -DCMAKE_BUILD_TYPE="Release" -DCMAKE_TOOLCHAIN_FILE=../CMake/mingwcc.toolchain.cmake - name: Build working-directory: ${{github.workspace}} @@ -160,10 +160,10 @@ jobs: include: # x64 builds - name: diablo-x64 - cmakeargs: '-D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON' + cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON' artifact: 'diablo-nightly-mingw-x64.zip' - name: hellfire-x64 - cmakeargs: '-D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON -D HELLFIRE=ON' + cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-mingw-x64.zip' steps: - uses: actions/checkout@v4 @@ -180,7 +180,7 @@ jobs: - name: Configure CMake shell: bash working-directory: ${{github.workspace}} - run: cmake -S. -Bbuild ${{ matrix.cmakeargs }} -D CMAKE_BUILD_TYPE="Release" -D CMAKE_TOOLCHAIN_FILE=../CMake/mingwcc64.toolchain.cmake + run: cmake -S. -Bbuild ${{ matrix.cmakeargs }} -DCMAKE_BUILD_TYPE="Release" -DCMAKE_TOOLCHAIN_FILE=../CMake/mingwcc64.toolchain.cmake - name: Build working-directory: ${{github.workspace}} @@ -206,10 +206,10 @@ jobs: include: # x86 builds - name: diablo-w9x - cmakeargs: '-D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D USE_PATCH=ON -D NONET=ON' + cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DUSE_PATCH=ON -DNONET=ON' artifact: 'diablo-nightly-mingw-w9x.zip' - name: hellfire-w9x - cmakeargs: '-D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D USE_PATCH=ON -D NONET=ON -D HELLFIRE=ON' + cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DUSE_PATCH=ON -DNONET=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-mingw-w9x.zip' steps: - name: Checkout @@ -252,19 +252,19 @@ jobs: #name: [diablo, hellfire] include: - name: diablo - cmakeargs: '-D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D DEVILUTIONX_SYSTEM_SDL2=OFF' + cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF' artifact: 'diablo-nightly-x86_64-linux-gnu.tar.xz' appimage: 'diablo-nightly-x86_64-linux-gnu.appimage' - name: hellfire - cmakeargs: '-D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D DEVILUTIONX_SYSTEM_SDL2=OFF -D HELLFIRE=ON' + cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DHELLFIRE=ON' artifact: 'hellfire-nightly-x86_64-linux-gnu.tar.xz' appimage: 'hellfire-nightly-x86_64-linux-gnu.appimage' - name: diablo-uxp - cmakeargs: '-D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON' + cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON' artifact: 'diablo-nightly-x86_64-linux-gnup.tar.xz' appimage: 'diablo-nightly-x86_64-linux-gnup.appimage' - name: hellfire-uxp - cmakeargs: '-D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON -D HELLFIRE=ON' + cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-x86_64-linux-gnup.tar.xz' appimage: 'hellfire-nightly-x86_64-linux-gnup.appimage' runs-on: ubuntu-20.04 @@ -323,16 +323,16 @@ jobs: #name: [diablo, hellfire] include: - name: diablo-aa64 - cmakeargs: '-D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D DEVILUTIONX_SYSTEM_SDL2=OFF' + cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF' artifact: 'diablo-nightly-aarch64.tar.xz' - name: hellfire-aa64 - cmakeargs: '-D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D DEVILUTIONX_SYSTEM_SDL2=OFF -D HELLFIRE=ON' + cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DHELLFIRE=ON' artifact: 'hellfire-nightly-aarch64.tar.xz' - name: diablo-aa64p - cmakeargs: '-D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON' + cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON' artifact: 'diablo-nightly-aarch64p.tar.xz' - name: hellfire-aa64p - cmakeargs: '-D DEVILUTIONX_SYSTEM_LIBSODIUM=OFF -D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON -D HELLFIRE=ON' + cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-aarch64p.tar.xz' runs-on: ubuntu-20.04 steps: @@ -382,16 +382,16 @@ jobs: #name: [diablo, hellfire] include: - name: diablo-mac - cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF' + cmakeargs: '-DDEVILUTIONX_SYSTEM_SDL2=OFF' artifact: 'diablo-nightly-mac.dmg' - name: hellfire-mac - cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -D HELLFIRE=ON' + cmakeargs: '-DDEVILUTIONX_SYSTEM_SDL2=OFF -DHELLFIRE=ON' artifact: 'hellfire-nightly-mac.dmg' - name: diablo-macp - cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON' + cmakeargs: '-DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON' artifact: 'diablo-nightly-macp.dmg' - name: hellfire-macp - cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON -D HELLFIRE=ON' + cmakeargs: '-DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-macp.dmg' runs-on: macos-latest steps: @@ -405,7 +405,7 @@ jobs: - name: Configure CMake shell: bash working-directory: ${{github.workspace}} - run: cmake -S. -Bbuild -D MACOSX_STANDALONE_APP_BUNDLE=ON ${{ matrix.cmakeargs }} + run: cmake -S. -Bbuild -DMACOSX_STANDALONE_APP_BUNDLE=ON ${{ matrix.cmakeargs }} - name: Build working-directory: ${{github.workspace}} @@ -433,13 +433,13 @@ jobs: cmakeargs: '' artifact: 'diablo-nightly-ios.ipa' - name: hellfire-ios - cmakeargs: '-D HELLFIRE=ON' + cmakeargs: '-DHELLFIRE=ON' artifact: 'hellfire-nightly-ios.ipa' - name: diablo-iosp - cmakeargs: '-D USE_PATCH=ON' + cmakeargs: '-DUSE_PATCH=ON' artifact: 'diablo-nightly-iosp.ipa' - name: hellfire-iosp - cmakeargs: '-D USE_PATCH=ON -D HELLFIRE=ON' + cmakeargs: '-DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-iosp.ipa' runs-on: macos-latest steps: @@ -552,10 +552,10 @@ jobs: cmakeargs: '-DZEROTIER=OFF -DHELLFIRE=ON' artifact: 'hellfire-nightly-rg350.opk' - name: diablo-rgp - cmakeargs: '-DZEROTIER=OFF -D USE_PATCH=ON' + cmakeargs: '-DZEROTIER=OFF -DUSE_PATCH=ON' artifact: 'diablo-nightly-rg350p.opk' - name: hellfire-rgp - cmakeargs: '-DZEROTIER=OFF -D USE_PATCH=ON -DHELLFIRE=ON' + cmakeargs: '-DZEROTIER=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-rg350p.opk' runs-on: ubuntu-22.04 steps: @@ -605,10 +605,10 @@ jobs: cmakeargs: '-DHELLFIRE=ON' artifact: 'hellfire-nightly-lepus.opk' - name: diablo-lepp - cmakeargs: '-D USE_PATCH=ON' + cmakeargs: '-DUSE_PATCH=ON' artifact: 'diablo-nightly-lepusp.opk' - name: hellfire-lepp - cmakeargs: '-D USE_PATCH=ON -DHELLFIRE=ON' + cmakeargs: '-DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-lepusp.opk' runs-on: ubuntu-22.04 steps: @@ -658,10 +658,10 @@ jobs: cmakeargs: '-DZEROTIER=OFF -DHELLFIRE=ON' artifact: 'hellfire-nightly-retrofw.opk' - name: diablo-rtrp - cmakeargs: '-DZEROTIER=OFF -D USE_PATCH=ON' + cmakeargs: '-DZEROTIER=OFF -DUSE_PATCH=ON' artifact: 'diablo-nightly-retrofwp.opk' - name: hellfire-rtrp - cmakeargs: '-DZEROTIER=OFF -D USE_PATCH=ON -DHELLFIRE=ON' + cmakeargs: '-DZEROTIER=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-retrofwp.opk' runs-on: ubuntu-latest steps: @@ -714,10 +714,10 @@ jobs: cmakeargs: '-DHELLFIRE=ON' artifact: 'hellfire-nightly-ps4.pkg' - name: diablo-ps4p - cmakeargs: '-D USE_PATCH=ON' + cmakeargs: '-DUSE_PATCH=ON' artifact: 'diablo-nightly-ps4p.pkg' - name: hellfire-ps4p - cmakeargs: '-D USE_PATCH=ON -DHELLFIRE=ON' + cmakeargs: '-DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-ps4p.pkg' runs-on: ubuntu-22.04 steps: From a17b295de580a1de0ec0fe5b067be47139ad552f Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 8 Dec 2023 11:53:01 +0100 Subject: [PATCH 006/596] split handle_recv --- Source/dvlnet/protocol_zt.cpp | 7 +++-- Source/dvlnet/zt_client.cpp | 53 +++++++++++++++-------------------- Source/dvlnet/zt_client.h | 6 ++-- 3 files changed, 30 insertions(+), 36 deletions(-) diff --git a/Source/dvlnet/protocol_zt.cpp b/Source/dvlnet/protocol_zt.cpp index 7ab873c9612..2daf912595c 100644 --- a/Source/dvlnet/protocol_zt.cpp +++ b/Source/dvlnet/protocol_zt.cpp @@ -144,12 +144,13 @@ void protocol_zt::send_queued_all() void protocol_zt::recv_from_peers(zt_client* client) { - for (peer_connection& ap : active_connections) { + for (int pnum = 0; pnum < MAX_PLRS; pnum++) { + peer_connection& ap = active_connections[pnum]; if (ap.sock != -1) { recv_peer(ap); while (ap.recv_queue.packet_ready()) { buffer_t pkt_buf = ap.recv_queue.read_packet(); - client->handle_recv(ap.peer, pkt_buf); + client->handle_recv(pkt_buf, pnum); } } } @@ -167,7 +168,7 @@ void protocol_zt::recv_from_udp(zt_client* client) endpoint ep; ep.from_addr(in6.sin6_addr.un.u8_addr); buffer_t pkt_buf = buffer_t(recv_buffer.begin(), recv_buffer.begin() + len); - client->handle_recv(ep, pkt_buf); + client->handle_recv_oob(pkt_buf, ep); } } diff --git a/Source/dvlnet/zt_client.cpp b/Source/dvlnet/zt_client.cpp index 120f5ca1884..905b8e536df 100644 --- a/Source/dvlnet/zt_client.cpp +++ b/Source/dvlnet/zt_client.cpp @@ -27,15 +27,6 @@ plr_t zt_client::next_free_conn() return i < game_init_info.ngMaxPlayers ? i : MAX_PLRS; } -void zt_client::disconnect_peer(const endpoint& peer) -{ - for (plr_t i = 0; i < MAX_PLRS; i++) { - if (proto.active_connections[i].peer == peer) { - proto.disconnect(i); - } - } -} - bool zt_client::wait_network() { // wait for ZeroTier for 5 seconds @@ -215,13 +206,21 @@ void zt_client::poll() } } -void zt_client::handle_recv(endpoint& sender, buffer_t& data) +void zt_client::handle_recv_oob(buffer_t& data, const endpoint& sender) +{ + packet* pkt = pktfty.make_in_packet(data); + if (pkt != NULL) + recv_ctrl(*pkt, sender); + delete pkt; +} + +void zt_client::handle_recv(buffer_t& data, int pnum) { packet* pkt = pktfty.make_in_packet(data); if (pkt != NULL) - handle_recv_packet(*pkt, sender); + handle_recv_packet(*pkt, pnum); else - disconnect_peer(sender); + proto.disconnect(pnum); delete pkt; } @@ -292,31 +291,25 @@ void zt_client::recv_ctrl(packet& pkt, const endpoint& sender) proto.send_oob(sender, reply->encrypted_data()); delete reply; } + } else if (pkt_type == PT_JOIN_ACCEPT) { + if (plr_self == PLR_BROADCAST && game_list[gamename].master == sender) { + recv_local(pkt); + } } } -void zt_client::handle_recv_packet(packet& pkt, const endpoint& sender) +void zt_client::handle_recv_packet(packet& pkt, int pnum) { plr_t src = pkt.pktSrc(); - if (src == PLR_BROADCAST) { - recv_ctrl(pkt, sender); - return; + // assert(plr_self != PLR_BROADCAST); + if (src == PLR_MASTER) { + src = get_master(); + } else if (src >= MAX_PLRS) { + return; // packet with invalid source -> drop } - if (plr_self == PLR_BROADCAST) { - if (pkt.pktType() != PT_JOIN_ACCEPT) - return; // non-global packet and we are not in game -> drop - if (game_list[gamename].master != sender) - return; // join accept, but from an unknown sender -> drop - } else { - if (src == PLR_MASTER) { - src = get_master(); - } else if (src >= MAX_PLRS) { - return; // packet with invalid source -> drop - } - if (sender != proto.active_connections[src].peer) { - return; // packet with mismatching source -> drop - } + if (pnum != src) { + return; // packet with mismatching source -> drop } recv_local(pkt); } diff --git a/Source/dvlnet/zt_client.h b/Source/dvlnet/zt_client.h index 4e14744c538..4a44b061847 100644 --- a/Source/dvlnet/zt_client.h +++ b/Source/dvlnet/zt_client.h @@ -17,7 +17,8 @@ class zt_client : public base_client { void get_gamelist(std::vector& games); bool network_ready(); - void handle_recv(endpoint& peer, buffer_t& data); + void handle_recv_oob(buffer_t& data, const endpoint& sender); + void handle_recv(buffer_t& data, int pnum); virtual ~zt_client() = default; @@ -45,10 +46,9 @@ class zt_client : public base_client { plr_t get_master(); plr_t next_free_conn(); - void disconnect_peer(const endpoint& peer); void send_info_request(); void handle_join_request(packet& pkt, const endpoint& sender); - void handle_recv_packet(packet& pkt, const endpoint& sender); + void handle_recv_packet(packet& pkt, int pnum); void recv_ctrl(packet& pkt, const endpoint& sender); bool wait_network(); From f3ea43bbf6fa4c702aea1ad24c9ae79b6c3c7100 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 8 Dec 2023 13:06:07 +0100 Subject: [PATCH 007/596] cosmetic --- CMakeLists.txt | 34 +++++++++++------------ Source/controls/devices/joystick.h | 3 -- Source/diablo.cpp | 4 +-- Source/itemdat.cpp | 2 +- Source/objdat.cpp | 6 ++-- Source/utils/file_util.h | 3 -- Source/utils/paths.cpp | 5 +--- Source/utils/thread.h | 3 -- tools/patcher/controls/devices/joystick.h | 3 -- tools/patcher/utils/file_util.h | 3 -- tools/patcher/utils/paths.cpp | 5 +--- 11 files changed, 25 insertions(+), 46 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c68834f497d..f5f8df1d0b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1144,28 +1144,28 @@ if(APPLE) install (TARGETS ${BIN_TARGET} DESTINATION ./) if(DEVIL_PATCHER) - set_target_properties(${DEVIL_PATCHER} PROPERTIES MACOSX_BUNDLE_ICON_FILE "AppIcon.icns") - set_target_properties(${DEVIL_PATCHER} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Packaging/apple/Info.plist") + set_target_properties(${DEVIL_PATCHER} PROPERTIES MACOSX_BUNDLE_ICON_FILE "AppIcon.icns") + set_target_properties(${DEVIL_PATCHER} PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Packaging/apple/Info.plist") - install (TARGETS ${DEVIL_PATCHER} DESTINATION ./) + install (TARGETS ${DEVIL_PATCHER} DESTINATION ./) endif() if(MACOSX_STANDALONE_APP_BUNDLE) - set(BUNDLE_FIXUP_CODE " - include(BundleUtilities) - fixup_bundle(\"${CMAKE_BINARY_DIR}/${BIN_TARGET}.app\" \"\" \"\") - ") - if(DEVIL_PATCHER) - set(BUNDLE_FIXUP_CODE "${BUNDLE_FIXUP_CODE}fixup_bundle(\"${CMAKE_BINARY_DIR}/${DEVIL_PATCHER}.app\" \"\" \"\") - ") - endif() - install(CODE ${BUNDLE_FIXUP_CODE} COMPONENT Runtime) + set(BUNDLE_FIXUP_CODE " + include(BundleUtilities) + fixup_bundle(\"${CMAKE_BINARY_DIR}/${BIN_TARGET}.app\" \"\" \"\") + ") + if(DEVIL_PATCHER) + set(BUNDLE_FIXUP_CODE "${BUNDLE_FIXUP_CODE}fixup_bundle(\"${CMAKE_BINARY_DIR}/${DEVIL_PATCHER}.app\" \"\" \"\") + ") + endif() + install(CODE ${BUNDLE_FIXUP_CODE} COMPONENT Runtime) - #install(CODE " - # include(BundleUtilities) - # fixup_bundle(${CMAKE_BINARY_DIR}/${MACOSX_BUNDLE_BUNDLE_NAME}.app \"\" \"\") - # " - # COMPONENT Runtime) + #install(CODE " + # include(BundleUtilities) + # fixup_bundle(${CMAKE_BINARY_DIR}/${MACOSX_BUNDLE_BUNDLE_NAME}.app \"\" \"\") + # " + # COMPONENT Runtime) endif() set(MACOSX_BUNDLE_LONG_VERSION_STRING "Version ${PROJECT_VERSION}") diff --git a/Source/controls/devices/joystick.h b/Source/controls/devices/joystick.h index aa592ba0e8c..901897a6013 100644 --- a/Source/controls/devices/joystick.h +++ b/Source/controls/devices/joystick.h @@ -6,10 +6,7 @@ #include #include - -#ifdef USE_SDL1 #include "utils/sdl2_to_1_2_backports.h" -#endif #include "../controller_buttons.h" diff --git a/Source/diablo.cpp b/Source/diablo.cpp index 331c6c9c3fc..e4af143b430 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -1286,7 +1286,7 @@ static void game_loop() if (multi_check_timeout() && gnTimeoutCurs == CURSOR_NONE) { gnTimeoutCurs = pcursicon; NewCursor(CURSOR_HOURGLASS); - //gbRedrawFlags = REDRAW_ALL; + // gbRedrawFlags = REDRAW_ALL; } //scrollrt_draw_screen(true); break; @@ -1294,7 +1294,7 @@ static void game_loop() if (gnTimeoutCurs != CURSOR_NONE) { NewCursor(gnTimeoutCurs); gnTimeoutCurs = CURSOR_NONE; - //gbRedrawFlags = REDRAW_ALL; + // gbRedrawFlags = REDRAW_ALL; } //if (ProcessInput()) { game_logic(); diff --git a/Source/itemdat.cpp b/Source/itemdat.cpp index 99e179d0682..a87536f9830 100644 --- a/Source/itemdat.cpp +++ b/Source/itemdat.cpp @@ -515,7 +515,7 @@ const UniqItemData UniqueItemList[NUM_UITEM] = { /*UITEM_MESSERREAVER*/ { "Messerschmidt's Reaver", UITYPE_GREATAXE, 50, 58000, IPL_DAMP, 200, 200, IPL_DAMMOD, 15, 15, IPL_ATTRIBS, 5, 5, IPL_LIFE, -50, -50, IPL_FIREDAM, 2, 12, IPL_INVCURS, ICURS_MESSERSCHMIDT, 0, ALIGN }, /*UITEM_CRACKRUST*/ { "Crackrust", UITYPE_MACE, 8, 11375, IPL_ATTRIBS, 2, 2, IPL_INDESTRUCTIBLE, 0, 0, IPL_ALLRES, 15, 15, IPL_DAMP, 50, 50, IPL_SKILLLEVELS, -1, -1, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_JHOLMHAMM*/ { "Hammer of Jholm", UITYPE_MAUL, 12, 8700, IPL_DAMP, 4, 10, IPL_INDESTRUCTIBLE, 0, 0, IPL_STR, 3, 3, IPL_TOHIT, 15, 15, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_CIVERBS*/// { "Civerb's Cudgel", UITYPE_MACE, 1, 2000, IPL_3XDAMVDEM, 35, 35, IPL_DEX, -5, -5, IPL_MAG, -2, -2, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_CIVERBS*/// { "Civerb's Cudgel", UITYPE_MACE, 1, 2000, IPL_3XDAMVDEM, 35, 35, IPL_DEX, -5, -5, IPL_MAG, -2, -2, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_CELESTSTAR*/ { "The Celestial Star", UITYPE_FLAIL, 14, 7810, IPL_NOMINSTR, 0, 0, IPL_LIGHT, 2, 2, IPL_DAMMOD, 10, 10, IPL_ACMOD, -8, -8, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_BARANSTAR*/ { "Baranar's Star", UITYPE_MORNSTAR, 14, 6850, IPL_TOHIT, 12, 12, IPL_DAMP, 80, 80, IPL_FASTATTACK, 1, 1, IPL_VIT, 4, 4, IPL_DEX, -4, -4, IPL_SETDUR, 60, 60, ALIGN }, /*UITEM_GNARLROOT*/ { "Gnarled Root", UITYPE_SPIKCLUB, 16, 9820, IPL_TOHIT, 20, 20, IPL_DAMP, 300, 300, IPL_DEX, 10, 10, IPL_MAG, 5, 5, IPL_ALLRES, 10, 10, IPL_ACMOD, -10, -10, ALIGN }, diff --git a/Source/objdat.cpp b/Source/objdat.cpp index 094ee069727..bee07e1240a 100644 --- a/Source/objdat.cpp +++ b/Source/objdat.cpp @@ -316,9 +316,9 @@ const ObjFileData objfiledata[NUM_OFILE_TYPES] = { /*OFILE_VAPOR1*/// { "Vapor1", SFX_NONE, 0, OAM_LOOP, 1, 13, 128, FALSE, OBM_UNBREAKABLE, ALIGN32 }, /*OFILE_PRSRPLT1*///{ "Prsrplt1", SFX_NONE, 0, OAM_NONE, 0, 10, 96, FALSE, OBM_UNBREAKABLE, ALIGN32 }, /*OFILE_TRAPHOLE*/ { "Traphole", SFX_NONE, 0, OAM_NONE, 0, 0, 64, FALSE, OBM_UNBREAKABLE, ALIGN32 }, -/*OFILE_DIRTFALL*///{ "Dirtfall", SFX_NONE, 0, OAM_LOOP, 0, 10, 96, FALSE, OBM_UNBREAKABLE, ALIGN32 }, -/*OFILE_WATER*/// { "Water", SFX_NONE, 0, OAM_LOOP, 1, 10, 128, TRUE, OBM_UNBREAKABLE, ALIGN32 }, -/*OFILE_MINIWATR*///{ "MiniWatr", SFX_NONE, 0, OAM_LOOP, 1, 10, 64, TRUE, OBM_UNBREAKABLE, ALIGN32 }, +/*OFILE_DIRTFALL*///{ "Dirtfall", SFX_NONE, 0, OAM_LOOP, 0, 10, 96, FALSE, OBM_UNBREAKABLE, ALIGN32 }, +/*OFILE_WATER*/// { "Water", SFX_NONE, 0, OAM_LOOP, 1, 10, 128, TRUE, OBM_UNBREAKABLE, ALIGN32 }, +/*OFILE_MINIWATR*///{ "MiniWatr", SFX_NONE, 0, OAM_LOOP, 1, 10, 64, TRUE, OBM_UNBREAKABLE, ALIGN32 }, /*OFILE_WTORCH2*/ { "WTorch2", SFX_NONE, 0, OAM_LOOP, 1, 9, 96, FALSE, OBM_UNBREAKABLE, ALIGN32 }, /*OFILE_WTORCH1*/ { "WTorch1", SFX_NONE, 0, OAM_LOOP, 1, 9, 96, FALSE, OBM_UNBREAKABLE, ALIGN32 }, /*OFILE_BCASE*/ { "BCase", SFX_NONE, 0, OAM_NONE, 0, 0, 96, FALSE, OBM_UNBREAKABLE, ALIGN32 }, diff --git a/Source/utils/file_util.h b/Source/utils/file_util.h index a185c5d03ce..382a8f993d4 100644 --- a/Source/utils/file_util.h +++ b/Source/utils/file_util.h @@ -5,10 +5,7 @@ #include #include - -#ifdef USE_SDL1 #include "utils/sdl2_to_1_2_backports.h" -#endif #include "log.h" diff --git a/Source/utils/paths.cpp b/Source/utils/paths.cpp index 84657c18905..9cb21f04662 100644 --- a/Source/utils/paths.cpp +++ b/Source/utils/paths.cpp @@ -1,15 +1,12 @@ #include "paths.h" #include +#include "utils/sdl2_to_1_2_backports.h" #ifdef __IPHONEOS__ #include "platform/ios/ios_paths.h" #endif -#ifdef USE_SDL1 -#include "utils/sdl2_to_1_2_backports.h" -#endif - #include "log.h" DEVILUTION_BEGIN_NAMESPACE diff --git a/Source/utils/thread.h b/Source/utils/thread.h index a7e1a7de092..3c93cdf3cef 100644 --- a/Source/utils/thread.h +++ b/Source/utils/thread.h @@ -1,10 +1,7 @@ #pragma once /*#include - -#ifdef USE_SDL1 #include "utils/sdl2_to_1_2_backports.h" -#endif #include "../defs.h"*/ #include "all.h" diff --git a/tools/patcher/controls/devices/joystick.h b/tools/patcher/controls/devices/joystick.h index aa592ba0e8c..901897a6013 100644 --- a/tools/patcher/controls/devices/joystick.h +++ b/tools/patcher/controls/devices/joystick.h @@ -6,10 +6,7 @@ #include #include - -#ifdef USE_SDL1 #include "utils/sdl2_to_1_2_backports.h" -#endif #include "../controller_buttons.h" diff --git a/tools/patcher/utils/file_util.h b/tools/patcher/utils/file_util.h index cffe00d96dd..670c660b2fb 100644 --- a/tools/patcher/utils/file_util.h +++ b/tools/patcher/utils/file_util.h @@ -5,10 +5,7 @@ #include #include - -#ifdef USE_SDL1 #include "utils/sdl2_to_1_2_backports.h" -#endif #include "log.h" diff --git a/tools/patcher/utils/paths.cpp b/tools/patcher/utils/paths.cpp index 84657c18905..9cb21f04662 100644 --- a/tools/patcher/utils/paths.cpp +++ b/tools/patcher/utils/paths.cpp @@ -1,15 +1,12 @@ #include "paths.h" #include +#include "utils/sdl2_to_1_2_backports.h" #ifdef __IPHONEOS__ #include "platform/ios/ios_paths.h" #endif -#ifdef USE_SDL1 -#include "utils/sdl2_to_1_2_backports.h" -#endif - #include "log.h" DEVILUTION_BEGIN_NAMESPACE From 30718ea0fa888700c1de450779bafd6bc63792c1 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 8 Dec 2023 16:31:42 +0100 Subject: [PATCH 008/596] save the level (info/delta) when the hero is saved --- Source/interfac.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Source/interfac.cpp b/Source/interfac.cpp index 3ea6f8cf8b7..f99ecb52ee7 100644 --- a/Source/interfac.cpp +++ b/Source/interfac.cpp @@ -269,11 +269,6 @@ void EnterLevel(BYTE lvl) static void SwitchGameLevel(int lvldir) { - if (IsMultiGame) { - DeltaSaveLevel(); - } else { - SaveLevel(); - } IncProgress(); FreeLevelMem(); EnterLevel(myplr._pDunLevel); @@ -300,8 +295,12 @@ void ShowCutscene(unsigned uMsg) nthread_run(); if (uMsg != DVL_DWM_NEWGAME) { - if (IsMultiGame) + if (IsMultiGame) { pfile_write_hero(false); + DeltaSaveLevel(); + } else { + SaveLevel(); + } // turned off to have a consistent fade in/out logic + reduces de-sync by // eliminating the need for special handling in InitLevelChange (player.cpp) //PaletteFadeOut(); From 41430bbe845e3f8fd76c8913725f4c2d0cc22498 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 8 Dec 2023 16:41:21 +0100 Subject: [PATCH 009/596] sync lvl_entry with window_messages --- Source/diablo.cpp | 2 +- Source/miniwin/miniwin.h | 53 ++++++++++++++++++---------------------- enums.h | 2 +- 3 files changed, 26 insertions(+), 31 deletions(-) diff --git a/Source/diablo.cpp b/Source/diablo.cpp index e4af143b430..675a01e9b74 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -1171,8 +1171,8 @@ static void GameWndProc(const Dvl_Event* e) return; case DVL_DWM_NEXTLVL: case DVL_DWM_PREVLVL: - case DVL_DWM_RTNLVL: case DVL_DWM_SETLVL: + case DVL_DWM_RTNLVL: case DVL_DWM_WARPLVL: case DVL_DWM_TWARPDN: case DVL_DWM_TWARPUP: diff --git a/Source/miniwin/miniwin.h b/Source/miniwin/miniwin.h index a7320b8ce52..41464da13d8 100644 --- a/Source/miniwin/miniwin.h +++ b/Source/miniwin/miniwin.h @@ -22,35 +22,30 @@ WNDPROC SetWindowProc(WNDPROC NewProc); // typedef enum window_messages { DVL_WM_NONE, - DVL_WM_QUIT, // 0x0012 - DVL_WM_MOUSEMOVE, // 0x0200 - DVL_WM_LBUTTONDOWN, // 0x0201 - DVL_WM_LBUTTONUP, // 0x0202 - DVL_WM_RBUTTONDOWN, // 0x0204 - DVL_WM_RBUTTONUP, // 0x0205 - - DVL_WM_KEYDOWN, // 0x0100 - DVL_WM_KEYUP, // 0x0101 - // DVL_WM_SYSKEYDOWN 0x0104 - // DVL_WM_SYSCOMMAND 0x0112 - DVL_WM_TEXT, // 0x0102 - - DVL_WM_CAPTURECHANGED, // 0x0215 - DVL_WM_PAINT, // 0x000F - DVL_WM_QUERYENDSESSION, // 0x0011 - - DVL_DWM_NEXTLVL, // = 0x402, // dungeon -> next level WM_USER+2 - DVL_DWM_PREVLVL, // = 0x403, // dungeon -> previous level - DVL_DWM_RTNLVL, // = 0x404, // setlevel -> dungeon - DVL_DWM_SETLVL, // = 0x405, // dungeon -> setlevel - DVL_DWM_TWARPDN, // = 0x407, // town -> dungeon - DVL_DWM_TWARPUP, // = 0x408, // dungeon -> town - DVL_DWM_WARPLVL, // = 0x406, // portal - DVL_DWM_RETOWN, // = 0x409, // restart in town - DVL_DWM_NEWGAME, // = 0x40A, - - // WM_LEIGHSKIP = 0x40C, // psx only - // WM_DIAVNEWLVL = 0x40D, // psx only + DVL_WM_QUIT, + DVL_WM_MOUSEMOVE, + DVL_WM_LBUTTONDOWN, + DVL_WM_LBUTTONUP, + DVL_WM_RBUTTONDOWN, + DVL_WM_RBUTTONUP, + + DVL_WM_KEYDOWN, + DVL_WM_KEYUP, + DVL_WM_TEXT, + + DVL_WM_CAPTURECHANGED, + DVL_WM_PAINT, + DVL_WM_QUERYENDSESSION, + + DVL_DWM_NEXTLVL, // dungeon -> next level + DVL_DWM_PREVLVL, // dungeon -> previous level + DVL_DWM_SETLVL, // dungeon -> setlevel + DVL_DWM_RTNLVL, // setlevel -> dungeon + DVL_DWM_WARPLVL, // portal (town <-> dungeon) + DVL_DWM_TWARPDN, // town -> dungeon + DVL_DWM_TWARPUP, // dungeon -> town + DVL_DWM_RETOWN, // restart in town + DVL_DWM_NEWGAME, // new game } window_messages; //#define DVL_SC_CLOSE 0xF060 diff --git a/enums.h b/enums.h index 3f2d8019f99..a14aaab388d 100644 --- a/enums.h +++ b/enums.h @@ -3742,11 +3742,11 @@ typedef enum lvl_entry { ENTRY_PREV, ENTRY_SETLVL, ENTRY_RTNLVL, - ENTRY_LOAD, ENTRY_WARPLVL, ENTRY_TWARPDN, ENTRY_TWARPUP, ENTRY_RETOWN, + ENTRY_LOAD, } lvl_entry; /*typedef enum game_info { From c93970776ecc07ef7df90511e395319cf642089d Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 8 Dec 2023 17:09:05 +0100 Subject: [PATCH 010/596] eliminate 'empty' step from DrawCutscene --- Source/interfac.cpp | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/Source/interfac.cpp b/Source/interfac.cpp index f99ecb52ee7..72cd4afbec3 100644 --- a/Source/interfac.cpp +++ b/Source/interfac.cpp @@ -107,26 +107,25 @@ static void DrawProgress() } #if DEBUG_MODE || DEV_MODE const char* progession[] { - "Startup", // 0 - "Save", // 1 - "Memfree", // 2 - "Music stop", // 3 - "Init Dungeon", // 4 - "Init Level", // 5 - "Create Dungeon", // 6 - "MonsterFX", // 7 - "Monsters", // 8 - "ObjectsGFX", // 9 - "Objects/Items", // 10 - "Missiles/Light", // 11 - "Music start", // 12 - "Network - Pending Turns", // 13 - "Network - Msg Queue", // 14 - "Network - Join Level", // 15 - "Network - Sync delta", // 16 - "Fadeout", // 17 +/* 0 */"Startup", +/* 1 */"Memfree", +/* 2 */"Music stop", +/* 3 */"Init Dungeon", +/* 4 */"Init Level", +/* 5 */"Create Dungeon", +/* 6 */"MonsterFX", +/* 7 */"Monsters", +/* 8 */"ObjectsGFX", +/* 9 */"Objects/Items", +/* 10 */"Missiles/Light", +/* 11 */"Music start", +/* 12 */"Network - Pending Turns", +/* 13 */"Network - Msg Queue", +/* 14 */"Network - Join Level", +/* 15 */"Network - Sync delta", +/* 16 */"Fadeout", }; - unsigned progress = sgdwProgress / ((BAR_WIDTH + 17) / 18); + unsigned progress = sgdwProgress / ((BAR_WIDTH + (lengthof(progession) - 1)) / lengthof(progession)); PrintString(screen_x + 10, screen_y + (BAR_HEIGHT - SMALL_FONT_HEIGHT) / 2 + SMALL_FONT_HEIGHT, screen_x + BAR_WIDTH - 20, progress < (unsigned)lengthof(progession) ? progession[progress] : "Unknown", false, COL_WHITE, 1); #endif } @@ -269,7 +268,6 @@ void EnterLevel(BYTE lvl) static void SwitchGameLevel(int lvldir) { - IncProgress(); FreeLevelMem(); EnterLevel(myplr._pDunLevel); IncProgress(); @@ -320,7 +318,6 @@ void ShowCutscene(unsigned uMsg) switch (uMsg) { case DVL_DWM_NEWGAME: - IncProgress(); IncProgress(); if (gbLoadGame /*&& gbValidSaveFile*/) { LoadGame(); From fe9f501a737f6d14328048d3cd6d148ddd1121cd Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 8 Dec 2023 17:20:03 +0100 Subject: [PATCH 011/596] add DVL_DWM_LOADGAME --- Source/diablo.cpp | 3 ++- Source/interfac.cpp | 18 ++++++++++-------- Source/miniwin/miniwin.h | 21 ++++++++++++--------- Source/nthread.cpp | 18 ++++++++---------- 4 files changed, 32 insertions(+), 28 deletions(-) diff --git a/Source/diablo.cpp b/Source/diablo.cpp index 675a01e9b74..cd6cd8c3777 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -1178,6 +1178,7 @@ static void GameWndProc(const Dvl_Event* e) case DVL_DWM_TWARPUP: case DVL_DWM_RETOWN: case DVL_DWM_NEWGAME: + case DVL_DWM_LOADGAME: gbActionBtnDown = false; gbAltActionBtnDown = false; if (gbQtextflag) { @@ -1383,7 +1384,7 @@ static void run_game() WNDPROC saveProc = InitGameFX(); SDL_Event event; - event.type = DVL_DWM_NEWGAME; + event.type = gbLoadGame ? DVL_DWM_LOADGAME : DVL_DWM_NEWGAME; GameWndProc(&event); #ifdef GPERF_HEAP_FIRST_GAME_ITERATION diff --git a/Source/interfac.cpp b/Source/interfac.cpp index 72cd4afbec3..4a820d52c90 100644 --- a/Source/interfac.cpp +++ b/Source/interfac.cpp @@ -65,6 +65,7 @@ static void InitCutscene(unsigned int uMsg) sgbLoadBarCol = 43; break; case DVL_DWM_NEWGAME: + case DVL_DWM_LOADGAME: sgpBackCel = CelLoadImage("Gendata\\Cutstart.CEL", PANEL_WIDTH); LoadPalette("Gendata\\Cutstart.pal"); sgbLoadBarOnTop = FALSE; @@ -292,7 +293,8 @@ void ShowCutscene(unsigned uMsg) WNDPROC saveProc; nthread_run(); - if (uMsg != DVL_DWM_NEWGAME) { + static_assert((unsigned)DVL_DWM_LOADGAME == (unsigned)DVL_DWM_NEWGAME + 1 && (unsigned)NUM_WNDMSGS == (unsigned)DVL_DWM_LOADGAME + 1, "Check to save hero/level in ShowCutscene must be adjusted."); + if (uMsg < DVL_DWM_NEWGAME) { if (IsMultiGame) { pfile_write_hero(false); DeltaSaveLevel(); @@ -319,13 +321,13 @@ void ShowCutscene(unsigned uMsg) switch (uMsg) { case DVL_DWM_NEWGAME: IncProgress(); - if (gbLoadGame /*&& gbValidSaveFile*/) { - LoadGame(); - } else { - //FreeLevelMem(); - pfile_delete_save_file(false); - LoadGameLevel(ENTRY_MAIN); - } + pfile_delete_save_file(false); + // FreeLevelMem(); + LoadGameLevel(ENTRY_MAIN); + break; + case DVL_DWM_LOADGAME: + IncProgress(); + LoadGame(); break; case DVL_DWM_NEXTLVL: assert(myplr._pDunLevel == currLvl._dLevelIdx + 1); diff --git a/Source/miniwin/miniwin.h b/Source/miniwin/miniwin.h index 41464da13d8..aafc89fcff9 100644 --- a/Source/miniwin/miniwin.h +++ b/Source/miniwin/miniwin.h @@ -37,15 +37,18 @@ typedef enum window_messages { DVL_WM_PAINT, DVL_WM_QUERYENDSESSION, - DVL_DWM_NEXTLVL, // dungeon -> next level - DVL_DWM_PREVLVL, // dungeon -> previous level - DVL_DWM_SETLVL, // dungeon -> setlevel - DVL_DWM_RTNLVL, // setlevel -> dungeon - DVL_DWM_WARPLVL, // portal (town <-> dungeon) - DVL_DWM_TWARPDN, // town -> dungeon - DVL_DWM_TWARPUP, // dungeon -> town - DVL_DWM_RETOWN, // restart in town - DVL_DWM_NEWGAME, // new game + DVL_DWM_NEXTLVL, // dungeon -> next level + DVL_DWM_PREVLVL, // dungeon -> previous level + DVL_DWM_SETLVL, // dungeon -> setlevel + DVL_DWM_RTNLVL, // setlevel -> dungeon + DVL_DWM_WARPLVL, // portal (town <-> dungeon) + DVL_DWM_TWARPDN, // town -> dungeon + DVL_DWM_TWARPUP, // dungeon -> town + DVL_DWM_RETOWN, // restart in town + DVL_DWM_NEWGAME, // new game + DVL_DWM_LOADGAME, // load game + + NUM_WNDMSGS } window_messages; //#define DVL_SC_CLOSE 0xF060 diff --git a/Source/nthread.cpp b/Source/nthread.cpp index c8ba401828e..3fdd9df48b4 100644 --- a/Source/nthread.cpp +++ b/Source/nthread.cpp @@ -393,18 +393,16 @@ void nthread_finish(UINT uMsg) turn_t lastGameTurn; unsigned tmp; - if (uMsg == DVL_DWM_NEWGAME) { - if (gbLoadGame /*&& gbValidSaveFile*/) { + if (uMsg == DVL_DWM_LOADGAME) { #ifndef NONET - assert(sghThread == NULL); + assert(sghThread == NULL); #endif - assert(geBufferMsgs == MSG_NORMAL); - assert(sgbPacketCountdown == 1); - // IncProgress(); - // IncProgress(); - // IncProgress(); - return; - } + assert(geBufferMsgs == MSG_NORMAL); + assert(sgbPacketCountdown == 1); + // IncProgress(); + // IncProgress(); + // IncProgress(); + return; } // phase 5 done // phase 6 begin From 3da7d12133050f35970d6a08842a99c78f9f2da9 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 8 Dec 2023 17:26:15 +0100 Subject: [PATCH 012/596] call FreeLevelMem before LoadGame (and SwitchGameLevel) --- Source/gamemenu.cpp | 1 + Source/interfac.cpp | 7 ++----- Source/loadsave.cpp | 1 - 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Source/gamemenu.cpp b/Source/gamemenu.cpp index a08265e9faf..3e073733450 100644 --- a/Source/gamemenu.cpp +++ b/Source/gamemenu.cpp @@ -124,6 +124,7 @@ static void gamemenu_load_game(bool bActivate) scrollrt_draw_game(); gbDeathflag = MDM_ALIVE; // gbZoomInFlag = false; + FreeLevelMem(); LoadGame(); ClrDiabloMsg(); PaletteFadeOut(); diff --git a/Source/interfac.cpp b/Source/interfac.cpp index 4a820d52c90..a0df03cf480 100644 --- a/Source/interfac.cpp +++ b/Source/interfac.cpp @@ -269,9 +269,7 @@ void EnterLevel(BYTE lvl) static void SwitchGameLevel(int lvldir) { - FreeLevelMem(); EnterLevel(myplr._pDunLevel); - IncProgress(); LoadGameLevel(lvldir); } @@ -317,16 +315,15 @@ void ShowCutscene(unsigned uMsg) DrawCutscene(); PaletteFadeIn(false); IncProgress(); + FreeLevelMem(); + IncProgress(); switch (uMsg) { case DVL_DWM_NEWGAME: - IncProgress(); pfile_delete_save_file(false); - // FreeLevelMem(); LoadGameLevel(ENTRY_MAIN); break; case DVL_DWM_LOADGAME: - IncProgress(); LoadGame(); break; case DVL_DWM_NEXTLVL: diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index d9f64979cd2..4c7f2db320e 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -764,7 +764,6 @@ void LoadGame() int _ViewX, _ViewY; int32_t _CurrSeed; - FreeLevelMem(); // TODO: UIDisconnectGame() ? SNetLeaveGame(); From e28f539bf77350d9ae722c09063598d136cbc332 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 9 Dec 2023 11:08:40 +0100 Subject: [PATCH 013/596] adjust spoken text with ListOffset --- Source/DiabloUI/diabloui.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/DiabloUI/diabloui.cpp b/Source/DiabloUI/diabloui.cpp index 41862b7d1f0..ffb8a24b894 100644 --- a/Source/DiabloUI/diabloui.cpp +++ b/Source/DiabloUI/diabloui.cpp @@ -70,13 +70,13 @@ void UiInitScreen(unsigned listSize, void (*fnFocus)(unsigned index), void (*fnS gfnListSelect = fnSelect; gfnListEsc = fnEsc; gfnListDelete = NULL; - if (fnFocus != NULL) + if (fnFocus != NULL) { fnFocus(SelectedItem); #if SCREEN_READER_INTEGRATION - if (gUIListItems.size() > SelectedItem) { - SpeakText(gUIListItems[SelectedItem]->m_text); - } + unsigned idx = SelectedItem - ListOffset; + SpeakText(gUIListItems[idx]->m_text); #endif + } gUiEditField = NULL; #if !defined(__SWITCH__) && !defined(__vita__) && !defined(__3DS__) @@ -143,13 +143,13 @@ static void UiFocus(unsigned itemIndex) UiScrollIntoView(); UiPlayMoveSound(); - if (gfnListFocus != NULL) + if (gfnListFocus != NULL) { gfnListFocus(itemIndex); #if SCREEN_READER_INTEGRATION - if (gUIListItems.size() > itemIndex) { - SpeakText(gUIListItems[itemIndex]->m_text); - } + unsigned idx = itemIndex - ListOffset; + SpeakText(gUIListItems[idx]->m_text); #endif + } } static void UiFocusUp() From f16e4e2a016954af18d5ddec838b4a89ed9ecdd7 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 9 Dec 2023 11:09:35 +0100 Subject: [PATCH 014/596] set _gbYNValue based on the index instead of m_value (DiabloUI) --- Source/DiabloUI/selyesno.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/DiabloUI/selyesno.cpp b/Source/DiabloUI/selyesno.cpp index b76e78ab8cb..b774f8c7249 100644 --- a/Source/DiabloUI/selyesno.cpp +++ b/Source/DiabloUI/selyesno.cpp @@ -24,7 +24,7 @@ static void SelyesnoFree() static void SelyesnoSelect(unsigned index) { - _gbYNValue = gUIListItems[index]->m_value == 0; + _gbYNValue = index == 0; _gbYNEndMenu = true; } From 9e7af6f800cfbef0e63c88d54ddf3b2740368c21 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 9 Dec 2023 11:11:26 +0100 Subject: [PATCH 015/596] use SELHERO_LIST_TOP instead of SELCONN_LIST_TOP in selhero.cpp --- Source/DiabloUI/selhero.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/DiabloUI/selhero.cpp b/Source/DiabloUI/selhero.cpp index d71537fe177..f54e8b9ee30 100644 --- a/Source/DiabloUI/selhero.cpp +++ b/Source/DiabloUI/selhero.cpp @@ -273,12 +273,12 @@ static void SelheroListDelete() SelheroResetScreen(selconn_bMulti ? "Multi Player Characters" : "Single Player Characters", "Confirm delete"); - SDL_Rect rect1 = { SELHERO_RPANEL_LEFT + 25, SELCONN_LIST_TOP, SELHERO_RPANEL_WIDTH - 2 * 25, 30 }; + SDL_Rect rect1 = { SELHERO_RPANEL_LEFT + 25, SELHERO_LIST_TOP, SELHERO_RPANEL_WIDTH - 2 * 25, 30 }; gUiItems.push_back(new UiText(selhero_heroInfo.hiName, rect1, UIS_HCENTER | UIS_VCENTER | UIS_BIG | UIS_SILVER)); gUIListItems.push_back(new UiListItem("Yes", 0)); gUIListItems.push_back(new UiListItem("No", 1)); - SDL_Rect rect2 = { SELHERO_RPANEL_LEFT + (SELHERO_RPANEL_WIDTH - 100) / 2, SELCONN_LIST_TOP + 40, 100, 26 * 2 }; + SDL_Rect rect2 = { SELHERO_RPANEL_LEFT + (SELHERO_RPANEL_WIDTH - 100) / 2, SELHERO_LIST_TOP + 40, 100, 26 * 2 }; gUiItems.push_back(new UiList(&gUIListItems, 2, rect2, UIS_HCENTER | UIS_VCENTER | UIS_MED | UIS_GOLD)); UiInitScreen(2, NULL, SelheroListDeleteYesNo, SelheroInitHeros); @@ -294,7 +294,7 @@ static void SelheroListInit() } SelheroUpdateViewportItems(); - SDL_Rect rect2 = { SELHERO_RPANEL_LEFT + 25, SELCONN_LIST_TOP, SELHERO_RPANEL_WIDTH - 2 * 25, 26 * (int)num_viewport_heroes }; + SDL_Rect rect2 = { SELHERO_RPANEL_LEFT + 25, SELHERO_LIST_TOP, SELHERO_RPANEL_WIDTH - 2 * 25, 26 * (int)num_viewport_heroes }; gUiItems.push_back(new UiList(&gUIListItems, num_viewport_heroes, rect2, UIS_HCENTER | UIS_VCENTER | UIS_MED | UIS_GOLD)); SDL_Rect rect3 = { SELHERO_RPANEL_LEFT + SELHERO_RPANEL_WIDTH - SCROLLBAR_BG_WIDTH + 1, SELHERO_RPANEL_TOP - 1, SCROLLBAR_BG_WIDTH, SELHERO_RPANEL_HEIGHT + 1 }; @@ -362,7 +362,7 @@ static void SelheroClassSelectorInit() gUIListItems.push_back(new UiListItem("Barbarian", PC_BARBARIAN)); #endif //assert(gUIListItems.size() == NUM_CLASSES); - SDL_Rect rect2 = { SELHERO_RPANEL_LEFT + (SELHERO_RPANEL_WIDTH - 270) / 2, SELCONN_LIST_TOP, 270, 26 * NUM_CLASSES }; + SDL_Rect rect2 = { SELHERO_RPANEL_LEFT + (SELHERO_RPANEL_WIDTH - 270) / 2, SELHERO_LIST_TOP, 270, 26 * NUM_CLASSES }; gUiItems.push_back(new UiList(&gUIListItems, NUM_CLASSES, rect2, UIS_HCENTER | UIS_VCENTER | UIS_MED | UIS_GOLD)); SDL_Rect rect3 = { SELHERO_RPANEL_LEFT, SELHERO_RBUTTON_TOP, SELHERO_RPANEL_WIDTH / 2, 35 }; @@ -381,7 +381,7 @@ static void SelheroLoadInit() gUIListItems.push_back(new UiListItem("Load Game", 0)); gUIListItems.push_back(new UiListItem("New Game", 1)); - SDL_Rect rect2 = { SELHERO_RPANEL_LEFT + (SELHERO_RPANEL_WIDTH - 280) / 2, SELCONN_LIST_TOP, 280, 26 * 2 }; + SDL_Rect rect2 = { SELHERO_RPANEL_LEFT + (SELHERO_RPANEL_WIDTH - 280) / 2, SELHERO_LIST_TOP, 280, 26 * 2 }; gUiItems.push_back(new UiList(&gUIListItems, 2, rect2, UIS_HCENTER | UIS_VCENTER | UIS_MED | UIS_GOLD)); SDL_Rect rect3 = { SELHERO_RPANEL_LEFT, SELHERO_RBUTTON_TOP, SELHERO_RPANEL_WIDTH / 2, 35 }; From 31664c4c727930ae294a9750fc1d01fda468c1e3 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 9 Dec 2023 11:14:20 +0100 Subject: [PATCH 016/596] don't support save-scumming (remove 'load game' from the game-menu) --- Source/gamemenu.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Source/gamemenu.cpp b/Source/gamemenu.cpp index 3e073733450..fcf8d5aac77 100644 --- a/Source/gamemenu.cpp +++ b/Source/gamemenu.cpp @@ -25,10 +25,10 @@ static void gamemenu_speed(bool bActivate); static TMenuItem sgSingleMenu[] = { // clang-format off // pszStr, fnMenu, dwFlags, wMenuParam* - { "Save Game", &gamemenu_save_game, GMF_ENABLED, 0, 0 }, { "Settings", &gamemenu_settings, GMF_ENABLED, 0, 0 }, { "New Game", &gamemenu_new_game, GMF_ENABLED, 0, 0 }, - { "Load Game", &gamemenu_load_game, GMF_ENABLED, 0, 0 }, + // { "Load Game", &gamemenu_load_game, GMF_ENABLED, 0, 0 }, + { "Save Game", &gamemenu_save_game, GMF_ENABLED, 0, 0 }, { "Exit Game", &gamemenu_exit_game, GMF_ENABLED, 0, 0 }, // clang-format on }; @@ -63,11 +63,10 @@ static void gamemenu_update_single() { bool enable; - gmenu_enable(&sgSingleMenu[3], gbValidSaveFile); // disable saving in case the player died, the player is changing the level, or diablo is dying enable = /*pcursicon == CURSOR_HAND &&*/ gbDeathflag == MDM_ALIVE && !myplr._pLvlChanging; // TODO: disable saving if there is a live turn in transit? (SNetGetLiveTurnsInTransit) - gmenu_enable(&sgSingleMenu[0], enable); + gmenu_enable(&sgSingleMenu[2], enable); } static void gamemenu_update_multi() From 58881f427701e69cfaa6fa7524d4a928265353ee Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 9 Dec 2023 11:32:40 +0100 Subject: [PATCH 017/596] move load/new game selection to selgame.cpp --- Source/DiabloUI/selgame.cpp | 111 +++++++++++++++++++++++------------- Source/DiabloUI/selhero.cpp | 33 ++--------- Source/multi.cpp | 17 +----- Source/pfile.cpp | 9 ++- enums.h | 8 +-- structs.h | 1 - 6 files changed, 85 insertions(+), 94 deletions(-) diff --git a/Source/DiabloUI/selgame.cpp b/Source/DiabloUI/selgame.cpp index 86c931d27ff..b74a6e081a9 100644 --- a/Source/DiabloUI/selgame.cpp +++ b/Source/DiabloUI/selgame.cpp @@ -64,7 +64,7 @@ static char selgame_GameName[NET_MAX_GAMENAME_LEN + 1] = ""; static char selgame_GamePort[8] = ""; static char selgame_Password[NET_MAX_PASSWD_LEN + 1] = ""; static char selgame_Description[128]; -static int selgame_mode; +static int selgame_mode; // _selgame_selections static bool selgame_endMenu; //int selgame_heroLevel; @@ -73,7 +73,6 @@ static _uigamedata* selgame_gameData; #define DESCRIPTION_WIDTH (SELGAME_LPANEL_WIDTH - 2 * 10) // Forward-declare UI-handlers, used by other handlers. -static void SelgameModeSelect(unsigned index); static void SelgameAddressListInit(); static void SelgameDiffSelect(unsigned index); static void SelgameSpeedSelect(unsigned index); @@ -301,21 +300,65 @@ static void SelgameDiffInit() UiInitScreen(3, SelgameDiffFocus, SelgameDiffSelect, SelgameDiffEsc); } +static void SelgameModeSet(unsigned value) +{ + selgame_mode = value; + + //gfnHeroInfo(UpdateHeroLevel); + int port = NET_DEFAULT_PORT; + getIniInt("Network", "Port", &port); + snprintf(selgame_GamePort, sizeof(selgame_GamePort), "%d", port); + if (value == SELGAME_CREATE) { + SelgameDiffInit(); + return; + } + if (value == SELGAME_LOAD) { + selgame_Password[0] = '\0'; + SelgamePasswordSelect(0); + return; + } + SelgameAddressListInit(); +} + +static void SelgameModeSelect(unsigned index) +{ + SelgameModeSet(gUIListItems[index]->m_value); +} + static void SelgameModeInit() { #ifndef NOHOSTING - if (provider == SELCONN_LOOPBACK || provider == SELCONN_TCPS || provider == SELCONN_TCPDS) { -#else - if (provider == SELCONN_LOOPBACK) { + if (provider == SELCONN_TCPS || provider == SELCONN_TCPDS) { + SelgameModeSet(SELGAME_CREATE); + return; + } #endif - SelgameModeSelect(SELGAME_CREATE); + if (provider == SELCONN_LOOPBACK) { + if (!gbValidSaveFile) { + SelgameModeSet(SELGAME_CREATE); + return; + } + + SelgameResetScreen("Single Player Game", "Select Action"); + + gUIListItems.push_back(new UiListItem("Load Game", SELGAME_LOAD)); + gUIListItems.push_back(new UiListItem("New Game", SELGAME_CREATE)); + SDL_Rect rect2 = { SELGAME_RPANEL_LEFT + (SELGAME_RPANEL_WIDTH - 280) / 2, SELGAME_LIST_TOP, 280, 26 * 2 }; + gUiItems.push_back(new UiList(&gUIListItems, 2, rect2, UIS_HCENTER | UIS_VCENTER | UIS_MED | UIS_GOLD)); + + SDL_Rect rect3 = { SELGAME_RPANEL_LEFT, SELGAME_RBUTTON_TOP, SELGAME_RPANEL_WIDTH / 2, 35 }; + gUiItems.push_back(new UiTxtButton("OK", &UiFocusNavigationSelect, rect3, UIS_HCENTER | UIS_VCENTER | UIS_BIG | UIS_GOLD)); + + SDL_Rect rect4 = { SELGAME_RPANEL_LEFT + SELGAME_RPANEL_WIDTH / 2, SELGAME_RBUTTON_TOP, SELGAME_RPANEL_WIDTH / 2, 35 }; + gUiItems.push_back(new UiTxtButton("Cancel", &UiFocusNavigationEsc, rect4, UIS_HCENTER | UIS_VCENTER | UIS_BIG | UIS_GOLD)); + + //assert(gUIListItems.size() == 2); + UiInitScreen(2, NULL, SelgameModeSelect, SelgameModeEsc); return; } SelgameResetScreen("Multi Player Game", "Select Action"); - static_assert(0 == (int)SELGAME_CREATE, "SelgameModeSelect expects the index and its value to match I."); - static_assert(1 == (int)SELGAME_JOIN, "SelgameModeSelect expects the index and its value to match II."); gUIListItems.push_back(new UiListItem("Create Game", SELGAME_CREATE)); gUIListItems.push_back(new UiListItem("Join Game", SELGAME_JOIN)); @@ -705,10 +748,12 @@ static void SelgamePasswordEsc() static void SelgameDiffEsc() { #ifndef NOHOSTING - if (provider == SELCONN_LOOPBACK || provider == SELCONN_TCPS || provider == SELCONN_TCPDS) { -#else - if (provider == SELCONN_LOOPBACK) { + if (provider == SELCONN_TCPS || provider == SELCONN_TCPDS) { + SelgameModeEsc(); + return; + } #endif + if (provider == SELCONN_LOOPBACK && !gbValidSaveFile) { SelgameModeEsc(); return; } @@ -718,53 +763,25 @@ static void SelgameDiffEsc() static void SelgameDiffSelect(unsigned index) { - int value = gUIListItems[index]->m_value; - - selgame_gameData->aeDifficulty = value; + selgame_gameData->aeDifficulty = gUIListItems[index]->m_value; if (!selconn_bMulti) { - selgame_gameData->aeMaxPlayers = 1; - selgame_gameData->aeTickRate = gnTicksRate; - selgame_gameData->aeNetUpdateRate = 1; selgame_Password[0] = '\0'; SelgamePasswordSelect(0); return; } - selgame_gameData->aeMaxPlayers = MAX_PLRS; SelgameSpeedInit(); } -static void SelgameModeSelect(unsigned index) -{ - selgame_mode = index; - - //gfnHeroInfo(UpdateHeroLevel); - int port = NET_DEFAULT_PORT; - getIniInt("Network", "Port", &port); - snprintf(selgame_GamePort, sizeof(selgame_GamePort), "%d", port); - if (index == SELGAME_CREATE) { - SelgameDiffInit(); - return; - } - SelgameAddressListInit(); -} - static void SelgameSpeedSelect(unsigned index) { selgame_gameData->aeTickRate = gUIListItems[index]->m_value; - selgame_gameData->aeNetUpdateRate = 1; if (provider == SELCONN_LOOPBACK) { selgame_Password[0] = '\0'; SelgamePasswordSelect(0); return; } -#ifndef ADAPTIVE_NETUPDATE - int latency = 80; - getIniInt("Network", "Latency", &latency); - selgame_gameData->aeNetUpdateRate = std::max(2, latency / (1000 / selgame_gameData->aeTickRate)); -#endif - if (ztProvider) { SelgamePasswordInit(0); return; @@ -780,7 +797,19 @@ static void SelgamePasswordSelect(unsigned index) char dialogText[256]; int port = 0; - if (selgame_mode == SELGAME_CREATE) { + if (selgame_mode != SELGAME_JOIN) { + // assert(selgame_mode == SELGAME_CREATE || selgame_mode == SELGAME_LOAD); + selgame_gameData->aeNetUpdateRate = 1; + selgame_gameData->aeMaxPlayers = !selconn_bMulti ? 1 : MAX_PLRS; + if (!selconn_bMulti) { + selgame_gameData->aeTickRate = gnTicksRate; +#ifndef ADAPTIVE_NETUPDATE + } else { + int latency = 80; + getIniInt("Network", "Latency", &latency); + selgame_gameData->aeNetUpdateRate = std::max(2, latency / (1000 / selgame_gameData->aeTickRate)); +#endif + } if (!ztProvider) { setIniValue("Network", "Port", selgame_GamePort); getIniInt("Network", "Port", &port); diff --git a/Source/DiabloUI/selhero.cpp b/Source/DiabloUI/selhero.cpp index f54e8b9ee30..809727bb838 100644 --- a/Source/DiabloUI/selhero.cpp +++ b/Source/DiabloUI/selhero.cpp @@ -339,14 +339,13 @@ static void SelheroClassSelectorFocus(unsigned index) selhero_heroInfo.hiMagic = MagicTbl[index]; //defaults.dsMagic; selhero_heroInfo.hiDexterity = DexterityTbl[index]; //defaults.dsDexterity; selhero_heroInfo.hiVitality = VitalityTbl[index]; //defaults.dsVitality; - //selhero_heroInfo.hiHasSaved = FALSE; SelheroSetStats(); } -static void SelheroLoadSelect(unsigned index) +static void SelheroContinue() { - selhero_result = index == 0 ? SELHERO_CONTINUE : SELHERO_NEW_DUNGEON; + selhero_result = SELHERO_CONTINUE; } static void SelheroClassSelectorInit() @@ -375,25 +374,6 @@ static void SelheroClassSelectorInit() UiInitScreen(NUM_CLASSES, SelheroClassSelectorFocus, SelheroNameInit, SelheroClassSelectorEsc); } -static void SelheroLoadInit() -{ - SelheroResetScreen("Single Player Characters", "Save File Exists"); - - gUIListItems.push_back(new UiListItem("Load Game", 0)); - gUIListItems.push_back(new UiListItem("New Game", 1)); - SDL_Rect rect2 = { SELHERO_RPANEL_LEFT + (SELHERO_RPANEL_WIDTH - 280) / 2, SELHERO_LIST_TOP, 280, 26 * 2 }; - gUiItems.push_back(new UiList(&gUIListItems, 2, rect2, UIS_HCENTER | UIS_VCENTER | UIS_MED | UIS_GOLD)); - - SDL_Rect rect3 = { SELHERO_RPANEL_LEFT, SELHERO_RBUTTON_TOP, SELHERO_RPANEL_WIDTH / 2, 35 }; - gUiItems.push_back(new UiTxtButton("OK", &UiFocusNavigationSelect, rect3, UIS_HCENTER | UIS_VCENTER | UIS_BIG | UIS_GOLD)); - - SDL_Rect rect4 = { SELHERO_RPANEL_LEFT + SELHERO_RPANEL_WIDTH / 2, SELHERO_RBUTTON_TOP, SELHERO_RPANEL_WIDTH / 2, 35 }; - gUiItems.push_back(new UiTxtButton("Cancel", &UiFocusNavigationEsc, rect4, UIS_HCENTER | UIS_VCENTER | UIS_BIG | UIS_GOLD)); - - //assert(gUIListItems.size() == 2); - UiInitScreen(2, NULL, SelheroLoadSelect, SelheroListInit); -} - static void SelheroListSelect(unsigned index) { if (index == selhero_SaveCount) { @@ -401,12 +381,7 @@ static void SelheroListSelect(unsigned index) return; } - if (selhero_heroInfo.hiHasSaved) { - SelheroLoadInit(); - return; - } - - SelheroLoadSelect(1); + SelheroContinue(); } static void SelheroNameInit(unsigned index) @@ -442,7 +417,7 @@ static void SelheroNameSelect(unsigned index) switch (result) { case NEWHERO_DONE: - SelheroLoadSelect(1); + SelheroContinue(); return; case NEWHERO_INVALID_NAME: err = "Invalid name.\nA name cannot contain reserved characters."; diff --git a/Source/multi.cpp b/Source/multi.cpp index 46225eb263a..cdbbc3c2cd5 100644 --- a/Source/multi.cpp +++ b/Source/multi.cpp @@ -775,11 +775,8 @@ static bool multi_init_game(bool bSinglePlayer, _uigamedata& gameData) gbSelectProvider = true; continue; } - } else { - dlgresult = SELHERO_NEW_DUNGEON; } gbSelectHero = bSinglePlayer; - gbLoadGame = dlgresult == SELHERO_CONTINUE; if (IsGameSrv) { gameData.aePlayerId = SNPLAYER_MASTER; mypnum = SNPLAYER_MASTER; @@ -788,14 +785,6 @@ static bool multi_init_game(bool bSinglePlayer, _uigamedata& gameData) pfile_read_hero_from_save(); } - if (gbLoadGame) { - // mypnum = 0; - gameData.aeMaxPlayers = 1; - gameData.aeTickRate = gnTicksRate; - gameData.aeNetUpdateRate = 1; - break; - } - // select game // sets gameData except for aePlayerId, aeSeed (if not joining a game) and aeVersionId dlgresult = UiSelectGame(&gameData); @@ -808,15 +797,15 @@ static bool multi_init_game(bool bSinglePlayer, _uigamedata& gameData) gbSelectHero = true; continue; } - - if (dlgresult == SELGAME_JOIN) { + gbLoadGame = dlgresult == SELGAME_LOAD; + gbJoinGame = dlgresult == SELGAME_JOIN; + if (gbJoinGame) { pnum = gameData.aePlayerId; if (mypnum != pnum) { copy_pod(plr, myplr); mypnum = pnum; //pfile_read_player_from_save(); } - gbJoinGame = true; } break; } diff --git a/Source/pfile.cpp b/Source/pfile.cpp index b60513a28a1..1d12ff07004 100644 --- a/Source/pfile.cpp +++ b/Source/pfile.cpp @@ -120,7 +120,7 @@ void pfile_write_hero(bool bFree) } } -static void pfile_player2hero(const PlayerStruct* p, _uiheroinfo* heroinfo, unsigned saveIdx, bool bHasSaveFile) +static void pfile_player2hero(const PlayerStruct* p, _uiheroinfo* heroinfo, unsigned saveIdx) { memset(heroinfo->hiName, 0, sizeof(heroinfo->hiName)); SStrCopy(heroinfo->hiName, p->_pName, sizeof(heroinfo->hiName)); @@ -132,7 +132,6 @@ static void pfile_player2hero(const PlayerStruct* p, _uiheroinfo* heroinfo, unsi heroinfo->hiMagic = p->_pMagic; heroinfo->hiDexterity = p->_pDexterity; heroinfo->hiVitality = p->_pVitality; - heroinfo->hiHasSaved = bHasSaveFile; } static bool ValidPlayerName(const char* name) @@ -166,7 +165,7 @@ static bool ValidPlayerName(const char* name) return false; SStrCopy(players[i]._pName, name_2, PLR_NAME_LEN); - pfile_player2hero(&players[0], &uihero, mySaveIdx, gbValidSaveFile); + pfile_player2hero(&players[0], &uihero, mySaveIdx); pfile_write_hero(); return true; }*/ @@ -190,7 +189,7 @@ void pfile_ui_load_hero_infos(std::vector<_uiheroinfo> &hero_infos) if (pfile_read_hero(archive, &pkplr)) { UnPackPlayer(&pkplr, 0); _uiheroinfo uihero; - pfile_player2hero(&players[0], &uihero, i, pfile_archive_contains_game(archive)); + pfile_player2hero(&players[0], &uihero, i); hero_infos.push_back(uihero); } SFileCloseArchive(archive); @@ -229,7 +228,7 @@ int pfile_ui_create_save(_uiheroinfo* heroinfo) //mpqapi_remove_entries(pfile_get_file_name); CreatePlayer(*heroinfo); pfile_encode_hero(0); - //pfile_player2hero(&players[0], heroinfo, save_num, false); + //pfile_player2hero(&players[0], heroinfo, save_num); pfile_flush(true); return NEWHERO_DONE; } diff --git a/enums.h b/enums.h index a14aaab388d..e01f730f48d 100644 --- a/enums.h +++ b/enums.h @@ -3997,15 +3997,15 @@ typedef enum _mainmenu_selections { } _mainmenu_selections; typedef enum _selhero_selections { - SELHERO_NONE = 0, - SELHERO_NEW_DUNGEON = 1, - SELHERO_CONTINUE = 2, - SELHERO_PREVIOUS = 3 + SELHERO_NONE, + SELHERO_CONTINUE, + SELHERO_PREVIOUS } _selhero_selections; typedef enum _selgame_selections { SELGAME_CREATE, SELGAME_JOIN, + SELGAME_LOAD, SELGAME_PREVIOUS } _selgame_selections; diff --git a/structs.h b/structs.h index 032e3eb2939..9bf962edc1b 100644 --- a/structs.h +++ b/structs.h @@ -2458,7 +2458,6 @@ typedef struct _uiheroinfo { int16_t hiMagic; int16_t hiDexterity; int16_t hiVitality; - BOOL hiHasSaved; } _uiheroinfo; typedef struct _uigamedata { From 2d4cfffe1c5e4dac60c61ac5797efa6b2845f573 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 9 Dec 2023 12:07:54 +0100 Subject: [PATCH 018/596] no need to delete the temporary levels in case of a new game (guLvlVisited should be 0) --- Source/interfac.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/interfac.cpp b/Source/interfac.cpp index a0df03cf480..eab6d88f04a 100644 --- a/Source/interfac.cpp +++ b/Source/interfac.cpp @@ -320,7 +320,6 @@ void ShowCutscene(unsigned uMsg) switch (uMsg) { case DVL_DWM_NEWGAME: - pfile_delete_save_file(false); LoadGameLevel(ENTRY_MAIN); break; case DVL_DWM_LOADGAME: From 26c5db00091fb62765b56dc113f56cb632e7b878 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 9 Dec 2023 12:25:18 +0100 Subject: [PATCH 019/596] do not call EnterLevel in SetupLocalPlr --- Source/interfac.cpp | 2 +- Source/multi.cpp | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Source/interfac.cpp b/Source/interfac.cpp index eab6d88f04a..2e966b1b0ce 100644 --- a/Source/interfac.cpp +++ b/Source/interfac.cpp @@ -320,7 +320,7 @@ void ShowCutscene(unsigned uMsg) switch (uMsg) { case DVL_DWM_NEWGAME: - LoadGameLevel(ENTRY_MAIN); + SwitchGameLevel(ENTRY_MAIN); break; case DVL_DWM_LOADGAME: LoadGame(); diff --git a/Source/multi.cpp b/Source/multi.cpp index cdbbc3c2cd5..ae5d71c5fde 100644 --- a/Source/multi.cpp +++ b/Source/multi.cpp @@ -662,10 +662,7 @@ static void SetupLocalPlr() { PlayerStruct* p; - EnterLevel(DLV_TOWN); - p = &myplr; - assert(currLvl._dLevelIdx == DLV_TOWN); p->_pDunLevel = DLV_TOWN; p->_pTeam = mypnum; p->_pManaShield = 0; From 989886b6347ab8e0fb6e6daebd9e304a2210b1e6 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 9 Dec 2023 12:42:49 +0100 Subject: [PATCH 020/596] inline SwitchGameLevel (interfac.cpp) --- Source/interfac.cpp | 61 +++++++++++++++------------------------------ 1 file changed, 20 insertions(+), 41 deletions(-) diff --git a/Source/interfac.cpp b/Source/interfac.cpp index 2e966b1b0ce..62d06a64791 100644 --- a/Source/interfac.cpp +++ b/Source/interfac.cpp @@ -267,12 +267,6 @@ void EnterLevel(BYTE lvl) currLvl._dLevelPlyrs = IsMultiGame ? gsDeltaData.ddLevelPlrs[lvl] : 1; } -static void SwitchGameLevel(int lvldir) -{ - EnterLevel(myplr._pDunLevel); - LoadGameLevel(lvldir); -} - /* * Load Game Load In-Game Single Game Multi Game * @@ -318,42 +312,27 @@ void ShowCutscene(unsigned uMsg) FreeLevelMem(); IncProgress(); - switch (uMsg) { - case DVL_DWM_NEWGAME: - SwitchGameLevel(ENTRY_MAIN); - break; - case DVL_DWM_LOADGAME: + if (uMsg != DVL_DWM_LOADGAME) { + int lvldir = ENTRY_MAIN; + if (uMsg != DVL_DWM_NEWGAME) { + lvldir += (uMsg - DVL_DWM_NEXTLVL); + if (uMsg == DVL_DWM_NEXTLVL) + assert(myplr._pDunLevel == currLvl._dLevelIdx + 1); + if (uMsg == DVL_DWM_PREVLVL) + assert(myplr._pDunLevel == currLvl._dLevelIdx - 1); + static_assert((int)DVL_DWM_NEXTLVL - (int)DVL_DWM_NEXTLVL == (int)ENTRY_MAIN - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted I."); + static_assert((int)DVL_DWM_PREVLVL - (int)DVL_DWM_NEXTLVL == (int)ENTRY_PREV - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted II."); + static_assert((int)DVL_DWM_SETLVL - (int)DVL_DWM_NEXTLVL == (int)ENTRY_SETLVL - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted III."); + static_assert((int)DVL_DWM_RTNLVL - (int)DVL_DWM_NEXTLVL == (int)ENTRY_RTNLVL - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted IV."); + static_assert((int)DVL_DWM_WARPLVL - (int)DVL_DWM_NEXTLVL == (int)ENTRY_WARPLVL - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted V."); + static_assert((int)DVL_DWM_TWARPDN - (int)DVL_DWM_NEXTLVL == (int)ENTRY_TWARPDN - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted VI."); + static_assert((int)DVL_DWM_TWARPUP - (int)DVL_DWM_NEXTLVL == (int)ENTRY_TWARPUP - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted VII."); + static_assert((int)DVL_DWM_RETOWN - (int)DVL_DWM_NEXTLVL == (int)ENTRY_RETOWN - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted VIII."); + } + EnterLevel(myplr._pDunLevel); + LoadGameLevel(lvldir); + } else { LoadGame(); - break; - case DVL_DWM_NEXTLVL: - assert(myplr._pDunLevel == currLvl._dLevelIdx + 1); - SwitchGameLevel(ENTRY_MAIN); - break; - case DVL_DWM_PREVLVL: - assert(myplr._pDunLevel == currLvl._dLevelIdx - 1); - SwitchGameLevel(ENTRY_PREV); - break; - case DVL_DWM_SETLVL: - SwitchGameLevel(ENTRY_SETLVL); - break; - case DVL_DWM_RTNLVL: - SwitchGameLevel(ENTRY_RTNLVL); - break; - case DVL_DWM_WARPLVL: - SwitchGameLevel(ENTRY_WARPLVL); - break; - case DVL_DWM_TWARPDN: - SwitchGameLevel(ENTRY_TWARPDN); - break; - case DVL_DWM_TWARPUP: - SwitchGameLevel(ENTRY_TWARPUP); - break; - case DVL_DWM_RETOWN: - SwitchGameLevel(ENTRY_RETOWN); - break; - default: - ASSUME_UNREACHABLE - break; } IncProgress(); // process packets arrived during LoadLevel / delta-load and disable nthread From d7647d853e891cb35ea80a7b43c05f80dc680970 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 10 Dec 2023 08:43:11 +0100 Subject: [PATCH 021/596] simplify validations in StartNewLvl - pnum : it should already be checked - fom : unused unless local player --- Source/player.cpp | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/Source/player.cpp b/Source/player.cpp index 4fa022dc996..56ca0dfbb1c 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -1759,20 +1759,14 @@ __attribute__((no_sanitize("shift-base"))) #endif void StartNewLvl(int pnum, int fom, int lvl) { - if ((unsigned)pnum >= MAX_PLRS) { - dev_fatal("StartNewLvl: illegal player %d", pnum); - } + // assert((unsigned)pnum < MAX_PLRS); + InitLevelChange(pnum); - switch (fom) { - case DVL_DWM_NEXTLVL: - case DVL_DWM_PREVLVL: - case DVL_DWM_RTNLVL: - case DVL_DWM_TWARPDN: - case DVL_DWM_SETLVL: - break; - case DVL_DWM_TWARPUP: - if (pnum == mypnum) { + // net_assert(lvl < NUM_LEVELS); + plr._pDunLevel = lvl; + if (pnum == mypnum) { + if (fom == DVL_DWM_TWARPUP) { assert(currLvl._dType >= 1); static_assert((int)TWARP_CATHEDRAL == (int)DTYPE_CATHEDRAL - 1, "Dtype to Warp conversion requires matching enums I."); static_assert((int)TWARP_CATACOMB == (int)DTYPE_CATACOMBS - 1, "Dtype to Warp conversion requires matching enums II."); @@ -1785,14 +1779,6 @@ void StartNewLvl(int pnum, int fom, int lvl) gbTWarpFrom = (currLvl._dType - 1); gbTownWarps |= 1 << gbTWarpFrom; } - break; - default: - net_assert(0); - ASSUME_UNREACHABLE - } - // net_assert(lvl < NUM_LEVELS); - plr._pDunLevel = lvl; - if (pnum == mypnum) { PostMessage(fom); } } From 7723355b339aeaecc8de588d4b736465b708005a Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 10 Dec 2023 08:44:22 +0100 Subject: [PATCH 022/596] ensure WarpDropX/Y is set --- Source/portal.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/portal.cpp b/Source/portal.cpp index 72fb29cb80b..a14efbea197 100644 --- a/Source/portal.cpp +++ b/Source/portal.cpp @@ -13,6 +13,7 @@ PortalStruct portals[MAXPORTAL]; int portalindex; /** X-coordinate of each players portal in town. */ +static_assert(MAXPORTAL <= 4, "Portal coordinates in town must be set."); const int WarpDropX[MAXPORTAL] = { 47 + DBORDERX, 49 + DBORDERX, 51 + DBORDERX, 53 + DBORDERX }; /** Y-coordinate of each players portal in town. */ const int WarpDropY[MAXPORTAL] = { 30 + DBORDERY, 30 + DBORDERY, 30 + DBORDERY, 30 + DBORDERY }; From 54a29f8a6eafceb53b1f2a40fafce749faab13da Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 10 Dec 2023 08:47:10 +0100 Subject: [PATCH 023/596] do not differentiate between standard/set levels in GetPerm/TempLevelNames --- Source/pfile.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/Source/pfile.cpp b/Source/pfile.cpp index 1d12ff07004..02d080b411f 100644 --- a/Source/pfile.cpp +++ b/Source/pfile.cpp @@ -238,11 +238,8 @@ static bool GetPermLevelNames(unsigned dwIndex, char (&szPerm)[DATA_ARCHIVE_MAX_ const char* fmt; static_assert(NUM_LEVELS < 100, "PermSaveNames are too short to fit the number of levels."); - if (dwIndex < NUM_STDLVLS) - fmt = "perml%02d"; - else if (dwIndex < NUM_LEVELS) { - dwIndex -= NUM_STDLVLS; - fmt = "perms%02d"; + if (dwIndex < NUM_LEVELS) { + fmt = "plvl%02d"; } else return false; @@ -255,11 +252,8 @@ static bool GetTempLevelNames(unsigned dwIndex, char (&szTemp)[DATA_ARCHIVE_MAX_ const char* fmt; static_assert(NUM_LEVELS < 100, "TempSaveNames are too short to fit the number of levels."); - if (dwIndex < NUM_STDLVLS) - fmt = "templ%02d"; - else if (dwIndex < NUM_LEVELS) { - dwIndex -= NUM_STDLVLS; - fmt = "temps%02d"; + if (dwIndex < NUM_LEVELS) { + fmt = "tlvl%02d"; } else return false; From de069250975b9b1a051f52e2e9a43368655c8a54 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 10 Dec 2023 08:50:00 +0100 Subject: [PATCH 024/596] do not call CalcPlrInv in SetupLocalPlr --- Source/multi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/multi.cpp b/Source/multi.cpp index ae5d71c5fde..65cf389303d 100644 --- a/Source/multi.cpp +++ b/Source/multi.cpp @@ -680,7 +680,7 @@ static void SetupLocalPlr() //if (!(p->_pSkillFlags & SFLAG_MELEE)) // p->_pAtkSkill = SPL_RATTACK; // recalculate _pAtkSkill and resistances (depending on the difficulty level) - CalcPlrInv(mypnum, false); + // CalcPlrInv(mypnum, false); - unnecessary, InitLvlPlayer should take care of this if (p->_pHitPoints < (1 << 6)) PlrSetHp(mypnum, (1 << 6)); From 77b63271ffdcfd97ca5f8aa787c5c6ba1e163f13 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 10 Dec 2023 08:59:56 +0100 Subject: [PATCH 025/596] adjust monster placement - allow group-size of 2 anywhere --- Source/monster.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index b2f5ab919aa..204bb525a51 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1141,7 +1141,7 @@ void InitMonsters() #endif na = RandRange(2, 3); else - na = RandRange(3, 5); + na = RandRange(2, 5); PlaceGroup(mtidx, na, 0, 0); } // } From 122c2d7b59c15ba3db413c73eae1b51f96401980 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 10 Dec 2023 09:04:54 +0100 Subject: [PATCH 026/596] bugfix for vanilla (random item placement) - do not reduce the desired area too fast --- Source/items.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Source/items.cpp b/Source/items.cpp index 80785a90a12..c3b9a3c4a2e 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -64,10 +64,10 @@ static void GetRandomItemSpace(int ii) static void GetRandomItemSpace(int randarea, int ii) { int x, y, i, j, tries; + constexpr int numTries = 1000; + // assert(randarea > 0 && randarea < DBORDERX && randarea < DBORDERY); - assert(randarea > 0); - - tries = 0; + tries = numTries; while (TRUE) { x = random_(0, DSIZEX) + DBORDERX; y = random_(0, DSIZEY) + DBORDERY; @@ -79,9 +79,11 @@ static void GetRandomItemSpace(int randarea, int ii) } break; fail: - tries++; - if (tries > 1000 && randarea > 1) + tries--; + if (tries < 0 && randarea > 1) { randarea--; + tries = numTries; + } } SetItemLoc(ii, x, y); From b3b31fc43e7b7c107b2b028765be3f3dc44f5dce Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 10 Dec 2023 09:41:45 +0100 Subject: [PATCH 027/596] reorganize load/savegame - assume mypnum of the local player is zero - assume pDunLevel and currLvl._dLevelIdx is the same - enter level just before LoadGameLevel (and after the player is loaded) --- Source/loadsave.cpp | 38 ++++++++++++++++++-------------------- structs.h | 5 +---- 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index 4c7f2db320e..fe1ff4732eb 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -323,16 +323,6 @@ static BYTE* LoadPlayer(BYTE* DVL_RESTRICT src, int pnum) tbuff += 4; // _pIAMinDam tbuff += 4; // _pIAMaxDam*/ - // CalculateGold(pnum); - CalcPlrInv(pnum, false); - - // Omit pointers _pAnimFileData - // Omit pointer alignment - - InitPlayerGFX(pnum); - SetPlrAnims(pnum); - SyncPlrAnim(pnum); - return src; } @@ -780,9 +770,6 @@ void LoadGame() // assert(gbNetUpdateRate == 1); gdwLastGameTurn = gdwGameLogicTurn; sgbSentThisCycle = ghs->vhSentCycle; - gnDifficulty = ghs->vhDifficulty; - currLvl._dLevelIdx = ghs->vhCurrLevel; - EnterLevel(currLvl._dLevelIdx); for (i = 0; i < NUM_LEVELS; i++) { glSeedTbl[i] = ghs->vhSeeds[i]; } @@ -811,25 +798,29 @@ void LoadGame() AutoMapScale = ghs->vhAutoMapScale; MiniMapScale = ghs->vhMiniMapScale; NormalMapScale = ghs->vhNormalMapScale; + gnDifficulty = ghs->vhDifficulty; AutoMapXOfs = ghs->vhAutoMapXOfs; AutoMapYOfs = ghs->vhAutoMapYOfs; guLvlVisited = ghs->vhLvlVisited; tbuff += sizeof(LSaveGameHeaderStruct); - - tbuff = LoadPlayer(tbuff, mypnum); + // assert(mypnum == 0); + tbuff = LoadPlayer(tbuff, 0); // load meta-data I. (used by LoadGameLevel) for (i = 0; i < NUM_QUESTS; i++) tbuff = LoadQuest(tbuff, i); for (i = 0; i < MAXPORTAL; i++) tbuff = LoadPortal(tbuff, i); - // load level-data + // load level + // assert(mypnum == 0); + EnterLevel(plx(0)._pDunLevel); LoadGameLevel(ENTRY_LOAD); ViewX = _ViewX; ViewY = _ViewY; ResyncQuests(); + // load level-data tbuff = LoadLevelData(tbuff, true); // load meta-data III. (modified by LoadGameLevel) @@ -870,6 +861,13 @@ void LoadGame() tbuff = LoadItem(tbuff, &witchitem[i]); } + // assert(mypnum == 0); + // CalculateGold(0); + CalcPlrInv(0, false); + InitPlayerGFX(0); + SetPlrAnims(0); + SyncPlrAnim(0); + InitAutomapScale(); //ResyncQuests(); @@ -1593,8 +1591,6 @@ void SaveGame() assert(gdwLastGameTurn == gdwGameLogicTurn || ((gdwLastGameTurn + 1) == gdwGameLogicTurn && gbNetUpdateRate == 1)); ghs->vhSentCycle = sgbSentThisCycle; - ghs->vhCurrLevel = currLvl._dLevelIdx; - ghs->vhDifficulty = gnDifficulty; for (i = 0; i < NUM_LEVELS; i++) { ghs->vhSeeds[i] = glSeedTbl[i]; } @@ -1623,14 +1619,15 @@ void SaveGame() ghs->vhAutoMapScale = AutoMapScale; ghs->vhMiniMapScale = MiniMapScale; ghs->vhNormalMapScale = NormalMapScale; + ghs->vhDifficulty = gnDifficulty; ghs->vhAutoMapXOfs = AutoMapXOfs; ghs->vhAutoMapYOfs = AutoMapYOfs; ghs->vhLvlVisited = guLvlVisited; tbuff += sizeof(LSaveGameHeaderStruct); - - tbuff = SavePlayer(tbuff, mypnum); + // assert(mypnum == 0); + tbuff = SavePlayer(tbuff, 0); // save meta-data I. for (i = 0; i < NUM_QUESTS; i++) @@ -1638,6 +1635,7 @@ void SaveGame() for (i = 0; i < MAXPORTAL; i++) tbuff = SavePortal(tbuff, i); // save level-data + // assert(currLvl._dLevelIdx == plx(0)._pDunLevel); constexpr size_t slt = /*MAXDUNX * MAXDUNY +*/ sizeof(LSaveGameLvlMetaStruct) + (MAX_MINIONS + MAX_TOWNERS) * sizeof(LSaveMonsterStruct) /*+ MAXMISSILES * 4 + MAXMISSILES * sizeof(LSaveMissileStruct) + MAXOBJECTS * (4 + sizeof(LSaveObjectStruct))*/ + MAXITEMS * (4 + sizeof(LSaveItemStruct)) + 5 * MAXDUNX * MAXDUNY + MAXDUNX * MAXDUNY * sizeof(INT) /*+ MAXDUNX * MAXDUNY + MAXDUNX * MAXDUNY*/; diff --git a/structs.h b/structs.h index 9bf962edc1b..373d96071a9 100644 --- a/structs.h +++ b/structs.h @@ -1121,9 +1121,6 @@ typedef struct LSaveGameHeaderStruct { LE_INT32 vhInitial; LE_UINT32 vhLogicTurn; LE_UINT32 vhSentCycle; - BYTE vhCurrLevel; - BYTE vhDifficulty; - BYTE vhAlign0[2]; LE_UINT32 vhSeeds[NUM_LEVELS]; LE_INT32 vhCurrSeed; LE_INT32 vhViewX; @@ -1144,7 +1141,7 @@ typedef struct LSaveGameHeaderStruct { BYTE vhAutoMapScale; BYTE vhMiniMapScale; BYTE vhNormalMapScale; - BYTE vhAlign; + BYTE vhDifficulty; LE_INT32 vhAutoMapXOfs; LE_INT32 vhAutoMapYOfs; LE_UINT32 vhLvlVisited; From 674215862f9fd5a9dea6877cb8a3d81400579524 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 10 Dec 2023 09:52:08 +0100 Subject: [PATCH 028/596] reorder LSaveGameHeaderStruct --- Source/loadsave.cpp | 4 ++-- structs.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index fe1ff4732eb..c4037fe05bc 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -792,13 +792,13 @@ void LoadGame() gnNumActiveWindows = ghs->vhNumActiveWindows; memcpy(gaActiveWindows, ghs->vhActiveWindows, sizeof(gaActiveWindows)); + gnDifficulty = ghs->vhDifficulty; gbTownWarps = ghs->vhTownWarps; gbWaterDone = ghs->vhWaterDone; AutoMapScale = ghs->vhAutoMapScale; MiniMapScale = ghs->vhMiniMapScale; NormalMapScale = ghs->vhNormalMapScale; - gnDifficulty = ghs->vhDifficulty; AutoMapXOfs = ghs->vhAutoMapXOfs; AutoMapYOfs = ghs->vhAutoMapYOfs; @@ -1613,13 +1613,13 @@ void SaveGame() ghs->vhNumActiveWindows = gnNumActiveWindows; memcpy(ghs->vhActiveWindows, gaActiveWindows, sizeof(gaActiveWindows)); + ghs->vhDifficulty = gnDifficulty; ghs->vhTownWarps = gbTownWarps; ghs->vhWaterDone = gbWaterDone; ghs->vhAutoMapScale = AutoMapScale; ghs->vhMiniMapScale = MiniMapScale; ghs->vhNormalMapScale = NormalMapScale; - ghs->vhDifficulty = gnDifficulty; ghs->vhAutoMapXOfs = AutoMapXOfs; ghs->vhAutoMapYOfs = AutoMapYOfs; diff --git a/structs.h b/structs.h index 373d96071a9..23a634b7aef 100644 --- a/structs.h +++ b/structs.h @@ -1136,12 +1136,12 @@ typedef struct LSaveGameHeaderStruct { BYTE vhInvflag; LE_INT32 vhNumActiveWindows; BYTE vhActiveWindows[NUM_WNDS]; + BYTE vhDifficulty; BYTE vhTownWarps; BYTE vhWaterDone; BYTE vhAutoMapScale; BYTE vhMiniMapScale; BYTE vhNormalMapScale; - BYTE vhDifficulty; LE_INT32 vhAutoMapXOfs; LE_INT32 vhAutoMapYOfs; LE_UINT32 vhLvlVisited; From da121d557d9e9685fb8a82830612502e97362909 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 10 Dec 2023 16:47:35 +0100 Subject: [PATCH 029/596] cleanup includes (mpqapi.cpp) --- Source/mpqapi.cpp | 5 ----- tools/patcher/mpqapi.cpp | 5 ----- 2 files changed, 10 deletions(-) diff --git a/Source/mpqapi.cpp b/Source/mpqapi.cpp index 6ada5d5219c..f4b8c758258 100644 --- a/Source/mpqapi.cpp +++ b/Source/mpqapi.cpp @@ -4,12 +4,7 @@ * Implementation of functions for creating and editing MPQ files. */ #include -//#include -//#include -//#include -#include #include -#include #include "all.h" #include "utils/file_util.h" diff --git a/tools/patcher/mpqapi.cpp b/tools/patcher/mpqapi.cpp index a9ed971741f..14b185455ac 100644 --- a/tools/patcher/mpqapi.cpp +++ b/tools/patcher/mpqapi.cpp @@ -4,12 +4,7 @@ * Implementation of functions for creating and editing MPQ files. */ #include -#include -#include -#include -#include #include -#include #include "all.h" #include "utils/file_util.h" From 8b11ae5b7577fc967c2f5c8049de70a39dcd3f46 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 10 Dec 2023 16:48:42 +0100 Subject: [PATCH 030/596] fix memory leak in the patcher --- tools/patcher/mpqapi.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/patcher/mpqapi.cpp b/tools/patcher/mpqapi.cpp index 14b185455ac..f4b8c758258 100644 --- a/tools/patcher/mpqapi.cpp +++ b/tools/patcher/mpqapi.cpp @@ -633,6 +633,7 @@ static bool mpqapi_write_file_contents(const char* pszName, const BYTE* pbData, mpqapi_alloc_block(pBlk->bqSizeAlloc + pBlk->bqOffset, emptyBlockSize); } } + mem_free_dbg(sectoroffsettable); return true; } on_error: From 7ca1a26c4bb245e13d50d79e37665db1c04db66e Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 10 Dec 2023 17:06:43 +0100 Subject: [PATCH 031/596] bugfix for 'de-duplicate code' --- Source/encrypt.cpp | 16 ++++++++++------ tools/patcher/encrypt.cpp | 16 ++++++++++------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/Source/encrypt.cpp b/Source/encrypt.cpp index 41a1c7d5879..63fe69c0127 100644 --- a/Source/encrypt.cpp +++ b/Source/encrypt.cpp @@ -93,9 +93,12 @@ DWORD PkwareCompress(BYTE* srcData, DWORD size) // type = CMP_BINARY; // dsize = CMP_IMPLODE_DICT_SIZE3; - if (implode(PkwareBufferRead, PkwareBufferWrite, work_buf, &info) == CMP_NO_ERROR) { - size = info.pbOutBuff - destData; + implode(PkwareBufferRead, PkwareBufferWrite, work_buf, &info); + // copy the result only if the compression reduces the size of the data + destSize = info.pbOutBuff - destData; + if (destSize < size) { memcpy(srcData, destData, size); + size = destSize; } mem_free_dbg(work_buf); mem_free_dbg(destData); @@ -113,10 +116,11 @@ void PkwareDecompress(BYTE* srcData, unsigned size, unsigned dwMaxBytes) TDataInfo info = TDataInfo(srcData, size, destData, dwMaxBytes); - if (explode(PkwareBufferRead, PkwareBufferWrite, work_buf, &info) == CMP_NO_ERROR) { - size = info.pbOutBuff - destData; - memcpy(srcData, destData, size); - } + explode(PkwareBufferRead, PkwareBufferWrite, work_buf, &info); + + size = info.pbOutBuff - destData; + memcpy(srcData, destData, size); + mem_free_dbg(work_buf); mem_free_dbg(destData); } diff --git a/tools/patcher/encrypt.cpp b/tools/patcher/encrypt.cpp index 41a1c7d5879..87149f4252e 100644 --- a/tools/patcher/encrypt.cpp +++ b/tools/patcher/encrypt.cpp @@ -93,9 +93,12 @@ DWORD PkwareCompress(BYTE* srcData, DWORD size) // type = CMP_BINARY; // dsize = CMP_IMPLODE_DICT_SIZE3; - if (implode(PkwareBufferRead, PkwareBufferWrite, work_buf, &info) == CMP_NO_ERROR) { - size = info.pbOutBuff - destData; + implode(PkwareBufferRead, PkwareBufferWrite, work_buf, &info); + // ignore the result if the compression was unsuccessful + destSize = info.pbOutBuff - destData; + if (destSize < size) { memcpy(srcData, destData, size); + size = destSize; } mem_free_dbg(work_buf); mem_free_dbg(destData); @@ -113,10 +116,11 @@ void PkwareDecompress(BYTE* srcData, unsigned size, unsigned dwMaxBytes) TDataInfo info = TDataInfo(srcData, size, destData, dwMaxBytes); - if (explode(PkwareBufferRead, PkwareBufferWrite, work_buf, &info) == CMP_NO_ERROR) { - size = info.pbOutBuff - destData; - memcpy(srcData, destData, size); - } + explode(PkwareBufferRead, PkwareBufferWrite, work_buf, &info); + + size = info.pbOutBuff - destData; + memcpy(srcData, destData, size); + mem_free_dbg(work_buf); mem_free_dbg(destData); } From b0e83eed461469a0f0bc1cfbbf2ad85eefaeec53 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 10 Dec 2023 17:25:09 +0100 Subject: [PATCH 032/596] comment out unused parts of stormlib --- 3rdParty/StormLib/src/SBaseCommon.cpp | 7 ++++--- 3rdParty/StormLib/src/SFileReadFile.cpp | 6 +++--- 3rdParty/StormLib/src/StormCommon.h | 3 ++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/3rdParty/StormLib/src/SBaseCommon.cpp b/3rdParty/StormLib/src/SBaseCommon.cpp index 8e9b4a0f634..abe0410116c 100644 --- a/3rdParty/StormLib/src/SBaseCommon.cpp +++ b/3rdParty/StormLib/src/SBaseCommon.cpp @@ -481,7 +481,7 @@ void DecryptMpqBlock(void * pvDataBlock, DWORD dwLength, DWORD dwKey1) * (dwKey1 + dwKey2) = DataBlock[0] ^ dwDecrypted0; * */ - +#ifdef FULL DWORD DetectFileKeyBySectorSize(LPDWORD EncryptedData, DWORD dwSectorSize, DWORD dwDecrypted0) { DWORD dwDecrypted1Max = dwSectorSize + dwDecrypted0; @@ -608,7 +608,7 @@ DWORD DetectFileKeyByContent(void * pvEncryptedData, DWORD dwSectorSize, DWORD d // Not detected, sorry return 0; } - +#endif // FULL DWORD DecryptFileKey( const char * szFileName, ULONGLONG MpqPos, @@ -1228,6 +1228,7 @@ DWORD AllocateSectorOffsets(TMPQFile * hf, bool bLoadFromFile) // Decrypt loaded sector positions if necessary if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED) { +#ifdef FULL // If we don't know the file key, try to find it. if(hf->dwFileKey == 0) { @@ -1239,7 +1240,7 @@ DWORD AllocateSectorOffsets(TMPQFile * hf, bool bLoadFromFile) return ERROR_UNKNOWN_FILE_KEY; } } - +#endif // FULL // Decrypt sector positions DecryptMpqBlock(hf->SectorOffsets, dwSectorOffsLen, hf->dwFileKey - 1); } diff --git a/3rdParty/StormLib/src/SFileReadFile.cpp b/3rdParty/StormLib/src/SFileReadFile.cpp index 2dfb088f9ca..df415624f3e 100644 --- a/3rdParty/StormLib/src/SFileReadFile.cpp +++ b/3rdParty/StormLib/src/SFileReadFile.cpp @@ -120,7 +120,7 @@ static DWORD ReadMpqSectors(TMPQFile * hf, LPBYTE pbBuffer, DWORD dwByteOffset, // If the file is encrypted, we have to decrypt the sector if (pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED) { BSWAP_ARRAY32_UNSIGNED(pbInSector, dwRawBytesInThisSector); - +#ifdef FULL // If we don't know the key, try to detect it by file content if (hf->dwFileKey == 0) { hf->dwFileKey = DetectFileKeyByContent(pbInSector, dwBytesInThisSector, hf->dwDataSize); @@ -129,7 +129,7 @@ static DWORD ReadMpqSectors(TMPQFile * hf, LPBYTE pbBuffer, DWORD dwByteOffset, break; } } - +#endif DecryptMpqBlock(pbInSector, dwRawBytesInThisSector, hf->dwFileKey + dwIndex); BSWAP_ARRAY32_UNSIGNED(pbInSector, dwRawBytesInThisSector); } @@ -150,7 +150,7 @@ static DWORD ReadMpqSectors(TMPQFile * hf, LPBYTE pbBuffer, DWORD dwByteOffset, } } } -#endif // FULL +#endif // If the sector is really compressed, decompress it. // WARNING : Some sectors may not be compressed, it can be determined only diff --git a/3rdParty/StormLib/src/StormCommon.h b/3rdParty/StormLib/src/StormCommon.h index b412e74ccb9..ddb6949db8a 100644 --- a/3rdParty/StormLib/src/StormCommon.h +++ b/3rdParty/StormLib/src/StormCommon.h @@ -239,9 +239,10 @@ DWORD GetDefaultSpecialFileFlags(DWORD dwFileSize, USHORT wFormatVersion); void EncryptMpqBlock(void * pvDataBlock, DWORD dwLength, DWORD dwKey); void DecryptMpqBlock(void * pvDataBlock, DWORD dwLength, DWORD dwKey); - +#ifdef FULL DWORD DetectFileKeyBySectorSize(LPDWORD EncryptedData, DWORD dwSectorSize, DWORD dwSectorOffsLen); DWORD DetectFileKeyByContent(void * pvEncryptedData, DWORD dwSectorSize, DWORD dwFileSize); +#endif DWORD DecryptFileKey(const char * szFileName, ULONGLONG MpqPos, DWORD dwFileSize, DWORD dwFlags); bool IsValidMD5(LPBYTE pbMd5); From 249517d3ec9895039932cfe59ee11c1e80b459c1 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 12 Dec 2023 11:03:04 +0100 Subject: [PATCH 033/596] bugfix for 'pre-patch the DUN-files of the catacombs' - prevent torches in the setpiece of the valor quest --- Source/drlg_l2.cpp | 8 ++++++++ tools/patcher/DiabloUI/patcher.cpp | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/Source/drlg_l2.cpp b/Source/drlg_l2.cpp index f350717ed99..0d1d7d3258d 100644 --- a/Source/drlg_l2.cpp +++ b/Source/drlg_l2.cpp @@ -2599,6 +2599,7 @@ static void DRLG_L2FixPreMap(int idx) lm[2 + 5 + 8 * 10] = SwapLE16(50); // remove 'items' lm[2 + 10 * 16 + 9 + 2 * 10 * 2] = 0; + // adjust objects // - add book and pedistal lm[2 + 10 * 16 + 10 * 16 * 2 * 2 + 10 * 16 * 2 * 2 + 9 + 24 * 10 * 2] = SwapLE16(15); lm[2 + 10 * 16 + 10 * 16 * 2 * 2 + 10 * 16 * 2 * 2 + 9 + 16 * 10 * 2] = SwapLE16(91); @@ -2615,6 +2616,13 @@ static void DRLG_L2FixPreMap(int idx) lm[2 + 10 * 16 + x + y * 10] = SwapLE16((3 << 8) | (3 << 10) | (3 << 12) | (3 << 14)); } } + lm[2 + 10 * 16 + 2 + 3 * 10] = SwapLE16((3 << 10)); + lm[2 + 10 * 16 + 3 + 3 * 10] = SwapLE16((3 << 8) | (3 << 12)); + lm[2 + 10 * 16 + 6 + 3 * 10] = SwapLE16((3 << 8) | (3 << 10) | (3 << 12)); + for (int y = 4; y < 7; y++) { + lm[2 + 10 * 16 + 3 + y * 10] = SwapLE16((3 << 8) | (3 << 12)); + lm[2 + 10 * 16 + 6 + y * 10] = SwapLE16((3 << 8) | (3 << 12)); + } } else if (pSetPieces[idx]._sptype == SPT_BCHAMB) { // patch the map - Bonestr1.DUN // useless tiles diff --git a/tools/patcher/DiabloUI/patcher.cpp b/tools/patcher/DiabloUI/patcher.cpp index f0693615525..725fe968e8e 100644 --- a/tools/patcher/DiabloUI/patcher.cpp +++ b/tools/patcher/DiabloUI/patcher.cpp @@ -667,6 +667,13 @@ static void patchDungeon(int fileIndex, BYTE* fileBuf, size_t* fileSize) lm[2 + 10 * 16 + x + y * 10] = SwapLE16((3 << 8) | (3 << 10) | (3 << 12) | (3 << 14)); } } + lm[2 + 10 * 16 + 2 + 3 * 10] = SwapLE16((3 << 10)); + lm[2 + 10 * 16 + 3 + 3 * 10] = SwapLE16((3 << 8) | (3 << 12)); + lm[2 + 10 * 16 + 6 + 3 * 10] = SwapLE16((3 << 8) | (3 << 10) | (3 << 12)); + for (int y = 4; y < 7; y++) { + lm[2 + 10 * 16 + 3 + y * 10] = SwapLE16((3 << 8) | (3 << 12)); + lm[2 + 10 * 16 + 6 + y * 10] = SwapLE16((3 << 8) | (3 << 12)); + } // remove rooms *fileSize = (2 + 10 * 16 + 10 * 16 * 2 * 2 + 10 * 16 * 2 * 2 + 10 * 16 * 2 * 2) * 2; } break; From c79c59885898d4c3982736f1087d287f6fce23c1 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 12 Dec 2023 16:21:57 +0100 Subject: [PATCH 034/596] bugfix for 'maintain synchronized inventories in multiplayer games II.' - fix the mushroom quest --- Source/towners.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/towners.cpp b/Source/towners.cpp index ec558a77e0c..c1994c32801 100644 --- a/Source/towners.cpp +++ b/Source/towners.cpp @@ -567,7 +567,7 @@ void SyncTownerQ(int pnum, int idx) quests[Q_MUSHROOM]._qmsg = TEXT_MUSH10; break; case IDI_BRAIN: - if (quests[Q_MUSHROOM]._qactive != QUEST_ACTIVE || quests[Q_MUSHROOM]._qvar1 >= QV_MUSHROOM_MUSHGIVEN) + if (quests[Q_MUSHROOM]._qactive != QUEST_ACTIVE || quests[Q_MUSHROOM]._qvar1 >= QV_MUSHROOM_BRAINGIVEN) return; quests[Q_MUSHROOM]._qvar1 = QV_MUSHROOM_BRAINGIVEN; quests[Q_MUSHROOM]._qmsg = TEXT_MUSH4; From 06bc271eff3d3dd2363d61350a67ca2d901989b4 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 12 Dec 2023 17:07:33 +0100 Subject: [PATCH 035/596] bugfix for vanilla(?) - restore portal missiles after load in town --- Source/loadsave.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index c4037fe05bc..d5a52e08f3b 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -696,6 +696,7 @@ static BYTE* LoadLevelData(BYTE* src, bool full) if (full) { for (i = 0; i < MAX_MINIONS + MAX_TOWNERS; i++) src = LoadMonster(src, i); + SyncPortals(); // restore portal missiles } } From a088156c0ae130dd7de3605d3930841b91705b27 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 13 Dec 2023 10:45:35 +0100 Subject: [PATCH 036/596] fix 'Pierce Shot' - fire the right missile... --- Source/spelldat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/spelldat.cpp b/Source/spelldat.cpp index 589220fa76e..221052ec394 100644 --- a/Source/spelldat.cpp +++ b/Source/spelldat.cpp @@ -50,7 +50,7 @@ const SpellData spelldata[NUM_SPELLS] = { /*SPL_RATTACK*/ { 0, STYPE_NONE, ICN_RTK, "Ranged Attack", SPELL_NA, SPELL_NA, SPELL_NA, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON | SFLAG_RANGED, 0, 0, MIS_ARROW, 0, 0, 0, 0, 0, 0, ALIGN64 }, /*SPL_POINT_BLANK*/ { 2, STYPE_NONE, ICN_RPB, "Point Blank", 4, SPELL_NA, SPELL_NA, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON | SFLAG_RANGED, 0, 0, MIS_PBARROW, 0, 2, 0, 0, 5000, 0, ALIGN64 }, /*SPL_FAR_SHOT*/ { 2, STYPE_NONE, ICN_RAS, "Far Shot", 8, SPELL_NA, SPELL_NA, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON | SFLAG_RANGED, 0, 0, MIS_ASARROW, 0, 2, 0, 0, 10000, 0, ALIGN64 }, -/*SPL_PIERCE_SHOT*/ { 2, STYPE_NONE, 20, "Pierce Shot", 14, SPELL_NA, SPELL_NA, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON | SFLAG_RANGED, 0, 0, MIS_ASARROW, 0, 2, 0, 0, 16000, 0, ALIGN64 }, +/*SPL_PIERCE_SHOT*/ { 2, STYPE_NONE, 20, "Pierce Shot", 14, SPELL_NA, SPELL_NA, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON | SFLAG_RANGED, 0, 0, MIS_PCARROW, 0, 2, 0, 0, 16000, 0, ALIGN64 }, /*SPL_MULTI_SHOT*/ { 8, STYPE_NONE, 9, "Multi Shot", 16, SPELL_NA, SPELL_NA, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON | SFLAG_RANGED, 0, 0, MIS_MLARROW, 0, 8, 0, 0, 20000, 0, ALIGN64 }, /*SPL_CHARGE*/ { 2, STYPE_MAGIC, ICN_CHR, "Charge", 10, SPELL_NA, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 0, 0, MIS_CHARGE, 0, 2, 0, 0, 12000, 0, ALIGN64 }, /*SPL_RAGE*/ { 7, STYPE_MAGIC, 23, "Rage", 2, SPELL_NA, 4, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_RAGE, 0, IS_CAST6, MIS_RAGE, 2, 2, 0, 0, 1500, 100, ALIGN64 }, From 9c29cc335a80652849221126599cc5c59a114169 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 13 Dec 2023 11:41:54 +0100 Subject: [PATCH 037/596] fix comments in AddL2Torches --- Source/objects.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/objects.cpp b/Source/objects.cpp index 855a47b66a2..fdde7951379 100644 --- a/Source/objects.cpp +++ b/Source/objects.cpp @@ -489,7 +489,7 @@ static void AddDunObjs(int x1, int y1, int x2, int y2) static void AddL2Torches() { int i, j; - // place torches on NE->SW walls + // place torches on NW->SE walls for (i = DBORDERX; i < DBORDERX + DSIZEX; i++) { for (j = DBORDERY; j < DBORDERY + DSIZEY; j++) { // skip setmap pieces @@ -510,7 +510,7 @@ static void AddL2Torches() j += 4; } } - // place torches on NW->SE walls + // place torches on NE->SW walls for (j = DBORDERY; j < DBORDERY + DSIZEY; j++) { for (i = DBORDERX; i < DBORDERX + DSIZEX; i++) { // skip setmap pieces From 05a5432b6f1cb5701c752046d6e7ca0c6ec50833 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 13 Dec 2023 11:43:00 +0100 Subject: [PATCH 038/596] bugfix for 'add oLightRadius, oLightOffX/Y to ObjectData' - fix light in "Lazarus' Lair" --- Source/gendung.cpp | 7 ++++--- Source/objects.cpp | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Source/gendung.cpp b/Source/gendung.cpp index e92097fd374..3b653edee2d 100644 --- a/Source/gendung.cpp +++ b/Source/gendung.cpp @@ -1608,16 +1608,17 @@ void DRLG_ChangeMap(int x1, int y1, int x2, int y2/*, bool hasNewObjPiece*/) y1 = 2 * y1 + DBORDERY; x2 = 2 * x2 + DBORDERX + 1; y2 = 2 * y2 + DBORDERY + 1; - // TODO: LoadPreLighting, DRLG_LightSubtiles? (see SyncPedestal) + LoadPreLighting(); + // TODO: DRLG_LightSubtiles? ObjChangeMap(x1, y1, x2, y2 /*, bool hasNewObjPiece*/); + SavePreLighting(); + // RedoLightAndVision(); // activate monsters MonChangeMap(); gbDoTransVals = true; if (!deltaload) { DRLG_RedoTrans(); } - // RedoLightAndVision(); - // TODO: SavePreLighting? } void DRLG_RedoTrans() diff --git a/Source/objects.cpp b/Source/objects.cpp index fdde7951379..709cb70c0c9 100644 --- a/Source/objects.cpp +++ b/Source/objects.cpp @@ -1829,6 +1829,7 @@ void MonstCheckDoors(int mx, int my) void ObjChangeMap(int x1, int y1, int x2, int y2/*, bool hasNewObjPiece*/) { int i; + // const ObjectData* ods; // activate objects for (i = 0; i < numobjects; i++) { @@ -1842,6 +1843,18 @@ void ObjChangeMap(int x1, int y1, int x2, int y2/*, bool hasNewObjPiece*/) dObject[os->_ox][os->_oy] = oi + 1; os->_oModeFlags &= ~OMF_RESERVED; os->_oSelFlag = objectdata[os->_otype].oSelFlag; + assert(objectdata[os->_otype].oLightRadius == 0); + /*ods = &objectdata[os->_otype]; + if (ods->oLightRadius != 0) { +#if FLICKER_LIGHT + if (type == OBJ_L1LIGHT) { + os->_olid = NO_LIGHT; + } else +#endif + { + TraceLightSource(os->_ox + ods->oLightOffX, os->_oy + ods->oLightOffY, ods->oLightRadius); + } + }*/ } // add new objects (doors + light) AddDunObjs(x1, y1, x2, y2); @@ -2201,7 +2214,7 @@ static void SyncPedestal(/*int oi*/) else DRLG_ChangeMap(sx, sy, sx + 9, sy + 8/*, false*/); // load the torches TODO: make this more generic (handle OMF_RESERVED in case of torches + always reload lighting)? - LoadPreLighting(); + // LoadPreLighting(); #if 1 { // BYTE lvlMask = 1 << currLvl._dType; From 3c21cea11ac451bbbaddaedf254398527fb0be28 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 13 Dec 2023 11:55:13 +0100 Subject: [PATCH 039/596] reorganize level-saves - save the number of items/monsters/objects/missiles in any case - save objects and missiles in town - reset stoned/charging monsters in LoadMonster instead in SaveMonster --- Source/loadsave.cpp | 159 ++++++++++++++++++-------------------------- 1 file changed, 64 insertions(+), 95 deletions(-) diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index d5a52e08f3b..477c5c44218 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -326,7 +326,7 @@ static BYTE* LoadPlayer(BYTE* DVL_RESTRICT src, int pnum) return src; } -static BYTE* LoadMonster(BYTE* DVL_RESTRICT src, int mnum) +static BYTE* LoadMonster(BYTE* DVL_RESTRICT src, int mnum, bool full) { MonsterStruct* DVL_RESTRICT mon = &monsters[mnum]; @@ -437,6 +437,18 @@ static BYTE* LoadMonster(BYTE* DVL_RESTRICT src, int mnum) // Skip pointer mAnims // Skip _mType + if (!full) { + // reset charging and stoned monsters, because the missiles are not saved + if (mon->_mmode == MM_STONE) { + mon->_mmode = mon->_mVar3; + } else if (mon->_mmode == MM_CHARGE) { + mon->_mmode = MM_STAND; + // TODO: set mVar1 and mVar2? + // mon->_mVar1 = MM_CHARGE; // STAND_PREV_MODE + // mon->_mVar2 = ...; + } + } + return src; } @@ -651,30 +663,33 @@ static BYTE* LoadPortal(BYTE* DVL_RESTRICT src, int i) static BYTE* LoadLevelData(BYTE* src, bool full) { - int i, ii; + int i, moncount, ii; LSaveGameLvlMetaStruct* lms; deltaload = true; + lms = (LSaveGameLvlMetaStruct*)src; + // if (full || currLvl._dType != DTYPE_TOWN) + nummonsters = lms->vvnummonsters; + if (full) + nummissiles = lms->vvnummissiles; + // if (full || currLvl._dType != DTYPE_TOWN) + numobjects = lms->vvnumobjects; + numitems = lms->vvnumitems; + src += sizeof(LSaveGameLvlMetaStruct); + moncount = currLvl._dType != DTYPE_TOWN ? MAXMONSTERS : (full ? MAX_MINIONS + MAX_TOWNERS : 0); + for (i = 0; i < moncount; i++) + src = LoadMonster(src, i, full); if (currLvl._dType != DTYPE_TOWN) { - lms = (LSaveGameLvlMetaStruct*)src; - nummonsters = lms->vvnummonsters; - if (full) - nummissiles = lms->vvnummissiles; - numobjects = lms->vvnumobjects; - numitems = lms->vvnumitems; - src += sizeof(LSaveGameLvlMetaStruct); - - for (i = 0; i < MAXMONSTERS; i++) - src = LoadMonster(src, i); - // run in a separate loop to make it faster(?) and more conform with the other Load/Sync function calls for (i = 0; i < MAXMONSTERS; i++) SyncMonsterAnim(i); - if (full) { - LE_LOAD_INTS(missileactive, src, lengthof(missileactive)); - src += lengthof(missileactive) * sizeof(LE_INT32); - for (i = 0; i < nummissiles; i++) - src = LoadMissile(src, missileactive[i]); - } + } + if (full) { + LE_LOAD_INTS(missileactive, src, lengthof(missileactive)); + src += lengthof(missileactive) * sizeof(LE_INT32); + for (i = 0; i < nummissiles; i++) + src = LoadMissile(src, missileactive[i]); + } + if (full || currLvl._dType != DTYPE_TOWN) { // LE_LOAD_INTS(objectactive, src, lengthof(objectactive)); // src += lengthof(objectactive) * sizeof(LE_INT32); // LE_LOAD_INTS(objectavail, src, lengthof(objectavail)); @@ -684,20 +699,6 @@ static BYTE* LoadLevelData(BYTE* src, bool full) // run in a separate loop because objects (e.g. crux) might depend on each other for (i = 0; i < numobjects; i++) SyncObjectAnim(i); // objectactive[i] - } else { // currLvl._dType == DTYPE_TOWN - lms = (LSaveGameLvlMetaStruct*)src; - if (full) - nummonsters = lms->vvnummonsters; - // nummissiles = lms->vvnummissiles; - // numobjects = lms->vvnumobjects; - numitems = lms->vvnumitems; - src += sizeof(LSaveGameLvlMetaStruct); - - if (full) { - for (i = 0; i < MAX_MINIONS + MAX_TOWNERS; i++) - src = LoadMonster(src, i); - SyncPortals(); // restore portal missiles - } } LE_LOAD_INTS(itemactive, src, lengthof(itemactive)); @@ -720,23 +721,20 @@ static BYTE* LoadLevelData(BYTE* src, bool full) src += MAXDUNX * MAXDUNY; memcpy(dPlayer, src, MAXDUNX * MAXDUNY); src += MAXDUNX * MAXDUNY; + memcpy(dMissile, src, MAXDUNX * MAXDUNY); + src += MAXDUNX * MAXDUNY; } if (full || currLvl._dType != DTYPE_TOWN) { LE_LOAD_INTS(&dMonster[0][0], src, MAXDUNX * MAXDUNY); src += MAXDUNX * MAXDUNY * sizeof(LE_INT32); + memcpy(dObject, src, MAXDUNX * MAXDUNY); + src += MAXDUNX * MAXDUNY; } if (currLvl._dType != DTYPE_TOWN) { memcpy(dDead, src, MAXDUNX * MAXDUNY); src += MAXDUNX * MAXDUNY; - memcpy(dObject, src, MAXDUNX * MAXDUNY); - src += MAXDUNX * MAXDUNY; - - if (full) { - memcpy(dMissile, src, MAXDUNX * MAXDUNY); - src += MAXDUNX * MAXDUNY; - } } deltaload = false; @@ -1180,22 +1178,10 @@ static BYTE* SavePlayer(BYTE* DVL_RESTRICT dest, int pnum) return dest; } -static BYTE* SaveMonster(BYTE* DVL_RESTRICT dest, int mnum, bool full) +static BYTE* SaveMonster(BYTE* DVL_RESTRICT dest, int mnum) { MonsterStruct* DVL_RESTRICT mon = &monsters[mnum]; - if (!full) { - // reset charging and stoned monsters, because the missiles are not saved - if (mon->_mmode == MM_STONE) { - mon->_mmode = mon->_mVar3; - } else if (mon->_mmode == MM_CHARGE) { - mon->_mmode = MM_STAND; - // TODO: set mVar1 and mVar2? - // mon->_mVar1 = MM_CHARGE; // STAND_PREV_MODE - // mon->_mVar2 = ...; - } - } - LSaveMonsterStruct* DVL_RESTRICT monSave = (LSaveMonsterStruct*)dest; #if SDL_BYTEORDER == SDL_BIG_ENDIAN || INTPTR_MAX != INT32_MAX monSave->vmmode = mon->_mmode; @@ -1495,46 +1481,32 @@ static BYTE* SavePortal(BYTE* DVL_RESTRICT dest, int i) static BYTE* SaveLevelData(BYTE* dest, bool full) { - int i; + int i, moncount; LSaveGameLvlMetaStruct* lms; - if (currLvl._dType != DTYPE_TOWN) { - lms = (LSaveGameLvlMetaStruct*)dest; - lms->vvnummonsters = nummonsters; - // if (full) - lms->vvnummissiles = nummissiles; - lms->vvnumobjects = numobjects; - lms->vvnumitems = numitems; - dest += sizeof(LSaveGameLvlMetaStruct); - - for (i = 0; i < MAXMONSTERS; i++) - dest = SaveMonster(dest, i, full); - - if (full) { - LE_SAVE_INTS(dest, missileactive, lengthof(missileactive)); - dest += lengthof(missileactive) * sizeof(LE_INT32); - for (i = 0; i < nummissiles; i++) - dest = SaveMissile(dest, missileactive[i]); - } + lms = (LSaveGameLvlMetaStruct*)dest; + lms->vvnummonsters = nummonsters; + // if (full) + lms->vvnummissiles = nummissiles; + lms->vvnumobjects = numobjects; + lms->vvnumitems = numitems; + dest += sizeof(LSaveGameLvlMetaStruct); + moncount = currLvl._dType != DTYPE_TOWN ? MAXMONSTERS : (full ? MAX_MINIONS + MAX_TOWNERS : 0); + for (i = 0; i < moncount; i++) + dest = SaveMonster(dest, i); + if (full) { + LE_SAVE_INTS(dest, missileactive, lengthof(missileactive)); + dest += lengthof(missileactive) * sizeof(LE_INT32); + for (i = 0; i < nummissiles; i++) + dest = SaveMissile(dest, missileactive[i]); + } + if (full || currLvl._dType != DTYPE_TOWN) { // LE_SAVE_INTS(dest, objectactive, lengthof(objectactive)); // dest += lengthof(objectactive) * sizeof(LE_INT32); // LE_SAVE_INTS(dest, objectavail, lengthof(objectavail)); // dest += lengthof(objectavail) * sizeof(LE_INT32); for (i = 0; i < numobjects; i++) dest = SaveObject(dest, i); // objectactive[i] - } else { - lms = (LSaveGameLvlMetaStruct*)dest; - if (full) - lms->vvnummonsters = nummonsters; - // lms->vvnummissiles = nummissiles; - // lms->vvnumobjects = numobjects; - lms->vvnumitems = numitems; - dest += sizeof(LSaveGameLvlMetaStruct); - - if (full) { - for (i = 0; i < MAX_MINIONS + MAX_TOWNERS; i++) - dest = SaveMonster(dest, i, true/*full*/); - } } LE_SAVE_INTS(dest, itemactive, lengthof(itemactive)); @@ -1554,23 +1526,20 @@ static BYTE* SaveLevelData(BYTE* dest, bool full) dest += MAXDUNX * MAXDUNY; memcpy(dest, dPlayer, MAXDUNX * MAXDUNY); dest += MAXDUNX * MAXDUNY; + memcpy(dest, dMissile, MAXDUNX * MAXDUNY); + dest += MAXDUNX * MAXDUNY; } if (full || currLvl._dType != DTYPE_TOWN) { LE_SAVE_INTS(dest, &dMonster[0][0], MAXDUNX * MAXDUNY); dest += MAXDUNX * MAXDUNY * sizeof(LE_INT32); + memcpy(dest, dObject, MAXDUNX * MAXDUNY); + dest += MAXDUNX * MAXDUNY; } if (currLvl._dType != DTYPE_TOWN) { memcpy(dest, dDead, MAXDUNX * MAXDUNY); dest += MAXDUNX * MAXDUNY; - memcpy(dest, dObject, MAXDUNX * MAXDUNY); - dest += MAXDUNX * MAXDUNY; - - if (full) { - memcpy(dest, dMissile, MAXDUNX * MAXDUNY); - dest += MAXDUNX * MAXDUNY; - } } return dest; @@ -1637,9 +1606,9 @@ void SaveGame() tbuff = SavePortal(tbuff, i); // save level-data // assert(currLvl._dLevelIdx == plx(0)._pDunLevel); - constexpr size_t slt = /*MAXDUNX * MAXDUNY +*/ sizeof(LSaveGameLvlMetaStruct) + (MAX_MINIONS + MAX_TOWNERS) * sizeof(LSaveMonsterStruct) /*+ MAXMISSILES * 4 - + MAXMISSILES * sizeof(LSaveMissileStruct) + MAXOBJECTS * (4 + sizeof(LSaveObjectStruct))*/ + MAXITEMS * (4 + sizeof(LSaveItemStruct)) - + 5 * MAXDUNX * MAXDUNY + MAXDUNX * MAXDUNY * sizeof(INT) /*+ MAXDUNX * MAXDUNY + MAXDUNX * MAXDUNY*/; + constexpr size_t slt = /*MAXDUNX * MAXDUNY +*/ sizeof(LSaveGameLvlMetaStruct) + (MAX_MINIONS + MAX_TOWNERS) * sizeof(LSaveMonsterStruct) + MAXMISSILES * 4 + + MAXMISSILES * sizeof(LSaveMissileStruct)/* + MAXOBJECTS * (4 + sizeof(LSaveObjectStruct))*/ + MAXITEMS * (4 + sizeof(LSaveItemStruct)) + + 5 * MAXDUNX * MAXDUNY + MAXDUNX * MAXDUNY * sizeof(INT)/* + MAXDUNX * MAXDUNY*/ + MAXDUNX * MAXDUNY; constexpr size_t sld = (MAXDUNX * MAXDUNY) + sizeof(LSaveGameLvlMetaStruct) + (MAXMONSTERS * sizeof(LSaveMonsterStruct) + MAXMISSILES * 4 + MAXMISSILES * sizeof(LSaveMissileStruct) + MAXOBJECTS * (4 + sizeof(LSaveObjectStruct))) + MAXITEMS * (4 + sizeof(LSaveItemStruct)) + 5 * MAXDUNX * MAXDUNY + (MAXDUNX * MAXDUNY * 4 + MAXDUNX * MAXDUNY + MAXDUNX * MAXDUNY); From 8a71642ab2df23ce08089862b80d01269d4cf715 Mon Sep 17 00:00:00 2001 From: Oleksandr Kalko Date: Wed, 13 Dec 2023 14:15:11 +0200 Subject: [PATCH 040/596] Android build system upgrades * Upgrade Gradle plugin to 8.2.0 * Upgrade Gradle to 8.5 * Upgrade NDK to 26.1 * Move `buildFeatures` to Gradle build file, since using flag in `gradle.properties` is deprecated --- android-project/app/build.gradle | 5 ++++- android-project/build.gradle | 2 +- android-project/gradle.properties | 1 - android-project/gradle/wrapper/gradle-wrapper.properties | 4 ++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/android-project/app/build.gradle b/android-project/app/build.gradle index 915c87488d4..85f2198b39d 100644 --- a/android-project/app/build.gradle +++ b/android-project/app/build.gradle @@ -7,7 +7,7 @@ if (buildAsApplication) { } android { - // ndkVersion '26.0.10792818' - asio is not ready for this + // ndkVersion '26.1.10909125' - asio is not ready for this ndkVersion '25.2.9519653' compileSdk 34 aaptOptions { // probably does not matter... @@ -37,6 +37,9 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + buildFeatures { + buildConfig true + } applicationVariants.all { variant -> tasks["merge${variant.name.capitalize()}Assets"] .dependsOn("externalNativeBuild${variant.name.capitalize()}") diff --git a/android-project/build.gradle b/android-project/build.gradle index 2aacd59e2a4..250375c438c 100644 --- a/android-project/build.gradle +++ b/android-project/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:8.1.1' + classpath 'com.android.tools.build:gradle:8.2.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/android-project/gradle.properties b/android-project/gradle.properties index 3f60deff987..9f958a0d111 100644 --- a/android-project/gradle.properties +++ b/android-project/gradle.properties @@ -1,3 +1,2 @@ -android.defaults.buildfeatures.buildconfig=true android.nonFinalResIds=false android.nonTransitiveRClass=false diff --git a/android-project/gradle/wrapper/gradle-wrapper.properties b/android-project/gradle/wrapper/gradle-wrapper.properties index fa7b9bcb86c..ff4eb9e0814 100644 --- a/android-project/gradle/wrapper/gradle-wrapper.properties +++ b/android-project/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sat Aug 19 20:48:57 CEST 2023 +#Wed Dec 13 13:49:58 EET 2023 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME From 3b66d9fca2310d3252b44c5db2225860aa46148c Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 14 Dec 2023 12:41:17 +0100 Subject: [PATCH 041/596] get rid of the walking variable in MAI_SkelBow --- Source/monster.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 204bb525a51..2ece5ea5756 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3069,7 +3069,6 @@ void MAI_SkelBow(int mnum) { MonsterStruct* mon; int v; - bool walking; mon = &monsters[mnum]; if (MON_ACTIVE || MON_RELAXED) @@ -3079,22 +3078,20 @@ void MAI_SkelBow(int mnum) // assert(!(mon->_mFlags & MFLAG_CAN_OPEN_DOOR)); mon->_mdir = currEnemyInfo._meLastDir; - walking = false; if (currEnemyInfo._meRealDist < 4) { v = random_(110, 100); if (v < (70 + 8 * mon->_mAI.aiInt)) { - walking = MonDumbWalk(mnum, OPPOSITE(mon->_mdir)); + if (MonDumbWalk(mnum, OPPOSITE(mon->_mdir))) + return; } } - if (!walking) { - // STAND_PREV_MODE - if (mon->_mVar1 == MM_DELAY && MON_HAS_ENEMY /*&& EnemyInLine(mnum)*/) { - // assert(LineClear(mon->_mx, mon->_my, mon->_menemyx, mon->_menemyy)); -- or just left the view, but who cares... - MonStartRAttack(mnum, MIS_ARROW); - } else { - MonStartDelay(mnum, RandRange(21, 24) - 4 * mon->_mAI.aiInt); - } + // STAND_PREV_MODE + if (mon->_mVar1 == MM_DELAY && MON_HAS_ENEMY /*&& EnemyInLine(mnum)*/) { + // assert(LineClear(mon->_mx, mon->_my, mon->_menemyx, mon->_menemyy)); -- or just left the view, but who cares... + MonStartRAttack(mnum, MIS_ARROW); + } else { + MonStartDelay(mnum, RandRange(21, 24) - 4 * mon->_mAI.aiInt); } } From 701debfca537237b8a0018704d25a792cc905fb8 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 14 Dec 2023 12:44:08 +0100 Subject: [PATCH 042/596] ensure monster-AI works with higher aiInt values II. --- Source/monster.cpp | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 2ece5ea5756..06e18d41ea6 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3087,9 +3087,13 @@ void MAI_SkelBow(int mnum) } // STAND_PREV_MODE - if (mon->_mVar1 == MM_DELAY && MON_HAS_ENEMY /*&& EnemyInLine(mnum)*/) { - // assert(LineClear(mon->_mx, mon->_my, mon->_menemyx, mon->_menemyy)); -- or just left the view, but who cares... - MonStartRAttack(mnum, MIS_ARROW); + if (mon->_mVar1 == MM_DELAY) { + if (MON_HAS_ENEMY /*&& EnemyInLine(mnum)*/) { + // assert(LineClear(mon->_mx, mon->_my, mon->_menemyx, mon->_menemyy)); -- or just left the view, but who cares... + MonStartRAttack(mnum, MIS_ARROW); + } else { + mon->_mVar1 = MM_STAND; // STAND_PREV_MODE + } } else { MonStartDelay(mnum, RandRange(21, 24) - 4 * mon->_mAI.aiInt); } @@ -3428,8 +3432,8 @@ void MAI_Ranged(int mnum) && MonDestWalk(mnum)) { return; } - } - MonStartDelay(mnum, md + 1); + } else + MonStartDelay(mnum, md + 1); } } else { MonDestWalk(mnum); @@ -3684,18 +3688,18 @@ void MAI_RoundRanged(int mnum) || v < ((8 * (mon->_mAI.aiInt + 1)) >> mon->_mAI.aiParam2)) && EnemyInLine(mnum)) { MonStartRSpAttack(mnum, mon->_mAI.aiParam1); + return; } else if (dist >= 2) { if (v < 10 * (mon->_mAI.aiInt + 5) || (MON_JUST_WALKED && v < 10 * (mon->_mAI.aiInt + 8))) { MonDestWalk(mnum); + return; } } else if (v < 10 * (mon->_mAI.aiInt + 6)) { MonStartAttack(mnum); + return; } - if (mon->_mmode == MM_STAND) { - v = std::max(1, RandRange(6, 13) - mon->_mAI.aiInt); - MonStartDelay(mnum, v); - } + MonStartDelay(mnum, RandRange(6, 13) - mon->_mAI.aiInt); } } @@ -3753,6 +3757,7 @@ void MAI_RoundRanged2(int mnum) if (v < 10 * (mon->_mAI.aiInt + 5) || (MON_JUST_WALKED && v < 10 * (mon->_mAI.aiInt + 8))) { MonDestWalk(mnum); + return; } } else { if (v < 10 * (mon->_mAI.aiInt + 4)) { @@ -3760,11 +3765,10 @@ void MAI_RoundRanged2(int mnum) MonStartAttack(mnum); else MonStartRSpAttack(mnum, mon->_mAI.aiParam1); + return; } } - if (mon->_mmode == MM_STAND) { - MonStartDelay(mnum, RandRange(6, 13) - mon->_mAI.aiInt); - } + MonStartDelay(mnum, RandRange(6, 13) - mon->_mAI.aiInt); } } From 0917bba59fe6790ae16fe11a27fa73fbe65c01d9 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 14 Dec 2023 12:50:19 +0100 Subject: [PATCH 043/596] Adria does not sell books or rejuvenation-potions --- Source/items.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Source/items.cpp b/Source/items.cpp index c3b9a3c4a2e..ef890c55e59 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -3499,11 +3499,8 @@ static bool WitchItemOk(int i) { return AllItemsList[i].itype == ITYPE_STAFF || (AllItemsList[i].itype == ITYPE_MISC - && (AllItemsList[i].iMiscId == IMISC_BOOK - || AllItemsList[i].iMiscId == IMISC_SCROLL - || AllItemsList[i].iMiscId == IMISC_RUNE - || AllItemsList[i].iMiscId == IMISC_REJUV - || AllItemsList[i].iMiscId == IMISC_FULLREJUV)); + && (AllItemsList[i].iMiscId == IMISC_SCROLL + || AllItemsList[i].iMiscId == IMISC_RUNE)); } static int RndWitchItem(unsigned lvl) From 48410e7943867c07b65b7d50f530b45d0920fd26 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 14 Dec 2023 12:54:15 +0100 Subject: [PATCH 044/596] cleanup stores.cpp - simplify PrintStoreItem + make it independent of 'HELLFIRE' - ignore the belt items when checking for items to sell + cosmetic --- Source/stores.cpp | 37 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index 1a77f6179f5..c14e0ed98f9 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -344,24 +344,19 @@ static void PrintStoreItem(const ItemStruct* is, int l, bool sel) AddSText(40, l++, false, sstr, iclr, false); cursor = 0; } - if (is->_iClass == ICLASS_WEAPON) { -#ifdef HELLFIRE - if (is->_iMinDam == is->_iMaxDam) { - if (is->_iMaxDur != DUR_INDESTRUCTIBLE) - cat_str(sstr, cursor, "Damage: %d Dur: %d/%d", is->_iMinDam, is->_iDurability, is->_iMaxDur); - else - cat_str(sstr, cursor, "Damage: %d Indestructible", is->_iMinDam); - } else -#endif - if (is->_iMaxDur != DUR_INDESTRUCTIBLE) - cat_str(sstr, cursor, "Damage: %d-%d Dur: %d/%d", is->_iMinDam, is->_iMaxDam, is->_iDurability, is->_iMaxDur); + if (is->_iClass == ICLASS_WEAPON || is->_iClass == ICLASS_ARMOR) { + if (is->_iClass == ICLASS_WEAPON) { + if (is->_iMinDam == is->_iMaxDam) + cat_str(sstr, cursor, "Damage: %d", is->_iMinDam); else - cat_str(sstr, cursor, "Damage: %d-%d Indestructible", is->_iMinDam, is->_iMaxDam); - } else if (is->_iClass == ICLASS_ARMOR) { + cat_str(sstr, cursor, "Damage: %d-%d", is->_iMinDam, is->_iMaxDam); + } else { + cat_str(sstr, cursor, "Armor: %d", is->_iAC); + } if (is->_iMaxDur != DUR_INDESTRUCTIBLE) - cat_str(sstr, cursor, "Armor: %d Dur: %d/%d", is->_iAC, is->_iDurability, is->_iMaxDur); + cat_str(sstr, cursor, " Dur: %d/%d", is->_iDurability, is->_iMaxDur); else - cat_str(sstr, cursor, "Armor: %d Indestructible", is->_iAC); + cat_str(sstr, cursor, " indestructible"); } if ((is->_iMinStr | is->_iMinMag | is->_iMinDex) != 0) { if (cursor != 0) @@ -600,12 +595,6 @@ static void S_StartSSell() for (i = 0; i < NUM_INV_GRID_ELEM; i++, pi++) if (SmithSellOk(pi)) AddStoreSell(pi, i); -#ifdef HELLFIRE - pi = p->_pSpdList; - for (i = 0; i < MAXBELTITEMS; i++, pi++) - if (SmithSellOk(pi)) - AddStoreSell(pi, -(i + 1)); -#endif gbWidePanel = true; gbRenderGold = true; @@ -770,10 +759,6 @@ static void S_StartWSell() for (i = 0; i < NUM_INV_GRID_ELEM; i++, pi++) if (WitchSellOk(pi)) AddStoreSell(pi, i); - pi = p->_pSpdList; - for (i = 0; i < MAXBELTITEMS; i++, pi++) - if (WitchSellOk(pi)) - AddStoreSell(pi, -(i + 1)); gbWidePanel = true; gbRenderGold = true; @@ -2355,7 +2340,7 @@ static void S_PriestEnter() switch (stextsel) { /*case STORE_PRIEST_GOSSIP: stextlhold = STORE_PRIEST_GOSSIP; - talker = TOWN_DRUNK; + talker = TOWN_PRIEST; stextshold = STORE_PRIEST; StartStore(STORE_GOSSIP); break;*/ From 46b007e48d88959997ff72e848e7011823f1e002 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 14 Dec 2023 16:31:43 +0100 Subject: [PATCH 045/596] draw the health-bar of the player's golem over the life-flask --- Source/control.cpp | 10 ++++++++++ Source/control.h | 1 + Source/scrollrt.cpp | 1 + 3 files changed, 12 insertions(+) diff --git a/Source/control.cpp b/Source/control.cpp index f2202a61176..191605474db 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -1591,6 +1591,7 @@ static void DrawHealthBar(int hp, int maxhp, int x, int y) if (y < 0) return; + static_assert(HEALTHBAR_HEIGHT < BORDER_BOTTOM, "DrawHealthBar might draw out of the buffer."); x -= HEALTHBAR_WIDTH / 2; if (x < 0) x = 0; @@ -2355,4 +2356,13 @@ void CheckTeamClick(bool shift) } } +void DrawGolemBar() +{ + MonsterStruct* mon = &monsters[mypnum]; + + if (mon->_mmode <= MM_INGAME_LAST) { + DrawHealthBar(mon->_mhitpoints, mon->_mmaxhp, LIFE_FLASK_X + LIFE_FLASK_WIDTH / 2 - SCREEN_X, PANEL_Y + PANEL_HEIGHT - 1 - HEALTHBAR_HEIGHT + 2 - SCREEN_Y); + } +} + DEVILUTION_END_NAMESPACE diff --git a/Source/control.h b/Source/control.h index 053bfca1496..00ff6060688 100644 --- a/Source/control.h +++ b/Source/control.h @@ -75,6 +75,7 @@ void DrawGoldSplit(int amount); void control_drop_gold(int vkey); void DrawTeamBook(); void CheckTeamClick(bool shift); +void DrawGolemBar(); /* data */ diff --git a/Source/scrollrt.cpp b/Source/scrollrt.cpp index 95c4391d777..73f5fa4ad4b 100644 --- a/Source/scrollrt.cpp +++ b/Source/scrollrt.cpp @@ -1477,6 +1477,7 @@ static void DrawView() } DrawLifeFlask(); DrawManaFlask(); + DrawGolemBar(); //if (gbRedrawFlags & (REDRAW_MANA_FLASK | REDRAW_SPELL_ICON)) { DrawSkillIcons(); //} From c1511d974ae3257a24cb8cbc57e851131ce3d22f Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 14 Dec 2023 16:42:41 +0100 Subject: [PATCH 046/596] rename MGOAL_ATTACK2 to MGOAL_ATTACK --- Source/monster.cpp | 12 ++++++------ enums.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 06e18d41ea6..c0d2cc91b97 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3214,7 +3214,7 @@ void MAI_Sneak(int mnum) if (EnemyInLine(mnum) && AddMissile(mx, my, fx, fy, md, MIS_FIREMAN, MST_MONSTER, mnum, 0) != -1) { mon->_mmode = MM_CHARGE; - mon->_mgoal = MGOAL_ATTACK2; + mon->_mgoal = MGOAL_ATTACK; //mon->_mgoalvar1 = 0; // FIREMAN_ACTION_PROGRESS } else { if (currEnemyInfo._meRealDist < 2) { @@ -3223,11 +3223,11 @@ void MAI_Sneak(int mnum) md = OPPOSITE(md); } if (!MonCallWalk(mnum, md)) { - mon->_mgoal = MGOAL_ATTACK2; + mon->_mgoal = MGOAL_ATTACK; MonStartFadein(mnum, mon->_mdir, false); } } - } else if (mon->_mgoal == MGOAL_ATTACK2) { + } else if (mon->_mgoal == MGOAL_ATTACK) { if (++mon->_mgoalvar1 > 3) { // FIREMAN_ACTION_PROGRESS mon->_mgoal = MGOAL_NORMAL; mon->_mgoalvar1 = 0; @@ -3239,7 +3239,7 @@ void MAI_Sneak(int mnum) } } else { assert(mon->_mgoal == MGOAL_RETREAT); - mon->_mgoal = MGOAL_ATTACK2; + mon->_mgoal = MGOAL_ATTACK; MonStartFadein(mnum, md, false); } }*/ @@ -3281,7 +3281,7 @@ void MAI_Fallen(int mnum) mon = &monsters[m - 1]; if (mon->_mAI.aiType == AI_FALLEN && !MON_RELAXED) { mon->_msquelch = SQUELCH_MAX; // prevent monster from getting in relaxed state - mon->_mgoal = MGOAL_ATTACK2; + mon->_mgoal = MGOAL_ATTACK; mon->_mgoalvar1 = amount; // FALLEN_ATTACK_AMOUNT } } @@ -3300,7 +3300,7 @@ void MAI_Fallen(int mnum) MonStartStand(mnum); } } else { - assert(mon->_mgoal == MGOAL_ATTACK2); + assert(mon->_mgoal == MGOAL_ATTACK); if (--mon->_mgoalvar1 != 0) { // FALLEN_ATTACK_AMOUNT MonEnemyInfo(mnum); if (currEnemyInfo._meRealDist < 2) { diff --git a/enums.h b/enums.h index e01f730f48d..ce8461c0c84 100644 --- a/enums.h +++ b/enums.h @@ -2449,7 +2449,7 @@ typedef enum _monster_goal { MGOAL_RETREAT, MGOAL_HEALING, MGOAL_MOVE, - MGOAL_ATTACK2, + MGOAL_ATTACK, MGOAL_TALKING, } _monster_goal; From e9b36407bf24b10c94ee386a6d804dce91851052 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 15 Dec 2023 16:33:41 +0100 Subject: [PATCH 047/596] validate IPL_CHARGES vs. SpellData.sStaffMax --- Source/debug.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Source/debug.cpp b/Source/debug.cpp index 20cbc38025f..71e4275425f 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -621,6 +621,14 @@ void ValidateData() app_fatal("PLParam too high for %d. prefix (power:%d, pparam2:%d)", i, pres->PLPower, pres->PLParam2); } } + if (pres->PLPower == IPL_CHARGES) { + for (int n = 0; n < NUM_SPELLS; n++) { + const SpellData& sd = spelldata[n]; + if (sd.sStaffLvl != SPELL_NA && sd.sStaffMax * pres->PLParam2 > UCHAR_MAX) { // required by (Un)PackPkItem + app_fatal("PLParam too high for %d. prefix (power:%d, pparam2:%d) to be used for staff with spell %d.", i, pres->PLPower, pres->PLParam2, n); + } + } + } } if (rnddrops > ITEM_RNDAFFIX_MAX || rnddrops > 0x7FFF) app_fatal("Too many prefix options: %d. Maximum is %d", rnddrops, ITEM_RNDAFFIX_MAX); From eb004b3fed8e71176a7985970e3964d32f006c8e Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 15 Dec 2023 16:35:40 +0100 Subject: [PATCH 048/596] allow randomized IPL_CHARGES and IPL_SETDUR --- Source/items.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/items.cpp b/Source/items.cpp index ef890c55e59..feadcf76c3f 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -1456,7 +1456,7 @@ static void SaveItemPower(int ii, int power, int param1, int param2, int minval, is->_iPLSkillLevels = r; break; case IPL_CHARGES: - is->_iCharges *= param1; + is->_iCharges *= r; is->_iMaxCharges = is->_iCharges; break; case IPL_FIREDAM: @@ -1580,8 +1580,8 @@ static void SaveItemPower(int ii, int power, int param1, int param2, int minval, is->_iMaxDam = param2; break; case IPL_SETDUR: - is->_iDurability = param1; - is->_iMaxDur = param1; + is->_iDurability = r; + is->_iMaxDur = r; break; case IPL_NOMINSTR: is->_iMinStr = 0; From 1ea86fd8b4ae680de2f50405791f1e85d881dfc4 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 15 Dec 2023 16:42:57 +0100 Subject: [PATCH 049/596] rebalance sStaffMin, sStaffMax and sStaffCost - reduce the cost of offensive spells (scrolls / recharge) - increase the available charges for offensive spells - increase the available charges for town portal and resurrect spells --- Source/items.cpp | 2 +- Source/spelldat.cpp | 58 ++++++++++++++++++++++----------------------- Source/stores.cpp | 2 +- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/Source/items.cpp b/Source/items.cpp index feadcf76c3f..a385af5366c 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -1332,7 +1332,7 @@ static void GetStaffSpell(int ii, unsigned lvl) is->_iMaxCharges = is->_iCharges; is->_iMinMag = sd->sMinInt; - v = is->_iCharges * sd->sStaffCost / 5; + v = is->_iCharges * sd->sStaffCost; is->_ivalue += v; is->_iIvalue += v; } diff --git a/Source/spelldat.cpp b/Source/spelldat.cpp index 221052ec394..99393b2fcbb 100644 --- a/Source/spelldat.cpp +++ b/Source/spelldat.cpp @@ -54,48 +54,48 @@ const SpellData spelldata[NUM_SPELLS] = { /*SPL_MULTI_SHOT*/ { 8, STYPE_NONE, 9, "Multi Shot", 16, SPELL_NA, SPELL_NA, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON | SFLAG_RANGED, 0, 0, MIS_MLARROW, 0, 8, 0, 0, 20000, 0, ALIGN64 }, /*SPL_CHARGE*/ { 2, STYPE_MAGIC, ICN_CHR, "Charge", 10, SPELL_NA, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 0, 0, MIS_CHARGE, 0, 2, 0, 0, 12000, 0, ALIGN64 }, /*SPL_RAGE*/ { 7, STYPE_MAGIC, 23, "Rage", 2, SPELL_NA, 4, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_RAGE, 0, IS_CAST6, MIS_RAGE, 2, 2, 0, 0, 1500, 100, ALIGN64 }, -/*SPL_FIREBOLT*/ { 6, STYPE_FIRE, 1, "Firebolt", 1, 2, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 15, IS_CAST2, MIS_FIREBOLT, 1, 3, 40, 80, 1000, 50, ALIGN64 }, -/*SPL_CBOLT*/ { 6, STYPE_LIGHTNING, 39, "Charged Bolt", 1, 2, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 25, IS_CAST2, MIS_CBOLTC, 1, 4, 40, 80, 1000, 50, ALIGN64 }, -/*SPL_HBOLT*/ { 7, STYPE_MAGIC, 42, "Acidbolt", 1, 2, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 20, IS_CAST2, MIS_HBOLT, 1, 4, 40, 80, 1000, 50, ALIGN64 }, -/*SPL_LIGHTNING*/ { 15, STYPE_LIGHTNING, 3, "Lightning", 4, 6, 4, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 20, IS_CAST4, MIS_LIGHTNINGC, 1, 8, 20, 60, 3000, 150, ALIGN64 }, -/*SPL_FLASH*/ { 30, STYPE_LIGHTNING, 4, "Flash", 5, 8, 6, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 33, IS_CAST4, MIS_FLASH, 3, 16, 20, 40, 7500, 500, ALIGN64 }, -/*SPL_FIREWALL*/ { 28, STYPE_FIRE, 6, "Fire Wall", 3, 4, 4, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 27, IS_CAST2, MIS_FIREWALLC, 3, 16, 8, 16, 6000, 400, ALIGN64 }, -/*SPL_FIREBALL*/ { 20, STYPE_FIRE, 12, "Fireball", 8, 14, 8, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 48, IS_CAST2, MIS_FIREBALL, 1, 14, 40, 80, 8000, 300, ALIGN64 }, -/*SPL_METEOR*/ { 54, STYPE_MAGIC, 31, "Meteor", 24, 32, 16, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 42, IS_CAST2, MIS_METEOR, 2, 30, 20, 60, 15000, 500, ALIGN64 }, -/*SPL_BLOODBOIL*/ { 40, STYPE_MAGIC, 23, "Bloodboil", 28, 36, 20, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 50, IS_CAST2, MIS_BLOODBOILC, 1, 30, 20, 60, 16000, 700, ALIGN64 }, -/*SPL_CHAIN*/ { 30, STYPE_LIGHTNING, 16, "Chain Lightning", 8, 14, 10, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 54, IS_CAST2, MIS_CHAIN, 2, 18, 20, 60, 11000, 750, ALIGN64 }, -/*SPL_WAVE*/ { 35, STYPE_FIRE, 14, "Fire Wave", 9, 16, 10, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 54, IS_CAST2, MIS_FIREWAVEC, 4, 20, 20, 40, 10000, 650, ALIGN64 }, -/*SPL_NOVA*/ { 60, STYPE_MAGIC, 11, "Nova", 14, 20, 14, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 87, IS_CAST4, MIS_LIGHTNOVAC, 5, 35, 16, 32, 21000, 1300, ALIGN64 }, -/*SPL_INFERNO*/ { 11, STYPE_FIRE, 15, "Inferno", 3, 4, 1, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 20, IS_CAST2, MIS_INFERNOC, 1, 6, 20, 40, 2000, 100, ALIGN64 }, -/*SPL_ELEMENTAL*/ { 35, STYPE_FIRE, 38, "Elemental", 8, 12, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 68, IS_CAST2, MIS_ELEMENTAL, 4, 20, 20, 60, 10500, 700, ALIGN64 }, -/*SPL_FLARE*/ { 25, STYPE_MAGIC, 36, "Blood Star", 14, 26, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 70, IS_CAST2, MIS_FLARE, 4, 14, 20, 60, 27500, 1800, ALIGN64 }, -/*SPL_POISON*/ { 22, STYPE_MAGIC, 25, "Poison", 18, 28, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 70, IS_CAST2, MIS_POISON, 1, 18, 20, 60, 24500, 1500, ALIGN64 }, -/*SPL_WIND*/ { 24, STYPE_MAGIC, 22, "Wind", 10, 18, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 44, IS_CAST2, MIS_WIND, 2, 12, 40, 80, 12500, 500, ALIGN64 }, -/*SPL_SHROUD*/ { 46, STYPE_MAGIC, 19, "Shroud", 20, 28, 18, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 36, IS_CAST2, MIS_SHROUD, 1, 18, 20, 60, 20500, 1500, ALIGN64 }, -/*SPL_GUARDIAN*/ { 50, STYPE_FIRE, 18, "Guardian", 9, 16, 12, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 61, IS_CAST2, MIS_GUARDIAN, 4, 30, 16, 32, 14000, 950, ALIGN64 }, -/*SPL_GOLEM*/ { 100, STYPE_FIRE, 21, "Golem", 11, 18, 10, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 81, IS_CAST2, MIS_GOLEM, 10, 60, 16, 32, 18000, 1100, ALIGN64 }, -/*SPL_STONE*/ { 60, STYPE_MAGIC, 8, "Stone Curse", 6, 10, 6, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 51, IS_CAST2, MIS_STONE, 4, 40, 8, 16, 12000, 800, ALIGN64 }, +/*SPL_FIREBOLT*/ { 6, STYPE_FIRE, 1, "Firebolt", 1, 2, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 15, IS_CAST2, MIS_FIREBOLT, 1, 3, 40, 80, 1000, 20, ALIGN64 }, +/*SPL_CBOLT*/ { 6, STYPE_LIGHTNING, 39, "Charged Bolt", 1, 2, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 25, IS_CAST2, MIS_CBOLTC, 1, 4, 40, 80, 1000, 20, ALIGN64 }, +/*SPL_HBOLT*/ { 7, STYPE_MAGIC, 42, "Acidbolt", 1, 2, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 20, IS_CAST2, MIS_HBOLT, 1, 4, 40, 80, 1000, 20, ALIGN64 }, +/*SPL_LIGHTNING*/ { 15, STYPE_LIGHTNING, 3, "Lightning", 4, 6, 4, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 20, IS_CAST4, MIS_LIGHTNINGC, 1, 8, 20, 60, 3000, 30, ALIGN64 }, +/*SPL_FLASH*/ { 30, STYPE_LIGHTNING, 4, "Flash", 5, 8, 6, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 33, IS_CAST4, MIS_FLASH, 3, 16, 20, 40, 7500, 40, ALIGN64 }, +/*SPL_FIREWALL*/ { 28, STYPE_FIRE, 6, "Fire Wall", 3, 4, 4, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 27, IS_CAST2, MIS_FIREWALLC, 3, 16, 8, 16, 6000, 80, ALIGN64 }, +/*SPL_FIREBALL*/ { 20, STYPE_FIRE, 12, "Fireball", 8, 14, 8, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 48, IS_CAST2, MIS_FIREBALL, 1, 14, 40, 80, 8000, 30, ALIGN64 }, +/*SPL_METEOR*/ { 54, STYPE_MAGIC, 31, "Meteor", 24, 32, 16, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 42, IS_CAST2, MIS_METEOR, 2, 30, 20, 60, 15000, 50, ALIGN64 }, +/*SPL_BLOODBOIL*/ { 40, STYPE_MAGIC, 23, "Bloodboil", 28, 36, 20, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 50, IS_CAST2, MIS_BLOODBOILC, 1, 30, 20, 60, 16000, 40, ALIGN64 }, +/*SPL_CHAIN*/ { 30, STYPE_LIGHTNING, 16, "Chain Lightning", 8, 14, 10, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 54, IS_CAST2, MIS_CHAIN, 2, 18, 20, 60, 11000, 45, ALIGN64 }, +/*SPL_WAVE*/ { 35, STYPE_FIRE, 14, "Fire Wave", 9, 16, 10, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 54, IS_CAST2, MIS_FIREWAVEC, 4, 20, 20, 60, 10000, 45, ALIGN64 }, +/*SPL_NOVA*/ { 60, STYPE_MAGIC, 11, "Nova", 14, 20, 14, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 87, IS_CAST4, MIS_LIGHTNOVAC, 5, 35, 16, 32, 21000, 50, ALIGN64 }, +/*SPL_INFERNO*/ { 11, STYPE_FIRE, 15, "Inferno", 3, 4, 1, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 20, IS_CAST2, MIS_INFERNOC, 1, 6, 40, 80, 2000, 20, ALIGN64 }, +/*SPL_ELEMENTAL*/ { 35, STYPE_FIRE, 38, "Elemental", 8, 12, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 68, IS_CAST2, MIS_ELEMENTAL, 4, 20, 20, 60, 10500, 40, ALIGN64 }, +/*SPL_FLARE*/ { 25, STYPE_MAGIC, 36, "Blood Star", 14, 26, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 70, IS_CAST2, MIS_FLARE, 4, 14, 30, 80, 27500, 30, ALIGN64 }, +/*SPL_POISON*/ { 22, STYPE_MAGIC, 25, "Poison", 18, 28, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 70, IS_CAST2, MIS_POISON, 1, 18, 30, 70, 24500, 30, ALIGN64 }, +/*SPL_WIND*/ { 24, STYPE_MAGIC, 22, "Wind", 10, 18, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 44, IS_CAST2, MIS_WIND, 2, 12, 40, 80, 12500, 35, ALIGN64 }, +/*SPL_SHROUD*/ { 46, STYPE_MAGIC, 19, "Shroud", 20, 28, 18, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 36, IS_CAST2, MIS_SHROUD, 1, 18, 20, 60, 20500, 80, ALIGN64 }, +/*SPL_GUARDIAN*/ { 50, STYPE_FIRE, 18, "Guardian", 9, 16, 12, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 61, IS_CAST2, MIS_GUARDIAN, 4, 30, 16, 32, 14000, 90, ALIGN64 }, +/*SPL_GOLEM*/ { 100, STYPE_FIRE, 21, "Golem", 11, 18, 10, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 81, IS_CAST2, MIS_GOLEM, 10, 60, 16, 32, 18000, 200, ALIGN64 }, +/*SPL_STONE*/ { 60, STYPE_MAGIC, 8, "Stone Curse", 6, 10, 6, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 51, IS_CAST2, MIS_STONE, 4, 40, 8, 16, 12000, 160, ALIGN64 }, /*SPL_INFRA*/ { 0, STYPE_MAGIC, 9, "Infravision", SPELL_NA, SPELL_NA, 8, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 43, IS_CAST8, MIS_INFRA, 0, 0, 0, 0, 0, 600, ALIGN64 }, -/*SPL_MANASHIELD*/ { 33, STYPE_MAGIC, 13, "Mana Shield", 6, 10, 8, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_ANY, 25, IS_CAST2, MIS_MANASHIELD, 0, 33, 4, 10, 16000, 1200, ALIGN64 }, -/*SPL_ATTRACT*/ { 4, STYPE_LIGHTNING, 30, "Attract", 2, 4, 4, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 20, IS_CAST4, MIS_ATTRACT, 0, 4, 40, 80, 2000, 200, ALIGN64 }, +/*SPL_MANASHIELD*/ { 33, STYPE_MAGIC, 13, "Mana Shield", 6, 10, 8, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_ANY, 25, IS_CAST2, MIS_MANASHIELD, 0, 33, 4, 10, 16000, 120, ALIGN64 }, +/*SPL_ATTRACT*/ { 4, STYPE_LIGHTNING, 30, "Attract", 2, 4, 4, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 20, IS_CAST4, MIS_ATTRACT, 0, 4, 40, 80, 2000, 30, ALIGN64 }, /*SPL_TELEKINESIS*/ { 15, STYPE_MAGIC, 40, "Telekinesis", 2, 4, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_TELEKINESIS, SFLAG_DUNGEON, 33, IS_CAST2, MIS_TELEKINESIS, 2, 8, 20, 40, 2500, 200, ALIGN64 }, -/*SPL_TELEPORT*/ { 35, STYPE_MAGIC, 24, "Teleport", 14, 24, 14, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_ANY, 105, IS_CAST6, MIS_TELEPORT, 5, 15, 16, 32, 20000, 1250, ALIGN64 }, -/*SPL_RNDTELEPORT*/ { 11, STYPE_MAGIC, 28, "Phasing", 7, 12, 6, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 39, IS_CAST2, MIS_RNDTELEPORT, 1, 4, 40, 80, 3500, 200, ALIGN64 }, -/*SPL_TOWN*/ { 35, STYPE_MAGIC, 7, "Town Portal", 3, 6, 4, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 20, IS_CAST6, MIS_TOWN, 3, 18, 8, 12, 3000, 200, ALIGN64 }, +/*SPL_TELEPORT*/ { 35, STYPE_MAGIC, 24, "Teleport", 14, 24, 14, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_ANY, 105, IS_CAST6, MIS_TELEPORT, 5, 15, 16, 32, 20000, 250, ALIGN64 }, +/*SPL_RNDTELEPORT*/ { 11, STYPE_MAGIC, 28, "Phasing", 7, 12, 6, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 39, IS_CAST2, MIS_RNDTELEPORT, 1, 4, 40, 80, 3500, 100, ALIGN64 }, +/*SPL_TOWN*/ { 35, STYPE_MAGIC, 7, "Town Portal", 3, 6, 4, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 20, IS_CAST6, MIS_TOWN, 3, 18, 20, 80, 3000, 200, ALIGN64 }, /*SPL_HEAL*/ { 5, STYPE_MAGIC, 2, "Healing", 1, 2, 1, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_ANY, 17, IS_CAST8, MIS_HEAL, 6, 1, 20, 40, 1000, 50, ALIGN64 }, /*SPL_HEALOTHER*/ { 5, STYPE_MAGIC, 10, "Heal Other", 1, 2, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_HEALOTHER, SFLAG_ANY, 17, IS_CAST8, MIS_HEALOTHER, 6, 1, 20, 40, 1000, 50, ALIGN64 }, -/*SPL_RESURRECT*/ { 0, STYPE_MAGIC, 41, "Resurrect", SPELL_NA, 10, 1, SDFLAG_TARGETED, CURSOR_RESURRECT, CURSOR_RESURRECT, SFLAG_ANY, 20, IS_CAST8, MIS_RESURRECT, 0, 0, 4, 10, 4000, 250, ALIGN64 }, +/*SPL_RESURRECT*/ { 0, STYPE_MAGIC, 41, "Resurrect", SPELL_NA, 10, 1, SDFLAG_TARGETED, CURSOR_RESURRECT, CURSOR_RESURRECT, SFLAG_ANY, 20, IS_CAST8, MIS_RESURRECT, 0, 0, 16, 32, 4000, 250, ALIGN64 }, /*SPL_IDENTIFY*/ { 0, STYPE_MAGIC, 5, "Identify", SPELL_NA, SPELL_NA, 1, 0, CURSOR_IDENTIFY, CURSOR_IDENTIFY, SFLAG_ANY, 20, IS_CAST6, MIS_OPITEM, 0, 0, 0, 0, 0, 100, ALIGN64 }, /*SPL_OIL*/ { 0, STYPE_MAGIC, 5, NULL, SPELL_NA, SPELL_NA, SPELL_NA, 0, CURSOR_NONE, CURSOR_OIL, SFLAG_ANY, 0, IS_CAST6, MIS_OPITEM, 0, 0, 0, 0, 0, 0, ALIGN64 }, /*SPL_REPAIR*/ { 0, STYPE_MAGIC, 26, "Item Repair", SPELL_NA, SPELL_NA, SPELL_NA, 0, CURSOR_NONE, CURSOR_REPAIR, SFLAG_ANY, 0, SFX_SILENCE, MIS_REPAIR, 0, 0, 0, 0, 0, 0, ALIGN64 }, /*SPL_RECHARGE*/ { 0, STYPE_MAGIC, 29, "Staff Recharge", SPELL_NA, SPELL_NA, SPELL_NA, 0, CURSOR_NONE, CURSOR_RECHARGE, SFLAG_ANY, 0, IS_CAST6, MIS_OPITEM, 0, 0, 0, 0, 0, 0, ALIGN64 }, -/*SPL_DISARM*/ { 0, STYPE_MAGIC, 37, "Trap Disarm", SPELL_NA, SPELL_NA, 1, SDFLAG_TARGETED, CURSOR_DISARM, CURSOR_DISARM, SFLAG_DUNGEON, 20, IS_CAST6, MIS_DISARM, 0, 0, 0, 0, 0, 75, ALIGN64 }, +/*SPL_DISARM*/ { 0, STYPE_MAGIC, 37, "Trap Disarm", SPELL_NA, SPELL_NA, 1, SDFLAG_TARGETED, CURSOR_DISARM, CURSOR_DISARM, SFLAG_DUNGEON, 20, IS_CAST6, MIS_DISARM, 0, 0, 0, 0, 0, 150, ALIGN64 }, #ifdef HELLFIRE /*SPL_BUCKLE*/ { 0, STYPE_MAGIC, 26, "Shield Buckle", SPELL_NA, SPELL_NA, SPELL_NA, 0, CURSOR_NONE, CURSOR_IDENTIFY, SFLAG_ANY, 0, IS_CAST6, MIS_OPITEM, 0, 0, 0, 0, 0, 0, ALIGN64 }, /*SPL_WHITTLE*/ { 0, STYPE_MAGIC, 29, "Staff Whittle", SPELL_NA, SPELL_NA, SPELL_NA, 0, CURSOR_NONE, CURSOR_RECHARGE, SFLAG_ANY, 0, IS_CAST6, MIS_OPITEM, 0, 0, 0, 0, 0, 0, ALIGN64 }, /*SPL_LIGHTWALL*/// { 28, STYPE_LIGHTNING, 46, "Lightning Wall", 3, 4, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 27, IS_CAST4, MIS_LIGHTWALLC, 3, 16, 8, 16, 6000, 400, ALIGN64 }, /*SPL_IMMOLAT */// { 60, STYPE_FIRE, 47, "Immolation", 14, 20, SPELL_NA, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 87, IS_CAST2, MIS_FIRENOVAC, 5, 35, 16, 32, 21000, 1300, ALIGN64 }, -/*SPL_FIRERING*/ { 28, STYPE_FIRE, 49, "Ring of Fire", 5, 10, SPELL_NA, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 27, IS_CAST2, MIS_FIRERING, 3, 16, 8, 16, 6000, 400, ALIGN64 }, +/*SPL_FIRERING*/ { 28, STYPE_FIRE, 49, "Ring of Fire", 5, 10, SPELL_NA, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 27, IS_CAST2, MIS_FIRERING, 3, 16, 8, 20, 6000, 80, ALIGN64 }, /*SPL_RUNEFIRE*/ { 0, STYPE_FIRE, 15, "Fire", SPELL_NA, SPELL_NA, 1, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_TELEPORT, SFLAG_DUNGEON, 0, IS_CAST8, MIS_RUNEFIRE, 0, 0, 0, 0, 0, 100, ALIGN64 }, /*SPL_RUNELIGHT*/ { 0, STYPE_LIGHTNING, 3, "Lightning", SPELL_NA, SPELL_NA, 3, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_TELEPORT, SFLAG_DUNGEON, 13, IS_CAST8, MIS_RUNELIGHT, 0, 0, 0, 0, 0, 200, ALIGN64 }, /*SPL_RUNENOVA*/ { 0, STYPE_LIGHTNING, 11, "Nova", SPELL_NA, SPELL_NA, 7, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_TELEPORT, SFLAG_DUNGEON, 42, IS_CAST8, MIS_RUNENOVA, 0, 0, 0, 0, 0, 400, ALIGN64 }, diff --git a/Source/stores.cpp b/Source/stores.cpp index c14e0ed98f9..ecce51fe890 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -786,7 +786,7 @@ static void AddStoreHoldRecharge(const ItemStruct* is, int i) itm = &storehold[storenumh]; copy_pod(*itm, *is); itm->_ivalue += spelldata[itm->_iSpell].sStaffCost; - itm->_ivalue = itm->_ivalue * (itm->_iMaxCharges - itm->_iCharges) / (itm->_iMaxCharges * 2); + itm->_ivalue = itm->_ivalue * (itm->_iMaxCharges - itm->_iCharges) / itm->_iMaxCharges; itm->_iIvalue = itm->_ivalue; storehidx[storenumh] = i; storenumh++; From 6491793a610029df737651a02f6dbd6fe695d775 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 15 Dec 2023 16:44:39 +0100 Subject: [PATCH 050/596] adjust the colors of the health-bars --- Source/control.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/control.cpp b/Source/control.cpp index 191605474db..efe982d0f6e 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -1601,7 +1601,7 @@ static void DrawHealthBar(int hp, int maxhp, int x, int y) // draw gray border dst = &gpBuffer[SCREENXY(x, y)]; for (int i = 0; i < HEALTHBAR_HEIGHT; i++, dst += BUFFER_WIDTH) - memset(dst, PAL16_GRAY + 5, HEALTHBAR_WIDTH); + memset(dst, PAL16_YELLOW + 8, HEALTHBAR_WIDTH); // draw the bar //width = (HEALTHBAR_WIDTH - 2) * hp / maxhp; @@ -1611,7 +1611,7 @@ static void DrawHealthBar(int hp, int maxhp, int x, int y) } dst = &gpBuffer[SCREENXY(x + 1, y + 1)]; for (int i = 0; i < HEALTHBAR_HEIGHT - 2; i++, dst += BUFFER_WIDTH) - memset(dst, PAL16_RED + 9, w); + memset(dst, PAL16_RED + 11, w); } static void DrawTrigInfo() From 08577256733f0ffc8ec27173a6945b5563398a0c Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 16 Dec 2023 12:48:46 +0100 Subject: [PATCH 051/596] bugfix for vanilla (minions vs displacement) - prevent AI-freeze after displacement (telekinesis, knockback, bat-teleport) of minions --- Source/monster.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index c0d2cc91b97..f9e0ed4846d 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -2726,10 +2726,10 @@ static void GroupUnity(int mnum) if (mon->_mleader != MON_NO_LEADER) { leader = &monsters[mon->_mleader]; clear = LineClear(mon->_mx, mon->_my, leader->_mfutx, leader->_mfuty); - if (clear) { - if (mon->_mleaderflag == MLEADER_AWAY + if (clear && abs(mon->_mx - leader->_mfutx) <= MON_PACK_DISTANCE && abs(mon->_my - leader->_mfuty) <= MON_PACK_DISTANCE) { + if (mon->_mleaderflag == MLEADER_AWAY) { leader->_mpacksize++; mon->_mleaderflag = MLEADER_PRESENT; } From 29b9207f7cefbc285041c329a089a77452f4ac1f Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 16 Dec 2023 12:51:15 +0100 Subject: [PATCH 052/596] use define instead of constants in MonDirOK --- Source/monster.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index f9e0ed4846d..02e73f087f4 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -2773,21 +2773,21 @@ static bool MonDirOK(int mnum, int mdir) fx = x + offset_x[mdir]; fy = y + offset_y[mdir]; - static_assert(DBORDERX >= 3, "DirOK expects a large enough border I."); - static_assert(DBORDERY >= 3, "DirOK expects a large enough border II."); + static_assert(DBORDERX >= MON_PACK_DISTANCE, "DirOK expects a large enough border I."); + static_assert(DBORDERY >= MON_PACK_DISTANCE, "DirOK expects a large enough border II."); assert(IN_DUNGEON_AREA(fx, fy)); if (!PosOkMonst(mnum, fx, fy)) return false; if (monsters[mnum]._mleaderflag == MLEADER_PRESENT) { - return abs(fx - monsters[monsters[mnum]._mleader]._mfutx) < 4 - && abs(fy - monsters[monsters[mnum]._mleader]._mfuty) < 4; + return abs(fx - monsters[monsters[mnum]._mleader]._mfutx) <= MON_PACK_DISTANCE + && abs(fy - monsters[monsters[mnum]._mleader]._mfuty) <= MON_PACK_DISTANCE; } if (monsters[mnum]._mpacksize == 0) return true; mcount = 0; - for (x = fx - 3; x <= fx + 3; x++) { - for (y = fy - 3; y <= fy + 3; y++) { + for (x = fx - MON_PACK_DISTANCE; x <= fx + MON_PACK_DISTANCE; x++) { + for (y = fy - MON_PACK_DISTANCE; y <= fy + MON_PACK_DISTANCE; y++) { assert(IN_DUNGEON_AREA(x, y)); ma = dMonster[x][y]; if (ma == 0) From e9b62b511f6ee0710b0ee603599d1c089cabe4a3 Mon Sep 17 00:00:00 2001 From: obligaron Date: Sat, 16 Dec 2023 20:54:02 +0100 Subject: [PATCH 053/596] Bump libzt --- 3rdParty/libzt/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/3rdParty/libzt/CMakeLists.txt b/3rdParty/libzt/CMakeLists.txt index 1c4b99fdf0e..258da55ce4c 100644 --- a/3rdParty/libzt/CMakeLists.txt +++ b/3rdParty/libzt/CMakeLists.txt @@ -9,9 +9,9 @@ set(OMIT_JSON_SUPPORT TRUE) include(FetchContent) FetchContent_Declare(libzt #GIT_REPOSITORY https://github.com/diasurgical/libzt.git - #GIT_TAG 47e38259e9c99ba2d8e7241515fa1b56cb538c8c) + #GIT_TAG db7b642a4ce9f0f5e0ba7f293bd7ffa7897e4831) GIT_REPOSITORY https://github.com/pionere/libzt.git - GIT_TAG 08a848ae3363984edf27667222bc410ad2144f57) + GIT_TAG b738557b538fc6948316c69312ced99d0ef495d4) FetchContent_MakeAvailableExcludeFromAll(libzt) #if(NOT ANDROID) From 6c620eabf59f506e88e78cd22496c3edcefefee5 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 17 Dec 2023 11:41:20 +0100 Subject: [PATCH 054/596] bugfix for 'adjustments to directional hits' - fix knockback direction --- Source/player.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/player.cpp b/Source/player.cpp index 56ca0dfbb1c..8b2fb63fd9c 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -1645,6 +1645,7 @@ static void PlrGetKnockback(int pnum, int dir) if (plr._pmode != PM_GOTHIT) PlrStartGetHit(pnum, dir); + dir = OPPOSITE(dir); oldx = plr._px; oldy = plr._py; if (PathWalkable(oldx, oldy, dir2pdir[dir])) { From 550d22901399a059f960e7c266dc75f0d1e09d63 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 17 Dec 2023 11:47:02 +0100 Subject: [PATCH 055/596] simplify PlrStartAnyHit (and PlrGetKnockback) --- Source/player.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/Source/player.cpp b/Source/player.cpp index 8b2fb63fd9c..8ab10bfa6b9 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -1638,9 +1638,9 @@ static void PlrStartGetHit(int pnum, int dir) static void PlrGetKnockback(int pnum, int dir) { int oldx, oldy, newx, newy; - - if (plr._pmode == PM_DEATH || plr._pmode == PM_DYING) - return; + // assert(plr._pHitPoints >= (1 << 6)); + // if (plr._pmode == PM_DEATH || plr._pmode == PM_DYING) + // return; if (plr._pmode != PM_GOTHIT) PlrStartGetHit(pnum, dir); @@ -1677,22 +1677,20 @@ void PlrStartAnyHit(int pnum, int mpnum, int dam, unsigned hitflags, int sx, int hitflags &= (ISPL_FAKE_FORCE_STUN | ISPL_KNOCKBACK); if (hitflags == 0) return; - dam = 0; + // dam = 0; } dir = GetDirection(plr._px, plr._py, sx, sy); PlaySfxLoc(sgSFXSets[SFXS_PLR_69][plr._pClass], plr._px, plr._py, 2); - if (hitflags & ISPL_KNOCKBACK) { - PlrGetKnockback(pnum, dir); - } - static_assert(MAX_PLRS <= MAX_MINIONS, "PlrStartAnyHit uses a single int to store player and monster sources."); if (!(plr._pIFlags & ISPL_NO_BLEED) && (hitflags & ISPL_FAKE_CAN_BLEED) && ((hitflags & ISPL_BLEED) ? random_(47, 64) == 0 : random_(48, 128) == 0)) AddMissile(0, 0, 0, 0, 0, MIS_BLEED, mpnum < MAX_PLRS ? (mpnum < 0 ? MST_OBJECT : MST_PLAYER) : MST_MONSTER, mpnum, pnum); // TODO: prevent golems from acting like a player? - if ((hitflags & ISPL_FAKE_FORCE_STUN) || (dam << ((hitflags & ISPL_STUN) ? 3 : 2)) >= plr._pMaxHP) { + if (hitflags & ISPL_KNOCKBACK) { + PlrGetKnockback(pnum, dir); + } else if ((hitflags & ISPL_FAKE_FORCE_STUN) || (dam << ((hitflags & ISPL_STUN) ? 3 : 2)) >= plr._pMaxHP) { PlrStartGetHit(pnum, dir); } } From 59b741c896681a97c7fec8ec106aff1b19d7fa5c Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 18 Dec 2023 08:56:15 +0100 Subject: [PATCH 056/596] move MonUpdateLeader up in monster.cpp --- Source/monster.cpp | 62 +++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 02e73f087f4..9cd56550684 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1671,6 +1671,37 @@ static void MonStartSpAttack(int mnum) AssertFixMonLocation(mnum); } +/* + * Disconnect monster from its pack/leader. + */ +void MonUpdateLeader(int mnum) +{ + MonsterStruct* mon; + int i; + + if ((unsigned)mnum >= MAXMONSTERS) { + dev_fatal("MonUpdateLeader: Invalid monster %d", mnum); + } + if (monsters[mnum]._mleaderflag == MLEADER_NONE) + return; + if (monsters[mnum]._mleaderflag == MLEADER_SELF) { + for (i = 0; i < MAXMONSTERS; i++) { + mon = &monsters[i]; + if (/*mon->_mleaderflag != MLEADER_NONE && */mon->_mleader == mnum) { + mon->_mleader = MON_NO_LEADER; + mon->_mleaderflag = MLEADER_NONE; + } + } + } else if (monsters[mnum]._mleaderflag == MLEADER_PRESENT) { + monsters[monsters[mnum]._mleader]._mpacksize--; + } + monsters[mnum]._mleader = MON_NO_LEADER; + monsters[mnum]._mleaderflag = MLEADER_NONE; + monsters[mnum]._mpacksize = 0; + // assert(monsters[mnum]._mvid == NO_VISION); + monsters[mnum]._mvid = NO_VISION; +} + void RemoveMonFromMap(int mnum) { MonsterStruct* mon; @@ -2502,37 +2533,6 @@ static bool MonDoGotHit(int mnum) return false; } -/* - * Disconnect monster from its pack/leader. - */ -void MonUpdateLeader(int mnum) -{ - MonsterStruct* mon; - int i; - - if ((unsigned)mnum >= MAXMONSTERS) { - dev_fatal("MonUpdateLeader: Invalid monster %d", mnum); - } - if (monsters[mnum]._mleaderflag == MLEADER_NONE) - return; - if (monsters[mnum]._mleaderflag == MLEADER_SELF) { - for (i = 0; i < MAXMONSTERS; i++) { - mon = &monsters[i]; - if (/*mon->_mleaderflag != MLEADER_NONE && */mon->_mleader == mnum) { - mon->_mleader = MON_NO_LEADER; - mon->_mleaderflag = MLEADER_NONE; - } - } - } else if (monsters[mnum]._mleaderflag == MLEADER_PRESENT) { - monsters[monsters[mnum]._mleader]._mpacksize--; - } - monsters[mnum]._mleader = MON_NO_LEADER; - monsters[mnum]._mleaderflag = MLEADER_NONE; - monsters[mnum]._mpacksize = 0; - // assert(monsters[mnum]._mvid == NO_VISION); - monsters[mnum]._mvid = NO_VISION; -} - void DoEnding() { // music_stop(); -- no need, music is already stopped at this point From 00273ccbe7d21d1c8a86cc62362b2bec09d0574d Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 18 Dec 2023 09:00:33 +0100 Subject: [PATCH 057/596] bugfix for vanilla (minions vs displacement) II. - disconnect charging snakes and teleporting bats from their pack --- Source/monster.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/monster.cpp b/Source/monster.cpp index 9cd56550684..70073b0879b 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1782,6 +1782,7 @@ static void MonTeleport(int mnum, int tx, int ty) mon->_mx = x; mon->_my = y; mon->_mdir = OPPOSITE(rx); + MonUpdateLeader(mnum); return; } } @@ -2974,6 +2975,7 @@ void MAI_Snake(int mnum) if (dist == 2 && LineClearMon(mnum, mon->_mx, mon->_my, mon->_menemyx, mon->_menemyy) && mon->_mVar1 != MM_CHARGE) { if (AddMissile(mon->_mx, mon->_my, mon->_menemyx, mon->_menemyy, mon->_mdir, MIS_RHINO, MST_MONSTER, mnum, 0) != -1) { PlayMonSFX(mnum, MS_ATTACK); + MonUpdateLeader(mnum); } } else if (mon->_mVar1 == MM_DELAY || random_(106, 100) >= 35 - 2 * mon->_mAI.aiInt) { // calculate the desired direction From 012a6f3b54c5570ade61064387129f92f4ca2e3c Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 18 Dec 2023 09:11:49 +0100 Subject: [PATCH 058/596] bugfix for vanilla (leader vs moving minion) - do not block the leader while one of its minion is moving --- Source/monster.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 70073b0879b..34110773712 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -2796,8 +2796,8 @@ static bool MonDirOK(int mnum, int mdir) ma = ma >= 0 ? ma - 1 : -(ma + 1); if (monsters[ma]._mleaderflag == MLEADER_PRESENT && monsters[ma]._mleader == mnum - && monsters[ma]._mfutx == x - && monsters[ma]._mfuty == y) { + && abs(fx - monsters[ma]._mfutx) <= MON_PACK_DISTANCE + && abs(fy - monsters[ma]._mfuty) <= MON_PACK_DISTANCE) { mcount++; } } From 15d0f68b9ec025b62107031af2499e5ef4908872 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 18 Dec 2023 12:58:14 +0100 Subject: [PATCH 059/596] improve placement of groups - ignore dTransVal - preserve the step only if it was blocked by a monster --- Source/monster.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 34110773712..6f550e56f20 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -801,7 +801,6 @@ static void PlaceGroup(int mtidx, int num, int leaderf, int leader) } while (!MonstPlace(x1, y1)); } - assert(dTransVal[x1][y1] != 0); static_assert(DBORDERX >= 1, "PlaceGroup expects a large enough border I."); static_assert(DBORDERY >= 1, "PlaceGroup expects a large enough border II."); xp = x1; yp = y1; @@ -810,14 +809,20 @@ static void PlaceGroup(int mtidx, int num, int leaderf, int leader) x2 = xp + offset_x[offset]; y2 = yp + offset_y[offset]; assert((unsigned)x2 < MAXDUNX); - assert((unsigned)y2 < MAXDUNX); - if (dTransVal[x2][y2] != dTransVal[x1][y1] - || ((leaderf & UMF_LEADER) && ((abs(x2 - x1) > MON_PACK_DISTANCE) || (abs(y2 - y1) > MON_PACK_DISTANCE)))) { + assert((unsigned)y2 < MAXDUNY); + if ((leaderf & UMF_LEADER) && ((abs(x2 - x1) > MON_PACK_DISTANCE) || (abs(y2 - y1) > MON_PACK_DISTANCE))) { + continue; + } + if (!MonstPlace(x2, y2)) { + if (dMonster[x2][y2] != 0) { + xp = x2; + yp = y2; + } continue; } xp = x2; yp = y2; - if ((!MonstPlace(xp, yp)) || random_(0, 2) != 0) + if (random_(0, 2) != 0) continue; // assert(nummonsters < MAXMONSTERS); mnum = PlaceMonster(mtidx, xp, yp); From 5f76f8974734cfe71eaf75dec0c73c58de1ca6a8 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 18 Dec 2023 13:08:54 +0100 Subject: [PATCH 060/596] optimize MonUpdateLeader and MonDirOK - a leader and its minions are always ordered in the monsters array 1. no need to check dMonster 2. no need to check the whole monsters array --- Source/monster.cpp | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 6f550e56f20..c0c623420a1 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1681,8 +1681,7 @@ static void MonStartSpAttack(int mnum) */ void MonUpdateLeader(int mnum) { - MonsterStruct* mon; - int i; + int ma; if ((unsigned)mnum >= MAXMONSTERS) { dev_fatal("MonUpdateLeader: Invalid monster %d", mnum); @@ -1690,11 +1689,12 @@ void MonUpdateLeader(int mnum) if (monsters[mnum]._mleaderflag == MLEADER_NONE) return; if (monsters[mnum]._mleaderflag == MLEADER_SELF) { - for (i = 0; i < MAXMONSTERS; i++) { - mon = &monsters[i]; - if (/*mon->_mleaderflag != MLEADER_NONE && */mon->_mleader == mnum) { - mon->_mleader = MON_NO_LEADER; - mon->_mleaderflag = MLEADER_NONE; + // assert(mnum + MON_PACK_SIZE <= MAXMONSTERS); + for (ma = mnum + 1; ma < mnum + MON_PACK_SIZE; ma++) { + // assert(monsters[ma]._mleader == mnum || monsters[ma]._mhitpoints == 0); + if (/*monsters[ma]._mleaderflag != MLEADER_NONE && */monsters[ma]._mleader == mnum) { + monsters[ma]._mleader = MON_NO_LEADER; + monsters[ma]._mleaderflag = MLEADER_NONE; } } } else if (monsters[mnum]._mleaderflag == MLEADER_PRESENT) { @@ -2789,25 +2789,20 @@ static bool MonDirOK(int mnum, int mdir) return abs(fx - monsters[monsters[mnum]._mleader]._mfutx) <= MON_PACK_DISTANCE && abs(fy - monsters[monsters[mnum]._mleader]._mfuty) <= MON_PACK_DISTANCE; } - if (monsters[mnum]._mpacksize == 0) + mcount = monsters[mnum]._mpacksize; + if (mcount == 0) return true; - mcount = 0; - for (x = fx - MON_PACK_DISTANCE; x <= fx + MON_PACK_DISTANCE; x++) { - for (y = fy - MON_PACK_DISTANCE; y <= fy + MON_PACK_DISTANCE; y++) { - assert(IN_DUNGEON_AREA(x, y)); - ma = dMonster[x][y]; - if (ma == 0) - continue; - ma = ma >= 0 ? ma - 1 : -(ma + 1); - if (monsters[ma]._mleaderflag == MLEADER_PRESENT - && monsters[ma]._mleader == mnum - && abs(fx - monsters[ma]._mfutx) <= MON_PACK_DISTANCE - && abs(fy - monsters[ma]._mfuty) <= MON_PACK_DISTANCE) { - mcount++; - } + // assert(mnum + MON_PACK_SIZE <= MAXMONSTERS); + for (ma = mnum + 1; ma < mnum + MON_PACK_SIZE; ma++) { + // assert(monsters[ma]._mleader == mnum || monsters[ma]._mhitpoints == 0); + if (monsters[ma]._mleaderflag == MLEADER_PRESENT + && monsters[ma]._mleader == mnum + && abs(fx - monsters[ma]._mfutx) <= MON_PACK_DISTANCE + && abs(fy - monsters[ma]._mfuty) <= MON_PACK_DISTANCE) { + mcount--; } } - return mcount == monsters[mnum]._mpacksize; + return mcount == 0; } static bool MonCallWalk(int mnum, int md) From 80a37ece2da64c0d27052d86e3be9277adcf32ef Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 18 Dec 2023 15:38:14 +0100 Subject: [PATCH 061/596] Bump actions/upload-artifact from 3 to 4 --- .github/workflows/cmake.yml | 8 ++++---- .github/workflows/nightly.yml | 30 +++++++++++++++--------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index bace57074af..6968e635177 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -1,4 +1,4 @@ -name: CMake +name: CMake # When creating a new workflow in GitHub’s action builder the default trigger is the push event. We want to extend this to push and pull request events. on: [push, pull_request] @@ -19,7 +19,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - + - name: Create Build Environment run: brew bundle install @@ -39,7 +39,7 @@ jobs: working-directory: ${{github.workspace}} # Execute the build. You can specify a specific target with "--target " run: cmake --build build -j $(sysctl -n hw.physicalcpu) --target package - + #- name: Release # uses: softprops/action-gh-release@v1 # if: startsWith(github.ref, 'refs/tags/') @@ -50,7 +50,7 @@ jobs: # Upload the created artifact - name: Upload if: ${{ !env.ACT }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: path: ${{github.workspace}}/build/devilutionx.dmg name: devilutionx.dmg diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 2af690e918e..b77a912ba68 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -97,7 +97,7 @@ jobs: # Upload the created artifact - name: Upload - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: path: ${{ env.buildDir }}/devilutionx.zip name: ${{ matrix.artifact }} @@ -143,7 +143,7 @@ jobs: # Upload the created artifact - name: Upload - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: path: build/devilutionx.zip name: ${{ matrix.artifact }} @@ -189,7 +189,7 @@ jobs: # Upload the created artifact - name: Upload - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: path: build/devilutionx.zip name: ${{ matrix.artifact }} @@ -236,7 +236,7 @@ jobs: # Upload the created artifact - name: Upload - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: path: ${{ env.buildDir }}/devilutionx.zip name: ${{ matrix.artifact }} @@ -272,7 +272,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - + - name: Create Build Environment run: Packaging/nix/debian-host-prep.sh @@ -300,14 +300,14 @@ jobs: - name: Upload Package if: ${{ !env.ACT }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: path: devilutionx-x86_64-linux-gnu.tar.xz name: ${{ matrix.artifact }} - name: Upload AppImage if: ${{ !env.ACT }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: path: devilutionx-x86_64-linux-gnu.appimage name: ${{ matrix.appimage }} @@ -367,7 +367,7 @@ jobs: - name: Upload Package if: ${{ !env.ACT }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: path: devilutionx-aarch64.tar.xz name: ${{ matrix.artifact }} @@ -415,7 +415,7 @@ jobs: # Upload the created artifact - name: Upload - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: path: ${{ env.buildDir }}/devilutionx.dmg name: ${{ matrix.artifact }} @@ -467,7 +467,7 @@ jobs: # Upload the created artifact - name: Upload - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: path: ${{ env.buildDir }}/devilutionx.ipa name: ${{ matrix.artifact }} @@ -528,7 +528,7 @@ jobs: run: cd android-project && ./gradlew assembleRelease -Pcmakearg0="${{ matrix.cmakearg0 }}" -Pcmakearg1="${{ matrix.cmakearg1 }}" -Pcmakearg2="${{ matrix.cmakearg2 }}" - name: Upload-Package - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: #name: devilutionx-debug.apk #path: android-project/app/build/outputs/apk/debug/app-debug.apk @@ -583,7 +583,7 @@ jobs: TOOLCHAIN: /opt/gcw0-toolchain - name: Upload-Package - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ matrix.artifact }} path: build-rg350/devilutionx-rg350.opk @@ -636,7 +636,7 @@ jobs: TOOLCHAIN: /opt/lepus-toolchain - name: Upload-Package - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ matrix.artifact }} path: build-lepus/devilutionx-lepus.opk @@ -691,7 +691,7 @@ jobs: TOOLCHAIN: /opt/retrofw-toolchain - name: Upload-Package - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: #name: devilutionx-retrofw.opk.zip name: ${{ matrix.artifact }} @@ -741,7 +741,7 @@ jobs: run: Packaging/ps4/build.sh "${{ matrix.cmakeargs }}" - name: Upload-Package - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ matrix.artifact }} path: build-ps4/devilutionx-ps4.pkg From 55a466f7c4ae2ede026857b424bd5a3af5b9c61f Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 18 Dec 2023 15:46:14 +0100 Subject: [PATCH 062/596] Bump actions/download-artifact from 3 to 4 --- .github/workflows/nightly.yml | 76 +++++++++++++++++------------------ 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index b77a912ba68..b75f9537b4e 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -755,237 +755,237 @@ jobs: steps: # Windows-builds (x86) - name: Download a diablo artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: diablo-nightly-x86.zip - run: mv ${{github.workspace}}/devilutionx.zip ${{github.workspace}}/diablo-nightly-x86.zip - name: Download a hellfire artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: hellfire-nightly-x86.zip - run: mv ${{github.workspace}}/devilutionx.zip ${{github.workspace}}/hellfire-nightly-x86.zip - name: Download a diablo artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: hellmini-nightly-x86.zip - run: mv ${{github.workspace}}/devilutionx.zip ${{github.workspace}}/hellmini-nightly-x86.zip - name: Download a diablo artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: hellsrv-nightly-x86.zip - run: mv ${{github.workspace}}/devilutionx.zip ${{github.workspace}}/hellsrv-nightly-x86.zip - name: Download a diablo artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: diablo-nightly-mingw-x86.zip - run: mv ${{github.workspace}}/devilutionx.zip ${{github.workspace}}/diablo-nightly-mingw-x86.zip - name: Download a hellfire artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: hellfire-nightly-mingw-x86.zip - run: mv ${{github.workspace}}/devilutionx.zip ${{github.workspace}}/hellfire-nightly-mingw-x86.zip # Windows-builds (x64) - name: Download a diablo artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: diablo-nightly-x64.zip - run: mv ${{github.workspace}}/devilutionx.zip ${{github.workspace}}/diablo-nightly-x64.zip - name: Download a hellfire artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: hellfire-nightly-x64.zip - run: mv ${{github.workspace}}/devilutionx.zip ${{github.workspace}}/hellfire-nightly-x64.zip - name: Download a diablo artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: diablo-nightly-mingw-x64.zip - run: mv ${{github.workspace}}/devilutionx.zip ${{github.workspace}}/diablo-nightly-mingw-x64.zip - name: Download a hellfire artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: hellfire-nightly-mingw-x64.zip - run: mv ${{github.workspace}}/devilutionx.zip ${{github.workspace}}/hellfire-nightly-mingw-x64.zip # Mac-builds - name: Download a diablo mac-artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: diablo-nightly-mac.dmg - run: mv ${{github.workspace}}/devilutionx.dmg ${{github.workspace}}/diablo-nightly-mac.dmg - name: Download a diablo mac-artifact using patched assets - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: diablo-nightly-macp.dmg - run: mv ${{github.workspace}}/devilutionx.dmg ${{github.workspace}}/diablo-nightly-macp.dmg - name: Download a hellfire mac-artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: hellfire-nightly-mac.dmg - run: mv ${{github.workspace}}/devilutionx.dmg ${{github.workspace}}/hellfire-nightly-mac.dmg - name: Download a hellfire mac-artifact using patched assets - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: hellfire-nightly-macp.dmg - run: mv ${{github.workspace}}/devilutionx.dmg ${{github.workspace}}/hellfire-nightly-macp.dmg # iOS-builds - name: Download a diablo iOS artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: diablo-nightly-ios.ipa - run: mv ${{github.workspace}}/devilutionx.ipa ${{github.workspace}}/diablo-nightly-ios.ipa - name: Download a diablo iOS artifact using patched assets - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: diablo-nightly-iosp.ipa - run: mv ${{github.workspace}}/devilutionx.ipa ${{github.workspace}}/diablo-nightly-iosp.ipa - name: Download a hellfire iOS artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: hellfire-nightly-ios.ipa - run: mv ${{github.workspace}}/devilutionx.ipa ${{github.workspace}}/hellfire-nightly-ios.ipa - name: Download a hellfire iOS artifact using patched assets - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: hellfire-nightly-iosp.ipa - run: mv ${{github.workspace}}/devilutionx.ipa ${{github.workspace}}/hellfire-nightly-iosp.ipa # Android-builds - name: Download a diablo android artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: diablo-nightly-android.apk - run: mv ${{github.workspace}}/app-release-unsigned.apk ${{github.workspace}}/diablo-nightly-android.apk - name: Download a diablo android artifact using patched assets - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: diablo-nightly-androidp.apk - run: mv ${{github.workspace}}/app-release-unsigned.apk ${{github.workspace}}/diablo-nightly-androidp.apk - name: Download a hellfire android artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: hellfire-nightly-android.apk - run: mv ${{github.workspace}}/app-release-unsigned.apk ${{github.workspace}}/hellfire-nightly-android.apk - name: Download a hellfire android artifact using patched assets - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: hellfire-nightly-androidp.apk - run: mv ${{github.workspace}}/app-release-unsigned.apk ${{github.workspace}}/hellfire-nightly-androidp.apk # rg350-builds - name: Download a diablo rg350 artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: diablo-nightly-rg350.opk - run: mv ${{github.workspace}}/devilutionx-rg350.opk ${{github.workspace}}/diablo-nightly-rg350.opk - name: Download a diablo rg350 artifact using patched assets - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: diablo-nightly-rg350p.opk - run: mv ${{github.workspace}}/devilutionx-rg350.opk ${{github.workspace}}/diablo-nightly-rg350p.opk - name: Download a hellfire rg350 artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: hellfire-nightly-rg350.opk - run: mv ${{github.workspace}}/devilutionx-rg350.opk ${{github.workspace}}/hellfire-nightly-rg350.opk - name: Download a hellfire rg350 artifact using patched assets - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: hellfire-nightly-rg350p.opk - run: mv ${{github.workspace}}/devilutionx-rg350.opk ${{github.workspace}}/hellfire-nightly-rg350p.opk # lepus-builds - name: Download a diablo lepus artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: diablo-nightly-lepus.opk - run: mv ${{github.workspace}}/devilutionx-lepus.opk ${{github.workspace}}/diablo-nightly-lepus.opk - name: Download a diablo lepus artifact using patched assets - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: diablo-nightly-lepusp.opk - run: mv ${{github.workspace}}/devilutionx-lepus.opk ${{github.workspace}}/diablo-nightly-lepusp.opk - name: Download a hellfire lepus artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: hellfire-nightly-lepus.opk - run: mv ${{github.workspace}}/devilutionx-lepus.opk ${{github.workspace}}/hellfire-nightly-lepus.opk - name: Download a hellfire lepus artifact using patched assets - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: hellfire-nightly-lepusp.opk - run: mv ${{github.workspace}}/devilutionx-lepus.opk ${{github.workspace}}/hellfire-nightly-lepusp.opk # retrofw-builds - name: Download a diablo retrofw artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: diablo-nightly-retrofw.opk - run: mv ${{github.workspace}}/devilutionx-retrofw.opk ${{github.workspace}}/diablo-nightly-retrofw.opk - name: Download a diablo retrofw artifact using patched assets - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: diablo-nightly-retrofwp.opk - run: mv ${{github.workspace}}/devilutionx-retrofw.opk ${{github.workspace}}/diablo-nightly-retrofwp.opk - name: Download a hellfire retrofw artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: hellfire-nightly-retrofw.opk - run: mv ${{github.workspace}}/devilutionx-retrofw.opk ${{github.workspace}}/hellfire-nightly-retrofw.opk - name: Download a hellfire retrofw artifact using patched assets - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: hellfire-nightly-retrofwp.opk - run: mv ${{github.workspace}}/devilutionx-retrofw.opk ${{github.workspace}}/hellfire-nightly-retrofwp.opk # ps4-builds - name: Download a diablo ps4 artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: diablo-nightly-ps4.pkg - run: mv ${{github.workspace}}/devilutionx-ps4.pkg ${{github.workspace}}/diablo-nightly-ps4.pkg - name: Download a diablo ps4 artifact using patched assets - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: diablo-nightly-ps4p.pkg - run: mv ${{github.workspace}}/devilutionx-ps4.pkg ${{github.workspace}}/diablo-nightly-ps4p.pkg - name: Download a hellfire ps4 artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: hellfire-nightly-ps4.pkg - run: mv ${{github.workspace}}/devilutionx-ps4.pkg ${{github.workspace}}/hellfire-nightly-ps4.pkg - name: Download a hellfire ps4 artifact using patched assets - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: hellfire-nightly-ps4p.pkg - run: mv ${{github.workspace}}/devilutionx-ps4.pkg ${{github.workspace}}/hellfire-nightly-ps4p.pkg From 45136ffb1c7a04771b436f7652df1bbbeaa1c491 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 18 Dec 2023 15:55:24 +0100 Subject: [PATCH 063/596] prevent desync due to relaxed absent minions - never leave the leader permanently (except for death) - prevent absent minions from relaxing --- Source/monster.cpp | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index c0c623420a1..b6e0a23fb9d 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1677,7 +1677,31 @@ static void MonStartSpAttack(int mnum) } /* - * Disconnect monster from its pack/leader. + * Disconnect monster from its pack/leader temporarily. + */ +static void MonLeaveLeader(int mnum) +{ + int ma; + + //if (monsters[mnum]._mleaderflag == MLEADER_NONE) + // return; + if (monsters[mnum]._mleaderflag == MLEADER_PRESENT) { + monsters[mnum]._mleaderflag = MLEADER_AWAY; + monsters[monsters[mnum]._mleader]._mpacksize--; + } else if (monsters[mnum]._mleaderflag == MLEADER_SELF) { + monsters[mnum]._mpacksize = 0; + // assert(mnum + MON_PACK_SIZE <= MAXMONSTERS); + for (ma = mnum + 1; ma < mnum + MON_PACK_SIZE; ma++) { + // assert(monsters[ma]._mleader == mnum || monsters[ma]._mhitpoints == 0); + if (/*monsters[ma]._mleaderflag != MLEADER_NONE && */monsters[ma]._mleader == mnum) { + monsters[ma]._mleaderflag = MLEADER_AWAY; + } + } + } +} + +/* + * Disconnect monster from its pack/leader permanently. */ void MonUpdateLeader(int mnum) { @@ -1787,7 +1811,7 @@ static void MonTeleport(int mnum, int tx, int ty) mon->_mx = x; mon->_my = y; mon->_mdir = OPPOSITE(rx); - MonUpdateLeader(mnum); + MonLeaveLeader(mnum); return; } } @@ -2739,9 +2763,9 @@ static void GroupUnity(int mnum) leader->_mpacksize++; mon->_mleaderflag = MLEADER_PRESENT; } - } else if (mon->_mleaderflag == MLEADER_PRESENT) { - leader->_mpacksize--; + } else if (mon->_mleaderflag == MLEADER_PRESENT) { // MonLeaveLeader mon->_mleaderflag = MLEADER_AWAY; + leader->_mpacksize--; } if (mon->_mleaderflag == MLEADER_PRESENT) { if (mon->_msquelch > leader->_msquelch) { @@ -2975,7 +2999,7 @@ void MAI_Snake(int mnum) if (dist == 2 && LineClearMon(mnum, mon->_mx, mon->_my, mon->_menemyx, mon->_menemyy) && mon->_mVar1 != MM_CHARGE) { if (AddMissile(mon->_mx, mon->_my, mon->_menemyx, mon->_menemyy, mon->_mdir, MIS_RHINO, MST_MONSTER, mnum, 0) != -1) { PlayMonSFX(mnum, MS_ATTACK); - MonUpdateLeader(mnum); + MonLeaveLeader(mnum); } } else if (mon->_mVar1 == MM_DELAY || random_(106, 100) >= 35 - 2 * mon->_mAI.aiInt) { // calculate the desired direction @@ -3050,7 +3074,7 @@ void MAI_Bat(int mnum) && v < 4 * mon->_mAI.aiInt + 33 && LineClearMon(mnum, mon->_mx, mon->_my, mon->_menemyx, mon->_menemyy)) { if (AddMissile(mon->_mx, mon->_my, mon->_menemyx, mon->_menemyy, mon->_mdir, MIS_RHINO, MST_MONSTER, mnum, 0) != -1) { - MonUpdateLeader(mnum); + MonLeaveLeader(mnum); } } else if (dist >= 2) { if (((unsigned)mon->_mVar2 > MON_WALK_DELAY && v < mon->_mAI.aiInt + 13) // STAND_TICK @@ -3503,7 +3527,7 @@ void MAI_Scav(int mnum) if (MON_ACTIVE || MON_RELAXED) return; if (mon->_mhitpoints < (mon->_mmaxhp >> 1) && mon->_mgoal != MGOAL_HEALING) { - MonUpdateLeader(mnum); + MonLeaveLeader(mnum); mon->_mgoal = MGOAL_HEALING; mon->_mgoalvar1 = 0; // HEALING_LOCATION_X //mon->_mgoalvar2 = 0; @@ -3919,7 +3943,7 @@ void MAI_Rhino(int mnum) mon->_mdir = currEnemyInfo._meLastDir; if (AddMissile(mon->_mx, mon->_my, mon->_menemyx, mon->_menemyy, mon->_mdir, MIS_RHINO, MST_MONSTER, mnum, 0) != -1) { PlayMonSFX(mnum, MS_SPECIAL); - MonUpdateLeader(mnum); + MonLeaveLeader(mnum); } } else if (dist < 2) { if (v < 2 * mon->_mAI.aiInt + 28) { @@ -4387,7 +4411,7 @@ void ProcessMonsters() #endif } mon->_msquelch = SQUELCH_MAX; - } else if (mon->_msquelch != 0 && mon->_mhitpoints == mon->_mmaxhp) { + } else if (mon->_msquelch != 0 && mon->_mhitpoints == mon->_mmaxhp && mon->_mleaderflag != MLEADER_AWAY) { mon->_msquelch--; if (mon->_msquelch == 0) { // reset monster state to ensure sync in multiplayer games From ff39a609438b4a8676acb48dbcb0b6661e15a87b Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 18 Dec 2023 16:03:45 +0100 Subject: [PATCH 064/596] cosmetic --- Source/monster.cpp | 44 ++++++++++++-------------------------------- 1 file changed, 12 insertions(+), 32 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index b6e0a23fb9d..799403e6848 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -2399,16 +2399,7 @@ static bool MonDoRAttack(int mnum) mon = &monsters[mnum]; if (mon->_mAnimFrame == mon->_mAFNum) { - AddMissile( - mon->_mx, - mon->_my, - mon->_menemyx, - mon->_menemyy, - mon->_mdir, - mon->_mVar1, // RATTACK_SKILL - MST_MONSTER, - mnum, - 0); + AddMissile(mon->_mx, mon->_my, mon->_menemyx, mon->_menemyy, mon->_mdir, mon->_mVar1, MST_MONSTER, mnum, 0); // RATTACK_SKILL PlayMonSFX(mnum, MS_ATTACK); } @@ -2428,16 +2419,7 @@ static bool MonDoRSpAttack(int mnum) mon = &monsters[mnum]; if (mon->_mAnimFrame == mon->_mAFNum2) { if (mon->_mAnimCnt == 0) { - AddMissile( - mon->_mx, - mon->_my, - mon->_menemyx, - mon->_menemyy, - mon->_mdir, - mon->_mVar1, // SPATTACK_SKILL - MST_MONSTER, - mnum, - 0); + AddMissile(mon->_mx, mon->_my, mon->_menemyx, mon->_menemyy, mon->_mdir, mon->_mVar1, MST_MONSTER, mnum, 0); // SPATTACK_SKILL PlayMonSFX(mnum, MS_SPECIAL); } @@ -3031,8 +3013,8 @@ void MAI_Snake(int mnum) } } else { // STAND_PREV_MODE if (mon->_mVar1 == MM_DELAY - || mon->_mVar1 == MM_CHARGE - || (random_(105, 100) < mon->_mAI.aiInt + 20)) { + || mon->_mVar1 == MM_CHARGE + || (random_(105, 100) < mon->_mAI.aiInt + 20)) { MonStartAttack(mnum); } else MonStartDelay(mnum, RandRange(11, 18) - mon->_mAI.aiInt); @@ -3070,9 +3052,9 @@ void MAI_Bat(int mnum) v = random_(107, 100); dist = currEnemyInfo._meRealDist; if (mon->_mType == MT_GBAT - && dist >= 5 - && v < 4 * mon->_mAI.aiInt + 33 - && LineClearMon(mnum, mon->_mx, mon->_my, mon->_menemyx, mon->_menemyy)) { + && dist >= 5 + && v < 4 * mon->_mAI.aiInt + 33 + && LineClearMon(mnum, mon->_mx, mon->_my, mon->_menemyx, mon->_menemyy)) { if (AddMissile(mon->_mx, mon->_my, mon->_menemyx, mon->_menemyy, mon->_mdir, MIS_RHINO, MST_MONSTER, mnum, 0) != -1) { MonLeaveLeader(mnum); } @@ -3238,7 +3220,7 @@ void MAI_Sneak(int mnum) mon->_mdir = md; if (mon->_mgoal == MGOAL_NORMAL) { if (EnemyInLine(mnum) - && AddMissile(mx, my, fx, fy, md, MIS_FIREMAN, MST_MONSTER, mnum, 0) != -1) { + && AddMissile(mx, my, fx, fy, md, MIS_FIREMAN, MST_MONSTER, mnum, 0) != -1) { mon->_mmode = MM_CHARGE; mon->_mgoal = MGOAL_ATTACK; //mon->_mgoalvar1 = 0; // FIREMAN_ACTION_PROGRESS @@ -3692,8 +3674,7 @@ void MAI_RoundRanged(int mnum) } /*if ((--mon->_mgoalvar1 <= 4 && MonDirOK(mnum, currEnemyInfo._meLastDir)) || mon->_mgoalvar1 == 0) { mon->_mgoal = MGOAL_NORMAL; - } else if (v < ((6 * (mon->_mAI.aiInt + 1)) >> mon->_mAI.aiParam2) - && EnemyInLine(mnum)) { + } else if (v < ((6 * (mon->_mAI.aiInt + 1)) >> mon->_mAI.aiParam2) && EnemyInLine(mnum)) { MonStartRSpAttack(mnum, mon->_mAI.aiParam1); } else { MonRoundWalk(mnum, currEnemyInfo._meLastDir, &mon->_mgoalvar2); // MOVE_TURN_DIRECTION @@ -3939,7 +3920,7 @@ void MAI_Rhino(int mnum) if (mon->_mgoal == MGOAL_NORMAL) { if (dist >= 5 && v < 2 * mon->_mAI.aiInt + 43 - && LineClearMon(mnum, mon->_mx, mon->_my, mon->_menemyx, mon->_menemyy)) { + && LineClearMon(mnum, mon->_mx, mon->_my, mon->_menemyx, mon->_menemyy)) { mon->_mdir = currEnemyInfo._meLastDir; if (AddMissile(mon->_mx, mon->_my, mon->_menemyx, mon->_menemyy, mon->_mdir, MIS_RHINO, MST_MONSTER, mnum, 0) != -1) { PlayMonSFX(mnum, MS_SPECIAL); @@ -4051,7 +4032,7 @@ void MAI_Counselor(int mnum) } } else { mon->_mdir = md; - if (mon->_mVar1 == MM_FADEIN) + if (mon->_mVar1 == MM_FADEIN) // STAND_PREV_MODE v >>= 1; if (mon->_mVar1 != MM_FADEIN && mon->_mhitpoints < (mon->_mmaxhp >> 1)) { #if DEBUG @@ -4062,8 +4043,7 @@ void MAI_Counselor(int mnum) mon->_mgoal = MGOAL_RETREAT; mon->_mgoalvar1 = 5; // RETREAT_DISTANCE MonStartFadeout(mnum, md, false); - } else if (mon->_mVar1 == MM_DELAY // STAND_PREV_MODE - || v < 2 * mon->_mAI.aiInt + 20) { + } else if (mon->_mVar1 == MM_DELAY || v < 2 * mon->_mAI.aiInt + 20) { MonStartRAttack(mnum, MIS_FLASH); } } From 0bf171da5716f7d51a5993ccbf9c1e6db95c5e75 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 18 Dec 2023 17:06:04 +0100 Subject: [PATCH 065/596] start monster-bleeding at the hit-offset --- Source/monster.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 799403e6848..fc756939984 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1899,11 +1899,11 @@ void MonStartPlrHit(int mnum, int pnum, int dam, unsigned hitflags, int sx, int return; if (mon->_mmode == MM_STONE) return; - if (hitflags & ISPL_KNOCKBACK) - MonGetKnockback(mnum, sx, sy); if (mon->_mFlags & MFLAG_CAN_BLEED && (hitflags & ISPL_FAKE_CAN_BLEED) && ((hitflags & ISPL_BLEED) ? random_(47, 32) == 0 : random_(48, 64) == 0)) AddMissile(0, 0, 0, 0, 0, MIS_BLEED, MST_PLAYER, pnum, mnum); + if (hitflags & ISPL_KNOCKBACK) + MonGetKnockback(mnum, sx, sy); if ((dam << ((hitflags & ISPL_STUN) ? 3 : 2)) >= mon->_mmaxhp /*&& mon->_mmode != MM_STONE*/) { mon->_mdir = OPPOSITE(plr._pdir); if (mon->_mType == MT_NBAT) From 48ed089e465289dbea0a17b3b6e119fd0eecb798 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 18 Dec 2023 17:08:55 +0100 Subject: [PATCH 066/596] leave leader behind in case of knockback and stone --- Source/missiles.cpp | 1 + Source/monster.cpp | 3 ++- Source/monster.h | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 189fb85b84a..31b953b9a12 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -2776,6 +2776,7 @@ int AddStone(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in mon = &monsters[mid]; if (!(mon->_mFlags & MFLAG_NOSTONE)) { if (mon->_mmode != MM_FADEIN && mon->_mmode != MM_FADEOUT && mon->_mmode != MM_CHARGE && mon->_mmode != MM_STONE && mon->_mmode != MM_DEATH /*mon->_mhitpoints >= (1 << 6*/) { + MonLeaveLeader(mid); mis->_miVar1 = mon->_mmode; mis->_miVar2 = mid; mon->_mVar3 = mon->_mmode; diff --git a/Source/monster.cpp b/Source/monster.cpp index fc756939984..6a2690160a0 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1679,7 +1679,7 @@ static void MonStartSpAttack(int mnum) /* * Disconnect monster from its pack/leader temporarily. */ -static void MonLeaveLeader(int mnum) +void MonLeaveLeader(int mnum) { int ma; @@ -1872,6 +1872,7 @@ static void MonGetKnockback(int mnum, int sx, int sy) mon->_my = newy; RemoveMonFromMap(mnum); MonPlace(mnum); + MonLeaveLeader(mnum); } } diff --git a/Source/monster.h b/Source/monster.h index 2a5f8c14a3a..736fe2b4266 100644 --- a/Source/monster.h +++ b/Source/monster.h @@ -50,6 +50,7 @@ void MonStartPlrHit(int mnum, int pnum, int dam, unsigned hitflags, int sx, int void MonStartMonHit(int defm, int offm, int dam); void MonStartKill(int mnum, int pnum); void MonSyncStartKill(int mnum, int x, int y, int pnum); +void MonLeaveLeader(int mnum); void MonUpdateLeader(int mnum); void MonAddDead(int mnum); void DoEnding(); From a6def50713e76dca9dd1cd8b2411519c8f756572 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 19 Dec 2023 08:59:14 +0100 Subject: [PATCH 067/596] add MonStopWalk to stop walking monsters when hit or knocked back --- Source/monster.cpp | 48 ++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 6a2690160a0..8110d1e6d9e 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1775,14 +1775,37 @@ static void MonPlace(int mnum) dMonster[mx][my] = mnum + 1; } -static void MonStartGetHit(int mnum) +static void MonStopWalk(int mnum) { MonsterStruct* mon = &monsters[mnum]; + int x, y; - assert(mon->_mmode != MM_DEATH && mon->_mmode != MM_STONE /*&& mon->_mType != MT_GOLEM */); + if (mon->_mmode < MM_WALK || mon->_mmode > MM_WALK2) + return; + if (mon->_mAnimFrame > (mon->_mAnims[MA_WALK].maFrames >> 1)) { + x = mon->_mfutx; + y = mon->_mfuty; + } else { + x = mon->_moldx; + y = mon->_moldy; + } + mon->_mx = x; + mon->_my = y; RemoveMonFromMap(mnum); MonPlace(mnum); + MonStartStand(mnum); + return; +} + +static void MonStartGetHit(int mnum) +{ + MonsterStruct* mon = &monsters[mnum]; + + assert(mon->_mmode != MM_DEATH && mon->_mmode != MM_STONE /*&& mon->_mType != MT_GOLEM */); + + MonStopWalk(mnum); + AssertFixMonLocation(mnum); NewMonsterAnim(mnum, MA_GOTHIT, mon->_mdir); @@ -1848,21 +1871,14 @@ static void MonGetKnockback(int mnum, int sx, int sy) MonsterStruct* mon = &monsters[mnum]; int oldx, oldy, newx, newy, dir; - if (mon->_mmode < MM_WALK || mon->_mmode > MM_WALK2) { - if (mon->_mmode == MM_DEATH || mon->_mmode == MM_STONE) - return; - oldx = mon->_mx; - oldy = mon->_my; - } else { - if (mon->_mAnimFrame > (mon->_mAnims[MA_WALK].maFrames >> 1)) { - oldx = mon->_mfutx; - oldy = mon->_mfuty; - } else { - oldx = mon->_moldx; - oldy = mon->_moldy; - } - } + if (mon->_mmode == MM_DEATH || mon->_mmode == MM_STONE) + return; + + MonStopWalk(mnum); + AssertFixMonLocation(mnum); + oldx = mon->_mx; + oldy = mon->_my; dir = GetDirection(sx, sy, oldx, oldy); if (PathWalkable(oldx, oldy, dir2pdir[dir])) { newx = oldx + offset_x[dir]; From 63613751c2eb9d4f32551a92c7d2037222cb7668 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 19 Dec 2023 09:09:35 +0100 Subject: [PATCH 068/596] do not knock back golems when hit by a charging rhino --- Source/monster.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 8110d1e6d9e..7720a0e6e78 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1892,8 +1892,8 @@ static void MonGetKnockback(int mnum, int sx, int sy) } } - if (mnum >= MAX_MINIONS) // mon->_mType != MT_GOLEM - MonStartGetHit(mnum); + // assert(mnum >= MAX_MINIONS); // mon->_mType != MT_GOLEM + MonStartGetHit(mnum); } void MonStartPlrHit(int mnum, int pnum, int dam, unsigned hitflags, int sx, int sy) @@ -4668,7 +4668,6 @@ void MissToMonst(int mi) MonHitMon(mnum, defm, mon->_mHit * 8, mon->_mMinDamage2, mon->_mMaxDamage2); if (mpnum == dMonster[oldx][oldy] && mon->_mAI.aiType == AI_RHINO) { /* mon->_mType < MT_NSNAKE || mon->_mType > MT_GSNAKE */ // TODO: use MonStartMonHit ? - MonGetKnockback(defm, mis->_misx, mis->_misy); PlayMonSFX(mnum, MS_GOTHIT); } } From e940505d2f39a5c6c0614ef2c03b27520c476cf1 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 19 Dec 2023 09:20:00 +0100 Subject: [PATCH 069/596] ignore dying monsters when telekinesis is applied --- Source/missiles.cpp | 2 +- Source/monster.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 31b953b9a12..65f2ab9c799 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -3288,7 +3288,7 @@ int AddTelekinesis(int mi, int sx, int sy, int dx, int dy, int midir, int micast case MTT_MONSTER: // assert(target < MAXMONSTERS); if (LineClear(plr._px, plr._py, monsters[target]._mx, monsters[target]._my) - && CheckMonsterHit(target, &ret) && monsters[target]._mmode != MM_STONE && (monsters[target]._mmaxhp >> (6 + 1)) < plr._pMagic) { + && CheckMonsterHit(target, &ret) && monsters[target]._mmode != MM_STONE && monsters[target]._mmode != MM_DEATH && (monsters[target]._mmaxhp >> (6 + 1)) < plr._pMagic) { monsters[target]._msquelch = SQUELCH_MAX; monsters[target]._mlastx = plr._px; monsters[target]._mlasty = plr._py; diff --git a/Source/monster.cpp b/Source/monster.cpp index 7720a0e6e78..3b1f59c1b73 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1871,8 +1871,7 @@ static void MonGetKnockback(int mnum, int sx, int sy) MonsterStruct* mon = &monsters[mnum]; int oldx, oldy, newx, newy, dir; - if (mon->_mmode == MM_DEATH || mon->_mmode == MM_STONE) - return; + // assert(mon->_mmode != MM_DEATH && mon->_mmode != MM_STONE); MonStopWalk(mnum); AssertFixMonLocation(mnum); @@ -1907,6 +1906,7 @@ void MonStartPlrHit(int mnum, int pnum, int dam, unsigned hitflags, int sx, int dev_fatal("Invalid player %d hitting monster %d", pnum, mnum); } mon = &monsters[mnum]; + // assert(mon->_mmode != MM_DEATH); mon->_mWhoHit |= 1 << pnum; if (pnum == mypnum) { NetSendCmdMonstDamage(mnum, mon->_mhitpoints); From aaa33bc94aeb6815d6227a7c2131a33c2c12570a Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 19 Dec 2023 09:47:16 +0100 Subject: [PATCH 070/596] cosmetic --- Source/monster.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 3b1f59c1b73..ae94dbf1444 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -702,8 +702,8 @@ static bool MonstPlace(int xp, int yp) { static_assert(DBORDERX >= MON_PACK_DISTANCE, "MonstPlace does not check IN_DUNGEON_AREA but expects a large enough border I."); static_assert(DBORDERY >= MON_PACK_DISTANCE, "MonstPlace does not check IN_DUNGEON_AREA but expects a large enough border II."); - return (dMonster[xp][yp] | /*dPlayer[xp][yp] |*/ nSolidTable[dPiece[xp][yp]] - | (dFlags[xp][yp] & (BFLAG_ALERT | BFLAG_MON_PROTECT))) == 0; + return (dMonster[xp][yp]/* | /*dPlayer[xp][yp] | dObject[xp][yp]*/ + | nSolidTable[dPiece[xp][yp]] | (dFlags[xp][yp] & (BFLAG_ALERT | BFLAG_MON_PROTECT))) == 0; } #ifdef HELLFIRE @@ -1780,6 +1780,7 @@ static void MonStopWalk(int mnum) MonsterStruct* mon = &monsters[mnum]; int x, y; + // assert(mon->_mmode != MM_STONE); if (mon->_mmode < MM_WALK || mon->_mmode > MM_WALK2) return; @@ -1802,7 +1803,7 @@ static void MonStartGetHit(int mnum) { MonsterStruct* mon = &monsters[mnum]; - assert(mon->_mmode != MM_DEATH && mon->_mmode != MM_STONE /*&& mon->_mType != MT_GOLEM */); + // assert(mon->_mmode != MM_DEATH && mon->_mmode != MM_STONE && mon->_mType != MT_GOLEM); MonStopWalk(mnum); AssertFixMonLocation(mnum); @@ -1921,7 +1922,7 @@ void MonStartPlrHit(int mnum, int pnum, int dam, unsigned hitflags, int sx, int AddMissile(0, 0, 0, 0, 0, MIS_BLEED, MST_PLAYER, pnum, mnum); if (hitflags & ISPL_KNOCKBACK) MonGetKnockback(mnum, sx, sy); - if ((dam << ((hitflags & ISPL_STUN) ? 3 : 2)) >= mon->_mmaxhp /*&& mon->_mmode != MM_STONE*/) { + if ((dam << ((hitflags & ISPL_STUN) ? 3 : 2)) >= mon->_mmaxhp) { mon->_mdir = OPPOSITE(plr._pdir); if (mon->_mType == MT_NBAT) MonTeleport(mnum, plr._pfutx, plr._pfuty); @@ -1937,6 +1938,7 @@ void MonStartMonHit(int defm, int offm, int dam) dev_fatal("Invalid monster %d getting hit by monster/trap", defm); } dmon = &monsters[defm]; + // assert(dmon->_mmode != MM_DEATH); if ((unsigned)offm < MAX_MINIONS) { static_assert(MAX_MINIONS == MAX_PLRS, "M2MStartHit requires that owner of a monster has the same id as the monster itself."); dmon->_mWhoHit |= 1 << offm; @@ -1947,13 +1949,15 @@ void MonStartMonHit(int defm, int offm, int dam) PlayMonSFX(defm, MS_GOTHIT); if (defm < MAX_MINIONS/* mon->_mType == MT_GOLEM */) return; + if (dmon->_mmode == MM_STONE) + return; // Knockback: // 1. Golems -> other monsters. assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_KNOCKBACK)); // 2. other monsters -> golems : golems are immune against knockbacks // Bleed: // 1. Golems -> other monsters. TODO: implement? // 2. other monsters -> golems. assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_CAN_BLEED)); - if ((dam << 2) >= dmon->_mmaxhp && dmon->_mmode != MM_STONE) { + if ((dam << 2) >= dmon->_mmaxhp) { if (offm >= 0) { dmon->_mdir = OPPOSITE(monsters[offm]._mdir); if (dmon->_mType == MT_NBAT) @@ -2756,8 +2760,8 @@ static void GroupUnity(int mnum) leader = &monsters[mon->_mleader]; clear = LineClear(mon->_mx, mon->_my, leader->_mfutx, leader->_mfuty); if (clear - && abs(mon->_mx - leader->_mfutx) <= MON_PACK_DISTANCE - && abs(mon->_my - leader->_mfuty) <= MON_PACK_DISTANCE) { + && abs(mon->_mx - leader->_mfutx) <= MON_PACK_DISTANCE + && abs(mon->_my - leader->_mfuty) <= MON_PACK_DISTANCE) { if (mon->_mleaderflag == MLEADER_AWAY) { leader->_mpacksize++; mon->_mleaderflag = MLEADER_PRESENT; From 5d4aad0ff78f4ca21f34108da4786dc31d91fede Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 19 Dec 2023 12:55:30 +0100 Subject: [PATCH 071/596] add MonStopWalk to stop walking monsters when hit or knocked back II. - prevent overwrite of mx/y from MonStopWalk --- Source/monster.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index ae94dbf1444..8507d794819 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1829,12 +1829,12 @@ static void MonTeleport(int mnum, int tx, int ty) y = ty + offset_y[rx]; assert(IN_DUNGEON_AREA(x, y)); if (x != mon->_mx && y != mon->_my && PosOkMonst(mnum, x, y)) { - //RemoveMonFromMap(mnum); - //assert(dMonster[mon->_mx][mon->_my] == 0); - //dMonster[x][y] = mnum + 1; mon->_mx = x; mon->_my = y; mon->_mdir = OPPOSITE(rx); + mon->_mmode = MM_STAND; // prevent overwrite of mx/y from MonStopWalk + // RemoveMonFromMap(mnum); + // MonPlace(mnum); MonLeaveLeader(mnum); return; } From 3d7c5968b0482f82ecda4dc8b0ea38d4a2b8a9ba Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 19 Dec 2023 13:02:17 +0100 Subject: [PATCH 072/596] swap hasenemy and alert checks in ProcessMonsters --- Source/monster.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 8507d794819..63d3747b786 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -4381,12 +4381,6 @@ void ProcessMonsters() alert = (dFlags[mon->_mx][mon->_my] & BFLAG_ALERT) != 0; hasenemy = MON_HAS_ENEMY; - if (alert && !hasenemy) { - MonFindEnemy(mnum); - // commented out, because the player might went out of sight in the meantime - // assert(MON_HAS_ENEMY || myplr._pInvincible); - alert = hasenemy = MON_HAS_ENEMY; - } if (hasenemy) { _menemy = mon->_menemy; if (!(mon->_mFlags & MFLAG_TARGETS_MONSTER)) { @@ -4396,6 +4390,11 @@ void ProcessMonsters() mon->_menemyx = monsters[_menemy]._mfutx; mon->_menemyy = monsters[_menemy]._mfuty; } + } else if (alert) { + MonFindEnemy(mnum); + // commented out, because the player might went out of sight in the meantime + // assert(MON_HAS_ENEMY || myplr._pInvincible); + alert = hasenemy = MON_HAS_ENEMY; } if (alert) { assert(hasenemy); From 952026016f631acfab5a6aff3efb6fc2134bb200 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 19 Dec 2023 13:09:57 +0100 Subject: [PATCH 073/596] 'bugfix' for vanilla (golems vs new target) - prevent golems from switching targets when a new monster moves to the same distance --- Source/monster.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 63d3747b786..a751001e7fc 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1415,8 +1415,12 @@ static void MonFindEnemy(int mnum) dist = std::max(abs(mon->_mx - tmon->_mx), abs(mon->_my - tmon->_my)); sameroom = tv == dTransVal[tmon->_mx][tmon->_my]; if (sameroom == bestsameroom) { - if (dist >= best_dist) + if (dist > best_dist) continue; + if (dist == best_dist) { + if (mon->_menemyy != i/* || !(mon->_mFlags & (MFLAG_TARGETS_MONSTER))*/) + continue; + } } else if (!sameroom) continue; enemy = -(tnum + 1); From 8b6f7919c7ce3ce360e1a5bd86ef726e43dad3a4 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 19 Dec 2023 13:11:34 +0100 Subject: [PATCH 074/596] update enemy even if the monster has already one (but prefer the original target) --- Source/monster.cpp | 54 +++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index a751001e7fc..4a9f47bb0da 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1370,8 +1370,12 @@ static void MonFindEnemy(int mnum) sameroom = tv == dTransVal[plx(i)._px][plx(i)._py]; dist = std::max(abs(mon->_mx - plx(i)._px), abs(mon->_my - plx(i)._py)); if (sameroom == bestsameroom) { - if (dist >= best_dist) + if (dist > best_dist) continue; + if (dist == best_dist) { + if (mon->_menemyy != i || (mon->_mFlags & MFLAG_TARGETS_MONSTER)) + continue; + } } else if (!sameroom) continue; enemy = i + 1; @@ -1389,8 +1393,12 @@ static void MonFindEnemy(int mnum) dist = std::max(abs(mon->_mx - tmon->_mx), abs(mon->_my - tmon->_my)); sameroom = tv == dTransVal[tmon->_mx][tmon->_my]; if (sameroom == bestsameroom) { - if (dist >= best_dist) + if (dist > best_dist) continue; + if (dist == best_dist) { + if (mon->_menemyy != i || !(mon->_mFlags & (MFLAG_TARGETS_MONSTER))) + continue; + } } else if (!sameroom) continue; enemy = -(i + 1); @@ -4364,8 +4372,8 @@ void MAI_Warlord(int mnum) void ProcessMonsters() { - int mnum, _menemy; - bool alert, hasenemy, raflag; + int mnum; + bool alert, raflag; MonsterStruct* mon; for (mnum = 0; mnum < MAXMONSTERS; mnum++) { @@ -4384,37 +4392,27 @@ void ProcessMonsters() } alert = (dFlags[mon->_mx][mon->_my] & BFLAG_ALERT) != 0; - hasenemy = MON_HAS_ENEMY; - if (hasenemy) { - _menemy = mon->_menemy; - if (!(mon->_mFlags & MFLAG_TARGETS_MONSTER)) { - mon->_menemyx = plx(_menemy)._pfutx; - mon->_menemyy = plx(_menemy)._pfuty; - } else { - mon->_menemyx = monsters[_menemy]._mfutx; - mon->_menemyy = monsters[_menemy]._mfuty; - } - } else if (alert) { + if (alert || MON_HAS_ENEMY) { MonFindEnemy(mnum); // commented out, because the player might went out of sight in the meantime // assert(MON_HAS_ENEMY || myplr._pInvincible); - alert = hasenemy = MON_HAS_ENEMY; } if (alert) { - assert(hasenemy); - mon->_mlastx = mon->_menemyx; - mon->_mlasty = mon->_menemyy; - if (mon->_msquelch == 0) { - if (mon->_mType == MT_CLEAVER) - PlaySfxLoc(USFX_CLEAVER, mon->_mx, mon->_my); + if (MON_HAS_ENEMY) { + mon->_mlastx = mon->_menemyx; + mon->_mlasty = mon->_menemyy; + if (mon->_msquelch == 0) { + if (mon->_mType == MT_CLEAVER) + PlaySfxLoc(USFX_CLEAVER, mon->_mx, mon->_my); #ifdef HELLFIRE - else if (mon->_mType == MT_NAKRUL) - PlaySfxLoc(quests[Q_JERSEY]._qactive != QUEST_NOTAVAIL ? USFX_NAKRUL6 : (quests[Q_NAKRUL]._qvar1 == QV_NAKRUL_BOOKOPEN ? USFX_NAKRUL4 : USFX_NAKRUL5), mon->_mx, mon->_my); - else if (mon->_mType == MT_DEFILER) - PlaySfxLoc(USFX_DEFILER8, mon->_mx, mon->_my); + else if (mon->_mType == MT_NAKRUL) + PlaySfxLoc(quests[Q_JERSEY]._qactive != QUEST_NOTAVAIL ? USFX_NAKRUL6 : (quests[Q_NAKRUL]._qvar1 == QV_NAKRUL_BOOKOPEN ? USFX_NAKRUL4 : USFX_NAKRUL5), mon->_mx, mon->_my); + else if (mon->_mType == MT_DEFILER) + PlaySfxLoc(USFX_DEFILER8, mon->_mx, mon->_my); #endif + } + mon->_msquelch = SQUELCH_MAX; } - mon->_msquelch = SQUELCH_MAX; } else if (mon->_msquelch != 0 && mon->_mhitpoints == mon->_mmaxhp && mon->_mleaderflag != MLEADER_AWAY) { mon->_msquelch--; if (mon->_msquelch == 0) { @@ -4432,6 +4430,8 @@ void ProcessMonsters() assert(mon->_mmode == MM_STAND); } // mon->_mFlags |= MFLAG_NO_ENEMY; + mon->_mFlags &= ~MFLAG_TARGETS_MONSTER; + mon->_menemy = 0; mon->_menemyx = 0; mon->_menemyy = 0; mon->_mVar1 = MM_STAND; // STAND_PREV_MODE From c47da6f46ee8e4f4d886d3db333181978fcb9e9c Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 19 Dec 2023 16:11:56 +0100 Subject: [PATCH 075/596] use future coordinates to target enemies --- Source/monster.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 4a9f47bb0da..f11c02cba1e 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1353,7 +1353,7 @@ static void MonFindEnemy(int mnum) int enemy, dist, best_dist; bool sameroom, bestsameroom; MonsterStruct *mon = &monsters[mnum], *tmon; - const BYTE tv = dTransVal[mon->_mx][mon->_my]; + const BYTE tv = dTransVal[mon->_mfutx][mon->_mfuty]; int flags; BYTE x, y; @@ -1365,10 +1365,10 @@ static void MonFindEnemy(int mnum) if (!plx(i)._pActive || currLvl._dLevelIdx != plx(i)._pDunLevel || plx(i)._pInvincible/*plx(i)._pLvlChanging || plx(i)._pHitPoints < (1 << 6)*/) continue; - if (!LineClear(mon->_mx, mon->_my, plx(i)._px, plx(i)._py)) + if (!LineClear(mon->_mfutx, mon->_mfuty, plx(i)._pfutx, plx(i)._pfuty)) continue; - sameroom = tv == dTransVal[plx(i)._px][plx(i)._py]; - dist = std::max(abs(mon->_mx - plx(i)._px), abs(mon->_my - plx(i)._py)); + sameroom = tv == dTransVal[plx(i)._pfutx][plx(i)._pfuty]; + dist = std::max(abs(mon->_mfutx - plx(i)._pfutx), abs(mon->_mfuty - plx(i)._pfuty)); if (sameroom == bestsameroom) { if (dist > best_dist) continue; @@ -1388,10 +1388,10 @@ static void MonFindEnemy(int mnum) continue; if (tmon->_mhitpoints < (1 << 6)) continue; - if (!LineClear(mon->_mx, mon->_my, tmon->_mx, tmon->_my)) + if (!LineClear(mon->_mfutx, mon->_mfuty, tmon->_mfutx, tmon->_mfuty)) continue; - dist = std::max(abs(mon->_mx - tmon->_mx), abs(mon->_my - tmon->_my)); - sameroom = tv == dTransVal[tmon->_mx][tmon->_my]; + dist = std::max(abs(mon->_mfutx - tmon->_mfutx), abs(mon->_mfuty - tmon->_mfuty)); + sameroom = tv == dTransVal[tmon->_mfutx][tmon->_mfuty]; if (sameroom == bestsameroom) { if (dist > best_dist) continue; @@ -1416,12 +1416,12 @@ static void MonFindEnemy(int mnum) continue; if (CanTalkToMonst(tnum)) continue; - //if (!LineClear(mon->_mx, mon->_my, tmon->_mx, tmon->_my)) + //if (!LineClear(mon->_mfutx, mon->_mfuty, tmon->_mfutx, tmon->_mfuty)) // continue; - if (!(dFlags[tmon->_mx][tmon->_my] & BFLAG_ALERT)) + if (!(dFlags[tmon->_mfutx][tmon->_mfuty] & BFLAG_ALERT)) continue; - dist = std::max(abs(mon->_mx - tmon->_mx), abs(mon->_my - tmon->_my)); - sameroom = tv == dTransVal[tmon->_mx][tmon->_my]; + dist = std::max(abs(mon->_mfutx - tmon->_mfutx), abs(mon->_mfuty - tmon->_mfuty)); + sameroom = tv == dTransVal[tmon->_mfutx][tmon->_mfuty]; if (sameroom == bestsameroom) { if (dist > best_dist) continue; @@ -4391,7 +4391,7 @@ void ProcessMonsters() mon->_mhitpoints = mon->_mmaxhp; } - alert = (dFlags[mon->_mx][mon->_my] & BFLAG_ALERT) != 0; + alert = (dFlags[mon->_mfutx][mon->_mfuty] & BFLAG_ALERT) != 0; if (alert || MON_HAS_ENEMY) { MonFindEnemy(mnum); // commented out, because the player might went out of sight in the meantime @@ -4403,12 +4403,12 @@ void ProcessMonsters() mon->_mlasty = mon->_menemyy; if (mon->_msquelch == 0) { if (mon->_mType == MT_CLEAVER) - PlaySfxLoc(USFX_CLEAVER, mon->_mx, mon->_my); + PlaySfxLoc(USFX_CLEAVER, mon->_mfutx, mon->_mfuty); #ifdef HELLFIRE else if (mon->_mType == MT_NAKRUL) - PlaySfxLoc(quests[Q_JERSEY]._qactive != QUEST_NOTAVAIL ? USFX_NAKRUL6 : (quests[Q_NAKRUL]._qvar1 == QV_NAKRUL_BOOKOPEN ? USFX_NAKRUL4 : USFX_NAKRUL5), mon->_mx, mon->_my); + PlaySfxLoc(quests[Q_JERSEY]._qactive != QUEST_NOTAVAIL ? USFX_NAKRUL6 : (quests[Q_NAKRUL]._qvar1 == QV_NAKRUL_BOOKOPEN ? USFX_NAKRUL4 : USFX_NAKRUL5), mon->_mfutx, mon->_mfuty); else if (mon->_mType == MT_DEFILER) - PlaySfxLoc(USFX_DEFILER8, mon->_mx, mon->_my); + PlaySfxLoc(USFX_DEFILER8, mon->_mfutx, mon->_mfuty); #endif } mon->_msquelch = SQUELCH_MAX; From e0ea287d2d127ad8f46c19a123d72808d0f9dc19 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 19 Dec 2023 16:24:22 +0100 Subject: [PATCH 076/596] prevent monsters from targeting teleport destination --- Source/monster.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index f11c02cba1e..92eb687102f 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1365,10 +1365,17 @@ static void MonFindEnemy(int mnum) if (!plx(i)._pActive || currLvl._dLevelIdx != plx(i)._pDunLevel || plx(i)._pInvincible/*plx(i)._pLvlChanging || plx(i)._pHitPoints < (1 << 6)*/) continue; - if (!LineClear(mon->_mfutx, mon->_mfuty, plx(i)._pfutx, plx(i)._pfuty)) + if (plx(i)._pmode < PM_WALK || plx(i)._pmode > PM_WALK2) { + x = plx(i)._px; + y = plx(i)._py; + } else { + x = plx(i)._pfutx; + y = plx(i)._pfuty; + } + if (!LineClear(mon->_mfutx, mon->_mfuty, x, y)) continue; - sameroom = tv == dTransVal[plx(i)._pfutx][plx(i)._pfuty]; - dist = std::max(abs(mon->_mfutx - plx(i)._pfutx), abs(mon->_mfuty - plx(i)._pfuty)); + sameroom = tv == dTransVal[x][y]; + dist = std::max(abs(mon->_mfutx - x), abs(mon->_mfuty - y)); if (sameroom == bestsameroom) { if (dist > best_dist) continue; @@ -1441,8 +1448,13 @@ static void MonFindEnemy(int mnum) if (enemy != 0) { if (enemy > 0) { enemy--; - x = plx(enemy)._pfutx; - y = plx(enemy)._pfuty; + if (plx(enemy)._pmode < PM_WALK || plx(enemy)._pmode > PM_WALK2) { + x = plx(enemy)._px; + y = plx(enemy)._py; + } else { + x = plx(enemy)._pfutx; + y = plx(enemy)._pfuty; + } } else { enemy = -(enemy + 1); flags |= MFLAG_TARGETS_MONSTER; From 4b9b3caed797d1d38cbe71d17ef152290795b76d Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 19 Dec 2023 16:34:26 +0100 Subject: [PATCH 077/596] set _mlastx/y in MonFindEnemy --- Source/monster.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 92eb687102f..a32674186c5 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1462,6 +1462,8 @@ static void MonFindEnemy(int mnum) y = monsters[enemy]._mfuty; } mon->_menemy = enemy; + mon->_mlastx = x; + mon->_mlasty = y; } else { // flags |= MFLAG_NO_ENEMY; x = 0; @@ -3846,8 +3848,6 @@ void MAI_Golem(int mnum) if (MON_HAS_ENEMY) { MonEnemyInfo(mnum); if (currEnemyInfo._meRealDist >= 2) { - mon->_mlastx = mon->_menemyx; - mon->_mlasty = mon->_menemyy; if (MonDestWalk(mnum)) { return; } @@ -4411,8 +4411,6 @@ void ProcessMonsters() } if (alert) { if (MON_HAS_ENEMY) { - mon->_mlastx = mon->_menemyx; - mon->_mlasty = mon->_menemyy; if (mon->_msquelch == 0) { if (mon->_mType == MT_CLEAVER) PlaySfxLoc(USFX_CLEAVER, mon->_mfutx, mon->_mfuty); From 510fb9820b7f606984caa555e87acc40aff9acce Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 19 Dec 2023 16:44:24 +0100 Subject: [PATCH 078/596] use x/y locals in the loops of MonFindEnemy --- Source/monster.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index a32674186c5..005ae5468eb 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1354,8 +1354,7 @@ static void MonFindEnemy(int mnum) bool sameroom, bestsameroom; MonsterStruct *mon = &monsters[mnum], *tmon; const BYTE tv = dTransVal[mon->_mfutx][mon->_mfuty]; - int flags; - BYTE x, y; + int x, y, flags; enemy = 0; best_dist = MAXDUNX + MAXDUNY; @@ -1395,10 +1394,12 @@ static void MonFindEnemy(int mnum) continue; if (tmon->_mhitpoints < (1 << 6)) continue; - if (!LineClear(mon->_mfutx, mon->_mfuty, tmon->_mfutx, tmon->_mfuty)) + x = tmon->_mfutx; + y = tmon->_mfuty; + if (!LineClear(mon->_mfutx, mon->_mfuty, x, y)) continue; - dist = std::max(abs(mon->_mfutx - tmon->_mfutx), abs(mon->_mfuty - tmon->_mfuty)); - sameroom = tv == dTransVal[tmon->_mfutx][tmon->_mfuty]; + dist = std::max(abs(mon->_mfutx - x), abs(mon->_mfuty - y)); + sameroom = tv == dTransVal[x][y]; if (sameroom == bestsameroom) { if (dist > best_dist) continue; @@ -1423,12 +1424,14 @@ static void MonFindEnemy(int mnum) continue; if (CanTalkToMonst(tnum)) continue; - //if (!LineClear(mon->_mfutx, mon->_mfuty, tmon->_mfutx, tmon->_mfuty)) + x = tmon->_mfutx; + y = tmon->_mfuty; + //if (!LineClear(mon->_mfutx, mon->_mfuty, x, y)) // continue; - if (!(dFlags[tmon->_mfutx][tmon->_mfuty] & BFLAG_ALERT)) + if (!(dFlags[x][y] & BFLAG_ALERT)) continue; - dist = std::max(abs(mon->_mfutx - tmon->_mfutx), abs(mon->_mfuty - tmon->_mfuty)); - sameroom = tv == dTransVal[tmon->_mfutx][tmon->_mfuty]; + dist = std::max(abs(mon->_mfutx - x), abs(mon->_mfuty - y)); + sameroom = tv == dTransVal[x][y]; if (sameroom == bestsameroom) { if (dist > best_dist) continue; From 20b630fb5ba7b04c6b91257bd20c75dc3ce5f727 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 20 Dec 2023 09:00:48 +0100 Subject: [PATCH 079/596] call MonFindEnemy in GroupUnity unconditionally --- Source/monster.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 005ae5468eb..c10bf5b7276 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -2781,9 +2781,8 @@ static void GroupUnity(int mnum) bool clear; mon = &monsters[mnum]; - // track/update enemy if still active - if (mon->_msquelch != 0) - MonFindEnemy(mnum); + // track/update enemy + MonFindEnemy(mnum); // check if the leader is still available and update its squelch value + enemy location if (mon->_mleader != MON_NO_LEADER) { leader = &monsters[mon->_mleader]; From d908148cb0066e958ef8f43a7d40f0777fff000d Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 20 Dec 2023 09:31:56 +0100 Subject: [PATCH 080/596] optimize GroupUnity (and MonDirOK) --- Source/monster.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index c10bf5b7276..5df198ead9d 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -471,10 +471,10 @@ void InitLvlMonsters() monsters[i]._mNameColor = COL_WHITE; monsters[i]._mlid = NO_LIGHT; // reset _mleaderflag value to simplify GroupUnity - monsters[i]._mleader = MON_NO_LEADER; - monsters[i]._mleaderflag = MLEADER_NONE; - monsters[i]._mpacksize = 0; - monsters[i]._mvid = NO_VISION; + // monsters[i]._mleader = MON_NO_LEADER; + // monsters[i]._mleaderflag = MLEADER_NONE; + // monsters[i]._mpacksize = 0; + // monsters[i]._mvid = NO_VISION; } // reserve minions nummonsters = MAX_MINIONS; @@ -2777,7 +2777,7 @@ static void ActivateSpawn(int mnum, int x, int y, int dir) static void GroupUnity(int mnum) { MonsterStruct *mon, *leader, *bmon; - int i; + int ma; bool clear; mon = &monsters[mnum]; @@ -2808,9 +2808,11 @@ static void GroupUnity(int mnum) } // update squelch value + enemy location of the pack monsters if (mon->_mpacksize != 0) { - for (i = 0; i < MAXMONSTERS; i++) { - bmon = &monsters[i]; - if (bmon->_mleaderflag == MLEADER_PRESENT && bmon->_mleader == mnum) { + // assert(mnum + MON_PACK_SIZE <= MAXMONSTERS); + for (ma = mnum + 1; ma < mnum + MON_PACK_SIZE; ma++) { + // assert(monsters[ma]._mleader == mnum || monsters[ma]._mhitpoints == 0); + bmon = &monsters[ma]; + if (bmon->_mleaderflag == MLEADER_PRESENT/* && bmon->_mleader == mnum*/) { if (mon->_msquelch > bmon->_msquelch) { bmon->_mlastx = mon->_mlastx; // BUGFIX: use _mlastx instead of _mx (fixed) bmon->_mlasty = mon->_mlasty; // BUGFIX: use _mlasty instead of _my (fixed) @@ -2850,8 +2852,7 @@ static bool MonDirOK(int mnum, int mdir) // assert(mnum + MON_PACK_SIZE <= MAXMONSTERS); for (ma = mnum + 1; ma < mnum + MON_PACK_SIZE; ma++) { // assert(monsters[ma]._mleader == mnum || monsters[ma]._mhitpoints == 0); - if (monsters[ma]._mleaderflag == MLEADER_PRESENT - && monsters[ma]._mleader == mnum + if (monsters[ma]._mleaderflag == MLEADER_PRESENT/* && monsters[ma]._mleader == mnum*/ && abs(fx - monsters[ma]._mfutx) <= MON_PACK_DISTANCE && abs(fy - monsters[ma]._mfuty) <= MON_PACK_DISTANCE) { mcount--; From 7e8f7c18cbd8de5d3b0caba068f7692ec1591fa4 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 20 Dec 2023 09:34:27 +0100 Subject: [PATCH 081/596] update enemy even if the monster has already one (but prefer the original target) II. --- Source/monster.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 5df198ead9d..d69b699ba37 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -670,7 +670,7 @@ void InitMonster(int mnum, int dir, int mtidx, int x, int y) //mon->_mgoalvar1 = 0; -- should be set before use //mon->_mgoalvar2 = 0; //mon->_mgoalvar3 = 0; - //mon->_menemy = 0; -- should be set before use + mon->_menemy = 0; mon->_menemyx = 0; mon->_menemyy = 0; mon->_mListener = 0; From dba8d7c87eac9d00425428b865d96a59bf1e7a3c Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 20 Dec 2023 09:58:07 +0100 Subject: [PATCH 082/596] update documentation of PlayerStruct and MonsterStruct --- Source/msg.cpp | 52 ++++++++++---------- structs.h | 128 ++++++++++++++++++++++++------------------------- 2 files changed, 90 insertions(+), 90 deletions(-) diff --git a/Source/msg.cpp b/Source/msg.cpp index 03b5b20b026..723433ef617 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -1248,8 +1248,8 @@ void LevelDeltaExport() tplr->spfuty = plr._pfuty; tplr->spoldx = plr._poldx; tplr->spoldy = plr._poldy; - //LE_INT32 spxoff; // Player sprite's pixel X-offset from tile. - //LE_INT32 spyoff; // Player sprite's pixel Y-offset from tile. + //tplr->spxoff = plr._pxoff; + //tplr->spyoff = plr._pyoff; tplr->spdir = plr._pdir; tplr->spAnimFrame = plr._pAnimFrame; tplr->spAnimCnt = plr._pAnimCnt; @@ -1285,37 +1285,37 @@ void LevelDeltaExport() tmon->smGoalvar1 = mon->_mgoalvar1; tmon->smGoalvar2 = mon->_mgoalvar2; tmon->smGoalvar3 = mon->_mgoalvar3; - tmon->smx = mon->_mx; // Tile X-position of monster - tmon->smy = mon->_my; // Tile Y-position of monster - tmon->smfutx = mon->_mfutx; // Future tile X-position of monster. Set at start of walking animation - tmon->smfuty = mon->_mfuty; // Future tile Y-position of monster. Set at start of walking animation - tmon->smoldx = mon->_moldx; // Most recent X-position in dMonster. - tmon->smoldy = mon->_moldy; // Most recent Y-position in dMonster. - //tmon->smxoff; // Monster sprite's pixel X-offset from tile. - //tmon->smyoff; // Monster sprite's pixel Y-offset from tile. - tmon->smdir = mon->_mdir; // Direction faced by monster (direction enum) - tmon->smEnemy = mon->_menemy; // The current target of the monster. An index in to either the plr or monster array based on the _meflag value. - tmon->smEnemyx = mon->_menemyx; // X-coordinate of enemy (usually correspond's to the enemy's futx value) - tmon->smEnemyy = mon->_menemyy; // Y-coordinate of enemy (usually correspond's to the enemy's futy value) - tmon->smListener = mon->_mListener; // the player to whom the monster is talking to - tmon->smAnimCnt = mon->_mAnimCnt; // Increases by one each game tick, counting how close we are to _mAnimFrameLen - tmon->smAnimFrame = mon->_mAnimFrame; // Current frame of animation. - // assert(!mon->_mDelFlag || mon->_mmode == MM_STONE); + tmon->smx = mon->_mx; + tmon->smy = mon->_my; + tmon->smfutx = mon->_mfutx; + tmon->smfuty = mon->_mfuty; + tmon->smoldx = mon->_moldx; + tmon->smoldy = mon->_moldy; + //tmon->smxoff = mon->_mxoff; + //tmon->smyoff = mon->_myoff; + tmon->smdir = mon->_mdir; + tmon->smEnemy = mon->_menemy; + tmon->smEnemyx = mon->_menemyx; + tmon->smEnemyy = mon->_menemyy; + tmon->smListener = mon->_mListener; tmon->smDelFlag = mon->_mDelFlag; // unused + tmon->smAnimCnt = mon->_mAnimCnt; + tmon->smAnimFrame = mon->_mAnimFrame; + // assert(!mon->_mDelFlag || mon->_mmode == MM_STONE); tmon->smVar1 = mon->_mVar1; tmon->smVar2 = mon->_mVar2; tmon->smVar3 = mon->_mVar3; tmon->smVar4 = mon->_mVar4; tmon->smVar5 = mon->_mVar5; - tmon->smVar6 = mon->_mVar6; // Used as _mxoff but with a higher range so that we can correctly apply velocities of a smaller number - tmon->smVar7 = mon->_mVar7; // Used as _myoff but with a higher range so that we can correctly apply velocities of a smaller number - tmon->smVar8 = mon->_mVar8; // Value used to measure progress for moving from one tile to another + tmon->smVar6 = mon->_mVar6; + tmon->smVar7 = mon->_mVar7; + tmon->smVar8 = mon->_mVar8; tmon->smHitpoints = mon->_mhitpoints; - tmon->smLastx = mon->_mlastx; // the last known X-coordinate of the enemy - tmon->smLasty = mon->_mlasty; // the last known Y-coordinate of the enemy - //tmon->smLeader = mon->_mleader; // the leader of the monster - tmon->smLeaderflag = mon->_mleaderflag; // the status of the monster's leader - //tmon->smPacksize = mon->_mpacksize; // the number of 'pack'-monsters close to their leader + tmon->smLastx = mon->_mlastx; + tmon->smLasty = mon->_mlasty; + //tmon->smLeader = mon->_mleader; + tmon->smLeaderflag = mon->_mleaderflag; + //tmon->smPacksize = mon->_mpacksize; //BYTE falign_CB; tmon->smFlags = mon->_mFlags; diff --git a/structs.h b/structs.h index 23a634b7aef..5756292f1f6 100644 --- a/structs.h +++ b/structs.h @@ -315,18 +315,18 @@ typedef struct PlayerStruct { int16_t _pTimer[NUM_PLRTIMERS]; unsigned _pExperience; unsigned _pNextExper; - int _px; // Tile X-position of player - int _py; // Tile Y-position of player - int _pfutx; // Future tile X-position of player. Set at start of walking animation - int _pfuty; // Future tile Y-position of player. Set at start of walking animation - int _poldx; // Most recent X-position in dPlayer. - int _poldy; // Most recent Y-position in dPlayer. - int _pxoff; // Player sprite's pixel X-offset from tile. - int _pyoff; // Player sprite's pixel Y-offset from tile. + int _px; // Tile X-position where the player should be drawn + int _py; // Tile Y-position where the player should be drawn + int _pfutx; // Future tile X-position where the player will be at the end of its action + int _pfuty; // Future tile Y-position where the player will be at the end of its action + int _poldx; // Most recent tile X-position where the player was at the start of its action + int _poldy; // Most recent tile Y-position where the player was at the start of its action + int _pxoff; // Pixel X-offset from tile X-position where the player should be drawn + int _pyoff; // Pixel Y-offset from tile Y-position where the player should be drawn int _pdir; // Direction faced by player (direction enum) BYTE* _pAnimData; int _pAnimFrameLen; // Tick length of each frame in the current animation - int _pAnimCnt; // Increases by one each game tick, counting how close we are to _pAnimFrameLen + int _pAnimCnt; // Increases by one each game tick, counting how close we are to _pAnimFrameLen unsigned _pAnimLen; // Number of frames in current animation unsigned _pAnimFrame; // Current frame of animation. int _pAnimWidth; @@ -685,7 +685,7 @@ static_assert((sizeof(MapMonData) & (sizeof(MapMonData) - 1)) == 512, "Align Map #endif #pragma pack(pop) typedef struct MonsterStruct { - int _mmode; /* MON_MODE */ + int _mmode; // MON_MODE unsigned _msquelch; BYTE _mMTidx; BYTE _mpathcount; // unused @@ -694,19 +694,19 @@ typedef struct MonsterStruct { int _mgoalvar1; int _mgoalvar2; int _mgoalvar3; - int _mx; // Tile X-position of monster - int _my; // Tile Y-position of monster - int _mfutx; // Future tile X-position of monster. Set at start of walking animation - int _mfuty; // Future tile Y-position of monster. Set at start of walking animation - int _moldx; // Most recent X-position in dMonster. - int _moldy; // Most recent Y-position in dMonster. - int _mxoff; // Monster sprite's pixel X-offset from tile. - int _myoff; // Monster sprite's pixel Y-offset from tile. - int _mdir; // Direction faced by monster (direction enum) - int _menemy; // The current target of the monster. An index in to either the plr or monster array based on the _meflag value. - BYTE _menemyx; // X-coordinate of enemy (usually correspond's to the enemy's futx value) - BYTE _menemyy; // Y-coordinate of enemy (usually correspond's to the enemy's futy value) - BYTE _mListener; // the player to whom the monster is talking to (unused) + int _mx; // Tile X-position where the monster should be drawn + int _my; // Tile Y-position where the monster should be drawn + int _mfutx; // Future tile X-position where the monster will be at the end of its action + int _mfuty; // Future tile Y-position where the monster will be at the end of its action + int _moldx; // Most recent tile X-position where the monster was at the start of its action + int _moldy; // Most recent tile Y-position where the monster was at the start of its action + int _mxoff; // Pixel X-offset from tile X-position where the monster should be drawn + int _myoff; // Pixel Y-offset from tile Y-position where the monster should be drawn + int _mdir; // Direction faced by monster (direction enum) + int _menemy; // The current target of the monster. An index in to either the plr or monster array depending on _mFlags (MFLAG_TARGETS_MONSTER) + BYTE _menemyx; // Future (except for teleporting) tile X-coordinate of the enemy + BYTE _menemyy; // Future (except for teleporting) tile Y-coordinate of the enemy + BYTE _mListener; // the player to whom the monster is talking to (unused) BOOLEAN _mDelFlag; // unused BYTE* _mAnimData; int _mAnimFrameLen; // Tick length of each frame in the current animation @@ -718,23 +718,23 @@ typedef struct MonsterStruct { int _mVar3; // Used to store the original mode of a stoned monster. Not 'thread' safe -> do not use for anything else! int _mVar4; int _mVar5; - int _mVar6; // Used as _mxoff but with a higher range so that we can correctly apply velocities of a smaller number - int _mVar7; // Used as _myoff but with a higher range so that we can correctly apply velocities of a smaller number - int _mVar8; // Value used to measure progress for moving from one tile to another + int _mVar6; + int _mVar7; + int _mVar8; int _mmaxhp; int _mhitpoints; - int _mlastx; // the last known X-coordinate of the enemy - int _mlasty; // the last known Y-coordinate of the enemy + int _mlastx; // the last known (future) tile X-coordinate of the enemy + int _mlasty; // the last known (future) tile Y-coordinate of the enemy int _mRndSeed; int _mAISeed; BYTE _muniqtype; BYTE _muniqtrans; - BYTE _mNameColor; // color of the tooltip. white: normal, blue: pack; gold: unique. (text_color) - BYTE _mlid; // light id of the monster - BYTE _mleader; // the leader of the monster + BYTE _mNameColor; // color of the tooltip. white: normal, blue: pack; gold: unique. (text_color) + BYTE _mlid; // light id of the monster + BYTE _mleader; // the leader of the monster BYTE _mleaderflag; // the status of the monster's leader - BYTE _mpacksize; // the number of 'pack'-monsters close to their leader - BYTE _mvid; // vision id of the monster (for minions only) + BYTE _mpacksize; // the number of 'pack'-monsters close to their leader + BYTE _mvid; // vision id of the monster (for minions only) const char* _mName; uint16_t _mFileNum; // _monster_gfx_id BYTE _mLevel; @@ -1262,14 +1262,14 @@ typedef struct LSavePlayerStruct { LE_INT16 vpTimer[NUM_PLRTIMERS]; LE_UINT32 vpExperience; LE_UINT32 vpNextExper; - LE_INT32 vpx; // Tile X-position of player - LE_INT32 vpy; // Tile Y-position of player - LE_INT32 vpfutx; // Future tile X-position of player. Set at start of walking animation - LE_INT32 vpfuty; // Future tile Y-position of player. Set at start of walking animation - LE_INT32 vpoldx; // Most recent X-position in dPlayer. - LE_INT32 vpoldy; // Most recent Y-position in dPlayer. - LE_INT32 vpxoff; // Player sprite's pixel X-offset from tile. - LE_INT32 vpyoff; // Player sprite's pixel Y-offset from tile. + LE_INT32 vpx; // Tile X-position where the player should be drawn + LE_INT32 vpy; // Tile Y-position where the player should be drawn + LE_INT32 vpfutx; // Future tile X-position where the player will be at the end of its action + LE_INT32 vpfuty; // Future tile Y-position where the player will be at the end of its action + LE_INT32 vpoldx; // Most recent tile X-position where the player was at the start of its action + LE_INT32 vpoldy; // Most recent tile Y-position where the player was at the start of its action + LE_INT32 vpxoff; // Pixel X-offset from tile X-position where the player should be drawn + LE_INT32 vpyoff; // Pixel Y-offset from tile Y-position where the player should be drawn LE_INT32 vpdir; // Direction faced by player (direction enum) INT vpAnimDataAlign; INT vpAnimFrameLenAlign; // Tick length of each frame in the current animation @@ -1339,7 +1339,7 @@ typedef struct LSavePlayerStruct { } LSavePlayerStruct; typedef struct LSaveMonsterStruct { - LE_INT32 vmmode; /* MON_MODE */ + LE_INT32 vmmode; // MON_MODE LE_UINT32 vmsquelch; BYTE vmMTidx; BYTE vmpathcount; // unused @@ -1348,18 +1348,18 @@ typedef struct LSaveMonsterStruct { LE_INT32 vmgoalvar1; LE_INT32 vmgoalvar2; LE_INT32 vmgoalvar3; - LE_INT32 vmx; // Tile X-position of monster - LE_INT32 vmy; // Tile Y-position of monster - LE_INT32 vmfutx; // Future tile X-position of monster. Set at start of walking animation - LE_INT32 vmfuty; // Future tile Y-position of monster. Set at start of walking animation - LE_INT32 vmoldx; // Most recent X-position in dMonster. - LE_INT32 vmoldy; // Most recent Y-position in dMonster. - LE_INT32 vmxoff; // Monster sprite's pixel X-offset from tile. - LE_INT32 vmyoff; // Monster sprite's pixel Y-offset from tile. + LE_INT32 vmx; // Tile X-position where the monster should be drawn + LE_INT32 vmy; // Tile Y-position where the monster should be drawn + LE_INT32 vmfutx; // Future tile X-position where the monster will be at the end of its action + LE_INT32 vmfuty; // Future tile Y-position where the monster will be at the end of its action + LE_INT32 vmoldx; // Most recent tile X-position where the monster was at the start of its action + LE_INT32 vmoldy; // Most recent tile Y-position where the monster was at the start of its action + LE_INT32 vmxoff; // Pixel X-offset from tile X-position where the monster should be drawn + LE_INT32 vmyoff; // Pixel Y-offset from tile X-position where the monster should be drawn LE_INT32 vmdir; // Direction faced by monster (direction enum) - LE_INT32 vmenemy; // The current target of the monster. An index in to either the plr or monster array based on the vmeflag value. - BYTE vmenemyx; // X-coordinate of enemy (usually correspond's to the enemy's futx value) - BYTE vmenemyy; // Y-coordinate of enemy (usually correspond's to the enemy's futy value) + LE_INT32 vmenemy; // The current target of the monster. An index in to either the plr or monster array depending on _mFlags (MFLAG_TARGETS_MONSTER) + BYTE vmenemyx; // Future (except for teleporting) tile X-coordinate of the enemy + BYTE vmenemyy; // Future (except for teleporting) tile Y-coordinate of the enemy BYTE vmListener; // the player to whom the monster is talking to (unused) BOOLEAN vmDelFlag; // unused INT vmAnimDataAlign; @@ -1372,23 +1372,23 @@ typedef struct LSaveMonsterStruct { LE_INT32 vmVar3; // Used to store the original mode of a stoned monster. Not 'thread' safe -> do not use for anything else! LE_INT32 vmVar4; LE_INT32 vmVar5; - LE_INT32 vmVar6; // Used as _mxoff but with a higher range so that we can correctly apply velocities of a smaller number - LE_INT32 vmVar7; // Used as _myoff but with a higher range so that we can correctly apply velocities of a smaller number - LE_INT32 vmVar8; // Value used to measure progress for moving from one tile to another + LE_INT32 vmVar6; + LE_INT32 vmVar7; + LE_INT32 vmVar8; LE_INT32 vmmaxhp; LE_INT32 vmhitpoints; - LE_INT32 vmlastx; // the last known X-coordinate of the enemy - LE_INT32 vmlasty; // the last known Y-coordinate of the enemy + LE_INT32 vmlastx; // the last known (future) tile X-coordinate of the enemy + LE_INT32 vmlasty; // the last known (future) tile Y-coordinate of the enemy LE_INT32 vmRndSeed; LE_INT32 vmAISeed; BYTE vmuniqtype; BYTE vmuniqtrans; - BYTE vmNameColor; - BYTE vmlid; - BYTE vmleader; // the leader of the monster + BYTE vmNameColor; // color of the tooltip. white: normal, blue: pack; gold: unique. (text_color) + BYTE vmlid; // light id of the monster + BYTE vmleader; // the leader of the monster BYTE vmleaderflag; // the status of the monster's leader - BYTE vmpacksize; // the number of 'pack'-monsters close to their leader - BYTE vmvid; // vision id of the monster (for minions only) + BYTE vmpacksize; // the number of 'pack'-monsters close to their leader + BYTE vmvid; // vision id of the monster (for minions only) INT vmNameAlign; LE_UINT16 vmFileNum; BYTE vmLevel; @@ -1407,7 +1407,7 @@ typedef struct LSaveMonsterStruct { LE_INT32 vmMagic; // hit chance of magic-projectile LE_INT32 vmArmorClass; // AC+evasion: used against physical-hit (melee+projectile) LE_INT32 vmEvasion; // evasion: used against magic-projectile - LE_UINT32 vmMagicRes; // resistances of the monster + LE_UINT32 vmMagicRes; // resistances of the monster (_monster_resistance) LE_UINT32 vmExp; } LSaveMonsterStruct; From 02177a11a1eea4e6a8d9015d64c5c01a91bfb45a Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 20 Dec 2023 10:28:52 +0100 Subject: [PATCH 083/596] update documentation of MissileStruct --- Source/msg.cpp | 30 +++++++++++++++--------------- structs.h | 40 ++++++++++++++++++++-------------------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/Source/msg.cpp b/Source/msg.cpp index 723433ef617..62448c8ed0b 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -1329,7 +1329,7 @@ void LevelDeltaExport() //assert(!mis->_miDelFlag); TSyncLvlMissile* DVL_RESTRICT tmis = (TSyncLvlMissile*)dst; tmis->smiMi = static_cast(mi + MAXMONSTERS); - tmis->smiType = mis->_miType; // Type of projectile (MIS_*) + tmis->smiType = mis->_miType; //BYTE _miFlags; //BYTE _miResist; tmis->smiFileNum = mis->_miFileNum; @@ -1344,20 +1344,20 @@ void LevelDeltaExport() //int _miAnimLen; //int _miAnimWidth; //int _miAnimXOffset; - tmis->smiAnimCnt = mis->_miAnimCnt; // Increases by one each game tick, counting how close we are to _miAnimFrameLen - tmis->smiAnimAdd = mis->_miAnimAdd; // - tmis->smiAnimFrame = mis->_miAnimFrame; // Current frame of animation. - tmis->smiDir = mis->_miDir; // The direction of the missile - tmis->smisx = mis->_misx; // Initial tile X-position for missile - tmis->smisy = mis->_misy; // Initial tile Y-position for missile - tmis->smix = mis->_mix; // Tile X-position of the missile - tmis->smiy = mis->_miy; // Tile Y-position of the missile - tmis->smixoff = mis->_mixoff; // Sprite pixel X-offset for the missile - tmis->smiyoff = mis->_miyoff; // Sprite pixel Y-offset for the missile - tmis->smixvel = mis->_mixvel; // Missile tile X-velocity while walking. This gets added onto _mitxoff each game tick - tmis->smiyvel = mis->_miyvel; // Missile tile Y-velocity while walking. This gets added onto _mitxoff each game tick - tmis->smitxoff = mis->_mitxoff; // How far the missile has travelled in its lifespan along the X-axis. mix/miy/mxoff/myoff get updated every game tick based on this - tmis->smityoff = mis->_mityoff; // How far the missile has travelled in its lifespan along the Y-axis. mix/miy/mxoff/myoff get updated every game tick based on this + tmis->smiAnimCnt = mis->_miAnimCnt; + tmis->smiAnimAdd = mis->_miAnimAdd; + tmis->smiAnimFrame = mis->_miAnimFrame; + tmis->smiDir = mis->_miDir; + tmis->smisx = mis->_misx; + tmis->smisy = mis->_misy; + tmis->smix = mis->_mix; + tmis->smiy = mis->_miy; + tmis->smixoff = mis->_mixoff; + tmis->smiyoff = mis->_miyoff; + tmis->smixvel = mis->_mixvel; + tmis->smiyvel = mis->_miyvel; + tmis->smitxoff = mis->_mitxoff; + tmis->smityoff = mis->_mityoff; // smiDir/_miDir reordered for better alignment tmis->smiSpllvl = mis->_miSpllvl; // int? tmis->smiSource = mis->_miSource; // int? diff --git a/structs.h b/structs.h index 5756292f1f6..e923e64c0a4 100644 --- a/structs.h +++ b/structs.h @@ -516,16 +516,16 @@ typedef struct MissileStruct { int _miAnimCnt; // Increases by one each game tick, counting how close we are to _miAnimFrameLen int _miAnimAdd; int _miAnimFrame; // Current frame of animation. - int _misx; // Initial tile X-position for missile - int _misy; // Initial tile Y-position for missile - int _mix; // Tile X-position of the missile - int _miy; // Tile Y-position of the missile - int _mixoff; // Sprite pixel X-offset for the missile - int _miyoff; // Sprite pixel Y-offset for the missile - int _mixvel; // Missile tile X-velocity while walking. This gets added onto _mitxoff each game tick - int _miyvel; // Missile tile Y-velocity while walking. This gets added onto _mitxoff each game tick - int _mitxoff; // How far the missile has travelled in its lifespan along the X-axis. mix/miy/mxoff/myoff get updated every game tick based on this - int _mityoff; // How far the missile has travelled in its lifespan along the Y-axis. mix/miy/mxoff/myoff get updated every game tick based on this + int _misx; // Initial tile X-position + int _misy; // Initial tile Y-position + int _mix; // Tile X-position where the missile should be drawn + int _miy; // Tile Y-position where the missile should be drawn + int _mixoff; // Pixel X-offset from tile X-position where the missile should be drawn + int _miyoff; // Pixel Y-offset from tile Y-position where the missile should be drawn + int _mixvel; // Missile tile (X - Y)-velocity while moving. This gets added onto _mitxoff each game tick + int _miyvel; // Missile tile (X + Y)-velocity while moving. This gets added onto _mityoff each game tick + int _mitxoff; // How far the missile has travelled in its lifespan along the (X - Y)-axis. mix/miy/mxoff/myoff get updated every game tick based on this + int _mityoff; // How far the missile has travelled in its lifespan along the (X + Y)-axis. mix/miy/mxoff/myoff get updated every game tick based on this int _miDir; // The direction of the missile int _miSpllvl; int _miSource; // missile_source_type @@ -1430,16 +1430,16 @@ typedef struct LSaveMissileStruct { LE_INT32 vmiAnimCnt; // Increases by one each game tick, counting how close we are to vmiAnimFrameLen LE_INT32 vmiAnimAdd; LE_INT32 vmiAnimFrame; // Current frame of animation. - LE_INT32 vmisx; // Initial tile X-position for missile - LE_INT32 vmisy; // Initial tile Y-position for missile - LE_INT32 vmix; // Tile X-position of the missile - LE_INT32 vmiy; // Tile Y-position of the missile - LE_INT32 vmixoff; // Sprite pixel X-offset for the missile - LE_INT32 vmiyoff; // Sprite pixel Y-offset for the missile - LE_INT32 vmixvel; // Missile tile X-velocity while walking. This gets added onto vmitxoff each game tick - LE_INT32 vmiyvel; // Missile tile Y-velocity while walking. This gets added onto vmitxoff each game tick - LE_INT32 vmitxoff; // How far the missile has travelled in its lifespan along the X-axis. mix/miy/mxoff/myoff get updated every game tick based on this - LE_INT32 vmityoff; // How far the missile has travelled in its lifespan along the Y-axis. mix/miy/mxoff/myoff get updated every game tick based on this + LE_INT32 vmisx; // Initial tile X-position + LE_INT32 vmisy; // Initial tile Y-position + LE_INT32 vmix; // Tile X-position where the missile should be drawn + LE_INT32 vmiy; // Tile Y-position where the missile should be drawn + LE_INT32 vmixoff; // Pixel X-offset from tile X-position where the missile should be drawn + LE_INT32 vmiyoff; // Pixel Y-offset from tile Y-position where the missile should be drawn + LE_INT32 vmixvel; // Missile tile (X - Y)-velocity while moving. This gets added onto _mitxoff each game tick + LE_INT32 vmiyvel; // Missile tile (X + Y)-velocity while moving. This gets added onto _mityoff each game tick + LE_INT32 vmitxoff; // How far the missile has travelled in its lifespan along the (X - Y)-axis. mix/miy/mxoff/myoff get updated every game tick based on this + LE_INT32 vmityoff; // How far the missile has travelled in its lifespan along the (X + Y)-axis. mix/miy/mxoff/myoff get updated every game tick based on this LE_INT32 vmiDir; // The direction of the missile LE_INT32 vmiSpllvl; LE_INT32 vmiSource; // missile_source_type From 252e37992b65fdd005b2e4b4414ee191a78863b0 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 20 Dec 2023 12:05:39 +0100 Subject: [PATCH 084/596] add MonStopWalk to stop walking monsters when hit or knocked back III. - fix walking NBATs --- Source/monster.cpp | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index d69b699ba37..61560cd8b6a 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1834,7 +1834,6 @@ static void MonStartGetHit(int mnum) // assert(mon->_mmode != MM_DEATH && mon->_mmode != MM_STONE && mon->_mType != MT_GOLEM); - MonStopWalk(mnum); AssertFixMonLocation(mnum); NewMonsterAnim(mnum, MA_GOTHIT, mon->_mdir); @@ -1845,27 +1844,30 @@ static void MonStartGetHit(int mnum) static void MonTeleport(int mnum, int tx, int ty) { MonsterStruct* mon; - int i, x, y, rx; + int i, oldx, oldy, newx, newy, rx; mon = &monsters[mnum]; - //assert(mon->_mmode != MM_STONE); + // assert(mon->_mmode != MM_DEATH && mon->_mmode != MM_STONE); + AssertFixMonLocation(mnum); + oldx = mon->_mx; + oldy = mon->_my; rx = random_(100, NUM_DIRS); static_assert(DBORDERX >= 1, "MonTeleport expects a large enough border I."); static_assert(DBORDERY >= 1, "MonTeleport expects a large enough border II."); for (i = 0; i < lengthof(offset_x); i++, rx = (rx + 1) & 7) { - x = tx + offset_x[rx]; - y = ty + offset_y[rx]; - assert(IN_DUNGEON_AREA(x, y)); - if (x != mon->_mx && y != mon->_my && PosOkMonst(mnum, x, y)) { - mon->_mx = x; - mon->_my = y; + newx = tx + offset_x[rx]; + newy = ty + offset_y[rx]; + assert(IN_DUNGEON_AREA(newx, newy)); + if (newx != oldx && newy != oldy && PosOkMonst(mnum, newx, newy)) { + mon->_mx = newx; + mon->_my = newy; + assert(OPPOSITE(rx) == GetDirection(newx, newy, tx, ty)); mon->_mdir = OPPOSITE(rx); - mon->_mmode = MM_STAND; // prevent overwrite of mx/y from MonStopWalk - // RemoveMonFromMap(mnum); - // MonPlace(mnum); + RemoveMonFromMap(mnum); + MonPlace(mnum); MonLeaveLeader(mnum); - return; + break; } } } @@ -1952,6 +1954,7 @@ void MonStartPlrHit(int mnum, int pnum, int dam, unsigned hitflags, int sx, int if (hitflags & ISPL_KNOCKBACK) MonGetKnockback(mnum, sx, sy); if ((dam << ((hitflags & ISPL_STUN) ? 3 : 2)) >= mon->_mmaxhp) { + MonStopWalk(mnum); mon->_mdir = OPPOSITE(plr._pdir); if (mon->_mType == MT_NBAT) MonTeleport(mnum, plr._pfutx, plr._pfuty); @@ -1987,6 +1990,7 @@ void MonStartMonHit(int defm, int offm, int dam) // 1. Golems -> other monsters. TODO: implement? // 2. other monsters -> golems. assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_CAN_BLEED)); if ((dam << 2) >= dmon->_mmaxhp) { + MonStopWalk(defm); if (offm >= 0) { dmon->_mdir = OPPOSITE(monsters[offm]._mdir); if (dmon->_mType == MT_NBAT) From 6889d1e78a898d9ca1573249dfdcc90eceef27bc Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 20 Dec 2023 12:14:58 +0100 Subject: [PATCH 085/596] update enemy even if the monster has already one (but prefer the original target) III. - fix _menemyy check of golems --- Source/monster.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 61560cd8b6a..7284d4057fc 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1436,7 +1436,7 @@ static void MonFindEnemy(int mnum) if (dist > best_dist) continue; if (dist == best_dist) { - if (mon->_menemyy != i/* || !(mon->_mFlags & (MFLAG_TARGETS_MONSTER))*/) + if (mon->_menemyy != tnum/* || !(mon->_mFlags & (MFLAG_TARGETS_MONSTER))*/) continue; } } else if (!sameroom) From 325a682b74274ed310b27bf23ecb70c88058e702 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 20 Dec 2023 12:20:24 +0100 Subject: [PATCH 086/596] use _mAnimLen/_pAnimLen instead of *Anims.*aFrames --- Source/missiles.cpp | 9 ++++++--- Source/monster.cpp | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 65f2ab9c799..58cb957abd8 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -1297,7 +1297,8 @@ int CheckMonCol(int mnum) static_assert(MM_WALK + 1 == MM_WALK2, "CheckMonCol expects ordered MM_WALKs."); if (mode > MM_WALK2 || mode < MM_WALK) return (negate || mode == MM_STONE) ? mnum : -1; - halfOver = mon->_mAnimFrame > (mon->_mAnims[MA_WALK].maFrames >> 1); + // assert(mon->_mAnims[MA_WALK].maFrames == mon->_mAnimLen); + halfOver = mon->_mAnimFrame > (mon->_mAnimLen >> 1); if (mode == MM_WALK) { if (negate) halfOver = !halfOver; @@ -1327,7 +1328,8 @@ int CheckPlrCol(int pnum) static_assert(PM_WALK + 1 == PM_WALK2, "CheckPlrCol expects ordered PM_WALKs."); if (mode > PM_WALK2 || mode < PM_WALK) return negate ? pnum : -1; - halfOver = plr._pAnimFrame > (plr._pAnims[PGX_WALK].paFrames >> 1); + // assert(plr._pAnims[PGX_WALK].paFrames == plr._pAnimLen); + halfOver = plr._pAnimFrame > (plr._pAnimLen >> 1); if (mode == PM_WALK) { if (negate) halfOver = !halfOver; @@ -3318,7 +3320,8 @@ int AddApocaC2(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, for (pnum = 0; pnum < MAX_PLRS; pnum++) { if (!plr._pActive || plr._pDunLevel != currLvl._dLevelIdx) continue; // skip player if not on the current level - if (plr._pAnimFrame > (plr._pAnims[PGX_WALK].paFrames >> 1)) { + // assert(plr._pAnims[PGX_WALK].paFrames == plr._mAnimLen); + if (plr._pAnimFrame > (plr._pAnimLen >> 1)) { px = plr._pfutx; py = plr._pfuty; } else { diff --git a/Source/monster.cpp b/Source/monster.cpp index 7284d4057fc..f9a18aa8615 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1813,7 +1813,8 @@ static void MonStopWalk(int mnum) if (mon->_mmode < MM_WALK || mon->_mmode > MM_WALK2) return; - if (mon->_mAnimFrame > (mon->_mAnims[MA_WALK].maFrames >> 1)) { + // assert(mon->_mAnims[MA_WALK].maFrames == mon->_mAnimLen); + if (mon->_mAnimFrame > (mon->_mAnimLen >> 1)) { x = mon->_mfutx; y = mon->_mfuty; } else { From fa6935b4516db887a460ca295ec97894f4534dac Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 20 Dec 2023 13:06:28 +0100 Subject: [PATCH 087/596] use future coordinates to target enemies II. - prevent reacting too early to walking enemies - always select the future coordinates --- Source/monster.cpp | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index f9a18aa8615..ad81db14303 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1364,7 +1364,7 @@ static void MonFindEnemy(int mnum) if (!plx(i)._pActive || currLvl._dLevelIdx != plx(i)._pDunLevel || plx(i)._pInvincible/*plx(i)._pLvlChanging || plx(i)._pHitPoints < (1 << 6)*/) continue; - if (plx(i)._pmode < PM_WALK || plx(i)._pmode > PM_WALK2) { + if ((plx(i)._pmode < PM_WALK || plx(i)._pmode > PM_WALK2) || plx(i)._pAnimFrame <= (plx(i)._pAnimLen >> 1)) { x = plx(i)._px; y = plx(i)._py; } else { @@ -1394,8 +1394,13 @@ static void MonFindEnemy(int mnum) continue; if (tmon->_mhitpoints < (1 << 6)) continue; - x = tmon->_mfutx; - y = tmon->_mfuty; + if ((tmon->_mmode < MM_WALK || tmon->_mmode > MM_WALK2) || tmon->_mAnimFrame <= (tmon->_mAnimLen >> 1)) { + x = tmon->_mx; + y = tmon->_my; + } else { + x = tmon->_mfutx; + y = tmon->_mfuty; + } if (!LineClear(mon->_mfutx, mon->_mfuty, x, y)) continue; dist = std::max(abs(mon->_mfutx - x), abs(mon->_mfuty - y)); @@ -1424,8 +1429,13 @@ static void MonFindEnemy(int mnum) continue; if (CanTalkToMonst(tnum)) continue; - x = tmon->_mfutx; - y = tmon->_mfuty; + if ((tmon->_mmode < MM_WALK || tmon->_mmode > MM_WALK2) || tmon->_mAnimFrame <= (tmon->_mAnimLen >> 1)) { + x = tmon->_mx; + y = tmon->_my; + } else { + x = tmon->_mfutx; + y = tmon->_mfuty; + } //if (!LineClear(mon->_mfutx, mon->_mfuty, x, y)) // continue; if (!(dFlags[x][y] & BFLAG_ALERT)) @@ -1451,13 +1461,8 @@ static void MonFindEnemy(int mnum) if (enemy != 0) { if (enemy > 0) { enemy--; - if (plx(enemy)._pmode < PM_WALK || plx(enemy)._pmode > PM_WALK2) { - x = plx(enemy)._px; - y = plx(enemy)._py; - } else { - x = plx(enemy)._pfutx; - y = plx(enemy)._pfuty; - } + x = plx(enemy)._pfutx; + y = plx(enemy)._pfuty; } else { enemy = -(enemy + 1); flags |= MFLAG_TARGETS_MONSTER; From d1eb9d6a1fbd6fccfeabd320b3862fc1c1695e51 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 21 Dec 2023 11:30:16 +0100 Subject: [PATCH 088/596] bugfix for vanilla (golem hp) - ensure that a golem hp is never zero --- Source/monster.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index ad81db14303..db5ed72ac21 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -5002,7 +5002,7 @@ void InitGolemStats(int mnum, int level) mon = &monsters[mnum]; mon->_mLevel = level; - mon->_mmaxhp = 640 * level; + mon->_mmaxhp = 640 * (level + 1); mon->_mArmorClass = 25 + level; mon->_mEvasion = 10 + (level >> 1); mon->_mHit = 4 * level + 40; From 455a96603bfdcbd64be0f27aca65fe8df7abfd81 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 21 Dec 2023 11:37:16 +0100 Subject: [PATCH 089/596] calculate hp out of the loop in AddHealOther --- Source/missiles.cpp | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 58cb957abd8..e060bfed8df 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -2916,33 +2916,34 @@ int AddHealOther(int mi, int sx, int sy, int dx, int dy, int midir, int micaster int pnum, i, hp; assert((unsigned)misource < MAX_PLRS); + // calculate hp + hp = RandRange(1, 10); + for (i = spllvl; i > 0; i--) { + hp += RandRange(1, 6); + } + for (i = plx(misource)._pLevel; i > 0; i--) { + hp += RandRange(1, 4); + } + hp <<= 6; + switch (plx(misource)._pClass) { + case PC_WARRIOR: hp <<= 1; break; +#ifdef HELLFIRE + case PC_MONK: hp *= 3; break; + case PC_BARBARIAN: hp <<= 1; break; + case PC_BARD: +#endif + case PC_ROGUE: hp += hp >> 1; break; + case PC_SORCERER: break; + default: + ASSUME_UNREACHABLE + } + // select target for (pnum = 0; pnum < MAX_PLRS; pnum++) { if (pnum != misource && plr._pActive && plr._pDunLevel == currLvl._dLevelIdx && plr._px == dx && plr._py == dy && plr._pHitPoints >= (1 << 6)) { - hp = RandRange(1, 10); - for (i = spllvl; i > 0; i--) { - hp += RandRange(1, 6); - } - for (i = plx(misource)._pLevel; i > 0; i--) { - hp += RandRange(1, 4); - } - hp <<= 6; - - switch (plx(misource)._pClass) { - case PC_WARRIOR: hp <<= 1; break; -#ifdef HELLFIRE - case PC_MONK: hp *= 3; break; - case PC_BARBARIAN: hp <<= 1; break; - case PC_BARD: -#endif - case PC_ROGUE: hp += hp >> 1; break; - case PC_SORCERER: break; - default: - ASSUME_UNREACHABLE - } PlrIncHp(pnum, hp); break; } From 339fad71af378cf697d05ecc7b851395a1181055 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 21 Dec 2023 11:38:11 +0100 Subject: [PATCH 090/596] bugfix for 'rework targeting' - fix the targeting of dead players --- Source/cursor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/cursor.cpp b/Source/cursor.cpp index 5d649a76182..b3bf4392ab3 100644 --- a/Source/cursor.cpp +++ b/Source/cursor.cpp @@ -413,7 +413,7 @@ void CheckCursMove() curitem[1] = dItem[mx][my]; if (dFlags[mx][my] & BFLAG_DEAD_PLAYER) { for (pnum = 0; pnum < MAX_PLRS; pnum++) { - if (/*pnum != mypnum && plr._pmode == PM_DEATH &&*/ plr._px == mx && plr._py == my && plr._pActive && plr._pDunLevel == currLvl._dLevelIdx) { + if (/*pnum != mypnum && */plr._pmode == PM_DEATH && plr._px == mx && plr._py == my && plr._pActive && plr._pDunLevel == currLvl._dLevelIdx) { deadplr[0] = pnum + 1; } } From 327f9510ee41cc894ea869157f326c2e04a50be9 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 21 Dec 2023 11:39:06 +0100 Subject: [PATCH 091/596] reduce the treasure in cathedral --- Source/themes.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/themes.cpp b/Source/themes.cpp index 5495f475208..292c548ff64 100644 --- a/Source/themes.cpp +++ b/Source/themes.cpp @@ -584,7 +584,7 @@ static void Theme_SkelRoom(int themeId, BYTE tv) static void Theme_Treasure(BYTE tv) { int xx, yy; - const BYTE treasrnds[4] = { 4, 9, 7, 10 }; + const BYTE treasrnds[4] = { 6, 9, 7, 10 }; const BYTE treasrnd = treasrnds[currLvl._dDunType - 1]; // TODO: use dType instead? for (xx = DBORDERX; xx < DBORDERX + DSIZEX; xx++) { From afd5542d807182ade8a302bb022b0ad15635cdd7 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 21 Dec 2023 11:51:12 +0100 Subject: [PATCH 092/596] cosmetic --- Source/objects.cpp | 7 ++-- structs.h | 98 +++++++++++++++++++++++----------------------- 2 files changed, 53 insertions(+), 52 deletions(-) diff --git a/Source/objects.cpp b/Source/objects.cpp index 709cb70c0c9..646f537b14f 100644 --- a/Source/objects.cpp +++ b/Source/objects.cpp @@ -1359,9 +1359,10 @@ int AddObject(int type, int ox, int oy) case OBJ_MUSHPATCH: Alloc2x2Obj(oi); break; - //case OBJ_TEARFTN: - // ObjAddRndSeed(oi); - // break; + //case OBJ_BLOODFTN: + //case OBJ_TEARFTN: + // ObjAddRndSeed(oi); + // break; case OBJ_MCIRCLE1: case OBJ_MCIRCLE2: AddMagicCircle(oi); diff --git a/structs.h b/structs.h index e923e64c0a4..6d3e4c361fa 100644 --- a/structs.h +++ b/structs.h @@ -321,8 +321,8 @@ typedef struct PlayerStruct { int _pfuty; // Future tile Y-position where the player will be at the end of its action int _poldx; // Most recent tile X-position where the player was at the start of its action int _poldy; // Most recent tile Y-position where the player was at the start of its action - int _pxoff; // Pixel X-offset from tile X-position where the player should be drawn - int _pyoff; // Pixel Y-offset from tile Y-position where the player should be drawn + int _pxoff; // Pixel X-offset from tile position where the player should be drawn + int _pyoff; // Pixel Y-offset from tile position where the player should be drawn int _pdir; // Direction faced by player (direction enum) BYTE* _pAnimData; int _pAnimFrameLen; // Tick length of each frame in the current animation @@ -520,8 +520,8 @@ typedef struct MissileStruct { int _misy; // Initial tile Y-position int _mix; // Tile X-position where the missile should be drawn int _miy; // Tile Y-position where the missile should be drawn - int _mixoff; // Pixel X-offset from tile X-position where the missile should be drawn - int _miyoff; // Pixel Y-offset from tile Y-position where the missile should be drawn + int _mixoff; // Pixel X-offset from tile position where the missile should be drawn + int _miyoff; // Pixel Y-offset from tile position where the missile should be drawn int _mixvel; // Missile tile (X - Y)-velocity while moving. This gets added onto _mitxoff each game tick int _miyvel; // Missile tile (X + Y)-velocity while moving. This gets added onto _mityoff each game tick int _mitxoff; // How far the missile has travelled in its lifespan along the (X - Y)-axis. mix/miy/mxoff/myoff get updated every game tick based on this @@ -700,8 +700,8 @@ typedef struct MonsterStruct { int _mfuty; // Future tile Y-position where the monster will be at the end of its action int _moldx; // Most recent tile X-position where the monster was at the start of its action int _moldy; // Most recent tile Y-position where the monster was at the start of its action - int _mxoff; // Pixel X-offset from tile X-position where the monster should be drawn - int _myoff; // Pixel Y-offset from tile Y-position where the monster should be drawn + int _mxoff; // Pixel X-offset from tile position where the monster should be drawn + int _myoff; // Pixel Y-offset from tile position where the monster should be drawn int _mdir; // Direction faced by monster (direction enum) int _menemy; // The current target of the monster. An index in to either the plr or monster array depending on _mFlags (MFLAG_TARGETS_MONSTER) BYTE _menemyx; // Future (except for teleporting) tile X-coordinate of the enemy @@ -1246,7 +1246,7 @@ typedef struct LSavePlayerStruct { LE_INT32 vpDestAction; LE_INT32 vpDestParam1; LE_INT32 vpDestParam2; - LE_INT32 vpDestParam3; // the skill to be used in case of skill based actions + LE_INT32 vpDestParam3; // the skill to be used in case of skill based actions LE_INT32 vpDestParam4; // the level of the skill to be used in case of skill based actions BOOLEAN vpActive; BYTE vpInvincible; @@ -1268,8 +1268,8 @@ typedef struct LSavePlayerStruct { LE_INT32 vpfuty; // Future tile Y-position where the player will be at the end of its action LE_INT32 vpoldx; // Most recent tile X-position where the player was at the start of its action LE_INT32 vpoldy; // Most recent tile Y-position where the player was at the start of its action - LE_INT32 vpxoff; // Pixel X-offset from tile X-position where the player should be drawn - LE_INT32 vpyoff; // Pixel Y-offset from tile Y-position where the player should be drawn + LE_INT32 vpxoff; // Pixel X-offset from tile position where the player should be drawn + LE_INT32 vpyoff; // Pixel Y-offset from tile position where the player should be drawn LE_INT32 vpdir; // Direction faced by player (direction enum) INT vpAnimDataAlign; INT vpAnimFrameLenAlign; // Tick length of each frame in the current animation @@ -1354,8 +1354,8 @@ typedef struct LSaveMonsterStruct { LE_INT32 vmfuty; // Future tile Y-position where the monster will be at the end of its action LE_INT32 vmoldx; // Most recent tile X-position where the monster was at the start of its action LE_INT32 vmoldy; // Most recent tile Y-position where the monster was at the start of its action - LE_INT32 vmxoff; // Pixel X-offset from tile X-position where the monster should be drawn - LE_INT32 vmyoff; // Pixel Y-offset from tile X-position where the monster should be drawn + LE_INT32 vmxoff; // Pixel X-offset from tile position where the monster should be drawn + LE_INT32 vmyoff; // Pixel Y-offset from tile position where the monster should be drawn LE_INT32 vmdir; // Direction faced by monster (direction enum) LE_INT32 vmenemy; // The current target of the monster. An index in to either the plr or monster array depending on _mFlags (MFLAG_TARGETS_MONSTER) BYTE vmenemyx; // Future (except for teleporting) tile X-coordinate of the enemy @@ -1434,8 +1434,8 @@ typedef struct LSaveMissileStruct { LE_INT32 vmisy; // Initial tile Y-position LE_INT32 vmix; // Tile X-position where the missile should be drawn LE_INT32 vmiy; // Tile Y-position where the missile should be drawn - LE_INT32 vmixoff; // Pixel X-offset from tile X-position where the missile should be drawn - LE_INT32 vmiyoff; // Pixel Y-offset from tile Y-position where the missile should be drawn + LE_INT32 vmixoff; // Pixel X-offset from tile position where the missile should be drawn + LE_INT32 vmiyoff; // Pixel Y-offset from tile position where the missile should be drawn LE_INT32 vmixvel; // Missile tile (X - Y)-velocity while moving. This gets added onto _mitxoff each game tick LE_INT32 vmiyvel; // Missile tile (X + Y)-velocity while moving. This gets added onto _mityoff each game tick LE_INT32 vmitxoff; // How far the missile has travelled in its lifespan along the (X - Y)-axis. mix/miy/mxoff/myoff get updated every game tick based on this @@ -1807,14 +1807,14 @@ typedef struct TSyncLvlPlayer { LE_INT32 spDestParam3; LE_INT32 spDestParam4; LE_INT16 spTimer[NUM_PLRTIMERS]; - BYTE spx; // Tile X-position of player - BYTE spy; // Tile Y-position of player - BYTE spfutx; // Future tile X-position of player. Set at start of walking animation - BYTE spfuty; // Future tile Y-position of player. Set at start of walking animation - BYTE spoldx; // Most recent X-position in dPlayer. - BYTE spoldy; // Most recent Y-position in dPlayer. -// LE_INT32 spxoff; // Player sprite's pixel X-offset from tile. -// LE_INT32 spyoff; // Player sprite's pixel Y-offset from tile. + BYTE spx; // Tile X-position where the player should be drawn + BYTE spy; // Tile Y-position where the player should be drawn + BYTE spfutx; // Future tile X-position where the player will be at the end of its action + BYTE spfuty; // Future tile Y-position where the player will be at the end of its action + BYTE spoldx; // Most recent tile X-position where the player was at the start of its action + BYTE spoldy; // Most recent tile Y-position where the player was at the start of its action +// LE_INT32 spxoff; // Pixel X-offset from tile position where the player should be drawn +// LE_INT32 spyoff; // Pixel Y-offset from tile position where the player should be drawn BYTE spdir; // Direction faced by player (direction enum) BYTE spAnimFrame; // Current frame of animation. BYTE spAnimCnt; // Increases by one each game tick, counting how close we are to _pAnimFrameLen @@ -1842,19 +1842,19 @@ typedef struct TSyncLvlMonster { LE_INT32 smGoalvar1; LE_INT32 smGoalvar2; LE_INT32 smGoalvar3; - BYTE smx; // Tile X-position of monster - BYTE smy; // Tile Y-position of monster - BYTE smfutx; // Future tile X-position of monster. Set at start of walking animation - BYTE smfuty; // Future tile Y-position of monster. Set at start of walking animation - BYTE smoldx; // Most recent X-position in dMonster. - BYTE smoldy; // Most recent Y-position in dMonster. -// LE_INT32 smxoff; // Monster sprite's pixel X-offset from tile. -// LE_INT32 smyoff; // Monster sprite's pixel Y-offset from tile. - BYTE smdir; // Direction faced by monster (direction enum) - LE_INT32 smEnemy; // The current target of the monster. An index in to either the plr or monster array based on the _meflag value. - BYTE smEnemyx; // X-coordinate of enemy (usually correspond's to the enemy's futx value) - BYTE smEnemyy; // Y-coordinate of enemy (usually correspond's to the enemy's futy value) - BYTE smListener; // the player to whom the monster is talking to (unused) + BYTE smx; // Tile X-position where the monster should be drawn + BYTE smy; // Tile Y-position where the monster should be drawn + BYTE smfutx; // Future tile X-position where the monster will be at the end of its action + BYTE smfuty; // Future tile Y-position where the monster will be at the end of its action + BYTE smoldx; // Most recent tile X-position where the monster was at the start of its action + BYTE smoldy; // Most recent tile Y-position where the monster was at the start of its action +// LE_INT32 smxoff; // Pixel X-offset from tile position where the monster should be drawn +// LE_INT32 smyoff; // Pixel Y-offset from tile position where the monster should be drawn + BYTE smdir; // Direction faced by monster (direction enum) + LE_INT32 smEnemy; // The current target of the monster. An index in to either the plr or monster array depending on _mFlags (MFLAG_TARGETS_MONSTER) + BYTE smEnemyx; // Future (except for teleporting) tile X-coordinate of the enemy + BYTE smEnemyy; // Future (except for teleporting) tile Y-coordinate of the enemy + BYTE smListener; // the player to whom the monster is talking to (unused) BOOLEAN smDelFlag; // unused BYTE smAnimCnt; // Increases by one each game tick, counting how close we are to _mAnimFrameLen BYTE smAnimFrame; // Current frame of animation. @@ -1863,12 +1863,12 @@ typedef struct TSyncLvlMonster { LE_INT32 smVar3; LE_INT32 smVar4; LE_INT32 smVar5; - LE_INT32 smVar6; // Used as _mxoff but with a higher range so that we can correctly apply velocities of a smaller number - LE_INT32 smVar7; // Used as _myoff but with a higher range so that we can correctly apply velocities of a smaller number - LE_INT32 smVar8; // Value used to measure progress for moving from one tile to another + LE_INT32 smVar6; + LE_INT32 smVar7; + LE_INT32 smVar8; LE_INT32 smHitpoints; - BYTE smLastx; // the last known X-coordinate of the enemy - BYTE smLasty; // the last known Y-coordinate of the enemy + BYTE smLastx; // the last known (future) tile X-coordinate of the enemy + BYTE smLasty; // the last known (future) tile Y-coordinate of the enemy //BYTE smLeader; // the leader of the monster BYTE smLeaderflag; // the status of the monster's leader //BYTE smPacksize; // the number of 'pack'-monsters close to their leader @@ -1890,14 +1890,14 @@ typedef struct TSyncLvlMissile { BYTE smiDir; // The direction of the missile BYTE smisx; // Initial tile X-position for missile BYTE smisy; // Initial tile Y-position for missile - BYTE smix; // Tile X-position of the missile - BYTE smiy; // Tile Y-position of the missile - LE_INT32 smixoff; // Sprite pixel X-offset for the missile - LE_INT32 smiyoff; // Sprite pixel Y-offset for the missile - LE_INT32 smixvel; // Missile tile X-velocity while walking. This gets added onto _mitxoff each game tick - LE_INT32 smiyvel; // Missile tile Y-velocity while walking. This gets added onto _mitxoff each game tick - LE_INT32 smitxoff; // How far the missile has travelled in its lifespan along the X-axis. mix/miy/mxoff/myoff get updated every game tick based on this - LE_INT32 smityoff; // How far the missile has travelled in its lifespan along the Y-axis. mix/miy/mxoff/myoff get updated every game tick based on this + BYTE smix; // Tile X-position where the missile should be drawn + BYTE smiy; // Tile Y-position where the missile should be drawn + LE_INT32 smixoff; // Pixel X-offset from tile position where the missile should be drawn + LE_INT32 smiyoff; // Pixel Y-offset from tile position where the missile should be drawn + LE_INT32 smixvel; // Missile tile (X - Y)-velocity while moving. This gets added onto _mitxoff each game tick + LE_INT32 smiyvel; // Missile tile (X + Y)-velocity while moving. This gets added onto _mityoff each game tick + LE_INT32 smitxoff; // How far the missile has travelled in its lifespan along the (X - Y)-axis. mix/miy/mxoff/myoff get updated every game tick based on this + LE_INT32 smityoff; // How far the missile has travelled in its lifespan along the (X + Y)-axis. mix/miy/mxoff/myoff get updated every game tick based on this LE_INT32 smiSpllvl; // TODO: int? LE_INT32 smiSource; // TODO: int? LE_INT32 smiCaster; // TODO: int? @@ -1911,8 +1911,8 @@ typedef struct TSyncLvlMissile { LE_INT32 smiVar4; LE_INT32 smiVar5; LE_INT32 smiVar6; - LE_INT32 smiVar7; - LE_INT32 smiVar8; + LE_INT32 smiVar7; // distance travelled in case of ARROW missiles + LE_INT32 smiVar8; // last target in case of non-DOT missiles BYTE smiLidRadius; } TSyncLvlMissile; From a3d6a7080df15837136837d7ea9d98228ef3e5ab Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 21 Dec 2023 12:38:27 +0100 Subject: [PATCH 093/596] bugfix for vanilla (stone vs talking monsters) - prevent stoning of talking monsters --- Source/missiles.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index e060bfed8df..3b1fc5d2f37 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -2776,7 +2776,7 @@ int AddStone(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in continue; mid = mid >= 0 ? mid - 1 : -(mid + 1); mon = &monsters[mid]; - if (!(mon->_mFlags & MFLAG_NOSTONE)) { + if (!(mon->_mFlags & MFLAG_NOSTONE) && !CanTalkToMonst(mid)) { if (mon->_mmode != MM_FADEIN && mon->_mmode != MM_FADEOUT && mon->_mmode != MM_CHARGE && mon->_mmode != MM_STONE && mon->_mmode != MM_DEATH /*mon->_mhitpoints >= (1 << 6*/) { MonLeaveLeader(mid); mis->_miVar1 = mon->_mmode; From d6bbddaa332052ce31af4272794f003cb39bc00f Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 21 Dec 2023 12:40:21 +0100 Subject: [PATCH 094/596] 'bugfix' for vanilla (guardian vs talking monsters) - prevent guardians from targeting quest monsters --- Source/missiles.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 3b1fc5d2f37..5b235653c5d 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -3448,12 +3448,15 @@ int AddMissile(int sx, int sy, int dx, int dy, int midir, int mitype, int micast static bool Sentfire(int mi, int sx, int sy) { + int mnum; MissileStruct* mis; mis = &missile[mi]; assert(mis->_miCaster == MST_PLAYER); - if (dMonster[sx][sy] - 1 >= MAX_MINIONS - && monsters[dMonster[sx][sy] - 1]._mhitpoints >= (1 << 6) + mnum = dMonster[sx][sy] - 1; + if (mnum >= MAX_MINIONS + && monsters[mnum]._mhitpoints >= (1 << 6) + && !CanTalkToMonst(mnum) && LineClear(mis->_mix, mis->_miy, sx, sy)) { // SetRndSeed(mis->_miRndSeed); AddMissile(mis->_mix, mis->_miy, sx, sy, 0, MIS_FIREBOLT, MST_PLAYER, mis->_miSource, mis->_miSpllvl); From 47da83dd3868a7fde43a048b4327aff5d18b0350 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 21 Dec 2023 14:48:02 +0100 Subject: [PATCH 095/596] simplify FindMeleeTarget (and FindRangedTarget a bit) --- Source/controls/plrctrls.cpp | 88 +++++++++++------------------------- 1 file changed, 27 insertions(+), 61 deletions(-) diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index 0a3ab446047..0b0dd1b3e22 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -1,9 +1,6 @@ #include "plrctrls.h" #if HAS_GAMECTRL || HAS_JOYSTICK || HAS_KBCTRL || HAS_DPAD -//#include -#include - #include "controller_motion.h" #include "game_controls.h" @@ -204,8 +201,6 @@ static void FindRangedTarget() if (tgtMode == 0) continue; const bool newCanTalk = tgtMode - 1; - if (!canTalk && newCanTalk) - continue; const MonsterStruct& mon = monsters[mnum]; const int mx = mon._mfutx; const int my = mon._mfuty; @@ -216,6 +211,8 @@ static void FindRangedTarget() continue; if (distance == newDdistance && rotations < newRotations) continue; + } else if (newCanTalk) { + continue; } distance = newDdistance; rotations = newRotations; @@ -226,66 +223,35 @@ static void FindRangedTarget() static void FindMeleeTarget() { - bool visited[MAXDUNX][MAXDUNY] = { { 0 } }; - int maxSteps = MAX_PATH_LENGTH; - int rotations = NUM_DIRS; + int rotations = NUM_DIRS, distance = MAXDUNX + MAXDUNY, mnum; bool canTalk = true; + int8_t walkpath[MAX_PATH_LENGTH + 1]; - struct SearchNode { - int x, y; - int steps; - }; - std::queue nodes; - { - const int startX = myplr._pfutx; - const int startY = myplr._pfuty; - visited[startX][startY] = true; - nodes.push({ startX, startY, 0 }); - } - - while (!nodes.empty()) { - SearchNode node = nodes.front(); - nodes.pop(); - - if (node.steps > maxSteps) - break; - static_assert(lengthof(pathxdir) == lengthof(pathydir), "Mismatching pathdir tables."); - for (int i = 0; i < lengthof(pathxdir); i++) { - const int dx = node.x + pathxdir[i]; - const int dy = node.y + pathydir[i]; - if (visited[dx][dy]) - continue; // already visited - - if (!PosOkPlayer(mypnum, dx, dy)) { - visited[dx][dy] = true; - - int mi = dMonster[dx][dy]; - if (mi != 0) { - mi = mi >= 0 ? mi - 1 : -(mi + 1); - const int tgtMode = CanTargetMonster(mi); - if (tgtMode != 0) { - const bool newCanTalk = tgtMode - 1; - if (!canTalk && newCanTalk) - continue; - const int newRotations = GetRotaryDistance(dx, dy); - if (canTalk == newCanTalk && rotations < newRotations) - continue; - rotations = newRotations; - canTalk = newCanTalk; - pcursmonst = mi; - if (!canTalk) - maxSteps = node.steps; // Monsters found, cap search to current steps - } - } - + for (mnum = 0; mnum < MAXMONSTERS; mnum++) { + const int tgtMode = CanTargetMonster(mnum); + if (tgtMode == 0) + continue; + const bool newCanTalk = tgtMode - 1; + const MonsterStruct& mon = monsters[mnum]; + const int mx = mon._mfutx; + const int my = mon._mfuty; + const int newDdistance = FindPath(PosOkPlayer, mypnum, myplr._pfutx, myplr._pfuty, mx, my, walkpath); + if (newDdistance < 0) { + continue; + } + const int newRotations = GetRotaryDistance(mx, my); + if (canTalk == newCanTalk) { + if (distance < newDdistance) continue; - } - - if (PathWalkable(node.x, node.y, i)) { - nodes.push({ dx, dy, node.steps + 1 }); - visited[dx][dy] = true; - } + if (distance == newDdistance && rotations < newRotations) + continue; + } else if (newCanTalk) { + continue; } + distance = newDdistance; + rotations = newRotations; + canTalk = newCanTalk; + pcursmonst = mnum; } } From 775c4172ca26ad1464bb2decdbe19ebba2622c0e Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 21 Dec 2023 14:57:05 +0100 Subject: [PATCH 096/596] convert HasRangedSpell to IsRangedSpell --- Source/controls/plrctrls.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index 0b0dd1b3e22..c97fd5063ac 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -156,12 +156,8 @@ static void CheckTownersNearby() } } -static bool HasRangedSpell() +static bool IsRangedSpell(int spl) { - int spl = myplr._pAltAtkSkill; - if (spl == SPL_INVALID) - spl = myplr._pAltMoveSkill; - return spl != SPL_INVALID && spl != SPL_TOWN && spl != SPL_TELEPORT @@ -257,7 +253,11 @@ static void FindMeleeTarget() static void CheckMonstersNearby() { - if ((myplr._pSkillFlags & SFLAG_RANGED) || HasRangedSpell()) { + int spl = myplr._pAltAtkSkill; + if (spl == SPL_INVALID) + spl = myplr._pAltMoveSkill; + + if ((myplr._pSkillFlags & SFLAG_RANGED) || IsRangedSpell(spl)) { FindRangedTarget(); return; } @@ -291,7 +291,7 @@ static void CheckPlayerNearby() const int my = players[i]._pfuty; if (!(dFlags[mx][my] & BFLAG_VISIBLE)) continue; - if ((myplr._pSkillFlags & SFLAG_RANGED) || HasRangedSpell()) { + if ((myplr._pSkillFlags & SFLAG_RANGED) || IsRangedSpell(spl)) { newDdistance = GetDistanceRanged(mx, my); } else { newDdistance = GetDistance(mx, my, distance); From 36eefa24adbe6750a55bf5f88bed6d93c2a5ca75 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 21 Dec 2023 15:23:18 +0100 Subject: [PATCH 097/596] merge FindMeleeTarget and FindRangedTarget and sync with CheckPlayerNearby --- Source/controls/plrctrls.cpp | 87 ++++++++++-------------------------- 1 file changed, 24 insertions(+), 63 deletions(-) diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index c97fd5063ac..e1a53865c74 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -187,10 +187,14 @@ static int CanTargetMonster(int mnum) return CanTalkToMonst(mnum) ? 2 : 1; } -static void FindRangedTarget() +static void CheckMonstersNearby() { - int rotations = NUM_DIRS, distance = MAXDUNX + MAXDUNY, mnum; - bool canTalk = true; + int newDdistance, rotations, distance = MAXDUNX + MAXDUNY, mnum; + bool ranged, canTalk = true; + int spl = myplr._pAltAtkSkill; + if (spl == SPL_INVALID) + spl = myplr._pAltMoveSkill; + ranged = (myplr._pSkillFlags & SFLAG_RANGED) || IsRangedSpell(spl); for (mnum = 0; mnum < MAXMONSTERS; mnum++) { const int tgtMode = CanTargetMonster(mnum); @@ -200,40 +204,12 @@ static void FindRangedTarget() const MonsterStruct& mon = monsters[mnum]; const int mx = mon._mfutx; const int my = mon._mfuty; - const int newDdistance = GetDistanceRanged(mx, my); - const int newRotations = GetRotaryDistance(mx, my); - if (canTalk == newCanTalk) { - if (distance < newDdistance) - continue; - if (distance == newDdistance && rotations < newRotations) + if (ranged) { + newDdistance = GetDistanceRanged(mx, my); + } else { + newDdistance = GetDistance(mx, my, distance); + if (newDdistance < 0) continue; - } else if (newCanTalk) { - continue; - } - distance = newDdistance; - rotations = newRotations; - canTalk = newCanTalk; - pcursmonst = mnum; - } -} - -static void FindMeleeTarget() -{ - int rotations = NUM_DIRS, distance = MAXDUNX + MAXDUNY, mnum; - bool canTalk = true; - int8_t walkpath[MAX_PATH_LENGTH + 1]; - - for (mnum = 0; mnum < MAXMONSTERS; mnum++) { - const int tgtMode = CanTargetMonster(mnum); - if (tgtMode == 0) - continue; - const bool newCanTalk = tgtMode - 1; - const MonsterStruct& mon = monsters[mnum]; - const int mx = mon._mfutx; - const int my = mon._mfuty; - const int newDdistance = FindPath(PosOkPlayer, mypnum, myplr._pfutx, myplr._pfuty, mx, my, walkpath); - if (newDdistance < 0) { - continue; } const int newRotations = GetRotaryDistance(mx, my); if (canTalk == newCanTalk) { @@ -251,47 +227,32 @@ static void FindMeleeTarget() } } -static void CheckMonstersNearby() +static void CheckPlayerNearby() { + int newDdistance, rotations, distance = MAXDUNX + MAXDUNY, pnum; + bool ranged; int spl = myplr._pAltAtkSkill; if (spl == SPL_INVALID) spl = myplr._pAltMoveSkill; - - if ((myplr._pSkillFlags & SFLAG_RANGED) || IsRangedSpell(spl)) { - FindRangedTarget(); - return; - } - - FindMeleeTarget(); -} - -static void CheckPlayerNearby() -{ - int newDdistance; - int rotations; - int distance = MAXDUNX + MAXDUNY; + ranged = (myplr._pSkillFlags & SFLAG_RANGED) || IsRangedSpell(spl); if (pcursmonst != MON_NONE) return; - int spl = myplr._pAltAtkSkill; - if (spl == SPL_INVALID) - spl = myplr._pAltMoveSkill; - - for (int i = 0; i < MAX_PLRS; i++) { - if (i == mypnum) + for (pnum = 0; pnum < MAX_PLRS; pnum++) { + if (pnum == mypnum) continue; if (spl != SPL_RESURRECT) { - if (players[i]._pHitPoints == 0) + if (plr._pHitPoints == 0) continue; - if (players[i]._pTeam == myplr._pTeam && spl != SPL_HEALOTHER) + if (plr._pTeam == myplr._pTeam && spl != SPL_HEALOTHER) continue; } - const int mx = players[i]._pfutx; - const int my = players[i]._pfuty; + const int mx = plr._pfutx; + const int my = plr._pfuty; if (!(dFlags[mx][my] & BFLAG_VISIBLE)) continue; - if ((myplr._pSkillFlags & SFLAG_RANGED) || IsRangedSpell(spl)) { + if (ranged) { newDdistance = GetDistanceRanged(mx, my); } else { newDdistance = GetDistance(mx, my, distance); @@ -307,7 +268,7 @@ static void CheckPlayerNearby() distance = newDdistance; rotations = newRotations; - pcursplr = i; + pcursplr = pnum; } } From d54b72e226e8aade0080c12d7643f495579c8d37 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 21 Dec 2023 15:38:04 +0100 Subject: [PATCH 098/596] shortcut CheckMonstersNearby, CheckTownersNearby. CheckPlayerNearby, FindItemOrObject based on pcurstgt --- Source/controls/plrctrls.cpp | 13 +++++++++++++ Source/diablo.cpp | 10 +++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index e1a53865c74..c321eaa2c9d 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -99,6 +99,7 @@ static void FindItemOrObject() int my = myplr._pfuty; int rotations = 5; + if (pcurstgt == TGT_NORMAL) { static_assert(DBORDERX >= 1 && DBORDERY >= 1, "FindItemOrObject expects a large enough border."); for (int xx = -1; xx <= 1; xx++) { for (int yy = -1; yy <= 1; yy++) { @@ -122,6 +123,9 @@ static void FindItemOrObject() if (currLvl._dType == DTYPE_TOWN || pcursitem != ITEM_NONE) return; // Don't look for objects in town + } else if (pcurstgt != TGT_OBJECT) { + return; + } for (int xx = -1; xx <= 1; xx++) { for (int yy = -1; yy <= 1; yy++) { @@ -148,6 +152,9 @@ static void FindItemOrObject() static void CheckTownersNearby() { + if (pcurstgt != TGT_NORMAL) + return; + for (int i = MAX_MINIONS; i < numtowners; i++) { int distance = GetDistance(monsters[i]._mx, monsters[i]._my, 2); if (distance < 0) @@ -196,6 +203,9 @@ static void CheckMonstersNearby() spl = myplr._pAltMoveSkill; ranged = (myplr._pSkillFlags & SFLAG_RANGED) || IsRangedSpell(spl); + if (pcurstgt != TGT_NORMAL && pcurstgt != TGT_PLAYER) + return; + for (mnum = 0; mnum < MAXMONSTERS; mnum++) { const int tgtMode = CanTargetMonster(mnum); if (tgtMode == 0) @@ -239,6 +249,9 @@ static void CheckPlayerNearby() if (pcursmonst != MON_NONE) return; + if (pcurstgt != TGT_NORMAL && pcurstgt != TGT_PLAYER && pcurstgt != TGT_DEAD) + return; + for (pnum = 0; pnum < MAX_PLRS; pnum++) { if (pnum == mypnum) continue; diff --git a/Source/diablo.cpp b/Source/diablo.cpp index cd6cd8c3777..6a25131c12b 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -456,19 +456,15 @@ bool TryIconCurs(bool bShift) } } break; case CURSOR_TELEPORT: + case CURSOR_HEALOTHER: + case CURSOR_RESURRECT: if (pcursmonst != MON_NONE) NetSendCmdMonSkill(pcursmonst, gbTSpell, gbTSplFrom); else if (pcursplr != PLR_NONE) NetSendCmdPlrSkill(pcursplr, gbTSpell, gbTSplFrom); - else + else if (pcursicon == CURSOR_TELEPORT) NetSendCmdLocSkill(pcurspos.x, pcurspos.y, gbTSpell, gbTSplFrom); break; - case CURSOR_HEALOTHER: - case CURSOR_RESURRECT: - if (pcursplr != PLR_NONE) { - NetSendCmdPlrSkill(pcursplr, gbTSpell, gbTSplFrom); - } - break; default: return false; } From 6d60d0c4352348a75b4793013ef346d6970d437e Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 21 Dec 2023 15:51:22 +0100 Subject: [PATCH 099/596] minor code-cleanup - eliminate premature optimization (to skip object check in town) - check pcursmonst before calling CheckPlayerNearby - cosmetic --- Source/controls/plrctrls.cpp | 47 +++++++++++++++++------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index c321eaa2c9d..c9613025e11 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -100,29 +100,29 @@ static void FindItemOrObject() int rotations = 5; if (pcurstgt == TGT_NORMAL) { - static_assert(DBORDERX >= 1 && DBORDERY >= 1, "FindItemOrObject expects a large enough border."); - for (int xx = -1; xx <= 1; xx++) { - for (int yy = -1; yy <= 1; yy++) { - int ii = dItem[mx + xx][my + yy]; - if (ii <= 0) - continue; - ii--; - if (items[ii]._itype == ITYPE_NONE || items[ii]._iSelFlag == 0) - continue; - int newRotations = GetRotaryDistance(mx + xx, my + yy); - if (rotations < newRotations) - continue; - if (GetDistance(mx + xx, my + yy, 1) < 0) - continue; - rotations = newRotations; - pcursitem = ii; - pcurspos.x = mx + xx; - pcurspos.y = my + yy; + static_assert(DBORDERX >= 1 && DBORDERY >= 1, "FindItemOrObject expects a large enough border."); + for (int xx = -1; xx <= 1; xx++) { + for (int yy = -1; yy <= 1; yy++) { + int ii = dItem[mx + xx][my + yy]; + if (ii <= 0) + continue; + ii--; + if (items[ii]._itype == ITYPE_NONE || items[ii]._iSelFlag == 0) + continue; + int newRotations = GetRotaryDistance(mx + xx, my + yy); + if (rotations < newRotations) + continue; + if (GetDistance(mx + xx, my + yy, 1) < 0) + continue; + rotations = newRotations; + pcursitem = ii; + pcurspos.x = mx + xx; + pcurspos.y = my + yy; + } } - } - if (currLvl._dType == DTYPE_TOWN || pcursitem != ITEM_NONE) - return; // Don't look for objects in town + if (pcursitem != ITEM_NONE) + return; } else if (pcurstgt != TGT_OBJECT) { return; } @@ -246,9 +246,6 @@ static void CheckPlayerNearby() spl = myplr._pAltMoveSkill; ranged = (myplr._pSkillFlags & SFLAG_RANGED) || IsRangedSpell(spl); - if (pcursmonst != MON_NONE) - return; - if (pcurstgt != TGT_NORMAL && pcurstgt != TGT_PLAYER && pcurstgt != TGT_DEAD) return; @@ -292,7 +289,7 @@ static void FindActor() else CheckTownersNearby(); - if (!IsLocalGame) + if (!IsLocalGame && pcursmonst == MON_NONE) CheckPlayerNearby(); } From 72bd7d6e92070d24230ce0c27fa2df05d95a7704 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 22 Dec 2023 08:31:06 +0100 Subject: [PATCH 100/596] split FindActor --- Source/controls/plrctrls.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index c9613025e11..9682f81874b 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -237,7 +237,7 @@ static void CheckMonstersNearby() } } -static void CheckPlayerNearby() +static void FindPlayer() { int newDdistance, rotations, distance = MAXDUNX + MAXDUNY, pnum; bool ranged; @@ -282,15 +282,12 @@ static void CheckPlayerNearby() } } -static void FindActor() +static void FindMonster() { if (currLvl._dType != DTYPE_TOWN) CheckMonstersNearby(); else CheckTownersNearby(); - - if (!IsLocalGame && pcursmonst == MON_NONE) - CheckPlayerNearby(); } static void FindTrigger() @@ -1016,7 +1013,9 @@ void plrctrls_after_check_curs_move() } if (!gbInvflag) { *infostr = '\0'; - FindActor(); + FindMonster(); + if (!IsLocalGame && pcursmonst == MON_NONE) + FindPlayer(); FindItemOrObject(); FindTrigger(); } From 8d965a1befc6990739230c120334ae0b69d99faf Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 22 Dec 2023 08:40:54 +0100 Subject: [PATCH 101/596] split FindItemOrObject --- Source/controls/plrctrls.cpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index 9682f81874b..a195e7d7896 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -93,13 +93,15 @@ static int GetDistanceRanged(int dx, int dy) return sqrt(a * a + b * b); } -static void FindItemOrObject() +static void FindItem() { int mx = myplr._pfutx; int my = myplr._pfuty; int rotations = 5; - if (pcurstgt == TGT_NORMAL) { + if (pcurstgt != TGT_NORMAL && pcurstgt != TGT_ITEM) + return; + static_assert(DBORDERX >= 1 && DBORDERY >= 1, "FindItemOrObject expects a large enough border."); for (int xx = -1; xx <= 1; xx++) { for (int yy = -1; yy <= 1; yy++) { @@ -120,12 +122,16 @@ static void FindItemOrObject() pcurspos.y = my + yy; } } +} - if (pcursitem != ITEM_NONE) - return; - } else if (pcurstgt != TGT_OBJECT) { +static void FindObject() +{ + int mx = myplr._pfutx; + int my = myplr._pfuty; + int rotations = 5; + + if (pcurstgt != TGT_NORMAL && pcurstgt != TGT_OBJECT) return; - } for (int xx = -1; xx <= 1; xx++) { for (int yy = -1; yy <= 1; yy++) { @@ -1016,7 +1022,9 @@ void plrctrls_after_check_curs_move() FindMonster(); if (!IsLocalGame && pcursmonst == MON_NONE) FindPlayer(); - FindItemOrObject(); + FindItem(); + if (pcursitem == ITEM_NONE) + FindObject(); FindTrigger(); } } From 18a6c3ead964576d5569e6bb459f2d2d714f6fbc Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 22 Dec 2023 08:48:41 +0100 Subject: [PATCH 102/596] check pcurstgt in plrctrls_after_check_curs_move instead of the Find* functions --- Source/controls/plrctrls.cpp | 45 +++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index a195e7d7896..f3980ab0333 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -99,9 +99,6 @@ static void FindItem() int my = myplr._pfuty; int rotations = 5; - if (pcurstgt != TGT_NORMAL && pcurstgt != TGT_ITEM) - return; - static_assert(DBORDERX >= 1 && DBORDERY >= 1, "FindItemOrObject expects a large enough border."); for (int xx = -1; xx <= 1; xx++) { for (int yy = -1; yy <= 1; yy++) { @@ -130,9 +127,6 @@ static void FindObject() int my = myplr._pfuty; int rotations = 5; - if (pcurstgt != TGT_NORMAL && pcurstgt != TGT_OBJECT) - return; - for (int xx = -1; xx <= 1; xx++) { for (int yy = -1; yy <= 1; yy++) { int oi = dObject[mx + xx][my + yy]; @@ -158,9 +152,6 @@ static void FindObject() static void CheckTownersNearby() { - if (pcurstgt != TGT_NORMAL) - return; - for (int i = MAX_MINIONS; i < numtowners; i++) { int distance = GetDistance(monsters[i]._mx, monsters[i]._my, 2); if (distance < 0) @@ -209,9 +200,6 @@ static void CheckMonstersNearby() spl = myplr._pAltMoveSkill; ranged = (myplr._pSkillFlags & SFLAG_RANGED) || IsRangedSpell(spl); - if (pcurstgt != TGT_NORMAL && pcurstgt != TGT_PLAYER) - return; - for (mnum = 0; mnum < MAXMONSTERS; mnum++) { const int tgtMode = CanTargetMonster(mnum); if (tgtMode == 0) @@ -252,9 +240,6 @@ static void FindPlayer() spl = myplr._pAltMoveSkill; ranged = (myplr._pSkillFlags & SFLAG_RANGED) || IsRangedSpell(spl); - if (pcurstgt != TGT_NORMAL && pcurstgt != TGT_PLAYER && pcurstgt != TGT_DEAD) - return; - for (pnum = 0; pnum < MAX_PLRS; pnum++) { if (pnum == mypnum) continue; @@ -1019,13 +1004,31 @@ void plrctrls_after_check_curs_move() } if (!gbInvflag) { *infostr = '\0'; - FindMonster(); - if (!IsLocalGame && pcursmonst == MON_NONE) - FindPlayer(); - FindItem(); - if (pcursitem == ITEM_NONE) + switch (pcurstgt) { + case TGT_NORMAL: + FindMonster(); + if (!IsLocalGame && pcursmonst == MON_NONE) + FindPlayer(); + FindItem(); + if (pcursitem == ITEM_NONE) + FindObject(); + FindTrigger(); + break; + case TGT_ITEM: + FindItem(); + break; + case TGT_OBJECT: FindObject(); - FindTrigger(); + break; + case TGT_PLAYER: + case TGT_DEAD: + FindPlayer(); + break; + case TGT_NONE: + break; + default: + ASSUME_UNREACHABLE + } } } } From 623e2fe30b3bf44f3e8e0aba756f6329341e9872 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 22 Dec 2023 09:22:00 +0100 Subject: [PATCH 103/596] bugfix for devilutionx (targeting players with controller) - prevent targeting inactive or non-level players --- Source/controls/plrctrls.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index f3980ab0333..6bc61b635d8 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -243,6 +243,8 @@ static void FindPlayer() for (pnum = 0; pnum < MAX_PLRS; pnum++) { if (pnum == mypnum) continue; + if (!plr._pActive || plr._pDunLevel != currLvl._dLevelIdx) + continue; if (spl != SPL_RESURRECT) { if (plr._pHitPoints == 0) continue; From 54acbc239ff8d7b2637ac5b07c95ee7cefe3a4d0 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 22 Dec 2023 09:33:39 +0100 Subject: [PATCH 104/596] improve FindPlayer - target only dead player and prefer teammates when pcurstgt is TGT_DEAD - allow targeting teammates even if the selected spell is not RESURRECT or HEALOTHER, but prefer opponents --- Source/controls/plrctrls.cpp | 44 ++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index 6bc61b635d8..f54a9c50e04 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -231,26 +231,27 @@ static void CheckMonstersNearby() } } -static void FindPlayer() +/** + * @brief Find a player to target + * @param mode: 0 - offensive, 1 - heal, 2 - dead + */ +static void FindPlayer(int mode) { int newDdistance, rotations, distance = MAXDUNX + MAXDUNY, pnum; - bool ranged; + bool ranged, sameTeam; int spl = myplr._pAltAtkSkill; if (spl == SPL_INVALID) spl = myplr._pAltMoveSkill; ranged = (myplr._pSkillFlags & SFLAG_RANGED) || IsRangedSpell(spl); + sameTeam = mode == 0; for (pnum = 0; pnum < MAX_PLRS; pnum++) { if (pnum == mypnum) continue; if (!plr._pActive || plr._pDunLevel != currLvl._dLevelIdx) continue; - if (spl != SPL_RESURRECT) { - if (plr._pHitPoints == 0) - continue; - if (plr._pTeam == myplr._pTeam && spl != SPL_HEALOTHER) - continue; - } + if ((mode == 2) != (plr._pHitPoints == 0)) + continue; const int mx = plr._pfutx; const int my = plr._pfuty; if (!(dFlags[mx][my] & BFLAG_VISIBLE)) @@ -262,15 +263,26 @@ static void FindPlayer() if (newDdistance < 0) continue; } - - if (distance < newDdistance) - continue; const int newRotations = GetRotaryDistance(mx, my); - if (distance == newDdistance && rotations < newRotations) - continue; + bool newSameTeam = plr._pTeam == myplr._pTeam; + if (newSameTeam == sameTeam) { + if (distance < newDdistance) + continue; + if (distance == newDdistance && rotations < newRotations) + continue; + } else { + if (mode == 0) { + if (newSameTeam) + continue; // offensive mode -> prefer opponents + } else { + if (!newSameTeam) + continue; // defensive mode -> prefer teammates + } + } distance = newDdistance; rotations = newRotations; + sameTeam = newSameTeam; pcursplr = pnum; } } @@ -1010,7 +1022,7 @@ void plrctrls_after_check_curs_move() case TGT_NORMAL: FindMonster(); if (!IsLocalGame && pcursmonst == MON_NONE) - FindPlayer(); + FindPlayer(0); FindItem(); if (pcursitem == ITEM_NONE) FindObject(); @@ -1023,8 +1035,10 @@ void plrctrls_after_check_curs_move() FindObject(); break; case TGT_PLAYER: + FindPlayer(1); + break; case TGT_DEAD: - FindPlayer(); + FindPlayer(2); break; case TGT_NONE: break; From 1b1ac74b4f4678473e669dfaa2f6c3ad3d670cc1 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 22 Dec 2023 09:43:25 +0100 Subject: [PATCH 105/596] cosmetic --- Source/controls/plrctrls.cpp | 66 ++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index f54a9c50e04..09e9ba44ab9 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -99,26 +99,26 @@ static void FindItem() int my = myplr._pfuty; int rotations = 5; - static_assert(DBORDERX >= 1 && DBORDERY >= 1, "FindItemOrObject expects a large enough border."); - for (int xx = -1; xx <= 1; xx++) { - for (int yy = -1; yy <= 1; yy++) { - int ii = dItem[mx + xx][my + yy]; - if (ii <= 0) - continue; - ii--; - if (items[ii]._itype == ITYPE_NONE || items[ii]._iSelFlag == 0) - continue; - int newRotations = GetRotaryDistance(mx + xx, my + yy); - if (rotations < newRotations) - continue; - if (GetDistance(mx + xx, my + yy, 1) < 0) - continue; - rotations = newRotations; - pcursitem = ii; - pcurspos.x = mx + xx; - pcurspos.y = my + yy; - } + static_assert(DBORDERX >= 1 && DBORDERY >= 1, "FindItemOrObject expects a large enough border."); + for (int xx = -1; xx <= 1; xx++) { + for (int yy = -1; yy <= 1; yy++) { + int ii = dItem[mx + xx][my + yy]; + if (ii <= 0) + continue; + ii--; + if (items[ii]._itype == ITYPE_NONE || items[ii]._iSelFlag == 0) + continue; + int newRotations = GetRotaryDistance(mx + xx, my + yy); + if (rotations < newRotations) + continue; + if (GetDistance(mx + xx, my + yy, 1) < 0) + continue; + rotations = newRotations; + pcursitem = ii; + pcurspos.x = mx + xx; + pcurspos.y = my + yy; } + } } static void FindObject() @@ -193,7 +193,7 @@ static int CanTargetMonster(int mnum) static void CheckMonstersNearby() { - int newDdistance, rotations, distance = MAXDUNX + MAXDUNY, mnum; + int newDistance, rotations, distance = MAXDUNX + MAXDUNY, mnum; bool ranged, canTalk = true; int spl = myplr._pAltAtkSkill; if (spl == SPL_INVALID) @@ -209,22 +209,22 @@ static void CheckMonstersNearby() const int mx = mon._mfutx; const int my = mon._mfuty; if (ranged) { - newDdistance = GetDistanceRanged(mx, my); + newDistance = GetDistanceRanged(mx, my); } else { - newDdistance = GetDistance(mx, my, distance); - if (newDdistance < 0) + newDistance = GetDistance(mx, my, distance); + if (newDistance < 0) continue; } const int newRotations = GetRotaryDistance(mx, my); if (canTalk == newCanTalk) { - if (distance < newDdistance) + if (distance < newDistance) continue; - if (distance == newDdistance && rotations < newRotations) + if (distance == newDistance && rotations < newRotations) continue; } else if (newCanTalk) { continue; } - distance = newDdistance; + distance = newDistance; rotations = newRotations; canTalk = newCanTalk; pcursmonst = mnum; @@ -237,7 +237,7 @@ static void CheckMonstersNearby() */ static void FindPlayer(int mode) { - int newDdistance, rotations, distance = MAXDUNX + MAXDUNY, pnum; + int newDistance, rotations, distance = MAXDUNX + MAXDUNY, pnum; bool ranged, sameTeam; int spl = myplr._pAltAtkSkill; if (spl == SPL_INVALID) @@ -257,18 +257,18 @@ static void FindPlayer(int mode) if (!(dFlags[mx][my] & BFLAG_VISIBLE)) continue; if (ranged) { - newDdistance = GetDistanceRanged(mx, my); + newDistance = GetDistanceRanged(mx, my); } else { - newDdistance = GetDistance(mx, my, distance); - if (newDdistance < 0) + newDistance = GetDistance(mx, my, distance); + if (newDistance < 0) continue; } const int newRotations = GetRotaryDistance(mx, my); bool newSameTeam = plr._pTeam == myplr._pTeam; if (newSameTeam == sameTeam) { - if (distance < newDdistance) + if (distance < newDistance) continue; - if (distance == newDdistance && rotations < newRotations) + if (distance == newDistance && rotations < newRotations) continue; } else { if (mode == 0) { @@ -280,7 +280,7 @@ static void FindPlayer(int mode) } } - distance = newDdistance; + distance = newDistance; rotations = newRotations; sameTeam = newSameTeam; pcursplr = pnum; From 3505ed88b8219d3c84528fda7de6646a43ae6585 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 22 Dec 2023 09:47:35 +0100 Subject: [PATCH 106/596] calculate targeting mode (ranged) in one place --- Source/controls/plrctrls.cpp | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index 09e9ba44ab9..d950d930547 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -191,14 +191,10 @@ static int CanTargetMonster(int mnum) return CanTalkToMonst(mnum) ? 2 : 1; } -static void CheckMonstersNearby() +static void CheckMonstersNearby(bool ranged) { int newDistance, rotations, distance = MAXDUNX + MAXDUNY, mnum; - bool ranged, canTalk = true; - int spl = myplr._pAltAtkSkill; - if (spl == SPL_INVALID) - spl = myplr._pAltMoveSkill; - ranged = (myplr._pSkillFlags & SFLAG_RANGED) || IsRangedSpell(spl); + bool canTalk = true; for (mnum = 0; mnum < MAXMONSTERS; mnum++) { const int tgtMode = CanTargetMonster(mnum); @@ -234,15 +230,12 @@ static void CheckMonstersNearby() /** * @brief Find a player to target * @param mode: 0 - offensive, 1 - heal, 2 - dead + * @param ranged: whether the current player is melee or ranged */ -static void FindPlayer(int mode) +static void FindPlayer(int mode, bool ranged) { int newDistance, rotations, distance = MAXDUNX + MAXDUNY, pnum; - bool ranged, sameTeam; - int spl = myplr._pAltAtkSkill; - if (spl == SPL_INVALID) - spl = myplr._pAltMoveSkill; - ranged = (myplr._pSkillFlags & SFLAG_RANGED) || IsRangedSpell(spl); + bool sameTeam; sameTeam = mode == 0; for (pnum = 0; pnum < MAX_PLRS; pnum++) { @@ -287,10 +280,10 @@ static void FindPlayer(int mode) } } -static void FindMonster() +static void FindMonster(bool ranged) { if (currLvl._dType != DTYPE_TOWN) - CheckMonstersNearby(); + CheckMonstersNearby(ranged); else CheckTownersNearby(); } @@ -1018,11 +1011,16 @@ void plrctrls_after_check_curs_move() } if (!gbInvflag) { *infostr = '\0'; + int spl = myplr._pAltAtkSkill; + if (spl == SPL_INVALID) + spl = myplr._pAltMoveSkill; + bool ranged = (myplr._pSkillFlags & SFLAG_RANGED) || IsRangedSpell(spl); + switch (pcurstgt) { case TGT_NORMAL: - FindMonster(); + FindMonster(ranged); if (!IsLocalGame && pcursmonst == MON_NONE) - FindPlayer(0); + FindPlayer(0, ranged); FindItem(); if (pcursitem == ITEM_NONE) FindObject(); @@ -1035,10 +1033,12 @@ void plrctrls_after_check_curs_move() FindObject(); break; case TGT_PLAYER: - FindPlayer(1); + assert(ranged); + FindPlayer(1, true); break; case TGT_DEAD: - FindPlayer(2); + assert(ranged); + FindPlayer(2, true); break; case TGT_NONE: break; From 0f9427bd350be4398442549ee4f2292c85099777 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 22 Dec 2023 10:14:58 +0100 Subject: [PATCH 107/596] inline CanTargetMonster --- Source/controls/plrctrls.cpp | 36 +++++++++--------------------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index d950d930547..136ebc5ed11 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -169,39 +169,20 @@ static bool IsRangedSpell(int spl) && (spelldata[spl].sUseFlags & myplr._pSkillFlags) == spelldata[spl].sUseFlags; } -static int CanTargetMonster(int mnum) -{ - MonsterStruct* mon; - - // The first MAX_MINIONS monsters are reserved for players' golems. - if (mnum < MAX_MINIONS) - return 0; - - mon = &monsters[mnum]; - if (mon->_mmode > MM_INGAME_LAST) - return 0; - if (mon->_mFlags & MFLAG_HIDDEN) - return 0; - if (mon->_mhitpoints < (1 << 6)) // dead - return 0; - - if (!(dFlags[mon->_mx][mon->_my] & BFLAG_VISIBLE)) - return 0; - - return CanTalkToMonst(mnum) ? 2 : 1; -} - static void CheckMonstersNearby(bool ranged) { int newDistance, rotations, distance = MAXDUNX + MAXDUNY, mnum; bool canTalk = true; - for (mnum = 0; mnum < MAXMONSTERS; mnum++) { - const int tgtMode = CanTargetMonster(mnum); - if (tgtMode == 0) - continue; - const bool newCanTalk = tgtMode - 1; + for (mnum = MAX_MINIONS; mnum < MAXMONSTERS; mnum++) { const MonsterStruct& mon = monsters[mnum]; + if (mon._mmode > MM_INGAME_LAST || mon._mmode == MM_DEATH) + continue; + if (mon._mFlags & MFLAG_HIDDEN) + continue; + if (!(dFlags[mon._mx][mon._my] & BFLAG_VISIBLE)) + continue; + const int mx = mon._mfutx; const int my = mon._mfuty; if (ranged) { @@ -211,6 +192,7 @@ static void CheckMonstersNearby(bool ranged) if (newDistance < 0) continue; } + const bool newCanTalk = CanTalkToMonst(mnum); const int newRotations = GetRotaryDistance(mx, my); if (canTalk == newCanTalk) { if (distance < newDistance) From f26f3b19be4f50b498e55df1592ab41dff0e2087 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 22 Dec 2023 10:25:34 +0100 Subject: [PATCH 108/596] bugfix for devilutionx (targeting players with controller) - check visibility of the (current) px/py --- Source/controls/plrctrls.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index 136ebc5ed11..d020fd4ceb7 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -227,10 +227,11 @@ static void FindPlayer(int mode, bool ranged) continue; if ((mode == 2) != (plr._pHitPoints == 0)) continue; + if (!(dFlags[plr._px][plr._py] & BFLAG_VISIBLE)) + continue; + const int mx = plr._pfutx; const int my = plr._pfuty; - if (!(dFlags[mx][my] & BFLAG_VISIBLE)) - continue; if (ranged) { newDistance = GetDistanceRanged(mx, my); } else { From 0373324a53a99e0274af31999960909c7729413a Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 22 Dec 2023 10:34:12 +0100 Subject: [PATCH 109/596] inline FindMonster + rename CheckMonstersNearby to FindMonster + rename CheckTownersNearby to FindTowner --- Source/controls/plrctrls.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index d020fd4ceb7..4a0f6c4e837 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -150,7 +150,7 @@ static void FindObject() } } -static void CheckTownersNearby() +static void FindTowner() { for (int i = MAX_MINIONS; i < numtowners; i++) { int distance = GetDistance(monsters[i]._mx, monsters[i]._my, 2); @@ -169,7 +169,11 @@ static bool IsRangedSpell(int spl) && (spelldata[spl].sUseFlags & myplr._pSkillFlags) == spelldata[spl].sUseFlags; } -static void CheckMonstersNearby(bool ranged) +/** + * @brief Find a monster to target + * @param ranged: whether the current player is melee or ranged + */ +static void FindMonster(bool ranged) { int newDistance, rotations, distance = MAXDUNX + MAXDUNY, mnum; bool canTalk = true; @@ -263,14 +267,6 @@ static void FindPlayer(int mode, bool ranged) } } -static void FindMonster(bool ranged) -{ - if (currLvl._dType != DTYPE_TOWN) - CheckMonstersNearby(ranged); - else - CheckTownersNearby(); -} - static void FindTrigger() { int rotations; @@ -1001,7 +997,10 @@ void plrctrls_after_check_curs_move() switch (pcurstgt) { case TGT_NORMAL: - FindMonster(ranged); + if (currLvl._dType != DTYPE_TOWN) + FindMonster(ranged); + else + FindTowner(); if (!IsLocalGame && pcursmonst == MON_NONE) FindPlayer(0, ranged); FindItem(); From 34f2da97c882c62b2c39c44b5e7e9b28d0c5f5ee Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 22 Dec 2023 10:44:17 +0100 Subject: [PATCH 110/596] cosmetic --- Source/controls/plrctrls.cpp | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index 4a0f6c4e837..6f2daba7caf 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -99,7 +99,7 @@ static void FindItem() int my = myplr._pfuty; int rotations = 5; - static_assert(DBORDERX >= 1 && DBORDERY >= 1, "FindItemOrObject expects a large enough border."); + static_assert(DBORDERX >= 1 && DBORDERY >= 1, "FindItem expects a large enough border."); for (int xx = -1; xx <= 1; xx++) { for (int yy = -1; yy <= 1; yy++) { int ii = dItem[mx + xx][my + yy]; @@ -127,6 +127,7 @@ static void FindObject() int my = myplr._pfuty; int rotations = 5; + static_assert(DBORDERX >= 1 && DBORDERY >= 1, "FindObject expects a large enough border."); for (int xx = -1; xx <= 1; xx++) { for (int yy = -1; yy <= 1; yy++) { int oi = dObject[mx + xx][my + yy]; @@ -160,8 +161,15 @@ static void FindTowner() } } -static bool IsRangedSpell(int spl) +static bool HasRangedSkill() { + if (myplr._pSkillFlags & SFLAG_RANGED) + return true; + + int spl = myplr._pAltAtkSkill; + if (spl == SPL_INVALID) + spl = myplr._pAltMoveSkill; + return spl != SPL_INVALID && spl != SPL_TOWN && spl != SPL_TELEPORT @@ -196,8 +204,8 @@ static void FindMonster(bool ranged) if (newDistance < 0) continue; } - const bool newCanTalk = CanTalkToMonst(mnum); const int newRotations = GetRotaryDistance(mx, my); + const bool newCanTalk = CanTalkToMonst(mnum); if (canTalk == newCanTalk) { if (distance < newDistance) continue; @@ -221,8 +229,7 @@ static void FindMonster(bool ranged) static void FindPlayer(int mode, bool ranged) { int newDistance, rotations, distance = MAXDUNX + MAXDUNY, pnum; - bool sameTeam; - sameTeam = mode == 0; + bool sameTeam = mode == 0; for (pnum = 0; pnum < MAX_PLRS; pnum++) { if (pnum == mypnum) @@ -244,8 +251,8 @@ static void FindPlayer(int mode, bool ranged) continue; } const int newRotations = GetRotaryDistance(mx, my); - bool newSameTeam = plr._pTeam == myplr._pTeam; - if (newSameTeam == sameTeam) { + const bool newSameTeam = plr._pTeam == myplr._pTeam; + if (sameTeam == newSameTeam) { if (distance < newDistance) continue; if (distance == newDistance && rotations < newRotations) @@ -990,10 +997,7 @@ void plrctrls_after_check_curs_move() } if (!gbInvflag) { *infostr = '\0'; - int spl = myplr._pAltAtkSkill; - if (spl == SPL_INVALID) - spl = myplr._pAltMoveSkill; - bool ranged = (myplr._pSkillFlags & SFLAG_RANGED) || IsRangedSpell(spl); + bool ranged = HasRangedSkill(); switch (pcurstgt) { case TGT_NORMAL: From 9c2ccbbea52063ec3a958a2c684baebe03d81b67 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 22 Dec 2023 10:55:38 +0100 Subject: [PATCH 111/596] reduce the number of returns in CheckCursMove --- Source/cursor.cpp | 204 +++++++++++++++++++++++----------------------- 1 file changed, 102 insertions(+), 102 deletions(-) diff --git a/Source/cursor.cpp b/Source/cursor.cpp index b3bf4392ab3..fbbd4f058e5 100644 --- a/Source/cursor.cpp +++ b/Source/cursor.cpp @@ -458,6 +458,100 @@ void CheckCursMove() switch (pcurstgt) { case TGT_NORMAL: + // select the previous monster/npc + if (pcursmonst != MON_NONE) { + for (int i = 4; i >= 0; i--) { + mi = curmon[i]; + if (mi != 0) { + mi = mi >= 0 ? mi - 1 : -(mi + 1); + if (mi != pcursmonst) { + continue; + } + if (!(monsters[mi]._mSelFlag & selFlag[i])) { + continue; + } + pcursmonst = mi; + pcurspos.x = mx + offx[i]; + pcurspos.y = my + offy[i]; + goto done; + } + } + } + // select a monster/npc + for (int i = 4; i >= 0; i--) { + mi = curmon[i]; + if (mi != 0) { + mi = mi >= 0 ? mi - 1 : -(mi + 1); + if (monsters[mi]._mhitpoints < (1 << 6) || (monsters[mi]._mFlags & MFLAG_HIDDEN)) { + continue; + } + if (!(monsters[mi]._mSelFlag & selFlag[i])) { + continue; + } + if (mi < MAX_MINIONS) { + break; + } + pcursmonst = mi; + pcurspos.x = mx + offx[i]; + pcurspos.y = my + offy[i]; + goto done; + } + } + // select a live player + for (int i = 2; i >= 0; i--) { + mi = curplr[i]; + if (mi != 0) { + mi = mi >= 0 ? mi - 1 : -(mi + 1); + if (mi == mypnum || plx(mi)._pHitPoints < (1 << 6)) { + continue; + } + pcursplr = mi; + pcurspos.x = mx + offx[i + 2]; + pcurspos.y = my + offy[i + 2]; + goto done; + } + } + // select a dead player + if (deadplr[0] != 0) { + pcursplr = deadplr[0]; + pcurspos.x = mx; + pcurspos.y = my; + goto done; + } + // select an object + for (int i = 4; i >= 0; i--) { + mi = curobj[i]; + if (mi != 0) { + mi = mi >= 0 ? mi - 1 : -(mi + 1); + if (!(objects[mi]._oSelFlag & selFlag[i])) { + continue; + } + pcursobj = mi; + pcurspos.x = mx + offx[i]; + pcurspos.y = my + offy[i]; + goto done; + } + } + // select an item + for (int i = 2; i >= 0; i--) { + mi = curitem[i]; + if (mi > 0) { + mi = mi - 1; + if (!(items[mi]._iSelFlag & selFlag[i + 2])) { + continue; + } + pcursitem = mi; + pcurspos.x = mx + offx[i + 2]; + pcurspos.y = my + offy[i + 2]; + goto done; + } + } + + pcurspos.x = mx; + pcurspos.y = my; + CheckTrigForce(); + CheckTownPortal(); +done: break; case TGT_ITEM: // select an item @@ -471,10 +565,10 @@ void CheckCursMove() pcursitem = mi; pcurspos.x = mx + offx[i + 2]; pcurspos.y = my + offy[i + 2]; - return; + break; } } - return; + break; case TGT_OBJECT: // select an object for (int i = 4; i >= 0; i--) { @@ -487,10 +581,10 @@ void CheckCursMove() pcursobj = mi; pcurspos.x = mx + offx[i]; pcurspos.y = my + offy[i]; - return; + break; } } - return; + break; case TGT_PLAYER: // select a live player for (int i = 2; i >= 0; i--) { @@ -503,117 +597,23 @@ void CheckCursMove() pcursplr = mi; pcurspos.x = mx + offx[i + 2]; pcurspos.y = my + offy[i + 2]; - return; + break; } } - return; + break; case TGT_DEAD: // select a dead player if (deadplr[0] != 0) { pcursplr = deadplr[0] - 1; pcurspos.x = mx; pcurspos.y = my; - return; } - return; + break; case TGT_NONE: - return; + break; default: ASSUME_UNREACHABLE } - // select the previous monster/npc - if (pcursmonst != MON_NONE) { - for (int i = 4; i >= 0; i--) { - mi = curmon[i]; - if (mi != 0) { - mi = mi >= 0 ? mi - 1 : -(mi + 1); - if (mi != pcursmonst) { - continue; - } - if (!(monsters[mi]._mSelFlag & selFlag[i])) { - continue; - } - pcursmonst = mi; - pcurspos.x = mx + offx[i]; - pcurspos.y = my + offy[i]; - return; - } - } - } - // select a monster/npc - for (int i = 4; i >= 0; i--) { - mi = curmon[i]; - if (mi != 0) { - mi = mi >= 0 ? mi - 1 : -(mi + 1); - if (monsters[mi]._mhitpoints < (1 << 6) || (monsters[mi]._mFlags & MFLAG_HIDDEN)) { - continue; - } - if (!(monsters[mi]._mSelFlag & selFlag[i])) { - continue; - } - if (mi < MAX_MINIONS) { - break; - } - pcursmonst = mi; - pcurspos.x = mx + offx[i]; - pcurspos.y = my + offy[i]; - return; - } - } - // select a live player - for (int i = 2; i >= 0; i--) { - mi = curplr[i]; - if (mi != 0) { - mi = mi >= 0 ? mi - 1 : -(mi + 1); - if (mi == mypnum || plx(mi)._pHitPoints < (1 << 6)) { - continue; - } - pcursplr = mi; - pcurspos.x = mx + offx[i + 2]; - pcurspos.y = my + offy[i + 2]; - return; - } - } - // select a dead player - if (deadplr[0] != 0) { - pcursplr = deadplr[0]; - pcurspos.x = mx; - pcurspos.y = my; - return; - } - // select an object - for (int i = 4; i >= 0; i--) { - mi = curobj[i]; - if (mi != 0) { - mi = mi >= 0 ? mi - 1 : -(mi + 1); - if (!(objects[mi]._oSelFlag & selFlag[i])) { - continue; - } - pcursobj = mi; - pcurspos.x = mx + offx[i]; - pcurspos.y = my + offy[i]; - return; - } - } - // select an item - for (int i = 2; i >= 0; i--) { - mi = curitem[i]; - if (mi > 0) { - mi = mi - 1; - if (!(items[mi]._iSelFlag & selFlag[i + 2])) { - continue; - } - pcursitem = mi; - pcurspos.x = mx + offx[i + 2]; - pcurspos.y = my + offy[i + 2]; - return; - } - } - - pcurspos.x = mx; - pcurspos.y = my; - CheckTrigForce(); - CheckTownPortal(); } DEVILUTION_END_NAMESPACE From 32adbf59e3b133b341fc77d663258e5df328e50f Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 22 Dec 2023 11:30:05 +0100 Subject: [PATCH 112/596] define 'i' local at the beginning of CheckCursMove --- Source/cursor.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Source/cursor.cpp b/Source/cursor.cpp index fbbd4f058e5..a801f1b1131 100644 --- a/Source/cursor.cpp +++ b/Source/cursor.cpp @@ -269,7 +269,7 @@ void CheckTownPortal() void CheckCursMove() { - int pnum, sx, sy, /*fx, fy,*/ mx, my, tx, ty, px, py, mi; + int i, pnum, sx, sy, /*fx, fy,*/ mx, my, tx, ty, px, py, mi; bool flipflag, flipx, flipy; pcursmonst = MON_NONE; @@ -293,7 +293,7 @@ void CheckCursMove() if (POS_IN_RECT(sx, sy, gnWndBeltX, gnWndBeltY, BELT_WIDTH, BELT_HEIGHT)) pcurswnd = WND_BELT; - for (int i = 0; i < gnNumActiveWindows; i++) { + for (i = 0; i < gnNumActiveWindows; i++) { switch (gaActiveWindows[i]) { case WND_INV: if (POS_IN_RECT(sx, sy, gnWndInvX, gnWndInvY, SPANEL_WIDTH, SPANEL_HEIGHT)) @@ -460,7 +460,7 @@ void CheckCursMove() case TGT_NORMAL: // select the previous monster/npc if (pcursmonst != MON_NONE) { - for (int i = 4; i >= 0; i--) { + for (i = 4; i >= 0; i--) { mi = curmon[i]; if (mi != 0) { mi = mi >= 0 ? mi - 1 : -(mi + 1); @@ -478,7 +478,7 @@ void CheckCursMove() } } // select a monster/npc - for (int i = 4; i >= 0; i--) { + for (i = 4; i >= 0; i--) { mi = curmon[i]; if (mi != 0) { mi = mi >= 0 ? mi - 1 : -(mi + 1); @@ -498,7 +498,7 @@ void CheckCursMove() } } // select a live player - for (int i = 2; i >= 0; i--) { + for (i = 2; i >= 0; i--) { mi = curplr[i]; if (mi != 0) { mi = mi >= 0 ? mi - 1 : -(mi + 1); @@ -519,7 +519,7 @@ void CheckCursMove() goto done; } // select an object - for (int i = 4; i >= 0; i--) { + for (i = 4; i >= 0; i--) { mi = curobj[i]; if (mi != 0) { mi = mi >= 0 ? mi - 1 : -(mi + 1); @@ -533,7 +533,7 @@ void CheckCursMove() } } // select an item - for (int i = 2; i >= 0; i--) { + for (i = 2; i >= 0; i--) { mi = curitem[i]; if (mi > 0) { mi = mi - 1; @@ -555,7 +555,7 @@ void CheckCursMove() break; case TGT_ITEM: // select an item - for (int i = 2; i >= 0; i--) { + for (i = 2; i >= 0; i--) { mi = curitem[i]; if (mi > 0) { mi = mi - 1; @@ -571,7 +571,7 @@ void CheckCursMove() break; case TGT_OBJECT: // select an object - for (int i = 4; i >= 0; i--) { + for (i = 4; i >= 0; i--) { mi = curobj[i]; if (mi != 0) { mi = mi >= 0 ? mi - 1 : -(mi + 1); @@ -587,7 +587,7 @@ void CheckCursMove() break; case TGT_PLAYER: // select a live player - for (int i = 2; i >= 0; i--) { + for (i = 2; i >= 0; i--) { mi = curplr[i]; if (mi != 0) { mi = mi >= 0 ? mi - 1 : -(mi + 1); From 823ef398dc832ed8432db8ceb3b87fc49ac4245f Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 22 Dec 2023 19:37:10 +0100 Subject: [PATCH 113/596] bugfix for 'fix connection of multiple (more than 2) entities' - prevent sending CMD_SYNCDATA with the initial turn --- Source/nthread.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/nthread.cpp b/Source/nthread.cpp index 3fdd9df48b4..737de88273e 100644 --- a/Source/nthread.cpp +++ b/Source/nthread.cpp @@ -200,6 +200,7 @@ static int SDLCALL nthread_handler(void* data) #endif void nthread_start() { + gbLvlLoad = 10; // TODO: duplicate logic in nthread_run... assert(geBufferMsgs == MSG_NORMAL); guNextTick = SDL_GetTicks() /*+ gnTickDelay*/; if (gbJoinGame) { From e380b74eade7750f5cbd134fdd6a8d16bb915352 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 23 Dec 2023 09:14:53 +0100 Subject: [PATCH 114/596] naming conventions - rename CMD_TWARP to CMD_USEPORTAL - rename On_TWARP to On_USEPORTAL - rename StartTWarp to UseTownPortal - rename ENTRY_WARPLVL to ENTRY_PORTLVL - rename DVL_DWM_WARPLVL to DVL_DWM_PORTLVL --- Source/diablo.cpp | 2 +- Source/interfac.cpp | 4 ++-- Source/miniwin/miniwin.h | 2 +- Source/missiles.cpp | 2 +- Source/msg.cpp | 8 ++++---- Source/player.cpp | 8 ++++---- Source/player.h | 2 +- Source/trigs.cpp | 4 ++-- enums.h | 4 ++-- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Source/diablo.cpp b/Source/diablo.cpp index 6a25131c12b..736b53cee0c 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -1169,7 +1169,7 @@ static void GameWndProc(const Dvl_Event* e) case DVL_DWM_PREVLVL: case DVL_DWM_SETLVL: case DVL_DWM_RTNLVL: - case DVL_DWM_WARPLVL: + case DVL_DWM_PORTLVL: case DVL_DWM_TWARPDN: case DVL_DWM_TWARPUP: case DVL_DWM_RETOWN: diff --git a/Source/interfac.cpp b/Source/interfac.cpp index 62d06a64791..c42d5fe8dc9 100644 --- a/Source/interfac.cpp +++ b/Source/interfac.cpp @@ -58,7 +58,7 @@ static void InitCutscene(unsigned int uMsg) lvl = currLvl._dLevelIdx; InitLvlCutscene(lvl); break; - case DVL_DWM_WARPLVL: + case DVL_DWM_PORTLVL: sgpBackCel = CelLoadImage("Gendata\\Cutportl.CEL", PANEL_WIDTH); LoadPalette("Gendata\\Cutportl.pal"); sgbLoadBarOnTop = FALSE; @@ -324,7 +324,7 @@ void ShowCutscene(unsigned uMsg) static_assert((int)DVL_DWM_PREVLVL - (int)DVL_DWM_NEXTLVL == (int)ENTRY_PREV - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted II."); static_assert((int)DVL_DWM_SETLVL - (int)DVL_DWM_NEXTLVL == (int)ENTRY_SETLVL - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted III."); static_assert((int)DVL_DWM_RTNLVL - (int)DVL_DWM_NEXTLVL == (int)ENTRY_RTNLVL - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted IV."); - static_assert((int)DVL_DWM_WARPLVL - (int)DVL_DWM_NEXTLVL == (int)ENTRY_WARPLVL - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted V."); + static_assert((int)DVL_DWM_PORTLVL - (int)DVL_DWM_NEXTLVL == (int)ENTRY_PORTLVL - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted V."); static_assert((int)DVL_DWM_TWARPDN - (int)DVL_DWM_NEXTLVL == (int)ENTRY_TWARPDN - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted VI."); static_assert((int)DVL_DWM_TWARPUP - (int)DVL_DWM_NEXTLVL == (int)ENTRY_TWARPUP - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted VII."); static_assert((int)DVL_DWM_RETOWN - (int)DVL_DWM_NEXTLVL == (int)ENTRY_RETOWN - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted VIII."); diff --git a/Source/miniwin/miniwin.h b/Source/miniwin/miniwin.h index aafc89fcff9..5738fed147c 100644 --- a/Source/miniwin/miniwin.h +++ b/Source/miniwin/miniwin.h @@ -41,7 +41,7 @@ typedef enum window_messages { DVL_DWM_PREVLVL, // dungeon -> previous level DVL_DWM_SETLVL, // dungeon -> setlevel DVL_DWM_RTNLVL, // setlevel -> dungeon - DVL_DWM_WARPLVL, // portal (town <-> dungeon) + DVL_DWM_PORTLVL, // portal (town <-> dungeon) DVL_DWM_TWARPDN, // town -> dungeon DVL_DWM_TWARPUP, // dungeon -> town DVL_DWM_RETOWN, // restart in town diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 5b235653c5d..e46b2532a14 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -4096,7 +4096,7 @@ void MI_Portal(int mi) p = &myplr; if (p->_px == mis->_mix && p->_py == mis->_miy && /*!p->_pLvlChanging &&*/ p->_pmode == PM_STAND && !mis->_miVar3) { mis->_miVar3 = TRUE; - NetSendCmdBParam1(CMD_TWARP, mis->_miSource); + NetSendCmdBParam1(CMD_USEPORTAL, mis->_miSource); } } diff --git a/Source/msg.cpp b/Source/msg.cpp index 62448c8ed0b..d20b5596809 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -2696,7 +2696,7 @@ static unsigned On_NEWLVL(TCmd* pCmd, int pnum) return sizeof(*cmd); } -static unsigned On_TWARP(TCmd* pCmd, int pnum) +static unsigned On_USEPORTAL(TCmd* pCmd, int pnum) { TCmdBParam1* cmd = (TCmdBParam1*)pCmd; BYTE idx = cmd->bParam1; @@ -2704,7 +2704,7 @@ static unsigned On_TWARP(TCmd* pCmd, int pnum) net_assert(idx < MAX_PLRS); if (plr._pmode != PM_DEATH) - StartTWarp(pnum, idx); + UseTownPortal(pnum, idx); return sizeof(*cmd); } @@ -4455,8 +4455,8 @@ unsigned ParseCmd(int pnum, TCmd* pCmd) return On_ACTIVATEPORTAL(pCmd, pnum); case CMD_NEWLVL: return On_NEWLVL(pCmd, pnum); - case CMD_TWARP: - return On_TWARP(pCmd, pnum); + case CMD_USEPORTAL: + return On_USEPORTAL(pCmd, pnum); case CMD_RETOWN: return On_RETOWN(pCmd, pnum); case CMD_JOINLEVEL: diff --git a/Source/player.cpp b/Source/player.cpp index 8ab10bfa6b9..4ff530d09d8 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -1803,10 +1803,10 @@ void RestartTownLvl(int pnum) } } -void StartTWarp(int pnum, int pidx) +void UseTownPortal(int pnum, int pidx) { if ((unsigned)pnum >= MAX_PLRS) { - dev_fatal("StartWarpLvl: illegal player %d", pnum); + dev_fatal("UseTownPortal: illegal player %d", pnum); } InitLevelChange(pnum); @@ -1814,7 +1814,7 @@ void StartTWarp(int pnum, int pidx) plr._pDunLevel = DLV_TOWN; } else { plr._pDunLevel = portals[pidx]._rlevel; - static_assert(MAXPORTAL == MAX_PLRS, "StartTWarp uses pnum as portal-id."); + static_assert(MAXPORTAL == MAX_PLRS, "UseTownPortal uses pnum as portal-id."); if (pidx == pnum) { DeactivatePortal(pidx); } @@ -1822,7 +1822,7 @@ void StartTWarp(int pnum, int pidx) if (pnum == mypnum) { UseCurrentPortal(pidx); - PostMessage(DVL_DWM_WARPLVL); + PostMessage(DVL_DWM_PORTLVL); } } diff --git a/Source/player.h b/Source/player.h index 4be257f4d3d..26e0265e0e7 100644 --- a/Source/player.h +++ b/Source/player.h @@ -44,7 +44,7 @@ void SyncPlrKill(int pnum, int dmgtype); void SyncPlrResurrect(int pnum); void StartNewLvl(int pnum, int fom, int lvl); void RestartTownLvl(int pnum); -void StartTWarp(int pnum, int pidx); +void UseTownPortal(int pnum, int pidx); void PlrFillHp(int pnum); void PlrFillMana(int pnum); void PlrSetHp(int pnum, int hp); diff --git a/Source/trigs.cpp b/Source/trigs.cpp index 3c5b9960941..060f7fbd66c 100644 --- a/Source/trigs.cpp +++ b/Source/trigs.cpp @@ -146,7 +146,7 @@ void InitView(int entry) { int type; - if (entry == ENTRY_WARPLVL) { + if (entry == ENTRY_PORTLVL) { GetPortalLvlPos(); return; } @@ -224,7 +224,7 @@ void InitView(int entry) } break; case ENTRY_LOAD: // set from the save file - case ENTRY_WARPLVL: // should not happen + case ENTRY_PORTLVL: // should not happen return; case ENTRY_TWARPDN: type = DWARP_TOWN; diff --git a/enums.h b/enums.h index ce8461c0c84..dabf9db66a5 100644 --- a/enums.h +++ b/enums.h @@ -3742,7 +3742,7 @@ typedef enum lvl_entry { ENTRY_PREV, ENTRY_SETLVL, ENTRY_RTNLVL, - ENTRY_WARPLVL, + ENTRY_PORTLVL, ENTRY_TWARPDN, ENTRY_TWARPUP, ENTRY_RETOWN, @@ -3889,7 +3889,7 @@ typedef enum _cmd_id { CMD_TELEKINOID, CMD_ACTIVATEPORTAL, CMD_NEWLVL, - CMD_TWARP, + CMD_USEPORTAL, CMD_RETOWN, CMD_JOINLEVEL, CMD_DISCONNECT, From c27ac2a59e0e73e97731b22e7ea5c5e61d6a9289 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 23 Dec 2023 10:48:21 +0100 Subject: [PATCH 115/596] cosmetic --- Source/monster.cpp | 2 +- Source/multi.cpp | 1 + Source/nthread.cpp | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index db5ed72ac21..5313ea7afc2 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -702,7 +702,7 @@ static bool MonstPlace(int xp, int yp) { static_assert(DBORDERX >= MON_PACK_DISTANCE, "MonstPlace does not check IN_DUNGEON_AREA but expects a large enough border I."); static_assert(DBORDERY >= MON_PACK_DISTANCE, "MonstPlace does not check IN_DUNGEON_AREA but expects a large enough border II."); - return (dMonster[xp][yp]/* | /*dPlayer[xp][yp] | dObject[xp][yp]*/ + return (dMonster[xp][yp]/* | dPlayer[xp][yp] | dObject[xp][yp]*/ | nSolidTable[dPiece[xp][yp]] | (dFlags[xp][yp] & (BFLAG_ALERT | BFLAG_MON_PROTECT))) == 0; } diff --git a/Source/multi.cpp b/Source/multi.cpp index 65cf389303d..3d6ee062e1a 100644 --- a/Source/multi.cpp +++ b/Source/multi.cpp @@ -684,6 +684,7 @@ static void SetupLocalPlr() if (p->_pHitPoints < (1 << 6)) PlrSetHp(mypnum, (1 << 6)); + assert(p->_pWalkpath[0] == DIR_NONE); assert(p->_pDestAction == ACTION_NONE); p->_pLvlChanging = TRUE; //p->_pInvincible = TRUE; - does not matter in town diff --git a/Source/nthread.cpp b/Source/nthread.cpp index 737de88273e..db0e7abb34d 100644 --- a/Source/nthread.cpp +++ b/Source/nthread.cpp @@ -200,7 +200,7 @@ static int SDLCALL nthread_handler(void* data) #endif void nthread_start() { - gbLvlLoad = 10; // TODO: duplicate logic in nthread_run... + gbLvlLoad = 10; // TODO: set this when _pLvlChanging of the local player is set to TRUE? assert(geBufferMsgs == MSG_NORMAL); guNextTick = SDL_GetTicks() /*+ gnTickDelay*/; if (gbJoinGame) { From 334fb65de8df21a8c1627f474fa1071fb0ffaeb3 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 23 Dec 2023 10:55:43 +0100 Subject: [PATCH 116/596] bugfix for 'cleanup of MonsterStructs and monster initialization' (less intrusive handling of gargoyles) --- Source/monster.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 5313ea7afc2..c16aef88e3d 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3670,7 +3670,7 @@ void MAI_Garg(int mnum) return; } } - if (mon->_mmode != MM_SPATTACK) { + if (mon->_mmode != MM_SPATTACK && mon->_mmode != MM_STONE) { if (mon->_mleaderflag == MLEADER_NONE) { MonStartSpAttack(mnum); mon->_mFlags |= MFLAG_LOCK_ANIMATION; From b9a3ee16087caa417d95d66f5120d73aece41c37 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 23 Dec 2023 11:08:25 +0100 Subject: [PATCH 117/596] make gargoyles immune to stone curse --- Source/debug.cpp | 4 ++++ Source/monstdat.cpp | 8 ++++---- Source/monster.cpp | 3 ++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Source/debug.cpp b/Source/debug.cpp index 71e4275425f..e20944c1878 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -264,6 +264,8 @@ void ValidateData() #endif if ((md.mAI.aiType == AI_CLEAVER || md.mAI.aiType == AI_FAT || md.mAI.aiType == AI_BAT) && (md.mFlags & MFLAG_CAN_OPEN_DOOR) && !(md.mFlags & MFLAG_SEARCH)) app_fatal("AI_CLEAVER, AI_FAT and AI_BAT only check the doors while searching (%s, %d)", md.mName, i); + if (md.mAI.aiType == AI_GARG && !(md.mFlags & MFLAG_NOSTONE)) + app_fatal("AI_GARG might override stoned state (%s, %d)", md.mName, i); // required by MAI_Garg if (md.mAI.aiInt > UINT8_MAX - HELL_LEVEL_BONUS / 16) // required by InitMonsterStats app_fatal("Too high aiInt %d for %s (%d).", md.mLevel, md.mName, i); if (md.mLevel == 0) // required by InitMonsterStats @@ -392,6 +394,8 @@ void ValidateData() #endif if ((um.mAI.aiType == AI_CLEAVER || um.mAI.aiType == AI_FAT) && (monsterdata[um.mtype].mFlags & MFLAG_CAN_OPEN_DOOR) && !(monsterdata[um.mtype].mFlags & MFLAG_SEARCH)) app_fatal("Unique AI_CLEAVER and AI_FAT only check the doors while searching (%s, %d)", um.mName, i); + if (um.mAI.aiType == AI_GARG && !(monsterdata[um.mtype].mFlags & MFLAG_NOSTONE)) + app_fatal("Unique AI_GARG might override stoned state (%s, %d)", um.mName, i); // required by MAI_Garg if (um.mAI.aiInt > UINT8_MAX - HELL_LEVEL_BONUS / 16) // required by InitUniqueMonster app_fatal("Too high aiInt %d for %s (%d).", um.muLevel, um.mName, i); if (um.muLevel == 0) // required by InitUniqueMonster diff --git a/Source/monstdat.cpp b/Source/monstdat.cpp index a4c9e842df0..181825a8360 100644 --- a/Source/monstdat.cpp +++ b/Source/monstdat.cpp @@ -91,10 +91,10 @@ const MonsterData monsterdata[NUM_MTYPES] = { /* MT_NTHIN */ { MOFILE_THIN, 20, 7, NULL, "Storm Rider", { AI_ROUNDRANGED, 1, MIS_LIGHTNINGC2, 0 }, 60, 120, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 80, 8, 18, 0, 0, 0, 50, 0, 30, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2391, ALIGN }, // MC_DEMON, /* MT_XTHIN */ { MOFILE_THIN, 22, 7, "Monsters\\Thin\\Thinv2.TRN", "Storm Lord", { AI_ROUNDRANGED, 2, MIS_LIGHTNINGC2, 0 }, 75, 135, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 85, 12, 24, 0, 0, 0, 55, 0, 35, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2775, ALIGN }, // MC_DEMON, /* MT_GTHIN */ { MOFILE_THIN, 24, 7, "Monsters\\Thin\\Thinv1.TRN", "Maelstrom", { AI_ROUNDRANGED, 3, MIS_LIGHTNINGC2, 0 }, 90, 150, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 90, 12, 28, 0, 0, 0, 60, 0, 40, 25, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 3177, ALIGN }, // MC_DEMON, -/* MT_NGARG */ { MOFILE_GARGOYLE, 9, 6, NULL, "Winged-Demon", { AI_GARG, 0, FALSE, 0 }, 45, 60, MFLAG_GARG_STONE | MFLAG_CAN_OPEN_DOOR, 50, 10, 16, 0, 0, 0, 0, 0, 45, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 662, ALIGN }, // MC_DEMON, -/* MT_XGARG */ { MOFILE_GARGOYLE, 13, 6, "Monsters\\Gargoyle\\GarE.TRN", "Gargoyle", { AI_GARG, 1, FALSE, 0 }, 60, 90, MFLAG_GARG_STONE | MFLAG_CAN_OPEN_DOOR, 65, 10, 16, 0, 0, 0, 0, 0, 45, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 1205, ALIGN }, // MC_DEMON, -/* MT_DGARG */ { MOFILE_GARGOYLE, 19, 6, "Monsters\\Gargoyle\\GargBr.TRN", "Blood Claw", { AI_GARG, 2, FALSE, 0 }, 75, 125, MFLAG_GARG_STONE | MFLAG_CAN_OPEN_DOOR, 80, 14, 22, 0, 0, 0, 0, 0, 50, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1873, ALIGN }, // MC_DEMON, -/* MT_BGARG */ { MOFILE_GARGOYLE, 23, 6, "Monsters\\Gargoyle\\GargB.TRN", "Death Wing", { AI_GARG, 3, FALSE, 0 }, 90, 150, MFLAG_GARG_STONE | MFLAG_CAN_OPEN_DOOR, 95, 16, 28, 0, 0, 0, 0, 0, 60, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2278, ALIGN }, // MC_DEMON, +/* MT_NGARG */ { MOFILE_GARGOYLE, 9, 6, NULL, "Winged-Demon", { AI_GARG, 0, FALSE, 0 }, 45, 60, MFLAG_GARG_STONE | MFLAG_NOSTONE | MFLAG_CAN_OPEN_DOOR, 50, 10, 16, 0, 0, 0, 0, 0, 45, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 662, ALIGN }, // MC_DEMON, +/* MT_XGARG */ { MOFILE_GARGOYLE, 13, 6, "Monsters\\Gargoyle\\GarE.TRN", "Gargoyle", { AI_GARG, 1, FALSE, 0 }, 60, 90, MFLAG_GARG_STONE | MFLAG_NOSTONE | MFLAG_CAN_OPEN_DOOR, 65, 10, 16, 0, 0, 0, 0, 0, 45, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 1205, ALIGN }, // MC_DEMON, +/* MT_DGARG */ { MOFILE_GARGOYLE, 19, 6, "Monsters\\Gargoyle\\GargBr.TRN", "Blood Claw", { AI_GARG, 2, FALSE, 0 }, 75, 125, MFLAG_GARG_STONE | MFLAG_NOSTONE | MFLAG_CAN_OPEN_DOOR, 80, 14, 22, 0, 0, 0, 0, 0, 50, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1873, ALIGN }, // MC_DEMON, +/* MT_BGARG */ { MOFILE_GARGOYLE, 23, 6, "Monsters\\Gargoyle\\GargB.TRN", "Death Wing", { AI_GARG, 3, FALSE, 0 }, 90, 150, MFLAG_GARG_STONE | MFLAG_NOSTONE | MFLAG_CAN_OPEN_DOOR, 95, 16, 28, 0, 0, 0, 0, 0, 60, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2278, ALIGN }, // MC_DEMON, /* MT_NMEGA */ { MOFILE_MEGA, 20, 7, NULL, "Slayer", { AI_ROUNDRANGED2, 0, MIS_INFERNOC, 0 }, 120, 140, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 100, 12, 20, 0, 0, 0, 50, 0, 60, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 2300, ALIGN }, // MC_DEMON, /* MT_DMEGA */ { MOFILE_MEGA, 22, 7, "Monsters\\Mega\\Guard.TRN", "Guardian", { AI_ROUNDRANGED2, 1, MIS_INFERNOC, 0 }, 140, 160, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 110, 14, 22, 0, 0, 0, 55, 0, 65, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 2714, ALIGN }, // MC_DEMON, /* MT_BMEGA */ { MOFILE_MEGA, 24, 7, "Monsters\\Mega\\Vtexl.TRN", "Vortex Lord", { AI_ROUNDRANGED2, 2, MIS_INFERNOC, 0 }, 160, 180, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 120, 18, 24, 0, 0, 0, 60, 0, 70, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 3252, ALIGN }, // MC_DEMON, diff --git a/Source/monster.cpp b/Source/monster.cpp index c16aef88e3d..5f7e52eac64 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3670,7 +3670,8 @@ void MAI_Garg(int mnum) return; } } - if (mon->_mmode != MM_SPATTACK && mon->_mmode != MM_STONE) { + if (mon->_mmode != MM_SPATTACK) { + // assert(mon->_mmode != MM_STONE); if (mon->_mleaderflag == MLEADER_NONE) { MonStartSpAttack(mnum); mon->_mFlags |= MFLAG_LOCK_ANIMATION; From 24c6c787bd087ead4538afda4f21c92cd3859f2e Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 23 Dec 2023 11:19:03 +0100 Subject: [PATCH 118/596] check _mmode instead of mhitpoints in CheckMonsterHit + ensure reserved/dead/etc. monsters are not affected by telekinesis --- Source/missiles.cpp | 2 +- Source/monster.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index e46b2532a14..ac848f362fb 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -3291,7 +3291,7 @@ int AddTelekinesis(int mi, int sx, int sy, int dx, int dy, int midir, int micast case MTT_MONSTER: // assert(target < MAXMONSTERS); if (LineClear(plr._px, plr._py, monsters[target]._mx, monsters[target]._my) - && CheckMonsterHit(target, &ret) && monsters[target]._mmode != MM_STONE && monsters[target]._mmode != MM_DEATH && (monsters[target]._mmaxhp >> (6 + 1)) < plr._pMagic) { + && CheckMonsterHit(target, &ret) && monsters[target]._mmode != MM_STONE && monsters[target]._mmode <= MM_INGAME_LAST && (monsters[target]._mmaxhp >> (6 + 1)) < plr._pMagic) { monsters[target]._msquelch = SQUELCH_MAX; monsters[target]._mlastx = plr._px; monsters[target]._mlasty = plr._py; diff --git a/Source/monster.cpp b/Source/monster.cpp index 5f7e52eac64..8eb089bbc0d 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -5047,7 +5047,7 @@ bool CheckMonsterHit(int mnum, bool* ret) } mon = &monsters[mnum]; - if (mon->_mgoal == MGOAL_TALKING || mon->_mmode == MM_CHARGE || mon->_mhitpoints < (1 << 6) + if (mon->_mgoal == MGOAL_TALKING || mon->_mmode == MM_CHARGE || mon->_mmode == MM_DEATH || (mon->_mAI.aiType == AI_SNEAK && mon->_mgoal == MGOAL_RETREAT) || (mon->_mAI.aiType == AI_COUNSLR && mon->_mgoal != MGOAL_NORMAL)) { *ret = false; From cf79e9898a2347704d2ea789c47dee8e29903cbe Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 23 Dec 2023 12:31:20 +0100 Subject: [PATCH 119/596] bugfix for vanilla (sneak vs stone curse) - prevent invincible stoned sneak while it is retreating --- Source/monster.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 8eb089bbc0d..b973d7acb93 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -5048,7 +5048,7 @@ bool CheckMonsterHit(int mnum, bool* ret) mon = &monsters[mnum]; if (mon->_mgoal == MGOAL_TALKING || mon->_mmode == MM_CHARGE || mon->_mmode == MM_DEATH - || (mon->_mAI.aiType == AI_SNEAK && mon->_mgoal == MGOAL_RETREAT) + || (mon->_mAI.aiType == AI_SNEAK && mon->_mgoal == MGOAL_RETREAT && mon->_mmode != MM_STONE) || (mon->_mAI.aiType == AI_COUNSLR && mon->_mgoal != MGOAL_NORMAL)) { *ret = false; return false; From 7a56b0e7f9ad8fc3bb45d3ba9390fde4bde17f33 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 23 Dec 2023 17:12:40 +0100 Subject: [PATCH 120/596] 'bugfix' for vanilla (blocked counselors) - do not 'remove' blocked counselors from the game --- Source/monster.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index b973d7acb93..c786d7ade42 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -4111,17 +4111,17 @@ void MAI_Counselor(int mnum) MonStartDelay(mnum, v); } } else if (mon->_mgoal == MGOAL_RETREAT) { - if (--mon->_mgoalvar1 != 0) // RETREAT_DISTANCE - MonCallWalk(mnum, OPPOSITE(md)); - else { + if (--mon->_mgoalvar1 == 0 // RETREAT_DISTANCE + || !MonCallWalk(mnum, OPPOSITE(md))) { mon->_mgoal = MGOAL_NORMAL; MonStartFadein(mnum, md, true); } } else { assert(mon->_mgoal == MGOAL_MOVE); if (dist >= 2 /*&& mon->_msquelch == SQUELCH_MAX && dTransVal[mon->_mx][mon->_my] == dTransVal[mon->_menemyx][mon->_menemyy]*/ - && (--mon->_mgoalvar1 > 4 || (mon->_mgoalvar1 > 0 && !MonDirOK(mnum, md)))) { // MOVE_DISTANCE - MonRoundWalk(mnum, md, &mon->_mgoalvar2); // MOVE_TURN_DIRECTION + && (--mon->_mgoalvar1 > 4 || (mon->_mgoalvar1 > 0 && !MonDirOK(mnum, md))) // MOVE_DISTANCE + && MonRoundWalk(mnum, md, &mon->_mgoalvar2)) { // MOVE_TURN_DIRECTION + ; } else { mon->_mgoal = MGOAL_NORMAL; MonStartFadein(mnum, md, true); From 685785c7cd9c4343615df44f91728069fc153512 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 23 Dec 2023 17:21:00 +0100 Subject: [PATCH 121/596] simplify PlrDecMana --- Source/player.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Source/player.cpp b/Source/player.cpp index 4ff530d09d8..396f1f2a33f 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -3278,10 +3278,8 @@ bool PlrDecHp(int pnum, int hp, int dmgtype) void PlrDecMana(int pnum, int mana) { - assert(mana >= 0); - if (plr._pIFlags & ISPL_NOMANA) - return; - + // assert(mana >= 0); + // assert(mana == 0 || !(plr._pIFlags & ISPL_NOMANA)); plr._pMana -= mana; plr._pManaBase -= mana; if (pnum == mypnum) { From 2e49a6bbebd9277e24cbce0c9ed2cb1e0900cc11 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 23 Dec 2023 17:21:55 +0100 Subject: [PATCH 122/596] 'improve' MAI_Counselor - do not attempt to retreat in case the path is blocked --- Source/monster.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index c786d7ade42..454a294fc57 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -2871,7 +2871,7 @@ static bool MonDirOK(int mnum, int mdir) return mcount == 0; } -static bool MonCallWalk(int mnum, int md) +static int MonFindDir(int mnum, int md) { int mdtemp; bool ok; @@ -2897,11 +2897,17 @@ static bool MonCallWalk(int mnum, int md) || (md = (mdtemp + 2) & 7, MonDirOK(mnum, md)); } } - if (ok) + return ok ? md : -1; +} + +static bool MonCallWalk(int mnum, int md) +{ + md = MonFindDir(mnum, md); + if (md >= 0) MonWalkDir(mnum, md); else MonFindEnemy(mnum); // prevent from stucking with an inaccessible enemy - return ok; + return md >= 0; } static bool MonDestWalk(int mnum) @@ -4093,7 +4099,7 @@ void MAI_Counselor(int mnum) mon->_mdir = md; if (mon->_mVar1 == MM_FADEIN) // STAND_PREV_MODE v >>= 1; - if (mon->_mVar1 != MM_FADEIN && mon->_mhitpoints < (mon->_mmaxhp >> 1)) { + if (mon->_mVar1 != MM_FADEIN && mon->_mhitpoints < (mon->_mmaxhp >> 1) && MonFindDir(mnum, OPPOSITE(md)) >= 0) { #if DEBUG assert(mon->_mAnims[MA_SPECIAL].maFrames * mon->_mAnims[MA_SPECIAL].maFrameLen * 2 + mon->_mAnims[MA_WALK].maFrames * mon->_mAnims[MA_WALK].maFrameLen * 5 < SQUELCH_MAX - SQUELCH_LOW); From ff1dc5dc623faee135b60bdc8a2d3ce685e3c059 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 23 Dec 2023 18:48:18 +0100 Subject: [PATCH 123/596] simplify MonCallWalk --- Source/monster.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 454a294fc57..7edd9ba4614 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -2905,8 +2905,8 @@ static bool MonCallWalk(int mnum, int md) md = MonFindDir(mnum, md); if (md >= 0) MonWalkDir(mnum, md); - else - MonFindEnemy(mnum); // prevent from stucking with an inaccessible enemy + //else + // MonFindEnemy(mnum); // prevent from stucking with an inaccessible enemy - not necessary if GroupUnity runs it unconditionally return md >= 0; } From 37f026644f92a23cc9c40f57b64d7443c3d8ec51 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 24 Dec 2023 08:36:13 +0100 Subject: [PATCH 124/596] test for MGOAL_NORMAL instead of MGOAL_RETREAT in MAI_Sneak --- Source/monster.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 7edd9ba4614..d4045589c67 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3224,7 +3224,7 @@ void MAI_Sneak(int mnum) range = 7 - mon->_mAI.aiInt; if (range < 4) range = 4; - if (mon->_mgoal != MGOAL_RETREAT) { + if (mon->_mgoal == MGOAL_NORMAL) { if (mon->_mVar1 == MM_GOTHIT) { // STAND_PREV_MODE mon->_mgoal = MGOAL_RETREAT; #if DEBUG @@ -3238,7 +3238,8 @@ void MAI_Sneak(int mnum) mon->_mgoal = MGOAL_NORMAL; } } - if (mon->_mgoal == MGOAL_RETREAT) { + if (mon->_mgoal != MGOAL_NORMAL) { + // assert(mon->_mgoal == MGOAL_RETREAT); md = OPPOSITE(currEnemyInfo._meLastDir); if (mon->_mType == MT_BSNEAK) { //md = random_(112, 2) != 0 ? left[md] : right[md]; @@ -3254,7 +3255,8 @@ void MAI_Sneak(int mnum) } else if ((dist > range) && !(mon->_mFlags & MFLAG_HIDDEN)) { MonStartFadeout(mnum, mon->_mdir, true); } else { - if (mon->_mgoal == MGOAL_RETREAT) { + if (mon->_mgoal != MGOAL_NORMAL) { + // assert(mon->_mgoal == MGOAL_RETREAT); if (MonCallWalk(mnum, mon->_mdir)) return; } else if (dist >= 2) { From b836df213608bb07d995ec5f583ede0ae174bd2a Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 24 Dec 2023 08:41:47 +0100 Subject: [PATCH 125/596] bugfix for vanilla (AI-sneak in corner) - prevent invincible sneak monsters when cornered --- Source/monster.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/monster.cpp b/Source/monster.cpp index d4045589c67..7663ce7dea1 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3259,6 +3259,7 @@ void MAI_Sneak(int mnum) // assert(mon->_mgoal == MGOAL_RETREAT); if (MonCallWalk(mnum, mon->_mdir)) return; + mon->_mgoal = MGOAL_NORMAL; } else if (dist >= 2) { if ((((unsigned)mon->_mVar2 > MON_WALK_DELAY && v < 4 * mon->_mAI.aiInt + 14) // STAND_TICK || (MON_JUST_WALKED && v < 4 * mon->_mAI.aiInt + 64))) From 584e9e056b552be48a7957d6b1d88f4fac5c8514 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 24 Dec 2023 08:45:10 +0100 Subject: [PATCH 126/596] move AI-Sneak to its enemy in case retreat fails --- Source/monster.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 7663ce7dea1..50332c7b924 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3260,14 +3260,14 @@ void MAI_Sneak(int mnum) if (MonCallWalk(mnum, mon->_mdir)) return; mon->_mgoal = MGOAL_NORMAL; - } else if (dist >= 2) { + } + if (dist >= 2) { if ((((unsigned)mon->_mVar2 > MON_WALK_DELAY && v < 4 * mon->_mAI.aiInt + 14) // STAND_TICK || (MON_JUST_WALKED && v < 4 * mon->_mAI.aiInt + 64))) MonDestWalk(mnum); - return; - } - if (dist < 2 && v < 4 * mon->_mAI.aiInt + 10) { - MonStartAttack(mnum); + } else { + if (v < 4 * mon->_mAI.aiInt + 10) + MonStartAttack(mnum); } } } From daa9d2a515f6fe7d898c6b12be82a69f1f794d96 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 24 Dec 2023 08:47:53 +0100 Subject: [PATCH 127/596] cosmetic --- Source/monster.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 50332c7b924..cbf764542ab 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3252,7 +3252,7 @@ void MAI_Sneak(int mnum) // assert(range >= 2); if (dist < range && (mon->_mFlags & MFLAG_HIDDEN)) { MonStartFadein(mnum, mon->_mdir, false); - } else if ((dist > range) && !(mon->_mFlags & MFLAG_HIDDEN)) { + } else if (dist > range && !(mon->_mFlags & MFLAG_HIDDEN)) { MonStartFadeout(mnum, mon->_mdir, true); } else { if (mon->_mgoal != MGOAL_NORMAL) { @@ -3262,8 +3262,8 @@ void MAI_Sneak(int mnum) mon->_mgoal = MGOAL_NORMAL; } if (dist >= 2) { - if ((((unsigned)mon->_mVar2 > MON_WALK_DELAY && v < 4 * mon->_mAI.aiInt + 14) // STAND_TICK - || (MON_JUST_WALKED && v < 4 * mon->_mAI.aiInt + 64))) + if (((unsigned)mon->_mVar2 > MON_WALK_DELAY && v < 4 * mon->_mAI.aiInt + 14) // STAND_TICK + || (MON_JUST_WALKED && v < 4 * mon->_mAI.aiInt + 64)) MonDestWalk(mnum); } else { if (v < 4 * mon->_mAI.aiInt + 10) From cb6e2cceb7ce9c036927840a52bddff792f275ea Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 24 Dec 2023 08:51:37 +0100 Subject: [PATCH 128/596] eliminate return in the middle of MAI_Sneak --- Source/monster.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index cbf764542ab..3ac235f8b81 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3254,13 +3254,9 @@ void MAI_Sneak(int mnum) MonStartFadein(mnum, mon->_mdir, false); } else if (dist > range && !(mon->_mFlags & MFLAG_HIDDEN)) { MonStartFadeout(mnum, mon->_mdir, true); - } else { - if (mon->_mgoal != MGOAL_NORMAL) { - // assert(mon->_mgoal == MGOAL_RETREAT); - if (MonCallWalk(mnum, mon->_mdir)) - return; - mon->_mgoal = MGOAL_NORMAL; - } + } else if (mon->_mgoal == MGOAL_NORMAL || !MonCallWalk(mnum, mon->_mdir)) { + // assert(mon->_mgoal == MGOAL_NORMAL || mon->_mgoal == MGOAL_RETREAT); + mon->_mgoal = MGOAL_NORMAL; if (dist >= 2) { if (((unsigned)mon->_mVar2 > MON_WALK_DELAY && v < 4 * mon->_mAI.aiInt + 14) // STAND_TICK || (MON_JUST_WALKED && v < 4 * mon->_mAI.aiInt + 64)) From f97c0d12d798b3ee6f6dff04d6a604d0561d7547 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 24 Dec 2023 09:00:07 +0100 Subject: [PATCH 129/596] eliminate premature optimization in plrctrls_after_check_curs_move --- Source/controls/plrctrls.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index 6f2daba7caf..8ebf2c0fa04 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -1005,7 +1005,7 @@ void plrctrls_after_check_curs_move() FindMonster(ranged); else FindTowner(); - if (!IsLocalGame && pcursmonst == MON_NONE) + if (pcursmonst == MON_NONE) FindPlayer(0, ranged); FindItem(); if (pcursitem == ITEM_NONE) From 81091cf9c0883956453b4d5e31e243a8230934fc Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 24 Dec 2023 09:04:53 +0100 Subject: [PATCH 130/596] 'bugfix' for vanilla (counselor vs fading) - make counselors invincible while fading (In vanilla the monster was invincible during fade-out, but not during fade-in) --- Source/monster.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 3ac235f8b81..c47b37e3d02 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -5052,9 +5052,8 @@ bool CheckMonsterHit(int mnum, bool* ret) } mon = &monsters[mnum]; - if (mon->_mgoal == MGOAL_TALKING || mon->_mmode == MM_CHARGE || mon->_mmode == MM_DEATH - || (mon->_mAI.aiType == AI_SNEAK && mon->_mgoal == MGOAL_RETREAT && mon->_mmode != MM_STONE) - || (mon->_mAI.aiType == AI_COUNSLR && mon->_mgoal != MGOAL_NORMAL)) { + if (mon->_mgoal == MGOAL_TALKING || mon->_mmode == MM_CHARGE || mon->_mmode == MM_DEATH || mon->_mmode == MM_FADEIN || mon->_mmode == MM_FADEOUT + || (mon->_mAI.aiType == AI_SNEAK && mon->_mgoal == MGOAL_RETREAT && mon->_mmode != MM_STONE)) { *ret = false; return false; } From c9b8300b15d60acbae3663508c7d1d06adcd208b Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 24 Dec 2023 09:08:12 +0100 Subject: [PATCH 131/596] reduce the number of mid-returns in CheckMonsterHit --- Source/monster.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index c47b37e3d02..e32127063d4 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -5046,26 +5046,23 @@ bool CanTalkToMonst(int mnum) bool CheckMonsterHit(int mnum, bool* ret) { MonsterStruct* mon; + bool result = true; if ((unsigned)mnum >= MAXMONSTERS) { dev_fatal("CheckMonsterHit: Invalid monster %d", mnum); } mon = &monsters[mnum]; - if (mon->_mgoal == MGOAL_TALKING || mon->_mmode == MM_CHARGE || mon->_mmode == MM_DEATH || mon->_mmode == MM_FADEIN || mon->_mmode == MM_FADEOUT || (mon->_mAI.aiType == AI_SNEAK && mon->_mgoal == MGOAL_RETREAT && mon->_mmode != MM_STONE)) { *ret = false; - return false; - } - - if (mon->_mAI.aiType == AI_GARG && mon->_mFlags & MFLAG_GARG_STONE) { + result = false; + } else if (mon->_mAI.aiType == AI_GARG && mon->_mFlags & MFLAG_GARG_STONE) { mon->_mFlags &= ~(MFLAG_GARG_STONE | MFLAG_LOCK_ANIMATION); - // mon->_mmode = MM_SPATTACK; *ret = true; - return false; + result = false; } - return true; + return result; } DEVILUTION_END_NAMESPACE From 543093d7c7a33346137e1d652c08a4a8b9864851 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 24 Dec 2023 09:20:32 +0100 Subject: [PATCH 132/596] eliminate mid-returns in MAI_Ranged --- Source/monster.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index e32127063d4..23a4d3f51f8 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3499,14 +3499,13 @@ void MAI_Ranged(int mnum) MonStartRSpAttack(mnum, mon->_mAI.aiParam1); else MonStartRAttack(mnum, mon->_mAI.aiParam1); - return; } else if (currEnemyInfo._meRealDist >= 4 - && random_(120, 100) < 10 * (mon->_mAI.aiInt + (currEnemyInfo._meRealDist != 4 ? 4 : 0)) - && MonDestWalk(mnum)) { - return; + && random_(120, 100) < 10 * (mon->_mAI.aiInt + (currEnemyInfo._meRealDist != 4 ? 4 : 0))) { + MonDestWalk(mnum); } - } else + } else { MonStartDelay(mnum, md + 1); + } } } else { MonDestWalk(mnum); From cbdbeda01bf022917dc25cc21b80f37582ed2b85 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 24 Dec 2023 10:03:33 +0100 Subject: [PATCH 133/596] bugfix for vanilla (rewards placement) - do not place items too far from the towner if not necessary --- Source/towners.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/towners.cpp b/Source/towners.cpp index c1994c32801..4cb33ea01cf 100644 --- a/Source/towners.cpp +++ b/Source/towners.cpp @@ -535,7 +535,7 @@ void SyncTownerQ(int pnum, int idx) quests[Q_BANNER]._qlog = FALSE; quests[Q_BANNER]._qvar1 = QV_BANNER_GIVEN; if (pnum == mypnum) - SpawnUnique(UITEM_HARCREST, TPOS_TAVERN + 1, ICM_SEND_FLIP); + SpawnUnique(UITEM_HARCREST, TPOS_TAVERN, ICM_SEND_FLIP); break; case IDI_ROCK: if (quests[Q_ROCK]._qactive != QUEST_ACTIVE) @@ -543,7 +543,7 @@ void SyncTownerQ(int pnum, int idx) quests[Q_ROCK]._qactive = QUEST_DONE; //quests[Q_ROCK]._qlog = FALSE; if (pnum == mypnum) - SpawnUnique(UITEM_INFRARING, TPOS_SMITH + 1, ICM_SEND_FLIP); + SpawnUnique(UITEM_INFRARING, TPOS_SMITH, ICM_SEND_FLIP); break; case IDI_ANVIL: if (quests[Q_ANVIL]._qactive != QUEST_ACTIVE) @@ -551,7 +551,7 @@ void SyncTownerQ(int pnum, int idx) quests[Q_ANVIL]._qactive = QUEST_DONE; //quests[Q_ANVIL]._qlog = FALSE; if (pnum == mypnum) - SpawnUnique(UITEM_GRISWOLD, TPOS_SMITH + 1, ICM_SEND_FLIP); + SpawnUnique(UITEM_GRISWOLD, TPOS_SMITH, ICM_SEND_FLIP); break; case IDI_FUNGALTM: if (quests[Q_MUSHROOM]._qactive != QUEST_INIT) @@ -572,7 +572,7 @@ void SyncTownerQ(int pnum, int idx) quests[Q_MUSHROOM]._qvar1 = QV_MUSHROOM_BRAINGIVEN; quests[Q_MUSHROOM]._qmsg = TEXT_MUSH4; if (pnum == mypnum) - SpawnQuestItemAt(IDI_SPECELIX, TPOS_HEALER + 1, ICM_SEND_FLIP); + SpawnQuestItemAt(IDI_SPECELIX, TPOS_HEALER, ICM_SEND_FLIP); break; case IDI_LAZSTAFF: if (quests[Q_BETRAYER]._qvar1 >= QV_BETRAYER_STAFFGIVEN /*|| quests[Q_BETRAYER]._qactive != QUEST_ACTIVE*/) @@ -672,7 +672,7 @@ void TalkToTowner(int tnum) } else if ((quests[Q_PWATER]._qactive == QUEST_INIT || quests[Q_PWATER]._qactive == QUEST_ACTIVE) && quests[Q_PWATER]._qvar1 == QV_PWATER_CLEAN) { quests[Q_PWATER]._qactive = QUEST_DONE; - SpawnUnique(UITEM_TRING, TPOS_HEALER + 1, ICM_SEND_FLIP); + SpawnUnique(UITEM_TRING, TPOS_HEALER, ICM_SEND_FLIP); qn = Q_PWATER; qt = TEXT_POISON5; } else if (quests[Q_MUSHROOM]._qactive == QUEST_ACTIVE From 3fdd465b49ce3085ed00fc0306c5c5e66b10728f Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 24 Dec 2023 13:38:48 +0100 Subject: [PATCH 134/596] bugfix for 'add mMin/MaxDamage2 fields to unique monsters' --- Source/monstdat.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/monstdat.cpp b/Source/monstdat.cpp index 181825a8360..e779a3b9193 100644 --- a/Source/monstdat.cpp +++ b/Source/monstdat.cpp @@ -408,7 +408,7 @@ const UniqMonData uniqMonData[] = { /*UMT_ZAMPHIR*/ { MT_YSNEAK, "Zamphir", "GENERAL", DLV_CAVES2, 20, 420, { AI_SNEAK, 3, 0, 0 }, 20, 30, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, UMF_GROUP, 0, 0, 0, 35, 20, Q_INVALID, TEXT_NONE, ALIGN }, #ifdef HELLFIRE /*UMT_HORKDMN*/ { MT_HORKDMN, "Hork Demon", NULL, DLV_NEST3, 28, 400, { AI_HORKDMN, 3, 0, 0 }, 20, 35, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, -/*UMT_DEFILER*/ { MT_DEFILER, "The Defiler", NULL, DLV_NEST4, 30, 480, { AI_FAT, 3, 0, 0 }, 30, 40, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, +/*UMT_DEFILER*/ { MT_DEFILER, "The Defiler", NULL, DLV_NEST4, 30, 480, { AI_FAT, 3, 0, 0 }, 30, 40, 24, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, /*UMT_NAKRUL*/ { MT_NAKRUL, "Na-Krul", NULL, 0, 32, 1332, { AI_SKELSD, 3, 0, 0 }, 40, 50, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, #endif { MT_TSKELAX, "Bonehead Keenaxe", "BHKA", DLV_CATHEDRAL2, 4, 91, { AI_SKELSD, 2, 0, 0 }, 4, 10, 0, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , UMF_GANG, 75, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, @@ -500,7 +500,7 @@ const UniqMonData uniqMonData[] = { // { MT_BSUCC, "Fleshdancer", "GENERAL", DLV_HELL4, 32, 999, { AI_RANGED, 3, MIS_SOLBRNR, FALSE }, 30, 50, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, #ifdef HELLFIRE { MT_FELLTWIN, "Bloodmoon the Lost", "GENERAL", DLV_NEST1, 16, 650, { AI_ZOMBIE, 0, 0, 0 }, 24, 40, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, UMF_GROUP, 30, 0, 0, 0, 70, Q_INVALID, TEXT_NONE, ALIGN }, - { MT_HELLBOAR, "Grimspike", "DE", DLV_NEST2, 22, 640, { AI_RHINO, 1, 0, 0 }, 25, 35, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, UMF_GANG, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, + { MT_HELLBOAR, "Grimspike", "DE", DLV_NEST2, 22, 640, { AI_RHINO, 1, 0, 0 }, 25, 35, 30, 50, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, UMF_GANG, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, { MT_SPIDLORD, "Webwidow", "ETH", DLV_NEST3, 24, 780, { AI_ROUNDRANGED2, 1, MIS_ACID, 0 }, 30, 45, 0, 0, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, // { MT_DRHINO, "Grimspike", "GENERAL", DLV_NEST3, 26, 534, { AI_SNEAK, 1, 0, 0 }, 25, 40, 0, 0, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, UMF_GANG, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, { MT_LASHWORM, "Stingiron", "BSM", DLV_NEST4, 26, 700, { AI_BAT, 3, 0, 0 }, 24, 40, 0, 0, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, UMF_GANG, 0, 0, 0, 70, 0, Q_INVALID, TEXT_NONE, ALIGN }, From 4635c6ee13c3a974715bf877e6367d5e3a41b9e0 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 24 Dec 2023 13:42:09 +0100 Subject: [PATCH 135/596] validate mMaxDamage2 and mmaxhp of the monsters (DEBUG_MODE) --- Source/debug.cpp | 17 +++++++++++++++++ Source/monstdat.cpp | 4 ++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Source/debug.cpp b/Source/debug.cpp index e20944c1878..4547bc15592 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -283,6 +283,12 @@ void ValidateData() app_fatal("Too high mHit2 %d for %s (%d).", md.mHit2, md.mName, i); if (md.mMagic > INT_MAX /*- HELL_MAGIC_BONUS */- HELL_LEVEL_BONUS * 5 / 2) // required by InitMonsterStats app_fatal("Too high mMagic %d for %s (%d).", md.mMagic, md.mName, i); + if (md.mMaxDamage == 0) + app_fatal("mMaxDamage is not set for %s (%d).", md.mName, i); + if (md.mMaxDamage2 == 0 && (md.mAI.aiType == AI_ROUND || md.mAI.aiType == AI_FAT || md.mAI.aiType == AI_RHINO || md.mAI.aiType == AI_SNAKE)) + app_fatal("mMaxDamage2 is not set for %s (%d).", md.mName, i); + if (md.mMaxDamage2 != 0 && (md.mAI.aiType == AI_SCAV || md.mAI.aiType == AI_GARG)) + app_fatal("Fake special attack of %s (%d) might hurt someone because mMaxDamage2 is set.", md.mName, i); if (md.mMinDamage > md.mMaxDamage) app_fatal("Too high mMinDamage %d for %s (%d).", md.mMinDamage, md.mName, i); if (md.mMinDamage2 > md.mMaxDamage2) @@ -413,6 +419,15 @@ void ValidateData() app_fatal("Too high mUnqHit2 %d for %s (%d).", um.mUnqHit2, um.mName, i); if (um.mUnqMag + monsterdata[um.mtype].mMagic > INT_MAX /*- HELL_MAGIC_BONUS */- HELL_LEVEL_BONUS * 5 / 2) // required by InitUniqueMonster app_fatal("Too high mUnqMag %d for %s (%d).", um.mUnqMag, um.mName, i); + if (um.mMaxDamage == 0 && monsterdata[um.mtype].mMaxDamage != 0) + if (um.mQuestId != Q_INVALID) + app_fatal("mMaxDamage is not set for unique monster %s (%d).", um.mName, i); + else + DoLog("mMaxDamage is not set for unique monster %s (%d).", um.mName, i); + if (um.mMaxDamage2 == 0 && (um.mAI.aiType == AI_ROUND || um.mAI.aiType == AI_FAT || um.mAI.aiType == AI_RHINO || um.mAI.aiType == AI_SNAKE)) + app_fatal("mMaxDamage2 is not set for unique monster %s (%d).", um.mName, i); + if (um.mMaxDamage2 != 0 && (um.mAI.aiType == AI_SCAV || um.mAI.aiType == AI_GARG)) + app_fatal("Fake special attack of the unique monster %s (%d) might hurt someone because mMaxDamage2 is set.", um.mName, i); if (um.mMinDamage > um.mMaxDamage) app_fatal("Too high mMinDamage %d for unique monster %s (%d).", um.mMinDamage, um.mName, i); if (um.mMinDamage2 > um.mMaxDamage2) @@ -436,6 +451,8 @@ void ValidateData() DoLog("Warn: Weak muMagicRes %d (%d) for %s (%d): worse than mMagicRes %d.", um.mMagicRes, j, um.mName, i, monsterdata[um.mtype].mMagicRes); } } + if (um.mmaxhp < monsterdata[um.mtype].mMaxHP) + DoLog("Warn: Low mmaxhp %d for %s (%d): lower than mMaxHP %d.", um.mmaxhp, um.mName, i, monsterdata[um.mtype].mMaxHP); #endif } diff --git a/Source/monstdat.cpp b/Source/monstdat.cpp index e779a3b9193..e59ecb300aa 100644 --- a/Source/monstdat.cpp +++ b/Source/monstdat.cpp @@ -63,7 +63,7 @@ const MonsterData monsterdata[NUM_MTYPES] = { /* MT_BACID */ { MOFILE_ACID, 21, 3, "Monsters\\Acid\\AcidB.TRN", "Pit Beast", { AI_ROUNDRANGED, 2, MIS_ACID, 1 }, 80, 110, 0 , 55, 8, 18, 0, 0, 0, 50, 0, 35, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2060, ALIGN }, // MC_ANIMAL, /* MT_XACID */ { MOFILE_ACID, 25, 3, "Monsters\\Acid\\AcidR.TRN", "Lava Maw", { AI_ROUNDRANGED, 3, MIS_ACID, 1 }, 100, 150, 0 , 65, 10, 20, 0, 0, 0, 60, 0, 35, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 2940, ALIGN }, // MC_ANIMAL, /* MT_SKING */ { MOFILE_SKING, 14, 7, "Monsters\\SkelSd\\White.TRN", "Skeleton King", { AI_SKELKING, 3, 0, 0 }, 140, 140, MFLAG_LIFESTEAL | MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 60, 6, 16, 0, 0, 0, 0, 0, 70, 30, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE , 570, ALIGN }, // MC_UNDEAD, -/* MT_CLEAVER */ { MOFILE_CLEAVER, 6, 3, NULL, "The Butcher", { AI_CLEAVER, 3, 0, 0 }, 320, 320, MFLAG_CAN_BLEED, 50, 6, 12, 0, 0, 0, 0, 0, 50, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 710, ALIGN }, // MC_DEMON, +/* MT_CLEAVER */ { MOFILE_CLEAVER, 6, 3, NULL, "The Butcher", { AI_CLEAVER, 3, 0, 0 }, 220, 220, MFLAG_CAN_BLEED, 50, 6, 12, 0, 0, 0, 0, 0, 50, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 710, ALIGN }, // MC_DEMON, /* MT_NFAT */ { MOFILE_FAT, 10, 3, NULL, "Overlord", { AI_FAT, 0, 0, 0 }, 60, 80, 0 | MFLAG_CAN_BLEED, 55, 6, 12, 30, 8, 14, 0, 0, 55, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 635, ALIGN }, // MC_DEMON, /* MT_BFAT */ { MOFILE_FAT, 14, 3, "Monsters\\Fat\\Blue.TRN", "Mud Man", { AI_FAT, 1, 0, 0 }, 100, 125, MFLAG_SEARCH | MFLAG_CAN_BLEED, 60, 8, 16, 35, 8, 20, 0, 0, 60, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 1165, ALIGN }, // MC_DEMON, /* MT_XFAT */ { MOFILE_FAT, 16, 3, "Monsters\\Fat\\FatB.TRN", "Toad Demon", { AI_FAT, 2, 0, 0 }, 135, 160, MFLAG_SEARCH | MFLAG_CAN_BLEED, 70, 8, 16, 40, 8, 20, 0, 0, 65, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1380, ALIGN }, // MC_DEMON, @@ -136,7 +136,7 @@ const MonsterData monsterdata[NUM_MTYPES] = { /* MT_LASHWORM */ { MOFILE_CLASP, 23, 3, NULL, "Lashworm", { AI_SKELSD, 3, 0, 0 }, 30, 30, 0 , 90, 12, 20, 0, 0, 0, 0, 0, 50, 35, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 600, ALIGN }, // MC_ANIMAL, /* MT_TORCHANT */ { MOFILE_ANTWORM, 22, 7, NULL, "Torchant", { AI_RANGED, 3, MIS_FIREBALL, FALSE }, 60, 80, 0 , 75, 20, 30, 0, 0, 0, 55, 0, 70, 50, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1250, ALIGN }, // MC_ANIMAL, /* MT_HORKDMN */ { MOFILE_HORKD, 28, 7, NULL, "Hork Demon", { AI_SKELSD, 3, 0, 0 }, 120, 160, MFLAG_SEARCH | MFLAG_CAN_BLEED, 60, 20, 35, 0, 0, 0, 0, 0, 80, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2000, ALIGN }, // MC_DEMON, -/* MT_DEFILER */ { MOFILE_HELLBUG, 30, 7, NULL, "Hell Bug", { AI_SKELSD, 3, 0, 0 }, 240, 240, MFLAG_SEARCH , 110, 20, 30, 80, 24, 40, 0, 0, 80, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 5000, ALIGN }, // MC_DEMON, +/* MT_DEFILER */ { MOFILE_HELLBUG, 30, 7, NULL, "Hell Bug", { AI_FAT, 3, 0, 0 }, 480, 480, MFLAG_SEARCH , 110, 20, 30, 80, 24, 40, 0, 0, 80, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 5000, ALIGN }, // MC_DEMON, /* MT_LRDSAYTR */ { MOFILE_GOATLORD, 26, 7, NULL, "Satyr Lord", { AI_SKELSD, 3, 0, 0 }, 160, 200, MFLAG_SEARCH | MFLAG_CAN_BLEED, 90, 20, 30, 0, 0, 0, 0, 0, 70, 60, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2800, ALIGN }, // MC_DEMON, /* MT_GRAVEDIG */ { MOFILE_GRAVDG, 26, 3, NULL, "Gravedigger", { AI_SCAV, 3, 0, 0 }, 120, 240, MFLAG_CAN_OPEN_DOOR, 80, 6, 26, 0, 0, 0, 0, 0, 20, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE , 2000, ALIGN }, // MC_UNDEAD, /* MT_BIGFALL */ { MOFILE_BIGFALL, 27, 3, NULL, "Devil Kin Brute", { AI_SKELSD, 3, 0, 0 }, 120, 160, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 100, 18, 24, 0, 0, 0, 0, 0, 70, 60, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2400, ALIGN }, // MC_ANIMAL, From f197c346864e019f4196570a81a948148ba75235 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 25 Dec 2023 09:00:52 +0100 Subject: [PATCH 136/596] select target of heal-other using dPlayer --- Source/missiles.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index ac848f362fb..be3dcad78c5 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -2913,7 +2913,7 @@ int AddHeal(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int int AddHealOther(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { - int pnum, i, hp; + int tnum, i, hp; assert((unsigned)misource < MAX_PLRS); // calculate hp @@ -2939,14 +2939,11 @@ int AddHealOther(int mi, int sx, int sy, int dx, int dy, int midir, int micaster ASSUME_UNREACHABLE } // select target - for (pnum = 0; pnum < MAX_PLRS; pnum++) { - if (pnum != misource - && plr._pActive && plr._pDunLevel == currLvl._dLevelIdx - && plr._px == dx && plr._py == dy - && plr._pHitPoints >= (1 << 6)) { - PlrIncHp(pnum, hp); - break; - } + tnum = dPlayer[dx][dy]; + if (tnum != 0) { + tnum = tnum >= 0 ? tnum - 1 : -(tnum + 1); + if (tnum != misource && plx(tnum)._pHitPoints >= (1 << 6)) + PlrIncHp(tnum, hp); } return MIRES_DELETE; } From ff9f19a9bf8a85fd6ec32671eba981b8c9f0ec43 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 25 Dec 2023 09:07:26 +0100 Subject: [PATCH 137/596] support healing of minions --- Source/control.cpp | 6 +++--- Source/controls/plrctrls.cpp | 20 +++++++++++++++----- Source/cursor.cpp | 20 ++++++++++++++++++-- Source/items.cpp | 18 ++++++------------ Source/missiles.cpp | 17 +++++++++++++++++ enums.h | 2 +- 6 files changed, 60 insertions(+), 23 deletions(-) diff --git a/Source/control.cpp b/Source/control.cpp index efe982d0f6e..3209388265b 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -378,9 +378,9 @@ void DrawSkillIcons() str = "Object"; numchar = lengthof("Object") - 1; break; - case TGT_PLAYER: - str = "Player"; - numchar = lengthof("Player") - 1; + case TGT_OTHER: + str = "Other"; + numchar = lengthof("Other") - 1; break; case TGT_DEAD: str = "Dead"; diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index 8ebf2c0fa04..e3924e16d04 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -179,14 +179,22 @@ static bool HasRangedSkill() /** * @brief Find a monster to target + * @param mode: 0 - offensive, 1 - heal * @param ranged: whether the current player is melee or ranged */ -static void FindMonster(bool ranged) +static void FindMonster(int mode, bool ranged) { - int newDistance, rotations, distance = MAXDUNX + MAXDUNY, mnum; + int newDistance, rotations, distance = MAXDUNX + MAXDUNY, mnum, lastMon; bool canTalk = true; - for (mnum = MAX_MINIONS; mnum < MAXMONSTERS; mnum++) { + if (mode == 0) { + mnum = MAX_MINIONS; + lastMon = MAXMONSTERS; + } else { + mnum = 0; + lastMon = MAX_MINIONS; + } + for ( ; mnum < lastMon; mnum++) { const MonsterStruct& mon = monsters[mnum]; if (mon._mmode > MM_INGAME_LAST || mon._mmode == MM_DEATH) continue; @@ -1002,7 +1010,7 @@ void plrctrls_after_check_curs_move() switch (pcurstgt) { case TGT_NORMAL: if (currLvl._dType != DTYPE_TOWN) - FindMonster(ranged); + FindMonster(0, ranged); else FindTowner(); if (pcursmonst == MON_NONE) @@ -1018,9 +1026,11 @@ void plrctrls_after_check_curs_move() case TGT_OBJECT: FindObject(); break; - case TGT_PLAYER: + case TGT_OTHER: assert(ranged); FindPlayer(1, true); + if (pcursplr == PLR_NONE) + FindMonster(1, true); break; case TGT_DEAD: assert(ranged); diff --git a/Source/cursor.cpp b/Source/cursor.cpp index a801f1b1131..8d51e801798 100644 --- a/Source/cursor.cpp +++ b/Source/cursor.cpp @@ -200,7 +200,7 @@ void NewCursor(int i) case CURSOR_TELEPORT: break; case CURSOR_HEALOTHER: - pcurstgt = TGT_PLAYER; + pcurstgt = TGT_OTHER; break; case CURSOR_HOURGLASS: break; @@ -585,7 +585,7 @@ void CheckCursMove() } } break; - case TGT_PLAYER: + case TGT_OTHER: // select a live player for (i = 2; i >= 0; i--) { mi = curplr[i]; @@ -600,6 +600,22 @@ void CheckCursMove() break; } } + if (i < 0) { + // select a live minion + for (i = 4; i >= 0; i--) { + mi = curmon[i]; + if (mi != 0) { + mi = mi >= 0 ? mi - 1 : -(mi + 1); + if (mi >= MAX_MINIONS || monsters[mi]._mhitpoints < (1 << 6)) { + continue; + } + pcursmonst = mi; + pcurspos.x = mx + offx[i]; + pcurspos.y = my + offy[i]; + break; + } + } + } break; case TGT_DEAD: // select a dead player diff --git a/Source/items.cpp b/Source/items.cpp index a385af5366c..8305dc663ca 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -1174,8 +1174,7 @@ static void GetBookSpell(int ii, unsigned lvl) ns = 0; for (bs = 0; bs < NUM_SPELLS; bs++) { if (spelldata[bs].sBookLvl != SPELL_NA && lvl >= spelldata[bs].sBookLvl - && (IsMultiGame - || (bs != SPL_RESURRECT && bs != SPL_HEALOTHER))) { + && (IsMultiGame || bs != SPL_RESURRECT)) { ss[ns] = bs; ns++; } @@ -1228,8 +1227,7 @@ static void GetScrollSpell(int ii, unsigned lvl) ns = 0; for (bs = 0; bs < lengthof(ss); bs++) { if (spelldata[bs].sScrollLvl != SPELL_NA && lvl >= spelldata[bs].sScrollLvl - && (IsMultiGame - || (bs != SPL_RESURRECT && bs != SPL_HEALOTHER))) { + && (IsMultiGame || bs != SPL_RESURRECT)) { ss[ns] = bs; ns++; } @@ -1262,8 +1260,7 @@ static void GetRuneSpell(int ii, unsigned lvl) ns = 0; for (bs = SPL_RUNE_FIRST; bs <= SPL_RUNE_LAST; bs++) { if (/*spelldata[bs].sScrollLvl != SPELL_NA &&*/ lvl >= spelldata[bs].sScrollLvl - /*&& (IsMultiGame - || (bs != SPL_RESURRECT && bs != SPL_HEALOTHER))*/) { + /*&& (IsMultiGame || bs != SPL_RESURRECT)*/) { ss[ns] = bs; ns++; } @@ -1312,8 +1309,7 @@ static void GetStaffSpell(int ii, unsigned lvl) ns = 0; for (bs = 0; bs < NUM_SPELLS; bs++) { if (spelldata[bs].sStaffLvl != SPELL_NA && lvl >= spelldata[bs].sStaffLvl - && (IsMultiGame - || (bs != SPL_RESURRECT && bs != SPL_HEALOTHER))) { + && (IsMultiGame || bs != SPL_RESURRECT)) { ss[ns] = bs; ns++; } @@ -1345,8 +1341,7 @@ static int GetItemSpell() ns = 0; for (bs = 0; bs < NUM_SPELLS; bs++) { if (spelldata[bs].sManaCost != 0 // TODO: use sSkillFlags ? - && (IsMultiGame - || (bs != SPL_RESURRECT && bs != SPL_HEALOTHER))) { + && (IsMultiGame || bs != SPL_RESURRECT)) { ss[ns] = bs; ns++; } @@ -3699,8 +3694,7 @@ void SpawnHealer(unsigned lvl) seed = NextRndSeed(); SetRndSeed(seed); GetItemAttrs(0, RndHealerItem(lvl), lvl); - } while (items[0]._iSpell != SPL_NULL && items[0]._iSpell != SPL_HEAL - && (items[0]._iSpell != SPL_HEALOTHER || !IsMultiGame)); + } while (items[0]._iSpell != SPL_NULL && items[0]._iSpell != SPL_HEAL && items[0]._iSpell != SPL_HEALOTHER); items[0]._iSeed = seed; items[0]._iCreateInfo = lvl | CF_HEALER; copy_pod(healitem[i], items[0]); diff --git a/Source/missiles.cpp b/Source/missiles.cpp index be3dcad78c5..11de1e8a4dd 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -2914,6 +2914,7 @@ int AddHeal(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int int AddHealOther(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { int tnum, i, hp; + MonsterStruct* mon; assert((unsigned)misource < MAX_PLRS); // calculate hp @@ -2941,9 +2942,25 @@ int AddHealOther(int mi, int sx, int sy, int dx, int dy, int midir, int micaster // select target tnum = dPlayer[dx][dy]; if (tnum != 0) { + // - player tnum = tnum >= 0 ? tnum - 1 : -(tnum + 1); if (tnum != misource && plx(tnum)._pHitPoints >= (1 << 6)) PlrIncHp(tnum, hp); + } else { + // - minion + tnum = dMonster[dx][dy]; + if (tnum != 0) { + tnum = tnum >= 0 ? tnum - 1 : -(tnum + 1); + if (tnum < MAX_MINIONS) { + mon = &monsters[tnum]; + if (mon->_mhitpoints >= (1 << 6)) { + // MonIncHp(tnum, hp); + mon->_mhitpoints += hp; + if (mon->_mhitpoints > mon->_mmaxhp) + mon->_mhitpoints = mon->_mmaxhp; + } + } + } } return MIRES_DELETE; } diff --git a/enums.h b/enums.h index dabf9db66a5..1dde439fc6c 100644 --- a/enums.h +++ b/enums.h @@ -3696,7 +3696,7 @@ typedef enum _target_mode { TGT_NORMAL, TGT_ITEM, TGT_OBJECT, - TGT_PLAYER, + TGT_OTHER, TGT_DEAD, TGT_NONE } _target_mode; From 7a6fb7f30eaa17ae279384e14cb8b61f2a1fe905 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 25 Dec 2023 09:39:33 +0100 Subject: [PATCH 138/596] check _mmode == MM_DEATH instead of _mhitpoints in MonFindEnemy --- Source/monster.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 23a4d3f51f8..a96e2a6d871 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1392,7 +1392,7 @@ static void MonFindEnemy(int mnum) tmon = &monsters[i]; if (tmon->_mmode > MM_INGAME_LAST) continue; - if (tmon->_mhitpoints < (1 << 6)) + if (tmon->_mmode == MM_DEATH) continue; if ((tmon->_mmode < MM_WALK || tmon->_mmode > MM_WALK2) || tmon->_mAnimFrame <= (tmon->_mAnimLen >> 1)) { x = tmon->_mx; @@ -1425,7 +1425,7 @@ static void MonFindEnemy(int mnum) tmon = &monsters[tnum]; if (tmon->_mmode > MM_INGAME_LAST) continue; - if (tmon->_mhitpoints < (1 << 6)) + if (tmon->_mmode == MM_DEATH) continue; if (CanTalkToMonst(tnum)) continue; From 18a41f9b1d110e5a20f13ee77f102516479e75e4 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 25 Dec 2023 09:41:29 +0100 Subject: [PATCH 139/596] bugfix for vanilla (golem vs hidden) - prevent minions from targeting hidden monsters --- Source/monster.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/monster.cpp b/Source/monster.cpp index a96e2a6d871..16456519695 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1394,6 +1394,8 @@ static void MonFindEnemy(int mnum) continue; if (tmon->_mmode == MM_DEATH) continue; + //if (tmon->_mFlags & MFLAG_HIDDEN) + // continue; if ((tmon->_mmode < MM_WALK || tmon->_mmode > MM_WALK2) || tmon->_mAnimFrame <= (tmon->_mAnimLen >> 1)) { x = tmon->_mx; y = tmon->_my; @@ -1427,6 +1429,8 @@ static void MonFindEnemy(int mnum) continue; if (tmon->_mmode == MM_DEATH) continue; + if (tmon->_mFlags & MFLAG_HIDDEN) + continue; if (CanTalkToMonst(tnum)) continue; if ((tmon->_mmode < MM_WALK || tmon->_mmode > MM_WALK2) || tmon->_mAnimFrame <= (tmon->_mAnimLen >> 1)) { From be41aa17f78c4c88ad6e8022d4497876683d9bfd Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 25 Dec 2023 09:43:45 +0100 Subject: [PATCH 140/596] inline CanTalkToMonst to MonFindEnemy --- Source/monster.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 16456519695..73a275a52ac 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1431,7 +1431,7 @@ static void MonFindEnemy(int mnum) continue; if (tmon->_mFlags & MFLAG_HIDDEN) continue; - if (CanTalkToMonst(tnum)) + if (tmon->_mgoal == MGOAL_TALKING) // CanTalkToMonst(tnum) continue; if ((tmon->_mmode < MM_WALK || tmon->_mmode > MM_WALK2) || tmon->_mAnimFrame <= (tmon->_mAnimLen >> 1)) { x = tmon->_mx; @@ -5055,7 +5055,8 @@ bool CheckMonsterHit(int mnum, bool* ret) dev_fatal("CheckMonsterHit: Invalid monster %d", mnum); } mon = &monsters[mnum]; - if (mon->_mgoal == MGOAL_TALKING || mon->_mmode == MM_CHARGE || mon->_mmode == MM_DEATH || mon->_mmode == MM_FADEIN || mon->_mmode == MM_FADEOUT + if (mon->_mgoal == MGOAL_TALKING // CanTalkToMonst(mnum) + || mon->_mmode == MM_CHARGE || mon->_mmode == MM_DEATH || mon->_mmode == MM_FADEIN || mon->_mmode == MM_FADEOUT || (mon->_mAI.aiType == AI_SNEAK && mon->_mgoal == MGOAL_RETREAT && mon->_mmode != MM_STONE)) { *ret = false; result = false; From 1388faff64317c6513098ef1689abe85ebe362f2 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 25 Dec 2023 09:57:59 +0100 Subject: [PATCH 141/596] play sfx even in the first 10 turns --- Source/effects.cpp | 4 ++-- Source/items.cpp | 4 ++-- Source/nthread.cpp | 10 +++++----- Source/player.cpp | 7 ++----- Source/player.h | 2 +- Source/sync.cpp | 2 +- 6 files changed, 13 insertions(+), 16 deletions(-) diff --git a/Source/effects.cpp b/Source/effects.cpp index 965dae3f86a..0759880abef 100644 --- a/Source/effects.cpp +++ b/Source/effects.cpp @@ -1258,7 +1258,7 @@ static void PlaySFX_priv(int psfx, bool loc, int x, int y) int lPan, lVolume; SFXStruct* pSFX; - if (!gbSoundOn || gbLvlLoad != 0) + if (!gbSoundOn || gbLvlLoad) return; lPan = 0; @@ -1293,7 +1293,7 @@ void PlayMonSFX(int mnum, int mode) SoundSample* snd; sndIdx = random_(164, lengthof(mapMonTypes[0].cmSnds[0])); - if (!gbSoundOn || gbLvlLoad != 0) + if (!gbSoundOn || gbLvlLoad) return; mon = &monsters[mnum]; diff --git a/Source/items.cpp b/Source/items.cpp index 8305dc663ca..fbe7fd3d96e 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -142,7 +142,7 @@ static void PlaceInitItems() SetItemData(ii, random_(12, 2) != 0 ? IDI_HEAL : IDI_MANA); items[ii]._iSeed = seed; items[ii]._iCreateInfo = lvl; // | CF_PREGEN; - // assert(gbLvlLoad != 0); + // assert(gbLvlLoad); RespawnItem(ii, false); GetRandomItemSpace(ii); @@ -2304,7 +2304,7 @@ void PlaceQuestItemInArea(int idx, int areasize) assert(i == numitems); CreateQuestItemAt(IDI_ROCK, objects[oi]._ox, objects[oi]._oy, ICM_DELTA); // SetItemData(i, IDI_ROCK); - // assert(gbLvlLoad != 0); + // assert(gbLvlLoad); // RespawnItem(i, false); // draw it above the stand items[i]._iSelFlag = 2; diff --git a/Source/nthread.cpp b/Source/nthread.cpp index db0e7abb34d..e23f8aa1886 100644 --- a/Source/nthread.cpp +++ b/Source/nthread.cpp @@ -200,7 +200,7 @@ static int SDLCALL nthread_handler(void* data) #endif void nthread_start() { - gbLvlLoad = 10; // TODO: set this when _pLvlChanging of the local player is set to TRUE? + gbLvlLoad = true; // TODO: set this when _pLvlChanging of the local player is set to TRUE? assert(geBufferMsgs == MSG_NORMAL); guNextTick = SDL_GetTicks() /*+ gnTickDelay*/; if (gbJoinGame) { @@ -251,7 +251,7 @@ void nthread_cleanup() void nthread_run() { - gbLvlLoad = 10; + gbLvlLoad = true; #ifndef NONET if (sghThread != NULL && !_gbRunThread) { _gbRunThread = true; @@ -353,7 +353,6 @@ static bool nthread_process_pending_delta_turns(bool pre) multi_process_msgs(); if (!pre) { for (i = gbNetUpdateRate; i > 0; i--) { - ++gbLvlLoad; game_logic(); } } else { @@ -403,8 +402,7 @@ void nthread_finish(UINT uMsg) // IncProgress(); // IncProgress(); // IncProgress(); - return; - } + } else { // phase 5 done // phase 6 begin // set current level to an invalid level @@ -555,6 +553,8 @@ void nthread_finish(UINT uMsg) NetSendCmd(CMD_REQUEST_PLRCHECK); } #endif + } + gbLvlLoad = false; } bool nthread_has_50ms_passed() diff --git a/Source/player.cpp b/Source/player.cpp index 396f1f2a33f..b98e1b30941 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -10,8 +10,8 @@ DEVILUTION_BEGIN_NAMESPACE int mypnum; PlayerStruct players[MAX_PLRS]; -/* Counter to suppress animations in case the current player is changing the level. */ -BYTE gbLvlLoad; +/* Whether the current player is changing the level. */ +bool gbLvlLoad; /** The current player while processing the players. */ BYTE gbGameLogicPnum; /** Cache the maximum sizes of the player gfx files. */ @@ -2776,9 +2776,6 @@ void ProcessPlayers() dev_fatal("ProcessPlayers: illegal player %d", mypnum); } - if (gbLvlLoad > 0) { - gbLvlLoad--; - } #ifndef NOSOUND if (gnSfxDelay > 0) { gnSfxDelay--; diff --git a/Source/player.h b/Source/player.h index 26e0265e0e7..7b00d30a377 100644 --- a/Source/player.h +++ b/Source/player.h @@ -19,7 +19,7 @@ extern "C" { extern int mypnum; extern PlayerStruct players[MAX_PLRS]; -extern BYTE gbLvlLoad; +extern bool gbLvlLoad; void InitPlayerGFX(int pnum); void InitPlrGFXMem(int pnum); diff --git a/Source/sync.cpp b/Source/sync.cpp index d597cdb1a92..1a60e15ffac 100644 --- a/Source/sync.cpp +++ b/Source/sync.cpp @@ -19,7 +19,7 @@ BYTE* sync_all_monsters(BYTE* pbBuf, unsigned size) MonsterStruct* mon; TSyncMonster* symon; - if (!IsMultiGame || gbLvlLoad == 10 /*|| nummonsters < 1*/) { // nummonsters is always >= MAX_MINIONS + if (!IsMultiGame || gbLvlLoad /*|| nummonsters < 1*/) { // nummonsters is always >= MAX_MINIONS return pbBuf; } if (remsize < sizeof(*pHdr) + sizeof(TSyncMonster)) { From 22dfa431fc6f0e778d518f14b188bbb9daa82b1c Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 25 Dec 2023 10:08:44 +0100 Subject: [PATCH 142/596] simplify monster-selection (CheckCursMove) --- Source/cursor.cpp | 5 ++--- Source/debug.cpp | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/cursor.cpp b/Source/cursor.cpp index 8d51e801798..a2fca0fcac9 100644 --- a/Source/cursor.cpp +++ b/Source/cursor.cpp @@ -467,6 +467,7 @@ void CheckCursMove() if (mi != pcursmonst) { continue; } + // assert(mi >= MAX_MINIONS || monsterdata[monsters[mi].mType].mSelFlag == 0); if (!(monsters[mi]._mSelFlag & selFlag[i])) { continue; } @@ -485,12 +486,10 @@ void CheckCursMove() if (monsters[mi]._mhitpoints < (1 << 6) || (monsters[mi]._mFlags & MFLAG_HIDDEN)) { continue; } + // assert(mi >= MAX_MINIONS || monsterdata[monsters[mi].mType].mSelFlag == 0); if (!(monsters[mi]._mSelFlag & selFlag[i])) { continue; } - if (mi < MAX_MINIONS) { - break; - } pcursmonst = mi; pcurspos.x = mx + offx[i]; pcurspos.y = my + offy[i]; diff --git a/Source/debug.cpp b/Source/debug.cpp index 4547bc15592..d4f3176ce19 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -252,6 +252,7 @@ void ValidateData() // monsters assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_KNOCKBACK)); // required by MonStartMonHit assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_CAN_BLEED)); // required by MonStartMonHit + assert(monsterdata[MT_GOLEM].mSelFlag == 0); // required by CheckCursMove for (i = 0; i < NUM_MTYPES; i++) { const MonsterData& md = monsterdata[i]; if ((md.mAI.aiType == AI_GOLUM || md.mAI.aiType == AI_SKELKING) && !(md.mFlags & MFLAG_CAN_OPEN_DOOR)) From 02e8bad8f13cf9ad0c1e4cd8054bdd16a348b893 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 25 Dec 2023 10:12:21 +0100 Subject: [PATCH 143/596] cosmetic --- Source/nthread.cpp | 270 ++++++++++++++++++++++----------------------- 1 file changed, 135 insertions(+), 135 deletions(-) diff --git a/Source/nthread.cpp b/Source/nthread.cpp index e23f8aa1886..a2a2e4c8783 100644 --- a/Source/nthread.cpp +++ b/Source/nthread.cpp @@ -403,155 +403,155 @@ void nthread_finish(UINT uMsg) // IncProgress(); // IncProgress(); } else { - // phase 5 done - // phase 6 begin - // set current level to an invalid level - // so the localized messages are considered external - assert(currLvl._dLevelIdx == myplr._pDunLevel); - currLvl._dLevelIdx = DLV_INVALID; + // phase 5 done + // phase 6 begin + // set current level to an invalid level + // so the localized messages are considered external + assert(currLvl._dLevelIdx == myplr._pDunLevel); + currLvl._dLevelIdx = DLV_INVALID; #ifndef NONET - // "Network - Pending Turns" (13) - // process messages arrived during level-load - if (sghThread != NULL) { - nthread_process_pending_turns(); + // "Network - Pending Turns" (13) + // process messages arrived during level-load + if (sghThread != NULL) { + nthread_process_pending_turns(); - // 'pause' the nthread - sgThreadMutex.Enter(); - _gbRunThread = false; + // 'pause' the nthread + sgThreadMutex.Enter(); + _gbRunThread = false; - nthread_process_pending_turns(); - } -#endif - IncProgress(); // "Network - Msg Queue" (14) - // phase 6 end - // phase 7 begin - clear queued outgoing messages (e.g. CMD_DEACTIVATEPORTAL) - for (int i = SNetGetTurnsInTransit(); i > 0; i--) { - if (!nthread_level_turn()) { - // IncProgress(); - // IncProgress(); - // assert(!gbRunGame); - goto done; + nthread_process_pending_turns(); } - } - IncProgress(); // "Network - Join Level" (15) - // phase 7 end - // phase 8 - NetSendCmdJoinLevel(); - // phase 9 begin - wait for join level replies - // process only joinlevel commands and deltalevel/leave messages - geBufferMsgs = MSG_LVL_DELTA_WAIT; - guOweLevelDelta = 1 << mypnum; - for (int pnum = 0; pnum < MAX_PLRS; pnum++) { - if (plr._pActive) - guOweLevelDelta |= 1 << pnum; - } - // TODO: delta_init_level_data ? - //memset(gsDeltaData.ddRecvLastCmd, NMSG_LVL_DELTA_END, sizeof(gsDeltaData.ddRecvLastCmd)); - gsDeltaData.ddRecvLastCmd = NMSG_LVL_DELTA_END; - //gsDeltaData.ddDeltaSender = SNPLAYER_ALL; - //gsDeltaData.ddSendRecvOffset = 0; - assert((gdwLastGameTurn * gbNetUpdateRate) == gdwGameLogicTurn); - lastGameTurn = gdwLastGameTurn; - tmp = 0; - while (geBufferMsgs == MSG_LVL_DELTA_WAIT) { - if (!nthread_level_turn()) { - // IncProgress(); - // assert(!gbRunGame); - goto done; +#endif + IncProgress(); // "Network - Msg Queue" (14) + // phase 6 end + // phase 7 begin - clear queued outgoing messages (e.g. CMD_DEACTIVATEPORTAL) + for (int i = SNetGetTurnsInTransit(); i > 0; i--) { + if (!nthread_level_turn()) { + // IncProgress(); + // IncProgress(); + // assert(!gbRunGame); + goto done; + } } - if (guOweLevelDelta == 0) { - break; + IncProgress(); // "Network - Join Level" (15) + // phase 7 end + // phase 8 + NetSendCmdJoinLevel(); + // phase 9 begin - wait for join level replies + // process only joinlevel commands and deltalevel/leave messages + geBufferMsgs = MSG_LVL_DELTA_WAIT; + guOweLevelDelta = 1 << mypnum; + for (int pnum = 0; pnum < MAX_PLRS; pnum++) { + if (plr._pActive) + guOweLevelDelta |= 1 << pnum; } - if (++tmp > NET_JOIN_TIMEOUT) { - app_warn("Unable to join level."); - gbRunGame = false; - // IncProgress(); - goto done; + // TODO: delta_init_level_data ? + //memset(gsDeltaData.ddRecvLastCmd, NMSG_LVL_DELTA_END, sizeof(gsDeltaData.ddRecvLastCmd)); + gsDeltaData.ddRecvLastCmd = NMSG_LVL_DELTA_END; + //gsDeltaData.ddDeltaSender = SNPLAYER_ALL; + //gsDeltaData.ddSendRecvOffset = 0; + assert((gdwLastGameTurn * gbNetUpdateRate) == gdwGameLogicTurn); + lastGameTurn = gdwLastGameTurn; + tmp = 0; + while (geBufferMsgs == MSG_LVL_DELTA_WAIT) { + if (!nthread_level_turn()) { + // IncProgress(); + // assert(!gbRunGame); + goto done; + } + if (guOweLevelDelta == 0) { + break; + } + if (++tmp > NET_JOIN_TIMEOUT) { + app_warn("Unable to join level."); + gbRunGame = false; + // IncProgress(); + goto done; + } } - } - IncProgress(); // "Network - Sync delta" (16) - assert(geBufferMsgs == MSG_LVL_DELTA_WAIT - || (gdwLastGameTurn >= guDeltaTurn && guDeltaTurn > lastGameTurn)); // TODO: overflow hickup - gdwLastGameTurn = lastGameTurn; - gdwGameLogicTurn = lastGameTurn * gbNetUpdateRate; - tmp = guSendLevelData; // preserve this mask, requests of the pending turns are supposed to be handled - // phase 9 end + IncProgress(); // "Network - Sync delta" (16) + assert(geBufferMsgs == MSG_LVL_DELTA_WAIT + || (gdwLastGameTurn >= guDeltaTurn && guDeltaTurn > lastGameTurn)); // TODO: overflow hickup + gdwLastGameTurn = lastGameTurn; + gdwGameLogicTurn = lastGameTurn * gbNetUpdateRate; + tmp = guSendLevelData; // preserve this mask, requests of the pending turns are supposed to be handled + // phase 9 end #ifndef NONET - if (geBufferMsgs != MSG_LVL_DELTA_WAIT) { - // phase 10a - level-delta received - assert(geBufferMsgs == MSG_LVL_DELTA_PROC); - if (!nthread_process_pending_delta_turns(true)) - goto done; - // phase 11 - load received level-delta - assert(geBufferMsgs == MSG_LVL_DELTA_PROC); - geBufferMsgs = MSG_NORMAL; - assert(currLvl._dLevelIdx == DLV_INVALID); - currLvl._dLevelIdx = myplr._pDunLevel; - // assert(IsMultiGame); - ResyncQuests(); - DeltaLoadLevel(); - //SyncPortals(); - LevelDeltaLoad(); - assert(geBufferMsgs == MSG_NORMAL); - assert(currLvl._dLevelIdx == myplr._pDunLevel); - // phase 12 - // assert(geBufferMsgs == MSG_NORMAL); - geBufferMsgs = MSG_LVL_DELTA_SKIP_JOIN; - nthread_process_pending_delta_turns(false); + if (geBufferMsgs != MSG_LVL_DELTA_WAIT) { + // phase 10a - level-delta received + assert(geBufferMsgs == MSG_LVL_DELTA_PROC); + if (!nthread_process_pending_delta_turns(true)) + goto done; + // phase 11 - load received level-delta + assert(geBufferMsgs == MSG_LVL_DELTA_PROC); + geBufferMsgs = MSG_NORMAL; + assert(currLvl._dLevelIdx == DLV_INVALID); + currLvl._dLevelIdx = myplr._pDunLevel; + // assert(IsMultiGame); + ResyncQuests(); + DeltaLoadLevel(); + //SyncPortals(); + LevelDeltaLoad(); + assert(geBufferMsgs == MSG_NORMAL); + assert(currLvl._dLevelIdx == myplr._pDunLevel); + // phase 12 + // assert(geBufferMsgs == MSG_NORMAL); + geBufferMsgs = MSG_LVL_DELTA_SKIP_JOIN; + nthread_process_pending_delta_turns(false); #else - assert(geBufferMsgs == MSG_LVL_DELTA_WAIT); - if (FALSE) { + assert(geBufferMsgs == MSG_LVL_DELTA_WAIT); + if (FALSE) { #endif /* !NONET */ - } else { - // phase 10b - geBufferMsgs = MSG_NORMAL; - guDeltaTurn = UINT32_MAX; - if (!nthread_process_pending_delta_turns(true)) - goto done; - // phase 11-12b - assert(currLvl._dLevelIdx == DLV_INVALID); - currLvl._dLevelIdx = myplr._pDunLevel; - ResyncQuests(); - if (IsMultiGame) { - DeltaLoadLevel(); - } else if (IsLvlVisited(currLvl._dLevelIdx)) { - LoadLevel(); + } else { + // phase 10b + geBufferMsgs = MSG_NORMAL; + guDeltaTurn = UINT32_MAX; + if (!nthread_process_pending_delta_turns(true)) + goto done; + // phase 11-12b + assert(currLvl._dLevelIdx == DLV_INVALID); + currLvl._dLevelIdx = myplr._pDunLevel; + ResyncQuests(); + if (IsMultiGame) { + DeltaLoadLevel(); + } else if (IsLvlVisited(currLvl._dLevelIdx)) { + LoadLevel(); + } + SyncPortals(); + InitLvlPlayer(mypnum, true); } - SyncPortals(); - InitLvlPlayer(mypnum, true); - } - guSendLevelData &= tmp; -done: - // skip till next turn - if (_gbTickInSync) { - guNextTick += (gbNetUpdateRate - sgbPacketCountdown) * gnTickDelay; - } - sgbPacketCountdown = 1; //gbNetUpdateRate; - // reset DeltaTurn to prevent turn-skips in case of turn_id-overflow - guDeltaTurn = 0; - // reset geBufferMsgs to normal - geBufferMsgs = MSG_NORMAL; - plrmsg_delay(false); - InitSync(); - // finalize the light/vision calculations - DRLG_RedoTrans(); - ProcessLightList(); - ProcessVisionList(); - // enter the dungeon level - PlayDungMsgs(); - guLvlVisited |= LEVEL_MASK(currLvl._dLevelIdx); + guSendLevelData &= tmp; + done: + // skip till next turn + if (_gbTickInSync) { + guNextTick += (gbNetUpdateRate - sgbPacketCountdown) * gnTickDelay; + } + sgbPacketCountdown = 1; //gbNetUpdateRate; + // reset DeltaTurn to prevent turn-skips in case of turn_id-overflow + guDeltaTurn = 0; + // reset geBufferMsgs to normal + geBufferMsgs = MSG_NORMAL; + plrmsg_delay(false); + InitSync(); + // finalize the light/vision calculations + DRLG_RedoTrans(); + ProcessLightList(); + ProcessVisionList(); + // enter the dungeon level + PlayDungMsgs(); + guLvlVisited |= LEVEL_MASK(currLvl._dLevelIdx); #ifdef HELLFIRE - if (quests[Q_DEFILER]._qactive == QUEST_INIT && currLvl._dLevelIdx == questlist[Q_DEFILER]._qdlvl) { - quests[Q_DEFILER]._qactive = QUEST_ACTIVE; - quests[Q_DEFILER]._qlog = TRUE; - NetSendCmdQuest(Q_DEFILER, false); // recipient should not matter - } + if (quests[Q_DEFILER]._qactive == QUEST_INIT && currLvl._dLevelIdx == questlist[Q_DEFILER]._qdlvl) { + quests[Q_DEFILER]._qactive = QUEST_ACTIVE; + quests[Q_DEFILER]._qlog = TRUE; + NetSendCmdQuest(Q_DEFILER, false); // recipient should not matter + } #endif #if DEV_MODE - if (gbActivePlayers > 1 && plx(0)._pDunLevel == plx(1)._pDunLevel) { - NetSendCmd(CMD_REQUEST_ITEMCHECK); - NetSendCmd(CMD_REQUEST_PLRCHECK); - } + if (gbActivePlayers > 1 && plx(0)._pDunLevel == plx(1)._pDunLevel) { + NetSendCmd(CMD_REQUEST_ITEMCHECK); + NetSendCmd(CMD_REQUEST_PLRCHECK); + } #endif } gbLvlLoad = false; From 1ff6b7d3c960937456845caa7cf98cb16b5c3d27 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 25 Dec 2023 10:55:36 +0100 Subject: [PATCH 144/596] rename 'done'-label to 'fail' in nthread_finish --- Source/nthread.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/nthread.cpp b/Source/nthread.cpp index a2a2e4c8783..97bc8c98971 100644 --- a/Source/nthread.cpp +++ b/Source/nthread.cpp @@ -430,7 +430,7 @@ void nthread_finish(UINT uMsg) // IncProgress(); // IncProgress(); // assert(!gbRunGame); - goto done; + goto fail; } } IncProgress(); // "Network - Join Level" (15) @@ -457,7 +457,7 @@ void nthread_finish(UINT uMsg) if (!nthread_level_turn()) { // IncProgress(); // assert(!gbRunGame); - goto done; + goto fail; } if (guOweLevelDelta == 0) { break; @@ -466,7 +466,7 @@ void nthread_finish(UINT uMsg) app_warn("Unable to join level."); gbRunGame = false; // IncProgress(); - goto done; + goto fail; } } IncProgress(); // "Network - Sync delta" (16) @@ -481,7 +481,7 @@ void nthread_finish(UINT uMsg) // phase 10a - level-delta received assert(geBufferMsgs == MSG_LVL_DELTA_PROC); if (!nthread_process_pending_delta_turns(true)) - goto done; + goto fail; // phase 11 - load received level-delta assert(geBufferMsgs == MSG_LVL_DELTA_PROC); geBufferMsgs = MSG_NORMAL; @@ -507,7 +507,7 @@ void nthread_finish(UINT uMsg) geBufferMsgs = MSG_NORMAL; guDeltaTurn = UINT32_MAX; if (!nthread_process_pending_delta_turns(true)) - goto done; + goto fail; // phase 11-12b assert(currLvl._dLevelIdx == DLV_INVALID); currLvl._dLevelIdx = myplr._pDunLevel; @@ -521,7 +521,7 @@ void nthread_finish(UINT uMsg) InitLvlPlayer(mypnum, true); } guSendLevelData &= tmp; - done: +fail: // skip till next turn if (_gbTickInSync) { guNextTick += (gbNetUpdateRate - sgbPacketCountdown) * gnTickDelay; From ec1bcec8ddf92365c5fd6079b448acef2fa4142b Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 25 Dec 2023 11:04:51 +0100 Subject: [PATCH 145/596] block other players longer while loading for level-delta --- Source/msg.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/msg.cpp b/Source/msg.cpp index d20b5596809..20873c91896 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -1190,8 +1190,7 @@ void LevelDeltaExport() for (pnum = 0; pnum < MAX_PLRS; pnum++) { if (!(guSendLevelData & (1 << pnum)) || // pnum did not request a level-delta // (guOweLevelDelta & (1 << pnum) == 0) || // got an (empty) level delta from pnum - (!validDelta && !myplr._pLvlChanging // both players are 'actively' loading - && plr._pDunLevel == myplr._pDunLevel // the same level -> + (!validDelta && plr._pDunLevel == myplr._pDunLevel // both players are loading the same level -> && (guRequestLevelData[pnum] > guRequestLevelData[mypnum] || (guRequestLevelData[pnum] == guRequestLevelData[mypnum] && pnum > mypnum)))) { // ignore lower priority requests TODO: overflow hickup ; // skip } else { From a0f5dbc532141f7f542bca6945e84a11ca4d596d Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 25 Dec 2023 11:06:19 +0100 Subject: [PATCH 146/596] simplify calculation of guOweLevelDelta --- Source/nthread.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/nthread.cpp b/Source/nthread.cpp index 97bc8c98971..adaead7f3fc 100644 --- a/Source/nthread.cpp +++ b/Source/nthread.cpp @@ -440,11 +440,13 @@ void nthread_finish(UINT uMsg) // phase 9 begin - wait for join level replies // process only joinlevel commands and deltalevel/leave messages geBufferMsgs = MSG_LVL_DELTA_WAIT; - guOweLevelDelta = 1 << mypnum; + tmp = 0; for (int pnum = 0; pnum < MAX_PLRS; pnum++) { if (plr._pActive) - guOweLevelDelta |= 1 << pnum; + tmp |= 1 << pnum; } + assert(tmp & (1 << mypnum)); + guOweLevelDelta = tmp; // TODO: delta_init_level_data ? //memset(gsDeltaData.ddRecvLastCmd, NMSG_LVL_DELTA_END, sizeof(gsDeltaData.ddRecvLastCmd)); gsDeltaData.ddRecvLastCmd = NMSG_LVL_DELTA_END; From 3ec4a044c010afe8fb8672914686e6bf2a7a079f Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 25 Dec 2023 11:17:38 +0100 Subject: [PATCH 147/596] get rid of plrmsg_delay --- Source/nthread.cpp | 3 --- Source/plrmsg.cpp | 17 ----------------- Source/plrmsg.h | 1 - 3 files changed, 21 deletions(-) diff --git a/Source/nthread.cpp b/Source/nthread.cpp index adaead7f3fc..7e07ab75b78 100644 --- a/Source/nthread.cpp +++ b/Source/nthread.cpp @@ -256,8 +256,6 @@ void nthread_run() if (sghThread != NULL && !_gbRunThread) { _gbRunThread = true; sgThreadMutex.Leave(); - - plrmsg_delay(true); } #endif } @@ -533,7 +531,6 @@ void nthread_finish(UINT uMsg) guDeltaTurn = 0; // reset geBufferMsgs to normal geBufferMsgs = MSG_NORMAL; - plrmsg_delay(false); InitSync(); // finalize the light/vision calculations DRLG_RedoTrans(); diff --git a/Source/plrmsg.cpp b/Source/plrmsg.cpp index 82f9dc0cfe4..8a7ec3e7735 100644 --- a/Source/plrmsg.cpp +++ b/Source/plrmsg.cpp @@ -40,23 +40,6 @@ static bool sgbSelecting; /** The message where the cursor is at the moment. */ static _plrmsg* sgpCurMsg; -void plrmsg_delay(bool delay) -{ - /*int i; - _plrmsg* pMsg; - Uint32 deltaTc; - - deltaTc = SDL_GetTicks(); - if (delay) { - guDelayStartTc = deltaTc; - return; - } - deltaTc -= guDelayStartTc; - pMsg = plr_msgs; - for (i = 0; i < PLRMSG_COUNT; i++, pMsg++) - pMsg->time += deltaTc;*/ -} - static void plrmsg_WordWrap(_plrmsg* pMsg) { char* text = pMsg->str; diff --git a/Source/plrmsg.h b/Source/plrmsg.h index be8b93bfc38..b30f6f6eb0c 100644 --- a/Source/plrmsg.h +++ b/Source/plrmsg.h @@ -14,7 +14,6 @@ extern "C" { extern bool gbTalkflag; -void plrmsg_delay(bool delay); void EventPlrMsg(const char* pszFmt, ...); void ReceivePlrMsg(int pnum, const char* pszStr); //void ClearPlrMsg(int pnum); From 29c0869eeafd015c6cf877c6673897aa1e2f39bf Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 25 Dec 2023 11:46:45 +0100 Subject: [PATCH 148/596] improve 'documentation' of nthread_finish --- Source/nthread.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Source/nthread.cpp b/Source/nthread.cpp index 7e07ab75b78..2b5b1f9dc84 100644 --- a/Source/nthread.cpp +++ b/Source/nthread.cpp @@ -492,12 +492,13 @@ void nthread_finish(UINT uMsg) DeltaLoadLevel(); //SyncPortals(); LevelDeltaLoad(); - assert(geBufferMsgs == MSG_NORMAL); - assert(currLvl._dLevelIdx == myplr._pDunLevel); // phase 12 + // assert(currLvl._dLevelIdx == myplr._pDunLevel); + // assert(!sgTurnQueue.empty()); // assert(geBufferMsgs == MSG_NORMAL); geBufferMsgs = MSG_LVL_DELTA_SKIP_JOIN; nthread_process_pending_delta_turns(false); + // assert(geBufferMsgs == MSG_NORMAL); #else assert(geBufferMsgs == MSG_LVL_DELTA_WAIT); if (FALSE) { @@ -508,6 +509,7 @@ void nthread_finish(UINT uMsg) guDeltaTurn = UINT32_MAX; if (!nthread_process_pending_delta_turns(true)) goto fail; + // assert(sgTurnQueue.empty()); // phase 11-12b assert(currLvl._dLevelIdx == DLV_INVALID); currLvl._dLevelIdx = myplr._pDunLevel; @@ -519,6 +521,7 @@ void nthread_finish(UINT uMsg) } SyncPortals(); InitLvlPlayer(mypnum, true); + // assert(geBufferMsgs == MSG_NORMAL); } guSendLevelData &= tmp; fail: @@ -529,7 +532,7 @@ void nthread_finish(UINT uMsg) sgbPacketCountdown = 1; //gbNetUpdateRate; // reset DeltaTurn to prevent turn-skips in case of turn_id-overflow guDeltaTurn = 0; - // reset geBufferMsgs to normal + // reset geBufferMsgs to normal (in case of failure) geBufferMsgs = MSG_NORMAL; InitSync(); // finalize the light/vision calculations From 8573a7792ec293dc6ef2bdd57d3268a5f4315aec Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 25 Dec 2023 11:52:09 +0100 Subject: [PATCH 149/596] send sync-data while (post-)processing pending delta turns --- Source/nthread.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/Source/nthread.cpp b/Source/nthread.cpp index 2b5b1f9dc84..f625d2cc95b 100644 --- a/Source/nthread.cpp +++ b/Source/nthread.cpp @@ -361,6 +361,15 @@ static bool nthread_process_pending_delta_turns(bool pre) return gbRunGame; } +static void nthread_finish_dungeon() +{ + InitSync(); + // finalize the light/vision calculations + DRLG_RedoTrans(); + ProcessLightList(); + ProcessVisionList(); +} + /* lvl out reply proc. proc. proc. proc. valid turns phase idx dun cmd reqs dlvl join other msgs/d delta inc. timed queued mode @@ -492,11 +501,13 @@ void nthread_finish(UINT uMsg) DeltaLoadLevel(); //SyncPortals(); LevelDeltaLoad(); + nthread_finish_dungeon(); // phase 12 // assert(currLvl._dLevelIdx == myplr._pDunLevel); // assert(!sgTurnQueue.empty()); // assert(geBufferMsgs == MSG_NORMAL); geBufferMsgs = MSG_LVL_DELTA_SKIP_JOIN; + gbLvlLoad = false; nthread_process_pending_delta_turns(false); // assert(geBufferMsgs == MSG_NORMAL); #else @@ -521,6 +532,7 @@ void nthread_finish(UINT uMsg) } SyncPortals(); InitLvlPlayer(mypnum, true); + nthread_finish_dungeon(); // assert(geBufferMsgs == MSG_NORMAL); } guSendLevelData &= tmp; @@ -534,11 +546,6 @@ void nthread_finish(UINT uMsg) guDeltaTurn = 0; // reset geBufferMsgs to normal (in case of failure) geBufferMsgs = MSG_NORMAL; - InitSync(); - // finalize the light/vision calculations - DRLG_RedoTrans(); - ProcessLightList(); - ProcessVisionList(); // enter the dungeon level PlayDungMsgs(); guLvlVisited |= LEVEL_MASK(currLvl._dLevelIdx); From aa877b9e3825daa0be3f0af653ceba5831127178 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 26 Dec 2023 10:08:58 +0100 Subject: [PATCH 150/596] bugfix 'simplified MAI_RoundRanged' - prevent too many round-steps when the enemy of an AI_ROUNDRANGED is closing in fast --- Source/monster.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 73a275a52ac..ab126086df8 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3737,18 +3737,17 @@ void MAI_RoundRanged(int mnum) if (mon->_mgoal == MGOAL_MOVE || (dist >= 3 && random_low(122, 4 << mon->_mAI.aiParam2) == 0)) { if (mon->_mgoal != MGOAL_MOVE) { mon->_mgoal = MGOAL_MOVE; - static_assert(MAXDUNX + MAXDUNY <= 0x7FFF, "MAI_RoundRanged uses RandRangeLow to set distance"); - mon->_mgoalvar1 = 4 + RandRangeLow(2, dist); // MOVE_DISTANCE - mon->_mgoalvar2 = random_(123, 2); // MOVE_TURN_DIRECTION + mon->_mgoalvar1 = 0; // MOVE_DISTANCE + mon->_mgoalvar2 = random_(123, 2); // MOVE_TURN_DIRECTION } - /*if ((--mon->_mgoalvar1 <= 4 && MonDirOK(mnum, currEnemyInfo._meLastDir)) || mon->_mgoalvar1 == 0) { + /*if (mon->_mgoalvar1++ >= 2 * dist && MonDirOK(mnum, currEnemyInfo._meLastDir)) { mon->_mgoal = MGOAL_NORMAL; } else if (v < ((6 * (mon->_mAI.aiInt + 1)) >> mon->_mAI.aiParam2) && EnemyInLine(mnum)) { MonStartRSpAttack(mnum, mon->_mAI.aiParam1); } else { MonRoundWalk(mnum, currEnemyInfo._meLastDir, &mon->_mgoalvar2); // MOVE_TURN_DIRECTION }*/ - if (--mon->_mgoalvar1 > 4 || (mon->_mgoalvar1 > 0 && !MonDirOK(mnum, currEnemyInfo._meLastDir))) { // MOVE_DISTANCE + if (mon->_mgoalvar1++ < 2 * dist || !MonDirOK(mnum, currEnemyInfo._meLastDir)) { // MOVE_DISTANCE MonRoundWalk(mnum, currEnemyInfo._meLastDir, &mon->_mgoalvar2); // MOVE_TURN_DIRECTION } else { mon->_mgoal = MGOAL_NORMAL; From 89c75b5763dc1127706b54b73a27d52656b64b6a Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 26 Dec 2023 10:16:15 +0100 Subject: [PATCH 151/596] cosmetic - fix assertions in MAI_Counselor - compare 'dist'-local against 2 --- Source/monster.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index ab126086df8..fd6356c9729 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3734,7 +3734,7 @@ void MAI_RoundRanged(int mnum) dist = currEnemyInfo._meRealDist; //v = random_(121, 10000); if (dist >= 2 && mon->_msquelch == SQUELCH_MAX /*&& dTransVal[mon->_mx][mon->_my] == dTransVal[fx][fy]*/) { - if (mon->_mgoal == MGOAL_MOVE || (dist >= 3 && random_low(122, 4 << mon->_mAI.aiParam2) == 0)) { + if (mon->_mgoal == MGOAL_MOVE || (dist > 2 && random_low(122, 4 << mon->_mAI.aiParam2) == 0)) { if (mon->_mgoal != MGOAL_MOVE) { mon->_mgoal = MGOAL_MOVE; mon->_mgoalvar1 = 0; // MOVE_DISTANCE @@ -3759,7 +3759,7 @@ void MAI_RoundRanged(int mnum) if (mon->_mgoal == MGOAL_NORMAL) { v = random_(124, 100); - if (((dist >= 3 && v < ((8 * (mon->_mAI.aiInt + 2)) >> mon->_mAI.aiParam2)) + if (((dist > 2 && v < ((8 * (mon->_mAI.aiInt + 2)) >> mon->_mAI.aiParam2)) || v < ((8 * (mon->_mAI.aiInt + 1)) >> mon->_mAI.aiParam2)) && EnemyInLine(mnum)) { MonStartRSpAttack(mnum, mon->_mAI.aiParam1); @@ -3805,7 +3805,7 @@ void MAI_RoundRanged2(int mnum) MonstCheckDoors(mon->_mx, mon->_my); v = random_(121, 100); if (dist >= 2 && mon->_msquelch == SQUELCH_MAX /*&& dTransVal[mon->_mx][mon->_my] == dTransVal[mon->_menemyx][mon->_menemyy]*/) { - if (mon->_mgoal == MGOAL_MOVE || (dist >= 3 && dist < 5)) { + if (mon->_mgoal == MGOAL_MOVE || (dist > 2 && dist < 5)) { if (mon->_mgoal != MGOAL_MOVE) { mon->_mgoal = MGOAL_MOVE; mon->_mgoalvar1 = 0; // MOVE_DISTANCE @@ -3823,7 +3823,7 @@ void MAI_RoundRanged2(int mnum) } if (mon->_mgoal == MGOAL_NORMAL) { - if (dist < 5 && (dist >= 3 || v < 5 * (mon->_mAI.aiInt + 1)) && EnemyInLine(mnum)) { + if (dist < 5 && (dist > 2 || v < 5 * (mon->_mAI.aiInt + 1)) && EnemyInLine(mnum)) { MonStartRSpAttack(mnum, mon->_mAI.aiParam1); return; } @@ -3908,7 +3908,7 @@ void MAI_SkelKing(int mnum) v = random_(126, 100); dist = currEnemyInfo._meRealDist; if (dist >= 2 && mon->_msquelch == SQUELCH_MAX) { - if (mon->_mgoal == MGOAL_MOVE || (dist >= 3 && random_(127, 4) == 0)) { + if (mon->_mgoal == MGOAL_MOVE || (dist > 2 && random_(127, 4) == 0)) { if (mon->_mgoal != MGOAL_MOVE) { mon->_mgoal = MGOAL_MOVE; mon->_mgoalvar1 = 0; // MOVE_DISTANCE @@ -3925,7 +3925,7 @@ void MAI_SkelKing(int mnum) } if (mon->_mgoal == MGOAL_NORMAL) { - if (((dist >= 3 && v < 4 * mon->_mAI.aiInt + 35) || v < 6) + if (((dist > 2 && v < 4 * mon->_mAI.aiInt + 35) || v < 6) && MON_HAS_ENEMY /*&& EnemyInLine(mnum)*/) { // assert(LineClear(mon->_mx, mon->_my, mon->_menemyx, mon->_menemyy)); -- or just left the view, but who cares... nx = mon->_mx + offset_x[md]; @@ -4039,7 +4039,7 @@ void MAI_Horkdemon(int mnum) } if (mon->_mgoal == MGOAL_NORMAL) { - if (dist >= 3 && v < 2 * mon->_mAI.aiInt + 43) { + if (dist > 2 && v < 2 * mon->_mAI.aiInt + 43) { if (PosOkMonst(mnum, mon->_mx + offset_x[mon->_mdir], mon->_my + offset_y[mon->_mdir]) && nummonsters < MAXMONSTERS) { MonStartRSpAttack(mnum, MIS_HORKDMN); } @@ -4087,10 +4087,10 @@ void MAI_Counselor(int mnum) MonStartRAttack(mnum, mon->_mAI.aiParam1); } else if (random_(124, 100) < 30 && mon->_msquelch == SQUELCH_MAX) { #if DEBUG - assert(mon->_mAnims[MA_SPECIAL].maFrames * mon->_mAnims[MA_SPECIAL].maFrameLen * 2 + - mon->_mAnims[MA_WALK].maFrames * mon->_mAnims[MA_WALK].maFrameLen * (6 + 4) < SQUELCH_MAX - SQUELCH_LOW); + assert((mon->_mAnims[MA_SPECIAL].maFrames - 1) * mon->_mAnims[MA_SPECIAL].maFrameLen * 2 + + (mon->_mAnims[MA_WALK].maFrames - 1) * mon->_mAnims[MA_WALK].maFrameLen * (6 + 4) < SQUELCH_MAX - SQUELCH_LOW); #endif - static_assert(2 * 20 + (6 + 4) * 1 < SQUELCH_MAX - SQUELCH_LOW, "MAI_Counselor might relax with move goal."); + static_assert((20 - 1) * 1 * 2 + (1 - 1) * 1 * (6 + 4) < SQUELCH_MAX - SQUELCH_LOW, "MAI_Counselor might relax with move goal."); mon->_mgoal = MGOAL_MOVE; mon->_mgoalvar1 = 6 + random_low(0, std::min(dist, 4)); // MOVE_DISTANCE mon->_mgoalvar2 = random_(125, 2); // MOVE_TURN_DIRECTION @@ -4102,10 +4102,10 @@ void MAI_Counselor(int mnum) v >>= 1; if (mon->_mVar1 != MM_FADEIN && mon->_mhitpoints < (mon->_mmaxhp >> 1) && MonFindDir(mnum, OPPOSITE(md)) >= 0) { #if DEBUG - assert(mon->_mAnims[MA_SPECIAL].maFrames * mon->_mAnims[MA_SPECIAL].maFrameLen * 2 + - mon->_mAnims[MA_WALK].maFrames * mon->_mAnims[MA_WALK].maFrameLen * 5 < SQUELCH_MAX - SQUELCH_LOW); + assert((mon->_mAnims[MA_SPECIAL].maFrames - 1) * mon->_mAnims[MA_SPECIAL].maFrameLen * 2 + + (mon->_mAnims[MA_WALK].maFrames - 1) * mon->_mAnims[MA_WALK].maFrameLen * 5 < SQUELCH_MAX - SQUELCH_LOW); #endif - static_assert(2 * 20 + 5 * 1 < SQUELCH_MAX - SQUELCH_LOW, "MAI_Counselor might relax with retreat goal."); + static_assert((20 - 1) * 1 * 2 + (1 - 1) * 1 * 5 < SQUELCH_MAX - SQUELCH_LOW, "MAI_Counselor might relax with retreat goal."); mon->_mgoal = MGOAL_RETREAT; mon->_mgoalvar1 = 5; // RETREAT_DISTANCE MonStartFadeout(mnum, md, false); From a5f1244e7ded480ecedfda09ea3c9d0aa30d4b53 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 26 Dec 2023 10:59:58 +0100 Subject: [PATCH 152/596] check mType instead of mnum to protect against bleed and stun --- Source/debug.cpp | 2 +- Source/monster.cpp | 24 +++++++++--------------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/Source/debug.cpp b/Source/debug.cpp index d4f3176ce19..0e3c8902ae5 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -251,7 +251,7 @@ void ValidateData() } // monsters assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_KNOCKBACK)); // required by MonStartMonHit - assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_CAN_BLEED)); // required by MonStartMonHit + assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_CAN_BLEED)); // required by MonStartMonHit and MonStartPlrHit assert(monsterdata[MT_GOLEM].mSelFlag == 0); // required by CheckCursMove for (i = 0; i < NUM_MTYPES; i++) { const MonsterData& md = monsterdata[i]; diff --git a/Source/monster.cpp b/Source/monster.cpp index fd6356c9729..9aa8d47ed95 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1933,7 +1933,7 @@ static void MonGetKnockback(int mnum, int sx, int sy) } } - // assert(mnum >= MAX_MINIONS); // mon->_mType != MT_GOLEM + // assert(mon->_mType != MT_GOLEM); MonStartGetHit(mnum); } @@ -1954,10 +1954,8 @@ void MonStartPlrHit(int mnum, int pnum, int dam, unsigned hitflags, int sx, int NetSendCmdMonstDamage(mnum, mon->_mhitpoints); } PlayMonSFX(mnum, MS_GOTHIT); - if (mnum < MAX_MINIONS) // mon->_mType == MT_GOLEM - return; - if (mon->_mmode == MM_STONE) - return; + // assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_CAN_BLEED)); + if (mon->_mType != MT_GOLEM && mon->_mmode != MM_STONE) { if (mon->_mFlags & MFLAG_CAN_BLEED && (hitflags & ISPL_FAKE_CAN_BLEED) && ((hitflags & ISPL_BLEED) ? random_(47, 32) == 0 : random_(48, 64) == 0)) AddMissile(0, 0, 0, 0, 0, MIS_BLEED, MST_PLAYER, pnum, mnum); @@ -1970,6 +1968,7 @@ void MonStartPlrHit(int mnum, int pnum, int dam, unsigned hitflags, int sx, int MonTeleport(mnum, plr._pfutx, plr._pfuty); MonStartGetHit(mnum); } + } } void MonStartMonHit(int defm, int offm, int dam) @@ -1989,16 +1988,10 @@ void MonStartMonHit(int defm, int offm, int dam) } } PlayMonSFX(defm, MS_GOTHIT); - if (defm < MAX_MINIONS/* mon->_mType == MT_GOLEM */) - return; - if (dmon->_mmode == MM_STONE) - return; - // Knockback: - // 1. Golems -> other monsters. assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_KNOCKBACK)); - // 2. other monsters -> golems : golems are immune against knockbacks - // Bleed: - // 1. Golems -> other monsters. TODO: implement? - // 2. other monsters -> golems. assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_CAN_BLEED)); + // assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_CAN_BLEED)); + if (dmon->_mType != MT_GOLEM && dmon->_mmode != MM_STONE) { + // TODO: implement monster vs. monster knockback & bleed? + // assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_KNOCKBACK)); if ((dam << 2) >= dmon->_mmaxhp) { MonStopWalk(defm); if (offm >= 0) { @@ -2008,6 +2001,7 @@ void MonStartMonHit(int defm, int offm, int dam) } MonStartGetHit(defm); } + } } static void MonDiabloDeath(int mnum, bool sendmsg) From 6a7895630a91120af7ff35966c89658d6422ebb0 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 26 Dec 2023 11:02:01 +0100 Subject: [PATCH 153/596] cosmetic --- Source/monster.cpp | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 9aa8d47ed95..da3fdf08094 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1956,18 +1956,18 @@ void MonStartPlrHit(int mnum, int pnum, int dam, unsigned hitflags, int sx, int PlayMonSFX(mnum, MS_GOTHIT); // assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_CAN_BLEED)); if (mon->_mType != MT_GOLEM && mon->_mmode != MM_STONE) { - if (mon->_mFlags & MFLAG_CAN_BLEED && (hitflags & ISPL_FAKE_CAN_BLEED) - && ((hitflags & ISPL_BLEED) ? random_(47, 32) == 0 : random_(48, 64) == 0)) - AddMissile(0, 0, 0, 0, 0, MIS_BLEED, MST_PLAYER, pnum, mnum); - if (hitflags & ISPL_KNOCKBACK) - MonGetKnockback(mnum, sx, sy); - if ((dam << ((hitflags & ISPL_STUN) ? 3 : 2)) >= mon->_mmaxhp) { - MonStopWalk(mnum); - mon->_mdir = OPPOSITE(plr._pdir); - if (mon->_mType == MT_NBAT) - MonTeleport(mnum, plr._pfutx, plr._pfuty); - MonStartGetHit(mnum); - } + if (mon->_mFlags & MFLAG_CAN_BLEED && (hitflags & ISPL_FAKE_CAN_BLEED) + && ((hitflags & ISPL_BLEED) ? random_(47, 32) == 0 : random_(48, 64) == 0)) + AddMissile(0, 0, 0, 0, 0, MIS_BLEED, MST_PLAYER, pnum, mnum); + if (hitflags & ISPL_KNOCKBACK) + MonGetKnockback(mnum, sx, sy); + if ((dam << ((hitflags & ISPL_STUN) ? 3 : 2)) >= mon->_mmaxhp) { + MonStopWalk(mnum); + mon->_mdir = OPPOSITE(plr._pdir); + if (mon->_mType == MT_NBAT) + MonTeleport(mnum, plr._pfutx, plr._pfuty); + MonStartGetHit(mnum); + } } } @@ -1990,17 +1990,17 @@ void MonStartMonHit(int defm, int offm, int dam) PlayMonSFX(defm, MS_GOTHIT); // assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_CAN_BLEED)); if (dmon->_mType != MT_GOLEM && dmon->_mmode != MM_STONE) { - // TODO: implement monster vs. monster knockback & bleed? - // assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_KNOCKBACK)); - if ((dam << 2) >= dmon->_mmaxhp) { - MonStopWalk(defm); - if (offm >= 0) { - dmon->_mdir = OPPOSITE(monsters[offm]._mdir); - if (dmon->_mType == MT_NBAT) - MonTeleport(defm, monsters[offm]._mfutx, monsters[offm]._mfuty); + // TODO: implement monster vs. monster knockback & bleed? + // assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_KNOCKBACK)); + if ((dam << 2) >= dmon->_mmaxhp) { + MonStopWalk(defm); + if (offm >= 0) { + dmon->_mdir = OPPOSITE(monsters[offm]._mdir); + if (dmon->_mType == MT_NBAT) + MonTeleport(defm, monsters[offm]._mfutx, monsters[offm]._mfuty); + } + MonStartGetHit(defm); } - MonStartGetHit(defm); - } } } From e1a7fa3910162bffc7a8b9c4bd372485bc12c33d Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 26 Dec 2023 11:20:26 +0100 Subject: [PATCH 154/596] improve MAI_Golem --- Source/monster.cpp | 62 +++++++++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index da3fdf08094..fbeac381562 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3844,42 +3844,54 @@ void MAI_RoundRanged2(int mnum) void MAI_Golem(int mnum) { MonsterStruct* mon; - int md, i; + int md, ld, i; mon = &monsters[mnum]; - assert(mon->_mmode <= MM_INGAME_LAST); - if (MON_ACTIVE) { - //assert(mon->_mmode == MM_DEATH || mon->_mmode == MM_SPSTAND - // || mon->_mmode == MM_ATTACK || mon->_mmode == MM_WALK || mon->_mmode == MM_WALK2); + if (MON_ACTIVE) return; + assert(mon->_msquelch == SQUELCH_MAX); + if (MON_HAS_ENEMY) { + MAI_Cleaver(mnum); + if (mon->_mmode != MM_STAND) + return; } - mon->_msquelch = SQUELCH_MAX; + if (mon->_mgoal == MGOAL_NORMAL) { + // go to the player + int8_t path[MAX_PATH_LENGTH]; + assert(monsterdata[MT_GOLEM].mFlags & MFLAG_CAN_OPEN_DOOR); + if (FindPath(PosOkMonst3, mnum, mon->_mx, mon->_my, plx(mnum)._px, plx(mnum)._py, path) > 1) { + md = path[0]; + MonCallWalk(mnum, md); + return; + } - if (!(mon->_mFlags & MFLAG_TARGETS_MONSTER)) - MonFindEnemy(mnum); + mon->_mgoal = MGOAL_MOVE; + mon->_mgoalvar1 = 0; // MOVE_DIRECTION + } + // follow the gaze of the player assert(monsterdata[MT_GOLEM].mFlags & MFLAG_CAN_OPEN_DOOR); // assert(mon->_mFlags & MFLAG_CAN_OPEN_DOOR); MonstCheckDoors(mon->_mx, mon->_my); - if (MON_HAS_ENEMY) { - MonEnemyInfo(mnum); - if (currEnemyInfo._meRealDist >= 2) { - if (MonDestWalk(mnum)) { - return; - } - } else { - MonStartAttack(mnum); + ld = mon->_mdir; + md = plx(mnum)._pdir; + if (MonCallWalk(mnum, md)) { + if (ld != OPPOSITE(mon->_mdir)) { return; } + if (++mon->_mgoalvar1 <= 2) { + return; // MOVE_DIRECTION + } + // had to turn twice -> give up following the gaze of the player + MonStopWalk(mnum); } - - md = plx(mnum)._pdir; - if (!MonCallWalk(mnum, md)) { - for (i = 0; i < NUM_DIRS; i++) { - md = (md + 1) & 7; - if (MonDirOK(mnum, md)) { - MonWalkDir(mnum, md); - break; - } + // walk around randomly + mon->_mgoal = MGOAL_NORMAL; + md = md + 2; + for (i = 0; i < NUM_DIRS - 5; i++) { + md = (md + 1) & 7; + if (MonDirOK(mnum, md)) { + MonWalkDir(mnum, md); + break; } } } From c3a41e5e0436717fbd3374e5401215818f7f42a6 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 26 Dec 2023 11:27:35 +0100 Subject: [PATCH 155/596] improve monster-search logic when the enemy disappears (e.g. teleport, phase, townport, attract) --- Source/monster.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index fbeac381562..395d94c04d9 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -2920,10 +2920,21 @@ static bool MonDestWalk(int mnum) Check = (mon->_mFlags & MFLAG_CAN_OPEN_DOOR) != 0 ? PosOkMonst3 : PosOkMonst; if (mon->_mFlags & MFLAG_CAN_OPEN_DOOR) MonstCheckDoors(mon->_mx, mon->_my); - if (FindPath(Check, mnum, mon->_mx, mon->_my, mon->_mlastx, mon->_mlasty, path) > 0) { + md = FindPath(Check, mnum, mon->_mx, mon->_my, mon->_mlastx, mon->_mlasty, path); + if (md > 0) { // found path to the enemy -> go md = path[0]; - } else { + } else if (md != 0) { // cound not find path to the enemy -> just go in its generic direction md = currEnemyInfo._meLastDir; + } else { // enemy disappeared -> walk around randomly + md = random_(145, NUM_DIRS); + for (int i = 0; i < NUM_DIRS; i++) { + if (MonDirOK(mnum, md)) { + mon->_mlastx += offset_x[md]; + mon->_mlasty += offset_y[md]; + break; + } + md = (md + 1) & 7; + } } } else { md = currEnemyInfo._meLastDir; From 1d9bb435e79c545f3a2c426feb35499b7635fc77 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 26 Dec 2023 11:37:08 +0100 Subject: [PATCH 156/596] rebalance the golem-stats --- Source/monstdat.cpp | 2 +- Source/monster.cpp | 28 +++++++++++++++++++--------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/Source/monstdat.cpp b/Source/monstdat.cpp index e59ecb300aa..24265d3a58e 100644 --- a/Source/monstdat.cpp +++ b/Source/monstdat.cpp @@ -119,7 +119,7 @@ const MonsterData monsterdata[NUM_MTYPES] = { /* MT_GMAGE */ { MOFILE_MAGE, 27, 7, "Monsters\\Mage\\Cnselg.TRN", "Magistrate", { AI_COUNSLR, 1, MIS_CBOLTC, 0 }, 85, 85, 0 , 100, 10, 24, 0, 0, 0, 65, 0, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 4478, ALIGN }, // MC_DEMON, /* MT_XMAGE */ { MOFILE_MAGE, 29, 7, "Monsters\\Mage\\Cnselgd.TRN", "Cabalist", { AI_COUNSLR, 2, MIS_LIGHTNINGC, 0 }, 120, 120, 0 , 110, 12, 28, 0, 0, 0, 70, 0, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 4929, ALIGN }, // MC_DEMON, /* MT_BMAGE */ { MOFILE_MAGE, 30, 7, "Monsters\\Mage\\Cnselbk.TRN", "Advocate", { AI_COUNSLR, 3, MIS_FIREBALL, 0 }, 145, 145, MFLAG_CAN_OPEN_DOOR, 120, 14, 32, 0, 0, 0, 70, 0, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 4968, ALIGN }, // MC_DEMON, -/* MT_GOLEM */ { MOFILE_GOLEM, 1, 0, NULL, "Golem", { AI_GOLUM, 0, 0, 0 }, 1, 1, MFLAG_NOSTONE | MFLAG_NOCORPSE | MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 0, ALIGN }, // MC_DEMON, +/* MT_GOLEM */ { MOFILE_GOLEM, 4, 0, NULL, "Golem", { AI_GOLUM, 0, 0, 0 }, 40, 40, MFLAG_NOSTONE | MFLAG_NOCORPSE | MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 30, 3, 5, 0, 0, 0, 0, 0, 50, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 0, ALIGN }, // MC_DEMON, /* MT_DIABLO */ { MOFILE_DIABLO, 32, 7, NULL, "The Dark Lord", { AI_ROUNDRANGED, 3, MIS_APOCAC2, 0 }, 1666, 1666, MFLAG_NOSTONE | MFLAG_NOCORPSE | MFLAG_KNOCKBACK | MFLAG_SEARCH, 240, 30, 60, 0, 0, 0, 200, 0, 90, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , 8333, ALIGN }, // MC_DEMON, /* MT_DARKMAGE*///{ MOFILE_DARKMAGE, 30, 7, NULL, "The Arch-Litch Malignus", { AI_COUNSLR, 3, MIS_FIREBALL, 0 }, 160, 160, MFLAG_CAN_OPEN_DOOR, 120, 20, 40, 0, 0, 0, 0, 0, 70, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 4968, ALIGN }, // MC_DEMON, #ifdef HELLFIRE diff --git a/Source/monster.cpp b/Source/monster.cpp index 395d94c04d9..e06ea1ac054 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -5026,14 +5026,24 @@ void InitGolemStats(int mnum, int level) MonsterStruct* mon; mon = &monsters[mnum]; - mon->_mLevel = level; - mon->_mmaxhp = 640 * (level + 1); - mon->_mArmorClass = 25 + level; - mon->_mEvasion = 10 + (level >> 1); - mon->_mHit = 4 * level + 40; - mon->_mMinDamage = 4 + (level >> 1); - mon->_mMaxDamage = 2 * mon->_mMinDamage; - mon->_mExp = 0; + int lvlBonus = level > 0 ? level - 1 : 0; + + // mon->_mAI.aiInt = monsterdata[MT_GOLEM].mAI.aiInt + lvlBonus / 16; + mon->_mHit = monsterdata[MT_GOLEM].mHit + lvlBonus * 5 / 2; + // mon->_mHit2 = monsterdata[MT_GOLEM].mHit2 + lvlBonus * 5 / 2; + // mon->_mMagic = monsterdata[MT_GOLEM].mMagic + lvlBonus * 5 / 2; + mon->_mEvasion = monsterdata[MT_GOLEM].mEvasion + lvlBonus * 5 / 2; + mon->_mArmorClass = monsterdata[MT_GOLEM].mArmorClass + lvlBonus * 5 / 2; + + int baseLvl = monsterdata[MT_GOLEM].mLevel; + int monLvl = baseLvl + lvlBonus; + mon->_mLevel = monLvl; + mon->_mmaxhp = (monLvl * monsterdata[MT_GOLEM].mMinHP / baseLvl) << 6; + mon->_mExp = 0; // monLvl * mon->_mExp / baseLvl; + mon->_mMinDamage = monLvl * monsterdata[MT_GOLEM].mMinDamage / baseLvl; + mon->_mMaxDamage = monLvl * monsterdata[MT_GOLEM].mMaxDamage / baseLvl; + // mon->_mMinDamage2 = monLvl * monsterdata[MT_GOLEM].mMinDamage2 / baseLvl; + // mon->_mMaxDamage2 = monLvl * monsterdata[MT_GOLEM].mMaxDamage2 / baseLvl; } void SpawnGolem(int mnum, int x, int y, int level) @@ -5044,7 +5054,7 @@ void SpawnGolem(int mnum, int x, int y, int level) if ((unsigned)mnum >= MAXMONSTERS) { dev_fatal("SpawnGolem: Invalid monster %d", mnum); } - InitGolemStats(mnum, level * 2 + (plx(mnum)._pMagic >> 6)); + InitGolemStats(mnum, level * 4 + (plx(mnum)._pMagic >> 6)); mon = &monsters[mnum]; mon->_mhitpoints = mon->_mmaxhp; mon->_mvid = AddVision(x, y, PLR_MIN_VISRAD, false); From 333543cbc16e2c9f20874c46184d41f3ddb87d81 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 26 Dec 2023 11:50:01 +0100 Subject: [PATCH 157/596] cosmetic --- Source/monster.cpp | 138 ++++++++++++++++++--------------------------- 1 file changed, 55 insertions(+), 83 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index e06ea1ac054..43cb30185f4 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -2986,11 +2986,9 @@ static bool MonRoundWalk(int mnum, int md, int* dir) void MAI_Zombie(int mnum) { - MonsterStruct* mon; + MonsterStruct* mon = &monsters[mnum]; int md; - - mon = &monsters[mnum]; - if (MON_ACTIVE || MON_RELAXED) + if (MON_RELAXED || MON_ACTIVE) return; if (random_(103, 100) < 2 * mon->_mAI.aiInt + 10) { @@ -3014,10 +3012,8 @@ void MAI_Zombie(int mnum) void MAI_SkelSd(int mnum) { - MonsterStruct* mon; - - mon = &monsters[mnum]; - if (MON_ACTIVE || MON_RELAXED) + MonsterStruct* mon = &monsters[mnum]; + if (MON_RELAXED || MON_ACTIVE) return; MonEnemyInfo(mnum); @@ -3041,13 +3037,12 @@ void MAI_SkelSd(int mnum) void MAI_Snake(int mnum) { - MonsterStruct* mon; + MonsterStruct* mon = &monsters[mnum]; int dist, md; - const BYTE pattern[6] = { 1, 1, 0, 7, 7, 0 }; - mon = &monsters[mnum]; - if (MON_ACTIVE || MON_RELAXED) + if (MON_RELAXED || MON_ACTIVE) return; + MonEnemyInfo(mnum); // assert(!(mon->_mFlags & MFLAG_CAN_OPEN_DOOR)); mon->_mdir = currEnemyInfo._meLastDir; @@ -3098,11 +3093,9 @@ void MAI_Snake(int mnum) void MAI_Bat(int mnum) { - MonsterStruct* mon; + MonsterStruct* mon = &monsters[mnum]; int md, v, dist; - - mon = &monsters[mnum]; - if (MON_ACTIVE || MON_RELAXED) + if (MON_RELAXED || MON_ACTIVE) return; MonEnemyInfo(mnum); @@ -3150,11 +3143,9 @@ void MAI_Bat(int mnum) void MAI_SkelBow(int mnum) { - MonsterStruct* mon; + MonsterStruct* mon = &monsters[mnum]; int v; - - mon = &monsters[mnum]; - if (MON_ACTIVE || MON_RELAXED) + if (MON_RELAXED || MON_ACTIVE) return; MonEnemyInfo(mnum); @@ -3184,11 +3175,9 @@ void MAI_SkelBow(int mnum) void MAI_Fat(int mnum) { - MonsterStruct* mon; + MonsterStruct* mon = &monsters[mnum]; int v; - - mon = &monsters[mnum]; - if (MON_ACTIVE || MON_RELAXED) + if (MON_RELAXED || MON_ACTIVE) return; MonEnemyInfo(mnum); @@ -3209,13 +3198,11 @@ void MAI_Fat(int mnum) void MAI_Sneak(int mnum) { - MonsterStruct* mon; - int md; - int dist, range, v; - - mon = &monsters[mnum]; - if (MON_ACTIVE || MON_RELAXED) + MonsterStruct* mon = &monsters[mnum]; + int md, dist, range, v; + if (MON_RELAXED || MON_ACTIVE) return; + // mx = mon->_mx; // my = mon->_my; // commented out because dLight is not in-sync in multiplayer games and with the added @@ -3279,12 +3266,11 @@ void MAI_Sneak(int mnum) /*void MAI_Fireman(int mnum) { - MonsterStruct* mon; + MonsterStruct* mon = &monsters[mnum]; int mx, my, fx, fy, md; - - mon = &monsters[mnum]; - if (MON_ACTIVE || MON_RELAXED) + if (MON_RELAXED || MON_ACTIVE) return; + MonEnemyInfo(mnum); mx = mon->_mx; my = mon->_my; @@ -3328,12 +3314,11 @@ void MAI_Sneak(int mnum) void MAI_Fallen(int mnum) { - MonsterStruct* mon; + MonsterStruct* mon = &monsters[mnum]; int x, y, mx, my, m, rad, amount; - - mon = &monsters[mnum]; - if (MON_ACTIVE || MON_RELAXED) + if (MON_RELAXED || MON_ACTIVE) return; + // assert(!(mon->_mFlags & MFLAG_CAN_OPEN_DOOR)); if (mon->_mgoal == MGOAL_NORMAL) { if (random_(113, 48) == 0) { @@ -3403,11 +3388,10 @@ void MAI_Fallen(int mnum) void MAI_Cleaver(int mnum) { - MonsterStruct* mon; - - mon = &monsters[mnum]; - if (MON_ACTIVE || MON_RELAXED) + MonsterStruct* mon = &monsters[mnum]; + if (MON_RELAXED || MON_ACTIVE) return; + MonEnemyInfo(mnum); // assert(!(mon->_mFlags & MFLAG_CAN_OPEN_DOOR) || (mon->_mFlags & MFLAG_SEARCH)); mon->_mdir = currEnemyInfo._meLastDir; @@ -3427,11 +3411,9 @@ void MAI_Cleaver(int mnum) */ void MAI_Round(int mnum) { - MonsterStruct* mon; + MonsterStruct* mon = &monsters[mnum]; int md, dist, v; - - mon = &monsters[mnum]; - if (MON_ACTIVE || MON_RELAXED) + if (MON_RELAXED || MON_ACTIVE) return; MonEnemyInfo(mnum); @@ -3483,12 +3465,11 @@ void MAI_Round(int mnum) */ void MAI_Ranged(int mnum) { + MonsterStruct* mon = &monsters[mnum]; int md; - MonsterStruct* mon; - - mon = &monsters[mnum]; - if (MON_ACTIVE || MON_RELAXED) + if (MON_RELAXED || MON_ACTIVE) return; + MonEnemyInfo(mnum); if (mon->_msquelch < SQUELCH_MAX && (mon->_mFlags & MFLAG_CAN_OPEN_DOOR)) MonstCheckDoors(mon->_mx, mon->_my); @@ -3574,13 +3555,12 @@ static void MonConsumeCorpse(MonsterStruct* mon) void MAI_Scav(int mnum) { - MonsterStruct* mon; + MonsterStruct* mon = &monsters[mnum]; int i, j, tx, ty, maxhp, tmp; const int8_t* cr; - - mon = &monsters[mnum]; - if (MON_ACTIVE || MON_RELAXED) + if (MON_RELAXED || MON_ACTIVE) return; + if (mon->_mhitpoints < (mon->_mmaxhp >> 1) && mon->_mgoal != MGOAL_HEALING) { MonLeaveLeader(mnum); mon->_mgoal = MGOAL_HEALING; @@ -3695,7 +3675,7 @@ void MAI_Garg(int mnum) return; } - if (MON_ACTIVE || MON_RELAXED) + if (MON_RELAXED || MON_ACTIVE) return; if (mon->_mhitpoints < (mon->_mmaxhp >> 1)) @@ -3727,12 +3707,11 @@ void MAI_Garg(int mnum) */ void MAI_RoundRanged(int mnum) { - MonsterStruct* mon; + MonsterStruct* mon = &monsters[mnum]; int dist, v; - - mon = &monsters[mnum]; - if (MON_ACTIVE || MON_RELAXED) + if (MON_RELAXED || MON_ACTIVE) return; + MonEnemyInfo(mnum); if (mon->_msquelch < SQUELCH_MAX && (mon->_mFlags & MFLAG_CAN_OPEN_DOOR)) MonstCheckDoors(mon->_mx, mon->_my); @@ -3792,12 +3771,11 @@ void MAI_RoundRanged(int mnum) */ void MAI_RoundRanged2(int mnum) { - MonsterStruct* mon; + MonsterStruct* mon = &monsters[mnum]; int dist, v; - - mon = &monsters[mnum]; - if (MON_ACTIVE || MON_RELAXED) + if (MON_RELAXED || MON_ACTIVE) return; + MonEnemyInfo(mnum); dist = currEnemyInfo._meRealDist; /*if (dist >= 5) { @@ -3909,12 +3887,11 @@ void MAI_Golem(int mnum) void MAI_SkelKing(int mnum) { - MonsterStruct* mon; + MonsterStruct* mon = &monsters[mnum]; int nx, ny, md, v, dist; - - mon = &monsters[mnum]; - if (MON_ACTIVE || MON_RELAXED) + if (MON_RELAXED || MON_ACTIVE) return; + MonEnemyInfo(mnum); if (mon->_msquelch < SQUELCH_MAX) { assert(monsterdata[MT_SKING].mFlags & MFLAG_CAN_OPEN_DOOR); @@ -3973,12 +3950,11 @@ void MAI_SkelKing(int mnum) void MAI_Rhino(int mnum) { - MonsterStruct* mon; + MonsterStruct* mon = &monsters[mnum]; int v, dist; - - mon = &monsters[mnum]; - if (MON_ACTIVE || MON_RELAXED) + if (MON_RELAXED || MON_ACTIVE) return; + MonEnemyInfo(mnum); if (mon->_msquelch < SQUELCH_MAX && (mon->_mFlags & MFLAG_CAN_OPEN_DOOR)) MonstCheckDoors(mon->_mx, mon->_my); @@ -4028,12 +4004,11 @@ void MAI_Rhino(int mnum) #ifdef HELLFIRE void MAI_Horkdemon(int mnum) { - MonsterStruct* mon; + MonsterStruct* mon = &monsters[mnum]; int v, dist; - - mon = &monsters[mnum]; - if (MON_ACTIVE || MON_RELAXED) + if (MON_RELAXED || MON_ACTIVE) return; + MonEnemyInfo(mnum); // assert(!(mon->_mFlags & MFLAG_CAN_OPEN_DOOR)); v = random_(131, 100); @@ -4086,12 +4061,11 @@ void MAI_Horkdemon(int mnum) */ void MAI_Counselor(int mnum) { - MonsterStruct* mon; + MonsterStruct* mon = &monsters[mnum]; int md, v, dist; - - mon = &monsters[mnum]; - if (MON_ACTIVE || MON_RELAXED) + if (MON_RELAXED || MON_ACTIVE) return; + MonEnemyInfo(mnum); if (mon->_msquelch < SQUELCH_MAX && (mon->_mFlags & MFLAG_CAN_OPEN_DOOR)) MonstCheckDoors(mon->_mx, mon->_my); @@ -4346,10 +4320,8 @@ void MAI_Lazhelp(int mnum) void MAI_Lachdanan(int mnum) { - MonsterStruct* mon; - - mon = &monsters[mnum]; - if (MON_ACTIVE || MON_RELAXED) + MonsterStruct* mon = &monsters[mnum]; + if (MON_RELAXED || MON_ACTIVE) return; mon->_mdir = MonEnemyLastDir(mnum); From 3b562c111c44bd175540b28132c541d90260653a Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 26 Dec 2023 13:17:08 +0100 Subject: [PATCH 158/596] raise the light radius of unique monster(s) --- Source/monster.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 43cb30185f4..75328f311ec 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -40,7 +40,7 @@ static_assert(MAXMONSTERS <= UCHAR_MAX, "Leader of monsters are stored in a BYTE #define MON_NO_LEADER MAXMONSTERS /** Light radius of unique monsters */ -#define MON_LIGHTRAD 3 +#define MON_LIGHTRAD 7 /** Maximum distance of the pack-monster from its leader. */ #define MON_PACK_DISTANCE 3 From 1f596dcc29f9ad514863c98baae7fec906a7729a Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 26 Dec 2023 13:26:17 +0100 Subject: [PATCH 159/596] bugfix for vanilla (monster-light with offset) - save/load monsters light with offset (and radius) --- Source/loadsave.cpp | 40 +++++++++++++++++++++++++++++++++++++++- Source/monster.cpp | 15 +-------------- Source/monster.h | 1 - Source/msg.cpp | 4 ++-- 4 files changed, 42 insertions(+), 18 deletions(-) diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index 477c5c44218..845f608b8fc 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -1545,6 +1545,43 @@ static BYTE* SaveLevelData(BYTE* dest, bool full) return dest; } +static BYTE* SaveMonstersLight(BYTE* dest) +{ + MonsterStruct* mon; + int mnum; + LE_INT32* nl = (LE_INT32*)dest; + *nl = 0; + dest += sizeof(LE_INT32); + for (mnum = 0; mnum < MAXMONSTERS; mnum++) { + mon = &monsters[mnum]; + if (mon->_mlid != NO_LIGHT) { + LE_INT32* mp = (LE_INT32*)dest; + *mp = mnum; + dest += sizeof(LE_INT32); + dest = SaveLight(dest, &LightList[mon->_mlid]); + *nl = *nl + 1; + } + } + return dest; +} + +static BYTE* SyncMonstersLight(BYTE* src) +{ + int i, lid; + int nl = *(LE_INT32*)src; + src += sizeof(LE_INT32); + for (i = 0; i < nl; i++) { + lid = monsters[*(LE_INT32*)src]._mlid; + src += sizeof(LE_INT32); + assert(lid != NO_LIGHT); + LightListStruct lls; + src = LoadLight(src, &lls); + ChangeLight(lid, lls._lx, lls._ly, lls._lradius); + ChangeLightScreenOff(lid, lls._lxoff, lls._lyoff); + } + return src; +} + void SaveGame() { int i; @@ -1679,6 +1716,7 @@ void SaveLevel() tbuff = fileBuff; tbuff = SaveLevelData(tbuff, false); + tbuff = SaveMonstersLight(tbuff); assert((size_t)tbuff - (size_t)fileBuff < sizeof(gsDeltaData.ddBuffer) - SHA1BlockSize - 8 /*sizeof(CodecSignature)*/); pfile_write_save_file(false, (size_t)tbuff - (size_t)fileBuff); @@ -1694,8 +1732,8 @@ void LoadLevel() tbuff = fileBuff; tbuff = LoadLevelData(tbuff, false); + tbuff = SyncMonstersLight(tbuff); - SyncMonsterLight(); //ResyncQuests(); //SyncPortals(); diff --git a/Source/monster.cpp b/Source/monster.cpp index 75328f311ec..4c20ab91c33 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -465,7 +465,7 @@ void InitLvlMonsters() monsters[i]._mWhoHit = 0; monsters[i]._mgoal = MGOAL_NORMAL; // reset _muniqtype value to simplify SyncMonsterAnim (loadsave.cpp) - // reset _mlid value to simplify SyncMonsterLight, DeltaLoadLevel, SummonMonster and InitTownerInfo + // reset _mlid value to simplify SyncMonstersLight, DeltaLoadLevel, SummonMonster and InitTownerInfo monsters[i]._muniqtype = 0; monsters[i]._muniqtrans = 0; monsters[i]._mNameColor = COL_WHITE; @@ -4629,19 +4629,6 @@ void SyncMonsterAnim(int mnum) mon->_mAnimLen = mon->_mAnims[anim].maFrames; } -void SyncMonsterLight() -{ - MonsterStruct* mon; - int i; - - for (i = 0; i < MAXMONSTERS; i++) { - mon = &monsters[i]; - if (mon->_mlid != NO_LIGHT /*&& mon->_mmode > MM_INGAME_LAST*/) { - ChangeLightXY(mon->_mlid, mon->_mx, mon->_my); - } - } -} - void MissToMonst(int mi) { MissileStruct* mis; diff --git a/Source/monster.h b/Source/monster.h index 736fe2b4266..b1b243e408b 100644 --- a/Source/monster.h +++ b/Source/monster.h @@ -59,7 +59,6 @@ void FreeMonsters(); //bool CheckAllowMissile(int x, int y); bool LineClear(int x1, int y1, int x2, int y2); void SyncMonsterAnim(int mnum); -void SyncMonsterLight(); void MissToMonst(int mnum); /* Check if the monster can be displaced to the given position. (unwillingly) */ bool PosOkMonster(int mnum, int x, int y); diff --git a/Source/msg.cpp b/Source/msg.cpp index 20873c91896..854482ca0b5 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -996,7 +996,7 @@ void DeltaLoadLevel() // set hitpoints for dead monsters as well to ensure sync in multiplayer // games even on the first game_logic run mon->_mhitpoints = mstr->dmhitpoints; - // SyncMonsterLight: inline for better performance + apply to moving monsters + // SyncMonstersLight: inline for better performance + apply to moving monsters if (mon->_mlid != NO_LIGHT) ChangeLightXY(mon->_mlid, mon->_mx, mon->_my); static_assert(DCMD_MON_DESTROYED == DCMD_MON_DEAD + 1, "DeltaLoadLevel expects ordered DCMD_MON_ enum I."); @@ -1040,7 +1040,7 @@ void DeltaLoadLevel() } nummonsters = MAX_MINIONS; } - // SyncMonsterLight(); + // SyncMonstersLight(); DeltaLoadAutomap(gsDeltaData.ddLocal[currLvl._dLevelIdx]); From 809b6bf4aa674c6a31e080c7d29408d74b62de96 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 26 Dec 2023 14:48:45 +0100 Subject: [PATCH 160/596] comment out unused code (moving monster-lights) --- Source/debug.cpp | 2 ++ Source/loadsave.cpp | 22 +++++++++++----------- Source/missiles.cpp | 3 ++- Source/monster.cpp | 39 ++++++++++++++++++++++----------------- Source/msg.cpp | 7 +++++-- 5 files changed, 42 insertions(+), 31 deletions(-) diff --git a/Source/debug.cpp b/Source/debug.cpp index 0e3c8902ae5..9da860b151c 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -413,6 +413,8 @@ void ValidateData() app_fatal("Invalid muLevel %d for %s (%d). Too high in hell to set the level of item-drop.", um.muLevel, um.mName, i); if ((um.mUnqFlags & UMF_LEADER) != 0 && ((um.mUnqFlags & UMF_GROUP) == 0)) app_fatal("Unique monster %s (%d) is a leader without group.", um.mName, i); + if ((um.mUnqFlags & UMF_LIGHT) != 0 && i != UMT_LACHDAN) + app_fatal("Unique monster %s (%d) has light, but its movement is not supported.", um.mName, i); // required by DeltaLoadLevel, LevelDeltaLoad, LoadLevel, SaveLevel, SetMapMonsters, MonChangeMap, MonStartWalk2, MonPlace, MonDoWalk, MonDoFadein, MonDoFadeout, MI_Rhino #if DEBUG_MODE if (um.mUnqHit + monsterdata[um.mtype].mHit > INT_MAX /*- HELL_TO_HIT_BONUS */- HELL_LEVEL_BONUS * 5 / 2) // required by InitUniqueMonster app_fatal("Too high mUnqHit %d for %s (%d).", um.mUnqHit, um.mName, i); diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index 845f608b8fc..958aa2e4126 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -653,14 +653,6 @@ static BYTE* LoadPortal(BYTE* DVL_RESTRICT src, int i) return src; } -/*static void RedoPlayerLight() -{ - for (int pnum = 0; pnum < MAX_PLRS; pnum++) { - if (plr._pActive && currLvl._dLevelIdx == plr._pDunLevel) - ChangeLightXY(plr._plid, plr._px, plr._py); - } -}*/ - static BYTE* LoadLevelData(BYTE* src, bool full) { int i, moncount, ii; @@ -1545,6 +1537,14 @@ static BYTE* SaveLevelData(BYTE* dest, bool full) return dest; } +/*static void RedoPlayerLight() +{ + for (int pnum = 0; pnum < MAX_PLRS; pnum++) { + if (plr._pActive && currLvl._dLevelIdx == plr._pDunLevel) + ChangeLightXY(plr._plid, plr._px, plr._py); + } +} + static BYTE* SaveMonstersLight(BYTE* dest) { MonsterStruct* mon; @@ -1580,7 +1580,7 @@ static BYTE* SyncMonstersLight(BYTE* src) ChangeLightScreenOff(lid, lls._lxoff, lls._lyoff); } return src; -} +}*/ void SaveGame() { @@ -1716,7 +1716,7 @@ void SaveLevel() tbuff = fileBuff; tbuff = SaveLevelData(tbuff, false); - tbuff = SaveMonstersLight(tbuff); + //tbuff = SaveMonstersLight(tbuff); -- assuming there are no moving monsters with light assert((size_t)tbuff - (size_t)fileBuff < sizeof(gsDeltaData.ddBuffer) - SHA1BlockSize - 8 /*sizeof(CodecSignature)*/); pfile_write_save_file(false, (size_t)tbuff - (size_t)fileBuff); @@ -1732,7 +1732,7 @@ void LoadLevel() tbuff = fileBuff; tbuff = LoadLevelData(tbuff, false); - tbuff = SyncMonstersLight(tbuff); + //tbuff = SyncMonstersLight(tbuff); -- assuming there are no moving monsters with light //ResyncQuests(); //SyncPortals(); diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 11de1e8a4dd..a2f9333481a 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -4593,7 +4593,8 @@ void MI_Rhino(int mi) if (monsters[mnum]._mx != bx || monsters[mnum]._my != by) { SetMonsterLoc(&monsters[mnum], bx, by); // assert(monsters[mnum]._mvid == NO_VISION); - ChangeLightXY(monsters[mnum]._mlid, bx, by); + // assert(monsters[mnum]._mlid == NO_LIGHT); + //ChangeLightXY(monsters[mnum]._mlid, bx, by); } ShiftMissilePos(mi); PutMissile(mi); diff --git a/Source/monster.cpp b/Source/monster.cpp index 4c20ab91c33..bc6e9dfe95d 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1064,7 +1064,8 @@ static void SetMapMonsters(int idx) if (!posOk) { dMonster[i][j] = 0; monsters[mnum]._mmode = MM_RESERVED; - ChangeLightRadius(monsters[mnum]._mlid, 0); + // assert(monsters[mnum]._mlid == NO_LIGHT); + //ChangeLightRadius(monsters[mnum]._mlid, 0); } } lm++; @@ -1173,7 +1174,8 @@ void MonChangeMap() && PosOkActor(monsters[mnum]._mx, monsters[mnum]._my)) { dMonster[monsters[mnum]._mx][monsters[mnum]._my] = mnum + 1; monsters[mnum]._mmode = MM_STAND; - ChangeLightRadius(monsters[mnum]._mlid, MON_LIGHTRAD); + // assert(monsters[mnum]._mlid == NO_LIGHT); + //ChangeLightRadius(monsters[mnum]._mlid, MON_LIGHTRAD); } } } @@ -1641,10 +1643,11 @@ static void MonStartWalk2(int mnum, int xvel, int yvel, int xoff, int yoff, int mon->_mx = mon->_mfutx = mx; mon->_my = mon->_mfuty = my; dMonster[mx][my] = mnum + 1; - if (mon->_mlid != NO_LIGHT && !(mon->_mFlags & MFLAG_HIDDEN)) { - ChangeLightXY(mon->_mlid, mon->_mx, mon->_my); - ChangeLightScreenOff(mon->_mlid, mon->_mxoff, mon->_myoff); - } + // assert(monsters[mnum]._mlid == NO_LIGHT); + //if (mon->_mlid != NO_LIGHT && !(mon->_mFlags & MFLAG_HIDDEN)) { + // ChangeLightXY(mon->_mlid, mx, my); + // ChangeLightScreenOff(mon->_mlid, mon->_mxoff, mon->_myoff); + //} } static void MonStartAttack(int mnum) @@ -1805,8 +1808,9 @@ static void MonPlace(int mnum) mon = &monsters[mnum]; mx = mon->_mx; my = mon->_my; - if (mon->_mlid != NO_LIGHT && !(mon->_mFlags & MFLAG_HIDDEN)) - ChangeLightXYOff(mon->_mlid, mx, my); + // assert(mon->_mlid == NO_LIGHT || (LightList[mon->_mlid]._lx == mx && LightList[mon->_mlid]._ly == my)); + //if (mon->_mlid != NO_LIGHT && !(mon->_mFlags & MFLAG_HIDDEN)) + // ChangeLightXYOff(mon->_mlid, mx, my); if (mon->_mvid != NO_VISION) ChangeVisionXY(mon->_mvid, mx, my); // place monster in the new position @@ -2309,8 +2313,9 @@ static bool MonDoWalk(int mnum) mon->_mVar7 += mon->_mVar5; // MWALK_YOFF <- WALK_YVEL mon->_mxoff = mon->_mVar6 >> MON_WALK_SHIFT; mon->_myoff = mon->_mVar7 >> MON_WALK_SHIFT; - if (mon->_mlid != NO_LIGHT && !(mon->_mFlags & MFLAG_HIDDEN)) - CondChangeLightScreenOff(mon->_mlid, mon->_mxoff, mon->_myoff); + // assert(mon->_mlid == NO_LIGHT); + //if (mon->_mlid != NO_LIGHT && !(mon->_mFlags & MFLAG_HIDDEN)) + // CondChangeLightScreenOff(mon->_mlid, mon->_mxoff, mon->_myoff); //} rv = false; } @@ -2525,10 +2530,11 @@ static bool MonDoFadein(int mnum) return false; mon->_mFlags &= ~MFLAG_REV_ANIMATION; - if (mon->_mlid != NO_LIGHT) { // && !(mon->_mFlags & MFLAG_HIDDEN)) { - ChangeLightRadius(mon->_mlid, MON_LIGHTRAD); - ChangeLightXYOff(mon->_mlid, mon->_mx, mon->_my); - } + // assert(mon->_mlid == NO_LIGHT); + //if (mon->_mlid != NO_LIGHT) { // && !(mon->_mFlags & MFLAG_HIDDEN)) { + // ChangeLightRadius(mon->_mlid, MON_LIGHTRAD); + // ChangeLightXYOff(mon->_mlid, mon->_mx, mon->_my); + //} AssertFixMonLocation(mnum); MonStartStand(mnum); return true; @@ -2545,9 +2551,8 @@ static bool MonDoFadeout(int mnum) mon->_mFlags &= ~MFLAG_REV_ANIMATION; //if (mon->_mType < MT_INCIN || mon->_mType > MT_HELLBURN) { mon->_mFlags |= MFLAG_HIDDEN; - if (mon->_mlid != NO_LIGHT) { - ChangeLightRadius(mon->_mlid, 0); - } + // assert(mon->_mlid == NO_LIGHT); + //ChangeLightRadius(mon->_mlid, 0); //} AssertFixMonLocation(mnum); MonStartStand(mnum); diff --git a/Source/msg.cpp b/Source/msg.cpp index 854482ca0b5..b87d3ca7929 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -996,9 +996,11 @@ void DeltaLoadLevel() // set hitpoints for dead monsters as well to ensure sync in multiplayer // games even on the first game_logic run mon->_mhitpoints = mstr->dmhitpoints; +#if 0 // commented out because the implementation is incomplete (e.g. what about hidden monsters) // SyncMonstersLight: inline for better performance + apply to moving monsters if (mon->_mlid != NO_LIGHT) ChangeLightXY(mon->_mlid, mon->_mx, mon->_my); +#endif static_assert(DCMD_MON_DESTROYED == DCMD_MON_DEAD + 1, "DeltaLoadLevel expects ordered DCMD_MON_ enum I."); static_assert(NUM_DCMD_MON == DCMD_MON_DESTROYED + 1, "DeltaLoadLevel expects ordered DCMD_MON_ enum II."); if (mstr->dmCmd >= DCMD_MON_DEAD) { @@ -1560,8 +1562,9 @@ void LevelDeltaLoad() //BYTE _mvid; // vision id of the monster (for minions only) mon->_mFlags = tmon->smFlags; // move the light of the monster - if (mon->_mlid != NO_LIGHT) - ChangeLightXY(mon->_mlid, mon->_moldx, mon->_moldy); + // assert(mon->_mlid == NO_LIGHT || (LightList[mon->_mlid]._lx == mx && LightList[mon->_mlid]._ly == my)); + //if (mon->_mlid != NO_LIGHT) + // ChangeLightXY(mon->_mlid, mon->_moldx, mon->_moldy); // place the monster mi = mon->_mmode; if (mi != MM_STONE || mon->_mhitpoints != 0) { From 478516f5a508b60a5dce72fe7a8bb08d0e7b031e Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 26 Dec 2023 16:30:15 +0100 Subject: [PATCH 161/596] get rid of _mWhoHit --- Source/loadsave.cpp | 4 ++-- Source/monster.cpp | 6 ++---- Source/msg.cpp | 18 ++++++------------ structs.h | 6 +++--- 4 files changed, 13 insertions(+), 21 deletions(-) diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index 958aa2e4126..a0afbb63f8c 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -337,7 +337,7 @@ static BYTE* LoadMonster(BYTE* DVL_RESTRICT src, int mnum, bool full) mon->_mMTidx = savedMon->vmMTidx; mon->_mpathcount = savedMon->vmpathcount; // unused - mon->_mWhoHit = savedMon->vmWhoHit; + mon->_mAlign_1 = savedMon->vmAlign_1; // unused mon->_mgoal = savedMon->vmgoal; mon->_mgoalvar1 = savedMon->vmgoalvar1; @@ -1181,7 +1181,7 @@ static BYTE* SaveMonster(BYTE* DVL_RESTRICT dest, int mnum) monSave->vmMTidx = mon->_mMTidx; monSave->vmpathcount = mon->_mpathcount; // unused - monSave->vmWhoHit = mon->_mWhoHit; + monSave->vmAlign_1 = mon->_mAlign_1; // unused monSave->vmgoal = mon->_mgoal; monSave->vmgoalvar1 = mon->_mgoalvar1; diff --git a/Source/monster.cpp b/Source/monster.cpp index bc6e9dfe95d..acf471f5005 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -462,7 +462,7 @@ void InitLvlMonsters() // reset _mMTidx value to simplify SyncMonsterAnim (loadsave.cpp) monsters[i]._mMTidx = 0; monsters[i]._mpathcount = 0; - monsters[i]._mWhoHit = 0; + monsters[i]._mAlign_1 = 0; monsters[i]._mgoal = MGOAL_NORMAL; // reset _muniqtype value to simplify SyncMonsterAnim (loadsave.cpp) // reset _mlid value to simplify SyncMonstersLight, DeltaLoadLevel, SummonMonster and InitTownerInfo @@ -665,7 +665,7 @@ void InitMonster(int mnum, int dir, int mtidx, int x, int y) //mon->_mVar8 = 0; mon->_msquelch = 0; mon->_mpathcount = 0; - mon->_mWhoHit = 0; + mon->_mAlign_1 = 0; mon->_mgoal = MGOAL_NORMAL; //mon->_mgoalvar1 = 0; -- should be set before use //mon->_mgoalvar2 = 0; @@ -1953,7 +1953,6 @@ void MonStartPlrHit(int mnum, int pnum, int dam, unsigned hitflags, int sx, int } mon = &monsters[mnum]; // assert(mon->_mmode != MM_DEATH); - mon->_mWhoHit |= 1 << pnum; if (pnum == mypnum) { NetSendCmdMonstDamage(mnum, mon->_mhitpoints); } @@ -1986,7 +1985,6 @@ void MonStartMonHit(int defm, int offm, int dam) // assert(dmon->_mmode != MM_DEATH); if ((unsigned)offm < MAX_MINIONS) { static_assert(MAX_MINIONS == MAX_PLRS, "M2MStartHit requires that owner of a monster has the same id as the monster itself."); - dmon->_mWhoHit |= 1 << offm; if (offm == mypnum) { NetSendCmdMonstDamage(defm, dmon->_mhitpoints); } diff --git a/Source/msg.cpp b/Source/msg.cpp index b87d3ca7929..74fedb5fa64 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -111,9 +111,6 @@ static void msg_mask_monhit(int pnum) gsDeltaData.ddLevel[i].monster[j].dmWhoHit &= mask; } } - // commented out because _mWhoHit is unused in multiplayer games - //for (i = 0; i < MAXMONSTERS; i++) - // monsters[i]._mWhoHit &= mask; } static int msg_wait_for_delta() @@ -558,14 +555,14 @@ static BYTE delta_kill_monster(const TCmdMonstKill* mon) { DDMonster* pD; int mnum; - BYTE bLevel, whoHit = 0; + BYTE bLevel, whoHit; - if (mon->mkPnum < MAX_PLRS) - whoHit |= 1 << mon->mkPnum; + whoHit = mon->mkPnum < MAX_PLRS ? 1 << mon->mkPnum : 0; mnum = mon->mkMnum; if (!IsMultiGame) { - return whoHit | monsters[mnum]._mWhoHit; + return whoHit; // TODO: what about trap-kills? + // return 1 << mypnum; -- exclude UMT_LACHDAN? } bLevel = mon->mkParam1.bParam1; @@ -1019,7 +1016,6 @@ void DeltaLoadLevel() mon->_mAnimData = mon->_mAnims[MA_DEATH].maAnimData[mon->_mdir]; } else { mon->_msquelch = mstr->dmactive; - // mon->_mWhoHit = mstr->dmWhoHit; if (mon->_mmode == MM_RESERVED) { mon->_mmode = MM_STAND; } @@ -1281,7 +1277,7 @@ void LevelDeltaExport() tmon->smMode = mon->_mmode; tmon->smSquelch = mon->_msquelch; //tmon->smPathcount = mon->_mpathcount; // unused - //tmon->smWhoHit = mon->_mWhoHit; -- not synced, because it is unused in multiplayer games + //tmon->smAlign_1 = mon->_mAlign_1; // unused tmon->smGoal = mon->_mgoal; tmon->smGoalvar1 = mon->_mgoalvar1; tmon->smGoalvar2 = mon->_mgoalvar2; @@ -1523,7 +1519,7 @@ void LevelDeltaLoad() mon->_mmode = tmon->smMode; mon->_msquelch = tmon->smSquelch; //mon->_mpathcount = tmon->smPathcount; // unused - //mon->_mWhoHit = tmon->smWhoHit; // unused in multiplayer games + //mon->_mAlign_1 = tmon->_mAlign_1; // unused mon->_mgoal = tmon->smGoal; mon->_mgoalvar1 = tmon->smGoalvar1; mon->_mgoalvar2 = tmon->smGoalvar2; @@ -3420,7 +3416,6 @@ static unsigned On_DUMP_MONSTERS(TCmd* pCmd, int pnum) "sq:%d " "idx:%d " //"pc:%d " - //"wh:%d " "g:%d " "gv1:%d " "gv2:%d " @@ -3493,7 +3488,6 @@ static unsigned On_DUMP_MONSTERS(TCmd* pCmd, int pnum) mon->_msquelch, mon->_mMTidx, //mon->_mpathcount, - //mon->_mWhoHit, mon->_mgoal, mon->_mgoalvar1, mon->_mgoalvar2, diff --git a/structs.h b/structs.h index 6d3e4c361fa..97f38b2c2d7 100644 --- a/structs.h +++ b/structs.h @@ -689,7 +689,7 @@ typedef struct MonsterStruct { unsigned _msquelch; BYTE _mMTidx; BYTE _mpathcount; // unused - BYTE _mWhoHit; // unused in multiplayer games + BYTE _mAlign_1; // unused BYTE _mgoal; int _mgoalvar1; int _mgoalvar2; @@ -1343,7 +1343,7 @@ typedef struct LSaveMonsterStruct { LE_UINT32 vmsquelch; BYTE vmMTidx; BYTE vmpathcount; // unused - BYTE vmWhoHit; + BYTE vmAlign_1; // unused BYTE vmgoal; LE_INT32 vmgoalvar1; LE_INT32 vmgoalvar2; @@ -1837,7 +1837,7 @@ typedef struct TSyncLvlMonster { LE_UINT32 smSquelch; //BYTE _mMTidx; //BYTE smPathcount; // unused - //BYTE smWhoHit; + //BYTE smAlign_1; // unused BYTE smGoal; LE_INT32 smGoalvar1; LE_INT32 smGoalvar2; From 61ab2cefaeb477ed08627fbc51d50b10e979ee06 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 26 Dec 2023 16:56:23 +0100 Subject: [PATCH 162/596] sync missile-targeting logic - ensure minions are not targeted by MIS_STONE - commented out CanTalkToMonst-check in Sentfire to make it consistent with MI_Rune, MI_Poison, FindClosestChain, FindClosest --- Source/missiles.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index a2f9333481a..e39b59eed8e 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -2771,10 +2771,9 @@ int AddStone(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in tx = dx + *++cr; ty = dy + *++cr; assert(IN_DUNGEON_AREA(tx, ty)); - mid = dMonster[tx][ty]; - if (mid == 0) + mid = dMonster[tx][ty] - 1; + if (mid < MAX_MINIONS) continue; - mid = mid >= 0 ? mid - 1 : -(mid + 1); mon = &monsters[mid]; if (!(mon->_mFlags & MFLAG_NOSTONE) && !CanTalkToMonst(mid)) { if (mon->_mmode != MM_FADEIN && mon->_mmode != MM_FADEOUT && mon->_mmode != MM_CHARGE && mon->_mmode != MM_STONE && mon->_mmode != MM_DEATH /*mon->_mhitpoints >= (1 << 6*/) { @@ -3470,7 +3469,7 @@ static bool Sentfire(int mi, int sx, int sy) mnum = dMonster[sx][sy] - 1; if (mnum >= MAX_MINIONS && monsters[mnum]._mhitpoints >= (1 << 6) - && !CanTalkToMonst(mnum) + //&& !CanTalkToMonst(mnum) -- commented out to make it consistent with MI_Rune, MI_Poison, FindClosestChain, FindClosest && LineClear(mis->_mix, mis->_miy, sx, sy)) { // SetRndSeed(mis->_miRndSeed); AddMissile(mis->_mix, mis->_miy, sx, sy, 0, MIS_FIREBOLT, MST_PLAYER, mis->_miSource, mis->_miSpllvl); From c10419064aa02dcf8eb00b43a0b16165219af64d Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 26 Dec 2023 17:00:06 +0100 Subject: [PATCH 163/596] cosmetic --- Source/missiles.cpp | 51 ++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index e39b59eed8e..7cc6ccb42cf 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -2775,33 +2775,32 @@ int AddStone(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in if (mid < MAX_MINIONS) continue; mon = &monsters[mid]; - if (!(mon->_mFlags & MFLAG_NOSTONE) && !CanTalkToMonst(mid)) { - if (mon->_mmode != MM_FADEIN && mon->_mmode != MM_FADEOUT && mon->_mmode != MM_CHARGE && mon->_mmode != MM_STONE && mon->_mmode != MM_DEATH /*mon->_mhitpoints >= (1 << 6*/) { - MonLeaveLeader(mid); - mis->_miVar1 = mon->_mmode; - mis->_miVar2 = mid; - mon->_mVar3 = mon->_mmode; - mon->_mmode = MM_STONE; - // ensure lastx/y are set when MI_Stone 'alerts' the monster - if (micaster == MST_PLAYER) { - mon->_mlastx = plx(misource)._px; - mon->_mlasty = plx(misource)._py; - //} else { - // assert(!MON_RELAXED); - } - - // range = (sl * 128 - HP + 128) * 2 - range = ((spllvl + 1) << (7 + 6)) - mon->_mmaxhp; - // TODO: add support for spell duration modifier - //range += (range * plx(misource)._pISplDur) >> 7; - range >>= 5; - if (range < 15) - return MIRES_DELETE; - if (range > 239) - range = 239; - mis->_miRange = range; - return MIRES_DONE; + if (!(mon->_mFlags & MFLAG_NOSTONE) && !CanTalkToMonst(mid) + && mon->_mmode != MM_FADEIN && mon->_mmode != MM_FADEOUT && mon->_mmode != MM_CHARGE && mon->_mmode != MM_STONE && mon->_mmode != MM_DEATH /*mon->_mhitpoints >= (1 << 6*/) { + MonLeaveLeader(mid); + mis->_miVar1 = mon->_mmode; + mis->_miVar2 = mid; + mon->_mVar3 = mon->_mmode; + mon->_mmode = MM_STONE; + // ensure lastx/y are set when MI_Stone 'alerts' the monster + if (micaster == MST_PLAYER) { + mon->_mlastx = plx(misource)._px; + mon->_mlasty = plx(misource)._py; + //} else { + // assert(!MON_RELAXED); } + + // range = (sl * 128 - HP + 128) * 2 + range = ((spllvl + 1) << (7 + 6)) - mon->_mmaxhp; + // TODO: add support for spell duration modifier + //range += (range * plx(misource)._pISplDur) >> 7; + range >>= 5; + if (range < 15) + return MIRES_DELETE; + if (range > 239) + range = 239; + mis->_miRange = range; + return MIRES_DONE; } } } From be2640dd8f42c8f38dd6a1e36960abff0da91988 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 27 Dec 2023 12:11:11 +0100 Subject: [PATCH 164/596] reset lastx/y in InitMonster and when a monster relaxes to prevent desync --- Source/monster.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index acf471f5005..353234201f2 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -675,8 +675,8 @@ void InitMonster(int mnum, int dir, int mtidx, int x, int y) mon->_menemyy = 0; mon->_mListener = 0; mon->_mDelFlag = FALSE; - //mon->_mlastx = 0; -- should be set before use - //mon->_mlasty = 0; + mon->_mlastx = 0; // should be set before use (except for stone-rune) + mon->_mlasty = 0; mon->_mRndSeed = NextRndSeed(); // mon->_mAISeed = -- should be set before use @@ -4457,6 +4457,8 @@ void ProcessMonsters() mon->_menemy = 0; mon->_menemyx = 0; mon->_menemyy = 0; + mon->_mlastx = 0; + mon->_mlasty = 0; mon->_mVar1 = MM_STAND; // STAND_PREV_MODE mon->_mVar2 = MON_WALK_DELAY + 1; // STAND_TICK assert(mon->_mgoal == MGOAL_NORMAL || mon->_mgoal == MGOAL_TALKING); From e2a06c5f2cb668f084eaf933930d0503f46ac6c5 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 27 Dec 2023 16:16:39 +0100 Subject: [PATCH 165/596] set mResist fields of the ARROW-missiles --- Source/misdat.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/misdat.cpp b/Source/misdat.cpp index 8e0fac40cce..cb56117dffc 100644 --- a/Source/misdat.cpp +++ b/Source/misdat.cpp @@ -12,11 +12,11 @@ DEVILUTION_BEGIN_NAMESPACE const MissileData missiledata[] = { // clang-format off // mAddProc, mProc, mdFlags, mResist, mFileNum, mDrawFlag, mlSFX, miSFX, mlSFXCnt, miSFXCnt, -/*MIS_ARROW*/ { &AddArrow, &MI_Arrow, MIF_ARROW | MIF_SHROUD | MIF_LEAD, MISR_NONE, MFILE_ARROWS, TRUE, PS_BFIRE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_PBARROW*/ { &AddArrow, &MI_Arrow, MIF_ARROW | MIF_SHROUD | MIF_LEAD, MISR_NONE, MFILE_ARROWS, TRUE, PS_BFIRE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_ASARROW*/ { &AddArrow, &MI_AsArrow, MIF_ARROW | MIF_LEAD, MISR_NONE, MFILE_ARROWS, TRUE, PS_BFIRE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_MLARROW*/ { &AddArrow, &MI_Arrow, MIF_ARROW | MIF_SHROUD | MIF_LEAD, MISR_NONE, MFILE_ARROWS, TRUE, PS_BFIRE, SFX_NONE, 1, 1, ALIGN }, // miSFX was IS_STING -/*MIS_PCARROW*/ { &AddArrow, &MI_Arrow, MIF_ARROW | MIF_SHROUD | MIF_LEAD, MISR_NONE, MFILE_ARROWS, TRUE, PS_BFIRE, SFX_NONE, 1, 1, ALIGN }, +/*MIS_ARROW*/ { &AddArrow, &MI_Arrow, MIF_ARROW | MIF_SHROUD | MIF_LEAD, MISR_PUNCTURE, MFILE_ARROWS, TRUE, PS_BFIRE, SFX_NONE, 1, 1, ALIGN }, +/*MIS_PBARROW*/ { &AddArrow, &MI_Arrow, MIF_ARROW | MIF_SHROUD | MIF_LEAD, MISR_PUNCTURE, MFILE_ARROWS, TRUE, PS_BFIRE, SFX_NONE, 1, 1, ALIGN }, +/*MIS_ASARROW*/ { &AddArrow, &MI_AsArrow, MIF_ARROW | MIF_LEAD, MISR_PUNCTURE, MFILE_ARROWS, TRUE, PS_BFIRE, SFX_NONE, 1, 1, ALIGN }, +/*MIS_MLARROW*/ { &AddArrow, &MI_Arrow, MIF_ARROW | MIF_SHROUD | MIF_LEAD, MISR_PUNCTURE, MFILE_ARROWS, TRUE, PS_BFIRE, SFX_NONE, 1, 1, ALIGN }, // miSFX was IS_STING +/*MIS_PCARROW*/ { &AddArrow, &MI_Arrow, MIF_ARROW | MIF_SHROUD | MIF_LEAD, MISR_PUNCTURE, MFILE_ARROWS, TRUE, PS_BFIRE, SFX_NONE, 1, 1, ALIGN }, /*MIS_FIREBOLT*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD | MIF_LEAD, MISR_FIRE, MFILE_FIREBA, TRUE, LS_FBOLT1, LS_FIRIMP2, 1, 1, ALIGN }, /*MIS_FIREBALL*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD | MIF_LEAD, MISR_FIRE, MFILE_FIREBA, TRUE, LS_FBOLT1, LS_FIRIMP2, 1, 1, ALIGN }, /*MIS_HBOLT*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD | MIF_LEAD, MISR_ACID, MFILE_HOLY, TRUE, LS_HOLYBOLT, LS_ELECIMP1, 1, 1, ALIGN }, From cdee681dfb541c6ecfab607e79f35f5eff3c61f6 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 27 Dec 2023 16:18:51 +0100 Subject: [PATCH 166/596] reorder enums.h - move missile_resistance closer to the other missile_* enums --- enums.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/enums.h b/enums.h index 1dde439fc6c..9b0e1779c20 100644 --- a/enums.h +++ b/enums.h @@ -2141,6 +2141,17 @@ typedef enum missile_collision_mode { MICM_BLOCK_WALL, } missile_collision_mode; +typedef enum missile_resistance { + MISR_NONE, + MISR_SLASH, + MISR_BLUNT, + MISR_PUNCTURE, + MISR_FIRE, + MISR_LIGHTNING, + MISR_MAGIC, + MISR_ACID, +} missile_resistance; + typedef enum _monster_ai { AI_ZOMBIE, AI_FAT, @@ -2501,17 +2512,6 @@ typedef enum _monster_resistance { MORS_ACID_IMMUNE = 0x03 << MORS_IDX_ACID, } _monster_resistance; -typedef enum missile_resistance { - MISR_NONE, - MISR_SLASH, - MISR_BLUNT, - MISR_PUNCTURE, - MISR_FIRE, - MISR_LIGHTNING, - MISR_MAGIC, - MISR_ACID, -} missile_resistance; - typedef enum _speech_id { TEXT_KING1, TEXT_KING2, From a11ee505aac2f5a0f12d4607dcdbf74594624a31 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 28 Dec 2023 09:09:38 +0100 Subject: [PATCH 167/596] always turn monsters with counselor-AI to its enemy --- Source/monster.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 353234201f2..51b68c30318 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -4074,6 +4074,7 @@ void MAI_Counselor(int mnum) MonstCheckDoors(mon->_mx, mon->_my); md = currEnemyInfo._meLastDir; dist = currEnemyInfo._meRealDist; + mon->_mdir = md; if (mon->_mgoal == MGOAL_NORMAL) { v = random_(121, 100); if (dist >= 2) { @@ -4091,7 +4092,6 @@ void MAI_Counselor(int mnum) MonStartFadeout(mnum, md, false); } } else { - mon->_mdir = md; if (mon->_mVar1 == MM_FADEIN) // STAND_PREV_MODE v >>= 1; if (mon->_mVar1 != MM_FADEIN && mon->_mhitpoints < (mon->_mmaxhp >> 1) && MonFindDir(mnum, OPPOSITE(md)) >= 0) { From 4481830c3650933f01c8544c8cee29d11bcde2bf Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 28 Dec 2023 09:17:04 +0100 Subject: [PATCH 168/596] use _mdir in MonStartFadein/out --- Source/monster.cpp | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 51b68c30318..d7344f77d45 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -2225,14 +2225,12 @@ void MonSyncStartKill(int mnum, int x, int y, int pnum) * Start fade in using the special effect of monsters. * Used by: Sneak, Fireman, Mage, DarkMage */ -static void MonStartFadein(int mnum, int md, bool backwards) +static void MonStartFadein(int mnum, bool backwards) { - MonsterStruct* mon; - - NewMonsterAnim(mnum, MA_SPECIAL, md); + MonsterStruct* mon = &monsters[mnum]; AssertFixMonLocation(mnum); + NewMonsterAnim(mnum, MA_SPECIAL, mon->_mdir); - mon = &monsters[mnum]; mon->_mmode = MM_FADEIN; mon->_mFlags &= ~MFLAG_HIDDEN; if (backwards) { @@ -2244,14 +2242,12 @@ static void MonStartFadein(int mnum, int md, bool backwards) } } -static void MonStartFadeout(int mnum, int md, bool backwards) +static void MonStartFadeout(int mnum, bool backwards) { - MonsterStruct* mon; - - NewMonsterAnim(mnum, MA_SPECIAL, md); + MonsterStruct* mon = &monsters[mnum]; AssertFixMonLocation(mnum); + NewMonsterAnim(mnum, MA_SPECIAL, mon->_mdir); - mon = &monsters[mnum]; mon->_mmode = MM_FADEOUT; if (backwards) { mon->_mFlags |= MFLAG_REV_ANIMATION; @@ -3250,9 +3246,9 @@ void MAI_Sneak(int mnum) range -= 2; // assert(range >= 2); if (dist < range && (mon->_mFlags & MFLAG_HIDDEN)) { - MonStartFadein(mnum, mon->_mdir, false); + MonStartFadein(mnum, false); } else if (dist > range && !(mon->_mFlags & MFLAG_HIDDEN)) { - MonStartFadeout(mnum, mon->_mdir, true); + MonStartFadeout(mnum, true); } else if (mon->_mgoal == MGOAL_NORMAL || !MonCallWalk(mnum, mon->_mdir)) { // assert(mon->_mgoal == MGOAL_NORMAL || mon->_mgoal == MGOAL_RETREAT); mon->_mgoal = MGOAL_NORMAL; @@ -3295,14 +3291,14 @@ void MAI_Sneak(int mnum) } if (!MonCallWalk(mnum, md)) { mon->_mgoal = MGOAL_ATTACK; - MonStartFadein(mnum, mon->_mdir, false); + MonStartFadein(mnum, false); } } } else if (mon->_mgoal == MGOAL_ATTACK) { if (++mon->_mgoalvar1 > 3) { // FIREMAN_ACTION_PROGRESS mon->_mgoal = MGOAL_NORMAL; mon->_mgoalvar1 = 0; - MonStartFadeout(mnum, md, true); + MonStartFadeout(mnum, true); } else if (EnemyInLine(mnum)) { MonStartRAttack(mnum, MIS_KRULL); } else { @@ -3311,7 +3307,7 @@ void MAI_Sneak(int mnum) } else { assert(mon->_mgoal == MGOAL_RETREAT); mon->_mgoal = MGOAL_ATTACK; - MonStartFadein(mnum, md, false); + MonStartFadein(mnum, false); } }*/ @@ -4089,7 +4085,7 @@ void MAI_Counselor(int mnum) mon->_mgoal = MGOAL_MOVE; mon->_mgoalvar1 = 6 + random_low(0, std::min(dist, 4)); // MOVE_DISTANCE mon->_mgoalvar2 = random_(125, 2); // MOVE_TURN_DIRECTION - MonStartFadeout(mnum, md, false); + MonStartFadeout(mnum, false); } } else { if (mon->_mVar1 == MM_FADEIN) // STAND_PREV_MODE @@ -4102,7 +4098,7 @@ void MAI_Counselor(int mnum) static_assert((20 - 1) * 1 * 2 + (1 - 1) * 1 * 5 < SQUELCH_MAX - SQUELCH_LOW, "MAI_Counselor might relax with retreat goal."); mon->_mgoal = MGOAL_RETREAT; mon->_mgoalvar1 = 5; // RETREAT_DISTANCE - MonStartFadeout(mnum, md, false); + MonStartFadeout(mnum, false); } else if (mon->_mVar1 == MM_DELAY || v < 2 * mon->_mAI.aiInt + 20) { MonStartRAttack(mnum, MIS_FLASH); } @@ -4115,7 +4111,7 @@ void MAI_Counselor(int mnum) if (--mon->_mgoalvar1 == 0 // RETREAT_DISTANCE || !MonCallWalk(mnum, OPPOSITE(md))) { mon->_mgoal = MGOAL_NORMAL; - MonStartFadein(mnum, md, true); + MonStartFadein(mnum, true); } } else { assert(mon->_mgoal == MGOAL_MOVE); @@ -4125,7 +4121,7 @@ void MAI_Counselor(int mnum) ; } else { mon->_mgoal = MGOAL_NORMAL; - MonStartFadein(mnum, md, true); + MonStartFadein(mnum, true); } } } @@ -4658,7 +4654,7 @@ void MissToMonst(int mi) assert(mon->_mdir == mis->_miDir); MonStartStand(mnum); /*if (mon->_mType >= MT_INCIN && mon->_mType <= MT_HELLBURN) { - MonStartFadein(mnum, mon->_mdir, false); + MonStartFadein(mnum, false); return; }*/ PlayMonSFX(mnum, MS_GOTHIT); From 6ba09415e4a1c3ff3c999386a4747f56b5d52d09 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 28 Dec 2023 09:50:32 +0100 Subject: [PATCH 169/596] 'bugfix' for vanilla (MM_HEAL) - set _mAnimCnt and _mAnimFrameLen (+ _mAnimLen) in MonStartHeal --- Source/monster.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index d7344f77d45..7e551374fe6 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -2260,11 +2260,11 @@ static void MonStartFadeout(int mnum, bool backwards) static void MonStartHeal(int mnum) { - MonsterStruct* mon; + MonsterStruct* mon = &monsters[mnum]; + AssertFixMonLocation(mnum); + NewMonsterAnim(mnum, MA_SPECIAL, mon->_mdir); - mon = &monsters[mnum]; - mon->_mAnimData = mon->_mAnims[MA_SPECIAL].maAnimData[mon->_mdir]; - mon->_mAnimFrame = mon->_mAnims[MA_SPECIAL].maFrames; + mon->_mAnimFrame = mon->_mAnimLen; mon->_mFlags |= MFLAG_REV_ANIMATION; mon->_mmode = MM_HEAL; static_assert((SQUELCH_MAX - SQUELCH_LOW) >= 16 * 8, "MonStartHeal might relax while healing."); From 5bbb69670de6a036f3de27990dcfe5425d25d1d7 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 28 Dec 2023 10:42:54 +0100 Subject: [PATCH 170/596] reduce the number of MonFindEnemy calls --- Source/monster.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 7e551374fe6..ecd5e94c2cd 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3651,7 +3651,7 @@ void MAI_Garg(int mnum) mon = &monsters[mnum]; if (mon->_mFlags & MFLAG_GARG_STONE) { if (!MON_RELAXED) { - // MonFindEnemy(mnum); + MonFindEnemy(mnum); mx = mon->_mx - mon->_menemyx; my = mon->_my - mon->_menemyy; dist = std::max(abs(mx), abs(my)); @@ -4413,7 +4413,7 @@ void ProcessMonsters() } alert = (dFlags[mon->_mfutx][mon->_mfuty] & BFLAG_ALERT) != 0; - if (alert || MON_HAS_ENEMY) { + if ((alert || MON_HAS_ENEMY) && !MON_ACTIVE) { MonFindEnemy(mnum); // commented out, because the player might went out of sight in the meantime // assert(MON_HAS_ENEMY || myplr._pInvincible); From cc63fa659e90a1ae3774c6988b201d4c1a58a62e Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 28 Dec 2023 10:44:03 +0100 Subject: [PATCH 171/596] use MonEnemyInfo in MAI_Garg --- Source/monster.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index ecd5e94c2cd..7c9902f784b 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3646,18 +3646,15 @@ void MAI_Scav(int mnum) void MAI_Garg(int mnum) { MonsterStruct* mon; - int mx, my, dist; mon = &monsters[mnum]; if (mon->_mFlags & MFLAG_GARG_STONE) { if (!MON_RELAXED) { MonFindEnemy(mnum); - mx = mon->_mx - mon->_menemyx; - my = mon->_my - mon->_menemyy; - dist = std::max(abs(mx), abs(my)); + MonEnemyInfo(mnum); // wake up if the enemy is close static_assert(std::max(DBORDERX, DBORDERY) > (5 + 2), "MAI_Garg skips MFLAG_NO_ENEMY-check by assuming a monster is usually 'far' from (0;0)."); // (_menemyx;_menemyy) - if (dist < mon->_mAI.aiInt + 2) { + if (currEnemyInfo._meRealDist < mon->_mAI.aiInt + 2) { mon->_mFlags &= ~(MFLAG_LOCK_ANIMATION | MFLAG_GARG_STONE); return; } From a8da342be8b2b63119bd66555aeb341fdf46c6c4 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 28 Dec 2023 11:37:38 +0100 Subject: [PATCH 172/596] validate MFLAG_GARG_STONE vs. MFLAG_HIDDEN --- Source/debug.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/debug.cpp b/Source/debug.cpp index 9da860b151c..206419d26cf 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -277,6 +277,8 @@ void ValidateData() app_fatal("Invalid mLevel %d for %s (%d). Too high to set the level of item-drop.", md.mLevel, md.mName, i); if (md.moFileNum == MOFILE_DIABLO && !(md.mFlags & MFLAG_NOCORPSE)) app_fatal("MOFILE_DIABLO does not have corpse animation but MFLAG_NOCORPSE is not set for %s (%d).", md.mName, i); + if ((md.mFlags & MFLAG_GARG_STONE) && (md.mFlags & MFLAG_HIDDEN)) + app_fatal("Both GARG_STONE and HIDDEN flags are set for %s (%d).", md.mName, i); // required ProcessMonsters #if DEBUG_MODE if (md.mHit > INT_MAX /*- HELL_TO_HIT_BONUS */- HELL_LEVEL_BONUS * 5 / 2) // required by InitMonsterStats app_fatal("Too high mHit %d for %s (%d).", md.mHit, md.mName, i); From 0720756e12ef4b8938fffdc5741d4bdb29cb2fab Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 28 Dec 2023 13:23:33 +0100 Subject: [PATCH 173/596] 'pre-calculate' hit-chance of arrow-missiles --- Source/missiles.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 7cc6ccb42cf..14645a8d2ee 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -760,7 +760,7 @@ static bool MonsterTrapHit(int mnum, int mi) // SetRndSeed(mis->_miRndSeed); // mis->_miRndSeed = NextRndSeed(); if (mis->_miFlags & MIF_ARROW) { - hper = 100 + (2 * currLvl._dLevel); + hper = mis->_miVar6; // MISHIT hper -= mon->_mArmorClass; hper -= mis->_miVar7 << 1; // MISDIST } else { @@ -999,7 +999,7 @@ static bool PlayerTrapHit(int pnum, int mi) // SetRndSeed(mis->_miRndSeed); // mis->_miRndSeed = NextRndSeed(); if (mis->_miFlags & MIF_ARROW) { - hper = 100 + (4 * currLvl._dLevel); + hper = mis->_miVar6; // MISHIT hper -= plr._pIAC; hper -= mis->_miVar7 << 1; // MISDIST } else { @@ -1061,7 +1061,7 @@ static bool PlayerMHit(int pnum, int mi) // mis->_miRndSeed = NextRndSeed(); mon = &monsters[mis->_miSource]; if (mis->_miFlags & MIF_ARROW) { - hper = 30 + mon->_mHit + (2 * mon->_mLevel); + hper = mis->_miVar6; // MISHIT hper -= plr._pIAC; hper -= mis->_miVar7 << 1; // MISDIST } else { @@ -1834,6 +1834,7 @@ int AddRingC(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in /* * Var1: x coordinate of the missile-target of MIS_ASARROW * Var2: y coordinate of the missile-target of MIS_ASARROW + * Var6: hit chance (MISHIT) * Var7: the distance travelled (MISDIST) */ int AddArrow(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) @@ -1884,12 +1885,15 @@ int AddArrow(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in mis->_miVar1 = dx; mis->_miVar2 = dy; } + // mis->_miVar6 = plx(misource)._pIHitChance; } else if (micaster == MST_MONSTER) { mis->_miMinDam = monsters[misource]._mMinDamage << 6; mis->_miMaxDam = monsters[misource]._mMaxDamage << 6; + mis->_miVar6 = 30 + monsters[misource]._mHit + 2 * monsters[misource]._mLevel; } else { mis->_miMinDam = currLvl._dLevel << 6; mis->_miMaxDam = currLvl._dLevel << (1 + 6); + mis->_miVar6 = 100 + currLvl._dLevel * 2; } return MIRES_DONE; } From d88901906fc9e1bacb5eea62e25231ab4278c270 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 28 Dec 2023 16:02:19 +0100 Subject: [PATCH 174/596] 'bugfix' for vanilla (h2h monster vs. monster) - do not ignore AC of the defending monster when an another monster attacks --- Source/monster.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 7c9902f784b..29b6a39f99d 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -2327,8 +2327,8 @@ static void MonHitMon(int offm, int defm, int hper, int mind, int maxd) if (!CheckMonsterHit(defm, &ret)) return; - hper += (monsters[offm]._mLevel << 1); - hper -= (monsters[defm]._mLevel << 1); + hper += 30 + 2 * monsters[offm]._mLevel; + hper -= monsters[defm]._mArmorClass; if (CheckHit(hper) || monsters[defm]._mmode == MM_STONE) { int dam = RandRange(mind, maxd) << 6; monsters[defm]._mhitpoints -= dam; From 52a7a41397f1b245cceb403990b5aca5fff33d54 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 28 Dec 2023 16:40:47 +0100 Subject: [PATCH 175/596] re-balance muLevels --- Source/monstdat.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Source/monstdat.cpp b/Source/monstdat.cpp index 24265d3a58e..3e2dc05c9f9 100644 --- a/Source/monstdat.cpp +++ b/Source/monstdat.cpp @@ -62,7 +62,7 @@ const MonsterData monsterdata[NUM_MTYPES] = { /* MT_RACID */ { MOFILE_ACID, 15, 3, "Monsters\\Acid\\AcidBlk.TRN", "Poison Spitter", { AI_ROUNDRANGED, 1, MIS_ACID, 1 }, 60, 85, 0 , 45, 4, 16, 0, 0, 0, 40, 0, 30, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, 1248, ALIGN }, // MC_ANIMAL, /* MT_BACID */ { MOFILE_ACID, 21, 3, "Monsters\\Acid\\AcidB.TRN", "Pit Beast", { AI_ROUNDRANGED, 2, MIS_ACID, 1 }, 80, 110, 0 , 55, 8, 18, 0, 0, 0, 50, 0, 35, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2060, ALIGN }, // MC_ANIMAL, /* MT_XACID */ { MOFILE_ACID, 25, 3, "Monsters\\Acid\\AcidR.TRN", "Lava Maw", { AI_ROUNDRANGED, 3, MIS_ACID, 1 }, 100, 150, 0 , 65, 10, 20, 0, 0, 0, 60, 0, 35, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 2940, ALIGN }, // MC_ANIMAL, -/* MT_SKING */ { MOFILE_SKING, 14, 7, "Monsters\\SkelSd\\White.TRN", "Skeleton King", { AI_SKELKING, 3, 0, 0 }, 140, 140, MFLAG_LIFESTEAL | MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 60, 6, 16, 0, 0, 0, 0, 0, 70, 30, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE , 570, ALIGN }, // MC_UNDEAD, +/* MT_SKING */ { MOFILE_SKING, 6, 7, "Monsters\\SkelSd\\White.TRN", "Skeleton King", { AI_SKELKING, 3, 0, 0 }, 140, 140, MFLAG_LIFESTEAL | MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 75, 6, 16, 0, 0, 0, 0, 0, 70, 30, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE , 570, ALIGN }, // MC_UNDEAD, /* MT_CLEAVER */ { MOFILE_CLEAVER, 6, 3, NULL, "The Butcher", { AI_CLEAVER, 3, 0, 0 }, 220, 220, MFLAG_CAN_BLEED, 50, 6, 12, 0, 0, 0, 0, 0, 50, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 710, ALIGN }, // MC_DEMON, /* MT_NFAT */ { MOFILE_FAT, 10, 3, NULL, "Overlord", { AI_FAT, 0, 0, 0 }, 60, 80, 0 | MFLAG_CAN_BLEED, 55, 6, 12, 30, 8, 14, 0, 0, 55, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 635, ALIGN }, // MC_DEMON, /* MT_BFAT */ { MOFILE_FAT, 14, 3, "Monsters\\Fat\\Blue.TRN", "Mud Man", { AI_FAT, 1, 0, 0 }, 100, 125, MFLAG_SEARCH | MFLAG_CAN_BLEED, 60, 8, 16, 35, 8, 20, 0, 0, 60, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 1165, ALIGN }, // MC_DEMON, @@ -135,8 +135,8 @@ const MonsterData monsterdata[NUM_MTYPES] = { /* MT_SPIDLORD */ { MOFILE_BSPIDR, 24, 7, NULL, "Spider Lord", { AI_ROUNDRANGED, 3, MIS_ACID, 1 }, 80, 100, MFLAG_SEARCH , 60, 8, 20, 0, 0, 0, 60, 0, 60, 50, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 1250, ALIGN }, // MC_ANIMAL, /* MT_LASHWORM */ { MOFILE_CLASP, 23, 3, NULL, "Lashworm", { AI_SKELSD, 3, 0, 0 }, 30, 30, 0 , 90, 12, 20, 0, 0, 0, 0, 0, 50, 35, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 600, ALIGN }, // MC_ANIMAL, /* MT_TORCHANT */ { MOFILE_ANTWORM, 22, 7, NULL, "Torchant", { AI_RANGED, 3, MIS_FIREBALL, FALSE }, 60, 80, 0 , 75, 20, 30, 0, 0, 0, 55, 0, 70, 50, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1250, ALIGN }, // MC_ANIMAL, -/* MT_HORKDMN */ { MOFILE_HORKD, 28, 7, NULL, "Hork Demon", { AI_SKELSD, 3, 0, 0 }, 120, 160, MFLAG_SEARCH | MFLAG_CAN_BLEED, 60, 20, 35, 0, 0, 0, 0, 0, 80, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2000, ALIGN }, // MC_DEMON, -/* MT_DEFILER */ { MOFILE_HELLBUG, 30, 7, NULL, "Hell Bug", { AI_FAT, 3, 0, 0 }, 480, 480, MFLAG_SEARCH , 110, 20, 30, 80, 24, 40, 0, 0, 80, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 5000, ALIGN }, // MC_DEMON, +/* MT_HORKDMN */ { MOFILE_HORKD, 22, 7, NULL, "Hork Demon", { AI_SKELSD, 3, 0, 0 }, 120, 160, MFLAG_SEARCH | MFLAG_CAN_BLEED, 75, 20, 35, 0, 0, 0, 0, 0, 80, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2000, ALIGN }, // MC_DEMON, +/* MT_DEFILER */ { MOFILE_HELLBUG, 24, 7, NULL, "Hell Bug", { AI_FAT, 3, 0, 0 }, 480, 480, MFLAG_SEARCH , 120, 20, 30, 90, 24, 40, 0, 0, 80, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 5000, ALIGN }, // MC_DEMON, /* MT_LRDSAYTR */ { MOFILE_GOATLORD, 26, 7, NULL, "Satyr Lord", { AI_SKELSD, 3, 0, 0 }, 160, 200, MFLAG_SEARCH | MFLAG_CAN_BLEED, 90, 20, 30, 0, 0, 0, 0, 0, 70, 60, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2800, ALIGN }, // MC_DEMON, /* MT_GRAVEDIG */ { MOFILE_GRAVDG, 26, 3, NULL, "Gravedigger", { AI_SCAV, 3, 0, 0 }, 120, 240, MFLAG_CAN_OPEN_DOOR, 80, 6, 26, 0, 0, 0, 0, 0, 20, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE , 2000, ALIGN }, // MC_UNDEAD, /* MT_BIGFALL */ { MOFILE_BIGFALL, 27, 3, NULL, "Devil Kin Brute", { AI_SKELSD, 3, 0, 0 }, 120, 160, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 100, 18, 24, 0, 0, 0, 0, 0, 70, 60, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2400, ALIGN }, // MC_ANIMAL, @@ -395,20 +395,20 @@ const UniqMonData uniqMonData[] = { // clang-format off // mtype, mName, mTrnName, muLevelIdx, muLevel, mmaxhp, mAI.aiType, aiInt, aiParam1, aiParam2, mMinDamage, mMaxDamage, mMinDamage2, mMaxDamage2, mMagicRes, mMagicRes2, mUnqFlags, mUnqHit, mUnqHit2, mUnqMag, mUnqEva, mUnqAC, mQuestId, mtalkmsg, /*UMT_GARBUD*/ { MT_NGOATMC, "Gharbad the Weak", "BSDB", DLV_CATHEDRAL4, 8, 120, { AI_GARBUD, 3, TRUE, 0 }, 8, 16, 8, 16, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_GARBUD, TEXT_GARBUD1, ALIGN }, -/*UMT_SKELKING*/ { MT_SKING, "Skeleton King", NULL, 0, 14, 240, { AI_SKELKING, 3, 0, 0 }, 6, 16, 0, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE , 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, +/*UMT_SKELKING*/ { MT_SKING, "Skeleton King", NULL, 0, 6, 240, { AI_SKELKING, 3, 0, 0 }, 6, 16, 0, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE , 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, /*UMT_ZHAR*/ { MT_NMAGE, "Zhar the Mad", "GENERAL", DLV_CATACOMBS4, 16, 360, { AI_ZHAR, 3, MIS_FIREBALL, 0 }, 16, 40, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_ZHAR, TEXT_ZHAR1, ALIGN }, /*UMT_SNOTSPIL*/ { MT_BFALLSP, "Snotspill", "BNG", 0, 8, 220, { AI_SNOTSPIL, 3, 0, 0 }, 10, 18, 0, 0, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_BANNER10, ALIGN }, -/*UMT_LAZARUS*/ { MT_BMAGE, "Arch-Bishop Lazarus", "GENERAL", 0, 32, 600, { AI_LAZARUS, 3, MIS_FIREBALL, 0 }, 30, 50, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_VILE13, ALIGN }, -/*UMT_RED_VEX*/ { MT_RSUCC, "Red Vex", "REDV", 0, 31, 400, { AI_LAZHELP, 3, MIS_HLSPWN, FALSE }, 30, 50, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_VILE13, ALIGN }, -/*UMT_BLACKJADE*/ { MT_RSUCC, "Black Jade", "BLKJD", 0, 31, 400, { AI_LAZHELP, 3, MIS_HLSPWN, FALSE }, 30, 50, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_VILE13, ALIGN }, +/*UMT_LAZARUS*/ { MT_BMAGE, "Arch-Bishop Lazarus", "GENERAL", 0, 30, 600, { AI_LAZARUS, 3, MIS_FIREBALL, 0 }, 30, 50, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_VILE13, ALIGN }, +/*UMT_RED_VEX*/ { MT_RSUCC, "Red Vex", "REDV", 0, 30, 400, { AI_LAZHELP, 3, MIS_HLSPWN, FALSE }, 30, 50, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_VILE13, ALIGN }, +/*UMT_BLACKJADE*/ { MT_RSUCC, "Black Jade", "BLKJD", 0, 30, 400, { AI_LAZHELP, 3, MIS_HLSPWN, FALSE }, 30, 50, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_VILE13, ALIGN }, /*UMT_LACHDAN*/ { MT_GBLACK, "Lachdanan", "BHKA", DLV_HELL2, 28, 500, { AI_LACHDAN, 3, 0, 0 }, 0, 0, 0, 0, 0 , 0, UMF_NODROP | UMF_LIGHT, 0, 0, 0, 0, 0, Q_VEIL, TEXT_VEIL9, ALIGN }, /*UMT_WARLORD*/ { MT_BBLACK, "Warlord of Blood", "GENERAL", 0, 26, 850, { AI_WARLORD, 3, 0, 0 }, 35, 50, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_WARLRD9, ALIGN }, /*UMT_BUTCHER*/ { MT_CLEAVER, "The Butcher", NULL, 0, 6, 220, { AI_CLEAVER, 3, 0, 0 }, 6, 12, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, /*UMT_DIABLO*/ { MT_DIABLO, "The Dark Lord", NULL, 0, 32, 1666, { AI_ROUNDRANGED, 3, MIS_APOCAC2, 0 }, 30, 60, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , UMF_NODROP , 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, /*UMT_ZAMPHIR*/ { MT_YSNEAK, "Zamphir", "GENERAL", DLV_CAVES2, 20, 420, { AI_SNEAK, 3, 0, 0 }, 20, 30, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, UMF_GROUP, 0, 0, 0, 35, 20, Q_INVALID, TEXT_NONE, ALIGN }, #ifdef HELLFIRE -/*UMT_HORKDMN*/ { MT_HORKDMN, "Hork Demon", NULL, DLV_NEST3, 28, 400, { AI_HORKDMN, 3, 0, 0 }, 20, 35, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, -/*UMT_DEFILER*/ { MT_DEFILER, "The Defiler", NULL, DLV_NEST4, 30, 480, { AI_FAT, 3, 0, 0 }, 30, 40, 24, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, +/*UMT_HORKDMN*/ { MT_HORKDMN, "Hork Demon", NULL, DLV_NEST3, 22, 400, { AI_HORKDMN, 3, 0, 0 }, 20, 35, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, +/*UMT_DEFILER*/ { MT_DEFILER, "The Defiler", NULL, DLV_NEST4, 24, 480, { AI_FAT, 3, 0, 0 }, 30, 40, 24, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, /*UMT_NAKRUL*/ { MT_NAKRUL, "Na-Krul", NULL, 0, 32, 1332, { AI_SKELSD, 3, 0, 0 }, 40, 50, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, #endif { MT_TSKELAX, "Bonehead Keenaxe", "BHKA", DLV_CATHEDRAL2, 4, 91, { AI_SKELSD, 2, 0, 0 }, 4, 10, 0, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , UMF_GANG, 75, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, @@ -499,13 +499,13 @@ const UniqMonData uniqMonData[] = { // { MT_RSUCC, "Webwidow", "GENERAL", DLV_HELL4, 32, 774, { AI_RANGED, 1, MIS_HLSPWN, FALSE }, 20, 50, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, // { MT_BSUCC, "Fleshdancer", "GENERAL", DLV_HELL4, 32, 999, { AI_RANGED, 3, MIS_SOLBRNR, FALSE }, 30, 50, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, #ifdef HELLFIRE - { MT_FELLTWIN, "Bloodmoon the Lost", "GENERAL", DLV_NEST1, 16, 650, { AI_ZOMBIE, 0, 0, 0 }, 24, 40, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, UMF_GROUP, 30, 0, 0, 0, 70, Q_INVALID, TEXT_NONE, ALIGN }, - { MT_HELLBOAR, "Grimspike", "DE", DLV_NEST2, 22, 640, { AI_RHINO, 1, 0, 0 }, 25, 35, 30, 50, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, UMF_GANG, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, - { MT_SPIDLORD, "Webwidow", "ETH", DLV_NEST3, 24, 780, { AI_ROUNDRANGED2, 1, MIS_ACID, 0 }, 30, 45, 0, 0, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, -// { MT_DRHINO, "Grimspike", "GENERAL", DLV_NEST3, 26, 534, { AI_SNEAK, 1, 0, 0 }, 25, 40, 0, 0, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, UMF_GANG, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, - { MT_LASHWORM, "Stingiron", "BSM", DLV_NEST4, 26, 700, { AI_BAT, 3, 0, 0 }, 24, 40, 0, 0, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, UMF_GANG, 0, 0, 0, 70, 0, Q_INVALID, TEXT_NONE, ALIGN }, - { MT_LRDSAYTR, "Blightstone", "GENERAL", DLV_CRYPT1, 28, 760, { AI_SKELSD, 0, 0, 0 }, 28, 46, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, UMF_GANG, 30, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, // minions are fire resistant/immune - { MT_SKLWING, "Bonesaw", "REDV", DLV_CRYPT2, 30, 700, { AI_ROUNDRANGED, 3, MIS_BONEDEMON, 0 }, 24, 40, 0, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE , UMF_GROUP, 0, 0, 70, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, + { MT_FELLTWIN, "Bloodmoon the Lost", "GENERAL", DLV_NEST1, 18, 650, { AI_ZOMBIE, 0, 0, 0 }, 24, 40, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, UMF_GROUP, 30, 0, 0, 0, 70, Q_INVALID, TEXT_NONE, ALIGN }, + { MT_HELLBOAR, "Grimspike", "DE", DLV_NEST2, 20, 640, { AI_RHINO, 1, 0, 0 }, 25, 35, 30, 50, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, UMF_GANG, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, + { MT_SPIDLORD, "Webwidow", "ETH", DLV_NEST3, 22, 780, { AI_ROUNDRANGED2, 1, MIS_ACID, 0 }, 30, 45, 0, 0, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, +// { MT_DRHINO, "Grimspike", "GENERAL", DLV_NEST3, 22, 534, { AI_SNEAK, 1, 0, 0 }, 25, 40, 0, 0, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, UMF_GANG, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, + { MT_LASHWORM, "Stingiron", "BSM", DLV_NEST4, 24, 700, { AI_BAT, 3, 0, 0 }, 24, 40, 0, 0, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, UMF_GANG, 0, 0, 0, 70, 0, Q_INVALID, TEXT_NONE, ALIGN }, + { MT_LRDSAYTR, "Blightstone", "GENERAL", DLV_CRYPT1, 26, 760, { AI_SKELSD, 0, 0, 0 }, 28, 46, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, UMF_GANG, 30, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, // minions are fire resistant/immune + { MT_SKLWING, "Bonesaw", "REDV", DLV_CRYPT2, 28, 700, { AI_ROUNDRANGED, 3, MIS_BONEDEMON, 0 }, 24, 40, 0, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE , UMF_GROUP, 0, 0, 70, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, { MT_BONEDEMN, "Devilskull", "BSDB", DLV_CRYPT3, 30, 900, { AI_SKELSD, 3, 0, 0 }, 20, 50, 0, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE , UMF_GROUP, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, // minions are fire immune even in normal { MT_REAPER, "Soulslash", "BASHTB", DLV_CRYPT4, 32, 1000, { AI_SKELSD, 3, 0, 0 }, 24, 52, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, UMF_GANG, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, #endif From a2ce14ff63ff0b03c80ea322b0bcf4e74ecf0095 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 29 Dec 2023 10:37:00 +0100 Subject: [PATCH 176/596] ensure minions leave no loot (or corpse) --- Source/monstdat.cpp | 2 +- Source/monster.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Source/monstdat.cpp b/Source/monstdat.cpp index 3e2dc05c9f9..790cca59191 100644 --- a/Source/monstdat.cpp +++ b/Source/monstdat.cpp @@ -119,7 +119,7 @@ const MonsterData monsterdata[NUM_MTYPES] = { /* MT_GMAGE */ { MOFILE_MAGE, 27, 7, "Monsters\\Mage\\Cnselg.TRN", "Magistrate", { AI_COUNSLR, 1, MIS_CBOLTC, 0 }, 85, 85, 0 , 100, 10, 24, 0, 0, 0, 65, 0, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 4478, ALIGN }, // MC_DEMON, /* MT_XMAGE */ { MOFILE_MAGE, 29, 7, "Monsters\\Mage\\Cnselgd.TRN", "Cabalist", { AI_COUNSLR, 2, MIS_LIGHTNINGC, 0 }, 120, 120, 0 , 110, 12, 28, 0, 0, 0, 70, 0, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 4929, ALIGN }, // MC_DEMON, /* MT_BMAGE */ { MOFILE_MAGE, 30, 7, "Monsters\\Mage\\Cnselbk.TRN", "Advocate", { AI_COUNSLR, 3, MIS_FIREBALL, 0 }, 145, 145, MFLAG_CAN_OPEN_DOOR, 120, 14, 32, 0, 0, 0, 70, 0, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 4968, ALIGN }, // MC_DEMON, -/* MT_GOLEM */ { MOFILE_GOLEM, 4, 0, NULL, "Golem", { AI_GOLUM, 0, 0, 0 }, 40, 40, MFLAG_NOSTONE | MFLAG_NOCORPSE | MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 30, 3, 5, 0, 0, 0, 0, 0, 50, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 0, ALIGN }, // MC_DEMON, +/* MT_GOLEM */ { MOFILE_GOLEM, 4, 0, NULL, "Golem", { AI_GOLUM, 0, 0, 0 }, 40, 40, MFLAG_NOSTONE | MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 30, 3, 5, 0, 0, 0, 0, 0, 50, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 0, ALIGN }, // MC_DEMON, /* MT_DIABLO */ { MOFILE_DIABLO, 32, 7, NULL, "The Dark Lord", { AI_ROUNDRANGED, 3, MIS_APOCAC2, 0 }, 1666, 1666, MFLAG_NOSTONE | MFLAG_NOCORPSE | MFLAG_KNOCKBACK | MFLAG_SEARCH, 240, 30, 60, 0, 0, 0, 200, 0, 90, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , 8333, ALIGN }, // MC_DEMON, /* MT_DARKMAGE*///{ MOFILE_DARKMAGE, 30, 7, NULL, "The Arch-Litch Malignus", { AI_COUNSLR, 3, MIS_FIREBALL, 0 }, 160, 160, MFLAG_CAN_OPEN_DOOR, 120, 20, 40, 0, 0, 0, 0, 0, 70, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 4968, ALIGN }, // MC_DEMON, #ifdef HELLFIRE diff --git a/Source/monster.cpp b/Source/monster.cpp index 29b6a39f99d..5d2b66ba264 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -2149,12 +2149,12 @@ static void MonstStartKill(int mnum, int mpnum, bool sendmsg) static_assert(MAXMONSTERS <= UCHAR_MAX, "MonstStartKill uses mnum as pnum, which must fit to BYTE."); NetSendCmdMonstKill(mnum, mpnum); } - if (mnum >= MAX_MINIONS) { + //if (mnum >= MAX_MINIONS) { MonUpdateLeader(mnum); SpawnLoot(mnum, sendmsg); - } else { + //} else { AddUnVision(mon->_mvid); - } + //} if (mon->_mType == MT_DIABLO) MonDiabloDeath(mnum, sendmsg); @@ -5015,6 +5015,7 @@ void SpawnGolem(int mnum, int x, int y, int level) mon = &monsters[mnum]; mon->_mhitpoints = mon->_mmaxhp; mon->_mvid = AddVision(x, y, PLR_MIN_VISRAD, false); + mon->_mFlags |= MFLAG_NOCORPSE | MFLAG_NODROP; ActivateSpawn(mnum, x, y, DIR_S); if (mnum == mypnum) NetSendCmdGolem(); From 562ae8288f4e31d6ca9b1f53a9221036c51e0632 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 29 Dec 2023 10:54:35 +0100 Subject: [PATCH 177/596] naming conventions - rename MonstStartKill to MonInitKill - rename MonStartPlrHit to MonHitByPlr - rename MonStartMonHit to MonHitByMon - rename MonStartKill to MonKill - rename MonSyncStartKill to MonSyncKill - rename PlrStartAnyHit to PlrHitByAny --- Source/debug.cpp | 4 ++-- Source/missiles.cpp | 18 +++++++++--------- Source/monster.cpp | 36 ++++++++++++++++++------------------ Source/monster.h | 8 ++++---- Source/msg.cpp | 2 +- Source/player.cpp | 22 +++++++++++----------- Source/player.h | 2 +- 7 files changed, 46 insertions(+), 46 deletions(-) diff --git a/Source/debug.cpp b/Source/debug.cpp index 206419d26cf..4e94fd84531 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -250,8 +250,8 @@ void ValidateData() assert(objectdata[OBJ_TORCHL2].oLvlTypes & lvlMask); // required by SyncPedestal } // monsters - assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_KNOCKBACK)); // required by MonStartMonHit - assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_CAN_BLEED)); // required by MonStartMonHit and MonStartPlrHit + assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_KNOCKBACK)); // required by MonHitByMon + assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_CAN_BLEED)); // required by MonHitByMon and MonHitByPlr assert(monsterdata[MT_GOLEM].mSelFlag == 0); // required by CheckCursMove for (i = 0; i < NUM_MTYPES; i++) { const MonsterData& md = monsterdata[i]; diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 14645a8d2ee..fa30182e5c4 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -779,12 +779,12 @@ static bool MonsterTrapHit(int mnum, int mi) mon->_mhitpoints -= dam; if (mon->_mhitpoints < (1 << 6)) { - MonStartKill(mnum, -1); + MonKill(mnum, -1); } else { /*if (resist != MORT_NONE) { PlayMonSFX(mnum, MS_GOTHIT); } else {*/ - MonStartMonHit(mnum, -1, dam); + MonHitByMon(mnum, -1, dam); //} } if (mon->_msquelch != SQUELCH_MAX) { @@ -911,7 +911,7 @@ static bool MonsterMHit(int mnum, int mi) } if (mon->_mhitpoints < (1 << 6)) { - MonStartKill(mnum, pnum); + MonKill(mnum, pnum); } else { /*if (resist != MORT_NONE) { PlayMonSFX(mnum, MS_GOTHIT); @@ -922,7 +922,7 @@ static bool MonsterMHit(int mnum, int mi) //if (hitFlags & ISPL_NOHEALMON) // mon->_mFlags |= MFLAG_NOHEAL; } - MonStartPlrHit(mnum, pnum, dam, hitFlags, mis->_misx, mis->_misy); + MonHitByPlr(mnum, pnum, dam, hitFlags, mis->_misx, mis->_misy); //} } @@ -1036,7 +1036,7 @@ static bool PlayerTrapHit(int pnum, int mi) hitFlags = 0; if (mis->_miFlags & MIF_ARROW) hitFlags = ISPL_FAKE_CAN_BLEED; - PlrStartAnyHit(pnum, -1, dam, hitFlags, mis->_misx, mis->_misy); + PlrHitByAny(pnum, -1, dam, hitFlags, mis->_misx, mis->_misy); } return true; } @@ -1105,7 +1105,7 @@ static bool PlayerMHit(int pnum, int mi) hitFlags = (mon->_mFlags & ISPL_HITFLAGS_MASK) | ISPL_FAKE_CAN_BLEED; static_assert((int)MFLAG_KNOCKBACK == (int)ISPL_KNOCKBACK, "PlayerMHit uses _mFlags as hitFlags."); } - PlrStartAnyHit(pnum, mis->_miSource, dam, hitFlags, mis->_misx, mis->_misy); + PlrHitByAny(pnum, mis->_miSource, dam, hitFlags, mis->_misx, mis->_misy); } return true; } @@ -1234,7 +1234,7 @@ static bool Plr2PlrMHit(int pnum, int mi) hitFlags = 0; if (mis->_miFlags & MIF_ARROW) hitFlags = (plx(mis->_miSource)._pIFlags & ISPL_HITFLAGS_MASK) | ISPL_FAKE_CAN_BLEED; - PlrStartAnyHit(pnum, mis->_miSource, dam, hitFlags, mis->_misx, mis->_misy); + PlrHitByAny(pnum, mis->_miSource, dam, hitFlags, mis->_misx, mis->_misy); } return true; } @@ -2878,7 +2878,7 @@ int AddGolem(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in missile[mi]._miMinDam = missile[mi]._miMaxDam >> 1; CheckSplashColFull(mi); - MonStartKill(misource, misource); + MonKill(misource, misource); return MIRES_DELETE; } @@ -3311,7 +3311,7 @@ int AddTelekinesis(int mi, int sx, int sy, int dx, int dy, int midir, int micast monsters[target]._msquelch = SQUELCH_MAX; monsters[target]._mlastx = plr._px; monsters[target]._mlasty = plr._py; - MonStartPlrHit(target, pnum, 0, ISPL_KNOCKBACK, plr._px, plr._py); + MonHitByPlr(target, pnum, 0, ISPL_KNOCKBACK, plr._px, plr._py); } break; case MTT_OBJECT: diff --git a/Source/monster.cpp b/Source/monster.cpp index 5d2b66ba264..f0a7c1aecd4 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1941,7 +1941,7 @@ static void MonGetKnockback(int mnum, int sx, int sy) MonStartGetHit(mnum); } -void MonStartPlrHit(int mnum, int pnum, int dam, unsigned hitflags, int sx, int sy) +void MonHitByPlr(int mnum, int pnum, int dam, unsigned hitflags, int sx, int sy) { MonsterStruct* mon; @@ -1974,7 +1974,7 @@ void MonStartPlrHit(int mnum, int pnum, int dam, unsigned hitflags, int sx, int } } -void MonStartMonHit(int defm, int offm, int dam) +void MonHitByMon(int defm, int offm, int dam) { MonsterStruct* dmon; @@ -2126,7 +2126,7 @@ static void SpawnLoot(int mnum, bool sendmsg) SpawnMonItem(mnum, mx, my, sendmsg); } -static void MonstStartKill(int mnum, int mpnum, bool sendmsg) +static void MonInitKill(int mnum, int mpnum, bool sendmsg) { MonsterStruct* mon; @@ -2146,7 +2146,7 @@ static void MonstStartKill(int mnum, int mpnum, bool sendmsg) mon->_mhitpoints = 0; CheckQuestKill(mnum, sendmsg); if (sendmsg) { - static_assert(MAXMONSTERS <= UCHAR_MAX, "MonstStartKill uses mnum as pnum, which must fit to BYTE."); + static_assert(MAXMONSTERS <= UCHAR_MAX, "MonInitKill uses mnum as pnum, which must fit to BYTE."); NetSendCmdMonstKill(mnum, mpnum); } //if (mnum >= MAX_MINIONS) { @@ -2189,21 +2189,21 @@ static void M2MStartKill(int offm, int defm) else sendmsg = true; - MonstStartKill(defm, offm, sendmsg); + MonInitKill(defm, offm, sendmsg); } -void MonStartKill(int mnum, int pnum) +void MonKill(int mnum, int pnum) { if ((unsigned)mnum >= MAXMONSTERS) { - dev_fatal("MonStartKill: Invalid monster %d", mnum); + dev_fatal("MonKill: Invalid monster %d", mnum); } - MonstStartKill(mnum, pnum, pnum == mypnum || pnum == -1); + MonInitKill(mnum, pnum, pnum == mypnum || pnum == -1); } -void MonSyncStartKill(int mnum, int x, int y, int pnum) +void MonSyncKill(int mnum, int x, int y, int pnum) { if ((unsigned)mnum >= MAXMONSTERS) { - dev_fatal("MonSyncStartKill: Invalid monster %d", mnum); + dev_fatal("MonSyncKill: Invalid monster %d", mnum); } if (monsters[mnum]._mmode == MM_DEATH || monsters[mnum]._mmode > MM_INGAME_LAST || (monsters[mnum]._mmode == MM_STONE && monsters[mnum]._mhitpoints == 0)) { @@ -2218,7 +2218,7 @@ void MonSyncStartKill(int mnum, int x, int y, int pnum) monsters[mnum]._moldy = y; } - MonstStartKill(mnum, pnum, false); + MonInitKill(mnum, pnum, false); } /* @@ -2335,7 +2335,7 @@ static void MonHitMon(int offm, int defm, int hper, int mind, int maxd) if (monsters[defm]._mhitpoints < (1 << 6)) { M2MStartKill(offm, defm); } else { - MonStartMonHit(defm, offm, dam); + MonHitByMon(defm, offm, dam); } } } @@ -2376,9 +2376,9 @@ static void MonHitPlr(int mnum, int pnum, int hper, int MinDam, int MaxDam) dam = RandRange(1, 3) << 6; mon->_mhitpoints -= dam; if (mon->_mhitpoints < (1 << 6)) - MonStartKill(mnum, pnum); + MonKill(mnum, pnum); else - MonStartMonHit(mnum, pnum, dam); + MonHitByMon(mnum, pnum, dam); }*/ dam = RandRange(MinDam, MaxDam) << 6; dam += plr._pIGetHit; @@ -2392,7 +2392,7 @@ static void MonHitPlr(int mnum, int pnum, int hper, int MinDam, int MaxDam) if (!PlrDecHp(pnum, dam, DMGTYPE_NPC)) { hitFlags = (mon->_mFlags & ISPL_HITFLAGS_MASK) | ISPL_FAKE_CAN_BLEED; static_assert((int)MFLAG_KNOCKBACK == (int)ISPL_KNOCKBACK, "MonHitPlr uses _mFlags as hitFlags."); - PlrStartAnyHit(pnum, mnum, dam, hitFlags, mon->_mx, mon->_my); + PlrHitByAny(pnum, mnum, dam, hitFlags, mon->_mx, mon->_my); } } @@ -4326,7 +4326,7 @@ void MAI_Lachdanan(int mnum) //if (mon->_mVar8++ >= gnTicksRate * 32) { if (IsMultiGame || !IsSFXPlaying(USFX_LACH3)) { // mon->_mgoal = MGOAL_NORMAL; - MonStartKill(mnum, -1); + MonKill(mnum, -1); } return; } @@ -4668,7 +4668,7 @@ void MissToMonst(int mi) // TODO: prevent bleeding if MonsterAI is AI_RHINO ? MonHitPlr(mnum, pnum, mon->_mHit * 8, mon->_mMinDamage2, mon->_mMaxDamage2); if (mpnum == dPlayer[oldx][oldy] && mon->_mAI.aiType == AI_RHINO) { /* mon->_mType < MT_NSNAKE || mon->_mType > MT_GSNAKE */ - PlrStartAnyHit(pnum, mnum, 0, ISPL_KNOCKBACK, mis->_misx, mis->_misy); + PlrHitByAny(pnum, mnum, 0, ISPL_KNOCKBACK, mis->_misx, mis->_misy); } return; } @@ -4679,7 +4679,7 @@ void MissToMonst(int mi) return; // do not hit team-mate : assert(mnum >= MAX_MINIONS); MonHitMon(mnum, defm, mon->_mHit * 8, mon->_mMinDamage2, mon->_mMaxDamage2); if (mpnum == dMonster[oldx][oldy] && mon->_mAI.aiType == AI_RHINO) { /* mon->_mType < MT_NSNAKE || mon->_mType > MT_GSNAKE */ - // TODO: use MonStartMonHit ? + // TODO: use MonHitByMon ? PlayMonSFX(mnum, MS_GOTHIT); } } diff --git a/Source/monster.h b/Source/monster.h index b1b243e408b..c56aae5b7c8 100644 --- a/Source/monster.h +++ b/Source/monster.h @@ -46,10 +46,10 @@ void AddMonster(int mtidx, int x, int y); void InitSummonedMonster(int mnum, int dir, int mtidx, int x, int y); int SummonMonster(int x, int y, int dir, int mtidx); void RemoveMonFromMap(int mnum); -void MonStartPlrHit(int mnum, int pnum, int dam, unsigned hitflags, int sx, int sy); -void MonStartMonHit(int defm, int offm, int dam); -void MonStartKill(int mnum, int pnum); -void MonSyncStartKill(int mnum, int x, int y, int pnum); +void MonHitByPlr(int mnum, int pnum, int dam, unsigned hitflags, int sx, int sy); +void MonHitByMon(int defm, int offm, int dam); +void MonKill(int mnum, int pnum); +void MonSyncKill(int mnum, int x, int y, int pnum); void MonLeaveLeader(int mnum); void MonUpdateLeader(int mnum); void MonAddDead(int mnum); diff --git a/Source/msg.cpp b/Source/msg.cpp index 74fedb5fa64..2f1fcb6af46 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -2715,7 +2715,7 @@ static unsigned On_MONSTDEATH(TCmd* pCmd, int pnum) BYTE whoHit, mask; if (pnum != mypnum && currLvl._dLevelIdx == cmd->mkParam1.bParam1) - MonSyncStartKill(cmd->mkMnum, cmd->mkParam1.x, cmd->mkParam1.y, cmd->mkPnum); + MonSyncKill(cmd->mkMnum, cmd->mkParam1.x, cmd->mkParam1.y, cmd->mkPnum); whoHit = delta_kill_monster(cmd); diff --git a/Source/player.cpp b/Source/player.cpp index b98e1b30941..97c5f46cbe6 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -872,7 +872,7 @@ void RemoveLvlPlayer(int pnum) RemovePlrFromMap(pnum); static_assert(MAX_MINIONS == MAX_PLRS, "RemoveLvlPlayer requires that owner of a monster has the same id as the monster itself."); if (currLvl._dLevelIdx != DLV_TOWN && monsters[pnum]._mmode <= MM_INGAME_LAST) { - MonStartKill(pnum, pnum); + MonKill(pnum, pnum); } } } @@ -1663,12 +1663,12 @@ static void PlrGetKnockback(int pnum, int dir) } } -void PlrStartAnyHit(int pnum, int mpnum, int dam, unsigned hitflags, int sx, int sy) +void PlrHitByAny(int pnum, int mpnum, int dam, unsigned hitflags, int sx, int sy) { int dir; if ((unsigned)pnum >= MAX_PLRS) { - dev_fatal("PlrStartAnyHit: illegal player %d", pnum); + dev_fatal("PlrHitByAny: illegal player %d", pnum); } // assert(plr._pHitPoints >= (1 << 6) && dam >= 0); @@ -1683,7 +1683,7 @@ void PlrStartAnyHit(int pnum, int mpnum, int dam, unsigned hitflags, int sx, int dir = GetDirection(plr._px, plr._py, sx, sy); PlaySfxLoc(sgSFXSets[SFXS_PLR_69][plr._pClass], plr._px, plr._py, 2); - static_assert(MAX_PLRS <= MAX_MINIONS, "PlrStartAnyHit uses a single int to store player and monster sources."); + static_assert(MAX_PLRS <= MAX_MINIONS, "PlrHitByAny uses a single int to store player and monster sources."); if (!(plr._pIFlags & ISPL_NO_BLEED) && (hitflags & ISPL_FAKE_CAN_BLEED) && ((hitflags & ISPL_BLEED) ? random_(47, 64) == 0 : random_(48, 128) == 0)) AddMissile(0, 0, 0, 0, 0, MIS_BLEED, mpnum < MAX_PLRS ? (mpnum < 0 ? MST_OBJECT : MST_PLAYER) : MST_MONSTER, mpnum, pnum); // TODO: prevent golems from acting like a player? @@ -2029,12 +2029,12 @@ static bool PlrHitMonst(int pnum, int sn, int sl, int mnum) //} if (mon->_mhitpoints < (1 << 6)) { - MonStartKill(mnum, pnum); + MonKill(mnum, pnum); } else { hitFlags = (plr._pIFlags & ISPL_HITFLAGS_MASK) | ISPL_FAKE_CAN_BLEED; //if (hitFlags & ISPL_NOHEALMON) // mon->_mFlags |= MFLAG_NOHEAL; - MonStartPlrHit(mnum, pnum, dam, hitFlags, plr._px, plr._py); + MonHitByPlr(mnum, pnum, dam, hitFlags, plr._px, plr._py); } return true; } @@ -2129,7 +2129,7 @@ static bool PlrHitPlr(int offp, int sn, int sl, int pnum) if (!PlrDecHp(pnum, dam, DMGTYPE_PLAYER)) { hitFlags = (plx(offp)._pIFlags & ISPL_HITFLAGS_MASK) | ISPL_FAKE_CAN_BLEED; - PlrStartAnyHit(pnum, offp, dam, hitFlags, plx(offp)._px, plx(offp)._py); + PlrHitByAny(pnum, offp, dam, hitFlags, plx(offp)._px, plx(offp)._py); } return true; } @@ -2919,7 +2919,7 @@ void MissToPlr(int mi, bool hit) return; } //if (mis->_miSpllvl < 10) - PlrStartAnyHit(pnum, -1, 0, ISPL_FAKE_FORCE_STUN, plr._px + (plr._px - mis->_misx), plr._py + (plr._py - mis->_misy)); + PlrHitByAny(pnum, -1, 0, ISPL_FAKE_FORCE_STUN, plr._px + (plr._px - mis->_misx), plr._py + (plr._py - mis->_misy)); //else // PlaySfxLoc(IS_BHIT, x, y); dist = (int)mis->_miRange - 24; // MISRANGE @@ -2961,12 +2961,12 @@ void MissToPlr(int mi, bool hit) //} if (mon->_mhitpoints < (1 << 6)) { - MonStartKill(mpnum, pnum); + MonKill(mpnum, pnum); } else { hitFlags = (plr._pIFlags & ISPL_HITFLAGS_MASK) | ISPL_STUN; //if (hitFlags & ISPL_NOHEALMON) // mon->_mFlags |= MFLAG_NOHEAL; - MonStartPlrHit(mpnum, pnum, dam, hitFlags, mis->_misx, mis->_misy); + MonHitByPlr(mpnum, pnum, dam, hitFlags, mis->_misx, mis->_misy); } return; } @@ -2999,7 +2999,7 @@ void MissToPlr(int mi, bool hit) // dam <<= 1; if (!PlrDecHp(mpnum, dam, DMGTYPE_PLAYER)) { hitFlags = (plr._pIFlags & ISPL_HITFLAGS_MASK) | ISPL_FAKE_FORCE_STUN; - PlrStartAnyHit(mpnum, pnum, dam, hitFlags, mis->_misx, mis->_misy); + PlrHitByAny(mpnum, pnum, dam, hitFlags, mis->_misx, mis->_misy); } return; } diff --git a/Source/player.h b/Source/player.h index 7b00d30a377..f765c67f8ec 100644 --- a/Source/player.h +++ b/Source/player.h @@ -39,7 +39,7 @@ void FixPlayerLocation(int pnum); void PlrStartStand(int pnum); void PlrStartBlock(int pnum, int sx, int sy); void RemovePlrFromMap(int pnum); -void PlrStartAnyHit(int pnum, int mpnum, int dam, unsigned hitflags, int sx, int sy); +void PlrHitByAny(int pnum, int mpnum, int dam, unsigned hitflags, int sx, int sy); void SyncPlrKill(int pnum, int dmgtype); void SyncPlrResurrect(int pnum); void StartNewLvl(int pnum, int fom, int lvl); From c79b7bebed4bc22053d6b59905d2b4ee5983c418 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 29 Dec 2023 11:21:39 +0100 Subject: [PATCH 178/596] ensure a missile of a disconnected player does not cause de-sync --- Source/monster.cpp | 35 +++++++++++++---------------------- Source/monster.h | 2 +- 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index f0a7c1aecd4..187070ac0f5 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -2170,34 +2170,25 @@ static void MonInitKill(int mnum, int mpnum, bool sendmsg) AddMissile(mon->_mx, mon->_my, 0, 0, 0, MIS_ACIDPUD, MST_MONSTER, mnum, 1); } -static void M2MStartKill(int offm, int defm) +void MonKill(int mnum, int mpnum) { bool sendmsg; - static_assert(MAX_MINIONS == MAX_PLRS, "M2MStartKill requires that owner of a monster has the same id as the monster itself."); - // check if it is a golem vs. monster/golem -> the attacker's owner should send the message - if (offm == mypnum) - sendmsg = true; - else if (offm < MAX_MINIONS) - sendmsg = false; - // check if it is a monster vs. golem -> the golem's owner should send the message - else if (defm == mypnum) - sendmsg = true; - else if (defm < MAX_MINIONS) - sendmsg = false; + if ((unsigned)mnum >= MAXMONSTERS) { + dev_fatal("MonKill: Invalid monster %d", mnum); + } + static_assert(MAX_MINIONS == MAX_PLRS, "MonKill requires that owner of a monster has the same id as the monster itself."); + // check if it is a plr/golem vs. monster/golem -> the attacker's owner should send the message + if ((unsigned)mpnum < MAX_PLRS) + sendmsg = mpnum == mypnum || !plx(mpnum)._pActive; // assert(MAX_MINIONS == MAX_PLRS) + // check if it is a monster/trap vs. golem -> the golem's owner should send the message + else if (mnum < MAX_MINIONS) + sendmsg = mnum == mypnum; // assert(MAX_MINIONS == MAX_PLRS && plx(mnum)._pActive) // monster vs. monster -> the host should send the message (should not happen at the moment) else sendmsg = true; - MonInitKill(defm, offm, sendmsg); -} - -void MonKill(int mnum, int pnum) -{ - if ((unsigned)mnum >= MAXMONSTERS) { - dev_fatal("MonKill: Invalid monster %d", mnum); - } - MonInitKill(mnum, pnum, pnum == mypnum || pnum == -1); + MonInitKill(mnum, mpnum, sendmsg); } void MonSyncKill(int mnum, int x, int y, int pnum) @@ -2333,7 +2324,7 @@ static void MonHitMon(int offm, int defm, int hper, int mind, int maxd) int dam = RandRange(mind, maxd) << 6; monsters[defm]._mhitpoints -= dam; if (monsters[defm]._mhitpoints < (1 << 6)) { - M2MStartKill(offm, defm); + MonKill(offm, defm); } else { MonHitByMon(defm, offm, dam); } diff --git a/Source/monster.h b/Source/monster.h index c56aae5b7c8..46b0cd7f650 100644 --- a/Source/monster.h +++ b/Source/monster.h @@ -48,7 +48,7 @@ int SummonMonster(int x, int y, int dir, int mtidx); void RemoveMonFromMap(int mnum); void MonHitByPlr(int mnum, int pnum, int dam, unsigned hitflags, int sx, int sy); void MonHitByMon(int defm, int offm, int dam); -void MonKill(int mnum, int pnum); +void MonKill(int mnum, int mpnum); void MonSyncKill(int mnum, int x, int y, int pnum); void MonLeaveLeader(int mnum); void MonUpdateLeader(int mnum); From f4d14958b7c4aa625e679c9922276fc063dafb13 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 29 Dec 2023 12:00:15 +0100 Subject: [PATCH 179/596] cosmetic --- Source/missiles.cpp | 48 ++++++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index fa30182e5c4..f266ff50acc 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -819,15 +819,13 @@ static bool MonsterMHit(int mnum, int mi) hper = plr._pIHitChance; hper -= mon->_mArmorClass; hper -= (mis->_miVar7 * mis->_miVar7 >> 1); // MISDIST + } else if (mis->_miFlags & MIF_AREA) { + hper = 40 + 2 * plr._pLevel; + hper -= 2 * mon->_mLevel; } else { - if (mis->_miFlags & MIF_AREA) { - hper = 40 + (plr._pLevel << 1); - hper -= (mon->_mLevel << 1); - } else { - hper = 50 + plr._pMagic; - hper -= (mon->_mLevel << 1) + mon->_mEvasion; - // hper -= dist; // TODO: either don't care about it, or set it! - } + hper = 50 + plr._pMagic; + hper -= 2 * mon->_mLevel + mon->_mEvasion; + // hper -= dist; // TODO: either don't care about it, or set it! } if (!CheckHit(hper) && mon->_mmode != MM_STONE) return false; @@ -1003,8 +1001,8 @@ static bool PlayerTrapHit(int pnum, int mi) hper -= plr._pIAC; hper -= mis->_miVar7 << 1; // MISDIST } else { - hper = 40 + (2 * currLvl._dLevel); - hper -= (2 * plr._pLevel); + hper = 40 + 2 * currLvl._dLevel; + hper -= 2 * plr._pLevel; } if (!CheckHit(hper)) @@ -1064,15 +1062,13 @@ static bool PlayerMHit(int pnum, int mi) hper = mis->_miVar6; // MISHIT hper -= plr._pIAC; hper -= mis->_miVar7 << 1; // MISDIST + } else if (mis->_miFlags & MIF_AREA) { + hper = 40 + 2 * mon->_mLevel; + hper -= 2 * plr._pLevel; } else { - if (mis->_miFlags & MIF_AREA) { - hper = 40 + (2 * mon->_mLevel); - hper -= (2 * plr._pLevel); - } else { - hper = 50 + mon->_mMagic; - hper -= plr._pIEvasion; - // hper -= dist; // TODO: either don't care about it, or set it! - } + hper = 50 + mon->_mMagic; + hper -= plr._pIEvasion; + // hper -= dist; // TODO: either don't care about it, or set it! } if (!CheckHit(hper)) @@ -1132,15 +1128,13 @@ static bool Plr2PlrMHit(int pnum, int mi) hper = plx(offp)._pIHitChance; hper -= plr._pIAC; hper -= (mis->_miVar7 * mis->_miVar7 >> 1); // MISDIST + } else if (mis->_miFlags & MIF_AREA) { + hper = 40 + 2 * plx(offp)._pLevel; + hper -= 2 * plr._pLevel; } else { - if (mis->_miFlags & MIF_AREA) { - hper = 40 + (2 * plx(offp)._pLevel); - hper -= (2 * plr._pLevel); - } else { - hper = 50 + plx(offp)._pMagic; - hper -= plr._pIEvasion; - // hper -= dist; // TODO: either don't care about it, or set it! - } + hper = 50 + plx(offp)._pMagic; + hper -= plr._pIEvasion; + // hper -= dist; // TODO: either don't care about it, or set it! } if (!CheckHit(hper)) return false; @@ -1149,7 +1143,7 @@ static bool Plr2PlrMHit(int pnum, int mi) tmp = plr._pIBlockChance; if (tmp != 0 && (plr._pmode == PM_STAND || plr._pmode == PM_BLOCK)) { // assert(plr._pSkillFlags & SFLAG_BLOCK); - tmp = tmp - (plx(offp)._pLevel << 1); + tmp = tmp - 2 * plx(offp)._pLevel; if (tmp > random_(73, 100)) { PlrStartBlock(pnum, mis->_misx, mis->_misy); return true; From 39a683444cfc00a439ebd2592844c9334d626c25 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 29 Dec 2023 12:10:43 +0100 Subject: [PATCH 180/596] bugfix for vanilla (golem vs missiles) - do not ignore the monster(golem) level when it is hit by a missile --- Source/missiles.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index f266ff50acc..886f7a6721b 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -747,7 +747,7 @@ static bool MonsterTrapHit(int mnum, int mi) { MissileStruct* mis; MonsterStruct* mon; - int hper, dam; + int misource, hper, dam; bool ret; mon = &monsters[mnum]; @@ -759,12 +759,15 @@ static bool MonsterTrapHit(int mnum, int mi) } // SetRndSeed(mis->_miRndSeed); // mis->_miRndSeed = NextRndSeed(); + misource = mis->_miSource; + // assert(misource == -1 || (unsigned)misource < MAXMONSTERS); if (mis->_miFlags & MIF_ARROW) { hper = mis->_miVar6; // MISHIT hper -= mon->_mArmorClass; hper -= mis->_miVar7 << 1; // MISDIST } else { - hper = 40; + hper = 40 + (misource < 0 ? 2 * currLvl._dLevel : 2 * monsters[misource]._mLevel); + hper -= 2 * mon->_mLevel; } if (!CheckHit(hper) && mon->_mmode != MM_STONE) return false; From 4e3071527f81c16681f482bce63d07547294a927 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 29 Dec 2023 12:14:08 +0100 Subject: [PATCH 181/596] complete the hit calculations of the missiles - handle area missiles from traps and monsters - pass misource to MonKill/MonHitByMon --- Source/missiles.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 886f7a6721b..f54fb8ffda3 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -765,9 +765,13 @@ static bool MonsterTrapHit(int mnum, int mi) hper = mis->_miVar6; // MISHIT hper -= mon->_mArmorClass; hper -= mis->_miVar7 << 1; // MISDIST - } else { + } else if (mis->_miFlags & MIF_AREA) { hper = 40 + (misource < 0 ? 2 * currLvl._dLevel : 2 * monsters[misource]._mLevel); hper -= 2 * mon->_mLevel; + } else { + hper = 50 + (misource < 0 ? 2 * currLvl._dLevel : monsters[misource]._mMagic); + hper -= 2 * mon->_mLevel + mon->_mEvasion; + // hper -= dist; // TODO: either don't care about it, or set it! } if (!CheckHit(hper) && mon->_mmode != MM_STONE) return false; @@ -782,12 +786,12 @@ static bool MonsterTrapHit(int mnum, int mi) mon->_mhitpoints -= dam; if (mon->_mhitpoints < (1 << 6)) { - MonKill(mnum, -1); + MonKill(mnum, misource); } else { /*if (resist != MORT_NONE) { PlayMonSFX(mnum, MS_GOTHIT); } else {*/ - MonHitByMon(mnum, -1, dam); + MonHitByMon(mnum, misource, dam); //} } if (mon->_msquelch != SQUELCH_MAX) { @@ -1003,9 +1007,13 @@ static bool PlayerTrapHit(int pnum, int mi) hper = mis->_miVar6; // MISHIT hper -= plr._pIAC; hper -= mis->_miVar7 << 1; // MISDIST - } else { + } else if (mis->_miFlags & MIF_AREA) { hper = 40 + 2 * currLvl._dLevel; hper -= 2 * plr._pLevel; + } else { + hper = 50 + 2 * currLvl._dLevel; + hper -= plr._pIEvasion; + // hper -= dist; // TODO: either don't care about it, or set it! } if (!CheckHit(hper)) From da3acf71b1a7c51f084d3740417d6622badd05b3 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 29 Dec 2023 12:42:30 +0100 Subject: [PATCH 182/596] prevent monster vs monster hits in MonsterTrapHit --- Source/missiles.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index f54fb8ffda3..d25d9e06365 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -761,6 +761,9 @@ static bool MonsterTrapHit(int mnum, int mi) // mis->_miRndSeed = NextRndSeed(); misource = mis->_miSource; // assert(misource == -1 || (unsigned)misource < MAXMONSTERS); + if (mnum >= MAX_MINIONS && misource >= MAX_MINIONS) { + return false; + } if (mis->_miFlags & MIF_ARROW) { hper = mis->_miVar6; // MISHIT hper -= mon->_mArmorClass; @@ -1252,11 +1255,8 @@ static bool MonMissHit(int mnum, int mi) if (mis->_miCaster & MST_PLAYER) { // player vs. monster return MonsterMHit(mnum, mi); - } else if (mis->_miCaster == MST_MONSTER) { - // monster vs. golem - return mnum < MAX_MINIONS && MonsterTrapHit(mnum, mi); } else { - // trap vs. monster + // trap/monster vs. monster return MonsterTrapHit(mnum, mi); } } From 2eb42fa2c1614e254e81e3bd6837a6b61fcf3e4d Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 29 Dec 2023 12:46:57 +0100 Subject: [PATCH 183/596] handle missile hits from traps against players in PlayerMHit --- Source/missiles.cpp | 87 ++++++--------------------------------------- 1 file changed, 10 insertions(+), 77 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index d25d9e06365..4f5568d12d4 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -989,75 +989,10 @@ unsigned CalcPlrDam(int pnum, BYTE mRes, unsigned mindam, unsigned maxdam) return dam; } -static bool PlayerTrapHit(int pnum, int mi) -{ - MissileStruct* mis; - int hper, tmp, dam; - unsigned hitFlags; - - mis = &missile[mi]; - if (!(mis->_miFlags & MIF_DOT)) { - if (mis->_miVar8 == -(pnum + 1)) - return false; - mis->_miVar8 = -(pnum + 1); - } - if (plr._pInvincible) { - return false; - } - // SetRndSeed(mis->_miRndSeed); - // mis->_miRndSeed = NextRndSeed(); - if (mis->_miFlags & MIF_ARROW) { - hper = mis->_miVar6; // MISHIT - hper -= plr._pIAC; - hper -= mis->_miVar7 << 1; // MISDIST - } else if (mis->_miFlags & MIF_AREA) { - hper = 40 + 2 * currLvl._dLevel; - hper -= 2 * plr._pLevel; - } else { - hper = 50 + 2 * currLvl._dLevel; - hper -= plr._pIEvasion; - // hper -= dist; // TODO: either don't care about it, or set it! - } - - if (!CheckHit(hper)) - return false; - - if (!(mis->_miFlags & MIF_NOBLOCK)) { - tmp = plr._pIBlockChance; - if (tmp != 0 && (plr._pmode == PM_STAND || plr._pmode == PM_BLOCK)) { - // assert(plr._pSkillFlags & SFLAG_BLOCK); - tmp = tmp - (currLvl._dLevel << 1); - if (tmp > random_(73, 100)) { - PlrStartBlock(pnum, mis->_misx, mis->_misy); - return true; - } - } - } - - dam = CalcPlrDam(pnum, mis->_miResist, mis->_miMinDam, mis->_miMaxDam); - if (dam == 0) - return false; - - if (!(mis->_miFlags & MIF_DOT)) { - dam += plr._pIGetHit; - if (dam < 64) - dam = 64; - } - - if (!PlrDecHp(pnum, dam, DMGTYPE_NPC)) { - hitFlags = 0; - if (mis->_miFlags & MIF_ARROW) - hitFlags = ISPL_FAKE_CAN_BLEED; - PlrHitByAny(pnum, -1, dam, hitFlags, mis->_misx, mis->_misy); - } - return true; -} - static bool PlayerMHit(int pnum, int mi) { MissileStruct* mis; - MonsterStruct* mon; - int hper, tmp, dam; + int misource, hper, tmp, dam; unsigned hitFlags; if (plr._pInvincible) { @@ -1071,16 +1006,17 @@ static bool PlayerMHit(int pnum, int mi) } // SetRndSeed(mis->_miRndSeed); // mis->_miRndSeed = NextRndSeed(); - mon = &monsters[mis->_miSource]; + misource = mis->_miSource; + // assert(misource == -1 || (unsigned)misource < MAXMONSTERS); if (mis->_miFlags & MIF_ARROW) { hper = mis->_miVar6; // MISHIT hper -= plr._pIAC; hper -= mis->_miVar7 << 1; // MISDIST } else if (mis->_miFlags & MIF_AREA) { - hper = 40 + 2 * mon->_mLevel; + hper = 40 + (misource >= 0 ? 2 * monsters[misource]._mLevel : 2 * currLvl._dLevel); hper -= 2 * plr._pLevel; } else { - hper = 50 + mon->_mMagic; + hper = 50 + (misource >= 0 ? monsters[misource]._mMagic : 2 * currLvl._dLevel); hper -= plr._pIEvasion; // hper -= dist; // TODO: either don't care about it, or set it! } @@ -1092,7 +1028,7 @@ static bool PlayerMHit(int pnum, int mi) tmp = plr._pIBlockChance; if (tmp != 0 && (plr._pmode == PM_STAND || plr._pmode == PM_BLOCK)) { // assert(plr._pSkillFlags & SFLAG_BLOCK); - tmp = tmp - (mon->_mLevel << 1); + tmp = tmp - (misource >= 0 ? 2 * monsters[misource]._mLevel : 2 * currLvl._dLevel); if (tmp > random_(73, 100)) { PlrStartBlock(pnum, mis->_misx, mis->_misy); return true; @@ -1112,10 +1048,10 @@ static bool PlayerMHit(int pnum, int mi) if (!PlrDecHp(pnum, dam, DMGTYPE_NPC)) { hitFlags = 0; if (mis->_miFlags & MIF_ARROW) { - hitFlags = (mon->_mFlags & ISPL_HITFLAGS_MASK) | ISPL_FAKE_CAN_BLEED; + hitFlags = (misource >= 0 ? monsters[misource]._mFlags & ISPL_HITFLAGS_MASK : 0) | ISPL_FAKE_CAN_BLEED; static_assert((int)MFLAG_KNOCKBACK == (int)ISPL_KNOCKBACK, "PlayerMHit uses _mFlags as hitFlags."); } - PlrHitByAny(pnum, mis->_miSource, dam, hitFlags, mis->_misx, mis->_misy); + PlrHitByAny(pnum, misource, dam, hitFlags, mis->_misx, mis->_misy); } return true; } @@ -1269,12 +1205,9 @@ static bool PlrMissHit(int pnum, int mi) if (mis->_miCaster & MST_PLAYER) { // player vs. player return Plr2PlrMHit(pnum, mi); - } else if (mis->_miCaster == MST_MONSTER) { - // monster vs. player - return PlayerMHit(pnum, mi); } else { - // trap vs. player - return PlayerTrapHit(pnum, mi); + // monster/trap vs. player + return PlayerMHit(pnum, mi); } } From f09d6b389dbefee220ddc5d86ba623e4f4bea32c Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 29 Dec 2023 12:57:25 +0100 Subject: [PATCH 184/596] naming conventions - rename MonsterMHit to MissMonHitByPlr - rename MonsterTrapHit to MissMonHitByMon - rename Plr2PlrMHit to MissPlrHitByPlr - rename PlayerMHit to MissPlrHitByMon --- Source/missiles.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 4f5568d12d4..0435c6a25b7 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -743,7 +743,7 @@ int AddElementalExplosion(int dx, int dy, int fdam, int ldam, int mdam, int adam return dam; } -static bool MonsterTrapHit(int mnum, int mi) +static bool MissMonHitByMon(int mnum, int mi) { MissileStruct* mis; MonsterStruct* mon; @@ -806,7 +806,7 @@ static bool MonsterTrapHit(int mnum, int mi) return true; } -static bool MonsterMHit(int mnum, int mi) +static bool MissMonHitByPlr(int mnum, int mi) { MonsterStruct* mon; MissileStruct* mis; @@ -989,7 +989,7 @@ unsigned CalcPlrDam(int pnum, BYTE mRes, unsigned mindam, unsigned maxdam) return dam; } -static bool PlayerMHit(int pnum, int mi) +static bool MissPlrHitByMon(int pnum, int mi) { MissileStruct* mis; int misource, hper, tmp, dam; @@ -1049,14 +1049,14 @@ static bool PlayerMHit(int pnum, int mi) hitFlags = 0; if (mis->_miFlags & MIF_ARROW) { hitFlags = (misource >= 0 ? monsters[misource]._mFlags & ISPL_HITFLAGS_MASK : 0) | ISPL_FAKE_CAN_BLEED; - static_assert((int)MFLAG_KNOCKBACK == (int)ISPL_KNOCKBACK, "PlayerMHit uses _mFlags as hitFlags."); + static_assert((int)MFLAG_KNOCKBACK == (int)ISPL_KNOCKBACK, "MissPlrHitByMon uses _mFlags as hitFlags."); } PlrHitByAny(pnum, misource, dam, hitFlags, mis->_misx, mis->_misy); } return true; } -static bool Plr2PlrMHit(int pnum, int mi) +static bool MissPlrHitByPlr(int pnum, int mi) { MissileStruct* mis; int offp, dam, tmp, hper; @@ -1190,10 +1190,10 @@ static bool MonMissHit(int mnum, int mi) mis = &missile[mi]; if (mis->_miCaster & MST_PLAYER) { // player vs. monster - return MonsterMHit(mnum, mi); + return MissMonHitByPlr(mnum, mi); } else { // trap/monster vs. monster - return MonsterTrapHit(mnum, mi); + return MissMonHitByMon(mnum, mi); } } @@ -1204,10 +1204,10 @@ static bool PlrMissHit(int pnum, int mi) mis = &missile[mi]; if (mis->_miCaster & MST_PLAYER) { // player vs. player - return Plr2PlrMHit(pnum, mi); + return MissPlrHitByPlr(pnum, mi); } else { // monster/trap vs. player - return PlayerMHit(pnum, mi); + return MissPlrHitByMon(pnum, mi); } } From c3b4a1a88fc643d968db19d2f5128047dc3ada3c Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 29 Dec 2023 12:58:21 +0100 Subject: [PATCH 185/596] cosmetic --- Source/missiles.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 0435c6a25b7..52cd6fd02db 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -769,10 +769,10 @@ static bool MissMonHitByMon(int mnum, int mi) hper -= mon->_mArmorClass; hper -= mis->_miVar7 << 1; // MISDIST } else if (mis->_miFlags & MIF_AREA) { - hper = 40 + (misource < 0 ? 2 * currLvl._dLevel : 2 * monsters[misource]._mLevel); + hper = 40 + (misource >= 0 ? 2 * monsters[misource]._mLevel : 2 * currLvl._dLevel); hper -= 2 * mon->_mLevel; } else { - hper = 50 + (misource < 0 ? 2 * currLvl._dLevel : monsters[misource]._mMagic); + hper = 50 + (misource >= 0 ? monsters[misource]._mMagic : 2 * currLvl._dLevel); hper -= 2 * mon->_mLevel + mon->_mEvasion; // hper -= dist; // TODO: either don't care about it, or set it! } @@ -1020,7 +1020,6 @@ static bool MissPlrHitByMon(int pnum, int mi) hper -= plr._pIEvasion; // hper -= dist; // TODO: either don't care about it, or set it! } - if (!CheckHit(hper)) return false; @@ -1192,7 +1191,7 @@ static bool MonMissHit(int mnum, int mi) // player vs. monster return MissMonHitByPlr(mnum, mi); } else { - // trap/monster vs. monster + // monster/trap vs. monster return MissMonHitByMon(mnum, mi); } } From 4d99503a3b7e5d8368439d1121c4b025c9eb5d90 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 29 Dec 2023 13:01:56 +0100 Subject: [PATCH 186/596] send quest-cmd of Q_DIABLO in CheckQuestKill --- Source/monster.cpp | 8 ++------ Source/quests.cpp | 4 ++++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 187070ac0f5..7023f577303 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -2006,16 +2006,12 @@ void MonHitByMon(int defm, int offm, int dam) } } -static void MonDiabloDeath(int mnum, bool sendmsg) +static void MonDiabloDeath(int mnum) { MonsterStruct* mon; int i, mx, my; unsigned killLevel; - quests[Q_DIABLO]._qactive = QUEST_DONE; - if (sendmsg) { - NetSendCmdQuest(Q_DIABLO, false); // recipient should not matter - } for (i = 0; i < MAXMONSTERS; i++) { // commented out because this is a pointless complexity //if (i == mnum) @@ -2157,7 +2153,7 @@ static void MonInitKill(int mnum, int mpnum, bool sendmsg) //} if (mon->_mType == MT_DIABLO) - MonDiabloDeath(mnum, sendmsg); + MonDiabloDeath(mnum); else PlayMonSFX(mnum, MS_DEATH); diff --git a/Source/quests.cpp b/Source/quests.cpp index 73b89713891..1c9cb3e91c3 100644 --- a/Source/quests.cpp +++ b/Source/quests.cpp @@ -192,6 +192,10 @@ void CheckQuestKill(int mnum, bool sendmsg) gnSfxNum = TEXT_QM_BUTCHER; qn = Q_BUTCHER; break; + case UMT_DIABLO: + quests[Q_DIABLO]._qactive = QUEST_DONE; + qn = Q_DIABLO; + break; #ifdef HELLFIRE case UMT_NAKRUL: quests[Q_NAKRUL]._qactive = QUEST_DONE; From 0ba75498000314940bd5c02af997c1c030ba8f77 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 29 Dec 2023 14:54:02 +0100 Subject: [PATCH 187/596] ensure a missile of a disconnected player does not cause de-sync II. --- Source/monster.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 7023f577303..903b3e2be52 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -2320,7 +2320,7 @@ static void MonHitMon(int offm, int defm, int hper, int mind, int maxd) int dam = RandRange(mind, maxd) << 6; monsters[defm]._mhitpoints -= dam; if (monsters[defm]._mhitpoints < (1 << 6)) { - MonKill(offm, defm); + MonKill(defm, offm); } else { MonHitByMon(defm, offm, dam); } From 33d97c87a1f8a2c90c2311a5439ceed59fa86780 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 29 Dec 2023 14:55:29 +0100 Subject: [PATCH 188/596] cosmetic --- Source/monster.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 903b3e2be52..47705152f27 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -700,8 +700,6 @@ void InitMonster(int mnum, int dir, int mtidx, int x, int y) */ static bool MonstPlace(int xp, int yp) { - static_assert(DBORDERX >= MON_PACK_DISTANCE, "MonstPlace does not check IN_DUNGEON_AREA but expects a large enough border I."); - static_assert(DBORDERY >= MON_PACK_DISTANCE, "MonstPlace does not check IN_DUNGEON_AREA but expects a large enough border II."); return (dMonster[xp][yp]/* | dPlayer[xp][yp] | dObject[xp][yp]*/ | nSolidTable[dPiece[xp][yp]] | (dFlags[xp][yp] & (BFLAG_ALERT | BFLAG_MON_PROTECT))) == 0; } @@ -788,6 +786,7 @@ static void PlaceGroup(int mtidx, int num, int leaderf, int leader) while (placed != 0) { nummonsters--; placed--; + // monsters[nummonsters]._mmode = MM_UNUSED; -- unnecessary assuming these are going to be overwritten... dMonster[monsters[nummonsters]._mx][monsters[nummonsters]._my] = 0; } @@ -975,6 +974,8 @@ static bool PlaceUniqueMonst(int uniqindex, int mtidx) xp = random_(91, DSIZEX) + DBORDERX; yp = random_(91, DSIZEY) + DBORDERY; count2 = 0; + static_assert(DBORDERX >= MON_PACK_DISTANCE, "PlaceUniqueMonst does not check IN_DUNGEON_AREA but expects a large enough border I."); + static_assert(DBORDERY >= MON_PACK_DISTANCE, "PlaceUniqueMonst does not check IN_DUNGEON_AREA but expects a large enough border II."); for (x = xp - MON_PACK_DISTANCE; x <= xp + MON_PACK_DISTANCE; x++) { for (y = yp - MON_PACK_DISTANCE; y <= yp + MON_PACK_DISTANCE; y++) { if (MonstPlace(x, y)) { @@ -1643,7 +1644,7 @@ static void MonStartWalk2(int mnum, int xvel, int yvel, int xoff, int yoff, int mon->_mx = mon->_mfutx = mx; mon->_my = mon->_mfuty = my; dMonster[mx][my] = mnum + 1; - // assert(monsters[mnum]._mlid == NO_LIGHT); + // assert(mon->_mlid == NO_LIGHT); //if (mon->_mlid != NO_LIGHT && !(mon->_mFlags & MFLAG_HIDDEN)) { // ChangeLightXY(mon->_mlid, mx, my); // ChangeLightScreenOff(mon->_mlid, mon->_mxoff, mon->_myoff); @@ -1839,7 +1840,6 @@ static void MonStopWalk(int mnum) RemoveMonFromMap(mnum); MonPlace(mnum); MonStartStand(mnum); - return; } static void MonStartGetHit(int mnum) @@ -2145,12 +2145,12 @@ static void MonInitKill(int mnum, int mpnum, bool sendmsg) static_assert(MAXMONSTERS <= UCHAR_MAX, "MonInitKill uses mnum as pnum, which must fit to BYTE."); NetSendCmdMonstKill(mnum, mpnum); } - //if (mnum >= MAX_MINIONS) { + // if (mnum >= MAX_MINIONS) { MonUpdateLeader(mnum); SpawnLoot(mnum, sendmsg); //} else { AddUnVision(mon->_mvid); - //} + // } if (mon->_mType == MT_DIABLO) MonDiabloDeath(mnum); @@ -2558,6 +2558,7 @@ static bool MonDoHeal(int mnum) mon->_mFlags |= MFLAG_LOCK_ANIMATION; } else { mon->_mhitpoints = mon->_mmaxhp; + // MonStartSpAttack(mnum); mon->_mFlags &= ~MFLAG_LOCK_ANIMATION; mon->_mmode = MM_SPATTACK; } From e440bb1f86618372094ba8c43b6b98c649521270 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 29 Dec 2023 15:20:31 +0100 Subject: [PATCH 189/596] simplify the placement of unique monsters - check uniquetrans in PlaceUniques - return mUnqFlags from InitUniqueMonster - call PlaceGroup from PlaceUniqueMonst - move static assert to its correct position --- Source/monster.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 47705152f27..83cbfe5972b 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -851,7 +851,7 @@ static void PlaceGroup(int mtidx, int num, int leaderf, int leader) } } -static void InitUniqueMonster(int mnum, int uniqindex) +static unsigned InitUniqueMonster(int mnum, int uniqindex) { char filestr[DATA_ARCHIVE_MAX_PATH]; const UniqMonData* uniqm; @@ -884,6 +884,7 @@ static void InitUniqueMonster(int mnum, int uniqindex) if (uniqm->mTrnName != NULL) { snprintf(filestr, sizeof(filestr), "Monsters\\Monsters\\%s.TRN", uniqm->mTrnName); LoadFileWithMem(filestr, ColorTrns[uniquetrans]); + static_assert(NUM_COLOR_TRNS <= UCHAR_MAX, "Color transform index stored in BYTE field."); mon->_muniqtrans = uniquetrans++; } @@ -943,28 +944,26 @@ static void InitUniqueMonster(int mnum, int uniqindex) mon->_mhitpoints = mon->_mmaxhp; - if (uniqm->mUnqFlags & UMF_NODROP) + unsigned flags = uniqm->mUnqFlags; + if (flags & UMF_NODROP) mon->_mFlags |= MFLAG_NODROP; static_assert(MAX_LIGHT_RAD >= MON_LIGHTRAD, "Light-radius of unique monsters are too high."); - if (uniqm->mUnqFlags & UMF_LIGHT) { + if (flags & UMF_LIGHT) { mon->_mlid = AddLight(mon->_mx, mon->_my, MON_LIGHTRAD); } + return flags; } -static bool PlaceUniqueMonst(int uniqindex, int mtidx) +static void PlaceUniqueMonst(int uniqindex, int mtidx) { int xp, yp, x, y; int count2; int mnum, count; - static_assert(NUM_COLOR_TRNS <= UCHAR_MAX, "Color transform index stored in BYTE field."); - if (uniquetrans >= NUM_COLOR_TRNS) { - return false; - } switch (uniqindex) { case UMT_ZHAR: if (zharlib == -1) - return false; + return; xp = themes[zharlib]._tsx1 + 4; yp = themes[zharlib]._tsy1 + 4; break; @@ -998,8 +997,10 @@ static bool PlaceUniqueMonst(int uniqindex, int mtidx) } // assert(nummonsters < MAXMONSTERS); mnum = PlaceMonster(mtidx, xp, yp); - InitUniqueMonster(mnum, uniqindex); - return true; + unsigned flags = InitUniqueMonster(mnum, uniqindex); + if (flags & UMF_GROUP) { + PlaceGroup(mtidx, MON_PACK_SIZE - 1, flags, mnum); + } } static void PlaceUniques() @@ -1007,6 +1008,8 @@ static void PlaceUniques() int u, mt; for (u = 0; uniqMonData[u].mtype != MT_INVALID; u++) { + if (uniquetrans >= NUM_COLOR_TRNS) + continue; if (uniqMonData[u].muLevelIdx != currLvl._dLevelIdx) continue; if (uniqMonData[u].mQuestId != Q_INVALID @@ -1014,10 +1017,7 @@ static void PlaceUniques() continue; for (mt = 0; mt < nummtypes; mt++) { if (mapMonTypes[mt].cmType == uniqMonData[u].mtype) { - if (PlaceUniqueMonst(u, mt) && uniqMonData[u].mUnqFlags & UMF_GROUP) { - // assert(mnum == nummonsters - 1); - PlaceGroup(mt, MON_PACK_SIZE - 1, uniqMonData[u].mUnqFlags, nummonsters - 1); - } + PlaceUniqueMonst(u, mt); break; } } From ea04ec43454a29e9b0ddcc59d8e813d6181e5af8 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 29 Dec 2023 17:51:10 +0100 Subject: [PATCH 190/596] prevent duplicate items on the floor (e.g. after duplicate messages from MonKill) --- Source/msg.cpp | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/Source/msg.cpp b/Source/msg.cpp index 2f1fcb6af46..ace86edc1ce 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -748,30 +748,31 @@ static bool delta_get_item(const TCmdGItem* pI) return false; } -static bool delta_put_item(const PkItemStruct* pItem, BYTE bLevel, int x, int y) +/* + * Add an item to the delta of the given level. + * @return 0: if there was no space, 1: if the item is a new item on the floor, 2: the item is supposed to be on the floor already + */ +static int delta_put_item(const PkItemStruct* pItem, BYTE bLevel, int x, int y) { int i; DDItem* pD; if (!IsMultiGame) - return true; + return 1; net_assert(bLevel < NUM_LEVELS); - // set out of loop to reduce the number of locals - // this might not change the level if there were MAXITEMS number of floor-items net_assert(gsDeltaData.ddLevelPlrs[bLevel] != 0); pD = gsDeltaData.ddLevel[bLevel].item; for (i = 0; i < MAXITEMS; i++, pD++) { if (pD->bCmd != DCMD_INVALID && pD->item.PkItemEq(*pItem)) { - if (pD->bCmd == DCMD_ITM_TAKEN) { + bool notOnFloor = pD->bCmd == DCMD_ITM_TAKEN; + if (notOnFloor) { pD->bCmd = DCMD_ITM_MOVED; pD->x = x; pD->y = y; } - //else - // app_fatal("Trying to drop a floor item?"); - return true; + return notOnFloor ? 1 : 2; } } @@ -782,11 +783,11 @@ static bool delta_put_item(const PkItemStruct* pItem, BYTE bLevel, int x, int y) pD->x = x; pD->y = y; copy_pod(pD->item, *pItem); - return true; + return 1; } } - return false; + return 0; } static void PackEar(PkItemStruct* dest, const ItemStruct* src) @@ -2418,7 +2419,7 @@ static unsigned On_PUTITEM(TCmd* pCmd, int pnum) { TCmdPItem* cmd = (TCmdPItem*)pCmd; ItemStruct* pi; - int x, y; + int x, y, pr; pi = &plr._pHoldItem; if (pi->_itype != ITYPE_NONE) { @@ -2436,8 +2437,9 @@ static unsigned On_PUTITEM(TCmd* pCmd, int pnum) #endif PkItemStruct pkItem; PackPkItem(&pkItem, pi); - if (delta_put_item(&pkItem, cmd->bLevel, x, y)) { - if (currLvl._dLevelIdx == cmd->bLevel) { + pr = delta_put_item(&pkItem, cmd->bLevel, x, y); + if (pr != 0) { + if (pr == 1 && currLvl._dLevelIdx == cmd->bLevel) { copy_pod(items[MAXITEMS], *pi); pi->_itype = ITYPE_NONE; SyncPutItem(pnum, x, y, true); @@ -2458,7 +2460,7 @@ static unsigned On_SPAWNITEM(TCmd* pCmd, int pnum) { TCmdRPItem* cmd = (TCmdRPItem*)pCmd; - if (delta_put_item(&cmd->item, cmd->bLevel, cmd->x, cmd->y) && currLvl._dLevelIdx == cmd->bLevel) { + if (delta_put_item(&cmd->item, cmd->bLevel, cmd->x, cmd->y) == 1 && currLvl._dLevelIdx == cmd->bLevel) { UnPackPkItem(&cmd->item); SyncPutItem(-1, cmd->x, cmd->y, cmd->bFlipFlag); } @@ -2775,7 +2777,7 @@ static unsigned On_MONSTSUMMON(TCmd* pCmd, int pnum) static bool PlrDeadItem(int pnum, ItemStruct* pi, int dir) { - int x, y; + int x, y, pr; if (pi->_itype == ITYPE_NONE) return true; @@ -2785,9 +2787,10 @@ static bool PlrDeadItem(int pnum, ItemStruct* pi, int dir) PackPkItem(&pkItem, pi); x = plr._px + offset_x[dir]; y = plr._py + offset_y[dir]; - if (!delta_put_item(&pkItem, plr._pDunLevel, x, y)) + pr = delta_put_item(&pkItem, plr._pDunLevel, x, y); + if (pr == 0) return false; - if (currLvl._dLevelIdx == plr._pDunLevel) { + if (pr == 1 && currLvl._dLevelIdx == plr._pDunLevel) { UnPackPkItem(&pkItem); SyncPutItem(pnum, x, y, true); } From c7276ca78132e5b2ecc4f16ada5d180023ed7197 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 29 Dec 2023 17:56:23 +0100 Subject: [PATCH 191/596] cosmetic --- Source/msg.cpp | 154 ++++++++++++++++++++++++------------------------- 1 file changed, 77 insertions(+), 77 deletions(-) diff --git a/Source/msg.cpp b/Source/msg.cpp index ace86edc1ce..44066828749 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -558,13 +558,12 @@ static BYTE delta_kill_monster(const TCmdMonstKill* mon) BYTE bLevel, whoHit; whoHit = mon->mkPnum < MAX_PLRS ? 1 << mon->mkPnum : 0; - - mnum = mon->mkMnum; if (!IsMultiGame) { return whoHit; // TODO: what about trap-kills? // return 1 << mypnum; -- exclude UMT_LACHDAN? } + mnum = mon->mkMnum; bLevel = mon->mkParam1.bParam1; net_assert(bLevel < NUM_LEVELS); net_assert(mnum < MAXMONSTERS); @@ -1463,8 +1462,8 @@ void LevelDeltaLoad() plr._pfuty = tplr->spfuty; plr._poldx = tplr->spoldx; plr._poldy = tplr->spoldy; - //LE_INT32 spxoff; // Player sprite's pixel X-offset from tile. - //LE_INT32 spyoff; // Player sprite's pixel Y-offset from tile. + //plr._pxoff = tplr->spxoff; + //plr._pyoff = tplr->spyoff; plr._pxoff = plr._pyoff = 0; // no need to sync these values as they are recalculated when used plr._pdir = tplr->spdir; plr._pAnimFrame = tplr->spAnimFrame; @@ -1519,40 +1518,40 @@ void LevelDeltaLoad() net_assert(tmon->smMode <= MM_INGAME_LAST); mon->_mmode = tmon->smMode; mon->_msquelch = tmon->smSquelch; - //mon->_mpathcount = tmon->smPathcount; // unused - //mon->_mAlign_1 = tmon->_mAlign_1; // unused + //mon->_mpathcount = tmon->smPathcount; + //mon->_mAlign_1 = tmon->smAlign_1; mon->_mgoal = tmon->smGoal; mon->_mgoalvar1 = tmon->smGoalvar1; mon->_mgoalvar2 = tmon->smGoalvar2; mon->_mgoalvar3 = tmon->smGoalvar3; - mon->_mx = tmon->smx; // Tile X-position of monster - mon->_my = tmon->smy; // Tile Y-position of monster - mon->_mfutx = tmon->smfutx; // Future tile X-position of monster. Set at start of walking animation - mon->_mfuty = tmon->smfuty; // Future tile Y-position of monster. Set at start of walking animation - mon->_moldx = tmon->smoldx; // Most recent X-position in dMonster. - mon->_moldy = tmon->smoldy; // Most recent Y-position in dMonster. - //tmon->smxoff; // Monster sprite's pixel X-offset from tile. - //tmon->smyoff; // Monster sprite's pixel Y-offset from tile. + mon->_mx = tmon->smx; + mon->_my = tmon->smy; + mon->_mfutx = tmon->smfutx; + mon->_mfuty = tmon->smfuty; + mon->_moldx = tmon->smoldx; + mon->_moldy = tmon->smoldy; + //mon->_mxoff = tmon->smxoff; + //mon->_myoff = tmon->smyoff; mon->_mxoff = mon->_myoff = 0; // no need to sync these values as they are recalculated when used - mon->_mdir = tmon->smdir; // Direction faced by monster (direction enum) - mon->_menemy = tmon->smEnemy; // The current target of the monster. An index in to either the plr or monster array based on the _meflag value. - mon->_menemyx = tmon->smEnemyx; // X-coordinate of enemy (usually correspond's to the enemy's futx value) - mon->_menemyy = tmon->smEnemyy; // Y-coordinate of enemy (usually correspond's to the enemy's futy value) - mon->_mListener = tmon->smListener; // the player to whom the monster is talking to - mon->_mDelFlag = tmon->smDelFlag; // - mon->_mAnimCnt = tmon->smAnimCnt; // Increases by one each game tick, counting how close we are to _mAnimFrameLen - mon->_mAnimFrame = tmon->smAnimFrame; // Current frame of animation. + mon->_mdir = tmon->smdir; + mon->_menemy = tmon->smEnemy; + mon->_menemyx = tmon->smEnemyx; + mon->_menemyy = tmon->smEnemyy; + mon->_mListener = tmon->smListener; + mon->_mDelFlag = tmon->smDelFlag; + mon->_mAnimCnt = tmon->smAnimCnt; + mon->_mAnimFrame = tmon->smAnimFrame; mon->_mVar1 = tmon->smVar1; mon->_mVar2 = tmon->smVar2; mon->_mVar3 = tmon->smVar3; mon->_mVar4 = tmon->smVar4; mon->_mVar5 = tmon->smVar5; - mon->_mVar6 = tmon->smVar6; // Used as _mxoff but with a higher range so that we can correctly apply velocities of a smaller number - mon->_mVar7 = tmon->smVar7; // Used as _myoff but with a higher range so that we can correctly apply velocities of a smaller number - mon->_mVar8 = tmon->smVar8; // Value used to measure progress for moving from one tile to another + mon->_mVar6 = tmon->smVar6; + mon->_mVar7 = tmon->smVar7; + mon->_mVar8 = tmon->smVar8; mon->_mhitpoints = tmon->smHitpoints; - mon->_mlastx = tmon->smLastx; // the last known X-coordinate of the enemy - mon->_mlasty = tmon->smLasty; // the last known Y-coordinate of the enemy + mon->_mlastx = tmon->smLastx; + mon->_mlasty = tmon->smLasty; //BYTE _mleader; // the leader of the monster //mon->_mleaderflag = tmon->smLeaderflag; // the status of the monster's leader //BYTE _mpacksize; // the number of 'pack'-monsters close to their leader @@ -1601,27 +1600,27 @@ void LevelDeltaLoad() mis = &missile[mi]; memset(mis, 0, sizeof(*mis)); - mis->_miType = tmis->smiType; // Type of projectile (MIS_*) - mis->_miFileNum = tmis->smiFileNum; // + mis->_miType = tmis->smiType; + mis->_miFileNum = tmis->smiFileNum; mis->_miDrawFlag = tmis->smiDrawFlag; // could be calculated mis->_miUniqTrans = tmis->smiUniqTrans; // mis->_miLightFlag = tmis->smiLightFlag; // could be calculated mis->_miPreFlag = tmis->smiPreFlag; // could be calculated //BOOL _miAnimFlag; - mis->_miAnimCnt = tmis->smiAnimCnt; // Increases by one each game tick, counting how close we are to _miAnimFrameLen - mis->_miAnimAdd = tmis->smiAnimAdd; // - mis->_miAnimFrame = tmis->smiAnimFrame; // Current frame of animation. - mis->_misx = tmis->smisx; // Initial tile X-position for missile - mis->_misy = tmis->smisy; // Initial tile Y-position for missile - mis->_mix = tmis->smix; // Tile X-position of the missile - mis->_miy = tmis->smiy; // Tile Y-position of the missile - mis->_mixoff = tmis->smixoff; // Sprite pixel X-offset for the missile - mis->_miyoff = tmis->smiyoff; // Sprite pixel Y-offset for the missile - mis->_mixvel = tmis->smixvel; // Missile tile X-velocity while walking. This gets added onto _mitxoff each game tick - mis->_miyvel = tmis->smiyvel; // Missile tile Y-velocity while walking. This gets added onto _mitxoff each game tick - mis->_mitxoff = tmis->smitxoff; // How far the missile has travelled in its lifespan along the X-axis. mix/miy/mxoff/myoff get updated every game tick based on this - mis->_mityoff = tmis->smityoff; // How far the missile has travelled in its lifespan along the Y-axis. mix/miy/mxoff/myoff get updated every game tick based on this - mis->_miDir = tmis->smiDir; // The direction of the missile + mis->_miAnimCnt = tmis->smiAnimCnt; + mis->_miAnimAdd = tmis->smiAnimAdd; + mis->_miAnimFrame = tmis->smiAnimFrame; + mis->_misx = tmis->smisx; + mis->_misy = tmis->smisy; + mis->_mix = tmis->smix; + mis->_miy = tmis->smiy; + mis->_mixoff = tmis->smixoff; + mis->_miyoff = tmis->smiyoff; + mis->_mixvel = tmis->smixvel; + mis->_miyvel = tmis->smiyvel; + mis->_mitxoff = tmis->smitxoff; + mis->_mityoff = tmis->smityoff; + mis->_miDir = tmis->smiDir; mis->_miSpllvl = tmis->smiSpllvl; // int? mis->_miSource = tmis->smiSource; // int? mis->_miCaster = tmis->smiCaster; // int? @@ -3440,7 +3439,7 @@ static unsigned On_DUMP_MONSTERS(TCmd* pCmd, int pnum) "ac:%d " "al:%d " "af:%d " - "df:%d " + //"df:%d " "v1:%d " "v2:%d " "v3:%d " @@ -3491,64 +3490,65 @@ static unsigned On_DUMP_MONSTERS(TCmd* pCmd, int pnum) mon->_msquelch, mon->_mMTidx, //mon->_mpathcount, + //mon->_mAlign_1, mon->_mgoal, mon->_mgoalvar1, mon->_mgoalvar2, mon->_mgoalvar3, - mon->_mx, // Tile X-position of monster - mon->_my, // Tile Y-position of monster - mon->_mfutx, // Future tile X-position of monster. Set at start of walking animation - mon->_mfuty, // Future tile Y-position of monster. Set at start of walking animation - mon->_moldx, // Most recent X-position in dMonster. - mon->_moldy, // Most recent Y-position in dMonster. - mon->_mxoff, // Monster sprite's pixel X-offset from tile. - mon->_myoff, // Monster sprite's pixel Y-offset from tile. - mon->_mdir, // Direction faced by monster (direction enum) - mon->_menemy, // The current target of the monster. An index in to either the plr or monster array based on the _meflag value. - mon->_menemyx, // X-coordinate of enemy (usually correspond's to the enemy's futx value) - mon->_menemyy, // Y-coordinate of enemy (usually correspond's to the enemy's futy value) - mon->_mListener, // the player to whom the monster is talking to - mon->_mAnimFrameLen, // Tick length of each frame in the current animation - mon->_mAnimCnt, // Increases by one each game tick, counting how close we are to _mAnimFrameLen - mon->_mAnimLen, // Number of frames in current animation - mon->_mAnimFrame, // Current frame of animation. - mon->_mDelFlag, + mon->_mx, + mon->_my, + mon->_mfutx, + mon->_mfuty, + mon->_moldx, + mon->_moldy, + mon->_mxoff, + mon->_myoff, + mon->_mdir, + mon->_menemy, + mon->_menemyx, + mon->_menemyy, + mon->_mListener, + mon->_mAnimFrameLen, + mon->_mAnimCnt, + mon->_mAnimLen, + mon->_mAnimFrame, + //mon->_mDelFlag, mon->_mVar1, mon->_mVar2, - mon->_mVar3, // Used to store the original mode of a stoned monster. Not 'thread' safe -> do not use for anything else! + mon->_mVar3, mon->_mVar4, mon->_mVar5, - mon->_mVar6, // Used as _mxoff but with a higher range so that we can correctly apply velocities of a smaller number - mon->_mVar7, // Used as _myoff but with a higher range so that we can correctly apply velocities of a smaller number - mon->_mVar8, // Value used to measure progress for moving from one tile to another + mon->_mVar6, + mon->_mVar7, + mon->_mVar8, mon->_mmaxhp, mon->_mhitpoints, - mon->_mlastx, // the last known X-coordinate of the enemy - mon->_mlasty, // the last known Y-coordinate of the enemy + mon->_mlastx, + mon->_mlasty, mon->_mRndSeed, mon->_mAISeed, mon->_muniqtype, mon->_muniqtrans, mon->_mNameColor, mon->_mlid, - mon->_mleader, // the leader of the monster - mon->_mleaderflag, // the status of the monster's leader - mon->_mpacksize, // the number of 'pack'-monsters close to their leader + mon->_mleader, + mon->_mleaderflag, + mon->_mpacksize, mon->_mvid, mon->_mLevel, mon->_mSelFlag, mon->_mAI.aiType, mon->_mAI.aiInt, mon->_mFlags, - mon->_mHit, // BUGFIX: Some monsters overflow this value on high difficulty (fixed) + mon->_mHit, mon->_mMinDamage, mon->_mMaxDamage, - mon->_mHit2, // BUGFIX: Some monsters overflow this value on high difficulty (fixed) + mon->_mHit2, mon->_mMinDamage2, mon->_mMaxDamage2, mon->_mMagic, - mon->_mArmorClass, // AC+evasion: used against physical-hit (melee+projectile) - mon->_mEvasion, // evasion: used against magic-projectile + mon->_mArmorClass, + mon->_mEvasion, mon->_mAFNum, mon->_mAFNum2, mon->_mMagicRes, @@ -3661,8 +3661,8 @@ static unsigned On_REQUEST_PLRCHECK(TCmd* pCmd, int pnum) buf++; *buf = plx(i)._poldy; buf++; - //int _pxoff; // Player sprite's pixel X-offset from tile. - //int _pyoff; // Player sprite's pixel Y-offset from tile. + //plr._pxoff = tplr->spxoff; + //plr._pyoff = tplr->spyoff; *buf = plx(i)._pdir; buf++; //int _pAnimFrameLen; // Tick length of each frame in the current animation From 58109f5cc96371d6f5ac7a10392cfd8b872fdce5 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 29 Dec 2023 18:10:04 +0100 Subject: [PATCH 192/596] ensure a missile of a player does not cause de-sync after the player leaves the level --- Source/monster.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 83cbfe5972b..125d522d134 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -2174,15 +2174,20 @@ void MonKill(int mnum, int mpnum) dev_fatal("MonKill: Invalid monster %d", mnum); } static_assert(MAX_MINIONS == MAX_PLRS, "MonKill requires that owner of a monster has the same id as the monster itself."); - // check if it is a plr/golem vs. monster/golem -> the attacker's owner should send the message - if ((unsigned)mpnum < MAX_PLRS) - sendmsg = mpnum == mypnum || !plx(mpnum)._pActive; // assert(MAX_MINIONS == MAX_PLRS) - // check if it is a monster/trap vs. golem -> the golem's owner should send the message - else if (mnum < MAX_MINIONS) - sendmsg = mnum == mypnum; // assert(MAX_MINIONS == MAX_PLRS && plx(mnum)._pActive) - // monster vs. monster -> the host should send the message (should not happen at the moment) - else - sendmsg = true; + // check if it is a plr/golem vs. monster/golem -> the attacker('s owner) should send the message + sendmsg = mpnum == mypnum; + if (!sendmsg) { + // not a kill by the local plr/golem -> check if the attacker is an active player on the level + if ((unsigned)mpnum >= MAX_PLRS || !plx(mpnum)._pActive || plx(mpnum)._pLvlChanging || plx(mpnum)._pDunLevel != currLvl._dLevelIdx) { + // select the first active player on the level + for (int pnum = 0; pnum < MAX_PLRS; pnum++) { + if (plr._pActive && !plr._pLvlChanging && plr._pDunLevel == currLvl._dLevelIdx) { + sendmsg = pnum == mypnum; + break; + } + } + } + } MonInitKill(mnum, mpnum, sendmsg); } From 8d3a4952c85e5b2bfbae96bc4ac71f6f58da0e2e Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 29 Dec 2023 18:12:35 +0100 Subject: [PATCH 193/596] disable unnecessary complexity in MonKill --- Source/monster.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/monster.cpp b/Source/monster.cpp index 125d522d134..95f069c76a1 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -2173,6 +2173,7 @@ void MonKill(int mnum, int mpnum) if ((unsigned)mnum >= MAXMONSTERS) { dev_fatal("MonKill: Invalid monster %d", mnum); } +#if 0 // commented out because it seems to be an unnecessary complexity static_assert(MAX_MINIONS == MAX_PLRS, "MonKill requires that owner of a monster has the same id as the monster itself."); // check if it is a plr/golem vs. monster/golem -> the attacker('s owner) should send the message sendmsg = mpnum == mypnum; @@ -2188,6 +2189,9 @@ void MonKill(int mnum, int mpnum) } } } +#else + sendmsg = true; +#endif MonInitKill(mnum, mpnum, sendmsg); } From ea9a49f7d99c7253241ae97a95146f03a52048ab Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 29 Dec 2023 19:15:25 +0100 Subject: [PATCH 194/596] simplify PlaceGroup - assume UMF_GROUP is set when leaderf is non-zero --- Source/monster.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 95f069c76a1..9ccf46c1d56 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -790,7 +790,8 @@ static void PlaceGroup(int mtidx, int num, int leaderf, int leader) dMonster[monsters[nummonsters]._mx][monsters[nummonsters]._my] = 0; } - if (leaderf & UMF_GROUP) { + if (leaderf) { + // assert(leaderf & UMF_GROUP); x1 = monsters[leader]._mx; y1 = monsters[leader]._my; } else { @@ -825,7 +826,8 @@ static void PlaceGroup(int mtidx, int num, int leaderf, int leader) continue; // assert(nummonsters < MAXMONSTERS); mnum = PlaceMonster(mtidx, xp, yp); - if (leaderf & UMF_GROUP) { + if (leaderf) { + // assert(leaderf & UMF_GROUP); monsters[mnum]._mNameColor = COL_BLUE; monsters[mnum]._mmaxhp *= 2; monsters[mnum]._mhitpoints = monsters[mnum]._mmaxhp; From e4702d30e6346789e6e3e47f82136c07b38c0d32 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 29 Dec 2023 19:20:17 +0100 Subject: [PATCH 195/596] bugfix for 'reduce the number of MonFindEnemy calls' --- Source/monster.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 9ccf46c1d56..c16fa0e97ab 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3648,11 +3648,9 @@ void MAI_Garg(int mnum) mon = &monsters[mnum]; if (mon->_mFlags & MFLAG_GARG_STONE) { - if (!MON_RELAXED) { - MonFindEnemy(mnum); + if (MON_HAS_ENEMY) { MonEnemyInfo(mnum); // wake up if the enemy is close - static_assert(std::max(DBORDERX, DBORDERY) > (5 + 2), "MAI_Garg skips MFLAG_NO_ENEMY-check by assuming a monster is usually 'far' from (0;0)."); // (_menemyx;_menemyy) if (currEnemyInfo._meRealDist < mon->_mAI.aiInt + 2) { mon->_mFlags &= ~(MFLAG_LOCK_ANIMATION | MFLAG_GARG_STONE); return; @@ -4409,7 +4407,7 @@ void ProcessMonsters() } alert = (dFlags[mon->_mfutx][mon->_mfuty] & BFLAG_ALERT) != 0; - if ((alert || MON_HAS_ENEMY) && !MON_ACTIVE) { + if ((alert || MON_HAS_ENEMY) && (!MON_ACTIVE || (mon->_mFlags & MFLAG_GARG_STONE))) { MonFindEnemy(mnum); // commented out, because the player might went out of sight in the meantime // assert(MON_HAS_ENEMY || myplr._pInvincible); From 5c58add9917814d0b25089ca0fea9e556aecafe9 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 30 Dec 2023 08:41:40 +0100 Subject: [PATCH 196/596] minor optimization (delta_put_item) --- Source/msg.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Source/msg.cpp b/Source/msg.cpp index 44066828749..0b75fe76c61 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -749,7 +749,7 @@ static bool delta_get_item(const TCmdGItem* pI) /* * Add an item to the delta of the given level. - * @return 0: if there was no space, 1: if the item is a new item on the floor, 2: the item is supposed to be on the floor already + * @return -1: if there was no space, 0: if the item is a new item on the floor, 1: the item is supposed to be on the floor already */ static int delta_put_item(const PkItemStruct* pItem, BYTE bLevel, int x, int y) { @@ -757,7 +757,7 @@ static int delta_put_item(const PkItemStruct* pItem, BYTE bLevel, int x, int y) DDItem* pD; if (!IsMultiGame) - return 1; + return 0; net_assert(bLevel < NUM_LEVELS); net_assert(gsDeltaData.ddLevelPlrs[bLevel] != 0); @@ -765,13 +765,13 @@ static int delta_put_item(const PkItemStruct* pItem, BYTE bLevel, int x, int y) for (i = 0; i < MAXITEMS; i++, pD++) { if (pD->bCmd != DCMD_INVALID && pD->item.PkItemEq(*pItem)) { - bool notOnFloor = pD->bCmd == DCMD_ITM_TAKEN; - if (notOnFloor) { + bool onFloor = pD->bCmd != DCMD_ITM_TAKEN; + if (!onFloor) { pD->bCmd = DCMD_ITM_MOVED; pD->x = x; pD->y = y; } - return notOnFloor ? 1 : 2; + return onFloor ? 1 : 0; } } @@ -782,11 +782,11 @@ static int delta_put_item(const PkItemStruct* pItem, BYTE bLevel, int x, int y) pD->x = x; pD->y = y; copy_pod(pD->item, *pItem); - return 1; + return 0; } } - return 0; + return -1; } static void PackEar(PkItemStruct* dest, const ItemStruct* src) @@ -2437,8 +2437,8 @@ static unsigned On_PUTITEM(TCmd* pCmd, int pnum) PkItemStruct pkItem; PackPkItem(&pkItem, pi); pr = delta_put_item(&pkItem, cmd->bLevel, x, y); - if (pr != 0) { - if (pr == 1 && currLvl._dLevelIdx == cmd->bLevel) { + if (pr >= 0) { + if (pr == 0 && currLvl._dLevelIdx == cmd->bLevel) { copy_pod(items[MAXITEMS], *pi); pi->_itype = ITYPE_NONE; SyncPutItem(pnum, x, y, true); @@ -2459,7 +2459,7 @@ static unsigned On_SPAWNITEM(TCmd* pCmd, int pnum) { TCmdRPItem* cmd = (TCmdRPItem*)pCmd; - if (delta_put_item(&cmd->item, cmd->bLevel, cmd->x, cmd->y) == 1 && currLvl._dLevelIdx == cmd->bLevel) { + if (delta_put_item(&cmd->item, cmd->bLevel, cmd->x, cmd->y) == 0 && currLvl._dLevelIdx == cmd->bLevel) { UnPackPkItem(&cmd->item); SyncPutItem(-1, cmd->x, cmd->y, cmd->bFlipFlag); } @@ -2787,9 +2787,9 @@ static bool PlrDeadItem(int pnum, ItemStruct* pi, int dir) x = plr._px + offset_x[dir]; y = plr._py + offset_y[dir]; pr = delta_put_item(&pkItem, plr._pDunLevel, x, y); - if (pr == 0) + if (pr < 0) return false; - if (pr == 1 && currLvl._dLevelIdx == plr._pDunLevel) { + if (pr == 0 && currLvl._dLevelIdx == plr._pDunLevel) { UnPackPkItem(&pkItem); SyncPutItem(pnum, x, y, true); } From 2f70a093ca71f650195d3e7d22dfc6602d9cb72f Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 30 Dec 2023 10:20:15 +0100 Subject: [PATCH 197/596] do not drag the char-window while one of the char-buttons is pressed --- Source/control.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/control.cpp b/Source/control.cpp index 3209388265b..aa7d57827f2 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -1783,7 +1783,9 @@ void CheckChrBtnClick() { int i; - if (myplr._pStatPts != 0 && !gbChrbtnactive) { + if (myplr._pStatPts != 0) { + if (gbChrbtnactive) + return; // true; for (i = 0; i < lengthof(ChrBtnsRect); i++) { if (!POS_IN_RECT(MousePos.x, MousePos.y, gnWndCharX + ChrBtnsRect[i].x, gnWndCharY + ChrBtnsRect[i].y, From be4a1ea6c31004c9ddb413406a18d7e33a7eb7a7 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 30 Dec 2023 10:25:17 +0100 Subject: [PATCH 198/596] simplify ReleaseChrBtn assuming ordered CMD_ADD* values --- Source/control.cpp | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/Source/control.cpp b/Source/control.cpp index aa7d57827f2..07b64977131 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -1814,23 +1814,10 @@ void ReleaseChrBtn() if (POS_IN_RECT(MousePos.x, MousePos.y, gnWndCharX + ChrBtnsRect[i].x, gnWndCharY + ChrBtnsRect[i].y, ChrBtnsRect[i].w, ChrBtnsRect[i].h)) { - switch (i) { - case 0: - NetSendCmd(CMD_ADDSTR); - break; - case 1: - NetSendCmd(CMD_ADDMAG); - break; - case 2: - NetSendCmd(CMD_ADDDEX); - break; - case 3: - NetSendCmd(CMD_ADDVIT); - break; - default: - ASSUME_UNREACHABLE - break; - } + static_assert((int)CMD_ADDSTR + 1 == (int)CMD_ADDMAG, "ReleaseChrBtn expects ordered CMD_ADD values I."); + static_assert((int)CMD_ADDMAG + 1 == (int)CMD_ADDDEX, "ReleaseChrBtn expects ordered CMD_ADD values II."); + static_assert((int)CMD_ADDDEX + 1 == (int)CMD_ADDVIT, "ReleaseChrBtn expects ordered CMD_ADD values III."); + NetSendCmd(CMD_ADDSTR + i); } } } From 5020399b1f69836d10218704f47b30f21212810b Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 30 Dec 2023 10:30:06 +0100 Subject: [PATCH 199/596] get rid of ChrBtnsRect --- Source/control.cpp | 44 ++++++++++++++---------------------- Source/control.h | 5 +--- Source/controls/plrctrls.cpp | 15 ++++++------ Source/gameui.h | 2 ++ 4 files changed, 27 insertions(+), 39 deletions(-) diff --git a/Source/control.cpp b/Source/control.cpp index 07b64977131..1d2b0143a42 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -79,7 +79,7 @@ static CelImageBuf* pChrPanelCel; /** Char-Panel button images CEL */ static CelImageBuf* pChrButtonCels; /** Specifies whether the button of the given attribute is pressed on Character-Panel. */ -static bool _gabChrbtn[NUM_ATTRIBS]; +bool gabChrbtn[NUM_ATTRIBS]; /** Specifies whether any attribute-button is pressed on Character-Panel. */ bool gbChrbtnactive; /** Color translations for the skill icons. */ @@ -123,15 +123,6 @@ static const char* PanBtnTxt[NUM_PANBTNS] = { "Teams" // clang-format on }; -/** Maps from attribute_id to the rectangle on screen used for attribute increment buttons. */ -const RECT32 ChrBtnsRect[NUM_ATTRIBS] = { - // clang-format off - { 132, 102, CHRBTN_WIDTH, CHRBTN_HEIGHT }, - { 132, 130, CHRBTN_WIDTH, CHRBTN_HEIGHT }, - { 132, 159, CHRBTN_WIDTH, CHRBTN_HEIGHT }, - { 132, 187, CHRBTN_WIDTH, CHRBTN_HEIGHT } - // clang-format on -}; /** The number of spells/skills on a single spellbook page. */ #define NUM_BOOK_ENTRIES 7 /** Maps from spellbook page number and position to spell_id. */ @@ -929,8 +920,8 @@ void InitControlPan() numpanbtns = IsLocalGame ? NUM_PANBTNS - 2 : NUM_PANBTNS; assert(pChrButtonCels == NULL); pChrButtonCels = CelLoadImage("Data\\CharBut.CEL", CHRBTN_WIDTH); - for (i = 0; i < lengthof(_gabChrbtn); i++) - _gabChrbtn[i] = false; + for (i = 0; i < lengthof(gabChrbtn); i++) + gabChrbtn[i] = false; gbChrbtnactive = false; assert(pTextBoxCels == NULL); pTextBoxCels = CelLoadImage("Data\\TextBox.CEL", LTPANEL_WIDTH); @@ -1294,10 +1285,10 @@ void DrawChr() if (p->_pStatPts > 0) { snprintf(chrstr, sizeof(chrstr), "%d", p->_pStatPts); PrintString(screen_x + 88, screen_y + 231, screen_x + 125, chrstr, true, COL_RED, FONT_KERN_SMALL); - CelDraw(screen_x + ChrBtnsRect[ATTRIB_STR].x, screen_y + ChrBtnsRect[ATTRIB_STR].y + CHRBTN_HEIGHT, pChrButtonCels, _gabChrbtn[ATTRIB_STR] ? 3 : 2); - CelDraw(screen_x + ChrBtnsRect[ATTRIB_MAG].x, screen_y + ChrBtnsRect[ATTRIB_MAG].y + CHRBTN_HEIGHT, pChrButtonCels, _gabChrbtn[ATTRIB_MAG] ? 5 : 4); - CelDraw(screen_x + ChrBtnsRect[ATTRIB_DEX].x, screen_y + ChrBtnsRect[ATTRIB_DEX].y + CHRBTN_HEIGHT, pChrButtonCels, _gabChrbtn[ATTRIB_DEX] ? 7 : 6); - CelDraw(screen_x + ChrBtnsRect[ATTRIB_VIT].x, screen_y + ChrBtnsRect[ATTRIB_VIT].y + CHRBTN_HEIGHT, pChrButtonCels, _gabChrbtn[ATTRIB_VIT] ? 9 : 8); + CelDraw(screen_x + CHRBTN_LEFT, screen_y + CHRBTN_TOP(ATTRIB_STR) + CHRBTN_HEIGHT - 1, pChrButtonCels, gabChrbtn[ATTRIB_STR] ? 3 : 2); + CelDraw(screen_x + CHRBTN_LEFT, screen_y + CHRBTN_TOP(ATTRIB_MAG) + CHRBTN_HEIGHT - 1, pChrButtonCels, gabChrbtn[ATTRIB_MAG] ? 5 : 4); + CelDraw(screen_x + CHRBTN_LEFT, screen_y + CHRBTN_TOP(ATTRIB_DEX) + CHRBTN_HEIGHT - 1, pChrButtonCels, gabChrbtn[ATTRIB_DEX] ? 7 : 6); + CelDraw(screen_x + CHRBTN_LEFT, screen_y + CHRBTN_TOP(ATTRIB_VIT) + CHRBTN_HEIGHT - 1, pChrButtonCels, gabChrbtn[ATTRIB_VIT] ? 9 : 8); } if (p->_pHasUnidItem) @@ -1786,13 +1777,13 @@ void CheckChrBtnClick() if (myplr._pStatPts != 0) { if (gbChrbtnactive) return; // true; - for (i = 0; i < lengthof(ChrBtnsRect); i++) { + for (i = 0; i < lengthof(gabChrbtn); i++) { if (!POS_IN_RECT(MousePos.x, MousePos.y, - gnWndCharX + ChrBtnsRect[i].x, gnWndCharY + ChrBtnsRect[i].y, - ChrBtnsRect[i].w, ChrBtnsRect[i].h)) + gnWndCharX + CHRBTN_LEFT, gnWndCharY + CHRBTN_TOP(i), + CHRBTN_WIDTH, CHRBTN_HEIGHT)) continue; - _gabChrbtn[i] = true; + gabChrbtn[i] = true; gbChrbtnactive = true; return; // true; } @@ -1806,14 +1797,13 @@ void ReleaseChrBtn() int i; gbChrbtnactive = false; - static_assert(lengthof(_gabChrbtn) == lengthof(ChrBtnsRect), "Mismatching _gabChrbtn and ChrBtnsRect tables."); - static_assert(lengthof(_gabChrbtn) == 4, "Table _gabChrbtn does not work with ReleaseChrBtns function."); - for (i = 0; i < lengthof(_gabChrbtn); ++i) { - if (_gabChrbtn[i]) { - _gabChrbtn[i] = false; + static_assert(lengthof(gabChrbtn) == 4, "Table gabChrbtn does not work with ReleaseChrBtns function."); + for (i = 0; i < lengthof(gabChrbtn); ++i) { + if (gabChrbtn[i]) { + gabChrbtn[i] = false; if (POS_IN_RECT(MousePos.x, MousePos.y, - gnWndCharX + ChrBtnsRect[i].x, gnWndCharY + ChrBtnsRect[i].y, - ChrBtnsRect[i].w, ChrBtnsRect[i].h)) { + gnWndCharX + CHRBTN_LEFT, gnWndCharY + CHRBTN_TOP(i), + CHRBTN_WIDTH, CHRBTN_HEIGHT)) { static_assert((int)CMD_ADDSTR + 1 == (int)CMD_ADDMAG, "ReleaseChrBtn expects ordered CMD_ADD values I."); static_assert((int)CMD_ADDMAG + 1 == (int)CMD_ADDDEX, "ReleaseChrBtn expects ordered CMD_ADD values II."); static_assert((int)CMD_ADDDEX + 1 == (int)CMD_ADDVIT, "ReleaseChrBtn expects ordered CMD_ADD values III."); diff --git a/Source/control.h b/Source/control.h index 00ff6060688..bfac163cae0 100644 --- a/Source/control.h +++ b/Source/control.h @@ -22,6 +22,7 @@ extern int dropGoldValue; extern int initialDropGoldValue; extern BYTE initialDropGoldIndex; extern bool gbChrbtnactive; +extern bool gabChrbtn[NUM_ATTRIBS]; extern BYTE infoclr; extern char infostr[256]; extern char tempstr[256]; @@ -77,10 +78,6 @@ void DrawTeamBook(); void CheckTeamClick(bool shift); void DrawGolemBar(); -/* data */ - -extern const RECT32 ChrBtnsRect[4]; - #ifdef __cplusplus } #endif diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index e3924e16d04..0ec90826dce 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -342,10 +342,10 @@ static void AttrIncBtnSnap(AxisDirection dir) // first, find our cursor location int slot = 0; - for (int i = 0; i < lengthof(ChrBtnsRect); i++) { + for (int i = 0; i < lengthof(gabChrbtn); i++) { if (POS_IN_RECT(MousePos.x, MousePos.y, - gnWndCharX + ChrBtnsRect[i].x, gnWndCharY + ChrBtnsRect[i].y, - ChrBtnsRect[i].w, ChrBtnsRect[i].h)) { + gnWndCharX + CHRBTN_LEFT, gnWndCharY + CHRBTN_TOP(i), + CHRBTN_WIDTH, CHRBTN_HEIGHT)) { slot = i; break; } @@ -356,14 +356,14 @@ static void AttrIncBtnSnap(AxisDirection dir) return; // Avoid wobbling when scaled --slot; } else if (dir.y == AxisDirectionY_DOWN) { - if (slot >= lengthof(ChrBtnsRect) - 1) + if (slot >= lengthof(gabChrbtn) - 1) return; // Avoid wobbling when scaled ++slot; } // move cursor to our new location - int x = gnWndCharX + ChrBtnsRect[slot].x + (ChrBtnsRect[slot].w / 2); - int y = gnWndCharY + ChrBtnsRect[slot].y + (ChrBtnsRect[slot].h / 2); + int x = gnWndCharX + CHRBTN_LEFT + (CHRBTN_WIDTH / 2); + int y = gnWndCharY + CHRBTN_TOP(slot) + (CHRBTN_HEIGHT / 2); SetCursorPos(x, y); } @@ -982,8 +982,7 @@ void FocusOnCharInfo() return; // Jump to the first incrementable stat. - const RECT32& rect = ChrBtnsRect[0]; - SetCursorPos(gnWndCharX + rect.x + (rect.w / 2), gnWndCharY + rect.y + (rect.h / 2)); + SetCursorPos(gnWndCharX + CHRBTN_LEFT + (CHRBTN_WIDTH / 2), gnWndCharY + CHRBTN_TOP(0) + (CHRBTN_HEIGHT / 2)); } void plrctrls_after_check_curs_move() diff --git a/Source/gameui.h b/Source/gameui.h index bec8a13535d..257912b8398 100644 --- a/Source/gameui.h +++ b/Source/gameui.h @@ -75,6 +75,8 @@ extern "C" { #define MENUBTN_HEIGHT 19 #define CHRBTN_WIDTH 41 #define CHRBTN_HEIGHT 22 +#define CHRBTN_LEFT 132 +#define CHRBTN_TOP(x) (103 + (CHRBTN_HEIGHT + 6) * x) #if ASSET_MPL == 1 #define SPLICON_WIDTH 37 #define SPLICON_HEIGHT 38 From 899374a854d55d84b70023e50498527f62a16334 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 30 Dec 2023 10:40:50 +0100 Subject: [PATCH 200/596] draw consistent char-buttons --- Packaging/resources/devilx.mpq | Bin 1241315 -> 1247157 bytes Packaging/resources/mpqfiles.txt | 1 + Source/control.cpp | 10 +++++----- Source/gameui.h | 6 +++--- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Packaging/resources/devilx.mpq b/Packaging/resources/devilx.mpq index 49423a545024ce4ba49e27481607ba41f9a79688..c51f2ac1d3c882b69909d0ce6f3e6a68627f65eb 100644 GIT binary patch delta 9235 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 delta 4249 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 vAqa;qAqj^rAqs~sAq$5tAq_pStatPts > 0) { snprintf(chrstr, sizeof(chrstr), "%d", p->_pStatPts); PrintString(screen_x + 88, screen_y + 231, screen_x + 125, chrstr, true, COL_RED, FONT_KERN_SMALL); - CelDraw(screen_x + CHRBTN_LEFT, screen_y + CHRBTN_TOP(ATTRIB_STR) + CHRBTN_HEIGHT - 1, pChrButtonCels, gabChrbtn[ATTRIB_STR] ? 3 : 2); - CelDraw(screen_x + CHRBTN_LEFT, screen_y + CHRBTN_TOP(ATTRIB_MAG) + CHRBTN_HEIGHT - 1, pChrButtonCels, gabChrbtn[ATTRIB_MAG] ? 5 : 4); - CelDraw(screen_x + CHRBTN_LEFT, screen_y + CHRBTN_TOP(ATTRIB_DEX) + CHRBTN_HEIGHT - 1, pChrButtonCels, gabChrbtn[ATTRIB_DEX] ? 7 : 6); - CelDraw(screen_x + CHRBTN_LEFT, screen_y + CHRBTN_TOP(ATTRIB_VIT) + CHRBTN_HEIGHT - 1, pChrButtonCels, gabChrbtn[ATTRIB_VIT] ? 9 : 8); + CelDraw(screen_x + CHRBTN_LEFT, screen_y + CHRBTN_TOP(ATTRIB_STR) + CHRBTN_HEIGHT - 1, pChrButtonCels, gabChrbtn[ATTRIB_STR] ? 2 : 1); + CelDraw(screen_x + CHRBTN_LEFT, screen_y + CHRBTN_TOP(ATTRIB_MAG) + CHRBTN_HEIGHT - 1, pChrButtonCels, gabChrbtn[ATTRIB_MAG] ? 2 : 1); + CelDraw(screen_x + CHRBTN_LEFT, screen_y + CHRBTN_TOP(ATTRIB_DEX) + CHRBTN_HEIGHT - 1, pChrButtonCels, gabChrbtn[ATTRIB_DEX] ? 2 : 1); + CelDraw(screen_x + CHRBTN_LEFT, screen_y + CHRBTN_TOP(ATTRIB_VIT) + CHRBTN_HEIGHT - 1, pChrButtonCels, gabChrbtn[ATTRIB_VIT] ? 2 : 1); } if (p->_pHasUnidItem) @@ -1426,7 +1426,7 @@ void DrawLevelUpIcon() screen_x = SCREEN_X + LVLUP_LEFT; screen_y = PANEL_Y + PANEL_HEIGHT - LVLUP_OFFSET; PrintString(screen_x - 38, screen_y + 20, screen_x - 38 + 120, "Level Up", true, COL_WHITE, FONT_KERN_SMALL); - CelDraw(screen_x, screen_y, pChrButtonCels, gbLvlbtndown ? 3 : 2); + CelDraw(screen_x, screen_y, pChrButtonCels, gbLvlbtndown ? 2 : 1); } static int DrawTooltip2(const char* text1, const char* text2, int x, int y, BYTE col) diff --git a/Source/gameui.h b/Source/gameui.h index 257912b8398..16a3228a640 100644 --- a/Source/gameui.h +++ b/Source/gameui.h @@ -73,10 +73,10 @@ extern "C" { #define MENUBTN_WIDTH 71 #define MENUBTN_HEIGHT 19 -#define CHRBTN_WIDTH 41 -#define CHRBTN_HEIGHT 22 +#define CHRBTN_WIDTH 40 +#define CHRBTN_HEIGHT 21 #define CHRBTN_LEFT 132 -#define CHRBTN_TOP(x) (103 + (CHRBTN_HEIGHT + 6) * x) +#define CHRBTN_TOP(x) (104 + (CHRBTN_HEIGHT + 7) * x) #if ASSET_MPL == 1 #define SPLICON_WIDTH 37 #define SPLICON_HEIGHT 38 From 7da2ba563335b77b722b1f89872878402174937a Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 30 Dec 2023 11:44:34 +0100 Subject: [PATCH 201/596] improve the handling of movement on the y-axis in the char-window - select slot based on the mouse (y) position - jump to the first/last in case the current position is outside of the range - no need to check _pStatPts (it is already checked and does not really matter anyway) - no need to check gbChrbtnactive (let the player cancel the button-click) - use NUM_ATTRIBS instead of lengthof(gabChrbtn) to avoid the need to expose gabChrbtn - avoid wobble even if not in the first/last slot --- Source/control.cpp | 2 +- Source/control.h | 1 - Source/controls/plrctrls.cpp | 40 ++++++++++++++++-------------------- 3 files changed, 19 insertions(+), 24 deletions(-) diff --git a/Source/control.cpp b/Source/control.cpp index 74ec7fea7c4..7d9a09db6b8 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -79,7 +79,7 @@ static CelImageBuf* pChrPanelCel; /** Char-Panel button images CEL */ static CelImageBuf* pChrButtonCels; /** Specifies whether the button of the given attribute is pressed on Character-Panel. */ -bool gabChrbtn[NUM_ATTRIBS]; +static bool gabChrbtn[NUM_ATTRIBS]; /** Specifies whether any attribute-button is pressed on Character-Panel. */ bool gbChrbtnactive; /** Color translations for the skill icons. */ diff --git a/Source/control.h b/Source/control.h index bfac163cae0..873c0409b1d 100644 --- a/Source/control.h +++ b/Source/control.h @@ -22,7 +22,6 @@ extern int dropGoldValue; extern int initialDropGoldValue; extern BYTE initialDropGoldIndex; extern bool gbChrbtnactive; -extern bool gabChrbtn[NUM_ATTRIBS]; extern BYTE infoclr; extern char infostr[256]; extern char tempstr[256]; diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index 0ec90826dce..dd36fc68a7d 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -337,34 +337,30 @@ static void AttrIncBtnSnap(AxisDirection dir) if (dir.y == AxisDirectionY_NONE) return; - if (gbChrbtnactive || myplr._pStatPts <= 0) - return; - - // first, find our cursor location - int slot = 0; - for (int i = 0; i < lengthof(gabChrbtn); i++) { - if (POS_IN_RECT(MousePos.x, MousePos.y, - gnWndCharX + CHRBTN_LEFT, gnWndCharY + CHRBTN_TOP(i), - CHRBTN_WIDTH, CHRBTN_HEIGHT)) { - slot = i; - break; - } + // find the current slot based on the mouse position + int slot = -1; + int sy = MousePos.y - (gnWndCharY + CHRBTN_TOP(0)); + while (sy >= 0) { + slot++; + sy -= CHRBTN_TOP(slot + 1) - CHRBTN_TOP(slot); } - + // step in the desired direction if (dir.y == AxisDirectionY_UP) { - if (slot == 0) - return; // Avoid wobbling when scaled - --slot; - } else if (dir.y == AxisDirectionY_DOWN) { - if (slot >= lengthof(gabChrbtn) - 1) - return; // Avoid wobbling when scaled - ++slot; + slot--; + } else { + // assert(dir.y == AxisDirectionY_DOWN); + slot++; } - + // limit the slot to the available ones + if (slot < 0) + slot = 0; + else if (slot >= NUM_ATTRIBS) + slot = NUM_ATTRIBS - 1; // move cursor to our new location int x = gnWndCharX + CHRBTN_LEFT + (CHRBTN_WIDTH / 2); int y = gnWndCharY + CHRBTN_TOP(slot) + (CHRBTN_HEIGHT / 2); - SetCursorPos(x, y); + if (abs(MousePos.x - x) >= CHRBTN_WIDTH / 2 || abs(MousePos.y - y) >= CHRBTN_HEIGHT / 2) // Avoid wobbling when scaled + SetCursorPos(x, y); } #define SELECT_INV_SLOT(s) \ From 63d8c854def07ff33e1102ac061d6c8e283e0010 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 30 Dec 2023 12:07:22 +0100 Subject: [PATCH 202/596] add CheckInChrBtnRect --- Source/control.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Source/control.cpp b/Source/control.cpp index 7d9a09db6b8..1fcd729e1bc 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -1770,6 +1770,13 @@ void DrawInfoStr() } } +static bool CheckInChrBtnRect(int i) +{ + return POS_IN_RECT(MousePos.x, MousePos.y, + gnWndCharX + CHRBTN_LEFT, gnWndCharY + CHRBTN_TOP(i), + CHRBTN_WIDTH, CHRBTN_HEIGHT); +} + void CheckChrBtnClick() { int i; @@ -1778,9 +1785,7 @@ void CheckChrBtnClick() if (gbChrbtnactive) return; // true; for (i = 0; i < lengthof(gabChrbtn); i++) { - if (!POS_IN_RECT(MousePos.x, MousePos.y, - gnWndCharX + CHRBTN_LEFT, gnWndCharY + CHRBTN_TOP(i), - CHRBTN_WIDTH, CHRBTN_HEIGHT)) + if (!CheckInChrBtnRect(i)) continue; gabChrbtn[i] = true; @@ -1801,9 +1806,7 @@ void ReleaseChrBtn() for (i = 0; i < lengthof(gabChrbtn); ++i) { if (gabChrbtn[i]) { gabChrbtn[i] = false; - if (POS_IN_RECT(MousePos.x, MousePos.y, - gnWndCharX + CHRBTN_LEFT, gnWndCharY + CHRBTN_TOP(i), - CHRBTN_WIDTH, CHRBTN_HEIGHT)) { + if (CheckInChrBtnRect(i)) { static_assert((int)CMD_ADDSTR + 1 == (int)CMD_ADDMAG, "ReleaseChrBtn expects ordered CMD_ADD values I."); static_assert((int)CMD_ADDMAG + 1 == (int)CMD_ADDDEX, "ReleaseChrBtn expects ordered CMD_ADD values II."); static_assert((int)CMD_ADDDEX + 1 == (int)CMD_ADDVIT, "ReleaseChrBtn expects ordered CMD_ADD values III."); From 526a806572856805edb87bde2a7c6ee373d6a3df Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 30 Dec 2023 12:09:05 +0100 Subject: [PATCH 203/596] add option to draw the char buttons over the base-stats --- Source/control.cpp | 19 ++++++++++++------- Source/controls/plrctrls.cpp | 2 +- Source/gameui.h | 1 + 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Source/control.cpp b/Source/control.cpp index 1fcd729e1bc..5f09f169eed 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -1234,6 +1234,7 @@ void DrawChr() BYTE col; char chrstr[64]; int screen_x, screen_y, pc, val, mindam, maxdam; + bool showStats; p = &myplr; pc = p->_pClass; @@ -1282,19 +1283,22 @@ void DrawChr() snprintf(chrstr, sizeof(chrstr), "%d", p->_pBaseVit); PrintString(screen_x + 88, screen_y + 203, screen_x + 125, chrstr, true, col, FONT_KERN_SMALL); - if (p->_pStatPts > 0) { + showStats = p->_pStatPts <= 0; + if (!showStats) { + showStats = (SDL_GetModState() & KMOD_ALT) != 0; snprintf(chrstr, sizeof(chrstr), "%d", p->_pStatPts); PrintString(screen_x + 88, screen_y + 231, screen_x + 125, chrstr, true, COL_RED, FONT_KERN_SMALL); - CelDraw(screen_x + CHRBTN_LEFT, screen_y + CHRBTN_TOP(ATTRIB_STR) + CHRBTN_HEIGHT - 1, pChrButtonCels, gabChrbtn[ATTRIB_STR] ? 2 : 1); - CelDraw(screen_x + CHRBTN_LEFT, screen_y + CHRBTN_TOP(ATTRIB_MAG) + CHRBTN_HEIGHT - 1, pChrButtonCels, gabChrbtn[ATTRIB_MAG] ? 2 : 1); - CelDraw(screen_x + CHRBTN_LEFT, screen_y + CHRBTN_TOP(ATTRIB_DEX) + CHRBTN_HEIGHT - 1, pChrButtonCels, gabChrbtn[ATTRIB_DEX] ? 2 : 1); - CelDraw(screen_x + CHRBTN_LEFT, screen_y + CHRBTN_TOP(ATTRIB_VIT) + CHRBTN_HEIGHT - 1, pChrButtonCels, gabChrbtn[ATTRIB_VIT] ? 2 : 1); + int sx = screen_x + (showStats ? CHRBTN_ALT : CHRBTN_LEFT); + CelDraw(sx, screen_y + CHRBTN_TOP(ATTRIB_STR) + CHRBTN_HEIGHT - 1, pChrButtonCels, gabChrbtn[ATTRIB_STR] ? 2 : 1); + CelDraw(sx, screen_y + CHRBTN_TOP(ATTRIB_MAG) + CHRBTN_HEIGHT - 1, pChrButtonCels, gabChrbtn[ATTRIB_MAG] ? 2 : 1); + CelDraw(sx, screen_y + CHRBTN_TOP(ATTRIB_DEX) + CHRBTN_HEIGHT - 1, pChrButtonCels, gabChrbtn[ATTRIB_DEX] ? 2 : 1); + CelDraw(sx, screen_y + CHRBTN_TOP(ATTRIB_VIT) + CHRBTN_HEIGHT - 1, pChrButtonCels, gabChrbtn[ATTRIB_VIT] ? 2 : 1); } if (p->_pHasUnidItem) return; - if (p->_pStatPts <= 0) { + if (showStats) { val = p->_pStrength; col = COL_WHITE; if (val > p->_pBaseStr) @@ -1772,8 +1776,9 @@ void DrawInfoStr() static bool CheckInChrBtnRect(int i) { + int sx = (SDL_GetModState() & KMOD_ALT) ? CHRBTN_ALT : CHRBTN_LEFT; return POS_IN_RECT(MousePos.x, MousePos.y, - gnWndCharX + CHRBTN_LEFT, gnWndCharY + CHRBTN_TOP(i), + gnWndCharX + sx, gnWndCharY + CHRBTN_TOP(i), CHRBTN_WIDTH, CHRBTN_HEIGHT); } diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index dd36fc68a7d..067a6392457 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -357,7 +357,7 @@ static void AttrIncBtnSnap(AxisDirection dir) else if (slot >= NUM_ATTRIBS) slot = NUM_ATTRIBS - 1; // move cursor to our new location - int x = gnWndCharX + CHRBTN_LEFT + (CHRBTN_WIDTH / 2); + int x = gnWndCharX + ((SDL_GetModState() & KMOD_ALT) != 0 ? CHRBTN_ALT : CHRBTN_LEFT) + (CHRBTN_WIDTH / 2); int y = gnWndCharY + CHRBTN_TOP(slot) + (CHRBTN_HEIGHT / 2); if (abs(MousePos.x - x) >= CHRBTN_WIDTH / 2 || abs(MousePos.y - y) >= CHRBTN_HEIGHT / 2) // Avoid wobbling when scaled SetCursorPos(x, y); diff --git a/Source/gameui.h b/Source/gameui.h index 16a3228a640..26417c034bb 100644 --- a/Source/gameui.h +++ b/Source/gameui.h @@ -76,6 +76,7 @@ extern "C" { #define CHRBTN_WIDTH 40 #define CHRBTN_HEIGHT 21 #define CHRBTN_LEFT 132 +#define CHRBTN_ALT 85 #define CHRBTN_TOP(x) (104 + (CHRBTN_HEIGHT + 7) * x) #if ASSET_MPL == 1 #define SPLICON_WIDTH 37 From 695fad1d6ec2a3fc0f67c86679d21a9206bf0272 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 30 Dec 2023 17:02:42 +0100 Subject: [PATCH 204/596] eliminate invalid asserts - unique packs might not be complete (bugfix for 'optimize MonUpdateLeader and MonDirOK') --- Source/monster.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index c16fa0e97ab..b6df3f3f09a 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1736,7 +1736,6 @@ void MonLeaveLeader(int mnum) monsters[mnum]._mpacksize = 0; // assert(mnum + MON_PACK_SIZE <= MAXMONSTERS); for (ma = mnum + 1; ma < mnum + MON_PACK_SIZE; ma++) { - // assert(monsters[ma]._mleader == mnum || monsters[ma]._mhitpoints == 0); if (/*monsters[ma]._mleaderflag != MLEADER_NONE && */monsters[ma]._mleader == mnum) { monsters[ma]._mleaderflag = MLEADER_AWAY; } @@ -1759,7 +1758,6 @@ void MonUpdateLeader(int mnum) if (monsters[mnum]._mleaderflag == MLEADER_SELF) { // assert(mnum + MON_PACK_SIZE <= MAXMONSTERS); for (ma = mnum + 1; ma < mnum + MON_PACK_SIZE; ma++) { - // assert(monsters[ma]._mleader == mnum || monsters[ma]._mhitpoints == 0); if (/*monsters[ma]._mleaderflag != MLEADER_NONE && */monsters[ma]._mleader == mnum) { monsters[ma]._mleader = MON_NO_LEADER; monsters[ma]._mleaderflag = MLEADER_NONE; @@ -2816,9 +2814,8 @@ static void GroupUnity(int mnum) if (mon->_mpacksize != 0) { // assert(mnum + MON_PACK_SIZE <= MAXMONSTERS); for (ma = mnum + 1; ma < mnum + MON_PACK_SIZE; ma++) { - // assert(monsters[ma]._mleader == mnum || monsters[ma]._mhitpoints == 0); bmon = &monsters[ma]; - if (bmon->_mleaderflag == MLEADER_PRESENT/* && bmon->_mleader == mnum*/) { + if (bmon->_mleaderflag == MLEADER_PRESENT && bmon->_mleader == mnum) { if (mon->_msquelch > bmon->_msquelch) { bmon->_mlastx = mon->_mlastx; // BUGFIX: use _mlastx instead of _mx (fixed) bmon->_mlasty = mon->_mlasty; // BUGFIX: use _mlasty instead of _my (fixed) @@ -2857,8 +2854,7 @@ static bool MonDirOK(int mnum, int mdir) return true; // assert(mnum + MON_PACK_SIZE <= MAXMONSTERS); for (ma = mnum + 1; ma < mnum + MON_PACK_SIZE; ma++) { - // assert(monsters[ma]._mleader == mnum || monsters[ma]._mhitpoints == 0); - if (monsters[ma]._mleaderflag == MLEADER_PRESENT/* && monsters[ma]._mleader == mnum*/ + if (monsters[ma]._mleaderflag == MLEADER_PRESENT && monsters[ma]._mleader == mnum && abs(fx - monsters[ma]._mfutx) <= MON_PACK_DISTANCE && abs(fy - monsters[ma]._mfuty) <= MON_PACK_DISTANCE) { mcount--; From b7e62b96aef8f8ec1122e22626686337e3c1d6f9 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 31 Dec 2023 08:43:57 +0100 Subject: [PATCH 205/596] optimize PlaceUniqueMonst --- Source/monster.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index b6df3f3f09a..5d3d45450e8 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -970,10 +970,12 @@ static void PlaceUniqueMonst(int uniqindex, int mtidx) yp = themes[zharlib]._tsy1 + 4; break; default: - count = 0; + count = 1000; while (TRUE) { xp = random_(91, DSIZEX) + DBORDERX; yp = random_(91, DSIZEY) + DBORDERY; + if (!MonstPlace(xp, yp)) + continue; count2 = 0; static_assert(DBORDERX >= MON_PACK_DISTANCE, "PlaceUniqueMonst does not check IN_DUNGEON_AREA but expects a large enough border I."); static_assert(DBORDERY >= MON_PACK_DISTANCE, "PlaceUniqueMonst does not check IN_DUNGEON_AREA but expects a large enough border II."); @@ -986,15 +988,11 @@ static void PlaceUniqueMonst(int uniqindex, int mtidx) } if (count2 < 2 * MON_PACK_SIZE) { - count++; - if (count < 1000) { + if (--count != 0) { continue; } } - - if (MonstPlace(xp, yp)) { - break; - } + break; } } // assert(nummonsters < MAXMONSTERS); From f696c9bf95c71a1c118d934dfa1a707f04f59fa3 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 31 Dec 2023 08:53:17 +0100 Subject: [PATCH 206/596] prevent possible de-sync when a gargoyle is disturbed in the first turn after joining a level --- Source/monster.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 5d3d45450e8..eaaadec4c79 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3642,14 +3642,6 @@ void MAI_Garg(int mnum) mon = &monsters[mnum]; if (mon->_mFlags & MFLAG_GARG_STONE) { - if (MON_HAS_ENEMY) { - MonEnemyInfo(mnum); - // wake up if the enemy is close - if (currEnemyInfo._meRealDist < mon->_mAI.aiInt + 2) { - mon->_mFlags &= ~(MFLAG_LOCK_ANIMATION | MFLAG_GARG_STONE); - return; - } - } if (mon->_mmode != MM_SPATTACK) { // assert(mon->_mmode != MM_STONE); if (mon->_mleaderflag == MLEADER_NONE) { @@ -3659,6 +3651,13 @@ void MAI_Garg(int mnum) mon->_mFlags &= ~MFLAG_GARG_STONE; } } + if (MON_HAS_ENEMY) { + MonEnemyInfo(mnum); + // wake up if the enemy is close + if (currEnemyInfo._meRealDist < mon->_mAI.aiInt + 2) { + mon->_mFlags &= ~(MFLAG_LOCK_ANIMATION | MFLAG_GARG_STONE); + } + } return; } From db076db2ad3a742f66ac0e8ab79849fc1cc3a729 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 31 Dec 2023 09:03:35 +0100 Subject: [PATCH 207/596] add _dLevelBonus to LevelStruct --- Source/interfac.cpp | 16 +++++++++++----- Source/monster.cpp | 14 ++------------ structs.h | 1 + 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/Source/interfac.cpp b/Source/interfac.cpp index c42d5fe8dc9..67155677a75 100644 --- a/Source/interfac.cpp +++ b/Source/interfac.cpp @@ -255,16 +255,22 @@ void LoadGameLevel(int lvldir) void EnterLevel(BYTE lvl) { + int lvlBonus; + + currLvl._dLevelPlyrs = IsMultiGame ? gsDeltaData.ddLevelPlrs[lvl] : 1; currLvl._dLevelIdx = lvl; currLvl._dLevel = AllLevels[lvl].dLevel; currLvl._dSetLvl = AllLevels[lvl].dSetLvl; currLvl._dType = AllLevels[lvl].dType; currLvl._dDunType = AllLevels[lvl].dDunType; - if (gnDifficulty == DIFF_NIGHTMARE) - currLvl._dLevel += NIGHTMARE_LEVEL_BONUS; - else if (gnDifficulty == DIFF_HELL) - currLvl._dLevel += HELL_LEVEL_BONUS; - currLvl._dLevelPlyrs = IsMultiGame ? gsDeltaData.ddLevelPlrs[lvl] : 1; + lvlBonus = 0; + if (gnDifficulty == DIFF_NIGHTMARE) { + lvlBonus += NIGHTMARE_LEVEL_BONUS; + } else if (gnDifficulty == DIFF_HELL) { + lvlBonus += HELL_LEVEL_BONUS; + } + currLvl._dLevelBonus = lvlBonus; + currLvl._dLevel += lvlBonus; } /* diff --git a/Source/monster.cpp b/Source/monster.cpp index eaaadec4c79..519e5319ebd 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -337,12 +337,7 @@ static void InitMonsterStats(int midx) cmon->cmMinHP = mdata->mMinHP; cmon->cmMaxHP = mdata->mMaxHP; - lvlBonus = 0; - if (gnDifficulty == DIFF_NIGHTMARE) { - lvlBonus = NIGHTMARE_LEVEL_BONUS; - } else if (gnDifficulty == DIFF_HELL) { - lvlBonus = HELL_LEVEL_BONUS; - } + lvlBonus = currLvl._dLevelBonus; cmon->cmAI.aiInt += lvlBonus / 16; cmon->cmHit += lvlBonus * 5 / 2; @@ -896,12 +891,7 @@ static unsigned InitUniqueMonster(int mnum, int uniqindex) mon->_mEvasion += uniqm->mUnqEva; mon->_mArmorClass += uniqm->mUnqAC; - lvlBonus = 0; - if (gnDifficulty == DIFF_NIGHTMARE) { - lvlBonus = NIGHTMARE_LEVEL_BONUS; - } else if (gnDifficulty == DIFF_HELL) { - lvlBonus = HELL_LEVEL_BONUS; - } + lvlBonus = currLvl._dLevelBonus; mon->_mAI.aiInt += lvlBonus / 16; /*mon->_mHit += lvlBonus * 5 / 2; diff --git a/structs.h b/structs.h index 97f38b2c2d7..e078f5c79f2 100644 --- a/structs.h +++ b/structs.h @@ -2074,6 +2074,7 @@ typedef struct LevelStruct { int _dType; // cached type of the level (dungeon_type) int _dDunType; // cached type of the dungeon (dungeon_gen_type) int _dLevelPlyrs; // cached number of players when the level was 'initialized' + int _dLevelBonus; // cached level bonus } LevelStruct; typedef struct LevelFileData { From c8f41f84b8ff1f0faa7071217bd727d87a5dfd4a Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 31 Dec 2023 12:14:31 +0100 Subject: [PATCH 208/596] adjust price and durability of Full Plate Mails --- Source/itemdat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/itemdat.cpp b/Source/itemdat.cpp index a87536f9830..277f13a1c78 100644 --- a/Source/itemdat.cpp +++ b/Source/itemdat.cpp @@ -129,7 +129,7 @@ const ItemData AllItemsList[NUM_IDI] = { /* */ { "Plate Mail", 1, 24, UITYPE_PLATEMAIL, ICURS_FIELD_PLATE, ITYPE_HARMOR, IMISC_NONE, SPL_NULL, ICLASS_ARMOR, ILOC_ARMOR, IDAM_NONE, 0, 0, 0, 65, 0, 0, FALSE, 42, 50, 70, 4600, ALIGN }, /* */ { "Field Plate", 1, 26, UITYPE_NONE, ICURS_FIELD_PLATE, ITYPE_HARMOR, IMISC_NONE, SPL_NULL, ICLASS_ARMOR, ILOC_ARMOR, IDAM_NONE, 0, 0, 0, 80, 0, 0, FALSE, 40, 45, 75, 5800, ALIGN }, /* */ { "Gothic Plate", 1, 28, UITYPE_NONE, ICURS_GOTHIC_PLATE, ITYPE_HARMOR, IMISC_NONE, SPL_NULL, ICLASS_ARMOR, ILOC_ARMOR, IDAM_NONE, 0, 0, 0, 100, 0, 0, FALSE, 50, 60, 80, 8000, ALIGN }, -/* */ { "Full Plate Mail", 1, 30, UITYPE_FULLPLATE, ICURS_FULL_PLATE_MAIL, ITYPE_HARMOR, IMISC_NONE, SPL_NULL, ICLASS_ARMOR, ILOC_ARMOR, IDAM_NONE, 0, 0, 0, 120, 0, 0, FALSE, 60, 75, 75, 6500, ALIGN }, +/* */ { "Full Plate Mail", 1, 30, UITYPE_FULLPLATE, ICURS_FULL_PLATE_MAIL, ITYPE_HARMOR, IMISC_NONE, SPL_NULL, ICLASS_ARMOR, ILOC_ARMOR, IDAM_NONE, 0, 0, 0, 120, 0, 0, FALSE, 60, 75, 70, 7500, ALIGN }, /* */ { "Buckler", 1, 1, UITYPE_BUCKLER, ICURS_BUCKLER, ITYPE_SHIELD, IMISC_NONE, SPL_NULL, ICLASS_ARMOR, ILOC_ONEHAND, IDAM_NONE, 0, 0, 0, 0, 0, 0, FALSE, 1, 5, 16, 30, ALIGN }, /* */ { "Small Shield", 1, 5, UITYPE_SMALLSHIELD, ICURS_SMALL_SHIELD, ITYPE_SHIELD, IMISC_NONE, SPL_NULL, ICLASS_ARMOR, ILOC_ONEHAND, IDAM_NONE, 0, 0, 0, 25, 0, 0, FALSE, 3, 8, 24, 90, ALIGN }, /* */ { "Large Shield", 1, 9, UITYPE_LARGESHIELD, ICURS_LARGE_SHIELD, ITYPE_SHIELD, IMISC_NONE, SPL_NULL, ICLASS_ARMOR, ILOC_ONEHAND, IDAM_NONE, 0, 0, 0, 40, 0, 0, FALSE, 5, 10, 32, 200, ALIGN }, From 4fc7da975ad810a50da8d7b0e38f844e47130776 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 31 Dec 2023 12:21:08 +0100 Subject: [PATCH 209/596] adjust the price of unique items --- Source/itemdat.cpp | 48 +++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/Source/itemdat.cpp b/Source/itemdat.cpp index 277f13a1c78..4e6136140bc 100644 --- a/Source/itemdat.cpp +++ b/Source/itemdat.cpp @@ -464,47 +464,47 @@ const AffixData PL_Suffix[] = { const UniqItemData UniqueItemList[NUM_UITEM] = { // clang-format off // UIName, UIUniqType, UIMinLvl, UIValue, UIPower1, UIParam1a, UIParam1b, UIPower2, UIParam2a, UIParam2b, UIPower3, UIParam3a, UIParam3b, UIPower4, UIParam4a, UIParam4b, UIPower5, UIParam5a, UIParam5b, UIPower6, UIParam6a, UIParam6b, -/*UITEM_CLEAVER*/ { "Butcher's Cleaver", UITYPE_CLEAVER, 1, 3650, IPL_STR, 10, 10, IPL_SETDAM, 4, 24, IPL_SETDUR, 10, 10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_SKCROWN*/ { "The Undead Crown", UITYPE_SKCROWN, 1, 16650, IPL_STEALLIFE, 8, 8, IPL_SETAC, 8, 8, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_CLEAVER*/ { "Butcher's Cleaver", UITYPE_CLEAVER, 1, 5650, IPL_STR, 10, 10, IPL_SETDAM, 4, 24, IPL_SETDUR, 10, 10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_SKCROWN*/ { "The Undead Crown", UITYPE_SKCROWN, 1, 26650, IPL_STEALLIFE, 8, 8, IPL_SETAC, 8, 8, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_INFRARING*/ { "Empyrean Band", UITYPE_INFRARING, 1, 8000, IPL_ATTRIBS, 2, 2, IPL_LIGHT, 2, 2, IPL_FASTRECOVER, 1, 1, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_OPTAMULET*/ { "Optic Amulet", UITYPE_OPTAMULET, 1, 9750, IPL_LIGHT, 2, 2, IPL_LIGHTRES, 20, 20, IPL_GETHIT, 1, 1, IPL_MAG, 5, 5, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_TRING*/ { "Ring of Truth", UITYPE_TRING, 1, 9100, IPL_LIFE, 10, 10, IPL_GETHIT, 1, 1, IPL_ALLRES, 10, 10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_HARCREST*/ { "Harlequin Crest", UITYPE_HARCREST, 1, 4000, IPL_SETAC, 3, 3, IPL_GETHIT, 1, 1, IPL_ATTRIBS, 2, 2, IPL_LIFE, 7, 7, IPL_MANA, 7, 7, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_STEELVEIL*/ { "Veil of Steel", UITYPE_STEELVEIL, 1, 63800, IPL_ALLRES, 50, 50, IPL_LIGHT, -2, -2, IPL_SETAC, 20, 20, IPL_MANA, -30, -30, IPL_STR, 15, 15, IPL_VIT, 15, 15, ALIGN }, -/*UITEM_ARMOFVAL*/ { "Arkaine's Valor", UITYPE_ARMOFVAL, 1, 42000, IPL_SETAC, 25, 25, IPL_VIT, 10, 10, IPL_GETHIT, 3, 3, IPL_FASTRECOVER, 3, 3, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_GRISWOLD*/ { "Griswold's Edge", UITYPE_GRISWOLD, 1, 42000, IPL_FIREDAM, 1, 10, IPL_TOHIT, 25, 25, IPL_FASTATTACK, 2, 2, IPL_KNOCKBACK, 0, 0, IPL_MANA, 20, 20, IPL_LIFE, -20, -20, ALIGN }, +/*UITEM_ARMOFVAL*/ { "Arkaine's Valor", UITYPE_ARMOFVAL, 1, 24000, IPL_SETAC, 25, 25, IPL_VIT, 10, 10, IPL_GETHIT, 3, 3, IPL_FASTRECOVER, 3, 3, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_GRISWOLD*/ { "Griswold's Edge", UITYPE_GRISWOLD, 1, 22000, IPL_FIREDAM, 1, 10, IPL_TOHIT, 25, 25, IPL_FASTATTACK, 2, 2, IPL_KNOCKBACK, 0, 0, IPL_MANA, 20, 20, IPL_LIFE, -20, -20, ALIGN }, #ifdef HELLFIRE -/*UITEM_BOVINE*/ { "Bovine Plate", UITYPE_BOVINE, 1, 400, IPL_SETAC, 150, 150, IPL_INDESTRUCTIBLE, 0, 0, IPL_LIGHT, 5, 5, IPL_ALLRES, 30, 30, IPL_MANA, -50, -50, IPL_SKILLLEVELS, -2, -2, ALIGN }, +/*UITEM_BOVINE*/ { "Bovine Plate", UITYPE_BOVINE, 1, 40000, IPL_SETAC, 150, 150, IPL_INDESTRUCTIBLE, 0, 0, IPL_LIGHT, 5, 5, IPL_ALLRES, 30, 30, IPL_MANA, -50, -50, IPL_SKILLLEVELS, -2, -2, ALIGN }, #else /*UITEM_LGTFORGE*/ { "Lightforge", UITYPE_MACE, 1, 26675, IPL_LIGHT, 4, 4, IPL_DAMP, 150, 150, IPL_TOHIT, 25, 25, IPL_FIREDAM, 10, 20, IPL_INDESTRUCTIBLE, 0, 0, IPL_ATTRIBS, 8, 8, ALIGN }, #endif /*UITEM_RIFTBOW*/ { "The Rift Bow", UITYPE_SHORTBOW, 1, 1800, IPL_DAMMOD, 2, 2, IPL_DEX, -3, -3, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_NEEDLER*/ { "The Needler", UITYPE_SHORTBOW, 2, 8900, IPL_TOHIT, 50, 50, IPL_SETDAM, 1, 3, IPL_FASTATTACK, 2, 2, IPL_INVCURS, ICURS_THE_NEEDLER, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_CELESTBOW*/ { "The Celestial Bow", UITYPE_LONGBOW, 4, 1200, IPL_NOMINSTR, 0, 0, IPL_DAMMOD, 2, 2, IPL_SETAC, 5, 5, IPL_INVCURS, ICURS_COMPOSITE_BOW, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_CELESTBOW*/ { "The Celestial Bow", UITYPE_LONGBOW, 4, 4200, IPL_NOMINSTR, 0, 0, IPL_DAMMOD, 2, 2, IPL_SETAC, 5, 5, IPL_INVCURS, ICURS_COMPOSITE_BOW, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_DEADLYHUNT*/// { "Deadly Hunter", UITYPE_COMPBOW, 3, 8750, IPL_3XDAMVDEM, 10, 10, IPL_TOHIT, 20, 20, IPL_MAG, -5, -5, IPL_INVCURS, ICURS_BATTLE_BOW, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_BOWOFDEAD*/ { "Bow of the Dead", UITYPE_COMPBOW, 5, 2500, IPL_TOHIT, 10, 10, IPL_DEX, 4, 4, IPL_VIT, -3, -3, IPL_LIGHT, -2, -2, IPL_SETDUR, 30, 30, IPL_INVCURS, ICURS_BATTLE_BOW, 0, ALIGN }, -/*UITEM_BLKOAKBOW*/ { "The Blackoak Bow", UITYPE_LONGBOW, 10, 2500, IPL_DEX, 10, 10, IPL_VIT, -10, -10, IPL_DAMP, 50, 50, IPL_LIGHT, -1, -1, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_BLKOAKBOW*/ { "The Blackoak Bow", UITYPE_LONGBOW, 10, 2800, IPL_DEX, 10, 10, IPL_VIT, -10, -10, IPL_DAMP, 50, 50, IPL_LIGHT, -1, -1, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_FLAMEDART*/ { "Flamedart", UITYPE_HUNTBOW, 10, 14250, IPL_FIREDAM, 1, 6, IPL_TOHIT, 20, 20, IPL_FIRERES, 40, 40, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_FLESHSTING*/ { "Fleshstinger", UITYPE_LONGBOW, 26, 16500, IPL_DEX, 15, 15, IPL_TOHIT, 40, 40, IPL_DAMP, 80, 80, IPL_DUR, 6, 6, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_WINDFORCE*/ { "Windforce", UITYPE_WARBOW, 34, 37750, IPL_STR, 5, 5, IPL_DAMP, 200, 200, IPL_KNOCKBACK, 0, 0, IPL_INVCURS, ICURS_WINDFORCE, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_EAGLEHORN*/ { "Eaglehorn", UITYPE_BATTLEBOW, 42, 42500, IPL_DEX, 20, 20, IPL_TOHIT, 50, 50, IPL_DAMP, 100, 100, IPL_INDESTRUCTIBLE, 0, 0, IPL_INVCURS, ICURS_BATTLE_BOW, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_GONNAGALDIRK*/ { "Gonnagal's Dirk", UITYPE_DAGGER, 1, 7040, IPL_DEX, -5, -5, IPL_DAMMOD, 4, 4, IPL_FASTATTACK, 2, 2, IPL_FIRERES, 25, 25, IPL_INVCURS, ICURS_GONNAGAL_DIRK, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_DEFENDER*/ { "The Defender", UITYPE_SABRE, 4, 2000, IPL_SETAC, 5, 5, IPL_VIT, 5, 5, IPL_TOHIT, -5, -5, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_GRYPHONCLAW*/ { "Gryphon's Claw", UITYPE_FALCHION, 20, 1000, IPL_DAMP, 100, 100, IPL_MAG, -2, -2, IPL_DEX, -5, -5, IPL_INVCURS, ICURS_FALCON_GRYPHON, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_WINDFORCE*/ { "Windforce", UITYPE_WARBOW, 34, 137750, IPL_STR, 5, 5, IPL_DAMP, 200, 200, IPL_KNOCKBACK, 0, 0, IPL_INVCURS, ICURS_WINDFORCE, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_EAGLEHORN*/ { "Eaglehorn", UITYPE_BATTLEBOW, 42, 57500, IPL_DEX, 20, 20, IPL_TOHIT, 50, 50, IPL_DAMP, 100, 100, IPL_INDESTRUCTIBLE, 0, 0, IPL_INVCURS, ICURS_BATTLE_BOW, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_GONNAGALDIRK*/ { "Gonnagal's Dirk", UITYPE_DAGGER, 1, 9040, IPL_DEX, -5, -5, IPL_DAMMOD, 4, 4, IPL_FASTATTACK, 2, 2, IPL_FIRERES, 25, 25, IPL_INVCURS, ICURS_GONNAGAL_DIRK, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_DEFENDER*/ { "The Defender", UITYPE_SABRE, 4, 1600, IPL_SETAC, 5, 5, IPL_VIT, 5, 5, IPL_TOHIT, -5, -5, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_GRYPHONCLAW*/ { "Gryphon's Claw", UITYPE_FALCHION, 20, 7000, IPL_DAMP, 100, 100, IPL_MAG, -2, -2, IPL_DEX, -5, -5, IPL_INVCURS, ICURS_FALCON_GRYPHON, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_BLACKRAZOR*/ { "Black Razor", UITYPE_DAGGER, 1, 2000, IPL_DAMP, 150, 150, IPL_VIT, 2, 2, IPL_SETDUR, 5, 5, IPL_INVCURS, ICURS_BLACK_RAZOR, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_GIBBOUSMOON*/ { "Gibbous Moon", UITYPE_BROADSWR, 12, 6660, IPL_ATTRIBS, 2, 2, IPL_DAMP, 25, 25, IPL_MANA, 15, 15, IPL_LIGHT, -3, -3, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_ICESHANK*/ { "Ice Shank", UITYPE_LONGSWR, 12, 5250, IPL_FIRERES, 40, 40, IPL_SETDUR, 15, 15, IPL_STR, 5, 10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_EXECUTIONER*/ { "The Executioner's Blade", UITYPE_FALCHION, 35, 7080, IPL_DAMP, 150, 150, IPL_LIFE, -10, -10, IPL_LIGHT, -1, -1, IPL_DUR, 200, 200, IPL_INVCURS, ICURS_EXECUTIONER_BLADE, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_BONESAW*/ { "The Bonesaw", UITYPE_CLAYMORE, 14, 4400, IPL_DAMMOD, 10, 10, IPL_STR, 10, 10, IPL_MAG, -5, -5, IPL_DEX, -5, -5, IPL_LIFE, 10, 10, IPL_MANA, -10, -10, ALIGN }, +/*UITEM_EXECUTIONER*/ { "The Executioner's Blade", UITYPE_FALCHION, 35, 17080, IPL_DAMP, 150, 150, IPL_LIFE, -10, -10, IPL_LIGHT, -1, -1, IPL_DUR, 200, 200, IPL_INVCURS, ICURS_EXECUTIONER_BLADE, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_BONESAW*/ { "The Bonesaw", UITYPE_CLAYMORE, 14, 34400, IPL_DAMMOD, 10, 10, IPL_STR, 10, 10, IPL_MAG, -5, -5, IPL_DEX, -5, -5, IPL_LIFE, 10, 10, IPL_MANA, -10, -10, ALIGN }, /*UITEM_SHADHAWK*/ { "Shadowhawk", UITYPE_BROADSWR, 16, 13750, IPL_LIGHT, -2, -2, IPL_STEALLIFE, 6, 6, IPL_TOHIT, 15, 15, IPL_ALLRES, 5, 5, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_WIZSPIKE*/ { "Wizardspike", UITYPE_DAGGER, 11, 12920, IPL_MAG, 15, 15, IPL_MANA, 35, 35, IPL_TOHIT, 25, 25, IPL_ALLRES, 15, 15, IPL_INVCURS, ICURS_WIZARDSPIKE, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_LGTSABRE*/ { "Lightsabre", UITYPE_SABRE, 13, 19150, IPL_LIGHT, 2, 2, IPL_LIGHTDAM, 1, 10, IPL_TOHIT, 20, 20, IPL_LIGHTRES, 50, 50, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_FALCONTALON*/ { "The Falcon's Talon", UITYPE_SCIMITAR, 15, 7867, IPL_FASTATTACK, 4, 4, IPL_TOHIT, 20, 20, IPL_DAMP, -33, -33, IPL_DEX, 10, 10, IPL_INVCURS, ICURS_FALCON_GRYPHON, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_INFERNO*/ { "Inferno", UITYPE_LONGSWR, 17, 34600, IPL_FIREDAM, 2, 12, IPL_LIGHT, 3, 3, IPL_MANA, 20, 20, IPL_FIRERES, 80, 80, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_DOOMBRINGER*/ { "Doombringer", UITYPE_BASTARDSWR, 38, 18250, IPL_TOHIT, 25, 25, IPL_DAMP, 250, 250, IPL_ATTRIBS, -5, -5, IPL_LIFE, -25, -25, IPL_LIGHT, -2, -2, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_GRIZZLY*/ { "The Grizzly", UITYPE_TWOHANDSWR, 23, 50000, IPL_STR, 20, 20, IPL_VIT, -5, -5, IPL_DAMP, 200, 200, IPL_KNOCKBACK, 0, 0, IPL_DUR, 100, 100, IPL_INVCURS, ICURS_THE_GRIZZLY, 0, ALIGN }, +/*UITEM_DOOMBRINGER*/ { "Doombringer", UITYPE_BASTARDSWR, 38, 68250, IPL_TOHIT, 25, 25, IPL_DAMP, 250, 250, IPL_ATTRIBS, -5, -5, IPL_LIFE, -25, -25, IPL_LIGHT, -2, -2, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_GRIZZLY*/ { "The Grizzly", UITYPE_TWOHANDSWR, 23, 112100, IPL_STR, 20, 20, IPL_VIT, -5, -5, IPL_DAMP, 200, 200, IPL_KNOCKBACK, 0, 0, IPL_DUR, 100, 100, IPL_INVCURS, ICURS_THE_GRIZZLY, 0, ALIGN }, /*UITEM_GRANDFATHER*/ { "The Grandfather", UITYPE_GREATSWR, 27, 119800, IPL_ONEHAND, 0, 0, IPL_ATTRIBS, 5, 5, IPL_TOHIT, 20, 20, IPL_DAMP, 70, 70, IPL_LIFE, 20, 20, IPL_INVCURS, ICURS_THE_GRANDFATHER, 0, ALIGN }, -/*UITEM_MANGLER*/ { "The Mangler", UITYPE_LARGEAXE, 35, 2850, IPL_DAMP, 200, 200, IPL_DEX, -5, -5, IPL_MAG, -5, -5, IPL_MANA, -10, -10, IPL_INVCURS, ICURS_AXE, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_MANGLER*/ { "The Mangler", UITYPE_LARGEAXE, 35, 49688, IPL_DAMP, 200, 200, IPL_DEX, -5, -5, IPL_MAG, -5, -5, IPL_MANA, -10, -10, IPL_INVCURS, ICURS_AXE, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_SHARPBEAK*/ { "Sharp Beak", UITYPE_LARGEAXE, 16, 2850, IPL_LIFE, 20, 20, IPL_MAG, -10, -10, IPL_MANA, -10, -10, IPL_INVCURS, ICURS_GREAT_AXE, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_BLOODLSLAYER*///{ "BloodSlayer", UITYPE_BROADAXE, 3, 2500, IPL_DAMP, 100, 100, IPL_3XDAMVDEM, 50, 50, IPL_ATTRIBS, -5, -5, IPL_SKILLLEVELS, -1, -1, IPL_INVCURS, ICURS_AXE, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_CELESTAXE*/ { "The Celestial Axe", UITYPE_BATTLEAXE, 12, 14100, IPL_NOMINSTR, 0, 0, IPL_TOHIT, 15, 15, IPL_LIFE, 15, 15, IPL_STR, -15, -15, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, @@ -512,17 +512,17 @@ const UniqItemData UniqueItemList[NUM_UITEM] = { /*UITEM_STONECLEAV*/ { "Stonecleaver", UITYPE_BROADAXE, 20, 23900, IPL_LIFE, 30, 30, IPL_TOHIT, 20, 20, IPL_DAMP, 50, 50, IPL_LIGHTRES, 40, 40, IPL_INVCURS, ICURS_STONECLEAVER, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_AGUHATCHET*/ { "Aguinara's Hatchet", UITYPE_SMALLAXE, 12, 24800, IPL_SKILLLEVELS, 1, 1, IPL_MAG, 10, 10, IPL_MAGICRES, 80, 80, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_HELLSLAYER*/ { "Hellslayer", UITYPE_BATTLEAXE, 30, 26200, IPL_STR, 8, 8, IPL_VIT, 8, 8, IPL_DAMP, 100, 100, IPL_LIFE, 25, 25, IPL_MANA, -25, -25, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_MESSERREAVER*/ { "Messerschmidt's Reaver", UITYPE_GREATAXE, 50, 58000, IPL_DAMP, 200, 200, IPL_DAMMOD, 15, 15, IPL_ATTRIBS, 5, 5, IPL_LIFE, -50, -50, IPL_FIREDAM, 2, 12, IPL_INVCURS, ICURS_MESSERSCHMIDT, 0, ALIGN }, +/*UITEM_MESSERREAVER*/ { "Messerschmidt's Reaver", UITYPE_GREATAXE, 50, 158000, IPL_DAMP, 200, 200, IPL_DAMMOD, 15, 15, IPL_ATTRIBS, 5, 5, IPL_LIFE, -50, -50, IPL_FIREDAM, 2, 12, IPL_INVCURS, ICURS_MESSERSCHMIDT, 0, ALIGN }, /*UITEM_CRACKRUST*/ { "Crackrust", UITYPE_MACE, 8, 11375, IPL_ATTRIBS, 2, 2, IPL_INDESTRUCTIBLE, 0, 0, IPL_ALLRES, 15, 15, IPL_DAMP, 50, 50, IPL_SKILLLEVELS, -1, -1, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_JHOLMHAMM*/ { "Hammer of Jholm", UITYPE_MAUL, 12, 8700, IPL_DAMP, 4, 10, IPL_INDESTRUCTIBLE, 0, 0, IPL_STR, 3, 3, IPL_TOHIT, 15, 15, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_CIVERBS*/// { "Civerb's Cudgel", UITYPE_MACE, 1, 2000, IPL_3XDAMVDEM, 35, 35, IPL_DEX, -5, -5, IPL_MAG, -2, -2, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_CELESTSTAR*/ { "The Celestial Star", UITYPE_FLAIL, 14, 7810, IPL_NOMINSTR, 0, 0, IPL_LIGHT, 2, 2, IPL_DAMMOD, 10, 10, IPL_ACMOD, -8, -8, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_CELESTSTAR*/ { "The Celestial Star", UITYPE_FLAIL, 14, 17810, IPL_NOMINSTR, 0, 0, IPL_LIGHT, 2, 2, IPL_DAMMOD, 10, 10, IPL_ACMOD, -8, -8, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_BARANSTAR*/ { "Baranar's Star", UITYPE_MORNSTAR, 14, 6850, IPL_TOHIT, 12, 12, IPL_DAMP, 80, 80, IPL_FASTATTACK, 1, 1, IPL_VIT, 4, 4, IPL_DEX, -4, -4, IPL_SETDUR, 60, 60, ALIGN }, -/*UITEM_GNARLROOT*/ { "Gnarled Root", UITYPE_SPIKCLUB, 16, 9820, IPL_TOHIT, 20, 20, IPL_DAMP, 300, 300, IPL_DEX, 10, 10, IPL_MAG, 5, 5, IPL_ALLRES, 10, 10, IPL_ACMOD, -10, -10, ALIGN }, +/*UITEM_GNARLROOT*/ { "Gnarled Root", UITYPE_SPIKCLUB, 16, 49820, IPL_TOHIT, 20, 20, IPL_DAMP, 300, 300, IPL_DEX, 10, 10, IPL_MAG, 5, 5, IPL_ALLRES, 10, 10, IPL_ACMOD, -10, -10, ALIGN }, /*UITEM_CRANBASH*/ { "The Cranium Basher", UITYPE_MAUL, 16, 36500, IPL_DAMMOD, 20, 20, IPL_STR, 15, 15, IPL_INDESTRUCTIBLE, 0, 0, IPL_MANA, -150, -150, IPL_ALLRES, 5, 5, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_SCHAEFHAMM*/ { "Schaefer's Hammer", UITYPE_WARHAMMER, 16, 56125, IPL_DAMP, -100, -100, IPL_LIGHTDAM, 1, 50, IPL_LIFE, 50, 50, IPL_TOHIT, 30, 30, IPL_LIGHTRES, 80, 80, IPL_LIGHT, 1, 1, ALIGN }, /*UITEM_DREAMFLANGE*/ { "Dreamflange", UITYPE_MACE, 26, 26450, IPL_MAG, 30, 30, IPL_MANA, 50, 50, IPL_MAGICRES, 50, 50, IPL_LIGHT, 2, 2, IPL_SKILLLEVELS, 1, 1, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_STAFFOFSHAD*/ { "Staff of Shadows", UITYPE_LONGSTAFF, 4, 1250, IPL_MAG, -10, -10, IPL_TOHIT, 10, 10, IPL_DAMP, 60, 60, IPL_LIGHT, -2, -2, IPL_FASTATTACK, 1, 1, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_STAFFOFSHAD*/ { "Staff of Shadows", UITYPE_LONGSTAFF, 4, 4250, IPL_MAG, -10, -10, IPL_TOHIT, 10, 10, IPL_DAMP, 60, 60, IPL_LIGHT, -2, -2, IPL_FASTATTACK, 1, 1, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_IMMOLATOR*/ { "Immolator", UITYPE_LONGSTAFF, 6, 3900, IPL_FIRERES, 20, 20, IPL_FIREDAM, 4, 4, IPL_MANA, 10, 10, IPL_VIT, -5, -5, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_STORMSPIRE*/ { "Storm Spire", UITYPE_WARSTAFF, 20, 22500, IPL_LIGHTRES, 50, 50, IPL_LIGHTDAM, 2, 8, IPL_STR, 10, 10, IPL_MAG, -10, -10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_GLEAMSONG*/ { "Gleamsong", UITYPE_SHORTSTAFF, 8, 6520, IPL_MANA, 25, 25, IPL_STR, -3, -3, IPL_VIT, -3, -3, IPL_SPELL, SPL_RNDTELEPORT, 76, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, @@ -531,10 +531,10 @@ const UniqItemData UniqueItemList[NUM_UITEM] = { /*UITEM_NAJPUZZLE*/ { "Naj's Puzzler", UITYPE_LONGSTAFF, 18, 34000, IPL_MAG, 20, 20, IPL_DEX, 10, 10, IPL_ALLRES, 20, 20, IPL_SPELL, SPL_TELEPORT, 57, IPL_LIFE, -25, -25, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_MINDCRY*/ { "Mindcry", UITYPE_QUARSTAFF, 20, 41500, IPL_MAG, 15, 15, IPL_SPELL, SPL_GUARDIAN, 69, IPL_ALLRES, 15, 15, IPL_SKILLLEVELS, 1, 1, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_RODOFONAN*/ { "Rod of Onan", UITYPE_WARSTAFF, 22, 44167, IPL_SPELL, SPL_GOLEM, 50, IPL_DAMP, 100, 100, IPL_ATTRIBS, 5, 5, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_SPIRITSHELM*/ { "Helm of Spirits", UITYPE_HELM, 1, 7525, IPL_STEALLIFE, 6, 6, IPL_INVCURS, ICURS_HELM_OF_SPIRITS, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_SPIRITSHELM*/ { "Helm of Spirits", UITYPE_HELM, 1, 17525, IPL_STEALLIFE, 6, 6, IPL_INVCURS, ICURS_HELM_OF_SPIRITS, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_THINKINGCAP*/ { "Thinking Cap", UITYPE_SKULLCAP, 6, 2020, IPL_MANA, 30, 30, IPL_SKILLLEVELS, 2, 2, IPL_ALLRES, 20, 20, IPL_SETDUR, 1, 1, IPL_INVCURS, ICURS_THINKING_CAP, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_OVERLORDHELM*/ { "OverLord's Helm", UITYPE_HELM, 7, 12500, IPL_STR, 20, 20, IPL_DEX, 15, 15, IPL_VIT, 5, 5, IPL_MAG, -20, -20, IPL_SETDUR, 15, 15, IPL_INVCURS, ICURS_OVERLORD_HELM, 0, ALIGN }, -/*UITEM_FOOLSCREST*/ { "Fool's Crest", UITYPE_HELM, 12, 10150, IPL_STR, -4, -4, IPL_LIFE, 100, 100, IPL_GETHIT, -6, -1, IPL_DEX, 5, 10, IPL_MAG, -8, -8, IPL_INVCURS, ICURS_FOOL_CREST, 0, ALIGN }, +/*UITEM_FOOLSCREST*/ { "Fool's Crest", UITYPE_HELM, 12, 20150, IPL_STR, -4, -4, IPL_LIFE, 100, 100, IPL_GETHIT, -6, -1, IPL_DEX, 5, 10, IPL_MAG, -8, -8, IPL_INVCURS, ICURS_FOOL_CREST, 0, ALIGN }, /*UITEM_GOTTERDAM*/ { "Gotterdamerung", UITYPE_GREATHELM, 21, 54900, IPL_ATTRIBS, 20, 20, IPL_SETAC, 60, 60, IPL_GETHIT, 4, 4, IPL_ALLRESZERO, 0, 0, IPL_LIGHT, -4, -4, IPL_INVCURS, ICURS_VEIL_OF_STEEL, 0, ALIGN }, /*UITEM_ROYCIRCLET*/ { "Royal Circlet", UITYPE_CROWN, 27, 24875, IPL_ATTRIBS, 10, 10, IPL_MANA, 40, 40, IPL_SETAC, 40, 40, IPL_LIGHT, 1, 1, IPL_INVCURS, ICURS_ROYAL_CIRCLET, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_TORNFLESH*/ { "Torn Flesh of Souls", UITYPE_RAGS, 2, 4825, IPL_SETAC, 8, 8, IPL_VIT, 10, 10, IPL_GETHIT, 1, 1, IPL_INDESTRUCTIBLE, 0, 0, IPL_INVCURS, ICURS_FLESH_OF_SOULS, 0, IPL_INVALID, 0, 0, ALIGN }, @@ -543,7 +543,7 @@ const UniqItemData UniqueItemList[NUM_UITEM] = { /*UITEM_LEATHAUT*/ { "Leather of Aut", UITYPE_LEATHARMOR, 4, 10550, IPL_SETAC, 15, 15, IPL_STR, 5, 5, IPL_MAG, -5, -5, IPL_DEX, 5, 5, IPL_INDESTRUCTIBLE, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_WISDWRAP*/ { "Wisdom's Wrap", UITYPE_ROBE, 5, 6200, IPL_MAG, 5, 5, IPL_MANA, 10, 10, IPL_LIGHTRES, 25, 25, IPL_SETAC, 15, 15, IPL_GETHIT, 1, 1, IPL_INVCURS, ICURS_UCLOAK, 0, ALIGN }, /*UITEM_SPARKMAIL*/ { "Sparking Mail", UITYPE_CHAINMAIL, 9, 15750, IPL_SETAC, 30, 30, IPL_LIGHTDAM, 1, 10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_SCAVCARAP*/ { "Scavenger Carapace", UITYPE_BREASTPLATE, 13, 14000, IPL_GETHIT, 15, 15, IPL_ACMOD, -30, -30, IPL_DEX, 5, 5, IPL_LIGHTRES, 40, 40, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_SCAVCARAP*/ { "Scavenger Carapace", UITYPE_BREASTPLATE, 13, 34000, IPL_GETHIT, 15, 15, IPL_ACMOD, -30, -30, IPL_DEX, 5, 5, IPL_LIGHTRES, 40, 40, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_NIGHTSCAPE*/ { "Nightscape", UITYPE_CAPE, 16, 11600, IPL_FASTRECOVER, 2, 2, IPL_LIGHT, -4, -4, IPL_SETAC, 15, 15, IPL_DEX, 3, 3, IPL_ALLRES, 20, 20, IPL_INVCURS, ICURS_UCLOAK, 0, ALIGN }, /*UITEM_NAJPLATE*/ { "Naj's Light Plate", UITYPE_PLATEMAIL, 19, 78700, IPL_NOMINSTR, 0, 0, IPL_MAG, 5, 5, IPL_MANA, 20, 20, IPL_ALLRES, 20, 20, IPL_SKILLLEVELS, 1, 1, IPL_INVCURS, ICURS_NAJ_PLATE, 0, ALIGN }, /*UITEM_DEMONSPIKE*/ { "Demonspike Coat", UITYPE_FULLPLATE, 25, 251175, IPL_SETAC, 100, 100, IPL_GETHIT, 6, 6, IPL_STR, 10, 10, IPL_INDESTRUCTIBLE, 0, 0, IPL_FIRERES, 50, 50, IPL_INVALID, 0, 0, ALIGN }, From 33515d2b0f4fc0a780381d5615b3e2abfa709b70 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 31 Dec 2023 12:31:26 +0100 Subject: [PATCH 210/596] ensure there is enough connected tiles when placing the group of unique monsters --- Source/monster.cpp | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 519e5319ebd..d2b4fad2666 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -946,6 +946,30 @@ static unsigned InitUniqueMonster(int mnum, int uniqindex) return flags; } +#define MON_PACK_AREA (1 + 2 * MON_PACK_DISTANCE) +#define MON_PACK_SPACE 8 +static_assert(MON_PACK_AREA <= MON_PACK_SPACE, "Not enough space to search for monster placement."); +static int MonPackSpace(int dx, int dy, int px, int py, bool (&visited)[MON_PACK_SPACE][MON_PACK_SPACE]) +{ + int result = 0; + + if (!visited[px][py]) { + visited[px][py] = true; + if (MonstPlace(dx, dy)) { + result = 1; + if (px != 0) + result += MonPackSpace(dx - 1, dy, px - 1, py, visited); + if (px != MON_PACK_AREA - 1) + result += MonPackSpace(dx + 1, dy, px + 1, py, visited); + if (py != 0) + result += MonPackSpace(dx, dy - 1, px, py - 1, visited); + if (py != MON_PACK_AREA - 1) + result += MonPackSpace(dx, dy + 1, px, py + 1, visited); + } + } + return result; +} + static void PlaceUniqueMonst(int uniqindex, int mtidx) { int xp, yp, x, y; @@ -964,21 +988,12 @@ static void PlaceUniqueMonst(int uniqindex, int mtidx) while (TRUE) { xp = random_(91, DSIZEX) + DBORDERX; yp = random_(91, DSIZEY) + DBORDERY; - if (!MonstPlace(xp, yp)) - continue; - count2 = 0; static_assert(DBORDERX >= MON_PACK_DISTANCE, "PlaceUniqueMonst does not check IN_DUNGEON_AREA but expects a large enough border I."); static_assert(DBORDERY >= MON_PACK_DISTANCE, "PlaceUniqueMonst does not check IN_DUNGEON_AREA but expects a large enough border II."); - for (x = xp - MON_PACK_DISTANCE; x <= xp + MON_PACK_DISTANCE; x++) { - for (y = yp - MON_PACK_DISTANCE; y <= yp + MON_PACK_DISTANCE; y++) { - if (MonstPlace(x, y)) { - count2++; - } - } - } - + bool visited[MON_PACK_SPACE][MON_PACK_SPACE] = { 0 }; + count2 = MonPackSpace(xp, yp, MON_PACK_DISTANCE, MON_PACK_DISTANCE, visited); if (count2 < 2 * MON_PACK_SIZE) { - if (--count != 0) { + if (count2 == 0 || --count != 0) { continue; } } From 7c606e040ee8e79ebf98eb97e5bd983e1f84e982 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 31 Dec 2023 15:53:08 +0100 Subject: [PATCH 211/596] check if each unique have a base type --- Source/debug.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Source/debug.cpp b/Source/debug.cpp index 4e94fd84531..10161110f3a 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -1019,6 +1019,13 @@ void ValidateData() app_fatal("Invalid UIParam6 set for '%s' %d.", ui.UIName, i); } } + int n = 0; + for ( ; n < NUM_IDI; n++) { + if (AllItemsList[n].iUniqType == ui.UIUniqType) + break; + } + if (n == NUM_IDI) + app_fatal("Missing base type for '%s' %d.", ui.UIName, i); } assert(itemfiledata[ItemCAnimTbl[ICURS_MAGIC_ROCK]].iAnimLen == 10); // required by ProcessItems // objects From 729719a1ad26f5be99dab4497dc2e56bc5ca9149 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 1 Jan 2024 10:26:54 +0100 Subject: [PATCH 212/596] test if MFLAG_GARG_STONE is supported by the monster-AI --- Source/debug.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Source/debug.cpp b/Source/debug.cpp index 10161110f3a..d10aa219d2b 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -267,6 +267,12 @@ void ValidateData() app_fatal("AI_CLEAVER, AI_FAT and AI_BAT only check the doors while searching (%s, %d)", md.mName, i); if (md.mAI.aiType == AI_GARG && !(md.mFlags & MFLAG_NOSTONE)) app_fatal("AI_GARG might override stoned state (%s, %d)", md.mName, i); // required by MAI_Garg + if (md.mFlags & MFLAG_GARG_STONE) { + if (md.mFlags & MFLAG_HIDDEN) + app_fatal("Both GARG_STONE and HIDDEN flags are set for %s (%d).", md.mName, i); // required ProcessMonsters + if (md.mAI.aiType != AI_GARG) + app_fatal("GARG_STONE flag is not supported by the AI of %s (%d).", md.mName, i); + } if (md.mAI.aiInt > UINT8_MAX - HELL_LEVEL_BONUS / 16) // required by InitMonsterStats app_fatal("Too high aiInt %d for %s (%d).", md.mLevel, md.mName, i); if (md.mLevel == 0) // required by InitMonsterStats @@ -277,8 +283,6 @@ void ValidateData() app_fatal("Invalid mLevel %d for %s (%d). Too high to set the level of item-drop.", md.mLevel, md.mName, i); if (md.moFileNum == MOFILE_DIABLO && !(md.mFlags & MFLAG_NOCORPSE)) app_fatal("MOFILE_DIABLO does not have corpse animation but MFLAG_NOCORPSE is not set for %s (%d).", md.mName, i); - if ((md.mFlags & MFLAG_GARG_STONE) && (md.mFlags & MFLAG_HIDDEN)) - app_fatal("Both GARG_STONE and HIDDEN flags are set for %s (%d).", md.mName, i); // required ProcessMonsters #if DEBUG_MODE if (md.mHit > INT_MAX /*- HELL_TO_HIT_BONUS */- HELL_LEVEL_BONUS * 5 / 2) // required by InitMonsterStats app_fatal("Too high mHit %d for %s (%d).", md.mHit, md.mName, i); @@ -1275,8 +1279,8 @@ void LogErrorF(const char* msg, ...) using namespace std::chrono; milliseconds ms = duration_cast(system_clock::now().time_since_epoch()); - //snprintf(tmp, sizeof(tmp), " @ %llu", ms.count()); - snprintf(tmp, sizeof(tmp), " @ %u", gdwGameLogicTurn); + snprintf(tmp, sizeof(tmp), " @ %llu", ms.count()); + // snprintf(tmp, sizeof(tmp), " @ %u", gdwGameLogicTurn); fputs(tmp, f0); fputc('\n', f0); From 352ef6701c44afdc050e2b0cd1be96d0d6588c8f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Jan 2024 08:32:54 +0100 Subject: [PATCH 213/596] Bump lukka/run-vcpkg from 11.3 to 11.4 (#5) Bumps [lukka/run-vcpkg](https://github.com/lukka/run-vcpkg) from 11.3 to 11.4. - [Release notes](https://github.com/lukka/run-vcpkg/releases) - [Commits](https://github.com/lukka/run-vcpkg/compare/v11.3...v11.4) --- updated-dependencies: - dependency-name: lukka/run-vcpkg dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/nightly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index b75f9537b4e..97e49f72cbf 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -72,7 +72,7 @@ jobs: # Download and build vcpkg, without installing any port. If content is cached already, it is a no-op. - name: Create Build Environment - uses: lukka/run-vcpkg@v11.3 + uses: lukka/run-vcpkg@v11.4 with: vcpkgGitCommitId: '927bc12e31148b0d44ae9d174b96c20e3bcf08eb' #setupOnly: true From 1becc4829d2f8769a08485d66c9a540b85110210 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 2 Jan 2024 14:32:02 +0100 Subject: [PATCH 214/596] bugfix for 'update enemy even if the monster has already one (but prefer the original target)' --- Source/monster.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index d2b4fad2666..0ee093c3376 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1387,7 +1387,7 @@ static void MonFindEnemy(int mnum) if (dist > best_dist) continue; if (dist == best_dist) { - if (mon->_menemyy != i || (mon->_mFlags & MFLAG_TARGETS_MONSTER)) + if (mon->_menemy != i || (mon->_mFlags & MFLAG_TARGETS_MONSTER)) continue; } } else if (!sameroom) @@ -1419,7 +1419,7 @@ static void MonFindEnemy(int mnum) if (dist > best_dist) continue; if (dist == best_dist) { - if (mon->_menemyy != i || !(mon->_mFlags & (MFLAG_TARGETS_MONSTER))) + if (mon->_menemy != i || !(mon->_mFlags & (MFLAG_TARGETS_MONSTER))) continue; } } else if (!sameroom) @@ -1458,7 +1458,7 @@ static void MonFindEnemy(int mnum) if (dist > best_dist) continue; if (dist == best_dist) { - if (mon->_menemyy != tnum/* || !(mon->_mFlags & (MFLAG_TARGETS_MONSTER))*/) + if (mon->_menemy != tnum/* || !(mon->_mFlags & (MFLAG_TARGETS_MONSTER))*/) continue; } } else if (!sameroom) From 463d92c46d5819bffe7d7a8a1ca5c32dbbdbe144 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 2 Jan 2024 14:39:05 +0100 Subject: [PATCH 215/596] adjust the handling of town-portals - let players 'use' portals even if dead to reduce the chance of de-sync - use RemovePortalMissile in AddTown to 'close' previous portals --- Source/missiles.cpp | 20 ++++++-------------- Source/msg.cpp | 3 +-- Source/portal.cpp | 4 ++-- 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 52cd6fd02db..4a8cddc05c8 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -2367,9 +2367,9 @@ static bool CheckIfTrig(int x, int y) */ int AddTown(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { - MissileStruct* mis; int i, j, tx, ty; const int8_t* cr; + // assert((unsigned)misource < MAX_PLRS); // the position of portals in town and recreated portals are fixed if (currLvl._dType != DTYPE_TOWN && spllvl >= 0) { const int RANGE = 6; @@ -2395,11 +2395,9 @@ int AddTown(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int ty = dy; } // 'delete' previous portal of the misource - for (i = 0; i < nummissiles; i++) { - mis = &missile[missileactive[i]]; - if (mis->_miType == MIS_TOWN && mis->_miSource == misource) - mis->_miRange = -1; - } + // assert(!missile[mi]._miDelFlag); + RemovePortalMissile(misource); + missile[mi]._miDelFlag = FALSE; // revert delete flag of the current missile // setup the new portal return AddPortal(mi, 0, 0, tx, ty, 0, 0, misource, spllvl); } @@ -2414,7 +2412,6 @@ int AddPortal(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, i mis = &missile[mi]; mis->_mix = mis->_misx = dx; mis->_miy = mis->_misy = dy; - mis->_miRange = 1; mis->_miLid = AddLight(dx, dy, spllvl >= 0 ? 1 : 15); if (spllvl >= 0) { PlaySfxLoc(LS_SENTINEL, dx, dy); @@ -4024,13 +4021,9 @@ void MI_Portal(int mi) MissileStruct* mis; static_assert(MAX_LIGHT_RAD >= 15, "MI_Portal needs at least light-radius of 15."); int ExpLight[17] = { 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15 }; - PlayerStruct* p; mis = &missile[mi]; - if (mis->_miRange < 0) { - mis->_miDelFlag = TRUE; // + AddUnLight - return; - } + // assert(!mis->_miDelFlag); if (mis->_miDir == 0) { // assert(mis->_miAnimLen < lengthof(ExpLight)); // assert(misfiledata[MFILE_RPORTAL].mfAnimLen[0] < lengthof(ExpLight)); @@ -4046,8 +4039,7 @@ void MI_Portal(int mi) } if (mis->_miType == MIS_TOWN) { - p = &myplr; - if (p->_px == mis->_mix && p->_py == mis->_miy && /*!p->_pLvlChanging &&*/ p->_pmode == PM_STAND && !mis->_miVar3) { + if (myplr._px == mis->_mix && myplr._py == mis->_miy && /*!myplr._pLvlChanging &&*/ myplr._pmode == PM_STAND && !mis->_miVar3) { mis->_miVar3 = TRUE; NetSendCmdBParam1(CMD_USEPORTAL, mis->_miSource); } diff --git a/Source/msg.cpp b/Source/msg.cpp index 0b75fe76c61..b6fe92e1bb9 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -2702,8 +2702,7 @@ static unsigned On_USEPORTAL(TCmd* pCmd, int pnum) net_assert(idx < MAX_PLRS); - if (plr._pmode != PM_DEATH) - UseTownPortal(pnum, idx); + UseTownPortal(pnum, idx); return sizeof(*cmd); } diff --git a/Source/portal.cpp b/Source/portal.cpp index a14efbea197..92c60c23dc9 100644 --- a/Source/portal.cpp +++ b/Source/portal.cpp @@ -80,8 +80,8 @@ void RemovePortalMissile(int pidx) MissileStruct* mis; int i; - if (!PortalOnLevel(pidx)) - return; + //if (!PortalOnLevel(pidx)) - skip test because portals and missiles might be out of sync temporary + // return; static_assert(MAXPORTAL == MAX_PLRS, "RemovePortalMissile finds portal-missiles by portal-id."); for (i = 0; i < nummissiles; i++) { From 68d814fcb96d4a07a1c525c8c2ea9d790043894b Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 2 Jan 2024 15:45:19 +0100 Subject: [PATCH 216/596] bugfix for 'ensure minions leave no loot (or corpse)' - fix vision maintenance - fix mFlags of the minions --- Source/monster.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 0ee093c3376..4214f3c5ea4 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -475,6 +475,7 @@ void InitLvlMonsters() nummonsters = MAX_MINIONS; if (currLvl._dLevelIdx != DLV_TOWN) { AddMonsterType(MT_GOLEM, FALSE); + mapMonTypes[0].cmFlags |= MFLAG_NOCORPSE | MFLAG_NODROP; for (i = 0; i < MAX_MINIONS; i++) { InitMonster(i, 0, 0, 0, 0); monsters[i]._mmode = MM_RESERVED; @@ -2148,11 +2149,11 @@ static void MonInitKill(int mnum, int mpnum, bool sendmsg) static_assert(MAXMONSTERS <= UCHAR_MAX, "MonInitKill uses mnum as pnum, which must fit to BYTE."); NetSendCmdMonstKill(mnum, mpnum); } - // if (mnum >= MAX_MINIONS) { + // if (mnum < MAX_MINIONS) { + AddUnVision(mon->_mvid); + //} else { MonUpdateLeader(mnum); SpawnLoot(mnum, sendmsg); - //} else { - AddUnVision(mon->_mvid); // } if (mon->_mType == MT_DIABLO) @@ -5010,7 +5011,7 @@ void SpawnGolem(int mnum, int x, int y, int level) mon = &monsters[mnum]; mon->_mhitpoints = mon->_mmaxhp; mon->_mvid = AddVision(x, y, PLR_MIN_VISRAD, false); - mon->_mFlags |= MFLAG_NOCORPSE | MFLAG_NODROP; + // assert((mon->_mFlags & (MFLAG_NOCORPSE | MFLAG_NODROP)) == (MFLAG_NOCORPSE | MFLAG_NODROP)); ActivateSpawn(mnum, x, y, DIR_S); if (mnum == mypnum) NetSendCmdGolem(); From 31c01bf231aedbec4190e3980bd98e56788960ab Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 2 Jan 2024 15:46:55 +0100 Subject: [PATCH 217/596] reorder MonInitKill --- Source/monster.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 4214f3c5ea4..d34254079aa 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -2144,17 +2144,17 @@ static void MonInitKill(int mnum, int mpnum, bool sendmsg) } mon->_msquelch = SQUELCH_MAX; // prevent monster from getting in relaxed state mon->_mhitpoints = 0; - CheckQuestKill(mnum, sendmsg); - if (sendmsg) { - static_assert(MAXMONSTERS <= UCHAR_MAX, "MonInitKill uses mnum as pnum, which must fit to BYTE."); - NetSendCmdMonstKill(mnum, mpnum); - } // if (mnum < MAX_MINIONS) { AddUnVision(mon->_mvid); //} else { MonUpdateLeader(mnum); SpawnLoot(mnum, sendmsg); // } + CheckQuestKill(mnum, sendmsg); + if (sendmsg) { + static_assert(MAXMONSTERS <= UCHAR_MAX, "MonInitKill uses mnum as pnum, which must fit to BYTE."); + NetSendCmdMonstKill(mnum, mpnum); + } if (mon->_mType == MT_DIABLO) MonDiabloDeath(mnum); From 35598c3071763e9aa4dcb13546e5461666c2cba8 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 2 Jan 2024 15:51:00 +0100 Subject: [PATCH 218/596] reset goal/enemy fields of the golem when it is spawned to prevent de-sync --- Source/monster.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/monster.cpp b/Source/monster.cpp index d34254079aa..650ad43b9a5 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -5007,6 +5007,7 @@ void SpawnGolem(int mnum, int x, int y, int level) if ((unsigned)mnum >= MAXMONSTERS) { dev_fatal("SpawnGolem: Invalid monster %d", mnum); } + InitMonster(mnum, DIR_S, 0, 0, 0); // reset goal, enemy (+last) InitGolemStats(mnum, level * 4 + (plx(mnum)._pMagic >> 6)); mon = &monsters[mnum]; mon->_mhitpoints = mon->_mmaxhp; From 9bc2566adb9c8d521d321ee841e43b185d6d1022 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 2 Jan 2024 15:55:37 +0100 Subject: [PATCH 219/596] stick to line of sight when selecting a target of a minion to prevent stuck golems in multiplayer games --- Source/monster.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 650ad43b9a5..49f9d504ba1 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1449,10 +1449,10 @@ static void MonFindEnemy(int mnum) x = tmon->_mfutx; y = tmon->_mfuty; } - //if (!LineClear(mon->_mfutx, mon->_mfuty, x, y)) - // continue; - if (!(dFlags[x][y] & BFLAG_ALERT)) + if (!LineClear(mon->_mfutx, mon->_mfuty, x, y)) continue; + // if (!(dFlags[x][y] & BFLAG_ALERT)) - stick to line of sight to prevent stuck golems in multiplayer games + // continue; dist = std::max(abs(mon->_mfutx - x), abs(mon->_mfuty - y)); sameroom = tv == dTransVal[x][y]; if (sameroom == bestsameroom) { From aa1872da0aeb67543a164a5fa9b01d39d3e1c56a Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 3 Jan 2024 11:23:33 +0100 Subject: [PATCH 220/596] fix the position of the belt --- Source/gameui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/gameui.h b/Source/gameui.h index 26417c034bb..8b1ada617c3 100644 --- a/Source/gameui.h +++ b/Source/gameui.h @@ -151,7 +151,7 @@ extern "C" { #define BELT_WIDTH 60 #define BELT_HEIGHT 118 #define BELT_LEFT PANEL_LEFT -#define BELT_TOP (PANEL_HEIGHT - (MENUBTN_HEIGHT + BELT_HEIGHT)) +#define BELT_TOP (PANEL_BOTTOM - (MENUBTN_HEIGHT + BELT_HEIGHT)) #define DURICON_WIDTH 32 #define GOLDDROP_WIDTH 261 From 1b4ea2818d80d8cddb5de6b033386c6742a6c48d Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 3 Jan 2024 11:41:26 +0100 Subject: [PATCH 221/596] cleanup libsmacker --- 3rdParty/libsmacker/smacker.c | 68 ++++++++++++++++++++++------------- 3rdParty/libsmacker/smacker.h | 2 +- Source/storm/storm_svid.cpp | 4 +-- 3 files changed, 47 insertions(+), 27 deletions(-) diff --git a/3rdParty/libsmacker/smacker.c b/3rdParty/libsmacker/smacker.c index a087a003cd9..45890c29265 100644 --- a/3rdParty/libsmacker/smacker.c +++ b/3rdParty/libsmacker/smacker.c @@ -1031,14 +1031,13 @@ smk smk_open_file(const char * filename, const unsigned char mode) void smk_close(smk s) { unsigned long u; -#ifdef FULL + if (s == NULL) { +#ifdef FULL fputs("libsmacker::smk_close() - ERROR: smk is NULL\n", stderr); +#endif return; } -#else - assert(s); -#endif /* free video sub-components */ for (u = 0; u < 4; u ++) { @@ -1971,75 +1970,96 @@ static char smk_render(smk s) /* rewind to first frame and unpack */ char smk_first(smk s) { - /* null check */ #ifdef FULL + /* null check */ if (s == NULL) { fputs("libsmacker::smk_first() - ERROR: smk is NULL\n", stderr); return -1; } -#else - assert(s); -#endif + s->cur_frame = 0; if (smk_render(s) < 0) { -#ifdef FULL fprintf(stderr, "libsmacker::smk_first(s) - Warning: frame %lu: smk_render returned errors.\n", s->cur_frame); -#endif return -1; } -#ifdef FULL if (s->f == 1) return SMK_LAST; -#endif return SMK_MORE; +#else + char result = SMK_MORE; + + assert(s); + + s->cur_frame = 0; + + if (smk_render(s) < 0) { + result = SMK_ERROR; + } + + return result; +#endif } /* advance to next frame */ char smk_next(smk s) { - /* null check */ #ifdef FULL + /* null check */ if (s == NULL) { fputs("libsmacker::smk_next() - ERROR: smk is NULL\n", stderr); return -1; } -#else - assert(s); -#endif if (s->cur_frame + 1 < (s->f + s->ring_frame)) { s->cur_frame ++; if (smk_render(s) < 0) { -#ifdef FULL fprintf(stderr, "libsmacker::smk_next(s) - Warning: frame %lu: smk_render returned errors.\n", s->cur_frame); -#endif return -1; } -#ifdef FULL + if (s->cur_frame + 1 == (s->f + s->ring_frame)) return SMK_LAST; -#endif + return SMK_MORE; } else if (s->ring_frame) { s->cur_frame = 1; if (smk_render(s) < 0) { -#ifdef FULL fprintf(stderr, "libsmacker::smk_next(s) - Warning: frame %lu: smk_render returned errors.\n", s->cur_frame); -#endif return -1; } -#ifdef FULL + if (s->cur_frame + 1 == (s->f + s->ring_frame)) return SMK_LAST; -#endif + return SMK_MORE; } return SMK_DONE; +#else + char result = SMK_DONE; + + assert(s); + + if (s->cur_frame + 1 < (s->f + s->ring_frame)) { + s->cur_frame ++; + + result = SMK_MORE; + } else if (s->ring_frame) { + s->cur_frame = 1; + + result = SMK_MORE; + } + + if (result == SMK_MORE && smk_render(s) < 0) { + result = SMK_ERROR; + } + + return result; +#endif } /* seek to a keyframe in an smk */ diff --git a/3rdParty/libsmacker/smacker.h b/3rdParty/libsmacker/smacker.h index 3fe98e45f8b..2a944f1329a 100644 --- a/3rdParty/libsmacker/smacker.h +++ b/3rdParty/libsmacker/smacker.h @@ -33,10 +33,10 @@ typedef struct smk_t * smk; #define SMK_MORE 0x01 #ifdef FULL #define SMK_LAST 0x02 -#define SMK_ERROR -1 #else #define SMK_ERR(x) ((x) < 0) #endif +#define SMK_ERROR -1 /** file-processing mode, pass to smk_open_file */ #define SMK_MODE_DISK 0x00 diff --git a/Source/storm/storm_svid.cpp b/Source/storm/storm_svid.cpp index 141219ae306..c13ea2bec5f 100644 --- a/Source/storm/storm_svid.cpp +++ b/Source/storm/storm_svid.cpp @@ -478,8 +478,8 @@ void SVidPlayEnd() RestartMixer(); } #endif // !NOSOUND - if (SVidSMK != NULL) - smk_close(SVidSMK); + smk_close(SVidSMK); + SVidSMK = NULL; MemFreeDbg(SVidBuffer); From d7a163dd97fadd2574b88063bb718298b5f81aed Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 3 Jan 2024 12:03:38 +0100 Subject: [PATCH 222/596] do not crash when there is an error during movie-playback (just stop if the video fails) --- Source/appfat.h | 13 +++++++++++++ Source/storm/storm_svid.cpp | 34 +++++++++++++++++++--------------- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/Source/appfat.h b/Source/appfat.h index 50465b1031a..8acdd780e30 100644 --- a/Source/appfat.h +++ b/Source/appfat.h @@ -76,6 +76,19 @@ void dev_fatal(const char* pszFmt, MsgArgs... args) { } #endif // DEBUG_MODE +#define app_issue(ec) \ + if (ec == ec) { \ + DoLog("ERROR(app.%d): %s @ %s:%d", ec, __FUNCTION__, __FILE__, __LINE__); \ + } +#define sdl_issue(ec) \ + if (ec == ec) { \ + DoLog("ERROR(sdl.%d): %s @ %s:%d", ec, __FUNCTION__, __FILE__, __LINE__); \ + } +#define asio_issue(ec, msg) \ + if (ec == ec) { \ + DoLog("ERROR(asio.%d): %s @ %s:%d", ec, __FUNCTION__, __FILE__, __LINE__); \ + } + #ifdef __cplusplus } #endif diff --git a/Source/storm/storm_svid.cpp b/Source/storm/storm_svid.cpp index c13ea2bec5f..8e8bd48b44f 100644 --- a/Source/storm/storm_svid.cpp +++ b/Source/storm/storm_svid.cpp @@ -285,16 +285,14 @@ HANDLE SVidPlayBegin(const char* filename, int flags) if (deviceId != 0) { SDL_PauseAudioDevice(deviceId, 0); /* start audio playing. */ } else { - DoLog(SDL_GetError()); - //sdl_error(ERR_SDL_AUDIO_DEVICE_SDL2); + sdl_issue(ERR_SDL_AUDIO_DEVICE_SDL2); } #else sVidAudioQueue->Subscribe(&audioFormat); if (SDL_OpenAudio(&audioFormat, NULL) == 0) { SDL_PauseAudio(0); } else { - DoLog(SDL_GetError()); - //sdl_error(ERR_SDL_AUDIO_DEVICE_SDL1); + sdl_issue(ERR_SDL_AUDIO_DEVICE_SDL1); } #endif } @@ -327,16 +325,18 @@ HANDLE SVidPlayBegin(const char* filename, int flags) 0, SVidWidth, SDL_PIXELFORMAT_INDEX8); - if (SVidSurface == NULL) { - sdl_error(ERR_SDL_VIDEO_CREATE); - } SVidPalette = SDL_AllocPalette(NUM_COLORS); - if (SVidPalette == NULL) { - sdl_error(ERR_SDL_VIDEO_PALETTE); + if (SVidSurface == NULL || SVidPalette == NULL) { + if (SVidSurface == NULL) { + sdl_issue(ERR_SDL_VIDEO_CREATE); + } else { + sdl_issue(ERR_SDL_VIDEO_PALETTE); + } + SVidPlayEnd(); + } else { + UpdatePalette(); } - UpdatePalette(); - SVidFrameEnd = SDL_GetTicks() * 1000.0 + SVidFrameLength; return SVidSMK; } @@ -390,7 +390,7 @@ bool SVidPlayContinue() BYTE* audio = SVidApplyVolume(smk_get_audio(SVidSMK, 0), len); #if SDL_VERSION_ATLEAST(2, 0, 4) if (SDL_QueueAudio(deviceId, audio, len) < 0) { - sdl_error(ERR_SDL_VIDEO_AUDIO); + sdl_issue(ERR_SDL_VIDEO_AUDIO); } #else sVidAudioQueue->Enqueue(audio, len); @@ -406,7 +406,8 @@ bool SVidPlayContinue() #ifndef USE_SDL1 if (renderer != NULL) { if (SDL_BlitSurface(SVidSurface, NULL, outputSurface, NULL) < 0) { - sdl_error(ERR_SDL_VIDEO_BLIT_A); + sdl_issue(ERR_SDL_VIDEO_BLIT_A); + return false; } } else #endif @@ -436,7 +437,8 @@ bool SVidPlayContinue() || outputSurface->w == static_cast(SVidWidth) || outputSurface->h == static_cast(SVidHeight)) { if (SDL_BlitSurface(SVidSurface, NULL, outputSurface, &outputRect) < 0) { - sdl_error(ERR_SDL_VIDEO_BLIT_B); + sdl_issue(ERR_SDL_VIDEO_BLIT_B); + return false; } } else { // The source surface is always 8-bit, and the output surface is never 8-bit in this branch. @@ -447,7 +449,9 @@ bool SVidPlayContinue() SDL_Surface* tmp = SDL_ConvertSurfaceFormat(SVidSurface, wndFormat, 0); #endif if (SDL_BlitScaled(tmp, NULL, outputSurface, &outputRect) < 0) { - sdl_error(ERR_SDL_VIDEO_BLIT_SCALED); + SDL_FreeSurface(tmp); + sdl_issue(ERR_SDL_VIDEO_BLIT_SCALED); + return false; } SDL_FreeSurface(tmp); } From baefcdaa0987ef9ebe6d05ee855c15c614499080 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 3 Jan 2024 12:11:02 +0100 Subject: [PATCH 223/596] simplify SVidPlayBegin - no need to call UpdatePalette (the first frame is supposed to be marked with new palette) - get rid of the asymmetric SVidBuffer assertion --- Source/storm/storm_svid.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/storm/storm_svid.cpp b/Source/storm/storm_svid.cpp index 8e8bd48b44f..b546635a020 100644 --- a/Source/storm/storm_svid.cpp +++ b/Source/storm/storm_svid.cpp @@ -254,7 +254,6 @@ HANDLE SVidPlayBegin(const char* filename, int flags) //0x200800 // Clear FB size_t dwBytes; - assert(SVidBuffer == NULL); SVidBuffer = LoadFileInMem(filename, &dwBytes); SVidSMK = smk_open_memory(SVidBuffer, dwBytes); @@ -334,8 +333,9 @@ HANDLE SVidPlayBegin(const char* filename, int flags) sdl_issue(ERR_SDL_VIDEO_PALETTE); } SVidPlayEnd(); - } else { - UpdatePalette(); + //} else { + // assert(smk_palette_updated(SVidSMK)); + // UpdatePalette(); } SVidFrameEnd = SDL_GetTicks() * 1000.0 + SVidFrameLength; return SVidSMK; From 84d6d04bca3f3b92cb2a10daf2df9b62478adea5 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 3 Jan 2024 12:15:54 +0100 Subject: [PATCH 224/596] preserve aspect ratio when playing a movie with a renderer --- Source/storm/storm_svid.cpp | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/Source/storm/storm_svid.cpp b/Source/storm/storm_svid.cpp index b546635a020..0b21865f871 100644 --- a/Source/storm/storm_svid.cpp +++ b/Source/storm/storm_svid.cpp @@ -303,11 +303,7 @@ HANDLE SVidPlayBegin(const char* filename, int flags) smk_enable_video(SVidSMK, enableVideo); smk_first(SVidSMK); // Decode first frame -#ifndef USE_SDL1 - if (renderer != NULL) { - RecreateDisplay(SVidWidth, SVidHeight); - } -#else +#ifdef USE_SDL1 TrySetVideoModeToSVidForSDL1(); #endif @@ -403,14 +399,6 @@ bool SVidPlayContinue() } SDL_Surface* outputSurface = GetOutputSurface(); -#ifndef USE_SDL1 - if (renderer != NULL) { - if (SDL_BlitSurface(SVidSurface, NULL, outputSurface, NULL) < 0) { - sdl_issue(ERR_SDL_VIDEO_BLIT_A); - return false; - } - } else -#endif { #ifdef USE_SDL1 const bool isIndexedOutputFormat = SDLBackport_IsPixelFormatIndexed(outputSurface->format); @@ -493,11 +481,7 @@ void SVidPlayEnd() SDL_FreeSurface(SVidSurface); SVidSurface = NULL; -#ifndef USE_SDL1 - if (renderer != NULL) { - RecreateDisplay(SCREEN_WIDTH, SCREEN_HEIGHT); - } -#else +#ifdef USE_SDL1 if (IsSVidVideoMode) { SetVideoModeToPrimary(IsFullScreen(), SCREEN_WIDTH, SCREEN_HEIGHT); IsSVidVideoMode = false; From 8f58f0b10e63fe616aa74ff0a0b8ccd3622a0f51 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 3 Jan 2024 12:17:38 +0100 Subject: [PATCH 225/596] support ToggleFullscreen during movies --- Source/movie.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Source/movie.cpp b/Source/movie.cpp index 3dd1dd1ff62..641a42e9d02 100644 --- a/Source/movie.cpp +++ b/Source/movie.cpp @@ -34,6 +34,13 @@ int play_movie(const char* pszMovie, int movieFlags) result = MPR_CANCEL; break; } +#ifndef USE_SDL1 + if (SDL_GetModState() & KMOD_ALT) { + if (e.vkcode == DVL_VK_RETURN) + ToggleFullscreen(); + continue; + } +#endif case DVL_WM_LBUTTONDOWN: case DVL_WM_RBUTTONDOWN: if (movieFlags & MOV_SKIP) { From 089c8b9e344e3e14706176d1ceb039d3fc6d8aa0 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 3 Jan 2024 12:19:24 +0100 Subject: [PATCH 226/596] use the format of the outputSurface instead of the window when rendering a (movie-)frame --- Source/storm/storm_svid.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/storm/storm_svid.cpp b/Source/storm/storm_svid.cpp index 0b21865f871..63d9232b195 100644 --- a/Source/storm/storm_svid.cpp +++ b/Source/storm/storm_svid.cpp @@ -400,11 +400,11 @@ bool SVidPlayContinue() SDL_Surface* outputSurface = GetOutputSurface(); { + SDL_PixelFormat* outputFormat = outputSurface->format; #ifdef USE_SDL1 - const bool isIndexedOutputFormat = SDLBackport_IsPixelFormatIndexed(outputSurface->format); + const bool isIndexedOutputFormat = SDLBackport_IsPixelFormatIndexed(outputFormat); #else - const Uint32 wndFormat = SDL_GetWindowPixelFormat(ghMainWnd); - const bool isIndexedOutputFormat = SDL_ISPIXELFORMAT_INDEXED(wndFormat); + const bool isIndexedOutputFormat = SDL_ISPIXELFORMAT_INDEXED(outputFormat->format); #endif SDL_Rect outputRect; if (isIndexedOutputFormat) { @@ -432,9 +432,9 @@ bool SVidPlayContinue() // The source surface is always 8-bit, and the output surface is never 8-bit in this branch. // We must convert to the output format before calling SDL_BlitScaled. #ifdef USE_SDL1 - SDL_Surface* tmp = SDL_ConvertSurface(SVidSurface, ghMainWnd->format, 0); + SDL_Surface* tmp = SDL_ConvertSurface(SVidSurface, outputFormat, 0); #else - SDL_Surface* tmp = SDL_ConvertSurfaceFormat(SVidSurface, wndFormat, 0); + SDL_Surface* tmp = SDL_ConvertSurfaceFormat(SVidSurface, outputFormat->format, 0); #endif if (SDL_BlitScaled(tmp, NULL, outputSurface, &outputRect) < 0) { SDL_FreeSurface(tmp); From c35b0859d5c4397ab331d19379893df4ed8f3da5 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 3 Jan 2024 12:37:14 +0100 Subject: [PATCH 227/596] clear the screen if the video mode is changed before playing a movie (SDL1) --- Source/storm/storm_svid.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Source/storm/storm_svid.cpp b/Source/storm/storm_svid.cpp index 63d9232b195..15267edf6e9 100644 --- a/Source/storm/storm_svid.cpp +++ b/Source/storm/storm_svid.cpp @@ -100,6 +100,8 @@ void TrySetVideoModeToSVidForSDL1() #endif SetVideoMode(w, h, display->format->BitsPerPixel, flags); + // Set the background to black. + SDL_FillRect(GetOutputSurface(), NULL, 0x000000); } #endif @@ -307,11 +309,6 @@ HANDLE SVidPlayBegin(const char* filename, int flags) TrySetVideoModeToSVidForSDL1(); #endif - // Set the background to black. - // commented out because the background is supposed to be black at this point - // due to RecreateDisplay, this should be done twice anyway... - // SDL_FillRect(GetOutputSurface(), NULL, 0x000000); - // Copy frame to buffer SVidSurface = SDL_CreateRGBSurfaceWithFormatFrom( (unsigned char*)smk_get_video(SVidSMK), From ec037c36fd788e02a068c8446cef730b6c811b16 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 3 Jan 2024 13:04:19 +0100 Subject: [PATCH 228/596] cosmetic --- Source/storm/storm_svid.cpp | 70 ++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/Source/storm/storm_svid.cpp b/Source/storm/storm_svid.cpp index 15267edf6e9..22299cdc5f9 100644 --- a/Source/storm/storm_svid.cpp +++ b/Source/storm/storm_svid.cpp @@ -81,7 +81,7 @@ void TrySetVideoModeToSVidForSDL1() // Check is there are any modes available. if (modes == NULL - || modes == reinterpret_cast(-1)) { // should not happen, since the first try was rejected... + || modes == reinterpret_cast(-1)) { // should not happen, since the first try was rejected... return; } @@ -396,50 +396,48 @@ bool SVidPlayContinue() } SDL_Surface* outputSurface = GetOutputSurface(); - { - SDL_PixelFormat* outputFormat = outputSurface->format; + SDL_PixelFormat* outputFormat = outputSurface->format; #ifdef USE_SDL1 - const bool isIndexedOutputFormat = SDLBackport_IsPixelFormatIndexed(outputFormat); + const bool isIndexedOutputFormat = SDLBackport_IsPixelFormatIndexed(outputFormat); #else - const bool isIndexedOutputFormat = SDL_ISPIXELFORMAT_INDEXED(outputFormat->format); + const bool isIndexedOutputFormat = SDL_ISPIXELFORMAT_INDEXED(outputFormat->format); #endif - SDL_Rect outputRect; - if (isIndexedOutputFormat) { - // Cannot scale if the output format is indexed (8-bit palette). - outputRect.w = static_cast(SVidWidth); - outputRect.h = static_cast(SVidHeight); - } else if (IsLandscapeFit(SVidWidth, SVidHeight, outputSurface->w, outputSurface->h)) { - outputRect.w = outputSurface->w; - outputRect.h = SVidHeight * outputSurface->w / SVidWidth; - } else { - outputRect.w = SVidWidth * outputSurface->h / SVidHeight; - outputRect.h = outputSurface->h; + SDL_Rect outputRect; + if (isIndexedOutputFormat) { + // Cannot scale if the output format is indexed (8-bit palette). + outputRect.w = static_cast(SVidWidth); + outputRect.h = static_cast(SVidHeight); + } else if (IsLandscapeFit(SVidWidth, SVidHeight, outputSurface->w, outputSurface->h)) { + outputRect.w = outputSurface->w; + outputRect.h = SVidHeight * outputSurface->w / SVidWidth; + } else { + outputRect.w = SVidWidth * outputSurface->h / SVidHeight; + outputRect.h = outputSurface->h; + } + outputRect.x = (outputSurface->w - outputRect.w) / 2; + outputRect.y = (outputSurface->h - outputRect.h) / 2; + + if (isIndexedOutputFormat + || outputSurface->w == static_cast(SVidWidth) + || outputSurface->h == static_cast(SVidHeight)) { + if (SDL_BlitSurface(SVidSurface, NULL, outputSurface, &outputRect) < 0) { + sdl_issue(ERR_SDL_VIDEO_BLIT_B); + return false; } - outputRect.x = (outputSurface->w - outputRect.w) / 2; - outputRect.y = (outputSurface->h - outputRect.h) / 2; - - if (isIndexedOutputFormat - || outputSurface->w == static_cast(SVidWidth) - || outputSurface->h == static_cast(SVidHeight)) { - if (SDL_BlitSurface(SVidSurface, NULL, outputSurface, &outputRect) < 0) { - sdl_issue(ERR_SDL_VIDEO_BLIT_B); - return false; - } - } else { - // The source surface is always 8-bit, and the output surface is never 8-bit in this branch. - // We must convert to the output format before calling SDL_BlitScaled. + } else { + // The source surface is always 8-bit, and the output surface is never 8-bit in this branch. + // We must convert to the output format before calling SDL_BlitScaled. #ifdef USE_SDL1 - SDL_Surface* tmp = SDL_ConvertSurface(SVidSurface, outputFormat, 0); + SDL_Surface* tmp = SDL_ConvertSurface(SVidSurface, outputFormat, 0); #else - SDL_Surface* tmp = SDL_ConvertSurfaceFormat(SVidSurface, outputFormat->format, 0); + SDL_Surface* tmp = SDL_ConvertSurfaceFormat(SVidSurface, outputFormat->format, 0); #endif - if (SDL_BlitScaled(tmp, NULL, outputSurface, &outputRect) < 0) { - SDL_FreeSurface(tmp); - sdl_issue(ERR_SDL_VIDEO_BLIT_SCALED); - return false; - } + if (SDL_BlitScaled(tmp, NULL, outputSurface, &outputRect) < 0) { SDL_FreeSurface(tmp); + sdl_issue(ERR_SDL_VIDEO_BLIT_SCALED); + return false; } + SDL_FreeSurface(tmp); } RenderPresent(); From 582136bac20314d50420f65ad9bf7bfaad36950a Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 4 Jan 2024 09:03:08 +0100 Subject: [PATCH 229/596] bugfix for devilutionx (Fit to Screen vs Integer Scaling) - fix window size when 'Fit to Screen' and 'Integer Scaling' are set (introduced in 157570a1f22f06639bbf63dd55d30dca98143fe1) + prevent crash if the window size is too small + 'document' the non 'Integer Scaling' branch --- Source/utils/display.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/Source/utils/display.cpp b/Source/utils/display.cpp index 83cfcecbe43..50f6a5a2dd1 100644 --- a/Source/utils/display.cpp +++ b/Source/utils/display.cpp @@ -148,9 +148,15 @@ static void CalculatePreferredWindowSize(int& width, int& height, bool useIntege } if (useIntegerScaling) { - int factor = std::min(mode.w / width, mode.h / height); - width = mode.w / factor; - height = mode.h / factor; + int wFactor = mode.w / width; + int hFactor = mode.h / height; + if (wFactor > hFactor) { + if (hFactor != 0) + width *= wFactor / hFactor; + } else { // if (hFactor > wFactor) { + if (wFactor != 0) + height *= hFactor / wFactor; + } return; } @@ -158,9 +164,11 @@ static void CalculatePreferredWindowSize(int& width, int& height, bool useIntege float hFactor = (float)mode.h / height; if (wFactor > hFactor) { - width = mode.w * height / mode.h; - } else { - height = mode.h * width / mode.w; + // if (hFactor != 0.0) + width = mode.w * height / mode.h; // width = width * (wFactor / hFactor); + } else { // if (hFactor > wFactor) { + // if (wFactor != 0.0) + height = mode.h * width / mode.w; // height = height * (hFactor / wFactor); } } #endif From b448e4718d59b977ed82f5a69d57cd71848fe917 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 4 Jan 2024 09:05:43 +0100 Subject: [PATCH 230/596] do not crash when SDL_GetDesktopDisplayMode fails in CalculatePreferredWindowSize - it is very unlikely + just proceed with the default values (similar to the same case in SpawnWindow) --- Source/utils/display.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/utils/display.cpp b/Source/utils/display.cpp index 50f6a5a2dd1..b4872a15d14 100644 --- a/Source/utils/display.cpp +++ b/Source/utils/display.cpp @@ -140,7 +140,7 @@ static void CalculatePreferredWindowSize(int& width, int& height, bool useIntege { SDL_DisplayMode mode; if (SDL_GetDesktopDisplayMode(0, &mode) != 0) { - sdl_error(ERR_SDL_DISPLAY_MODE_GET); + return; } if (mode.w < mode.h) { From 33862f3643836480187bf5a2f624dab16967d089 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 4 Jan 2024 09:08:01 +0100 Subject: [PATCH 231/596] cosmetic --- Source/utils/display.cpp | 52 +++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/Source/utils/display.cpp b/Source/utils/display.cpp index b4872a15d14..f31fa3023ce 100644 --- a/Source/utils/display.cpp +++ b/Source/utils/display.cpp @@ -139,36 +139,32 @@ static void AdjustToScreenGeometry(int width, int height) static void CalculatePreferredWindowSize(int& width, int& height, bool useIntegerScaling) { SDL_DisplayMode mode; - if (SDL_GetDesktopDisplayMode(0, &mode) != 0) { - return; - } - - if (mode.w < mode.h) { - std::swap(mode.w, mode.h); - } - - if (useIntegerScaling) { - int wFactor = mode.w / width; - int hFactor = mode.h / height; - if (wFactor > hFactor) { - if (hFactor != 0) - width *= wFactor / hFactor; - } else { // if (hFactor > wFactor) { - if (wFactor != 0) - height *= hFactor / wFactor; + if (SDL_GetDesktopDisplayMode(0, &mode) == 0) { + if (mode.w < mode.h) { + std::swap(mode.w, mode.h); } - return; - } - float wFactor = (float)mode.w / width; - float hFactor = (float)mode.h / height; - - if (wFactor > hFactor) { - // if (hFactor != 0.0) - width = mode.w * height / mode.h; // width = width * (wFactor / hFactor); - } else { // if (hFactor > wFactor) { - // if (wFactor != 0.0) - height = mode.h * width / mode.w; // height = height * (hFactor / wFactor); + if (useIntegerScaling) { + int wFactor = mode.w / width; + int hFactor = mode.h / height; + if (wFactor > hFactor) { + if (hFactor != 0) + width *= wFactor / hFactor; + } else { // if (hFactor > wFactor) { + if (wFactor != 0) + height *= hFactor / wFactor; + } + } else { + float wFactor = (float)mode.w / width; + float hFactor = (float)mode.h / height; + if (wFactor > hFactor) { + // if (hFactor != 0.0) + width = mode.w * height / mode.h; // width = width * (wFactor / hFactor); + } else { // if (hFactor > wFactor) { + // if (wFactor != 0.0) + height = mode.h * width / mode.w; // height = height * (hFactor / wFactor); + } + } } } #endif From 50b5d189097bf0a053b23b9f76674bb24fa1cf51 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 4 Jan 2024 09:10:29 +0100 Subject: [PATCH 232/596] handle scaling in a more 'standard' way in case of 3DS --- Source/platform/ctr/display.cpp | 4 +--- Source/platform/ctr/display.hpp | 2 +- Source/utils/display.cpp | 5 ++--- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/Source/platform/ctr/display.cpp b/Source/platform/ctr/display.cpp index 1dffc76287d..5dd7440f657 100644 --- a/Source/platform/ctr/display.cpp +++ b/Source/platform/ctr/display.cpp @@ -1,10 +1,8 @@ #include "platform/ctr/display.hpp" #include -uint32_t Get3DSScalingFlag(bool fitToScreen, int width, int height) +uint32_t Get3DSScalingFlag(int width, int height) { - if (fitToScreen) - return SDL_FULLSCREEN; if (width * 3 < height * 5) return SDL_FITHEIGHT; return SDL_FITWIDTH; diff --git a/Source/platform/ctr/display.hpp b/Source/platform/ctr/display.hpp index f641c253be0..b316b629e51 100644 --- a/Source/platform/ctr/display.hpp +++ b/Source/platform/ctr/display.hpp @@ -2,4 +2,4 @@ #include -uint32_t Get3DSScalingFlag(bool fitToScreen, int width, int height); +uint32_t Get3DSScalingFlag(int width, int height); diff --git a/Source/utils/display.cpp b/Source/utils/display.cpp index f31fa3023ce..43fb2f2bb15 100644 --- a/Source/utils/display.cpp +++ b/Source/utils/display.cpp @@ -94,9 +94,8 @@ void SetVideoModeToPrimary(bool fullscreen, int width, int height) if (fullscreen) flags |= SDL_FULLSCREEN; #ifdef __3DS__ - flags &= ~SDL_FULLSCREEN; - bool fitToScreen = getIniBool("Graphics", "Fit to Screen", true); - flags |= Get3DSScalingFlag(fitToScreen, width, height); + else + flags |= Get3DSScalingFlag(width, height); #endif SetVideoMode(width, height, SDL1_VIDEO_MODE_BPP, flags); } From 5a0b01311cc43c0203359941c61d53f2e1c41d39 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 5 Jan 2024 08:55:57 +0100 Subject: [PATCH 233/596] hide more unused features of StormLib III. --- 3rdParty/StormLib/src/SBaseCommon.cpp | 39 ++++++++++++---- 3rdParty/StormLib/src/SBaseFileTable.cpp | 54 ++++++++++++++++++---- 3rdParty/StormLib/src/SBaseSubTypes.cpp | 6 +-- 3rdParty/StormLib/src/SFileOpenArchive.cpp | 50 +++++++++++++++----- 3rdParty/StormLib/src/SFileReadFile.cpp | 9 +++- 3rdParty/StormLib/src/StormCommon.h | 13 ++++-- 3rdParty/StormLib/src/StormLib.h | 14 ++++-- 7 files changed, 145 insertions(+), 40 deletions(-) diff --git a/3rdParty/StormLib/src/SBaseCommon.cpp b/3rdParty/StormLib/src/SBaseCommon.cpp index abe0410116c..4acde94c4e8 100644 --- a/3rdParty/StormLib/src/SBaseCommon.cpp +++ b/3rdParty/StormLib/src/SBaseCommon.cpp @@ -918,14 +918,20 @@ TMPQFile * CreateFileHandle(TMPQArchive * ha, TFileEntry * pFileEntry) void * LoadMpqTable( TMPQArchive * ha, ULONGLONG ByteOffset, +#ifdef FULL_COMP LPBYTE pbTableHash, DWORD dwCompressedSize, +#endif DWORD dwTableSize, DWORD dwKey, DWORD * PtrRealTableSize) { ULONGLONG FileSize = 0; +#ifdef FULL_COMP LPBYTE pbCompressed = NULL; +#else + const DWORD dwCompressedSize = dwTableSize; +#endif LPBYTE pbMpqTable; LPBYTE pbToRead; DWORD dwBytesToRead = dwTableSize; @@ -935,6 +941,7 @@ void * LoadMpqTable( pbMpqTable = pbToRead = STORM_ALLOC(BYTE, dwTableSize); if(pbMpqTable != NULL) { +#ifdef FULL_COMP // Check if the MPQ table is compressed if(dwCompressedSize < dwTableSize) { @@ -948,7 +955,7 @@ void * LoadMpqTable( return NULL; } } - +#endif // Get the file offset from which we will read the table // Note: According to Storm.dll from Warcraft III (version 2002), // if the hash table position is 0xFFFFFFFF, no SetFilePointer call is done @@ -1003,21 +1010,18 @@ void * LoadMpqTable( DecryptMpqBlock(pbToRead, dwCompressedSize, dwKey); BSWAP_ARRAY32_UNSIGNED(pbToRead, dwCompressedSize); } - +#ifdef FULL_COMP // If the table is compressed, decompress it if(dwCompressedSize < dwTableSize) { -#ifdef FULL_COMP int cbOutBuffer = (int)dwTableSize; int cbInBuffer = (int)dwCompressedSize; if(!SCompDecompress2(pbMpqTable, &cbOutBuffer, pbCompressed, cbInBuffer)) dwErrCode = GetLastError(); -#else dwErrCode = ERROR_FILE_CORRUPT; -#endif } - +#endif // Make sure that the table is properly byte-swapped BSWAP_ARRAY32_UNSIGNED(pbMpqTable, dwTableSize); } @@ -1028,10 +1032,11 @@ void * LoadMpqTable( STORM_FREE(pbMpqTable); pbMpqTable = NULL; } - +#ifdef FULL_COMP // Free the compression buffer, if any if(pbCompressed != NULL) STORM_FREE(pbCompressed); +#endif } // Return the MPQ table @@ -1155,9 +1160,11 @@ DWORD AllocatePatchInfo(TMPQFile * hf, bool bLoadFromFile) hf->pPatchInfo = pPatchInfo; return ERROR_SUCCESS; } -#endif // Allocates sector offset table DWORD AllocateSectorOffsets(TMPQFile * hf, bool bLoadFromFile) +#else +DWORD AllocateSectorOffsets(TMPQFile * hf) +#endif { TMPQArchive * ha = hf->ha; TFileEntry * pFileEntry = hf->pFileEntry; @@ -1199,9 +1206,10 @@ DWORD AllocateSectorOffsets(TMPQFile * hf, bool bLoadFromFile) hf->SectorOffsets = STORM_ALLOC(DWORD, (dwSectorOffsLen / sizeof(DWORD))); if(hf->SectorOffsets == NULL) return ERROR_NOT_ENOUGH_MEMORY; - +#ifdef FULL // Only read from the file if we are supposed to do so if(bLoadFromFile) +#endif { ULONGLONG RawFilePos = hf->RawFilePos; #ifdef FULL @@ -1305,17 +1313,22 @@ DWORD AllocateSectorOffsets(TMPQFile * hf, bool bLoadFromFile) goto __LoadSectorOffsets; } } +#ifdef FULL else { memset(hf->SectorOffsets, 0, dwSectorOffsLen); hf->SectorOffsets[0] = dwSectorOffsLen; } +#endif } return ERROR_SUCCESS; } - +#ifdef FULL DWORD AllocateSectorChecksums(TMPQFile * hf, bool bLoadFromFile) +#else +DWORD AllocateSectorChecksums(TMPQFile * hf) +#endif { TMPQArchive * ha = hf->ha; TFileEntry * pFileEntry = hf->pFileEntry; @@ -1353,6 +1366,7 @@ DWORD AllocateSectorChecksums(TMPQFile * hf, bool bLoadFromFile) dwExpectedSize = (hf->dwSectorCount + 2) * sizeof(DWORD); if(hf->SectorOffsets[0] != 0 && hf->SectorOffsets[0] == dwExpectedSize) { +#ifdef FULL // If we are not loading from the MPQ file, we just allocate the sector table // In that case, do not check any sizes if(bLoadFromFile == false) @@ -1366,6 +1380,7 @@ DWORD AllocateSectorChecksums(TMPQFile * hf, bool bLoadFromFile) return ERROR_SUCCESS; } else +#endif { // Is there valid size of the sector checksums? if(hf->SectorOffsets[hf->dwSectorCount + 1] >= hf->SectorOffsets[hf->dwSectorCount]) @@ -1381,7 +1396,11 @@ DWORD AllocateSectorChecksums(TMPQFile * hf, bool bLoadFromFile) RawFilePos = CalculateRawSectorOffset(hf, dwCrcOffset); // Now read the table from the MPQ +#ifdef FULL hf->SectorChksums = (DWORD *)LoadMpqTable(ha, RawFilePos, NULL, dwCompressedSize, dwCrcSize, 0, NULL); +#else + hf->SectorChksums = (DWORD *)LoadMpqTable(ha, RawFilePos, dwCrcSize, 0, NULL); +#endif if(hf->SectorChksums == NULL) return ERROR_NOT_ENOUGH_MEMORY; } diff --git a/3rdParty/StormLib/src/SBaseFileTable.cpp b/3rdParty/StormLib/src/SBaseFileTable.cpp index 880a1a9ec58..a134e012161 100644 --- a/3rdParty/StormLib/src/SBaseFileTable.cpp +++ b/3rdParty/StormLib/src/SBaseFileTable.cpp @@ -384,7 +384,6 @@ static ULONGLONG DetermineArchiveSize_V4( // Return the calculated archive size return ArchiveSize; } -#endif ULONGLONG FileOffsetFromMpqOffset(TMPQArchive * ha, ULONGLONG MpqOffset) { if(ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1) @@ -398,7 +397,14 @@ ULONGLONG FileOffsetFromMpqOffset(TMPQArchive * ha, ULONGLONG MpqOffset) return ha->MpqPos + MpqOffset; } } - +#else +ULONGLONG FileOffsetFromMpqOffset(TMPQArchive * ha, ULONGLONG MpqOffset) +{ + assert(ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1); + // For MPQ archive v1, any file offset is only 32-bit + return (ULONGLONG)((DWORD)ha->MpqPos + (DWORD)MpqOffset); +} +#endif ULONGLONG CalculateRawSectorOffset( TMPQFile * hf, DWORD dwSectorOffset) @@ -419,12 +425,15 @@ ULONGLONG CalculateRawSectorOffset( // RawFilePos = hf->RawFilePos + dwSectorOffset; +#ifdef FULL if(hf->ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1) +#endif RawFilePos = (DWORD)hf->ha->MpqPos + (DWORD)hf->pFileEntry->ByteOffset + dwSectorOffset; #ifdef FULL // We also have to add patch header size, if patch header is present if(hf->pPatchInfo != NULL) RawFilePos += hf->pPatchInfo->dwLength; + #endif // Return the result offset return RawFilePos; @@ -501,16 +510,16 @@ DWORD ConvertMpqHeaderToFormat4( // Fill the rest of the header memset((LPBYTE)pHeader + MPQ_HEADER_SIZE_V1, 0, sizeof(TMPQHeader) - MPQ_HEADER_SIZE_V1); +#ifdef FULL pHeader->BlockTableSize64 = pHeader->dwBlockTableSize * sizeof(TMPQBlock); pHeader->HashTableSize64 = pHeader->dwHashTableSize * sizeof(TMPQHash); pHeader->ArchiveSize64 = pHeader->dwArchiveSize; - +#endif // Block table position must be calculated as 32-bit value // Note: BOBA protector puts block table before the MPQ header, so it is negative BlockTablePos64 = (ULONGLONG)((DWORD)ByteOffset + pHeader->dwBlockTablePos); #ifdef FULL BlockTableMask = 0xFFFFFFF0; -#endif // Determine the archive size on malformed MPQs if(ha->dwFlags & MPQ_FLAG_MALFORMED) @@ -527,6 +536,7 @@ DWORD ConvertMpqHeaderToFormat4( pHeader->dwBlockTableSize = (DWORD)((FileSize - BlockTablePos64) / sizeof(TMPQBlock)); pHeader->BlockTableSize64 = pHeader->dwBlockTableSize * sizeof(TMPQBlock); } +#endif break; #ifdef FULL case MPQ_FORMAT_VERSION_2: @@ -935,8 +945,9 @@ static DWORD BuildFileTableFromBlockTable( { // Sanity checks assert(pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1); +#ifdef FULL assert(pHeader->HiBlockTablePos64 == 0); - +#endif // Allocate the translation table DefragmentTable = STORM_ALLOC(DWORD, pHeader->dwBlockTableSize); if(DefragmentTable == NULL) @@ -1016,7 +1027,9 @@ static DWORD BuildFileTableFromBlockTable( if(ha->dwFileTableSize > ha->dwMaxFileCount) { ha->pFileTable = STORM_REALLOC(TFileEntry, ha->pFileTable, ha->dwMaxFileCount); +#ifdef FULL ha->pHeader->BlockTableSize64 = ha->dwMaxFileCount * sizeof(TMPQBlock); +#endif ha->pHeader->dwBlockTableSize = ha->dwMaxFileCount; ha->dwFileTableSize = ha->dwMaxFileCount; } @@ -2349,7 +2362,9 @@ static TMPQHash * LoadHashTable(TMPQArchive * ha) ULONGLONG ByteOffset; TMPQHash * pHashTable = NULL; DWORD dwTableSize; +#ifdef FULL DWORD dwCmpSize; +#endif DWORD dwRealTableSize; // Note: It is allowed to load hash table if it is at offset 0. @@ -2367,12 +2382,19 @@ static TMPQHash * LoadHashTable(TMPQArchive * ha) case MPQ_SUBTYPE_MPQ: // Calculate the position and size of the hash table +#ifdef FULL ByteOffset = FileOffsetFromMpqOffset(ha, MAKE_OFFSET64(pHeader->wHashTablePosHi, pHeader->dwHashTablePos)); dwTableSize = pHeader->dwHashTableSize * sizeof(TMPQHash); dwCmpSize = (DWORD)pHeader->HashTableSize64; // Read, decrypt and uncompress the hash table pHashTable = (TMPQHash *)LoadMpqTable(ha, ByteOffset, pHeader->MD5_HashTable, dwCmpSize, dwTableSize, g_dwHashTableKey, &dwRealTableSize); +#else + ByteOffset = FileOffsetFromMpqOffset(ha, pHeader->dwHashTablePos); + dwTableSize = pHeader->dwHashTableSize * sizeof(TMPQHash); + + pHashTable = (TMPQHash *)LoadMpqTable(ha, ByteOffset, dwTableSize, g_dwHashTableKey, &dwRealTableSize); +#endif // DumpHashTable(pHashTable, pHeader->dwHashTableSize); // If the hash table was cut, we can/have to defragment it @@ -2384,7 +2406,7 @@ static TMPQHash * LoadHashTable(TMPQArchive * ha) ha->dwFlags |= (MPQ_FLAG_MALFORMED | MPQ_FLAG_HASH_TABLE_CUT); } break; - +#ifdef FULL case MPQ_SUBTYPE_SQP: pHashTable = LoadSqpHashTable(ha); break; @@ -2392,6 +2414,7 @@ static TMPQHash * LoadHashTable(TMPQArchive * ha) case MPQ_SUBTYPE_MPK: pHashTable = LoadMpkHashTable(ha); break; +#endif } // Return the loaded hash table @@ -2415,7 +2438,9 @@ TMPQBlock * LoadBlockTable(TMPQArchive * ha, bool /* bDontFixEntries */) TMPQBlock * pBlockTable = NULL; ULONGLONG ByteOffset; DWORD dwTableSize; +#ifdef FULL DWORD dwCmpSize; +#endif DWORD dwRealTableSize; // Note: It is possible that the block table starts at offset 0 @@ -2433,18 +2458,24 @@ TMPQBlock * LoadBlockTable(TMPQArchive * ha, bool /* bDontFixEntries */) case MPQ_SUBTYPE_MPQ: // Calculate byte position of the block table +#ifdef FULL ByteOffset = FileOffsetFromMpqOffset(ha, MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos)); dwTableSize = pHeader->dwBlockTableSize * sizeof(TMPQBlock); dwCmpSize = (DWORD)pHeader->BlockTableSize64; // Read, decrypt and uncompress the block table pBlockTable = (TMPQBlock * )LoadMpqTable(ha, ByteOffset, NULL, dwCmpSize, dwTableSize, g_dwBlockTableKey, &dwRealTableSize); +#else + ByteOffset = FileOffsetFromMpqOffset(ha, pHeader->dwBlockTablePos); + dwTableSize = pHeader->dwBlockTableSize * sizeof(TMPQBlock); + pBlockTable = (TMPQBlock * )LoadMpqTable(ha, ByteOffset, dwTableSize, g_dwBlockTableKey, &dwRealTableSize); +#endif // If the block table was cut, we need to remember it if(pBlockTable != NULL && dwRealTableSize && dwRealTableSize < dwTableSize) ha->dwFlags |= (MPQ_FLAG_MALFORMED | MPQ_FLAG_BLOCK_TABLE_CUT); break; - +#ifdef FULL case MPQ_SUBTYPE_SQP: pBlockTable = LoadSqpBlockTable(ha); @@ -2454,6 +2485,7 @@ TMPQBlock * LoadBlockTable(TMPQArchive * ha, bool /* bDontFixEntries */) pBlockTable = LoadMpkBlockTable(ha); break; +#endif } return pBlockTable; @@ -2511,7 +2543,11 @@ DWORD LoadAnyHashTable(TMPQArchive * ha) TMPQHeader * pHeader = ha->pHeader; // If the MPQ archive is empty, don't bother trying to load anything +#ifdef FULL if(pHeader->dwHashTableSize == 0 && pHeader->HetTableSize64 == 0) +#else + if(pHeader->dwHashTableSize == 0) +#endif return CreateHashTable(ha, HASH_TABLE_SIZE_DEFAULT); #ifdef FULL @@ -2568,7 +2604,7 @@ static DWORD BuildFileTable_Classic(TMPQArchive * ha) { dwErrCode = ERROR_NOT_ENOUGH_MEMORY; } - +#ifdef FULL // Load the hi-block table if(dwErrCode == ERROR_SUCCESS && pHeader->HiBlockTablePos64 != 0) { @@ -2607,7 +2643,7 @@ static DWORD BuildFileTable_Classic(TMPQArchive * ha) dwErrCode = ERROR_NOT_ENOUGH_MEMORY; } } - +#endif return dwErrCode; } diff --git a/3rdParty/StormLib/src/SBaseSubTypes.cpp b/3rdParty/StormLib/src/SBaseSubTypes.cpp index 99203d678d5..cd5f6be02e9 100644 --- a/3rdParty/StormLib/src/SBaseSubTypes.cpp +++ b/3rdParty/StormLib/src/SBaseSubTypes.cpp @@ -11,7 +11,7 @@ #define __STORMLIB_SELF__ #include "StormLib.h" #include "StormCommon.h" - +#ifdef FULL /*****************************************************************************/ /* */ /* Support for SQP file format (War of the Immortals) */ @@ -97,7 +97,6 @@ DWORD ConvertSqpHeaderToFormat4( ULONGLONG FileSize, DWORD dwFlags) { -#ifdef FULL TSQPHeader * pSqpHeader = (TSQPHeader *)ha->HeaderData; TMPQHeader Header; @@ -152,7 +151,7 @@ DWORD ConvertSqpHeaderToFormat4( return ERROR_SUCCESS; } } -#endif + return ERROR_FILE_CORRUPT; } @@ -630,3 +629,4 @@ TMPQBlock * LoadMpkBlockTable(TMPQArchive * ha) return pBlockTable; } +#endif // FULL \ No newline at end of file diff --git a/3rdParty/StormLib/src/SFileOpenArchive.cpp b/3rdParty/StormLib/src/SFileOpenArchive.cpp index 4f4f28698df..908b0f20d6c 100644 --- a/3rdParty/StormLib/src/SFileOpenArchive.cpp +++ b/3rdParty/StormLib/src/SFileOpenArchive.cpp @@ -21,10 +21,9 @@ //----------------------------------------------------------------------------- // Local functions - +#ifdef FULL static MTYPE CheckMapType(LPCTSTR szFileName, LPBYTE pbHeaderBuffer, size_t cbHeaderBuffer) { -#ifdef FULL LPDWORD HeaderInt32 = (LPDWORD)pbHeaderBuffer; LPCTSTR szExtension; @@ -71,7 +70,7 @@ static MTYPE CheckMapType(LPCTSTR szFileName, LPBYTE pbHeaderBuffer, size_t cbHe if(0 < HeaderInt32[0x0F] && HeaderInt32[0x0F] < 0x10000) return MapTypeWarcraft3; } -#endif + // No special map type recognized return MapTypeNotRecognized; } @@ -102,14 +101,14 @@ static TMPQUserData * IsValidMpqUserData(ULONGLONG ByteOffset, ULONGLONG FileSiz return NULL; } - +#endif // This function gets the right positions of the hash table and the block table. static DWORD VerifyMpqTablePositions(TMPQArchive * ha, ULONGLONG FileSize) { TMPQHeader * pHeader = ha->pHeader; ULONGLONG ByteOffset; //bool bMalformed = (ha->dwFlags & MPQ_FLAG_MALFORMED) ? true : false; - +#ifdef FULL // Check the begin of HET table if(pHeader->HetTablePos64) { @@ -149,7 +148,23 @@ static DWORD VerifyMpqTablePositions(TMPQArchive * ha, ULONGLONG FileSize) // if(ByteOffset > FileSize) // return ERROR_BAD_FORMAT; //} +#else + // Check the begin of hash table + if(pHeader->dwHashTablePos) + { + ByteOffset = FileOffsetFromMpqOffset(ha, pHeader->dwHashTablePos); + if(ByteOffset > FileSize) + return ERROR_BAD_FORMAT; + } + // Check the begin of block table + if(pHeader->dwBlockTablePos) + { + ByteOffset = FileOffsetFromMpqOffset(ha, pHeader->dwBlockTablePos); + if(ByteOffset > FileSize) + return ERROR_BAD_FORMAT; + } +#endif // All OK. return ERROR_SUCCESS; } @@ -214,7 +229,9 @@ HANDLE WINAPI SFileOpenArchive( const TCHAR * szMpqName, DWORD dwFlags) { +#ifdef FULL TMPQUserData * pUserData; +#endif TFileStream * pStream = NULL; // Open file stream TMPQArchive * ha = NULL; // Archive handle TFileEntry * pFileEntry; @@ -256,7 +273,7 @@ HANDLE WINAPI SFileOpenArchive( if((ha = STORM_ALLOC(TMPQArchive, 1)) == NULL) dwErrCode = ERROR_NOT_ENOUGH_MEMORY; } - +#ifdef FULL // Allocate buffer for searching MPQ header if(dwErrCode == ERROR_SUCCESS) { @@ -264,23 +281,25 @@ HANDLE WINAPI SFileOpenArchive( if(pbHeaderBuffer == NULL) dwErrCode = ERROR_NOT_ENOUGH_MEMORY; } - +#endif // Find the position of MPQ header if(dwErrCode == ERROR_SUCCESS) { ULONGLONG ByteOffset = 0; +#ifdef FULL ULONGLONG EndOfSearch = FileSize; DWORD dwStrmFlags = 0; DWORD dwHeaderSize; DWORD dwHeaderID; bool bSearchComplete = false; - +#endif memset(ha, 0, sizeof(TMPQArchive)); #ifdef FULL ha->dwValidFileFlags = MPQ_FILE_VALID_FLAGS; #endif ha->pfnHashString = HashStringSlash; ha->pStream = pStream; +#ifdef FULL pStream = NULL; // Set the archive read only if the stream is read-only @@ -364,8 +383,15 @@ HANDLE WINAPI SFileOpenArchive( dwHeaderSize = BSWAP_INT32_UNSIGNED(ha->HeaderData[1]); if(dwHeaderID == g_dwMpqSignature && dwHeaderSize >= MPQ_HEADER_SIZE_V1) { +#else + if(!FileStream_Read(ha->pStream, &ByteOffset, ha->HeaderData, sizeof(ha->HeaderData))) + { + dwErrCode = GetLastError(); + } else { +#endif // FULL // Now convert the header to version 4 dwErrCode = ConvertMpqHeaderToFormat4(ha, ByteOffset, FileSize, dwFlags, MapType); +#ifdef FULL if(dwErrCode != ERROR_FAKE_MPQ_HEADER) { bSearchComplete = true; @@ -393,15 +419,17 @@ HANDLE WINAPI SFileOpenArchive( // Move the pointers ByteOffset += 0x200; } +#endif // FULL } // Did we identify one of the supported headers? if(dwErrCode == ERROR_SUCCESS) { +#ifdef FULL // Set the user data position to the MPQ header, if none if(ha->pUserData == NULL) ha->UserDataPos = ByteOffset; - +#endif // Set the position of the MPQ header ha->pHeader = (TMPQHeader *)ha->HeaderData; ha->MpqPos = ByteOffset; @@ -418,7 +446,7 @@ HANDLE WINAPI SFileOpenArchive( { // Dump the header // DumpMpqHeader(ha->pHeader); - +#ifdef FULL // W3x Map Protectors use the fact that War3's Storm.dll ignores the MPQ user data, // and ignores the MPQ format version as well. The trick is to // fake MPQ format 2, with an improper hi-word position of hash table and block table @@ -430,7 +458,7 @@ HANDLE WINAPI SFileOpenArchive( ha->dwFlags |= MPQ_FLAG_READ_ONLY; ha->pUserData = NULL; } - +#endif // Anti-overflow. If the hash table size in the header is // higher than 0x10000000, it would overflow in 32-bit version // Observed in the malformed Warcraft III maps diff --git a/3rdParty/StormLib/src/SFileReadFile.cpp b/3rdParty/StormLib/src/SFileReadFile.cpp index df415624f3e..84ca9db39f0 100644 --- a/3rdParty/StormLib/src/SFileReadFile.cpp +++ b/3rdParty/StormLib/src/SFileReadFile.cpp @@ -56,7 +56,11 @@ static DWORD ReadMpqSectors(TMPQFile * hf, LPBYTE pbBuffer, DWORD dwByteOffset, if (pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK) { // If the sector positions are not loaded yet, do it if (hf->SectorOffsets == NULL) { +#ifdef FULL dwErrCode = AllocateSectorOffsets(hf, true); +#else + dwErrCode = AllocateSectorOffsets(hf); +#endif if (dwErrCode != ERROR_SUCCESS || hf->SectorOffsets == NULL) return dwErrCode; } @@ -71,8 +75,11 @@ static DWORD ReadMpqSectors(TMPQFile * hf, LPBYTE pbBuffer, DWORD dwByteOffset, // We only try to load sector CRCs once, and regardless if it fails // or not, we won't try that again for the given file. // - +#ifdef FULL AllocateSectorChecksums(hf, true); +#else + AllocateSectorChecksums(hf); +#endif hf->bLoadedSectorCRCs = true; } diff --git a/3rdParty/StormLib/src/StormCommon.h b/3rdParty/StormLib/src/StormCommon.h index ddb6949db8a..638e108a29f 100644 --- a/3rdParty/StormLib/src/StormCommon.h +++ b/3rdParty/StormLib/src/StormCommon.h @@ -331,7 +331,7 @@ bool QueryMpqSignatureInfo(TMPQArchive * ha, PMPQ_SIGNATURE_INFO pSignatureInfo) //----------------------------------------------------------------------------- // Support for alternate file formats (SBaseSubTypes.cpp) - +#ifdef FULL DWORD ConvertSqpHeaderToFormat4(TMPQArchive * ha, ULONGLONG FileSize, DWORD dwFlags); TMPQHash * LoadSqpHashTable(TMPQArchive * ha); TMPQBlock * LoadSqpBlockTable(TMPQArchive * ha); @@ -343,19 +343,26 @@ TMPQBlock * LoadMpkBlockTable(TMPQArchive * ha); #ifdef FULL int SCompDecompressMpk(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer); #endif // FULL - +#endif // FULL //----------------------------------------------------------------------------- // Common functions - MPQ File TMPQFile * CreateFileHandle(TMPQArchive * ha, TFileEntry * pFileEntry); //TMPQFile * CreateWritableHandle(TMPQArchive * ha, DWORD dwFileSize); +#ifdef FULL void * LoadMpqTable(TMPQArchive * ha, ULONGLONG ByteOffset, LPBYTE pbTableHash, DWORD dwCompressedSize, DWORD dwRealSize, DWORD dwKey, DWORD * PtrRealTableSize); +#else +void * LoadMpqTable(TMPQArchive * ha, ULONGLONG ByteOffset, DWORD dwRealSize, DWORD dwKey, DWORD * PtrRealTableSize); +#endif DWORD AllocateSectorBuffer(TMPQFile * hf); #ifdef FULL DWORD AllocatePatchInfo(TMPQFile * hf, bool bLoadFromFile); -#endif DWORD AllocateSectorOffsets(TMPQFile * hf, bool bLoadFromFile); DWORD AllocateSectorChecksums(TMPQFile * hf, bool bLoadFromFile); +#else +DWORD AllocateSectorOffsets(TMPQFile * hf); +DWORD AllocateSectorChecksums(TMPQFile * hf); +#endif //DWORD WritePatchInfo(TMPQFile * hf); //DWORD WriteSectorOffsets(TMPQFile * hf); //DWORD WriteSectorChecksums(TMPQFile * hf); diff --git a/3rdParty/StormLib/src/StormLib.h b/3rdParty/StormLib/src/StormLib.h index a9ee8567e5d..3b64c86bb19 100644 --- a/3rdParty/StormLib/src/StormLib.h +++ b/3rdParty/StormLib/src/StormLib.h @@ -506,10 +506,14 @@ typedef struct TMPQBits TMPQBits; // #define MPQ_HEADER_SIZE_V1 0x20 +#ifdef FULL #define MPQ_HEADER_SIZE_V2 0x2C #define MPQ_HEADER_SIZE_V3 0x44 #define MPQ_HEADER_SIZE_V4 0xD0 #define MPQ_HEADER_DWORDS (MPQ_HEADER_SIZE_V4 / 0x04) +#else +#define MPQ_HEADER_DWORDS (MPQ_HEADER_SIZE_V1 / 0x04) +#endif typedef struct _TMPQUserData { @@ -568,7 +572,7 @@ typedef struct _TMPQHeader // Number of entries in the block table DWORD dwBlockTableSize; - +#ifdef FULL //-- MPQ HEADER v 2 ------------------------------------------- // Offset to the beginning of array of 16-bit high parts of file offsets. @@ -619,6 +623,7 @@ typedef struct _TMPQHeader unsigned char MD5_BetTable[MD5_DIGEST_SIZE]; // MD5 of the BET table before decryption unsigned char MD5_HetTable[MD5_DIGEST_SIZE]; // MD5 of the HET table before decryption unsigned char MD5_MpqHeader[MD5_DIGEST_SIZE]; // MD5 of the MPQ header from signature to (including) MD5_HetTable +#endif } TMPQHeader; #pragma pack(pop) @@ -831,16 +836,17 @@ typedef struct _TMPQNameCache typedef struct _TMPQArchive { TFileStream * pStream; // Open stream for the MPQ - +#ifdef FULL ULONGLONG UserDataPos; // Position of user data (relative to the begin of the file) +#endif ULONGLONG MpqPos; // MPQ header offset (relative to the begin of the file) ULONGLONG FileSize; // Size of the file at the moment of file open #ifdef FULL struct _TMPQArchive * haPatch; // Pointer to patch archive, if any struct _TMPQArchive * haBase; // Pointer to base ("previous version") archive, if any TMPQNamePrefix * pPatchPrefix; // Patch prefix to precede names of patch files -#endif TMPQUserData * pUserData; // MPQ user data (NULL if not present in the file) +#endif TMPQHeader * pHeader; // MPQ file header TMPQHash * pHashTable; // Hash table #ifdef FULL @@ -849,7 +855,9 @@ typedef struct _TMPQArchive TFileEntry * pFileTable; // File table HASH_STRING pfnHashString; // Hashing function that will convert the file name into hash +#ifdef FULL TMPQUserData UserData; // MPQ user data. Valid only when ID_MPQ_USERDATA has been found +#endif DWORD HeaderData[MPQ_HEADER_DWORDS]; // Storage for MPQ header #ifdef FULL DWORD dwHETBlockSize; From 79e61777611e2fa6d54a06a42ed20818a359dd7c Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 5 Jan 2024 10:50:27 +0100 Subject: [PATCH 234/596] ensure a rune is placed in line-of-sight + return MIRES* from PlaceRune --- Source/missiles.cpp | 44 ++++++++++++-------------------------------- 1 file changed, 12 insertions(+), 32 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 4a8cddc05c8..c92098f8061 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -1560,7 +1560,7 @@ void InitMissiles() } #ifdef HELLFIRE -static bool PlaceRune(int mi, int dx, int dy, int mitype, int mirange) +static int PlaceRune(int mi, int sx, int sy, int dx, int dy, int mitype, int mirange) { int i, j, tx, ty; const int8_t* cr; @@ -1582,16 +1582,16 @@ static bool PlaceRune(int mi, int dx, int dy, int mitype, int mirange) tx = dx + *++cr; ty = dy + *++cr; assert(IN_DUNGEON_AREA(tx, ty)); - if (PosOkMissile(tx, ty)) { + if (PosOkMissile(tx, ty) && LineClear(sx, sy, tx, ty)) { mis->_mix = tx; mis->_miy = ty; static_assert(MAX_LIGHT_RAD >= 8, "PlaceRune needs at least light-radius of 8."); mis->_miLid = AddLight(tx, ty, 8); - return true; + return MIRES_DONE; } } } - return false; + return MIRES_FAIL_DELETE; } /** @@ -1601,11 +1601,7 @@ static bool PlaceRune(int mi, int dx, int dy, int mitype, int mirange) */ int AddFireRune(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { - if (LineClear(sx, sy, dx, dy)) { - if (PlaceRune(mi, dx, dy, MIS_FIREEXP, 0)) - return MIRES_DONE; - } - return MIRES_FAIL_DELETE; + return PlaceRune(mi, sx, sy, dx, dy, MIS_FIREEXP, 0); } /** @@ -1615,12 +1611,8 @@ int AddFireRune(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, */ int AddLightRune(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { - if (LineClear(sx, sy, dx, dy)) { - static_assert(DBORDERX >= 1 && DBORDERY >= 1, "AddLightRune expects a large enough border."); - if (PlaceRune(mi, dx, dy, MIS_LIGHTNINGC, 1)) - return MIRES_DONE; - } - return MIRES_FAIL_DELETE; + static_assert(DBORDERX >= 1 && DBORDERY >= 1, "AddLightRune expects a large enough border."); + return PlaceRune(mi, sx, sy, dx, dy, MIS_LIGHTNINGC, 1); } /** @@ -1630,12 +1622,8 @@ int AddLightRune(int mi, int sx, int sy, int dx, int dy, int midir, int micaster */ int AddNovaRune(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { - if (LineClear(sx, sy, dx, dy)) { - static_assert(DBORDERX >= 1 && DBORDERY >= 1, "AddNovaRune expects a large enough border."); - if (PlaceRune(mi, dx, dy, MIS_LIGHTNOVAC, 1)) - return MIRES_DONE; - } - return MIRES_FAIL_DELETE; + static_assert(DBORDERX >= 1 && DBORDERY >= 1, "AddNovaRune expects a large enough border."); + return PlaceRune(mi, sx, sy, dx, dy, MIS_LIGHTNOVAC, 1); } /** @@ -1645,12 +1633,8 @@ int AddNovaRune(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, */ int AddWaveRune(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { - if (LineClear(sx, sy, dx, dy)) { - static_assert(DBORDERX >= 1 && DBORDERY >= 1, "AddWaveRune expects a large enough border."); - if (PlaceRune(mi, dx, dy, MIS_FIREWAVEC, 1)) - return MIRES_DONE; - } - return MIRES_FAIL_DELETE; + static_assert(DBORDERX >= 1 && DBORDERY >= 1, "AddWaveRune expects a large enough border."); + return PlaceRune(mi, sx, sy, dx, dy, MIS_FIREWAVEC, 1); } /** @@ -1660,11 +1644,7 @@ int AddWaveRune(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, */ int AddStoneRune(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { - if (LineClear(sx, sy, dx, dy)) { - if (PlaceRune(mi, dx, dy, MIS_STONE, 0)) - return MIRES_DONE; - } - return MIRES_FAIL_DELETE; + return PlaceRune(mi, sx, sy, dx, dy, MIS_STONE, 0); } int AddHorkSpawn(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) From 917278b47634feb9c5a9dcc4b30acd1bfe9a5120 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 5 Jan 2024 11:08:43 +0100 Subject: [PATCH 235/596] ensure every cast is limited - limit stone-curse and town-portal to line-of-sight - limit teleport to distance - prevent rune from firing out-of-sight --- Source/missiles.cpp | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index c92098f8061..3e226ec2477 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -2038,6 +2038,17 @@ int AddTeleport(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int i, j, tx, ty; const int8_t* cr; + // MisInCastDistance(sx, sy, midir, dx, dy, 7); + while (true) { + tx = abs(sx - dx); + ty = abs(sy - dy); + i = sqrt(tx * tx + ty * ty); + if (i <= 7) + break; + dx += offset_x[OPPOSITE(midir)]; + dy += offset_y[OPPOSITE(midir)]; + } + assert((unsigned)misource < MAX_PLRS); static_assert(DBORDERX >= 5 && DBORDERY >= 5, "AddTeleport expects a large enough border."); for (i = 0; i <= 5; i++) { @@ -2360,11 +2371,9 @@ int AddTown(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int tx = dx + *++cr; ty = dy + *++cr; assert(IN_DUNGEON_AREA(tx, ty)); - if (PosOkMissile(tx, ty)) { - if (!CheckIfTrig(tx, ty)) { - i = RANGE; - break; - } + if (PosOkMissile(tx, ty) && !CheckIfTrig(tx, ty) && LineClear(sx, sy, tx, ty)) { + i = RANGE; + break; } } } @@ -2690,7 +2699,7 @@ int AddStone(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in ty = dy + *++cr; assert(IN_DUNGEON_AREA(tx, ty)); mid = dMonster[tx][ty] - 1; - if (mid < MAX_MINIONS) + if (mid < MAX_MINIONS || !LineClear(sx, sy, tx, ty)) continue; mon = &monsters[mid]; if (!(mon->_mFlags & MFLAG_NOSTONE) && !CanTalkToMonst(mid) @@ -3817,7 +3826,7 @@ void MI_HorkSpawn(int mi) void MI_Rune(int mi) { MissileStruct* mis; - int j, mnum, tx, ty; + int j, mnum, sx, sy, tx, ty; const int8_t* cr; mis = &missile[mi]; @@ -3827,10 +3836,12 @@ void MI_Rune(int mi) return; } if (--mis->_miVar3 < 0) { + sx = mis->_mix; + sy = mis->_miy; cr = &CrawlTable[CrawlNum[mis->_miVar2]]; for (j = *cr; j > 0; j--) { - tx = mis->_mix + *++cr; - ty = mis->_miy + *++cr; + tx = sx + *++cr; + ty = sy + *++cr; if (dPlayer[tx][ty] == 0) { mnum = dMonster[tx][ty]; if (mnum == 0) @@ -3839,8 +3850,10 @@ void MI_Rune(int mi) if (monsters[mnum]._mmode == MM_STONE || monsters[mnum]._mmode == MM_DEATH) continue; } + if (!LineClear(sx, sy, tx, ty)) + continue; // SetRndSeed(mis->_miRndSeed); - AddMissile(mis->_mix, mis->_miy, tx, ty, 0, mis->_miVar1, mis->_miCaster, mis->_miSource, mis->_miSpllvl); + AddMissile(sx, sy, tx, ty, 0, mis->_miVar1, mis->_miCaster, mis->_miSource, mis->_miSpllvl); mis->_miRange -= 48; mis->_miVar3 = 48; break; From cd53896428b480b2ca8a8909ce80b6da976efc72 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 5 Jan 2024 11:13:29 +0100 Subject: [PATCH 236/596] cosmetic --- Source/missiles.cpp | 44 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 3e226ec2477..0f7ffa8668e 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -2305,15 +2305,13 @@ int AddShroud(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, i tx = dx + *++cr; ty = dy + *++cr; assert(IN_DUNGEON_AREA(tx, ty)); - if (LineClear(sx, sy, tx, ty)) { - if (PosOkMissile(tx, ty)) { - mis->_mix = tx; - mis->_miy = ty; - //mis->_misx = tx; - //mis->_misy = ty; - mis->_miRange = 32 * spllvl + 160; - return MIRES_DONE; - } + if (PosOkMissile(tx, ty) && LineClear(sx, sy, tx, ty)) { + mis->_mix = tx; + mis->_miy = ty; + //mis->_misx = tx; + //mis->_misy = ty; + mis->_miRange = 32 * spllvl + 160; + return MIRES_DONE; } } } @@ -2750,17 +2748,15 @@ int AddGuardian(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, tx = dx + *++cr; ty = dy + *++cr; assert(IN_DUNGEON_AREA(tx, ty)); - if (LineClear(sx, sy, tx, ty)) { - if (PosOkMissile(tx, ty)) { - mis->_mix = tx; - mis->_miy = ty; - mis->_misx = tx; - mis->_misy = ty; - static_assert(MAX_LIGHT_RAD >= 1, "AddGuardian needs at least light-radius of 1."); - mis->_miLid = AddLight(tx, ty, 1); - mis->_miRange = spllvl + (plx(misource)._pLevel >> 1); - return MIRES_DONE; - } + if (PosOkMissile(tx, ty) && LineClear(sx, sy, tx, ty)) { + mis->_mix = tx; + mis->_miy = ty; + mis->_misx = tx; + mis->_misy = ty; + static_assert(MAX_LIGHT_RAD >= 1, "AddGuardian needs at least light-radius of 1."); + mis->_miLid = AddLight(tx, ty, 1); + mis->_miRange = spllvl + (plx(misource)._pLevel >> 1); + return MIRES_DONE; } } } @@ -2784,11 +2780,9 @@ int AddGolem(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in tx = dx + *++cr; ty = dy + *++cr; assert(IN_DUNGEON_AREA(tx, ty)); - if (LineClear(sx, sy, tx, ty)) { - if (PosOkActor(tx, ty)) { - SpawnGolem(misource, tx, ty, spllvl); - return MIRES_DELETE; - } + if (PosOkActor(tx, ty) && LineClear(sx, sy, tx, ty)) { + SpawnGolem(misource, tx, ty, spllvl); + return MIRES_DELETE; } } } From ddf5bd695bd4e6cd86186cca0d9c05faf0f86f17 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 5 Jan 2024 11:35:44 +0100 Subject: [PATCH 237/596] validate SDFLAG_TARGETED of SPL_TELEPORT --- Source/debug.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/debug.cpp b/Source/debug.cpp index d10aa219d2b..d27a80b0be8 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -1069,7 +1069,7 @@ void ValidateData() #endif // spells - bool hasBookSpell = false, hasStaffSpell = false, hasScrollSpell = false, hasRuneSpell = false; + assert(spelldata[SPL_TELEPORT].sSkillFlags & SDFLAG_TARGETED); // required by AddTeleport #define OBJ_TARGETING_CURSOR(x) ((x) == CURSOR_NONE || (x) == CURSOR_DISARM) assert(OBJ_TARGETING_CURSOR(spelldata[SPL_DISARM].scCurs)); // required by TryIconCurs assert(OBJ_TARGETING_CURSOR(spelldata[SPL_DISARM].spCurs)); // required by TryIconCurs @@ -1096,6 +1096,7 @@ void ValidateData() #define SPEC_TARGETING_CURSOR(x) ((x) == CURSOR_NONE || (x) == CURSOR_TELEKINESIS) assert(SPEC_TARGETING_CURSOR(spelldata[SPL_TELEKINESIS].scCurs)); // required by TryIconCurs assert(SPEC_TARGETING_CURSOR(spelldata[SPL_TELEKINESIS].spCurs)); // required by TryIconCurs + bool hasBookSpell = false, hasStaffSpell = false, hasScrollSpell = false, hasRuneSpell = false; for (i = 0; i < NUM_SPELLS; i++) { const SpellData& sd = spelldata[i]; if (i == SPL_DISARM From 405be1fb6dcf84b7a3223c3fe6ffc6bef20fb14e Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 6 Jan 2024 11:39:17 +0100 Subject: [PATCH 238/596] place the same number of monsters regardless if it is a single- or multi-player game --- Source/debug.cpp | 2 + Source/monstdat.cpp | 274 ++++++++++++++++++++++---------------------- Source/monster.cpp | 2 - Source/questdat.cpp | 52 ++++----- 4 files changed, 165 insertions(+), 165 deletions(-) diff --git a/Source/debug.cpp b/Source/debug.cpp index d27a80b0be8..f06e59d27a0 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -243,6 +243,8 @@ void ValidateData() app_fatal("Too low dLevel on level %s (%d)", AllLevels[i].dLevelName, i); if ((AllLevels[i].dLevel * 8 - AllLevels[i].dLevel * 2) >= 0x7FFF) // required by GetItemAttrs app_fatal("Too high dLevel on level %s (%d)", AllLevels[i].dLevelName, i); + if (AllLevels[i].dMonDensity > UINT_MAX / (DSIZEX * DSIZEY)) + app_fatal("Too high dMonDensity on level %s (%d)", AllLevels[i].dLevelName, i); // required by InitMonsters } { BYTE lvlMask = 1 << AllLevels[questlist[Q_BLOOD]._qdlvl].dType; diff --git a/Source/monstdat.cpp b/Source/monstdat.cpp index 790cca59191..94ba78110fe 100644 --- a/Source/monstdat.cpp +++ b/Source/monstdat.cpp @@ -13,145 +13,145 @@ DEVILUTION_BEGIN_NAMESPACE const MonsterData monsterdata[NUM_MTYPES] = { // clang-format off // moFileNum, mLevel, mSelFlag, mTransFile, mName, mAI.aiType, aiInt, aiParam1, aiParam2, mMinHP, mMaxHP, mFlags, mHit, mMinDamage, mMaxDamage, mHit2, mMinDamage2, mMaxDamage2, mMagic, mMagic2, mArmorClass, mEvasion, mMagicRes, mMagicRes2, mExp, -/* MT_NZOMBIE */ { MOFILE_ZOMBIE, 1, 3, NULL, "Zombie", { AI_ZOMBIE, 0, 0, 0 }, 4, 7, 0 , 10, 2, 5, 0, 0, 0, 0, 0, 5, 5, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , 54, ALIGN }, // MC_UNDEAD, -/* MT_BZOMBIE */ { MOFILE_ZOMBIE, 2, 3, "Monsters\\Zombie\\Bluered.TRN", "Ghoul", { AI_ZOMBIE, 1, 0, 0 }, 7, 11, 0 , 10, 3, 10, 0, 0, 0, 0, 0, 10, 10, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , 58, ALIGN }, // MC_UNDEAD, -/* MT_GZOMBIE */ { MOFILE_ZOMBIE, 4, 3, "Monsters\\Zombie\\Grey.TRN", "Rotting Carcass", { AI_ZOMBIE, 2, 0, 0 }, 15, 25, 0 , 25, 5, 15, 0, 0, 0, 0, 0, 15, 10, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST , 136, ALIGN }, // MC_UNDEAD, -/* MT_YZOMBIE */ { MOFILE_ZOMBIE, 6, 3, "Monsters\\Zombie\\Yellow.TRN", "Black Death", { AI_ZOMBIE, 3, 0, 0 }, 25, 40, 0 , 30, 6, 22, 0, 0, 0, 0, 0, 20, 10, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST , 240, ALIGN }, // MC_UNDEAD, -/* MT_RFALLSP */ { MOFILE_FALLSP, 1, 3, "Monsters\\FalSpear\\FallenT.TRN", "Fallen One", { AI_FALLEN, 0, 0, 0 }, 1, 4, 0 , 15, 1, 3, 0, 0, 0, 0, 0, 0, 0, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 46, ALIGN }, // MC_ANIMAL, -/* MT_DFALLSP */ { MOFILE_FALLSP, 3, 3, "Monsters\\FalSpear\\Dark.TRN", "Carver", { AI_FALLEN, 2, 0, 0 }, 4, 8, 0 , 20, 2, 5, 0, 0, 0, 0, 0, 5, 5, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 80, ALIGN }, // MC_ANIMAL, -/* MT_YFALLSP */ { MOFILE_FALLSP, 5, 3, NULL, "Devil Kin", { AI_FALLEN, 2, 0, 0 }, 12, 24, 0 , 25, 3, 7, 0, 0, 0, 0, 0, 10, 10, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 155, ALIGN }, // MC_ANIMAL, -/* MT_BFALLSP */ { MOFILE_FALLSP, 7, 3, "Monsters\\FalSpear\\Blue.TRN", "Dark One", { AI_FALLEN, 3, 0, 0 }, 20, 36, 0 , 30, 4, 8, 0, 0, 0, 0, 0, 15, 15, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 255, ALIGN }, // MC_ANIMAL, -/* MT_WSKELAX */ { MOFILE_SKELAX, 1, 3, "Monsters\\SkelSd\\White.TRN", "Skeleton", { AI_SKELSD, 0, 0, 0 }, 2, 4, 0 , 20, 1, 4, 0, 0, 0, 0, 0, 0, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , 64, ALIGN }, // MC_UNDEAD, -/* MT_TSKELAX */ { MOFILE_SKELAX, 2, 3, "Monsters\\SkelSd\\Skelt.TRN", "Corpse Axe", { AI_SKELSD, 1, 0, 0 }, 4, 7, 0 , 25, 3, 5, 0, 0, 0, 0, 0, 0, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , 68, ALIGN }, // MC_UNDEAD, -/* MT_RSKELAX */ { MOFILE_SKELAX, 4, 3, NULL, "Burning Dead", { AI_SKELSD, 2, 0, 0 }, 8, 12, 0 , 30, 3, 7, 0, 0, 0, 0, 0, 5, 5, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE , 154, ALIGN }, // MC_UNDEAD, -/* MT_XSKELAX */ { MOFILE_SKELAX, 6, 3, "Monsters\\SkelSd\\Black.TRN", "Horror", { AI_SKELSD, 3, 0, 0 }, 12, 20, 0 , 35, 4, 9, 0, 0, 0, 0, 0, 15, 10, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST , 264, ALIGN }, // MC_UNDEAD, -/* MT_RFALLSD */ { MOFILE_FALLSD, 1, 3, "Monsters\\FalSpear\\FallenT.TRN", "Fallen One", { AI_FALLEN, 0, 0, 0 }, 2, 5, 0 , 15, 1, 4, 0, 0, 0, 0, 0, 10, 10, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 52, ALIGN }, // MC_ANIMAL, -/* MT_DFALLSD */ { MOFILE_FALLSD, 3, 3, "Monsters\\FalSpear\\Dark.TRN", "Carver", { AI_FALLEN, 1, 0, 0 }, 5, 9, 0 , 20, 2, 7, 0, 0, 0, 0, 0, 15, 15, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 90, ALIGN }, // MC_ANIMAL, -/* MT_YFALLSD */ { MOFILE_FALLSD, 5, 3, NULL, "Devil Kin", { AI_FALLEN, 2, 0, 0 }, 16, 24, 0 , 25, 4, 10, 0, 0, 0, 0, 0, 20, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 180, ALIGN }, // MC_ANIMAL, -/* MT_BFALLSD */ { MOFILE_FALLSD, 7, 3, "Monsters\\FalSpear\\Blue.TRN", "Dark One", { AI_FALLEN, 3, 0, 0 }, 24, 36, 0 , 30, 4, 12, 0, 0, 0, 0, 0, 25, 25, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 280, ALIGN }, // MC_ANIMAL, -/* MT_NSCAV */ { MOFILE_SCAV, 2, 3, NULL, "Scavenger", { AI_SCAV, 0, 0, 0 }, 3, 6, 0 , 20, 1, 5, 0, 0, 0, 0, 0, 10, 10, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 80, ALIGN }, // MC_ANIMAL, -/* MT_BSCAV */ { MOFILE_SCAV, 4, 3, "Monsters\\Scav\\ScavBr.TRN", "Plague Eater", { AI_SCAV, 1, 0, 0 }, 12, 24, 0 , 30, 1, 8, 0, 0, 0, 0, 0, 20, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 188, ALIGN }, // MC_ANIMAL, -/* MT_WSCAV */ { MOFILE_SCAV, 6, 3, "Monsters\\Scav\\ScavBe.TRN", "Shadow Beast", { AI_SCAV, 2, 0, 0 }, 24, 36, 0 , 35, 3, 12, 0, 0, 0, 0, 0, 25, 25, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 375, ALIGN }, // MC_ANIMAL, -/* MT_YSCAV */ { MOFILE_SCAV, 8, 3, "Monsters\\Scav\\ScavW.TRN", "Bone Gasher", { AI_SCAV, 3, 0, 0 }, 28, 40, 0 , 35, 5, 15, 0, 0, 0, 0, 0, 30, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 552, ALIGN }, // MC_ANIMAL, -/* MT_WSKELBW */ { MOFILE_SKELBW, 3, 3, "Monsters\\SkelSd\\White.TRN", "Skeleton", { AI_SKELBOW, 0, 0, 0 }, 2, 4, 0 , 15, 1, 3, 0, 0, 0, 0, 0, 0, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , 110, ALIGN }, // MC_UNDEAD, -/* MT_TSKELBW */ { MOFILE_SKELBW, 5, 3, "Monsters\\SkelSd\\Skelt.TRN", "Corpse Bow", { AI_SKELBOW, 1, 0, 0 }, 8, 16, 0 , 25, 1, 4, 0, 0, 0, 0, 0, 0, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , 210, ALIGN }, // MC_UNDEAD, -/* MT_RSKELBW */ { MOFILE_SKELBW, 7, 3, NULL, "Burning Dead", { AI_SKELBOW, 2, 0, 0 }, 10, 24, 0 , 30, 1, 6, 0, 0, 0, 0, 0, 5, 5, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE , 364, ALIGN }, // MC_UNDEAD, -/* MT_XSKELBW */ { MOFILE_SKELBW, 9, 3, "Monsters\\SkelSd\\Black.TRN", "Horror", { AI_SKELBOW, 3, 0, 0 }, 15, 45, 0 , 35, 2, 9, 0, 0, 0, 0, 0, 15, 10, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST , 594, ALIGN }, // MC_UNDEAD, -/* MT_WSKELSD */ { MOFILE_SKELSD, 2, 3, "Monsters\\SkelSd\\White.TRN", "Skeleton Captain", { AI_SKELSD, 0, 0, 0 }, 3, 6, 0 , 20, 2, 7, 0, 0, 0, 0, 0, 10, 10, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , 90, ALIGN }, // MC_UNDEAD, -/* MT_TSKELSD */ { MOFILE_SKELSD, 4, 3, "Monsters\\SkelSd\\Skelt.TRN", "Corpse Captain", { AI_SKELSD, 1, 0, 0 }, 12, 20, 0 , 30, 3, 9, 0, 0, 0, 0, 0, 5, 5, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , 200, ALIGN }, // MC_UNDEAD, -/* MT_RSKELSD */ { MOFILE_SKELSD, 6, 3, NULL, "Burning Dead Captain", { AI_SKELSD, 2, 0, 0 }, 16, 30, 0 , 35, 4, 10, 0, 0, 0, 0, 0, 15, 10, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE , 393, ALIGN }, // MC_UNDEAD, -/* MT_XSKELSD */ { MOFILE_SKELSD, 8, 3, "Monsters\\SkelSd\\Black.TRN", "Horror Captain", { AI_SKELSD, 3, 0, 0 }, 35, 50, MFLAG_SEARCH , 40, 5, 14, 0, 0, 0, 0, 0, 30, 20, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST , 604, ALIGN }, // MC_UNDEAD, -/* MT_INVILORD *///{ MOFILE_TSNEAK, 0, 3, NULL, "Invisible Lord", { AI_SKELSD, 3, 0, 0 }, 278, 278, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 65, 16, 30, 0, 0, 0, 0, 0, 60, 50, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2000, ALIGN }, // MC_DEMON, -/* MT_NSNEAK */ { MOFILE_SNEAK, 5, 3, NULL, "Hidden", { AI_SNEAK, 0, 0, 0 }, 8, 24, MFLAG_HIDDEN , 35, 3, 6, 0, 0, 0, 0, 0, 25, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 278, ALIGN }, // MC_DEMON, -/* MT_RSNEAK */ { MOFILE_SNEAK, 9, 3, "Monsters\\Sneak\\Sneakv2.TRN", "Stalker", { AI_SNEAK, 1, 0, 0 }, 30, 45, MFLAG_HIDDEN | MFLAG_SEARCH , 40, 8, 16, 0, 0, 0, 0, 0, 30, 25, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 630, ALIGN }, // MC_DEMON, -/* MT_BSNEAK */ { MOFILE_SNEAK, 11, 3, "Monsters\\Sneak\\Sneakv3.TRN", "Unseen", { AI_SNEAK, 2, 0, 0 }, 35, 50, MFLAG_HIDDEN | MFLAG_SEARCH , 45, 12, 20, 0, 0, 0, 0, 0, 30, 25, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, 935, ALIGN }, // MC_DEMON, -/* MT_YSNEAK */ { MOFILE_SNEAK, 13, 3, "Monsters\\Sneak\\Sneakv1.TRN", "Illusion Weaver", { AI_SNEAK, 3, 0, 0 }, 40, 60, MFLAG_HIDDEN | MFLAG_SEARCH , 60, 16, 24, 0, 0, 0, 0, 0, 30, 25, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 1500, ALIGN }, // MC_DEMON, -/* MT_NGOATMC */ { MOFILE_GOATMC, 8, 3, NULL, "Flesh Clan", { AI_ROUND, 0, TRUE, 0 }, 30, 45, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 50, 4, 10, 10, 12, 16, 0, 0, 40, 35, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 460, ALIGN }, // MC_DEMON, -/* MT_BGOATMC */ { MOFILE_GOATMC, 10, 3, "Monsters\\GoatMace\\Beige.TRN", "Stone Clan", { AI_ROUND, 1, TRUE, 0 }, 40, 55, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 60, 6, 12, 15, 14, 20, 0, 0, 40, 35, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, 685, ALIGN }, // MC_DEMON, -/* MT_RGOATMC */ { MOFILE_GOATMC, 12, 3, "Monsters\\GoatMace\\Red.TRN", "Fire Clan", { AI_ROUND, 2, TRUE, 0 }, 50, 65, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 70, 8, 16, 15, 16, 24, 0, 0, 45, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 906, ALIGN }, // MC_DEMON, -/* MT_GGOATMC */ { MOFILE_GOATMC, 14, 3, "Monsters\\GoatMace\\Gray.TRN", "Night Clan", { AI_ROUND, 3, TRUE, 0 }, 55, 70, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 80, 10, 20, 20, 20, 30, 0, 0, 50, 45, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, 1190, ALIGN }, // MC_DEMON, -/* MT_RBAT */ { MOFILE_BAT, 3, 6, "Monsters\\Bat\\red.trn", "Fiend", { AI_BAT, 0, 0, 0 }, 3, 6, MFLAG_NODROP , 35, 1, 6, 0, 0, 0, 0, 0, 0, 0, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 102, ALIGN }, // MC_ANIMAL, -/* MT_NBAT */ { MOFILE_BAT, 7, 6, NULL, "Blink", { AI_BAT, 1, 0, 0 }, 12, 28, MFLAG_NODROP , 45, 1, 8, 0, 0, 0, 0, 0, 15, 15, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 340, ALIGN }, // MC_ANIMAL, -/* MT_GBAT */ { MOFILE_BAT, 9, 6, "Monsters\\Bat\\grey.trn", "Gloom", { AI_BAT, 2, 0, 0 }, 28, 36, MFLAG_NODROP | MFLAG_SEARCH , 70, 4, 12, 0, 0, 0, 0, 0, 35, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, 509, ALIGN }, // MC_ANIMAL, -/* MT_XBAT */ { MOFILE_BAT, 13, 6, "Monsters\\Bat\\orange.trn", "Familiar", { AI_BAT, 3, 0, 0 }, 20, 35, MFLAG_NODROP | MFLAG_SEARCH , 50, 4, 16, 0, 0, 0, 35, 0, 35, 35, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 448, ALIGN }, // MC_DEMON, -/* MT_NGOATBW */ { MOFILE_GOATBW, 8, 3, NULL, "Flesh Clan", { AI_RANGED, 0, MIS_ARROW, FALSE }, 20, 35, MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 35, 1, 7, 0, 0, 0, 0, 0, 35, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 448, ALIGN }, // MC_DEMON, -/* MT_BGOATBW */ { MOFILE_GOATBW, 10, 3, "Monsters\\GoatMace\\Beige.TRN", "Stone Clan", { AI_RANGED, 1, MIS_ARROW, FALSE }, 30, 40, MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 40, 2, 9, 0, 0, 0, 0, 0, 35, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, 645, ALIGN }, // MC_DEMON, -/* MT_RGOATBW */ { MOFILE_GOATBW, 12, 3, "Monsters\\GoatMace\\Red.TRN", "Fire Clan", { AI_RANGED, 2, MIS_ARROW, FALSE }, 40, 50, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 45, 3, 11, 0, 0, 0, 0, 0, 35, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 822, ALIGN }, // MC_DEMON, -/* MT_GGOATBW */ { MOFILE_GOATBW, 14, 3, "Monsters\\GoatMace\\Gray.TRN", "Night Clan", { AI_RANGED, 3, MIS_ARROW, FALSE }, 50, 65, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 50, 4, 13, 0, 0, 0, 0, 0, 40, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, 1092, ALIGN }, // MC_DEMON, -/* MT_NACID */ { MOFILE_ACID, 11, 3, NULL, "Acid Beast", { AI_ROUNDRANGED, 0, MIS_ACID, 1 }, 40, 66, 0 , 40, 4, 12, 0, 0, 0, 30, 0, 30, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, 846, ALIGN }, // MC_ANIMAL, -/* MT_RACID */ { MOFILE_ACID, 15, 3, "Monsters\\Acid\\AcidBlk.TRN", "Poison Spitter", { AI_ROUNDRANGED, 1, MIS_ACID, 1 }, 60, 85, 0 , 45, 4, 16, 0, 0, 0, 40, 0, 30, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, 1248, ALIGN }, // MC_ANIMAL, -/* MT_BACID */ { MOFILE_ACID, 21, 3, "Monsters\\Acid\\AcidB.TRN", "Pit Beast", { AI_ROUNDRANGED, 2, MIS_ACID, 1 }, 80, 110, 0 , 55, 8, 18, 0, 0, 0, 50, 0, 35, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2060, ALIGN }, // MC_ANIMAL, -/* MT_XACID */ { MOFILE_ACID, 25, 3, "Monsters\\Acid\\AcidR.TRN", "Lava Maw", { AI_ROUNDRANGED, 3, MIS_ACID, 1 }, 100, 150, 0 , 65, 10, 20, 0, 0, 0, 60, 0, 35, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 2940, ALIGN }, // MC_ANIMAL, -/* MT_SKING */ { MOFILE_SKING, 6, 7, "Monsters\\SkelSd\\White.TRN", "Skeleton King", { AI_SKELKING, 3, 0, 0 }, 140, 140, MFLAG_LIFESTEAL | MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 75, 6, 16, 0, 0, 0, 0, 0, 70, 30, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE , 570, ALIGN }, // MC_UNDEAD, -/* MT_CLEAVER */ { MOFILE_CLEAVER, 6, 3, NULL, "The Butcher", { AI_CLEAVER, 3, 0, 0 }, 220, 220, MFLAG_CAN_BLEED, 50, 6, 12, 0, 0, 0, 0, 0, 50, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 710, ALIGN }, // MC_DEMON, -/* MT_NFAT */ { MOFILE_FAT, 10, 3, NULL, "Overlord", { AI_FAT, 0, 0, 0 }, 60, 80, 0 | MFLAG_CAN_BLEED, 55, 6, 12, 30, 8, 14, 0, 0, 55, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 635, ALIGN }, // MC_DEMON, -/* MT_BFAT */ { MOFILE_FAT, 14, 3, "Monsters\\Fat\\Blue.TRN", "Mud Man", { AI_FAT, 1, 0, 0 }, 100, 125, MFLAG_SEARCH | MFLAG_CAN_BLEED, 60, 8, 16, 35, 8, 20, 0, 0, 60, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 1165, ALIGN }, // MC_DEMON, -/* MT_XFAT */ { MOFILE_FAT, 16, 3, "Monsters\\Fat\\FatB.TRN", "Toad Demon", { AI_FAT, 2, 0, 0 }, 135, 160, MFLAG_SEARCH | MFLAG_CAN_BLEED, 70, 8, 16, 40, 8, 20, 0, 0, 65, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1380, ALIGN }, // MC_DEMON, -/* MT_RFAT */ { MOFILE_FAT, 20, 3, "Monsters\\Fat\\FatF.TRN", "Flayed One", { AI_FAT, 3, 0, 0 }, 160, 200, MFLAG_SEARCH | MFLAG_CAN_BLEED, 85, 10, 20, 45, 12, 24, 0, 0, 70, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 2058, ALIGN }, // MC_DEMON, -/* MT_WYRM */// { MOFILE_WORM, 0, 3, NULL, "Wyrm", { AI_SKELSD, 0, 0, 0 }, 60, 90, 0 , 40, 4, 10, 0, 0, 0, 0, 0, 25, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, 660, ALIGN }, // MC_ANIMAL, -/* MT_CAVSLUG*/// { MOFILE_WORM, 0, 3, NULL, "Cave Slug", { AI_SKELSD, 1, 0, 0 }, 75, 110, 0 , 50, 6, 13, 0, 0, 0, 0, 0, 30, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, 994, ALIGN }, // MC_ANIMAL, -/* MT_DVLWYRM*/// { MOFILE_WORM, 0, 3, NULL, "Devil Wyrm", { AI_SKELSD, 2, 0, 0 }, 100, 140, 0 , 55, 8, 16, 0, 0, 0, 0, 0, 30, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 1320, ALIGN }, // MC_ANIMAL, -/* MT_DEVOUR*/// { MOFILE_WORM, 0, 3, NULL, "Devourer", { AI_SKELSD, 3, 0, 0 }, 125, 200, 0 , 60, 10, 20, 0, 0, 0, 0, 0, 35, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 1827, ALIGN }, // MC_ANIMAL, -/* MT_NMAGMA */ { MOFILE_MAGMA, 13, 7, NULL, "Magma Demon", { AI_ROUNDRANGED, 0, MIS_MAGMABALL, 0 }, 50, 70, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 45, 2, 10, 0, 0, 0, 35, 0, 45, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 1076, ALIGN }, // MC_DEMON, -/* MT_YMAGMA */ { MOFILE_MAGMA, 14, 7, "Monsters\\Magma\\Yellow.TRN", "Blood Stone", { AI_ROUNDRANGED, 1, MIS_MAGMABALL, 0 }, 55, 75, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 50, 2, 12, 0, 0, 0, 40, 0, 45, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 1309, ALIGN }, // MC_DEMON, -/* MT_BMAGMA */ { MOFILE_MAGMA, 16, 7, "Monsters\\Magma\\Blue.TRN", "Hell Stone", { AI_ROUNDRANGED, 2, MIS_MAGMABALL, 0 }, 60, 80, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 60, 2, 20, 0, 0, 0, 45, 0, 50, 45, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 1680, ALIGN }, // MC_DEMON, -/* MT_WMAGMA */ { MOFILE_MAGMA, 18, 7, "Monsters\\Magma\\Wierd.TRN", "Lava Lord", { AI_ROUNDRANGED, 3, MIS_MAGMABALL, 0 }, 70, 85, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 75, 4, 24, 0, 0, 0, 50, 0, 60, 50, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 2124, ALIGN }, // MC_DEMON, -/* MT_NRHINO */ { MOFILE_RHINO, 13, 7, NULL, "Horned Demon", { AI_RHINO, 0, 0, 0 }, 40, 80, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 60, 2, 16, 0, 5, 32, 0, 0, 40, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 1172, ALIGN }, // MC_ANIMAL, -/* MT_XRHINO */ { MOFILE_RHINO, 15, 7, "Monsters\\Rhino\\Orange.TRN", "Mud Runner", { AI_RHINO, 1, 0, 0 }, 50, 90, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 70, 6, 18, 0, 12, 36, 0, 0, 45, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 1404, ALIGN }, // MC_ANIMAL, -/* MT_BRHINO */ { MOFILE_RHINO, 17, 7, "Monsters\\Rhino\\Blue.TRN", "Frost Charger", { AI_RHINO, 2, 0, 0 }, 60, 100, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 80, 8, 20, 0, 20, 40, 0, 0, 50, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1720, ALIGN }, // MC_ANIMAL, -/* MT_DRHINO */ { MOFILE_RHINO, 19, 7, "Monsters\\Rhino\\RhinoB.TRN", "Obsidian Lord", { AI_RHINO, 3, 0, 0 }, 70, 110, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 90, 10, 22, 0, 20, 50, 0, 0, 55, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 1809, ALIGN }, // MC_ANIMAL, -/* MT_REDDTH */// { MOFILE_THIN, 0, 7, "Monsters\\Thin\\Thinv3.TRN", "Red Death", { AI_ROUNDRANGED, 1, MIS_LIGHTNINGC, 0 }, 96, 96, 0 , 75, 10, 20, 0, 0, 0, 50, 0, 60, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 2168, ALIGN }, // MC_DEMON, -/* MT_LTCHDMN *///{ MOFILE_THIN, 0, 7, "Monsters\\Thin\\Thinv3.TRN", "Litch Demon", { AI_ROUNDRANGED, 2, MIS_LIGHTNINGC, 0 }, 110, 110, 0 , 80, 10, 24, 0, 0, 0, 50, 0, 45, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2736, ALIGN }, // MC_DEMON, -/* MT_UDEDBLRG*///{ MOFILE_THIN, 0, 7, "Monsters\\Thin\\Thinv3.TRN", "Undead Balrog", { AI_ROUNDRANGED, 3, MIS_LIGHTNINGC, 0 }, 130, 130, 0 , 85, 12, 30, 0, 0, 0, 55, 0, 65, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 3575, ALIGN }, // MC_DEMON, -/* MT_INCIN */// { MOFILE_FIREMAN, 0, 3, NULL, "Incinerator", { AI_FIREMAN, 0, 0, 0 }, 30, 45, 0 , 75, 8, 16, 0, 0, 0, 0, 0, 25, 15, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 1888, ALIGN }, // MC_DEMON, -/* MT_FLAMLRD *///{ MOFILE_FIREMAN, 0, 3, NULL, "Flame Lord", { AI_FIREMAN, 1, 0, 0 }, 40, 55, 0 , 75, 10, 20, 0, 0, 0, 0, 0, 25, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 2250, ALIGN }, // MC_DEMON, -/* MT_DOOMFIRE*///{ MOFILE_FIREMAN, 0, 3, NULL, "Doom Fire", { AI_FIREMAN, 2, 0, 0 }, 50, 65, 0 , 80, 12, 24, 0, 0, 0, 0, 0, 30, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2740, ALIGN }, // MC_DEMON, -/* MT_HELLBURN*///{ MOFILE_FIREMAN, 0, 3, NULL, "Hell Burner", { AI_FIREMAN, 3, 0, 0 }, 60, 80, 0 , 85, 15, 30, 0, 0, 0, 0, 0, 30, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 3355, ALIGN }, // MC_DEMON, -/* MT_RTHIN */ { MOFILE_THIN, 18, 7, "Monsters\\Thin\\Thinv3.TRN", "Red Storm", { AI_ROUNDRANGED, 0, MIS_LIGHTNINGC2, 0 }, 55, 110, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 80, 8, 18, 0, 0, 0, 50, 0, 30, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2160, ALIGN }, // MC_DEMON, -/* MT_NTHIN */ { MOFILE_THIN, 20, 7, NULL, "Storm Rider", { AI_ROUNDRANGED, 1, MIS_LIGHTNINGC2, 0 }, 60, 120, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 80, 8, 18, 0, 0, 0, 50, 0, 30, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2391, ALIGN }, // MC_DEMON, -/* MT_XTHIN */ { MOFILE_THIN, 22, 7, "Monsters\\Thin\\Thinv2.TRN", "Storm Lord", { AI_ROUNDRANGED, 2, MIS_LIGHTNINGC2, 0 }, 75, 135, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 85, 12, 24, 0, 0, 0, 55, 0, 35, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2775, ALIGN }, // MC_DEMON, -/* MT_GTHIN */ { MOFILE_THIN, 24, 7, "Monsters\\Thin\\Thinv1.TRN", "Maelstrom", { AI_ROUNDRANGED, 3, MIS_LIGHTNINGC2, 0 }, 90, 150, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 90, 12, 28, 0, 0, 0, 60, 0, 40, 25, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 3177, ALIGN }, // MC_DEMON, -/* MT_NGARG */ { MOFILE_GARGOYLE, 9, 6, NULL, "Winged-Demon", { AI_GARG, 0, FALSE, 0 }, 45, 60, MFLAG_GARG_STONE | MFLAG_NOSTONE | MFLAG_CAN_OPEN_DOOR, 50, 10, 16, 0, 0, 0, 0, 0, 45, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 662, ALIGN }, // MC_DEMON, -/* MT_XGARG */ { MOFILE_GARGOYLE, 13, 6, "Monsters\\Gargoyle\\GarE.TRN", "Gargoyle", { AI_GARG, 1, FALSE, 0 }, 60, 90, MFLAG_GARG_STONE | MFLAG_NOSTONE | MFLAG_CAN_OPEN_DOOR, 65, 10, 16, 0, 0, 0, 0, 0, 45, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 1205, ALIGN }, // MC_DEMON, -/* MT_DGARG */ { MOFILE_GARGOYLE, 19, 6, "Monsters\\Gargoyle\\GargBr.TRN", "Blood Claw", { AI_GARG, 2, FALSE, 0 }, 75, 125, MFLAG_GARG_STONE | MFLAG_NOSTONE | MFLAG_CAN_OPEN_DOOR, 80, 14, 22, 0, 0, 0, 0, 0, 50, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1873, ALIGN }, // MC_DEMON, -/* MT_BGARG */ { MOFILE_GARGOYLE, 23, 6, "Monsters\\Gargoyle\\GargB.TRN", "Death Wing", { AI_GARG, 3, FALSE, 0 }, 90, 150, MFLAG_GARG_STONE | MFLAG_NOSTONE | MFLAG_CAN_OPEN_DOOR, 95, 16, 28, 0, 0, 0, 0, 0, 60, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2278, ALIGN }, // MC_DEMON, -/* MT_NMEGA */ { MOFILE_MEGA, 20, 7, NULL, "Slayer", { AI_ROUNDRANGED2, 0, MIS_INFERNOC, 0 }, 120, 140, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 100, 12, 20, 0, 0, 0, 50, 0, 60, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 2300, ALIGN }, // MC_DEMON, -/* MT_DMEGA */ { MOFILE_MEGA, 22, 7, "Monsters\\Mega\\Guard.TRN", "Guardian", { AI_ROUNDRANGED2, 1, MIS_INFERNOC, 0 }, 140, 160, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 110, 14, 22, 0, 0, 0, 55, 0, 65, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 2714, ALIGN }, // MC_DEMON, -/* MT_BMEGA */ { MOFILE_MEGA, 24, 7, "Monsters\\Mega\\Vtexl.TRN", "Vortex Lord", { AI_ROUNDRANGED2, 2, MIS_INFERNOC, 0 }, 160, 180, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 120, 18, 24, 0, 0, 0, 60, 0, 70, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 3252, ALIGN }, // MC_DEMON, -/* MT_RMEGA */ { MOFILE_MEGA, 26, 7, "Monsters\\Mega\\Balr.TRN", "Balrog", { AI_ROUNDRANGED2, 3, MIS_INFERNOC, 0 }, 180, 200, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 130, 22, 30, 0, 0, 0, 60, 0, 75, 35, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 3643, ALIGN }, // MC_DEMON, -/* MT_NSNAKE */ { MOFILE_SNAKE, 21, 7, NULL, "Cave Viper", { AI_SNAKE, 0, 0, 0 }, 100, 150, MFLAG_SEARCH , 90, 8, 20, 0, 16, 40, 0, 0, 60, 50, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, 2725, ALIGN }, // MC_DEMON, -/* MT_RSNAKE */ { MOFILE_SNAKE, 23, 7, "Monsters\\Snake\\SnakR.TRN", "Fire Drake", { AI_SNAKE, 1, 0, 0 }, 120, 170, MFLAG_SEARCH , 105, 12, 24, 0, 24, 48, 0, 0, 65, 50, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 3139, ALIGN }, // MC_DEMON, -/* MT_BSNAKE */ { MOFILE_SNAKE, 25, 7, "Monsters\\Snake\\Snakg.TRN", "Gold Viper", { AI_SNAKE, 2, 0, 0 }, 140, 180, MFLAG_SEARCH , 120, 15, 26, 0, 30, 52, 0, 0, 70, 50, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 3540, ALIGN }, // MC_DEMON, -/* MT_GSNAKE */ { MOFILE_SNAKE, 27, 7, "Monsters\\Snake\\Snakb.TRN", "Azure Drake", { AI_SNAKE, 3, 0, 0 }, 160, 200, MFLAG_SEARCH , 130, 18, 30, 0, 36, 60, 0, 0, 75, 55, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 3791, ALIGN }, // MC_DEMON, -/* MT_NBLACK */ { MOFILE_BLACK, 24, 7, NULL, "Black Knight", { AI_SKELSD, 0, 0, 0 }, 150, 150, MFLAG_SEARCH , 110, 15, 20, 0, 0, 0, 0, 0, 75, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 3360, ALIGN }, // MC_DEMON, -/* MT_RBLACK */ { MOFILE_BLACK, 26, 7, "Monsters\\Black\\BlkKntRT.TRN", "Doom Guard", { AI_SKELSD, 0, 0, 0 }, 165, 165, MFLAG_SEARCH , 130, 18, 25, 0, 0, 0, 0, 0, 75, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 3650, ALIGN }, // MC_DEMON, -/* MT_BBLACK */ { MOFILE_BLACK, 28, 7, "Monsters\\Black\\BlkKntBT.TRN", "Steel Lord", { AI_SKELSD, 1, 0, 0 }, 180, 180, MFLAG_SEARCH , 120, 20, 30, 0, 0, 0, 0, 0, 80, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 4252, ALIGN }, // MC_DEMON, -/* MT_GBLACK */ { MOFILE_BLACK, 30, 7, "Monsters\\Black\\BlkKntBe.TRN", "Blood Knight", { AI_SKELSD, 1, 0, 0 }, 200, 200, MFLAG_SEARCH , 130, 25, 35, 0, 0, 0, 0, 0, 85, 35, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 5130, ALIGN }, // MC_DEMON, -/* MT_UNRAV */// { MOFILE_UNRAV, 0, 3, NULL, "Unraveler", { AI_SKELSD, 0, 0, 0 }, 70, 150, 0 , 75, 10, 20, 0, 0, 0, 0, 0, 70, 40, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE , 3812, ALIGN }, // MC_UNDEAD, -/* MT_HOLOWONE*///{ MOFILE_UNRAV, 0, 3, NULL, "Hollow One", { AI_SKELSD, 1, 0, 0 }, 135, 240, 0 , 75, 12, 24, 0, 0, 0, 0, 0, 75, 40, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST , 4374, ALIGN }, // MC_UNDEAD, -/* MT_PAINMSTR*///{ MOFILE_UNRAV, 0, 3, NULL, "Pain Master", { AI_SKELSD, 2, 0, 0 }, 110, 200, 0 , 80, 16, 30, 0, 0, 0, 0, 0, 80, 40, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST , 5147, ALIGN }, // MC_UNDEAD, -/* MT_REALWEAV*///{ MOFILE_UNRAV, 0, 3, NULL, "Reality Weaver", { AI_SKELSD, 3, 0, 0 }, 135, 240, 0 , 85, 20, 35, 0, 0, 0, 0, 0, 85, 40, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE , 5925, ALIGN }, // MC_UNDEAD, -/* MT_NSUCC */ { MOFILE_SUCC, 24, 3, NULL, "Succubus", { AI_RANGED, 0, MIS_FLARE, FALSE }, 120, 150, MFLAG_CAN_OPEN_DOOR, 100, 1, 20, 0, 0, 0, 60, 0, 60, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 3696, ALIGN }, // MC_DEMON, -/* MT_GSUCC */ { MOFILE_SUCC, 26, 3, "Monsters\\Succ\\Succb.TRN", "Snow Witch", { AI_RANGED, 1, MIS_SNOWWICH, FALSE }, 135, 175, 0 , 110, 1, 24, 0, 0, 0, 60, 0, 65, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 4084, ALIGN }, // MC_DEMON, -/* MT_RSUCC */ { MOFILE_SUCC, 28, 3, "Monsters\\Succ\\Succrw.TRN", "Hell Spawn", { AI_RANGED, 2, MIS_HLSPWN, FALSE }, 150, 200, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 115, 1, 30, 0, 0, 0, 65, 0, 75, 45, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 4480, ALIGN }, // MC_DEMON, -/* MT_BSUCC */ { MOFILE_SUCC, 30, 3, "Monsters\\Succ\\Succbw.TRN", "Soul Burner", { AI_RANGED, 3, MIS_SOLBRNR, FALSE }, 140, 225, MFLAG_SEARCH, 120, 1, 35, 0, 0, 0, 70, 0, 85, 50, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 4644, ALIGN }, // MC_DEMON, -/* MT_NMAGE */ { MOFILE_MAGE, 25, 7, NULL, "Counselor", { AI_COUNSLR, 0, MIS_FIREBOLT, 0 }, 70, 70, 0 , 90, 8, 20, 0, 0, 0, 60, 0, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 4070, ALIGN }, // MC_DEMON, -/* MT_GMAGE */ { MOFILE_MAGE, 27, 7, "Monsters\\Mage\\Cnselg.TRN", "Magistrate", { AI_COUNSLR, 1, MIS_CBOLTC, 0 }, 85, 85, 0 , 100, 10, 24, 0, 0, 0, 65, 0, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 4478, ALIGN }, // MC_DEMON, -/* MT_XMAGE */ { MOFILE_MAGE, 29, 7, "Monsters\\Mage\\Cnselgd.TRN", "Cabalist", { AI_COUNSLR, 2, MIS_LIGHTNINGC, 0 }, 120, 120, 0 , 110, 12, 28, 0, 0, 0, 70, 0, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 4929, ALIGN }, // MC_DEMON, -/* MT_BMAGE */ { MOFILE_MAGE, 30, 7, "Monsters\\Mage\\Cnselbk.TRN", "Advocate", { AI_COUNSLR, 3, MIS_FIREBALL, 0 }, 145, 145, MFLAG_CAN_OPEN_DOOR, 120, 14, 32, 0, 0, 0, 70, 0, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 4968, ALIGN }, // MC_DEMON, +/* MT_NZOMBIE */ { MOFILE_ZOMBIE, 1, 3, NULL, "Zombie", { AI_ZOMBIE, 0, 0, 0 }, 4, 7, 0 , 10, 2, 5, 0, 0, 0, 0, 0, 5, 5, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , 36, ALIGN }, // MC_UNDEAD, +/* MT_BZOMBIE */ { MOFILE_ZOMBIE, 2, 3, "Monsters\\Zombie\\Bluered.TRN", "Ghoul", { AI_ZOMBIE, 1, 0, 0 }, 7, 11, 0 , 10, 3, 10, 0, 0, 0, 0, 0, 10, 10, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , 38, ALIGN }, // MC_UNDEAD, +/* MT_GZOMBIE */ { MOFILE_ZOMBIE, 4, 3, "Monsters\\Zombie\\Grey.TRN", "Rotting Carcass", { AI_ZOMBIE, 2, 0, 0 }, 15, 25, 0 , 25, 5, 15, 0, 0, 0, 0, 0, 15, 10, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST , 90, ALIGN }, // MC_UNDEAD, +/* MT_YZOMBIE */ { MOFILE_ZOMBIE, 6, 3, "Monsters\\Zombie\\Yellow.TRN", "Black Death", { AI_ZOMBIE, 3, 0, 0 }, 25, 40, 0 , 30, 6, 22, 0, 0, 0, 0, 0, 20, 10, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST , 160, ALIGN }, // MC_UNDEAD, +/* MT_RFALLSP */ { MOFILE_FALLSP, 1, 3, "Monsters\\FalSpear\\FallenT.TRN", "Fallen One", { AI_FALLEN, 0, 0, 0 }, 1, 4, 0 , 15, 1, 3, 0, 0, 0, 0, 0, 0, 0, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 30, ALIGN }, // MC_ANIMAL, +/* MT_DFALLSP */ { MOFILE_FALLSP, 3, 3, "Monsters\\FalSpear\\Dark.TRN", "Carver", { AI_FALLEN, 2, 0, 0 }, 4, 8, 0 , 20, 2, 5, 0, 0, 0, 0, 0, 5, 5, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 53, ALIGN }, // MC_ANIMAL, +/* MT_YFALLSP */ { MOFILE_FALLSP, 5, 3, NULL, "Devil Kin", { AI_FALLEN, 2, 0, 0 }, 12, 24, 0 , 25, 3, 7, 0, 0, 0, 0, 0, 10, 10, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 103, ALIGN }, // MC_ANIMAL, +/* MT_BFALLSP */ { MOFILE_FALLSP, 7, 3, "Monsters\\FalSpear\\Blue.TRN", "Dark One", { AI_FALLEN, 3, 0, 0 }, 20, 36, 0 , 30, 4, 8, 0, 0, 0, 0, 0, 15, 15, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 170, ALIGN }, // MC_ANIMAL, +/* MT_WSKELAX */ { MOFILE_SKELAX, 1, 3, "Monsters\\SkelSd\\White.TRN", "Skeleton", { AI_SKELSD, 0, 0, 0 }, 2, 4, 0 , 20, 1, 4, 0, 0, 0, 0, 0, 0, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , 42, ALIGN }, // MC_UNDEAD, +/* MT_TSKELAX */ { MOFILE_SKELAX, 2, 3, "Monsters\\SkelSd\\Skelt.TRN", "Corpse Axe", { AI_SKELSD, 1, 0, 0 }, 4, 7, 0 , 25, 3, 5, 0, 0, 0, 0, 0, 0, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , 45, ALIGN }, // MC_UNDEAD, +/* MT_RSKELAX */ { MOFILE_SKELAX, 4, 3, NULL, "Burning Dead", { AI_SKELSD, 2, 0, 0 }, 8, 12, 0 , 30, 3, 7, 0, 0, 0, 0, 0, 5, 5, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE , 102, ALIGN }, // MC_UNDEAD, +/* MT_XSKELAX */ { MOFILE_SKELAX, 6, 3, "Monsters\\SkelSd\\Black.TRN", "Horror", { AI_SKELSD, 3, 0, 0 }, 12, 20, 0 , 35, 4, 9, 0, 0, 0, 0, 0, 15, 10, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST , 176, ALIGN }, // MC_UNDEAD, +/* MT_RFALLSD */ { MOFILE_FALLSD, 1, 3, "Monsters\\FalSpear\\FallenT.TRN", "Fallen One", { AI_FALLEN, 0, 0, 0 }, 2, 5, 0 , 15, 1, 4, 0, 0, 0, 0, 0, 10, 10, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 34, ALIGN }, // MC_ANIMAL, +/* MT_DFALLSD */ { MOFILE_FALLSD, 3, 3, "Monsters\\FalSpear\\Dark.TRN", "Carver", { AI_FALLEN, 1, 0, 0 }, 5, 9, 0 , 20, 2, 7, 0, 0, 0, 0, 0, 15, 15, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 60, ALIGN }, // MC_ANIMAL, +/* MT_YFALLSD */ { MOFILE_FALLSD, 5, 3, NULL, "Devil Kin", { AI_FALLEN, 2, 0, 0 }, 16, 24, 0 , 25, 4, 10, 0, 0, 0, 0, 0, 20, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 120, ALIGN }, // MC_ANIMAL, +/* MT_BFALLSD */ { MOFILE_FALLSD, 7, 3, "Monsters\\FalSpear\\Blue.TRN", "Dark One", { AI_FALLEN, 3, 0, 0 }, 24, 36, 0 , 30, 4, 12, 0, 0, 0, 0, 0, 25, 25, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 186, ALIGN }, // MC_ANIMAL, +/* MT_NSCAV */ { MOFILE_SCAV, 2, 3, NULL, "Scavenger", { AI_SCAV, 0, 0, 0 }, 3, 6, 0 , 20, 1, 5, 0, 0, 0, 0, 0, 10, 10, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 53, ALIGN }, // MC_ANIMAL, +/* MT_BSCAV */ { MOFILE_SCAV, 4, 3, "Monsters\\Scav\\ScavBr.TRN", "Plague Eater", { AI_SCAV, 1, 0, 0 }, 12, 24, 0 , 30, 1, 8, 0, 0, 0, 0, 0, 20, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 125, ALIGN }, // MC_ANIMAL, +/* MT_WSCAV */ { MOFILE_SCAV, 6, 3, "Monsters\\Scav\\ScavBe.TRN", "Shadow Beast", { AI_SCAV, 2, 0, 0 }, 24, 36, 0 , 35, 3, 12, 0, 0, 0, 0, 0, 25, 25, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 250, ALIGN }, // MC_ANIMAL, +/* MT_YSCAV */ { MOFILE_SCAV, 8, 3, "Monsters\\Scav\\ScavW.TRN", "Bone Gasher", { AI_SCAV, 3, 0, 0 }, 28, 40, 0 , 35, 5, 15, 0, 0, 0, 0, 0, 30, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 368, ALIGN }, // MC_ANIMAL, +/* MT_WSKELBW */ { MOFILE_SKELBW, 3, 3, "Monsters\\SkelSd\\White.TRN", "Skeleton", { AI_SKELBOW, 0, 0, 0 }, 2, 4, 0 , 15, 1, 3, 0, 0, 0, 0, 0, 0, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , 73, ALIGN }, // MC_UNDEAD, +/* MT_TSKELBW */ { MOFILE_SKELBW, 5, 3, "Monsters\\SkelSd\\Skelt.TRN", "Corpse Bow", { AI_SKELBOW, 1, 0, 0 }, 8, 16, 0 , 25, 1, 4, 0, 0, 0, 0, 0, 0, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , 140, ALIGN }, // MC_UNDEAD, +/* MT_RSKELBW */ { MOFILE_SKELBW, 7, 3, NULL, "Burning Dead", { AI_SKELBOW, 2, 0, 0 }, 10, 24, 0 , 30, 1, 6, 0, 0, 0, 0, 0, 5, 5, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE , 242, ALIGN }, // MC_UNDEAD, +/* MT_XSKELBW */ { MOFILE_SKELBW, 9, 3, "Monsters\\SkelSd\\Black.TRN", "Horror", { AI_SKELBOW, 3, 0, 0 }, 15, 45, 0 , 35, 2, 9, 0, 0, 0, 0, 0, 15, 10, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST , 396, ALIGN }, // MC_UNDEAD, +/* MT_WSKELSD */ { MOFILE_SKELSD, 2, 3, "Monsters\\SkelSd\\White.TRN", "Skeleton Captain", { AI_SKELSD, 0, 0, 0 }, 3, 6, 0 , 20, 2, 7, 0, 0, 0, 0, 0, 10, 10, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , 60, ALIGN }, // MC_UNDEAD, +/* MT_TSKELSD */ { MOFILE_SKELSD, 4, 3, "Monsters\\SkelSd\\Skelt.TRN", "Corpse Captain", { AI_SKELSD, 1, 0, 0 }, 12, 20, 0 , 30, 3, 9, 0, 0, 0, 0, 0, 5, 5, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , 133, ALIGN }, // MC_UNDEAD, +/* MT_RSKELSD */ { MOFILE_SKELSD, 6, 3, NULL, "Burning Dead Captain", { AI_SKELSD, 2, 0, 0 }, 16, 30, 0 , 35, 4, 10, 0, 0, 0, 0, 0, 15, 10, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE , 262, ALIGN }, // MC_UNDEAD, +/* MT_XSKELSD */ { MOFILE_SKELSD, 8, 3, "Monsters\\SkelSd\\Black.TRN", "Horror Captain", { AI_SKELSD, 3, 0, 0 }, 35, 50, MFLAG_SEARCH , 40, 5, 14, 0, 0, 0, 0, 0, 30, 20, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST , 402, ALIGN }, // MC_UNDEAD, +/* MT_INVILORD*///{ MOFILE_TSNEAK, 0, 3, NULL, "Invisible Lord", { AI_SKELSD, 3, 0, 0 }, 278, 278, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 65, 16, 30, 0, 0, 0, 0, 0, 60, 50, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1333, ALIGN }, // MC_DEMON, +/* MT_NSNEAK */ { MOFILE_SNEAK, 5, 3, NULL, "Hidden", { AI_SNEAK, 0, 0, 0 }, 8, 24, MFLAG_HIDDEN , 35, 3, 6, 0, 0, 0, 0, 0, 25, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 185, ALIGN }, // MC_DEMON, +/* MT_RSNEAK */ { MOFILE_SNEAK, 9, 3, "Monsters\\Sneak\\Sneakv2.TRN", "Stalker", { AI_SNEAK, 1, 0, 0 }, 30, 45, MFLAG_HIDDEN | MFLAG_SEARCH , 40, 8, 16, 0, 0, 0, 0, 0, 30, 25, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 420, ALIGN }, // MC_DEMON, +/* MT_BSNEAK */ { MOFILE_SNEAK, 11, 3, "Monsters\\Sneak\\Sneakv3.TRN", "Unseen", { AI_SNEAK, 2, 0, 0 }, 35, 50, MFLAG_HIDDEN | MFLAG_SEARCH , 45, 12, 20, 0, 0, 0, 0, 0, 30, 25, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, 623, ALIGN }, // MC_DEMON, +/* MT_YSNEAK */ { MOFILE_SNEAK, 13, 3, "Monsters\\Sneak\\Sneakv1.TRN", "Illusion Weaver", { AI_SNEAK, 3, 0, 0 }, 40, 60, MFLAG_HIDDEN | MFLAG_SEARCH , 60, 16, 24, 0, 0, 0, 0, 0, 30, 25, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 1000, ALIGN }, // MC_DEMON, +/* MT_NGOATMC */ { MOFILE_GOATMC, 8, 3, NULL, "Flesh Clan", { AI_ROUND, 0, TRUE, 0 }, 30, 45, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 50, 4, 10, 10, 12, 16, 0, 0, 40, 35, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 306, ALIGN }, // MC_DEMON, +/* MT_BGOATMC */ { MOFILE_GOATMC, 10, 3, "Monsters\\GoatMace\\Beige.TRN", "Stone Clan", { AI_ROUND, 1, TRUE, 0 }, 40, 55, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 60, 6, 12, 15, 14, 20, 0, 0, 40, 35, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, 456, ALIGN }, // MC_DEMON, +/* MT_RGOATMC */ { MOFILE_GOATMC, 12, 3, "Monsters\\GoatMace\\Red.TRN", "Fire Clan", { AI_ROUND, 2, TRUE, 0 }, 50, 65, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 70, 8, 16, 15, 16, 24, 0, 0, 45, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 604, ALIGN }, // MC_DEMON, +/* MT_GGOATMC */ { MOFILE_GOATMC, 14, 3, "Monsters\\GoatMace\\Gray.TRN", "Night Clan", { AI_ROUND, 3, TRUE, 0 }, 55, 70, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 80, 10, 20, 20, 20, 30, 0, 0, 50, 45, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, 793, ALIGN }, // MC_DEMON, +/* MT_RBAT */ { MOFILE_BAT, 3, 6, "Monsters\\Bat\\red.trn", "Fiend", { AI_BAT, 0, 0, 0 }, 3, 6, MFLAG_NODROP , 35, 1, 6, 0, 0, 0, 0, 0, 0, 0, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 68, ALIGN }, // MC_ANIMAL, +/* MT_NBAT */ { MOFILE_BAT, 7, 6, NULL, "Blink", { AI_BAT, 1, 0, 0 }, 12, 28, MFLAG_NODROP , 45, 1, 8, 0, 0, 0, 0, 0, 15, 15, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 226, ALIGN }, // MC_ANIMAL, +/* MT_GBAT */ { MOFILE_BAT, 9, 6, "Monsters\\Bat\\grey.trn", "Gloom", { AI_BAT, 2, 0, 0 }, 28, 36, MFLAG_NODROP | MFLAG_SEARCH , 70, 4, 12, 0, 0, 0, 0, 0, 35, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, 339, ALIGN }, // MC_ANIMAL, +/* MT_XBAT */ { MOFILE_BAT, 13, 6, "Monsters\\Bat\\orange.trn", "Familiar", { AI_BAT, 3, 0, 0 }, 20, 35, MFLAG_NODROP | MFLAG_SEARCH , 50, 4, 16, 0, 0, 0, 35, 0, 35, 35, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 298, ALIGN }, // MC_DEMON, +/* MT_NGOATBW */ { MOFILE_GOATBW, 8, 3, NULL, "Flesh Clan", { AI_RANGED, 0, MIS_ARROW, FALSE }, 20, 35, MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 35, 1, 7, 0, 0, 0, 0, 0, 35, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 298, ALIGN }, // MC_DEMON, +/* MT_BGOATBW */ { MOFILE_GOATBW, 10, 3, "Monsters\\GoatMace\\Beige.TRN", "Stone Clan", { AI_RANGED, 1, MIS_ARROW, FALSE }, 30, 40, MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 40, 2, 9, 0, 0, 0, 0, 0, 35, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, 430, ALIGN }, // MC_DEMON, +/* MT_RGOATBW */ { MOFILE_GOATBW, 12, 3, "Monsters\\GoatMace\\Red.TRN", "Fire Clan", { AI_RANGED, 2, MIS_ARROW, FALSE }, 40, 50, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 45, 3, 11, 0, 0, 0, 0, 0, 35, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 548, ALIGN }, // MC_DEMON, +/* MT_GGOATBW */ { MOFILE_GOATBW, 14, 3, "Monsters\\GoatMace\\Gray.TRN", "Night Clan", { AI_RANGED, 3, MIS_ARROW, FALSE }, 50, 65, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 50, 4, 13, 0, 0, 0, 0, 0, 40, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, 728, ALIGN }, // MC_DEMON, +/* MT_NACID */ { MOFILE_ACID, 11, 3, NULL, "Acid Beast", { AI_ROUNDRANGED, 0, MIS_ACID, 1 }, 40, 66, 0 , 40, 4, 12, 0, 0, 0, 30, 0, 30, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, 564, ALIGN }, // MC_ANIMAL, +/* MT_RACID */ { MOFILE_ACID, 15, 3, "Monsters\\Acid\\AcidBlk.TRN", "Poison Spitter", { AI_ROUNDRANGED, 1, MIS_ACID, 1 }, 60, 85, 0 , 45, 4, 16, 0, 0, 0, 40, 0, 30, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, 832, ALIGN }, // MC_ANIMAL, +/* MT_BACID */ { MOFILE_ACID, 21, 3, "Monsters\\Acid\\AcidB.TRN", "Pit Beast", { AI_ROUNDRANGED, 2, MIS_ACID, 1 }, 80, 110, 0 , 55, 8, 18, 0, 0, 0, 50, 0, 35, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1373, ALIGN }, // MC_ANIMAL, +/* MT_XACID */ { MOFILE_ACID, 25, 3, "Monsters\\Acid\\AcidR.TRN", "Lava Maw", { AI_ROUNDRANGED, 3, MIS_ACID, 1 }, 100, 150, 0 , 65, 10, 20, 0, 0, 0, 60, 0, 35, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 1960, ALIGN }, // MC_ANIMAL, +/* MT_SKING */ { MOFILE_SKING, 6, 7, "Monsters\\SkelSd\\White.TRN", "Skeleton King", { AI_SKELKING, 3, 0, 0 }, 140, 140, MFLAG_LIFESTEAL | MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 75, 6, 16, 0, 0, 0, 0, 0, 70, 30, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE , 380, ALIGN }, // MC_UNDEAD, +/* MT_CLEAVER */ { MOFILE_CLEAVER, 6, 3, NULL, "The Butcher", { AI_CLEAVER, 3, 0, 0 }, 220, 220, MFLAG_CAN_BLEED, 50, 6, 12, 0, 0, 0, 0, 0, 50, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 473, ALIGN }, // MC_DEMON, +/* MT_NFAT */ { MOFILE_FAT, 10, 3, NULL, "Overlord", { AI_FAT, 0, 0, 0 }, 60, 80, 0 | MFLAG_CAN_BLEED, 55, 6, 12, 30, 8, 14, 0, 0, 55, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 423, ALIGN }, // MC_DEMON, +/* MT_BFAT */ { MOFILE_FAT, 14, 3, "Monsters\\Fat\\Blue.TRN", "Mud Man", { AI_FAT, 1, 0, 0 }, 100, 125, MFLAG_SEARCH | MFLAG_CAN_BLEED, 60, 8, 16, 35, 8, 20, 0, 0, 60, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 776, ALIGN }, // MC_DEMON, +/* MT_XFAT */ { MOFILE_FAT, 16, 3, "Monsters\\Fat\\FatB.TRN", "Toad Demon", { AI_FAT, 2, 0, 0 }, 135, 160, MFLAG_SEARCH | MFLAG_CAN_BLEED, 70, 8, 16, 40, 8, 20, 0, 0, 65, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 920, ALIGN }, // MC_DEMON, +/* MT_RFAT */ { MOFILE_FAT, 20, 3, "Monsters\\Fat\\FatF.TRN", "Flayed One", { AI_FAT, 3, 0, 0 }, 160, 200, MFLAG_SEARCH | MFLAG_CAN_BLEED, 85, 10, 20, 45, 12, 24, 0, 0, 70, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 1372, ALIGN }, // MC_DEMON, +/* MT_WYRM */// { MOFILE_WORM, 0, 3, NULL, "Wyrm", { AI_SKELSD, 0, 0, 0 }, 60, 90, 0 , 40, 4, 10, 0, 0, 0, 0, 0, 25, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, 440, ALIGN }, // MC_ANIMAL, +/* MT_CAVSLUG*/// { MOFILE_WORM, 0, 3, NULL, "Cave Slug", { AI_SKELSD, 1, 0, 0 }, 75, 110, 0 , 50, 6, 13, 0, 0, 0, 0, 0, 30, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, 662, ALIGN }, // MC_ANIMAL, +/* MT_DVLWYRM*/// { MOFILE_WORM, 0, 3, NULL, "Devil Wyrm", { AI_SKELSD, 2, 0, 0 }, 100, 140, 0 , 55, 8, 16, 0, 0, 0, 0, 0, 30, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 880, ALIGN }, // MC_ANIMAL, +/* MT_DEVOUR*/// { MOFILE_WORM, 0, 3, NULL, "Devourer", { AI_SKELSD, 3, 0, 0 }, 125, 200, 0 , 60, 10, 20, 0, 0, 0, 0, 0, 35, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 1218, ALIGN }, // MC_ANIMAL, +/* MT_NMAGMA */ { MOFILE_MAGMA, 13, 7, NULL, "Magma Demon", { AI_ROUNDRANGED, 0, MIS_MAGMABALL, 0 }, 50, 70, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 45, 2, 10, 0, 0, 0, 35, 0, 45, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 717, ALIGN }, // MC_DEMON, +/* MT_YMAGMA */ { MOFILE_MAGMA, 14, 7, "Monsters\\Magma\\Yellow.TRN", "Blood Stone", { AI_ROUNDRANGED, 1, MIS_MAGMABALL, 0 }, 55, 75, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 50, 2, 12, 0, 0, 0, 40, 0, 45, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 872, ALIGN }, // MC_DEMON, +/* MT_BMAGMA */ { MOFILE_MAGMA, 16, 7, "Monsters\\Magma\\Blue.TRN", "Hell Stone", { AI_ROUNDRANGED, 2, MIS_MAGMABALL, 0 }, 60, 80, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 60, 2, 20, 0, 0, 0, 45, 0, 50, 45, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 1120, ALIGN }, // MC_DEMON, +/* MT_WMAGMA */ { MOFILE_MAGMA, 18, 7, "Monsters\\Magma\\Wierd.TRN", "Lava Lord", { AI_ROUNDRANGED, 3, MIS_MAGMABALL, 0 }, 70, 85, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 75, 4, 24, 0, 0, 0, 50, 0, 60, 50, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 1416, ALIGN }, // MC_DEMON, +/* MT_NRHINO */ { MOFILE_RHINO, 13, 7, NULL, "Horned Demon", { AI_RHINO, 0, 0, 0 }, 40, 80, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 60, 2, 16, 0, 5, 32, 0, 0, 40, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 781, ALIGN }, // MC_ANIMAL, +/* MT_XRHINO */ { MOFILE_RHINO, 15, 7, "Monsters\\Rhino\\Orange.TRN", "Mud Runner", { AI_RHINO, 1, 0, 0 }, 50, 90, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 70, 6, 18, 0, 12, 36, 0, 0, 45, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 936, ALIGN }, // MC_ANIMAL, +/* MT_BRHINO */ { MOFILE_RHINO, 17, 7, "Monsters\\Rhino\\Blue.TRN", "Frost Charger", { AI_RHINO, 2, 0, 0 }, 60, 100, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 80, 8, 20, 0, 20, 40, 0, 0, 50, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1146, ALIGN }, // MC_ANIMAL, +/* MT_DRHINO */ { MOFILE_RHINO, 19, 7, "Monsters\\Rhino\\RhinoB.TRN", "Obsidian Lord", { AI_RHINO, 3, 0, 0 }, 70, 110, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 90, 10, 22, 0, 20, 50, 0, 0, 55, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 1206, ALIGN }, // MC_ANIMAL, +/* MT_REDDTH */// { MOFILE_THIN, 0, 7, "Monsters\\Thin\\Thinv3.TRN", "Red Death", { AI_ROUNDRANGED, 1, MIS_LIGHTNINGC, 0 }, 96, 96, 0 , 75, 10, 20, 0, 0, 0, 50, 0, 60, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 1444, ALIGN }, // MC_DEMON, +/* MT_LTCHDMN *///{ MOFILE_THIN, 0, 7, "Monsters\\Thin\\Thinv3.TRN", "Litch Demon", { AI_ROUNDRANGED, 2, MIS_LIGHTNINGC, 0 }, 110, 110, 0 , 80, 10, 24, 0, 0, 0, 50, 0, 45, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 1824, ALIGN }, // MC_DEMON, +/* MT_UDEDBLRG*///{ MOFILE_THIN, 0, 7, "Monsters\\Thin\\Thinv3.TRN", "Undead Balrog", { AI_ROUNDRANGED, 3, MIS_LIGHTNINGC, 0 }, 130, 130, 0 , 85, 12, 30, 0, 0, 0, 55, 0, 65, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2383, ALIGN }, // MC_DEMON, +/* MT_INCIN */// { MOFILE_FIREMAN, 0, 3, NULL, "Incinerator", { AI_FIREMAN, 0, 0, 0 }, 30, 45, 0 , 75, 8, 16, 0, 0, 0, 0, 0, 25, 15, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 1258, ALIGN }, // MC_DEMON, +/* MT_FLAMLRD *///{ MOFILE_FIREMAN, 0, 3, NULL, "Flame Lord", { AI_FIREMAN, 1, 0, 0 }, 40, 55, 0 , 75, 10, 20, 0, 0, 0, 0, 0, 25, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 1500, ALIGN }, // MC_DEMON, +/* MT_DOOMFIRE*///{ MOFILE_FIREMAN, 0, 3, NULL, "Doom Fire", { AI_FIREMAN, 2, 0, 0 }, 50, 65, 0 , 80, 12, 24, 0, 0, 0, 0, 0, 30, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1826, ALIGN }, // MC_DEMON, +/* MT_HELLBURN*///{ MOFILE_FIREMAN, 0, 3, NULL, "Hell Burner", { AI_FIREMAN, 3, 0, 0 }, 60, 80, 0 , 85, 15, 30, 0, 0, 0, 0, 0, 30, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2236, ALIGN }, // MC_DEMON, +/* MT_RTHIN */ { MOFILE_THIN, 18, 7, "Monsters\\Thin\\Thinv3.TRN", "Red Storm", { AI_ROUNDRANGED, 0, MIS_LIGHTNINGC2, 0 }, 55, 110, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 80, 8, 18, 0, 0, 0, 50, 0, 30, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 1440, ALIGN }, // MC_DEMON, +/* MT_NTHIN */ { MOFILE_THIN, 20, 7, NULL, "Storm Rider", { AI_ROUNDRANGED, 1, MIS_LIGHTNINGC2, 0 }, 60, 120, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 80, 8, 18, 0, 0, 0, 50, 0, 30, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 1594, ALIGN }, // MC_DEMON, +/* MT_XTHIN */ { MOFILE_THIN, 22, 7, "Monsters\\Thin\\Thinv2.TRN", "Storm Lord", { AI_ROUNDRANGED, 2, MIS_LIGHTNINGC2, 0 }, 75, 135, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 85, 12, 24, 0, 0, 0, 55, 0, 35, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 1850, ALIGN }, // MC_DEMON, +/* MT_GTHIN */ { MOFILE_THIN, 24, 7, "Monsters\\Thin\\Thinv1.TRN", "Maelstrom", { AI_ROUNDRANGED, 3, MIS_LIGHTNINGC2, 0 }, 90, 150, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 90, 12, 28, 0, 0, 0, 60, 0, 40, 25, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2118, ALIGN }, // MC_DEMON, +/* MT_NGARG */ { MOFILE_GARGOYLE, 9, 6, NULL, "Winged-Demon", { AI_GARG, 0, FALSE, 0 }, 45, 60, MFLAG_GARG_STONE | MFLAG_NOSTONE | MFLAG_CAN_OPEN_DOOR, 50, 10, 16, 0, 0, 0, 0, 0, 45, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 441, ALIGN }, // MC_DEMON, +/* MT_XGARG */ { MOFILE_GARGOYLE, 13, 6, "Monsters\\Gargoyle\\GarE.TRN", "Gargoyle", { AI_GARG, 1, FALSE, 0 }, 60, 90, MFLAG_GARG_STONE | MFLAG_NOSTONE | MFLAG_CAN_OPEN_DOOR, 65, 10, 16, 0, 0, 0, 0, 0, 45, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 803, ALIGN }, // MC_DEMON, +/* MT_DGARG */ { MOFILE_GARGOYLE, 19, 6, "Monsters\\Gargoyle\\GargBr.TRN", "Blood Claw", { AI_GARG, 2, FALSE, 0 }, 75, 125, MFLAG_GARG_STONE | MFLAG_NOSTONE | MFLAG_CAN_OPEN_DOOR, 80, 14, 22, 0, 0, 0, 0, 0, 50, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1248, ALIGN }, // MC_DEMON, +/* MT_BGARG */ { MOFILE_GARGOYLE, 23, 6, "Monsters\\Gargoyle\\GargB.TRN", "Death Wing", { AI_GARG, 3, FALSE, 0 }, 90, 150, MFLAG_GARG_STONE | MFLAG_NOSTONE | MFLAG_CAN_OPEN_DOOR, 95, 16, 28, 0, 0, 0, 0, 0, 60, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 1518, ALIGN }, // MC_DEMON, +/* MT_NMEGA */ { MOFILE_MEGA, 20, 7, NULL, "Slayer", { AI_ROUNDRANGED2, 0, MIS_INFERNOC, 0 }, 120, 140, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 100, 12, 20, 0, 0, 0, 50, 0, 60, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 1533, ALIGN }, // MC_DEMON, +/* MT_DMEGA */ { MOFILE_MEGA, 22, 7, "Monsters\\Mega\\Guard.TRN", "Guardian", { AI_ROUNDRANGED2, 1, MIS_INFERNOC, 0 }, 140, 160, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 110, 14, 22, 0, 0, 0, 55, 0, 65, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 1809, ALIGN }, // MC_DEMON, +/* MT_BMEGA */ { MOFILE_MEGA, 24, 7, "Monsters\\Mega\\Vtexl.TRN", "Vortex Lord", { AI_ROUNDRANGED2, 2, MIS_INFERNOC, 0 }, 160, 180, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 120, 18, 24, 0, 0, 0, 60, 0, 70, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2168, ALIGN }, // MC_DEMON, +/* MT_RMEGA */ { MOFILE_MEGA, 26, 7, "Monsters\\Mega\\Balr.TRN", "Balrog", { AI_ROUNDRANGED2, 3, MIS_INFERNOC, 0 }, 180, 200, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 130, 22, 30, 0, 0, 0, 60, 0, 75, 35, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2428, ALIGN }, // MC_DEMON, +/* MT_NSNAKE */ { MOFILE_SNAKE, 21, 7, NULL, "Cave Viper", { AI_SNAKE, 0, 0, 0 }, 100, 150, MFLAG_SEARCH , 90, 8, 20, 0, 16, 40, 0, 0, 60, 50, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, 1816, ALIGN }, // MC_DEMON, +/* MT_RSNAKE */ { MOFILE_SNAKE, 23, 7, "Monsters\\Snake\\SnakR.TRN", "Fire Drake", { AI_SNAKE, 1, 0, 0 }, 120, 170, MFLAG_SEARCH , 105, 12, 24, 0, 24, 48, 0, 0, 65, 50, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 2092, ALIGN }, // MC_DEMON, +/* MT_BSNAKE */ { MOFILE_SNAKE, 25, 7, "Monsters\\Snake\\Snakg.TRN", "Gold Viper", { AI_SNAKE, 2, 0, 0 }, 140, 180, MFLAG_SEARCH , 120, 15, 26, 0, 30, 52, 0, 0, 70, 50, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2360, ALIGN }, // MC_DEMON, +/* MT_GSNAKE */ { MOFILE_SNAKE, 27, 7, "Monsters\\Snake\\Snakb.TRN", "Azure Drake", { AI_SNAKE, 3, 0, 0 }, 160, 200, MFLAG_SEARCH , 130, 18, 30, 0, 36, 60, 0, 0, 75, 55, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2527, ALIGN }, // MC_DEMON, +/* MT_NBLACK */ { MOFILE_BLACK, 24, 7, NULL, "Black Knight", { AI_SKELSD, 0, 0, 0 }, 150, 150, MFLAG_SEARCH , 110, 15, 20, 0, 0, 0, 0, 0, 75, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2240, ALIGN }, // MC_DEMON, +/* MT_RBLACK */ { MOFILE_BLACK, 26, 7, "Monsters\\Black\\BlkKntRT.TRN", "Doom Guard", { AI_SKELSD, 0, 0, 0 }, 165, 165, MFLAG_SEARCH , 130, 18, 25, 0, 0, 0, 0, 0, 75, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 2433, ALIGN }, // MC_DEMON, +/* MT_BBLACK */ { MOFILE_BLACK, 28, 7, "Monsters\\Black\\BlkKntBT.TRN", "Steel Lord", { AI_SKELSD, 1, 0, 0 }, 180, 180, MFLAG_SEARCH , 120, 20, 30, 0, 0, 0, 0, 0, 80, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2834, ALIGN }, // MC_DEMON, +/* MT_GBLACK */ { MOFILE_BLACK, 30, 7, "Monsters\\Black\\BlkKntBe.TRN", "Blood Knight", { AI_SKELSD, 1, 0, 0 }, 200, 200, MFLAG_SEARCH , 130, 25, 35, 0, 0, 0, 0, 0, 85, 35, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 3420, ALIGN }, // MC_DEMON, +/* MT_UNRAV */// { MOFILE_UNRAV, 0, 3, NULL, "Unraveler", { AI_SKELSD, 0, 0, 0 }, 70, 150, 0 , 75, 10, 20, 0, 0, 0, 0, 0, 70, 40, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE , 2541, ALIGN }, // MC_UNDEAD, +/* MT_HOLOWONE*///{ MOFILE_UNRAV, 0, 3, NULL, "Hollow One", { AI_SKELSD, 1, 0, 0 }, 135, 240, 0 , 75, 12, 24, 0, 0, 0, 0, 0, 75, 40, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST , 2916, ALIGN }, // MC_UNDEAD, +/* MT_PAINMSTR*///{ MOFILE_UNRAV, 0, 3, NULL, "Pain Master", { AI_SKELSD, 2, 0, 0 }, 110, 200, 0 , 80, 16, 30, 0, 0, 0, 0, 0, 80, 40, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST , 3431, ALIGN }, // MC_UNDEAD, +/* MT_REALWEAV*///{ MOFILE_UNRAV, 0, 3, NULL, "Reality Weaver", { AI_SKELSD, 3, 0, 0 }, 135, 240, 0 , 85, 20, 35, 0, 0, 0, 0, 0, 85, 40, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE , 3950, ALIGN }, // MC_UNDEAD, +/* MT_NSUCC */ { MOFILE_SUCC, 24, 3, NULL, "Succubus", { AI_RANGED, 0, MIS_FLARE, FALSE }, 120, 150, MFLAG_CAN_OPEN_DOOR, 100, 1, 20, 0, 0, 0, 60, 0, 60, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 2464, ALIGN }, // MC_DEMON, +/* MT_GSUCC */ { MOFILE_SUCC, 26, 3, "Monsters\\Succ\\Succb.TRN", "Snow Witch", { AI_RANGED, 1, MIS_SNOWWICH, FALSE }, 135, 175, 0 , 110, 1, 24, 0, 0, 0, 60, 0, 65, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2722, ALIGN }, // MC_DEMON, +/* MT_RSUCC */ { MOFILE_SUCC, 28, 3, "Monsters\\Succ\\Succrw.TRN", "Hell Spawn", { AI_RANGED, 2, MIS_HLSPWN, FALSE }, 150, 200, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 115, 1, 30, 0, 0, 0, 65, 0, 75, 45, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2986, ALIGN }, // MC_DEMON, +/* MT_BSUCC */ { MOFILE_SUCC, 30, 3, "Monsters\\Succ\\Succbw.TRN", "Soul Burner", { AI_RANGED, 3, MIS_SOLBRNR, FALSE }, 140, 225, MFLAG_SEARCH, 120, 1, 35, 0, 0, 0, 70, 0, 85, 50, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 3096, ALIGN }, // MC_DEMON, +/* MT_NMAGE */ { MOFILE_MAGE, 25, 7, NULL, "Counselor", { AI_COUNSLR, 0, MIS_FIREBOLT, 0 }, 70, 70, 0 , 90, 8, 20, 0, 0, 0, 60, 0, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2713, ALIGN }, // MC_DEMON, +/* MT_GMAGE */ { MOFILE_MAGE, 27, 7, "Monsters\\Mage\\Cnselg.TRN", "Magistrate", { AI_COUNSLR, 1, MIS_CBOLTC, 0 }, 85, 85, 0 , 100, 10, 24, 0, 0, 0, 65, 0, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2985, ALIGN }, // MC_DEMON, +/* MT_XMAGE */ { MOFILE_MAGE, 29, 7, "Monsters\\Mage\\Cnselgd.TRN", "Cabalist", { AI_COUNSLR, 2, MIS_LIGHTNINGC, 0 }, 120, 120, 0 , 110, 12, 28, 0, 0, 0, 70, 0, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 3286, ALIGN }, // MC_DEMON, +/* MT_BMAGE */ { MOFILE_MAGE, 30, 7, "Monsters\\Mage\\Cnselbk.TRN", "Advocate", { AI_COUNSLR, 3, MIS_FIREBALL, 0 }, 145, 145, MFLAG_CAN_OPEN_DOOR, 120, 14, 32, 0, 0, 0, 70, 0, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 3312, ALIGN }, // MC_DEMON, /* MT_GOLEM */ { MOFILE_GOLEM, 4, 0, NULL, "Golem", { AI_GOLUM, 0, 0, 0 }, 40, 40, MFLAG_NOSTONE | MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 30, 3, 5, 0, 0, 0, 0, 0, 50, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 0, ALIGN }, // MC_DEMON, -/* MT_DIABLO */ { MOFILE_DIABLO, 32, 7, NULL, "The Dark Lord", { AI_ROUNDRANGED, 3, MIS_APOCAC2, 0 }, 1666, 1666, MFLAG_NOSTONE | MFLAG_NOCORPSE | MFLAG_KNOCKBACK | MFLAG_SEARCH, 240, 30, 60, 0, 0, 0, 200, 0, 90, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , 8333, ALIGN }, // MC_DEMON, -/* MT_DARKMAGE*///{ MOFILE_DARKMAGE, 30, 7, NULL, "The Arch-Litch Malignus", { AI_COUNSLR, 3, MIS_FIREBALL, 0 }, 160, 160, MFLAG_CAN_OPEN_DOOR, 120, 20, 40, 0, 0, 0, 0, 0, 70, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 4968, ALIGN }, // MC_DEMON, +/* MT_DIABLO */ { MOFILE_DIABLO, 32, 7, NULL, "The Dark Lord", { AI_ROUNDRANGED, 3, MIS_APOCAC2, 0 }, 1666, 1666, MFLAG_NOSTONE | MFLAG_NOCORPSE | MFLAG_KNOCKBACK | MFLAG_SEARCH, 240, 30, 60, 0, 0, 0, 200, 0, 90, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , 5555, ALIGN }, // MC_DEMON, +/* MT_DARKMAGE*///{ MOFILE_DARKMAGE, 30, 7, NULL, "The Arch-Litch Malignus", { AI_COUNSLR, 3, MIS_FIREBALL, 0 }, 160, 160, MFLAG_CAN_OPEN_DOOR, 120, 20, 40, 0, 0, 0, 0, 0, 70, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 3312, ALIGN }, // MC_DEMON, #ifdef HELLFIRE -/* MT_HELLBOAR */ { MOFILE_FORK, 19, 3, NULL, "Hellboar", { AI_SKELSD, 2, 0, 0 }, 80, 100, MFLAG_KNOCKBACK | MFLAG_SEARCH | MFLAG_CAN_BLEED, 70, 16, 22, 0, 0, 0, 0, 0, 60, 25, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 750, ALIGN }, // MC_DEMON, -/* MT_STINGER */ { MOFILE_SCORP, 18, 1, NULL, "Stinger", { AI_SKELSD, 3, 0, 0 }, 30, 40, 0 , 85, 1, 28, 0, 0, 0, 0, 0, 50, 40, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 500, ALIGN }, // MC_ANIMAL, -/* MT_PSYCHORB */ { MOFILE_EYE, 20, 6, NULL, "Psychorb", { AI_RANGED, 3, MIS_PSYCHORB, FALSE }, 20, 30, 0 , 80, 10, 10, 0, 0, 0, 55, 0, 40, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 450, ALIGN }, // MC_ANIMAL, -/* MT_ARACHNON */ { MOFILE_SPIDER, 20, 7, NULL, "Arachnon", { AI_SKELSD, 3, 0, 0 }, 60, 80, MFLAG_SEARCH , 50, 5, 15, 0, 0, 0, 0, 0, 50, 40, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 500, ALIGN }, // MC_ANIMAL, -/* MT_FELLTWIN */ { MOFILE_TSNEAK, 18, 3, NULL, "Felltwin", { AI_SKELSD, 3, 0, 0 }, 50, 70, MFLAG_SEARCH , 70, 10, 18, 0, 0, 0, 0, 0, 50, 35, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 600, ALIGN }, // MC_DEMON, -/* MT_UNRAV */ { MOFILE_UNRAV, 19, 3, NULL, "The Shredded", { AI_SKELSD, 0, 0, 0 }, 70, 90, 0 , 95, 6, 12, 0, 0, 0, 0, 0, 65, 40, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , 900, ALIGN }, // MC_UNDEAD, -/* MT_HORKSPWN */ { MOFILE_SPAWN, 21, 3, NULL, "Hork Spawn", { AI_SKELSD, 3, 0, 0 }, 30, 30, MFLAG_NODROP , 60, 10, 25, 0, 0, 0, 0, 0, 25, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, 250, ALIGN }, // MC_DEMON, -/* MT_VENMTAIL */ { MOFILE_WSCORP, 22, 1, NULL, "Venomtail", { AI_SKELSD, 3, 0, 0 }, 40, 50, 0 , 95, 1, 32, 0, 0, 0, 0, 0, 60, 50, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 1000, ALIGN }, // MC_ANIMAL, -/* MT_NECRMORB */ { MOFILE_EYE2, 24, 6, NULL, "Necromorb", { AI_RANGED, 3, MIS_NECROMORB, FALSE }, 30, 40, 0 , 80, 20, 20, 0, 0, 0, 60, 0, 50, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1100, ALIGN }, // MC_ANIMAL, -/* MT_SPIDLORD */ { MOFILE_BSPIDR, 24, 7, NULL, "Spider Lord", { AI_ROUNDRANGED, 3, MIS_ACID, 1 }, 80, 100, MFLAG_SEARCH , 60, 8, 20, 0, 0, 0, 60, 0, 60, 50, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 1250, ALIGN }, // MC_ANIMAL, -/* MT_LASHWORM */ { MOFILE_CLASP, 23, 3, NULL, "Lashworm", { AI_SKELSD, 3, 0, 0 }, 30, 30, 0 , 90, 12, 20, 0, 0, 0, 0, 0, 50, 35, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 600, ALIGN }, // MC_ANIMAL, -/* MT_TORCHANT */ { MOFILE_ANTWORM, 22, 7, NULL, "Torchant", { AI_RANGED, 3, MIS_FIREBALL, FALSE }, 60, 80, 0 , 75, 20, 30, 0, 0, 0, 55, 0, 70, 50, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1250, ALIGN }, // MC_ANIMAL, -/* MT_HORKDMN */ { MOFILE_HORKD, 22, 7, NULL, "Hork Demon", { AI_SKELSD, 3, 0, 0 }, 120, 160, MFLAG_SEARCH | MFLAG_CAN_BLEED, 75, 20, 35, 0, 0, 0, 0, 0, 80, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2000, ALIGN }, // MC_DEMON, -/* MT_DEFILER */ { MOFILE_HELLBUG, 24, 7, NULL, "Hell Bug", { AI_FAT, 3, 0, 0 }, 480, 480, MFLAG_SEARCH , 120, 20, 30, 90, 24, 40, 0, 0, 80, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 5000, ALIGN }, // MC_DEMON, -/* MT_LRDSAYTR */ { MOFILE_GOATLORD, 26, 7, NULL, "Satyr Lord", { AI_SKELSD, 3, 0, 0 }, 160, 200, MFLAG_SEARCH | MFLAG_CAN_BLEED, 90, 20, 30, 0, 0, 0, 0, 0, 70, 60, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2800, ALIGN }, // MC_DEMON, -/* MT_GRAVEDIG */ { MOFILE_GRAVDG, 26, 3, NULL, "Gravedigger", { AI_SCAV, 3, 0, 0 }, 120, 240, MFLAG_CAN_OPEN_DOOR, 80, 6, 26, 0, 0, 0, 0, 0, 20, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE , 2000, ALIGN }, // MC_UNDEAD, -/* MT_BIGFALL */ { MOFILE_BIGFALL, 27, 3, NULL, "Devil Kin Brute", { AI_SKELSD, 3, 0, 0 }, 120, 160, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 100, 18, 24, 0, 0, 0, 0, 0, 70, 60, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2400, ALIGN }, // MC_ANIMAL, -/* MT_TOMBRAT */ { MOFILE_RAT, 26, 3, NULL, "Tomb Rat", { AI_SKELSD, 3, 0, 0 }, 80, 120, 0 , 120, 12, 25, 0, 0, 0, 0, 0, 30, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1800, ALIGN }, // MC_ANIMAL, -/* MT_FIREBAT */ { MOFILE_HELLBAT, 27, 7, NULL, "Firebat", { AI_RANGED, 3, MIS_FIREBOLT, FALSE }, 60, 80, 0 , 100, 8, 24, 0, 0, 0, 60, 0, 70, 40, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2400, ALIGN }, // MC_ANIMAL, -/* MT_SKLWING */ { MOFILE_DEMSKEL, 28, 7, "Monsters\\Mega\\Vtexl.TRN", "Skullwing", { AI_SKELSD, 0, 0, 0 }, 70, 70, 0 , 75, 24, 32, 0, 0, 0, 0, 0, 80, 30, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , 3000, ALIGN }, // MC_UNDEAD, -/* MT_LICH */ { MOFILE_LICH, 27, 7, NULL, "Lich", { AI_RANGED, 3, MIS_LICH, FALSE }, 80, 100, 0 , 100, 16, 20, 0, 0, 0, 60, 0, 60, 20, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE , 3000, ALIGN }, // MC_UNDEAD, -/* MT_CRYPTDMN */ { MOFILE_BUBBA, 29, 3, "Monsters\\Fat\\FatB.TRN", "Crypt Demon", { AI_SKELSD, 3, 0, 0 }, 200, 240, 0 , 100, 20, 40, 0, 0, 0, 0, 0, 85, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 3200, ALIGN }, // MC_DEMON, -/* MT_HELLBAT */ { MOFILE_HELLBAT2, 29, 7, NULL, "Hellbat", { AI_RANGED, 3, MIS_FIREBALL, FALSE }, 100, 140, 0 , 110, 30, 30, 0, 0, 0, 70, 0, 80, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 3600, ALIGN }, // MC_DEMON, -/* MT_BONEDEMN */ { MOFILE_DEMSKEL, 30, 7, "Monsters\\Fat\\FatB.TRN", "Bone Demon", { AI_ROUNDRANGED, 0, MIS_BONEDEMON, 0 }, 240, 280, 0 , 100, 40, 50, 0, 0, 0, 70, 0, 50, 20, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE , 5000, ALIGN }, // MC_UNDEAD, -/* MT_ARCHLICH */ { MOFILE_LICH2, 30, 7, NULL, "Arch Lich", { AI_RANGED, 3, MIS_ARCHLICH, FALSE }, 180, 200, 0 , 120, 30, 30, 0, 0, 0, 70, 0, 75, 25, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE , 4000, ALIGN }, // MC_UNDEAD, -/* MT_BICLOPS */ { MOFILE_BYCLPS, 30, 3, NULL, "Biclops", { AI_SKELSD, 3, 0, 0 }, 200, 240, MFLAG_KNOCKBACK | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 90, 40, 50, 0, 0, 0, 0, 0, 80, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 4000, ALIGN }, // MC_DEMON, -/* MT_FLESTHNG */ { MOFILE_FLESH, 28, 7, NULL, "Flesh Thing", { AI_SKELSD, 3, 0, 0 }, 300, 400, MFLAG_CAN_BLEED, 150, 12, 18, 0, 0, 0, 0, 0, 70, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 4000, ALIGN }, // MC_DEMON, -/* MT_REAPER */ { MOFILE_REAPER, 30, 3, NULL, "Reaper", { AI_SKELSD, 3, 0, 0 }, 260, 300, MFLAG_CAN_BLEED, 120, 30, 35, 0, 0, 0, 0, 0, 90, 35, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 6000, ALIGN }, // MC_DEMON, -/* MT_NAKRUL */ { MOFILE_NKR, 32, 7, NULL, "Na-Krul", { AI_SKELSD, 3, 0, 0 }, 1332, 1332, MFLAG_NOSTONE | MFLAG_KNOCKBACK | MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 150, 40, 50, 0, 0, 0, 0, 0, 125, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 7333, ALIGN }, // MC_DEMON, +/* MT_HELLBOAR */ { MOFILE_FORK, 19, 3, NULL, "Hellboar", { AI_SKELSD, 2, 0, 0 }, 80, 100, MFLAG_KNOCKBACK | MFLAG_SEARCH | MFLAG_CAN_BLEED, 70, 16, 22, 0, 0, 0, 0, 0, 60, 25, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 500, ALIGN }, // MC_DEMON, +/* MT_STINGER */ { MOFILE_SCORP, 18, 1, NULL, "Stinger", { AI_SKELSD, 3, 0, 0 }, 30, 40, 0 , 85, 1, 28, 0, 0, 0, 0, 0, 50, 40, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 333, ALIGN }, // MC_ANIMAL, +/* MT_PSYCHORB */ { MOFILE_EYE, 20, 6, NULL, "Psychorb", { AI_RANGED, 3, MIS_PSYCHORB, FALSE }, 20, 30, 0 , 80, 10, 10, 0, 0, 0, 55, 0, 40, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 300, ALIGN }, // MC_ANIMAL, +/* MT_ARACHNON */ { MOFILE_SPIDER, 20, 7, NULL, "Arachnon", { AI_SKELSD, 3, 0, 0 }, 60, 80, MFLAG_SEARCH , 50, 5, 15, 0, 0, 0, 0, 0, 50, 40, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 333, ALIGN }, // MC_ANIMAL, +/* MT_FELLTWIN */ { MOFILE_TSNEAK, 18, 3, NULL, "Felltwin", { AI_SKELSD, 3, 0, 0 }, 50, 70, MFLAG_SEARCH , 70, 10, 18, 0, 0, 0, 0, 0, 50, 35, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 400, ALIGN }, // MC_DEMON, +/* MT_UNRAV */ { MOFILE_UNRAV, 19, 3, NULL, "The Shredded", { AI_SKELSD, 0, 0, 0 }, 70, 90, 0 , 95, 6, 12, 0, 0, 0, 0, 0, 65, 40, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , 600, ALIGN }, // MC_UNDEAD, +/* MT_HORKSPWN */ { MOFILE_SPAWN, 21, 3, NULL, "Hork Spawn", { AI_SKELSD, 3, 0, 0 }, 30, 30, MFLAG_NODROP , 60, 10, 25, 0, 0, 0, 0, 0, 25, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, 166, ALIGN }, // MC_DEMON, +/* MT_VENMTAIL */ { MOFILE_WSCORP, 22, 1, NULL, "Venomtail", { AI_SKELSD, 3, 0, 0 }, 40, 50, 0 , 95, 1, 32, 0, 0, 0, 0, 0, 60, 50, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 666, ALIGN }, // MC_ANIMAL, +/* MT_NECRMORB */ { MOFILE_EYE2, 24, 6, NULL, "Necromorb", { AI_RANGED, 3, MIS_NECROMORB, FALSE }, 30, 40, 0 , 80, 20, 20, 0, 0, 0, 60, 0, 50, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 733, ALIGN }, // MC_ANIMAL, +/* MT_SPIDLORD */ { MOFILE_BSPIDR, 24, 7, NULL, "Spider Lord", { AI_ROUNDRANGED, 3, MIS_ACID, 1 }, 80, 100, MFLAG_SEARCH , 60, 8, 20, 0, 0, 0, 60, 0, 60, 50, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 833, ALIGN }, // MC_ANIMAL, +/* MT_LASHWORM */ { MOFILE_CLASP, 23, 3, NULL, "Lashworm", { AI_SKELSD, 3, 0, 0 }, 30, 30, 0 , 90, 12, 20, 0, 0, 0, 0, 0, 50, 35, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 400, ALIGN }, // MC_ANIMAL, +/* MT_TORCHANT */ { MOFILE_ANTWORM, 22, 7, NULL, "Torchant", { AI_RANGED, 3, MIS_FIREBALL, FALSE }, 60, 80, 0 , 75, 20, 30, 0, 0, 0, 55, 0, 70, 50, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 833, ALIGN }, // MC_ANIMAL, +/* MT_HORKDMN */ { MOFILE_HORKD, 22, 7, NULL, "Hork Demon", { AI_SKELSD, 3, 0, 0 }, 120, 160, MFLAG_SEARCH | MFLAG_CAN_BLEED, 75, 20, 35, 0, 0, 0, 0, 0, 80, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 1333, ALIGN }, // MC_DEMON, +/* MT_DEFILER */ { MOFILE_HELLBUG, 24, 7, NULL, "Hell Bug", { AI_FAT, 3, 0, 0 }, 480, 480, MFLAG_SEARCH , 120, 20, 30, 90, 24, 40, 0, 0, 80, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 3333, ALIGN }, // MC_DEMON, +/* MT_LRDSAYTR */ { MOFILE_GOATLORD, 26, 7, NULL, "Satyr Lord", { AI_SKELSD, 3, 0, 0 }, 160, 200, MFLAG_SEARCH | MFLAG_CAN_BLEED, 90, 20, 30, 0, 0, 0, 0, 0, 70, 60, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 1866, ALIGN }, // MC_DEMON, +/* MT_GRAVEDIG */ { MOFILE_GRAVDG, 26, 3, NULL, "Gravedigger", { AI_SCAV, 3, 0, 0 }, 120, 240, MFLAG_CAN_OPEN_DOOR, 80, 6, 26, 0, 0, 0, 0, 0, 20, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE , 1333, ALIGN }, // MC_UNDEAD, +/* MT_BIGFALL */ { MOFILE_BIGFALL, 27, 3, NULL, "Devil Kin Brute", { AI_SKELSD, 3, 0, 0 }, 120, 160, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 100, 18, 24, 0, 0, 0, 0, 0, 70, 60, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1600, ALIGN }, // MC_ANIMAL, +/* MT_TOMBRAT */ { MOFILE_RAT, 26, 3, NULL, "Tomb Rat", { AI_SKELSD, 3, 0, 0 }, 80, 120, 0 , 120, 12, 25, 0, 0, 0, 0, 0, 30, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1200, ALIGN }, // MC_ANIMAL, +/* MT_FIREBAT */ { MOFILE_HELLBAT, 27, 7, NULL, "Firebat", { AI_RANGED, 3, MIS_FIREBOLT, FALSE }, 60, 80, 0 , 100, 8, 24, 0, 0, 0, 60, 0, 70, 40, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1600, ALIGN }, // MC_ANIMAL, +/* MT_SKLWING */ { MOFILE_DEMSKEL, 28, 7, "Monsters\\Mega\\Vtexl.TRN", "Skullwing", { AI_SKELSD, 0, 0, 0 }, 70, 70, 0 , 75, 24, 32, 0, 0, 0, 0, 0, 80, 30, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , 2000, ALIGN }, // MC_UNDEAD, +/* MT_LICH */ { MOFILE_LICH, 27, 7, NULL, "Lich", { AI_RANGED, 3, MIS_LICH, FALSE }, 80, 100, 0 , 100, 16, 20, 0, 0, 0, 60, 0, 60, 20, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE , 2000, ALIGN }, // MC_UNDEAD, +/* MT_CRYPTDMN */ { MOFILE_BUBBA, 29, 3, "Monsters\\Fat\\FatB.TRN", "Crypt Demon", { AI_SKELSD, 3, 0, 0 }, 200, 240, 0 , 100, 20, 40, 0, 0, 0, 0, 0, 85, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2133, ALIGN }, // MC_DEMON, +/* MT_HELLBAT */ { MOFILE_HELLBAT2, 29, 7, NULL, "Hellbat", { AI_RANGED, 3, MIS_FIREBALL, FALSE }, 100, 140, 0 , 110, 30, 30, 0, 0, 0, 70, 0, 80, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2400, ALIGN }, // MC_DEMON, +/* MT_BONEDEMN */ { MOFILE_DEMSKEL, 30, 7, "Monsters\\Fat\\FatB.TRN", "Bone Demon", { AI_ROUNDRANGED, 0, MIS_BONEDEMON, 0 }, 240, 280, 0 , 100, 40, 50, 0, 0, 0, 70, 0, 50, 20, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE , 3333, ALIGN }, // MC_UNDEAD, +/* MT_ARCHLICH */ { MOFILE_LICH2, 30, 7, NULL, "Arch Lich", { AI_RANGED, 3, MIS_ARCHLICH, FALSE }, 180, 200, 0 , 120, 30, 30, 0, 0, 0, 70, 0, 75, 25, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE , 2666, ALIGN }, // MC_UNDEAD, +/* MT_BICLOPS */ { MOFILE_BYCLPS, 30, 3, NULL, "Biclops", { AI_SKELSD, 3, 0, 0 }, 200, 240, MFLAG_KNOCKBACK | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 90, 40, 50, 0, 0, 0, 0, 0, 80, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2666, ALIGN }, // MC_DEMON, +/* MT_FLESTHNG */ { MOFILE_FLESH, 28, 7, NULL, "Flesh Thing", { AI_SKELSD, 3, 0, 0 }, 300, 400, MFLAG_CAN_BLEED, 150, 12, 18, 0, 0, 0, 0, 0, 70, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2666, ALIGN }, // MC_DEMON, +/* MT_REAPER */ { MOFILE_REAPER, 30, 3, NULL, "Reaper", { AI_SKELSD, 3, 0, 0 }, 260, 300, MFLAG_CAN_BLEED, 120, 30, 35, 0, 0, 0, 0, 0, 90, 35, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 4000, ALIGN }, // MC_DEMON, +/* MT_NAKRUL */ { MOFILE_NKR, 32, 7, NULL, "Na-Krul", { AI_SKELSD, 3, 0, 0 }, 1332, 1332, MFLAG_NOSTONE | MFLAG_KNOCKBACK | MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 150, 40, 50, 0, 0, 0, 0, 0, 125, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 4888, ALIGN }, // MC_DEMON, #endif // clang-format on }; diff --git a/Source/monster.cpp b/Source/monster.cpp index 49f9d504ba1..edc1df46692 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1127,8 +1127,6 @@ void InitMonsters() na = na * AllLevels[currLvl._dLevelIdx].dMonDensity / 32; numplacemonsters = na / 32; - if (IsMultiGame) - numplacemonsters += numplacemonsters >> 1; totalmonsters = nummonsters + numplacemonsters; if (totalmonsters > MAXMONSTERS - 10) totalmonsters = MAXMONSTERS - 10; diff --git a/Source/questdat.cpp b/Source/questdat.cpp index 3c89da03080..34bf96769f0 100644 --- a/Source/questdat.cpp +++ b/Source/questdat.cpp @@ -17,100 +17,100 @@ const LevelData AllLevels[NUM_LEVELS] = { { MT_INVALID }, }, /*DLV_CATHEDRAL1*/ { 2, FALSE, DTYPE_CATHEDRAL, DGT_CATHEDRAL, TMUSIC_L1, LFILE_L1, 10, 10, "Cathedral 1", - "Levels\\L1Data\\L1_%d.PAL", "Gendata\\Cutl1d.CEL", "Gendata\\Cutl1d.pal", TRUE, 138, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L1Data\\L1_%d.PAL", "Gendata\\Cutl1d.CEL", "Gendata\\Cutl1d.pal", TRUE, 138, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_NZOMBIE, MT_RFALLSP, MT_WSKELAX, MT_RFALLSD, MT_NSCAV, MT_WSKELSD, MT_INVALID }, }, /*DLV_CATHEDRAL2*/ { 4, FALSE, DTYPE_CATHEDRAL, DGT_CATHEDRAL, TMUSIC_L1, LFILE_L1, 10, 10, "Cathedral 2", - "Levels\\L1Data\\L1_%d.PAL", "Gendata\\Cutl1d.CEL", "Gendata\\Cutl1d.pal", TRUE, 138, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L1Data\\L1_%d.PAL", "Gendata\\Cutl1d.CEL", "Gendata\\Cutl1d.pal", TRUE, 138, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_NZOMBIE, MT_RFALLSP, MT_WSKELAX, MT_RFALLSD, MT_NSCAV, MT_WSKELSD, MT_BZOMBIE, MT_GZOMBIE, MT_DFALLSP, MT_YFALLSP, MT_TSKELAX, MT_RSKELAX, MT_DFALLSD, MT_YFALLSD, MT_WSKELBW, MT_TSKELBW, MT_BSCAV, MT_TSKELSD, MT_NSNEAK, MT_RBAT, MT_INVALID }, }, /*DLV_CATHEDRAL3*/ { 6, FALSE, DTYPE_CATHEDRAL, DGT_CATHEDRAL, TMUSIC_L1, LFILE_L1, 10, 10, "Cathedral 3", - "Levels\\L1Data\\L1_%d.PAL", "Gendata\\Cutl1d.CEL", "Gendata\\Cutl1d.pal", TRUE, 138, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L1Data\\L1_%d.PAL", "Gendata\\Cutl1d.CEL", "Gendata\\Cutl1d.pal", TRUE, 138, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_NSCAV, MT_WSKELSD, MT_BZOMBIE, MT_GZOMBIE, MT_DFALLSP, MT_YFALLSP, MT_TSKELAX, MT_RSKELAX, MT_DFALLSD, MT_YFALLSD, MT_WSKELBW, MT_TSKELBW, MT_BSCAV, MT_TSKELSD, MT_NSNEAK, MT_RBAT, MT_NBAT, MT_YZOMBIE, MT_BFALLSP, MT_XSKELAX, MT_BFALLSD, MT_WSCAV, MT_RSKELBW, MT_RSKELSD, MT_INVALID }, }, /*DLV_CATHEDRAL4*/ { 8, FALSE, DTYPE_CATHEDRAL, DGT_CATHEDRAL, TMUSIC_L1, LFILE_L1, 10, 10, "Cathedral 4", - "Levels\\L1Data\\L1_%d.PAL", "Gendata\\Cutl1d.CEL", "Gendata\\Cutl1d.pal", TRUE, 138, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L1Data\\L1_%d.PAL", "Gendata\\Cutl1d.CEL", "Gendata\\Cutl1d.pal", TRUE, 138, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_GZOMBIE, MT_YFALLSP, MT_RSKELAX, MT_YFALLSD, MT_TSKELBW, MT_BSCAV, MT_TSKELSD, MT_NSNEAK, MT_NBAT, MT_YZOMBIE, MT_BFALLSP, MT_XSKELAX, MT_BFALLSD, MT_WSCAV, MT_RSKELBW, MT_RSKELSD, MT_GBAT, MT_YSCAV, MT_XSKELBW, MT_XSKELSD, MT_NGOATMC, MT_NGOATBW, MT_INVALID }, }, /*DLV_CATACOMBS1*/ { 10, FALSE, DTYPE_CATACOMBS, DGT_CATACOMBS, TMUSIC_L2, LFILE_L2, 10, 10, "Catacombs 1", - "Levels\\L2Data\\L2_%d.PAL", "Gendata\\Cut2.CEL", "Gendata\\Cut2.pal", TRUE, 254, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L2Data\\L2_%d.PAL", "Gendata\\Cut2.CEL", "Gendata\\Cut2.pal", TRUE, 254, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_NSNEAK, MT_NBAT, MT_YZOMBIE, MT_BFALLSP, MT_XSKELAX, MT_BFALLSD, MT_WSCAV, MT_RSKELBW, MT_RSKELSD, MT_GBAT, MT_YSCAV, MT_XSKELBW, MT_XSKELSD, MT_NGOATMC, MT_NGOATBW, MT_BGOATBW, MT_BGOATMC, MT_RSNEAK, MT_NFAT, MT_NGARG, MT_INVALID }, }, /*DLV_CATACOMBS2*/ { 12, FALSE, DTYPE_CATACOMBS, DGT_CATACOMBS, TMUSIC_L2, LFILE_L2, 10, 10, "Catacombs 2", - "Levels\\L2Data\\L2_%d.PAL", "Gendata\\Cut2.CEL", "Gendata\\Cut2.pal", TRUE, 254, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L2Data\\L2_%d.PAL", "Gendata\\Cut2.CEL", "Gendata\\Cut2.pal", TRUE, 254, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_GBAT, MT_YSCAV, MT_XSKELBW, MT_XSKELSD, MT_NGOATMC, MT_NGOATBW, MT_BGOATBW, MT_BGOATMC, MT_RSNEAK, MT_NFAT, MT_NGARG, MT_BSNEAK, MT_RGOATMC, MT_XBAT, MT_RGOATBW, MT_NACID, MT_INVALID }, }, /*DLV_CATACOMBS3*/ { 14, FALSE, DTYPE_CATACOMBS, DGT_CATACOMBS, TMUSIC_L2, LFILE_L2, 10, 10, "Catacombs 3", - "Levels\\L2Data\\L2_%d.PAL", "Gendata\\Cut2.CEL", "Gendata\\Cut2.pal", TRUE, 254, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L2Data\\L2_%d.PAL", "Gendata\\Cut2.CEL", "Gendata\\Cut2.pal", TRUE, 254, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_BGOATBW, MT_BGOATMC, MT_RSNEAK, MT_NFAT, MT_NGARG, MT_BSNEAK, MT_RGOATMC, MT_XBAT, MT_RGOATBW, MT_NACID, MT_GGOATBW, MT_GGOATMC, MT_BFAT, MT_NRHINO, MT_XGARG, MT_INVALID }, }, /*DLV_CATACOMBS4*/ { 16, FALSE, DTYPE_CATACOMBS, DGT_CATACOMBS, TMUSIC_L2, LFILE_L2, 10, 10, "Catacombs 4", - "Levels\\L2Data\\L2_%d.PAL", "Gendata\\Cut2.CEL", "Gendata\\Cut2.pal", TRUE, 254, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L2Data\\L2_%d.PAL", "Gendata\\Cut2.CEL", "Gendata\\Cut2.pal", TRUE, 254, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_BSNEAK, MT_RGOATMC, MT_XBAT, MT_RGOATBW, MT_NACID, MT_GGOATBW, MT_GGOATMC, MT_BFAT, MT_NRHINO, MT_XGARG, MT_XRHINO, MT_YSNEAK, MT_RACID, MT_XFAT, MT_NMAGMA, MT_YMAGMA, MT_INVALID }, }, /*DLV_CAVES1*/ { 18, FALSE, DTYPE_CAVES, DGT_CAVES, TMUSIC_L3, LFILE_L3, 10, 10, "Caves 1", - "Levels\\L3Data\\L3_%d.PAL", "Gendata\\Cut3.CEL", "Gendata\\Cut3.pal", FALSE, 43, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L3Data\\L3_%d.PAL", "Gendata\\Cut3.CEL", "Gendata\\Cut3.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_GGOATBW, MT_GGOATMC, MT_BFAT, MT_NRHINO, MT_XGARG, MT_XRHINO, MT_YSNEAK, MT_RACID, MT_XFAT, MT_NMAGMA, MT_YMAGMA, MT_DGARG, MT_BMAGMA, MT_WMAGMA, MT_BRHINO, MT_RTHIN, MT_INVALID }, }, /*DLV_CAVES2*/ { 20, FALSE, DTYPE_CAVES, DGT_CAVES, TMUSIC_L3, LFILE_L3, 10, 10, "Caves 2", - "Levels\\L3Data\\L3_%d.PAL", "Gendata\\Cut3.CEL", "Gendata\\Cut3.pal", FALSE, 43, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L3Data\\L3_%d.PAL", "Gendata\\Cut3.CEL", "Gendata\\Cut3.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_XRHINO, MT_YSNEAK, MT_RACID, MT_XFAT, MT_YMAGMA, MT_DGARG, MT_BMAGMA, MT_WMAGMA, MT_BRHINO, MT_RTHIN, MT_DRHINO, MT_BACID, MT_RFAT, MT_NTHIN, MT_BGARG, MT_NMEGA, MT_INVALID }, }, /*DLV_CAVES3*/ { 22, FALSE, DTYPE_CAVES, DGT_CAVES, TMUSIC_L3, LFILE_L3, 10, 10, "Caves 3", - "Levels\\L3Data\\L3_%d.PAL", "Gendata\\Cut3.CEL", "Gendata\\Cut3.pal", FALSE, 43, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L3Data\\L3_%d.PAL", "Gendata\\Cut3.CEL", "Gendata\\Cut3.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_DGARG, MT_BMAGMA, MT_WMAGMA, MT_BRHINO, MT_RTHIN, MT_DRHINO, MT_BACID, MT_RFAT, MT_NTHIN, MT_BGARG, MT_NMEGA, MT_DMEGA, MT_NSNAKE, MT_XTHIN, MT_INVALID }, }, /*DLV_CAVES4*/ { 24, FALSE, DTYPE_CAVES, DGT_CAVES, TMUSIC_L3, LFILE_L3, 10, 10, "Caves 4", - "Levels\\L3Data\\L3_%d.PAL", "Gendata\\Cut3.CEL", "Gendata\\Cut3.pal", FALSE, 43, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L3Data\\L3_%d.PAL", "Gendata\\Cut3.CEL", "Gendata\\Cut3.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_DRHINO, MT_BACID, MT_RFAT, MT_NTHIN, MT_BGARG, MT_NMEGA, MT_DMEGA, MT_NSNAKE, MT_XTHIN, MT_RSNAKE, MT_NBLACK, MT_NSUCC, MT_BMEGA, MT_XACID, MT_GTHIN, MT_INVALID }, }, /*DLV_HELL1*/ { 26, FALSE, DTYPE_HELL, DGT_HELL, TMUSIC_L4, LFILE_L4, 12, 16, "Hell 1", - "Levels\\L4Data\\L4_%d.PAL", "Gendata\\Cut4.CEL", "Gendata\\Cut4.pal", FALSE, 43, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L4Data\\L4_%d.PAL", "Gendata\\Cut4.CEL", "Gendata\\Cut4.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_DMEGA, MT_NSNAKE, MT_XTHIN, MT_RSNAKE, MT_NBLACK, MT_NSUCC, MT_BMEGA, MT_XACID, MT_GTHIN, MT_RMEGA, MT_BSNAKE, MT_RBLACK, MT_GBLACK, MT_GSUCC, MT_NMAGE, MT_INVALID }, }, /*DLV_HELL2*/ { 28, FALSE, DTYPE_HELL, DGT_HELL, TMUSIC_L4, LFILE_L4, 12, 16, "Hell 2", - "Levels\\L4Data\\L4_%d.PAL", "Gendata\\Cut4.CEL", "Gendata\\Cut4.pal", FALSE, 43, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L4Data\\L4_%d.PAL", "Gendata\\Cut4.CEL", "Gendata\\Cut4.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_RSNAKE, MT_NBLACK, MT_NSUCC, MT_BMEGA, MT_XACID, MT_GTHIN, MT_RMEGA, MT_BSNAKE, MT_RBLACK, MT_GBLACK, MT_GSUCC, MT_NMAGE, MT_GMAGE, MT_BBLACK, MT_RSUCC, MT_INVALID }, }, /*DLV_HELL3*/ { 30, FALSE, DTYPE_HELL, DGT_HELL, TMUSIC_L4, LFILE_L4, 12, 16, "Hell 3", - "Levels\\L4Data\\L4_%d.PAL", "Gendata\\Cut4.CEL", "Gendata\\Cut4.pal", FALSE, 43, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L4Data\\L4_%d.PAL", "Gendata\\Cut4.CEL", "Gendata\\Cut4.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_RMEGA, MT_RBLACK, MT_GSUCC, MT_GMAGE, MT_BBLACK, MT_RSUCC, MT_GSNAKE, MT_BSUCC, MT_XMAGE, MT_INVALID }, }, /*DLV_HELL4*/ { 32, FALSE, DTYPE_HELL, DGT_HELL, TMUSIC_L4, LFILE_L4, 12, 16, "Diablo", - "Levels\\L4Data\\L4_%d.PAL", "Gendata\\Cutgate.CEL", "Gendata\\Cutgate.pal", FALSE, 43, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L4Data\\L4_%d.PAL", "Gendata\\Cutgate.CEL", "Gendata\\Cutgate.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_INVALID }, /* MT_GBLACK, MT_BMAGE, MT_NBLACK, MT_DIABLO */ }, #ifdef HELLFIRE /*DLV_NEST1*/ { 18, FALSE, DTYPE_NEST, DGT_CAVES, TMUSIC_L6, LFILE_L6, 10, 10, "Nest 1", - "NLevels\\L6Data\\L6Base%d.PAL", "Nlevels\\Cutl6.CEL", "Nlevels\\Cutl6.pal", FALSE, 43, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "NLevels\\L6Data\\L6Base%d.PAL", "Nlevels\\Cutl6.CEL", "Nlevels\\Cutl6.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_HELLBOAR, MT_STINGER, MT_PSYCHORB, MT_ARACHNON, MT_FELLTWIN, MT_UNRAV, MT_INVALID }, }, /*DLV_NEST2*/ { 20, FALSE, DTYPE_NEST, DGT_CAVES, TMUSIC_L6, LFILE_L6, 10, 10, "Nest 2", - "NLevels\\L6Data\\L6Base%d.PAL", "Nlevels\\Cutl6.CEL", "Nlevels\\Cutl6.pal", FALSE, 43, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "NLevels\\L6Data\\L6Base%d.PAL", "Nlevels\\Cutl6.CEL", "Nlevels\\Cutl6.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_HELLBOAR, MT_STINGER, MT_PSYCHORB, MT_ARACHNON, MT_FELLTWIN, MT_UNRAV, MT_INVALID }, /* MT_HORKSPWN */ }, /*DLV_NEST3*/ { 22, FALSE, DTYPE_NEST, DGT_CAVES, TMUSIC_L6, LFILE_L6, 10, 10, "Nest 3", - "NLevels\\L6Data\\L6Base%d.PAL", "Nlevels\\Cutl6.CEL", "Nlevels\\Cutl6.pal", FALSE, 43, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "NLevels\\L6Data\\L6Base%d.PAL", "Nlevels\\Cutl6.CEL", "Nlevels\\Cutl6.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_VENMTAIL, MT_NECRMORB, MT_SPIDLORD, MT_LASHWORM, MT_TORCHANT, MT_INVALID }, /* MT_HORKSPWN, MT_HORKDMN */ }, /*DLV_NEST4*/ { 24, FALSE, DTYPE_NEST, DGT_CAVES, TMUSIC_L6, LFILE_L6, 10, 10, "Nest 4", - "NLevels\\L6Data\\L6Base%d.PAL", "Nlevels\\Cutl6.CEL", "Nlevels\\Cutl6.pal", FALSE, 43, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "NLevels\\L6Data\\L6Base%d.PAL", "Nlevels\\Cutl6.CEL", "Nlevels\\Cutl6.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_VENMTAIL, MT_NECRMORB, MT_SPIDLORD, MT_LASHWORM, MT_TORCHANT, MT_INVALID }, /* MT_DEFILER */ }, /*DLV_CRYPT1*/ { 26, FALSE, DTYPE_CRYPT, DGT_CATHEDRAL, TMUSIC_L5, LFILE_L5, 10, 10, "Crypt 1", - "NLevels\\L5Data\\L5Base.PAL", "Nlevels\\Cutl5.CEL", "Nlevels\\Cutl5.pal", FALSE, 43, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "NLevels\\L5Data\\L5Base.PAL", "Nlevels\\Cutl5.CEL", "Nlevels\\Cutl5.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_LRDSAYTR, MT_GRAVEDIG, MT_BIGFALL, MT_TOMBRAT, MT_FIREBAT, MT_LICH, MT_INVALID }, }, /*DLV_CRYPT2*/ { 28, FALSE, DTYPE_CRYPT, DGT_CATHEDRAL, TMUSIC_L5, LFILE_L5, 10, 10, "Crypt 2", - "NLevels\\L5Data\\L5Base.PAL", "Nlevels\\Cutl5.CEL", "Nlevels\\Cutl5.pal", FALSE, 43, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "NLevels\\L5Data\\L5Base.PAL", "Nlevels\\Cutl5.CEL", "Nlevels\\Cutl5.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_BIGFALL, MT_TOMBRAT, MT_FIREBAT, MT_SKLWING, MT_LICH, MT_CRYPTDMN, MT_INVALID }, }, /*DLV_CRYPT3*/ { 30, FALSE, DTYPE_CRYPT, DGT_CATHEDRAL, TMUSIC_L5, LFILE_L5, 10, 10, "Crypt 3", - "NLevels\\L5Data\\L5Base.PAL", "Nlevels\\Cutl5.CEL", "Nlevels\\Cutl5.pal", FALSE, 43, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "NLevels\\L5Data\\L5Base.PAL", "Nlevels\\Cutl5.CEL", "Nlevels\\Cutl5.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_CRYPTDMN, MT_HELLBAT, MT_BONEDEMN, MT_ARCHLICH, MT_BICLOPS, MT_FLESTHNG, MT_REAPER, MT_INVALID }, }, /*DLV_CRYPT4*/ { 32, FALSE, DTYPE_CRYPT, DGT_CATHEDRAL, TMUSIC_L5, LFILE_L5, 10, 10, "Crypt 4", - "NLevels\\L5Data\\L5Base.PAL", "Nlevels\\Cutl5.CEL", "Nlevels\\Cutl5.pal", FALSE, 43, 34, 32, 0, 0, WRPT_NONE, SPT_NONE, + "NLevels\\L5Data\\L5Base.PAL", "Nlevels\\Cutl5.CEL", "Nlevels\\Cutl5.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_HELLBAT, MT_BICLOPS, MT_FLESTHNG, MT_REAPER, MT_INVALID }, /* MT_ARCHLICH, MT_NAKRUL */ }, #endif @@ -122,7 +122,7 @@ const LevelData AllLevels[NUM_LEVELS] = { { MT_INVALID }, },*/ /*SL_SKELKING*/ { 6, TRUE, DTYPE_CATHEDRAL, DGT_CATHEDRAL, TMUSIC_L1, LFILE_L1, 10, 10, "Skeleton King's Lair", - "Levels\\L1Data\\L1_2.pal", "Gendata\\Cutl1d.CEL", "Gendata\\Cutl1d.pal", TRUE, 138, 81, 0, DBORDERX+2*33, DBORDERY+2*13, WRPT_L1_UP, SPT_LVL_SKELKING, + "Levels\\L1Data\\L1_2.pal", "Gendata\\Cutl1d.CEL", "Gendata\\Cutl1d.pal", TRUE, 138, 120, 0, DBORDERX+2*33, DBORDERY+2*13, WRPT_L1_UP, SPT_LVL_SKELKING, { MT_RSKELAX, MT_TSKELBW, MT_RSKELBW, MT_XSKELBW, MT_RSKELSD, MT_INVALID }, }, /*SL_BONECHAMB*/ { 12, TRUE, DTYPE_CATACOMBS, DGT_CATACOMBS, TMUSIC_L2, LFILE_L2, 10, 10, "Chamber of Bone", @@ -134,7 +134,7 @@ const LevelData AllLevels[NUM_LEVELS] = { { MT_INVALID }, / * MT_XRHINO * / },*/ /*SL_POISONWATER*/ { 4, TRUE, DTYPE_CAVES, DGT_CAVES, TMUSIC_L3, LFILE_L3, 10, 10, "Poisoned Water Supply", - "Levels\\L3Data\\L3pfoul.pal", "Gendata\\Cutl1d.CEL", "Gendata\\Cutl1d.pal", TRUE, 138, 70, 0, DBORDERX+2*7, DBORDERY+2*33+1, WRPT_L3_DOWN, SPT_LVL_PWATER, + "Levels\\L3Data\\L3pfoul.pal", "Gendata\\Cutl1d.CEL", "Gendata\\Cutl1d.pal", TRUE, 138, 100, 0, DBORDERX+2*7, DBORDERY+2*33+1, WRPT_L3_DOWN, SPT_LVL_PWATER, { MT_DFALLSP, MT_YFALLSD, MT_INVALID }, /* , MT_NGOATMC, MT_NGOATBW */ }, /*SL_VILEBETRAYER*/ { 30, TRUE, DTYPE_CATHEDRAL, DGT_CATHEDRAL, TMUSIC_L1, LFILE_L1, 10, 10, "Archbishop Lazarus' Lair", From 8881a8ac5050ed0619011e9e9feffdc3b745961e Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 6 Jan 2024 11:42:31 +0100 Subject: [PATCH 239/596] cosmetic --- Source/missiles.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 0f7ffa8668e..4217afd1dd1 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -2040,11 +2040,12 @@ int AddTeleport(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, // MisInCastDistance(sx, sy, midir, dx, dy, 7); while (true) { - tx = abs(sx - dx); - ty = abs(sy - dy); + tx = sx - dx; + ty = sy - dy; i = sqrt(tx * tx + ty * ty); if (i <= 7) break; + // assert(i < MAXDUNX + MAXDUNY); dx += offset_x[OPPOSITE(midir)]; dy += offset_y[OPPOSITE(midir)]; } From b218c7e05f3dc519e6e139f490c9862721982def Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 11 Jan 2024 10:46:17 +0100 Subject: [PATCH 240/596] cleanup the swapping functions of StormLib --- 3rdParty/StormLib/src/SBaseCommon.cpp | 31 +++++---------------------- 3rdParty/StormLib/src/StormPort.h | 20 +++-------------- 2 files changed, 8 insertions(+), 43 deletions(-) diff --git a/3rdParty/StormLib/src/SBaseCommon.cpp b/3rdParty/StormLib/src/SBaseCommon.cpp index 4acde94c4e8..bd09744bdb9 100644 --- a/3rdParty/StormLib/src/SBaseCommon.cpp +++ b/3rdParty/StormLib/src/SBaseCommon.cpp @@ -1817,41 +1817,20 @@ void CalculateDataBlockHash(void * pvDataBlock, DWORD cbDataBlock, LPBYTE md5_ha #ifndef STORMLIB_LITTLE_ENDIAN -// Swaps a signed 16-bit integer -int16_t SwapInt16(uint16_t val) -{ - return (val << 8) | ((val >> 8) & 0xFF); -} - -// Swaps an unsigned 16-bit integer +// Swaps a 16-bit integer uint16_t SwapUInt16(uint16_t val) { return (val << 8) | (val >> 8 ); } -// Swaps a signed 32-bit integer -int32_t SwapInt32(uint32_t val) -{ - val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF ); - return (val << 16) | ((val >> 16) & 0xFFFF); -} - -// Swaps an unsigned 32-bit integer +// Swaps a 32-bit integer uint32_t SwapUInt32(uint32_t val) { val = ((val << 8) & 0xFF00FF00 ) | ((val >> 8) & 0xFF00FF ); return (val << 16) | (val >> 16); } -// Swaps a signed 64-bit integer -int64_t SwapInt64(uint64_t val) -{ - val = ((val << 8) & 0xFF00FF00FF00FF00ULL ) | ((val >> 8) & 0x00FF00FF00FF00FFULL ); - val = ((val << 16) & 0xFFFF0000FFFF0000ULL ) | ((val >> 16) & 0x0000FFFF0000FFFFULL ); - return (val << 32) | ((val >> 32) & 0xFFFFFFFFULL); -} - -// Swaps an unsigned 64-bit integer +// Swaps a 64-bit integer uint64_t SwapUInt64(uint64_t val) { val = ((val << 8) & 0xFF00FF00FF00FF00ULL ) | ((val >> 8) & 0x00FF00FF00FF00FFULL ); @@ -1886,7 +1865,7 @@ void ConvertUInt32Buffer(void * ptr, size_t length) } // Swaps array of unsigned 64-bit integers -void ConvertUInt64Buffer(void * ptr, size_t length) +/*void ConvertUInt64Buffer(void * ptr, size_t length) { uint64_t * buffer = (uint64_t *)ptr; uint32_t nElements = (uint32_t)(length / sizeof(uint64_t)); @@ -1896,7 +1875,7 @@ void ConvertUInt64Buffer(void * ptr, size_t length) *buffer = SwapUInt64(*buffer); buffer++; } -} +}*/ // Swaps the TMPQHeader structure void ConvertTMPQHeader(void *header, uint16_t version) diff --git a/3rdParty/StormLib/src/StormPort.h b/3rdParty/StormLib/src/StormPort.h index 92faa818e64..69f03ba534d 100644 --- a/3rdParty/StormLib/src/StormPort.h +++ b/3rdParty/StormLib/src/StormPort.h @@ -426,48 +426,34 @@ #ifdef STORMLIB_LITTLE_ENDIAN #define BSWAP_INT16_UNSIGNED(a) (a) - #define BSWAP_INT16_SIGNED(a) (a) #define BSWAP_INT32_UNSIGNED(a) (a) - #define BSWAP_INT32_SIGNED(a) (a) - #define BSWAP_INT64_SIGNED(a) (a) #define BSWAP_INT64_UNSIGNED(a) (a) #define BSWAP_ARRAY16_UNSIGNED(a,b) {} #define BSWAP_ARRAY32_UNSIGNED(a,b) {} - #define BSWAP_ARRAY64_UNSIGNED(a,b) {} - #define BSWAP_PART_HEADER(a) {} +// #define BSWAP_ARRAY64_UNSIGNED(a,b) {} #define BSWAP_TMPQHEADER(a,b) {} - #define BSWAP_TMPKHEADER(a) {} #else #ifdef __cplusplus extern "C" { #endif - int16_t SwapInt16(uint16_t); uint16_t SwapUInt16(uint16_t); - int32_t SwapInt32(uint32_t); uint32_t SwapUInt32(uint32_t); - int64_t SwapInt64(uint64_t); uint64_t SwapUInt64(uint64_t); void ConvertUInt16Buffer(void * ptr, size_t length); void ConvertUInt32Buffer(void * ptr, size_t length); - void ConvertUInt64Buffer(void * ptr, size_t length); - void ConvertTMPQUserData(void *userData); +// void ConvertUInt64Buffer(void * ptr, size_t length); void ConvertTMPQHeader(void *header, uint16_t wPart); - void ConvertTMPKHeader(void *header); #ifdef __cplusplus } #endif - #define BSWAP_INT16_SIGNED(a) SwapInt16((a)) #define BSWAP_INT16_UNSIGNED(a) SwapUInt16((a)) - #define BSWAP_INT32_SIGNED(a) SwapInt32((a)) #define BSWAP_INT32_UNSIGNED(a) SwapUInt32((a)) - #define BSWAP_INT64_SIGNED(a) SwapInt64((a)) #define BSWAP_INT64_UNSIGNED(a) SwapUInt64((a)) #define BSWAP_ARRAY16_UNSIGNED(a,b) ConvertUInt16Buffer((a),(b)) #define BSWAP_ARRAY32_UNSIGNED(a,b) ConvertUInt32Buffer((a),(b)) - #define BSWAP_ARRAY64_UNSIGNED(a,b) ConvertUInt64Buffer((a),(b)) +// #define BSWAP_ARRAY64_UNSIGNED(a,b) ConvertUInt64Buffer((a),(b)) #define BSWAP_TMPQHEADER(a,b) ConvertTMPQHeader((a),(b)) - #define BSWAP_TMPKHEADER(a) ConvertTMPKHeader((a)) #endif #endif // __STORMPORT_H__ From 4dce080c1bd0367a298d74e64cab789dfa508719 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 16 Jan 2024 08:58:36 +0100 Subject: [PATCH 241/596] improve the handling of volume during video-playback - do not decode audio if sound is turned off - do not adjust audio if volume is on max (or after the video loops) --- Source/storm/storm_svid.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Source/storm/storm_svid.cpp b/Source/storm/storm_svid.cpp index 22299cdc5f9..cecba0d34ef 100644 --- a/Source/storm/storm_svid.cpp +++ b/Source/storm/storm_svid.cpp @@ -33,6 +33,8 @@ static BYTE* SVidBuffer; static unsigned long SVidWidth, SVidHeight; #ifndef NOSOUND static BYTE SVidAudioDepth; +/* 1: adjust the volume of a 16bit audio, 0: adjust the volume of a 8bit audio, -1: do not adjust the volume (on max sound or when looping) */ +static int8_t SVidAudioAdjust; #endif static bool IsLandscapeFit(unsigned long srcW, unsigned long srcH, unsigned long dstW, unsigned long dstH) @@ -265,18 +267,20 @@ HANDLE SVidPlayBegin(const char* filename, int flags) } #ifndef NOSOUND - if (enableAudio) { + if (enableAudio && gbSoundOn) { unsigned char channels, depth; unsigned long rate; smk_info_audio(SVidSMK, &channels, &depth, &rate); if (depth != 0) { + smk_enable_audio(SVidSMK, 0, true); + SVidAudioDepth = depth; + SVidAudioAdjust = gnSoundVolume == VOLUME_MAX ? -1 : (depth == 16 ? 1 : 0); - smk_enable_audio(SVidSMK, 0, true); SDL_AudioSpec audioFormat; memset(&audioFormat, 0, sizeof(audioFormat)); audioFormat.freq = rate; - audioFormat.format = SVidAudioDepth == 16 ? AUDIO_S16SYS : AUDIO_U8; + audioFormat.format = depth == 16 ? AUDIO_S16SYS : AUDIO_U8; audioFormat.channels = channels; Mix_CloseAudio(); @@ -345,7 +349,9 @@ static bool SVidLoadNextFrame() if (SMK_ERR(result) || !SVidLoop) { return false; } - +#ifndef NOSOUND + SVidAudioAdjust = -1; +#endif smk_first(SVidSMK); } @@ -357,10 +363,10 @@ static BYTE* SVidApplyVolume(BYTE* raw, unsigned long rawLen) //BYTE* scaled = DiabloAllocPtr(rawLen); BYTE* scaled = raw; - if (SVidAudioDepth == 16) { + if (SVidAudioAdjust > 0) { for (unsigned long i = 0; i < rawLen / 2; i++) ((Sint16*)scaled)[i] = ADJUST_VOLUME(((Sint16*)raw)[i], 0, gnSoundVolume); - } else { + } else if (SVidAudioAdjust == 0) { for (unsigned long i = 0; i < rawLen; i++) scaled[i] = ADJUST_VOLUME((raw[i] - 128), 0, gnSoundVolume) + 128; } From f4796367526a35874f235f646616f9b934095034 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 16 Jan 2024 09:00:48 +0100 Subject: [PATCH 242/596] bugfix for vanilla (ending movies) - fix graphical glitch in the ending movies --- tools/patcher/DiabloUI/patcher.cpp | 255 +++++++++++++++++++++++++++++ 1 file changed, 255 insertions(+) diff --git a/tools/patcher/DiabloUI/patcher.cpp b/tools/patcher/DiabloUI/patcher.cpp index 725fe968e8e..089bfe00824 100644 --- a/tools/patcher/DiabloUI/patcher.cpp +++ b/tools/patcher/DiabloUI/patcher.cpp @@ -20,6 +20,9 @@ static constexpr int RETURN_ERROR = 101; static constexpr int RETURN_DONE = 100; typedef enum filenames { + FILE_MOVIE_VIC1, + FILE_MOVIE_VIC2, + FILE_MOVIE_VIC3, #if ASSET_MPL == 1 FILE_TOWN_CEL, FILE_TOWN_MIN, @@ -119,6 +122,9 @@ typedef enum filenames { } filenames; static const char* const filesToPatch[NUM_FILENAMES] = { +/*FILE_MOVIE_VIC1*/ "gendata\\DiabVic1.smk", +/*FILE_MOVIE_VIC2*/ "gendata\\DiabVic2.smk", +/*FILE_MOVIE_VIC3*/ "gendata\\DiabVic3.smk", #if ASSET_MPL == 1 /*FILE_TOWN_CEL*/ "Levels\\TownData\\Town.CEL", /*FILE_TOWN_MIN*/ "Levels\\TownData\\Town.MIN", @@ -327,6 +333,249 @@ static BYTE* buildBlkMin(BYTE* minBuf, size_t *minLen, unsigned blockSize) return minBuf; } +static void patchMovie(int fileIndex, BYTE* fileBuf, size_t* fileSize) +{ + uint32_t* lm = (uint32_t*)fileBuf; + + // TODO: validate file-size + switch (fileIndex) { + case FILE_MOVIE_VIC1: + { // patch movie - DiabVic1.smk + lm += 2365112 / 4; + lm[0] = SwapLE32(-550965321); + lm[1] = SwapLE32(-272898787); + lm[2] = SwapLE32(2091106043); + lm[3] = SwapLE32(1596505681); + lm[4] = SwapLE32(2009739156); + lm[5] = SwapLE32(-202827765); + lm[6] = SwapLE32(2104344764); + lm[7] = SwapLE32(-2141622575); + lm[8] = SwapLE32(48038255); + lm[9] = SwapLE32(45358492); + lm[10] = SwapLE32(-1267717305); + lm[11] = SwapLE32(-1587331326); + lm[12] = SwapLE32(-2120218010); + lm[13] = SwapLE32(-2011561816); + lm[14] = SwapLE32(1414846530); + lm[15] = SwapLE32(-1349224483); + lm[16] = SwapLE32(1596506156); + lm[17] = SwapLE32(-1101954983); + lm[18] = SwapLE32(1199431464); + lm[19] = SwapLE32(1367122681); + lm[20] = SwapLE32(-1805702978); + lm[21] = SwapLE32(-545797585); + lm[22] = SwapLE32(1596505681); + lm[23] = SwapLE32(-225513580); + lm[24] = SwapLE32(1005517125); + lm[25] = SwapLE32(-1947920438); + lm[26] = SwapLE32(-1560721934); + lm[27] = SwapLE32(-71413380); + lm[28] = SwapLE32(-112856434); + lm[29] = SwapLE32(-1101955934); + lm[30] = SwapLE32(-1349230808); + lm[31] = SwapLE32(199978722); + lm[32] = SwapLE32(-834474092); + lm[33] = SwapLE32(1232795968); + lm[34] = SwapLE32(1968370609); + lm[35] = SwapLE32(-1751256130); + lm[36] = SwapLE32(26469610); + lm[37] = SwapLE32(-1792990555); + lm[38] = SwapLE32(-1099607468); + lm[39] = SwapLE32(1251410675); + lm[40] = SwapLE32(-136193238); + lm[41] = SwapLE32(2079387026); + lm[42] = SwapLE32(-130195607); + lm[43] = SwapLE32(1596987095); + lm[44] = SwapLE32(-905946117); + lm[45] = SwapLE32(-113243273); + lm[46] = SwapLE32(781362926); + lm[47] = SwapLE32(399126420); + lm[48] = SwapLE32(1173523429); + lm[49] = SwapLE32(-176381191); + lm[50] = SwapLE32(275362381); + lm[51] = SwapLE32(-155288568); + lm[52] = SwapLE32(1439028673); + lm[53] = SwapLE32(-2129603742); + lm[54] = SwapLE32(766280566); + lm[55] = SwapLE32(919806055); + lm[56] = SwapLE32(1681665368); + lm[57] = SwapLE32(-863511906); + lm[58] = SwapLE32(-1957164198); + lm[59] = SwapLE32(-1063860819); + lm[60] = SwapLE32(-883300707); + lm[61] = SwapLE32(-1663365712); + lm[62] = SwapLE32(-107803491); + lm[63] = SwapLE32(706130563); + lm[64] = SwapLE32(-905866675); + lm[65] = SwapLE32(-1308512774); + lm[66] = SwapLE32(1493841248); + lm[67] = SwapLE32(256192880); + lm[68] = SwapLE32(-619848059); + lm[69] = SwapLE32(369285801); + lm[70] = SwapLE32(-876682358); + lm[71] = SwapLE32(334941186); + lm[72] = SwapLE32(2128183385); + lm[73] = SwapLE32(23856562); + } break; + case FILE_MOVIE_VIC2: + { // patch movie - DiabVic2.smk + lm += 2303424 / 4; + lm[0] = SwapLE32(-692176717); + lm[1] = SwapLE32(1924240277); + lm[2] = SwapLE32(-1116350926); + lm[3] = SwapLE32(846226659); + lm[4] = SwapLE32(211556664); + lm[5] = SwapLE32(1836009038); + lm[6] = SwapLE32(1847955435); + lm[7] = SwapLE32(-1153933168); + lm[8] = SwapLE32(-14372439); + lm[9] = SwapLE32(-1352999270); + lm[10] = SwapLE32(2047723429); + lm[11] = SwapLE32(231186652); + lm[12] = SwapLE32(-748630536); + lm[13] = SwapLE32(1183210856); + lm[14] = SwapLE32(-1080806677); + lm[15] = SwapLE32(-1159502474); + lm[16] = SwapLE32(1490301554); + lm[17] = SwapLE32(1666238914); + lm[18] = SwapLE32(-1820121335); + lm[19] = SwapLE32(211594929); + lm[20] = SwapLE32(-2094594482); + lm[21] = SwapLE32(-523648621); + lm[22] = SwapLE32(657173604); + lm[23] = SwapLE32(1540461443); + lm[24] = SwapLE32(1663511471); + lm[25] = SwapLE32(-1676068515); + lm[26] = SwapLE32(654724620); + lm[27] = SwapLE32(-910060669); + lm[28] = SwapLE32(-1047294120); + lm[29] = SwapLE32(1885659337); + lm[30] = SwapLE32(-1676068814); + lm[31] = SwapLE32(76938764); + lm[32] = SwapLE32(1988926659); + lm[33] = SwapLE32(-2121035208); + lm[34] = SwapLE32(162658691); + lm[35] = SwapLE32(1300551711); + lm[36] = SwapLE32(-1315994408); + lm[37] = SwapLE32(-943693268); + lm[38] = SwapLE32(1911569951); + lm[39] = SwapLE32(-598899496); + lm[40] = SwapLE32(-1136785472); + lm[41] = SwapLE32(-130681637); + lm[42] = SwapLE32(-84905981); + lm[43] = SwapLE32(1866660917); + lm[44] = SwapLE32(-1123243555); + lm[45] = SwapLE32(-1214044363); + lm[46] = SwapLE32(1991009510); + lm[47] = SwapLE32(-2094590931); + lm[48] = SwapLE32(-523648621); + lm[49] = SwapLE32(942829668); + lm[50] = SwapLE32(-661056999); + lm[51] = SwapLE32(-663336473); + lm[52] = SwapLE32(-2103178071); + lm[53] = SwapLE32(-810450266); + lm[54] = SwapLE32(-1798627861); + lm[55] = SwapLE32(468686179); + lm[56] = SwapLE32(-510503487); + lm[57] = SwapLE32(1505680763); + lm[58] = SwapLE32(172312093); + lm[59] = SwapLE32(-450712496); + lm[60] = SwapLE32(-284186083); + lm[61] = SwapLE32(124493483); + lm[62] = SwapLE32(2141065680); + lm[63] = SwapLE32(344695419); + lm[64] = SwapLE32(-174581497); + lm[65] = SwapLE32(2096023608); + lm[66] = SwapLE32(-1908604696); + lm[67] = SwapLE32(-1021173752); + lm[68] = SwapLE32(-1211136129); + lm[69] = SwapLE32(-688626406); + lm[70] = SwapLE32(1030122221); + lm[71] = SwapLE32(-1448569291); + lm[72] = SwapLE32(1780845896); + lm[73] = SwapLE32(-810685910); + } break; + case FILE_MOVIE_VIC3: + { // patch movie - DiabVic3.smk + lm += 2313520 / 4; + lm[0] = SwapLE32(1810378268); + lm[1] = SwapLE32(1956082596); + lm[2] = SwapLE32(-1852204306); + lm[3] = SwapLE32(-1528346162); + lm[4] = SwapLE32(-382086541); + lm[5] = SwapLE32(248990172); + lm[6] = SwapLE32(-1442865169); + lm[7] = SwapLE32(1302565187); + lm[8] = SwapLE32(-15115782); + lm[9] = SwapLE32(1349539657); + lm[10] = SwapLE32(-3497991); + lm[11] = SwapLE32(1715994196); + lm[12] = SwapLE32(-94472062); + lm[13] = SwapLE32(-2014741919); + lm[14] = SwapLE32(1392874889); + lm[15] = SwapLE32(-414656584); + lm[16] = SwapLE32(-1658193332); + lm[17] = SwapLE32(1957161267); + lm[18] = SwapLE32(1186702574); + lm[19] = SwapLE32(-1818417350); + lm[20] = SwapLE32(-1528346162); + lm[21] = SwapLE32(1807340147); + lm[22] = SwapLE32(970093476); + lm[23] = SwapLE32(-1658462999); + lm[24] = SwapLE32(593350291); + lm[25] = SwapLE32(1238274973); + lm[26] = SwapLE32(-764173081); + lm[27] = SwapLE32(451843001); + lm[28] = SwapLE32(1316265193); + lm[29] = SwapLE32(-1818417350); + lm[30] = SwapLE32(2028423630); + lm[31] = SwapLE32(1213262382); + lm[32] = SwapLE32(1233196775); + lm[33] = SwapLE32(-466215703); + lm[34] = SwapLE32(14841857); + lm[35] = SwapLE32(1006878780); + lm[36] = SwapLE32(-192136591); + lm[37] = SwapLE32(-2008008564); + lm[38] = SwapLE32(14818371); + lm[39] = SwapLE32(1342160956); + lm[40] = SwapLE32(-2142182884); + lm[41] = SwapLE32(-1934654195); + lm[42] = SwapLE32(859320077); + lm[43] = SwapLE32(384383416); + lm[44] = SwapLE32(-1817907820); + lm[45] = SwapLE32(-764109362); + lm[46] = SwapLE32(-40358983); + lm[47] = SwapLE32(-414593385); + lm[48] = SwapLE32(970093476); + lm[49] = SwapLE32(1316265193); + lm[50] = SwapLE32(145792077); + lm[51] = SwapLE32(-1810424179); + lm[52] = SwapLE32(-183817203); + lm[53] = SwapLE32(689004884); + lm[54] = SwapLE32(-296328173); + lm[55] = SwapLE32(-673137993); + lm[56] = SwapLE32(502011765); + lm[57] = SwapLE32(1689426827); + lm[58] = SwapLE32(-547293725); + lm[59] = SwapLE32(-474683808); + lm[60] = SwapLE32(-1511228563); + lm[61] = SwapLE32(-1515184584); + lm[62] = SwapLE32(-753466767); + lm[63] = SwapLE32(-880436852); + lm[64] = SwapLE32(1545606400); + lm[65] = SwapLE32(316322038); + lm[66] = SwapLE32(-1061779178); + lm[67] = SwapLE32(719126690); + lm[68] = SwapLE32(-1785938886); + lm[69] = SwapLE32(1415292139); + lm[70] = SwapLE32(-191309975); + lm[71] = SwapLE32(644310227); + lm[72] = SwapLE32(-222423811); + lm[73] = SwapLE32(1019295561); + } break; + } +} + static void patchDungeon(int fileIndex, BYTE* fileBuf, size_t* fileSize) { uint16_t* lm = (uint16_t*)fileBuf; @@ -1933,6 +2182,12 @@ static BYTE* patchFile(int index, size_t *dwLen) } switch (index) { + case FILE_MOVIE_VIC1: + case FILE_MOVIE_VIC2: + case FILE_MOVIE_VIC3: + { // patch .SMK + patchMovie(index, buf, dwLen); + } break; #if ASSET_MPL == 1 case FILE_TOWN_CEL: { // patch dMicroCels - TOWN.CEL From baf34af553a4c4ef0da3603ede3caf76695e884a Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 17 Jan 2024 08:52:42 +0100 Subject: [PATCH 243/596] assume valid SMK files if DEBUG_MODE is not set --- 3rdParty/libsmacker/smacker.c | 172 ++++++++++++++++++++++++++++++---- 1 file changed, 152 insertions(+), 20 deletions(-) diff --git a/3rdParty/libsmacker/smacker.c b/3rdParty/libsmacker/smacker.c index 45890c29265..01d450205b8 100644 --- a/3rdParty/libsmacker/smacker.c +++ b/3rdParty/libsmacker/smacker.c @@ -19,13 +19,13 @@ #include #include -/* logging replacements */ #ifdef FULL -#define PrintError(msg) perror(msg); -#define LogErrorMsg(msg) fputs(msg, stderr); -#define LogError(msg, ...) fprintf(stderr, msg, __VA_ARGS__); -#else -#if DEBUG_MODE || DEV_MODE +#undef DEBUG_MODE +#define DEBUG_MODE 1 +#endif + +/* logging replacements */ +#if DEBUG_MODE #define PrintError(msg) perror(msg); #define LogErrorMsg(msg) fputs(msg, stderr); #define LogError(msg, ...) fprintf(stderr, msg, __VA_ARGS__); @@ -33,8 +33,7 @@ #define PrintError(msg) #define LogErrorMsg(msg) #define LogError(msg, ...) -#endif -#endif /* FULL */ +#endif /* DEBUG_MODE */ /* ************************************************************************* */ /* BITSTREAM Structure */ @@ -71,7 +70,9 @@ static int smk_bs_read_1(struct smk_bit_t * const bs) /* don't die when running out of bits, but signal */ if (bs->buffer >= bs->end) { LogErrorMsg("libsmacker::smk_bs_read_1(): ERROR: bitstream exhausted.\n"); +#if DEBUG_MODE return -1; +#endif } /* get next bit and store for return */ @@ -94,13 +95,13 @@ static int smk_bs_read_8(struct smk_bit_t * const bs) { /* null check */ assert(bs); - +#if DEBUG_MODE /* don't die when running out of bits, but signal */ if (bs->buffer + (bs->bit_num > 0) >= bs->end) { LogErrorMsg("libsmacker::smk_bs_read_8(): ERROR: bitstream exhausted.\n"); return -1; } - +#endif if (bs->bit_num) { /* unaligned read */ int ret = *bs->buffer >> bs->bit_num; @@ -135,17 +136,19 @@ static int _smk_huff8_build_rec(struct smk_huff8_t * const t, struct smk_bit_t * int bit, value; assert(t); assert(bs); - +#if DEBUG_MODE /* Make sure we aren't running out of bounds */ if (t->size >= 511) { LogErrorMsg("libsmacker::_smk_huff8_build_rec() - ERROR: size exceeded\n"); return 0; } - +#endif /* Read the next bit */ if ((bit = smk_bs_read_1(bs)) < 0) { LogErrorMsg("libsmacker::_smk_huff8_build_rec() - ERROR: get_bit returned -1\n"); +#if DEBUG_MODE return 0; +#endif } if (bit) { @@ -160,7 +163,9 @@ static int _smk_huff8_build_rec(struct smk_huff8_t * const t, struct smk_bit_t * /* go build the left branch */ if (! _smk_huff8_build_rec(t, bs)) { LogErrorMsg("libsmacker::_smk_huff8_build_rec() - ERROR: failed to build left sub-tree\n"); +#if DEBUG_MODE return 0; +#endif } /* now go back to our current location, and @@ -170,14 +175,18 @@ static int _smk_huff8_build_rec(struct smk_huff8_t * const t, struct smk_bit_t * /* continue building the right side */ if (! _smk_huff8_build_rec(t, bs)) { LogErrorMsg("libsmacker::_smk_huff8_build_rec() - ERROR: failed to build right sub-tree\n"); +#if DEBUG_MODE return 0; +#endif } } else { /* Bit unset signifies a Leaf node. */ /* Attempt to read value */ if ((value = smk_bs_read_8(bs)) < 0) { LogErrorMsg("libsmacker::_smk_huff8_build_rec() - ERROR: get_byte returned -1\n"); +#if DEBUG_MODE return 0; +#endif } /* store to tree */ @@ -200,7 +209,9 @@ static int smk_huff8_build(struct smk_huff8_t * const t, struct smk_bit_t * cons /* Smacker huff trees begin with a set-bit. */ if ((bit = smk_bs_read_1(bs)) < 0) { LogErrorMsg("libsmacker::smk_huff8_build() - ERROR: initial get_bit returned -1\n"); +#if DEBUG_MODE return 0; +#endif } /* OK to fill out the struct now */ @@ -211,7 +222,9 @@ static int smk_huff8_build(struct smk_huff8_t * const t, struct smk_bit_t * cons if (bit) { if (! _smk_huff8_build_rec(t, bs)) { LogErrorMsg("libsmacker::smk_huff8_build() - ERROR: tree build failed\n"); +#if DEBUG_MODE return 0; +#endif } } else t->tree[0] = 0; @@ -219,13 +232,17 @@ static int smk_huff8_build(struct smk_huff8_t * const t, struct smk_bit_t * cons /* huff trees end with an unset-bit */ if ((bit = smk_bs_read_1(bs)) < 0) { LogErrorMsg("libsmacker::smk_huff8_build() - ERROR: final get_bit returned -1\n"); +#if DEBUG_MODE return 0; +#endif } /* a 0 is expected here, a 1 generally indicates a problem! */ if (bit) { LogErrorMsg("libsmacker::smk_huff8_build() - ERROR: final get_bit returned 1\n"); +#if DEBUG_MODE return 0; +#endif } return 1; @@ -243,7 +260,9 @@ static int smk_huff8_lookup(const struct smk_huff8_t * const t, struct smk_bit_t while (t->tree[index] & SMK_HUFF8_BRANCH) { if ((bit = smk_bs_read_1(bs)) < 0) { LogErrorMsg("libsmacker::smk_huff8_lookup() - ERROR: get_bit returned -1\n"); +#if DEBUG_MODE return -1; +#endif } if (bit) { @@ -278,7 +297,11 @@ struct smk_huff16_t { /* HUFF16 Functions */ /* ************************************************************************* */ /* Recursive sub-func for building a tree into an array. */ +#if DEBUG_MODE static int _smk_huff16_build_rec(struct smk_huff16_t * const t, struct smk_bit_t * const bs, const struct smk_huff8_t * const low8, const struct smk_huff8_t * const hi8, const size_t limit) +#else +static int _smk_huff16_build_rec(struct smk_huff16_t * const t, struct smk_bit_t * const bs, const struct smk_huff8_t * const low8, const struct smk_huff8_t * const hi8) +#endif { int bit, value; assert(t); @@ -286,16 +309,19 @@ static int _smk_huff16_build_rec(struct smk_huff16_t * const t, struct smk_bit_t assert(low8); assert(hi8); +#if DEBUG_MODE /* Make sure we aren't running out of bounds */ if (t->size >= limit) { LogErrorMsg("libsmacker::_smk_huff16_build_rec() - ERROR: size exceeded\n"); return 0; } - +#endif /* Read the first bit */ if ((bit = smk_bs_read_1(bs)) < 0) { LogErrorMsg("libsmacker::_smk_huff16_build_rec() - ERROR: get_bit returned -1\n"); +#if DEBUG_MODE return 0; +#endif } if (bit) { @@ -304,26 +330,36 @@ static int _smk_huff16_build_rec(struct smk_huff16_t * const t, struct smk_bit_t value = t->size ++; /* go build the left branch */ +#if DEBUG_MODE if (! _smk_huff16_build_rec(t, bs, low8, hi8, limit)) { LogErrorMsg("libsmacker::_smk_huff16_build_rec() - ERROR: failed to build left sub-tree\n"); return 0; } +#else + _smk_huff16_build_rec(t, bs, low8, hi8); +#endif /* now go back to our current location, and mark our location as a "jump" */ t->tree[value] = SMK_HUFF16_BRANCH | t->size; /* continue building the right side */ +#if DEBUG_MODE if (! _smk_huff16_build_rec(t, bs, low8, hi8, limit)) { LogErrorMsg("libsmacker::_smk_huff16_build_rec() - ERROR: failed to build right sub-tree\n"); return 0; } +#else + _smk_huff16_build_rec(t, bs, low8, hi8); +#endif } else { /* Bit unset signifies a Leaf node. */ /* Attempt to read LOW value */ if ((value = smk_huff8_lookup(low8, bs)) < 0) { LogErrorMsg("libsmacker::_smk_huff16_build_rec() - ERROR: get LOW value returned -1\n"); +#if DEBUG_MODE return 0; +#endif } t->tree[t->size] = value; @@ -331,7 +367,9 @@ static int _smk_huff16_build_rec(struct smk_huff16_t * const t, struct smk_bit_t /* now read HIGH value */ if ((value = smk_huff8_lookup(hi8, bs)) < 0) { LogErrorMsg("libsmacker::_smk_huff16_build_rec() - ERROR: get HIGH value returned -1\n"); +#if DEBUG_MODE return 0; +#endif } /* Looks OK: we got low and hi values. Return a new LEAF */ @@ -365,7 +403,9 @@ static int smk_huff16_build(struct smk_huff16_t * const t, struct smk_bit_t * co /* Smacker huff trees begin with a set-bit. */ if ((bit = smk_bs_read_1(bs)) < 0) { LogErrorMsg("libsmacker::smk_huff16_build() - ERROR: initial get_bit returned -1\n"); +#if DEBUG_MODE return 0; +#endif } t->size = 0; @@ -376,20 +416,26 @@ static int smk_huff16_build(struct smk_huff16_t * const t, struct smk_bit_t * co /* build low-8-bits tree */ if (! smk_huff8_build(&low8, bs)) { LogErrorMsg("libsmacker::smk_huff16_build() - ERROR: failed to build LOW tree\n"); +#if DEBUG_MODE return 0; +#endif } /* build hi-8-bits tree */ if (! smk_huff8_build(&hi8, bs)) { LogErrorMsg("libsmacker::smk_huff16_build() - ERROR: failed to build HIGH tree\n"); +#if DEBUG_MODE return 0; +#endif } /* Init the escape code cache. */ for (i = 0; i < 3; i ++) { if ((value = smk_bs_read_8(bs)) < 0) { LogError("libsmacker::smk_huff16_build() - ERROR: get LOW value for cache %d returned -1\n", i); +#if DEBUG_MODE return 0; +#endif } t->cache[i] = value; @@ -397,18 +443,20 @@ static int smk_huff16_build(struct smk_huff16_t * const t, struct smk_bit_t * co /* now read HIGH value */ if ((value = smk_bs_read_8(bs)) < 0) { LogError("libsmacker::smk_huff16_build() - ERROR: get HIGH value for cache %d returned -1\n", i); +#if DEBUG_MODE return 0; +#endif } t->cache[i] |= (value << 8); } - +#if DEBUG_MODE /* Everything looks OK so far. Time to malloc structure. */ if (alloc_size < 12 || alloc_size % 4) { LogError("libsmacker::smk_huff16_build() - ERROR: illegal value %u for alloc_size\n", alloc_size); return 0; } - +#endif limit = (alloc_size - 12) / 4; if ((t->tree = malloc(limit * sizeof(unsigned int))) == NULL) { @@ -417,6 +465,7 @@ static int smk_huff16_build(struct smk_huff16_t * const t, struct smk_bit_t * co } /* Finally, call recursive function to retrieve the Bigtree. */ +#if DEBUG_MODE if (! _smk_huff16_build_rec(t, bs, &low8, &hi8, limit)) { LogErrorMsg("libsmacker::smk_huff16_build() - ERROR: failed to build huff16 tree\n"); goto error; @@ -427,6 +476,9 @@ static int smk_huff16_build(struct smk_huff16_t * const t, struct smk_bit_t * co LogErrorMsg("libsmacker::smk_huff16_build() - ERROR: failed to completely decode huff16 tree\n"); goto error; } +#else + _smk_huff16_build_rec(t, bs, &low8, &hi8); +#endif } else { if ((t->tree = malloc(sizeof(unsigned int))) == NULL) { PrintError("libsmacker::smk_huff16_build() - ERROR: failed to malloc() huff16 tree"); @@ -440,20 +492,26 @@ static int smk_huff16_build(struct smk_huff16_t * const t, struct smk_bit_t * co /* Check final end tag. */ if ((bit = smk_bs_read_1(bs)) < 0) { LogErrorMsg("libsmacker::smk_huff16_build() - ERROR: final get_bit returned -1\n"); +#if DEBUG_MODE goto error; +#endif } /* a 0 is expected here, a 1 generally indicates a problem! */ if (bit) { LogErrorMsg("libsmacker::smk_huff16_build() - ERROR: final get_bit returned 1\n"); +#if DEBUG_MODE goto error; +#endif } return 1; +#if DEBUG_MODE error: free(t->tree); t->tree = NULL; return 0; +#endif } /* Look up a 16-bit value from a large huff tree. @@ -469,7 +527,9 @@ static int smk_huff16_lookup(struct smk_huff16_t * const t, struct smk_bit_t * c while (t->tree[index] & SMK_HUFF16_BRANCH) { if ((bit = smk_bs_read_1(bs)) < 0) { LogErrorMsg("libsmacker::smk_huff16_lookup() - ERROR: get_bit returned -1\n"); +#if DEBUG_MODE return -1; +#endif } if (bit) { @@ -643,7 +703,9 @@ static char smk_read_memory(void * buf, const unsigned long size, unsigned char { if (size > *p_size) { LogError("libsmacker::smk_read_memory(buf,%lu,p,%lu) - ERROR: Short read\n", (unsigned long)size, (unsigned long)*p_size); +#if DEBUG_MODE return -1; +#endif } memcpy(buf, *p, size); @@ -656,8 +718,11 @@ static char smk_read_in_memory(unsigned char ** buf, const unsigned long size, u { if (size > *p_size) { LogError("libsmacker::smk_read_in_memory(buf,%lu,p,%lu) - ERROR: Short read\n", (unsigned long)size, (unsigned long)*p_size); +#if DEBUG_MODE return -1; +#endif } + *buf = *p; *p += size; *p_size -= size; @@ -684,7 +749,7 @@ static char smk_read_in_memory(unsigned char ** buf, const unsigned long size, u goto error; \ } \ } -#else +#elif DEBUG_MODE #define smk_read(ret,n) \ { \ { \ @@ -696,8 +761,16 @@ static char smk_read_in_memory(unsigned char ** buf, const unsigned long size, u goto error; \ } \ } +#else +#define smk_read(ret,n) \ +{ \ + { \ + r = (smk_read_memory(ret,n,&fp.ram,&size)); \ + } \ +} #endif #ifndef FULL_ORIG +#if DEBUG_MODE #define smk_read_in(ret, n) \ { \ { \ @@ -709,7 +782,15 @@ static char smk_read_in_memory(unsigned char ** buf, const unsigned long size, u goto error; \ } \ } -#endif +#else +#define smk_read_in(ret, n) \ +{ \ + { \ + r = (smk_read_in_memory(&ret,n,&fp.ram,&size)); \ + } \ +} +#endif // DEBUG_MODE +#endif // !FULL_ORIG /* Calls smk_read, but returns a ul */ #define smk_read_ul(p) \ { \ @@ -754,12 +835,14 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned if (buf[0] != 'S' || buf[1] != 'M' || buf[2] != 'K') { LogError("libsmacker::smk_open_generic - ERROR: invalid SMKn signature (got: %s)\n", buf); +#if DEBUG_MODE goto error; +#endif } /* Read .smk file version */ //smk_read(buf, 1); - +#if DEBUG_MODE if (buf[3] != '2' && buf[3] != '4') { LogError("libsmacker::smk_open_generic - Warning: invalid SMK version %c (expected: 2 or 4)\n", buf[3]); @@ -771,6 +854,7 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned LogError("\tProcessing will continue as type %c\n", buf[3]); } +#endif s->video.v = buf[3]; /* width, height, total num frames */ @@ -892,7 +976,9 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned for (temp_u = 0; temp_u < 4; temp_u ++) { if (! smk_huff16_build(&s->video.tree[temp_u], &bs, s->video.tree_size[temp_u])) { LogError("libsmacker::smk_open_generic - ERROR: failed to create huff16 tree %lu\n", temp_u); +#if DEBUG_MODE goto error; +#endif } } @@ -939,10 +1025,12 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned #endif return s; +#if DEBUG_MODE error: smk_free(hufftree_chunk); smk_close(s); return NULL; +#endif } /* open an smk (from a memory buffer) */ @@ -1360,7 +1448,9 @@ static char smk_render_palette(struct smk_video_t * s, unsigned char * p, unsign /* check for overflow condition */ if (i + count > 256) { LogError("libsmacker::palette_render(s,p,size) - ERROR: overflow, 0x80 attempt to skip %d entries from %d\n", count, i); +#if DEBUG_MODE goto error; +#endif } /* finally: advance the index. */ @@ -1372,7 +1462,9 @@ static char smk_render_palette(struct smk_video_t * s, unsigned char * p, unsign to the next entries of the new palette. */ if (size < 2) { LogErrorMsg("libsmacker::palette_render(s,p,size) - ERROR: 0x40 ran out of bytes for copy\n"); +#if DEBUG_MODE goto error; +#endif } /* pick "count" items to copy */ @@ -1387,7 +1479,9 @@ static char smk_render_palette(struct smk_video_t * s, unsigned char * p, unsign /* overflow: see if we write/read beyond 256colors, or overwrite own palette */ if (i + count > 256 || src + count > 256) { // condition fixed to prevent artifacts in the final video LogError("libsmacker::palette_render(s,p,size) - ERROR: overflow, 0x40 attempt to copy %d entries from %d to %d\n", count, src, i); +#if DEBUG_MODE goto error; +#endif } /* OK! Copy the color-palette entries. */ @@ -1398,13 +1492,17 @@ static char smk_render_palette(struct smk_video_t * s, unsigned char * p, unsign Direct-set the next 3 bytes for palette index */ if (size < 3) { LogError("libsmacker::palette_render - ERROR: 0x3F ran out of bytes for copy, size=%lu\n", size); +#if DEBUG_MODE goto error; +#endif } for (count = 0; count < 3; count ++) { if (*p > 0x3F) { LogError("libsmacker::palette_render - ERROR: palette index exceeds 0x3F (entry [%u][%u])\n", i, count); +#if DEBUG_MODE goto error; +#endif } s->palette[i][count] = palmap[*p]; @@ -1418,14 +1516,18 @@ static char smk_render_palette(struct smk_video_t * s, unsigned char * p, unsign if (i < 256) { LogError("libsmacker::palette_render - ERROR: did not completely fill palette (idx=%u)\n", i); +#if DEBUG_MODE goto error; +#endif } return 0; +#if DEBUG_MODE error: /* Error, return -1 The new palette probably has errors but is preferrable to a black screen */ return -1; +#endif } static char smk_render_video(struct smk_video_t * s, unsigned char * p, unsigned int size) @@ -1468,7 +1570,9 @@ static char smk_render_video(struct smk_video_t * s, unsigned char * p, unsigned while (row < s->h) { if ((unpack = smk_huff16_lookup(&s->tree[SMK_TREE_TYPE], &bs)) < 0) { LogErrorMsg("libsmacker::smk_render_video() - ERROR: failed to lookup from TYPE tree.\n"); +#if DEBUG_MODE return -1; +#endif } type = ((unpack & 0x0003)); @@ -1496,7 +1600,9 @@ static char smk_render_video(struct smk_video_t * s, unsigned char * p, unsigned case 0: if ((unpack = smk_huff16_lookup(&s->tree[SMK_TREE_MCLR], &bs)) < 0) { LogErrorMsg("libsmacker::smk_render_video() - ERROR: failed to lookup from MCLR tree.\n"); +#if DEBUG_MODE return -1; +#endif } s1 = (unpack & 0xFF00) >> 8; @@ -1504,7 +1610,9 @@ static char smk_render_video(struct smk_video_t * s, unsigned char * p, unsigned if ((unpack = smk_huff16_lookup(&s->tree[SMK_TREE_MMAP], &bs)) < 0) { LogErrorMsg("libsmacker::smk_render_video() - ERROR: failed to lookup from MMAP tree.\n"); +#if DEBUG_MODE return -1; +#endif } temp = 0x01; @@ -1528,7 +1636,9 @@ static char smk_render_video(struct smk_video_t * s, unsigned char * p, unsigned for (k = 0; k < 4; k ++) { if ((unpack = smk_huff16_lookup(&s->tree[SMK_TREE_FULL], &bs)) < 0) { LogErrorMsg("libsmacker::smk_render_video() - ERROR: failed to lookup from FULL tree.\n"); +#if DEBUG_MODE return -1; +#endif } t[skip + 3] = ((unpack & 0xFF00) >> 8); @@ -1536,7 +1646,9 @@ static char smk_render_video(struct smk_video_t * s, unsigned char * p, unsigned if ((unpack = smk_huff16_lookup(&s->tree[SMK_TREE_FULL], &bs)) < 0) { LogErrorMsg("libsmacker::smk_render_video() - ERROR: failed to lookup from FULL tree.\n"); +#if DEBUG_MODE return -1; +#endif } t[skip + 1] = ((unpack & 0xFF00) >> 8); @@ -1574,7 +1686,9 @@ static char smk_render_video(struct smk_video_t * s, unsigned char * p, unsigned for (k = 0; k < 2; k ++) { if ((unpack = smk_huff16_lookup(&s->tree[SMK_TREE_FULL], &bs)) < 0) { LogErrorMsg("libsmacker::smk_render_video() - ERROR: failed to lookup from FULL tree.\n"); +#if DEBUG_MODE return -1; +#endif } for (i = 0; i < 2; i ++) { @@ -1590,7 +1704,9 @@ static char smk_render_video(struct smk_video_t * s, unsigned char * p, unsigned for (k = 0; k < 2; k ++) { if ((unpack = smk_huff16_lookup(&s->tree[SMK_TREE_FULL], &bs)) < 0) { LogErrorMsg("libsmacker::smk_render_video() - ERROR: failed to lookup from FULL tree.\n"); +#if DEBUG_MODE return -1; +#endif } t[skip + 3] = ((unpack & 0xFF00) >> 8); @@ -1600,7 +1716,9 @@ static char smk_render_video(struct smk_video_t * s, unsigned char * p, unsigned if ((unpack = smk_huff16_lookup(&s->tree[SMK_TREE_FULL], &bs)) < 0) { LogErrorMsg("libsmacker::smk_render_video() - ERROR: failed to lookup from FULL tree.\n"); +#if DEBUG_MODE return -1; +#endif } t[skip + 1] = ((unpack & 0xFF00) >> 8); @@ -1655,7 +1773,9 @@ static char smk_render_audio(struct smk_audio_t * s, unsigned char * p, unsigned /* need at least 4 bytes to process */ if (size < 4) { LogErrorMsg("libsmacker::smk_render_audio() - ERROR: need 4 bytes to get unpacked output buffer size.\n"); +#if DEBUG_MODE goto error; +#endif } /* chunk is compressed (huff-compressed dpcm), retrieve unpacked buffer size */ @@ -1839,8 +1959,10 @@ static char smk_render_audio(struct smk_audio_t * s, unsigned char * p, unsigned } return 0; +#if DEBUG_MODE error: return -1; +#endif } /* "Renders" (unpacks) the frame at cur_frame @@ -1855,7 +1977,9 @@ static char smk_render(smk s) /* Retrieve current chunk_size for this frame. */ if (!(i = s->chunk_size[s->cur_frame])) { LogError("libsmacker::smk_render(s) - Warning: frame %lu: chunk_size is 0.\n", s->cur_frame); +#if DEBUG_MODE goto error; +#endif } #ifdef FULL @@ -1883,7 +2007,9 @@ static char smk_render(smk s) /* Just point buffer at the right place */ if (!s->source.chunk_data[s->cur_frame]) { LogError("libsmacker::smk_render(s) - ERROR: frame %lu: memory chunk is a NULL pointer.\n", s->cur_frame); +#if DEBUG_MODE goto error; +#endif } buffer = s->source.chunk_data[s->cur_frame]; @@ -1898,7 +2024,9 @@ static char smk_render(smk s) /* need at least 1 byte to process */ if (!i) { LogError("libsmacker::smk_render(s) - ERROR: frame %lu: insufficient data for a palette rec.\n", s->cur_frame); +#if DEBUG_MODE goto error; +#endif } /* Byte 1 in block, times 4, tells how many @@ -1919,7 +2047,9 @@ static char smk_render(smk s) /* need at least 4 byte to process */ if (i < 4) { LogError("libsmacker::smk_render(s) - ERROR: frame %lu: insufficient data for audio[%u] rec.\n", s->cur_frame, track); +#if DEBUG_MODE goto error; +#endif } /* First 4 bytes in block tell how many @@ -1943,7 +2073,9 @@ static char smk_render(smk s) if (s->video.enable) { if (smk_render_video(&(s->video), p, i) < 0) { LogError("libsmacker::smk_render(s) - ERROR: frame %lu: failed to render video.\n", s->cur_frame); +#if DEBUG_MODE goto error; +#endif } } @@ -1955,16 +2087,16 @@ static char smk_render(smk s) #endif return 0; +#if DEBUG_MODE error: -#ifdef FULL if (s->mode == SMK_MODE_DISK) { /* Remember that buffer we allocated? Trash it */ smk_free(buffer); } -#endif return -1; +#endif } /* rewind to first frame and unpack */ From 6918b0469f7b3f7cfa656d3cb68b3ff071aabe61 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 17 Jan 2024 11:26:35 +0100 Subject: [PATCH 244/596] smacker optimizations I. - aligned read in smk_bs_read_8 is rare -> no need for the extra path --- 3rdParty/libsmacker/smacker.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/3rdParty/libsmacker/smacker.c b/3rdParty/libsmacker/smacker.c index 01d450205b8..0397f794d55 100644 --- a/3rdParty/libsmacker/smacker.c +++ b/3rdParty/libsmacker/smacker.c @@ -102,15 +102,19 @@ static int smk_bs_read_8(struct smk_bit_t * const bs) return -1; } #endif +#ifdef FULL if (bs->bit_num) { +#endif /* unaligned read */ int ret = *bs->buffer >> bs->bit_num; bs->buffer ++; return ret | (*bs->buffer << (8 - bs->bit_num) & 0xFF); +#if FULL } /* aligned read */ return *bs->buffer++; +#endif } /* ************************************************************************* */ From 03e4ff20b8a662092ce3bbc3a51ff3f21f0e8549 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 17 Jan 2024 11:34:41 +0100 Subject: [PATCH 245/596] comment out the remaining use of smk_t.mode --- 3rdParty/libsmacker/smacker.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/3rdParty/libsmacker/smacker.c b/3rdParty/libsmacker/smacker.c index 0397f794d55..95c3b604977 100644 --- a/3rdParty/libsmacker/smacker.c +++ b/3rdParty/libsmacker/smacker.c @@ -575,9 +575,10 @@ static int smk_huff16_lookup(struct smk_huff16_t * const t, struct smk_bit_t * c struct smk_t { /* meta-info */ +#ifdef FULL /* file mode: see flags, smacker.h */ unsigned char mode; - +#endif /* microsec per frame - stored as a double to handle scaling (large positive millisec / frame values may overflow a ul) */ double usf; @@ -990,12 +991,12 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned smk_free(hufftree_chunk); /* Go ahead and malloc storage for the video frame */ smk_malloc(s->video.frame, s->video.w * s->video.h); +#ifdef FULL /* final processing: depending on ProcessMode, handle what to do with rest of file data */ s->mode = process_mode; /* Handle the rest of the data. For MODE_MEMORY, read the chunks and store */ -#ifdef FULL if (s->mode == SMK_MODE_MEMORY) { #endif smk_malloc(s->source.chunk_data, (s->f + s->ring_frame) * sizeof(unsigned char *)); From d8d0fc051745de5afa872fe507e2e050804440e2 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 17 Jan 2024 11:47:09 +0100 Subject: [PATCH 246/596] smacker optimizations II. - reduce the number of locals in smk_render_video --- 3rdParty/libsmacker/smacker.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/3rdParty/libsmacker/smacker.c b/3rdParty/libsmacker/smacker.c index 95c3b604977..5cb17bd1752 100644 --- a/3rdParty/libsmacker/smacker.c +++ b/3rdParty/libsmacker/smacker.c @@ -1539,7 +1539,9 @@ static char smk_render_video(struct smk_video_t * s, unsigned char * p, unsigned { unsigned char * t = s->frame; unsigned char s1, s2; +#ifdef FULL unsigned short temp; +#endif unsigned long i, j, k, row, col, skip; /* used for video decoding */ struct smk_bit_t bs; @@ -1619,17 +1621,26 @@ static char smk_render_video(struct smk_video_t * s, unsigned char * p, unsigned return -1; #endif } - +#ifdef FULL temp = 0x01; - +#endif for (k = 0; k < 4; k ++) { for (i = 0; i < 4; i ++) { +#ifdef FULL if (unpack & temp) t[skip + i] = s1; else t[skip + i] = s2; temp = temp << 1; +#else + if (unpack & 0x01) + t[skip + i] = s1; + else + t[skip + i] = s2; + + unpack = (unsigned)unpack >> 1; +#endif } skip += s->w; From 9d8fa32bfda40a6e933c063ceccb0f8cfafcf3a2 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 17 Jan 2024 11:56:33 +0100 Subject: [PATCH 247/596] smacker optimizations III. - reduce the number of memset calls in smk_render_video --- 3rdParty/libsmacker/smacker.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/3rdParty/libsmacker/smacker.c b/3rdParty/libsmacker/smacker.c index 5cb17bd1752..f056938738c 100644 --- a/3rdParty/libsmacker/smacker.c +++ b/3rdParty/libsmacker/smacker.c @@ -1688,7 +1688,8 @@ static char smk_render_video(struct smk_video_t * s, unsigned char * p, unsigned } */ break; - case 3: /* SOLID BLOCK */ + case 3: /* SOLID BLOCK */ { +#ifdef FULL memset(&t[skip], typedata, 4); skip += s->w; memset(&t[skip], typedata, 4); @@ -1696,7 +1697,18 @@ static char smk_render_video(struct smk_video_t * s, unsigned char * p, unsigned memset(&t[skip], typedata, 4); skip += s->w; memset(&t[skip], typedata, 4); - break; +#else + uint32_t value; + memset(&value, typedata, 4); + *(uint32_t*)&t[skip] = value; + skip += s->w; + *(uint32_t*)&t[skip] = value; + skip += s->w; + *(uint32_t*)&t[skip] = value; + skip += s->w; + *(uint32_t*)&t[skip] = value; +#endif + } break; case 4: /* V4 DOUBLE BLOCK */ for (k = 0; k < 2; k ++) { From e99983e053b0ecf383d00eed1b18a7e08f0da73f Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 17 Jan 2024 12:01:06 +0100 Subject: [PATCH 248/596] smacker optimizations IV. - calculate the number of total_frames (f + ring_frame) only once --- 3rdParty/libsmacker/smacker.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/3rdParty/libsmacker/smacker.c b/3rdParty/libsmacker/smacker.c index f056938738c..e047aedd7ae 100644 --- a/3rdParty/libsmacker/smacker.c +++ b/3rdParty/libsmacker/smacker.c @@ -582,9 +582,12 @@ struct smk_t { /* microsec per frame - stored as a double to handle scaling (large positive millisec / frame values may overflow a ul) */ double usf; - +#ifdef FULL /* total frames */ unsigned long f; +#else + unsigned long total_frames; /* f + ring_frame */ +#endif /* does file have a ring frame? (in other words, does file loop?) */ unsigned char ring_frame; @@ -865,7 +868,11 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned /* width, height, total num frames */ smk_read_ul(s->video.w); smk_read_ul(s->video.h); +#ifdef FULL smk_read_ul(s->f); +#else + smk_read_ul(s->total_frames); +#endif /* frames per second calculation */ smk_read_ul(temp_u); temp_l = (int)temp_u; @@ -886,11 +893,10 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned Y scale / Y interlace go in the Video flags. The user should scale appropriately. */ smk_read_ul(temp_u); - +#ifdef FULL if (temp_u & 0x01) s->ring_frame = 1; -#ifdef FULL if (temp_u & 0x02) s->video.y_scale_mode = SMK_FLAG_Y_DOUBLE; @@ -900,6 +906,11 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned s->video.y_scale_mode = SMK_FLAG_Y_INTERLACE; } +#else + if (temp_u & 0x01) { + s->ring_frame = 1; + s->total_frames++; + } #endif /* Max buffer size for each audio track - used to pre-allocate buffers */ for (temp_l = 0; temp_l < 7; temp_l ++) @@ -945,10 +956,15 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned /* FrameSizes and Keyframe marker are stored together. */ #ifdef FULL smk_malloc(s->keyframe, (s->f + s->ring_frame)); -#endif + smk_malloc(s->chunk_size, (s->f + s->ring_frame) * sizeof(unsigned long)); for (temp_u = 0; temp_u < (s->f + s->ring_frame); temp_u ++) { +#else + smk_malloc(s->chunk_size, s->total_frames * sizeof(unsigned long)); + + for (temp_u = 0; temp_u < s->total_frames; temp_u ++) { +#endif smk_read_ul(s->chunk_size[temp_u]); #ifdef FULL @@ -967,7 +983,7 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned for (temp_u = 0; temp_u < (s->f + s->ring_frame); temp_u ++) smk_read(&s->frame_type[temp_u], 1); #else - smk_read_in(s->frame_type, (s->f + s->ring_frame)); + smk_read_in(s->frame_type, s->total_frames); #endif /* HuffmanTrees We know the sizes already: read and assemble into @@ -998,8 +1014,10 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned /* Handle the rest of the data. For MODE_MEMORY, read the chunks and store */ if (s->mode == SMK_MODE_MEMORY) { -#endif smk_malloc(s->source.chunk_data, (s->f + s->ring_frame) * sizeof(unsigned char *)); +#else + smk_malloc(s->source.chunk_data, s->total_frames * sizeof(unsigned char *)); +#endif #ifdef FULL_ORIG for (temp_u = 0; temp_u < (s->f + s->ring_frame); temp_u ++) { @@ -1007,7 +1025,7 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned smk_read(s->source.chunk_data[temp_u], s->chunk_size[temp_u]); } #else - for (temp_u = 0; temp_u < (s->f + s->ring_frame); temp_u ++) { + for (temp_u = 0; temp_u < s->total_frames; temp_u ++) { smk_read_in(s->source.chunk_data[temp_u], s->chunk_size[temp_u]); } #endif @@ -2204,7 +2222,7 @@ char smk_next(smk s) assert(s); - if (s->cur_frame + 1 < (s->f + s->ring_frame)) { + if (s->cur_frame + 1 < s->total_frames) { s->cur_frame ++; result = SMK_MORE; From accf170738c34a41942e94f60a54dbbb883a269a Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 17 Jan 2024 12:15:11 +0100 Subject: [PATCH 249/596] disable support for SMKv4 --- 3rdParty/libsmacker/smacker.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/3rdParty/libsmacker/smacker.c b/3rdParty/libsmacker/smacker.c index e047aedd7ae..19195f1e6cb 100644 --- a/3rdParty/libsmacker/smacker.c +++ b/3rdParty/libsmacker/smacker.c @@ -1569,7 +1569,9 @@ static char smk_render_video(struct smk_video_t * s, unsigned char * p, unsigned unsigned char type; unsigned char blocklen; unsigned char typedata; +#ifdef FULL_V4 char bit; +#endif const unsigned short sizetable[64] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, @@ -1603,7 +1605,7 @@ static char smk_render_video(struct smk_video_t * s, unsigned char * p, unsigned type = ((unpack & 0x0003)); blocklen = ((unpack & 0x00FC) >> 2); typedata = ((unpack & 0xFF00) >> 8); - +#ifdef FULL_V4 /* support for v4 full-blocks */ if (type == 1 && s->v == '4') { bit = smk_bs_read_1(&bs); @@ -1617,7 +1619,7 @@ static char smk_render_video(struct smk_video_t * s, unsigned char * p, unsigned type = 5; } } - +#endif for (j = 0; (j < sizetable[blocklen]) && (row < s->h); j ++) { skip = (row * s->w) + col; @@ -1727,7 +1729,7 @@ static char smk_render_video(struct smk_video_t * s, unsigned char * p, unsigned *(uint32_t*)&t[skip] = value; #endif } break; - +#ifdef FULL_V4 case 4: /* V4 DOUBLE BLOCK */ for (k = 0; k < 2; k ++) { if ((unpack = smk_huff16_lookup(&s->tree[SMK_TREE_FULL], &bs)) < 0) { @@ -1775,6 +1777,7 @@ static char smk_render_video(struct smk_video_t * s, unsigned char * p, unsigned } break; +#endif } col += 4; From 80a9891504a3d56925cca03499022008ac0813e7 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 17 Jan 2024 12:30:33 +0100 Subject: [PATCH 250/596] fix smacker in debug mode --- 3rdParty/libsmacker/smacker.c | 1 + 1 file changed, 1 insertion(+) diff --git a/3rdParty/libsmacker/smacker.c b/3rdParty/libsmacker/smacker.c index 19195f1e6cb..01ad30b4ab2 100644 --- a/3rdParty/libsmacker/smacker.c +++ b/3rdParty/libsmacker/smacker.c @@ -836,6 +836,7 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned return NULL; } #else + s = NULL; smk_malloc(s, sizeof(struct smk_t)); #endif /* Check for a valid signature */ From d0efe32360667d0c30db43787a4af3b27a459132 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 17 Jan 2024 12:32:24 +0100 Subject: [PATCH 251/596] smacker optimizations V. - eliminate pointless complexity on little-endian systems --- 3rdParty/libsmacker/smacker.c | 48 ++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/3rdParty/libsmacker/smacker.c b/3rdParty/libsmacker/smacker.c index 01ad30b4ab2..e3e2a0c3ef5 100644 --- a/3rdParty/libsmacker/smacker.c +++ b/3rdParty/libsmacker/smacker.c @@ -19,9 +19,23 @@ #include #include -#ifdef FULL -#undef DEBUG_MODE -#define DEBUG_MODE 1 +/* endianness */ +#if !defined(_WIN32) +#include +#endif +#ifndef __BIG_ENDIAN__ +#define smk_swap_le16(X) (X) +#define smk_swap_le32(X) (X) +#else +static uint16_t smk_swap_le16(uint16_t val) +{ + return (val << 8) | (val >> 8); +} +static uint32_t smk_swap_le32(uint32_t val) +{ + val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF); + return (val << 16) | (val >> 16); +} #endif /* logging replacements */ @@ -800,6 +814,7 @@ static char smk_read_in_memory(unsigned char ** buf, const unsigned long size, u #endif // DEBUG_MODE #endif // !FULL_ORIG /* Calls smk_read, but returns a ul */ +#ifdef FULL #define smk_read_ul(p) \ { \ smk_read(buf,4); \ @@ -808,6 +823,13 @@ static char smk_read_in_memory(unsigned char ** buf, const unsigned long size, u ((unsigned long) buf[1] << 8) | \ ((unsigned long) buf[0]); \ } +#else +#define smk_read_ul(p) \ +{ \ + smk_read(buf,4); \ + p = smk_swap_le32(*(uint32_t*)&buf[0]); \ +} +#endif /* PUBLIC FUNCTIONS */ /* open an smk (from a generic Source) */ @@ -1677,19 +1699,24 @@ static char smk_render_video(struct smk_video_t * s, unsigned char * p, unsigned return -1; #endif } - +#ifdef FULL t[skip + 3] = ((unpack & 0xFF00) >> 8); t[skip + 2] = (unpack & 0x00FF); - +#else + *(uint16_t*)&t[skip + 2] = smk_swap_le16(unpack); +#endif if ((unpack = smk_huff16_lookup(&s->tree[SMK_TREE_FULL], &bs)) < 0) { LogErrorMsg("libsmacker::smk_render_video() - ERROR: failed to lookup from FULL tree.\n"); #if DEBUG_MODE return -1; #endif } - +#ifdef FULL t[skip + 1] = ((unpack & 0xFF00) >> 8); t[skip] = (unpack & 0x00FF); +#else + *(uint16_t*)&t[skip] = smk_swap_le16(unpack); +#endif skip += s->w; } @@ -1829,10 +1856,14 @@ static char smk_render_audio(struct smk_audio_t * s, unsigned char * p, unsigned } /* chunk is compressed (huff-compressed dpcm), retrieve unpacked buffer size */ +#ifdef FULL s->buffer_size = ((unsigned int) p[3] << 24) | ((unsigned int) p[2] << 16) | ((unsigned int) p[1] << 8) | ((unsigned int) p[0]); +#else + s->buffer_size = smk_swap_le32(*(uint32_t*)&p[0]); +#endif p += 4; size -= 4; /* Compressed audio: must unpack here */ @@ -2104,11 +2135,14 @@ static char smk_render(smk s) /* First 4 bytes in block tell how many subsequent bytes are present */ +#ifdef FULL size = (((unsigned int) p[3] << 24) | ((unsigned int) p[2] << 16) | ((unsigned int) p[1] << 8) | ((unsigned int) p[0])); - +#else + size = smk_swap_le32(*(uint32_t*)&p[0]); +#endif /* If audio rendering enabled, kick this off for decode. */ if (s->audio[track].enable) smk_render_audio(&s->audio[track], p + 4, size - 4); From 168329e543d1b8ea8d101829ba06f9f21dff2040 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 18 Jan 2024 12:19:10 +0100 Subject: [PATCH 252/596] use LogError/LogErrorMsg/PrintError defines in smacker.c --- 3rdParty/libsmacker/smacker.c | 80 +++++++++++++++++------------------ 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/3rdParty/libsmacker/smacker.c b/3rdParty/libsmacker/smacker.c index e3e2a0c3ef5..aa5b1bcb440 100644 --- a/3rdParty/libsmacker/smacker.c +++ b/3rdParty/libsmacker/smacker.c @@ -711,8 +711,8 @@ static char smk_read_file(void * buf, const size_t size, FILE * fp) size_t bytesRead = fread(buf, 1, size, fp); if (bytesRead != size) { - fprintf(stderr, "libsmacker::smk_read_file(buf,%lu,fp) - ERROR: Short read, %lu bytes returned\n", (unsigned long)size, (unsigned long)bytesRead); - perror("\tReason"); + LogError("libsmacker::smk_read_file(buf,%lu,fp) - ERROR: Short read, %lu bytes returned\n", (unsigned long)size, (unsigned long)bytesRead); + PrintError("\tReason"); return -1; } @@ -767,7 +767,7 @@ static char smk_read_in_memory(unsigned char ** buf, const unsigned long size, u } \ if (r < 0) \ { \ - fprintf(stderr,"libsmacker::smk_read(...) - Errors encountered on read, bailing out (file: %s, line: %lu)\n", __FILE__, (unsigned long)__LINE__); \ + LogError("libsmacker::smk_read(...) - Errors encountered on read, bailing out (file: %s, line: %lu)\n", __FILE__, (unsigned long)__LINE__); \ goto error; \ } \ } @@ -854,7 +854,7 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned /* safe malloc the structure */ #ifdef FULL if ((s = calloc(1, sizeof(struct smk_t))) == NULL) { - perror("libsmacker::smk_open_generic() - ERROR: failed to malloc() smk structure"); + PrintError("libsmacker::smk_open_generic() - ERROR: failed to malloc() smk structure"); return NULL; } #else @@ -925,7 +925,7 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned if (temp_u & 0x04) { if (s->video.y_scale_mode == SMK_FLAG_Y_DOUBLE) - fputs("libsmacker::smk_open_generic - Warning: SMK file specifies both Y-Double AND Y-Interlace.\n", stderr); + LogErrorMsg("libsmacker::smk_open_generic - Warning: SMK file specifies both Y-Double AND Y-Interlace.\n"); s->video.y_scale_mode = SMK_FLAG_Y_INTERLACE; } @@ -965,7 +965,7 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned s->audio[temp_l].channels = ((temp_u & 0x10000000) ? 2 : 1); #ifdef FULL if (temp_u & 0x0c000000) { - fprintf(stderr, "libsmacker::smk_open_generic - Warning: audio track %ld is compressed with Bink (perceptual) Audio Codec: this is currently unsupported by libsmacker\n", temp_l); + LogError("libsmacker::smk_open_generic - Warning: audio track %ld is compressed with Bink (perceptual) Audio Codec: this is currently unsupported by libsmacker\n", temp_l); s->audio[temp_l].compress = 2; } #endif @@ -1062,8 +1062,8 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned s->source.file.chunk_offset[temp_u] = ftell(fp.file); if (fseek(fp.file, s->chunk_size[temp_u], SEEK_CUR)) { - fprintf(stderr, "libsmacker::smk_open - ERROR: fseek to frame %lu not OK.\n", temp_u); - perror("\tError reported was"); + LogError("libsmacker::smk_open - ERROR: fseek to frame %lu not OK.\n", temp_u); + PrintError("\tError reported was"); goto error; } } @@ -1087,7 +1087,7 @@ smk smk_open_memory(const unsigned char * buffer, const unsigned long size) #ifdef FULL if (buffer == NULL) { - fputs("libsmacker::smk_open_memory() - ERROR: buffer pointer is NULL\n", stderr); + LogErrorMsg("libsmacker::smk_open_memory() - ERROR: buffer pointer is NULL\n"); return NULL; } #else @@ -1099,7 +1099,7 @@ smk smk_open_memory(const unsigned char * buffer, const unsigned long size) if (!(s = smk_open_generic(0, fp, size, SMK_MODE_MEMORY))) #ifdef FULL - fprintf(stderr, "libsmacker::smk_open_memory(buffer,%lu) - ERROR: Fatal error in smk_open_generic, returning NULL.\n", size); + LogError("libsmacker::smk_open_memory(buffer,%lu) - ERROR: Fatal error in smk_open_generic, returning NULL.\n", size); #else ; #endif @@ -1114,7 +1114,7 @@ smk smk_open_filepointer(FILE * file, const unsigned char mode) union smk_read_t fp; if (file == NULL) { - fputs("libsmacker::smk_open_filepointer() - ERROR: file pointer is NULL\n", stderr); + LogErrorMsg("libsmacker::smk_open_filepointer() - ERROR: file pointer is NULL\n"); return NULL; } @@ -1122,7 +1122,7 @@ smk smk_open_filepointer(FILE * file, const unsigned char mode) fp.file = file; if (!(s = smk_open_generic(1, fp, 0, mode))) { - fprintf(stderr, "libsmacker::smk_open_filepointer(file,%u) - ERROR: Fatal error in smk_open_generic, returning NULL.\n", mode); + LogError("libsmacker::smk_open_filepointer(file,%u) - ERROR: Fatal error in smk_open_generic, returning NULL.\n", mode); fclose(fp.file); goto error; } @@ -1143,13 +1143,13 @@ smk smk_open_file(const char * filename, const unsigned char mode) FILE * fp; if (filename == NULL) { - fputs("libsmacker::smk_open_file() - ERROR: filename is NULL\n", stderr); + LogErrorMsg("libsmacker::smk_open_file() - ERROR: filename is NULL\n"); return NULL; } if (!(fp = fopen(filename, "rb"))) { - fprintf(stderr, "libsmacker::smk_open_file(%s,%u) - ERROR: could not open file\n", filename, mode); - perror("\tError reported was"); + LogError("libsmacker::smk_open_file(%s,%u) - ERROR: could not open file\n", filename, mode); + PrintError("\tError reported was"); goto error; } @@ -1168,7 +1168,7 @@ void smk_close(smk s) if (s == NULL) { #ifdef FULL - fputs("libsmacker::smk_close() - ERROR: smk is NULL\n", stderr); + LogErrorMsg("libsmacker::smk_close() - ERROR: smk is NULL\n"); #endif return; } @@ -1224,12 +1224,12 @@ char smk_info_all(const smk object, unsigned long * frame, unsigned long * frame /* null check */ #ifdef FULL if (object == NULL) { - fputs("libsmacker::smk_info_all() - ERROR: smk is NULL\n", stderr); + LogErrorMsg("libsmacker::smk_info_all() - ERROR: smk is NULL\n"); return -1; } if (!frame && !frame_count && !usf) { - fputs("libsmacker::smk_info_all(object,frame,frame_count,usf) - ERROR: Request for info with all-NULL return references\n", stderr); + LogErrorMsg("libsmacker::smk_info_all(object,frame,frame_count,usf) - ERROR: Request for info with all-NULL return references\n"); goto error; } @@ -1260,12 +1260,12 @@ char smk_info_video(const smk object, unsigned long * w, unsigned long * h, unsi /* null check */ #ifdef FULL if (object == NULL) { - fputs("libsmacker::smk_info_video() - ERROR: smk is NULL\n", stderr); + LogErrorMsg("libsmacker::smk_info_video() - ERROR: smk is NULL\n"); return -1; } if (!w && !h && !y_scale_mode) { - fputs("libsmacker::smk_info_all(object,w,h,y_scale_mode) - ERROR: Request for info with all-NULL return references\n", stderr); + LogErrorMsg("libsmacker::smk_info_all(object,w,h,y_scale_mode) - ERROR: Request for info with all-NULL return references\n"); return -1; } #else @@ -1296,12 +1296,12 @@ char smk_info_audio(const smk object, unsigned char * track_mask, unsigned char /* null check */ if (object == NULL) { - fputs("libsmacker::smk_info_audio() - ERROR: smk is NULL\n", stderr); + LogErrorMsg("libsmacker::smk_info_audio() - ERROR: smk is NULL\n"); return -1; } if (!track_mask && !channels && !bitdepth && !audio_rate) { - fputs("libsmacker::smk_info_audio(object,track_mask,channels,bitdepth,audio_rate) - ERROR: Request for info with all-NULL return references\n", stderr); + LogErrorMsg("libsmacker::smk_info_audio(object,track_mask,channels,bitdepth,audio_rate) - ERROR: Request for info with all-NULL return references\n"); return -1; } @@ -1349,7 +1349,7 @@ char smk_enable_all(smk object, const unsigned char mask) /* null check */ if (object == NULL) { - fputs("libsmacker::smk_enable_all() - ERROR: smk is NULL\n", stderr); + LogErrorMsg("libsmacker::smk_enable_all() - ERROR: smk is NULL\n"); return -1; } @@ -1369,7 +1369,7 @@ char smk_enable_video(smk object, const unsigned char enable) /* null check */ #ifdef FULL if (object == NULL) { - fputs("libsmacker::smk_enable_video() - ERROR: smk is NULL\n", stderr); + LogErrorMsg("libsmacker::smk_enable_video() - ERROR: smk is NULL\n"); return -1; } #else @@ -1385,7 +1385,7 @@ char smk_enable_audio(smk object, const unsigned char track, const unsigned char /* null check */ #ifdef FULL if (object == NULL) { - fputs("libsmacker::smk_enable_audio() - ERROR: smk is NULL\n", stderr); + LogErrorMsg("libsmacker::smk_enable_audio() - ERROR: smk is NULL\n"); return -1; } #else @@ -1401,7 +1401,7 @@ const unsigned char * smk_get_palette(const smk object) /* null check */ #ifdef FULL if (object == NULL) { - fputs("libsmacker::smk_get_palette() - ERROR: smk is NULL\n", stderr); + LogErrorMsg("libsmacker::smk_get_palette() - ERROR: smk is NULL\n"); return NULL; } #else @@ -1415,7 +1415,7 @@ const unsigned char * smk_get_video(const smk object) /* null check */ #ifdef FULL if (object == NULL) { - fputs("libsmacker::smk_get_video() - ERROR: smk is NULL\n", stderr); + LogErrorMsg("libsmacker::smk_get_video() - ERROR: smk is NULL\n"); return NULL; } #else @@ -1433,7 +1433,7 @@ unsigned char * smk_get_audio(const smk object, const unsigned char t) /* null check */ #ifdef FULL if (object == NULL) { - fputs("libsmacker::smk_get_audio() - ERROR: smk is NULL\n", stderr); + LogErrorMsg("libsmacker::smk_get_audio() - ERROR: smk is NULL\n"); return NULL; } #else @@ -1447,7 +1447,7 @@ unsigned long smk_get_audio_size(const smk object, const unsigned char t) /* null check */ #ifdef FULL if (object == NULL) { - fputs("libsmacker::smk_get_audio_size() - ERROR: smk is NULL\n", stderr); + LogErrorMsg("libsmacker::smk_get_audio_size() - ERROR: smk is NULL\n"); return 0; } #else @@ -2067,20 +2067,20 @@ static char smk_render(smk s) if (s->mode == SMK_MODE_DISK) { /* Skip to frame in file */ if (fseek(s->source.file.fp, s->source.file.chunk_offset[s->cur_frame], SEEK_SET)) { - fprintf(stderr, "libsmacker::smk_render(s) - ERROR: fseek to frame %lu (offset %lu) failed.\n", s->cur_frame, s->source.file.chunk_offset[s->cur_frame]); - perror("\tError reported was"); + LogError("libsmacker::smk_render(s) - ERROR: fseek to frame %lu (offset %lu) failed.\n", s->cur_frame, s->source.file.chunk_offset[s->cur_frame]); + PrintError("\tError reported was"); goto error; } /* In disk-streaming mode: make way for our incoming chunk buffer */ if ((buffer = malloc(i)) == NULL) { - perror("libsmacker::smk_render() - ERROR: failed to malloc() buffer"); + PrintError("libsmacker::smk_render() - ERROR: failed to malloc() buffer"); return -1; } /* Read into buffer */ if (smk_read_file(buffer, i/*s->chunk_size[s->cur_frame]*/, s->source.file.fp) < 0) { - fprintf(stderr, "libsmacker::smk_render(s) - ERROR: frame %lu (offset %lu): smk_read had errors.\n", s->cur_frame, s->source.file.chunk_offset[s->cur_frame]); + LogError("libsmacker::smk_render(s) - ERROR: frame %lu (offset %lu): smk_read had errors.\n", s->cur_frame, s->source.file.chunk_offset[s->cur_frame]); goto error; } } else { @@ -2189,14 +2189,14 @@ char smk_first(smk s) #ifdef FULL /* null check */ if (s == NULL) { - fputs("libsmacker::smk_first() - ERROR: smk is NULL\n", stderr); + LogErrorMsg("libsmacker::smk_first() - ERROR: smk is NULL\n"); return -1; } s->cur_frame = 0; if (smk_render(s) < 0) { - fprintf(stderr, "libsmacker::smk_first(s) - Warning: frame %lu: smk_render returned errors.\n", s->cur_frame); + LogError("libsmacker::smk_first(s) - Warning: frame %lu: smk_render returned errors.\n", s->cur_frame); return -1; } @@ -2224,7 +2224,7 @@ char smk_next(smk s) #ifdef FULL /* null check */ if (s == NULL) { - fputs("libsmacker::smk_next() - ERROR: smk is NULL\n", stderr); + LogErrorMsg("libsmacker::smk_next() - ERROR: smk is NULL\n"); return -1; } @@ -2232,7 +2232,7 @@ char smk_next(smk s) s->cur_frame ++; if (smk_render(s) < 0) { - fprintf(stderr, "libsmacker::smk_next(s) - Warning: frame %lu: smk_render returned errors.\n", s->cur_frame); + LogError("libsmacker::smk_next(s) - Warning: frame %lu: smk_render returned errors.\n", s->cur_frame); return -1; } @@ -2244,7 +2244,7 @@ char smk_next(smk s) s->cur_frame = 1; if (smk_render(s) < 0) { - fprintf(stderr, "libsmacker::smk_next(s) - Warning: frame %lu: smk_render returned errors.\n", s->cur_frame); + LogError("libsmacker::smk_next(s) - Warning: frame %lu: smk_render returned errors.\n", s->cur_frame); return -1; } @@ -2284,7 +2284,7 @@ char smk_seek_keyframe(smk s, unsigned long f) { /* null check */ if (s == NULL) { - fputs("libsmacker::smk_seek_keyframe() - ERROR: smk is NULL\n", stderr); + LogErrorMsg("libsmacker::smk_seek_keyframe() - ERROR: smk is NULL\n"); return -1; } @@ -2297,7 +2297,7 @@ char smk_seek_keyframe(smk s, unsigned long f) /* render the frame: we're ready */ if (smk_render(s) < 0) { - fprintf(stderr, "libsmacker::smk_seek_keyframe(s,%lu) - Warning: frame %lu: smk_render returned errors.\n", f, s->cur_frame); + LogError("libsmacker::smk_seek_keyframe(s,%lu) - Warning: frame %lu: smk_render returned errors.\n", f, s->cur_frame); return -1; } From 4b26fadf686e994a0ef665d318c92ff6c6693509 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 18 Jan 2024 12:21:16 +0100 Subject: [PATCH 253/596] improve the handling of DEBUG_MODE in smacker.c --- 3rdParty/libsmacker/smacker.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/3rdParty/libsmacker/smacker.c b/3rdParty/libsmacker/smacker.c index aa5b1bcb440..a8906ce74c1 100644 --- a/3rdParty/libsmacker/smacker.c +++ b/3rdParty/libsmacker/smacker.c @@ -38,6 +38,10 @@ static uint32_t smk_swap_le32(uint32_t val) } #endif +#ifdef FULL +#undef DEBUG_MODE +#define DEBUG_MODE 1 +#endif /* logging replacements */ #if DEBUG_MODE #define PrintError(msg) perror(msg); @@ -47,7 +51,7 @@ static uint32_t smk_swap_le32(uint32_t val) #define PrintError(msg) #define LogErrorMsg(msg) #define LogError(msg, ...) -#endif /* DEBUG_MODE */ +#endif // DEBUG_MODE /* ************************************************************************* */ /* BITSTREAM Structure */ @@ -154,13 +158,13 @@ static int _smk_huff8_build_rec(struct smk_huff8_t * const t, struct smk_bit_t * int bit, value; assert(t); assert(bs); -#if DEBUG_MODE /* Make sure we aren't running out of bounds */ if (t->size >= 511) { LogErrorMsg("libsmacker::_smk_huff8_build_rec() - ERROR: size exceeded\n"); +#if DEBUG_MODE return 0; - } #endif + } /* Read the next bit */ if ((bit = smk_bs_read_1(bs)) < 0) { LogErrorMsg("libsmacker::_smk_huff8_build_rec() - ERROR: get_bit returned -1\n"); @@ -800,7 +804,7 @@ static char smk_read_in_memory(unsigned char ** buf, const unsigned long size, u } \ if (r < 0) \ { \ - LogError("libsmacker::smk_read(...) - Errors encountered on read, bailing out (file: %s, line: %lu)\n", __FILE__, (unsigned long)__LINE__); \ + LogError("libsmacker::smk_read(...) - Errors encountered on read_in, bailing out (file: %s, line: %lu)\n", __FILE__, (unsigned long)__LINE__); \ goto error; \ } \ } @@ -2173,14 +2177,14 @@ static char smk_render(smk s) return 0; #if DEBUG_MODE error: - +#ifdef FULL if (s->mode == SMK_MODE_DISK) { /* Remember that buffer we allocated? Trash it */ smk_free(buffer); } - +#endif // FULL return -1; -#endif +#endif // DEBUG_MODE } /* rewind to first frame and unpack */ From 1a0bf3bf3de109d920ec9e5937ddf408f789ffc1 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 18 Jan 2024 12:47:36 +0100 Subject: [PATCH 254/596] disable ring_frame (loop) support in smacker --- 3rdParty/libsmacker/smacker.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/3rdParty/libsmacker/smacker.c b/3rdParty/libsmacker/smacker.c index a8906ce74c1..2f2e8af37a6 100644 --- a/3rdParty/libsmacker/smacker.c +++ b/3rdParty/libsmacker/smacker.c @@ -603,12 +603,11 @@ struct smk_t { #ifdef FULL /* total frames */ unsigned long f; + /* does file have a ring frame? (in other words, does file loop?) */ + unsigned char ring_frame; #else unsigned long total_frames; /* f + ring_frame */ #endif - /* does file have a ring frame? (in other words, does file loop?) */ - unsigned char ring_frame; - /* Index of current frame */ unsigned long cur_frame; @@ -935,7 +934,7 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned } #else if (temp_u & 0x01) { - s->ring_frame = 1; + LogErrorMsg("libsmacker::smk_open_generic - Warning: ring_frames are no supported by the game.\n"); s->total_frames++; } #endif @@ -2268,14 +2267,9 @@ char smk_next(smk s) s->cur_frame ++; result = SMK_MORE; - } else if (s->ring_frame) { - s->cur_frame = 1; - - result = SMK_MORE; - } - - if (result == SMK_MORE && smk_render(s) < 0) { - result = SMK_ERROR; + if (smk_render(s) < 0) { + result = SMK_ERROR; + } } return result; From 566d55b1c5b3d59c36fa7e4f43fe5f14ebd44c0e Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 19 Jan 2024 12:16:52 +0100 Subject: [PATCH 255/596] use consistent error messages in smacker --- 3rdParty/libsmacker/smacker.c | 58 +++++++++++++++++------------------ 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/3rdParty/libsmacker/smacker.c b/3rdParty/libsmacker/smacker.c index 2f2e8af37a6..47b2ec0e7f3 100644 --- a/3rdParty/libsmacker/smacker.c +++ b/3rdParty/libsmacker/smacker.c @@ -803,7 +803,7 @@ static char smk_read_in_memory(unsigned char ** buf, const unsigned long size, u } \ if (r < 0) \ { \ - LogError("libsmacker::smk_read(...) - Errors encountered on read_in, bailing out (file: %s, line: %lu)\n", __FILE__, (unsigned long)__LINE__); \ + LogError("libsmacker::smk_read_in(...) - Errors encountered on read, bailing out (file: %s, line: %lu)\n", __FILE__, (unsigned long)__LINE__); \ goto error; \ } \ } @@ -868,7 +868,7 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned smk_read(buf, 4); if (buf[0] != 'S' || buf[1] != 'M' || buf[2] != 'K') { - LogError("libsmacker::smk_open_generic - ERROR: invalid SMKn signature (got: %s)\n", buf); + LogError("libsmacker::smk_open_generic() - ERROR: invalid SMKn signature (got: %s)\n", buf); #if DEBUG_MODE goto error; #endif @@ -878,7 +878,7 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned //smk_read(buf, 1); #if DEBUG_MODE if (buf[3] != '2' && buf[3] != '4') { - LogError("libsmacker::smk_open_generic - Warning: invalid SMK version %c (expected: 2 or 4)\n", buf[3]); + LogError("libsmacker::smk_open_generic() - Warning: invalid SMK version %c (expected: 2 or 4)\n", buf[3]); /* take a guess */ if (buf[3] < '4') @@ -928,13 +928,13 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned if (temp_u & 0x04) { if (s->video.y_scale_mode == SMK_FLAG_Y_DOUBLE) - LogErrorMsg("libsmacker::smk_open_generic - Warning: SMK file specifies both Y-Double AND Y-Interlace.\n"); + LogErrorMsg("libsmacker::smk_open_generic() - Warning: SMK file specifies both Y-Double AND Y-Interlace.\n"); s->video.y_scale_mode = SMK_FLAG_Y_INTERLACE; } #else if (temp_u & 0x01) { - LogErrorMsg("libsmacker::smk_open_generic - Warning: ring_frames are no supported by the game.\n"); + LogErrorMsg("libsmacker::smk_open_generic() - Warning: ring_frames are no supported by the game.\n"); s->total_frames++; } #endif @@ -968,7 +968,7 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned s->audio[temp_l].channels = ((temp_u & 0x10000000) ? 2 : 1); #ifdef FULL if (temp_u & 0x0c000000) { - LogError("libsmacker::smk_open_generic - Warning: audio track %ld is compressed with Bink (perceptual) Audio Codec: this is currently unsupported by libsmacker\n", temp_l); + LogError("libsmacker::smk_open_generic() - Warning: audio track %ld is compressed with Bink (perceptual) Audio Codec: this is currently unsupported by libsmacker\n", temp_l); s->audio[temp_l].compress = 2; } #endif @@ -1022,7 +1022,7 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned /* create some tables */ for (temp_u = 0; temp_u < 4; temp_u ++) { if (! smk_huff16_build(&s->video.tree[temp_u], &bs, s->video.tree_size[temp_u])) { - LogError("libsmacker::smk_open_generic - ERROR: failed to create huff16 tree %lu\n", temp_u); + LogError("libsmacker::smk_open_generic() - ERROR: failed to create huff16 tree %lu\n", temp_u); #if DEBUG_MODE goto error; #endif @@ -1065,7 +1065,7 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned s->source.file.chunk_offset[temp_u] = ftell(fp.file); if (fseek(fp.file, s->chunk_size[temp_u], SEEK_CUR)) { - LogError("libsmacker::smk_open - ERROR: fseek to frame %lu not OK.\n", temp_u); + LogError("libsmacker::smk_open_generic() - ERROR: fseek to frame %lu not OK.\n", temp_u); PrintError("\tError reported was"); goto error; } @@ -1232,7 +1232,7 @@ char smk_info_all(const smk object, unsigned long * frame, unsigned long * frame } if (!frame && !frame_count && !usf) { - LogErrorMsg("libsmacker::smk_info_all(object,frame,frame_count,usf) - ERROR: Request for info with all-NULL return references\n"); + LogErrorMsg("libsmacker::smk_info_all() - ERROR: Request for info with all-NULL return references\n"); goto error; } @@ -1268,7 +1268,7 @@ char smk_info_video(const smk object, unsigned long * w, unsigned long * h, unsi } if (!w && !h && !y_scale_mode) { - LogErrorMsg("libsmacker::smk_info_all(object,w,h,y_scale_mode) - ERROR: Request for info with all-NULL return references\n"); + LogErrorMsg("libsmacker::smk_info_video() - ERROR: Request for info with all-NULL return references\n"); return -1; } #else @@ -1496,7 +1496,7 @@ static char smk_render_palette(struct smk_video_t * s, unsigned char * p, unsign /* check for overflow condition */ if (i + count > 256) { - LogError("libsmacker::palette_render(s,p,size) - ERROR: overflow, 0x80 attempt to skip %d entries from %d\n", count, i); + LogError("libsmacker::smk_render_palette() - ERROR: overflow, 0x80 attempt to skip %d entries from %d\n", count, i); #if DEBUG_MODE goto error; #endif @@ -1510,7 +1510,7 @@ static char smk_render_palette(struct smk_video_t * s, unsigned char * p, unsign starting from entry (s), to the next entries of the new palette. */ if (size < 2) { - LogErrorMsg("libsmacker::palette_render(s,p,size) - ERROR: 0x40 ran out of bytes for copy\n"); + LogErrorMsg("libsmacker::smk_render_palette() - ERROR: 0x40 ran out of bytes for copy\n"); #if DEBUG_MODE goto error; #endif @@ -1527,7 +1527,7 @@ static char smk_render_palette(struct smk_video_t * s, unsigned char * p, unsign /* overflow: see if we write/read beyond 256colors, or overwrite own palette */ if (i + count > 256 || src + count > 256) { // condition fixed to prevent artifacts in the final video - LogError("libsmacker::palette_render(s,p,size) - ERROR: overflow, 0x40 attempt to copy %d entries from %d to %d\n", count, src, i); + LogError("libsmacker::smk_render_palette() - ERROR: overflow, 0x40 attempt to copy %d entries from %d to %d\n", count, src, i); #if DEBUG_MODE goto error; #endif @@ -1540,7 +1540,7 @@ static char smk_render_palette(struct smk_video_t * s, unsigned char * p, unsign /* 0x00: Set Color block Direct-set the next 3 bytes for palette index */ if (size < 3) { - LogError("libsmacker::palette_render - ERROR: 0x3F ran out of bytes for copy, size=%lu\n", size); + LogError("libsmacker::smk_render_palette() - ERROR: 0x3F ran out of bytes for copy, size=%lu\n", size); #if DEBUG_MODE goto error; #endif @@ -1548,7 +1548,7 @@ static char smk_render_palette(struct smk_video_t * s, unsigned char * p, unsign for (count = 0; count < 3; count ++) { if (*p > 0x3F) { - LogError("libsmacker::palette_render - ERROR: palette index exceeds 0x3F (entry [%u][%u])\n", i, count); + LogError("libsmacker::smk_render_palette() - ERROR: palette index exceeds 0x3F (entry [%u][%u])\n", i, count); #if DEBUG_MODE goto error; #endif @@ -1564,7 +1564,7 @@ static char smk_render_palette(struct smk_video_t * s, unsigned char * p, unsign } if (i < 256) { - LogError("libsmacker::palette_render - ERROR: did not completely fill palette (idx=%u)\n", i); + LogError("libsmacker::smk_render_palette() - ERROR: did not completely fill palette (idx=%u)\n", i); #if DEBUG_MODE goto error; #endif @@ -1875,19 +1875,19 @@ static char smk_render_audio(struct smk_audio_t * s, unsigned char * p, unsigned bit = smk_bs_read_1(&bs); #ifdef FULL if (!bit) { - LogErrorMsg("libsmacker::smk_render_audio - ERROR: initial get_bit returned 0\n"); + LogErrorMsg("libsmacker::smk_render_audio() - ERROR: initial get_bit returned 0\n"); goto error; } bit = smk_bs_read_1(&bs); if (s->channels != (bit == 1 ? 2 : 1)) - LogErrorMsg("libsmacker::smk_render - ERROR: mono/stereo mismatch\n"); + LogErrorMsg("libsmacker::smk_render_audio() - ERROR: mono/stereo mismatch\n"); bit = smk_bs_read_1(&bs); if (s->bitdepth != (bit == 1 ? 16 : 8)) - LogErrorMsg("libsmacker::smk_render - ERROR: 8-/16-bit mismatch\n"); + LogErrorMsg("libsmacker::smk_render_audio() - ERROR: 8-/16-bit mismatch\n"); /* build the trees */ smk_huff8_build(&aud_tree[0], &bs); @@ -1961,18 +1961,18 @@ static char smk_render_audio(struct smk_audio_t * s, unsigned char * p, unsigned } #else if (!bit) - LogErrorMsg("libsmacker::smk_render_audio - ERROR: initial get_bit returned 0\n"); + LogErrorMsg("libsmacker::smk_render_audio() - ERROR: initial get_bit returned 0\n"); bit = smk_bs_read_1(&bs); bitdepth = s->bitdepth; channels = s->channels; if (channels != (bit == 1 ? 2 : 1)) - LogErrorMsg("libsmacker::smk_render - ERROR: mono/stereo mismatch\n"); + LogErrorMsg("libsmacker::smk_render_audio() - ERROR: mono/stereo mismatch\n"); bit = smk_bs_read_1(&bs); if (bitdepth != (bit == 1 ? 16 : 8)) - LogErrorMsg("libsmacker::smk_render - ERROR: 8-/16-bit mismatch\n"); + LogErrorMsg("libsmacker::smk_render_audio() - ERROR: 8-/16-bit mismatch\n"); /* build the trees */ smk_huff8_build(&aud_tree[0], &bs); @@ -2060,7 +2060,7 @@ static char smk_render(smk s) /* Retrieve current chunk_size for this frame. */ if (!(i = s->chunk_size[s->cur_frame])) { - LogError("libsmacker::smk_render(s) - Warning: frame %lu: chunk_size is 0.\n", s->cur_frame); + LogError("libsmacker::smk_render() - Warning: frame %lu: chunk_size is 0.\n", s->cur_frame); #if DEBUG_MODE goto error; #endif @@ -2070,7 +2070,7 @@ static char smk_render(smk s) if (s->mode == SMK_MODE_DISK) { /* Skip to frame in file */ if (fseek(s->source.file.fp, s->source.file.chunk_offset[s->cur_frame], SEEK_SET)) { - LogError("libsmacker::smk_render(s) - ERROR: fseek to frame %lu (offset %lu) failed.\n", s->cur_frame, s->source.file.chunk_offset[s->cur_frame]); + LogError("libsmacker::smk_render() - ERROR: fseek to frame %lu (offset %lu) failed.\n", s->cur_frame, s->source.file.chunk_offset[s->cur_frame]); PrintError("\tError reported was"); goto error; } @@ -2083,14 +2083,14 @@ static char smk_render(smk s) /* Read into buffer */ if (smk_read_file(buffer, i/*s->chunk_size[s->cur_frame]*/, s->source.file.fp) < 0) { - LogError("libsmacker::smk_render(s) - ERROR: frame %lu (offset %lu): smk_read had errors.\n", s->cur_frame, s->source.file.chunk_offset[s->cur_frame]); + LogError("libsmacker::smk_render() - ERROR: frame %lu (offset %lu): smk_read had errors.\n", s->cur_frame, s->source.file.chunk_offset[s->cur_frame]); goto error; } } else { #endif /* Just point buffer at the right place */ if (!s->source.chunk_data[s->cur_frame]) { - LogError("libsmacker::smk_render(s) - ERROR: frame %lu: memory chunk is a NULL pointer.\n", s->cur_frame); + LogError("libsmacker::smk_render() - ERROR: frame %lu: memory chunk is a NULL pointer.\n", s->cur_frame); #if DEBUG_MODE goto error; #endif @@ -2107,7 +2107,7 @@ static char smk_render(smk s) if (s->frame_type[s->cur_frame] & 0x01) { /* need at least 1 byte to process */ if (!i) { - LogError("libsmacker::smk_render(s) - ERROR: frame %lu: insufficient data for a palette rec.\n", s->cur_frame); + LogError("libsmacker::smk_render() - ERROR: frame %lu: insufficient data for a palette rec.\n", s->cur_frame); #if DEBUG_MODE goto error; #endif @@ -2130,7 +2130,7 @@ static char smk_render(smk s) if (s->frame_type[s->cur_frame] & (0x02 << track)) { /* need at least 4 byte to process */ if (i < 4) { - LogError("libsmacker::smk_render(s) - ERROR: frame %lu: insufficient data for audio[%u] rec.\n", s->cur_frame, track); + LogError("libsmacker::smk_render() - ERROR: frame %lu: insufficient data for audio[%u] rec.\n", s->cur_frame, track); #if DEBUG_MODE goto error; #endif @@ -2159,7 +2159,7 @@ static char smk_render(smk s) /* Unpack video chunk */ if (s->video.enable) { if (smk_render_video(&(s->video), p, i) < 0) { - LogError("libsmacker::smk_render(s) - ERROR: frame %lu: failed to render video.\n", s->cur_frame); + LogError("libsmacker::smk_render() - ERROR: frame %lu: failed to render video.\n", s->cur_frame); #if DEBUG_MODE goto error; #endif From c478f66daec4e4de5277f327f0425a06d93a4e24 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 19 Jan 2024 12:19:33 +0100 Subject: [PATCH 256/596] make smacker more resilient when DEBUG_MODE is set --- 3rdParty/libsmacker/smacker.c | 75 +++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 13 deletions(-) diff --git a/3rdParty/libsmacker/smacker.c b/3rdParty/libsmacker/smacker.c index 47b2ec0e7f3..4917719ae90 100644 --- a/3rdParty/libsmacker/smacker.c +++ b/3rdParty/libsmacker/smacker.c @@ -1634,12 +1634,22 @@ static char smk_render_video(struct smk_video_t * s, unsigned char * p, unsigned #ifdef FULL_V4 /* support for v4 full-blocks */ if (type == 1 && s->v == '4') { - bit = smk_bs_read_1(&bs); + if ((bit = smk_bs_read_1(&bs)) < 0) { + LogErrorMsg("libsmacker::smk_render_video() - ERROR: first subtype of v4 returned -1\n"); +#if DEBUG_MODE + return -1; +#endif + } if (bit) type = 4; else { - bit = smk_bs_read_1(&bs); + if ((bit = smk_bs_read_1(&bs)) < 0) { + LogErrorMsg("libsmacker::smk_render_video() - ERROR: second subtype of v4 returned -1\n"); +#if DEBUG_MODE + return -1; +#endif + } if (bit) type = 5; @@ -1872,7 +1882,12 @@ static char smk_render_audio(struct smk_audio_t * s, unsigned char * p, unsigned /* Compressed audio: must unpack here */ /* Set up a bitstream */ smk_bs_init(&bs, p, size); - bit = smk_bs_read_1(&bs); + if ((bit = smk_bs_read_1(&bs)) < 0) { + LogErrorMsg("libsmacker::smk_render_audio() - ERROR: initial get_bit returned -1\n"); +#if DEBUG_MODE + goto error; +#endif + } #ifdef FULL if (!bit) { LogErrorMsg("libsmacker::smk_render_audio() - ERROR: initial get_bit returned 0\n"); @@ -1963,13 +1978,23 @@ static char smk_render_audio(struct smk_audio_t * s, unsigned char * p, unsigned if (!bit) LogErrorMsg("libsmacker::smk_render_audio() - ERROR: initial get_bit returned 0\n"); - bit = smk_bs_read_1(&bs); + if ((bit = smk_bs_read_1(&bs)) < 0) { + LogErrorMsg("libsmacker::smk_render_audio() - ERROR: channels_bit returned -1\n"); +#if DEBUG_MODE + goto error; +#endif + } bitdepth = s->bitdepth; channels = s->channels; if (channels != (bit == 1 ? 2 : 1)) LogErrorMsg("libsmacker::smk_render_audio() - ERROR: mono/stereo mismatch\n"); - bit = smk_bs_read_1(&bs); + if ((bit = smk_bs_read_1(&bs)) < 0) { + LogErrorMsg("libsmacker::smk_render_audio() - ERROR: bitdepth_bit returned -1\n"); +#if DEBUG_MODE + goto error; +#endif + } if (bitdepth != (bit == 1 ? 16 : 8)) LogErrorMsg("libsmacker::smk_render_audio() - ERROR: 8-/16-bit mismatch\n"); @@ -2106,20 +2131,30 @@ static char smk_render(smk s) /* Palette record first */ if (s->frame_type[s->cur_frame] & 0x01) { /* need at least 1 byte to process */ - if (!i) { - LogError("libsmacker::smk_render() - ERROR: frame %lu: insufficient data for a palette rec.\n", s->cur_frame); -#if DEBUG_MODE - goto error; -#endif - } + assert(i != 0); /* Byte 1 in block, times 4, tells how many subsequent bytes are present */ size = 4 * (*p); + if (i < size) { + LogError("libsmacker::smk_render() - ERROR: frame %lu: insufficient data for a palette content.\n", s->cur_frame); +#if DEBUG_MODE + goto error; +#endif + } + /* If video rendering enabled, kick this off for decode. */ - if (s->video.enable) + if (s->video.enable) { + if (size < 1) { + LogError("libsmacker::smk_render() - ERROR: frame %lu: invalid palette size.\n", s->cur_frame); +#if DEBUG_MODE + goto error; +#endif + } + smk_render_palette(&(s->video), p + 1, size - 1); + } p += size; i -= size; @@ -2146,9 +2181,23 @@ static char smk_render(smk s) #else size = smk_swap_le32(*(uint32_t*)&p[0]); #endif + if (i < size) { + LogError("libsmacker::smk_render() - ERROR: frame %lu: insufficient data for audio[%u] content.\n", s->cur_frame, track); +#if DEBUG_MODE + goto error; +#endif + } /* If audio rendering enabled, kick this off for decode. */ - if (s->audio[track].enable) + if (s->audio[track].enable) { + if (size < 4) { + LogError("libsmacker::smk_render() - ERROR: frame %lu: invalid data size for audio[%u] content.\n", s->cur_frame, track); +#if DEBUG_MODE + goto error; +#endif + } + smk_render_audio(&s->audio[track], p + 4, size - 4); + } p += size; i -= size; From b8f0114ffd1ed776305083ca2fef9631785b875e Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 25 Jan 2024 09:48:53 +0100 Subject: [PATCH 257/596] report invalid alloc_size in DEBUG_MODE --- 3rdParty/libsmacker/smacker.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/3rdParty/libsmacker/smacker.c b/3rdParty/libsmacker/smacker.c index 4917719ae90..38dfa4efbae 100644 --- a/3rdParty/libsmacker/smacker.c +++ b/3rdParty/libsmacker/smacker.c @@ -127,7 +127,7 @@ static int smk_bs_read_8(struct smk_bit_t * const bs) int ret = *bs->buffer >> bs->bit_num; bs->buffer ++; return ret | (*bs->buffer << (8 - bs->bit_num) & 0xFF); -#if FULL +#ifdef FULL } /* aligned read */ @@ -472,13 +472,13 @@ static int smk_huff16_build(struct smk_huff16_t * const t, struct smk_bit_t * co t->cache[i] |= (value << 8); } -#if DEBUG_MODE /* Everything looks OK so far. Time to malloc structure. */ if (alloc_size < 12 || alloc_size % 4) { LogError("libsmacker::smk_huff16_build() - ERROR: illegal value %u for alloc_size\n", alloc_size); +#if DEBUG_MODE return 0; - } #endif + } limit = (alloc_size - 12) / 4; if ((t->tree = malloc(limit * sizeof(unsigned int))) == NULL) { From d5939be03cd31e6667f115b695a898293b4dbb03 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 2 Feb 2024 08:44:07 +0100 Subject: [PATCH 258/596] minor smacker optimizations - 'read' header in one step - store tree-sizes in a local array - eliminate pointless null checks before free + use defines instead of constants --- 3rdParty/libsmacker/smacker.c | 231 ++++++++++++++++++++++++++-------- 1 file changed, 180 insertions(+), 51 deletions(-) diff --git a/3rdParty/libsmacker/smacker.c b/3rdParty/libsmacker/smacker.c index 38dfa4efbae..e46064383bf 100644 --- a/3rdParty/libsmacker/smacker.c +++ b/3rdParty/libsmacker/smacker.c @@ -122,8 +122,8 @@ static int smk_bs_read_8(struct smk_bit_t * const bs) #endif #ifdef FULL if (bs->bit_num) { -#endif /* unaligned read */ +#endif int ret = *bs->buffer >> bs->bit_num; bs->buffer ++; return ret | (*bs->buffer << (8 - bs->bit_num) & 0xFF); @@ -158,6 +158,7 @@ static int _smk_huff8_build_rec(struct smk_huff8_t * const t, struct smk_bit_t * int bit, value; assert(t); assert(bs); + /* Make sure we aren't running out of bounds */ if (t->size >= 511) { LogErrorMsg("libsmacker::_smk_huff8_build_rec() - ERROR: size exceeded\n"); @@ -165,6 +166,7 @@ static int _smk_huff8_build_rec(struct smk_huff8_t * const t, struct smk_bit_t * return 0; #endif } + /* Read the next bit */ if ((bit = smk_bs_read_1(bs)) < 0) { LogErrorMsg("libsmacker::_smk_huff8_build_rec() - ERROR: get_bit returned -1\n"); @@ -305,7 +307,12 @@ static int smk_huff8_lookup(const struct smk_huff8_t * const t, struct smk_bit_t /* ************************************************************************* */ #define SMK_HUFF16_BRANCH 0x80000000 #define SMK_HUFF16_CACHE 0x40000000 +#ifdef FULL #define SMK_HUFF16_LEAF_MASK 0x3FFFFFFF +#else +#define SMK_HUFF16_LEAF_MASK 0x7FFFFFFF +#define SMK_HUFF16_CACHE_MSK 0x3 +#endif struct smk_huff16_t { unsigned int * tree; @@ -479,8 +486,8 @@ static int smk_huff16_build(struct smk_huff16_t * const t, struct smk_bit_t * co return 0; #endif } - limit = (alloc_size - 12) / 4; + limit = (alloc_size - 12) / 4; if ((t->tree = malloc(limit * sizeof(unsigned int))) == NULL) { PrintError("libsmacker::smk_huff16_build() - ERROR: failed to malloc() huff16 tree"); return 0; @@ -568,7 +575,7 @@ static int smk_huff16_lookup(struct smk_huff16_t * const t, struct smk_bit_t * c if (value & SMK_HUFF16_CACHE) { /* uses cached value instead of actual value */ - value = t->cache[value & SMK_HUFF16_LEAF_MASK]; + value = t->cache[value & SMK_HUFF16_CACHE_MSK]; } if (t->cache[0] != value) { @@ -590,6 +597,29 @@ static int smk_huff16_lookup(struct smk_huff16_t * const t, struct smk_bit_t * c #define SMK_TREE_MCLR 1 #define SMK_TREE_FULL 2 #define SMK_TREE_TYPE 3 +#ifndef FULL +#define SMK_TREE_COUNT 4 + +#define SMK_AUDIO_TRACKS 7 + +typedef struct _smk_header { + uint8_t SmkMarker[4]; + uint32_t VideoWidth; + uint32_t VideoHeight; + uint32_t FrameCount; + uint32_t FrameLen; + uint32_t VideoFlags; + uint32_t AudioMaxChunkLength[SMK_AUDIO_TRACKS]; // uncompressed length + uint32_t VideoTreeDataSize; + uint32_t VideoTreeSize[SMK_TREE_COUNT]; // uncompressed size + uint32_t AudioType[SMK_AUDIO_TRACKS]; + uint32_t Dummy; + // uint32_t FrameDataSize[FrameCount]; + // uint8_t FrameType[FrameCount]; + // uint8_t VideoTreeData[VideoTreeDataSize]; + // uint8_t FrameData[FrameDataSize][FrameCount]; - [PAL_SIZE PALETTE] [AUDIO_SIZE{4} (AUDIO_DATA | UNCOMPRESSED_SIZE{4} 1 CH W TREE_DATA[4] AUDIO_DATA)][7] [VIDEO_DATA] +} smk_header; +#endif struct smk_t { /* meta-info */ @@ -653,13 +683,17 @@ struct smk_t { 1: doubled 2: interlaced */ unsigned char y_scale_mode; -#endif + /* version ('2' or '4') */ unsigned char v; /* Huffman trees */ unsigned long tree_size[4]; - struct smk_huff16_t tree[4]; +#elif DEBUG_MODE + /* version ('2' or '4') */ + unsigned char v; +#endif + struct smk_huff16_t tree[SMK_TREE_COUNT]; /* Palette data type: pointer to last-decoded-palette */ unsigned char palette[256][3]; @@ -692,7 +726,7 @@ struct smk_t { /* pointer to last-decoded-audio-buffer */ void * buffer; unsigned long buffer_size; - } audio[7]; + } audio[SMK_AUDIO_TRACKS]; }; union smk_read_t { @@ -836,7 +870,11 @@ static char smk_read_in_memory(unsigned char ** buf, const unsigned long size, u /* PUBLIC FUNCTIONS */ /* open an smk (from a generic Source) */ +#ifdef FULL static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned long size, const unsigned char process_mode) +#else +static smk smk_open_generic(union smk_read_t fp, unsigned long size) +#endif { /* Smacker structure we intend to work on / return */ smk s; @@ -860,23 +898,17 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned PrintError("libsmacker::smk_open_generic() - ERROR: failed to malloc() smk structure"); return NULL; } -#else - s = NULL; - smk_malloc(s, sizeof(struct smk_t)); -#endif + /* Check for a valid signature */ smk_read(buf, 4); if (buf[0] != 'S' || buf[1] != 'M' || buf[2] != 'K') { LogError("libsmacker::smk_open_generic() - ERROR: invalid SMKn signature (got: %s)\n", buf); -#if DEBUG_MODE goto error; -#endif } /* Read .smk file version */ //smk_read(buf, 1); -#if DEBUG_MODE if (buf[3] != '2' && buf[3] != '4') { LogError("libsmacker::smk_open_generic() - Warning: invalid SMK version %c (expected: 2 or 4)\n", buf[3]); @@ -888,17 +920,12 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned LogError("\tProcessing will continue as type %c\n", buf[3]); } -#endif s->video.v = buf[3]; /* width, height, total num frames */ smk_read_ul(s->video.w); smk_read_ul(s->video.h); -#ifdef FULL smk_read_ul(s->f); -#else - smk_read_ul(s->total_frames); -#endif /* frames per second calculation */ smk_read_ul(temp_u); temp_l = (int)temp_u; @@ -919,7 +946,6 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned Y scale / Y interlace go in the Video flags. The user should scale appropriately. */ smk_read_ul(temp_u); -#ifdef FULL if (temp_u & 0x01) s->ring_frame = 1; @@ -932,12 +958,6 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned s->video.y_scale_mode = SMK_FLAG_Y_INTERLACE; } -#else - if (temp_u & 0x01) { - LogErrorMsg("libsmacker::smk_open_generic() - Warning: ring_frames are no supported by the game.\n"); - s->total_frames++; - } -#endif /* Max buffer size for each audio track - used to pre-allocate buffers */ for (temp_l = 0; temp_l < 7; temp_l ++) smk_read_ul(s->audio[temp_l].max_buffer); @@ -954,10 +974,9 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned smk_read_ul(temp_u); if (temp_u & 0x40000000) { -#ifdef FULL /* Audio track specifies "exists" flag, malloc structure and copy components. */ s->audio[temp_l].exists = 1; -#endif + /* and for all audio tracks */ smk_malloc(s->audio[temp_l].buffer, s->audio[temp_l].max_buffer); @@ -966,12 +985,12 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned s->audio[temp_l].bitdepth = ((temp_u & 0x20000000) ? 16 : 8); s->audio[temp_l].channels = ((temp_u & 0x10000000) ? 2 : 1); -#ifdef FULL + if (temp_u & 0x0c000000) { LogError("libsmacker::smk_open_generic() - Warning: audio track %ld is compressed with Bink (perceptual) Audio Codec: this is currently unsupported by libsmacker\n", temp_l); s->audio[temp_l].compress = 2; } -#endif + /* Bits 25 & 24 are unused. */ s->audio[temp_l].rate = (temp_u & 0x00FFFFFF); } @@ -979,6 +998,99 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned /* Skip over Dummy field */ smk_read_ul(temp_u); +#else + unsigned long video_tree_size[SMK_TREE_COUNT]; + + s = NULL; + smk_malloc(s, sizeof(struct smk_t)); + smk_header *hdr = (smk_header*)fp.ram; + if (size < sizeof(smk_header)) { + LogError("libsmacker::smk_open_generic() - ERROR: SMK content is too short. (got: %d, required: %d)\n", size, sizeof(smk_header)); +#if DEBUG_MODE + goto error; +#endif + } + size -= sizeof(smk_header); + fp.ram += sizeof(smk_header); + + /* Check for a valid signature */ + if (hdr->SmkMarker[0] != 'S' || hdr->SmkMarker[1] != 'M' || hdr->SmkMarker[2] != 'K') { + LogError("libsmacker::smk_open_generic() - ERROR: invalid SMKn signature (got: %c%c%c)\n", hdr->SmkMarker[0], hdr->SmkMarker[1], hdr->SmkMarker[2]); +#if DEBUG_MODE + goto error; +#endif + } +#if DEBUG_MODE + /* Read .smk file version */ + if (hdr->SmkMarker[3] != '2') { + LogError("libsmacker::smk_open_generic() - Warning: SMK version %c is not supported by the game.\n", hdr->SmkMarker[3]); + } + s->video.v = hdr->SmkMarker[3]; +#endif + s->video.w = smk_swap_le32(hdr->VideoWidth); + s->video.h = smk_swap_le32(hdr->VideoHeight); + s->total_frames = smk_swap_le32(hdr->FrameCount); + /* frames per second calculation */ + temp_u = smk_swap_le32(hdr->FrameLen); + /* frames per second calculation */ + temp_l = (int)temp_u; + + if (temp_l > 0) { + /* millisec per frame */ + s->usf = temp_l * 1000; + } else if (temp_l < 0) { + /* 10 microsec per frame */ + s->usf = temp_l * -10; + } else { + /* defaults to 10 usf (= 100000 microseconds) */ + s->usf = 100000; + } + /* Video flags follow. + Ring frame is important to libsmacker. + Y scale / Y interlace go in the Video flags. + The user should scale appropriately. */ + temp_u = smk_swap_le32(hdr->VideoFlags); +#if DEBUG_MODE + if (temp_u & 0x01) { + LogErrorMsg("libsmacker::smk_open_generic() - Warning: ring_frames are no supported by the game.\n"); + s->total_frames++; + } +#endif + /* Max buffer size for each audio track - used to pre-allocate buffers */ + for (temp_l = 0; temp_l < SMK_AUDIO_TRACKS; temp_l ++) + s->audio[temp_l].max_buffer = smk_swap_le32(hdr->AudioMaxChunkLength[temp_l]); + /* Read size of "hufftree chunk" - save for later. */ + tree_size = smk_swap_le32(hdr->VideoTreeDataSize); + /* "unpacked" sizes of each huff tree */ + for (temp_l = 0; temp_l < SMK_TREE_COUNT; temp_l ++) { + video_tree_size[temp_l] = smk_swap_le32(hdr->VideoTreeSize[temp_l]); + } + /* read audio rate data */ + for (temp_l = 0; temp_l < SMK_AUDIO_TRACKS; temp_l ++) { + temp_u = smk_swap_le32(hdr->AudioType[temp_l]); + + if (temp_u & 0x40000000) { + /* and for all audio tracks */ + smk_malloc(s->audio[temp_l].buffer, s->audio[temp_l].max_buffer); +#ifdef FULL + if (temp_u & 0x80000000) + s->audio[temp_l].compress = 1; +#else + s->audio[temp_l].compress = ((temp_u & 0x80000000) ? 1 : 0); +#endif + s->audio[temp_l].bitdepth = ((temp_u & 0x20000000) ? 16 : 8); + s->audio[temp_l].channels = ((temp_u & 0x10000000) ? 2 : 1); +#if DEBUG_MODE + if (temp_u & 0x0c000000) { + LogError("libsmacker::smk_open_generic() - Warning: audio track %ld is compressed with Bink (perceptual) Audio Codec: this is currently unsupported by libsmacker\n", temp_l); + s->audio[temp_l].compress = 2; + } +#endif + /* Bits 25 & 24 are unused. */ + s->audio[temp_l].rate = (temp_u & 0x00FFFFFF); + } + } +#endif // FULL /* FrameSizes and Keyframe marker are stored together. */ #ifdef FULL smk_malloc(s->keyframe, (s->f + s->ring_frame)); @@ -1020,8 +1132,12 @@ static smk smk_open_generic(const unsigned char m, union smk_read_t fp, unsigned smk_bs_init(&bs, hufftree_chunk, tree_size); /* create some tables */ - for (temp_u = 0; temp_u < 4; temp_u ++) { + for (temp_u = 0; temp_u < SMK_TREE_COUNT; temp_u ++) { +#ifdef FULL if (! smk_huff16_build(&s->video.tree[temp_u], &bs, s->video.tree_size[temp_u])) { +#else + if (! smk_huff16_build(&s->video.tree[temp_u], &bs, video_tree_size[temp_u])) { +#endif LogError("libsmacker::smk_open_generic() - ERROR: failed to create huff16 tree %lu\n", temp_u); #if DEBUG_MODE goto error; @@ -1100,12 +1216,13 @@ smk smk_open_memory(const unsigned char * buffer, const unsigned long size) /* set up the read union for Memory mode */ fp.ram = (unsigned char *)buffer; - if (!(s = smk_open_generic(0, fp, size, SMK_MODE_MEMORY))) -#ifdef FULL - LogError("libsmacker::smk_open_memory(buffer,%lu) - ERROR: Fatal error in smk_open_generic, returning NULL.\n", size); -#else - ; +#ifdef FULL + if (!(s = smk_open_generic(0, fp, size, SMK_MODE_MEMORY))) +#else + if (!(s = smk_open_generic(fp, size))) #endif + LogError("libsmacker::smk_open_memory(buffer,%lu) - ERROR: Fatal error in smk_open_generic, returning NULL.\n", size); + ; return s; } @@ -1177,16 +1294,24 @@ void smk_close(smk s) } /* free video sub-components */ - for (u = 0; u < 4; u ++) { + for (u = 0; u < SMK_TREE_COUNT; u ++) { +#ifdef FULL if (s->video.tree[u].tree) free(s->video.tree[u].tree); +#else + free(s->video.tree[u].tree); +#endif } smk_free(s->video.frame); /* free audio sub-components */ - for (u = 0; u < 7; u++) { + for (u = 0; u < SMK_AUDIO_TRACKS; u++) { +#ifdef FULL if (s->audio[u].buffer) smk_free(s->audio[u].buffer); +#else + free(s->audio[u].buffer); +#endif } #ifdef FULL @@ -1206,14 +1331,16 @@ void smk_close(smk s) } else { #endif /* mem-mode */ - if (s->source.chunk_data != NULL) { #ifdef FULL_ORIG + if (s->source.chunk_data != NULL) { for (u = 0; u < (s->f + s->ring_frame); u++) smk_free(s->source.chunk_data[u]); -#endif smk_free(s->source.chunk_data); } +#else + free(s->source.chunk_data); +#endif #ifdef FULL } #endif @@ -1336,7 +1463,7 @@ char smk_info_audio(const smk object, unsigned char * track_mask, unsigned char return 0; } #else -void smk_info_audio(const smk object, unsigned char* channels, unsigned char* bitdepth, unsigned long* audio_rate) +void smk_info_audio(const smk object, unsigned char * channels, unsigned char * bitdepth, unsigned long * audio_rate) { *channels = object->audio[0].channels; *bitdepth = object->audio[0].bitdepth; @@ -1617,7 +1744,7 @@ static char smk_render_video(struct smk_video_t * s, unsigned char * p, unsigned smk_bs_init(&bs, p, size); /* Reset the cache on all bigtrees */ - for (i = 0; i < 4; i++) + for (i = 0; i < SMK_TREE_COUNT; i++) memset(&s->tree[i].cache, 0, 3 * sizeof(unsigned short)); while (row < s->h) { @@ -1975,9 +2102,9 @@ static char smk_render_audio(struct smk_audio_t * s, unsigned char * p, unsigned } } #else - if (!bit) + if (!bit) { LogErrorMsg("libsmacker::smk_render_audio() - ERROR: initial get_bit returned 0\n"); - + } if ((bit = smk_bs_read_1(&bs)) < 0) { LogErrorMsg("libsmacker::smk_render_audio() - ERROR: channels_bit returned -1\n"); #if DEBUG_MODE @@ -1986,9 +2113,9 @@ static char smk_render_audio(struct smk_audio_t * s, unsigned char * p, unsigned } bitdepth = s->bitdepth; channels = s->channels; - if (channels != (bit == 1 ? 2 : 1)) + if (channels != (bit == 1 ? 2 : 1)) { LogErrorMsg("libsmacker::smk_render_audio() - ERROR: mono/stereo mismatch\n"); - + } if ((bit = smk_bs_read_1(&bs)) < 0) { LogErrorMsg("libsmacker::smk_render_audio() - ERROR: bitdepth_bit returned -1\n"); #if DEBUG_MODE @@ -1996,9 +2123,9 @@ static char smk_render_audio(struct smk_audio_t * s, unsigned char * p, unsigned #endif } - if (bitdepth != (bit == 1 ? 16 : 8)) + if (bitdepth != (bit == 1 ? 16 : 8)) { LogErrorMsg("libsmacker::smk_render_audio() - ERROR: 8-/16-bit mismatch\n"); - + } /* build the trees */ smk_huff8_build(&aud_tree[0], &bs); @@ -2024,8 +2151,9 @@ static char smk_render_audio(struct smk_audio_t * s, unsigned char * p, unsigned if (bitdepth == 16) { unpack2 = smk_bs_read_8(&bs); ((uint16_t *)cur_buf)[1] = unpack2 | ((uint16_t)unpack << 8); - } else + } else { ((uint8_t *)cur_buf)[1] = unpack; + } } unpack = smk_bs_read_8(&bs); @@ -2034,8 +2162,9 @@ static char smk_render_audio(struct smk_audio_t * s, unsigned char * p, unsigned unpack2 = smk_bs_read_8(&bs); ((uint16_t *)cur_buf)[0] = unpack2 | ((uint16_t)unpack << 8); - } else + } else { ((uint8_t *)cur_buf)[0] = unpack; + } cur_buf += offset; @@ -2090,7 +2219,6 @@ static char smk_render(smk s) goto error; #endif } - #ifdef FULL if (s->mode == SMK_MODE_DISK) { /* Skip to frame in file */ @@ -2161,7 +2289,7 @@ static char smk_render(smk s) } /* Unpack audio chunks */ - for (track = 0; track < 7; track ++) { + for (track = 0; track < SMK_AUDIO_TRACKS; track ++) { if (s->frame_type[s->cur_frame] & (0x02 << track)) { /* need at least 4 byte to process */ if (i < 4) { @@ -2187,6 +2315,7 @@ static char smk_render(smk s) goto error; #endif } + /* If audio rendering enabled, kick this off for decode. */ if (s->audio[track].enable) { if (size < 4) { From 15407eb5c0ac3e5af6c15ac42b5d946a236d0e36 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 3 Feb 2024 09:42:45 +0100 Subject: [PATCH 259/596] optimize the audio-mixer - do not include scalar converters if not necessary - do not check whether SSE2 is available if it is guaranteed --- 3rdParty/SDL2_mixer/src/effect_position.c | 134 +++++++++++++--------- 3rdParty/SDL2_mixer/src/utils.c | 60 +++++++--- 2 files changed, 123 insertions(+), 71 deletions(-) diff --git a/3rdParty/SDL2_mixer/src/effect_position.c b/3rdParty/SDL2_mixer/src/effect_position.c index b7048259c9f..27607842be0 100644 --- a/3rdParty/SDL2_mixer/src/effect_position.c +++ b/3rdParty/SDL2_mixer/src/effect_position.c @@ -33,6 +33,25 @@ #define MIX_INTERNAL_EFFECT__ #include "effects_internal.h" +#ifndef FULL + +#ifdef __SSE2__ +#define HAVE_SSE2_INTRINSICS +#endif + +#if defined(__x86_64__) && defined(HAVE_SSE2_INTRINSICS) +#define NEED_SCALAR_CONVERTER_FALLBACKS 0 /* x86_64 guarantees SSE2. */ +#elif defined(__MACOSX__) && defined(HAVE_SSE2_INTRINSICS) +#define NEED_SCALAR_CONVERTER_FALLBACKS 0 /* Mac OS X/Intel guarantees SSE2. */ +#endif + +/* Set to zero if platform is guaranteed to use a SIMD codepath here. */ +#ifndef NEED_SCALAR_CONVERTER_FALLBACKS +#define NEED_SCALAR_CONVERTER_FALLBACKS 1 +#endif + +#endif // FULL + /* profile code: #include #include @@ -48,9 +67,9 @@ */ -/* - * Positional effects...panning, distance attenuation, etc. - */ +/* + * Positional effects...panning, distance attenuation, etc. + */ #ifdef FULL // FIX_EFF static _Mix_EffectPosArgs **pos_args_array = NULL; @@ -59,10 +78,10 @@ static _Mix_EffectPosArgs *pos_args_global = NULL; #endif static int position_channels = 0; #endif // FULL - FIX_EFF -static SDL_bool _Eff_volume_s16lbs(void* stream, unsigned len, void* udata); -static SDL_bool (*_Eff_do_volume_s16lbs)(void* stream, unsigned len, void* udata) = _Eff_volume_s16lbs; -static SDL_bool _Eff_position_s16lsb(void* stream, unsigned len, void* udata); -static SDL_bool (*_Eff_do_position_s16lsb)(void* stream, unsigned len, void* udata) = _Eff_position_s16lsb; + +/* Function pointers set to a CPU-specific implementation. */ +static SDL_bool (*_Eff_do_volume_s16lbs)(void* stream, unsigned len, void* udata) = NULL; +static SDL_bool (*_Eff_do_position_s16lsb)(void* stream, unsigned len, void* udata) = NULL; #ifdef FULL // FIX_EFF /* This just frees up the callback-specific data. */ @@ -89,8 +108,8 @@ static void SDLCALL _Eff_PositionDone(int channel, void *udata) static void SDLCALL _Eff_position_u8(int chan, void *stream, int len, void *udata) { Uint8 *ptr = (Uint8 *) stream; - const float dist_f = ((_Mix_EffectPosArgs *)udata)->distance_f; - const float left_f = ((_Mix_EffectPosArgs *)udata)->left_f; + const float dist_f = ((_Mix_EffectPosArgs *)udata)->distance_f; + const float left_f = ((_Mix_EffectPosArgs *)udata)->left_f; const float right_f = ((_Mix_EffectPosArgs *)udata)->right_f; int i; @@ -392,8 +411,8 @@ static void SDLCALL _Eff_position_table_u8(int chan, void *stream, int len, void static void SDLCALL _Eff_position_s8(int chan, void *stream, int len, void *udata) { Sint8 *ptr = (Sint8 *) stream; - const float dist_f = ((_Mix_EffectPosArgs *)udata)->distance_f; - const float left_f = ((_Mix_EffectPosArgs *)udata)->left_f; + const float dist_f = ((_Mix_EffectPosArgs *)udata)->distance_f; + const float left_f = ((_Mix_EffectPosArgs *)udata)->left_f; const float right_f = ((_Mix_EffectPosArgs *)udata)->right_f; int i; @@ -594,9 +613,9 @@ static void SDLCALL _Eff_position_table_s8(int chan, void *stream, int len, void static void SDLCALL _Eff_position_u16lsb(int chan, void *stream, int len, void *udata) { Uint16 *ptr = (Uint16 *) stream; - const SDL_bool opp = ((_Mix_EffectPosArgs *)udata)->room_angle == 180 ? SDL_TRUE : SDL_FALSE; - const float dist_f = ((_Mix_EffectPosArgs *)udata)->distance_f; - const float left_f = ((_Mix_EffectPosArgs *)udata)->left_f; + const SDL_bool opp = ((_Mix_EffectPosArgs *)udata)->room_angle == 180 ? SDL_TRUE : SDL_FALSE; + const float dist_f = ((_Mix_EffectPosArgs *)udata)->distance_f; + const float left_f = ((_Mix_EffectPosArgs *)udata)->left_f; const float right_f = ((_Mix_EffectPosArgs *)udata)->right_f; int i; @@ -751,16 +770,16 @@ static SDL_bool SDLCALL _Eff_position_s16lsb(void* stream, unsigned len, void* u /* 16 signed bits (lsb) * 2 channels. */ Sint16* ptr = (Sint16*)stream; #ifdef FULL // FIX_OUT - const SDL_bool opp = ((_Mix_EffectPosArgs *)udata)->room_angle == 180 ? SDL_TRUE : SDL_FALSE; - const float dist_f = ((_Mix_EffectPosArgs *)udata)->distance_f; -#endif + const SDL_bool opp = ((_Mix_EffectPosArgs *)udata)->room_angle == 180 ? SDL_TRUE : SDL_FALSE; + const float dist_f = ((_Mix_EffectPosArgs *)udata)->distance_f; +#endif #ifdef FULL // FIX_EFF - const float left_f = ((_Mix_EffectPosArgs *)udata)->left_f; + const float left_f = ((_Mix_EffectPosArgs *)udata)->left_f; const float right_f = ((_Mix_EffectPosArgs *)udata)->right_f; (void)chan; #else Mix_Channel* channel = (Mix_Channel*)udata; - //const float left_f = channel->effect.left_f * channel->volume / MIX_MAX_VOLUME; + //const float left_f = channel->effect.left_f * channel->volume / MIX_MAX_VOLUME; //const float right_f = channel->effect.right_f * channel->volume / MIX_MAX_VOLUME; //if (left_f < 1.0f / SDL_MAX_SINT16 && right_f < 1.0f / SDL_MAX_SINT16) // return SDL_FALSE; @@ -817,7 +836,7 @@ static SDL_bool SDLCALL _Eff_position_s16lsb(void* stream, unsigned len, void* u } return SDL_TRUE; } -#ifdef __SSE2__ +#ifdef HAVE_SSE2_INTRINSICS static SDL_bool SDLCALL _Eff_position_s16lsb_SSE2(void* stream, unsigned len, void* udata) { /* 16 signed bits (lsb) * 2 channels. */ @@ -851,7 +870,7 @@ static SDL_bool SDLCALL _Eff_position_s16lsb_SSE2(void* stream, unsigned len, vo } return SDL_TRUE; } -#endif // __SSE2__ +#endif // HAVE_SSE2_INTRINSICS #ifdef __AVX__ static SDL_bool SDLCALL _Eff_position_s16lsb_AVX(void* stream, unsigned len, void* udata) { @@ -898,15 +917,15 @@ static SDL_bool _Eff_volume_s16lbs(void* stream, unsigned len, void* udata) if (volume == MIX_MAX_VOLUME) return SDL_TRUE; len /= sizeof(Sint16); - while (len--) { - vol = SDL_SwapLE16(*ptr); - ADJUST_VOLUME(vol, volume); - *ptr = SDL_SwapLE16(vol); - ptr++; + while (len--) { + vol = SDL_SwapLE16(*ptr); + ADJUST_VOLUME(vol, volume); + *ptr = SDL_SwapLE16(vol); + ptr++; } return SDL_TRUE; } -#ifdef __SSE2__ +#ifdef HAVE_SSE2_INTRINSICS static SDL_bool _Eff_volume_s16lbs_SSE2(void* stream, unsigned len, void* udata) { /* 16 signed bits (lsb) * 2 channels. */ @@ -933,15 +952,15 @@ static SDL_bool _Eff_volume_s16lbs_SSE2(void* stream, unsigned len, void* udata) volume /= (1 << 16) / MIX_MAX_VOLUME; len /= sizeof(Sint16); - while (len--) { - vol = SDL_SwapLE16(*ptr); - ADJUST_VOLUME(vol, volume); - *ptr = SDL_SwapLE16(vol); - ptr++; - } + while (len--) { + vol = SDL_SwapLE16(*ptr); + ADJUST_VOLUME(vol, volume); + *ptr = SDL_SwapLE16(vol); + ptr++; + } return SDL_TRUE; } -#endif // __SSE2__ +#endif // HAVE_SSE2_INTRINSICS #ifdef __AVX__ static SDL_bool _Eff_volume_s16lbs_AVX(void* stream, unsigned len, void* udata) { @@ -969,12 +988,12 @@ static SDL_bool _Eff_volume_s16lbs_AVX(void* stream, unsigned len, void* udata) volume /= (1 << 16) / MIX_MAX_VOLUME; len /= sizeof(Sint16); - while (len--) { - vol = SDL_SwapLE16(*ptr); - ADJUST_VOLUME(vol, volume); - *ptr = SDL_SwapLE16(vol); - ptr++; - } + while (len--) { + vol = SDL_SwapLE16(*ptr); + ADJUST_VOLUME(vol, volume); + *ptr = SDL_SwapLE16(vol); + ptr++; + } return SDL_TRUE; } #endif // __AVX__ @@ -1089,9 +1108,9 @@ static void SDLCALL _Eff_position_u16msb(int chan, void *stream, int len, void * { /* 16 signed bits (lsb) * 2 channels. */ Uint16 *ptr = (Uint16 *) stream; - const SDL_bool opp = ((_Mix_EffectPosArgs *)udata)->room_angle == 180 ? SDL_TRUE : SDL_FALSE; - const float dist_f = ((_Mix_EffectPosArgs *)udata)->distance_f; - const float left_f = ((_Mix_EffectPosArgs *)udata)->left_f; + const SDL_bool opp = ((_Mix_EffectPosArgs *)udata)->room_angle == 180 ? SDL_TRUE : SDL_FALSE; + const float dist_f = ((_Mix_EffectPosArgs *)udata)->distance_f; + const float left_f = ((_Mix_EffectPosArgs *)udata)->left_f; const float right_f = ((_Mix_EffectPosArgs *)udata)->right_f; int i; @@ -1241,8 +1260,8 @@ static void SDLCALL _Eff_position_s16msb(int chan, void *stream, int len, void * { /* 16 signed bits (lsb) * 2 channels. */ Sint16 *ptr = (Sint16 *) stream; - const float dist_f = ((_Mix_EffectPosArgs *)udata)->distance_f; - const float left_f = ((_Mix_EffectPosArgs *)udata)->left_f; + const float dist_f = ((_Mix_EffectPosArgs *)udata)->distance_f; + const float left_f = ((_Mix_EffectPosArgs *)udata)->left_f; const float right_f = ((_Mix_EffectPosArgs *)udata)->right_f; int i; @@ -1369,9 +1388,9 @@ static void SDLCALL _Eff_position_s32lsb(int chan, void *stream, int len, void * { /* 32 signed bits (lsb) * 2 channels. */ Sint32 *ptr = (Sint32 *) stream; - const SDL_bool opp = ((_Mix_EffectPosArgs *)udata)->room_angle == 180 ? SDL_TRUE : SDL_FALSE; - const float dist_f = ((_Mix_EffectPosArgs *)udata)->distance_f; - const float left_f = ((_Mix_EffectPosArgs *)udata)->left_f; + const SDL_bool opp = ((_Mix_EffectPosArgs *)udata)->room_angle == 180 ? SDL_TRUE : SDL_FALSE; + const float dist_f = ((_Mix_EffectPosArgs *)udata)->distance_f; + const float left_f = ((_Mix_EffectPosArgs *)udata)->left_f; const float right_f = ((_Mix_EffectPosArgs *)udata)->right_f; int i; @@ -1510,8 +1529,8 @@ static void SDLCALL _Eff_position_s32msb(int chan, void *stream, int len, void * { /* 32 signed bits (lsb) * 2 channels. */ Sint32 *ptr = (Sint32 *) stream; - const float dist_f = ((_Mix_EffectPosArgs *)udata)->distance_f; - const float left_f = ((_Mix_EffectPosArgs *)udata)->left_f; + const float dist_f = ((_Mix_EffectPosArgs *)udata)->distance_f; + const float left_f = ((_Mix_EffectPosArgs *)udata)->left_f; const float right_f = ((_Mix_EffectPosArgs *)udata)->right_f; int i; @@ -1638,8 +1657,8 @@ static void SDLCALL _Eff_position_f32sys(int chan, void *stream, int len, void * { /* float * 2 channels. */ float *ptr = (float *) stream; - const float dist_f = ((_Mix_EffectPosArgs *)udata)->distance_f; - const float left_f = ((_Mix_EffectPosArgs *)udata)->left_f; + const float dist_f = ((_Mix_EffectPosArgs *)udata)->distance_f; + const float left_f = ((_Mix_EffectPosArgs *)udata)->left_f; const float right_f = ((_Mix_EffectPosArgs *)udata)->right_f; int i; @@ -2357,8 +2376,17 @@ int Mix_SetPosition(int channel, Sint16 angle, Uint8 distance) void _Eff_PositionInit(void) { -#ifdef __SSE2__ +#if NEED_SCALAR_CONVERTER_FALLBACKS + _Eff_do_volume_s16lbs = _Eff_volume_s16lbs; + _Eff_do_position_s16lsb = _Eff_position_s16lsb; +#endif +#ifdef HAVE_SSE2_INTRINSICS +#if NEED_SCALAR_CONVERTER_FALLBACKS if (SDL_HasSSE2()) { +#else + // SDL_assert(SDL_HasSSE2()); + if (1) { +#endif _Eff_do_volume_s16lbs = _Eff_volume_s16lbs_SSE2; _Eff_do_position_s16lsb = _Eff_position_s16lsb_SSE2; } diff --git a/3rdParty/SDL2_mixer/src/utils.c b/3rdParty/SDL2_mixer/src/utils.c index c7e1b820d1e..0d021c75f6b 100644 --- a/3rdParty/SDL2_mixer/src/utils.c +++ b/3rdParty/SDL2_mixer/src/utils.c @@ -26,18 +26,29 @@ #include #ifndef FULL // SELF_CONV +#ifdef __SSE2__ +#define HAVE_SSE2_INTRINSICS +#endif + +#if defined(__x86_64__) && defined(HAVE_SSE2_INTRINSICS) +#define NEED_SCALAR_CONVERTER_FALLBACKS 0 /* x86_64 guarantees SSE2. */ +#elif defined(__MACOSX__) && defined(HAVE_SSE2_INTRINSICS) +#define NEED_SCALAR_CONVERTER_FALLBACKS 0 /* Mac OS X/Intel guarantees SSE2. */ +#endif + +/* Set to zero if platform is guaranteed to use a SIMD codepath here. */ +#ifndef NEED_SCALAR_CONVERTER_FALLBACKS +#define NEED_SCALAR_CONVERTER_FALLBACKS 1 +#endif + +/* Function pointers set to a CPU-specific implementation. */ //void Mix_Converter_AUDIO8_Mono2Stereo(Mix_BuffOps* buf); -//void (*Mix_Convert_AUDIO8_Mono2Stereo)(Mix_BuffOps* buf) = Mix_Converter_AUDIO8_Mono2Stereo; -static void Mix_Converter_AUDIO16_Mono2Stereo(Mix_BuffOps* buf); -static void (*Mix_Convert_AUDIO16_Mono2Stereo)(Mix_BuffOps* buf) = Mix_Converter_AUDIO16_Mono2Stereo; -static void Mix_Converter_AUDIO8_Resample_Half(Mix_BuffOps* buf); -static void (*Mix_Convert_AUDIO8_Resample_Half)(Mix_BuffOps* buf) = Mix_Converter_AUDIO8_Resample_Half; -static void Mix_Converter_AUDIO16_Resample_Half(Mix_BuffOps* buf); -static void (*Mix_Convert_AUDIO16_Resample_Half)(Mix_BuffOps* buf) = Mix_Converter_AUDIO16_Resample_Half; -static void Mix_Converter_U8_S16LSB(Mix_BuffOps* buf); -static void (*Mix_Convert_U8_S16LSB)(Mix_BuffOps* buf) = Mix_Converter_U8_S16LSB; -void Mix_Mixer_AUDIOS16(void* dst, const void* src, unsigned len); -void (*Mix_MixAudioFormat)(void* dst, const void* src, unsigned len) = Mix_Mixer_AUDIOS16; +//void (*Mix_Convert_AUDIO8_Mono2Stereo)(Mix_BuffOps* buf) = NULL; +static void (*Mix_Convert_AUDIO16_Mono2Stereo)(Mix_BuffOps* buf) = NULL; +static void (*Mix_Convert_AUDIO8_Resample_Half)(Mix_BuffOps* buf) = NULL; +static void (*Mix_Convert_AUDIO16_Resample_Half)(Mix_BuffOps* buf) = NULL; +static void (*Mix_Convert_U8_S16LSB)(Mix_BuffOps* buf) = NULL; +void (*Mix_MixAudioFormat)(void* dst, const void* src, unsigned len) = NULL; #endif @@ -276,7 +287,7 @@ void Mix_Mixer_AUDIOS16(void* dst, const void* src, unsigned len) currPos++; } } -#ifdef __SSE2__ +#ifdef HAVE_SSE2_INTRINSICS void Mix_Mixer_AUDIOS16_SSE2(void* dst, const void* src, unsigned len) { const Sint16* srcPos = (const Sint16*)src; @@ -298,7 +309,7 @@ void Mix_Mixer_AUDIOS16_SSE2(void* dst, const void* src, unsigned len) Mix_Mixer_AUDIOS16(currPos, srcPos, len); } } -#endif // __SSE2__ +#endif // HAVE_SSE2_INTRINSICS #ifdef __AVX__ void Mix_Mixer_AUDIOS16_AVX(void* dst, const void* src, unsigned len) { @@ -355,7 +366,7 @@ void Mix_Converter_AUDIO16_Mono2Stereo_AVX(Mix_BuffOps* buf) } } #endif // __AVX__ -#ifdef __SSE2__ +#ifdef HAVE_SSE2_INTRINSICS void Mix_Converter_AUDIO16_Mono2Stereo_SSE2(Mix_BuffOps* buf) { Sint16* srcPos = (Sint16*)buf->endPos; @@ -402,7 +413,7 @@ void Mix_Converter_AUDIO16_Mono2Stereo(Mix_BuffOps* buf) } } -#ifdef __SSE2__ +#ifdef HAVE_SSE2_INTRINSICS void Mix_Converter_AUDIO8_Resample_Half_SSE2(Mix_BuffOps* buf) { Uint8* srcPos = (Uint8*)buf->currPos; @@ -451,7 +462,7 @@ void Mix_Converter_AUDIO8_Resample_Half(Mix_BuffOps* buf) } } -#ifdef __SSE2__ +#ifdef HAVE_SSE2_INTRINSICS void Mix_Converter_AUDIO16_Resample_Half_SSE2(Mix_BuffOps* buf) { Sint16* srcPos = (Sint16*)buf->currPos; @@ -544,7 +555,7 @@ void Mix_Converter_U8_S16LSB_AVX(Mix_BuffOps* buf) } } #endif // __AVX__ -#ifdef __SSE2__ +#ifdef HAVE_SSE2_INTRINSICS void Mix_Converter_U8_S16LSB_SSE2(Mix_BuffOps* buf) { Uint8* srcPos = (Uint8*)buf->endPos; @@ -600,8 +611,21 @@ void Mix_Converter_U8_S16LSB(Mix_BuffOps* buf) void Mix_Utils_Init() { -#ifdef __SSE2__ +#if NEED_SCALAR_CONVERTER_FALLBACKS + //Mix_Convert_AUDIO8_Mono2Stereo = Mix_Converter_AUDIO8_Mono2Stereo; + Mix_Convert_AUDIO16_Mono2Stereo = Mix_Converter_AUDIO16_Mono2Stereo; + Mix_Convert_AUDIO8_Resample_Half = Mix_Converter_AUDIO8_Resample_Half; + Mix_Convert_AUDIO16_Resample_Half = Mix_Converter_AUDIO16_Resample_Half; + Mix_MixAudioFormat = Mix_Mixer_AUDIOS16; + Mix_Convert_U8_S16LSB = Mix_Converter_U8_S16LSB; +#endif +#ifdef HAVE_SSE2_INTRINSICS +#if NEED_SCALAR_CONVERTER_FALLBACKS if (SDL_HasSSE2()) { +#else + // SDL_assert(SDL_HasSSE2()); + if (1) { +#endif //Mix_Convert_AUDIO8_Mono2Stereo = Mix_Converter_AUDIO8_Mono2Stereo_SSE2; Mix_Convert_AUDIO16_Mono2Stereo = Mix_Converter_AUDIO16_Mono2Stereo_SSE2; Mix_Convert_AUDIO8_Resample_Half = Mix_Converter_AUDIO8_Resample_Half_SSE2; From 35dec69a4f5ad4465ab753ddc9691c60993e5fd2 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 4 Feb 2024 09:24:18 +0100 Subject: [PATCH 260/596] update build.gradle of android - upgrade gradle-version - use the SDL2-template to define the cleaning task --- android-project/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android-project/build.gradle b/android-project/build.gradle index 250375c438c..9a83e3e989c 100644 --- a/android-project/build.gradle +++ b/android-project/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:8.2.0' + classpath 'com.android.tools.build:gradle:8.2.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -20,6 +20,6 @@ allprojects { } } -tasks.register('clean', Delete) { +task clean(type: Delete) { delete rootProject.buildDir } From 1bff93134150ee4ea69926c477fe7c3456e17d64 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 7 Feb 2024 08:32:23 +0100 Subject: [PATCH 261/596] fix vita build (except for network) --- CMakeLists.txt | 19 +++++++------------ Source/main.cpp | 2 ++ Source/platform/vita/network.cpp | 9 ++++++++- Source/platform/vita/random.cpp | 8 ++++++++ 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f5f8df1d0b4..08f94c02aa9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1007,19 +1007,14 @@ endif() if(VITA) target_link_libraries(${BIN_TARGET} PRIVATE ScePower_stub - SceNet_stub - SceNetCtl_stub - freetype - png - m - z - FLAC - vorbisfile - vorbis - ogg - mikmod - mpg123 + SceAppUtil_stub ) + if(NOT NONET) + target_link_libraries(${BIN_TARGET} PRIVATE + SceNet_stub + SceNetCtl_stub + ) + endif() #target_compile_definitions(${BIN_TARGET} PRIVATE VITA) endif() diff --git a/Source/main.cpp b/Source/main.cpp index 117256c9404..7433f3c1c3b 100644 --- a/Source/main.cpp +++ b/Source/main.cpp @@ -10,6 +10,8 @@ #endif #ifdef __vita__ #include +#include "platform/vita/network.h" +#include "platform/vita/random.hpp" #endif #ifdef RUN_TESTS #include diff --git a/Source/platform/vita/network.cpp b/Source/platform/vita/network.cpp index c55788c1d12..0eefc1ec476 100644 --- a/Source/platform/vita/network.cpp +++ b/Source/platform/vita/network.cpp @@ -1,7 +1,9 @@ +#include "platform/vita/network.h" + +#ifndef NONET #include #include #include -#include "platform/vita/network.h" #include #include #include @@ -30,3 +32,8 @@ void vita_enable_network() return; } } +#else +void vita_enable_network() +{ +} +#endif // !NONET \ No newline at end of file diff --git a/Source/platform/vita/random.cpp b/Source/platform/vita/random.cpp index 297959ed266..6c0576c4b7e 100644 --- a/Source/platform/vita/random.cpp +++ b/Source/platform/vita/random.cpp @@ -1,3 +1,6 @@ +#include "random.hpp" + +#ifndef NONET #include #include #include @@ -32,3 +35,8 @@ void randombytes_vitarandom_init() { randombytes_set_implementation(&randombytes_vitarandom_implementation); } +#else +void randombytes_vitarandom_init() +{ +} +#endif // !NONET \ No newline at end of file From 194b8809e73ac0c53593b9b35322bf5ec8ad52da Mon Sep 17 00:00:00 2001 From: Daniel Thamdrup Date: Mon, 5 Feb 2024 12:18:29 +0100 Subject: [PATCH 262/596] build vita in the nightly job Signed-off-by: Daniel Thamdrup --- .github/workflows/nightly.yml | 48 +++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 97e49f72cbf..20449b10be8 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -746,6 +746,54 @@ jobs: name: ${{ matrix.artifact }} path: build-ps4/devilutionx-ps4.pkg + # vita-builds + build_vita: + needs: build_check + if: ${{ needs.build_check.outputs.should_run != 'false' }} + name: Nightly-VITA + strategy: + fail-fast: false + matrix: + #name: [diablo, hellfire] + include: + - name: diablo + cmakeargs: '-DNONET=ON' + artifact: 'diablo-nightly-vita.vpk' + - name: hellfire + cmakeargs: '-DNONET=ON -DHELLFIRE=ON' + artifact: 'hellfire-nightly-vita.vpk' + - name: diablo-vita + cmakeargs: '-DNONET=ON -D USE_PATCH=ON' + artifact: 'diablo-nightly-vita.vpk' + - name: hellfire-vita + cmakeargs: '-DNONET=ON -D USE_PATCH=ON -DHELLFIRE=ON' + artifact: 'hellfire-nightly-vita.vpk' + runs-on: ubuntu-22.04 + container: vitasdk/vitasdk:latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Create Build Environment + run: apk add git ninja gettext + + - name: Configure CMake + run: | + cmake -S. -Bbuild -GNinja \ + -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} ${{ matrix.cmakeargs }} \ + -DCMAKE_TOOLCHAIN_FILE=${VITASDK}/share/vita.toolchain.cmake + + - name: Build + run: cmake --build build -j $(sysctl -n hw.physicalcpu) + + - name: Upload Package + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.artifact }} + path: ./build/devilutionx.vpk + # Releases release: needs: [build_check, build_msvc, build_mingw, build_mingw_x64, build_mac, build_ios, build_android, build_rg350, build_lepus, build_retrofw, build_ps4] From fe945355aad21bee4b96e8a5e3c18896eb0d79ee Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 7 Feb 2024 12:48:20 +0100 Subject: [PATCH 263/596] get rid of a pointless copy in SNetCreateGame --- Source/storm/storm_net.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Source/storm/storm_net.cpp b/Source/storm/storm_net.cpp index dbc0e586901..a1928dd1d0e 100644 --- a/Source/storm/storm_net.cpp +++ b/Source/storm/storm_net.cpp @@ -34,15 +34,12 @@ void SNetUnregisterEventHandler(int evtype) bool SNetCreateGame(unsigned port, const char* pszGamePassword, _uigamedata* gameData, char (&errorText)[256]) { bool result; - // assert(gameData != NULL && pszGamePassword != NULL); dvlnet_inst->make_default_gamename(gpszGameName); SStrCopy(gpszGamePassword, pszGamePassword, sizeof(gpszGamePassword)); result = dvlnet_inst->setup_game(gameData, gpszGameName, port, pszGamePassword, errorText); #ifdef ZEROTIER - if (port == 0) - SStrCopy(gpszGameName, gpszGameName, sizeof(gpszGameName)); - else + if (port != 0) #endif snprintf(gpszGameName, sizeof(gpszGameName), "%s:%d", gpszGameName, port); return result; From 19f1439fe4f1f4d98f6cc616c292661e17b151b5 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 7 Feb 2024 12:50:05 +0100 Subject: [PATCH 264/596] fix game-name when connecting to an address without port (port == 0) --- Source/storm/storm_net.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/storm/storm_net.cpp b/Source/storm/storm_net.cpp index a1928dd1d0e..57f29bd93e0 100644 --- a/Source/storm/storm_net.cpp +++ b/Source/storm/storm_net.cpp @@ -47,13 +47,13 @@ bool SNetCreateGame(unsigned port, const char* pszGamePassword, _uigamedata* gam bool SNetJoinGame(const char* pszGameName, unsigned port, const char* pszGamePassword, char (&errorText)[256]) { + const char* format = "%s:%d"; // assert(pszGameName != NULL && pszGamePassword != NULL); #ifdef ZEROTIER if (port == 0) - SStrCopy(gpszGameName, gpszGameName, sizeof(gpszGameName)); - else + format = "%s"; #endif - snprintf(gpszGameName, sizeof(gpszGameName), "%s:%d", pszGameName, port); + snprintf(gpszGameName, sizeof(gpszGameName), format, pszGameName, port); SStrCopy(gpszGamePassword, pszGamePassword, sizeof(gpszGamePassword)); return dvlnet_inst->setup_game(NULL, pszGameName, port, pszGamePassword, errorText); } From f427fa86590ae27b5e1aed0d2cb54d94dbb8d1be Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 7 Feb 2024 12:54:46 +0100 Subject: [PATCH 265/596] fix compilation on big-endian systems --- Source/town.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/town.cpp b/Source/town.cpp index 6d23d5f85fc..f6436c1c574 100644 --- a/Source/town.cpp +++ b/Source/town.cpp @@ -67,7 +67,7 @@ static void LoadTown() uint32_t* pBuf = (uint32_t*)LoadFileInMem(TOWN_PREDUN); int* dp = &dPiece[0][0]; uint32_t* pTmp = pBuf; - for (x = 0; x < MAXDUNX * MAXDUNY; x++, dp++, pTmp++) + for (int x = 0; x < MAXDUNX * MAXDUNY; x++, dp++, pTmp++) *dp = SwapLE32(*pTmp); mem_free_dbg(pBuf); From b9efd6d3ac2464778bc05d27fdc5c0347d4d72c5 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 7 Feb 2024 12:56:25 +0100 Subject: [PATCH 266/596] use appropriate type for stream_end when CAN_SEEKP_BEYOND_EOF is not set --- Source/mpqapi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/mpqapi.cpp b/Source/mpqapi.cpp index f4b8c758258..796eb37b2de 100644 --- a/Source/mpqapi.cpp +++ b/Source/mpqapi.cpp @@ -579,7 +579,7 @@ static bool mpqapi_write_file_contents(const char* pszName, const BYTE* pbData, goto on_error; #else // Ensure we do not seekp beyond EOF by filling the missing space. - std::streampos stream_end; + long stream_end; if (!cur_archive.stream.seekp(0, SEEK_END) || !cur_archive.stream.tellp(&stream_end)) goto on_error; std::size_t curSize = stream_end - cur_archive.stream_begin; From f34eecc153b0ead6473a9bdf65876e166fc3cbb8 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 8 Feb 2024 09:22:23 +0100 Subject: [PATCH 267/596] fix n3ds build --- Source/platform/ctr/asio/net/if.c | 2 ++ Source/platform/ctr/asio/sys/socket.c | 2 ++ Source/platform/ctr/asio/sys/uio.c | 2 ++ Source/platform/ctr/keyboard.cpp | 4 ++-- Source/platform/ctr/messagebox.cpp | 3 ++- Source/platform/ctr/random.cpp | 7 +++++++ Source/platform/ctr/sockets.cpp | 13 ++++++++++++- Source/platform/ctr/system.cpp | 4 ++-- structs.h | 6 ++++++ 9 files changed, 37 insertions(+), 6 deletions(-) diff --git a/Source/platform/ctr/asio/net/if.c b/Source/platform/ctr/asio/net/if.c index 910cb557701..4e72fa6e42f 100644 --- a/Source/platform/ctr/asio/net/if.c +++ b/Source/platform/ctr/asio/net/if.c @@ -1,3 +1,4 @@ +#ifdef TCPIP #include #include #include @@ -20,3 +21,4 @@ struct if_nameindex *if_nameindex() void if_freenameindex(struct if_nameindex *__ptr) { } +#endif \ No newline at end of file diff --git a/Source/platform/ctr/asio/sys/socket.c b/Source/platform/ctr/asio/sys/socket.c index 30710ec6646..c1dfaa492ef 100644 --- a/Source/platform/ctr/asio/sys/socket.c +++ b/Source/platform/ctr/asio/sys/socket.c @@ -1,3 +1,4 @@ +#ifdef TCPIP #include #include #include @@ -106,3 +107,4 @@ int socketpair(int domain, int type, int protocol, int socket_vector[2]) { return ENOTSUP; } +#endif \ No newline at end of file diff --git a/Source/platform/ctr/asio/sys/uio.c b/Source/platform/ctr/asio/sys/uio.c index 4d6b74a1728..352b862928f 100644 --- a/Source/platform/ctr/asio/sys/uio.c +++ b/Source/platform/ctr/asio/sys/uio.c @@ -1,3 +1,4 @@ +#ifdef TCPIP #include #include #include @@ -11,3 +12,4 @@ ssize_t writev(int __fd, const struct iovec *__iovec, int __count) { return ENOTSUP; } +#endif \ No newline at end of file diff --git a/Source/platform/ctr/keyboard.cpp b/Source/platform/ctr/keyboard.cpp index 4b56b18df49..96882947c6d 100644 --- a/Source/platform/ctr/keyboard.cpp +++ b/Source/platform/ctr/keyboard.cpp @@ -13,7 +13,7 @@ struct vkbdEvent { }; static vkbdEvent events[16]; -static int eventCount = 0; +static unsigned eventCount = 0; void ctr_vkbdInput(const char *hintText, const char *inText, char *outText, int maxLength) { @@ -30,7 +30,7 @@ void ctr_vkbdInput(const char *hintText, const char *inText, char *outText, int void ctr_vkbdFlush() { - for (int i = 0; i < eventCount; i++) { + for (unsigned i = 0; i < eventCount; i++) { vkbdEvent &event = events[i]; SwkbdState swkbd; diff --git a/Source/platform/ctr/messagebox.cpp b/Source/platform/ctr/messagebox.cpp index cee9d1b2e05..bfca1bd5620 100644 --- a/Source/platform/ctr/messagebox.cpp +++ b/Source/platform/ctr/messagebox.cpp @@ -1,6 +1,7 @@ #include <3ds.h> #include #include "utils/sdl2_to_1_2_backports.h" +#include "utils/log.h" int SDL_ShowSimpleMessageBox(Uint32 flags, const char *title, @@ -13,7 +14,7 @@ int SDL_ShowSimpleMessageBox(Uint32 flags, bool init = !gspHasGpuRight(); char text[1024]; - snprintf(text, sizeof(text), "%s\n\n%s", title, message) + snprintf(text, sizeof(text), "%s\n\n%s", title, message); if (init) gfxInitDefault(); diff --git a/Source/platform/ctr/random.cpp b/Source/platform/ctr/random.cpp index c18b4944114..aa566ee4be2 100644 --- a/Source/platform/ctr/random.cpp +++ b/Source/platform/ctr/random.cpp @@ -1,3 +1,5 @@ +#include "random.hpp" +#ifndef NONET #include #include #include <3ds.h> @@ -46,3 +48,8 @@ void randombytes_ctrrandom_init() { randombytes_set_implementation(&randombytes_ctrrandom_implementation); } +#else +void randombytes_ctrrandom_init() +{ +} +#endif // !NONET \ No newline at end of file diff --git a/Source/platform/ctr/sockets.cpp b/Source/platform/ctr/sockets.cpp index a3157540344..bc4909fc453 100644 --- a/Source/platform/ctr/sockets.cpp +++ b/Source/platform/ctr/sockets.cpp @@ -1,5 +1,9 @@ +#include "sockets.hpp" +#ifndef NONET #include +#include #include <3ds.h> +#include "utils/log.h" constexpr auto SOC_ALIGN = 0x1000; constexpr auto SOC_BUFFERSIZE = 0x100000; @@ -59,4 +63,11 @@ void n3ds_socInit() atexit([]() { n3ds_socExit(); }); initialized = true; } - +#else +void n3ds_socExit() +{ +} +void n3ds_socInit() +{ +} +#endif // !NONET \ No newline at end of file diff --git a/Source/platform/ctr/system.cpp b/Source/platform/ctr/system.cpp index 815acb36e63..15ca6d97c39 100644 --- a/Source/platform/ctr/system.cpp +++ b/Source/platform/ctr/system.cpp @@ -1,7 +1,7 @@ #include <3ds.h> #include #include -#include "platform/ctr/cfgu_service.hpp +#include "platform/ctr/cfgu_service.hpp" #include "platform/ctr/random.hpp" #include "platform/ctr/sockets.hpp" #include "platform/ctr/system.h" @@ -78,7 +78,7 @@ bool ctr_is_n3ds() bool ctr_should_disable_backlight() { - n3ds::CFGUService cfguService; + dvl::n3ds::CFGUService cfguService; if (!cfguService.IsInitialized()) return false; diff --git a/structs.h b/structs.h index e078f5c79f2..6e678ba43c8 100644 --- a/structs.h +++ b/structs.h @@ -962,6 +962,9 @@ typedef struct LE_UINT32 { void operator=(unsigned val) { _value = SwapLE32(val); }; + void operator=(unsigned long val) { + _value = SwapLE32(val); + }; #if INT_MAX != INT32_MAX void operator=(uint32_t val) { _value = SwapLE32(val); @@ -988,6 +991,9 @@ typedef struct LE_INT32 { void operator=(int val) { _value = SwapLE32(val); }; + void operator=(long val) { + _value = SwapLE32(val); + }; #if INT_MAX != INT32_MAX void operator=(int32_t val) { _value = SwapLE32(val); From 6db9c7914e5859c3c1cc69d4a921fdd5a9c6bad4 Mon Sep 17 00:00:00 2001 From: Daniel Thamdrup Date: Tue, 6 Feb 2024 13:44:58 +0100 Subject: [PATCH 268/596] build 3ds in the nightly job Signed-off-by: Daniel Thamdrup --- .github/workflows/nightly.yml | 77 ++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 20449b10be8..db7acfbf32a 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -764,10 +764,10 @@ jobs: artifact: 'hellfire-nightly-vita.vpk' - name: diablo-vita cmakeargs: '-DNONET=ON -D USE_PATCH=ON' - artifact: 'diablo-nightly-vita.vpk' + artifact: 'diablo-nightly-vitap.vpk' - name: hellfire-vita cmakeargs: '-DNONET=ON -D USE_PATCH=ON -DHELLFIRE=ON' - artifact: 'hellfire-nightly-vita.vpk' + artifact: 'hellfire-nightly-vitap.vpk' runs-on: ubuntu-22.04 container: vitasdk/vitasdk:latest steps: @@ -794,6 +794,79 @@ jobs: name: ${{ matrix.artifact }} path: ./build/devilutionx.vpk + # 3ds-builds + build_n3ds: + needs: build_check + if: ${{ needs.build_check.outputs.should_run != 'false' }} + name: Nightly-Nintendo 3DS + strategy: + fail-fast: false + matrix: + #name: [diablo, hellfire] + include: + - name: diablo + cmakeargs: '-DNONET=ON' + artifact: 'diablo-nightly-3ds.3dsx' + cia: 'diablo-nightly-3ds.cia' + - name: hellfire + cmakeargs: '-DNONET=ON -DHELLFIRE=ON' + artifact: 'hellfire-nightly-3ds.3dsx' + cia: 'hellfire-nightly-3ds.cia' + - name: diablo-3ds + cmakeargs: '-DNONET=ON -D USE_PATCH=ON' + artifact: 'diablo-nightly-3dsp.3dsx' + cia: 'diablo-nightly-3dsp.cia' + - name: hellfire-3ds + cmakeargs: '-DNONET=ON -D USE_PATCH=ON -DHELLFIRE=ON' + artifact: 'hellfire-nightly-3dsp.3dsx' + cia: 'hellfire-nightly-3dsp.cia' + runs-on: ubuntu-22.04 + container: devkitpro/devkitarm:latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install dependencies + run: | + apt-get update && \ + apt-get install -y --no-install-recommends --no-install-suggests \ + ffmpeg \ + gettext + + - name: Get external dependencies + run: | + wget https://github.com/diasurgical/bannertool/releases/download/1.2.0/bannertool.zip + unzip -j "bannertool.zip" "linux-x86_64/bannertool" -d "/opt/devkitpro/tools/bin" + wget https://github.com/3DSGuy/Project_CTR/releases/download/makerom-v0.18/makerom-v0.18-ubuntu_x86_64.zip + unzip "makerom-v0.18-ubuntu_x86_64.zip" "makerom" -d "/opt/devkitpro/tools/bin" + chmod a+x /opt/devkitpro/tools/bin/makerom + + - name: Configure CMake + run: | + cmake -S. -Bbuild -GNinja \ + -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DNINTENDO_3DS=ON \ + -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/3DS.cmake + + - name: Build DevilutionX + run: cmake --build build -j$(nproc) + + - name: Upload + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.artifact }} + path: | + ./build/devilutionx.3dsx + + - name: Upload + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.cia }} + path: | + ./build/devilutionx.cia + # Releases release: needs: [build_check, build_msvc, build_mingw, build_mingw_x64, build_mac, build_ios, build_android, build_rg350, build_lepus, build_retrofw, build_ps4] From fe3261ae7703d47e676acf39a8adcad4c0e8829b Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 8 Feb 2024 09:38:36 +0100 Subject: [PATCH 269/596] fix amiga build --- Source/storm/storm.cpp | 5 ++- structs.h | 75 ++++++++++++++++++++++-------------------- 2 files changed, 44 insertions(+), 36 deletions(-) diff --git a/Source/storm/storm.cpp b/Source/storm/storm.cpp index 8b042a003be..b8d25391711 100644 --- a/Source/storm/storm.cpp +++ b/Source/storm/storm.cpp @@ -88,9 +88,12 @@ HANDLE SFileOpenFile(const char* filename) void SStrCopy(char* dest, const char* src, int max_length) { +#ifndef __AMIGA__ if (memccpy(dest, src, '\0', max_length) == NULL) dest[max_length - 1] = '\0'; - //strncpy(dest, src, max_length); +#else + strncpy(dest, src, max_length); +#endif } void SFileEnableDirectAccess(bool enable) diff --git a/structs.h b/structs.h index 6e678ba43c8..f03ef5285b8 100644 --- a/structs.h +++ b/structs.h @@ -3,11 +3,16 @@ * * Various global structures. */ +#ifndef _STRUCTS_H +#define _STRUCTS_H DEVILUTION_BEGIN_NAMESPACE -#ifndef _STRUCTS_H -#define _STRUCTS_H +#ifndef __AMIGA__ +#define static_warning(x, msg) static_assert(x, msg) +#else +#define static_warning(x, msg) +#endif #if INT_MAX == INT32_MAX && INTPTR_MAX == INT32_MAX #define X86_32bit_COMP @@ -136,7 +141,7 @@ typedef struct UniqItemData { } UniqItemData; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) -static_assert((sizeof(UniqItemData) & (sizeof(UniqItemData) - 1)) == 64, "Align UniqItemData to power of 2 for better performance."); +static_warning((sizeof(UniqItemData) & (sizeof(UniqItemData) - 1)) == 64, "Align UniqItemData to power of 2 for better performance."); #endif typedef struct ItemFileData { @@ -148,7 +153,7 @@ typedef struct ItemFileData { } ItemFileData; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) -static_assert((sizeof(ItemFileData) & (sizeof(ItemFileData) - 1)) == 0, "Align ItemFileData to power of 2 for better performance."); +static_warning((sizeof(ItemFileData) & (sizeof(ItemFileData) - 1)) == 0, "Align ItemFileData to power of 2 for better performance."); #endif typedef struct ItemData { @@ -178,7 +183,7 @@ typedef struct ItemData { } ItemData; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) -static_assert((sizeof(ItemData) & (sizeof(ItemData) - 1)) == 0, "Align ItemData to power of 2 for better performance."); +static_warning((sizeof(ItemData) & (sizeof(ItemData) - 1)) == 0, "Align ItemData to power of 2 for better performance."); #endif typedef struct ItemStruct { @@ -266,7 +271,7 @@ typedef struct ItemStruct { } ItemStruct; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) -static_assert((sizeof(ItemStruct) & (sizeof(ItemStruct) - 1)) == 0, "Align ItemStruct closer to power of 2 for better performance."); +static_warning((sizeof(ItemStruct) & (sizeof(ItemStruct) - 1)) == 0, "Align ItemStruct closer to power of 2 for better performance."); #endif ////////////////////////////////////////////////// @@ -279,7 +284,7 @@ typedef struct PlrAnimType { } PlrAnimType; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) -static_assert((sizeof(PlrAnimType) & (sizeof(PlrAnimType) - 1)) == 0, "Align PlrAnimType closer to power of 2 for better performance."); +static_warning((sizeof(PlrAnimType) & (sizeof(PlrAnimType) - 1)) == 0, "Align PlrAnimType closer to power of 2 for better performance."); #endif typedef struct PlrAnimStruct { @@ -288,9 +293,9 @@ typedef struct PlrAnimStruct { int paAnimWidth; } PlrAnimStruct; #ifdef X86_32bit_COMP -static_assert((sizeof(PlrAnimStruct) & (sizeof(PlrAnimStruct) - 1)) == 32, "Align PlrAnimStruct closer to power of 2 for better performance."); +static_warning((sizeof(PlrAnimStruct) & (sizeof(PlrAnimStruct) - 1)) == 32, "Align PlrAnimStruct closer to power of 2 for better performance."); #elif defined(X86_64bit_COMP) -static_assert((sizeof(PlrAnimStruct) & (sizeof(PlrAnimStruct) - 1)) == 64, "Align PlrAnimStruct closer to power of 2 for better performance."); +static_warning((sizeof(PlrAnimStruct) & (sizeof(PlrAnimStruct) - 1)) == 64, "Align PlrAnimStruct closer to power of 2 for better performance."); #endif typedef struct PlayerStruct { @@ -445,7 +450,7 @@ typedef struct PlayerStruct { } PlayerStruct; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) -static_assert((sizeof(PlayerStruct) & (sizeof(PlayerStruct) - 1)) == 0, "Align PlayerStruct closer to power of 2 for better performance."); +static_warning((sizeof(PlayerStruct) & (sizeof(PlayerStruct) - 1)) == 0, "Align PlayerStruct closer to power of 2 for better performance."); #endif ////////////////////////////////////////////////// @@ -479,7 +484,7 @@ typedef struct MissileData { } MissileData; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) -static_assert((sizeof(MissileData) & (sizeof(MissileData) - 1)) == 0, "Align MissileData to power of 2 for better performance."); +static_warning((sizeof(MissileData) & (sizeof(MissileData) - 1)) == 0, "Align MissileData to power of 2 for better performance."); #endif typedef struct MisFileData { @@ -494,7 +499,7 @@ typedef struct MisFileData { ALIGNMENT(2, 14) } MisFileData; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) -static_assert((sizeof(MisFileData) & (sizeof(MisFileData) - 1)) == 0, "Align MisFileData to power of 2 for better performance."); +static_warning((sizeof(MisFileData) & (sizeof(MisFileData) - 1)) == 0, "Align MisFileData to power of 2 for better performance."); #endif typedef struct MissileStruct { @@ -547,9 +552,9 @@ typedef struct MissileStruct { } MissileStruct; #ifdef X86_32bit_COMP -static_assert((sizeof(MissileStruct) & (sizeof(MissileStruct) - 1)) == 128, "Align MissileStruct closer to power of 2 for better performance."); +static_warning((sizeof(MissileStruct) & (sizeof(MissileStruct) - 1)) == 128, "Align MissileStruct closer to power of 2 for better performance."); #elif defined(X86_64bit_COMP) -static_assert((sizeof(MissileStruct) & (sizeof(MissileStruct) - 1)) == 0, "Align MissileStruct closer to power of 2 for better performance."); +static_warning((sizeof(MissileStruct) & (sizeof(MissileStruct) - 1)) == 0, "Align MissileStruct closer to power of 2 for better performance."); #endif ////////////////////////////////////////////////// @@ -588,9 +593,9 @@ typedef struct MonAnimStruct { int maFrameLen; } MonAnimStruct; #ifdef X86_32bit_COMP -static_assert((sizeof(MonAnimStruct) & (sizeof(MonAnimStruct) - 1)) == 32, "Align MonAnimStruct closer to power of 2 for better performance."); +static_warning((sizeof(MonAnimStruct) & (sizeof(MonAnimStruct) - 1)) == 32, "Align MonAnimStruct closer to power of 2 for better performance."); #elif defined(X86_64bit_COMP) -static_assert((sizeof(MonAnimStruct) & (sizeof(MonAnimStruct) - 1)) == 64, "Align MonAnimStruct closer to power of 2 for better performance."); +static_warning((sizeof(MonAnimStruct) & (sizeof(MonAnimStruct) - 1)) == 64, "Align MonAnimStruct closer to power of 2 for better performance."); #endif typedef struct MonsterAI { @@ -626,7 +631,7 @@ typedef struct MonsterData { ALIGNMENT(5, 2) } MonsterData; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) -static_assert((sizeof(MonsterData) & (sizeof(MonsterData) - 1)) == 0, "Align MonsterData to power of 2 for better performance."); +static_warning((sizeof(MonsterData) & (sizeof(MonsterData) - 1)) == 0, "Align MonsterData to power of 2 for better performance."); #endif typedef struct MonFileData { @@ -641,9 +646,9 @@ typedef struct MonFileData { BYTE moAFNum2; } MonFileData; #ifdef X86_32bit_COMP -static_assert((sizeof(MonFileData) & (sizeof(MonFileData) - 1)) == 0, "Align MonFileData to power of 2 for better performance."); +static_warning((sizeof(MonFileData) & (sizeof(MonFileData) - 1)) == 0, "Align MonFileData to power of 2 for better performance."); #elif defined(X86_64bit_COMP) -static_assert((sizeof(MonFileData) & (sizeof(MonFileData) - 1)) == 64, "Align MonFileData to power of 2 for better performance."); +static_warning((sizeof(MonFileData) & (sizeof(MonFileData) - 1)) == 64, "Align MonFileData to power of 2 for better performance."); #endif #pragma pack(push, 1) typedef struct MapMonData { @@ -679,9 +684,9 @@ typedef struct MapMonData { ALIGNMENT(24, 17); } MapMonData; #ifdef X86_32bit_COMP -static_assert((sizeof(MapMonData) & (sizeof(MapMonData) - 1)) == 0, "Align MapMonData closer to power of 2 for better performance."); +static_warning((sizeof(MapMonData) & (sizeof(MapMonData) - 1)) == 0, "Align MapMonData closer to power of 2 for better performance."); #elif defined(X86_64bit_COMP) -static_assert((sizeof(MapMonData) & (sizeof(MapMonData) - 1)) == 512, "Align MapMonData closer to power of 2 for better performance."); +static_warning((sizeof(MapMonData) & (sizeof(MapMonData) - 1)) == 512, "Align MapMonData closer to power of 2 for better performance."); #endif #pragma pack(pop) typedef struct MonsterStruct { @@ -763,7 +768,7 @@ typedef struct MonsterStruct { } MonsterStruct; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) -static_assert((sizeof(MonsterStruct) & (sizeof(MonsterStruct) - 1)) == 0, "Align MonsterStruct to power of 2 for better performance."); +static_warning((sizeof(MonsterStruct) & (sizeof(MonsterStruct) - 1)) == 0, "Align MonsterStruct to power of 2 for better performance."); #endif typedef struct MonEnemyStruct { @@ -798,7 +803,7 @@ typedef struct UniqMonData { } UniqMonData; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) -static_assert((sizeof(UniqMonData) & (sizeof(UniqMonData) - 1)) == 0, "Align UniqMonData to power of 2 for better performance."); +static_warning((sizeof(UniqMonData) & (sizeof(UniqMonData) - 1)) == 0, "Align UniqMonData to power of 2 for better performance."); #endif ////////////////////////////////////////////////// @@ -833,7 +838,7 @@ typedef struct ObjectData { } ObjectData; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) -static_assert((sizeof(ObjectData) & (sizeof(ObjectData) - 1)) == 0, "Align ObjectData closer to power of 2 for better performance."); +static_warning((sizeof(ObjectData) & (sizeof(ObjectData) - 1)) == 0, "Align ObjectData closer to power of 2 for better performance."); #endif typedef struct ObjFileData { @@ -850,7 +855,7 @@ typedef struct ObjFileData { } ObjFileData; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) -static_assert((sizeof(ObjFileData) & (sizeof(ObjFileData) - 1)) == 0, "Align ObjFileData closer to power of 2 for better performance."); +static_warning((sizeof(ObjFileData) & (sizeof(ObjFileData) - 1)) == 0, "Align ObjFileData closer to power of 2 for better performance."); #endif typedef struct ObjectStruct { @@ -892,7 +897,7 @@ typedef struct ObjectStruct { } ObjectStruct; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) -static_assert((sizeof(ObjectStruct) & (sizeof(ObjectStruct) - 1)) == 0, "Align ObjectStruct to power of 2 for better performance."); +static_warning((sizeof(ObjectStruct) & (sizeof(ObjectStruct) - 1)) == 0, "Align ObjectStruct to power of 2 for better performance."); #endif ////////////////////////////////////////////////// @@ -907,7 +912,7 @@ typedef struct PortalStruct { } PortalStruct; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) -static_assert((sizeof(PortalStruct) & (sizeof(PortalStruct) - 1)) == 0, "Align PortalStruct closer to power of 2 for better performance."); +static_warning((sizeof(PortalStruct) & (sizeof(PortalStruct) - 1)) == 0, "Align PortalStruct closer to power of 2 for better performance."); #endif ////////////////////////////////////////////////// @@ -2118,9 +2123,9 @@ typedef struct LevelData { } LevelData; #ifdef X86_32bit_COMP -static_assert((sizeof(LevelData) & (sizeof(LevelData) - 1)) == 0, "Align LevelData to power of 2 for better performance."); +static_warning((sizeof(LevelData) & (sizeof(LevelData) - 1)) == 0, "Align LevelData to power of 2 for better performance."); #elif defined(X86_64bit_COMP) -static_assert((sizeof(LevelData) & (sizeof(LevelData) - 1)) == 64, "Align LevelData to power of 2 for better performance."); +static_warning((sizeof(LevelData) & (sizeof(LevelData) - 1)) == 64, "Align LevelData to power of 2 for better performance."); #endif typedef struct WarpStruct { @@ -2155,7 +2160,7 @@ typedef struct QuestStruct { } QuestStruct; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) -static_assert((sizeof(QuestStruct) & (sizeof(QuestStruct) - 1)) == 0, "Align QuestStruct to power of 2 for better performance."); +static_warning((sizeof(QuestStruct) & (sizeof(QuestStruct) - 1)) == 0, "Align QuestStruct to power of 2 for better performance."); #endif typedef struct QuestData { @@ -2210,7 +2215,7 @@ typedef struct SpellData { ALIGNMENT64(6) } SpellData; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) -static_assert((sizeof(SpellData) & (sizeof(SpellData) - 1)) == 0, "Align SpellData to power of 2 for better performance."); +static_warning((sizeof(SpellData) & (sizeof(SpellData) - 1)) == 0, "Align SpellData to power of 2 for better performance."); #endif ////////////////////////////////////////////////// @@ -2327,7 +2332,7 @@ typedef struct ThemeStruct { } ThemeStruct; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) -static_assert((sizeof(ThemeStruct) & (sizeof(ThemeStruct) - 1)) == 0, "Align ThemeStruct to power of 2 for better performance."); +static_warning((sizeof(ThemeStruct) & (sizeof(ThemeStruct) - 1)) == 0, "Align ThemeStruct to power of 2 for better performance."); #endif ////////////////////////////////////////////////// @@ -2361,7 +2366,7 @@ typedef struct LightListStruct { } LightListStruct; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) -static_assert((sizeof(LightListStruct) & (sizeof(LightListStruct) - 1)) == 0, "Align LightListStruct closer to power of 2 for better performance."); +static_warning((sizeof(LightListStruct) & (sizeof(LightListStruct) - 1)) == 0, "Align LightListStruct closer to power of 2 for better performance."); #endif ////////////////////////////////////////////////// @@ -2492,7 +2497,7 @@ typedef struct PATHNODE { } PATHNODE; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) -static_assert((sizeof(PATHNODE) & (sizeof(PATHNODE) - 1)) == 0, "Align PATHNODE closer to power of 2 for better performance."); +static_warning((sizeof(PATHNODE) & (sizeof(PATHNODE) - 1)) == 0, "Align PATHNODE closer to power of 2 for better performance."); #endif ////////////////////////////////////////////////// @@ -2582,7 +2587,7 @@ typedef struct STextStruct { } STextStruct; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) -static_assert((sizeof(STextStruct) & (sizeof(STextStruct) - 1)) == 0, "Align STextStruct closer to power of 2 for better performance."); +static_warning((sizeof(STextStruct) & (sizeof(STextStruct) - 1)) == 0, "Align STextStruct closer to power of 2 for better performance."); #endif ////////////////////////////////////////////////// From fb31f4278e4b37f427265e23287d5e0b754a501f Mon Sep 17 00:00:00 2001 From: Daniel Thamdrup Date: Tue, 6 Feb 2024 15:28:17 +0100 Subject: [PATCH 270/596] build amigam68k in the nightly job Signed-off-by: Daniel Thamdrup --- .github/workflows/nightly.yml | 63 ++++++++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index db7acfbf32a..88693dd717b 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -768,7 +768,7 @@ jobs: - name: hellfire-vita cmakeargs: '-DNONET=ON -D USE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-vitap.vpk' - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest container: vitasdk/vitasdk:latest steps: - name: Checkout @@ -792,9 +792,9 @@ jobs: uses: actions/upload-artifact@v4 with: name: ${{ matrix.artifact }} - path: ./build/devilutionx.vpk + path: build/devilutionx.vpk - # 3ds-builds + # n3ds-builds build_n3ds: needs: build_check if: ${{ needs.build_check.outputs.should_run != 'false' }} @@ -820,7 +820,7 @@ jobs: cmakeargs: '-DNONET=ON -D USE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-3dsp.3dsx' cia: 'hellfire-nightly-3dsp.cia' - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest container: devkitpro/devkitarm:latest steps: @@ -857,15 +857,62 @@ jobs: uses: actions/upload-artifact@v4 with: name: ${{ matrix.artifact }} - path: | - ./build/devilutionx.3dsx + path: build/devilutionx.3dsx - name: Upload uses: actions/upload-artifact@v4 with: name: ${{ matrix.cia }} - path: | - ./build/devilutionx.cia + path: build/devilutionx.cia + + # amiga-builds + build_amiga: + needs: build_check + if: ${{ needs.build_check.outputs.should_run != 'false' }} + name: Nightly-Amiga M68K + strategy: + fail-fast: false + matrix: + #name: [diablo, hellfire] + include: + - name: diablo + cmakeargs: '-DNONET=ON' + artifact: 'diablo-nightly-amiga' + - name: hellfire + cmakeargs: '-DNONET=ON -DHELLFIRE=ON' + artifact: 'hellfire-nightly-amiga' + - name: diablo-amiga + cmakeargs: '-DNONET=ON -D USE_PATCH=ON' + artifact: 'diablo-nightly-amigap' + - name: hellfire-amiga + cmakeargs: '-DNONET=ON -D USE_PATCH=ON -DHELLFIRE=ON' + artifact: 'hellfire-nightly-amigap' + runs-on: ubuntu-latest + container: amigadev/crosstools:m68k-amigaos-gcc10 + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Run prep.sh script + run: Packaging/amiga/prep.sh + + - name: Configure CMake + run: | + cmake -S. -Bbuild -GNinja \ + -DM68K_COMMON="-s -ffast-math -O3" \ + -DM68K_CPU=68040 \ + -DM68K_FPU=hard + + - name: Build DevilutionX + run: cmake --build build + + - name: Upload Package + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.artifact }} + path: ./build/devilutionx # Releases release: From 6de929c46b1484b284e04ffcb44ffef53cb3f3ed Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 8 Feb 2024 10:22:33 +0100 Subject: [PATCH 271/596] fix switch build --- Source/platform/switch/asio/net/if.c | 2 ++ Source/platform/switch/asio/pause.c | 4 +++- Source/platform/switch/asio/sys/signal.c | 2 ++ Source/platform/switch/docking.cpp | 2 ++ Source/platform/switch/docking.h | 2 ++ Source/platform/switch/network.cpp | 11 +++++++++++ Source/platform/switch/random.cpp | 8 ++++++++ 7 files changed, 30 insertions(+), 1 deletion(-) diff --git a/Source/platform/switch/asio/net/if.c b/Source/platform/switch/asio/net/if.c index 910cb557701..4e72fa6e42f 100644 --- a/Source/platform/switch/asio/net/if.c +++ b/Source/platform/switch/asio/net/if.c @@ -1,3 +1,4 @@ +#ifdef TCPIP #include #include #include @@ -20,3 +21,4 @@ struct if_nameindex *if_nameindex() void if_freenameindex(struct if_nameindex *__ptr) { } +#endif \ No newline at end of file diff --git a/Source/platform/switch/asio/pause.c b/Source/platform/switch/asio/pause.c index 2911968375a..d663ee7c09c 100644 --- a/Source/platform/switch/asio/pause.c +++ b/Source/platform/switch/asio/pause.c @@ -1,7 +1,9 @@ +#ifdef TCPIP #include int pause(void) { errno = ENOSYS; return -1; -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/Source/platform/switch/asio/sys/signal.c b/Source/platform/switch/asio/sys/signal.c index 4b9c394d48d..b5c3c99a7b0 100644 --- a/Source/platform/switch/asio/sys/signal.c +++ b/Source/platform/switch/asio/sys/signal.c @@ -1,3 +1,4 @@ +#ifdef TCPIP #include #include @@ -5,3 +6,4 @@ int pthread_sigmask(int, const sigset_t *, sigset_t *) { return ENOTSUP; } +#endif \ No newline at end of file diff --git a/Source/platform/switch/docking.cpp b/Source/platform/switch/docking.cpp index d70639c0cfb..ec70f41d613 100644 --- a/Source/platform/switch/docking.cpp +++ b/Source/platform/switch/docking.cpp @@ -3,6 +3,8 @@ #include #include +#include "utils/display.h" + DEVILUTION_BEGIN_NAMESPACE static int currently_docked = -1; // keep track of docked or handheld mode diff --git a/Source/platform/switch/docking.h b/Source/platform/switch/docking.h index 67348111ef1..235071f44e8 100644 --- a/Source/platform/switch/docking.h +++ b/Source/platform/switch/docking.h @@ -1,5 +1,7 @@ #pragma once +#include "../defs.h" + DEVILUTION_BEGIN_NAMESPACE void HandleDocking(); diff --git a/Source/platform/switch/network.cpp b/Source/platform/switch/network.cpp index 4526f1a619b..195d5797bc4 100644 --- a/Source/platform/switch/network.cpp +++ b/Source/platform/switch/network.cpp @@ -1,3 +1,6 @@ +#include "platform/switch/network.h" + +#ifndef NONET #include #include #include @@ -21,3 +24,11 @@ void switch_disable_network() close(nxlink_sock); socketExit(); } +#else +void switch_enable_network() +{ +} +void switch_disable_network() +{ +} +#endif \ No newline at end of file diff --git a/Source/platform/switch/random.cpp b/Source/platform/switch/random.cpp index 6c16d228cd8..651f788eec6 100644 --- a/Source/platform/switch/random.cpp +++ b/Source/platform/switch/random.cpp @@ -1,3 +1,6 @@ +#include "random.hpp" + +#ifndef NONET #include #include @@ -52,3 +55,8 @@ void randombytes_switchrandom_init() randombytes_set_implementation(&randombytes_switchrandom_implementation); atexit(csrngExit); } +#else +void randombytes_switchrandom_init() +{ +} +#endif // !NONET \ No newline at end of file From bda109953983458f3fd0ba326f2c03732d03e68b Mon Sep 17 00:00:00 2001 From: Daniel Thamdrup Date: Mon, 5 Feb 2024 21:28:10 +0100 Subject: [PATCH 272/596] build switch in the nightly job Signed-off-by: Daniel Thamdrup --- .github/workflows/nightly.yml | 55 +++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 88693dd717b..a6813f15cc0 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -865,6 +865,60 @@ jobs: name: ${{ matrix.cia }} path: build/devilutionx.cia + # switch-builds + build_switch: + needs: build_check + if: ${{ needs.build_check.outputs.should_run != 'false' }} + name: Nightly-Nintendo Switch + strategy: + fail-fast: false + matrix: + #name: [diablo, hellfire] + include: + - name: diablo + cmakeargs: '-DNONET=ON' + artifact: 'diablo-nightly-switch.nro' + - name: hellfire + cmakeargs: '-DNONET=ON -DHELLFIRE=ON' + artifact: 'hellfire-nightly-switch.nro' + - name: diablo-switch + cmakeargs: '-DNONET=ON -D USE_PATCH=ON' + artifact: 'diablo-nightly-switchp.nro' + - name: hellfire-switch + cmakeargs: '-DNONET=ON -D USE_PATCH=ON -DHELLFIRE=ON' + artifact: 'hellfire-nightly-switchp.nro' + runs-on: ubuntu-latest + container: devkitpro/devkita64:latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # - name: Create Build Environment + # run: brew bundle install + - name: Install dependencies + shell: bash + run: | + apt-get update && \ + apt-get install -y --no-install-recommends --no-install-suggests \ + gettext + + - name: Configure CMake + run: | + cmake -S . -B build \ + -D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \ + -D CMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake + + - name: Build DevilutionX + run: cmake --build build -j$(nproc) + + - name: Upload Package + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.artifact }} + path: ./build/devilutionx.nro + # amiga-builds build_amiga: needs: build_check @@ -901,6 +955,7 @@ jobs: - name: Configure CMake run: | cmake -S. -Bbuild -GNinja \ + -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \ -DM68K_COMMON="-s -ffast-math -O3" \ -DM68K_CPU=68040 \ -DM68K_FPU=hard From 554892a5f0a5c863194bba683e796105ef010729 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 9 Feb 2024 08:00:13 +0100 Subject: [PATCH 273/596] fix the new nightly builds --- .github/workflows/nightly.yml | 66 +++++++++++++++++------------------ 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index a6813f15cc0..875603e01b3 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -847,7 +847,7 @@ jobs: - name: Configure CMake run: | cmake -S. -Bbuild -GNinja \ - -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DNINTENDO_3DS=ON \ + -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} ${{ matrix.cmakeargs }} -DNINTENDO_3DS=ON \ -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/3DS.cmake - name: Build DevilutionX @@ -887,37 +887,37 @@ jobs: - name: hellfire-switch cmakeargs: '-DNONET=ON -D USE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-switchp.nro' - runs-on: ubuntu-latest - container: devkitpro/devkita64:latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - # - name: Create Build Environment - # run: brew bundle install - - name: Install dependencies - shell: bash - run: | - apt-get update && \ - apt-get install -y --no-install-recommends --no-install-suggests \ - gettext - - - name: Configure CMake - run: | - cmake -S . -B build \ - -D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \ - -D CMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake - - - name: Build DevilutionX - run: cmake --build build -j$(nproc) - - - name: Upload Package - uses: actions/upload-artifact@v4 - with: - name: ${{ matrix.artifact }} - path: ./build/devilutionx.nro + runs-on: ubuntu-latest + container: devkitpro/devkita64:latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # - name: Create Build Environment + # run: brew bundle install + - name: Install dependencies + shell: bash + run: | + apt-get update && \ + apt-get install -y --no-install-recommends --no-install-suggests \ + gettext + + - name: Configure CMake + run: | + cmake -S . -B build \ + -D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} ${{ matrix.cmakeargs }} \ + -D CMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake + + - name: Build DevilutionX + run: cmake --build build -j$(nproc) + + - name: Upload Package + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.artifact }} + path: ./build/devilutionx.nro # amiga-builds build_amiga: @@ -955,7 +955,7 @@ jobs: - name: Configure CMake run: | cmake -S. -Bbuild -GNinja \ - -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \ + -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} ${{ matrix.cmakeargs }} \ -DM68K_COMMON="-s -ffast-math -O3" \ -DM68K_CPU=68040 \ -DM68K_FPU=hard From 0d04cae2d07a67fca7589dcfb8dbc6494cf1dfdf Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 10 Feb 2024 08:30:33 +0100 Subject: [PATCH 274/596] apply fixes to the patcher --- tools/patcher/mpqapi.cpp | 2 +- tools/patcher/platform/ctr/keyboard.cpp | 4 ++-- tools/patcher/platform/ctr/messagebox.cpp | 3 ++- tools/patcher/platform/ctr/system.cpp | 4 ++-- tools/patcher/platform/switch/docking.cpp | 2 ++ tools/patcher/platform/switch/docking.h | 2 ++ tools/patcher/storm/storm.cpp | 5 ++++- 7 files changed, 15 insertions(+), 7 deletions(-) diff --git a/tools/patcher/mpqapi.cpp b/tools/patcher/mpqapi.cpp index f4b8c758258..796eb37b2de 100644 --- a/tools/patcher/mpqapi.cpp +++ b/tools/patcher/mpqapi.cpp @@ -579,7 +579,7 @@ static bool mpqapi_write_file_contents(const char* pszName, const BYTE* pbData, goto on_error; #else // Ensure we do not seekp beyond EOF by filling the missing space. - std::streampos stream_end; + long stream_end; if (!cur_archive.stream.seekp(0, SEEK_END) || !cur_archive.stream.tellp(&stream_end)) goto on_error; std::size_t curSize = stream_end - cur_archive.stream_begin; diff --git a/tools/patcher/platform/ctr/keyboard.cpp b/tools/patcher/platform/ctr/keyboard.cpp index 4b56b18df49..96882947c6d 100644 --- a/tools/patcher/platform/ctr/keyboard.cpp +++ b/tools/patcher/platform/ctr/keyboard.cpp @@ -13,7 +13,7 @@ struct vkbdEvent { }; static vkbdEvent events[16]; -static int eventCount = 0; +static unsigned eventCount = 0; void ctr_vkbdInput(const char *hintText, const char *inText, char *outText, int maxLength) { @@ -30,7 +30,7 @@ void ctr_vkbdInput(const char *hintText, const char *inText, char *outText, int void ctr_vkbdFlush() { - for (int i = 0; i < eventCount; i++) { + for (unsigned i = 0; i < eventCount; i++) { vkbdEvent &event = events[i]; SwkbdState swkbd; diff --git a/tools/patcher/platform/ctr/messagebox.cpp b/tools/patcher/platform/ctr/messagebox.cpp index cee9d1b2e05..bfca1bd5620 100644 --- a/tools/patcher/platform/ctr/messagebox.cpp +++ b/tools/patcher/platform/ctr/messagebox.cpp @@ -1,6 +1,7 @@ #include <3ds.h> #include #include "utils/sdl2_to_1_2_backports.h" +#include "utils/log.h" int SDL_ShowSimpleMessageBox(Uint32 flags, const char *title, @@ -13,7 +14,7 @@ int SDL_ShowSimpleMessageBox(Uint32 flags, bool init = !gspHasGpuRight(); char text[1024]; - snprintf(text, sizeof(text), "%s\n\n%s", title, message) + snprintf(text, sizeof(text), "%s\n\n%s", title, message); if (init) gfxInitDefault(); diff --git a/tools/patcher/platform/ctr/system.cpp b/tools/patcher/platform/ctr/system.cpp index 8ed89cb85f4..2e661509ede 100644 --- a/tools/patcher/platform/ctr/system.cpp +++ b/tools/patcher/platform/ctr/system.cpp @@ -1,7 +1,7 @@ #include <3ds.h> #include #include -#include "platform/ctr/cfgu_service.hpp +#include "platform/ctr/cfgu_service.hpp" #include "platform/ctr/system.h" bool shouldDisableBacklight; @@ -76,7 +76,7 @@ bool ctr_is_n3ds() bool ctr_should_disable_backlight() { - n3ds::CFGUService cfguService; + dvl::n3ds::CFGUService cfguService; if (!cfguService.IsInitialized()) return false; diff --git a/tools/patcher/platform/switch/docking.cpp b/tools/patcher/platform/switch/docking.cpp index d70639c0cfb..ec70f41d613 100644 --- a/tools/patcher/platform/switch/docking.cpp +++ b/tools/patcher/platform/switch/docking.cpp @@ -3,6 +3,8 @@ #include #include +#include "utils/display.h" + DEVILUTION_BEGIN_NAMESPACE static int currently_docked = -1; // keep track of docked or handheld mode diff --git a/tools/patcher/platform/switch/docking.h b/tools/patcher/platform/switch/docking.h index 67348111ef1..235071f44e8 100644 --- a/tools/patcher/platform/switch/docking.h +++ b/tools/patcher/platform/switch/docking.h @@ -1,5 +1,7 @@ #pragma once +#include "../defs.h" + DEVILUTION_BEGIN_NAMESPACE void HandleDocking(); diff --git a/tools/patcher/storm/storm.cpp b/tools/patcher/storm/storm.cpp index 17722b6b048..051fa25902a 100644 --- a/tools/patcher/storm/storm.cpp +++ b/tools/patcher/storm/storm.cpp @@ -83,9 +83,12 @@ HANDLE SFileOpenFile(const char* filename) void SStrCopy(char* dest, const char* src, int max_length) { +#ifndef __AMIGA__ if (memccpy(dest, src, '\0', max_length) == NULL) dest[max_length - 1] = '\0'; - //strncpy(dest, src, max_length); +#else + strncpy(dest, src, max_length); +#endif } void SFileEnableDirectAccess(bool enable) From 39f5e181b1f59686b701075ace9349507f68dc2e Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 10 Feb 2024 08:34:41 +0100 Subject: [PATCH 275/596] fix amiga/prep.sh --- Packaging/amiga/prep.sh | 110 ++++++++++++---------------------------- 1 file changed, 32 insertions(+), 78 deletions(-) diff --git a/Packaging/amiga/prep.sh b/Packaging/amiga/prep.sh index 50b1c7a010b..548c2e75cce 100755 --- a/Packaging/amiga/prep.sh +++ b/Packaging/amiga/prep.sh @@ -1,78 +1,32 @@ -#!/usr/bin/env bash - -# exit when any command fails -set -euo pipefail - -#set compiler params -export TARGET='m68k-amigaos' -export SYSROOT=/opt/$TARGET -export M68K_CPU=68040 -export M68K_FPU=hard -export M68K_CPU_FPU="-m${M68K_CPU} -m${M68K_FPU}-float" -export M68K_COMMON="-s -ffast-math -fomit-frame-pointer" -export M68K_CFLAGS="${M68K_CPU_FPU} ${M68K_COMMON}" -export M68K_CXXFLAGS="${M68K_CPU_FPU} ${M68K_COMMON}" - -PARALLELISM="$(getconf _NPROCESSORS_ONLN)" - -declare -ra CMAKE_FLAGS=( - -DM68K_CPU="$M68K_CPU" - -DM68K_FPU="$M68K_FPU" - -DM68K_COMMON="$M68K_COMMON" - -DBUILD_SHARED_LIBS=OFF - -DCMAKE_BUILD_TYPE=Release - -DCMAKE_INSTALL_PREFIX="${SYSROOT}/usr" -) - -mkdir -p deps -mkdir -p ${SYSROOT}/usr/lib -mkdir -p ${SYSROOT}/usr/include -cd deps - -# ZLIB -wget https://www.zlib.net/zlib-1.2.11.tar.gz -O zlib-1.2.11.tar.gz -tar -xvf zlib-1.2.11.tar.gz -mkdir -p zlib-1.2.11/build -cd zlib-1.2.11 -cmake -S. -Bbuild "${CMAKE_FLAGS[@]}" -O3 -fno-exceptions -w -noixemul -DBIG_ENDIAN -DAMIGA -fpermissive -std=c++14" -cmake --build build -j"$PARALLELISM" --config Release --target install -cd .. - -# SDL1.2 -wget https://github.com/AmigaPorts/libSDL12/archive/master.tar.gz -O SDL-1.2.tar.gz -tar -xvf SDL-1.2.tar.gz -cd libSDL12-master -make PREFX=${SYSROOT} PREF=${SYSROOT} -j"$PARALLELISM" -mkdir -p ${SYSROOT}/usr/lib -mkdir -p ${SYSROOT}/usr/include -cp -fvr libSDL.a ${SYSROOT}/usr/lib/ -cp -fvr include/* ${SYSROOT}/usr/include/ -cd .. - -# SDL_mixer -#wget https://github.com/SDL-mirror/SDL_mixer/archive/SDL-1.2.tar.gz -O SDL_mixer-SDL-1.2.tar.gz -#tar -xvf SDL_mixer-SDL-1.2.tar.gz -#cd SDL_mixer-SDL-1.2 -#./autogen.sh -#SDL_LIBS='-lSDL -ldebug' SDL_CFLAGS="-I${SYSROOT}/usr/include/SDL -noixemul" CFLAGS="${M68K_CFLAGS}" CXXFLAGS="${M68K_CXXFLAGS}" ./configure --disable-sdltest --disable-shared --enable-static --host=${TARGET} --prefix="${SYSROOT}/usr" -#make -j$(getconf _NPROCESSORS_ONLN) -#make install -#cd .. - -# FreeType -#wget https://download.savannah.gnu.org/releases/freetype/freetype-2.10.1.tar.gz -O freetype-2.10.1.tar.gz -#tar -xvf freetype-2.10.1.tar.gz -#mkdir -p freetype-2.10.1/build -#cd freetype-2.10.1 -#cmake -S. -Bbuild -DUNIX=1 -DM68K_CPU="$M68K_CPU" -DM68K_FPU="$M68K_FPU" -DM68K_COMMON="${M68K_COMMON}" -#cmake --build build -j"$PARALLELISM" --config Release --target install -#cd .. - -# SDL_ttf -#wget https://github.com/SDL-mirror/SDL_ttf/archive/SDL-1.2.tar.gz -O SDL_ttf-SDL-1.2.tar.gz -#tar -xvf SDL_ttf-SDL-1.2.tar.gz -#cd SDL_ttf-SDL-1.2 -#./autogen.sh -#LDFLAGS="-L${SYSROOT}/usr/lib" SDL_LIBS='-lSDL -ldebug' SDL_CFLAGS="-L${SYSROOT}/usr/lib -I${SYSROOT}/usr/include/SDL -noixemul" CFLAGS="${M68K_CFLAGS}" CXXFLAGS="${M68K_CXXFLAGS}" FT2_CFLAGS="-L${SYSROOT}/usr/lib -I${SYSROOT}/usr/include/freetype2" FT2_LIBS="-lfreetype -lzlib" ./configure --disable-shared --enable-static --host=${TARGET} --prefix=${SYSROOT}/usr -#make -j$(getconf _NPROCESSORS_ONLN) -#make install +#!/usr/bin/env bash + +# exit when any command fails +set -euo pipefail + +#set compiler params +export TARGET='m68k-amigaos' +export SYSROOT=/opt/$TARGET +export M68K_CPU=68040 +export M68K_FPU=hard +export M68K_CPU_FPU="-m${M68K_CPU} -m${M68K_FPU}-float" +export M68K_COMMON="-s -ffast-math -fomit-frame-pointer" +export M68K_CFLAGS="${M68K_CPU_FPU} ${M68K_COMMON}" +export M68K_CXXFLAGS="${M68K_CPU_FPU} ${M68K_COMMON}" + +PARALLELISM="$(getconf _NPROCESSORS_ONLN)" + +mkdir -p deps +mkdir -p ${SYSROOT}/usr/lib +mkdir -p ${SYSROOT}/usr/include +cd deps + +# SDL1.2 +wget https://github.com/AmigaPorts/libSDL12/archive/master.tar.gz -O SDL-1.2.tar.gz +tar -xvf SDL-1.2.tar.gz +cd libSDL12-master +make PREFX=${SYSROOT} PREF=${SYSROOT} -j"$PARALLELISM" +mkdir -p ${SYSROOT}/usr/lib +mkdir -p ${SYSROOT}/usr/include +cp -fvr libSDL.a ${SYSROOT}/usr/lib/ +cp -fvr include/* ${SYSROOT}/usr/include/ +cd .. From 7523cf86d830d8a887d1598e2d97723fd19d89a6 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 10 Feb 2024 11:46:53 +0100 Subject: [PATCH 276/596] fix patcher on 3DS + dont use source files from the game in the patcher --- CMakeLists.txt | 13 ++++++++----- tools/patcher/DiabloUI/diabloui.cpp | 2 ++ tools/patcher/platform/ctr/system.cpp | 4 ++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 08f94c02aa9..33d9c6fdd5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -688,15 +688,15 @@ if(USE_PATCH AND NOT ANDROID) if(NINTENDO_SWITCH) list(APPEND devil_patcher_SRCS - Source/platform/switch/docking.cpp - Source/platform/switch/romfs.cpp) + tools/patcher/platform/switch/docking.cpp + tools/patcher/platform/switch/romfs.cpp) endif() if(NINTENDO_3DS) list(APPEND devil_patcher_SRCS - Source/platform/ctr/system.cpp - Source/platform/ctr/display.cpp - Source/platform/ctr/messagebox.cpp) + tools/patcher/platform/ctr/system.cpp + tools/patcher/platform/ctr/display.cpp + tools/patcher/platform/ctr/messagebox.cpp) endif() set(PATCHER_SOURCES ${devil_patcher_SRCS}) @@ -1023,6 +1023,9 @@ if(NINTENDO_3DS) #target_include_directories(${BIN_TARGET} PRIVATE ${TREMOR_INCLUDE_DIRS}) #target_link_libraries(${BIN_TARGET} PRIVATE 3ds::ogg 3ds::mikmod 3ds::mad 3ds::freetype 3ds::bzip2 3ds::png) target_link_libraries(${BIN_TARGET} PRIVATE 3ds::citro3d 3ds::ctrulib) + if(DEVIL_PATCHER) + target_link_libraries(${DEVIL_PATCHER} PRIVATE 3ds::citro3d 3ds::ctrulib) + endif() endif() if(GPERF) diff --git a/tools/patcher/DiabloUI/diabloui.cpp b/tools/patcher/DiabloUI/diabloui.cpp index febce856ba2..493058508a5 100644 --- a/tools/patcher/DiabloUI/diabloui.cpp +++ b/tools/patcher/DiabloUI/diabloui.cpp @@ -462,11 +462,13 @@ void UiRenderAndPoll() #if HAS_GAMECTRL || HAS_JOYSTICK || HAS_KBCTRL || HAS_DPAD HandleMenuMove(); #endif +#if FULL_UI #ifdef __3DS__ // Keyboard blocks until input is finished // so defer until after render and fade-in ctr_vkbdFlush(); #endif +#endif // FULL_UI } static void Render(const UiText* uiArtText) diff --git a/tools/patcher/platform/ctr/system.cpp b/tools/patcher/platform/ctr/system.cpp index 2e661509ede..876a8199e92 100644 --- a/tools/patcher/platform/ctr/system.cpp +++ b/tools/patcher/platform/ctr/system.cpp @@ -109,8 +109,8 @@ void ctr_sys_init() acInit(); atexit([]() { acExit(); }); - n3ds_socInit(); - atexit([]() { n3ds_socExit(); }); + // n3ds_socInit(); + // atexit([]() { n3ds_socExit(); }); // randombytes_ctrrandom_init(); atexit([]() { From 8a65a8d96733b7d831cc9e34926ea74ee16ecc8b Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 10 Feb 2024 11:48:04 +0100 Subject: [PATCH 277/596] make ctr/keyboard.h/cpp more conform --- Source/platform/ctr/keyboard.cpp | 5 +++-- Source/platform/ctr/keyboard.h | 2 -- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Source/platform/ctr/keyboard.cpp b/Source/platform/ctr/keyboard.cpp index 96882947c6d..b41aab96ef4 100644 --- a/Source/platform/ctr/keyboard.cpp +++ b/Source/platform/ctr/keyboard.cpp @@ -1,7 +1,8 @@ +#include "platform/ctr/keyboard.h" + #include #include - -#include "platform/ctr/keyboard.h" +#include <3ds.h> constexpr size_t MAX_TEXT_LENGTH = 255; diff --git a/Source/platform/ctr/keyboard.h b/Source/platform/ctr/keyboard.h index 1fde63234a7..81fbe56dfa7 100644 --- a/Source/platform/ctr/keyboard.h +++ b/Source/platform/ctr/keyboard.h @@ -1,6 +1,4 @@ #pragma once -#include <3ds.h> - void ctr_vkbdInput(const char *title, const char *inText, char *outText, int maxLength); void ctr_vkbdFlush(); From 7da13dc2702d3c7d5b75fdec7b460a1e6300b56d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Feb 2024 08:14:57 +0100 Subject: [PATCH 278/596] Bump lukka/run-vcpkg from 11.4 to 11.5 (#6) Bumps [lukka/run-vcpkg](https://github.com/lukka/run-vcpkg) from 11.4 to 11.5. - [Release notes](https://github.com/lukka/run-vcpkg/releases) - [Commits](https://github.com/lukka/run-vcpkg/compare/v11.4...v11.5) --- updated-dependencies: - dependency-name: lukka/run-vcpkg dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/nightly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 875603e01b3..5661004735d 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -72,7 +72,7 @@ jobs: # Download and build vcpkg, without installing any port. If content is cached already, it is a no-op. - name: Create Build Environment - uses: lukka/run-vcpkg@v11.4 + uses: lukka/run-vcpkg@v11.5 with: vcpkgGitCommitId: '927bc12e31148b0d44ae9d174b96c20e3bcf08eb' #setupOnly: true From 64330ccec80750b4bc273600e8b15f0f97938fad Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 1 Mar 2024 19:59:07 +0100 Subject: [PATCH 279/596] fix SStrCopy on AMIGA --- Source/storm/storm.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/storm/storm.cpp b/Source/storm/storm.cpp index b8d25391711..1d463e4f401 100644 --- a/Source/storm/storm.cpp +++ b/Source/storm/storm.cpp @@ -92,7 +92,8 @@ void SStrCopy(char* dest, const char* src, int max_length) if (memccpy(dest, src, '\0', max_length) == NULL) dest[max_length - 1] = '\0'; #else - strncpy(dest, src, max_length); + strncpy(dest, src, max_length - 1); + dest[max_length - 1] = '\0'; #endif } From 65bc1cfe89c38ead97f33b1b293dd414e36ff692 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 3 Mar 2024 09:16:54 +0100 Subject: [PATCH 280/596] update nightly builds - add win98, n3ds, vita, amiga, switch, aarch builds to the release - fix artifact links and descriptions of the windows hellfire builds --- .github/workflows/nightly.yml | 256 ++++++++++++++++++++++++++++++++-- 1 file changed, 247 insertions(+), 9 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 5661004735d..df3e55a17b8 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -971,7 +971,7 @@ jobs: # Releases release: - needs: [build_check, build_msvc, build_mingw, build_mingw_x64, build_mac, build_ios, build_android, build_rg350, build_lepus, build_retrofw, build_ps4] + needs: [build_check, build_msvc, build_mingw, build_mingw_x64, build_w98, build_linux64, build_aarch, build_mac, build_ios, build_android, build_rg350, build_lepus, build_retrofw, build_ps4, build_vita, build_n3ds, build_switch, build_amiga] if: ${{ needs.build_check.outputs.should_run != 'false' }} #runs-on: windows-latest runs-on: ubuntu-latest @@ -1013,6 +1013,18 @@ jobs: name: hellfire-nightly-mingw-x86.zip - run: mv ${{github.workspace}}/devilutionx.zip ${{github.workspace}}/hellfire-nightly-mingw-x86.zip + - name: Download a diablo artifact + uses: actions/download-artifact@v4 + with: + name: diablo-nightly-mingw-w9x.zip + - run: mv ${{github.workspace}}/devilutionx.zip ${{github.workspace}}/diablo-nightly-mingw-w9x.zip + + - name: Download a hellfire artifact + uses: actions/download-artifact@v4 + with: + name: hellfire-nightly-mingw-w9x.zip + - run: mv ${{github.workspace}}/devilutionx.zip ${{github.workspace}}/hellfire-nightly-mingw-w9x.zip + # Windows-builds (x64) - name: Download a diablo artifact uses: actions/download-artifact@v4 @@ -1038,6 +1050,80 @@ jobs: name: hellfire-nightly-mingw-x64.zip - run: mv ${{github.workspace}}/devilutionx.zip ${{github.workspace}}/hellfire-nightly-mingw-x64.zip + # Linux-builds (x64) + - name: Download a diablo artifact + uses: actions/download-artifact@v4 + with: + name: diablo-nightly-x86_64-linux-gnu.tar.xz + - run: mv ${{github.workspace}}/devilutionx-x86_64-linux-gnu.tar.xz ${{github.workspace}}/diablo-nightly-x86_64-linux-gnu.tar.xz + + - name: Download a diablo artifact + uses: actions/download-artifact@v4 + with: + name: diablo-nightly-x86_64-linux-gnu.appimage + - run: mv ${{github.workspace}}/devilutionx-x86_64-linux-gnu.appimage ${{github.workspace}}/diablo-nightly-x86_64-linux-gnu.appimage + + - name: Download a hellfire artifact + uses: actions/download-artifact@v4 + with: + name: hellfire-nightly-x86_64-linux-gnu.tar.xz + - run: mv ${{github.workspace}}/devilutionx-x86_64-linux-gnu.tar.xz ${{github.workspace}}/hellfire-nightly-x86_64-linux-gnu.tar.xz + + - name: Download a hellfire artifact + uses: actions/download-artifact@v4 + with: + name: hellfire-nightly-x86_64-linux-gnu.appimage + - run: mv ${{github.workspace}}/devilutionx-x86_64-linux-gnu.appimage ${{github.workspace}}/hellfire-nightly-x86_64-linux-gnu.appimage + + - name: Download a diablo artifact + uses: actions/download-artifact@v4 + with: + name: diablo-nightly-x86_64-linux-gnup.tar.xz + - run: mv ${{github.workspace}}/devilutionx-x86_64-linux-gnu.tar.xz ${{github.workspace}}/diablo-nightly-x86_64-linux-gnup.tar.xz + + - name: Download a diablo artifact + uses: actions/download-artifact@v4 + with: + name: diablo-nightly-x86_64-linux-gnup.appimage + - run: mv ${{github.workspace}}/devilutionx-x86_64-linux-gnu.appimage ${{github.workspace}}/diablo-nightly-x86_64-linux-gnup.appimage + + - name: Download a hellfire artifact + uses: actions/download-artifact@v4 + with: + name: hellfire-nightly-x86_64-linux-gnup.tar.xz + - run: mv ${{github.workspace}}/devilutionx-x86_64-linux-gnu.tar.xz ${{github.workspace}}/hellfire-nightly-x86_64-linux-gnup.tar.xz + + - name: Download a hellfire artifact + uses: actions/download-artifact@v4 + with: + name: hellfire-nightly-x86_64-linux-gnup.appimage + - run: mv ${{github.workspace}}/devilutionx-x86_64-linux-gnu.appimage ${{github.workspace}}/hellfire-nightly-x86_64-linux-gnup.appimage + + # Aarch64-builds (x64) + - name: Download a diablo aarch64-artifact + uses: actions/download-artifact@v4 + with: + name: diablo-nightly-aarch64.tar.xz + - run: mv ${{github.workspace}}/devilutionx-aarch64.tar.xz ${{github.workspace}}/diablo-nightly-aarch64.tar.xz + + - name: Download a diablo aarch64-artifact using patched assets + uses: actions/download-artifact@v4 + with: + name: diablo-nightly-aarch64p.tar.xz + - run: mv ${{github.workspace}}/devilutionx-aarch64.tar.xz ${{github.workspace}}/diablo-nightly-aarch64p.tar.xz + + - name: Download a hellfire aarch64-artifact + uses: actions/download-artifact@v4 + with: + name: hellfire-nightly-aarch64.tar.xz + - run: mv ${{github.workspace}}/devilutionx-aarch64.tar.xz ${{github.workspace}}/hellfire-nightly-aarch64.tar.xz + + - name: Download a hellfire aarch64-artifact using patched assets + uses: actions/download-artifact@v4 + with: + name: hellfire-nightly-aarch64p.tar.xz + - run: mv ${{github.workspace}}/devilutionx-aarch64.tar.xz ${{github.workspace}}/hellfire-nightly-aarch64p.tar.xz + # Mac-builds - name: Download a diablo mac-artifact uses: actions/download-artifact@v4 @@ -1213,6 +1299,130 @@ jobs: name: hellfire-nightly-ps4p.pkg - run: mv ${{github.workspace}}/devilutionx-ps4.pkg ${{github.workspace}}/hellfire-nightly-ps4p.pkg + # vita-builds + - name: Download a diablo vita artifact + uses: actions/download-artifact@v4 + with: + name: diablo-nightly-vita.vpk + - run: mv ${{github.workspace}}/devilutionx.vpk ${{github.workspace}}/diablo-nightly-vita.vpk + + - name: Download a diablo vita artifact using patched assets + uses: actions/download-artifact@v4 + with: + name: diablo-nightly-vitap.vpk + - run: mv ${{github.workspace}}/devilutionx.vpk ${{github.workspace}}/diablo-nightly-vitap.vpk + + - name: Download a hellfire vita artifact + uses: actions/download-artifact@v4 + with: + name: hellfire-nightly-vita.vpk + - run: mv ${{github.workspace}}/devilutionx.vpk ${{github.workspace}}/hellfire-nightly-vita.vpk + + - name: Download a hellfire vita artifact using patched assets + uses: actions/download-artifact@v4 + with: + name: hellfire-nightly-vitap.vpk + - run: mv ${{github.workspace}}/devilutionx.vpk ${{github.workspace}}/hellfire-nightly-vitap.vpk + + # n3ds-builds + - name: Download a diablo n3ds artifact + uses: actions/download-artifact@v4 + with: + name: diablo-nightly-3ds.3dsx + - run: mv ${{github.workspace}}/devilutionx.3dsx ${{github.workspace}}/diablo-nightly-3ds.3dsx + + - name: Download a diablo n3ds artifact + uses: actions/download-artifact@v4 + with: + name: diablo-nightly-3ds.cia + - run: mv ${{github.workspace}}/devilutionx.cia ${{github.workspace}}/diablo-nightly-3ds.cia + + - name: Download a diablo n3ds artifact using patched assets + uses: actions/download-artifact@v4 + with: + name: diablo-nightly-3dsp.3dsx + - run: mv ${{github.workspace}}/devilutionx.3dsx ${{github.workspace}}/diablo-nightly-3dsp.3dsx + + - name: Download a diablo n3ds artifact using patched assets + uses: actions/download-artifact@v4 + with: + name: diablo-nightly-3dsp.cia + - run: mv ${{github.workspace}}/devilutionx.cia ${{github.workspace}}/diablo-nightly-3dsp.cia + + - name: Download a hellfire n3ds artifact + uses: actions/download-artifact@v4 + with: + name: hellfire-nightly-3ds.3dsx + - run: mv ${{github.workspace}}/devilutionx.3dsx ${{github.workspace}}/hellfire-nightly-3ds.3dsx + + - name: Download a hellfire n3ds artifact + uses: actions/download-artifact@v4 + with: + name: hellfire-nightly-3ds.cia + - run: mv ${{github.workspace}}/devilutionx.cia ${{github.workspace}}/hellfire-nightly-3ds.cia + + - name: Download a hellfire n3ds artifact using patched assets + uses: actions/download-artifact@v4 + with: + name: hellfire-nightly-3dsp.3dsx + - run: mv ${{github.workspace}}/devilutionx.3dsx ${{github.workspace}}/hellfire-nightly-3dsp.3dsx + + - name: Download a hellfire n3ds artifact using patched assets + uses: actions/download-artifact@v4 + with: + name: hellfire-nightly-3dsp.cia + - run: mv ${{github.workspace}}/devilutionx.cia ${{github.workspace}}/hellfire-nightly-3dsp.cia + + # switch-builds + - name: Download a diablo switch artifact + uses: actions/download-artifact@v4 + with: + name: diablo-nightly-switch.nro + - run: mv ${{github.workspace}}/devilutionx.nro ${{github.workspace}}/diablo-nightly-switch.nro + + - name: Download a diablo switch artifact using patched assets + uses: actions/download-artifact@v4 + with: + name: diablo-nightly-switchp.nro + - run: mv ${{github.workspace}}/devilutionx.nro ${{github.workspace}}/diablo-nightly-switchp.nro + + - name: Download a hellfire switch artifact + uses: actions/download-artifact@v4 + with: + name: hellfire-nightly-switch.nro + - run: mv ${{github.workspace}}/devilutionx.nro ${{github.workspace}}/hellfire-nightly-switch.nro + + - name: Download a hellfire switch artifact using patched assets + uses: actions/download-artifact@v4 + with: + name: hellfire-nightly-switchp.nro + - run: mv ${{github.workspace}}/devilutionx.nro ${{github.workspace}}/hellfire-nightly-switchp.nro + + # amiga-builds + - name: Download a diablo amiga artifact + uses: actions/download-artifact@v4 + with: + name: diablo-nightly-amiga + - run: mv ${{github.workspace}}/devilutionx ${{github.workspace}}/diablo-nightly-amiga + + - name: Download a diablo amiga artifact using patched assets + uses: actions/download-artifact@v4 + with: + name: diablo-nightly-amigap + - run: mv ${{github.workspace}}/devilutionx ${{github.workspace}}/diablo-nightly-amigap + + - name: Download a hellfire amiga artifact + uses: actions/download-artifact@v4 + with: + name: hellfire-nightly-amiga + - run: mv ${{github.workspace}}/devilutionx ${{github.workspace}}/hellfire-nightly-amiga + + - name: Download a hellfire amiga artifact using patched assets + uses: actions/download-artifact@v4 + with: + name: hellfire-nightly-amigap + - run: mv ${{github.workspace}}/devilutionx ${{github.workspace}}/hellfire-nightly-amigap + # release notes - name: Create release notes run: | @@ -1228,12 +1438,19 @@ jobs: echo '[diablo-nightly-retrofw.opk](../../releases/download/devilx-nightly/diablo-nightly-retrofw.opk) | Diablo package for `RetroFW`' >> RELEASE_NOTE.md echo '[diablo-nightly-rg350.opk](../../releases/download/devilx-nightly/diablo-nightly-rg350.opk) | Diablo package for `RG350`' >> RELEASE_NOTE.md echo '[diablo-nightly-ps4.pkg](../../releases/download/devilx-nightly/diablo-nightly-ps4.pkg) | Diablo package for `PS4`' >> RELEASE_NOTE.md + echo '[diablo-nightly-aarch64.tar.xz](../../releases/download/devilx-nightly/diablo-nightly-aarch64.tar.xz) | Diablo package for `aarch64`' >> RELEASE_NOTE.md echo '[diablo-nightly-mac.dmg](../../releases/download/devilx-nightly/diablo-nightly-mac.dmg) | Diablo package for `Mac`' >> RELEASE_NOTE.md echo '[diablo-nightly-ios.ipa](../../releases/download/devilx-nightly/diablo-nightly-ios.ipa) | Diablo package for `iOS`' >> RELEASE_NOTE.md + echo '[diablo-nightly-vita.vpk](../../releases/download/devilx-nightly/diablo-nightly-vita.vpk) | Diablo package for `Vita`' >> RELEASE_NOTE.md + echo '[diablo-nightly-3ds.3dsx](../../releases/download/devilx-nightly/diablo-nightly-3ds.3dsx) | Diablo package for `Nintendo 3DS` (3dsx)' >> RELEASE_NOTE.md + echo '[diablo-nightly-3ds.cia](../../releases/download/devilx-nightly/diablo-nightly-3ds.cia) | Diablo package for `Nintendo 3DS` (cia)' >> RELEASE_NOTE.md + echo '[diablo-nightly-switch.nro](../../releases/download/devilx-nightly/diablo-nightly-switch.nro) | Diablo package for `Nintendo Switch`' >> RELEASE_NOTE.md + echo '[diablo-nightly-amiga](../../releases/download/devilx-nightly/diablo-nightly-amiga) | Diablo package for `Amiga`' >> RELEASE_NOTE.md echo '[diablo-nightly-x64.zip](../../releases/download/devilx-nightly/diablo-nightly-x64.zip) | Diablo build for `Windows x64` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md echo '[diablo-nightly-mingw-x64.zip](../../releases/download/devilx-nightly/diablo-nightly-mingw-x64.zip) | Diablo build for `Windows x64`' >> RELEASE_NOTE.md echo '[diablo-nightly-x86.zip](../../releases/download/devilx-nightly/diablo-nightly-x86.zip) | Diablo build for `Windows x86` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md echo '[diablo-nightly-mingw-x86.zip](../../releases/download/devilx-nightly/diablo-nightly-mingw-x86.zip) | Diablo build for `Windows x86`' >> RELEASE_NOTE.md + echo '[diablo-nightly-mingw-w9x.zip](../../releases/download/devilx-nightly/diablo-nightly-mingw-w9x.zip) | Diablo build for `Windows 98`' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md echo '### **Diablo: Hellfire**' >> RELEASE_NOTE.md echo '_Filename_ | _Description_' >> RELEASE_NOTE.md @@ -1243,12 +1460,19 @@ jobs: echo '[hellfire-nightly-retrofw.opk](../../releases/download/devilx-nightly/hellfire-nightly-retrofw.opk) | Hellfire package for `RetroFW`' >> RELEASE_NOTE.md echo '[hellfire-nightly-rg350.opk](../../releases/download/devilx-nightly/hellfire-nightly-rg350.opk) | Hellfire package for `RG350`' >> RELEASE_NOTE.md echo '[hellfire-nightly-ps4.pkg](../../releases/download/devilx-nightly/hellfire-nightly-ps4.pkg) | Hellfire package for `PS4`' >> RELEASE_NOTE.md + echo '[hellfire-nightly-aarch64.tar.xz](../../releases/download/devilx-nightly/hellfire-nightly-aarch64.tar.xz) | Hellfire package for `aarch64`' >> RELEASE_NOTE.md echo '[hellfire-nightly-mac.dmg](../../releases/download/devilx-nightly/hellfire-nightly-mac.dmg) | Hellfire package for `Mac`' >> RELEASE_NOTE.md echo '[hellfire-nightly-ios.ipa](../../releases/download/devilx-nightly/hellfire-nightly-ios.ipa) | Hellfire package for `iOS`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-x64.zip](../../releases/download/devilx-nightly/hellfire-nightly-x64.zip) | Hellfire build for `Windows x64`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-mingw-x64.zip](../../releases/download/devilx-nightly/hellfire-nightly-x64.zip) | Hellfire build for `Windows x64` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md - echo '[hellfire-nightly-x86.zip](../../releases/download/devilx-nightly/hellfire-nightly-x86.zip) | Hellfire build for `Windows x86`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-mingw-x86.zip](../../releases/download/devilx-nightly/hellfire-nightly-x86.zip) | Hellfire build for `Windows x86` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md + echo '[hellfire-nightly-vita.vpk](../../releases/download/devilx-nightly/hellfire-nightly-vita.vpk) | Hellfire package for `Vita`' >> RELEASE_NOTE.md + echo '[hellfire-nightly-3ds.3dsx](../../releases/download/devilx-nightly/hellfire-nightly-3ds.3dsx) | Hellfire package for `Nintendo 3DS` (3dsx)' >> RELEASE_NOTE.md + echo '[hellfire-nightly-3ds.cia](../../releases/download/devilx-nightly/hellfire-nightly-3ds.cia) | Hellfire package for `Nintendo 3DS` (cia)' >> RELEASE_NOTE.md + echo '[hellfire-nightly-switch.nro](../../releases/download/devilx-nightly/hellfire-nightly-switch.nro) | Hellfire package for `Nintendo Switch`' >> RELEASE_NOTE.md + echo '[hellfire-nightly-amiga](../../releases/download/devilx-nightly/hellfire-nightly-amiga) | Hellfire package for `Amiga`' >> RELEASE_NOTE.md + echo '[hellfire-nightly-x64.zip](../../releases/download/devilx-nightly/hellfire-nightly-x64.zip) | Hellfire build for `Windows x64` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md + echo '[hellfire-nightly-mingw-x64.zip](../../releases/download/devilx-nightly/hellfire-nightly-mingw-x64.zip) | Hellfire build for `Windows x64`' >> RELEASE_NOTE.md + echo '[hellfire-nightly-x86.zip](../../releases/download/devilx-nightly/hellfire-nightly-x86.zip) | Hellfire build for `Windows x86` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md + echo '[hellfire-nightly-mingw-x86.zip](../../releases/download/devilx-nightly/hellfire-nightly-mingw-x86.zip) | Hellfire build for `Windows x86`' >> RELEASE_NOTE.md + echo '[hellfire-nightly-mingw-w9x.zip](../../releases/download/devilx-nightly/hellfire-nightly-mingw-w9x.zip) | Hellfire build for `Windows 98`' >> RELEASE_NOTE.md echo '[hellmini-nightly-x86.zip](../../releases/download/devilx-nightly/hellmini-nightly-x86.zip) | Minimal Hellfire build for `Windows x86`
- no internet, controller, sound or widescreen support' >> RELEASE_NOTE.md echo '[hellsrv-nightly-x86.zip](../../releases/download/devilx-nightly/hellsrv-nightly-x86.zip) | Minimal Hellfire server for `Windows x86`
- no controller, sound or widescreen support
- only server functionality' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md @@ -1260,12 +1484,19 @@ jobs: echo '[diablo-nightly-retrofwp.opk](../../releases/download/devilx-nightly/diablo-nightly-retrofwp.opk) | Diablo package for `RetroFW`' >> RELEASE_NOTE.md echo '[diablo-nightly-rg350p.opk](../../releases/download/devilx-nightly/diablo-nightly-rg350p.opk) | Diablo package for `RG350`' >> RELEASE_NOTE.md echo '[diablo-nightly-ps4p.pkg](../../releases/download/devilx-nightly/diablo-nightly-ps4p.pkg) | Diablo package for `PS4`' >> RELEASE_NOTE.md + echo '[diablo-nightly-aarch64p.tar.xz](../../releases/download/devilx-nightly/diablo-nightly-aarch64p.tar.xz) | Diablo package for `aarch64`' >> RELEASE_NOTE.md echo '[diablo-nightly-macp.dmg](../../releases/download/devilx-nightly/diablo-nightly-macp.dmg) | Diablo package for `Mac`' >> RELEASE_NOTE.md echo '[diablo-nightly-iosp.ipa](../../releases/download/devilx-nightly/diablo-nightly-iosp.ipa) | Diablo package for `iOS`' >> RELEASE_NOTE.md + echo '[diablo-nightly-vitap.vpk](../../releases/download/devilx-nightly/diablo-nightly-vitap.vpk) | Diablo package for `Vita`' >> RELEASE_NOTE.md + echo '[diablo-nightly-3dsp.3dsx](../../releases/download/devilx-nightly/diablo-nightly-3dsp.3dsx) | Diablo package for `Nintendo 3DS` (3dsx)' >> RELEASE_NOTE.md + echo '[diablo-nightly-3dsp.cia](../../releases/download/devilx-nightly/diablo-nightly-3dsp.cia) | Diablo package for `Nintendo 3DS` (cia)' >> RELEASE_NOTE.md + echo '[diablo-nightly-switchp.nro](../../releases/download/devilx-nightly/diablo-nightly-switchp.nro) | Diablo package for `Nintendo Switch`' >> RELEASE_NOTE.md + echo '[diablo-nightly-amigap](../../releases/download/devilx-nightly/diablo-nightly-amigap) | Diablo package for `Amiga`' >> RELEASE_NOTE.md echo '[diablo-nightly-x64.zip](../../releases/download/devilx-nightly/diablo-nightly-x64.zip) | Diablo build for `Windows x64` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md echo '[diablo-nightly-mingw-x64.zip](../../releases/download/devilx-nightly/diablo-nightly-mingw-x64.zip) | Diablo build for `Windows x64`' >> RELEASE_NOTE.md echo '[diablo-nightly-x86.zip](../../releases/download/devilx-nightly/diablo-nightly-x86.zip) | Diablo build for `Windows x86` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md echo '[diablo-nightly-mingw-x86.zip](../../releases/download/devilx-nightly/diablo-nightly-mingw-x86.zip) | Diablo build for `Windows x86`' >> RELEASE_NOTE.md + echo '[diablo-nightly-mingw-w9x.zip](../../releases/download/devilx-nightly/diablo-nightly-mingw-w9x.zip) | Diablo build for `Windows 98`' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md echo '### **Diablo: Hellfire** using patched assets' >> RELEASE_NOTE.md echo '_Filename_ | _Description_' >> RELEASE_NOTE.md @@ -1275,12 +1506,19 @@ jobs: echo '[hellfire-nightly-retrofwp.opk](../../releases/download/devilx-nightly/hellfire-nightly-retrofwp.opk) | Hellfire package for `RetroFW`' >> RELEASE_NOTE.md echo '[hellfire-nightly-rg350p.opk](../../releases/download/devilx-nightly/hellfire-nightly-rg350p.opk) | Hellfire package for `RG350`' >> RELEASE_NOTE.md echo '[hellfire-nightly-ps4p.pkg](../../releases/download/devilx-nightly/hellfire-nightly-ps4p.pkg) | Hellfire package for `PS4`' >> RELEASE_NOTE.md + echo '[hellfire-nightly-aarch64p.tar.xz](../../releases/download/devilx-nightly/hellfire-nightly-aarch64p.tar.xz) | Hellfire package for `aarch64`' >> RELEASE_NOTE.md echo '[hellfire-nightly-macp.dmg](../../releases/download/devilx-nightly/hellfire-nightly-macp.dmg) | Hellfire package for `Mac`' >> RELEASE_NOTE.md echo '[hellfire-nightly-iosp.ipa](../../releases/download/devilx-nightly/hellfire-nightly-iosp.ipa) | Hellfire package for `iOS`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-x64.zip](../../releases/download/devilx-nightly/hellfire-nightly-x64.zip) | Hellfire build for `Windows x64`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-mingw-x64.zip](../../releases/download/devilx-nightly/hellfire-nightly-x64.zip) | Hellfire build for `Windows x64` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md - echo '[hellfire-nightly-x86.zip](../../releases/download/devilx-nightly/hellfire-nightly-x86.zip) | Hellfire build for `Windows x86`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-mingw-x86.zip](../../releases/download/devilx-nightly/hellfire-nightly-x86.zip) | Hellfire build for `Windows x86` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md + echo '[hellfire-nightly-vitap.vpk](../../releases/download/devilx-nightly/hellfire-nightly-vitap.vpk) | Hellfire package for `Vita`' >> RELEASE_NOTE.md + echo '[hellfire-nightly-3dsp.3dsx](../../releases/download/devilx-nightly/hellfire-nightly-3dsp.3dsx) | Hellfire package for `Nintendo 3DS` (3dsx)' >> RELEASE_NOTE.md + echo '[hellfire-nightly-3dsp.cia](../../releases/download/devilx-nightly/hellfire-nightly-3dsp.cia) | Hellfire package for `Nintendo 3DS` (cia)' >> RELEASE_NOTE.md + echo '[hellfire-nightly-switchp.nro](../../releases/download/devilx-nightly/hellfire-nightly-switchp.nro) | Hellfire package for `Nintendo Switch`' >> RELEASE_NOTE.md + echo '[hellfire-nightly-amigap](../../releases/download/devilx-nightly/hellfire-nightly-amigap) | Hellfire package for `Amiga`' >> RELEASE_NOTE.md + echo '[hellfire-nightly-x64.zip](../../releases/download/devilx-nightly/hellfire-nightly-x64.zip) | Hellfire build for `Windows x64`(requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md + echo '[hellfire-nightly-mingw-x64.zip](../../releases/download/devilx-nightly/hellfire-nightly-mingw-x64.zip) | Hellfire build for `Windows x64`' >> RELEASE_NOTE.md + echo '[hellfire-nightly-x86.zip](../../releases/download/devilx-nightly/hellfire-nightly-x86.zip) | Hellfire build for `Windows x86` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md + echo '[hellfire-nightly-mingw-x86.zip](../../releases/download/devilx-nightly/hellfire-nightly-mingw-x86.zip) | Hellfire build for `Windows x86` >> RELEASE_NOTE.md + echo '[hellfire-nightly-mingw-w9x.zip](../../releases/download/devilx-nightly/hellfire-nightly-mingw-w9x.zip) | Hellfire build for `Windows 98`' >> RELEASE_NOTE.md echo '[hellmini-nightly-x86.zip](../../releases/download/devilx-nightly/hellmini-nightly-x86.zip) | Minimal Hellfire build for `Windows x86`
- no internet, controller, sound or widescreen support' >> RELEASE_NOTE.md echo '[hellsrv-nightly-x86.zip](../../releases/download/devilx-nightly/hellsrv-nightly-x86.zip) | Minimal Hellfire server for `Windows x86`
- no controller, sound or widescreen support
- only server functionality' >> RELEASE_NOTE.md From 9494b889853043b8a614d2193d293c6e1c567a0b Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 4 Mar 2024 08:08:56 +0100 Subject: [PATCH 281/596] fix typo --- .github/workflows/nightly.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index df3e55a17b8..cd65c46a7ae 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1514,10 +1514,10 @@ jobs: echo '[hellfire-nightly-3dsp.cia](../../releases/download/devilx-nightly/hellfire-nightly-3dsp.cia) | Hellfire package for `Nintendo 3DS` (cia)' >> RELEASE_NOTE.md echo '[hellfire-nightly-switchp.nro](../../releases/download/devilx-nightly/hellfire-nightly-switchp.nro) | Hellfire package for `Nintendo Switch`' >> RELEASE_NOTE.md echo '[hellfire-nightly-amigap](../../releases/download/devilx-nightly/hellfire-nightly-amigap) | Hellfire package for `Amiga`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-x64.zip](../../releases/download/devilx-nightly/hellfire-nightly-x64.zip) | Hellfire build for `Windows x64`(requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md + echo '[hellfire-nightly-x64.zip](../../releases/download/devilx-nightly/hellfire-nightly-x64.zip) | Hellfire build for `Windows x64` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md echo '[hellfire-nightly-mingw-x64.zip](../../releases/download/devilx-nightly/hellfire-nightly-mingw-x64.zip) | Hellfire build for `Windows x64`' >> RELEASE_NOTE.md echo '[hellfire-nightly-x86.zip](../../releases/download/devilx-nightly/hellfire-nightly-x86.zip) | Hellfire build for `Windows x86` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md - echo '[hellfire-nightly-mingw-x86.zip](../../releases/download/devilx-nightly/hellfire-nightly-mingw-x86.zip) | Hellfire build for `Windows x86` >> RELEASE_NOTE.md + echo '[hellfire-nightly-mingw-x86.zip](../../releases/download/devilx-nightly/hellfire-nightly-mingw-x86.zip) | Hellfire build for `Windows x86`' >> RELEASE_NOTE.md echo '[hellfire-nightly-mingw-w9x.zip](../../releases/download/devilx-nightly/hellfire-nightly-mingw-w9x.zip) | Hellfire build for `Windows 98`' >> RELEASE_NOTE.md echo '[hellmini-nightly-x86.zip](../../releases/download/devilx-nightly/hellmini-nightly-x86.zip) | Minimal Hellfire build for `Windows x86`
- no internet, controller, sound or widescreen support' >> RELEASE_NOTE.md echo '[hellsrv-nightly-x86.zip](../../releases/download/devilx-nightly/hellsrv-nightly-x86.zip) | Minimal Hellfire server for `Windows x86`
- no controller, sound or widescreen support
- only server functionality' >> RELEASE_NOTE.md From dcaf5ea1c0504db4f7ed489aa30e68b69f713b1b Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 6 Mar 2024 07:58:08 +0100 Subject: [PATCH 282/596] add the packages to the release --- .github/workflows/nightly.yml | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index cd65c46a7ae..8fd446c4f3d 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1513,7 +1513,7 @@ jobs: echo '[hellfire-nightly-3dsp.3dsx](../../releases/download/devilx-nightly/hellfire-nightly-3dsp.3dsx) | Hellfire package for `Nintendo 3DS` (3dsx)' >> RELEASE_NOTE.md echo '[hellfire-nightly-3dsp.cia](../../releases/download/devilx-nightly/hellfire-nightly-3dsp.cia) | Hellfire package for `Nintendo 3DS` (cia)' >> RELEASE_NOTE.md echo '[hellfire-nightly-switchp.nro](../../releases/download/devilx-nightly/hellfire-nightly-switchp.nro) | Hellfire package for `Nintendo Switch`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-amigap](../../releases/download/devilx-nightly/hellfire-nightly-amigap) | Hellfire package for `Amiga`' >> RELEASE_NOTE.md + echo '[hellfire-nightly-amigap](../../releases/download/devilx-nightly/hellfire-nightly-amigap) | Hellfire package for `Amiga`' >> RELEASE_NOTE.md echo '[hellfire-nightly-x64.zip](../../releases/download/devilx-nightly/hellfire-nightly-x64.zip) | Hellfire build for `Windows x64` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md echo '[hellfire-nightly-mingw-x64.zip](../../releases/download/devilx-nightly/hellfire-nightly-mingw-x64.zip) | Hellfire build for `Windows x64`' >> RELEASE_NOTE.md echo '[hellfire-nightly-x86.zip](../../releases/download/devilx-nightly/hellfire-nightly-x86.zip) | Hellfire build for `Windows x86` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md @@ -1555,23 +1555,37 @@ jobs: ${{github.workspace}}/diablo-nightly-retrofw.opk ${{github.workspace}}/diablo-nightly-rg350.opk ${{github.workspace}}/diablo-nightly-ps4.pkg + ${{github.workspace}}/diablo-nightly-aarch64.tar.xz ${{github.workspace}}/diablo-nightly-mac.dmg ${{github.workspace}}/diablo-nightly-ios.ipa + ${{github.workspace}}/diablo-nightly-vita.vpk + ${{github.workspace}}/diablo-nightly-3ds.3dsx + ${{github.workspace}}/diablo-nightly-3ds.cia + ${{github.workspace}}/diablo-nightly-switch.nro + ${{github.workspace}}/diablo-nightly-amiga ${{github.workspace}}/diablo-nightly-x64.zip ${{github.workspace}}/diablo-nightly-mingw-x64.zip ${{github.workspace}}/diablo-nightly-x86.zip ${{github.workspace}}/diablo-nightly-mingw-x86.zip + ${{github.workspace}}/diablo-nightly-mingw-w9x.zip ${{github.workspace}}/hellfire-nightly-android.apk ${{github.workspace}}/hellfire-nightly-lepus.opk ${{github.workspace}}/hellfire-nightly-retrofw.opk ${{github.workspace}}/hellfire-nightly-rg350.opk ${{github.workspace}}/hellfire-nightly-ps4.pkg + ${{github.workspace}}/hellfire-nightly-aarch64.tar.xz ${{github.workspace}}/hellfire-nightly-mac.dmg ${{github.workspace}}/hellfire-nightly-ios.ipa + ${{github.workspace}}/hellfire-nightly-vita.vpk + ${{github.workspace}}/hellfire-nightly-3ds.3dsx + ${{github.workspace}}/hellfire-nightly-3ds.cia + ${{github.workspace}}/hellfire-nightly-switch.nro + ${{github.workspace}}/hellfire-nightly-amiga ${{github.workspace}}/hellfire-nightly-x64.zip ${{github.workspace}}/hellfire-nightly-mingw-x64.zip ${{github.workspace}}/hellfire-nightly-x86.zip ${{github.workspace}}/hellfire-nightly-mingw-x86.zip + ${{github.workspace}}/hellfire-nightly-mingw-w9x.zip ${{github.workspace}}/hellmini-nightly-x86.zip ${{github.workspace}}/hellsrv-nightly-x86.zip ${{github.workspace}}/diablo-nightly-androidp.apk @@ -1579,15 +1593,27 @@ jobs: ${{github.workspace}}/diablo-nightly-retrofwp.opk ${{github.workspace}}/diablo-nightly-rg350p.opk ${{github.workspace}}/diablo-nightly-ps4p.pkg + ${{github.workspace}}/diablo-nightly-aarch64p.tar.xz ${{github.workspace}}/diablo-nightly-macp.dmg ${{github.workspace}}/diablo-nightly-iosp.ipa + ${{github.workspace}}/diablo-nightly-vitap.vpk + ${{github.workspace}}/diablo-nightly-3dsp.3dsx + ${{github.workspace}}/diablo-nightly-3dsp.cia + ${{github.workspace}}/diablo-nightly-switchp.nro + ${{github.workspace}}/diablo-nightly-amigap ${{github.workspace}}/hellfire-nightly-androidp.apk ${{github.workspace}}/hellfire-nightly-lepusp.opk ${{github.workspace}}/hellfire-nightly-retrofwp.opk ${{github.workspace}}/hellfire-nightly-rg350p.opk ${{github.workspace}}/hellfire-nightly-ps4p.pkg + ${{github.workspace}}/hellfire-nightly-aarch64p.tar.xz ${{github.workspace}}/hellfire-nightly-macp.dmg ${{github.workspace}}/hellfire-nightly-iosp.ipa + ${{github.workspace}}/hellfire-nightly-vitap.vpk + ${{github.workspace}}/hellfire-nightly-3dsp.3dsx + ${{github.workspace}}/hellfire-nightly-3dsp.cia + ${{github.workspace}}/hellfire-nightly-switchp.nro + ${{github.workspace}}/hellfire-nightly-amigap fail_on_unmatched_files: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 107b4adb60b7797b9b4a4b3bd2aa2eb67433d347 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 11 Mar 2024 19:59:49 +0100 Subject: [PATCH 283/596] bugfix for 'cleanup SpawnWindow' f9f4a5ea57692ecc077568d75d11b9cc14cf3e06 fix refresh-rate calculation when SDL does not specify it (SDL_DisplayMode.refresh_rate == 0) --- Source/utils/display.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Source/utils/display.cpp b/Source/utils/display.cpp index 43fb2f2bb15..9439b47c1ad 100644 --- a/Source/utils/display.cpp +++ b/Source/utils/display.cpp @@ -138,7 +138,8 @@ static void AdjustToScreenGeometry(int width, int height) static void CalculatePreferredWindowSize(int& width, int& height, bool useIntegerScaling) { SDL_DisplayMode mode; - if (SDL_GetDesktopDisplayMode(0, &mode) == 0) { + SDL_GetDesktopDisplayMode(0, &mode); + if (mode.w < mode.h) { std::swap(mode.w, mode.h); } @@ -164,7 +165,6 @@ static void CalculatePreferredWindowSize(int& width, int& height, bool useIntege height = mode.h * width / mode.w; // height = height * (hFactor / wFactor); } } - } } #endif @@ -331,8 +331,9 @@ void SpawnWindow() int refreshRate = 60; #ifndef USE_SDL1 SDL_DisplayMode mode; - // TODO: use SDL_GetCurrentDisplayMode after window is shown? - if (SDL_GetDesktopDisplayMode(0, &mode) == 0) { + // TODO: use SDL_GetWindowDisplayMode? + SDL_GetDesktopDisplayMode(0, &mode); + if (mode.refresh_rate != 0) { refreshRate = mode.refresh_rate; } #endif From a0e3afdacff51db5b83257b8c72f415d8f5252f7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Mar 2024 07:18:37 +0100 Subject: [PATCH 284/596] Bump softprops/action-gh-release from 0.1.15 to 2.0.3 (#7) Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 0.1.15 to 2.0.3. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/v0.1.15...v2.0.3) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/nightly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 8fd446c4f3d..94828f174f4 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1543,7 +1543,7 @@ jobs: shell: bash - name: Release - uses: softprops/action-gh-release@v0.1.15 + uses: softprops/action-gh-release@v2.0.3 with: tag_name: devilx-nightly body_path: ${{ github.workspace }}/RELEASE_NOTE.md From 6476d288cbf08c95929090868f4d5d4ddf7979b7 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 14 Mar 2024 11:16:36 +0100 Subject: [PATCH 285/596] handle multiple arguments in ps4/build.sh --- Packaging/ps4/build.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Packaging/ps4/build.sh b/Packaging/ps4/build.sh index af81ab28119..672de77ccae 100755 --- a/Packaging/ps4/build.sh +++ b/Packaging/ps4/build.sh @@ -11,7 +11,8 @@ cmake -S. -B"$BUILD_DIR" \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_VERBOSE_MAKEFILE=ON \ -DCMAKE_TOOLCHAIN_FILE="/opt/pacbrew/ps4/openorbis/cmake/ps4.cmake" \ - "${CMAKE_ARGS}" + ${CMAKE_ARGS} \ + "$@" cmake --build "$BUILD_DIR" -j $(getconf _NPROCESSORS_ONLN) mv "$BUILD_DIR"/IV0001-DVLX00001_00-*.pkg "$BUILD_DIR"/devilutionx-ps4.pkg From 524307adf036bfff311774fb2eb4c7cc9571f7dc Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 15 Mar 2024 17:17:41 +0100 Subject: [PATCH 286/596] update SDL2 --- .github/workflows/nightly.yml | 2 +- 3rdParty/SDL2/CMakeLists.txt | 2 +- .../src/main/java/org/libsdl/app/HIDDeviceManager.java | 8 ++++++++ .../app/src/main/java/org/libsdl/app/SDLActivity.java | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 94828f174f4..7ae3997df44 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -74,7 +74,7 @@ jobs: - name: Create Build Environment uses: lukka/run-vcpkg@v11.5 with: - vcpkgGitCommitId: '927bc12e31148b0d44ae9d174b96c20e3bcf08eb' + vcpkgGitCommitId: '095ee06e7f60dceef7d713e3f8b1c2eb10d650d7' #setupOnly: true # Now that vcpkg is installed, it is being used to run with the desired arguments. - name: Install Required Packages diff --git a/3rdParty/SDL2/CMakeLists.txt b/3rdParty/SDL2/CMakeLists.txt index 0a56861bb4d..4acf7364201 100644 --- a/3rdParty/SDL2/CMakeLists.txt +++ b/3rdParty/SDL2/CMakeLists.txt @@ -75,7 +75,7 @@ FetchContent_Declare(SDL2 #URL https://github.com/libsdl-org/SDL/archive/5056b29b0f8611b470d8b8bdb313eab628f8bd6e.tar.gz #URL_HASH MD5=3fb6d72c33434082c32d2649c35c6502 GIT_REPOSITORY https://github.com/pionere/SDL.git - GIT_TAG 2f10fc5b4b7e9210d2cd522e8528e2c43d7ac548 + GIT_TAG 7f3b9f3a95e347363f563c2811dec4f497abe787 ) FetchContent_MakeAvailableExcludeFromAll(SDL2) diff --git a/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java b/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java index 6f7013b2fc4..e7281fdf26a 100644 --- a/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java +++ b/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java @@ -273,6 +273,7 @@ private boolean isXboxOneController(UsbDevice usbDevice, UsbInterface usbInterfa final int XB1_IFACE_SUBCLASS = 71; final int XB1_IFACE_PROTOCOL = 208; final int[] SUPPORTED_VENDORS = { + 0x03f0, // HP 0x044f, // Thrustmaster 0x045e, // Microsoft 0x0738, // Mad Catz @@ -284,6 +285,7 @@ private boolean isXboxOneController(UsbDevice usbDevice, UsbInterface usbInterfa 0x24c6, // PowerA 0x2dc8, // 8BitDo 0x2e24, // Hyperkin + 0x3537, // GameSir }; if (usbInterface.getId() == 0 && @@ -357,6 +359,12 @@ private void connectHIDDeviceUSB(UsbDevice usbDevice) { private void initializeBluetooth() { Log.d(TAG, "Initializing Bluetooth"); + if (Build.VERSION.SDK_INT >= 31 /* Android 12 */ && + mContext.getPackageManager().checkPermission(android.Manifest.permission.BLUETOOTH_CONNECT, mContext.getPackageName()) != PackageManager.PERMISSION_GRANTED) { + Log.d(TAG, "Couldn't initialize Bluetooth, missing android.permission.BLUETOOTH_CONNECT"); + return; + } + if (Build.VERSION.SDK_INT <= 30 /* Android 11.0 (R) */ && mContext.getPackageManager().checkPermission(android.Manifest.permission.BLUETOOTH, mContext.getPackageName()) != PackageManager.PERMISSION_GRANTED) { Log.d(TAG, "Couldn't initialize Bluetooth, missing android.permission.BLUETOOTH"); diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java index 033b0d8a8e9..05b82a7e402 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -61,7 +61,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh private static final String TAG = "SDL"; private static final int SDL_MAJOR_VERSION = 2; private static final int SDL_MINOR_VERSION = 29; - private static final int SDL_MICRO_VERSION = 0; + private static final int SDL_MICRO_VERSION = 2; /* // Display InputType.SOURCE/CLASS of events and devices // From b7d592243c75a7f156ec3003b67d1134b60ad3a2 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 16 Mar 2024 07:32:35 +0100 Subject: [PATCH 287/596] use static sdl2 on ps4, vita and switch --- .github/workflows/nightly.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 7ae3997df44..911805da2dd 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -708,16 +708,16 @@ jobs: #name: [diablo, hellfire] include: - name: diablo - cmakeargs: '' + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF' artifact: 'diablo-nightly-ps4.pkg' - name: hellfire - cmakeargs: '-DHELLFIRE=ON' + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DHELLFIRE=ON' artifact: 'hellfire-nightly-ps4.pkg' - name: diablo-ps4p - cmakeargs: '-DUSE_PATCH=ON' + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON' artifact: 'diablo-nightly-ps4p.pkg' - name: hellfire-ps4p - cmakeargs: '-DUSE_PATCH=ON -DHELLFIRE=ON' + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-ps4p.pkg' runs-on: ubuntu-22.04 steps: @@ -757,16 +757,16 @@ jobs: #name: [diablo, hellfire] include: - name: diablo - cmakeargs: '-DNONET=ON' + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON' artifact: 'diablo-nightly-vita.vpk' - name: hellfire - cmakeargs: '-DNONET=ON -DHELLFIRE=ON' + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-vita.vpk' - name: diablo-vita - cmakeargs: '-DNONET=ON -D USE_PATCH=ON' + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON -D USE_PATCH=ON' artifact: 'diablo-nightly-vitap.vpk' - name: hellfire-vita - cmakeargs: '-DNONET=ON -D USE_PATCH=ON -DHELLFIRE=ON' + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON -D USE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-vitap.vpk' runs-on: ubuntu-latest container: vitasdk/vitasdk:latest @@ -876,16 +876,16 @@ jobs: #name: [diablo, hellfire] include: - name: diablo - cmakeargs: '-DNONET=ON' + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON' artifact: 'diablo-nightly-switch.nro' - name: hellfire - cmakeargs: '-DNONET=ON -DHELLFIRE=ON' + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-switch.nro' - name: diablo-switch - cmakeargs: '-DNONET=ON -D USE_PATCH=ON' + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON -D USE_PATCH=ON' artifact: 'diablo-nightly-switchp.nro' - name: hellfire-switch - cmakeargs: '-DNONET=ON -D USE_PATCH=ON -DHELLFIRE=ON' + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON -D USE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-switchp.nro' runs-on: ubuntu-latest container: devkitpro/devkita64:latest From 1a5d248186f7c8a2b4a7b8f4a035ca61b57d7fce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Mar 2024 08:27:30 +0100 Subject: [PATCH 288/596] Bump softprops/action-gh-release from 2.0.3 to 2.0.4 (#8) Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.0.3 to 2.0.4. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/v2.0.3...v2.0.4) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/nightly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 911805da2dd..0acbf755e43 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1543,7 +1543,7 @@ jobs: shell: bash - name: Release - uses: softprops/action-gh-release@v2.0.3 + uses: softprops/action-gh-release@v2.0.4 with: tag_name: devilx-nightly body_path: ${{ github.workspace }}/RELEASE_NOTE.md From ea1ad96e8b4f03ab76fb8b9b6dd2ebfa775b751c Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 23 Mar 2024 09:51:48 +0100 Subject: [PATCH 289/596] audio adjustments - call Mix_OpenAudioDevice instead of Mix_OpenAudio - add SDL_AUDIO_ALLOW_SAMPLES_CHANGE flag 1. in-game audio: SDL_mixer should take care about it 2. video playback: the internal buffer_queue should take care about it + fix line endings (music_wav.c, music_wav.h, types_internal.h) --- 3rdParty/SDL2_mixer/include/SDL_mixer.h | 4 +- 3rdParty/SDL2_mixer/src/codecs/music_wav.c | 202 ++++++++++---------- 3rdParty/SDL2_mixer/src/codecs/music_wav.h | 16 +- 3rdParty/SDL2_mixer/src/mixer.c | 7 +- 3rdParty/SDL2_mixer/src/types_internal.h | 30 +-- Source/sound.cpp | 2 +- Source/storm/storm_svid.cpp | 2 +- Source/utils/sdl2_to_1_2_backports.h | 5 + tools/patcher/sound.cpp | 2 +- tools/patcher/utils/sdl2_to_1_2_backports.h | 5 + 10 files changed, 141 insertions(+), 134 deletions(-) diff --git a/3rdParty/SDL2_mixer/include/SDL_mixer.h b/3rdParty/SDL2_mixer/include/SDL_mixer.h index d94808cd679..0f994d545a3 100644 --- a/3rdParty/SDL2_mixer/include/SDL_mixer.h +++ b/3rdParty/SDL2_mixer/include/SDL_mixer.h @@ -207,11 +207,11 @@ typedef enum { typedef struct _Mix_Music Mix_Music; /* Open the mixer with a certain audio format */ -extern DECLSPEC int SDLCALL Mix_OpenAudio(int frequency, Uint16 format, int channels, int chunksize); #ifdef FULL +extern DECLSPEC int SDLCALL Mix_OpenAudio(int frequency, Uint16 format, int channels, int chunksize); +#endif /* Open the mixer with specific device and certain audio format */ extern DECLSPEC int SDLCALL Mix_OpenAudioDevice(int frequency, Uint16 format, int channels, int chunksize, const char* device, int allowed_changes); -#endif #ifdef FULL // FIX_CHAN /* Dynamically change the number of channels managed by the mixer. If decreasing the number of channels, the upper channels are diff --git a/3rdParty/SDL2_mixer/src/codecs/music_wav.c b/3rdParty/SDL2_mixer/src/codecs/music_wav.c index 9feef8aaedc..363018f2457 100644 --- a/3rdParty/SDL2_mixer/src/codecs/music_wav.c +++ b/3rdParty/SDL2_mixer/src/codecs/music_wav.c @@ -223,9 +223,9 @@ static void* WAV_CreateFromRW(Mix_RWops* src, Mix_Audio* dst) return NULL; } #else - SDL_BuildAudioCVT(&wave->cvt, - wave->spec.format, wave->spec.channels, wave->spec.freq, -#ifdef FULL // FIX_OUT + SDL_BuildAudioCVT(&wave->cvt, + wave->spec.format, wave->spec.channels, wave->spec.freq, +#ifdef FULL // FIX_OUT music_spec.format, music_spec.channels, music_spec.freq); #else MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, MIX_DEFAULT_FREQUENCY); @@ -616,7 +616,7 @@ static int WAV_GetSome(Mix_Channel* channel, void* stream, int bytes) return -1; } } else { - /* We might be looping, continue */ + /* We might be looping, continue */ at_end = SDL_TRUE; } #ifdef FULL // WAV_LOOP @@ -658,103 +658,103 @@ static int WAV_GetSome(Mix_Channel* channel, void* stream, int bytes) #else // USE_SDL1 WAV_Music *wave = (WAV_Music *)context; #ifdef FULL // FILE_INT - Sint64 pos, stop; -#ifdef FULL // WAV_LOOP - WAVLoopPoint *loop; - Sint64 loop_start; - Sint64 loop_stop; -#endif -#else - int pos, stop; -#ifdef FULL // WAV_LOOP - WAVLoopPoint *loop; - int loop_start; - int loop_stop; -#endif -#endif // FULL -#ifdef FULL // WAV_LOOP - SDL_bool looped = SDL_FALSE; - unsigned i; -#endif - int consumed; - void *stream = data; - - pos = Mix_RWtell(wave->src); - stop = wave->stop; -#ifdef FULL // WAV_LOOP - loop = NULL; - for (i = 0; i < wave->numloops; ++i) { - loop = &wave->loops[i]; - if (loop->active) { - const int bytes_per_sample = (SDL_AUDIO_BITSIZE(wave->spec.format) / 8) * wave->spec.channels; - loop_start = wave->start + loop->start * bytes_per_sample; - loop_stop = wave->start + (loop->stop + 1) * bytes_per_sample; - if (pos >= loop_start && pos < loop_stop) - { - stop = loop_stop; - break; - } - } - loop = NULL; - } -#endif // FULL - WAV_LOOP - if (wave->cvt.needed) { - int original_len = (int)((double)bytes/wave->cvt.len_ratio); - /* Make sure the length is a multiple of the sample size */ - { - const int bytes_per_sample = (SDL_AUDIO_BITSIZE(wave->spec.format) / 8) * wave->spec.channels; - const int alignment_mask = (bytes_per_sample - 1); - original_len &= ~alignment_mask; - } - if (wave->cvt.len != original_len) { - int worksize; - if (wave->cvt.buf != NULL) { - SDL_free(wave->cvt.buf); - } - worksize = original_len*wave->cvt.len_mult; - wave->cvt.buf=(Uint8 *)SDL_malloc(worksize); - if (wave->cvt.buf == NULL) { + Sint64 pos, stop; +#ifdef FULL // WAV_LOOP + WAVLoopPoint *loop; + Sint64 loop_start; + Sint64 loop_stop; +#endif +#else + int pos, stop; +#ifdef FULL // WAV_LOOP + WAVLoopPoint *loop; + int loop_start; + int loop_stop; +#endif +#endif // FULL +#ifdef FULL // WAV_LOOP + SDL_bool looped = SDL_FALSE; + unsigned i; +#endif + int consumed; + void *stream = data; + + pos = Mix_RWtell(wave->src); + stop = wave->stop; +#ifdef FULL // WAV_LOOP + loop = NULL; + for (i = 0; i < wave->numloops; ++i) { + loop = &wave->loops[i]; + if (loop->active) { + const int bytes_per_sample = (SDL_AUDIO_BITSIZE(wave->spec.format) / 8) * wave->spec.channels; + loop_start = wave->start + loop->start * bytes_per_sample; + loop_stop = wave->start + (loop->stop + 1) * bytes_per_sample; + if (pos >= loop_start && pos < loop_stop) + { + stop = loop_stop; + break; + } + } + loop = NULL; + } +#endif // FULL - WAV_LOOP + if (wave->cvt.needed) { + int original_len = (int)((double)bytes/wave->cvt.len_ratio); + /* Make sure the length is a multiple of the sample size */ + { + const int bytes_per_sample = (SDL_AUDIO_BITSIZE(wave->spec.format) / 8) * wave->spec.channels; + const int alignment_mask = (bytes_per_sample - 1); + original_len &= ~alignment_mask; + } + if (wave->cvt.len != original_len) { + int worksize; + if (wave->cvt.buf != NULL) { + SDL_free(wave->cvt.buf); + } + worksize = original_len*wave->cvt.len_mult; + wave->cvt.buf=(Uint8 *)SDL_malloc(worksize); + if (wave->cvt.buf == NULL) { Mix_OutOfMemory(); - return -1; - } - wave->cvt.len = original_len; - } - if ((stop - pos) < original_len) { - original_len = (int)(stop - pos); - } - original_len = (int)Mix_RWread(wave->src, wave->cvt.buf, 1, original_len); - wave->cvt.len = original_len; - SDL_ConvertAudio(&wave->cvt); - //SDL_MixAudioFormat(stream, wave->cvt.buf, music_spec.format, wave->cvt.len_cvt, wave->volume); - SDL_MixAudio(stream, wave->cvt.buf, wave->cvt.len_cvt, wave->volume); - consumed = wave->cvt.len_cvt; - } else { - Uint8 *data; - if ((stop - pos) < bytes) { - bytes = (int)(stop - pos); - } - data = SDL_stack_alloc(Uint8, bytes); - if (data) { - bytes = (int)Mix_RWread(wave->src, data, 1, bytes); // MUS_ENC - //SDL_MixAudioFormat(stream, data, music_spec.format, bytes, wave->volume); - SDL_MixAudio(stream, data, bytes, wave->volume); - SDL_stack_free(data); - } - consumed = bytes; - } -#ifdef FULL // WAV_LOOP - if (loop && Mix_RWtell(wave->src) >= stop) { - if (loop->current_play_count == 1) { - loop->active = SDL_FALSE; - } else { - if (loop->current_play_count > 0) { - --loop->current_play_count; - } - if (Mix_RWseek(wave->src, loop_start, RW_SEEK_SET) < 0) return -1; - looped = SDL_TRUE; - } - } + } + wave->cvt.len = original_len; + } + if ((stop - pos) < original_len) { + original_len = (int)(stop - pos); + } + original_len = (int)Mix_RWread(wave->src, wave->cvt.buf, 1, original_len); + wave->cvt.len = original_len; + SDL_ConvertAudio(&wave->cvt); + //SDL_MixAudioFormat(stream, wave->cvt.buf, music_spec.format, wave->cvt.len_cvt, wave->volume); + SDL_MixAudio(stream, wave->cvt.buf, wave->cvt.len_cvt, wave->volume); + consumed = wave->cvt.len_cvt; + } else { + Uint8 *data; + if ((stop - pos) < bytes) { + bytes = (int)(stop - pos); + } + data = SDL_stack_alloc(Uint8, bytes); + if (data) { + bytes = (int)Mix_RWread(wave->src, data, 1, bytes); // MUS_ENC + //SDL_MixAudioFormat(stream, data, music_spec.format, bytes, wave->volume); + SDL_MixAudio(stream, data, bytes, wave->volume); + SDL_stack_free(data); + } + consumed = bytes; + } +#ifdef FULL // WAV_LOOP + if (loop && Mix_RWtell(wave->src) >= stop) { + if (loop->current_play_count == 1) { + loop->active = SDL_FALSE; + } else { + if (loop->current_play_count > 0) { + --loop->current_play_count; + } + if (Mix_RWseek(wave->src, loop_start, RW_SEEK_SET) < 0) + return -1; + looped = SDL_TRUE; + } + } if (!looped && (consumed == 0 || Mix_RWtell(wave->src) >= wave->stop)) { #else // FULL - WAV_LOOP if (consumed == 0 || Mix_RWtell(wave->src) >= wave->stop) { @@ -1032,8 +1032,8 @@ static void WAV_Delete(Mix_Audio* audio) #endif } #else - if (wave->cvt.buf != NULL) { - SDL_free(wave->cvt.buf); + if (wave->cvt.buf != NULL) { + SDL_free(wave->cvt.buf); #ifndef FULL // FIX_MUS wave->cvt.buf = NULL; #endif diff --git a/3rdParty/SDL2_mixer/src/codecs/music_wav.h b/3rdParty/SDL2_mixer/src/codecs/music_wav.h index 71282ccd20e..5e27cc128dd 100644 --- a/3rdParty/SDL2_mixer/src/codecs/music_wav.h +++ b/3rdParty/SDL2_mixer/src/codecs/music_wav.h @@ -23,14 +23,14 @@ #ifndef MUSIC_WAV_H_ #define MUSIC_WAV_H_ -#ifdef FULL -#include "music.h" -#else -#include "../music.h" -#include "../mixer.h" -#endif -#ifndef FULL // SELF_CONV -#include "../utils.h" +#ifdef FULL +#include "music.h" +#else +#include "../music.h" +#include "../mixer.h" +#endif +#ifndef FULL // SELF_CONV +#include "../utils.h" #endif #include "../types_internal.h" diff --git a/3rdParty/SDL2_mixer/src/mixer.c b/3rdParty/SDL2_mixer/src/mixer.c index af8fcd62fae..1edb297a849 100644 --- a/3rdParty/SDL2_mixer/src/mixer.c +++ b/3rdParty/SDL2_mixer/src/mixer.c @@ -567,18 +567,15 @@ int Mix_OpenAudioDevice(int frequency, Uint16 format, int nchannels, int chunksi #endif return(0); } - +#ifdef FULL // FIX_OUT /* Open the mixer with a certain desired audio format */ int Mix_OpenAudio(int frequency, Uint16 format, int nchannels, int chunksize) { -#ifdef FULL // FIX_OUT return Mix_OpenAudioDevice(frequency, format, nchannels, chunksize, NULL, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_CHANNELS_CHANGE); -#else - return Mix_OpenAudioDevice(frequency, format, nchannels, chunksize, NULL, 0); -#endif } +#endif #ifdef FULL // FIX_CHAN /* Dynamically change the number of channels managed by the mixer. If decreasing the number of channels, the upper channels are diff --git a/3rdParty/SDL2_mixer/src/types_internal.h b/3rdParty/SDL2_mixer/src/types_internal.h index b924f2261af..1b4e9bddd9b 100644 --- a/3rdParty/SDL2_mixer/src/types_internal.h +++ b/3rdParty/SDL2_mixer/src/types_internal.h @@ -80,21 +80,21 @@ typedef uint64_t Uint64; #define SDL_MIN_UINT64 ((Uint64)(0x0000000000000000ull)) /* 0 */ #endif // !SDL_VERSION_ATLEAST(2, 0, 7) -#ifdef _MSC_VER -#ifdef _DEVMODE -#define ASSUME_UNREACHABLE assert(0); -#else -#define ASSUME_UNREACHABLE __assume(0); -#endif -#elif defined(__clang__) -#define ASSUME_UNREACHABLE __builtin_unreachable(); -#elif defined(__GNUC__) -#if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 405 -#define ASSUME_UNREACHABLE __builtin_unreachable(); -#else -#define ASSUME_UNREACHABLE -#endif -#endif +#ifdef _MSC_VER +#ifdef _DEVMODE +#define ASSUME_UNREACHABLE assert(0); +#else +#define ASSUME_UNREACHABLE __assume(0); +#endif +#elif defined(__clang__) +#define ASSUME_UNREACHABLE __builtin_unreachable(); +#elif defined(__GNUC__) +#if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 405 +#define ASSUME_UNREACHABLE __builtin_unreachable(); +#else +#define ASSUME_UNREACHABLE +#endif +#endif /* Effects */ diff --git a/Source/sound.cpp b/Source/sound.cpp index 7bd1e39ecbf..d6c64da9a42 100644 --- a/Source/sound.cpp +++ b/Source/sound.cpp @@ -127,7 +127,7 @@ void sound_file_load(const char* path, SoundSample* pSnd) void RestartMixer() { - if (Mix_OpenAudio(SND_DEFAULT_FREQUENCY, SND_DEFAULT_FORMAT, SND_DEFAULT_CHANNELS, 1024) < 0) { + if (Mix_OpenAudioDevice(SND_DEFAULT_FREQUENCY, SND_DEFAULT_FORMAT, SND_DEFAULT_CHANNELS, 1024, NULL, SDL_AUDIO_ALLOW_SAMPLES_CHANGE) < 0) { DoLog(Mix_GetError()); } Mix_VolumeMusic(MIX_VOLUME(gnMusicVolume)); diff --git a/Source/storm/storm_svid.cpp b/Source/storm/storm_svid.cpp index cecba0d34ef..617d4d8d125 100644 --- a/Source/storm/storm_svid.cpp +++ b/Source/storm/storm_svid.cpp @@ -286,7 +286,7 @@ HANDLE SVidPlayBegin(const char* filename, int flags) Mix_CloseAudio(); #if SDL_VERSION_ATLEAST(2, 0, 4) - deviceId = SDL_OpenAudioDevice(NULL, 0, &audioFormat, NULL, 0); + deviceId = SDL_OpenAudioDevice(NULL, 0, &audioFormat, NULL, SDL_AUDIO_ALLOW_SAMPLES_CHANGE); if (deviceId != 0) { SDL_PauseAudioDevice(deviceId, 0); /* start audio playing. */ } else { diff --git a/Source/utils/sdl2_to_1_2_backports.h b/Source/utils/sdl2_to_1_2_backports.h index 7ddcc968e76..d83845d6058 100644 --- a/Source/utils/sdl2_to_1_2_backports.h +++ b/Source/utils/sdl2_to_1_2_backports.h @@ -333,4 +333,9 @@ int SDL_BlitScaled(SDL_Surface* src, SDL_Rect* srcrect, char* SDL_GetBasePath(); char* SDL_GetPrefPath(const char* org, const char* app); +//== Audio + +// Audio flags are not supported in SDL1. +#define SDL_AUDIO_ALLOW_SAMPLES_CHANGE 0 + #endif // USE_SDL1 diff --git a/tools/patcher/sound.cpp b/tools/patcher/sound.cpp index 7bd1e39ecbf..d6c64da9a42 100644 --- a/tools/patcher/sound.cpp +++ b/tools/patcher/sound.cpp @@ -127,7 +127,7 @@ void sound_file_load(const char* path, SoundSample* pSnd) void RestartMixer() { - if (Mix_OpenAudio(SND_DEFAULT_FREQUENCY, SND_DEFAULT_FORMAT, SND_DEFAULT_CHANNELS, 1024) < 0) { + if (Mix_OpenAudioDevice(SND_DEFAULT_FREQUENCY, SND_DEFAULT_FORMAT, SND_DEFAULT_CHANNELS, 1024, NULL, SDL_AUDIO_ALLOW_SAMPLES_CHANGE) < 0) { DoLog(Mix_GetError()); } Mix_VolumeMusic(MIX_VOLUME(gnMusicVolume)); diff --git a/tools/patcher/utils/sdl2_to_1_2_backports.h b/tools/patcher/utils/sdl2_to_1_2_backports.h index 7ddcc968e76..d83845d6058 100644 --- a/tools/patcher/utils/sdl2_to_1_2_backports.h +++ b/tools/patcher/utils/sdl2_to_1_2_backports.h @@ -333,4 +333,9 @@ int SDL_BlitScaled(SDL_Surface* src, SDL_Rect* srcrect, char* SDL_GetBasePath(); char* SDL_GetPrefPath(const char* org, const char* app); +//== Audio + +// Audio flags are not supported in SDL1. +#define SDL_AUDIO_ALLOW_SAMPLES_CHANGE 0 + #endif // USE_SDL1 From 57eae9fa51496469e398039daec8f370a6862f02 Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Thu, 28 Mar 2024 15:56:40 +0100 Subject: [PATCH 290/596] Make it more clear that the Battle.net installation also works --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0d7a16f7ee8..ffee5d64366 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -

+

@@ -26,11 +26,11 @@ For a full list of changes see our [changelog](docs/CHANGELOG.md). # How to Install -Note: You'll need access to the data from the original game. If you don't have an original CD then you can [buy Diablo from GoG.com](https://www.gog.com/game/diablo). +Note: You'll need access to the data from the original game. If you don't have an original CD then you can [buy Diablo from GoG.com](https://www.gog.com/game/diablo) or Battle.net. Download the latest [DevilutionX release](https://github.com/pionere/devilutionX/releases) and extract the contents to a location of your choosing or [build from source](#building-from-source). -- Copy `DIABDAT.MPQ` from the CD or GOG-installation (or [extract it from the GoG installer](https://github.com/diasurgical/devilutionX/wiki/Extracting-the-.MPQs-from-the-GoG-installer)) to the DevilutionX folder. +- Copy `DIABDAT.MPQ` from the CD or Diablo-installation (or [extract it from the GoG installer](https://github.com/diasurgical/devilutionX/wiki/Extracting-the-.MPQs-from-the-GoG-installer)) to the DevilutionX folder. - To run the Diablo: Hellfire expansion you will need to also copy `hellfire.mpq`, `hfmonk.mpq`, `hfmusic.mpq`, `hfvoice.mpq`. For more detailed instructions: [Installation Instructions](./docs/installing.md). From 557506818bc01fd3d192a1e2e8f3d5e24b260055 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 29 Mar 2024 08:33:31 +0100 Subject: [PATCH 291/596] increase the mana cost of teleport --- Source/spelldat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/spelldat.cpp b/Source/spelldat.cpp index 99393b2fcbb..4bf92d94c8b 100644 --- a/Source/spelldat.cpp +++ b/Source/spelldat.cpp @@ -79,7 +79,7 @@ const SpellData spelldata[NUM_SPELLS] = { /*SPL_MANASHIELD*/ { 33, STYPE_MAGIC, 13, "Mana Shield", 6, 10, 8, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_ANY, 25, IS_CAST2, MIS_MANASHIELD, 0, 33, 4, 10, 16000, 120, ALIGN64 }, /*SPL_ATTRACT*/ { 4, STYPE_LIGHTNING, 30, "Attract", 2, 4, 4, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 20, IS_CAST4, MIS_ATTRACT, 0, 4, 40, 80, 2000, 30, ALIGN64 }, /*SPL_TELEKINESIS*/ { 15, STYPE_MAGIC, 40, "Telekinesis", 2, 4, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_TELEKINESIS, SFLAG_DUNGEON, 33, IS_CAST2, MIS_TELEKINESIS, 2, 8, 20, 40, 2500, 200, ALIGN64 }, -/*SPL_TELEPORT*/ { 35, STYPE_MAGIC, 24, "Teleport", 14, 24, 14, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_ANY, 105, IS_CAST6, MIS_TELEPORT, 5, 15, 16, 32, 20000, 250, ALIGN64 }, +/*SPL_TELEPORT*/ { 80, STYPE_MAGIC, 24, "Teleport", 14, 24, 14, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_ANY, 105, IS_CAST6, MIS_TELEPORT, 2, 40, 16, 32, 20000, 250, ALIGN64 }, /*SPL_RNDTELEPORT*/ { 11, STYPE_MAGIC, 28, "Phasing", 7, 12, 6, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 39, IS_CAST2, MIS_RNDTELEPORT, 1, 4, 40, 80, 3500, 100, ALIGN64 }, /*SPL_TOWN*/ { 35, STYPE_MAGIC, 7, "Town Portal", 3, 6, 4, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 20, IS_CAST6, MIS_TOWN, 3, 18, 20, 80, 3000, 200, ALIGN64 }, /*SPL_HEAL*/ { 5, STYPE_MAGIC, 2, "Healing", 1, 2, 1, 0, CURSOR_NONE, CURSOR_NONE, SFLAG_ANY, 17, IS_CAST8, MIS_HEAL, 6, 1, 20, 40, 1000, 50, ALIGN64 }, From dcb88ab7dded150b1061dc2246818bcba512a58b Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 14 Apr 2024 08:54:27 +0200 Subject: [PATCH 292/596] adjust the handling of the unique cursor graphics - add UICurs to UniqItemData (get rid of IPL_INVCURS) - use separate graphics for the gnarled root (new graphics for the spiked club) - rename ICURS_STUDDED_LEATHER_ARMOR to ICURS_STUD_LEATH_ARMOR --- Source/itemdat.cpp | 234 ++++++++++++++++++++++----------------------- Source/items.cpp | 17 ++-- enums.h | 7 +- structs.h | 1 + 4 files changed, 131 insertions(+), 128 deletions(-) diff --git a/Source/itemdat.cpp b/Source/itemdat.cpp index 4e6136140bc..c4bb75f0921 100644 --- a/Source/itemdat.cpp +++ b/Source/itemdat.cpp @@ -120,7 +120,7 @@ const ItemData AllItemsList[NUM_IDI] = { /* */ { "Quilted Armor", 1, 4, UITYPE_NONE, ICURS_QUILTED_ARMOR, ITYPE_LARMOR, IMISC_NONE, SPL_NULL, ICLASS_ARMOR, ILOC_ARMOR, IDAM_NONE, 0, 0, 0, 0, 0, 0, FALSE, 7, 10, 30, 200, ALIGN }, /* */ { "Leather Armor", 1, 6, UITYPE_LEATHARMOR, ICURS_LEATHER_ARMOR, ITYPE_LARMOR, IMISC_NONE, SPL_NULL, ICLASS_ARMOR, ILOC_ARMOR, IDAM_NONE, 0, 0, 0, 0, 0, 0, FALSE, 10, 13, 35, 300, ALIGN }, /* */ { "Hard Leather Armor", 1, 7, UITYPE_NONE, ICURS_HARD_LEATHER_ARMOR, ITYPE_LARMOR, IMISC_NONE, SPL_NULL, ICLASS_ARMOR, ILOC_ARMOR, IDAM_NONE, 0, 0, 0, 0, 0, 0, FALSE, 11, 14, 40, 450, ALIGN }, -/* */ { "Studded Leather Armor", 1, 9, UITYPE_STUDARMOR, ICURS_STUDDED_LEATHER_ARMOR, ITYPE_LARMOR, IMISC_NONE, SPL_NULL, ICLASS_ARMOR, ILOC_ARMOR, IDAM_NONE, 0, 0, 0, 20, 0, 0, FALSE, 15, 17, 45, 700, ALIGN }, +/* */ { "Studded Leather Armor", 1, 9, UITYPE_STUDARMOR, ICURS_STUD_LEATH_ARMOR, ITYPE_LARMOR, IMISC_NONE, SPL_NULL, ICLASS_ARMOR, ILOC_ARMOR, IDAM_NONE, 0, 0, 0, 20, 0, 0, FALSE, 15, 17, 45, 700, ALIGN }, /* */ { "Ring Mail", 1, 10, UITYPE_NONE, ICURS_RING_MAIL, ITYPE_MARMOR, IMISC_NONE, SPL_NULL, ICLASS_ARMOR, ILOC_ARMOR, IDAM_NONE, 0, 0, 0, 25, 0, 0, FALSE, 17, 20, 50, 900, ALIGN }, /* */ { "Chain Mail", 1, 13, UITYPE_CHAINMAIL, ICURS_CHAIN_MAIL, ITYPE_MARMOR, IMISC_NONE, SPL_NULL, ICLASS_ARMOR, ILOC_ARMOR, IDAM_NONE, 0, 0, 0, 30, 0, 0, FALSE, 18, 22, 55, 1250, ALIGN }, /* */ { "Scale Mail", 1, 16, UITYPE_NONE, ICURS_SCALE_MAIL, ITYPE_MARMOR, IMISC_NONE, SPL_NULL, ICLASS_ARMOR, ILOC_ARMOR, IDAM_NONE, 0, 0, 0, 35, 0, 0, FALSE, 23, 28, 60, 2300, ALIGN }, @@ -463,126 +463,126 @@ const AffixData PL_Suffix[] = { /** Contains the data related to each unique item ID. */ const UniqItemData UniqueItemList[NUM_UITEM] = { // clang-format off -// UIName, UIUniqType, UIMinLvl, UIValue, UIPower1, UIParam1a, UIParam1b, UIPower2, UIParam2a, UIParam2b, UIPower3, UIParam3a, UIParam3b, UIPower4, UIParam4a, UIParam4b, UIPower5, UIParam5a, UIParam5b, UIPower6, UIParam6a, UIParam6b, -/*UITEM_CLEAVER*/ { "Butcher's Cleaver", UITYPE_CLEAVER, 1, 5650, IPL_STR, 10, 10, IPL_SETDAM, 4, 24, IPL_SETDUR, 10, 10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_SKCROWN*/ { "The Undead Crown", UITYPE_SKCROWN, 1, 26650, IPL_STEALLIFE, 8, 8, IPL_SETAC, 8, 8, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_INFRARING*/ { "Empyrean Band", UITYPE_INFRARING, 1, 8000, IPL_ATTRIBS, 2, 2, IPL_LIGHT, 2, 2, IPL_FASTRECOVER, 1, 1, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_OPTAMULET*/ { "Optic Amulet", UITYPE_OPTAMULET, 1, 9750, IPL_LIGHT, 2, 2, IPL_LIGHTRES, 20, 20, IPL_GETHIT, 1, 1, IPL_MAG, 5, 5, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_TRING*/ { "Ring of Truth", UITYPE_TRING, 1, 9100, IPL_LIFE, 10, 10, IPL_GETHIT, 1, 1, IPL_ALLRES, 10, 10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_HARCREST*/ { "Harlequin Crest", UITYPE_HARCREST, 1, 4000, IPL_SETAC, 3, 3, IPL_GETHIT, 1, 1, IPL_ATTRIBS, 2, 2, IPL_LIFE, 7, 7, IPL_MANA, 7, 7, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_STEELVEIL*/ { "Veil of Steel", UITYPE_STEELVEIL, 1, 63800, IPL_ALLRES, 50, 50, IPL_LIGHT, -2, -2, IPL_SETAC, 20, 20, IPL_MANA, -30, -30, IPL_STR, 15, 15, IPL_VIT, 15, 15, ALIGN }, -/*UITEM_ARMOFVAL*/ { "Arkaine's Valor", UITYPE_ARMOFVAL, 1, 24000, IPL_SETAC, 25, 25, IPL_VIT, 10, 10, IPL_GETHIT, 3, 3, IPL_FASTRECOVER, 3, 3, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_GRISWOLD*/ { "Griswold's Edge", UITYPE_GRISWOLD, 1, 22000, IPL_FIREDAM, 1, 10, IPL_TOHIT, 25, 25, IPL_FASTATTACK, 2, 2, IPL_KNOCKBACK, 0, 0, IPL_MANA, 20, 20, IPL_LIFE, -20, -20, ALIGN }, +// UIName, UIUniqType, UIMinLvl, UICurs, UIValue, UIPower1, UIParam1a, UIParam1b, UIPower2, UIParam2a, UIParam2b, UIPower3, UIParam3a, UIParam3b, UIPower4, UIParam4a, UIParam4b, UIPower5, UIParam5a, UIParam5b, UIPower6, UIParam6a, UIParam6b, +/*UITEM_CLEAVER*/ { "Butcher's Cleaver", UITYPE_CLEAVER, 1, ICURS_CLEAVER, 5650, IPL_STR, 10, 10, IPL_SETDAM, 4, 24, IPL_SETDUR, 10, 10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_SKCROWN*/ { "The Undead Crown", UITYPE_SKCROWN, 1, ICURS_THE_UNDEAD_CROWN, 26650, IPL_STEALLIFE, 8, 8, IPL_SETAC, 8, 8, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_INFRARING*/ { "Empyrean Band", UITYPE_INFRARING, 1, ICURS_EMPYREAN_BAND, 8000, IPL_ATTRIBS, 2, 2, IPL_LIGHT, 2, 2, IPL_FASTRECOVER, 1, 1, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_OPTAMULET*/ { "Optic Amulet", UITYPE_OPTAMULET, 1, ICURS_OPTIC_AMULET, 9750, IPL_LIGHT, 2, 2, IPL_LIGHTRES, 20, 20, IPL_GETHIT, 1, 1, IPL_MAG, 5, 5, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_TRING*/ { "Ring of Truth", UITYPE_TRING, 1, ICURS_RING_OF_TRUTH, 9100, IPL_LIFE, 10, 10, IPL_GETHIT, 1, 1, IPL_ALLRES, 10, 10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_HARCREST*/ { "Harlequin Crest", UITYPE_HARCREST, 1, ICURS_HARLEQUIN_CREST, 4000, IPL_SETAC, 3, 3, IPL_GETHIT, 1, 1, IPL_ATTRIBS, 2, 2, IPL_LIFE, 7, 7, IPL_MANA, 7, 7, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_STEELVEIL*/ { "Veil of Steel", UITYPE_STEELVEIL, 1, ICURS_VEIL_OF_STEEL, 63800, IPL_ALLRES, 50, 50, IPL_LIGHT, -2, -2, IPL_SETAC, 20, 20, IPL_MANA, -30, -30, IPL_STR, 15, 15, IPL_VIT, 15, 15, ALIGN }, +/*UITEM_ARMOFVAL*/ { "Arkaine's Valor", UITYPE_ARMOFVAL, 1, ICURS_ARKAINES_VALOR, 24000, IPL_SETAC, 25, 25, IPL_VIT, 10, 10, IPL_GETHIT, 3, 3, IPL_FASTRECOVER, 3, 3, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_GRISWOLD*/ { "Griswold's Edge", UITYPE_GRISWOLD, 1, ICURS_BROAD_SWORD, 22000, IPL_FIREDAM, 1, 10, IPL_TOHIT, 25, 25, IPL_FASTATTACK, 2, 2, IPL_KNOCKBACK, 0, 0, IPL_MANA, 20, 20, IPL_LIFE, -20, -20, ALIGN }, #ifdef HELLFIRE -/*UITEM_BOVINE*/ { "Bovine Plate", UITYPE_BOVINE, 1, 40000, IPL_SETAC, 150, 150, IPL_INDESTRUCTIBLE, 0, 0, IPL_LIGHT, 5, 5, IPL_ALLRES, 30, 30, IPL_MANA, -50, -50, IPL_SKILLLEVELS, -2, -2, ALIGN }, +/*UITEM_BOVINE*/ { "Bovine Plate", UITYPE_BOVINE, 1, ICURS_BOVINE, 40000, IPL_SETAC, 150, 150, IPL_INDESTRUCTIBLE, 0, 0, IPL_LIGHT, 5, 5, IPL_ALLRES, 30, 30, IPL_MANA, -50, -50, IPL_SKILLLEVELS, -2, -2, ALIGN }, #else -/*UITEM_LGTFORGE*/ { "Lightforge", UITYPE_MACE, 1, 26675, IPL_LIGHT, 4, 4, IPL_DAMP, 150, 150, IPL_TOHIT, 25, 25, IPL_FIREDAM, 10, 20, IPL_INDESTRUCTIBLE, 0, 0, IPL_ATTRIBS, 8, 8, ALIGN }, +/*UITEM_LGTFORGE*/ { "Lightforge", UITYPE_MACE, 1, ICURS_MACE, 26675, IPL_LIGHT, 4, 4, IPL_DAMP, 150, 150, IPL_TOHIT, 25, 25, IPL_FIREDAM, 10, 20, IPL_INDESTRUCTIBLE, 0, 0, IPL_ATTRIBS, 8, 8, ALIGN }, #endif -/*UITEM_RIFTBOW*/ { "The Rift Bow", UITYPE_SHORTBOW, 1, 1800, IPL_DAMMOD, 2, 2, IPL_DEX, -3, -3, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_NEEDLER*/ { "The Needler", UITYPE_SHORTBOW, 2, 8900, IPL_TOHIT, 50, 50, IPL_SETDAM, 1, 3, IPL_FASTATTACK, 2, 2, IPL_INVCURS, ICURS_THE_NEEDLER, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_CELESTBOW*/ { "The Celestial Bow", UITYPE_LONGBOW, 4, 4200, IPL_NOMINSTR, 0, 0, IPL_DAMMOD, 2, 2, IPL_SETAC, 5, 5, IPL_INVCURS, ICURS_COMPOSITE_BOW, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_DEADLYHUNT*/// { "Deadly Hunter", UITYPE_COMPBOW, 3, 8750, IPL_3XDAMVDEM, 10, 10, IPL_TOHIT, 20, 20, IPL_MAG, -5, -5, IPL_INVCURS, ICURS_BATTLE_BOW, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_BOWOFDEAD*/ { "Bow of the Dead", UITYPE_COMPBOW, 5, 2500, IPL_TOHIT, 10, 10, IPL_DEX, 4, 4, IPL_VIT, -3, -3, IPL_LIGHT, -2, -2, IPL_SETDUR, 30, 30, IPL_INVCURS, ICURS_BATTLE_BOW, 0, ALIGN }, -/*UITEM_BLKOAKBOW*/ { "The Blackoak Bow", UITYPE_LONGBOW, 10, 2800, IPL_DEX, 10, 10, IPL_VIT, -10, -10, IPL_DAMP, 50, 50, IPL_LIGHT, -1, -1, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_FLAMEDART*/ { "Flamedart", UITYPE_HUNTBOW, 10, 14250, IPL_FIREDAM, 1, 6, IPL_TOHIT, 20, 20, IPL_FIRERES, 40, 40, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_FLESHSTING*/ { "Fleshstinger", UITYPE_LONGBOW, 26, 16500, IPL_DEX, 15, 15, IPL_TOHIT, 40, 40, IPL_DAMP, 80, 80, IPL_DUR, 6, 6, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_WINDFORCE*/ { "Windforce", UITYPE_WARBOW, 34, 137750, IPL_STR, 5, 5, IPL_DAMP, 200, 200, IPL_KNOCKBACK, 0, 0, IPL_INVCURS, ICURS_WINDFORCE, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_EAGLEHORN*/ { "Eaglehorn", UITYPE_BATTLEBOW, 42, 57500, IPL_DEX, 20, 20, IPL_TOHIT, 50, 50, IPL_DAMP, 100, 100, IPL_INDESTRUCTIBLE, 0, 0, IPL_INVCURS, ICURS_BATTLE_BOW, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_GONNAGALDIRK*/ { "Gonnagal's Dirk", UITYPE_DAGGER, 1, 9040, IPL_DEX, -5, -5, IPL_DAMMOD, 4, 4, IPL_FASTATTACK, 2, 2, IPL_FIRERES, 25, 25, IPL_INVCURS, ICURS_GONNAGAL_DIRK, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_DEFENDER*/ { "The Defender", UITYPE_SABRE, 4, 1600, IPL_SETAC, 5, 5, IPL_VIT, 5, 5, IPL_TOHIT, -5, -5, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_GRYPHONCLAW*/ { "Gryphon's Claw", UITYPE_FALCHION, 20, 7000, IPL_DAMP, 100, 100, IPL_MAG, -2, -2, IPL_DEX, -5, -5, IPL_INVCURS, ICURS_FALCON_GRYPHON, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_BLACKRAZOR*/ { "Black Razor", UITYPE_DAGGER, 1, 2000, IPL_DAMP, 150, 150, IPL_VIT, 2, 2, IPL_SETDUR, 5, 5, IPL_INVCURS, ICURS_BLACK_RAZOR, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_GIBBOUSMOON*/ { "Gibbous Moon", UITYPE_BROADSWR, 12, 6660, IPL_ATTRIBS, 2, 2, IPL_DAMP, 25, 25, IPL_MANA, 15, 15, IPL_LIGHT, -3, -3, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_ICESHANK*/ { "Ice Shank", UITYPE_LONGSWR, 12, 5250, IPL_FIRERES, 40, 40, IPL_SETDUR, 15, 15, IPL_STR, 5, 10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_EXECUTIONER*/ { "The Executioner's Blade", UITYPE_FALCHION, 35, 17080, IPL_DAMP, 150, 150, IPL_LIFE, -10, -10, IPL_LIGHT, -1, -1, IPL_DUR, 200, 200, IPL_INVCURS, ICURS_EXECUTIONER_BLADE, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_BONESAW*/ { "The Bonesaw", UITYPE_CLAYMORE, 14, 34400, IPL_DAMMOD, 10, 10, IPL_STR, 10, 10, IPL_MAG, -5, -5, IPL_DEX, -5, -5, IPL_LIFE, 10, 10, IPL_MANA, -10, -10, ALIGN }, -/*UITEM_SHADHAWK*/ { "Shadowhawk", UITYPE_BROADSWR, 16, 13750, IPL_LIGHT, -2, -2, IPL_STEALLIFE, 6, 6, IPL_TOHIT, 15, 15, IPL_ALLRES, 5, 5, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_WIZSPIKE*/ { "Wizardspike", UITYPE_DAGGER, 11, 12920, IPL_MAG, 15, 15, IPL_MANA, 35, 35, IPL_TOHIT, 25, 25, IPL_ALLRES, 15, 15, IPL_INVCURS, ICURS_WIZARDSPIKE, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_LGTSABRE*/ { "Lightsabre", UITYPE_SABRE, 13, 19150, IPL_LIGHT, 2, 2, IPL_LIGHTDAM, 1, 10, IPL_TOHIT, 20, 20, IPL_LIGHTRES, 50, 50, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_FALCONTALON*/ { "The Falcon's Talon", UITYPE_SCIMITAR, 15, 7867, IPL_FASTATTACK, 4, 4, IPL_TOHIT, 20, 20, IPL_DAMP, -33, -33, IPL_DEX, 10, 10, IPL_INVCURS, ICURS_FALCON_GRYPHON, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_INFERNO*/ { "Inferno", UITYPE_LONGSWR, 17, 34600, IPL_FIREDAM, 2, 12, IPL_LIGHT, 3, 3, IPL_MANA, 20, 20, IPL_FIRERES, 80, 80, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_DOOMBRINGER*/ { "Doombringer", UITYPE_BASTARDSWR, 38, 68250, IPL_TOHIT, 25, 25, IPL_DAMP, 250, 250, IPL_ATTRIBS, -5, -5, IPL_LIFE, -25, -25, IPL_LIGHT, -2, -2, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_GRIZZLY*/ { "The Grizzly", UITYPE_TWOHANDSWR, 23, 112100, IPL_STR, 20, 20, IPL_VIT, -5, -5, IPL_DAMP, 200, 200, IPL_KNOCKBACK, 0, 0, IPL_DUR, 100, 100, IPL_INVCURS, ICURS_THE_GRIZZLY, 0, ALIGN }, -/*UITEM_GRANDFATHER*/ { "The Grandfather", UITYPE_GREATSWR, 27, 119800, IPL_ONEHAND, 0, 0, IPL_ATTRIBS, 5, 5, IPL_TOHIT, 20, 20, IPL_DAMP, 70, 70, IPL_LIFE, 20, 20, IPL_INVCURS, ICURS_THE_GRANDFATHER, 0, ALIGN }, -/*UITEM_MANGLER*/ { "The Mangler", UITYPE_LARGEAXE, 35, 49688, IPL_DAMP, 200, 200, IPL_DEX, -5, -5, IPL_MAG, -5, -5, IPL_MANA, -10, -10, IPL_INVCURS, ICURS_AXE, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_SHARPBEAK*/ { "Sharp Beak", UITYPE_LARGEAXE, 16, 2850, IPL_LIFE, 20, 20, IPL_MAG, -10, -10, IPL_MANA, -10, -10, IPL_INVCURS, ICURS_GREAT_AXE, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_BLOODLSLAYER*///{ "BloodSlayer", UITYPE_BROADAXE, 3, 2500, IPL_DAMP, 100, 100, IPL_3XDAMVDEM, 50, 50, IPL_ATTRIBS, -5, -5, IPL_SKILLLEVELS, -1, -1, IPL_INVCURS, ICURS_AXE, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_CELESTAXE*/ { "The Celestial Axe", UITYPE_BATTLEAXE, 12, 14100, IPL_NOMINSTR, 0, 0, IPL_TOHIT, 15, 15, IPL_LIFE, 15, 15, IPL_STR, -15, -15, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_WICKEDAXE*/ { "Wicked Axe", UITYPE_LARGEAXE, 14, 31150, IPL_TOHIT, 30, 30, IPL_DEX, 10, 10, IPL_VIT, -10, -10, IPL_GETHIT, 1, 6, IPL_INDESTRUCTIBLE, 0, 0, IPL_INVCURS, ICURS_GREAT_AXE, 0, ALIGN }, -/*UITEM_STONECLEAV*/ { "Stonecleaver", UITYPE_BROADAXE, 20, 23900, IPL_LIFE, 30, 30, IPL_TOHIT, 20, 20, IPL_DAMP, 50, 50, IPL_LIGHTRES, 40, 40, IPL_INVCURS, ICURS_STONECLEAVER, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_AGUHATCHET*/ { "Aguinara's Hatchet", UITYPE_SMALLAXE, 12, 24800, IPL_SKILLLEVELS, 1, 1, IPL_MAG, 10, 10, IPL_MAGICRES, 80, 80, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_HELLSLAYER*/ { "Hellslayer", UITYPE_BATTLEAXE, 30, 26200, IPL_STR, 8, 8, IPL_VIT, 8, 8, IPL_DAMP, 100, 100, IPL_LIFE, 25, 25, IPL_MANA, -25, -25, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_MESSERREAVER*/ { "Messerschmidt's Reaver", UITYPE_GREATAXE, 50, 158000, IPL_DAMP, 200, 200, IPL_DAMMOD, 15, 15, IPL_ATTRIBS, 5, 5, IPL_LIFE, -50, -50, IPL_FIREDAM, 2, 12, IPL_INVCURS, ICURS_MESSERSCHMIDT, 0, ALIGN }, -/*UITEM_CRACKRUST*/ { "Crackrust", UITYPE_MACE, 8, 11375, IPL_ATTRIBS, 2, 2, IPL_INDESTRUCTIBLE, 0, 0, IPL_ALLRES, 15, 15, IPL_DAMP, 50, 50, IPL_SKILLLEVELS, -1, -1, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_JHOLMHAMM*/ { "Hammer of Jholm", UITYPE_MAUL, 12, 8700, IPL_DAMP, 4, 10, IPL_INDESTRUCTIBLE, 0, 0, IPL_STR, 3, 3, IPL_TOHIT, 15, 15, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_CIVERBS*/// { "Civerb's Cudgel", UITYPE_MACE, 1, 2000, IPL_3XDAMVDEM, 35, 35, IPL_DEX, -5, -5, IPL_MAG, -2, -2, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_CELESTSTAR*/ { "The Celestial Star", UITYPE_FLAIL, 14, 17810, IPL_NOMINSTR, 0, 0, IPL_LIGHT, 2, 2, IPL_DAMMOD, 10, 10, IPL_ACMOD, -8, -8, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_BARANSTAR*/ { "Baranar's Star", UITYPE_MORNSTAR, 14, 6850, IPL_TOHIT, 12, 12, IPL_DAMP, 80, 80, IPL_FASTATTACK, 1, 1, IPL_VIT, 4, 4, IPL_DEX, -4, -4, IPL_SETDUR, 60, 60, ALIGN }, -/*UITEM_GNARLROOT*/ { "Gnarled Root", UITYPE_SPIKCLUB, 16, 49820, IPL_TOHIT, 20, 20, IPL_DAMP, 300, 300, IPL_DEX, 10, 10, IPL_MAG, 5, 5, IPL_ALLRES, 10, 10, IPL_ACMOD, -10, -10, ALIGN }, -/*UITEM_CRANBASH*/ { "The Cranium Basher", UITYPE_MAUL, 16, 36500, IPL_DAMMOD, 20, 20, IPL_STR, 15, 15, IPL_INDESTRUCTIBLE, 0, 0, IPL_MANA, -150, -150, IPL_ALLRES, 5, 5, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_SCHAEFHAMM*/ { "Schaefer's Hammer", UITYPE_WARHAMMER, 16, 56125, IPL_DAMP, -100, -100, IPL_LIGHTDAM, 1, 50, IPL_LIFE, 50, 50, IPL_TOHIT, 30, 30, IPL_LIGHTRES, 80, 80, IPL_LIGHT, 1, 1, ALIGN }, -/*UITEM_DREAMFLANGE*/ { "Dreamflange", UITYPE_MACE, 26, 26450, IPL_MAG, 30, 30, IPL_MANA, 50, 50, IPL_MAGICRES, 50, 50, IPL_LIGHT, 2, 2, IPL_SKILLLEVELS, 1, 1, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_STAFFOFSHAD*/ { "Staff of Shadows", UITYPE_LONGSTAFF, 4, 4250, IPL_MAG, -10, -10, IPL_TOHIT, 10, 10, IPL_DAMP, 60, 60, IPL_LIGHT, -2, -2, IPL_FASTATTACK, 1, 1, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_IMMOLATOR*/ { "Immolator", UITYPE_LONGSTAFF, 6, 3900, IPL_FIRERES, 20, 20, IPL_FIREDAM, 4, 4, IPL_MANA, 10, 10, IPL_VIT, -5, -5, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_STORMSPIRE*/ { "Storm Spire", UITYPE_WARSTAFF, 20, 22500, IPL_LIGHTRES, 50, 50, IPL_LIGHTDAM, 2, 8, IPL_STR, 10, 10, IPL_MAG, -10, -10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_GLEAMSONG*/ { "Gleamsong", UITYPE_SHORTSTAFF, 8, 6520, IPL_MANA, 25, 25, IPL_STR, -3, -3, IPL_VIT, -3, -3, IPL_SPELL, SPL_RNDTELEPORT, 76, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_THUNDERCALL*/ { "Thundercall", UITYPE_COMPSTAFF, 14, 22250, IPL_TOHIT, 35, 35, IPL_LIGHTDAM, 1, 10, IPL_SPELL, SPL_LIGHTNING, 76, IPL_LIGHTRES, 30, 30, IPL_LIGHT, 2, 2, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_PROTECTOR*/ { "The Protector", UITYPE_SHORTSTAFF, 16, 17240, IPL_VIT, 5, 5, IPL_GETHIT, 5, 5, IPL_SETAC, 40, 40, IPL_SPELL, SPL_HEAL, 86, IPL_ALLRES, 5, 5, IPL_INVCURS, ICURS_THE_PROTECTOR, 0, ALIGN }, -/*UITEM_NAJPUZZLE*/ { "Naj's Puzzler", UITYPE_LONGSTAFF, 18, 34000, IPL_MAG, 20, 20, IPL_DEX, 10, 10, IPL_ALLRES, 20, 20, IPL_SPELL, SPL_TELEPORT, 57, IPL_LIFE, -25, -25, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_MINDCRY*/ { "Mindcry", UITYPE_QUARSTAFF, 20, 41500, IPL_MAG, 15, 15, IPL_SPELL, SPL_GUARDIAN, 69, IPL_ALLRES, 15, 15, IPL_SKILLLEVELS, 1, 1, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_RODOFONAN*/ { "Rod of Onan", UITYPE_WARSTAFF, 22, 44167, IPL_SPELL, SPL_GOLEM, 50, IPL_DAMP, 100, 100, IPL_ATTRIBS, 5, 5, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_SPIRITSHELM*/ { "Helm of Spirits", UITYPE_HELM, 1, 17525, IPL_STEALLIFE, 6, 6, IPL_INVCURS, ICURS_HELM_OF_SPIRITS, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_THINKINGCAP*/ { "Thinking Cap", UITYPE_SKULLCAP, 6, 2020, IPL_MANA, 30, 30, IPL_SKILLLEVELS, 2, 2, IPL_ALLRES, 20, 20, IPL_SETDUR, 1, 1, IPL_INVCURS, ICURS_THINKING_CAP, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_OVERLORDHELM*/ { "OverLord's Helm", UITYPE_HELM, 7, 12500, IPL_STR, 20, 20, IPL_DEX, 15, 15, IPL_VIT, 5, 5, IPL_MAG, -20, -20, IPL_SETDUR, 15, 15, IPL_INVCURS, ICURS_OVERLORD_HELM, 0, ALIGN }, -/*UITEM_FOOLSCREST*/ { "Fool's Crest", UITYPE_HELM, 12, 20150, IPL_STR, -4, -4, IPL_LIFE, 100, 100, IPL_GETHIT, -6, -1, IPL_DEX, 5, 10, IPL_MAG, -8, -8, IPL_INVCURS, ICURS_FOOL_CREST, 0, ALIGN }, -/*UITEM_GOTTERDAM*/ { "Gotterdamerung", UITYPE_GREATHELM, 21, 54900, IPL_ATTRIBS, 20, 20, IPL_SETAC, 60, 60, IPL_GETHIT, 4, 4, IPL_ALLRESZERO, 0, 0, IPL_LIGHT, -4, -4, IPL_INVCURS, ICURS_VEIL_OF_STEEL, 0, ALIGN }, -/*UITEM_ROYCIRCLET*/ { "Royal Circlet", UITYPE_CROWN, 27, 24875, IPL_ATTRIBS, 10, 10, IPL_MANA, 40, 40, IPL_SETAC, 40, 40, IPL_LIGHT, 1, 1, IPL_INVCURS, ICURS_ROYAL_CIRCLET, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_TORNFLESH*/ { "Torn Flesh of Souls", UITYPE_RAGS, 2, 4825, IPL_SETAC, 8, 8, IPL_VIT, 10, 10, IPL_GETHIT, 1, 1, IPL_INDESTRUCTIBLE, 0, 0, IPL_INVCURS, ICURS_FLESH_OF_SOULS, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_GLADBANE*/ { "The Gladiator's Bane", UITYPE_STUDARMOR, 6, 3450, IPL_SETAC, 25, 25, IPL_GETHIT, 2, 2, IPL_DUR, 200, 200, IPL_ATTRIBS, -3, -3, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_RAINCLOAK*/ { "The Rainbow Cloak", UITYPE_CLOAK, 2, 4900, IPL_SETAC, 10, 10, IPL_ATTRIBS, 1, 1, IPL_ALLRES, 10, 10, IPL_LIFE, 5, 5, IPL_DUR, 50, 50, IPL_INVCURS, ICURS_UCLOAK, 0, ALIGN }, -/*UITEM_LEATHAUT*/ { "Leather of Aut", UITYPE_LEATHARMOR, 4, 10550, IPL_SETAC, 15, 15, IPL_STR, 5, 5, IPL_MAG, -5, -5, IPL_DEX, 5, 5, IPL_INDESTRUCTIBLE, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_WISDWRAP*/ { "Wisdom's Wrap", UITYPE_ROBE, 5, 6200, IPL_MAG, 5, 5, IPL_MANA, 10, 10, IPL_LIGHTRES, 25, 25, IPL_SETAC, 15, 15, IPL_GETHIT, 1, 1, IPL_INVCURS, ICURS_UCLOAK, 0, ALIGN }, -/*UITEM_SPARKMAIL*/ { "Sparking Mail", UITYPE_CHAINMAIL, 9, 15750, IPL_SETAC, 30, 30, IPL_LIGHTDAM, 1, 10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_SCAVCARAP*/ { "Scavenger Carapace", UITYPE_BREASTPLATE, 13, 34000, IPL_GETHIT, 15, 15, IPL_ACMOD, -30, -30, IPL_DEX, 5, 5, IPL_LIGHTRES, 40, 40, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_NIGHTSCAPE*/ { "Nightscape", UITYPE_CAPE, 16, 11600, IPL_FASTRECOVER, 2, 2, IPL_LIGHT, -4, -4, IPL_SETAC, 15, 15, IPL_DEX, 3, 3, IPL_ALLRES, 20, 20, IPL_INVCURS, ICURS_UCLOAK, 0, ALIGN }, -/*UITEM_NAJPLATE*/ { "Naj's Light Plate", UITYPE_PLATEMAIL, 19, 78700, IPL_NOMINSTR, 0, 0, IPL_MAG, 5, 5, IPL_MANA, 20, 20, IPL_ALLRES, 20, 20, IPL_SKILLLEVELS, 1, 1, IPL_INVCURS, ICURS_NAJ_PLATE, 0, ALIGN }, -/*UITEM_DEMONSPIKE*/ { "Demonspike Coat", UITYPE_FULLPLATE, 25, 251175, IPL_SETAC, 100, 100, IPL_GETHIT, 6, 6, IPL_STR, 10, 10, IPL_INDESTRUCTIBLE, 0, 0, IPL_FIRERES, 50, 50, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_DEFLECTOR*/ { "The Deflector", UITYPE_BUCKLER, 1, 1500, IPL_SETAC, 7, 7, IPL_ALLRES, 10, 10, IPL_DAMP, -20, -20, IPL_TOHIT, -5, -5, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_SKULLSHLD*/ { "Split Skull Shield", UITYPE_BUCKLER, 1, 2025, IPL_SETAC, 10, 10, IPL_LIFE, 10, 10, IPL_STR, 2, 2, IPL_LIGHT, -1, -1, IPL_SETDUR, 15, 15, IPL_INVCURS, ICURS_SKULL_SHIELD, 0, ALIGN }, -/*UITEM_DRAGONBRCH*/ { "Dragon's Breach", UITYPE_KITESHIELD, 2, 19200, IPL_FIRERES, 25, 25, IPL_STR, 5, 5, IPL_SETAC, 20, 20, IPL_MAG, -5, -5, IPL_INDESTRUCTIBLE, 0, 0, IPL_INVCURS, ICURS_DRAGON_SHIELD, 0, ALIGN }, -/*UITEM_BLKOAKSHLD*/ { "Blackoak Shield", UITYPE_SMALLSHIELD, 4, 5725, IPL_DEX, 10, 10, IPL_VIT, -10, -10, IPL_SETAC, 18, 18, IPL_LIGHT, -1, -1, IPL_DUR, 150, 150, IPL_INVCURS, ICURS_HOLY_DEFENDER, 0, ALIGN }, -/*UITEM_HOLYDEF*/ { "Holy Defender", UITYPE_LARGESHIELD, 10, 13800, IPL_SETAC, 15, 15, IPL_GETHIT, 2, 2, IPL_FIRERES, 20, 20, IPL_DUR, 200, 200, IPL_FASTBLOCK, 1, 1, IPL_INVCURS, ICURS_HOLY_DEFENDER, 0, ALIGN }, -/*UITEM_SPIRITSHLD*/ { "Spirit Ward", UITYPE_TOWERSHIELD, 24, 39200, IPL_ACMOD, 10, 10, IPL_FASTRECOVER, 2, 2, IPL_ALLRES, 6, 12, IPL_VIT, 4, 10, IPL_INVCURS, ICURS_SPIRIT_SHIELD, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_STORMSHLD*/ { "Stormshield", UITYPE_GOTHSHIELD, 24, 49000, IPL_SETAC, 40, 40, IPL_GETHIT, -4, -4, IPL_STR, 10, 10, IPL_INDESTRUCTIBLE, 0, 0, IPL_FASTBLOCK, 1, 1, IPL_INVCURS, ICURS_STORMSHIELD, 0, ALIGN }, -/*UITEM_BRAMBLE*/ { "Bramble", UITYPE_RING, 1, 1000, IPL_ATTRIBS, -2, -2, IPL_DAMMOD, 3, 3, IPL_MANA, 10, 10, IPL_INVCURS, ICURS_RING_BRAMBLE, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_TYRAELGIFT*/ { "Tyrael's Gift", UITYPE_AMULET, 44, 46105, IPL_VIT, 10, 10, IPL_LIFE, 30, 30, IPL_GETHIT, 8, 8, IPL_NO_BLEED, 0, 0, IPL_INVCURS, ICURS_AMULET_TYRAEL, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_LILITHCOLLAR*/ { "Collar of Lilith", UITYPE_AMULET, 48, 54175, IPL_LIFE, 40, 40, IPL_STEALLIFE, 3, 3, IPL_BLEED, 0, 0, IPL_INVCURS, ICURS_AMULET_LILITH, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_BLEEDER*/ { "The Bleeder", UITYPE_RING, 2, 8500, IPL_MAGICRES, 20, 20, IPL_MANA, 30, 30, IPL_LIFE, -10, -10, IPL_INVCURS, ICURS_RING_BLEEDER, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_CONSTRICT*/ { "Constricting Ring", UITYPE_RING, 5, 62000, IPL_ALLRES, 95, 95, IPL_DRAINLIFE, 0, 0, IPL_INVCURS, ICURS_RING_CONSTRICTING, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_ENGAGERING*/ { "Ring of Engagement", UITYPE_RING, 11, 12476, IPL_GETHIT, 1, 2, IPL_STR, 5, 10, IPL_SETAC, 5, 5, IPL_PENETRATE_PHYS, 0, 0, IPL_INVCURS, ICURS_GOLD_RING, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_DESTRING*/ { "Ring of Destruction", UITYPE_RING, 28, 31250, IPL_CRITP, 100, 140, IPL_ACMOD, -60, -60, IPL_TOHIT, 60, 100, IPL_GETHIT, -4, -1, IPL_INVCURS, ICURS_RING_DESTRUCTION, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_RAINBOWRING*/ { "Rainbow of Jordan", UITYPE_RING, 48, 42750, IPL_SKILLLEVELS, 1, 1, IPL_SKILLLVL, 1, 2, IPL_LIFE, 30, 50, IPL_INVCURS, ICURS_GOLD_RING, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_RIFTBOW*/ { "The Rift Bow", UITYPE_SHORTBOW, 1, ICURS_SHORT_BOW, 1800, IPL_DAMMOD, 2, 2, IPL_DEX, -3, -3, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_NEEDLER*/ { "The Needler", UITYPE_SHORTBOW, 2, ICURS_THE_NEEDLER, 8900, IPL_TOHIT, 50, 50, IPL_SETDAM, 1, 3, IPL_FASTATTACK, 2, 2, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_CELESTBOW*/ { "The Celestial Bow", UITYPE_LONGBOW, 4, ICURS_COMPOSITE_BOW, 4200, IPL_NOMINSTR, 0, 0, IPL_DAMMOD, 2, 2, IPL_SETAC, 5, 5, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_DEADLYHUNT*/// { "Deadly Hunter", UITYPE_COMPBOW, 3, ICURS_BATTLE_BOW, 8750, IPL_3XDAMVDEM, 10, 10, IPL_TOHIT, 20, 20, IPL_MAG, -5, -5, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_BOWOFDEAD*/ { "Bow of the Dead", UITYPE_COMPBOW, 5, ICURS_BATTLE_BOW, 2500, IPL_TOHIT, 10, 10, IPL_DEX, 4, 4, IPL_VIT, -3, -3, IPL_LIGHT, -2, -2, IPL_SETDUR, 30, 30, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_BLKOAKBOW*/ { "The Blackoak Bow", UITYPE_LONGBOW, 10, ICURS_HUNTERS_BOW, 2800, IPL_DEX, 10, 10, IPL_VIT, -10, -10, IPL_DAMP, 50, 50, IPL_LIGHT, -1, -1, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_FLAMEDART*/ { "Flamedart", UITYPE_HUNTBOW, 10, ICURS_HUNTERS_BOW, 14250, IPL_FIREDAM, 1, 6, IPL_TOHIT, 20, 20, IPL_FIRERES, 40, 40, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_FLESHSTING*/ { "Fleshstinger", UITYPE_LONGBOW, 26, ICURS_HUNTERS_BOW, 16500, IPL_DEX, 15, 15, IPL_TOHIT, 40, 40, IPL_DAMP, 80, 80, IPL_DUR, 6, 6, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_WINDFORCE*/ { "Windforce", UITYPE_WARBOW, 34, ICURS_WINDFORCE, 137750, IPL_STR, 5, 5, IPL_DAMP, 200, 200, IPL_KNOCKBACK, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_EAGLEHORN*/ { "Eaglehorn", UITYPE_BATTLEBOW, 42, ICURS_BATTLE_BOW, 57500, IPL_DEX, 20, 20, IPL_TOHIT, 50, 50, IPL_DAMP, 100, 100, IPL_INDESTRUCTIBLE, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_GONNAGALDIRK*/ { "Gonnagal's Dirk", UITYPE_DAGGER, 1, ICURS_GONNAGAL_DIRK, 9040, IPL_DEX, -5, -5, IPL_DAMMOD, 4, 4, IPL_FASTATTACK, 2, 2, IPL_FIRERES, 25, 25, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_DEFENDER*/ { "The Defender", UITYPE_SABRE, 4, ICURS_SABRE, 1600, IPL_SETAC, 5, 5, IPL_VIT, 5, 5, IPL_TOHIT, -5, -5, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_GRYPHONCLAW*/ { "Gryphon's Claw", UITYPE_FALCHION, 20, ICURS_FALCON_GRYPHON, 7000, IPL_DAMP, 100, 100, IPL_MAG, -2, -2, IPL_DEX, -5, -5, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_BLACKRAZOR*/ { "Black Razor", UITYPE_DAGGER, 1, ICURS_BLACK_RAZOR, 2000, IPL_DAMP, 150, 150, IPL_VIT, 2, 2, IPL_SETDUR, 5, 5, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_GIBBOUSMOON*/ { "Gibbous Moon", UITYPE_BROADSWR, 12, ICURS_BROAD_SWORD, 6660, IPL_ATTRIBS, 2, 2, IPL_DAMP, 25, 25, IPL_MANA, 15, 15, IPL_LIGHT, -3, -3, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_ICESHANK*/ { "Ice Shank", UITYPE_LONGSWR, 12, ICURS_LONG_SWORD, 5250, IPL_FIRERES, 40, 40, IPL_SETDUR, 15, 15, IPL_STR, 5, 10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_EXECUTIONER*/ { "The Executioner's Blade", UITYPE_FALCHION, 35, ICURS_EXECUTIONER_BLADE, 17080, IPL_DAMP, 150, 150, IPL_LIFE, -10, -10, IPL_LIGHT, -1, -1, IPL_DUR, 200, 200, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_BONESAW*/ { "The Bonesaw", UITYPE_CLAYMORE, 14, ICURS_CLAYMORE, 34400, IPL_DAMMOD, 10, 10, IPL_STR, 10, 10, IPL_MAG, -5, -5, IPL_DEX, -5, -5, IPL_LIFE, 10, 10, IPL_MANA, -10, -10, ALIGN }, +/*UITEM_SHADHAWK*/ { "Shadowhawk", UITYPE_BROADSWR, 16, ICURS_BROAD_SWORD, 13750, IPL_LIGHT, -2, -2, IPL_STEALLIFE, 6, 6, IPL_TOHIT, 15, 15, IPL_ALLRES, 5, 5, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_WIZSPIKE*/ { "Wizardspike", UITYPE_DAGGER, 11, ICURS_WIZARDSPIKE, 12920, IPL_MAG, 15, 15, IPL_MANA, 35, 35, IPL_TOHIT, 25, 25, IPL_ALLRES, 15, 15, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_LGTSABRE*/ { "Lightsabre", UITYPE_SABRE, 13, ICURS_SABRE, 19150, IPL_LIGHT, 2, 2, IPL_LIGHTDAM, 1, 10, IPL_TOHIT, 20, 20, IPL_LIGHTRES, 50, 50, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_FALCONTALON*/ { "The Falcon's Talon", UITYPE_SCIMITAR, 15, ICURS_FALCON_GRYPHON, 7867, IPL_FASTATTACK, 4, 4, IPL_TOHIT, 20, 20, IPL_DAMP, -33, -33, IPL_DEX, 10, 10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_INFERNO*/ { "Inferno", UITYPE_LONGSWR, 17, ICURS_LONG_SWORD, 34600, IPL_FIREDAM, 2, 12, IPL_LIGHT, 3, 3, IPL_MANA, 20, 20, IPL_FIRERES, 80, 80, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_DOOMBRINGER*/ { "Doombringer", UITYPE_BASTARDSWR, 38, ICURS_BASTARD_SWORD, 68250, IPL_TOHIT, 25, 25, IPL_DAMP, 250, 250, IPL_ATTRIBS, -5, -5, IPL_LIFE, -25, -25, IPL_LIGHT, -2, -2, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_GRIZZLY*/ { "The Grizzly", UITYPE_TWOHANDSWR, 23, ICURS_THE_GRIZZLY, 112100, IPL_STR, 20, 20, IPL_VIT, -5, -5, IPL_DAMP, 200, 200, IPL_KNOCKBACK, 0, 0, IPL_DUR, 100, 100, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_GRANDFATHER*/ { "The Grandfather", UITYPE_GREATSWR, 27, ICURS_THE_GRANDFATHER, 119800, IPL_ONEHAND, 0, 0, IPL_ATTRIBS, 5, 5, IPL_TOHIT, 20, 20, IPL_DAMP, 70, 70, IPL_LIFE, 20, 20, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_MANGLER*/ { "The Mangler", UITYPE_LARGEAXE, 35, ICURS_AXE, 49688, IPL_DAMP, 200, 200, IPL_DEX, -5, -5, IPL_MAG, -5, -5, IPL_MANA, -10, -10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_SHARPBEAK*/ { "Sharp Beak", UITYPE_LARGEAXE, 16, ICURS_GREAT_AXE, 2850, IPL_LIFE, 20, 20, IPL_MAG, -10, -10, IPL_MANA, -10, -10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_BLOODLSLAYER*///{ "BloodSlayer", UITYPE_BROADAXE, 3, ICURS_AXE, 2500, IPL_DAMP, 100, 100, IPL_3XDAMVDEM, 50, 50, IPL_ATTRIBS, -5, -5, IPL_SKILLLEVELS, -1, -1, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_CELESTAXE*/ { "The Celestial Axe", UITYPE_BATTLEAXE, 12, ICURS_BATTLE_AXE, 14100, IPL_NOMINSTR, 0, 0, IPL_TOHIT, 15, 15, IPL_LIFE, 15, 15, IPL_STR, -15, -15, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_WICKEDAXE*/ { "Wicked Axe", UITYPE_LARGEAXE, 14, ICURS_GREAT_AXE, 31150, IPL_TOHIT, 30, 30, IPL_DEX, 10, 10, IPL_VIT, -10, -10, IPL_GETHIT, 1, 6, IPL_INDESTRUCTIBLE, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_STONECLEAV*/ { "Stonecleaver", UITYPE_BROADAXE, 20, ICURS_STONECLEAVER, 23900, IPL_LIFE, 30, 30, IPL_TOHIT, 20, 20, IPL_DAMP, 50, 50, IPL_LIGHTRES, 40, 40, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_AGUHATCHET*/ { "Aguinara's Hatchet", UITYPE_SMALLAXE, 12, ICURS_SMALL_AXE, 24800, IPL_SKILLLEVELS, 1, 1, IPL_MAG, 10, 10, IPL_MAGICRES, 80, 80, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_HELLSLAYER*/ { "Hellslayer", UITYPE_BATTLEAXE, 30, ICURS_BATTLE_AXE, 26200, IPL_STR, 8, 8, IPL_VIT, 8, 8, IPL_DAMP, 100, 100, IPL_LIFE, 25, 25, IPL_MANA, -25, -25, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_MESSERREAVER*/ { "Messerschmidt's Reaver", UITYPE_GREATAXE, 50, ICURS_MESSERSCHMIDT, 158000, IPL_DAMP, 200, 200, IPL_DAMMOD, 15, 15, IPL_ATTRIBS, 5, 5, IPL_LIFE, -50, -50, IPL_FIREDAM, 2, 12, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_CRACKRUST*/ { "Crackrust", UITYPE_MACE, 8, ICURS_MACE, 11375, IPL_ATTRIBS, 2, 2, IPL_INDESTRUCTIBLE, 0, 0, IPL_ALLRES, 15, 15, IPL_DAMP, 50, 50, IPL_SKILLLEVELS, -1, -1, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_JHOLMHAMM*/ { "Hammer of Jholm", UITYPE_MAUL, 12, ICURS_MAUL, 8700, IPL_DAMP, 4, 10, IPL_INDESTRUCTIBLE, 0, 0, IPL_STR, 3, 3, IPL_TOHIT, 15, 15, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_CIVERBS*/// { "Civerb's Cudgel", UITYPE_MACE, 1, ICURS_MACE, 2000, IPL_3XDAMVDEM, 35, 35, IPL_DEX, -5, -5, IPL_MAG, -2, -2, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_CELESTSTAR*/ { "The Celestial Star", UITYPE_FLAIL, 14, ICURS_FLAIL, 17810, IPL_NOMINSTR, 0, 0, IPL_LIGHT, 2, 2, IPL_DAMMOD, 10, 10, IPL_ACMOD, -8, -8, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_BARANSTAR*/ { "Baranar's Star", UITYPE_MORNSTAR, 14, ICURS_MORNING_STAR, 6850, IPL_TOHIT, 12, 12, IPL_DAMP, 80, 80, IPL_FASTATTACK, 1, 1, IPL_VIT, 4, 4, IPL_DEX, -4, -4, IPL_SETDUR, 60, 60, ALIGN }, +/*UITEM_GNARLROOT*/ { "Gnarled Root", UITYPE_SPIKCLUB, 16, ICURS_GNARLROOT, 49820, IPL_TOHIT, 20, 20, IPL_DAMP, 300, 300, IPL_DEX, 10, 10, IPL_MAG, 5, 5, IPL_ALLRES, 10, 10, IPL_ACMOD, -10, -10, ALIGN }, +/*UITEM_CRANBASH*/ { "The Cranium Basher", UITYPE_MAUL, 16, ICURS_MAUL, 36500, IPL_DAMMOD, 20, 20, IPL_STR, 15, 15, IPL_INDESTRUCTIBLE, 0, 0, IPL_MANA, -150, -150, IPL_ALLRES, 5, 5, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_SCHAEFHAMM*/ { "Schaefer's Hammer", UITYPE_WARHAMMER, 16, ICURS_WAR_HAMMER, 56125, IPL_DAMP, -100, -100, IPL_LIGHTDAM, 1, 50, IPL_LIFE, 50, 50, IPL_TOHIT, 30, 30, IPL_LIGHTRES, 80, 80, IPL_LIGHT, 1, 1, ALIGN }, +/*UITEM_DREAMFLANGE*/ { "Dreamflange", UITYPE_MACE, 26, ICURS_MACE, 26450, IPL_MAG, 30, 30, IPL_MANA, 50, 50, IPL_MAGICRES, 50, 50, IPL_LIGHT, 2, 2, IPL_SKILLLEVELS, 1, 1, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_STAFFOFSHAD*/ { "Staff of Shadows", UITYPE_LONGSTAFF, 4, ICURS_LONG_STAFF, 4250, IPL_MAG, -10, -10, IPL_TOHIT, 10, 10, IPL_DAMP, 60, 60, IPL_LIGHT, -2, -2, IPL_FASTATTACK, 1, 1, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_IMMOLATOR*/ { "Immolator", UITYPE_LONGSTAFF, 6, ICURS_LONG_STAFF, 3900, IPL_FIRERES, 20, 20, IPL_FIREDAM, 4, 4, IPL_MANA, 10, 10, IPL_VIT, -5, -5, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_STORMSPIRE*/ { "Storm Spire", UITYPE_WARSTAFF, 20, ICURS_WAR_STAFF, 22500, IPL_LIGHTRES, 50, 50, IPL_LIGHTDAM, 2, 8, IPL_STR, 10, 10, IPL_MAG, -10, -10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_GLEAMSONG*/ { "Gleamsong", UITYPE_SHORTSTAFF, 8, ICURS_SHORT_STAFF, 6520, IPL_MANA, 25, 25, IPL_STR, -3, -3, IPL_VIT, -3, -3, IPL_SPELL, SPL_RNDTELEPORT, 76, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_THUNDERCALL*/ { "Thundercall", UITYPE_COMPSTAFF, 14, ICURS_COMPOSITE_STAFF, 22250, IPL_TOHIT, 35, 35, IPL_LIGHTDAM, 1, 10, IPL_SPELL, SPL_LIGHTNING, 76, IPL_LIGHTRES, 30, 30, IPL_LIGHT, 2, 2, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_PROTECTOR*/ { "The Protector", UITYPE_SHORTSTAFF, 16, ICURS_THE_PROTECTOR, 17240, IPL_VIT, 5, 5, IPL_GETHIT, 5, 5, IPL_SETAC, 40, 40, IPL_SPELL, SPL_HEAL, 86, IPL_ALLRES, 5, 5, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_NAJPUZZLE*/ { "Naj's Puzzler", UITYPE_LONGSTAFF, 18, ICURS_LONG_STAFF, 34000, IPL_MAG, 20, 20, IPL_DEX, 10, 10, IPL_ALLRES, 20, 20, IPL_SPELL, SPL_TELEPORT, 57, IPL_LIFE, -25, -25, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_MINDCRY*/ { "Mindcry", UITYPE_QUARSTAFF, 20, ICURS_SHORT_STAFF, 41500, IPL_MAG, 15, 15, IPL_SPELL, SPL_GUARDIAN, 69, IPL_ALLRES, 15, 15, IPL_SKILLLEVELS, 1, 1, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_RODOFONAN*/ { "Rod of Onan", UITYPE_WARSTAFF, 22, ICURS_WAR_STAFF, 44167, IPL_SPELL, SPL_GOLEM, 50, IPL_DAMP, 100, 100, IPL_ATTRIBS, 5, 5, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_SPIRITSHELM*/ { "Helm of Spirits", UITYPE_HELM, 1, ICURS_HELM_OF_SPIRITS, 17525, IPL_STEALLIFE, 6, 6, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_THINKINGCAP*/ { "Thinking Cap", UITYPE_SKULLCAP, 6, ICURS_THINKING_CAP, 2020, IPL_MANA, 30, 30, IPL_SKILLLEVELS, 2, 2, IPL_ALLRES, 20, 20, IPL_SETDUR, 1, 1, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_OVERLORDHELM*/ { "OverLord's Helm", UITYPE_HELM, 7, ICURS_OVERLORD_HELM, 12500, IPL_STR, 20, 20, IPL_DEX, 15, 15, IPL_VIT, 5, 5, IPL_MAG, -20, -20, IPL_SETDUR, 15, 15, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_FOOLSCREST*/ { "Fool's Crest", UITYPE_HELM, 12, ICURS_FOOL_CREST, 20150, IPL_STR, -4, -4, IPL_LIFE, 100, 100, IPL_GETHIT, -6, -1, IPL_DEX, 5, 10, IPL_MAG, -8, -8, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_GOTTERDAM*/ { "Gotterdamerung", UITYPE_GREATHELM, 21, ICURS_VEIL_OF_STEEL, 54900, IPL_ATTRIBS, 20, 20, IPL_SETAC, 60, 60, IPL_GETHIT, 4, 4, IPL_ALLRESZERO, 0, 0, IPL_LIGHT, -4, -4, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_ROYCIRCLET*/ { "Royal Circlet", UITYPE_CROWN, 27, ICURS_ROYAL_CIRCLET, 24875, IPL_ATTRIBS, 10, 10, IPL_MANA, 40, 40, IPL_SETAC, 40, 40, IPL_LIGHT, 1, 1, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_TORNFLESH*/ { "Torn Flesh of Souls", UITYPE_RAGS, 2, ICURS_FLESH_OF_SOULS, 4825, IPL_SETAC, 8, 8, IPL_VIT, 10, 10, IPL_GETHIT, 1, 1, IPL_INDESTRUCTIBLE, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_GLADBANE*/ { "The Gladiator's Bane", UITYPE_STUDARMOR, 6, ICURS_STUD_LEATH_ARMOR, 3450, IPL_SETAC, 25, 25, IPL_GETHIT, 2, 2, IPL_DUR, 200, 200, IPL_ATTRIBS, -3, -3, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_RAINCLOAK*/ { "The Rainbow Cloak", UITYPE_CLOAK, 2, ICURS_UCLOAK, 4900, IPL_SETAC, 10, 10, IPL_ATTRIBS, 1, 1, IPL_ALLRES, 10, 10, IPL_LIFE, 5, 5, IPL_DUR, 50, 50, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_LEATHAUT*/ { "Leather of Aut", UITYPE_LEATHARMOR, 4, ICURS_LEATHER_ARMOR, 10550, IPL_SETAC, 15, 15, IPL_STR, 5, 5, IPL_MAG, -5, -5, IPL_DEX, 5, 5, IPL_INDESTRUCTIBLE, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_WISDWRAP*/ { "Wisdom's Wrap", UITYPE_ROBE, 5, ICURS_UCLOAK, 6200, IPL_MAG, 5, 5, IPL_MANA, 10, 10, IPL_LIGHTRES, 25, 25, IPL_SETAC, 15, 15, IPL_GETHIT, 1, 1, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_SPARKMAIL*/ { "Sparking Mail", UITYPE_CHAINMAIL, 9, ICURS_CHAIN_MAIL, 15750, IPL_SETAC, 30, 30, IPL_LIGHTDAM, 1, 10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_SCAVCARAP*/ { "Scavenger Carapace", UITYPE_BREASTPLATE, 13, ICURS_BREAST_PLATE, 34000, IPL_GETHIT, 15, 15, IPL_ACMOD, -30, -30, IPL_DEX, 5, 5, IPL_LIGHTRES, 40, 40, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_NIGHTSCAPE*/ { "Nightscape", UITYPE_CAPE, 16, ICURS_UCLOAK, 11600, IPL_FASTRECOVER, 2, 2, IPL_LIGHT, -4, -4, IPL_SETAC, 15, 15, IPL_DEX, 3, 3, IPL_ALLRES, 20, 20, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_NAJPLATE*/ { "Naj's Light Plate", UITYPE_PLATEMAIL, 19, ICURS_NAJ_PLATE, 78700, IPL_NOMINSTR, 0, 0, IPL_MAG, 5, 5, IPL_MANA, 20, 20, IPL_ALLRES, 20, 20, IPL_SKILLLEVELS, 1, 1, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_DEMONSPIKE*/ { "Demonspike Coat", UITYPE_FULLPLATE, 25, ICURS_FULL_PLATE_MAIL, 251175, IPL_SETAC, 100, 100, IPL_GETHIT, 6, 6, IPL_STR, 10, 10, IPL_INDESTRUCTIBLE, 0, 0, IPL_FIRERES, 50, 50, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_DEFLECTOR*/ { "The Deflector", UITYPE_BUCKLER, 1, ICURS_BUCKLER, 1500, IPL_SETAC, 7, 7, IPL_ALLRES, 10, 10, IPL_DAMP, -20, -20, IPL_TOHIT, -5, -5, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_SKULLSHLD*/ { "Split Skull Shield", UITYPE_BUCKLER, 1, ICURS_SKULL_SHIELD, 2025, IPL_SETAC, 10, 10, IPL_LIFE, 10, 10, IPL_STR, 2, 2, IPL_LIGHT, -1, -1, IPL_SETDUR, 15, 15, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_DRAGONBRCH*/ { "Dragon's Breach", UITYPE_KITESHIELD, 2, ICURS_DRAGON_SHIELD, 19200, IPL_FIRERES, 25, 25, IPL_STR, 5, 5, IPL_SETAC, 20, 20, IPL_MAG, -5, -5, IPL_INDESTRUCTIBLE, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_BLKOAKSHLD*/ { "Blackoak Shield", UITYPE_SMALLSHIELD, 4, ICURS_HOLY_DEFENDER, 5725, IPL_DEX, 10, 10, IPL_VIT, -10, -10, IPL_SETAC, 18, 18, IPL_LIGHT, -1, -1, IPL_DUR, 150, 150, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_HOLYDEF*/ { "Holy Defender", UITYPE_LARGESHIELD, 10, ICURS_HOLY_DEFENDER, 13800, IPL_SETAC, 15, 15, IPL_GETHIT, 2, 2, IPL_FIRERES, 20, 20, IPL_DUR, 200, 200, IPL_FASTBLOCK, 1, 1, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_SPIRITSHLD*/ { "Spirit Ward", UITYPE_TOWERSHIELD, 24, ICURS_SPIRIT_SHIELD, 39200, IPL_ACMOD, 10, 10, IPL_FASTRECOVER, 2, 2, IPL_ALLRES, 6, 12, IPL_VIT, 4, 10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_STORMSHLD*/ { "Stormshield", UITYPE_GOTHSHIELD, 24, ICURS_STORMSHIELD, 49000, IPL_SETAC, 40, 40, IPL_GETHIT, -4, -4, IPL_STR, 10, 10, IPL_INDESTRUCTIBLE, 0, 0, IPL_FASTBLOCK, 1, 1, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_BRAMBLE*/ { "Bramble", UITYPE_RING, 1, ICURS_RING_BRAMBLE, 1000, IPL_ATTRIBS, -2, -2, IPL_DAMMOD, 3, 3, IPL_MANA, 10, 10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_TYRAELGIFT*/ { "Tyrael's Gift", UITYPE_AMULET, 44, ICURS_AMULET_TYRAEL, 46105, IPL_VIT, 10, 10, IPL_LIFE, 30, 30, IPL_GETHIT, 8, 8, IPL_NO_BLEED, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_LILITHCOLLAR*/ { "Collar of Lilith", UITYPE_AMULET, 48, ICURS_AMULET_LILITH, 54175, IPL_LIFE, 40, 40, IPL_STEALLIFE, 3, 3, IPL_BLEED, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_BLEEDER*/ { "The Bleeder", UITYPE_RING, 2, ICURS_RING_BLEEDER, 8500, IPL_MAGICRES, 20, 20, IPL_MANA, 30, 30, IPL_LIFE, -10, -10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_CONSTRICT*/ { "Constricting Ring", UITYPE_RING, 5, ICURS_RING_CONSTRICTING, 62000, IPL_ALLRES, 95, 95, IPL_DRAINLIFE, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_ENGAGERING*/ { "Ring of Engagement", UITYPE_RING, 11, ICURS_GOLD_RING, 12476, IPL_GETHIT, 1, 2, IPL_STR, 5, 10, IPL_SETAC, 5, 5, IPL_PENETRATE_PHYS, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_DESTRING*/ { "Ring of Destruction", UITYPE_RING, 28, ICURS_RING_DESTRUCTION, 31250, IPL_CRITP, 100, 140, IPL_ACMOD, -60, -60, IPL_TOHIT, 60, 100, IPL_GETHIT, -4, -1, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_RAINBOWRING*/ { "Rainbow of Jordan", UITYPE_RING, 48, ICURS_GOLD_RING, 42750, IPL_SKILLLEVELS, 1, 1, IPL_SKILLLVL, 1, 2, IPL_LIFE, 30, 50, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, #ifdef HELLFIRE -/*UITEM_GKNUCKLE*/ { "Giant's Knuckle", UITYPE_RING, 8, 8000, IPL_STR, 60, 60, IPL_DEX, -30, -30, IPL_INVCURS, ICURS_RING_GIANTS, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_MERCURING*/ { "Mercurial Ring", UITYPE_RING, 8, 8000, IPL_DEX, 60, 60, IPL_STR, -30, -30, IPL_INVCURS, ICURS_RING_MERCURIAL, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_XORINERING*/ { "Xorine's Ring", UITYPE_RING, 8, 8000, IPL_MAG, 60, 60, IPL_STR, -30, -30, IPL_INVCURS, ICURS_RING_XORINE, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_KARIGRING*/ { "Karik's Ring", UITYPE_RING, 8, 8000, IPL_VIT, 60, 60, IPL_MAG, -30, -30, IPL_INVCURS, ICURS_RING_KARIK, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_MAGMARING*/ { "Ring of Magma", UITYPE_RING, 8, 8000, IPL_FIRERES, 60, 60, IPL_LIGHTRES, -30, -30, IPL_MAGICRES, -30, -30, IPL_INVCURS, ICURS_RING_MAGMA, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_MYSTICSRING*/ { "Ring of the Mystics", UITYPE_RING, 8, 8000, IPL_MAGICRES, 60, 60, IPL_FIRERES, -30, -30, IPL_LIGHTRES, -30, -30, IPL_INVCURS, ICURS_RING_MYSTICS, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_THUNDERRING*/ { "Ring of Thunder", UITYPE_RING, 8, 8000, IPL_LIGHTRES, 60, 60, IPL_FIRERES, -30, -30, IPL_MAGICRES, -30, -30, IPL_INVCURS, ICURS_RING_THUNDER, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_WARDINGAMU*/ { "Amulet of Warding", UITYPE_AMULET, 12, 30000, IPL_ALLRES, 40, 40, IPL_LIFE, -100, -100, IPL_INVCURS, ICURS_AMULET_WARDING, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_GNATSTING*/ { "Gnat Sting", UITYPE_HUNTBOW, 15, 30000, IPL_CRITP, 200, 200, IPL_FASTATTACK, 1, 1, IPL_INDESTRUCTIBLE, 0, 0, IPL_INVCURS, ICURS_GNAT_STING, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_FLAMBEAU*/ { "Flambeau", UITYPE_COMPBOW, 11, 30000, IPL_FIREDAM, 30, 40, IPL_SETDAM, 0, 0, IPL_INDESTRUCTIBLE, 0, 0, IPL_INVCURS, ICURS_FLAMBEAU, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_GLOOMARMOR*/ { "Armor of Gloom", UITYPE_FULLPLATE, 25, 200000, IPL_NOMINSTR, 0, 0, IPL_SETAC, 225, 225, IPL_ALLRESZERO, 0, 0, IPL_LIGHT, -2, -2, IPL_INVCURS, ICURS_GLOOMARMOR, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_BLITZEN*/ { "Blitzen", UITYPE_COMPBOW, 13, 30000, IPL_LIGHTDAM, 20, 30, IPL_SETDAM, 0, 0, IPL_INDESTRUCTIBLE, 0, 0, IPL_INVCURS, ICURS_BLITZEN, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_THUNDERCLAP*/ { "Thunderclap", UITYPE_WARHAMMER, 13, 30000, IPL_LIGHTDAM, 3, 6, IPL_STR, 20, 20, IPL_LIGHTRES, 30, 30, IPL_LIGHT, 2, 2, IPL_INDESTRUCTIBLE, 0, 0, IPL_INVCURS, ICURS_THUNDERCLAP, 0, ALIGN }, -/*UITEM_SHIROTACHI*/ { "Shirotachi", UITYPE_GREATSWR, 21, 36000, IPL_ONEHAND, 0, 0, IPL_FASTATTACK, 4, 4, IPL_PENETRATE_PHYS, 0, 0, IPL_LIGHTDAM, 6, 6, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_SOULEATER*/ { "Eater of Souls", UITYPE_TWOHANDSWR, 23, 42000, IPL_INDESTRUCTIBLE, 0, 0, IPL_LIFE, 50, 50, IPL_STEALLIFE, 6, 6, IPL_STEALMANA, 5, 5, IPL_DRAINLIFE, 0, 0, IPL_INVCURS, ICURS_SOUL_EATER, 0, ALIGN }, -/*UITEM_DIAMONDEDGE*/ { "Diamondedge", UITYPE_LONGSWR, 17, 42000, IPL_SETDUR, 10, 10, IPL_TOHIT, 50, 50, IPL_DAMP, 100, 100, IPL_LIGHTRES, 50, 50, IPL_SETAC, 10, 10, IPL_INVCURS, ICURS_DIAMONDEDGE, 0, ALIGN }, -/*UITEM_BONEARMOR*/// { "Bone Chain Armor", UITYPE_CHAINMAIL, 13, 36000, IPL_SETAC, 40, 40, IPL_ACUNDEAD, 0, 0, IPL_INVCURS, ICURS_BONEARMOR, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_DEMONARMOR*/// { "Demon Plate Armor", UITYPE_FULLPLATE, 25, 80000, IPL_SETAC, 80, 80, IPL_ACDEMON, 0, 0, IPL_INVCURS, ICURS_DEMONARMOR, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_ACOLYTEAMU*/ { "Acolyte's Amulet", UITYPE_AMULET, 10, 10000, IPL_MANATOLIFE, 0, 0, IPL_INVCURS, ICURS_AMULET_ACOLYTE, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_GLADIATORING*/ { "Gladiator's Ring", UITYPE_RING, 10, 10000, IPL_LIFETOMANA, 0, 0, IPL_INVCURS, ICURS_RING_GLADIATOR, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_GKNUCKLE*/ { "Giant's Knuckle", UITYPE_RING, 8, ICURS_RING_GIANTS, 8000, IPL_STR, 60, 60, IPL_DEX, -30, -30, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_MERCURING*/ { "Mercurial Ring", UITYPE_RING, 8, ICURS_RING_MERCURIAL, 8000, IPL_DEX, 60, 60, IPL_STR, -30, -30, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_XORINERING*/ { "Xorine's Ring", UITYPE_RING, 8, ICURS_RING_XORINE, 8000, IPL_MAG, 60, 60, IPL_STR, -30, -30, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_KARIGRING*/ { "Karik's Ring", UITYPE_RING, 8, ICURS_RING_KARIK, 8000, IPL_VIT, 60, 60, IPL_MAG, -30, -30, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_MAGMARING*/ { "Ring of Magma", UITYPE_RING, 8, ICURS_RING_MAGMA, 8000, IPL_FIRERES, 60, 60, IPL_LIGHTRES, -30, -30, IPL_MAGICRES, -30, -30, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_MYSTICSRING*/ { "Ring of the Mystics", UITYPE_RING, 8, ICURS_RING_MYSTICS, 8000, IPL_MAGICRES, 60, 60, IPL_FIRERES, -30, -30, IPL_LIGHTRES, -30, -30, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_THUNDERRING*/ { "Ring of Thunder", UITYPE_RING, 8, ICURS_RING_THUNDER, 8000, IPL_LIGHTRES, 60, 60, IPL_FIRERES, -30, -30, IPL_MAGICRES, -30, -30, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_WARDINGAMU*/ { "Amulet of Warding", UITYPE_AMULET, 12, ICURS_AMULET_WARDING, 30000, IPL_ALLRES, 40, 40, IPL_LIFE, -100, -100, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_GNATSTING*/ { "Gnat Sting", UITYPE_HUNTBOW, 15, ICURS_GNAT_STING, 30000, IPL_CRITP, 200, 200, IPL_FASTATTACK, 1, 1, IPL_INDESTRUCTIBLE, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_FLAMBEAU*/ { "Flambeau", UITYPE_COMPBOW, 11, ICURS_FLAMBEAU, 30000, IPL_FIREDAM, 30, 40, IPL_SETDAM, 0, 0, IPL_INDESTRUCTIBLE, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_GLOOMARMOR*/ { "Armor of Gloom", UITYPE_FULLPLATE, 25, ICURS_GLOOMARMOR, 200000, IPL_NOMINSTR, 0, 0, IPL_SETAC, 225, 225, IPL_ALLRESZERO, 0, 0, IPL_LIGHT, -2, -2, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_BLITZEN*/ { "Blitzen", UITYPE_COMPBOW, 13, ICURS_BLITZEN, 30000, IPL_LIGHTDAM, 20, 30, IPL_SETDAM, 0, 0, IPL_INDESTRUCTIBLE, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_THUNDERCLAP*/ { "Thunderclap", UITYPE_WARHAMMER, 13, ICURS_THUNDERCLAP, 30000, IPL_LIGHTDAM, 3, 6, IPL_STR, 20, 20, IPL_LIGHTRES, 30, 30, IPL_LIGHT, 2, 2, IPL_INDESTRUCTIBLE, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_SHIROTACHI*/ { "Shirotachi", UITYPE_GREATSWR, 21, ICURS_GREAT_SWORD, 36000, IPL_ONEHAND, 0, 0, IPL_FASTATTACK, 4, 4, IPL_PENETRATE_PHYS, 0, 0, IPL_LIGHTDAM, 6, 6, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_SOULEATER*/ { "Eater of Souls", UITYPE_TWOHANDSWR, 23, ICURS_SOUL_EATER, 42000, IPL_INDESTRUCTIBLE, 0, 0, IPL_LIFE, 50, 50, IPL_STEALLIFE, 6, 6, IPL_STEALMANA, 5, 5, IPL_DRAINLIFE, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_DIAMONDEDGE*/ { "Diamondedge", UITYPE_LONGSWR, 17, ICURS_DIAMONDEDGE, 42000, IPL_SETDUR, 10, 10, IPL_TOHIT, 50, 50, IPL_DAMP, 100, 100, IPL_LIGHTRES, 50, 50, IPL_SETAC, 10, 10, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_BONEARMOR*/// { "Bone Chain Armor", UITYPE_CHAINMAIL, 13, ICURS_BONEARMOR, 36000, IPL_SETAC, 40, 40, IPL_ACUNDEAD, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_DEMONARMOR*/// { "Demon Plate Armor", UITYPE_FULLPLATE, 25, ICURS_DEMONARMOR, 80000, IPL_SETAC, 80, 80, IPL_ACDEMON, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_ACOLYTEAMU*/ { "Acolyte's Amulet", UITYPE_AMULET, 10, ICURS_AMULET_ACOLYTE, 10000, IPL_MANATOLIFE, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_GLADIATORING*/ { "Gladiator's Ring", UITYPE_RING, 10, ICURS_RING_GLADIATOR, 10000, IPL_LIFETOMANA, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, #endif // clang-format on }; diff --git a/Source/items.cpp b/Source/items.cpp index fbe7fd3d96e..89bc406c3a6 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -1516,9 +1516,9 @@ static void SaveItemPower(int ii, int power, int param1, int param2, int minval, case IPL_LIGHT: is->_iPLLight = r; break; - case IPL_INVCURS: - is->_iCurs = param1; - break; + // case IPL_INVCURS: + // is->_iCurs = param1; + // break; //case IPL_THORNS: // is->_iFlags |= ISPL_THORNS; // break; @@ -1947,6 +1947,7 @@ static void GetUniqueItem(int ii, int uid) SaveItemPower(ii, ui->UIPower6, ui->UIParam6a, ui->UIParam6b, 0, 0, 1); }}}}} + items[ii]._iCurs = ui->UICurs; items[ii]._iIvalue = ui->UIValue; // if (items[ii]._iMiscId == IMISC_UNIQUE) @@ -2904,9 +2905,9 @@ void PrintItemPower(BYTE plidx, const ItemStruct* is) case IPL_LIGHT: snprintf(tempstr, sizeof(tempstr), "%+d%% light radius", 10 * is->_iPLLight); break; - case IPL_INVCURS: - copy_cstr(tempstr, " "); - break; + // case IPL_INVCURS: + // copy_cstr(tempstr, " "); + // break; //case IPL_THORNS: // copy_cstr(tempstr, "attacker takes 1-3 damage"); // break; @@ -3039,10 +3040,10 @@ static void PrintItemString(int x, int& y, const char* str, int col) static void PrintUniquePower(BYTE plidx, ItemStruct* is, int x, int& y) { - if (plidx != IPL_INVCURS) { + // if (plidx != IPL_INVCURS) { PrintItemPower(plidx, is); PrintItemString(x, y); - } + // } } static void DrawUniqueInfo(ItemStruct* is, int x, int& y) diff --git a/enums.h b/enums.h index 9b0e1779c20..f2395f3724d 100644 --- a/enums.h +++ b/enums.h @@ -382,7 +382,7 @@ typedef enum item_effect_type { IPL_DUR_CURSE, IPL_INDESTRUCTIBLE, IPL_LIGHT, - IPL_INVCURS, + //IPL_INVCURS, //IPL_THORNS, IPL_NOMANA, IPL_KNOCKBACK, @@ -527,7 +527,8 @@ typedef enum item_cursor_graphic { ICURS_CLUB = 66, ICURS_SABRE = 67, ICURS_FALCON_GRYPHON = 68, - ICURS_SPIKED_CLUB = 70, + ICURS_GNARLROOT = 70, + ICURS_SPIKED_CLUB = 71, ICURS_SCIMITAR = 72, ICURS_POIGNARD = 73, ICURS_FULL_HELM = 75, @@ -561,7 +562,7 @@ typedef enum item_cursor_graphic { ICURS_STONECLEAVER = 104, ICURS_SMALL_SHIELD = 105, ICURS_CLEAVER = 106, - ICURS_STUDDED_LEATHER_ARMOR = 107, + ICURS_STUD_LEATH_ARMOR = 107, ICURS_BATTLE_BOW = 108, ICURS_SHORT_STAFF = 109, ICURS_TWO_HANDED_SWORD = 110, diff --git a/structs.h b/structs.h index f03ef5285b8..a0fc0106875 100644 --- a/structs.h +++ b/structs.h @@ -118,6 +118,7 @@ typedef struct UniqItemData { const char* UIName; BYTE UIUniqType; // unique_item_type BYTE UIMinLvl; + uint16_t UICurs; int UIValue; BYTE UIPower1; // item_effect_type int UIParam1a; From 94fea9f05c4ab92675373c4a9a8e1934d46589b5 Mon Sep 17 00:00:00 2001 From: KPhoenix Date: Thu, 11 Apr 2024 17:15:11 -0400 Subject: [PATCH 293/596] fix stormshield --- Source/itemdat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/itemdat.cpp b/Source/itemdat.cpp index c4bb75f0921..e1a27e2e689 100644 --- a/Source/itemdat.cpp +++ b/Source/itemdat.cpp @@ -553,7 +553,7 @@ const UniqItemData UniqueItemList[NUM_UITEM] = { /*UITEM_BLKOAKSHLD*/ { "Blackoak Shield", UITYPE_SMALLSHIELD, 4, ICURS_HOLY_DEFENDER, 5725, IPL_DEX, 10, 10, IPL_VIT, -10, -10, IPL_SETAC, 18, 18, IPL_LIGHT, -1, -1, IPL_DUR, 150, 150, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_HOLYDEF*/ { "Holy Defender", UITYPE_LARGESHIELD, 10, ICURS_HOLY_DEFENDER, 13800, IPL_SETAC, 15, 15, IPL_GETHIT, 2, 2, IPL_FIRERES, 20, 20, IPL_DUR, 200, 200, IPL_FASTBLOCK, 1, 1, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_SPIRITSHLD*/ { "Spirit Ward", UITYPE_TOWERSHIELD, 24, ICURS_SPIRIT_SHIELD, 39200, IPL_ACMOD, 10, 10, IPL_FASTRECOVER, 2, 2, IPL_ALLRES, 6, 12, IPL_VIT, 4, 10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_STORMSHLD*/ { "Stormshield", UITYPE_GOTHSHIELD, 24, ICURS_STORMSHIELD, 49000, IPL_SETAC, 40, 40, IPL_GETHIT, -4, -4, IPL_STR, 10, 10, IPL_INDESTRUCTIBLE, 0, 0, IPL_FASTBLOCK, 1, 1, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_STORMSHLD*/ { "Stormshield", UITYPE_GOTHSHIELD, 24, ICURS_STORMSHIELD, 49000, IPL_SETAC, 40, 40, IPL_GETHIT, -4, -4, IPL_STR, 10, 10, IPL_INDESTRUCTIBLE, 0, 0, IPL_FASTBLOCK, 1, 1, IPL_LIGHTRES, 50, 50, ALIGN }, /*UITEM_BRAMBLE*/ { "Bramble", UITYPE_RING, 1, ICURS_RING_BRAMBLE, 1000, IPL_ATTRIBS, -2, -2, IPL_DAMMOD, 3, 3, IPL_MANA, 10, 10, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_TYRAELGIFT*/ { "Tyrael's Gift", UITYPE_AMULET, 44, ICURS_AMULET_TYRAEL, 46105, IPL_VIT, 10, 10, IPL_LIFE, 30, 30, IPL_GETHIT, 8, 8, IPL_NO_BLEED, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_LILITHCOLLAR*/ { "Collar of Lilith", UITYPE_AMULET, 48, ICURS_AMULET_LILITH, 54175, IPL_LIFE, 40, 40, IPL_STEALLIFE, 3, 3, IPL_BLEED, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, From e7472e2917aba2b8437877a54311f51e8e84cc8b Mon Sep 17 00:00:00 2001 From: Eric Robinson <68359262+kphoenix137@users.noreply.github.com> Date: Thu, 18 Apr 2024 21:23:39 -0400 Subject: [PATCH 294/596] Fix Hammer of Jholm (#7069) --- Source/itemdat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/itemdat.cpp b/Source/itemdat.cpp index e1a27e2e689..2999b42aa57 100644 --- a/Source/itemdat.cpp +++ b/Source/itemdat.cpp @@ -514,7 +514,7 @@ const UniqItemData UniqueItemList[NUM_UITEM] = { /*UITEM_HELLSLAYER*/ { "Hellslayer", UITYPE_BATTLEAXE, 30, ICURS_BATTLE_AXE, 26200, IPL_STR, 8, 8, IPL_VIT, 8, 8, IPL_DAMP, 100, 100, IPL_LIFE, 25, 25, IPL_MANA, -25, -25, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_MESSERREAVER*/ { "Messerschmidt's Reaver", UITYPE_GREATAXE, 50, ICURS_MESSERSCHMIDT, 158000, IPL_DAMP, 200, 200, IPL_DAMMOD, 15, 15, IPL_ATTRIBS, 5, 5, IPL_LIFE, -50, -50, IPL_FIREDAM, 2, 12, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_CRACKRUST*/ { "Crackrust", UITYPE_MACE, 8, ICURS_MACE, 11375, IPL_ATTRIBS, 2, 2, IPL_INDESTRUCTIBLE, 0, 0, IPL_ALLRES, 15, 15, IPL_DAMP, 50, 50, IPL_SKILLLEVELS, -1, -1, IPL_INVALID, 0, 0, ALIGN }, -/*UITEM_JHOLMHAMM*/ { "Hammer of Jholm", UITYPE_MAUL, 12, ICURS_MAUL, 8700, IPL_DAMP, 4, 10, IPL_INDESTRUCTIBLE, 0, 0, IPL_STR, 3, 3, IPL_TOHIT, 15, 15, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, +/*UITEM_JHOLMHAMM*/ { "Hammer of Jholm", UITYPE_MAUL, 12, ICURS_MAUL, 8700, IPL_SETDAM, 4, 10, IPL_INDESTRUCTIBLE, 0, 0, IPL_STR, 3, 3, IPL_TOHIT, 15, 15, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_CIVERBS*/// { "Civerb's Cudgel", UITYPE_MACE, 1, ICURS_MACE, 2000, IPL_3XDAMVDEM, 35, 35, IPL_DEX, -5, -5, IPL_MAG, -2, -2, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_CELESTSTAR*/ { "The Celestial Star", UITYPE_FLAIL, 14, ICURS_FLAIL, 17810, IPL_NOMINSTR, 0, 0, IPL_LIGHT, 2, 2, IPL_DAMMOD, 10, 10, IPL_ACMOD, -8, -8, IPL_INVALID, 0, 0, IPL_INVALID, 0, 0, ALIGN }, /*UITEM_BARANSTAR*/ { "Baranar's Star", UITYPE_MORNSTAR, 14, ICURS_MORNING_STAR, 6850, IPL_TOHIT, 12, 12, IPL_DAMP, 80, 80, IPL_FASTATTACK, 1, 1, IPL_VIT, 4, 4, IPL_DEX, -4, -4, IPL_SETDUR, 60, 60, ALIGN }, From 4836741e7d034ab67a40f8ba0693b0fafd3faa4b Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 3 May 2024 09:42:39 +0200 Subject: [PATCH 295/596] update SDL2_mixer --- 3rdParty/SDL2_mixer/src/utils.c | 84 +++++++++++++-------------------- 1 file changed, 34 insertions(+), 50 deletions(-) diff --git a/3rdParty/SDL2_mixer/src/utils.c b/3rdParty/SDL2_mixer/src/utils.c index 0d021c75f6b..917e7478b69 100644 --- a/3rdParty/SDL2_mixer/src/utils.c +++ b/3rdParty/SDL2_mixer/src/utils.c @@ -31,14 +31,14 @@ #endif #if defined(__x86_64__) && defined(HAVE_SSE2_INTRINSICS) -#define NEED_SCALAR_CONVERTER_FALLBACKS 0 /* x86_64 guarantees SSE2. */ +#define HAVE_SSE2_SUPPORT 1 /* x86_64 guarantees SSE2. */ #elif defined(__MACOSX__) && defined(HAVE_SSE2_INTRINSICS) -#define NEED_SCALAR_CONVERTER_FALLBACKS 0 /* Mac OS X/Intel guarantees SSE2. */ +#define HAVE_SSE2_SUPPORT 1 /* Mac OS X/Intel guarantees SSE2. */ + #endif -/* Set to zero if platform is guaranteed to use a SIMD codepath here. */ -#ifndef NEED_SCALAR_CONVERTER_FALLBACKS -#define NEED_SCALAR_CONVERTER_FALLBACKS 1 +#ifndef HAVE_SSE2_SUPPORT +#define HAVE_SSE2_SUPPORT 0 #endif /* Function pointers set to a CPU-specific implementation. */ @@ -477,13 +477,13 @@ void Mix_Converter_AUDIO16_Resample_Half_SSE2(Mix_BuffOps* buf) __m128i aa = _mm_loadu_si128((const __m128i*)srcPos); __m128i bb = _mm_loadu_si128((const __m128i*)&srcPos[8]); - aa = _mm_shufflehi_epi16(aa, (0 << 0) | (2 << 2) | (1 << 4) | (3 << 6)); - aa = _mm_shufflelo_epi16(aa, (0 << 0) | (2 << 2) | (1 << 4) | (3 << 6)); - aa = _mm_shuffle_epi32(aa, (0 << 0) | (2 << 2) | (1 << 4) | (3 << 6)); + aa = _mm_shufflehi_epi16(aa, _MM_SHUFFLE(3, 1, 2, 0)); + aa = _mm_shufflelo_epi16(aa, _MM_SHUFFLE(3, 1, 2, 0)); + aa = _mm_shuffle_epi32(aa, _MM_SHUFFLE(3, 1, 2, 0)); - bb = _mm_shufflehi_epi16(bb, (0 << 0) | (2 << 2) | (1 << 4) | (3 << 6)); - bb = _mm_shufflelo_epi16(bb, (0 << 0) | (2 << 2) | (1 << 4) | (3 << 6)); - bb = _mm_shuffle_epi32(bb, (0 << 0) | (2 << 2) | (1 << 4) | (3 << 6)); + bb = _mm_shufflehi_epi16(bb, _MM_SHUFFLE(3, 1, 2, 0)); + bb = _mm_shufflelo_epi16(bb, _MM_SHUFFLE(3, 1, 2, 0)); + bb = _mm_shuffle_epi32(bb, _MM_SHUFFLE(3, 1, 2, 0)); __m128i cc = _mm_unpacklo_epi64(aa, bb); _mm_storeu_si128((__m128i*)dstPos, cc); @@ -526,32 +526,25 @@ void Mix_Converter_U8_S16LSB_AVX(Mix_BuffOps* buf) buf->endPos = dstPos; const __m256i zero = _mm256_setzero_si256(); - const __m256i sub = _mm256_set1_epi16(128); + const __m256i sign = _mm256_set1_epi8(0x80); while (&currPos[32] <= srcPos) { srcPos -= 32; - dstPos -= 32; - - __m256i aa = _mm256_loadu_si256((const __m256i*)srcPos); - - __m256i bb = _mm256_unpackhi_epi8(aa, zero);// zfill(a[hi], 16) - bb = _mm256_sub_epi16(bb, sub); // subtract 128 + dstPos -= 64; - bb = _mm256_slli_epi16(bb, 8); // shl 8 - _mm256_storeu_si256((__m256i*)dstPos, bb); + const __m256i src00 = _mm256_loadu_si256((__m128i const *)&srcPos[0]); /* get 32 uint8 into an XMM register. */ + const __m256i value = _mm_xor_si128(sign, src00); /* 'convert' to int8 */ + const __m256i src0 = _mm_unpacklo_epi8(zero, value); + const __m256i src1 = _mm_unpackhi_epi8(zero, value); - dstPos -= 32; - __m256i cc = _mm256_unpacklo_epi8(aa, zero);// zfill(a[lo], 16) - cc = _mm256_sub_epi16(cc, sub); // subtract 128 - - cc = _mm256_slli_epi16(cc, 8); // shl 8 - _mm256_storeu_si256((__m256i*)dstPos, cc); + _mm_storeu_si128((__m256i*)&dstPos[0], src0); + _mm_storeu_si128((__m256i*)&dstPos[32], src1); } while (srcPos != currPos) { srcPos--; dstPos -= 2; - *(Sint16*)dstPos = SDL_SwapLE16((*srcPos - 128) << 8); + *(Sint16*)dstPos = SDL_SwapLE16((Sint8)(srcPos[0] ^ 0x80) << 8); } } #endif // __AVX__ @@ -565,32 +558,25 @@ void Mix_Converter_U8_S16LSB_SSE2(Mix_BuffOps* buf) buf->endPos = dstPos; const __m128i zero = _mm_setzero_si128(); - const __m128i sub = _mm_set1_epi16(128); + const __m128i sign = _mm_set1_epi8(0x80); while (&currPos[16] <= srcPos) { srcPos -= 16; - dstPos -= 16; - - __m128i aa = _mm_loadu_si128((const __m128i*)srcPos); - - __m128i bb = _mm_unpackhi_epi8(aa, zero); // zfill(a[hi], 16) - bb = _mm_sub_epi16(bb, sub); // subtract 128 + dstPos -= 32; - bb = _mm_slli_epi16(bb, 8); // shl 8 - _mm_storeu_si128((__m128i*)dstPos, bb); + const __m128i src00 = _mm_loadu_si128((__m128i const *)&srcPos[0]); /* get 16 uint8 into an XMM register. */ + const __m128i value = _mm_xor_si128(sign, src00); /* 'convert' to int8 */ + const __m128i src0 = _mm_unpacklo_epi8(zero, value); + const __m128i src1 = _mm_unpackhi_epi8(zero, value); - dstPos -= 16; - __m128i cc = _mm_unpacklo_epi8(aa, zero); // zfill(a[lo], 16) - cc = _mm_sub_epi16(cc, sub); // subtract 128 - - cc = _mm_slli_epi16(cc, 8); // shl 8 - _mm_storeu_si128((__m128i*)dstPos, cc); + _mm_storeu_si128((__m128i*)&dstPos[0], src0); + _mm_storeu_si128((__m128i*)&dstPos[16], src1); } while (srcPos != currPos) { srcPos--; dstPos -= 2; - *(Sint16*)dstPos = SDL_SwapLE16((*srcPos - 128) << 8); + *(Sint16*)dstPos = SDL_SwapLE16((Sint8)(srcPos[0] ^ 0x80) << 8); } } #endif @@ -605,26 +591,24 @@ void Mix_Converter_U8_S16LSB(Mix_BuffOps* buf) while (srcPos != currPos) { srcPos--; dstPos -= 2; - *(Sint16*)dstPos = SDL_SwapLE16((*srcPos - 128) << 8); + *(Sint16*)dstPos = SDL_SwapLE16((Sint8)(srcPos[0] ^ 0x80) << 8); } } void Mix_Utils_Init() { -#if NEED_SCALAR_CONVERTER_FALLBACKS - //Mix_Convert_AUDIO8_Mono2Stereo = Mix_Converter_AUDIO8_Mono2Stereo; + // Mix_Convert_AUDIO8_Mono2Stereo = Mix_Converter_AUDIO8_Mono2Stereo; Mix_Convert_AUDIO16_Mono2Stereo = Mix_Converter_AUDIO16_Mono2Stereo; Mix_Convert_AUDIO8_Resample_Half = Mix_Converter_AUDIO8_Resample_Half; Mix_Convert_AUDIO16_Resample_Half = Mix_Converter_AUDIO16_Resample_Half; Mix_MixAudioFormat = Mix_Mixer_AUDIOS16; Mix_Convert_U8_S16LSB = Mix_Converter_U8_S16LSB; -#endif #ifdef HAVE_SSE2_INTRINSICS -#if NEED_SCALAR_CONVERTER_FALLBACKS - if (SDL_HasSSE2()) { -#else +#if HAVE_SSE2_SUPPORT // SDL_assert(SDL_HasSSE2()); if (1) { +#else + if (SDL_HasSSE2()) { #endif //Mix_Convert_AUDIO8_Mono2Stereo = Mix_Converter_AUDIO8_Mono2Stereo_SSE2; Mix_Convert_AUDIO16_Mono2Stereo = Mix_Converter_AUDIO16_Mono2Stereo_SSE2; From bd96f915d2969c966aa5652a1852b741cd94b503 Mon Sep 17 00:00:00 2001 From: staphen Date: Mon, 29 Apr 2024 20:12:31 -0400 Subject: [PATCH 296/596] Revert CI runners for MacOS/iOS to macos-11 --- .github/workflows/cmake.yml | 2 +- .github/workflows/nightly.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 6968e635177..7517450f5f8 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -13,7 +13,7 @@ jobs: # well on Windows or Mac. You can convert this to a matrix build if you need # cross-platform coverage. # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix - runs-on: macos-latest + runs-on: macos-11 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 0acbf755e43..942c5debe55 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -393,7 +393,7 @@ jobs: - name: hellfire-macp cmakeargs: '-DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-macp.dmg' - runs-on: macos-latest + runs-on: macos-11 steps: - uses: actions/checkout@v4 with: @@ -441,7 +441,7 @@ jobs: - name: hellfire-iosp cmakeargs: '-DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-iosp.ipa' - runs-on: macos-latest + runs-on: macos-11 steps: - uses: actions/checkout@v4 with: From 89e45139076d58be288b3b634af3ed7e95c22165 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 3 May 2024 13:23:32 +0200 Subject: [PATCH 297/596] fix avx code --- 3rdParty/SDL2_mixer/src/effect_position.c | 26 ++++++++-------- 3rdParty/SDL2_mixer/src/utils.c | 36 +++++++++++------------ 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/3rdParty/SDL2_mixer/src/effect_position.c b/3rdParty/SDL2_mixer/src/effect_position.c index 27607842be0..f905d3f363a 100644 --- a/3rdParty/SDL2_mixer/src/effect_position.c +++ b/3rdParty/SDL2_mixer/src/effect_position.c @@ -871,8 +871,8 @@ static SDL_bool SDLCALL _Eff_position_s16lsb_SSE2(void* stream, unsigned len, vo return SDL_TRUE; } #endif // HAVE_SSE2_INTRINSICS -#ifdef __AVX__ -static SDL_bool SDLCALL _Eff_position_s16lsb_AVX(void* stream, unsigned len, void* udata) +#ifdef __AVX2__ +static SDL_bool SDLCALL _Eff_position_s16lsb_AVX2(void* stream, unsigned len, void* udata) { /* 16 signed bits (lsb) * 2 channels. */ Sint16* ptr = (Sint16*)stream; @@ -882,9 +882,9 @@ static SDL_bool SDLCALL _Eff_position_s16lsb_AVX(void* stream, unsigned len, voi if (left == 0 && right == 0) return SDL_FALSE; - //static_assert((MIX_MAX_VOLUME & (MIX_MAX_VOLUME - 1)) == 0, "_Eff_position_s16lsb_AVX expects MIX_MAX_VOLUME to be a power of 2."); - //static_assert((MIX_MAX_POS_EFFECT & (MIX_MAX_POS_EFFECT - 1)) == 0, "_Eff_position_s16lsb_AVX expects MIX_MAX_POS_EFFECT to be a power of 2."); - //static_assert((MIX_MAX_VOLUME * MIX_MAX_POS_EFFECT) <= (1 << 16), "_Eff_position_s16lsb_AVX expects MIX_MAX_VOLUME to be low."); + //static_assert((MIX_MAX_VOLUME & (MIX_MAX_VOLUME - 1)) == 0, "_Eff_position_s16lsb_AVX2 expects MIX_MAX_VOLUME to be a power of 2."); + //static_assert((MIX_MAX_POS_EFFECT & (MIX_MAX_POS_EFFECT - 1)) == 0, "_Eff_position_s16lsb_AVX2 expects MIX_MAX_POS_EFFECT to be a power of 2."); + //static_assert((MIX_MAX_VOLUME * MIX_MAX_POS_EFFECT) <= (1 << 16), "_Eff_position_s16lsb_AVX2 expects MIX_MAX_VOLUME to be low."); left *= (1 << 16) / (MIX_MAX_VOLUME * MIX_MAX_POS_EFFECT); right *= (1 << 16) / (MIX_MAX_VOLUME * MIX_MAX_POS_EFFECT); @@ -896,7 +896,7 @@ static SDL_bool SDLCALL _Eff_position_s16lsb_AVX(void* stream, unsigned len, voi len -= 32; __m256i aa = _mm256_loadu_si256((const __m256i*)ptr); __m256i bb = _mm256_mulhi_epi16(aa, mm); - _mm_storeu_si256(ptr, bb); + _mm256_storeu_si256(ptr, bb); ptr += 16; } @@ -961,8 +961,8 @@ static SDL_bool _Eff_volume_s16lbs_SSE2(void* stream, unsigned len, void* udata) return SDL_TRUE; } #endif // HAVE_SSE2_INTRINSICS -#ifdef __AVX__ -static SDL_bool _Eff_volume_s16lbs_AVX(void* stream, unsigned len, void* udata) +#ifdef __AVX2__ +static SDL_bool _Eff_volume_s16lbs_AVX2(void* stream, unsigned len, void* udata) { /* 16 signed bits (lsb) * 2 channels. */ Sint16* ptr = (Sint16*)stream; @@ -982,7 +982,7 @@ static SDL_bool _Eff_volume_s16lbs_AVX(void* stream, unsigned len, void* udata) len -= 32; __m256i aa = _mm256_loadu_si256((const __m256i*)ptr); __m256i bb = _mm256_mulhi_epi16(aa, mm); - _mm_storeu_si256(ptr, bb); + _mm256_storeu_si256(ptr, bb); ptr += 16; } @@ -2391,10 +2391,10 @@ void _Eff_PositionInit(void) _Eff_do_position_s16lsb = _Eff_position_s16lsb_SSE2; } #endif -#if defined(__AVX__) && SDL_VERSION_ATLEAST(2, 0, 2) - if (SDL_HasAVX()) { - _Eff_do_volume_s16lbs = _Eff_volume_s16lbs_AVX; - _Eff_do_position_s16lsb = _Eff_position_s16lsb_AVX; +#if defined(__AVX2__) && SDL_VERSION_ATLEAST(2, 0, 2) + if (SDL_HasAVX2()) { + _Eff_do_volume_s16lbs = _Eff_volume_s16lbs_AVX2; + _Eff_do_position_s16lsb = _Eff_position_s16lsb_AVX2; } #endif } diff --git a/3rdParty/SDL2_mixer/src/utils.c b/3rdParty/SDL2_mixer/src/utils.c index 917e7478b69..20da3b6912c 100644 --- a/3rdParty/SDL2_mixer/src/utils.c +++ b/3rdParty/SDL2_mixer/src/utils.c @@ -310,8 +310,8 @@ void Mix_Mixer_AUDIOS16_SSE2(void* dst, const void* src, unsigned len) } } #endif // HAVE_SSE2_INTRINSICS -#ifdef __AVX__ -void Mix_Mixer_AUDIOS16_AVX(void* dst, const void* src, unsigned len) +#ifdef __AVX2__ +void Mix_Mixer_AUDIOS16_AVX2(void* dst, const void* src, unsigned len) { const Sint16* srcPos = (const Sint16*)src; Sint16* currPos = (Sint16*)dst; @@ -322,7 +322,7 @@ void Mix_Mixer_AUDIOS16_AVX(void* dst, const void* src, unsigned len) __m256i bb = _mm256_loadu_si256((const __m256i*)currPos); __m256i cc = _mm256_adds_epi16(aa, bb); - _mm_storeu_si256(currPos, cc); + _mm256_storeu_si256(currPos, cc); currPos += 16; srcPos += 16; @@ -336,8 +336,8 @@ void Mix_Mixer_AUDIOS16_AVX(void* dst, const void* src, unsigned len) #endif // FULL - SELF_MIX #ifndef FULL // SELF_CONV -#ifdef __AVX__ -void Mix_Converter_AUDIO16_Mono2Stereo_AVX(Mix_BuffOps* buf) +#ifdef __AVX2__ +void Mix_Converter_AUDIO16_Mono2Stereo_AVX2(Mix_BuffOps* buf) { Sint16* srcPos = (Sint16*)buf->endPos; Sint16* currPos = (Sint16*)buf->currPos; @@ -516,8 +516,8 @@ void Mix_Converter_AUDIO16_Resample_Half(Mix_BuffOps* buf) } } -#ifdef __AVX__ -void Mix_Converter_U8_S16LSB_AVX(Mix_BuffOps* buf) +#ifdef __AVX2__ +void Mix_Converter_U8_S16LSB_AVX2(Mix_BuffOps* buf) { Uint8* srcPos = (Uint8*)buf->endPos; Uint8* currPos = (Uint8*)buf->currPos; @@ -532,13 +532,13 @@ void Mix_Converter_U8_S16LSB_AVX(Mix_BuffOps* buf) srcPos -= 32; dstPos -= 64; - const __m256i src00 = _mm256_loadu_si256((__m128i const *)&srcPos[0]); /* get 32 uint8 into an XMM register. */ - const __m256i value = _mm_xor_si128(sign, src00); /* 'convert' to int8 */ - const __m256i src0 = _mm_unpacklo_epi8(zero, value); - const __m256i src1 = _mm_unpackhi_epi8(zero, value); + const __m256i src00 = _mm256_loadu_si256((__m256i const *)&srcPos[0]); /* get 32 uint8 into an XMM register. */ + const __m256i value = _mm256_xor_si256(sign, src00); /* 'convert' to int8 */ + const __m256i src0 = _mm256_unpacklo_epi8(zero, value); + const __m256i src1 = _mm256_unpackhi_epi8(zero, value); - _mm_storeu_si128((__m256i*)&dstPos[0], src0); - _mm_storeu_si128((__m256i*)&dstPos[32], src1); + _mm256_storeu_si256((__m256i*)&dstPos[0], src0); + _mm256_storeu_si256((__m256i*)&dstPos[32], src1); } while (srcPos != currPos) { @@ -618,11 +618,11 @@ void Mix_Utils_Init() Mix_Convert_U8_S16LSB = Mix_Converter_U8_S16LSB_SSE2; } #endif -#if defined(__AVX__) && SDL_VERSION_ATLEAST(2, 0, 2) - if (SDL_HasAVX()) { - Mix_Convert_AUDIO16_Mono2Stereo = Mix_Converter_AUDIO16_Mono2Stereo_AVX; - Mix_MixAudioFormat = Mix_Mixer_AUDIOS16_AVX; - Mix_Convert_U8_S16LSB = Mix_Converter_U8_S16LSB_AVX; +#if defined(__AVX2__) && SDL_VERSION_ATLEAST(2, 0, 2) + if (SDL_HasAVX2()) { + Mix_Convert_AUDIO16_Mono2Stereo = Mix_Converter_AUDIO16_Mono2Stereo_AVX2; + Mix_MixAudioFormat = Mix_Mixer_AUDIOS16_AVX2; + Mix_Convert_U8_S16LSB = Mix_Converter_U8_S16LSB_AVX2; } #endif } From f14f1aa8e69069d9e31857f343589ab4060b4740 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 6 May 2024 16:14:59 +0200 Subject: [PATCH 298/596] update SDL2 --- 3rdParty/SDL2/CMakeLists.txt | 2 +- 3rdParty/SDL2_mixer/src/effect_position.c | 61 ++++++++--------------- 3rdParty/SDL2_mixer/src/utils.c | 44 ++++++---------- 3 files changed, 37 insertions(+), 70 deletions(-) diff --git a/3rdParty/SDL2/CMakeLists.txt b/3rdParty/SDL2/CMakeLists.txt index 4acf7364201..13438179c99 100644 --- a/3rdParty/SDL2/CMakeLists.txt +++ b/3rdParty/SDL2/CMakeLists.txt @@ -75,7 +75,7 @@ FetchContent_Declare(SDL2 #URL https://github.com/libsdl-org/SDL/archive/5056b29b0f8611b470d8b8bdb313eab628f8bd6e.tar.gz #URL_HASH MD5=3fb6d72c33434082c32d2649c35c6502 GIT_REPOSITORY https://github.com/pionere/SDL.git - GIT_TAG 7f3b9f3a95e347363f563c2811dec4f497abe787 + GIT_TAG c60a2afdd3b8b0a99d259fdf450cf0faecf999cc ) FetchContent_MakeAvailableExcludeFromAll(SDL2) diff --git a/3rdParty/SDL2_mixer/src/effect_position.c b/3rdParty/SDL2_mixer/src/effect_position.c index f905d3f363a..38b6d0db73f 100644 --- a/3rdParty/SDL2_mixer/src/effect_position.c +++ b/3rdParty/SDL2_mixer/src/effect_position.c @@ -33,25 +33,6 @@ #define MIX_INTERNAL_EFFECT__ #include "effects_internal.h" -#ifndef FULL - -#ifdef __SSE2__ -#define HAVE_SSE2_INTRINSICS -#endif - -#if defined(__x86_64__) && defined(HAVE_SSE2_INTRINSICS) -#define NEED_SCALAR_CONVERTER_FALLBACKS 0 /* x86_64 guarantees SSE2. */ -#elif defined(__MACOSX__) && defined(HAVE_SSE2_INTRINSICS) -#define NEED_SCALAR_CONVERTER_FALLBACKS 0 /* Mac OS X/Intel guarantees SSE2. */ -#endif - -/* Set to zero if platform is guaranteed to use a SIMD codepath here. */ -#ifndef NEED_SCALAR_CONVERTER_FALLBACKS -#define NEED_SCALAR_CONVERTER_FALLBACKS 1 -#endif - -#endif // FULL - /* profile code: #include #include @@ -836,7 +817,7 @@ static SDL_bool SDLCALL _Eff_position_s16lsb(void* stream, unsigned len, void* u } return SDL_TRUE; } -#ifdef HAVE_SSE2_INTRINSICS +#ifdef SDL_SSE2_INTRINSICS static SDL_bool SDLCALL _Eff_position_s16lsb_SSE2(void* stream, unsigned len, void* udata) { /* 16 signed bits (lsb) * 2 channels. */ @@ -870,8 +851,8 @@ static SDL_bool SDLCALL _Eff_position_s16lsb_SSE2(void* stream, unsigned len, vo } return SDL_TRUE; } -#endif // HAVE_SSE2_INTRINSICS -#ifdef __AVX2__ +#endif // SDL_SSE2_INTRINSICS +#ifdef SDL_AVX2_INTRINSICS static SDL_bool SDLCALL _Eff_position_s16lsb_AVX2(void* stream, unsigned len, void* udata) { /* 16 signed bits (lsb) * 2 channels. */ @@ -905,7 +886,7 @@ static SDL_bool SDLCALL _Eff_position_s16lsb_AVX2(void* stream, unsigned len, vo } return SDL_TRUE; } -#endif // __AVX__ +#endif // SDL_AVX2_INTRINSICS #define ADJUST_VOLUME(s, v) (s = (s*v)/MIX_MAX_VOLUME) static SDL_bool _Eff_volume_s16lbs(void* stream, unsigned len, void* udata) { @@ -925,7 +906,7 @@ static SDL_bool _Eff_volume_s16lbs(void* stream, unsigned len, void* udata) } return SDL_TRUE; } -#ifdef HAVE_SSE2_INTRINSICS +#ifdef SDL_SSE2_INTRINSICS static SDL_bool _Eff_volume_s16lbs_SSE2(void* stream, unsigned len, void* udata) { /* 16 signed bits (lsb) * 2 channels. */ @@ -960,8 +941,8 @@ static SDL_bool _Eff_volume_s16lbs_SSE2(void* stream, unsigned len, void* udata) } return SDL_TRUE; } -#endif // HAVE_SSE2_INTRINSICS -#ifdef __AVX2__ +#endif // SDL_SSE2_INTRINSICS +#ifdef SDL_AVX2_INTRINSICS static SDL_bool _Eff_volume_s16lbs_AVX2(void* stream, unsigned len, void* udata) { /* 16 signed bits (lsb) * 2 channels. */ @@ -996,7 +977,7 @@ static SDL_bool _Eff_volume_s16lbs_AVX2(void* stream, unsigned len, void* udata) } return SDL_TRUE; } -#endif // __AVX__ +#endif // SDL_AVX2_INTRINSICS #ifdef FULL // FIX_OUT static void SDLCALL _Eff_position_s16lsb_c4(int chan, void *stream, int len, void *udata) { @@ -2376,27 +2357,27 @@ int Mix_SetPosition(int channel, Sint16 angle, Uint8 distance) void _Eff_PositionInit(void) { -#if NEED_SCALAR_CONVERTER_FALLBACKS - _Eff_do_volume_s16lbs = _Eff_volume_s16lbs; - _Eff_do_position_s16lsb = _Eff_position_s16lsb; +#if defined(SDL_AVX2_INTRINSICS) && SDL_VERSION_ATLEAST(2, 0, 2) + if (SDL_HasAVX2()) { + _Eff_do_volume_s16lbs = _Eff_volume_s16lbs_AVX2; + _Eff_do_position_s16lsb = _Eff_position_s16lsb_AVX2; + return; + } #endif -#ifdef HAVE_SSE2_INTRINSICS -#if NEED_SCALAR_CONVERTER_FALLBACKS - if (SDL_HasSSE2()) { -#else +#ifdef SDL_SSE2_INTRINSICS +#ifdef SDL_HAVE_SSE2_SUPPORT // SDL_assert(SDL_HasSSE2()); if (1) { +#else + if (SDL_HasSSE2()) { #endif _Eff_do_volume_s16lbs = _Eff_volume_s16lbs_SSE2; _Eff_do_position_s16lsb = _Eff_position_s16lsb_SSE2; + return; } #endif -#if defined(__AVX2__) && SDL_VERSION_ATLEAST(2, 0, 2) - if (SDL_HasAVX2()) { - _Eff_do_volume_s16lbs = _Eff_volume_s16lbs_AVX2; - _Eff_do_position_s16lsb = _Eff_position_s16lsb_AVX2; - } -#endif + _Eff_do_volume_s16lbs = _Eff_volume_s16lbs; + _Eff_do_position_s16lsb = _Eff_position_s16lsb; } void _Eff_PositionDeinit(void) diff --git a/3rdParty/SDL2_mixer/src/utils.c b/3rdParty/SDL2_mixer/src/utils.c index 20da3b6912c..dadb7c31004 100644 --- a/3rdParty/SDL2_mixer/src/utils.c +++ b/3rdParty/SDL2_mixer/src/utils.c @@ -26,20 +26,6 @@ #include #ifndef FULL // SELF_CONV -#ifdef __SSE2__ -#define HAVE_SSE2_INTRINSICS -#endif - -#if defined(__x86_64__) && defined(HAVE_SSE2_INTRINSICS) -#define HAVE_SSE2_SUPPORT 1 /* x86_64 guarantees SSE2. */ -#elif defined(__MACOSX__) && defined(HAVE_SSE2_INTRINSICS) -#define HAVE_SSE2_SUPPORT 1 /* Mac OS X/Intel guarantees SSE2. */ - -#endif - -#ifndef HAVE_SSE2_SUPPORT -#define HAVE_SSE2_SUPPORT 0 -#endif /* Function pointers set to a CPU-specific implementation. */ //void Mix_Converter_AUDIO8_Mono2Stereo(Mix_BuffOps* buf); @@ -287,7 +273,7 @@ void Mix_Mixer_AUDIOS16(void* dst, const void* src, unsigned len) currPos++; } } -#ifdef HAVE_SSE2_INTRINSICS +#ifdef SDL_SSE2_INTRINSICS void Mix_Mixer_AUDIOS16_SSE2(void* dst, const void* src, unsigned len) { const Sint16* srcPos = (const Sint16*)src; @@ -309,8 +295,8 @@ void Mix_Mixer_AUDIOS16_SSE2(void* dst, const void* src, unsigned len) Mix_Mixer_AUDIOS16(currPos, srcPos, len); } } -#endif // HAVE_SSE2_INTRINSICS -#ifdef __AVX2__ +#endif // SDL_SSE2_INTRINSICS +#ifdef SDL_AVX2_INTRINSICS void Mix_Mixer_AUDIOS16_AVX2(void* dst, const void* src, unsigned len) { const Sint16* srcPos = (const Sint16*)src; @@ -332,11 +318,11 @@ void Mix_Mixer_AUDIOS16_AVX2(void* dst, const void* src, unsigned len) Mix_Mixer_AUDIOS16(currPos, srcPos, len); } } -#endif // __AVX__ +#endif // SDL_AVX2_INTRINSICS #endif // FULL - SELF_MIX #ifndef FULL // SELF_CONV -#ifdef __AVX2__ +#ifdef SDL_AVX2_INTRINSICS void Mix_Converter_AUDIO16_Mono2Stereo_AVX2(Mix_BuffOps* buf) { Sint16* srcPos = (Sint16*)buf->endPos; @@ -365,8 +351,8 @@ void Mix_Converter_AUDIO16_Mono2Stereo_AVX2(Mix_BuffOps* buf) *dstPos = *srcPos; } } -#endif // __AVX__ -#ifdef HAVE_SSE2_INTRINSICS +#endif // SDL_AVX2_INTRINSICS +#ifdef SDL_SSE2_INTRINSICS void Mix_Converter_AUDIO16_Mono2Stereo_SSE2(Mix_BuffOps* buf) { Sint16* srcPos = (Sint16*)buf->endPos; @@ -413,7 +399,7 @@ void Mix_Converter_AUDIO16_Mono2Stereo(Mix_BuffOps* buf) } } -#ifdef HAVE_SSE2_INTRINSICS +#ifdef SDL_SSE2_INTRINSICS void Mix_Converter_AUDIO8_Resample_Half_SSE2(Mix_BuffOps* buf) { Uint8* srcPos = (Uint8*)buf->currPos; @@ -462,7 +448,7 @@ void Mix_Converter_AUDIO8_Resample_Half(Mix_BuffOps* buf) } } -#ifdef HAVE_SSE2_INTRINSICS +#ifdef SDL_SSE2_INTRINSICS void Mix_Converter_AUDIO16_Resample_Half_SSE2(Mix_BuffOps* buf) { Sint16* srcPos = (Sint16*)buf->currPos; @@ -516,7 +502,7 @@ void Mix_Converter_AUDIO16_Resample_Half(Mix_BuffOps* buf) } } -#ifdef __AVX2__ +#ifdef SDL_AVX2_INTRINSICS void Mix_Converter_U8_S16LSB_AVX2(Mix_BuffOps* buf) { Uint8* srcPos = (Uint8*)buf->endPos; @@ -547,8 +533,8 @@ void Mix_Converter_U8_S16LSB_AVX2(Mix_BuffOps* buf) *(Sint16*)dstPos = SDL_SwapLE16((Sint8)(srcPos[0] ^ 0x80) << 8); } } -#endif // __AVX__ -#ifdef HAVE_SSE2_INTRINSICS +#endif // SDL_AVX2_INTRINSICS +#ifdef SDL_SSE2_INTRINSICS void Mix_Converter_U8_S16LSB_SSE2(Mix_BuffOps* buf) { Uint8* srcPos = (Uint8*)buf->endPos; @@ -603,8 +589,8 @@ void Mix_Utils_Init() Mix_Convert_AUDIO16_Resample_Half = Mix_Converter_AUDIO16_Resample_Half; Mix_MixAudioFormat = Mix_Mixer_AUDIOS16; Mix_Convert_U8_S16LSB = Mix_Converter_U8_S16LSB; -#ifdef HAVE_SSE2_INTRINSICS -#if HAVE_SSE2_SUPPORT +#ifdef SDL_SSE2_INTRINSICS +#if SDL_HAVE_SSE2_SUPPORT // SDL_assert(SDL_HasSSE2()); if (1) { #else @@ -618,7 +604,7 @@ void Mix_Utils_Init() Mix_Convert_U8_S16LSB = Mix_Converter_U8_S16LSB_SSE2; } #endif -#if defined(__AVX2__) && SDL_VERSION_ATLEAST(2, 0, 2) +#if defined(SDL_AVX2_INTRINSICS) && SDL_VERSION_ATLEAST(2, 0, 2) if (SDL_HasAVX2()) { Mix_Convert_AUDIO16_Mono2Stereo = Mix_Converter_AUDIO16_Mono2Stereo_AVX2; Mix_MixAudioFormat = Mix_Mixer_AUDIOS16_AVX2; From e098c465951fa1df8a2071b6efc861102e3fa5b4 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 7 May 2024 07:27:15 +0200 Subject: [PATCH 299/596] fix build --- 3rdParty/SDL2_mixer/src/effect_position.c | 16 +++++----- 3rdParty/SDL2_mixer/src/utils.c | 38 +++++++++++------------ 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/3rdParty/SDL2_mixer/src/effect_position.c b/3rdParty/SDL2_mixer/src/effect_position.c index 38b6d0db73f..4bfc3c3bc62 100644 --- a/3rdParty/SDL2_mixer/src/effect_position.c +++ b/3rdParty/SDL2_mixer/src/effect_position.c @@ -745,7 +745,7 @@ static void SDLCALL _Eff_position_s16lsb(int chan, void *stream, int len, void * #else //static_assert(SDL_MAX_SINT16 * MIX_MAX_POS_EFFECT * MIX_MAX_VOLUME <= SDL_MAX_SINT32, "Volume might overflow when the effects are calculated."); #define ADJUST_SIDE_VOLUME(s, v) (s = (s*v)/(MIX_MAX_VOLUME * MIX_MAX_POS_EFFECT)) -static SDL_bool SDLCALL _Eff_position_s16lsb(void* stream, unsigned len, void* udata) +static SDL_bool _Eff_position_s16lsb(void* stream, unsigned len, void* udata) #endif { /* 16 signed bits (lsb) * 2 channels. */ @@ -818,7 +818,7 @@ static SDL_bool SDLCALL _Eff_position_s16lsb(void* stream, unsigned len, void* u return SDL_TRUE; } #ifdef SDL_SSE2_INTRINSICS -static SDL_bool SDLCALL _Eff_position_s16lsb_SSE2(void* stream, unsigned len, void* udata) +static SDL_bool _Eff_position_s16lsb_SSE2(void* stream, unsigned len, void* udata) { /* 16 signed bits (lsb) * 2 channels. */ Sint16* ptr = (Sint16*)stream; @@ -842,7 +842,7 @@ static SDL_bool SDLCALL _Eff_position_s16lsb_SSE2(void* stream, unsigned len, vo len -= 16; __m128i aa = _mm_loadu_si128((const __m128i*)ptr); __m128i bb = _mm_mulhi_epi16(aa, mm); - _mm_storeu_si128(ptr, bb); + _mm_storeu_si128((__m128i*)ptr, bb); ptr += 8; } @@ -853,7 +853,7 @@ static SDL_bool SDLCALL _Eff_position_s16lsb_SSE2(void* stream, unsigned len, vo } #endif // SDL_SSE2_INTRINSICS #ifdef SDL_AVX2_INTRINSICS -static SDL_bool SDLCALL _Eff_position_s16lsb_AVX2(void* stream, unsigned len, void* udata) +static SDL_bool SDL_TARGETING("avx2") _Eff_position_s16lsb_AVX2(void* stream, unsigned len, void* udata) { /* 16 signed bits (lsb) * 2 channels. */ Sint16* ptr = (Sint16*)stream; @@ -877,7 +877,7 @@ static SDL_bool SDLCALL _Eff_position_s16lsb_AVX2(void* stream, unsigned len, vo len -= 32; __m256i aa = _mm256_loadu_si256((const __m256i*)ptr); __m256i bb = _mm256_mulhi_epi16(aa, mm); - _mm256_storeu_si256(ptr, bb); + _mm256_storeu_si256((__m256i*)ptr, bb); ptr += 16; } @@ -927,7 +927,7 @@ static SDL_bool _Eff_volume_s16lbs_SSE2(void* stream, unsigned len, void* udata) len -= 16; __m128i aa = _mm_loadu_si128((const __m128i*)ptr); __m128i bb = _mm_mulhi_epi16(aa, mm); - _mm_storeu_si128(ptr, bb); + _mm_storeu_si128((__m128i*)ptr, bb); ptr += 8; } @@ -943,7 +943,7 @@ static SDL_bool _Eff_volume_s16lbs_SSE2(void* stream, unsigned len, void* udata) } #endif // SDL_SSE2_INTRINSICS #ifdef SDL_AVX2_INTRINSICS -static SDL_bool _Eff_volume_s16lbs_AVX2(void* stream, unsigned len, void* udata) +static SDL_bool SDL_TARGETING("avx2") _Eff_volume_s16lbs_AVX2(void* stream, unsigned len, void* udata) { /* 16 signed bits (lsb) * 2 channels. */ Sint16* ptr = (Sint16*)stream; @@ -963,7 +963,7 @@ static SDL_bool _Eff_volume_s16lbs_AVX2(void* stream, unsigned len, void* udata) len -= 32; __m256i aa = _mm256_loadu_si256((const __m256i*)ptr); __m256i bb = _mm256_mulhi_epi16(aa, mm); - _mm256_storeu_si256(ptr, bb); + _mm256_storeu_si256((__m256i*)ptr, bb); ptr += 16; } diff --git a/3rdParty/SDL2_mixer/src/utils.c b/3rdParty/SDL2_mixer/src/utils.c index dadb7c31004..e05a1c72ee2 100644 --- a/3rdParty/SDL2_mixer/src/utils.c +++ b/3rdParty/SDL2_mixer/src/utils.c @@ -247,7 +247,7 @@ void Mix_RWFromMem(Mix_RWops* rwOps, const void* mem, size_t size) /** * Mix audio buffers. Based on SDL_MixAudioFormat of SDL2/SDL_audio. */ -void Mix_Mixer_AUDIOS16(void* dst, const void* src, unsigned len) +static void Mix_Mixer_AUDIOS16(void* dst, const void* src, unsigned len) { // assert(format == AUDIO_S16LSB); const Sint16* srcPos = (const Sint16*)src; @@ -274,7 +274,7 @@ void Mix_Mixer_AUDIOS16(void* dst, const void* src, unsigned len) } } #ifdef SDL_SSE2_INTRINSICS -void Mix_Mixer_AUDIOS16_SSE2(void* dst, const void* src, unsigned len) +static void Mix_Mixer_AUDIOS16_SSE2(void* dst, const void* src, unsigned len) { const Sint16* srcPos = (const Sint16*)src; Sint16* currPos = (Sint16*)dst; @@ -285,7 +285,7 @@ void Mix_Mixer_AUDIOS16_SSE2(void* dst, const void* src, unsigned len) __m128i bb = _mm_loadu_si128((const __m128i*)currPos); __m128i cc = _mm_adds_epi16(aa, bb); - _mm_storeu_si128(currPos, cc); + _mm_storeu_si128((__m128i*)currPos, cc); currPos += 8; srcPos += 8; @@ -297,7 +297,7 @@ void Mix_Mixer_AUDIOS16_SSE2(void* dst, const void* src, unsigned len) } #endif // SDL_SSE2_INTRINSICS #ifdef SDL_AVX2_INTRINSICS -void Mix_Mixer_AUDIOS16_AVX2(void* dst, const void* src, unsigned len) +static void SDL_TARGETING("avx2") Mix_Mixer_AUDIOS16_AVX2(void* dst, const void* src, unsigned len) { const Sint16* srcPos = (const Sint16*)src; Sint16* currPos = (Sint16*)dst; @@ -308,7 +308,7 @@ void Mix_Mixer_AUDIOS16_AVX2(void* dst, const void* src, unsigned len) __m256i bb = _mm256_loadu_si256((const __m256i*)currPos); __m256i cc = _mm256_adds_epi16(aa, bb); - _mm256_storeu_si256(currPos, cc); + _mm256_storeu_si256((__m256i*)currPos, cc); currPos += 16; srcPos += 16; @@ -323,7 +323,7 @@ void Mix_Mixer_AUDIOS16_AVX2(void* dst, const void* src, unsigned len) #ifndef FULL // SELF_CONV #ifdef SDL_AVX2_INTRINSICS -void Mix_Converter_AUDIO16_Mono2Stereo_AVX2(Mix_BuffOps* buf) +static void SDL_TARGETING("avx2") Mix_Converter_AUDIO16_Mono2Stereo_AVX2(Mix_BuffOps* buf) { Sint16* srcPos = (Sint16*)buf->endPos; Sint16* currPos = (Sint16*)buf->currPos; @@ -336,11 +336,11 @@ void Mix_Converter_AUDIO16_Mono2Stereo_AVX2(Mix_BuffOps* buf) dstPos -= 16; __m256i aa = _mm256_loadu_si256((const __m256i*)srcPos); __m256i bb = _mm256_unpackhi_epi16(aa, aa); - _mm256_storeu_si256(dstPos, bb); + _mm256_storeu_si256((__m256i*)dstPos, bb); dstPos -= 16; __m256i cc = _mm256_unpacklo_epi16(aa, aa); - _mm256_storeu_si256(dstPos, cc); + _mm256_storeu_si256((__m256i*)dstPos, cc); } while (srcPos != currPos) { @@ -353,7 +353,7 @@ void Mix_Converter_AUDIO16_Mono2Stereo_AVX2(Mix_BuffOps* buf) } #endif // SDL_AVX2_INTRINSICS #ifdef SDL_SSE2_INTRINSICS -void Mix_Converter_AUDIO16_Mono2Stereo_SSE2(Mix_BuffOps* buf) +static void Mix_Converter_AUDIO16_Mono2Stereo_SSE2(Mix_BuffOps* buf) { Sint16* srcPos = (Sint16*)buf->endPos; Sint16* currPos = (Sint16*)buf->currPos; @@ -366,11 +366,11 @@ void Mix_Converter_AUDIO16_Mono2Stereo_SSE2(Mix_BuffOps* buf) dstPos -= 8; __m128i aa = _mm_loadu_si128((const __m128i*)srcPos); __m128i bb = _mm_unpackhi_epi16(aa, aa); - _mm_storeu_si128(dstPos, bb); + _mm_storeu_si128((__m128i*)dstPos, bb); dstPos -= 8; __m128i cc = _mm_unpacklo_epi16(aa, aa); - _mm_storeu_si128(dstPos, cc); + _mm_storeu_si128((__m128i*)dstPos, cc); } while (srcPos != currPos) { @@ -382,7 +382,7 @@ void Mix_Converter_AUDIO16_Mono2Stereo_SSE2(Mix_BuffOps* buf) } } #endif // _SSE2_ -void Mix_Converter_AUDIO16_Mono2Stereo(Mix_BuffOps* buf) +static void Mix_Converter_AUDIO16_Mono2Stereo(Mix_BuffOps* buf) { Sint16* srcPos = (Sint16*)buf->endPos; Sint16* currPos = (Sint16*)buf->currPos; @@ -400,7 +400,7 @@ void Mix_Converter_AUDIO16_Mono2Stereo(Mix_BuffOps* buf) } #ifdef SDL_SSE2_INTRINSICS -void Mix_Converter_AUDIO8_Resample_Half_SSE2(Mix_BuffOps* buf) +static void Mix_Converter_AUDIO8_Resample_Half_SSE2(Mix_BuffOps* buf) { Uint8* srcPos = (Uint8*)buf->currPos; Uint8* dstPos = srcPos; @@ -431,7 +431,7 @@ void Mix_Converter_AUDIO8_Resample_Half_SSE2(Mix_BuffOps* buf) } } #endif -void Mix_Converter_AUDIO8_Resample_Half(Mix_BuffOps* buf) +static void Mix_Converter_AUDIO8_Resample_Half(Mix_BuffOps* buf) { Uint8* srcPos = (Uint8*)buf->currPos; Uint8* dstPos = srcPos; @@ -449,7 +449,7 @@ void Mix_Converter_AUDIO8_Resample_Half(Mix_BuffOps* buf) } #ifdef SDL_SSE2_INTRINSICS -void Mix_Converter_AUDIO16_Resample_Half_SSE2(Mix_BuffOps* buf) +static void Mix_Converter_AUDIO16_Resample_Half_SSE2(Mix_BuffOps* buf) { Sint16* srcPos = (Sint16*)buf->currPos; Sint16* dstPos = srcPos; @@ -485,7 +485,7 @@ void Mix_Converter_AUDIO16_Resample_Half_SSE2(Mix_BuffOps* buf) } } #endif -void Mix_Converter_AUDIO16_Resample_Half(Mix_BuffOps* buf) +static void Mix_Converter_AUDIO16_Resample_Half(Mix_BuffOps* buf) { Sint16* srcPos = (Sint16*)buf->currPos; Sint16* dstPos = srcPos; @@ -503,7 +503,7 @@ void Mix_Converter_AUDIO16_Resample_Half(Mix_BuffOps* buf) } #ifdef SDL_AVX2_INTRINSICS -void Mix_Converter_U8_S16LSB_AVX2(Mix_BuffOps* buf) +static void SDL_TARGETING("avx2") Mix_Converter_U8_S16LSB_AVX2(Mix_BuffOps* buf) { Uint8* srcPos = (Uint8*)buf->endPos; Uint8* currPos = (Uint8*)buf->currPos; @@ -535,7 +535,7 @@ void Mix_Converter_U8_S16LSB_AVX2(Mix_BuffOps* buf) } #endif // SDL_AVX2_INTRINSICS #ifdef SDL_SSE2_INTRINSICS -void Mix_Converter_U8_S16LSB_SSE2(Mix_BuffOps* buf) +static void Mix_Converter_U8_S16LSB_SSE2(Mix_BuffOps* buf) { Uint8* srcPos = (Uint8*)buf->endPos; Uint8* currPos = (Uint8*)buf->currPos; @@ -566,7 +566,7 @@ void Mix_Converter_U8_S16LSB_SSE2(Mix_BuffOps* buf) } } #endif -void Mix_Converter_U8_S16LSB(Mix_BuffOps* buf) +static void Mix_Converter_U8_S16LSB(Mix_BuffOps* buf) { Uint8* srcPos = (Uint8*)buf->endPos; Uint8* currPos = (Uint8*)buf->currPos; From e0a3ee62f01388bca2a55de9763b64c0e876fc46 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 8 May 2024 11:34:51 +0200 Subject: [PATCH 300/596] fix mingw-x86 builds --- 3rdParty/SDL2/CMakeLists.txt | 2 +- 3rdParty/SDL2_mixer/src/effect_position.c | 4 ++-- 3rdParty/SDL2_mixer/src/utils.c | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/3rdParty/SDL2/CMakeLists.txt b/3rdParty/SDL2/CMakeLists.txt index 13438179c99..39bc885f504 100644 --- a/3rdParty/SDL2/CMakeLists.txt +++ b/3rdParty/SDL2/CMakeLists.txt @@ -75,7 +75,7 @@ FetchContent_Declare(SDL2 #URL https://github.com/libsdl-org/SDL/archive/5056b29b0f8611b470d8b8bdb313eab628f8bd6e.tar.gz #URL_HASH MD5=3fb6d72c33434082c32d2649c35c6502 GIT_REPOSITORY https://github.com/pionere/SDL.git - GIT_TAG c60a2afdd3b8b0a99d259fdf450cf0faecf999cc + GIT_TAG e7ea792fcd617d65930d080a0b0a76de37a8cc8b ) FetchContent_MakeAvailableExcludeFromAll(SDL2) diff --git a/3rdParty/SDL2_mixer/src/effect_position.c b/3rdParty/SDL2_mixer/src/effect_position.c index 4bfc3c3bc62..fbffe04ce6e 100644 --- a/3rdParty/SDL2_mixer/src/effect_position.c +++ b/3rdParty/SDL2_mixer/src/effect_position.c @@ -818,7 +818,7 @@ static SDL_bool _Eff_position_s16lsb(void* stream, unsigned len, void* udata) return SDL_TRUE; } #ifdef SDL_SSE2_INTRINSICS -static SDL_bool _Eff_position_s16lsb_SSE2(void* stream, unsigned len, void* udata) +static SDL_bool SDL_TARGETING("sse2") _Eff_position_s16lsb_SSE2(void* stream, unsigned len, void* udata) { /* 16 signed bits (lsb) * 2 channels. */ Sint16* ptr = (Sint16*)stream; @@ -907,7 +907,7 @@ static SDL_bool _Eff_volume_s16lbs(void* stream, unsigned len, void* udata) return SDL_TRUE; } #ifdef SDL_SSE2_INTRINSICS -static SDL_bool _Eff_volume_s16lbs_SSE2(void* stream, unsigned len, void* udata) +static SDL_bool SDL_TARGETING("sse2") _Eff_volume_s16lbs_SSE2(void* stream, unsigned len, void* udata) { /* 16 signed bits (lsb) * 2 channels. */ Sint16* ptr = (Sint16*)stream; diff --git a/3rdParty/SDL2_mixer/src/utils.c b/3rdParty/SDL2_mixer/src/utils.c index e05a1c72ee2..372fddf4f2b 100644 --- a/3rdParty/SDL2_mixer/src/utils.c +++ b/3rdParty/SDL2_mixer/src/utils.c @@ -274,7 +274,7 @@ static void Mix_Mixer_AUDIOS16(void* dst, const void* src, unsigned len) } } #ifdef SDL_SSE2_INTRINSICS -static void Mix_Mixer_AUDIOS16_SSE2(void* dst, const void* src, unsigned len) +static void SDL_TARGETING("sse2") Mix_Mixer_AUDIOS16_SSE2(void* dst, const void* src, unsigned len) { const Sint16* srcPos = (const Sint16*)src; Sint16* currPos = (Sint16*)dst; @@ -353,7 +353,7 @@ static void SDL_TARGETING("avx2") Mix_Converter_AUDIO16_Mono2Stereo_AVX2(Mix_Buf } #endif // SDL_AVX2_INTRINSICS #ifdef SDL_SSE2_INTRINSICS -static void Mix_Converter_AUDIO16_Mono2Stereo_SSE2(Mix_BuffOps* buf) +static void SDL_TARGETING("sse2") Mix_Converter_AUDIO16_Mono2Stereo_SSE2(Mix_BuffOps* buf) { Sint16* srcPos = (Sint16*)buf->endPos; Sint16* currPos = (Sint16*)buf->currPos; @@ -381,7 +381,7 @@ static void Mix_Converter_AUDIO16_Mono2Stereo_SSE2(Mix_BuffOps* buf) *dstPos = *srcPos; } } -#endif // _SSE2_ +#endif // SDL_SSE2_INTRINSICS static void Mix_Converter_AUDIO16_Mono2Stereo(Mix_BuffOps* buf) { Sint16* srcPos = (Sint16*)buf->endPos; @@ -400,7 +400,7 @@ static void Mix_Converter_AUDIO16_Mono2Stereo(Mix_BuffOps* buf) } #ifdef SDL_SSE2_INTRINSICS -static void Mix_Converter_AUDIO8_Resample_Half_SSE2(Mix_BuffOps* buf) +static void SDL_TARGETING("sse2") Mix_Converter_AUDIO8_Resample_Half_SSE2(Mix_BuffOps* buf) { Uint8* srcPos = (Uint8*)buf->currPos; Uint8* dstPos = srcPos; @@ -449,7 +449,7 @@ static void Mix_Converter_AUDIO8_Resample_Half(Mix_BuffOps* buf) } #ifdef SDL_SSE2_INTRINSICS -static void Mix_Converter_AUDIO16_Resample_Half_SSE2(Mix_BuffOps* buf) +static void SDL_TARGETING("sse2") Mix_Converter_AUDIO16_Resample_Half_SSE2(Mix_BuffOps* buf) { Sint16* srcPos = (Sint16*)buf->currPos; Sint16* dstPos = srcPos; @@ -535,7 +535,7 @@ static void SDL_TARGETING("avx2") Mix_Converter_U8_S16LSB_AVX2(Mix_BuffOps* buf) } #endif // SDL_AVX2_INTRINSICS #ifdef SDL_SSE2_INTRINSICS -static void Mix_Converter_U8_S16LSB_SSE2(Mix_BuffOps* buf) +static void SDL_TARGETING("sse2") Mix_Converter_U8_S16LSB_SSE2(Mix_BuffOps* buf) { Uint8* srcPos = (Uint8*)buf->endPos; Uint8* currPos = (Uint8*)buf->currPos; From 95bdc37b20f172684c34b383cafb6219fa0a9f2d Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 9 May 2024 07:10:34 +0200 Subject: [PATCH 301/596] update SDL2 --- 3rdParty/SDL2/CMakeLists.txt | 2 +- .../main/java/org/libsdl/app/SDLActivity.java | 6 ++++-- .../org/libsdl/app/SDLControllerManager.java | 16 +++++++++------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/3rdParty/SDL2/CMakeLists.txt b/3rdParty/SDL2/CMakeLists.txt index 39bc885f504..4108c3229e5 100644 --- a/3rdParty/SDL2/CMakeLists.txt +++ b/3rdParty/SDL2/CMakeLists.txt @@ -75,7 +75,7 @@ FetchContent_Declare(SDL2 #URL https://github.com/libsdl-org/SDL/archive/5056b29b0f8611b470d8b8bdb313eab628f8bd6e.tar.gz #URL_HASH MD5=3fb6d72c33434082c32d2649c35c6502 GIT_REPOSITORY https://github.com/pionere/SDL.git - GIT_TAG e7ea792fcd617d65930d080a0b0a76de37a8cc8b + GIT_TAG ac0a97ea29715d16d60519cbe84f1e76f6b1198d ) FetchContent_MakeAvailableExcludeFromAll(SDL2) diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java index 05b82a7e402..8e282040c4f 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -60,8 +60,8 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityChangeListener { private static final String TAG = "SDL"; private static final int SDL_MAJOR_VERSION = 2; - private static final int SDL_MINOR_VERSION = 29; - private static final int SDL_MICRO_VERSION = 2; + private static final int SDL_MINOR_VERSION = 31; + private static final int SDL_MICRO_VERSION = 0; /* // Display InputType.SOURCE/CLASS of events and devices // @@ -1764,6 +1764,8 @@ public static boolean setSystemCursor(int cursorID) { } catch (Exception e) { return false; } + } else { + return false; } return true; } diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java b/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java index d6913f1571f..9d8b20b7bbf 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java @@ -546,13 +546,15 @@ public void pollHapticDevices() { if (haptic == null) { InputDevice device = InputDevice.getDevice(deviceIds[i]); Vibrator vib = device.getVibrator(); - if (vib.hasVibrator()) { - haptic = new SDLHaptic(); - haptic.device_id = deviceIds[i]; - haptic.name = device.getName(); - haptic.vib = vib; - mHaptics.add(haptic); - SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name); + if (vib != null) { + if (vib.hasVibrator()) { + haptic = new SDLHaptic(); + haptic.device_id = deviceIds[i]; + haptic.name = device.getName(); + haptic.vib = vib; + mHaptics.add(haptic); + SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name); + } } } } From 962784704ec84e481b1f66b66ec7e358b07bcd4a Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 9 May 2024 15:16:46 +0200 Subject: [PATCH 302/596] help the compiler... --- 3rdParty/libsmacker/smacker.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/3rdParty/libsmacker/smacker.c b/3rdParty/libsmacker/smacker.c index e46064383bf..3f7989b27bd 100644 --- a/3rdParty/libsmacker/smacker.c +++ b/3rdParty/libsmacker/smacker.c @@ -1158,6 +1158,7 @@ static smk smk_open_generic(union smk_read_t fp, unsigned long size) if (s->mode == SMK_MODE_MEMORY) { smk_malloc(s->source.chunk_data, (s->f + s->ring_frame) * sizeof(unsigned char *)); #else + { smk_malloc(s->source.chunk_data, s->total_frames * sizeof(unsigned char *)); #endif @@ -1186,8 +1187,8 @@ static smk smk_open_generic(union smk_read_t fp, unsigned long size) goto error; } } - } #endif + } return s; #if DEBUG_MODE @@ -1216,13 +1217,13 @@ smk smk_open_memory(const unsigned char * buffer, const unsigned long size) /* set up the read union for Memory mode */ fp.ram = (unsigned char *)buffer; -#ifdef FULL - if (!(s = smk_open_generic(0, fp, size, SMK_MODE_MEMORY))) -#else - if (!(s = smk_open_generic(fp, size))) +#ifdef FULL + if (!(s = smk_open_generic(0, fp, size, SMK_MODE_MEMORY))) +#else + if (!(s = smk_open_generic(fp, size))) #endif - LogError("libsmacker::smk_open_memory(buffer,%lu) - ERROR: Fatal error in smk_open_generic, returning NULL.\n", size); - ; + LogError("libsmacker::smk_open_memory(buffer,%lu) - ERROR: Fatal error in smk_open_generic, returning NULL.\n", size); + ; return s; } From 3ee6b5127612484ccefc05e44c7764c768f52864 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 11 May 2024 10:01:35 +0200 Subject: [PATCH 303/596] update SDL2 --- 3rdParty/SDL2/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdParty/SDL2/CMakeLists.txt b/3rdParty/SDL2/CMakeLists.txt index 4108c3229e5..ed9f14c5eb4 100644 --- a/3rdParty/SDL2/CMakeLists.txt +++ b/3rdParty/SDL2/CMakeLists.txt @@ -75,7 +75,7 @@ FetchContent_Declare(SDL2 #URL https://github.com/libsdl-org/SDL/archive/5056b29b0f8611b470d8b8bdb313eab628f8bd6e.tar.gz #URL_HASH MD5=3fb6d72c33434082c32d2649c35c6502 GIT_REPOSITORY https://github.com/pionere/SDL.git - GIT_TAG ac0a97ea29715d16d60519cbe84f1e76f6b1198d + GIT_TAG 7262505555e6ecc4bfaae26d7ec2f0a42b3e6dd3 ) FetchContent_MakeAvailableExcludeFromAll(SDL2) From 6cccab563a3606a03286c660e66e7f93bf406de9 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 11 May 2024 10:39:23 +0200 Subject: [PATCH 304/596] do not patch L5Light.CEL if the assets are upscaled --- tools/patcher/DiabloUI/patcher.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/patcher/DiabloUI/patcher.cpp b/tools/patcher/DiabloUI/patcher.cpp index 089bfe00824..d847119d27d 100644 --- a/tools/patcher/DiabloUI/patcher.cpp +++ b/tools/patcher/DiabloUI/patcher.cpp @@ -115,7 +115,9 @@ typedef enum filenames { FILE_NEST_MIN, #endif FILE_NEST_TIL, +#if ASSET_MPL == 1 FILE_L5LIGHT_CEL, +#endif FILE_OBJCURS_CEL, #endif NUM_FILENAMES @@ -217,7 +219,9 @@ static const char* const filesToPatch[NUM_FILENAMES] = { /*FILE_NEST_MIN*/ "NLevels\\L6Data\\L6.MIN", #endif /*FILE_NEST_TIL*/ "NLevels\\L6Data\\L6.TIL", +#if ASSET_MPL == 1 /*FILE_L5LIGHT_CEL*/ "Objects\\L5Light.CEL", +#endif /*FILE_OBJCURS_CEL*/ "Data\\Inv\\Objcurs.CEL", #endif }; @@ -2687,10 +2691,12 @@ static BYTE* patchFile(int index, size_t *dwLen) } DRLP_L5_PatchTil(buf); } break; +#if ASSET_MPL == 1 case FILE_L5LIGHT_CEL: { // fix object gfx file - L5Light.CEL buf = fixL5Light(buf, dwLen); } break; +#endif // ASSET_MPL case FILE_OBJCURS_CEL: { size_t sizeB, sizeAB; From 0475c2dcebff941db303cd70943e4631650e92a9 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 11 May 2024 10:50:23 +0200 Subject: [PATCH 305/596] fix the walking animation of 'Devil Kin Brute' --- tools/patcher/DiabloUI/patcher.cpp | 1275 +++++++++++++++++++++++++++- 1 file changed, 1273 insertions(+), 2 deletions(-) diff --git a/tools/patcher/DiabloUI/patcher.cpp b/tools/patcher/DiabloUI/patcher.cpp index d847119d27d..736460546fe 100644 --- a/tools/patcher/DiabloUI/patcher.cpp +++ b/tools/patcher/DiabloUI/patcher.cpp @@ -117,6 +117,7 @@ typedef enum filenames { FILE_NEST_TIL, #if ASSET_MPL == 1 FILE_L5LIGHT_CEL, + FILE_MON_FALLGW, #endif FILE_OBJCURS_CEL, #endif @@ -221,6 +222,7 @@ static const char* const filesToPatch[NUM_FILENAMES] = { /*FILE_NEST_TIL*/ "NLevels\\L6Data\\L6.TIL", #if ASSET_MPL == 1 /*FILE_L5LIGHT_CEL*/ "Objects\\L5Light.CEL", +/*FILE_MON_FALLGW*/ "Monsters\\BigFall\\Fallgw.CL2", #endif /*FILE_OBJCURS_CEL*/ "Data\\Inv\\Objcurs.CEL", #endif @@ -2065,8 +2067,7 @@ BYTE* createWarriorAnim(BYTE* cl2Buf, size_t *dwLen, const BYTE* atkBuf, const B for (int n = 1; n <= ni; n++) { memset(&gpBuffer[0], TRANS_COLOR, BUFFER_WIDTH * height); - - if (ii == 1) { + if (ii == 1) { // DIR_SW // draw the stand frame const BYTE* stdFrameBuf = CelGetFrameStart(stdBuf, ii); // for (int y = 0; y < height; y++) { @@ -2177,6 +2178,1263 @@ BYTE* createWarriorAnim(BYTE* cl2Buf, size_t *dwLen, const BYTE* atkBuf, const B return resCl2Buf; } +BYTE* createFallgwAnim(BYTE* cl2Buf, size_t *dwLen, BYTE* stdBuf) +{ + constexpr BYTE TRANS_COLOR = 1; + constexpr int numGroups = NUM_DIRS; + constexpr int frameCount = 8; + constexpr bool groupped = true; + constexpr int height = 128; + constexpr int width = 128; + + BYTE* resCl2Buf = DiabloAllocPtr(2 * *dwLen); + memset(resCl2Buf, 0, 2 * *dwLen); + + int headerSize = 0; + for (int i = 0; i < numGroups; i++) { + int ni = frameCount; + headerSize += 4 + 4 * (ni + 1); + } + if (groupped) { + headerSize += sizeof(DWORD) * numGroups; + } + + DWORD* hdr = (DWORD*)resCl2Buf; + if (groupped) { + // add optional {CL2 GROUP HEADER} + int offset = numGroups * 4; + for (int i = 0; i < numGroups; i++, hdr++) { + hdr[0] = offset; + int ni = frameCount; + offset += 4 + 4 * (ni + 1); + } + } + + BYTE* pBuf = &resCl2Buf[headerSize]; + for (int ii = 0; ii < numGroups; ii++) { + int ni = frameCount; + hdr[0] = SwapLE32(ni); + hdr[1] = SwapLE32((size_t)pBuf - (size_t)hdr); + + const BYTE* frameBuf = CelGetFrameStart(cl2Buf, ii); + + for (int n = 1; n <= ni; n++) { + memset(&gpBuffer[0], TRANS_COLOR, BUFFER_WIDTH * height); + + if (ii == 6) { // DIR_E + // duplicate the current frame + // for (int y = 0; y < height; y++) { + // memset(&gpBuffer[0 + BUFFER_WIDTH * y], TRANS_COLOR, width); + // } + Cl2Draw(0, height - 1, frameBuf, n, width); + // draw the west-walk frame + const BYTE* wwFrameBuf = CelGetFrameStart(cl2Buf, 2); // DIR_W + // for (int y = 0; y < height; y++) { + // memset(&gpBuffer[width + BUFFER_WIDTH * y], TRANS_COLOR, width); + // } + Cl2Draw(width, height - 1, wwFrameBuf, n, width); + + int i = n - 1; + // mirror the west-walk frame + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + unsigned addr = x + BUFFER_WIDTH * y; + unsigned addr2 = width + (width - x - 1) + BUFFER_WIDTH * y; + BYTE color = gpBuffer[addr2]; + if (color != TRANS_COLOR) { + if ((color >= 170 && color <= 175) || (color >= 190 && color <= 205) || color >= 251) { + if (i == 0) { + if (x >= 71 && y >= 99 && y <= 112) { + continue; + } + } + if (i == 1) { + if (x >= 67 && y >= 101 && y <= 110) { + continue; + } + } + if (i == 2) { + if (x >= 62 && y >= 105 && y <= 114) { + continue; + } + } + if (i == 3) { + if (x >= 58 && y >= 109 && y <= 118) { + continue; + } + } + if (i == 4) { + if (x >= 57 && y >= 110 && y <= 121) { + continue; + } + } + if (i == 5) { + if (x >= 58 && y >= 110 && y <= 119) { + continue; + } + } + if (i == 6) { + if (x >= 62 && y >= 106 && y <= 114) { + continue; + } + } + if (i == 7) { + if (x >= 66 && y >= 96 && y <= 112) { + continue; + } + } + /*if (x >= 62 && y >= 99 && y <= 121) { + continue; + }*/ + } + if (color == 0) { + if (i == 0) { + if (/*x >= 87 || */(x >= 81 && y >= 118 + 10 - x / 8)) { + color = TRANS_COLOR; + } + } + if (i == 1) { + if (/*x >= 87 || */(x >= 79 && y >= 118 + 10 - x / 8)) { + color = TRANS_COLOR; + } + } + if (i == 2) { + if (/*x >= 87 || */(x >= 75 && y >= 118 + 10 - x / 8)) { + color = TRANS_COLOR; + } + } + if (i == 3) { + if (/*x >= 87 || */(x >= 70 && y >= 118)) { + color = TRANS_COLOR; + } + } + if (i == 4) { + if (/*x >= 87 || */(x >= 67 && y >= 119)) { + color = TRANS_COLOR; + } + } + if (i == 5) { + if (/*x >= 87 || */(x >= 71 && y >= 119)) { + color = TRANS_COLOR; + } + } + if (i == 6) { + if (/*x >= 87 || */(x >= 72 && y >= 117 && y >= 120 + 72 - x)) { + color = TRANS_COLOR; + } + } + if (i == 7) { + if (/*x >= 87 || */(x >= 85 && y <= 118 && y >= 118 + 85 - x)) { + color = TRANS_COLOR; + } + } + /*if (x >= 65 && y >= 115 && y <= 122) { + continue; + }*/ + } + } + gpBuffer[addr] = color; + } + } + + // copy the club from the stand frame + int fn, dx, dy; + switch (i) { + case 0: fn = 8; dx = -11; dy = 11; break; + case 1: fn = 9; dx = -8; dy = 9; break; + case 2: fn = 9; dx = -7; dy = 9; break; + case 3: fn = 9; dx = -5; dy = 9; break; + case 4: fn = 9; dx = -4; dy = 9; break; + case 5: fn = 9; dx = -5; dy = 8; break; + case 6: fn = 8; dx = -2; dy = 5; break; + case 7: fn = 9; dx = -8; dy = 8; break; + } + const BYTE* stdFrameBuf = CelGetFrameStart(stdBuf, ii); + for (int y = 0; y < height; y++) { + memset(&gpBuffer[width + BUFFER_WIDTH * y], TRANS_COLOR, width); + } + Cl2Draw(width, height - 1, stdFrameBuf, fn + 1, width); + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + unsigned addr = x + dx + BUFFER_WIDTH * (y + dy); + unsigned addr2 = width + x + BUFFER_WIDTH * y; + BYTE color = gpBuffer[addr2]; + if (color == TRANS_COLOR) { + continue; + } + switch (fn) { + case 7: + if (x < 60 || y < 88 || y > 111 || (color != 0 && !(color >= 170 && color <= 175) && !(color >= 188 && color <= 205) && color != 223 && color != 251 && color != 252)) + continue; + break; + case 8: + case 9: + if (x < 80 || y < 86 || y > 109 || (color != 0 && !(color >= 170 && color <= 175) && !(color >= 188 && color <= 205) && color != 223 && color != 251 && color != 252)) + continue; + break; + } + BYTE curr_color = gpBuffer[addr]; + if (curr_color == TRANS_COLOR + || (i == 0 && curr_color == 0 && x >= 75 + 11)) { + gpBuffer[addr] = color; + } + } + } + + // fix artifacts + switch (i) { + case 0: dx = 85; break; + case 1: dx = 92; break; + case 2: dx = 93; break; + case 3: dx = 95; break; + case 4: dx = 96; break; + case 5: dx = 95; break; + case 6: dx = 94; break; + case 7: dx = 93; break; + } + for (int y = 85; y < height; y++) { + for (int x = dx; x < width; x++) { + gpBuffer[x + BUFFER_WIDTH * y] = TRANS_COLOR; + } + } + + if (i == 0) { + gpBuffer[76 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[83 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[77 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[78 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[79 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[83 + BUFFER_WIDTH * 110] = TRANS_COLOR; // color0) + gpBuffer[84 + BUFFER_WIDTH * 110] = TRANS_COLOR; // color0) + gpBuffer[78 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[79 + BUFFER_WIDTH * 112] = 0; // was tp + gpBuffer[80 + BUFFER_WIDTH * 112] = 0; // was tp + gpBuffer[79 + BUFFER_WIDTH * 113] = 0; // was tp + gpBuffer[81 + BUFFER_WIDTH * 115] = TRANS_COLOR; // color0) + gpBuffer[82 + BUFFER_WIDTH * 115] = TRANS_COLOR; // color0) + gpBuffer[83 + BUFFER_WIDTH * 115] = TRANS_COLOR; // color0) + gpBuffer[84 + BUFFER_WIDTH * 115] = TRANS_COLOR; // color0) + gpBuffer[82 + BUFFER_WIDTH * 116] = TRANS_COLOR; // color0) + gpBuffer[83 + BUFFER_WIDTH * 116] = TRANS_COLOR; // color0) + gpBuffer[84 + BUFFER_WIDTH * 116] = TRANS_COLOR; // color0) + gpBuffer[69 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[70 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[80 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[81 + BUFFER_WIDTH * 118] = 0; // was tp + } + if (i == 1) { + for (int y = 106; y < 114; y++) { + for (int x = 73; x < 86; x++) { + if (y < 276 - 2 * x) { + gpBuffer[x + BUFFER_WIDTH * y] = 0; + } + } + } + for (int y = 105; y < 109; y++) { + for (int x = 84; x < 88; x++) { + if (x != 87 || (y != 105 || y != 108)) { + gpBuffer[x + BUFFER_WIDTH * y] = 0; + } + } + } + gpBuffer[73 + BUFFER_WIDTH * 100] = 175; // was tp + gpBuffer[74 + BUFFER_WIDTH * 100] = 175; // was tp + gpBuffer[91 + BUFFER_WIDTH * 102] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 103] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 103] = TRANS_COLOR; // color191) + gpBuffer[84 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[82 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[83 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[84 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 109] = TRANS_COLOR; // color207) + gpBuffer[82 + BUFFER_WIDTH * 113] = 0; // was tp + gpBuffer[84 + BUFFER_WIDTH * 115] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 115] = TRANS_COLOR; // color0) + gpBuffer[82 + BUFFER_WIDTH * 116] = TRANS_COLOR; // color0) + gpBuffer[83 + BUFFER_WIDTH * 116] = TRANS_COLOR; // color0) + gpBuffer[84 + BUFFER_WIDTH * 116] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 116] = TRANS_COLOR; // color0) + gpBuffer[82 + BUFFER_WIDTH * 117] = TRANS_COLOR; // color0) + gpBuffer[83 + BUFFER_WIDTH * 117] = TRANS_COLOR; // color0) + gpBuffer[84 + BUFFER_WIDTH * 117] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 117] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 117] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 117] = TRANS_COLOR; // color0) + gpBuffer[76 + BUFFER_WIDTH * 118] = TRANS_COLOR; // color0) + gpBuffer[77 + BUFFER_WIDTH * 118] = TRANS_COLOR; // color0) + gpBuffer[78 + BUFFER_WIDTH * 118] = TRANS_COLOR; // color0) + gpBuffer[79 + BUFFER_WIDTH * 118] = TRANS_COLOR; // color0) + gpBuffer[74 + BUFFER_WIDTH * 119] = TRANS_COLOR; // color0) + gpBuffer[75 + BUFFER_WIDTH * 119] = TRANS_COLOR; // color0) + gpBuffer[76 + BUFFER_WIDTH * 119] = TRANS_COLOR; // color0) + } + if (i == 2) { + gpBuffer[71 + BUFFER_WIDTH * 96] = 238; // was color191) + gpBuffer[71 + BUFFER_WIDTH * 97] = 237; // was color191) + gpBuffer[72 + BUFFER_WIDTH * 97] = 236; // was tp + gpBuffer[73 + BUFFER_WIDTH * 97] = 237; // was color191) + gpBuffer[75 + BUFFER_WIDTH * 97] = 236; // was tp + gpBuffer[76 + BUFFER_WIDTH * 97] = 236; // was tp + gpBuffer[71 + BUFFER_WIDTH * 98] = 238; // was tp + gpBuffer[72 + BUFFER_WIDTH * 98] = 237; // was tp + gpBuffer[73 + BUFFER_WIDTH * 98] = 236; // was tp + gpBuffer[74 + BUFFER_WIDTH * 98] = 236; // was color203) + gpBuffer[70 + BUFFER_WIDTH * 99] = 238; // was tp + gpBuffer[71 + BUFFER_WIDTH * 99] = 236; // was tp + gpBuffer[72 + BUFFER_WIDTH * 99] = 238; // was tp + gpBuffer[73 + BUFFER_WIDTH * 99] = 238; // was tp + gpBuffer[74 + BUFFER_WIDTH * 99] = 238; // was tp + gpBuffer[70 + BUFFER_WIDTH * 100] = 235; // was tp + gpBuffer[71 + BUFFER_WIDTH * 100] = 237; // was tp + gpBuffer[72 + BUFFER_WIDTH * 100] = 237; // was tp + gpBuffer[73 + BUFFER_WIDTH * 100] = 238; // was tp + gpBuffer[74 + BUFFER_WIDTH * 100] = 238; // was tp + gpBuffer[75 + BUFFER_WIDTH * 100] = 236; // was tp + gpBuffer[69 + BUFFER_WIDTH * 101] = 237; // was tp + gpBuffer[70 + BUFFER_WIDTH * 101] = 236; // was tp + gpBuffer[71 + BUFFER_WIDTH * 101] = 237; // was tp + gpBuffer[72 + BUFFER_WIDTH * 101] = 237; // was tp + gpBuffer[73 + BUFFER_WIDTH * 101] = 238; // was tp + gpBuffer[74 + BUFFER_WIDTH * 101] = 236; // was tp + gpBuffer[75 + BUFFER_WIDTH * 101] = 173; // was tp + gpBuffer[76 + BUFFER_WIDTH * 101] = 173; // was tp + gpBuffer[69 + BUFFER_WIDTH * 102] = 237; // was tp + gpBuffer[70 + BUFFER_WIDTH * 102] = 237; // was tp + gpBuffer[71 + BUFFER_WIDTH * 102] = 236; // was tp + gpBuffer[72 + BUFFER_WIDTH * 102] = 237; // was tp + gpBuffer[73 + BUFFER_WIDTH * 102] = 238; // was tp + gpBuffer[74 + BUFFER_WIDTH * 102] = 236; // was tp + gpBuffer[70 + BUFFER_WIDTH * 103] = 238; // was tp + gpBuffer[71 + BUFFER_WIDTH * 103] = 238; // was tp + gpBuffer[72 + BUFFER_WIDTH * 103] = 238; // was tp + gpBuffer[92 + BUFFER_WIDTH * 103] = TRANS_COLOR; // color0) + gpBuffer[70 + BUFFER_WIDTH * 104] = 238; // was tp + gpBuffer[71 + BUFFER_WIDTH * 104] = 238; // was tp + gpBuffer[72 + BUFFER_WIDTH * 104] = 238; // was tp + gpBuffer[73 + BUFFER_WIDTH * 104] = 236; // was tp + gpBuffer[84 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[70 + BUFFER_WIDTH * 105] = 235; // was tp + gpBuffer[71 + BUFFER_WIDTH * 105] = 238; // was tp + gpBuffer[72 + BUFFER_WIDTH * 105] = 236; // was tp + gpBuffer[73 + BUFFER_WIDTH * 105] = 238; // was color170) + gpBuffer[85 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[70 + BUFFER_WIDTH * 106] = 236; // was color238) + gpBuffer[71 + BUFFER_WIDTH * 106] = 238; // was tp + gpBuffer[72 + BUFFER_WIDTH * 106] = 238; // was tp + gpBuffer[73 + BUFFER_WIDTH * 106] = 238; // was tp + gpBuffer[92 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[71 + BUFFER_WIDTH * 107] = 238; // was tp + gpBuffer[72 + BUFFER_WIDTH * 107] = 238; // was tp + gpBuffer[73 + BUFFER_WIDTH * 107] = 0; // was tp + gpBuffer[81 + BUFFER_WIDTH * 107] = 0; // was tp + gpBuffer[82 + BUFFER_WIDTH * 107] = 0; // was tp + gpBuffer[83 + BUFFER_WIDTH * 107] = 0; // was tp + gpBuffer[68 + BUFFER_WIDTH * 108] = 238; // was tp + gpBuffer[69 + BUFFER_WIDTH * 108] = 236; // was tp + gpBuffer[70 + BUFFER_WIDTH * 108] = 238; // was tp + gpBuffer[71 + BUFFER_WIDTH * 108] = 238; // was tp + gpBuffer[73 + BUFFER_WIDTH * 108] = 0; // was color191) + gpBuffer[76 + BUFFER_WIDTH * 108] = 0; // was tp + gpBuffer[77 + BUFFER_WIDTH * 108] = 0; // was tp + gpBuffer[78 + BUFFER_WIDTH * 108] = 0; // was tp + gpBuffer[79 + BUFFER_WIDTH * 108] = 0; // was tp + gpBuffer[80 + BUFFER_WIDTH * 108] = 0; // was tp + gpBuffer[81 + BUFFER_WIDTH * 108] = 0; // was tp + gpBuffer[82 + BUFFER_WIDTH * 108] = 0; // was tp + gpBuffer[83 + BUFFER_WIDTH * 108] = 0; // was tp + gpBuffer[68 + BUFFER_WIDTH * 109] = 238; // was tp + gpBuffer[69 + BUFFER_WIDTH * 109] = 238; // was tp + gpBuffer[70 + BUFFER_WIDTH * 109] = 238; // was tp + gpBuffer[73 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[74 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[75 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[76 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[77 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[78 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[79 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[80 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[81 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[82 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[88 + BUFFER_WIDTH * 109] = TRANS_COLOR; // color207) + gpBuffer[73 + BUFFER_WIDTH * 110] = 0; // was color189) + gpBuffer[74 + BUFFER_WIDTH * 110] = 0; // was color189) + gpBuffer[75 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[76 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[77 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[78 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[79 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[80 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[81 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[86 + BUFFER_WIDTH * 110] = TRANS_COLOR; // color223) + gpBuffer[71 + BUFFER_WIDTH * 111] = 237; // was color0) + gpBuffer[83 + BUFFER_WIDTH * 111] = TRANS_COLOR; // color0) + gpBuffer[71 + BUFFER_WIDTH * 112] = 237; // was color0) + gpBuffer[72 + BUFFER_WIDTH * 112] = 237; // was color0) + gpBuffer[73 + BUFFER_WIDTH * 112] = 238; // was color0) + gpBuffer[74 + BUFFER_WIDTH * 112] = 237; // was color0) + gpBuffer[81 + BUFFER_WIDTH * 112] = 0; // was tp + gpBuffer[82 + BUFFER_WIDTH * 112] = 0; // was tp + gpBuffer[85 + BUFFER_WIDTH * 112] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 112] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 112] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 112] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 112] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 112] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 112] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 112] = TRANS_COLOR; // color0) + gpBuffer[70 + BUFFER_WIDTH * 113] = 236; // was color0) + gpBuffer[71 + BUFFER_WIDTH * 113] = 236; // was color0) + gpBuffer[72 + BUFFER_WIDTH * 113] = 237; // was color0) + gpBuffer[73 + BUFFER_WIDTH * 113] = 237; // was color0) + gpBuffer[83 + BUFFER_WIDTH * 113] = 0; // was tp + gpBuffer[84 + BUFFER_WIDTH * 113] = 0; // was tp + gpBuffer[89 + BUFFER_WIDTH * 113] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 113] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 113] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 113] = TRANS_COLOR; // color0) + gpBuffer[73 + BUFFER_WIDTH * 114] = 236; // was color0) + gpBuffer[85 + BUFFER_WIDTH * 114] = 0; // was tp + gpBuffer[86 + BUFFER_WIDTH * 115] = TRANS_COLOR; // color0) + gpBuffer[84 + BUFFER_WIDTH * 116] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 116] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 116] = TRANS_COLOR; // color0) + gpBuffer[75 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[76 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[77 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[78 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[79 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[83 + BUFFER_WIDTH * 117] = TRANS_COLOR; // color0) + gpBuffer[84 + BUFFER_WIDTH * 117] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 117] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 117] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 117] = TRANS_COLOR; // color0) + gpBuffer[79 + BUFFER_WIDTH * 118] = TRANS_COLOR; // color0) + } + if (i == 3) { // 52 + gpBuffer[68 + BUFFER_WIDTH * 87] = 237; // was tp + gpBuffer[69 + BUFFER_WIDTH * 87] = 237; // was tp + gpBuffer[70 + BUFFER_WIDTH * 88] = 237; // was tp + gpBuffer[75 + BUFFER_WIDTH * 88] = 237; // was tp + gpBuffer[70 + BUFFER_WIDTH * 89] = 237; // was tp + gpBuffer[71 + BUFFER_WIDTH * 89] = 237; // was tp + gpBuffer[72 + BUFFER_WIDTH * 90] = 237; // was tp + gpBuffer[72 + BUFFER_WIDTH * 91] = 237; // was tp + gpBuffer[76 + BUFFER_WIDTH * 91] = 175; // was color237) + gpBuffer[77 + BUFFER_WIDTH * 91] = TRANS_COLOR; // color237) + gpBuffer[77 + BUFFER_WIDTH * 92] = 175; // was tp + gpBuffer[76 + BUFFER_WIDTH * 94] = 237; // was tp + gpBuffer[76 + BUFFER_WIDTH * 95] = 237; // was tp + gpBuffer[77 + BUFFER_WIDTH * 95] = 175; // was tp + gpBuffer[66 + BUFFER_WIDTH * 96] = 235; // was tp + gpBuffer[76 + BUFFER_WIDTH * 96] = 237; // was tp + gpBuffer[77 + BUFFER_WIDTH * 96] = 237; // was tp + gpBuffer[78 + BUFFER_WIDTH * 96] = 237; // was tp + gpBuffer[66 + BUFFER_WIDTH * 97] = 235; // was tp + gpBuffer[76 + BUFFER_WIDTH * 97] = 203; // was tp + gpBuffer[77 + BUFFER_WIDTH * 97] = 203; // was tp + gpBuffer[78 + BUFFER_WIDTH * 97] = 237; // was tp + gpBuffer[66 + BUFFER_WIDTH * 98] = 235; // was tp + gpBuffer[75 + BUFFER_WIDTH * 98] = 237; // was tp + gpBuffer[73 + BUFFER_WIDTH * 99] = 237; // was tp + gpBuffer[74 + BUFFER_WIDTH * 99] = 174; // was tp + gpBuffer[75 + BUFFER_WIDTH * 99] = 203; // was tp + gpBuffer[76 + BUFFER_WIDTH * 99] = 237; // was tp + gpBuffer[77 + BUFFER_WIDTH * 99] = 203; // was color170) + gpBuffer[73 + BUFFER_WIDTH * 100] = 237; // was tp + gpBuffer[74 + BUFFER_WIDTH * 100] = 174; // was tp + gpBuffer[75 + BUFFER_WIDTH * 100] = 174; // was tp + gpBuffer[76 + BUFFER_WIDTH * 100] = 237; // was tp + gpBuffer[77 + BUFFER_WIDTH * 100] = 237; // was tp + gpBuffer[67 + BUFFER_WIDTH * 101] = 237; // was tp + gpBuffer[73 + BUFFER_WIDTH * 101] = 174; // was tp + gpBuffer[80 + BUFFER_WIDTH * 101] = 175; // was tp + gpBuffer[81 + BUFFER_WIDTH * 101] = 172; // was tp + gpBuffer[67 + BUFFER_WIDTH * 102] = 237; // was tp + gpBuffer[73 + BUFFER_WIDTH * 102] = 238; // was tp + gpBuffer[66 + BUFFER_WIDTH * 103] = 238; // was tp + gpBuffer[67 + BUFFER_WIDTH * 103] = 237; // was tp + gpBuffer[68 + BUFFER_WIDTH * 103] = 237; // was tp + gpBuffer[73 + BUFFER_WIDTH * 103] = 237; // was tp + gpBuffer[75 + BUFFER_WIDTH * 103] = TRANS_COLOR; // color189) + gpBuffer[76 + BUFFER_WIDTH * 103] = TRANS_COLOR; // color188) + gpBuffer[86 + BUFFER_WIDTH * 103] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 103] = TRANS_COLOR; // color0) + gpBuffer[66 + BUFFER_WIDTH * 104] = 237; // was tp + gpBuffer[67 + BUFFER_WIDTH * 104] = 237; // was tp + gpBuffer[68 + BUFFER_WIDTH * 104] = 235; // was tp + gpBuffer[69 + BUFFER_WIDTH * 104] = 235; // was color207) + gpBuffer[81 + BUFFER_WIDTH * 104] = 0; // was tp + gpBuffer[84 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[94 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[66 + BUFFER_WIDTH * 105] = 237; // was tp + gpBuffer[67 + BUFFER_WIDTH * 105] = 237; // was tp + gpBuffer[68 + BUFFER_WIDTH * 105] = 235; // was tp + gpBuffer[72 + BUFFER_WIDTH * 105] = 237; // was tp + gpBuffer[75 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color170) + gpBuffer[84 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[94 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[66 + BUFFER_WIDTH * 106] = 237; // was tp + gpBuffer[67 + BUFFER_WIDTH * 106] = 235; // was tp + gpBuffer[68 + BUFFER_WIDTH * 106] = 235; // was tp + gpBuffer[72 + BUFFER_WIDTH * 106] = 237; // was tp + gpBuffer[73 + BUFFER_WIDTH * 106] = 237; // was tp + gpBuffer[85 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[94 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[66 + BUFFER_WIDTH * 107] = 235; // was tp + gpBuffer[67 + BUFFER_WIDTH * 107] = 237; // was tp + gpBuffer[68 + BUFFER_WIDTH * 107] = 237; // was tp + gpBuffer[72 + BUFFER_WIDTH * 107] = 237; // was tp + gpBuffer[85 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[94 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[66 + BUFFER_WIDTH * 108] = 237; // was tp + gpBuffer[67 + BUFFER_WIDTH * 108] = 235; // was tp + gpBuffer[68 + BUFFER_WIDTH * 108] = 235; // was tp + gpBuffer[84 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[94 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[67 + BUFFER_WIDTH * 109] = 237; // was tp + gpBuffer[68 + BUFFER_WIDTH * 109] = 235; // was tp + gpBuffer[71 + BUFFER_WIDTH * 109] = 238; // was tp + gpBuffer[83 + BUFFER_WIDTH * 109] = TRANS_COLOR; // color0) + gpBuffer[84 + BUFFER_WIDTH * 109] = TRANS_COLOR; // color0) + gpBuffer[68 + BUFFER_WIDTH * 110] = 238; // was tp + gpBuffer[72 + BUFFER_WIDTH * 110] = 238; // was tp + gpBuffer[76 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[77 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[78 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[79 + BUFFER_WIDTH * 110] = 0; // was 235 + gpBuffer[80 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[71 + BUFFER_WIDTH * 111] = 238; // was tp + gpBuffer[72 + BUFFER_WIDTH * 111] = 238; // was tp + gpBuffer[73 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[74 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[75 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[76 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[77 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[78 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[79 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[80 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[81 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[82 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[83 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[69 + BUFFER_WIDTH * 112] = 238; // was tp + gpBuffer[73 + BUFFER_WIDTH * 112] = 237; // was color0 + gpBuffer[84 + BUFFER_WIDTH * 112] = 0; // was tp + gpBuffer[85 + BUFFER_WIDTH * 112] = 0; // was tp + gpBuffer[86 + BUFFER_WIDTH * 112] = 0; // was tp + gpBuffer[68 + BUFFER_WIDTH * 113] = 238; // was tp + gpBuffer[73 + BUFFER_WIDTH * 113] = 0; // was tp + gpBuffer[74 + BUFFER_WIDTH * 113] = 0; // was tp + gpBuffer[88 + BUFFER_WIDTH * 113] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 113] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 113] = TRANS_COLOR; // color0) + gpBuffer[72 + BUFFER_WIDTH * 114] = 0; // was tp + gpBuffer[76 + BUFFER_WIDTH * 114] = 0; // was color188 + gpBuffer[88 + BUFFER_WIDTH * 114] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 114] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 114] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 114] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 115] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 115] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 115] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 115] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 115] = TRANS_COLOR; // color0) + gpBuffer[72 + BUFFER_WIDTH * 116] = 0; // was tp + gpBuffer[85 + BUFFER_WIDTH * 116] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 116] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 116] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 116] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 116] = TRANS_COLOR; // color0) + gpBuffer[70 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[71 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[72 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[85 + BUFFER_WIDTH * 117] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 117] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 117] = TRANS_COLOR; // color0) + gpBuffer[70 + BUFFER_WIDTH * 118] = 0; // was tp + gpBuffer[71 + BUFFER_WIDTH * 118] = 0; // was tp + gpBuffer[72 + BUFFER_WIDTH * 118] = 0; // was tp + } + if (i == 4) { // 53 + gpBuffer[72 + BUFFER_WIDTH * 89] = 238; // was tp + gpBuffer[73 + BUFFER_WIDTH * 90] = 238; // was tp + gpBuffer[73 + BUFFER_WIDTH * 91] = 238; // was tp + gpBuffer[74 + BUFFER_WIDTH * 91] = 238; // was tp + gpBuffer[74 + BUFFER_WIDTH * 92] = 238; // was tp + gpBuffer[75 + BUFFER_WIDTH * 94] = 238; // was tp + gpBuffer[75 + BUFFER_WIDTH * 95] = 238; // was tp + gpBuffer[77 + BUFFER_WIDTH * 95] = 237; // was tp + gpBuffer[78 + BUFFER_WIDTH * 95] = 237; // was tp + gpBuffer[79 + BUFFER_WIDTH * 95] = 237; // was tp + gpBuffer[76 + BUFFER_WIDTH * 96] = 236; // was tp + gpBuffer[77 + BUFFER_WIDTH * 96] = 237; // was tp + gpBuffer[78 + BUFFER_WIDTH * 96] = 236; // was tp + gpBuffer[79 + BUFFER_WIDTH * 96] = 237; // was tp + gpBuffer[80 + BUFFER_WIDTH * 96] = 234; // was tp + gpBuffer[77 + BUFFER_WIDTH * 97] = 237; // was tp + gpBuffer[78 + BUFFER_WIDTH * 97] = 203; // was tp + gpBuffer[79 + BUFFER_WIDTH * 97] = 236; // was tp + gpBuffer[65 + BUFFER_WIDTH * 98] = 238; // was color190) + gpBuffer[66 + BUFFER_WIDTH * 98] = 238; // was tp + gpBuffer[67 + BUFFER_WIDTH * 98] = 238; // was tp + gpBuffer[76 + BUFFER_WIDTH * 98] = 237; // was tp + gpBuffer[65 + BUFFER_WIDTH * 99] = 236; // was tp + gpBuffer[66 + BUFFER_WIDTH * 99] = 236; // was tp + gpBuffer[67 + BUFFER_WIDTH * 99] = 238; // was tp + gpBuffer[76 + BUFFER_WIDTH * 99] = 237; // was tp + gpBuffer[77 + BUFFER_WIDTH * 99] = 237; // was tp + gpBuffer[66 + BUFFER_WIDTH * 100] = 236; // was tp + gpBuffer[67 + BUFFER_WIDTH * 100] = 237; // was tp + gpBuffer[75 + BUFFER_WIDTH * 100] = 237; // was tp + gpBuffer[76 + BUFFER_WIDTH * 100] = 237; // was tp + gpBuffer[77 + BUFFER_WIDTH * 100] = 237; // was tp + gpBuffer[78 + BUFFER_WIDTH * 100] = 236; // was tp + gpBuffer[65 + BUFFER_WIDTH * 101] = 237; // was tp + gpBuffer[66 + BUFFER_WIDTH * 101] = 236; // was tp + gpBuffer[74 + BUFFER_WIDTH * 101] = 237; // was tp + gpBuffer[75 + BUFFER_WIDTH * 101] = 237; // was tp + gpBuffer[76 + BUFFER_WIDTH * 101] = 237; // was tp + gpBuffer[75 + BUFFER_WIDTH * 102] = 237; // was tp + gpBuffer[75 + BUFFER_WIDTH * 103] = 237; // was tp + gpBuffer[77 + BUFFER_WIDTH * 103] = TRANS_COLOR; // color188) + gpBuffer[75 + BUFFER_WIDTH * 104] = 236; // was tp + gpBuffer[85 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[94 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[95 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[75 + BUFFER_WIDTH * 105] = 236; // was tp + gpBuffer[83 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[84 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[94 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[95 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[75 + BUFFER_WIDTH * 106] = 237; // was color0) + gpBuffer[83 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[84 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[94 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[95 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[74 + BUFFER_WIDTH * 107] = 237; // was color0) + gpBuffer[84 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[94 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[95 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[75 + BUFFER_WIDTH * 108] = 237; // was color0) + gpBuffer[76 + BUFFER_WIDTH * 108] = 237; // was color0) + gpBuffer[86 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[94 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[75 + BUFFER_WIDTH * 109] = 236; // was color0) + gpBuffer[76 + BUFFER_WIDTH * 109] = 236; // was color0) + gpBuffer[86 + BUFFER_WIDTH * 109] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 109] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 109] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 109] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 109] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 109] = TRANS_COLOR; // color0) + gpBuffer[76 + BUFFER_WIDTH * 110] = 219; // was color0) + gpBuffer[77 + BUFFER_WIDTH * 110] = 236; // was color0) + gpBuffer[78 + BUFFER_WIDTH * 110] = 237; // was color0) + gpBuffer[77 + BUFFER_WIDTH * 111] = 237; // was color0) + gpBuffer[78 + BUFFER_WIDTH * 111] = 237; // was color0) + gpBuffer[79 + BUFFER_WIDTH * 111] = 236; // was color0) + gpBuffer[80 + BUFFER_WIDTH * 111] = 237; // was color188) + gpBuffer[81 + BUFFER_WIDTH * 111] = 236; // was tp + gpBuffer[83 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[85 + BUFFER_WIDTH * 111] = TRANS_COLOR; // color0) + gpBuffer[77 + BUFFER_WIDTH * 112] = 237; // was tp + gpBuffer[79 + BUFFER_WIDTH * 112] = 237; // was tp + gpBuffer[82 + BUFFER_WIDTH * 112] = 236; // was color219) + gpBuffer[83 + BUFFER_WIDTH * 112] = 237; // was color219) + gpBuffer[85 + BUFFER_WIDTH * 112] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 112] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 112] = TRANS_COLOR; // color0) + gpBuffer[64 + BUFFER_WIDTH * 113] = 0; // was tp + gpBuffer[65 + BUFFER_WIDTH * 113] = 0; // was tp + gpBuffer[66 + BUFFER_WIDTH * 113] = 0; // was tp + gpBuffer[67 + BUFFER_WIDTH * 113] = 0; // was tp + gpBuffer[68 + BUFFER_WIDTH * 113] = 0; // was tp + gpBuffer[69 + BUFFER_WIDTH * 113] = 0; // was tp + gpBuffer[70 + BUFFER_WIDTH * 113] = 0; // was tp + gpBuffer[71 + BUFFER_WIDTH * 113] = 0; // was tp + gpBuffer[84 + BUFFER_WIDTH * 113] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 113] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 113] = TRANS_COLOR; // color0) + gpBuffer[69 + BUFFER_WIDTH * 114] = 0; // was tp + gpBuffer[70 + BUFFER_WIDTH * 114] = 0; // was tp + gpBuffer[71 + BUFFER_WIDTH * 114] = 0; // was tp + gpBuffer[72 + BUFFER_WIDTH * 114] = 0; // was tp + gpBuffer[73 + BUFFER_WIDTH * 114] = 0; // was tp + gpBuffer[74 + BUFFER_WIDTH * 114] = 0; // was tp + gpBuffer[75 + BUFFER_WIDTH * 114] = 0; // was tp + gpBuffer[87 + BUFFER_WIDTH * 114] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 114] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 114] = TRANS_COLOR; // color0) + gpBuffer[72 + BUFFER_WIDTH * 115] = 0; // was tp + gpBuffer[73 + BUFFER_WIDTH * 115] = 0; // was tp + gpBuffer[74 + BUFFER_WIDTH * 115] = 0; // was tp + gpBuffer[75 + BUFFER_WIDTH * 115] = 0; // was tp + gpBuffer[76 + BUFFER_WIDTH * 115] = 0; // was tp + gpBuffer[77 + BUFFER_WIDTH * 115] = 0; // was color172) + gpBuffer[89 + BUFFER_WIDTH * 115] = TRANS_COLOR; // color0) + gpBuffer[60 + BUFFER_WIDTH * 116] = 0; // was tp + gpBuffer[61 + BUFFER_WIDTH * 116] = 0; // was tp + gpBuffer[62 + BUFFER_WIDTH * 116] = 0; // was tp + gpBuffer[71 + BUFFER_WIDTH * 116] = 0; // was tp + gpBuffer[72 + BUFFER_WIDTH * 116] = 0; // was tp + gpBuffer[73 + BUFFER_WIDTH * 116] = 0; // was tp + gpBuffer[74 + BUFFER_WIDTH * 116] = 0; // was tp + gpBuffer[75 + BUFFER_WIDTH * 116] = 0; // was tp + gpBuffer[76 + BUFFER_WIDTH * 116] = 0; // was color172) + gpBuffer[89 + BUFFER_WIDTH * 116] = TRANS_COLOR; // color0) + gpBuffer[69 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[70 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[71 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[72 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[73 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[74 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[75 + BUFFER_WIDTH * 117] = TRANS_COLOR; // color0) + gpBuffer[80 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[81 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[82 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[83 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[84 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[85 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[67 + BUFFER_WIDTH * 118] = 0; // was tp + gpBuffer[68 + BUFFER_WIDTH * 118] = 0; // was tp + gpBuffer[69 + BUFFER_WIDTH * 118] = 0; // was tp + gpBuffer[70 + BUFFER_WIDTH * 118] = 0; // was tp + gpBuffer[71 + BUFFER_WIDTH * 118] = 0; // was tp + gpBuffer[75 + BUFFER_WIDTH * 118] = TRANS_COLOR; // color0) + gpBuffer[76 + BUFFER_WIDTH * 118] = TRANS_COLOR; // color0) + gpBuffer[77 + BUFFER_WIDTH * 118] = TRANS_COLOR; // color0) + gpBuffer[84 + BUFFER_WIDTH * 118] = 0; // was tp + gpBuffer[85 + BUFFER_WIDTH * 118] = 0; // was tp + gpBuffer[56 + BUFFER_WIDTH * 120] = 0; // was tp + gpBuffer[85 + BUFFER_WIDTH * 120] = TRANS_COLOR; // color223) + } + if (i == 5) { // 54 + gpBuffer[74 + BUFFER_WIDTH * 94] = 203; // was tp + gpBuffer[73 + BUFFER_WIDTH * 95] = 237; // was tp + gpBuffer[74 + BUFFER_WIDTH * 95] = 236; // was tp + gpBuffer[75 + BUFFER_WIDTH * 95] = 173; // was tp + gpBuffer[76 + BUFFER_WIDTH * 95] = 172; // was tp + gpBuffer[77 + BUFFER_WIDTH * 95] = 203; // was tp + gpBuffer[76 + BUFFER_WIDTH * 96] = 174; // was tp + gpBuffer[77 + BUFFER_WIDTH * 96] = 173; // was tp + gpBuffer[78 + BUFFER_WIDTH * 96] = 203; // was tp + gpBuffer[74 + BUFFER_WIDTH * 97] = 172; // was color235) + gpBuffer[75 + BUFFER_WIDTH * 97] = 171; // was tp + gpBuffer[75 + BUFFER_WIDTH * 98] = 172; // was tp + gpBuffer[76 + BUFFER_WIDTH * 98] = 171; // was tp + gpBuffer[73 + BUFFER_WIDTH * 99] = 237; // was color0) + gpBuffer[75 + BUFFER_WIDTH * 99] = 171; // was tp + gpBuffer[76 + BUFFER_WIDTH * 99] = 203; // was tp + gpBuffer[77 + BUFFER_WIDTH * 99] = 203; // was tp + // gpBuffer[78 + BUFFER_WIDTH * 99] = 171; // was color174) + gpBuffer[73 + BUFFER_WIDTH * 100] = 237; // was tp + gpBuffer[74 + BUFFER_WIDTH * 100] = 237; // was tp + gpBuffer[75 + BUFFER_WIDTH * 100] = 237; // was tp + gpBuffer[76 + BUFFER_WIDTH * 100] = 172; // was tp + gpBuffer[77 + BUFFER_WIDTH * 100] = 171; // was tp + gpBuffer[73 + BUFFER_WIDTH * 101] = 237; // was tp + gpBuffer[74 + BUFFER_WIDTH * 101] = 237; // was tp + gpBuffer[75 + BUFFER_WIDTH * 101] = 237; // was tp + gpBuffer[73 + BUFFER_WIDTH * 102] = 237; // was tp + gpBuffer[74 + BUFFER_WIDTH * 102] = 220; // was tp + gpBuffer[92 + BUFFER_WIDTH * 102] = TRANS_COLOR; // color0) + gpBuffer[73 + BUFFER_WIDTH * 103] = 237; // was tp + gpBuffer[74 + BUFFER_WIDTH * 103] = 220; // was tp + gpBuffer[75 + BUFFER_WIDTH * 103] = 172; // was tp + gpBuffer[87 + BUFFER_WIDTH * 103] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 103] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 103] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 103] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 103] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 103] = TRANS_COLOR; // color0) + gpBuffer[73 + BUFFER_WIDTH * 104] = 220; // was tp + gpBuffer[74 + BUFFER_WIDTH * 104] = 235; // was tp + gpBuffer[85 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[94 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[73 + BUFFER_WIDTH * 105] = 236; // was tp + gpBuffer[74 + BUFFER_WIDTH * 105] = 235; // was tp + gpBuffer[75 + BUFFER_WIDTH * 105] = 172; // was tp + gpBuffer[86 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[94 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[72 + BUFFER_WIDTH * 106] = 236; // was color191) + gpBuffer[73 + BUFFER_WIDTH * 106] = 236; // was tp + gpBuffer[87 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[94 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[94 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[94 + BUFFER_WIDTH * 108] = TRANS_COLOR; // color0) + gpBuffer[69 + BUFFER_WIDTH * 110] = 236; // was tp + gpBuffer[70 + BUFFER_WIDTH * 110] = 237; // was tp + gpBuffer[72 + BUFFER_WIDTH * 110] = 235; // was tp + gpBuffer[87 + BUFFER_WIDTH * 110] = TRANS_COLOR; // color188) + gpBuffer[70 + BUFFER_WIDTH * 111] = 237; // was tp + gpBuffer[71 + BUFFER_WIDTH * 111] = 236; // was tp + gpBuffer[72 + BUFFER_WIDTH * 111] = 236; // was tp + gpBuffer[73 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[74 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[75 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[76 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[77 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[78 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[79 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[80 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[81 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[82 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[83 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[68 + BUFFER_WIDTH * 112] = 236; // was tp + gpBuffer[73 + BUFFER_WIDTH * 112] = 236; // was color0) + gpBuffer[82 + BUFFER_WIDTH * 112] = 0; // was tp + gpBuffer[83 + BUFFER_WIDTH * 112] = 0; // was tp + gpBuffer[84 + BUFFER_WIDTH * 112] = 0; // was tp + gpBuffer[85 + BUFFER_WIDTH * 112] = 0; // was tp + gpBuffer[86 + BUFFER_WIDTH * 112] = 0; // was tp + gpBuffer[87 + BUFFER_WIDTH * 112] = 0; // was tp + gpBuffer[69 + BUFFER_WIDTH * 113] = 237; // was tp + gpBuffer[70 + BUFFER_WIDTH * 113] = 237; // was tp + gpBuffer[72 + BUFFER_WIDTH * 113] = 236; // was tp + gpBuffer[73 + BUFFER_WIDTH * 113] = 237; // was tp + gpBuffer[74 + BUFFER_WIDTH * 113] = 236; // was tp + gpBuffer[75 + BUFFER_WIDTH * 113] = 236; // was color0) + gpBuffer[77 + BUFFER_WIDTH * 113] = 236; // was color0) + gpBuffer[89 + BUFFER_WIDTH * 113] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 113] = TRANS_COLOR; // color0) + gpBuffer[69 + BUFFER_WIDTH * 114] = 236; // was tp + gpBuffer[74 + BUFFER_WIDTH * 114] = 237; // was tp + gpBuffer[75 + BUFFER_WIDTH * 114] = 236; // was tp + gpBuffer[89 + BUFFER_WIDTH * 114] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 114] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 114] = TRANS_COLOR; // color0) + gpBuffer[73 + BUFFER_WIDTH * 115] = 236; // was tp + gpBuffer[88 + BUFFER_WIDTH * 115] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 115] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 115] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 115] = TRANS_COLOR; // color0) + gpBuffer[81 + BUFFER_WIDTH * 116] = 0; // was tp + gpBuffer[82 + BUFFER_WIDTH * 116] = 0; // was tp + gpBuffer[83 + BUFFER_WIDTH * 116] = 0; // was tp + gpBuffer[84 + BUFFER_WIDTH * 116] = 0; // was tp + gpBuffer[90 + BUFFER_WIDTH * 117] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 118] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 118] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 118] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 118] = TRANS_COLOR; // color0) + gpBuffer[60 + BUFFER_WIDTH * 119] = 0; // was tp + gpBuffer[57 + BUFFER_WIDTH * 120] = 0; // was tp + gpBuffer[58 + BUFFER_WIDTH * 120] = 0; // was tp + } + if (i == 6) { // 55 + gpBuffer[70 + BUFFER_WIDTH * 90] = 173; // was color237) + gpBuffer[71 + BUFFER_WIDTH * 91] = 235; // was color237) + gpBuffer[72 + BUFFER_WIDTH * 91] = 235; // was tp + gpBuffer[73 + BUFFER_WIDTH * 92] = 235; // was tp + gpBuffer[71 + BUFFER_WIDTH * 93] = 0; // was tp + gpBuffer[72 + BUFFER_WIDTH * 93] = 0; // was tp + gpBuffer[73 + BUFFER_WIDTH * 93] = 173; // was tp + gpBuffer[74 + BUFFER_WIDTH * 93] = 173; // was tp + gpBuffer[72 + BUFFER_WIDTH * 94] = 173; // was tp + gpBuffer[73 + BUFFER_WIDTH * 94] = 173; // was tp + gpBuffer[74 + BUFFER_WIDTH * 94] = 0; // was tp + gpBuffer[75 + BUFFER_WIDTH * 94] = 173; // was tp + gpBuffer[72 + BUFFER_WIDTH * 95] = 221; // was tp + gpBuffer[73 + BUFFER_WIDTH * 95] = 173; // was tp + gpBuffer[74 + BUFFER_WIDTH * 95] = 173; // was tp + gpBuffer[75 + BUFFER_WIDTH * 95] = 203; // was tp + gpBuffer[76 + BUFFER_WIDTH * 95] = 171; // was tp + gpBuffer[77 + BUFFER_WIDTH * 95] = 203; // was tp + gpBuffer[78 + BUFFER_WIDTH * 95] = 252; // was tp + gpBuffer[73 + BUFFER_WIDTH * 96] = 173; // was tp + gpBuffer[74 + BUFFER_WIDTH * 96] = 203; // was tp + gpBuffer[75 + BUFFER_WIDTH * 96] = 171; // was tp + gpBuffer[76 + BUFFER_WIDTH * 96] = 203; // was tp + gpBuffer[77 + BUFFER_WIDTH * 96] = 203; // was tp + gpBuffer[78 + BUFFER_WIDTH * 96] = 171; // was tp + gpBuffer[79 + BUFFER_WIDTH * 96] = 171; // was tp + gpBuffer[80 + BUFFER_WIDTH * 96] = 171; // was tp + gpBuffer[81 + BUFFER_WIDTH * 96] = 171; // was tp + gpBuffer[74 + BUFFER_WIDTH * 97] = 237; // was tp + gpBuffer[75 + BUFFER_WIDTH * 97] = 203; // was tp + gpBuffer[76 + BUFFER_WIDTH * 97] = 171; // was tp + gpBuffer[77 + BUFFER_WIDTH * 97] = 171; // was tp + gpBuffer[78 + BUFFER_WIDTH * 97] = 171; // was tp + gpBuffer[79 + BUFFER_WIDTH * 97] = 171; // was tp + gpBuffer[80 + BUFFER_WIDTH * 97] = 203; // was tp + gpBuffer[74 + BUFFER_WIDTH * 98] = 0; // was tp + gpBuffer[75 + BUFFER_WIDTH * 98] = 237; // was tp + gpBuffer[76 + BUFFER_WIDTH * 98] = 171; // was tp + gpBuffer[77 + BUFFER_WIDTH * 98] = 203; // was tp + gpBuffer[78 + BUFFER_WIDTH * 98] = 203; // was tp + gpBuffer[79 + BUFFER_WIDTH * 98] = 203; // was tp + gpBuffer[75 + BUFFER_WIDTH * 99] = 0; // was tp + gpBuffer[76 + BUFFER_WIDTH * 99] = 0; // was tp + gpBuffer[77 + BUFFER_WIDTH * 99] = 171; // was tp + gpBuffer[78 + BUFFER_WIDTH * 99] = 171; // was tp + gpBuffer[79 + BUFFER_WIDTH * 99] = 203; // was tp + gpBuffer[77 + BUFFER_WIDTH * 100] = 0; // was tp + gpBuffer[78 + BUFFER_WIDTH * 100] = 171; // was tp + gpBuffer[77 + BUFFER_WIDTH * 101] = 237; // was tp + gpBuffer[93 + BUFFER_WIDTH * 102] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 103] = TRANS_COLOR; // color0) + gpBuffer[70 + BUFFER_WIDTH * 104] = 237; // was tp + gpBuffer[71 + BUFFER_WIDTH * 104] = 237; // was tp + gpBuffer[72 + BUFFER_WIDTH * 104] = 236; // was tp + gpBuffer[84 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[69 + BUFFER_WIDTH * 105] = 237; // was tp + gpBuffer[70 + BUFFER_WIDTH * 105] = 237; // was tp + gpBuffer[83 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[84 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[68 + BUFFER_WIDTH * 106] = 237; // was tp + gpBuffer[69 + BUFFER_WIDTH * 106] = 236; // was tp + gpBuffer[83 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[84 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 106] = TRANS_COLOR; // color0) + gpBuffer[68 + BUFFER_WIDTH * 107] = 236; // was tp + gpBuffer[83 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[84 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color191) + gpBuffer[93 + BUFFER_WIDTH * 107] = TRANS_COLOR; // color0) + gpBuffer[61 + BUFFER_WIDTH * 108] = 236; // was tp + gpBuffer[62 + BUFFER_WIDTH * 108] = 236; // was tp + gpBuffer[67 + BUFFER_WIDTH * 108] = 237; // was tp + gpBuffer[80 + BUFFER_WIDTH * 108] = 0; // was tp + gpBuffer[81 + BUFFER_WIDTH * 108] = 0; // was tp + gpBuffer[82 + BUFFER_WIDTH * 108] = 0; // was tp + gpBuffer[59 + BUFFER_WIDTH * 109] = 236; // was tp + gpBuffer[68 + BUFFER_WIDTH * 109] = 237; // was tp + gpBuffer[69 + BUFFER_WIDTH * 109] = 236; // was tp + gpBuffer[72 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[73 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[74 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[75 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[76 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[77 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[78 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[79 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[80 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[81 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[82 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[83 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[71 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[72 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[73 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[74 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[75 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[76 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[77 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[78 + BUFFER_WIDTH * 110] = 0; // was color171) + gpBuffer[79 + BUFFER_WIDTH * 110] = 0; // was color188) + gpBuffer[80 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[81 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[82 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[83 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[84 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[88 + BUFFER_WIDTH * 110] = TRANS_COLOR; // color207) + gpBuffer[77 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[78 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[79 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[80 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[81 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[82 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[83 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[84 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[85 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[86 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[88 + BUFFER_WIDTH * 112] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 112] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 112] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 112] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 112] = TRANS_COLOR; // color0) + gpBuffer[76 + BUFFER_WIDTH * 113] = 237; // was tp + gpBuffer[88 + BUFFER_WIDTH * 113] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 113] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 113] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 113] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 113] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 113] = TRANS_COLOR; // color0) + gpBuffer[75 + BUFFER_WIDTH * 114] = 237; // was tp + gpBuffer[90 + BUFFER_WIDTH * 114] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 114] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 114] = TRANS_COLOR; // color0) + gpBuffer[93 + BUFFER_WIDTH * 114] = TRANS_COLOR; // color0) + gpBuffer[66 + BUFFER_WIDTH * 115] = 237; // was tp + gpBuffer[67 + BUFFER_WIDTH * 115] = 237; // was tp + gpBuffer[83 + BUFFER_WIDTH * 115] = 0; // was tp + gpBuffer[84 + BUFFER_WIDTH * 115] = 0; // was tp + gpBuffer[85 + BUFFER_WIDTH * 115] = 0; // was tp + gpBuffer[86 + BUFFER_WIDTH * 115] = 0; // was tp + gpBuffer[87 + BUFFER_WIDTH * 115] = 0; // was tp + gpBuffer[88 + BUFFER_WIDTH * 115] = 0; // was tp + gpBuffer[64 + BUFFER_WIDTH * 116] = 237; // was tp + gpBuffer[83 + BUFFER_WIDTH * 116] = 0; // was tp + gpBuffer[84 + BUFFER_WIDTH * 116] = 0; // was tp + gpBuffer[85 + BUFFER_WIDTH * 116] = 0; // was tp + gpBuffer[86 + BUFFER_WIDTH * 116] = 0; // was tp + gpBuffer[87 + BUFFER_WIDTH * 116] = 0; // was tp + gpBuffer[73 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[74 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[75 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[76 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[77 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[78 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[80 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[81 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[82 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[83 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[84 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[85 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[86 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[87 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[64 + BUFFER_WIDTH * 118] = 237; // was tp + gpBuffer[84 + BUFFER_WIDTH * 118] = 0; // was tp + gpBuffer[85 + BUFFER_WIDTH * 118] = 0; // was tp + gpBuffer[86 + BUFFER_WIDTH * 118] = 0; // was tp + } + if (i == 7) { // 56 + gpBuffer[90 + BUFFER_WIDTH * 102] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 102] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 102] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 103] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 103] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 103] = TRANS_COLOR; // color0) + gpBuffer[90 + BUFFER_WIDTH * 103] = TRANS_COLOR; // color0) + gpBuffer[91 + BUFFER_WIDTH * 103] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 103] = TRANS_COLOR; // color0) + gpBuffer[84 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[88 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[89 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color0) + gpBuffer[92 + BUFFER_WIDTH * 104] = TRANS_COLOR; // color191) + gpBuffer[83 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[84 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[85 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[86 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[87 + BUFFER_WIDTH * 105] = TRANS_COLOR; // color0) + gpBuffer[82 + BUFFER_WIDTH * 107] = 0; // was tp + gpBuffer[83 + BUFFER_WIDTH * 107] = 0; // was tp + gpBuffer[78 + BUFFER_WIDTH * 108] = 0; // was tp + gpBuffer[79 + BUFFER_WIDTH * 108] = 0; // was tp + gpBuffer[80 + BUFFER_WIDTH * 108] = 0; // was tp + gpBuffer[81 + BUFFER_WIDTH * 108] = 0; // was tp + gpBuffer[82 + BUFFER_WIDTH * 108] = 0; // was tp + gpBuffer[83 + BUFFER_WIDTH * 108] = 0; // was tp + gpBuffer[76 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[77 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[78 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[79 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[80 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[81 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[82 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[83 + BUFFER_WIDTH * 109] = 0; // was tp + gpBuffer[75 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[76 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[77 + BUFFER_WIDTH * 110] = 0; // was tp + gpBuffer[79 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[80 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[81 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[82 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[83 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[84 + BUFFER_WIDTH * 111] = 0; // was tp + gpBuffer[80 + BUFFER_WIDTH * 112] = 0; // was tp + gpBuffer[81 + BUFFER_WIDTH * 112] = 0; // was tp + gpBuffer[82 + BUFFER_WIDTH * 112] = 0; // was tp + gpBuffer[83 + BUFFER_WIDTH * 112] = 0; // was tp + gpBuffer[84 + BUFFER_WIDTH * 112] = 0; // was tp + gpBuffer[85 + BUFFER_WIDTH * 112] = 0; // was tp + gpBuffer[84 + BUFFER_WIDTH * 113] = 0; // was tp + gpBuffer[85 + BUFFER_WIDTH * 113] = 0; // was tp + gpBuffer[86 + BUFFER_WIDTH * 113] = 0; // was tp + gpBuffer[86 + BUFFER_WIDTH * 114] = 0; // was tp + gpBuffer[85 + BUFFER_WIDTH * 117] = 0; // was tp + gpBuffer[85 + BUFFER_WIDTH * 118] = 0; // was tp + gpBuffer[85 + BUFFER_WIDTH * 119] = 0; // was tp + gpBuffer[84 + BUFFER_WIDTH * 120] = 0; // was tp + } + } else { + Cl2Draw(0, height - 1, frameBuf, n, width); + } + + BYTE* frameSrc = &gpBuffer[0 + (height - 1) * BUFFER_WIDTH]; + + pBuf = EncodeCl2(pBuf, frameSrc, width, height, TRANS_COLOR); + hdr[n + 1] = SwapLE32((size_t)pBuf - (size_t)hdr); + } + hdr += ni + 2; + } + + *dwLen = (size_t)pBuf - (size_t)resCl2Buf; + + mem_free_dbg(cl2Buf); + return resCl2Buf; +} + static BYTE* patchFile(int index, size_t *dwLen) { BYTE* buf = LoadFileInMem(filesToPatch[index], dwLen); @@ -2696,6 +3954,19 @@ static BYTE* patchFile(int index, size_t *dwLen) { // fix object gfx file - L5Light.CEL buf = fixL5Light(buf, dwLen); } break; + case FILE_MON_FALLGW: + { + size_t stdLen; + const char* stdFileName = "Monsters\\BigFall\\Fallgn.CL2"; + BYTE* stdBuf = LoadFileInMem(stdFileName, &stdLen); + if (stdBuf == NULL) { + mem_free_dbg(buf); + app_warn("Unable to open file %s in the mpq.", stdFileName); + return NULL; + } + buf = createFallgwAnim(buf, dwLen, stdBuf); + mem_free_dbg(stdBuf); + } break; #endif // ASSET_MPL case FILE_OBJCURS_CEL: { From 35f22c1bb83792ce583a9b0a6e1c9d51b93a9126 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 12 May 2024 08:53:33 +0200 Subject: [PATCH 306/596] more compact release-notes to fit on one page --- .github/workflows/nightly.yml | 239 +++++++++++++++++++++------------- 1 file changed, 149 insertions(+), 90 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 942c5debe55..9251687a55f 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1430,97 +1430,156 @@ jobs: echo '' >> RELEASE_NOTE.md echo 'For the list of changes see [changelog](docs/CHANGELOG.md#DevilX).' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md - echo '### **Diablo**' >> RELEASE_NOTE.md - echo '_Filename_ | _Description_' >> RELEASE_NOTE.md - echo '------------ | -------------' >> RELEASE_NOTE.md - echo '[diablo-nightly-android.apk](../../releases/download/devilx-nightly/diablo-nightly-android.apk) | Diablo package for `Android`' >> RELEASE_NOTE.md - echo '[diablo-nightly-lepus.opk](../../releases/download/devilx-nightly/diablo-nightly-lepus.opk) | Diablo package for `Lepus`' >> RELEASE_NOTE.md - echo '[diablo-nightly-retrofw.opk](../../releases/download/devilx-nightly/diablo-nightly-retrofw.opk) | Diablo package for `RetroFW`' >> RELEASE_NOTE.md - echo '[diablo-nightly-rg350.opk](../../releases/download/devilx-nightly/diablo-nightly-rg350.opk) | Diablo package for `RG350`' >> RELEASE_NOTE.md - echo '[diablo-nightly-ps4.pkg](../../releases/download/devilx-nightly/diablo-nightly-ps4.pkg) | Diablo package for `PS4`' >> RELEASE_NOTE.md - echo '[diablo-nightly-aarch64.tar.xz](../../releases/download/devilx-nightly/diablo-nightly-aarch64.tar.xz) | Diablo package for `aarch64`' >> RELEASE_NOTE.md - echo '[diablo-nightly-mac.dmg](../../releases/download/devilx-nightly/diablo-nightly-mac.dmg) | Diablo package for `Mac`' >> RELEASE_NOTE.md - echo '[diablo-nightly-ios.ipa](../../releases/download/devilx-nightly/diablo-nightly-ios.ipa) | Diablo package for `iOS`' >> RELEASE_NOTE.md - echo '[diablo-nightly-vita.vpk](../../releases/download/devilx-nightly/diablo-nightly-vita.vpk) | Diablo package for `Vita`' >> RELEASE_NOTE.md - echo '[diablo-nightly-3ds.3dsx](../../releases/download/devilx-nightly/diablo-nightly-3ds.3dsx) | Diablo package for `Nintendo 3DS` (3dsx)' >> RELEASE_NOTE.md - echo '[diablo-nightly-3ds.cia](../../releases/download/devilx-nightly/diablo-nightly-3ds.cia) | Diablo package for `Nintendo 3DS` (cia)' >> RELEASE_NOTE.md - echo '[diablo-nightly-switch.nro](../../releases/download/devilx-nightly/diablo-nightly-switch.nro) | Diablo package for `Nintendo Switch`' >> RELEASE_NOTE.md - echo '[diablo-nightly-amiga](../../releases/download/devilx-nightly/diablo-nightly-amiga) | Diablo package for `Amiga`' >> RELEASE_NOTE.md - echo '[diablo-nightly-x64.zip](../../releases/download/devilx-nightly/diablo-nightly-x64.zip) | Diablo build for `Windows x64` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md - echo '[diablo-nightly-mingw-x64.zip](../../releases/download/devilx-nightly/diablo-nightly-mingw-x64.zip) | Diablo build for `Windows x64`' >> RELEASE_NOTE.md - echo '[diablo-nightly-x86.zip](../../releases/download/devilx-nightly/diablo-nightly-x86.zip) | Diablo build for `Windows x86` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md - echo '[diablo-nightly-mingw-x86.zip](../../releases/download/devilx-nightly/diablo-nightly-mingw-x86.zip) | Diablo build for `Windows x86`' >> RELEASE_NOTE.md - echo '[diablo-nightly-mingw-w9x.zip](../../releases/download/devilx-nightly/diablo-nightly-mingw-w9x.zip) | Diablo build for `Windows 98`' >> RELEASE_NOTE.md + echo '### **Packages**' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo ' ' >> RELEASE_NOTE.md + echo '
DiabloEnvironmentHellfire
BasePatchedBasePatched
android.apkandroidp.apkAndroidandroid.apkandroidp.apk
lepus.opklepusp.opkLepuslepus.opklepusp.opk
retrofw.opkretrofwp.opkRetroFWretrofw.opkretrofwp.opk
rg350.opkrg350p.opkRG350rg350.opkrg350p.opk
ps4.pkgps4p.pkgPS4ps4.pkgps4p.pkg
aarch64.tar.xzaarch64p.tar.xzaarch64aarch64.tar.xzaarch64p.tar.xz
mac.dmgmacp.dmgMacmac.dmgmacp.dmg
ios.ipaiosp.ipaiOSios.ipaiosp.ipa
vita.vpkvitap.vpkVitavita.vpkvitap.vpk
3ds.3dsx3dsp.3dsxNintendo 3DS3ds.3dsx3dsp.3dsx
3ds.cia3dsp.cia3ds.cia3dsp.cia
switch.nroswitchp.nroNintendo Switchswitch.nroswitchp.nro
amigaamigapAmigaamigaamigap
x64.zip 1Windows x64x64.zip 1
mingw-x64.zipmingw-x64.zip
x86.zip 1Windows x86x86.zip 1
mingw-x86.zipmingw-x86.zip
mini-x86.zip 2srv-x86.zip 3
mingw-w9x.zipWindows 98mingw-w9x.zip
' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md - echo '### **Diablo: Hellfire**' >> RELEASE_NOTE.md - echo '_Filename_ | _Description_' >> RELEASE_NOTE.md - echo '------------ | -------------' >> RELEASE_NOTE.md - echo '[hellfire-nightly-android.apk](../../releases/download/devilx-nightly/hellfire-nightly-android.apk) | Hellfire package for `Android`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-lepus.opk](../../releases/download/devilx-nightly/hellfire-nightly-lepus.opk) | Hellfire package for `Lepus`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-retrofw.opk](../../releases/download/devilx-nightly/hellfire-nightly-retrofw.opk) | Hellfire package for `RetroFW`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-rg350.opk](../../releases/download/devilx-nightly/hellfire-nightly-rg350.opk) | Hellfire package for `RG350`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-ps4.pkg](../../releases/download/devilx-nightly/hellfire-nightly-ps4.pkg) | Hellfire package for `PS4`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-aarch64.tar.xz](../../releases/download/devilx-nightly/hellfire-nightly-aarch64.tar.xz) | Hellfire package for `aarch64`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-mac.dmg](../../releases/download/devilx-nightly/hellfire-nightly-mac.dmg) | Hellfire package for `Mac`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-ios.ipa](../../releases/download/devilx-nightly/hellfire-nightly-ios.ipa) | Hellfire package for `iOS`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-vita.vpk](../../releases/download/devilx-nightly/hellfire-nightly-vita.vpk) | Hellfire package for `Vita`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-3ds.3dsx](../../releases/download/devilx-nightly/hellfire-nightly-3ds.3dsx) | Hellfire package for `Nintendo 3DS` (3dsx)' >> RELEASE_NOTE.md - echo '[hellfire-nightly-3ds.cia](../../releases/download/devilx-nightly/hellfire-nightly-3ds.cia) | Hellfire package for `Nintendo 3DS` (cia)' >> RELEASE_NOTE.md - echo '[hellfire-nightly-switch.nro](../../releases/download/devilx-nightly/hellfire-nightly-switch.nro) | Hellfire package for `Nintendo Switch`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-amiga](../../releases/download/devilx-nightly/hellfire-nightly-amiga) | Hellfire package for `Amiga`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-x64.zip](../../releases/download/devilx-nightly/hellfire-nightly-x64.zip) | Hellfire build for `Windows x64` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md - echo '[hellfire-nightly-mingw-x64.zip](../../releases/download/devilx-nightly/hellfire-nightly-mingw-x64.zip) | Hellfire build for `Windows x64`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-x86.zip](../../releases/download/devilx-nightly/hellfire-nightly-x86.zip) | Hellfire build for `Windows x86` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md - echo '[hellfire-nightly-mingw-x86.zip](../../releases/download/devilx-nightly/hellfire-nightly-mingw-x86.zip) | Hellfire build for `Windows x86`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-mingw-w9x.zip](../../releases/download/devilx-nightly/hellfire-nightly-mingw-w9x.zip) | Hellfire build for `Windows 98`' >> RELEASE_NOTE.md - echo '[hellmini-nightly-x86.zip](../../releases/download/devilx-nightly/hellmini-nightly-x86.zip) | Minimal Hellfire build for `Windows x86`
- no internet, controller, sound or widescreen support' >> RELEASE_NOTE.md - echo '[hellsrv-nightly-x86.zip](../../releases/download/devilx-nightly/hellsrv-nightly-x86.zip) | Minimal Hellfire server for `Windows x86`
- no controller, sound or widescreen support
- only server functionality' >> RELEASE_NOTE.md - echo '' >> RELEASE_NOTE.md - echo '### **Diablo** using patched assets' >> RELEASE_NOTE.md - echo '_Filename_ | _Description_' >> RELEASE_NOTE.md - echo '------------ | -------------' >> RELEASE_NOTE.md - echo '[diablo-nightly-androidp.apk](../../releases/download/devilx-nightly/diablo-nightly-androidp.apk) | Diablo package for `Android`' >> RELEASE_NOTE.md - echo '[diablo-nightly-lepusp.opk](../../releases/download/devilx-nightly/diablo-nightly-lepusp.opk) | Diablo package for `Lepus`' >> RELEASE_NOTE.md - echo '[diablo-nightly-retrofwp.opk](../../releases/download/devilx-nightly/diablo-nightly-retrofwp.opk) | Diablo package for `RetroFW`' >> RELEASE_NOTE.md - echo '[diablo-nightly-rg350p.opk](../../releases/download/devilx-nightly/diablo-nightly-rg350p.opk) | Diablo package for `RG350`' >> RELEASE_NOTE.md - echo '[diablo-nightly-ps4p.pkg](../../releases/download/devilx-nightly/diablo-nightly-ps4p.pkg) | Diablo package for `PS4`' >> RELEASE_NOTE.md - echo '[diablo-nightly-aarch64p.tar.xz](../../releases/download/devilx-nightly/diablo-nightly-aarch64p.tar.xz) | Diablo package for `aarch64`' >> RELEASE_NOTE.md - echo '[diablo-nightly-macp.dmg](../../releases/download/devilx-nightly/diablo-nightly-macp.dmg) | Diablo package for `Mac`' >> RELEASE_NOTE.md - echo '[diablo-nightly-iosp.ipa](../../releases/download/devilx-nightly/diablo-nightly-iosp.ipa) | Diablo package for `iOS`' >> RELEASE_NOTE.md - echo '[diablo-nightly-vitap.vpk](../../releases/download/devilx-nightly/diablo-nightly-vitap.vpk) | Diablo package for `Vita`' >> RELEASE_NOTE.md - echo '[diablo-nightly-3dsp.3dsx](../../releases/download/devilx-nightly/diablo-nightly-3dsp.3dsx) | Diablo package for `Nintendo 3DS` (3dsx)' >> RELEASE_NOTE.md - echo '[diablo-nightly-3dsp.cia](../../releases/download/devilx-nightly/diablo-nightly-3dsp.cia) | Diablo package for `Nintendo 3DS` (cia)' >> RELEASE_NOTE.md - echo '[diablo-nightly-switchp.nro](../../releases/download/devilx-nightly/diablo-nightly-switchp.nro) | Diablo package for `Nintendo Switch`' >> RELEASE_NOTE.md - echo '[diablo-nightly-amigap](../../releases/download/devilx-nightly/diablo-nightly-amigap) | Diablo package for `Amiga`' >> RELEASE_NOTE.md - echo '[diablo-nightly-x64.zip](../../releases/download/devilx-nightly/diablo-nightly-x64.zip) | Diablo build for `Windows x64` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md - echo '[diablo-nightly-mingw-x64.zip](../../releases/download/devilx-nightly/diablo-nightly-mingw-x64.zip) | Diablo build for `Windows x64`' >> RELEASE_NOTE.md - echo '[diablo-nightly-x86.zip](../../releases/download/devilx-nightly/diablo-nightly-x86.zip) | Diablo build for `Windows x86` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md - echo '[diablo-nightly-mingw-x86.zip](../../releases/download/devilx-nightly/diablo-nightly-mingw-x86.zip) | Diablo build for `Windows x86`' >> RELEASE_NOTE.md - echo '[diablo-nightly-mingw-w9x.zip](../../releases/download/devilx-nightly/diablo-nightly-mingw-w9x.zip) | Diablo build for `Windows 98`' >> RELEASE_NOTE.md - echo '' >> RELEASE_NOTE.md - echo '### **Diablo: Hellfire** using patched assets' >> RELEASE_NOTE.md - echo '_Filename_ | _Description_' >> RELEASE_NOTE.md - echo '------------ | -------------' >> RELEASE_NOTE.md - echo '[hellfire-nightly-androidp.apk](../../releases/download/devilx-nightly/hellfire-nightly-androidp.apk) | Hellfire package for `Android`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-lepusp.opk](../../releases/download/devilx-nightly/hellfire-nightly-lepusp.opk) | Hellfire package for `Lepus`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-retrofwp.opk](../../releases/download/devilx-nightly/hellfire-nightly-retrofwp.opk) | Hellfire package for `RetroFW`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-rg350p.opk](../../releases/download/devilx-nightly/hellfire-nightly-rg350p.opk) | Hellfire package for `RG350`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-ps4p.pkg](../../releases/download/devilx-nightly/hellfire-nightly-ps4p.pkg) | Hellfire package for `PS4`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-aarch64p.tar.xz](../../releases/download/devilx-nightly/hellfire-nightly-aarch64p.tar.xz) | Hellfire package for `aarch64`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-macp.dmg](../../releases/download/devilx-nightly/hellfire-nightly-macp.dmg) | Hellfire package for `Mac`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-iosp.ipa](../../releases/download/devilx-nightly/hellfire-nightly-iosp.ipa) | Hellfire package for `iOS`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-vitap.vpk](../../releases/download/devilx-nightly/hellfire-nightly-vitap.vpk) | Hellfire package for `Vita`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-3dsp.3dsx](../../releases/download/devilx-nightly/hellfire-nightly-3dsp.3dsx) | Hellfire package for `Nintendo 3DS` (3dsx)' >> RELEASE_NOTE.md - echo '[hellfire-nightly-3dsp.cia](../../releases/download/devilx-nightly/hellfire-nightly-3dsp.cia) | Hellfire package for `Nintendo 3DS` (cia)' >> RELEASE_NOTE.md - echo '[hellfire-nightly-switchp.nro](../../releases/download/devilx-nightly/hellfire-nightly-switchp.nro) | Hellfire package for `Nintendo Switch`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-amigap](../../releases/download/devilx-nightly/hellfire-nightly-amigap) | Hellfire package for `Amiga`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-x64.zip](../../releases/download/devilx-nightly/hellfire-nightly-x64.zip) | Hellfire build for `Windows x64` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md - echo '[hellfire-nightly-mingw-x64.zip](../../releases/download/devilx-nightly/hellfire-nightly-mingw-x64.zip) | Hellfire build for `Windows x64`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-x86.zip](../../releases/download/devilx-nightly/hellfire-nightly-x86.zip) | Hellfire build for `Windows x86` (requires [VC++ Runtime](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist))' >> RELEASE_NOTE.md - echo '[hellfire-nightly-mingw-x86.zip](../../releases/download/devilx-nightly/hellfire-nightly-mingw-x86.zip) | Hellfire build for `Windows x86`' >> RELEASE_NOTE.md - echo '[hellfire-nightly-mingw-w9x.zip](../../releases/download/devilx-nightly/hellfire-nightly-mingw-w9x.zip) | Hellfire build for `Windows 98`' >> RELEASE_NOTE.md - echo '[hellmini-nightly-x86.zip](../../releases/download/devilx-nightly/hellmini-nightly-x86.zip) | Minimal Hellfire build for `Windows x86`
- no internet, controller, sound or widescreen support' >> RELEASE_NOTE.md - echo '[hellsrv-nightly-x86.zip](../../releases/download/devilx-nightly/hellsrv-nightly-x86.zip) | Minimal Hellfire server for `Windows x86`
- no controller, sound or widescreen support
- only server functionality' >> RELEASE_NOTE.md + echo '
' >> RELEASE_NOTE.md + echo '
    ' >> RELEASE_NOTE.md + echo '
  1. ' >> RELEASE_NOTE.md + echo '

    requires VC++ Runtime

    ' >> RELEASE_NOTE.md + echo '
  2. ' >> RELEASE_NOTE.md + echo '
  3. ' >> RELEASE_NOTE.md + echo '

    minimal build - no internet, controller or sound support

    ' >> RELEASE_NOTE.md + echo '
  4. ' >> RELEASE_NOTE.md + echo '
  5. ' >> RELEASE_NOTE.md + echo '

    server build - no controller or sound support

    ' >> RELEASE_NOTE.md + echo '
  6. ' >> RELEASE_NOTE.md + echo '
' >> RELEASE_NOTE.md + echo '
' >> RELEASE_NOTE.md #- name: Show content of workspace # run: find $RUNNER_WORKSPACE From 33891bf4ee9dff66cb33bf571a4a76b19a7d2292 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 May 2024 07:07:51 +0200 Subject: [PATCH 307/596] Bump softprops/action-gh-release from 2.0.4 to 2.0.5 (#9) Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.0.4 to 2.0.5. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/v2.0.4...v2.0.5) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/nightly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 9251687a55f..7f906940a86 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1602,7 +1602,7 @@ jobs: shell: bash - name: Release - uses: softprops/action-gh-release@v2.0.4 + uses: softprops/action-gh-release@v2.0.5 with: tag_name: devilx-nightly body_path: ${{ github.workspace }}/RELEASE_NOTE.md From cfac4cc3e92a559c53efdf386492adae8c9cdd9f Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 14 May 2024 19:24:32 +0200 Subject: [PATCH 308/596] reduce whitespace in the release notes to overcome the limitation of github --- .github/workflows/nightly.yml | 259 +++++++++++++++------------------- 1 file changed, 113 insertions(+), 146 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 7f906940a86..be68e3ea9eb 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1431,155 +1431,122 @@ jobs: echo 'For the list of changes see [changelog](docs/CHANGELOG.md#DevilX).' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md echo '### **Packages**' >> RELEASE_NOTE.md - echo '' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo ' ' >> RELEASE_NOTE.md - echo '
DiabloEnvironmentHellfire
BasePatchedBasePatched
android.apkandroidp.apkAndroidandroid.apkandroidp.apk
lepus.opklepusp.opkLepuslepus.opklepusp.opk
retrofw.opkretrofwp.opkRetroFWretrofw.opkretrofwp.opk
rg350.opkrg350p.opkRG350rg350.opkrg350p.opk
ps4.pkgps4p.pkgPS4ps4.pkgps4p.pkg
aarch64.tar.xzaarch64p.tar.xzaarch64aarch64.tar.xzaarch64p.tar.xz
mac.dmgmacp.dmgMacmac.dmgmacp.dmg
ios.ipaiosp.ipaiOSios.ipaiosp.ipa
vita.vpkvitap.vpkVitavita.vpkvitap.vpk
3ds.3dsx3dsp.3dsxNintendo 3DS3ds.3dsx3dsp.3dsx
3ds.cia3dsp.cia3ds.cia3dsp.cia
switch.nroswitchp.nroNintendo Switchswitch.nroswitchp.nro
amigaamigapAmigaamigaamigap
x64.zip 1Windows x64x64.zip 1
mingw-x64.zipmingw-x64.zip
x86.zip 1Windows x86x86.zip 1
mingw-x86.zipmingw-x86.zip
mini-x86.zip 2srv-x86.zip 3
mingw-w9x.zipWindows 98mingw-w9x.zip
' >> RELEASE_NOTE.md - echo '' >> RELEASE_NOTE.md - echo '
' >> RELEASE_NOTE.md - echo '
    ' >> RELEASE_NOTE.md - echo '
  1. ' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '' >> RELEASE_NOTE.md + echo '
    DiabloEnvironmentHellfire
    BasePatchedBasePatched
    android.apkandroidp.apkAndroidandroid.apkandroidp.apk
    lepus.opklepusp.opkLepuslepus.opklepusp.opk
    retrofw.opkretrofwp.opkRetroFWretrofw.opkretrofwp.opk
    rg350.opkrg350p.opkRG350rg350.opkrg350p.opk
    ps4.pkgps4p.pkgPS4ps4.pkgps4p.pkg
    aarch64.tar.xzaarch64p.tar.xzaarch64aarch64.tar.xzaarch64p.tar.xz
    mac.dmgmacp.dmgMacmac.dmgmacp.dmg
    ios.ipaiosp.ipaiOSios.ipaiosp.ipa
    vita.vpkvitap.vpkVitavita.vpkvitap.vpk
    3ds.3dsx3dsp.3dsxNintendo 3DS3ds.3dsx3dsp.3dsx
    3ds.cia3dsp.cia3ds.cia3dsp.cia
    switch.nroswitchp.nroNintendo Switchswitch.nroswitchp.nro
    amigaamigapAmigaamigaamigap
    x64.zip 1Windows x64x64.zip 1
    mingw-x64.zipmingw-x64.zip
    x86.zip 1Windows x86x86.zip 1
    mingw-x86.zipmingw-x86.zip
    mini-x86.zip 2srv-x86.zip 3
    mingw-w9x.zipWindows 98mingw-w9x.zip
    ' >> RELEASE_NOTE.md + echo '
    1. ' >> RELEASE_NOTE.md echo '

      requires VC++ Runtime

      ' >> RELEASE_NOTE.md - echo '
    2. ' >> RELEASE_NOTE.md - echo '
    3. ' >> RELEASE_NOTE.md + echo '
    4. ' >> RELEASE_NOTE.md echo '

      minimal build - no internet, controller or sound support

      ' >> RELEASE_NOTE.md - echo '
    5. ' >> RELEASE_NOTE.md - echo '
    6. ' >> RELEASE_NOTE.md + echo '
    7. ' >> RELEASE_NOTE.md echo '

      server build - no controller or sound support

      ' >> RELEASE_NOTE.md - echo '
    8. ' >> RELEASE_NOTE.md - echo '
    ' >> RELEASE_NOTE.md - echo '
    ' >> RELEASE_NOTE.md + echo '
' >> RELEASE_NOTE.md #- name: Show content of workspace # run: find $RUNNER_WORKSPACE From 7e65a5cf9b0dd372dd4469611ab9e54a869bfc7b Mon Sep 17 00:00:00 2001 From: Oleksandr Kalko Date: Mon, 29 Apr 2024 13:55:05 +0300 Subject: [PATCH 309/596] General Android upgrades * Gradle to 8.7 * Android Gradle plugin to 8.3.2 Playtested to my Google Pixel 2, Android 11 --- .../app/src/main/java/org/libsdl/app/SDLActivity.java | 2 +- android-project/build.gradle | 2 +- android-project/gradle/wrapper/gradle-wrapper.properties | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java index 8e282040c4f..349771a44cc 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -61,7 +61,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh private static final String TAG = "SDL"; private static final int SDL_MAJOR_VERSION = 2; private static final int SDL_MINOR_VERSION = 31; - private static final int SDL_MICRO_VERSION = 0; + private static final int SDL_MICRO_VERSION = 2; /* // Display InputType.SOURCE/CLASS of events and devices // diff --git a/android-project/build.gradle b/android-project/build.gradle index 9a83e3e989c..64c2f760a0a 100644 --- a/android-project/build.gradle +++ b/android-project/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:8.2.2' + classpath 'com.android.tools.build:gradle:8.3.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/android-project/gradle/wrapper/gradle-wrapper.properties b/android-project/gradle/wrapper/gradle-wrapper.properties index ff4eb9e0814..47efc1051bb 100644 --- a/android-project/gradle/wrapper/gradle-wrapper.properties +++ b/android-project/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Dec 13 13:49:58 EET 2023 +#Mon Apr 29 13:42:12 EEST 2024 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME From 8ba3cdfd619447ec0d0114e4c0d9c28755a01c69 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 3 Jul 2024 07:33:21 +0200 Subject: [PATCH 310/596] fix release notes --- .github/workflows/nightly.yml | 128 +++++++++++++++++----------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index be68e3ea9eb..26b07512c10 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1441,104 +1441,104 @@ jobs: echo 'Base' >> RELEASE_NOTE.md echo 'Patched' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md - echo 'android.apk' >> RELEASE_NOTE.md - echo 'androidp.apk' >> RELEASE_NOTE.md + echo 'android.apk' >> RELEASE_NOTE.md + echo 'androidp.apk' >> RELEASE_NOTE.md echo 'Android' >> RELEASE_NOTE.md - echo 'android.apk' >> RELEASE_NOTE.md - echo 'androidp.apk' >> RELEASE_NOTE.md + echo 'android.apk' >> RELEASE_NOTE.md + echo 'androidp.apk' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md - echo 'lepus.opk' >> RELEASE_NOTE.md - echo 'lepusp.opk' >> RELEASE_NOTE.md + echo 'lepus.opk' >> RELEASE_NOTE.md + echo 'lepusp.opk' >> RELEASE_NOTE.md echo 'Lepus' >> RELEASE_NOTE.md - echo 'lepus.opk' >> RELEASE_NOTE.md - echo 'lepusp.opk' >> RELEASE_NOTE.md + echo 'lepus.opk' >> RELEASE_NOTE.md + echo 'lepusp.opk' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md - echo 'retrofw.opk' >> RELEASE_NOTE.md - echo 'retrofwp.opk' >> RELEASE_NOTE.md + echo 'retrofw.opk' >> RELEASE_NOTE.md + echo 'retrofwp.opk' >> RELEASE_NOTE.md echo 'RetroFW' >> RELEASE_NOTE.md - echo 'retrofw.opk' >> RELEASE_NOTE.md - echo 'retrofwp.opk' >> RELEASE_NOTE.md + echo 'retrofw.opk' >> RELEASE_NOTE.md + echo 'retrofwp.opk' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md - echo 'rg350.opk' >> RELEASE_NOTE.md - echo 'rg350p.opk' >> RELEASE_NOTE.md + echo 'rg350.opk' >> RELEASE_NOTE.md + echo 'rg350p.opk' >> RELEASE_NOTE.md echo 'RG350' >> RELEASE_NOTE.md - echo 'rg350.opk' >> RELEASE_NOTE.md - echo 'rg350p.opk' >> RELEASE_NOTE.md + echo 'rg350.opk' >> RELEASE_NOTE.md + echo 'rg350p.opk' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md - echo 'ps4.pkg' >> RELEASE_NOTE.md - echo 'ps4p.pkg' >> RELEASE_NOTE.md + echo 'ps4.pkg' >> RELEASE_NOTE.md + echo 'ps4p.pkg' >> RELEASE_NOTE.md echo 'PS4' >> RELEASE_NOTE.md - echo 'ps4.pkg' >> RELEASE_NOTE.md - echo 'ps4p.pkg' >> RELEASE_NOTE.md + echo 'ps4.pkg' >> RELEASE_NOTE.md + echo 'ps4p.pkg' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md - echo 'aarch64.tar.xz' >> RELEASE_NOTE.md - echo 'aarch64p.tar.xz' >> RELEASE_NOTE.md + echo 'aarch64.tar.xz' >> RELEASE_NOTE.md + echo 'aarch64p.tar.xz' >> RELEASE_NOTE.md echo 'aarch64' >> RELEASE_NOTE.md - echo 'aarch64.tar.xz' >> RELEASE_NOTE.md - echo 'aarch64p.tar.xz' >> RELEASE_NOTE.md + echo 'aarch64.tar.xz' >> RELEASE_NOTE.md + echo 'aarch64p.tar.xz' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md - echo 'mac.dmg' >> RELEASE_NOTE.md - echo 'macp.dmg' >> RELEASE_NOTE.md + echo 'mac.dmg' >> RELEASE_NOTE.md + echo 'macp.dmg' >> RELEASE_NOTE.md echo 'Mac' >> RELEASE_NOTE.md - echo 'mac.dmg' >> RELEASE_NOTE.md - echo 'macp.dmg' >> RELEASE_NOTE.md + echo 'mac.dmg' >> RELEASE_NOTE.md + echo 'macp.dmg' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md - echo 'ios.ipa' >> RELEASE_NOTE.md - echo 'iosp.ipa' >> RELEASE_NOTE.md + echo 'ios.ipa' >> RELEASE_NOTE.md + echo 'iosp.ipa' >> RELEASE_NOTE.md echo 'iOS' >> RELEASE_NOTE.md - echo 'ios.ipa' >> RELEASE_NOTE.md - echo 'iosp.ipa' >> RELEASE_NOTE.md + echo 'ios.ipa' >> RELEASE_NOTE.md + echo 'iosp.ipa' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md - echo 'vita.vpk' >> RELEASE_NOTE.md - echo 'vitap.vpk' >> RELEASE_NOTE.md + echo 'vita.vpk' >> RELEASE_NOTE.md + echo 'vitap.vpk' >> RELEASE_NOTE.md echo 'Vita' >> RELEASE_NOTE.md - echo 'vita.vpk' >> RELEASE_NOTE.md - echo 'vitap.vpk' >> RELEASE_NOTE.md + echo 'vita.vpk' >> RELEASE_NOTE.md + echo 'vitap.vpk' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md - echo '3ds.3dsx' >> RELEASE_NOTE.md - echo '3dsp.3dsx' >> RELEASE_NOTE.md + echo '3ds.3dsx' >> RELEASE_NOTE.md + echo '3dsp.3dsx' >> RELEASE_NOTE.md echo 'Nintendo 3DS' >> RELEASE_NOTE.md - echo '3ds.3dsx' >> RELEASE_NOTE.md - echo '3dsp.3dsx' >> RELEASE_NOTE.md + echo '3ds.3dsx' >> RELEASE_NOTE.md + echo '3dsp.3dsx' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md - echo '3ds.cia' >> RELEASE_NOTE.md - echo '3dsp.cia' >> RELEASE_NOTE.md - echo '3ds.cia' >> RELEASE_NOTE.md - echo '3dsp.cia' >> RELEASE_NOTE.md + echo '3ds.cia' >> RELEASE_NOTE.md + echo '3dsp.cia' >> RELEASE_NOTE.md + echo '3ds.cia' >> RELEASE_NOTE.md + echo '3dsp.cia' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md - echo 'switch.nro' >> RELEASE_NOTE.md - echo 'switchp.nro' >> RELEASE_NOTE.md + echo 'switch.nro' >> RELEASE_NOTE.md + echo 'switchp.nro' >> RELEASE_NOTE.md echo 'Nintendo Switch' >> RELEASE_NOTE.md - echo 'switch.nro' >> RELEASE_NOTE.md - echo 'switchp.nro' >> RELEASE_NOTE.md + echo 'switch.nro' >> RELEASE_NOTE.md + echo 'switchp.nro' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md - echo 'amiga' >> RELEASE_NOTE.md - echo 'amigap' >> RELEASE_NOTE.md + echo 'amiga' >> RELEASE_NOTE.md + echo 'amigap' >> RELEASE_NOTE.md echo 'Amiga' >> RELEASE_NOTE.md - echo 'amiga' >> RELEASE_NOTE.md - echo 'amigap' >> RELEASE_NOTE.md + echo 'amiga' >> RELEASE_NOTE.md + echo 'amigap' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md - echo 'x64.zip 1' >> RELEASE_NOTE.md + echo 'x64.zip 1' >> RELEASE_NOTE.md echo 'Windows x64' >> RELEASE_NOTE.md - echo 'x64.zip 1' >> RELEASE_NOTE.md + echo 'x64.zip 1' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md - echo 'mingw-x64.zip' >> RELEASE_NOTE.md - echo 'mingw-x64.zip' >> RELEASE_NOTE.md + echo 'mingw-x64.zip' >> RELEASE_NOTE.md + echo 'mingw-x64.zip' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md - echo 'x86.zip 1' >> RELEASE_NOTE.md + echo 'x86.zip 1' >> RELEASE_NOTE.md echo 'Windows x86' >> RELEASE_NOTE.md - echo 'x86.zip 1' >> RELEASE_NOTE.md + echo 'x86.zip 1' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md - echo 'mingw-x86.zip' >> RELEASE_NOTE.md - echo 'mingw-x86.zip' >> RELEASE_NOTE.md + echo 'mingw-x86.zip' >> RELEASE_NOTE.md + echo 'mingw-x86.zip' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md - echo 'mini-x86.zip 2' >> RELEASE_NOTE.md - echo 'srv-x86.zip 3' >> RELEASE_NOTE.md + echo 'mini-x86.zip 2' >> RELEASE_NOTE.md + echo 'srv-x86.zip 3' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md - echo 'mingw-w9x.zip' >> RELEASE_NOTE.md + echo 'mingw-w9x.zip' >> RELEASE_NOTE.md echo 'Windows 98' >> RELEASE_NOTE.md - echo 'mingw-w9x.zip' >> RELEASE_NOTE.md + echo 'mingw-w9x.zip' >> RELEASE_NOTE.md echo '' >> RELEASE_NOTE.md echo '
  1. ' >> RELEASE_NOTE.md echo '

    requires VC++ Runtime

    ' >> RELEASE_NOTE.md From 6d036c6d07ac209ae6afa03146e01dcdb385d5aa Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 3 Jul 2024 11:33:41 +0200 Subject: [PATCH 311/596] fix class selector - bugfix for "add SelheroResetScreen" --- Source/DiabloUI/selhero.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/DiabloUI/selhero.cpp b/Source/DiabloUI/selhero.cpp index 809727bb838..25d81b8655d 100644 --- a/Source/DiabloUI/selhero.cpp +++ b/Source/DiabloUI/selhero.cpp @@ -141,7 +141,9 @@ static void SelheroSetStats() int baseFlags = UIS_HCENTER | UIS_VCENTER | UIS_BIG; if (heroclass < NUM_CLASSES) { - SELLIST_DIALOG_DELETE_BUTTON->m_iFlags = baseFlags | UIS_GOLD; + if (SELLIST_DIALOG_DELETE_BUTTON != NULL) { + SELLIST_DIALOG_DELETE_BUTTON->m_iFlags = baseFlags | UIS_GOLD; + } SELHERO_DIALOG_HERO_IMG->m_frame = heroclass + 1; selhero_heroFrame = heroclass + 1; @@ -151,6 +153,7 @@ static void SelheroSetStats() snprintf(textStats[3], sizeof(textStats[3]), "%d", selhero_heroInfo.hiDexterity); snprintf(textStats[4], sizeof(textStats[4]), "%d", selhero_heroInfo.hiVitality); } else { + assert(SELLIST_DIALOG_DELETE_BUTTON != NULL); SELLIST_DIALOG_DELETE_BUTTON->m_iFlags = baseFlags | UIS_SILVER | UIS_DISABLED; SELHERO_DIALOG_HERO_IMG->m_frame = 0; selhero_heroFrame = 0; From 1badd1db14cc6149d48b24e6ced44a4f5dd95b67 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 3 Jul 2024 12:19:34 +0200 Subject: [PATCH 312/596] use macos-12 runners --- .github/workflows/cmake.yml | 4 ++-- .github/workflows/nightly.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 7517450f5f8..0284aa9487c 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -1,4 +1,4 @@ -name: CMake +name: CMake # When creating a new workflow in GitHub’s action builder the default trigger is the push event. We want to extend this to push and pull request events. on: [push, pull_request] @@ -13,7 +13,7 @@ jobs: # well on Windows or Mac. You can convert this to a matrix build if you need # cross-platform coverage. # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix - runs-on: macos-11 + runs-on: macos-12 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 26b07512c10..36cd1eb1c93 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -393,7 +393,7 @@ jobs: - name: hellfire-macp cmakeargs: '-DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-macp.dmg' - runs-on: macos-11 + runs-on: macos-12 steps: - uses: actions/checkout@v4 with: @@ -441,7 +441,7 @@ jobs: - name: hellfire-iosp cmakeargs: '-DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-iosp.ipa' - runs-on: macos-11 + runs-on: macos-12 steps: - uses: actions/checkout@v4 with: From 5f089c1fbcded9cda784ea46d9d3ace509545477 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 4 Jul 2024 08:25:26 +0200 Subject: [PATCH 313/596] do not install unused packages in Nightly-MSVC --- .github/workflows/nightly.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 36cd1eb1c93..5dd4a52a3ae 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -41,28 +41,28 @@ jobs: include: # x86 builds - name: diablo-x86 - packages: 'sdl2:x86-windows libsodium:x86-windows' + #packages: 'sdl2:x86-windows libsodium:x86-windows' cmakeargs: '-A Win32 -D_WIN32_WINNT=0x0600 -DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON' artifact: 'diablo-nightly-x86.zip' - name: hellfire-x86 - packages: 'sdl2:x86-windows libsodium:x86-windows' + #packages: 'sdl2:x86-windows libsodium:x86-windows' cmakeargs: '-A Win32 -D_WIN32_WINNT=0x0600 -DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-x86.zip' - name: hellmini-x86 - packages: 'sdl2:x86-windows' + #packages: 'sdl2:x86-windows' cmakeargs: '-A Win32 -D_WIN32_WINNT=0x0501 -DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON -DHAS_JOYSTICK=OFF -DHAS_DPAD=OFF -DHAS_GAMECTRL=OFF -DHAS_TOUCHPAD=OFF -DHAS_KBCTRL=OFF -DNONET=ON -DNOSOUND=ON -DSCREEN_WIDTH=640 -DSCREEN_HEIGHT=480 -DNOWIDESCREEN=ON' artifact: 'hellmini-nightly-x86.zip' - name: hellsrv-x86 - packages: 'sdl2:x86-windows libsodium:x86-windows' + #packages: 'sdl2:x86-windows libsodium:x86-windows' cmakeargs: '-A Win32 -D_WIN32_WINNT=0x0501 -DNOHOSTING=OFF -DHOSTONLY=ON -DINET_MODE=ON -DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON -DHAS_JOYSTICK=OFF -DHAS_DPAD=OFF -DHAS_GAMECTRL=OFF -DHAS_TOUCHPAD=OFF -DHAS_KBCTRL=OFF -DNOSOUND=ON -DSCREEN_WIDTH=640 -DSCREEN_HEIGHT=480 -DNOWIDESCREEN=ON' artifact: 'hellsrv-nightly-x86.zip' # x64 builds - name: diablo - packages: 'sdl2:x64-windows libsodium:x64-windows' + #packages: 'sdl2:x64-windows libsodium:x64-windows' cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON' artifact: 'diablo-nightly-x64.zip' - name: hellfire - packages: 'sdl2:x64-windows libsodium:x64-windows' + #packages: 'sdl2:x64-windows libsodium:x64-windows' cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-x64.zip' steps: @@ -77,12 +77,12 @@ jobs: vcpkgGitCommitId: '095ee06e7f60dceef7d713e3f8b1c2eb10d650d7' #setupOnly: true # Now that vcpkg is installed, it is being used to run with the desired arguments. - - name: Install Required Packages - run: | - vcpkg install ${{ matrix.packages }} - # Start-Process -Wait -NoNewWindow -FilePath "$env:VCPKG_ROOT\vcpkg" -ArgumentList "install ${{ matrix.packages }}" - # $VCPKG_ROOT/vcpkg install ${{ matrix.packages }} - #shell: bash + #- name: Install Required Packages + # run: | + # vcpkg install ${{ matrix.packages }} + # # Start-Process -Wait -NoNewWindow -FilePath "$env:VCPKG_ROOT\vcpkg" -ArgumentList "install ${{ matrix.packages }}" + # # $VCPKG_ROOT/vcpkg install ${{ matrix.packages }} + # #shell: bash - name: Configure CMake shell: bash From 037f7f8ccc49f070937e56a343d7e9b9301274bf Mon Sep 17 00:00:00 2001 From: Trihedraf Date: Mon, 3 Jun 2024 15:00:19 -0700 Subject: [PATCH 314/596] Update mingw scripts to latest dependency releases --- Packaging/windows/mingw-prep.sh | 4 ++-- Packaging/windows/mingw9x-prep.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Packaging/windows/mingw-prep.sh b/Packaging/windows/mingw-prep.sh index 5ea17029038..6b92b4063a5 100755 --- a/Packaging/windows/mingw-prep.sh +++ b/Packaging/windows/mingw-prep.sh @@ -1,9 +1,9 @@ #!/usr/bin/env bash -SDLDEV_VERS=2.28.5 +SDLDEV_VERS=2.30.3 SDLTTF_VERS=2.0.15 SDLMIXER_VERS=2.0.4 -SODIUM_VERS=1.0.18 +SODIUM_VERS=1.0.20 # exit when any command fails set -euo pipefail diff --git a/Packaging/windows/mingw9x-prep.sh b/Packaging/windows/mingw9x-prep.sh index 020983cefaf..e23820a2b81 100755 --- a/Packaging/windows/mingw9x-prep.sh +++ b/Packaging/windows/mingw9x-prep.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash SDLDEV_VERS=1.2.15 -SODIUM_VERS=1.0.18 +SODIUM_VERS=1.0.20 # exit when any command fails set -euo pipefail From f9021697daf44ee6694b0afe2967ea27b7f7194a Mon Sep 17 00:00:00 2001 From: Trihedraf Date: Thu, 6 Jun 2024 19:42:28 -0700 Subject: [PATCH 315/596] Add NSIS CPack --- CMakeLists.txt | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 33d9c6fdd5b..18ad6181b71 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -150,6 +150,7 @@ option(PIE "Generate position-independent code" OFF) option(CPACK "Configure CPack" ON) option(USE_LD_MOLD "Use mold linker(GNU|Clang)" OFF) option(MACOSX_STANDALONE_APP_BUNDLE "Generate a portable app bundle to use on other devices (requires sudo)" OFF) +option(WIN_NSIS "Generate an NSIS installer" OFF) option(USE_SDL1 "Use SDL1.2 instead of SDL2" OFF) option(NOSOUND "Disable sound support" OFF) option(STREAM_ALL_AUDIO "Stream all the audio. For extremely RAM-constrained platforms." OFF) @@ -1293,8 +1294,20 @@ endif() if(CPACK) if(WIN32) set(CPACK_PACKAGE_NAME ${project_name}) - set(CPACK_PACKAGE_FILE_NAME ${project_name}) - set(CPACK_GENERATOR "ZIP") + if(WIN_NSIS) + set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}_${PROJECT_VERSION}_Installer") + set(CPACK_GENERATOR "NSIS") + set(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME}") + set(CPACK_NSIS_MUI_ICON "${PROJECT_SOURCE_DIR}/Packaging/windows/icon.ico") + set(CPACK_NSIS_MUI_UNIICON "${PROJECT_SOURCE_DIR}/Packaging/windows/icon.ico") + set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE.md") + set(CPACK_NSIS_EXECUTABLES_DIRECTORY ".") + set(CPACK_PACKAGE_EXECUTABLES "${BIN_TARGET}" "${PROJECT_NAME}") + set(CPACK_NSIS_MUI_FINISHPAGE_RUN "${BIN_TARGET}") + else() + set(CPACK_PACKAGE_FILE_NAME ${project_name}) + set(CPACK_GENERATOR "ZIP") + endif() set(CPACK_STRIP_FILES TRUE) install(TARGETS ${BIN_TARGET} DESTINATION .) From 86f0d47c3a228d0dfeebc86d83e3b7365d44d249 Mon Sep 17 00:00:00 2001 From: staphen Date: Wed, 3 Jul 2024 17:54:45 -0400 Subject: [PATCH 316/596] [Android] Force app to overlap with the display cutout --- .../org/diasurgical/devilutionx/DevilutionXSDLActivity.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/android-project/app/src/main/java/org/diasurgical/devilutionx/DevilutionXSDLActivity.java b/android-project/app/src/main/java/org/diasurgical/devilutionx/DevilutionXSDLActivity.java index 37001201bf5..c8ba430cc91 100644 --- a/android-project/app/src/main/java/org/diasurgical/devilutionx/DevilutionXSDLActivity.java +++ b/android-project/app/src/main/java/org/diasurgical/devilutionx/DevilutionXSDLActivity.java @@ -10,6 +10,7 @@ import android.view.SurfaceView; import android.view.ViewTreeObserver; import android.widget.Toast; +import android.view.WindowManager; import org.libsdl.app.SDLActivity; @@ -30,6 +31,10 @@ protected void onCreate(Bundle savedInstanceState) { if (Build.VERSION.SDK_INT >= 25) trackVisibleSpace(); + // Force app to overlap with the display cutout + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) + getWindow().getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; + externalDir = chooseExternalFilesDir(); migrateSaveGames(); From 83b533c8382a1ccc42345ebcd44c7a7690c28539 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Mon, 17 Jun 2024 08:36:51 +0100 Subject: [PATCH 317/596] SDL1: Fix windowed video mode On Ubuntu 24.04 when running in a window, `SDL_GetVideoInfo` returns the display size rather than the window size, resulting in incorrect scaling. Using `SDL_GetVideoSurface` instead of `SDL_GetVideoInfo` fixes this. --- Source/utils/display.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Source/utils/display.cpp b/Source/utils/display.cpp index 9439b47c1ad..d0a364bc32c 100644 --- a/Source/utils/display.cpp +++ b/Source/utils/display.cpp @@ -82,9 +82,12 @@ void SetVideoMode(int width, int height, int bpp, uint32_t flags) sdl_error(ERR_SDL_DISPLAY_MODE_SET); } #if DEBUG_MODE - const SDL_VideoInfo* current = SDL_GetVideoInfo(); - DoLog("Video mode is now %dx%d bpp=%d flags=0x%08X", - current->current_w, current->current_h, current->vfmt->BitsPerPixel, SDL_GetVideoSurface()->flags); + const SDL_Surface *surface = SDL_GetVideoSurface(); + if (surface == NULL) { + sdl_error(ERR_SDL_DISPLAY_MODE_SET); + } + DoLog("Video surface is now %dx%d bpp=%d flags=0x%08X", + surface->w, surface->h, surface->format->BitsPerPixel, surface->flags); #endif } @@ -266,9 +269,12 @@ void SpawnWindow() if (grabInput) SDL_WM_GrabInput(SDL_GRAB_ON); atexit(SDL_VideoQuit); // Without this video mode is not restored after fullscreen. - const SDL_VideoInfo* current = SDL_GetVideoInfo(); - width = current->current_w; - height = current->current_h; + const SDL_Surface *surface = SDL_GetVideoSurface(); + if (surface == NULL) { + sdl_error(ERR_SDL_WINDOW_CREATE); + } + width = surface->w; + height = surface->h; #else bool integerScalingEnabled = getIniBool("Graphics", "Integer Scaling", false); bool upscale = getIniBool("Graphics", "Upscale", true); From 654479cb767705602444f9e4f1e0a8be56ee79ee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Jul 2024 08:30:12 +0200 Subject: [PATCH 318/596] Bump softprops/action-gh-release from 2.0.5 to 2.0.6 (#10) Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.0.5 to 2.0.6. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/v2.0.5...v2.0.6) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/nightly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 5dd4a52a3ae..17ec69343f0 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1569,7 +1569,7 @@ jobs: shell: bash - name: Release - uses: softprops/action-gh-release@v2.0.5 + uses: softprops/action-gh-release@v2.0.6 with: tag_name: devilx-nightly body_path: ${{ github.workspace }}/RELEASE_NOTE.md From 948238725c94c29b005830e9ff15052c8610da75 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 5 Jul 2024 08:46:36 +0200 Subject: [PATCH 319/596] fix class selector II. - bugfix for "add SelheroResetScreen" --- Source/DiabloUI/selhero.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/DiabloUI/selhero.cpp b/Source/DiabloUI/selhero.cpp index 25d81b8655d..a51b42913d2 100644 --- a/Source/DiabloUI/selhero.cpp +++ b/Source/DiabloUI/selhero.cpp @@ -370,6 +370,8 @@ static void SelheroClassSelectorInit() SDL_Rect rect3 = { SELHERO_RPANEL_LEFT, SELHERO_RBUTTON_TOP, SELHERO_RPANEL_WIDTH / 2, 35 }; gUiItems.push_back(new UiTxtButton("OK", &UiFocusNavigationSelect, rect3, UIS_HCENTER | UIS_VCENTER | UIS_BIG | UIS_GOLD)); + SELLIST_DIALOG_DELETE_BUTTON = NULL; // TODO: reset in SelheroFreeDlgItems? + SDL_Rect rect4 = { SELHERO_RPANEL_LEFT + SELHERO_RPANEL_WIDTH / 2, SELHERO_RBUTTON_TOP, SELHERO_RPANEL_WIDTH / 2, 35 }; gUiItems.push_back(new UiTxtButton("Cancel", &UiFocusNavigationEsc, rect4, UIS_HCENTER | UIS_VCENTER | UIS_BIG | UIS_GOLD)); From 5c8c5563f0d485ecaa9de305ce4c5baa76c10138 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 5 Jul 2024 10:06:42 +0200 Subject: [PATCH 320/596] fix the patcher - bugfix for 'add special cel-frames for the arches in Crypt' --- tools/patcher/drlp_l1.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/patcher/drlp_l1.cpp b/tools/patcher/drlp_l1.cpp index 2f5f7227b6a..346f48aa548 100644 --- a/tools/patcher/drlp_l1.cpp +++ b/tools/patcher/drlp_l1.cpp @@ -2563,7 +2563,7 @@ BYTE* DRLP_L5_PatchSpec(const BYTE* minBuf, size_t minLen, const BYTE* celBuf, s // if (frame.subtileIndex0 < 0) { // continue; // } - for (int n = 0; n < lengthof(frame.microIndices0); n++) { + for (int n = 0; n < lengthof(frame.microIndices0) && frame.subtileIndex0 >= 0; n++) { if (frame.microIndices0[n] < 0) { continue; } From 057db03e41d8cc21f4dfaaae26d5e0014446ab20 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 6 Jul 2024 11:46:28 +0200 Subject: [PATCH 321/596] zfill the work-buffer of pkware-compress to make the mpq consistent --- tools/patcher/encrypt.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/patcher/encrypt.cpp b/tools/patcher/encrypt.cpp index 87149f4252e..8c165d2cdcf 100644 --- a/tools/patcher/encrypt.cpp +++ b/tools/patcher/encrypt.cpp @@ -82,6 +82,8 @@ DWORD PkwareCompress(BYTE* srcData, DWORD size) unsigned int destSize; // , type, dsize; work_buf = (char*)DiabloAllocPtr(CMP_BUFFER_SIZE); + // zfill the work-buffer to make the result consistent (see Warning in WriteCmpData(TCmpStruct * pWork) / (implode.cpp) + memset(work_buf, 0, CMP_BUFFER_SIZE); destSize = 2 * size; if (destSize < 2 * CMP_IMPLODE_DICT_SIZE3) From 6d24eb1a4d98bc0632ab975616c80dcdd498499b Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 6 Jul 2024 11:48:53 +0200 Subject: [PATCH 322/596] eliminte unused parameter of mpqapi_write_file_contents --- Source/mpqapi.cpp | 9 ++------- tools/patcher/mpqapi.cpp | 9 ++------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/Source/mpqapi.cpp b/Source/mpqapi.cpp index 796eb37b2de..94fa267cd3e 100644 --- a/Source/mpqapi.cpp +++ b/Source/mpqapi.cpp @@ -554,14 +554,9 @@ static uint32_t mpqapi_add_entry(const char* pszName, uint32_t block_index) return 0; } -static bool mpqapi_write_file_contents(const char* pszName, const BYTE* pbData, DWORD dwLen, uint32_t block) +static bool mpqapi_write_file_contents(const BYTE* pbData, DWORD dwLen, uint32_t block) { FileMpqBlockEntry* pBlk = &cur_archive.sgpBlockTbl[block]; - const char* tmp; - while ((tmp = strchr(pszName, ':'))) - pszName = tmp + 1; - while ((tmp = strchr(pszName, '\\'))) - pszName = tmp + 1; const uint32_t num_sectors = (dwLen + (MPQ_SECTOR_SIZE - 1)) / MPQ_SECTOR_SIZE; const uint32_t offset_table_bytesize = sizeof(uint32_t) * (num_sectors + 1); @@ -648,7 +643,7 @@ bool mpqapi_write_entry(const char* pszName, const BYTE* pbData, DWORD dwLen) cur_archive.modified = true; mpqapi_remove_entry(pszName); block = mpqapi_add_entry(pszName, HASH_ENTRY_FREE); - if (!mpqapi_write_file_contents(pszName, pbData, dwLen, block)) { + if (!mpqapi_write_file_contents(pbData, dwLen, block)) { mpqapi_remove_entry(pszName); return false; } diff --git a/tools/patcher/mpqapi.cpp b/tools/patcher/mpqapi.cpp index 796eb37b2de..94fa267cd3e 100644 --- a/tools/patcher/mpqapi.cpp +++ b/tools/patcher/mpqapi.cpp @@ -554,14 +554,9 @@ static uint32_t mpqapi_add_entry(const char* pszName, uint32_t block_index) return 0; } -static bool mpqapi_write_file_contents(const char* pszName, const BYTE* pbData, DWORD dwLen, uint32_t block) +static bool mpqapi_write_file_contents(const BYTE* pbData, DWORD dwLen, uint32_t block) { FileMpqBlockEntry* pBlk = &cur_archive.sgpBlockTbl[block]; - const char* tmp; - while ((tmp = strchr(pszName, ':'))) - pszName = tmp + 1; - while ((tmp = strchr(pszName, '\\'))) - pszName = tmp + 1; const uint32_t num_sectors = (dwLen + (MPQ_SECTOR_SIZE - 1)) / MPQ_SECTOR_SIZE; const uint32_t offset_table_bytesize = sizeof(uint32_t) * (num_sectors + 1); @@ -648,7 +643,7 @@ bool mpqapi_write_entry(const char* pszName, const BYTE* pbData, DWORD dwLen) cur_archive.modified = true; mpqapi_remove_entry(pszName); block = mpqapi_add_entry(pszName, HASH_ENTRY_FREE); - if (!mpqapi_write_file_contents(pszName, pbData, dwLen, block)) { + if (!mpqapi_write_file_contents(pbData, dwLen, block)) { mpqapi_remove_entry(pszName); return false; } From 36d5099c158f24eaf0b213cb3fecc47b98904ae4 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 6 Jul 2024 12:06:54 +0200 Subject: [PATCH 323/596] add option to check the md5sum of the mpq files in the patcher --- CMakeLists.txt | 1 + tools/patcher/DiabloUI/checker.cpp | 152 ++++++++++++ tools/patcher/DiabloUI/diablo.h | 5 +- tools/patcher/DiabloUI/mainmenu.cpp | 5 +- tools/patcher/DiabloUI/merger.cpp | 3 + tools/patcher/diabloui.h | 2 + tools/patcher/init.cpp | 36 +-- tools/patcher/mainmenu.cpp | 3 + tools/patcher/utils/md5.h | 359 ++++++++++++++++++++++++++++ 9 files changed, 548 insertions(+), 18 deletions(-) create mode 100644 tools/patcher/DiabloUI/checker.cpp create mode 100644 tools/patcher/utils/md5.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 18ad6181b71..af4771f9fdd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -658,6 +658,7 @@ if(USE_PATCH AND NOT ANDROID) tools/patcher/controls/devices/kbcontroller.cpp tools/patcher/controls/game_controls.cpp tools/patcher/controls/touch.cpp + tools/patcher/DiabloUI/checker.cpp tools/patcher/DiabloUI/diabloui.cpp tools/patcher/DiabloUI/dialogs.cpp tools/patcher/DiabloUI/mainmenu.cpp diff --git a/tools/patcher/DiabloUI/checker.cpp b/tools/patcher/DiabloUI/checker.cpp new file mode 100644 index 00000000000..7de0dcc6535 --- /dev/null +++ b/tools/patcher/DiabloUI/checker.cpp @@ -0,0 +1,152 @@ +#include "diablo.h" +#include "diabloui.h" +#include "selok.h" +#include "utils/paths.h" +#include "utils/md5.h" + +DEVILUTION_BEGIN_NAMESPACE + +static unsigned workProgress; +static unsigned workPhase; +static MD5* md5; + +static constexpr int RETURN_ERROR = 101; +static constexpr int RETURN_DONE = 100; + +static int checkResult[NUM_MPQS + 1]; + +typedef struct FileMetaInfo { + const char* fileName; + const char* fileHash0; // GOG | patched devilx-mpq + const char* fileHash1; // ??? | non-patched devilx-mpq + bool optional; +} FileMetaInfo; + +static const FileMetaInfo filemetadata[] = { +#if ASSET_MPL != 1 + { "DEVILHD.MPQ", "", "", false }, +#endif + { "DEVILX.MPQ", "251688ff12da6d42ea2ebf31d83d3f3c", "b336be80b3968d4bf8495a2983d4d9f9", false }, +#ifdef HELLFIRE + { "HF_OPT2.MPQ", "", "", true }, + { "HF_OPT1.MPQ", "", "", true }, + { "HF_VOICE.MPQ", "6ae6ce3e89ece92c1e3e912a91d0b186", "6ae6ce3e89ece92c1e3e912a91d0b186", false }, + { "HF_MUSIC.MPQ", "5f79b271b4a291fc8968df7e8aa80d52", "f40a5dede03e84b663a1ced6ddc1cc20", false }, + { "HF_BARB.MPQ", "", "", true }, + { "HF_BARD.MPQ", "", "", true }, + { "HF_MONK.MPQ", "5a6b8f1ef6d505d469c31aef6e48e89d", "5a6b8f1ef6d505d469c31aef6e48e89d", false }, + { "HELLFIRE.MPQ", "c996bd970df13ea7aa5e2417f8e78b9f", "c996bd970df13ea7aa5e2417f8e78b9f", false }, +#endif + { "PATCH_RT.MPQ", "d2488b30310c1d293eaf068a29709e65", "", true }, + { "DIABDAT.MPQ", "011bc6518e6166206231080a4440b373", "68f049866b44688a7af65ba766bef75a", false }, +#if USE_MPQONE + { MPQONE, "81befc2f5f061df0ac3d9de1ecbaff7f", "", false }, +#else + { MPQONE, "81befc2f5f061df0ac3d9de1ecbaff7f", "", true }, +#endif +}; +static_assert(NUM_MPQS + 1 == sizeof(filemetadata) / sizeof(FileMetaInfo), "Mismatching metadata."); + +static int checker_callback() +{ + if (!diabdat_paths[workPhase].empty()) { + char* res = md5->digestFile(diabdat_paths[workPhase].c_str()); + + if (SDL_strcmp(filemetadata[workPhase].fileHash0, res) == 0) { + checkResult[workPhase] = 0; + } else if (SDL_strcmp(filemetadata[workPhase].fileHash1, res) == 0) { + checkResult[workPhase] = 1; + } else { + // LogErrorF("", "File:%s hash:%s", diabdat_paths[workPhase].c_str(), res); + checkResult[workPhase] = 2; + } + } else { + checkResult[workPhase] = -1; + } + + if (++workPhase > NUM_MPQS) { + return RETURN_DONE; + } + + workProgress = (99 * workPhase / NUM_MPQS) - 1; + + while (++workProgress >= 100) + workProgress -= 100; + return workProgress; +} + +void UiCheckerDialog() +{ + workProgress = 0; + workPhase = 0; + md5 = new MD5(); + + bool result = UiProgressDialog("...Check in progress...", checker_callback); + + delete md5; + md5 = NULL; + + if (!result) { + return; + } + + { + char dialogTitle[32]; + char dialogText[256]; + dialogTitle[0] = '\0'; + dialogText[0] = '\0'; + int cursor = 0; + + for (int i = 0; i <= NUM_MPQS && cursor < sizeof(dialogText) - 1; i++) { + if (checkResult[i] == 0) { + // LogErrorF("", "File:%s is correct (GOG).", filemetadata[i].fileName); + continue; + } + if (checkResult[i] == 1) { + if (i != MPQ_DEVILX) { + // LogErrorF("", "File:%s is correct (???).", filemetadata[i].fileName); + continue; + } + } + if (filemetadata[i].optional && i != NUM_MPQS) { + // LogErrorF("", "File:%s ignored.", filemetadata[i].fileName); + continue; + } + if (dialogText[0] != '\0') { + dialogText[cursor] = '\n'; + cursor++; + dialogText[cursor] = '0'; + } + if (checkResult[i] < 0) { + // file is missing/not created + if (i != NUM_MPQS) + cursor += snprintf(&dialogText[cursor], sizeof(dialogText) - cursor, "%s is missing.", filemetadata[i].fileName); + else + cursor += snprintf(&dialogText[cursor], sizeof(dialogText) - cursor, "%s is not created.", filemetadata[i].fileName); + } else if (checkResult[i] == 1) { + // matching hash + assert(i == MPQ_DEVILX); + cursor += snprintf(&dialogText[cursor], sizeof(dialogText) - cursor, "%s must be patched.", filemetadata[i].fileName); + } else { + // hash does not match + if (i != NUM_MPQS) + cursor += snprintf(&dialogText[cursor], sizeof(dialogText) - cursor, "%s is corrupt.", filemetadata[i].fileName); + else + cursor += snprintf(&dialogText[cursor], sizeof(dialogText) - cursor, "%s must be recreated.", filemetadata[i].fileName); + } + // LogErrorF("", "File:%s reported. cursor at %d.", filemetadata[i].fileName, cursor); + } +#if USE_MPQONE + if (checkResult[NUM_MPQS] == 0 && dialogText[0] != '\0') { + snprintf(dialogText, sizeof(dialogText), "The merged mpq file is ready to be used."); + } +#endif + if (dialogText[0] == '\0') { + snprintf(dialogText, sizeof(dialogText), "The mpq files are complete."); + } + + UiSelOkDialog(dialogTitle, dialogText); + } +} + +DEVILUTION_END_NAMESPACE diff --git a/tools/patcher/DiabloUI/diablo.h b/tools/patcher/DiabloUI/diablo.h index be2b4681f61..a0beb69d9fd 100644 --- a/tools/patcher/DiabloUI/diablo.h +++ b/tools/patcher/DiabloUI/diablo.h @@ -5,7 +5,7 @@ */ #pragma once -//#include +#include #include "all.h" @@ -15,6 +15,9 @@ DEVILUTION_BEGIN_NAMESPACE extern "C" { #endif +/* Defined in init.cpp */ +extern std::string diabdat_paths[NUM_MPQS + 1]; + /* Defined in effects.cpp */ /*#ifndef NOSOUND void PlaySFX(int psfx); diff --git a/tools/patcher/DiabloUI/mainmenu.cpp b/tools/patcher/DiabloUI/mainmenu.cpp index 283efa4a3b8..900e99eb00a 100644 --- a/tools/patcher/DiabloUI/mainmenu.cpp +++ b/tools/patcher/DiabloUI/mainmenu.cpp @@ -24,11 +24,12 @@ static void MainmenuEsc() static void MainmenuLoad() { - int numOptions = 3; + int numOptions = 4; gUIListItems.push_back(new UiListItem("Patch Assets", 0)); gUIListItems.push_back(new UiListItem("Merge Assets", 1)); - gUIListItems.push_back(new UiListItem("Exit Patcher", 2)); + gUIListItems.push_back(new UiListItem("Check Assets", 2)); + gUIListItems.push_back(new UiListItem("Exit Patcher", 3)); LoadBackgroundArt("ui_art\\mainmenu.CEL", "ui_art\\menu.pal"); diff --git a/tools/patcher/DiabloUI/merger.cpp b/tools/patcher/DiabloUI/merger.cpp index fbfa6ed856d..1471ae8eaf5 100644 --- a/tools/patcher/DiabloUI/merger.cpp +++ b/tools/patcher/DiabloUI/merger.cpp @@ -1,6 +1,7 @@ #include #include +#include "diablo.h" #include "diabloui.h" #include "selok.h" #include "selyesno.h" @@ -221,6 +222,7 @@ static int merger_callback() app_warn("Failed to create %s.", path.c_str()); return RETURN_ERROR; } + diabdat_paths[NUM_MPQS] = path; } return RETURN_DONE; default: ASSUME_UNREACHABLE @@ -260,6 +262,7 @@ void UiMergerDialog() SFileCloseArchive(diabdat_mpqs[NUM_MPQS]); diabdat_mpqs[NUM_MPQS] = NULL; + diabdat_paths[NUM_MPQS].clear(); std::string path = std::string(GetBasePath()) + MPQONE; RemoveFile(path.c_str()); } diff --git a/tools/patcher/diabloui.h b/tools/patcher/diabloui.h index febbaf72698..0deb5977e67 100644 --- a/tools/patcher/diabloui.h +++ b/tools/patcher/diabloui.h @@ -19,6 +19,8 @@ void UiDestroy(); bool UiTitleDialog(); /* Defined in mainmenu.cpp */ int UiMainMenuDialog(); +/* Defined in checker.cpp */ +void UiCheckerDialog(); /* Defined in merger.cpp */ void UiMergerDialog(); /* Defined in patcher.cpp */ diff --git a/tools/patcher/init.cpp b/tools/patcher/init.cpp index a87ce8e2b1c..b7c1feac184 100644 --- a/tools/patcher/init.cpp +++ b/tools/patcher/init.cpp @@ -8,8 +8,10 @@ //#endif #include "all.h" +#include "DiabloUI/diablo.h" #include "utils/paths.h" #include "utils/file_util.h" +#include "utils/md5.h" #include "storm/storm_cfg.h" #include #if DEV_MODE @@ -25,8 +27,10 @@ DEVILUTION_BEGIN_NAMESPACE /** A handle to the mpq archives. */ HANDLE diabdat_mpqs[NUM_MPQS + 1]; +/** Path to the mpq archives. */ +std::string diabdat_paths[NUM_MPQS + 1]; -static HANDLE init_test_access(const char* mpq_name) +static HANDLE init_test_access(const char* mpq_name, unsigned fileIndex) { HANDLE archive; #if defined(__3DS__) || defined(__SWITCH__) @@ -39,11 +43,13 @@ static HANDLE init_test_access(const char* mpq_name) const char* paths[2] = { GetBasePath(), GetPrefPath() }; #endif std::string mpq_abspath; + diabdat_paths[fileIndex].clear(); for (int i = 0; i < lengthof(paths); i++) { mpq_abspath = paths[i]; mpq_abspath += mpq_name; archive = SFileOpenArchive(mpq_abspath.c_str(), MPQ_OPEN_READ_ONLY); if (archive != NULL) { + diabdat_paths[fileIndex] = mpq_abspath; return archive; } } @@ -138,34 +144,34 @@ void InitArchives() CreateMpq("devilx.mpq", "Work\\", "mpqfiles.txt"); CreateMpq("devilx_hd2.mpq", "WorkHd\\", "hdfiles.txt"); #endif - diabdat_mpqs[NUM_MPQS] = init_test_access(MPQONE); + diabdat_mpqs[NUM_MPQS] = init_test_access(MPQONE, NUM_MPQS); - diabdat_mpqs[MPQ_DIABDAT] = init_test_access(DATA_ARCHIVE_MAIN); + diabdat_mpqs[MPQ_DIABDAT] = init_test_access(DATA_ARCHIVE_MAIN, MPQ_DIABDAT); if (diabdat_mpqs[MPQ_DIABDAT] == NULL) - diabdat_mpqs[MPQ_DIABDAT] = init_test_access(DATA_ARCHIVE_MAIN_ALT); + diabdat_mpqs[MPQ_DIABDAT] = init_test_access(DATA_ARCHIVE_MAIN_ALT, MPQ_DIABDAT); if (diabdat_mpqs[MPQ_DIABDAT] == NULL) app_fatal("Can not find/access '%s' in the game folder.", DATA_ARCHIVE_MAIN); - diabdat_mpqs[MPQ_PATCH_RT] = init_test_access(DATA_ARCHIVE_PATCH); + diabdat_mpqs[MPQ_PATCH_RT] = init_test_access(DATA_ARCHIVE_PATCH, MPQ_PATCH_RT); //if (!SFileOpenFileEx(diabdat_mpqs[MPQ_DIABDAT], "ui_art\\title.pcx", SFILE_OPEN_CHECK_EXISTS, NULL)) // InsertCDDlg(); #ifdef HELLFIRE - diabdat_mpqs[MPQ_HELLFIRE] = init_test_access("hellfire.mpq"); - diabdat_mpqs[MPQ_HF_MONK] = init_test_access("hfmonk.mpq"); - diabdat_mpqs[MPQ_HF_BARD] = init_test_access("hfbard.mpq"); - diabdat_mpqs[MPQ_HF_BARB] = init_test_access("hfbarb.mpq"); - diabdat_mpqs[MPQ_HF_MUSIC] = init_test_access("hfmusic.mpq"); - diabdat_mpqs[MPQ_HF_VOICE] = init_test_access("hfvoice.mpq"); - diabdat_mpqs[MPQ_HF_OPT1] = init_test_access("hfopt1.mpq"); - diabdat_mpqs[MPQ_HF_OPT2] = init_test_access("hfopt2.mpq"); + diabdat_mpqs[MPQ_HELLFIRE] = init_test_access("hellfire.mpq", MPQ_HELLFIRE); + diabdat_mpqs[MPQ_HF_MONK] = init_test_access("hfmonk.mpq", MPQ_HF_MONK); + diabdat_mpqs[MPQ_HF_BARD] = init_test_access("hfbard.mpq", MPQ_HF_BARD); + diabdat_mpqs[MPQ_HF_BARB] = init_test_access("hfbarb.mpq", MPQ_HF_BARB); + diabdat_mpqs[MPQ_HF_MUSIC] = init_test_access("hfmusic.mpq", MPQ_HF_MUSIC); + diabdat_mpqs[MPQ_HF_VOICE] = init_test_access("hfvoice.mpq", MPQ_HF_VOICE); + diabdat_mpqs[MPQ_HF_OPT1] = init_test_access("hfopt1.mpq", MPQ_HF_OPT1); + diabdat_mpqs[MPQ_HF_OPT2] = init_test_access("hfopt2.mpq", MPQ_HF_OPT2); #endif - diabdat_mpqs[MPQ_DEVILX] = init_test_access("devilx.mpq"); + diabdat_mpqs[MPQ_DEVILX] = init_test_access("devilx.mpq", MPQ_DEVILX); if (diabdat_mpqs[MPQ_DEVILX] == NULL) app_fatal("Can not find/access '%s' in the game folder.", "devilx.mpq"); #if ASSET_MPL != 1 char tmpstr[32]; snprintf(tmpstr, lengthof(tmpstr), "devilx_hd%d.mpq", ASSET_MPL); - diabdat_mpqs[MPQ_DEVILHD] = init_test_access(tmpstr); + diabdat_mpqs[MPQ_DEVILHD] = init_test_access(tmpstr, MPQ_DEVILHD); if (diabdat_mpqs[MPQ_DEVILHD] == NULL) app_fatal("Can not find/access '%s' in the game folder.", tmpstr); #endif diff --git a/tools/patcher/mainmenu.cpp b/tools/patcher/mainmenu.cpp index ffb021c4d3a..aafc0eae369 100644 --- a/tools/patcher/mainmenu.cpp +++ b/tools/patcher/mainmenu.cpp @@ -39,6 +39,9 @@ void mainmenu_loop() UiMergerDialog(); continue; case 2: + UiCheckerDialog(); + continue; + case 3: break; default: ASSUME_UNREACHABLE diff --git a/tools/patcher/utils/md5.h b/tools/patcher/utils/md5.h new file mode 100644 index 00000000000..54bfc35c338 --- /dev/null +++ b/tools/patcher/utils/md5.h @@ -0,0 +1,359 @@ +#ifndef MD5_H +#define MD5_H +#include +#include + +#include "../all.h" + +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + +//#pragma region MD5 defines +// Constants for MD5Transform routine. +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +static unsigned char PADDING[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +// F, G, H and I are basic MD5 functions. +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +// ROTATE_LEFT rotates x left n bits. +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +// Rotation is separate from addition to prevent recomputation. +#define FF(a, b, c, d, x, s, ac) { \ + (a) += F ((b), (c), (d)) + (x) + (DWORD)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) { \ + (a) += G ((b), (c), (d)) + (x) + (DWORD)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) { \ + (a) += H ((b), (c), (d)) + (x) + (DWORD)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) { \ + (a) += I ((b), (c), (d)) + (x) + (DWORD)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +//#pragma endregion + +// convenient object that wraps +// the C-functions for use in C++ only +class MD5 +{ +private: + struct __context_t { + DWORD state[4]; /* state (ABCD) */ + DWORD count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ + } context; + +//#pragma region static helper functions + // The core of the MD5 algorithm is here. + // MD5 basic transformation. Transforms state based on block. + static void MD5Transform(DWORD state[4], const unsigned char block[64]) + { + DWORD a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + + Decode(x, block, 64); + + /* Round 1 */ + FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */ + FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */ + FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */ + FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */ + FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */ + FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */ + FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */ + FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */ + FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */ + FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */ + FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */ + GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */ + GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */ + GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */ + GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */ + GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */ + GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */ + GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */ + GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */ + GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */ + GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */ + HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */ + HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */ + HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */ + HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */ + HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */ + HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */ + HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */ + HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */ + HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */ + II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */ + II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */ + II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */ + II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */ + II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */ + II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */ + II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */ + II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */ + II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + // Zeroize sensitive information. + memset(x, 0, sizeof(x)); + } + + // Encodes input (DWORD) into output (unsigned char). Assumes len is + // a multiple of 4. + static void Encode(unsigned char *output, DWORD *input, unsigned int len) + { + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) { + /*output[j] = (unsigned char)(input[i] & 0xff); + output[j + 1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j + 2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j + 3] = (unsigned char)((input[i] >> 24) & 0xff);*/ + + *(DWORD *)&output[j] = SwapLE32(input[i]); + } + } + + // Decodes input (unsigned char) into output (DWORD). Assumes len is + // a multiple of 4. + static void Decode(DWORD *output, const unsigned char *input, unsigned int len) + { + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) { + /*output[i] = ((DWORD)input[j]) | (((DWORD)input[j + 1]) << 8) | + (((DWORD)input[j + 2]) << 16) | (((DWORD)input[j + 3]) << 24);*/ + + output[i] = SwapLE32(*(DWORD *)&input[j]); + } + } +//#pragma endregion + + +public: + // MAIN FUNCTIONS + MD5() + { + // Init(); + } + +private: + // MD5 initialization. Begins an MD5 operation, writing a new context. + void Init() + { + context.count[0] = context.count[1] = 0; + + // Load magic initialization constants. + context.state[0] = 0x67452301; + context.state[1] = 0xefcdab89; + context.state[2] = 0x98badcfe; + context.state[3] = 0x10325476; + } + + // MD5 block update operation. Continues an MD5 message-digest + // operation, processing another message block, and updating the + // context. + void Update( + const unsigned char *input, // input block + unsigned int inputLen) // length of input block + { + unsigned int i, index, partLen; + + // Compute number of bytes mod 64 + index = (unsigned int)((context.count[0] >> 3) & 0x3F); + + // Update number of bits + if ((context.count[0] += ((DWORD)inputLen << 3)) + < ((DWORD)inputLen << 3)) + context.count[1]++; + context.count[1] += ((DWORD)inputLen >> 29); + + partLen = 64 - index; + + // Transform as many times as possible. + if (inputLen >= partLen) { + memcpy(&context.buffer[index], input, partLen); + MD5Transform(context.state, context.buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + MD5Transform(context.state, &input[i]); + + index = 0; + } + else + i = 0; + + /* Buffer remaining input */ + memcpy(&context.buffer[index], &input[i], inputLen - i); + } + + // MD5 finalization. Ends an MD5 message-digest operation, writing the + // the message digest and zeroizing the context. + // Writes to digestRaw + void Final() + { + unsigned char bits[8]; + unsigned int index, padLen; + + // Save number of bits + Encode(bits, context.count, 8); + + // Pad out to 56 mod 64. + index = (unsigned int)((context.count[0] >> 3) & 0x3f); + padLen = (index < 56) ? (56 - index) : (120 - index); + Update(PADDING, padLen); + + // Append length (before padding) + Update(bits, 8); + + // Store state in digest + Encode(digestRaw, context.state, 16); + + // Zeroize sensitive information. + memset(&context, 0, sizeof(context)); + + writeToString(); + } + + /// Buffer must be 32+1 (nul) = 33 chars long at least + void writeToString() + { + int pos; + + for (pos = 0; pos < 16; pos++) + sprintf(digestChars + (pos * 2), "%02x", digestRaw[pos]); + } + + // an MD5 digest is a 16-byte number (32 hex digits) + BYTE digestRaw[16]; + + // This version of the digest is actually + // a "printf'd" version of the digest. + char digestChars[33]; + +public: + /// Load a file from disk and digest it + // Digests a file and returns the result. + char* digestFile(const char *filename) + { + Init(); + + FILE *file; + + int len; + unsigned char buffer[1024]; + + if ((file = fopen(filename, "rb")) == NULL) + printf("%s can't be opened\n", filename); + else + { + while (len = fread(buffer, 1, 1024, file)) + Update(buffer, len); + Final(); + + fclose(file); + } + + return digestChars; + } + + /// Digests a byte-array already in memory + char* digestMemory(const BYTE *memchunk, int len) + { + Init(); + Update(memchunk, len); + Final(); + + return digestChars; + } + + // Digests a string and prints the result. + char* digestString(const char *string) + { + Init(); + Update((const unsigned char*)string, strlen(string)); + Final(); + + return digestChars; + } +}; + +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + +#endif /* MD5_H */ From 8db5c9cbd5e23517eac9a50dfbef49273bf83597 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 8 Jul 2024 14:36:13 +0200 Subject: [PATCH 324/596] fix SStrCopy in the patcher (amiga) --- tools/patcher/storm/storm.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/patcher/storm/storm.cpp b/tools/patcher/storm/storm.cpp index 051fa25902a..e7ecd28e955 100644 --- a/tools/patcher/storm/storm.cpp +++ b/tools/patcher/storm/storm.cpp @@ -87,7 +87,8 @@ void SStrCopy(char* dest, const char* src, int max_length) if (memccpy(dest, src, '\0', max_length) == NULL) dest[max_length - 1] = '\0'; #else - strncpy(dest, src, max_length); + strncpy(dest, src, max_length - 1); + dest[max_length - 1] = '\0'; #endif } From 991535f974647b76d21b33f63a81a7b04c78580d Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 8 Jul 2024 14:38:33 +0200 Subject: [PATCH 325/596] cleanup the includes in switch/network.cpp --- Source/platform/switch/network.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/platform/switch/network.cpp b/Source/platform/switch/network.cpp index 195d5797bc4..18be7ab1a66 100644 --- a/Source/platform/switch/network.cpp +++ b/Source/platform/switch/network.cpp @@ -4,7 +4,6 @@ #include #include #include -#include "platform/switch/network.h" static int nxlink_sock = -1; // for stdio on Switch From 04376c17b086d36fa9ceaf489f6384b8572bb7ed Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 8 Jul 2024 14:39:13 +0200 Subject: [PATCH 326/596] update SDL2 --- 3rdParty/SDL2/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdParty/SDL2/CMakeLists.txt b/3rdParty/SDL2/CMakeLists.txt index ed9f14c5eb4..6f24ff46458 100644 --- a/3rdParty/SDL2/CMakeLists.txt +++ b/3rdParty/SDL2/CMakeLists.txt @@ -75,7 +75,7 @@ FetchContent_Declare(SDL2 #URL https://github.com/libsdl-org/SDL/archive/5056b29b0f8611b470d8b8bdb313eab628f8bd6e.tar.gz #URL_HASH MD5=3fb6d72c33434082c32d2649c35c6502 GIT_REPOSITORY https://github.com/pionere/SDL.git - GIT_TAG 7262505555e6ecc4bfaae26d7ec2f0a42b3e6dd3 + GIT_TAG af566e3f1858490714fe355759fef4a9da58b1eb ) FetchContent_MakeAvailableExcludeFromAll(SDL2) From e74623b340102e1ff14c661126063eeeb09e4f1e Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 9 Jul 2024 07:44:34 +0200 Subject: [PATCH 327/596] bump vcpkg of the nightly-build --- .github/workflows/nightly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 17ec69343f0..a33b23ba2b3 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -74,7 +74,7 @@ jobs: - name: Create Build Environment uses: lukka/run-vcpkg@v11.5 with: - vcpkgGitCommitId: '095ee06e7f60dceef7d713e3f8b1c2eb10d650d7' + vcpkgGitCommitId: 'f7423ee180c4b7f40d43402c2feb3859161ef625' #setupOnly: true # Now that vcpkg is installed, it is being used to run with the desired arguments. #- name: Install Required Packages From 122232d0b0e9bd9165a7f3d06e7b1eace4f77874 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 9 Jul 2024 15:28:23 +0200 Subject: [PATCH 328/596] use only the standard animation for the shrines bugfix for 'patch CEL files of objects' 922a5faa447492ac87203f2672b5b6f872383666 --- Source/objects.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/objects.cpp b/Source/objects.cpp index 646f537b14f..a217624419a 100644 --- a/Source/objects.cpp +++ b/Source/objects.cpp @@ -1170,10 +1170,11 @@ static void AddShrine(int oi) os = &objects[oi]; os->_oRndSeed = NextRndSeed(); os->_oVar1 = FindValidShrine(NUM_SHRINETYPE); // SHRINE_TYPE + /* -- disabled because the animation is shifted and not much point without trap (+ cel file is cut in the patcher) if (random_(150, 2) != 0) { os->_oAnimFrame = 12; os->_oAnimLen = 22; - } + }*/ } static void ObjAddRndSeed(int oi) From bca80c2341d7e18dfd66794b74511c7abde9751f Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 9 Jul 2024 15:46:19 +0200 Subject: [PATCH 329/596] use the whole back-buffer for drawing (patcher) --- tools/patcher/DiabloUI/patcher.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tools/patcher/DiabloUI/patcher.cpp b/tools/patcher/DiabloUI/patcher.cpp index 736460546fe..c672e8bae1e 100644 --- a/tools/patcher/DiabloUI/patcher.cpp +++ b/tools/patcher/DiabloUI/patcher.cpp @@ -14,7 +14,6 @@ DEVILUTION_BEGIN_NAMESPACE static unsigned workProgress; static unsigned workPhase; -static HANDLE mpqone; static int hashCount; static constexpr int RETURN_ERROR = 101; static constexpr int RETURN_DONE = 100; @@ -4166,11 +4165,22 @@ void UiPatcherDialog() workPhase = 0; // ignore the merged mpq during the patch - mpqone = diabdat_mpqs[NUM_MPQS]; + HANDLE mpqone = diabdat_mpqs[NUM_MPQS]; diabdat_mpqs[NUM_MPQS] = NULL; + // use the whole buffer for drawing + BYTE* bufstart = gpBufStart; + BYTE* bufend = gpBufEnd; + gpBufStart = &gpBuffer[0]; + gpBufEnd = &gpBuffer[BUFFER_WIDTH * BUFFER_HEIGHT]; + bool result = UiProgressDialog("...Patch in progress...", patcher_callback); + // restore the merged mpq diabdat_mpqs[NUM_MPQS] = mpqone; + // restore buffer start/end + gpBufStart = bufstart; + gpBufEnd = bufend; + if (!result) { return; } From d4e9dc859a8f52a08e941f09d941bcb880d77445 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 10 Jul 2024 11:53:57 +0200 Subject: [PATCH 330/596] use the whole name of the spell when naming a rune --- Source/spelldat.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/spelldat.cpp b/Source/spelldat.cpp index 4bf92d94c8b..8bc8522ec17 100644 --- a/Source/spelldat.cpp +++ b/Source/spelldat.cpp @@ -99,8 +99,8 @@ const SpellData spelldata[NUM_SPELLS] = { /*SPL_RUNEFIRE*/ { 0, STYPE_FIRE, 15, "Fire", SPELL_NA, SPELL_NA, 1, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_TELEPORT, SFLAG_DUNGEON, 0, IS_CAST8, MIS_RUNEFIRE, 0, 0, 0, 0, 0, 100, ALIGN64 }, /*SPL_RUNELIGHT*/ { 0, STYPE_LIGHTNING, 3, "Lightning", SPELL_NA, SPELL_NA, 3, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_TELEPORT, SFLAG_DUNGEON, 13, IS_CAST8, MIS_RUNELIGHT, 0, 0, 0, 0, 0, 200, ALIGN64 }, /*SPL_RUNENOVA*/ { 0, STYPE_LIGHTNING, 11, "Nova", SPELL_NA, SPELL_NA, 7, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_TELEPORT, SFLAG_DUNGEON, 42, IS_CAST8, MIS_RUNENOVA, 0, 0, 0, 0, 0, 400, ALIGN64 }, -/*SPL_RUNEWAVE*/ { 0, STYPE_FIRE, 14, "Wave", SPELL_NA, SPELL_NA, 7, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_TELEPORT, SFLAG_DUNGEON, 42, IS_CAST8, MIS_RUNEWAVE, 0, 0, 0, 0, 0, 500, ALIGN64 }, -/*SPL_RUNESTONE*/ { 0, STYPE_MAGIC, 8, "Stone", SPELL_NA, SPELL_NA, 7, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_TELEPORT, SFLAG_DUNGEON, 25, IS_CAST8, MIS_RUNESTONE, 0, 0, 0, 0, 0, 300, ALIGN64 }, +/*SPL_RUNEWAVE*/ { 0, STYPE_FIRE, 14, "Fire Wave", SPELL_NA, SPELL_NA, 7, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_TELEPORT, SFLAG_DUNGEON, 42, IS_CAST8, MIS_RUNEWAVE, 0, 0, 0, 0, 0, 500, ALIGN64 }, +/*SPL_RUNESTONE*/ { 0, STYPE_MAGIC, 8, "Stone Curse", SPELL_NA, SPELL_NA, 7, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_TELEPORT, SFLAG_DUNGEON, 25, IS_CAST8, MIS_RUNESTONE, 0, 0, 0, 0, 0, 300, ALIGN64 }, #endif // clang-format on }; From 9287f3618da1a9f4ac28b2e8b93a984dc2bb3944 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 11 Jul 2024 12:07:46 +0200 Subject: [PATCH 331/596] comment out an unused function (PortalOnLevel) --- Source/portal.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/portal.cpp b/Source/portal.cpp index 92c60c23dc9..55f7b8c059b 100644 --- a/Source/portal.cpp +++ b/Source/portal.cpp @@ -70,10 +70,10 @@ void ActivatePortal(int pidx, int x, int y, int bLevel) portals[pidx]._rlevel = bLevel; } -static bool PortalOnLevel(int pidx) -{ - return portals[pidx]._rlevel == currLvl._dLevelIdx || currLvl._dLevelIdx == DLV_TOWN; -} +//static bool PortalOnLevel(int pidx) +//{ +// return portals[pidx]._rlevel == currLvl._dLevelIdx || currLvl._dLevelIdx == DLV_TOWN; +//} void RemovePortalMissile(int pidx) { From 1a8c5a3b10a415789d55704b1a19659ac96cd2b8 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 11 Jul 2024 12:08:59 +0200 Subject: [PATCH 332/596] eliminate unused locals --- Source/monster.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index edc1df46692..bd39070b90b 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -973,7 +973,7 @@ static int MonPackSpace(int dx, int dy, int px, int py, bool (&visited)[MON_PACK static void PlaceUniqueMonst(int uniqindex, int mtidx) { - int xp, yp, x, y; + int xp, yp; int count2; int mnum, count; From eef8597865ef4386efabce802f5bee8ebf879ba7 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 11 Jul 2024 12:14:48 +0200 Subject: [PATCH 333/596] minor MAI-optimizations (Sneak, Counselor) --- Source/monster.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index bd39070b90b..f7c57838ca0 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3212,7 +3212,6 @@ void MAI_Sneak(int mnum) MonEnemyInfo(mnum); // assert(!(mon->_mFlags & MFLAG_CAN_OPEN_DOOR)); dist = currEnemyInfo._meRealDist; - md = currEnemyInfo._meLastDir; range = 7 - mon->_mAI.aiInt; if (range < 4) range = 4; @@ -3230,9 +3229,10 @@ void MAI_Sneak(int mnum) mon->_mgoal = MGOAL_NORMAL; } } + md = currEnemyInfo._meLastDir; if (mon->_mgoal != MGOAL_NORMAL) { // assert(mon->_mgoal == MGOAL_RETREAT); - md = OPPOSITE(currEnemyInfo._meLastDir); + md = OPPOSITE(md); if (mon->_mType == MT_BSNEAK) { //md = random_(112, 2) != 0 ? left[md] : right[md]; md = (md + 2 * random_(112, 2) - 1) & 7; @@ -4067,7 +4067,7 @@ void MAI_Counselor(int mnum) if (dist >= 2) { if (v < 5 * (mon->_mAI.aiInt + 10) && EnemyInLine(mnum)) { MonStartRAttack(mnum, mon->_mAI.aiParam1); - } else if (random_(124, 100) < 30 && mon->_msquelch == SQUELCH_MAX) { + } else if (random_(124, 128) < 39 && mon->_msquelch == SQUELCH_MAX) { #if DEBUG assert((mon->_mAnims[MA_SPECIAL].maFrames - 1) * mon->_mAnims[MA_SPECIAL].maFrameLen * 2 + (mon->_mAnims[MA_WALK].maFrames - 1) * mon->_mAnims[MA_WALK].maFrameLen * (6 + 4) < SQUELCH_MAX - SQUELCH_LOW); From 223f9deeca3f6aad3161b1ef55a80bdfd5cedf18 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 11 Jul 2024 12:17:25 +0200 Subject: [PATCH 334/596] add errands (custom levels) --- Source/automap.cpp | 3 +- Source/diablo.cpp | 1 + Source/drlg_l1.cpp | 47 +++++++++++++++++++++++-- Source/drlg_l2.cpp | 27 ++++++++++++++- Source/drlg_l3.cpp | 45 +++++++++++++++++++++++- Source/drlg_l4.cpp | 37 +++++++++++++++++++- Source/gamemenu.cpp | 2 +- Source/gendung.cpp | 2 +- Source/interfac.cpp | 56 ++++++++++++++++++++++++------ Source/loadsave.cpp | 6 ++++ Source/miniwin/miniwin.h | 1 + Source/monster.cpp | 39 +++++++++++++-------- Source/msg.cpp | 74 ++++++++++++++++++++++++++++++++++++++-- Source/msg.h | 4 +++ Source/multi.cpp | 2 +- Source/objects.cpp | 2 +- Source/palette.cpp | 2 +- Source/questdat.cpp | 2 +- Source/questdat.h | 2 +- Source/quests.cpp | 4 ++- Source/quests.h | 8 +++-- Source/stores.cpp | 48 ++++++++++++++++++++++++-- Source/themes.cpp | 6 ++-- Source/trigs.cpp | 4 +++ docs/CHANGELOG.md | 1 + enums.h | 7 +++- structs.h | 27 ++++++++++++++- 27 files changed, 408 insertions(+), 51 deletions(-) diff --git a/Source/automap.cpp b/Source/automap.cpp index ea5f2e57058..773ddb32a81 100644 --- a/Source/automap.cpp +++ b/Source/automap.cpp @@ -430,7 +430,8 @@ static BYTE GetAutomapType(int x, int y, bool view) */ static void DrawAutomapText() { - PrintGameStr(SCREEN_X + 8, SCREEN_Y + 20, AllLevels[currLvl._dLevelIdx].dLevelName, COL_GOLD); + if (!currLvl._dDynLvl) + PrintGameStr(SCREEN_X + 8, SCREEN_Y + 20, AllLevels[currLvl._dLevelNum].dLevelName, COL_GOLD); } /** diff --git a/Source/diablo.cpp b/Source/diablo.cpp index 736b53cee0c..cb2395d6b66 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -1169,6 +1169,7 @@ static void GameWndProc(const Dvl_Event* e) case DVL_DWM_PREVLVL: case DVL_DWM_SETLVL: case DVL_DWM_RTNLVL: + case DVL_DWM_DYNLVL: case DVL_DWM_PORTLVL: case DVL_DWM_TWARPDN: case DVL_DWM_TWARPUP: diff --git a/Source/drlg_l1.cpp b/Source/drlg_l1.cpp index 61ed491a9e8..edac04b515d 100644 --- a/Source/drlg_l1.cpp +++ b/Source/drlg_l1.cpp @@ -55,6 +55,33 @@ static const BYTE L1BTYPES[207] = { 0, 0, 0, 0, 0, 0, 0 // clang-format on }; +/** Miniset: Entry point of the dynamic maps. */ +const BYTE L1DYNENTRY[] = { + // clang-format off + 3, 3, // width, height -- larger miniset to prevent theme-room placement + + 2, 2, 2, // search + 13, 13, 13, + 13, 13, 13, + + 0, 0, 0, // replace + 0, 134, 0, + 0, 0, 0, + // clang-format on +}; +#ifdef HELLFIRE +const BYTE L5DYNENTRY[] = { + // clang-format off + 2, 2, // width, height + + 2, 2, // search + 13, 13, + + 0, 0, // replace + 195, 0, + // clang-format on +}; +#endif /** Miniset: stairs up on a corner wall. */ //const BYTE STAIRSUP[] = { // // clang-format off @@ -2616,6 +2643,22 @@ static void DRLG_L1() L1FillChambers(); L1AddWall(); L1ClearChamberFlags(); + if (currLvl._dDynLvl) { +#ifdef HELLFIRE + POS32 warpPos = DRLG_PlaceMiniSet(currLvl._dType == DTYPE_CRYPT ? L5DYNENTRY : L1DYNENTRY); +#else + POS32 warpPos = DRLG_PlaceMiniSet(L1DYNENTRY); +#endif + if (warpPos.x < 0) { + continue; + } + pWarps[DWARP_ENTRY]._wx = warpPos.x; + pWarps[DWARP_ENTRY]._wy = warpPos.y; + pWarps[DWARP_ENTRY]._wx = 2 * pWarps[DWARP_ENTRY]._wx + DBORDERX + 2; + pWarps[DWARP_ENTRY]._wy = 2 * pWarps[DWARP_ENTRY]._wy + DBORDERY + 1; + pWarps[DWARP_ENTRY]._wtype = WRPT_CIRCLE; + break; + } if (placeWater) { POS32 warpPos = DRLG_PlaceMiniSet(PWATERIN); if (warpPos.x < 0) { @@ -2739,7 +2782,7 @@ static void DRLG_L1() DRLG_L5PlaceRndSet(L5PREVERTWALL, 100); DRLG_L5PlaceRndSet(L5PREHORIZWALL, 100); DRLG_L5PlaceRndSet(L5RNDLFLOOR1, 60); - switch (currLvl._dLevelIdx) { + switch (currLvl._dLevelNum) { case DLV_CRYPT1: DRLG_L5Crypt_pattern2(30); DRLG_L5Crypt_pattern3(15); @@ -3197,7 +3240,7 @@ static void LoadL1Dungeon(const LevelData* lds) void CreateL1Dungeon() { - const LevelData* lds = &AllLevels[currLvl._dLevelIdx]; + const LevelData* lds = &AllLevels[currLvl._dLevelNum]; if (lds->dSetLvl) { LoadL1Dungeon(lds); diff --git a/Source/drlg_l2.cpp b/Source/drlg_l2.cpp index 0d1d7d3258d..9e0f9bcd661 100644 --- a/Source/drlg_l2.cpp +++ b/Source/drlg_l2.cpp @@ -80,6 +80,18 @@ const BYTE L2BTYPES[159] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, //150.. // clang-format on }; +/** Miniset: Entry point of the dynamic maps. */ +const BYTE L2DYNENTRY[] = { + // clang-format off + 2, 2, // width, height + + 2, 2, // search + 3, 3, + + 33, 0, // replace + 0, 0, + // clang-format on +}; /** Miniset: Stairs up. */ const BYTE L2USTAIRS[] = { // clang-format off @@ -2314,6 +2326,19 @@ static void DRLG_L2() DRLG_L2SetRoom(0); } + if (currLvl._dDynLvl) { + POS32 warpPos = DRLG_PlaceMiniSet(L2DYNENTRY); + if (warpPos.x < 0) { + continue; + } + + pWarps[DWARP_ENTRY]._wx = warpPos.x; + pWarps[DWARP_ENTRY]._wy = warpPos.y; + pWarps[DWARP_ENTRY]._wx = 2 * pWarps[DWARP_ENTRY]._wx + DBORDERX + 1; + pWarps[DWARP_ENTRY]._wy = 2 * pWarps[DWARP_ENTRY]._wy + DBORDERY + 1; + pWarps[DWARP_ENTRY]._wtype = WRPT_CIRCLE; + break; + } POS32 warpPos = DRLG_PlaceMiniSet(L2USTAIRS); // L2USTAIRS (5, 3) if (warpPos.x < 0) { continue; @@ -2720,7 +2745,7 @@ static void LoadL2Dungeon(const LevelData* lds) void CreateL2Dungeon() { - const LevelData* lds = &AllLevels[currLvl._dLevelIdx]; + const LevelData* lds = &AllLevels[currLvl._dLevelNum]; if (lds->dSetLvl) { LoadL2Dungeon(lds); diff --git a/Source/drlg_l3.cpp b/Source/drlg_l3.cpp index cd5cb8f67ac..a808a25a3f7 100644 --- a/Source/drlg_l3.cpp +++ b/Source/drlg_l3.cpp @@ -25,6 +25,32 @@ const BYTE themeTiles[NUM_DRT_TYPES] = { DEFAULT_MEGATILE_L3, 135, 134, 147, 146 * where each cell either contains a SW wall or it doesn't. */ const BYTE L3ConvTbl[16] = { BASE_MEGATILE_L3, 11, 3, 10, 1, 9, 12, 12, 6, 13, 4, 13, 2, 14, 5, 7 }; + +/** Miniset: Entry point of the dynamic maps. */ +const BYTE L3DYNENTRY[] = { + // clang-format off + 2, 2, // width, height + + 9, 7, // search + 9, 7, + + 109, 0, // replace + 0, 0, + // clang-format on +}; +#ifdef HELLFIRE +const BYTE L6DYNENTRY[] = { + // clang-format off + 2, 2, // width, height + + 9, 7, // search + 9, 7, + + 15, 0, // replace + 0, 0, + // clang-format on +}; +#endif /** Miniset: Stairs up. */ const BYTE L3USTAIRS[] = { // clang-format off @@ -2360,6 +2386,23 @@ static void DRLG_L3() if (pSetPieces[0]._spData != NULL) { // pSetPieces[0]._sptype != SPT_NONE DRLG_L3SetRoom(0); } + if (currLvl._dDynLvl) { +#ifdef HELLFIRE + POS32 warpPos = DRLG_PlaceMiniSet(currLvl._dType == DTYPE_NEST ? L6DYNENTRY : L3DYNENTRY); +#else + POS32 warpPos = DRLG_PlaceMiniSet(L3DYNENTRY); +#endif + if (warpPos.x < 0) { + continue; + } + + pWarps[DWARP_ENTRY]._wx = warpPos.x; + pWarps[DWARP_ENTRY]._wy = warpPos.y; + pWarps[DWARP_ENTRY]._wx = 2 * pWarps[DWARP_ENTRY]._wx + DBORDERX + 1; + pWarps[DWARP_ENTRY]._wy = 2 * pWarps[DWARP_ENTRY]._wy + DBORDERY; + pWarps[DWARP_ENTRY]._wtype = WRPT_CIRCLE; + break; + } #ifdef HELLFIRE if (currLvl._dType == DTYPE_NEST) { POS32 warpPos = DRLG_PlaceMiniSet(L6USTAIRS); // L6USTAIRS(1, 3) @@ -2596,7 +2639,7 @@ static void LoadL3Dungeon(const LevelData* lds) void CreateL3Dungeon() { - const LevelData* lds = &AllLevels[currLvl._dLevelIdx]; + const LevelData* lds = &AllLevels[currLvl._dLevelNum]; if (lds->dSetLvl) { LoadL3Dungeon(lds); diff --git a/Source/drlg_l4.cpp b/Source/drlg_l4.cpp index a703132ee5d..a7ef7a05449 100644 --- a/Source/drlg_l4.cpp +++ b/Source/drlg_l4.cpp @@ -26,6 +26,29 @@ const BYTE themeTiles[NUM_DRT_TYPES] = { DEFAULT_MEGATILE_L4, 1, 2, 1, 2, 9, 16, */ const BYTE L4ConvTbl[16] = { BASE_MEGATILE_L4, 6, 1, 6, 2, 6, 6, 6, 9, 6, 1, 6, 2, 6, 3, 6 }; +/** Miniset: Entry point of the dynamic maps. */ +const BYTE L4DYNENTRY1[] = { + // clang-format off + 2, 2, // width, height + + 2, 2, // search + 6, 6, + + 64, 0, // replace + 0, 0, + // clang-format on +}; +const BYTE L4DYNENTRY2[] = { + // clang-format off + 2, 2, // width, height + + 2, 6, // search + 2, 6, + + 63, 0, // replace + 0, 0, + // clang-format on +}; /** Miniset: Stairs up. */ const BYTE L4USTAIRS[] = { // clang-format off @@ -1992,6 +2015,18 @@ static void DRLG_L4() } L4AddWall(); + if (currLvl._dDynLvl) { + POS32 warpPos = DRLG_PlaceMiniSet(random_(141, 2) ? L4DYNENTRY1 : L4DYNENTRY2); + if (warpPos.x < 0) { + continue; + } + pWarps[DWARP_ENTRY]._wx = warpPos.x; + pWarps[DWARP_ENTRY]._wy = warpPos.y; + pWarps[DWARP_ENTRY]._wx = 2 * pWarps[DWARP_ENTRY]._wx + DBORDERX + 1; + pWarps[DWARP_ENTRY]._wy = 2 * pWarps[DWARP_ENTRY]._wy + DBORDERY + 1; + pWarps[DWARP_ENTRY]._wtype = WRPT_CIRCLE; + break; + } POS32 warpPos = DRLG_PlaceMiniSet(L4USTAIRS); // L4USTAIRS (5, 6) if (warpPos.x < 0) { continue; @@ -2328,7 +2363,7 @@ static void LoadL4Dungeon(const LevelData* lds) void CreateL4Dungeon() { - const LevelData* lds = &AllLevels[currLvl._dLevelIdx]; + const LevelData* lds = &AllLevels[currLvl._dLevelNum]; if (lds->dSetLvl) { LoadL4Dungeon(lds); diff --git a/Source/gamemenu.cpp b/Source/gamemenu.cpp index fcf8d5aac77..535c8c76250 100644 --- a/Source/gamemenu.cpp +++ b/Source/gamemenu.cpp @@ -248,7 +248,7 @@ static void gamemenu_music_volume(bool bActivate) } else { // assert(gbMusicOn); if (!musicOn) - music_start(AllLevels[currLvl._dLevelIdx].dMusic); + music_start(AllLevels[currLvl._dLevelNum].dMusic); } gamemenu_get_music(); PlaySFX(IS_TITLEMOV); diff --git a/Source/gendung.cpp b/Source/gendung.cpp index 3b653edee2d..f594d796ebd 100644 --- a/Source/gendung.cpp +++ b/Source/gendung.cpp @@ -141,7 +141,7 @@ void InitLvlDungeon() #if ASSET_MPL == 1 uint16_t blocks, *minFile, *pSubtile, *pPTmp; #endif - const LevelData* lds = &AllLevels[currLvl._dLevelIdx]; + const LevelData* lds = &AllLevels[currLvl._dLevelNum]; const LevelFileData* lfd = &levelfiledata[lds->dfindex]; static_assert((int)WRPT_NONE == 0, "InitLvlDungeon fills pWarps with 0 instead of WRPT_NONE values."); diff --git a/Source/interfac.cpp b/Source/interfac.cpp index 67155677a75..0bf0d06f74e 100644 --- a/Source/interfac.cpp +++ b/Source/interfac.cpp @@ -58,6 +58,7 @@ static void InitCutscene(unsigned int uMsg) lvl = currLvl._dLevelIdx; InitLvlCutscene(lvl); break; + case DVL_DWM_DYNLVL: case DVL_DWM_PORTLVL: sgpBackCel = CelLoadImage("Gendata\\Cutportl.CEL", PANEL_WIDTH); LoadPalette("Gendata\\Cutportl.pal"); @@ -192,6 +193,9 @@ static void CreateDungeon() void LoadGameLevel(int lvldir) { + extern int32_t sglGameSeed; + assert(sglGameSeed == glSeedTbl[currLvl._dLevelIdx] || currLvl._dDynLvl); + music_stop(); //if (pcursicon > CURSOR_HAND && pcursicon < CURSOR_FIRSTITEM) { // NewCursor(CURSOR_HAND); @@ -214,7 +218,7 @@ void LoadGameLevel(int lvldir) InitLvlItems(); // reset items IncProgress(); // "Create Dungeon" (6) - SetRndSeed(glSeedTbl[currLvl._dLevelIdx]); + // SetRndSeed(glSeedTbl[currLvl._dLevelIdx]); // fill pre: pSetPieces // fill in loop: dungeon, pWarps, uses drlgFlags, dungBlock // fill post: themeLoc, pdungeon, dPiece, dTransVal @@ -250,20 +254,49 @@ void LoadGameLevel(int lvldir) IncProgress(); // "Music start" (12) - music_start(AllLevels[currLvl._dLevelIdx].dMusic); + music_start(AllLevels[currLvl._dLevelNum].dMusic); } void EnterLevel(BYTE lvl) { int lvlBonus; + SetRndSeed(glSeedTbl[lvl]); currLvl._dLevelPlyrs = IsMultiGame ? gsDeltaData.ddLevelPlrs[lvl] : 1; currLvl._dLevelIdx = lvl; - currLvl._dLevel = AllLevels[lvl].dLevel; - currLvl._dSetLvl = AllLevels[lvl].dSetLvl; - currLvl._dType = AllLevels[lvl].dType; - currLvl._dDunType = AllLevels[lvl].dDunType; - lvlBonus = 0; + currLvl._dDynLvl = lvl >= NUM_FIXLVLS; + if (currLvl._dDynLvl) { + // select level + unsigned baseLevel = gDynLevels[lvl - NUM_FIXLVLS]._dnLevel; + // assert(baseLevel + HELL_LEVEL_BONUS < CF_LEVEL); + int availableLvls[NUM_FIXLVLS]; + int numLvls = 0; + for (int i = DLV_CATHEDRAL1; i < NUM_STDLVLS; i++) { + if (AllLevels[i].dLevel <= baseLevel /*&& AllLevels[i].dMonTypes[0] != MT_INVALID*/) { + availableLvls[numLvls] = i; + numLvls++; + } + } + lvl = DLV_CATHEDRAL1; + if (numLvls != 0) { + lvl = availableLvls[random_low(141, numLvls)]; + } else { + baseLevel = AllLevels[DLV_CATHEDRAL1].dLevel; + } + currLvl._dLevelNum = lvl; + currLvl._dLevel = AllLevels[lvl].dLevel; + currLvl._dSetLvl = false; // AllLevels[lvl].dSetLvl; + currLvl._dType = AllLevels[lvl].dType; + currLvl._dDunType = AllLevels[lvl].dDunType; + lvlBonus = baseLevel - AllLevels[lvl].dLevel; + } else { + currLvl._dLevelNum = lvl; + currLvl._dLevel = AllLevels[lvl].dLevel; + currLvl._dSetLvl = AllLevels[lvl].dSetLvl; + currLvl._dType = AllLevels[lvl].dType; + currLvl._dDunType = AllLevels[lvl].dDunType; + lvlBonus = 0; + } if (gnDifficulty == DIFF_NIGHTMARE) { lvlBonus += NIGHTMARE_LEVEL_BONUS; } else if (gnDifficulty == DIFF_HELL) { @@ -330,10 +363,11 @@ void ShowCutscene(unsigned uMsg) static_assert((int)DVL_DWM_PREVLVL - (int)DVL_DWM_NEXTLVL == (int)ENTRY_PREV - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted II."); static_assert((int)DVL_DWM_SETLVL - (int)DVL_DWM_NEXTLVL == (int)ENTRY_SETLVL - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted III."); static_assert((int)DVL_DWM_RTNLVL - (int)DVL_DWM_NEXTLVL == (int)ENTRY_RTNLVL - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted IV."); - static_assert((int)DVL_DWM_PORTLVL - (int)DVL_DWM_NEXTLVL == (int)ENTRY_PORTLVL - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted V."); - static_assert((int)DVL_DWM_TWARPDN - (int)DVL_DWM_NEXTLVL == (int)ENTRY_TWARPDN - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted VI."); - static_assert((int)DVL_DWM_TWARPUP - (int)DVL_DWM_NEXTLVL == (int)ENTRY_TWARPUP - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted VII."); - static_assert((int)DVL_DWM_RETOWN - (int)DVL_DWM_NEXTLVL == (int)ENTRY_RETOWN - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted VIII."); + static_assert((int)DVL_DWM_DYNLVL - (int)DVL_DWM_NEXTLVL == (int)ENTRY_DYNLVL - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted V."); + static_assert((int)DVL_DWM_PORTLVL - (int)DVL_DWM_NEXTLVL == (int)ENTRY_PORTLVL - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted VI."); + static_assert((int)DVL_DWM_TWARPDN - (int)DVL_DWM_NEXTLVL == (int)ENTRY_TWARPDN - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted VII."); + static_assert((int)DVL_DWM_TWARPUP - (int)DVL_DWM_NEXTLVL == (int)ENTRY_TWARPUP - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted VIII."); + static_assert((int)DVL_DWM_RETOWN - (int)DVL_DWM_NEXTLVL == (int)ENTRY_RETOWN - (int)ENTRY_MAIN, "Conversion from DVL_DWM_* to ENTRY_* in ShowCutscene must be adjusted IX."); } EnterLevel(myplr._pDunLevel); LoadGameLevel(lvldir); diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index a0afbb63f8c..adb46d28f08 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -765,6 +765,9 @@ void LoadGame() glSeedTbl[i] = ghs->vhSeeds[i]; } _CurrSeed = ghs->vhCurrSeed; + for (i = 0; i < NUM_DYNLVLS; i++) { + gDynLevels[i]._dnLevel = ghs->vhDynLvls[i].vdLevel; + } // load player-data _ViewX = ghs->vhViewX; _ViewY = ghs->vhViewY; @@ -1601,6 +1604,9 @@ void SaveGame() for (i = 0; i < NUM_LEVELS; i++) { ghs->vhSeeds[i] = glSeedTbl[i]; } + for (i = 0; i < NUM_DYNLVLS; i++) { + ghs->vhDynLvls[i].vdLevel = gDynLevels[i]._dnLevel; + } ghs->vhCurrSeed = GetRndSeed(); // save player-data ghs->vhViewX = ViewX; diff --git a/Source/miniwin/miniwin.h b/Source/miniwin/miniwin.h index 5738fed147c..818b42d56d0 100644 --- a/Source/miniwin/miniwin.h +++ b/Source/miniwin/miniwin.h @@ -41,6 +41,7 @@ typedef enum window_messages { DVL_DWM_PREVLVL, // dungeon -> previous level DVL_DWM_SETLVL, // dungeon -> setlevel DVL_DWM_RTNLVL, // setlevel -> dungeon + DVL_DWM_DYNLVL, // town -> custom dungeon DVL_DWM_PORTLVL, // portal (town <-> dungeon) DVL_DWM_TWARPDN, // town -> dungeon DVL_DWM_TWARPUP, // dungeon -> town diff --git a/Source/monster.cpp b/Source/monster.cpp index f7c57838ca0..87fd2ec32c7 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -494,14 +494,6 @@ void GetLevelMTypes() lvl = currLvl._dLevelIdx; //if (!currLvl._dSetLvl) { - if (lvl == DLV_HELL4) { - AddMonsterType(MT_BMAGE, TRUE); - AddMonsterType(MT_GBLACK, TRUE); - // AddMonsterType(MT_NBLACK, FALSE); - // AddMonsterType(uniqMonData[UMT_DIABLO].mtype, FALSE); - return; - } - #ifdef HELLFIRE if (lvl == uniqMonData[UMT_HORKDMN].muLevelIdx - 1) AddMonsterType(MT_HORKSPWN, TRUE); @@ -512,7 +504,6 @@ void GetLevelMTypes() if (lvl == uniqMonData[UMT_DEFILER].muLevelIdx) AddMonsterType(uniqMonData[UMT_DEFILER].mtype, FALSE); if (lvl == DLV_CRYPT4) { - AddMonsterType(MT_ARCHLICH, TRUE); // AddMonsterType(uniqMonData[UMT_NAKRUL].mtype, FALSE); } #endif @@ -548,6 +539,19 @@ void GetLevelMTypes() // AddMonsterType(uniqMonData[UMT_RED_VEX].mtype, FALSE); // assert(uniqMonData[UMT_RED_VEX].mtype == uniqMonData[UMT_BLACKJADE].mtype); //} + lvl = currLvl._dLevelNum; + if (lvl == DLV_HELL4) { + AddMonsterType(MT_BMAGE, TRUE); + AddMonsterType(MT_GBLACK, TRUE); + // AddMonsterType(MT_NBLACK, FALSE); + // AddMonsterType(uniqMonData[UMT_DIABLO].mtype, FALSE); + // return; + } +#ifdef HELLFIRE + if (lvl == DLV_CRYPT4) { + AddMonsterType(MT_ARCHLICH, TRUE); + } +#endif lds = &AllLevels[lvl]; for (nt = 0; nt < lengthof(lds->dMonTypes); nt++) { mtype = lds->dMonTypes[nt]; @@ -726,7 +730,7 @@ void WakeNakrul() void InitSummonedMonster(int mnum, int dir, int mtidx, int x, int y) { static_assert(DLV_TOWN == 0, "InitSummonedMonster skips the first entry glSeedTbl assuming the 'dynamic' seed is stored there."); - SetRndSeed(glSeedTbl[(mnum % (NUM_LEVELS - 1)) + 1]); + SetRndSeed(glSeedTbl[(mnum % (NUM_FIXLVLS - 1)) + 1]); InitMonster(mnum, dir, mtidx, x, y); monsters[mnum]._mFlags |= MFLAG_NOCORPSE | MFLAG_NODROP; } @@ -1016,10 +1020,14 @@ static void PlaceUniques() for (u = 0; uniqMonData[u].mtype != MT_INVALID; u++) { if (uniquetrans >= NUM_COLOR_TRNS) continue; - if (uniqMonData[u].muLevelIdx != currLvl._dLevelIdx) + /*if (uniqMonData[u].muLevelIdx != currLvl._dLevelIdx) continue; if (uniqMonData[u].mQuestId != Q_INVALID && quests[uniqMonData[u].mQuestId]._qactive == QUEST_NOTAVAIL) + continue;*/ + if (uniqMonData[u].muLevelIdx != currLvl._dLevelNum) + continue; + if (uniqMonData[u].mQuestId != Q_INVALID && !QuestStatus(uniqMonData[u].mQuestId)) continue; for (mt = 0; mt < nummtypes; mt++) { if (mapMonTypes[mt].cmType == uniqMonData[u].mtype) { @@ -1124,7 +1132,7 @@ void InitMonsters() for (yy = DBORDERY; yy < DSIZEY + DBORDERY; yy++) if ((nSolidTable[dPiece[xx][yy]] | (dFlags[xx][yy] & (BFLAG_ALERT | BFLAG_MON_PROTECT))) == 0) na++; - na = na * AllLevels[currLvl._dLevelIdx].dMonDensity / 32; + na = na * AllLevels[currLvl._dLevelNum].dMonDensity / 32; numplacemonsters = na / 32; totalmonsters = nummonsters + numplacemonsters; @@ -2070,7 +2078,7 @@ static void SpawnLoot(int mnum, bool sendmsg) my = mon->_my; switch (mon->_muniqtype - 1) { case UMT_GARBUD: - assert(QuestStatus(Q_GARBUD)); + // assert(QuestStatus(Q_GARBUD)); CreateTypeItem(mx, my, CFDQ_GOOD, ITYPE_MACE, IMISC_NONE, sendmsg ? ICM_SEND_FLIP : ICM_DUMMY); return; case UMT_LAZARUS: @@ -2086,19 +2094,20 @@ static void SpawnLoot(int mnum, bool sendmsg) } break; case UMT_ZAMPHIR: - if (quests[Q_MUSHROOM]._qactive != QUEST_NOTAVAIL) { + if (quests[Q_MUSHROOM]._qactive != QUEST_NOTAVAIL && currLvl._dLevelIdx == uniqMonData[UMT_ZAMPHIR].muLevelIdx) { SpawnQuestItemAt(IDI_BRAIN, mx, my, sendmsg ? ICM_SEND_FLIP : ICM_DUMMY); return; } break; #ifdef HELLFIRE case UMT_HORKDMN: - if (quests[Q_GIRL]._qactive != QUEST_NOTAVAIL) { + if (quests[Q_GIRL]._qactive != QUEST_NOTAVAIL && currLvl._dLevelIdx == uniqMonData[UMT_HORKDMN].muLevelIdx) { SpawnQuestItemAt(IDI_THEODORE, mx, my, sendmsg ? ICM_SEND_FLIP : ICM_DUMMY); return; } break; case UMT_DEFILER: + // assert(QuestStatus(Q_DEFILER)); //if (IsSFXPlaying(USFX_DEFILER8)) StopStreamSFX(); // quests[Q_DEFILER]._qlog = FALSE; diff --git a/Source/msg.cpp b/Source/msg.cpp index b6fe92e1bb9..c65117a2bf4 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -263,8 +263,9 @@ static BYTE* DeltaExportJunk(BYTE* dst) { DDPortal* pDPortal; DDQuest* pDQuest; + DDDynLevel* pDLevel; int i; - constexpr int junkDataSize = MAXPORTAL * sizeof(DDPortal) + NUM_QUESTS * sizeof(DDQuest) + sizeof(gsDeltaData.ddJunk); + constexpr int junkDataSize = MAXPORTAL * sizeof(DDPortal) + NUM_QUESTS * sizeof(DDQuest) + NUM_DYNLVLS * sizeof(DDDynLevel) + sizeof(gsDeltaData.ddJunk); static_assert(sizeof(gsDeltaData.ddSendRecvPkt.apMsg.tpData.content) >= junkDataSize, "DJunk does not fit to the buffer in DeltaExportJunk."); // export portals @@ -283,6 +284,14 @@ static BYTE* DeltaExportJunk(BYTE* dst) pDQuest->qvar1 = quests[i]._qvar1; } dst = (BYTE*)pDQuest; + // export dynamic levels + pDLevel = (DDDynLevel*)dst; + for (i = 0; i < NUM_DYNLVLS; i++) { + pDLevel->dlSeed = glSeedTbl[NUM_FIXLVLS + i]; + pDLevel->dlLevel = gDynLevels[i]._dnLevel; + pDLevel++; + } + dst = (BYTE*)pDLevel; // export golems memcpy(dst, &gsDeltaData.ddJunk, sizeof(gsDeltaData.ddJunk)); dst += sizeof(gsDeltaData.ddJunk); @@ -294,9 +303,10 @@ static void DeltaImportJunk() { DDPortal* pDPortal; DDQuest* pDQuest; + DDDynLevel* pDLevel; int i; BYTE* src = gsDeltaData.ddSendRecvPkt.apMsg.tpData.content; - constexpr int junkDataSize = MAXPORTAL * sizeof(DDPortal) + NUM_QUESTS * sizeof(DDQuest) + sizeof(gsDeltaData.ddJunk); + constexpr int junkDataSize = MAXPORTAL * sizeof(DDPortal) + NUM_QUESTS * sizeof(DDQuest) + NUM_DYNLVLS * sizeof(DDDynLevel) + sizeof(gsDeltaData.ddJunk); // static_assert(sizeof(gsDeltaData.ddSendRecvPkt.apMsg.tpData.content) >= sizeof(gsDeltaData.ddJunk), "DJunk does not fit to the buffer in DeltaImportJunk."); static_assert(sizeof(gsDeltaData.ddSendRecvPkt.apMsg.tpData.content) >= junkDataSize, "DJunk does not fit to the buffer in DeltaImportJunk."); @@ -318,6 +328,14 @@ static void DeltaImportJunk() quests[i]._qvar1 = pDQuest->qvar1; } src = (BYTE*)pDQuest; + // export dynamic levels + pDLevel = (DDDynLevel*)src; + for (i = 0; i < NUM_DYNLVLS; i++) { + glSeedTbl[NUM_FIXLVLS + i] = pDLevel->dlSeed; + gDynLevels[i]._dnLevel = pDLevel->dlLevel; + pDLevel++; + } + src = (BYTE*)pDLevel; // update golems memcpy(&gsDeltaData.ddJunk, src, sizeof(gsDeltaData.ddJunk)); // src += sizeof(gsDeltaData.ddJunk); @@ -2177,6 +2195,17 @@ void NetSendCmdNewLvl(BYTE fom, BYTE bLevel) NetSendChunk((BYTE*)&cmd, sizeof(cmd)); } +void NetSendCmdCreateLvl(DWORD seed) +{ + TCmdCreateLvl cmd; + + cmd.bCmd = CMD_CREATELVL; + cmd.clPlayers = gbActivePlayers; // TODO: could be done in On_CREATELVL + cmd.clSeed = seed; + + NetSendChunk((BYTE*)&cmd, sizeof(cmd)); +} + void NetSendCmdString(unsigned int pmask) { int dwStrLen; @@ -2695,6 +2724,45 @@ static unsigned On_NEWLVL(TCmd* pCmd, int pnum) return sizeof(*cmd); } +static unsigned On_CREATELVL(TCmd* pCmd, int pnum) +{ + TCmdCreateLvl* cmd = (TCmdCreateLvl*)pCmd; + BYTE bLevel, bPlayers; + for (bLevel = NUM_FIXLVLS; bLevel < NUM_LEVELS; bLevel++) { + int i = 0; + for ( ; i < MAX_PLRS; i++) { + if (plx(i)._pActive && plx(i)._pDunLevel == bLevel) + break; + if (portals[i]._rlevel == bLevel) + break; + } + if (i == MAX_PLRS) { + break; + } + } + bPlayers = cmd->clPlayers; + net_assert(bLevel < NUM_LEVELS); + net_assert(bPlayers != 0 && bPlayers < MAX_PLRS); + // reset level delta (entities + automap) + // - multi + static_assert((int)DCMD_INVALID == 0, "On_CREATELVL initializes the items with zero, assuming the invalid command to be zero."); + static_assert((int)DCMD_MON_INVALID == 0, "On_CREATELVL initializes the monsters with zero, assuming the invalid command to be zero."); + static_assert((int)CMD_SYNCDATA == 0, "On_CREATELVL initializes the objects with zero, assuming none of the valid commands for an object to be zero."); + memset(&gsDeltaData.ddLevel[bLevel], 0, sizeof(DDLevel)); + memset(&gsDeltaData.ddLocal[bLevel], 0, sizeof(LocalLevel)); + // - single + guLvlVisited &= ~LEVEL_MASK(bLevel); + // setup the new level + glSeedTbl[bLevel] = cmd->clSeed; + gsDeltaData.ddLevelPlrs[bLevel] = bPlayers; + static_assert(MAXCHARLEVEL + HELL_LEVEL_BONUS < CF_LEVEL, "On_CREATELVL might initialize a level which is too high for item-drops."); + gDynLevels[bLevel - NUM_FIXLVLS]._dnLevel = plr._pLevel; + + StartNewLvl(pnum, DVL_DWM_DYNLVL, bLevel); + + return sizeof(*cmd); +} + static unsigned On_USEPORTAL(TCmd* pCmd, int pnum) { TCmdBParam1* cmd = (TCmdBParam1*)pCmd; @@ -4453,6 +4521,8 @@ unsigned ParseCmd(int pnum, TCmd* pCmd) return On_ACTIVATEPORTAL(pCmd, pnum); case CMD_NEWLVL: return On_NEWLVL(pCmd, pnum); + case CMD_CREATELVL: + return On_CREATELVL(pCmd, pnum); case CMD_USEPORTAL: return On_USEPORTAL(pCmd, pnum); case CMD_RETOWN: diff --git a/Source/msg.h b/Source/msg.h index 1651890da7a..67d55c839ab 100644 --- a/Source/msg.h +++ b/Source/msg.h @@ -102,6 +102,10 @@ void SendStoreCmd2(BYTE bStoreId); * @param bLevel: the destination level */ void NetSendCmdNewLvl(BYTE fom, BYTE bLevel); +/** Initiate level creation and change. + * @param seed: the seed of the level + */ +void NetSendCmdCreateLvl(DWORD seed); void NetSendCmdString(unsigned int pmask); unsigned ParseMsg(int pnum, TCmd* pCmd); unsigned ParseCmd(int pnum, TCmd* pCmd); diff --git a/Source/multi.cpp b/Source/multi.cpp index 3d6ee062e1a..ab4d1e4244b 100644 --- a/Source/multi.cpp +++ b/Source/multi.cpp @@ -816,7 +816,7 @@ static bool multi_init_game(bool bSinglePlayer, _uigamedata& gameData) SetRndSeed(gameData.aeSeed); sgbSentThisCycle = gameData.aeTurn; - for (i = 0; i < NUM_LEVELS; i++) { + for (i = 0; i < NUM_FIXLVLS; i++) { seed = NextRndSeed(); seed = (seed >> 8) | (seed << 24); // _rotr(seed, 8) glSeedTbl[i] = seed; diff --git a/Source/objects.cpp b/Source/objects.cpp index a217624419a..40794c1076a 100644 --- a/Source/objects.cpp +++ b/Source/objects.cpp @@ -976,7 +976,7 @@ void InitObjects() for (int yy = DBORDERY; yy < DSIZEY + DBORDERY; yy++) if ((nSolidTable[dPiece[xx][yy]] | (dFlags[xx][yy] & BFLAG_OBJ_PROTECT)) == 0) na++; - na = na * AllLevels[currLvl._dLevelIdx].dObjDensity / 32; + na = na * AllLevels[currLvl._dLevelNum].dObjDensity / 32; if (lvlMask & objectdata[OBJ_SARC].oLvlTypes) { static_assert(DSIZEX * DSIZEY < 0x7FFF, "InitObjects uses RandRangeLow I."); diff --git a/Source/palette.cpp b/Source/palette.cpp index 28c7976cec4..4175c20b472 100644 --- a/Source/palette.cpp +++ b/Source/palette.cpp @@ -83,7 +83,7 @@ void LoadLvlPalette() char szFileName[DATA_ARCHIVE_MAX_PATH]; rv = RandRange(1, 4); - snprintf(szFileName, sizeof(szFileName), AllLevels[currLvl._dLevelIdx].dPalName, rv); + snprintf(szFileName, sizeof(szFileName), AllLevels[currLvl._dLevelNum].dPalName, rv); LoadPalette(szFileName); } diff --git a/Source/questdat.cpp b/Source/questdat.cpp index 34bf96769f0..2a134ba94b3 100644 --- a/Source/questdat.cpp +++ b/Source/questdat.cpp @@ -7,7 +7,7 @@ DEVILUTION_BEGIN_NAMESPACE -const LevelData AllLevels[NUM_LEVELS] = { +const LevelData AllLevels[NUM_FIXLVLS] = { // clang-format off // dLevel, dSetLvl, dType, dDunType, dMusic, dfindex, dMicroTileLen, dBlocks, dLevelName, /*DLV_TOWN*/ { 0, FALSE, DTYPE_TOWN, DGT_TOWN, TMUSIC_TOWN, LFILE_TOWN, 16, 16, "Tristram", diff --git a/Source/questdat.h b/Source/questdat.h index a2b76f91997..f70441015a4 100644 --- a/Source/questdat.h +++ b/Source/questdat.h @@ -12,7 +12,7 @@ DEVILUTION_BEGIN_NAMESPACE extern "C" { #endif -extern const LevelData AllLevels[NUM_LEVELS]; +extern const LevelData AllLevels[NUM_FIXLVLS]; extern const LevelFileData levelfiledata[NUM_LFILE_TYPES]; extern const QuestData questlist[NUM_QUESTS]; extern const SetPieceData setpiecedata[NUM_SPT_TYPES]; diff --git a/Source/quests.cpp b/Source/quests.cpp index 1c9cb3e91c3..56ee9f41024 100644 --- a/Source/quests.cpp +++ b/Source/quests.cpp @@ -13,6 +13,8 @@ DEVILUTION_BEGIN_NAMESPACE /** The pseudo random seeds to generate the levels. */ uint32_t glSeedTbl[NUM_LEVELS]; +/** Contains the informations to recreate the dynamic levels. */ +DynLevelStruct gDynLevels[NUM_DYNLVLS]; /** Contains the quests of the current game. */ QuestStruct quests[NUM_QUESTS]; /** Quest-log panel CEL */ @@ -27,7 +29,7 @@ unsigned numqlines; unsigned qline; BYTE gbTownWarps; BYTE gbWaterDone; -static_assert(NUM_LEVELS <= 32, "guLvlVisited can not maintain too many levels."); +/** the masks of the visited levels */ uint32_t guLvlVisited; int gnSfxDelay; int gnSfxNum; diff --git a/Source/quests.h b/Source/quests.h index 724605239f4..56b7c847fa1 100644 --- a/Source/quests.h +++ b/Source/quests.h @@ -13,6 +13,7 @@ extern "C" { #endif extern uint32_t glSeedTbl[NUM_LEVELS]; +extern DynLevelStruct gDynLevels[NUM_DYNLVLS]; extern BYTE gbTownWarps; extern BYTE gbWaterDone; extern uint32_t guLvlVisited; @@ -20,8 +21,11 @@ extern int gnSfxDelay; extern int gnSfxNum; extern QuestStruct quests[NUM_QUESTS]; -#define LEVEL_MASK(x) ((uint32_t)1 << (x)) -#define IsLvlVisited(x) ((guLvlVisited & LEVEL_MASK(x)) != 0) +#define LEVEL_MASK(x) (x < 32 ? (uint32_t)1 << (x) : 0) + +static_assert(NUM_FIXLVLS + 2 <= 32, "guLvlVisited can not maintain too many levels."); +// test whether the player has visited the given level (can not be used on the dynamic levels in multiplayer games) +#define IsLvlVisited(x) ((guLvlVisited & ((uint32_t)1 << (x))) != 0) void InitQuests(); void InitQuestGFX(); diff --git a/Source/stores.cpp b/Source/stores.cpp index ecce51fe890..886f77f149f 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -60,9 +60,12 @@ DEVILUTION_BEGIN_NAMESPACE #define STORE_DRUNK_GOSSIP 12 #define STORE_DRUNK_EXIT 18 -#define STORE_PRIEST_GOSSIP 12 +#define STORE_PRIEST_ERRAND 12 #define STORE_PRIEST_EXIT 18 +#define STORE_ERRAND_YES 18 +#define STORE_ERRAND_NO 20 + // service prices #define STORE_ID_PRICE 100 #define STORE_PEGBOY_PRICE 50 @@ -1153,11 +1156,21 @@ static void S_StartPriest() gbHasScroll = false; AddSText(0, 2, true, "Tremain the Priest", COL_GOLD, false); AddSText(0, 9, true, "Would you like to:", COL_GOLD, false); - //AddSText(0, STORE_PRIEST_GOSSIP, true, "Talk to Tremain", COL_BLUE, true); + AddSText(0, STORE_PRIEST_ERRAND, true, "Run errand", COL_BLUE, true); AddSText(0, STORE_PRIEST_EXIT, true, "Say Goodbye", COL_WHITE, true); AddSLine(5); } +static void S_StartErrand() +{ + AddSText(0, 2, true, "Tremain the Priest", COL_GOLD, false); + // AddSText(0, 12, true, "Would you like to", COL_WHITE, false); + AddSText(0, 14, true, "Go on an errand?", COL_WHITE, false); + AddSText(0, STORE_ERRAND_YES, true, "Yes", COL_WHITE, true); + AddSText(0, STORE_ERRAND_NO, true, "No", COL_WHITE, true); + AddSLine(5); +} + void StartStore(int s) { int i; @@ -1241,6 +1254,9 @@ void StartStore(int s) case STORE_PRIEST: S_StartPriest(); break; + case STORE_ERRAND: + S_StartErrand(); + break; default: ASSUME_UNREACHABLE break; @@ -1375,6 +1391,9 @@ void STextESC() stextsel = stextlhold; stextsidx = stextvhold; break; + case STORE_ERRAND: + StartStore(STORE_PRIEST); + break; default: ASSUME_UNREACHABLE break; @@ -2344,6 +2363,12 @@ static void S_PriestEnter() stextshold = STORE_PRIEST; StartStore(STORE_GOSSIP); break;*/ + case STORE_PRIEST_ERRAND: + stextlhold = STORE_PRIEST_ERRAND; + talker = TOWN_PRIEST; + stextshold = STORE_PRIEST; + StartStore(STORE_ERRAND); + break; case STORE_PRIEST_EXIT: stextflag = STORE_NONE; break; @@ -2353,6 +2378,22 @@ static void S_PriestEnter() } } +static void S_ErrandEnter() +{ + switch (stextsel) { + case STORE_ERRAND_YES: + NetSendCmdCreateLvl(GetRndSeed()); + stextflag = STORE_NONE; + break; + case STORE_ERRAND_NO: + StartStore(STORE_PRIEST); + break; + default: + ASSUME_UNREACHABLE + break; + } +} + void STextEnter() { assert(!gbQtextflag); @@ -2429,6 +2470,9 @@ void STextEnter() case STORE_PRIEST: S_PriestEnter(); break; + case STORE_ERRAND: + S_ErrandEnter(); + break; case STORE_WAIT: return; default: diff --git a/Source/themes.cpp b/Source/themes.cpp index 292c548ff64..066ef474c05 100644 --- a/Source/themes.cpp +++ b/Source/themes.cpp @@ -313,7 +313,7 @@ void InitThemes() int i, j; // assert(currLvl._dType != DTYPE_TOWN); - if (currLvl._dLevelIdx >= DLV_HELL4) // there are no themes in hellfire (and on diablo-level) + if (currLvl._dLevelNum >= DLV_HELL4) // there are no themes in hellfire (and on diablo-level) return; // TODO: use dType instead @@ -360,7 +360,7 @@ void HoldThemeRooms() { int i, x, y, x1, y1, x2, y2; // assert(currLvl._dType != DTYPE_TOWN); - // assert(currLvl._dLevelIdx < DLV_HELL4 || numthemes == 0); // there are no themes in hellfire (and on diablo-level) + // assert(currLvl._dLevelNum < DLV_HELL4 || numthemes == 0); // there are no themes in hellfire (and on diablo-level) for (i = numthemes - 1; i >= 0; i--) { x1 = themes[i]._tsx1; @@ -834,7 +834,7 @@ void CreateThemeRooms() int i; BYTE tv; // assert(currLvl._dType != DTYPE_TOWN); - // assert(currLvl._dLevelIdx < DLV_HELL4 || numthemes == 0); // there are no themes in hellfire (and on diablo-level) + // assert(currLvl._dLevelNum < DLV_HELL4 || numthemes == 0); // there are no themes in hellfire (and on diablo-level) //gbInitObjFlag = true; for (i = 0; i < numthemes; i++) { diff --git a/Source/trigs.cpp b/Source/trigs.cpp index 060f7fbd66c..6913fc39169 100644 --- a/Source/trigs.cpp +++ b/Source/trigs.cpp @@ -57,6 +57,9 @@ static void InitTownTriggers() static void InitDunTriggers() { numtrigs = 0; + if (currLvl._dDynLvl) { + return; + } for (int i = lengthof(pWarps) - 1; i >= 0; i--) { if (pWarps[i]._wx == 0) { continue; @@ -207,6 +210,7 @@ void InitView(int entry) type = DWARP_EXIT; break; case ENTRY_SETLVL: + case ENTRY_DYNLVL: type = DWARP_ENTRY; break; case ENTRY_RTNLVL: diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 413a3a4899b..4bfdd6f119c 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -67,6 +67,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - better rewards on higher difficulties - HP/Exp/Loot from monsters are depending on the number of players - limited offers in stores/wirt +- added errands (custom levels) ### System - Lockstep networking - Adaptive netupdate diff --git a/enums.h b/enums.h index f2395f3724d..8933f42e2ce 100644 --- a/enums.h +++ b/enums.h @@ -3289,7 +3289,9 @@ typedef enum _setlevels { SL_POISONWATER, SL_VILEBETRAYER, NUM_SETLVLS = SL_VILEBETRAYER - NUM_STDLVLS + 1, - NUM_LEVELS = NUM_STDLVLS + NUM_SETLVLS, + NUM_FIXLVLS = NUM_STDLVLS + NUM_SETLVLS, + NUM_DYNLVLS = 2 * MAX_PLRS, + NUM_LEVELS = NUM_STDLVLS + NUM_SETLVLS + NUM_DYNLVLS, DLV_INVALID = NUM_LEVELS } _setlevels; @@ -3743,6 +3745,7 @@ typedef enum lvl_entry { ENTRY_PREV, ENTRY_SETLVL, ENTRY_RTNLVL, + ENTRY_DYNLVL, ENTRY_PORTLVL, ENTRY_TWARPDN, ENTRY_TWARPUP, @@ -3890,6 +3893,7 @@ typedef enum _cmd_id { CMD_TELEKINOID, CMD_ACTIVATEPORTAL, CMD_NEWLVL, + CMD_CREATELVL, CMD_USEPORTAL, CMD_RETOWN, CMD_JOINLEVEL, @@ -4331,6 +4335,7 @@ typedef enum talk_id { STORE_DRUNK, STORE_BARMAID, STORE_PRIEST, + STORE_ERRAND, STORE_WAIT, } talk_id; diff --git a/structs.h b/structs.h index a0fc0106875..436b74e45a3 100644 --- a/structs.h +++ b/structs.h @@ -1129,11 +1129,16 @@ typedef struct PkPlayerStruct { ////////////////////////////////////////////////// #pragma pack(push, 1) +typedef struct LSaveGameDynLvlStruct { + BYTE vdLevel; +} LSaveGameDynLvlStruct; + typedef struct LSaveGameHeaderStruct { LE_INT32 vhInitial; LE_UINT32 vhLogicTurn; LE_UINT32 vhSentCycle; LE_UINT32 vhSeeds[NUM_LEVELS]; + LSaveGameDynLvlStruct vhDynLvls[NUM_DYNLVLS]; LE_INT32 vhCurrSeed; LE_INT32 vhViewX; LE_INT32 vhViewY; @@ -1618,6 +1623,12 @@ typedef struct TCmdNewLvl { BYTE bLevel; } TCmdNewLvl; +typedef struct TCmdCreateLvl { + BYTE bCmd; + BYTE clPlayers; + LE_UINT32 clSeed; +} TCmdCreateLvl; + typedef struct TCmdItemOp { BYTE bCmd; BYTE ioIdx; @@ -1983,6 +1994,11 @@ typedef struct DDLevel { DDMonster monster[MAXMONSTERS]; } DDLevel; +typedef struct DDDynLevel { + LE_UINT32 dlSeed; // the seed of the dynamic level + BYTE dlLevel; // the difficulty level of the dynamic level +} DDDynLevel; + typedef struct LocalLevel { BYTE automapsv[MAXDUNX][MAXDUNY]; // TODO: compress the data? } LocalLevel; @@ -2002,6 +2018,7 @@ typedef struct DDQuest { typedef struct DDJunk { // DDPortal jPortals[MAXPORTAL]; // DDQuest jQuests[NUM_QUESTS]; + // DDDynLevel[NUM_DYNLVLS] BYTE jGolems[MAX_MINIONS]; } DDJunk; @@ -2080,8 +2097,10 @@ typedef struct TBuffer { ////////////////////////////////////////////////// typedef struct LevelStruct { - int _dLevelIdx; // index in AllLevels (dungeon_level) + int _dLevelIdx; // dungeon_level / NUM_LEVELS + int _dLevelNum; // index in AllLevels (dungeon_level / NUM_FIXLVLS) bool _dSetLvl; // cached flag if the level is a set-level + bool _dDynLvl; // cached flag if the level is a dynamic-level int _dLevel; // cached difficulty value of the level int _dType; // cached type of the level (dungeon_type) int _dDunType; // cached type of the dungeon (dungeon_gen_type) @@ -2152,6 +2171,12 @@ typedef struct SetPieceData { // quests ////////////////////////////////////////////////// +typedef struct DynLevelStruct { + // uint32_t _dnSeed; -- stored in glSeedTbl + // BYTE _dnPlayers; -- stored in gsDeltaData.ddLevelPlrs + BYTE _dnLevel; +} DynLevelStruct; + typedef struct QuestStruct { BYTE _qactive; // quest_state BYTE _qvar1; // quest parameter which is synchronized with the other players From 5767c81c73ff29b3357ec8dcb46f329f46a6a9f9 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 12 Jul 2024 12:36:11 +0200 Subject: [PATCH 335/596] update SDL2 --- 3rdParty/SDL2/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdParty/SDL2/CMakeLists.txt b/3rdParty/SDL2/CMakeLists.txt index 6f24ff46458..8e6036095a8 100644 --- a/3rdParty/SDL2/CMakeLists.txt +++ b/3rdParty/SDL2/CMakeLists.txt @@ -75,7 +75,7 @@ FetchContent_Declare(SDL2 #URL https://github.com/libsdl-org/SDL/archive/5056b29b0f8611b470d8b8bdb313eab628f8bd6e.tar.gz #URL_HASH MD5=3fb6d72c33434082c32d2649c35c6502 GIT_REPOSITORY https://github.com/pionere/SDL.git - GIT_TAG af566e3f1858490714fe355759fef4a9da58b1eb + GIT_TAG 74876973d1f13fedadabe49a6812d7d88af80b86 ) FetchContent_MakeAvailableExcludeFromAll(SDL2) From 8847ec8600dc91395d5d4067ce5d4fded9573ef6 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 12 Jul 2024 12:58:22 +0200 Subject: [PATCH 336/596] add MPQONE_OPTIONAL (patcher) --- tools/patcher/DiabloUI/checker.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tools/patcher/DiabloUI/checker.cpp b/tools/patcher/DiabloUI/checker.cpp index 7de0dcc6535..fb89d217d01 100644 --- a/tools/patcher/DiabloUI/checker.cpp +++ b/tools/patcher/DiabloUI/checker.cpp @@ -22,6 +22,12 @@ typedef struct FileMetaInfo { bool optional; } FileMetaInfo; +#if USE_MPQONE +#define MPQONE_OPTIONAL false +#else +#define MPQONE_OPTIONAL true +#endif + static const FileMetaInfo filemetadata[] = { #if ASSET_MPL != 1 { "DEVILHD.MPQ", "", "", false }, @@ -39,11 +45,7 @@ static const FileMetaInfo filemetadata[] = { #endif { "PATCH_RT.MPQ", "d2488b30310c1d293eaf068a29709e65", "", true }, { "DIABDAT.MPQ", "011bc6518e6166206231080a4440b373", "68f049866b44688a7af65ba766bef75a", false }, -#if USE_MPQONE - { MPQONE, "81befc2f5f061df0ac3d9de1ecbaff7f", "", false }, -#else - { MPQONE, "81befc2f5f061df0ac3d9de1ecbaff7f", "", true }, -#endif + { MPQONE, "81befc2f5f061df0ac3d9de1ecbaff7f", "", MPQONE_OPTIONAL }, }; static_assert(NUM_MPQS + 1 == sizeof(filemetadata) / sizeof(FileMetaInfo), "Mismatching metadata."); From 1575d09ecf7515f3cdb836ca2f13375a2276d99c Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 12 Jul 2024 13:00:30 +0200 Subject: [PATCH 337/596] fix the md5hash checks of the base (non-hellfire) game --- tools/patcher/DiabloUI/checker.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tools/patcher/DiabloUI/checker.cpp b/tools/patcher/DiabloUI/checker.cpp index fb89d217d01..838c69469da 100644 --- a/tools/patcher/DiabloUI/checker.cpp +++ b/tools/patcher/DiabloUI/checker.cpp @@ -22,6 +22,13 @@ typedef struct FileMetaInfo { bool optional; } FileMetaInfo; +#ifdef HELLFIRE +#define MPQDEVXP_HASH "251688ff12da6d42ea2ebf31d83d3f3c" +#define MPQONE_HASH "81befc2f5f061df0ac3d9de1ecbaff7f" +#else +#define MPQDEVXP_HASH "7814c8a9402f2130c7e1894ff3d2044a" +#define MPQONE_HASH "7c201ea260497b2ca98ae77975754125" +#endif #if USE_MPQONE #define MPQONE_OPTIONAL false #else @@ -32,7 +39,7 @@ static const FileMetaInfo filemetadata[] = { #if ASSET_MPL != 1 { "DEVILHD.MPQ", "", "", false }, #endif - { "DEVILX.MPQ", "251688ff12da6d42ea2ebf31d83d3f3c", "b336be80b3968d4bf8495a2983d4d9f9", false }, + { "DEVILX.MPQ", MPQDEVXP_HASH, "b336be80b3968d4bf8495a2983d4d9f9", false }, #ifdef HELLFIRE { "HF_OPT2.MPQ", "", "", true }, { "HF_OPT1.MPQ", "", "", true }, @@ -45,7 +52,7 @@ static const FileMetaInfo filemetadata[] = { #endif { "PATCH_RT.MPQ", "d2488b30310c1d293eaf068a29709e65", "", true }, { "DIABDAT.MPQ", "011bc6518e6166206231080a4440b373", "68f049866b44688a7af65ba766bef75a", false }, - { MPQONE, "81befc2f5f061df0ac3d9de1ecbaff7f", "", MPQONE_OPTIONAL }, + { MPQONE, MPQONE_HASH, "", MPQONE_OPTIONAL }, }; static_assert(NUM_MPQS + 1 == sizeof(filemetadata) / sizeof(FileMetaInfo), "Mismatching metadata."); From d69177c645f39c862cb32b9eff09324b35a4ae07 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 13 Jul 2024 15:50:09 +0200 Subject: [PATCH 338/596] consistently use BYTE to select an item from the intentory --- Source/msg.cpp | 4 ++-- Source/msg.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/msg.cpp b/Source/msg.cpp index c65117a2bf4..52bc8070827 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -2011,7 +2011,7 @@ void NetSendCmdQuest(BYTE q, bool extOnly) NetSendChunk((BYTE*)&cmd, sizeof(cmd)); } -void SendStoreCmd1(unsigned idx, BYTE bStoreId, int value) +void SendStoreCmd1(BYTE idx, BYTE bStoreId, int value) { TCmdStore1 cmd; @@ -2091,7 +2091,7 @@ void NetSendCmdDelItem(BYTE bLoc) NetSendChunk((BYTE*)&cmd, sizeof(cmd)); } -void NetSendCmdItemSkill(int cii, BYTE skill, int8_t from) +void NetSendCmdItemSkill(BYTE cii, BYTE skill, int8_t from) { TCmdItemOp cmd; diff --git a/Source/msg.h b/Source/msg.h index 67d55c839ab..d1ba20e21bb 100644 --- a/Source/msg.h +++ b/Source/msg.h @@ -51,7 +51,7 @@ void NetSendCmdDelItem(BYTE bLoc); * @param skill: the skill to be used * @param from: the source of the skill */ -void NetSendCmdItemSkill(int cii, BYTE skill, int8_t from); +void NetSendCmdItemSkill(BYTE cii, BYTE skill, int8_t from); /** Use a spell/skill on a given location using from as a source. * @param x: the x coordinate of the target (MAXDUNX) * @param y: the y coordinate of the target (MAXDUNY) @@ -95,7 +95,7 @@ void NetSendCmdMonstSummon(int mnum); void NetSendCmdGolem(); void NetSendShrineCmd(BYTE type, int seed); void NetSendCmdQuest(BYTE q, bool extOnly); -void SendStoreCmd1(unsigned idx, BYTE bStoreId, int value); +void SendStoreCmd1(BYTE idx, BYTE bStoreId, int value); void SendStoreCmd2(BYTE bStoreId); /** Initiate level change. * @param fom: the type of the level-change (window_messages) From 6da6e1190bc9d1add0127bd5d5caa00ebdcb7e27 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 14 Jul 2024 09:29:23 +0200 Subject: [PATCH 339/596] get rid of NetSendCmdDelItem --- Source/msg.cpp | 10 ---------- Source/msg.h | 1 - Source/player.cpp | 2 +- 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/Source/msg.cpp b/Source/msg.cpp index 52bc8070827..387d1ea897d 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -2081,16 +2081,6 @@ void NetSendCmdSpawnItem(bool flipFlag) NetSendChunk((BYTE*)&cmd, sizeof(cmd)); } -void NetSendCmdDelItem(BYTE bLoc) -{ - TCmdBParam1 cmd; - - cmd.bCmd = CMD_DELPLRITEM; - cmd.bParam1 = bLoc; - - NetSendChunk((BYTE*)&cmd, sizeof(cmd)); -} - void NetSendCmdItemSkill(BYTE cii, BYTE skill, int8_t from) { TCmdItemOp cmd; diff --git a/Source/msg.h b/Source/msg.h index d1ba20e21bb..8bd79d1c96d 100644 --- a/Source/msg.h +++ b/Source/msg.h @@ -45,7 +45,6 @@ void NetSendCmdBParam2(BYTE bCmd, BYTE bParam1, BYTE bParam2); void NetSendCmdGItem(BYTE bCmd, BYTE ii); void NetSendCmdPutItem(BYTE x, BYTE y); void NetSendCmdSpawnItem(bool flipFlag); -void NetSendCmdDelItem(BYTE bLoc); /** Use a spell on an item using from as a source. * @param cii: the index of the item in the inventory * @param skill: the skill to be used diff --git a/Source/player.cpp b/Source/player.cpp index 97c5f46cbe6..641c1cb917e 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -1907,7 +1907,7 @@ static void ReduceItemDur(ItemStruct* pi, BYTE iLoc, int pnum) return; pi->_iDurability = 1; if (pnum == mypnum) - NetSendCmdDelItem(iLoc); + NetSendCmdBParam1(CMD_DELPLRITEM, iLoc); } static void WeaponDur(int pnum, int durrnd) From 2fc4edb4c86ffed32bf38b1dcefa1c30c360993d Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Wed, 17 Jul 2024 01:29:00 +0100 Subject: [PATCH 340/596] Bump SDL to v2.30.5 --- .editorconfig | 3 +++ 3rdParty/SDL2/CMakeLists.txt | 4 ++-- Packaging/windows/mingw-prep.sh | 2 +- .../java/org/libsdl/app/HIDDeviceManager.java | 9 +++++++- .../app/src/main/java/org/libsdl/app/SDL.java | 14 +++++++---- .../main/java/org/libsdl/app/SDLActivity.java | 12 +++++----- tools/update_sdl_android_project.sh | 23 +++++++++++++++++++ 7 files changed, 52 insertions(+), 15 deletions(-) create mode 100755 tools/update_sdl_android_project.sh diff --git a/.editorconfig b/.editorconfig index 0311a34932b..0840d4bece8 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,6 +11,9 @@ insert_final_newline = true # Visual C++ Code Style settings cpp_generate_documentation_comments = doxygen_slash_star +[*.java] +end_of_line = lf + [*.pot] end_of_line = lf diff --git a/3rdParty/SDL2/CMakeLists.txt b/3rdParty/SDL2/CMakeLists.txt index 8e6036095a8..05ee3b515a9 100644 --- a/3rdParty/SDL2/CMakeLists.txt +++ b/3rdParty/SDL2/CMakeLists.txt @@ -70,8 +70,8 @@ endif() include(FetchContent_MakeAvailableExcludeFromAll) include(FetchContent) FetchContent_Declare(SDL2 - #URL https://github.com/libsdl-org/SDL/archive/refs/tags/release-2.0.18.tar.gz - #URL_HASH MD5=647e2890385e5f13b9aeee2e27fa26e7 + #URL https://github.com/libsdl-org/SDL/releases/download/release-2.30.5/SDL2-2.30.5.tar.gz + #URL_HASH SHA256=f374f3fa29c37dfcc20822d4a7d7dc57e58924d1a5f2ad511bfab4c8193de63b #URL https://github.com/libsdl-org/SDL/archive/5056b29b0f8611b470d8b8bdb313eab628f8bd6e.tar.gz #URL_HASH MD5=3fb6d72c33434082c32d2649c35c6502 GIT_REPOSITORY https://github.com/pionere/SDL.git diff --git a/Packaging/windows/mingw-prep.sh b/Packaging/windows/mingw-prep.sh index 6b92b4063a5..1320d3cd65e 100755 --- a/Packaging/windows/mingw-prep.sh +++ b/Packaging/windows/mingw-prep.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -SDLDEV_VERS=2.30.3 +SDLDEV_VERS=2.30.5 SDLTTF_VERS=2.0.15 SDLMIXER_VERS=2.0.4 SODIUM_VERS=1.0.20 diff --git a/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java b/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java index e7281fdf26a..21a1c1d18ee 100644 --- a/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java +++ b/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java @@ -277,6 +277,7 @@ private boolean isXboxOneController(UsbDevice usbDevice, UsbInterface usbInterfa 0x044f, // Thrustmaster 0x045e, // Microsoft 0x0738, // Mad Catz + 0x0b05, // ASUS 0x0e6f, // PDP 0x0f0d, // Hori 0x10f5, // Turtle Beach @@ -590,7 +591,13 @@ public boolean openDevice(int deviceID) { } else { flags = 0; } - mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, new Intent(HIDDeviceManager.ACTION_USB_PERMISSION), flags)); + if (Build.VERSION.SDK_INT >= 33 /* Android 14.0 (U) */) { + Intent intent = new Intent(HIDDeviceManager.ACTION_USB_PERMISSION); + intent.setPackage(mContext.getPackageName()); + mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, intent, flags)); + } else { + mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, new Intent(HIDDeviceManager.ACTION_USB_PERMISSION), flags)); + } } catch (Exception e) { Log.v(TAG, "Couldn't request permission for USB device " + usbDevice); HIDDeviceOpenResult(deviceID, false); diff --git a/android-project/app/src/main/java/org/libsdl/app/SDL.java b/android-project/app/src/main/java/org/libsdl/app/SDL.java index 44c21c1c75c..139be9d151c 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDL.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDL.java @@ -38,6 +38,10 @@ public static Context getContext() { } public static void loadLibrary(String libraryName) throws UnsatisfiedLinkError, SecurityException, NullPointerException { + loadLibrary(libraryName, mContext); + } + + public static void loadLibrary(String libraryName, Context context) throws UnsatisfiedLinkError, SecurityException, NullPointerException { if (libraryName == null) { throw new NullPointerException("No library name provided."); @@ -53,10 +57,10 @@ public static void loadLibrary(String libraryName) throws UnsatisfiedLinkError, // To use ReLinker, just add it as a dependency. For more information, see // https://github.com/KeepSafe/ReLinker for ReLinker's repository. // - Class relinkClass = mContext.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker"); - Class relinkListenerClass = mContext.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker$LoadListener"); - Class contextClass = mContext.getClassLoader().loadClass("android.content.Context"); - Class stringClass = mContext.getClassLoader().loadClass("java.lang.String"); + Class relinkClass = context.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker"); + Class relinkListenerClass = context.getClassLoader().loadClass("com.getkeepsafe.relinker.ReLinker$LoadListener"); + Class contextClass = context.getClassLoader().loadClass("android.content.Context"); + Class stringClass = context.getClassLoader().loadClass("java.lang.String"); // Get a 'force' instance of the ReLinker, so we can ensure libraries are reinstalled if // they've changed during updates. @@ -66,7 +70,7 @@ public static void loadLibrary(String libraryName) throws UnsatisfiedLinkError, // Actually load the library! Method loadMethod = relinkInstanceClass.getDeclaredMethod("loadLibrary", contextClass, stringClass, stringClass, relinkListenerClass); - loadMethod.invoke(relinkInstance, mContext, libraryName, null, null); + loadMethod.invoke(relinkInstance, context, libraryName, null, null); } catch (final Throwable e) { // Fall back diff --git a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java index 349771a44cc..88c5ea3038b 100644 --- a/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -61,7 +61,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh private static final String TAG = "SDL"; private static final int SDL_MAJOR_VERSION = 2; private static final int SDL_MINOR_VERSION = 31; - private static final int SDL_MICRO_VERSION = 2; + private static final int SDL_MICRO_VERSION = 5; /* // Display InputType.SOURCE/CLASS of events and devices // @@ -281,7 +281,7 @@ protected String[] getLibraries() { // Load the .so public void loadLibraries() { for (String lib : getLibraries()) { - SDL.loadLibrary(lib); + SDL.loadLibrary(lib, this); } } @@ -995,8 +995,8 @@ public void setOrientationBis(int w, int h, boolean resizable, String hint) /* No valid hint, nothing is explicitly allowed */ if (!is_portrait_allowed && !is_landscape_allowed) { if (resizable) { - /* All orientations are allowed */ - req = ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR; + /* All orientations are allowed, respecting user orientation lock setting */ + req = ActivityInfo.SCREEN_ORIENTATION_FULL_USER; } else { /* Fixed window and nothing specified. Get orientation from w/h of created window */ req = (w > h ? ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT); @@ -1005,8 +1005,8 @@ public void setOrientationBis(int w, int h, boolean resizable, String hint) /* At least one orientation is allowed */ if (resizable) { if (is_portrait_allowed && is_landscape_allowed) { - /* hint allows both landscape and portrait, promote to full sensor */ - req = ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR; + /* hint allows both landscape and portrait, promote to full user */ + req = ActivityInfo.SCREEN_ORIENTATION_FULL_USER; } else { /* Use the only one allowed "orientation" */ req = (is_landscape_allowed ? orientation_landscape : orientation_portrait); diff --git a/tools/update_sdl_android_project.sh b/tools/update_sdl_android_project.sh new file mode 100755 index 00000000000..c74dc9b87e5 --- /dev/null +++ b/tools/update_sdl_android_project.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +set -euo pipefail + +SDL_BASE=https://raw.githubusercontent.com/libsdl-org/SDL/release-2.30.5 +FILES=( + HIDDevice.java + HIDDeviceBLESteamController.java + HIDDeviceManager.java + HIDDeviceUSB.java + SDL.java + SDLActivity.java + SDLAudioManager.java + SDLControllerManager.java + SDLSurface.java +) + +for f in "${FILES[@]}"; do + set -x + curl -L -O -s "${SDL_BASE}/android-project/app/src/main/java/org/libsdl/app/${f}" \ + --output-dir android-project/app/src/main/java/org/libsdl/app/ + { set +x; } 2> /dev/null +done +>&2 echo "Done. Remember to manually check for and sync changes in XML files, such as AndroidManifest.xml" From b4ab769fa1dab07c00cb1b212e91a4cd37e924c4 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 18 Jul 2024 19:24:58 +0200 Subject: [PATCH 341/596] fix the placement of lecterns in the skeleton rooms - prevent placement next to arches to avoid lockout - allow placement next to 'lamps' in the cathedral --- Source/themes.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/themes.cpp b/Source/themes.cpp index 066ef474c05..8618ad555d3 100644 --- a/Source/themes.cpp +++ b/Source/themes.cpp @@ -566,11 +566,13 @@ static void Theme_SkelRoom(int themeId, BYTE tv) AddObject(OBJ_BANNERL, xx + 1, yy + 1); } - if (dObject[xx][yy - 3] == 0) { + if ((dObject[xx][yy - 3] == 0 || !objects[dObject[xx][yy - 3] - 1]._oDoorFlag) // not a door + && (nSolidTable[dPiece[xx][yy - 3]] || !nSolidTable[dPiece[xx + 1][yy - 3]])) { // or a single path to NE TODO: allow if !nSolidTable[dPiece[xx - 1][yy - 3]]? // assert(dObject[xx][yy - 2] == 0); AddObject(OBJ_BOOK2R, xx, yy - 2); } - if (dObject[xx][yy + 3] == 0) { + if ((dObject[xx][yy + 3] == 0 || !objects[dObject[xx][yy + 3] - 1]._oDoorFlag) // not a door + && (nSolidTable[dPiece[xx][yy + 3]] || !nSolidTable[dPiece[xx + 1][yy + 3]])) { // or a single path to SW TODO: allow if !nSolidTable[dPiece[xx - 1][yy + 3]]? // assert(dObject[xx][yy + 2] == 0); AddObject(OBJ_BOOK2R, xx, yy + 2); } From 808f7a24b7eea43e242755b84136615a3e6f708b Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Fri, 19 Jul 2024 18:00:41 +0200 Subject: [PATCH 342/596] Update iOS toolchain --- CMake/ios.toolchain.cmake | 421 ++++++++++++++++++++++++++------------ 1 file changed, 295 insertions(+), 126 deletions(-) diff --git a/CMake/ios.toolchain.cmake b/CMake/ios.toolchain.cmake index 5d04587719f..a235cd0d633 100644 --- a/CMake/ios.toolchain.cmake +++ b/CMake/ios.toolchain.cmake @@ -37,7 +37,7 @@ # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # -# This file is based off of the Platform/Darwin.cmake and +# This file is based on the Platform/Darwin.cmake and # Platform/UnixPaths.cmake files which are included with CMake 2.8.4 # It has been altered for iOS development. # @@ -51,47 +51,61 @@ # # INFORMATION / HELP # -# The following options control the behaviour of this toolchain: +############################################################################### +# OPTIONS # +############################################################################### # # PLATFORM: (default "OS64") # OS = Build for iPhoneOS. # OS64 = Build for arm64 iphoneOS. -# OS64COMBINED = Build for arm64 x86_64 iphoneOS. Combined into FAT STATIC lib (supported on 3.14+ of CMakewith "-G Xcode" argument ONLY) +# OS64COMBINED = Build for arm64 x86_64 iphoneOS + iphoneOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with "-G Xcode" argument in combination with the "cmake --install" CMake build step) # SIMULATOR = Build for x86 i386 iphoneOS Simulator. # SIMULATOR64 = Build for x86_64 iphoneOS Simulator. # SIMULATORARM64 = Build for arm64 iphoneOS Simulator. +# SIMULATOR64COMBINED = Build for arm64 x86_64 iphoneOS Simulator. Combined into FAT STATIC lib (supported on 3.14+ of CMakewith "-G Xcode" argument ONLY) # TVOS = Build for arm64 tvOS. -# TVOSCOMBINED = Build for arm64 x86_64 tvOS. Combined into FAT STATIC lib (supported on 3.14+ of CMake with "-G Xcode" argument ONLY) +# TVOSCOMBINED = Build for arm64 x86_64 tvOS + tvOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with "-G Xcode" argument in combination with the "cmake --install" CMake build step) # SIMULATOR_TVOS = Build for x86_64 tvOS Simulator. +# SIMULATORARM64_TVOS = Build for arm64 tvOS Simulator. +# VISIONOSCOMBINED = Build for arm64 visionOS + visionOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with "-G Xcode" argument in combination with the "cmake --install" CMake build step) +# VISIONOS = Build for arm64 visionOS. +# SIMULATOR_VISIONOS = Build for arm64 visionOS Simulator. # WATCHOS = Build for armv7k arm64_32 for watchOS. -# WATCHOSCOMBINED = Build for armv7k arm64_32 x86_64 watchOS. Combined into FAT STATIC lib (supported on 3.14+ of CMake with "-G Xcode" argument ONLY) +# WATCHOSCOMBINED = Build for armv7k arm64_32 x86_64 watchOS + watchOS Simulator. Combined into FAT STATIC lib (only supported on 3.14+ of CMake with "-G Xcode" argument in combination with the "cmake --install" CMake build step) # SIMULATOR_WATCHOS = Build for x86_64 for watchOS Simulator. +# SIMULATORARM64_WATCHOS = Build for arm64 for watchOS Simulator. # MAC = Build for x86_64 macOS. # MAC_ARM64 = Build for Apple Silicon macOS. +# MAC_UNIVERSAL = Combined build for x86_64 and Apple Silicon on macOS. # MAC_CATALYST = Build for x86_64 macOS with Catalyst support (iOS toolchain on macOS). # Note: The build argument "MACOSX_DEPLOYMENT_TARGET" can be used to control min-version of macOS # MAC_CATALYST_ARM64 = Build for Apple Silicon macOS with Catalyst support (iOS toolchain on macOS). # Note: The build argument "MACOSX_DEPLOYMENT_TARGET" can be used to control min-version of macOS +# MAC_CATALYST_UNIVERSAL = Combined build for x86_64 and Apple Silicon on Catalyst. # # CMAKE_OSX_SYSROOT: Path to the SDK to use. By default this is # automatically determined from PLATFORM and xcodebuild, but # can also be manually specified (although this should not be required). # # CMAKE_DEVELOPER_ROOT: Path to the Developer directory for the platform -# being compiled for. By default this is automatically determined from +# being compiled for. By default, this is automatically determined from # CMAKE_OSX_SYSROOT, but can also be manually specified (although this should # not be required). # -# DEPLOYMENT_TARGET: Minimum SDK version to target. Default 2.0 on watchOS and 9.0 on tvOS+iOS +# DEPLOYMENT_TARGET: Minimum SDK version to target. Default 6.0 on watchOS, 13.0 on tvOS+iOS/iPadOS, 11.0 on macOS, 1.0 on visionOS +# +# NAMED_LANGUAGE_SUPPORT: +# ON (default) = Will require "enable_language(OBJC) and/or enable_language(OBJCXX)" for full OBJC|OBJCXX support +# OFF = Will embed the OBJC and OBJCXX flags into the CMAKE_C_FLAGS and CMAKE_CXX_FLAGS (legacy behavior, CMake version < 3.16) # -# ENABLE_BITCODE: (1|0) Enables or disables bitcode support. Default 1 (true) +# ENABLE_BITCODE: (ON|OFF) Enables or disables bitcode support. Default OFF # -# ENABLE_ARC: (1|0) Enables or disables ARC support. Default 1 (true, ARC enabled by default) +# ENABLE_ARC: (ON|OFF) Enables or disables ARC support. Default ON (ARC enabled by default) # -# ENABLE_VISIBILITY: (1|0) Enables or disables symbol visibility support. Default 0 (false, visibility hidden by default) +# ENABLE_VISIBILITY: (ON|OFF) Enables or disables symbol visibility support. Default OFF (visibility hidden by default) # -# ENABLE_STRICT_TRY_COMPILE: (1|0) Enables or disables strict try_compile() on all Check* directives (will run linker -# to actually check if linking is possible). Default 0 (false, will set CMAKE_TRY_COMPILE_TARGET_TYPE to STATIC_LIBRARY) +# ENABLE_STRICT_TRY_COMPILE: (ON|OFF) Enables or disables strict try_compile() on all Check* directives (will run linker +# to actually check if linking is possible). Default OFF (will set CMAKE_TRY_COMPILE_TARGET_TYPE to STATIC_LIBRARY) # # ARCHS: (armv7 armv7s armv7k arm64 arm64_32 i386 x86_64) If specified, will override the default architectures for the given PLATFORM # OS = armv7 armv7s arm64 (if applicable) @@ -101,12 +115,22 @@ # SIMULATORARM64 = arm64 # TVOS = arm64 # SIMULATOR_TVOS = x86_64 (i386 has since long been deprecated) +# SIMULATORARM64_TVOS = arm64 # WATCHOS = armv7k arm64_32 (if applicable) # SIMULATOR_WATCHOS = x86_64 (i386 has since long been deprecated) +# SIMULATORARM64_WATCHOS = arm64 # MAC = x86_64 # MAC_ARM64 = arm64 +# MAC_UNIVERSAL = x86_64 arm64 # MAC_CATALYST = x86_64 # MAC_CATALYST_ARM64 = arm64 +# MAC_CATALYST_UNIVERSAL = x86_64 arm64 +# +# NOTE: When manually specifying ARCHS, put a semi-colon between the entries. E.g., -DARCHS="armv7;arm64" +# +############################################################################### +# END OPTIONS # +############################################################################### # # This toolchain defines the following properties (available via get_property()) for use externally: # @@ -114,7 +138,7 @@ # XCODE_VERSION: Version number (not including Build version) of Xcode detected. # SDK_VERSION: Version of SDK being used. # OSX_ARCHITECTURES: Architectures being compiled for (generated from PLATFORM). -# APPLE_TARGET_TRIPLE: Used by autoconf build systems. NOTE: If "ARCHS" are overridden, this will *NOT* be set! +# APPLE_TARGET_TRIPLE: Used by autoconf build systems. NOTE: If "ARCHS" is overridden, this will *NOT* be set! # # This toolchain defines the following macros for use externally: # @@ -132,28 +156,20 @@ cmake_minimum_required(VERSION 3.8.0) # CMake invokes the toolchain file twice during the first build, but only once during subsequent rebuilds. -if(DEFINED ENV{_IOS_TOOLCHAIN_HAS_RUN}) +# NOTE: To improve single-library build-times, provide the flag "OS_SINGLE_BUILD" as a build argument. +if(DEFINED OS_SINGLE_BUILD AND DEFINED ENV{_IOS_TOOLCHAIN_HAS_RUN}) return() endif() set(ENV{_IOS_TOOLCHAIN_HAS_RUN} true) -############################################################################### -# OPTIONS # -############################################################################### - -option(DROP_32_BIT "Drops the 32-bit targets universally." YES) - -############################################################################### -# END OPTIONS # -############################################################################### - # List of supported platform values list(APPEND _supported_platforms - "OS" "OS64" "OS64COMBINED" "SIMULATOR" "SIMULATOR64" "SIMULATORARM64" - "TVOS" "TVOSCOMBINED" "SIMULATOR_TVOS" - "WATCHOS" "WATCHOSCOMBINED" "SIMULATOR_WATCHOS" - "MAC" "MAC_ARM64" - "MAC_CATALYST" "MAC_CATALYST_ARM64") + "OS" "OS64" "OS64COMBINED" "SIMULATOR" "SIMULATOR64" "SIMULATORARM64" "SIMULATOR64COMBINED" + "TVOS" "TVOSCOMBINED" "SIMULATOR_TVOS" "SIMULATORARM64_TVOS" + "WATCHOS" "WATCHOSCOMBINED" "SIMULATOR_WATCHOS" "SIMULATORARM64_WATCHOS" + "MAC" "MAC_ARM64" "MAC_UNIVERSAL" + "VISIONOS" "SIMULATOR_VISIONOS" "VISIONOSCOMBINED" + "MAC_CATALYST" "MAC_CATALYST_ARM64" "MAC_CATALYST_UNIVERSAL") # Cache what generator is used set(USED_CMAKE_GENERATOR "${CMAKE_GENERATOR}") @@ -165,9 +181,9 @@ endif() # Get the Xcode version being used. # Problem: CMake runs toolchain files multiple times, but can't read cache variables on some runs. -# Workaround: On first run (in which cache variables are always accessible), set an intermediary environment variable. +# Workaround: On the first run (in which cache variables are always accessible), set an intermediary environment variable. # -# NOTE: This pattern is used i many places in this toolchain to speed up checks of all sorts +# NOTE: This pattern is used in many places in this toolchain to speed up checks of all sorts if(DEFINED XCODE_VERSION_INT) # Environment variables are always preserved. set(ENV{_XCODE_VERSION_INT} "${XCODE_VERSION_INT}") @@ -189,10 +205,10 @@ endif() # Assuming that xcode 12.0 is installed you most probably have ios sdk 14.0 or later installed (tested on Big Sur) # if you don't set a deployment target it will be set the way you only get 64-bit builds -if(NOT DEFINED DEPLOYMENT_TARGET AND XCODE_VERSION_INT VERSION_GREATER 12.0) - # Temporarily fix the arm64 issues in CMake install-combined by excluding arm64 for simulator builds (needed for Apple Silicon...) - set(CMAKE_XCODE_ATTRIBUTE_EXCLUDED_ARCHS[sdk=iphonesimulator*] "arm64") -endif() +#if(NOT DEFINED DEPLOYMENT_TARGET AND XCODE_VERSION_INT VERSION_GREATER 12.0) +# Temporarily fix the arm64 issues in CMake install-combined by excluding arm64 for simulator builds (needed for Apple Silicon...) +# set(CMAKE_XCODE_ATTRIBUTE_EXCLUDED_ARCHS[sdk=iphonesimulator*] "arm64") +#endif() # Check if the platform variable is set if(DEFINED PLATFORM) @@ -205,7 +221,7 @@ elseif(NOT DEFINED PLATFORM) endif () if(PLATFORM MATCHES ".*COMBINED" AND NOT CMAKE_GENERATOR MATCHES "Xcode") - message(FATAL_ERROR "The combined builds support requires Xcode to be used as generator via '-G Xcode' command-line argument in CMake") + message(FATAL_ERROR "The combined builds support requires Xcode to be used as a generator via '-G Xcode' command-line argument in CMake") endif() # Safeguard that the platform value is set and is one of the supported values @@ -217,11 +233,11 @@ if("${contains_PLATFORM}" EQUAL "-1") endif() # Check if Apple Silicon is supported -if(PLATFORM MATCHES "^(MAC_ARM64)$|^(MAC_CATALYST_ARM64)$" AND ${CMAKE_VERSION} VERSION_LESS "3.19.5") +if(PLATFORM MATCHES "^(MAC_ARM64)$|^(MAC_CATALYST_ARM64)$|^(MAC_UNIVERSAL)$|^(MAC_CATALYST_UNIVERSAL)$" AND ${CMAKE_VERSION} VERSION_LESS "3.19.5") message(FATAL_ERROR "Apple Silicon builds requires a minimum of CMake 3.19.5") endif() -# Touch toolchain variable to suppress "unused variable" warning. +# Touch the toolchain variable to suppress the "unused variable" warning. # This happens if CMake is invoked with the same command line the second time. if(CMAKE_TOOLCHAIN_FILE) endif() @@ -232,27 +248,46 @@ set(CMAKE_HAVE_THREADS_LIBRARY 1) set(CMAKE_USE_WIN32_THREADS_INIT 0) set(CMAKE_USE_PTHREADS_INIT 1) -# Specify minimum version of deployment target. +# Specify named language support defaults. +if(NOT DEFINED NAMED_LANGUAGE_SUPPORT AND ${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.16") + set(NAMED_LANGUAGE_SUPPORT ON) + message(STATUS "[DEFAULTS] Using explicit named language support! E.g., enable_language(CXX) is needed in the project files.") +elseif(NOT DEFINED NAMED_LANGUAGE_SUPPORT AND ${CMAKE_VERSION} VERSION_LESS "3.16") + set(NAMED_LANGUAGE_SUPPORT OFF) + message(STATUS "[DEFAULTS] Disabling explicit named language support. Falling back to legacy behavior.") +elseif(DEFINED NAMED_LANGUAGE_SUPPORT AND ${CMAKE_VERSION} VERSION_LESS "3.16") + message(FATAL_ERROR "CMake named language support for OBJC and OBJCXX was added in CMake 3.16.") +endif() +set(NAMED_LANGUAGE_SUPPORT_INT ${NAMED_LANGUAGE_SUPPORT} CACHE BOOL + "Whether or not to enable explicit named language support" FORCE) + +# Specify the minimum version of the deployment target. if(NOT DEFINED DEPLOYMENT_TARGET) if (PLATFORM MATCHES "WATCHOS") # Unless specified, SDK version 4.0 is used by default as minimum target version (watchOS). - set(DEPLOYMENT_TARGET "4.0") + set(DEPLOYMENT_TARGET "6.0") elseif(PLATFORM STREQUAL "MAC") - # Unless specified, SDK version 10.13 (High sierra) is used by default as minimum target version (macos). - set(DEPLOYMENT_TARGET "10.13") + # Unless specified, SDK version 10.13 (High Sierra) is used by default as the minimum target version (macos). + set(DEPLOYMENT_TARGET "11.0") + elseif(PLATFORM STREQUAL "VISIONOS" OR PLATFORM STREQUAL "SIMULATOR_VISIONOS" OR PLATFORM STREQUAL "VISIONOSCOMBINED") + # Unless specified, SDK version 1.0 is used by default as minimum target version (visionOS). + set(DEPLOYMENT_TARGET "1.0") elseif(PLATFORM STREQUAL "MAC_ARM64") - # Unless specified, SDK version 11.0 (Big Sur) is used by default as minimum target version (macos on arm). + # Unless specified, SDK version 11.0 (Big Sur) is used by default as the minimum target version (macOS on arm). set(DEPLOYMENT_TARGET "11.0") - elseif(PLATFORM STREQUAL "MAC_CATALYST" OR PLATFORM STREQUAL "MAC_CATALYST_ARM64") - # Unless specified, SDK version 13.0 is used by default as minimum target version (mac catalyst minimum requirement). - set(DEPLOYMENT_TARGET "13.0") - else() - # Unless specified, SDK version 11.0 is used by default as minimum target version (iOS, tvOS). + elseif(PLATFORM STREQUAL "MAC_UNIVERSAL") + # Unless specified, SDK version 11.0 (Big Sur) is used by default as minimum target version for universal builds. set(DEPLOYMENT_TARGET "11.0") + elseif(PLATFORM STREQUAL "MAC_CATALYST" OR PLATFORM STREQUAL "MAC_CATALYST_ARM64" OR PLATFORM STREQUAL "MAC_CATALYST_UNIVERSAL") + # Unless specified, SDK version 13.0 is used by default as the minimum target version (mac catalyst minimum requirement). + set(DEPLOYMENT_TARGET "13.1") + else() + # Unless specified, SDK version 11.0 is used by default as the minimum target version (iOS, tvOS). + set(DEPLOYMENT_TARGET "13.0") endif() message(STATUS "[DEFAULTS] Using the default min-version since DEPLOYMENT_TARGET not provided!") -elseif(DEFINED DEPLOYMENT_TARGET AND PLATFORM MATCHES "^MAC_CATALYST" AND ${DEPLOYMENT_TARGET} VERSION_LESS "13.0") - message(FATAL_ERROR "Mac Catalyst builds requires a minimum deployment target of 13.0!") +elseif(DEFINED DEPLOYMENT_TARGET AND PLATFORM MATCHES "^MAC_CATALYST" AND ${DEPLOYMENT_TARGET} VERSION_LESS "13.1") + message(FATAL_ERROR "Mac Catalyst builds requires a minimum deployment target of 13.1!") endif() # Store the DEPLOYMENT_TARGET in the cache @@ -279,19 +314,19 @@ if(PLATFORM_INT STREQUAL "OS") set(SDK_NAME iphoneos) if(NOT ARCHS) set(ARCHS armv7 armv7s arm64) - set(APPLE_TARGET_TRIPLE_INT arm-apple-ios$${DEPLOYMENT_TARGET}) + set(APPLE_TARGET_TRIPLE_INT arm-apple-ios${DEPLOYMENT_TARGET}) else() - set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}) + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}) endif() elseif(PLATFORM_INT STREQUAL "OS64") set(SDK_NAME iphoneos) if(NOT ARCHS) if (XCODE_VERSION_INT VERSION_GREATER 10.0) - set(ARCHS arm64) # Add arm64e when Apple have fixed the integration issues with it, libarclite_iphoneos.a is currently missung bitcode markers for example + set(ARCHS arm64) # FIXME: Add arm64e when Apple has fixed the integration issues with it, libarclite_iphoneos.a is currently missing bitcode markers for example else() set(ARCHS arm64) endif() - set(APPLE_TARGET_TRIPLE_INT aarch64-apple-ios${DEPLOYMENT_TARGET}) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-ios${DEPLOYMENT_TARGET}) else() set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}) endif() @@ -299,12 +334,12 @@ elseif(PLATFORM_INT STREQUAL "OS64COMBINED") set(SDK_NAME iphoneos) if(MODERN_CMAKE) if(NOT ARCHS) - if (XCODE_VERSION_INT VERSION_GREATER 10.0) - set(ARCHS arm64 x86_64) # Add arm64e when Apple have fixed the integration issues with it, libarclite_iphoneos.a is currently missung bitcode markers for example + if (XCODE_VERSION_INT VERSION_GREATER 12.0) + set(ARCHS arm64 x86_64) set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "arm64") - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64 arm64") set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "arm64") - set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64 arm64") else() set(ARCHS arm64 x86_64) set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "arm64") @@ -312,13 +347,37 @@ elseif(PLATFORM_INT STREQUAL "OS64COMBINED") set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "arm64") set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64") endif() - set(APPLE_TARGET_TRIPLE_INT aarch64-x86_64-apple-ios${DEPLOYMENT_TARGET}) + set(APPLE_TARGET_TRIPLE_INT arm64-x86_64-apple-ios${DEPLOYMENT_TARGET}) else() set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}) endif() else() message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the OS64COMBINED setting work") endif() +elseif(PLATFORM_INT STREQUAL "SIMULATOR64COMBINED") + set(SDK_NAME iphonesimulator) + if(MODERN_CMAKE) + if(NOT ARCHS) + if (XCODE_VERSION_INT VERSION_GREATER 12.0) + set(ARCHS arm64 x86_64) # FIXME: Add arm64e when Apple have fixed the integration issues with it, libarclite_iphoneos.a is currently missing bitcode markers for example + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64 arm64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64 arm64") + else() + set(ARCHS arm64 x86_64) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphoneos*] "") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*] "x86_64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphoneos*] "") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=iphonesimulator*] "x86_64") + endif() + set(APPLE_TARGET_TRIPLE_INT aarch64-x86_64-apple-ios${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator) + endif() + else() + message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the SIMULATOR64COMBINED setting work") + endif() elseif(PLATFORM_INT STREQUAL "SIMULATOR") set(SDK_NAME iphonesimulator) if(NOT ARCHS) @@ -340,7 +399,7 @@ elseif(PLATFORM_INT STREQUAL "SIMULATORARM64") set(SDK_NAME iphonesimulator) if(NOT ARCHS) set(ARCHS arm64) - set(APPLE_TARGET_TRIPLE_INT aarch64-apple-ios${DEPLOYMENT_TARGET}-simulator) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-ios${DEPLOYMENT_TARGET}-simulator) else() set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-simulator) endif() @@ -348,7 +407,7 @@ elseif(PLATFORM_INT STREQUAL "TVOS") set(SDK_NAME appletvos) if(NOT ARCHS) set(ARCHS arm64) - set(APPLE_TARGET_TRIPLE_INT aarch64-apple-tvos${DEPLOYMENT_TARGET}) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-tvos${DEPLOYMENT_TARGET}) else() set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}) endif() @@ -357,11 +416,11 @@ elseif (PLATFORM_INT STREQUAL "TVOSCOMBINED") if(MODERN_CMAKE) if(NOT ARCHS) set(ARCHS arm64 x86_64) - set(APPLE_TARGET_TRIPLE_INT aarch64-x86_64-apple-tvos${DEPLOYMENT_TARGET}) + set(APPLE_TARGET_TRIPLE_INT arm64-x86_64-apple-tvos${DEPLOYMENT_TARGET}) set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=appletvos*] "arm64") - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=appletvsimulator*] "x86_64") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=appletvsimulator*] "x86_64 arm64") set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=appletvos*] "arm64") - set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=appletvsimulator*] "x86_64") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=appletvsimulator*] "x86_64 arm64") else() set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}) endif() @@ -376,12 +435,20 @@ elseif(PLATFORM_INT STREQUAL "SIMULATOR_TVOS") else() set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}-simulator) endif() +elseif(PLATFORM_INT STREQUAL "SIMULATORARM64_TVOS") + set(SDK_NAME appletvsimulator) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-tvos${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-tvos${DEPLOYMENT_TARGET}-simulator) + endif() elseif(PLATFORM_INT STREQUAL "WATCHOS") set(SDK_NAME watchos) if(NOT ARCHS) if (XCODE_VERSION_INT VERSION_GREATER 10.0) set(ARCHS armv7k arm64_32) - set(APPLE_TARGET_TRIPLE_INT aarch64_32-apple-watchos${DEPLOYMENT_TARGET}) + set(APPLE_TARGET_TRIPLE_INT arm64_32-apple-watchos${DEPLOYMENT_TARGET}) else() set(ARCHS armv7k) set(APPLE_TARGET_TRIPLE_INT arm-apple-watchos${DEPLOYMENT_TARGET}) @@ -395,7 +462,7 @@ elseif(PLATFORM_INT STREQUAL "WATCHOSCOMBINED") if(NOT ARCHS) if (XCODE_VERSION_INT VERSION_GREATER 10.0) set(ARCHS armv7k arm64_32 i386) - set(APPLE_TARGET_TRIPLE_INT aarch64_32-i386-apple-watchos${DEPLOYMENT_TARGET}) + set(APPLE_TARGET_TRIPLE_INT arm64_32-i386-apple-watchos${DEPLOYMENT_TARGET}) set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchos*] "armv7k arm64_32") set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=watchsimulator*] "i386") set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=watchos*] "armv7k arm64_32") @@ -422,6 +489,44 @@ elseif(PLATFORM_INT STREQUAL "SIMULATOR_WATCHOS") else() set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}-simulator) endif() +elseif(PLATFORM_INT STREQUAL "SIMULATORARM64_WATCHOS") + set(SDK_NAME watchsimulator) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-watchos${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-watchos${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "SIMULATOR_VISIONOS") + set(SDK_NAME xrsimulator) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-xros${DEPLOYMENT_TARGET}-simulator) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-xros${DEPLOYMENT_TARGET}-simulator) + endif() +elseif(PLATFORM_INT STREQUAL "VISIONOS") + set(SDK_NAME xros) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-xros${DEPLOYMENT_TARGET}) + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-xros${DEPLOYMENT_TARGET}) + endif() +elseif(PLATFORM_INT STREQUAL "VISIONOSCOMBINED") + set(SDK_NAME xros) + if(MODERN_CMAKE) + if(NOT ARCHS) + set(ARCHS arm64) + set(APPLE_TARGET_TRIPLE_INT arm64-apple-xros${DEPLOYMENT_TARGET}) + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=xros*] "arm64") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=xrsimulator*] "arm64") + else() + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-xros${DEPLOYMENT_TARGET}) + endif() + else() + message(FATAL_ERROR "Please make sure that you are running CMake 3.14+ to make the VISIONOSCOMBINED setting work") + endif() elseif(PLATFORM_INT STREQUAL "MAC" OR PLATFORM_INT STREQUAL "MAC_CATALYST") set(SDK_NAME macosx) if(NOT ARCHS) @@ -444,10 +549,26 @@ elseif(PLATFORM_INT MATCHES "^(MAC_ARM64)$|^(MAC_CATALYST_ARM64)$") elseif(PLATFORM_INT STREQUAL "MAC_CATALYST_ARM64") set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-macabi) endif() +elseif(PLATFORM_INT STREQUAL "MAC_UNIVERSAL") + set(SDK_NAME macosx) + if(NOT ARCHS) + set(ARCHS "x86_64;arm64") + endif() + string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-macosx${DEPLOYMENT_TARGET}) +elseif(PLATFORM_INT STREQUAL "MAC_CATALYST_UNIVERSAL") + set(SDK_NAME macosx) + if(NOT ARCHS) + set(ARCHS "x86_64;arm64") + endif() + string(REPLACE ";" "-" ARCHS_SPLIT "${ARCHS}") + set(APPLE_TARGET_TRIPLE_INT ${ARCHS_SPLIT}-apple-ios${DEPLOYMENT_TARGET}-macabi) else() message(FATAL_ERROR "Invalid PLATFORM: ${PLATFORM_INT}") endif() +string(REPLACE ";" " " ARCHS_SPACED "${ARCHS}") + if(MODERN_CMAKE AND PLATFORM_INT MATCHES ".*COMBINED" AND NOT CMAKE_GENERATOR MATCHES "Xcode") message(FATAL_ERROR "The COMBINED options only work with Xcode generator, -G Xcode") endif() @@ -455,21 +576,22 @@ endif() if(CMAKE_GENERATOR MATCHES "Xcode" AND PLATFORM_INT MATCHES "^MAC_CATALYST") set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") set(CMAKE_XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS "macosx") - set(CMAKE_XCODE_EFFECTIVE_PLATFORMS "-maccatalyst") + set(CMAKE_XCODE_ATTRIBUTE_SUPPORTS_MACCATALYST "YES") if(NOT DEFINED MACOSX_DEPLOYMENT_TARGET) set(CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET "10.15") else() set(CMAKE_XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET "${MACOSX_DEPLOYMENT_TARGET}") endif() elseif(CMAKE_GENERATOR MATCHES "Xcode") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") set(CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "${DEPLOYMENT_TARGET}") if(NOT PLATFORM_INT MATCHES ".*COMBINED") - set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=${SDK_NAME}*] "${ARCHS}") - set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=${SDK_NAME}*] "${ARCHS}") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS[sdk=${SDK_NAME}*] "${ARCHS_SPACED}") + set(CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS[sdk=${SDK_NAME}*] "${ARCHS_SPACED}") endif() endif() -# If user did not specify the SDK root to use, then query xcodebuild for it. +# If the user did not specify the SDK root to use, then query xcodebuild for it. if(DEFINED CMAKE_OSX_SYSROOT_INT) # Environment variables are always preserved. set(ENV{_CMAKE_OSX_SYSROOT_INT} "${CMAKE_OSX_SYSROOT_INT}") @@ -496,34 +618,30 @@ elseif(DEFINED CMAKE_OSX_SYSROOT_INT) endif() # Use bitcode or not -if(NOT DEFINED ENABLE_BITCODE AND NOT ARCHS MATCHES "((^|;|, )(i386|x86_64))+") - # Unless specified, enable bitcode support by default - message(STATUS "[DEFAULTS] Enabling bitcode support by default. ENABLE_BITCODE not provided!") - set(ENABLE_BITCODE TRUE) -elseif(NOT DEFINED ENABLE_BITCODE) - message(STATUS "[DEFAULTS] Disabling bitcode support by default on simulators. ENABLE_BITCODE not provided for override!") - set(ENABLE_BITCODE FALSE) +if(NOT DEFINED ENABLE_BITCODE) + message(STATUS "[DEFAULTS] Disabling bitcode support by default. ENABLE_BITCODE not provided for override!") + set(ENABLE_BITCODE OFF) endif() set(ENABLE_BITCODE_INT ${ENABLE_BITCODE} CACHE BOOL "Whether or not to enable bitcode" FORCE) # Use ARC or not if(NOT DEFINED ENABLE_ARC) # Unless specified, enable ARC support by default - set(ENABLE_ARC TRUE) + set(ENABLE_ARC ON) message(STATUS "[DEFAULTS] Enabling ARC support by default. ENABLE_ARC not provided!") endif() set(ENABLE_ARC_INT ${ENABLE_ARC} CACHE BOOL "Whether or not to enable ARC" FORCE) # Use hidden visibility or not if(NOT DEFINED ENABLE_VISIBILITY) # Unless specified, disable symbols visibility by default - set(ENABLE_VISIBILITY FALSE) + set(ENABLE_VISIBILITY OFF) message(STATUS "[DEFAULTS] Hiding symbols visibility by default. ENABLE_VISIBILITY not provided!") endif() set(ENABLE_VISIBILITY_INT ${ENABLE_VISIBILITY} CACHE BOOL "Whether or not to hide symbols from the dynamic linker (-fvisibility=hidden)" FORCE) # Set strict compiler checks or not if(NOT DEFINED ENABLE_STRICT_TRY_COMPILE) # Unless specified, disable strict try_compile() - set(ENABLE_STRICT_TRY_COMPILE FALSE) + set(ENABLE_STRICT_TRY_COMPILE OFF) message(STATUS "[DEFAULTS] Using NON-strict compiler checks by default. ENABLE_STRICT_TRY_COMPILE not provided!") endif() set(ENABLE_STRICT_TRY_COMPILE_INT ${ENABLE_STRICT_TRY_COMPILE} CACHE BOOL @@ -613,10 +731,14 @@ foreach(lang ${languages}) set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "${BUILD_LIBTOOL} -static -o " CACHE INTERNAL "") endforeach() -# CMake 3.14+ support building for iOS, watchOS and tvOS out of the box. +# CMake 3.14+ support building for iOS, watchOS, and tvOS out of the box. if(MODERN_CMAKE) if(SDK_NAME MATCHES "iphone") set(CMAKE_SYSTEM_NAME iOS) + elseif(SDK_NAME MATCHES "xros") + set(CMAKE_SYSTEM_NAME visionOS) + elseif(SDK_NAME MATCHES "xrsimulator") + set(CMAKE_SYSTEM_NAME visionOS) elseif(SDK_NAME MATCHES "macosx") set(CMAKE_SYSTEM_NAME Darwin) elseif(SDK_NAME MATCHES "appletv") @@ -626,33 +748,38 @@ if(MODERN_CMAKE) endif() # Provide flags for a combined FAT library build on newer CMake versions if(PLATFORM_INT MATCHES ".*COMBINED") - set(CMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH "NO") set(CMAKE_IOS_INSTALL_COMBINED YES) - message(STATUS "Will combine built (static) artifacts into FAT lib...") + if(CMAKE_GENERATOR MATCHES "Xcode") + # Set the SDKROOT Xcode properties to a Xcode-friendly value (the SDK_NAME, E.g, iphoneos) + # This way, Xcode will automatically switch between the simulator and device SDK when building. + set(CMAKE_XCODE_ATTRIBUTE_SDKROOT "${SDK_NAME}") + # Force to not build just one ARCH, but all! + set(CMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH "NO") + endif() endif() elseif(NOT DEFINED CMAKE_SYSTEM_NAME AND ${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.10") # Legacy code path prior to CMake 3.14 or fallback if no CMAKE_SYSTEM_NAME specified set(CMAKE_SYSTEM_NAME iOS) elseif(NOT DEFINED CMAKE_SYSTEM_NAME) - # Legacy code path prior to CMake 3.14 or fallback if no CMAKE_SYSTEM_NAME specified + # Legacy code path before CMake 3.14 or fallback if no CMAKE_SYSTEM_NAME specified set(CMAKE_SYSTEM_NAME Darwin) endif() # Standard settings. set(CMAKE_SYSTEM_VERSION ${SDK_VERSION} CACHE INTERNAL "") -set(UNIX TRUE CACHE BOOL "") -set(APPLE TRUE CACHE BOOL "") -if(PLATFORM STREQUAL "MAC" OR PLATFORM STREQUAL "MAC_ARM64") - set(IOS FALSE CACHE BOOL "") - set(MACOS TRUE CACHE BOOL "") -elseif(PLATFORM STREQUAL "MAC_CATALYST" OR PLATFORM STREQUAL "MAC_CATALYST_ARM64") - set(IOS TRUE CACHE BOOL "") - set(MACOS TRUE CACHE BOOL "") +set(UNIX ON CACHE BOOL "") +set(APPLE ON CACHE BOOL "") +if(PLATFORM STREQUAL "MAC" OR PLATFORM STREQUAL "MAC_ARM64" OR PLATFORM STREQUAL "MAC_UNIVERSAL") + set(IOS OFF CACHE BOOL "") + set(MACOS ON CACHE BOOL "") +elseif(PLATFORM STREQUAL "MAC_CATALYST" OR PLATFORM STREQUAL "MAC_CATALYST_ARM64" OR PLATFORM STREQUAL "MAC_CATALYST_UNIVERSAL") + set(IOS ON CACHE BOOL "") + set(MACOS ON CACHE BOOL "") +elseif(PLATFORM STREQUAL "VISIONOS" OR PLATFORM STREQUAL "SIMULATOR_VISIONOS" OR PLATFORM STREQUAL "VISIONOSCOMBINED") + set(IOS OFF CACHE BOOL "") + set(VISIONOS ON CACHE BOOL "") else() - set(IOS TRUE CACHE BOOL "") + set(IOS ON CACHE BOOL "") endif() -set(CMAKE_AR ar CACHE FILEPATH "" FORCE) -set(CMAKE_RANLIB ranlib CACHE FILEPATH "" FORCE) -set(CMAKE_STRIP strip CACHE FILEPATH "" FORCE) # Set the architectures for which to build. set(CMAKE_OSX_ARCHITECTURES ${ARCHS} CACHE INTERNAL "") # Change the type of target generated for try_compile() so it'll work when cross-compiling, weak compiler checks @@ -660,10 +787,14 @@ if(NOT ENABLE_STRICT_TRY_COMPILE_INT) set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) endif() # All iOS/Darwin specific settings - some may be redundant. -set(CMAKE_MACOSX_BUNDLE YES) +if (NOT DEFINED CMAKE_MACOSX_BUNDLE) + set(CMAKE_MACOSX_BUNDLE YES) +endif() set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO") +set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO") set(CMAKE_SHARED_LIBRARY_PREFIX "lib") set(CMAKE_SHARED_LIBRARY_SUFFIX ".dylib") +set(CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES ".tbd" ".so") set(CMAKE_SHARED_MODULE_PREFIX "lib") set(CMAKE_SHARED_MODULE_SUFFIX ".so") set(CMAKE_C_COMPILER_ABI ELF) @@ -710,12 +841,18 @@ if(${CMAKE_VERSION} VERSION_LESS "3.11") elseif(PLATFORM_INT STREQUAL "SIMULATOR_TVOS") set(SDK_NAME_VERSION_FLAGS "-mtvos-simulator-version-min=${DEPLOYMENT_TARGET}") +elseif(PLATFORM_INT STREQUAL "SIMULATORARM64_TVOS") + set(SDK_NAME_VERSION_FLAGS + "-mtvos-simulator-version-min=${DEPLOYMENT_TARGET}") elseif(PLATFORM_INT STREQUAL "WATCHOS") set(SDK_NAME_VERSION_FLAGS "-mwatchos-version-min=${DEPLOYMENT_TARGET}") elseif(PLATFORM_INT STREQUAL "SIMULATOR_WATCHOS") set(SDK_NAME_VERSION_FLAGS "-mwatchos-simulator-version-min=${DEPLOYMENT_TARGET}") + elseif(PLATFORM_INT STREQUAL "SIMULATORARM64_WATCHOS") + set(SDK_NAME_VERSION_FLAGS + "-mwatchos-simulator-version-min=${DEPLOYMENT_TARGET}") elseif(PLATFORM_INT STREQUAL "MAC") set(SDK_NAME_VERSION_FLAGS "-mmacosx-version-min=${DEPLOYMENT_TARGET}") @@ -726,7 +863,7 @@ if(${CMAKE_VERSION} VERSION_LESS "3.11") endif() elseif(NOT PLATFORM_INT MATCHES "^MAC_CATALYST") # Newer versions of CMake sets the version min flags correctly, skip this for Mac Catalyst targets - set(CMAKE_OSX_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET}) + set(CMAKE_OSX_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET} CACHE INTERNAL "Minimum OS X deployment version") endif() if(DEFINED APPLE_TARGET_TRIPLE_INT) @@ -757,6 +894,14 @@ else() set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "NO") endif() +if(NAMED_LANGUAGE_SUPPORT_INT) + set(OBJC_VARS "-fobjc-abi-version=2 -DOBJC_OLD_DISPATCH_PROTOTYPES=0") + set(OBJC_LEGACY_VARS "") +else() + set(OBJC_VARS "") + set(OBJC_LEGACY_VARS "-fobjc-abi-version=2 -DOBJC_OLD_DISPATCH_PROTOTYPES=0") +endif() + if(NOT ENABLE_VISIBILITY_INT) foreach(lang ${languages}) set(CMAKE_${lang}_VISIBILITY_PRESET "hidden" CACHE INTERNAL "") @@ -775,35 +920,48 @@ if(DEFINED APPLE_TARGET_TRIPLE) set(APPLE_TARGET_TRIPLE_FLAG "-target ${APPLE_TARGET_TRIPLE}") endif() -#Check if Xcode generator is used, since that will handle these flags automagically +#Check if Xcode generator is used since that will handle these flags automagically if(CMAKE_GENERATOR MATCHES "Xcode") - message(STATUS "Not setting any manual command-line buildflags, since Xcode is selected as generator.") + message(STATUS "Not setting any manual command-line buildflags, since Xcode is selected as the generator. Modifying the Xcode build-settings directly instead.") else() - set(CMAKE_C_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${CMAKE_C_FLAGS}") + set(CMAKE_C_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${OBJC_LEGACY_VARS} ${BITCODE} ${VISIBILITY} ${CMAKE_C_FLAGS}" CACHE INTERNAL + "Flags used by the compiler during all C build types.") set(CMAKE_C_FLAGS_DEBUG "-O0 -g ${CMAKE_C_FLAGS_DEBUG}") set(CMAKE_C_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_C_FLAGS_MINSIZEREL}") set(CMAKE_C_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_C_FLAGS_RELWITHDEBINFO}") set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_C_FLAGS_RELEASE}") - set(CMAKE_CXX_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${CMAKE_CXX_FLAGS}") + set(CMAKE_CXX_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${OBJC_LEGACY_VARS} ${BITCODE} ${VISIBILITY} ${CMAKE_CXX_FLAGS}" CACHE INTERNAL + "Flags used by the compiler during all CXX build types.") set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g ${CMAKE_CXX_FLAGS_DEBUG}") set(CMAKE_CXX_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_CXX_FLAGS_MINSIZEREL}") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_CXX_FLAGS_RELEASE}") - set(CMAKE_OBJC_FLAGS "${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${FOBJC_ARC} -fobjc-weak -fobjc-abi-version=2 -fobjc-legacy-dispatch -DOBJC_OLD_DISPATCH_PROTOTYPES=0 ${CMAKE_OBJC_FLAGS}") - set(CMAKE_OBJC_FLAGS_DEBUG "-O0 -g ${CMAKE_OBJC_FLAGS_DEBUG}") - set(CMAKE_OBJC_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_OBJC_FLAGS_MINSIZEREL}") - set(CMAKE_OBJC_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_OBJC_FLAGS_RELWITHDEBINFO}") - set(CMAKE_OBJC_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_OBJC_FLAGS_RELEASE}") - set(CMAKE_OBJCXX_FLAGS "${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${FOBJC_ARC} -fobjc-weak -fobjc-abi-version=2 -fobjc-legacy-dispatch -DOBJC_OLD_DISPATCH_PROTOTYPES=0 ${CMAKE_OBJCXX_FLAGS}") - set(CMAKE_OBJCXX_FLAGS_DEBUG "-O0 -g ${CMAKE_OBJCXX_FLAGS_DEBUG}") - set(CMAKE_OBJCXX_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_OBJCXX_FLAGS_MINSIZEREL}") - set(CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO}") - set(CMAKE_OBJCXX_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_OBJCXX_FLAGS_RELEASE}") - set(CMAKE_C_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}") - set(CMAKE_CXX_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}") - set(CMAKE_OBJC_LINK_FLAGS "${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_OBJC_LINK_FLAGS}") - set(CMAKE_OBJCXX_LINK_FLAGS "${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_OBJCXX_LINK_FLAGS}") - set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp -arch ${CMAKE_OSX_ARCHITECTURES} ${APPLE_TARGET_TRIPLE_FLAG}") + if(NAMED_LANGUAGE_SUPPORT_INT) + set(CMAKE_OBJC_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${FOBJC_ARC} ${OBJC_VARS} ${CMAKE_OBJC_FLAGS}" CACHE INTERNAL + "Flags used by the compiler during all OBJC build types.") + set(CMAKE_OBJC_FLAGS_DEBUG "-O0 -g ${CMAKE_OBJC_FLAGS_DEBUG}") + set(CMAKE_OBJC_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_OBJC_FLAGS_MINSIZEREL}") + set(CMAKE_OBJC_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_OBJC_FLAGS_RELWITHDEBINFO}") + set(CMAKE_OBJC_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_OBJC_FLAGS_RELEASE}") + set(CMAKE_OBJCXX_FLAGS "${C_TARGET_FLAGS} ${APPLE_TARGET_TRIPLE_FLAG} ${SDK_NAME_VERSION_FLAGS} ${BITCODE} ${VISIBILITY} ${FOBJC_ARC} ${OBJC_VARS} ${CMAKE_OBJCXX_FLAGS}" CACHE INTERNAL + "Flags used by the compiler during all OBJCXX build types.") + set(CMAKE_OBJCXX_FLAGS_DEBUG "-O0 -g ${CMAKE_OBJCXX_FLAGS_DEBUG}") + set(CMAKE_OBJCXX_FLAGS_MINSIZEREL "-DNDEBUG -Os ${CMAKE_OBJCXX_FLAGS_MINSIZEREL}") + set(CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO}") + set(CMAKE_OBJCXX_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_OBJCXX_FLAGS_RELEASE}") + endif() + set(CMAKE_C_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}" CACHE INTERNAL + "Flags used by the compiler for all C link types.") + set(CMAKE_CXX_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}" CACHE INTERNAL + "Flags used by the compiler for all CXX link types.") + if(NAMED_LANGUAGE_SUPPORT_INT) + set(CMAKE_OBJC_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_OBJC_LINK_FLAGS}" CACHE INTERNAL + "Flags used by the compiler for all OBJC link types.") + set(CMAKE_OBJCXX_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_OBJCXX_LINK_FLAGS}" CACHE INTERNAL + "Flags used by the compiler for all OBJCXX link types.") + endif() + set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp -arch ${CMAKE_OSX_ARCHITECTURES} ${APPLE_TARGET_TRIPLE_FLAG}" CACHE INTERNAL + "Flags used by the compiler for all ASM build types.") endif() ## Print status messages to inform of the current state @@ -820,6 +978,9 @@ message(STATUS "Using minimum deployment version: ${DEPLOYMENT_TARGET}" " (SDK version: ${SDK_VERSION})") if(MODERN_CMAKE) message(STATUS "Merging integrated CMake 3.14+ iOS,tvOS,watchOS,macOS toolchain(s) with this toolchain!") + if(PLATFORM_INT MATCHES ".*COMBINED") + message(STATUS "Will combine built (static) artifacts into FAT lib...") + endif() endif() if(CMAKE_GENERATOR MATCHES "Xcode") message(STATUS "Using Xcode version: ${XCODE_VERSION_INT}") @@ -859,6 +1020,7 @@ set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES PLATFORM XCODE_VERSION_INT SDK_VERSION + NAMED_LANGUAGE_SUPPORT DEPLOYMENT_TARGET CMAKE_DEVELOPER_ROOT CMAKE_OSX_SYSROOT_INT @@ -881,6 +1043,13 @@ set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_RELEASE + CMAKE_C_LINK_FLAGS + CMAKE_CXX_LINK_FLAGS + CMAKE_ASM_FLAGS +) + +if(NAMED_LANGUAGE_SUPPORT_INT) + list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_OBJC_FLAGS CMAKE_OBJC_DEBUG CMAKE_OBJC_MINSIZEREL @@ -891,12 +1060,10 @@ set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_OBJCXX_MINSIZEREL CMAKE_OBJCXX_RELWITHDEBINFO CMAKE_OBJCXX_RELEASE - CMAKE_C_LINK_FLAGS - CMAKE_CXX_LINK_FLAGS CMAKE_OBJC_LINK_FLAGS CMAKE_OBJCXX_LINK_FLAGS - CMAKE_ASM_FLAGS - ) + ) +endif() set(CMAKE_PLATFORM_HAS_INSTALLNAME 1) set(CMAKE_SHARED_LINKER_FLAGS "-rpath @executable_path/Frameworks -rpath @loader_path/Frameworks") @@ -909,16 +1076,18 @@ set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-install_name") # Set the find root to the SDK developer roots. # Note: CMAKE_FIND_ROOT_PATH is only useful when cross-compiling. Thus, do not set on macOS builds. -if(NOT PLATFORM_INT STREQUAL "MAC" AND NOT PLATFORM_INT STREQUAL "MAC_ARM64") +if(NOT PLATFORM_INT MATCHES "^MAC.*$") list(APPEND CMAKE_FIND_ROOT_PATH "${CMAKE_OSX_SYSROOT_INT}" CACHE INTERNAL "") - set(CMAKE_IGNORE_PATH "/System/Library/Frameworks;/usr/local/lib" CACHE INTERNAL "") + set(CMAKE_IGNORE_PATH "/System/Library/Frameworks;/usr/local/lib;/opt/homebrew" CACHE INTERNAL "") endif() # Default to searching for frameworks first. -set(CMAKE_FIND_FRAMEWORK FIRST) +IF(NOT DEFINED CMAKE_FIND_FRAMEWORK) + set(CMAKE_FIND_FRAMEWORK FIRST) +ENDIF(NOT DEFINED CMAKE_FIND_FRAMEWORK) # Set up the default search directories for frameworks. -if(PLATFORM_INT MATCHES "^MAC_CATALYST") +if(PLATFORM_INT MATCHES "^MAC_CATALYST") set(CMAKE_FRAMEWORK_PATH ${CMAKE_DEVELOPER_ROOT}/Library/PrivateFrameworks ${CMAKE_OSX_SYSROOT_INT}/System/Library/Frameworks @@ -966,7 +1135,7 @@ macro(find_host_package) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE NEVER) set(_TOOLCHAIN_IOS ${IOS}) - set(IOS FALSE) + set(IOS OFF) find_package(${ARGN}) set(IOS ${_TOOLCHAIN_IOS}) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH) From 9fe1fe8d94bde508421af076614e940a81b0f21b Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 21 Jul 2024 08:00:37 +0200 Subject: [PATCH 343/596] use the whole panel to draw the item details --- Source/items.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/items.cpp b/Source/items.cpp index 89bc406c3a6..74e0c42955a 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -3022,19 +3022,19 @@ void PrintItemPower(BYTE plidx, const ItemStruct* is) static void PrintItemString(int x, int& y) { - PrintString(x, y, x + 257, tempstr, true, COL_WHITE, FONT_KERN_SMALL); + PrintString(x, y, x + (STPANEL_WIDTH - 2 * TPANEL_BORDER), tempstr, true, COL_WHITE, FONT_KERN_SMALL); y += 24; } static void PrintItemString(int x, int& y, const char* str) { - PrintString(x, y, x + 257, str, true, COL_WHITE, FONT_KERN_SMALL); + PrintString(x, y, x + (STPANEL_WIDTH - 2 * TPANEL_BORDER), str, true, COL_WHITE, FONT_KERN_SMALL); y += 24; } static void PrintItemString(int x, int& y, const char* str, int col) { - PrintString(x, y, x + 257, str, true, col, FONT_KERN_SMALL); + PrintString(x, y, x + (STPANEL_WIDTH - 2 * TPANEL_BORDER), str, true, col, FONT_KERN_SMALL); y += 24; } @@ -3258,7 +3258,7 @@ void DrawInvItemDetails() // add separator DrawTextBoxSLine(x, y, 74, false); - x += 8; + x += TPANEL_BORDER; y += 44; is = PlrItem(mypnum, pcursinvitem); From bafc7123ef874bfa9ae0e3e6baa1d42b53667f49 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 21 Jul 2024 08:05:44 +0200 Subject: [PATCH 344/596] reorder PrintItemMiscInfo --- Source/items.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/items.cpp b/Source/items.cpp index 74e0c42955a..e180dd9e2f3 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -3175,12 +3175,6 @@ static void PrintItemMiscInfo(const ItemStruct* is, int x, int& y) desc = "increase inner magic"; PrintItemString(x, y, desc); break; - case IMISC_OILCLEAN: - desc = "removes the affixes"; - PrintItemString(x, y, desc); - desc = "of a magic item"; - PrintItemString(x, y, desc); - break; case IMISC_OILRESIST: desc = "imbues a normal item to"; PrintItemString(x, y, desc); @@ -3193,6 +3187,12 @@ static void PrintItemMiscInfo(const ItemStruct* is, int x, int& y) desc = "a magic item"; PrintItemString(x, y, desc); break; + case IMISC_OILCLEAN: + desc = "removes the affixes"; + PrintItemString(x, y, desc); + desc = "of a magic item"; + PrintItemString(x, y, desc); + break; #ifdef HELLFIRE //case IMISC_MAPOFDOOM: // desc = "right-click to view"; From 180d3bfbcad43227338ebe1d80fe922a77bd4421 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 21 Jul 2024 08:07:17 +0200 Subject: [PATCH 345/596] set SetRndSeed in RecreateTownItem --- Source/items.cpp | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/Source/items.cpp b/Source/items.cpp index e180dd9e2f3..11ec61ffc09 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -3706,18 +3706,18 @@ void SpawnHealer(unsigned lvl) SortHealer(); } -static void RecreateSmithItem(int ii, int iseed, int idx, unsigned lvl) +static void RecreateSmithItem(int ii/*, int iseed*/, int idx, unsigned lvl) { - SetRndSeed(iseed); + // SetRndSeed(iseed); GetItemAttrs(ii, RndSmithItem(lvl), lvl); //items[ii]._iSeed = iseed; //items[ii]._iCreateInfo = lvl | CF_SMITH; } -static void RecreatePremiumItem(int ii, int iseed, int idx, unsigned lvl) +static void RecreatePremiumItem(int ii/*, int iseed*/, int idx, unsigned lvl) { - SetRndSeed(iseed); + // SetRndSeed(iseed); GetItemAttrs(ii, RndSmithItem(lvl), lvl); GetItemBonus(ii, lvl >> 1, lvl, true, false); @@ -3725,9 +3725,9 @@ static void RecreatePremiumItem(int ii, int iseed, int idx, unsigned lvl) //items[ii]._iCreateInfo = lvl | CF_SMITHPREMIUM; } -static void RecreateBoyItem(int ii, int iseed, int idx, unsigned lvl) +static void RecreateBoyItem(int ii/*, int iseed*/, int idx, unsigned lvl) { - SetRndSeed(iseed); + // SetRndSeed(iseed); GetItemAttrs(ii, RndSmithItem(lvl), lvl); GetItemBonus(ii, lvl >> 1, lvl << 1, true, true); @@ -3735,12 +3735,12 @@ static void RecreateBoyItem(int ii, int iseed, int idx, unsigned lvl) //items[ii]._iCreateInfo = lvl | CF_BOY; } -static void RecreateWitchItem(int ii, int iseed, int idx, unsigned lvl) +static void RecreateWitchItem(int ii/*, int iseed*/, int idx, unsigned lvl) { /*if (idx == IDI_MANA || idx == IDI_FULLMANA || idx == IDI_PORTAL) { SetItemData(ii, idx); } else {*/ - SetRndSeed(iseed); + // SetRndSeed(iseed); GetItemAttrs(ii, RndWitchItem(lvl), lvl); // if (random_(51, 100) <= 5 || items[ii]._itype == ITYPE_STAFF) GetItemBonus(ii, lvl >> 1, lvl, true, true); @@ -3750,12 +3750,12 @@ static void RecreateWitchItem(int ii, int iseed, int idx, unsigned lvl) //items[ii]._iCreateInfo = lvl | CF_WITCH; } -static void RecreateHealerItem(int ii, int iseed, int idx, unsigned lvl) +static void RecreateHealerItem(int ii/*, int iseed*/, int idx, unsigned lvl) { /*if (idx == IDI_HEAL || idx == IDI_FULLHEAL || idx == IDI_RESURRECT) { SetItemData(ii, idx); } else {*/ - SetRndSeed(iseed); + // SetRndSeed(iseed); GetItemAttrs(ii, RndHealerItem(lvl), lvl); //} @@ -3763,9 +3763,9 @@ static void RecreateHealerItem(int ii, int iseed, int idx, unsigned lvl) //items[ii]._iCreateInfo = lvl | CF_HEALER; } -static void RecreateCraftedItem(int ii, int iseed, int idx, unsigned lvl) +static void RecreateCraftedItem(int ii/*, int iseed*/, int idx, unsigned lvl) { - SetRndSeed(iseed); + // SetRndSeed(iseed); GetItemAttrs(ii, idx, lvl); if (random_(51, 2) != 0) GetItemBonus(ii, 0, lvl != 0 ? lvl : 1, true, true); @@ -3781,24 +3781,25 @@ void RecreateTownItem(int ii, int iseed, uint16_t idx, uint16_t icreateinfo) loc = (icreateinfo & CF_TOWN) >> 8; lvl = icreateinfo & CF_LEVEL; + SetRndSeed(iseed); switch (loc) { case CFL_SMITH: - RecreateSmithItem(ii, iseed, idx, lvl); + RecreateSmithItem(ii, /*iseed, */idx, lvl); break; case CFL_SMITHPREMIUM: - RecreatePremiumItem(ii, iseed, idx, lvl); + RecreatePremiumItem(ii, /*iseed, */idx, lvl); break; case CFL_BOY: - RecreateBoyItem(ii, iseed, idx, lvl); + RecreateBoyItem(ii, /*iseed, */idx, lvl); break; case CFL_WITCH: - RecreateWitchItem(ii, iseed, idx, lvl); + RecreateWitchItem(ii, /*iseed, */idx, lvl); break; case CFL_HEALER: - RecreateHealerItem(ii, iseed, idx, lvl); + RecreateHealerItem(ii, /*iseed, */idx, lvl); break; case CFL_CRAFTED: - RecreateCraftedItem(ii, iseed, idx, lvl); + RecreateCraftedItem(ii, /*iseed, */idx, lvl); break; default: ASSUME_UNREACHABLE; From 193adb612d0d7044f4401874058232b9143f7059 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 21 Jul 2024 08:16:25 +0200 Subject: [PATCH 346/596] naming conventions (text_render) --- Source/engine/render/text_render.cpp | 26 ++++++++++----------- Source/engine/render/text_render.h | 12 +++++----- tools/patcher/engine/render/text_render.cpp | 20 ++++++++-------- tools/patcher/engine/render/text_render.h | 6 ++--- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/Source/engine/render/text_render.cpp b/Source/engine/render/text_render.cpp index d7eb32c3bdb..82908e45b61 100644 --- a/Source/engine/render/text_render.cpp +++ b/Source/engine/render/text_render.cpp @@ -218,15 +218,15 @@ static void PrintBigColorChar(int sx, int sy, int nCel, BYTE col) } } -int PrintBigChar(int sx, int sy, BYTE text, BYTE col) +int PrintBigChar(int sx, int sy, BYTE chr, BYTE col) { - BYTE nCel = gbStdFontFrame[text]; + BYTE nCel = gbStdFontFrame[chr]; if (nCel != 0) { PrintBigColorChar(sx, sy, nCel, col); // draw optional diacritic - if (text >= 128) { - BYTE dCel = gbStdDiacFrame[text - 128]; + if (chr >= 128) { + BYTE dCel = gbStdDiacFrame[chr - 128]; if (dCel != 0) { PrintBigColorChar(sx, sy, dCel, col); } @@ -236,15 +236,15 @@ int PrintBigChar(int sx, int sy, BYTE text, BYTE col) return bigFontWidth[nCel] + FONT_KERN_BIG; } -int PrintSmallChar(int sx, int sy, BYTE text, BYTE col) +int PrintSmallChar(int sx, int sy, BYTE chr, BYTE col) { - BYTE nCel = gbStdFontFrame[text]; + BYTE nCel = gbStdFontFrame[chr]; if (nCel != 0) { PrintSmallColorChar(sx, sy, nCel, col); // draw optional diacritic - if (text >= 128) { - BYTE dCel = gbStdDiacFrame[text - 128]; + if (chr >= 128) { + BYTE dCel = gbStdDiacFrame[chr - 128]; if (dCel != 0) { PrintSmallColorChar(sx, sy, dCel, col); } @@ -254,9 +254,9 @@ int PrintSmallChar(int sx, int sy, BYTE text, BYTE col) return smallFontWidth[nCel] + FONT_KERN_SMALL; } -int PrintHugeChar(int sx, int sy, BYTE text, BYTE col) +int PrintHugeChar(int sx, int sy, BYTE chr, BYTE col) { - BYTE nCel = gbHugeFontFrame[text]; + BYTE nCel = gbHugeFontFrame[chr]; if (nCel != 0) { // PrintHugeColorChar(sx, sy, nCel, col); @@ -318,19 +318,19 @@ void PrintGameStr(int x, int y, const char* text, BYTE color) * @param x Screen coordinate * @param y Screen coordinate * @param endX End of line in screen coordinate - * @param pszStr String to print, in Windows-1252 encoding + * @param text String to print, in Windows-1252 encoding * @param center * @param col text_color color value * @param kern Letter spacing */ -void PrintString(int x, int y, int endX, const char* text, bool cjustflag, BYTE col, int kern) +void PrintString(int x, int y, int endX, const char* text, bool center, BYTE col, int kern) { BYTE c; const char* tmp; int strEnd; int k; - if (cjustflag) { + if (center) { strEnd = x; tmp = text; while (*tmp != '\0') { diff --git a/Source/engine/render/text_render.h b/Source/engine/render/text_render.h index 6a41f8ce40f..1595f8ae244 100644 --- a/Source/engine/render/text_render.h +++ b/Source/engine/render/text_render.h @@ -32,13 +32,13 @@ int GetBigStringWidth(const char* text); int GetSmallStringWidth(const char* text); void PrintSmallColorChar(int sx, int sy, int nCel, BYTE col); -int PrintSmallChar(int sx, int sy, BYTE text, BYTE col); -int PrintBigChar(int sx, int sy, BYTE text, BYTE col); -int PrintHugeChar(int sx, int sy, BYTE text, BYTE col); -void PrintString(int x, int y, int endX, const char* pszStr, bool center, BYTE col, int kern); -void PrintGameStr(int x, int y, const char* str, BYTE color); +int PrintSmallChar(int sx, int sy, BYTE chr, BYTE col); +int PrintBigChar(int sx, int sy, BYTE chr, BYTE col); +int PrintHugeChar(int sx, int sy, BYTE chr, BYTE col); +void PrintString(int x, int y, int endX, const char* text, bool center, BYTE col, int kern); +void PrintGameStr(int x, int y, const char* text, BYTE color); int PrintLimitedString(int x, int y, const char* text, int limit, BYTE col); -void PrintHugeString(int x, int y, const char* pszStr, int light); +void PrintHugeString(int x, int y, const char* text, int light); void DrawHugePentSpn(int x1, int x2, int y); void DrawSmallPentSpn(int x1, int x2, int y); diff --git a/tools/patcher/engine/render/text_render.cpp b/tools/patcher/engine/render/text_render.cpp index 1d265fc19c6..b54efadc0f3 100644 --- a/tools/patcher/engine/render/text_render.cpp +++ b/tools/patcher/engine/render/text_render.cpp @@ -218,15 +218,15 @@ static void PrintBigColorChar(int sx, int sy, int nCel, BYTE col) } } -int PrintBigChar(int sx, int sy, BYTE text, BYTE col) +int PrintBigChar(int sx, int sy, BYTE chr, BYTE col) { - BYTE nCel = gbStdFontFrame[text]; + BYTE nCel = gbStdFontFrame[chr]; if (nCel != 0) { PrintBigColorChar(sx, sy, nCel, col); // draw optional diacritic - if (text >= 128) { - BYTE dCel = gbStdDiacFrame[text - 128]; + if (chr >= 128) { + BYTE dCel = gbStdDiacFrame[chr - 128]; if (dCel != 0) { PrintBigColorChar(sx, sy, dCel, col); } @@ -236,15 +236,15 @@ int PrintBigChar(int sx, int sy, BYTE text, BYTE col) return bigFontWidth[nCel] + FONT_KERN_BIG; } -int PrintSmallChar(int sx, int sy, BYTE text, BYTE col) +int PrintSmallChar(int sx, int sy, BYTE chr, BYTE col) { - BYTE nCel = gbStdFontFrame[text]; + BYTE nCel = gbStdFontFrame[chr]; if (nCel != 0) { PrintSmallColorChar(sx, sy, nCel, col); // draw optional diacritic - if (text >= 128) { - BYTE dCel = gbStdDiacFrame[text - 128]; + if (chr >= 128) { + BYTE dCel = gbStdDiacFrame[chr - 128]; if (dCel != 0) { PrintSmallColorChar(sx, sy, dCel, col); } @@ -254,9 +254,9 @@ int PrintSmallChar(int sx, int sy, BYTE text, BYTE col) return smallFontWidth[nCel] + FONT_KERN_SMALL; } -int PrintHugeChar(int sx, int sy, BYTE text, BYTE col) +int PrintHugeChar(int sx, int sy, BYTE chr, BYTE col) { - BYTE nCel = gbHugeFontFrame[text]; + BYTE nCel = gbHugeFontFrame[chr]; if (nCel != 0) { // PrintHugeColorChar(sx, sy, nCel, col); diff --git a/tools/patcher/engine/render/text_render.h b/tools/patcher/engine/render/text_render.h index a5fcbfcf327..2d2d8078512 100644 --- a/tools/patcher/engine/render/text_render.h +++ b/tools/patcher/engine/render/text_render.h @@ -31,9 +31,9 @@ int GetHugeStringWidth(const char* text); int GetBigStringWidth(const char* text); int GetSmallStringWidth(const char* text); -int PrintSmallChar(int sx, int sy, BYTE text, BYTE col); -int PrintBigChar(int sx, int sy, BYTE text, BYTE col); -int PrintHugeChar(int sx, int sy, BYTE text, BYTE col); +int PrintSmallChar(int sx, int sy, BYTE chr, BYTE col); +int PrintBigChar(int sx, int sy, BYTE chr, BYTE col); +int PrintHugeChar(int sx, int sy, BYTE chr, BYTE col); #ifdef __cplusplus } From a3e770ba52fa7e11b8ad7c2181382307ca3f06c6 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 21 Jul 2024 08:29:19 +0200 Subject: [PATCH 347/596] add separate PrintJustifiedString --- Source/control.cpp | 72 ++++++++++++++-------------- Source/engine/render/text_render.cpp | 45 +++++++++++------ Source/engine/render/text_render.h | 3 +- Source/error.cpp | 2 +- Source/interfac.cpp | 2 +- Source/items.cpp | 6 +-- 6 files changed, 73 insertions(+), 57 deletions(-) diff --git a/Source/control.cpp b/Source/control.cpp index 5f09f169eed..865d378d34d 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -286,7 +286,7 @@ static void DrawSpellIconOverlay(int x, int y, int sn, int st) ASSUME_UNREACHABLE return; } - PrintString(x + SPLICON_OVERX, y, x + SPLICON_WIDTH - SPLICON_OVERX, tempstr, true, t, FONT_KERN_SMALL); + PrintJustifiedString(x + SPLICON_OVERX, y, x + SPLICON_WIDTH - SPLICON_OVERX, tempstr, t, FONT_KERN_SMALL); } static void DrawSkillIcon(int pnum, BYTE spl, BYTE st, BYTE offset) @@ -1016,7 +1016,7 @@ void DrawCtrlBtns() pb = gabPanbtn[i]; CelDraw(x, y + MENUBTN_HEIGHT - 1, pPanelButtonCels, 2); // print the text of the button - PrintString(x + 3, y + (MENUBTN_HEIGHT + SMALL_FONT_HEIGHT) / 2, x + MENUBTN_WIDTH - 1, PanBtnTxt[i], true, pb ? COL_GOLD : COL_WHITE, FONT_KERN_SMALL); + PrintJustifiedString(x + 3, y + (MENUBTN_HEIGHT + SMALL_FONT_HEIGHT) / 2, x + MENUBTN_WIDTH - 1, PanBtnTxt[i], pb ? COL_GOLD : COL_WHITE, FONT_KERN_SMALL); } } @@ -1242,17 +1242,17 @@ void DrawChr() screen_x = SCREEN_X + gnWndCharX; screen_y = SCREEN_Y + gnWndCharY; CelDraw(screen_x, screen_y + SPANEL_HEIGHT - 1, pChrPanelCel, 1); - PrintString(screen_x + 5, screen_y + 19, screen_x + 144, p->_pName, true, COL_WHITE, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 5, screen_y + 19, screen_x + 144, p->_pName, COL_WHITE, FONT_KERN_SMALL); - PrintString(screen_x + 153, screen_y + 19, screen_x + 292, ClassStrTbl[pc], true, COL_WHITE, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 153, screen_y + 19, screen_x + 292, ClassStrTbl[pc], COL_WHITE, FONT_KERN_SMALL); col = COL_WHITE; snprintf(chrstr, sizeof(chrstr), "%d", p->_pLevel); - PrintString(screen_x + 53, screen_y + 46, screen_x + 96, chrstr, true, col, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 53, screen_y + 46, screen_x + 96, chrstr, col, FONT_KERN_SMALL); col = COL_WHITE; snprintf(chrstr, sizeof(chrstr), "%d", p->_pExperience); - PrintString(screen_x + 200, screen_y + 46, screen_x + 292, chrstr, true, col, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 200, screen_y + 46, screen_x + 292, chrstr, col, FONT_KERN_SMALL); if (p->_pLevel == MAXCHARLEVEL) { copy_cstr(chrstr, "None"); @@ -1261,33 +1261,33 @@ void DrawChr() snprintf(chrstr, sizeof(chrstr), "%d", p->_pNextExper); col = COL_WHITE; } - PrintString(screen_x + 200, screen_y + 71, screen_x + 292, chrstr, true, col, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 200, screen_y + 71, screen_x + 292, chrstr, col, FONT_KERN_SMALL); col = COL_WHITE; snprintf(chrstr, sizeof(chrstr), "%d", p->_pGold); - PrintString(screen_x + 221, screen_y + 97, screen_x + 292, chrstr, true, col, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 221, screen_y + 97, screen_x + 292, chrstr, col, FONT_KERN_SMALL); col = COL_WHITE; snprintf(chrstr, sizeof(chrstr), "%d", p->_pBaseStr); - PrintString(screen_x + 88, screen_y + 119, screen_x + 125, chrstr, true, col, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 88, screen_y + 119, screen_x + 125, chrstr, col, FONT_KERN_SMALL); col = COL_WHITE; snprintf(chrstr, sizeof(chrstr), "%d", p->_pBaseMag); - PrintString(screen_x + 88, screen_y + 147, screen_x + 125, chrstr, true, col, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 88, screen_y + 147, screen_x + 125, chrstr, col, FONT_KERN_SMALL); col = COL_WHITE; snprintf(chrstr, sizeof(chrstr), "%d", p->_pBaseDex); - PrintString(screen_x + 88, screen_y + 175, screen_x + 125, chrstr, true, col, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 88, screen_y + 175, screen_x + 125, chrstr, col, FONT_KERN_SMALL); col = COL_WHITE; snprintf(chrstr, sizeof(chrstr), "%d", p->_pBaseVit); - PrintString(screen_x + 88, screen_y + 203, screen_x + 125, chrstr, true, col, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 88, screen_y + 203, screen_x + 125, chrstr, col, FONT_KERN_SMALL); showStats = p->_pStatPts <= 0; if (!showStats) { showStats = (SDL_GetModState() & KMOD_ALT) != 0; snprintf(chrstr, sizeof(chrstr), "%d", p->_pStatPts); - PrintString(screen_x + 88, screen_y + 231, screen_x + 125, chrstr, true, COL_RED, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 88, screen_y + 231, screen_x + 125, chrstr, COL_RED, FONT_KERN_SMALL); int sx = screen_x + (showStats ? CHRBTN_ALT : CHRBTN_LEFT); CelDraw(sx, screen_y + CHRBTN_TOP(ATTRIB_STR) + CHRBTN_HEIGHT - 1, pChrButtonCels, gabChrbtn[ATTRIB_STR] ? 2 : 1); CelDraw(sx, screen_y + CHRBTN_TOP(ATTRIB_MAG) + CHRBTN_HEIGHT - 1, pChrButtonCels, gabChrbtn[ATTRIB_MAG] ? 2 : 1); @@ -1306,7 +1306,7 @@ void DrawChr() else if (val < p->_pBaseStr) col = COL_RED; snprintf(chrstr, sizeof(chrstr), "%d", val); - PrintString(screen_x + 135, screen_y + 119, screen_x + 172, chrstr, true, col, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 135, screen_y + 119, screen_x + 172, chrstr, col, FONT_KERN_SMALL); val = p->_pMagic; col = COL_WHITE; @@ -1315,7 +1315,7 @@ void DrawChr() else if (val < p->_pBaseMag) col = COL_RED; snprintf(chrstr, sizeof(chrstr), "%d", val); - PrintString(screen_x + 135, screen_y + 147, screen_x + 172, chrstr, true, col, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 135, screen_y + 147, screen_x + 172, chrstr, col, FONT_KERN_SMALL); val = p->_pDexterity; col = COL_WHITE; @@ -1324,7 +1324,7 @@ void DrawChr() else if (val < p->_pBaseDex) col = COL_RED; snprintf(chrstr, sizeof(chrstr), "%d", val); - PrintString(screen_x + 135, screen_y + 175, screen_x + 172, chrstr, true, col, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 135, screen_y + 175, screen_x + 172, chrstr, col, FONT_KERN_SMALL); val = p->_pVitality; col = COL_WHITE; @@ -1333,16 +1333,16 @@ void DrawChr() else if (val < p->_pBaseVit) col = COL_RED; snprintf(chrstr, sizeof(chrstr), "%d", val); - PrintString(screen_x + 135, screen_y + 203, screen_x + 172, chrstr, true, col, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 135, screen_y + 203, screen_x + 172, chrstr, col, FONT_KERN_SMALL); } snprintf(chrstr, sizeof(chrstr), "%d/%d", p->_pIAC, p->_pIEvasion); // instead of (242;291) x-limits, (239;294) are used to make sure the values are displayed - PrintString(screen_x + 239, screen_y + 122, screen_x + 294, chrstr, true, COL_WHITE, -1); + PrintJustifiedString(screen_x + 239, screen_y + 122, screen_x + 294, chrstr, COL_WHITE, -1); snprintf(chrstr, sizeof(chrstr), "%d/%d", p->_pIBlockChance, p->_pICritChance / 2); // instead of (242;291) x-limits, (241;292) are used to make sure the values are displayed - PrintString(screen_x + 241, screen_y + 150, screen_x + 292, chrstr, true, COL_WHITE, -1); + PrintJustifiedString(screen_x + 241, screen_y + 150, screen_x + 292, chrstr, COL_WHITE, -1); val = p->_pIHitChance; col = COL_WHITE; @@ -1351,7 +1351,7 @@ void DrawChr() else if (p->_pIBaseHitBonus == IBONUS_NEGATIVE) col = COL_RED; snprintf(chrstr, sizeof(chrstr), "%d%%", val); - PrintString(screen_x + 242, screen_y + 178, screen_x + 291, chrstr, true, col, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 242, screen_y + 178, screen_x + 291, chrstr, col, FONT_KERN_SMALL); col = COL_WHITE; mindam = (p->_pIFMinDam + p->_pILMinDam + p->_pIMMinDam + p->_pIAMinDam) >> 6; @@ -1362,7 +1362,7 @@ void DrawChr() maxdam += (p->_pISlMaxDam + p->_pIBlMaxDam + p->_pIPcMaxDam) >> (6 + 1); snprintf(chrstr, sizeof(chrstr), "%d-%d", mindam, maxdam); // instead of (242;291) x-limits, (240;293) are used to make sure the values are displayed - PrintString(screen_x + 240, screen_y + 206, screen_x + 293, chrstr, true, col, mindam < 100 ? 0 : -1); + PrintJustifiedString(screen_x + 240, screen_y + 206, screen_x + 293, chrstr, col, mindam < 100 ? 0 : -1); val = p->_pMagResist; if (val < MAXRESIST) { @@ -1372,7 +1372,7 @@ void DrawChr() col = COL_GOLD; copy_cstr(chrstr, "MAX"); } - PrintString(screen_x + 185, screen_y + 254, screen_x + 234, chrstr, true, col, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 185, screen_y + 254, screen_x + 234, chrstr, col, FONT_KERN_SMALL); val = p->_pFireResist; if (val < MAXRESIST) { @@ -1382,7 +1382,7 @@ void DrawChr() col = COL_GOLD; copy_cstr(chrstr, "MAX"); } - PrintString(screen_x + 242, screen_y + 254, screen_x + 291, chrstr, true, col, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 242, screen_y + 254, screen_x + 291, chrstr, col, FONT_KERN_SMALL); val = p->_pLghtResist; if (val < MAXRESIST) { @@ -1392,7 +1392,7 @@ void DrawChr() col = COL_GOLD; copy_cstr(chrstr, "MAX"); } - PrintString(screen_x + 185, screen_y + 289, screen_x + 234, chrstr, true, col, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 185, screen_y + 289, screen_x + 234, chrstr, col, FONT_KERN_SMALL); val = p->_pAcidResist; if (val < MAXRESIST) { @@ -1402,25 +1402,25 @@ void DrawChr() col = COL_GOLD; copy_cstr(chrstr, "MAX"); } - PrintString(screen_x + 242, screen_y + 289, screen_x + 291, chrstr, true, col, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 242, screen_y + 289, screen_x + 291, chrstr, col, FONT_KERN_SMALL); val = p->_pMaxHP; col = val <= p->_pMaxHPBase ? COL_WHITE : COL_BLUE; snprintf(chrstr, sizeof(chrstr), "%d", val >> 6); - PrintString(screen_x + 87, screen_y + 260, screen_x + 126, chrstr, true, col, FONT_KERN_SMALL); // 88, 125 -> 87, 126 otherwise '1000' is truncated + PrintJustifiedString(screen_x + 87, screen_y + 260, screen_x + 126, chrstr, col, FONT_KERN_SMALL); // 88, 125 -> 87, 126 otherwise '1000' is truncated if (p->_pHitPoints != val) col = COL_RED; snprintf(chrstr, sizeof(chrstr), "%d", p->_pHitPoints >> 6); - PrintString(screen_x + 134, screen_y + 260, screen_x + 173, chrstr, true, col, FONT_KERN_SMALL); // 135, 172 -> 134, 173 otherwise '1000' is truncated + PrintJustifiedString(screen_x + 134, screen_y + 260, screen_x + 173, chrstr, col, FONT_KERN_SMALL); // 135, 172 -> 134, 173 otherwise '1000' is truncated val = p->_pMaxMana; col = val <= p->_pMaxManaBase ? COL_WHITE : COL_BLUE; snprintf(chrstr, sizeof(chrstr), "%d", val >> 6); - PrintString(screen_x + 87, screen_y + 288, screen_x + 126, chrstr, true, col, FONT_KERN_SMALL); // 88, 125 -> 87, 126 otherwise '1000' is truncated + PrintJustifiedString(screen_x + 87, screen_y + 288, screen_x + 126, chrstr, col, FONT_KERN_SMALL); // 88, 125 -> 87, 126 otherwise '1000' is truncated if (p->_pMana != val) col = COL_RED; snprintf(chrstr, sizeof(chrstr), "%d", p->_pMana >> 6); - PrintString(screen_x + 134, screen_y + 288, screen_x + 173, chrstr, true, col, FONT_KERN_SMALL); // 135, 172 -> 134, 173 otherwise '1000' is truncated + PrintJustifiedString(screen_x + 134, screen_y + 288, screen_x + 173, chrstr, col, FONT_KERN_SMALL); // 135, 172 -> 134, 173 otherwise '1000' is truncated } void DrawLevelUpIcon() @@ -1429,7 +1429,7 @@ void DrawLevelUpIcon() screen_x = SCREEN_X + LVLUP_LEFT; screen_y = PANEL_Y + PANEL_HEIGHT - LVLUP_OFFSET; - PrintString(screen_x - 38, screen_y + 20, screen_x - 38 + 120, "Level Up", true, COL_WHITE, FONT_KERN_SMALL); + PrintJustifiedString(screen_x - 38, screen_y + 20, screen_x - 38 + 120, "Level Up", COL_WHITE, FONT_KERN_SMALL); CelDraw(screen_x, screen_y, pChrButtonCels, gbLvlbtndown ? 2 : 1); } @@ -1968,7 +1968,7 @@ void DrawSpellBook() CelDraw(sx, yp + SPANEL_HEIGHT - 1, pSpellBkCel, 1); // selected page snprintf(tempstr, sizeof(tempstr), "%d.", guBooktab + 1); - PrintString(sx + 2, yp + SPANEL_HEIGHT - 7, sx + SPANEL_WIDTH, tempstr, true, COL_WHITE, 0); + PrintJustifiedString(sx + 2, yp + SPANEL_HEIGHT - 7, sx + SPANEL_WIDTH, tempstr, COL_WHITE, 0); #if SCREEN_READER_INTEGRATION BYTE prevSkill = currSkill; @@ -2109,10 +2109,10 @@ void DrawGoldSplit(int amount) CelDraw(screen_x, screen_y, pGoldDropCel, 1); snprintf(tempstr, sizeof(tempstr), "You have %d gold", initialDropGoldValue); - PrintString(screen_x + 15, screen_y - (18 + 18 * 4), screen_x + GOLDDROP_WIDTH - 15, tempstr, true, COL_GOLD, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 15, screen_y - (18 + 18 * 4), screen_x + GOLDDROP_WIDTH - 15, tempstr, COL_GOLD, FONT_KERN_SMALL); snprintf(tempstr, sizeof(tempstr), "%s. How many do", get_pieces_str(initialDropGoldValue)); - PrintString(screen_x + 15, screen_y - (18 + 18 * 3), screen_x + GOLDDROP_WIDTH - 15, tempstr, true, COL_GOLD, FONT_KERN_SMALL); - PrintString(screen_x + 15, screen_y - (18 + 18 * 2), screen_x + GOLDDROP_WIDTH - 15, "you want to remove?", true, COL_GOLD, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 15, screen_y - (18 + 18 * 3), screen_x + GOLDDROP_WIDTH - 15, tempstr, COL_GOLD, FONT_KERN_SMALL); + PrintJustifiedString(screen_x + 15, screen_y - (18 + 18 * 2), screen_x + GOLDDROP_WIDTH - 15, "you want to remove?", COL_GOLD, FONT_KERN_SMALL); screen_x += 37; screen_y -= 18 + 18 * 1; if (amount > 0) { @@ -2214,7 +2214,7 @@ void DrawTeamBook() CelDraw(sx, yp + SPANEL_HEIGHT - 1, pSpellBkCel, 1); // selected page snprintf(tempstr, sizeof(tempstr), "%d.", guTeamTab + 1); - PrintString(sx + 2, yp + SPANEL_HEIGHT - 7, sx + SPANEL_WIDTH, tempstr, true, COL_WHITE, 0); + PrintJustifiedString(sx + 2, yp + SPANEL_HEIGHT - 7, sx + SPANEL_WIDTH, tempstr, COL_WHITE, 0); hasTeam = PlrHasTeam(); @@ -2227,7 +2227,7 @@ void DrawTeamBook() if (!plr._pActive) continue; // name - PrintString(sx + SBOOK_LINE_TAB, yp - 25, sx + SBOOK_LINE_TAB + SBOOK_LINE_LENGTH, plr._pName, false, COL_WHITE, 0); + PrintString(sx + SBOOK_LINE_TAB, yp - 25, sx + SBOOK_LINE_TAB + SBOOK_LINE_LENGTH, plr._pName, COL_WHITE, 0); // class(level) - team static_assert(MAXCHARLEVEL < 100, "Level must fit to the TeamBook."); snprintf(tempstr, sizeof(tempstr), "%s (lvl:%2d) %c", ClassStrTbl[plr._pClass], plr._pLevel, 'a' + plr._pTeam); diff --git a/Source/engine/render/text_render.cpp b/Source/engine/render/text_render.cpp index 82908e45b61..50851a41bfa 100644 --- a/Source/engine/render/text_render.cpp +++ b/Source/engine/render/text_render.cpp @@ -319,28 +319,14 @@ void PrintGameStr(int x, int y, const char* text, BYTE color) * @param y Screen coordinate * @param endX End of line in screen coordinate * @param text String to print, in Windows-1252 encoding - * @param center * @param col text_color color value * @param kern Letter spacing */ -void PrintString(int x, int y, int endX, const char* text, bool center, BYTE col, int kern) +void PrintString(int x, int y, int endX, const char* text, BYTE col, int kern) { BYTE c; - const char* tmp; - int strEnd; int k; - if (center) { - strEnd = x; - tmp = text; - while (*tmp != '\0') { - c = gbStdFontFrame[(BYTE)*tmp++]; - strEnd += smallFontWidth[c] + kern; - } - if (strEnd < endX) { - x += (endX - strEnd) >> 1; - } - } while (*text != '\0') { c = gbStdFontFrame[(BYTE)*text++]; k = smallFontWidth[c] + kern; @@ -351,6 +337,35 @@ void PrintString(int x, int y, int endX, const char* text, bool center, BYTE col } } +/** + * @brief Render text string justified to the back buffer + * @param x Screen coordinate + * @param y Screen coordinate + * @param endX End of line in screen coordinate + * @param text String to print, in Windows-1252 encoding + * @param col text_color color value + * @param kern Letter spacing + */ +void PrintJustifiedString(int x, int y, int endX, const char* text, BYTE col, int kern) +{ + BYTE c; + const char* tmp; + int strEnd; + int k; + + strEnd = x; + tmp = text; + while (*tmp != '\0') { + c = gbStdFontFrame[(BYTE)*tmp++]; + strEnd += smallFontWidth[c] + kern; + } + if (strEnd < endX) { + x += (endX - strEnd) >> 1; + } + + PrintString(x, y, endX, text, col, kern); +} + int PrintLimitedString(int x, int y, const char* text, int limit, BYTE col) { BYTE c; diff --git a/Source/engine/render/text_render.h b/Source/engine/render/text_render.h index 1595f8ae244..a3cb7f0f80d 100644 --- a/Source/engine/render/text_render.h +++ b/Source/engine/render/text_render.h @@ -35,7 +35,8 @@ void PrintSmallColorChar(int sx, int sy, int nCel, BYTE col); int PrintSmallChar(int sx, int sy, BYTE chr, BYTE col); int PrintBigChar(int sx, int sy, BYTE chr, BYTE col); int PrintHugeChar(int sx, int sy, BYTE chr, BYTE col); -void PrintString(int x, int y, int endX, const char* text, bool center, BYTE col, int kern); +void PrintString(int x, int y, int endX, const char* text, BYTE col, int kern); +void PrintJustifiedString(int x, int y, int endX, const char* text, BYTE col, int kern); void PrintGameStr(int x, int y, const char* text, BYTE color); int PrintLimitedString(int x, int y, const char* text, int limit, BYTE col); void PrintHugeString(int x, int y, const char* text, int light); diff --git a/Source/error.cpp b/Source/error.cpp index ec7dc9977da..13adbb61b3c 100644 --- a/Source/error.cpp +++ b/Source/error.cpp @@ -143,7 +143,7 @@ void DrawDiabloMsg() DrawRectTrans(x + SLIDER_BORDER, y - SLIDER_BOX_HEIGHT + SLIDER_BORDER, (3 * SLIDER_BOX_WIDTH) / 2 - 2 * SLIDER_BORDER, (SLIDER_BOX_HEIGHT - 2 * SLIDER_BORDER), PAL_BLACK); // print the message SStrCopy(tempstr, MsgStrings[currmsg], sizeof(tempstr)); - PrintString(x, y - (SLIDER_BOX_HEIGHT - SMALL_FONT_HEIGHT) / 2, x + (3 * SLIDER_BOX_WIDTH) / 2, tempstr, true, COL_GOLD, FONT_KERN_SMALL); + PrintJustifiedString(x, y - (SLIDER_BOX_HEIGHT - SMALL_FONT_HEIGHT) / 2, x + (3 * SLIDER_BOX_WIDTH) / 2, tempstr, COL_GOLD, FONT_KERN_SMALL); if (msgdelay > 0 && msgdelay <= SDL_GetTicks() - 3500) { msgdelay = 0; diff --git a/Source/interfac.cpp b/Source/interfac.cpp index 0bf0d06f74e..5a1de4497e3 100644 --- a/Source/interfac.cpp +++ b/Source/interfac.cpp @@ -128,7 +128,7 @@ static void DrawProgress() /* 16 */"Fadeout", }; unsigned progress = sgdwProgress / ((BAR_WIDTH + (lengthof(progession) - 1)) / lengthof(progession)); - PrintString(screen_x + 10, screen_y + (BAR_HEIGHT - SMALL_FONT_HEIGHT) / 2 + SMALL_FONT_HEIGHT, screen_x + BAR_WIDTH - 20, progress < (unsigned)lengthof(progession) ? progession[progress] : "Unknown", false, COL_WHITE, 1); + PrintString(screen_x + 10, screen_y + (BAR_HEIGHT - SMALL_FONT_HEIGHT) / 2 + SMALL_FONT_HEIGHT, screen_x + BAR_WIDTH - 20, progress < (unsigned)lengthof(progession) ? progession[progress] : "Unknown", COL_WHITE, FONT_KERN_SMALL); #endif } diff --git a/Source/items.cpp b/Source/items.cpp index 11ec61ffc09..826fbbaa19b 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -3022,19 +3022,19 @@ void PrintItemPower(BYTE plidx, const ItemStruct* is) static void PrintItemString(int x, int& y) { - PrintString(x, y, x + (STPANEL_WIDTH - 2 * TPANEL_BORDER), tempstr, true, COL_WHITE, FONT_KERN_SMALL); + PrintJustifiedString(x, y, x + (STPANEL_WIDTH - 2 * TPANEL_BORDER), tempstr, COL_WHITE, FONT_KERN_SMALL); y += 24; } static void PrintItemString(int x, int& y, const char* str) { - PrintString(x, y, x + (STPANEL_WIDTH - 2 * TPANEL_BORDER), str, true, COL_WHITE, FONT_KERN_SMALL); + PrintJustifiedString(x, y, x + (STPANEL_WIDTH - 2 * TPANEL_BORDER), str, COL_WHITE, FONT_KERN_SMALL); y += 24; } static void PrintItemString(int x, int& y, const char* str, int col) { - PrintString(x, y, x + (STPANEL_WIDTH - 2 * TPANEL_BORDER), str, true, col, FONT_KERN_SMALL); + PrintJustifiedString(x, y, x + (STPANEL_WIDTH - 2 * TPANEL_BORDER), str, col, FONT_KERN_SMALL); y += 24; } From 4fec14b6c3dc7201a95e2962fd5fcb578cb395c5 Mon Sep 17 00:00:00 2001 From: Byrgius <140657444+Byrgiuss@users.noreply.github.com> Date: Sun, 21 Jul 2024 21:16:04 +0300 Subject: [PATCH 348/596] Turkish Translation (#7197) --- .../app/src/main/res/values-tr/strings.xml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 android-project/app/src/main/res/values-tr/strings.xml diff --git a/android-project/app/src/main/res/values-tr/strings.xml b/android-project/app/src/main/res/values-tr/strings.xml new file mode 100644 index 00000000000..f874370d024 --- /dev/null +++ b/android-project/app/src/main/res/values-tr/strings.xml @@ -0,0 +1,14 @@ + + DevilutionX + + + Tam sürümü oynayabilmek için orjinal oyunun DIABDAT.MPQ dosyasını Android/data/org.diasurgical.devilutionx/files konumuna atmalısınız.
    \n
    \nEğer orjinal oyuna sahip değilseniz Diablo'yu bu linkten satın alabilirsiniz: GOG.com.
    + + Daha fazla ayrıntı için lütfen kontrol edin: Kurulum Talimatları + Tekrar kontrol et + Oyun Dosyaları + + Oyun dosyaları eksik + + +
    From 6c6a6b8d79a7ba98160f920ebaa6429164f4b868 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Sun, 21 Jul 2024 19:42:54 +0100 Subject: [PATCH 349/596] values-tr/strings.xml: Escape single quote --- android-project/app/src/main/res/values-tr/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android-project/app/src/main/res/values-tr/strings.xml b/android-project/app/src/main/res/values-tr/strings.xml index f874370d024..d56463dda40 100644 --- a/android-project/app/src/main/res/values-tr/strings.xml +++ b/android-project/app/src/main/res/values-tr/strings.xml @@ -2,7 +2,7 @@ DevilutionX - Tam sürümü oynayabilmek için orjinal oyunun DIABDAT.MPQ dosyasını Android/data/org.diasurgical.devilutionx/files konumuna atmalısınız.
    \n
    \nEğer orjinal oyuna sahip değilseniz Diablo'yu bu linkten satın alabilirsiniz: GOG.com.
    + Tam sürümü oynayabilmek için orjinal oyunun DIABDAT.MPQ dosyasını Android/data/org.diasurgical.devilutionx/files konumuna atmalısınız.
    \n
    \nEğer orjinal oyuna sahip değilseniz Diablo\'yu bu linkten satın alabilirsiniz: GOG.com.
    Daha fazla ayrıntı için lütfen kontrol edin: Kurulum Talimatları Tekrar kontrol et From 97c1e0fca4acd356e5379c969a2967eff3501f90 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jul 2024 07:33:21 +0200 Subject: [PATCH 350/596] Bump softprops/action-gh-release from 2.0.6 to 2.0.8 (#11) Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.0.6 to 2.0.8. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/v2.0.6...v2.0.8) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/nightly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index a33b23ba2b3..12cdec98fc8 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1569,7 +1569,7 @@ jobs: shell: bash - name: Release - uses: softprops/action-gh-release@v2.0.6 + uses: softprops/action-gh-release@v2.0.8 with: tag_name: devilx-nightly body_path: ${{ github.workspace }}/RELEASE_NOTE.md From c1fddf5054aad4985b440b43f50d4a22442fe66e Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 24 Jul 2024 13:19:50 +0200 Subject: [PATCH 351/596] bugfixes to handle the stone curse properly - do not modify the MonsterStruct if the stone curse is too weak - add shatter animation if the missile expire in the same round as the monster die --- Source/missiles.cpp | 54 +++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 4217afd1dd1..d1115dc1ced 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -2700,9 +2700,21 @@ int AddStone(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in mid = dMonster[tx][ty] - 1; if (mid < MAX_MINIONS || !LineClear(sx, sy, tx, ty)) continue; + assert(mid < MAXMONSTERS); mon = &monsters[mid]; if (!(mon->_mFlags & MFLAG_NOSTONE) && !CanTalkToMonst(mid) && mon->_mmode != MM_FADEIN && mon->_mmode != MM_FADEOUT && mon->_mmode != MM_CHARGE && mon->_mmode != MM_STONE && mon->_mmode != MM_DEATH /*mon->_mhitpoints >= (1 << 6*/) { + // range = (sl * 128 - HP + 128) * 2 + range = ((spllvl + 1) << (7 + 6)) - mon->_mmaxhp; + // TODO: add support for spell duration modifier + //range += (range * plx(misource)._pISplDur) >> 7; + range >>= 5; + if (range < 15) + return MIRES_DELETE; + if (range > 239) + range = 239; + mis->_miRange = range; + MonLeaveLeader(mid); mis->_miVar1 = mon->_mmode; mis->_miVar2 = mid; @@ -2716,16 +2728,6 @@ int AddStone(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in // assert(!MON_RELAXED); } - // range = (sl * 128 - HP + 128) * 2 - range = ((spllvl + 1) << (7 + 6)) - mon->_mmaxhp; - // TODO: add support for spell duration modifier - //range += (range * plx(misource)._pISplDur) >> 7; - range >>= 5; - if (range < 15) - return MIRES_DELETE; - if (range > 239) - range = 239; - mis->_miRange = range; return MIRES_DONE; } } @@ -4370,25 +4372,13 @@ void MI_Stone(int mi) dead = mon->_mhitpoints < (1 << 6); // assert(mon->_mmode == MM_STONE); mis->_miRange--; - if (mis->_miRange < 0) { - mis->_miDelFlag = TRUE; - if (!dead) { + if (!dead) { + if (mis->_miRange < 0) { + mis->_miDelFlag = TRUE; mon->_mmode = mis->_miVar1; - } else { - // TODO: RemoveMonFromGame ? - // mon->_mAnimFrame = mon->_mAnimLen; - // mon->_mAnimCnt = -1; - // reset squelch value to simplify MonFallenFear, sync_all_monsters and LevelDeltaExport - mon->_msquelch = 0; - // assert(mnum >= MAX_MINIONS); - // mon->_mmode = (mon->_mFlags & MFLAG_NOCORPSE) ? MM_UNUSED : MM_DEAD; - mon->_mmode = MM_UNUSED; - nummonsters--; + return; } - return; - } - if (!dead) { mon->_msquelch = SQUELCH_MAX; // prevent monster from getting in relaxed state } else { if (mis->_miFileNum != MFILE_SHATTER1) { @@ -4400,6 +4390,18 @@ void MI_Stone(int mi) // mis->_mixoff = mon->_mxoff; // mis->_miyoff = mon->_myoff; SetMissDir(mi, 0); + } else if (mis->_miRange < 0) { + mis->_miDelFlag = TRUE; + // TODO: RemoveMonFromGame ? + // mon->_mAnimFrame = mon->_mAnimLen; + // mon->_mAnimCnt = -1; + // reset squelch value to simplify MonFallenFear, sync_all_monsters and LevelDeltaExport + mon->_msquelch = 0; + // assert(mnum >= MAX_MINIONS); + // mon->_mmode = (mon->_mFlags & MFLAG_NOCORPSE) ? MM_UNUSED : MM_DEAD; + mon->_mmode = MM_UNUSED; + nummonsters--; + return; } else if (mis->_miAnimFrame == misfiledata[MFILE_SHATTER1].mfAnimLen[0]) { mis->_miAnimFlag = FALSE; } From aa47ea2ec4744b922313babfbce023ba9cd9210e Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 25 Jul 2024 15:02:43 +0200 Subject: [PATCH 352/596] raise the hp of certain hellfire monsters --- Source/monstdat.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/monstdat.cpp b/Source/monstdat.cpp index 94ba78110fe..3b3f57df5d9 100644 --- a/Source/monstdat.cpp +++ b/Source/monstdat.cpp @@ -125,24 +125,24 @@ const MonsterData monsterdata[NUM_MTYPES] = { #ifdef HELLFIRE /* MT_HELLBOAR */ { MOFILE_FORK, 19, 3, NULL, "Hellboar", { AI_SKELSD, 2, 0, 0 }, 80, 100, MFLAG_KNOCKBACK | MFLAG_SEARCH | MFLAG_CAN_BLEED, 70, 16, 22, 0, 0, 0, 0, 0, 60, 25, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 500, ALIGN }, // MC_DEMON, /* MT_STINGER */ { MOFILE_SCORP, 18, 1, NULL, "Stinger", { AI_SKELSD, 3, 0, 0 }, 30, 40, 0 , 85, 1, 28, 0, 0, 0, 0, 0, 50, 40, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 333, ALIGN }, // MC_ANIMAL, -/* MT_PSYCHORB */ { MOFILE_EYE, 20, 6, NULL, "Psychorb", { AI_RANGED, 3, MIS_PSYCHORB, FALSE }, 20, 30, 0 , 80, 10, 10, 0, 0, 0, 55, 0, 40, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 300, ALIGN }, // MC_ANIMAL, +/* MT_PSYCHORB */ { MOFILE_EYE, 20, 6, NULL, "Psychorb", { AI_RANGED, 3, MIS_PSYCHORB, FALSE }, 30, 40, 0 , 80, 10, 10, 0, 0, 0, 55, 0, 40, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 300, ALIGN }, // MC_ANIMAL, /* MT_ARACHNON */ { MOFILE_SPIDER, 20, 7, NULL, "Arachnon", { AI_SKELSD, 3, 0, 0 }, 60, 80, MFLAG_SEARCH , 50, 5, 15, 0, 0, 0, 0, 0, 50, 40, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 333, ALIGN }, // MC_ANIMAL, /* MT_FELLTWIN */ { MOFILE_TSNEAK, 18, 3, NULL, "Felltwin", { AI_SKELSD, 3, 0, 0 }, 50, 70, MFLAG_SEARCH , 70, 10, 18, 0, 0, 0, 0, 0, 50, 35, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 400, ALIGN }, // MC_DEMON, /* MT_UNRAV */ { MOFILE_UNRAV, 19, 3, NULL, "The Shredded", { AI_SKELSD, 0, 0, 0 }, 70, 90, 0 , 95, 6, 12, 0, 0, 0, 0, 0, 65, 40, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , 600, ALIGN }, // MC_UNDEAD, /* MT_HORKSPWN */ { MOFILE_SPAWN, 21, 3, NULL, "Hork Spawn", { AI_SKELSD, 3, 0, 0 }, 30, 30, MFLAG_NODROP , 60, 10, 25, 0, 0, 0, 0, 0, 25, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, 166, ALIGN }, // MC_DEMON, /* MT_VENMTAIL */ { MOFILE_WSCORP, 22, 1, NULL, "Venomtail", { AI_SKELSD, 3, 0, 0 }, 40, 50, 0 , 95, 1, 32, 0, 0, 0, 0, 0, 60, 50, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 666, ALIGN }, // MC_ANIMAL, -/* MT_NECRMORB */ { MOFILE_EYE2, 24, 6, NULL, "Necromorb", { AI_RANGED, 3, MIS_NECROMORB, FALSE }, 30, 40, 0 , 80, 20, 20, 0, 0, 0, 60, 0, 50, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 733, ALIGN }, // MC_ANIMAL, +/* MT_NECRMORB */ { MOFILE_EYE2, 24, 6, NULL, "Necromorb", { AI_RANGED, 3, MIS_NECROMORB, FALSE }, 50, 70, 0 , 80, 20, 20, 0, 0, 0, 60, 0, 50, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 733, ALIGN }, // MC_ANIMAL, /* MT_SPIDLORD */ { MOFILE_BSPIDR, 24, 7, NULL, "Spider Lord", { AI_ROUNDRANGED, 3, MIS_ACID, 1 }, 80, 100, MFLAG_SEARCH , 60, 8, 20, 0, 0, 0, 60, 0, 60, 50, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 833, ALIGN }, // MC_ANIMAL, -/* MT_LASHWORM */ { MOFILE_CLASP, 23, 3, NULL, "Lashworm", { AI_SKELSD, 3, 0, 0 }, 30, 30, 0 , 90, 12, 20, 0, 0, 0, 0, 0, 50, 35, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 400, ALIGN }, // MC_ANIMAL, +/* MT_LASHWORM */ { MOFILE_CLASP, 23, 3, NULL, "Lashworm", { AI_SKELSD, 3, 0, 0 }, 70, 70, 0 , 90, 12, 20, 0, 0, 0, 0, 0, 50, 35, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 400, ALIGN }, // MC_ANIMAL, /* MT_TORCHANT */ { MOFILE_ANTWORM, 22, 7, NULL, "Torchant", { AI_RANGED, 3, MIS_FIREBALL, FALSE }, 60, 80, 0 , 75, 20, 30, 0, 0, 0, 55, 0, 70, 50, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 833, ALIGN }, // MC_ANIMAL, /* MT_HORKDMN */ { MOFILE_HORKD, 22, 7, NULL, "Hork Demon", { AI_SKELSD, 3, 0, 0 }, 120, 160, MFLAG_SEARCH | MFLAG_CAN_BLEED, 75, 20, 35, 0, 0, 0, 0, 0, 80, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 1333, ALIGN }, // MC_DEMON, /* MT_DEFILER */ { MOFILE_HELLBUG, 24, 7, NULL, "Hell Bug", { AI_FAT, 3, 0, 0 }, 480, 480, MFLAG_SEARCH , 120, 20, 30, 90, 24, 40, 0, 0, 80, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 3333, ALIGN }, // MC_DEMON, /* MT_LRDSAYTR */ { MOFILE_GOATLORD, 26, 7, NULL, "Satyr Lord", { AI_SKELSD, 3, 0, 0 }, 160, 200, MFLAG_SEARCH | MFLAG_CAN_BLEED, 90, 20, 30, 0, 0, 0, 0, 0, 70, 60, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 1866, ALIGN }, // MC_DEMON, /* MT_GRAVEDIG */ { MOFILE_GRAVDG, 26, 3, NULL, "Gravedigger", { AI_SCAV, 3, 0, 0 }, 120, 240, MFLAG_CAN_OPEN_DOOR, 80, 6, 26, 0, 0, 0, 0, 0, 20, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE , 1333, ALIGN }, // MC_UNDEAD, /* MT_BIGFALL */ { MOFILE_BIGFALL, 27, 3, NULL, "Devil Kin Brute", { AI_SKELSD, 3, 0, 0 }, 120, 160, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 100, 18, 24, 0, 0, 0, 0, 0, 70, 60, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1600, ALIGN }, // MC_ANIMAL, -/* MT_TOMBRAT */ { MOFILE_RAT, 26, 3, NULL, "Tomb Rat", { AI_SKELSD, 3, 0, 0 }, 80, 120, 0 , 120, 12, 25, 0, 0, 0, 0, 0, 30, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1200, ALIGN }, // MC_ANIMAL, +/* MT_TOMBRAT */ { MOFILE_RAT, 26, 3, NULL, "Tomb Rat", { AI_SKELSD, 3, 0, 0 }, 90, 140, 0 , 120, 12, 25, 0, 0, 0, 0, 0, 30, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1200, ALIGN }, // MC_ANIMAL, /* MT_FIREBAT */ { MOFILE_HELLBAT, 27, 7, NULL, "Firebat", { AI_RANGED, 3, MIS_FIREBOLT, FALSE }, 60, 80, 0 , 100, 8, 24, 0, 0, 0, 60, 0, 70, 40, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 1600, ALIGN }, // MC_ANIMAL, -/* MT_SKLWING */ { MOFILE_DEMSKEL, 28, 7, "Monsters\\Mega\\Vtexl.TRN", "Skullwing", { AI_SKELSD, 0, 0, 0 }, 70, 70, 0 , 75, 24, 32, 0, 0, 0, 0, 0, 80, 30, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , 2000, ALIGN }, // MC_UNDEAD, +/* MT_SKLWING */ { MOFILE_DEMSKEL, 28, 7, "Monsters\\Mega\\Vtexl.TRN", "Skullwing", { AI_SKELSD, 0, 0, 0 }, 150, 170, 0 , 75, 24, 32, 0, 0, 0, 0, 0, 80, 30, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , 2000, ALIGN }, // MC_UNDEAD, /* MT_LICH */ { MOFILE_LICH, 27, 7, NULL, "Lich", { AI_RANGED, 3, MIS_LICH, FALSE }, 80, 100, 0 , 100, 16, 20, 0, 0, 0, 60, 0, 60, 20, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE , 2000, ALIGN }, // MC_UNDEAD, /* MT_CRYPTDMN */ { MOFILE_BUBBA, 29, 3, "Monsters\\Fat\\FatB.TRN", "Crypt Demon", { AI_SKELSD, 3, 0, 0 }, 200, 240, 0 , 100, 20, 40, 0, 0, 0, 0, 0, 85, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2133, ALIGN }, // MC_DEMON, /* MT_HELLBAT */ { MOFILE_HELLBAT2, 29, 7, NULL, "Hellbat", { AI_RANGED, 3, MIS_FIREBALL, FALSE }, 100, 140, 0 , 110, 30, 30, 0, 0, 0, 70, 0, 80, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2400, ALIGN }, // MC_DEMON, From 185ee68636d95db1208fa0b99e0450308d6b7aaa Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 25 Jul 2024 15:04:28 +0200 Subject: [PATCH 353/596] reduce the spacing if the text is too wide (PrintJustifiedString) --- Source/engine/render/text_render.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Source/engine/render/text_render.cpp b/Source/engine/render/text_render.cpp index 50851a41bfa..a4e5a7f9470 100644 --- a/Source/engine/render/text_render.cpp +++ b/Source/engine/render/text_render.cpp @@ -351,16 +351,18 @@ void PrintJustifiedString(int x, int y, int endX, const char* text, BYTE col, in BYTE c; const char* tmp; int strEnd; - int k; - +restart: strEnd = x; tmp = text; while (*tmp != '\0') { c = gbStdFontFrame[(BYTE)*tmp++]; strEnd += smallFontWidth[c] + kern; } - if (strEnd < endX) { + if (strEnd <= endX) { x += (endX - strEnd) >> 1; + } else if (kern > 0) { + --kern; + goto restart; } PrintString(x, y, endX, text, col, kern); From 5d1ade5e857c6a7fdbc70a42566da61781871ed9 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 25 Jul 2024 15:56:25 +0200 Subject: [PATCH 354/596] use the whole width to draw overlay on the skill-icons --- Source/control.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/control.cpp b/Source/control.cpp index 865d378d34d..cb39a48109c 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -286,7 +286,7 @@ static void DrawSpellIconOverlay(int x, int y, int sn, int st) ASSUME_UNREACHABLE return; } - PrintJustifiedString(x + SPLICON_OVERX, y, x + SPLICON_WIDTH - SPLICON_OVERX, tempstr, t, FONT_KERN_SMALL); + PrintJustifiedString(x, y, x + SPLICON_WIDTH, tempstr, t, FONT_KERN_SMALL); } static void DrawSkillIcon(int pnum, BYTE spl, BYTE st, BYTE offset) From b2f3e57ecb81187ea48953ea3f0b283b9f752784 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 25 Jul 2024 16:00:51 +0200 Subject: [PATCH 355/596] improve validations in LevelDeltaLoad --- Source/msg.cpp | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/Source/msg.cpp b/Source/msg.cpp index 387d1ea897d..36f9d60d249 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -1708,17 +1708,17 @@ void LevelDeltaLoad() net_assert(plr._py == plr._poldy); switch (plr._pmode) { case PM_ATTACK: - net_assert(plr._pVar5 < NUM_SPELLS); // ATTACK_SKILL - net_assert(plr._pVar6 >= 0); // ATTACK_SKILL_LEVEL + net_assert((unsigned)plr._pVar5 < NUM_SPELLS); // ATTACK_SKILL + net_assert(plr._pVar6 >= 0); // ATTACK_SKILL_LEVEL break; case PM_RATTACK: - net_assert(plr._pVar5 < NUM_SPELLS); // RATTACK_SKILL - net_assert(plr._pVar6 >= 0); // RATTACK_SKILL_LEVEL + net_assert((unsigned)plr._pVar5 < NUM_SPELLS); // RATTACK_SKILL + net_assert(plr._pVar6 >= 0); // RATTACK_SKILL_LEVEL break; case PM_SPELL: net_assert(plr._pVar1 >= DBORDERX && plr._pVar1 < DBORDERX + DSIZEX); // SPELL_TARGET_X net_assert(plr._pVar2 >= DBORDERY && plr._pVar2 < DBORDERY + DSIZEY); // SPELL_TARGET_Y - net_assert(plr._pVar5 < NUM_SPELLS); // SPELL_NUM + net_assert((unsigned)plr._pVar5 < NUM_SPELLS); // SPELL_NUM net_assert(plr._pVar6 >= 0); // SPELL_LEVEL break; } @@ -1728,42 +1728,42 @@ void LevelDeltaLoad() case ACTION_WALK: break; case ACTION_OPERATE: - net_assert(plr._pDestParam1 < MAXOBJECTS); - net_assert(plr._pDestParam2 < MAXDUNX); - net_assert(plr._pDestParam3 < MAXDUNY); + net_assert((unsigned)plr._pDestParam1 < MAXOBJECTS); + net_assert((unsigned)plr._pDestParam2 < MAXDUNX); + net_assert((unsigned)plr._pDestParam3 < MAXDUNY); net_assert(abs(dObject[plr._pDestParam2][plr._pDestParam3]) == plr._pDestParam1 + 1); break; case ACTION_BLOCK: - net_assert(plr._pDestParam1 < NUM_DIRS); + net_assert((unsigned)plr._pDestParam1 < NUM_DIRS); break; case ACTION_ATTACKMON: case ACTION_RATTACKMON: case ACTION_SPELLMON: - net_assert(plr._pDestParam1 < MAXMONSTERS); - net_assert(plr._pDestParam3 < NUM_SPELLS); // ATTACK_SKILL, SPELL_NUM + net_assert((unsigned)plr._pDestParam1 < MAXMONSTERS); + net_assert((unsigned)plr._pDestParam3 < NUM_SPELLS); // ATTACK_SKILL, SPELL_NUM net_assert(plr._pDestParam4 >= 0); // ATTACK_SKILL_LEVEL, SPELL_LEVEL break; case ACTION_ATTACK: case ACTION_RATTACK: - net_assert(plr._pDestParam3 < NUM_SPELLS); // ATTACK_SKILL + net_assert((unsigned)plr._pDestParam3 < NUM_SPELLS); // ATTACK_SKILL net_assert(plr._pDestParam4 >= 0); // ATTACK_SKILL_LEVEL break; case ACTION_ATTACKPLR: case ACTION_RATTACKPLR: case ACTION_SPELLPLR: - net_assert(plr._pDestParam1 < MAX_PLRS); - net_assert(plr._pDestParam3 < NUM_SPELLS); // ATTACK_SKILL, SPELL_NUM + net_assert((unsigned)plr._pDestParam1 < MAX_PLRS); + net_assert((unsigned)plr._pDestParam3 < NUM_SPELLS); // ATTACK_SKILL, SPELL_NUM net_assert(plr._pDestParam4 >= 0); // ATTACK_SKILL_LEVEL, SPELL_LEVEL break; case ACTION_SPELL: net_assert(plr._pDestParam1 >= DBORDERX && plr._pDestParam1 < DBORDERX + DSIZEX); // SPELL_TARGET_X net_assert(plr._pDestParam2 >= DBORDERY && plr._pDestParam2 < DBORDERY + DSIZEY); // SPELL_TARGET_Y - net_assert(plr._pDestParam3 < NUM_SPELLS); // SPELL_NUM + net_assert((unsigned)plr._pDestParam3 < NUM_SPELLS); // SPELL_NUM net_assert(plr._pDestParam4 >= 0); // SPELL_LEVEL if (plr._pDestParam3 == SPL_DISARM) - net_assert(plr._pDestParam4 < MAXOBJECTS); // fake SPELL_LEVEL + net_assert((unsigned)plr._pDestParam4 < MAXOBJECTS); // fake SPELL_LEVEL if (plr._pDestParam3 == SPL_RESURRECT) - net_assert(plr._pDestParam4 < MAX_PLRS); // fake SPELL_LEVEL + net_assert((unsigned)plr._pDestParam4 < MAX_PLRS); // fake SPELL_LEVEL if (plr._pDestParam3 == SPL_TELEKINESIS) { switch (plr._pDestParam4 >> 16) { case MTT_ITEM: @@ -1783,10 +1783,10 @@ void LevelDeltaLoad() break; case ACTION_PICKUPITEM: // put item in hand (inventory screen open) case ACTION_PICKUPAITEM: // put item in inventory - net_assert(plr._pDestParam1 < MAXITEMS); + net_assert((unsigned)plr._pDestParam1 < MAXITEMS); break; case ACTION_TALK: - net_assert(plr._pDestParam1 < MAXMONSTERS); + net_assert((unsigned)plr._pDestParam1 < MAXMONSTERS); break; default: net_assert(0); From 94ca0633b23b8e23b2c95151b663a17b97f0373d Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 25 Jul 2024 16:03:07 +0200 Subject: [PATCH 356/596] get rid of MDMAXX/Y --- defs.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/defs.h b/defs.h index b88ff08be96..f101c73ac07 100644 --- a/defs.h +++ b/defs.h @@ -115,8 +115,6 @@ static_assert(DMAXY % 2 == 0, "DRLG_L4 constructs the dungeon by mirroring a qua #define MAXTILES 255 #define MAXSUBTILES 1023 #define MAXVISION (MAX_PLRS + MAX_MINIONS) -#define MDMAXX 40 -#define MDMAXY 40 #define MAXCHARLEVEL 50 #define MAXSPLLEVEL 15 #ifdef HELLFIRE From ddb204e7a7a389559ee4ca58623fcd846ed90692 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 25 Jul 2024 17:07:54 +0200 Subject: [PATCH 357/596] rebalance item-affixes - make special affixes available on higher levels - prevent high level affixes to be added right after a higher base item becomes available - ensure a staff can keep its spell after a cleansing oil is used - ensure oils can be used on the starting staves of mages and monks --- Source/debug.cpp | 25 +-- Source/itemdat.cpp | 452 +++++++++++++++++++++++---------------------- Source/itemdat.h | 1 + Source/items.cpp | 39 ++-- Source/stores.cpp | 10 +- enums.h | 7 + structs.h | 7 +- 7 files changed, 274 insertions(+), 267 deletions(-) diff --git a/Source/debug.cpp b/Source/debug.cpp index f06e59d27a0..e625704bd81 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -507,7 +507,8 @@ void ValidateData() minMediumArmor = ids.iMinMLvl; if (ids.itype == ITYPE_HARMOR && ids.iMinMLvl < minHeavyArmor && ids.iRnd != 0) minHeavyArmor = ids.iMinMLvl; - if (ids.iMinMLvl == 0 && ids.itype != ITYPE_MISC && ids.itype != ITYPE_GOLD && ids.iMiscId != IMISC_UNIQUE) + if (ids.iMinMLvl == 0 && ids.itype != ITYPE_MISC && ids.itype != ITYPE_GOLD + && (ids.iMiscId != IMISC_UNIQUE || ids.itype == ITYPE_STAFF /* required by DoWhittle */)) // required by DoClean app_fatal("iMinMLvl field is not set for %s (%d).", ids.iName, i); if (ids.iMiscId == IMISC_UNIQUE && ids.iRnd != 0) app_fatal("Fix unique item %s (%d) should not be part of the loot.", ids.iName, i); @@ -736,16 +737,13 @@ void ValidateData() for (i = 1; i < MAXCHARLEVEL; i++) { int a = 0, b = 0, c = 0, w = 0; for (const AffixData* pres = PL_Prefix; pres->PLPower != IPL_INVALID; pres++) { - if (pres->PLMinLvl > i) { - if (pres->PLMinLvl <= (i << 1) && pres->PLOk) - c++; - continue; + if (pres->PLRanges[IAR_SHOP].to >= i + 8 && pres->PLRanges[IAR_SHOP].from <= i + 8 && pres->PLOk) { + c++; } - if (pres->PLMinLvl >= (i >> 1) && pres->PLOk) { + if (pres->PLRanges[IAR_SHOP].to >= i && pres->PLRanges[IAR_SHOP].from <= i && pres->PLOk) { a++; - c++; } - if (pres->PLMinLvl >= (i >> 2)) { + if (pres->PLRanges[IAR_DROP].to >= i && pres->PLRanges[IAR_DROP].from <= i) { b++; if (!pres->PLOk) w++; @@ -753,16 +751,13 @@ void ValidateData() } int as = 0, bs = 0, cs = 0, ws = 0; for (const AffixData* pres = PL_Suffix; pres->PLPower != IPL_INVALID; pres++) { - if (pres->PLMinLvl > i) { - if (pres->PLMinLvl <= (i << 1) && pres->PLOk) - cs++; - continue; + if (pres->PLRanges[IAR_SHOP].to >= i + 8 && pres->PLRanges[IAR_SHOP].from <= i + 8 && pres->PLOk) { + cs++; } - if (pres->PLMinLvl >= (i >> 1) && pres->PLOk) { + if (pres->PLRanges[IAR_SHOP].to >= i && pres->PLRanges[IAR_SHOP].from <= i && pres->PLOk) { as++; - cs++; } - if (pres->PLMinLvl >= (i >> 2)) { + if (pres->PLRanges[IAR_DROP].to >= i && pres->PLRanges[IAR_DROP].from <= i) { bs++; if (!pres->PLOk) ws++; diff --git a/Source/itemdat.cpp b/Source/itemdat.cpp index 2999b42aa57..d4412db46f5 100644 --- a/Source/itemdat.cpp +++ b/Source/itemdat.cpp @@ -13,6 +13,8 @@ DEVILUTION_BEGIN_NAMESPACE #define SS_BOOK 1 #define SS_RUNE 8 +#define PLR1LVL (MAXCHARLEVEL + 2 + 1) + /** Maps from item_cursor_graphic to item_gfx_id. */ const BYTE ItemCAnimTbl[NUM_ICURS] = { // clang-format off @@ -226,237 +228,237 @@ const ItemData AllItemsList[NUM_IDI] = { /** Contains the data related to each item prefix. */ const AffixData PL_Prefix[] = { // clang-format off -// PLPower, PLParam1, PLParam2, PLMinLvl, PLIType, PLDouble, PLOk, PLMinVal, PLMaxVal, PLMultVal -/*tin*/ { IPL_TOHIT, -10, -1, 3, PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, TRUE, FALSE, 0, 0, -3 }, -/*iron*/ { IPL_TOHIT, 1, 15, 1, PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, TRUE, TRUE, 600, 1000, 3 }, -/*silver*/ { IPL_TOHIT, 10, 30, 8, PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, TRUE, TRUE, 1600, 2000, 7 }, -/*platinum*/ { IPL_TOHIT, 31, 45, 16, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 3100, 4000, 11 }, -/*platinum*/ { IPL_TOHIT, 31, 45, 24, PLT_MISC, TRUE, TRUE, 3100, 4000, 11 }, -/*mithril*/ { IPL_TOHIT, 46, 60, 24, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 4100, 6000, 13 }, -/*meteoric*/ { IPL_TOHIT, 61, 90, 32, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 6100, 10000, 15 }, -/*mithril*/ { IPL_TOHIT, 46, 60, 32, PLT_MISC, TRUE, TRUE, 4100, 6000, 13 }, -/*weird*/ { IPL_TOHIT, 91, 120, 42, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 10100, 14000, 17 }, -/*strange*/ { IPL_TOHIT, 121, 150, 54, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 14100, 20000, 20 }, -/*bent*/ { IPL_DAMP, -75, -25, 3, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, FALSE, 0, 0, -8 }, -/*jagged*/ { IPL_DAMP, 20, 35, 1, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 250, 450, 6 }, -/*deadly*/ { IPL_DAMP, 30, 50, 6, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 500, 700, 8 }, -/*heavy*/ { IPL_DAMP, 51, 65, 10, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 750, 950, 10 }, -/*vicious*/ { IPL_DAMP, 66, 80, 16, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 1000, 1450, 16 }, -/*brutal*/ { IPL_DAMP, 81, 95, 22, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 1500, 1950, 20 }, -/*massive*/ { IPL_DAMP, 96, 110, 32, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 2000, 2450, 26 }, -/*savage*/ { IPL_DAMP, 111, 125, 44, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 2500, 3000, 30 }, -/*ruthless*/ { IPL_DAMP, 126, 150, 50, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 10100, 15000, 34 }, -/*merciless*/ { IPL_DAMP, 151, 175, 60, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 15000, 20000, 40 }, -/*clumsy*/ { IPL_TOHIT_DAMP, -75, -25, 4, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, FALSE, 0, 0, -10 }, -/*sharp*/ { IPL_TOHIT_DAMP, 20, 35, 1, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 350, 950, 10 }, -/*fine*/ { IPL_TOHIT_DAMP, 30, 50, 6, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 1100, 1700, 14 }, -/*warrior's*/ { IPL_TOHIT_DAMP, 51, 65, 12, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 1850, 2450, 26 }, -/*soldier's*/ { IPL_TOHIT_DAMP, 66, 80, 18, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 2600, 3950, 34 }, -/*lord's*/ { IPL_TOHIT_DAMP, 81, 95, 24, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 4100, 5950, 42 }, -/*knight's*/ { IPL_TOHIT_DAMP, 96, 110, 35, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 6100, 8450, 52 }, -/*master's*/ { IPL_TOHIT_DAMP, 111, 125, 48, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 8600, 13000, 60 }, -/*champion's*/ { IPL_TOHIT_DAMP, 126, 150, 52, PLT_MELEE | PLT_STAFF , TRUE, TRUE, 15200, 24000, 66 }, -/*king's*/ { IPL_TOHIT_DAMP, 151, 175, 60, PLT_MELEE | PLT_STAFF , TRUE, TRUE, 24100, 35000, 76 }, -/*hurt*/ { IPL_CRITP, 25, 40, 8, PLT_ARMO | PLT_MISC, FALSE, TRUE, 1000, 2000, 2 }, -/*weal*/ { IPL_CRITP, 41, 60, 24, PLT_ARMO | PLT_MISC, FALSE, TRUE, 2000, 4000, 4 }, -/*gimp*/ { IPL_CRITP, 61, 80, 48, PLT_ARMO | PLT_MISC, FALSE, TRUE, 4000, 8000, 8 }, -/*impair*/ { IPL_CRITP, 81, 100, 56, PLT_ARMO | PLT_MISC, FALSE, TRUE, 8000, 16000, 16 }, -/*vulnerable*/ { IPL_ACP, -100, -25, 3, PLT_ARMO | PLT_SHLD , TRUE, FALSE, 0, 0, -3 }, -/*fine*/ { IPL_ACP, 20, 30, 1, PLT_ARMO | PLT_SHLD , TRUE, TRUE, 20, 100, 2 }, -/*grand*/ { IPL_ACP, 25, 50, 6, PLT_ARMO | PLT_SHLD , TRUE, TRUE, 220, 300, 5 }, -/*valiant*/ { IPL_ACP, 51, 70, 10, PLT_ARMO | PLT_SHLD , TRUE, TRUE, 320, 400, 7 }, -/*glorious*/ { IPL_ACP, 71, 90, 14, PLT_ARMO | PLT_SHLD , TRUE, TRUE, 420, 600, 9 }, -/*blessed*/ { IPL_ACP, 91, 110, 19, PLT_ARMO | PLT_SHLD , TRUE, TRUE, 620, 800, 11 }, -/*saintly*/ { IPL_ACP, 111, 130, 24, PLT_ARMO | PLT_SHLD , TRUE, TRUE, 820, 1200, 13 }, -/*awesome*/ { IPL_ACP, 131, 150, 30, PLT_ARMO | PLT_SHLD , TRUE, TRUE, 1220, 2000, 15 }, -/*holy*/ { IPL_ACP, 151, 170, 42, PLT_ARMO | PLT_SHLD , TRUE, TRUE, 5200, 6000, 17 }, -/*godly*/ { IPL_ACP, 171, 200, 60, PLT_ARMO | PLT_SHLD , TRUE, TRUE, 6200, 7000, 20 }, -/*rose*/ { IPL_FIRERES, 5, 15, 1, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 100, 500, 2 }, -/*red*/ { IPL_FIRERES, 10, 25, 8, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 500, 1500, 2 }, -/*crimson*/ { IPL_FIRERES, 21, 35, 16, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 2100, 3000, 2 }, -/*burgundy*/ { IPL_FIRERES, 36, 50, 28, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 3100, 4000, 2 }, -/*garnet*/ { IPL_FIRERES, 51, 65, 40, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 8200, 12000, 3 }, -/*ruby*/ { IPL_FIRERES, 66, 80, 50, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 17100, 20000, 5 }, -/*sky*/ { IPL_LIGHTRES, 5, 15, 1, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 100, 500, 2 }, -/*blue*/ { IPL_LIGHTRES, 10, 25, 8, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 500, 1500, 2 }, -/*azure*/ { IPL_LIGHTRES, 21, 35, 16, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 2100, 3000, 2 }, -/*lapis*/ { IPL_LIGHTRES, 36, 50, 28, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 3100, 4000, 2 }, -/*cobalt*/ { IPL_LIGHTRES, 51, 65, 40, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 8200, 12000, 3 }, -/*sapphire*/ { IPL_LIGHTRES, 66, 80, 50, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 17100, 20000, 5 }, -/*mist*/ { IPL_MAGICRES, 5, 15, 1, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 100, 500, 2 }, -/*white*/ { IPL_MAGICRES, 10, 25, 8, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 500, 1500, 2 }, -/*pearl*/ { IPL_MAGICRES, 21, 35, 16, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 2100, 3000, 2 }, -/*ivory*/ { IPL_MAGICRES, 36, 50, 28, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 3100, 4000, 2 }, -/*crystal*/ { IPL_MAGICRES, 51, 65, 40, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 8200, 12000, 3 }, -/*diamond*/ { IPL_MAGICRES, 66, 80, 50, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 17100, 20000, 5 }, -/*lime*/ { IPL_ACIDRES, 5, 15, 1, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 100, 500, 2 }, -/*green*/ { IPL_ACIDRES, 10, 25, 8, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 500, 1500, 2 }, -/*malachite*/ { IPL_ACIDRES, 21, 35, 16, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 2100, 3000, 2 }, -/*jade*/ { IPL_ACIDRES, 36, 50, 28, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 3100, 4000, 2 }, -/*turquoise*/ { IPL_ACIDRES, 51, 65, 40, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 8200, 12000, 3 }, -/*emerald*/ { IPL_ACIDRES, 66, 80, 50, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 17100, 20000, 5 }, -/*topaz*/ { IPL_ALLRES, 10, 15, 8, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 2000, 5000, 3 }, -/*amber*/ { IPL_ALLRES, 16, 20, 16, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 7400, 10000, 3 }, -/*beryl*/ { IPL_ALLRES, 21, 30, 33, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 11000, 15000, 3 }, -/*obsidian*/ { IPL_ALLRES, 31, 40, 50, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 24000, 40000, 4 }, -/*aquamarine*/ { IPL_ALLRES, 41, 50, 54, PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW , FALSE, TRUE, 61000, 75000, 7 }, -/*hyena's*/ { IPL_MANA, -25, -1, 4, PLT_STAFF | PLT_MISC, FALSE, FALSE, -2500, -100, -1 }, -/*spider's*/ { IPL_MANA, 10, 20, 1, PLT_STAFF | PLT_MISC, FALSE, TRUE, 500, 1000, 2 }, -/*snake's*/ { IPL_MANA, 15, 30, 6, PLT_STAFF | PLT_MISC, FALSE, TRUE, 2100, 4000, 5 }, -/*serpent's*/ { IPL_MANA, 31, 40, 14, PLT_STAFF | PLT_MISC, FALSE, TRUE, 4100, 6000, 7 }, -/*drake's*/ { IPL_MANA, 41, 50, 24, PLT_STAFF | PLT_MISC, FALSE, TRUE, 6100, 10000, 9 }, -/*dragon's*/ { IPL_MANA, 51, 60, 32, PLT_STAFF | PLT_MISC, FALSE, TRUE, 10100, 15000, 11 }, -/*wyrm's*/ { IPL_MANA, 61, 80, 42, PLT_STAFF , FALSE, TRUE, 15100, 19000, 12 }, -/*hydra's*/ { IPL_MANA, 81, 100, 50, PLT_STAFF , FALSE, TRUE, 19100, 30000, 13 }, -/*angel's*/ { IPL_SKILLLEVELS, 1, 1, 15, PLT_STAFF , FALSE, TRUE, 25000, 25000, 2 }, -/*arch-Angel's*/ { IPL_SKILLLEVELS, 2, 2, 25, PLT_STAFF , FALSE, TRUE, 50000, 50000, 3 }, -/*apprentice's*/ { IPL_SKILLLVL, 1, 1, 20, PLT_ARMO | PLT_SHLD | PLT_STAFF | PLT_MISC, FALSE, TRUE, 13000, 13000, 2 }, -/*mage's*/ { IPL_SKILLLVL, 1, 2, 40, PLT_ARMO | PLT_SHLD | PLT_STAFF | PLT_MISC, FALSE, TRUE, 13000, 26000, 3 }, -/*speed*/ { IPL_FASTCAST, 1, 1, 19, PLT_STAFF , FALSE, TRUE, 8000, 8000, 8 }, -/*haste*/ { IPL_FASTCAST, 2, 2, 27, PLT_STAFF , FALSE, TRUE, 16000, 16000, 16 }, -/*harmony*/ { IPL_FASTCAST, 3, 3, 42, PLT_STAFF , FALSE, TRUE, 32000, 32000, 32 }, -/*plentiful*/ { IPL_CHARGES, 2, 2, 12, PLT_CHRG , FALSE, TRUE, 2000, 2000, 2 }, -/*bountiful*/ { IPL_CHARGES, 3, 3, 24, PLT_CHRG , FALSE, TRUE, 3000, 3000, 3 }, -/*warm*/ { IPL_FIREDAM, 2, 4, 3, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 1800, 1800, 2 }, -/*fire*/ { IPL_FIREDAM, 5, 8, 8, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 5000, 5000, 2 }, -/*flaming*/ { IPL_FIREDAM, 10, 16, 16, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 10000, 10000, 2 }, -/*burning*/ { IPL_FIREDAM, 20, 32, 35, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 20000, 20000, 2 }, -/*yellow*/ { IPL_LIGHTDAM, 1, 6, 4, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 2000, 2000, 2 }, -/*lightning*/ { IPL_LIGHTDAM, 1, 10, 9, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 5000, 5000, 2 }, -/*shocking*/ { IPL_LIGHTDAM, 1, 20, 18, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 10000, 10000, 2 }, -/*thunder*/ { IPL_LIGHTDAM, 1, 40, 35, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 20000, 20000, 2 }, -/*glow*/ { IPL_MAGICDAM, 2, 5, 4, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 2000, 2000, 2 }, -/*unkind*/ { IPL_MAGICDAM, 3, 7, 9, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 5000, 5000, 2 }, -/*spiteful*/ { IPL_MAGICDAM, 8, 12, 18, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 10000, 10000, 2 }, -/*malicious*/ { IPL_MAGICDAM, 16, 24, 35, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 20000, 20000, 2 }, -/*citric*/ { IPL_ACIDDAM, 3, 6, 5, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 2500, 2500, 2 }, -/*acidic*/ { IPL_ACIDDAM, 4, 7, 10, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 5000, 5000, 2 }, -/*bitter*/ { IPL_ACIDDAM, 8, 15, 18, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 10000, 10000, 2 }, -/*corrosive*/ { IPL_ACIDDAM, 18, 28, 35, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 20000, 20000, 2 }, -/*fairy*/ { IPL_CRYSTALLINE, 30, 60, 32, PLT_MELEE | PLT_STAFF | PLT_BOW , FALSE, TRUE, 1000, 3000, 3 }, -/*crystalline*/ { IPL_CRYSTALLINE, 61, 110, 60, PLT_MELEE | PLT_BOW , FALSE, TRUE, 10000, 30000, 8 }, - { IPL_INVALID, 0, 0, 0, 0 , FALSE, FALSE, 0, 0, 0 }, +// PLPower, PLParam1, PLParam2, PLRanges, IAR_DROP, from_1, IAR_SHOP, from_2, IAR_CRAFT, PLIType, PLDouble, PLOk, PLMinVal, PLMaxVal, PLMultVal +/*tin*/ { IPL_TOHIT, -10, -1, 3, 12, 0, 0, 0, 0, PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, TRUE, FALSE, 0, 0, -3 }, +/*iron*/ { IPL_TOHIT, 1, 15, 0, 12, 0, 12, 0, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, TRUE, TRUE, 600, 1000, 3 }, +/*silver*/ { IPL_TOHIT, 16, 35, 8, 32, 8, 24, 8, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, TRUE, TRUE, 1600, 2000, 7 }, +/*platinum*/ { IPL_TOHIT, 36, 55, 16, 64, 16, 32, 16, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 3100, 4000, 11 }, +/*platinum*/ { IPL_TOHIT, 36, 55, 24, 64, 24, 48, 24, ILVLMAX, PLT_MISC, TRUE, TRUE, 3100, 4000, 11 }, +/*mithril*/ { IPL_TOHIT, 56, 80, 24, ILVLMAX, 24, 48, 24, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 4100, 6000, 13 }, +/*meteoric*/ { IPL_TOHIT, 81, 105, 32, ILVLMAX, 32, ILVLMAX, 32, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 6100, 10000, 15 }, +/*mithril*/ { IPL_TOHIT, 56, 80, 32, ILVLMAX, PLR1LVL, ILVLMAX, 32, ILVLMAX, PLT_MISC, TRUE, TRUE, 4100, 6000, 13 }, +/*weird*/ { IPL_TOHIT, 106, 130, 42, ILVLMAX, PLR1LVL, ILVLMAX, 42, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 10100, 14000, 17 }, +/*strange*/ { IPL_TOHIT, 131, 160, 54, ILVLMAX, 0, 0, 54, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 14100, 20000, 20 }, +/*bent*/ { IPL_DAMP, -75, -25, 3, 16, 0, 0, 0, 0, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, FALSE, 0, 0, -8 }, +/*jagged*/ { IPL_DAMP, 10, 35, 0, 12, 0, 8, 0, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 250, 450, 6 }, +/*deadly*/ { IPL_DAMP, 36, 50, 6, 32, 6, 16, 6, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 500, 700, 8 }, +/*heavy*/ { IPL_DAMP, 51, 60, 10, 64, 10, 32, 10, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 750, 950, 10 }, +/*vicious*/ { IPL_DAMP, 61, 80, 16, ILVLMAX, 16, 48, 16, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 1000, 1450, 16 }, +/*brutal*/ { IPL_DAMP, 81, 100, 22, ILVLMAX, 22, ILVLMAX, 22, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 1500, 1950, 20 }, +/*massive*/ { IPL_DAMP, 101, 120, 32, ILVLMAX, 32, ILVLMAX, 32, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 2000, 5000, 26 }, +/*savage*/ { IPL_DAMP, 121, 140, 44, ILVLMAX, PLR1LVL, ILVLMAX, 44, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 5000, 10000, 30 }, +/*ruthless*/ { IPL_DAMP, 141, 160, 50, ILVLMAX, 0, 0, 50, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 10000, 15000, 34 }, +/*merciless*/ { IPL_DAMP, 161, 180, 60, ILVLMAX, 0, 0, 60, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 15000, 20000, 40 }, +/*clumsy*/ { IPL_TOHIT_DAMP, -75, -25, 4, 20, 0, 0, 0, 0, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, FALSE, 0, 0, -10 }, +/*sharp*/ { IPL_TOHIT_DAMP, 10, 35, 0, 14, 0, 10, 0, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 350, 950, 10 }, +/*fine*/ { IPL_TOHIT_DAMP, 36, 50, 6, 36, 6, 20, 6, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 1100, 1700, 14 }, +/*warrior's*/ { IPL_TOHIT_DAMP, 51, 60, 12, 72, 12, 36, 12, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 1850, 2450, 26 }, +/*soldier's*/ { IPL_TOHIT_DAMP, 61, 80, 18, ILVLMAX, 18, 48, 18, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 2600, 3950, 34 }, +/*lord's*/ { IPL_TOHIT_DAMP, 81, 100, 24, ILVLMAX, 24, ILVLMAX, 24, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 4100, 5950, 42 }, +/*knight's*/ { IPL_TOHIT_DAMP, 101, 120, 35, ILVLMAX, 35, ILVLMAX, 35, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 6100, 8450, 52 }, +/*master's*/ { IPL_TOHIT_DAMP, 121, 140, 48, ILVLMAX, PLR1LVL, ILVLMAX, 48, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , TRUE, TRUE, 8600, 13000, 60 }, +/*champion's*/ { IPL_TOHIT_DAMP, 141, 160, 52, ILVLMAX, 0, 0, 52, ILVLMAX, PLT_MELEE | PLT_STAFF , TRUE, TRUE, 15200, 24000, 66 }, +/*king's*/ { IPL_TOHIT_DAMP, 161, 180, 60, ILVLMAX, 0, 0, 60, ILVLMAX, PLT_MELEE | PLT_STAFF , TRUE, TRUE, 24100, 35000, 76 }, +/*hurt*/ { IPL_CRITP, 25, 40, 8, 64, 8, 48, 8, ILVLMAX, PLT_ARMO | PLT_MISC, FALSE, TRUE, 1000, 2000, 2 }, +/*weal*/ { IPL_CRITP, 41, 60, 24, ILVLMAX, 24, ILVLMAX, 24, ILVLMAX, PLT_ARMO | PLT_MISC, FALSE, TRUE, 2000, 4000, 4 }, +/*gimp*/ { IPL_CRITP, 61, 80, 48, ILVLMAX, 0, 0, 48, ILVLMAX, PLT_ARMO | PLT_MISC, FALSE, TRUE, 4000, 8000, 8 }, +/*impair*/ { IPL_CRITP, 81, 100, 56, ILVLMAX, 0, 0, 56, ILVLMAX, PLT_ARMO | PLT_MISC, FALSE, TRUE, 8000, 16000, 16 }, +/*vulnerable*/ { IPL_ACP, -100, -25, 3, 16, 0, 0, 0, 0, PLT_ARMO | PLT_SHLD , TRUE, FALSE, 0, 0, -3 }, +/*fine*/ { IPL_ACP, 20, 30, 0, 12, 0, 8, 0, ILVLMAX, PLT_ARMO | PLT_SHLD , TRUE, TRUE, 20, 100, 2 }, +/*grand*/ { IPL_ACP, 25, 50, 6, 32, 6, 14, 6, ILVLMAX, PLT_ARMO | PLT_SHLD , TRUE, TRUE, 220, 300, 5 }, +/*valiant*/ { IPL_ACP, 51, 70, 10, 48, 10, 30, 10, ILVLMAX, PLT_ARMO | PLT_SHLD , TRUE, TRUE, 320, 400, 7 }, +/*glorious*/ { IPL_ACP, 71, 90, 14, 64, 14, 44, 14, ILVLMAX, PLT_ARMO | PLT_SHLD , TRUE, TRUE, 420, 600, 9 }, +/*blessed*/ { IPL_ACP, 91, 110, 19, ILVLMAX, 19, ILVLMAX, 19, ILVLMAX, PLT_ARMO | PLT_SHLD , TRUE, TRUE, 620, 800, 11 }, +/*saintly*/ { IPL_ACP, 111, 130, 24, ILVLMAX, 24, ILVLMAX, 24, ILVLMAX, PLT_ARMO | PLT_SHLD , TRUE, TRUE, 820, 1200, 13 }, +/*awesome*/ { IPL_ACP, 131, 150, 30, ILVLMAX, PLR1LVL, ILVLMAX, 30, ILVLMAX, PLT_ARMO | PLT_SHLD , TRUE, TRUE, 1220, 2000, 15 }, +/*holy*/ { IPL_ACP, 151, 170, 42, ILVLMAX, 0, 0, 42, ILVLMAX, PLT_ARMO | PLT_SHLD , TRUE, TRUE, 5200, 6000, 17 }, +/*godly*/ { IPL_ACP, 171, 200, 60, ILVLMAX, 0, 0, 60, ILVLMAX, PLT_ARMO | PLT_SHLD , TRUE, TRUE, 6200, 7000, 20 }, +/*rose*/ { IPL_FIRERES, 5, 15, 0, 48, 0, 16, 0, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 100, 500, 2 }, +/*red*/ { IPL_FIRERES, 10, 25, 8, 64, 8, 30, 8, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 500, 1500, 2 }, +/*crimson*/ { IPL_FIRERES, 21, 35, 16, ILVLMAX, 16, 42, 16, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 2100, 3000, 2 }, +/*burgundy*/ { IPL_FIRERES, 36, 50, 28, ILVLMAX, 28, ILVLMAX, 28, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 3100, 4000, 2 }, +/*garnet*/ { IPL_FIRERES, 51, 65, 40, ILVLMAX, PLR1LVL, ILVLMAX, 40, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 8200, 12000, 3 }, +/*ruby*/ { IPL_FIRERES, 66, 80, 50, ILVLMAX, 0, 0, 50, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 17100, 20000, 5 }, +/*sky*/ { IPL_LIGHTRES, 5, 15, 0, 48, 0, 16, 0, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 100, 500, 2 }, +/*blue*/ { IPL_LIGHTRES, 10, 25, 8, 64, 8, 30, 8, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 500, 1500, 2 }, +/*azure*/ { IPL_LIGHTRES, 21, 35, 16, ILVLMAX, 16, 42, 16, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 2100, 3000, 2 }, +/*lapis*/ { IPL_LIGHTRES, 36, 50, 28, ILVLMAX, 28, ILVLMAX, 28, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 3100, 4000, 2 }, +/*cobalt*/ { IPL_LIGHTRES, 51, 65, 40, ILVLMAX, PLR1LVL, ILVLMAX, 40, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 8200, 12000, 3 }, +/*sapphire*/ { IPL_LIGHTRES, 66, 80, 50, ILVLMAX, 0, 0, 50, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 17100, 20000, 5 }, +/*mist*/ { IPL_MAGICRES, 5, 15, 0, 48, 0, 16, 0, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 100, 500, 2 }, +/*white*/ { IPL_MAGICRES, 10, 25, 8, 64, 8, 30, 8, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 500, 1500, 2 }, +/*pearl*/ { IPL_MAGICRES, 21, 35, 16, ILVLMAX, 16, 42, 16, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 2100, 3000, 2 }, +/*ivory*/ { IPL_MAGICRES, 36, 50, 28, ILVLMAX, 28, ILVLMAX, 28, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 3100, 4000, 2 }, +/*crystal*/ { IPL_MAGICRES, 51, 65, 40, ILVLMAX, 40, ILVLMAX, 40, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 8200, 12000, 3 }, +/*diamond*/ { IPL_MAGICRES, 66, 80, 50, ILVLMAX, 0, 0, 50, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 17100, 20000, 5 }, +/*lime*/ { IPL_ACIDRES, 5, 15, 0, 48, 0, 16, 0, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 100, 500, 2 }, +/*green*/ { IPL_ACIDRES, 10, 25, 8, 64, 8, 30, 8, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 500, 1500, 2 }, +/*malachite*/ { IPL_ACIDRES, 21, 35, 16, ILVLMAX, 16, 42, 16, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 2100, 3000, 2 }, +/*jade*/ { IPL_ACIDRES, 36, 50, 28, ILVLMAX, 28, ILVLMAX, 28, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 3100, 4000, 2 }, +/*turquoise*/ { IPL_ACIDRES, 51, 65, 40, ILVLMAX, 40, ILVLMAX, 40, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 8200, 12000, 3 }, +/*emerald*/ { IPL_ACIDRES, 66, 80, 50, ILVLMAX, 0, 0, 50, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 17100, 20000, 5 }, +/*topaz*/ { IPL_ALLRES, 10, 15, 8, 64, 8, 18, 8, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 2000, 5000, 3 }, +/*amber*/ { IPL_ALLRES, 16, 20, 16, ILVLMAX, 16, 36, 16, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 7400, 10000, 3 }, +/*beryl*/ { IPL_ALLRES, 21, 30, 33, ILVLMAX, 33, ILVLMAX, 33, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 11000, 15000, 3 }, +/*obsidian*/ { IPL_ALLRES, 31, 40, 50, ILVLMAX, PLR1LVL, ILVLMAX, 50, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 24000, 40000, 4 }, +/*aquamarine*/ { IPL_ALLRES, 41, 50, 54, ILVLMAX, 0, 0, 54, ILVLMAX, PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW , FALSE, TRUE, 61000, 75000, 7 }, +/*hyena's*/ { IPL_MANA, -25, -1, 4, 16, 0, 0, 0, 0, PLT_STAFF | PLT_MISC, FALSE, FALSE, -2500, -100, -1 }, +/*spider's*/ { IPL_MANA, 10, 20, 0, 12, 0, 10, 0, ILVLMAX, PLT_STAFF | PLT_MISC, FALSE, TRUE, 500, 1000, 2 }, +/*snake's*/ { IPL_MANA, 15, 30, 6, 32, 6, 24, 6, ILVLMAX, PLT_STAFF | PLT_MISC, FALSE, TRUE, 2100, 4000, 5 }, +/*serpent's*/ { IPL_MANA, 31, 40, 14, 64, 14, 40, 14, ILVLMAX, PLT_STAFF | PLT_MISC, FALSE, TRUE, 4100, 6000, 7 }, +/*drake's*/ { IPL_MANA, 41, 50, 24, ILVLMAX, 24, ILVLMAX, 24, ILVLMAX, PLT_STAFF | PLT_MISC, FALSE, TRUE, 6100, 10000, 9 }, +/*dragon's*/ { IPL_MANA, 51, 60, 32, ILVLMAX, PLR1LVL, ILVLMAX, 32, ILVLMAX, PLT_STAFF | PLT_MISC, FALSE, TRUE, 10100, 15000, 11 }, +/*wyrm's*/ { IPL_MANA, 61, 80, 42, ILVLMAX, 0, 0, 42, ILVLMAX, PLT_STAFF , FALSE, TRUE, 15100, 19000, 12 }, +/*hydra's*/ { IPL_MANA, 81, 100, 50, ILVLMAX, 0, 0, 50, ILVLMAX, PLT_STAFF , FALSE, TRUE, 19100, 30000, 13 }, +/*angel's*/ { IPL_SKILLLEVELS, 1, 1, 15, ILVLMAX, 15, ILVLMAX, 15, ILVLMAX, PLT_STAFF , FALSE, TRUE, 25000, 25000, 2 }, +/*arch-Angel's*/ { IPL_SKILLLEVELS, 2, 2, 25, ILVLMAX, 25, ILVLMAX, 25, ILVLMAX, PLT_STAFF , FALSE, TRUE, 50000, 50000, 3 }, +/*apprentice's*/ { IPL_SKILLLVL, 1, 1, 20, ILVLMAX, 20, ILVLMAX, 20, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_STAFF | PLT_MISC, FALSE, TRUE, 13000, 13000, 2 }, +/*mage's*/ { IPL_SKILLLVL, 2, 2, 40, ILVLMAX, 40, ILVLMAX, 40, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_STAFF | PLT_MISC, FALSE, TRUE, 26000, 26000, 3 }, +/*speed*/ { IPL_FASTCAST, 1, 1, 19, ILVLMAX, 19, ILVLMAX, 19, ILVLMAX, PLT_STAFF , FALSE, TRUE, 8000, 8000, 8 }, +/*haste*/ { IPL_FASTCAST, 2, 2, 27, ILVLMAX, 27, ILVLMAX, 27, ILVLMAX, PLT_STAFF , FALSE, TRUE, 16000, 16000, 16 }, +/*harmony*/ { IPL_FASTCAST, 3, 3, 42, ILVLMAX, 0, 0, 42, ILVLMAX, PLT_STAFF , FALSE, TRUE, 32000, 32000, 32 }, +/*plentiful*/ { IPL_CHARGES, 2, 2, 12, ILVLMAX, 12, ILVLMAX, 12, ILVLMAX, PLT_CHRG , FALSE, TRUE, 2000, 2000, 2 }, +/*bountiful*/ { IPL_CHARGES, 3, 3, 24, ILVLMAX, 24, ILVLMAX, 24, ILVLMAX, PLT_CHRG , FALSE, TRUE, 3000, 3000, 3 }, +/*warm*/ { IPL_FIREDAM, 2, 4, 3, 16, 3, 16, 3, ILVLMAX, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 1800, 1800, 2 }, +/*fire*/ { IPL_FIREDAM, 5, 8, 8, 32, 8, 32, 8, ILVLMAX, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 5000, 5000, 2 }, +/*flaming*/ { IPL_FIREDAM, 10, 16, 16, 64, 16, 64, 16, ILVLMAX, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 10000, 10000, 2 }, +/*burning*/ { IPL_FIREDAM, 20, 32, 35, ILVLMAX, 35, ILVLMAX, 35, ILVLMAX, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 20000, 20000, 2 }, +/*yellow*/ { IPL_LIGHTDAM, 1, 6, 4, 16, 4, 16, 4, ILVLMAX, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 2000, 2000, 2 }, +/*lightning*/ { IPL_LIGHTDAM, 1, 10, 9, 36, 9, 36, 9, ILVLMAX, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 5000, 5000, 2 }, +/*shocking*/ { IPL_LIGHTDAM, 1, 20, 18, 72, 18, 72, 18, ILVLMAX, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 10000, 10000, 2 }, +/*thunder*/ { IPL_LIGHTDAM, 1, 40, 35, ILVLMAX, 35, ILVLMAX, 35, ILVLMAX, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 20000, 20000, 2 }, +/*glow*/ { IPL_MAGICDAM, 2, 5, 4, 16, 4, 16, 4, ILVLMAX, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 2000, 2000, 2 }, +/*unkind*/ { IPL_MAGICDAM, 3, 7, 9, 36, 9, 36, 9, ILVLMAX, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 5000, 5000, 2 }, +/*spiteful*/ { IPL_MAGICDAM, 8, 12, 18, 72, 18, 72, 18, ILVLMAX, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 10000, 10000, 2 }, +/*malicious*/ { IPL_MAGICDAM, 16, 24, 35, ILVLMAX, 35, ILVLMAX, 35, ILVLMAX, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 20000, 20000, 2 }, +/*citric*/ { IPL_ACIDDAM, 3, 6, 5, 20, 5, 20, 5, ILVLMAX, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 2500, 2500, 2 }, +/*acidic*/ { IPL_ACIDDAM, 4, 7, 10, 40, 10, 40, 10, ILVLMAX, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 5000, 5000, 2 }, +/*bitter*/ { IPL_ACIDDAM, 8, 15, 18, 72, 18, 72, 18, ILVLMAX, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 10000, 10000, 2 }, +/*corrosive*/ { IPL_ACIDDAM, 18, 28, 35, ILVLMAX, 35, ILVLMAX, 35, ILVLMAX, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 20000, 20000, 2 }, +/*fairy*/ { IPL_CRYSTALLINE, 30, 60, 32, ILVLMAX, PLR1LVL, ILVLMAX, 32, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , FALSE, TRUE, 1000, 3000, 3 }, +/*crystalline*/ { IPL_CRYSTALLINE, 61, 110, 60, ILVLMAX, 0, 0, 60, ILVLMAX, PLT_MELEE | PLT_BOW , FALSE, TRUE, 10000, 30000, 8 }, + { IPL_INVALID, 0, 0, 0, 0, 0, 0, 0, 0, 0 , FALSE, FALSE, 0, 0, 0 }, // clang-format on }; /** Contains the data related to each item suffix. */ const AffixData PL_Suffix[] = { // clang-format off -// PLPower, PLParam1, PLParam2, PLMinLvl, PLIType, PLDouble, PLOk, PLMinVal, PLMaxVal, PLMultVal -/*quality*/ { IPL_DAMMOD, 1, 2, 3, PLT_MELEE , FALSE, TRUE, 1000, 2000, 4 }, -/*maiming*/ { IPL_DAMMOD, 2, 5, 8, PLT_MELEE , FALSE, TRUE, 3000, 5000, 6 }, -/*slaying*/ { IPL_DAMMOD, 6, 8, 15, PLT_MELEE , FALSE, TRUE, 6000, 8000, 10 }, -/*gore*/ { IPL_DAMMOD, 9, 12, 25, PLT_MELEE , FALSE, TRUE, 9100, 12000, 20 }, -/*carnage*/ { IPL_DAMMOD, 13, 16, 35, PLT_MELEE , FALSE, TRUE, 13100, 16000, 30 }, -/*slaughter*/ { IPL_DAMMOD, 17, 20, 50, PLT_MELEE , FALSE, TRUE, 17000, 20000, 38 }, -/*quality*/ { IPL_DAMMOD, 1, 2, 6, PLT_STAFF | PLT_BOW , FALSE, TRUE, 1000, 2000, 4 }, -/*maiming*/ { IPL_DAMMOD, 2, 5, 16, PLT_STAFF | PLT_BOW , FALSE, TRUE, 3000, 5000, 6 }, -/*gore*/ { IPL_DAMMOD, 6, 7, 32, PLT_STAFF | PLT_BOW , FALSE, TRUE, 9100, 12000, 20 }, -/*slaughter*/ { IPL_DAMMOD, 8, 10, 50, PLT_STAFF | PLT_BOW , FALSE, TRUE, 17000, 20000, 38 }, -/*wool*/ { IPL_ACMOD, 1, 5, 2, PLT_ARMO | PLT_SHLD , FALSE, TRUE, 100, 200, 4 }, -/*fleece*/ { IPL_ACMOD, 6, 10, 18, PLT_ARMO | PLT_SHLD , FALSE, TRUE, 2000, 6000, 10 }, -/*leather*/ { IPL_ACMOD, 11, 15, 50, PLT_ARMO | PLT_SHLD , FALSE, TRUE, 8000, 12000, 16 }, -/*cotton*/ { IPL_ACMOD, 1, 5, 5, PLT_LARMOR | PLT_MARMOR | PLT_HARMOR , FALSE, TRUE, 100, 200, 4 }, -/*wool*/ { IPL_ACMOD, 6, 10, 10, PLT_LARMOR | PLT_MARMOR | PLT_HARMOR , FALSE, TRUE, 2000, 6000, 10 }, -/*fleece*/ { IPL_ACMOD, 11, 25, 20, PLT_LARMOR | PLT_MARMOR | PLT_HARMOR , FALSE, TRUE, 8000, 12000, 16 }, -/*leather*/ { IPL_ACMOD, 26, 40, 42, PLT_MARMOR | PLT_HARMOR , FALSE, TRUE, 12000, 20000, 20 }, -/*leather*/ { IPL_ACMOD, 26, 40, 60, PLT_LARMOR , FALSE, TRUE, 12000, 20000, 20 }, -/*chain*/ { IPL_ACMOD, 41, 50, 60, PLT_HARMOR , FALSE, TRUE, 20000, 24000, 24 }, -/*pain*/ { IPL_GETHIT, -4, -1, 8, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, FALSE, 0, 0, -4 }, -/*health*/ { IPL_GETHIT, 1, 3, 3, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, TRUE, 200, 200, 2 }, -/*absorption*/ { IPL_GETHIT, 2, 7, 12, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, TRUE, 1001, 2500, 10 }, -/*deflection*/ { IPL_GETHIT, 8, 11, 24, PLT_ARMO | PLT_SHLD , FALSE, TRUE, 2500, 6500, 15 }, -/*deflection*/ { IPL_GETHIT, 8, 11, 48, PLT_MISC, FALSE, TRUE, 2500, 6500, 15 }, -/*osmosis*/ { IPL_GETHIT, 12, 15, 50, PLT_ARMO , FALSE, TRUE, 7500, 10000, 20 }, -/*frailty*/ { IPL_STR, -10, -1, 3, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_BOW | PLT_MISC, FALSE, FALSE, 0, 0, -3 }, -/*strength*/ { IPL_STR, 1, 8, 1, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 200, 1000, 2 }, -/*might*/ { IPL_STR, 4, 16, 9, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 1200, 2000, 3 }, -/*power*/ { IPL_STR, 17, 23, 18, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 2200, 3000, 4 }, -/*giants*/ { IPL_STR, 24, 30, 36, PLT_ARMO | PLT_MELEE | PLT_BOW | PLT_MISC, FALSE, TRUE, 3200, 5000, 7 }, -/*giants*/ { IPL_STR, 24, 30, 50, PLT_SHLD | PLT_STAFF , FALSE, TRUE, 3200, 5000, 7 }, -/*titans*/ { IPL_STR, 31, 35, 50, PLT_MELEE | PLT_MISC, FALSE, TRUE, 5200, 10000, 10 }, -/*paralysis*/ { IPL_DEX, -10, -1, 3, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_BOW | PLT_MISC, FALSE, FALSE, 0, 0, -3 }, -/*dexterity*/ { IPL_DEX, 1, 8, 1, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 200, 1000, 2 }, -/*skill*/ { IPL_DEX, 4, 16, 9, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 1200, 2000, 3 }, -/*accuracy*/ { IPL_DEX, 17, 23, 23, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 2200, 3000, 4 }, -/*precision*/ { IPL_DEX, 24, 30, 36, PLT_ARMO | PLT_MELEE | PLT_BOW | PLT_MISC, FALSE, TRUE, 3200, 5000, 7 }, -/*precision*/ { IPL_DEX, 24, 30, 50, PLT_SHLD | PLT_STAFF , FALSE, TRUE, 3200, 5000, 7 }, -/*perfection*/ { IPL_DEX, 31, 35, 50, PLT_BOW | PLT_MISC, FALSE, TRUE, 5200, 10000, 10 }, -/*the fool*/ { IPL_MAG, -10, -1, 3, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, FALSE, 0, 0, -3 }, -/*magic*/ { IPL_MAG, 1, 8, 1, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 200, 1000, 2 }, -/*the mind*/ { IPL_MAG, 4, 16, 9, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 1200, 2000, 3 }, -/*brilliance*/ { IPL_MAG, 17, 23, 23, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 2200, 3000, 4 }, -/*sorcery*/ { IPL_MAG, 24, 30, 36, PLT_ARMO | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 3200, 5000, 7 }, -/*sorcery*/ { IPL_MAG, 24, 30, 50, PLT_SHLD , FALSE, TRUE, 3200, 5000, 7 }, -/*wizardry*/ { IPL_MAG, 31, 35, 50, PLT_STAFF | PLT_MISC, FALSE, TRUE, 5200, 10000, 10 }, -/*illness*/ { IPL_VIT, -10, -1, 3, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_BOW | PLT_MISC, FALSE, FALSE, 0, 0, -3 }, -/*vitality*/ { IPL_VIT, 1, 8, 1, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 200, 1000, 2 }, -/*zest*/ { IPL_VIT, 4, 16, 9, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 1200, 2000, 3 }, -/*vim*/ { IPL_VIT, 17, 23, 23, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 2200, 3000, 4 }, -/*vigor*/ { IPL_VIT, 24, 30, 36, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_BOW | PLT_MISC, FALSE, TRUE, 3200, 5000, 7 }, -/*life*/ { IPL_VIT, 31, 35, 50, PLT_MISC, FALSE, TRUE, 5200, 10000, 10 }, -/*trouble*/ { IPL_ATTRIBS, -10, -1, 8, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_BOW | PLT_MISC, FALSE, FALSE, 0, 0, -10 }, -/*the sky*/ { IPL_ATTRIBS, 1, 3, 5, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 800, 4000, 5 }, -/*the moon*/ { IPL_ATTRIBS, 4, 7, 11, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 4800, 8000, 10 }, -/*the stars*/ { IPL_ATTRIBS, 8, 11, 24, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 8800, 12000, 15 }, -/*the heavens*/ { IPL_ATTRIBS, 12, 15, 44, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_BOW | PLT_MISC, FALSE, TRUE, 12800, 20000, 20 }, -/*the zodiac*/ { IPL_ATTRIBS, 16, 20, 60, PLT_MISC, FALSE, TRUE, 20800, 40000, 30 }, -/*the vulture*/ { IPL_LIFE, -25, -1, 3, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, FALSE, 0, 0, -4 }, -/*the fox*/ { IPL_LIFE, 10, 20, 1, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, TRUE, 100, 1000, 2 }, -/*the jaguar*/ { IPL_LIFE, 16, 30, 7, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, TRUE, 1100, 2000, 3 }, -/*the wolf*/ { IPL_LIFE, 31, 40, 15, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, TRUE, 4100, 6000, 7 }, -/*the tiger*/ { IPL_LIFE, 41, 50, 21, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, TRUE, 6100, 10000, 9 }, -/*the lion*/ { IPL_LIFE, 51, 60, 27, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, TRUE, 10100, 15000, 11 }, -/*the mammoth*/ { IPL_LIFE, 61, 80, 40, PLT_ARMO , FALSE, TRUE, 15100, 19000, 12 }, -/*the whale*/ { IPL_LIFE, 81, 100, 60, PLT_ARMO , FALSE, TRUE, 19100, 30000, 13 }, -/*brittleness*/ { IPL_DUR_CURSE, 26, 75, 3, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW , FALSE, FALSE, 0, 0, -2 }, -/*sturdiness*/ { IPL_DUR, 26, 50, 1, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF , FALSE, TRUE, 100, 100, 2 }, -/*craftsmanship*/ { IPL_DUR, 30, 100, 6, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF , FALSE, TRUE, 200, 200, 2 }, -/*structure*/ { IPL_DUR, 101, 200, 12, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF , FALSE, TRUE, 300, 300, 2 }, -/*the ages*/ { IPL_INDESTRUCTIBLE, 0, 0, 25, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF , FALSE, TRUE, 600, 600, 5 }, -/*the dark*/ { IPL_LIGHT, -4, -1, 7, PLT_ARMO | PLT_MELEE | PLT_MISC, FALSE, FALSE, 0, 0, -3 }, -/*light*/ { IPL_LIGHT, 1, 2, 4, PLT_ARMO | PLT_MELEE | PLT_MISC, FALSE, TRUE, 750, 750, 2 }, -/*radiance*/ { IPL_LIGHT, 3, 4, 8, PLT_ARMO | PLT_MELEE | PLT_MISC, FALSE, TRUE, 1500, 1500, 3 }, -/*lightness*/ { IPL_FASTWALK, 1, 1, 19, PLT_LARMOR | PLT_MARMOR | PLT_HARMOR , FALSE, TRUE, 8000, 8000, 8 }, -/*speed*/ { IPL_FASTWALK, 2, 2, 27, PLT_LARMOR | PLT_MARMOR , FALSE, TRUE, 16000, 16000, 16 }, -/*haste*/ { IPL_FASTWALK, 3, 3, 40, PLT_LARMOR , FALSE, TRUE, 32000, 32000, 32 }, -/*fire*/ { IPL_FIREDAM, 2, 3, 4, PLT_BOW , FALSE, TRUE, 2000, 2000, 2 }, -/*flaming*/ { IPL_FIREDAM, 3, 5, 11, PLT_BOW , FALSE, TRUE, 4000, 4000, 4 }, -/*burning*/ { IPL_FIREDAM, 6, 10, 22, PLT_BOW , FALSE, TRUE, 5000, 5000, 5 }, -/*scorching*/ { IPL_FIREDAM, 10, 12, 35, PLT_BOW , FALSE, TRUE, 6000, 6000, 6 }, -/*lightning*/ { IPL_LIGHTDAM, 1, 6, 13, PLT_BOW , FALSE, TRUE, 6000, 6000, 2 }, -/*shocking*/ { IPL_LIGHTDAM, 1, 10, 21, PLT_BOW , FALSE, TRUE, 8000, 8000, 4 }, -/*thunder*/ { IPL_LIGHTDAM, 1, 20, 40, PLT_BOW , FALSE, TRUE, 12000, 12000, 6 }, -/*unkind*/ { IPL_MAGICDAM, 2, 5, 13, PLT_BOW , FALSE, TRUE, 6000, 6000, 2 }, -/*spiteful*/ { IPL_MAGICDAM, 4, 6, 21, PLT_BOW , FALSE, TRUE, 8000, 8000, 4 }, -/*malicious*/ { IPL_MAGICDAM, 8, 12, 40, PLT_BOW , FALSE, TRUE, 12000, 12000, 6 }, -/*acidic*/ { IPL_ACIDDAM, 3, 5, 13, PLT_BOW , FALSE, TRUE, 6000, 6000, 2 }, -/*bitter*/ { IPL_ACIDDAM, 4, 8, 21, PLT_BOW , FALSE, TRUE, 8000, 8000, 4 }, -/*corrosive*/ { IPL_ACIDDAM, 10, 14, 40, PLT_BOW , FALSE, TRUE, 12000, 12000, 6 }, -/*many*/ { IPL_DUR, 100, 100, 3, PLT_BOW , FALSE, TRUE, 750, 750, 2 }, -/*plenty*/ { IPL_DUR, 200, 200, 7, PLT_BOW , FALSE, TRUE, 1500, 1500, 3 }, -/*thorns*/// { IPL_THORNS, 0, 0, 1, PLT_ARMO | PLT_SHLD , FALSE, TRUE, 500, 500, 2 }, -/*corruption*/ { IPL_NOMANA, 0, 0, 8, PLT_ARMO | PLT_SHLD | PLT_MELEE , FALSE, FALSE, -1000, -1000, -1 }, -/*thieves*/// { IPL_ABSHALFTRAP, 0, 0, 11, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, TRUE, 1500, 1500, 2 }, -/*the bear*/ { IPL_KNOCKBACK, 0, 0, 18, PLT_MELEE | PLT_STAFF | PLT_BOW , FALSE, TRUE, 750, 750, 2 }, -/*bashing*/ { IPL_STUN, 0, 0, 24, PLT_MELEE | PLT_STAFF | PLT_BOW , FALSE, TRUE, 1500, 1500, 2 }, -/*bloodlust*/ { IPL_BLEED, 0, 0, 24, PLT_MELEE | PLT_BOW , FALSE, TRUE, 3000, 3000, 3 }, -/*mosquito*/ { IPL_STEALMANA, 1, 2, 4, PLT_MELEE , FALSE, TRUE, 4000, 7500, 3 }, -/*the bat*/ { IPL_STEALMANA, 2, 4, 10, PLT_MELEE , FALSE, TRUE, 7500, 15000, 3 }, -/*vampires*/ { IPL_STEALMANA, 4, 6, 20, PLT_MELEE , FALSE, TRUE, 15000, 22500, 3 }, -/*flea*/ { IPL_STEALLIFE, 1, 3, 6, PLT_MELEE , FALSE, TRUE, 5000, 10000, 3 }, -/*the leech*/ { IPL_STEALLIFE, 3, 5, 15, PLT_MELEE , FALSE, TRUE, 10000, 15000, 3 }, -/*blood*/ { IPL_STEALLIFE, 5, 8, 32, PLT_MELEE , FALSE, TRUE, 15000, 25000, 3 }, -/*piercing*/ { IPL_PENETRATE_PHYS, 0, 0, 15, PLT_MELEE | PLT_BOW , FALSE, TRUE, 1000, 1000, 8 }, -/*readiness*/ { IPL_FASTATTACK, 1, 1, 3, PLT_MELEE | PLT_STAFF | PLT_BOW , FALSE, TRUE, 2000, 2000, 2 }, -/*swiftness*/ { IPL_FASTATTACK, 1, 2, 10, PLT_MELEE | PLT_STAFF | PLT_BOW , FALSE, TRUE, 4000, 4000, 4 }, -/*speed*/ { IPL_FASTATTACK, 2, 3, 35, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 8000, 8000, 8 }, -/*haste*/ { IPL_FASTATTACK, 4, 4, 50, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 16000, 16000, 16 }, -/*balance*/ { IPL_FASTRECOVER, 1, 1, 3, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, TRUE, 2000, 2000, 2 }, -/*stability*/ { IPL_FASTRECOVER, 1, 2, 10, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, TRUE, 4000, 4000, 4 }, -/*harmony*/ { IPL_FASTRECOVER, 2, 3, 20, PLT_ARMO | PLT_MISC, FALSE, TRUE, 8000, 8000, 8 }, -/*blocking*/ { IPL_FASTBLOCK, 1, 1, 5, PLT_SHLD , FALSE, TRUE, 4000, 4000, 4 }, -/* */ { IPL_INVALID, 0, 0, 0, 0 , FALSE, FALSE, 0, 0, 0 }, +// PLPower, PLParam1, PLParam2, PLRanges, IAR_DROP, from_1, IAR_SHOP, from_2, IAR_CRAFT, PLIType, PLDouble, PLOk, PLMinVal, PLMaxVal, PLMultVal +/*quality*/ { IPL_DAMMOD, 1, 2, 3, 16, 3, 10, 3, ILVLMAX, PLT_MELEE , FALSE, TRUE, 1000, 2000, 4 }, +/*maiming*/ { IPL_DAMMOD, 2, 5, 8, 32, 8, 24, 8, ILVLMAX, PLT_MELEE , FALSE, TRUE, 3000, 5000, 6 }, +/*slaying*/ { IPL_DAMMOD, 6, 8, 15, 64, 15, 48, 15, ILVLMAX, PLT_MELEE , FALSE, TRUE, 6000, 8000, 10 }, +/*gore*/ { IPL_DAMMOD, 9, 12, 25, ILVLMAX, 25, ILVLMAX, 25, ILVLMAX, PLT_MELEE , FALSE, TRUE, 9100, 12000, 20 }, +/*carnage*/ { IPL_DAMMOD, 13, 16, 35, ILVLMAX, 35, ILVLMAX, 35, ILVLMAX, PLT_MELEE , FALSE, TRUE, 13100, 16000, 30 }, +/*slaughter*/ { IPL_DAMMOD, 17, 20, 50, ILVLMAX, 0, 0, 50, ILVLMAX, PLT_MELEE , FALSE, TRUE, 17000, 20000, 38 }, +/*quality*/ { IPL_DAMMOD, 1, 2, 6, 24, 6, 24, 6, ILVLMAX, PLT_STAFF | PLT_BOW , FALSE, TRUE, 1000, 2000, 4 }, +/*maiming*/ { IPL_DAMMOD, 2, 5, 16, 64, 16, 48, 16, ILVLMAX, PLT_STAFF | PLT_BOW , FALSE, TRUE, 3000, 5000, 6 }, +/*gore*/ { IPL_DAMMOD, 6, 7, 32, ILVLMAX, 32, ILVLMAX, 32, ILVLMAX, PLT_STAFF | PLT_BOW , FALSE, TRUE, 9100, 12000, 20 }, +/*slaughter*/ { IPL_DAMMOD, 8, 10, 50, ILVLMAX, 48, ILVLMAX, 50, ILVLMAX, PLT_STAFF | PLT_BOW , FALSE, TRUE, 17000, 20000, 38 }, +/*wool*/ { IPL_ACMOD, 1, 5, 2, 16, 2, 16, 2, ILVLMAX, PLT_ARMO | PLT_SHLD , FALSE, TRUE, 100, 200, 4 }, +/*fleece*/ { IPL_ACMOD, 6, 10, 18, 72, 18, ILVLMAX, 18, ILVLMAX, PLT_ARMO | PLT_SHLD , FALSE, TRUE, 2000, 6000, 10 }, +/*leather*/ { IPL_ACMOD, 11, 15, 50, ILVLMAX, 48, ILVLMAX, 50, ILVLMAX, PLT_ARMO | PLT_SHLD , FALSE, TRUE, 8000, 12000, 16 }, +/*cotton*/ { IPL_ACMOD, 1, 5, 5, 32, 5, 16, 5, ILVLMAX, PLT_LARMOR | PLT_MARMOR | PLT_HARMOR , FALSE, TRUE, 100, 200, 4 }, +/*wool*/ { IPL_ACMOD, 6, 10, 10, 64, 10, 24, 10, ILVLMAX, PLT_LARMOR | PLT_MARMOR | PLT_HARMOR , FALSE, TRUE, 2000, 6000, 10 }, +/*fleece*/ { IPL_ACMOD, 11, 25, 20, ILVLMAX, 20, 45, 20, ILVLMAX, PLT_LARMOR | PLT_MARMOR | PLT_HARMOR , FALSE, TRUE, 8000, 12000, 16 }, +/*leather*/ { IPL_ACMOD, 26, 40, 42, ILVLMAX, 42, ILVLMAX, 42, ILVLMAX, PLT_MARMOR | PLT_HARMOR , FALSE, TRUE, 12000, 20000, 20 }, +/*leather*/ { IPL_ACMOD, 26, 40, 60, ILVLMAX, 40, ILVLMAX, 60, ILVLMAX, PLT_LARMOR , FALSE, TRUE, 12000, 20000, 20 }, +/*chain*/ { IPL_ACMOD, 41, 50, 60, ILVLMAX, 40, ILVLMAX, 60, ILVLMAX, PLT_HARMOR , FALSE, TRUE, 20000, 24000, 24 }, +/*pain*/ { IPL_GETHIT, -4, -1, 8, 24, 0, 0, 0, 0, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, FALSE, 0, 0, -4 }, +/*health*/ { IPL_GETHIT, 1, 3, 3, 16, 3, 16, 3, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, TRUE, 200, 200, 2 }, +/*absorption*/ { IPL_GETHIT, 2, 7, 12, 48, 12, 32, 12, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, TRUE, 1001, 2500, 10 }, +/*deflection*/ { IPL_GETHIT, 8, 11, 24, ILVLMAX, 24, ILVLMAX, 24, ILVLMAX, PLT_ARMO | PLT_SHLD , FALSE, TRUE, 2500, 6500, 15 }, +/*deflection*/ { IPL_GETHIT, 8, 11, 48, ILVLMAX, 48, ILVLMAX, 48, ILVLMAX, PLT_MISC, FALSE, TRUE, 2500, 6500, 15 }, +/*osmosis*/ { IPL_GETHIT, 12, 15, 50, ILVLMAX, 48, ILVLMAX, 50, ILVLMAX, PLT_ARMO , FALSE, TRUE, 7500, 10000, 20 }, +/*frailty*/ { IPL_STR, -10, -1, 3, 12, 0, 0, 0, 0, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_BOW | PLT_MISC, FALSE, FALSE, 0, 0, -3 }, +/*strength*/ { IPL_STR, 1, 8, 0, 20, 0, 14, 0, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 200, 1000, 2 }, +/*might*/ { IPL_STR, 8, 16, 9, 36, 9, 36, 9, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 1200, 2000, 3 }, +/*power*/ { IPL_STR, 17, 23, 23, ILVLMAX, 23, ILVLMAX, 23, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 2200, 3000, 4 }, +/*giants*/ { IPL_STR, 24, 30, 36, ILVLMAX, 36, ILVLMAX, 36, ILVLMAX, PLT_ARMO | PLT_MELEE | PLT_BOW | PLT_MISC, FALSE, TRUE, 3200, 5000, 7 }, +/*giants*/ { IPL_STR, 24, 30, 50, ILVLMAX, 0, 0, 50, ILVLMAX, PLT_SHLD | PLT_STAFF , FALSE, TRUE, 3200, 5000, 7 }, +/*titans*/ { IPL_STR, 31, 35, 50, ILVLMAX, 0, 0, 50, ILVLMAX, PLT_MELEE | PLT_MISC, FALSE, TRUE, 5200, 10000, 10 }, +/*paralysis*/ { IPL_DEX, -10, -1, 3, 12, 0, 0, 0, 0, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_BOW | PLT_MISC, FALSE, FALSE, 0, 0, -3 }, +/*dexterity*/ { IPL_DEX, 1, 8, 0, 20, 0, 14, 0, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 200, 1000, 2 }, +/*skill*/ { IPL_DEX, 8, 16, 9, 36, 9, 36, 9, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 1200, 2000, 3 }, +/*accuracy*/ { IPL_DEX, 17, 23, 23, ILVLMAX, 23, ILVLMAX, 23, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 2200, 3000, 4 }, +/*precision*/ { IPL_DEX, 24, 30, 36, ILVLMAX, 36, ILVLMAX, 36, ILVLMAX, PLT_ARMO | PLT_MELEE | PLT_BOW | PLT_MISC, FALSE, TRUE, 3200, 5000, 7 }, +/*precision*/ { IPL_DEX, 24, 30, 50, ILVLMAX, 0, 0, 50, ILVLMAX, PLT_SHLD | PLT_STAFF , FALSE, TRUE, 3200, 5000, 7 }, +/*perfection*/ { IPL_DEX, 31, 35, 50, ILVLMAX, 0, 0, 50, ILVLMAX, PLT_BOW | PLT_MISC, FALSE, TRUE, 5200, 10000, 10 }, +/*the fool*/ { IPL_MAG, -10, -1, 3, 12, 0, 0, 0, 0, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, FALSE, 0, 0, -3 }, +/*magic*/ { IPL_MAG, 1, 8, 0, 20, 0, 14, 0, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 200, 1000, 2 }, +/*the mind*/ { IPL_MAG, 8, 16, 9, 36, 9, 36, 9, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 1200, 2000, 3 }, +/*brilliance*/ { IPL_MAG, 17, 23, 23, ILVLMAX, 23, ILVLMAX, 23, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 2200, 3000, 4 }, +/*sorcery*/ { IPL_MAG, 24, 30, 36, ILVLMAX, 36, ILVLMAX, 36, ILVLMAX, PLT_ARMO | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 3200, 5000, 7 }, +/*sorcery*/ { IPL_MAG, 24, 30, 50, ILVLMAX, 0, 0, 50, ILVLMAX, PLT_SHLD , FALSE, TRUE, 3200, 5000, 7 }, +/*wizardry*/ { IPL_MAG, 31, 35, 50, ILVLMAX, 0, 0, 50, ILVLMAX, PLT_STAFF | PLT_MISC, FALSE, TRUE, 5200, 10000, 10 }, +/*illness*/ { IPL_VIT, -10, -1, 3, 12, 0, 0, 0, 0, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_BOW | PLT_MISC, FALSE, FALSE, 0, 0, -3 }, +/*vitality*/ { IPL_VIT, 1, 8, 0, 20, 0, 14, 0, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 200, 1000, 2 }, +/*zest*/ { IPL_VIT, 4, 16, 9, 36, 9, 36, 9, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 1200, 2000, 3 }, +/*vim*/ { IPL_VIT, 17, 23, 23, ILVLMAX, 23, ILVLMAX, 23, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 2200, 3000, 4 }, +/*vigor*/ { IPL_VIT, 24, 30, 36, ILVLMAX, 36, ILVLMAX, 36, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_BOW | PLT_MISC, FALSE, TRUE, 3200, 5000, 7 }, +/*life*/ { IPL_VIT, 31, 35, 50, ILVLMAX, 0, 0, 50, ILVLMAX, PLT_MISC, FALSE, TRUE, 5200, 10000, 10 }, +/*trouble*/ { IPL_ATTRIBS, -10, -1, 8, 16, 0, 0, 0, 0, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_BOW | PLT_MISC, FALSE, FALSE, 0, 0, -10 }, +/*the sky*/ { IPL_ATTRIBS, 1, 3, 5, 20, 5, 16, 5, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 800, 4000, 5 }, +/*the moon*/ { IPL_ATTRIBS, 4, 7, 11, 48, 11, 42, 11, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 4800, 8000, 10 }, +/*the stars*/ { IPL_ATTRIBS, 8, 11, 24, ILVLMAX, 24, ILVLMAX, 24, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW | PLT_MISC, FALSE, TRUE, 8800, 12000, 15 }, +/*the heavens*/ { IPL_ATTRIBS, 12, 15, 44, ILVLMAX, 0, 0, 44, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_BOW | PLT_MISC, FALSE, TRUE, 12800, 20000, 20 }, +/*the zodiac*/ { IPL_ATTRIBS, 16, 20, 60, ILVLMAX, 0, 0, 60, ILVLMAX, PLT_MISC, FALSE, TRUE, 20800, 40000, 30 }, +/*the vulture*/ { IPL_LIFE, -25, -1, 3, 12, 0, 0, 0, 0, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, FALSE, 0, 0, -4 }, +/*the fox*/ { IPL_LIFE, 10, 20, 0, 12, 0, 10, 0, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, TRUE, 100, 1000, 2 }, +/*the jaguar*/ { IPL_LIFE, 21, 30, 7, 28, 7, 20, 7, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, TRUE, 1100, 2000, 3 }, +/*the wolf*/ { IPL_LIFE, 31, 40, 15, 64, 15, 32, 15, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, TRUE, 4100, 6000, 7 }, +/*the tiger*/ { IPL_LIFE, 41, 50, 21, ILVLMAX, 21, ILVLMAX, 21, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, TRUE, 6100, 10000, 9 }, +/*the lion*/ { IPL_LIFE, 51, 60, 27, ILVLMAX, 27, ILVLMAX, 27, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, TRUE, 10100, 15000, 11 }, +/*the mammoth*/ { IPL_LIFE, 61, 80, 40, ILVLMAX, PLR1LVL, ILVLMAX, 40, ILVLMAX, PLT_ARMO , FALSE, TRUE, 15100, 19000, 12 }, +/*the whale*/ { IPL_LIFE, 81, 100, 60, ILVLMAX, 0, 0, 60, ILVLMAX, PLT_ARMO , FALSE, TRUE, 19100, 30000, 13 }, +/*brittleness*/ { IPL_DUR_CURSE, 26, 75, 3, 16, 0, 0, 0, 0, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF | PLT_BOW , FALSE, FALSE, 0, 0, -2 }, +/*sturdiness*/ { IPL_DUR, 26, 50, 0, 64, 0, 48, 0, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF , FALSE, TRUE, 100, 100, 2 }, +/*craftsmanship*/ { IPL_DUR, 51, 100, 6, ILVLMAX, 6, ILVLMAX, 6, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF , FALSE, TRUE, 200, 200, 2 }, +/*structure*/ { IPL_DUR, 101, 200, 12, ILVLMAX, 12, ILVLMAX, 12, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF , FALSE, TRUE, 300, 300, 2 }, +/*the ages*/ { IPL_INDESTRUCTIBLE, 0, 0, 25, ILVLMAX, 0, 0, 25, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MELEE | PLT_STAFF , FALSE, TRUE, 600, 600, 5 }, +/*the dark*/ { IPL_LIGHT, -4, -1, 7, 32, 0, 0, 0, 0, PLT_ARMO | PLT_MELEE | PLT_MISC, FALSE, FALSE, 0, 0, -3 }, +/*light*/ { IPL_LIGHT, 1, 2, 4, ILVLMAX, 4, ILVLMAX, 4, ILVLMAX, PLT_ARMO | PLT_MELEE | PLT_MISC, FALSE, TRUE, 750, 750, 2 }, +/*radiance*/ { IPL_LIGHT, 3, 4, 8, ILVLMAX, 8, ILVLMAX, 8, ILVLMAX, PLT_ARMO | PLT_MELEE | PLT_MISC, FALSE, TRUE, 1500, 1500, 3 }, +/*lightness*/ { IPL_FASTWALK, 1, 1, 19, ILVLMAX, 19, ILVLMAX, 19, ILVLMAX, PLT_LARMOR | PLT_MARMOR | PLT_HARMOR , FALSE, TRUE, 8000, 8000, 8 }, +/*speed*/ { IPL_FASTWALK, 2, 2, 27, ILVLMAX, 27, ILVLMAX, 27, ILVLMAX, PLT_LARMOR | PLT_MARMOR , FALSE, TRUE, 16000, 16000, 16 }, +/*haste*/ { IPL_FASTWALK, 3, 3, 40, ILVLMAX, 0, 0, 40, ILVLMAX, PLT_LARMOR , FALSE, TRUE, 32000, 32000, 32 }, +/*fire*/ { IPL_FIREDAM, 2, 3, 4, 32, 4, 16, 4, ILVLMAX, PLT_BOW , FALSE, TRUE, 2000, 2000, 2 }, +/*flaming*/ { IPL_FIREDAM, 3, 5, 11, 64, 11, 48, 11, ILVLMAX, PLT_BOW , FALSE, TRUE, 4000, 4000, 4 }, +/*burning*/ { IPL_FIREDAM, 6, 10, 22, ILVLMAX, 22, ILVLMAX, 22, ILVLMAX, PLT_BOW , FALSE, TRUE, 5000, 5000, 5 }, +/*scorching*/ { IPL_FIREDAM, 10, 12, 35, ILVLMAX, 35, ILVLMAX, 35, ILVLMAX, PLT_BOW , FALSE, TRUE, 6000, 6000, 6 }, +/*lightning*/ { IPL_LIGHTDAM, 1, 6, 13, 64, 13, 42, 13, ILVLMAX, PLT_BOW , FALSE, TRUE, 6000, 6000, 2 }, +/*shocking*/ { IPL_LIGHTDAM, 1, 10, 21, ILVLMAX, 21, ILVLMAX, 21, ILVLMAX, PLT_BOW , FALSE, TRUE, 8000, 8000, 4 }, +/*thunder*/ { IPL_LIGHTDAM, 1, 20, 40, ILVLMAX, 40, ILVLMAX, 40, ILVLMAX, PLT_BOW , FALSE, TRUE, 12000, 12000, 6 }, +/*unkind*/ { IPL_MAGICDAM, 2, 5, 13, 64, 13, 42, 13, ILVLMAX, PLT_BOW , FALSE, TRUE, 6000, 6000, 2 }, +/*spiteful*/ { IPL_MAGICDAM, 4, 6, 21, ILVLMAX, 21, ILVLMAX, 21, ILVLMAX, PLT_BOW , FALSE, TRUE, 8000, 8000, 4 }, +/*malicious*/ { IPL_MAGICDAM, 8, 12, 40, ILVLMAX, 40, ILVLMAX, 40, ILVLMAX, PLT_BOW , FALSE, TRUE, 12000, 12000, 6 }, +/*acidic*/ { IPL_ACIDDAM, 3, 5, 13, 64, 13, 42, 13, ILVLMAX, PLT_BOW , FALSE, TRUE, 6000, 6000, 2 }, +/*bitter*/ { IPL_ACIDDAM, 4, 8, 21, ILVLMAX, 21, ILVLMAX, 21, ILVLMAX, PLT_BOW , FALSE, TRUE, 8000, 8000, 4 }, +/*corrosive*/ { IPL_ACIDDAM, 10, 14, 40, ILVLMAX, 40, ILVLMAX, 40, ILVLMAX, PLT_BOW , FALSE, TRUE, 12000, 12000, 6 }, +/*many*/ { IPL_DUR, 100, 100, 3, ILVLMAX, 3, ILVLMAX, 3, ILVLMAX, PLT_BOW , FALSE, TRUE, 750, 750, 2 }, +/*plenty*/ { IPL_DUR, 200, 200, 7, ILVLMAX, 7, ILVLMAX, 7, ILVLMAX, PLT_BOW , FALSE, TRUE, 1500, 1500, 3 }, +/*thorns*/// { IPL_THORNS, 0, 0, 1, ILVLMAX, 1, ILVLMAX, 1, ILVLMAX, PLT_ARMO | PLT_SHLD , FALSE, TRUE, 500, 500, 2 }, +/*corruption*/ { IPL_NOMANA, 0, 0, 8, 20, 0, 0, 0, 0, PLT_ARMO | PLT_SHLD | PLT_MELEE , FALSE, FALSE, -1000, -1000, -1 }, +/*thieves*/// { IPL_ABSHALFTRAP, 0, 0, 11, ILVLMAX, 11, ILVLMAX, 11, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, TRUE, 1500, 1500, 2 }, +/*the bear*/ { IPL_KNOCKBACK, 0, 0, 18, ILVLMAX, 18, ILVLMAX, 18, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , FALSE, TRUE, 750, 750, 2 }, +/*bashing*/ { IPL_STUN, 0, 0, 24, ILVLMAX, 24, ILVLMAX, 24, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , FALSE, TRUE, 1500, 1500, 2 }, +/*bloodlust*/ { IPL_BLEED, 0, 0, 24, ILVLMAX, 24, ILVLMAX, 24, ILVLMAX, PLT_MELEE | PLT_BOW , FALSE, TRUE, 3000, 3000, 3 }, +/*mosquito*/ { IPL_STEALMANA, 1, 2, 4, 64, 4, 40, 4, ILVLMAX, PLT_MELEE , FALSE, TRUE, 4000, 7500, 3 }, +/*the bat*/ { IPL_STEALMANA, 2, 4, 10, ILVLMAX, 10, ILVLMAX, 10, ILVLMAX, PLT_MELEE , FALSE, TRUE, 7500, 15000, 3 }, +/*vampires*/ { IPL_STEALMANA, 4, 6, 20, ILVLMAX, 20, ILVLMAX, 20, ILVLMAX, PLT_MELEE , FALSE, TRUE, 15000, 22500, 3 }, +/*flea*/ { IPL_STEALLIFE, 1, 3, 6, 64, 6, 40, 6, ILVLMAX, PLT_MELEE , FALSE, TRUE, 5000, 10000, 3 }, +/*the leech*/ { IPL_STEALLIFE, 3, 5, 15, ILVLMAX, 15, ILVLMAX, 15, ILVLMAX, PLT_MELEE , FALSE, TRUE, 10000, 15000, 3 }, +/*blood*/ { IPL_STEALLIFE, 5, 8, 32, ILVLMAX, 32, ILVLMAX, 32, ILVLMAX, PLT_MELEE , FALSE, TRUE, 15000, 25000, 3 }, +/*piercing*/ { IPL_PENETRATE_PHYS, 0, 0, 15, ILVLMAX, 15, ILVLMAX, 15, ILVLMAX, PLT_MELEE | PLT_BOW , FALSE, TRUE, 1000, 1000, 8 }, +/*readiness*/ { IPL_FASTATTACK, 1, 1, 3, ILVLMAX, 3, ILVLMAX, 3, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , FALSE, TRUE, 2000, 2000, 2 }, +/*swiftness*/ { IPL_FASTATTACK, 2, 2, 10, ILVLMAX, 0, 0, 10, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , FALSE, TRUE, 4000, 4000, 4 }, +/*speed*/ { IPL_FASTATTACK, 3, 3, 35, ILVLMAX, 0, 0, 35, ILVLMAX, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 8000, 8000, 8 }, +/*haste*/ { IPL_FASTATTACK, 4, 4, 50, ILVLMAX, 0, 0, 50, ILVLMAX, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 16000, 16000, 16 }, +/*balance*/ { IPL_FASTRECOVER, 1, 1, 3, ILVLMAX, 3, ILVLMAX, 3, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, TRUE, 2000, 2000, 2 }, +/*stability*/ { IPL_FASTRECOVER, 2, 2, 10, ILVLMAX, 10, ILVLMAX, 10, ILVLMAX, PLT_ARMO | PLT_SHLD | PLT_MISC, FALSE, TRUE, 4000, 4000, 4 }, +/*harmony*/ { IPL_FASTRECOVER, 3, 3, 20, ILVLMAX, 20, ILVLMAX, 20, ILVLMAX, PLT_ARMO | PLT_MISC, FALSE, TRUE, 8000, 8000, 8 }, +/*blocking*/ { IPL_FASTBLOCK, 1, 1, 5, ILVLMAX, 5, ILVLMAX, 5, ILVLMAX, PLT_SHLD , FALSE, TRUE, 4000, 4000, 4 }, +/* */ { IPL_INVALID, 0, 0, 0, 0, 0, 0, 0, 0, 0 , FALSE, FALSE, 0, 0, 0 }, // clang-format on }; diff --git a/Source/itemdat.h b/Source/itemdat.h index bd053fb5e47..84f8abef548 100644 --- a/Source/itemdat.h +++ b/Source/itemdat.h @@ -10,6 +10,7 @@ DEVILUTION_BEGIN_NAMESPACE #define ITEM_RNDDROP_MAX 160 #define ITEM_RNDAFFIX_MAX 160 +#define ILVLMAX 127 #ifdef __cplusplus extern "C" { diff --git a/Source/items.cpp b/Source/items.cpp index 826fbbaa19b..03796cbefd9 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -1630,7 +1630,7 @@ static void SaveItemPower(int ii, int power, int param1, int param2, int minval, } } -static void GetItemPower(int ii, unsigned minlvl, unsigned maxlvl, int flgs, bool onlygood) +static void GetItemPower(int ii, unsigned lvl, BYTE range, int flgs, bool onlygood) { int nl, v; const AffixData *pres, *sufs; @@ -1639,6 +1639,8 @@ static void GetItemPower(int ii, unsigned minlvl, unsigned maxlvl, int flgs, boo BOOLEAN good; // assert(items[ii]._iMagical == ITEM_QUALITY_NORMAL); + if (flgs != PLT_MISC) // items[ii]._itype != ITYPE_RING && items[ii]._itype != ITYPE_AMULET) + lvl = lvl > AllItemsList[items[ii]._iIdx].iMinMLvl ? lvl - AllItemsList[items[ii]._iIdx].iMinMLvl : 0; // select affixes (3: both, 2: prefix, 1: suffix) v = random_(23, 128); @@ -1649,7 +1651,7 @@ static void GetItemPower(int ii, unsigned minlvl, unsigned maxlvl, int flgs, boo nl = 0; for (pres = PL_Prefix; pres->PLPower != IPL_INVALID; pres++) { if ((flgs & pres->PLIType) - && pres->PLMinLvl >= minlvl && pres->PLMinLvl <= maxlvl + && pres->PLRanges[range].from <= lvl && pres->PLRanges[range].to >= lvl // && (!onlygood || pres->PLOk)) { && (good <= pres->PLOk)) { l[nl] = pres; @@ -1679,7 +1681,7 @@ static void GetItemPower(int ii, unsigned minlvl, unsigned maxlvl, int flgs, boo nl = 0; for (sufs = PL_Suffix; sufs->PLPower != IPL_INVALID; sufs++) { if ((sufs->PLIType & flgs) - && sufs->PLMinLvl >= minlvl && sufs->PLMinLvl <= maxlvl + && sufs->PLRanges[range].from <= lvl && sufs->PLRanges[range].to >= lvl // && (!onlygood || sufs->PLOk)) { && (good <= sufs->PLOk)) { l[nl] = sufs; @@ -1717,7 +1719,7 @@ static void GetItemPower(int ii, unsigned minlvl, unsigned maxlvl, int flgs, boo } } -static void GetItemBonus(int ii, unsigned minlvl, unsigned maxlvl, bool onlygood, bool allowspells) +static void GetItemBonus(int ii, unsigned lvl, BYTE range, bool onlygood, bool allowspells) { int flgs; @@ -1750,7 +1752,7 @@ static void GetItemBonus(int ii, unsigned minlvl, unsigned maxlvl, bool onlygood case ITYPE_STAFF: flgs = PLT_STAFF; if (allowspells && random_(17, 4) != 0) { - GetStaffSpell(ii, maxlvl); + GetStaffSpell(ii, lvl); if (random_(51, 2) != 0) return; flgs |= PLT_CHRG; @@ -1767,7 +1769,7 @@ static void GetItemBonus(int ii, unsigned minlvl, unsigned maxlvl, bool onlygood return; } - GetItemPower(ii, minlvl, maxlvl, flgs, onlygood); + GetItemPower(ii, lvl, range, flgs, onlygood); } static int RndUItem(unsigned lvl) @@ -1986,7 +1988,7 @@ static void SetupAllItems(int ii, int idx, int iseed, unsigned lvl, unsigned qua || random_(32, 128) < 14 || (unsigned)random_(33, 128) <= lvl) { uid = CheckUnique(ii, lvl, quality); if (uid < 0) { - GetItemBonus(ii, lvl >> 2, lvl, quality >= CFDQ_GOOD, true); + GetItemBonus(ii, lvl, IAR_DROP, quality >= CFDQ_GOOD, true); } else { GetUniqueItem(ii, uid); return; @@ -2517,7 +2519,7 @@ static void DoRecharge(int pnum, int cii) static void DoClean(ItemStruct* pi, bool whittle) { int seed, spell; - uint16_t ci, idx; + uint16_t ci, idx, ll; seed = pi->_iSeed; spell = pi->_iSpell; @@ -2528,9 +2530,12 @@ static void DoClean(ItemStruct* pi, bool whittle) idx = IDI_DROPSHSTAFF; spell = SPL_NULL; } - + ll = (pi->_itype != ITYPE_RING && pi->_itype != ITYPE_AMULET) ? AllItemsList[idx].iMinMLvl : 0; + if (spell != SPL_NULL && spelldata[spell].sStaffLvl > ll) { + ll = spelldata[spell].sStaffLvl; + } ci = (pi->_iCreateInfo & CF_LEVEL); - if (ci > AllItemsList[idx].iMinMLvl) + if (ci > ll) ci--; ci |= CF_CRAFTED; @@ -3457,7 +3462,7 @@ static void SpawnOnePremium(int i, unsigned lvl) seed = NextRndSeed(); SetRndSeed(seed); GetItemAttrs(0, RndSmithItem(lvl), lvl); - GetItemBonus(0, lvl >> 1, lvl, true, false); + GetItemBonus(0, lvl, IAR_SHOP, true, false); } while (items[0]._iIvalue > SMITH_MAX_PREMIUM_VALUE); items[0]._iSeed = seed; items[0]._iCreateInfo = lvl | CF_SMITHPREMIUM; @@ -3576,7 +3581,7 @@ void SpawnWitch(unsigned lvl) SetRndSeed(seed); GetItemAttrs(0, RndWitchItem(lvl), lvl); // if (random_(51, 100) <= 5 || items[0]._itype == ITYPE_STAFF) - GetItemBonus(0, lvl >> 1, lvl, true, true); + GetItemBonus(0, lvl, IAR_SHOP, true, true); } while (items[0]._iIvalue > WITCH_MAX_VALUE); items[0]._iSeed = seed; items[0]._iCreateInfo = lvl | CF_WITCH; @@ -3599,7 +3604,7 @@ void SpawnBoy(unsigned lvl) seed = NextRndSeed(); SetRndSeed(seed); GetItemAttrs(0, RndSmithItem(lvl), lvl); - GetItemBonus(0, lvl >> 1, lvl << 1, true, true); + GetItemBonus(0, lvl, IAR_SHOP, true, true); } while (items[0]._iIvalue > BOY_MAX_VALUE); items[0]._iSeed = seed; items[0]._iCreateInfo = lvl | CF_BOY; @@ -3719,7 +3724,7 @@ static void RecreatePremiumItem(int ii/*, int iseed*/, int idx, unsigned lvl) { // SetRndSeed(iseed); GetItemAttrs(ii, RndSmithItem(lvl), lvl); - GetItemBonus(ii, lvl >> 1, lvl, true, false); + GetItemBonus(ii, lvl, IAR_SHOP, true, false); //items[ii]._iSeed = iseed; //items[ii]._iCreateInfo = lvl | CF_SMITHPREMIUM; @@ -3729,7 +3734,7 @@ static void RecreateBoyItem(int ii/*, int iseed*/, int idx, unsigned lvl) { // SetRndSeed(iseed); GetItemAttrs(ii, RndSmithItem(lvl), lvl); - GetItemBonus(ii, lvl >> 1, lvl << 1, true, true); + GetItemBonus(ii, lvl, IAR_SHOP, true, true); //items[ii]._iSeed = iseed; //items[ii]._iCreateInfo = lvl | CF_BOY; @@ -3743,7 +3748,7 @@ static void RecreateWitchItem(int ii/*, int iseed*/, int idx, unsigned lvl) // SetRndSeed(iseed); GetItemAttrs(ii, RndWitchItem(lvl), lvl); // if (random_(51, 100) <= 5 || items[ii]._itype == ITYPE_STAFF) - GetItemBonus(ii, lvl >> 1, lvl, true, true); + GetItemBonus(ii, lvl, IAR_SHOP, true, true); //} //items[ii]._iSeed = iseed; @@ -3768,7 +3773,7 @@ static void RecreateCraftedItem(int ii/*, int iseed*/, int idx, unsigned lvl) // SetRndSeed(iseed); GetItemAttrs(ii, idx, lvl); if (random_(51, 2) != 0) - GetItemBonus(ii, 0, lvl != 0 ? lvl : 1, true, true); + GetItemBonus(ii, lvl, IAR_CRAFT, true, true); //items[ii]._iSeed = iseed; //items[ii]._iCreateInfo = lvl | CF_CRAFTED; diff --git a/Source/stores.cpp b/Source/stores.cpp index 886f77f149f..e3de2e6e1a2 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -70,10 +70,6 @@ DEVILUTION_BEGIN_NAMESPACE #define STORE_ID_PRICE 100 #define STORE_PEGBOY_PRICE 50 -// level limits of the premium items by the smith -#define STORE_PITEM_MINLVL 6 -#define STORE_PITEM_MAXLVL 32 - /* The current item in store. */ ItemStruct storeitem; /* The item for sale by Wirt. */ @@ -167,10 +163,6 @@ static unsigned StoresLimitedItemLvl() int l = myplr._pLevel; l += 2; - if (l < STORE_PITEM_MINLVL) - l = STORE_PITEM_MINLVL; - if (l > STORE_PITEM_MAXLVL) - l = STORE_PITEM_MAXLVL; return l; } @@ -204,7 +196,7 @@ void InitLvlStores() SpawnSmith(l); SpawnWitch(l); SpawnHealer(l); - SpawnBoy(l); + SpawnBoy(l + 8); SpawnPremium(l); } diff --git a/enums.h b/enums.h index 8933f42e2ce..36bbf965e0b 100644 --- a/enums.h +++ b/enums.h @@ -415,6 +415,13 @@ typedef enum item_effect_type { IPL_INVALID = 0xFF, } item_effect_type; +typedef enum item_affix_range { + IAR_DROP, + IAR_SHOP, + IAR_CRAFT, + NUM_IARS +} item_affix_range; + typedef enum affix_item_type { PLT_MISC = 1 << 1, PLT_BOW = 1 << 2, diff --git a/structs.h b/structs.h index 436b74e45a3..1ab8cb4a051 100644 --- a/structs.h +++ b/structs.h @@ -101,11 +101,16 @@ typedef struct CelImageBuf { // items ////////////////////////////////////////////////// +typedef struct RANGE { + BYTE from; + BYTE to; +} RANGE; + typedef struct AffixData { BYTE PLPower; // item_effect_type int PLParam1; int PLParam2; - BYTE PLMinLvl; + RANGE PLRanges[NUM_IARS]; int PLIType; // affix_item_type BOOLEAN PLDouble; BOOLEAN PLOk; From 085cc17fa1e097c7099e7ec51e79b23ccf8f57bf Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 26 Jul 2024 13:59:09 +0200 Subject: [PATCH 358/596] fix ValidateData when HELLFIRE is not set --- Source/debug.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Source/debug.cpp b/Source/debug.cpp index e625704bd81..02fae847831 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -494,6 +494,11 @@ void ValidateData() int rnddrops = 0; for (i = 0; i < NUM_IDI; i++) { const ItemData& ids = AllItemsList[i]; + if (ids.iName == NULL) { + if (i >= IDI_RNDDROP_FIRST || ids.iRnd != 0) + app_fatal("Invalid iRnd value for nameless item (%d)", i); + continue; + } if (strlen(ids.iName) > 32 - 1) app_fatal("Too long name for %s (%d)", ids.iName, i); rnddrops += ids.iRnd; @@ -1171,8 +1176,10 @@ void ValidateData() app_fatal("No staff spell for GetStaffSpell."); if (!hasScrollSpell) app_fatal("No scroll spell for GetScrollSpell."); +#ifdef HELLFIRE if (!hasRuneSpell) app_fatal("No rune spell for GetRuneSpell."); +#endif // missiles for (i = 0; i < NUM_MISTYPES; i++) { From f8be5a4605be7441f87983d04c6a367b42da640a Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 27 Jul 2024 09:36:27 +0200 Subject: [PATCH 359/596] fix oil-usage when HELLFIRE is not set --- Source/msg.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/msg.cpp b/Source/msg.cpp index 36f9d60d249..ab7d49e62b5 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -2562,11 +2562,9 @@ static unsigned On_OPERATEITEM(TCmd* pCmd, int pnum) (cmd->iou.from == SPLFROM_ABILITY && cmd->iou.skill != SPL_OIL)); net_assert(cmd->ioIdx < NUM_INVELEM); -#ifdef HELLFIRE if (cmd->iou.skill == SPL_OIL) DoOil(pnum, cmd->iou.from, cmd->ioIdx); else -#endif DoAbility(pnum, cmd->iou.from, cmd->ioIdx); if (currLvl._dLevelIdx == plr._pDunLevel) { From cf05f8b3847665d711126b73f585d89554eef2b8 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 27 Jul 2024 19:17:11 +0200 Subject: [PATCH 360/596] fix string-limit in stores --- Source/stores.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/stores.cpp b/Source/stores.cpp index e3de2e6e1a2..cd6fd66f4c7 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -209,7 +209,9 @@ void PrintSString(int x, int y, bool cjustflag, const char* str, BYTE col, int v sx = (gbWidePanel ? LTPANEL_X + 7 : STORE_PNL_X + 7) + x; sy = LTPANEL_Y + 20 + y * 12 + stextlines[y]._syoff; limit = gbWidePanel ? LTPANEL_WIDTH - 7 * 2 : STPANEL_WIDTH - 7 * 2; + limit -= x; if (cjustflag) { + // assert(x == 0); -- otherwise limit -= x; ? width = GetSmallStringWidth(str); if (width < limit) { sx += (limit - width) >> 1; From 4c4c0a4ecf619a77a5c1c2d49ec354848cc6ee64 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 28 Jul 2024 07:34:28 +0200 Subject: [PATCH 361/596] add campaigns --- Packaging/resources/devilx.mpq | Bin 1247157 -> 1250309 bytes Packaging/resources/listfiles.txt | 1 + Packaging/resources/mpqfiles.txt | 1 + Source/control.cpp | 203 +++++++++++++++++++++++++++++ Source/control.h | 6 + Source/cursor.cpp | 2 +- Source/debug.cpp | 1 + Source/diablo.cpp | 15 +++ Source/gameui.h | 4 + Source/interfac.cpp | 3 +- Source/inv.cpp | 59 +++++++++ Source/inv.h | 1 + Source/itemdat.cpp | 3 +- Source/items.cpp | 10 +- Source/loadsave.cpp | 2 + Source/msg.cpp | 34 ++++- Source/msg.h | 2 +- Source/scrollrt.cpp | 3 + Source/stores.cpp | 2 +- defs.h | 3 + docs/CHANGELOG.md | 2 +- enums.h | 16 ++- structs.h | 12 ++ tools/patcher/DiabloUI/checker.cpp | 10 +- 24 files changed, 378 insertions(+), 17 deletions(-) diff --git a/Packaging/resources/devilx.mpq b/Packaging/resources/devilx.mpq index c51f2ac1d3c882b69909d0ce6f3e6a68627f65eb..9d9f3bc7312bb8d4817be30eacd406f5b33abde1 100644 GIT binary patch delta 11642 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 ZNdF-JgYpmRKWP7;|AWy;!GXE8@qZ(> (idx - 1)) & 1) ? SDL_TRUE : SDL_FALSE; + if (x > 8 - CAM_RADIUS && camEntries[x - 1][y].ceDunType == DTYPE_TOWN) { + camEntries[x - 1][y].ceDunType = NUM_DTYPES + type; + db++; + } + if (x < 8 + CAM_RADIUS && camEntries[x + 1][y].ceDunType == DTYPE_TOWN) { + camEntries[x + 1][y].ceDunType = NUM_DTYPES + type; + db++; + } + if (y > 8 - CAM_RADIUS && camEntries[x][y - 1].ceDunType == DTYPE_TOWN) { + camEntries[x][y - 1].ceDunType = NUM_DTYPES + type; + db++; + } + if (y < 8 + CAM_RADIUS && camEntries[x][y + 1].ceDunType == DTYPE_TOWN) { + camEntries[x][y + 1].ceDunType = NUM_DTYPES + type; + db++; + } + *border += db; +} + +static void control_setmaplevel(int x, int y, BYTE lvl) +{ + if (camEntries[x][y].ceIndex != 0 && (camEntries[x][y].ceLevel == 0 || camEntries[x][y].ceLevel > lvl)) { + camEntries[x][y].ceLevel = lvl; + + lvl += 4; + if (lvl > MAXCAMPAIGNLVL) + lvl = MAXCAMPAIGNLVL; + control_setmaplevel(x + 1, y + 0, lvl); + control_setmaplevel(x - 1, y + 0, lvl); + control_setmaplevel(x + 0, y + 1, lvl); + control_setmaplevel(x + 0, y - 1, lvl); + } +} + +void InitCampaignMap(int cii) +{ + BYTE idx = 0; + WORD available; + int border = 1; + int numMaps = MAXCAMPAIGNSIZE; + // TODO: prevent map-open after CMD_USEPLRMAP? + camItemIndex = cii; + ItemStruct* is = PlrItem(mypnum, camItemIndex); + available = is->_ivalue; + // generate the map + SetRndSeed(is->_iSeed); + + memset(camEntries, 0, sizeof(camEntries)); + static_assert(DTYPE_TOWN == 0, "InitCampaignMap must be adjusted."); + control_addmappos(lengthof(camEntries) / 2, lengthof(camEntries[0]) / 2, random_(200, NUM_DTYPES - 1) + 1, ++idx, available, &border); + + for (int i = 0; i < numMaps - 1; i++) { + int step = random_low(201, border) + 1; + for (int x = 0; x < lengthof(camEntries); x++) { + for (int y = 0; y < lengthof(camEntries[0]); y++) { + if (camEntries[x][y].ceDunType > NUM_DTYPES && --step == 0) { + BYTE type = random_(202, 3 * (NUM_DTYPES - 1)) + 1; + if (type >= NUM_DTYPES) { + type = camEntries[x][y].ceDunType - NUM_DTYPES; + } + control_addmappos(x, y, type, ++idx, available, &border); + x = lengthof(camEntries); + break; + } + } + } + } + + BYTE lvl = (is->_iCreateInfo & CF_LEVEL) - HELL_LEVEL_BONUS; + control_setmaplevel(lengthof(camEntries) / 2, lengthof(camEntries[0]) / 2, lvl); + + gbCampaignMapFlag = true; +} + +void TryCampaignMapClick(bool bShift, bool altAction) +{ + if (!altAction) { + BYTE mIdx = currCamEntry.ceIndex; + if (mIdx != 0) { + if (currCamEntry.ceAvailable) { + selCamEntry = currCamEntry; + NetSendCmdBParam2(CMD_USEPLRMAP, camItemIndex, mIdx - 1); + if (!bShift) { + if (gbInvflag) { + gbInvflag = false; + /* gbInvflag =*/ ToggleWindow(WND_INV); + } + } + } else { + return; + } + } + } + + gbCampaignMapFlag = false; +} + +void DrawCampaignMap() +{ + int x, y, sx, sy, lx, ly; + sx = PANEL_CENTERX(CAMICON_WIDTH * CAMROWICONLS); + sy = PANEL_CENTERY(CAMICON_HEIGHT * CAMROWICONLS) + CAMICON_HEIGHT; + + sx += CAMICON_WIDTH * (CAM_RADIUS - lengthof(camEntries) / 2); + sy += CAMICON_HEIGHT * (CAM_RADIUS - lengthof(camEntries[0]) / 2); + + currCamEntry = { 0 }; + for (int cy = 0; cy < lengthof(camEntries[0]); cy++) { + for (int cx = 0; cx < lengthof(camEntries); cx++) { + const CampaignMapEntry &cme = camEntries[cy][cx]; + if (cme.ceIndex != 0) { + x = sx + CAMICON_WIDTH * (cx/* + CAM_RADIUS - lengthof(camEntries) / 2*/); + y = sy + CAMICON_HEIGHT * (cy/* + CAM_RADIUS - lengthof(camEntries[0]) / 2*/); + lx = x - BORDER_LEFT; + ly = y - (BORDER_TOP + CAMICON_HEIGHT); + + const BYTE* tbl = ColorTrns[COLOR_TRN_GRAY]; + if (cme.ceAvailable) { // not visited + if ((cx == lengthof(camEntries) / 2 && cy == lengthof(camEntries[0]) / 2) // starting place + || (camEntries[cy + 0][cx + 1].ceIndex != 0 && !camEntries[cy + 0][cx + 1].ceAvailable) // neighbour of a visited place + || (camEntries[cy + 0][cx - 1].ceIndex != 0 && !camEntries[cy + 0][cx - 1].ceAvailable) + || (camEntries[cy + 1][cx + 0].ceIndex != 0 && !camEntries[cy + 1][cx + 0].ceAvailable) + || (camEntries[cy - 1][cx + 0].ceIndex != 0 && !camEntries[cy - 1][cx + 0].ceAvailable)) { + tbl = ColorTrns[0]; + } else { + continue; + } + } + + CelDrawTrnTbl(x, y, pMapIconCels, cme.ceDunType, tbl); + + if (POS_IN_RECT(MousePos.x, MousePos.y, lx, ly, CAMICON_WIDTH, CAMICON_HEIGHT)) { + CelDrawTrnTbl(x, y, pMapIconCels, CAMICONLAST, tbl); + + currCamEntry = cme; + } + } + } + } +} + DEVILUTION_END_NAMESPACE diff --git a/Source/control.h b/Source/control.h index 873c0409b1d..dc8ae37d440 100644 --- a/Source/control.h +++ b/Source/control.h @@ -39,6 +39,9 @@ extern unsigned guTeamMute; extern bool gabPanbtn[NUM_PANBTNS]; extern int numpanbtns; extern bool gbSkillListFlag; +extern bool gbCampaignMapFlag; +extern int camItemIndex; +extern CampaignMapEntry selCamEntry; void DrawSkillList(); void SetSkill(bool shift, bool altSkill); @@ -76,6 +79,9 @@ void control_drop_gold(int vkey); void DrawTeamBook(); void CheckTeamClick(bool shift); void DrawGolemBar(); +void InitCampaignMap(int cii); +void DrawCampaignMap(); +void TryCampaignMapClick(bool bShift, bool altAction); #ifdef __cplusplus } diff --git a/Source/cursor.cpp b/Source/cursor.cpp index a2fca0fcac9..2eaaa86f8d3 100644 --- a/Source/cursor.cpp +++ b/Source/cursor.cpp @@ -285,7 +285,7 @@ void CheckCursMove() static_assert(MDM_ALIVE == 0, "BitOr optimization of CheckCursMove expects MDM_ALIVE to be zero."); static_assert(STORE_NONE == 0, "BitOr optimization of CheckCursMove expects STORE_NONE to be zero."); - if (gbDeathflag /*| gbDoomflag*/ | gbSkillListFlag | gbQtextflag | stextflag) + if (gbDeathflag /*| gbDoomflag*/ | gbSkillListFlag | gbQtextflag | stextflag | gbCampaignMapFlag) return; sx = MousePos.x; diff --git a/Source/debug.cpp b/Source/debug.cpp index 02fae847831..dbcbf128b94 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -588,6 +588,7 @@ void ValidateData() case IMISC_OILRESIST: case IMISC_OILCHANCE: case IMISC_OILCLEAN: + case IMISC_MAP: break; default: app_fatal("Usable item %s (%d) with miscId %d is not handled by SyncUseItem.", ids.iName, i, ids.iMiscId); diff --git a/Source/diablo.cpp b/Source/diablo.cpp index cb2395d6b66..7a4e8fc8873 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -483,6 +483,11 @@ static void ActionBtnDown(bool bShift) //assert(!gbDoomflag); assert(!gbQtextflag); + if (gbCampaignMapFlag) { + TryCampaignMapClick(bShift, false); + return; + } + if (gbSkillListFlag) { SetSkill(bShift, false); return; @@ -563,6 +568,11 @@ static void AltActionBtnDown(bool bShift) //assert(!gbDoomflag); assert(!gbQtextflag); + if (gbCampaignMapFlag) { + TryCampaignMapClick(bShift, true); + return; + } + if (gbSkillListFlag) { SetSkill(bShift, true); return; @@ -696,6 +706,10 @@ bool PressEscKey() gbSkillListFlag = false; rv = true; } + if (gbCampaignMapFlag) { + gbCampaignMapFlag = false; + rv = true; + } if (gabPanbtn[PANBTN_MAINMENU]) { gabPanbtn[PANBTN_MAINMENU] = false; rv = true; @@ -714,6 +728,7 @@ void ClearPanels() gbInvflag = false; gnNumActiveWindows = 0; gbSkillListFlag = false; + gbCampaignMapFlag = false; gbDropGoldFlag = false; } diff --git a/Source/gameui.h b/Source/gameui.h index 8b1ada617c3..af021e2c970 100644 --- a/Source/gameui.h +++ b/Source/gameui.h @@ -109,6 +109,10 @@ extern "C" { #define LVLUP_LEFT (PANEL_LEFT + 175) #define LVLUP_OFFSET 24 +#define CAMICON_WIDTH 37 +#define CAMICON_HEIGHT 38 +#define CAMICONLAST 7 + #define LTPANEL_WIDTH 591 #define STPANEL_WIDTH 271 #define TPANEL_HEIGHT 303 diff --git a/Source/interfac.cpp b/Source/interfac.cpp index 5a1de4497e3..5a40fd652fe 100644 --- a/Source/interfac.cpp +++ b/Source/interfac.cpp @@ -268,11 +268,12 @@ void EnterLevel(BYTE lvl) if (currLvl._dDynLvl) { // select level unsigned baseLevel = gDynLevels[lvl - NUM_FIXLVLS]._dnLevel; + unsigned leveltype = gDynLevels[lvl - NUM_FIXLVLS]._dnType; // assert(baseLevel + HELL_LEVEL_BONUS < CF_LEVEL); int availableLvls[NUM_FIXLVLS]; int numLvls = 0; for (int i = DLV_CATHEDRAL1; i < NUM_STDLVLS; i++) { - if (AllLevels[i].dLevel <= baseLevel /*&& AllLevels[i].dMonTypes[0] != MT_INVALID*/) { + if (AllLevels[i].dLevel <= baseLevel && (leveltype == DLV_TOWN || leveltype == AllLevels[i].dType) /*&& AllLevels[i].dMonTypes[0] != MT_INVALID*/) { availableLvls[numLvls] = i; numLvls++; } diff --git a/Source/inv.cpp b/Source/inv.cpp index f723d82350e..eef732c42ff 100644 --- a/Source/inv.cpp +++ b/Source/inv.cpp @@ -1830,6 +1830,9 @@ bool InvUseItem(int cii) && (spelldata[is->_iSpell].sUseFlags & SFLAG_DUNGEON) == SFLAG_DUNGEON) { return true; } + if (currLvl._dType != DTYPE_TOWN && is->_iMiscId == IMISC_MAP) { + return true; + } // add sfx if (is->_iMiscId == IMISC_BOOK) @@ -1878,6 +1881,9 @@ bool InvUseItem(int cii) gbTSplFrom = cii; NewCursor(CURSOR_OIL); return true; + case IMISC_MAP: + InitCampaignMap(cii); + return true; #ifdef HELLFIRE case IMISC_NOTE: StartQTextMsg(TEXT_BOOK9); @@ -1974,6 +1980,7 @@ bool SyncUseItem(int pnum, BYTE cii, BYTE sn) case IMISC_OILRESIST: case IMISC_OILCHANCE: case IMISC_OILCLEAN: + case IMISC_MAP: // should not happen, only if the player is reckless... return false; default: @@ -1985,6 +1992,58 @@ bool SyncUseItem(int pnum, BYTE cii, BYTE sn) return sn == SPL_INVALID; } +bool SyncUseMapItem(int pnum, BYTE cii, BYTE mIdx) +{ + ItemStruct* is; + + // assert(plr._pmode != PM_DEATH); + // assert(cii < NUM_INVELEM); + // assert(mIdx < MAXCAMPAIGNSIZE); + + is = PlrItem(pnum, cii); + + if (is->_itype == ITYPE_NONE || !is->_iStatFlag) + return false; + + // if (!is->_iUsable) + // return false; + + // use the item + if (is->_iMiscId != IMISC_MAP) { + return false; + } + + int available = is->_ivalue; + int mask = 1 << mIdx; + if (!(available & mask)) { + return false; + } + + if (pnum == mypnum && camItemIndex == cii) { + SetRndSeed(is->_iSeed); + // skip the seeds used during map-generation + for (int i = 0; i < 2 * MAXCAMPAIGNSIZE; i++) { + NextRndSeed(); + } + // calculate the seed of the map + for (int i = 0; i < mIdx; i++) { + DWORD seed = NextRndSeed(); + seed = (seed >> 8) | (seed << 24); // _rotr(seed, 8) + SetRndSeed(seed); + } + NetSendCmdCreateLvl(GetRndSeed(), selCamEntry.ceLevel, selCamEntry.ceDunType); + } + + available &= ~mask; + if (available == 0) { + SyncPlrItemRemove(pnum, cii); + } else { + is->_ivalue = available; + } + + return true; +} + void CalculateGold(int pnum) { ItemStruct* pi; diff --git a/Source/inv.h b/Source/inv.h index f87d00a8879..d36d60fe544 100644 --- a/Source/inv.h +++ b/Source/inv.h @@ -49,6 +49,7 @@ BYTE CheckInvItem(); BYTE CheckInvBelt(); bool InvUseItem(int cii); bool SyncUseItem(int pnum, BYTE cii, BYTE sn); +bool SyncUseMapItem(int pnum, BYTE cii, BYTE mIdx); void CalculateGold(int pnum); #ifdef __cplusplus diff --git a/Source/itemdat.cpp b/Source/itemdat.cpp index d4412db46f5..1090a845169 100644 --- a/Source/itemdat.cpp +++ b/Source/itemdat.cpp @@ -20,7 +20,7 @@ const BYTE ItemCAnimTbl[NUM_ICURS] = { // clang-format off IFILE_FBTTLEBB, IFILE_SCROLL, IFILE_SCROLL, IFILE_SCROLL, IFILE_GOLDFLIP, IFILE_GOLDFLIP, IFILE_GOLDFLIP, IFILE_RING, IFILE_RING, IFILE_RING, IFILE_RING, IFILE_RING, IFILE_RING, IFILE_RING, IFILE_RING, IFILE_FBTTLEDY, IFILE_FBTTLEDY, IFILE_FBTTLEBY, IFILE_RING, IFILE_FEAR, - IFILE_FEAR, IFILE_FEAR, 0, 0, 0, IFILE_BLDSTN, 0, 0, 0, IFILE_FBTTLEBL, + IFILE_FEAR, IFILE_FEAR, 0, 0, 0, IFILE_BLDSTN, IFILE_BLDSTN, 0, 0, IFILE_FBTTLEBL, IFILE_FBTTLEBL, IFILE_FBTTLEWH, IFILE_FBTTLE, IFILE_FBTTLEBY, IFILE_FBTTLEOR, IFILE_FBTTLEBR, IFILE_FBTTLEBL, IFILE_FBTTLEBY, IFILE_FBTTLEDB, IFILE_FBTTLEDB, IFILE_FBRAIN, 0, IFILE_FBRAIN, 0, IFILE_RING, IFILE_RING, IFILE_RING, IFILE_RING, IFILE_RING, 0/*IFILE_FHEART*/, IFILE_SWRDFLIP, IFILE_SWRDFLIP, 0/*IFILE_FOOD*/, IFILE_SWRDFLIP, IFILE_SWRDFLIP, IFILE_SWRDFLIP, IFILE_SWRDFLIP, IFILE_SWRDFLIP, IFILE_SWRDFLIP, IFILE_MACE, // 50 ... @@ -213,6 +213,7 @@ const ItemData AllItemsList[NUM_IDI] = { /* */ { "Amulet", 1, 8, UITYPE_AMULET, ICURS_AMULET, ITYPE_AMULET, IMISC_NONE, SPL_NULL, ICLASS_MISC, ILOC_AMULET, IDAM_NONE, 0, 0, 0, 0, 0, 0, FALSE, 0, 0, 0, 1200, ALIGN }, /* */ { "Amulet", 1, 16, UITYPE_AMULET, ICURS_AMULET, ITYPE_AMULET, IMISC_NONE, SPL_NULL, ICLASS_MISC, ILOC_AMULET, IDAM_NONE, 0, 0, 0, 0, 0, 0, FALSE, 0, 0, 0, 1200, ALIGN }, /* */ { "Amulet", 1, 33, UITYPE_AMULET, ICURS_AMULET, ITYPE_AMULET, IMISC_NONE, SPL_NULL, ICLASS_MISC, ILOC_AMULET, IDAM_NONE, 0, 0, 0, 0, 0, 0, FALSE, 0, 0, 0, 1200, ALIGN }, +/*IDI_CAMPAIGNMAP*/ { "Campaign Map", 1, 64, UITYPE_NONE, ICURS_CAMPAIGN_MAP, ITYPE_MISC, IMISC_MAP, SPL_NULL, ICLASS_MISC, ILOC_UNEQUIPABLE, IDAM_NONE, 0, 0, 0, 0, 0, 0, TRUE, 0, 0, 1, 0xFFFF, ALIGN }, #ifdef HELLFIRE /* */ { "Rune of ", 1, 1, UITYPE_NONE, ICURS_RUNE_OF_FIRE, ITYPE_MISC, IMISC_RUNE, SPL_NULL, ICLASS_MISC, ILOC_BELT, IDAM_NONE, 0, 0, 0, 0, 0, 0, TRUE, 0, 0, SS_RUNE, 0, ALIGN }, /* */ { "Rune of ", 1, 3, UITYPE_NONE, ICURS_RUNE_OF_FIRE, ITYPE_MISC, IMISC_RUNE, SPL_NULL, ICLASS_MISC, ILOC_BELT, IDAM_NONE, 0, 0, 0, 0, 0, 0, TRUE, 0, 0, SS_RUNE, 0, ALIGN }, diff --git a/Source/items.cpp b/Source/items.cpp index 03796cbefd9..a5bc064c5b3 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -1797,7 +1797,7 @@ static int RndUItem(unsigned lvl) for (i = IDI_RNDDROP_FIRST; i < NUM_IDI; i++) { ril[i - IDI_RNDDROP_FIRST] = (lvl < AllItemsList[i].iMinMLvl || - (AllItemsList[i].itype == ITYPE_MISC && AllItemsList[i].iMiscId != IMISC_BOOK)) ? 0 : AllItemsList[i].iRnd; + (AllItemsList[i].itype == ITYPE_MISC && AllItemsList[i].iMiscId != IMISC_BOOK && AllItemsList[i].iMiscId != IMISC_MAP)) ? 0 : AllItemsList[i].iRnd; } ri = 0; for (i = 0; i < (NUM_IDI - IDI_RNDDROP_FIRST); i++) @@ -3198,6 +3198,14 @@ static void PrintItemMiscInfo(const ItemStruct* is, int x, int& y) desc = "of a magic item"; PrintItemString(x, y, desc); break; + case IMISC_MAP: + snprintf(tempstr, sizeof(tempstr), "(lvl: %d)", is->_iCreateInfo & CF_LEVEL); + PrintItemString(x, y); + desc = "right-click to use"; + PrintItemString(x, y, desc); + desc = "(only in town)"; + PrintItemString(x, y, desc); + return; #ifdef HELLFIRE //case IMISC_MAPOFDOOM: // desc = "right-click to view"; diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index adb46d28f08..a92968d53b5 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -767,6 +767,7 @@ void LoadGame() _CurrSeed = ghs->vhCurrSeed; for (i = 0; i < NUM_DYNLVLS; i++) { gDynLevels[i]._dnLevel = ghs->vhDynLvls[i].vdLevel; + gDynLevels[i]._dnType = ghs->vhDynLvls[i].vdType; } // load player-data _ViewX = ghs->vhViewX; @@ -1606,6 +1607,7 @@ void SaveGame() } for (i = 0; i < NUM_DYNLVLS; i++) { ghs->vhDynLvls[i].vdLevel = gDynLevels[i]._dnLevel; + ghs->vhDynLvls[i].vdType = gDynLevels[i]._dnType; } ghs->vhCurrSeed = GetRndSeed(); // save player-data diff --git a/Source/msg.cpp b/Source/msg.cpp index ab7d49e62b5..a0ab0a7a6cb 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -289,6 +289,7 @@ static BYTE* DeltaExportJunk(BYTE* dst) for (i = 0; i < NUM_DYNLVLS; i++) { pDLevel->dlSeed = glSeedTbl[NUM_FIXLVLS + i]; pDLevel->dlLevel = gDynLevels[i]._dnLevel; + pDLevel->dlType = gDynLevels[i]._dnType; pDLevel++; } dst = (BYTE*)pDLevel; @@ -328,11 +329,12 @@ static void DeltaImportJunk() quests[i]._qvar1 = pDQuest->qvar1; } src = (BYTE*)pDQuest; - // export dynamic levels + // update dynamic levels pDLevel = (DDDynLevel*)src; for (i = 0; i < NUM_DYNLVLS; i++) { glSeedTbl[NUM_FIXLVLS + i] = pDLevel->dlSeed; gDynLevels[i]._dnLevel = pDLevel->dlLevel; + gDynLevels[i]._dnType = pDLevel->dlType; pDLevel++; } src = (BYTE*)pDLevel; @@ -833,6 +835,7 @@ void PackPkItem(PkItemStruct* dest, const ItemStruct* src) dest->bMDur = src->_iMaxDur; dest->bCh = src->_iCharges; dest->bMCh = src->_iMaxCharges; + static_assert(MAXCAMPAIGNSIZE <= 16, "PackPkItem stores the campaign status in 2 bytes."); dest->wValue = static_cast(src->_ivalue); } else { PackEar(dest, src); @@ -923,6 +926,8 @@ void UnPackPkItem(const PkItemStruct* src) value = src->wValue; net_assert(value <= GOLD_MAX_LIMIT); SetGoldItemValue(&items[MAXITEMS], value); + } else if (idx == IDI_CAMPAIGNMAP) { + items[MAXITEMS]._ivalue = src->wValue; } items[MAXITEMS]._iIdentified = src->bId; items[MAXITEMS]._iDurability = src->bDur; @@ -2185,13 +2190,15 @@ void NetSendCmdNewLvl(BYTE fom, BYTE bLevel) NetSendChunk((BYTE*)&cmd, sizeof(cmd)); } -void NetSendCmdCreateLvl(DWORD seed) +void NetSendCmdCreateLvl(DWORD seed, BYTE lvl, BYTE type) { TCmdCreateLvl cmd; cmd.bCmd = CMD_CREATELVL; cmd.clPlayers = gbActivePlayers; // TODO: could be done in On_CREATELVL cmd.clSeed = seed; + cmd.clLevel = lvl; + cmd.clType = type; NetSendChunk((BYTE*)&cmd, sizeof(cmd)); } @@ -2716,6 +2723,7 @@ static unsigned On_CREATELVL(TCmd* pCmd, int pnum) { TCmdCreateLvl* cmd = (TCmdCreateLvl*)pCmd; BYTE bLevel, bPlayers; + if (plr._pDunLevel == DLV_TOWN && !plr._pLvlChanging && plr._pmode != PM_DEATH) { for (bLevel = NUM_FIXLVLS; bLevel < NUM_LEVELS; bLevel++) { int i = 0; for ( ; i < MAX_PLRS; i++) { @@ -2731,6 +2739,7 @@ static unsigned On_CREATELVL(TCmd* pCmd, int pnum) bPlayers = cmd->clPlayers; net_assert(bLevel < NUM_LEVELS); net_assert(bPlayers != 0 && bPlayers < MAX_PLRS); + net_assert(cmd->clType < NUM_DTYPES); // reset level delta (entities + automap) // - multi static_assert((int)DCMD_INVALID == 0, "On_CREATELVL initializes the items with zero, assuming the invalid command to be zero."); @@ -2744,10 +2753,12 @@ static unsigned On_CREATELVL(TCmd* pCmd, int pnum) glSeedTbl[bLevel] = cmd->clSeed; gsDeltaData.ddLevelPlrs[bLevel] = bPlayers; static_assert(MAXCHARLEVEL + HELL_LEVEL_BONUS < CF_LEVEL, "On_CREATELVL might initialize a level which is too high for item-drops."); - gDynLevels[bLevel - NUM_FIXLVLS]._dnLevel = plr._pLevel; + gDynLevels[bLevel - NUM_FIXLVLS]._dnLevel = cmd->clLevel; + gDynLevels[bLevel - NUM_FIXLVLS]._dnType = cmd->clType; StartNewLvl(pnum, DVL_DWM_DYNLVL, bLevel); + } return sizeof(*cmd); } @@ -3066,6 +3077,21 @@ static unsigned On_USEPLRITEM(TCmd* pCmd, int pnum) return sizeof(*cmd); } +static unsigned On_USEPLRMAP(TCmd* pCmd, int pnum) +{ + TCmdBParam2* cmd = (TCmdBParam2*)pCmd; + BYTE cii = cmd->bParam1; + BYTE mIdx = cmd->bParam2; + + net_assert(cii < NUM_INVELEM); + net_assert(mIdx < MAXCAMPAIGNSIZE); + + if (plr._pmode != PM_DEATH) + SyncUseMapItem(pnum, cii, mIdx); + + return sizeof(*cmd); +} + static unsigned On_PLRINFO(TCmd* pCmd, int pnum) { TMsgLarge* cmd = (TMsgLarge*)pCmd; @@ -4471,6 +4497,8 @@ unsigned ParseCmd(int pnum, TCmd* pCmd) return On_DELPLRITEM(pCmd, pnum); case CMD_USEPLRITEM: return On_USEPLRITEM(pCmd, pnum); + case CMD_USEPLRMAP: + return On_USEPLRMAP(pCmd, pnum); case CMD_PUTITEM: return On_PUTITEM(pCmd, pnum); case CMD_SPAWNITEM: diff --git a/Source/msg.h b/Source/msg.h index 8bd79d1c96d..bbabdaf85ee 100644 --- a/Source/msg.h +++ b/Source/msg.h @@ -104,7 +104,7 @@ void NetSendCmdNewLvl(BYTE fom, BYTE bLevel); /** Initiate level creation and change. * @param seed: the seed of the level */ -void NetSendCmdCreateLvl(DWORD seed); +void NetSendCmdCreateLvl(DWORD seed, BYTE lvl, BYTE type); void NetSendCmdString(unsigned int pmask); unsigned ParseMsg(int pnum, TCmd* pCmd); unsigned ParseCmd(int pnum, TCmd* pCmd); diff --git a/Source/scrollrt.cpp b/Source/scrollrt.cpp index 73f5fa4ad4b..30907c59a41 100644 --- a/Source/scrollrt.cpp +++ b/Source/scrollrt.cpp @@ -1513,6 +1513,9 @@ static void DrawView() if (gbSkillListFlag) { DrawSkillList(); } + if (gbCampaignMapFlag) { + DrawCampaignMap(); + } if (gbShowTooltip || (SDL_GetModState() & KMOD_ALT)) { DrawInfoStr(); } diff --git a/Source/stores.cpp b/Source/stores.cpp index cd6fd66f4c7..bd32e520587 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -2376,7 +2376,7 @@ static void S_ErrandEnter() { switch (stextsel) { case STORE_ERRAND_YES: - NetSendCmdCreateLvl(GetRndSeed()); + NetSendCmdCreateLvl(GetRndSeed(), myplr._pLevel, DTYPE_TOWN); stextflag = STORE_NONE; break; case STORE_ERRAND_NO: diff --git a/defs.h b/defs.h index f101c73ac07..14f4f726d3c 100644 --- a/defs.h +++ b/defs.h @@ -123,6 +123,9 @@ static_assert(DMAXY % 2 == 0, "DRLG_L4 constructs the dungeon by mirroring a qua #define BASESTAFFCHARGES 40 #endif +#define MAXCAMPAIGNLVL 60 +#define MAXCAMPAIGNSIZE 16 + // number of inventory grid cells #define NUM_INV_GRID_ELEM 40 diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 4bfdd6f119c..c8ede6b5760 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -67,7 +67,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - better rewards on higher difficulties - HP/Exp/Loot from monsters are depending on the number of players - limited offers in stores/wirt -- added errands (custom levels) +- added errands, campaigns (custom levels) ### System - Lockstep networking - Adaptive netupdate diff --git a/enums.h b/enums.h index 36bbf965e0b..565611789e6 100644 --- a/enums.h +++ b/enums.h @@ -63,10 +63,11 @@ typedef enum item_indexes { IDI_BOOK4 = 0x61, IDI_CLUB = 0x7A, IDI_DROPSHSTAFF= 0x86, + IDI_CAMPAIGNMAP= 0x93, #ifdef HELLFIRE - NUM_IDI = 0x9A, + NUM_IDI = 0x9B, #else - NUM_IDI = 0x93, + NUM_IDI = 0x94, #endif IDI_PHOLDER = 0xFFFE, IDI_NONE = 0xFFFF @@ -241,6 +242,7 @@ typedef enum item_misc_id { IMISC_OILCLEAN, IMISC_OILLAST = IMISC_OILCLEAN, //IMISC_MAPOFDOOM, + IMISC_MAP, IMISC_RUNE, IMISC_NOTE, IMISC_INVALID = -1, @@ -500,6 +502,7 @@ typedef enum item_cursor_graphic { ICURS_EAR_WARRIOR = 20, ICURS_EAR_ROGUE = 21, ICURS_BLOOD_STONE = 25, + ICURS_CAMPAIGN_MAP = 26, ICURS_OIL_OF_DEXTERITY = 29, ICURS_OIL_OF_STRENGTH = 30, ICURS_OIL_OF_CLEANSING = 31, @@ -3128,8 +3131,11 @@ typedef enum dungeon_type { DTYPE_CATACOMBS, DTYPE_CAVES, DTYPE_HELL, +#ifdef HELLFIRE DTYPE_CRYPT, DTYPE_NEST, +#endif + NUM_DTYPES } dungeon_type; typedef enum dungeon_gen_type { @@ -3146,8 +3152,13 @@ typedef enum dungeon_type_mask { DTM_CATACOMBS = 1 << DTYPE_CATACOMBS, DTM_CAVES = 1 << DTYPE_CAVES, DTM_HELL = 1 << DTYPE_HELL, +#ifdef HELLFIRE DTM_CRYPT = 1 << DTYPE_CRYPT, DTM_NEST = 1 << DTYPE_NEST, +#else + DTM_CRYPT = 0, + DTM_NEST = 0, +#endif DTM_ANY = DTM_CATHEDRAL | DTM_CATACOMBS | DTM_CAVES | DTM_HELL | DTM_CRYPT | DTM_NEST, DTM_NONE = 0, } dungeon_type_mask; @@ -3881,6 +3892,7 @@ typedef enum _cmd_id { CMD_CUTPLRITEM, CMD_DELPLRITEM, CMD_USEPLRITEM, + CMD_USEPLRMAP, CMD_PUTITEM, CMD_SPAWNITEM, CMD_GETITEM, diff --git a/structs.h b/structs.h index 1ab8cb4a051..5a2cc3645df 100644 --- a/structs.h +++ b/structs.h @@ -97,6 +97,13 @@ typedef struct CelImageBuf { BYTE imageData[32000]; // size does not matter, the struct is allocated dynamically } CelImageBuf; +typedef struct CampaignMapEntry { + BYTE ceDunType; + BYTE ceIndex; + BYTE ceLevel; + BOOLEAN ceAvailable; +} CampaignMapEntry; + ////////////////////////////////////////////////// // items ////////////////////////////////////////////////// @@ -1136,6 +1143,7 @@ typedef struct PkPlayerStruct { #pragma pack(push, 1) typedef struct LSaveGameDynLvlStruct { BYTE vdLevel; + BYTE vdType; } LSaveGameDynLvlStruct; typedef struct LSaveGameHeaderStruct { @@ -1632,6 +1640,8 @@ typedef struct TCmdCreateLvl { BYTE bCmd; BYTE clPlayers; LE_UINT32 clSeed; + BYTE clLevel; + BYTE clType; } TCmdCreateLvl; typedef struct TCmdItemOp { @@ -2002,6 +2012,7 @@ typedef struct DDLevel { typedef struct DDDynLevel { LE_UINT32 dlSeed; // the seed of the dynamic level BYTE dlLevel; // the difficulty level of the dynamic level + BYTE dlType; // dungeon_type (random in case of DTYPE_TOWN) } DDDynLevel; typedef struct LocalLevel { @@ -2180,6 +2191,7 @@ typedef struct DynLevelStruct { // uint32_t _dnSeed; -- stored in glSeedTbl // BYTE _dnPlayers; -- stored in gsDeltaData.ddLevelPlrs BYTE _dnLevel; + BYTE _dnType; } DynLevelStruct; typedef struct QuestStruct { diff --git a/tools/patcher/DiabloUI/checker.cpp b/tools/patcher/DiabloUI/checker.cpp index 838c69469da..867aa1fb7b5 100644 --- a/tools/patcher/DiabloUI/checker.cpp +++ b/tools/patcher/DiabloUI/checker.cpp @@ -23,11 +23,11 @@ typedef struct FileMetaInfo { } FileMetaInfo; #ifdef HELLFIRE -#define MPQDEVXP_HASH "251688ff12da6d42ea2ebf31d83d3f3c" -#define MPQONE_HASH "81befc2f5f061df0ac3d9de1ecbaff7f" +#define MPQDEVXP_HASH "4dc99a3508ec4e46ea617a987381389e" +#define MPQONE_HASH "6fd287f43ed950ff25a4218787314b40" #else -#define MPQDEVXP_HASH "7814c8a9402f2130c7e1894ff3d2044a" -#define MPQONE_HASH "7c201ea260497b2ca98ae77975754125" +#define MPQDEVXP_HASH "4c0681b79a0af6d3d6907f985b9a3bc5" +#define MPQONE_HASH "88815f47b3bec695f20c763687516208" #endif #if USE_MPQONE #define MPQONE_OPTIONAL false @@ -39,7 +39,7 @@ static const FileMetaInfo filemetadata[] = { #if ASSET_MPL != 1 { "DEVILHD.MPQ", "", "", false }, #endif - { "DEVILX.MPQ", MPQDEVXP_HASH, "b336be80b3968d4bf8495a2983d4d9f9", false }, + { "DEVILX.MPQ", MPQDEVXP_HASH, "646be569d22f1d542851008ea6c9e22f", false }, #ifdef HELLFIRE { "HF_OPT2.MPQ", "", "", true }, { "HF_OPT1.MPQ", "", "", true }, From 080b859679a6a37326913af9c1965059f055284f Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 29 Jul 2024 08:02:22 +0200 Subject: [PATCH 362/596] adjust the healing speed of scavengers based on the monster level when HELLFIRE is not set --- Source/monster.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 87fd2ec32c7..4f301a9978a 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3594,7 +3594,7 @@ void MAI_Scav(int mnum) MonConsumeCorpse(mon); } #else - mon->_mhitpoints += 1 << 6; + mon->_mhitpoints += mon->_mLevel << (6 - 2); if (mon->_mhitpoints > maxhp) mon->_mhitpoints = maxhp; if (mon->_mhitpoints >= (maxhp >> 1) + (maxhp >> 2)) From 891352d1fa165a2f2487e4d973160d08a6d16e36 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 29 Jul 2024 16:00:50 +0200 Subject: [PATCH 363/596] reduce the number of recursive calls in stores --- Source/stores.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index bd32e520587..a7229119da5 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -827,20 +827,26 @@ static void S_StartWRecharge() static void S_StartNoMoney() { - StartStore(stextshold); + // StartStore(stextshold); + // ClearSText(STORE_LIST_FIRST, STORE_LINES); gbHasScroll = false; gbWidePanel = true; gbRenderGold = false; - ClearSText(STORE_LIST_FIRST, STORE_LINES); AddSText(0, 14, true, "You do not have enough gold", COL_WHITE, true); + + AddSLine(3); + AddSLine(21); } static void S_StartNoRoom() { - StartStore(stextshold); + // StartStore(stextshold); + // ClearSText(STORE_LIST_FIRST, STORE_LINES); gbHasScroll = false; - ClearSText(STORE_LIST_FIRST, STORE_LINES); AddSText(0, 14, true, "You do not have enough room in inventory", COL_WHITE, true); + + AddSLine(3); + AddSLine(21); } static void S_StartWait() @@ -852,11 +858,13 @@ static void S_StartWait() static void S_StartConfirm() { - StartStore(stextshold); + // StartStore(stextshold); + // ClearSText(STORE_LIST_FIRST, STORE_LINES); gbHasScroll = false; - ClearSText(STORE_LIST_FIRST, STORE_LINES); PrintStoreItem(&storeitem, 8, false); AddSTextVal(8, storeitem._iIvalue); + AddSLine(3); + AddSLine(21); switch (stextshold) { case STORE_PBUY: From 3ace16be62e7cee1bf6ac3c8799ad96f0a0c5097 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 29 Jul 2024 16:19:20 +0200 Subject: [PATCH 364/596] unify the handling of stores (wirt + cain) - use AddStoreFrame to show the item + go to the menu before leaving (wirt) - use AddStoreFrame to show the id-page (cain) --- Source/stores.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index a7229119da5..cab1a21f4cd 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -926,15 +926,12 @@ static void S_StartBBoy() gbWidePanel = true; gbRenderGold = true; gbHasScroll = false; - AddSText(10, 1, false, "I have this item for sale:", COL_GOLD, false); - AddSLine(3); - AddSLine(21); StorePrepareItemBuy(&boyitem); PrintStoreItem(&boyitem, STORE_PEGBOY_BUY, true); AddSTextVal(STORE_PEGBOY_BUY, boyitem._iIvalue); - AddSText(0, 22, true, "Leave", COL_WHITE, true); - OffsetSTextY(22, 6); + + AddStoreFrame("I have this item for sale:"); } static void S_StartHealer() @@ -1073,11 +1070,9 @@ static void S_StartIdShow() //gbRenderGold = true; gbHasScroll = false; - AddSLine(3); - AddSText(0, 7, true, "This item is:", COL_WHITE, false); PrintStoreItem(&storeitem, 11, false); - AddSText(0, 18, true, "Done", COL_WHITE, true); - AddSLine(21); + + AddStoreFrame("This item is:"); } static void S_StartTalk() @@ -1334,7 +1329,6 @@ void STextESC() case STORE_SMITH: case STORE_WITCH: case STORE_PEGBOY: - case STORE_PBUY: case STORE_HEALER: case STORE_STORY: case STORE_TAVERN: @@ -1383,6 +1377,10 @@ void STextESC() StartStore(STORE_STORY); stextsel = STORE_STORY_IDENTIFY; break; + case STORE_PBUY: + StartStore(STORE_PEGBOY); + stextsel = STORE_PEGBOY_QUERY; + break; case STORE_IDSHOW: StartStore(STORE_SIDENTIFY); break; @@ -2096,8 +2094,10 @@ static void S_BBuyEnter() stextlhold = STORE_PEGBOY_BUY; StoreStartBuy(&boyitem, boyitem._iIvalue); } else { - assert(stextsel == 22); - stextflag = STORE_NONE; + assert(stextsel == STORE_BACK); + // stextflag = STORE_NONE; + StartStore(STORE_PEGBOY); + stextsel = STORE_PEGBOY_QUERY; } } From db8bf9d85aaef4b929784d89e12f0d088df4e01d Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 29 Jul 2024 16:42:42 +0200 Subject: [PATCH 365/596] fix the handling of the sale of the wirt-item --- Source/stores.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index cab1a21f4cd..87382ba9097 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -923,6 +923,12 @@ static void S_StartBoy() static void S_StartBBoy() { + if (boyitem._itype == ITYPE_NONE) { + stextflag = STORE_PEGBOY; + stextlhold = STORE_PEGBOY_EXIT2; + S_StartBoy(); + return; + } gbWidePanel = true; gbRenderGold = true; gbHasScroll = false; @@ -1174,6 +1180,7 @@ void StartStore(int s) ClearSText(0, STORE_LINES); ReleaseStoreBtn(); + stextflag = s; switch (s) { case STORE_SMITH: S_StartSmith(); @@ -1265,7 +1272,6 @@ void StartStore(int s) } stextsel = i == STORE_LINES ? -1 : i; - stextflag = s; } void DrawStore() From ef8774002cbdd91585e1f6a317d4b6cc2970dac7 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 30 Jul 2024 08:12:16 +0200 Subject: [PATCH 366/596] deduplicate logic in stores using STextESC --- Source/stores.cpp | 92 +++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 48 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index 87382ba9097..b53b1f047eb 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -1579,8 +1579,9 @@ static void S_SBuyEnter() int idx; if (stextsel == STORE_BACK) { - StartStore(STORE_SMITH); - stextsel = STORE_SMITH_BUY; + STextESC(); + // StartStore(STORE_SMITH); + // stextsel = STORE_SMITH_BUY; } else { stextlhold = stextsel; stextvhold = stextsidx; @@ -1618,8 +1619,9 @@ static void S_SPBuyEnter() int i, idx, xx; if (stextsel == STORE_BACK) { - StartStore(STORE_SMITH); - stextsel = STORE_SMITH_SPBUY; + STextESC(); + // StartStore(STORE_SMITH); + // stextsel = STORE_SMITH_SPBUY; } else { stextshold = STORE_SPBUY; stextlhold = stextsel; @@ -1868,8 +1870,9 @@ static void S_SSell() static void S_SSellEnter() { if (stextsel == STORE_BACK) { - StartStore(STORE_SMITH); - stextsel = STORE_SMITH_SELL; + STextESC(); + // StartStore(STORE_SMITH); + // stextsel = STORE_SMITH_SELL; } else { S_SSell(); } @@ -1899,8 +1902,9 @@ static void S_SRepairEnter() int idx; if (stextsel == STORE_BACK) { - StartStore(STORE_SMITH); - stextsel = STORE_SMITH_REPAIR; + STextESC(); + // StartStore(STORE_SMITH); + // stextsel = STORE_SMITH_REPAIR; } else { stextshold = STORE_SREPAIR; stextlhold = stextsel; @@ -1968,8 +1972,9 @@ static void S_WBuyEnter() int idx; if (stextsel == STORE_BACK) { - StartStore(STORE_WITCH); - stextsel = STORE_WITCH_BUY; + STextESC(); + // StartStore(STORE_WITCH); + // stextsel = STORE_WITCH_BUY; } else { stextlhold = stextsel; stextvhold = stextsidx; @@ -1983,8 +1988,9 @@ static void S_WBuyEnter() static void S_WSellEnter() { if (stextsel == STORE_BACK) { - StartStore(STORE_WITCH); - stextsel = STORE_WITCH_SELL; + STextESC(); + // StartStore(STORE_WITCH); + // stextsel = STORE_WITCH_SELL; } else { S_SSell(); } @@ -2013,8 +2019,9 @@ static void S_WRechargeEnter() int idx; if (stextsel == STORE_BACK) { - StartStore(STORE_WITCH); - stextsel = STORE_WITCH_RECHARGE; + STextESC(); + // StartStore(STORE_WITCH); + // stextsel = STORE_WITCH_RECHARGE; } else { stextshold = STORE_WRECHARGE; stextlhold = stextsel; @@ -2094,16 +2101,15 @@ static void HealerBuyItem() static void S_BBuyEnter() { - if (stextsel == STORE_PEGBOY_BUY) { + if (stextsel == STORE_BACK) { + STextESC(); + // StartStore(STORE_PEGBOY); + // stextsel = STORE_PEGBOY_QUERY; + } else { stextshold = STORE_PBUY; stextvhold = stextsidx; stextlhold = STORE_PEGBOY_BUY; StoreStartBuy(&boyitem, boyitem._iIvalue); - } else { - assert(stextsel == STORE_BACK); - // stextflag = STORE_NONE; - StartStore(STORE_PEGBOY); - stextsel = STORE_PEGBOY_QUERY; } } @@ -2164,23 +2170,7 @@ static void S_ConfirmEnter() S_StartWait(); return; } - - StartStore(lastshold); - // deliberate redirect -> done - //if (stextshold != lastshold) { - // return; - //} - // store page is empty -> done - //if (stextsel == STORE_BACK) { - // return; - //} - - stextsel = stextlhold; - stextsidx = std::min(stextvhold, stextsmax); - - while (stextsel != -1 && !stextlines[stextsel]._ssel) { - stextsel--; - } + STextESC(); } static void S_HealerEnter() @@ -2215,8 +2205,9 @@ static void S_HBuyEnter() int idx; if (stextsel == STORE_BACK) { - StartStore(STORE_HEALER); - stextsel = STORE_HEALER_BUY; + STextESC(); + // StartStore(STORE_HEALER); + // stextsel = STORE_HEALER_BUY; } else { stextlhold = stextsel; stextvhold = stextsidx; @@ -2252,8 +2243,9 @@ static void S_SIDEnter() int idx; if (stextsel == STORE_BACK) { - StartStore(STORE_STORY); - stextsel = STORE_STORY_IDENTIFY; + STextESC(); + // StartStore(STORE_STORY); + // stextsel = STORE_STORY_IDENTIFY; } else { stextshold = STORE_SIDENTIFY; stextlhold = stextsel; @@ -2272,8 +2264,9 @@ static void S_TalkEnter() int i, tq, sn, la; if (stextsel == 22) { - StartStore(stextshold); - stextsel = stextlhold; + STextESC(); + // StartStore(stextshold); + // stextsel = stextlhold; return; } @@ -2394,7 +2387,8 @@ static void S_ErrandEnter() stextflag = STORE_NONE; break; case STORE_ERRAND_NO: - StartStore(STORE_PRIEST); + STextESC(); + // StartStore(STORE_PRIEST); break; default: ASSUME_UNREACHABLE @@ -2435,9 +2429,10 @@ void STextEnter() break; case STORE_NOMONEY: case STORE_NOROOM: - StartStore(stextshold); - stextsel = stextlhold; - stextsidx = stextvhold; + STextESC(); + // StartStore(stextshold); + // stextsel = stextlhold; + // stextsidx = stextvhold; break; case STORE_CONFIRM: S_ConfirmEnter(); @@ -2464,7 +2459,8 @@ void STextEnter() S_TalkEnter(); break; case STORE_IDSHOW: - StartStore(STORE_SIDENTIFY); + STextESC(); + // StartStore(STORE_SIDENTIFY); break; case STORE_DRUNK: S_DrunkEnter(); From f9d4f7af127d05d7313e743dcb795a0b23d56633 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 30 Jul 2024 08:27:11 +0200 Subject: [PATCH 367/596] simplify StoreSellItem --- Source/stores.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index b53b1f047eb..cb49f173de8 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -1841,13 +1841,6 @@ static void StoreSellItem() } cost = storehold[idx]._iIvalue; SendStoreCmd1(i, STORE_SSELL, cost); - - storenumh--; - while (idx < storenumh) { - copy_pod(storehold[idx], storehold[idx + 1]); - storehidx[idx] = storehidx[idx + 1]; - idx++; - } } static void S_SSell() From 2e745d0556f02bac16621bfea4c9e806c35c7f69 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 30 Jul 2024 08:29:19 +0200 Subject: [PATCH 368/596] add separators (lines) to the store-textbox in DrawStore --- Source/stores.cpp | 58 +++++++++++++++++++++++++---------------------- structs.h | 2 +- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index cb49f173de8..a26c228cc7e 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -152,7 +152,7 @@ static void ClearSText(int s, int e) stextlines[i]._sstr[0] = '\0'; stextlines[i]._sjust = false; stextlines[i]._sclr = COL_WHITE; - stextlines[i]._sline = false; + // stextlines[i]._sline = false; stextlines[i]._ssel = false; stextlines[i]._sval = -1; } @@ -268,10 +268,10 @@ void InitSTextHelp() ClearSText(0, STORE_LINES); // necessary to reset the _syoff values } -static void AddSLine(int y) +/*static void AddSLine(int y) { stextlines[y]._sline = true; -} +}*/ static void AddSTextVal(int y, int val) { @@ -293,7 +293,7 @@ static void AddSText(int x, int y, bool j, const char* str, BYTE clr, bool sel) SStrCopy(ss->_sstr, str, sizeof(ss->_sstr)); ss->_sjust = j; ss->_sclr = clr; - ss->_sline = false; + // ss->_sline = false; ss->_ssel = sel; } @@ -373,8 +373,8 @@ static void PrintStoreItem(const ItemStruct* is, int l, bool sel) static void AddStoreFrame(const char* title) { AddSText(10, 1, false, title, COL_GOLD, false); - AddSLine(3); - AddSLine(21); + // AddSLine(3); + // AddSLine(21); AddSText(0, STORE_BACK, true, "Back", COL_WHITE, true); OffsetSTextY(STORE_BACK, 6); } @@ -393,7 +393,7 @@ static void S_StartSmith() AddSText(0, STORE_SMITH_SELL, true, "Sell items", COL_WHITE, true); AddSText(0, STORE_SMITH_REPAIR, true, "Repair items", COL_WHITE, true); AddSText(0, STORE_SMITH_EXIT, true, "Leave the shop", COL_WHITE, true); - AddSLine(5); + // AddSLine(5); } static void StorePrepareItemBuy(ItemStruct* is) @@ -681,7 +681,7 @@ static void S_StartWitch() AddSText(0, STORE_WITCH_SELL, true, "Sell items", COL_WHITE, true); AddSText(0, STORE_WITCH_RECHARGE, true, "Recharge staves", COL_WHITE, true); AddSText(0, STORE_WITCH_EXIT, true, "Leave the shack", COL_WHITE, true); - AddSLine(5); + // AddSLine(5); } static void S_ScrollWBuy() @@ -834,8 +834,8 @@ static void S_StartNoMoney() gbRenderGold = false; AddSText(0, 14, true, "You do not have enough gold", COL_WHITE, true); - AddSLine(3); - AddSLine(21); + // AddSLine(3); + // AddSLine(21); } static void S_StartNoRoom() @@ -845,8 +845,8 @@ static void S_StartNoRoom() gbHasScroll = false; AddSText(0, 14, true, "You do not have enough room in inventory", COL_WHITE, true); - AddSLine(3); - AddSLine(21); + // AddSLine(3); + // AddSLine(21); } static void S_StartWait() @@ -863,8 +863,8 @@ static void S_StartConfirm() gbHasScroll = false; PrintStoreItem(&storeitem, 8, false); AddSTextVal(8, storeitem._iIvalue); - AddSLine(3); - AddSLine(21); + // AddSLine(3); + // AddSLine(21); switch (stextshold) { case STORE_PBUY: @@ -904,7 +904,7 @@ static void S_StartBoy() gbRenderGold = false; gbHasScroll = false; AddSText(0, 2, true, "Wirt the Peg-legged boy", COL_GOLD, false); - AddSLine(5); + // AddSLine(5); if (boyitem._itype != ITYPE_NONE) { AddSText(0, STORE_PEGBOY_GOSSIP1, true, "Talk to Wirt", COL_BLUE, true); AddSText(0, 12, true, "I have something for sale,", COL_GOLD, false); @@ -952,7 +952,7 @@ static void S_StartHealer() AddSText(0, STORE_HEALER_HEAL, true, "Receive healing", COL_WHITE, true); AddSText(0, STORE_HEALER_BUY, true, "Buy items", COL_WHITE, true); AddSText(0, STORE_HEALER_EXIT, true, "Leave Healer's home", COL_WHITE, true); - AddSLine(5); + // AddSLine(5); } static void S_ScrollHBuy() @@ -1008,7 +1008,7 @@ static void S_StartStory() AddSText(0, STORE_STORY_GOSSIP, true, "Talk to Cain", COL_BLUE, true); AddSText(0, STORE_STORY_IDENTIFY, true, "Identify an item", COL_WHITE, true); AddSText(0, STORE_STORY_EXIT, true, "Say goodbye", COL_WHITE, true); - AddSLine(5); + // AddSLine(5); } static bool IdItemOk(const ItemStruct* is) @@ -1090,7 +1090,7 @@ static void S_StartTalk() gbHasScroll = false; snprintf(tempstr, sizeof(tempstr), "Talk to %s", talkname[talker]); AddSText(0, 2, true, tempstr, COL_GOLD, false); - AddSLine(5); + // AddSLine(5); sn = 0; for (i = 0; i < NUM_QUESTS; i++) { if (quests[i]._qactive == QUEST_ACTIVE && Qtalklist[talker][i] != TEXT_NONE && quests[i]._qlog) @@ -1125,7 +1125,7 @@ static void S_StartTavern() AddSText(0, 9, true, "Would you like to:", COL_GOLD, false); AddSText(0, STORE_TAVERN_GOSSIP, true, "Talk to Ogden", COL_BLUE, true); AddSText(0, STORE_TAVERN_EXIT, true, "Leave the tavern", COL_WHITE, true); - AddSLine(5); + // AddSLine(5); } static void S_StartBarMaid() @@ -1137,7 +1137,7 @@ static void S_StartBarMaid() AddSText(0, 9, true, "Would you like to:", COL_GOLD, false); AddSText(0, STORE_BARMAID_GOSSIP, true, "Talk to Gillian", COL_BLUE, true); AddSText(0, STORE_BARMAID_EXIT, true, "Say goodbye", COL_WHITE, true); - AddSLine(5); + // AddSLine(5); } static void S_StartDrunk() @@ -1149,7 +1149,7 @@ static void S_StartDrunk() AddSText(0, 9, true, "Would you like to:", COL_GOLD, false); AddSText(0, STORE_DRUNK_GOSSIP, true, "Talk to Farnham", COL_BLUE, true); AddSText(0, STORE_DRUNK_EXIT, true, "Say Goodbye", COL_WHITE, true); - AddSLine(5); + // AddSLine(5); } static void S_StartPriest() @@ -1161,7 +1161,7 @@ static void S_StartPriest() AddSText(0, 9, true, "Would you like to:", COL_GOLD, false); AddSText(0, STORE_PRIEST_ERRAND, true, "Run errand", COL_BLUE, true); AddSText(0, STORE_PRIEST_EXIT, true, "Say Goodbye", COL_WHITE, true); - AddSLine(5); + // AddSLine(5); } static void S_StartErrand() @@ -1171,7 +1171,7 @@ static void S_StartErrand() AddSText(0, 14, true, "Go on an errand?", COL_WHITE, false); AddSText(0, STORE_ERRAND_YES, true, "Yes", COL_WHITE, true); AddSText(0, STORE_ERRAND_NO, true, "No", COL_WHITE, true); - AddSLine(5); + // AddSLine(5); } void StartStore(int s) @@ -1279,10 +1279,14 @@ void DrawStore() STextStruct* sts; int i; - if (gbWidePanel) + if (gbWidePanel) { DrawTextBox(); - else + DrawTextBoxSLine(LTPANEL_X, LTPANEL_Y, 3 * 12 + 14, true); + DrawTextBoxSLine(LTPANEL_X, LTPANEL_Y, 21 * 12 + 14, true); + } else { DrawSTextBox(STORE_PNL_X, LTPANEL_Y); + DrawTextBoxSLine(STORE_PNL_X, LTPANEL_Y, 5 * 12 + 14, false); + } if (gbHasScroll) { switch (stextflag) { @@ -1313,8 +1317,8 @@ void DrawStore() for (i = 0; i < STORE_LINES; i++) { sts = &stextlines[i]; - if (sts->_sline) - DrawTextBoxSLine(gbWidePanel ? LTPANEL_X : STORE_PNL_X, LTPANEL_Y, i * 12 + 14, gbWidePanel); + // if (sts->_sline) + // DrawTextBoxSLine(gbWidePanel ? LTPANEL_X : STORE_PNL_X, LTPANEL_Y, i * 12 + 14, gbWidePanel); if (sts->_sstr[0] != '\0') PrintSString(sts->_sx, i, sts->_sjust, sts->_sstr, sts->_sclr, sts->_sval); } diff --git a/structs.h b/structs.h index 5a2cc3645df..4f602afaedb 100644 --- a/structs.h +++ b/structs.h @@ -2624,7 +2624,7 @@ typedef struct STextStruct { char _sstr[112]; bool _sjust; BYTE _sclr; - bool _sline; + // bool _sline; bool _ssel; int _sval; } STextStruct; From 8c102c7cf61ffc2c84e114382122296f71e4e433 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 31 Jul 2024 15:10:50 +0200 Subject: [PATCH 369/596] do not print the value on the right side in stores if it is zero --- Source/stores.cpp | 4 ++-- Source/stores.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index a26c228cc7e..bd499e32213 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -154,7 +154,7 @@ static void ClearSText(int s, int e) stextlines[i]._sclr = COL_WHITE; // stextlines[i]._sline = false; stextlines[i]._ssel = false; - stextlines[i]._sval = -1; + stextlines[i]._sval = 0; } } @@ -219,7 +219,7 @@ void PrintSString(int x, int y, bool cjustflag, const char* str, BYTE col, int v } px = stextsel == y ? sx : INT_MAX; sx = PrintLimitedString(sx, sy, str, limit, col); - if (val >= 0) { + if (val > 0) { assert(!cjustflag && gbWidePanel); snprintf(valstr, sizeof(valstr), "%d", val); sx = LTPANEL_X + LTPANEL_WIDTH - (2 * SMALL_SCROLL_WIDTH + x + GetSmallStringWidth(valstr)); diff --git a/Source/stores.h b/Source/stores.h index 2cf599d61a1..e965f6939e0 100644 --- a/Source/stores.h +++ b/Source/stores.h @@ -36,7 +36,7 @@ extern ItemStruct healitem[HEALER_ITEMS]; void InitStoresOnce(); void InitLvlStores(); -void PrintSString(int x, int y, bool cjustflag, const char* str, BYTE col, int val = -1); +void PrintSString(int x, int y, bool cjustflag, const char* str, BYTE col, int val = 0); void InitSTextHelp(); void StartStore(int s); void DrawStore(); From 6aeddd54c558c3e21340611cad03918828489d10 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 31 Jul 2024 15:11:35 +0200 Subject: [PATCH 370/596] use memset in ClearSText (stores) --- Source/stores.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index bd499e32213..25a3bb37c53 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -144,9 +144,11 @@ static const char* const talkname[] = { static void ClearSText(int s, int e) { - int i; + // int i; - for (i = s; i < e; i++) { + static_assert(COL_WHITE == 0, "ClearSText skips color initialization by expecting COL_WHITE to be zero."); + memset(&stextlines[s], 0, (size_t)&stextlines[e] - (size_t)&stextlines[s]); + /*for (i = s; i < e; i++) { stextlines[i]._sx = 0; stextlines[i]._syoff = 0; stextlines[i]._sstr[0] = '\0'; @@ -155,7 +157,7 @@ static void ClearSText(int s, int e) // stextlines[i]._sline = false; stextlines[i]._ssel = false; stextlines[i]._sval = 0; - } + }*/ } static unsigned StoresLimitedItemLvl() From 8cc66999f8a47e0595a2a4666f4c8365dd711575 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 31 Jul 2024 15:18:05 +0200 Subject: [PATCH 371/596] show the player's gold when the "You do not have enough gold" message is shown in stores --- Source/stores.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index 25a3bb37c53..efd1c06b1fd 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -833,7 +833,7 @@ static void S_StartNoMoney() // ClearSText(STORE_LIST_FIRST, STORE_LINES); gbHasScroll = false; gbWidePanel = true; - gbRenderGold = false; + gbRenderGold = true; AddSText(0, 14, true, "You do not have enough gold", COL_WHITE, true); // AddSLine(3); From 991090603d64cd48c68938b777bf2c27c764cc25 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 31 Jul 2024 15:19:28 +0200 Subject: [PATCH 372/596] always show the player's gold on the wide-panel of the stores --- Source/stores.cpp | 49 ++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index efd1c06b1fd..cda14a3beb8 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -96,7 +96,7 @@ BYTE stextflag; /** Is the current dialog full size */ static bool gbWidePanel; /** Should 'Your gold ' text be displayed on the top-right corner */ -static bool gbRenderGold; +// static bool gbRenderGold; /** Does the current panel have a scrollbar */ static bool gbHasScroll; /** The index of the first visible item in the store. */ @@ -175,7 +175,7 @@ void InitStoresOnce() ClearSText(0, STORE_LINES); stextflag = STORE_NONE; gbWidePanel = false; - gbRenderGold = false; + // gbRenderGold = false; gbHasScroll = false; numpremium = 0; premiumlevel = StoresLimitedItemLvl(); @@ -384,7 +384,7 @@ static void AddStoreFrame(const char* title) static void S_StartSmith() { gbWidePanel = false; - gbRenderGold = false; + // gbRenderGold = false; gbHasScroll = false; AddSText(0, 1, true, "Welcome to the", COL_GOLD, false); AddSText(0, 3, true, "Blacksmith's shop", COL_GOLD, false); @@ -441,7 +441,7 @@ static void S_StartSBuy() storenumh++; gbWidePanel = true; - gbRenderGold = true; + // gbRenderGold = true; if (storenumh == 0) { //StartStore(STORE_SMITH); //stextshold = STORE_SMITH; @@ -503,7 +503,7 @@ static void S_StartSPBuy() storenumh++; gbWidePanel = true; - gbRenderGold = true; + // gbRenderGold = true; if (storenumh == 0) { //StartStore(STORE_SMITH); //stextshold = STORE_SMITH; @@ -596,7 +596,7 @@ static void S_StartSSell() AddStoreSell(pi, i); gbWidePanel = true; - gbRenderGold = true; + // gbRenderGold = true; if (storenumh == 0) { gbHasScroll = false; msg = "You have nothing I want."; @@ -656,7 +656,7 @@ static void S_StartSRepair() AddStoreHoldRepair(pi, i); gbWidePanel = true; - gbRenderGold = true; + // gbRenderGold = true; if (storenumh == 0) { gbHasScroll = false; msg = "You have nothing to repair."; @@ -673,7 +673,7 @@ static void S_StartSRepair() static void S_StartWitch() { gbWidePanel = false; - gbRenderGold = false; + // gbRenderGold = false; gbHasScroll = false; AddSText(0, 2, true, "Witch's shack", COL_GOLD, false); @@ -721,7 +721,7 @@ static void S_StartWBuy() storenumh++; gbWidePanel = true; - gbRenderGold = true; + // gbRenderGold = true; gbHasScroll = true; stextsidx = 0; S_ScrollWBuy(); @@ -760,7 +760,7 @@ static void S_StartWSell() AddStoreSell(pi, i); gbWidePanel = true; - gbRenderGold = true; + // gbRenderGold = true; if (storenumh == 0) { gbHasScroll = false; msg = "You have nothing I want."; @@ -813,7 +813,7 @@ static void S_StartWRecharge() AddStoreHoldRecharge(pi, i); gbWidePanel = true; - gbRenderGold = true; + // gbRenderGold = true; if (storenumh == 0) { gbHasScroll = false; msg = "You have nothing to recharge."; @@ -833,7 +833,7 @@ static void S_StartNoMoney() // ClearSText(STORE_LIST_FIRST, STORE_LINES); gbHasScroll = false; gbWidePanel = true; - gbRenderGold = true; + // gbRenderGold = true; AddSText(0, 14, true, "You do not have enough gold", COL_WHITE, true); // AddSLine(3); @@ -903,7 +903,7 @@ static void S_StartConfirm() static void S_StartBoy() { gbWidePanel = false; - gbRenderGold = false; + // gbRenderGold = false; gbHasScroll = false; AddSText(0, 2, true, "Wirt the Peg-legged boy", COL_GOLD, false); // AddSLine(5); @@ -932,7 +932,7 @@ static void S_StartBBoy() return; } gbWidePanel = true; - gbRenderGold = true; + // gbRenderGold = true; gbHasScroll = false; StorePrepareItemBuy(&boyitem); @@ -945,7 +945,7 @@ static void S_StartBBoy() static void S_StartHealer() { gbWidePanel = false; - gbRenderGold = false; + // gbRenderGold = false; gbHasScroll = false; AddSText(0, 1, true, "Welcome to the", COL_GOLD, false); AddSText(0, 3, true, "Healer's home", COL_GOLD, false); @@ -992,7 +992,7 @@ static void S_StartHBuy() storenumh++; gbWidePanel = true; - gbRenderGold = true; + // gbRenderGold = true; gbHasScroll = true; stextsidx = 0; S_ScrollHBuy(); @@ -1003,7 +1003,7 @@ static void S_StartHBuy() static void S_StartStory() { gbWidePanel = false; - gbRenderGold = false; + // gbRenderGold = false; gbHasScroll = false; AddSText(0, 2, true, "The Town Elder", COL_GOLD, false); AddSText(0, 9, true, "Would you like to:", COL_GOLD, false); @@ -1054,7 +1054,7 @@ static void S_StartSIdentify() AddStoreHoldId(pi, i); gbWidePanel = true; - gbRenderGold = true; + // gbRenderGold = true; if (storenumh == 0) { gbHasScroll = false; msg = "You have nothing to identify."; @@ -1088,7 +1088,7 @@ static void S_StartTalk() int i, sn, la; gbWidePanel = false; - gbRenderGold = false; + // gbRenderGold = false; gbHasScroll = false; snprintf(tempstr, sizeof(tempstr), "Talk to %s", talkname[talker]); AddSText(0, 2, true, tempstr, COL_GOLD, false); @@ -1120,7 +1120,7 @@ static void S_StartTalk() static void S_StartTavern() { gbWidePanel = false; - gbRenderGold = false; + // gbRenderGold = false; gbHasScroll = false; AddSText(0, 1, true, "Welcome to the", COL_GOLD, false); AddSText(0, 3, true, "Rising Sun", COL_GOLD, false); @@ -1133,7 +1133,7 @@ static void S_StartTavern() static void S_StartBarMaid() { gbWidePanel = false; - gbRenderGold = false; + // gbRenderGold = false; gbHasScroll = false; AddSText(0, 2, true, "Gillian", COL_GOLD, false); AddSText(0, 9, true, "Would you like to:", COL_GOLD, false); @@ -1145,7 +1145,7 @@ static void S_StartBarMaid() static void S_StartDrunk() { gbWidePanel = false; - gbRenderGold = false; + // gbRenderGold = false; gbHasScroll = false; AddSText(0, 2, true, "Farnham the Drunk", COL_GOLD, false); AddSText(0, 9, true, "Would you like to:", COL_GOLD, false); @@ -1157,7 +1157,7 @@ static void S_StartDrunk() static void S_StartPriest() { gbWidePanel = false; - gbRenderGold = false; + // gbRenderGold = false; gbHasScroll = false; AddSText(0, 2, true, "Tremain the Priest", COL_GOLD, false); AddSText(0, 9, true, "Would you like to:", COL_GOLD, false); @@ -1325,7 +1325,8 @@ void DrawStore() PrintSString(sts->_sx, i, sts->_sjust, sts->_sstr, sts->_sclr, sts->_sval); } - if (gbRenderGold) { + // if (gbRenderGold) { + if (gbWidePanel) { snprintf(tempstr, sizeof(tempstr), "Your gold: %d", myplr._pGold); // assert(gbWidePanel); PrintSString(LTPANEL_WIDTH - 178, 1, false, tempstr, COL_GOLD); From 2d49bbe92122cf2823d33dfa0888a03d6b72e590 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 1 Aug 2024 09:09:10 +0200 Subject: [PATCH 373/596] add separator line to the small textbox in DrawSTextBox --- Source/control.cpp | 6 +++++- Source/items.cpp | 3 --- Source/stores.cpp | 1 - 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/control.cpp b/Source/control.cpp index 2af2f301e84..cf177b8f792 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -1891,15 +1891,19 @@ void DrawTextBox() } /** - * @brief Draw a small text box with transparent background. + * @brief Draw a small text box with transparent background and a separator. * used as background to items and in stores. * @param x: the starting x-coordinate of the text box * @param y: the starting y-coordinate of the text box */ void DrawSTextBox(int x, int y) { + // draw the box CelDraw(x, y + TPANEL_HEIGHT, pSTextBoxCels, 1); + // draw the background DrawRectTrans(x + TPANEL_BORDER, y + TPANEL_BORDER, STPANEL_WIDTH - 2 * TPANEL_BORDER, TPANEL_HEIGHT - 2 * TPANEL_BORDER, PAL_BLACK); + // add separator + DrawTextBoxSLine(x, y, 5 * 12 + 14, false); } /** diff --git a/Source/items.cpp b/Source/items.cpp index a5bc064c5b3..190f3492ed8 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -3268,9 +3268,6 @@ void DrawInvItemDetails() // draw the background DrawSTextBox(x, y); - // add separator - DrawTextBoxSLine(x, y, 74, false); - x += TPANEL_BORDER; y += 44; diff --git a/Source/stores.cpp b/Source/stores.cpp index cda14a3beb8..646283036b4 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -1287,7 +1287,6 @@ void DrawStore() DrawTextBoxSLine(LTPANEL_X, LTPANEL_Y, 21 * 12 + 14, true); } else { DrawSTextBox(STORE_PNL_X, LTPANEL_Y); - DrawTextBoxSLine(STORE_PNL_X, LTPANEL_Y, 5 * 12 + 14, false); } if (gbHasScroll) { From 0358151de8f171fac9b13c1bb6d52c3a8abadea6 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 1 Aug 2024 09:20:22 +0200 Subject: [PATCH 374/596] reduce the header-size of the help-textbox --- Source/help.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/help.cpp b/Source/help.cpp index e85e94a715d..8a1ae5888aa 100644 --- a/Source/help.cpp +++ b/Source/help.cpp @@ -93,11 +93,11 @@ void DrawHelp() DrawTextBox(); - PrintSString(0, 2, true, HELP_TITLE, COL_GOLD); - DrawTextBoxSLine(LTPANEL_X, LTPANEL_Y, 5 * 12 + 14, true); + PrintSString(0, 1, true, HELP_TITLE, COL_GOLD); + DrawTextBoxSLine(LTPANEL_X, LTPANEL_Y, 3 * 12 + 14, true); - for (i = 7; i < 22; i++) { - s = gbHelpLines[helpFirstLine + i - 7]; + for (i = 5; i < 22; i++) { + s = gbHelpLines[helpFirstLine + i - 5]; if (*s == '$') { s++; col = COL_RED; @@ -136,7 +136,7 @@ void HelpScrollUp() void HelpScrollDown() { - if (helpFirstLine < (HELP_LINES_SIZE - (22 - 7))) + if (helpFirstLine < (HELP_LINES_SIZE - (22 - 5))) helpFirstLine++; } From 9eea846bc65a0fdc0d632004e395d9cb8a86abf5 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 1 Aug 2024 13:25:59 +0200 Subject: [PATCH 375/596] add separator line to the normal textbox in DrawTextBox --- Source/control.cpp | 9 ++++++++- Source/control.h | 2 +- Source/help.cpp | 3 +-- Source/minitext.cpp | 2 +- Source/stores.cpp | 4 +--- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Source/control.cpp b/Source/control.cpp index cf177b8f792..a62c3eabad5 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -1879,15 +1879,22 @@ void ReleaseChrBtn() * @brief Draw a large text box with transparent background. * used as background to quest dialog window and in stores. */ -void DrawTextBox() +void DrawTextBox(unsigned separators) { int x, y; x = LTPANEL_X; y = LTPANEL_Y; + // draw the box CelDraw(x, y + TPANEL_HEIGHT, pTextBoxCels, 1); + // draw the background DrawRectTrans(x + TPANEL_BORDER, y + TPANEL_BORDER, LTPANEL_WIDTH - 2 * TPANEL_BORDER, TPANEL_HEIGHT - 2 * TPANEL_BORDER, PAL_BLACK); + // add separator + if (separators & 1) + DrawTextBoxSLine(x, y, 3 * 12 + 14, true); + if (separators & 2) + DrawTextBoxSLine(x, y, 21 * 12 + 14, true); } /** diff --git a/Source/control.h b/Source/control.h index dc8ae37d440..13bb1b41361 100644 --- a/Source/control.h +++ b/Source/control.h @@ -67,7 +67,7 @@ void DrawLevelUpIcon(); void DrawInfoStr(); void CheckChrBtnClick(); void ReleaseChrBtn(); -void DrawTextBox(); +void DrawTextBox(unsigned separators); void DrawSTextBox(int x, int y); void DrawTextBoxSLine(int x, int y, int dy, bool widePanel); void DrawDurIcon(); diff --git a/Source/help.cpp b/Source/help.cpp index 8a1ae5888aa..953d6a01d3c 100644 --- a/Source/help.cpp +++ b/Source/help.cpp @@ -91,10 +91,9 @@ void DrawHelp() BYTE col; const char* s; - DrawTextBox(); + DrawTextBox(1); PrintSString(0, 1, true, HELP_TITLE, COL_GOLD); - DrawTextBoxSLine(LTPANEL_X, LTPANEL_Y, 3 * 12 + 14, true); for (i = 5; i < 22; i++) { s = gbHelpLines[helpFirstLine + i - 5]; diff --git a/Source/minitext.cpp b/Source/minitext.cpp index 3d7cf506390..31d4d17e9ff 100644 --- a/Source/minitext.cpp +++ b/Source/minitext.cpp @@ -57,7 +57,7 @@ void DrawQText() Uint32 currTime; BYTE *pStart, *pEnd; - DrawTextBox(); + DrawTextBox(0); /// ASSERT: assert(gpBuffer != NULL); // TODO: create a function in engine to draw with a given height? (similar to DrawFlask2 in control.cpp) diff --git a/Source/stores.cpp b/Source/stores.cpp index 646283036b4..a5c2d5b12a4 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -1282,9 +1282,7 @@ void DrawStore() int i; if (gbWidePanel) { - DrawTextBox(); - DrawTextBoxSLine(LTPANEL_X, LTPANEL_Y, 3 * 12 + 14, true); - DrawTextBoxSLine(LTPANEL_X, LTPANEL_Y, 21 * 12 + 14, true); + DrawTextBox(3); } else { DrawSTextBox(STORE_PNL_X, LTPANEL_Y); } From 96ff48ad2c71094f50459889a92f41b0a55d6295 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 2 Aug 2024 08:08:20 +0200 Subject: [PATCH 376/596] sync IsSFXPlaying calls in monster.cpp --- Source/monster.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 4f301a9978a..a9d8615347f 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -2082,7 +2082,7 @@ static void SpawnLoot(int mnum, bool sendmsg) CreateTypeItem(mx, my, CFDQ_GOOD, ITYPE_MACE, IMISC_NONE, sendmsg ? ICM_SEND_FLIP : ICM_DUMMY); return; case UMT_LAZARUS: - //if (IsSFXPlaying(USFX_LAZ1)) + //if (IsSFXPlaying(USFX_LAZ1)) // alltext[TEXT_VILE13].sfxnr StopStreamSFX(); break; case UMT_SKELKING: @@ -2108,7 +2108,7 @@ static void SpawnLoot(int mnum, bool sendmsg) break; case UMT_DEFILER: // assert(QuestStatus(Q_DEFILER)); - //if (IsSFXPlaying(USFX_DEFILER8)) + //if (IsSFXPlaying(USFX_DEFILER8)) // alltext[TEXT_DEFILER5].sfxnr StopStreamSFX(); // quests[Q_DEFILER]._qlog = FALSE; quests[Q_DEFILER]._qactive = QUEST_DONE; @@ -2117,6 +2117,7 @@ static void SpawnLoot(int mnum, bool sendmsg) SpawnQuestItemAt(IDI_FANG, mx, my, sendmsg ? ICM_SEND_FLIP : ICM_DUMMY); return; case UMT_NAKRUL: + // alltext[TEXT_NAKRUL4].sfxnr alltext[TEXT_NAKRUL5].sfxnr alltext[TEXT_NAKRUL?].sfxnr //if (IsSFXPlaying(USFX_NAKRUL4) || IsSFXPlaying(USFX_NAKRUL5) || IsSFXPlaying(USFX_NAKRUL6)) StopStreamSFX(); quests[Q_NAKRUL]._qactive = QUEST_DONE; @@ -4139,7 +4140,7 @@ void MAI_Garbud(int mnum) if (mon->_mgoalvar1) { // TALK_SPEAKING if (dFlags[mon->_mx][mon->_my] & BFLAG_ALERT) { // MON_TIMER //if (quests[Q_GARBUD]._qvar1 == QV_GARBUD_ATTACK && mon->_mVar8++ >= gnTicksRate * 6) { - if (quests[Q_GARBUD]._qvar1 == QV_GARBUD_ATTACK && (IsMultiGame || !IsSFXPlaying(USFX_GARBUD4))) { + if (quests[Q_GARBUD]._qvar1 == QV_GARBUD_ATTACK && (IsMultiGame || !IsSFXPlaying(USFX_GARBUD4))) { // alltext[TEXT_GARBUD4].sfxnr mon->_mgoal = MGOAL_NORMAL; // mon->_msquelch = SQUELCH_MAX; } @@ -4183,7 +4184,7 @@ void MAI_Zhar(int mnum) } } //if (quests[Q_ZHAR]._qvar1 == QV_ZHAR_ATTACK && mon->_mVar8++ >= gnTicksRate * 4/*!IsSFXPlaying(USFX_ZHAR2)*/) { - if (quests[Q_ZHAR]._qvar1 == QV_ZHAR_ATTACK && (IsMultiGame || !IsSFXPlaying(USFX_ZHAR2))) { + if (quests[Q_ZHAR]._qvar1 == QV_ZHAR_ATTACK && (IsMultiGame || !IsSFXPlaying(USFX_ZHAR2))) { // alltext[TEXT_ZHAR2].sfxnr // mon->_msquelch = SQUELCH_MAX; mon->_mgoal = MGOAL_NORMAL; } @@ -4225,7 +4226,7 @@ void MAI_SnotSpil(int mnum) case QV_BANNER_TALK2: //if (mon->_mVar8++ < gnTicksRate * 6) // MON_TIMER // return; // wait till the sfx is running, but don't rely on IsSFXPlaying - if (IsMultiGame || IsSFXPlaying(alltext[TEXT_BANNER12].sfxnr)) + if (IsMultiGame || IsSFXPlaying(USFX_SNOT3)) // alltext[TEXT_BANNER12].sfxnr return; //if (mon->_mListener == mypnum || !plx(mon->_mListener)._pActive || plx(mon->_mListener)._pDunLevel != currLvl._dLevelIdx) { NetSendCmd(CMD_OPENSPIL); @@ -4283,7 +4284,7 @@ void MAI_Lazarus(int mnum) PlayInGameMovie("gendata\\fprst3.smk"); mon->_mmode = MM_TALK; // mon->_mListener = mypnum; - } else { // TALK_SPEAKING + } else { // TALK_SPEAKING alltext[TEXT_VILE13].sfxnr if (IsSFXPlaying(USFX_LAZ1) && myplr._px == LAZ_CIRCLE_X && myplr._py == LAZ_CIRCLE_Y) return; DRLG_ChangeMap(7, 20, 11, 22/*, false*/); @@ -4327,7 +4328,7 @@ void MAI_Lachdanan(int mnum) if (quests[Q_VEIL]._qactive == QUEST_DONE) { // MON_TIMER //if (mon->_mVar8++ >= gnTicksRate * 32) { - if (IsMultiGame || !IsSFXPlaying(USFX_LACH3)) { + if (IsMultiGame || !IsSFXPlaying(USFX_LACH3)) { // alltext[TEXT_VEIL11].sfxnr // mon->_mgoal = MGOAL_NORMAL; MonKill(mnum, -1); } @@ -4369,7 +4370,7 @@ void MAI_Warlord(int mnum) //if (mon->_mVar8++ < gnTicksRate * 8) // MON_TIMER // return; // wait till the sfx is running, but don't rely on IsSFXPlaying // assert(!IsMultiGame); - if (/*!IsMultiGame &&*/ IsSFXPlaying(alltext[TEXT_WARLRD9].sfxnr)) + if (/*!IsMultiGame &&*/ IsSFXPlaying(USFX_WARLRD1)) // alltext[TEXT_WARLRD9].sfxnr return; quests[Q_WARLORD]._qvar1 = QV_WARLORD_ATTACK; //if (mon->_mListener == mypnum || !plx(mon->_mListener)._pActive || plx(mon->_mListener)._pDunLevel != currLvl._dLevelIdx) { From b57931d8fcf7f155f0ac9782bf68a48329b4a932 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Thu, 1 Aug 2024 08:59:05 +0100 Subject: [PATCH 377/596] Remove unused sounds --- Packaging/resources/listfiles.txt | 4 ++-- Source/effects.cpp | 4 ++-- Source/textdat.cpp | 4 ++-- enums.h | 4 ++-- tools/patcher/DiabloUI/checker.cpp | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Packaging/resources/listfiles.txt b/Packaging/resources/listfiles.txt index 5b497dcaa52..93fc7fa1eeb 100644 --- a/Packaging/resources/listfiles.txt +++ b/Packaging/resources/listfiles.txt @@ -3442,13 +3442,13 @@ Sfx\Monsters\Lach01.wav Sfx\Monsters\Lach02.wav Sfx\Monsters\Lach03.wav Sfx\Monsters\Laz01.wav -Sfx\Monsters\Laz02.wav +_Sfx\Monsters\Laz02.wav Sfx\Monsters\Sking01.wav Sfx\Monsters\Snot01.wav Sfx\Monsters\Snot02.wav Sfx\Monsters\Snot03.wav Sfx\Monsters\Warlrd01.wav -Sfx\Monsters\Wlock01.wav +_Sfx\Monsters\Wlock01.wav Sfx\Monsters\Zhar01.wav Sfx\Monsters\Zhar02.wav Sfx\Narrator\Nar01.wav diff --git a/Source/effects.cpp b/Source/effects.cpp index 0759880abef..d6c2da2bce0 100644 --- a/Source/effects.cpp +++ b/Source/effects.cpp @@ -991,13 +991,13 @@ static SFXStruct sgSFX[NUM_SFXS] = { /*USFX_LACH2*/ { sfx_STREAM, "Sfx\\Monsters\\Lach02.wav", { 0, NULL } }, /*USFX_LACH3*/ { sfx_STREAM, "Sfx\\Monsters\\Lach03.wav", { 0, NULL } }, /*USFX_LAZ1*/ { sfx_STREAM, "Sfx\\Monsters\\Laz01.wav", { 0, NULL } }, -/*USFX_LAZ2*/ { sfx_STREAM, "Sfx\\Monsters\\Laz02.wav", { 0, NULL } }, +/*USFX_LAZ2*/// { sfx_STREAM, "Sfx\\Monsters\\Laz02.wav", { 0, NULL } }, /*USFX_SKING1*/ { sfx_STREAM, "Sfx\\Monsters\\Sking01.wav", { 0, NULL } }, /*USFX_SNOT1*/ { sfx_STREAM, "Sfx\\Monsters\\Snot01.wav", { 0, NULL } }, /*USFX_SNOT2*/ { sfx_STREAM, "Sfx\\Monsters\\Snot02.wav", { 0, NULL } }, /*USFX_SNOT3*/ { sfx_STREAM, "Sfx\\Monsters\\Snot03.wav", { 0, NULL } }, /*USFX_WARLRD1*/ { sfx_STREAM, "Sfx\\Monsters\\Warlrd01.wav", { 0, NULL } }, -/*USFX_WLOCK1*/ { sfx_STREAM, "Sfx\\Monsters\\Wlock01.wav", { 0, NULL } }, +/*USFX_WLOCK1*///{ sfx_STREAM, "Sfx\\Monsters\\Wlock01.wav", { 0, NULL } }, /*USFX_ZHAR1*/ { sfx_STREAM, "Sfx\\Monsters\\Zhar01.wav", { 0, NULL } }, /*USFX_ZHAR2*/ { sfx_STREAM, "Sfx\\Monsters\\Zhar02.wav", { 0, NULL } }, /*USFX_DIABLOD*/ { sfx_STREAM, "Sfx\\Monsters\\DiabloD.wav", { 0, NULL } }, diff --git a/Source/textdat.cpp b/Source/textdat.cpp index c808183326e..9e3e07b0165 100644 --- a/Source/textdat.cpp +++ b/Source/textdat.cpp @@ -1,4 +1,4 @@ -/** +/** * @file textdat.cpp * * Implementation of all dialog texts. @@ -94,7 +94,7 @@ const TextData alltext[NUM_TEXTS] = { TRUE, FALSE, TxS(0), TSFX_PEGBOY3 }, { NULL/*"Abandon your foolish quest. All that awaits you is the wrath of my Master! You are too late to save the child. Now you will join him in Hell!"*/, FALSE, FALSE, 0, USFX_LAZ1 }, -// { NULL/*" "*/, FALSE, FALSE, 0, USFX_LAZ1 }, +// { NULL/*" "*/, FALSE, FALSE, 0, USFX_LAZ2 }, { "Hmm, I don't know what I can really tell you about this that will be of any help. The water that fills our wells comes from an underground spring. I have heard of a tunnel that leads to a great lake - perhaps they are one and the same. Unfortunately, I do not know what would cause our water supply to be tainted.", /* TEXT_POISON1 */ TRUE, FALSE, TxS(0), TSFX_STORY4 }, { "I have always tried to keep a large supply of foodstuffs and drink in our storage cellar, but with the entire town having no source of fresh water, even our stores will soon run dry.\n\nPlease, do what you can or I don't know what we will do.", diff --git a/enums.h b/enums.h index 565611789e6..7b7a78be223 100644 --- a/enums.h +++ b/enums.h @@ -1797,13 +1797,13 @@ typedef enum _sfx_id { USFX_LACH2, USFX_LACH3, USFX_LAZ1, - USFX_LAZ2, + //USFX_LAZ2, USFX_SKING1, USFX_SNOT1, USFX_SNOT2, USFX_SNOT3, USFX_WARLRD1, - USFX_WLOCK1, + //USFX_WLOCK1, USFX_ZHAR1, USFX_ZHAR2, USFX_DIABLOD, diff --git a/tools/patcher/DiabloUI/checker.cpp b/tools/patcher/DiabloUI/checker.cpp index 867aa1fb7b5..471e3a4a75f 100644 --- a/tools/patcher/DiabloUI/checker.cpp +++ b/tools/patcher/DiabloUI/checker.cpp @@ -24,10 +24,10 @@ typedef struct FileMetaInfo { #ifdef HELLFIRE #define MPQDEVXP_HASH "4dc99a3508ec4e46ea617a987381389e" -#define MPQONE_HASH "6fd287f43ed950ff25a4218787314b40" +#define MPQONE_HASH "c060c972cc1a6c5dd1f64adb2d432417" #else #define MPQDEVXP_HASH "4c0681b79a0af6d3d6907f985b9a3bc5" -#define MPQONE_HASH "88815f47b3bec695f20c763687516208" +#define MPQONE_HASH "ba32299daae9a8e96c7c8d923fd4272b" #endif #if USE_MPQONE #define MPQONE_OPTIONAL false From 395b126f5c146fd6b54e40ce89bc1a106aa10911 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 3 Aug 2024 10:35:57 +0200 Subject: [PATCH 378/596] bugfix for vanilla - prevent the player from following a hidden monster --- Source/player.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/player.cpp b/Source/player.cpp index 641c1cb917e..b92e4346b6d 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -2530,7 +2530,8 @@ static bool CheckNewPath(int pnum) } if (plr._pDestAction == ACTION_ATTACKMON) { - MakePlrPath(pnum, monsters[plr._pDestParam1]._mfutx, monsters[plr._pDestParam1]._mfuty, false); + if (!(monsters[plr._pDestParam1]._mFlags & MFLAG_HIDDEN)) + MakePlrPath(pnum, monsters[plr._pDestParam1]._mfutx, monsters[plr._pDestParam1]._mfuty, false); } else if (plr._pDestAction == ACTION_ATTACKPLR) { MakePlrPath(pnum, plx(plr._pDestParam1)._pfutx, plx(plr._pDestParam1)._pfuty, false); } From bd5b2f695e28c82cb11bec10d064228d7c2976f5 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 4 Aug 2024 08:43:14 +0200 Subject: [PATCH 379/596] bugfix for hellfire (death vs Satyr Lord) - patch the death animation of "Satyr Lord" monsters --- tools/patcher/DiabloUI/checker.cpp | 4 +- tools/patcher/DiabloUI/patcher.cpp | 237 +++++++++++++++++++++++++++++ 2 files changed, 239 insertions(+), 2 deletions(-) diff --git a/tools/patcher/DiabloUI/checker.cpp b/tools/patcher/DiabloUI/checker.cpp index 471e3a4a75f..edc91bffc79 100644 --- a/tools/patcher/DiabloUI/checker.cpp +++ b/tools/patcher/DiabloUI/checker.cpp @@ -23,8 +23,8 @@ typedef struct FileMetaInfo { } FileMetaInfo; #ifdef HELLFIRE -#define MPQDEVXP_HASH "4dc99a3508ec4e46ea617a987381389e" -#define MPQONE_HASH "c060c972cc1a6c5dd1f64adb2d432417" +#define MPQDEVXP_HASH "17ff1a81ac05e54d552c7f75cc8d94d8" +#define MPQONE_HASH "03d484146ad5191e81074ca9af6c6c2a" #else #define MPQDEVXP_HASH "4c0681b79a0af6d3d6907f985b9a3bc5" #define MPQONE_HASH "ba32299daae9a8e96c7c8d923fd4272b" diff --git a/tools/patcher/DiabloUI/patcher.cpp b/tools/patcher/DiabloUI/patcher.cpp index c672e8bae1e..2f9b6a6d567 100644 --- a/tools/patcher/DiabloUI/patcher.cpp +++ b/tools/patcher/DiabloUI/patcher.cpp @@ -117,6 +117,7 @@ typedef enum filenames { #if ASSET_MPL == 1 FILE_L5LIGHT_CEL, FILE_MON_FALLGW, + FILE_MON_GOATLD, #endif FILE_OBJCURS_CEL, #endif @@ -222,6 +223,7 @@ static const char* const filesToPatch[NUM_FILENAMES] = { #if ASSET_MPL == 1 /*FILE_L5LIGHT_CEL*/ "Objects\\L5Light.CEL", /*FILE_MON_FALLGW*/ "Monsters\\BigFall\\Fallgw.CL2", +/*FILE_MON_GOATLD*/ "Monsters\\GoatLord\\GoatLd.CL2", #endif /*FILE_OBJCURS_CEL*/ "Data\\Inv\\Objcurs.CEL", #endif @@ -2177,6 +2179,237 @@ BYTE* createWarriorAnim(BYTE* cl2Buf, size_t *dwLen, const BYTE* atkBuf, const B return resCl2Buf; } +BYTE* fixGoatLdAnim(BYTE* cl2Buf, size_t *dwLen) +{ + constexpr BYTE TRANS_COLOR = 1; + constexpr int numGroups = NUM_DIRS; + constexpr int frameCount = 16; + constexpr bool groupped = true; + constexpr int height = 128; + constexpr int width = 160; + + BYTE* resCl2Buf = DiabloAllocPtr(2 * *dwLen); + memset(resCl2Buf, 0, 2 * *dwLen); + + int headerSize = 0; + for (int i = 0; i < numGroups; i++) { + int ni = frameCount; + headerSize += 4 + 4 * (ni + 1); + } + if (groupped) { + headerSize += sizeof(DWORD) * numGroups; + } + + DWORD* hdr = (DWORD*)resCl2Buf; + if (groupped) { + // add optional {CL2 GROUP HEADER} + int offset = numGroups * 4; + for (int i = 0; i < numGroups; i++, hdr++) { + hdr[0] = offset; + int ni = frameCount; + offset += 4 + 4 * (ni + 1); + } + } + + BYTE* pBuf = &resCl2Buf[headerSize]; + bool needsPatch = false; + for (int ii = 0; ii < numGroups; ii++) { + int ni = frameCount; + hdr[0] = SwapLE32(ni); + hdr[1] = SwapLE32((size_t)pBuf - (size_t)hdr); + + const BYTE* frameBuf = CelGetFrameStart(cl2Buf, ii); + + for (int n = 1; n <= ni; n++) { + memset(&gpBuffer[0], TRANS_COLOR, BUFFER_WIDTH * height); + // draw the frame to the buffer + Cl2Draw(0, height - 1, frameBuf, n, width); + // test if the animation is already patched + if (ii == 1 && n == 9) { + needsPatch = gpBuffer[71 + BUFFER_WIDTH * 127] != TRANS_COLOR; // assume it is already done + } + + if (needsPatch) { + switch (ii) { + case DIR_SW: { + switch (n) { + case 9: + case 10: + case 11: + case 12: { + // shift the monster with (0;16) up + for (int y = 16; y < height; y++) { + for (int x = 0; x < width; x++) { + unsigned addr = x + BUFFER_WIDTH * y; + unsigned addr2 = x + BUFFER_WIDTH * (y - 16); + BYTE color = gpBuffer[addr]; + if (color == TRANS_COLOR) + continue; + gpBuffer[addr2] = color; + gpBuffer[addr] = TRANS_COLOR; + } + } + // copy pixels from the followup frames + if (n != 9) { + Cl2Draw(width, height - 1, frameBuf, n + 4, width); + for (int y = 4 - 1; y >= 0; y--) { + for (int x = 0; x < width; x++) { + unsigned addr = width + x + BUFFER_WIDTH * y; + unsigned addr2 = x + BUFFER_WIDTH * (y + 112); + BYTE color = gpBuffer[addr]; + if (color == TRANS_COLOR) + continue; + gpBuffer[addr2] = color; + } + } + } + } break; + case 14: + case 15: + case 16: { + // clear pixels from the first rows + for (int y = 4 - 1; y >= 0; y--) { + for (int x = 0; x < width; x++) { + gpBuffer[x + BUFFER_WIDTH * y] = TRANS_COLOR; + } + } + } break; + } + } break; + case DIR_W: { + switch (n) { + case 9: + case 10: + case 11: + case 12: { + // shift the monster with (0;16) up + for (int y = 16; y < height; y++) { + for (int x = 0; x < width; x++) { + unsigned addr = x + BUFFER_WIDTH * y; + unsigned addr2 = x + BUFFER_WIDTH * (y - 16); + BYTE color = gpBuffer[addr]; + if (color == TRANS_COLOR) + continue; + gpBuffer[addr2] = color; + gpBuffer[addr] = TRANS_COLOR; + } + } + // copy pixels from the followup frames + { + Cl2Draw(width, height - 1, frameBuf, n + 4, width); + for (int y = 16 - 1; y >= 0; y--) { + for (int x = 0; x < width; x++) { + unsigned addr = width + x + BUFFER_WIDTH * y; + unsigned addr2 = x + BUFFER_WIDTH * (y + 112); + BYTE color = gpBuffer[addr]; + if (color == TRANS_COLOR) + continue; + gpBuffer[addr2] = color; + } + } + } + } break; + case 13: + case 14: + case 15: + case 16: { + // shift the monster with (1;9) up/right + for (int y = 16; y < height; y++) { + for (int x = width - 1 - 1; x >= 0; x--) { + unsigned addr = x + BUFFER_WIDTH * y; + unsigned addr2 = x + 1 + BUFFER_WIDTH * (y - 9); + BYTE color = gpBuffer[addr]; + if (color == TRANS_COLOR) + continue; + gpBuffer[addr2] = color; + gpBuffer[addr] = TRANS_COLOR; + } + } + // clear pixels from the first rows + for (int y = 16 - 1; y >= 0; y--) { + for (int x = 0; x < width; x++) { + gpBuffer[x + BUFFER_WIDTH * y] = TRANS_COLOR; + } + } + } break; + } + } break; + case DIR_NW: { + switch (n) { + case 12: + case 13: + case 14: + case 15: + case 16: { + // shift the monster with (0;4) down + for (int y = height - 4 - 1; y >= 0; y--) { + for (int x = width - 1; x >= 0; x--) { + unsigned addr = x + BUFFER_WIDTH * y; + unsigned addr2 = x + BUFFER_WIDTH * (y + 4); + BYTE color = gpBuffer[addr]; + if (color == TRANS_COLOR) + continue; + gpBuffer[addr2] = color; + gpBuffer[addr] = TRANS_COLOR; + } + } + } break; + } + } break; + case DIR_E: { + switch (n) { + case 9: + case 10: + case 11: + case 12: { + // clear pixels from the first rows + for (int y = 4 - 1; y >= 0; y--) { + for (int x = 0; x < width; x++) { + gpBuffer[x + BUFFER_WIDTH * y] = TRANS_COLOR; + } + } + } break; + } + } break; + case DIR_SE: { + switch (n) { + case 12: + case 13: + case 14: + case 15: + case 16: { + // shift the monster with (0;16) up + for (int y = 16; y < height; y++) { + for (int x = 0; x < width; x++) { + unsigned addr = x + BUFFER_WIDTH * y; + unsigned addr2 = x + BUFFER_WIDTH * (y - 16); + BYTE color = gpBuffer[addr]; + if (color == TRANS_COLOR) + continue; + gpBuffer[addr2] = color; + gpBuffer[addr] = TRANS_COLOR; + } + } + } break; + } + } break; + } + } + + BYTE* frameSrc = &gpBuffer[0 + (height - 1) * BUFFER_WIDTH]; + + pBuf = EncodeCl2(pBuf, frameSrc, width, height, TRANS_COLOR); + hdr[n + 1] = SwapLE32((size_t)pBuf - (size_t)hdr); + } + hdr += ni + 2; + } + + *dwLen = (size_t)pBuf - (size_t)resCl2Buf; + + mem_free_dbg(cl2Buf); + return resCl2Buf; +} + BYTE* createFallgwAnim(BYTE* cl2Buf, size_t *dwLen, BYTE* stdBuf) { constexpr BYTE TRANS_COLOR = 1; @@ -3966,6 +4199,10 @@ static BYTE* patchFile(int index, size_t *dwLen) buf = createFallgwAnim(buf, dwLen, stdBuf); mem_free_dbg(stdBuf); } break; + case FILE_MON_GOATLD: + { // fix monster gfx file - GoatLd.CL2 + buf = fixGoatLdAnim(buf, dwLen); + } break; #endif // ASSET_MPL case FILE_OBJCURS_CEL: { From 2562655b281642ab82627a4e8911e8bcb32fda54 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 5 Aug 2024 07:50:28 +0200 Subject: [PATCH 380/596] merge branches of path_parent_path --- Source/path.cpp | 48 ++++++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/Source/path.cpp b/Source/path.cpp index 005f3ee60ba..b33e2071d05 100644 --- a/Source/path.cpp +++ b/Source/path.cpp @@ -168,6 +168,7 @@ static inline void PathAppendChild(PATHNODE* parent, PATHNODE* child) static bool path_parent_path(PATHNODE* pPath, int dx, int dy) { BYTE nextWalkCost; + bool frontier; PATHNODE* dxdy; nextWalkCost = pPath->walkCost + PathStepCost(pPath->x, pPath->y, dx, dy); @@ -175,6 +176,11 @@ static bool path_parent_path(PATHNODE* pPath, int dx, int dy) // 3 cases to consider // case 1: (dx,dy) is already on the frontier dxdy = PathFrontNodeAt(dx, dy); + frontier = dxdy != NULL; + if (!frontier) { + // case 2: (dx,dy) was already visited + dxdy = PathVisitedNodeAt(dx, dy); + } if (dxdy != NULL) { PathAppendChild(pPath, dxdy); if (nextWalkCost < dxdy->walkCost /*&& PathWalkable(pPath->x, pPath->y, dx, dy)*/) { @@ -182,36 +188,26 @@ static bool path_parent_path(PATHNODE* pPath, int dx, int dy) dxdy->Parent = pPath; dxdy->walkCost = nextWalkCost; dxdy->totalCost = nextWalkCost + dxdy->remainingCost; - } - } else { - // case 2: (dx,dy) was already visited - dxdy = PathVisitedNodeAt(dx, dy); - if (dxdy != NULL) { - PathAppendChild(pPath, dxdy); - if (nextWalkCost < dxdy->walkCost /*&& PathWalkable(pPath->x, pPath->y, dx, dy)*/) { - // update the node - dxdy->Parent = pPath; - dxdy->walkCost = nextWalkCost; - dxdy->totalCost = nextWalkCost + dxdy->remainingCost; + if (!frontier) { // already explored, so re-update others starting from that node PathUpdateCosts(dxdy); } - } else { - // case 3: (dx,dy) is totally new - if (gnLastNodeIdx == MAXPATHNODES - 1) - return false; - dxdy = &path_nodes[++gnLastNodeIdx]; - memset(dxdy, 0, sizeof(PATHNODE)); - dxdy->Parent = pPath; - PathAppendChild(pPath, dxdy); - dxdy->x = dx; - dxdy->y = dy; - dxdy->remainingCost = PathRemainingCost(dx, dy); - dxdy->walkCost = nextWalkCost; - dxdy->totalCost = nextWalkCost + dxdy->remainingCost; - // add it to the frontier - PathAddNode(dxdy); } + } else { + // case 3: (dx,dy) is totally new + if (gnLastNodeIdx == MAXPATHNODES - 1) + return false; + dxdy = &path_nodes[++gnLastNodeIdx]; + memset(dxdy, 0, sizeof(PATHNODE)); + dxdy->Parent = pPath; + PathAppendChild(pPath, dxdy); + dxdy->x = dx; + dxdy->y = dy; + dxdy->remainingCost = PathRemainingCost(dx, dy); + dxdy->walkCost = nextWalkCost; + dxdy->totalCost = nextWalkCost + dxdy->remainingCost; + // add it to the frontier + PathAddNode(dxdy); } return true; } From 979a8614479411bf157de0fe75f66da693feeb73 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 5 Aug 2024 08:02:50 +0200 Subject: [PATCH 381/596] add debug code to path.cpp --- Source/path.cpp | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/Source/path.cpp b/Source/path.cpp index b33e2071d05..4c84e2f539d 100644 --- a/Source/path.cpp +++ b/Source/path.cpp @@ -7,6 +7,8 @@ DEVILUTION_BEGIN_NAMESPACE +// #define DEBUG_PATH + /** Pre-allocated memory to store nodes used by the path finding algorithm. */ PATHNODE path_nodes[MAXPATHNODES]; /** The index of last used node in path_nodes. */ @@ -21,7 +23,10 @@ static PATHNODE* pathUpdateStack[MAXPATHNODES]; static PATHNODE* pathFrontNodes; /** The target location. */ static int gnTx, gnTy; - +#ifdef DEBUG_PATH +/** The target location. */ +static int gnSx, gnSy; +#endif /** For iterating over the 8 possible movement directions. */ // PDIR_N W E S NW NE SE SW const int8_t pathxdir[8] = { -1, -1, 1, 1, -1, 0, 1, 0 }; @@ -126,6 +131,7 @@ static void PathUpdateCosts(PATHNODE* pPath) newWalkCost = PathOld->walkCost + PathStepCost(PathOld->x, PathOld->y, PathAct->x, PathAct->y); if (newWalkCost < PathAct->walkCost /*&& PathWalkable(PathOld->x, PathOld->y, PathAct->x, PathAct->y)*/) { + // EventPlrMsg("Update walk 0 %d:%d cost%d:%d last%d to cost%d:%d", PathAct->x - gnSx, PathAct->y - gnSy, PathAct->totalCost, PathAct->walkCost, PathAct->lastStepCost, newWalkCost + PathAct->remainingCost, newWalkCost); PathAct->Parent = PathOld; PathAct->walkCost = newWalkCost; PathAct->totalCost = newWalkCost + PathAct->remainingCost; @@ -184,7 +190,8 @@ static bool path_parent_path(PATHNODE* pPath, int dx, int dy) if (dxdy != NULL) { PathAppendChild(pPath, dxdy); if (nextWalkCost < dxdy->walkCost /*&& PathWalkable(pPath->x, pPath->y, dx, dy)*/) { - // we'll explore it later, just update + // update the node + // EventPlrMsg("Update %d path %d:%d cost%d:%d last%d to cost%d:%d last%d", frontier, dxdy->x - gnSx, dxdy->y - gnSy, dxdy->totalCost, dxdy->walkCost, dxdy->lastStepCost, nextWalkCost + dxdy->remainingCost, nextWalkCost, stepCost); dxdy->Parent = pPath; dxdy->walkCost = nextWalkCost; dxdy->totalCost = nextWalkCost + dxdy->remainingCost; @@ -192,11 +199,15 @@ static bool path_parent_path(PATHNODE* pPath, int dx, int dy) // already explored, so re-update others starting from that node PathUpdateCosts(dxdy); } + } else { + // LogErrorF("Ignoring path %d:%d cost%d vs. %d last%d vs. last%d", dxdy->x - gnSx, dxdy->y - gnSy, nextWalkCost, dxdy->walkCost, dxdy->lastStepCost, stepCost); } } else { // case 3: (dx,dy) is totally new - if (gnLastNodeIdx == MAXPATHNODES - 1) + if (gnLastNodeIdx == MAXPATHNODES - 1) { + // EventPlrMsg("Not enough nodes %d:%d", pPath->x - gnSx, pPath->y - gnSy); return false; + } dxdy = &path_nodes[++gnLastNodeIdx]; memset(dxdy, 0, sizeof(PATHNODE)); dxdy->Parent = pPath; @@ -263,7 +274,11 @@ int FindPath(bool (*PosOk)(int, int, int), int PosOkArg, int sx, int sy, int dx, { PATHNODE* currNode; int path_length, i; - +#ifdef DEBUG_PATH + // EventPlrMsg("Find path from %d:%d to %d:%d", sx, sy, dx, dy); + gnSx = sx; + gnSy = sy; +#endif gnTx = dx; gnTy = dy; // create root nodes for the visited/frontier linked lists @@ -279,26 +294,36 @@ int FindPath(bool (*PosOk)(int, int, int), int PosOkArg, int sx, int sy, int dx, pathVisitedNodes = currNode; // A* search until we find (dx,dy) or fail while (TRUE) { + // LogErrorF("Eval path from %d:%d", currNode->x - gnSx, currNode->y - gnSy); // reached the end, success! if (currNode->x == gnTx && currNode->y == gnTy) { path_length = 0; while (currNode->Parent != NULL) { - if (path_length == MAX_PATH_LENGTH) + if (path_length == MAX_PATH_LENGTH) { + // EventPlrMsg("Found path from %d:%d to %d:%d -- too long", sx - gnSx, sy - gnSy, dx, dy - gnSy); return -1; // path does not fit to the destination, abort! + } reversePathDirs[path_length++] = path_directions[3 * (currNode->y - currNode->Parent->y) - currNode->Parent->x + 4 + currNode->x]; currNode = currNode->Parent; } for (i = 0; i < path_length; i++) path[i] = reversePathDirs[path_length - i - 1]; + // EventPlrMsg("Found path from %d:%d to %d:%d: %d", sx - gnSx, sy - gnSy, dx - gnSx, dy - gnSy, path_length); return i; } - if (currNode->totalCost > 4 * (MAX_PATH_LENGTH - 1)) + if (currNode->totalCost > 4 * (MAX_PATH_LENGTH - 1)) { + // EventPlrMsg("No path from %d:%d to %d:%d -- too long", sx - gnSx, sy - gnSy, dx, dy - gnSy); return -1; // path is hopeless - if (!path_get_path(PosOk, PosOkArg, currNode)) + } + if (!path_get_path(PosOk, PosOkArg, currNode)) { + // EventPlrMsg("No path from %d:%d to %d:%d -- too many options", sx - gnSx, sy - gnSy, dx, dy - gnSy); return -1; // ran out of nodes, abort! + } currNode = PathPopNode(); - if (currNode == NULL) + if (currNode == NULL) { + // EventPlrMsg("No path from %d:%d to %d:%d -- not at all", sx - gnSx, sy - gnSy, dx, dy - gnSy); return -1; // frontier is empty, no path! + } } } From b3f247fe19cb66de15b95fa3533ddf78ae58316d Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 5 Aug 2024 08:22:41 +0200 Subject: [PATCH 382/596] bugfix for vanilla (pathfinding) I. - fix the weights of the paths - prefer routes where the last step is the greatest (because usually it is not used. E.g. target is a monster/npc/object/item) --- Source/path.cpp | 59 ++++++++++++++++++++++++++++++++++++------------- structs.h | 1 + 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/Source/path.cpp b/Source/path.cpp index 4c84e2f539d..79c5664a1fd 100644 --- a/Source/path.cpp +++ b/Source/path.cpp @@ -84,15 +84,9 @@ static PATHNODE* PathVisitedNodeAt(int dx, int dy) static void PathAddNode(PATHNODE* pPath) { PATHNODE *next, *current; - BYTE currCost; current = pathFrontNodes; next = pathFrontNodes->NextNode; - currCost = pPath->totalCost; - while (next != NULL && next->totalCost < currCost) { - current = next; - next = next->NextNode; - } pPath->NextNode = next; current->NextNode = pPath; } @@ -117,7 +111,7 @@ static void PathUpdateCosts(PATHNODE* pPath) PATHNODE* PathOld; PATHNODE* PathAct; int updateStackSize; - BYTE i, newWalkCost; + BYTE i, newStepCost, newWalkCost; pathUpdateStack[0] = pPath; updateStackSize = 1; @@ -129,14 +123,20 @@ static void PathUpdateCosts(PATHNODE* pPath) if (PathAct == NULL) break; - newWalkCost = PathOld->walkCost + PathStepCost(PathOld->x, PathOld->y, PathAct->x, PathAct->y); + newStepCost = PathStepCost(PathOld->x, PathOld->y, PathAct->x, PathAct->y); + newWalkCost = PathOld->walkCost + newStepCost; if (newWalkCost < PathAct->walkCost /*&& PathWalkable(PathOld->x, PathOld->y, PathAct->x, PathAct->y)*/) { // EventPlrMsg("Update walk 0 %d:%d cost%d:%d last%d to cost%d:%d", PathAct->x - gnSx, PathAct->y - gnSy, PathAct->totalCost, PathAct->walkCost, PathAct->lastStepCost, newWalkCost + PathAct->remainingCost, newWalkCost); PathAct->Parent = PathOld; PathAct->walkCost = newWalkCost; + PathAct->lastStepCost = newStepCost; PathAct->totalCost = newWalkCost + PathAct->remainingCost; pathUpdateStack[updateStackSize] = PathAct; updateStackSize++; + } else if (newWalkCost == PathAct->walkCost /*&& PathWalkable(PathOld->x, PathOld->y, PathAct->x, PathAct->y)*/ && newStepCost > PathAct->lastStepCost) { + // EventPlrMsg("Update walk 1 %d:%d cost%d:%d last%d to cost%d:%d", PathAct->x - gnSx, PathAct->y - gnSy, PathAct->totalCost, PathAct->walkCost, PathAct->lastStepCost, newWalkCost + PathAct->remainingCost, newWalkCost); + PathAct->Parent = PathOld; + PathAct->lastStepCost = newStepCost; } } } while (updateStackSize != 0); @@ -150,8 +150,12 @@ static int PathRemainingCost(int x, int y) int delta_x = abs(x - gnTx); int delta_y = abs(y - gnTy); - // see PathStepCost for why this is times 2 - return 2 * (delta_x + delta_y); + // see PathStepCost for why this is times 2 and 3 + if (delta_x > delta_y) { + return 2 * (delta_x - delta_y) + 3 * delta_y; + } else { + return 2 * (delta_y - delta_x) + 3 * delta_x; + } } static inline void PathAppendChild(PATHNODE* parent, PATHNODE* child) @@ -174,10 +178,12 @@ static inline void PathAppendChild(PATHNODE* parent, PATHNODE* child) static bool path_parent_path(PATHNODE* pPath, int dx, int dy) { BYTE nextWalkCost; + BYTE stepCost; bool frontier; PATHNODE* dxdy; - nextWalkCost = pPath->walkCost + PathStepCost(pPath->x, pPath->y, dx, dy); + stepCost = PathStepCost(pPath->x, pPath->y, dx, dy); + nextWalkCost = pPath->walkCost + stepCost; // 3 cases to consider // case 1: (dx,dy) is already on the frontier @@ -189,16 +195,21 @@ static bool path_parent_path(PATHNODE* pPath, int dx, int dy) } if (dxdy != NULL) { PathAppendChild(pPath, dxdy); + // update the node if necessary if (nextWalkCost < dxdy->walkCost /*&& PathWalkable(pPath->x, pPath->y, dx, dy)*/) { - // update the node // EventPlrMsg("Update %d path %d:%d cost%d:%d last%d to cost%d:%d last%d", frontier, dxdy->x - gnSx, dxdy->y - gnSy, dxdy->totalCost, dxdy->walkCost, dxdy->lastStepCost, nextWalkCost + dxdy->remainingCost, nextWalkCost, stepCost); dxdy->Parent = pPath; + dxdy->lastStepCost = stepCost; dxdy->walkCost = nextWalkCost; dxdy->totalCost = nextWalkCost + dxdy->remainingCost; if (!frontier) { // already explored, so re-update others starting from that node PathUpdateCosts(dxdy); } + } else if (nextWalkCost == dxdy->walkCost /*&& PathWalkable(pPath->x, pPath->y, dx, dy)*/ && stepCost > dxdy->lastStepCost) { + // EventPlrMsg("Update 2 path %d:%d cost%d:%d last%d to last%d", dxdy->x - gnSx, dxdy->y - gnSy, dxdy->totalCost, dxdy->walkCost, dxdy->lastStepCost, stepCost); + dxdy->Parent = pPath; + dxdy->lastStepCost = stepCost; } else { // LogErrorF("Ignoring path %d:%d cost%d vs. %d last%d vs. last%d", dxdy->x - gnSx, dxdy->y - gnSy, nextWalkCost, dxdy->walkCost, dxdy->lastStepCost, stepCost); } @@ -216,6 +227,7 @@ static bool path_parent_path(PATHNODE* pPath, int dx, int dy) dxdy->y = dy; dxdy->remainingCost = PathRemainingCost(dx, dy); dxdy->walkCost = nextWalkCost; + dxdy->lastStepCost = stepCost; dxdy->totalCost = nextWalkCost + dxdy->remainingCost; // add it to the frontier PathAddNode(dxdy); @@ -253,11 +265,28 @@ static bool path_get_path(bool (*PosOk)(int, int, int), int PosOkArg, PATHNODE* */ static PATHNODE* PathPopNode() { - PATHNODE* result; + PATHNODE* prevNode = pathFrontNodes; + PATHNODE* result = pathFrontNodes->NextNode; - result = pathFrontNodes->NextNode; if (result != NULL) { - pathFrontNodes->NextNode = result->NextNode; + PATHNODE* res = result; + PATHNODE* pNode; + while (true) { + pNode = res; + res = res->NextNode; + if (res == NULL) { + break; + } + + if (res->totalCost < result->totalCost + // || (res->totalCost == result->totalCost && (res->walkCost < result->walkCost || (res->walkCost == result->walkCost && res->lastStepCost > result->lastStepCost)))) { + || (res->totalCost == result->totalCost && result->remainingCost == 0)) { + result = res; + prevNode = pNode; + } + } + + prevNode->NextNode = result->NextNode; result->NextNode = pathVisitedNodes->NextNode; pathVisitedNodes->NextNode = result; } diff --git a/structs.h b/structs.h index 4f602afaedb..629611c144c 100644 --- a/structs.h +++ b/structs.h @@ -2530,6 +2530,7 @@ typedef struct _uigamedata { typedef struct PATHNODE { BYTE totalCost; BYTE remainingCost; + BYTE lastStepCost; BYTE walkCost; int x; int y; From 9876eb439b93d1a36ac48ba1cc40da077bf48794 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 5 Aug 2024 08:35:14 +0200 Subject: [PATCH 383/596] bugfix for vanilla (pathfinding) II. - use integers for path-costs to prevent overflow (after the previous fix this is no longer possible, but there is not much point to use BYTE anyway and the values might be close to the limit which makes the code 'fragile') --- Source/path.cpp | 6 +++--- structs.h | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/path.cpp b/Source/path.cpp index 79c5664a1fd..6daf9c88eed 100644 --- a/Source/path.cpp +++ b/Source/path.cpp @@ -111,7 +111,7 @@ static void PathUpdateCosts(PATHNODE* pPath) PATHNODE* PathOld; PATHNODE* PathAct; int updateStackSize; - BYTE i, newStepCost, newWalkCost; + int i, newStepCost, newWalkCost; pathUpdateStack[0] = pPath; updateStackSize = 1; @@ -177,8 +177,8 @@ static inline void PathAppendChild(PATHNODE* parent, PATHNODE* child) */ static bool path_parent_path(PATHNODE* pPath, int dx, int dy) { - BYTE nextWalkCost; - BYTE stepCost; + int nextWalkCost; + int stepCost; bool frontier; PATHNODE* dxdy; diff --git a/structs.h b/structs.h index 629611c144c..dff58e33a66 100644 --- a/structs.h +++ b/structs.h @@ -2528,16 +2528,16 @@ typedef struct _uigamedata { ////////////////////////////////////////////////// typedef struct PATHNODE { - BYTE totalCost; - BYTE remainingCost; - BYTE lastStepCost; - BYTE walkCost; + int totalCost; + int remainingCost; + int lastStepCost; + int walkCost; int x; int y; struct PATHNODE* Parent; struct PATHNODE* Child[NUM_DIRS]; struct PATHNODE* NextNode; - ALIGNMENT(3, 8) + ALIGNMENT64(6) } PATHNODE; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) From 7ff9262ae8d2814e4fefdb82732d0014d8959c75 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 6 Aug 2024 07:37:45 +0200 Subject: [PATCH 384/596] optimize pathfinding I. - disable PathUpdateCosts --- Source/path.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Source/path.cpp b/Source/path.cpp index 6daf9c88eed..59fa4c4879c 100644 --- a/Source/path.cpp +++ b/Source/path.cpp @@ -102,7 +102,7 @@ static inline int PathStepCost(int sx, int sy, int dx, int dy) { return (sx == dx || sy == dy) ? 2 : 3; } - +#ifdef DEBUG_PATH /** * @brief update all path costs using depth-first search starting at pPath */ @@ -126,7 +126,7 @@ static void PathUpdateCosts(PATHNODE* pPath) newStepCost = PathStepCost(PathOld->x, PathOld->y, PathAct->x, PathAct->y); newWalkCost = PathOld->walkCost + newStepCost; if (newWalkCost < PathAct->walkCost /*&& PathWalkable(PathOld->x, PathOld->y, PathAct->x, PathAct->y)*/) { - // EventPlrMsg("Update walk 0 %d:%d cost%d:%d last%d to cost%d:%d", PathAct->x - gnSx, PathAct->y - gnSy, PathAct->totalCost, PathAct->walkCost, PathAct->lastStepCost, newWalkCost + PathAct->remainingCost, newWalkCost); + EventPlrMsg("Update walk 0 %d:%d cost%d:%d last%d to cost%d:%d", PathAct->x - gnSx, PathAct->y - gnSy, PathAct->totalCost, PathAct->walkCost, PathAct->lastStepCost, newWalkCost + PathAct->remainingCost, newWalkCost); PathAct->Parent = PathOld; PathAct->walkCost = newWalkCost; PathAct->lastStepCost = newStepCost; @@ -134,14 +134,14 @@ static void PathUpdateCosts(PATHNODE* pPath) pathUpdateStack[updateStackSize] = PathAct; updateStackSize++; } else if (newWalkCost == PathAct->walkCost /*&& PathWalkable(PathOld->x, PathOld->y, PathAct->x, PathAct->y)*/ && newStepCost > PathAct->lastStepCost) { - // EventPlrMsg("Update walk 1 %d:%d cost%d:%d last%d to cost%d:%d", PathAct->x - gnSx, PathAct->y - gnSy, PathAct->totalCost, PathAct->walkCost, PathAct->lastStepCost, newWalkCost + PathAct->remainingCost, newWalkCost); + EventPlrMsg("Update walk 1 %d:%d cost%d:%d last%d to cost%d:%d", PathAct->x - gnSx, PathAct->y - gnSy, PathAct->totalCost, PathAct->walkCost, PathAct->lastStepCost, newWalkCost + PathAct->remainingCost, newWalkCost); PathAct->Parent = PathOld; PathAct->lastStepCost = newStepCost; } } } while (updateStackSize != 0); } - +#endif /** * @brief heuristic, estimated cost from (x,y) to (gnTx,gnTy) */ @@ -202,10 +202,12 @@ static bool path_parent_path(PATHNODE* pPath, int dx, int dy) dxdy->lastStepCost = stepCost; dxdy->walkCost = nextWalkCost; dxdy->totalCost = nextWalkCost + dxdy->remainingCost; +#ifdef DEBUG_PATH if (!frontier) { // already explored, so re-update others starting from that node PathUpdateCosts(dxdy); } +#endif } else if (nextWalkCost == dxdy->walkCost /*&& PathWalkable(pPath->x, pPath->y, dx, dy)*/ && stepCost > dxdy->lastStepCost) { // EventPlrMsg("Update 2 path %d:%d cost%d:%d last%d to last%d", dxdy->x - gnSx, dxdy->y - gnSy, dxdy->totalCost, dxdy->walkCost, dxdy->lastStepCost, stepCost); dxdy->Parent = pPath; From cfd8bbde28d7ac39404bfda73c4fc36099875d5a Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 6 Aug 2024 07:51:09 +0200 Subject: [PATCH 385/596] optimize pathfinding II. - calculate the directions only if the path fits to the destination --- Source/path.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/path.cpp b/Source/path.cpp index 59fa4c4879c..3416ac29dde 100644 --- a/Source/path.cpp +++ b/Source/path.cpp @@ -334,11 +334,11 @@ int FindPath(bool (*PosOk)(int, int, int), int PosOkArg, int sx, int sy, int dx, // EventPlrMsg("Found path from %d:%d to %d:%d -- too long", sx - gnSx, sy - gnSy, dx, dy - gnSy); return -1; // path does not fit to the destination, abort! } - reversePathDirs[path_length++] = path_directions[3 * (currNode->y - currNode->Parent->y) - currNode->Parent->x + 4 + currNode->x]; + reversePathDirs[path_length++] = 3 * (currNode->y - currNode->Parent->y) - currNode->Parent->x + 4 + currNode->x; currNode = currNode->Parent; } for (i = 0; i < path_length; i++) - path[i] = reversePathDirs[path_length - i - 1]; + path[i] = path_directions[reversePathDirs[path_length - i - 1]]; // EventPlrMsg("Found path from %d:%d to %d:%d: %d", sx - gnSx, sy - gnSy, dx - gnSx, dy - gnSy, path_length); return i; } From 81dfab328172bb37528425b3da3c3b0eca607ffd Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 6 Aug 2024 07:52:33 +0200 Subject: [PATCH 386/596] optimize pathfinding III. - reduce the limit of totalCost in FindPath --- Source/path.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/path.cpp b/Source/path.cpp index 3416ac29dde..6fae0ffbf3a 100644 --- a/Source/path.cpp +++ b/Source/path.cpp @@ -342,7 +342,7 @@ int FindPath(bool (*PosOk)(int, int, int), int PosOkArg, int sx, int sy, int dx, // EventPlrMsg("Found path from %d:%d to %d:%d: %d", sx - gnSx, sy - gnSy, dx - gnSx, dy - gnSy, path_length); return i; } - if (currNode->totalCost > 4 * (MAX_PATH_LENGTH - 1)) { + if (currNode->totalCost > 3 * MAX_PATH_LENGTH) { // EventPlrMsg("No path from %d:%d to %d:%d -- too long", sx - gnSx, sy - gnSy, dx, dy - gnSy); return -1; // path is hopeless } From 718504c306e8bb9a39d391e1cdc18d68225c34a3 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 6 Aug 2024 07:54:23 +0200 Subject: [PATCH 387/596] optimize pathfinding IV. - use (more) locals in path_get_path --- Source/path.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Source/path.cpp b/Source/path.cpp index 6fae0ffbf3a..4bce3090684 100644 --- a/Source/path.cpp +++ b/Source/path.cpp @@ -244,16 +244,19 @@ static bool path_parent_path(PATHNODE* pPath, int dx, int dy) */ static bool path_get_path(bool (*PosOk)(int, int, int), int PosOkArg, PATHNODE* pPath) { + int sx, sy; int dx, dy; int i; bool ok; + sx = pPath->x; + sy = pPath->y; static_assert(lengthof(pathxdir) == lengthof(pathydir), "Mismatching pathdir tables."); for (i = 0; i < lengthof(pathxdir); i++) { - dx = pPath->x + pathxdir[i]; - dy = pPath->y + pathydir[i]; + dx = sx + pathxdir[i]; + dy = sy + pathydir[i]; ok = PosOk(PosOkArg, dx, dy); - if ((ok && PathWalkable(pPath->x, pPath->y, i)) || (!ok && dx == gnTx && dy == gnTy)) { + if ((ok && PathWalkable(sx, sy, i)) || (!ok && dx == gnTx && dy == gnTy)) { if (!path_parent_path(pPath, dx, dy)) return false; } From 0fa29094fb01119102a293e8bfe0b954a42e34ce Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 6 Aug 2024 07:57:22 +0200 Subject: [PATCH 388/596] optimize pathfinding V. - calculate stepCost in path_get_path --- Source/path.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/Source/path.cpp b/Source/path.cpp index 4bce3090684..e03179c87b8 100644 --- a/Source/path.cpp +++ b/Source/path.cpp @@ -23,14 +23,16 @@ static PATHNODE* pathUpdateStack[MAXPATHNODES]; static PATHNODE* pathFrontNodes; /** The target location. */ static int gnTx, gnTy; -#ifdef DEBUG_PATH -/** The target location. */ -static int gnSx, gnSy; -#endif + /** For iterating over the 8 possible movement directions. */ // PDIR_N W E S NW NE SE SW const int8_t pathxdir[8] = { -1, -1, 1, 1, -1, 0, 1, 0 }; const int8_t pathydir[8] = { -1, 1, -1, 1, 0, -1, 0, 1 }; +#ifdef DEBUG_PATH +static const int8_t stepcost[8] = { 3, 3, 3, 3, 2, 2, 2, 2 }; +/** The target location. */ +static int gnSx, gnSy; +#endif /** Maps from facing direction to path-direction. */ const BYTE dir2pdir[NUM_DIRS] = { PDIR_S, PDIR_SW, PDIR_W, PDIR_NW, PDIR_N, PDIR_NE, PDIR_E, PDIR_SE }; @@ -175,14 +177,14 @@ static inline void PathAppendChild(PATHNODE* parent, PATHNODE* child) * * @return true if step successfully added, false if we ran out of nodes to use */ -static bool path_parent_path(PATHNODE* pPath, int dx, int dy) +static bool path_parent_path(PATHNODE* pPath, int dx, int dy, int stepCost) { int nextWalkCost; - int stepCost; + // int stepCost; bool frontier; PATHNODE* dxdy; - stepCost = PathStepCost(pPath->x, pPath->y, dx, dy); + // stepCost = PathStepCost(pPath->x, pPath->y, dx, dy); nextWalkCost = pPath->walkCost + stepCost; // 3 cases to consider @@ -257,7 +259,10 @@ static bool path_get_path(bool (*PosOk)(int, int, int), int PosOkArg, PATHNODE* dy = sy + pathydir[i]; ok = PosOk(PosOkArg, dx, dy); if ((ok && PathWalkable(sx, sy, i)) || (!ok && dx == gnTx && dy == gnTy)) { - if (!path_parent_path(pPath, dx, dy)) +#ifdef DEBUG_PATH + assert(stepcost[i] == (i < 4 ? 3 : 2)); +#endif + if (!path_parent_path(pPath, dx, dy, i < 4 ? 3 : 2)) return false; } } From cba9c6f90cab99fffb9e169f181b87f8262efa95 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 6 Aug 2024 08:48:20 +0200 Subject: [PATCH 389/596] add possible pathfinding optimizations --- Source/path.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/path.cpp b/Source/path.cpp index e03179c87b8..55398d7685f 100644 --- a/Source/path.cpp +++ b/Source/path.cpp @@ -132,7 +132,7 @@ static void PathUpdateCosts(PATHNODE* pPath) PathAct->Parent = PathOld; PathAct->walkCost = newWalkCost; PathAct->lastStepCost = newStepCost; - PathAct->totalCost = newWalkCost + PathAct->remainingCost; + PathAct->totalCost = newWalkCost + PathAct->remainingCost; // PathAct->totalCost -= PathAct->walkCost - newWalkCost; pathUpdateStack[updateStackSize] = PathAct; updateStackSize++; } else if (newWalkCost == PathAct->walkCost /*&& PathWalkable(PathOld->x, PathOld->y, PathAct->x, PathAct->y)*/ && newStepCost > PathAct->lastStepCost) { @@ -203,7 +203,7 @@ static bool path_parent_path(PATHNODE* pPath, int dx, int dy, int stepCost) dxdy->Parent = pPath; dxdy->lastStepCost = stepCost; dxdy->walkCost = nextWalkCost; - dxdy->totalCost = nextWalkCost + dxdy->remainingCost; + dxdy->totalCost = nextWalkCost + dxdy->remainingCost; // dxdy->totalCost -= dxdy->walkCost - nextWalkCost; #ifdef DEBUG_PATH if (!frontier) { // already explored, so re-update others starting from that node From 63a3ff9f670cf26037cb88bb4fb2c975c066f53e Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 6 Aug 2024 08:50:00 +0200 Subject: [PATCH 390/596] document STextStruct --- structs.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/structs.h b/structs.h index dff58e33a66..34769ab20ad 100644 --- a/structs.h +++ b/structs.h @@ -2620,14 +2620,14 @@ typedef struct TriggerStruct { ////////////////////////////////////////////////// typedef struct STextStruct { - int _sx; - int _syoff; - char _sstr[112]; - bool _sjust; - BYTE _sclr; + int _sx; // starting position + int _syoff; // y-offset where the text should be printed + char _sstr[112]; // the text + bool _sjust; // whether the string should be justified + BYTE _sclr; // the color of the string // bool _sline; - bool _ssel; - int _sval; + bool _ssel; // whether the line is selectable + int _sval; // integer value to be printed on the right side of the line } STextStruct; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) From 5e875b93abfb27401c515dc58b68cdf30c44fc60 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 6 Aug 2024 09:11:35 +0200 Subject: [PATCH 391/596] simplify the STORE_PRIEST_ERRAND case in S_PriestEnter --- Source/stores.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index a5c2d5b12a4..c22e3f4520b 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -2362,9 +2362,6 @@ static void S_PriestEnter() StartStore(STORE_GOSSIP); break;*/ case STORE_PRIEST_ERRAND: - stextlhold = STORE_PRIEST_ERRAND; - talker = TOWN_PRIEST; - stextshold = STORE_PRIEST; StartStore(STORE_ERRAND); break; case STORE_PRIEST_EXIT: From 3b1ecd334b5a50060f9481098525281a26e9ac77 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 6 Aug 2024 09:13:25 +0200 Subject: [PATCH 392/596] initialize stextsidx in StartStore --- Source/stores.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index c22e3f4520b..dbd9f0b9cbc 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -451,7 +451,7 @@ static void S_StartSBuy() msg = "I have no basic item for sale."; } else { gbHasScroll = true; - stextsidx = 0; + // stextsidx = 0; S_ScrollSBuy(); msg = "I have these basic items for sale:"; @@ -513,7 +513,7 @@ static void S_StartSPBuy() msg = "I have no premium item for sale."; } else { gbHasScroll = true; - stextsidx = 0; + // stextsidx = 0; S_ScrollSPBuy(); msg = "I have these premium items for sale:"; @@ -602,7 +602,7 @@ static void S_StartSSell() msg = "You have nothing I want."; } else { gbHasScroll = true; - stextsidx = 0; + // stextsidx = 0; S_ScrollSSell(); msg = "Which item is for sale?"; @@ -662,7 +662,7 @@ static void S_StartSRepair() msg = "You have nothing to repair."; } else { gbHasScroll = true; - stextsidx = 0; + // stextsidx = 0; S_ScrollSSell(); msg = "Repair which item?"; @@ -723,7 +723,7 @@ static void S_StartWBuy() gbWidePanel = true; // gbRenderGold = true; gbHasScroll = true; - stextsidx = 0; + // stextsidx = 0; S_ScrollWBuy(); AddStoreFrame("I have these items for sale:"); @@ -766,7 +766,7 @@ static void S_StartWSell() msg = "You have nothing I want."; } else { gbHasScroll = true; - stextsidx = 0; + // stextsidx = 0; S_ScrollSSell(); msg = "Which item is for sale?"; } @@ -819,7 +819,7 @@ static void S_StartWRecharge() msg = "You have nothing to recharge."; } else { gbHasScroll = true; - stextsidx = 0; + // stextsidx = 0; S_ScrollSSell(); msg = "Recharge which item?"; @@ -994,7 +994,7 @@ static void S_StartHBuy() gbWidePanel = true; // gbRenderGold = true; gbHasScroll = true; - stextsidx = 0; + // stextsidx = 0; S_ScrollHBuy(); AddStoreFrame("I have these items for sale:"); @@ -1060,7 +1060,7 @@ static void S_StartSIdentify() msg = "You have nothing to identify."; } else { gbHasScroll = true; - stextsidx = 0; + // stextsidx = 0; S_ScrollSSell(); msg = "Identify which item?"; @@ -1183,6 +1183,7 @@ void StartStore(int s) ClearSText(0, STORE_LINES); ReleaseStoreBtn(); stextflag = s; + stextsidx = 0; switch (s) { case STORE_SMITH: S_StartSmith(); From 248065dc5819447170b0a3d16ec92b7a4c6fa8c9 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 6 Aug 2024 09:32:42 +0200 Subject: [PATCH 393/596] sync the stextl/v/svhold setters in stores.cpp --- Source/stores.cpp | 59 +++++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index dbd9f0b9cbc..ec06de37511 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -1350,7 +1350,9 @@ void STextESC() break; case STORE_GOSSIP: StartStore(stextshold); + // stextflag = stextshold; stextsel = stextlhold; + // stextsidx = stextvhold; break; case STORE_SBUY: StartStore(STORE_SMITH); @@ -1399,6 +1401,7 @@ void STextESC() case STORE_NOROOM: case STORE_CONFIRM: StartStore(stextshold); + // stextflag = stextshold; stextsel = stextlhold; stextsidx = stextvhold; break; @@ -1480,8 +1483,9 @@ static void S_SmithEnter() switch (stextsel) { case STORE_SMITH_GOSSIP: stextlhold = STORE_SMITH_GOSSIP; - talker = TOWN_SMITH; + // stextvhold = stextsidx; stextshold = STORE_SMITH; + talker = TOWN_SMITH; StartStore(STORE_GOSSIP); break; case STORE_SMITH_BUY: @@ -1628,9 +1632,9 @@ static void S_SPBuyEnter() // StartStore(STORE_SMITH); // stextsel = STORE_SMITH_SPBUY; } else { - stextshold = STORE_SPBUY; stextlhold = stextsel; stextvhold = stextsidx; + stextshold = STORE_SPBUY; xx = stextsidx + ((stextsel - STORE_LIST_FIRST) >> 2); idx = 0; for (i = 0; xx >= 0; i++) { @@ -1822,8 +1826,12 @@ void SyncStoreCmd(int pnum, int cmd, int ii, int price) return; } + // stextflag = stextshold; -- except for wirt's redirect stextsel = stextlhold; - stextsidx = std::min(stextvhold, stextsmax); + stextsidx = stextvhold; + if (stextsidx > stextsmax) { + stextsidx = stextsmax; + } while (stextsel != -1 && !stextlines[stextsel]._ssel) { stextsel--; @@ -1853,9 +1861,10 @@ static void S_SSell() int idx; stextlhold = stextsel; - idx = stextsidx + ((stextsel - STORE_LIST_FIRST) >> 2); - stextshold = stextflag; stextvhold = stextsidx; + stextshold = stextflag; + + idx = stextsidx + ((stextsel - STORE_LIST_FIRST) >> 2); copy_pod(storeitem, storehold[idx]); idx = storehidx[idx] >= 0 ? storeitem._iCurs + CURSOR_FIRSTITEM : CURSOR_NONE; @@ -1904,9 +1913,9 @@ static void S_SRepairEnter() // StartStore(STORE_SMITH); // stextsel = STORE_SMITH_REPAIR; } else { - stextshold = STORE_SREPAIR; stextlhold = stextsel; stextvhold = stextsidx; + stextshold = STORE_SREPAIR; idx = stextsidx + ((stextsel - STORE_LIST_FIRST) >> 2); copy_pod(storeitem, storehold[idx]); if (myplr._pGold < storehold[idx]._iIvalue) @@ -1921,8 +1930,9 @@ static void S_WitchEnter() switch (stextsel) { case STORE_WITCH_GOSSIP: stextlhold = STORE_WITCH_GOSSIP; - talker = TOWN_WITCH; + // stextvhold = stextsidx; stextshold = STORE_WITCH; + talker = TOWN_WITCH; StartStore(STORE_GOSSIP); return; case STORE_WITCH_BUY: @@ -2021,9 +2031,9 @@ static void S_WRechargeEnter() // StartStore(STORE_WITCH); // stextsel = STORE_WITCH_RECHARGE; } else { - stextshold = STORE_WRECHARGE; stextlhold = stextsel; stextvhold = stextsidx; + stextshold = STORE_WRECHARGE; idx = stextsidx + ((stextsel - STORE_LIST_FIRST) >> 2); copy_pod(storeitem, storehold[idx]); if (myplr._pGold < storehold[idx]._iIvalue) @@ -2037,9 +2047,9 @@ static void S_BoyEnter() { if (boyitem._itype != ITYPE_NONE) { if (stextsel == STORE_PEGBOY_QUERY) { - stextshold = STORE_PEGBOY; stextlhold = STORE_PEGBOY_QUERY; stextvhold = stextsidx; + stextshold = STORE_PEGBOY; if (boyitem._iIdentified) { StartStore(STORE_PBUY); } else if (myplr._pGold < STORE_PEGBOY_PRICE) { @@ -2061,8 +2071,9 @@ static void S_BoyEnter() } } stextlhold = stextsel; - talker = TOWN_PEGBOY; + // stextvhold = stextsidx; stextshold = STORE_PEGBOY; + talker = TOWN_PEGBOY; StartStore(STORE_GOSSIP); } @@ -2104,9 +2115,9 @@ static void S_BBuyEnter() // StartStore(STORE_PEGBOY); // stextsel = STORE_PEGBOY_QUERY; } else { - stextshold = STORE_PBUY; - stextvhold = stextsidx; stextlhold = STORE_PEGBOY_BUY; + stextvhold = stextsidx; + stextshold = STORE_PBUY; StoreStartBuy(&boyitem, boyitem._iIvalue); } } @@ -2115,7 +2126,8 @@ static void StoryIdItem() { int idx; - idx = storehidx[((stextlhold - STORE_LIST_FIRST) >> 2) + stextvhold]; + idx = stextvhold + ((stextlhold - STORE_LIST_FIRST) >> 2); + idx = storehidx[idx]; if (idx < 0) idx = INVITEM_BODY_FIRST - (idx + 1); else @@ -2176,8 +2188,9 @@ static void S_HealerEnter() switch (stextsel) { case STORE_HEALER_GOSSIP: stextlhold = STORE_HEALER_GOSSIP; - talker = TOWN_HEALER; + // stextvhold = stextsidx; stextshold = STORE_HEALER; + talker = TOWN_HEALER; StartStore(STORE_GOSSIP); break; case STORE_HEALER_HEAL: @@ -2220,8 +2233,9 @@ static void S_StoryEnter() switch (stextsel) { case STORE_STORY_GOSSIP: stextlhold = STORE_STORY_GOSSIP; - talker = TOWN_STORY; + // stextvhold = stextsidx; stextshold = STORE_STORY; + talker = TOWN_STORY; StartStore(STORE_GOSSIP); break; case STORE_STORY_IDENTIFY: @@ -2245,9 +2259,9 @@ static void S_SIDEnter() // StartStore(STORE_STORY); // stextsel = STORE_STORY_IDENTIFY; } else { - stextshold = STORE_SIDENTIFY; stextlhold = stextsel; stextvhold = stextsidx; + stextshold = STORE_SIDENTIFY; idx = stextsidx + ((stextsel - STORE_LIST_FIRST) >> 2); copy_pod(storeitem, storehold[idx]); if (myplr._pGold < storehold[idx]._iIvalue) @@ -2304,8 +2318,9 @@ static void S_TavernEnter() switch (stextsel) { case STORE_TAVERN_GOSSIP: stextlhold = STORE_TAVERN_GOSSIP; - talker = TOWN_TAVERN; + // stextvhold = stextsidx; stextshold = STORE_TAVERN; + talker = TOWN_TAVERN; StartStore(STORE_GOSSIP); break; case STORE_TAVERN_EXIT: @@ -2322,8 +2337,9 @@ static void S_BarmaidEnter() switch (stextsel) { case STORE_BARMAID_GOSSIP: stextlhold = STORE_BARMAID_GOSSIP; - talker = TOWN_BARMAID; + // stextvhold = stextsidx; stextshold = STORE_BARMAID; + talker = TOWN_BARMAID; StartStore(STORE_GOSSIP); break; case STORE_BARMAID_EXIT: @@ -2340,8 +2356,9 @@ static void S_DrunkEnter() switch (stextsel) { case STORE_DRUNK_GOSSIP: stextlhold = STORE_DRUNK_GOSSIP; - talker = TOWN_DRUNK; + // stextvhold = stextsidx; stextshold = STORE_DRUNK; + talker = TOWN_DRUNK; StartStore(STORE_GOSSIP); break; case STORE_DRUNK_EXIT: @@ -2358,8 +2375,9 @@ static void S_PriestEnter() switch (stextsel) { /*case STORE_PRIEST_GOSSIP: stextlhold = STORE_PRIEST_GOSSIP; - talker = TOWN_PRIEST; + // stextvhold = stextsidx; stextshold = STORE_PRIEST; + talker = TOWN_PRIEST; StartStore(STORE_GOSSIP); break;*/ case STORE_PRIEST_ERRAND: @@ -2426,6 +2444,7 @@ void STextEnter() case STORE_NOROOM: STextESC(); // StartStore(stextshold); + // // stextflag = stextshold; // stextsel = stextlhold; // stextsidx = stextvhold; break; From cb2f5af33868ec39c7082c1a9945547b5d20c82d Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 6 Aug 2024 09:43:09 +0200 Subject: [PATCH 394/596] add DEBUG_STORES and DEBUG_ASSERT to stores.cpp --- Source/stores.cpp | 55 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index ec06de37511..7892e326e9d 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -9,6 +9,13 @@ DEVILUTION_BEGIN_NAMESPACE +// #define DEBUG_STORES +#ifdef DEBUG_STORES +#define DEBUG_ASSERT(x) assert(x) +#else +#define DEBUG_ASSERT(x) ((void)0) +#endif + // required size of the store to accomodate the relevant items #define STORAGE_LIMIT (NUM_INV_GRID_ELEM + (MAXBELTITEMS > NUM_INVLOC ? MAXBELTITEMS : NUM_INVLOC)) @@ -60,6 +67,7 @@ DEVILUTION_BEGIN_NAMESPACE #define STORE_DRUNK_GOSSIP 12 #define STORE_DRUNK_EXIT 18 +//#define STORE_PRIEST_GOSSIP 12 #define STORE_PRIEST_ERRAND 12 #define STORE_PRIEST_EXIT 18 @@ -222,13 +230,13 @@ void PrintSString(int x, int y, bool cjustflag, const char* str, BYTE col, int v px = stextsel == y ? sx : INT_MAX; sx = PrintLimitedString(sx, sy, str, limit, col); if (val > 0) { - assert(!cjustflag && gbWidePanel); + DEBUG_ASSERT(!cjustflag && gbWidePanel); snprintf(valstr, sizeof(valstr), "%d", val); sx = LTPANEL_X + LTPANEL_WIDTH - (2 * SMALL_SCROLL_WIDTH + x + GetSmallStringWidth(valstr)); PrintGameStr(sx, sy, valstr, col); } if (px != INT_MAX) { - assert(cjustflag || gbWidePanel); + DEBUG_ASSERT(cjustflag || gbWidePanel); DrawSmallPentSpn(px - FOCUS_SMALL, cjustflag ? sx + 6 : (LTPANEL_X + LTPANEL_WIDTH - (x + FOCUS_SMALL)), sy + 1); } } @@ -240,7 +248,7 @@ static void DrawSSlider(/*int y1, int y2*/) //assert(LTPANEL_X + LTPANEL_WIDTH == STORE_PNL_X + STPANEL_WIDTH); //x = STORE_PNL_X + STPANEL_WIDTH - (SMALL_SCROLL_WIDTH + 2); - assert(gbWidePanel); + DEBUG_ASSERT(gbWidePanel); x = LTPANEL_X + LTPANEL_WIDTH - (SMALL_SCROLL_WIDTH + 2); yd1 = y1 * SMALL_SCROLL_HEIGHT + LTPANEL_Y + 20; // top position of the scrollbar yd2 = y2 * SMALL_SCROLL_HEIGHT + LTPANEL_Y + 20; // bottom position of the scrollbar @@ -1417,9 +1425,7 @@ void STextESC() void STextUp() { PlaySFX(IS_TITLEMOV); - if (stextsel == -1) { - return; - } + DEBUG_ASSERT(stextsel != -1); if (gbHasScroll && stextsel == STORE_LIST_FIRST) { if (stextsidx != 0) @@ -1437,9 +1443,7 @@ void STextUp() void STextDown() { PlaySFX(IS_TITLEMOV); - if (stextsel == -1) { - return; - } + DEBUG_ASSERT(stextsel != -1); if (gbHasScroll && stextsel == stextdown) { if (stextsidx < stextsmax) @@ -1456,7 +1460,8 @@ void STextDown() void STextPageUp() { - if (stextsel != -1 && gbHasScroll) { + DEBUG_ASSERT(stextsel != -1); + if (gbHasScroll) { PlaySFX(IS_TITLEMOV); stextsidx -= 4; if (stextsidx < 0) { @@ -1468,7 +1473,8 @@ void STextPageUp() void STextPageDown() { - if (stextsel != -1 && gbHasScroll) { + DEBUG_ASSERT(stextsel != -1); + if (gbHasScroll) { PlaySFX(IS_TITLEMOV); stextsidx += 4; if (stextsidx > stextsmax) { @@ -1482,6 +1488,7 @@ static void S_SmithEnter() { switch (stextsel) { case STORE_SMITH_GOSSIP: + DEBUG_ASSERT(stextflag == STORE_SMITH); stextlhold = STORE_SMITH_GOSSIP; // stextvhold = stextsidx; stextshold = STORE_SMITH; @@ -1592,6 +1599,7 @@ static void S_SBuyEnter() // StartStore(STORE_SMITH); // stextsel = STORE_SMITH_BUY; } else { + DEBUG_ASSERT(stextflag == STORE_SBUY); stextlhold = stextsel; stextvhold = stextsidx; stextshold = STORE_SBUY; @@ -1632,6 +1640,7 @@ static void S_SPBuyEnter() // StartStore(STORE_SMITH); // stextsel = STORE_SMITH_SPBUY; } else { + DEBUG_ASSERT(stextflag == STORE_SPBUY); stextlhold = stextsel; stextvhold = stextsidx; stextshold = STORE_SPBUY; @@ -1779,7 +1788,7 @@ void SyncStoreCmd(int pnum, int cmd, int ii, int price) lastshold = nextMode; break; case STORE_SIDENTIFY: - assert(price == STORE_ID_PRICE); + DEBUG_ASSERT(price == STORE_ID_PRICE); if (!TakePlrsMoney(pnum, STORE_ID_PRICE)) return; pi = PlrItem(pnum, ii); @@ -1803,7 +1812,7 @@ void SyncStoreCmd(int pnum, int cmd, int ii, int price) pi->_iCharges = pi->_iMaxCharges; break; case STORE_PEGBOY: - assert(price == STORE_PEGBOY_PRICE); + DEBUG_ASSERT(price == STORE_PEGBOY_PRICE); if (!TakePlrsMoney(pnum, STORE_PEGBOY_PRICE)) return; //lastshold = STORE_PEGBOY; @@ -1832,9 +1841,10 @@ void SyncStoreCmd(int pnum, int cmd, int ii, int price) if (stextsidx > stextsmax) { stextsidx = stextsmax; } - - while (stextsel != -1 && !stextlines[stextsel]._ssel) { + DEBUG_ASSERT(stextsel != -1); + while (/*stextsel != -1 && */ !stextlines[stextsel]._ssel) { stextsel--; + DEBUG_ASSERT(stextsel != -1); } } @@ -1913,6 +1923,7 @@ static void S_SRepairEnter() // StartStore(STORE_SMITH); // stextsel = STORE_SMITH_REPAIR; } else { + DEBUG_ASSERT(stextflag == STORE_SREPAIR); stextlhold = stextsel; stextvhold = stextsidx; stextshold = STORE_SREPAIR; @@ -1929,6 +1940,7 @@ static void S_WitchEnter() { switch (stextsel) { case STORE_WITCH_GOSSIP: + DEBUG_ASSERT(stextflag == STORE_WITCH); stextlhold = STORE_WITCH_GOSSIP; // stextvhold = stextsidx; stextshold = STORE_WITCH; @@ -1984,6 +1996,7 @@ static void S_WBuyEnter() // StartStore(STORE_WITCH); // stextsel = STORE_WITCH_BUY; } else { + DEBUG_ASSERT(stextflag == STORE_WBUY); stextlhold = stextsel; stextvhold = stextsidx; stextshold = STORE_WBUY; @@ -2031,6 +2044,7 @@ static void S_WRechargeEnter() // StartStore(STORE_WITCH); // stextsel = STORE_WITCH_RECHARGE; } else { + DEBUG_ASSERT(stextflag == STORE_WRECHARGE); stextlhold = stextsel; stextvhold = stextsidx; stextshold = STORE_WRECHARGE; @@ -2045,6 +2059,7 @@ static void S_WRechargeEnter() static void S_BoyEnter() { + DEBUG_ASSERT(stextflag == STORE_PEGBOY); if (boyitem._itype != ITYPE_NONE) { if (stextsel == STORE_PEGBOY_QUERY) { stextlhold = STORE_PEGBOY_QUERY; @@ -2115,6 +2130,8 @@ static void S_BBuyEnter() // StartStore(STORE_PEGBOY); // stextsel = STORE_PEGBOY_QUERY; } else { + DEBUG_ASSERT(stextflag == STORE_PBUY); + DEBUG_ASSERT(stextsel == STORE_PEGBOY_BUY); stextlhold = STORE_PEGBOY_BUY; stextvhold = stextsidx; stextshold = STORE_PBUY; @@ -2187,6 +2204,7 @@ static void S_HealerEnter() { switch (stextsel) { case STORE_HEALER_GOSSIP: + DEBUG_ASSERT(stextflag == STORE_HEALER); stextlhold = STORE_HEALER_GOSSIP; // stextvhold = stextsidx; stextshold = STORE_HEALER; @@ -2220,6 +2238,7 @@ static void S_HBuyEnter() // StartStore(STORE_HEALER); // stextsel = STORE_HEALER_BUY; } else { + DEBUG_ASSERT(stextflag == STORE_HBUY); stextlhold = stextsel; stextvhold = stextsidx; stextshold = STORE_HBUY; @@ -2232,6 +2251,7 @@ static void S_StoryEnter() { switch (stextsel) { case STORE_STORY_GOSSIP: + DEBUG_ASSERT(stextflag == STORE_STORY); stextlhold = STORE_STORY_GOSSIP; // stextvhold = stextsidx; stextshold = STORE_STORY; @@ -2259,6 +2279,7 @@ static void S_SIDEnter() // StartStore(STORE_STORY); // stextsel = STORE_STORY_IDENTIFY; } else { + DEBUG_ASSERT(stextflag == STORE_SIDENTIFY); stextlhold = stextsel; stextvhold = stextsidx; stextshold = STORE_SIDENTIFY; @@ -2317,6 +2338,7 @@ static void S_TavernEnter() { switch (stextsel) { case STORE_TAVERN_GOSSIP: + DEBUG_ASSERT(stextflag == STORE_TAVERN); stextlhold = STORE_TAVERN_GOSSIP; // stextvhold = stextsidx; stextshold = STORE_TAVERN; @@ -2336,6 +2358,7 @@ static void S_BarmaidEnter() { switch (stextsel) { case STORE_BARMAID_GOSSIP: + DEBUG_ASSERT(stextflag == STORE_BARMAID); stextlhold = STORE_BARMAID_GOSSIP; // stextvhold = stextsidx; stextshold = STORE_BARMAID; @@ -2355,6 +2378,7 @@ static void S_DrunkEnter() { switch (stextsel) { case STORE_DRUNK_GOSSIP: + DEBUG_ASSERT(stextflag == STORE_DRUNK); stextlhold = STORE_DRUNK_GOSSIP; // stextvhold = stextsidx; stextshold = STORE_DRUNK; @@ -2374,6 +2398,7 @@ static void S_PriestEnter() { switch (stextsel) { /*case STORE_PRIEST_GOSSIP: + DEBUG_ASSERT(stextflag == STORE_PRIEST); stextlhold = STORE_PRIEST_GOSSIP; // stextvhold = stextsidx; stextshold = STORE_PRIEST; From db17706a5d9512bf477853237a70b52e26d7e021 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 6 Aug 2024 13:06:03 +0200 Subject: [PATCH 395/596] use icons in stores --- Source/controls/plrctrls.cpp | 4 + Source/stores.cpp | 422 +++++++++++++++++++++++++++++------ Source/stores.h | 2 + structs.h | 9 +- 4 files changed, 370 insertions(+), 67 deletions(-) diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index 067a6392457..1154bb2ee56 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -788,6 +788,10 @@ static void StoreMove(AxisDirection moveDir) STextUp(); else if (moveDir.y == AxisDirectionY_DOWN) STextDown(); + else if (moveDir.x == AxisDirectionX_LEFT) + STextLeft(); + else if (moveDir.x == AxisDirectionX_RIGHT) + STextRight(); } typedef void (*HandleLeftStickOrDPadFn)(dvl::AxisDirection); diff --git a/Source/stores.cpp b/Source/stores.cpp index 7892e326e9d..7f5cd1ebfa7 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -78,6 +78,10 @@ DEVILUTION_BEGIN_NAMESPACE #define STORE_ID_PRICE 100 #define STORE_PEGBOY_PRICE 50 +#define STORE_ITEM_LINES ((3 * INV_SLOT_SIZE_PX + 11) / 12) +#define STORE_LINE_ITEMS 8 +#define STORE_PAGE_ITEMS (STORE_LINE_ITEMS * 2) + /* The current item in store. */ ItemStruct storeitem; /* The item for sale by Wirt. */ @@ -119,8 +123,12 @@ static int stextshold; static STextStruct stextlines[STORE_LINES]; /** Currently selected text line from stextlines */ static int stextsel; +/** Currently selected item index from stextlines */ +static int stextselx; /** Remember stextsel while displaying a dialog */ static int stextlhold; +/** Remember stextselx while displaying a dialog */ +static int stextxhold; /** The maximum possible value of stextsidx */ static int stextsmax; /** Copies of the players items as presented in the store */ @@ -155,6 +163,7 @@ static void ClearSText(int s, int e) // int i; static_assert(COL_WHITE == 0, "ClearSText skips color initialization by expecting COL_WHITE to be zero."); + static_assert(CURSOR_NONE == 0, "ClearSText skips cursor initialization by expecting CURSOR_NONE to be zero."); memset(&stextlines[s], 0, (size_t)&stextlines[e] - (size_t)&stextlines[s]); /*for (i = s; i < e; i++) { stextlines[i]._sx = 0; @@ -307,6 +316,17 @@ static void AddSText(int x, int y, bool j, const char* str, BYTE clr, bool sel) ss->_ssel = sel; } +static void AddSItem(int x, int y, int idx, int iCurs, bool selectable) +{ + STextStruct* ss; + + ss = &stextlines[y]; + ss->_sx = x; + ss->_sitemlist = true; + ss->_siCurs[idx] = iCurs + CURSOR_FIRSTITEM; + ss->_ssel = selectable; +} + static BYTE StoreItemColor(const ItemStruct* is) { if (!is->_iStatFlag) @@ -416,27 +436,47 @@ static void StorePrepareItemBuy(ItemStruct* is) static void S_ScrollSBuy() { ItemStruct* is; - int l; + unsigned l; ClearSText(STORE_LIST_FIRST, STORE_LIST_FOOTER); //stextup = STORE_LIST_FIRST; is = &smithitem[stextsidx]; - for (l = STORE_LIST_FIRST; l < 20; l += 4) { + for (l = 0; l < STORE_PAGE_ITEMS; l++) { if (is->_itype != ITYPE_NONE) { StorePrepareItemBuy(is); - PrintStoreItem(is, l, true); - AddSTextVal(l, is->_iIvalue); - stextdown = l; + int line = STORE_LIST_FIRST + (l / STORE_LINE_ITEMS) * STORE_ITEM_LINES; + AddSItem(60, line, l % STORE_LINE_ITEMS, is->_iCurs, TRUE); + stextdown = line; is++; } } if (stextsel != -1 && /*stextsel != STORE_BACK &&*/ !stextlines[stextsel]._ssel) stextsel = stextdown; - stextsmax = storenumh - 4; - if (stextsmax < 0) + if (stextsel != -1 && stextlines[stextsel]._sitemlist) { + while (stextselx >= 0 && stextlines[stextsel]._siCurs[stextselx] == CURSOR_NONE) { + stextselx--; + } + } + + is = &smithitem[stextsidx]; + for (l = 0; l < STORE_PAGE_ITEMS; l++) { + if (is->_itype != ITYPE_NONE) { + if (stextsel == STORE_LIST_FIRST + (l / STORE_LINE_ITEMS) * STORE_ITEM_LINES && stextselx == l % STORE_LINE_ITEMS) { + // StorePrepareItemBuy(is); + PrintStoreItem(is, STORE_LIST_FOOTER - 3, false); + AddSTextVal(STORE_LIST_FOOTER - 3, is->_iIvalue); + } + is++; + } + } + static_assert(lengthof(smithitem) <= STORE_PAGE_ITEMS, "S_ScrollSBuy must fit to a single store-page."); + // stextsmax = storenumh - STORE_PAGE_ITEMS; + // if (stextsmax <= 0) stextsmax = 0; + // else + // stextsmax = ((stextsmax + STORE_LINE_ITEMS - 1) / STORE_LINE_ITEMS) * STORE_LINE_ITEMS; } static void S_StartSBuy() @@ -471,7 +511,7 @@ static void S_StartSBuy() static void S_ScrollSPBuy() { ItemStruct* is; - int idx, l, boughtitems; + unsigned idx, l, boughtitems; ClearSText(STORE_LIST_FIRST, STORE_LIST_FOOTER); //stextup = STORE_LIST_FIRST; @@ -481,23 +521,46 @@ static void S_ScrollSPBuy() if (premiumitems[idx]._itype != ITYPE_NONE) boughtitems--; - for (l = STORE_LIST_FIRST; l < 20 && idx < SMITH_PREMIUM_ITEMS; ) { + unsigned sidx = idx; + for (l = 0; l < STORE_PAGE_ITEMS && idx < SMITH_PREMIUM_ITEMS; ) { is = &premiumitems[idx]; if (is->_itype != ITYPE_NONE) { StorePrepareItemBuy(is); - PrintStoreItem(is, l, true); - AddSTextVal(l, is->_iIvalue); - stextdown = l; - l += 4; + int line = STORE_LIST_FIRST + (l / STORE_LINE_ITEMS) * STORE_ITEM_LINES; + AddSItem(60, line, l % STORE_LINE_ITEMS, is->_iCurs, TRUE); + stextdown = line; + l++; } idx++; } if (stextsel != -1 && /*stextsel != STORE_BACK &&*/ !stextlines[stextsel]._ssel) stextsel = stextdown; - stextsmax = storenumh - 4; - if (stextsmax < 0) + if (stextsel != -1 && stextlines[stextsel]._sitemlist) { + while (stextselx >= 0 && stextlines[stextsel]._siCurs[stextselx] == CURSOR_NONE) { + stextselx--; + } + } + + idx = sidx; + for (l = 0; l < STORE_PAGE_ITEMS && idx < SMITH_PREMIUM_ITEMS; ) { + is = &premiumitems[idx]; + if (is->_itype != ITYPE_NONE) { + if (stextsel == STORE_LIST_FIRST + (l / STORE_LINE_ITEMS) * STORE_ITEM_LINES && stextselx == l % STORE_LINE_ITEMS) { + // StorePrepareItemBuy(is); + PrintStoreItem(is, STORE_LIST_FOOTER - 3, false); + AddSTextVal(STORE_LIST_FOOTER - 3, is->_iIvalue); + } + l++; + } + idx++; + } + static_assert(lengthof(premiumitems) <= STORE_PAGE_ITEMS, "S_ScrollSPBuy must fit to a single store-page."); + // stextsmax = storenumh - STORE_PAGE_ITEMS; + // if (stextsmax <= 0) stextsmax = 0; + // else + // stextsmax = ((stextsmax + STORE_LINE_ITEMS - 1) / STORE_LINE_ITEMS) * STORE_LINE_ITEMS; } static void S_StartSPBuy() @@ -563,27 +626,44 @@ static bool SmithSellOk(const ItemStruct* is) static void S_ScrollSSell() { ItemStruct* is; - int idx, l; + unsigned l; ClearSText(STORE_LIST_FIRST, STORE_LIST_FOOTER); //stextup = STORE_LIST_FIRST; - idx = stextsidx; - for (l = STORE_LIST_FIRST; l < 20; l += 4) { - is = &storehold[idx]; + is = &storehold[stextsidx]; + for (l = 0; l < STORE_PAGE_ITEMS; l++) { if (is->_itype != ITYPE_NONE) { - PrintStoreItem(is, l, true); - AddSTextVal(l, is->_iMagical != ITEM_QUALITY_NORMAL && is->_iIdentified ? is->_iIvalue : is->_ivalue); - stextdown = l; + int line = STORE_LIST_FIRST + (l / STORE_LINE_ITEMS) * STORE_ITEM_LINES; + AddSItem(60, line, l % STORE_LINE_ITEMS, is->_iCurs, TRUE); + stextdown = line; + is++; } - idx++; } if (stextsel != -1 && /*stextsel != STORE_BACK &&*/ !stextlines[stextsel]._ssel) stextsel = stextdown; - stextsmax = storenumh - 4; - if (stextsmax < 0) + if (stextsel != -1 && stextlines[stextsel]._sitemlist) { + while (stextselx >= 0 && stextlines[stextsel]._siCurs[stextselx] == CURSOR_NONE) { + stextselx--; + } + } + + is = &storehold[stextsidx]; + for (l = 0; l < STORE_PAGE_ITEMS; l++) { + if (is->_itype != ITYPE_NONE) { + if (stextsel == STORE_LIST_FIRST + (l / STORE_LINE_ITEMS) * STORE_ITEM_LINES && stextselx == l % STORE_LINE_ITEMS) { + PrintStoreItem(is, STORE_LIST_FOOTER - 3, false); + AddSTextVal(STORE_LIST_FOOTER - 3, is->_iIvalue/*is->_iMagical != ITEM_QUALITY_NORMAL && is->_iIdentified ? is->_iIvalue : is->_ivalue*/); + } + is++; + } + } + stextsmax = storenumh - STORE_PAGE_ITEMS; + if (stextsmax <= 0) stextsmax = 0; + else + stextsmax = ((stextsmax + STORE_LINE_ITEMS + 1) / STORE_LINE_ITEMS) * STORE_LINE_ITEMS; } static void S_StartSSell() @@ -697,27 +777,46 @@ static void S_StartWitch() static void S_ScrollWBuy() { ItemStruct* is; - int l; + unsigned l; ClearSText(STORE_LIST_FIRST, STORE_LIST_FOOTER); //stextup = STORE_LIST_FIRST; is = &witchitem[stextsidx]; - for (l = STORE_LIST_FIRST; l < 20; l += 4) { + for (l = 0; l < STORE_PAGE_ITEMS; l++) { if (is->_itype != ITYPE_NONE) { StorePrepareItemBuy(is); - PrintStoreItem(is, l, true); - AddSTextVal(l, is->_iIvalue); - stextdown = l; + int line = STORE_LIST_FIRST + (l / STORE_LINE_ITEMS) * STORE_ITEM_LINES; + AddSItem(60, line, l % STORE_LINE_ITEMS, is->_iCurs, TRUE); + stextdown = line; is++; } } if (stextsel != -1 && /*stextsel != STORE_BACK &&*/ !stextlines[stextsel]._ssel) stextsel = stextdown; - stextsmax = storenumh - 4; - if (stextsmax < 0) + if (stextsel != -1 && stextlines[stextsel]._sitemlist) { + while (stextselx >= 0 && stextlines[stextsel]._siCurs[stextselx] == CURSOR_NONE) { + stextselx--; + } + } + + is = &witchitem[stextsidx]; + for (l = 0; l < STORE_PAGE_ITEMS; l++) { + if (is->_itype != ITYPE_NONE) { + if (stextsel == STORE_LIST_FIRST + (l / STORE_LINE_ITEMS) * STORE_ITEM_LINES && stextselx == l % STORE_LINE_ITEMS) { + // StorePrepareItemBuy(is); + PrintStoreItem(is, STORE_LIST_FOOTER - 3, false); + AddSTextVal(STORE_LIST_FOOTER - 3, is->_iIvalue); + } + is++; + } + } + stextsmax = storenumh - STORE_PAGE_ITEMS; + if (stextsmax <= 0) stextsmax = 0; + else + stextsmax = ((stextsmax + STORE_LINE_ITEMS - 1) / STORE_LINE_ITEMS) * STORE_LINE_ITEMS; } static void S_StartWBuy() @@ -871,8 +970,9 @@ static void S_StartConfirm() // StartStore(stextshold); // ClearSText(STORE_LIST_FIRST, STORE_LINES); gbHasScroll = false; - PrintStoreItem(&storeitem, 8, false); - AddSTextVal(8, storeitem._iIvalue); + AddSItem(260, STORE_LIST_FIRST, 0, storeitem._iCurs, FALSE); + PrintStoreItem(&storeitem, STORE_LIST_FIRST - 1 + STORE_ITEM_LINES, false); + AddSTextVal(STORE_LIST_FIRST - 1 + STORE_ITEM_LINES, storeitem._iIvalue); // AddSLine(3); // AddSLine(21); @@ -944,6 +1044,7 @@ static void S_StartBBoy() gbHasScroll = false; StorePrepareItemBuy(&boyitem); + AddSItem(260, STORE_LIST_FIRST, 0, boyitem._iCurs, FALSE); PrintStoreItem(&boyitem, STORE_PEGBOY_BUY, true); AddSTextVal(STORE_PEGBOY_BUY, boyitem._iIvalue); @@ -968,27 +1069,47 @@ static void S_StartHealer() static void S_ScrollHBuy() { ItemStruct* is; - int l; + unsigned l; ClearSText(STORE_LIST_FIRST, STORE_LIST_FOOTER); //stextup = STORE_LIST_FIRST; is = &healitem[stextsidx]; - for (l = STORE_LIST_FIRST; l < 20; l += 4) { + for (l = 0; l < STORE_PAGE_ITEMS; l++) { if (is->_itype != ITYPE_NONE) { StorePrepareItemBuy(is); - PrintStoreItem(is, l, true); - AddSTextVal(l, is->_iIvalue); - stextdown = l; + int line = STORE_LIST_FIRST + (l / STORE_LINE_ITEMS) * STORE_ITEM_LINES; + AddSItem(60, line, l % STORE_LINE_ITEMS, is->_iCurs, TRUE); + stextdown = line; is++; } } if (stextsel != -1 && /*stextsel != STORE_BACK &&*/ !stextlines[stextsel]._ssel) stextsel = stextdown; - stextsmax = storenumh - 4; - if (stextsmax < 0) + if (stextsel != -1 && stextlines[stextsel]._sitemlist) { + while (stextselx >= 0 && stextlines[stextsel]._siCurs[stextselx] == CURSOR_NONE) { + stextselx--; + } + } + + is = &healitem[stextsidx]; + for (l = 0; l < STORE_PAGE_ITEMS; l++) { + if (is->_itype != ITYPE_NONE) { + if (stextsel == STORE_LIST_FIRST + (l / STORE_LINE_ITEMS) * STORE_ITEM_LINES && stextselx == l % STORE_LINE_ITEMS) { + // StorePrepareItemBuy(is); + PrintStoreItem(is, STORE_LIST_FOOTER - 3, false); + AddSTextVal(STORE_LIST_FOOTER - 3, is->_iIvalue); + } + is++; + } + } + static_assert(lengthof(healitem) <= STORE_PAGE_ITEMS, "S_ScrollHBuy must fit to a single store-page."); + // stextsmax = storenumh - STORE_PAGE_ITEMS; + // if (stextsmax <= 0) stextsmax = 0; + // else + // stextsmax = ((stextsmax + STORE_LINE_ITEMS - 1) / STORE_LINE_ITEMS) * STORE_LINE_ITEMS; } static void S_StartHBuy() @@ -1086,6 +1207,7 @@ static void S_StartIdShow() //gbRenderGold = true; gbHasScroll = false; + AddSItem(260, STORE_LIST_FIRST, 0, storeitem._iCurs, FALSE); PrintStoreItem(&storeitem, 11, false); AddStoreFrame("This item is:"); @@ -1283,8 +1405,48 @@ void StartStore(int s) } stextsel = i == STORE_LINES ? -1 : i; + stextselx = 0; } +/*void DrawStoreLineX(int sx, int sy, int dx, int dy, int length) +{ + int sxy, dxy, width; + + width = BUFFER_WIDTH; + sxy = sx + 0 + width * (sy + 0); + dxy = dx + 0 + width * dy; + + /// ASSERT: assert(gpBuffer != NULL); + + int i; + BYTE *src, *dst; + + src = &gpBuffer[sxy]; + dst = &gpBuffer[dxy]; + + for (i = 0; i < TPANEL_BORDER; i++, src += width, dst += width) + memcpy(dst, src, length); +} +void DrawStoreLineY(int sx, int sy, int dx, int dy, int height) +{ + int sxy, dxy, width; + + width = BUFFER_WIDTH; + sxy = sx + 0 + width * (sy + 0); + dxy = dx + 0 + width * dy; + + /// ASSERT: assert(gpBuffer != NULL); + + int i; + BYTE *src, *dst; + + src = &gpBuffer[sxy]; + dst = &gpBuffer[dxy]; + + for (i = 0; i < height; i++, src += width, dst += width) + memcpy(dst, src, TPANEL_BORDER); +}*/ + void DrawStore() { STextStruct* sts; @@ -1329,6 +1491,48 @@ void DrawStore() // DrawTextBoxSLine(gbWidePanel ? LTPANEL_X : STORE_PNL_X, LTPANEL_Y, i * 12 + 14, gbWidePanel); if (sts->_sstr[0] != '\0') PrintSString(sts->_sx, i, sts->_sjust, sts->_sstr, sts->_sclr, sts->_sval); + else if (sts->_sitemlist) { + for (int n = 0; n < lengthof(sts->_siCurs); n++) { + int frame = sts->_siCurs[n]; + if (frame != CURSOR_NONE) { + // int sx = (gbWidePanel ? LTPANEL_X + 7 : STORE_PNL_X + 7) + sts->_sx; + int px = LTPANEL_X, py = LTPANEL_Y + 1; + int sx = px + 7 + sts->_sx; + int sy = py + 19 + /* + 1*/ + i * 12 + sts->_syoff; + int frame_width = InvItemWidth[frame]; + + sx += n * 2 * INV_SLOT_SIZE_PX; + sy += (STORE_ITEM_LINES - (1 + 1)) * 12; + + sx += (2 * INV_SLOT_SIZE_PX - InvItemWidth[frame]) >> 1; + sy -= (3 * INV_SLOT_SIZE_PX - InvItemHeight[frame]) >> 1; + + if (stextsel == i && stextselx == n) { + // assert(gbWidePanel); + // DrawTextBoxSLine(px, py, 20 + i * 12, false); + /* + // top-left corner + DrawStoreLineX(px, py, sx + 0 * INV_SLOT_SIZE_PX, sy - 3 * INV_SLOT_SIZE_PX, INV_SLOT_SIZE_PX / 2); + DrawStoreLineY(px, py, sx + 0 * INV_SLOT_SIZE_PX, sy - 3 * INV_SLOT_SIZE_PX, INV_SLOT_SIZE_PX / 2); + // top-right corner + DrawStoreLineX(px + LTPANEL_WIDTH - INV_SLOT_SIZE_PX / 2, py, sx + 2 * INV_SLOT_SIZE_PX - INV_SLOT_SIZE_PX / 2, sy - 3 * INV_SLOT_SIZE_PX, INV_SLOT_SIZE_PX / 2); + DrawStoreLineY(px + LTPANEL_WIDTH - TPANEL_BORDER, py, sx + 2 * INV_SLOT_SIZE_PX - TPANEL_BORDER, sy - 3 * INV_SLOT_SIZE_PX, INV_SLOT_SIZE_PX / 2); + // bottom-left corner + DrawStoreLineX(px, py + TPANEL_HEIGHT - TPANEL_BORDER, sx + 0 * INV_SLOT_SIZE_PX, sy - TPANEL_BORDER, INV_SLOT_SIZE_PX / 2); + DrawStoreLineY(px, py + TPANEL_HEIGHT - TPANEL_BORDER - INV_SLOT_SIZE_PX / 2, sx + 0 * INV_SLOT_SIZE_PX, sy - INV_SLOT_SIZE_PX / 2 - TPANEL_BORDER, INV_SLOT_SIZE_PX / 2); + // bottom-right corner + DrawStoreLineX(px + LTPANEL_WIDTH - INV_SLOT_SIZE_PX / 2, py + TPANEL_HEIGHT - TPANEL_BORDER, sx + 2 * INV_SLOT_SIZE_PX - INV_SLOT_SIZE_PX / 2, sy - TPANEL_BORDER, INV_SLOT_SIZE_PX / 2); + DrawStoreLineY(px + LTPANEL_WIDTH - TPANEL_BORDER, py + TPANEL_HEIGHT - TPANEL_BORDER - INV_SLOT_SIZE_PX / 2, sx + 2 * INV_SLOT_SIZE_PX - TPANEL_BORDER, sy - INV_SLOT_SIZE_PX / 2 - TPANEL_BORDER, INV_SLOT_SIZE_PX / 2); + */ + CelClippedDrawOutline(ICOL_YELLOW, sx, sy, pCursCels, frame, frame_width); + } + + // sx += (2 * INV_SLOT_SIZE_PX - InvItemWidth[frame]) >> 1; + // sy -= (3 * INV_SLOT_SIZE_PX - InvItemHeight[frame]) >> 1; + CelClippedDrawLightTbl(sx, sy, pCursCels, frame, frame_width, 0 /* COLOR_TRN_RED */); + } + } + } } // if (gbRenderGold) { @@ -1360,6 +1564,7 @@ void STextESC() StartStore(stextshold); // stextflag = stextshold; stextsel = stextlhold; + // stextselx = stextxhold; // stextsidx = stextvhold; break; case STORE_SBUY: @@ -1411,6 +1616,7 @@ void STextESC() StartStore(stextshold); // stextflag = stextshold; stextsel = stextlhold; + stextselx = stextxhold; stextsidx = stextvhold; break; case STORE_ERRAND: @@ -1428,8 +1634,10 @@ void STextUp() DEBUG_ASSERT(stextsel != -1); if (gbHasScroll && stextsel == STORE_LIST_FIRST) { - if (stextsidx != 0) - stextsidx--; + if (stextsidx != 0) { + DEBUG_ASSERT(stextlines[stextsel]._sitemlist); + stextsidx -= STORE_LINE_ITEMS; + } return; } @@ -1446,8 +1654,10 @@ void STextDown() DEBUG_ASSERT(stextsel != -1); if (gbHasScroll && stextsel == stextdown) { - if (stextsidx < stextsmax) - stextsidx++; + if (stextsidx < stextsmax) { + DEBUG_ASSERT(stextlines[stextsel]._sitemlist); + stextsidx += STORE_LINE_ITEMS; + } return; } @@ -1458,12 +1668,43 @@ void STextDown() } while (!stextlines[stextsel]._ssel); } +void STextRight() +{ + DEBUG_ASSERT(stextsel != -1); + if (/*stextsel == -1 || */!stextlines[stextsel]._sitemlist) { + return; + } + PlaySFX(IS_TITLEMOV); + + do { + stextselx++; + if (stextselx == STORE_LINE_ITEMS) + stextselx = 0; + } while (stextlines[stextsel]._siCurs[stextselx] == CURSOR_NONE); +} + +void STextLeft() +{ + DEBUG_ASSERT(stextsel != -1); + if (/*stextsel == -1 || */!stextlines[stextsel]._sitemlist) { + return; + } + PlaySFX(IS_TITLEMOV); + + do { + stextselx--; + if (stextselx < 0) + stextselx = STORE_LINE_ITEMS - 1; + } while (stextlines[stextsel]._siCurs[stextselx] == CURSOR_NONE); +} + void STextPageUp() { DEBUG_ASSERT(stextsel != -1); if (gbHasScroll) { + DEBUG_ASSERT(stextsidx == 0 || stextlines[stextsel]._sitemlist); PlaySFX(IS_TITLEMOV); - stextsidx -= 4; + stextsidx -= STORE_PAGE_ITEMS; if (stextsidx < 0) { stextsidx = 0; stextsel = STORE_LIST_FIRST; @@ -1475,8 +1716,9 @@ void STextPageDown() { DEBUG_ASSERT(stextsel != -1); if (gbHasScroll) { + DEBUG_ASSERT(stextsmax == 0 || stextlines[stextsel]._sitemlist); PlaySFX(IS_TITLEMOV); - stextsidx += 4; + stextsidx += STORE_PAGE_ITEMS; if (stextsidx > stextsmax) { stextsidx = stextsmax; stextsel = stextdown; @@ -1490,6 +1732,7 @@ static void S_SmithEnter() case STORE_SMITH_GOSSIP: DEBUG_ASSERT(stextflag == STORE_SMITH); stextlhold = STORE_SMITH_GOSSIP; + // stextxhold = stextselx; // stextvhold = stextsidx; stextshold = STORE_SMITH; talker = TOWN_SMITH; @@ -1569,7 +1812,7 @@ static void SmithBuyItem() SendStoreCmd2(STORE_SBUY); - idx = stextvhold + ((stextlhold - STORE_LIST_FIRST) >> 2); + idx = stextvhold + ((stextlhold - STORE_LIST_FIRST) / STORE_ITEM_LINES) * STORE_LINE_ITEMS + stextxhold; do { copy_pod(smithitem[idx], smithitem[idx + 1]); idx++; @@ -1601,9 +1844,10 @@ static void S_SBuyEnter() } else { DEBUG_ASSERT(stextflag == STORE_SBUY); stextlhold = stextsel; + stextxhold = stextselx; stextvhold = stextsidx; stextshold = STORE_SBUY; - idx = stextsidx + ((stextsel - STORE_LIST_FIRST) >> 2); + idx = stextsidx + ((stextsel - STORE_LIST_FIRST) / STORE_ITEM_LINES) * STORE_LINE_ITEMS + stextselx; StoreStartBuy(&smithitem[idx], smithitem[idx]._iIvalue); } } @@ -1617,7 +1861,7 @@ static void SmithBuyPItem() SendStoreCmd2(STORE_SPBUY); - idx = stextvhold + ((stextlhold - STORE_LIST_FIRST) >> 2); + idx = stextvhold + ((stextlhold - STORE_LIST_FIRST) / STORE_ITEM_LINES) * STORE_LINE_ITEMS + stextxhold; xx = 0; for (i = 0; idx >= 0; i++) { if (premiumitems[i]._itype != ITYPE_NONE) { @@ -1642,9 +1886,10 @@ static void S_SPBuyEnter() } else { DEBUG_ASSERT(stextflag == STORE_SPBUY); stextlhold = stextsel; + stextxhold = stextselx; stextvhold = stextsidx; stextshold = STORE_SPBUY; - xx = stextsidx + ((stextsel - STORE_LIST_FIRST) >> 2); + xx = stextsidx + ((stextsel - STORE_LIST_FIRST) / STORE_ITEM_LINES) * STORE_LINE_ITEMS + stextselx; idx = 0; for (i = 0; xx >= 0; i++) { if (premiumitems[i]._itype != ITYPE_NONE) { @@ -1837,6 +2082,7 @@ void SyncStoreCmd(int pnum, int cmd, int ii, int price) // stextflag = stextshold; -- except for wirt's redirect stextsel = stextlhold; + stextselx = stextxhold; stextsidx = stextvhold; if (stextsidx > stextsmax) { stextsidx = stextsmax; @@ -1846,6 +2092,11 @@ void SyncStoreCmd(int pnum, int cmd, int ii, int price) stextsel--; DEBUG_ASSERT(stextsel != -1); } + if (/*stextsel != -1 && */ stextlines[stextsel]._sitemlist) { + while (stextselx >= 0 && stextlines[stextsel]._siCurs[stextselx] == CURSOR_NONE) { + stextselx--; + } + } } /** @@ -1855,7 +2106,7 @@ static void StoreSellItem() { int i, idx, cost; - idx = stextvhold + ((stextlhold - STORE_LIST_FIRST) >> 2); + idx = stextvhold + ((stextlhold - STORE_LIST_FIRST) / STORE_ITEM_LINES) * STORE_LINE_ITEMS + stextxhold; i = storehidx[idx]; if (i >= 0) { i += INVITEM_INV_FIRST; @@ -1871,10 +2122,11 @@ static void S_SSell() int idx; stextlhold = stextsel; + stextxhold = stextselx; stextvhold = stextsidx; stextshold = stextflag; - idx = stextsidx + ((stextsel - STORE_LIST_FIRST) >> 2); + idx = stextsidx + ((stextsel - STORE_LIST_FIRST) / STORE_ITEM_LINES) * STORE_LINE_ITEMS + stextselx; copy_pod(storeitem, storehold[idx]); idx = storehidx[idx] >= 0 ? storeitem._iCurs + CURSOR_FIRSTITEM : CURSOR_NONE; @@ -1902,7 +2154,7 @@ static void SmithRepairItem() { int i, idx; - idx = stextvhold + ((stextlhold - STORE_LIST_FIRST) >> 2); + idx = stextvhold + ((stextlhold - STORE_LIST_FIRST) / STORE_ITEM_LINES) * STORE_LINE_ITEMS + stextxhold; i = storehidx[idx]; if (i < 0) { @@ -1925,9 +2177,10 @@ static void S_SRepairEnter() } else { DEBUG_ASSERT(stextflag == STORE_SREPAIR); stextlhold = stextsel; + stextxhold = stextselx; stextvhold = stextsidx; stextshold = STORE_SREPAIR; - idx = stextsidx + ((stextsel - STORE_LIST_FIRST) >> 2); + idx = stextsidx + ((stextsel - STORE_LIST_FIRST) / STORE_ITEM_LINES) * STORE_LINE_ITEMS + stextselx; copy_pod(storeitem, storehold[idx]); if (myplr._pGold < storehold[idx]._iIvalue) StartStore(STORE_NOMONEY); @@ -1942,6 +2195,7 @@ static void S_WitchEnter() case STORE_WITCH_GOSSIP: DEBUG_ASSERT(stextflag == STORE_WITCH); stextlhold = STORE_WITCH_GOSSIP; + // stextxhold = stextselx; // stextvhold = stextsidx; stextshold = STORE_WITCH; talker = TOWN_WITCH; @@ -1972,7 +2226,7 @@ static void WitchBuyItem() { int idx; - idx = stextvhold + ((stextlhold - STORE_LIST_FIRST) >> 2); + idx = stextvhold + ((stextlhold - STORE_LIST_FIRST) / STORE_ITEM_LINES) * STORE_LINE_ITEMS + stextxhold; if (idx < 3) storeitem._iSeed = NextRndSeed(); @@ -1998,9 +2252,10 @@ static void S_WBuyEnter() } else { DEBUG_ASSERT(stextflag == STORE_WBUY); stextlhold = stextsel; + stextxhold = stextselx; stextvhold = stextsidx; stextshold = STORE_WBUY; - idx = stextsidx + ((stextsel - STORE_LIST_FIRST) >> 2); + idx = stextsidx + ((stextsel - STORE_LIST_FIRST) / STORE_ITEM_LINES) * STORE_LINE_ITEMS + stextselx; StoreStartBuy(&witchitem[idx], witchitem[idx]._iIvalue); } @@ -2024,7 +2279,7 @@ static void WitchRechargeItem() { int i, idx; - idx = stextvhold + ((stextlhold - STORE_LIST_FIRST) >> 2); + idx = stextvhold + ((stextlhold - STORE_LIST_FIRST) / STORE_ITEM_LINES) * STORE_LINE_ITEMS + stextxhold; i = storehidx[idx]; if (i < 0) { @@ -2046,9 +2301,10 @@ static void S_WRechargeEnter() } else { DEBUG_ASSERT(stextflag == STORE_WRECHARGE); stextlhold = stextsel; + stextxhold = stextselx; stextvhold = stextsidx; stextshold = STORE_WRECHARGE; - idx = stextsidx + ((stextsel - STORE_LIST_FIRST) >> 2); + idx = stextsidx + ((stextsel - STORE_LIST_FIRST) / STORE_ITEM_LINES) * STORE_LINE_ITEMS + stextselx; copy_pod(storeitem, storehold[idx]); if (myplr._pGold < storehold[idx]._iIvalue) StartStore(STORE_NOMONEY); @@ -2063,6 +2319,7 @@ static void S_BoyEnter() if (boyitem._itype != ITYPE_NONE) { if (stextsel == STORE_PEGBOY_QUERY) { stextlhold = STORE_PEGBOY_QUERY; + // stextxhold = stextselx; stextvhold = stextsidx; stextshold = STORE_PEGBOY; if (boyitem._iIdentified) { @@ -2086,6 +2343,7 @@ static void S_BoyEnter() } } stextlhold = stextsel; + // stextxhold = stextselx; // stextvhold = stextsidx; stextshold = STORE_PEGBOY; talker = TOWN_PEGBOY; @@ -2107,7 +2365,7 @@ static void HealerBuyItem() int idx; bool infinite; - idx = stextvhold + ((stextlhold - STORE_LIST_FIRST) >> 2); + idx = stextvhold + ((stextlhold - STORE_LIST_FIRST) / STORE_ITEM_LINES) * STORE_LINE_ITEMS + stextxhold; infinite = idx < (IsMultiGame ? 3 : 2); if (infinite) storeitem._iSeed = NextRndSeed(); @@ -2133,6 +2391,7 @@ static void S_BBuyEnter() DEBUG_ASSERT(stextflag == STORE_PBUY); DEBUG_ASSERT(stextsel == STORE_PEGBOY_BUY); stextlhold = STORE_PEGBOY_BUY; + // stextxhold = stextselx; stextvhold = stextsidx; stextshold = STORE_PBUY; StoreStartBuy(&boyitem, boyitem._iIvalue); @@ -2143,7 +2402,7 @@ static void StoryIdItem() { int idx; - idx = stextvhold + ((stextlhold - STORE_LIST_FIRST) >> 2); + idx = stextvhold + ((stextlhold - STORE_LIST_FIRST) / STORE_ITEM_LINES) * STORE_LINE_ITEMS + stextxhold; idx = storehidx[idx]; if (idx < 0) idx = INVITEM_BODY_FIRST - (idx + 1); @@ -2206,6 +2465,7 @@ static void S_HealerEnter() case STORE_HEALER_GOSSIP: DEBUG_ASSERT(stextflag == STORE_HEALER); stextlhold = STORE_HEALER_GOSSIP; + // stextxhold = stextselx; // stextvhold = stextsidx; stextshold = STORE_HEALER; talker = TOWN_HEALER; @@ -2240,9 +2500,10 @@ static void S_HBuyEnter() } else { DEBUG_ASSERT(stextflag == STORE_HBUY); stextlhold = stextsel; + stextxhold = stextselx; stextvhold = stextsidx; stextshold = STORE_HBUY; - idx = stextsidx + ((stextsel - STORE_LIST_FIRST) >> 2); + idx = stextsidx + ((stextsel - STORE_LIST_FIRST) / STORE_ITEM_LINES) * STORE_LINE_ITEMS + stextselx; StoreStartBuy(&healitem[idx], healitem[idx]._iIvalue); } } @@ -2253,6 +2514,7 @@ static void S_StoryEnter() case STORE_STORY_GOSSIP: DEBUG_ASSERT(stextflag == STORE_STORY); stextlhold = STORE_STORY_GOSSIP; + // stextxhold = stextselx; // stextvhold = stextsidx; stextshold = STORE_STORY; talker = TOWN_STORY; @@ -2281,9 +2543,10 @@ static void S_SIDEnter() } else { DEBUG_ASSERT(stextflag == STORE_SIDENTIFY); stextlhold = stextsel; + stextxhold = stextselx; stextvhold = stextsidx; stextshold = STORE_SIDENTIFY; - idx = stextsidx + ((stextsel - STORE_LIST_FIRST) >> 2); + idx = stextsidx + ((stextsel - STORE_LIST_FIRST) / STORE_ITEM_LINES) * STORE_LINE_ITEMS + stextselx; copy_pod(storeitem, storehold[idx]); if (myplr._pGold < storehold[idx]._iIvalue) StartStore(STORE_NOMONEY); @@ -2340,6 +2603,7 @@ static void S_TavernEnter() case STORE_TAVERN_GOSSIP: DEBUG_ASSERT(stextflag == STORE_TAVERN); stextlhold = STORE_TAVERN_GOSSIP; + // stextxhold = stextselx; // stextvhold = stextsidx; stextshold = STORE_TAVERN; talker = TOWN_TAVERN; @@ -2360,6 +2624,7 @@ static void S_BarmaidEnter() case STORE_BARMAID_GOSSIP: DEBUG_ASSERT(stextflag == STORE_BARMAID); stextlhold = STORE_BARMAID_GOSSIP; + // stextxhold = stextselx; // stextvhold = stextsidx; stextshold = STORE_BARMAID; talker = TOWN_BARMAID; @@ -2380,6 +2645,7 @@ static void S_DrunkEnter() case STORE_DRUNK_GOSSIP: DEBUG_ASSERT(stextflag == STORE_DRUNK); stextlhold = STORE_DRUNK_GOSSIP; + // stextxhold = stextselx; // stextvhold = stextsidx; stextshold = STORE_DRUNK; talker = TOWN_DRUNK; @@ -2400,6 +2666,7 @@ static void S_PriestEnter() /*case STORE_PRIEST_GOSSIP: DEBUG_ASSERT(stextflag == STORE_PRIEST); stextlhold = STORE_PRIEST_GOSSIP; + // stextxhold = stextselx; // stextvhold = stextsidx; stextshold = STORE_PRIEST; talker = TOWN_PRIEST; @@ -2471,6 +2738,7 @@ void STextEnter() // StartStore(stextshold); // // stextflag = stextshold; // stextsel = stextlhold; + // stextselx = stextxhold; // stextsidx = stextvhold; break; case STORE_CONFIRM: @@ -2579,14 +2847,36 @@ void TryStoreBtnClick() if (y >= 22) y = 22; // allow clicking on multi-line items - else if (gbHasScroll /*&& y < 21*/ && !stextlines[y]._ssel) { - y--; - if (!stextlines[y]._ssel) { + else if (gbHasScroll /*&& y < 21*/ /*&& !stextlines[y]._ssel*/) { + y++; + for (int n = 0; n < STORE_ITEM_LINES; n++) { + if (stextlines[y]._ssel) + break; y--; + if (y == 0) + break; } } //if (stextlines[y]._ssel || (gbHasScroll && y == STORE_BACK)) { if (stextlines[y]._ssel) { + if (stextlines[y]._sitemlist) { + int x = MousePos.x - (LTPANEL_X + 7 + 60 - SCREEN_X); + if (x >= 0) { + x /= (2 * INV_SLOT_SIZE_PX); + if (x < lengthof(stextlines[y]._siCurs)) { + if (stextlines[y]._siCurs[x] != CURSOR_NONE) { + // EventPlrMsg("clicked pos %d:%d", x, y); + stextselx = x; + } else { + return; + } + } else { + return; + } + } else { + return; + } + } stextsel = y; STextEnter(); } diff --git a/Source/stores.h b/Source/stores.h index e965f6939e0..23573f9d9ac 100644 --- a/Source/stores.h +++ b/Source/stores.h @@ -43,6 +43,8 @@ void DrawStore(); void STextESC(); void STextUp(); void STextDown(); +void STextRight(); +void STextLeft(); void STextPageUp(); void STextPageDown(); void SyncStoreCmd(int pnum, int cmd, int ii, int price); diff --git a/structs.h b/structs.h index 34769ab20ad..0c0f384b276 100644 --- a/structs.h +++ b/structs.h @@ -2622,7 +2622,14 @@ typedef struct TriggerStruct { typedef struct STextStruct { int _sx; // starting position int _syoff; // y-offset where the text should be printed - char _sstr[112]; // the text + union { + char _sstr[112]; // the text + struct { + char _schr; // placeholder to differentiate from a normal text + int _siCurs[8]; // the list of item cursors (cursor_id) to be drawn + }; + }; + bool _sitemlist; // whether items should be drawn bool _sjust; // whether the string should be justified BYTE _sclr; // the color of the string // bool _sline; From 350737d9aa54ccc9f0e3e582f50545540d2ee7d5 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 7 Aug 2024 12:29:57 +0200 Subject: [PATCH 396/596] adjust monster levels to match the dungeon levels more closely --- Source/monstdat.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/monstdat.cpp b/Source/monstdat.cpp index 3b3f57df5d9..f6c4b33ab0f 100644 --- a/Source/monstdat.cpp +++ b/Source/monstdat.cpp @@ -72,9 +72,9 @@ const MonsterData monsterdata[NUM_MTYPES] = { /* MT_CAVSLUG*/// { MOFILE_WORM, 0, 3, NULL, "Cave Slug", { AI_SKELSD, 1, 0, 0 }, 75, 110, 0 , 50, 6, 13, 0, 0, 0, 0, 0, 30, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_ACID_IMMUNE, 662, ALIGN }, // MC_ANIMAL, /* MT_DVLWYRM*/// { MOFILE_WORM, 0, 3, NULL, "Devil Wyrm", { AI_SKELSD, 2, 0, 0 }, 100, 140, 0 , 55, 8, 16, 0, 0, 0, 0, 0, 30, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 880, ALIGN }, // MC_ANIMAL, /* MT_DEVOUR*/// { MOFILE_WORM, 0, 3, NULL, "Devourer", { AI_SKELSD, 3, 0, 0 }, 125, 200, 0 , 60, 10, 20, 0, 0, 0, 0, 0, 35, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 1218, ALIGN }, // MC_ANIMAL, -/* MT_NMAGMA */ { MOFILE_MAGMA, 13, 7, NULL, "Magma Demon", { AI_ROUNDRANGED, 0, MIS_MAGMABALL, 0 }, 50, 70, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 45, 2, 10, 0, 0, 0, 35, 0, 45, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 717, ALIGN }, // MC_DEMON, -/* MT_YMAGMA */ { MOFILE_MAGMA, 14, 7, "Monsters\\Magma\\Yellow.TRN", "Blood Stone", { AI_ROUNDRANGED, 1, MIS_MAGMABALL, 0 }, 55, 75, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 50, 2, 12, 0, 0, 0, 40, 0, 45, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 872, ALIGN }, // MC_DEMON, -/* MT_BMAGMA */ { MOFILE_MAGMA, 16, 7, "Monsters\\Magma\\Blue.TRN", "Hell Stone", { AI_ROUNDRANGED, 2, MIS_MAGMABALL, 0 }, 60, 80, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 60, 2, 20, 0, 0, 0, 45, 0, 50, 45, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 1120, ALIGN }, // MC_DEMON, +/* MT_NMAGMA */ { MOFILE_MAGMA, 15, 7, NULL, "Magma Demon", { AI_ROUNDRANGED, 0, MIS_MAGMABALL, 0 }, 55, 70, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 50, 2, 10, 0, 0, 0, 35, 0, 45, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 717, ALIGN }, // MC_DEMON, +/* MT_YMAGMA */ { MOFILE_MAGMA, 16, 7, "Monsters\\Magma\\Yellow.TRN", "Blood Stone", { AI_ROUNDRANGED, 1, MIS_MAGMABALL, 0 }, 60, 75, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 55, 2, 12, 0, 0, 0, 40, 0, 45, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 872, ALIGN }, // MC_DEMON, +/* MT_BMAGMA */ { MOFILE_MAGMA, 17, 7, "Monsters\\Magma\\Blue.TRN", "Hell Stone", { AI_ROUNDRANGED, 2, MIS_MAGMABALL, 0 }, 65, 80, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 65, 3, 20, 0, 0, 0, 45, 0, 55, 45, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 1180, ALIGN }, // MC_DEMON, /* MT_WMAGMA */ { MOFILE_MAGMA, 18, 7, "Monsters\\Magma\\Wierd.TRN", "Lava Lord", { AI_ROUNDRANGED, 3, MIS_MAGMABALL, 0 }, 70, 85, MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 75, 4, 24, 0, 0, 0, 50, 0, 60, 50, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 1416, ALIGN }, // MC_DEMON, /* MT_NRHINO */ { MOFILE_RHINO, 13, 7, NULL, "Horned Demon", { AI_RHINO, 0, 0, 0 }, 40, 80, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 60, 2, 16, 0, 5, 32, 0, 0, 40, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 781, ALIGN }, // MC_ANIMAL, /* MT_XRHINO */ { MOFILE_RHINO, 15, 7, "Monsters\\Rhino\\Orange.TRN", "Mud Runner", { AI_RHINO, 1, 0, 0 }, 50, 90, MFLAG_SEARCH | MFLAG_CAN_BLEED | MFLAG_CAN_OPEN_DOOR, 70, 6, 18, 0, 12, 36, 0, 0, 45, 20, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, 936, ALIGN }, // MC_ANIMAL, @@ -102,7 +102,7 @@ const MonsterData monsterdata[NUM_MTYPES] = { /* MT_NSNAKE */ { MOFILE_SNAKE, 21, 7, NULL, "Cave Viper", { AI_SNAKE, 0, 0, 0 }, 100, 150, MFLAG_SEARCH , 90, 8, 20, 0, 16, 40, 0, 0, 60, 50, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_ACID_IMMUNE, 1816, ALIGN }, // MC_DEMON, /* MT_RSNAKE */ { MOFILE_SNAKE, 23, 7, "Monsters\\Snake\\SnakR.TRN", "Fire Drake", { AI_SNAKE, 1, 0, 0 }, 120, 170, MFLAG_SEARCH , 105, 12, 24, 0, 24, 48, 0, 0, 65, 50, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 2092, ALIGN }, // MC_DEMON, /* MT_BSNAKE */ { MOFILE_SNAKE, 25, 7, "Monsters\\Snake\\Snakg.TRN", "Gold Viper", { AI_SNAKE, 2, 0, 0 }, 140, 180, MFLAG_SEARCH , 120, 15, 26, 0, 30, 52, 0, 0, 70, 50, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2360, ALIGN }, // MC_DEMON, -/* MT_GSNAKE */ { MOFILE_SNAKE, 27, 7, "Monsters\\Snake\\Snakb.TRN", "Azure Drake", { AI_SNAKE, 3, 0, 0 }, 160, 200, MFLAG_SEARCH , 130, 18, 30, 0, 36, 60, 0, 0, 75, 55, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2527, ALIGN }, // MC_DEMON, +/* MT_GSNAKE */ { MOFILE_SNAKE, 29, 7, "Monsters\\Snake\\Snakb.TRN", "Azure Drake", { AI_SNAKE, 3, 0, 0 }, 180, 220, MFLAG_SEARCH , 130, 20, 32, 0, 38, 64, 0, 0, 75, 55, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2727, ALIGN }, // MC_DEMON, /* MT_NBLACK */ { MOFILE_BLACK, 24, 7, NULL, "Black Knight", { AI_SKELSD, 0, 0, 0 }, 150, 150, MFLAG_SEARCH , 110, 15, 20, 0, 0, 0, 0, 0, 75, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 2240, ALIGN }, // MC_DEMON, /* MT_RBLACK */ { MOFILE_BLACK, 26, 7, "Monsters\\Black\\BlkKntRT.TRN", "Doom Guard", { AI_SKELSD, 0, 0, 0 }, 165, 165, MFLAG_SEARCH , 130, 18, 25, 0, 0, 0, 0, 0, 75, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_ACID_IMMUNE, 2433, ALIGN }, // MC_DEMON, /* MT_BBLACK */ { MOFILE_BLACK, 28, 7, "Monsters\\Black\\BlkKntBT.TRN", "Steel Lord", { AI_SKELSD, 1, 0, 0 }, 180, 180, MFLAG_SEARCH , 120, 20, 30, 0, 0, 0, 0, 0, 80, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2834, ALIGN }, // MC_DEMON, From 5780e5be38f2023973c6cafa29fb95c0dc6a4da3 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 8 Aug 2024 07:16:18 +0200 Subject: [PATCH 397/596] get rid of stextup (stores) --- Source/stores.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index 7f5cd1ebfa7..2f4dd0038f8 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -115,8 +115,6 @@ static bool gbHasScroll; static int stextsidx; /** The line number of the last visible item in the store */ static int stextdown; -/** Previous scroll position */ -//static int stextup; /** Remember stextflag while displaying a dialog */ static int stextshold; /** Text lines */ @@ -439,7 +437,6 @@ static void S_ScrollSBuy() unsigned l; ClearSText(STORE_LIST_FIRST, STORE_LIST_FOOTER); - //stextup = STORE_LIST_FIRST; is = &smithitem[stextsidx]; for (l = 0; l < STORE_PAGE_ITEMS; l++) { @@ -514,7 +511,6 @@ static void S_ScrollSPBuy() unsigned idx, l, boughtitems; ClearSText(STORE_LIST_FIRST, STORE_LIST_FOOTER); - //stextup = STORE_LIST_FIRST; boughtitems = stextsidx; for (idx = 0; boughtitems != 0; idx++) @@ -629,7 +625,6 @@ static void S_ScrollSSell() unsigned l; ClearSText(STORE_LIST_FIRST, STORE_LIST_FOOTER); - //stextup = STORE_LIST_FIRST; is = &storehold[stextsidx]; for (l = 0; l < STORE_PAGE_ITEMS; l++) { @@ -780,7 +775,6 @@ static void S_ScrollWBuy() unsigned l; ClearSText(STORE_LIST_FIRST, STORE_LIST_FOOTER); - //stextup = STORE_LIST_FIRST; is = &witchitem[stextsidx]; for (l = 0; l < STORE_PAGE_ITEMS; l++) { @@ -1072,7 +1066,6 @@ static void S_ScrollHBuy() unsigned l; ClearSText(STORE_LIST_FIRST, STORE_LIST_FOOTER); - //stextup = STORE_LIST_FIRST; is = &healitem[stextsidx]; for (l = 0; l < STORE_PAGE_ITEMS; l++) { From d5f68f505b4983778f6e929fbbc4858ee42ec985 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 8 Aug 2024 07:19:14 +0200 Subject: [PATCH 398/596] initialize gbHasScroll in StartStore --- Source/stores.cpp | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index 2f4dd0038f8..b92d45e9d3f 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -191,7 +191,7 @@ void InitStoresOnce() stextflag = STORE_NONE; gbWidePanel = false; // gbRenderGold = false; - gbHasScroll = false; + // gbHasScroll = false; numpremium = 0; premiumlevel = StoresLimitedItemLvl(); // assert((premiumlevel + premiumlvladd[0]) >= 1); @@ -411,7 +411,7 @@ static void S_StartSmith() { gbWidePanel = false; // gbRenderGold = false; - gbHasScroll = false; + // gbHasScroll = false; AddSText(0, 1, true, "Welcome to the", COL_GOLD, false); AddSText(0, 3, true, "Blacksmith's shop", COL_GOLD, false); AddSText(0, 7, true, "Would you like to:", COL_GOLD, false); @@ -757,7 +757,7 @@ static void S_StartWitch() { gbWidePanel = false; // gbRenderGold = false; - gbHasScroll = false; + // gbHasScroll = false; AddSText(0, 2, true, "Witch's shack", COL_GOLD, false); AddSText(0, 9, true, "Would you like to:", COL_GOLD, false); @@ -932,7 +932,7 @@ static void S_StartNoMoney() { // StartStore(stextshold); // ClearSText(STORE_LIST_FIRST, STORE_LINES); - gbHasScroll = false; + // gbHasScroll = false; gbWidePanel = true; // gbRenderGold = true; AddSText(0, 14, true, "You do not have enough gold", COL_WHITE, true); @@ -945,7 +945,7 @@ static void S_StartNoRoom() { // StartStore(stextshold); // ClearSText(STORE_LIST_FIRST, STORE_LINES); - gbHasScroll = false; + // gbHasScroll = false; AddSText(0, 14, true, "You do not have enough room in inventory", COL_WHITE, true); // AddSLine(3); @@ -963,7 +963,7 @@ static void S_StartConfirm() { // StartStore(stextshold); // ClearSText(STORE_LIST_FIRST, STORE_LINES); - gbHasScroll = false; + // gbHasScroll = false; AddSItem(260, STORE_LIST_FIRST, 0, storeitem._iCurs, FALSE); PrintStoreItem(&storeitem, STORE_LIST_FIRST - 1 + STORE_ITEM_LINES, false); AddSTextVal(STORE_LIST_FIRST - 1 + STORE_ITEM_LINES, storeitem._iIvalue); @@ -1006,7 +1006,7 @@ static void S_StartBoy() { gbWidePanel = false; // gbRenderGold = false; - gbHasScroll = false; + // gbHasScroll = false; AddSText(0, 2, true, "Wirt the Peg-legged boy", COL_GOLD, false); // AddSLine(5); if (boyitem._itype != ITYPE_NONE) { @@ -1035,7 +1035,7 @@ static void S_StartBBoy() } gbWidePanel = true; // gbRenderGold = true; - gbHasScroll = false; + // gbHasScroll = false; StorePrepareItemBuy(&boyitem); AddSItem(260, STORE_LIST_FIRST, 0, boyitem._iCurs, FALSE); @@ -1049,7 +1049,7 @@ static void S_StartHealer() { gbWidePanel = false; // gbRenderGold = false; - gbHasScroll = false; + // gbHasScroll = false; AddSText(0, 1, true, "Welcome to the", COL_GOLD, false); AddSText(0, 3, true, "Healer's home", COL_GOLD, false); AddSText(0, 9, true, "Would you like to:", COL_GOLD, false); @@ -1126,7 +1126,7 @@ static void S_StartStory() { gbWidePanel = false; // gbRenderGold = false; - gbHasScroll = false; + // gbHasScroll = false; AddSText(0, 2, true, "The Town Elder", COL_GOLD, false); AddSText(0, 9, true, "Would you like to:", COL_GOLD, false); AddSText(0, STORE_STORY_GOSSIP, true, "Talk to Cain", COL_BLUE, true); @@ -1198,7 +1198,7 @@ static void S_StartIdShow() //gbWidePanel = true; //gbRenderGold = true; - gbHasScroll = false; + // gbHasScroll = false; AddSItem(260, STORE_LIST_FIRST, 0, storeitem._iCurs, FALSE); PrintStoreItem(&storeitem, 11, false); @@ -1212,7 +1212,7 @@ static void S_StartTalk() gbWidePanel = false; // gbRenderGold = false; - gbHasScroll = false; + // gbHasScroll = false; snprintf(tempstr, sizeof(tempstr), "Talk to %s", talkname[talker]); AddSText(0, 2, true, tempstr, COL_GOLD, false); // AddSLine(5); @@ -1244,7 +1244,7 @@ static void S_StartTavern() { gbWidePanel = false; // gbRenderGold = false; - gbHasScroll = false; + // gbHasScroll = false; AddSText(0, 1, true, "Welcome to the", COL_GOLD, false); AddSText(0, 3, true, "Rising Sun", COL_GOLD, false); AddSText(0, 9, true, "Would you like to:", COL_GOLD, false); @@ -1257,7 +1257,7 @@ static void S_StartBarMaid() { gbWidePanel = false; // gbRenderGold = false; - gbHasScroll = false; + // gbHasScroll = false; AddSText(0, 2, true, "Gillian", COL_GOLD, false); AddSText(0, 9, true, "Would you like to:", COL_GOLD, false); AddSText(0, STORE_BARMAID_GOSSIP, true, "Talk to Gillian", COL_BLUE, true); @@ -1269,7 +1269,7 @@ static void S_StartDrunk() { gbWidePanel = false; // gbRenderGold = false; - gbHasScroll = false; + // gbHasScroll = false; AddSText(0, 2, true, "Farnham the Drunk", COL_GOLD, false); AddSText(0, 9, true, "Would you like to:", COL_GOLD, false); AddSText(0, STORE_DRUNK_GOSSIP, true, "Talk to Farnham", COL_BLUE, true); @@ -1281,7 +1281,7 @@ static void S_StartPriest() { gbWidePanel = false; // gbRenderGold = false; - gbHasScroll = false; + // gbHasScroll = false; AddSText(0, 2, true, "Tremain the Priest", COL_GOLD, false); AddSText(0, 9, true, "Would you like to:", COL_GOLD, false); AddSText(0, STORE_PRIEST_ERRAND, true, "Run errand", COL_BLUE, true); @@ -1291,6 +1291,7 @@ static void S_StartPriest() static void S_StartErrand() { + // gbHasScroll = false; AddSText(0, 2, true, "Tremain the Priest", COL_GOLD, false); // AddSText(0, 12, true, "Would you like to", COL_WHITE, false); AddSText(0, 14, true, "Go on an errand?", COL_WHITE, false); @@ -1307,6 +1308,7 @@ void StartStore(int s) ReleaseStoreBtn(); stextflag = s; stextsidx = 0; + gbHasScroll = false; switch (s) { case STORE_SMITH: S_StartSmith(); From 9784dff95d26c9c167dd55396d38e7cbd17d2218 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 8 Aug 2024 07:22:21 +0200 Subject: [PATCH 399/596] cleanup gbHasScroll setters (stores) --- Source/stores.cpp | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index b92d45e9d3f..0b02070f5c8 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -487,15 +487,14 @@ static void S_StartSBuy() gbWidePanel = true; // gbRenderGold = true; + gbHasScroll = storenumh != 0; if (storenumh == 0) { //StartStore(STORE_SMITH); //stextshold = STORE_SMITH; //stextsel = STORE_SMITH_BUY; //return false; - gbHasScroll = false; msg = "I have no basic item for sale."; } else { - gbHasScroll = true; // stextsidx = 0; S_ScrollSBuy(); @@ -571,15 +570,14 @@ static void S_StartSPBuy() gbWidePanel = true; // gbRenderGold = true; + gbHasScroll = storenumh != 0; if (storenumh == 0) { //StartStore(STORE_SMITH); //stextshold = STORE_SMITH; //stextsel = STORE_SMITH_SPBUY; //return false; - gbHasScroll = false; msg = "I have no premium item for sale."; } else { - gbHasScroll = true; // stextsidx = 0; S_ScrollSPBuy(); @@ -680,11 +678,10 @@ static void S_StartSSell() gbWidePanel = true; // gbRenderGold = true; + gbHasScroll = storenumh != 0; if (storenumh == 0) { - gbHasScroll = false; msg = "You have nothing I want."; } else { - gbHasScroll = true; // stextsidx = 0; S_ScrollSSell(); @@ -740,11 +737,10 @@ static void S_StartSRepair() gbWidePanel = true; // gbRenderGold = true; + gbHasScroll = storenumh != 0; if (storenumh == 0) { - gbHasScroll = false; msg = "You have nothing to repair."; } else { - gbHasScroll = true; // stextsidx = 0; S_ScrollSSell(); @@ -862,11 +858,10 @@ static void S_StartWSell() gbWidePanel = true; // gbRenderGold = true; + gbHasScroll = storenumh != 0; if (storenumh == 0) { - gbHasScroll = false; msg = "You have nothing I want."; } else { - gbHasScroll = true; // stextsidx = 0; S_ScrollSSell(); msg = "Which item is for sale?"; @@ -915,11 +910,10 @@ static void S_StartWRecharge() gbWidePanel = true; // gbRenderGold = true; + gbHasScroll = storenumh != 0; if (storenumh == 0) { - gbHasScroll = false; msg = "You have nothing to recharge."; } else { - gbHasScroll = true; // stextsidx = 0; S_ScrollSSell(); @@ -1177,11 +1171,10 @@ static void S_StartSIdentify() gbWidePanel = true; // gbRenderGold = true; + gbHasScroll = storenumh != 0; if (storenumh == 0) { - gbHasScroll = false; msg = "You have nothing to identify."; } else { - gbHasScroll = true; // stextsidx = 0; S_ScrollSSell(); From 3ef84285cad4399a8ab1ad68b7b210c10f8b4cfd Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 8 Aug 2024 07:24:38 +0200 Subject: [PATCH 400/596] initialize stextsmax in StartStore --- Source/stores.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index 0b02070f5c8..8775075396b 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -471,7 +471,7 @@ static void S_ScrollSBuy() static_assert(lengthof(smithitem) <= STORE_PAGE_ITEMS, "S_ScrollSBuy must fit to a single store-page."); // stextsmax = storenumh - STORE_PAGE_ITEMS; // if (stextsmax <= 0) - stextsmax = 0; + // stextsmax = 0; // else // stextsmax = ((stextsmax + STORE_LINE_ITEMS - 1) / STORE_LINE_ITEMS) * STORE_LINE_ITEMS; } @@ -553,7 +553,7 @@ static void S_ScrollSPBuy() static_assert(lengthof(premiumitems) <= STORE_PAGE_ITEMS, "S_ScrollSPBuy must fit to a single store-page."); // stextsmax = storenumh - STORE_PAGE_ITEMS; // if (stextsmax <= 0) - stextsmax = 0; + // stextsmax = 0; // else // stextsmax = ((stextsmax + STORE_LINE_ITEMS - 1) / STORE_LINE_ITEMS) * STORE_LINE_ITEMS; } @@ -1094,7 +1094,7 @@ static void S_ScrollHBuy() static_assert(lengthof(healitem) <= STORE_PAGE_ITEMS, "S_ScrollHBuy must fit to a single store-page."); // stextsmax = storenumh - STORE_PAGE_ITEMS; // if (stextsmax <= 0) - stextsmax = 0; + // stextsmax = 0; // else // stextsmax = ((stextsmax + STORE_LINE_ITEMS - 1) / STORE_LINE_ITEMS) * STORE_LINE_ITEMS; } @@ -1301,6 +1301,7 @@ void StartStore(int s) ReleaseStoreBtn(); stextflag = s; stextsidx = 0; + stextsmax = 0; gbHasScroll = false; switch (s) { case STORE_SMITH: From 4118f21d0ce9827bd676d6aa603bced721e8415d Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 8 Aug 2024 07:26:59 +0200 Subject: [PATCH 401/596] initialize gbWidePanel in StartStore --- Source/stores.cpp | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index 8775075396b..b4b9ef19b0c 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -189,7 +189,7 @@ void InitStoresOnce() ClearSText(0, STORE_LINES); stextflag = STORE_NONE; - gbWidePanel = false; + // gbWidePanel = false; // gbRenderGold = false; // gbHasScroll = false; numpremium = 0; @@ -409,7 +409,7 @@ static void AddStoreFrame(const char* title) static void S_StartSmith() { - gbWidePanel = false; + // gbWidePanel = false; // gbRenderGold = false; // gbHasScroll = false; AddSText(0, 1, true, "Welcome to the", COL_GOLD, false); @@ -751,7 +751,7 @@ static void S_StartSRepair() static void S_StartWitch() { - gbWidePanel = false; + // gbWidePanel = false; // gbRenderGold = false; // gbHasScroll = false; @@ -940,6 +940,7 @@ static void S_StartNoRoom() // StartStore(stextshold); // ClearSText(STORE_LIST_FIRST, STORE_LINES); // gbHasScroll = false; + gbWidePanel = true; AddSText(0, 14, true, "You do not have enough room in inventory", COL_WHITE, true); // AddSLine(3); @@ -958,6 +959,7 @@ static void S_StartConfirm() // StartStore(stextshold); // ClearSText(STORE_LIST_FIRST, STORE_LINES); // gbHasScroll = false; + gbWidePanel = true; AddSItem(260, STORE_LIST_FIRST, 0, storeitem._iCurs, FALSE); PrintStoreItem(&storeitem, STORE_LIST_FIRST - 1 + STORE_ITEM_LINES, false); AddSTextVal(STORE_LIST_FIRST - 1 + STORE_ITEM_LINES, storeitem._iIvalue); @@ -998,7 +1000,7 @@ static void S_StartConfirm() static void S_StartBoy() { - gbWidePanel = false; + // gbWidePanel = false; // gbRenderGold = false; // gbHasScroll = false; AddSText(0, 2, true, "Wirt the Peg-legged boy", COL_GOLD, false); @@ -1041,7 +1043,7 @@ static void S_StartBBoy() static void S_StartHealer() { - gbWidePanel = false; + // gbWidePanel = false; // gbRenderGold = false; // gbHasScroll = false; AddSText(0, 1, true, "Welcome to the", COL_GOLD, false); @@ -1118,7 +1120,7 @@ static void S_StartHBuy() static void S_StartStory() { - gbWidePanel = false; + // gbWidePanel = false; // gbRenderGold = false; // gbHasScroll = false; AddSText(0, 2, true, "The Town Elder", COL_GOLD, false); @@ -1189,7 +1191,7 @@ static void S_StartIdShow() //StartStore(STORE_SIDENTIFY); //ClearSText(STORE_LIST_FIRST, STORE_LINES); - //gbWidePanel = true; + gbWidePanel = true; //gbRenderGold = true; // gbHasScroll = false; @@ -1203,7 +1205,7 @@ static void S_StartTalk() { int i, sn, la; - gbWidePanel = false; + // gbWidePanel = false; // gbRenderGold = false; // gbHasScroll = false; snprintf(tempstr, sizeof(tempstr), "Talk to %s", talkname[talker]); @@ -1235,7 +1237,7 @@ static void S_StartTalk() static void S_StartTavern() { - gbWidePanel = false; + // gbWidePanel = false; // gbRenderGold = false; // gbHasScroll = false; AddSText(0, 1, true, "Welcome to the", COL_GOLD, false); @@ -1248,7 +1250,7 @@ static void S_StartTavern() static void S_StartBarMaid() { - gbWidePanel = false; + // gbWidePanel = false; // gbRenderGold = false; // gbHasScroll = false; AddSText(0, 2, true, "Gillian", COL_GOLD, false); @@ -1260,7 +1262,7 @@ static void S_StartBarMaid() static void S_StartDrunk() { - gbWidePanel = false; + // gbWidePanel = false; // gbRenderGold = false; // gbHasScroll = false; AddSText(0, 2, true, "Farnham the Drunk", COL_GOLD, false); @@ -1272,7 +1274,7 @@ static void S_StartDrunk() static void S_StartPriest() { - gbWidePanel = false; + // gbWidePanel = false; // gbRenderGold = false; // gbHasScroll = false; AddSText(0, 2, true, "Tremain the Priest", COL_GOLD, false); @@ -1284,6 +1286,7 @@ static void S_StartPriest() static void S_StartErrand() { + // gbWidePanel = false; // gbHasScroll = false; AddSText(0, 2, true, "Tremain the Priest", COL_GOLD, false); // AddSText(0, 12, true, "Would you like to", COL_WHITE, false); @@ -1303,6 +1306,7 @@ void StartStore(int s) stextsidx = 0; stextsmax = 0; gbHasScroll = false; + gbWidePanel = false; // 11 vs 14 switch (s) { case STORE_SMITH: S_StartSmith(); From 119ced916215484e12b6241aef901249be941535 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 8 Aug 2024 07:31:14 +0200 Subject: [PATCH 402/596] add StoreUpdateSelection to simplify the S_Scroll* functions --- Source/stores.cpp | 85 +++++------------------------------------------ 1 file changed, 8 insertions(+), 77 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index b4b9ef19b0c..fd11c604e35 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -156,6 +156,8 @@ static const char* const talkname[] = { // clang-format on }; +static void StoreUpdateSelection(); + static void ClearSText(int s, int e) { // int i; @@ -445,21 +447,6 @@ static void S_ScrollSBuy() int line = STORE_LIST_FIRST + (l / STORE_LINE_ITEMS) * STORE_ITEM_LINES; AddSItem(60, line, l % STORE_LINE_ITEMS, is->_iCurs, TRUE); stextdown = line; - is++; - } - } - - if (stextsel != -1 && /*stextsel != STORE_BACK &&*/ !stextlines[stextsel]._ssel) - stextsel = stextdown; - if (stextsel != -1 && stextlines[stextsel]._sitemlist) { - while (stextselx >= 0 && stextlines[stextsel]._siCurs[stextselx] == CURSOR_NONE) { - stextselx--; - } - } - - is = &smithitem[stextsidx]; - for (l = 0; l < STORE_PAGE_ITEMS; l++) { - if (is->_itype != ITYPE_NONE) { if (stextsel == STORE_LIST_FIRST + (l / STORE_LINE_ITEMS) * STORE_ITEM_LINES && stextselx == l % STORE_LINE_ITEMS) { // StorePrepareItemBuy(is); PrintStoreItem(is, STORE_LIST_FOOTER - 3, false); @@ -524,23 +511,6 @@ static void S_ScrollSPBuy() int line = STORE_LIST_FIRST + (l / STORE_LINE_ITEMS) * STORE_ITEM_LINES; AddSItem(60, line, l % STORE_LINE_ITEMS, is->_iCurs, TRUE); stextdown = line; - l++; - } - idx++; - } - - if (stextsel != -1 && /*stextsel != STORE_BACK &&*/ !stextlines[stextsel]._ssel) - stextsel = stextdown; - if (stextsel != -1 && stextlines[stextsel]._sitemlist) { - while (stextselx >= 0 && stextlines[stextsel]._siCurs[stextselx] == CURSOR_NONE) { - stextselx--; - } - } - - idx = sidx; - for (l = 0; l < STORE_PAGE_ITEMS && idx < SMITH_PREMIUM_ITEMS; ) { - is = &premiumitems[idx]; - if (is->_itype != ITYPE_NONE) { if (stextsel == STORE_LIST_FIRST + (l / STORE_LINE_ITEMS) * STORE_ITEM_LINES && stextselx == l % STORE_LINE_ITEMS) { // StorePrepareItemBuy(is); PrintStoreItem(is, STORE_LIST_FOOTER - 3, false); @@ -630,21 +600,6 @@ static void S_ScrollSSell() int line = STORE_LIST_FIRST + (l / STORE_LINE_ITEMS) * STORE_ITEM_LINES; AddSItem(60, line, l % STORE_LINE_ITEMS, is->_iCurs, TRUE); stextdown = line; - is++; - } - } - - if (stextsel != -1 && /*stextsel != STORE_BACK &&*/ !stextlines[stextsel]._ssel) - stextsel = stextdown; - if (stextsel != -1 && stextlines[stextsel]._sitemlist) { - while (stextselx >= 0 && stextlines[stextsel]._siCurs[stextselx] == CURSOR_NONE) { - stextselx--; - } - } - - is = &storehold[stextsidx]; - for (l = 0; l < STORE_PAGE_ITEMS; l++) { - if (is->_itype != ITYPE_NONE) { if (stextsel == STORE_LIST_FIRST + (l / STORE_LINE_ITEMS) * STORE_ITEM_LINES && stextselx == l % STORE_LINE_ITEMS) { PrintStoreItem(is, STORE_LIST_FOOTER - 3, false); AddSTextVal(STORE_LIST_FOOTER - 3, is->_iIvalue/*is->_iMagical != ITEM_QUALITY_NORMAL && is->_iIdentified ? is->_iIvalue : is->_ivalue*/); @@ -779,21 +734,6 @@ static void S_ScrollWBuy() int line = STORE_LIST_FIRST + (l / STORE_LINE_ITEMS) * STORE_ITEM_LINES; AddSItem(60, line, l % STORE_LINE_ITEMS, is->_iCurs, TRUE); stextdown = line; - is++; - } - } - - if (stextsel != -1 && /*stextsel != STORE_BACK &&*/ !stextlines[stextsel]._ssel) - stextsel = stextdown; - if (stextsel != -1 && stextlines[stextsel]._sitemlist) { - while (stextselx >= 0 && stextlines[stextsel]._siCurs[stextselx] == CURSOR_NONE) { - stextselx--; - } - } - - is = &witchitem[stextsidx]; - for (l = 0; l < STORE_PAGE_ITEMS; l++) { - if (is->_itype != ITYPE_NONE) { if (stextsel == STORE_LIST_FIRST + (l / STORE_LINE_ITEMS) * STORE_ITEM_LINES && stextselx == l % STORE_LINE_ITEMS) { // StorePrepareItemBuy(is); PrintStoreItem(is, STORE_LIST_FOOTER - 3, false); @@ -1070,21 +1010,6 @@ static void S_ScrollHBuy() int line = STORE_LIST_FIRST + (l / STORE_LINE_ITEMS) * STORE_ITEM_LINES; AddSItem(60, line, l % STORE_LINE_ITEMS, is->_iCurs, TRUE); stextdown = line; - is++; - } - } - - if (stextsel != -1 && /*stextsel != STORE_BACK &&*/ !stextlines[stextsel]._ssel) - stextsel = stextdown; - if (stextsel != -1 && stextlines[stextsel]._sitemlist) { - while (stextselx >= 0 && stextlines[stextsel]._siCurs[stextselx] == CURSOR_NONE) { - stextselx--; - } - } - - is = &healitem[stextsidx]; - for (l = 0; l < STORE_PAGE_ITEMS; l++) { - if (is->_itype != ITYPE_NONE) { if (stextsel == STORE_LIST_FIRST + (l / STORE_LINE_ITEMS) * STORE_ITEM_LINES && stextselx == l % STORE_LINE_ITEMS) { // StorePrepareItemBuy(is); PrintStoreItem(is, STORE_LIST_FOOTER - 3, false); @@ -1476,6 +1401,7 @@ void DrawStore() ASSUME_UNREACHABLE break; } + StoreUpdateSelection(); // check maxx } for (i = 0; i < STORE_LINES; i++) { @@ -2077,6 +2003,11 @@ void SyncStoreCmd(int pnum, int cmd, int ii, int price) stextsel = stextlhold; stextselx = stextxhold; stextsidx = stextvhold; + StoreUpdateSelection(); +} + +static void StoreUpdateSelection() +{ if (stextsidx > stextsmax) { stextsidx = stextsmax; } From c9d8fe0692ce50980eecaf32cc25d9bb5a68cacf Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 8 Aug 2024 08:01:33 +0200 Subject: [PATCH 403/596] add gbRenderGold setters to the S_Start* functions --- Source/stores.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index fd11c604e35..b4d1ca9af51 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -881,6 +881,7 @@ static void S_StartNoRoom() // ClearSText(STORE_LIST_FIRST, STORE_LINES); // gbHasScroll = false; gbWidePanel = true; + // gbRenderGold = true; AddSText(0, 14, true, "You do not have enough room in inventory", COL_WHITE, true); // AddSLine(3); @@ -900,6 +901,7 @@ static void S_StartConfirm() // ClearSText(STORE_LIST_FIRST, STORE_LINES); // gbHasScroll = false; gbWidePanel = true; + // gbRenderGold = true; AddSItem(260, STORE_LIST_FIRST, 0, storeitem._iCurs, FALSE); PrintStoreItem(&storeitem, STORE_LIST_FIRST - 1 + STORE_ITEM_LINES, false); AddSTextVal(STORE_LIST_FIRST - 1 + STORE_ITEM_LINES, storeitem._iIvalue); @@ -1117,7 +1119,7 @@ static void S_StartIdShow() //ClearSText(STORE_LIST_FIRST, STORE_LINES); gbWidePanel = true; - //gbRenderGold = true; + // gbRenderGold = true; // gbHasScroll = false; AddSItem(260, STORE_LIST_FIRST, 0, storeitem._iCurs, FALSE); @@ -1212,6 +1214,7 @@ static void S_StartPriest() static void S_StartErrand() { // gbWidePanel = false; + // gbRenderGold = false; // gbHasScroll = false; AddSText(0, 2, true, "Tremain the Priest", COL_GOLD, false); // AddSText(0, 12, true, "Would you like to", COL_WHITE, false); From 64f8f16e455d0441ab774accb88d98399bd68e7b Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 8 Aug 2024 08:05:11 +0200 Subject: [PATCH 404/596] reorder stores.cpp --- Source/stores.cpp | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index b4d1ca9af51..9d5850bb5a5 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -156,8 +156,6 @@ static const char* const talkname[] = { // clang-format on }; -static void StoreUpdateSelection(); - static void ClearSText(int s, int e) { // int i; @@ -866,9 +864,9 @@ static void S_StartNoMoney() { // StartStore(stextshold); // ClearSText(STORE_LIST_FIRST, STORE_LINES); - // gbHasScroll = false; gbWidePanel = true; // gbRenderGold = true; + // gbHasScroll = false; AddSText(0, 14, true, "You do not have enough gold", COL_WHITE, true); // AddSLine(3); @@ -879,9 +877,9 @@ static void S_StartNoRoom() { // StartStore(stextshold); // ClearSText(STORE_LIST_FIRST, STORE_LINES); - // gbHasScroll = false; gbWidePanel = true; // gbRenderGold = true; + // gbHasScroll = false; AddSText(0, 14, true, "You do not have enough room in inventory", COL_WHITE, true); // AddSLine(3); @@ -899,9 +897,9 @@ static void S_StartConfirm() { // StartStore(stextshold); // ClearSText(STORE_LIST_FIRST, STORE_LINES); - // gbHasScroll = false; gbWidePanel = true; // gbRenderGold = true; + // gbHasScroll = false; AddSItem(260, STORE_LIST_FIRST, 0, storeitem._iCurs, FALSE); PrintStoreItem(&storeitem, STORE_LIST_FIRST - 1 + STORE_ITEM_LINES, false); AddSTextVal(STORE_LIST_FIRST - 1 + STORE_ITEM_LINES, storeitem._iIvalue); @@ -1233,8 +1231,9 @@ void StartStore(int s) stextflag = s; stextsidx = 0; stextsmax = 0; - gbHasScroll = false; gbWidePanel = false; // 11 vs 14 + // gbRenderGold = false; + gbHasScroll = false; switch (s) { case STORE_SMITH: S_StartSmith(); @@ -1329,6 +1328,23 @@ void StartStore(int s) stextselx = 0; } +static void StoreUpdateSelection() +{ + if (stextsidx > stextsmax) { + stextsidx = stextsmax; + } + DEBUG_ASSERT(stextsel != -1); + while (/*stextsel != -1 && */ !stextlines[stextsel]._ssel) { + stextsel--; + DEBUG_ASSERT(stextsel != -1); + } + if (/*stextsel != -1 && */ stextlines[stextsel]._sitemlist) { + while (stextselx >= 0 && stextlines[stextsel]._siCurs[stextselx] == CURSOR_NONE) { + stextselx--; + } + } +} + /*void DrawStoreLineX(int sx, int sy, int dx, int dy, int length) { int sxy, dxy, width; @@ -2009,23 +2025,6 @@ void SyncStoreCmd(int pnum, int cmd, int ii, int price) StoreUpdateSelection(); } -static void StoreUpdateSelection() -{ - if (stextsidx > stextsmax) { - stextsidx = stextsmax; - } - DEBUG_ASSERT(stextsel != -1); - while (/*stextsel != -1 && */ !stextlines[stextsel]._ssel) { - stextsel--; - DEBUG_ASSERT(stextsel != -1); - } - if (/*stextsel != -1 && */ stextlines[stextsel]._sitemlist) { - while (stextselx >= 0 && stextlines[stextsel]._siCurs[stextselx] == CURSOR_NONE) { - stextselx--; - } - } -} - /** * @brief Sells an item from the player's inventory or belt. */ From e3b6b0e49e117e49e9a2e46ce8d2c91cec24ae08 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 9 Aug 2024 07:52:16 +0200 Subject: [PATCH 405/596] clear itemlist of stores in DrawStore --- Source/stores.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index 9d5850bb5a5..068afe04d7e 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -436,7 +436,7 @@ static void S_ScrollSBuy() ItemStruct* is; unsigned l; - ClearSText(STORE_LIST_FIRST, STORE_LIST_FOOTER); + // ClearSText(STORE_LIST_FIRST, STORE_LIST_FOOTER); is = &smithitem[stextsidx]; for (l = 0; l < STORE_PAGE_ITEMS; l++) { @@ -494,7 +494,7 @@ static void S_ScrollSPBuy() ItemStruct* is; unsigned idx, l, boughtitems; - ClearSText(STORE_LIST_FIRST, STORE_LIST_FOOTER); + // ClearSText(STORE_LIST_FIRST, STORE_LIST_FOOTER); boughtitems = stextsidx; for (idx = 0; boughtitems != 0; idx++) @@ -590,7 +590,7 @@ static void S_ScrollSSell() ItemStruct* is; unsigned l; - ClearSText(STORE_LIST_FIRST, STORE_LIST_FOOTER); + // ClearSText(STORE_LIST_FIRST, STORE_LIST_FOOTER); is = &storehold[stextsidx]; for (l = 0; l < STORE_PAGE_ITEMS; l++) { @@ -723,7 +723,7 @@ static void S_ScrollWBuy() ItemStruct* is; unsigned l; - ClearSText(STORE_LIST_FIRST, STORE_LIST_FOOTER); + // ClearSText(STORE_LIST_FIRST, STORE_LIST_FOOTER); is = &witchitem[stextsidx]; for (l = 0; l < STORE_PAGE_ITEMS; l++) { @@ -1001,7 +1001,7 @@ static void S_ScrollHBuy() ItemStruct* is; unsigned l; - ClearSText(STORE_LIST_FIRST, STORE_LIST_FOOTER); + // ClearSText(STORE_LIST_FIRST, STORE_LIST_FOOTER); is = &healitem[stextsidx]; for (l = 0; l < STORE_PAGE_ITEMS; l++) { @@ -1396,6 +1396,8 @@ void DrawStore() } if (gbHasScroll) { + // update list entries (TODO: only if stextsmax != 0?) + ClearSText(STORE_LIST_FIRST, STORE_LIST_FOOTER); switch (stextflag) { case STORE_SBUY: S_ScrollSBuy(); From 88f778453dcf29bebbc4aac191e7a7cf9c9f9220 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 9 Aug 2024 07:53:39 +0200 Subject: [PATCH 406/596] no need to clear the store-lines in InitStoresOnce --- Source/stores.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index 068afe04d7e..82f6607f4ae 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -187,7 +187,7 @@ void InitStoresOnce() { int i; - ClearSText(0, STORE_LINES); + // ClearSText(0, STORE_LINES); stextflag = STORE_NONE; // gbWidePanel = false; // gbRenderGold = false; From aab368a6c82a949e8e39a6656aa4a85d0a77f987 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 9 Aug 2024 07:56:54 +0200 Subject: [PATCH 407/596] do not change the y-offset in AddSText --- Source/stores.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index 82f6607f4ae..7114e603e99 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -306,7 +306,7 @@ static void AddSText(int x, int y, bool j, const char* str, BYTE clr, bool sel) ss = &stextlines[y]; ss->_sx = x; - ss->_syoff = 0; + // ss->_syoff = 0; SStrCopy(ss->_sstr, str, sizeof(ss->_sstr)); ss->_sjust = j; ss->_sclr = clr; From 4e119f7d26147601bbf92a9eb8defd216ce158cd Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 9 Aug 2024 07:58:54 +0200 Subject: [PATCH 408/596] no need to clear the store lines in InitSTextHelp - the lines are overwritten by the help texts - the y-offsets are zero at the end of the conversations --- Source/stores.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index 7114e603e99..4c392e13607 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -282,7 +282,7 @@ void InitSTextHelp() gbWidePanel = true; // assert(gbRenderGold == false); - not necessary since it is not used in PrintSString // assert(gbHasScroll == false); - not necessary since it is not used in PrintSString - ClearSText(0, STORE_LINES); // necessary to reset the _syoff values + // ClearSText(0, STORE_LINES); // necessary to reset the _syoff values -- should be zero at the moment... } /*static void AddSLine(int y) From 27ea847483e6d61f77efc6ea468a9f5fc37da7f4 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 9 Aug 2024 08:03:17 +0200 Subject: [PATCH 409/596] there must be a selectable line in the stores -> use DEBUG_ASSERT in StartStore --- Source/stores.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index 4c392e13607..20efc5f1a76 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -1324,7 +1324,8 @@ void StartStore(int s) break; } - stextsel = i == STORE_LINES ? -1 : i; + DEBUG_ASSERT(i != STORE_LINES); + stextsel = /*i == STORE_LINES ? -1 :*/ i; stextselx = 0; } From 5cbdcad9b199ca8210b77001d5b2a58d25b0a655 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 9 Aug 2024 08:11:43 +0200 Subject: [PATCH 410/596] allow swapping of campaign maps in inventory --- Source/inv.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/Source/inv.cpp b/Source/inv.cpp index eef732c42ff..80b44b1642c 100644 --- a/Source/inv.cpp +++ b/Source/inv.cpp @@ -729,6 +729,13 @@ static int MergeStackableItem(ItemStruct* a, ItemStruct* b) { int gt, ig, cn; + // assert(a->_iUsable || b->_iUsable); + if (a->_iMiscId == IMISC_MAP // TODO: use a->_iMaxDur != 1 instead? + || a->_iMiscId != b->_iMiscId + || a->_iSpell != b->_iSpell) { + return CURSOR_NONE; + } + // assert(a->_iUsable && b->_iUsable); gt = a->_iDurability; ig = b->_iDurability + gt; // STACK //a->_ivalue /= a->_iDurability; @@ -991,13 +998,13 @@ void InvPasteItem(int pnum, BYTE r) if (it == 0) { // empty target copy_pod(*is, *holditem); - } else if (holditem->_iUsable - && holditem->_iMiscId == is->_iMiscId - && holditem->_iSpell == is->_iSpell) { - // matching stackable items - cn = MergeStackableItem(is, holditem); - break; } else { + if (holditem->_iUsable) { + cn = MergeStackableItem(is, holditem); + if (cn != CURSOR_NONE) + break; + } + it--; for (i = 0; i < NUM_INV_GRID_ELEM; i++) { if (p->_pInvList[i]._itype == ITYPE_PLACEHOLDER @@ -1079,12 +1086,12 @@ void InvPasteBeltItem(int pnum, BYTE r) return; // assert(holditem->_iUsable); is = &plr._pSpdList[r]; - if (is->_itype != ITYPE_NONE - && is->_iMiscId == holditem->_iMiscId - && is->_iSpell == holditem->_iSpell) { + cn = CURSOR_NONE; + if (is->_itype != ITYPE_NONE) { // matching stackable items cn = MergeStackableItem(is, holditem); - } else { + } + if (cn == CURSOR_NONE) { cn = SwapItem(is, holditem); if (holditem->_itype == ITYPE_NONE) cn = CURSOR_HAND; From 72050e1768d9562b761fa7e7e2e0667f7b579e3d Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 9 Aug 2024 08:40:58 +0200 Subject: [PATCH 411/596] handle left/right buttons in stores --- Source/diablo.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Source/diablo.cpp b/Source/diablo.cpp index 7a4e8fc8873..eb768294e67 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -975,12 +975,16 @@ static void PressKey(int vkey) } break; case ACT_LEFT: - if (gbAutomapflag != AMM_NONE) { + if (stextflag != STORE_NONE) { + STextLeft(); + } else if (gbAutomapflag != AMM_NONE) { AutomapLeft(); } break; case ACT_RIGHT: - if (gbAutomapflag != AMM_NONE) { + if (stextflag != STORE_NONE) { + STextRight(); + } else if (gbAutomapflag != AMM_NONE) { AutomapRight(); } break; From fe730a806361f8289f77e22d796dd9e4bac47d57 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 9 Aug 2024 09:59:39 +0200 Subject: [PATCH 412/596] validate GOLD_MAX_LIMIT in PackPkItem --- Source/msg.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/msg.cpp b/Source/msg.cpp index a0ab0a7a6cb..0dd66492ff5 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -835,6 +835,7 @@ void PackPkItem(PkItemStruct* dest, const ItemStruct* src) dest->bMDur = src->_iMaxDur; dest->bCh = src->_iCharges; dest->bMCh = src->_iMaxCharges; + static_assert(GOLD_MAX_LIMIT <= UINT16_MAX, "PackPkItem stores the gold value in 2 bytes."); static_assert(MAXCAMPAIGNSIZE <= 16, "PackPkItem stores the campaign status in 2 bytes."); dest->wValue = static_cast(src->_ivalue); } else { From f58eaa2571618798136f22014270ee8708204259 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 9 Aug 2024 10:01:25 +0200 Subject: [PATCH 413/596] use assertion in control_drop_gold --- Source/control.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Source/control.cpp b/Source/control.cpp index a62c3eabad5..6cb29d6eeb0 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -2204,10 +2204,7 @@ void control_drop_gold(int vkey) { int newValue; - if (myplr._pHitPoints < (1 << 6)) { - gbDropGoldFlag = false; - return; - } + assert(myplr._pHitPoints >= (1 << 6) || vkey == DVL_VK_ESCAPE); if (vkey == DVL_VK_RETURN) { if (dropGoldValue > 0) From 88070e3bc2b42bfe58780a79e69cd220dedbd0ce Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 9 Aug 2024 10:08:44 +0200 Subject: [PATCH 414/596] disable md5-checker for the moment (patcher) --- tools/patcher/DiabloUI/mainmenu.cpp | 14 ++++++++------ tools/patcher/mainmenu.cpp | 2 ++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/tools/patcher/DiabloUI/mainmenu.cpp b/tools/patcher/DiabloUI/mainmenu.cpp index 900e99eb00a..2dcb6b10864 100644 --- a/tools/patcher/DiabloUI/mainmenu.cpp +++ b/tools/patcher/DiabloUI/mainmenu.cpp @@ -24,12 +24,14 @@ static void MainmenuEsc() static void MainmenuLoad() { - int numOptions = 4; - - gUIListItems.push_back(new UiListItem("Patch Assets", 0)); - gUIListItems.push_back(new UiListItem("Merge Assets", 1)); - gUIListItems.push_back(new UiListItem("Check Assets", 2)); - gUIListItems.push_back(new UiListItem("Exit Patcher", 3)); + const int numOptions = 3; // 4; + int currOption = 0; + + gUIListItems.push_back(new UiListItem("Patch Assets", currOption++)); + gUIListItems.push_back(new UiListItem("Merge Assets", currOption++)); + // gUIListItems.push_back(new UiListItem("Check Assets", currOption++)); + gUIListItems.push_back(new UiListItem("Exit Patcher", currOption++)); + assert(numOptions == currOption); LoadBackgroundArt("ui_art\\mainmenu.CEL", "ui_art\\menu.pal"); diff --git a/tools/patcher/mainmenu.cpp b/tools/patcher/mainmenu.cpp index aafc0eae369..77ee6d76868 100644 --- a/tools/patcher/mainmenu.cpp +++ b/tools/patcher/mainmenu.cpp @@ -39,9 +39,11 @@ void mainmenu_loop() UiMergerDialog(); continue; case 2: +#if 0 UiCheckerDialog(); continue; case 3: +#endif break; default: ASSUME_UNREACHABLE From 8a7b4b0e977bde14ab7d7fc6709c160ef51fd9ab Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 10 Aug 2024 15:47:06 +0200 Subject: [PATCH 415/596] use only gray(PAL16_GRAY) or yellow(PAL16_YELLOW) colors in the inventory (Inv.CEL) --- Packaging/resources/devilx.mpq | Bin 1250309 -> 1250182 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Packaging/resources/devilx.mpq b/Packaging/resources/devilx.mpq index 9d9f3bc7312bb8d4817be30eacd406f5b33abde1..bc01c524266346535369540b0267604dfee3a2fc 100644 GIT binary patch delta 18415 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 delta 18597 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 HiV|UoH_5|K From 0c7d5abce335eb706f4511d2c018bafb301f05e7 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 10 Aug 2024 17:09:20 +0200 Subject: [PATCH 416/596] simplify InvDrawSlotBack based on #5266 --- Source/inv.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/inv.cpp b/Source/inv.cpp index 80b44b1642c..9a57f92cbab 100644 --- a/Source/inv.cpp +++ b/Source/inv.cpp @@ -225,7 +225,7 @@ static void InvDrawSlotBack(int X, int Y, int W, int H) pix = *dst; if (pix >= PAL16_BLUE) { if (pix <= PAL16_BLUE + 15) - *dst -= PAL16_BLUE - PAL16_BEIGE; + ; // *dst -= PAL16_BLUE - PAL16_BEIGE; else if (pix >= PAL16_GRAY) *dst -= PAL16_GRAY - PAL16_BEIGE; } From f8732974a6909220bf2e44401256ad46f943adce Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 10 Aug 2024 17:14:10 +0200 Subject: [PATCH 417/596] patch ObjCurs.CEL - center the graphics - fix the colors in frame 165 - make the amulet in frame 56 more round --- tools/patcher/DiabloUI/patcher.cpp | 248 ++++++++++++++++++++++++++++- 1 file changed, 243 insertions(+), 5 deletions(-) diff --git a/tools/patcher/DiabloUI/patcher.cpp b/tools/patcher/DiabloUI/patcher.cpp index 2f9b6a6d567..aef8922a799 100644 --- a/tools/patcher/DiabloUI/patcher.cpp +++ b/tools/patcher/DiabloUI/patcher.cpp @@ -119,8 +119,8 @@ typedef enum filenames { FILE_MON_FALLGW, FILE_MON_GOATLD, #endif +#endif // HELLFIRE FILE_OBJCURS_CEL, -#endif NUM_FILENAMES } filenames; @@ -225,8 +225,8 @@ static const char* const filesToPatch[NUM_FILENAMES] = { /*FILE_MON_FALLGW*/ "Monsters\\BigFall\\Fallgw.CL2", /*FILE_MON_GOATLD*/ "Monsters\\GoatLord\\GoatLd.CL2", #endif +#endif // HELLFIRE /*FILE_OBJCURS_CEL*/ "Data\\Inv\\Objcurs.CEL", -#endif }; #define nSolidTable(pn, v) \ @@ -2179,6 +2179,237 @@ BYTE* createWarriorAnim(BYTE* cl2Buf, size_t *dwLen, const BYTE* atkBuf, const B return resCl2Buf; } +static void moveImage(int width, int height, int dx, int dy, BYTE TRANS_COLOR) +{ + if (dx > 0) { + for (int y = 0; y < height; y++) { + for (int x = width - dx - 1; x >= 0; x--) { + gpBuffer[x + dx + BUFFER_WIDTH * y] = gpBuffer[x + BUFFER_WIDTH * y]; + gpBuffer[x + BUFFER_WIDTH * y] = TRANS_COLOR; + } + } + } + if (dx < 0) { + for (int y = 0; y < height; y++) { + for (int x = -dx; x < width; x++) { + gpBuffer[x + dx + BUFFER_WIDTH * y] = gpBuffer[x + BUFFER_WIDTH * y]; + gpBuffer[x + BUFFER_WIDTH * y] = TRANS_COLOR; + } + } + } + if (dy > 0) { + for (int y = height - dy - 1; y >= 0; y--) { + for (int x = 0; x < width; x++) { + gpBuffer[x + BUFFER_WIDTH * (y + dy)] = gpBuffer[x + BUFFER_WIDTH * y]; + gpBuffer[x + BUFFER_WIDTH * y] = TRANS_COLOR; + } + } + } + if (dy < 0) { + for (int y = -dy; y < height; y++) { + for (int x = 0; x < width; x++) { + gpBuffer[x + BUFFER_WIDTH * (y + dy)] = gpBuffer[x + BUFFER_WIDTH * y]; + gpBuffer[x + BUFFER_WIDTH * y] = TRANS_COLOR; + } + } + } +} + +static BYTE* centerCursors(BYTE* celBuf, size_t* celLen) +{ + constexpr BYTE TRANS_COLOR = 1; + constexpr BYTE SUB_HEADER_SIZE = 10; + + DWORD* srcHeaderCursor = (DWORD*)celBuf; + int srcCelEntries = SwapLE32(srcHeaderCursor[0]); + srcHeaderCursor++; + + const int resCelEntries = NUM_ICURS + CURSOR_FIRSTITEM - 1; + assert(srcCelEntries == resCelEntries); + + // create the new CEL file + size_t maxCelSize = *celLen * 2; + BYTE* resCelBuf = DiabloAllocPtr(maxCelSize); + memset(resCelBuf, 0, maxCelSize); + + DWORD* dstHeaderCursor = (DWORD*)resCelBuf; + *dstHeaderCursor = SwapLE32(resCelEntries); + dstHeaderCursor++; + + BYTE* dstDataCursor = resCelBuf + 4 * (resCelEntries + 2); + bool needsPatch = false; + for (int i = 0; i < resCelEntries; i++) { + // draw the frame to the back-buffer + memset(&gpBuffer[0], TRANS_COLOR, InvItemHeight[i + 1] * BUFFER_WIDTH); + CelClippedDraw(0, InvItemHeight[i + 1] - 1, celBuf, i + 1, InvItemWidth[i + 1]); + + int dx = 0, dy = 0; + switch (i + 1) { + case 236: dx = 0; dy = -2; break; + case 234: dx = 0; dy = -2; break; + case 233: dx = 0; dy = -1; break; + case 232: dx = -2; dy = -2; break; + case 231: dx = 0; dy = -1; break; + case 230: dx = 2; dy = 0; break; + case 229: dx = -1; dy = -3; break; + case 228: dx = 0; dy = -2; break; + case 227: dx = -1; dy = -2; break; + case 226: dx = -1; dy = -2; break; + case 225: dx = 0; dy = 2; break; + case 224: dx = -1; dy = 1; break; + case 223: dx = 0; dy = 1; break; + case 222: dx = -2; dy = 3; break; + case 221: dx = -1; dy = 2; break; + case 220: dx = -1; dy = 0; break; + case 219: dx = -1; dy = 0; break; + case 218: dx = -1; dy = 0; break; + case 217: dx = 0; dy = 1; break; + case 216: dx = -1; dy = 9; break; // a + case 215: dx = 0; dy = 12; break; // a + case 213: dx = -1; dy = 0; break; + case 179: dx = 1; dy = 5; break; + case 177: dx = 0; dy = 2; break; + case 176: dx = 1; dy = 0; break; + case 173: dx = 1; dy = 0; break; + case 171: dx = 0; dy = -3; break; // a + case 167: dx = - 1; dy = 0; break; + case 165: dx = 2; dy = -3; // overwrite bright yellow colors on the armor + for (int y = 0; y < InvItemHeight[i + 1]; y++) { + for (int x = 0; x < InvItemWidth[i + 1]; x++) { + BYTE color = gpBuffer[x + BUFFER_WIDTH * y]; + if (color == 144 || color == 145) + gpBuffer[x + BUFFER_WIDTH * y] = color + 96; + } + } + break; + case 164: dx = 0; dy = 4; break;// a + case 162: dx = 0; dy = -4; break;// a + case 161: dx = 0; dy = 1; break; + case 159: dx = 1; dy = 1; break; + case 158: dx = 0; dy = 3; break; + case 157: dx = 1; dy = -1; break; + case 156: dx = 0; dy = 1; break; + case 154: dx = 1; dy = 0; break; + case 153: dx = -1; dy = 1; break; + case 152: dx = 0; dy = 2; break; + case 151: dx = 0; dy = 2; break;// a + case 147: dx = 0; dy = 2; break;// a + case 146: dx = - 2; dy = -2; break; + case 145: dx = 0; dy = -2; break; + case 144: dx = 0; dy = 1; break; + case 142: dx = 1; dy = 2; break; + case 141: dx = 0; dy = 4; break;// a + case 140: dx = 0; dy = 0; break; //a + case 139: dx = 1; dy = 1; break;// a + case 138: dx = 3; dy = 1; break; + case 137: dx = 1; dy = 0; break; + case 135: dx = - 1; dy = 0; break; + case 134: dx = 0; dy = 2; break; + case 133: dx = - 1; dy = -1; break; + case 130: dx = - 1; dy = 2; break; + case 127: dx = 0; dy = 1; break; + case 126: dx = 1; dy = 4; break;// a + case 124: dx = 0; dy = 3; break; + case 123: dx = - 1; dy = 3; break;// a + case 120: dx = 0; dy = 1; break; + case 119: dx = 0; dy = 1; break; + case 116: dx = 0; dy = 1; break; + case 115: dx = 0; dy = 4; break;// a + case 114: dx = 0; dy = 1; break; + case 112: dx = 0; dy = -1; break; + case 109: dx = 3; dy = 3; break; + case 108: dx = 2; dy = 3; break; + case 106: dx = 0; dy = 2; break; + case 105: dx = 1; dy = 0; break; + case 104: dx = 0; dy = 1; break; + case 103: dx = 0; dy = 1; break; + case 102: dx = 0; dy = 1; break; + case 100: dx = 0; dy = 3; break; + case 99: dx = 1; dy = 2; break; + case 98: dx = 0; dy = 2; break; + case 95: dx = 1; dy = 1; break; + case 94: dx = 1; dy = 0; break; + case 93: dx = 0; dy = 2; break; + case 92: dx = 0; dy = 2; break; + case 90: dx = 0; dy = 1; break; + case 89: dx = 1; dy = 8; break; + case 88: dx = 0; dy = 1; break; + case 87: dx = 0; dy = 1; break; + case 86: dx = 0; dy = 2; break; + case 85: dx = 0; dy = 2; break; + case 84: dx = 1; dy = 1; break; + case 83: dx = 0; dy = 3; break; + case 82: dx = 1; dy = 2; break; + case 81: dx = - 2; dy = -3; break; + case 76: dx = -1; dy = -3; break; + case 75: dx = -2; dy = 0; break; + case 74: dx = 2; dy = 0; break; + case 72: dx = -1; dy = 0; break; + case 69: dx = 0; dy = 1; break; + case 68: dx = 1; dy = 0; break; + case 66: dx = 0; dy = 1; break; + case 65: dx = 1; dy = 0; break; + case 64: dx = 0; dy = 4; break; + case 63: dx = 0; dy = 2; break; + case 60: dx = 0; dy = 1; break;// ? + case 57: dx = 0; dy = 1; break;// ? + case 56: dx = 0; dy = 1; // make the amulet more round + if (needsPatch) { + gpBuffer[16 + BUFFER_WIDTH * 25] = 188; + gpBuffer[17 + BUFFER_WIDTH * 25] = 186; + gpBuffer[18 + BUFFER_WIDTH * 25] = 185; + gpBuffer[19 + BUFFER_WIDTH * 25] = 184; + gpBuffer[20 + BUFFER_WIDTH * 25] = 183; + } + break; + case 55: dx = -1; dy = 3; break; + case 52: dx = 0; dy = 1; break; + case 51: dx = -1; dy = 0; break; + case 49: dx = 1; dy = 0; break; + case 43: dx = -1; dy = 0; break; + case 42: dx = 1; dy = 0; break; + case 39: dx = 0; dy = -1; break; + case 36: dx = 1; dy = 0; break; + case 37: dx = 0; dy = 1; break; + case 35: dx = 1; dy = 0; break; + case 34: dx = 2; dy = 1; break; + case 33: dx = 0; dy = 1; break; + case 32: dx = -1; dy = 1; break; + case 31: dx = 0; dy = 1; break; + case 30: dx = 2; dy = 0; break; + case 27: dx = 0; dy = 1; break; + case 26: dx = 1; dy = 0; break; + case 25: dx = 0; dy = 1; break; + case 24: dx = 1; dy = 0; break; + case 22: dx = 0; dy = 1; break; + case 20: dx = 1; dy = 2; break; + case 19: dx = 1; dy = 1; break; + case 13: dx = 1; dy = 0; + needsPatch = gpBuffer[25 + BUFFER_WIDTH * 4] == TRANS_COLOR; // assume it is already done + break; + } + + if (needsPatch) { + moveImage(InvItemWidth[i + 1], InvItemHeight[i + 1], dx, dy, TRANS_COLOR); + } + + // write to the new CEL file + dstHeaderCursor[0] = SwapLE32((size_t)dstDataCursor - (size_t)resCelBuf); + dstHeaderCursor++; + + dstDataCursor = EncodeFrame(dstDataCursor, InvItemWidth[i + 1], InvItemHeight[i + 1], SUB_HEADER_SIZE, TRANS_COLOR); + + // skip the original frame + srcHeaderCursor++; + } + + // add file-size + *celLen = (size_t)dstDataCursor - (size_t)resCelBuf; + dstHeaderCursor[0] = SwapLE32(*celLen); + + return resCelBuf; +} + BYTE* fixGoatLdAnim(BYTE* cl2Buf, size_t *dwLen) { constexpr BYTE TRANS_COLOR = 1; @@ -4204,21 +4435,26 @@ static BYTE* patchFile(int index, size_t *dwLen) buf = fixGoatLdAnim(buf, dwLen); } break; #endif // ASSET_MPL +#endif // HELLFIRE case FILE_OBJCURS_CEL: { +#ifdef HELLFIRE size_t sizeB, sizeAB; BYTE *aCursCels, *bCursCels; - DWORD numA, numAB; + DWORD numAB; +#endif + DWORD numA; numA = SwapLE32(((DWORD*)buf)[0]); if (numA != 179) { - if (numA != 179 + 61 - 2) { + if (numA != NUM_ICURS + CURSOR_FIRSTITEM - 1 /* 179 + 61 - 2*/) { mem_free_dbg(buf); app_warn("Invalid file %s in the mpq.", filesToPatch[index]); buf = NULL; } return buf; } +#ifdef HELLFIRE bCursCels = LoadFileInMem("Data\\Inv\\Objcurs2.CEL", &sizeB); // merge the two cel files aCursCels = buf; @@ -4242,8 +4478,10 @@ static BYTE* patchFile(int index, size_t *dwLen) mem_free_dbg(buf); buf = aCursCels; *dwLen = sizeAB; - } break; #endif // HELLFIRE + // move the graphics to the center + minor adjustments + buf = centerCursors(buf, dwLen); + } break; default: ASSUME_UNREACHABLE break; From a22a21aeed561e7f50720049ba36aebc461304db Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 10 Aug 2024 17:15:59 +0200 Subject: [PATCH 418/596] adjust the positions of the equipment-slots --- Source/inv.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Source/inv.cpp b/Source/inv.cpp index 9a57f92cbab..686fd8f72e9 100644 --- a/Source/inv.cpp +++ b/Source/inv.cpp @@ -36,18 +36,18 @@ CelImageBuf* pBeltCels; const InvXY InvRect[NUM_XY_SLOTS] = { // clang-format off // X, Y - { 121, 29 }, // helmet - { 121 + INV_SLOT_SIZE_PX, 29 }, // helmet - { 121, 29 + INV_SLOT_SIZE_PX }, // helmet - { 121 + INV_SLOT_SIZE_PX, 29 + INV_SLOT_SIZE_PX }, // helmet - { 61, 171 }, // left ring - { 206, 171 }, // right ring - { 187, 45 }, // amulet + { 120, 30 }, // helmet + { 120 + INV_SLOT_SIZE_PX, 30 }, // helmet + { 120, 30 + INV_SLOT_SIZE_PX }, // helmet + { 120 + INV_SLOT_SIZE_PX, 30 + INV_SLOT_SIZE_PX }, // helmet + { 60, 172 }, // left ring + { 205, 172 }, // right ring + { 186, 44 }, // amulet { 47, 82 }, // left hand { 47 + INV_SLOT_SIZE_PX, 82 }, // left hand { 47, 82 + INV_SLOT_SIZE_PX }, // left hand { 47 + INV_SLOT_SIZE_PX, 82 + INV_SLOT_SIZE_PX }, // left hand - { 57, 82 + 2*INV_SLOT_SIZE_PX }, // left hand + { 47, 82 + 2*INV_SLOT_SIZE_PX }, // left hand { 47 + INV_SLOT_SIZE_PX, 82 + 2*INV_SLOT_SIZE_PX }, // left hand { 192, 82 }, // right hand { 192 + INV_SLOT_SIZE_PX, 82 }, // right hand @@ -55,12 +55,12 @@ const InvXY InvRect[NUM_XY_SLOTS] = { { 192 + INV_SLOT_SIZE_PX, 82 + INV_SLOT_SIZE_PX }, // right hand { 192, 82 + 2*INV_SLOT_SIZE_PX }, // right hand { 192 + INV_SLOT_SIZE_PX, 82 + 2*INV_SLOT_SIZE_PX }, // right hand - { 121, 93 }, // chest - { 121 + INV_SLOT_SIZE_PX, 93 }, // chest - { 121, 93 + INV_SLOT_SIZE_PX }, // chest - { 121 + INV_SLOT_SIZE_PX, 93 + INV_SLOT_SIZE_PX }, // chest - { 121, 93 + 2*INV_SLOT_SIZE_PX }, // chest - { 121 + INV_SLOT_SIZE_PX, 93 + 2*INV_SLOT_SIZE_PX }, // chest + { 120, 94 }, // chest + { 120 + INV_SLOT_SIZE_PX, 94 }, // chest + { 120, 94 + INV_SLOT_SIZE_PX }, // chest + { 120 + INV_SLOT_SIZE_PX, 94 + INV_SLOT_SIZE_PX }, // chest + { 120, 94 + 2*INV_SLOT_SIZE_PX }, // chest + { 120 + INV_SLOT_SIZE_PX, 94 + 2*INV_SLOT_SIZE_PX }, // chest { 2 + 0 * (INV_SLOT_SIZE_PX + 1), 206 }, // inv row 1 { 2 + 1 * (INV_SLOT_SIZE_PX + 1), 206 }, // inv row 1 { 2 + 2 * (INV_SLOT_SIZE_PX + 1), 206 }, // inv row 1 From 83d711792b52bb33fe69bf759245a1ba4c8a350c Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 11 Aug 2024 10:45:38 +0200 Subject: [PATCH 419/596] document the micaster/misource parameters of the Add*missile* functions --- Source/missiles.cpp | 144 ++++++++++++++++++++++++++------------------ Source/objects.cpp | 2 +- 2 files changed, 86 insertions(+), 60 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index d1115dc1ced..9121a600e43 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -1565,7 +1565,7 @@ static int PlaceRune(int mi, int sx, int sy, int dx, int dy, int mitype, int mir int i, j, tx, ty; const int8_t* cr; MissileStruct* mis; - + // (micaster == MST_PLAYER || micaster == MST_OBJECT); mis = &missile[mi]; mis->_miVar1 = mitype; mis->_miVar2 = mirange; // trigger range @@ -1649,6 +1649,8 @@ int AddStoneRune(int mi, int sx, int sy, int dx, int dy, int midir, int micaster int AddHorkSpawn(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { + // (micaster == MST_MONSTER); + // 'assert'(misource < MAXMONSTERS); GetMissileVel(mi, sx, sy, dx, dy, MIS_SHIFTEDVEL(8)); // missile[mi]._miMinDam = missile[mi]._miMaxDam = 0; missile[mi]._miRange = 9 - 1; @@ -1678,12 +1680,12 @@ int AddFireexp(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, { MissileStruct* mis; int mindam, maxdam, dam; - + // ((micaster & MST_PLAYER) || micaster == MST_OBJECT); mis = &missile[mi]; mis->_miRange = misfiledata[MFILE_BIGEXP].mfAnimLen[0] * misfiledata[MFILE_BIGEXP].mfAnimFrameLen[0]; if (misource != -1) { - assert((unsigned)misource < MAX_PLRS); + // assert((unsigned)misource < MAX_PLRS); mindam = 1 + (plx(misource)._pMagic >> 1) + 16 * spllvl; maxdam = 1 + (plx(misource)._pMagic >> 1) + 32 * spllvl; dam = RandRange(mindam, maxdam); @@ -1730,7 +1732,7 @@ int AddRingC(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in { int tx, ty, j, mitype; const int8_t* cr; - + // ((micaster & MST_PLAYER) || micaster == MST_OBJECT); mitype = MIS_FIREWALL; //mis->_miType == MIS_FIRERING ? MIS_FIREWALL : MIS_LIGHTWALL; static_assert(DBORDERX >= 3 && DBORDERY >= 3, "AddRingC expects a large enough border."); @@ -1881,6 +1883,8 @@ int AddFirebolt(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int AddMagmaball(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { MissileStruct* mis; + // (micaster == MST_MONSTER); + // assert(misource < MAXMONSTERS); GetMissileVel(mi, sx, sy, dx, dy, MIS_SHIFTEDVEL(16)); mis = &missile[mi]; @@ -1899,7 +1903,7 @@ int AddLightball(int mi, int sx, int sy, int dx, int dy, int midir, int micaster { MissileStruct* mis; int mindam, maxdam; - + // ((micaster & MST_PLAYER) || micaster == MST_OBJECT); if (sx == dx && sy == dy) { dx += XDirAdd[midir]; dy += YDirAdd[midir]; @@ -1927,7 +1931,8 @@ int AddPoison(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, i { MissileStruct* mis; int magic, mindam, maxdam; - + // (micaster & MST_PLAYER); + // assert((unsigned)misource < MAX_PLRS); if (sx == dx && sy == dy) { dx += XDirAdd[midir]; dy += YDirAdd[midir]; @@ -1937,7 +1942,6 @@ int AddPoison(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, i mis = &missile[mi]; mis->_miRange = 16 * spllvl + 96; //if (misource != -1) { - assert((unsigned)misource < MAX_PLRS); // TODO: add support for spell duration modifier // range += (plx(misource)._pISplDur * range) >> 7; magic = plx(misource)._pMagic; @@ -1961,7 +1965,8 @@ int AddWind(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int { MissileStruct* mis; int magic, mindam, maxdam; - + // (micaster & MST_PLAYER); + // assert((unsigned)misource < MAX_PLRS); if (sx == dx && sy == dy) { dx += XDirAdd[midir]; dy += YDirAdd[midir]; @@ -1974,7 +1979,6 @@ int AddWind(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int GetMissilePos(mi); mis->_miRange = 255; //if (misource != -1) { - assert((unsigned)misource < MAX_PLRS); magic = plx(misource)._pMagic; mindam = (magic >> 3) + 7 * spllvl + 1; maxdam = (magic >> 3) + 8 * spllvl + 1; @@ -1992,7 +1996,8 @@ int AddWind(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int int AddAcid(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { MissileStruct* mis; - + // (micaster == MST_MONSTER); + // assert(misource < MAXMONSTERS); GetMissileVel(mi, sx, sy, dx, dy, MIS_SHIFTEDVEL(16)); SetMissDir(mi, GetDirection16(sx, sy, dx, dy)); mis = &missile[mi]; @@ -2008,7 +2013,8 @@ int AddAcidpud(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, { MissileStruct* mis; int dam; - + // (micaster == MST_MONSTER); + // assert(misource < MAXMONSTERS); mis = &missile[mi]; if (spllvl == 0) { // pud from a missile @@ -2037,7 +2043,8 @@ int AddTeleport(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, { int i, j, tx, ty; const int8_t* cr; - + // (micaster & MST_PLAYER); + // assert((unsigned)misource < MAX_PLRS); // MisInCastDistance(sx, sy, midir, dx, dy, 7); while (true) { tx = sx - dx; @@ -2050,7 +2057,6 @@ int AddTeleport(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, dy += offset_y[OPPOSITE(midir)]; } - assert((unsigned)misource < MAX_PLRS); static_assert(DBORDERX >= 5 && DBORDERY >= 5, "AddTeleport expects a large enough border."); for (i = 0; i <= 5; i++) { cr = &CrawlTable[CrawlNum[i]]; @@ -2070,8 +2076,8 @@ int AddTeleport(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int AddRndTeleport(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { int nTries; - - assert((unsigned)misource < MAX_PLRS); + // ((micaster & MST_PLAYER) || micaster == MST_OBJECT); + // assert((unsigned)misource < MAX_PLRS); static_assert(DBORDERX >= 6 && DBORDERY >= 6, "AddRndTeleport expects a large enough border."); if ((micaster & MST_PLAYER) || (dx == 0 && dy == 0)) { nTries = 0; @@ -2103,11 +2109,11 @@ int AddFirewall(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, { MissileStruct* mis; int magic, mindam, maxdam; - + // ((micaster & MST_PLAYER) || micaster == MST_OBJECT); mis = &missile[mi]; mis->_miRange = 64 * spllvl + 160; if (misource != -1) { - assert((unsigned)misource < MAX_PLRS); + // assert((unsigned)misource < MAX_PLRS); // TODO: add support for spell duration modifier // range += (plx(misource)._pISplDur * range) >> 7; magic = plx(misource)._pMagic; @@ -2228,7 +2234,8 @@ int AddLightning(int mi, int sx, int sy, int dx, int dy, int midir, int micaster int AddBloodBoilC(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { MissileStruct* mis; - + // (micaster & MST_PLAYER); + // 'assert'((unsigned)misource < MAX_PLRS); mis = &missile[mi]; mis->_mix = dx - 2; @@ -2245,7 +2252,8 @@ int AddBloodBoil(int mi, int sx, int sy, int dx, int dy, int midir, int micaster int mindam, maxdam; mis = &missile[mi]; - // assert(micaster & MST_PLAYER); + // (micaster & MST_PLAYER); + // assert((unsigned)misource < MAX_PLRS); mindam = (plx(misource)._pMagic >> 2) + (spllvl << 2) + 10; maxdam = (plx(misource)._pMagic >> 2) + (spllvl << 3) + 10; @@ -2295,8 +2303,8 @@ int AddShroud(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, i MissileStruct* mis; int i, j, tx, ty; const int8_t* cr; - - assert((unsigned)misource < MAX_PLRS); + // (micaster & MST_PLAYER); + // ((unsigned)misource < MAX_PLRS); mis = &missile[mi]; static_assert(DBORDERX >= 5 && DBORDERY >= 5, "AddShroud expects a large enough border."); @@ -2359,7 +2367,8 @@ int AddTown(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int { int i, j, tx, ty; const int8_t* cr; - // assert((unsigned)misource < MAX_PLRS); + // ((micaster & MST_PLAYER) || micaster == MST_NA); + // ((unsigned)misource < MAX_PLRS); // the position of portals in town and recreated portals are fixed if (currLvl._dType != DTYPE_TOWN && spllvl >= 0) { const int RANGE = 6; @@ -2396,7 +2405,7 @@ int AddTown(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int int AddPortal(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { MissileStruct* mis; - + // ((micaster & MST_PLAYER) || micaster == MST_NA); mis = &missile[mi]; mis->_mix = mis->_misx = dx; mis->_miy = mis->_misy = dy; @@ -2453,11 +2462,11 @@ int AddFireWave(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, { MissileStruct* mis; int magic, mindam, maxdam; - + // ((micaster & MST_PLAYER) || micaster == MST_OBJECT); GetMissileVel(mi, sx, sy, dx, dy, MIS_SHIFTEDVEL(16)); mis = &missile[mi]; if (misource != -1) { - assert((unsigned)misource < MAX_PLRS); + // assert((unsigned)misource < MAX_PLRS); magic = plx(misource)._pMagic; mindam = (magic >> 3) + 2 * spllvl + 1; maxdam = (magic >> 3) + 4 * spllvl + 2; @@ -2479,7 +2488,8 @@ int AddMeteor(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, i MissileStruct* mis; int mindam, maxdam, i, j, tx, ty; const int8_t* cr; - + // (micaster & MST_PLAYER); + // assert((unsigned)misource < MAX_PLRS); mis = &missile[mi]; //if (micaster & MST_PLAYER) { mindam = (plx(misource)._pMagic >> 2) + (spllvl << 3) + 40; @@ -2521,9 +2531,8 @@ int AddMeteor(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, i int AddChain(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { MissileStruct* mis; - - assert((unsigned)misource < MAX_PLRS); - + // (micaster & MST_PLAYER); + // assert((unsigned)misource < MAX_PLRS); if (sx == dx && sy == dy) { dx += XDirAdd[midir]; dy += YDirAdd[midir]; @@ -2553,7 +2562,8 @@ int AddChain(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in int AddRhino(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { MissileStruct* mis; - + // (micaster == MST_MONSTER); + // assert((unsigned)misource < MAXMONSTERS); GetMissileVel(mi, sx, sy, dx, dy, MIS_SHIFTEDVEL(18)); //assert(dMonster[sx][sy] == misource + 1); dMonster[sx][sy] = -(misource + 1); @@ -2575,7 +2585,8 @@ int AddCharge(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, i { MissileStruct* mis; int pnum = misource, chv, aa; - + // (micaster & MST_PLAYER); + // assert((unsigned)pnum < MAX_PLRS); dPlayer[sx][sy] = -(pnum + 1); if (sx == dx && sy == dy) { dx += XDirAdd[midir]; @@ -2687,8 +2698,8 @@ int AddStone(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in MonsterStruct* mon; int i, j, tx, ty, mid, range; const int8_t* cr; - - assert((unsigned)misource < MAX_PLRS); + // (micaster & MST_PLAYER); + // assert((unsigned)misource < MAX_PLRS); mis = &missile[mi]; static_assert(DBORDERX >= 2 && DBORDERY >= 2, "AddStone expects a large enough border."); for (i = 0; i <= 2; i++) { @@ -2740,8 +2751,8 @@ int AddGuardian(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, MissileStruct* mis; int i, j, tx, ty; const int8_t* cr; - - assert((unsigned)misource < MAX_PLRS); + // (micaster & MST_PLAYER); + // assert((unsigned)misource < MAX_PLRS); mis = &missile[mi]; static_assert(DBORDERX >= 5 && DBORDERY >= 5, "AddGuardian expects a large enough border."); @@ -2771,9 +2782,9 @@ int AddGolem(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in MonsterStruct* mon; int tx, ty, i, j; const int8_t* cr; - - assert((unsigned)misource < MAX_PLRS); - + // (micaster & MST_PLAYER); + // ((unsigned)misource < MAX_PLRS); + static_assert(MAX_MINIONS == MAX_PLRS, "AddGolem requires that owner of a monster has the same id as the monster itself."); mon = &monsters[misource]; if (mon->_mmode > MM_INGAME_LAST) { static_assert(DBORDERX >= 5 && DBORDERY >= 5, "AddGolem expects a large enough border."); @@ -2805,8 +2816,8 @@ int AddGolem(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in int AddHeal(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { int i, hp; - - assert((unsigned)misource < MAX_PLRS); + // (micaster & MST_PLAYER); + // assert((unsigned)misource < MAX_PLRS); hp = RandRange(1, 10); for (i = spllvl; i > 0; i--) { @@ -2837,8 +2848,8 @@ int AddHealOther(int mi, int sx, int sy, int dx, int dy, int midir, int micaster { int tnum, i, hp; MonsterStruct* mon; - - assert((unsigned)misource < MAX_PLRS); + // (micaster & MST_PLAYER); + // assert((unsigned)misource < MAX_PLRS); // calculate hp hp = RandRange(1, 10); for (i = spllvl; i > 0; i--) { @@ -2896,8 +2907,8 @@ int AddElemental(int mi, int sx, int sy, int dx, int dy, int midir, int micaster { MissileStruct* mis; int magic, i, mindam, maxdam; - - assert((unsigned)misource < MAX_PLRS); + // (micaster & MST_PLAYER); + // assert((unsigned)misource < MAX_PLRS); if (sx == dx && sy == dy) { dx += XDirAdd[midir]; dy += YDirAdd[midir]; @@ -2938,8 +2949,8 @@ int AddWallC(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in MissileStruct* mis; int i, j, tx, ty; const int8_t* cr; - - assert((unsigned)misource < MAX_PLRS); + // (micaster & MST_PLAYER); + // ((unsigned)misource < MAX_PLRS); static_assert(DBORDERX >= 5 && DBORDERY >= 5, "AddWallC expects a large enough border."); mis = &missile[mi]; for (i = 0; i <= 5; i++) { @@ -2967,7 +2978,8 @@ int AddWallC(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in int AddFireWaveC(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { - assert((unsigned)misource < MAX_PLRS); + // (micaster & MST_PLAYER); + // ((unsigned)misource < MAX_PLRS); int sd, nx, ny, dir; int i, j; @@ -3000,6 +3012,7 @@ int AddNovaC(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in { int i, tx, ty; const int8_t* cr; + // ((micaster & MST_PLAYER) || micaster == MST_OBJECT); static_assert(DBORDERX >= 3 && DBORDERY >= 3, "AddNovaC expects a large enough border."); cr = &CrawlTable[CrawlNum[3]]; for (i = *cr; i > 0; i--) { @@ -3015,7 +3028,7 @@ int AddDisarm(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, i { int oi = spllvl; int pnum = misource; - + // (micaster & MST_PLAYER); // assert((unsigned)pnum < MAX_PLRS); // assert((unsigned)oi < MAXOBJECTS); // assert(objects[oi]._oBreak == OBM_UNBREAKABLE); @@ -3034,7 +3047,7 @@ int AddInferno(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, MissileStruct* mis; MissileStruct* bmis; int mindam, maxdam; - + // ((micaster & MST_PLAYER) || micaster == MST_MONSTER); mis = &missile[mi]; static_assert(MAX_LIGHT_RAD >= 1, "AddInferno needs at least light-radius of 1."); bmis = &missile[midir]; @@ -3067,7 +3080,7 @@ int AddInferno(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int AddInfernoC(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { MissileStruct* mis; - + // ((micaster & MST_PLAYER) || micaster == MST_MONSTER); if (sx == dx && sy == dy) { dx += XDirAdd[midir]; dy += YDirAdd[midir]; @@ -3094,7 +3107,7 @@ int AddInfernoC(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int AddBarrelExp(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { MissileStruct* mis; - + // (micaster == MST_NA); mis = &missile[mi]; mis->_miMinDam = 8 << (6 + gnDifficulty); mis->_miMaxDam = 16 << (6 + gnDifficulty); @@ -3107,6 +3120,8 @@ int AddCboltC(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, i { int i = 3; + // ((micaster & MST_PLAYER) || micaster == MST_MONSTER); + // checks commented out, because spllvl is zero if the caster is not a player //if (misource != -1) { // if (micaster & MST_PLAYER) { @@ -3129,7 +3144,7 @@ int AddCboltC(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, i int AddCbolt(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { MissileStruct* mis; - + // ((micaster & MST_PLAYER) || micaster == MST_MONSTER); if (sx == dx && sy == dy) { dx += XDirAdd[midir]; dy += YDirAdd[midir]; @@ -3158,6 +3173,9 @@ int AddResurrect(int mi, int sx, int sy, int dx, int dy, int midir, int micaster { MissileStruct* mis; + // (micaster & MST_PLAYER); + // ((unsigned)misource < MAX_PLRS); + if (spllvl == mypnum) NetSendCmd(CMD_PLRRESURRECT); @@ -3176,6 +3194,9 @@ int AddAttract(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int dist, i, j, tx, ty, mnum; const int8_t* cr; + // (micaster & MST_PLAYER); + // ((unsigned)misource < MAX_PLRS); + if (!LineClear(sx, sy, dx, dy)) return MIRES_FAIL_DELETE; @@ -3215,6 +3236,7 @@ int AddTelekinesis(int mi, int sx, int sy, int dx, int dy, int midir, int micast int target = spllvl & 0xFFFF; int type = spllvl >> 16; bool ret; + // (micaster & MST_PLAYER); // assert((unsigned)pnum < MAX_PLRS); switch (type) { @@ -3251,8 +3273,11 @@ int AddApocaC2(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, MissileStruct* mis; int pnum, px, py; + // (micaster == MST_MONSTER); + // (misource == DIABLO); + mis = &missile[mi]; - mis->_miMinDam = mis->_miMaxDam = 40 << (6 + gnDifficulty); // assert(misource == DIABLO); + mis->_miMinDam = mis->_miMaxDam = 40 << (6 + gnDifficulty); for (pnum = 0; pnum < MAX_PLRS; pnum++) { if (!plr._pActive || plr._pDunLevel != currLvl._dLevelIdx) @@ -3284,7 +3309,8 @@ int AddApocaC2(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int AddManashield(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { - assert((unsigned)misource < MAX_PLRS); + // ((micaster & MST_PLAYER) || micaster == MST_NA); + // ((unsigned)misource < MAX_PLRS); if (misource == mypnum) { if (plx(misource)._pManaShield == 0) @@ -3298,8 +3324,8 @@ int AddManashield(int mi, int sx, int sy, int dx, int dy, int midir, int micaste int AddInfra(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { int i, range; - - assert((unsigned)misource < MAX_PLRS); + // ((micaster & MST_PLAYER) || micaster == MST_NA); + // assert((unsigned)misource < MAX_PLRS); range = 1584; for (i = spllvl; i > 0; i--) { range += range >> 3; @@ -3312,10 +3338,10 @@ int AddInfra(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in int AddRage(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { - int pnum; + int pnum = misource; + // (micaster & MST_PLAYER); + // assert((unsigned)pnum < MAX_PLRS); - pnum = misource; - assert((unsigned)pnum < MAX_PLRS); if (plr._pTimer[PLTR_RAGE] == 0) { plr._pTimer[PLTR_RAGE] = 32 * spllvl + 245; PlaySfxLoc(sgSFXSets[SFXS_PLR_70][plr._pClass], plr._px, plr._py); diff --git a/Source/objects.cpp b/Source/objects.cpp index 40794c1076a..e1ed3c5ab4c 100644 --- a/Source/objects.cpp +++ b/Source/objects.cpp @@ -3178,7 +3178,7 @@ static void OperateBarrel(int pnum, int oi, bool sendmsg) if (os->_otype == xotype) { for (yp = os->_oy - 1; yp <= os->_oy + 1; yp++) { for (xp = os->_ox - 1; xp <= os->_ox + 1; xp++) { - AddMissile(xp, yp, 0, 0, 0, MIS_BARRELEX, MST_OBJECT, -1, 0); + AddMissile(xp, yp, 0, 0, 0, MIS_BARRELEX, MST_NA, -1, 0); mpo = dObject[xp][yp]; if (mpo > 0) { mpo--; From 6c9c324540e52d51f99acc597a1f9d47a6fb64c3 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 11 Aug 2024 17:26:34 +0200 Subject: [PATCH 420/596] get rid of two obsolete assertions --- Source/monster.cpp | 1 - Source/player.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index a9d8615347f..d85081a80f4 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -4652,7 +4652,6 @@ void MissToMonst(int mi) // assert(dPlayer[mon->_mx][mon->_my] == 0); // assert(!(mon->_mFlags & MFLAG_HIDDEN)); //ChangeLightXYOff(mon->_mlid, mon->_mx, mon->_my); - assert(mon->_mdir == mis->_miDir); MonStartStand(mnum); /*if (mon->_mType >= MT_INCIN && mon->_mType <= MT_HELLBURN) { MonStartFadein(mnum, false); diff --git a/Source/player.cpp b/Source/player.cpp index b92e4346b6d..13b6e1b2b18 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -2915,7 +2915,6 @@ void MissToPlr(int mi, bool hit) //ChangeLightXYOff(plr._plid, plr._px, plr._py); //ChangeVisionXY(plr._pvid, plr._px, plr._py); if (!hit || plr._pHitPoints < (1 << 6)) { - assert(plr._pdir == mis->_miDir); PlrStartStand(pnum); return; } From df6c52f0a2377039eeff02164d48ee7878a4dc77 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 11 Aug 2024 17:50:44 +0200 Subject: [PATCH 421/596] fix the parameter-name of MissToMonst (monster.h) --- Source/monster.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/monster.h b/Source/monster.h index 46b0cd7f650..3fa89ff4399 100644 --- a/Source/monster.h +++ b/Source/monster.h @@ -59,7 +59,7 @@ void FreeMonsters(); //bool CheckAllowMissile(int x, int y); bool LineClear(int x1, int y1, int x2, int y2); void SyncMonsterAnim(int mnum); -void MissToMonst(int mnum); +void MissToMonst(int mi); /* Check if the monster can be displaced to the given position. (unwillingly) */ bool PosOkMonster(int mnum, int x, int y); /* Check if the monster can be placed to the given position. (willingly) */ From 05a636cfd0539b2e85daf8b231c0413749d10639 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 12 Aug 2024 07:23:27 +0200 Subject: [PATCH 422/596] fix the patcher after 'patch ObjCurs.CEL' --- tools/patcher/cursor.cpp | 76 ++++++++++++++++++++++++++++++++++++++-- tools/patcher/cursor.h | 2 ++ 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/tools/patcher/cursor.cpp b/tools/patcher/cursor.cpp index 6d065bc8641..8ee2761a077 100644 --- a/tools/patcher/cursor.cpp +++ b/tools/patcher/cursor.cpp @@ -18,6 +18,78 @@ BYTE* pCursCels; /** Index of current cursor image */ int pcursicon; +/* Maps from objcurs.cel frame number to frame width. + **If the values are modified, make sure validateCursorAreas does not fail.** + */ +/*constexpr*/ const int InvItemWidth[(int)CURSOR_FIRSTITEM + (int)NUM_ICURS] = { + // clang-format off + // Cursors + 0, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 23, + // Items + 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, + 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, + 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, + 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, + 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, + 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, + 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, + 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, + 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, + 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, + 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, + 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, + 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, + 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, + 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, + 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, + 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, +#ifdef HELLFIRE + 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, + 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, + 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, + 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, + 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, + 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX +#endif + // clang-format on +}; + +/* Maps from objcurs.cel frame number to frame height. + **If the values are modified, make sure validateCursorAreas does not fail.** + */ +/*constexpr*/ const int InvItemHeight[(int)CURSOR_FIRSTITEM + (int)NUM_ICURS] = { + // clang-format off + // Cursors + 0, 29, 32, 32, 32, 32, 32, 32, 32, 32, 32, 35, + // Items + 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, + 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, + 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, + 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, + 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, + 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, + 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, + 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, + 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, + 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, + 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, + 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, + 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, + 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, + 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, + 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, + 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, +#ifdef HELLFIRE + 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, + 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, + 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, 1 * INV_SLOT_SIZE_PX, + 2 * INV_SLOT_SIZE_PX, 2 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, + 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, + 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX, 3 * INV_SLOT_SIZE_PX +#endif + // clang-format on +}; + void InitCursorGFX() { assert(pCursCels == NULL); @@ -36,8 +108,8 @@ void FreeCursorGFX() void NewCursor(int i) { pcursicon = i; - cursW = 33; // InvItemWidth[i]; - cursH = 29; // InvItemHeight[i]; + cursW = InvItemWidth[i]; + cursH = InvItemHeight[i]; } DEVILUTION_END_NAMESPACE diff --git a/tools/patcher/cursor.h b/tools/patcher/cursor.h index b7b7fc726f3..2b68e2b9d39 100644 --- a/tools/patcher/cursor.h +++ b/tools/patcher/cursor.h @@ -23,6 +23,8 @@ void NewCursor(int i); /* rdata */ #define MAX_CURSOR_AREA 8192 +extern const int InvItemWidth[(int)CURSOR_FIRSTITEM + (int)NUM_ICURS]; +extern const int InvItemHeight[(int)CURSOR_FIRSTITEM + (int)NUM_ICURS]; #ifdef __cplusplus } From 587d07319cbd9dccb77633b4b5145459864708e3 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 12 Aug 2024 07:25:23 +0200 Subject: [PATCH 423/596] sync AddStoreSell/AddStoreHoldRepair/AddStoreHoldRecharge/AddStoreHoldId --- Source/stores.cpp | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index 20efc5f1a76..9ddbac3a783 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -555,21 +555,23 @@ static void S_StartSPBuy() //return true; } -static void AddStoreSell(ItemStruct* is, int i) +static void AddStoreSell(const ItemStruct* is, int i) { + ItemStruct* itm; int value; copy_pod(storehold[storenumh], *is); - is = &storehold[storenumh]; - value = (is->_iMagical != ITEM_QUALITY_NORMAL && is->_iIdentified) ? is->_iIvalue : is->_ivalue; + itm = &storehold[storenumh]; + value = (itm->_iMagical != ITEM_QUALITY_NORMAL && itm->_iIdentified) ? itm->_iIvalue : itm->_ivalue; value >>= 3; if (value == 0) value = 1; - is->_iIvalue = is->_ivalue = value; + itm->_iIvalue = itm->_ivalue = value; - storehidx[storenumh++] = i; + storehidx[storenumh] = i; + storenumh++; } static bool SmithSellOk(const ItemStruct* is) @@ -651,18 +653,17 @@ static bool SmithRepairOk(const ItemStruct* is) static void AddStoreHoldRepair(const ItemStruct* is, int i) { ItemStruct* itm; - int v; + int value; itm = &storehold[storenumh]; copy_pod(*itm, *is); - v = std::max(itm->_ivalue, itm->_iIvalue / 3); - v = v * (itm->_iMaxDur - itm->_iDurability) / (itm->_iMaxDur * 2); - if (v == 0) - v = 1; + value = std::max(itm->_ivalue, itm->_iIvalue / 3); + value = value * (itm->_iMaxDur - itm->_iDurability) / (itm->_iMaxDur * 2); + if (value == 0) + value = 1; - itm->_iIvalue = v; - itm->_ivalue = v; + itm->_iIvalue = itm->_ivalue = value; storehidx[storenumh] = i; storenumh++; } @@ -815,12 +816,13 @@ static bool WitchRechargeOk(const ItemStruct* is) static void AddStoreHoldRecharge(const ItemStruct* is, int i) { ItemStruct* itm; + int value; itm = &storehold[storenumh]; copy_pod(*itm, *is); - itm->_ivalue += spelldata[itm->_iSpell].sStaffCost; - itm->_ivalue = itm->_ivalue * (itm->_iMaxCharges - itm->_iCharges) / itm->_iMaxCharges; - itm->_iIvalue = itm->_ivalue; + value = itm->_ivalue + spelldata[itm->_iSpell].sStaffCost; + value = value * (itm->_iMaxCharges - itm->_iCharges) / itm->_iMaxCharges; + itm->_iIvalue = itm->_ivalue = value; storehidx[storenumh] = i; storenumh++; } @@ -1065,12 +1067,11 @@ static bool IdItemOk(const ItemStruct* is) static void AddStoreHoldId(const ItemStruct* is, int i) { - ItemStruct* holditem; + ItemStruct* itm; - holditem = &storehold[storenumh]; - copy_pod(*holditem, *is); - holditem->_ivalue = STORE_ID_PRICE; - holditem->_iIvalue = STORE_ID_PRICE; + itm = &storehold[storenumh]; + copy_pod(*itm, *is); + itm->_ivalue = itm->_iIvalue = STORE_ID_PRICE; storehidx[storenumh] = i; storenumh++; } From ee7987a58a1869c5391063e8b9014d8ab1be838b Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 12 Aug 2024 12:36:37 +0200 Subject: [PATCH 424/596] fix a few warnings --- Source/control.cpp | 2 +- Source/gamemenu.cpp | 6 +++--- Source/path.cpp | 6 ++++-- Source/stores.cpp | 1 - 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Source/control.cpp b/Source/control.cpp index 6cb29d6eeb0..be50e3ba9b9 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -2528,7 +2528,7 @@ void DrawCampaignMap() sx += CAMICON_WIDTH * (CAM_RADIUS - lengthof(camEntries) / 2); sy += CAMICON_HEIGHT * (CAM_RADIUS - lengthof(camEntries[0]) / 2); - currCamEntry = { 0 }; + currCamEntry = { 0, 0, 0, FALSE }; for (int cy = 0; cy < lengthof(camEntries[0]); cy++) { for (int cx = 0; cx < lengthof(camEntries); cx++) { const CampaignMapEntry &cme = camEntries[cy][cx]; diff --git a/Source/gamemenu.cpp b/Source/gamemenu.cpp index 535c8c76250..d1d14e4ed06 100644 --- a/Source/gamemenu.cpp +++ b/Source/gamemenu.cpp @@ -12,7 +12,7 @@ DEVILUTION_BEGIN_NAMESPACE static void gamemenu_previous(bool bActivate); static void gamemenu_new_game(bool bActivate); static void gamemenu_exit_game(bool bActivate); -static void gamemenu_load_game(bool bActivate); +//static void gamemenu_load_game(bool bActivate); static void gamemenu_save_game(bool bActivate); static void gamemenu_restart_town(bool bActivate); //void gamemenu_settings(bool bActivate); @@ -113,7 +113,7 @@ static void gamemenu_exit_game(bool bActivate) gbRunGameResult = false; } -static void gamemenu_load_game(bool bActivate) +/*static void gamemenu_load_game(bool bActivate) { WNDPROC saveProc = SetWindowProc(DisableInputWndProc); gamemenu_off(); @@ -134,7 +134,7 @@ static void gamemenu_load_game(bool bActivate) PaletteFadeIn(false); interface_msg_pump(); SetWindowProc(saveProc); -} +}*/ static void gamemenu_save_game(bool bActivate) { diff --git a/Source/path.cpp b/Source/path.cpp index 55398d7685f..b8879763f3a 100644 --- a/Source/path.cpp +++ b/Source/path.cpp @@ -17,8 +17,10 @@ static unsigned gnLastNodeIdx; static int8_t reversePathDirs[MAX_PATH_LENGTH]; /** A linked list of all visited nodes. */ static PATHNODE* pathVisitedNodes; +#ifdef DEBUG_PATH /** A stack for recursively update nodes. */ static PATHNODE* pathUpdateStack[MAXPATHNODES]; +#endif /** A linked list of the A* frontier, sorted by distance. */ static PATHNODE* pathFrontNodes; /** The target location. */ @@ -92,7 +94,7 @@ static void PathAddNode(PATHNODE* pPath) pPath->NextNode = next; current->NextNode = pPath; } - +#ifdef DEBUG_PATH /** * @brief return 2 if (sx,sy) is horizontally/vertically aligned with (dx,dy), else 3 * @@ -104,7 +106,7 @@ static inline int PathStepCost(int sx, int sy, int dx, int dy) { return (sx == dx || sy == dy) ? 2 : 3; } -#ifdef DEBUG_PATH + /** * @brief update all path costs using depth-first search starting at pPath */ diff --git a/Source/stores.cpp b/Source/stores.cpp index 9ddbac3a783..5c7ec69c885 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -501,7 +501,6 @@ static void S_ScrollSPBuy() if (premiumitems[idx]._itype != ITYPE_NONE) boughtitems--; - unsigned sidx = idx; for (l = 0; l < STORE_PAGE_ITEMS && idx < SMITH_PREMIUM_ITEMS; ) { is = &premiumitems[idx]; if (is->_itype != ITYPE_NONE) { From 36a2ba106779bc9dd666f71da4bf43c29713f1b9 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 13 Aug 2024 10:33:20 +0200 Subject: [PATCH 425/596] fix CheckCursMove when gbZoomInFlag is set --- Source/cursor.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Source/cursor.cpp b/Source/cursor.cpp index 2eaaa86f8d3..719ab55cfbd 100644 --- a/Source/cursor.cpp +++ b/Source/cursor.cpp @@ -332,11 +332,6 @@ void CheckCursMove() return; } - if (gbZoomInFlag) { - sx >>= 1; - sy >>= 1; - } - sx += gsMouseVp._vOffsetX; sy += gsMouseVp._vOffsetY; @@ -353,6 +348,11 @@ void CheckCursMove() // sy -= fy; //} + if (gbZoomInFlag) { + sx >>= 1; + sy >>= 1; + } + // Center player tile on screen mx = ViewX + gsMouseVp._vShiftX; my = ViewY + gsMouseVp._vShiftY; @@ -417,7 +417,6 @@ void CheckCursMove() deadplr[0] = pnum + 1; } } - } } if (dFlags[mx + 1][my + 1] & BFLAG_VISIBLE) { From 7c4dfe681d3518da399bfd678ca66a066939e902 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 13 Aug 2024 10:36:57 +0200 Subject: [PATCH 426/596] draw tooltip more precisely - handle movement of the current player - handle movement of the target monster/player --- Source/control.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Source/control.cpp b/Source/control.cpp index be50e3ba9b9..9427e12cbbc 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -1524,6 +1524,9 @@ static POS32 GetMousePos(int x, int y) pos.x *= TILE_WIDTH / 2; pos.y *= TILE_HEIGHT / 2; + pos.x += ScrollInfo._sxoff; + pos.y += ScrollInfo._syoff; + if (gbZoomInFlag) { pos.x <<= 1; pos.y <<= 1; @@ -1747,12 +1750,16 @@ void DrawInfoStr() MonsterStruct* mon = &monsters[pcursmonst]; strcpy(infostr, mon->_mName); // TNR_NAME or a monster's name pos = GetMousePos(mon->_mx, mon->_my); + pos.x += mon->_mxoff; + pos.y += mon->_myoff; pos.y -= ((mon->_mSelFlag & 6) ? TILE_HEIGHT * 2 : TILE_HEIGHT) + TOOLTIP_OFFSET; pos.x += DrawTooltip(infostr, pos.x, pos.y, mon->_mNameColor); DrawHealthBar(mon->_mhitpoints, mon->_mmaxhp, pos.x, pos.y + TOOLTIP_HEIGHT - HEALTHBAR_HEIGHT / 2); } else if (pcursplr != PLR_NONE) { PlayerStruct* p = &players[pcursplr]; pos = GetMousePos(p->_px, p->_py); + pos.x += p->_pxoff; + pos.y += p->_pyoff; pos.y -= TILE_HEIGHT * 2 + TOOLTIP_OFFSET; snprintf(infostr, sizeof(infostr), p->_pManaShield == 0 ? "%s(%d)" : "%s(%d)*", ClassStrTbl[p->_pClass], p->_pLevel); pos.x += DrawTooltip2(p->_pName, infostr, pos.x, pos.y, COL_GOLD); From a469572dad6fba0c151486a49dc7d0b39bfd4186 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 14 Aug 2024 07:37:02 +0200 Subject: [PATCH 427/596] use the return value of AddElementalExplosion in PlrHitPlr --- Source/player.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/player.cpp b/Source/player.cpp index 13b6e1b2b18..cdc238eb7d5 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -2123,8 +2123,7 @@ static bool PlrHitPlr(int offp, int sn, int sl, int pnum) adam = CalcPlrDam(pnum, MISR_ACID, plx(offp)._pIAMinDam, adam); } if ((fdam | ldam | mdam | adam) != 0) { - dam += fdam + ldam + mdam + adam; - AddElementalExplosion(plr._px, plr._py, fdam, ldam, mdam, adam); + dam += AddElementalExplosion(plr._px, plr._py, fdam, ldam, mdam, adam); } if (!PlrDecHp(pnum, dam, DMGTYPE_PLAYER)) { From 8928e1f1168569e0e1fe36b7b160e615a401fba6 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 14 Aug 2024 13:15:27 +0200 Subject: [PATCH 428/596] draw elemental explosion with offset --- Source/missiles.cpp | 25 ++++++++++++++++++++----- Source/missiles.h | 2 +- Source/player.cpp | 4 ++-- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 9121a600e43..cd19a8bd555 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -717,10 +717,10 @@ unsigned CalcMonsterDam(unsigned mor, BYTE mRes, unsigned mindam, unsigned maxda return dam; } -int AddElementalExplosion(int dx, int dy, int fdam, int ldam, int mdam, int adam) +int AddElementalExplosion(int fdam, int ldam, int mdam, int adam, bool isMonster, int mpnum) { int dam = fdam + ldam + mdam + adam; - int mtype; + int mtype, mx, my, mxoff, myoff, mi; if (dam == 0) { return 0; @@ -731,7 +731,22 @@ int AddElementalExplosion(int dx, int dy, int fdam, int ldam, int mdam, int adam } else { mtype = mdam >= adam ? MIS_EXMAGIC : MIS_EXACID; } - AddMissile(dx, dy, -1, 0, 0, mtype, MST_NA, 0, 0); + if (isMonster) { + mx = monsters[mpnum]._mx; + my = monsters[mpnum]._my; + mxoff = monsters[mpnum]._mxoff; + myoff = monsters[mpnum]._myoff; + } else { + mx = plx(mpnum)._px; + my = plx(mpnum)._py; + mxoff = plx(mpnum)._pxoff; + myoff = plx(mpnum)._pyoff; + } + mi = AddMissile(mx, my, -1, 0, 0, mtype, MST_NA, 0, 0); + if (mi >= 0) { + missile[mi]._mixoff = mxoff; + missile[mi]._miyoff = myoff; + } /*int gfx = random_(8, dam); if (gfx >= dam - (fdam + ldam)) { if (gfx < dam - ldam) { @@ -896,7 +911,7 @@ static bool MissMonHitByPlr(int mnum, int mi) if (adam != 0) { adam = CalcMonsterDam(mon->_mMagicRes, MISR_ACID, plr._pIAMinDam, adam, false); } - dam += AddElementalExplosion(mon->_mx, mon->_my, fdam, ldam, mdam, adam); + dam += AddElementalExplosion(fdam, ldam, mdam, adam, true, mnum); } else { dam = CalcMonsterDam(mon->_mMagicRes, mis->_miResist, mis->_miMinDam, mis->_miMaxDam, false); } @@ -1158,7 +1173,7 @@ static bool MissPlrHitByPlr(int pnum, int mi) if (adam != 0) { adam = CalcPlrDam(pnum, MISR_ACID, plx(offp)._pIAMinDam, adam); } - dam += AddElementalExplosion(plr._px, plr._py, fdam, ldam, mdam, adam); + dam += AddElementalExplosion(fdam, ldam, mdam, adam, false, pnum); } else { dam = CalcPlrDam(pnum, mis->_miResist, mis->_miMinDam, mis->_miMaxDam); dam >>= 1; diff --git a/Source/missiles.h b/Source/missiles.h index 356383f29a7..d3e91e20e15 100644 --- a/Source/missiles.h +++ b/Source/missiles.h @@ -21,7 +21,7 @@ unsigned CalcMonsterDam(unsigned mor, BYTE mRes, unsigned mindam, unsigned maxda unsigned CalcPlrDam(int pnum, BYTE mRes, unsigned mindam, unsigned maxdam); int CheckMonCol(int _mnum_); int CheckPlrCol(int _pnum_); -int AddElementalExplosion(int dx, int dy, int fdam, int ldam, int mdam, int hdam); +int AddElementalExplosion(int fdam, int ldam, int mdam, int hdam, bool isMonster, int mpnum); int AddMissile(int sx, int sy, int dx, int dy, int midir, int mitype, int micaster, int misource, int spllvl); void LoadMissileGFX(BYTE midx); void InitGameMissileGFX(); diff --git a/Source/player.cpp b/Source/player.cpp index cdc238eb7d5..0406bd39f79 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -2022,7 +2022,7 @@ static bool PlrHitMonst(int pnum, int sn, int sl, int mnum) if (adam != 0) adam = CalcMonsterDam(mon->_mMagicRes, MISR_ACID, plr._pIAMinDam, adam, false); - dam += AddElementalExplosion(mon->_mx, mon->_my, fdam, ldam, mdam, adam); + dam += AddElementalExplosion(fdam, ldam, mdam, adam, true, mnum); //if (pnum == mypnum) { mon->_mhitpoints -= dam; @@ -2123,7 +2123,7 @@ static bool PlrHitPlr(int offp, int sn, int sl, int pnum) adam = CalcPlrDam(pnum, MISR_ACID, plx(offp)._pIAMinDam, adam); } if ((fdam | ldam | mdam | adam) != 0) { - dam += AddElementalExplosion(plr._px, plr._py, fdam, ldam, mdam, adam); + dam += AddElementalExplosion(fdam, ldam, mdam, adam, false, pnum); } if (!PlrDecHp(pnum, dam, DMGTYPE_PLAYER)) { From 9dbb895f86b313e0226b22225352d8f6fdc34cd6 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 15 Aug 2024 07:35:54 +0200 Subject: [PATCH 429/596] bugfix for hellfire (lockout in nest) - prevent lockout of subtiles in nest --- Packaging/resources/devilx.mpq | Bin 1250182 -> 1250184 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Packaging/resources/devilx.mpq b/Packaging/resources/devilx.mpq index bc01c524266346535369540b0267604dfee3a2fc..0a4eb54da18b3f2d1ca8a82f7c0427d82314d732 100644 GIT binary patch delta 3095 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 Jx6CaPyyctp=biun From 4e35ac2bd4f10c57397f5869d3541f657e198a95 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 15 Aug 2024 07:42:56 +0200 Subject: [PATCH 430/596] bugfix for hellfire (horkspawn vs. block) - prevent triggering block-animation when the missile of "Hork Demon" hits the player --- Source/missiles.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index cd19a8bd555..7bb7e06b3d7 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -3834,16 +3834,18 @@ void MI_HorkSpawn(int mi) const int8_t* cr; mis = &missile[mi]; - CheckMissileCol(mi, mis->_mix, mis->_miy, MICM_BLOCK_ANY); mis->_miRange--; if (mis->_miRange >= 0) { mis->_mitxoff += mis->_mixvel; mis->_mityoff += mis->_miyvel; GetMissilePos(mi); - - PutMissile(mi); - return; + // if ((mis->_mix == mis->_misx && mis->_miy == mis->_misy) || PosOkMissile(mis->_mix, mis->_miy)) { + // if (PosOkMonster(mis->_miSource, mis->_mix, mis->_miy)) { + PutMissile(mi); + return; + // } } + // assert(abs(mis->_mix - mis->_misx) <= 1 && abs(mis->_miy - mis->_misy) <= 1); mis->_miDelFlag = TRUE; static_assert(DBORDERX >= 1 && DBORDERY >= 1, "MI_HorkSpawn expects a large enough border."); for (i = 0; i <= 1; i++) { From 8ce6818027db4169b320c42e6a6f325e4ccad6c9 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 15 Aug 2024 07:44:58 +0200 Subject: [PATCH 431/596] switch back to the original delete-tag-and-release --- .github/workflows/nightly.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 12cdec98fc8..9041a36a30b 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1552,9 +1552,9 @@ jobs: # run: find $RUNNER_WORKSPACE # shell: bash - # uses: dev-drprasad/delete-tag-and-release@v0.2.0 + # uses: pionere/delete-tag-and-release@v1 - name: Delete tag and release - uses: pionere/delete-tag-and-release@v1 + uses: dev-drprasad/delete-tag-and-release@v1.1 with: delete_release: true tag_name: devilx-nightly From da568a08244a66f70c0c293f778428fd0a4dc055 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 16 Aug 2024 08:07:16 +0200 Subject: [PATCH 432/596] get rid of an obsolete assertion --- Source/monster.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index d85081a80f4..31a4f545e67 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1568,8 +1568,6 @@ static void MonStartDelay(int mnum, int len) { MonsterStruct* mon; - // assert(len > 0); - mon = &monsters[mnum]; mon->_mVar2 = len; // DELAY_TICK : length of the delay mon->_mmode = MM_DELAY; From ed3dd76d59ae51ada66205d51b058568397271ab Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 16 Aug 2024 08:10:52 +0200 Subject: [PATCH 433/596] add affixes to campaign maps --- Source/control.cpp | 35 +++++++++++++---------- Source/control.h | 2 +- Source/debug.cpp | 33 ++++++++++++++++++++++ Source/itemdat.cpp | 11 +++++++- Source/items.cpp | 69 ++++++++++++++++++++++++++++++++++++---------- enums.h | 7 +++++ 6 files changed, 126 insertions(+), 31 deletions(-) diff --git a/Source/control.cpp b/Source/control.cpp index 9427e12cbbc..e011bd1181b 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -46,8 +46,8 @@ unsigned guTeamMute; /** Campaign-map images CEL */ static CelImageBuf* pMapIconCels; -/** Specifies whether the campaign-map is displayed. */ -bool gbCampaignMapFlag; +/** Specifies the campaign-map status. */ +BYTE gbCampaignMapFlag; /** The 'highlighted' map on the campaign-map. */ static CampaignMapEntry currCamEntry; /** The entries of the current campaign-map. */ @@ -965,7 +965,7 @@ void InitControlPan() #endif // ASSET_MPL == 1 assert(pMapIconCels == NULL); pMapIconCels = CelLoadImage("Data\\MapIcon.CEL", CAMICON_WIDTH); - gbCampaignMapFlag = false; + gbCampaignMapFlag = CMAP_NONE; /*for (i = 0; i < NUM_RSPLTYPES; i++) { for (j = 0; j < NUM_COLORS; j++) SkillTrns[j] = j; @@ -1788,7 +1788,7 @@ void DrawInfoStr() break; } DrawTooltip2(spelldata[currSkill].sNameText, src, MousePos.x, MousePos.y - (SPLICON_HEIGHT / 4 + TOOLTIP_OFFSET), COL_WHITE); - } else if (gbCampaignMapFlag) { + } else if (gbCampaignMapFlag != CMAP_NONE) { if (currCamEntry.ceIndex == 0) return; const char* type; @@ -1823,7 +1823,7 @@ void DrawInfoStr() } else if (gnDifficulty == DIFF_HELL) { lvl += HELL_LEVEL_BONUS; } - snprintf(infostr, sizeof(infostr), "(lvl: %d)", lvl); + snprintf(infostr, sizeof(infostr), gbCampaignMapFlag == CMAP_IDENTIFIED ? "(lvl: %d)" : "(lvl: ??)", lvl); DrawTooltip2(type, infostr, MousePos.x, MousePos.y - (CAMICON_HEIGHT / 4 + TOOLTIP_OFFSET), COL_WHITE); } else if (pcursinvitem != INVITEM_NONE) { DrawInvItemDetails(); @@ -2448,18 +2448,18 @@ static void control_addmappos(int x, int y, BYTE type, BYTE idx, WORD available, *border += db; } -static void control_setmaplevel(int x, int y, BYTE lvl) +static void control_setmaplevel(int x, int y, BYTE lvl, BYTE dlvl) { if (camEntries[x][y].ceIndex != 0 && (camEntries[x][y].ceLevel == 0 || camEntries[x][y].ceLevel > lvl)) { camEntries[x][y].ceLevel = lvl; - lvl += 4; + lvl += dlvl; if (lvl > MAXCAMPAIGNLVL) lvl = MAXCAMPAIGNLVL; - control_setmaplevel(x + 1, y + 0, lvl); - control_setmaplevel(x - 1, y + 0, lvl); - control_setmaplevel(x + 0, y + 1, lvl); - control_setmaplevel(x + 0, y - 1, lvl); + control_setmaplevel(x + 1, y + 0, lvl, dlvl); + control_setmaplevel(x - 1, y + 0, lvl, dlvl); + control_setmaplevel(x + 0, y + 1, lvl, dlvl); + control_setmaplevel(x + 0, y - 1, lvl, dlvl); } } @@ -2480,6 +2480,7 @@ void InitCampaignMap(int cii) static_assert(DTYPE_TOWN == 0, "InitCampaignMap must be adjusted."); control_addmappos(lengthof(camEntries) / 2, lengthof(camEntries[0]) / 2, random_(200, NUM_DTYPES - 1) + 1, ++idx, available, &border); + numMaps += is->_iPLLight - 6; for (int i = 0; i < numMaps - 1; i++) { int step = random_low(201, border) + 1; for (int x = 0; x < lengthof(camEntries); x++) { @@ -2497,10 +2498,14 @@ void InitCampaignMap(int cii) } } - BYTE lvl = (is->_iCreateInfo & CF_LEVEL) - HELL_LEVEL_BONUS; - control_setmaplevel(lengthof(camEntries) / 2, lengthof(camEntries[0]) / 2, lvl); + BYTE lvl = (is->_iAC == 0 ? (is->_iCreateInfo & CF_LEVEL) : is->_iAC) - HELL_LEVEL_BONUS; + lvl += is->_iPLSkillLevels; + BYTE dlvl = 2; + dlvl += is->_iPLAC; - gbCampaignMapFlag = true; + control_setmaplevel(lengthof(camEntries) / 2, lengthof(camEntries[0]) / 2, lvl, dlvl); + + gbCampaignMapFlag = is->_iMagical == ITEM_QUALITY_NORMAL || is->_iIdentified ? CMAP_IDENTIFIED : CMAP_UNIDENTIFIED; } void TryCampaignMapClick(bool bShift, bool altAction) @@ -2523,7 +2528,7 @@ void TryCampaignMapClick(bool bShift, bool altAction) } } - gbCampaignMapFlag = false; + gbCampaignMapFlag = CMAP_NONE; } void DrawCampaignMap() diff --git a/Source/control.h b/Source/control.h index 13bb1b41361..10773f97caa 100644 --- a/Source/control.h +++ b/Source/control.h @@ -39,7 +39,7 @@ extern unsigned guTeamMute; extern bool gabPanbtn[NUM_PANBTNS]; extern int numpanbtns; extern bool gbSkillListFlag; -extern bool gbCampaignMapFlag; +extern BYTE gbCampaignMapFlag; extern int camItemIndex; extern CampaignMapEntry selCamEntry; diff --git a/Source/debug.cpp b/Source/debug.cpp index dbcbf128b94..e19221e7325 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -484,6 +484,12 @@ void ValidateData() app_fatal("IDI_BOOK1 is not a book, its miscId is %d, iminlvl %d.", AllItemsList[IDI_BOOK1].iMiscId, AllItemsList[IDI_BOOK1].iMinMLvl); if (AllItemsList[IDI_BOOK4].iMiscId != IMISC_BOOK) app_fatal("IDI_BOOK4 is not a book, its miscId is %d, iminlvl %d.", AllItemsList[IDI_BOOK4].iMiscId, AllItemsList[IDI_BOOK4].iMinMLvl); + if (AllItemsList[IDI_CAMPAIGNMAP].iMiscId != IMISC_MAP) + app_fatal("IDI_CAMPAIGNMAP is not a map, its miscId is %d, iminlvl %d.", AllItemsList[IDI_CAMPAIGNMAP].iMiscId, AllItemsList[IDI_CAMPAIGNMAP].iMinMLvl); + if (AllItemsList[IDI_CAMPAIGNMAP].iDurability != 1) // required because of affixes and map level + app_fatal("IDI_CAMPAIGNMAP stack-size is not one, its miscId is %d, iminlvl %d.", AllItemsList[IDI_CAMPAIGNMAP].iMiscId, AllItemsList[IDI_CAMPAIGNMAP].iMinMLvl); + if (AllItemsList[IDI_CAMPAIGNMAP].iValue != (1 << (MAXCAMPAIGNSIZE - 6)) - 1) // required by InitCampaignMap + app_fatal("IDI_CAMPAIGNMAP base value is invalid (%d vs. %d).", AllItemsList[IDI_CAMPAIGNMAP].iValue, (1 << (MAXCAMPAIGNSIZE - 2)) - 1); static_assert(IDI_BOOK4 - IDI_BOOK1 == 3, "Invalid IDI_BOOK indices."); if (AllItemsList[IDI_CLUB].iCurs != ICURS_CLUB) app_fatal("IDI_CLUB is not a club, its cursor is %d, iminlvl %d.", AllItemsList[IDI_CLUB].iCurs, AllItemsList[IDI_CLUB].iMinMLvl); @@ -668,6 +674,33 @@ void ValidateData() } } } + if (pres->PLIType == PLT_MAP) { + if (pres->PLPower == IPL_ACP) { + if (pres->PLParam1 < -2) { // required by InitCampaignMap + app_fatal("(Map-)PLParam too low for %d. prefix (power:%d, pparam1:%d)", i, pres->PLPower, pres->PLParam1); + } + if (pres->PLParam2 > UCHAR_MAX - 2) { // required by InitCampaignMap + app_fatal("(Map-)PLParam too high for %d. prefix (power:%d, pparam2:%d)", i, pres->PLPower, pres->PLParam2); + } + } + if (pres->PLPower == IPL_LIGHT) { + if (pres->PLParam1 < -(MAXCAMPAIGNSIZE - (1 + 6))) { // required by InitCampaignMap and GetItemPower + app_fatal("(Map-)PLParam too low for %d. prefix (power:%d, pparam1:%d)", i, pres->PLPower, pres->PLParam1); + } + if (pres->PLParam2 > 6) { // required by InitCampaignMap and GetItemPower + app_fatal("(Map-)PLParam too high for %d. prefix (power:%d, pparam2:%d)", i, pres->PLPower, pres->PLParam2); + } + } + if (pres->PLMultVal != 1) { + app_fatal("(Map-)PLMultVal invalid for %d. prefix (power:%d, pparam1:%d)", i, pres->PLPower, pres->PLParam1); + } + if (pres->PLMinVal != 0) { + app_fatal("(Map-)PLMinVal invalid for %d. prefix (power:%d, pparam1:%d)", i, pres->PLPower, pres->PLParam1); + } + if (pres->PLMaxVal != 0) { + app_fatal("(Map-)PLMaxVal invalid for %d. prefix (power:%d, pparam1:%d)", i, pres->PLPower, pres->PLParam1); + } + } } if (rnddrops > ITEM_RNDAFFIX_MAX || rnddrops > 0x7FFF) app_fatal("Too many prefix options: %d. Maximum is %d", rnddrops, ITEM_RNDAFFIX_MAX); diff --git a/Source/itemdat.cpp b/Source/itemdat.cpp index 1090a845169..1d972599ab7 100644 --- a/Source/itemdat.cpp +++ b/Source/itemdat.cpp @@ -213,7 +213,7 @@ const ItemData AllItemsList[NUM_IDI] = { /* */ { "Amulet", 1, 8, UITYPE_AMULET, ICURS_AMULET, ITYPE_AMULET, IMISC_NONE, SPL_NULL, ICLASS_MISC, ILOC_AMULET, IDAM_NONE, 0, 0, 0, 0, 0, 0, FALSE, 0, 0, 0, 1200, ALIGN }, /* */ { "Amulet", 1, 16, UITYPE_AMULET, ICURS_AMULET, ITYPE_AMULET, IMISC_NONE, SPL_NULL, ICLASS_MISC, ILOC_AMULET, IDAM_NONE, 0, 0, 0, 0, 0, 0, FALSE, 0, 0, 0, 1200, ALIGN }, /* */ { "Amulet", 1, 33, UITYPE_AMULET, ICURS_AMULET, ITYPE_AMULET, IMISC_NONE, SPL_NULL, ICLASS_MISC, ILOC_AMULET, IDAM_NONE, 0, 0, 0, 0, 0, 0, FALSE, 0, 0, 0, 1200, ALIGN }, -/*IDI_CAMPAIGNMAP*/ { "Campaign Map", 1, 64, UITYPE_NONE, ICURS_CAMPAIGN_MAP, ITYPE_MISC, IMISC_MAP, SPL_NULL, ICLASS_MISC, ILOC_UNEQUIPABLE, IDAM_NONE, 0, 0, 0, 0, 0, 0, TRUE, 0, 0, 1, 0xFFFF, ALIGN }, +/*IDI_CAMPAIGNMAP*/ { "Campaign Map", 1, 64, UITYPE_NONE, ICURS_CAMPAIGN_MAP, ITYPE_MISC, IMISC_MAP, SPL_NULL, ICLASS_MISC, ILOC_UNEQUIPABLE, IDAM_NONE, 0, 0, 0, 0, 0, 0, TRUE, 0, 0, 1, 0x3FF, ALIGN }, #ifdef HELLFIRE /* */ { "Rune of ", 1, 1, UITYPE_NONE, ICURS_RUNE_OF_FIRE, ITYPE_MISC, IMISC_RUNE, SPL_NULL, ICLASS_MISC, ILOC_BELT, IDAM_NONE, 0, 0, 0, 0, 0, 0, TRUE, 0, 0, SS_RUNE, 0, ALIGN }, /* */ { "Rune of ", 1, 3, UITYPE_NONE, ICURS_RUNE_OF_FIRE, ITYPE_MISC, IMISC_RUNE, SPL_NULL, ICLASS_MISC, ILOC_BELT, IDAM_NONE, 0, 0, 0, 0, 0, 0, TRUE, 0, 0, SS_RUNE, 0, ALIGN }, @@ -338,6 +338,15 @@ const AffixData PL_Prefix[] = { /*corrosive*/ { IPL_ACIDDAM, 18, 28, 35, ILVLMAX, 35, ILVLMAX, 35, ILVLMAX, PLT_MELEE | PLT_STAFF , FALSE, TRUE, 20000, 20000, 2 }, /*fairy*/ { IPL_CRYSTALLINE, 30, 60, 32, ILVLMAX, PLR1LVL, ILVLMAX, 32, ILVLMAX, PLT_MELEE | PLT_STAFF | PLT_BOW , FALSE, TRUE, 1000, 3000, 3 }, /*crystalline*/ { IPL_CRYSTALLINE, 61, 110, 60, ILVLMAX, 0, 0, 60, ILVLMAX, PLT_MELEE | PLT_BOW , FALSE, TRUE, 10000, 30000, 8 }, + +/*baselvl */ { IPL_SKILLLEVELS, -4, -1, 0, ILVLMAX, 0, ILVLMAX, 0, ILVLMAX, PLT_MAP , FALSE, TRUE, 0, 0, 1 }, +/*crystalline*/ { IPL_SKILLLEVELS, 1, 4, 0, ILVLMAX, 0, ILVLMAX, 0, ILVLMAX, PLT_MAP , FALSE, TRUE, 0, 0, 1 }, +/*deltalvl */ { IPL_ACP, -2, -1, 0, ILVLMAX, 0, ILVLMAX, 0, ILVLMAX, PLT_MAP , FALSE, TRUE, 0, 0, 1 }, +/*crystalline*/ { IPL_ACP, 1, 2, 0, ILVLMAX, 0, ILVLMAX, 0, ILVLMAX, PLT_MAP , FALSE, TRUE, 0, 0, 1 }, +/*setlvl */ { IPL_SETAC, 60, 75, 0, 80 - 64, 0, ILVLMAX, 0, ILVLMAX, PLT_MAP , FALSE, TRUE, 0, 0, 1 }, +/*crystalline*/ { IPL_SETAC, 76, 90, 70 - 64, ILVLMAX, 0, ILVLMAX, 0, ILVLMAX, PLT_MAP , FALSE, TRUE, 0, 0, 1 }, +/*num area */ { IPL_LIGHT, -2, -1, 0, ILVLMAX, 0, ILVLMAX, 0, ILVLMAX, PLT_MAP , FALSE, TRUE, 0, 0, 1 }, +/*crystalline*/ { IPL_LIGHT, 1, 6, 0, ILVLMAX, 0, ILVLMAX, 0, ILVLMAX, PLT_MAP , TRUE, TRUE, 0, 0, 1 }, { IPL_INVALID, 0, 0, 0, 0, 0, 0, 0, 0, 0 , FALSE, FALSE, 0, 0, 0 }, // clang-format on }; diff --git a/Source/items.cpp b/Source/items.cpp index 190f3492ed8..009ae6f8f85 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -1705,15 +1705,21 @@ static void GetItemPower(int ii, unsigned lvl, BYTE range, int flgs, bool onlygo } // prefix or suffix added -> recalculate the value of the item if (items[ii]._iMagical == ITEM_QUALITY_MAGIC) { - v = items[ii]._iVMult; - if (v >= 0) { - v *= items[ii]._ivalue; + if (items[ii]._iMiscId != IMISC_MAP) { + v = items[ii]._iVMult; + if (v >= 0) { + v *= items[ii]._ivalue; + } + else { + v = items[ii]._ivalue / -v; + } + v += items[ii]._iVAdd; + if (v <= 0) { + v = 1; + } } else { - v = items[ii]._ivalue / -v; - } - v += items[ii]._iVAdd; - if (v <= 0) { - v = 1; + v = ((1 << MAXCAMPAIGNSIZE) - 1) >> (6 - items[ii]._iPLLight); + items[ii]._ivalue = v; } items[ii]._iIvalue = v; } @@ -1725,7 +1731,10 @@ static void GetItemBonus(int ii, unsigned lvl, BYTE range, bool onlygood, bool a switch (items[ii]._itype) { case ITYPE_MISC: - return; + if (items[ii]._iMiscId != IMISC_MAP) + return; + flgs = PLT_MAP; + break; case ITYPE_SWORD: case ITYPE_AXE: case ITYPE_MACE: @@ -2699,8 +2708,13 @@ void DoOil(int pnum, int8_t from, BYTE cii) return; pi = PlrItem(pnum, cii); - if (pi->_itype == ITYPE_NONE || pi->_itype == ITYPE_MISC || pi->_itype == ITYPE_GOLD) + if (pi->_itype == ITYPE_NONE || pi->_itype == ITYPE_GOLD) { + return; + } + if (pi->_itype == ITYPE_MISC + && (pi->_iMiscId != IMISC_MAP || !(pi->_ivalue & 1) || (oilType != IMISC_OILCHANCE && oilType != IMISC_OILCLEAN))) { return; + } if (oilType == IMISC_OILCLEAN) { if (pi->_iMagical != ITEM_QUALITY_MAGIC) @@ -2793,7 +2807,7 @@ void DoOil(int pnum, int8_t from, BYTE cii) CalcPlrInv(pnum, true); } -void PrintItemPower(BYTE plidx, const ItemStruct* is) +static void PrintEquipmentPower(BYTE plidx, const ItemStruct* is) { switch (plidx) { case IPL_TOHIT: @@ -3025,6 +3039,34 @@ void PrintItemPower(BYTE plidx, const ItemStruct* is) } } +static void PrintMapPower(BYTE plidx, const ItemStruct* is) +{ + switch (plidx) { + case IPL_SKILLLEVELS: + snprintf(tempstr, sizeof(tempstr), "%+d to map levels", is->_iPLSkillLevels); + break; + case IPL_ACP: + snprintf(tempstr, sizeof(tempstr), "%+d to level gain", is->_iPLAC); + break; + case IPL_SETAC: + snprintf(tempstr, sizeof(tempstr), "starting level %d", is->_iAC); + break; + case IPL_LIGHT: + snprintf(tempstr, sizeof(tempstr), (is->_iPLLight & 1) ? "%+d area" : "%+d areas", is->_iPLLight); + break; + default: + ASSUME_UNREACHABLE + } +} + +void PrintItemPower(BYTE plidx, const ItemStruct* is) +{ + if (is->_itype != ITYPE_MISC || is->_iMiscId != IMISC_MAP) + PrintEquipmentPower(plidx, is); + else + PrintMapPower(plidx, is); +} + static void PrintItemString(int x, int& y) { PrintJustifiedString(x, y, x + (STPANEL_WIDTH - 2 * TPANEL_BORDER), tempstr, COL_WHITE, FONT_KERN_SMALL); @@ -3199,8 +3241,7 @@ static void PrintItemMiscInfo(const ItemStruct* is, int x, int& y) PrintItemString(x, y, desc); break; case IMISC_MAP: - snprintf(tempstr, sizeof(tempstr), "(lvl: %d)", is->_iCreateInfo & CF_LEVEL); - PrintItemString(x, y); + y += 24; desc = "right-click to use"; PrintItemString(x, y, desc); desc = "(only in town)"; @@ -3276,7 +3317,7 @@ void DrawInvItemDetails() PrintItemString(x, y, ItemName(is), ItemColor(is)); // add item-level info or stack-size - if (is->_itype != ITYPE_MISC && is->_itype != ITYPE_GOLD) { + if ((is->_itype != ITYPE_MISC || is->_iMiscId == IMISC_MAP) && is->_itype != ITYPE_GOLD) { snprintf(tempstr, sizeof(tempstr), "(lvl: %d)", is->_iCreateInfo & CF_LEVEL); y -= 6; PrintItemString(x, y); diff --git a/enums.h b/enums.h index 7b7a78be223..a27f45f3f73 100644 --- a/enums.h +++ b/enums.h @@ -435,6 +435,7 @@ typedef enum affix_item_type { PLT_LARMOR = 1 << 8, PLT_MARMOR = 1 << 9, PLT_HARMOR = 1 << 10, + PLT_MAP = 1 << 11, } affix_item_type; typedef enum item_base_bonus { @@ -4328,6 +4329,12 @@ typedef enum quest_nakrul_book { QNB_BOOK_C, } quest_nakrul_book; +typedef enum map_status { + CMAP_NONE, + CMAP_IDENTIFIED, + CMAP_UNIDENTIFIED +} map_status; + typedef enum talk_id { STORE_NONE, STORE_SMITH, From 206a7c6bb02d74381448a208468455ba694c5d56 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 17 Aug 2024 08:35:52 +0200 Subject: [PATCH 434/596] adjust some metainfo - sync the error messages in MissToPlr with the other Plr* functions - fix the typo in MonDestWalk --- Source/monster.cpp | 2 +- Source/player.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 31a4f545e67..c084a0d7e89 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -2927,7 +2927,7 @@ static bool MonDestWalk(int mnum) md = FindPath(Check, mnum, mon->_mx, mon->_my, mon->_mlastx, mon->_mlasty, path); if (md > 0) { // found path to the enemy -> go md = path[0]; - } else if (md != 0) { // cound not find path to the enemy -> just go in its generic direction + } else if (md != 0) { // could not find path to the enemy -> just go in its generic direction md = currEnemyInfo._meLastDir; } else { // enemy disappeared -> walk around randomly md = random_(145, NUM_DIRS); diff --git a/Source/player.cpp b/Source/player.cpp index 0406bd39f79..7f25d34d607 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -2895,12 +2895,12 @@ void MissToPlr(int mi, bool hit) bool ret; if ((unsigned)mi >= MAXMISSILES) { - dev_fatal("MissToPlr: Invalid missile %d", mi); + dev_fatal("MissToPlr: illegal missile %d", mi); } mis = &missile[mi]; pnum = mis->_miSource; if ((unsigned)pnum >= MAX_PLRS) { - dev_fatal("MissToPlr: Invalid player %d", pnum); + dev_fatal("MissToPlr: illegal player %d", pnum); } //dPlayer[plr._px][plr._py] = pnum + 1; /*assert(plr._pfutx == plr._px); From 6efac52d1dca86f24ad03ea30c8e15d046e2eb72 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 17 Aug 2024 08:39:40 +0200 Subject: [PATCH 435/596] add DEBUG_DATA switch to debug.cpp and test the static data only if it is defined --- Source/debug.cpp | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/Source/debug.cpp b/Source/debug.cpp index e19221e7325..56f5b35c5c7 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -12,6 +12,7 @@ DEVILUTION_BEGIN_NAMESPACE #if DEBUG_MODE +#define DEBUG_DATA void CheckDungeonClear() { int i, j; @@ -173,7 +174,7 @@ void ValidateData() #endif // DEBUG // text //PrintText(gszHelpText, '|', LTPANEL_WIDTH - 2 * 7); - +#ifdef DEBUG_DATA for (i = 0; i < lengthof(gbStdFontFrame); i++) { if (gbStdFontFrame[i] >= lengthof(smallFontWidth)) app_fatal("Width of the small font %d ('%c') is undefined (frame number: %d).", i, i, gbStdFontFrame[i]); @@ -246,6 +247,7 @@ void ValidateData() if (AllLevels[i].dMonDensity > UINT_MAX / (DSIZEX * DSIZEY)) app_fatal("Too high dMonDensity on level %s (%d)", AllLevels[i].dLevelName, i); // required by InitMonsters } +#endif // DEBUG_DATA { BYTE lvlMask = 1 << AllLevels[questlist[Q_BLOOD]._qdlvl].dType; assert(objectdata[OBJ_TORCHL1].oLvlTypes & lvlMask); // required by SyncPedestal @@ -255,6 +257,7 @@ void ValidateData() assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_KNOCKBACK)); // required by MonHitByMon assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_CAN_BLEED)); // required by MonHitByMon and MonHitByPlr assert(monsterdata[MT_GOLEM].mSelFlag == 0); // required by CheckCursMove +#ifdef DEBUG_DATA for (i = 0; i < NUM_MTYPES; i++) { const MonsterData& md = monsterdata[i]; if ((md.mAI.aiType == AI_GOLUM || md.mAI.aiType == AI_SKELKING) && !(md.mFlags & MFLAG_CAN_OPEN_DOOR)) @@ -285,7 +288,6 @@ void ValidateData() app_fatal("Invalid mLevel %d for %s (%d). Too high to set the level of item-drop.", md.mLevel, md.mName, i); if (md.moFileNum == MOFILE_DIABLO && !(md.mFlags & MFLAG_NOCORPSE)) app_fatal("MOFILE_DIABLO does not have corpse animation but MFLAG_NOCORPSE is not set for %s (%d).", md.mName, i); -#if DEBUG_MODE if (md.mHit > INT_MAX /*- HELL_TO_HIT_BONUS */- HELL_LEVEL_BONUS * 5 / 2) // required by InitMonsterStats app_fatal("Too high mHit %d for %s (%d).", md.mHit, md.mName, i); if (md.mHit2 > INT_MAX /*- HELL_TO_HIT_BONUS */- HELL_LEVEL_BONUS * 5 / 2) // required by InitMonsterStats @@ -325,7 +327,6 @@ void ValidateData() app_fatal("Bad mMagicRes2 %d (%d) for %s (%d): worse than mMagicRes %d.", md.mMagicRes2, j, md.mName, i, md.mMagicRes); } } -#endif } for (i = 0; i < NUM_MOFILE; i++) { const MonFileData& md = monfiledata[i]; @@ -342,7 +343,7 @@ void ValidateData() if (md.moAnimFrameLen[MA_SPECIAL] * md.moAnimFrames[MA_SPECIAL] >= SQUELCH_LOW) app_fatal("Too long(%d) special animation for %s (%d) to finish before relax.", md.moAnimFrameLen[MA_SPECIAL] * md.moAnimFrames[MA_SPECIAL], md.moGfxFile, i); } - +#endif // umt checks for GetLevelMTypes #ifdef HELLFIRE assert(uniqMonData[UMT_HORKDMN].mtype == MT_HORKDMN); @@ -373,7 +374,7 @@ void ValidateData() assert((uniqMonData[UMT_NAKRUL].mMagicRes & MORS_ACID_IMMUNE) >= (targetRes & MORS_ACID_IMMUNE)); } #endif - +#ifdef DEBUG_DATA for (i = 0; uniqMonData[i].mtype != MT_INVALID; i++) { const UniqMonData& um = uniqMonData[i]; if (um.mtype >= NUM_MTYPES) @@ -423,7 +424,6 @@ void ValidateData() app_fatal("Unique monster %s (%d) is a leader without group.", um.mName, i); if ((um.mUnqFlags & UMF_LIGHT) != 0 && i != UMT_LACHDAN) app_fatal("Unique monster %s (%d) has light, but its movement is not supported.", um.mName, i); // required by DeltaLoadLevel, LevelDeltaLoad, LoadLevel, SaveLevel, SetMapMonsters, MonChangeMap, MonStartWalk2, MonPlace, MonDoWalk, MonDoFadein, MonDoFadeout, MI_Rhino -#if DEBUG_MODE if (um.mUnqHit + monsterdata[um.mtype].mHit > INT_MAX /*- HELL_TO_HIT_BONUS */- HELL_LEVEL_BONUS * 5 / 2) // required by InitUniqueMonster app_fatal("Too high mUnqHit %d for %s (%d).", um.mUnqHit, um.mName, i); if (um.mUnqHit2 + monsterdata[um.mtype].mHit2 > INT_MAX /*- HELL_TO_HIT_BONUS */- HELL_LEVEL_BONUS * 5 / 2) // required by InitUniqueMonster @@ -464,9 +464,8 @@ void ValidateData() } if (um.mmaxhp < monsterdata[um.mtype].mMaxHP) DoLog("Warn: Low mmaxhp %d for %s (%d): lower than mMaxHP %d.", um.mmaxhp, um.mName, i, monsterdata[um.mtype].mMaxHP); -#endif } - +#endif // items if (AllItemsList[IDI_HEAL].iMiscId != IMISC_HEAL) app_fatal("IDI_HEAL is not a heal potion, its miscId is %d, iminlvl %d.", AllItemsList[IDI_HEAL].iMiscId, AllItemsList[IDI_HEAL].iMinMLvl); @@ -495,6 +494,7 @@ void ValidateData() app_fatal("IDI_CLUB is not a club, its cursor is %d, iminlvl %d.", AllItemsList[IDI_CLUB].iCurs, AllItemsList[IDI_CLUB].iMinMLvl); if (AllItemsList[IDI_DROPSHSTAFF].iUniqType != UITYPE_SHORTSTAFF) app_fatal("IDI_DROPSHSTAFF is not a short staff, its utype is %d, iminlvl %d.", AllItemsList[UITYPE_SHORTSTAFF].iUniqType, AllItemsList[UITYPE_SHORTSTAFF].iMinMLvl); +#ifdef DEBUG_DATA int minAmu, minLightArmor, minMediumArmor, minHeavyArmor; //, maxStaff = 0; minAmu = minLightArmor = minMediumArmor = minHeavyArmor = MAXCHARLEVEL; int rnddrops = 0; @@ -772,7 +772,6 @@ void ValidateData() if (rnddrops > ITEM_RNDAFFIX_MAX || rnddrops > 0x7FFF) app_fatal("Too many suffix options: %d. Maximum is %d", rnddrops, ITEM_RNDAFFIX_MAX); -#if 0 for (i = 1; i < MAXCHARLEVEL; i++) { int a = 0, b = 0, c = 0, w = 0; for (const AffixData* pres = PL_Prefix; pres->PLPower != IPL_INVALID; pres++) { @@ -804,7 +803,7 @@ void ValidateData() } LogErrorF("Affix for lvl%2d: shop(%d:%d) loot(%d:%d/%d:%d) boy(%d:%d)", i, a, as, b, bs, w, ws, c, cs); } -#endif + // unique items for (i = 0; i < NUM_UITEM; i++) { const UniqItemData& ui = UniqueItemList[i]; @@ -1067,7 +1066,9 @@ void ValidateData() if (n == NUM_IDI) app_fatal("Missing base type for '%s' %d.", ui.UIName, i); } +#endif // DEBUG_DATA assert(itemfiledata[ItemCAnimTbl[ICURS_MAGIC_ROCK]].iAnimLen == 10); // required by ProcessItems +#ifdef DEBUG_DATA // objects for (i = 0; i < NUM_OFILE_TYPES; i++) { const ObjFileData& od = objfiledata[i]; @@ -1094,6 +1095,7 @@ void ValidateData() app_fatal("Light radius is too high for %d. object.", i); } } +#endif // DEBUG_DATA assert(objectdata[OBJ_L1RDOOR].oSelFlag == objectdata[OBJ_L1LDOOR].oSelFlag); // required by OpenDoor, CloseDoor assert(objectdata[OBJ_L2LDOOR].oSelFlag == objectdata[OBJ_L1LDOOR].oSelFlag); // required by OpenDoor, CloseDoor assert(objectdata[OBJ_L2RDOOR].oSelFlag == objectdata[OBJ_L1LDOOR].oSelFlag); // required by OpenDoor, CloseDoor @@ -1132,6 +1134,7 @@ void ValidateData() #define SPEC_TARGETING_CURSOR(x) ((x) == CURSOR_NONE || (x) == CURSOR_TELEKINESIS) assert(SPEC_TARGETING_CURSOR(spelldata[SPL_TELEKINESIS].scCurs)); // required by TryIconCurs assert(SPEC_TARGETING_CURSOR(spelldata[SPL_TELEKINESIS].spCurs)); // required by TryIconCurs +#ifdef DEBUG_DATA bool hasBookSpell = false, hasStaffSpell = false, hasScrollSpell = false, hasRuneSpell = false; for (i = 0; i < NUM_SPELLS; i++) { const SpellData& sd = spelldata[i]; @@ -1255,6 +1258,7 @@ void ValidateData() if (mfd.mfAnimXOffset != (mfd.mfAnimWidth - TILE_WIDTH) / 2) app_fatal("Missile %d is not drawn to the center. Width: %d, Offset: %d", i, mfd.mfAnimWidth, mfd.mfAnimXOffset); } +#endif // DEBUG_DATA assert(misfiledata[MFILE_LGHNING].mfAnimLen[0] == misfiledata[MFILE_THINLGHT].mfAnimLen[0]); // required by AddLightning assert(misfiledata[MFILE_FIREWAL].mfAnimFrameLen[0] == 1); // required by MI_Firewall assert(misfiledata[MFILE_FIREWAL].mfAnimLen[0] < 14 /* lengthof(FireWallLight) */); // required by MI_Firewall @@ -1281,7 +1285,7 @@ void ValidateData() assert(monfiledata[MOFILE_SNAKE].moAnimFrames[MA_ATTACK] == 13); // required by MI_Rhino assert(monfiledata[MOFILE_SNAKE].moAnimFrameLen[MA_ATTACK] == 1); // required by MI_Rhino assert(monfiledata[MOFILE_MAGMA].moAnimFrameLen[MA_SPECIAL] == 1); // required by MonDoRSpAttack - +#ifdef DEBUG_DATA // towners for (i = 0; i < STORE_TOWNERS; i++) { //const int(*gl)[2] = &GossipList[i]; @@ -1293,6 +1297,7 @@ void ValidateData() app_fatal("Too high GossipList range (%d-%d) for %d", gl[0], gl[1], i); } } +#endif // DEBUG_DATA } #endif /* DEBUG_MODE || DEV_MODE */ From b1c431a210634952c2be3b2c94c22bce1ec8b38d Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 17 Aug 2024 08:46:58 +0200 Subject: [PATCH 436/596] extend the validations of monsterdata/monfiledata --- Source/debug.cpp | 61 +++++++++++++++++++++++++++++++++++++++++++++ Source/monstdat.cpp | 2 +- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/Source/debug.cpp b/Source/debug.cpp index 56f5b35c5c7..3730a333063 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -106,6 +106,13 @@ static void PrintText(const char* text, char lineSep, int limit) fclose(textFile); } +/* copy-paste from monster.cpp */ +static bool IsSkel(int mt) +{ + return (mt >= MT_WSKELAX && mt <= MT_XSKELAX) + || (mt >= MT_WSKELBW && mt <= MT_XSKELBW) + || (mt >= MT_WSKELSD && mt <= MT_XSKELSD); +} void ValidateData() { @@ -257,6 +264,7 @@ void ValidateData() assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_KNOCKBACK)); // required by MonHitByMon assert(!(monsterdata[MT_GOLEM].mFlags & MFLAG_CAN_BLEED)); // required by MonHitByMon and MonHitByPlr assert(monsterdata[MT_GOLEM].mSelFlag == 0); // required by CheckCursMove + assert(monsterdata[MT_GBAT].mAI.aiType == AI_BAT); // required by MAI_Bat #ifdef DEBUG_DATA for (i = 0; i < NUM_MTYPES; i++) { const MonsterData& md = monsterdata[i]; @@ -288,6 +296,57 @@ void ValidateData() app_fatal("Invalid mLevel %d for %s (%d). Too high to set the level of item-drop.", md.mLevel, md.mName, i); if (md.moFileNum == MOFILE_DIABLO && !(md.mFlags & MFLAG_NOCORPSE)) app_fatal("MOFILE_DIABLO does not have corpse animation but MFLAG_NOCORPSE is not set for %s (%d).", md.mName, i); + if (lengthof(monfiledata) <= md.moFileNum) + app_fatal("Invalid moFileNum %d for %s (%d). Must not be more than %d.", md.mLevel, md.mName, i, lengthof(monfiledata)); + BYTE afnumReq = 0, altDamReq = 0; + if (md.mAI.aiType == AI_ROUNDRANGED || md.mAI.aiType == AI_ROUNDRANGED2 || (md.mAI.aiType == AI_RANGED && md.mAI.aiParam2) // required for MonStartRSpAttack / MonDoRSpAttack +#ifdef HELLFIRE + || md.mAI.aiType == AI_HORKDMN +#endif + ) { + afnumReq |= 2; + } + if (md.mAI.aiType == AI_FAT || md.mAI.aiType == AI_ROUND || md.mAI.aiType == AI_GARBUD || md.mAI.aiType == AI_SCAV || md.mAI.aiType == AI_GARG) { // required for MonStartSpAttack / MonDoSpAttack + afnumReq |= 1; + } + if ((md.mAI.aiType == AI_FALLEN || md.mAI.aiType == AI_GOLUM || IsSkel(i)) && monfiledata[md.moFileNum].moSndSpecial) { // required for MonStartSpStand + afnumReq |= 2; + } + if (md.mAI.aiType == AI_RHINO || md.mAI.aiType == AI_SNAKE) { // required for MissToMonst + altDamReq |= 1; // requires mMaxDamage2 + } + if (afnumReq != 0) { + if (afnumReq & 2) { + // moAFNum2 required + if (monfiledata[md.moFileNum].moAFNum2 == 0) { + app_fatal("moAFNum2 is not set for %s (%d).", md.mName, i); + } + } + if (afnumReq & 1) { + // moAFNum2 optional + if (monfiledata[md.moFileNum].moAFNum2 != 0) { + altDamReq |= 3; // requires mMaxDamage2 and mHit2 + } + } + } else { + if (monfiledata[md.moFileNum].moAFNum2 != 0) + LogErrorF("moAFNum2 is set for %s (%d), but it is not used.", md.mName, i); + } + if (altDamReq != 0) { + if (altDamReq & 1) { + if (md.mMaxDamage2 == 0) + app_fatal("mMaxDamage2 is not set for %s (%d).", md.mName, i); + } + if (altDamReq & 2) { + if (md.mHit2 == 0) + app_fatal("mHit2 is not set for %s (%d).", md.mName, i); + } + } else { + if (md.mHit2 != 0) + LogErrorF("mHit2 is set for %s (%d), but it is not used.", md.mName, i); + if (md.mMaxDamage2 != 0) + LogErrorF("mMaxDamage2 is set (%d) for %s (%d), but it is not used.", md.mMaxDamage2, md.mName, i); + } if (md.mHit > INT_MAX /*- HELL_TO_HIT_BONUS */- HELL_LEVEL_BONUS * 5 / 2) // required by InitMonsterStats app_fatal("Too high mHit %d for %s (%d).", md.mHit, md.mName, i); if (md.mHit2 > INT_MAX /*- HELL_TO_HIT_BONUS */- HELL_LEVEL_BONUS * 5 / 2) // required by InitMonsterStats @@ -342,6 +401,8 @@ void ValidateData() app_fatal("Too long(%d) attack animation for %s (%d) to finish before relax.", md.moAnimFrameLen[MA_ATTACK] * md.moAnimFrames[MA_ATTACK], md.moGfxFile, i); if (md.moAnimFrameLen[MA_SPECIAL] * md.moAnimFrames[MA_SPECIAL] >= SQUELCH_LOW) app_fatal("Too long(%d) special animation for %s (%d) to finish before relax.", md.moAnimFrameLen[MA_SPECIAL] * md.moAnimFrames[MA_SPECIAL], md.moGfxFile, i); + if (md.moAnimFrameLen[MA_SPECIAL] == 0 && md.moAFNum2 != 0) + app_fatal("moAFNum2 is set for %s (%d), but it has no special animation.", md.moGfxFile, i); } #endif // umt checks for GetLevelMTypes diff --git a/Source/monstdat.cpp b/Source/monstdat.cpp index f6c4b33ab0f..96fdab201c7 100644 --- a/Source/monstdat.cpp +++ b/Source/monstdat.cpp @@ -217,7 +217,7 @@ const MonFileData monfiledata[NUM_MOFILE] = { /*MOFILE_BYCLPS*/ { 800, "Monsters\\Byclps\\Byclps%c.CL2", "Monsters\\newsfx\\Biclop%c%d.WAV", { 10, 11, 16, 6, 16, 0 }, { 2, 1, 1, 1, 2, 0 }, 180, FALSE, 8, 0 }, // moImage = 974 ? /*MOFILE_FLESH*/ { 800, "Monsters\\Flesh\\Flesh%c.CL2", "Monsters\\newsfx\\FleshT%c%d.WAV", { 15, 24, 15, 6, 16, 0 }, { 1, 1, 1, 1, 1, 0 }, 164, TRUE, 8, 0 }, // moImage = 1711 ? /*MOFILE_REAPER*/ { 800, "Monsters\\Reaper\\Reap%c.CL2", "Monsters\\newsfx\\Reaper%c%d.WAV", { 12, 10, 14, 6, 16, 0 }, { 2, 1, 1, 1, 1, 0 }, 180, FALSE, 8, 0 }, // moImage = 1546 ? -/*MOFILE_NKR*/ { 1200, "Monsters\\Nkr\\Nkr%c.CL2", "Monsters\\newsfx\\Nakrul%c%d.WAV", { 2, 6, 16, 6, 16, 0 }, { 1, 1, 1, 1, 1, 0 }, 226, FALSE, 7, 10 }, // moImage = 2763 ? moSndSpecial was TRUE, but unused +/*MOFILE_NKR*/ { 1200, "Monsters\\Nkr\\Nkr%c.CL2", "Monsters\\newsfx\\Nakrul%c%d.WAV", { 2, 6, 16, 6, 16, 0 }, { 1, 1, 1, 1, 1, 0 }, 226, FALSE, 7, 0 }, // moImage = 2763 ? moSndSpecial was TRUE, but unused #endif // clang-format on }; From 51c3a8d81e93031b16fe4028fb6f8d8f50fcc716 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 17 Aug 2024 08:47:44 +0200 Subject: [PATCH 437/596] reduce the cost of SPL_SHROUD --- Source/spelldat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/spelldat.cpp b/Source/spelldat.cpp index 8bc8522ec17..fda2c5c4f1c 100644 --- a/Source/spelldat.cpp +++ b/Source/spelldat.cpp @@ -71,7 +71,7 @@ const SpellData spelldata[NUM_SPELLS] = { /*SPL_FLARE*/ { 25, STYPE_MAGIC, 36, "Blood Star", 14, 26, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 70, IS_CAST2, MIS_FLARE, 4, 14, 30, 80, 27500, 30, ALIGN64 }, /*SPL_POISON*/ { 22, STYPE_MAGIC, 25, "Poison", 18, 28, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 70, IS_CAST2, MIS_POISON, 1, 18, 30, 70, 24500, 30, ALIGN64 }, /*SPL_WIND*/ { 24, STYPE_MAGIC, 22, "Wind", 10, 18, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 44, IS_CAST2, MIS_WIND, 2, 12, 40, 80, 12500, 35, ALIGN64 }, -/*SPL_SHROUD*/ { 46, STYPE_MAGIC, 19, "Shroud", 20, 28, 18, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 36, IS_CAST2, MIS_SHROUD, 1, 18, 20, 60, 20500, 80, ALIGN64 }, +/*SPL_SHROUD*/ { 28, STYPE_MAGIC, 19, "Shroud", 20, 28, 18, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 36, IS_CAST2, MIS_SHROUD, 1, 18, 20, 60, 20500, 80, ALIGN64 }, /*SPL_GUARDIAN*/ { 50, STYPE_FIRE, 18, "Guardian", 9, 16, 12, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 61, IS_CAST2, MIS_GUARDIAN, 4, 30, 16, 32, 14000, 90, ALIGN64 }, /*SPL_GOLEM*/ { 100, STYPE_FIRE, 21, "Golem", 11, 18, 10, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 81, IS_CAST2, MIS_GOLEM, 10, 60, 16, 32, 18000, 200, ALIGN64 }, /*SPL_STONE*/ { 60, STYPE_MAGIC, 8, "Stone Curse", 6, 10, 6, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 51, IS_CAST2, MIS_STONE, 4, 40, 8, 16, 12000, 160, ALIGN64 }, From cfcb96ba7fbd65121db49cd39217d57abc67e433 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 17 Aug 2024 08:50:33 +0200 Subject: [PATCH 438/596] add Swamp spell --- Source/control.cpp | 2 +- Source/misdat.cpp | 3 +++ Source/misproc.h | 1 + Source/missiles.cpp | 63 ++++++++++++++++++++++++++++++++++++++++++--- Source/monster.cpp | 30 +++++++++++++++++++++ Source/monster.h | 1 + Source/player.cpp | 22 ++++++++++++++++ Source/player.h | 1 + Source/spelldat.cpp | 2 ++ docs/CHANGELOG.md | 2 +- enums.h | 4 +++ 11 files changed, 125 insertions(+), 6 deletions(-) diff --git a/Source/control.cpp b/Source/control.cpp index e011bd1181b..2b88ec31878 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -146,7 +146,7 @@ static BYTE SpellPages[SPLBOOKTABS][NUM_BOOK_ENTRIES] = { { SPL_WHIPLASH, SPL_WALLOP, SPL_SWIPE, SPL_POINT_BLANK, SPL_FAR_SHOT, SPL_MULTI_SHOT, SPL_PIERCE_SHOT }, { SPL_GOLEM, SPL_MANASHIELD, SPL_HEAL, SPL_HEALOTHER, SPL_RNDTELEPORT, SPL_TELEPORT, SPL_TOWN }, { SPL_METEOR, SPL_HBOLT, SPL_FLARE, SPL_FLASH, SPL_POISON, SPL_BLOODBOIL, SPL_WIND }, - { SPL_CHARGE, SPL_RAGE, SPL_INVALID, SPL_SHROUD, SPL_TELEKINESIS, SPL_ATTRACT, SPL_STONE }, + { SPL_CHARGE, SPL_RAGE, SPL_SWAMP, SPL_SHROUD, SPL_TELEKINESIS, SPL_ATTRACT, SPL_STONE }, #ifdef HELLFIRE { SPL_FIRERING, SPL_RUNEFIRE, SPL_RUNEWAVE, SPL_RUNELIGHT, SPL_RUNENOVA, SPL_INVALID, SPL_INVALID }, #endif diff --git a/Source/misdat.cpp b/Source/misdat.cpp index cb56117dffc..7f124bddc29 100644 --- a/Source/misdat.cpp +++ b/Source/misdat.cpp @@ -47,6 +47,8 @@ const MissileData missiledata[] = { /*MIS_LIGHTNING2*/ { &AddLightning, &MI_Lightning, MIF_SHROUD | MIF_NOBLOCK | MIF_DOT, MISR_LIGHTNING, MFILE_THINLGHT, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, /*MIS_BLOODBOILC*/ { &AddBloodBoilC, &MI_BloodBoilC, 0, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, /*MIS_BLOODBOIL*/ { &AddBloodBoil, &MI_BloodBoil, 0, MISR_MAGIC, MFILE_BLODBURS, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, +/*MIS_SWAMPC*/ { &AddBloodBoilC, &MI_SwampC, 0, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, +/*MIS_SWAMP*/ { &AddMisexp, &MI_LongExp, 0, MISR_NONE, MFILE_SWAMP, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, /*MIS_TOWN*/ { &AddTown, &MI_Portal, 0, MISR_NONE, MFILE_PORTAL, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, /*MIS_RPORTAL*/ { &AddPortal, &MI_Portal, 0, MISR_NONE, MFILE_RPORTAL, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, /*MIS_FLASH*/ { &AddFlash, &MI_Flash, MIF_NOBLOCK | MIF_AREA | MIF_DOT, MISR_MAGIC, MFILE_BLUEXFR, TRUE, LS_NOVA, SFX_NONE, 1, 1, ALIGN }, // miSFX was LS_ELECIMP1 @@ -155,6 +157,7 @@ const MisFileData misfiledata[NUM_MFILE + 1] = { /*MFILE_DOOM*/// { 9, "Doom", NULL, 0, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, { 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0 }, 96, 16, ALIGN }, /*MFILE_DOOMEXP*///{ 1, "Doomexp", NULL, 0, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 96, 16, ALIGN }, /*MFILE_BLODBURS*/ { 1, "Blodburs", NULL, 0, { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 128, 32, ALIGN }, +/*MFILE_SWAMP*/ { 1, "Blodburs", "Monsters\\FalSpear\\FallenT.TRN", 0, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 128, 32, ALIGN }, /*MFILE_NEWEXP*/// { 1, "Newexp", NULL, 0, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 96, 16, ALIGN }, /*MFILE_SHATTER1*/ { 1, "Shatter1", NULL, 0, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 128, 32, ALIGN }, /*MFILE_BIGEXP*/ { 1, "Bigexp", NULL, 0, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 160, 48, ALIGN }, diff --git a/Source/misproc.h b/Source/misproc.h index 2a04f7a61da..39107a2663b 100644 --- a/Source/misproc.h +++ b/Source/misproc.h @@ -100,6 +100,7 @@ void MI_LightningC(int mi); void MI_Lightning(int mi); void MI_BloodBoilC(int mi); void MI_BloodBoil(int mi); +void MI_SwampC(int mi); void MI_Bleed(int mi); void MI_Portal(int mi); void MI_Flash(int mi); diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 7bb7e06b3d7..b9980df9c29 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -2360,7 +2360,8 @@ int AddMisexp(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, i } //mis->_mixvel = 0; //mis->_miyvel = 0; - mis->_miRange = mis->_miAnimLen; + // assert(mis->_miAnimFrameLen == 1); + mis->_miRange = mis->_miAnimLen/* * mis->_miAnimFrameLen*/; return MIRES_DONE; } @@ -3980,15 +3981,15 @@ void MI_BloodBoilC(int mi) int mx, my; mis = &missile[mi]; - assert(misfiledata[MFILE_BLODBURS].mfAnimFrameLen[0] * misfiledata[MFILE_BLODBURS].mfAnimLen[0] == 16); - if ((mis->_miVar1++ & 7) == 0) { + // assert(mis->_miType == MIS_BLOODBOILC || mis->_miType == MIS_SWAMPC); + if ((mis->_miVar1++ & (mis->_miType == MIS_BLOODBOILC ? 7 : 3)) == 0) { mis->_miVar2++; if (mis->_miVar2 >= lengthof(BloodBoilLocs)) mis->_miVar2 = 0; mx = mis->_mix + BloodBoilLocs[mis->_miVar2][0]; my = mis->_miy + BloodBoilLocs[mis->_miVar2][1]; if ((nMissileTable[dPiece[mx][my]] | dObject[mx][my]) == 0) { - AddMissile(mx, my, 0, 0, 0, MIS_BLOODBOIL, mis->_miCaster, mis->_miSource, mis->_miSpllvl); + AddMissile(mx, my, -1, 0, 0, mis->_miType == MIS_BLOODBOILC ? MIS_BLOODBOIL : MIS_SWAMP, mis->_miCaster, mis->_miSource, mis->_miSpllvl); } } mis->_miRange--; @@ -3996,6 +3997,60 @@ void MI_BloodBoilC(int mi) mis->_miDelFlag = TRUE; } +void MI_SwampC(int mi) +{ + MissileStruct *mis, *bmis; + int i, bmi, dx, dy, mx, my, mnum, pnum; + bool matches[16][16] = { false }; + const int bx = 8 - 2; const int by = 8 - 2; + + mis = &missile[mi]; + for (i = 0; i < nummissiles; i++) { + bmi = missileactive[i]; + bmis = &missile[bmi]; + if (bmis->_miType != MIS_SWAMPC) + continue; + if (bmis->_miSpllvl < mis->_miSpllvl) + continue; + if (bmis->_miSpllvl == mis->_miSpllvl && mi <= bmi) + continue; + dx = bmis->_mix - mis->_mix; + dy = bmis->_miy - mis->_miy; + if (dx < -4 || dx > 4 || dy < -4 || dy > 4) + continue; + dx += bx; + dy += by; + for (int n = 0; n < lengthof(BloodBoilLocs); n++) { + mx = dx + BloodBoilLocs[n][0]; + my = dy + BloodBoilLocs[n][1]; + matches[mx][my] = true; + } + } + + for (int n = 0; n < lengthof(BloodBoilLocs); n++) { + dx = BloodBoilLocs[n][0]; + dy = BloodBoilLocs[n][1]; + if (matches[dx + bx][dy + by]) + continue; + mx = mis->_mix + dx; + my = mis->_miy + dy; + + mnum = dMonster[mx][my]; + if (mnum < 0) { + mnum = -(mnum + 1); + MonHinder(mnum, mis->_miSpllvl, mis->_miVar1); + } else { + pnum = dPlayer[mx][my]; + if (pnum < 0) { + pnum = -(pnum + 1); + PlrHinder(pnum, mis->_miSpllvl, mis->_miVar1); + } + } + } + + MI_BloodBoilC(mi); +} + void MI_BloodBoil(int mi) { MissileStruct* mis; diff --git a/Source/monster.cpp b/Source/monster.cpp index c084a0d7e89..8146350613a 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -4629,6 +4629,36 @@ void SyncMonsterAnim(int mnum) mon->_mAnimLen = mon->_mAnims[anim].maFrames; } +void MonHinder(int mnum, int spllvl, unsigned tick) +{ + MonsterStruct* mon; + int effect; + if ((unsigned)mnum >= MAXMONSTERS) { + dev_fatal("MonHinder: Invalid monster %d", mnum); + } + mon = &monsters[mnum]; + if ((mon->_mmode < MM_WALK || mon->_mmode > MM_WALK2) && mon->_mmode != MM_CHARGE) + return; + + effect = spllvl * 6 - mon->_mLevel; + effect = effect >= 6 ? 2 : (effect > 0 ? 3 : (effect >= -6 ? 4 : 0)); + if (effect != 0 && ((unsigned)tick % (unsigned)effect) == 0) { + if (mon->_mmode != MM_CHARGE) { + mon->_mAnimCnt--; + mon->_mVar6 -= mon->_mVar4; // MWALK_XOFF <- WALK_XVEL + mon->_mVar7 -= mon->_mVar5; // MWALK_YOFF <- WALK_YVEL + } else { + AssertFixMonLocation(mnum); + // assert(dMonster[mon->_mx][mon->_my] == -(mnum + 1)); + dMonster[mon->_mx][mon->_my] = mnum + 1; + // assert(dPlayer[mon->_mx][mon->_my] == 0); + // assert(!(mon->_mFlags & MFLAG_HIDDEN)); + //ChangeLightXYOff(mon->_mlid, mon->_mx, mon->_my); + MonStartStand(mnum); + } + } +} + void MissToMonst(int mi) { MissileStruct* mis; diff --git a/Source/monster.h b/Source/monster.h index 3fa89ff4399..1c09da64a45 100644 --- a/Source/monster.h +++ b/Source/monster.h @@ -59,6 +59,7 @@ void FreeMonsters(); //bool CheckAllowMissile(int x, int y); bool LineClear(int x1, int y1, int x2, int y2); void SyncMonsterAnim(int mnum); +void MonHinder(int mnum, int spllvl, unsigned tick); void MissToMonst(int mi); /* Check if the monster can be displaced to the given position. (unwillingly) */ bool PosOkMonster(int mnum, int x, int y); diff --git a/Source/player.cpp b/Source/player.cpp index 7f25d34d607..1fcd8131fc8 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -2886,6 +2886,28 @@ void ClrPlrPath(int pnum) //memset(plr._pWalkpath, DIR_NONE, sizeof(plr._pWalkpath)); } +void PlrHinder(int pnum, int spllvl, unsigned tick) +{ + int effect; + if ((unsigned)pnum >= MAX_PLRS) { + dev_fatal("PlrHinder: illegal player %d", pnum); + } + if ((plr._pmode < PM_WALK || plr._pmode > PM_WALK2 /*|| plr._pAnimFrame == plr._pAnimLen*/) && plr._pmode != PM_CHARGE) + return; + effect = spllvl * 4 - plr._pLevel; + effect = effect > 10 ? 2 : (effect > 0 ? 3 : (effect > -10 ? 4 : 0)); + if (effect != 0 && ((unsigned)tick % (unsigned)effect) == 0) { + if (plr._pmode != PM_CHARGE) { + plr._pAnimCnt--; + plr._pVar6 -= plr._pVar4; // WALK_XOFF <- WALK_XVEL + plr._pVar7 -= plr._pVar5; // WALK_YOFF <- WALK_YVEL + plr._pVar8--; // WALK_TICK + } else { + PlrStartStand(pnum); + } + } +} + void MissToPlr(int mi, bool hit) { MissileStruct* mis; diff --git a/Source/player.h b/Source/player.h index f765c67f8ec..498f27f2cbc 100644 --- a/Source/player.h +++ b/Source/player.h @@ -55,6 +55,7 @@ bool PlrDecHp(int pnum, int hp, int dmgtype); void PlrDecMana(int pnum, int mana); void ProcessPlayers(); void ClrPlrPath(int pnum); +void PlrHinder(int pnum, int spllvl, unsigned tick); void MissToPlr(int mi, bool hit); bool PosOkActor(int x, int y); bool PosOkPlayer(int pnum, int x, int y); diff --git a/Source/spelldat.cpp b/Source/spelldat.cpp index fda2c5c4f1c..8e5a4aa54ae 100644 --- a/Source/spelldat.cpp +++ b/Source/spelldat.cpp @@ -26,6 +26,7 @@ DEVILUTION_BEGIN_NAMESPACE #endif /* + reused icons : 4 unused icons : // hellfire only 51 - SPL_MANA/MAGI 50 - SPL_JESTER @@ -72,6 +73,7 @@ const SpellData spelldata[NUM_SPELLS] = { /*SPL_POISON*/ { 22, STYPE_MAGIC, 25, "Poison", 18, 28, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 70, IS_CAST2, MIS_POISON, 1, 18, 30, 70, 24500, 30, ALIGN64 }, /*SPL_WIND*/ { 24, STYPE_MAGIC, 22, "Wind", 10, 18, SPELL_NA, SDFLAG_TARGETED, CURSOR_NONE, CURSOR_NONE, SFLAG_DUNGEON, 44, IS_CAST2, MIS_WIND, 2, 12, 40, 80, 12500, 35, ALIGN64 }, /*SPL_SHROUD*/ { 28, STYPE_MAGIC, 19, "Shroud", 20, 28, 18, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 36, IS_CAST2, MIS_SHROUD, 1, 18, 20, 60, 20500, 80, ALIGN64 }, +/*SPL_SWAMP*/ { 21, STYPE_MAGIC, 4, "Swamp", 30, 40, 24, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 36, IS_CAST2, MIS_SWAMPC, 1, 16, 20, 60, 18500, 70, ALIGN64 }, /*SPL_GUARDIAN*/ { 50, STYPE_FIRE, 18, "Guardian", 9, 16, 12, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 61, IS_CAST2, MIS_GUARDIAN, 4, 30, 16, 32, 14000, 90, ALIGN64 }, /*SPL_GOLEM*/ { 100, STYPE_FIRE, 21, "Golem", 11, 18, 10, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 81, IS_CAST2, MIS_GOLEM, 10, 60, 16, 32, 18000, 200, ALIGN64 }, /*SPL_STONE*/ { 60, STYPE_MAGIC, 8, "Stone Curse", 6, 10, 6, SDFLAG_TARGETED, CURSOR_TELEPORT, CURSOR_NONE, SFLAG_DUNGEON, 51, IS_CAST2, MIS_STONE, 4, 40, 8, 16, 12000, 160, ALIGN64 }, diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index c8ede6b5760..33eeba5b27f 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -34,7 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - separate resistance against acid - slash/blunt/puncture damage types with corresponding resistances - added Whiplash/Wallop/Swipe/Multi Shot/Pierce Shot/Far Shot/Point Blank/Charge skills -- added Attract/Meteor/Bloodboil/Poison/Wind/Shroud spells +- added Attract/Meteor/Bloodboil/Poison/Wind/Shroud/Swamp spells - skills/spells have experience counters - books give skill experience instead of a whole level - rebalanced spells (some spells removed, others damage modified, runes fire multiple times, etc...) diff --git a/enums.h b/enums.h index a27f45f3f73..19833dec2c1 100644 --- a/enums.h +++ b/enums.h @@ -1953,6 +1953,8 @@ typedef enum missile_id { MIS_LIGHTNING2, MIS_BLOODBOILC, MIS_BLOODBOIL, + MIS_SWAMPC, + MIS_SWAMP, MIS_TOWN, MIS_RPORTAL, MIS_FLASH, @@ -2072,6 +2074,7 @@ typedef enum missile_gfx_id { //MFILE_DOOM, //MFILE_DOOMEXP, MFILE_BLODBURS, + MFILE_SWAMP, //MFILE_NEWEXP, MFILE_SHATTER1, MFILE_BIGEXP, @@ -3814,6 +3817,7 @@ typedef enum spell_id { SPL_POISON, SPL_WIND, SPL_SHROUD, + SPL_SWAMP, SPL_GUARDIAN, SPL_GOLEM, SPL_STONE, From f37e551e8c81b73fea3ec64a306e8f3b8ca16437 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 18 Aug 2024 09:49:44 +0200 Subject: [PATCH 439/596] update StormLib --- 3rdParty/StormLib/README | 1 + 3rdParty/StormLib/src/SFileGetFileInfo.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/3rdParty/StormLib/README b/3rdParty/StormLib/README index e8d6da65efd..6c08f5b87d8 100644 --- a/3rdParty/StormLib/README +++ b/3rdParty/StormLib/README @@ -1,5 +1,6 @@ This is a slightly modified version of ladislav-zezula/StormLib@bf6a10b5e54c541ba5b17562ab139e58eac6393c (11.10.2023) except for 7da097c51323f15752f252e8c5ed0bd1a349ec75, 18e92b75928995dbd93be9a5774a62aa19042614, 8a16217c5167240cada465727f67fdaf23b08f86 and 6f89c7ba8530c37f1f5a6048406cb18c40e5a458 +there are no relevant modifications till ladislav-zezula/StormLib@539a04e06578ce9b0cf005446eff66e18753076d (25.07.2024) Changes: diff --git a/3rdParty/StormLib/src/SFileGetFileInfo.cpp b/3rdParty/StormLib/src/SFileGetFileInfo.cpp index ee7109b2109..db933869f7a 100644 --- a/3rdParty/StormLib/src/SFileGetFileInfo.cpp +++ b/3rdParty/StormLib/src/SFileGetFileInfo.cpp @@ -482,7 +482,7 @@ bool WINAPI SFileFreeFileInfo(void * pvFileInfo, SFileInfoClass InfoClass) //----------------------------------------------------------------------------- // Tries to retrieve the file name -struct TFileHeader2Ext +/*struct TFileHeader2Ext { DWORD dwOffset00Data; // Required data at offset 00 (32-bits) DWORD dwOffset00Mask; // Mask for data at offset 00 (32 bits). 0 = data are ignored @@ -530,7 +530,7 @@ static TFileHeader2Ext data2ext[] = {0, 0, 0, 0, NULL} // Terminator }; -/*static DWORD CreatePseudoFileName(HANDLE hFile, TFileEntry * pFileEntry, char * szFileName) +static DWORD CreatePseudoFileName(HANDLE hFile, TFileEntry * pFileEntry, char * szFileName) { TMPQFile * hf = (TMPQFile *)hFile; // MPQ File handle DWORD FirstBytes[2] = {0, 0}; // The first 4 bytes of the file From b7150f45f6024304b02887ab8ae887a21ad816e3 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 18 Aug 2024 09:53:40 +0200 Subject: [PATCH 440/596] use MAX_REP_LENGTH in implode.cpp --- 3rdParty/PKWare/implode.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/3rdParty/PKWare/implode.cpp b/3rdParty/PKWare/implode.cpp index 95404993d7f..d2f94a0ce29 100644 --- a/3rdParty/PKWare/implode.cpp +++ b/3rdParty/PKWare/implode.cpp @@ -386,7 +386,7 @@ static unsigned int FindRep(TCmpStruct * pWork, unsigned char * input_data) // Find out how many more characters are equal to the first repetition. while(*prev_rep_end == input_data[rep_length2]) { - if(++rep_length2 >= 0x204) + if(++rep_length2 >= MAX_REP_LENGTH) break; prev_rep_end++; } @@ -396,7 +396,7 @@ static unsigned int FindRep(TCmpStruct * pWork, unsigned char * input_data) { // Calculate the distance of the new repetition pWork->distance = (unsigned int)(input_data - prev_repetition - 1); - if((rep_length = rep_length2) == 0x204) + if((rep_length = rep_length2) == MAX_REP_LENGTH) return rep_length; // Update the additional elements in the "offs09BC" table @@ -418,7 +418,7 @@ static unsigned int FindRep(TCmpStruct * pWork, unsigned char * input_data) static void WriteCmpData(TCmpStruct * pWork) { unsigned char * input_data_end; // Pointer to the end of the input data - unsigned char * input_data = pWork->work_buff + pWork->dsize_bytes + 0x204; + unsigned char * input_data = pWork->work_buff + pWork->dsize_bytes + MAX_REP_LENGTH; unsigned int input_data_ended = 0; // If 1, then all data from the input stream have been already loaded unsigned int save_rep_length; // Saved length of current repetition unsigned int save_distance = 0; // Saved distance of current repetition @@ -443,7 +443,7 @@ static void WriteCmpData(TCmpStruct * pWork) // Load the bytes from the input stream, up to 0x1000 bytes while(bytes_to_load != 0) { - bytes_loaded = pWork->read_buf((char *)pWork->work_buff + pWork->dsize_bytes + 0x204 + total_loaded, + bytes_loaded = pWork->read_buf((char *)pWork->work_buff + pWork->dsize_bytes + MAX_REP_LENGTH + total_loaded, &bytes_to_load, pWork->param); if(bytes_loaded == 0) @@ -462,7 +462,7 @@ static void WriteCmpData(TCmpStruct * pWork) input_data_end = pWork->work_buff + pWork->dsize_bytes + total_loaded; if(input_data_ended) - input_data_end += 0x204; + input_data_end += MAX_REP_LENGTH; // // Warning: The end of the buffer passed to "SortBuffer" is actually 2 bytes beyond @@ -485,7 +485,7 @@ static void WriteCmpData(TCmpStruct * pWork) break; case 1: - SortBuffer(pWork, input_data - pWork->dsize_bytes + 0x204, input_data_end + 1); + SortBuffer(pWork, input_data - pWork->dsize_bytes + MAX_REP_LENGTH, input_data_end + 1); phase++; break; @@ -593,7 +593,7 @@ _00402252:; if(input_data_ended == 0) { input_data -= 0x1000; - memmove(pWork->work_buff, pWork->work_buff + 0x1000, pWork->dsize_bytes + 0x204); + memmove(pWork->work_buff, pWork->work_buff + 0x1000, pWork->dsize_bytes + MAX_REP_LENGTH); } } From 551e1aeec2354646871e59d0239aac683f3559ca Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 18 Aug 2024 09:54:35 +0200 Subject: [PATCH 441/596] fix vulnerability alert fixes #12 --- 3rdParty/PKWare/implode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdParty/PKWare/implode.cpp b/3rdParty/PKWare/implode.cpp index d2f94a0ce29..e36483f1036 100644 --- a/3rdParty/PKWare/implode.cpp +++ b/3rdParty/PKWare/implode.cpp @@ -169,7 +169,7 @@ static unsigned int FindRep(TCmpStruct * pWork, unsigned char * input_data) unsigned char * input_data_ptr; unsigned short phash_offs_index; // Index to the table with PAIR_HASH positions unsigned short min_phash_offs; // The lowest allowed hash offset - unsigned short offs_in_rep; // Offset within found repetition + unsigned int offs_in_rep; // Offset within found repetition unsigned int equal_byte_count; // Number of bytes that are equal to the previous occurence unsigned int rep_length = 1; // Length of the found repetition unsigned int rep_length2; // Secondary repetition From fd648ce8e59963aeb8fd47979e0d534bccbec30f Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 18 Aug 2024 10:37:09 +0200 Subject: [PATCH 442/596] fix vulnerability alert II. - use size_t for audioLength to fix the alert - use unsigned type to make the code more robust fixes #13 --- 3rdParty/SDL2_mixer/src/mixer.c | 2 +- 3rdParty/SDL2_mixer/src/types_internal.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/3rdParty/SDL2_mixer/src/mixer.c b/3rdParty/SDL2_mixer/src/mixer.c index 1edb297a849..e6933e9bc27 100644 --- a/3rdParty/SDL2_mixer/src/mixer.c +++ b/3rdParty/SDL2_mixer/src/mixer.c @@ -829,7 +829,7 @@ Mix_Audio* Mix_LoadWAV_RW(Mix_RWops* src, SDL_bool stream) #ifdef FULL // SELF_CONV SDL_AudioCVT wavecvt; #endif - int audioLength; + size_t audioLength; #ifdef FULL // WAV_CHECK /* rcg06012001 Make sure src is valid */ if (!src) { diff --git a/3rdParty/SDL2_mixer/src/types_internal.h b/3rdParty/SDL2_mixer/src/types_internal.h index 1b4e9bddd9b..fcc175c6197 100644 --- a/3rdParty/SDL2_mixer/src/types_internal.h +++ b/3rdParty/SDL2_mixer/src/types_internal.h @@ -267,8 +267,8 @@ typedef struct { Sint64 samplesize; #endif #else - int start; - int stop; + unsigned start; + unsigned stop; #ifdef FULL // MUS_ENC, SEEK int samplesize; #endif @@ -323,7 +323,7 @@ typedef struct _Mix_Audio { int lastChannel; #ifndef FULL // SELF_CONV void (*converters[3])(Mix_BuffOps* buf); - int convMpl; + unsigned convMpl; #endif } _Mix_Audio; #endif // FULL - FIX_MUS From 44d4b810beb41722113a332c759f7cdf71f6b853 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 18 Aug 2024 11:04:15 +0200 Subject: [PATCH 443/596] trigger code scanning manually --- .github/workflows/code-ql.yml | 92 +++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 .github/workflows/code-ql.yml diff --git a/.github/workflows/code-ql.yml b/.github/workflows/code-ql.yml new file mode 100644 index 00000000000..0eab2455c66 --- /dev/null +++ b/.github/workflows/code-ql.yml @@ -0,0 +1,92 @@ +name: Weekly Code Scanning + +#on: [push, pull_request] +on: + schedule: + - cron: "0 0 * * 0" # Every Sunday at midnight + +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} + permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + include: + - language: c-cpp + build-mode: autobuild + - language: java-kotlin + build-mode: none # This mode only analyzes Java. Set this to 'autobuild' or 'manual' to analyze Kotlin too. + - language: python + build-mode: none + #- language: ruby + # build-mode: none + # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" + From 2728317beea37f39f989e97b2a42eed7660520da Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 18 Aug 2024 13:12:24 +0200 Subject: [PATCH 444/596] make DRLG_L1PlaceThemeRooms a bit more readable --- Source/drlg_l1.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Source/drlg_l1.cpp b/Source/drlg_l1.cpp index edac04b515d..4de3c814156 100644 --- a/Source/drlg_l1.cpp +++ b/Source/drlg_l1.cpp @@ -1976,14 +1976,12 @@ static void DRLG_L1PlaceThemeRooms() if (!fit) continue; // create the room - int w = roomRight - roomLeft + 1; - int h = roomBottom - roomTop + 1; - w += 2; - h += 2; + int w = (roomRight + 1) - (roomLeft - 1) + 1; + int h = (roomBottom + 1) - (roomTop - 1) + 1; themes[numthemes]._tsx1 = roomLeft - 1; themes[numthemes]._tsy1 = roomTop - 1; - themes[numthemes]._tsx2 = roomLeft + w - 2; - themes[numthemes]._tsy2 = roomTop + h - 2; + themes[numthemes]._tsx2 = roomLeft - 1 + w - 1; + themes[numthemes]._tsy2 = roomTop - 1 + h - 1; numthemes++; if (numthemes == lengthof(themes)) break; From 7800509ae6d8c79810cbfd73da771471fee26eb5 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 18 Aug 2024 13:13:24 +0200 Subject: [PATCH 445/596] restore size-limit of the theme rooms in cathedral --- Source/drlg_l1.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/drlg_l1.cpp b/Source/drlg_l1.cpp index 4de3c814156..203ac7cc2af 100644 --- a/Source/drlg_l1.cpp +++ b/Source/drlg_l1.cpp @@ -1974,10 +1974,12 @@ static void DRLG_L1PlaceThemeRooms() } } if (!fit) - continue; + continue; // room is too small or incomplete // create the room int w = (roomRight + 1) - (roomLeft - 1) + 1; int h = (roomBottom + 1) - (roomTop - 1) + 1; + if (w * h > 100) + continue; // room is too large themes[numthemes]._tsx1 = roomLeft - 1; themes[numthemes]._tsy1 = roomTop - 1; themes[numthemes]._tsx2 = roomLeft - 1 + w - 1; From 13669bcf4b1b2ead9c27f9cb62aa613cf7d8ce32 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 18 Aug 2024 13:38:57 +0200 Subject: [PATCH 446/596] improve ValidaData - make the checks of the unique-item-powers more effective - check the conflict of IPL_SETAC and IPL_ACMOD - check the conflict of IPL_STR, IPL_MAG and IPL_DEX - add checks for itemfiledata - check MI_Misexp and MI_MiniExp separately (the limit is different) - fix unused local warning - fix the mMaxDamage-check of the unique monsters --- Source/debug.cpp | 436 +++++++++++++++++++---------------------------- 1 file changed, 180 insertions(+), 256 deletions(-) diff --git a/Source/debug.cpp b/Source/debug.cpp index 3730a333063..1691bea94c4 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -114,10 +114,75 @@ static bool IsSkel(int mt) || (mt >= MT_WSKELSD && mt <= MT_XSKELSD); } -void ValidateData() +static BYTE GetUniqueItemPower(const UniqItemData& ui, int index) +{ + switch (index) { + case 1: return ui.UIPower1; + case 2: return ui.UIPower2; + case 3: return ui.UIPower3; + case 4: return ui.UIPower4; + case 5: return ui.UIPower5; + case 6: return ui.UIPower6; + default: ASSUME_UNREACHABLE; return 0; + } +} + +static int GetUniqueItemParamA(const UniqItemData& ui, int index) +{ + switch (index) { + case 1: return ui.UIParam1a; + case 2: return ui.UIParam2a; + case 3: return ui.UIParam3a; + case 4: return ui.UIParam4a; + case 5: return ui.UIParam5a; + case 6: return ui.UIParam6a; + default: ASSUME_UNREACHABLE; return 0; + } +} + +static int GetUniqueItemParamB(const UniqItemData& ui, int index) +{ + switch (index) { + case 1: return ui.UIParam1b; + case 2: return ui.UIParam2b; + case 3: return ui.UIParam3b; + case 4: return ui.UIParam4b; + case 5: return ui.UIParam5b; + case 6: return ui.UIParam6b; + default: ASSUME_UNREACHABLE; return 0; + } +} + +static bool HasUniqueItemReq(const UniqItemData& ui, BYTE pow) { int i; + for (i = 1; i < 6; i++) { + if (pow == IPL_STR && GetUniqueItemPower(ui, i) == IPL_NOMINSTR) + return false; + } + for (i = 0; i < NUM_IDI; i++) { + const ItemData& ids = AllItemsList[i]; + if (ids.iUniqType == ui.UIUniqType) { + int minv; + switch (pow) { + case IPL_STR: minv = ids.iMinStr; break; + case IPL_MAG: minv = ids.iMinMag; break; + case IPL_DEX: minv = ids.iMinDex; break; + default:ASSUME_UNREACHABLE; break; + } + if (minv != 0) + return true; + } + } + return false; +} + +void ValidateData() +{ +#ifdef DEBUG_DATA + int i; +#endif #if DEBUG_MODE // dvlnet { @@ -492,7 +557,7 @@ void ValidateData() if (um.mUnqMag + monsterdata[um.mtype].mMagic > INT_MAX /*- HELL_MAGIC_BONUS */- HELL_LEVEL_BONUS * 5 / 2) // required by InitUniqueMonster app_fatal("Too high mUnqMag %d for %s (%d).", um.mUnqMag, um.mName, i); if (um.mMaxDamage == 0 && monsterdata[um.mtype].mMaxDamage != 0) - if (um.mQuestId != Q_INVALID) + if (um.mAI.aiType != AI_LACHDAN) app_fatal("mMaxDamage is not set for unique monster %s (%d).", um.mName, i); else DoLog("mMaxDamage is not set for unique monster %s (%d).", um.mName, i); @@ -818,16 +883,18 @@ void ValidateData() (pres->PLPower == IPL_FIRERES || pres->PLPower == IPL_LIGHTRES || pres->PLPower == IPL_MAGICRES || pres->PLPower == IPL_ACIDRES)) { app_fatal("IPL_FIRERES/IPL_LIGHTRES/IPL_MAGICRES/IPL_ACIDRES and IPL_ALLRES might be set for the same item."); } - if (sufs->PLPower == IPL_TOHIT && pres->PLPower == IPL_TOHIT_DAMP) { - app_fatal("IPL_TOHIT_DAMP and IPL_TOHIT might be set for the same item."); - } - if (pres->PLPower == IPL_TOHIT && sufs->PLPower == IPL_TOHIT_DAMP) { - app_fatal("IPL_TOHIT and IPL_TOHIT_DAMP might be set for the same item."); + if ((pres->PLPower == IPL_TOHIT || pres->PLPower == IPL_TOHIT_DAMP) && + (sufs->PLPower == IPL_TOHIT || sufs->PLPower == IPL_TOHIT_DAMP)) { + app_fatal("IPL_TOHIT/IPL_TOHIT_DAMP might be set for the same item."); } if ((pres->PLPower == IPL_DAMP || pres->PLPower == IPL_TOHIT_DAMP || pres->PLPower == IPL_CRYSTALLINE) && (sufs->PLPower == IPL_DAMP || sufs->PLPower == IPL_TOHIT_DAMP || sufs->PLPower == IPL_CRYSTALLINE)) { app_fatal("IPL_DAMP/IPL_TOHIT_DAMP/IPL_CRYSTALLINE might be set for the same item."); } + if ((pres->PLPower == IPL_SETAC || pres->PLPower == IPL_ACMOD) && + (sufs->PLPower == IPL_SETAC || sufs->PLPower == IPL_ACMOD)) { + app_fatal("IPL_SETAC/IPL_ACMOD might be set for the same item."); + } } } if (rnddrops > ITEM_RNDAFFIX_MAX || rnddrops > 0x7FFF) @@ -868,255 +935,94 @@ void ValidateData() // unique items for (i = 0; i < NUM_UITEM; i++) { const UniqItemData& ui = UniqueItemList[i]; - if (ui.UIPower1 == IPL_INVALID) - app_fatal("Unique item '%s' %d does not have any affix", ui.UIName, i); - //if (ui.UIPower1 != IPL_INVALID) { - if (ui.UIPower1 == ui.UIPower2) { - app_fatal("SaveItemPower does not support the same affix multiple times on '%s' %d, 1vs2.", ui.UIName, i); - } - if (ui.UIPower1 == ui.UIPower3) { - app_fatal("SaveItemPower does not support the same affix multiple times on '%s' %d, 1vs3.", ui.UIName, i); - } - if (ui.UIPower1 == ui.UIPower4) { - app_fatal("SaveItemPower does not support the same affix multiple times on '%s' %d, 1vs4.", ui.UIName, i); - } - if (ui.UIPower1 == ui.UIPower5) { - app_fatal("SaveItemPower does not support the same affix multiple times on '%s' %d, 1vs5.", ui.UIName, i); - } - if (ui.UIPower1 == ui.UIPower6) { - app_fatal("SaveItemPower does not support the same affix multiple times on '%s' %d, 1vs6.", ui.UIName, i); - } - //} - if (ui.UIPower2 != IPL_INVALID) { - if (ui.UIPower2 == ui.UIPower3) { - app_fatal("SaveItemPower does not support the same affix multiple times on '%s' %d, 2vs3.", ui.UIName, i); - } - if (ui.UIPower2 == ui.UIPower4) { - app_fatal("SaveItemPower does not support the same affix multiple times on '%s' %d, 2vs4.", ui.UIName, i); - } - if (ui.UIPower2 == ui.UIPower5) { - app_fatal("SaveItemPower does not support the same affix multiple times on '%s' %d, 2vs5.", ui.UIName, i); - } - if (ui.UIPower2 == ui.UIPower6) { - app_fatal("SaveItemPower does not support the same affix multiple times on '%s' %d, 2vs6.", ui.UIName, i); - } - } else { - if (ui.UIPower3 != IPL_INVALID || ui.UIPower4 != IPL_INVALID || ui.UIPower5 != IPL_INVALID || ui.UIPower6 != IPL_INVALID) - app_fatal("Unique item '%s' %d ignores its set affix, because UIPower2 is IPL_INVALID.", ui.UIName, i); - } - if (ui.UIPower3 != IPL_INVALID) { - if (ui.UIPower3 == ui.UIPower4) { - app_fatal("SaveItemPower does not support the same affix multiple times on '%s' %d, 3vs4.", ui.UIName, i); - } - if (ui.UIPower3 == ui.UIPower5) { - app_fatal("SaveItemPower does not support the same affix multiple times on '%s' %d, 3vs5.", ui.UIName, i); - } - if (ui.UIPower3 == ui.UIPower6) { - app_fatal("SaveItemPower does not support the same affix multiple times on '%s' %d, 3vs6.", ui.UIName, i); - } - } else { - if (ui.UIPower4 != IPL_INVALID || ui.UIPower5 != IPL_INVALID || ui.UIPower6 != IPL_INVALID) - app_fatal("Unique item '%s' %d ignores its set affix, because UIPower3 is IPL_INVALID.", ui.UIName, i); - } - if (ui.UIPower4 != IPL_INVALID) { - if (ui.UIPower4 == ui.UIPower5) { - app_fatal("SaveItemPower does not support the same affix multiple times on '%s' %d, 4vs5.", ui.UIName, i); - } - if (ui.UIPower4 == ui.UIPower6) { - app_fatal("SaveItemPower does not support the same affix multiple times on '%s' %d, 4vs6.", ui.UIName, i); - } - } else { - if (ui.UIPower5 != IPL_INVALID || ui.UIPower6 != IPL_INVALID) - app_fatal("Unique item '%s' %d ignores its set affix, because UIPower4 is IPL_INVALID.", ui.UIName, i); - } - if (ui.UIPower5 != IPL_INVALID) { - if (ui.UIPower5 == ui.UIPower6) { - app_fatal("SaveItemPower does not support the same affix multiple times on '%s' %d, 5vs6.", ui.UIName, i); - } - } else { - if (ui.UIPower6 != IPL_INVALID) - app_fatal("Unique item '%s' %d ignores its set affix, because UIPower5 is IPL_INVALID.", ui.UIName, i); - } - if (ui.UIPower1 == IPL_ATTRIBS || ui.UIPower2 == IPL_ATTRIBS || ui.UIPower3 == IPL_ATTRIBS || ui.UIPower4 == IPL_ATTRIBS || ui.UIPower5 == IPL_ATTRIBS || ui.UIPower6 == IPL_ATTRIBS) { - if ((ui.UIPower1 == IPL_STR || ui.UIPower2 == IPL_STR || ui.UIPower3 == IPL_STR || ui.UIPower4 == IPL_STR || ui.UIPower5 == IPL_STR || ui.UIPower6 == IPL_STR) || - (ui.UIPower1 == IPL_MAG || ui.UIPower2 == IPL_MAG || ui.UIPower3 == IPL_MAG || ui.UIPower4 == IPL_MAG || ui.UIPower5 == IPL_MAG || ui.UIPower6 == IPL_MAG) || - (ui.UIPower1 == IPL_DEX || ui.UIPower2 == IPL_DEX || ui.UIPower3 == IPL_DEX || ui.UIPower4 == IPL_DEX || ui.UIPower5 == IPL_DEX || ui.UIPower6 == IPL_DEX) || - (ui.UIPower1 == IPL_VIT || ui.UIPower2 == IPL_VIT || ui.UIPower3 == IPL_VIT || ui.UIPower4 == IPL_VIT || ui.UIPower5 == IPL_VIT || ui.UIPower6 == IPL_VIT)) { - app_fatal("SaveItemPower does not support IPL_ATTRIBS and IPL_STR/IPL_MAG/IPL_DEX/IPL_VIT modifiers at the same time on '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower1 == IPL_ALLRES || ui.UIPower2 == IPL_ALLRES || ui.UIPower3 == IPL_ALLRES || ui.UIPower4 == IPL_ALLRES || ui.UIPower5 == IPL_ALLRES || ui.UIPower6 == IPL_ALLRES) { - if ((ui.UIPower1 == IPL_FIRERES || ui.UIPower2 == IPL_FIRERES || ui.UIPower3 == IPL_FIRERES || ui.UIPower4 == IPL_FIRERES || ui.UIPower5 == IPL_FIRERES || ui.UIPower6 == IPL_FIRERES) || - (ui.UIPower1 == IPL_LIGHTRES || ui.UIPower2 == IPL_LIGHTRES || ui.UIPower3 == IPL_LIGHTRES || ui.UIPower4 == IPL_LIGHTRES || ui.UIPower5 == IPL_LIGHTRES || ui.UIPower6 == IPL_LIGHTRES) || - (ui.UIPower1 == IPL_MAGICRES || ui.UIPower2 == IPL_MAGICRES || ui.UIPower3 == IPL_MAGICRES || ui.UIPower4 == IPL_MAGICRES || ui.UIPower5 == IPL_MAGICRES || ui.UIPower6 == IPL_MAGICRES) || - (ui.UIPower1 == IPL_ACIDRES || ui.UIPower2 == IPL_ACIDRES || ui.UIPower3 == IPL_ACIDRES || ui.UIPower4 == IPL_ACIDRES || ui.UIPower5 == IPL_ACIDRES || ui.UIPower6 == IPL_ACIDRES)) { - app_fatal("SaveItemPower does not support IPL_ALLRES and IPL_FIRERES/IPL_LIGHTRES/IPL_MAGICRES/IPL_ACIDRES modifiers at the same time on '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower1 == IPL_TOHIT || ui.UIPower2 == IPL_TOHIT || ui.UIPower3 == IPL_TOHIT || ui.UIPower4 == IPL_TOHIT || ui.UIPower5 == IPL_TOHIT || ui.UIPower6 == IPL_TOHIT) { - if (ui.UIPower1 == IPL_TOHIT_DAMP || ui.UIPower2 == IPL_TOHIT_DAMP || ui.UIPower3 == IPL_TOHIT_DAMP || ui.UIPower4 == IPL_TOHIT_DAMP || ui.UIPower5 == IPL_TOHIT_DAMP || ui.UIPower6 == IPL_TOHIT_DAMP) { - app_fatal("SaveItemPower does not support IPL_TOHIT and IPL_TOHIT_DAMP modifiers at the same time on '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower1 == IPL_DAMP || ui.UIPower2 == IPL_DAMP || ui.UIPower3 == IPL_DAMP || ui.UIPower4 == IPL_DAMP || ui.UIPower5 == IPL_DAMP || ui.UIPower6 == IPL_DAMP) { - if ((ui.UIPower1 == IPL_TOHIT_DAMP || ui.UIPower2 == IPL_TOHIT_DAMP || ui.UIPower3 == IPL_TOHIT_DAMP || ui.UIPower4 == IPL_TOHIT_DAMP || ui.UIPower5 == IPL_TOHIT_DAMP || ui.UIPower6 == IPL_TOHIT_DAMP) || - (ui.UIPower1 == IPL_CRYSTALLINE || ui.UIPower2 == IPL_CRYSTALLINE || ui.UIPower3 == IPL_CRYSTALLINE || ui.UIPower4 == IPL_CRYSTALLINE || ui.UIPower5 == IPL_CRYSTALLINE || ui.UIPower6 == IPL_CRYSTALLINE)) { - app_fatal("SaveItemPower does not support IPL_DAMP and IPL_TOHIT_DAMP/IPL_CRYSTALLINE modifiers at the same time on '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower1 == IPL_TOHIT_DAMP || ui.UIPower2 == IPL_TOHIT_DAMP || ui.UIPower3 == IPL_TOHIT_DAMP || ui.UIPower4 == IPL_TOHIT_DAMP || ui.UIPower5 == IPL_TOHIT_DAMP || ui.UIPower6 == IPL_TOHIT_DAMP) { - if (ui.UIPower1 == IPL_CRYSTALLINE || ui.UIPower2 == IPL_CRYSTALLINE || ui.UIPower3 == IPL_CRYSTALLINE || ui.UIPower4 == IPL_CRYSTALLINE || ui.UIPower5 == IPL_CRYSTALLINE || ui.UIPower6 == IPL_CRYSTALLINE) { - app_fatal("SaveItemPower does not support IPL_TOHIT_DAMP and IPL_CRYSTALLINE modifiers at the same time on '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower1 == IPL_FASTATTACK) { - if (ui.UIParam1a < 1 || ui.UIParam1b > 4) { - app_fatal("Invalid UIParam1 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower1 == IPL_FASTRECOVER) { - if (ui.UIParam1a < 1 || ui.UIParam1b > 3) { - app_fatal("Invalid UIParam1 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower1 == IPL_FASTCAST) { - if (ui.UIParam1a < 1 || ui.UIParam1b > 3) { - app_fatal("Invalid UIParam1 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower1 == IPL_FASTWALK) { - if (ui.UIParam1a < 1 || ui.UIParam1b > 3) { - app_fatal("Invalid UIParam1 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower1 == IPL_DUR) { - if (ui.UIParam1b > 200) { - app_fatal("Invalid UIParam1 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower2 == IPL_FASTATTACK) { - if (ui.UIParam2a < 1 || ui.UIParam2b > 4) { - app_fatal("Invalid UIParam2 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower2 == IPL_FASTRECOVER) { - if (ui.UIParam2a < 1 || ui.UIParam2a > 3) { - app_fatal("Invalid UIParam2a set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower2 == IPL_FASTCAST) { - if (ui.UIParam2a < 1 || ui.UIParam2b > 3) { - app_fatal("Invalid UIParam2 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower2 == IPL_FASTWALK) { - if (ui.UIParam2a < 1 || ui.UIParam2b > 3) { - app_fatal("Invalid UIParam2 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower2 == IPL_DUR) { - if (ui.UIParam2b > 200) { - app_fatal("Invalid UIParam2 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower3 == IPL_FASTATTACK) { - if (ui.UIParam3a < 1 || ui.UIParam3b > 4) { - app_fatal("Invalid UIParam3 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower3 == IPL_FASTRECOVER) { - if (ui.UIParam3a < 1 || ui.UIParam3b > 3) { - app_fatal("Invalid UIParam3 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower3 == IPL_FASTCAST) { - if (ui.UIParam3a < 1 || ui.UIParam3b > 3) { - app_fatal("Invalid UIParam3 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower3 == IPL_FASTWALK) { - if (ui.UIParam3a < 1 || ui.UIParam3b > 3) { - app_fatal("Invalid UIParam3 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower3 == IPL_DUR) { - if (ui.UIParam3b > 200) { - app_fatal("Invalid UIParam3 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower4 == IPL_FASTATTACK) { - if (ui.UIParam4a < 1 || ui.UIParam4b > 4) { - app_fatal("Invalid UIParam4 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower4 == IPL_FASTRECOVER) { - if (ui.UIParam4a < 1 || ui.UIParam4b > 3) { - app_fatal("Invalid UIParam4 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower4 == IPL_FASTCAST) { - if (ui.UIParam4a < 1 || ui.UIParam4b > 3) { - app_fatal("Invalid UIParam4 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower4 == IPL_FASTWALK) { - if (ui.UIParam4a < 1 || ui.UIParam4b > 3) { - app_fatal("Invalid UIParam4 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower4 == IPL_DUR) { - if (ui.UIParam4b > 200) { - app_fatal("Invalid UIParam4 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower5 == IPL_FASTATTACK) { - if (ui.UIParam5a < 1 || ui.UIParam5b > 4) { - app_fatal("Invalid UIParam5 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower5 == IPL_FASTRECOVER) { - if (ui.UIParam5a < 1 || ui.UIParam5b > 3) { - app_fatal("Invalid UIParam5 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower5 == IPL_FASTCAST) { - if (ui.UIParam5a < 1 || ui.UIParam5b > 3) { - app_fatal("Invalid UIParam5 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower5 == IPL_FASTWALK) { - if (ui.UIParam5a < 1 || ui.UIParam5b > 3) { - app_fatal("Invalid UIParam5 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower5 == IPL_DUR) { - if (ui.UIParam5b > 200) { - app_fatal("Invalid UIParam5 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower6 == IPL_FASTATTACK) { - if (ui.UIParam6a < 1 || ui.UIParam6b > 4) { - app_fatal("Invalid UIParam6 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower6 == IPL_FASTRECOVER) { - if (ui.UIParam6a < 1 || ui.UIParam6b > 3) { - app_fatal("Invalid UIParam6 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower6 == IPL_FASTCAST) { - if (ui.UIParam6a < 1 || ui.UIParam6b > 3) { - app_fatal("Invalid UIParam6 set for '%s' %d.", ui.UIName, i); - } - } - if (ui.UIPower6 == IPL_FASTWALK) { - if (ui.UIParam6a < 1 || ui.UIParam6b > 3) { - app_fatal("Invalid UIParam6 set for '%s' %d.", ui.UIName, i); + for (int n = 1; n <= 6; n++) { + BYTE pow = GetUniqueItemPower(ui, n); + if (pow != IPL_INVALID) { + for (int m = n + 1; m <= 6; m++) { + if (GetUniqueItemPower(ui, m) == pow) + app_fatal("SaveItemPower does not support the same affix multiple times on '%s' %d, %dvs%d.", ui.UIName, i, n, m); + } + } else { + if (n == 1) + app_fatal("Unique item '%s' %d does not have any affix", ui.UIName, i); + for (int m = n + 1; m <= 6; m++) { + if (GetUniqueItemPower(ui, m) != IPL_INVALID) + app_fatal("Unique item '%s' %d ignores its set affix%d, because UIPower%d is IPL_INVALID.", ui.UIName, i); + } } - } - if (ui.UIPower6 == IPL_DUR) { - if (ui.UIParam6b > 200) { - app_fatal("Invalid UIParam6 set for '%s' %d.", ui.UIName, i); + if (pow == IPL_ATTRIBS) { + for (int m = 1; m <= 6; m++) { + pow = GetUniqueItemPower(ui, m); + if (pow == IPL_STR || pow == IPL_MAG || pow == IPL_DEX || pow == IPL_VIT) + app_fatal("SaveItemPower does not support IPL_ATTRIBS and IPL_STR/IPL_MAG/IPL_DEX/IPL_VIT modifiers at the same time on '%s' %d, %dvs%d.", ui.UIName, i, n, m); + } + } else if (pow == IPL_ALLRES) { + for (int m = 1; m <= 6; m++) { + pow = GetUniqueItemPower(ui, m); + if (pow == IPL_FIRERES || pow == IPL_LIGHTRES || pow == IPL_MAGICRES || pow == IPL_ACIDRES) + app_fatal("SaveItemPower does not support IPL_ALLRES and IPL_FIRERES/IPL_LIGHTRES/IPL_MAGICRES/IPL_ACIDRES modifiers at the same time on '%s' %d, %dvs%d.", ui.UIName, i, n, m); + } + } else if (pow == IPL_TOHIT) { + for (int m = 1; m <= 6; m++) { + pow = GetUniqueItemPower(ui, m); + if (pow == IPL_TOHIT_DAMP) + app_fatal("SaveItemPower does not support IPL_TOHIT and IPL_TOHIT_DAMP modifiers at the same time on '%s' %d, %dvs%d.", ui.UIName, i, n, m); + } + } else if (pow == IPL_SETDAM && GetUniqueItemParamA(ui, n) == 0 && GetUniqueItemParamB(ui, n) == 0) { + for (int m = 1; m <= 6; m++) { + pow = GetUniqueItemPower(ui, m); + if (pow == IPL_DAMMOD || pow == IPL_DAMP || pow == IPL_TOHIT_DAMP || pow == IPL_CRYSTALLINE) + app_fatal("SaveItemPower does not support IPL_SETDAM (0) and IPL_DAMMOD/IPL_DAMP/IPL_TOHIT_DAMP/IPL_CRYSTALLINE modifiers at the same time on '%s' %d, %dvs%d.", ui.UIName, i, n, m); + } + } else if (pow == IPL_DAMP || pow == IPL_TOHIT_DAMP || pow == IPL_CRYSTALLINE) { + for (int m = 1; m <= 6; m++) { + pow = GetUniqueItemPower(ui, m); + if (n != m && (pow == IPL_DAMP || pow == IPL_TOHIT_DAMP || pow == IPL_CRYSTALLINE)) + app_fatal("SaveItemPower does not support IPL_DAMP/IPL_TOHIT_DAMP/IPL_CRYSTALLINE modifiers at the same time on '%s' %d, %dvs%d.", ui.UIName, i, n, m); + } + } else if (pow == IPL_SETAC) { + for (int m = 1; m <= 6; m++) { + pow = GetUniqueItemPower(ui, m); + if (pow == IPL_ACMOD) + app_fatal("SaveItemPower does not support IPL_SETAC and IPL_ACMOD modifiers at the same time on '%s' %d, %dvs%d.", ui.UIName, i, n, m); + } + } else if (pow == IPL_FASTATTACK) { + if (GetUniqueItemParamA(ui, n) < 1 || GetUniqueItemParamB(ui, n) > 4) + app_fatal("Invalid UIParam%d set for '%s' %d.", n, ui.UIName, i); + } else if (pow == IPL_FASTRECOVER) { + if (GetUniqueItemParamA(ui, n) < 1 || GetUniqueItemParamB(ui, n) > 3) + app_fatal("Invalid UIParam%d set for '%s' %d.", n, ui.UIName, i); + } else if (pow == IPL_FASTCAST) { + if (GetUniqueItemParamA(ui, n) < 1 || GetUniqueItemParamB(ui, n) > 3) + app_fatal("Invalid UIParam%d set for '%s' %d.", n, ui.UIName, i); + } else if (pow == IPL_FASTWALK) { + if (GetUniqueItemParamA(ui, n) < 1 || GetUniqueItemParamB(ui, n) > 3) + app_fatal("Invalid UIParam%d set for '%s' %d.", n, ui.UIName, i); + } else if (pow == IPL_DUR) { + if (GetUniqueItemParamA(ui, n) <= 0 || GetUniqueItemParamB(ui, n) > 200) + app_fatal("Invalid UIParam%d set for '%s' %d.", n, ui.UIName, i); + } else if ((pow == IPL_STR || pow == IPL_MAG || pow == IPL_DEX) && GetUniqueItemParamA(ui, n) < 0 && HasUniqueItemReq(ui, pow)) { + for (int m = 1; m <= 6; m++) { + BYTE pw = GetUniqueItemPower(ui, m); + if (pow != pw && (pw == IPL_STR || pw == IPL_MAG || pw == IPL_DEX) && GetUniqueItemParamB(ui, m) > 0) { + // str/mag/dex +- modifiers + for (int ii = i + 1; ii < NUM_UITEM; ii++) { + const UniqItemData& oui = UniqueItemList[ii]; + if (!HasUniqueItemReq(oui, pw)) + continue; + for (int o = 1; o <= 6; o++) { + if (GetUniqueItemPower(oui, o) == pow && GetUniqueItemParamB(ui, o) > 0) { + for (int p = 1; p <= 6; p++) { + if (GetUniqueItemPower(oui, p) == pw && GetUniqueItemParamA(ui, p) < 0) { + app_fatal("Unique items '%s' %d and '%s' %d might help each other to equip.", ui.UIName, i, oui.UIName, ii); + } + } + break; + } + } + } + } + } } } int n = 0; @@ -1130,6 +1036,19 @@ void ValidateData() #endif // DEBUG_DATA assert(itemfiledata[ItemCAnimTbl[ICURS_MAGIC_ROCK]].iAnimLen == 10); // required by ProcessItems #ifdef DEBUG_DATA + for (i = 0; i < NUM_IFILE; i++) { + const ItemFileData& id = itemfiledata[i]; + if (id.idSFX != SFX_NONE) { + if (id.idSFX >= NUM_SFXS) + app_fatal("Invalid idSFX %d for %s (%d)", id.idSFX, id.ifName, i); + if ((id.iAnimLen >> 1) < 2) + app_fatal("Too short iAnimLen %d for %s (%d)", id.iAnimLen, id.ifName, i); // required by ProcessItems + } + if (id.iiSFX != SFX_NONE) { + if (id.iiSFX >= NUM_SFXS) + app_fatal("Invalid iiSFX %d for %s (%d)", id.iiSFX, id.ifName, i); + } + } // objects for (i = 0; i < NUM_OFILE_TYPES; i++) { const ObjFileData& od = objfiledata[i]; @@ -1299,11 +1218,16 @@ void ValidateData() #endif if (md.mProc == NULL) app_fatal("Missile %d has no valid mProc.", i); - if (md.mProc == MI_Misexp || md.mProc == MI_MiniExp) { + if (md.mProc == MI_Misexp) { for (int j = 0; j < misfiledata[md.mFileNum].mfAnimFAmt; j++) { assert(misfiledata[md.mFileNum].mfAnimLen[j] < 16 /* lengthof(ExpLight) */); } } + if (md.mProc == MI_MiniExp) { + for (int j = 0; j < misfiledata[md.mFileNum].mfAnimFAmt; j++) { + assert(misfiledata[md.mFileNum].mfAnimLen[j] < 11 /* lengthof(ExpLight) */); + } + } if (md.mDrawFlag) { if (md.mFileNum == MFILE_NONE && i != MIS_RHINO && i != MIS_CHARGE) app_fatal("Missile %d is drawn, but has no valid mFileNum.", i); From 1a5dc6e4062ed3cdacffbc0ceef5b835d441c57b Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 18 Aug 2024 14:00:27 +0200 Subject: [PATCH 447/596] adjust struct-alignments on x64-systems --- Source/misdat.cpp | 230 +++++++++++++++++++++++----------------------- structs.h | 10 +- 2 files changed, 120 insertions(+), 120 deletions(-) diff --git a/Source/misdat.cpp b/Source/misdat.cpp index 7f124bddc29..769b80f3817 100644 --- a/Source/misdat.cpp +++ b/Source/misdat.cpp @@ -12,122 +12,122 @@ DEVILUTION_BEGIN_NAMESPACE const MissileData missiledata[] = { // clang-format off // mAddProc, mProc, mdFlags, mResist, mFileNum, mDrawFlag, mlSFX, miSFX, mlSFXCnt, miSFXCnt, -/*MIS_ARROW*/ { &AddArrow, &MI_Arrow, MIF_ARROW | MIF_SHROUD | MIF_LEAD, MISR_PUNCTURE, MFILE_ARROWS, TRUE, PS_BFIRE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_PBARROW*/ { &AddArrow, &MI_Arrow, MIF_ARROW | MIF_SHROUD | MIF_LEAD, MISR_PUNCTURE, MFILE_ARROWS, TRUE, PS_BFIRE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_ASARROW*/ { &AddArrow, &MI_AsArrow, MIF_ARROW | MIF_LEAD, MISR_PUNCTURE, MFILE_ARROWS, TRUE, PS_BFIRE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_MLARROW*/ { &AddArrow, &MI_Arrow, MIF_ARROW | MIF_SHROUD | MIF_LEAD, MISR_PUNCTURE, MFILE_ARROWS, TRUE, PS_BFIRE, SFX_NONE, 1, 1, ALIGN }, // miSFX was IS_STING -/*MIS_PCARROW*/ { &AddArrow, &MI_Arrow, MIF_ARROW | MIF_SHROUD | MIF_LEAD, MISR_PUNCTURE, MFILE_ARROWS, TRUE, PS_BFIRE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_FIREBOLT*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD | MIF_LEAD, MISR_FIRE, MFILE_FIREBA, TRUE, LS_FBOLT1, LS_FIRIMP2, 1, 1, ALIGN }, -/*MIS_FIREBALL*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD | MIF_LEAD, MISR_FIRE, MFILE_FIREBA, TRUE, LS_FBOLT1, LS_FIRIMP2, 1, 1, ALIGN }, -/*MIS_HBOLT*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD | MIF_LEAD, MISR_ACID, MFILE_HOLY, TRUE, LS_HOLYBOLT, LS_ELECIMP1, 1, 1, ALIGN }, -/*MIS_FLARE*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD | MIF_LEAD, MISR_MAGIC, MFILE_FLARE, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_SNOWWICH*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD, MISR_MAGIC, MFILE_SCUBMISB, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_HLSPWN*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD, MISR_MAGIC, MFILE_SCUBMISD, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_SOLBRNR*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD, MISR_MAGIC, MFILE_SCUBMISC, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_MAGMABALL*/ { &AddMagmaball, &MI_Firebolt, MIF_SHROUD, MISR_FIRE, MFILE_MAGBALL, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_ACID*/ { &AddAcid, &MI_Acid, MIF_SHROUD, MISR_ACID, MFILE_ACIDBF, TRUE, LS_ACID, SFX_NONE, 2, 1, ALIGN }, -/*MIS_ACIDPUD*/ { &AddAcidpud, &MI_Acidpud, MIF_NOBLOCK | MIF_AREA | MIF_DOT, MISR_ACID, MFILE_ACIDPUD, TRUE, LS_PUDDLE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_EXACIDP*/ { &AddMisexp, &MI_Acidsplat, 0, MISR_ACID, MFILE_ACIDSPLA, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_EXFIRE*/ { &AddMisexp, &MI_MiniExp, 0, MISR_NONE, MFILE_MAGBLOS, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_EXFBALL*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_BIGEXP, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_EXLGHT*/ { &AddMisexp, &MI_MiniExp, 0, MISR_NONE, MFILE_MINILTNG, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_EXMAGIC*/ { &AddMisexp, &MI_MiniExp, 0, MISR_NONE, MFILE_MAGICEXP, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_EXACID*/ { &AddMisexp, &MI_MiniExp, 0, MISR_NONE, MFILE_GREENEXP, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_EXHOLY*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_HOLYEXPL, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_EXFLARE*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_FLAREEXP, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_EXSNOWWICH*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_SCBSEXPB, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_EXHLSPWN*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_SCBSEXPD, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_EXSOLBRNR*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_SCBSEXPC, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_POISON*/ { &AddPoison, &MI_Poison, MIF_SHROUD | MIF_NOBLOCK | MIF_AREA | MIF_DOT, MISR_MAGIC, MFILE_MAGICEXP, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_WIND*/ { &AddWind, &MI_Wind, MIF_SHROUD | MIF_NOBLOCK | MIF_DOT | MIF_LEAD, MISR_MAGIC, MFILE_WIND, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_LIGHTBALL*/ { &AddLightball, &MI_Lightball, MIF_SHROUD | MIF_DOT | MIF_LEAD, MISR_LIGHTNING, MFILE_LGHNING, TRUE, LS_LNING1, LS_ELECIMP1, 1, 1, ALIGN }, -/*MIS_LIGHTNINGC*/ { &AddLightningC, &MI_LightningC, MIF_SHROUD, MISR_NONE, MFILE_NONE, FALSE, LS_LNING1, SFX_NONE, 1, 1, ALIGN }, -/*MIS_LIGHTNING*/ { &AddLightning, &MI_Lightning, MIF_SHROUD | MIF_NOBLOCK | MIF_DOT | MIF_LEAD, MISR_LIGHTNING, MFILE_LGHNING, TRUE, SFX_NONE, LS_ELECIMP1, 1, 1, ALIGN }, -/*MIS_LIGHTNINGC2*/ { &AddLightningC, &MI_LightningC, MIF_SHROUD, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_LIGHTNING2*/ { &AddLightning, &MI_Lightning, MIF_SHROUD | MIF_NOBLOCK | MIF_DOT, MISR_LIGHTNING, MFILE_THINLGHT, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_BLOODBOILC*/ { &AddBloodBoilC, &MI_BloodBoilC, 0, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_BLOODBOIL*/ { &AddBloodBoil, &MI_BloodBoil, 0, MISR_MAGIC, MFILE_BLODBURS, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_SWAMPC*/ { &AddBloodBoilC, &MI_SwampC, 0, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_SWAMP*/ { &AddMisexp, &MI_LongExp, 0, MISR_NONE, MFILE_SWAMP, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_TOWN*/ { &AddTown, &MI_Portal, 0, MISR_NONE, MFILE_PORTAL, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_RPORTAL*/ { &AddPortal, &MI_Portal, 0, MISR_NONE, MFILE_RPORTAL, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_FLASH*/ { &AddFlash, &MI_Flash, MIF_NOBLOCK | MIF_AREA | MIF_DOT, MISR_MAGIC, MFILE_BLUEXFR, TRUE, LS_NOVA, SFX_NONE, 1, 1, ALIGN }, // miSFX was LS_ELECIMP1 -/*MIS_FLASH2*/ { &AddFlash2, &MI_Flash2, 0, MISR_NONE, MFILE_BLUEXBK, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_CHAIN*/ { &AddChain, &MI_Chain, MIF_SHROUD | MIF_NOBLOCK | MIF_LEAD, MISR_LIGHTNING, MFILE_LGHNING, TRUE, LS_LNING1, LS_ELECIMP1, 1, 1, ALIGN }, -/*MIS_BLODSTAR*/// { NULL, NULL, 0, MISR_NONE, MFILE_BLOOD, TRUE, LS_BLODSTAR, LS_BLSIMPT, 1, 1, ALIGN }, -/*MIS_BONE*/// { NULL, NULL, 0, MISR_NONE, MFILE_BONE, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_METLHIT*/// { NULL, NULL, 0, MISR_NONE, MFILE_METLHIT, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_RHINO*/ { &AddRhino, &MI_Rhino, 0, MISR_NONE, MFILE_NONE, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_CHARGE*/ { &AddCharge, &MI_Charge, 0, MISR_NONE, MFILE_NONE, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_TELEPORT*/ { &AddTeleport, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, LS_ELEMENTL, SFX_NONE, 1, 1, ALIGN }, -/*MIS_RNDTELEPORT*/ { &AddRndTeleport, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, LS_TELEPORT, SFX_NONE, 1, 1, ALIGN }, -/*MIS_FARROW*/// { NULL, NULL, 0, MISR_FIRE, MFILE_FARROW, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_DOOMSERP*/// { NULL, NULL, 0, MISR_MAGIC, MFILE_DOOM, FALSE, LS_DSERP, SFX_NONE, 1, 1, ALIGN }, -/*MIS_STONE*/ { &AddStone, &MI_Stone, 0, MISR_NONE, MFILE_NONE, FALSE, LS_SCURIMP, SFX_NONE, 1, 1, ALIGN }, -/*MIS_SHROUD*/ { &AddShroud, &MI_Shroud, MIF_SHROUD, MISR_NONE, MFILE_SHROUD, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_INVISIBL*/// { NULL, NULL, 0, MISR_NONE, MFILE_NONE, FALSE, LS_INVISIBL, SFX_NONE, 1, 1, ALIGN }, -/*MIS_GUARDIAN*/ { &AddGuardian, &MI_Guardian, MIF_SHROUD, MISR_NONE, MFILE_GUARD, TRUE, LS_GUARD, SFX_NONE, 1, 1, ALIGN }, // miSFX was LS_GUARDLAN -/*MIS_GOLEM*/ { &AddGolem, &MI_Dummy, MIF_AREA, MISR_NONE, MFILE_NONE, FALSE, LS_GOLUM, SFX_NONE, 1, 1, ALIGN }, -/*MIS_ETHEREALIZE*///{ NULL, NULL, 0, MISR_NONE, MFILE_ETHRSHLD, TRUE, LS_ETHEREAL, SFX_NONE, 1, 1, ALIGN }, -/*MIS_BLEED*/ { &AddBleed, &MI_Bleed, MIF_NOBLOCK | MIF_AREA | MIF_DOT, MISR_NONE, MFILE_BLODBURS, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_EXAPOCA*/// { &AddApocaExp, &MI_ApocaExp, 0, MISR_NONE, MFILE_NEWEXP, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_FIREWALLC*/ { &AddWallC, &MI_WallC, MIF_SHROUD, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_FIREWALL*/ { &AddFirewall, &MI_Firewall, MIF_SHROUD | MIF_NOBLOCK | MIF_AREA | MIF_DOT, MISR_FIRE, MFILE_FIREWAL, TRUE, LS_WALLLOOP, SFX_NONE, 1, 1, ALIGN }, // miSFX was LS_FIRIMP2 -/*MIS_FIREWAVEC*/ { &AddFireWaveC, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, LS_FLAMWAVE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_FIREWAVE*/ { &AddFireWave, &MI_FireWave, MIF_SHROUD | MIF_AREA | MIF_DOT | MIF_LEAD, MISR_FIRE, MFILE_FIREWAL, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_METEOR*/ { &AddMeteor, &MI_Meteor, 0, MISR_BLUNT, MFILE_SHATTER1, TRUE, LS_WALLLOOP, SFX_NONE, 1, 1, ALIGN }, -/*MIS_LIGHTNOVAC*/ { &AddNovaC, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, LS_NOVA, SFX_NONE, 1, 1, ALIGN }, -/*MIS_APOCAC*/// { &AddApocaC, &MI_ApocaC, 0, MISR_NONE, MFILE_NONE, FALSE, LS_APOC, SFX_NONE, 1, 1, ALIGN }, -/*MIS_HEAL*/ { &AddHeal, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_HEALOTHER*/ { &AddHealOther, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_RESURRECT*/ { &AddResurrect, &MI_Resurrect, 0, MISR_NONE, MFILE_RESSUR1, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, // miSFX was LS_RESUR -/*MIS_ATTRACT*/ { &AddAttract, &MI_Resurrect, 0, MISR_NONE, MFILE_RESSUR1, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_TELEKINESIS*/ { &AddTelekinesis, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, LS_ETHEREAL, SFX_NONE, 1, 1, ALIGN }, -/*MIS_LARROW*/// { NULL, NULL, 0, MISR_LIGHTNING, MFILE_LARROW, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_OPITEM*/ { &AddOpItem, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_REPAIR*/ { &AddOpItem, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, IS_REPAIR, SFX_NONE, 1, 1, ALIGN }, -/*MIS_DISARM*/ { &AddDisarm, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, LS_TRAPDIS, SFX_NONE, 1, 1, ALIGN }, -/*MIS_INFERNOC*/ { &AddInfernoC, &MI_InfernoC, MIF_SHROUD, MISR_NONE, MFILE_NONE, FALSE, LS_SPOUTSTR, SFX_NONE, 1, 1, ALIGN }, -/*MIS_INFERNO*/ { &AddInferno, &MI_Inferno, MIF_SHROUD | MIF_NOBLOCK | MIF_AREA | MIF_DOT, MISR_FIRE, MFILE_INFERNO, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_FIRETRAP*/// { &AddFireTrap, &MI_FireTrap, MIF_AREA | MIF_DOT, MISR_FIRE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_BARRELEX*/ { &AddBarrelExp, &MI_Dummy, 0, MISR_FIRE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_FIREMAN*/// { &AddFireman, &MI_Fireman, 0, MISR_NONE, MFILE_NONE, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_KRULL*/// { &AddKrull, &MI_Krull, 0, MISR_FIRE, MFILE_KRULL, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_CBOLTC*/ { &AddCboltC, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, LS_CBOLT, SFX_NONE, 1, 1, ALIGN }, -/*MIS_CBOLT*/ { &AddCbolt, &MI_Cbolt, MIF_SHROUD, MISR_LIGHTNING, MFILE_MINILTNG, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_ELEMENTAL*/ { &AddElemental, &MI_Elemental, MIF_SHROUD | MIF_LEAD, MISR_FIRE, MFILE_FIRERUN, TRUE, LS_ELEMENTL, SFX_NONE, 1, 1, ALIGN }, -/*MIS_BONESPIRIT*///{ &AddBoneSpirit, &MI_Bonespirit, 0, MISR_MAGIC, MFILE_SKLBALL, TRUE, LS_BONESP, LS_BSIMPCT, 1, 1, ALIGN }, -/*MIS_APOCAC2*/ { &AddApocaC2, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_EXAPOCA2*/ { &AddMisexp, &MI_LongExp, 0, MISR_NONE, MFILE_FIREPLAR, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_MANASHIELD*/ { &AddManashield, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, LS_MSHIELD, SFX_NONE, 1, 1, ALIGN }, -/*MIS_INFRA*/ { &AddInfra, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, LS_INFRAVIS, SFX_NONE, 1, 1, ALIGN }, -/*MIS_RAGE*/ { &AddRage, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, +/*MIS_ARROW*/ { &AddArrow, &MI_Arrow, MIF_ARROW | MIF_SHROUD | MIF_LEAD, MISR_PUNCTURE, MFILE_ARROWS, TRUE, PS_BFIRE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_PBARROW*/ { &AddArrow, &MI_Arrow, MIF_ARROW | MIF_SHROUD | MIF_LEAD, MISR_PUNCTURE, MFILE_ARROWS, TRUE, PS_BFIRE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_ASARROW*/ { &AddArrow, &MI_AsArrow, MIF_ARROW | MIF_LEAD, MISR_PUNCTURE, MFILE_ARROWS, TRUE, PS_BFIRE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_MLARROW*/ { &AddArrow, &MI_Arrow, MIF_ARROW | MIF_SHROUD | MIF_LEAD, MISR_PUNCTURE, MFILE_ARROWS, TRUE, PS_BFIRE, SFX_NONE, 1, 1, ALIGN32 }, // miSFX was IS_STING +/*MIS_PCARROW*/ { &AddArrow, &MI_Arrow, MIF_ARROW | MIF_SHROUD | MIF_LEAD, MISR_PUNCTURE, MFILE_ARROWS, TRUE, PS_BFIRE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_FIREBOLT*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD | MIF_LEAD, MISR_FIRE, MFILE_FIREBA, TRUE, LS_FBOLT1, LS_FIRIMP2, 1, 1, ALIGN32 }, +/*MIS_FIREBALL*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD | MIF_LEAD, MISR_FIRE, MFILE_FIREBA, TRUE, LS_FBOLT1, LS_FIRIMP2, 1, 1, ALIGN32 }, +/*MIS_HBOLT*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD | MIF_LEAD, MISR_ACID, MFILE_HOLY, TRUE, LS_HOLYBOLT, LS_ELECIMP1, 1, 1, ALIGN32 }, +/*MIS_FLARE*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD | MIF_LEAD, MISR_MAGIC, MFILE_FLARE, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_SNOWWICH*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD, MISR_MAGIC, MFILE_SCUBMISB, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_HLSPWN*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD, MISR_MAGIC, MFILE_SCUBMISD, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_SOLBRNR*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD, MISR_MAGIC, MFILE_SCUBMISC, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_MAGMABALL*/ { &AddMagmaball, &MI_Firebolt, MIF_SHROUD, MISR_FIRE, MFILE_MAGBALL, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_ACID*/ { &AddAcid, &MI_Acid, MIF_SHROUD, MISR_ACID, MFILE_ACIDBF, TRUE, LS_ACID, SFX_NONE, 2, 1, ALIGN32 }, +/*MIS_ACIDPUD*/ { &AddAcidpud, &MI_Acidpud, MIF_NOBLOCK | MIF_AREA | MIF_DOT, MISR_ACID, MFILE_ACIDPUD, TRUE, LS_PUDDLE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_EXACIDP*/ { &AddMisexp, &MI_Acidsplat, 0, MISR_ACID, MFILE_ACIDSPLA, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_EXFIRE*/ { &AddMisexp, &MI_MiniExp, 0, MISR_NONE, MFILE_MAGBLOS, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_EXFBALL*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_BIGEXP, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_EXLGHT*/ { &AddMisexp, &MI_MiniExp, 0, MISR_NONE, MFILE_MINILTNG, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_EXMAGIC*/ { &AddMisexp, &MI_MiniExp, 0, MISR_NONE, MFILE_MAGICEXP, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_EXACID*/ { &AddMisexp, &MI_MiniExp, 0, MISR_NONE, MFILE_GREENEXP, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_EXHOLY*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_HOLYEXPL, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_EXFLARE*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_FLAREEXP, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_EXSNOWWICH*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_SCBSEXPB, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_EXHLSPWN*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_SCBSEXPD, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_EXSOLBRNR*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_SCBSEXPC, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_POISON*/ { &AddPoison, &MI_Poison, MIF_SHROUD | MIF_NOBLOCK | MIF_AREA | MIF_DOT, MISR_MAGIC, MFILE_MAGICEXP, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_WIND*/ { &AddWind, &MI_Wind, MIF_SHROUD | MIF_NOBLOCK | MIF_DOT | MIF_LEAD, MISR_MAGIC, MFILE_WIND, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_LIGHTBALL*/ { &AddLightball, &MI_Lightball, MIF_SHROUD | MIF_DOT | MIF_LEAD, MISR_LIGHTNING, MFILE_LGHNING, TRUE, LS_LNING1, LS_ELECIMP1, 1, 1, ALIGN32 }, +/*MIS_LIGHTNINGC*/ { &AddLightningC, &MI_LightningC, MIF_SHROUD, MISR_NONE, MFILE_NONE, FALSE, LS_LNING1, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_LIGHTNING*/ { &AddLightning, &MI_Lightning, MIF_SHROUD | MIF_NOBLOCK | MIF_DOT | MIF_LEAD, MISR_LIGHTNING, MFILE_LGHNING, TRUE, SFX_NONE, LS_ELECIMP1, 1, 1, ALIGN32 }, +/*MIS_LIGHTNINGC2*/ { &AddLightningC, &MI_LightningC, MIF_SHROUD, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_LIGHTNING2*/ { &AddLightning, &MI_Lightning, MIF_SHROUD | MIF_NOBLOCK | MIF_DOT, MISR_LIGHTNING, MFILE_THINLGHT, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_BLOODBOILC*/ { &AddBloodBoilC, &MI_BloodBoilC, 0, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_BLOODBOIL*/ { &AddBloodBoil, &MI_BloodBoil, 0, MISR_MAGIC, MFILE_BLODBURS, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_SWAMPC*/ { &AddBloodBoilC, &MI_SwampC, 0, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_SWAMP*/ { &AddMisexp, &MI_LongExp, 0, MISR_NONE, MFILE_SWAMP, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_TOWN*/ { &AddTown, &MI_Portal, 0, MISR_NONE, MFILE_PORTAL, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_RPORTAL*/ { &AddPortal, &MI_Portal, 0, MISR_NONE, MFILE_RPORTAL, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_FLASH*/ { &AddFlash, &MI_Flash, MIF_NOBLOCK | MIF_AREA | MIF_DOT, MISR_MAGIC, MFILE_BLUEXFR, TRUE, LS_NOVA, SFX_NONE, 1, 1, ALIGN32 }, // miSFX was LS_ELECIMP1 +/*MIS_FLASH2*/ { &AddFlash2, &MI_Flash2, 0, MISR_NONE, MFILE_BLUEXBK, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_CHAIN*/ { &AddChain, &MI_Chain, MIF_SHROUD | MIF_NOBLOCK | MIF_LEAD, MISR_LIGHTNING, MFILE_LGHNING, TRUE, LS_LNING1, LS_ELECIMP1, 1, 1, ALIGN32 }, +/*MIS_BLODSTAR*/// { NULL, NULL, 0, MISR_NONE, MFILE_BLOOD, TRUE, LS_BLODSTAR, LS_BLSIMPT, 1, 1, ALIGN32 }, +/*MIS_BONE*/// { NULL, NULL, 0, MISR_NONE, MFILE_BONE, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_METLHIT*/// { NULL, NULL, 0, MISR_NONE, MFILE_METLHIT, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_RHINO*/ { &AddRhino, &MI_Rhino, 0, MISR_NONE, MFILE_NONE, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_CHARGE*/ { &AddCharge, &MI_Charge, 0, MISR_NONE, MFILE_NONE, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_TELEPORT*/ { &AddTeleport, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, LS_ELEMENTL, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_RNDTELEPORT*/ { &AddRndTeleport, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, LS_TELEPORT, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_FARROW*/// { NULL, NULL, 0, MISR_FIRE, MFILE_FARROW, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_DOOMSERP*/// { NULL, NULL, 0, MISR_MAGIC, MFILE_DOOM, FALSE, LS_DSERP, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_STONE*/ { &AddStone, &MI_Stone, 0, MISR_NONE, MFILE_NONE, FALSE, LS_SCURIMP, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_SHROUD*/ { &AddShroud, &MI_Shroud, MIF_SHROUD, MISR_NONE, MFILE_SHROUD, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_INVISIBL*/// { NULL, NULL, 0, MISR_NONE, MFILE_NONE, FALSE, LS_INVISIBL, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_GUARDIAN*/ { &AddGuardian, &MI_Guardian, MIF_SHROUD, MISR_NONE, MFILE_GUARD, TRUE, LS_GUARD, SFX_NONE, 1, 1, ALIGN32 }, // miSFX was LS_GUARDLAN +/*MIS_GOLEM*/ { &AddGolem, &MI_Dummy, MIF_AREA, MISR_NONE, MFILE_NONE, FALSE, LS_GOLUM, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_ETHEREALIZE*///{ NULL, NULL, 0, MISR_NONE, MFILE_ETHRSHLD, TRUE, LS_ETHEREAL, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_BLEED*/ { &AddBleed, &MI_Bleed, MIF_NOBLOCK | MIF_AREA | MIF_DOT, MISR_NONE, MFILE_BLODBURS, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_EXAPOCA*/// { &AddApocaExp, &MI_ApocaExp, 0, MISR_NONE, MFILE_NEWEXP, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_FIREWALLC*/ { &AddWallC, &MI_WallC, MIF_SHROUD, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_FIREWALL*/ { &AddFirewall, &MI_Firewall, MIF_SHROUD | MIF_NOBLOCK | MIF_AREA | MIF_DOT, MISR_FIRE, MFILE_FIREWAL, TRUE, LS_WALLLOOP, SFX_NONE, 1, 1, ALIGN32 }, // miSFX was LS_FIRIMP2 +/*MIS_FIREWAVEC*/ { &AddFireWaveC, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, LS_FLAMWAVE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_FIREWAVE*/ { &AddFireWave, &MI_FireWave, MIF_SHROUD | MIF_AREA | MIF_DOT | MIF_LEAD, MISR_FIRE, MFILE_FIREWAL, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_METEOR*/ { &AddMeteor, &MI_Meteor, 0, MISR_BLUNT, MFILE_SHATTER1, TRUE, LS_WALLLOOP, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_LIGHTNOVAC*/ { &AddNovaC, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, LS_NOVA, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_APOCAC*/// { &AddApocaC, &MI_ApocaC, 0, MISR_NONE, MFILE_NONE, FALSE, LS_APOC, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_HEAL*/ { &AddHeal, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_HEALOTHER*/ { &AddHealOther, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_RESURRECT*/ { &AddResurrect, &MI_Resurrect, 0, MISR_NONE, MFILE_RESSUR1, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, // miSFX was LS_RESUR +/*MIS_ATTRACT*/ { &AddAttract, &MI_Resurrect, 0, MISR_NONE, MFILE_RESSUR1, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_TELEKINESIS*/ { &AddTelekinesis, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, LS_ETHEREAL, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_LARROW*/// { NULL, NULL, 0, MISR_LIGHTNING, MFILE_LARROW, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_OPITEM*/ { &AddOpItem, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_REPAIR*/ { &AddOpItem, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, IS_REPAIR, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_DISARM*/ { &AddDisarm, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, LS_TRAPDIS, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_INFERNOC*/ { &AddInfernoC, &MI_InfernoC, MIF_SHROUD, MISR_NONE, MFILE_NONE, FALSE, LS_SPOUTSTR, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_INFERNO*/ { &AddInferno, &MI_Inferno, MIF_SHROUD | MIF_NOBLOCK | MIF_AREA | MIF_DOT, MISR_FIRE, MFILE_INFERNO, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_FIRETRAP*/// { &AddFireTrap, &MI_FireTrap, MIF_AREA | MIF_DOT, MISR_FIRE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_BARRELEX*/ { &AddBarrelExp, &MI_Dummy, 0, MISR_FIRE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_FIREMAN*/// { &AddFireman, &MI_Fireman, 0, MISR_NONE, MFILE_NONE, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_KRULL*/// { &AddKrull, &MI_Krull, 0, MISR_FIRE, MFILE_KRULL, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_CBOLTC*/ { &AddCboltC, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, LS_CBOLT, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_CBOLT*/ { &AddCbolt, &MI_Cbolt, MIF_SHROUD, MISR_LIGHTNING, MFILE_MINILTNG, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_ELEMENTAL*/ { &AddElemental, &MI_Elemental, MIF_SHROUD | MIF_LEAD, MISR_FIRE, MFILE_FIRERUN, TRUE, LS_ELEMENTL, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_BONESPIRIT*///{ &AddBoneSpirit, &MI_Bonespirit, 0, MISR_MAGIC, MFILE_SKLBALL, TRUE, LS_BONESP, LS_BSIMPCT, 1, 1, ALIGN32 }, +/*MIS_APOCAC2*/ { &AddApocaC2, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_EXAPOCA2*/ { &AddMisexp, &MI_LongExp, 0, MISR_NONE, MFILE_FIREPLAR, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_MANASHIELD*/ { &AddManashield, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, LS_MSHIELD, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_INFRA*/ { &AddInfra, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, LS_INFRAVIS, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_RAGE*/ { &AddRage, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, #ifdef HELLFIRE -/*MIS_LIGHTWALLC*///{ &AddWallC, &MI_WallC, 0, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_LIGHTWALL*/// { &AddLightwall, &MI_Lightwall, MIF_NOBLOCK | MIF_AREA | MIF_DOT, MISR_LIGHTNING, MFILE_LGHNING, TRUE, LS_LMAG, LS_ELECIMP1, 1, 1, ALIGN }, -/*MIS_FIRENOVAC*/// { &AddNovaC, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, LS_FBOLT1, SFX_NONE, 1, 1, ALIGN }, -/*MIS_FIREBALL2*/// { &AddFireball2, &MI_Fireball, 0, MISR_FIRE, MFILE_FIREBA, TRUE, IS_FBALLBOW, LS_FIRIMP2, 1, 1, ALIGN }, -/*MIS_REFLECT*/// { &AddReflection, &MI_Reflect, 0, MISR_NONE, MFILE_REFLECT, TRUE, LS_MSHIELD, SFX_NONE, 1, 1, ALIGN }, -/*MIS_FIRERING*/ { &AddRingC, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_MANATRAP*/// { &AddManaTrap, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, IS_CAST7, SFX_NONE, 1, 1, ALIGN }, -/*MIS_LIGHTRING*/// { &AddRingC, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_RUNEFIRE*/ { &AddFireRune, &MI_Rune, 0, MISR_NONE, MFILE_RGLOWS1, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_RUNELIGHT*/ { &AddLightRune, &MI_Rune, 0, MISR_NONE, MFILE_RGLOWS1, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_RUNENOVA*/ { &AddNovaRune, &MI_Rune, 0, MISR_NONE, MFILE_RGLOWS1, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_RUNEWAVE*/ { &AddWaveRune, &MI_Rune, 0, MISR_NONE, MFILE_RGLOWS1, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_RUNESTONE*/ { &AddStoneRune, &MI_Rune, 0, MISR_NONE, MFILE_RGLOWS1, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_FIREEXP*/ { &AddFireexp, &MI_Misexp, 0, MISR_FIRE, MFILE_BIGEXP, TRUE, LS_FLAMWAVE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_HORKDMN*/ { &AddHorkSpawn, &MI_HorkSpawn, MIF_SHROUD, MISR_NONE, MFILE_SPAWNS, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_PSYCHORB*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD, MISR_MAGIC, MFILE_MS_ORA, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_LICH*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD, MISR_MAGIC, MFILE_MS_ORA_A, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_BONEDEMON*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD, MISR_MAGIC, MFILE_MS_ORA_B, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_ARCHLICH*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD, MISR_MAGIC, MFILE_MS_YEB_A, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_NECROMORB*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD, MISR_MAGIC, MFILE_MS_REB_B, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN }, -/*MIS_EXPSYCHORB*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_EXORA1, TRUE, LS_FIRIMP2, SFX_NONE, 1, 1, ALIGN }, -/*MIS_EXLICH*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_EXORA1_A, TRUE, LS_FIRIMP2, SFX_NONE, 1, 1, ALIGN }, -/*MIS_EXBONEDEMON*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_EXORA1_B, TRUE, LS_FIRIMP2, SFX_NONE, 1, 1, ALIGN }, -/*MIS_EXARCHLICH*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_EXYEL2_A, TRUE, LS_FIRIMP2, SFX_NONE, 1, 1, ALIGN }, -/*MIS_EXNECROMORB*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_EXYEL2_B, TRUE, LS_FIRIMP2, SFX_NONE, 1, 1, ALIGN }, +/*MIS_LIGHTWALLC*///{ &AddWallC, &MI_WallC, 0, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_LIGHTWALL*/// { &AddLightwall, &MI_Lightwall, MIF_NOBLOCK | MIF_AREA | MIF_DOT, MISR_LIGHTNING, MFILE_LGHNING, TRUE, LS_LMAG, LS_ELECIMP1, 1, 1, ALIGN32 }, +/*MIS_FIRENOVAC*/// { &AddNovaC, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, LS_FBOLT1, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_FIREBALL2*/// { &AddFireball2, &MI_Fireball, 0, MISR_FIRE, MFILE_FIREBA, TRUE, IS_FBALLBOW, LS_FIRIMP2, 1, 1, ALIGN32 }, +/*MIS_REFLECT*/// { &AddReflection, &MI_Reflect, 0, MISR_NONE, MFILE_REFLECT, TRUE, LS_MSHIELD, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_FIRERING*/ { &AddRingC, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_MANATRAP*/// { &AddManaTrap, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, IS_CAST7, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_LIGHTRING*/// { &AddRingC, &MI_Dummy, 0, MISR_NONE, MFILE_NONE, FALSE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_RUNEFIRE*/ { &AddFireRune, &MI_Rune, 0, MISR_NONE, MFILE_RGLOWS1, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_RUNELIGHT*/ { &AddLightRune, &MI_Rune, 0, MISR_NONE, MFILE_RGLOWS1, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_RUNENOVA*/ { &AddNovaRune, &MI_Rune, 0, MISR_NONE, MFILE_RGLOWS1, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_RUNEWAVE*/ { &AddWaveRune, &MI_Rune, 0, MISR_NONE, MFILE_RGLOWS1, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_RUNESTONE*/ { &AddStoneRune, &MI_Rune, 0, MISR_NONE, MFILE_RGLOWS1, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_FIREEXP*/ { &AddFireexp, &MI_Misexp, 0, MISR_FIRE, MFILE_BIGEXP, TRUE, LS_FLAMWAVE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_HORKDMN*/ { &AddHorkSpawn, &MI_HorkSpawn, MIF_SHROUD, MISR_NONE, MFILE_SPAWNS, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_PSYCHORB*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD, MISR_MAGIC, MFILE_MS_ORA, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_LICH*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD, MISR_MAGIC, MFILE_MS_ORA_A, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_BONEDEMON*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD, MISR_MAGIC, MFILE_MS_ORA_B, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_ARCHLICH*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD, MISR_MAGIC, MFILE_MS_YEB_A, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_NECROMORB*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD, MISR_MAGIC, MFILE_MS_REB_B, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_EXPSYCHORB*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_EXORA1, TRUE, LS_FIRIMP2, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_EXLICH*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_EXORA1_A, TRUE, LS_FIRIMP2, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_EXBONEDEMON*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_EXORA1_B, TRUE, LS_FIRIMP2, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_EXARCHLICH*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_EXYEL2_A, TRUE, LS_FIRIMP2, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_EXNECROMORB*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_EXYEL2_B, TRUE, LS_FIRIMP2, SFX_NONE, 1, 1, ALIGN32 }, #endif // clang-format on }; diff --git a/structs.h b/structs.h index 0c0f384b276..1074ea4ce2c 100644 --- a/structs.h +++ b/structs.h @@ -162,7 +162,7 @@ typedef struct ItemFileData { int idSFX; // sounds effect of dropping the item on ground (_sfx_id). int iiSFX; // sounds effect of placing the item in the inventory (_sfx_id). int iAnimLen; // item drop animation length - ALIGNMENT64(2) + ALIGNMENT64(3) } ItemFileData; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) @@ -192,7 +192,7 @@ typedef struct ItemData { BYTE iMaxAC; BYTE iDurability; int iValue; - ALIGNMENT(5, 3) + ALIGNMENT(5, 4) } ItemData; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) @@ -493,7 +493,7 @@ typedef struct MissileData { int miSFX; // sound effect on impact (_sfx_id) BYTE mlSFXCnt; // number of launch sound effects to choose from BYTE miSFXCnt; // number of impact sound effects to choose from - ALIGNMENT(2, 7) + ALIGNMENT32(2) } MissileData; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) @@ -777,7 +777,7 @@ typedef struct MonsterStruct { uint16_t _mAlign_0; // unused int _mType; // _monster_id MonAnimStruct* _mAnims; - ALIGNMENT(6, 1) + ALIGNMENT(6, 2) } MonsterStruct; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) @@ -906,7 +906,7 @@ typedef struct ObjectStruct { int _oVar6; int _oVar7; int _oVar8; - ALIGNMENT(8, 5) + ALIGNMENT(8, 6) } ObjectStruct; #if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) From 8efc40011bae77dc30b0d87f410b2478f760eb2e Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 19 Aug 2024 08:25:55 +0200 Subject: [PATCH 448/596] merge InitThemes and HoldThemeRooms --- Source/interfac.cpp | 3 +- Source/themes.cpp | 71 ++++++++++++++++++++++----------------------- Source/themes.h | 10 ++++--- 3 files changed, 41 insertions(+), 43 deletions(-) diff --git a/Source/interfac.cpp b/Source/interfac.cpp index 5a40fd652fe..b69f6775569 100644 --- a/Source/interfac.cpp +++ b/Source/interfac.cpp @@ -229,9 +229,8 @@ void LoadGameLevel(int lvldir) IncProgress(); // "MonsterFX" (7) if (currLvl._dType != DTYPE_TOWN) { GetLevelMTypes(); // select monster types and load their fx - InitThemes(); // select theme types + InitThemes(); // protect themes with dFlags and select theme types IncProgress(); // "Monsters" (8) - HoldThemeRooms(); // protect themes with dFlags InitMonsters(); // place monsters } else { InitLvlStores(); diff --git a/Source/themes.cpp b/Source/themes.cpp index 8618ad555d3..d01e6fba56a 100644 --- a/Source/themes.cpp +++ b/Source/themes.cpp @@ -310,12 +310,41 @@ void InitLvlThemes() void InitThemes() { - int i, j; + int i, j, x, y, x1, y1, x2, y2; // assert(currLvl._dType != DTYPE_TOWN); if (currLvl._dLevelNum >= DLV_HELL4) // there are no themes in hellfire (and on diablo-level) return; + for (i = 0; i < numthemes; i++) { + x1 = themes[i]._tsx1; + y1 = themes[i]._tsy1; + x2 = themes[i]._tsx2; + y2 = themes[i]._tsy2; + // convert to subtile-coordinates + x1 = DBORDERX + 2 * x1; + y1 = DBORDERY + 2 * y1; + x2 = DBORDERX + 2 * x2 + 1; + y2 = DBORDERY + 2 * y2 + 1; + themes[i]._tsx1 = x1; + themes[i]._tsy1 = y1; + themes[i]._tsx2 = x2; + themes[i]._tsy2 = y2; + // select transval + themes[i]._tsTransVal = dTransVal[x1 + 2][y1 + 2]; + assert(themes[i]._tsTransVal != 0); + // protect themes with dFlags + // v = themes[i]._tsTransVal; + for (x = x1 + 1; x < x2; x++) { + for (y = y1 + 1; y < y2; y++) { + // if (dTransVal[x][y] == v) { -- wall? + dFlags[x][y] |= BFLAG_MON_PROTECT | BFLAG_OBJ_PROTECT; + // } + } + } + } + + // select theme types // TODO: use dType instead _gbShrineFlag = currLvl._dDunType != DGT_CAVES && currLvl._dDunType != DGT_HELL; _gbSkelRoomFlag = _gbShrineFlag && numSkelTypes != 0; @@ -329,16 +358,6 @@ void InitThemes() _gbTFountainFlag = true; _gbTreasureFlag = true; - for (i = 0; i < numthemes; i++) { - // convert to subtile-coordinates - themes[i]._tsx1 = DBORDERX + 2 * themes[i]._tsx1; - themes[i]._tsy1 = DBORDERY + 2 * themes[i]._tsy1; - themes[i]._tsx2 = DBORDERX + 2 * themes[i]._tsx2 + 1; - themes[i]._tsy2 = DBORDERY + 2 * themes[i]._tsy2 + 1; - // select transval - themes[i]._tsTransVal = dTransVal[themes[i]._tsx1 + 2][themes[i]._tsy1 + 2]; - assert(themes[i]._tsTransVal != 0); - } if (QuestStatus(Q_ZHAR)) { for (i = 0; i < numthemes; i++) { if (SpecialThemeFit(i, THEME_LIBRARY)) { @@ -356,28 +375,6 @@ void InitThemes() } } -void HoldThemeRooms() -{ - int i, x, y, x1, y1, x2, y2; - // assert(currLvl._dType != DTYPE_TOWN); - // assert(currLvl._dLevelNum < DLV_HELL4 || numthemes == 0); // there are no themes in hellfire (and on diablo-level) - - for (i = numthemes - 1; i >= 0; i--) { - x1 = themes[i]._tsx1; - y1 = themes[i]._tsy1; - x2 = themes[i]._tsx2; - y2 = themes[i]._tsy2; - // v = themes[i]._tsTransVal; - for (x = x1 + 1; x < x2; x++) { - for (y = y1 + 1; y < y2; y++) { - // if (dTransVal[x][y] == v) { -- wall? - dFlags[x][y] |= BFLAG_MON_PROTECT | BFLAG_OBJ_PROTECT; - // } - } - } - } -} - /* * Place a theme object with the specified frequency. * @param tv: theme id in the dungeon matrix. @@ -566,13 +563,13 @@ static void Theme_SkelRoom(int themeId, BYTE tv) AddObject(OBJ_BANNERL, xx + 1, yy + 1); } - if ((dObject[xx][yy - 3] == 0 || !objects[dObject[xx][yy - 3] - 1]._oDoorFlag) // not a door - && (nSolidTable[dPiece[xx][yy - 3]] || !nSolidTable[dPiece[xx + 1][yy - 3]])) { // or a single path to NE TODO: allow if !nSolidTable[dPiece[xx - 1][yy - 3]]? + if ((dObject[xx][yy - 3] == 0 || !objects[dObject[xx][yy - 3] - 1]._oDoorFlag) // not a door + && (nSolidTable[dPiece[xx][yy - 3]] || !nSolidTable[dPiece[xx + 1][yy - 3]])) { // or a single path to NE TODO: allow if !nSolidTable[dPiece[xx - 1][yy - 3]]? // assert(dObject[xx][yy - 2] == 0); AddObject(OBJ_BOOK2R, xx, yy - 2); } - if ((dObject[xx][yy + 3] == 0 || !objects[dObject[xx][yy + 3] - 1]._oDoorFlag) // not a door - && (nSolidTable[dPiece[xx][yy + 3]] || !nSolidTable[dPiece[xx + 1][yy + 3]])) { // or a single path to SW TODO: allow if !nSolidTable[dPiece[xx - 1][yy + 3]]? + if ((dObject[xx][yy + 3] == 0 || !objects[dObject[xx][yy + 3] - 1]._oDoorFlag) // not a door + && (nSolidTable[dPiece[xx][yy + 3]] || !nSolidTable[dPiece[xx + 1][yy + 3]])) { // or a single path to SW TODO: allow if !nSolidTable[dPiece[xx - 1][yy + 3]]? // assert(dObject[xx][yy + 2] == 0); AddObject(OBJ_BOOK2R, xx, yy + 2); } diff --git a/Source/themes.h b/Source/themes.h index 0136a2a37c1..1a26db12629 100644 --- a/Source/themes.h +++ b/Source/themes.h @@ -16,16 +16,18 @@ extern int numthemes; extern int zharlib; extern ThemeStruct themes[MAXTHEMES]; +/** + * @brief InitLvlThemes resets the global variables of the theme rooms. + */ void InitLvlThemes(); -void InitThemes(); /** - * @brief HoldThemeRooms marks theme rooms as populated. + * @brief InitThemes marks theme rooms as populated and selects their type. */ -void HoldThemeRooms(); +void InitThemes(); /** - * CreateThemeRooms adds thematic elements to rooms. + * @brief CreateThemeRooms adds thematic elements to rooms. */ void CreateThemeRooms(); From e4cebab0e7cad4af1f5a1869ca6e5c8eb5cf67c3 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 19 Aug 2024 10:06:58 +0200 Subject: [PATCH 449/596] update libzt --- 3rdParty/libzt/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdParty/libzt/CMakeLists.txt b/3rdParty/libzt/CMakeLists.txt index 258da55ce4c..ec05f4e7d60 100644 --- a/3rdParty/libzt/CMakeLists.txt +++ b/3rdParty/libzt/CMakeLists.txt @@ -11,7 +11,7 @@ FetchContent_Declare(libzt #GIT_REPOSITORY https://github.com/diasurgical/libzt.git #GIT_TAG db7b642a4ce9f0f5e0ba7f293bd7ffa7897e4831) GIT_REPOSITORY https://github.com/pionere/libzt.git - GIT_TAG b738557b538fc6948316c69312ced99d0ef495d4) + GIT_TAG fc82cd88c36eba2333550de190631689f2449c7a) FetchContent_MakeAvailableExcludeFromAll(libzt) #if(NOT ANDROID) From a17d893d901af5c12147c96d0d4f0ae8b60610bc Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 20 Aug 2024 10:41:34 +0200 Subject: [PATCH 450/596] add new monster types to hell levels --- Source/debug.cpp | 2 + Source/misdat.cpp | 4 ++ Source/misproc.h | 2 + Source/missiles.cpp | 116 +++++++++++++++++++++++++++++++++++++++++--- Source/monstai.h | 1 + Source/monstdat.cpp | 2 + Source/monster.cpp | 82 ++++++++++++++++++++++++++++++- Source/questdat.cpp | 4 +- docs/CHANGELOG.md | 1 + enums.h | 7 +++ 10 files changed, 211 insertions(+), 10 deletions(-) diff --git a/Source/debug.cpp b/Source/debug.cpp index 1691bea94c4..a4bc889bce9 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -353,6 +353,8 @@ void ValidateData() } if (md.mAI.aiInt > UINT8_MAX - HELL_LEVEL_BONUS / 16) // required by InitMonsterStats app_fatal("Too high aiInt %d for %s (%d).", md.mLevel, md.mName, i); + if (md.mAI.aiType == AI_MAGE && md.mAI.aiInt < 1)// required by MAI_Mage (RETREAT) + app_fatal("Too low aiInt %d for %s (%d).", md.mLevel, md.mName, i); if (md.mLevel == 0) // required by InitMonsterStats app_fatal("Invalid mLevel %d for %s (%d).", md.mLevel, md.mName, i); if (md.mLevel > UINT8_MAX - HELL_LEVEL_BONUS) // required by InitMonsterStats diff --git a/Source/misdat.cpp b/Source/misdat.cpp index 769b80f3817..eeece5a7a85 100644 --- a/Source/misdat.cpp +++ b/Source/misdat.cpp @@ -24,6 +24,7 @@ const MissileData missiledata[] = { /*MIS_SNOWWICH*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD, MISR_MAGIC, MFILE_SCUBMISB, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, /*MIS_HLSPWN*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD, MISR_MAGIC, MFILE_SCUBMISD, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, /*MIS_SOLBRNR*/ { &AddFirebolt, &MI_Firebolt, MIF_SHROUD, MISR_MAGIC, MFILE_SCUBMISC, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_MAGE*/ { &AddMage, &MI_Mage, MIF_SHROUD, MISR_MAGIC, MFILE_MAGEMIS, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, /*MIS_MAGMABALL*/ { &AddMagmaball, &MI_Firebolt, MIF_SHROUD, MISR_FIRE, MFILE_MAGBALL, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, /*MIS_ACID*/ { &AddAcid, &MI_Acid, MIF_SHROUD, MISR_ACID, MFILE_ACIDBF, TRUE, LS_ACID, SFX_NONE, 2, 1, ALIGN32 }, /*MIS_ACIDPUD*/ { &AddAcidpud, &MI_Acidpud, MIF_NOBLOCK | MIF_AREA | MIF_DOT, MISR_ACID, MFILE_ACIDPUD, TRUE, LS_PUDDLE, SFX_NONE, 1, 1, ALIGN32 }, @@ -38,6 +39,7 @@ const MissileData missiledata[] = { /*MIS_EXSNOWWICH*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_SCBSEXPB, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, /*MIS_EXHLSPWN*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_SCBSEXPD, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, /*MIS_EXSOLBRNR*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_SCBSEXPC, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, +/*MIS_EXMAGE*/ { &AddMisexp, &MI_Misexp, 0, MISR_NONE, MFILE_MAGEEXP, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, /*MIS_POISON*/ { &AddPoison, &MI_Poison, MIF_SHROUD | MIF_NOBLOCK | MIF_AREA | MIF_DOT, MISR_MAGIC, MFILE_MAGICEXP, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, /*MIS_WIND*/ { &AddWind, &MI_Wind, MIF_SHROUD | MIF_NOBLOCK | MIF_DOT | MIF_LEAD, MISR_MAGIC, MFILE_WIND, TRUE, SFX_NONE, SFX_NONE, 1, 1, ALIGN32 }, /*MIS_LIGHTBALL*/ { &AddLightball, &MI_Lightball, MIF_SHROUD | MIF_DOT | MIF_LEAD, MISR_LIGHTNING, MFILE_LGHNING, TRUE, LS_LNING1, LS_ELECIMP1, 1, 1, ALIGN32 }, @@ -188,6 +190,8 @@ const MisFileData misfiledata[NUM_MFILE + 1] = { /*MFILE_SCBSEXPC*/ { 1, "Scbsexpc", NULL, MAFLAG_HIDDEN, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 128, 32, ALIGN }, /*MFILE_SCUBMISD*/ { 1, "Scubmisd", NULL, MAFLAG_HIDDEN, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 96, 16, ALIGN }, /*MFILE_SCBSEXPD*/ { 1, "Scbsexpd", NULL, MAFLAG_HIDDEN, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 128, 32, ALIGN }, +/*MFILE_MAGEMIS*/ { 1, "Scubmisb", "PlrGFX\\Stone.TRN", MAFLAG_HIDDEN, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 96, 16, ALIGN }, +/*MFILE_MAGEEXP*/ { 1, "Scbsexpb", "PlrGFX\\Stone.TRN", MAFLAG_HIDDEN, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 128, 32, ALIGN }, #ifdef HELLFIRE /*MFILE_SPAWNS*/ { 8, "spawns", NULL, MAFLAG_HIDDEN, { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, { 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0 }, 96, 16, ALIGN }, /*MFILE_RGLOWS1*/ { 1, "rglows1", NULL, 0, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 96, 16, ALIGN }, diff --git a/Source/misproc.h b/Source/misproc.h index 39107a2663b..ef7515e76a7 100644 --- a/Source/misproc.h +++ b/Source/misproc.h @@ -26,6 +26,7 @@ int AddRingC(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in #endif int AddArrow(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl); int AddFirebolt(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl); +int AddMage(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl); int AddMagmaball(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl); int AddLightball(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl); int AddPoison(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl); @@ -85,6 +86,7 @@ void MI_AsArrow(int mi); void MI_Firebolt(int mi); void MI_Lightball(int mi); void MI_Poison(int mi); +void MI_Mage(int mi); void MI_Wind(int mi); //void MI_Krull(int mi); void MI_Acid(int mi); diff --git a/Source/missiles.cpp b/Source/missiles.cpp index b9980df9c29..7c80a226ca6 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -1895,6 +1895,28 @@ int AddFirebolt(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, return MIRES_DONE; } +/** + * Var1: the target player + * Var2: turn timer + */ +int AddMage(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) +{ + MissileStruct* mis; + constexpr int MAX_BRIGHTNESS = 10; + // (micaster == MST_MONSTER); + // assert(misource < MAXMONSTERS); + mis = &missile[mi]; + mis->_miVar1 = dPlayer[dx][dy]; + GetMissileVel(mi, sx, sy, dx, dy, MIS_SHIFTEDVEL(4)); + mis->_miUniqTrans = MAX_BRIGHTNESS; + mis->_miRange = 255; + mis->_miMinDam = monsters[misource]._mMinDamage << 6; + mis->_miMaxDam = monsters[misource]._mMaxDamage << 6; + static_assert(MAX_LIGHT_RAD >= 8, "AddMage needs at least light-radius of 8."); + mis->_miLid = AddLight(sx, sy, 8); + return MIRES_DONE; +} + int AddMagmaball(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { MissileStruct* mis; @@ -2249,9 +2271,12 @@ int AddLightning(int mi, int sx, int sy, int dx, int dy, int midir, int micaster int AddBloodBoilC(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { MissileStruct* mis; - // (micaster & MST_PLAYER); - // 'assert'((unsigned)misource < MAX_PLRS); + // ((micaster & MST_PLAYER) || micaster == MST_MONSTER); mis = &missile[mi]; + if (micaster == MST_MONSTER) { + spllvl = monsters[misource]._mLevel / 6; // TODO: add _mSkillLvl? + mis->_miSpllvl = spllvl; + } mis->_mix = dx - 2; mis->_miy = dy - 2; @@ -2265,12 +2290,15 @@ int AddBloodBoil(int mi, int sx, int sy, int dx, int dy, int midir, int micaster { MissileStruct* mis; int mindam, maxdam; - + // ((micaster & MST_PLAYER) || micaster == MST_MONSTER); mis = &missile[mi]; - // (micaster & MST_PLAYER); - // assert((unsigned)misource < MAX_PLRS); - mindam = (plx(misource)._pMagic >> 2) + (spllvl << 2) + 10; - maxdam = (plx(misource)._pMagic >> 2) + (spllvl << 3) + 10; + if (micaster == MST_MONSTER) { + mindam = monsters[misource]._mLevel >> 1; // TODO: use _mSkillLvl? + maxdam = monsters[misource]._mLevel; + } else { + mindam = (plx(misource)._pMagic >> 2) + (spllvl << 2) + 10; + maxdam = (plx(misource)._pMagic >> 2) + (spllvl << 3) + 10; + } mis->_miMinDam = mindam << 6; mis->_miMaxDam = maxdam << 6; @@ -2357,6 +2385,7 @@ int AddMisexp(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, i mis->_miyoff = bmis->_miyoff; //mis->_mitxoff = bmis->_mitxoff; //mis->_mityoff = bmis->_mityoff; + mis->_miUniqTrans = bmis->_miUniqTrans; } //mis->_mixvel = 0; //mis->_miyvel = 0; @@ -3567,6 +3596,79 @@ void MI_Firebolt(int mi) mis->_miDelFlag = TRUE; // + AddUnLight } +void MI_Mage(int mi) +{ + MissileStruct *mis, *bmis; + constexpr int MAX_BRIGHTNESS = 10; + int i, bmi, xptype; + + mis = &missile[mi]; + mis->_mitxoff += mis->_mixvel; + mis->_mityoff += mis->_miyvel; + GetMissilePos(mi); + bool wallHit = true; + if (mis->_mix != mis->_misx || mis->_miy != mis->_misy) { + wallHit = CheckMissileCol(mi, mis->_mix, mis->_miy, MICM_BLOCK_ANY); + } + mis->_miRange--; + if (mis->_miRange >= 0) { + for (i = 0; i < nummissiles; i++) { + bmi = missileactive[i]; + if (bmi <= mi) + continue; + bmis = &missile[bmi]; + // check the type of the other missile + if (bmis->_miType != MIS_MAGE) { + continue; + } + // check the distance + if (bmis->_mix != mis->_mix || bmis->_miy != mis->_miy) { + continue; + } + int doff = abs(bmis->_mixoff - mis->_mixoff) + abs(bmis->_miyoff - mis->_miyoff) * 2; + if (doff > 64 * ASSET_MPL) + continue; + // check target + if (mis->_miVar1 != 0 && bmis->_miVar1 != 0 && mis->_miVar1 != bmis->_miVar1) + continue; + // merge the missiles + if (mis->_miVar1 != 0) + bmis->_miVar1 = mis->_miVar1; + bmis->_miUniqTrans -= (MAX_BRIGHTNESS - mis->_miUniqTrans) + 1; + if (bmis->_miUniqTrans < 0) + bmis->_miUniqTrans = 0; + bmis->_miMinDam += mis->_miMinDam; + bmis->_miMaxDam += mis->_miMaxDam; + if (bmis->_miRange < mis->_miRange + 1) + bmis->_miRange = mis->_miRange + 1; + // assert(mis->_miCaster == MST_MONSTER && bmis->_miCaster == MST_MONSTER); + if (monsters[bmis->_miSource]._mMagic < monsters[mis->_miSource]._mMagic) + bmis->_miSource = mis->_miSource; + mis->_miDelFlag = TRUE; // + AddUnLight + return; + } + + if (mis->_miVar1 != 0 && (mis->_miVar2++ & 7) == 0) { + int pnum = mis->_miVar1; + pnum = pnum >= 0 ? pnum - 1 : -(pnum + 1); + if (plr._pActive && plr._pDunLevel == currLvl._dLevelIdx && plr._pHitPoints >= (1 << 6) && (mis->_mix != plr._px || mis->_miy != plr._py)) { + GetMissileVel(mi, mis->_mix, mis->_miy, plr._px, plr._py, MIS_SHIFTEDVEL(4)); + } else { + mis->_miVar1 = 0; + } + } + + CondChangeLightXY(mis->_miLid, mis->_mix, mis->_miy); + PutMissile(mi); + return; + } + + xptype = MIS_EXMAGE; + AddMissile(0, 0, mi, 0, 0, xptype, MST_NA, 0, 0); + + mis->_miDelFlag = TRUE; // + AddUnLight +} + void MI_Poison(int mi) { MissileStruct* mis; diff --git a/Source/monstai.h b/Source/monstai.h index 28d15b38eb2..97e2dff6b69 100644 --- a/Source/monstai.h +++ b/Source/monstai.h @@ -35,6 +35,7 @@ void MAI_Golem(int mnum); void MAI_SkelKing(int mnum); void MAI_Rhino(int mnum); void MAI_Counselor(int mnum); +void MAI_Mage(int mnum); void MAI_Garbud(int mnum); void MAI_Zhar(int mnum); void MAI_SnotSpil(int mnum); diff --git a/Source/monstdat.cpp b/Source/monstdat.cpp index 96fdab201c7..ae345028dc5 100644 --- a/Source/monstdat.cpp +++ b/Source/monstdat.cpp @@ -119,6 +119,8 @@ const MonsterData monsterdata[NUM_MTYPES] = { /* MT_GMAGE */ { MOFILE_MAGE, 27, 7, "Monsters\\Mage\\Cnselg.TRN", "Magistrate", { AI_COUNSLR, 1, MIS_CBOLTC, 0 }, 85, 85, 0 , 100, 10, 24, 0, 0, 0, 65, 0, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, 2985, ALIGN }, // MC_DEMON, /* MT_XMAGE */ { MOFILE_MAGE, 29, 7, "Monsters\\Mage\\Cnselgd.TRN", "Cabalist", { AI_COUNSLR, 2, MIS_LIGHTNINGC, 0 }, 120, 120, 0 , 110, 12, 28, 0, 0, 0, 70, 0, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 3286, ALIGN }, // MC_DEMON, /* MT_BMAGE */ { MOFILE_MAGE, 30, 7, "Monsters\\Mage\\Cnselbk.TRN", "Advocate", { AI_COUNSLR, 3, MIS_FIREBALL, 0 }, 145, 145, MFLAG_CAN_OPEN_DOOR, 120, 14, 32, 0, 0, 0, 70, 0, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 3312, ALIGN }, // MC_DEMON, +/* MT_SMAGE */ { MOFILE_MAGE, 28, 7, "Monsters\\Fat\\Blue.TRN", "Deacon", { AI_MAGE, 1, MIS_SWAMPC, 0 }, 175, 175, 0 , 110, 12, 14, 0, 0, 0, 70, 0, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 3186, ALIGN }, // MC_DEMON, +/* MT_OMAGE */ { MOFILE_MAGE, 30, 7, "Monsters\\Zombie\\Grey.TRN", "Vicar", { AI_MAGE, 2, MIS_BLOODBOILC, 0 }, 190, 190, 0 , 120, 13, 15, 0, 0, 0, 75, 0, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_RESIST, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_RESIST, 3416, ALIGN }, // MC_DEMON, /* MT_GOLEM */ { MOFILE_GOLEM, 4, 0, NULL, "Golem", { AI_GOLUM, 0, 0, 0 }, 40, 40, MFLAG_NOSTONE | MFLAG_SEARCH | MFLAG_CAN_OPEN_DOOR, 30, 3, 5, 0, 0, 0, 0, 0, 50, 20, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, 0, ALIGN }, // MC_DEMON, /* MT_DIABLO */ { MOFILE_DIABLO, 32, 7, NULL, "The Dark Lord", { AI_ROUNDRANGED, 3, MIS_APOCAC2, 0 }, 1666, 1666, MFLAG_NOSTONE | MFLAG_NOCORPSE | MFLAG_KNOCKBACK | MFLAG_SEARCH, 240, 30, 60, 0, 0, 0, 200, 0, 90, 40, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST , 5555, ALIGN }, // MC_DEMON, /* MT_DARKMAGE*///{ MOFILE_DARKMAGE, 30, 7, NULL, "The Arch-Litch Malignus", { AI_COUNSLR, 3, MIS_FIREBALL, 0 }, 160, 160, MFLAG_CAN_OPEN_DOOR, 120, 20, 40, 0, 0, 0, 0, 0, 70, 30, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_RESIST | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_IMMUNE | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, 3312, ALIGN }, // MC_DEMON, diff --git a/Source/monster.cpp b/Source/monster.cpp index 8146350613a..a30778540e3 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -137,6 +137,7 @@ static void (*const AiProc[])(int i) = { /*AI_SNOTSPIL*/ &MAI_SnotSpil, /*AI_SNAKE*/ &MAI_Snake, /*AI_COUNSLR*/ &MAI_Counselor, +/*AI_MAGE*/ &MAI_Mage, /*AI_ROUNDRANGED2*/ &MAI_RoundRanged2, /*AI_LAZARUS*/ &MAI_Lazarus, /*AI_LAZHELP*/ &MAI_Lazhelp, @@ -275,6 +276,11 @@ static void InitMonsterGFX(int midx) LoadMissileGFX(MFILE_SCUBMISC); LoadMissileGFX(MFILE_SCBSEXPC); break; + case MT_SMAGE: + case MT_OMAGE: + LoadMissileGFX(MFILE_MAGEMIS); + LoadMissileGFX(MFILE_MAGEEXP); + break; case MT_DIABLO: LoadMissileGFX(MFILE_FIREPLAR); break; @@ -4052,7 +4058,8 @@ void MAI_Horkdemon(int mnum) /* * AI for monsters using ranged attacks. Uses MIS_FLASH when the target is next to the monster. - * Attempts to walk in a circle around the target. Uses fade in/out while moving. + * Attempts to walk in a circle around the target. Retreats on low hp. + * Uses fade in/out while moving. * * @param mnum: the id of the monster * @param aiParam1: the missile type to be launched at the end of the attack animation when the target is far away. @@ -4125,6 +4132,79 @@ void MAI_Counselor(int mnum) } } +/* + * AI for monsters using ranged attacks (MIS_MAGE normally, aiParam1 occasionally). + * Uses MIS_FLASH when the target is next to the monster. + * Attempts to walk in a circle around the target. Might move a bit when the enemy is far away. + * Uses fade in/out while moving. + * + * @param mnum: the id of the monster + * @param aiParam1: the missile type to be launched at the end of the attack animation when the target is far away. + */ +void MAI_Mage(int mnum) +{ + MonsterStruct* mon = &monsters[mnum]; + int md, v, dist; + if (MON_RELAXED || MON_ACTIVE) + return; + + MonEnemyInfo(mnum); + // if (mon->_msquelch < SQUELCH_MAX && (mon->_mFlags & MFLAG_CAN_OPEN_DOOR)) + // MonstCheckDoors(mon->_mx, mon->_my); + md = currEnemyInfo._meLastDir; + dist = currEnemyInfo._meRealDist; + mon->_mdir = md; + if (mon->_mgoal == MGOAL_NORMAL) { + v = random_(121, 100); + if (dist >= 2) { + if (v < 5 * (mon->_mAI.aiInt + 10) && EnemyInLine(mnum)) { + MonStartRAttack(mnum, v == (5 * (4 + 10) - 1) ? mon->_mAI.aiParam1 : MIS_MAGE /*mon->_mAI.aiParam2*/); + } else if (mon->_msquelch >= SQUELCH_MAX && random_(124, 128) < 39) { +#if DEBUG + assert((mon->_mAnims[MA_SPECIAL].maFrames - 1) * mon->_mAnims[MA_SPECIAL].maFrameLen * 2 + + (mon->_mAnims[MA_WALK].maFrames - 1) * mon->_mAnims[MA_WALK].maFrameLen * (6 + 4) < SQUELCH_MAX - SQUELCH_LOW); +#endif + static_assert((20 - 1) * 1 * 2 + (1 - 1) * 1 * (6 + 4) < SQUELCH_MAX - SQUELCH_LOW, "MAI_Mage might relax with move goal."); + mon->_mgoal = MGOAL_MOVE; + mon->_mgoalvar1 = 6 + random_low(0, std::min(dist, 4)); // MOVE_DISTANCE + mon->_mgoalvar2 = random_(130, 2); // MOVE_TURN_DIRECTION + MonStartFadeout(mnum, false); + } else if (mon->_msquelch < SQUELCH_MAX && mon->_msquelch >= SQUELCH_MAX - 20 && mon->_mVar1 != MM_DELAY) { + static_assert((20 - 1) * 1 * 2 + (1 - 1) * 1 * 2 < SQUELCH_MAX - 20 - SQUELCH_LOW, "MAI_Mage might relax with retreat goal."); + mon->_mgoal = MGOAL_RETREAT; + mon->_mgoalvar1 = mon->_mAI.aiInt + 1; // RETREAT_DISTANCE + MonStartFadeout(mnum, false); + } + } else { + if (mon->_mVar1 == MM_FADEIN) // STAND_PREV_MODE + v >>= 1; + if (mon->_mVar1 == MM_DELAY || v < 2 * mon->_mAI.aiInt + 20) { + MonStartRAttack(mnum, v < 10 ? MIS_FLASH : MIS_MAGE /*mon->_mAI.aiParam2*/); + } + } + if (mon->_mmode == MM_STAND) { + v = std::max(1, RandRange(11, 18) - 2 * mon->_mAI.aiInt); + MonStartDelay(mnum, v); + } + } else if (mon->_mgoal == MGOAL_RETREAT) { + if (--mon->_mgoalvar1 == 0 // RETREAT_DISTANCE + || !MonCallWalk(mnum, random_(130, NUM_DIRS))) { + mon->_mgoal = MGOAL_NORMAL; + MonStartFadein(mnum, true); + } + } else { + assert(mon->_mgoal == MGOAL_MOVE); + if (dist >= 2 /*&& mon->_msquelch == SQUELCH_MAX && dTransVal[mon->_mx][mon->_my] == dTransVal[mon->_menemyx][mon->_menemyy]*/ + && (--mon->_mgoalvar1 > 4 || (mon->_mgoalvar1 > 0 && !MonDirOK(mnum, md))) // MOVE_DISTANCE + && MonRoundWalk(mnum, md, &mon->_mgoalvar2)) { // MOVE_TURN_DIRECTION + ; + } else { + mon->_mgoal = MGOAL_NORMAL; + MonStartFadein(mnum, true); + } + } +} + void MAI_Garbud(int mnum) { MonsterStruct* mon; diff --git a/Source/questdat.cpp b/Source/questdat.cpp index 2a134ba94b3..baa8f95b878 100644 --- a/Source/questdat.cpp +++ b/Source/questdat.cpp @@ -70,11 +70,11 @@ const LevelData AllLevels[NUM_FIXLVLS] = { }, /*DLV_HELL2*/ { 28, FALSE, DTYPE_HELL, DGT_HELL, TMUSIC_L4, LFILE_L4, 12, 16, "Hell 2", "Levels\\L4Data\\L4_%d.PAL", "Gendata\\Cut4.CEL", "Gendata\\Cut4.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, - { MT_RSNAKE, MT_NBLACK, MT_NSUCC, MT_BMEGA, MT_XACID, MT_GTHIN, MT_RMEGA, MT_BSNAKE, MT_RBLACK, MT_GBLACK, MT_GSUCC, MT_NMAGE, MT_GMAGE, MT_BBLACK, MT_RSUCC, MT_INVALID }, + { MT_RSNAKE, MT_NBLACK, MT_NSUCC, MT_BMEGA, MT_XACID, MT_GTHIN, MT_RMEGA, MT_BSNAKE, MT_RBLACK, MT_GBLACK, MT_GSUCC, MT_NMAGE, MT_GMAGE, MT_SMAGE, MT_BBLACK, MT_RSUCC, MT_INVALID }, }, /*DLV_HELL3*/ { 30, FALSE, DTYPE_HELL, DGT_HELL, TMUSIC_L4, LFILE_L4, 12, 16, "Hell 3", "Levels\\L4Data\\L4_%d.PAL", "Gendata\\Cut4.CEL", "Gendata\\Cut4.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, - { MT_RMEGA, MT_RBLACK, MT_GSUCC, MT_GMAGE, MT_BBLACK, MT_RSUCC, MT_GSNAKE, MT_BSUCC, MT_XMAGE, MT_INVALID }, + { MT_RMEGA, MT_RBLACK, MT_GSUCC, MT_GMAGE, MT_BBLACK, MT_RSUCC, MT_GSNAKE, MT_BSUCC, MT_XMAGE, MT_SMAGE, MT_OMAGE, MT_INVALID }, }, /*DLV_HELL4*/ { 32, FALSE, DTYPE_HELL, DGT_HELL, TMUSIC_L4, LFILE_L4, 12, 16, "Diablo", "Levels\\L4Data\\L4_%d.PAL", "Gendata\\Cutgate.CEL", "Gendata\\Cutgate.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 33eeba5b27f..e7824477523 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -57,6 +57,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - The Defiler drops a fang instead of the Cathedral Map (the fang acts the same way as the Cathedral Map) - the brain quest-item is dropped by a new unique monster - Skeleton King (and Hork Demon) are summoning monsters in multiplayer games +- added new monster types to hell levels - added unique monsters to crypt and nest levels - multiple corpses are allowed on one tile - players do not leave the game after Diablo is defeated (restart in town) diff --git a/enums.h b/enums.h index 19833dec2c1..3d576aef7a4 100644 --- a/enums.h +++ b/enums.h @@ -1930,6 +1930,7 @@ typedef enum missile_id { MIS_SNOWWICH, MIS_HLSPWN, MIS_SOLBRNR, + MIS_MAGE, MIS_MAGMABALL, MIS_ACID, MIS_ACIDPUD, @@ -1944,6 +1945,7 @@ typedef enum missile_id { MIS_EXSNOWWICH, MIS_EXHLSPWN, MIS_EXSOLBRNR, + MIS_EXMAGE, MIS_POISON, MIS_WIND, MIS_LIGHTBALL, @@ -2105,6 +2107,8 @@ typedef enum missile_gfx_id { MFILE_SCBSEXPC, MFILE_SCUBMISD, MFILE_SCBSEXPD, + MFILE_MAGEMIS, + MFILE_MAGEEXP, #ifdef HELLFIRE MFILE_SPAWNS, MFILE_RGLOWS1, @@ -2190,6 +2194,7 @@ typedef enum _monster_ai { AI_SNOTSPIL, AI_SNAKE, AI_COUNSLR, + AI_MAGE, AI_ROUNDRANGED2, AI_LAZARUS, AI_LAZHELP, @@ -2314,6 +2319,8 @@ typedef enum _monster_id { MT_GMAGE, MT_XMAGE, MT_BMAGE, + MT_SMAGE, + MT_OMAGE, MT_GOLEM, MT_DIABLO, //MT_DARKMAGE, From d65fe8b2bc48bbdbd994a67697fb6347ef448133 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 20 Aug 2024 18:02:19 +0200 Subject: [PATCH 451/596] fix theme rooms of the dynamic levels on DLV_HELL4 --- Source/themes.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Source/themes.cpp b/Source/themes.cpp index d01e6fba56a..ff71f9acbc6 100644 --- a/Source/themes.cpp +++ b/Source/themes.cpp @@ -313,9 +313,9 @@ void InitThemes() int i, j, x, y, x1, y1, x2, y2; // assert(currLvl._dType != DTYPE_TOWN); - if (currLvl._dLevelNum >= DLV_HELL4) // there are no themes in hellfire (and on diablo-level) + if (numthemes == 0) return; - + // assert(currLvl._dLevelNum < DLV_HELL4 || (currLvl._dDynLvl && currLvl._dLevelNum == DLV_HELL4)); // there are no themes in hellfire (and on diablo-level) for (i = 0; i < numthemes; i++) { x1 = themes[i]._tsx1; y1 = themes[i]._tsy1; @@ -832,9 +832,7 @@ void CreateThemeRooms() { int i; BYTE tv; - // assert(currLvl._dType != DTYPE_TOWN); - // assert(currLvl._dLevelNum < DLV_HELL4 || numthemes == 0); // there are no themes in hellfire (and on diablo-level) - + // assert(currLvl._dLevelNum < DLV_HELL4 || (currLvl._dDynLvl && currLvl._dLevelNum == DLV_HELL4) || numthemes == 0); // there are no themes in hellfire (and on diablo-level) //gbInitObjFlag = true; for (i = 0; i < numthemes; i++) { tv = themes[i]._tsTransVal; From 97cd2d008fd09453a48122481da892b7e72722dc Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 21 Aug 2024 12:28:07 +0200 Subject: [PATCH 452/596] get rid of a pointless SetRndSeed in PlaceInitItems --- Source/items.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/items.cpp b/Source/items.cpp index 009ae6f8f85..028507e2fbf 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -138,7 +138,6 @@ static void PlaceInitItems() ii = itemactive[numitems]; assert(ii == numitems); seed = NextRndSeed(); - SetRndSeed(seed); SetItemData(ii, random_(12, 2) != 0 ? IDI_HEAL : IDI_MANA); items[ii]._iSeed = seed; items[ii]._iCreateInfo = lvl; // | CF_PREGEN; From 9172c15ec3cb3aa19c1d3bd5b983d4d106af71ab Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 21 Aug 2024 12:32:21 +0200 Subject: [PATCH 453/596] use int32_t to store rng-seeds --- Source/msg.cpp | 2 +- Source/msg.h | 2 +- Source/multi.cpp | 6 +++--- Source/quests.cpp | 2 +- Source/quests.h | 2 +- structs.h | 24 ++++++++++++------------ 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Source/msg.cpp b/Source/msg.cpp index 0dd66492ff5..22a7c5dd5aa 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -2191,7 +2191,7 @@ void NetSendCmdNewLvl(BYTE fom, BYTE bLevel) NetSendChunk((BYTE*)&cmd, sizeof(cmd)); } -void NetSendCmdCreateLvl(DWORD seed, BYTE lvl, BYTE type) +void NetSendCmdCreateLvl(int32_t seed, BYTE lvl, BYTE type) { TCmdCreateLvl cmd; diff --git a/Source/msg.h b/Source/msg.h index bbabdaf85ee..0b188f0b840 100644 --- a/Source/msg.h +++ b/Source/msg.h @@ -104,7 +104,7 @@ void NetSendCmdNewLvl(BYTE fom, BYTE bLevel); /** Initiate level creation and change. * @param seed: the seed of the level */ -void NetSendCmdCreateLvl(DWORD seed, BYTE lvl, BYTE type); +void NetSendCmdCreateLvl(int32_t seed, BYTE lvl, BYTE type); void NetSendCmdString(unsigned int pmask); unsigned ParseMsg(int pnum, TCmd* pCmd); unsigned ParseCmd(int pnum, TCmd* pCmd); diff --git a/Source/multi.cpp b/Source/multi.cpp index ab4d1e4244b..c5476984091 100644 --- a/Source/multi.cpp +++ b/Source/multi.cpp @@ -172,7 +172,7 @@ void multi_send_direct_msg(unsigned pmask, const BYTE* pbSrc, BYTE bLen) void multi_rnd_seeds() { int i; - uint32_t seed; + int32_t seed; gdwGameLogicTurn++; if (!IsMultiGame) @@ -743,7 +743,7 @@ void NetClose() static bool multi_init_game(bool bSinglePlayer, _uigamedata& gameData) { int i, dlgresult, pnum; - uint32_t seed; + int32_t seed; while (TRUE) { // mypnum = 0; @@ -818,7 +818,7 @@ static bool multi_init_game(bool bSinglePlayer, _uigamedata& gameData) for (i = 0; i < NUM_FIXLVLS; i++) { seed = NextRndSeed(); - seed = (seed >> 8) | (seed << 24); // _rotr(seed, 8) + seed = ((uint32_t)seed >> 8) | ((uint32_t)seed << 24); // _rotr(seed, 8) glSeedTbl[i] = seed; SetRndSeed(seed); } diff --git a/Source/quests.cpp b/Source/quests.cpp index 56ee9f41024..379a85de862 100644 --- a/Source/quests.cpp +++ b/Source/quests.cpp @@ -12,7 +12,7 @@ DEVILUTION_BEGIN_NAMESPACE #define L3_WATER_PAL "Levels\\L3Data\\L3pwater.pal" /** The pseudo random seeds to generate the levels. */ -uint32_t glSeedTbl[NUM_LEVELS]; +int32_t glSeedTbl[NUM_LEVELS]; /** Contains the informations to recreate the dynamic levels. */ DynLevelStruct gDynLevels[NUM_DYNLVLS]; /** Contains the quests of the current game. */ diff --git a/Source/quests.h b/Source/quests.h index 56b7c847fa1..fd42b72ff41 100644 --- a/Source/quests.h +++ b/Source/quests.h @@ -12,7 +12,7 @@ DEVILUTION_BEGIN_NAMESPACE extern "C" { #endif -extern uint32_t glSeedTbl[NUM_LEVELS]; +extern int32_t glSeedTbl[NUM_LEVELS]; extern DynLevelStruct gDynLevels[NUM_DYNLVLS]; extern BYTE gbTownWarps; extern BYTE gbWaterDone; diff --git a/structs.h b/structs.h index 1074ea4ce2c..02b20662dfb 100644 --- a/structs.h +++ b/structs.h @@ -200,7 +200,7 @@ static_warning((sizeof(ItemData) & (sizeof(ItemData) - 1)) == 0, "Align ItemData #endif typedef struct ItemStruct { - int _iSeed; + int32_t _iSeed; uint16_t _iIdx; // item_indexes uint16_t _iCreateInfo; // icreateinfo_flag union { @@ -743,8 +743,8 @@ typedef struct MonsterStruct { int _mhitpoints; int _mlastx; // the last known (future) tile X-coordinate of the enemy int _mlasty; // the last known (future) tile Y-coordinate of the enemy - int _mRndSeed; - int _mAISeed; + int32_t _mRndSeed; + int32_t _mAISeed; BYTE _muniqtype; BYTE _muniqtrans; BYTE _mNameColor; // color of the tooltip. white: normal, blue: pack; gold: unique. (text_color) @@ -897,7 +897,7 @@ typedef struct ObjectStruct { BYTE _oSelFlag; BOOLEAN _oPreFlag; unsigned _olid; // light id of the object - int _oRndSeed; + int32_t _oRndSeed; int _oVar1; int _oVar2; int _oVar3; @@ -1150,7 +1150,7 @@ typedef struct LSaveGameHeaderStruct { LE_INT32 vhInitial; LE_UINT32 vhLogicTurn; LE_UINT32 vhSentCycle; - LE_UINT32 vhSeeds[NUM_LEVELS]; + LE_INT32 vhSeeds[NUM_LEVELS]; LSaveGameDynLvlStruct vhDynLvls[NUM_DYNLVLS]; LE_INT32 vhCurrSeed; LE_INT32 vhViewX; @@ -1639,7 +1639,7 @@ typedef struct TCmdNewLvl { typedef struct TCmdCreateLvl { BYTE bCmd; BYTE clPlayers; - LE_UINT32 clSeed; + LE_INT32 clSeed; BYTE clLevel; BYTE clType; } TCmdCreateLvl; @@ -2010,9 +2010,9 @@ typedef struct DDLevel { } DDLevel; typedef struct DDDynLevel { - LE_UINT32 dlSeed; // the seed of the dynamic level - BYTE dlLevel; // the difficulty level of the dynamic level - BYTE dlType; // dungeon_type (random in case of DTYPE_TOWN) + LE_INT32 dlSeed; // the seed of the dynamic level + BYTE dlLevel; // the difficulty level of the dynamic level + BYTE dlType; // dungeon_type (random in case of DTYPE_TOWN) } DDDynLevel; typedef struct LocalLevel { @@ -2116,7 +2116,7 @@ typedef struct LevelStruct { int _dLevelIdx; // dungeon_level / NUM_LEVELS int _dLevelNum; // index in AllLevels (dungeon_level / NUM_FIXLVLS) bool _dSetLvl; // cached flag if the level is a set-level - bool _dDynLvl; // cached flag if the level is a dynamic-level + bool _dDynLvl; // cached flag if the level is a dynamic-level int _dLevel; // cached difficulty value of the level int _dType; // cached type of the level (dungeon_type) int _dDunType; // cached type of the dungeon (dungeon_gen_type) @@ -2188,8 +2188,8 @@ typedef struct SetPieceData { ////////////////////////////////////////////////// typedef struct DynLevelStruct { - // uint32_t _dnSeed; -- stored in glSeedTbl - // BYTE _dnPlayers; -- stored in gsDeltaData.ddLevelPlrs + // int32_t _dnSeed; -- stored in glSeedTbl + // BYTE _dnPlayers; -- stored in gsDeltaData.ddLevelPlrs BYTE _dnLevel; BYTE _dnType; } DynLevelStruct; From ac4963f7d07ab71c9d32a35c756f368644433458 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 22 Aug 2024 08:05:14 +0200 Subject: [PATCH 454/596] bugfix for vanilla (rng-seed) - fix the handling of the game-seed: do not truncate when a new seed is requested --- Source/engine.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Source/engine.cpp b/Source/engine.cpp index 50cfe28c19d..846bdffaab2 100644 --- a/Source/engine.cpp +++ b/Source/engine.cpp @@ -129,7 +129,12 @@ int32_t NextRndSeed() SeedCount++; #endif sglGameSeed = RndMult * static_cast(sglGameSeed) + RndInc; - return abs(sglGameSeed); + return sglGameSeed; +} + +static unsigned NextRndValue() +{ + return abs(NextRndSeed()); } /** @@ -143,8 +148,8 @@ int random_(BYTE idx, int v) if (v <= 0) return 0; if (v < 0x7FFF) - return (((unsigned)NextRndSeed()) >> 16) % v; - return ((unsigned)NextRndSeed()) % v; + return ((NextRndValue()) >> 16) % v; + return (NextRndValue()) % v; } /** @@ -157,7 +162,7 @@ int random_low(BYTE idx, int v) { // assert(v > 0); // assert(v < 0x7FFF); - return (((unsigned)NextRndSeed()) >> 16) % v; + return ((NextRndValue()) >> 16) % v; } /** From 6d3621215541c1fa9a41134960ed17f487a324c2 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 22 Aug 2024 08:10:10 +0200 Subject: [PATCH 455/596] 'bugfix' for vanilla (theme-room placement) - skip only the necessary length after a theme-room is added --- Source/gendung.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/gendung.cpp b/Source/gendung.cpp index f594d796ebd..2d515d93819 100644 --- a/Source/gendung.cpp +++ b/Source/gendung.cpp @@ -1552,7 +1552,7 @@ void DRLG_PlaceThemeRooms(int minSize, int maxSize, const BYTE (&themeTiles)[NUM return; } - j += tArea.x + 2; + j += tArea.y; } } } From fba8608a75793dc9d3afee1d196ba8c8bb777393 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 23 Aug 2024 08:42:02 +0200 Subject: [PATCH 456/596] get rid of the rndSize parameter of DRLG_PlaceThemeRooms - use rndSkip instead of rndSize to randomize the size of the theme-room --- Source/drlg_l2.cpp | 2 +- Source/drlg_l3.cpp | 2 +- Source/drlg_l4.cpp | 2 +- Source/gendung.cpp | 4 ++-- Source/gendung.h | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/drlg_l2.cpp b/Source/drlg_l2.cpp index 9e0f9bcd661..03a1861c8e9 100644 --- a/Source/drlg_l2.cpp +++ b/Source/drlg_l2.cpp @@ -2383,7 +2383,7 @@ static void DRLG_L2() L2LockoutFix(); // L2DoorFix(); - commented out, because this is no longer necessary - DRLG_PlaceThemeRooms(6, 10, themeTiles, 0, false); + DRLG_PlaceThemeRooms(6, 10, themeTiles, 0); L2CreateArches(); // L2DoorFix2(); - commented out, because there is not much point to do this after L2CreateArches diff --git a/Source/drlg_l3.cpp b/Source/drlg_l3.cpp index a808a25a3f7..eaa9a4b6f67 100644 --- a/Source/drlg_l3.cpp +++ b/Source/drlg_l3.cpp @@ -2550,7 +2550,7 @@ static void DRLG_L3() // assert(currLvl._dType == DTYPE_CAVES); FixL3HallofHeroes(); DRLG_L3River(); - DRLG_PlaceThemeRooms(5, 10, themeTiles, 0, false); + DRLG_PlaceThemeRooms(5, 10, themeTiles, 0); DRLG_L3Wood(); //DRLG_L3PlaceRndSet(L3LTITE1, 20); - commented out because of a graphical glitch diff --git a/Source/drlg_l4.cpp b/Source/drlg_l4.cpp index a7ef7a05449..021b32bd763 100644 --- a/Source/drlg_l4.cpp +++ b/Source/drlg_l4.cpp @@ -2078,7 +2078,7 @@ static void DRLG_L4() // DRLG_L4GeneralFix(); - commented out, because this is no longer necessary if (currLvl._dLevelIdx != DLV_HELL4) { - DRLG_PlaceThemeRooms(7, 10, themeTiles, 112, true); + DRLG_PlaceThemeRooms(7, 10, themeTiles, 112); DRLG_L4ThemeExitFix(); } diff --git a/Source/gendung.cpp b/Source/gendung.cpp index 2d515d93819..457d970d540 100644 --- a/Source/gendung.cpp +++ b/Source/gendung.cpp @@ -1511,7 +1511,7 @@ static void DRLG_CreateThemeRoom(int themeIndex, const BYTE (&themeTiles)[NUM_DR } } -void DRLG_PlaceThemeRooms(int minSize, int maxSize, const BYTE (&themeTiles)[NUM_DRT_TYPES], int rndSkip, bool rndSize) +void DRLG_PlaceThemeRooms(int minSize, int maxSize, const BYTE (&themeTiles)[NUM_DRT_TYPES], int rndSkip) { int i, j; int min; @@ -1531,7 +1531,7 @@ void DRLG_PlaceThemeRooms(int minSize, int maxSize, const BYTE (&themeTiles)[NUM continue; } // randomize the size - if (rndSize) { + if (rndSkip) { // assert(minSize > 2); min = minSize - 2; static_assert(DMAXX /* - minSize */ + 2 < 0x7FFF, "DRLG_PlaceThemeRooms uses RandRangeLow to set themeW."); diff --git a/Source/gendung.h b/Source/gendung.h index b4ee9bc6096..d3824b77f04 100644 --- a/Source/gendung.h +++ b/Source/gendung.h @@ -63,7 +63,7 @@ void DRLG_RedoTrans(); //void DRLG_AreaTrans(int num, const BYTE* List); void DRLG_FloodTVal(); void DRLG_LoadSP(int idx, BYTE bv); -void DRLG_PlaceThemeRooms(int minSize, int maxSize, const BYTE (&themeTiles)[NUM_DRT_TYPES], int rndSkip, bool rndSize); +void DRLG_PlaceThemeRooms(int minSize, int maxSize, const BYTE (&themeTiles)[NUM_DRT_TYPES], int rndSkip); bool InThemeRoom(int x, int y); void DRLG_ChangeMap(int x1, int y1, int x2, int y2 /*, bool hasNewObjPiece*/); From bb2f5bd2eae2adb6881130ff14b12ea5615c5691 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 23 Aug 2024 17:19:57 +0200 Subject: [PATCH 457/596] limit the size of the theme-rooms in cathedral the same way as everywhere else --- Source/drlg_l1.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/drlg_l1.cpp b/Source/drlg_l1.cpp index 203ac7cc2af..e5dbf287e13 100644 --- a/Source/drlg_l1.cpp +++ b/Source/drlg_l1.cpp @@ -1978,7 +1978,7 @@ static void DRLG_L1PlaceThemeRooms() // create the room int w = (roomRight + 1) - (roomLeft - 1) + 1; int h = (roomBottom + 1) - (roomTop - 1) + 1; - if (w * h > 100) + if (w > 10 - 2 || h > 10 - 2) continue; // room is too large themes[numthemes]._tsx1 = roomLeft - 1; themes[numthemes]._tsy1 = roomTop - 1; From 3fc45a20a0c9654cacbf50069d90327d77f2ee74 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 23 Aug 2024 17:26:18 +0200 Subject: [PATCH 458/596] use unsigned division in L1RoomGen --- Source/drlg_l1.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/drlg_l1.cpp b/Source/drlg_l1.cpp index e5dbf287e13..7edd5305a25 100644 --- a/Source/drlg_l1.cpp +++ b/Source/drlg_l1.cpp @@ -1107,7 +1107,7 @@ static void L1RoomGen(int x, int y, int w, int h, bool dir) for (i = 20; i != 0; i--) { width = RandRange(2, 6) & ~1; height = RandRange(2, 6) & ~1; - ry = h / 2 + y - height / 2; + ry = h / 2u + y - height / 2u; rx = x - width; if (L1CheckVHall(x, ry - 1, height + 2) && L1CheckRoom(rx - 1, ry - 1, width + 1, height + 2)) // BUGFIX: swap args 3 and 4 ("height+2" and "width+1") (fixed) @@ -1133,7 +1133,7 @@ static void L1RoomGen(int x, int y, int w, int h, bool dir) for (i = 20; i != 0; i--) { width = RandRange(2, 6) & ~1; height = RandRange(2, 6) & ~1; - rx = w / 2 + x - width / 2; + rx = w / 2u + x - width / 2u; ry = y - height; if (L1CheckHHall(y, rx - 1, width + 2) && L1CheckRoom(rx - 1, ry - 1, width + 2, height + 1)) From 0373061e60a3e2d1c5e5e8541d38b478476cf6de Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 23 Aug 2024 17:29:27 +0200 Subject: [PATCH 459/596] optimize chamber-selection in cathedral - select all chambers when none of the chamber would be selected by random (a single central chamber has a low chance of success) - use a single random to select the chambers --- Source/drlg_l1.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Source/drlg_l1.cpp b/Source/drlg_l1.cpp index 7edd5305a25..0a8055a7890 100644 --- a/Source/drlg_l1.cpp +++ b/Source/drlg_l1.cpp @@ -1167,10 +1167,16 @@ static void DRLG_L1CreateDungeon() nRoomCnt = 0; ChambersVertical = random_(0, 2); - ChambersFirst = random_(0, 2); - ChambersMiddle = random_(0, 2); - ChambersLast = random_(0, 2); - // make sure there is at least one chamber + prevent standalone first/last chambers + // select the base chambers + i = random_(0, 8); + // make sure at least one chamber is selected + // (prefer complete selection over a single chamber to increase the chance of success) + if (i == 0) + i = 7; + ChambersFirst = (i & 1) ? TRUE : FALSE; + ChambersMiddle = (i & 2) ? TRUE : FALSE; + ChambersLast = (i & 4) ? TRUE : FALSE; + // prevent standalone first/last chambers if (!(ChambersFirst & ChambersLast)) ChambersMiddle = TRUE; if (ChambersVertical) { From d74025f89059e6f5e4aec35efa4fc28ebb8c185f Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 23 Aug 2024 17:35:21 +0200 Subject: [PATCH 460/596] add an alternative DRLG_L1GetArea-implementation - turned off for the moment, because it does not matter too much --- Source/drlg_l1.cpp | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/Source/drlg_l1.cpp b/Source/drlg_l1.cpp index 0a8055a7890..bc90a602da9 100644 --- a/Source/drlg_l1.cpp +++ b/Source/drlg_l1.cpp @@ -1115,13 +1115,13 @@ static void L1RoomGen(int x, int y, int w, int h, bool dir) } if (i != 0) - L1DrawRoom(rx, ry, width, height); + L1DrawRoom(rx, ry, width, height); // try to place a room to the right - rxy2 = x + w; + rxy2 = x + w; ran2 = L1CheckVHall(rxy2 - 1, ry - 1, height + 2) && L1CheckRoom(rxy2, ry - 1, width + 1, height + 2); if (ran2) - L1DrawRoom(rxy2, ry, width, height); + L1DrawRoom(rxy2, ry, width, height); // proceed with the placed a room on the left if (i != 0) L1RoomGen(rx, ry, width, height, true); @@ -1141,13 +1141,13 @@ static void L1RoomGen(int x, int y, int w, int h, bool dir) } if (i != 0) - L1DrawRoom(rx, ry, width, height); + L1DrawRoom(rx, ry, width, height); // try to place a room to the bottom - rxy2 = y + h; + rxy2 = y + h; ran2 = L1CheckHHall(rxy2 - 1, rx - 1, width + 2) && L1CheckRoom(rx - 1, rxy2, width + 2, height + 1); if (ran2) - L1DrawRoom(rx, rxy2, width, height); + L1DrawRoom(rx, rxy2, width, height); // proceed with the placed a room on the top if (i != 0) L1RoomGen(rx, ry, width, height, false); @@ -1252,16 +1252,29 @@ static void DRLG_L1CreateDungeon() static int DRLG_L1GetArea() { int i, rv; +#if 1 BYTE* pTmp; rv = 0; static_assert(sizeof(dungeon) == DMAXX * DMAXY, "Linear traverse of dungeon does not work in DRLG_L1GetArea."); pTmp = &dungeon[0][0]; for (i = 0; i < DMAXX * DMAXY; i++, pTmp++) { - assert(*pTmp <= 1); + // assert(*pTmp <= 1); rv += *pTmp; } - +#else + rv = 0; + for (i = 0; i < nRoomCnt; i++) { + rv += drlg.L1RoomList[i].lrw * drlg.L1RoomList[i].lrh; + } + if (ChambersFirst + ChambersMiddle + ChambersLast == 3) { + rv += 6 * 4 * 2; + } else if (ChambersFirst + ChambersMiddle + ChambersLast == 2) { + rv += 6 * 4; + if (!ChambersMiddle) + rv += 6 * 4 + CHAMBER_SIZE * 6; + } +#endif return rv; } From 8beb29c055259161d358bc02eab7b731725d9743 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 23 Aug 2024 17:37:48 +0200 Subject: [PATCH 461/596] limit the maximum size of the dungeon in DLV_CATHEDRAL1/2 (probably as it was intended) --- Source/drlg_l1.cpp | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/Source/drlg_l1.cpp b/Source/drlg_l1.cpp index bc90a602da9..5b3e11f6f9d 100644 --- a/Source/drlg_l1.cpp +++ b/Source/drlg_l1.cpp @@ -2635,26 +2635,22 @@ void DRLG_L1InitTransVals() static void DRLG_L1() { int i; - int minarea; + int areaidx; bool placeWater = QuestStatus(Q_PWATER); - - switch (currLvl._dLevelIdx) { - case DLV_CATHEDRAL1: - minarea = 533; - break; - case DLV_CATHEDRAL2: - minarea = 693; - break; - default: - minarea = 761; - break; + const int arealimits[] = { DMAXX * DMAXY, 761, 693, 533 }; + areaidx = 0; + if (currLvl._dLevelIdx == DLV_CATHEDRAL1) { + areaidx = 2; + } else if (currLvl._dLevelIdx == DLV_CATHEDRAL2) { + areaidx = 1; } while (true) { do { memset(dungeon, 0, sizeof(dungeon)); DRLG_L1CreateDungeon(); - } while (DRLG_L1GetArea() < minarea); + i = DRLG_L1GetArea(); + } while (i > arealimits[areaidx] || i < arealimits[areaidx + 1]); DRLG_L1MakeMegas(); L1TileFix(); From 4207331b9e609f763c555b94dae6ac29ba643731 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 24 Aug 2024 08:06:33 +0200 Subject: [PATCH 462/596] fix bias in L1RoomGen --- Source/drlg_l1.cpp | 96 ++++++++++++++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 34 deletions(-) diff --git a/Source/drlg_l1.cpp b/Source/drlg_l1.cpp index 5b3e11f6f9d..b3e4ca356f3 100644 --- a/Source/drlg_l1.cpp +++ b/Source/drlg_l1.cpp @@ -1113,20 +1113,34 @@ static void L1RoomGen(int x, int y, int w, int h, bool dir) && L1CheckRoom(rx - 1, ry - 1, width + 1, height + 2)) // BUGFIX: swap args 3 and 4 ("height+2" and "width+1") (fixed) break; } - - if (i != 0) - L1DrawRoom(rx, ry, width, height); + // - add room to the left + if (i != 0) { + L1DrawRoom(rx, ry, width, height); + i = 1; + } else { + rx = -1; + i = 20; + } // try to place a room to the right - rxy2 = x + w; - ran2 = L1CheckVHall(rxy2 - 1, ry - 1, height + 2) - && L1CheckRoom(rxy2, ry - 1, width + 1, height + 2); - if (ran2) - L1DrawRoom(rxy2, ry, width, height); - // proceed with the placed a room on the left + rxy2 = x + w; + while (true) { + if (L1CheckVHall(rxy2 - 1, ry - 1, height + 2) + && L1CheckRoom(rxy2, ry - 1, width + 1, height + 2)) + break; + if (--i == 0) + break; + width = RandRange(2, 6) & ~1; + height = RandRange(2, 6) & ~1; + ry = h / 2u + y - height / 2u; + } + // - add room to the right if (i != 0) + L1DrawRoom(rxy2, ry, width, height); + // proceed with the placed a room on the left + if (rx >= 0) L1RoomGen(rx, ry, width, height, true); // proceed with the placed a room on the right - if (ran2) + if (i != 0) L1RoomGen(rxy2, ry, width, height, true); } else { // try to place a room to the top @@ -1139,20 +1153,34 @@ static void L1RoomGen(int x, int y, int w, int h, bool dir) && L1CheckRoom(rx - 1, ry - 1, width + 2, height + 1)) break; } - - if (i != 0) - L1DrawRoom(rx, ry, width, height); + // - add room to the top + if (i != 0) { + L1DrawRoom(rx, ry, width, height); + i = 1; + } else { + ry = -1; + i = 20; + } // try to place a room to the bottom - rxy2 = y + h; - ran2 = L1CheckHHall(rxy2 - 1, rx - 1, width + 2) - && L1CheckRoom(rx - 1, rxy2, width + 2, height + 1); - if (ran2) - L1DrawRoom(rx, rxy2, width, height); - // proceed with the placed a room on the top + rxy2 = y + h; + while (true) { + if (L1CheckHHall(rxy2 - 1, rx - 1, width + 2) + && L1CheckRoom(rx - 1, rxy2, width + 2, height + 1)) + break; + if (--i == 0) + break; + width = RandRange(2, 6) & ~1; + height = RandRange(2, 6) & ~1; + rx = w / 2u + x - width / 2u; + } + // - add room to the bottom if (i != 0) + L1DrawRoom(rx, rxy2, width, height); + // proceed with the placed a room on the top + if (ry >= 0) L1RoomGen(rx, ry, width, height, false); // proceed with the placed a room on the bottom - if (ran2) + if (i != 0) L1RoomGen(rx, rxy2, width, height, false); } } @@ -1170,11 +1198,11 @@ static void DRLG_L1CreateDungeon() // select the base chambers i = random_(0, 8); // make sure at least one chamber is selected - // (prefer complete selection over a single chamber to increase the chance of success) - if (i == 0) - i = 7; - ChambersFirst = (i & 1) ? TRUE : FALSE; - ChambersMiddle = (i & 2) ? TRUE : FALSE; + // (prefer complete selection over a single chamber to increase the chance of success) + if (i == 0) + i = 7; + ChambersFirst = (i & 1) ? TRUE : FALSE; + ChambersMiddle = (i & 2) ? TRUE : FALSE; ChambersLast = (i & 4) ? TRUE : FALSE; // prevent standalone first/last chambers if (!(ChambersFirst & ChambersLast)) @@ -1266,14 +1294,14 @@ static int DRLG_L1GetArea() rv = 0; for (i = 0; i < nRoomCnt; i++) { rv += drlg.L1RoomList[i].lrw * drlg.L1RoomList[i].lrh; - } + } if (ChambersFirst + ChambersMiddle + ChambersLast == 3) { rv += 6 * 4 * 2; } else if (ChambersFirst + ChambersMiddle + ChambersLast == 2) { - rv += 6 * 4; - if (!ChambersMiddle) + rv += 6 * 4; + if (!ChambersMiddle) rv += 6 * 4 + CHAMBER_SIZE * 6; - } + } #endif return rv; } @@ -2637,12 +2665,12 @@ static void DRLG_L1() int i; int areaidx; bool placeWater = QuestStatus(Q_PWATER); - const int arealimits[] = { DMAXX * DMAXY, 761, 693, 533 }; - areaidx = 0; - if (currLvl._dLevelIdx == DLV_CATHEDRAL1) { + const int arealimits[] = { DMAXX * DMAXY, 761, 693, 533 }; + areaidx = 0; + if (currLvl._dLevelIdx == DLV_CATHEDRAL1) { areaidx = 2; - } else if (currLvl._dLevelIdx == DLV_CATHEDRAL2) { - areaidx = 1; + } else if (currLvl._dLevelIdx == DLV_CATHEDRAL2) { + areaidx = 1; } while (true) { From 842f9b6a9df0e12d738f4266a3e215bbb9bd8562 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 24 Aug 2024 08:11:23 +0200 Subject: [PATCH 463/596] decrease the size of the arrays in DRLG_FitThemeRoom --- Source/gendung.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/gendung.cpp b/Source/gendung.cpp index 457d970d540..6bd9d0f021c 100644 --- a/Source/gendung.cpp +++ b/Source/gendung.cpp @@ -1402,10 +1402,10 @@ void InitLvlMap() static POS32 DRLG_FitThemeRoom(BYTE floor, int x, int y, int minSize, int maxSize) { int xmax, ymax, i, j, smallest; - int xArray[20], yArray[20]; + int xArray[16], yArray[16]; int size, bestSize, w, h; - // assert(maxSize < 20); + // assert(maxSize < 16); xmax = std::min(maxSize, DMAXX - x); ymax = std::min(maxSize, DMAXY - y); From d26f970485b0ae83c3b6dd610f3691aed1e9c12e Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 24 Aug 2024 08:13:48 +0200 Subject: [PATCH 464/596] add (RECT_)AREA32 structs and use AREA32 in DRLG_PlaceThemeRooms --- Source/gendung.cpp | 16 ++++++++-------- structs.h | 12 ++++++++++++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/Source/gendung.cpp b/Source/gendung.cpp index 6bd9d0f021c..2870c06975d 100644 --- a/Source/gendung.cpp +++ b/Source/gendung.cpp @@ -1399,7 +1399,7 @@ void InitLvlMap() * @param maxSize the maximum size of the room (must be less than 20) * @return the size of the room */ -static POS32 DRLG_FitThemeRoom(BYTE floor, int x, int y, int minSize, int maxSize) +static AREA32 DRLG_FitThemeRoom(BYTE floor, int x, int y, int minSize, int maxSize) { int xmax, ymax, i, j, smallest; int xArray[16], yArray[16]; @@ -1526,8 +1526,8 @@ void DRLG_PlaceThemeRooms(int minSize, int maxSize, const BYTE (&themeTiles)[NUM continue; } // check if there is enough space - POS32 tArea = DRLG_FitThemeRoom(themeTiles[DRT_FLOOR], i, j, minSize, maxSize); - if (tArea.x <= 0) { + AREA32 tArea = DRLG_FitThemeRoom(themeTiles[DRT_FLOOR], i, j, minSize, maxSize); + if (tArea.w <= 0) { continue; } // randomize the size @@ -1536,23 +1536,23 @@ void DRLG_PlaceThemeRooms(int minSize, int maxSize, const BYTE (&themeTiles)[NUM min = minSize - 2; static_assert(DMAXX /* - minSize */ + 2 < 0x7FFF, "DRLG_PlaceThemeRooms uses RandRangeLow to set themeW."); static_assert(DMAXY /* - minSize */ + 2 < 0x7FFF, "DRLG_PlaceThemeRooms uses RandRangeLow to set themeH."); - tArea.x = RandRangeLow(min, tArea.x); - tArea.y = RandRangeLow(min, tArea.y); + tArea.w = RandRangeLow(min, tArea.w); + tArea.h = RandRangeLow(min, tArea.h); } // ensure there is no overlapping with previous themes if (!InThemeRoom(i + 1, j + 1)) { // create the room themes[numthemes]._tsx1 = i + 1; themes[numthemes]._tsy1 = j + 1; - themes[numthemes]._tsx2 = i + 1 + tArea.x - 1; - themes[numthemes]._tsy2 = j + 1 + tArea.y - 1; + themes[numthemes]._tsx2 = i + 1 + tArea.w - 1; + themes[numthemes]._tsy2 = j + 1 + tArea.h - 1; DRLG_CreateThemeRoom(numthemes, themeTiles); numthemes++; if (numthemes == lengthof(themes)) return; } - j += tArea.y; + j += tArea.h; } } } diff --git a/structs.h b/structs.h index 02b20662dfb..743d0066266 100644 --- a/structs.h +++ b/structs.h @@ -80,6 +80,11 @@ typedef struct POS32 { int y; } POS32; +typedef struct AREA32 { + int w; + int h; +} AREA32; + typedef struct RECT32 { int x; int y; @@ -87,6 +92,13 @@ typedef struct RECT32 { int h; } RECT32; +typedef struct RECT_AREA32 { + int x1; + int y1; + int x2; + int y2; +} RECT_AREA32; + typedef struct CelImageBuf { #if DEBUG_MODE WORD ciWidth; // number of images before loaded, but overwritten with width when loaded From ddb1fede2c668a1ca81b53f9788d2a3321a28125 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 24 Aug 2024 08:27:45 +0200 Subject: [PATCH 465/596] return bool from DRLG_FitThemeRoom --- Source/gendung.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Source/gendung.cpp b/Source/gendung.cpp index 2870c06975d..8424469e539 100644 --- a/Source/gendung.cpp +++ b/Source/gendung.cpp @@ -1397,9 +1397,10 @@ void InitLvlMap() * @param y the y-coordinate of the starting position * @param minSize the minimum size of the room (must be less than 20) * @param maxSize the maximum size of the room (must be less than 20) - * @return the size of the room + * @param room the w/h of the room if found + * @return whether a fitting room was found */ -static AREA32 DRLG_FitThemeRoom(BYTE floor, int x, int y, int minSize, int maxSize) +static bool DRLG_FitThemeRoom(BYTE floor, int x, int y, int minSize, int maxSize, AREA32 &room) { int xmax, ymax, i, j, smallest; int xArray[16], yArray[16]; @@ -1411,7 +1412,7 @@ static AREA32 DRLG_FitThemeRoom(BYTE floor, int x, int y, int minSize, int maxSi ymax = std::min(maxSize, DMAXY - y); // BUGFIX: change '&&' to '||' (fixed) if (xmax < minSize || ymax < minSize) - return { 0, 0 }; + return false; memset(xArray, 0, sizeof(xArray)); memset(yArray, 0, sizeof(yArray)); @@ -1430,7 +1431,7 @@ static AREA32 DRLG_FitThemeRoom(BYTE floor, int x, int y, int minSize, int maxSi xArray[++i] = smallest; } if (i < minSize) - return { 0, 0 }; + return false; // find vertical(y) limits smallest = ymax; @@ -1446,7 +1447,7 @@ static AREA32 DRLG_FitThemeRoom(BYTE floor, int x, int y, int minSize, int maxSi yArray[++i] = smallest; } if (i < minSize) - return { 0, 0 }; + return false; // select the best option xmax = std::max(xmax, ymax); @@ -1466,7 +1467,9 @@ static AREA32 DRLG_FitThemeRoom(BYTE floor, int x, int y, int minSize, int maxSi } } assert(bestSize != 0); - return { w - 2, h - 2 }; + room.w = w - 2; + room.h = h - 2; + return true; } static void DRLG_CreateThemeRoom(int themeIndex, const BYTE (&themeTiles)[NUM_DRT_TYPES]) @@ -1526,8 +1529,8 @@ void DRLG_PlaceThemeRooms(int minSize, int maxSize, const BYTE (&themeTiles)[NUM continue; } // check if there is enough space - AREA32 tArea = DRLG_FitThemeRoom(themeTiles[DRT_FLOOR], i, j, minSize, maxSize); - if (tArea.w <= 0) { + AREA32 tArea; + if (!DRLG_FitThemeRoom(themeTiles[DRT_FLOOR], i, j, minSize, maxSize, tArea)) { continue; } // randomize the size From 7d2d4e3d2ae111031b56ab2f2a49609ca373c5c0 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 24 Aug 2024 08:44:33 +0200 Subject: [PATCH 466/596] limit the number of theme-rooms in cathedral (and everywhere else) to 8 --- Source/drlg_l1.cpp | 33 +++++++++++++++++++++++++-------- Source/gendung.cpp | 2 +- defs.h | 2 +- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/Source/drlg_l1.cpp b/Source/drlg_l1.cpp index b3e4ca356f3..ab3e837efc9 100644 --- a/Source/drlg_l1.cpp +++ b/Source/drlg_l1.cpp @@ -1969,7 +1969,9 @@ static void L1TileFix() static void DRLG_L1PlaceThemeRooms() { - for (int i = ChambersFirst + ChambersMiddle + ChambersLast; i < nRoomCnt; i++) { + RECT_AREA32 thops[32]; + int i, numops = 0; + for (i = ChambersFirst + ChambersMiddle + ChambersLast; i < nRoomCnt; i++) { int roomLeft = drlg.L1RoomList[i].lrx; int roomRight = roomLeft + drlg.L1RoomList[i].lrw - 1; int roomTop = drlg.L1RoomList[i].lry; @@ -2027,14 +2029,29 @@ static void DRLG_L1PlaceThemeRooms() int h = (roomBottom + 1) - (roomTop - 1) + 1; if (w > 10 - 2 || h > 10 - 2) continue; // room is too large - themes[numthemes]._tsx1 = roomLeft - 1; - themes[numthemes]._tsy1 = roomTop - 1; - themes[numthemes]._tsx2 = roomLeft - 1 + w - 1; - themes[numthemes]._tsy2 = roomTop - 1 + h - 1; - numthemes++; - if (numthemes == lengthof(themes)) - break; + // register the room + thops[numops].x1 = roomLeft - 1; + thops[numops].y1 = roomTop - 1; + thops[numops].x2 = roomLeft - 1 + w - 1; + thops[numops].y2 = roomTop - 1 + h - 1; + numops++; + if (numops == lengthof(thops)) + break; // should not happen (too often), otherwise the theme-placement is biased + } + // filter the rooms + while (numops > lengthof(themes)) { + i = random_low(0, numops); + --numops; + thops[i] = thops[numops]; + } + // add the rooms + for (i = 0; i < numops; i++) { + themes[i]._tsx1 = thops[i].x1; + themes[i]._tsy1 = thops[i].y1; + themes[i]._tsx2 = thops[i].x2; + themes[i]._tsy2 = thops[i].y2; } + numthemes = numops; } #ifdef HELLFIRE diff --git a/Source/gendung.cpp b/Source/gendung.cpp index 8424469e539..79e04e3d5e2 100644 --- a/Source/gendung.cpp +++ b/Source/gendung.cpp @@ -1552,7 +1552,7 @@ void DRLG_PlaceThemeRooms(int minSize, int maxSize, const BYTE (&themeTiles)[NUM DRLG_CreateThemeRoom(numthemes, themeTiles); numthemes++; if (numthemes == lengthof(themes)) - return; + break; // should not happen (too often), otherwise the theme-placement is biased } j += tArea.h; diff --git a/defs.h b/defs.h index 14f4f726d3c..07221e8fbe3 100644 --- a/defs.h +++ b/defs.h @@ -111,7 +111,7 @@ static_assert(DMAXY % 2 == 0, "DRLG_L4 constructs the dungeon by mirroring a qua #define MAXOBJECTS 127 #define OBJ_NONE 0xFF #define MAXPORTAL MAX_PLRS -#define MAXTHEMES 32 +#define MAXTHEMES 8 #define MAXTILES 255 #define MAXSUBTILES 1023 #define MAXVISION (MAX_PLRS + MAX_MINIONS) From 547bb1ca32940b982dcd67a7ceb79f7954f70d48 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 24 Aug 2024 08:53:05 +0200 Subject: [PATCH 467/596] use int fields in L1ROOM and ensure L1RoomList is large enough --- Source/drlg_l1.cpp | 2 +- structs.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/drlg_l1.cpp b/Source/drlg_l1.cpp index ab3e837efc9..da5c708178c 100644 --- a/Source/drlg_l1.cpp +++ b/Source/drlg_l1.cpp @@ -1098,7 +1098,7 @@ static bool L1CheckHHall(int y, int left, int w) static void L1RoomGen(int x, int y, int w, int h, bool dir) { int dirProb, i, width, height, rx, ry, rxy2; - bool ran2; + static_assert((DMAXX * DMAXY - (CHAMBER_SIZE + 2) * (CHAMBER_SIZE + 2) + 4) / (2 * 2) <= lengthof(drlg.L1RoomList), "L1RoomGen skips limit checks assuming enough L1RoomList entries."); dirProb = random_(0, 4); diff --git a/structs.h b/structs.h index 743d0066266..41ca72cd6f0 100644 --- a/structs.h +++ b/structs.h @@ -2336,10 +2336,10 @@ typedef struct ROOMHALLNODE { } ROOMHALLNODE; typedef struct L1ROOM { - BYTE lrx; - BYTE lry; - BYTE lrw; - BYTE lrh; + int lrx; + int lry; + int lrw; + int lrh; } L1ROOM; typedef struct ThemePosDir { From 67c0e488fa301f94ac723e8cbd1656ffb20ad7b5 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 24 Aug 2024 09:00:14 +0200 Subject: [PATCH 468/596] use int fields in ThemePosDir and ensure thLocs is large enough --- Source/gendung.cpp | 2 +- Source/themes.cpp | 10 +++++++--- structs.h | 8 ++++---- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Source/gendung.cpp b/Source/gendung.cpp index 79e04e3d5e2..21c85f8f33c 100644 --- a/Source/gendung.cpp +++ b/Source/gendung.cpp @@ -1518,7 +1518,7 @@ void DRLG_PlaceThemeRooms(int minSize, int maxSize, const BYTE (&themeTiles)[NUM { int i, j; int min; - + // assert((maxSize - 2) * (maxSize - 2) <= lengthof(drlg.thLocs)); for (i = 0; i < DMAXX; i++) { for (j = 0; j < DMAXY; j++) { // always start from a floor tile diff --git a/Source/themes.cpp b/Source/themes.cpp index ff71f9acbc6..27c954519a2 100644 --- a/Source/themes.cpp +++ b/Source/themes.cpp @@ -81,6 +81,7 @@ static int TFit_Shrine(int themeId) drlg.thLocs[numMatches].tpdvar1 = 1; drlg.thLocs[numMatches].tpdvar2 = 0; numMatches++; + static_assert(lengthof(drlg.thLocs) >= (10 - 2 - (1 + 1)) * (10 - 2 - (1 + 1)), "TFit_Shrine skips limit checks assuming enough thLocs entries I."); // if (numMatches == lengthof(drlg.thLocs)) // goto done; } @@ -103,6 +104,7 @@ static int TFit_Shrine(int themeId) drlg.thLocs[numMatches].tpdvar1 = 0; drlg.thLocs[numMatches].tpdvar2 = 0; numMatches++; + static_assert(lengthof(drlg.thLocs) >= (10 - 2 - (1 + 1)) * (10 - 2 - (1 + 1)), "TFit_Shrine skips limit checks assuming enough thLocs entries II."); // if (numMatches == lengthof(drlg.thLocs)) // goto done; } @@ -112,7 +114,7 @@ static int TFit_Shrine(int themeId) // done: if (numMatches == 0) return -1; - // static_assert(lengthof(drlg.thLocs) < 0x7FFF); + static_assert(lengthof(drlg.thLocs) < 0x7FFF, "TFit_Shrine uses random_low to select a matching location."); return random_low(0, numMatches); } @@ -140,6 +142,7 @@ static int TFit_Obj5(int themeId) drlg.thLocs[numMatches].tpdvar1 = 0; drlg.thLocs[numMatches].tpdvar2 = 0; numMatches++; + static_assert(lengthof(drlg.thLocs) >= (10 - 2 - (3 + 3)) * (10 - 2 - (3 + 3)), "TFit_Obj5 skips limit checks assuming enough thLocs entries II."); // if (numMatches == lengthof(drlg.thLocs)) // goto done; } @@ -149,7 +152,7 @@ static int TFit_Obj5(int themeId) // done: if (numMatches == 0) return -1; - // static_assert(lengthof(drlg.thLocs) < 0x7FFF); + static_assert(lengthof(drlg.thLocs) < 0x7FFF, "TFit_Obj5 uses random_low to select a matching location."); return random_low(0, numMatches); } @@ -186,6 +189,7 @@ static int TFit_Obj3(int themeId) drlg.thLocs[numMatches].tpdvar1 = 0; drlg.thLocs[numMatches].tpdvar2 = 0; numMatches++; + static_assert(lengthof(drlg.thLocs) >= (10 - 2 - (2 + 2)) * (10 - 2 - (2 + 2)), "TFit_Obj3 skips limit checks assuming enough thLocs entries II."); // if (numMatches == lengthof(drlg.thLocs)) // goto done; } @@ -194,7 +198,7 @@ static int TFit_Obj3(int themeId) // done: if (numMatches == 0) return -1; - // static_assert(lengthof(drlg.thLocs) < 0x7FFF); + static_assert(lengthof(drlg.thLocs) < 0x7FFF, "TFit_Obj3 uses random_low to select a matching location."); return random_low(0, numMatches); } diff --git a/structs.h b/structs.h index 41ca72cd6f0..50032bff05d 100644 --- a/structs.h +++ b/structs.h @@ -2343,10 +2343,10 @@ typedef struct L1ROOM { } L1ROOM; typedef struct ThemePosDir { - BYTE tpdx; - BYTE tpdy; - BYTE tpdvar1; - BYTE tpdvar2; // unused + int tpdx; + int tpdy; + int tpdvar1; + int tpdvar2; // unused } ThemePosDir; /** The number of generated rooms in cathedral. */ From 54e3cdce86da052e9dafdfec1644a709c17628f9 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 24 Aug 2024 09:14:26 +0200 Subject: [PATCH 469/596] get rid of placeWater in DRLG_L1 --- Source/drlg_l1.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/drlg_l1.cpp b/Source/drlg_l1.cpp index da5c708178c..f6a51560206 100644 --- a/Source/drlg_l1.cpp +++ b/Source/drlg_l1.cpp @@ -2681,7 +2681,7 @@ static void DRLG_L1() { int i; int areaidx; - bool placeWater = QuestStatus(Q_PWATER); + // bool placeWater = QuestStatus(Q_PWATER); const int arealimits[] = { DMAXX * DMAXY, 761, 693, 533 }; areaidx = 0; if (currLvl._dLevelIdx == DLV_CATHEDRAL1) { @@ -2719,7 +2719,7 @@ static void DRLG_L1() pWarps[DWARP_ENTRY]._wtype = WRPT_CIRCLE; break; } - if (placeWater) { + if (QuestStatus(Q_PWATER)) { POS32 warpPos = DRLG_PlaceMiniSet(PWATERIN); if (warpPos.x < 0) { continue; From 8fd1645060b1c3d0827f94c10074069c9e0bbc88 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 24 Aug 2024 09:15:26 +0200 Subject: [PATCH 470/596] cosmetic adjustments --- Source/control.cpp | 4 ++-- Source/drlg_l1.cpp | 4 ++-- Source/engine.cpp | 6 +++--- Source/gendung.cpp | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/control.cpp b/Source/control.cpp index 2b88ec31878..0609d715ccb 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -1883,7 +1883,7 @@ void ReleaseChrBtn() } /** - * @brief Draw a large text box with transparent background. + * @brief Draw a large text box with transparent background with separators. * used as background to quest dialog window and in stores. */ void DrawTextBox(unsigned separators) @@ -1905,7 +1905,7 @@ void DrawTextBox(unsigned separators) } /** - * @brief Draw a small text box with transparent background and a separator. + * @brief Draw a small text box with transparent background with a separator. * used as background to items and in stores. * @param x: the starting x-coordinate of the text box * @param y: the starting y-coordinate of the text box diff --git a/Source/drlg_l1.cpp b/Source/drlg_l1.cpp index f6a51560206..6d168cbfc4a 100644 --- a/Source/drlg_l1.cpp +++ b/Source/drlg_l1.cpp @@ -645,6 +645,7 @@ static void DRLG_L5Shadows() // dungeon[i][j - 1] = 204; } else { // 25 -> not perfect, but ok and it would require a new door object as well + // 195 -> not perfect, but ok and only on the dyn map entrance // TODO: what else? } } @@ -2679,8 +2680,7 @@ void DRLG_L1InitTransVals() static void DRLG_L1() { - int i; - int areaidx; + int i, areaidx; // bool placeWater = QuestStatus(Q_PWATER); const int arealimits[] = { DMAXX * DMAXY, 761, 693, 533 }; areaidx = 0; diff --git a/Source/engine.cpp b/Source/engine.cpp index 846bdffaab2..baf60ccf205 100644 --- a/Source/engine.cpp +++ b/Source/engine.cpp @@ -148,8 +148,8 @@ int random_(BYTE idx, int v) if (v <= 0) return 0; if (v < 0x7FFF) - return ((NextRndValue()) >> 16) % v; - return (NextRndValue()) % v; + return (NextRndValue() >> 16) % v; + return NextRndValue() % v; } /** @@ -162,7 +162,7 @@ int random_low(BYTE idx, int v) { // assert(v > 0); // assert(v < 0x7FFF); - return ((NextRndValue()) >> 16) % v; + return (NextRndValue() >> 16) % v; } /** diff --git a/Source/gendung.cpp b/Source/gendung.cpp index 21c85f8f33c..022c15019a7 100644 --- a/Source/gendung.cpp +++ b/Source/gendung.cpp @@ -1611,8 +1611,8 @@ void DRLG_ChangeMap(int x1, int y1, int x2, int y2/*, bool hasNewObjPiece*/) y1 = 2 * y1 + DBORDERY; x2 = 2 * x2 + DBORDERX + 1; y2 = 2 * y2 + DBORDERY + 1; - LoadPreLighting(); // TODO: DRLG_LightSubtiles? + LoadPreLighting(); ObjChangeMap(x1, y1, x2, y2 /*, bool hasNewObjPiece*/); SavePreLighting(); // RedoLightAndVision(); From f927709b1f3ccf7919af4602946ef204f49fa2f1 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 24 Aug 2024 09:15:55 +0200 Subject: [PATCH 471/596] ensure alignment of ROOMHALLNODE, L1ROOM and ThemePosDir --- structs.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/structs.h b/structs.h index 50032bff05d..30b22cf2493 100644 --- a/structs.h +++ b/structs.h @@ -2333,8 +2333,13 @@ typedef struct ROOMHALLNODE { int nHallx2; int nHally2; int nHalldir; + ALIGNMENT(6, 6) } ROOMHALLNODE; +#if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) +static_warning((sizeof(ROOMHALLNODE) & (sizeof(ROOMHALLNODE) - 1)) == 0, "Align ROOMHALLNODE to power of 2 for better performance."); +#endif + typedef struct L1ROOM { int lrx; int lry; @@ -2342,6 +2347,10 @@ typedef struct L1ROOM { int lrh; } L1ROOM; +#if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) +static_warning((sizeof(L1ROOM) & (sizeof(L1ROOM) - 1)) == 0, "Align L1ROOM to power of 2 for better performance."); +#endif + typedef struct ThemePosDir { int tpdx; int tpdy; @@ -2349,10 +2358,15 @@ typedef struct ThemePosDir { int tpdvar2; // unused } ThemePosDir; +#if defined(X86_32bit_COMP) || defined(X86_64bit_COMP) +static_warning((sizeof(ThemePosDir) & (sizeof(ThemePosDir) - 1)) == 0, "Align ThemePosDir to power of 2 for better performance."); +#endif + /** The number of generated rooms in cathedral. */ #define L1_MAXROOMS ((DSIZEX * DSIZEY) / sizeof(L1ROOM)) /** The number of generated rooms in catacombs. */ #define L2_MAXROOMS 32 +static_assert(L2_MAXROOMS * sizeof(ROOMHALLNODE) <= (DSIZEX * DSIZEY), "RoomList is too large for DrlgMem."); /** Possible matching locations in a theme room. */ #define THEME_LOCS ((DSIZEX * DSIZEY) / sizeof(ThemePosDir)) From c75a8e4def126bc309f695fb550d060eb707583e Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 25 Aug 2024 08:02:23 +0200 Subject: [PATCH 472/596] fix the description of the local functions in themes.cpp --- Source/themes.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/themes.cpp b/Source/themes.cpp index 27c954519a2..a59bed6bb59 100644 --- a/Source/themes.cpp +++ b/Source/themes.cpp @@ -381,7 +381,7 @@ void InitThemes() /* * Place a theme object with the specified frequency. - * @param tv: theme id in the dungeon matrix. + * @param tv: room id in the dungeon matrix. * @param type: the type of the object to place * @param rndfrq: the frequency to place the object */ @@ -400,7 +400,7 @@ static void Place_Obj3(BYTE tv, int type, int rndfrq) /** * PlaceThemeMonsts places theme monsters with the specified frequency. * - * @param tv: theme id in the dungeon matrix. + * @param tv: room id in the dungeon matrix. */ static void PlaceThemeMonsts(BYTE tv) { @@ -433,7 +433,7 @@ static void PlaceThemeMonsts(BYTE tv) /** * Theme_Barrel initializes the barrel theme. * - * @param tv: theme id in the dungeon matrix. + * @param tv: room id in the dungeon matrix. */ static void Theme_Barrel(BYTE tv) { @@ -582,7 +582,7 @@ static void Theme_SkelRoom(int themeId, BYTE tv) /** * Theme_Treasure initializes the treasure theme. * - * @param tv: theme id in the dungeon matrix. + * @param tv: room id in the dungeon matrix. */ static void Theme_Treasure(BYTE tv) { From 892c670a1c74e1adf08720e87be0a2bbdcc72b1e Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 25 Aug 2024 08:08:02 +0200 Subject: [PATCH 473/596] do not propagate the damage type to SyncPlrKill (the value is used only by the local player, who should already be in a 'dying' state) --- Source/msg.cpp | 2 +- Source/player.cpp | 4 ++-- Source/player.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/msg.cpp b/Source/msg.cpp index 22a7c5dd5aa..e07988ed3f1 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -2904,7 +2904,7 @@ static unsigned On_PLRDEAD(TCmd* pCmd, int pnum) PlrDeadItem(pnum, &ear, DIR_S); } - SyncPlrKill(pnum, dmgtype); + SyncPlrKill(pnum); if (pnum == mypnum) check_update_plr(pnum); diff --git a/Source/player.cpp b/Source/player.cpp index 1fcd8131fc8..6362f50ebe3 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -1695,7 +1695,7 @@ void PlrHitByAny(int pnum, int mpnum, int dam, unsigned hitflags, int sx, int sy } } -void SyncPlrKill(int pnum, int dmgtype) +void SyncPlrKill(int pnum) { if ((unsigned)pnum >= MAX_PLRS) { dev_fatal("SyncPlrKill: illegal player %d", pnum); @@ -1706,7 +1706,7 @@ void SyncPlrKill(int pnum, int dmgtype) } if (plr._pmode != PM_DYING) { - StartPlrKill(pnum, dmgtype); + StartPlrKill(pnum, DMGTYPE_UNKNOWN); } plr._pmode = PM_DEATH; diff --git a/Source/player.h b/Source/player.h index 498f27f2cbc..359cde154fb 100644 --- a/Source/player.h +++ b/Source/player.h @@ -40,7 +40,7 @@ void PlrStartStand(int pnum); void PlrStartBlock(int pnum, int sx, int sy); void RemovePlrFromMap(int pnum); void PlrHitByAny(int pnum, int mpnum, int dam, unsigned hitflags, int sx, int sy); -void SyncPlrKill(int pnum, int dmgtype); +void SyncPlrKill(int pnum); void SyncPlrResurrect(int pnum); void StartNewLvl(int pnum, int fom, int lvl); void RestartTownLvl(int pnum); From a6ccc7d4c24bd05e2da556ff0853b18aedaa00ec Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 25 Aug 2024 08:20:32 +0200 Subject: [PATCH 474/596] bugfix for vanilla (rock vs. stand) - fix the draw order of rock and its stand when the rock is dropped to the ground due to full inventory (#7304) --- Source/items.cpp | 4 ++-- Source/objdat.cpp | 2 +- Source/scrollrt.cpp | 10 +++++----- structs.h | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Source/items.cpp b/Source/items.cpp index 028507e2fbf..189b1aad6c7 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -2319,7 +2319,7 @@ void PlaceQuestItemInArea(int idx, int areasize) // RespawnItem(i, false); // draw it above the stand items[i]._iSelFlag = 2; - items[i]._iPostDraw = TRUE; + //items[i]._iPostDraw = TRUE; items[i]._iAnimFrame = 11; //items[i]._iAnimFlag = TRUE; // items[i]._iCreateInfo = items_get_currlevel(); // | CF_PREGEN; @@ -2343,7 +2343,7 @@ void RespawnItem(int ii, bool FlipFlag) is->_iAnimFrameLen = 1; //is->_iAnimWidth = ITEM_ANIM_WIDTH; //is->_iAnimXOffset = (ITEM_ANIM_WIDTH - TILE_WIDTH) / 2; - is->_iPostDraw = FALSE; + //is->_iPostDraw = FALSE; if (FlipFlag) { is->_iAnimFrame = 1; is->_iAnimFlag = TRUE; diff --git a/Source/objdat.cpp b/Source/objdat.cpp index bee07e1240a..88b2525b78a 100644 --- a/Source/objdat.cpp +++ b/Source/objdat.cpp @@ -184,7 +184,7 @@ const ObjectData objectdata[NUM_OBJECTS] = { /*OBJ_CRUXM*/ { OFILE_CRUXSK1, 0, THEME_NONE, Q_INVALID, 1, 0, 0, 0, OPF_NONE, OMF_FLOOR | OMF_ACTIVE, FALSE, ODT_NONE, 3, FALSE, FALSE, ALIGN }, /*OBJ_CRUXR*/ { OFILE_CRUXSK2, 0, THEME_NONE, Q_INVALID, 1, 0, 0, 0, OPF_NONE, OMF_FLOOR | OMF_ACTIVE, FALSE, ODT_NONE, 3, FALSE, FALSE, ALIGN }, /*OBJ_CRUXL*/ { OFILE_CRUXSK3, 0, THEME_NONE, Q_INVALID, 1, 0, 0, 0, OPF_NONE, OMF_FLOOR | OMF_ACTIVE, FALSE, ODT_NONE, 3, FALSE, FALSE, ALIGN }, -/*OBJ_STAND*/ { OFILE_ROCKSTAN, 0, THEME_NONE, Q_ROCK, 1, 0, 0, 0, OPF_NONE, OMF_FLOOR, TRUE, ODT_NONE, 0, FALSE, FALSE, ALIGN }, +/*OBJ_STAND*/ { OFILE_ROCKSTAN, 0, THEME_NONE, Q_ROCK, 1, 0, 0, 0, OPF_NONE, OMF_FLOOR, TRUE, ODT_NONE, 0, TRUE, FALSE, ALIGN }, /*OBJ_ANGEL*/// { OFILE_ANGEL, 0, THEME_NONE, Q_INVALID, 1, 0, 0, 0, OPF_NONE, OMF_FLOOR, FALSE, ODT_NONE, 0, FALSE, FALSE, ALIGN }, /*OBJ_NUDEW2R*/// { OFILE_NUDE2, 0, THEME_NONE, Q_INVALID, 0, 0, 0, 0, OPF_NONE, OMF_FLOOR, FALSE, ODT_NONE, 0, FALSE, FALSE, ALIGN }, /*OBJ_SWITCHSKL*/ { OFILE_SWITCH4, DTM_HELL, THEME_NONE, Q_INVALID, 1, 0, 0, 0, OPF_NONE, OMF_FLOOR | OMF_ACTIVE, TRUE, ODT_NONE, 1, FALSE, TRUE, ALIGN }, diff --git a/Source/scrollrt.cpp b/Source/scrollrt.cpp index 30907c59a41..39963d35dc4 100644 --- a/Source/scrollrt.cpp +++ b/Source/scrollrt.cpp @@ -1018,8 +1018,8 @@ static void DrawItem(int ii, int sx, int sy) ii--; is = &items[ii]; - if (is->_iPostDraw == gbPreFlag) - return; + //if (is->_iPostDraw == gbPreFlag) + // return; pCelBuff = is->_iAnimData; if (pCelBuff == NULL) { @@ -1111,9 +1111,9 @@ static void scrollrt_draw_dungeon(int sx, int sy, int dx, int dy) mpnum = dObject[sx][sy]; if (mpnum != 0) DrawObject(mpnum, sx, sy, dx, dy); - bv = dItem[sx][sy]; - if (bv != 0) - DrawItem(bv, dx, dy); + //bv = dItem[sx][sy]; + //if (bv != 0) + // DrawItem(bv, dx, dy); if (currLvl._dType != DTYPE_TOWN) { bv = nSpecTrapTable[dPiece[sx][sy]] & PST_SPEC_TYPE; diff --git a/structs.h b/structs.h index 30b22cf2493..4efbdcd98b9 100644 --- a/structs.h +++ b/structs.h @@ -247,7 +247,7 @@ typedef struct ItemStruct { unsigned _iAnimFrame; // Current frame of animation. //int _iAnimWidth; //int _iAnimXOffset; - BOOL _iPostDraw; // should be drawn during the post-phase (magic rock on the stand) + BOOL _iPostDraw; // should be drawn during the post-phase (magic rock on the stand) -- unused BOOL _iIdentified; char _iName[32]; int _ivalue; From a27bdd4429a904e9c6e52f019e9d40ee8129300f Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 26 Aug 2024 09:10:11 +0200 Subject: [PATCH 475/596] fix a warning --- Source/control.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/control.cpp b/Source/control.cpp index 0609d715ccb..f3648296592 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -1823,7 +1823,7 @@ void DrawInfoStr() } else if (gnDifficulty == DIFF_HELL) { lvl += HELL_LEVEL_BONUS; } - snprintf(infostr, sizeof(infostr), gbCampaignMapFlag == CMAP_IDENTIFIED ? "(lvl: %d)" : "(lvl: ??)", lvl); + snprintf(infostr, sizeof(infostr), gbCampaignMapFlag == CMAP_IDENTIFIED ? "(lvl: %d)" : "(lvl: \?\?)", lvl); DrawTooltip2(type, infostr, MousePos.x, MousePos.y - (CAMICON_HEIGHT / 4 + TOOLTIP_OFFSET), COL_WHITE); } else if (pcursinvitem != INVITEM_NONE) { DrawInvItemDetails(); From 6bea93dc36b24368f6e1a973f171a559bc5b0132 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 26 Aug 2024 09:21:07 +0200 Subject: [PATCH 476/596] select the internal subtiles of the theme-room in InitThemes --- Source/monster.cpp | 4 ++-- Source/themes.cpp | 34 +++++++++++++++++----------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index a30778540e3..bb064aea737 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -991,8 +991,8 @@ static void PlaceUniqueMonst(int uniqindex, int mtidx) case UMT_ZHAR: if (zharlib == -1) return; - xp = themes[zharlib]._tsx1 + 4; - yp = themes[zharlib]._tsy1 + 4; + xp = themes[zharlib]._tsx1 + 3; + yp = themes[zharlib]._tsy1 + 3; break; default: count = 1000; diff --git a/Source/themes.cpp b/Source/themes.cpp index a59bed6bb59..0c9ae2176bc 100644 --- a/Source/themes.cpp +++ b/Source/themes.cpp @@ -59,8 +59,8 @@ static int TFit_Shrine(int themeId) BYTE tv = themes[themeId]._tsTransVal; numMatches = 0; - for (xx = themes[themeId]._tsx1 + 1; xx < themes[themeId]._tsx2; xx++) { - for (yy = themes[themeId]._tsy1 + 1; yy < themes[themeId]._tsy2; yy++) { + for (xx = themes[themeId]._tsx1; xx <= themes[themeId]._tsx2; xx++) { + for (yy = themes[themeId]._tsy1; yy <= themes[themeId]._tsy2; yy++) { if (dTransVal[xx][yy] == tv && !nSolidTable[dPiece[xx][yy]]) { if ((nSpecTrapTable[dPiece[xx][yy - 1]] & PST_TRAP_TYPE) != PST_NONE // make sure the place is wide enough @@ -124,8 +124,8 @@ static int TFit_Obj5(int themeId) BYTE tv = themes[themeId]._tsTransVal; numMatches = 0; - for (xx = themes[themeId]._tsx1 + 3; xx < themes[themeId]._tsx2 - 2; xx++) { - for (yy = themes[themeId]._tsy1 + 3; yy < themes[themeId]._tsy2 - 2; yy++) { + for (xx = themes[themeId]._tsx1 + 2; xx < themes[themeId]._tsx2 - 1; xx++) { + for (yy = themes[themeId]._tsy1 + 2; yy < themes[themeId]._tsy2 - 1; yy++) { if (dTransVal[xx][yy] == tv && !nSolidTable[dPiece[xx][yy]]) { static_assert(lengthof(trm5x) == lengthof(trm5y), "Mismatching trm5 tables."); for (i = 0; i < lengthof(trm5x); i++) { @@ -181,8 +181,8 @@ static int TFit_Obj3(int themeId) BYTE tv = themes[themeId]._tsTransVal; numMatches = 0; - for (xx = themes[themeId]._tsx1 + 2; xx < themes[themeId]._tsx2 - 1; xx++) { - for (yy = themes[themeId]._tsy1 + 2; yy < themes[themeId]._tsy2 - 1; yy++) { + for (xx = themes[themeId]._tsx1 + 1; xx < themes[themeId]._tsx2; xx++) { + for (yy = themes[themeId]._tsy1 + 1; yy < themes[themeId]._tsy2; yy++) { if (CheckThemeObj3(xx, yy, tv)) { drlg.thLocs[numMatches].tpdx = xx; drlg.thLocs[numMatches].tpdy = yy; @@ -325,22 +325,22 @@ void InitThemes() y1 = themes[i]._tsy1; x2 = themes[i]._tsx2; y2 = themes[i]._tsy2; - // convert to subtile-coordinates - x1 = DBORDERX + 2 * x1; - y1 = DBORDERY + 2 * y1; - x2 = DBORDERX + 2 * x2 + 1; - y2 = DBORDERY + 2 * y2 + 1; + // convert to subtile-coordinates and select the internal subtiles of the room [p0;p1) + x1 = DBORDERX + 2 * x1 + 1; + y1 = DBORDERY + 2 * y1 + 1; + x2 = DBORDERX + 2 * x2; + y2 = DBORDERY + 2 * y2; themes[i]._tsx1 = x1; themes[i]._tsy1 = y1; themes[i]._tsx2 = x2; themes[i]._tsy2 = y2; // select transval - themes[i]._tsTransVal = dTransVal[x1 + 2][y1 + 2]; + themes[i]._tsTransVal = dTransVal[x1 + 1][y1 + 1]; assert(themes[i]._tsTransVal != 0); // protect themes with dFlags // v = themes[i]._tsTransVal; - for (x = x1 + 1; x < x2; x++) { - for (y = y1 + 1; y < y2; y++) { + for (x = x1; x <= x2; x++) { + for (y = y1; y <= y2; y++) { // if (dTransVal[x][y] == v) { -- wall? dFlags[x][y] |= BFLAG_MON_PROTECT | BFLAG_OBJ_PROTECT; // } @@ -489,10 +489,10 @@ static void Theme_MonstPit(int themeId, BYTE tv) int r, xx, yy; bool done = false; - r = random_(11, (themes[themeId]._tsx2 - themes[themeId]._tsx1 - 1) * (themes[themeId]._tsy2 - themes[themeId]._tsy1 - 1)); + r = random_(11, (themes[themeId]._tsx2 + 1 - themes[themeId]._tsx1) * (themes[themeId]._tsy2 + 1 - themes[themeId]._tsy1)); restart: - for (xx = themes[themeId]._tsx1 + 1; xx < themes[themeId]._tsx2 && !done; xx++) { - for (yy = themes[themeId]._tsy1 + 1; yy < themes[themeId]._tsy2 && !done; yy++) { + for (xx = themes[themeId]._tsx1; xx <= themes[themeId]._tsx2 && !done; xx++) { + for (yy = themes[themeId]._tsy1; yy <= themes[themeId]._tsy2 && !done; yy++) { if (dTransVal[xx][yy] == tv && !nSolidTable[dPiece[xx][yy]] && --r < 0) { CreateRndItem(xx, yy, CFDQ_GOOD, ICM_DELTA); done = true; From 327b111cf8aac292e376a3d20f9a85759e54195e Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 26 Aug 2024 09:24:49 +0200 Subject: [PATCH 477/596] fix the search areas in themes.cpp --- Source/themes.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Source/themes.cpp b/Source/themes.cpp index 0c9ae2176bc..3447d93b570 100644 --- a/Source/themes.cpp +++ b/Source/themes.cpp @@ -59,8 +59,8 @@ static int TFit_Shrine(int themeId) BYTE tv = themes[themeId]._tsTransVal; numMatches = 0; - for (xx = themes[themeId]._tsx1; xx <= themes[themeId]._tsx2; xx++) { - for (yy = themes[themeId]._tsy1; yy <= themes[themeId]._tsy2; yy++) { + for (xx = themes[themeId]._tsx1; xx < themes[themeId]._tsx2; xx++) { + for (yy = themes[themeId]._tsy1; yy < themes[themeId]._tsy2; yy++) { if (dTransVal[xx][yy] == tv && !nSolidTable[dPiece[xx][yy]]) { if ((nSpecTrapTable[dPiece[xx][yy - 1]] & PST_TRAP_TYPE) != PST_NONE // make sure the place is wide enough @@ -124,8 +124,8 @@ static int TFit_Obj5(int themeId) BYTE tv = themes[themeId]._tsTransVal; numMatches = 0; - for (xx = themes[themeId]._tsx1 + 2; xx < themes[themeId]._tsx2 - 1; xx++) { - for (yy = themes[themeId]._tsy1 + 2; yy < themes[themeId]._tsy2 - 1; yy++) { + for (xx = themes[themeId]._tsx1 + 2; xx < themes[themeId]._tsx2 - 2; xx++) { + for (yy = themes[themeId]._tsy1 + 2; yy < themes[themeId]._tsy2 - 2; yy++) { if (dTransVal[xx][yy] == tv && !nSolidTable[dPiece[xx][yy]]) { static_assert(lengthof(trm5x) == lengthof(trm5y), "Mismatching trm5 tables."); for (i = 0; i < lengthof(trm5x); i++) { @@ -181,8 +181,8 @@ static int TFit_Obj3(int themeId) BYTE tv = themes[themeId]._tsTransVal; numMatches = 0; - for (xx = themes[themeId]._tsx1 + 1; xx < themes[themeId]._tsx2; xx++) { - for (yy = themes[themeId]._tsy1 + 1; yy < themes[themeId]._tsy2; yy++) { + for (xx = themes[themeId]._tsx1 + 1; xx < themes[themeId]._tsx2 - 1; xx++) { + for (yy = themes[themeId]._tsy1 + 1; yy < themes[themeId]._tsy2 - 1; yy++) { if (CheckThemeObj3(xx, yy, tv)) { drlg.thLocs[numMatches].tpdx = xx; drlg.thLocs[numMatches].tpdy = yy; @@ -489,10 +489,10 @@ static void Theme_MonstPit(int themeId, BYTE tv) int r, xx, yy; bool done = false; - r = random_(11, (themes[themeId]._tsx2 + 1 - themes[themeId]._tsx1) * (themes[themeId]._tsy2 + 1 - themes[themeId]._tsy1)); + r = random_(11, (themes[themeId]._tsx2 - themes[themeId]._tsx1) * (themes[themeId]._tsy2 - themes[themeId]._tsy1)); restart: - for (xx = themes[themeId]._tsx1; xx <= themes[themeId]._tsx2 && !done; xx++) { - for (yy = themes[themeId]._tsy1; yy <= themes[themeId]._tsy2 && !done; yy++) { + for (xx = themes[themeId]._tsx1; xx < themes[themeId]._tsx2 && !done; xx++) { + for (yy = themes[themeId]._tsy1; yy < themes[themeId]._tsy2 && !done; yy++) { if (dTransVal[xx][yy] == tv && !nSolidTable[dPiece[xx][yy]] && --r < 0) { CreateRndItem(xx, yy, CFDQ_GOOD, ICM_DELTA); done = true; From e4e72b4de3fa4382181e1a4b5fdf7758905f4776 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 26 Aug 2024 09:28:35 +0200 Subject: [PATCH 478/596] simplify Theme_MonstPit --- Source/themes.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Source/themes.cpp b/Source/themes.cpp index 3447d93b570..8f8e32954ea 100644 --- a/Source/themes.cpp +++ b/Source/themes.cpp @@ -487,20 +487,19 @@ static void Theme_Shrine(int themeId, BYTE tv) static void Theme_MonstPit(int themeId, BYTE tv) { int r, xx, yy; - bool done = false; r = random_(11, (themes[themeId]._tsx2 - themes[themeId]._tsx1) * (themes[themeId]._tsy2 - themes[themeId]._tsy1)); -restart: - for (xx = themes[themeId]._tsx1; xx < themes[themeId]._tsx2 && !done; xx++) { - for (yy = themes[themeId]._tsy1; yy < themes[themeId]._tsy2 && !done; yy++) { + while (true) { + for (xx = themes[themeId]._tsx1; xx < themes[themeId]._tsx2; xx++) { + for (yy = themes[themeId]._tsy1; yy < themes[themeId]._tsy2; yy++) { if (dTransVal[xx][yy] == tv && !nSolidTable[dPiece[xx][yy]] && --r < 0) { CreateRndItem(xx, yy, CFDQ_GOOD, ICM_DELTA); - done = true; + goto done; } } } - if (!done) - goto restart; + } +done: PlaceThemeMonsts(tv); } From 210a6dc703ddd71ac2072b9ef10e73545e56cb50 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 26 Aug 2024 09:29:27 +0200 Subject: [PATCH 479/596] cosmetic --- Source/themes.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/themes.cpp b/Source/themes.cpp index 8f8e32954ea..45361a1b309 100644 --- a/Source/themes.cpp +++ b/Source/themes.cpp @@ -490,15 +490,15 @@ static void Theme_MonstPit(int themeId, BYTE tv) r = random_(11, (themes[themeId]._tsx2 - themes[themeId]._tsx1) * (themes[themeId]._tsy2 - themes[themeId]._tsy1)); while (true) { - for (xx = themes[themeId]._tsx1; xx < themes[themeId]._tsx2; xx++) { - for (yy = themes[themeId]._tsy1; yy < themes[themeId]._tsy2; yy++) { - if (dTransVal[xx][yy] == tv && !nSolidTable[dPiece[xx][yy]] && --r < 0) { - CreateRndItem(xx, yy, CFDQ_GOOD, ICM_DELTA); - goto done; + for (xx = themes[themeId]._tsx1; xx < themes[themeId]._tsx2; xx++) { + for (yy = themes[themeId]._tsy1; yy < themes[themeId]._tsy2; yy++) { + if (dTransVal[xx][yy] == tv && !nSolidTable[dPiece[xx][yy]] && --r < 0) { + CreateRndItem(xx, yy, CFDQ_GOOD, ICM_DELTA); + goto done; + } } } } - } done: PlaceThemeMonsts(tv); From 2b319ac2d5e80ff7c9fca13462d6262a9e770fd2 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 26 Aug 2024 09:38:23 +0200 Subject: [PATCH 480/596] use 'while (true)' for unconditional loops --- 3rdParty/SDL2_mixer/src/mixer.c | 2 +- Source/diablo.cpp | 4 ++-- Source/drlg_l1.cpp | 6 +++--- Source/drlg_l2.cpp | 18 +++++++++--------- Source/drlg_l3.cpp | 8 ++++---- Source/drlg_l4.cpp | 10 +++++----- Source/gendung.cpp | 2 +- Source/items.cpp | 14 +++++++------- Source/mainmenu.cpp | 2 +- Source/minitext.cpp | 2 +- Source/monster.cpp | 4 ++-- Source/multi.cpp | 6 +++--- Source/objects.cpp | 10 +++++----- Source/path.cpp | 4 ++-- Source/platform/vita/keyboard.cpp | 2 +- Source/utils/sdl2_to_1_2_backports.cpp | 2 +- tools/patcher/mainmenu.cpp | 2 +- tools/patcher/platform/vita/keyboard.cpp | 2 +- tools/patcher/utils/sdl2_to_1_2_backports.cpp | 2 +- 19 files changed, 51 insertions(+), 51 deletions(-) diff --git a/3rdParty/SDL2_mixer/src/mixer.c b/3rdParty/SDL2_mixer/src/mixer.c index e6933e9bc27..2131725205c 100644 --- a/3rdParty/SDL2_mixer/src/mixer.c +++ b/3rdParty/SDL2_mixer/src/mixer.c @@ -1938,7 +1938,7 @@ static int _Mix_register_effect(effect_info **e, Mix_EffectFunc_t f, *e = new_e; } else { effect_info *cur = *e; - while (1) { + while (true) { if (cur->next == NULL) { cur->next = new_e; break; diff --git a/Source/diablo.cpp b/Source/diablo.cpp index eb768294e67..df508f831ff 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -1406,7 +1406,7 @@ static void run_game() #ifdef GPERF_HEAP_FIRST_GAME_ITERATION unsigned run_game_iteration = 0; #endif - while (TRUE) { + while (true) { while (gbRunGame && PeekMessage(event)) { DispatchMessage(&event); } @@ -1445,7 +1445,7 @@ bool StartGame(bool bSinglePlayer) gbSelectProvider = true; gbSelectHero = true; - while (TRUE) { + while (true) { if (!NetInit(bSinglePlayer)) { return true; } diff --git a/Source/drlg_l1.cpp b/Source/drlg_l1.cpp index 6d168cbfc4a..bb243b9b75b 100644 --- a/Source/drlg_l1.cpp +++ b/Source/drlg_l1.cpp @@ -1393,7 +1393,7 @@ static bool L1AddHWall(int x, int y) BYTE bv; i = x; - while (TRUE) { + while (true) { i++; bv = dungeon[i][y]; if (bv != 13) @@ -1475,7 +1475,7 @@ static void L1AddVWall(int x, int y) BYTE bv; j = y; - while (TRUE) { + while (true) { j++; bv = dungeon[x][j]; if (bv != 13) @@ -2149,7 +2149,7 @@ static void DRLG_L1Subs() if (c != 0 && (drlgFlags[x][y] & DRLG_FROZEN) == 0) { rv = random_(0, MAX_MATCH); k = 0; - while (TRUE) { + while (true) { if (c == L1BTYPES[k] && --rv < 0) { break; } diff --git a/Source/drlg_l2.cpp b/Source/drlg_l2.cpp index 03a1861c8e9..33afa1c5465 100644 --- a/Source/drlg_l2.cpp +++ b/Source/drlg_l2.cpp @@ -569,7 +569,7 @@ static void DRLG_L2Subs() if (c != 0 && (drlgFlags[x][y] & DRLG_FROZEN) == 0) { rv = random_(0, MAX_MATCH); k = 0; - while (TRUE) { + while (true) { if (c == L2BTYPES[k] && --rv < 0) { break; } @@ -1135,7 +1135,7 @@ static void ConnectHall(int nX1, int nY1, int nX2, int nY2, int nHd) //assert(nX2 >= 0 && nX2 < DMAXX && nY2 >= 0 && nY2 < DMAXY); pdungeon[nX2][nY2] = PRE_HALLWAY; - while (TRUE) { + while (true) { //assert(nX1 < DMAXX - 2 || nCurrd != HDIR_RIGHT); //assert(nX1 > 1 || nCurrd != HDIR_LEFT); //assert(nY1 < DMAXX - 2 || nCurrd != HDIR_DOWN); @@ -1609,7 +1609,7 @@ static bool DL2_FillVoids() int tries; tries = 0; - while (TRUE) { + while (true) { if (DRLG_L2GetArea() >= 800) return true; next_try: @@ -1689,7 +1689,7 @@ static bool DL2_FillVoids() if (y2 - y1 < 5) goto next_try; if (!xLeft) { - while (TRUE) { + while (true) { if (x2 == DMAXX - 1) { break; } @@ -1708,7 +1708,7 @@ static bool DL2_FillVoids() x2 -= 2; } else { // assert(!xRight); - while (TRUE) { + while (true) { if (x1 == 0) { break; } @@ -1761,7 +1761,7 @@ static bool DL2_FillVoids() if (x2 - x1 < 5) goto next_try; if (!xUp) { - while (TRUE) { + while (true) { if (y2 == DMAXY - 1) { break; } @@ -1781,7 +1781,7 @@ static bool DL2_FillVoids() y2 -= 2; } else { // assert(!xDown); - while (TRUE) { + while (true) { if (y1 == 0) { break; } @@ -2048,7 +2048,7 @@ static void L2LockoutFix() doorok = dungeon[i][j] == 5; if ((dungeon[i][j] == 2 || doorok) && dungeon[i][j - 1] == 3 && dungeon[i][j + 1] == 3) { //assert(j >= 1 && j <= DMAXY - 2); - while (TRUE) { + while (true) { i++; //assert(i < DMAXX); if (dungeon[i][j - 1] != 3 || dungeon[i][j + 1] != 3) { @@ -2076,7 +2076,7 @@ static void L2LockoutFix() doorok = dungeon[i][j] == 4; if ((dungeon[i][j] == 1 || doorok) && dungeon[i - 1][j] == 3 && dungeon[i + 1][j] == 3) { //assert(i >= 1 && i <= DMAXX - 2); - while (TRUE) { + while (true) { j++; //assert(j < DMAXY); if (dungeon[i - 1][j] != 3 || dungeon[i + 1][j] != 3) { diff --git a/Source/drlg_l3.cpp b/Source/drlg_l3.cpp index eaa9a4b6f67..6a6b380d348 100644 --- a/Source/drlg_l3.cpp +++ b/Source/drlg_l3.cpp @@ -1946,7 +1946,7 @@ static void DRLG_L3Subs() if (c != 0 && (drlgFlags[x][y] & DRLG_FROZEN) == 0) { rv = random_(0, MAX_MATCH); k = 0; - while (TRUE) { + while (true) { if (c == L3BTYPES[k] && --rv < 0) { break; } @@ -2014,7 +2014,7 @@ static void DRLG_L6Subs() if (c != 0) { rv = random_(0, MAX_MATCH); k = 0; - while (TRUE) { + while (true) { if (c == L6BTYPES[k] && --rv < 0) { break; } @@ -2165,7 +2165,7 @@ static void DRLG_L3Wood() if (InThemeRoom(i, j - 1)) continue; // in a theme room -> skip y1 = j; - while (TRUE) { + while (true) { y1--; bv = dungeon[i][y1]; if (bv == 10) { // normal wall @@ -2220,7 +2220,7 @@ static void DRLG_L3Wood() if (InThemeRoom(i - 1, j)) continue; // in a theme room -> skip x1 = i; - while (TRUE) { + while (true) { x1--; bv = dungeon[x1][j]; if (bv == 9) { // normal wall diff --git a/Source/drlg_l4.cpp b/Source/drlg_l4.cpp index 021b32bd763..4a3ebe36d3e 100644 --- a/Source/drlg_l4.cpp +++ b/Source/drlg_l4.cpp @@ -605,7 +605,7 @@ static void L4AddHWall(int x, int y) BYTE bv; i = x; - while (TRUE) { + while (true) { i++; bv = dungeon[i][y]; if (bv != 6) @@ -696,7 +696,7 @@ static void L4AddVWall(int x, int y) BYTE bv; j = y; - while (TRUE) { + while (true) { j++; bv = dungeon[x][j]; if (bv != 6) @@ -1158,7 +1158,7 @@ static void DRLG_L4Subs() if (c != 0 && (drlgFlags[x][y] & DRLG_FROZEN) == 0) { rv = random_(0, MAX_MATCH); k = 0; - while (TRUE) { + while (true) { if (c == L4BTYPES[k] && --rv < 0) break; if (++k == NUM_L4TYPES) @@ -1224,7 +1224,7 @@ static void L4ConnectBlock() } rv = RandRange(1, L4BLOCKY - 1); - while (TRUE) { + while (true) { if (hallok[rv] != 0) { for (i = L4BLOCKX - 1; i > hallok[rv]; i--) { drlg.dungBlock[i][rv] = 1; @@ -1253,7 +1253,7 @@ static void L4ConnectBlock() } rv = RandRange(1, L4BLOCKX - 1); - while (TRUE) { + while (true) { if (hallok[rv] != 0) { for (j = L4BLOCKY - 1; j > hallok[rv]; j--) { drlg.dungBlock[rv][j] = 1; diff --git a/Source/gendung.cpp b/Source/gendung.cpp index 022c15019a7..ff619a7d044 100644 --- a/Source/gendung.cpp +++ b/Source/gendung.cpp @@ -937,7 +937,7 @@ POS32 DRLG_PlaceMiniSet(const BYTE* miniset) sh = miniset[1]; // assert(sw < DMAXX && sh < DMAXY); tries = (DMAXX * DMAXY) & ~0xFF; - while (TRUE) { + while (true) { if ((tries & 0xFF) == 0) { sx = random_low(0, DMAXX - sw); sy = random_low(0, DMAXY - sh); diff --git a/Source/items.cpp b/Source/items.cpp index 189b1aad6c7..5225f78fe95 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -68,7 +68,7 @@ static void GetRandomItemSpace(int randarea, int ii) // assert(randarea > 0 && randarea < DBORDERX && randarea < DBORDERY); tries = numTries; - while (TRUE) { + while (true) { x = random_(0, DSIZEX) + DBORDERX; y = random_(0, DSIZEY) + DBORDERY; for (i = x; i < x + randarea; i++) { @@ -2547,7 +2547,7 @@ static void DoClean(ItemStruct* pi, bool whittle) ci--; ci |= CF_CRAFTED; - while (TRUE) { + while (true) { RecreateItem(seed, idx, ci); assert(items[MAXITEMS]._iIdx == idx); if (items[MAXITEMS]._iPrePower == IPL_INVALID @@ -2589,7 +2589,7 @@ static void BuckleItem(ItemStruct* pi) magic = pi->_iMagical == ITEM_QUALITY_NORMAL ? ITEM_QUALITY_NORMAL : ITEM_QUALITY_MAGIC; ci |= CF_CRAFTED; - while (TRUE) { + while (true) { RecreateItem(seed, idx, ci); assert(items[MAXITEMS]._iIdx == idx); if (items[MAXITEMS]._iMagical == magic) @@ -2788,7 +2788,7 @@ void DoOil(int pnum, int8_t from, BYTE cii) spell = pi->_iSpell; seed = pi->_iSeed; - while (TRUE) { + while (true) { RecreateItem(seed, idx, ci); assert(items[MAXITEMS]._iIdx == idx); if (items[MAXITEMS]._iSpell == spell @@ -3867,7 +3867,7 @@ void SpawnSpellBook(int ispell, int x, int y, bool sendmsg) idx = RndTypeItems(ITYPE_MISC, IMISC_BOOK, lvl); - while (TRUE) { + while (true) { SetupAllItems(MAXITEMS, idx, NextRndSeed(), lvl, CFDQ_NORMAL); assert(items[MAXITEMS]._iMiscId == IMISC_BOOK); if (items[MAXITEMS]._iSpell == ispell) @@ -3886,7 +3886,7 @@ void SpawnAmulet(uint16_t wCI, int x, int y/*, bool sendmsg*/) lvl = wCI & CF_LEVEL; // TODO: make sure there is an amulet which fits? - while (TRUE) { + while (true) { idx = RndTypeItems(ITYPE_AMULET, IMISC_NONE, lvl); SetupAllItems(MAXITEMS, idx, NextRndSeed(), lvl, CFDQ_GOOD); if (items[MAXITEMS]._iCurs == ICURS_AMULET) @@ -3905,7 +3905,7 @@ void SpawnMagicItem(int itype, int icurs, int x, int y, bool sendmsg) lvl = items_get_currlevel(); - while (TRUE) { + while (true) { idx = RndTypeItems(itype, IMISC_NONE, lvl); SetupAllItems(MAXITEMS, idx, NextRndSeed(), lvl, CFDQ_GOOD); if (items[MAXITEMS]._iCurs == icurs) diff --git a/Source/mainmenu.cpp b/Source/mainmenu.cpp index 8c77fe0f24d..d92f02e88c2 100644 --- a/Source/mainmenu.cpp +++ b/Source/mainmenu.cpp @@ -70,7 +70,7 @@ void mainmenu_loop() { mainmenu_refresh_music(); - while (TRUE) { + while (true) { switch (UiMainMenuDialog()) { case MAINMENU_SINGLE_PLAYER: if (mainmenu_single_player()) diff --git a/Source/minitext.cpp b/Source/minitext.cpp index 31d4d17e9ff..85fdf2e2c38 100644 --- a/Source/minitext.cpp +++ b/Source/minitext.cpp @@ -73,7 +73,7 @@ void DrawQText() while (*str != '\0') { len = 0; sstr = endstr = str; - while (TRUE) { + while (true) { if (*sstr == '\0') { endstr = sstr; break; diff --git a/Source/monster.cpp b/Source/monster.cpp index bb064aea737..c005e3757cc 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -996,7 +996,7 @@ static void PlaceUniqueMonst(int uniqindex, int mtidx) break; default: count = 1000; - while (TRUE) { + while (true) { xp = random_(91, DSIZEX) + DBORDERX; yp = random_(91, DSIZEY) + DBORDERY; static_assert(DBORDERX >= MON_PACK_DISTANCE, "PlaceUniqueMonst does not check IN_DUNGEON_AREA but expects a large enough border I."); @@ -4540,7 +4540,7 @@ void ProcessMonsters() } } - while (TRUE) { + while (true) { AiProc[mon->_mAI.aiType](mnum); switch (mon->_mmode) { diff --git a/Source/multi.cpp b/Source/multi.cpp index c5476984091..3c730fa0ad6 100644 --- a/Source/multi.cpp +++ b/Source/multi.cpp @@ -95,7 +95,7 @@ static BYTE* multi_add_chunks(BYTE* dest, unsigned* size) if (sgTurnChunkBuf.dwDataSize != 0) { src_ptr = &sgTurnChunkBuf.bData[0]; - while (TRUE) { + while (true) { chunk_size = *src_ptr; if (chunk_size == 0 || chunk_size > *size) break; @@ -745,7 +745,7 @@ static bool multi_init_game(bool bSinglePlayer, _uigamedata& gameData) int i, dlgresult, pnum; int32_t seed; - while (TRUE) { + while (true) { // mypnum = 0; // select provider @@ -832,7 +832,7 @@ bool NetInit(bool bSinglePlayer) { _uigamedata gameData; - while (TRUE) { + while (true) { SetRndSeed(0); gameData.aeSeed = time(NULL); gameData.aeVersionId = GAME_VERSION; diff --git a/Source/objects.cpp b/Source/objects.cpp index e1ed3c5ab4c..088a3482c6b 100644 --- a/Source/objects.cpp +++ b/Source/objects.cpp @@ -241,7 +241,7 @@ static POS32 RndLoc3x3() int xp, yp, i, j, tries; static_assert(DBORDERX != 0, "RndLoc3x3 returns 0;0 position as a failed location."); tries = 0; - while (TRUE) { + while (true) { xp = random_(140, DSIZEX) + DBORDERX; yp = random_(140, DSIZEY) + DBORDERY; for (i = -1; i <= 1; i++) { @@ -263,7 +263,7 @@ static POS32 RndLoc3x4() int xp, yp, i, j, tries; static_assert(DBORDERX != 0, "RndLoc3x4 returns 0;0 position as a failed location."); tries = 0; - while (TRUE) { + while (true) { xp = random_(140, DSIZEX) + DBORDERX; yp = random_(140, DSIZEY) + DBORDERY; for (i = -1; i <= 1; i++) { @@ -285,7 +285,7 @@ static POS32 RndLoc5x5() int xp, yp, i, j, tries; static_assert(DBORDERX != 0, "RndLoc5x5 returns 0;0 position as a failed location."); tries = 0; - while (TRUE) { + while (true) { xp = random_(140, DSIZEX) + DBORDERX; yp = random_(140, DSIZEY) + DBORDERY; for (i = -2; i <= 2; i++) { @@ -307,7 +307,7 @@ static POS32 RndLoc7x5() int xp, yp, i, j, tries; static_assert(DBORDERX != 0, "RndLoc7x5 returns 0;0 position as a failed location."); tries = 0; - while (TRUE) { + while (true) { xp = random_(140, DSIZEX) + DBORDERX; yp = random_(140, DSIZEY) + DBORDERY; for (i = -3; i <= 3; i++) { @@ -1155,7 +1155,7 @@ static int FindValidShrine(int filter) int rv; BYTE excl = IsMultiGame ? SHRINETYPE_SINGLE : SHRINETYPE_MULTI; - while (TRUE) { + while (true) { rv = random_(0, NUM_SHRINETYPE); if (rv != filter && shrineavail[rv] != excl) break; diff --git a/Source/path.cpp b/Source/path.cpp index b8879763f3a..0b92b3b82c5 100644 --- a/Source/path.cpp +++ b/Source/path.cpp @@ -72,7 +72,7 @@ static PATHNODE* PathVisitedNodeAt(int dx, int dy) { PATHNODE* result = pathVisitedNodes; - while (TRUE) { + while (true) { if (result->x == dx && result->y == dy) break; result = result->NextNode; @@ -334,7 +334,7 @@ int FindPath(bool (*PosOk)(int, int, int), int PosOkArg, int sx, int sy, int dx, currNode->totalCost = currNode->remainingCost + currNode->walkCost; pathVisitedNodes = currNode; // A* search until we find (dx,dy) or fail - while (TRUE) { + while (true) { // LogErrorF("Eval path from %d:%d", currNode->x - gnSx, currNode->y - gnSy); // reached the end, success! if (currNode->x == gnTx && currNode->y == gnTy) { diff --git a/Source/platform/vita/keyboard.cpp b/Source/platform/vita/keyboard.cpp index e27cfdb25f8..0030e4102d3 100644 --- a/Source/platform/vita/keyboard.cpp +++ b/Source/platform/vita/keyboard.cpp @@ -53,7 +53,7 @@ static void utf8_to_utf16(const uint8_t *src, uint16_t *dst) static int vita_input_thread(void *ime_buffer) { - while (1) { + while (true) { // update IME status. Terminate, if finished SceCommonDialogStatus dialogStatus = sceImeDialogGetStatus(); if (dialogStatus == SCE_COMMON_DIALOG_STATUS_FINISHED) { diff --git a/Source/utils/sdl2_to_1_2_backports.cpp b/Source/utils/sdl2_to_1_2_backports.cpp index 97719323268..1f5dd56a335 100644 --- a/Source/utils/sdl2_to_1_2_backports.cpp +++ b/Source/utils/sdl2_to_1_2_backports.cpp @@ -501,7 +501,7 @@ static char* readSymLink(const char* path) ssize_t len = 64; ssize_t rc = -1; - while (1) { + while (true) { char* ptr = (char*)SDL_realloc(retval, (size_t)len); if (ptr == NULL) { SDL_OutOfMemory(); diff --git a/tools/patcher/mainmenu.cpp b/tools/patcher/mainmenu.cpp index 77ee6d76868..7748d32bb31 100644 --- a/tools/patcher/mainmenu.cpp +++ b/tools/patcher/mainmenu.cpp @@ -30,7 +30,7 @@ void mainmenu_loop() { mainmenu_refresh_music(); - while (TRUE) { + while (true) { switch (UiMainMenuDialog()) { case 0: UiPatcherDialog(); diff --git a/tools/patcher/platform/vita/keyboard.cpp b/tools/patcher/platform/vita/keyboard.cpp index e27cfdb25f8..0030e4102d3 100644 --- a/tools/patcher/platform/vita/keyboard.cpp +++ b/tools/patcher/platform/vita/keyboard.cpp @@ -53,7 +53,7 @@ static void utf8_to_utf16(const uint8_t *src, uint16_t *dst) static int vita_input_thread(void *ime_buffer) { - while (1) { + while (true) { // update IME status. Terminate, if finished SceCommonDialogStatus dialogStatus = sceImeDialogGetStatus(); if (dialogStatus == SCE_COMMON_DIALOG_STATUS_FINISHED) { diff --git a/tools/patcher/utils/sdl2_to_1_2_backports.cpp b/tools/patcher/utils/sdl2_to_1_2_backports.cpp index 97719323268..1f5dd56a335 100644 --- a/tools/patcher/utils/sdl2_to_1_2_backports.cpp +++ b/tools/patcher/utils/sdl2_to_1_2_backports.cpp @@ -501,7 +501,7 @@ static char* readSymLink(const char* path) ssize_t len = 64; ssize_t rc = -1; - while (1) { + while (true) { char* ptr = (char*)SDL_realloc(retval, (size_t)len); if (ptr == NULL) { SDL_OutOfMemory(); From ac6e2f690111402c7ae69c28c6e7cd1669d3c5f4 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 26 Aug 2024 11:54:46 +0200 Subject: [PATCH 481/596] update SDL2 --- 3rdParty/SDL2/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdParty/SDL2/CMakeLists.txt b/3rdParty/SDL2/CMakeLists.txt index 05ee3b515a9..f3eeabed6cd 100644 --- a/3rdParty/SDL2/CMakeLists.txt +++ b/3rdParty/SDL2/CMakeLists.txt @@ -75,7 +75,7 @@ FetchContent_Declare(SDL2 #URL https://github.com/libsdl-org/SDL/archive/5056b29b0f8611b470d8b8bdb313eab628f8bd6e.tar.gz #URL_HASH MD5=3fb6d72c33434082c32d2649c35c6502 GIT_REPOSITORY https://github.com/pionere/SDL.git - GIT_TAG 74876973d1f13fedadabe49a6812d7d88af80b86 + GIT_TAG 808dd1496ddafddc933c3ca31155e2ca593b5d67 ) FetchContent_MakeAvailableExcludeFromAll(SDL2) From fab3b2939086118ec39e63c16e8f021bc20e9771 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 26 Aug 2024 12:30:09 +0200 Subject: [PATCH 482/596] use manual build to improve CodeQL-coverage --- .github/workflows/code-ql.yml | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/.github/workflows/code-ql.yml b/.github/workflows/code-ql.yml index 0eab2455c66..037646234e2 100644 --- a/.github/workflows/code-ql.yml +++ b/.github/workflows/code-ql.yml @@ -37,7 +37,8 @@ jobs: matrix: include: - language: c-cpp - build-mode: autobuild + #build-mode: autobuild + build-mode: manual - language: java-kotlin build-mode: none # This mode only analyzes Java. Set this to 'autobuild' or 'manual' to analyze Kotlin too. - language: python @@ -75,15 +76,20 @@ jobs: # to build your code. # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - if: matrix.build-mode == 'manual' + - name: Create Build Environment + if: matrix.build-mode == 'manual' + run: > + sudo apt-get update && + sudo apt install -y cmake gcc-mingw-w64-i686 g++-mingw-w64-i686 pkg-config-mingw-w64-i686 libz-mingw-w64-dev gettext dpkg-dev wget git sudo && + sudo rm /usr/i686-w64-mingw32/lib/libz.dll.a && + sudo Packaging/windows/mingw-prep.sh + + - name: Build + if: matrix.build-mode == 'manual' shell: bash run: | - echo 'If you are using a "manual" build mode for one or more of the' \ - 'languages you are analyzing, replace this with the commands to build' \ - 'your code, for example:' - echo ' make bootstrap' - echo ' make release' - exit 1 + cmake -S. -Bbuild -DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON -DCMAKE_BUILD_TYPE="Release" -DCMAKE_TOOLCHAIN_FILE=../CMake/mingwcc.toolchain.cmake + cmake --build build -j $(nproc) --target package - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 From 8901ed4cccfba618dc201aee1d06c8fc3a764c96 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 26 Aug 2024 12:37:47 +0200 Subject: [PATCH 483/596] protect only the inner tiles of the theme-room --- Source/themes.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/themes.cpp b/Source/themes.cpp index 45361a1b309..154ffa5dcd3 100644 --- a/Source/themes.cpp +++ b/Source/themes.cpp @@ -337,10 +337,10 @@ void InitThemes() // select transval themes[i]._tsTransVal = dTransVal[x1 + 1][y1 + 1]; assert(themes[i]._tsTransVal != 0); - // protect themes with dFlags + // protect themes with dFlags - TODO: extend the protection +1 to prevent overdrawn shrine and torch? unlikely + protection would prevent torches in theme rooms... // v = themes[i]._tsTransVal; - for (x = x1; x <= x2; x++) { - for (y = y1; y <= y2; y++) { + for (x = x1; x < x2; x++) { + for (y = y1; y < y2; y++) { // if (dTransVal[x][y] == v) { -- wall? dFlags[x][y] |= BFLAG_MON_PROTECT | BFLAG_OBJ_PROTECT; // } From 6edb9b63203f11385f6645ce938196e2166d1fd0 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 26 Aug 2024 12:39:19 +0200 Subject: [PATCH 484/596] limit search in themes.cpp to the room-rectangles --- Source/themes.cpp | 78 +++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/Source/themes.cpp b/Source/themes.cpp index 154ffa5dcd3..45d15dd6cfe 100644 --- a/Source/themes.cpp +++ b/Source/themes.cpp @@ -381,16 +381,17 @@ void InitThemes() /* * Place a theme object with the specified frequency. + * @param themeId: theme id. * @param tv: room id in the dungeon matrix. * @param type: the type of the object to place * @param rndfrq: the frequency to place the object */ -static void Place_Obj3(BYTE tv, int type, int rndfrq) +static void Place_Obj3(int themeId, BYTE tv, int type, int rndfrq) { int xx, yy; // assert(rndfrq > 0); - for (xx = DBORDERX + 1; xx < DBORDERX + DSIZEX - 1; xx++) { - for (yy = DBORDERY + 1; yy < DBORDERY + DSIZEY - 1; yy++) { + for (xx = themes[themeId]._tsx1; xx < themes[themeId]._tsx2; xx++) { + for (yy = themes[themeId]._tsy1; yy < themes[themeId]._tsy2; yy++) { if (CheckThemeObj3(xx, yy, tv) && random_low(0, rndfrq) == 0) { AddObject(type, xx, yy); } @@ -400,9 +401,10 @@ static void Place_Obj3(BYTE tv, int type, int rndfrq) /** * PlaceThemeMonsts places theme monsters with the specified frequency. * + * @param themeId: theme id. * @param tv: room id in the dungeon matrix. */ -static void PlaceThemeMonsts(BYTE tv) +static void PlaceThemeMonsts(int themeId, BYTE tv) { int xx, yy; int scattertypes[MAX_LVLMTYPES]; @@ -419,8 +421,8 @@ static void PlaceThemeMonsts(BYTE tv) } // assert(numscattypes > 0); mtype = scattertypes[random_low(0, numscattypes)]; - for (xx = DBORDERX; xx < DBORDERX + DSIZEX; xx++) { - for (yy = DBORDERY; yy < DBORDERY + DSIZEY; yy++) { + for (xx = themes[themeId]._tsx1; xx < themes[themeId]._tsx2; xx++) { + for (yy = themes[themeId]._tsy1; yy < themes[themeId]._tsy2; yy++) { if (dTransVal[xx][yy] == tv && (nSolidTable[dPiece[xx][yy]] | dItem[xx][yy] | dObject[xx][yy]) == 0) { if (random_low(0, rndfrq) == 0) { AddMonster(mtype, xx, yy); @@ -433,16 +435,17 @@ static void PlaceThemeMonsts(BYTE tv) /** * Theme_Barrel initializes the barrel theme. * + * @param themeId: theme id. * @param tv: room id in the dungeon matrix. */ -static void Theme_Barrel(BYTE tv) +static void Theme_Barrel(int themeId, BYTE tv) { int r, xx, yy; const BYTE barrnds[4] = { 2, 6, 4, 8 }; const BYTE barrnd = barrnds[currLvl._dDunType - 1]; // TODO: use dType instead? - for (xx = DBORDERX; xx < DBORDERX + DSIZEX; xx++) { - for (yy = DBORDERY; yy < DBORDERY + DSIZEY; yy++) { + for (xx = themes[themeId]._tsx1; xx < themes[themeId]._tsx2; xx++) { + for (yy = themes[themeId]._tsy1; yy < themes[themeId]._tsy2; yy++) { if (dTransVal[xx][yy] == tv && !nSolidTable[dPiece[xx][yy]]) { if (random_low(0, barrnd) == 0) { r = random_low(0, barrnd) == 0 ? OBJ_BARREL : OBJ_BARRELEX; @@ -451,7 +454,7 @@ static void Theme_Barrel(BYTE tv) } } } - PlaceThemeMonsts(tv); + PlaceThemeMonsts(themeId, tv); } /** @@ -475,7 +478,7 @@ static void Theme_Shrine(int themeId, BYTE tv) AddObject(OBJ_SHRINEL, xx, yy); AddObject(OBJ_CANDLE2, xx, yy + 1); } - PlaceThemeMonsts(tv); + PlaceThemeMonsts(themeId, tv); } /** @@ -501,7 +504,7 @@ static void Theme_MonstPit(int themeId, BYTE tv) } done: - PlaceThemeMonsts(tv); + PlaceThemeMonsts(themeId, tv); } static void AddSkelMonster(int x, int y) @@ -581,16 +584,17 @@ static void Theme_SkelRoom(int themeId, BYTE tv) /** * Theme_Treasure initializes the treasure theme. * + * @param themeId: theme id. * @param tv: room id in the dungeon matrix. */ -static void Theme_Treasure(BYTE tv) +static void Theme_Treasure(int themeId, BYTE tv) { int xx, yy; const BYTE treasrnds[4] = { 6, 9, 7, 10 }; const BYTE treasrnd = treasrnds[currLvl._dDunType - 1]; // TODO: use dType instead? - for (xx = DBORDERX; xx < DBORDERX + DSIZEX; xx++) { - for (yy = DBORDERY; yy < DBORDERY + DSIZEY; yy++) { + for (xx = themes[themeId]._tsx1; xx < themes[themeId]._tsx2; xx++) { + for (yy = themes[themeId]._tsy1; yy < themes[themeId]._tsy2; yy++) { if (dTransVal[xx][yy] == tv && !nSolidTable[dPiece[xx][yy]]) { if (random_low(0, treasrnd) == 0) { CreateTypeItem(xx, yy, CFDQ_NORMAL, ITYPE_GOLD, IMISC_NONE, ICM_DELTA); @@ -600,7 +604,7 @@ static void Theme_Treasure(BYTE tv) } } } - PlaceThemeMonsts(tv); + PlaceThemeMonsts(themeId, tv); } /** @@ -628,8 +632,8 @@ static void Theme_Library(int themeId, BYTE tv) } librnd = librnds[currLvl._dDunType - 1]; // TODO: use dType instead? - for (xx = DBORDERX + 1; xx < DBORDERX + DSIZEX - 1; xx++) { - for (yy = DBORDERY + 1; yy < DBORDERY + DSIZEY - 1; yy++) { + for (xx = themes[themeId]._tsx1; xx < themes[themeId]._tsx2; xx++) { + for (yy = themes[themeId]._tsy1; yy < themes[themeId]._tsy2; yy++) { if (CheckThemeObj3(xx, yy, tv) && dMonster[xx][yy] == 0 && random_low(0, librnd) == 0) { oi = AddObject(OBJ_BOOK2L, xx, yy); if (random_low(0, 2 * librnd) != 0 && oi != -1) { /// BUGFIX: check AddObject succeeded (fixed) @@ -643,7 +647,7 @@ static void Theme_Library(int themeId, BYTE tv) if (/*QuestStatus(Q_ZHAR) &&*/ themeId == zharlib) return; - PlaceThemeMonsts(tv); + PlaceThemeMonsts(themeId, tv); } /** @@ -658,9 +662,9 @@ static void Theme_Torture(int themeId, BYTE tv) const BYTE tortrnd = tortrnds[currLvl._dDunType - 1]; // TODO: use dType instead? AddObject(random_(46, 2) ? OBJ_TNUDEW : OBJ_TNUDEM, themes[themeId]._tsObjX, themes[themeId]._tsObjY); - Place_Obj3(tv, OBJ_TNUDEM, tortrnd); - Place_Obj3(tv, OBJ_TNUDEW, tortrnd); - PlaceThemeMonsts(tv); + Place_Obj3(themeId, tv, OBJ_TNUDEM, tortrnd); + Place_Obj3(themeId, tv, OBJ_TNUDEW, tortrnd); + PlaceThemeMonsts(themeId, tv); } /** @@ -672,7 +676,7 @@ static void Theme_Torture(int themeId, BYTE tv) static void Theme_BloodFountain(int themeId, BYTE tv) { AddObject(OBJ_BLOODFTN, themes[themeId]._tsObjX, themes[themeId]._tsObjY); - PlaceThemeMonsts(tv); + PlaceThemeMonsts(themeId, tv); } /** @@ -687,8 +691,8 @@ static void Theme_Decap(int themeId, BYTE tv) const BYTE decaprnd = decaprnds[currLvl._dDunType - 1]; // TODO: use dType instead? AddObject(OBJ_DECAP, themes[themeId]._tsObjX, themes[themeId]._tsObjY); - Place_Obj3(tv, OBJ_DECAP, decaprnd); - PlaceThemeMonsts(tv); + Place_Obj3(themeId, tv, OBJ_DECAP, decaprnd); + PlaceThemeMonsts(themeId, tv); } /** @@ -700,7 +704,7 @@ static void Theme_Decap(int themeId, BYTE tv) static void Theme_PurifyingFountain(int themeId, BYTE tv) { AddObject(OBJ_PURIFYINGFTN, themes[themeId]._tsObjX, themes[themeId]._tsObjY); - PlaceThemeMonsts(tv); + PlaceThemeMonsts(themeId, tv); } /** @@ -716,8 +720,8 @@ static void Theme_ArmorStand(int themeId, BYTE tv) AddObject(_gbArmorFlag ? OBJ_ARMORSTAND : OBJ_ARMORSTANDN, themes[themeId]._tsObjX, themes[themeId]._tsObjY); _gbArmorFlag = false; - Place_Obj3(tv, OBJ_ARMORSTANDN, armorrnd); - PlaceThemeMonsts(tv); + Place_Obj3(themeId, tv, OBJ_ARMORSTANDN, armorrnd); + PlaceThemeMonsts(themeId, tv); } /** @@ -750,7 +754,7 @@ static void Theme_GoatShrine(int themeId, BYTE tv) static void Theme_Cauldron(int themeId, BYTE tv) { AddObject(OBJ_CAULDRON, themes[themeId]._tsObjX, themes[themeId]._tsObjY); - PlaceThemeMonsts(tv); + PlaceThemeMonsts(themeId, tv); } /** @@ -762,7 +766,7 @@ static void Theme_Cauldron(int themeId, BYTE tv) static void Theme_MurkyFountain(int themeId, BYTE tv) { AddObject(OBJ_MURKYFTN, themes[themeId]._tsObjX, themes[themeId]._tsObjY); - PlaceThemeMonsts(tv); + PlaceThemeMonsts(themeId, tv); } /** @@ -774,7 +778,7 @@ static void Theme_MurkyFountain(int themeId, BYTE tv) static void Theme_TearFountain(int themeId, BYTE tv) { AddObject(OBJ_TEARFTN, themes[themeId]._tsObjX, themes[themeId]._tsObjY); - PlaceThemeMonsts(tv); + PlaceThemeMonsts(themeId, tv); } /** @@ -789,8 +793,8 @@ static void Theme_BrnCross(int themeId, BYTE tv) const BYTE bcrossrnd = bcrossrnds[currLvl._dDunType - 1]; // TODO: use dType instead? AddObject(OBJ_TBCROSS, themes[themeId]._tsObjX, themes[themeId]._tsObjY); - Place_Obj3(tv, OBJ_TBCROSS, bcrossrnd); - PlaceThemeMonsts(tv); + Place_Obj3(themeId, tv, OBJ_TBCROSS, bcrossrnd); + PlaceThemeMonsts(themeId, tv); } /** @@ -812,8 +816,8 @@ static void Theme_WeaponRack(int themeId, BYTE tv) AddObject(type + (_gbWeaponFlag ? 0 : 1), themes[themeId]._tsObjX, themes[themeId]._tsObjY); _gbWeaponFlag = false; type += 1; - Place_Obj3(tv, type, weaponrnd); - PlaceThemeMonsts(tv); + Place_Obj3(themeId, tv, type, weaponrnd); + PlaceThemeMonsts(themeId, tv); } /** @@ -841,7 +845,7 @@ void CreateThemeRooms() tv = themes[i]._tsTransVal; switch (themes[i]._tsType) { case THEME_BARREL: - Theme_Barrel(tv); + Theme_Barrel(i, tv); break; case THEME_SHRINE: Theme_Shrine(i, tv); @@ -853,7 +857,7 @@ void CreateThemeRooms() Theme_SkelRoom(i, tv); break; case THEME_TREASURE: - Theme_Treasure(tv); + Theme_Treasure(i, tv); break; case THEME_LIBRARY: Theme_Library(i, tv); From a562ef62c4c08f746128ef1e6dde204044d0538e Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 27 Aug 2024 08:27:33 +0200 Subject: [PATCH 485/596] bugfix for vanilla (equipment vs. self-bonus) - prevent the equipment of an item using the power of that item --- Source/items.cpp | 50 ++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/Source/items.cpp b/Source/items.cpp index 5225f78fe95..18fb3dfd074 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -830,47 +830,51 @@ static void ItemStatOk(ItemStruct* is, int sa, int ma, int da) static void CalcItemReqs(int pnum) { int i; - bool changeflag; ItemStruct* pi; int sa, ma, da, sc, mc, dc; + int strReq[NUM_INVLOC]; + int magReq[NUM_INVLOC]; + int dexReq[NUM_INVLOC]; sa = plr._pBaseStr; ma = plr._pBaseMag; da = plr._pBaseDex; pi = plr._pInvBody; - for (i = NUM_INVLOC; i != 0; i--, pi++) { + for (i = 0; i < NUM_INVLOC; i++, pi++) { if (pi->_itype != ITYPE_NONE) { pi->_iStatFlag = TRUE; //if (pi->_iIdentified) { sa += pi->_iPLStr; ma += pi->_iPLMag; da += pi->_iPLDex; + strReq[i] = pi->_iMinStr == 0 ? INT_MIN : pi->_iMinStr + (pi->_iPLStr > 0 ? pi->_iPLStr : 0); + magReq[i] = pi->_iMinMag == 0 ? INT_MIN : pi->_iMinMag + (pi->_iPLMag > 0 ? pi->_iPLMag : 0); + dexReq[i] = pi->_iMinDex == 0 ? INT_MIN : pi->_iMinDex + (pi->_iPLDex > 0 ? pi->_iPLDex : 0); //} } } - do { - changeflag = false; - sc = std::max(0, sa); - mc = std::max(0, ma); - dc = std::max(0, da); - pi = plr._pInvBody; - for (i = NUM_INVLOC; i != 0; i--, pi++) { - if (pi->_itype == ITYPE_NONE) - continue; - if (sc >= pi->_iMinStr && mc >= pi->_iMinMag && dc >= pi->_iMinDex) - continue; - if (pi->_iStatFlag) { - pi->_iStatFlag = FALSE; - changeflag = true; - //if (pi->_iIdentified) { - sa -= pi->_iPLStr; - ma -= pi->_iPLMag; - da -= pi->_iPLDex; - //} - } +recheck: + pi = plr._pInvBody; + for (i = 0; i < NUM_INVLOC; i++, pi++) { + if (pi->_itype == ITYPE_NONE) + continue; + if (sa >= strReq[i] && ma >= magReq[i] && da >= dexReq[i]) + continue; + if (pi->_iStatFlag) { + pi->_iStatFlag = FALSE; + //if (pi->_iIdentified) { + sa -= pi->_iPLStr; + ma -= pi->_iPLMag; + da -= pi->_iPLDex; + //} + goto recheck; } - } while (changeflag); + } + + sc = std::max(0, sa); + mc = std::max(0, ma); + dc = std::max(0, da); pi = &plr._pHoldItem; ItemStatOk(pi, sc, mc, dc); From d3378df99d8dc2b58e07cef3474e94b9dfbd8d31 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 27 Aug 2024 10:24:33 +0200 Subject: [PATCH 486/596] fix warnings of possible overflow after multiplication --- 3rdParty/libsmacker/smacker.c | 2 +- tools/patcher/DiabloUI/patcher.cpp | 2 +- tools/patcher/drlp_l2.cpp | 45 +++++++++++------------------- tools/patcher/drlp_l3.cpp | 24 ++++++---------- 4 files changed, 26 insertions(+), 47 deletions(-) diff --git a/3rdParty/libsmacker/smacker.c b/3rdParty/libsmacker/smacker.c index 3f7989b27bd..ba4c5c43db3 100644 --- a/3rdParty/libsmacker/smacker.c +++ b/3rdParty/libsmacker/smacker.c @@ -1148,7 +1148,7 @@ static smk smk_open_generic(union smk_read_t fp, unsigned long size) /* clean up */ smk_free(hufftree_chunk); /* Go ahead and malloc storage for the video frame */ - smk_malloc(s->video.frame, s->video.w * s->video.h); + smk_malloc(s->video.frame, (size_t)s->video.w * s->video.h); #ifdef FULL /* final processing: depending on ProcessMode, handle what to do with rest of file data */ s->mode = process_mode; diff --git a/tools/patcher/DiabloUI/patcher.cpp b/tools/patcher/DiabloUI/patcher.cpp index aef8922a799..b8bb6966509 100644 --- a/tools/patcher/DiabloUI/patcher.cpp +++ b/tools/patcher/DiabloUI/patcher.cpp @@ -2009,7 +2009,7 @@ static BYTE* ReEncodeCL2(BYTE* cl2Buf, size_t *dwLen, int numGroups, int frameCo const BYTE* frameBuf = CelGetFrameStart(cl2Buf, ii); for (int n = 1; n <= ni; n++) { - memset(&gpBuffer[0], TRANS_COLOR, BUFFER_WIDTH * height); + memset(&gpBuffer[0], TRANS_COLOR, (size_t)BUFFER_WIDTH * height); Cl2Draw(0, height - 1, frameBuf, n, width); BYTE* frameSrc = &gpBuffer[0 + (height - 1) * BUFFER_WIDTH]; diff --git a/tools/patcher/drlp_l2.cpp b/tools/patcher/drlp_l2.cpp index 100022dbbb5..83c25fef5b0 100644 --- a/tools/patcher/drlp_l2.cpp +++ b/tools/patcher/drlp_l2.cpp @@ -11,15 +11,9 @@ DEVILUTION_BEGIN_NAMESPACE BYTE* DRLP_L2_PatchDoors(BYTE* celBuf, size_t* celLen) { - typedef struct { - int frameIndex; - int frameWidth; - int frameHeight; - } CelFrame; - const CelFrame frames[] = { - { 0, 64, 128 }, - { 1, 64, 128 }, - }; + const int frames[] = { 0, 1 }; + constexpr int FRAME_WIDTH = 64; + constexpr int FRAME_HEIGHT = 128; constexpr BYTE TRANS_COLOR = 128; constexpr BYTE SUB_HEADER_SIZE = 10; @@ -40,11 +34,11 @@ BYTE* DRLP_L2_PatchDoors(BYTE* celBuf, size_t* celLen) BYTE* dstDataCursor = resCelBuf + 4 * (srcCelEntries + 2); for (int i = 0; i < srcCelEntries; i++) { - const CelFrame &frame = frames[idx]; - if (i == frame.frameIndex) { + const int frameIndex = frames[idx]; + if (i == frameIndex) { // draw the frame to the back-buffer - memset(&gpBuffer[0], TRANS_COLOR, frame.frameHeight * BUFFER_WIDTH); - CelClippedDraw(0, frame.frameHeight - 1, celBuf, frame.frameIndex + 1, frame.frameWidth); + memset(&gpBuffer[0], TRANS_COLOR, (size_t)FRAME_HEIGHT * BUFFER_WIDTH); + CelClippedDraw(0, FRAME_HEIGHT - 1, celBuf, frameIndex + 1, FRAME_WIDTH); if (idx == 0) { for (int y = 44; y < 55; y++) { @@ -63,7 +57,7 @@ BYTE* DRLP_L2_PatchDoors(BYTE* celBuf, size_t* celLen) dstHeaderCursor[0] = SwapLE32((size_t)dstDataCursor - (size_t)resCelBuf); dstHeaderCursor++; - dstDataCursor = EncodeFrame(dstDataCursor, frame.frameWidth, frame.frameHeight, SUB_HEADER_SIZE, TRANS_COLOR); + dstDataCursor = EncodeFrame(dstDataCursor, FRAME_WIDTH, FRAME_HEIGHT, SUB_HEADER_SIZE, TRANS_COLOR); // skip the original frame srcHeaderCursor++; @@ -87,16 +81,9 @@ BYTE* DRLP_L2_PatchDoors(BYTE* celBuf, size_t* celLen) BYTE* DRLP_L2_PatchSpec(BYTE* celBuf, size_t* celLen) { - typedef struct { - int frameIndex; - int frameWidth; - int frameHeight; - } CelFrame; - const CelFrame frames[] = { - { 0, 64, 160 }, - { 1, 64, 160 }, - { 4, 64, 160 }, - }; + const int frames[] = { 0, 1, 4 }; + constexpr int FRAME_WIDTH = 64; + constexpr int FRAME_HEIGHT = 160; constexpr BYTE TRANS_COLOR = 128; constexpr BYTE SUB_HEADER_SIZE = 10; @@ -117,11 +104,11 @@ BYTE* DRLP_L2_PatchSpec(BYTE* celBuf, size_t* celLen) BYTE* dstDataCursor = resCelBuf + 4 * (srcCelEntries + 2); for (int i = 0; i < srcCelEntries; i++) { - const CelFrame &frame = frames[idx]; - if (i == frame.frameIndex) { + const int frameIndex = frames[idx]; + if (i == frameIndex) { // draw the frame to the back-buffer - memset(&gpBuffer[0], TRANS_COLOR, frame.frameHeight * BUFFER_WIDTH); - CelClippedDraw(0, frame.frameHeight - 1, celBuf, frame.frameIndex + 1, frame.frameWidth); + memset(&gpBuffer[0], TRANS_COLOR, (size_t)FRAME_HEIGHT * BUFFER_WIDTH); + CelClippedDraw(0, FRAME_HEIGHT - 1, celBuf, frameIndex + 1, FRAME_WIDTH); if (idx == 0) { gpBuffer[10 + 52 * BUFFER_WIDTH] = 55; @@ -152,7 +139,7 @@ BYTE* DRLP_L2_PatchSpec(BYTE* celBuf, size_t* celLen) dstHeaderCursor[0] = SwapLE32((size_t)dstDataCursor - (size_t)resCelBuf); dstHeaderCursor++; - dstDataCursor = EncodeFrame(dstDataCursor, frame.frameWidth, frame.frameHeight, SUB_HEADER_SIZE, TRANS_COLOR); + dstDataCursor = EncodeFrame(dstDataCursor, FRAME_WIDTH, FRAME_HEIGHT, SUB_HEADER_SIZE, TRANS_COLOR); // skip the original frame srcHeaderCursor++; diff --git a/tools/patcher/drlp_l3.cpp b/tools/patcher/drlp_l3.cpp index 56b345b46b0..2373f1800c6 100644 --- a/tools/patcher/drlp_l3.cpp +++ b/tools/patcher/drlp_l3.cpp @@ -11,17 +11,9 @@ DEVILUTION_BEGIN_NAMESPACE BYTE* DRLP_L3_PatchDoors(BYTE* celBuf, size_t* celLen) { - typedef struct { - int frameIndex; - int frameWidth; - int frameHeight; - } CelFrame; - const CelFrame frames[] = { - { 0, 64, 128 }, - { 1, 64, 128 }, - { 2, 64, 128 }, - { 3, 64, 128 }, - }; + const int frames[] = { 0, 1, 2, 3 }; + constexpr int FRAME_WIDTH = 64; + constexpr int FRAME_HEIGHT = 128; constexpr BYTE TRANS_COLOR = 128; constexpr BYTE SUB_HEADER_SIZE = 10; @@ -42,11 +34,11 @@ BYTE* DRLP_L3_PatchDoors(BYTE* celBuf, size_t* celLen) BYTE* dstDataCursor = resCelBuf + 4 * (srcCelEntries + 2); for (int i = 0; i < srcCelEntries; i++) { - const CelFrame &frame = frames[idx]; - if (i == frame.frameIndex) { + const int frameIndex = frames[idx]; + if (i == frameIndex) { // draw the frame to the back-buffer - memset(&gpBuffer[0], TRANS_COLOR, frame.frameHeight * BUFFER_WIDTH); - CelClippedDraw(0, frame.frameHeight - 1, celBuf, frame.frameIndex + 1, frame.frameWidth); + memset(&gpBuffer[0], TRANS_COLOR, (size_t)FRAME_HEIGHT * BUFFER_WIDTH); + CelClippedDraw(0, FRAME_HEIGHT - 1, celBuf, frameIndex + 1, FRAME_WIDTH); if (idx == 0) { // add shadows @@ -359,7 +351,7 @@ BYTE* DRLP_L3_PatchDoors(BYTE* celBuf, size_t* celLen) dstHeaderCursor[0] = SwapLE32((size_t)dstDataCursor - (size_t)resCelBuf); dstHeaderCursor++; - dstDataCursor = EncodeFrame(dstDataCursor, frame.frameWidth, frame.frameHeight, SUB_HEADER_SIZE, TRANS_COLOR); + dstDataCursor = EncodeFrame(dstDataCursor, FRAME_WIDTH, FRAME_HEIGHT, SUB_HEADER_SIZE, TRANS_COLOR); // skip the original frame srcHeaderCursor++; From ebf5dd3a409713f398e7a0d4f302056b16ab33e1 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 27 Aug 2024 12:09:06 +0200 Subject: [PATCH 487/596] update SDL2 --- 3rdParty/SDL2/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdParty/SDL2/CMakeLists.txt b/3rdParty/SDL2/CMakeLists.txt index f3eeabed6cd..7b7ead2a18b 100644 --- a/3rdParty/SDL2/CMakeLists.txt +++ b/3rdParty/SDL2/CMakeLists.txt @@ -75,7 +75,7 @@ FetchContent_Declare(SDL2 #URL https://github.com/libsdl-org/SDL/archive/5056b29b0f8611b470d8b8bdb313eab628f8bd6e.tar.gz #URL_HASH MD5=3fb6d72c33434082c32d2649c35c6502 GIT_REPOSITORY https://github.com/pionere/SDL.git - GIT_TAG 808dd1496ddafddc933c3ca31155e2ca593b5d67 + GIT_TAG 839e98c66a22f6792cf60f67002c22e1f40d3296 ) FetchContent_MakeAvailableExcludeFromAll(SDL2) From 02bea01bdab97e25a3d4dfa26fca6f46f10dbace Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 27 Aug 2024 12:29:54 +0200 Subject: [PATCH 488/596] turn off clang-format check completely --- .github/workflows/clang-format-check.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/clang-format-check.yml b/.github/workflows/clang-format-check.yml index 9870f1e99ab..96c5cbec722 100644 --- a/.github/workflows/clang-format-check.yml +++ b/.github/workflows/clang-format-check.yml @@ -1,10 +1,9 @@ name: clang-format check -on: [push, pull_request] +#on: [push, pull_request] jobs: formatting-check: - if: false name: Formatting Check runs-on: ubuntu-latest strategy: From 1f1b87cfb67407cc756ed48f456f5141ec962057 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 27 Aug 2024 12:31:24 +0200 Subject: [PATCH 489/596] give only the necessary permissions to CodeQL --- .github/workflows/code-ql.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/code-ql.yml b/.github/workflows/code-ql.yml index 037646234e2..98dd9710251 100644 --- a/.github/workflows/code-ql.yml +++ b/.github/workflows/code-ql.yml @@ -26,11 +26,11 @@ jobs: security-events: write # required to fetch internal or private CodeQL packs - packages: read + #packages: read # only required for workflows in private repositories - actions: read - contents: read + #actions: read + #contents: read strategy: fail-fast: false @@ -76,13 +76,13 @@ jobs: # to build your code. # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - name: Create Build Environment + - name: Create Build Environment if: matrix.build-mode == 'manual' - run: > - sudo apt-get update && - sudo apt install -y cmake gcc-mingw-w64-i686 g++-mingw-w64-i686 pkg-config-mingw-w64-i686 libz-mingw-w64-dev gettext dpkg-dev wget git sudo && - sudo rm /usr/i686-w64-mingw32/lib/libz.dll.a && - sudo Packaging/windows/mingw-prep.sh + run: > + sudo apt-get update && + sudo apt install -y cmake gcc-mingw-w64-i686 g++-mingw-w64-i686 pkg-config-mingw-w64-i686 libz-mingw-w64-dev gettext dpkg-dev wget git sudo && + sudo rm /usr/i686-w64-mingw32/lib/libz.dll.a && + sudo Packaging/windows/mingw-prep.sh - name: Build if: matrix.build-mode == 'manual' From 179f14894dcacc64951fc7b02690bc80ed2cc236 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 27 Aug 2024 12:38:30 +0200 Subject: [PATCH 490/596] add more build options to CodeQL --- .github/workflows/code-ql.yml | 60 +++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/.github/workflows/code-ql.yml b/.github/workflows/code-ql.yml index 98dd9710251..af72de48113 100644 --- a/.github/workflows/code-ql.yml +++ b/.github/workflows/code-ql.yml @@ -13,13 +13,13 @@ on: # jobs: analyze: - name: Analyze (${{ matrix.language }}) + name: Analyze (${{ matrix.name }}) # Runner size impacts CodeQL analysis time. To learn more, please see: # - https://gh.io/recommended-hardware-resources-for-running-codeql # - https://gh.io/supported-runners-and-hardware-resources # - https://gh.io/using-larger-runners (GitHub.com only) # Consider using larger runners or machines with greater resources for possible analysis time improvements. - runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || (matrix.version == 'mac-x64' && 'macos-12') || 'ubuntu-latest' }} timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} permissions: # required for all workflows @@ -36,12 +36,34 @@ jobs: fail-fast: false matrix: include: - - language: c-cpp - #build-mode: autobuild + #- name: c-cpp (auto) + # language: c-cpp + # build-mode: autobuild + #- name: c-cpp (win-x86) + # language: c-cpp + # build-mode: manual + # version: win-x86 + # cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON -DCMAKE_TOOLCHAIN_FILE=../CMake/mingwcc.toolchain.cmake' + - name: c-cpp (win-x64) + language: c-cpp build-mode: manual - - language: java-kotlin + version: win-x64 + cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON -DCMAKE_TOOLCHAIN_FILE=../CMake/mingwcc64.toolchain.cmake' + #- name: c-cpp (linux-x64) + # language: c-cpp + # build-mode: manual + # version: linux-x64 + # cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON -DCMAKE_INSTALL_PREFIX=/usr' + #- name: c-cpp (mac-x64) + # language: c-cpp + # build-mode: manual + # version: mac-x64 + # cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON -DMACOSX_STANDALONE_APP_BUNDLE=ON' + - name: java + language: java-kotlin build-mode: none # This mode only analyzes Java. Set this to 'autobuild' or 'manual' to analyze Kotlin too. - - language: python + - name: python + language: python build-mode: none #- language: ruby # build-mode: none @@ -63,6 +85,7 @@ jobs: with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} + #debug: true # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. @@ -77,22 +100,39 @@ jobs: # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - name: Create Build Environment - if: matrix.build-mode == 'manual' + if: matrix.version == 'win-x86' run: > sudo apt-get update && sudo apt install -y cmake gcc-mingw-w64-i686 g++-mingw-w64-i686 pkg-config-mingw-w64-i686 libz-mingw-w64-dev gettext dpkg-dev wget git sudo && sudo rm /usr/i686-w64-mingw32/lib/libz.dll.a && sudo Packaging/windows/mingw-prep.sh + - name: Create Build Environment + if: matrix.version == 'win-x64' + run: > + sudo apt-get update && + sudo apt-get install -y cmake gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 pkg-config-mingw-w64-x86-64 libz-mingw-w64-dev dpkg-dev wget git sudo && + sudo rm /usr/x86_64-w64-mingw32/lib/libz.dll.a && + sudo Packaging/windows/mingw-prep.sh + + - name: Create Build Environment + if: matrix.version == 'linux-x64' + run: Packaging/nix/debian-host-prep.sh + + - name: Create Build Environment + if: matrix.version == 'mac-x64' + run: brew bundle install + + # TODO: -j $(nproc) vs. -j $(sysctl -n hw.physicalcpu) - name: Build if: matrix.build-mode == 'manual' shell: bash run: | - cmake -S. -Bbuild -DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON -DCMAKE_BUILD_TYPE="Release" -DCMAKE_TOOLCHAIN_FILE=../CMake/mingwcc.toolchain.cmake - cmake --build build -j $(nproc) --target package + cmake -S. -Bbuild ${{ matrix.cmakeargs }} -DCMAKE_BUILD_TYPE="Release" && \ + cmake --build build --target package - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 with: - category: "/language:${{matrix.language}}" + category: "/language:${{matrix.language}}${{matrix.version}}" From 8b3874f1f93c9ae02d939c3dc2eb5b0e3c1c7d9c Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 28 Aug 2024 08:26:20 +0200 Subject: [PATCH 491/596] get rid of the unused source files --- Source/utils/endian.hpp | 31 --------- Source/utils/enum_traits.h | 59 ---------------- Source/utils/sdl_bilinear_scale.cpp | 101 ---------------------------- Source/utils/sdl_bilinear_scale.hpp | 21 ------ Source/utils/sdl_geometry.h | 23 ------- Source/utils/sdl_ptrs.h | 80 ---------------------- tools/patcher/utils/endian.hpp | 31 --------- tools/patcher/utils/sdl_geometry.h | 23 ------- tools/patcher/utils/sdl_ptrs.h | 80 ---------------------- 9 files changed, 449 deletions(-) delete mode 100644 Source/utils/endian.hpp delete mode 100644 Source/utils/enum_traits.h delete mode 100644 Source/utils/sdl_bilinear_scale.cpp delete mode 100644 Source/utils/sdl_bilinear_scale.hpp delete mode 100644 Source/utils/sdl_geometry.h delete mode 100644 Source/utils/sdl_ptrs.h delete mode 100644 tools/patcher/utils/endian.hpp delete mode 100644 tools/patcher/utils/sdl_geometry.h delete mode 100644 tools/patcher/utils/sdl_ptrs.h diff --git a/Source/utils/endian.hpp b/Source/utils/endian.hpp deleted file mode 100644 index 6655195b81a..00000000000 --- a/Source/utils/endian.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include - -DEVILUTION_BEGIN_NAMESPACE - -template -constexpr std::uint16_t LoadLE16(const T* b) -{ - static_assert(sizeof(T) == 1, "invalid argument"); - // NOLINTNEXTLINE(readability-magic-numbers) - return (static_cast(b[1]) << 8) | static_cast(b[0]); -} - -template -constexpr std::uint32_t LoadLE32(const T* b) -{ - static_assert(sizeof(T) == 1, "invalid argument"); - // NOLINTNEXTLINE(readability-magic-numbers) - return (static_cast(b[3]) << 24) | (static_cast(b[2]) << 16) | (static_cast(b[1]) << 8) | static_cast(b[0]); -} - -template -constexpr std::uint32_t LoadBE32(const T* b) -{ - static_assert(sizeof(T) == 1, "invalid argument"); - // NOLINTNEXTLINE(readability-magic-numbers) - return (static_cast(b[0]) << 24) | (static_cast(b[1]) << 16) | (static_cast(b[2]) << 8) | static_cast(b[3]); -} - -DEVILUTION_END_NAMESPACE diff --git a/Source/utils/enum_traits.h b/Source/utils/enum_traits.h deleted file mode 100644 index 3f2c6618cdd..00000000000 --- a/Source/utils/enum_traits.h +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @file enum_traits.h - * - * Base template for 'enum_traits' which allow us to access static information about an enum. - */ -#pragma once - -#include -#include "../defs.h" - -DEVILUTION_BEGIN_NAMESPACE - -template -struct enum_size { - constexpr static const std::size_t value = static_cast(T::LAST) + 1; -}; - -template -class enum_values { -public: - class Iterator { - typename std::underlying_type::type m_value; - - public: - Iterator(typename std::underlying_type::type value) - : m_value(value) - { - } - - const T operator*() const - { - return static_cast(m_value); - } - - void operator++() - { - m_value++; - } - - bool operator!=(Iterator rhs) const - { - return m_value != rhs.m_value; - } - }; -}; - -template -typename enum_values::Iterator begin(enum_values) -{ - return typename enum_values::Iterator(static_cast::type>(T::FIRST)); -} - -template -typename enum_values::Iterator end(enum_values) -{ - return typename enum_values::Iterator(static_cast::type>(T::LAST) + 1); -} - -DEVILUTION_END_NAMESPACE diff --git a/Source/utils/sdl_bilinear_scale.cpp b/Source/utils/sdl_bilinear_scale.cpp deleted file mode 100644 index d2c5acae1d6..00000000000 --- a/Source/utils/sdl_bilinear_scale.cpp +++ /dev/null @@ -1,101 +0,0 @@ -#include "utils/sdl_bilinear_scale.hpp" - -#include -#include - -// Performs bilinear scaling using fixed-width integer math. - -namespace devilution { - -namespace { - -unsigned Frac(unsigned fixedPoint) -{ - return fixedPoint & 0xffff; -} - -unsigned ToInt(unsigned fixedPoint) -{ - return fixedPoint >> 16; -} - -std::unique_ptr CreateMixFactors(unsigned srcSize, unsigned dstSize) -{ - std::unique_ptr result { new unsigned[dstSize + 1] }; - const auto scale = static_cast(65536.0 * static_cast(srcSize - 1) / dstSize); - unsigned mix = 0; - for (unsigned i = 0; i <= dstSize; ++i) { - result[i] = mix; - mix = Frac(mix) + scale; - } - return result; -}; - -std::uint8_t MixColors(std::uint8_t first, std::uint8_t second, unsigned ratio) -{ - return ToInt((second - first) * ratio) + first; -} - -} // namespace - -void BilinearScale32(SDL_Surface* src, SDL_Surface* dst) -{ - const std::unique_ptr mixXs = CreateMixFactors(src->w, dst->w); - const std::unique_ptr mixYs = CreateMixFactors(src->h, dst->h); - - const unsigned dgap = dst->pitch - dst->w * 4; - - auto* srcPixels = static_cast(src->pixels); - auto* dstPixels = static_cast(dst->pixels); - - unsigned* curMixY = &mixYs[0]; - unsigned srcY = 0; - for (unsigned y = 0; y < static_cast(dst->h); ++y) { - std::uint8_t* s[4] = { - srcPixels, // Self - srcPixels + 4, // Right - srcPixels + src->pitch, // Bottom - srcPixels + src->pitch + 4 // Bottom right - }; - - unsigned* curMixX = &mixXs[0]; - unsigned srcX = 0; - for (unsigned x = 0; x < static_cast(dst->w); ++x) { - const unsigned mixX = Frac(*curMixX); - const unsigned mixY = Frac(*curMixY); - for (unsigned channel = 0; channel < 4; ++channel) { - dstPixels[channel] = MixColors( - MixColors(s[0][channel], s[1][channel], mixX), - MixColors(s[2][channel], s[3][channel], mixX), - mixY); - } - - ++curMixX; - if (*curMixX > 0) { - unsigned step = ToInt(*curMixX); - srcX += step; - if (srcX <= static_cast(src->w)) { - step *= 4; - for (auto& v : s) { - v += step; - } - } - } - - dstPixels += 4; - } - - ++curMixY; - if (*curMixY > 0) { - const unsigned step = ToInt(*curMixY); - srcY += step; - if (srcY < static_cast(src->h)) { - srcPixels += step * src->pitch; - } - } - - dstPixels += dgap; - } -} - -} // namespace devilution diff --git a/Source/utils/sdl_bilinear_scale.hpp b/Source/utils/sdl_bilinear_scale.hpp deleted file mode 100644 index dfbb86a9cdb..00000000000 --- a/Source/utils/sdl_bilinear_scale.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include - -#if SDL_VERSION_ATLEAST(2, 0, 0) -#include -#else -#include -#endif - -#include "../defs.h" - -DEVILUTION_BEGIN_NAMESPACE - -/** - * @brief Bilinear 32-bit scaling. - * Requires `src` and `dst` to have the same pixel format (ARGB8888 or RGBA8888). - */ -void BilinearScale32(SDL_Surface* src, SDL_Surface* dst); - -DEVILUTION_END_NAMESPACE diff --git a/Source/utils/sdl_geometry.h b/Source/utils/sdl_geometry.h deleted file mode 100644 index 6d1dd80fa82..00000000000 --- a/Source/utils/sdl_geometry.h +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @file sdl_geometry.h - * Helpers for SDL geometry types - */ -#pragma once - -#include - -#if SDL_VERSION_ATLEAST(2, 0, 0) -#include -#else -#include -#endif - -/** - * @brief Same as constructing directly but avoids type conversion warnings. - */ -inline SDL_Rect MakeSdlRect( - decltype(SDL_Rect {}.x) x, decltype(SDL_Rect {}.y) y, - decltype(SDL_Rect {}.w) w, decltype(SDL_Rect {}.h) h) -{ - return SDL_Rect { x, y, w, h }; -} diff --git a/Source/utils/sdl_ptrs.h b/Source/utils/sdl_ptrs.h deleted file mode 100644 index 35c9953cb76..00000000000 --- a/Source/utils/sdl_ptrs.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once -/** - * @brief std::unique_ptr specializations for SDL types. - */ - -#include -#include - -#include -#include "utils/sdl2_to_1_2_backports.h" -#include "utils/sdl2_backports.h" - -#include "../defs.h" - -DEVILUTION_BEGIN_NAMESPACE - -/** - * @brief Deletes the SDL surface using `SDL_FreeSurface`. - */ -struct SDLSurfaceDeleter { - void operator()(SDL_Surface* surface) const - { - SDL_FreeSurface(surface); - } -}; - -using SDLSurfaceUniquePtr = std::unique_ptr; - -#if SDL_VERSION_ATLEAST(2, 0, 0) -struct SDLCursorDeleter { - void operator()(SDL_Cursor* cursor) const - { - SDL_FreeCursor(cursor); - } -}; - -using SDLCursorUniquePtr = std::unique_ptr; -#endif - -#ifndef USE_SDL1 -struct SDLTextureDeleter { - void operator()(SDL_Texture* texture) const - { - SDL_DestroyTexture(texture); - } -}; - -using SDLTextureUniquePtr = std::unique_ptr; -#endif - -struct SDLPaletteDeleter { - void operator()(SDL_Palette* palette) const - { - SDL_FreePalette(palette); - } -}; - -using SDLPaletteUniquePtr = std::unique_ptr; - -/** - * @brief Deletes the object using `SDL_free`. - */ -template -struct SDLFreeDeleter { - static_assert(!std::is_same::value, - "SDL_Surface should use SDLSurfaceUniquePtr instead."); - - void operator()(T* obj) const - { - SDL_free(obj); - } -}; - -/** - * @brief A unique pointer to T that is deleted with SDL_free. - */ -template -using SDLUniquePtr = std::unique_ptr>; - -DEVILUTION_END_NAMESPACE diff --git a/tools/patcher/utils/endian.hpp b/tools/patcher/utils/endian.hpp deleted file mode 100644 index 6655195b81a..00000000000 --- a/tools/patcher/utils/endian.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include - -DEVILUTION_BEGIN_NAMESPACE - -template -constexpr std::uint16_t LoadLE16(const T* b) -{ - static_assert(sizeof(T) == 1, "invalid argument"); - // NOLINTNEXTLINE(readability-magic-numbers) - return (static_cast(b[1]) << 8) | static_cast(b[0]); -} - -template -constexpr std::uint32_t LoadLE32(const T* b) -{ - static_assert(sizeof(T) == 1, "invalid argument"); - // NOLINTNEXTLINE(readability-magic-numbers) - return (static_cast(b[3]) << 24) | (static_cast(b[2]) << 16) | (static_cast(b[1]) << 8) | static_cast(b[0]); -} - -template -constexpr std::uint32_t LoadBE32(const T* b) -{ - static_assert(sizeof(T) == 1, "invalid argument"); - // NOLINTNEXTLINE(readability-magic-numbers) - return (static_cast(b[0]) << 24) | (static_cast(b[1]) << 16) | (static_cast(b[2]) << 8) | static_cast(b[3]); -} - -DEVILUTION_END_NAMESPACE diff --git a/tools/patcher/utils/sdl_geometry.h b/tools/patcher/utils/sdl_geometry.h deleted file mode 100644 index 6d1dd80fa82..00000000000 --- a/tools/patcher/utils/sdl_geometry.h +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @file sdl_geometry.h - * Helpers for SDL geometry types - */ -#pragma once - -#include - -#if SDL_VERSION_ATLEAST(2, 0, 0) -#include -#else -#include -#endif - -/** - * @brief Same as constructing directly but avoids type conversion warnings. - */ -inline SDL_Rect MakeSdlRect( - decltype(SDL_Rect {}.x) x, decltype(SDL_Rect {}.y) y, - decltype(SDL_Rect {}.w) w, decltype(SDL_Rect {}.h) h) -{ - return SDL_Rect { x, y, w, h }; -} diff --git a/tools/patcher/utils/sdl_ptrs.h b/tools/patcher/utils/sdl_ptrs.h deleted file mode 100644 index 35c9953cb76..00000000000 --- a/tools/patcher/utils/sdl_ptrs.h +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once -/** - * @brief std::unique_ptr specializations for SDL types. - */ - -#include -#include - -#include -#include "utils/sdl2_to_1_2_backports.h" -#include "utils/sdl2_backports.h" - -#include "../defs.h" - -DEVILUTION_BEGIN_NAMESPACE - -/** - * @brief Deletes the SDL surface using `SDL_FreeSurface`. - */ -struct SDLSurfaceDeleter { - void operator()(SDL_Surface* surface) const - { - SDL_FreeSurface(surface); - } -}; - -using SDLSurfaceUniquePtr = std::unique_ptr; - -#if SDL_VERSION_ATLEAST(2, 0, 0) -struct SDLCursorDeleter { - void operator()(SDL_Cursor* cursor) const - { - SDL_FreeCursor(cursor); - } -}; - -using SDLCursorUniquePtr = std::unique_ptr; -#endif - -#ifndef USE_SDL1 -struct SDLTextureDeleter { - void operator()(SDL_Texture* texture) const - { - SDL_DestroyTexture(texture); - } -}; - -using SDLTextureUniquePtr = std::unique_ptr; -#endif - -struct SDLPaletteDeleter { - void operator()(SDL_Palette* palette) const - { - SDL_FreePalette(palette); - } -}; - -using SDLPaletteUniquePtr = std::unique_ptr; - -/** - * @brief Deletes the object using `SDL_free`. - */ -template -struct SDLFreeDeleter { - static_assert(!std::is_same::value, - "SDL_Surface should use SDLSurfaceUniquePtr instead."); - - void operator()(T* obj) const - { - SDL_free(obj); - } -}; - -/** - * @brief A unique pointer to T that is deleted with SDL_free. - */ -template -using SDLUniquePtr = std::unique_ptr>; - -DEVILUTION_END_NAMESPACE From b6e5098d4a6b8cd9284b2fed396fca3133ad12c3 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 28 Aug 2024 10:34:30 +0200 Subject: [PATCH 492/596] assume theme-rooms are rectangles --- Source/themes.cpp | 207 ++++++++++++++++++++++------------------------ 1 file changed, 97 insertions(+), 110 deletions(-) diff --git a/Source/themes.cpp b/Source/themes.cpp index 45d15dd6cfe..4b1c722f040 100644 --- a/Source/themes.cpp +++ b/Source/themes.cpp @@ -56,12 +56,12 @@ static const int trm3y[] = { static int TFit_Shrine(int themeId) { int xx, yy, numMatches; - BYTE tv = themes[themeId]._tsTransVal; numMatches = 0; - for (xx = themes[themeId]._tsx1; xx < themes[themeId]._tsx2; xx++) { - for (yy = themes[themeId]._tsy1; yy < themes[themeId]._tsy2; yy++) { - if (dTransVal[xx][yy] == tv && !nSolidTable[dPiece[xx][yy]]) { + yy = themes[themeId]._tsy1; + for (xx = themes[themeId]._tsx1 + 1; xx < themes[themeId]._tsx2 - 1; xx++) { + // assert(dTransVal[xx][yy] == themes[themeId]._tsTransVal && dTransVal[xx - 1][yy] == themes[themeId]._tsTransVal && dTransVal[xx + 1][yy] == themes[themeId]._tsTransVal); + if (/*dTransVal[xx][yy] == tv &&*/ !nSolidTable[dPiece[xx][yy]]) { if ((nSpecTrapTable[dPiece[xx][yy - 1]] & PST_TRAP_TYPE) != PST_NONE // make sure the place is wide enough // - on the inside @@ -71,8 +71,8 @@ static int TFit_Shrine(int themeId) && nSolidTable[dPiece[xx - 1][yy - 1]] && nSolidTable[dPiece[xx + 1][yy - 1]] // make sure it is in the same room - && dTransVal[xx - 1][yy] == tv - && dTransVal[xx + 1][yy] == tv) { + /*&& dTransVal[xx - 1][yy] == tv + && dTransVal[xx + 1][yy] == tv*/) { // assert(dObject[xx][yy] == 0); // assert(dObject[xx - 1][yy] == 0); // assert(dObject[xx + 1][yy] == 0); @@ -85,6 +85,11 @@ static int TFit_Shrine(int themeId) // if (numMatches == lengthof(drlg.thLocs)) // goto done; } + } + xx = themes[themeId]._tsx1; + for (yy = themes[themeId]._tsy1 + 1; yy < themes[themeId]._tsy2 - 1; yy++) { + // assert(dTransVal[xx][yy] == themes[themeId]._tsTransVal && dTransVal[xx][yy - 1] == themes[themeId]._tsTransVal && dTransVal[xx][yy + 1] == themes[themeId]._tsTransVal); + if (/*dTransVal[xx][yy] == tv &&*/ !nSolidTable[dPiece[xx][yy]]) { if ((nSpecTrapTable[dPiece[xx - 1][yy]] & PST_TRAP_TYPE) != PST_NONE // make sure the place is wide enough // - on the inside @@ -94,8 +99,8 @@ static int TFit_Shrine(int themeId) && nSolidTable[dPiece[xx - 1][yy - 1]] && nSolidTable[dPiece[xx - 1][yy + 1]] // make sure it is in the same room - && dTransVal[xx][yy - 1] == tv - && dTransVal[xx][yy + 1] == tv) { + /*&& dTransVal[xx][yy - 1] == tv + && dTransVal[xx][yy + 1] == tv*/) { // assert(dObject[xx][yy] == 0); // assert(dObject[xx][yy - 1] == 0); // assert(dObject[xx][yy + 1] == 0); @@ -121,20 +126,21 @@ static int TFit_Shrine(int themeId) static int TFit_Obj5(int themeId) { int xx, yy, i, numMatches; - BYTE tv = themes[themeId]._tsTransVal; numMatches = 0; for (xx = themes[themeId]._tsx1 + 2; xx < themes[themeId]._tsx2 - 2; xx++) { for (yy = themes[themeId]._tsy1 + 2; yy < themes[themeId]._tsy2 - 2; yy++) { - if (dTransVal[xx][yy] == tv && !nSolidTable[dPiece[xx][yy]]) { + // assert(dTransVal[xx][yy] == themes[themeId]._tsTransVal); + if (/*dTransVal[xx][yy] == tv &&*/ !nSolidTable[dPiece[xx][yy]]) { static_assert(lengthof(trm5x) == lengthof(trm5y), "Mismatching trm5 tables."); for (i = 0; i < lengthof(trm5x); i++) { if (nSolidTable[dPiece[xx + trm5x[i]][yy + trm5y[i]]]) { break; } - if (dTransVal[xx + trm5x[i]][yy + trm5y[i]] != tv) { - break; - } + //assert(dTransVal[xx + trm5x[i]][yy + trm5y[i]] == themes[themeId]._tsTransVal); + //if (dTransVal[xx + trm5x[i]][yy + trm5y[i]] != tv) { + // break; + //} } if (i == lengthof(trm5x)) { drlg.thLocs[numMatches].tpdx = xx; @@ -156,7 +162,7 @@ static int TFit_Obj5(int themeId) return random_low(0, numMatches); } -static bool CheckThemeObj3(int x, int y, BYTE tv) +static bool CheckThemeObj3(int x, int y) { int i, xx, yy; @@ -166,8 +172,9 @@ static bool CheckThemeObj3(int x, int y, BYTE tv) yy = y + trm3y[i]; //if (xx < 0 || yy < 0) // return false; - if (dTransVal[xx][yy] != tv) - return false; + //assert(dTransVal[xx][yy] == themes[themeId]._tsTransVal); + //if (dTransVal[xx][yy] != tv) + // return false; if ((nSolidTable[dPiece[xx][yy]] | dObject[xx][yy]) != 0) return false; } @@ -178,12 +185,11 @@ static bool CheckThemeObj3(int x, int y, BYTE tv) static int TFit_Obj3(int themeId) { int xx, yy, numMatches; - BYTE tv = themes[themeId]._tsTransVal; numMatches = 0; for (xx = themes[themeId]._tsx1 + 1; xx < themes[themeId]._tsx2 - 1; xx++) { for (yy = themes[themeId]._tsy1 + 1; yy < themes[themeId]._tsy2 - 1; yy++) { - if (CheckThemeObj3(xx, yy, tv)) { + if (CheckThemeObj3(xx, yy)) { drlg.thLocs[numMatches].tpdx = xx; drlg.thLocs[numMatches].tpdy = yy; drlg.thLocs[numMatches].tpdvar1 = 0; @@ -382,17 +388,16 @@ void InitThemes() /* * Place a theme object with the specified frequency. * @param themeId: theme id. - * @param tv: room id in the dungeon matrix. * @param type: the type of the object to place * @param rndfrq: the frequency to place the object */ -static void Place_Obj3(int themeId, BYTE tv, int type, int rndfrq) +static void Place_Obj3(int themeId, int type, int rndfrq) { int xx, yy; // assert(rndfrq > 0); - for (xx = themes[themeId]._tsx1; xx < themes[themeId]._tsx2; xx++) { - for (yy = themes[themeId]._tsy1; yy < themes[themeId]._tsy2; yy++) { - if (CheckThemeObj3(xx, yy, tv) && random_low(0, rndfrq) == 0) { + for (xx = themes[themeId]._tsx1 + 1; xx < themes[themeId]._tsx2 - 1; xx++) { + for (yy = themes[themeId]._tsy1 + 1; yy < themes[themeId]._tsy2 - 1; yy++) { + if (CheckThemeObj3(xx, yy) && random_low(0, rndfrq) == 0) { AddObject(type, xx, yy); } } @@ -402,9 +407,8 @@ static void Place_Obj3(int themeId, BYTE tv, int type, int rndfrq) * PlaceThemeMonsts places theme monsters with the specified frequency. * * @param themeId: theme id. - * @param tv: room id in the dungeon matrix. */ -static void PlaceThemeMonsts(int themeId, BYTE tv) +static void PlaceThemeMonsts(int themeId) { int xx, yy; int scattertypes[MAX_LVLMTYPES]; @@ -423,7 +427,8 @@ static void PlaceThemeMonsts(int themeId, BYTE tv) mtype = scattertypes[random_low(0, numscattypes)]; for (xx = themes[themeId]._tsx1; xx < themes[themeId]._tsx2; xx++) { for (yy = themes[themeId]._tsy1; yy < themes[themeId]._tsy2; yy++) { - if (dTransVal[xx][yy] == tv && (nSolidTable[dPiece[xx][yy]] | dItem[xx][yy] | dObject[xx][yy]) == 0) { + // assert(dTransVal[xx][yy] == themes[themeId]._tsTransVal); + if (/*dTransVal[xx][yy] == tv &&*/ (nSolidTable[dPiece[xx][yy]] | dItem[xx][yy] | dObject[xx][yy]) == 0) { if (random_low(0, rndfrq) == 0) { AddMonster(mtype, xx, yy); } @@ -436,9 +441,8 @@ static void PlaceThemeMonsts(int themeId, BYTE tv) * Theme_Barrel initializes the barrel theme. * * @param themeId: theme id. - * @param tv: room id in the dungeon matrix. */ -static void Theme_Barrel(int themeId, BYTE tv) +static void Theme_Barrel(int themeId) { int r, xx, yy; const BYTE barrnds[4] = { 2, 6, 4, 8 }; @@ -446,7 +450,8 @@ static void Theme_Barrel(int themeId, BYTE tv) for (xx = themes[themeId]._tsx1; xx < themes[themeId]._tsx2; xx++) { for (yy = themes[themeId]._tsy1; yy < themes[themeId]._tsy2; yy++) { - if (dTransVal[xx][yy] == tv && !nSolidTable[dPiece[xx][yy]]) { + // assert(dTransVal[xx][yy] == themes[themeId]._tsTransVal); + if (/*dTransVal[xx][yy] == tv &&*/ !nSolidTable[dPiece[xx][yy]]) { if (random_low(0, barrnd) == 0) { r = random_low(0, barrnd) == 0 ? OBJ_BARREL : OBJ_BARRELEX; AddObject(r, xx, yy); @@ -454,16 +459,15 @@ static void Theme_Barrel(int themeId, BYTE tv) } } } - PlaceThemeMonsts(themeId, tv); + PlaceThemeMonsts(themeId); } /** * Theme_Shrine initializes the shrine theme. * * @param themeId: theme id. - * @param tv: room id in the dungeon matrix. */ -static void Theme_Shrine(int themeId, BYTE tv) +static void Theme_Shrine(int themeId) { int xx, yy; @@ -478,16 +482,15 @@ static void Theme_Shrine(int themeId, BYTE tv) AddObject(OBJ_SHRINEL, xx, yy); AddObject(OBJ_CANDLE2, xx, yy + 1); } - PlaceThemeMonsts(themeId, tv); + PlaceThemeMonsts(themeId); } /** * Theme_MonstPit initializes the monster pit theme. * * @param themeId: theme id. - * @param tv: room id in the dungeon matrix. */ -static void Theme_MonstPit(int themeId, BYTE tv) +static void Theme_MonstPit(int themeId) { int r, xx, yy; @@ -495,7 +498,8 @@ static void Theme_MonstPit(int themeId, BYTE tv) while (true) { for (xx = themes[themeId]._tsx1; xx < themes[themeId]._tsx2; xx++) { for (yy = themes[themeId]._tsy1; yy < themes[themeId]._tsy2; yy++) { - if (dTransVal[xx][yy] == tv && !nSolidTable[dPiece[xx][yy]] && --r < 0) { + // assert(dTransVal[xx][yy] == themes[themeId]._tsTransVal); + if (/*dTransVal[xx][yy] == tv &&*/ !nSolidTable[dPiece[xx][yy]] && --r < 0) { CreateRndItem(xx, yy, CFDQ_GOOD, ICM_DELTA); goto done; } @@ -504,7 +508,7 @@ static void Theme_MonstPit(int themeId, BYTE tv) } done: - PlaceThemeMonsts(themeId, tv); + PlaceThemeMonsts(themeId); } static void AddSkelMonster(int x, int y) @@ -517,9 +521,8 @@ static void AddSkelMonster(int x, int y) * Theme_SkelRoom initializes the skeleton room theme. * * @param themeId: theme id. - * @param tv: room id in the dungeon matrix. */ -static void Theme_SkelRoom(int themeId, BYTE tv) +static void Theme_SkelRoom(int themeId) { int xx, yy; const BYTE monstrnds[4] = { 6, 7, 3, 9 }; @@ -585,9 +588,8 @@ static void Theme_SkelRoom(int themeId, BYTE tv) * Theme_Treasure initializes the treasure theme. * * @param themeId: theme id. - * @param tv: room id in the dungeon matrix. */ -static void Theme_Treasure(int themeId, BYTE tv) +static void Theme_Treasure(int themeId) { int xx, yy; const BYTE treasrnds[4] = { 6, 9, 7, 10 }; @@ -595,7 +597,8 @@ static void Theme_Treasure(int themeId, BYTE tv) for (xx = themes[themeId]._tsx1; xx < themes[themeId]._tsx2; xx++) { for (yy = themes[themeId]._tsy1; yy < themes[themeId]._tsy2; yy++) { - if (dTransVal[xx][yy] == tv && !nSolidTable[dPiece[xx][yy]]) { + // assert(dTransVal[xx][yy] == themes[themeId]._tsTransVal); + if (/*dTransVal[xx][yy] == tv &&*/ !nSolidTable[dPiece[xx][yy]]) { if (random_low(0, treasrnd) == 0) { CreateTypeItem(xx, yy, CFDQ_NORMAL, ITYPE_GOLD, IMISC_NONE, ICM_DELTA); } else if (random_low(0, treasrnd) == 0) { @@ -604,16 +607,15 @@ static void Theme_Treasure(int themeId, BYTE tv) } } } - PlaceThemeMonsts(themeId, tv); + PlaceThemeMonsts(themeId); } /** * Theme_Library initializes the library theme. * * @param themeId: theme id. - * @param tv: room id in the dungeon matrix. */ -static void Theme_Library(int themeId, BYTE tv) +static void Theme_Library(int themeId) { int xx, yy, oi; const BYTE librnds[4] = { 1, 2, 2, 5 }; @@ -632,9 +634,9 @@ static void Theme_Library(int themeId, BYTE tv) } librnd = librnds[currLvl._dDunType - 1]; // TODO: use dType instead? - for (xx = themes[themeId]._tsx1; xx < themes[themeId]._tsx2; xx++) { - for (yy = themes[themeId]._tsy1; yy < themes[themeId]._tsy2; yy++) { - if (CheckThemeObj3(xx, yy, tv) && dMonster[xx][yy] == 0 && random_low(0, librnd) == 0) { + for (xx = themes[themeId]._tsx1 + 1; xx < themes[themeId]._tsx2 - 1; xx++) { + for (yy = themes[themeId]._tsy1 + 1; yy < themes[themeId]._tsy2 - 1; yy++) { + if (CheckThemeObj3(xx, yy) && dMonster[xx][yy] == 0 && random_low(0, librnd) == 0) { oi = AddObject(OBJ_BOOK2L, xx, yy); if (random_low(0, 2 * librnd) != 0 && oi != -1) { /// BUGFIX: check AddObject succeeded (fixed) objects[oi]._oSelFlag = 0; @@ -644,93 +646,85 @@ static void Theme_Library(int themeId, BYTE tv) } } - if (/*QuestStatus(Q_ZHAR) &&*/ themeId == zharlib) - return; - - PlaceThemeMonsts(themeId, tv); + if (/*QuestStatus(Q_ZHAR) &&*/ themeId != zharlib) + PlaceThemeMonsts(themeId); } /** * Theme_Torture initializes the torture theme. * * @param themeId: theme id. - * @param tv: room id in the dungeon matrix. */ -static void Theme_Torture(int themeId, BYTE tv) +static void Theme_Torture(int themeId) { const BYTE tortrnds[4] = { 6 * 2, 8 * 2, 3 * 2, 8 * 2 }; const BYTE tortrnd = tortrnds[currLvl._dDunType - 1]; // TODO: use dType instead? AddObject(random_(46, 2) ? OBJ_TNUDEW : OBJ_TNUDEM, themes[themeId]._tsObjX, themes[themeId]._tsObjY); - Place_Obj3(themeId, tv, OBJ_TNUDEM, tortrnd); - Place_Obj3(themeId, tv, OBJ_TNUDEW, tortrnd); - PlaceThemeMonsts(themeId, tv); + Place_Obj3(themeId, OBJ_TNUDEM, tortrnd); + Place_Obj3(themeId, OBJ_TNUDEW, tortrnd); + PlaceThemeMonsts(themeId); } /** * Theme_BloodFountain initializes the blood fountain theme. * * @param themeId: theme id. - * @param tv: room id in the dungeon matrix. */ -static void Theme_BloodFountain(int themeId, BYTE tv) +static void Theme_BloodFountain(int themeId) { AddObject(OBJ_BLOODFTN, themes[themeId]._tsObjX, themes[themeId]._tsObjY); - PlaceThemeMonsts(themeId, tv); + PlaceThemeMonsts(themeId); } /** * Theme_Decap initializes the decapitated theme. * * @param themeId: theme id. - * @param tv: room id in the dungeon matrix. */ -static void Theme_Decap(int themeId, BYTE tv) +static void Theme_Decap(int themeId) { const BYTE decaprnds[4] = { 6, 8, 3, 8 }; const BYTE decaprnd = decaprnds[currLvl._dDunType - 1]; // TODO: use dType instead? AddObject(OBJ_DECAP, themes[themeId]._tsObjX, themes[themeId]._tsObjY); - Place_Obj3(themeId, tv, OBJ_DECAP, decaprnd); - PlaceThemeMonsts(themeId, tv); + Place_Obj3(themeId, OBJ_DECAP, decaprnd); + PlaceThemeMonsts(themeId); } /** * Theme_PurifyingFountain initializes the purifying fountain theme. * * @param themeId: theme id. - * @param tv: room id in the dungeon matrix. */ -static void Theme_PurifyingFountain(int themeId, BYTE tv) +static void Theme_PurifyingFountain(int themeId) { AddObject(OBJ_PURIFYINGFTN, themes[themeId]._tsObjX, themes[themeId]._tsObjY); - PlaceThemeMonsts(themeId, tv); + PlaceThemeMonsts(themeId); } /** * Theme_ArmorStand initializes the armor stand theme. * * @param themeId: theme id. - * @param tv: room id in the dungeon matrix. */ -static void Theme_ArmorStand(int themeId, BYTE tv) +static void Theme_ArmorStand(int themeId) { const BYTE armorrnds[4] = { 6, 8, 3, 8 }; const BYTE armorrnd = armorrnds[currLvl._dDunType - 1]; // TODO: use dType instead? AddObject(_gbArmorFlag ? OBJ_ARMORSTAND : OBJ_ARMORSTANDN, themes[themeId]._tsObjX, themes[themeId]._tsObjY); _gbArmorFlag = false; - Place_Obj3(themeId, tv, OBJ_ARMORSTANDN, armorrnd); - PlaceThemeMonsts(themeId, tv); + Place_Obj3(themeId, OBJ_ARMORSTANDN, armorrnd); + PlaceThemeMonsts(themeId); } /** * Theme_GoatShrine initializes the goat shrine theme. * * @param themeId: theme id. - * @param tv: room id in the dungeon matrix. */ -static void Theme_GoatShrine(int themeId, BYTE tv) +static void Theme_GoatShrine(int themeId) { int i, xx, yy, x, y; @@ -740,7 +734,7 @@ static void Theme_GoatShrine(int themeId, BYTE tv) for (i = 0; i < lengthof(offset_x); i++) { x = xx + offset_x[i]; y = yy + offset_y[i]; - assert(dTransVal[x][y] == tv && !nSolidTable[dPiece[x][y]]); + // assert(dTransVal[x][y] == themes[themeId]._tsTransVal && !nSolidTable[dPiece[x][y]]); AddMonster(mapGoatTypes[0], x, y); // OPPOSITE(i) } } @@ -749,61 +743,56 @@ static void Theme_GoatShrine(int themeId, BYTE tv) * Theme_Cauldron initializes the cauldron theme. * * @param themeId: theme id. - * @param tv: room id in the dungeon matrix. */ -static void Theme_Cauldron(int themeId, BYTE tv) +static void Theme_Cauldron(int themeId) { AddObject(OBJ_CAULDRON, themes[themeId]._tsObjX, themes[themeId]._tsObjY); - PlaceThemeMonsts(themeId, tv); + PlaceThemeMonsts(themeId); } /** * Theme_MurkyFountain initializes the murky fountain theme. * * @param themeId: theme id. - * @param tv: room id in the dungeon matrix. */ -static void Theme_MurkyFountain(int themeId, BYTE tv) +static void Theme_MurkyFountain(int themeId) { AddObject(OBJ_MURKYFTN, themes[themeId]._tsObjX, themes[themeId]._tsObjY); - PlaceThemeMonsts(themeId, tv); + PlaceThemeMonsts(themeId); } /** * Theme_TearFountain initializes the tear fountain theme. * * @param themeId: theme id. - * @param tv: room id in the dungeon matrix. */ -static void Theme_TearFountain(int themeId, BYTE tv) +static void Theme_TearFountain(int themeId) { AddObject(OBJ_TEARFTN, themes[themeId]._tsObjX, themes[themeId]._tsObjY); - PlaceThemeMonsts(themeId, tv); + PlaceThemeMonsts(themeId); } /** * Theme_BrnCross initializes the burning cross theme. * * @param themeId: theme id. - * @param tv: room id in the dungeon matrix. */ -static void Theme_BrnCross(int themeId, BYTE tv) +static void Theme_BrnCross(int themeId) { const BYTE bcrossrnds[4] = { 5, 7, 3, 8 }; const BYTE bcrossrnd = bcrossrnds[currLvl._dDunType - 1]; // TODO: use dType instead? AddObject(OBJ_TBCROSS, themes[themeId]._tsObjX, themes[themeId]._tsObjY); - Place_Obj3(themeId, tv, OBJ_TBCROSS, bcrossrnd); - PlaceThemeMonsts(themeId, tv); + Place_Obj3(themeId, OBJ_TBCROSS, bcrossrnd); + PlaceThemeMonsts(themeId); } /** * Theme_WeaponRack initializes the weapon rack theme. * * @param themeId: theme id. - * @param tv: room id in the dungeon matrix. */ -static void Theme_WeaponRack(int themeId, BYTE tv) +static void Theme_WeaponRack(int themeId) { int type; const BYTE weaponrnds[4] = { 6, 8, 5, 8 }; @@ -816,8 +805,8 @@ static void Theme_WeaponRack(int themeId, BYTE tv) AddObject(type + (_gbWeaponFlag ? 0 : 1), themes[themeId]._tsObjX, themes[themeId]._tsObjY); _gbWeaponFlag = false; type += 1; - Place_Obj3(themeId, tv, type, weaponrnd); - PlaceThemeMonsts(themeId, tv); + Place_Obj3(themeId, type, weaponrnd); + PlaceThemeMonsts(themeId); } /** @@ -838,62 +827,60 @@ static void Theme_WeaponRack(int themeId, BYTE tv) void CreateThemeRooms() { int i; - BYTE tv; // assert(currLvl._dLevelNum < DLV_HELL4 || (currLvl._dDynLvl && currLvl._dLevelNum == DLV_HELL4) || numthemes == 0); // there are no themes in hellfire (and on diablo-level) //gbInitObjFlag = true; for (i = 0; i < numthemes; i++) { - tv = themes[i]._tsTransVal; switch (themes[i]._tsType) { case THEME_BARREL: - Theme_Barrel(i, tv); + Theme_Barrel(i); break; case THEME_SHRINE: - Theme_Shrine(i, tv); + Theme_Shrine(i); break; case THEME_MONSTPIT: - Theme_MonstPit(i, tv); + Theme_MonstPit(i); break; case THEME_SKELROOM: - Theme_SkelRoom(i, tv); + Theme_SkelRoom(i); break; case THEME_TREASURE: - Theme_Treasure(i, tv); + Theme_Treasure(i); break; case THEME_LIBRARY: - Theme_Library(i, tv); + Theme_Library(i); break; case THEME_TORTURE: - Theme_Torture(i, tv); + Theme_Torture(i); break; case THEME_BLOODFOUNTAIN: - Theme_BloodFountain(i, tv); + Theme_BloodFountain(i); break; case THEME_DECAPITATED: - Theme_Decap(i, tv); + Theme_Decap(i); break; case THEME_PURIFYINGFOUNTAIN: - Theme_PurifyingFountain(i, tv); + Theme_PurifyingFountain(i); break; case THEME_ARMORSTAND: - Theme_ArmorStand(i, tv); + Theme_ArmorStand(i); break; case THEME_GOATSHRINE: - Theme_GoatShrine(i, tv); + Theme_GoatShrine(i); break; case THEME_CAULDRON: - Theme_Cauldron(i, tv); + Theme_Cauldron(i); break; case THEME_MURKYFOUNTAIN: - Theme_MurkyFountain(i, tv); + Theme_MurkyFountain(i); break; case THEME_TEARFOUNTAIN: - Theme_TearFountain(i, tv); + Theme_TearFountain(i); break; case THEME_BRNCROSS: - Theme_BrnCross(i, tv); + Theme_BrnCross(i); break; case THEME_WEAPONRACK: - Theme_WeaponRack(i, tv); + Theme_WeaponRack(i); break; default: ASSUME_UNREACHABLE From 7e9fa04e4be62248f99b4706415c71a2b1c5a8fa Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 29 Aug 2024 09:05:08 +0200 Subject: [PATCH 493/596] cleanup the window_messages-enums --- Source/miniwin/miniwin.h | 2 +- tools/patcher/miniwin/miniwin.h | 17 +---------------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/Source/miniwin/miniwin.h b/Source/miniwin/miniwin.h index 818b42d56d0..e712f1efb33 100644 --- a/Source/miniwin/miniwin.h +++ b/Source/miniwin/miniwin.h @@ -35,7 +35,7 @@ typedef enum window_messages { DVL_WM_CAPTURECHANGED, DVL_WM_PAINT, - DVL_WM_QUERYENDSESSION, + // DVL_WM_QUERYENDSESSION, DVL_DWM_NEXTLVL, // dungeon -> next level DVL_DWM_PREVLVL, // dungeon -> previous level diff --git a/tools/patcher/miniwin/miniwin.h b/tools/patcher/miniwin/miniwin.h index 8262f797c22..173173716ad 100644 --- a/tools/patcher/miniwin/miniwin.h +++ b/tools/patcher/miniwin/miniwin.h @@ -24,26 +24,11 @@ typedef enum window_messages { DVL_WM_KEYDOWN, // 0x0100 DVL_WM_KEYUP, // 0x0101 - // DVL_WM_SYSKEYDOWN 0x0104 - // DVL_WM_SYSCOMMAND 0x0112 DVL_WM_TEXT, // 0x0102 DVL_WM_CAPTURECHANGED, // 0x0215 DVL_WM_PAINT, // 0x000F - DVL_WM_QUERYENDSESSION, // 0x0011 - - DVL_DWM_NEXTLVL, // = 0x402, // dungeon -> next level WM_USER+2 - DVL_DWM_PREVLVL, // = 0x403, // dungeon -> previous level - DVL_DWM_RTNLVL, // = 0x404, // setlevel -> dungeon - DVL_DWM_SETLVL, // = 0x405, // dungeon -> setlevel - DVL_DWM_TWARPDN, // = 0x407, // town -> dungeon - DVL_DWM_TWARPUP, // = 0x408, // dungeon -> town - DVL_DWM_WARPLVL, // = 0x406, // portal - DVL_DWM_RETOWN, // = 0x409, // restart in town - DVL_DWM_NEWGAME, // = 0x40A, - - // WM_LEIGHSKIP = 0x40C, // psx only - // WM_DIAVNEWLVL = 0x40D, // psx only + // DVL_WM_QUERYENDSESSION, // 0x0011 } window_messages; //#define DVL_SC_CLOSE 0xF060 From 072684aec08f4c09ee7d7a6bb17d76b45367da60 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 29 Aug 2024 09:16:16 +0200 Subject: [PATCH 494/596] simplify DisableInputWndProc and GameWndProc - use ASSUME_UNREACHABLE in the switch statements - have a single return point --- Source/diablo.cpp | 73 ++++++++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/Source/diablo.cpp b/Source/diablo.cpp index df508f831ff..9a8d943571f 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -1080,39 +1080,55 @@ void DisableInputWndProc(const Dvl_Event* e) switch (e->type) { case DVL_WM_KEYDOWN: UpdateActionBtnState(e->vkcode, true); - return; + break; // return; case DVL_WM_KEYUP: UpdateActionBtnState(e->vkcode, false); - return; + break; // return; case DVL_WM_TEXT: //case DVL_WM_SYSKEYDOWN: //case DVL_WM_SYSCOMMAND: - return; + break; // return; case DVL_WM_QUIT: NetSendCmd(CMD_DISCONNECT); gbRunGameResult = false; - return; + break; // return; case DVL_WM_MOUSEMOVE: - return; + break; // return; case DVL_WM_LBUTTONDOWN: UpdateActionBtnState(DVL_VK_LBUTTON, true); - return; + break; // return; case DVL_WM_LBUTTONUP: UpdateActionBtnState(DVL_VK_LBUTTON, false); - return; + break; // return; case DVL_WM_RBUTTONDOWN: UpdateActionBtnState(DVL_VK_RBUTTON, true); - return; + break; // return; case DVL_WM_RBUTTONUP: UpdateActionBtnState(DVL_VK_RBUTTON, false); - return; + break; // return; case DVL_WM_CAPTURECHANGED: gbActionBtnDown = false; gbAltActionBtnDown = false; - return; + break; // return; case DVL_WM_PAINT: gbRedrawFlags = REDRAW_ALL; - return; + break; // return; + case DVL_WM_NONE: + // case DVL_WM_QUERYENDSESSION: + // case DVL_DWM_NEXTLVL: + // case DVL_DWM_PREVLVL: + // case DVL_DWM_SETLVL: + // case DVL_DWM_RTNLVL: + // case DVL_DWM_DYNLVL: + // case DVL_DWM_PORTLVL: + // case DVL_DWM_TWARPDN: + // case DVL_DWM_TWARPUP: + // case DVL_DWM_RETOWN: + // case DVL_DWM_NEWGAME: + // case DVL_DWM_LOADGAME: + break; + default: + ASSUME_UNREACHABLE } // MainWndProc(uMsg); @@ -1123,24 +1139,24 @@ static void GameWndProc(const Dvl_Event* e) switch (e->type) { case DVL_WM_KEYDOWN: PressKey(e->vkcode); - return; + break; // return; case DVL_WM_KEYUP: ReleaseKey(e->vkcode); - return; + break; // return; case DVL_WM_TEXT: #ifndef USE_SDL1 if (gmenu_is_active()) { - return; + break; // return; } if (gbTalkflag) { plrmsg_CatToText(e->text.text); - return; + break; // return; } #endif - return; + break; // return; //case DVL_WM_SYSKEYDOWN: // if (PressSysKey(wParam)) - // return; + // break; // return; // break; //case DVL_WM_SYSCOMMAND: // if (wParam != DVL_SC_CLOSE) @@ -1152,7 +1168,7 @@ static void GameWndProc(const Dvl_Event* e) NetSendCmd(CMD_DISCONNECT); gbRunGameResult = false; gbGamePaused = false; - return; + break; // return; case DVL_WM_MOUSEMOVE: if (gmenu_is_active()) gmenu_on_mouse_move(); @@ -1160,30 +1176,30 @@ static void GameWndProc(const Dvl_Event* e) DoWndDrag(); else if (gbTalkflag) plrmsg_HandleMouseMoveEvent(); - return; + break; // return; case DVL_WM_LBUTTONDOWN: //GetMousePos(wParam); -- disabled to prevent inconsistent MousePos.x/y vs. CheckCursMove state PressKey(DVL_VK_LBUTTON); - return; + break; // return; case DVL_WM_LBUTTONUP: //GetMousePos(wParam); ReleaseKey(DVL_VK_LBUTTON); - return; + break; // return; case DVL_WM_RBUTTONDOWN: //GetMousePos(wParam); PressKey(DVL_VK_RBUTTON); - return; + break; // return; case DVL_WM_RBUTTONUP: //GetMousePos(wParam); ReleaseKey(DVL_VK_RBUTTON); - return; + break; // return; case DVL_WM_CAPTURECHANGED: gbActionBtnDown = false; gbAltActionBtnDown = false; - return; + break; // return; case DVL_WM_PAINT: gbRedrawFlags = REDRAW_ALL; - return; + break; // return; case DVL_DWM_NEXTLVL: case DVL_DWM_PREVLVL: case DVL_DWM_SETLVL: @@ -1209,7 +1225,12 @@ static void GameWndProc(const Dvl_Event* e) scrollrt_draw_game(); //gbRedrawFlags = REDRAW_ALL; } - return; + break; // return; + case DVL_WM_NONE: + // case DVL_WM_QUERYENDSESSION: + break; + default: + ASSUME_UNREACHABLE } // MainWndProc(uMsg); From 08bc9f5bbe8c419b519ce0e925b0dc24cb0ddf5d Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 29 Aug 2024 09:25:18 +0200 Subject: [PATCH 495/596] use ColorTrns (COLOR_TRN_CORAL) instead of FONT_TRN_RED --- Source/engine/render/text_render.cpp | 8 ++++---- tools/patcher/engine/render/text_render.cpp | 8 ++++---- tools/patcher/lighting.cpp | 18 ++++++++++++++++++ tools/patcher/lighting.h | 3 ++- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/Source/engine/render/text_render.cpp b/Source/engine/render/text_render.cpp index a4e5a7f9470..c227036814a 100644 --- a/Source/engine/render/text_render.cpp +++ b/Source/engine/render/text_render.cpp @@ -127,7 +127,7 @@ static CelImageBuf* pHugePentSpinCels; * Merged color translations for fonts. The shades of one color are used in one font.CEL * SmalText.CEL uses PAL16_GRAY values, while MedTextS and BigTGold.CEL are using PAL16_YELLOWs */ -static BYTE fontColorTrns[16 + 2][16] = { +static BYTE fontColorTrns[][16] = { // clang-format off // skip non-generic colors { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, @@ -146,13 +146,13 @@ static BYTE fontColorTrns[16 + 2][16] = { // TRN for COL_GOLD (SmalText) { PAL16_YELLOW + 2, PAL16_YELLOW + 3, PAL16_YELLOW + 4, PAL16_YELLOW + 5, PAL16_YELLOW + 6, PAL16_YELLOW + 7, PAL16_YELLOW + 8, PAL16_YELLOW + 9, PAL16_YELLOW + 10, PAL16_YELLOW + 11, PAL16_YELLOW + 12, PAL16_YELLOW + 13, PAL16_YELLOW + 14, PAL16_YELLOW + 15, PAL16_ORANGE + 15, 0 }, // TRN for COL_RED (SmalText) - { PAL16_RED, PAL16_RED + 1, PAL16_RED + 2, PAL16_RED + 3, PAL16_RED + 4, PAL16_RED + 5, PAL16_RED + 6, PAL16_RED + 7, PAL16_RED + 8, PAL16_RED + 9, PAL16_RED + 10, PAL16_RED + 11, PAL16_RED + 12, PAL16_RED + 13, PAL16_RED + 14, PAL16_RED + 15 }, + //{ PAL16_RED, PAL16_RED + 1, PAL16_RED + 2, PAL16_RED + 3, PAL16_RED + 4, PAL16_RED + 5, PAL16_RED + 6, PAL16_RED + 7, PAL16_RED + 8, PAL16_RED + 9, PAL16_RED + 10, PAL16_RED + 11, PAL16_RED + 12, PAL16_RED + 13, PAL16_RED + 14, PAL16_RED + 15 }, // clang-format on }; #define FONT_TRN_SILVER (&fontColorTrns[0][0]) #define FONT_TRN_BLUE (&fontColorTrns[0][0]) #define FONT_TRN_GOLD (&fontColorTrns[1][0]) -#define FONT_TRN_RED (&fontColorTrns[2][0]) +//#define FONT_TRN_RED (&fontColorTrns[2][0]) void InitText() { @@ -196,7 +196,7 @@ void PrintSmallColorChar(int sx, int sy, int nCel, BYTE col) tbl = FONT_TRN_BLUE; break; case COL_RED: - tbl = FONT_TRN_RED; + tbl = ColorTrns[COLOR_TRN_CORAL]; // FONT_TRN_RED; break; case COL_GOLD: tbl = FONT_TRN_GOLD; diff --git a/tools/patcher/engine/render/text_render.cpp b/tools/patcher/engine/render/text_render.cpp index b54efadc0f3..440f2bc3b6c 100644 --- a/tools/patcher/engine/render/text_render.cpp +++ b/tools/patcher/engine/render/text_render.cpp @@ -127,7 +127,7 @@ static CelImageBuf* pHugePentSpinCels; * Merged color translations for fonts. The shades of one color are used in one font.CEL * SmalText.CEL uses PAL16_GRAY values, while MedTextS and BigTGold.CEL are using PAL16_YELLOWs */ -static BYTE fontColorTrns[16 + 2][16] = { +static BYTE fontColorTrns[][16] = { // clang-format off // skip non-generic colors { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, @@ -146,13 +146,13 @@ static BYTE fontColorTrns[16 + 2][16] = { // TRN for COL_GOLD (SmalText) { PAL16_YELLOW + 2, PAL16_YELLOW + 3, PAL16_YELLOW + 4, PAL16_YELLOW + 5, PAL16_YELLOW + 6, PAL16_YELLOW + 7, PAL16_YELLOW + 8, PAL16_YELLOW + 9, PAL16_YELLOW + 10, PAL16_YELLOW + 11, PAL16_YELLOW + 12, PAL16_YELLOW + 13, PAL16_YELLOW + 14, PAL16_YELLOW + 15, PAL16_ORANGE + 15, 0 }, // TRN for COL_RED (SmalText) - { PAL16_RED, PAL16_RED + 1, PAL16_RED + 2, PAL16_RED + 3, PAL16_RED + 4, PAL16_RED + 5, PAL16_RED + 6, PAL16_RED + 7, PAL16_RED + 8, PAL16_RED + 9, PAL16_RED + 10, PAL16_RED + 11, PAL16_RED + 12, PAL16_RED + 13, PAL16_RED + 14, PAL16_RED + 15 }, + //{ PAL16_RED, PAL16_RED + 1, PAL16_RED + 2, PAL16_RED + 3, PAL16_RED + 4, PAL16_RED + 5, PAL16_RED + 6, PAL16_RED + 7, PAL16_RED + 8, PAL16_RED + 9, PAL16_RED + 10, PAL16_RED + 11, PAL16_RED + 12, PAL16_RED + 13, PAL16_RED + 14, PAL16_RED + 15 }, // clang-format on }; #define FONT_TRN_SILVER (&fontColorTrns[0][0]) #define FONT_TRN_BLUE (&fontColorTrns[0][0]) #define FONT_TRN_GOLD (&fontColorTrns[1][0]) -#define FONT_TRN_RED (&fontColorTrns[2][0]) +//#define FONT_TRN_RED (&fontColorTrns[2][0]) void InitText() { @@ -196,7 +196,7 @@ static void PrintSmallColorChar(int sx, int sy, int nCel, BYTE col) tbl = FONT_TRN_BLUE; break; case COL_RED: - tbl = FONT_TRN_RED; + tbl = ColorTrns[COLOR_TRN_CORAL]; // FONT_TRN_RED; break; case COL_GOLD: tbl = FONT_TRN_GOLD; diff --git a/tools/patcher/lighting.cpp b/tools/patcher/lighting.cpp index 1a435c880bf..46b959acc9b 100644 --- a/tools/patcher/lighting.cpp +++ b/tools/patcher/lighting.cpp @@ -7,4 +7,22 @@ DEVILUTION_BEGIN_NAMESPACE +/* + * In-game color translation tables. + * 0-MAXDARKNESS: inverse brightness translations. + * MAXDARKNESS+1: RED color translation. + * MAXDARKNESS+2: GRAY color translation. + * MAXDARKNESS+3: CORAL color translation. + * MAXDARKNESS+4.. translations of unique monsters. + */ +BYTE ColorTrns[NUM_COLOR_TRNS][NUM_COLORS]; + +void InitLighting() +{ + // LoadFileWithMem("Levels\\TownData\\Town.TRS", ColorTrns[0]); + LoadFileWithMem("PlrGFX\\Infra.TRN", ColorTrns[COLOR_TRN_RED]); + LoadFileWithMem("PlrGFX\\Stone.TRN", ColorTrns[COLOR_TRN_GRAY]); + LoadFileWithMem("PlrGFX\\Coral.TRN", ColorTrns[COLOR_TRN_CORAL]); +} + DEVILUTION_END_NAMESPACE diff --git a/tools/patcher/lighting.h b/tools/patcher/lighting.h index 80a6f7e4fb7..c24620a09ff 100644 --- a/tools/patcher/lighting.h +++ b/tools/patcher/lighting.h @@ -18,8 +18,9 @@ extern "C" { #define COLOR_TRN_GRAY MAXDARKNESS + 2 #define COLOR_TRN_CORAL MAXDARKNESS + 3 // #define COLOR_TRN_UNIQ MAXDARKNESS + 4 +extern BYTE ColorTrns[NUM_COLOR_TRNS][NUM_COLORS]; -inline void InitLighting() { } +void InitLighting(); #ifdef __cplusplus } From c93de6bf67c8a00278535a43153cb8df3c48a331 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 29 Aug 2024 10:12:39 +0200 Subject: [PATCH 496/596] use 'One-line' color translations for fonts --- Packaging/resources/devilx.mpq | Bin 1250184 -> 1250149 bytes Source/engine/render/text_render.cpp | 31 +++++++------------- tools/patcher/engine/render/text_render.cpp | 28 ++++++------------ 3 files changed, 20 insertions(+), 39 deletions(-) diff --git a/Packaging/resources/devilx.mpq b/Packaging/resources/devilx.mpq index 0a4eb54da18b3f2d1ca8a82f7c0427d82314d732..fc5e6189ca9d7d21fb469cdac291fa6ef3ff359c 100644 GIT binary patch delta 11868 zcmWOAWkZt<6b4`{kPt*bN?I65H^>M@L2~e-(oDKLM?EM?3rOciqjYy89Rum^lpHy> zvDXjRAGkl9bM6yXsJ>O8POPD&&A>`PKw$ZUI2gc7a1KUR!q(e7od#~4`O(1;m^_bM|iO6>W z12DgT%=oW*7m@{`d%A2lrK2D8{IM!yF1GhFK{;;&1|GO3yzKQlJGGfZJ1i+c%SAsL zE>;7ltlv3U3{~K}pPvd4rh2Lo=HN9{)}m?N4Tw&5nl_oO1#9^w&q&L6N}K;#4-epa zaxf{UiRNX;u=rEiy1rQI`K!i(83ZSajcR<71DUuVk3aCT4ljz09b)@0V|5IUq4@UG zO8a3KYjJ(q>$P~l;dNNjW9sMk0>H=oLnDEo&VY-oRW(6Awnz_`!5VF zKCJ6FwGAqHv{_Z{sK7umF@*G!?_n3p?&A^&h$rc{e=67UxRtnco%B$b?b&{ezk4#_ z)Q6ZdSHASC-a67T!mhstti`P;xIN1oK);$cQ=|G=;@Qy=+MvSwRaJ6N(eD(?09sOZ z{8@aKfyh;3{Js9w1mq7L`yUMM$Uf<%II6<4t$nC#_|MIEooA0*pP&BsL4vH2cslIT zl$>CF*3^}b@Sd24Ws(;6L`$< zrh~-MWa+?iWxb0ibdOF_h?Vq>d%0DrSuUHTW;N6>#WQvidWSwsUYuOh5U+L(I;qf| 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 N|Dmj3h<#G}<$wJlT+#pl delta 11903 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 Date: Thu, 29 Aug 2024 10:22:20 +0200 Subject: [PATCH 497/596] support drawing characters with light-trns --- Source/engine/render/text_render.cpp | 68 ++++++++++++++------- Source/engine/render/text_render.h | 2 +- Source/gmenu.cpp | 2 +- tools/patcher/engine/render/text_render.cpp | 51 +++++++++++++--- tools/patcher/lighting.cpp | 2 +- tools/patcher/lighting.h | 2 +- 6 files changed, 95 insertions(+), 32 deletions(-) diff --git a/Source/engine/render/text_render.cpp b/Source/engine/render/text_render.cpp index e54052392b2..aaf086145b8 100644 --- a/Source/engine/render/text_render.cpp +++ b/Source/engine/render/text_render.cpp @@ -193,7 +193,7 @@ void PrintSmallColorChar(int sx, int sy, int nCel, BYTE col) tbl = GRY_FONT_TRN_GOLD; break; default: - ASSUME_UNREACHABLE + tbl = ColorTrns[col - COL_GOLD]; break; } CelDrawTrnTbl(sx, sy, pSmallTextCels, nCel, tbl); @@ -201,12 +201,50 @@ void PrintSmallColorChar(int sx, int sy, int nCel, BYTE col) static void PrintBigColorChar(int sx, int sy, int nCel, BYTE col) { - if (col == COL_GOLD) { + BYTE* tbl; + + switch (col) { + case COL_WHITE: + tbl = YLW_FONT_TRN_SILVER; + break; + case COL_BLUE: // -- unused + tbl = YLW_FONT_TRN_BLUE; + break; + case COL_RED: // -- unused + tbl = ColorTrns[COLOR_TRN_CORAL]; // YLW_FONT_TRN_RED; + break; + case COL_GOLD: CelDraw(sx, sy, pBigTextCels, nCel); - } else { - // assert(col == COL_WHITE); - CelDrawTrnTbl(sx, sy, pBigTextCels, nCel, YLW_FONT_TRN_SILVER); + return; + default: + tbl = ColorTrns[col - COL_GOLD]; + break; + } + CelDrawTrnTbl(sx, sy, pBigTextCels, nCel, tbl); +} + +static void PrintHugeColorChar(int sx, int sy, int nCel, BYTE col) +{ + BYTE* tbl; + + switch (col) { + case COL_WHITE: // -- unused + tbl = YLW_FONT_TRN_SILVER; + break; + case COL_BLUE: // -- unused + tbl = YLW_FONT_TRN_BLUE; + break; + case COL_RED: // -- unused + tbl = ColorTrns[COLOR_TRN_CORAL]; // YLW_FONT_TRN_RED; + break; + case COL_GOLD: + CelDraw(sx, sy, pHugeGoldTextCels, nCel); + return; + default: + tbl = ColorTrns[col - COL_GOLD]; + break; } + CelDrawTrnTbl(sx, sy, pHugeGoldTextCels, nCel, tbl); } int PrintBigChar(int sx, int sy, BYTE chr, BYTE col) @@ -250,8 +288,7 @@ int PrintHugeChar(int sx, int sy, BYTE chr, BYTE col) BYTE nCel = gbHugeFontFrame[chr]; if (nCel != 0) { - // PrintHugeColorChar(sx, sy, nCel, col); - CelDraw(sx, sy, pHugeGoldTextCels, nCel); + PrintHugeColorChar(sx, sy, nCel, col); } return hugeFontWidth[nCel] + FONT_KERN_HUGE; @@ -374,22 +411,11 @@ int PrintLimitedString(int x, int y, const char* text, int limit, BYTE col) return x; } -void PrintHugeString(int x, int y, const char* text, int light) +void PrintHugeString(int x, int y, const char* text, BYTE col) { - BYTE c, *tbl; - - // TODO: uncomment if performance is required - //tbl = light == 0 ? NULL : ColorTrns[light]; - tbl = ColorTrns[light]; + // TODO: preselect color-trn if performance is required while (*text != '\0') { - c = gbHugeFontFrame[(BYTE)*text++]; - if (c != 0) { - // if (tbl == NULL) - // CelDraw(x, y, pHugeGoldTextCels, c); - // else - CelDrawTrnTbl(x, y, pHugeGoldTextCels, c, tbl); - } - x += hugeFontWidth[c] + FONT_KERN_HUGE; + x += PrintHugeChar(x, y, (BYTE)*text++, col); } } diff --git a/Source/engine/render/text_render.h b/Source/engine/render/text_render.h index a3cb7f0f80d..28d33eccd7a 100644 --- a/Source/engine/render/text_render.h +++ b/Source/engine/render/text_render.h @@ -39,7 +39,7 @@ void PrintString(int x, int y, int endX, const char* text, BYTE col, int kern); void PrintJustifiedString(int x, int y, int endX, const char* text, BYTE col, int kern); void PrintGameStr(int x, int y, const char* text, BYTE color); int PrintLimitedString(int x, int y, const char* text, int limit, BYTE col); -void PrintHugeString(int x, int y, const char* text, int light); +void PrintHugeString(int x, int y, const char* text, BYTE col); void DrawHugePentSpn(int x1, int x2, int y); void DrawSmallPentSpn(int x1, int x2, int y); diff --git a/Source/gmenu.cpp b/Source/gmenu.cpp index c45c3f9516e..2dbb55c4142 100644 --- a/Source/gmenu.cpp +++ b/Source/gmenu.cpp @@ -40,7 +40,7 @@ void gmenu_draw_pause() x = PANEL_CENTERX(135); static_assert(MAXDARKNESS >= 4, "Blinking pause uses too many shades."); light = (SDL_GetTicks() / 256) % 4; - PrintHugeString(x, PANEL_CENTERY(TILE_HEIGHT * 4), "Pause", light); + PrintHugeString(x, PANEL_CENTERY(TILE_HEIGHT * 4), "Pause", COL_GOLD + light); } } diff --git a/tools/patcher/engine/render/text_render.cpp b/tools/patcher/engine/render/text_render.cpp index c55c7b3281a..140c0e93e80 100644 --- a/tools/patcher/engine/render/text_render.cpp +++ b/tools/patcher/engine/render/text_render.cpp @@ -192,7 +192,7 @@ static void PrintSmallColorChar(int sx, int sy, int nCel, BYTE col) tbl = GRY_FONT_TRN_GOLD; break; default: - ASSUME_UNREACHABLE + tbl = ColorTrns[col - COL_GOLD]; break; } CelDrawTrnTbl(sx, sy, pSmallTextCels, nCel, tbl); @@ -200,12 +200,50 @@ static void PrintSmallColorChar(int sx, int sy, int nCel, BYTE col) static void PrintBigColorChar(int sx, int sy, int nCel, BYTE col) { - if (col == COL_GOLD) { + BYTE* tbl; + + switch (col) { + case COL_WHITE: + tbl = YLW_FONT_TRN_SILVER; + break; + case COL_BLUE: // -- unused + tbl = YLW_FONT_TRN_BLUE; + break; + case COL_RED: // -- unused + tbl = ColorTrns[COLOR_TRN_CORAL]; // FONT_TRN_RED; + break; + case COL_GOLD: CelDraw(sx, sy, pBigTextCels, nCel); - } else { - // assert(col == COL_WHITE); - CelDrawTrnTbl(sx, sy, pBigTextCels, nCel, YLW_FONT_TRN_SILVER); + return; + default: + tbl = ColorTrns[col - COL_GOLD]; + break; } + CelDrawTrnTbl(sx, sy, pBigTextCels, nCel, tbl); +} + +static void PrintHugeColorChar(int sx, int sy, int nCel, BYTE col) +{ + BYTE* tbl; + + switch (col) { + case COL_WHITE: // -- unused + tbl = YLW_FONT_TRN_SILVER; + break; + case COL_BLUE: // -- unused + tbl = YLW_FONT_TRN_BLUE; + break; + case COL_RED: // -- unused + tbl = ColorTrns[COLOR_TRN_CORAL]; // FONT_TRN_RED; + break; + case COL_GOLD: + CelDraw(sx, sy, pHugeGoldTextCels, nCel); + return; + default: + tbl = ColorTrns[col - COL_GOLD]; + break; + } + CelDrawTrnTbl(sx, sy, pHugeGoldTextCels, nCel, tbl); } int PrintBigChar(int sx, int sy, BYTE chr, BYTE col) @@ -249,8 +287,7 @@ int PrintHugeChar(int sx, int sy, BYTE chr, BYTE col) BYTE nCel = gbHugeFontFrame[chr]; if (nCel != 0) { - // PrintHugeColorChar(sx, sy, nCel, col); - CelDraw(sx, sy, pHugeGoldTextCels, nCel); + PrintHugeColorChar(sx, sy, nCel, col); } return hugeFontWidth[nCel] + FONT_KERN_HUGE; diff --git a/tools/patcher/lighting.cpp b/tools/patcher/lighting.cpp index 46b959acc9b..033adc7fa80 100644 --- a/tools/patcher/lighting.cpp +++ b/tools/patcher/lighting.cpp @@ -19,7 +19,7 @@ BYTE ColorTrns[NUM_COLOR_TRNS][NUM_COLORS]; void InitLighting() { - // LoadFileWithMem("Levels\\TownData\\Town.TRS", ColorTrns[0]); + LoadFileWithMem("Levels\\TownData\\Town.TRS", ColorTrns[0]); LoadFileWithMem("PlrGFX\\Infra.TRN", ColorTrns[COLOR_TRN_RED]); LoadFileWithMem("PlrGFX\\Stone.TRN", ColorTrns[COLOR_TRN_GRAY]); LoadFileWithMem("PlrGFX\\Coral.TRN", ColorTrns[COLOR_TRN_CORAL]); diff --git a/tools/patcher/lighting.h b/tools/patcher/lighting.h index c24620a09ff..6f023d8c487 100644 --- a/tools/patcher/lighting.h +++ b/tools/patcher/lighting.h @@ -12,7 +12,7 @@ DEVILUTION_BEGIN_NAMESPACE extern "C" { #endif -#define MAXDARKNESS 1 +#define MAXDARKNESS 15 #define NUM_COLOR_TRNS (MAXDARKNESS + 1 + 3 + 0) #define COLOR_TRN_RED MAXDARKNESS + 1 #define COLOR_TRN_GRAY MAXDARKNESS + 2 From fbc950250360ea809fc368aee11f50d33a67f9a3 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 29 Aug 2024 10:32:30 +0200 Subject: [PATCH 498/596] documentation + cosmetic --- Source/engine/render/text_render.cpp | 9 +++++---- Source/engine/render/text_render.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Source/engine/render/text_render.cpp b/Source/engine/render/text_render.cpp index aaf086145b8..268344c22e3 100644 --- a/Source/engine/render/text_render.cpp +++ b/Source/engine/render/text_render.cpp @@ -334,10 +334,11 @@ int GetSmallStringWidth(const char* text) return i - FONT_KERN_SMALL; } -void PrintGameStr(int x, int y, const char* text, BYTE color) +void PrintGameStr(int x, int y, const char* text, BYTE col) { + // TODO: preselect color-trn if performance is required while (*text != '\0') { - x += PrintSmallChar(x, y, (BYTE)*text++, color); + x += PrintSmallChar(x, y, (BYTE)*text++, col); } } @@ -354,7 +355,7 @@ void PrintString(int x, int y, int endX, const char* text, BYTE col, int kern) { BYTE c; int k; - + // TODO: preselect color-trn if performance is required while (*text != '\0') { c = gbStdFontFrame[(BYTE)*text++]; k = smallFontWidth[c] + kern; @@ -399,7 +400,7 @@ void PrintJustifiedString(int x, int y, int endX, const char* text, BYTE col, in int PrintLimitedString(int x, int y, const char* text, int limit, BYTE col) { BYTE c; - + // TODO: preselect color-trn if performance is required while (*text != '\0') { c = gbStdFontFrame[(BYTE)*text++]; limit -= smallFontWidth[c] + FONT_KERN_SMALL; diff --git a/Source/engine/render/text_render.h b/Source/engine/render/text_render.h index 28d33eccd7a..9786b7d1066 100644 --- a/Source/engine/render/text_render.h +++ b/Source/engine/render/text_render.h @@ -37,7 +37,7 @@ int PrintBigChar(int sx, int sy, BYTE chr, BYTE col); int PrintHugeChar(int sx, int sy, BYTE chr, BYTE col); void PrintString(int x, int y, int endX, const char* text, BYTE col, int kern); void PrintJustifiedString(int x, int y, int endX, const char* text, BYTE col, int kern); -void PrintGameStr(int x, int y, const char* text, BYTE color); +void PrintGameStr(int x, int y, const char* text, BYTE col); int PrintLimitedString(int x, int y, const char* text, int limit, BYTE col); void PrintHugeString(int x, int y, const char* text, BYTE col); From db65e05ddd3621512681122a4486201b191df379 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 29 Aug 2024 10:34:29 +0200 Subject: [PATCH 499/596] highlight menu item under the mouse --- Source/DiabloUI/diabloui.cpp | 10 ++++++++-- Source/DiabloUI/text_draw.cpp | 3 +++ Source/DiabloUI/ui_item.h | 1 + tools/patcher/DiabloUI/diabloui.cpp | 10 ++++++++-- tools/patcher/DiabloUI/text_draw.cpp | 3 +++ tools/patcher/DiabloUI/ui_item.h | 1 + 6 files changed, 24 insertions(+), 4 deletions(-) diff --git a/Source/DiabloUI/diabloui.cpp b/Source/DiabloUI/diabloui.cpp index ffb8a24b894..09f0d9f562e 100644 --- a/Source/DiabloUI/diabloui.cpp +++ b/Source/DiabloUI/diabloui.cpp @@ -476,9 +476,15 @@ static void Render(const UiImage* uiImage) CelDraw(x, y, uiImage->m_cel_data, frame + 1); } +static int UIItemFlags(int flags, const SDL_Rect& rect) +{ + const SDL_Point point = { MousePos.x, MousePos.y }; + return flags | (SDL_PointInRect(&point, &rect) ? UIS_LIGHT : 0); +} + static void Render(const UiTxtButton* uiButton) { - DrawArtStr(uiButton->m_text, uiButton->m_rect, uiButton->m_iFlags); + DrawArtStr(uiButton->m_text, uiButton->m_rect, UIItemFlags(uiButton->m_iFlags, uiButton->m_rect)); } static void Render(const UiButton* button) @@ -502,7 +508,7 @@ static void Render(const UiList* uiList) if (i + ListOffset == SelectedItem) DrawSelector(rect); UiListItem* item = (*uiList->m_vecItems)[i]; - DrawArtStr(item->m_text, rect, uiList->m_iFlags); + DrawArtStr(item->m_text, rect, UIItemFlags(uiList->m_iFlags, rect)); } } diff --git a/Source/DiabloUI/text_draw.cpp b/Source/DiabloUI/text_draw.cpp index ed131833a29..d3dc081b0b0 100644 --- a/Source/DiabloUI/text_draw.cpp +++ b/Source/DiabloUI/text_draw.cpp @@ -24,6 +24,9 @@ void DrawArtStr(const char* text, const SDL_Rect& rect, int flags) static int (*pChar)(int sx, int sy, BYTE text, BYTE col); color = color == AFC_SILVER ? COL_WHITE : COL_GOLD; + if (flags & UIS_LIGHT) { + color = COL_GOLD + 2; + } switch (size) { case AFT_SMALL: w = GetSmallStringWidth(text); diff --git a/Source/DiabloUI/ui_item.h b/Source/DiabloUI/ui_item.h index bd4ebd83ea5..46b95d4b19b 100644 --- a/Source/DiabloUI/ui_item.h +++ b/Source/DiabloUI/ui_item.h @@ -43,6 +43,7 @@ enum UiFlags : uint16_t { UIS_VCENTER = 1 << 6, UIS_SILVER = AFC_SILVER << 7, UIS_GOLD = AFC_GOLD << 7, + UIS_LIGHT = 1 << 8, UIS_OPTIONAL = 1 << 11, UIS_DISABLED = 1 << 12, UIS_HIDDEN = 1 << 13, diff --git a/tools/patcher/DiabloUI/diabloui.cpp b/tools/patcher/DiabloUI/diabloui.cpp index 493058508a5..02fa7d1e83e 100644 --- a/tools/patcher/DiabloUI/diabloui.cpp +++ b/tools/patcher/DiabloUI/diabloui.cpp @@ -484,10 +484,16 @@ static void Render(const UiImage* uiImage) CelDraw(x, y, uiImage->m_cel_data, frame + 1); } + +static int UIItemFlags(int flags, const SDL_Rect& rect) +{ + const SDL_Point point = { MousePos.x, MousePos.y }; + return flags | (SDL_PointInRect(&point, &rect) ? UIS_LIGHT : 0); +} #if FULL_UI static void Render(const UiTxtButton* uiButton) { - DrawArtStr(uiButton->m_text, uiButton->m_rect, uiButton->m_iFlags); + DrawArtStr(uiButton->m_text, uiButton->m_rect, UIItemFlags(uiButton->m_iFlags, uiButton->m_rect)); } #endif static void Render(const UiButton* button) @@ -511,7 +517,7 @@ static void Render(const UiList* uiList) if (i + ListOffset == SelectedItem) DrawSelector(rect); UiListItem* item = (*uiList->m_vecItems)[i]; - DrawArtStr(item->m_text, rect, uiList->m_iFlags); + DrawArtStr(item->m_text, rect, UIItemFlags(uiList->m_iFlags, rect)); } } #if FULL_UI diff --git a/tools/patcher/DiabloUI/text_draw.cpp b/tools/patcher/DiabloUI/text_draw.cpp index ed131833a29..d3dc081b0b0 100644 --- a/tools/patcher/DiabloUI/text_draw.cpp +++ b/tools/patcher/DiabloUI/text_draw.cpp @@ -24,6 +24,9 @@ void DrawArtStr(const char* text, const SDL_Rect& rect, int flags) static int (*pChar)(int sx, int sy, BYTE text, BYTE col); color = color == AFC_SILVER ? COL_WHITE : COL_GOLD; + if (flags & UIS_LIGHT) { + color = COL_GOLD + 2; + } switch (size) { case AFT_SMALL: w = GetSmallStringWidth(text); diff --git a/tools/patcher/DiabloUI/ui_item.h b/tools/patcher/DiabloUI/ui_item.h index 553f9dab737..e242b13a5a3 100644 --- a/tools/patcher/DiabloUI/ui_item.h +++ b/tools/patcher/DiabloUI/ui_item.h @@ -43,6 +43,7 @@ enum UiFlags : uint16_t { UIS_VCENTER = 1 << 6, UIS_SILVER = AFC_SILVER << 7, UIS_GOLD = AFC_GOLD << 7, + UIS_LIGHT = 1 << 8, UIS_DISABLED = 1 << 12, UIS_HIDDEN = 1 << 13, From 928ad557667094fd53f56e64b0b096d61ff719c8 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 29 Aug 2024 10:45:27 +0200 Subject: [PATCH 500/596] highlight in-game menu item under the mouse --- Source/gmenu.cpp | 47 ++++++++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/Source/gmenu.cpp b/Source/gmenu.cpp index 2dbb55c4142..c350c9ed7e3 100644 --- a/Source/gmenu.cpp +++ b/Source/gmenu.cpp @@ -165,14 +165,41 @@ static int gmenu_get_lfont(TMenuItem* pItem) return GetHugeStringWidth(pItem->pszStr); } +static TMenuItem* current_menu_item(bool activate) +{ + int i, w; + TMenuItem* pItem; + + i = MousePos.y - (PANEL_TOP + GAMEMENU_HEADER_Y + GAMEMENU_HEADER_OFF); + if (i < 0) { + return NULL; + } + i /= GAMEMENU_ITEM_HEIGHT; + if (i >= guCurrentMenuSize) { + return NULL; + } + pItem = &gpCurrentMenu[i]; + if (!(pItem->dwFlags & GMF_ENABLED)) { + return NULL; + } + w = gmenu_get_lfont(pItem) / 2; + if (abs(MousePos.x - SCREEN_WIDTH / 2) > w) + return NULL; + + if (activate) + guCurrItemIdx = i; + return pItem; +} + static void gmenu_draw_menu_item(int i, int y) { TMenuItem* pItem = &gpCurrentMenu[i]; + TMenuItem* mItem = current_menu_item(false); unsigned w, x, nSteps, step, pos; w = gmenu_get_lfont(pItem); x = PANEL_CENTERX(w); - PrintHugeString(x, y, pItem->pszStr, (pItem->dwFlags & GMF_ENABLED) ? 0 : MAXDARKNESS); + PrintHugeString(x, y, pItem->pszStr, COL_GOLD + ((pItem->dwFlags & GMF_ENABLED) ? (pItem == mItem ? 2 : 0) : MAXDARKNESS)); if (pItem == &gpCurrentMenu[guCurrItemIdx]) DrawHugePentSpn(x - (FOCUS_HUGE + 6), x + 4 + w, y + 1); if (pItem->dwFlags & GMF_SLIDER) { @@ -286,7 +313,6 @@ void gmenu_on_mouse_move() void gmenu_left_mouse(bool isDown) { TMenuItem* pItem; - int i, w; // assert(gmenu_is_active()); if (!isDown) { @@ -301,22 +327,9 @@ void gmenu_left_mouse(bool isDown) return; } #endif - i = MousePos.y - (PANEL_TOP + GAMEMENU_HEADER_Y + GAMEMENU_HEADER_OFF); - if (i < 0) { - return; - } - i /= GAMEMENU_ITEM_HEIGHT; - if (i >= guCurrentMenuSize) { - return; - } - pItem = &gpCurrentMenu[i]; - if (!(pItem->dwFlags & GMF_ENABLED)) { - return; - } - w = gmenu_get_lfont(pItem) / 2; - if (abs(MousePos.x - SCREEN_WIDTH / 2) > w) + pItem = current_menu_item(true); + if (pItem == NULL) return; - guCurrItemIdx = i; if (pItem->dwFlags & GMF_SLIDER) { gmenu_mouse_slider(); } else { From 9a41dce7e95531a9dd1df58bc81c58c8c939cad9 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 29 Aug 2024 10:58:54 +0200 Subject: [PATCH 501/596] highlight store menu item under the mouse --- Source/stores.cpp | 49 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index 5c7ec69c885..3bb6f45d99f 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -1384,6 +1384,32 @@ void DrawStoreLineY(int sx, int sy, int dx, int dy, int height) for (i = 0; i < height; i++, src += width, dst += width) memcpy(dst, src, TPANEL_BORDER); }*/ +static int current_store_index() +{ + int mx, my, y; + + mx = MousePos.x; + my = MousePos.y; + + y = (my - (LTPANEL_Y - SCREEN_Y + 8)) / 12; + if (gbWidePanel) { + if (mx < LTPANEL_X - SCREEN_X || mx > LTPANEL_X + LTPANEL_WIDTH - SCREEN_X) + y = 0; + } else { + if (mx < STORE_PNL_X - SCREEN_X || mx > STORE_PNL_X + STPANEL_WIDTH - SCREEN_X) + y = 0; + } + + if (y >= STORE_LIST_FIRST && y < STORE_LINES) { + static_assert(STORE_BACK <= 22, "STORE_BACK does not fit to current_store_index."); + // add some freedom to the back button since it has an offset + if (y >= 22) + y = 22; + } else { + y = 0; + } + return y; +} void DrawStore() { @@ -1426,12 +1452,14 @@ void DrawStore() StoreUpdateSelection(); // check maxx } + int y = current_store_index(); + STextStruct* stc = &stextlines[y]; for (i = 0; i < STORE_LINES; i++) { sts = &stextlines[i]; // if (sts->_sline) // DrawTextBoxSLine(gbWidePanel ? LTPANEL_X : STORE_PNL_X, LTPANEL_Y, i * 12 + 14, gbWidePanel); if (sts->_sstr[0] != '\0') - PrintSString(sts->_sx, i, sts->_sjust, sts->_sstr, sts->_sclr, sts->_sval); + PrintSString(sts->_sx, i, sts->_sjust, sts->_sstr, (sts == stc && sts->_ssel) ? COL_GOLD + 1 + 4 : sts->_sclr, sts->_sval); else if (sts->_sitemlist) { for (int n = 0; n < lengthof(sts->_siCurs); n++) { int frame = sts->_siCurs[n]; @@ -2728,14 +2756,9 @@ void TryStoreBtnClick() assert(!gbQtextflag); if (stextsel != -1 && stextflag != STORE_WAIT) { - if (gbWidePanel) { - if (MousePos.x < LTPANEL_X - SCREEN_X || MousePos.x > LTPANEL_X + LTPANEL_WIDTH - SCREEN_X) - return; - } else { - if (MousePos.x < STORE_PNL_X - SCREEN_X || MousePos.x > STORE_PNL_X + STPANEL_WIDTH - SCREEN_X) - return; - } - y = (MousePos.y - (LTPANEL_Y - SCREEN_Y + 8)) / 12; + y = current_store_index(); + if (y == 0) + return; //assert(LTPANEL_X + LTPANEL_WIDTH == STORE_PNL_X + STPANEL_WIDTH); //if (MousePos.x >= STORE_PNL_X + STPANEL_WIDTH - (SMALL_SCROLL_WIDTH + 2) - SCREEN_X && gbHasScroll) { if (MousePos.x >= LTPANEL_X + LTPANEL_WIDTH - (SMALL_SCROLL_WIDTH + 2) - SCREEN_X && gbHasScroll) { @@ -2770,13 +2793,9 @@ void TryStoreBtnClick() } } } - } else if (y >= STORE_LIST_FIRST && y < STORE_LINES) { - static_assert(STORE_BACK <= 22, "STORE_BACK does not fit to TryStoreBtnClick."); - // add some freedom to the back button since it has an offset - if (y >= 22) - y = 22; + } else { // allow clicking on multi-line items - else if (gbHasScroll /*&& y < 21*/ /*&& !stextlines[y]._ssel*/) { + if (gbHasScroll && y < 21 /*&& !stextlines[y]._ssel*/) { y++; for (int n = 0; n < STORE_ITEM_LINES; n++) { if (stextlines[y]._ssel) From 18d638b5720549d0a25e2ecc27da18ee6e47f543 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 29 Aug 2024 11:31:57 +0200 Subject: [PATCH 502/596] set the starting position of the mouse over the first menu entry --- Source/diablo.cpp | 2 +- tools/patcher/diablo.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/diablo.cpp b/Source/diablo.cpp index 9a8d943571f..23d4cbeab68 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -142,7 +142,7 @@ static int diablo_parse_flags(int argc, char** argv) static void diablo_init_screen() { MousePos.x = SCREEN_WIDTH / 2; - MousePos.y = SCREEN_HEIGHT / 2; + MousePos.y = MAINMENU_TOP + MAINMENU_ITEM_HEIGHT / 2; #if HAS_GAMECTRL || HAS_JOYSTICK || HAS_KBCTRL || HAS_DPAD if (!sgbControllerActive) #endif diff --git a/tools/patcher/diablo.cpp b/tools/patcher/diablo.cpp index 2416e71446e..f80fc6719ea 100644 --- a/tools/patcher/diablo.cpp +++ b/tools/patcher/diablo.cpp @@ -43,7 +43,7 @@ static int diablo_parse_flags(int argc, char** argv) static void diablo_init_screen() { MousePos.x = SCREEN_WIDTH / 2; - MousePos.y = SCREEN_HEIGHT / 2; + MousePos.y = MAINMENU_TOP + MAINMENU_ITEM_HEIGHT / 2; #if HAS_GAMECTRL || HAS_JOYSTICK || HAS_KBCTRL || HAS_DPAD if (!sgbControllerActive) #endif From 94cf65beb0a9f2ed32c9870e7279c90e987dce4b Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 29 Aug 2024 11:52:16 +0200 Subject: [PATCH 503/596] use white color for 'Run errand' --- Source/stores.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/stores.cpp b/Source/stores.cpp index 3bb6f45d99f..eac87357cf8 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -1204,7 +1204,7 @@ static void S_StartPriest() // gbHasScroll = false; AddSText(0, 2, true, "Tremain the Priest", COL_GOLD, false); AddSText(0, 9, true, "Would you like to:", COL_GOLD, false); - AddSText(0, STORE_PRIEST_ERRAND, true, "Run errand", COL_BLUE, true); + AddSText(0, STORE_PRIEST_ERRAND, true, "Run errand", COL_WHITE, true); AddSText(0, STORE_PRIEST_EXIT, true, "Say Goodbye", COL_WHITE, true); // AddSLine(5); } From 499f8bec533883aa373a017251d14819cc6c62c7 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 29 Aug 2024 12:02:03 +0200 Subject: [PATCH 504/596] optimize the positioning of the modifier hints --- Source/controls/modifier_hints.cpp | 37 +++++++++++++----------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/Source/controls/modifier_hints.cpp b/Source/controls/modifier_hints.cpp index ed541db7c70..903c6cba22c 100644 --- a/Source/controls/modifier_hints.cpp +++ b/Source/controls/modifier_hints.cpp @@ -20,7 +20,7 @@ int CalculateTextWidth(const char* s) int SpaceWidth() { - static const int spaceWidth = CalculateTextWidth(" "); + static const int spaceWidth = smallFontWidth[0]; // CalculateTextWidth(" "); return spaceWidth; } @@ -28,34 +28,29 @@ struct CircleMenuHint { CircleMenuHint(bool isDpad, const char* top, const char* right, const char* bottom, const char* left) : is_dpad(isDpad) , top(top) - , top_w(CalculateTextWidth(top)) , right(right) - , right_w(CalculateTextWidth(right)) , bottom(bottom) - , bottom_w(CalculateTextWidth(bottom)) , left(left) - , left_w(CalculateTextWidth(left)) - , x_mid(left_w + SpaceWidth() * 5 / 2) { - } - - int Width() const - { - return 2 * x_mid; + int left_w = CalculateTextWidth(left); + int x_mid = left_w + SpaceWidth() * 5 / 2; + width = 2 * x_mid; + top_offx = x_mid - CalculateTextWidth(top) / 2; + bottom_offx = x_mid - CalculateTextWidth(bottom) / 2; + right_offx = left_w + SpaceWidth() * 5; } bool is_dpad; const char* top; - int top_w; const char* right; - int right_w; const char* bottom; - int bottom_w; const char* left; - int left_w; - int x_mid; + int width; + int top_offx; + int right_offx; + int bottom_offx; }; bool IsTopActive(const CircleMenuHint& hint) @@ -97,14 +92,14 @@ void DrawCircleMenuHint(const CircleMenuHint& hint, int x, int y) x += SCREEN_X; y += SCREEN_Y; - PrintGameStr(x + hint.x_mid - hint.top_w / 2, y, hint.top, CircleMenuHintTextColor(IsTopActive(hint))); + PrintGameStr(x + hint.top_offx, y, hint.top, CircleMenuHintTextColor(IsTopActive(hint))); y += lineHeight; PrintGameStr(x, y, hint.left, CircleMenuHintTextColor(IsLeftActive(hint))); - PrintGameStr(x + hint.left_w + 5 * SpaceWidth(), y, hint.right, CircleMenuHintTextColor(IsRightActive(hint))); + PrintGameStr(x + hint.right_offx, y, hint.right, CircleMenuHintTextColor(IsRightActive(hint))); y += lineHeight; - PrintGameStr(x + hint.x_mid - hint.bottom_w / 2, y, hint.bottom, CircleMenuHintTextColor(IsBottomActive(hint))); + PrintGameStr(x + hint.bottom_offx, y, hint.bottom, CircleMenuHintTextColor(IsBottomActive(hint))); } const int CircleMarginX = 16; @@ -117,7 +112,7 @@ void DrawStartModifierMenu() static const CircleMenuHint dPad(/*is_dpad=*/true, /*top=*/"Menu", /*right=*/"Inv", /*bottom=*/"Map", /*left=*/"Char"); static const CircleMenuHint buttons(/*is_dpad=*/false, /*top=*/"", /*right=*/"", /*bottom=*/"Spells", /*left=*/"Quests"); DrawCircleMenuHint(dPad, PANEL_LEFT + CircleMarginX, SCREEN_HEIGHT - CirclesTop); - DrawCircleMenuHint(buttons, PANEL_LEFT + PANEL_WIDTH - buttons.Width() - CircleMarginX, SCREEN_HEIGHT - CirclesTop); + DrawCircleMenuHint(buttons, PANEL_LEFT + PANEL_WIDTH - buttons.width - CircleMarginX, SCREEN_HEIGHT - CirclesTop); } void DrawSelectModifierMenu() @@ -129,7 +124,7 @@ void DrawSelectModifierMenu() DrawCircleMenuHint(dPad, PANEL_LEFT + CircleMarginX, SCREEN_HEIGHT - CirclesTop); } static const CircleMenuHint spells(/*is_dpad=*/false, "W", "R", "E", "Q"); - DrawCircleMenuHint(spells, PANEL_LEFT + PANEL_WIDTH - spells.Width() - CircleMarginX, SCREEN_HEIGHT - CirclesTop); + DrawCircleMenuHint(spells, PANEL_LEFT + PANEL_WIDTH - spells.width - CircleMarginX, SCREEN_HEIGHT - CirclesTop); } } // namespace From 60dac83c72d9e976e1c7034175cf03a99fab98b6 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 29 Aug 2024 12:11:50 +0200 Subject: [PATCH 505/596] reorder DisableInputWndProc and GameWndProc --- Source/diablo.cpp | 57 +++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/Source/diablo.cpp b/Source/diablo.cpp index 23d4cbeab68..732b97f0d33 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -1078,13 +1078,7 @@ static void UpdateActionBtnState(int vKey, bool dir) void DisableInputWndProc(const Dvl_Event* e) { switch (e->type) { - case DVL_WM_KEYDOWN: - UpdateActionBtnState(e->vkcode, true); - break; // return; - case DVL_WM_KEYUP: - UpdateActionBtnState(e->vkcode, false); - break; // return; - case DVL_WM_TEXT: + case DVL_WM_NONE: //case DVL_WM_SYSKEYDOWN: //case DVL_WM_SYSCOMMAND: break; // return; @@ -1106,6 +1100,14 @@ void DisableInputWndProc(const Dvl_Event* e) case DVL_WM_RBUTTONUP: UpdateActionBtnState(DVL_VK_RBUTTON, false); break; // return; + case DVL_WM_KEYDOWN: + UpdateActionBtnState(e->vkcode, true); + break; // return; + case DVL_WM_KEYUP: + UpdateActionBtnState(e->vkcode, false); + break; // return; + case DVL_WM_TEXT: + break; // return; case DVL_WM_CAPTURECHANGED: gbActionBtnDown = false; gbAltActionBtnDown = false; @@ -1113,7 +1115,6 @@ void DisableInputWndProc(const Dvl_Event* e) case DVL_WM_PAINT: gbRedrawFlags = REDRAW_ALL; break; // return; - case DVL_WM_NONE: // case DVL_WM_QUERYENDSESSION: // case DVL_DWM_NEXTLVL: // case DVL_DWM_PREVLVL: @@ -1126,7 +1127,7 @@ void DisableInputWndProc(const Dvl_Event* e) // case DVL_DWM_RETOWN: // case DVL_DWM_NEWGAME: // case DVL_DWM_LOADGAME: - break; + // break; default: ASSUME_UNREACHABLE } @@ -1137,23 +1138,8 @@ void DisableInputWndProc(const Dvl_Event* e) static void GameWndProc(const Dvl_Event* e) { switch (e->type) { - case DVL_WM_KEYDOWN: - PressKey(e->vkcode); - break; // return; - case DVL_WM_KEYUP: - ReleaseKey(e->vkcode); - break; // return; - case DVL_WM_TEXT: -#ifndef USE_SDL1 - if (gmenu_is_active()) { - break; // return; - } - if (gbTalkflag) { - plrmsg_CatToText(e->text.text); - break; // return; - } -#endif - break; // return; + case DVL_WM_NONE: + break; //case DVL_WM_SYSKEYDOWN: // if (PressSysKey(wParam)) // break; // return; @@ -1193,6 +1179,20 @@ static void GameWndProc(const Dvl_Event* e) //GetMousePos(wParam); ReleaseKey(DVL_VK_RBUTTON); break; // return; + case DVL_WM_KEYDOWN: + PressKey(e->vkcode); + break; // return; + case DVL_WM_KEYUP: + ReleaseKey(e->vkcode); + break; // return; + case DVL_WM_TEXT: +#ifndef USE_SDL1 + if (gmenu_is_active()) + break; // return; + else if (gbTalkflag) + plrmsg_CatToText(e->text.text); +#endif + break; // return; case DVL_WM_CAPTURECHANGED: gbActionBtnDown = false; gbAltActionBtnDown = false; @@ -1200,6 +1200,8 @@ static void GameWndProc(const Dvl_Event* e) case DVL_WM_PAINT: gbRedrawFlags = REDRAW_ALL; break; // return; + // case DVL_WM_QUERYENDSESSION: + // break; case DVL_DWM_NEXTLVL: case DVL_DWM_PREVLVL: case DVL_DWM_SETLVL: @@ -1226,9 +1228,6 @@ static void GameWndProc(const Dvl_Event* e) //gbRedrawFlags = REDRAW_ALL; } break; // return; - case DVL_WM_NONE: - // case DVL_WM_QUERYENDSESSION: - break; default: ASSUME_UNREACHABLE } From 22119433e11ac942e1633d7fb5d93d02bb8f8e0d Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 29 Aug 2024 12:17:50 +0200 Subject: [PATCH 506/596] reduce the number of return points in gmenu_on_mouse_move and gmenu_left_mouse --- Source/gmenu.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Source/gmenu.cpp b/Source/gmenu.cpp index c350c9ed7e3..d01b7dda045 100644 --- a/Source/gmenu.cpp +++ b/Source/gmenu.cpp @@ -304,10 +304,11 @@ static void gmenu_mouse_slider() void gmenu_on_mouse_move() { - if (!_gbMouseNavigation) - return; // FALSE; - gmenu_mouse_slider(); - // return TRUE; + if (_gbMouseNavigation) { + gmenu_mouse_slider(); + // return TRUE; + } + // return FALSE; } void gmenu_left_mouse(bool isDown) @@ -328,12 +329,12 @@ void gmenu_left_mouse(bool isDown) } #endif pItem = current_menu_item(true); - if (pItem == NULL) - return; - if (pItem->dwFlags & GMF_SLIDER) { - gmenu_mouse_slider(); - } else { - pItem->fnMenu(true); + if (pItem != NULL) { + if (pItem->dwFlags & GMF_SLIDER) { + gmenu_mouse_slider(); + } else { + pItem->fnMenu(true); + } } } From 87a896f28ee8748851b1b11eee7c0eeaabc78b25 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 29 Aug 2024 12:19:26 +0200 Subject: [PATCH 507/596] use arithmetic shift instead of signed div by 2 --- Source/DiabloUI/text_draw.cpp | 4 ++-- Source/control.cpp | 15 ++++++++------- Source/controls/modifier_hints.cpp | 8 ++++---- Source/debug.cpp | 4 ++++ Source/diablo.cpp | 2 +- Source/drlg_l4.cpp | 12 ++++++------ Source/gmenu.cpp | 9 +++++---- Source/scrollrt.cpp | 6 +++--- Source/storm/storm_svid.cpp | 4 ++-- tools/patcher/DiabloUI/text_draw.cpp | 4 ++-- tools/patcher/diablo.cpp | 2 +- 11 files changed, 38 insertions(+), 32 deletions(-) diff --git a/Source/DiabloUI/text_draw.cpp b/Source/DiabloUI/text_draw.cpp index d3dc081b0b0..9aa8cac7e89 100644 --- a/Source/DiabloUI/text_draw.cpp +++ b/Source/DiabloUI/text_draw.cpp @@ -10,7 +10,7 @@ DEVILUTION_BEGIN_NAMESPACE static int AlignXOffset(int flags, const SDL_Rect& dest, int w) { if (flags & UIS_HCENTER) - return (dest.w - w) / 2; + return (dest.w - w) >> 1; if (flags & UIS_RIGHT) return dest.w - w; return 0; @@ -57,7 +57,7 @@ void DrawArtStr(const char* text, const SDL_Rect& rect, int flags) } int x = rect.x + AlignXOffset(flags, rect, w) + SCREEN_X; - int y = rect.y + ((flags & UIS_VCENTER) ? (rect.h - h) / 2 : 0) + SCREEN_Y + h; + int y = rect.y + ((flags & UIS_VCENTER) ? ((rect.h - h) >> 1) : 0) + SCREEN_Y + h; y += dy; h += dy; diff --git a/Source/control.cpp b/Source/control.cpp index f3648296592..017c2f375e5 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -381,6 +381,7 @@ void DrawSkillIcons() case TGT_OBJECT: str = "Object"; numchar = lengthof("Object") - 1; + static_assert((lengthof("Object") - 1) * SMALL_FONT_HEIGHT <= 2 * SPLICON_WIDTH, "DrawSkillIcons uses unsigned division to calculate sy."); break; case TGT_OTHER: str = "Other"; @@ -399,12 +400,12 @@ void DrawSkillIcons() } // PrintSmallVerticalStr centered int sx = PANEL_X + PANEL_WIDTH - SMALL_FONT_HEIGHT - 2; - int sy = PANEL_Y + PANEL_HEIGHT - 2 * SPLICON_WIDTH + (2 * SPLICON_WIDTH - numchar * SMALL_FONT_HEIGHT) / 2; + int sy = PANEL_Y + PANEL_HEIGHT - 2 * SPLICON_WIDTH + (2 * SPLICON_WIDTH - numchar * SMALL_FONT_HEIGHT) / 2u; for (unsigned i = 0; i < numchar; i++) { sy += SMALL_FONT_HEIGHT; BYTE nCel = gbStdFontFrame[str[i]]; // PrintSmallChar(sx + (SMALL_FONT_WIDTH - smallFontWidth[nCel]) / 2, sy, str[i], COL_GOLD); - PrintSmallColorChar(sx + (13 - smallFontWidth[nCel]) / 2, sy, nCel, COL_GOLD); + PrintSmallColorChar(sx + (13 - smallFontWidth[nCel]) / 2u, sy, nCel, COL_GOLD); } } @@ -1462,7 +1463,7 @@ static int DrawTooltip2(const char* text1, const char* text2, int x, int y, BYTE if (y < 0) return result; - x -= width / 2; + x -= width / 2u; if (x < 0) { result = -x; x = 0; @@ -1532,8 +1533,8 @@ static POS32 GetMousePos(int x, int y) pos.y <<= 1; } - pos.x += SCREEN_WIDTH / 2; - pos.y += VIEWPORT_HEIGHT / 2; + pos.x += SCREEN_WIDTH / 2u; + pos.y += VIEWPORT_HEIGHT / 2u; return pos; } @@ -1569,7 +1570,7 @@ static int DrawTooltip(const char* text, int x, int y, BYTE col) if (y < 0) return result; - x -= width / 2; + x -= width / 2u; if (x < 0) { result = -x; x = 0; @@ -1831,7 +1832,7 @@ void DrawInfoStr() DrawTrigInfo(); } else if (pcursicon >= CURSOR_FIRSTITEM) { GetItemInfo(&myplr._pHoldItem); - DrawTooltip(infostr, MousePos.x + cursW / 2, MousePos.y - TOOLTIP_OFFSET, infoclr); + DrawTooltip(infostr, MousePos.x + cursW / 2u, MousePos.y - TOOLTIP_OFFSET, infoclr); } } diff --git a/Source/controls/modifier_hints.cpp b/Source/controls/modifier_hints.cpp index 903c6cba22c..14aa2e9740b 100644 --- a/Source/controls/modifier_hints.cpp +++ b/Source/controls/modifier_hints.cpp @@ -32,11 +32,11 @@ struct CircleMenuHint { , bottom(bottom) , left(left) { - int left_w = CalculateTextWidth(left); - int x_mid = left_w + SpaceWidth() * 5 / 2; + int left_w = CalculateTextWidth(left); // std::max(CalculateTextWidth(left), CalculateTextWidth(right)); + int x_mid = left_w + SpaceWidth() * 5 / 2u; width = 2 * x_mid; - top_offx = x_mid - CalculateTextWidth(top) / 2; - bottom_offx = x_mid - CalculateTextWidth(bottom) / 2; + top_offx = x_mid - CalculateTextWidth(top) / 2u; + bottom_offx = x_mid - CalculateTextWidth(bottom) / 2u; right_offx = left_w + SpaceWidth() * 5; } diff --git a/Source/debug.cpp b/Source/debug.cpp index a4bc889bce9..4acf72d072d 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -251,6 +251,10 @@ void ValidateData() if (gbStdFontFrame[i] >= lengthof(smallFontWidth)) app_fatal("Width of the small font %d ('%c') is undefined (frame number: %d).", i, i, gbStdFontFrame[i]); } + for (i = 0; i < lengthof(smallFontWidth); i++) { + if (smallFontWidth[i] > 13) + app_fatal("Width of the small font %d is too high.", i); // required by DrawSkillIcons + } if (GetHugeStringWidth("Pause") != 135) app_fatal("gmenu_draw_pause expects hardcoded width 135."); diff --git a/Source/diablo.cpp b/Source/diablo.cpp index 732b97f0d33..9a079492c18 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -141,7 +141,7 @@ static int diablo_parse_flags(int argc, char** argv) static void diablo_init_screen() { - MousePos.x = SCREEN_WIDTH / 2; + MousePos.x = SCREEN_WIDTH / 2u; MousePos.y = MAINMENU_TOP + MAINMENU_ITEM_HEIGHT / 2; #if HAS_GAMECTRL || HAS_JOYSTICK || HAS_KBCTRL || HAS_DPAD if (!sgbControllerActive) diff --git a/Source/drlg_l4.cpp b/Source/drlg_l4.cpp index 4a3ebe36d3e..846c990f910 100644 --- a/Source/drlg_l4.cpp +++ b/Source/drlg_l4.cpp @@ -1374,7 +1374,7 @@ static void L4RoomGen(int x, int y, int w, int h, bool dir) for (i = 20; i != 0; i--) { width = RandRange(2, 6) & ~1; height = RandRange(2, 6) & ~1; - ry = h / 2 + y - height / 2; + ry = h / 2u + y - height / 2u; rx = x - width; if (L4CheckVHall(x, ry - 1, height + 2) && L4CheckRoom(rx - 1, ry - 1, width + 1, height + 2)) /// BUGFIX: swap args 3 and 4 ("ch+2" and "cw+1") (fixed) @@ -1400,7 +1400,7 @@ static void L4RoomGen(int x, int y, int w, int h, bool dir) for (i = 20; i != 0; i--) { width = RandRange(2, 6) & ~1; height = RandRange(2, 6) & ~1; - rx = w / 2 + x - width / 2; + rx = w / 2u + x - width / 2u; ry = y - height; if (L4CheckHHall(y, rx - 1, width + 2) && L4CheckRoom(rx - 1, ry - 1, width + 2, height + 1)) @@ -1959,21 +1959,21 @@ static void DRLG_L4ThemeExitFix() y2 = themes[i]._tsy2; switch (random_(0, 4)) { case 0: - yy = (y1 + y2 + 1) / 2; + yy = (y1 + y2 + 1) / 2u; dungeon[x1][yy - 1] = 53; dungeon[x1][yy + 0] = 50; dungeon[x1][yy + 1] = 52; //dungeon[x2 - 1][yy - 1] = 54; break; case 1: - yy = (y1 + y2 + 1) / 2; + yy = (y1 + y2 + 1) / 2u; dungeon[x2][yy - 1] = 53; dungeon[x2][yy + 0] = 50; dungeon[x2][yy + 1] = 52; //dungeon[x2 - 1][yy - 1] = 54; break; case 2: - xx = (x1 + x2 + 1) / 2; + xx = (x1 + x2 + 1) / 2u; dungeon[xx - 1][y1] = 57; dungeon[xx + 0][y1] = 50; dungeon[xx + 1][y1] = 56; @@ -1981,7 +1981,7 @@ static void DRLG_L4ThemeExitFix() //dungeon[xx - 1][y2 - 1] = 58; break; case 3: - xx = (x1 + x2 + 1) / 2; + xx = (x1 + x2 + 1) / 2u; dungeon[xx - 1][y2] = 57; dungeon[xx + 0][y2] = 50; dungeon[xx + 1][y2] = 56; diff --git a/Source/gmenu.cpp b/Source/gmenu.cpp index d01b7dda045..a7395f7d74f 100644 --- a/Source/gmenu.cpp +++ b/Source/gmenu.cpp @@ -182,8 +182,8 @@ static TMenuItem* current_menu_item(bool activate) if (!(pItem->dwFlags & GMF_ENABLED)) { return NULL; } - w = gmenu_get_lfont(pItem) / 2; - if (abs(MousePos.x - SCREEN_WIDTH / 2) > w) + w = gmenu_get_lfont(pItem) / 2u; + if (abs(MousePos.x - (int)(SCREEN_WIDTH / 2u)) > w) return NULL; if (activate) @@ -285,7 +285,7 @@ static void gmenu_mouse_slider() TMenuItem* pItem; int offset; - offset = MousePos.x - (SCREEN_WIDTH / 2 - SLIDER_ROW_WIDTH / 2 + SLIDER_OFFSET + SLIDER_BORDER + SLIDER_BUTTON_WIDTH / 2); + offset = MousePos.x - (SCREEN_WIDTH / 2u - SLIDER_ROW_WIDTH / 2 + SLIDER_OFFSET + SLIDER_BORDER + SLIDER_BUTTON_WIDTH / 2); if (offset < 0) { if (offset < -(SLIDER_BUTTON_WIDTH / 2)) return; @@ -351,8 +351,9 @@ void gmenu_slider_set(TMenuItem* pItem, int min, int max, int value) int nSteps; //assert(pItem != NULL); + //assert(max > min); nSteps = pItem->wMenuParam1; - pItem->wMenuParam2 = ((max - min) / 2 + (value - min) * nSteps) / (max - min); + pItem->wMenuParam2 = ((max - min) / 2u + (value - min) * nSteps) / (max - min); } int gmenu_slider_get(TMenuItem* pItem, int min, int max) diff --git a/Source/scrollrt.cpp b/Source/scrollrt.cpp index 39963d35dc4..dc2dba75190 100644 --- a/Source/scrollrt.cpp +++ b/Source/scrollrt.cpp @@ -1253,14 +1253,14 @@ static void scrollrt_draw(int x, int y, int sx, int sy, int rows, int columns) */ static void Zoom() { - int wdt = SCREEN_WIDTH / 2; - int nSrcOff = SCREENXY(SCREEN_WIDTH / 2 - 1, VIEWPORT_HEIGHT / 2 - 1); + int wdt = SCREEN_WIDTH / 2u; + int nSrcOff = SCREENXY(SCREEN_WIDTH / 2u - 1, VIEWPORT_HEIGHT / 2u - 1); int nDstOff = SCREENXY(SCREEN_WIDTH - 1, VIEWPORT_HEIGHT - 1); BYTE* src = &gpBuffer[nSrcOff]; BYTE* dst = &gpBuffer[nDstOff]; - for (int hgt = 0; hgt < VIEWPORT_HEIGHT / 2; hgt++) { + for (unsigned hgt = 0; hgt < VIEWPORT_HEIGHT / 2u; hgt++) { for (int i = 0; i < wdt; i++) { *dst-- = *src; *dst-- = *src; diff --git a/Source/storm/storm_svid.cpp b/Source/storm/storm_svid.cpp index 617d4d8d125..c0db91f0b16 100644 --- a/Source/storm/storm_svid.cpp +++ b/Source/storm/storm_svid.cpp @@ -420,8 +420,8 @@ bool SVidPlayContinue() outputRect.w = SVidWidth * outputSurface->h / SVidHeight; outputRect.h = outputSurface->h; } - outputRect.x = (outputSurface->w - outputRect.w) / 2; - outputRect.y = (outputSurface->h - outputRect.h) / 2; + outputRect.x = (outputSurface->w - outputRect.w) >> 1; + outputRect.y = (outputSurface->h - outputRect.h) >> 1; if (isIndexedOutputFormat || outputSurface->w == static_cast(SVidWidth) diff --git a/tools/patcher/DiabloUI/text_draw.cpp b/tools/patcher/DiabloUI/text_draw.cpp index d3dc081b0b0..9aa8cac7e89 100644 --- a/tools/patcher/DiabloUI/text_draw.cpp +++ b/tools/patcher/DiabloUI/text_draw.cpp @@ -10,7 +10,7 @@ DEVILUTION_BEGIN_NAMESPACE static int AlignXOffset(int flags, const SDL_Rect& dest, int w) { if (flags & UIS_HCENTER) - return (dest.w - w) / 2; + return (dest.w - w) >> 1; if (flags & UIS_RIGHT) return dest.w - w; return 0; @@ -57,7 +57,7 @@ void DrawArtStr(const char* text, const SDL_Rect& rect, int flags) } int x = rect.x + AlignXOffset(flags, rect, w) + SCREEN_X; - int y = rect.y + ((flags & UIS_VCENTER) ? (rect.h - h) / 2 : 0) + SCREEN_Y + h; + int y = rect.y + ((flags & UIS_VCENTER) ? ((rect.h - h) >> 1) : 0) + SCREEN_Y + h; y += dy; h += dy; diff --git a/tools/patcher/diablo.cpp b/tools/patcher/diablo.cpp index f80fc6719ea..aa7c15b1d44 100644 --- a/tools/patcher/diablo.cpp +++ b/tools/patcher/diablo.cpp @@ -42,7 +42,7 @@ static int diablo_parse_flags(int argc, char** argv) static void diablo_init_screen() { - MousePos.x = SCREEN_WIDTH / 2; + MousePos.x = SCREEN_WIDTH / 2u; MousePos.y = MAINMENU_TOP + MAINMENU_ITEM_HEIGHT / 2; #if HAS_GAMECTRL || HAS_JOYSTICK || HAS_KBCTRL || HAS_DPAD if (!sgbControllerActive) From 34c664288cf5ee4a032fae11b108b3c82c7547f3 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 29 Aug 2024 12:54:47 +0200 Subject: [PATCH 508/596] fix DRLG_PlaceThemeRooms after 'limit the number of theme-rooms in cathedral (and everywhere else) to 8' --- Source/gendung.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/gendung.cpp b/Source/gendung.cpp index ff619a7d044..15be8a9fcb1 100644 --- a/Source/gendung.cpp +++ b/Source/gendung.cpp @@ -1552,7 +1552,7 @@ void DRLG_PlaceThemeRooms(int minSize, int maxSize, const BYTE (&themeTiles)[NUM DRLG_CreateThemeRoom(numthemes, themeTiles); numthemes++; if (numthemes == lengthof(themes)) - break; // should not happen (too often), otherwise the theme-placement is biased + return; // should not happen (too often), otherwise the theme-placement is biased } j += tArea.h; From 8daebbdf2e553b756fcc5def8cedafd4e670bcc4 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 30 Aug 2024 08:16:46 +0200 Subject: [PATCH 509/596] fix bias in L4RoomGen --- Source/drlg_l4.cpp | 74 +++++++++++++++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 20 deletions(-) diff --git a/Source/drlg_l4.cpp b/Source/drlg_l4.cpp index 846c990f910..9e618edae5d 100644 --- a/Source/drlg_l4.cpp +++ b/Source/drlg_l4.cpp @@ -1365,7 +1365,6 @@ static bool L4CheckHHall(int y, int left, int w) static void L4RoomGen(int x, int y, int w, int h, bool dir) { int dirProb, i, width, height, rx, ry, rxy2; - bool ran2; dirProb = random_(0, 4); @@ -1377,23 +1376,40 @@ static void L4RoomGen(int x, int y, int w, int h, bool dir) ry = h / 2u + y - height / 2u; rx = x - width; if (L4CheckVHall(x, ry - 1, height + 2) - && L4CheckRoom(rx - 1, ry - 1, width + 1, height + 2)) /// BUGFIX: swap args 3 and 4 ("ch+2" and "cw+1") (fixed) + && L4CheckRoom(rx - 1, ry - 1, width + 1, height + 2)) { /// BUGFIX: swap args 3 and 4 ("ch+2" and "cw+1") (fixed) + // - add room to the left + L4DrawRoom(rx, ry, width, height); break; + } + } + if (i != 0) { + // room added to the left -> force similar room on the right side + i = 1; + } else { + // room was not added to the left -> try more options on the right + rx = -1; + i = 20; } - - if (i != 0) - L4DrawRoom(rx, ry, width, height); // try to place a room to the right rxy2 = x + w; - ran2 = L4CheckVHall(rxy2 - 1, ry - 1, height + 2) - && L4CheckRoom(rxy2, ry - 1, width + 1, height + 2); - if (ran2) - L4DrawRoom(rxy2, ry, width, height); + while(true) { + if (L4CheckVHall(rxy2 - 1, ry - 1, height + 2) + && L4CheckRoom(rxy2, ry - 1, width + 1, height + 2)) { + // - add room to the right + L4DrawRoom(rxy2, ry, width, height); + break; + } + if (--i == 0) + break; + width = RandRange(2, 6) & ~1; + height = RandRange(2, 6) & ~1; + ry = h / 2u + y - height / 2u; + } // proceed with the placed a room on the left - if (i != 0) + if (rx >= 0) L4RoomGen(rx, ry, width, height, true); // proceed with the placed a room on the right - if (ran2) + if (i != 0) L4RoomGen(rxy2, ry, width, height, true); } else { // try to place a room to the top @@ -1403,23 +1419,41 @@ static void L4RoomGen(int x, int y, int w, int h, bool dir) rx = w / 2u + x - width / 2u; ry = y - height; if (L4CheckHHall(y, rx - 1, width + 2) - && L4CheckRoom(rx - 1, ry - 1, width + 2, height + 1)) + && L4CheckRoom(rx - 1, ry - 1, width + 2, height + 1)) { + // - add room to the top + L4DrawRoom(rx, ry, width, height); break; + } } - if (i != 0) - L4DrawRoom(rx, ry, width, height); + if (i != 0) { + // room added to the top -> force similar room on the bottom side + i = 1; + } else { + // room was not added to the top -> try more options on the bottom + ry = -1; + i = 20; + } // try to place a room to the bottom rxy2 = y + h; - ran2 = L4CheckHHall(rxy2 - 1, rx - 1, width + 2) - && L4CheckRoom(rx - 1, rxy2, width + 2, height + 1); - if (ran2) - L4DrawRoom(rx, rxy2, width, height); + while(true) { + if (L4CheckHHall(rxy2 - 1, rx - 1, width + 2) + && L4CheckRoom(rx - 1, rxy2, width + 2, height + 1)) { + // - add room to the bottom + L4DrawRoom(rx, rxy2, width, height); + break; + } + if (--i == 0) + break; + width = RandRange(2, 6) & ~1; + height = RandRange(2, 6) & ~1; + rx = w / 2u + x - width / 2u; + } // proceed with the placed a room on the top - if (i != 0) + if (ry >= 0) L4RoomGen(rx, ry, width, height, false); // proceed with the placed a room on the bottom - if (ran2) + if (i != 0) L4RoomGen(rx, rxy2, width, height, false); } } From 0549d800632dd9d1cfa650d213df1696f06e2c07 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 30 Aug 2024 08:38:43 +0200 Subject: [PATCH 510/596] run CodeQL only once per month --- .github/workflows/code-ql.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/code-ql.yml b/.github/workflows/code-ql.yml index af72de48113..1b5d168d0e5 100644 --- a/.github/workflows/code-ql.yml +++ b/.github/workflows/code-ql.yml @@ -3,7 +3,7 @@ name: Weekly Code Scanning #on: [push, pull_request] on: schedule: - - cron: "0 0 * * 0" # Every Sunday at midnight + - cron: "0 0 1 * *" # First day of the months # For most projects, this workflow file will not need changing; you simply need # to commit it to your repository. From 85d75cb625777b1f6f249c5bf66d10a365c3149b Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 30 Aug 2024 08:40:06 +0200 Subject: [PATCH 511/596] add an empty line to the upstairs in hell to leave space for shadow-tiles --- Source/drlg_l4.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/drlg_l4.cpp b/Source/drlg_l4.cpp index 9e618edae5d..e960e9cc369 100644 --- a/Source/drlg_l4.cpp +++ b/Source/drlg_l4.cpp @@ -52,7 +52,7 @@ const BYTE L4DYNENTRY2[] = { /** Miniset: Stairs up. */ const BYTE L4USTAIRS[] = { // clang-format off - 4, 5, // width, height + 5, 5, // width, height 6, 6, 6, 6, // search 6, 6, 6, 6, @@ -60,11 +60,11 @@ const BYTE L4USTAIRS[] = { 6, 6, 6, 6, 6, 6, 6, 6, - 0, 0, 0, 0, // replace - 36, 38, 35, 0, - 37, 34, 33, 32, - 0, 0, 31, 0, - 0, 0, 0, 0, + 0, 0, 0, 0, 0, // replace + 36, 38, 35, 0, 0, + 37, 34, 33, 32, 0, + 0, 0, 31, 0, 0, + 0, 0, 0, 0, 0, // clang-format on }; /** Miniset: Stairs up to town. */ From 3d75c6605d3092745ac40c7bd80b906e70ae4ff0 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 30 Aug 2024 08:41:56 +0200 Subject: [PATCH 512/596] don't use tile 36 in hell --- Source/drlg_l4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/drlg_l4.cpp b/Source/drlg_l4.cpp index e960e9cc369..0f85747bfbc 100644 --- a/Source/drlg_l4.cpp +++ b/Source/drlg_l4.cpp @@ -61,7 +61,7 @@ const BYTE L4USTAIRS[] = { 6, 6, 6, 6, 0, 0, 0, 0, 0, // replace - 36, 38, 35, 0, 0, + 0, 38, 35, 0, 0, 37, 34, 33, 32, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, From 2dd25e4c2371bdaa01172c49bb014a95eecb087e Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Thu, 29 Aug 2024 16:18:51 +0200 Subject: [PATCH 513/596] Update to latest Android SDK --- android-project/app/build.gradle | 4 ++-- .../org/diasurgical/devilutionx/DataActivity.java | 11 +++++++++++ android-project/build.gradle | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/android-project/app/build.gradle b/android-project/app/build.gradle index 85f2198b39d..a09c4122f66 100644 --- a/android-project/app/build.gradle +++ b/android-project/app/build.gradle @@ -9,7 +9,7 @@ if (buildAsApplication) { android { // ndkVersion '26.1.10909125' - asio is not ready for this ndkVersion '25.2.9519653' - compileSdk 34 + compileSdk 35 aaptOptions { // probably does not matter... noCompress 'mpq' } @@ -21,7 +21,7 @@ android { applicationId "org.diasurgical.devilx" } minSdkVersion 21 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 666 versionName "1.0.0" externalNativeBuild { diff --git a/android-project/app/src/main/java/org/diasurgical/devilutionx/DataActivity.java b/android-project/app/src/main/java/org/diasurgical/devilutionx/DataActivity.java index 7305b7bdb03..326a68ff6fe 100644 --- a/android-project/app/src/main/java/org/diasurgical/devilutionx/DataActivity.java +++ b/android-project/app/src/main/java/org/diasurgical/devilutionx/DataActivity.java @@ -8,6 +8,7 @@ import android.content.IntentFilter; import android.database.Cursor; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; import android.text.method.LinkMovementMethod; @@ -66,6 +67,16 @@ protected void onDestroy() { request.setDestinationInExternalFilesDir(this, null, fileName); + if (mReceiver == null) { + mReceiver = new DownloadReceiver(); + IntentFilter filter = new IntentFilter("android.intent.action.DOWNLOAD_COMPLETE"); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + registerReceiver(mReceiver, filter, Context.RECEIVER_EXPORTED); + } else { + registerReceiver(mReceiver, filter); + } + } + DownloadManager downloadManager = (DownloadManager)this.getSystemService(Context.DOWNLOAD_SERVICE); downloadManager.enqueue(request); diff --git a/android-project/build.gradle b/android-project/build.gradle index 64c2f760a0a..a2f85db185b 100644 --- a/android-project/build.gradle +++ b/android-project/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:8.3.2' + classpath 'com.android.tools.build:gradle:8.5.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files From 959cf04d2c1fd88b6864468aa171d263f0acb683 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 31 Aug 2024 08:21:02 +0200 Subject: [PATCH 514/596] remove invalid comments --- Source/drlg_l4.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Source/drlg_l4.cpp b/Source/drlg_l4.cpp index 0f85747bfbc..ecc3c560701 100644 --- a/Source/drlg_l4.cpp +++ b/Source/drlg_l4.cpp @@ -881,7 +881,6 @@ static void ValidateSEConnection(int x, int y) /* * Draw wall around the tiles selected by L4FirstRoom (and L4ConnectBlock). - * Assumes the border of dungeon was empty. * New dungeon values: 4 .. 29 except 20 */ static void L4TileFix() @@ -1203,7 +1202,6 @@ static void L4Block2Dungeon() /* * Create link between the quarters (blocks) of the dungeon. - * Assumes the border of dungBlock to be empty. */ static void L4ConnectBlock() { @@ -1392,7 +1390,7 @@ static void L4RoomGen(int x, int y, int w, int h, bool dir) } // try to place a room to the right rxy2 = x + w; - while(true) { + while (true) { if (L4CheckVHall(rxy2 - 1, ry - 1, height + 2) && L4CheckRoom(rxy2, ry - 1, width + 1, height + 2)) { // - add room to the right @@ -1436,7 +1434,7 @@ static void L4RoomGen(int x, int y, int w, int h, bool dir) } // try to place a room to the bottom rxy2 = y + h; - while(true) { + while (true) { if (L4CheckHHall(rxy2 - 1, rx - 1, width + 2) && L4CheckRoom(rx - 1, rxy2, width + 2, height + 1)) { // - add room to the bottom From 17c6df94f1d6c326cf2b554540488b218e03018c Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 31 Aug 2024 08:24:30 +0200 Subject: [PATCH 515/596] bugfix for vanilla (block connections in hell) - prevent connections drawn over rooms in hell --- Source/drlg_l4.cpp | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/Source/drlg_l4.cpp b/Source/drlg_l4.cpp index ecc3c560701..f4721ea27e2 100644 --- a/Source/drlg_l4.cpp +++ b/Source/drlg_l4.cpp @@ -1207,23 +1207,19 @@ static void L4ConnectBlock() { int j, i, rv; BYTE hallok[std::max(L4BLOCKX, L4BLOCKY)]; - - memset(hallok, 0, sizeof(hallok)); - for (j = L4BLOCKY - 2; j >= 0; j--) { - for (i = L4BLOCKX - 2; i >= 0; i--) { + // find the right side of the rooms + for (j = L4BLOCKY - 1; j >= 0; j--) { + for (i = L4BLOCKX - 1; i > 0; i--) { if (drlg.dungBlock[i][j] == 1) { - assert(i + 1 < L4BLOCKX && j + 1 < L4BLOCKY); - if (drlg.dungBlock[i][j + 1] == 1 && drlg.dungBlock[i + 1][j + 1] == 0) { - hallok[j] = i; - } - i = 0; + break; } } + hallok[j] = i; } - + // connect to the right side of the dungeon rv = RandRange(1, L4BLOCKY - 1); while (true) { - if (hallok[rv] != 0) { + if (hallok[rv] != 0 && hallok[rv] == hallok[rv + 1]) { for (i = L4BLOCKX - 1; i > hallok[rv]; i--) { drlg.dungBlock[i][rv] = 1; drlg.dungBlock[i][rv + 1] = 1; @@ -1231,28 +1227,25 @@ static void L4ConnectBlock() break; } else { rv++; - if (rv == L4BLOCKY) { + if (rv == L4BLOCKY - 1) { rv = 1; } } } - memset(hallok, 0, sizeof(hallok)); - for (i = L4BLOCKX - 2; i >= 0; i--) { - for (j = L4BLOCKY - 2; j >= 0; j--) { + // find the bottom side of the rooms + for (i = L4BLOCKX - 1; i >= 0; i--) { + for (j = L4BLOCKY - 1; j > 0; j--) { if (drlg.dungBlock[i][j] == 1) { - assert(i + 1 < L4BLOCKX && j + 1 < L4BLOCKY); - if (drlg.dungBlock[i + 1][j] == 1 && drlg.dungBlock[i + 1][j + 1] == 0) { - hallok[i] = j; - } - j = 0; + break; } } + hallok[i] = j; } - + // connect to the bottom side of the dungeon rv = RandRange(1, L4BLOCKX - 1); while (true) { - if (hallok[rv] != 0) { + if (hallok[rv] != 0 && hallok[rv] == hallok[rv + 1]) { for (j = L4BLOCKY - 1; j > hallok[rv]; j--) { drlg.dungBlock[rv][j] = 1; drlg.dungBlock[rv + 1][j] = 1; @@ -1260,7 +1253,7 @@ static void L4ConnectBlock() break; } else { rv++; - if (rv == L4BLOCKX) { + if (rv == L4BLOCKX - 1) { rv = 1; } } From dd0e1b89a01f2c779656963fa11f8d330c5a5426 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 31 Aug 2024 10:33:22 +0200 Subject: [PATCH 516/596] fix bias in L4ConnectBlock --- Source/drlg_l4.cpp | 54 ++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/Source/drlg_l4.cpp b/Source/drlg_l4.cpp index f4721ea27e2..2051f2691b8 100644 --- a/Source/drlg_l4.cpp +++ b/Source/drlg_l4.cpp @@ -1200,6 +1200,22 @@ static void L4Block2Dungeon() } } +static int L4SelectPos(const BYTE (&hall)[20]) +{ + int i, n, rv; + BYTE match[20]; + n = 0; + for (i = 20 - 2; i > 0; i--) { + if (hall[i] != 0 && hall[i] == hall[i + 1]) { + match[n] = i; + n++; + } + } + // assert(n != 0); + rv = random_low(0, n); + return match[rv]; +} + /* * Create link between the quarters (blocks) of the dungeon. */ @@ -1216,21 +1232,12 @@ static void L4ConnectBlock() } hallok[j] = i; } + // select a position with matching 2 tiles-wide ending + rv = L4SelectPos(hallok); // connect to the right side of the dungeon - rv = RandRange(1, L4BLOCKY - 1); - while (true) { - if (hallok[rv] != 0 && hallok[rv] == hallok[rv + 1]) { - for (i = L4BLOCKX - 1; i > hallok[rv]; i--) { - drlg.dungBlock[i][rv] = 1; - drlg.dungBlock[i][rv + 1] = 1; - } - break; - } else { - rv++; - if (rv == L4BLOCKY - 1) { - rv = 1; - } - } + for (i = L4BLOCKX - 1; i > hallok[rv]; i--) { + drlg.dungBlock[i][rv] = 1; + drlg.dungBlock[i][rv + 1] = 1; } // find the bottom side of the rooms @@ -1242,21 +1249,12 @@ static void L4ConnectBlock() } hallok[i] = j; } + // select a position with matching 2 tiles-wide ending + rv = L4SelectPos(hallok); // connect to the bottom side of the dungeon - rv = RandRange(1, L4BLOCKX - 1); - while (true) { - if (hallok[rv] != 0 && hallok[rv] == hallok[rv + 1]) { - for (j = L4BLOCKY - 1; j > hallok[rv]; j--) { - drlg.dungBlock[rv][j] = 1; - drlg.dungBlock[rv + 1][j] = 1; - } - break; - } else { - rv++; - if (rv == L4BLOCKX - 1) { - rv = 1; - } - } + for (j = L4BLOCKY - 1; j > hallok[rv]; j--) { + drlg.dungBlock[rv][j] = 1; + drlg.dungBlock[rv + 1][j] = 1; } } From 70b503d09fc4909c031b80467c060dc9f589f404 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 31 Aug 2024 13:04:51 +0200 Subject: [PATCH 517/596] adjust the logic to connect the blocks in hell - prevent connection from the furthermost tile (prevents double/quadrupled halls) - allow connection from the first tile (does not make much difference) --- Source/drlg_l4.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/drlg_l4.cpp b/Source/drlg_l4.cpp index 2051f2691b8..b09bc8e847f 100644 --- a/Source/drlg_l4.cpp +++ b/Source/drlg_l4.cpp @@ -1205,7 +1205,7 @@ static int L4SelectPos(const BYTE (&hall)[20]) int i, n, rv; BYTE match[20]; n = 0; - for (i = 20 - 2; i > 0; i--) { + for (i = 20 - 3; i >= 0; i--) { if (hall[i] != 0 && hall[i] == hall[i + 1]) { match[n] = i; n++; From f230ef7f1995a96c6085893abd187c1b837d0e97 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 31 Aug 2024 13:06:36 +0200 Subject: [PATCH 518/596] add the area of the connections when the dungeon is built in hell --- Source/drlg_l4.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/drlg_l4.cpp b/Source/drlg_l4.cpp index b09bc8e847f..7b27500ff04 100644 --- a/Source/drlg_l4.cpp +++ b/Source/drlg_l4.cpp @@ -2024,8 +2024,8 @@ static void DRLG_L4() //static_assert(sizeof(dungeon) == DMAXX * DMAXY, "Linear traverse of dungeon does not work in DRLG_L4."); //memset(dungeon, 30, sizeof(dungeon)); L4FirstRoom(); - } while (DRLG_L4GetArea() < 173); - L4ConnectBlock(); + L4ConnectBlock(); + } while (DRLG_L4GetArea() < 190); L4Block2Dungeon(); DRLG_L4MakeMegas(); From 40086dd413fc2f9a6fb384666a2149f7998c6711 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 31 Aug 2024 13:08:49 +0200 Subject: [PATCH 519/596] cosmetic adjustments (SaveItemPower) --- Source/items.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/Source/items.cpp b/Source/items.cpp index 18fb3dfd074..35efb7c1985 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -1502,19 +1502,16 @@ static void SaveItemPower(int ii, int power, int param1, int param2, int minval, break; case IPL_DUR: r2 = r * is->_iMaxDur / 100; - is->_iMaxDur += r2; - is->_iDurability += r2; + is->_iDurability = is->_iMaxDur = is->_iMaxDur + r2; break; case IPL_CRYSTALLINE: is->_iPLDam = r * 2; // no break case IPL_DUR_CURSE: - is->_iMaxDur = r < 100 ? (is->_iMaxDur - r * is->_iMaxDur / 100) : 1; - is->_iDurability = is->_iMaxDur; + is->_iDurability = is->_iMaxDur = r < 100 ? (is->_iMaxDur - r * is->_iMaxDur / 100) : 1; break; case IPL_INDESTRUCTIBLE: - is->_iDurability = DUR_INDESTRUCTIBLE; - is->_iMaxDur = DUR_INDESTRUCTIBLE; + is->_iDurability = is->_iMaxDur = DUR_INDESTRUCTIBLE; break; case IPL_LIGHT: is->_iPLLight = r; @@ -1578,8 +1575,7 @@ static void SaveItemPower(int ii, int power, int param1, int param2, int minval, is->_iMaxDam = param2; break; case IPL_SETDUR: - is->_iDurability = r; - is->_iMaxDur = r; + is->_iDurability = is->_iMaxDur = r; break; case IPL_NOMINSTR: is->_iMinStr = 0; From e65e98ce38e2909d4f226fd44cbd4c0cda0681e5 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 31 Aug 2024 13:10:13 +0200 Subject: [PATCH 520/596] use the same description for IPL_SETDUR/IPL_DUR/IPL_DUR_CURSE --- Source/items.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Source/items.cpp b/Source/items.cpp index 35efb7c1985..c71d780e2a9 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -2912,10 +2912,9 @@ static void PrintEquipmentPower(BYTE plidx, const ItemStruct* is) snprintf(tempstr, sizeof(tempstr), "mana: %+d", is->_iPLMana >> 6); break; case IPL_DUR: - copy_cstr(tempstr, "high durability"); - break; case IPL_DUR_CURSE: - copy_cstr(tempstr, "decreased durability"); + case IPL_SETDUR: + copy_cstr(tempstr, "altered durability"); break; case IPL_INDESTRUCTIBLE: copy_cstr(tempstr, "indestructible"); @@ -2983,9 +2982,6 @@ static void PrintEquipmentPower(BYTE plidx, const ItemStruct* is) case IPL_SETDAM: copy_cstr(tempstr, "unusual item damage"); break; - case IPL_SETDUR: - copy_cstr(tempstr, "altered durability"); - break; case IPL_NOMINSTR: copy_cstr(tempstr, "no strength requirement"); break; From 19bb705f33b5ffc261c70cc7edcd6f70ed736dfa Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 31 Aug 2024 13:12:23 +0200 Subject: [PATCH 521/596] ensure CrawlTable/CrawlNum have enough entries --- Source/lighting.cpp | 2 ++ Source/missiles.cpp | 29 +++++++++++++++++++++++------ Source/monster.cpp | 1 + Source/objects.cpp | 5 +++-- Source/player.cpp | 5 +++-- 5 files changed, 32 insertions(+), 10 deletions(-) diff --git a/Source/lighting.cpp b/Source/lighting.cpp index 516c9e2887d..78492d14078 100644 --- a/Source/lighting.cpp +++ b/Source/lighting.cpp @@ -668,6 +668,7 @@ void TraceLightSource(int nXPos, int nYPos, int nRadius) nRadius = 2 * (nRadius + 1) * 8 * 16; static_assert(INT_MAX / (2 * 8 * 16) > MAX_LIGHT_RAD, "Light tracing overflows in TraceLightSource."); static_assert(MAX_OFFSET == 8, "Light tracing shift must be adjusted in TraceLightSource."); + static_assert(lengthof(CrawlNum) > 15, "TraceLightSource uses CrawlTable/CrawlNum up to radius 15."); cr = &CrawlTable[CrawlNum[15]]; for (i = (BYTE)*cr; i > 0; i--) { x1 = nXPos; @@ -798,6 +799,7 @@ void DoVision(int nXPos, int nYPos, int nRadius, bool local) } } nRadius = 2 * (nRadius + 1); + static_assert(lengthof(CrawlNum) > 15, "DoVision uses CrawlTable/CrawlNum up to radius 15."); cr = &CrawlTable[CrawlNum[15]]; for (i = (BYTE)*cr; i > 0; i--) { x1 = nXPos; diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 7c80a226ca6..a1bf959452f 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -265,6 +265,7 @@ static bool FindClosest(int sx, int sy, int& dx, int& dy) mid = mid >= 0 ? mid - 1 : -(mid + 1); static_assert(DBORDERX >= 15 && DBORDERY >= 15, "FindClosest expects a large enough border."); + static_assert(lengthof(CrawlNum) > 15, "FindClosest uses CrawlTable/CrawlNum up to radius 16."); for (i = 1; i <= 15; i++) { cr = &CrawlTable[CrawlNum[i]]; for (j = (BYTE)*cr; j > 0; j--) { @@ -299,6 +300,7 @@ static bool FindClosestChain(int sx, int sy, int& dx, int& dy) mid = mid >= 0 ? mid - 1 : -(mid + 1); static_assert(DBORDERX >= 7 && DBORDERY >= 7, "FindClosestChain expects a large enough border."); + static_assert(lengthof(CrawlNum) > 7, "FindClosestChain uses CrawlTable/CrawlNum up to radius 7."); for (i = 1; i <= 7; i++) { cr = &CrawlTable[CrawlNum[i]]; for (j = (BYTE)*cr; j > 0; j--) { @@ -1591,6 +1593,7 @@ static int PlaceRune(int mi, int sx, int sy, int dx, int dy, int mitype, int mir } mis->_miRange = 16 + 1584; // delay + ttl static_assert(DBORDERX >= 9 && DBORDERY >= 9, "PlaceRune expects a large enough border."); + static_assert(lengthof(CrawlNum) > 9, "PlaceRune uses CrawlTable/CrawlNum up to radius 9."); for (i = 0; i <= 9; i++) { cr = &CrawlTable[CrawlNum[i]]; for (j = *cr; j > 0; j--) { @@ -1616,7 +1619,7 @@ static int PlaceRune(int mi, int sx, int sy, int dx, int dy, int mitype, int mir */ int AddFireRune(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { - return PlaceRune(mi, sx, sy, dx, dy, MIS_FIREEXP, 0); + return PlaceRune(mi, sx, sy, dx, dy, MIS_FIREEXP, 0); // RUNE_RANGE } /** @@ -1627,7 +1630,7 @@ int AddFireRune(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int AddLightRune(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { static_assert(DBORDERX >= 1 && DBORDERY >= 1, "AddLightRune expects a large enough border."); - return PlaceRune(mi, sx, sy, dx, dy, MIS_LIGHTNINGC, 1); + return PlaceRune(mi, sx, sy, dx, dy, MIS_LIGHTNINGC, 1); // RUNE_RANGE } /** @@ -1638,7 +1641,7 @@ int AddLightRune(int mi, int sx, int sy, int dx, int dy, int midir, int micaster int AddNovaRune(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { static_assert(DBORDERX >= 1 && DBORDERY >= 1, "AddNovaRune expects a large enough border."); - return PlaceRune(mi, sx, sy, dx, dy, MIS_LIGHTNOVAC, 1); + return PlaceRune(mi, sx, sy, dx, dy, MIS_LIGHTNOVAC, 1); // RUNE_RANGE } /** @@ -1649,7 +1652,7 @@ int AddNovaRune(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int AddWaveRune(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { static_assert(DBORDERX >= 1 && DBORDERY >= 1, "AddWaveRune expects a large enough border."); - return PlaceRune(mi, sx, sy, dx, dy, MIS_FIREWAVEC, 1); + return PlaceRune(mi, sx, sy, dx, dy, MIS_FIREWAVEC, 1); // RUNE_RANGE } /** @@ -1659,7 +1662,7 @@ int AddWaveRune(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, */ int AddStoneRune(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { - return PlaceRune(mi, sx, sy, dx, dy, MIS_STONE, 0); + return PlaceRune(mi, sx, sy, dx, dy, MIS_STONE, 0); // RUNE_RANGE } int AddHorkSpawn(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) @@ -1751,6 +1754,7 @@ int AddRingC(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in mitype = MIS_FIREWALL; //mis->_miType == MIS_FIRERING ? MIS_FIREWALL : MIS_LIGHTWALL; static_assert(DBORDERX >= 3 && DBORDERY >= 3, "AddRingC expects a large enough border."); + static_assert(lengthof(CrawlNum) > 3, "AddRingC uses CrawlTable/CrawlNum radius 3."); cr = &CrawlTable[CrawlNum[3]]; for (j = *cr; j > 0; j--) { tx = sx + *++cr; @@ -2095,6 +2099,7 @@ int AddTeleport(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, } static_assert(DBORDERX >= 5 && DBORDERY >= 5, "AddTeleport expects a large enough border."); + static_assert(lengthof(CrawlNum) > 5, "AddTeleport uses CrawlTable/CrawlNum up to radius 5."); for (i = 0; i <= 5; i++) { cr = &CrawlTable[CrawlNum[i]]; for (j = (BYTE)*cr; j > 0; j--) { @@ -2351,6 +2356,7 @@ int AddShroud(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, i mis = &missile[mi]; static_assert(DBORDERX >= 5 && DBORDERY >= 5, "AddShroud expects a large enough border."); + static_assert(lengthof(CrawlNum) > 5, "AddShroud uses CrawlTable/CrawlNum up to radius 5."); for (i = 0; i <= 5; i++) { cr = &CrawlTable[CrawlNum[i]]; for (j = (BYTE)*cr; j > 0; j--) { @@ -2418,6 +2424,7 @@ int AddTown(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int if (currLvl._dType != DTYPE_TOWN && spllvl >= 0) { const int RANGE = 6; static_assert(DBORDERX >= RANGE - 1 && DBORDERY >= RANGE - 1, "AddTown expects a large enough border."); + static_assert(lengthof(CrawlNum) >= RANGE, "AddShroud uses CrawlTable/CrawlNum up to radius 5."); for (i = 0; i < RANGE; i++) { cr = &CrawlTable[CrawlNum[i]]; for (j = (BYTE)*cr; j > 0; j--) { @@ -2550,6 +2557,7 @@ int AddMeteor(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, i mis->_miMaxDam = maxdam << 6; static_assert(DBORDERX >= 5 && DBORDERY >= 5, "AddMeteor expects a large enough border."); + static_assert(lengthof(CrawlNum) > 5, "AddMeteor uses CrawlTable/CrawlNum up to radius 5."); for (i = 0; i <= 5; i++) { cr = &CrawlTable[CrawlNum[i]]; for (j = (BYTE)*cr; j > 0; j--) { @@ -2747,6 +2755,7 @@ int AddStone(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in // assert((unsigned)misource < MAX_PLRS); mis = &missile[mi]; static_assert(DBORDERX >= 2 && DBORDERY >= 2, "AddStone expects a large enough border."); + static_assert(lengthof(CrawlNum) > 2, "AddStone uses CrawlTable/CrawlNum up to radius 2."); for (i = 0; i <= 2; i++) { cr = &CrawlTable[CrawlNum[i]]; for (j = (BYTE)*cr; j > 0; j--) { @@ -2801,6 +2810,7 @@ int AddGuardian(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, mis = &missile[mi]; static_assert(DBORDERX >= 5 && DBORDERY >= 5, "AddGuardian expects a large enough border."); + static_assert(lengthof(CrawlNum) > 5, "AddGuardian uses CrawlTable/CrawlNum up to radius 5."); for (i = 0; i <= 5; i++) { cr = &CrawlTable[CrawlNum[i]]; for (j = (BYTE)*cr; j > 0; j--) { @@ -2833,6 +2843,7 @@ int AddGolem(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in mon = &monsters[misource]; if (mon->_mmode > MM_INGAME_LAST) { static_assert(DBORDERX >= 5 && DBORDERY >= 5, "AddGolem expects a large enough border."); + static_assert(lengthof(CrawlNum) > 5, "AddGolem uses CrawlTable/CrawlNum up to radius 5."); for (i = 0; i <= 5; i++) { cr = &CrawlTable[CrawlNum[i]]; for (j = (BYTE)*cr; j > 0; j--) { @@ -2997,6 +3008,7 @@ int AddWallC(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in // (micaster & MST_PLAYER); // ((unsigned)misource < MAX_PLRS); static_assert(DBORDERX >= 5 && DBORDERY >= 5, "AddWallC expects a large enough border."); + static_assert(lengthof(CrawlNum) > 5, "AddWallC uses CrawlTable/CrawlNum up to radius 5."); mis = &missile[mi]; for (i = 0; i <= 5; i++) { cr = &CrawlTable[CrawlNum[i]]; @@ -3059,6 +3071,7 @@ int AddNovaC(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in const int8_t* cr; // ((micaster & MST_PLAYER) || micaster == MST_OBJECT); static_assert(DBORDERX >= 3 && DBORDERY >= 3, "AddNovaC expects a large enough border."); + static_assert(lengthof(CrawlNum) > 3, "AddNovaC uses CrawlTable/CrawlNum radius 3."); cr = &CrawlTable[CrawlNum[3]]; for (i = *cr; i > 0; i--) { tx = sx + *++cr; @@ -3253,6 +3266,7 @@ int AddAttract(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, dist = 4 + (spllvl >> 2); static_assert(DBORDERX >= 9 && DBORDERY >= 9, "AddAttract expects a large enough border."); + static_assert(lengthof(CrawlNum) > 9, "AddAttract uses CrawlTable/CrawlNum up to radius 9."); if (dist > 9) dist = 9; for (i = 0; i <= dist; i++) { @@ -3951,6 +3965,7 @@ void MI_HorkSpawn(int mi) // assert(abs(mis->_mix - mis->_misx) <= 1 && abs(mis->_miy - mis->_misy) <= 1); mis->_miDelFlag = TRUE; static_assert(DBORDERX >= 1 && DBORDERY >= 1, "MI_HorkSpawn expects a large enough border."); + static_assert(lengthof(CrawlNum) > 1, "MI_HorkSpawn uses CrawlTable/CrawlNum up to radius 1."); for (i = 0; i <= 1; i++) { cr = &CrawlTable[CrawlNum[i]]; for (j = *cr; j > 0; j--) { @@ -3981,7 +3996,8 @@ void MI_Rune(int mi) if (--mis->_miVar3 < 0) { sx = mis->_mix; sy = mis->_miy; - cr = &CrawlTable[CrawlNum[mis->_miVar2]]; + static_assert(lengthof(CrawlNum) > 1, "MI_Rune uses CrawlTable/CrawlNum up to radius 1."); + cr = &CrawlTable[CrawlNum[mis->_miVar2]]; // RUNE_RANGE for (j = *cr; j > 0; j--) { tx = sx + *++cr; ty = sy + *++cr; @@ -4392,6 +4408,7 @@ void MI_Guardian(int mi) if (mis->_miRange >= 0) { ex = false; static_assert(DBORDERX >= 6 && DBORDERY >= 6, "MI_Guardian expects a large enough border."); + static_assert(lengthof(CrawlNum) > 6, "MI_Guardian uses CrawlTable/CrawlNum up to radius 6."); for (i = 6; i >= 0 && !ex; i--) { cr = &CrawlTable[CrawlNum[i]]; for (j = *cr; j > 0; j--) { diff --git a/Source/monster.cpp b/Source/monster.cpp index c005e3757cc..82d5704e70d 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3612,6 +3612,7 @@ void MAI_Scav(int mnum) static_assert(DBORDERY >= 4, "MAI_Scav expects a large enough border II."); static_assert(MAXDUNX < UCHAR_MAX, "MAI_Scav stores dungeon coordinates in BYTE field I."); static_assert(MAXDUNY < UCHAR_MAX, "MAI_Scav stores dungeon coordinates in BYTE field II."); + static_assert(lengthof(CrawlNum) > 4, "MAI_Scav uses CrawlTable/CrawlNum up to radius 4."); assert(CrawlTable[CrawlNum[4]] == 32); BYTE corpseLocs[32 * 2]; tmp = 0; diff --git a/Source/objects.cpp b/Source/objects.cpp index 088a3482c6b..e8fad58ee99 100644 --- a/Source/objects.cpp +++ b/Source/objects.cpp @@ -1425,8 +1425,8 @@ static void FindClosestPlr(int* dx, int* dy) { int xx, yy, j, i; const int8_t* cr; - - for (i = 0; i < 10; i++) { + static_assert(lengthof(CrawlNum) > 9, "FindClosestPlr uses CrawlTable/CrawlNum up to radius 9."); + for (i = 0; i <= 9; i++) { cr = &CrawlTable[CrawlNum[i]]; for (j = *cr; j > 0; j--) { xx = *dx + *++cr; @@ -2795,6 +2795,7 @@ static void OperateShrine(int pnum, int oi, bool sendmsg) static_assert(MIS_RUNEFIRE + 2 == MIS_RUNENOVA, "SHRINE_SOLAR expects runes in a given order II."); static_assert(MIS_RUNEFIRE + 3 == MIS_RUNEWAVE, "SHRINE_SOLAR expects runes in a given order III."); static_assert(DBORDERX >= 3 && DBORDERY >= 3, "SHRINE_SOLAR expects a large enough border."); + static_assert(lengthof(CrawlNum) > 3, "OperateShrine uses CrawlTable/CrawlNum radius 3."); const int8_t* cr = &CrawlTable[CrawlNum[3]]; mode = sendmsg ? ICM_SEND : ICM_DUMMY; for (i = (BYTE)*cr; i > 0; i--) { diff --git a/Source/player.cpp b/Source/player.cpp index 6362f50ebe3..b22b8634db5 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -749,8 +749,9 @@ static void PlacePlayer(int pnum) return; if (i == lengthof(plrxoff2)) { - static_assert(DBORDERX >= 16 && DBORDERY >= 16, "PlacePlayer expects a large enough border."); - for (i = 2; i < 16; i++) { + static_assert(DBORDERX >= 15 && DBORDERY >= 15, "PlacePlayer expects a large enough border."); + static_assert(lengthof(CrawlNum) > 15, "PlacePlayer uses CrawlTable/CrawlNum up to radius 16."); + for (i = 2; i <= 15; i++) { cr = &CrawlTable[CrawlNum[i]]; for (j = (BYTE)*cr; j > 0; j--) { nx = plr._px + *++cr; From d5e4c2bcf8af2f54e4f12964cd72bfbeffc2e116 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 31 Aug 2024 22:52:01 +0200 Subject: [PATCH 522/596] get rid of the (incorrect) avx2-converters --- 3rdParty/SDL2_mixer/src/utils.c | 64 --------------------------------- 1 file changed, 64 deletions(-) diff --git a/3rdParty/SDL2_mixer/src/utils.c b/3rdParty/SDL2_mixer/src/utils.c index 372fddf4f2b..0ba574dab4c 100644 --- a/3rdParty/SDL2_mixer/src/utils.c +++ b/3rdParty/SDL2_mixer/src/utils.c @@ -322,36 +322,6 @@ static void SDL_TARGETING("avx2") Mix_Mixer_AUDIOS16_AVX2(void* dst, const void* #endif // FULL - SELF_MIX #ifndef FULL // SELF_CONV -#ifdef SDL_AVX2_INTRINSICS -static void SDL_TARGETING("avx2") Mix_Converter_AUDIO16_Mono2Stereo_AVX2(Mix_BuffOps* buf) -{ - Sint16* srcPos = (Sint16*)buf->endPos; - Sint16* currPos = (Sint16*)buf->currPos; - - Sint16* dstPos = srcPos + (srcPos - currPos); - buf->endPos = dstPos; - - while (&currPos[16] <= srcPos) { - srcPos -= 16; - dstPos -= 16; - __m256i aa = _mm256_loadu_si256((const __m256i*)srcPos); - __m256i bb = _mm256_unpackhi_epi16(aa, aa); - _mm256_storeu_si256((__m256i*)dstPos, bb); - - dstPos -= 16; - __m256i cc = _mm256_unpacklo_epi16(aa, aa); - _mm256_storeu_si256((__m256i*)dstPos, cc); - } - - while (srcPos != currPos) { - srcPos--; - dstPos--; - *dstPos = *srcPos; - dstPos--; - *dstPos = *srcPos; - } -} -#endif // SDL_AVX2_INTRINSICS #ifdef SDL_SSE2_INTRINSICS static void SDL_TARGETING("sse2") Mix_Converter_AUDIO16_Mono2Stereo_SSE2(Mix_BuffOps* buf) { @@ -502,38 +472,6 @@ static void Mix_Converter_AUDIO16_Resample_Half(Mix_BuffOps* buf) } } -#ifdef SDL_AVX2_INTRINSICS -static void SDL_TARGETING("avx2") Mix_Converter_U8_S16LSB_AVX2(Mix_BuffOps* buf) -{ - Uint8* srcPos = (Uint8*)buf->endPos; - Uint8* currPos = (Uint8*)buf->currPos; - - Uint8* dstPos = srcPos + (srcPos - currPos); - buf->endPos = dstPos; - - const __m256i zero = _mm256_setzero_si256(); - const __m256i sign = _mm256_set1_epi8(0x80); - - while (&currPos[32] <= srcPos) { - srcPos -= 32; - dstPos -= 64; - - const __m256i src00 = _mm256_loadu_si256((__m256i const *)&srcPos[0]); /* get 32 uint8 into an XMM register. */ - const __m256i value = _mm256_xor_si256(sign, src00); /* 'convert' to int8 */ - const __m256i src0 = _mm256_unpacklo_epi8(zero, value); - const __m256i src1 = _mm256_unpackhi_epi8(zero, value); - - _mm256_storeu_si256((__m256i*)&dstPos[0], src0); - _mm256_storeu_si256((__m256i*)&dstPos[32], src1); - } - - while (srcPos != currPos) { - srcPos--; - dstPos -= 2; - *(Sint16*)dstPos = SDL_SwapLE16((Sint8)(srcPos[0] ^ 0x80) << 8); - } -} -#endif // SDL_AVX2_INTRINSICS #ifdef SDL_SSE2_INTRINSICS static void SDL_TARGETING("sse2") Mix_Converter_U8_S16LSB_SSE2(Mix_BuffOps* buf) { @@ -606,9 +544,7 @@ void Mix_Utils_Init() #endif #if defined(SDL_AVX2_INTRINSICS) && SDL_VERSION_ATLEAST(2, 0, 2) if (SDL_HasAVX2()) { - Mix_Convert_AUDIO16_Mono2Stereo = Mix_Converter_AUDIO16_Mono2Stereo_AVX2; Mix_MixAudioFormat = Mix_Mixer_AUDIOS16_AVX2; - Mix_Convert_U8_S16LSB = Mix_Converter_U8_S16LSB_AVX2; } #endif } From 912399eb222f2dd0515c2dc1c0ac27bdac1beb13 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 1 Sep 2024 12:46:33 +0200 Subject: [PATCH 523/596] fix the handling of the (audio-) volume (SSE2/AVX) --- 3rdParty/SDL2_mixer/src/effect_position.c | 163 +++++++++++++++------- 1 file changed, 116 insertions(+), 47 deletions(-) diff --git a/3rdParty/SDL2_mixer/src/effect_position.c b/3rdParty/SDL2_mixer/src/effect_position.c index fbffe04ce6e..bebfbb5fff0 100644 --- a/3rdParty/SDL2_mixer/src/effect_position.c +++ b/3rdParty/SDL2_mixer/src/effect_position.c @@ -743,7 +743,7 @@ static void SDLCALL _Eff_position_u16lsb_c6(int chan, void *stream, int len, voi #ifdef FULL // FIX_EFF static void SDLCALL _Eff_position_s16lsb(int chan, void *stream, int len, void *udata) #else -//static_assert(SDL_MAX_SINT16 * MIX_MAX_POS_EFFECT * MIX_MAX_VOLUME <= SDL_MAX_SINT32, "Volume might overflow when the effects are calculated."); +SDL_COMPILE_TIME_ASSERT(_Eff_position_s16lsb_MIX_MAX_VOLUME, SDL_MAX_SINT16 * MIX_MAX_POS_EFFECT * MIX_MAX_VOLUME <= SDL_MAX_SINT32); #define ADJUST_SIDE_VOLUME(s, v) (s = (s*v)/(MIX_MAX_VOLUME * MIX_MAX_POS_EFFECT)) static SDL_bool _Eff_position_s16lsb(void* stream, unsigned len, void* udata) #endif @@ -765,9 +765,10 @@ static SDL_bool _Eff_position_s16lsb(void* stream, unsigned len, void* udata) //if (left_f < 1.0f / SDL_MAX_SINT16 && right_f < 1.0f / SDL_MAX_SINT16) // return SDL_FALSE; int voll, volr; - const int left = channel->effect.left_vol * channel->volume; - const int right = channel->effect.right_vol * channel->volume; - if (left == 0 && right == 0) + const int volume = ((Mix_Channel*)udata)->volume; + const int left = channel->effect.left_vol * volume; + const int right = channel->effect.right_vol * volume; + if (volume == 0) return SDL_FALSE; #endif #if 0 @@ -823,26 +824,43 @@ static SDL_bool SDL_TARGETING("sse2") _Eff_position_s16lsb_SSE2(void* stream, un /* 16 signed bits (lsb) * 2 channels. */ Sint16* ptr = (Sint16*)stream; Mix_Channel* channel = (Mix_Channel*)udata; - int left = channel->effect.left_vol * channel->volume; - int right = channel->effect.right_vol * channel->volume; - if (left == 0 && right == 0) + const int volume = ((Mix_Channel*)udata)->volume; + int left = channel->effect.left_vol * volume; + int right = channel->effect.right_vol * volume; + if (volume == 0) return SDL_FALSE; - //static_assert((MIX_MAX_VOLUME & (MIX_MAX_VOLUME - 1)) == 0, "_Eff_position_s16lsb_SSE2 expects MIX_MAX_VOLUME to be a power of 2."); - //static_assert((MIX_MAX_POS_EFFECT & (MIX_MAX_POS_EFFECT - 1)) == 0, "_Eff_position_s16lsb_SSE2 expects MIX_MAX_POS_EFFECT to be a power of 2."); - //static_assert((MIX_MAX_VOLUME * MIX_MAX_POS_EFFECT) <= (1 << 16), "_Eff_position_s16lsb_SSE2 expects MIX_MAX_VOLUME to be low."); - left *= (1 << 16) / (MIX_MAX_VOLUME * MIX_MAX_POS_EFFECT); - right *= (1 << 16) / (MIX_MAX_VOLUME * MIX_MAX_POS_EFFECT); - - __m128i ma = _mm_set1_epi16(left); - __m128i mb = _mm_set1_epi16(right); - __m128i mm = _mm_unpacklo_epi16(ma, mb); +#if 1 + SDL_INLINE_COMPILE_TIME_ASSERT(_Eff_position_s16lsb_SSE2_MIX_MAX_VOLUME, (MIX_MAX_VOLUME & (MIX_MAX_VOLUME - 1)) == 0); + SDL_INLINE_COMPILE_TIME_ASSERT(_Eff_position_s16lsb_SSE2_MIX_MAX_POS_EFFECT, (MIX_MAX_POS_EFFECT & (MIX_MAX_POS_EFFECT - 1)) == 0); + SDL_INLINE_COMPILE_TIME_ASSERT(_Eff_position_s16lsb_SSE2_low, (MIX_MAX_VOLUME * MIX_MAX_POS_EFFECT) <= (1 << 15)); + left *= (1 << 15) / (MIX_MAX_VOLUME * MIX_MAX_POS_EFFECT); + right *= (1 << 15) / (MIX_MAX_VOLUME * MIX_MAX_POS_EFFECT); + if ((int16_t)left < 0) { + left = INT16_MAX; + } + if ((int16_t)right < 0) { + right = INT16_MAX; + } +#endif + __m128i mm = _mm_set1_epi32(left | (right << 16)); while (len >= 16) { len -= 16; __m128i aa = _mm_loadu_si128((const __m128i*)ptr); - __m128i bb = _mm_mulhi_epi16(aa, mm); - _mm_storeu_si128((__m128i*)ptr, bb); +#if 1 + __m128i sm = _mm_mulhi_epi16(aa, mm); + __m128i cc = _mm_slli_epi16(sm, 1); +#else + __m128i lo = _mm_mullo_epi16(aa, mm); + __m128i hi = _mm_mulhi_epi16(aa, mm); + __m128i c0 = _mm_unpacklo_epi16(lo, hi); + __m128i c1 = _mm_unpackhi_epi16(lo, hi); + __m128i d0 = _mm_srai_epi32(c0, 10 + 4); + __m128i d1 = _mm_srai_epi32(c1, 10 + 4); + __m128i cc = _mm_packs_epi32(d0, d1); +#endif + _mm_storeu_si128((__m128i*)ptr, cc); ptr += 8; } @@ -858,26 +876,47 @@ static SDL_bool SDL_TARGETING("avx2") _Eff_position_s16lsb_AVX2(void* stream, un /* 16 signed bits (lsb) * 2 channels. */ Sint16* ptr = (Sint16*)stream; Mix_Channel* channel = (Mix_Channel*)udata; - int left = channel->effect.left_vol * channel->volume; - int right = channel->effect.right_vol * channel->volume; - if (left == 0 && right == 0) + const int volume = ((Mix_Channel*)udata)->volume; + int left = channel->effect.left_vol * volume; + int right = channel->effect.right_vol * volume; + if (volume == 0) return SDL_FALSE; - //static_assert((MIX_MAX_VOLUME & (MIX_MAX_VOLUME - 1)) == 0, "_Eff_position_s16lsb_AVX2 expects MIX_MAX_VOLUME to be a power of 2."); - //static_assert((MIX_MAX_POS_EFFECT & (MIX_MAX_POS_EFFECT - 1)) == 0, "_Eff_position_s16lsb_AVX2 expects MIX_MAX_POS_EFFECT to be a power of 2."); - //static_assert((MIX_MAX_VOLUME * MIX_MAX_POS_EFFECT) <= (1 << 16), "_Eff_position_s16lsb_AVX2 expects MIX_MAX_VOLUME to be low."); - left *= (1 << 16) / (MIX_MAX_VOLUME * MIX_MAX_POS_EFFECT); - right *= (1 << 16) / (MIX_MAX_VOLUME * MIX_MAX_POS_EFFECT); +#if 1 + SDL_INLINE_COMPILE_TIME_ASSERT(_Eff_position_s16lsb_AVX2_MIX_MAX_VOLUME, (MIX_MAX_VOLUME & (MIX_MAX_VOLUME - 1)) == 0); + SDL_INLINE_COMPILE_TIME_ASSERT(_Eff_position_s16lsb_AVX2_MIX_MAX_POS_EFFECT, (MIX_MAX_POS_EFFECT & (MIX_MAX_POS_EFFECT - 1)) == 0); + SDL_INLINE_COMPILE_TIME_ASSERT(_Eff_position_s16lsb_AVX2_low, (MIX_MAX_VOLUME * MIX_MAX_POS_EFFECT) <= (1 << 15)); + left *= (1 << 15) / (MIX_MAX_VOLUME * MIX_MAX_POS_EFFECT); + right *= (1 << 15) / (MIX_MAX_VOLUME * MIX_MAX_POS_EFFECT); + if ((int16_t)left < 0) { + left = INT16_MAX; + } + if ((int16_t)right < 0) { + right = INT16_MAX; + } +#else + SDL_INLINE_COMPILE_TIME_ASSERT(_Eff_position_s16lsb_AVX2_MIX_MAX_VOLUME, MIX_MAX_VOLUME == (1 << 10)); + SDL_INLINE_COMPILE_TIME_ASSERT(_Eff_position_s16lsb_AVX2_MIX_MAX_POS_EFFECT, MIX_MAX_POS_EFFECT == (1 << 4)); +#endif - __m256i ma = _mm256_set1_epi16(left); - __m256i mb = _mm256_set1_epi16(right); - __m256i mm = _mm256_unpacklo_epi16(ma, mb); + __m256i mm = _mm256_set1_epi32(left | (right << 16)); while (len >= 32) { len -= 32; __m256i aa = _mm256_loadu_si256((const __m256i*)ptr); - __m256i bb = _mm256_mulhi_epi16(aa, mm); - _mm256_storeu_si256((__m256i*)ptr, bb); +#if 1 + __m256i sm = _mm256_mulhi_epi16(aa, mm); + __m256i cc = _mm256_slli_epi16(sm, 1); +#else + __m256i lo = _mm256_mullo_epi16(aa, mm); + __m256i hi = _mm256_mulhi_epi16(aa, mm); + __m256i c0 = _mm256_unpacklo_epi16(lo, hi); + __m256i c1 = _mm256_unpackhi_epi16(lo, hi); + __m256i d0 = _mm256_srai_epi32(c0, 10 + 4); + __m256i d1 = _mm256_srai_epi32(c1, 10 + 4); + __m256i cc = _mm256_packs_epi32(d0, d1); +#endif + _mm256_storeu_si256((__m256i*)ptr, cc); ptr += 16; } @@ -917,21 +956,36 @@ static SDL_bool SDL_TARGETING("sse2") _Eff_volume_s16lbs_SSE2(void* stream, unsi if (volume == MIX_MAX_VOLUME) return SDL_TRUE; - //static_assert((MIX_MAX_VOLUME & (MIX_MAX_VOLUME - 1)) == 0, "_Eff_volume_s16lbs_SSE2 expects MIX_MAX_VOLUME to be a power of 2."); - //static_assert(MIX_MAX_VOLUME <= (1 << 16), "_Eff_volume_s16lbs_SSE2 expects MIX_MAX_VOLUME to be low."); - volume *= (1 << 16) / MIX_MAX_VOLUME; - +#if 1 + SDL_INLINE_COMPILE_TIME_ASSERT(_Eff_volume_s16lbs_SSE2_MIX_MAX_VOLUME, (MIX_MAX_VOLUME & (MIX_MAX_VOLUME - 1)) == 0); + SDL_INLINE_COMPILE_TIME_ASSERT(_Eff_volume_s16lbs_SSE2_low, MIX_MAX_VOLUME <= (1 << 15)); + volume *= (1 << 15) / MIX_MAX_VOLUME; +#else + SDL_INLINE_COMPILE_TIME_ASSERT(_Eff_volume_s16lbs_SSE2_MIX_MAX_VOLUME, MIX_MAX_VOLUME == (1 << 10)); +#endif __m128i mm = _mm_set1_epi16(volume); while (len >= 16) { len -= 16; __m128i aa = _mm_loadu_si128((const __m128i*)ptr); - __m128i bb = _mm_mulhi_epi16(aa, mm); - _mm_storeu_si128((__m128i*)ptr, bb); +#if 1 + __m128i sm = _mm_mulhi_epi16(aa, mm); + __m128i cc = _mm_slli_epi16(sm, 1); +#else + __m128i lo = _mm_mullo_epi16(aa, mm); + __m128i hi = _mm_mulhi_epi16(aa, mm); + __m128i c0 = _mm_unpacklo_epi16(lo, hi); + __m128i c1 = _mm_unpackhi_epi16(lo, hi); + __m128i d0 = _mm_srai_epi32(c0, 10); + __m128i d1 = _mm_srai_epi32(c1, 10); + __m128i cc = _mm_packs_epi32(d0, d1); +#endif + _mm_storeu_si128((__m128i*)ptr, cc); ptr += 8; } - - volume /= (1 << 16) / MIX_MAX_VOLUME; +#if 1 + volume /= (unsigned)((1 << 15) / MIX_MAX_VOLUME); +#endif len /= sizeof(Sint16); while (len--) { vol = SDL_SwapLE16(*ptr); @@ -953,21 +1007,36 @@ static SDL_bool SDL_TARGETING("avx2") _Eff_volume_s16lbs_AVX2(void* stream, unsi if (volume == MIX_MAX_VOLUME) return SDL_TRUE; - //static_assert((MIX_MAX_VOLUME & (MIX_MAX_VOLUME - 1)) == 0, "_Eff_volume_s16lbs_AVX expects MIX_MAX_VOLUME to be a power of 2."); - //static_assert(MIX_MAX_VOLUME <= (1 << 16), "_Eff_volume_s16lbs_AVX expects MIX_MAX_VOLUME to be low."); - volume *= (1 << 16) / MIX_MAX_VOLUME; - +#if 1 + SDL_INLINE_COMPILE_TIME_ASSERT(_Eff_volume_s16lbs_AVX2_MIX_MAX_VOLUME, (MIX_MAX_VOLUME & (MIX_MAX_VOLUME - 1)) == 0); + SDL_INLINE_COMPILE_TIME_ASSERT(_Eff_volume_s16lbs_AVX2_low, MIX_MAX_VOLUME <= (1 << 15)); + volume *= (1 << 15) / MIX_MAX_VOLUME; +#else + SDL_INLINE_COMPILE_TIME_ASSERT(_Eff_volume_s16lbs_AVX2_MIX_MAX_VOLUME, MIX_MAX_VOLUME == (1 << 10)); +#endif __m256i mm = _mm256_set1_epi16(volume); while (len >= 32) { len -= 32; __m256i aa = _mm256_loadu_si256((const __m256i*)ptr); - __m256i bb = _mm256_mulhi_epi16(aa, mm); - _mm256_storeu_si256((__m256i*)ptr, bb); +#if 1 + __m256i sm = _mm256_mulhi_epi16(aa, mm); + __m256i cc = _mm256_slli_epi16(sm, 1); +#else + __m256i lo = _mm256_mullo_epi16(aa, mm); + __m256i hi = _mm256_mulhi_epi16(aa, mm); + __m256i c0 = _mm256_unpacklo_epi16(lo, hi); + __m256i c1 = _mm256_unpackhi_epi16(lo, hi); + __m256i d0 = _mm256_srai_epi32(c0, 10); + __m256i d1 = _mm256_srai_epi32(c1, 10); + __m256i cc = _mm256_packs_epi32(d0, d1); +#endif + _mm256_storeu_si256((__m256i*)ptr, cc); ptr += 16; } - - volume /= (1 << 16) / MIX_MAX_VOLUME; +#if 1 + volume /= (unsigned)((1 << 15) / MIX_MAX_VOLUME); +#endif len /= sizeof(Sint16); while (len--) { vol = SDL_SwapLE16(*ptr); From 4cebe837c340cf7bb1be9209e4208da7a895ff3a Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 2 Sep 2024 08:31:39 +0200 Subject: [PATCH 524/596] simplify the loops in AddTown and in MI_Guardian --- Source/missiles.cpp | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index a1bf959452f..9f3cb699a89 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -2422,23 +2422,22 @@ int AddTown(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int // ((unsigned)misource < MAX_PLRS); // the position of portals in town and recreated portals are fixed if (currLvl._dType != DTYPE_TOWN && spllvl >= 0) { - const int RANGE = 6; - static_assert(DBORDERX >= RANGE - 1 && DBORDERY >= RANGE - 1, "AddTown expects a large enough border."); - static_assert(lengthof(CrawlNum) >= RANGE, "AddShroud uses CrawlTable/CrawlNum up to radius 5."); - for (i = 0; i < RANGE; i++) { + static_assert(DBORDERX >= 5 && DBORDERY >= 5, "AddTown expects a large enough border."); + static_assert(lengthof(CrawlNum) > 5, "AddShroud uses CrawlTable/CrawlNum up to radius 5."); + for (i = 0; i <= 5; i++) { cr = &CrawlTable[CrawlNum[i]]; for (j = (BYTE)*cr; j > 0; j--) { tx = dx + *++cr; ty = dy + *++cr; assert(IN_DUNGEON_AREA(tx, ty)); if (PosOkMissile(tx, ty) && !CheckIfTrig(tx, ty) && LineClear(sx, sy, tx, ty)) { - i = RANGE; - break; + goto done; } } } - if (i == RANGE) - return MIRES_FAIL_DELETE; + return MIRES_FAIL_DELETE; +done: + ; } else { tx = dx; ty = dy; @@ -4406,19 +4405,19 @@ void MI_Guardian(int mi) // check for an enemy mis->_miRange--; if (mis->_miRange >= 0) { - ex = false; static_assert(DBORDERX >= 6 && DBORDERY >= 6, "MI_Guardian expects a large enough border."); static_assert(lengthof(CrawlNum) > 6, "MI_Guardian uses CrawlTable/CrawlNum up to radius 6."); - for (i = 6; i >= 0 && !ex; i--) { + for (i = 6; i >= 0; i--) { cr = &CrawlTable[CrawlNum[i]]; for (j = *cr; j > 0; j--) { tx = mis->_mix + *++cr; ty = mis->_miy + *++cr; - ex = Sentfire(mi, tx, ty); - if (ex) - break; + if (Sentfire(mi, tx, ty)) + goto done; } } +done: + ; } else { // start collapse SetMissDir(mi, 0); From a385c2044fb408ab00e12cd8ed5c904eec018569 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 2 Sep 2024 08:45:01 +0200 Subject: [PATCH 525/596] ensure the number of entries in CrawlTable is interpreted as a positive integer --- Source/missiles.cpp | 12 ++++++------ Source/objects.cpp | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 9f3cb699a89..6c6aee271c8 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -1596,7 +1596,7 @@ static int PlaceRune(int mi, int sx, int sy, int dx, int dy, int mitype, int mir static_assert(lengthof(CrawlNum) > 9, "PlaceRune uses CrawlTable/CrawlNum up to radius 9."); for (i = 0; i <= 9; i++) { cr = &CrawlTable[CrawlNum[i]]; - for (j = *cr; j > 0; j--) { + for (j = (BYTE)*cr; j > 0; j--) { tx = dx + *++cr; ty = dy + *++cr; assert(IN_DUNGEON_AREA(tx, ty)); @@ -1756,7 +1756,7 @@ int AddRingC(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in static_assert(DBORDERX >= 3 && DBORDERY >= 3, "AddRingC expects a large enough border."); static_assert(lengthof(CrawlNum) > 3, "AddRingC uses CrawlTable/CrawlNum radius 3."); cr = &CrawlTable[CrawlNum[3]]; - for (j = *cr; j > 0; j--) { + for (j = (BYTE)*cr; j > 0; j--) { tx = sx + *++cr; ty = sy + *++cr; assert(IN_DUNGEON_AREA(tx, ty)); @@ -3072,7 +3072,7 @@ int AddNovaC(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in static_assert(DBORDERX >= 3 && DBORDERY >= 3, "AddNovaC expects a large enough border."); static_assert(lengthof(CrawlNum) > 3, "AddNovaC uses CrawlTable/CrawlNum radius 3."); cr = &CrawlTable[CrawlNum[3]]; - for (i = *cr; i > 0; i--) { + for (i = (BYTE)*cr; i > 0; i--) { tx = sx + *++cr; ty = sy + *++cr; AddMissile(sx, sy, tx, ty, 0, MIS_LIGHTBALL, micaster, misource, spllvl); @@ -3967,7 +3967,7 @@ void MI_HorkSpawn(int mi) static_assert(lengthof(CrawlNum) > 1, "MI_HorkSpawn uses CrawlTable/CrawlNum up to radius 1."); for (i = 0; i <= 1; i++) { cr = &CrawlTable[CrawlNum[i]]; - for (j = *cr; j > 0; j--) { + for (j = (BYTE)*cr; j > 0; j--) { tx = mis->_mix + *++cr; ty = mis->_miy + *++cr; // assert(IN_DUNGEON_AREA(tx, ty)); @@ -3997,7 +3997,7 @@ void MI_Rune(int mi) sy = mis->_miy; static_assert(lengthof(CrawlNum) > 1, "MI_Rune uses CrawlTable/CrawlNum up to radius 1."); cr = &CrawlTable[CrawlNum[mis->_miVar2]]; // RUNE_RANGE - for (j = *cr; j > 0; j--) { + for (j = (BYTE)*cr; j > 0; j--) { tx = sx + *++cr; ty = sy + *++cr; if (dPlayer[tx][ty] == 0) { @@ -4409,7 +4409,7 @@ void MI_Guardian(int mi) static_assert(lengthof(CrawlNum) > 6, "MI_Guardian uses CrawlTable/CrawlNum up to radius 6."); for (i = 6; i >= 0; i--) { cr = &CrawlTable[CrawlNum[i]]; - for (j = *cr; j > 0; j--) { + for (j = (BYTE)*cr; j > 0; j--) { tx = mis->_mix + *++cr; ty = mis->_miy + *++cr; if (Sentfire(mi, tx, ty)) diff --git a/Source/objects.cpp b/Source/objects.cpp index e8fad58ee99..d9c7d2cd0a1 100644 --- a/Source/objects.cpp +++ b/Source/objects.cpp @@ -1428,7 +1428,7 @@ static void FindClosestPlr(int* dx, int* dy) static_assert(lengthof(CrawlNum) > 9, "FindClosestPlr uses CrawlTable/CrawlNum up to radius 9."); for (i = 0; i <= 9; i++) { cr = &CrawlTable[CrawlNum[i]]; - for (j = *cr; j > 0; j--) { + for (j = (BYTE)*cr; j > 0; j--) { xx = *dx + *++cr; yy = *dy + *++cr; if (PosOkActor(xx, yy) && PosOkPortal(xx, yy)) { From 690eff9ee82a09e8752c16c67b73d56dc4cadb55 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 2 Sep 2024 10:13:26 +0200 Subject: [PATCH 526/596] validate CrawlTable for MAI_Scav in ValidateData --- Source/debug.cpp | 3 ++- Source/monster.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/debug.cpp b/Source/debug.cpp index 4acf72d072d..4adc344f103 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -268,7 +268,8 @@ void ValidateData() if (i != CURSOR_NONE && InvItemHeight[i] == 0) app_fatal("Invalid (zero) cursor height at %d.", i); } - + // meta-data + assert(CrawlTable[CrawlNum[4]] == 32); // required by MAI_Scav // quests for (i = 0; i < lengthof(AllLevels); i++) { int j = 0; diff --git a/Source/monster.cpp b/Source/monster.cpp index 82d5704e70d..d06de4ea342 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3613,7 +3613,7 @@ void MAI_Scav(int mnum) static_assert(MAXDUNX < UCHAR_MAX, "MAI_Scav stores dungeon coordinates in BYTE field I."); static_assert(MAXDUNY < UCHAR_MAX, "MAI_Scav stores dungeon coordinates in BYTE field II."); static_assert(lengthof(CrawlNum) > 4, "MAI_Scav uses CrawlTable/CrawlNum up to radius 4."); - assert(CrawlTable[CrawlNum[4]] == 32); + // assert(CrawlTable[CrawlNum[4]] == 32); BYTE corpseLocs[32 * 2]; tmp = 0; for (i = 1; i <= 4; i++) { From 5e403a2477606fab4846b878018b5479201d4c94 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 2 Sep 2024 10:51:34 +0200 Subject: [PATCH 527/596] validate CrawlNum/CrawlTable in ValidateData - check the offsets in CrawlNum vs the entry-counts in CrawlTable - ensure the entries of CrawlTable are unique --- Source/debug.cpp | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Source/debug.cpp b/Source/debug.cpp index 4adc344f103..02942bfcb5c 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -269,6 +269,42 @@ void ValidateData() app_fatal("Invalid (zero) cursor height at %d.", i); } // meta-data + // - CrawlNum + for (int n = 0; n < lengthof(CrawlNum); n++) { + int a = CrawlNum[n]; + int e = CrawlTable[a]; + int b; + if (n < lengthof(CrawlNum) - 1) { + b = CrawlNum[n + 1]; + } else { + b = lengthof(CrawlTable); + } + if (a + 1 + 2 * e != b) + app_fatal("CrawlNum mismatch %d vs %d (idx=%d)", a + 1 + 2 * e, b, n); + } + // - CrawlTable + for (int i = 0; i < lengthof(CrawlTable); i++) { + int k = 0; + for (; k < lengthof(CrawlNum); k++) { + if (CrawlNum[k] == i) + break; + } + if (k >= lengthof(CrawlNum)) { + for (int n = i + 2; n < lengthof(CrawlTable); n++) { + k = 0; + for (; k < lengthof(CrawlNum); k++) { + if (CrawlNum[k] == n) + break; + } + if (k >= lengthof(CrawlNum)) { + if (CrawlTable[n] == CrawlTable[i] && CrawlTable[n + 1] == CrawlTable[i + 1]) + app_fatal("Duplicate entry (%d:%d) in CrawlTable (@ %d and %d)", CrawlTable[n], CrawlTable[n + 1], n, i); + n++; + } + } + i++; + } + } assert(CrawlTable[CrawlNum[4]] == 32); // required by MAI_Scav // quests for (i = 0; i < lengthof(AllLevels); i++) { From 5137772a76a2f70175fe4fdd0da7565d06a10776 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 2 Sep 2024 11:14:26 +0200 Subject: [PATCH 528/596] cosmetic --- Source/lighting.cpp | 208 ++++++++++++++++++++++---------------------- 1 file changed, 104 insertions(+), 104 deletions(-) diff --git a/Source/lighting.cpp b/Source/lighting.cpp index 78492d14078..98e15970a6c 100644 --- a/Source/lighting.cpp +++ b/Source/lighting.cpp @@ -87,7 +87,7 @@ const int8_t CrawlTable[2749] = { -1, -2, 1, -2, -1, 1, 1, 1, -1, -1, 1, -1, -2, 1, 2, 1, -2, -1, 2, -1, -2, 0, 2, 0, - 24, // 3 - 45 + 24, // 3 - 45 0, 3, 0, -3, -1, 3, 1, 3, -1, -3, 1, -3, -2, 3, 2, 3, -2, -3, 2, -3, -2, 2, 2, 2, @@ -103,7 +103,7 @@ const int8_t CrawlTable[2749] = { -4, -3, 4, -3, -4, 2, 4, 2, -4, -2, 4, -2, -4, 1, 4, 1, -4, -1, 4, -1, -4, 0, 4, 0, - 40, // 5 - 159 + 40, // 5 - 159 0, 5, 0, -5, -1, 5, 1, 5, -1, -5, 1, -5, -2, 5, 2, 5, -2, -5, 2, -5, -3, 5, 3, 5, @@ -335,110 +335,110 @@ const int8_t CrawlTable[2749] = { -15, -2, 15, -2, -15, 1, 15, 1, -15, -1, 15, -1, -15, 0, 15, 0, (int8_t)128, // 16 - 1930 - 0, 16, 0, -16, -1, 16, 1, 16, - -1, -16, 1, -16, -2, 16, 2, 16, - -2, -16, 2, -16, -3, 16, 3, 16, - -3, -16, 3, -16, -4, 16, 4, 16, - -4, -16, 4, -16, -5, 16, 5, 16, - -5, -16, 5, -16, -6, 16, 6, 16, - -6, -16, 6, -16, -7, 16, 7, 16, - -7, -16, 7, -16, -8, 16, 8, 16, - -8, -16, 8, -16, -9, 16, 9, 16, - -9, -16, 9, -16, -10, 16, 10, 16, - -10, -16, 10, -16, -11, 16, 11, 16, - -11, -16, 11, -16, -12, 16, 12, 16, - -12, -16, 12, -16, -13, 16, 13, 16, - -13, -16, 13, -16, -14, 16, 14, 16, - -14, -16, 14, -16, -15, 16, 15, 16, - -15, -16, 15, -16, -15, 15, 15, 15, - -15, -15, 15, -15, -16, 15, 16, 15, - -16, -15, 16, -15, -16, 14, 16, 14, - -16, -14, 16, -14, -16, 13, 16, 13, - -16, -13, 16, -13, -16, 12, 16, 12, - -16, -12, 16, -12, -16, 11, 16, 11, - -16, -11, 16, -11, -16, 10, 16, 10, - -16, -10, 16, -10, -16, 9, 16, 9, - -16, -9, 16, -9, -16, 8, 16, 8, - -16, -8, 16, -8, -16, 7, 16, 7, - -16, -7, 16, -7, -16, 6, 16, 6, - -16, -6, 16, -6, -16, 5, 16, 5, - -16, -5, 16, -5, -16, 4, 16, 4, - -16, -4, 16, -4, -16, 3, 16, 3, - -16, -3, 16, -3, -16, 2, 16, 2, - -16, -2, 16, -2, -16, 1, 16, 1, - -16, -1, 16, -1, -16, 0, 16, 0, + 0, 16, 0,-16, -1, 16, 1, 16, + -1,-16, 1,-16, -2, 16, 2, 16, + -2,-16, 2,-16, -3, 16, 3, 16, + -3,-16, 3,-16, -4, 16, 4, 16, + -4,-16, 4,-16, -5, 16, 5, 16, + -5,-16, 5,-16, -6, 16, 6, 16, + -6,-16, 6,-16, -7, 16, 7, 16, + -7,-16, 7,-16, -8, 16, 8, 16, + -8,-16, 8,-16, -9, 16, 9, 16, + -9,-16, 9,-16, -10, 16, 10, 16, + -10,-16, 10,-16, -11, 16, 11, 16, + -11,-16, 11,-16, -12, 16, 12, 16, + -12,-16, 12,-16, -13, 16, 13, 16, + -13,-16, 13,-16, -14, 16, 14, 16, + -14,-16, 14,-16, -15, 16, 15, 16, + -15,-16, 15,-16, -15, 15, 15, 15, + -15,-15, 15,-15, -16, 15, 16, 15, + -16,-15, 16,-15, -16, 14, 16, 14, + -16,-14, 16,-14, -16, 13, 16, 13, + -16,-13, 16,-13, -16, 12, 16, 12, + -16,-12, 16,-12, -16, 11, 16, 11, + -16,-11, 16,-11, -16, 10, 16, 10, + -16,-10, 16,-10, -16, 9, 16, 9, + -16, -9, 16, -9, -16, 8, 16, 8, + -16, -8, 16, -8, -16, 7, 16, 7, + -16, -7, 16, -7, -16, 6, 16, 6, + -16, -6, 16, -6, -16, 5, 16, 5, + -16, -5, 16, -5, -16, 4, 16, 4, + -16, -4, 16, -4, -16, 3, 16, 3, + -16, -3, 16, -3, -16, 2, 16, 2, + -16, -2, 16, -2, -16, 1, 16, 1, + -16, -1, 16, -1, -16, 0, 16, 0, (int8_t)136, // 17 - 2187 - 0, 17, 0, -17, -1, 17, 1, 17, - -1, -17, 1, -17, -2, 17, 2, 17, - -2, -17, 2, -17, -3, 17, 3, 17, - -3, -17, 3, -17, -4, 17, 4, 17, - -4, -17, 4, -17, -5, 17, 5, 17, - -5, -17, 5, -17, -6, 17, 6, 17, - -6, -17, 6, -17, -7, 17, 7, 17, - -7, -17, 7, -17, -8, 17, 8, 17, - -8, -17, 8, -17, -9, 17, 9, 17, - -9, -17, 9, -17, -10, 17, 10, 17, - -10, -17, 10, -17, -11, 17, 11, 17, - -11, -17, 11, -17, -12, 17, 12, 17, - -12, -17, 12, -17, -13, 17, 13, 17, - -13, -17, 13, -17, -14, 17, 14, 17, - -14, -17, 14, -17, -15, 17, 15, 17, - -15, -17, 15, -17, -16, 17, 16, 17, - -16, -17, 16, -17, -16, 16, 16, 16, - -16, -16, 16, -16, -17, 16, 17, 16, - -17, -16, 17, -16, -17, 15, 17, 15, - -17, -15, 17, -15, -17, 14, 17, 14, - -17, -14, 17, -14, -17, 13, 17, 13, - -17, -13, 17, -13, -17, 12, 17, 12, - -17, -12, 17, -12, -17, 11, 17, 11, - -17, -11, 17, -11, -17, 10, 17, 10, - -17, -10, 17, -10, -17, 9, 17, 9, - -17, -9, 17, -9, -17, 8, 17, 8, - -17, -8, 17, -8, -17, 7, 17, 7, - -17, -7, 17, -7, -17, 6, 17, 6, - -17, -6, 17, -6, -17, 5, 17, 5, - -17, -5, 17, -5, -17, 4, 17, 4, - -17, -4, 17, -4, -17, 3, 17, 3, - -17, -3, 17, -3, -17, 2, 17, 2, - -17, -2, 17, -2, -17, 1, 17, 1, - -17, -1, 17, -1, -17, 0, 17, 0, + 0, 17, 0,-17, -1, 17, 1, 17, + -1,-17, 1,-17, -2, 17, 2, 17, + -2,-17, 2,-17, -3, 17, 3, 17, + -3,-17, 3,-17, -4, 17, 4, 17, + -4,-17, 4,-17, -5, 17, 5, 17, + -5,-17, 5,-17, -6, 17, 6, 17, + -6,-17, 6,-17, -7, 17, 7, 17, + -7,-17, 7,-17, -8, 17, 8, 17, + -8,-17, 8,-17, -9, 17, 9, 17, + -9,-17, 9,-17, -10, 17, 10, 17, + -10,-17, 10,-17, -11, 17, 11, 17, + -11,-17, 11,-17, -12, 17, 12, 17, + -12,-17, 12,-17, -13, 17, 13, 17, + -13,-17, 13,-17, -14, 17, 14, 17, + -14,-17, 14,-17, -15, 17, 15, 17, + -15,-17, 15,-17, -16, 17, 16, 17, + -16,-17, 16,-17, -16, 16, 16, 16, + -16,-16, 16,-16, -17, 16, 17, 16, + -17,-16, 17,-16, -17, 15, 17, 15, + -17,-15, 17,-15, -17, 14, 17, 14, + -17,-14, 17,-14, -17, 13, 17, 13, + -17,-13, 17,-13, -17, 12, 17, 12, + -17,-12, 17,-12, -17, 11, 17, 11, + -17,-11, 17,-11, -17, 10, 17, 10, + -17,-10, 17,-10, -17, 9, 17, 9, + -17, -9, 17, -9, -17, 8, 17, 8, + -17, -8, 17, -8, -17, 7, 17, 7, + -17, -7, 17, -7, -17, 6, 17, 6, + -17, -6, 17, -6, -17, 5, 17, 5, + -17, -5, 17, -5, -17, 4, 17, 4, + -17, -4, 17, -4, -17, 3, 17, 3, + -17, -3, 17, -3, -17, 2, 17, 2, + -17, -2, 17, -2, -17, 1, 17, 1, + -17, -1, 17, -1, -17, 0, 17, 0, (int8_t)144, // 18 - 2460 - 0, 18, 0, -18, -1, 18, 1, 18, - -1, -18, 1, -18, -2, 18, 2, 18, - -2, -18, 2, -18, -3, 18, 3, 18, - -3, -18, 3, -18, -4, 18, 4, 18, - -4, -18, 4, -18, -5, 18, 5, 18, - -5, -18, 5, -18, -6, 18, 6, 18, - -6, -18, 6, -18, -7, 18, 7, 18, - -7, -18, 7, -18, -8, 18, 8, 18, - -8, -18, 8, -18, -9, 18, 9, 18, - -9, -18, 9, -18, -10, 18, 10, 18, - -10, -18, 10, -18, -11, 18, 11, 18, - -11, -18, 11, -18, -12, 18, 12, 18, - -12, -18, 12, -18, -13, 18, 13, 18, - -13, -18, 13, -18, -14, 18, 14, 18, - -14, -18, 14, -18, -15, 18, 15, 18, - -15, -18, 15, -18, -16, 18, 16, 18, - -16, -18, 16, -18, -17, 18, 17, 18, - -17, -18, 17, -18, -17, 17, 17, 17, - -17, -17, 17, -17, -18, 17, 18, 17, - -18, -17, 18, -17, -18, 16, 18, 16, - -18, -16, 18, -16, -18, 15, 18, 15, - -18, -15, 18, -15, -18, 14, 18, 14, - -18, -14, 18, -14, -18, 13, 18, 13, - -18, -13, 18, -13, -18, 12, 18, 12, - -18, -12, 18, -12, -18, 11, 18, 11, - -18, -11, 18, -11, -18, 10, 18, 10, - -18, -10, 18, -10, -18, 9, 18, 9, - -18, -9, 18, -9, -18, 8, 18, 8, - -18, -8, 18, -8, -18, 7, 18, 7, - -18, -7, 18, -7, -18, 6, 18, 6, - -18, -6, 18, -6, -18, 5, 18, 5, - -18, -5, 18, -5, -18, 4, 18, 4, - -18, -4, 18, -4, -18, 3, 18, 3, - -18, -3, 18, -3, -18, 2, 18, 2, - -18, -2, 18, -2, -18, 1, 18, 1, - -18, -1, 18, -1, -18, 0, 18, 0 + 0, 18, 0,-18, -1, 18, 1, 18, + -1,-18, 1,-18, -2, 18, 2, 18, + -2,-18, 2,-18, -3, 18, 3, 18, + -3,-18, 3,-18, -4, 18, 4, 18, + -4,-18, 4,-18, -5, 18, 5, 18, + -5,-18, 5,-18, -6, 18, 6, 18, + -6,-18, 6,-18, -7, 18, 7, 18, + -7,-18, 7,-18, -8, 18, 8, 18, + -8,-18, 8,-18, -9, 18, 9, 18, + -9,-18, 9,-18, -10, 18, 10, 18, + -10,-18, 10,-18, -11, 18, 11, 18, + -11,-18, 11,-18, -12, 18, 12, 18, + -12,-18, 12,-18, -13, 18, 13, 18, + -13,-18, 13,-18, -14, 18, 14, 18, + -14,-18, 14,-18, -15, 18, 15, 18, + -15,-18, 15,-18, -16, 18, 16, 18, + -16,-18, 16,-18, -17, 18, 17, 18, + -17,-18, 17,-18, -17, 17, 17, 17, + -17,-17, 17,-17, -18, 17, 18, 17, + -18,-17, 18,-17, -18, 16, 18, 16, + -18,-16, 18,-16, -18, 15, 18, 15, + -18,-15, 18,-15, -18, 14, 18, 14, + -18,-14, 18,-14, -18, 13, 18, 13, + -18,-13, 18,-13, -18, 12, 18, 12, + -18,-12, 18,-12, -18, 11, 18, 11, + -18,-11, 18,-11, -18, 10, 18, 10, + -18,-10, 18,-10, -18, 9, 18, 9, + -18, -9, 18, -9, -18, 8, 18, 8, + -18, -8, 18, -8, -18, 7, 18, 7, + -18, -7, 18, -7, -18, 6, 18, 6, + -18, -6, 18, -6, -18, 5, 18, 5, + -18, -5, 18, -5, -18, 4, 18, 4, + -18, -4, 18, -4, -18, 3, 18, 3, + -18, -3, 18, -3, -18, 2, 18, 2, + -18, -2, 18, -2, -18, 1, 18, 1, + -18, -1, 18, -1, -18, 0, 18, 0, // clang-format on }; From 18e1be4fe43ae4128447e2e49d5e9dceeb4466f4 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 2 Sep 2024 12:17:18 +0200 Subject: [PATCH 529/596] add code to recreate the crawl-table --- Source/debug.cpp | 110 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/Source/debug.cpp b/Source/debug.cpp index 02942bfcb5c..5ad053bda0f 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -176,8 +176,117 @@ static bool HasUniqueItemReq(const UniqItemData& ui, BYTE pow) } return false; } +#ifdef DEBUG_DATA +static bool lessCrawlTableEntry(const POS32 *a, const POS32 *b) +{ + if (abs(a->y) != abs(b->y)) + return abs(a->y) > abs(b->y); + if (abs(a->x) != abs(b->x)) + return abs(a->x) < abs(b->x); + if (a->y != b->y) { + return a->y > b->y; + } + return a->x < b->x; +} + +static void sortCrawlTable(POS32 *table, unsigned entries, bool (cmpFunc)(const POS32 *a, const POS32 *b)) +{ + if (entries <= 1) + return; + sortCrawlTable(&table[0], entries - entries / 2, cmpFunc); + sortCrawlTable(&table[entries - entries / 2], entries / 2, cmpFunc); + + unsigned cl = 0; + unsigned cr = entries - entries / 2; + unsigned el = cr; + unsigned er = entries; + + POS32 *tmp = (POS32 *)malloc(sizeof(table[0]) * entries); + + for (unsigned i = 0; i < entries; i++) { + if (cr >= er || (cl < el && !cmpFunc(&table[cr], &table[cl]))) { + tmp[i] = table[cl]; + cl++; + } else { + tmp[i] = table[cr]; + cr++; + } + } + memcpy(table, tmp, sizeof(table[0]) * entries); +} +static void recreateCrawlTable() +{ + constexpr int r = 18; + int crns[r + 1]; + memset(crns, 0, sizeof(crns)); + POS32 ctableentries[r + 1][2 * 2 * r * 4]; + memset(ctableentries, 0x80, sizeof(ctableentries)); + int dx, dy, tx, ty, dist, total = 0; + dx = r + 1; + dy = r + 1; + for (tx = dx - r; tx <= dx + r; tx++) { + for (ty = dx - r; ty <= dy + r; ty++) { + dist = std::max(abs(tx - dx), abs(ty - dy)); + if (abs(tx - dx) == abs(ty - dy) && (tx != dx || ty != dy)) + dist++; + if (dist <= r) { + ctableentries[dist][crns[dist]].x = tx - dx; + ctableentries[dist][crns[dist]].y = ty - dy; + crns[dist]++; + total++; + } + } + } + for (int n = 0; n <= r; n++) { + sortCrawlTable(ctableentries[n], crns[n], lessCrawlTableEntry); + } + LogErrorF("const int8_t CrawlTable[%d] = {", total * 2 + r + 1); + LogErrorF(" // clang-format off"); + int cursor = 0; + for (int n = 0; n <= r; n++) { + int ii = crns[n]; + if (ii < 100) + LogErrorF(" %d,\t\t\t\t\t\t\t\t\t\t// %2d - %d", ii, n, cursor); + else if (ii < 128) + LogErrorF(" %d,\t\t\t\t\t\t\t\t\t// %2d - %d", ii, n, cursor); + else + LogErrorF(" (int8_t)%d,\t\t\t\t\t\t\t// %2d - %d", ii, n, cursor); + cursor++; + cursor += 2 * ii; + tempstr[0] = '\0'; + for (int i = 0; i < ii; i++) { + if ((i % 4) == 0) { + copy_cstr(tempstr, "\t"); + } + snprintf(tempstr, sizeof(tempstr), "%s%3d,%3d, ", tempstr, ctableentries[n][i].x, ctableentries[n][i].y); + if ((i % 4) == 3) { + tempstr[strlen(tempstr) - 2] = '\0'; + LogErrorF(tempstr); + tempstr[0] = '\0'; + } + } + if (tempstr[0] != '\0') { + tempstr[strlen(tempstr) - 2] = '\0'; + LogErrorF(tempstr); + tempstr[0] = '\0'; + } + } + LogErrorF(" // clang-format on"); + LogErrorF("};"); + snprintf(tempstr, sizeof(tempstr), "const int CrawlNum[%d] = {", r + 1); + cursor = 0; + for (int n = 0; n <= r; n++) { + snprintf(tempstr, sizeof(tempstr), "%s %d,", tempstr, cursor); + cursor++; + cursor += 2 * crns[n]; + } + tempstr[strlen(tempstr) - 1] = '\0'; + snprintf(tempstr, sizeof(tempstr), "%s };", tempstr); + LogErrorF(tempstr); +} +#endif // DEBUG_DATA void ValidateData() { #ifdef DEBUG_DATA @@ -269,6 +378,7 @@ void ValidateData() app_fatal("Invalid (zero) cursor height at %d.", i); } // meta-data + // recreateCrawlTable(); // - CrawlNum for (int n = 0; n < lengthof(CrawlNum); n++) { int a = CrawlNum[n]; From 3c0e163ff3eace450d331e00f0cd68700b702fda Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 2 Sep 2024 15:55:15 +0200 Subject: [PATCH 530/596] validate CrawlTable for AddNovaC in ValidateData --- Source/debug.cpp | 1 + Source/missiles.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/Source/debug.cpp b/Source/debug.cpp index 5ad053bda0f..dbf3da6dc07 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -416,6 +416,7 @@ void ValidateData() } } assert(CrawlTable[CrawlNum[4]] == 32); // required by MAI_Scav + assert(CrawlTable[CrawlNum[3]] == 24); // required by AddNovaC // quests for (i = 0; i < lengthof(AllLevels); i++) { int j = 0; diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 6c6aee271c8..0cbe1f9a6ac 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -3071,6 +3071,7 @@ int AddNovaC(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in // ((micaster & MST_PLAYER) || micaster == MST_OBJECT); static_assert(DBORDERX >= 3 && DBORDERY >= 3, "AddNovaC expects a large enough border."); static_assert(lengthof(CrawlNum) > 3, "AddNovaC uses CrawlTable/CrawlNum radius 3."); + // assert(CrawlTable[CrawlNum[3]] == 24); -- (total) damage depends on this cr = &CrawlTable[CrawlNum[3]]; for (i = (BYTE)*cr; i > 0; i--) { tx = sx + *++cr; From 2d8326f085ac1db57a3405c882bf2fc3b23e1756 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 2 Sep 2024 18:11:03 +0200 Subject: [PATCH 531/596] fix a few warnings --- Source/DiabloUI/selconn.cpp | 4 ++-- Source/debug.cpp | 11 ++++++----- Source/missiles.cpp | 3 +-- Source/msg.cpp | 6 +++--- Source/palette.cpp | 2 +- tools/patcher/townp.cpp | 1 + tools/patcher/utils/md5.h | 2 +- 7 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Source/DiabloUI/selconn.cpp b/Source/DiabloUI/selconn.cpp index 7bd0d17b9fe..07754e67697 100644 --- a/Source/DiabloUI/selconn.cpp +++ b/Source/DiabloUI/selconn.cpp @@ -12,7 +12,7 @@ DEVILUTION_BEGIN_NAMESPACE bool selconn_bMulti = false; int provider; - +#ifndef NONET static_assert(MAX_PLRS < 100, "Not enough space to print the info message."); static char selconn_MaxPlayers[22]; static char selconn_Description[64]; @@ -136,7 +136,7 @@ static void SelconnSelect(unsigned index) selconn_EndMenu = true; } - +#endif // NONET bool UiSelectProvider(bool bMulti) { selconn_bMulti = bMulti; diff --git a/Source/debug.cpp b/Source/debug.cpp index dbf3da6dc07..cb2a60c7ebb 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -53,7 +53,7 @@ void DumpDungeon() #endif /* DEBUG_MODE */ #if DEBUG_MODE || DEV_MODE -static const char* ReadTextLine(const char* str, char lineSep, int limit) +/*static const char* ReadTextLine(const char* str, char lineSep, int limit) { int w; BYTE c; @@ -80,7 +80,7 @@ static const char* ReadTextLine(const char* str, char lineSep, int limit) static void PrintText(const char* text, char lineSep, int limit) { const char* s = text; - int i = 0, w; + // int i = 0, w; BYTE col; FILE* textFile = fopen("f:\\sample.txt", "wb"); @@ -92,7 +92,7 @@ static void PrintText(const char* text, char lineSep, int limit) col = COL_WHITE; } s = ReadTextLine(s, lineSep, limit); - w = GetSmallStringWidth(tempstr); + // w = GetSmallStringWidth(tempstr); // LogErrorF("%03d(%04d):%s", i++, w, tempstr); if (col == COL_RED) @@ -105,7 +105,8 @@ static void PrintText(const char* text, char lineSep, int limit) } fclose(textFile); -} +}*/ +#ifdef DEBUG_DATA /* copy-paste from monster.cpp */ static bool IsSkel(int mt) { @@ -176,7 +177,7 @@ static bool HasUniqueItemReq(const UniqItemData& ui, BYTE pow) } return false; } -#ifdef DEBUG_DATA + static bool lessCrawlTableEntry(const POS32 *a, const POS32 *b) { if (abs(a->y) != abs(b->y)) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 0cbe1f9a6ac..c03a7132ec4 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -3620,9 +3620,8 @@ void MI_Mage(int mi) mis->_mitxoff += mis->_mixvel; mis->_mityoff += mis->_miyvel; GetMissilePos(mi); - bool wallHit = true; if (mis->_mix != mis->_misx || mis->_miy != mis->_misy) { - wallHit = CheckMissileCol(mi, mis->_mix, mis->_miy, MICM_BLOCK_ANY); + CheckMissileCol(mi, mis->_mix, mis->_miy, MICM_BLOCK_ANY); } mis->_miRange--; if (mis->_miRange >= 0) { diff --git a/Source/msg.cpp b/Source/msg.cpp index e07988ed3f1..0d6e1eea5b0 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -3656,7 +3656,7 @@ static unsigned On_DUMP_MONSTERS(TCmd* pCmd, int pnum) mstr->dmy, mstr->dmdir, mstr->dmactive, - mstr->dmhitpoints, + (int)mstr->dmhitpoints, mstr->dmWhoHit); // clang-format on } else { @@ -4022,10 +4022,10 @@ static unsigned On_DO_PLRCHECK(TCmd* pCmd, int pnum) //memcpy(buf, plx(i)._pTimer, sizeof(plx(i)._pTimer)); //buf += sizeof(plx(i)._pTimer); - if (plx(i)._pExperience != *(INT*)src) + if (plx(i)._pExperience != *(UINT*)src) PrintPlrMismatch("expr", plx(i)._pExperience, *(INT*)src, pnum, i); src += sizeof(INT); - if (plx(i)._pNextExper != *(INT*)src) + if (plx(i)._pNextExper != *(UINT*)src) PrintPlrMismatch("nexpr", plx(i)._pNextExper, *(INT*)src, pnum, i); src += sizeof(INT); diff --git a/Source/palette.cpp b/Source/palette.cpp index 4175c20b472..b857e11ec1f 100644 --- a/Source/palette.cpp +++ b/Source/palette.cpp @@ -209,7 +209,7 @@ void palette_update_crypt() palette_update(); } -/*static int nestCycleCounter = 3; +static int nestCycleCounter = 3; void palette_update_nest() { int i; diff --git a/tools/patcher/townp.cpp b/tools/patcher/townp.cpp index f7c642cfa6c..b815c0ae7f7 100644 --- a/tools/patcher/townp.cpp +++ b/tools/patcher/townp.cpp @@ -1396,6 +1396,7 @@ copy 440[1] -> 438[0], 406[10] move micro 438[0 2] -> 406[12 14] blkmcr 440[1] blkmcr 441[0] +*/ /* copy 441[1] -> 412[8], 439[0] copy 438[1] -> 439[0] diff --git a/tools/patcher/utils/md5.h b/tools/patcher/utils/md5.h index 54bfc35c338..f7b1d052bb5 100644 --- a/tools/patcher/utils/md5.h +++ b/tools/patcher/utils/md5.h @@ -319,7 +319,7 @@ class MD5 printf("%s can't be opened\n", filename); else { - while (len = fread(buffer, 1, 1024, file)) + while ((len = fread(buffer, 1, 1024, file))) Update(buffer, len); Final(); From 845602d28d19b58b4447fe6729b4c530e9c39631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20T=C3=B6rnblom?= Date: Sun, 25 Aug 2024 19:27:43 +0200 Subject: [PATCH 532/596] add experimental port for jailbroken PS5s --- .github/workflows/nightly.yml | 49 ++++++++++++++++++++++++++++++++ CMake/amiga_defs.cmake | 1 + CMake/ps5_defs.cmake | 24 ++++++++++++++++ CMakeLists.txt | 5 ++++ Packaging/ps5/README.md | 40 ++++++++++++++++++++++++++ Packaging/ps5/build.sh | 34 ++++++++++++++++++++++ Packaging/ps5/homebrew.js | 26 +++++++++++++++++ Packaging/ps5/sce_sys/icon0.png | Bin 0 -> 45131 bytes Source/storm/storm.cpp | 2 +- tools/patcher/storm/storm.cpp | 2 +- 10 files changed, 181 insertions(+), 2 deletions(-) create mode 100644 CMake/ps5_defs.cmake create mode 100644 Packaging/ps5/README.md create mode 100755 Packaging/ps5/build.sh create mode 100755 Packaging/ps5/homebrew.js create mode 100644 Packaging/ps5/sce_sys/icon0.png diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 9041a36a30b..1ebedc30620 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -746,6 +746,55 @@ jobs: name: ${{ matrix.artifact }} path: build-ps4/devilutionx-ps4.pkg + # ps5-builds + build_ps5: + needs: build_check + if: ${{ needs.build_check.outputs.should_run != 'false' }} + name: Nightly-PS5 + strategy: + fail-fast: false + matrix: + #name: [diablo, hellfire] + include: + - name: diablo + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF' + artifact: 'diablo-nightly-ps5.zip' + - name: hellfire + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DHELLFIRE=ON' + artifact: 'hellfire-nightly-ps5.zip' + - name: diablo+patch + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON' + artifact: 'diablo-nightly-ps5p.zip' + - name: hellfire+patch + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' + artifact: 'hellfire-nightly-ps5p.zip' + runs-on: ubuntu-22.04 + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Create Build Environment + run: | + sudo apt update + sudo apt install cmake pkg-config clang-15 lld-15 + sudo apt install build-essential autoconf libtool yasm nasm + sudo apt install smpq gperf pkgconf libarchive-tools autopoint po4a git curl doxygen wget + wget https://github.com/ps5-payload-dev/pacbrew-repo/releases/download/v0.8/ps5-payload-dev.tar.gz + sudo tar -xf ps5-payload-dev.tar.gz -C / + + - name: Build + working-directory: ${{github.workspace}} + shell: bash + run: Packaging/ps5/build.sh "${{ matrix.cmakeargs }}" + + - name: Upload-Package + uses: actions/upload-artifact@v4 + with: + path: build-ps5/devilutionx-ps5.zip + name: ${{ matrix.artifact }} + # vita-builds build_vita: needs: build_check diff --git a/CMake/amiga_defs.cmake b/CMake/amiga_defs.cmake index d5c4f634a26..0b6e7073728 100644 --- a/CMake/amiga_defs.cmake +++ b/CMake/amiga_defs.cmake @@ -4,6 +4,7 @@ set(UBSAN OFF) # General build options. set(NONET ON) +set(NOMEMCCPY ON) set(USE_SDL1 ON) #set(TTF_FONT_NAME \"LiberationSerif-Bold.ttf\") diff --git a/CMake/ps5_defs.cmake b/CMake/ps5_defs.cmake new file mode 100644 index 00000000000..5002117ebb3 --- /dev/null +++ b/CMake/ps5_defs.cmake @@ -0,0 +1,24 @@ +# Disable sanitizers. They're not supported out-of-the-box. +set(ASAN OFF) +set(UBSAN OFF) + +# General build options. +# If the executable is stripped, create-fself fails with: +# Failed to build FSELF: no symbol section +#set(DISABLE_STRIP ON) +#set(DISABLE_LTO ON) +set(NONET ON) +set(NOMEMCCPY ON) +#set(DISCORD_INTEGRATION OFF) +#set(BUILD_TESTING OFF) +#set(NOEXIT ON) +#set(BUILD_ASSETS_MPQ ON) + +# Packbrew SDK provides SDL_image, but FindSDL2_image() fails to +# pick up its dependencies (with includes libjpeg, libwebp etc). +# One way to address this, is to do the following: +# +# target_link_libraries(${BIN_TARGET} PUBLIC ${PC_SDL2_image_LIBRARIES}) +# +# or simply use the in-tree copy as follows: +#set(DEVILUTIONX_SYSTEM_SDL_IMAGE OFF) diff --git a/CMakeLists.txt b/CMakeLists.txt index af4771f9fdd..dc638208e28 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,6 +112,10 @@ if(PS4) include(ps4_defs) endif() +if(PS5) + include(ps5_defs) +endif() + if(ANDROID) include(android_defs) endif() @@ -861,6 +865,7 @@ foreach( HAS_JOYSTICK SCREEN_READER_INTEGRATION PREFILL_PLAYER_NAME + NOMEMCCPY DEBUG_MODE DEV_MODE GPERF diff --git a/Packaging/ps5/README.md b/Packaging/ps5/README.md new file mode 100644 index 00000000000..96ac02fd886 --- /dev/null +++ b/Packaging/ps5/README.md @@ -0,0 +1,40 @@ +# devilutionX PS5 port + +## Prerequisites +- A Playstation 5 capable of running the [ps5-payload-websrv][websrv] homebrew. +- Game assets from the Diablo game (diabdat.mpq), + or its [shareware][shareware] (spawn.mpq) + +## Installation +- Copy the game assets (e.g., via ftp) to /data/homebrew/devilutionX +- Launch the [ps5-payload-websrv][websrv] homebrew +- Launch the game from your browser at http://PS5-IP:8080, or using the + [companion launcher][launcher] from the PS5 menu system + +## Controls +- D-pad: move hero +- ○: attack nearby enemies, talk to townspeople and merchants, pickup/place + items in the inventory, OK while in main menu +- ×: select spell, back while in menus +- △: pickup items, open nearby chests and doors, use item in the inventory +- □: cast spell, delete character while in main menu +- L1: use health item from belt +- R1: use mana potion from belt +- L2: toggle character sheet +- R2: toggle inventory +- Left stick: move hero +- Right stick: move cursor +- L3: toggle auto map +- R3: click with cursor + +## Building from Source +Install the [PacBrew PS5 SDK][pacbrew], then run the following + bash script: +```console +devilutionX$ ./Packaging/ps5/build.sh +``` + +[shareware]: http://ftp.blizzard.com/pub/demos/diablosw.exe +[pacbrew]: https://github.com/ps5-payload-dev/pacbrew-repo +[websrv]: https://github.com/ps5-payload-dev/websrv +[launcher]: https://github.com/ps5-payload-dev/websrv/blob/master/homebrew/IV9999-FAKE00001_00-HOMEBREWLOADER01.pkg?raw=true diff --git a/Packaging/ps5/build.sh b/Packaging/ps5/build.sh new file mode 100755 index 00000000000..3e0d943b51f --- /dev/null +++ b/Packaging/ps5/build.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +set -e +SCRIPTDIR="${BASH_SOURCE[0]}" +SCRIPTDIR="$(dirname "${SCRIPTDIR}")" + +declare -r CMAKE_ARGS="$1" +declare -r BUILD_DIR="build-ps5" + +if [ -z "${PS5_PAYLOAD_SDK}" ]; then + export PS5_PAYLOAD_SDK=/opt/ps5-payload-sdk +fi + +source "${PS5_PAYLOAD_SDK}/toolchain/prospero.sh" + +${CMAKE} -S "${SCRIPTDIR}/../../" -B"$BUILD_DIR" \ + -DCMAKE_BUILD_TYPE=Release \ + ${CMAKE_ARGS} \ + "$@" +${MAKE} -C "$BUILD_DIR" -j $(getconf _NPROCESSORS_ONLN) + +rm -rf "$BUILD_DIR"/DevilutionX +mkdir "$BUILD_DIR"/DevilutionX + +cp -r "${SCRIPTDIR}/sce_sys" "$BUILD_DIR"/DevilutionX/ +cp "${SCRIPTDIR}/homebrew.js" "$BUILD_DIR"/DevilutionX/ +cp "${SCRIPTDIR}/README.md" "$BUILD_DIR"/DevilutionX/ +cp "$BUILD_DIR"/devilx.mpq "$BUILD_DIR"/DevilutionX/ +cp "$BUILD_DIR"/devilutionx "$BUILD_DIR"/DevilutionX/devilutionx.elf + +# Let github actions do this? +cd "$BUILD_DIR" +rm -f devilutionx-ps5.zip +zip -r devilutionx-ps5.zip DevilutionX diff --git a/Packaging/ps5/homebrew.js b/Packaging/ps5/homebrew.js new file mode 100755 index 00000000000..ceb1f4e4188 --- /dev/null +++ b/Packaging/ps5/homebrew.js @@ -0,0 +1,26 @@ + +async function main() { + const PAYLOAD = window.workingDir + '/devilutionx.elf'; + + return { + mainText: "DevilutionX", + secondaryText: 'Diablo build for modern OSes', + onclick: async () => { + return { + path: PAYLOAD, + args: '' + }; + }, + options: [ + { + text: "Skip Intro", + onclick: async () => { + return { + path: PAYLOAD, + args: '-n' + }; + } + } + ] + }; +} diff --git a/Packaging/ps5/sce_sys/icon0.png b/Packaging/ps5/sce_sys/icon0.png new file mode 100644 index 0000000000000000000000000000000000000000..14566fc13b9feeb4f31a99b3d385895a409dacb9 GIT binary patch literal 45131 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 `RciAr;wxdDVruFSCR!ZrtNo}!mv{WK&U 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 literal 0 HcmV?d00001 diff --git a/Source/storm/storm.cpp b/Source/storm/storm.cpp index 1d463e4f401..188d997460a 100644 --- a/Source/storm/storm.cpp +++ b/Source/storm/storm.cpp @@ -88,7 +88,7 @@ HANDLE SFileOpenFile(const char* filename) void SStrCopy(char* dest, const char* src, int max_length) { -#ifndef __AMIGA__ +#ifndef NOMEMCCPY if (memccpy(dest, src, '\0', max_length) == NULL) dest[max_length - 1] = '\0'; #else diff --git a/tools/patcher/storm/storm.cpp b/tools/patcher/storm/storm.cpp index e7ecd28e955..01120f2c1a5 100644 --- a/tools/patcher/storm/storm.cpp +++ b/tools/patcher/storm/storm.cpp @@ -83,7 +83,7 @@ HANDLE SFileOpenFile(const char* filename) void SStrCopy(char* dest, const char* src, int max_length) { -#ifndef __AMIGA__ +#ifndef NOMEMCCPY if (memccpy(dest, src, '\0', max_length) == NULL) dest[max_length - 1] = '\0'; #else From 71781f4f0b9394c79b598cbab522e9bbe3e6acfd Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 3 Sep 2024 08:30:25 +0200 Subject: [PATCH 533/596] sort the entries of CrawlTable by distance --- Source/debug.cpp | 17 +- Source/lighting.cpp | 682 ++++++++++++++++++++++---------------------- 2 files changed, 355 insertions(+), 344 deletions(-) diff --git a/Source/debug.cpp b/Source/debug.cpp index cb2a60c7ebb..1e09117f7d2 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -178,7 +178,7 @@ static bool HasUniqueItemReq(const UniqItemData& ui, BYTE pow) return false; } -static bool lessCrawlTableEntry(const POS32 *a, const POS32 *b) +/*static bool lessCrawlTableEntry(const POS32 *a, const POS32 *b) { if (abs(a->y) != abs(b->y)) return abs(a->y) > abs(b->y); @@ -190,6 +190,13 @@ static bool lessCrawlTableEntry(const POS32 *a, const POS32 *b) return a->x < b->x; } +static bool lessCrawlTableEntryDist(const POS32 *a, const POS32 *b) +{ + int da = a->x * a->x + a->y * a->y; + int db = b->x * b->x + b->y * b->y; + return da < db; +} + static void sortCrawlTable(POS32 *table, unsigned entries, bool (cmpFunc)(const POS32 *a, const POS32 *b)) { if (entries <= 1) @@ -219,6 +226,7 @@ static void sortCrawlTable(POS32 *table, unsigned entries, bool (cmpFunc)(const static void recreateCrawlTable() { constexpr int r = 18; + constexpr int version = 1; int crns[r + 1]; memset(crns, 0, sizeof(crns)); POS32 ctableentries[r + 1][2 * 2 * r * 4]; @@ -240,7 +248,10 @@ static void recreateCrawlTable() } } for (int n = 0; n <= r; n++) { - sortCrawlTable(ctableentries[n], crns[n], lessCrawlTableEntry); + if (version == 0) + sortCrawlTable(ctableentries[n], crns[n], lessCrawlTableEntry); + else + sortCrawlTable(ctableentries[n], crns[n], lessCrawlTableEntryDist); } LogErrorF("const int8_t CrawlTable[%d] = {", total * 2 + r + 1); LogErrorF(" // clang-format off"); @@ -286,7 +297,7 @@ static void recreateCrawlTable() tempstr[strlen(tempstr) - 1] = '\0'; snprintf(tempstr, sizeof(tempstr), "%s };", tempstr); LogErrorF(tempstr); -} +}*/ #endif // DEBUG_DATA void ValidateData() { diff --git a/Source/lighting.cpp b/Source/lighting.cpp index 98e15970a6c..55aad459563 100644 --- a/Source/lighting.cpp +++ b/Source/lighting.cpp @@ -81,364 +81,364 @@ const int8_t CrawlTable[2749] = { 1, // 0 - 0 0, 0, 4, // 1 - 3 - 0, 1, 0, -1, -1, 0, 1, 0, + -1, 0, 0, -1, 0, 1, 1, 0, 16, // 2 - 12 - 0, 2, 0, -2, -1, 2, 1, 2, - -1, -2, 1, -2, -1, 1, 1, 1, - -1, -1, 1, -1, -2, 1, 2, 1, - -2, -1, 2, -1, -2, 0, 2, 0, + -1, -1, -1, 1, 1, -1, 1, 1, + -2, 0, 0, -2, 0, 2, 2, 0, + -2, -1, -2, 1, -1, -2, -1, 2, + 1, -2, 1, 2, 2, -1, 2, 1, 24, // 3 - 45 - 0, 3, 0, -3, -1, 3, 1, 3, - -1, -3, 1, -3, -2, 3, 2, 3, - -2, -3, 2, -3, -2, 2, 2, 2, - -2, -2, 2, -2, -3, 2, 3, 2, - -3, -2, 3, -2, -3, 1, 3, 1, - -3, -1, 3, -1, -3, 0, 3, 0, + -2, -2, -2, 2, 2, -2, 2, 2, + -3, 0, 0, -3, 0, 3, 3, 0, + -3, -1, -3, 1, -1, -3, -1, 3, + 1, -3, 1, 3, 3, -1, 3, 1, + -3, -2, -3, 2, -2, -3, -2, 3, + 2, -3, 2, 3, 3, -2, 3, 2, 32, // 4 - 94 - 0, 4, 0, -4, -1, 4, 1, 4, - -1, -4, 1, -4, -2, 4, 2, 4, - -2, -4, 2, -4, -3, 4, 3, 4, - -3, -4, 3, -4, -3, 3, 3, 3, - -3, -3, 3, -3, -4, 3, 4, 3, - -4, -3, 4, -3, -4, 2, 4, 2, - -4, -2, 4, -2, -4, 1, 4, 1, - -4, -1, 4, -1, -4, 0, 4, 0, + -4, 0, 0, -4, 0, 4, 4, 0, + -4, -1, -4, 1, -1, -4, -1, 4, + 1, -4, 1, 4, 4, -1, 4, 1, + -3, -3, -3, 3, 3, -3, 3, 3, + -4, -2, -4, 2, -2, -4, -2, 4, + 2, -4, 2, 4, 4, -2, 4, 2, + -4, -3, -4, 3, -3, -4, -3, 4, + 3, -4, 3, 4, 4, -3, 4, 3, 40, // 5 - 159 - 0, 5, 0, -5, -1, 5, 1, 5, - -1, -5, 1, -5, -2, 5, 2, 5, - -2, -5, 2, -5, -3, 5, 3, 5, - -3, -5, 3, -5, -4, 5, 4, 5, - -4, -5, 4, -5, -4, 4, 4, 4, - -4, -4, 4, -4, -5, 4, 5, 4, - -5, -4, 5, -4, -5, 3, 5, 3, - -5, -3, 5, -3, -5, 2, 5, 2, - -5, -2, 5, -2, -5, 1, 5, 1, - -5, -1, 5, -1, -5, 0, 5, 0, + -5, 0, 0, -5, 0, 5, 5, 0, + -5, -1, -5, 1, -1, -5, -1, 5, + 1, -5, 1, 5, 5, -1, 5, 1, + -5, -2, -5, 2, -2, -5, -2, 5, + 2, -5, 2, 5, 5, -2, 5, 2, + -4, -4, -4, 4, 4, -4, 4, 4, + -5, -3, -5, 3, -3, -5, -3, 5, + 3, -5, 3, 5, 5, -3, 5, 3, + -5, -4, -5, 4, -4, -5, -4, 5, + 4, -5, 4, 5, 5, -4, 5, 4, 48, // 6 - 240 - 0, 6, 0, -6, -1, 6, 1, 6, - -1, -6, 1, -6, -2, 6, 2, 6, - -2, -6, 2, -6, -3, 6, 3, 6, - -3, -6, 3, -6, -4, 6, 4, 6, - -4, -6, 4, -6, -5, 6, 5, 6, - -5, -6, 5, -6, -5, 5, 5, 5, - -5, -5, 5, -5, -6, 5, 6, 5, - -6, -5, 6, -5, -6, 4, 6, 4, - -6, -4, 6, -4, -6, 3, 6, 3, - -6, -3, 6, -3, -6, 2, 6, 2, - -6, -2, 6, -2, -6, 1, 6, 1, - -6, -1, 6, -1, -6, 0, 6, 0, + -6, 0, 0, -6, 0, 6, 6, 0, + -6, -1, -6, 1, -1, -6, -1, 6, + 1, -6, 1, 6, 6, -1, 6, 1, + -6, -2, -6, 2, -2, -6, -2, 6, + 2, -6, 2, 6, 6, -2, 6, 2, + -6, -3, -6, 3, -3, -6, -3, 6, + 3, -6, 3, 6, 6, -3, 6, 3, + -5, -5, -5, 5, 5, -5, 5, 5, + -6, -4, -6, 4, -4, -6, -4, 6, + 4, -6, 4, 6, 6, -4, 6, 4, + -6, -5, -6, 5, -5, -6, -5, 6, + 5, -6, 5, 6, 6, -5, 6, 5, 56, // 7 - 337 - 0, 7, 0, -7, -1, 7, 1, 7, - -1, -7, 1, -7, -2, 7, 2, 7, - -2, -7, 2, -7, -3, 7, 3, 7, - -3, -7, 3, -7, -4, 7, 4, 7, - -4, -7, 4, -7, -5, 7, 5, 7, - -5, -7, 5, -7, -6, 7, 6, 7, - -6, -7, 6, -7, -6, 6, 6, 6, - -6, -6, 6, -6, -7, 6, 7, 6, - -7, -6, 7, -6, -7, 5, 7, 5, - -7, -5, 7, -5, -7, 4, 7, 4, - -7, -4, 7, -4, -7, 3, 7, 3, - -7, -3, 7, -3, -7, 2, 7, 2, - -7, -2, 7, -2, -7, 1, 7, 1, - -7, -1, 7, -1, -7, 0, 7, 0, + -7, 0, 0, -7, 0, 7, 7, 0, + -7, -1, -7, 1, -1, -7, -1, 7, + 1, -7, 1, 7, 7, -1, 7, 1, + -7, -2, -7, 2, -2, -7, -2, 7, + 2, -7, 2, 7, 7, -2, 7, 2, + -7, -3, -7, 3, -3, -7, -3, 7, + 3, -7, 3, 7, 7, -3, 7, 3, + -7, -4, -7, 4, -4, -7, -4, 7, + 4, -7, 4, 7, 7, -4, 7, 4, + -6, -6, -6, 6, 6, -6, 6, 6, + -7, -5, -7, 5, -5, -7, -5, 7, + 5, -7, 5, 7, 7, -5, 7, 5, + -7, -6, -7, 6, -6, -7, -6, 7, + 6, -7, 6, 7, 7, -6, 7, 6, 64, // 8 - 450 - 0, 8, 0, -8, -1, 8, 1, 8, - -1, -8, 1, -8, -2, 8, 2, 8, - -2, -8, 2, -8, -3, 8, 3, 8, - -3, -8, 3, -8, -4, 8, 4, 8, - -4, -8, 4, -8, -5, 8, 5, 8, - -5, -8, 5, -8, -6, 8, 6, 8, - -6, -8, 6, -8, -7, 8, 7, 8, - -7, -8, 7, -8, -7, 7, 7, 7, - -7, -7, 7, -7, -8, 7, 8, 7, - -8, -7, 8, -7, -8, 6, 8, 6, - -8, -6, 8, -6, -8, 5, 8, 5, - -8, -5, 8, -5, -8, 4, 8, 4, - -8, -4, 8, -4, -8, 3, 8, 3, - -8, -3, 8, -3, -8, 2, 8, 2, - -8, -2, 8, -2, -8, 1, 8, 1, - -8, -1, 8, -1, -8, 0, 8, 0, + -8, 0, 0, -8, 0, 8, 8, 0, + -8, -1, -8, 1, -1, -8, -1, 8, + 1, -8, 1, 8, 8, -1, 8, 1, + -8, -2, -8, 2, -2, -8, -2, 8, + 2, -8, 2, 8, 8, -2, 8, 2, + -8, -3, -8, 3, -3, -8, -3, 8, + 3, -8, 3, 8, 8, -3, 8, 3, + -8, -4, -8, 4, -4, -8, -4, 8, + 4, -8, 4, 8, 8, -4, 8, 4, + -8, -5, -8, 5, -5, -8, -5, 8, + 5, -8, 5, 8, 8, -5, 8, 5, + -7, -7, -7, 7, 7, -7, 7, 7, + -8, -6, -8, 6, -6, -8, -6, 8, + 6, -8, 6, 8, 8, -6, 8, 6, + -8, -7, -8, 7, -7, -8, -7, 8, + 7, -8, 7, 8, 8, -7, 8, 7, 72, // 9 - 579 - 0, 9, 0, -9, -1, 9, 1, 9, - -1, -9, 1, -9, -2, 9, 2, 9, - -2, -9, 2, -9, -3, 9, 3, 9, - -3, -9, 3, -9, -4, 9, 4, 9, - -4, -9, 4, -9, -5, 9, 5, 9, - -5, -9, 5, -9, -6, 9, 6, 9, - -6, -9, 6, -9, -7, 9, 7, 9, - -7, -9, 7, -9, -8, 9, 8, 9, - -8, -9, 8, -9, -8, 8, 8, 8, - -8, -8, 8, -8, -9, 8, 9, 8, - -9, -8, 9, -8, -9, 7, 9, 7, - -9, -7, 9, -7, -9, 6, 9, 6, - -9, -6, 9, -6, -9, 5, 9, 5, - -9, -5, 9, -5, -9, 4, 9, 4, - -9, -4, 9, -4, -9, 3, 9, 3, - -9, -3, 9, -3, -9, 2, 9, 2, - -9, -2, 9, -2, -9, 1, 9, 1, - -9, -1, 9, -1, -9, 0, 9, 0, + -9, 0, 0, -9, 0, 9, 9, 0, + -9, -1, -9, 1, -1, -9, -1, 9, + 1, -9, 1, 9, 9, -1, 9, 1, + -9, -2, -9, 2, -2, -9, -2, 9, + 2, -9, 2, 9, 9, -2, 9, 2, + -9, -3, -9, 3, -3, -9, -3, 9, + 3, -9, 3, 9, 9, -3, 9, 3, + -9, -4, -9, 4, -4, -9, -4, 9, + 4, -9, 4, 9, 9, -4, 9, 4, + -9, -5, -9, 5, -5, -9, -5, 9, + 5, -9, 5, 9, 9, -5, 9, 5, + -9, -6, -9, 6, -6, -9, -6, 9, + 6, -9, 6, 9, 9, -6, 9, 6, + -8, -8, -8, 8, 8, -8, 8, 8, + -9, -7, -9, 7, -7, -9, -7, 9, + 7, -9, 7, 9, 9, -7, 9, 7, + -9, -8, -9, 8, -8, -9, -8, 9, + 8, -9, 8, 9, 9, -8, 9, 8, 80, // 10 - 724 - 0, 10, 0,-10, -1, 10, 1, 10, - -1,-10, 1,-10, -2, 10, 2, 10, - -2,-10, 2,-10, -3, 10, 3, 10, - -3,-10, 3,-10, -4, 10, 4, 10, - -4,-10, 4,-10, -5, 10, 5, 10, - -5,-10, 5,-10, -6, 10, 6, 10, - -6,-10, 6,-10, -7, 10, 7, 10, - -7,-10, 7,-10, -8, 10, 8, 10, - -8,-10, 8,-10, -9, 10, 9, 10, - -9,-10, 9,-10, -9, 9, 9, 9, - -9, -9, 9, -9, -10, 9, 10, 9, - -10, -9, 10, -9, -10, 8, 10, 8, - -10, -8, 10, -8, -10, 7, 10, 7, - -10, -7, 10, -7, -10, 6, 10, 6, - -10, -6, 10, -6, -10, 5, 10, 5, - -10, -5, 10, -5, -10, 4, 10, 4, - -10, -4, 10, -4, -10, 3, 10, 3, - -10, -3, 10, -3, -10, 2, 10, 2, - -10, -2, 10, -2, -10, 1, 10, 1, - -10, -1, 10, -1, -10, 0, 10, 0, + -10, 0, 0,-10, 0, 10, 10, 0, + -10, -1, -10, 1, -1,-10, -1, 10, + 1,-10, 1, 10, 10, -1, 10, 1, + -10, -2, -10, 2, -2,-10, -2, 10, + 2,-10, 2, 10, 10, -2, 10, 2, + -10, -3, -10, 3, -3,-10, -3, 10, + 3,-10, 3, 10, 10, -3, 10, 3, + -10, -4, -10, 4, -4,-10, -4, 10, + 4,-10, 4, 10, 10, -4, 10, 4, + -10, -5, -10, 5, -5,-10, -5, 10, + 5,-10, 5, 10, 10, -5, 10, 5, + -10, -6, -10, 6, -6,-10, -6, 10, + 6,-10, 6, 10, 10, -6, 10, 6, + -10, -7, -10, 7, -7,-10, -7, 10, + 7,-10, 7, 10, 10, -7, 10, 7, + -9, -9, -9, 9, 9, -9, 9, 9, + -10, -8, -10, 8, -8,-10, -8, 10, + 8,-10, 8, 10, 10, -8, 10, 8, + -10, -9, -10, 9, -9,-10, -9, 10, + 9,-10, 9, 10, 10, -9, 10, 9, 88, // 11 - 885 - 0, 11, 0,-11, -1, 11, 1, 11, - -1,-11, 1,-11, -2, 11, 2, 11, - -2,-11, 2,-11, -3, 11, 3, 11, - -3,-11, 3,-11, -4, 11, 4, 11, - -4,-11, 4,-11, -5, 11, 5, 11, - -5,-11, 5,-11, -6, 11, 6, 11, - -6,-11, 6,-11, -7, 11, 7, 11, - -7,-11, 7,-11, -8, 11, 8, 11, - -8,-11, 8,-11, -9, 11, 9, 11, - -9,-11, 9,-11, -10, 11, 10, 11, - -10,-11, 10,-11, -10, 10, 10, 10, - -10,-10, 10,-10, -11, 10, 11, 10, - -11,-10, 11,-10, -11, 9, 11, 9, - -11, -9, 11, -9, -11, 8, 11, 8, - -11, -8, 11, -8, -11, 7, 11, 7, - -11, -7, 11, -7, -11, 6, 11, 6, - -11, -6, 11, -6, -11, 5, 11, 5, - -11, -5, 11, -5, -11, 4, 11, 4, - -11, -4, 11, -4, -11, 3, 11, 3, - -11, -3, 11, -3, -11, 2, 11, 2, - -11, -2, 11, -2, -11, 1, 11, 1, - -11, -1, 11, -1, -11, 0, 11, 0, + -11, 0, 0,-11, 0, 11, 11, 0, + -11, -1, -11, 1, -1,-11, -1, 11, + 1,-11, 1, 11, 11, -1, 11, 1, + -11, -2, -11, 2, -2,-11, -2, 11, + 2,-11, 2, 11, 11, -2, 11, 2, + -11, -3, -11, 3, -3,-11, -3, 11, + 3,-11, 3, 11, 11, -3, 11, 3, + -11, -4, -11, 4, -4,-11, -4, 11, + 4,-11, 4, 11, 11, -4, 11, 4, + -11, -5, -11, 5, -5,-11, -5, 11, + 5,-11, 5, 11, 11, -5, 11, 5, + -11, -6, -11, 6, -6,-11, -6, 11, + 6,-11, 6, 11, 11, -6, 11, 6, + -11, -7, -11, 7, -7,-11, -7, 11, + 7,-11, 7, 11, 11, -7, 11, 7, + -11, -8, -11, 8, -8,-11, -8, 11, + 8,-11, 8, 11, 11, -8, 11, 8, + -10,-10, -10, 10, 10,-10, 10, 10, + -11, -9, -11, 9, -9,-11, -9, 11, + 9,-11, 9, 11, 11, -9, 11, 9, + -11,-10, -11, 10, -10,-11, -10, 11, + 10,-11, 10, 11, 11,-10, 11, 10, 96, // 12 - 1062 - 0, 12, 0,-12, -1, 12, 1, 12, - -1,-12, 1,-12, -2, 12, 2, 12, - -2,-12, 2,-12, -3, 12, 3, 12, - -3,-12, 3,-12, -4, 12, 4, 12, - -4,-12, 4,-12, -5, 12, 5, 12, - -5,-12, 5,-12, -6, 12, 6, 12, - -6,-12, 6,-12, -7, 12, 7, 12, - -7,-12, 7,-12, -8, 12, 8, 12, - -8,-12, 8,-12, -9, 12, 9, 12, - -9,-12, 9,-12, -10, 12, 10, 12, - -10,-12, 10,-12, -11, 12, 11, 12, - -11,-12, 11,-12, -11, 11, 11, 11, - -11,-11, 11,-11, -12, 11, 12, 11, - -12,-11, 12,-11, -12, 10, 12, 10, - -12,-10, 12,-10, -12, 9, 12, 9, - -12, -9, 12, -9, -12, 8, 12, 8, - -12, -8, 12, -8, -12, 7, 12, 7, - -12, -7, 12, -7, -12, 6, 12, 6, - -12, -6, 12, -6, -12, 5, 12, 5, - -12, -5, 12, -5, -12, 4, 12, 4, - -12, -4, 12, -4, -12, 3, 12, 3, - -12, -3, 12, -3, -12, 2, 12, 2, - -12, -2, 12, -2, -12, 1, 12, 1, - -12, -1, 12, -1, -12, 0, 12, 0, + -12, 0, 0,-12, 0, 12, 12, 0, + -12, -1, -12, 1, -1,-12, -1, 12, + 1,-12, 1, 12, 12, -1, 12, 1, + -12, -2, -12, 2, -2,-12, -2, 12, + 2,-12, 2, 12, 12, -2, 12, 2, + -12, -3, -12, 3, -3,-12, -3, 12, + 3,-12, 3, 12, 12, -3, 12, 3, + -12, -4, -12, 4, -4,-12, -4, 12, + 4,-12, 4, 12, 12, -4, 12, 4, + -12, -5, -12, 5, -5,-12, -5, 12, + 5,-12, 5, 12, 12, -5, 12, 5, + -12, -6, -12, 6, -6,-12, -6, 12, + 6,-12, 6, 12, 12, -6, 12, 6, + -12, -7, -12, 7, -7,-12, -7, 12, + 7,-12, 7, 12, 12, -7, 12, 7, + -12, -8, -12, 8, -8,-12, -8, 12, + 8,-12, 8, 12, 12, -8, 12, 8, + -12, -9, -12, 9, -9,-12, -9, 12, + 9,-12, 9, 12, 12, -9, 12, 9, + -11,-11, -11, 11, 11,-11, 11, 11, + -12,-10, -12, 10, -10,-12, -10, 12, + 10,-12, 10, 12, 12,-10, 12, 10, + -12,-11, -12, 11, -11,-12, -11, 12, + 11,-12, 11, 12, 12,-11, 12, 11, 104, // 13 - 1255 - 0, 13, 0,-13, -1, 13, 1, 13, - -1,-13, 1,-13, -2, 13, 2, 13, - -2,-13, 2,-13, -3, 13, 3, 13, - -3,-13, 3,-13, -4, 13, 4, 13, - -4,-13, 4,-13, -5, 13, 5, 13, - -5,-13, 5,-13, -6, 13, 6, 13, - -6,-13, 6,-13, -7, 13, 7, 13, - -7,-13, 7,-13, -8, 13, 8, 13, - -8,-13, 8,-13, -9, 13, 9, 13, - -9,-13, 9,-13, -10, 13, 10, 13, - -10,-13, 10,-13, -11, 13, 11, 13, - -11,-13, 11,-13, -12, 13, 12, 13, - -12,-13, 12,-13, -12, 12, 12, 12, - -12,-12, 12,-12, -13, 12, 13, 12, - -13,-12, 13,-12, -13, 11, 13, 11, - -13,-11, 13,-11, -13, 10, 13, 10, - -13,-10, 13,-10, -13, 9, 13, 9, - -13, -9, 13, -9, -13, 8, 13, 8, - -13, -8, 13, -8, -13, 7, 13, 7, - -13, -7, 13, -7, -13, 6, 13, 6, - -13, -6, 13, -6, -13, 5, 13, 5, - -13, -5, 13, -5, -13, 4, 13, 4, - -13, -4, 13, -4, -13, 3, 13, 3, - -13, -3, 13, -3, -13, 2, 13, 2, - -13, -2, 13, -2, -13, 1, 13, 1, - -13, -1, 13, -1, -13, 0, 13, 0, + -13, 0, 0,-13, 0, 13, 13, 0, + -13, -1, -13, 1, -1,-13, -1, 13, + 1,-13, 1, 13, 13, -1, 13, 1, + -13, -2, -13, 2, -2,-13, -2, 13, + 2,-13, 2, 13, 13, -2, 13, 2, + -13, -3, -13, 3, -3,-13, -3, 13, + 3,-13, 3, 13, 13, -3, 13, 3, + -13, -4, -13, 4, -4,-13, -4, 13, + 4,-13, 4, 13, 13, -4, 13, 4, + -13, -5, -13, 5, -5,-13, -5, 13, + 5,-13, 5, 13, 13, -5, 13, 5, + -13, -6, -13, 6, -6,-13, -6, 13, + 6,-13, 6, 13, 13, -6, 13, 6, + -13, -7, -13, 7, -7,-13, -7, 13, + 7,-13, 7, 13, 13, -7, 13, 7, + -13, -8, -13, 8, -8,-13, -8, 13, + 8,-13, 8, 13, 13, -8, 13, 8, + -13, -9, -13, 9, -9,-13, -9, 13, + 9,-13, 9, 13, 13, -9, 13, 9, + -13,-10, -13, 10, -10,-13, -10, 13, + 10,-13, 10, 13, 13,-10, 13, 10, + -12,-12, -12, 12, 12,-12, 12, 12, + -13,-11, -13, 11, -11,-13, -11, 13, + 11,-13, 11, 13, 13,-11, 13, 11, + -13,-12, -13, 12, -12,-13, -12, 13, + 12,-13, 12, 13, 13,-12, 13, 12, 112, // 14 - 1464 - 0, 14, 0,-14, -1, 14, 1, 14, - -1,-14, 1,-14, -2, 14, 2, 14, - -2,-14, 2,-14, -3, 14, 3, 14, - -3,-14, 3,-14, -4, 14, 4, 14, - -4,-14, 4,-14, -5, 14, 5, 14, - -5,-14, 5,-14, -6, 14, 6, 14, - -6,-14, 6,-14, -7, 14, 7, 14, - -7,-14, 7,-14, -8, 14, 8, 14, - -8,-14, 8,-14, -9, 14, 9, 14, - -9,-14, 9,-14, -10, 14, 10, 14, - -10,-14, 10,-14, -11, 14, 11, 14, - -11,-14, 11,-14, -12, 14, 12, 14, - -12,-14, 12,-14, -13, 14, 13, 14, - -13,-14, 13,-14, -13, 13, 13, 13, - -13,-13, 13,-13, -14, 13, 14, 13, - -14,-13, 14,-13, -14, 12, 14, 12, - -14,-12, 14,-12, -14, 11, 14, 11, - -14,-11, 14,-11, -14, 10, 14, 10, - -14,-10, 14,-10, -14, 9, 14, 9, - -14, -9, 14, -9, -14, 8, 14, 8, - -14, -8, 14, -8, -14, 7, 14, 7, - -14, -7, 14, -7, -14, 6, 14, 6, - -14, -6, 14, -6, -14, 5, 14, 5, - -14, -5, 14, -5, -14, 4, 14, 4, - -14, -4, 14, -4, -14, 3, 14, 3, - -14, -3, 14, -3, -14, 2, 14, 2, - -14, -2, 14, -2, -14, 1, 14, 1, - -14, -1, 14, -1, -14, 0, 14, 0, + -14, 0, 0,-14, 0, 14, 14, 0, + -14, -1, -14, 1, -1,-14, -1, 14, + 1,-14, 1, 14, 14, -1, 14, 1, + -14, -2, -14, 2, -2,-14, -2, 14, + 2,-14, 2, 14, 14, -2, 14, 2, + -14, -3, -14, 3, -3,-14, -3, 14, + 3,-14, 3, 14, 14, -3, 14, 3, + -14, -4, -14, 4, -4,-14, -4, 14, + 4,-14, 4, 14, 14, -4, 14, 4, + -14, -5, -14, 5, -5,-14, -5, 14, + 5,-14, 5, 14, 14, -5, 14, 5, + -14, -6, -14, 6, -6,-14, -6, 14, + 6,-14, 6, 14, 14, -6, 14, 6, + -14, -7, -14, 7, -7,-14, -7, 14, + 7,-14, 7, 14, 14, -7, 14, 7, + -14, -8, -14, 8, -8,-14, -8, 14, + 8,-14, 8, 14, 14, -8, 14, 8, + -14, -9, -14, 9, -9,-14, -9, 14, + 9,-14, 9, 14, 14, -9, 14, 9, + -14,-10, -14, 10, -10,-14, -10, 14, + 10,-14, 10, 14, 14,-10, 14, 10, + -14,-11, -14, 11, -11,-14, -11, 14, + 11,-14, 11, 14, 14,-11, 14, 11, + -13,-13, -13, 13, 13,-13, 13, 13, + -14,-12, -14, 12, -12,-14, -12, 14, + 12,-14, 12, 14, 14,-12, 14, 12, + -14,-13, -14, 13, -13,-14, -13, 14, + 13,-14, 13, 14, 14,-13, 14, 13, 120, // 15 - 1689 - 0, 15, 0,-15, -1, 15, 1, 15, - -1,-15, 1,-15, -2, 15, 2, 15, - -2,-15, 2,-15, -3, 15, 3, 15, - -3,-15, 3,-15, -4, 15, 4, 15, - -4,-15, 4,-15, -5, 15, 5, 15, - -5,-15, 5,-15, -6, 15, 6, 15, - -6,-15, 6,-15, -7, 15, 7, 15, - -7,-15, 7,-15, -8, 15, 8, 15, - -8,-15, 8,-15, -9, 15, 9, 15, - -9,-15, 9,-15, -10, 15, 10, 15, - -10,-15, 10,-15, -11, 15, 11, 15, - -11,-15, 11,-15, -12, 15, 12, 15, - -12,-15, 12,-15, -13, 15, 13, 15, - -13,-15, 13,-15, -14, 15, 14, 15, - -14,-15, 14,-15, -14, 14, 14, 14, - -14,-14, 14,-14, -15, 14, 15, 14, - -15,-14, 15,-14, -15, 13, 15, 13, - -15,-13, 15,-13, -15, 12, 15, 12, - -15,-12, 15,-12, -15, 11, 15, 11, - -15,-11, 15,-11, -15, 10, 15, 10, - -15,-10, 15,-10, -15, 9, 15, 9, - -15, -9, 15, -9, -15, 8, 15, 8, - -15, -8, 15, -8, -15, 7, 15, 7, - -15, -7, 15, -7, -15, 6, 15, 6, - -15, -6, 15, -6, -15, 5, 15, 5, - -15, -5, 15, -5, -15, 4, 15, 4, - -15, -4, 15, -4, -15, 3, 15, 3, - -15, -3, 15, -3, -15, 2, 15, 2, - -15, -2, 15, -2, -15, 1, 15, 1, - -15, -1, 15, -1, -15, 0, 15, 0, + -15, 0, 0,-15, 0, 15, 15, 0, + -15, -1, -15, 1, -1,-15, -1, 15, + 1,-15, 1, 15, 15, -1, 15, 1, + -15, -2, -15, 2, -2,-15, -2, 15, + 2,-15, 2, 15, 15, -2, 15, 2, + -15, -3, -15, 3, -3,-15, -3, 15, + 3,-15, 3, 15, 15, -3, 15, 3, + -15, -4, -15, 4, -4,-15, -4, 15, + 4,-15, 4, 15, 15, -4, 15, 4, + -15, -5, -15, 5, -5,-15, -5, 15, + 5,-15, 5, 15, 15, -5, 15, 5, + -15, -6, -15, 6, -6,-15, -6, 15, + 6,-15, 6, 15, 15, -6, 15, 6, + -15, -7, -15, 7, -7,-15, -7, 15, + 7,-15, 7, 15, 15, -7, 15, 7, + -15, -8, -15, 8, -8,-15, -8, 15, + 8,-15, 8, 15, 15, -8, 15, 8, + -15, -9, -15, 9, -9,-15, -9, 15, + 9,-15, 9, 15, 15, -9, 15, 9, + -15,-10, -15, 10, -10,-15, -10, 15, + 10,-15, 10, 15, 15,-10, 15, 10, + -15,-11, -15, 11, -11,-15, -11, 15, + 11,-15, 11, 15, 15,-11, 15, 11, + -15,-12, -15, 12, -12,-15, -12, 15, + 12,-15, 12, 15, 15,-12, 15, 12, + -14,-14, -14, 14, 14,-14, 14, 14, + -15,-13, -15, 13, -13,-15, -13, 15, + 13,-15, 13, 15, 15,-13, 15, 13, + -15,-14, -15, 14, -14,-15, -14, 15, + 14,-15, 14, 15, 15,-14, 15, 14, (int8_t)128, // 16 - 1930 - 0, 16, 0,-16, -1, 16, 1, 16, - -1,-16, 1,-16, -2, 16, 2, 16, - -2,-16, 2,-16, -3, 16, 3, 16, - -3,-16, 3,-16, -4, 16, 4, 16, - -4,-16, 4,-16, -5, 16, 5, 16, - -5,-16, 5,-16, -6, 16, 6, 16, - -6,-16, 6,-16, -7, 16, 7, 16, - -7,-16, 7,-16, -8, 16, 8, 16, - -8,-16, 8,-16, -9, 16, 9, 16, - -9,-16, 9,-16, -10, 16, 10, 16, - -10,-16, 10,-16, -11, 16, 11, 16, - -11,-16, 11,-16, -12, 16, 12, 16, - -12,-16, 12,-16, -13, 16, 13, 16, - -13,-16, 13,-16, -14, 16, 14, 16, - -14,-16, 14,-16, -15, 16, 15, 16, - -15,-16, 15,-16, -15, 15, 15, 15, - -15,-15, 15,-15, -16, 15, 16, 15, - -16,-15, 16,-15, -16, 14, 16, 14, - -16,-14, 16,-14, -16, 13, 16, 13, - -16,-13, 16,-13, -16, 12, 16, 12, - -16,-12, 16,-12, -16, 11, 16, 11, - -16,-11, 16,-11, -16, 10, 16, 10, - -16,-10, 16,-10, -16, 9, 16, 9, - -16, -9, 16, -9, -16, 8, 16, 8, - -16, -8, 16, -8, -16, 7, 16, 7, - -16, -7, 16, -7, -16, 6, 16, 6, - -16, -6, 16, -6, -16, 5, 16, 5, - -16, -5, 16, -5, -16, 4, 16, 4, - -16, -4, 16, -4, -16, 3, 16, 3, - -16, -3, 16, -3, -16, 2, 16, 2, - -16, -2, 16, -2, -16, 1, 16, 1, - -16, -1, 16, -1, -16, 0, 16, 0, + -16, 0, 0,-16, 0, 16, 16, 0, + -16, -1, -16, 1, -1,-16, -1, 16, + 1,-16, 1, 16, 16, -1, 16, 1, + -16, -2, -16, 2, -2,-16, -2, 16, + 2,-16, 2, 16, 16, -2, 16, 2, + -16, -3, -16, 3, -3,-16, -3, 16, + 3,-16, 3, 16, 16, -3, 16, 3, + -16, -4, -16, 4, -4,-16, -4, 16, + 4,-16, 4, 16, 16, -4, 16, 4, + -16, -5, -16, 5, -5,-16, -5, 16, + 5,-16, 5, 16, 16, -5, 16, 5, + -16, -6, -16, 6, -6,-16, -6, 16, + 6,-16, 6, 16, 16, -6, 16, 6, + -16, -7, -16, 7, -7,-16, -7, 16, + 7,-16, 7, 16, 16, -7, 16, 7, + -16, -8, -16, 8, -8,-16, -8, 16, + 8,-16, 8, 16, 16, -8, 16, 8, + -16, -9, -16, 9, -9,-16, -9, 16, + 9,-16, 9, 16, 16, -9, 16, 9, + -16,-10, -16, 10, -10,-16, -10, 16, + 10,-16, 10, 16, 16,-10, 16, 10, + -16,-11, -16, 11, -11,-16, -11, 16, + 11,-16, 11, 16, 16,-11, 16, 11, + -16,-12, -16, 12, -12,-16, -12, 16, + 12,-16, 12, 16, 16,-12, 16, 12, + -16,-13, -16, 13, -13,-16, -13, 16, + 13,-16, 13, 16, 16,-13, 16, 13, + -15,-15, -15, 15, 15,-15, 15, 15, + -16,-14, -16, 14, -14,-16, -14, 16, + 14,-16, 14, 16, 16,-14, 16, 14, + -16,-15, -16, 15, -15,-16, -15, 16, + 15,-16, 15, 16, 16,-15, 16, 15, (int8_t)136, // 17 - 2187 - 0, 17, 0,-17, -1, 17, 1, 17, - -1,-17, 1,-17, -2, 17, 2, 17, - -2,-17, 2,-17, -3, 17, 3, 17, - -3,-17, 3,-17, -4, 17, 4, 17, - -4,-17, 4,-17, -5, 17, 5, 17, - -5,-17, 5,-17, -6, 17, 6, 17, - -6,-17, 6,-17, -7, 17, 7, 17, - -7,-17, 7,-17, -8, 17, 8, 17, - -8,-17, 8,-17, -9, 17, 9, 17, - -9,-17, 9,-17, -10, 17, 10, 17, - -10,-17, 10,-17, -11, 17, 11, 17, - -11,-17, 11,-17, -12, 17, 12, 17, - -12,-17, 12,-17, -13, 17, 13, 17, - -13,-17, 13,-17, -14, 17, 14, 17, - -14,-17, 14,-17, -15, 17, 15, 17, - -15,-17, 15,-17, -16, 17, 16, 17, - -16,-17, 16,-17, -16, 16, 16, 16, - -16,-16, 16,-16, -17, 16, 17, 16, - -17,-16, 17,-16, -17, 15, 17, 15, - -17,-15, 17,-15, -17, 14, 17, 14, - -17,-14, 17,-14, -17, 13, 17, 13, - -17,-13, 17,-13, -17, 12, 17, 12, - -17,-12, 17,-12, -17, 11, 17, 11, - -17,-11, 17,-11, -17, 10, 17, 10, - -17,-10, 17,-10, -17, 9, 17, 9, - -17, -9, 17, -9, -17, 8, 17, 8, - -17, -8, 17, -8, -17, 7, 17, 7, - -17, -7, 17, -7, -17, 6, 17, 6, - -17, -6, 17, -6, -17, 5, 17, 5, - -17, -5, 17, -5, -17, 4, 17, 4, - -17, -4, 17, -4, -17, 3, 17, 3, - -17, -3, 17, -3, -17, 2, 17, 2, - -17, -2, 17, -2, -17, 1, 17, 1, - -17, -1, 17, -1, -17, 0, 17, 0, + -17, 0, 0,-17, 0, 17, 17, 0, + -17, -1, -17, 1, -1,-17, -1, 17, + 1,-17, 1, 17, 17, -1, 17, 1, + -17, -2, -17, 2, -2,-17, -2, 17, + 2,-17, 2, 17, 17, -2, 17, 2, + -17, -3, -17, 3, -3,-17, -3, 17, + 3,-17, 3, 17, 17, -3, 17, 3, + -17, -4, -17, 4, -4,-17, -4, 17, + 4,-17, 4, 17, 17, -4, 17, 4, + -17, -5, -17, 5, -5,-17, -5, 17, + 5,-17, 5, 17, 17, -5, 17, 5, + -17, -6, -17, 6, -6,-17, -6, 17, + 6,-17, 6, 17, 17, -6, 17, 6, + -17, -7, -17, 7, -7,-17, -7, 17, + 7,-17, 7, 17, 17, -7, 17, 7, + -17, -8, -17, 8, -8,-17, -8, 17, + 8,-17, 8, 17, 17, -8, 17, 8, + -17, -9, -17, 9, -9,-17, -9, 17, + 9,-17, 9, 17, 17, -9, 17, 9, + -17,-10, -17, 10, -10,-17, -10, 17, + 10,-17, 10, 17, 17,-10, 17, 10, + -17,-11, -17, 11, -11,-17, -11, 17, + 11,-17, 11, 17, 17,-11, 17, 11, + -17,-12, -17, 12, -12,-17, -12, 17, + 12,-17, 12, 17, 17,-12, 17, 12, + -17,-13, -17, 13, -13,-17, -13, 17, + 13,-17, 13, 17, 17,-13, 17, 13, + -17,-14, -17, 14, -14,-17, -14, 17, + 14,-17, 14, 17, 17,-14, 17, 14, + -16,-16, -16, 16, 16,-16, 16, 16, + -17,-15, -17, 15, -15,-17, -15, 17, + 15,-17, 15, 17, 17,-15, 17, 15, + -17,-16, -17, 16, -16,-17, -16, 17, + 16,-17, 16, 17, 17,-16, 17, 16, (int8_t)144, // 18 - 2460 - 0, 18, 0,-18, -1, 18, 1, 18, - -1,-18, 1,-18, -2, 18, 2, 18, - -2,-18, 2,-18, -3, 18, 3, 18, - -3,-18, 3,-18, -4, 18, 4, 18, - -4,-18, 4,-18, -5, 18, 5, 18, - -5,-18, 5,-18, -6, 18, 6, 18, - -6,-18, 6,-18, -7, 18, 7, 18, - -7,-18, 7,-18, -8, 18, 8, 18, - -8,-18, 8,-18, -9, 18, 9, 18, - -9,-18, 9,-18, -10, 18, 10, 18, - -10,-18, 10,-18, -11, 18, 11, 18, - -11,-18, 11,-18, -12, 18, 12, 18, - -12,-18, 12,-18, -13, 18, 13, 18, - -13,-18, 13,-18, -14, 18, 14, 18, - -14,-18, 14,-18, -15, 18, 15, 18, - -15,-18, 15,-18, -16, 18, 16, 18, - -16,-18, 16,-18, -17, 18, 17, 18, - -17,-18, 17,-18, -17, 17, 17, 17, - -17,-17, 17,-17, -18, 17, 18, 17, - -18,-17, 18,-17, -18, 16, 18, 16, - -18,-16, 18,-16, -18, 15, 18, 15, - -18,-15, 18,-15, -18, 14, 18, 14, - -18,-14, 18,-14, -18, 13, 18, 13, - -18,-13, 18,-13, -18, 12, 18, 12, - -18,-12, 18,-12, -18, 11, 18, 11, - -18,-11, 18,-11, -18, 10, 18, 10, - -18,-10, 18,-10, -18, 9, 18, 9, - -18, -9, 18, -9, -18, 8, 18, 8, - -18, -8, 18, -8, -18, 7, 18, 7, - -18, -7, 18, -7, -18, 6, 18, 6, - -18, -6, 18, -6, -18, 5, 18, 5, - -18, -5, 18, -5, -18, 4, 18, 4, - -18, -4, 18, -4, -18, 3, 18, 3, - -18, -3, 18, -3, -18, 2, 18, 2, - -18, -2, 18, -2, -18, 1, 18, 1, - -18, -1, 18, -1, -18, 0, 18, 0, + -18, 0, 0,-18, 0, 18, 18, 0, + -18, -1, -18, 1, -1,-18, -1, 18, + 1,-18, 1, 18, 18, -1, 18, 1, + -18, -2, -18, 2, -2,-18, -2, 18, + 2,-18, 2, 18, 18, -2, 18, 2, + -18, -3, -18, 3, -3,-18, -3, 18, + 3,-18, 3, 18, 18, -3, 18, 3, + -18, -4, -18, 4, -4,-18, -4, 18, + 4,-18, 4, 18, 18, -4, 18, 4, + -18, -5, -18, 5, -5,-18, -5, 18, + 5,-18, 5, 18, 18, -5, 18, 5, + -18, -6, -18, 6, -6,-18, -6, 18, + 6,-18, 6, 18, 18, -6, 18, 6, + -18, -7, -18, 7, -7,-18, -7, 18, + 7,-18, 7, 18, 18, -7, 18, 7, + -18, -8, -18, 8, -8,-18, -8, 18, + 8,-18, 8, 18, 18, -8, 18, 8, + -18, -9, -18, 9, -9,-18, -9, 18, + 9,-18, 9, 18, 18, -9, 18, 9, + -18,-10, -18, 10, -10,-18, -10, 18, + 10,-18, 10, 18, 18,-10, 18, 10, + -18,-11, -18, 11, -11,-18, -11, 18, + 11,-18, 11, 18, 18,-11, 18, 11, + -18,-12, -18, 12, -12,-18, -12, 18, + 12,-18, 12, 18, 18,-12, 18, 12, + -18,-13, -18, 13, -13,-18, -13, 18, + 13,-18, 13, 18, 18,-13, 18, 13, + -18,-14, -18, 14, -14,-18, -14, 18, + 14,-18, 14, 18, 18,-14, 18, 14, + -18,-15, -18, 15, -15,-18, -15, 18, + 15,-18, 15, 18, 18,-15, 18, 15, + -17,-17, -17, 17, 17,-17, 17, 17, + -18,-16, -18, 16, -16,-18, -16, 18, + 16,-18, 16, 18, 18,-16, 18, 16, + -18,-17, -18, 17, -17,-18, -17, 18, + 17,-18, 17, 18, 18,-17, 18, 17, // clang-format on }; From abc9c868404a39ee2261d0123ed14395a68f0d59 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 3 Sep 2024 08:41:11 +0200 Subject: [PATCH 534/596] bugfix for vanilla (crawltable vs distance) - calculate the entries of the crawltable based on the distance (except when radius is smaller than 4, to preserve the 'wall-ness' of the firering) --- Source/debug.cpp | 9 +- Source/lighting.cpp | 424 ++++++++++++++++++-------------------------- Source/lighting.h | 2 +- Source/monster.cpp | 4 +- 4 files changed, 188 insertions(+), 251 deletions(-) diff --git a/Source/debug.cpp b/Source/debug.cpp index 1e09117f7d2..4e766c29edb 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -239,6 +239,13 @@ static void recreateCrawlTable() dist = std::max(abs(tx - dx), abs(ty - dy)); if (abs(tx - dx) == abs(ty - dy) && (tx != dx || ty != dy)) dist++; + if (version != 0 && dist > 3) { + dist = (tx - dx) * (tx - dx) + (ty - dy) * (ty - dy); + dist = sqrt((double)dist) + 0.5f; + // if (dist == 1 && (tx != dx || ty != dy)) + // dist++; + } + if (dist <= r) { ctableentries[dist][crns[dist]].x = tx - dx; ctableentries[dist][crns[dist]].y = ty - dy; @@ -427,7 +434,7 @@ void ValidateData() i++; } } - assert(CrawlTable[CrawlNum[4]] == 32); // required by MAI_Scav + assert(CrawlTable[CrawlNum[4]] == 24); // required by MAI_Scav assert(CrawlTable[CrawlNum[3]] == 24); // required by AddNovaC // quests for (i = 0; i < lengthof(AllLevels); i++) { diff --git a/Source/lighting.cpp b/Source/lighting.cpp index 55aad459563..6e04a905765 100644 --- a/Source/lighting.cpp +++ b/Source/lighting.cpp @@ -76,7 +76,7 @@ BYTE ColorTrns[NUM_COLOR_TRNS][NUM_COLORS]; * | 526 * +-------> x */ -const int8_t CrawlTable[2749] = { +const int8_t CrawlTable[2189] = { // clang-format off 1, // 0 - 0 0, 0, @@ -94,356 +94,286 @@ const int8_t CrawlTable[2749] = { 1, -3, 1, 3, 3, -1, 3, 1, -3, -2, -3, 2, -2, -3, -2, 3, 2, -3, 2, 3, 3, -2, 3, 2, - 32, // 4 - 94 + 24, // 4 - 94 -4, 0, 0, -4, 0, 4, 4, 0, -4, -1, -4, 1, -1, -4, -1, 4, 1, -4, 1, 4, 4, -1, 4, 1, -3, -3, -3, 3, 3, -3, 3, 3, -4, -2, -4, 2, -2, -4, -2, 4, 2, -4, 2, 4, 4, -2, 4, 2, - -4, -3, -4, 3, -3, -4, -3, 4, - 3, -4, 3, 4, 4, -3, 4, 3, - 40, // 5 - 159 - -5, 0, 0, -5, 0, 5, 5, 0, + 28, // 5 - 143 + -5, 0, -4, -3, -4, 3, -3, -4, + -3, 4, 0, -5, 0, 5, 3, -4, + 3, 4, 4, -3, 4, 3, 5, 0, -5, -1, -5, 1, -1, -5, -1, 5, 1, -5, 1, 5, 5, -1, 5, 1, -5, -2, -5, 2, -2, -5, -2, 5, 2, -5, 2, 5, 5, -2, 5, 2, + 40, // 6 - 200 -4, -4, -4, 4, 4, -4, 4, 4, -5, -3, -5, 3, -3, -5, -3, 5, 3, -5, 3, 5, 5, -3, 5, 3, - -5, -4, -5, 4, -4, -5, -4, 5, - 4, -5, 4, 5, 5, -4, 5, 4, - 48, // 6 - 240 -6, 0, 0, -6, 0, 6, 6, 0, -6, -1, -6, 1, -1, -6, -1, 6, 1, -6, 1, 6, 6, -1, 6, 1, -6, -2, -6, 2, -2, -6, -2, 6, 2, -6, 2, 6, 6, -2, 6, 2, + -5, -4, -5, 4, -4, -5, -4, 5, + 4, -5, 4, 5, 5, -4, 5, 4, + 40, // 7 - 281 -6, -3, -6, 3, -3, -6, -3, 6, 3, -6, 3, 6, 6, -3, 6, 3, - -5, -5, -5, 5, 5, -5, 5, 5, + -7, 0, 0, -7, 0, 7, 7, 0, + -7, -1, -7, 1, -5, -5, -5, 5, + -1, -7, -1, 7, 1, -7, 1, 7, + 5, -5, 5, 5, 7, -1, 7, 1, -6, -4, -6, 4, -4, -6, -4, 6, 4, -6, 4, 6, 6, -4, 6, 4, - -6, -5, -6, 5, -5, -6, -5, 6, - 5, -6, 5, 6, 6, -5, 6, 5, - 56, // 7 - 337 - -7, 0, 0, -7, 0, 7, 7, 0, - -7, -1, -7, 1, -1, -7, -1, 7, - 1, -7, 1, 7, 7, -1, 7, 1, -7, -2, -7, 2, -2, -7, -2, 7, 2, -7, 2, 7, 7, -2, 7, 2, + 48, // 8 - 362 -7, -3, -7, 3, -3, -7, -3, 7, 3, -7, 3, 7, 7, -3, 7, 3, - -7, -4, -7, 4, -4, -7, -4, 7, - 4, -7, 4, 7, 7, -4, 7, 4, - -6, -6, -6, 6, 6, -6, 6, 6, - -7, -5, -7, 5, -5, -7, -5, 7, - 5, -7, 5, 7, 7, -5, 7, 5, - -7, -6, -7, 6, -6, -7, -6, 7, - 6, -7, 6, 7, 7, -6, 7, 6, - 64, // 8 - 450 + -6, -5, -6, 5, -5, -6, -5, 6, + 5, -6, 5, 6, 6, -5, 6, 5, -8, 0, 0, -8, 0, 8, 8, 0, - -8, -1, -8, 1, -1, -8, -1, 8, - 1, -8, 1, 8, 8, -1, 8, 1, + -8, -1, -8, 1, -7, -4, -7, 4, + -4, -7, -4, 7, -1, -8, -1, 8, + 1, -8, 1, 8, 4, -7, 4, 7, + 7, -4, 7, 4, 8, -1, 8, 1, -8, -2, -8, 2, -2, -8, -2, 8, 2, -8, 2, 8, 8, -2, 8, 2, + -6, -6, -6, 6, 6, -6, 6, 6, + 68, // 9 - 459 -8, -3, -8, 3, -3, -8, -3, 8, 3, -8, 3, 8, 8, -3, 8, 3, + -7, -5, -7, 5, -5, -7, -5, 7, + 5, -7, 5, 7, 7, -5, 7, 5, -8, -4, -8, 4, -4, -8, -4, 8, 4, -8, 4, 8, 8, -4, 8, 4, - -8, -5, -8, 5, -5, -8, -5, 8, - 5, -8, 5, 8, 8, -5, 8, 5, - -7, -7, -7, 7, 7, -7, 7, 7, - -8, -6, -8, 6, -6, -8, -6, 8, - 6, -8, 6, 8, 8, -6, 8, 6, - -8, -7, -8, 7, -7, -8, -7, 8, - 7, -8, 7, 8, 8, -7, 8, 7, - 72, // 9 - 579 -9, 0, 0, -9, 0, 9, 9, 0, -9, -1, -9, 1, -1, -9, -1, 9, 1, -9, 1, 9, 9, -1, 9, 1, - -9, -2, -9, 2, -2, -9, -2, 9, - 2, -9, 2, 9, 9, -2, 9, 2, + -9, -2, -9, 2, -7, -6, -7, 6, + -6, -7, -6, 7, -2, -9, -2, 9, + 2, -9, 2, 9, 6, -7, 6, 7, + 7, -6, 7, 6, 9, -2, 9, 2, + -8, -5, -8, 5, -5, -8, -5, 8, + 5, -8, 5, 8, 8, -5, 8, 5, -9, -3, -9, 3, -3, -9, -3, 9, 3, -9, 3, 9, 9, -3, 9, 3, + 56, // 10 - 596 -9, -4, -9, 4, -4, -9, -4, 9, 4, -9, 4, 9, 9, -4, 9, 4, - -9, -5, -9, 5, -5, -9, -5, 9, - 5, -9, 5, 9, 9, -5, 9, 5, - -9, -6, -9, 6, -6, -9, -6, 9, - 6, -9, 6, 9, 9, -6, 9, 6, - -8, -8, -8, 8, 8, -8, 8, 8, - -9, -7, -9, 7, -7, -9, -7, 9, - 7, -9, 7, 9, 9, -7, 9, 7, - -9, -8, -9, 8, -8, -9, -8, 9, - 8, -9, 8, 9, 9, -8, 9, 8, - 80, // 10 - 724 - -10, 0, 0,-10, 0, 10, 10, 0, + -7, -7, -7, 7, 7, -7, 7, 7, + -10, 0, -8, -6, -8, 6, -6, -8, + -6, 8, 0,-10, 0, 10, 6, -8, + 6, 8, 8, -6, 8, 6, 10, 0, -10, -1, -10, 1, -1,-10, -1, 10, 1,-10, 1, 10, 10, -1, 10, 1, -10, -2, -10, 2, -2,-10, -2, 10, 2,-10, 2, 10, 10, -2, 10, 2, + -9, -5, -9, 5, -5, -9, -5, 9, + 5, -9, 5, 9, 9, -5, 9, 5, -10, -3, -10, 3, -3,-10, -3, 10, 3,-10, 3, 10, 10, -3, 10, 3, + 72, // 11 - 709 + -8, -7, -8, 7, -7, -8, -7, 8, + 7, -8, 7, 8, 8, -7, 8, 7, -10, -4, -10, 4, -4,-10, -4, 10, 4,-10, 4, 10, 10, -4, 10, 4, - -10, -5, -10, 5, -5,-10, -5, 10, - 5,-10, 5, 10, 10, -5, 10, 5, - -10, -6, -10, 6, -6,-10, -6, 10, - 6,-10, 6, 10, 10, -6, 10, 6, - -10, -7, -10, 7, -7,-10, -7, 10, - 7,-10, 7, 10, 10, -7, 10, 7, - -9, -9, -9, 9, 9, -9, 9, 9, - -10, -8, -10, 8, -8,-10, -8, 10, - 8,-10, 8, 10, 10, -8, 10, 8, - -10, -9, -10, 9, -9,-10, -9, 10, - 9,-10, 9, 10, 10, -9, 10, 9, - 88, // 11 - 885 + -9, -6, -9, 6, -6, -9, -6, 9, + 6, -9, 6, 9, 9, -6, 9, 6, -11, 0, 0,-11, 0, 11, 11, 0, -11, -1, -11, 1, -1,-11, -1, 11, 1,-11, 1, 11, 11, -1, 11, 1, - -11, -2, -11, 2, -2,-11, -2, 11, - 2,-11, 2, 11, 11, -2, 11, 2, - -11, -3, -11, 3, -3,-11, -3, 11, - 3,-11, 3, 11, 11, -3, 11, 3, + -11, -2, -11, 2, -10, -5, -10, 5, + -5,-10, -5, 10, -2,-11, -2, 11, + 2,-11, 2, 11, 5,-10, 5, 10, + 10, -5, 10, 5, 11, -2, 11, 2, + -8, -8, -8, 8, 8, -8, 8, 8, + -11, -3, -11, 3, -9, -7, -9, 7, + -7, -9, -7, 9, -3,-11, -3, 11, + 3,-11, 3, 11, 7, -9, 7, 9, + 9, -7, 9, 7, 11, -3, 11, 3, + 68, // 12 - 854 + -10, -6, -10, 6, -6,-10, -6, 10, + 6,-10, 6, 10, 10, -6, 10, 6, -11, -4, -11, 4, -4,-11, -4, 11, 4,-11, 4, 11, 11, -4, 11, 4, + -12, 0, 0,-12, 0, 12, 12, 0, + -12, -1, -12, 1, -9, -8, -9, 8, + -8, -9, -8, 9, -1,-12, -1, 12, + 1,-12, 1, 12, 8, -9, 8, 9, + 9, -8, 9, 8, 12, -1, 12, 1, -11, -5, -11, 5, -5,-11, -5, 11, 5,-11, 5, 11, 11, -5, 11, 5, - -11, -6, -11, 6, -6,-11, -6, 11, - 6,-11, 6, 11, 11, -6, 11, 6, - -11, -7, -11, 7, -7,-11, -7, 11, - 7,-11, 7, 11, 11, -7, 11, 7, - -11, -8, -11, 8, -8,-11, -8, 11, - 8,-11, 8, 11, 11, -8, 11, 8, - -10,-10, -10, 10, 10,-10, 10, 10, - -11, -9, -11, 9, -9,-11, -9, 11, - 9,-11, 9, 11, 11, -9, 11, 9, - -11,-10, -11, 10, -10,-11, -10, 11, - 10,-11, 10, 11, 11,-10, 11, 10, - 96, // 12 - 1062 - -12, 0, 0,-12, 0, 12, 12, 0, - -12, -1, -12, 1, -1,-12, -1, 12, - 1,-12, 1, 12, 12, -1, 12, 1, -12, -2, -12, 2, -2,-12, -2, 12, 2,-12, 2, 12, 12, -2, 12, 2, + -10, -7, -10, 7, -7,-10, -7, 10, + 7,-10, 7, 10, 10, -7, 10, 7, -12, -3, -12, 3, -3,-12, -3, 12, 3,-12, 3, 12, 12, -3, 12, 3, + 88, // 13 - 991 + -11, -6, -11, 6, -6,-11, -6, 11, + 6,-11, 6, 11, 11, -6, 11, 6, -12, -4, -12, 4, -4,-12, -4, 12, 4,-12, 4, 12, 12, -4, 12, 4, - -12, -5, -12, 5, -5,-12, -5, 12, - 5,-12, 5, 12, 12, -5, 12, 5, - -12, -6, -12, 6, -6,-12, -6, 12, - 6,-12, 6, 12, 12, -6, 12, 6, - -12, -7, -12, 7, -7,-12, -7, 12, - 7,-12, 7, 12, 12, -7, 12, 7, - -12, -8, -12, 8, -8,-12, -8, 12, - 8,-12, 8, 12, 12, -8, 12, 8, - -12, -9, -12, 9, -9,-12, -9, 12, - 9,-12, 9, 12, 12, -9, 12, 9, - -11,-11, -11, 11, 11,-11, 11, 11, - -12,-10, -12, 10, -10,-12, -10, 12, - 10,-12, 10, 12, 12,-10, 12, 10, - -12,-11, -12, 11, -11,-12, -11, 12, - 11,-12, 11, 12, 12,-11, 12, 11, - 104, // 13 - 1255 - -13, 0, 0,-13, 0, 13, 13, 0, - -13, -1, -13, 1, -1,-13, -1, 13, - 1,-13, 1, 13, 13, -1, 13, 1, + -9, -9, -9, 9, 9, -9, 9, 9, + -10, -8, -10, 8, -8,-10, -8, 10, + 8,-10, 8, 10, 10, -8, 10, 8, + -13, 0, -12, -5, -12, 5, -5,-12, + -5, 12, 0,-13, 0, 13, 5,-12, + 5, 12, 12, -5, 12, 5, 13, 0, + -13, -1, -13, 1, -11, -7, -11, 7, + -7,-11, -7, 11, -1,-13, -1, 13, + 1,-13, 1, 13, 7,-11, 7, 11, + 11, -7, 11, 7, 13, -1, 13, 1, -13, -2, -13, 2, -2,-13, -2, 13, 2,-13, 2, 13, 13, -2, 13, 2, -13, -3, -13, 3, -3,-13, -3, 13, 3,-13, 3, 13, 13, -3, 13, 3, - -13, -4, -13, 4, -4,-13, -4, 13, - 4,-13, 4, 13, 13, -4, 13, 4, + -12, -6, -12, 6, -6,-12, -6, 12, + 6,-12, 6, 12, 12, -6, 12, 6, + -10, -9, -10, 9, -9,-10, -9, 10, + 9,-10, 9, 10, 10, -9, 10, 9, + 88, // 14 - 1168 + -13, -4, -13, 4, -11, -8, -11, 8, + -8,-11, -8, 11, -4,-13, -4, 13, + 4,-13, 4, 13, 8,-11, 8, 11, + 11, -8, 11, 8, 13, -4, 13, 4, + -12, -7, -12, 7, -7,-12, -7, 12, + 7,-12, 7, 12, 12, -7, 12, 7, -13, -5, -13, 5, -5,-13, -5, 13, 5,-13, 5, 13, 13, -5, 13, 5, - -13, -6, -13, 6, -6,-13, -6, 13, - 6,-13, 6, 13, 13, -6, 13, 6, - -13, -7, -13, 7, -7,-13, -7, 13, - 7,-13, 7, 13, 13, -7, 13, 7, - -13, -8, -13, 8, -8,-13, -8, 13, - 8,-13, 8, 13, 13, -8, 13, 8, - -13, -9, -13, 9, -9,-13, -9, 13, - 9,-13, 9, 13, 13, -9, 13, 9, - -13,-10, -13, 10, -10,-13, -10, 13, - 10,-13, 10, 13, 13,-10, 13, 10, - -12,-12, -12, 12, 12,-12, 12, 12, - -13,-11, -13, 11, -11,-13, -11, 13, - 11,-13, 11, 13, 13,-11, 13, 11, - -13,-12, -13, 12, -12,-13, -12, 13, - 12,-13, 12, 13, 13,-12, 13, 12, - 112, // 14 - 1464 -14, 0, 0,-14, 0, 14, 14, 0, -14, -1, -14, 1, -1,-14, -1, 14, 1,-14, 1, 14, 14, -1, 14, 1, - -14, -2, -14, 2, -2,-14, -2, 14, - 2,-14, 2, 14, 14, -2, 14, 2, - -14, -3, -14, 3, -3,-14, -3, 14, - 3,-14, 3, 14, 14, -3, 14, 3, + -14, -2, -14, 2, -10,-10, -10, 10, + -2,-14, -2, 14, 2,-14, 2, 14, + 10,-10, 10, 10, 14, -2, 14, 2, + -11, -9, -11, 9, -9,-11, -9, 11, + 9,-11, 9, 11, 11, -9, 11, 9, + -14, -3, -14, 3, -13, -6, -13, 6, + -6,-13, -6, 13, -3,-14, -3, 14, + 3,-14, 3, 14, 6,-13, 6, 13, + 13, -6, 13, 6, 14, -3, 14, 3, + -12, -8, -12, 8, -8,-12, -8, 12, + 8,-12, 8, 12, 12, -8, 12, 8, + 84, // 15 - 1345 -14, -4, -14, 4, -4,-14, -4, 14, 4,-14, 4, 14, 14, -4, 14, 4, - -14, -5, -14, 5, -5,-14, -5, 14, - 5,-14, 5, 14, 14, -5, 14, 5, - -14, -6, -14, 6, -6,-14, -6, 14, - 6,-14, 6, 14, 14, -6, 14, 6, - -14, -7, -14, 7, -7,-14, -7, 14, - 7,-14, 7, 14, 14, -7, 14, 7, - -14, -8, -14, 8, -8,-14, -8, 14, - 8,-14, 8, 14, 14, -8, 14, 8, - -14, -9, -14, 9, -9,-14, -9, 14, - 9,-14, 9, 14, 14, -9, 14, 9, - -14,-10, -14, 10, -10,-14, -10, 14, - 10,-14, 10, 14, 14,-10, 14, 10, - -14,-11, -14, 11, -11,-14, -11, 14, - 11,-14, 11, 14, 14,-11, 14, 11, - -13,-13, -13, 13, 13,-13, 13, 13, - -14,-12, -14, 12, -12,-14, -12, 14, - 12,-14, 12, 14, 14,-12, 14, 12, - -14,-13, -14, 13, -13,-14, -13, 14, - 13,-14, 13, 14, 14,-13, 14, 13, - 120, // 15 - 1689 - -15, 0, 0,-15, 0, 15, 15, 0, + -13, -7, -13, 7, -7,-13, -7, 13, + 7,-13, 7, 13, 13, -7, 13, 7, + -14, -5, -14, 5, -11,-10, -11, 10, + -10,-11, -10, 11, -5,-14, -5, 14, + 5,-14, 5, 14, 10,-11, 10, 11, + 11,-10, 11, 10, 14, -5, 14, 5, + -15, 0, -12, -9, -12, 9, -9,-12, + -9, 12, 0,-15, 0, 15, 9,-12, + 9, 12, 12, -9, 12, 9, 15, 0, -15, -1, -15, 1, -1,-15, -1, 15, 1,-15, 1, 15, 15, -1, 15, 1, -15, -2, -15, 2, -2,-15, -2, 15, 2,-15, 2, 15, 15, -2, 15, 2, + -14, -6, -14, 6, -6,-14, -6, 14, + 6,-14, 6, 14, 14, -6, 14, 6, + -13, -8, -13, 8, -8,-13, -8, 13, + 8,-13, 8, 13, 13, -8, 13, 8, -15, -3, -15, 3, -3,-15, -3, 15, 3,-15, 3, 15, 15, -3, 15, 3, + 112, // 16 - 1514 -15, -4, -15, 4, -4,-15, -4, 15, 4,-15, 4, 15, 15, -4, 15, 4, - -15, -5, -15, 5, -5,-15, -5, 15, - 5,-15, 5, 15, 15, -5, 15, 5, - -15, -6, -15, 6, -6,-15, -6, 15, - 6,-15, 6, 15, 15, -6, 15, 6, - -15, -7, -15, 7, -7,-15, -7, 15, - 7,-15, 7, 15, 15, -7, 15, 7, - -15, -8, -15, 8, -8,-15, -8, 15, - 8,-15, 8, 15, 15, -8, 15, 8, - -15, -9, -15, 9, -9,-15, -9, 15, - 9,-15, 9, 15, 15, -9, 15, 9, - -15,-10, -15, 10, -10,-15, -10, 15, - 10,-15, 10, 15, 15,-10, 15, 10, - -15,-11, -15, 11, -11,-15, -11, 15, - 11,-15, 11, 15, 15,-11, 15, 11, - -15,-12, -15, 12, -12,-15, -12, 15, - 12,-15, 12, 15, 15,-12, 15, 12, - -14,-14, -14, 14, 14,-14, 14, 14, - -15,-13, -15, 13, -13,-15, -13, 15, - 13,-15, 13, 15, 15,-13, 15, 13, - -15,-14, -15, 14, -14,-15, -14, 15, - 14,-15, 14, 15, 15,-14, 15, 14, - (int8_t)128, // 16 - 1930 + -11,-11, -11, 11, 11,-11, 11, 11, + -12,-10, -12, 10, -10,-12, -10, 12, + 10,-12, 10, 12, 12,-10, 12, 10, + -14, -7, -14, 7, -7,-14, -7, 14, + 7,-14, 7, 14, 14, -7, 14, 7, + -15, -5, -15, 5, -13, -9, -13, 9, + -9,-13, -9, 13, -5,-15, -5, 15, + 5,-15, 5, 15, 9,-13, 9, 13, + 13, -9, 13, 9, 15, -5, 15, 5, -16, 0, 0,-16, 0, 16, 16, 0, -16, -1, -16, 1, -1,-16, -1, 16, 1,-16, 1, 16, 16, -1, 16, 1, - -16, -2, -16, 2, -2,-16, -2, 16, - 2,-16, 2, 16, 16, -2, 16, 2, - -16, -3, -16, 3, -3,-16, -3, 16, - 3,-16, 3, 16, 16, -3, 16, 3, + -16, -2, -16, 2, -14, -8, -14, 8, + -8,-14, -8, 14, -2,-16, -2, 16, + 2,-16, 2, 16, 8,-14, 8, 14, + 14, -8, 14, 8, 16, -2, 16, 2, + -15, -6, -15, 6, -6,-15, -6, 15, + 6,-15, 6, 15, 15, -6, 15, 6, + -16, -3, -16, 3, -12,-11, -12, 11, + -11,-12, -11, 12, -3,-16, -3, 16, + 3,-16, 3, 16, 11,-12, 11, 12, + 12,-11, 12, 11, 16, -3, 16, 3, + -13,-10, -13, 10, -10,-13, -10, 13, + 10,-13, 10, 13, 13,-10, 13, 10, -16, -4, -16, 4, -4,-16, -4, 16, 4,-16, 4, 16, 16, -4, 16, 4, + 112, // 17 - 1739 + -15, -7, -15, 7, -7,-15, -7, 15, + 7,-15, 7, 15, 15, -7, 15, 7, + -14, -9, -14, 9, -9,-14, -9, 14, + 9,-14, 9, 14, 14, -9, 14, 9, -16, -5, -16, 5, -5,-16, -5, 16, 5,-16, 5, 16, 16, -5, 16, 5, + -12,-12, -12, 12, 12,-12, 12, 12, + -17, 0, -15, -8, -15, 8, -8,-15, + -8, 15, 0,-17, 0, 17, 8,-15, + 8, 15, 15, -8, 15, 8, 17, 0, + -17, -1, -17, 1, -13,-11, -13, 11, + -11,-13, -11, 13, -1,-17, -1, 17, + 1,-17, 1, 17, 11,-13, 11, 13, + 13,-11, 13, 11, 17, -1, 17, 1, -16, -6, -16, 6, -6,-16, -6, 16, 6,-16, 6, 16, 16, -6, 16, 6, - -16, -7, -16, 7, -7,-16, -7, 16, - 7,-16, 7, 16, 16, -7, 16, 7, - -16, -8, -16, 8, -8,-16, -8, 16, - 8,-16, 8, 16, 16, -8, 16, 8, - -16, -9, -16, 9, -9,-16, -9, 16, - 9,-16, 9, 16, 16, -9, 16, 9, - -16,-10, -16, 10, -10,-16, -10, 16, - 10,-16, 10, 16, 16,-10, 16, 10, - -16,-11, -16, 11, -11,-16, -11, 16, - 11,-16, 11, 16, 16,-11, 16, 11, - -16,-12, -16, 12, -12,-16, -12, 16, - 12,-16, 12, 16, 16,-12, 16, 12, - -16,-13, -16, 13, -13,-16, -13, 16, - 13,-16, 13, 16, 16,-13, 16, 13, - -15,-15, -15, 15, 15,-15, 15, 15, - -16,-14, -16, 14, -14,-16, -14, 16, - 14,-16, 14, 16, 16,-14, 16, 14, - -16,-15, -16, 15, -15,-16, -15, 16, - 15,-16, 15, 16, 16,-15, 16, 15, - (int8_t)136, // 17 - 2187 - -17, 0, 0,-17, 0, 17, 17, 0, - -17, -1, -17, 1, -1,-17, -1, 17, - 1,-17, 1, 17, 17, -1, 17, 1, -17, -2, -17, 2, -2,-17, -2, 17, 2,-17, 2, 17, 17, -2, 17, 2, + -14,-10, -14, 10, -10,-14, -10, 14, + 10,-14, 10, 14, 14,-10, 14, 10, -17, -3, -17, 3, -3,-17, -3, 17, 3,-17, 3, 17, 17, -3, 17, 3, - -17, -4, -17, 4, -4,-17, -4, 17, - 4,-17, 4, 17, 17, -4, 17, 4, + -17, -4, -17, 4, -16, -7, -16, 7, + -7,-16, -7, 16, -4,-17, -4, 17, + 4,-17, 4, 17, 7,-16, 7, 16, + 16, -7, 16, 7, 17, -4, 17, 4, + -15, -9, -15, 9, -9,-15, -9, 15, + 9,-15, 9, 15, 15, -9, 15, 9, + 112, // 18 - 1964 + -13,-12, -13, 12, -12,-13, -12, 13, + 12,-13, 12, 13, 13,-12, 13, 12, -17, -5, -17, 5, -5,-17, -5, 17, 5,-17, 5, 17, 17, -5, 17, 5, - -17, -6, -17, 6, -6,-17, -6, 17, - 6,-17, 6, 17, 17, -6, 17, 6, - -17, -7, -17, 7, -7,-17, -7, 17, - 7,-17, 7, 17, 17, -7, 17, 7, - -17, -8, -17, 8, -8,-17, -8, 17, - 8,-17, 8, 17, 17, -8, 17, 8, - -17, -9, -17, 9, -9,-17, -9, 17, - 9,-17, 9, 17, 17, -9, 17, 9, - -17,-10, -17, 10, -10,-17, -10, 17, - 10,-17, 10, 17, 17,-10, 17, 10, - -17,-11, -17, 11, -11,-17, -11, 17, - 11,-17, 11, 17, 17,-11, 17, 11, - -17,-12, -17, 12, -12,-17, -12, 17, - 12,-17, 12, 17, 17,-12, 17, 12, - -17,-13, -17, 13, -13,-17, -13, 17, - 13,-17, 13, 17, 17,-13, 17, 13, - -17,-14, -17, 14, -14,-17, -14, 17, - 14,-17, 14, 17, 17,-14, 17, 14, - -16,-16, -16, 16, 16,-16, 16, 16, - -17,-15, -17, 15, -15,-17, -15, 17, - 15,-17, 15, 17, 17,-15, 17, 15, - -17,-16, -17, 16, -16,-17, -16, 17, - 16,-17, 16, 17, 17,-16, 17, 16, - (int8_t)144, // 18 - 2460 + -14,-11, -14, 11, -11,-14, -11, 14, + 11,-14, 11, 14, 14,-11, 14, 11, + -16, -8, -16, 8, -8,-16, -8, 16, + 8,-16, 8, 16, 16, -8, 16, 8, -18, 0, 0,-18, 0, 18, 18, 0, - -18, -1, -18, 1, -1,-18, -1, 18, - 1,-18, 1, 18, 18, -1, 18, 1, + -18, -1, -18, 1, -17, -6, -17, 6, + -15,-10, -15, 10, -10,-15, -10, 15, + -6,-17, -6, 17, -1,-18, -1, 18, + 1,-18, 1, 18, 6,-17, 6, 17, + 10,-15, 10, 15, 15,-10, 15, 10, + 17, -6, 17, 6, 18, -1, 18, 1, -18, -2, -18, 2, -2,-18, -2, 18, 2,-18, 2, 18, 18, -2, 18, 2, -18, -3, -18, 3, -3,-18, -3, 18, 3,-18, 3, 18, 18, -3, 18, 3, - -18, -4, -18, 4, -4,-18, -4, 18, - 4,-18, 4, 18, 18, -4, 18, 4, - -18, -5, -18, 5, -5,-18, -5, 18, - 5,-18, 5, 18, 18, -5, 18, 5, - -18, -6, -18, 6, -6,-18, -6, 18, - 6,-18, 6, 18, 18, -6, 18, 6, - -18, -7, -18, 7, -7,-18, -7, 18, - 7,-18, 7, 18, 18, -7, 18, 7, - -18, -8, -18, 8, -8,-18, -8, 18, - 8,-18, 8, 18, 18, -8, 18, 8, - -18, -9, -18, 9, -9,-18, -9, 18, - 9,-18, 9, 18, 18, -9, 18, 9, - -18,-10, -18, 10, -10,-18, -10, 18, - 10,-18, 10, 18, 18,-10, 18, 10, - -18,-11, -18, 11, -11,-18, -11, 18, - 11,-18, 11, 18, 18,-11, 18, 11, - -18,-12, -18, 12, -12,-18, -12, 18, - 12,-18, 12, 18, 18,-12, 18, 12, - -18,-13, -18, 13, -13,-18, -13, 18, - 13,-18, 13, 18, 18,-13, 18, 13, - -18,-14, -18, 14, -14,-18, -14, 18, - 14,-18, 14, 18, 18,-14, 18, 14, - -18,-15, -18, 15, -15,-18, -15, 18, - 15,-18, 15, 18, 18,-15, 18, 15, - -17,-17, -17, 17, 17,-17, 17, 17, - -18,-16, -18, 16, -16,-18, -16, 18, - 16,-18, 16, 18, 18,-16, 18, 16, - -18,-17, -18, 17, -17,-18, -17, 18, - 17,-18, 17, 18, 18,-17, 18, 17, + -16, -9, -16, 9, -9,-16, -9, 16, + 9,-16, 9, 16, 16, -9, 16, 9, + -17, -7, -17, 7, -13,-13, -13, 13, + -7,-17, -7, 17, 7,-17, 7, 17, + 13,-13, 13, 13, 17, -7, 17, 7, + -18, -4, -18, 4, -14,-12, -14, 12, + -12,-14, -12, 14, -4,-18, -4, 18, + 4,-18, 4, 18, 12,-14, 12, 14, + 14,-12, 14, 12, 18, -4, 18, 4, // clang-format on }; /** Indices of CrawlTable to select the entries at a given distance. */ -const int CrawlNum[19] = { 0, 3, 12, 45, 94, 159, 240, 337, 450, 579, 724, 885, 1062, 1255, 1464, 1689, 1930, 2187, 2460 }; +const int CrawlNum[19] = { 0, 3, 12, 45, 94, 143, 200, 281, 362, 459, 596, 709, 854, 991, 1168, 1345, 1514, 1739, 1964 }; static void RotateRadius(int* ox, int* oy, int* dx, int* dy, int* bx, int* by) { diff --git a/Source/lighting.h b/Source/lighting.h index b0302d7cf2e..5338b01d06b 100644 --- a/Source/lighting.h +++ b/Source/lighting.h @@ -74,7 +74,7 @@ void lighting_update_nest(); /* rdata */ -extern const int8_t CrawlTable[2749]; +extern const int8_t CrawlTable[2189]; extern const int CrawlNum[19]; #ifdef __cplusplus diff --git a/Source/monster.cpp b/Source/monster.cpp index d06de4ea342..ab80c21abfe 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -3613,8 +3613,8 @@ void MAI_Scav(int mnum) static_assert(MAXDUNX < UCHAR_MAX, "MAI_Scav stores dungeon coordinates in BYTE field I."); static_assert(MAXDUNY < UCHAR_MAX, "MAI_Scav stores dungeon coordinates in BYTE field II."); static_assert(lengthof(CrawlNum) > 4, "MAI_Scav uses CrawlTable/CrawlNum up to radius 4."); - // assert(CrawlTable[CrawlNum[4]] == 32); - BYTE corpseLocs[32 * 2]; + // assert(CrawlTable[CrawlNum[4]] == 24); + BYTE corpseLocs[24 * 2]; tmp = 0; for (i = 1; i <= 4; i++) { cr = &CrawlTable[CrawlNum[i]]; From e99bdce5f79cbcad0b6b179268d0e13c9e0674b6 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 3 Sep 2024 08:45:47 +0200 Subject: [PATCH 535/596] get rid of the unused entries of the CrawlTable --- Source/debug.cpp | 2 +- Source/lighting.cpp | 91 +-------------------------------------------- Source/lighting.h | 4 +- 3 files changed, 5 insertions(+), 92 deletions(-) diff --git a/Source/debug.cpp b/Source/debug.cpp index 4e766c29edb..996ebbc1121 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -225,8 +225,8 @@ static void sortCrawlTable(POS32 *table, unsigned entries, bool (cmpFunc)(const static void recreateCrawlTable() { - constexpr int r = 18; constexpr int version = 1; + constexpr int r = version == 0 ? 18 : 15; int crns[r + 1]; memset(crns, 0, sizeof(crns)); POS32 ctableentries[r + 1][2 * 2 * r * 4]; diff --git a/Source/lighting.cpp b/Source/lighting.cpp index 6e04a905765..7a797425ce1 100644 --- a/Source/lighting.cpp +++ b/Source/lighting.cpp @@ -76,7 +76,7 @@ BYTE ColorTrns[NUM_COLOR_TRNS][NUM_COLORS]; * | 526 * +-------> x */ -const int8_t CrawlTable[2189] = { +const int8_t CrawlTable[1514] = { // clang-format off 1, // 0 - 0 0, 0, @@ -282,98 +282,11 @@ const int8_t CrawlTable[2189] = { 8,-13, 8, 13, 13, -8, 13, 8, -15, -3, -15, 3, -3,-15, -3, 15, 3,-15, 3, 15, 15, -3, 15, 3, - 112, // 16 - 1514 - -15, -4, -15, 4, -4,-15, -4, 15, - 4,-15, 4, 15, 15, -4, 15, 4, - -11,-11, -11, 11, 11,-11, 11, 11, - -12,-10, -12, 10, -10,-12, -10, 12, - 10,-12, 10, 12, 12,-10, 12, 10, - -14, -7, -14, 7, -7,-14, -7, 14, - 7,-14, 7, 14, 14, -7, 14, 7, - -15, -5, -15, 5, -13, -9, -13, 9, - -9,-13, -9, 13, -5,-15, -5, 15, - 5,-15, 5, 15, 9,-13, 9, 13, - 13, -9, 13, 9, 15, -5, 15, 5, - -16, 0, 0,-16, 0, 16, 16, 0, - -16, -1, -16, 1, -1,-16, -1, 16, - 1,-16, 1, 16, 16, -1, 16, 1, - -16, -2, -16, 2, -14, -8, -14, 8, - -8,-14, -8, 14, -2,-16, -2, 16, - 2,-16, 2, 16, 8,-14, 8, 14, - 14, -8, 14, 8, 16, -2, 16, 2, - -15, -6, -15, 6, -6,-15, -6, 15, - 6,-15, 6, 15, 15, -6, 15, 6, - -16, -3, -16, 3, -12,-11, -12, 11, - -11,-12, -11, 12, -3,-16, -3, 16, - 3,-16, 3, 16, 11,-12, 11, 12, - 12,-11, 12, 11, 16, -3, 16, 3, - -13,-10, -13, 10, -10,-13, -10, 13, - 10,-13, 10, 13, 13,-10, 13, 10, - -16, -4, -16, 4, -4,-16, -4, 16, - 4,-16, 4, 16, 16, -4, 16, 4, - 112, // 17 - 1739 - -15, -7, -15, 7, -7,-15, -7, 15, - 7,-15, 7, 15, 15, -7, 15, 7, - -14, -9, -14, 9, -9,-14, -9, 14, - 9,-14, 9, 14, 14, -9, 14, 9, - -16, -5, -16, 5, -5,-16, -5, 16, - 5,-16, 5, 16, 16, -5, 16, 5, - -12,-12, -12, 12, 12,-12, 12, 12, - -17, 0, -15, -8, -15, 8, -8,-15, - -8, 15, 0,-17, 0, 17, 8,-15, - 8, 15, 15, -8, 15, 8, 17, 0, - -17, -1, -17, 1, -13,-11, -13, 11, - -11,-13, -11, 13, -1,-17, -1, 17, - 1,-17, 1, 17, 11,-13, 11, 13, - 13,-11, 13, 11, 17, -1, 17, 1, - -16, -6, -16, 6, -6,-16, -6, 16, - 6,-16, 6, 16, 16, -6, 16, 6, - -17, -2, -17, 2, -2,-17, -2, 17, - 2,-17, 2, 17, 17, -2, 17, 2, - -14,-10, -14, 10, -10,-14, -10, 14, - 10,-14, 10, 14, 14,-10, 14, 10, - -17, -3, -17, 3, -3,-17, -3, 17, - 3,-17, 3, 17, 17, -3, 17, 3, - -17, -4, -17, 4, -16, -7, -16, 7, - -7,-16, -7, 16, -4,-17, -4, 17, - 4,-17, 4, 17, 7,-16, 7, 16, - 16, -7, 16, 7, 17, -4, 17, 4, - -15, -9, -15, 9, -9,-15, -9, 15, - 9,-15, 9, 15, 15, -9, 15, 9, - 112, // 18 - 1964 - -13,-12, -13, 12, -12,-13, -12, 13, - 12,-13, 12, 13, 13,-12, 13, 12, - -17, -5, -17, 5, -5,-17, -5, 17, - 5,-17, 5, 17, 17, -5, 17, 5, - -14,-11, -14, 11, -11,-14, -11, 14, - 11,-14, 11, 14, 14,-11, 14, 11, - -16, -8, -16, 8, -8,-16, -8, 16, - 8,-16, 8, 16, 16, -8, 16, 8, - -18, 0, 0,-18, 0, 18, 18, 0, - -18, -1, -18, 1, -17, -6, -17, 6, - -15,-10, -15, 10, -10,-15, -10, 15, - -6,-17, -6, 17, -1,-18, -1, 18, - 1,-18, 1, 18, 6,-17, 6, 17, - 10,-15, 10, 15, 15,-10, 15, 10, - 17, -6, 17, 6, 18, -1, 18, 1, - -18, -2, -18, 2, -2,-18, -2, 18, - 2,-18, 2, 18, 18, -2, 18, 2, - -18, -3, -18, 3, -3,-18, -3, 18, - 3,-18, 3, 18, 18, -3, 18, 3, - -16, -9, -16, 9, -9,-16, -9, 16, - 9,-16, 9, 16, 16, -9, 16, 9, - -17, -7, -17, 7, -13,-13, -13, 13, - -7,-17, -7, 17, 7,-17, 7, 17, - 13,-13, 13, 13, 17, -7, 17, 7, - -18, -4, -18, 4, -14,-12, -14, 12, - -12,-14, -12, 14, -4,-18, -4, 18, - 4,-18, 4, 18, 12,-14, 12, 14, - 14,-12, 14, 12, 18, -4, 18, 4, // clang-format on }; /** Indices of CrawlTable to select the entries at a given distance. */ -const int CrawlNum[19] = { 0, 3, 12, 45, 94, 143, 200, 281, 362, 459, 596, 709, 854, 991, 1168, 1345, 1514, 1739, 1964 }; +const int CrawlNum[16] = { 0, 3, 12, 45, 94, 143, 200, 281, 362, 459, 596, 709, 854, 991, 1168, 1345 }; static void RotateRadius(int* ox, int* oy, int* dx, int* dy, int* bx, int* by) { diff --git a/Source/lighting.h b/Source/lighting.h index 5338b01d06b..97d4cc05ad0 100644 --- a/Source/lighting.h +++ b/Source/lighting.h @@ -74,8 +74,8 @@ void lighting_update_nest(); /* rdata */ -extern const int8_t CrawlTable[2189]; -extern const int CrawlNum[19]; +extern const int8_t CrawlTable[1514]; +extern const int CrawlNum[16]; #ifdef __cplusplus } From 8753ad562cb784cc221fda60c8f0bc3ba9e88d1b Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 3 Sep 2024 08:46:17 +0200 Subject: [PATCH 536/596] cleanup nightly.yml --- .github/workflows/nightly.yml | 100 ++++++++++++++-------------------- 1 file changed, 40 insertions(+), 60 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 1ebedc30620..2ad06a8cbe6 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -37,7 +37,6 @@ jobs: strategy: fail-fast: false matrix: - #name: [diablo, hellfire] include: # x86 builds - name: diablo-x86 @@ -57,11 +56,11 @@ jobs: cmakeargs: '-A Win32 -D_WIN32_WINNT=0x0501 -DNOHOSTING=OFF -DHOSTONLY=ON -DINET_MODE=ON -DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON -DHAS_JOYSTICK=OFF -DHAS_DPAD=OFF -DHAS_GAMECTRL=OFF -DHAS_TOUCHPAD=OFF -DHAS_KBCTRL=OFF -DNOSOUND=ON -DSCREEN_WIDTH=640 -DSCREEN_HEIGHT=480 -DNOWIDESCREEN=ON' artifact: 'hellsrv-nightly-x86.zip' # x64 builds - - name: diablo + - name: diablo+patch #packages: 'sdl2:x64-windows libsodium:x64-windows' cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON' artifact: 'diablo-nightly-x64.zip' - - name: hellfire + - name: hellfire+patch #packages: 'sdl2:x64-windows libsodium:x64-windows' cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-x64.zip' @@ -110,13 +109,12 @@ jobs: strategy: fail-fast: false matrix: - #name: [diablo-x86, hellfire-x86] include: # x86 builds - - name: diablo-x86 + - name: diablo+patch cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON' artifact: 'diablo-nightly-mingw-x86.zip' - - name: hellfire-x86 + - name: hellfire+patch cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-mingw-x86.zip' steps: @@ -156,13 +154,12 @@ jobs: strategy: fail-fast: false matrix: - #name: [diablo, hellfire] include: # x64 builds - - name: diablo-x64 + - name: diablo+patch cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON' artifact: 'diablo-nightly-mingw-x64.zip' - - name: hellfire-x64 + - name: hellfire+patch cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-mingw-x64.zip' steps: @@ -202,13 +199,12 @@ jobs: strategy: fail-fast: false matrix: - #name: [diablo-x86, hellfire-x86] include: # x86 builds - - name: diablo-w9x + - name: diablo+patch cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DUSE_PATCH=ON -DNONET=ON' artifact: 'diablo-nightly-mingw-w9x.zip' - - name: hellfire-w9x + - name: hellfire+patch cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DUSE_PATCH=ON -DNONET=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-mingw-w9x.zip' steps: @@ -249,7 +245,6 @@ jobs: strategy: fail-fast: false matrix: - #name: [diablo, hellfire] include: - name: diablo cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF' @@ -259,11 +254,11 @@ jobs: cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DHELLFIRE=ON' artifact: 'hellfire-nightly-x86_64-linux-gnu.tar.xz' appimage: 'hellfire-nightly-x86_64-linux-gnu.appimage' - - name: diablo-uxp + - name: diablo+patch cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON' artifact: 'diablo-nightly-x86_64-linux-gnup.tar.xz' appimage: 'diablo-nightly-x86_64-linux-gnup.appimage' - - name: hellfire-uxp + - name: hellfire+patch cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-x86_64-linux-gnup.tar.xz' appimage: 'hellfire-nightly-x86_64-linux-gnup.appimage' @@ -320,18 +315,17 @@ jobs: strategy: fail-fast: false matrix: - #name: [diablo, hellfire] include: - - name: diablo-aa64 + - name: diablo cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF' artifact: 'diablo-nightly-aarch64.tar.xz' - - name: hellfire-aa64 + - name: hellfire cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DHELLFIRE=ON' artifact: 'hellfire-nightly-aarch64.tar.xz' - - name: diablo-aa64p + - name: diablo+patch cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON' artifact: 'diablo-nightly-aarch64p.tar.xz' - - name: hellfire-aa64p + - name: hellfire+patch cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-aarch64p.tar.xz' runs-on: ubuntu-20.04 @@ -379,18 +373,17 @@ jobs: strategy: fail-fast: false matrix: - #name: [diablo, hellfire] include: - - name: diablo-mac + - name: diablo cmakeargs: '-DDEVILUTIONX_SYSTEM_SDL2=OFF' artifact: 'diablo-nightly-mac.dmg' - - name: hellfire-mac + - name: hellfire cmakeargs: '-DDEVILUTIONX_SYSTEM_SDL2=OFF -DHELLFIRE=ON' artifact: 'hellfire-nightly-mac.dmg' - - name: diablo-macp + - name: diablo+patch cmakeargs: '-DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON' artifact: 'diablo-nightly-macp.dmg' - - name: hellfire-macp + - name: hellfire+patch cmakeargs: '-DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-macp.dmg' runs-on: macos-12 @@ -427,18 +420,17 @@ jobs: strategy: fail-fast: false matrix: - #name: [diablo, hellfire] include: - - name: diablo-ios + - name: diablo cmakeargs: '' artifact: 'diablo-nightly-ios.ipa' - - name: hellfire-ios + - name: hellfire cmakeargs: '-DHELLFIRE=ON' artifact: 'hellfire-nightly-ios.ipa' - - name: diablo-iosp + - name: diablo+patch cmakeargs: '-DUSE_PATCH=ON' artifact: 'diablo-nightly-iosp.ipa' - - name: hellfire-iosp + - name: hellfire+patch cmakeargs: '-DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-iosp.ipa' runs-on: macos-12 @@ -479,17 +471,16 @@ jobs: strategy: fail-fast: false matrix: - #name: [diablo, hellfire] include: - name: diablo artifact: 'diablo-nightly-android.apk' - name: hellfire cmakearg0: '-DHELLFIRE=ON' artifact: 'hellfire-nightly-android.apk' - - name: diablo-adrp + - name: diablo+patch cmakearg0: '-DUSE_PATCH=ON' artifact: 'diablo-nightly-androidp.apk' - - name: hellfire-adrp + - name: hellfire+patch cmakearg0: '-DUSE_PATCH=ON' cmakearg1: '-DHELLFIRE=ON' artifact: 'hellfire-nightly-androidp.apk' @@ -543,7 +534,6 @@ jobs: strategy: fail-fast: false matrix: - #name: [diablo, hellfire] include: - name: diablo cmakeargs: '-DZEROTIER=OFF' @@ -551,10 +541,10 @@ jobs: - name: hellfire cmakeargs: '-DZEROTIER=OFF -DHELLFIRE=ON' artifact: 'hellfire-nightly-rg350.opk' - - name: diablo-rgp + - name: diablo+patch cmakeargs: '-DZEROTIER=OFF -DUSE_PATCH=ON' artifact: 'diablo-nightly-rg350p.opk' - - name: hellfire-rgp + - name: hellfire+patch cmakeargs: '-DZEROTIER=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-rg350p.opk' runs-on: ubuntu-22.04 @@ -596,7 +586,6 @@ jobs: strategy: fail-fast: false matrix: - #name: [diablo, hellfire] include: - name: diablo cmakeargs: '' @@ -604,10 +593,10 @@ jobs: - name: hellfire cmakeargs: '-DHELLFIRE=ON' artifact: 'hellfire-nightly-lepus.opk' - - name: diablo-lepp + - name: diablo+patch cmakeargs: '-DUSE_PATCH=ON' artifact: 'diablo-nightly-lepusp.opk' - - name: hellfire-lepp + - name: hellfire+patch cmakeargs: '-DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-lepusp.opk' runs-on: ubuntu-22.04 @@ -649,7 +638,6 @@ jobs: strategy: fail-fast: false matrix: - #name: [diablo, hellfire] include: - name: diablo cmakeargs: '-DZEROTIER=OFF' @@ -657,10 +645,10 @@ jobs: - name: hellfire cmakeargs: '-DZEROTIER=OFF -DHELLFIRE=ON' artifact: 'hellfire-nightly-retrofw.opk' - - name: diablo-rtrp + - name: diablo+patch cmakeargs: '-DZEROTIER=OFF -DUSE_PATCH=ON' artifact: 'diablo-nightly-retrofwp.opk' - - name: hellfire-rtrp + - name: hellfire+patch cmakeargs: '-DZEROTIER=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-retrofwp.opk' runs-on: ubuntu-latest @@ -705,7 +693,6 @@ jobs: strategy: fail-fast: false matrix: - #name: [diablo, hellfire] include: - name: diablo cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF' @@ -713,10 +700,10 @@ jobs: - name: hellfire cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DHELLFIRE=ON' artifact: 'hellfire-nightly-ps4.pkg' - - name: diablo-ps4p + - name: diablo+patch cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON' artifact: 'diablo-nightly-ps4p.pkg' - - name: hellfire-ps4p + - name: hellfire+patch cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-ps4p.pkg' runs-on: ubuntu-22.04 @@ -754,7 +741,6 @@ jobs: strategy: fail-fast: false matrix: - #name: [diablo, hellfire] include: - name: diablo cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF' @@ -803,7 +789,6 @@ jobs: strategy: fail-fast: false matrix: - #name: [diablo, hellfire] include: - name: diablo cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON' @@ -811,10 +796,10 @@ jobs: - name: hellfire cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-vita.vpk' - - name: diablo-vita + - name: diablo+patch cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON -D USE_PATCH=ON' artifact: 'diablo-nightly-vitap.vpk' - - name: hellfire-vita + - name: hellfire+patch cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON -D USE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-vitap.vpk' runs-on: ubuntu-latest @@ -851,7 +836,6 @@ jobs: strategy: fail-fast: false matrix: - #name: [diablo, hellfire] include: - name: diablo cmakeargs: '-DNONET=ON' @@ -861,11 +845,11 @@ jobs: cmakeargs: '-DNONET=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-3ds.3dsx' cia: 'hellfire-nightly-3ds.cia' - - name: diablo-3ds + - name: diablo+patch cmakeargs: '-DNONET=ON -D USE_PATCH=ON' artifact: 'diablo-nightly-3dsp.3dsx' cia: 'diablo-nightly-3dsp.cia' - - name: hellfire-3ds + - name: hellfire+patch cmakeargs: '-DNONET=ON -D USE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-3dsp.3dsx' cia: 'hellfire-nightly-3dsp.cia' @@ -922,7 +906,6 @@ jobs: strategy: fail-fast: false matrix: - #name: [diablo, hellfire] include: - name: diablo cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON' @@ -930,10 +913,10 @@ jobs: - name: hellfire cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-switch.nro' - - name: diablo-switch + - name: diablo+patch cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON -D USE_PATCH=ON' artifact: 'diablo-nightly-switchp.nro' - - name: hellfire-switch + - name: hellfire+patch cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON -D USE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-switchp.nro' runs-on: ubuntu-latest @@ -944,8 +927,6 @@ jobs: with: fetch-depth: 0 - # - name: Create Build Environment - # run: brew bundle install - name: Install dependencies shell: bash run: | @@ -976,7 +957,6 @@ jobs: strategy: fail-fast: false matrix: - #name: [diablo, hellfire] include: - name: diablo cmakeargs: '-DNONET=ON' @@ -984,10 +964,10 @@ jobs: - name: hellfire cmakeargs: '-DNONET=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-amiga' - - name: diablo-amiga + - name: diablo+patch cmakeargs: '-DNONET=ON -D USE_PATCH=ON' artifact: 'diablo-nightly-amigap' - - name: hellfire-amiga + - name: hellfire+patch cmakeargs: '-DNONET=ON -D USE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-amigap' runs-on: ubuntu-latest From 358c523478ee598f5c2aae1af51a5303d035a82b Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 3 Sep 2024 09:00:50 +0200 Subject: [PATCH 537/596] update asio --- 3rdParty/asio/CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/3rdParty/asio/CMakeLists.txt b/3rdParty/asio/CMakeLists.txt index 4fc598657cc..504754c7f90 100644 --- a/3rdParty/asio/CMakeLists.txt +++ b/3rdParty/asio/CMakeLists.txt @@ -2,10 +2,12 @@ include(FetchContent_MakeAvailableExcludeFromAll) include(FetchContent) FetchContent_Declare(asio - URL https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-18-1.zip - URL_HASH MD5=e8eb4612ddaeb0f6e4e865e0d5d94da9 + #URL https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-18-1.zip + #URL_HASH MD5=e8eb4612ddaeb0f6e4e865e0d5d94da9 #URL https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-18-2.zip #URL_HASH MD5=0f297c14ffec04d8ac9bd74f3c8aba36 + URL https://github.com/chriskohlhoff/asio/archive/refs/tags/asio-1-31-0.zip + URL_HASH MD5=f1ade8d4a2b86daf7f5ad90fdbde6691 ) #FetchContent_Declare(asio # URL https://github.com/chriskohlhoff/asio/archive/77bcfe775ad63178942c9dd95d93edd10442b80f.zip From ab2d47a22aada6b745ad26e38a21f5a857d1f984 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 3 Sep 2024 09:46:43 +0200 Subject: [PATCH 538/596] bugfix for 'add an empty line to the upstairs in hell to leave space for shadow-tiles' --- Source/drlg_l4.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Source/drlg_l4.cpp b/Source/drlg_l4.cpp index 7b27500ff04..bb9c6f77094 100644 --- a/Source/drlg_l4.cpp +++ b/Source/drlg_l4.cpp @@ -54,11 +54,11 @@ const BYTE L4USTAIRS[] = { // clang-format off 5, 5, // width, height - 6, 6, 6, 6, // search - 6, 6, 6, 6, - 6, 6, 6, 6, - 6, 6, 6, 6, - 6, 6, 6, 6, + 6, 6, 6, 6, 6, // search + 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, // replace 0, 38, 35, 0, 0, From e2f89d510b371a7d1f2de367ab540f42043c6a62 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 4 Sep 2024 08:09:58 +0200 Subject: [PATCH 539/596] improve the precision of missile-movement (GetMissilePos) --- Source/missiles.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index c03a7132ec4..af9d849ec56 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -591,6 +591,10 @@ static void GetMissilePos(int mi) mis = &missile[mi]; mx = mis->_mitxoff >> (MIS_BASE_VELO_SHIFT + MIS_VELO_SHIFT); my = mis->_mityoff >> (MIS_BASE_VELO_SHIFT + MIS_VELO_SHIFT); + if ((mis->_mitxoff >> (MIS_BASE_VELO_SHIFT + MIS_VELO_SHIFT - 1) & 1)) + mx++; + if ((mis->_mityoff >> (MIS_BASE_VELO_SHIFT + MIS_VELO_SHIFT - 1) & 1)) + my++; dx = mx + my; dy = my - mx; From f4b2a4ddc5ab1f55fd57f3b6352068267be0630a Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 4 Sep 2024 08:15:15 +0200 Subject: [PATCH 540/596] do not deduct (staff-)charge when the spell is already queued --- Source/msg.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Source/msg.cpp b/Source/msg.cpp index 0d6e1eea5b0..85afe2e5605 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -2505,21 +2505,21 @@ static bool CheckPlrSkillUse(int pnum, CmdSkillUse& su) if (plr._pmode != PM_DEATH && (spelldata[sn].sUseFlags & plr._pSkillFlags) == spelldata[sn].sUseFlags) { su.from = plr._pSkillLvl[sn]; + // do not deduct mana/charge if the skill/level matches the set (skill based) action + static_assert((int)ACTION_ATTACK + 1 == (int)ACTION_ATTACKMON, "CheckPlrSkillUse expects ordered action-ids I."); + static_assert((int)ACTION_ATTACKMON + 1 == (int)ACTION_ATTACKPLR, "CheckPlrSkillUse expects ordered action-ids II."); + static_assert((int)ACTION_ATTACKPLR + 1 == (int)ACTION_RATTACK, "CheckPlrSkillUse expects ordered action-ids III."); + static_assert((int)ACTION_RATTACK + 1 == (int)ACTION_RATTACKMON, "CheckPlrSkillUse expects ordered action-ids IV."); + static_assert((int)ACTION_RATTACKMON + 1 == (int)ACTION_RATTACKPLR, "CheckPlrSkillUse expects ordered action-ids V."); + static_assert((int)ACTION_RATTACKPLR + 1 == (int)ACTION_SPELL, "CheckPlrSkillUse expects ordered action-ids VI."); + static_assert((int)ACTION_SPELL + 1 == (int)ACTION_SPELLMON, "CheckPlrSkillUse expects ordered action-ids VII."); + static_assert((int)ACTION_SPELLMON + 1 == (int)ACTION_SPELLPLR, "CheckPlrSkillUse expects ordered action-ids VIII."); + if (sn == plr._pDestParam3 && ((BYTE)su.from) == plr._pDestParam4 + && plr._pDestAction >= ACTION_ATTACK && plr._pDestAction <= ACTION_SPELLPLR) + return sameLvl; if (sf == SPLFROM_MANA) { if (su.from == 0) return false; - // do not deduct mana if the skill/level matches the set (skill based) action - static_assert((int)ACTION_ATTACK + 1 == (int)ACTION_ATTACKMON, "CheckPlrSkillUse expects ordered action-ids I."); - static_assert((int)ACTION_ATTACKMON + 1 == (int)ACTION_ATTACKPLR, "CheckPlrSkillUse expects ordered action-ids II."); - static_assert((int)ACTION_ATTACKPLR + 1 == (int)ACTION_RATTACK, "CheckPlrSkillUse expects ordered action-ids III."); - static_assert((int)ACTION_RATTACK + 1 == (int)ACTION_RATTACKMON, "CheckPlrSkillUse expects ordered action-ids IV."); - static_assert((int)ACTION_RATTACKMON + 1 == (int)ACTION_RATTACKPLR, "CheckPlrSkillUse expects ordered action-ids V."); - static_assert((int)ACTION_RATTACKPLR + 1 == (int)ACTION_SPELL, "CheckPlrSkillUse expects ordered action-ids VI."); - static_assert((int)ACTION_SPELL + 1 == (int)ACTION_SPELLMON, "CheckPlrSkillUse expects ordered action-ids VII."); - static_assert((int)ACTION_SPELLMON + 1 == (int)ACTION_SPELLPLR, "CheckPlrSkillUse expects ordered action-ids VIII."); - if (sn == plr._pDestParam3 && ((BYTE)su.from) == plr._pDestParam4 - && plr._pDestAction >= ACTION_ATTACK && plr._pDestAction <= ACTION_SPELLPLR) - return sameLvl; net_assert(plr._pMemSkills & SPELL_MASK(sn)); // always grant skill-activity to prevent de-sync // TODO: add checks to prevent abuse? From 544ffdf0b4ed1897c28f1bff3c3286c1a2816e60 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 4 Sep 2024 08:21:38 +0200 Subject: [PATCH 541/596] fix the skill-use check of disarm/telekinesis actions - always deduct resource for disarm/telekinesis actions, because DestParam4 is not the real spell-level --- Source/msg.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/msg.cpp b/Source/msg.cpp index 85afe2e5605..8d012e90694 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -2514,7 +2514,7 @@ static bool CheckPlrSkillUse(int pnum, CmdSkillUse& su) static_assert((int)ACTION_RATTACKPLR + 1 == (int)ACTION_SPELL, "CheckPlrSkillUse expects ordered action-ids VI."); static_assert((int)ACTION_SPELL + 1 == (int)ACTION_SPELLMON, "CheckPlrSkillUse expects ordered action-ids VII."); static_assert((int)ACTION_SPELLMON + 1 == (int)ACTION_SPELLPLR, "CheckPlrSkillUse expects ordered action-ids VIII."); - if (sn == plr._pDestParam3 && ((BYTE)su.from) == plr._pDestParam4 + if (sn != SPL_TELEKINESIS && sn != SPL_DISARM && sn == plr._pDestParam3 && ((BYTE)su.from) == plr._pDestParam4 && plr._pDestAction >= ACTION_ATTACK && plr._pDestAction <= ACTION_SPELLPLR) return sameLvl; if (sf == SPLFROM_MANA) { From c0ad8173721d814b05017a474592b1d46af96d3f Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 4 Sep 2024 08:23:56 +0200 Subject: [PATCH 542/596] use arithmetic shift instead of signed div by 2 II. --- Source/gendung.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/gendung.cpp b/Source/gendung.cpp index 15be8a9fcb1..d5aa496a57b 100644 --- a/Source/gendung.cpp +++ b/Source/gendung.cpp @@ -1508,9 +1508,9 @@ static void DRLG_CreateThemeRoom(int themeIndex, const BYTE (&themeTiles)[NUM_DR // exits if (random_(0, 2) == 0) { - dungeon[x2][(y1 + y2 + 1) / 2] = themeTiles[DRT_DOOR_VERT]; + dungeon[x2][(y1 + y2 + 1) / 2u] = themeTiles[DRT_DOOR_VERT]; } else { - dungeon[(x1 + x2 + 1) / 2][y2] = themeTiles[DRT_DOOR_HORIZ]; + dungeon[(x1 + x2 + 1) / 2u][y2] = themeTiles[DRT_DOOR_HORIZ]; } } From 0db44e96b985c48cbc08eb08d3486b5344f7aba6 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 4 Sep 2024 08:24:37 +0200 Subject: [PATCH 543/596] cosmetic --- Source/drlg_l2.cpp | 3 +-- Source/drlg_l4.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Source/drlg_l2.cpp b/Source/drlg_l2.cpp index 33afa1c5465..76b97dafee3 100644 --- a/Source/drlg_l2.cpp +++ b/Source/drlg_l2.cpp @@ -766,7 +766,7 @@ static void DRLG_L2Shadows() dungeon[i - 1][j - 1] = replace; dungeon[i - 1][j] = 50; } else { - // automaptype MWT_NORTH_EAST, MWT_NORTH, tile 9, 45, 50 -> ok + // automaptype MWT_NORTH_EAST, MWT_NORTH, tile 2, 5, 8, 9, 33, 45, 50 -> ok // TODO: what else? } } @@ -2331,7 +2331,6 @@ static void DRLG_L2() if (warpPos.x < 0) { continue; } - pWarps[DWARP_ENTRY]._wx = warpPos.x; pWarps[DWARP_ENTRY]._wy = warpPos.y; pWarps[DWARP_ENTRY]._wx = 2 * pWarps[DWARP_ENTRY]._wx + DBORDERX + 1; diff --git a/Source/drlg_l4.cpp b/Source/drlg_l4.cpp index bb9c6f77094..e8afdfb1476 100644 --- a/Source/drlg_l4.cpp +++ b/Source/drlg_l4.cpp @@ -508,7 +508,7 @@ static void DRLG_L4SetRoom(int idx) } /* - * Transform dungeon by replacing values using 2x2 block patterns defined in L1ConvTbl + * Transform dungeon by replacing values using 2x2 block patterns defined in L4ConvTbl * New dungeon values: 1 2 3 6 9 30 */ static void DRLG_L4MakeMegas() From 5e68af7734abfbd2c2e6b6c59a44734d99e128f4 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 4 Sep 2024 08:26:34 +0200 Subject: [PATCH 544/596] reorganize the net-configurations - enable net on win98, ps5 - disable net on amiga, n3ds, switch, vita with the corresponding cmake-definitions --- .github/workflows/nightly.yml | 36 +++++++++++++++++------------------ CMake/amiga_defs.cmake | 3 ++- CMake/n3ds_defs.cmake | 3 ++- CMake/ps4_defs.cmake | 2 ++ CMake/ps5_defs.cmake | 2 +- CMake/switch_defs.cmake | 3 ++- CMake/vita_defs.cmake | 3 ++- CMake/windows9x_defs.cmake | 5 +++-- 8 files changed, 32 insertions(+), 25 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 2ad06a8cbe6..532a5b8c856 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -202,10 +202,10 @@ jobs: include: # x86 builds - name: diablo+patch - cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DUSE_PATCH=ON -DNONET=ON' + cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DUSE_PATCH=ON' artifact: 'diablo-nightly-mingw-w9x.zip' - name: hellfire+patch - cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DUSE_PATCH=ON -DNONET=ON -DHELLFIRE=ON' + cmakeargs: '-DDEVILUTIONX_SYSTEM_LIBSODIUM=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-mingw-w9x.zip' steps: - name: Checkout @@ -791,16 +791,16 @@ jobs: matrix: include: - name: diablo - cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON' + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF' artifact: 'diablo-nightly-vita.vpk' - name: hellfire - cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON -DHELLFIRE=ON' + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DHELLFIRE=ON' artifact: 'hellfire-nightly-vita.vpk' - name: diablo+patch - cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON -D USE_PATCH=ON' + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON' artifact: 'diablo-nightly-vitap.vpk' - name: hellfire+patch - cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON -D USE_PATCH=ON -DHELLFIRE=ON' + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-vitap.vpk' runs-on: ubuntu-latest container: vitasdk/vitasdk:latest @@ -838,19 +838,19 @@ jobs: matrix: include: - name: diablo - cmakeargs: '-DNONET=ON' + cmakeargs: '' artifact: 'diablo-nightly-3ds.3dsx' cia: 'diablo-nightly-3ds.cia' - name: hellfire - cmakeargs: '-DNONET=ON -DHELLFIRE=ON' + cmakeargs: '-DHELLFIRE=ON' artifact: 'hellfire-nightly-3ds.3dsx' cia: 'hellfire-nightly-3ds.cia' - name: diablo+patch - cmakeargs: '-DNONET=ON -D USE_PATCH=ON' + cmakeargs: '-D USE_PATCH=ON' artifact: 'diablo-nightly-3dsp.3dsx' cia: 'diablo-nightly-3dsp.cia' - name: hellfire+patch - cmakeargs: '-DNONET=ON -D USE_PATCH=ON -DHELLFIRE=ON' + cmakeargs: '-D USE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-3dsp.3dsx' cia: 'hellfire-nightly-3dsp.cia' runs-on: ubuntu-latest @@ -908,16 +908,16 @@ jobs: matrix: include: - name: diablo - cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON' + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF' artifact: 'diablo-nightly-switch.nro' - name: hellfire - cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON -DHELLFIRE=ON' + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DHELLFIRE=ON' artifact: 'hellfire-nightly-switch.nro' - name: diablo+patch - cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON -D USE_PATCH=ON' + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON' artifact: 'diablo-nightly-switchp.nro' - name: hellfire+patch - cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -DNONET=ON -D USE_PATCH=ON -DHELLFIRE=ON' + cmakeargs: '-D DEVILUTIONX_SYSTEM_SDL2=OFF -D USE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-switchp.nro' runs-on: ubuntu-latest container: devkitpro/devkita64:latest @@ -959,16 +959,16 @@ jobs: matrix: include: - name: diablo - cmakeargs: '-DNONET=ON' + cmakeargs: '' artifact: 'diablo-nightly-amiga' - name: hellfire - cmakeargs: '-DNONET=ON -DHELLFIRE=ON' + cmakeargs: '-DHELLFIRE=ON' artifact: 'hellfire-nightly-amiga' - name: diablo+patch - cmakeargs: '-DNONET=ON -D USE_PATCH=ON' + cmakeargs: '-D USE_PATCH=ON' artifact: 'diablo-nightly-amigap' - name: hellfire+patch - cmakeargs: '-DNONET=ON -D USE_PATCH=ON -DHELLFIRE=ON' + cmakeargs: '-D USE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-amigap' runs-on: ubuntu-latest container: amigadev/crosstools:m68k-amigaos-gcc10 diff --git a/CMake/amiga_defs.cmake b/CMake/amiga_defs.cmake index 0b6e7073728..011556437f8 100644 --- a/CMake/amiga_defs.cmake +++ b/CMake/amiga_defs.cmake @@ -3,9 +3,10 @@ set(ASAN OFF) set(UBSAN OFF) # General build options. -set(NONET ON) set(NOMEMCCPY ON) set(USE_SDL1 ON) +set(NONET ON) +#set(DEVILUTIONX_SYSTEM_LIBSODIUM OFF) #set(TTF_FONT_NAME \"LiberationSerif-Bold.ttf\") # Enable exception support as they are used in dvlnet code diff --git a/CMake/n3ds_defs.cmake b/CMake/n3ds_defs.cmake index f47ca4315c1..221d2012b2a 100644 --- a/CMake/n3ds_defs.cmake +++ b/CMake/n3ds_defs.cmake @@ -6,9 +6,10 @@ set(UBSAN OFF) # The 3ds build handles the stripping in a custom way. set(USE_SDL1 ON) set(DISABLE_STRIP ON) +set(NONET ON) #set(ZEROTIER OFF) # Disable system dependencies. -set(DEVILUTIONX_SYSTEM_LIBSODIUM OFF) +#set(DEVILUTIONX_SYSTEM_LIBSODIUM OFF) # additional compilation definitions add_definitions(-D__3DS__) diff --git a/CMake/ps4_defs.cmake b/CMake/ps4_defs.cmake index dbc6d1b4172..0e05c737476 100644 --- a/CMake/ps4_defs.cmake +++ b/CMake/ps4_defs.cmake @@ -8,6 +8,8 @@ set(UBSAN OFF) set(DISABLE_STRIP ON) set(DISABLE_LTO ON) set(NONET ON) +#set(ZEROTIER OFF) +#set(DEVILUTIONX_SYSTEM_LIBSODIUM OFF) #set(DISCORD_INTEGRATION OFF) #set(BUILD_TESTING OFF) #set(NOEXIT ON) diff --git a/CMake/ps5_defs.cmake b/CMake/ps5_defs.cmake index 5002117ebb3..8620d5275e3 100644 --- a/CMake/ps5_defs.cmake +++ b/CMake/ps5_defs.cmake @@ -7,7 +7,7 @@ set(UBSAN OFF) # Failed to build FSELF: no symbol section #set(DISABLE_STRIP ON) #set(DISABLE_LTO ON) -set(NONET ON) +#set(NONET ON) set(NOMEMCCPY ON) #set(DISCORD_INTEGRATION OFF) #set(BUILD_TESTING OFF) diff --git a/CMake/switch_defs.cmake b/CMake/switch_defs.cmake index a5e4ecdf5fe..1ef90f9d323 100644 --- a/CMake/switch_defs.cmake +++ b/CMake/switch_defs.cmake @@ -3,9 +3,10 @@ set(ASAN OFF) set(UBSAN OFF) # General build options. +set(NONET ON) #set(ZEROTIER OFF) # Disable system dependencies. -set(DEVILUTIONX_SYSTEM_LIBSODIUM OFF) +#set(DEVILUTIONX_SYSTEM_LIBSODIUM OFF) set(PREFILL_PLAYER_NAME ON) diff --git a/CMake/vita_defs.cmake b/CMake/vita_defs.cmake index de9b835beee..0a45d9c4049 100644 --- a/CMake/vita_defs.cmake +++ b/CMake/vita_defs.cmake @@ -5,8 +5,9 @@ set(UBSAN OFF) # General build options. # The Vita build needs the information set(DISABLE_STRIP ON) +set(NONET ON) #set(ZEROTIER OFF) # Disable system dependencies. -set(DEVILUTIONX_SYSTEM_LIBSODIUM OFF) +#set(DEVILUTIONX_SYSTEM_LIBSODIUM OFF) set(PREFILL_PLAYER_NAME ON) diff --git a/CMake/windows9x_defs.cmake b/CMake/windows9x_defs.cmake index b9fbb621d8a..626e869ed58 100644 --- a/CMake/windows9x_defs.cmake +++ b/CMake/windows9x_defs.cmake @@ -1,11 +1,12 @@ set(ASAN OFF) set(UBSAN OFF) -#set(NONET ON) set(USE_SDL1 ON) +#set(NONET ON) +set(ZEROTIER OFF) #set(DEVILUTIONX_SYSTEM_BZIP2 OFF) #set(DEVILUTIONX_SYSTEM_LIBFMT OFF) -#set(DEVILUTIONX_STATIC_LIBSODIUM OFF) +set(DEVILUTIONX_STATIC_LIBSODIUM OFF) # Compatibility with Windows 9x 8-bit mode and improved performance set(SDL1_VIDEO_MODE_BPP 8) From ff337c40c723c24efb38fdaf8ec25fbc432bfba6 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 7 Sep 2024 08:13:18 +0200 Subject: [PATCH 545/596] do not disable LTO on ps4 --- CMake/ps4_defs.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMake/ps4_defs.cmake b/CMake/ps4_defs.cmake index 0e05c737476..a93d9b47e08 100644 --- a/CMake/ps4_defs.cmake +++ b/CMake/ps4_defs.cmake @@ -6,7 +6,7 @@ set(UBSAN OFF) # If the executable is stripped, create-fself fails with: # Failed to build FSELF: no symbol section set(DISABLE_STRIP ON) -set(DISABLE_LTO ON) +#set(DISABLE_LTO ON) set(NONET ON) #set(ZEROTIER OFF) #set(DEVILUTIONX_SYSTEM_LIBSODIUM OFF) From 2a4c1d9fe48fd7240e564b0fb53816d40d0e1f4e Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 7 Sep 2024 12:09:12 +0200 Subject: [PATCH 546/596] SLA fixes - mark subtile 76 extern in L4.SLA - subtile 180 is North-West wall in L2.SLA --- Packaging/resources/devilx.mpq | Bin 1250149 -> 1250148 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Packaging/resources/devilx.mpq b/Packaging/resources/devilx.mpq index fc5e6189ca9d7d21fb469cdac291fa6ef3ff359c..a0c1ff12c124ab698f1c23e2fe8f0ca671fa4058 100644 GIT binary patch delta 3872 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
  2. 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 j5DbS%5DkY&5Dte(5D$k)5D Date: Sun, 8 Sep 2024 07:41:56 +0200 Subject: [PATCH 547/596] do not report libsodium usage if nonet is not set --- CMakeLists.txt | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dc638208e28..8345a0cea98 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1694,15 +1694,17 @@ else() message(STATUS " Using dynamically linked SDL2.") endif() endif() -if(DEVILUTIONX_STATIC_LIBSODIUM) - set(_LINK_MODE "statically") -else() - set(_LINK_MODE "dynamically") -endif() -if(DEVILUTIONX_SYSTEM_LIBSODIUM) - set(_SOURCE "system ") -else() - set(_SOURCE "") +if(NOT NONET) + if(DEVILUTIONX_STATIC_LIBSODIUM) + set(_LINK_MODE "statically") + else() + set(_LINK_MODE "dynamically") + endif() + if(DEVILUTIONX_SYSTEM_LIBSODIUM) + set(_SOURCE "system ") + else() + set(_SOURCE "") + endif() + message(STATUS " Using ${_LINK_MODE} linked ${_SOURCE}libsodium.") endif() -message(STATUS " Using ${_LINK_MODE} linked ${_SOURCE}libsodium.") message(STATUS "") From 30d22908f99c0c062c3435f5eeebb4fdfbe2c002 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 8 Sep 2024 07:42:24 +0200 Subject: [PATCH 548/596] use static sdl2/libsodium by default --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8345a0cea98..b5b5769b00c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -181,12 +181,12 @@ cmake_dependent_option(HAS_TOUCHPAD "Enable touchpad support" ON "NOT USE_SDL1" option(SCREEN_READER_INTEGRATION "Build with screen reader support" OFF) if(NOT NONET) - option(DEVILUTIONX_SYSTEM_LIBSODIUM "Use system-provided libsodium" ON) + option(DEVILUTIONX_SYSTEM_LIBSODIUM "Use system-provided libsodium" OFF) cmake_conditional_option(DEVILUTIONX_STATIC_LIBSODIUM "Link static libsodium" NOT ${DEVILUTIONX_SYSTEM_LIBSODIUM}) endif() if(NOT USE_SDL1) - option(DEVILUTIONX_SYSTEM_SDL2 "Use system-provided SDL2" ON) + option(DEVILUTIONX_SYSTEM_SDL2 "Use system-provided SDL2" OFF) cmake_conditional_option(DEVILUTIONX_STATIC_SDL2 "Link static SDL2" NOT ${DEVILUTIONX_SYSTEM_SDL2}) endif() From aa57643ac96ffb1d8acb12cd7dcf3856bd8f8f4e Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 9 Sep 2024 11:33:26 +0200 Subject: [PATCH 549/596] simplify CanPut after 'rework targeting' --- Source/inv.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/inv.cpp b/Source/inv.cpp index 686fd8f72e9..16e0c402464 100644 --- a/Source/inv.cpp +++ b/Source/inv.cpp @@ -1474,7 +1474,7 @@ bool CanPut(int x, int y) return false; } - oi = dObject[x + 1][y + 1]; + /*oi = dObject[x + 1][y + 1]; if (oi != 0) { oi = oi >= 0 ? oi - 1 : -(oi + 1); if (objects[oi]._oSelFlag != 0) @@ -1486,10 +1486,10 @@ bool CanPut(int x, int y) oi2 = dObject[x][y + 1]; if (oi2 > 0 && objects[oi - 1]._oSelFlag != 0 && objects[oi2 - 1]._oSelFlag != 0) return false; - } + }*/ if (currLvl._dType == DTYPE_TOWN) - if ((dMonster[x][y] | dMonster[x + 1][y + 1]) != 0) + if ((dMonster[x][y] /*| dMonster[x + 1][y + 1]*/) != 0) return false; return true; From cf48b15ebea7007db4ae75613db32d54bd6f80a2 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 9 Sep 2024 11:34:22 +0200 Subject: [PATCH 550/596] use CanPut in ItemSpaceOk --- Source/items.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/items.cpp b/Source/items.cpp index c71d780e2a9..3643b695db3 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -1065,6 +1065,8 @@ void CreatePlrItems(int pnum) */ bool ItemSpaceOk(int x, int y) { + return CanPut(x, y) && (dMonster[x][y] | dPlayer[x][y]) == 0; +#if 0 int oi; if (x < DBORDERX || x >= DBORDERX + DSIZEX || y < DBORDERY || y >= DBORDERY + DSIZEY) @@ -1099,6 +1101,7 @@ bool ItemSpaceOk(int x, int y) return false; */ return true; +#endif } static bool GetItemSpace(int x, int y, int ii) From be1478dc6050fc1c9ac3d3e603b248855ed210ef Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 9 Sep 2024 11:41:37 +0200 Subject: [PATCH 551/596] improve item placement - previous logic: 1. try to place around the target using ItemSpaceOk (does not place over monsters/players) 2... try to place further away using ItemSpaceOk (does not place over monsters/players) - new logic: 1. try to place around the target using ItemSpaceOk (does not place over monsters/players) 2. try to place around the target using CanPut (ignores monsters/players) 3. try to place further away using LineClear and CanPut (ignores monsters/players) 4. try to place further away using CanPut (ignores monsters/players) --- Source/items.cpp | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/Source/items.cpp b/Source/items.cpp index 3643b695db3..0889cb79a36 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -1104,14 +1104,14 @@ bool ItemSpaceOk(int x, int y) #endif } -static bool GetItemSpace(int x, int y, int ii) +static bool GetItemSpace(int x, int y, bool (func)(int x, int y), int ii) { BYTE i, rs; BYTE slist[NUM_DIRS + 1]; rs = 0; for (i = 0; i < lengthof(area3x3_x); i++) { - if (ItemSpaceOk(x + area3x3_x[i], y + area3x3_y[i])) { + if (func(x + area3x3_x[i], y + area3x3_y[i])) { slist[rs] = i; rs++; } @@ -1129,21 +1129,27 @@ static bool GetItemSpace(int x, int y, int ii) static void GetSuperItemSpace(int x, int y, int ii) { int xx, yy; - int i, j, k; - - if (!GetItemSpace(x, y, ii)) { - for (k = 2; k < 50; k++) { - for (j = -k; j <= k; j++) { - yy = y + j; - for (i = -k; i <= k; i++) { - xx = i + x; - if (ItemSpaceOk(xx, yy)) { - SetItemLoc(ii, xx, yy); - return; - } + int i, j; + + if (!GetItemSpace(x, y, ItemSpaceOk, ii) && !GetItemSpace(x, y, CanPut, ii)) { + const int8_t* cr; + bool ignoreLine = false; +restart: + for (i = 2; i < lengthof(CrawlNum); i--) { + cr = &CrawlTable[CrawlNum[i]]; + for (j = (BYTE)*cr; j > 0; j--) { + xx = x + *++cr; + yy = y + *++cr; + if (CanPut(xx, yy) && (ignoreLine || LineClear(x, y, xx, yy))) { + SetItemLoc(ii, xx, yy); + return; } } } + if (!ignoreLine) { + ignoreLine = true; + goto restart; + } } } From 9564fab1729cf780cc715ac2673eec374f598784 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 9 Sep 2024 11:48:46 +0200 Subject: [PATCH 552/596] make pPack argument of UnPackPlayer constant --- Source/pack.cpp | 4 ++-- Source/pack.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/pack.cpp b/Source/pack.cpp index 40fe7afd0ce..6396557be9e 100644 --- a/Source/pack.cpp +++ b/Source/pack.cpp @@ -133,11 +133,11 @@ static void UnPackItem(const PkItemStruct* pis, ItemStruct* is) } } -void UnPackPlayer(PkPlayerStruct* pPack, int pnum) +void UnPackPlayer(const PkPlayerStruct* pPack, int pnum) { int i; ItemStruct* pi; - PkItemStruct* pki; + const PkItemStruct* pki; // TODO: validate data from the internet //SetPlayerLoc(&plr, pPack->px, pPack->py); diff --git a/Source/pack.h b/Source/pack.h index 5ba52907642..565d8ca007a 100644 --- a/Source/pack.h +++ b/Source/pack.h @@ -13,7 +13,7 @@ extern "C" { #endif void PackPlayer(PkPlayerStruct* pPack, int pnum); -void UnPackPlayer(PkPlayerStruct* pPack, int pnum); +void UnPackPlayer(const PkPlayerStruct* pPack, int pnum); /* rdata */ #ifdef __cplusplus From 929c9193bea114d8fdf260b8d2abad3cf84fa884 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 9 Sep 2024 12:01:02 +0200 Subject: [PATCH 553/596] bump androind-ndk --- android-project/app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android-project/app/build.gradle b/android-project/app/build.gradle index a09c4122f66..97592e04a70 100644 --- a/android-project/app/build.gradle +++ b/android-project/app/build.gradle @@ -7,8 +7,8 @@ if (buildAsApplication) { } android { - // ndkVersion '26.1.10909125' - asio is not ready for this - ndkVersion '25.2.9519653' + ndkVersion '26.1.10909125' + // ndkVersion '25.2.9519653' compileSdk 35 aaptOptions { // probably does not matter... noCompress 'mpq' From 4ccea443acfdfb37c7bab1934a6b3a1e643186fc Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 11 Sep 2024 08:10:00 +0200 Subject: [PATCH 554/596] do not reset infostr - no need to reset infostr, it is supposed to work like tempstr --- Source/control.cpp | 3 ++- Source/controls/plrctrls.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/control.cpp b/Source/control.cpp index 017c2f375e5..8ccf1d094fe 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -945,7 +945,8 @@ void InitControlPan() pSTextSlidCels = CelLoadImage("Data\\TextSlid.CEL", SMALL_SCROLL_WIDTH); assert(pDurIconCels == NULL); pDurIconCels = CelLoadImage("Items\\DurIcons.CEL", DURICON_WIDTH); - infostr[0] = '\0'; + // infostr[0] = '\0'; + // tempstr[0] = '\0'; gbRedrawFlags |= REDRAW_HP_FLASK | REDRAW_MANA_FLASK | REDRAW_SPEED_BAR; gbLvlUp = false; gbSkillListFlag = false; diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index 1154bb2ee56..902b89a980b 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -1003,7 +1003,7 @@ void plrctrls_after_check_curs_move() return; } if (!gbInvflag) { - *infostr = '\0'; + // infostr[0] = '\0'; bool ranged = HasRangedSkill(); switch (pcurstgt) { From 535e4aed2f094dc0f8609e3896ec8a357906c5de Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 12 Sep 2024 15:29:31 +0200 Subject: [PATCH 555/596] make RecreateTownItem static --- Source/items.cpp | 56 ++++++++++++++++++++++++------------------------ Source/items.h | 1 - 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/Source/items.cpp b/Source/items.cpp index 0889cb79a36..6bdbd244919 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -2174,33 +2174,6 @@ void CreateTypeItem(int x, int y, unsigned quality, int itype, int imisc, int mo } } -void RecreateItem(int iseed, uint16_t wIndex, uint16_t wCI) -{ - if (wIndex == IDI_GOLD) { - SetItemData(MAXITEMS, IDI_GOLD); - //items[MAXITEMS]._iSeed = iseed; - //items[MAXITEMS]._iCreateInfo = wCI; - } else { - if ((wCI & ~CF_LEVEL) == 0) { - SetItemData(MAXITEMS, wIndex); - //items[MAXITEMS]._iSeed = iseed; - //items[MAXITEMS]._iCreateInfo = wCI; - } else { - if (wCI & CF_TOWN) { - RecreateTownItem(MAXITEMS, iseed, wIndex, wCI); - // items[MAXITEMS]._iSeed = iseed; - // items[MAXITEMS]._iCreateInfo = wCI; - //} else if ((wCI & CF_USEFUL) == CF_USEFUL) { - // SetupAllUseful(MAXITEMS, iseed, wCI & CF_LEVEL); - } else { - SetupAllItems(MAXITEMS, wIndex, iseed, wCI & CF_LEVEL, (wCI & CF_DROP_QUALITY) >> 11); //, onlygood); - } - } - } - items[MAXITEMS]._iSeed = iseed; - items[MAXITEMS]._iCreateInfo = wCI; -} - /** * Place a fixed item to the given location. * @@ -3829,7 +3802,7 @@ static void RecreateCraftedItem(int ii/*, int iseed*/, int idx, unsigned lvl) //items[ii]._iCreateInfo = lvl | CF_CRAFTED; } -void RecreateTownItem(int ii, int iseed, uint16_t idx, uint16_t icreateinfo) +static void RecreateTownItem(int ii, int iseed, uint16_t idx, uint16_t icreateinfo) { int loc; unsigned lvl; @@ -3921,4 +3894,31 @@ void SpawnMagicItem(int itype, int icurs, int x, int y, bool sendmsg) NetSendCmdSpawnItem(true); } +void RecreateItem(int iseed, uint16_t wIndex, uint16_t wCI) +{ + if (wIndex == IDI_GOLD) { + SetItemData(MAXITEMS, IDI_GOLD); + //items[MAXITEMS]._iSeed = iseed; + //items[MAXITEMS]._iCreateInfo = wCI; + } else { + if ((wCI & ~CF_LEVEL) == 0) { + SetItemData(MAXITEMS, wIndex); + //items[MAXITEMS]._iSeed = iseed; + //items[MAXITEMS]._iCreateInfo = wCI; + } else { + if (wCI & CF_TOWN) { + RecreateTownItem(MAXITEMS, iseed, wIndex, wCI); + // items[MAXITEMS]._iSeed = iseed; + // items[MAXITEMS]._iCreateInfo = wCI; + //} else if ((wCI & CF_USEFUL) == CF_USEFUL) { + // SetupAllUseful(MAXITEMS, iseed, wCI & CF_LEVEL); + } else { + SetupAllItems(MAXITEMS, wIndex, iseed, wCI & CF_LEVEL, (wCI & CF_DROP_QUALITY) >> 11); //, onlygood); + } + } + } + items[MAXITEMS]._iSeed = iseed; + items[MAXITEMS]._iCreateInfo = wCI; +} + DEVILUTION_END_NAMESPACE diff --git a/Source/items.h b/Source/items.h index b460516c7b9..62da917a7bf 100644 --- a/Source/items.h +++ b/Source/items.h @@ -71,7 +71,6 @@ void SpawnPremium(unsigned lvl); void SpawnWitch(unsigned lvl); void SpawnBoy(unsigned lvl); void SpawnHealer(unsigned lvl); -void RecreateTownItem(int ii, int iseed, uint16_t idx, uint16_t icreateinfo); void SpawnSpellBook(int ispell, int x, int y, bool sendmsg); void SpawnMagicItem(int itype, int icurs, int x, int y, bool sendmsg); From 56614b3d736edaf88348c415b21724aceb062e0e Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 12 Sep 2024 16:48:03 +0200 Subject: [PATCH 556/596] fix (h2h) acid-damage calculation bugfix for 'uniform elemental damage/resists' --- Source/player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/player.cpp b/Source/player.cpp index b22b8634db5..16d531b7e25 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -2019,7 +2019,7 @@ static bool PlrHitMonst(int pnum, int sn, int sl, int mnum) int mdam = plr._pIMMaxDam; if (mdam != 0) mdam = CalcMonsterDam(mon->_mMagicRes, MISR_MAGIC, plr._pIMMinDam, mdam, false); - int adam = 0; + int adam = plr._pIAMaxDam; if (adam != 0) adam = CalcMonsterDam(mon->_mMagicRes, MISR_ACID, plr._pIAMinDam, adam, false); From 3c5a02f8e5c8210487f1fdbb62dcfc6c048dac04 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 13 Sep 2024 09:27:26 +0200 Subject: [PATCH 557/596] bugfix for vanilla (El Chupacabras vs MAI_ROUND) - do not use special attack logic with the scavenging animation --- Source/monstdat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/monstdat.cpp b/Source/monstdat.cpp index ae345028dc5..2ae9e583e6c 100644 --- a/Source/monstdat.cpp +++ b/Source/monstdat.cpp @@ -425,7 +425,7 @@ const UniqMonData uniqMonData[] = { { MT_TSKELSD, "Brokenhead Bangshield", "BHBS", DLV_CATHEDRAL3, 6, 108, { AI_SKELSD, 3, 0, 0 }, 12, 20, 0, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE , UMF_GANG, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, { MT_YFALLSP, "Bongo", "BNG", DLV_CATHEDRAL3, 6, 178, { AI_FALLEN, 3, 0, 0 }, 9, 21, 0, 0, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, UMF_GANG, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, { MT_BZOMBIE, "Rotcarnage", "RCRN", DLV_CATHEDRAL3, 6, 102, { AI_ZOMBIE, 3, 0, 0 }, 9, 24, 0, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_RESIST , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_LIGHTNING_IMMUNE , UMF_GANG, 0, 0, 0, 0, 35, Q_INVALID, TEXT_NONE, ALIGN }, - { MT_BSCAV, "El Chupacabras", "GENERAL", DLV_CATHEDRAL3, 6, 120, { AI_ROUND, 0, TRUE, 0 }, 10, 18, 30, 30, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, UMF_GANG, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, + { MT_BSCAV, "El Chupacabras", "GENERAL", DLV_CATHEDRAL3, 6, 120, { AI_ROUND, 0, FALSE, 0 }, 10, 18, 0, 0, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_ACID_IMMUNE, MORS_BLUNT_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, UMF_GANG, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, { MT_TSKELBW, "Skullfire", "SKFR", DLV_CATHEDRAL3, 6, 125, { AI_RANGED, 1, MIS_ARROW, FALSE }, 6, 10, 0, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_FIRE_IMMUNE , 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, { MT_NSNEAK, "Warpskull", "TSPO", DLV_CATHEDRAL3, 6, 117, { AI_SNEAK, 2, 0, 0 }, 6, 18, 0, 0, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_RESIST | MORS_ACID_IMMUNE, MORS_SLASH_PROTECTED | MORS_BLUNT_PROTECTED | MORS_PUNCTURE_PROTECTED | MORS_FIRE_RESIST | MORS_LIGHTNING_IMMUNE | MORS_ACID_IMMUNE, UMF_GANG, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, { MT_GZOMBIE, "Goretongue", "PMR", DLV_CATHEDRAL3, 6, 156, { AI_SKELSD, 1, 0, 0 }, 15, 30, 0, 0, MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE , MORS_SLASH_RESIST | MORS_PUNCTURE_PROTECTED | MORS_MAGIC_IMMUNE | MORS_FIRE_RESIST , 0, 0, 0, 0, 0, 0, Q_INVALID, TEXT_NONE, ALIGN }, From 8484bfd94ae849792c51ea75bb9a1477e70e5022 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 13 Sep 2024 12:14:23 +0200 Subject: [PATCH 558/596] fix the handling of manashields from scrolls --- Source/missiles.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index af9d849ec56..d9759f0c784 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -3377,7 +3377,7 @@ int AddManashield(int mi, int sx, int sy, int dx, int dy, int midir, int micaste if (misource == mypnum) { if (plx(misource)._pManaShield == 0) - NetSendCmdBParam1(CMD_SETSHIELD, spllvl); + NetSendCmdBParam1(CMD_SETSHIELD, spllvl + 1); else NetSendCmd(CMD_REMSHIELD); } From 027289eb16691b40bcbc6ac300241587fb97ba07 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 13 Sep 2024 15:55:34 +0200 Subject: [PATCH 559/596] handle Swamp-skill in GetDamageAmt --- Source/missiles.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index d9759f0c784..dbfee716fb0 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -92,6 +92,7 @@ void GetDamageAmt(int sn, int sl, int* minv, int* maxv) case SPL_CHARGE: case SPL_RAGE: case SPL_SHROUD: + case SPL_SWAMP: case SPL_STONE: case SPL_INFRA: case SPL_MANASHIELD: From 5a7c81d64d0a72cf8f4c2f610e680d3b56ced0f5 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 13 Sep 2024 16:26:28 +0200 Subject: [PATCH 560/596] validate GetDamageAmt in ValidateData --- Source/debug.cpp | 4 +++- Source/missiles.cpp | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/debug.cpp b/Source/debug.cpp index 996ebbc1121..d4fc288ecf9 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -92,7 +92,7 @@ static void PrintText(const char* text, char lineSep, int limit) col = COL_WHITE; } s = ReadTextLine(s, lineSep, limit); - // w = GetSmallStringWidth(tempstr); + // w = GetSmallStringWidth(tempstr); // LogErrorF("%03d(%04d):%s", i++, w, tempstr); if (col == COL_RED) @@ -1291,6 +1291,8 @@ void ValidateData() bool hasBookSpell = false, hasStaffSpell = false, hasScrollSpell = false, hasRuneSpell = false; for (i = 0; i < NUM_SPELLS; i++) { const SpellData& sd = spelldata[i]; + int mind, maxd; + GetDamageAmt(i, 0, &mind, &maxd); if (i == SPL_DISARM || i == SPL_HEALOTHER || i == SPL_RESURRECT || i == SPL_IDENTIFY || i == SPL_OIL || i == SPL_REPAIR || i == SPL_RECHARGE diff --git a/Source/missiles.cpp b/Source/missiles.cpp index dbfee716fb0..a0cce90e37a 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -105,6 +105,7 @@ void GetDamageAmt(int sn, int sl, int* minv, int* maxv) case SPL_HEALOTHER: case SPL_RESURRECT: case SPL_IDENTIFY: + case SPL_OIL: case SPL_REPAIR: case SPL_RECHARGE: case SPL_DISARM: From 83703fcab757b2649c470e51676693b0f001e9df Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 16 Sep 2024 11:18:31 +0200 Subject: [PATCH 561/596] bugfix for 'rework the handling of the skills' - set rnd-seed in CreatePlayer to have distinct seeds for the base items --- Source/player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/player.cpp b/Source/player.cpp index 16d531b7e25..41311057b49 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -629,7 +629,7 @@ void CreatePlayer(const _uiheroinfo& heroinfo) int i, pnum = 0; memset(&plr, 0, sizeof(PlayerStruct)); - //SetRndSeed(SDL_GetTicks()); + SetRndSeed(SDL_GetTicks()); // used by CreatePlrItems / CreateBaseItem plr._pLevel = heroinfo.hiLevel; plr._pClass = heroinfo.hiClass; From e8d4060299bb9b92a0d17514d3ba0d442a1d42c4 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 17 Sep 2024 09:55:43 +0200 Subject: [PATCH 562/596] use time() instead of SDL_GetTicks() to save the hero data periodically --- Source/pfile.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Source/pfile.cpp b/Source/pfile.cpp index 02d080b411f..48b38b6eafd 100644 --- a/Source/pfile.cpp +++ b/Source/pfile.cpp @@ -11,6 +11,7 @@ #include "diabloui.h" #include "utils/file_util.h" #include "DiabloUI/diablo.h" +#include DEVILUTION_BEGIN_NAMESPACE @@ -18,11 +19,11 @@ DEVILUTION_BEGIN_NAMESPACE #define SAVEFILE_HERO "hero" #define PFILE_SAVE_MPQ_HASHCOUNT 2048 #define PFILE_SAVE_MPQ_BLOCKCOUNT 2048 -#define PFILE_SAVE_INTERVAL 60000 +#define PFILE_SAVE_INTERVAL 60 unsigned mySaveIdx; bool gbValidSaveFile; -static Uint32 guNextSaveTc; +static uint32_t guNextSaveTc; #define PASSWORD_SINGLE "xrgyrkj1" #define PASSWORD_MULTI "szqnlsk1" @@ -304,7 +305,7 @@ void pfile_read_hero_from_save() mypnum = 0; gbValidSaveFile = pfile_archive_contains_game(archive); SFileCloseArchive(archive); - guNextSaveTc = SDL_GetTicks() + PFILE_SAVE_INTERVAL; + guNextSaveTc = time(NULL) + PFILE_SAVE_INTERVAL; } void pfile_rename_temp_to_perm() @@ -418,7 +419,7 @@ void pfile_read_save_file(bool full) void pfile_update(bool force_save) { if (IsMultiGame) { - Uint32 currTc = SDL_GetTicks(); + uint32_t currTc = time(NULL); if (force_save || currTc > guNextSaveTc) { guNextSaveTc = currTc + PFILE_SAVE_INTERVAL; pfile_write_hero(false); From 11a42d4c1cb951af09103f1bc9d4c46ef32bcdac Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 19 Sep 2024 08:01:07 +0200 Subject: [PATCH 563/596] add PlrCheckBlock --- Source/missiles.cpp | 22 ++++--------------- Source/monster.cpp | 15 ++++--------- Source/player.cpp | 51 +++++++++++++++++++++++---------------------- Source/player.h | 2 +- 4 files changed, 35 insertions(+), 55 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index a0cce90e37a..d84465bb2bf 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -1047,15 +1047,8 @@ static bool MissPlrHitByMon(int pnum, int mi) return false; if (!(mis->_miFlags & MIF_NOBLOCK)) { - tmp = plr._pIBlockChance; - if (tmp != 0 && (plr._pmode == PM_STAND || plr._pmode == PM_BLOCK)) { - // assert(plr._pSkillFlags & SFLAG_BLOCK); - tmp = tmp - (misource >= 0 ? 2 * monsters[misource]._mLevel : 2 * currLvl._dLevel); - if (tmp > random_(73, 100)) { - PlrStartBlock(pnum, mis->_misx, mis->_misy); - return true; - } - } + if (PlrCheckBlock(pnum, misource >= 0 ? monsters[misource]._mLevel : currLvl._dLevel, mis->_misx, mis->_misy)) + return true; } dam = CalcPlrDam(pnum, mis->_miResist, mis->_miMinDam, mis->_miMaxDam); @@ -1112,15 +1105,8 @@ static bool MissPlrHitByPlr(int pnum, int mi) return false; if (!(mis->_miFlags & MIF_NOBLOCK)) { - tmp = plr._pIBlockChance; - if (tmp != 0 && (plr._pmode == PM_STAND || plr._pmode == PM_BLOCK)) { - // assert(plr._pSkillFlags & SFLAG_BLOCK); - tmp = tmp - 2 * plx(offp)._pLevel; - if (tmp > random_(73, 100)) { - PlrStartBlock(pnum, mis->_misx, mis->_misy); - return true; - } - } + if (PlrCheckBlock(pnum, plx(offp)._pLevel, mis->_misx, mis->_misy)) + return true; } if (mis->_miFlags & MIF_ARROW) { diff --git a/Source/monster.cpp b/Source/monster.cpp index ab80c21abfe..2bc3fc1145a 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -2355,7 +2355,7 @@ static void MonHitMon(int offm, int defm, int hper, int mind, int maxd) static void MonHitPlr(int mnum, int pnum, int hper, int MinDam, int MaxDam) { MonsterStruct* mon; - int dam, blkper; + int dam; unsigned hitFlags; if ((unsigned)pnum >= MAX_PLRS) { @@ -2371,16 +2371,9 @@ static void MonHitPlr(int mnum, int pnum, int hper, int MinDam, int MaxDam) if (!CheckHit(hper)) return; - blkper = plr._pIBlockChance; - if (blkper != 0 - && (plr._pmode == PM_STAND || plr._pmode == PM_BLOCK)) { - // assert(plr._pSkillFlags & SFLAG_BLOCK); - blkper = blkper - (mon->_mLevel << 1); - if (blkper > random_(98, 100)) { - PlrStartBlock(pnum, mon->_mx, mon->_my); - return; - } - } + if (PlrCheckBlock(pnum, mon->_mLevel, mon->_mx, mon->_my)) + return; + if (mon->_mType == MT_YZOMBIE && pnum == mypnum) { NetSendCmd(CMD_DECHP); } diff --git a/Source/player.cpp b/Source/player.cpp index 41311057b49..4cf3356f2de 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -2059,16 +2059,8 @@ static bool PlrHitPlr(int offp, int sn, int sl, int pnum) if (!CheckHit(hper)) return false; - blkper = plr._pIBlockChance; - if (blkper != 0 - && (plr._pmode == PM_STAND || plr._pmode == PM_BLOCK)) { - // assert(plr._pSkillFlags & SFLAG_BLOCK); - blkper = blkper - (plx(offp)._pLevel << 1); - if (blkper > random_(5, 100)) { - PlrStartBlock(pnum, plx(offp)._px, plx(offp)._py); - return true; - } - } + if (PlrCheckBlock(pnum, plx(offp)._pLevel, plx(offp)._px, plx(offp)._py)) + return true; dam = 0; damsl = plx(offp)._pISlMaxDam; @@ -2332,14 +2324,10 @@ static void ShieldDur(int pnum) //#endif } -void PlrStartBlock(int pnum, int sx, int sy) +static void PlrStartBlock(int pnum, int sx, int sy) { int dir; - if ((unsigned)pnum >= MAX_PLRS) { - dev_fatal("PlrStartBlock: illegal player %d", pnum); - } - if (plr._pHitPoints < (1 << 6)) { StartPlrKill(pnum, DMGTYPE_UNKNOWN); // BUGFIX: is this really necessary? return; @@ -2358,6 +2346,27 @@ void PlrStartBlock(int pnum, int sx, int sy) } } +bool PlrCheckBlock(int pnum, int bmod, int sx, int sy) +{ + if ((unsigned)pnum >= MAX_PLRS) { + dev_fatal("PlrCheckBlock: illegal player %d", pnum); + } + + bool result = false; + int blkper = plr._pIBlockChance; + if (blkper != 0 + && (plr._pmode == PM_STAND || plr._pmode == PM_BLOCK)) { + // assert(plr._pSkillFlags & SFLAG_BLOCK); + blkper = blkper - bmod * 2; + if (blkper > random_(98, 100)) { + PlrStartBlock(pnum, sx, sy); + result = true; + } + } + + return result; +} + static void PlrDoBlock(int pnum) { int extlen; @@ -3005,16 +3014,8 @@ void MissToPlr(int mi, bool hit) if (!CheckHit(hper)) return; - blkper = plx(mpnum)._pIBlockChance; - if (blkper != 0 - && (plx(mpnum)._pmode == PM_STAND || plx(mpnum)._pmode == PM_BLOCK)) { - // assert(plr._pSkillFlags & SFLAG_BLOCK); - blkper = blkper - (plr._pLevel << 1); - if (blkper > random_(5, 100)) { - PlrStartBlock(mpnum, mis->_misx, mis->_misy); - return; - } - } + if (PlrCheckBlock(mpnum, plr._pLevel, mis->_misx, mis->_misy)) + return; dam = CalcPlrDam(mpnum, MISR_BLUNT, minbl, maxbl); //if (random_(151, 200) < plr._pICritChance) diff --git a/Source/player.h b/Source/player.h index 359cde154fb..beeacb181d2 100644 --- a/Source/player.h +++ b/Source/player.h @@ -37,8 +37,8 @@ void RemoveLvlPlayer(int pnum); //void PlrDoTrans(int x, int y); void FixPlayerLocation(int pnum); void PlrStartStand(int pnum); -void PlrStartBlock(int pnum, int sx, int sy); void RemovePlrFromMap(int pnum); +bool PlrCheckBlock(int pnum, int bmod, int sx, int sy); void PlrHitByAny(int pnum, int mpnum, int dam, unsigned hitflags, int sx, int sy); void SyncPlrKill(int pnum); void SyncPlrResurrect(int pnum); From 0d31688f7c75715c1a28a8ac9ea87dc9617b8c7c Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 19 Sep 2024 08:54:15 +0200 Subject: [PATCH 564/596] eliminate poinless hp-check --- Source/player.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Source/player.cpp b/Source/player.cpp index 4cf3356f2de..b1a2e96c4cc 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -2328,11 +2328,6 @@ static void PlrStartBlock(int pnum, int sx, int sy) { int dir; - if (plr._pHitPoints < (1 << 6)) { - StartPlrKill(pnum, DMGTYPE_UNKNOWN); // BUGFIX: is this really necessary? - return; - } - dir = GetDirection(plr._px, plr._py, sx, sy); if (plr._pmode != PM_BLOCK) { assert(plr._pmode == PM_STAND); From 776092661eee9355bd4a04c3034205cce1f98fc9 Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 19 Sep 2024 08:56:13 +0200 Subject: [PATCH 565/596] validate spelldata.sMissile value in ValidateData - ensure either sType or SFLAG_RANGED-flag in sUseFlags is set --- Source/debug.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/debug.cpp b/Source/debug.cpp index d4fc288ecf9..71b91d9e6e8 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -1359,6 +1359,8 @@ void ValidateData() app_fatal("Targeted skill %s (%d) does not have scCurs.", sd.sNameText, i); hasScrollSpell = true; } + if (sd.sMissile != 0 && sd.sType == STYPE_NONE && !(sd.sUseFlags & SFLAG_RANGED)) // required by On_SKILLXY, On_SKILLMON, On_SKILLPLR + app_fatal("Skill %s (%d) supposed to use a missile, but neither sType nor the SFLAG_RANGED-flag is set.", sd.sNameText, i); //if (!(sd.sUseFlags & SFLAG_DUNGEON) && sd.sType != STYPE_NONE && sd.sType != STYPE_MAGIC && i != SPL_NULL) // app_fatal("GFX is not loaded in town for skill %s (%d).", sd.sNameText, i); // required by InitPlayerGFX } From 0ca11fd4b7a38a67e11c6811acf9d09d76af1ddf Mon Sep 17 00:00:00 2001 From: pionere Date: Thu, 19 Sep 2024 09:00:21 +0200 Subject: [PATCH 566/596] include ctime instead of time.h --- Source/DiabloUI/selhero.cpp | 2 +- Source/multi.cpp | 2 +- Source/pfile.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/DiabloUI/selhero.cpp b/Source/DiabloUI/selhero.cpp index a51b42913d2..4f9079a257d 100644 --- a/Source/DiabloUI/selhero.cpp +++ b/Source/DiabloUI/selhero.cpp @@ -1,4 +1,4 @@ -#include +#include #include "../all.h" #include "DiabloUI/diablo.h" diff --git a/Source/multi.cpp b/Source/multi.cpp index 3c730fa0ad6..5cf1e6b9591 100644 --- a/Source/multi.cpp +++ b/Source/multi.cpp @@ -6,7 +6,7 @@ #include "all.h" #include "diabloui.h" #include "storm/storm_net.h" -#include +#include #include "DiabloUI/diablo.h" DEVILUTION_BEGIN_NAMESPACE diff --git a/Source/pfile.cpp b/Source/pfile.cpp index 48b38b6eafd..29fb2f8d94c 100644 --- a/Source/pfile.cpp +++ b/Source/pfile.cpp @@ -11,7 +11,7 @@ #include "diabloui.h" #include "utils/file_util.h" #include "DiabloUI/diablo.h" -#include +#include DEVILUTION_BEGIN_NAMESPACE From 3d4e021e000f41513f43656b89e311fc2339fff9 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 20 Sep 2024 09:05:26 +0200 Subject: [PATCH 567/596] reorder PlayerStruct --- Source/loadsave.cpp | 12 ++++++------ structs.h | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index a92968d53b5..7151545596c 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -279,10 +279,11 @@ static BYTE* LoadPlayer(BYTE* DVL_RESTRICT src, int pnum) tbuff += 4; // _pMana tbuff += 4; // _pMaxMana tbuff += 64; // _pSkillLvl + tbuff += 8; // _pISpells + tbuff += 1; // _pSkillFlags tbuff += 1; // _pInfraFlag tbuff += 1; // _pgfxnum tbuff += 1; // _pHasUnidItem - tbuff += 1; // _pAlign_B0 tbuff += 4; // _pISlMinDam tbuff += 4; // _pISlMaxDam tbuff += 4; // _pIBlMinDam @@ -298,12 +299,11 @@ static BYTE* LoadPlayer(BYTE* DVL_RESTRICT src, int pnum) tbuff += 1; // _pLghtResist tbuff += 1; // _pAcidResist tbuff += 4; // _pIHitChance - tbuff += 1; // _pSkillFlags tbuff += 1; // _pIBaseHitBonus tbuff += 1; // _pICritChance tbuff += 1; // _pIBlockChance + tbuff += 1; // _pAlign_B0 - tbuff += 8; // _pISpells tbuff += 4; // _pIFlags tbuff += 1; // _pIWalkSpeed tbuff += 1; // _pIRecoverySpeed @@ -1124,10 +1124,11 @@ static BYTE* SavePlayer(BYTE* DVL_RESTRICT dest, int pnum) tbuff += 4; // _pMana tbuff += 4; // _pMaxMana tbuff += 64; // _pSkillLvl + tbuff += 8; // _pISpells + tbuff += 1; // _pSkillFlags tbuff += 1; // _pInfraFlag tbuff += 1; // _pgfxnum tbuff += 1; // _pHasUnidItem - tbuff += 1; // _pAlign_B0 tbuff += 4; // _pISlMinDam tbuff += 4; // _pISlMaxDam tbuff += 4; // _pIBlMinDam @@ -1143,12 +1144,11 @@ static BYTE* SavePlayer(BYTE* DVL_RESTRICT dest, int pnum) tbuff += 1; // _pLghtResist tbuff += 1; // _pAcidResist tbuff += 4; // _pIHitChance - tbuff += 1; // _pSkillFlags tbuff += 1; // _pIBaseHitBonus tbuff += 1; // _pICritChance tbuff += 1; // _pIBlockChance + tbuff += 1; // _pAlign_B0 - tbuff += 8; // _pISpells tbuff += 4; // _pIFlags tbuff += 1; // _pIWalkSpeed tbuff += 1; // _pIRecoverySpeed diff --git a/structs.h b/structs.h index 4efbdcd98b9..d67074b91dc 100644 --- a/structs.h +++ b/structs.h @@ -428,10 +428,11 @@ typedef struct PlayerStruct { int _pMana; // the current mana of the player int _pMaxMana; // the maximum mana of the player BYTE _pSkillLvl[64]; // the skill levels of the player + uint64_t _pISpells; // Bitmask of skills available via equipped items (staff) + BYTE _pSkillFlags; // Bitmask of allowed skill-types (SFLAG_*) BOOLEAN _pInfraFlag; BYTE _pgfxnum; // Bitmask indicating what variant of the sprite the player is using. Lower byte define weapon (anim_weapon_id) and higher values define armour (starting with anim_armor_id) BOOLEAN _pHasUnidItem; // whether the player has an unidentified (magic) item equipped - BYTE _pAlign_B0; int _pISlMinDam; // min slash-damage (swords, axes) int _pISlMaxDam; // max slash-damage (swords, axes) int _pIBlMinDam; // min blunt-damage (maces, axes) @@ -447,12 +448,11 @@ typedef struct PlayerStruct { int8_t _pLghtResist; int8_t _pAcidResist; int _pIHitChance; - BYTE _pSkillFlags; // Bitmask of allowed skill-types (SFLAG_*) BYTE _pIBaseHitBonus; // indicator whether the base BonusToHit of the items is positive/negative/neutral BYTE _pICritChance; // 200 == 100% BYTE _pIBlockChance; - uint64_t _pISpells; // Bitmask of skills available via equipped items (staff) - unsigned _pIFlags; + BYTE _pAlign_B0; + unsigned _pIFlags; // item_special_effect BYTE _pIWalkSpeed; BYTE _pIRecoverySpeed; BYTE _pIBaseCastSpeed; From 395ef71e2bae09430185f76328688f088343ff2c Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 20 Sep 2024 10:05:09 +0200 Subject: [PATCH 568/596] use time() instead of SDL_GetTicks() to draw chat messages --- Source/plrmsg.cpp | 7 ++++--- structs.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Source/plrmsg.cpp b/Source/plrmsg.cpp index 8a7ec3e7735..c267875793b 100644 --- a/Source/plrmsg.cpp +++ b/Source/plrmsg.cpp @@ -10,10 +10,11 @@ #include "plrctrls.h" #include "utils/utf8.h" #include "storm/storm_net.h" +#include DEVILUTION_BEGIN_NAMESPACE -#define PLRMSG_TEXT_TIMEOUT 10000 +#define PLRMSG_TEXT_TIMEOUT 10 #define PLRMSG_WIDTH (PANEL_WIDTH - 20) static const char gszProductName[] = { PROJECT_NAME " v" PROJECT_VERSION }; @@ -88,7 +89,7 @@ static _plrmsg* AddPlrMsg(int pnum) static_assert((PLRMSG_COUNT & (PLRMSG_COUNT - 1)) == 0, "Modulo to BitAnd optimization requires a power of 2."); plr_msg_slot = (unsigned)(plr_msg_slot + 1) % PLRMSG_COUNT; pMsg->player = pnum; - pMsg->time = SDL_GetTicks(); + pMsg->time = time(NULL); if (pMsg == sgpCurMsg) { sgpCurMsg = &plr_msgs[PLRMSG_COUNT]; } @@ -247,7 +248,7 @@ void DrawPlrMsg(bool onTop) nummsgs = 0; numlines = 0; if (!gbTalkflag) { - timeout = SDL_GetTicks() - PLRMSG_TEXT_TIMEOUT; + timeout = time(NULL) - PLRMSG_TEXT_TIMEOUT; linelimit = 3; } else { numlines += plr_msgs[PLRMSG_COUNT].lineBreak != 0 ? 2 : 1; diff --git a/structs.h b/structs.h index d67074b91dc..4c64fd1ae1c 100644 --- a/structs.h +++ b/structs.h @@ -2672,7 +2672,7 @@ static_warning((sizeof(STextStruct) & (sizeof(STextStruct) - 1)) == 0, "Align ST ////////////////////////////////////////////////// typedef struct _plrmsg { - Uint32 time; + uint32_t time; BYTE player; BYTE lineBreak; char str[122]; From 62175c4cd2c9aa661db74dc21944bc3cdfc7f0f0 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 20 Sep 2024 10:15:01 +0200 Subject: [PATCH 569/596] validate MIF_ARROW in ValidateData --- Source/debug.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Source/debug.cpp b/Source/debug.cpp index 71b91d9e6e8..1ace37292b4 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -1405,6 +1405,10 @@ void ValidateData() assert(misfiledata[md.mFileNum].mfAnimLen[j] < 11 /* lengthof(ExpLight) */); } } + if (md.mdFlags & MIF_ARROW) { + if (i != MIS_ARROW && i != MIS_PBARROW && i != MIS_ASARROW && i != MIS_MLARROW && i != MIS_PCARROW) + app_fatal("Arrow-Missile %d is not handled in MissMonHitByPlr and in MissPlrHitByPlr.", i); + } if (md.mDrawFlag) { if (md.mFileNum == MFILE_NONE && i != MIS_RHINO && i != MIS_CHARGE) app_fatal("Missile %d is drawn, but has no valid mFileNum.", i); @@ -1421,6 +1425,11 @@ void ValidateData() app_fatal("Missile %d is not drawn to the center. Width: %d, Offset: %d", i, mfd.mfAnimWidth, mfd.mfAnimXOffset); } #endif // DEBUG_DATA + assert((missiledata[MIS_ARROW].mdFlags & MIF_ARROW) != 0); // required by MissMonHitByPlr, MissPlrHitByPlr + assert((missiledata[MIS_PBARROW].mdFlags & MIF_ARROW) != 0); // required by MissMonHitByPlr, MissPlrHitByPlr + assert((missiledata[MIS_ASARROW].mdFlags & MIF_ARROW) != 0); // required by MissMonHitByPlr, MissPlrHitByPlr + assert((missiledata[MIS_MLARROW].mdFlags & MIF_ARROW) != 0); // required by MissMonHitByPlr, MissPlrHitByPlr + assert((missiledata[MIS_PCARROW].mdFlags & MIF_ARROW) != 0); // required by MissMonHitByPlr, MissPlrHitByPlr assert(misfiledata[MFILE_LGHNING].mfAnimLen[0] == misfiledata[MFILE_THINLGHT].mfAnimLen[0]); // required by AddLightning assert(misfiledata[MFILE_FIREWAL].mfAnimFrameLen[0] == 1); // required by MI_Firewall assert(misfiledata[MFILE_FIREWAL].mfAnimLen[0] < 14 /* lengthof(FireWallLight) */); // required by MI_Firewall From 32463e7aed2b9460de2654d41554535442ad5d70 Mon Sep 17 00:00:00 2001 From: pionere Date: Fri, 20 Sep 2024 10:17:12 +0200 Subject: [PATCH 570/596] use time() instead of SDL_GetTicks() to draw error (shrine) messages --- Source/error.cpp | 9 +++++---- Source/error.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Source/error.cpp b/Source/error.cpp index 13adbb61b3c..261ea632593 100644 --- a/Source/error.cpp +++ b/Source/error.cpp @@ -7,11 +7,12 @@ #include "engine/render/cel_render.h" #include "engine/render/raw_render.h" #include "engine/render/text_render.h" +#include DEVILUTION_BEGIN_NAMESPACE char msgtable[NUM_EMSGS]; -Uint32 msgdelay; +uint32_t msgdelay; BYTE currmsg; BYTE msgcnt; @@ -101,7 +102,7 @@ void InitDiabloMsg(BYTE e) msgcnt++; currmsg = msgtable[0]; - msgdelay = SDL_GetTicks(); + msgdelay = time(NULL); } void ClrDiabloMsg() @@ -145,7 +146,7 @@ void DrawDiabloMsg() SStrCopy(tempstr, MsgStrings[currmsg], sizeof(tempstr)); PrintJustifiedString(x, y - (SLIDER_BOX_HEIGHT - SMALL_FONT_HEIGHT) / 2, x + (3 * SLIDER_BOX_WIDTH) / 2, tempstr, COL_GOLD, FONT_KERN_SMALL); - if (msgdelay > 0 && msgdelay <= SDL_GetTicks() - 3500) { + if (msgdelay > 0 && msgdelay <= time(NULL) - 4) { msgdelay = 0; } if (msgdelay == 0) { @@ -154,7 +155,7 @@ void DrawDiabloMsg() currmsg = EMSG_NONE; } else { currmsg = msgtable[msgcnt]; - msgdelay = SDL_GetTicks(); + msgdelay = time(NULL); } } } diff --git a/Source/error.h b/Source/error.h index 48a3e3c896a..a176b0b7969 100644 --- a/Source/error.h +++ b/Source/error.h @@ -12,7 +12,7 @@ DEVILUTION_BEGIN_NAMESPACE extern "C" { #endif -extern Uint32 msgdelay; +extern uint32_t msgdelay; extern BYTE currmsg; void InitDiabloMsg(BYTE e); From 70892bbbe1dfce18fe0cee586f70027da2884a13 Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 21 Sep 2024 10:44:48 +0200 Subject: [PATCH 571/596] simplify GetItemSpell --- Source/debug.cpp | 1 + Source/items.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/debug.cpp b/Source/debug.cpp index 1ace37292b4..dfea39f4344 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -1260,6 +1260,7 @@ void ValidateData() #endif // spells + assert(spelldata[SPL_RESURRECT].sManaCost == 0); // required by GetItemSpell assert(spelldata[SPL_TELEPORT].sSkillFlags & SDFLAG_TARGETED); // required by AddTeleport #define OBJ_TARGETING_CURSOR(x) ((x) == CURSOR_NONE || (x) == CURSOR_DISARM) assert(OBJ_TARGETING_CURSOR(spelldata[SPL_DISARM].scCurs)); // required by TryIconCurs diff --git a/Source/items.cpp b/Source/items.cpp index 6bdbd244919..fe6d283d401 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -1352,8 +1352,8 @@ static int GetItemSpell() ns = 0; for (bs = 0; bs < NUM_SPELLS; bs++) { - if (spelldata[bs].sManaCost != 0 // TODO: use sSkillFlags ? - && (IsMultiGame || bs != SPL_RESURRECT)) { + if (spelldata[bs].sManaCost != 0) { // TODO: use sSkillFlags ? + // assert(!IsMultiGame || bs != SPL_RESURRECT); ss[ns] = bs; ns++; } From ea40bcff81bdc67dda319e0c6e8611eb8d780a6b Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 21 Sep 2024 11:07:19 +0200 Subject: [PATCH 572/596] validate the distance travelled by arrows using SPL_FAR_SHOT or SPL_POINT_BLANK --- Source/debug.cpp | 13 +++++++++++++ Source/missiles.cpp | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/Source/debug.cpp b/Source/debug.cpp index dfea39f4344..4dbae2b53dc 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -944,6 +944,9 @@ void ValidateData() if (pres->PLParam1 < 1 || pres->PLParam2 > 4) { app_fatal("Invalid PLParam set for %d. prefix (power:%d, pparam1:%d)", i, pres->PLPower, pres->PLParam1); } + if (pres->PLParam2 >= 3 && (pres->PLIType & PLT_BOW)) { + app_fatal("Too high PLParam2 set for %d. prefix (power:%d, pparam2:%d)", i, pres->PLPower, pres->PLParam2); // required by MissMonHitByPlr and MissPlrHitByPlr + } } if (pres->PLPower == IPL_FASTRECOVER) { if (pres->PLParam1 < 1 || pres->PLParam2 > 3) { @@ -1013,6 +1016,9 @@ void ValidateData() if (sufs->PLParam1 < 1 || sufs->PLParam2 > 4) { app_fatal("Invalid PLParam set for %d. suffix (power:%d, pparam1:%d)", i, sufs->PLPower, sufs->PLParam1); } + if (sufs->PLParam2 >= 3 && (sufs->PLIType & PLT_BOW)) { + app_fatal("Too high PLParam2 set for %d. suffix (power:%d, pparam2:%d)", i, sufs->PLPower, sufs->PLParam2); // required by MissMonHitByPlr and MissPlrHitByPlr + } } if (sufs->PLPower == IPL_FASTRECOVER) { if (sufs->PLParam1 < 1 || sufs->PLParam2 > 3) { @@ -1162,6 +1168,13 @@ void ValidateData() } else if (pow == IPL_FASTATTACK) { if (GetUniqueItemParamA(ui, n) < 1 || GetUniqueItemParamB(ui, n) > 4) app_fatal("Invalid UIParam%d set for '%s' %d.", n, ui.UIName, i); + if (GetUniqueItemParamB(ui, n) >= 3) { + for (int n = 0; n < NUM_IDI; n++) { + if (AllItemsList[n].iUniqType == ui.UIUniqType && AllItemsList[n].itype == ITYPE_BOW) { + app_fatal("Too high UIParam%d set for '%s' %d.", n, ui.UIName, i); // required by MissMonHitByPlr and MissPlrHitByPlr + } + } + } } else if (pow == IPL_FASTRECOVER) { if (GetUniqueItemParamA(ui, n) < 1 || GetUniqueItemParamB(ui, n) > 3) app_fatal("Invalid UIParam%d set for '%s' %d.", n, ui.UIName, i); diff --git a/Source/missiles.cpp b/Source/missiles.cpp index d84465bb2bf..79532c19b16 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -887,9 +887,11 @@ static bool MissMonHitByPlr(int mnum, int mi) case MIS_ARROW: break; case MIS_PBARROW: + // assert(mis->_miVar7 <= 6); -- guaranteed by _miRange dam = (dam * (64 + 32 - 16 * mis->_miVar7 + mis->_miSpllvl)) >> 6; // MISDIST break; case MIS_ASARROW: + // assert(mis->_miVar7 >= 2); -- depends on _pIArrowVelBonus dam = (dam * (8 * mis->_miVar7 - 16 + mis->_miSpllvl)) >> 5; // MISDIST break; case MIS_MLARROW: @@ -1131,9 +1133,11 @@ static bool MissPlrHitByPlr(int pnum, int mi) case MIS_ARROW: break; case MIS_PBARROW: + // assert(mis->_miVar7 <= 6); -- guaranteed by _miRange dam = (dam * (64 + 32 - 16 * mis->_miVar7 + mis->_miSpllvl)) >> 6; // MISDIST break; case MIS_ASARROW: + // assert(mis->_miVar7 >= 2); -- depends on _pIArrowVelBonus dam = (dam * (8 * mis->_miVar7 - 16 + mis->_miSpllvl)) >> 5; // MISDIST break; case MIS_MLARROW: From 693c7ada907fe7da94874e5c4f75a0723a99108a Mon Sep 17 00:00:00 2001 From: pionere Date: Sat, 21 Sep 2024 11:08:12 +0200 Subject: [PATCH 573/596] fix warnings --- Source/missiles.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 79532c19b16..56173ab966f 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -1017,7 +1017,7 @@ unsigned CalcPlrDam(int pnum, BYTE mRes, unsigned mindam, unsigned maxdam) static bool MissPlrHitByMon(int pnum, int mi) { MissileStruct* mis; - int misource, hper, tmp, dam; + int misource, hper, dam; unsigned hitFlags; if (plr._pInvincible) { @@ -1076,7 +1076,7 @@ static bool MissPlrHitByMon(int pnum, int mi) static bool MissPlrHitByPlr(int pnum, int mi) { MissileStruct* mis; - int offp, dam, tmp, hper; + int offp, dam, hper; unsigned hitFlags; mis = &missile[mi]; From 2b6b2af0bb4d50b293eedccaa745f89c74b39130 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 22 Sep 2024 08:50:14 +0200 Subject: [PATCH 574/596] comment out obsolete type definitions (WPARAM/LPARAM/MSG) --- structs.h | 12 ++++++------ tools/patcher/diablo.h | 1 - 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/structs.h b/structs.h index 4c64fd1ae1c..126b5a50444 100644 --- a/structs.h +++ b/structs.h @@ -53,8 +53,8 @@ typedef uint16_t WORD; typedef unsigned int UINT; -typedef int32_t WPARAM; -typedef int32_t LPARAM; +// typedef int32_t WPARAM; +// typedef int32_t LPARAM; // // Handles @@ -66,10 +66,10 @@ typedef HANDLE HMODULE, HDC, HINSTANCE; typedef SDL_Event Dvl_Event; typedef void (*WNDPROC)(const Dvl_Event*); -typedef struct tagMSG { - UINT message; - WPARAM wParam; -} MSG, *LPMSG; +// typedef struct tagMSG { +// UINT message; +// WPARAM wParam; +// } MSG, *LPMSG; ////////////////////////////////////////////////// // control diff --git a/tools/patcher/diablo.h b/tools/patcher/diablo.h index a937abf43c7..29ed8c10e58 100644 --- a/tools/patcher/diablo.h +++ b/tools/patcher/diablo.h @@ -22,7 +22,6 @@ extern BYTE* pMicrosCel; void diablo_quit(int exitStatus); int DiabloMain(int argc, char** argv); bool PressEscKey(); -void DisableInputWndProc(UINT uMsg, WPARAM wParam); #ifdef __cplusplus } From be2c8140d014178792dadb3f55f0f113dbce21c6 Mon Sep 17 00:00:00 2001 From: pionere Date: Sun, 22 Sep 2024 10:56:54 +0200 Subject: [PATCH 575/596] make engine.h more robust - use size_t instead of DWORD in the templates - use standard sized types (uint32_t/uint16_t) instead of DWORD/WORD everywhere else - do not use std::min --- Source/engine.h | 41 ++++++++++++++++++++++------------------- tools/patcher/engine.h | 41 ++++++++++++++++++++++------------------- 2 files changed, 44 insertions(+), 38 deletions(-) diff --git a/Source/engine.h b/Source/engine.h index dea2d882341..0e780294b3e 100644 --- a/Source/engine.h +++ b/Source/engine.h @@ -21,19 +21,19 @@ DEVILUTION_BEGIN_NAMESPACE inline const BYTE* CelGetFrameStart(const BYTE* pCelBuff, int nCel) { - const DWORD* pFrameTable; + const uint32_t* pFrameTable; - pFrameTable = (const DWORD*)pCelBuff; + pFrameTable = (const uint32_t*)pCelBuff; return &pCelBuff[SwapLE32(pFrameTable[nCel])]; } inline const BYTE* CelGetFrame(const BYTE* pCelBuff, int nCel, int* nDataSize) { - const DWORD* pFrameTable; - DWORD nCellStart; + const uint32_t* pFrameTable; + uint32_t nCellStart; - pFrameTable = (const DWORD*)&pCelBuff[nCel * 4]; + pFrameTable = (const uint32_t*)&pCelBuff[nCel * 4]; nCellStart = SwapLE32(pFrameTable[0]); *nDataSize = SwapLE32(pFrameTable[1]) - nCellStart; return &pCelBuff[nCellStart]; @@ -41,11 +41,11 @@ inline const BYTE* CelGetFrame(const BYTE* pCelBuff, int nCel, int* nDataSize) inline const BYTE* CelGetFrameClipped(const BYTE* pCelBuff, int nCel, int* nDataSize) { - const WORD* pFrameTable; - WORD nDataStart; + const uint16_t* pFrameTable; + uint16_t nDataStart; const BYTE* pRLEBytes = CelGetFrame(pCelBuff, nCel, nDataSize); - pFrameTable = (const WORD*)&pRLEBytes[0]; + pFrameTable = (const uint16_t*)&pRLEBytes[0]; nDataStart = SwapLE16(pFrameTable[0]); *nDataSize -= nDataStart; @@ -54,11 +54,11 @@ inline const BYTE* CelGetFrameClipped(const BYTE* pCelBuff, int nCel, int* nData inline const BYTE* CelGetFrameClippedAt(const BYTE* pCelBuff, int nCel, int block, int* nDataSize) { - const WORD* pFrameTable; - WORD nDataStart; + const uint16_t* pFrameTable; + uint16_t nDataStart; const BYTE* pRLEBytes = CelGetFrame(pCelBuff, nCel, nDataSize); - pFrameTable = (const WORD*)&pRLEBytes[0]; + pFrameTable = (const uint16_t*)&pRLEBytes[0]; nDataStart = SwapLE16(pFrameTable[block]); // assert(nDataStart != 0); *nDataSize -= nDataStart; @@ -99,14 +99,14 @@ BYTE* LoadFileInMem(const char* pszName, size_t* pdwFileLen = NULL); void LoadFileWithMem(const char* pszName, BYTE* p); char** LoadTxtFile(const char* name, int lines); -/* Load .CEL file and overwrite the first (unused) DWORD with nWidth */ -inline CelImageBuf* CelLoadImage(const char* name, DWORD nWidth) +/* Load .CEL file and overwrite the first (unused) uint32_t with nWidth */ +inline CelImageBuf* CelLoadImage(const char* name, uint32_t nWidth) { CelImageBuf* res; res = (CelImageBuf*)LoadFileInMem(name); #if DEBUG_MODE - res->ciFrameCnt = SwapLE32(*((DWORD*)res)); + res->ciFrameCnt = SwapLE32(*((uint32_t*)res)); #endif res->ciWidth = nWidth; return res; @@ -157,7 +157,7 @@ inline int RandRangeLow(int minVal, int maxVal) * Copy string from src to dest. * The NULL terminated content of src is copied to dest. */ -template +template inline void copy_str(char (&dest)[N1], char (&src)[N2]) { static_assert(N1 >= N2, "String does not fit the destination."); @@ -170,11 +170,13 @@ inline void copy_str(char (&dest)[N1], char (&src)[N2]) * Copy constant string from src to dest. * The whole (padded) length of the src array is copied. */ -template +template inline void copy_cstr(char (&dest)[N1], const char (&src)[N2]) { static_assert(N1 >= N2, "String does not fit the destination."); - memcpy(dest, src, std::min(N1, (DWORD)(((N2 + sizeof(int) - 1) / sizeof(int)) * sizeof(int)))); + constexpr size_t src_len = ((N2 + sizeof(int) - 1) / sizeof(int)) * sizeof(int); + constexpr size_t len = N1 >= src_len ? src_len : N1; + memcpy(dest, src, len); } /* @@ -201,13 +203,14 @@ inline void copy_pod(T& dest, const T& src) template inline void cat_str(char (&dest)[N], int& pos, const char* fmt, ...) { - int n; + int n, res; va_list va; va_start(va, fmt); n = N - pos; - pos += std::min(vsnprintf(&dest[pos], n, fmt, va), n - 1); + res = vsnprintf(&dest[pos], n, fmt, va); + pos += (res <= n - 1) ? res : n - 1; va_end(va); } diff --git a/tools/patcher/engine.h b/tools/patcher/engine.h index 5ef0dd0143e..e87f6c9a40f 100644 --- a/tools/patcher/engine.h +++ b/tools/patcher/engine.h @@ -22,19 +22,19 @@ DEVILUTION_BEGIN_NAMESPACE inline const BYTE* CelGetFrameStart(const BYTE* pCelBuff, int nCel) { - const DWORD* pFrameTable; + const uint32_t* pFrameTable; - pFrameTable = (const DWORD*)pCelBuff; + pFrameTable = (const uint32_t*)pCelBuff; return &pCelBuff[SwapLE32(pFrameTable[nCel])]; } inline const BYTE* CelGetFrame(const BYTE* pCelBuff, int nCel, int* nDataSize) { - const DWORD* pFrameTable; - DWORD nCellStart; + const uint32_t* pFrameTable; + uint32_t nCellStart; - pFrameTable = (const DWORD*)&pCelBuff[nCel * 4]; + pFrameTable = (const uint32_t*)&pCelBuff[nCel * 4]; nCellStart = SwapLE32(pFrameTable[0]); *nDataSize = SwapLE32(pFrameTable[1]) - nCellStart; return &pCelBuff[nCellStart]; @@ -42,11 +42,11 @@ inline const BYTE* CelGetFrame(const BYTE* pCelBuff, int nCel, int* nDataSize) inline const BYTE* CelGetFrameClipped(const BYTE* pCelBuff, int nCel, int* nDataSize) { - const WORD* pFrameTable; - WORD nDataStart; + const uint16_t* pFrameTable; + uint16_t nDataStart; const BYTE* pRLEBytes = CelGetFrame(pCelBuff, nCel, nDataSize); - pFrameTable = (const WORD*)&pRLEBytes[0]; + pFrameTable = (const uint16_t*)&pRLEBytes[0]; nDataStart = SwapLE16(pFrameTable[0]); *nDataSize -= nDataStart; @@ -55,11 +55,11 @@ inline const BYTE* CelGetFrameClipped(const BYTE* pCelBuff, int nCel, int* nData inline const BYTE* CelGetFrameClippedAt(const BYTE* pCelBuff, int nCel, int block, int* nDataSize) { - const WORD* pFrameTable; - WORD nDataStart; + const uint16_t* pFrameTable; + uint16_t nDataStart; const BYTE* pRLEBytes = CelGetFrame(pCelBuff, nCel, nDataSize); - pFrameTable = (const WORD*)&pRLEBytes[0]; + pFrameTable = (const uint16_t*)&pRLEBytes[0]; nDataStart = SwapLE16(pFrameTable[block]); // assert(nDataStart != 0); *nDataSize -= nDataStart; @@ -88,14 +88,14 @@ BYTE* LoadFileInMem(const char* pszName, size_t* pdwFileLen = NULL); void LoadFileWithMem(const char* pszName, BYTE* p); char** LoadTxtFile(const char* name, int lines); -/* Load .CEL file and overwrite the first (unused) DWORD with nWidth */ -inline CelImageBuf* CelLoadImage(const char* name, DWORD nWidth) +/* Load .CEL file and overwrite the first (unused) uint32_t with nWidth */ +inline CelImageBuf* CelLoadImage(const char* name, uint32_t nWidth) { CelImageBuf* res; res = (CelImageBuf*)LoadFileInMem(name); #if DEBUG_MODE - res->ciFrameCnt = SwapLE32(*((DWORD*)res)); + res->ciFrameCnt = SwapLE32(*((uint32_t*)res)); #endif res->ciWidth = nWidth; return res; @@ -134,7 +134,7 @@ BYTE* CelMerge(BYTE* celA, size_t nDataSizeA, BYTE* celB, size_t nDataSizeB); * Copy string from src to dest. * The NULL terminated content of src is copied to dest. */ -template +template inline void copy_str(char (&dest)[N1], char (&src)[N2]) { static_assert(N1 >= N2, "String does not fit the destination."); @@ -147,11 +147,13 @@ inline void copy_str(char (&dest)[N1], char (&src)[N2]) * Copy constant string from src to dest. * The whole (padded) length of the src array is copied. */ -template +template inline void copy_cstr(char (&dest)[N1], const char (&src)[N2]) { static_assert(N1 >= N2, "String does not fit the destination."); - memcpy(dest, src, std::min(N1, (DWORD)(((N2 + sizeof(int) - 1) / sizeof(int)) * sizeof(int)))); + constexpr size_t src_len = ((N2 + sizeof(int) - 1) / sizeof(int)) * sizeof(int); + constexpr size_t len = N1 >= src_len ? src_len : N1; + memcpy(dest, src, len); } /* @@ -178,13 +180,14 @@ inline void copy_pod(T& dest, const T& src) template inline void cat_str(char (&dest)[N], int& pos, const char* fmt, ...) { - int n; + int n, res; va_list va; va_start(va, fmt); n = N - pos; - pos += std::min(vsnprintf(&dest[pos], n, fmt, va), n - 1); + res = vsnprintf(&dest[pos], n, fmt, va); + pos += (res <= n - 1) ? res : n - 1; va_end(va); } From 16252c4e0ab47a9d95243cb6bf24e5892245dda9 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 23 Sep 2024 08:15:33 +0200 Subject: [PATCH 576/596] rebalance block chance - use uint16_t to store the block chance - adjust the block chance calculation - remove cap from block chance - use CheckHit to calculate whether block succeeeds --- Source/items.cpp | 2 +- Source/loadsave.cpp | 6 ++---- Source/player.cpp | 2 +- structs.h | 3 +-- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Source/items.cpp b/Source/items.cpp index fe6d283d401..320e25f3823 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -704,7 +704,7 @@ void CalcPlrItemVals(int pnum, bool Loadgfx) plr._pICritChance = cc; // calculate block chance - plr._pIBlockChance = (plr._pSkillFlags & SFLAG_BLOCK) ? std::min(200, 10 + (std::min(plr._pStrength, plr._pDexterity) >> 1)) : 0; + plr._pIBlockChance = (plr._pSkillFlags & SFLAG_BLOCK) ? std::min(plr._pStrength, plr._pDexterity) : 0; // calculate walk speed plr._pIWalkSpeed = WalkSpeed(plr._pIFlags); diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index 7151545596c..d69f0db41a3 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -301,8 +301,7 @@ static BYTE* LoadPlayer(BYTE* DVL_RESTRICT src, int pnum) tbuff += 4; // _pIHitChance tbuff += 1; // _pIBaseHitBonus tbuff += 1; // _pICritChance - tbuff += 1; // _pIBlockChance - tbuff += 1; // _pAlign_B0 + tbuff += 2; // _pIBlockChance tbuff += 4; // _pIFlags tbuff += 1; // _pIWalkSpeed @@ -1146,8 +1145,7 @@ static BYTE* SavePlayer(BYTE* DVL_RESTRICT dest, int pnum) tbuff += 4; // _pIHitChance tbuff += 1; // _pIBaseHitBonus tbuff += 1; // _pICritChance - tbuff += 1; // _pIBlockChance - tbuff += 1; // _pAlign_B0 + tbuff += 2; // _pIBlockChance tbuff += 4; // _pIFlags tbuff += 1; // _pIWalkSpeed diff --git a/Source/player.cpp b/Source/player.cpp index b1a2e96c4cc..42a8cbc7d81 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -2353,7 +2353,7 @@ bool PlrCheckBlock(int pnum, int bmod, int sx, int sy) && (plr._pmode == PM_STAND || plr._pmode == PM_BLOCK)) { // assert(plr._pSkillFlags & SFLAG_BLOCK); blkper = blkper - bmod * 2; - if (blkper > random_(98, 100)) { + if (CheckHit(blkper)) { PlrStartBlock(pnum, sx, sy); result = true; } diff --git a/structs.h b/structs.h index 126b5a50444..fe3747a3f7d 100644 --- a/structs.h +++ b/structs.h @@ -450,8 +450,7 @@ typedef struct PlayerStruct { int _pIHitChance; BYTE _pIBaseHitBonus; // indicator whether the base BonusToHit of the items is positive/negative/neutral BYTE _pICritChance; // 200 == 100% - BYTE _pIBlockChance; - BYTE _pAlign_B0; + uint16_t _pIBlockChance; unsigned _pIFlags; // item_special_effect BYTE _pIWalkSpeed; BYTE _pIRecoverySpeed; From af9df69cc887a571686d84e89b4b3872e8aa292f Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 23 Sep 2024 08:21:43 +0200 Subject: [PATCH 577/596] rebalance charge damage of the players - adjust charge damage calculation. Make it more dependent on the (base)AC of the shield. - apply the 'low' damage of short charges - do not force stun in pvp --- Source/items.cpp | 2 +- Source/player.cpp | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Source/items.cpp b/Source/items.cpp index 320e25f3823..d70709beba9 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -610,7 +610,7 @@ void CalcPlrItemVals(int pnum, bool Loadgfx) static_assert((int)ANIM_ID_MACE + 1 == (int)ANIM_ID_MACE_SHIELD, "CalcPlrItemVals uses inc to set gfx with shield III."); gfx++; - maxdam += wRight->_iAC << (6 + 1 - 1); // 2*AC - halved by resists, doubled by MissToPlr + maxdam += wRight->_iAC << (6 + 2 + 1 - 1); // 4*AC - halved by resists, doubled by MissToPlr } plr._pIChMinDam = maxdam >> 1; plr._pIChMaxDam = maxdam; diff --git a/Source/player.cpp b/Source/player.cpp index 42a8cbc7d81..829807a66ad 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -2949,16 +2949,20 @@ void MissToPlr(int mi, bool hit) //else // PlaySfxLoc(IS_BHIT, x, y); dist = (int)mis->_miRange - 24; // MISRANGE - if (dist < 0) - return; + // if (dist < 0) + // return; if (dist > 32) dist = 32; minbl = plr._pIChMinDam; maxbl = plr._pIChMaxDam; - if (maxbl != 0) { + //if (maxbl != 0) { minbl = ((64 + dist) * minbl) >> 5; maxbl = ((64 + dist) * maxbl) >> 5; - } + //} + if (maxbl <= 0) + return; + //if (minbl < 0) + // minbl = 0; oldx = mis->_mix; oldy = mis->_miy; @@ -3016,7 +3020,7 @@ void MissToPlr(int mi, bool hit) //if (random_(151, 200) < plr._pICritChance) // dam <<= 1; if (!PlrDecHp(mpnum, dam, DMGTYPE_PLAYER)) { - hitFlags = (plr._pIFlags & ISPL_HITFLAGS_MASK) | ISPL_FAKE_FORCE_STUN; + hitFlags = (plr._pIFlags & ISPL_HITFLAGS_MASK) | ISPL_STUN; PlrHitByAny(mpnum, pnum, dam, hitFlags, mis->_misx, mis->_misy); } return; From 94a5fbe07c9c9984b29dc1c09340119bfdc72ba5 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 23 Sep 2024 09:08:51 +0200 Subject: [PATCH 578/596] provide GitHub token as an input instead from an environment variable --- .github/workflows/nightly.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 532a5b8c856..5291d589b05 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1604,6 +1604,7 @@ jobs: body_path: ${{ github.workspace }}/RELEASE_NOTE.md draft: false prerelease: true + token: ${{ secrets.GITHUB_TOKEN }} files: | ${{github.workspace}}/diablo-nightly-android.apk ${{github.workspace}}/diablo-nightly-lepus.opk @@ -1670,5 +1671,5 @@ jobs: ${{github.workspace}}/hellfire-nightly-switchp.nro ${{github.workspace}}/hellfire-nightly-amigap fail_on_unmatched_files: true - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + #env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 8765791b6f5aa740fb25fd5ea3271aade96738d9 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 24 Sep 2024 07:35:06 +0200 Subject: [PATCH 579/596] fix description of PlrGFXAnimLens after 'sync order of PLR_ANIM and player_graphic' --- Source/player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/player.cpp b/Source/player.cpp index 829807a66ad..9f002819602 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -83,7 +83,7 @@ static const PlrAnimType PlrAnimTypes[NUM_PGTS] = { }; /** * Specifies the number of frames of each animation for each player class. - STAND, ATTACK, WALK, BLOCK, DEATH, SPELL, GOTHIT + STAND, WALK, ATTACK, SPELL, BLOCK, GOTHIT, DEATH */ const BYTE PlrGFXAnimLens[NUM_CLASSES][NUM_PLR_ANIMS] = { // clang-format off From 29696b7c08871aec8e4ff7b1c7a9845638b9f319 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 24 Sep 2024 10:03:50 +0200 Subject: [PATCH 580/596] fix frame skipping of player animations II. --- Source/player.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/player.cpp b/Source/player.cpp index 9f002819602..680c6dc7273 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -2557,7 +2557,7 @@ static bool CheckNewPath(int pnum) //PlrStartStand(pnum); StartStand(pnum); plr._pDestAction = ACTION_NONE; - return false; + // return true; -- does not matter (at the moment) } return true; } @@ -2616,6 +2616,7 @@ static bool CheckNewPath(int pnum) || plr._pDestAction == ACTION_OPERATE) { StartAttack(pnum); plr._pDestAction = ACTION_NONE; + return true; } } else if (plr._pmode == PM_RATTACK && plr._pAnimFrame > plr._pAFNum) { if (plr._pDestAction == ACTION_RATTACK @@ -2623,6 +2624,7 @@ static bool CheckNewPath(int pnum) || plr._pDestAction == ACTION_RATTACKPLR) { StartRangeAttack(pnum); plr._pDestAction = ACTION_NONE; + return true; } } else if (plr._pmode == PM_SPELL && plr._pAnimFrame > plr._pSFNum) { if (plr._pDestAction == ACTION_SPELL @@ -2630,6 +2632,7 @@ static bool CheckNewPath(int pnum) || plr._pDestAction == ACTION_SPELLPLR) { StartSpell(pnum); plr._pDestAction = ACTION_NONE; + return true; } } return false; From 3e5770960135bcb296f77a634d8db309cb6c0e9d Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 24 Sep 2024 10:54:44 +0200 Subject: [PATCH 581/596] fix hit-recovery of the players - initialize _pVar8 for PlrDoGotHit (bugfix for 'support cast rate and walk speed modifiers') --- Source/player.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/player.cpp b/Source/player.cpp index 680c6dc7273..7822b74dff5 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -1631,6 +1631,7 @@ static void PlrStartGetHit(int pnum, int dir) NewPlrAnim(pnum, PGX_GOTHIT, dir); plr._pmode = PM_GOTHIT; + plr._pVar8 = 0; // GOTHIT_TICK RemovePlrFromMap(pnum); dPlayer[plr._px][plr._py] = pnum + 1; FixPlayerLocation(pnum); From aaee8b80d4c924a70826b3aceed584e8d3136e48 Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 24 Sep 2024 11:11:58 +0200 Subject: [PATCH 582/596] make gbGameLogicPnum static --- Source/player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/player.cpp b/Source/player.cpp index 7822b74dff5..bd246a0098a 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -13,7 +13,7 @@ PlayerStruct players[MAX_PLRS]; /* Whether the current player is changing the level. */ bool gbLvlLoad; /** The current player while processing the players. */ -BYTE gbGameLogicPnum; +static BYTE gbGameLogicPnum; /** Cache the maximum sizes of the player gfx files. */ static unsigned _guPlrFrameSize[NUM_PGXS + 1]; /** Whether the _guPlrFrameSize array is initalized. */ From cb022fe0130fb7edca40f871754c2d396801940c Mon Sep 17 00:00:00 2001 From: pionere Date: Tue, 24 Sep 2024 18:46:33 +0200 Subject: [PATCH 583/596] 'bugfix' for vanilla (Cbolt vs. monster damage) - use the configured monster damage to calculate the damage of charged bolts in case of Magistrates --- Source/missiles.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 56173ab966f..f6b4ec0949f 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -3198,6 +3198,7 @@ int AddCboltC(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, i int AddCbolt(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, int misource, int spllvl) { MissileStruct* mis; + int mindam, maxdam; // ((micaster & MST_PLAYER) || micaster == MST_MONSTER); if (sx == dx && sy == dy) { dx += XDirAdd[midir]; @@ -3213,11 +3214,14 @@ int AddCbolt(int mi, int sx, int sy, int dx, int dy, int midir, int micaster, in //mis->_miVar3 = 0; mis->_miVar4 = random_(0, 16); if (micaster & MST_PLAYER) { - mis->_miMinDam = 1; - mis->_miMaxDam = (plx(misource)._pMagic << (-2 + 6)) + (spllvl << (2 + 6)); + mindam = 1; + maxdam = (plx(misource)._pMagic << (-2 + 6)) + (spllvl << (2 + 6)); } else { - mis->_miMinDam = mis->_miMaxDam = 15 << (6 + gnDifficulty); + mindam = monsters[misource]._mMinDamage << 6; + maxdam = monsters[misource]._mMaxDamage << 6; } + mis->_miMinDam = mindam; + mis->_miMaxDam = maxdam; mis->_miRange = 255; mis->_miAnimFrame = RandRange(1, misfiledata[MFILE_MINILTNG].mfAnimLen[0]); return MIRES_DONE; From d4d1a3bffc8a1a8bb8677b673dffb445771bcd63 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 25 Sep 2024 08:21:36 +0200 Subject: [PATCH 584/596] fix TFit_Shrine after 'assume theme-rooms are rectangles' --- Source/themes.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/themes.cpp b/Source/themes.cpp index 4b1c722f040..67dcbe3831d 100644 --- a/Source/themes.cpp +++ b/Source/themes.cpp @@ -85,6 +85,7 @@ static int TFit_Shrine(int themeId) // if (numMatches == lengthof(drlg.thLocs)) // goto done; } + } } xx = themes[themeId]._tsx1; for (yy = themes[themeId]._tsy1 + 1; yy < themes[themeId]._tsy2 - 1; yy++) { @@ -115,7 +116,6 @@ static int TFit_Shrine(int themeId) } } } - } // done: if (numMatches == 0) return -1; From d221c2a5a7aadfd531a9ef995d23188bff1300b9 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 25 Sep 2024 09:25:53 +0200 Subject: [PATCH 585/596] cosmetic --- Source/drlg_l3.cpp | 1 - Source/items.cpp | 2 +- Source/monster.cpp | 2 +- Source/platform/ctr/asio/sys/socket.c | 2 +- Source/platform/switch/asio/pause.c | 2 +- Source/plrmsg.cpp | 2 +- structs.h | 4 ++-- tools/patcher/drlp_l2.cpp | 2 +- tools/patcher/utils/md5.h | 2 +- 9 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Source/drlg_l3.cpp b/Source/drlg_l3.cpp index 6a6b380d348..d7b4f9e5138 100644 --- a/Source/drlg_l3.cpp +++ b/Source/drlg_l3.cpp @@ -2395,7 +2395,6 @@ static void DRLG_L3() if (warpPos.x < 0) { continue; } - pWarps[DWARP_ENTRY]._wx = warpPos.x; pWarps[DWARP_ENTRY]._wy = warpPos.y; pWarps[DWARP_ENTRY]._wx = 2 * pWarps[DWARP_ENTRY]._wx + DBORDERX + 1; diff --git a/Source/items.cpp b/Source/items.cpp index d70709beba9..ade59481004 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -600,7 +600,7 @@ void CalcPlrItemVals(int pnum, bool Loadgfx) bf = true; } #endif*/ - maxdam = plr._pMaxHP >> (2 - 1 + 1); // ~1/4 hp - halved by resists, doubled by MissToPlr + maxdam = plr._pMaxHP >> (2 + 1 - 1); // ~1/4 hp - halved by resists, doubled by MissToPlr if (wRight->_itype == ITYPE_SHIELD && wRight->_iStatFlag && (gfx == ANIM_ID_UNARMED || gfx == ANIM_ID_SWORD || gfx == ANIM_ID_MACE)) { tac += ((plr._pDexterity - (1 << 7)) * wRight->_iAC) >> 7; diff --git a/Source/monster.cpp b/Source/monster.cpp index 2bc3fc1145a..2fd694db676 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -483,7 +483,7 @@ void InitLvlMonsters() AddMonsterType(MT_GOLEM, FALSE); mapMonTypes[0].cmFlags |= MFLAG_NOCORPSE | MFLAG_NODROP; for (i = 0; i < MAX_MINIONS; i++) { - InitMonster(i, 0, 0, 0, 0); + InitMonster(i, DIR_S, 0, 0, 0); monsters[i]._mmode = MM_RESERVED; } } diff --git a/Source/platform/ctr/asio/sys/socket.c b/Source/platform/ctr/asio/sys/socket.c index c1dfaa492ef..9c348469943 100644 --- a/Source/platform/ctr/asio/sys/socket.c +++ b/Source/platform/ctr/asio/sys/socket.c @@ -107,4 +107,4 @@ int socketpair(int domain, int type, int protocol, int socket_vector[2]) { return ENOTSUP; } -#endif \ No newline at end of file +#endif // TCPIP \ No newline at end of file diff --git a/Source/platform/switch/asio/pause.c b/Source/platform/switch/asio/pause.c index d663ee7c09c..b216bc2d7ee 100644 --- a/Source/platform/switch/asio/pause.c +++ b/Source/platform/switch/asio/pause.c @@ -6,4 +6,4 @@ int pause(void) errno = ENOSYS; return -1; } -#endif \ No newline at end of file +#endif // TCPIP \ No newline at end of file diff --git a/Source/plrmsg.cpp b/Source/plrmsg.cpp index c267875793b..353cd978e5c 100644 --- a/Source/plrmsg.cpp +++ b/Source/plrmsg.cpp @@ -242,7 +242,7 @@ void DrawPlrMsg(bool onTop) int msgs[PLRMSG_COUNT], nummsgs, numlines; int i, idx, x, y, h, linelimit, top; const int width = PLRMSG_WIDTH; - Uint32 timeout; + uint32_t timeout; // collect the messages nummsgs = 0; diff --git a/structs.h b/structs.h index fe3747a3f7d..558de151d2b 100644 --- a/structs.h +++ b/structs.h @@ -428,8 +428,8 @@ typedef struct PlayerStruct { int _pMana; // the current mana of the player int _pMaxMana; // the maximum mana of the player BYTE _pSkillLvl[64]; // the skill levels of the player - uint64_t _pISpells; // Bitmask of skills available via equipped items (staff) - BYTE _pSkillFlags; // Bitmask of allowed skill-types (SFLAG_*) + uint64_t _pISpells; // Bitmask of skills available via equipped items (staff) + BYTE _pSkillFlags; // Bitmask of allowed skill-types (SFLAG_*) BOOLEAN _pInfraFlag; BYTE _pgfxnum; // Bitmask indicating what variant of the sprite the player is using. Lower byte define weapon (anim_weapon_id) and higher values define armour (starting with anim_armor_id) BOOLEAN _pHasUnidItem; // whether the player has an unidentified (magic) item equipped diff --git a/tools/patcher/drlp_l2.cpp b/tools/patcher/drlp_l2.cpp index 83c25fef5b0..5d66eaeb5f2 100644 --- a/tools/patcher/drlp_l2.cpp +++ b/tools/patcher/drlp_l2.cpp @@ -11,7 +11,7 @@ DEVILUTION_BEGIN_NAMESPACE BYTE* DRLP_L2_PatchDoors(BYTE* celBuf, size_t* celLen) { - const int frames[] = { 0, 1 }; + const int frames[] = { 0, 1 }; constexpr int FRAME_WIDTH = 64; constexpr int FRAME_HEIGHT = 128; diff --git a/tools/patcher/utils/md5.h b/tools/patcher/utils/md5.h index f7b1d052bb5..54bfc35c338 100644 --- a/tools/patcher/utils/md5.h +++ b/tools/patcher/utils/md5.h @@ -319,7 +319,7 @@ class MD5 printf("%s can't be opened\n", filename); else { - while ((len = fread(buffer, 1, 1024, file))) + while (len = fread(buffer, 1, 1024, file)) Update(buffer, len); Final(); From 8b99650cf7c95d8ceca5ff90455bfeeb17e56d2e Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 25 Sep 2024 09:27:46 +0200 Subject: [PATCH 586/596] eliminate unused parameters of DRLP_L1_PatchSpec --- tools/patcher/DiabloUI/patcher.cpp | 19 +------------------ tools/patcher/drlp_l1.cpp | 2 +- tools/patcher/drlp_l1.h | 2 +- 3 files changed, 3 insertions(+), 20 deletions(-) diff --git a/tools/patcher/DiabloUI/patcher.cpp b/tools/patcher/DiabloUI/patcher.cpp index b8bb6966509..68ee68722d9 100644 --- a/tools/patcher/DiabloUI/patcher.cpp +++ b/tools/patcher/DiabloUI/patcher.cpp @@ -3954,24 +3954,7 @@ static BYTE* patchFile(int index, size_t *dwLen) } break; case FILE_CATHEDRAL_SCEL: { // patch pSpecialsCel - L1S.CEL - size_t minLen; - BYTE* minBuf = LoadFileInMem(filesToPatch[FILE_CATHEDRAL_MIN], &minLen); - if (minBuf == NULL) { - mem_free_dbg(buf); - app_warn("Unable to open file %s in the mpq.", filesToPatch[FILE_CATHEDRAL_MIN]); - return NULL; - } - size_t celLen; - BYTE* celBuf = LoadFileInMem(filesToPatch[FILE_CATHEDRAL_CEL], &celLen); - if (celBuf == NULL) { - mem_free_dbg(minBuf); - mem_free_dbg(buf); - app_warn("Unable to open file %s in the mpq.", filesToPatch[FILE_CATHEDRAL_CEL]); - return NULL; - } - buf = DRLP_L1_PatchSpec(minBuf, minLen, celBuf, celLen, buf, dwLen); - mem_free_dbg(celBuf); - mem_free_dbg(minBuf); + buf = DRLP_L1_PatchSpec(buf, dwLen); } break; case FILE_CATHEDRAL_CEL: { // patch dMicroCels - L1.CEL diff --git a/tools/patcher/drlp_l1.cpp b/tools/patcher/drlp_l1.cpp index 346f48aa548..fbcd853bd09 100644 --- a/tools/patcher/drlp_l1.cpp +++ b/tools/patcher/drlp_l1.cpp @@ -142,7 +142,7 @@ BYTE* DRLP_L1_PatchDoors(BYTE* celBuf, size_t* celLen) return resCelBuf; } -BYTE* DRLP_L1_PatchSpec(const BYTE* minBuf, size_t minLen, const BYTE* celBuf, size_t celLen, BYTE* sCelBuf, size_t* sCelLen) +BYTE* DRLP_L1_PatchSpec(BYTE* sCelBuf, size_t* sCelLen) { constexpr BYTE TRANS_COLOR = 128; constexpr BYTE SUB_HEADER_SIZE = 10; diff --git a/tools/patcher/drlp_l1.h b/tools/patcher/drlp_l1.h index 7153d3ed63f..aee68466bad 100644 --- a/tools/patcher/drlp_l1.h +++ b/tools/patcher/drlp_l1.h @@ -15,7 +15,7 @@ extern "C" { #define BLOCK_SIZE_L1 10 BYTE* DRLP_L1_PatchDoors(BYTE* celBuf, size_t* celLen); -BYTE* DRLP_L1_PatchSpec(const BYTE* minBuf, size_t minLen, const BYTE* celBuf, size_t celLen, BYTE* sCelBuf, size_t* sCelLen); +BYTE* DRLP_L1_PatchSpec(BYTE* sCelBuf, size_t* sCelLen); BYTE* DRLP_L1_PatchCel(const BYTE* minBuf, size_t minLen, BYTE* celBuf, size_t* celLen); void DRLP_L1_PatchMin(BYTE* minBuf); void DRLP_L1_PatchTil(BYTE* tilBuf); From 6030fe56fa0ff38e93a138a35991750b2e6790b1 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 25 Sep 2024 09:29:54 +0200 Subject: [PATCH 587/596] check the walk-animation lengths of the players in ValidateData --- Source/debug.cpp | 3 +++ Source/player.cpp | 5 +---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/debug.cpp b/Source/debug.cpp index 4dbae2b53dc..8f28bb4d963 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -1471,6 +1471,9 @@ void ValidateData() assert(monfiledata[MOFILE_SNAKE].moAnimFrameLen[MA_ATTACK] == 1); // required by MI_Rhino assert(monfiledata[MOFILE_MAGMA].moAnimFrameLen[MA_SPECIAL] == 1); // required by MonDoRSpAttack #ifdef DEBUG_DATA + // players + for (i = 0; i < NUM_CLASSES; i++) + assert(PlrGFXAnimLens[i][PA_WALK] == PlrGFXAnimLens[PC_WARRIOR][PA_WALK]); // required by StartWalk // towners for (i = 0; i < STORE_TOWNERS; i++) { //const int(*gl)[2] = &GossipList[i]; diff --git a/Source/player.cpp b/Source/player.cpp index bd246a0098a..b3026db622a 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -1304,12 +1304,9 @@ static bool StartWalk(int pnum) return false; } -#if DEBUG_MODE - for (i = 0; i < NUM_CLASSES; i++) - assert(PlrGFXAnimLens[i][PA_WALK] == PlrGFXAnimLens[PC_WARRIOR][PA_WALK]); -#endif static_assert(TILE_WIDTH / TILE_HEIGHT == 2, "StartWalk relies on fix width/height ratio of the floor-tile."); static_assert(PLR_WALK_SHIFT == MON_WALK_SHIFT, "To reuse MWVel in StartWalk, PLR_WALK_SHIFT must be equal to MON_WALK_SHIFT."); + // assert(PlrGFXAnimLens[plr._pClass][PA_WALK] == PlrGFXAnimLens[PC_WARRIOR][PA_WALK]); assert(PlrGFXAnimLens[PC_WARRIOR][PA_WALK] <= lengthof(MWVel)); assert(PlrGFXAnimLens[PC_WARRIOR][PA_WALK] == 8); // StartWalk relies on fix walk-animation length to calculate the x/y velocity mwi = MWVel[PlrGFXAnimLens[PC_WARRIOR][PA_WALK] - (plr._pIWalkSpeed == 0 ? 0 : (1 + plr._pIWalkSpeed)) - 1]; From f94034b3003360f195704ad263629b1f75017c29 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 25 Sep 2024 09:31:10 +0200 Subject: [PATCH 588/596] sync L1RoomGen with L4RoomGen --- Source/drlg_l1.cpp | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/Source/drlg_l1.cpp b/Source/drlg_l1.cpp index bb243b9b75b..b33f5bf3a18 100644 --- a/Source/drlg_l1.cpp +++ b/Source/drlg_l1.cpp @@ -1111,14 +1111,17 @@ static void L1RoomGen(int x, int y, int w, int h, bool dir) ry = h / 2u + y - height / 2u; rx = x - width; if (L1CheckVHall(x, ry - 1, height + 2) - && L1CheckRoom(rx - 1, ry - 1, width + 1, height + 2)) // BUGFIX: swap args 3 and 4 ("height+2" and "width+1") (fixed) + && L1CheckRoom(rx - 1, ry - 1, width + 1, height + 2)) { // BUGFIX: swap args 3 and 4 ("height+2" and "width+1") (fixed) + // - add room to the left + L1DrawRoom(rx, ry, width, height); break; + } } - // - add room to the left if (i != 0) { - L1DrawRoom(rx, ry, width, height); + // room added to the left -> force similar room on the right side i = 1; } else { + // room was not added to the left -> try to more options on the right rx = -1; i = 20; } @@ -1126,17 +1129,18 @@ static void L1RoomGen(int x, int y, int w, int h, bool dir) rxy2 = x + w; while (true) { if (L1CheckVHall(rxy2 - 1, ry - 1, height + 2) - && L1CheckRoom(rxy2, ry - 1, width + 1, height + 2)) + && L1CheckRoom(rxy2, ry - 1, width + 1, height + 2)) { + // - add room to the right + L1DrawRoom(rxy2, ry, width, height); break; + } if (--i == 0) break; width = RandRange(2, 6) & ~1; height = RandRange(2, 6) & ~1; ry = h / 2u + y - height / 2u; } - // - add room to the right if (i != 0) - L1DrawRoom(rxy2, ry, width, height); // proceed with the placed a room on the left if (rx >= 0) L1RoomGen(rx, ry, width, height, true); @@ -1151,14 +1155,17 @@ static void L1RoomGen(int x, int y, int w, int h, bool dir) rx = w / 2u + x - width / 2u; ry = y - height; if (L1CheckHHall(y, rx - 1, width + 2) - && L1CheckRoom(rx - 1, ry - 1, width + 2, height + 1)) + && L1CheckRoom(rx - 1, ry - 1, width + 2, height + 1)) { + // - add room to the top + L1DrawRoom(rx, ry, width, height); break; + } } - // - add room to the top if (i != 0) { - L1DrawRoom(rx, ry, width, height); + // room added to the top -> force similar room on the bottom side i = 1; } else { + // room was not added to the top -> try to more options on the bottom ry = -1; i = 20; } @@ -1166,17 +1173,17 @@ static void L1RoomGen(int x, int y, int w, int h, bool dir) rxy2 = y + h; while (true) { if (L1CheckHHall(rxy2 - 1, rx - 1, width + 2) - && L1CheckRoom(rx - 1, rxy2, width + 2, height + 1)) + && L1CheckRoom(rx - 1, rxy2, width + 2, height + 1)) { + // - add room to the bottom + L1DrawRoom(rx, rxy2, width, height); break; + } if (--i == 0) break; width = RandRange(2, 6) & ~1; height = RandRange(2, 6) & ~1; rx = w / 2u + x - width / 2u; } - // - add room to the bottom - if (i != 0) - L1DrawRoom(rx, rxy2, width, height); // proceed with the placed a room on the top if (ry >= 0) L1RoomGen(rx, ry, width, height, false); From ab4366c13071ec170e1b0a765de345a59ffac4b9 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 25 Sep 2024 09:36:03 +0200 Subject: [PATCH 589/596] fix warnings --- Source/inv.cpp | 2 +- Source/player.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/inv.cpp b/Source/inv.cpp index 16e0c402464..7af0d373fe3 100644 --- a/Source/inv.cpp +++ b/Source/inv.cpp @@ -1459,7 +1459,7 @@ int FindGetItem(const PkItemStruct* pkItem) bool CanPut(int x, int y) { - int oi, oi2; + int oi; // , oi2; if (x < DBORDERX || x >= DBORDERX + DSIZEX || y < DBORDERY || y >= DBORDERY + DSIZEY) return false; diff --git a/Source/player.cpp b/Source/player.cpp index b3026db622a..063b2ba5b42 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -2040,7 +2040,7 @@ static bool PlrHitMonst(int pnum, int sn, int sl, int mnum) static bool PlrHitPlr(int offp, int sn, int sl, int pnum) { - int hper, blkper, dam, damsl, dambl, dampc; + int hper, dam, damsl, dambl, dampc; unsigned tmp, hitFlags; if ((unsigned)offp >= MAX_PLRS) { @@ -2918,7 +2918,7 @@ void MissToPlr(int mi, bool hit) { MissileStruct* mis; MonsterStruct* mon; - int pnum, oldx, oldy, mpnum, dist, minbl, maxbl, dam, hper, blkper; + int pnum, oldx, oldy, mpnum, dist, minbl, maxbl, dam, hper; unsigned hitFlags; bool ret; From d031f10ecd9a55b154c606754875ed700f0b50b0 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 25 Sep 2024 09:43:58 +0200 Subject: [PATCH 590/596] make AssertFixMon static --- Source/monster.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/monster.cpp b/Source/monster.cpp index 2fd694db676..5c11db47bfc 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1544,7 +1544,7 @@ static void FixMonLocation(int mnum) mon->_mfuty = mon->_moldy = mon->_my; } -void AssertFixMonLocation(int mnum) +static void AssertFixMonLocation(int mnum) { MonsterStruct* mon; From 92eb1482886a425b3c642ec105ac6e8b31b4c095 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 25 Sep 2024 09:52:40 +0200 Subject: [PATCH 591/596] add DecreasePlrMaxHp --- Source/msg.cpp | 15 +-------------- Source/player.cpp | 21 +++++++++++++++++++++ Source/player.h | 1 + 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/Source/msg.cpp b/Source/msg.cpp index 8d012e90694..96a6d66511b 100644 --- a/Source/msg.cpp +++ b/Source/msg.cpp @@ -2276,20 +2276,7 @@ static unsigned On_ADDVIT(TCmd* pCmd, int pnum) static unsigned On_DECHP(TCmd* pCmd, int pnum) { - int tmp; - - if (plr._pMaxHPBase > (1 << 6) && plr._pMaxHP > (1 << 6)) { - tmp = plr._pMaxHP - (1 << 6); - plr._pMaxHP = tmp; - if (plr._pHitPoints > tmp) { - plr._pHitPoints = tmp; - } - tmp = plr._pMaxHPBase - (1 << 6); - plr._pMaxHPBase = tmp; - if (plr._pHPBase > tmp) { - plr._pHPBase = tmp; - } - } + DecreasePlrMaxHp(pnum); return sizeof(*pCmd); } diff --git a/Source/player.cpp b/Source/player.cpp index 063b2ba5b42..c9f9953371a 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -3444,6 +3444,27 @@ void IncreasePlrVit(int pnum) CalcPlrInv(pnum, true); } +void DecreasePlrMaxHp(int pnum) +{ + int tmp; + if ((unsigned)pnum >= MAX_PLRS) { + dev_fatal("DecreasePlrMaxHp: illegal player %d", pnum); + } + + if (plr._pMaxHPBase > (1 << 6) && plr._pMaxHP > (1 << 6)) { + tmp = plr._pMaxHP - (1 << 6); + plr._pMaxHP = tmp; + if (plr._pHitPoints > tmp) { + plr._pHitPoints = tmp; + } + tmp = plr._pMaxHPBase - (1 << 6); + plr._pMaxHPBase = tmp; + if (plr._pHPBase > tmp) { + plr._pHPBase = tmp; + } + } +} + void RestorePlrHpVit(int pnum) { int hp; diff --git a/Source/player.h b/Source/player.h index beeacb181d2..7fa90ef60ec 100644 --- a/Source/player.h +++ b/Source/player.h @@ -65,6 +65,7 @@ void IncreasePlrStr(int pnum); void IncreasePlrMag(int pnum); void IncreasePlrDex(int pnum); void IncreasePlrVit(int pnum); +void DecreasePlrMaxHp(int pnum); void RestorePlrHpVit(int pnum); // Set each location to the input location. From b02ba7b311226b1e9d272307c1208c05f90d6e7b Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 25 Sep 2024 09:58:13 +0200 Subject: [PATCH 592/596] fix L1RoomGen after 'sync L1RoomGen with L4RoomGen' --- Source/drlg_l1.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/drlg_l1.cpp b/Source/drlg_l1.cpp index b33f5bf3a18..22dd74e0db2 100644 --- a/Source/drlg_l1.cpp +++ b/Source/drlg_l1.cpp @@ -1140,7 +1140,6 @@ static void L1RoomGen(int x, int y, int w, int h, bool dir) height = RandRange(2, 6) & ~1; ry = h / 2u + y - height / 2u; } - if (i != 0) // proceed with the placed a room on the left if (rx >= 0) L1RoomGen(rx, ry, width, height, true); From d5952e7ea9bcfc5b762c2a75c8c0ed6500d5bbb5 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 25 Sep 2024 10:19:24 +0200 Subject: [PATCH 593/596] use a single sha1-context --- Source/codec.cpp | 25 +++++++++++++------------ Source/sha.cpp | 12 +++++++----- Source/sha.h | 8 ++++---- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/Source/codec.cpp b/Source/codec.cpp index dff0c6f2035..c1447a78b18 100644 --- a/Source/codec.cpp +++ b/Source/codec.cpp @@ -35,17 +35,18 @@ static void CodecInitKey(const char* pszPassword) } BYTE digest[SHA1HashSize]; - SHA1Reset(0); - SHA1Calculate(0, pw, digest); + SHA1Reset(/*0*/); + SHA1Calculate(/*0,*/ pw, digest); SHA1Clear(); for (unsigned i = 0; i < sizeof(key); ++i) key[i] ^= digest[i % SHA1HashSize]; memset(pw, 0, sizeof(pw)); memset(digest, 0, sizeof(digest)); - for (int n = 0; n < SHA1ContextNum; ++n) { - SHA1Reset(n); - SHA1Calculate(n, &key[sizeof(key) - SHA1BlockSize], NULL); - } + static_assert(SHA1ContextNum == 1, "CodecInitKey must initialize the sha1 contexts."); + // for (int n = 0; n < SHA1ContextNum; ++n) { + SHA1Reset(/*n*/); + SHA1Calculate(/*n,*/ &key[sizeof(key) - SHA1BlockSize], NULL); + // } memset(key, 0, sizeof(key)); } @@ -64,11 +65,11 @@ int codec_decode(BYTE* pbSrcDst, DWORD size, const char* pszPassword) return 0; for (i = size; i != 0; pbSrcDst += SHA1BlockSize, i -= SHA1BlockSize) { memcpy(buf, pbSrcDst, SHA1BlockSize); - SHA1Result(0, dst); + SHA1Result(/*0, */dst); for (int j = 0; j < SHA1BlockSize; j++) { buf[j] ^= dst[j % SHA1HashSize]; } - SHA1Calculate(0, buf, NULL); + SHA1Calculate(/*0,*/ buf, NULL); memcpy(pbSrcDst, buf, SHA1BlockSize); } @@ -78,7 +79,7 @@ int codec_decode(BYTE* pbSrcDst, DWORD size, const char* pszPassword) goto error; } - SHA1Result(0, dst); + SHA1Result(/*0,*/ dst); if (sig->checksum != *(uint32_t*)dst) { goto error; } @@ -116,8 +117,8 @@ void codec_encode(BYTE* pbSrcDst, DWORD size, DWORD encodedSize, const char* psz memcpy(buf, pbSrcDst, chunk); if (chunk < SHA1BlockSize) memset(buf + chunk, 0, SHA1BlockSize - chunk); - SHA1Result(0, dst); - SHA1Calculate(0, buf, NULL); + SHA1Result(/*0,*/ dst); + SHA1Calculate(/*0,*/ buf, NULL); for (int i = 0; i < SHA1BlockSize; i++) { buf[i] ^= dst[i % SHA1HashSize]; } @@ -126,7 +127,7 @@ void codec_encode(BYTE* pbSrcDst, DWORD size, DWORD encodedSize, const char* psz size -= chunk; } memset(buf, 0, sizeof(buf)); - SHA1Result(0, dst); + SHA1Result(/*0,*/ dst); sig = (CodecSignature*)pbSrcDst; sig->error = 0; sig->unused = 0; diff --git a/Source/sha.cpp b/Source/sha.cpp index 156730a4ca0..7c2b38bb6b2 100644 --- a/Source/sha.cpp +++ b/Source/sha.cpp @@ -132,10 +132,10 @@ void SHA1Clear() memset(sgSHA1, 0, sizeof(sgSHA1)); } -void SHA1Result(int n, BYTE Message_Digest[SHA1HashSize]) +void SHA1Result(/*int n,*/ BYTE Message_Digest[SHA1HashSize]) { DWORD* Message_Digest_Block; - int i; + int i, n = 0; assert(Message_Digest != NULL); Message_Digest_Block = (DWORD*)Message_Digest; @@ -145,15 +145,17 @@ void SHA1Result(int n, BYTE Message_Digest[SHA1HashSize]) } } -void SHA1Calculate(int n, const BYTE* data, BYTE Message_Digest[SHA1HashSize]) +void SHA1Calculate(/*int n,*/ const BYTE* data, BYTE Message_Digest[SHA1HashSize]) { + int n = 0; SHA1Input(&sgSHA1[n], data, SHA1BlockSize); if (Message_Digest != NULL) - SHA1Result(n, Message_Digest); + SHA1Result(/*n,*/ Message_Digest); } -void SHA1Reset(int n) +void SHA1Reset(/*int n*/) { + int n = 0; SHA1Init(&sgSHA1[n]); } diff --git a/Source/sha.h b/Source/sha.h index 69329a3a2a4..14983835879 100644 --- a/Source/sha.h +++ b/Source/sha.h @@ -12,14 +12,14 @@ DEVILUTION_BEGIN_NAMESPACE extern "C" { #endif -#define SHA1ContextNum 3 +#define SHA1ContextNum 1 #define SHA1HashSize 20 #define SHA1BlockSize 64 void SHA1Clear(); -void SHA1Result(int n, BYTE Message_Digest[SHA1HashSize]); -void SHA1Calculate(int n, const BYTE* data, BYTE Message_Digest[SHA1HashSize]); -void SHA1Reset(int n); +void SHA1Result(/*int n, */BYTE Message_Digest[SHA1HashSize]); +void SHA1Calculate(/*int n, */const BYTE* data, BYTE Message_Digest[SHA1HashSize]); +void SHA1Reset(/*int n*/); #ifdef __cplusplus } From ad125070a6aef9bfcdf0e272f295be9f5e3c2a89 Mon Sep 17 00:00:00 2001 From: pionere Date: Wed, 25 Sep 2024 11:23:06 +0200 Subject: [PATCH 594/596] rebalance monster/object density in cathedral and crypt --- Source/questdat.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Source/questdat.cpp b/Source/questdat.cpp index baa8f95b878..baa1a027c32 100644 --- a/Source/questdat.cpp +++ b/Source/questdat.cpp @@ -17,19 +17,19 @@ const LevelData AllLevels[NUM_FIXLVLS] = { { MT_INVALID }, }, /*DLV_CATHEDRAL1*/ { 2, FALSE, DTYPE_CATHEDRAL, DGT_CATHEDRAL, TMUSIC_L1, LFILE_L1, 10, 10, "Cathedral 1", - "Levels\\L1Data\\L1_%d.PAL", "Gendata\\Cutl1d.CEL", "Gendata\\Cutl1d.pal", TRUE, 138, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L1Data\\L1_%d.PAL", "Gendata\\Cutl1d.CEL", "Gendata\\Cutl1d.pal", TRUE, 138, 40, 24, 0, 0, WRPT_NONE, SPT_NONE, { MT_NZOMBIE, MT_RFALLSP, MT_WSKELAX, MT_RFALLSD, MT_NSCAV, MT_WSKELSD, MT_INVALID }, }, /*DLV_CATHEDRAL2*/ { 4, FALSE, DTYPE_CATHEDRAL, DGT_CATHEDRAL, TMUSIC_L1, LFILE_L1, 10, 10, "Cathedral 2", - "Levels\\L1Data\\L1_%d.PAL", "Gendata\\Cutl1d.CEL", "Gendata\\Cutl1d.pal", TRUE, 138, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L1Data\\L1_%d.PAL", "Gendata\\Cutl1d.CEL", "Gendata\\Cutl1d.pal", TRUE, 138, 40, 24, 0, 0, WRPT_NONE, SPT_NONE, { MT_NZOMBIE, MT_RFALLSP, MT_WSKELAX, MT_RFALLSD, MT_NSCAV, MT_WSKELSD, MT_BZOMBIE, MT_GZOMBIE, MT_DFALLSP, MT_YFALLSP, MT_TSKELAX, MT_RSKELAX, MT_DFALLSD, MT_YFALLSD, MT_WSKELBW, MT_TSKELBW, MT_BSCAV, MT_TSKELSD, MT_NSNEAK, MT_RBAT, MT_INVALID }, }, /*DLV_CATHEDRAL3*/ { 6, FALSE, DTYPE_CATHEDRAL, DGT_CATHEDRAL, TMUSIC_L1, LFILE_L1, 10, 10, "Cathedral 3", - "Levels\\L1Data\\L1_%d.PAL", "Gendata\\Cutl1d.CEL", "Gendata\\Cutl1d.pal", TRUE, 138, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L1Data\\L1_%d.PAL", "Gendata\\Cutl1d.CEL", "Gendata\\Cutl1d.pal", TRUE, 138, 40, 24, 0, 0, WRPT_NONE, SPT_NONE, { MT_NSCAV, MT_WSKELSD, MT_BZOMBIE, MT_GZOMBIE, MT_DFALLSP, MT_YFALLSP, MT_TSKELAX, MT_RSKELAX, MT_DFALLSD, MT_YFALLSD, MT_WSKELBW, MT_TSKELBW, MT_BSCAV, MT_TSKELSD, MT_NSNEAK, MT_RBAT, MT_NBAT, MT_YZOMBIE, MT_BFALLSP, MT_XSKELAX, MT_BFALLSD, MT_WSCAV, MT_RSKELBW, MT_RSKELSD, MT_INVALID }, }, /*DLV_CATHEDRAL4*/ { 8, FALSE, DTYPE_CATHEDRAL, DGT_CATHEDRAL, TMUSIC_L1, LFILE_L1, 10, 10, "Cathedral 4", - "Levels\\L1Data\\L1_%d.PAL", "Gendata\\Cutl1d.CEL", "Gendata\\Cutl1d.pal", TRUE, 138, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L1Data\\L1_%d.PAL", "Gendata\\Cutl1d.CEL", "Gendata\\Cutl1d.pal", TRUE, 138, 40, 24, 0, 0, WRPT_NONE, SPT_NONE, { MT_GZOMBIE, MT_YFALLSP, MT_RSKELAX, MT_YFALLSD, MT_TSKELBW, MT_BSCAV, MT_TSKELSD, MT_NSNEAK, MT_NBAT, MT_YZOMBIE, MT_BFALLSP, MT_XSKELAX, MT_BFALLSD, MT_WSCAV, MT_RSKELBW, MT_RSKELSD, MT_GBAT, MT_YSCAV, MT_XSKELBW, MT_XSKELSD, MT_NGOATMC, MT_NGOATBW, MT_INVALID }, }, /*DLV_CATACOMBS1*/ { 10, FALSE, DTYPE_CATACOMBS, DGT_CATACOMBS, TMUSIC_L2, LFILE_L2, 10, 10, "Catacombs 1", @@ -65,19 +65,19 @@ const LevelData AllLevels[NUM_FIXLVLS] = { { MT_DRHINO, MT_BACID, MT_RFAT, MT_NTHIN, MT_BGARG, MT_NMEGA, MT_DMEGA, MT_NSNAKE, MT_XTHIN, MT_RSNAKE, MT_NBLACK, MT_NSUCC, MT_BMEGA, MT_XACID, MT_GTHIN, MT_INVALID }, }, /*DLV_HELL1*/ { 26, FALSE, DTYPE_HELL, DGT_HELL, TMUSIC_L4, LFILE_L4, 12, 16, "Hell 1", - "Levels\\L4Data\\L4_%d.PAL", "Gendata\\Cut4.CEL", "Gendata\\Cut4.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L4Data\\L4_%d.PAL", "Gendata\\Cut4.CEL", "Gendata\\Cut4.pal", FALSE, 43, 46, 30, 0, 0, WRPT_NONE, SPT_NONE, { MT_DMEGA, MT_NSNAKE, MT_XTHIN, MT_RSNAKE, MT_NBLACK, MT_NSUCC, MT_BMEGA, MT_XACID, MT_GTHIN, MT_RMEGA, MT_BSNAKE, MT_RBLACK, MT_GBLACK, MT_GSUCC, MT_NMAGE, MT_INVALID }, }, /*DLV_HELL2*/ { 28, FALSE, DTYPE_HELL, DGT_HELL, TMUSIC_L4, LFILE_L4, 12, 16, "Hell 2", - "Levels\\L4Data\\L4_%d.PAL", "Gendata\\Cut4.CEL", "Gendata\\Cut4.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L4Data\\L4_%d.PAL", "Gendata\\Cut4.CEL", "Gendata\\Cut4.pal", FALSE, 43, 46, 30, 0, 0, WRPT_NONE, SPT_NONE, { MT_RSNAKE, MT_NBLACK, MT_NSUCC, MT_BMEGA, MT_XACID, MT_GTHIN, MT_RMEGA, MT_BSNAKE, MT_RBLACK, MT_GBLACK, MT_GSUCC, MT_NMAGE, MT_GMAGE, MT_SMAGE, MT_BBLACK, MT_RSUCC, MT_INVALID }, }, /*DLV_HELL3*/ { 30, FALSE, DTYPE_HELL, DGT_HELL, TMUSIC_L4, LFILE_L4, 12, 16, "Hell 3", - "Levels\\L4Data\\L4_%d.PAL", "Gendata\\Cut4.CEL", "Gendata\\Cut4.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L4Data\\L4_%d.PAL", "Gendata\\Cut4.CEL", "Gendata\\Cut4.pal", FALSE, 43, 46, 30, 0, 0, WRPT_NONE, SPT_NONE, { MT_RMEGA, MT_RBLACK, MT_GSUCC, MT_GMAGE, MT_BBLACK, MT_RSUCC, MT_GSNAKE, MT_BSUCC, MT_XMAGE, MT_SMAGE, MT_OMAGE, MT_INVALID }, }, /*DLV_HELL4*/ { 32, FALSE, DTYPE_HELL, DGT_HELL, TMUSIC_L4, LFILE_L4, 12, 16, "Diablo", - "Levels\\L4Data\\L4_%d.PAL", "Gendata\\Cutgate.CEL", "Gendata\\Cutgate.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, + "Levels\\L4Data\\L4_%d.PAL", "Gendata\\Cutgate.CEL", "Gendata\\Cutgate.pal", FALSE, 43, 46, 30, 0, 0, WRPT_NONE, SPT_NONE, { MT_INVALID }, /* MT_GBLACK, MT_BMAGE, MT_NBLACK, MT_DIABLO */ }, #ifdef HELLFIRE @@ -98,19 +98,19 @@ const LevelData AllLevels[NUM_FIXLVLS] = { { MT_VENMTAIL, MT_NECRMORB, MT_SPIDLORD, MT_LASHWORM, MT_TORCHANT, MT_INVALID }, /* MT_DEFILER */ }, /*DLV_CRYPT1*/ { 26, FALSE, DTYPE_CRYPT, DGT_CATHEDRAL, TMUSIC_L5, LFILE_L5, 10, 10, "Crypt 1", - "NLevels\\L5Data\\L5Base.PAL", "Nlevels\\Cutl5.CEL", "Nlevels\\Cutl5.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, + "NLevels\\L5Data\\L5Base.PAL", "Nlevels\\Cutl5.CEL", "Nlevels\\Cutl5.pal", FALSE, 43, 48, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_LRDSAYTR, MT_GRAVEDIG, MT_BIGFALL, MT_TOMBRAT, MT_FIREBAT, MT_LICH, MT_INVALID }, }, /*DLV_CRYPT2*/ { 28, FALSE, DTYPE_CRYPT, DGT_CATHEDRAL, TMUSIC_L5, LFILE_L5, 10, 10, "Crypt 2", - "NLevels\\L5Data\\L5Base.PAL", "Nlevels\\Cutl5.CEL", "Nlevels\\Cutl5.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, + "NLevels\\L5Data\\L5Base.PAL", "Nlevels\\Cutl5.CEL", "Nlevels\\Cutl5.pal", FALSE, 43, 48, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_BIGFALL, MT_TOMBRAT, MT_FIREBAT, MT_SKLWING, MT_LICH, MT_CRYPTDMN, MT_INVALID }, }, /*DLV_CRYPT3*/ { 30, FALSE, DTYPE_CRYPT, DGT_CATHEDRAL, TMUSIC_L5, LFILE_L5, 10, 10, "Crypt 3", - "NLevels\\L5Data\\L5Base.PAL", "Nlevels\\Cutl5.CEL", "Nlevels\\Cutl5.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, + "NLevels\\L5Data\\L5Base.PAL", "Nlevels\\Cutl5.CEL", "Nlevels\\Cutl5.pal", FALSE, 43, 48, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_CRYPTDMN, MT_HELLBAT, MT_BONEDEMN, MT_ARCHLICH, MT_BICLOPS, MT_FLESTHNG, MT_REAPER, MT_INVALID }, }, /*DLV_CRYPT4*/ { 32, FALSE, DTYPE_CRYPT, DGT_CATHEDRAL, TMUSIC_L5, LFILE_L5, 10, 10, "Crypt 4", - "NLevels\\L5Data\\L5Base.PAL", "Nlevels\\Cutl5.CEL", "Nlevels\\Cutl5.pal", FALSE, 43, 50, 32, 0, 0, WRPT_NONE, SPT_NONE, + "NLevels\\L5Data\\L5Base.PAL", "Nlevels\\Cutl5.CEL", "Nlevels\\Cutl5.pal", FALSE, 43, 48, 32, 0, 0, WRPT_NONE, SPT_NONE, { MT_HELLBAT, MT_BICLOPS, MT_FLESTHNG, MT_REAPER, MT_INVALID }, /* MT_ARCHLICH, MT_NAKRUL */ }, #endif From 68d27672b1485b5de681cbf4110430e8b5704da8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 16:54:01 +0100 Subject: [PATCH 595/596] Bump softprops/action-gh-release from 2.0.8 to 2.1.0 (#15) Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.0.8 to 2.1.0. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/v2.0.8...v2.1.0) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/nightly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 5291d589b05..10b596233da 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1598,7 +1598,7 @@ jobs: shell: bash - name: Release - uses: softprops/action-gh-release@v2.0.8 + uses: softprops/action-gh-release@v2.1.0 with: tag_name: devilx-nightly body_path: ${{ github.workspace }}/RELEASE_NOTE.md From 520113cb8357c267bd9a49055da415797b7d1ef2 Mon Sep 17 00:00:00 2001 From: pionere Date: Mon, 16 Dec 2024 18:44:23 +0100 Subject: [PATCH 596/596] use macos-13 runners --- .github/workflows/cmake.yml | 2 +- .github/workflows/nightly.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 0284aa9487c..8d51d3814e9 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -13,7 +13,7 @@ jobs: # well on Windows or Mac. You can convert this to a matrix build if you need # cross-platform coverage. # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix - runs-on: macos-12 + runs-on: macos-13 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 10b596233da..e744a87b163 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -386,7 +386,7 @@ jobs: - name: hellfire+patch cmakeargs: '-DDEVILUTIONX_SYSTEM_SDL2=OFF -DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-macp.dmg' - runs-on: macos-12 + runs-on: macos-13 steps: - uses: actions/checkout@v4 with: @@ -433,7 +433,7 @@ jobs: - name: hellfire+patch cmakeargs: '-DUSE_PATCH=ON -DHELLFIRE=ON' artifact: 'hellfire-nightly-iosp.ipa' - runs-on: macos-12 + runs-on: macos-13 steps: - uses: actions/checkout@v4 with: