diff --git a/.github/workflows/build-msvc-cmake.yml b/.github/workflows/build-msvc-cmake.yml new file mode 100644 index 0000000000..54491c032d --- /dev/null +++ b/.github/workflows/build-msvc-cmake.yml @@ -0,0 +1,122 @@ +name: CI Build + +on: + push: + branches: [master, develop] + pull_request: + branches: [master, develop] + +jobs: + build-mingw-x86: + name: "MinGW Windows x86" + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: dkfans/setup-cpp@master + + - name: Update system + run: | + set -eux + sudo apt update + sudo apt install -y build-essential g++-mingw-w64-i686 libpng16-16t64 + + - name: Build + run: | + set -eux + BUILD_NUMBER=$(git rev-list --count HEAD) + make BUILD_NUMBER=$BUILD_NUMBER standard + + build-linux-x86_64: + name: "Linux x86_64" + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Update system + run: | + set -eux + sudo apt update + sudo apt install -y \ + build-essential \ + pkg-config \ + curl \ + libavcodec-dev \ + libavformat-dev \ + libavutil-dev \ + libopenal-dev \ + libluajit-5.1-dev \ + libminizip-dev \ + libnatpmp-dev \ + libspng-dev \ + libsdl2-dev \ + libsdl2-image-dev \ + libsdl2-mixer-dev \ + libsdl2-net-dev \ + libswresample-dev \ + libminiupnpc-dev \ + zlib1g-dev + + - name: Build + run: | + set -eux + BUILD_NUMBER=$(git rev-list --count HEAD) + make BUILD_NUMBER=$BUILD_NUMBER -f linux.mk + + build-msvc-x86: + name: "MSVC x86 Release" + runs-on: windows-latest + + permissions: + contents: read + packages: write + + env: + VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite" + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Export GitHub Actions cache environment + uses: actions/github-script@v7 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || ''); + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); + + - name: Setup vcpkg binary caching via GitHub Packages + shell: pwsh + env: + GH_PACKAGES_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + $owner = "${{ github.repository_owner }}" + $source = "https://nuget.pkg.github.com/${owner}/index.json" + nuget sources add -Name "GitHub" -Source $source -Username $owner -Password $env:GH_PACKAGES_TOKEN -StorePasswordInClearText + nuget setapikey $env:GH_PACKAGES_TOKEN -Source "GitHub" + $mode = if ("${{ github.event_name }}" -eq "push") { "readwrite" } else { "read" } + echo "VCPKG_BINARY_SOURCES=clear;x-gha,readwrite;nuget,GitHub,${mode}" >> $env:GITHUB_ENV + + - name: Init vcpkg submodule + run: git submodule update --init external/vcpkg + + - name: Bootstrap vcpkg + shell: cmd + run: .\external\vcpkg\bootstrap-vcpkg.bat -disableMetrics + + - uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x86 + + - name: Configure + run: cmake --preset x86-windows-static-release + + - name: Build + run: cmake --build --preset x86-windows-static-release diff --git a/.gitignore b/.gitignore index 04f217aed8..879a061b28 100644 --- a/.gitignore +++ b/.gitignore @@ -14,10 +14,8 @@ /config/fxdata/*.dat /config/fxdata/*.fon .vs/ -build*/ /out/* *.cache -.vscode /libexterns docs/html docs/latex @@ -32,7 +30,6 @@ res/keeperfx_icon.ico /deps/zlib /deps/spng /deps/astronomy -/deps/centijson /deps/ffmpeg /deps/openal /deps/luajit @@ -40,7 +37,26 @@ res/keeperfx_icon.ico /deps/libnatpmp /deps/*.tar.gz /cppcheck.cache + +# vcpkg installed packages — build output, never committed. +# Placed one level up (../vcpkg_installed) so all worktrees share one copy. +vcpkg_installed/ + /src/ver_defs.h keeperfx.log crash_log.txt .local/ +.deploy/ + +# Python cache +__pycache__/ +*.pyc +*.pyo +*.pyd +.Python + +# Generated documentation/audit reports +*_AUDIT_REPORT.md +*_DEPENDENCIES_*.md +*_SECURITY_AUDIT.md +.vscode/.sonar-token diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..78b7060988 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "external/vcpkg"] + path = external/vcpkg + url = https://github.com/microsoft/vcpkg diff --git a/CMakeLists.txt b/CMakeLists.txt index 585294eb8a..5cc0929ddf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,91 +10,47 @@ project(keeperfx C CXX) set(CMAKE_C_STANDARD 11) set(CMAKE_CXX_STANDARD 20) -# Get the abbreviated commit Id of the head. -find_package(Git REQUIRED) -execute_process(COMMAND "${GIT_EXECUTABLE}" describe --always OUTPUT_VARIABLE COMMIT_ID OUTPUT_STRIP_TRAILING_WHITESPACE) - +# Version information set(VER_MAJOR 1) -set(VER_MINOR 2) -set(VER_RELEASE 0) +set(VER_MINOR 3) +set(VER_RELEASE 1) set(VER_BUILD 0) set(VER_STRING "${VER_MAJOR}.${VER_MINOR}.${VER_RELEASE}.${VER_BUILD} ${PACKAGE_SUFFIX}") set(PACKAGE_SUFFIX "") -set(GIT_REVISION "${COMMIT_ID}") -# CMAKE_BINARY_DIR is defined in CMakePresets.json. -set(KEEPERFX_VER_DEFS_H_IN ${CMAKE_SOURCE_DIR}/ver_defs.h.in) -set(KEEPERFX_VER_DEFS_H_OUT ${CMAKE_SOURCE_DIR}/ver_defs.h) +# Extract git revision +find_package(Git QUIET) +if(GIT_FOUND) + execute_process( + COMMAND ${GIT_EXECUTABLE} describe --always + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE GIT_REVISION + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) +else() + set(GIT_REVISION "unknown") +endif() + +# Generate version header +set(KEEPERFX_VER_DEFS_H_IN ${CMAKE_SOURCE_DIR}/build/ver_defs.h.in) +set(KEEPERFX_VER_DEFS_H_OUT ${CMAKE_SOURCE_DIR}/src/ver_defs.h) configure_file(${KEEPERFX_VER_DEFS_H_IN} ${KEEPERFX_VER_DEFS_H_OUT}) -find_package(SDL2 CONFIG REQUIRED) -find_package(SDL2_image CONFIG REQUIRED) -find_package(SDL2_mixer CONFIG REQUIRED) -find_package(SDL2_net CONFIG REQUIRED) - -# Global definitions. -add_compile_definitions(_CRT_NONSTDC_NO_WARNINGS _CRT_SECURE_NO_WARNINGS) - -file(GLOB_RECURSE KEEPERFX_SOURCES_C "src/*.c") -file(GLOB_RECURSE KEEPERFX_SOURCES_CXX "src/*.cpp") - -# Global definitions for all targets. -add_compile_definitions("DEBUG=$,1,0>") -add_compile_definitions("SPNG_STATIC=1") - -# Add two executable targets: keeperfx and keeperfx_hvlog. -add_executable(keeperfx ${KEEPERFX_SOURCES_C} ${KEEPERFX_SOURCES_CXX}) - -target_compile_definitions(keeperfx PUBLIC BFDEBUG_LEVEL=0) -target_sources(keeperfx PRIVATE "res/keeperfx_stdres.rc") +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# Load CMake Modules +# See: build/cmake/modules/ +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/build/cmake/modules) -add_executable(keeperfx_hvlog ${KEEPERFX_SOURCES_C} ${KEEPERFX_SOURCES_CXX}) +include(Helpers) +include(Platforms) +include(Dependencies) +include(BuildTargets) -target_compile_definitions(keeperfx_hvlog PUBLIC BFDEBUG_LEVEL=10) -target_sources(keeperfx_hvlog PRIVATE "res/keeperfx_stdres.rc") - -message(STATUS "We are using ${CMAKE_CXX_COMPILER_ID}") - -# The default bfd linker in MinGW is extremely slow. LLVM linker (LLD) is much much faster. -set_property(TARGET keeperfx PROPERTY LINKER_TYPE LLD) -set_property(TARGET keeperfx_hvlog PROPERTY LINKER_TYPE LLD) - -set(WARNFLAGS -Wall -W -Wshadow -Wno-sign-compare -Wno-unused-parameter -Wno-strict-aliasing -Wno-unknown-pragmas -Werror) -set(GNU_COMPILER_FLAG -march=x86-64 -fno-omit-frame-pointer -fmessage-length=0) -set(GNU_LINK_FLAG -mwindows -Wl,--enable-auto-import) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wimplicit") -target_compile_options(keeperfx PRIVATE ${WARNFLAGS} ${GNU_COMPILER_FLAG}) -target_compile_options(keeperfx_hvlog PRIVATE ${WARNFLAGS} ${GNU_COMPILER_FLAG}) -target_link_options(keeperfx PRIVATE ${GNU_LINK_FLAG} -Wl,-Map,keeperfx.map) -target_link_options(keeperfx_hvlog PRIVATE ${GNU_LINK_FLAG} -Wl,-Map,keeperfx_hvlog.map) -target_link_libraries (keeperfx PUBLIC -static stdc++ winpthread -dynamic) -target_link_libraries (keeperfx_hvlog PUBLIC -static stdc++ winpthread -dynamic) - -# System libraries. -target_link_libraries(keeperfx PRIVATE imagehlp dbghelp) -target_link_libraries(keeperfx_hvlog PRIVATE imagehlp dbghelp) - -# Go into submodules. +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# Subdirectories +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ add_subdirectory(deps) add_subdirectory(tools) -# External libraries. -target_link_libraries(keeperfx - PRIVATE - $,SDL2::SDL2,SDL2::SDL2-static>) -target_link_libraries(keeperfx - PRIVATE $,SDL2_mixer::SDL2_mixer,SDL2_mixer::SDL2_mixer-static>) -target_link_libraries(keeperfx - PRIVATE $,SDL2_net::SDL2_net,SDL2_net::SDL2_net-static>) -target_link_libraries(keeperfx - PRIVATE $,SDL2_image::SDL2_image,SDL2_image::SDL2_image-static>) - -target_link_libraries(keeperfx_hvlog - PRIVATE - $,SDL2::SDL2,SDL2::SDL2-static>) -target_link_libraries(keeperfx_hvlog - PRIVATE $,SDL2_mixer::SDL2_mixer,SDL2_mixer::SDL2_mixer-static>) -target_link_libraries(keeperfx_hvlog - PRIVATE $,SDL2_net::SDL2_net,SDL2_net::SDL2_net-static>) -target_link_libraries(keeperfx_hvlog - PRIVATE $,SDL2_image::SDL2_image,SDL2_image::SDL2_image-static>) diff --git a/CMakePresets.json b/CMakePresets.json index b606168c37..eed05b2bb6 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -1,4 +1,4 @@ -{ +{ "version": 3, "configurePresets": [ { @@ -11,10 +11,10 @@ "installDir": "${sourceDir}/out/install/${presetName}", "cacheVariables": { "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}", - "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" + "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/external/vcpkg/scripts/buildsystems/vcpkg.cmake", + "VCPKG_INSTALLED_DIR": "${sourceDir}/../vcpkg_installed" } }, - { "name": "x86", "hidden": true, @@ -23,12 +23,13 @@ "strategy": "external" } }, - { "name": "Debug", "displayName": "Config Debug", "hidden": true, - "cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" } + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + } }, { "name": "Release", @@ -38,7 +39,6 @@ "CMAKE_BUILD_TYPE": "RelWithDebInfo" } }, - { "name": "MSVC", "hidden": true, @@ -60,32 +60,210 @@ } } }, - { "name": "Debug-Clang", "displayName": "Debug Clang", - "inherits": [ "base", "x86", "Debug", "Clang" ], + "inherits": [ + "base", + "x86", + "Debug", + "Clang" + ], "hidden": true }, { "name": "Release-Clang", "displayName": "Release Clang", - "inherits": [ "base", "x86", "Release", "Clang" ], + "inherits": [ + "base", + "x86", + "Release", + "Clang" + ], "hidden": true }, { "name": "Debug-MSVC", "displayName": "Debug MSVC", - "inherits": [ "base", "x86", "Debug", "MSVC" ], + "inherits": [ + "base", + "x86", + "Debug", + "MSVC" + ], "hidden": true }, { "name": "Release-MSVC", "displayName": "Release MSVC", - "inherits": [ "base", "x86", "Release", "MSVC" ], + "inherits": [ + "base", + "x86", + "Release", + "MSVC" + ], "hidden": true }, + { + "name": "linux-base", + "displayName": "Linux Base", + "description": "Base for Linux native builds (no vcpkg toolchain; uses system packages)", + "hidden": true, + "generator": "Ninja", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "installDir": "${sourceDir}/out/install/${presetName}", + "cacheVariables": { + "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}" + } + }, + { + "name": "x64", + "hidden": true, + "architecture": { + "value": "x64", + "strategy": "external" + } + }, + { + "name": "MSVC-x86-Base", + "hidden": true, + "inherits": "base", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "installDir": "${sourceDir}/out/install/${presetName}", + "architecture": { + "value": "x86", + "strategy": "external" + }, + "cacheVariables": { + "CMAKE_C_COMPILER": "cl.exe", + "CMAKE_CXX_COMPILER": "cl.exe", + "VCPKG_TARGET_TRIPLET": "x86-windows-static", + "CMAKE_POLICY_VERSION_MINIMUM": "3.5", + "CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreaded$<$:Debug>" + } + }, + { + "name": "MSVC-x64-Base", + "hidden": true, + "inherits": "base", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "installDir": "${sourceDir}/out/install/${presetName}", + "architecture": { + "value": "x64", + "strategy": "external" + }, + "cacheVariables": { + "CMAKE_C_COMPILER": "cl.exe", + "CMAKE_CXX_COMPILER": "cl.exe", + "VCPKG_TARGET_TRIPLET": "x64-windows-static", + "CMAKE_POLICY_VERSION_MINIMUM": "3.5", + "CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreaded$<$:Debug>" + } + }, + { + "name": "x86-windows-static-debug", + "displayName": "MSVC x86 Debug (static)", + "description": "Windows x86 Debug build with MSVC, static runtime linking", + "inherits": [ + "MSVC-x86-Base", + "Debug" + ], + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "on" + } + }, + { + "name": "x86-windows-static-release", + "displayName": "MSVC x86 Release (static)", + "description": "Windows x86 Release build with MSVC, static runtime linking, optimized", + "inherits": [ + "MSVC-x86-Base", + "Release" + ], + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "on" + } + }, + { + "name": "x64-windows-static-debug", + "displayName": "MSVC x64 Debug (static)", + "description": "Windows x64 Debug build with MSVC, static runtime linking", + "inherits": [ + "MSVC-x64-Base", + "Debug" + ], + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "on" + } + }, + { + "name": "x64-windows-static-release", + "displayName": "MSVC x64 Release (static)", + "description": "Windows x64 Release build with MSVC, static runtime linking, optimized", + "inherits": [ + "MSVC-x64-Base", + "Release" + ], + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "on" + } + }, + { + "name": "x86-windows-static-debug-asan", + "displayName": "MSVC x86 Debug + ASan (static)", + "description": "Windows x86 Debug with AddressSanitizer for catching OOB/UAF bugs", + "inherits": [ "MSVC-x86-Base", "Debug" ], + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "on", + "KEEPERFX_SANITIZERS": "ON" + } + }, + + { + "name": "x86-windows-static-reldebug-asan", + "displayName": "MSVC x86 RelDebug + ASan (static)", + "description": "Windows x86 RelWithDebInfo with AddressSanitizer (better perf than Debug)", + "inherits": [ "MSVC-x86-Base", "Release" ], + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "on", + "KEEPERFX_SANITIZERS": "ON" + } + }, + + { + "name": "x64-windows-static-debug-asan", + "displayName": "MSVC x64 Debug + ASan (static)", + "description": "Windows x64 Debug with AddressSanitizer for catching OOB/UAF bugs", + "inherits": [ "MSVC-x64-Base", "Debug" ], + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "on", + "KEEPERFX_SANITIZERS": "ON" + } + }, + + { + "name": "x64-windows-static-reldebug-asan", + "displayName": "MSVC x64 RelDebug + ASan (static)", + "description": "Windows x64 RelWithDebInfo with AddressSanitizer (better perf than Debug)", + "inherits": [ "MSVC-x64-Base", "Release" ], + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "on", + "KEEPERFX_SANITIZERS": "ON" + } + }, + { + "name": "cross-base", + "displayName": "Cross-Compile Base", + "description": "Base for Docker/Linux cross-compile builds (no vcpkg; toolchain set per-preset)", + "hidden": true, + "generator": "Ninja", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "installDir": "${sourceDir}/out/install/${presetName}", + "cacheVariables": { + "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}" + } + }, { "name": "MingGW32-Base", "hidden": true, @@ -104,11 +282,19 @@ } } }, - { "name": "x86-MinGW32-Debug", "displayName": "x86-MinGW32-Debug", - "inherits": [ "MingGW32-Base", "x86", "Debug" ], + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + }, + "inherits": [ + "MingGW32-Base", + "x86", + "Debug" + ], "cacheVariables": { "CMAKE_EXPORT_COMPILE_COMMANDS": "on" } @@ -116,8 +302,106 @@ { "name": "x86-MinGW32-Release", "displayName": "x86-MinGW32-Release", - "inherits": [ "MingGW32-Base", "x86", "Release" ], + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + }, + "inherits": [ + "MingGW32-Base", + "x86", + "Release" + ], + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "on" + } + }, + { + "name": "windows-x86-release", + "displayName": "Windows x86 Release (Docker/Linux cross-compile)", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Linux" + }, + "description": "Cross-compile for Windows x86 from Linux using i686-w64-mingw32. Designed for use inside the keeperfx-build-mingw32 Docker image.", + "inherits": [ + "cross-base", + "Release" + ], + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/build/cmake/mingw32.cmake", + "CMAKE_EXPORT_COMPILE_COMMANDS": "on", + "CMAKE_BUILD_TYPE": "Release" + } + }, + { + "name": "windows-x86-debug", + "displayName": "Windows x86 Debug (Docker/Linux cross-compile)", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Linux" + }, + "description": "Cross-compile for Windows x86 from Linux using i686-w64-mingw32, with full debug symbols. For use inside the keeperfx-build-mingw32 Docker image.", + "inherits": [ + "cross-base", + "Debug" + ], "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/build/cmake/mingw32.cmake", + "CMAKE_EXPORT_COMPILE_COMMANDS": "on" + } + }, + { + "name": "windows-x64-release", + "displayName": "Windows x64 Release (Docker/Linux cross-compile)", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Linux" + }, + "description": "Cross-compile for Windows x64 from Linux using x86_64-w64-mingw32. Designed for use inside the keeperfx-build-mingw64 Docker image.", + "inherits": [ + "cross-base", + "Release" + ], + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/build/cmake/mingw64.cmake", + "CMAKE_EXPORT_COMPILE_COMMANDS": "on", + "CMAKE_BUILD_TYPE": "Release" + } + }, + { + "name": "linux-x64-release", + "displayName": "Linux x64 Release", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Linux" + }, + "description": "Linux native build using system packages", + "inherits": [ + "linux-base", + "Release" + ], + "cacheVariables": { + "CMAKE_EXPORT_COMPILE_COMMANDS": "on" + } + }, + { + "name": "linux-x64-asan", + "displayName": "Linux x64 ASAN", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Linux" + }, + "description": "Linux native build with AddressSanitizer + UndefinedBehaviorSanitizer", + "inherits": "linux-base", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "KEEPERFX_SANITIZERS": "ON", "CMAKE_EXPORT_COMPILE_COMMANDS": "on" } } @@ -130,7 +414,6 @@ "verbose": true, "configurePreset": "Debug" }, - { "name": "StandardLog", "hidden": true, @@ -143,7 +426,6 @@ "inherits": "Base", "targets": "keeperfx_hvlog" }, - { "name": "Debug-Clang-Standard", "displayName": "Debug Clang Standard", @@ -192,7 +474,6 @@ "inherits": "HeavyLog", "configurePreset": "Release-MSVC" }, - { "name": "Debug-MinGW32-Standard", "displayName": "Debug MinGW32 Standard", @@ -216,6 +497,85 @@ "displayName": "Release MinGW32 HeavyLog", "inherits": "HeavyLog", "configurePreset": "x86-MinGW32-Release" + }, + { + "name": "windows-x86-release", + "displayName": "Windows x86 Release", + "inherits": "StandardLog", + "configurePreset": "windows-x86-release" + }, + { + "name": "windows-x86-debug", + "displayName": "Windows x86 Debug", + "inherits": "StandardLog", + "configurePreset": "windows-x86-debug" + }, + { + "name": "x86-windows-static-debug", + "displayName": "MSVC x86 Debug (static)", + "inherits": "StandardLog", + "configurePreset": "x86-windows-static-debug" + }, + { + "name": "x86-windows-static-release", + "displayName": "MSVC x86 Release (static)", + "inherits": "StandardLog", + "configurePreset": "x86-windows-static-release" + }, + { + "name": "x64-windows-static-debug", + "displayName": "MSVC x64 Debug (static)", + "inherits": "StandardLog", + "configurePreset": "x64-windows-static-debug" + }, + { + "name": "x64-windows-static-release", + "displayName": "MSVC x64 Release (static)", + "inherits": "StandardLog", + "configurePreset": "x64-windows-static-release" + }, + { + "name": "x86-windows-static-debug-asan", + "displayName": "MSVC x86 Debug + ASan (static)", + "inherits": "StandardLog", + "configurePreset": "x86-windows-static-debug-asan" + }, + { + "name": "x86-windows-static-reldebug-asan", + "displayName": "MSVC x86 RelDebug + ASan (static)", + "inherits": "StandardLog", + "configurePreset": "x86-windows-static-reldebug-asan" + }, + { + "name": "x64-windows-static-debug-asan", + "displayName": "MSVC x64 Debug + ASan (static)", + "inherits": "StandardLog", + "configurePreset": "x64-windows-static-debug-asan" + }, + { + "name": "x64-windows-static-reldebug-asan", + "displayName": "MSVC x64 RelDebug + ASan (static)", + "inherits": "StandardLog", + "configurePreset": "x64-windows-static-reldebug-asan" + }, + + { + "name": "windows-x64-release", + "displayName": "Windows x64 Release", + "inherits": "StandardLog", + "configurePreset": "windows-x64-release" + }, + { + "name": "linux-x64-release", + "displayName": "Linux x64 Release", + "inherits": "StandardLog", + "configurePreset": "linux-x64-release" + }, + { + "name": "linux-x64-asan", + "displayName": "Linux x64 ASAN", + "inherits": "Base", + "configurePreset": "linux-x64-asan" } ] -} +} \ No newline at end of file diff --git a/build/cmake/mingw32.cmake b/build/cmake/mingw32.cmake new file mode 100644 index 0000000000..c3380596d8 --- /dev/null +++ b/build/cmake/mingw32.cmake @@ -0,0 +1,9 @@ +set(CMAKE_SYSTEM_NAME Windows) +set(TOOLCHAIN_PREFIX i686-w64-mingw32) +set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc-posix) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++-posix) +set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres) +set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX}) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/build/cmake/mingw64.cmake b/build/cmake/mingw64.cmake new file mode 100644 index 0000000000..943858d91b --- /dev/null +++ b/build/cmake/mingw64.cmake @@ -0,0 +1,9 @@ +set(CMAKE_SYSTEM_NAME Windows) +set(TOOLCHAIN_PREFIX x86_64-w64-mingw32) +set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc-posix) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++-posix) +set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres) +set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX}) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/build/cmake/modules/BuildTargets.cmake b/build/cmake/modules/BuildTargets.cmake new file mode 100644 index 0000000000..43bd26fa01 --- /dev/null +++ b/build/cmake/modules/BuildTargets.cmake @@ -0,0 +1,140 @@ +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# BuildTargets.cmake — Target definitions (keeperfx, keeperfx_hvlog, tests) +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +# ━━━ Source File Collection ━━━ +file(GLOB_RECURSE KEEPERFX_SOURCES_C "src/*.c") +file(GLOB_RECURSE KEEPERFX_SOURCES_CXX "src/*.cpp") + +# Exclude stub files — added back explicitly when needed +list(FILTER KEEPERFX_SOURCES_C EXCLUDE REGEX ".*/bflib_cpu_stub\\.c$") +list(FILTER KEEPERFX_SOURCES_C EXCLUDE REGEX ".*/bflib_network_stub\\.c$") + +# OpenGL renderer exclusion +if(NOT KEEPERFX_RENDERER_OPENGL) + list(FILTER KEEPERFX_SOURCES_CXX EXCLUDE REGEX ".*/renderer/RendererOpenGL\\.cpp$") + list(FILTER KEEPERFX_SOURCES_CXX EXCLUDE REGEX ".*/platform_gl_sdl2\\.cpp$") +endif() + +# ━━━ Networking Exclusions ━━━ +if(NOT KEEPERFX_NETWORKING) + list(FILTER KEEPERFX_SOURCES_C EXCLUDE REGEX ".*/api\\.c$") + list(FILTER KEEPERFX_SOURCES_C EXCLUDE REGEX ".*/bflib_tcpsp\\.c$") + list(FILTER KEEPERFX_SOURCES_C EXCLUDE REGEX ".*/bflib_base_tcp\\.c$") + list(FILTER KEEPERFX_SOURCES_C EXCLUDE REGEX ".*/bflib_client_tcp\\.c$") + list(FILTER KEEPERFX_SOURCES_C EXCLUDE REGEX ".*/bflib_server_tcp\\.c$") + list(FILTER KEEPERFX_SOURCES_C EXCLUDE REGEX ".*/bflib_enet\\.c$") + list(FILTER KEEPERFX_SOURCES_C EXCLUDE REGEX ".*/net_portforward\\.c$") + list(FILTER KEEPERFX_SOURCES_C EXCLUDE REGEX ".*/bflib_netsession\\.c$") + list(FILTER KEEPERFX_SOURCES_CXX EXCLUDE REGEX ".*/bflib_netsp\\.cpp$") + list(FILTER KEEPERFX_SOURCES_CXX EXCLUDE REGEX ".*/bflib_network\\.cpp$") + list(FILTER KEEPERFX_SOURCES_CXX EXCLUDE REGEX ".*/bflib_network_exchange\\.cpp$") + list(FILTER KEEPERFX_SOURCES_C EXCLUDE REGEX ".*/net_resync\\.c$") + list(FILTER KEEPERFX_SOURCES_C EXCLUDE REGEX ".*/net_input_lag\\.c$") + list(FILTER KEEPERFX_SOURCES_C EXCLUDE REGEX ".*/net_received_packets\\.c$") + list(FILTER KEEPERFX_SOURCES_C EXCLUDE REGEX ".*/net_redundant_packets\\.c$") + list(FILTER KEEPERFX_SOURCES_C EXCLUDE REGEX ".*/net_checksums\\.c$") + list(FILTER KEEPERFX_SOURCES_C EXCLUDE REGEX ".*/net_game\\.c$") + list(FILTER KEEPERFX_SOURCES_CXX EXCLUDE REGEX ".*/bflib_enet\\.cpp$") + list(FILTER KEEPERFX_SOURCES_CXX EXCLUDE REGEX ".*/bflib_base_tcp\\.cpp$") + list(FILTER KEEPERFX_SOURCES_CXX EXCLUDE REGEX ".*/bflib_client_tcp\\.cpp$") + list(FILTER KEEPERFX_SOURCES_CXX EXCLUDE REGEX ".*/bflib_server_tcp\\.cpp$") + list(FILTER KEEPERFX_SOURCES_CXX EXCLUDE REGEX ".*/net_portforward\\.cpp$") + list(FILTER KEEPERFX_SOURCES_CXX EXCLUDE REGEX ".*/net_resync\\.cpp$") + list(APPEND KEEPERFX_SOURCES_C "src/bflib_network_stub.c") +endif() + +# ━━━ Desktop platform filtering (Windows vs Linux) ━━━ +if(WIN32 OR MINGW) + list(FILTER KEEPERFX_SOURCES_CXX EXCLUDE REGEX ".*/platform/PlatformLinux\\.cpp$") + list(FILTER KEEPERFX_SOURCES_CXX EXCLUDE REGEX ".*/src/linux\\.cpp$") +elseif(UNIX AND NOT APPLE) + list(FILTER KEEPERFX_SOURCES_CXX EXCLUDE REGEX ".*/platform/PlatformWindows\\.cpp$") + list(FILTER KEEPERFX_SOURCES_CXX EXCLUDE REGEX ".*/src/windows\\.cpp$") +elseif(APPLE) + list(FILTER KEEPERFX_SOURCES_CXX EXCLUDE REGEX ".*/platform/PlatformLinux\\.cpp$") + list(FILTER KEEPERFX_SOURCES_CXX EXCLUDE REGEX ".*/platform/PlatformWindows\\.cpp$") + list(FILTER KEEPERFX_SOURCES_CXX EXCLUDE REGEX ".*/src/linux\\.cpp$") + list(FILTER KEEPERFX_SOURCES_CXX EXCLUDE REGEX ".*/src/windows\\.cpp$") +endif() + +# ━━━ Main Targets: keeperfx & keeperfx_hvlog ━━━ +add_executable(keeperfx ${KEEPERFX_SOURCES_C} ${KEEPERFX_SOURCES_CXX}) +if(MSVC) + set_target_properties(keeperfx PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/.deploy" + RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_SOURCE_DIR}/.deploy" + ) +endif() +target_include_directories(keeperfx PRIVATE src deps/centitoml deps/centijson/include) +target_compile_definitions(keeperfx PUBLIC BFDEBUG_LEVEL=0) +if(WIN32) + target_sources(keeperfx PRIVATE "res/keeperfx_stdres.rc") +endif() +apply_keeperfx_warnings(keeperfx) +apply_keeperfx_link_flags(keeperfx) +apply_windows_system_libs(keeperfx) + +# Link SDL2 (vcpkg static targets have -static suffix; mingw/Linux use plain names) +macro(kfx_link_sdl2_target TARGET_NAME) + if(TARGET SDL2::SDL2-static) + target_link_libraries(${TARGET_NAME} PRIVATE SDL2::SDL2-static) + elseif(TARGET SDL2::SDL2) + target_link_libraries(${TARGET_NAME} PRIVATE SDL2::SDL2 SDL2::SDL2main) + elseif(TARGET SDL2) + target_link_libraries(${TARGET_NAME} PRIVATE SDL2) + endif() + if(TARGET SDL2_image::SDL2_image-static) + target_link_libraries(${TARGET_NAME} PRIVATE SDL2_image::SDL2_image-static) + elseif(TARGET SDL2_image::SDL2_image) + target_link_libraries(${TARGET_NAME} PRIVATE SDL2_image::SDL2_image) + endif() + if(TARGET SDL2_mixer::SDL2_mixer-static) + target_link_libraries(${TARGET_NAME} PRIVATE SDL2_mixer::SDL2_mixer-static) + elseif(TARGET SDL2_mixer::SDL2_mixer) + target_link_libraries(${TARGET_NAME} PRIVATE SDL2_mixer::SDL2_mixer) + endif() + if(KEEPERFX_NETWORKING) + if(TARGET SDL2_net::SDL2_net-static) + target_link_libraries(${TARGET_NAME} PRIVATE SDL2_net::SDL2_net-static) + elseif(TARGET SDL2_net::SDL2_net) + target_link_libraries(${TARGET_NAME} PRIVATE SDL2_net::SDL2_net) + endif() + endif() +endmacro() +kfx_link_sdl2_target(keeperfx) + +add_executable(keeperfx_hvlog ${KEEPERFX_SOURCES_C} ${KEEPERFX_SOURCES_CXX}) +target_include_directories(keeperfx_hvlog PRIVATE src deps/centitoml deps/centijson/include) +target_compile_definitions(keeperfx_hvlog PUBLIC BFDEBUG_LEVEL=10) +if(WIN32) + target_sources(keeperfx_hvlog PRIVATE "res/keeperfx_stdres.rc") +endif() +apply_keeperfx_warnings(keeperfx_hvlog) +apply_keeperfx_link_flags(keeperfx_hvlog) +apply_windows_system_libs(keeperfx_hvlog) + +kfx_link_sdl2_target(keeperfx_hvlog) + +# ━━━ Dependent Platform Libraries ━━━ +# Linked AFTER targets are created (see `add_subdirectory(deps)` in root CMakeLists.txt) + +# ━━━ Test Target ━━━ +file(GLOB TEST_SOURCES "tests/*.cpp") +add_library(cunit_static STATIC + "deps/CUnit-2.1-3/CUnit/Sources/Basic/Basic.c" + "deps/CUnit-2.1-3/CUnit/Sources/Framework/TestDB.c" + "deps/CUnit-2.1-3/CUnit/Sources/Framework/CUError.c" + "deps/CUnit-2.1-3/CUnit/Sources/Framework/TestRun.c" + "deps/CUnit-2.1-3/CUnit/Sources/Framework/Util.c" +) +target_include_directories(cunit_static PUBLIC "deps/CUnit-2.1-3/CUnit/Headers") + +add_executable(tests ${TEST_SOURCES} ${KEEPERFX_SOURCES_C} ${KEEPERFX_SOURCES_CXX}) +target_compile_definitions(tests PUBLIC BFDEBUG_LEVEL=0) +target_link_libraries(tests PRIVATE cunit_static) +apply_keeperfx_warnings(tests) +apply_keeperfx_link_flags(tests) +apply_windows_system_libs(tests) + +message(STATUS "Compiler: ${CMAKE_CXX_COMPILER_ID}") diff --git a/build/cmake/modules/Dependencies.cmake b/build/cmake/modules/Dependencies.cmake new file mode 100644 index 0000000000..cb7a7fb19b --- /dev/null +++ b/build/cmake/modules/Dependencies.cmake @@ -0,0 +1,66 @@ +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# Dependencies.cmake — find_package() for all dependencies +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +# ━━━ SDL2 & Graphics ━━━ +# MinGW cross-compile: force static SDL2 libs (no runtime DLLs) +if(MINGW OR CMAKE_CROSSCOMPILING) + set(SDL2_USE_STATIC_LIBS ON) + set(SDL2IMAGE_STATIC ON) + set(SDL2MIXER_STATIC ON) + set(SDL2NET_STATIC ON) +endif() + +find_package(SDL2 CONFIG REQUIRED) +find_package(SDL2_image CONFIG REQUIRED) +find_package(SDL2_mixer CONFIG REQUIRED) +if(KEEPERFX_NETWORKING) + find_package(SDL2_net CONFIG REQUIRED) +endif() + +# ━━━ OpenGL Renderer (optional) ━━━ +if(KEEPERFX_RENDERER_OPENGL) + find_package(glad CONFIG QUIET) + if(glad_FOUND) + kfx_status("DEPS" "OpenGL renderer backend enabled (glad found)") + else() + kfx_status("DEPS" "OpenGL renderer backend disabled (glad not found; install via vcpkg)") + set(KEEPERFX_RENDERER_OPENGL OFF) + endif() +endif() + +# ━━━ Audio & Codecs (vcpkg) ━━━ +find_package(FFmpeg MODULE QUIET) +if(FFmpeg_FOUND) + kfx_status("DEPS" "FFmpeg found (vcpkg)") +else() + kfx_status("DEPS" "FFmpeg not yet in vcpkg — will use fallback from deps/ tarballs") +endif() + +find_package(OpenAL CONFIG QUIET) +if(OpenAL_FOUND OR OPENAL_FOUND) + kfx_status("DEPS" "OpenAL found (vcpkg)") +else() + kfx_status("DEPS" "OpenAL not found — will use fallback from deps/ tarballs") +endif() + +# ━━━ Networking ━━━ +find_package(enet CONFIG QUIET) +if(enet_FOUND) + kfx_status("DEPS" "enet found (vcpkg)") +else() + kfx_status("DEPS" "enet not found via vcpkg — will use fallback from deps/ tarballs") +endif() + +# ━━━ JSON (centijson) ━━━ +find_package(centijson CONFIG QUIET) +if(centijson_FOUND) + kfx_status("DEPS" "centijson found (vcpkg)") +else() + kfx_status("DEPS" "centijson not found via vcpkg — will build from deps/ sources") +endif() + +# ━━━ Global Definitions (all platforms) ━━━ +add_compile_definitions(_CRT_NONSTDC_NO_WARNINGS _CRT_SECURE_NO_WARNINGS) +add_compile_definitions("DEBUG=$,1,0>") +add_compile_definitions("SPNG_STATIC=1") diff --git a/build/cmake/modules/Helpers.cmake b/build/cmake/modules/Helpers.cmake new file mode 100644 index 0000000000..76f2f18c93 --- /dev/null +++ b/build/cmake/modules/Helpers.cmake @@ -0,0 +1,63 @@ +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# Helpers.cmake — Common functions and macros +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +# Log a status message with [PREFIX] for clarity +function(kfx_status PREFIX MESSAGE) + message(STATUS "[${PREFIX}] ${MESSAGE}") +endfunction() + +# Apply common compilation flags to a target based on platform +function(apply_keeperfx_warnings TARGET) + if(MSVC) + # MSVC: use /W3, suppress common cross-platform noise + target_compile_options(${TARGET} PRIVATE + /W3 + /wd4996 # deprecated functions + /wd4267 # size_t conversion + /wd4244 # float/int conversion + /wd4305 # truncation + /wd4018 # signed/unsigned mismatch + /wd4146 # unary minus on unsigned + /wd4101 # unreferenced local variable + ) + return() + endif() + + set(WARNFLAGS -Wall -W -Wshadow -Wno-sign-compare -Wno-unused-parameter -Wno-strict-aliasing -Wno-unknown-pragmas -Werror) + + # Desktop: MinGW or native Linux + set(GNU_COMPILER_FLAG -march=x86-64 -fno-omit-frame-pointer -fmessage-length=0) + target_compile_options(${TARGET} PRIVATE ${WARNFLAGS} ${GNU_COMPILER_FLAG}) +endfunction() + +# Apply common link options to a target based on platform +function(apply_keeperfx_link_flags TARGET) + if(MSVC) + # MSVC: Windows subsystem, no GCC-style flags. + # /MANIFEST:NO disables the auto-generated manifest because keeperfx_stdres.rc + # already embeds the manifest via RT_MANIFEST, and duplicate manifests cause LNK error. + target_link_options(${TARGET} PRIVATE /SUBSYSTEM:WINDOWS /MANIFEST:NO) + return() + endif() + + if(WIN32 OR MINGW) + # MinGW: Windows subsystem + map file + target_link_options(${TARGET} PRIVATE -mwindows -Wl,--enable-auto-import -Wl,-Map,${TARGET}.map) + target_link_libraries(${TARGET} PUBLIC -static stdc++ winpthread -dynamic) + # Use LLVM linker (LLD) for faster linking + set_property(TARGET ${TARGET} PROPERTY LINKER_TYPE LLD) + else() + # Linux: pthreads + map file + target_link_options(${TARGET} PRIVATE -Wl,-Map,${TARGET}.map) + find_package(Threads REQUIRED) + target_link_libraries(${TARGET} PUBLIC Threads::Threads) + endif() +endfunction() + +# Apply system libraries (Windows only: imagehlp, dbghelp, ole32, uuid, winmm, ws2_32) +function(apply_windows_system_libs TARGET) + if(WIN32) + target_link_libraries(${TARGET} PRIVATE imagehlp dbghelp ole32 uuid winmm ws2_32) + endif() +endfunction() diff --git a/build/cmake/modules/Platforms.cmake b/build/cmake/modules/Platforms.cmake new file mode 100644 index 0000000000..3403954a1e --- /dev/null +++ b/build/cmake/modules/Platforms.cmake @@ -0,0 +1,43 @@ +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# Platforms.cmake — Platform detection and build options +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +message(STATUS "Building for desktop platform") + +# Build options +option(KEEPERFX_NETWORKING "Build with multiplayer networking support" ON) +option(KEEPERFX_RENDERER_OPENGL "Enable the OpenGL renderer backend (desktop only)" ON) +option(KFX_DEBUG_MEMORY "Enable KfxAlloc guard zones and per-site tracking" OFF) + +# Apply compile definitions +if(KEEPERFX_NETWORKING) + add_compile_definitions("KEEPERFX_NETWORKING=1") +endif() + +if(KFX_DEBUG_MEMORY) + add_compile_definitions("KFX_DEBUG_MEMORY=1") +endif() + +add_compile_definitions("KEEPERFX_LUA_AVAILABLE=1") +add_compile_definitions("SDL_MIXER_AVAILABLE=1") + +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +# Sanitizers (AddressSanitizer + UndefinedBehaviorSanitizer) +# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +option(KEEPERFX_SANITIZERS "Enable AddressSanitizer (+ UBSan on GCC/Clang)" OFF) +if(KEEPERFX_SANITIZERS) + if(MSVC) + add_compile_options(/fsanitize=address) + # MSVC ASan needs the debug info for useful stack traces + add_compile_options(/Zi) + add_link_options(/DEBUG) + # Disable STL container annotations — pre-built vcpkg libs don't have them, + # causing LNK2038 mismatch errors (annotate_string / annotate_vector) + add_compile_definitions(_DISABLE_STRING_ANNOTATION _DISABLE_VECTOR_ANNOTATION) + kfx_status("SANITIZERS" "MSVC AddressSanitizer enabled (/fsanitize=address)") + else() + add_compile_options(-fsanitize=address,undefined -fno-omit-frame-pointer) + add_link_options(-fsanitize=address,undefined) + kfx_status("SANITIZERS" "GCC/Clang ASan + UBSan enabled") + endif() +endif() diff --git a/build/cmake/toolchains/msvc.cmake b/build/cmake/toolchains/msvc.cmake new file mode 100644 index 0000000000..9d0734de7e --- /dev/null +++ b/build/cmake/toolchains/msvc.cmake @@ -0,0 +1,74 @@ +# MSVC Toolchain Configuration +# Configures CMake to use Microsoft Visual C++ (cl.exe) for Windows native builds. +# Triplets: x86-windows-static, x64-windows-static + +set(CMAKE_SYSTEM_NAME Windows) + +# Compiler Configuration +set(CMAKE_C_COMPILER cl.exe CACHE STRING "C compiler" FORCE) +set(CMAKE_CXX_COMPILER cl.exe CACHE STRING "C++ compiler" FORCE) +set(CMAKE_RC_COMPILER rc.exe CACHE STRING "Resource compiler" FORCE) + +# Force MSVC detection +set(MSVC TRUE CACHE BOOL "Force MSVC detection" FORCE) +set(CMAKE_CXX_COMPILER_ID "MSVC" CACHE STRING "CXX compiler ID" FORCE) +set(CMAKE_C_COMPILER_ID "MSVC" CACHE STRING "C compiler ID" FORCE) + +# Disable compiler checks (assumes MSVC environment already set up) +set(CMAKE_C_COMPILER_FORCED TRUE) +set(CMAKE_CXX_COMPILER_FORCED TRUE) + +# Language Configuration +set(CMAKE_C_STANDARD 11 CACHE STRING "C standard") +set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard") + +# Compiler Flags +# /J: unsigned char by default (GCC compatibility); matches MinGW behavior +# /fp:precise: Floating point model (default, but explicit) +# /W4: Warning level 4 (most rigorous) +# /WX: Treat warnings as errors (matches MinGW -Werror behavior, can be relaxed) + +# /std:clatest: Enable latest C standard preview (C23) — required for typeof keyword +# used in config.h field() macro (offsetof(typeof(expr), member) is a C23 pattern). +set(MSVC_COMMON_FLAGS "/J /fp:precise /W4 /std:clatest") + +# For Release: /O2 (optimize for speed), /Gy (function-level linking) +# For Debug: /Od (disable optimizations), /Zi (generate program database) +string(APPEND CMAKE_C_FLAGS "${MSVC_COMMON_FLAGS}") +string(APPEND CMAKE_CXX_FLAGS "${MSVC_COMMON_FLAGS}") + +string(APPEND CMAKE_C_FLAGS_RELEASE " /O2 /Gy") +string(APPEND CMAKE_CXX_FLAGS_RELEASE " /O2 /Gy") + +string(APPEND CMAKE_C_FLAGS_DEBUG " /Od /Zi /RTC1") +string(APPEND CMAKE_CXX_FLAGS_DEBUG " /Od /Zi /RTC1") + +# C4996: 'function': was declared deprecated +# MSVC often warns about POSIX functions like fopen (prefer fopen_s). +# For compatibility with cross-platform code (GCC doesn't warn), suppress this. +# C4267: 'var': conversion from 'size_t' to 'type', possible loss of data +# Intentionally suppressed for cross-compilation compatibility. +string(APPEND CMAKE_C_FLAGS " /wd4996 /wd4267") +string(APPEND CMAKE_CXX_FLAGS " /wd4996 /wd4267") + +# Runtime Library Linking +# /MT: Multithreaded static runtime (Release) +# /MD: Multithreaded dynamic runtime (Debug with DLL) +# CMake handles most of this automatically via CMAKE_MSVC_RUNTIME_LIBRARY, +# but we can explicitly set it for consistency. +set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + +# Linker Configuration +# /SUBSYSTEM:CONSOLE (default for executables) +# /OPT:REF (remove unreferenced functions) +string(APPEND CMAKE_EXE_LINKER_FLAGS " /OPT:REF") +string(APPEND CMAKE_SHARED_LINKER_FLAGS " /OPT:REF") + +# vcpkg triplet configuration (auto-set by CMakePresets.json, but documented here) +# When using this toolchain with vcpkg, ensure CMakePresets.json sets: +# "cacheVariables": { +# "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/vcpkg/scripts/buildsystems/cmake/vcpkg.cmake", +# "VCPKG_TARGET_TRIPLET": "x86-windows-static" or "x64-windows-static" +# } + +message(STATUS "MSVC Toolchain: cl.exe, C11/C++17, /MT (static runtime), triplet: ${VCPKG_TARGET_TRIPLET}") diff --git a/build/keeperfx.exe.manifest b/build/keeperfx.exe.manifest new file mode 100644 index 0000000000..8014da4984 --- /dev/null +++ b/build/keeperfx.exe.manifest @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + true/pm + permonitorv2,permonitor + + + + diff --git a/build/make/package.mk b/build/make/package.mk new file mode 100644 index 0000000000..04f80f74fe --- /dev/null +++ b/build/make/package.mk @@ -0,0 +1,163 @@ +#****************************************************************************** +# Free implementation of Bullfrog's Dungeon Keeper strategy game. +#****************************************************************************** +# @file package.mk +# A script used by GNU Make to recompile the project. +# @par Purpose: +# Defines make rules for package with release of KeeperFX. +# @par Comment: +# None. +# @author Tomasz Lis +# @date 01 Jul 2011 - 01 Jul 2011 +# @par Copying and copyrights: +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +#****************************************************************************** +empty = +space = $(empty) $(empty) +PKG_NAME = pkg/keeperfx-$(subst $(space),_,$(subst .,_,$(VER_STRING)))-patch.7z +PKG_CAMPAIGN_FILES = \ + $(patsubst %,pkg/campgns/campgn_order.txt,$(CAMPAIGNS)) \ + $(patsubst %,pkg/campgns/%.cfg,$(CAMPAIGNS)) \ + $(patsubst %,pkg/%,$(foreach campaign,$(CAMPAIGNS),$(wildcard campgns/$(campaign)/*.txt))) \ + $(patsubst %,pkg/%,$(foreach campaign,$(CAMPAIGNS),$(wildcard campgns/$(campaign)_crtr/*.cfg))) \ + $(patsubst %,pkg/%,$(foreach campaign,$(CAMPAIGNS),$(wildcard campgns/$(campaign)_lnd/*.txt))) +PKG_CAMPAIGN_DIRS = $(sort $(dir $(PKG_CAMPAIGN_FILES))) +PKG_CREATURE_FILES = $(patsubst config/creatrs/%,pkg/creatrs/%,$(wildcard config/creatrs/*.cfg)) +PKG_FXDATA_FILES = \ + $(patsubst config/fxdata/%,pkg/fxdata/%,$(wildcard config/fxdata/*.cfg)) \ + $(patsubst config/fxdata/%,pkg/fxdata/%,$(wildcard config/fxdata/*.toml)) \ + $(patsubst config/fxdata/%,pkg/fxdata/%,$(wildcard config/fxdata/*.txt)) \ + $(patsubst config/%,pkg/%,$(wildcard config/fxdata/lua/**/*.lua)) \ + pkg/fxdata/lua/init.lua +PKG_FXDATA_DIRS = $(sort $(dir $(PKG_FXDATA_FILES))) +PKG_MOD_FILES := $(patsubst config/%,pkg/%,$(shell find config/mods -type f)) +PKG_MOD_DIRS := $(sort $(dir $(PKG_MOD_FILES))) + +PKG_MAPPACK_FILES = \ + $(patsubst %,pkg/levels/mappck_order.txt,$(MAPPACKS)) \ + $(patsubst %,pkg/levels/%.cfg,$(MAPPACKS)) \ + $(patsubst %,pkg/%,$(foreach mappack,$(MAPPACKS),$(wildcard levels/$(mappack)/*.cfg))) \ + $(patsubst %,pkg/%,$(foreach mappack,$(MAPPACKS),$(filter-out %/readme.txt,$(wildcard levels/$(mappack)/*.txt)))) \ + $(patsubst %,pkg/%,$(foreach mappack,$(MAPPACKS),$(filter-out %/readme.txt,$(wildcard levels/$(mappack)/*.toml)))) \ + $(patsubst %,pkg/%,$(foreach mappack,$(MAPPACKS),$(filter-out %/readme.txt,$(wildcard levels/$(mappack)/*.cfg)))) \ + $(patsubst %,pkg/%,$(foreach mappack,$(MAPPACKS),$(wildcard levels/$(mappack)_crtr/*.cfg))) \ + $(patsubst %,pkg/%,$(foreach mappack,$(MAPPACKS),$(wildcard levels/$(mappack)_cfgs/*.cfg))) \ + $(patsubst %,pkg/%,$(foreach mappack,$(MAPPACKS),$(wildcard levels/$(mappack)_cfgs/*.toml))) +PKG_MAPPACK_DIRS = $(sort $(dir $(PKG_MAPPACK_FILES))) +PKG_BIN = pkg/$(notdir $(BIN)) +PKG_BIN_MAP = $(PKG_BIN:%.exe=%.map) +PKG_HVLOGBIN = pkg/$(notdir $(HVLOGBIN)) +PKG_HVLOGBIN_MAP = $(PKG_HVLOGBIN:%.exe=%.map) +PKG_DOCS = pkg/keeperfx_readme.txt +PKG_DLL = \ + pkg/SDL2_net.dll \ + pkg/SDL2_mixer.dll \ + pkg/SDL2_image.dll \ + pkg/SDL2.dll +PKG_FILES = \ + $(PKG_CAMPAIGN_FILES) \ + $(PKG_CREATURE_FILES) \ + $(PKG_FXDATA_FILES) \ + $(PKG_MOD_FILES) \ + $(PKG_MAPPACK_FILES) \ + $(NGTEXTDATS) \ + $(NCTEXTDATS) \ + $(MPTEXTDATS) \ + pkg/keeperfx.cfg \ + $(PKG_BIN) \ + $(PKG_BIN_MAP) \ + $(PKG_HVLOGBIN) \ + $(PKG_HVLOGBIN_MAP) \ + $(PKG_DOCS) \ + $(PKG_DLL) + +.PHONY: package + +pkg pkg/creatrs pkg/fxdata pkg/campgns pkg/fxdata/lua $(PKG_MAPPACK_DIRS) $(PKG_CAMPAIGN_DIRS) $(PKG_FXDATA_DIRS) $(PKG_MOD_DIRS): + $(MKDIR) $@ + +pkg/fxdata/lua/%.lua: config/fxdata/lua/%.lua + @mkdir -p $(dir $@) + $(CP) $^ $@ + +pkg/fxdata/lua/init.lua: config/fxdata/lua/init.lua | pkg/fxdata/lua + @mkdir -p $(dir $@) + $(CP) $< $@ + +pkg/keeperfx.cfg: config/keeperfx.cfg | pkg + $(CP) $^ $@ + +$(PKG_BIN): $(BIN) | pkg + $(CP) $^ $@ + +$(PKG_HVLOGBIN): $(HVLOGBIN) | pkg + $(CP) $^ $@ + +$(PKG_BIN_MAP): $(BIN) | pkg + $(CP) $(BIN:%.exe=%.map) $@ + +$(PKG_HVLOGBIN_MAP): $(HVLOGBIN) | pkg + $(CP) $(HVLOGBIN:%.exe=%.map) $@ + +pkg/%.txt: docs/%.txt | pkg + $(CP) $^ $@ + +pkg/campgns/%.cfg: campgns/%.cfg | pkg/campgns + $(CP) $^ $@ + +pkg/campgns/%.txt: campgns/%.txt | $(PKG_CAMPAIGN_DIRS) + $(CP) $^ $@ + +pkg/creatrs/%.cfg: config/creatrs/%.cfg | pkg/creatrs + $(CP) $^ $@ + +pkg/fxdata/%.cfg: config/fxdata/%.cfg | pkg/fxdata + $(CP) $^ $@ + +pkg/fxdata/%.toml: config/fxdata/%.toml | pkg/fxdata + $(CP) $^ $@ + +pkg/fxdata/%.txt: config/fxdata/%.txt | pkg/fxdata + $(CP) $^ $@ + +pkg/fxdata/lua/%.lua: config/fxdata/lua/%.lua | pkg/fxdata/lua + $(CP) $^ $@ + +pkg/fxdata/lua/lib/%.lua: config/fxdata/lua/lib/%.lua | pkg/fxdata/lua/lib + $(CP) $^ $@ + +pkg/fxdata/lua/class/%.lua: config/fxdata/lua/class/%.lua | pkg/fxdata/lua/class + $(CP) $^ $@ + +pkg/mods/%: config/mods/% | $(PKG_MOD_DIRS) + $(CP) $< $@ + +pkg/levels/%.cfg: levels/%.cfg | $(PKG_MAPPACK_DIRS) + $(CP) $^ $@ + +pkg/levels/%.txt: levels/%.txt | $(PKG_MAPPACK_DIRS) + $(CP) $^ $@ + +pkg/SDL2_net.dll: sdl/for_final_package/SDL2_net.dll | pkg + $(CP) $^ $@ + +pkg/SDL2_mixer.dll: sdl/for_final_package/SDL2_mixer.dll | pkg + $(CP) $^ $@ + +pkg/SDL2_image.dll: sdl/for_final_package/SDL2_image.dll | pkg + $(CP) $^ $@ + +pkg/SDL2.dll: sdl/for_final_package/SDL2.dll | pkg + $(CP) $^ $@ + +$(PKG_NAME): $(PKG_FILES) | pkg + $(RM) $@ && cd $(dir $(PKG_NAME)) && 7z a $(notdir $(PKG_NAME)) $(patsubst pkg/%,%,$^) >/dev/null + +package: $(PKG_NAME) + +clean-package: + $(RM) -r pkg diff --git a/build/make/pkg_gfx.mk b/build/make/pkg_gfx.mk new file mode 100644 index 0000000000..5551dac638 --- /dev/null +++ b/build/make/pkg_gfx.mk @@ -0,0 +1,399 @@ +#****************************************************************************** +# Free implementation of Bullfrog's Dungeon Keeper strategy game. +#****************************************************************************** +# @file pkg_gfx.mk +# A script used by GNU Make to recompile the project. +# @par Purpose: +# Defines make rules for tools needed to build KeeperFX. +# Most tools can either by compiled from source or downloaded. +# @par Comment: +# None. +# @author Tomasz Lis +# @date 25 Jan 2009 - 02 Jul 2011 +# @par Copying and copyrights: +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +#****************************************************************************** + +LANDVIEWRAWS = \ +$(foreach num,00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21,pkg/campgns/keeporig_lnd/rgmap$(num).raw pkg/campgns/keeporig_lnd/viframe$(num).dat) \ +$(foreach num,00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21,pkg/campgns/ancntkpr_lnd/rgmap$(num).raw pkg/campgns/ancntkpr_lnd/viframe$(num).dat) \ +$(foreach num,00 01 02 03 04 05 06 07 08 09,pkg/campgns/burdnimp_lnd/rgmap$(num).raw pkg/campgns/burdnimp_lnd/viframe$(num).dat) \ +$(foreach num,00 01 02 03 04 05 06 07,pkg/campgns/dzjr06lv_lnd/rgmap$(num).raw pkg/campgns/dzjr06lv_lnd/viframe$(num).dat) \ +$(foreach num,00 01 02 03 04 05 06 07 08 09 10,pkg/campgns/jdkmaps8_lnd/rgmap$(num).raw pkg/campgns/jdkmaps8_lnd/viframe$(num).dat) \ +$(foreach num,00 01 02 03 04 05 06 07 08 09 10 11 12,pkg/campgns/lqizgood_lnd/rgmap$(num).raw pkg/campgns/lqizgood_lnd/viframe$(num).dat) \ +$(foreach num,00 01 02 03 04 05 06 07 08,pkg/campgns/postanck_lnd/rgmap$(num).raw pkg/campgns/postanck_lnd/viframe$(num).dat) \ +$(foreach num,00 01 02 03 04 05 06 07,pkg/campgns/pstunded_lnd/rgmap$(num).raw pkg/campgns/pstunded_lnd/viframe$(num).dat) \ +$(foreach num,00 01 02 03 04 05 06 07,pkg/campgns/twinkprs_lnd/rgmap$(num).raw pkg/campgns/twinkprs_lnd/viframe$(num).dat) \ +$(foreach num,00 01 02 03 04 05 06 07,pkg/campgns/undedkpr_lnd/rgmap$(num).raw pkg/campgns/undedkpr_lnd/viframe$(num).dat) + +LANDVIEWDATTABS = \ +pkg/ldata/lndflag_ens.dat \ +pkg/ldata/netflag_ens.dat \ +pkg/ldata/lndflag_pin.dat \ +pkg/ldata/netflag_pin.dat \ +pkg/ldata/maphand.dat \ +pkg/ldata/netfont.dat + +TOTRUREGFX = \ +pkg/ldata/torture.raw \ +pkg/ldata/door01.dat \ +pkg/ldata/door02.dat \ +pkg/ldata/door03.dat \ +pkg/ldata/door04.dat \ +pkg/ldata/door05.dat \ +pkg/ldata/door06.dat \ +pkg/ldata/door07.dat \ +pkg/ldata/door08.dat \ +pkg/ldata/door09.dat \ +pkg/ldata/fronttor.dat + +FRONTENDGFX = \ +pkg/data/legal32.raw \ +pkg/data/legal64.raw \ +pkg/data/legal-720p-wide.raw \ +pkg/data/legal-1080p-wide.raw \ +pkg/data/startfx32.raw \ +pkg/data/startfx64.raw \ +pkg/data/loading32.raw \ +pkg/data/loading64.raw \ +pkg/data/nocd.raw \ +pkg/ldata/front.raw \ +pkg/ldata/frontft1.dat \ +pkg/ldata/frontft2.dat \ +pkg/ldata/frontft3.dat \ +pkg/ldata/frontft4.dat \ +pkg/ldata/frontbit.dat + +ENGINEGFX = \ +pkg/data/creature.jty \ +pkg/data/frac00.raw \ +pkg/data/frac01.raw \ +pkg/data/frac02.raw \ +pkg/data/frac03.raw \ +pkg/data/frac04.raw \ +pkg/data/frac05.raw \ +pkg/data/frac06.raw \ +pkg/data/frac07.raw \ +pkg/data/frac08.raw \ +pkg/data/gui2-64.dat \ +pkg/data/gui2-32.dat \ +pkg/data/gui1-64.dat \ +pkg/data/gui1-32.dat \ +pkg/data/pointer64.dat \ +pkg/data/font1-64.dat \ +pkg/data/font1-32.dat \ +pkg/data/font2-32.dat \ +pkg/data/font2-64.dat \ +pkg/data/tmapa000.dat \ +pkg/data/tmapa001.dat \ +pkg/data/tmapa002.dat \ +pkg/data/tmapa003.dat \ +pkg/data/tmapa004.dat \ +pkg/data/tmapa005.dat \ +pkg/data/tmapa006.dat \ +pkg/data/tmapa007.dat \ +pkg/data/tmapa008.dat \ +pkg/data/tmapa009.dat \ +pkg/data/tmapa010.dat \ +pkg/data/tmapa011.dat \ +pkg/data/tmapa012.dat \ +pkg/data/tmapa013.dat \ +pkg/data/tmapb000.dat \ +pkg/data/tmapb001.dat \ +pkg/data/tmapb002.dat \ +pkg/data/tmapb003.dat \ +pkg/data/tmapb004.dat \ +pkg/data/tmapb005.dat \ +pkg/data/tmapb006.dat \ +pkg/data/tmapb007.dat \ +pkg/data/tmapb008.dat \ +pkg/data/tmapb009.dat \ +pkg/data/tmapb010.dat \ +pkg/data/tmapb011.dat \ +pkg/data/tmapb012.dat \ +pkg/data/tmapb013.dat \ +pkg/data/swipe01.dat \ +pkg/data/swipe02.dat \ +pkg/data/swipe03.dat \ +pkg/data/swipe04.dat \ +pkg/data/swipe05.dat \ +pkg/data/swipe06.dat \ +pkg/data/swipe07.dat \ +pkg/data/gmap64.raw \ +pkg/data/gmap32.raw \ +pkg/data/gmapbug.dat + +GUIDATTABS = $(LANDVIEWDATTABS) $(TOTRUREDATTABS) $(ENGINEDATTABS) + +.PHONY: pkg-gfx pkg-landviews pkg-menugfx pkg-enginegfx + +pkg-gfx: pkg-landviews pkg-menugfx pkg-enginegfx + +pkg-landviews: $(LANDVIEWRAWS) $(LANDVIEWDATTABS) + +pkg-menugfx: $(TOTRUREGFX) $(FRONTENDGFX) + +pkg-enginegfx: $(ENGINEGFX) + +pkg-landviewtabs: $(LANDVIEWDATTABS) + +# Creation of land view image files for campaigns +define define_campaign_landview_rule +pkg/campgns/$(1)_lnd/rgmap%.pal: gfx/landviews/$(1)_lnd/rgmap%.png gfx/landviews/$(1)_lnd/viframe.png tools/png2bestpal/res/color_tbl_landview.txt $$(PNGTOBSPAL) + -$$(ECHO) 'Building land view palette: $$@' + @$$(MKDIR) $$(@D) + $$(PNGTOBSPAL) -o "$$@" -m "$$(word 3,$$^)" "$$(word 1,$$^)" "$$(word 2,$$^)" + -$$(ECHO) 'Finished building: $$@' + -$$(ECHO) ' ' + +pkg/campgns/$(1)_lnd/rgmap%.raw: gfx/landviews/$(1)_lnd/rgmap%.png pkg/campgns/$(1)_lnd/rgmap%.pal $$(PNGTORAW) $$(RNC) + -$$(ECHO) 'Building land view image: $$@' + $$(PNGTORAW) -o "$$@" -p "$$(word 2,$$^)" -f raw -l 100 "$$<" + -$$(RNC) "$$@" + -$$(ECHO) 'Finished building: $$@' + -$$(ECHO) ' ' + +pkg/campgns/$(1)_lnd/viframe%.dat: gfx/landviews/$(1)_lnd/viframe.png pkg/campgns/$(1)_lnd/rgmap%.pal $$(PNGTORAW) $$(RNC) + -$$(ECHO) 'Building land view frame: $$@' + $$(PNGTORAW) -o "$$@" -p "$$(word 2,$$^)" -f hspr -l 50 "$$<" + -$$(RNC) "$$@" + -$$(ECHO) 'Finished building: $$@' + -$$(ECHO) ' ' + +# mark palette files precious to make sure they're not auto-removed after dependencies are built +.PRECIOUS: pkg/campgns/$(1)_lnd/rgmap%.pal +endef + +$(foreach campaign,$(sort $(CAMPAIGNS)),$(eval $(call define_campaign_landview_rule,$(campaign)))) + +pkg/ldata/torture.pal: gfx/menufx/torturescr/tortr_background.png gfx/menufx/torturescr/tortr_doora_open11.png gfx/menufx/torturescr/tortr_doorb_open11.png gfx/menufx/torturescr/tortr_doorc_open11.png gfx/menufx/torturescr/tortr_doord_open11.png gfx/menufx/torturescr/tortr_doore_open11.png gfx/menufx/torturescr/tortr_doorf_open11.png gfx/menufx/torturescr/tortr_doorg_open11.png gfx/menufx/torturescr/tortr_doorh_open11.png gfx/menufx/torturescr/tortr_doori_open11.png gfx/menufx/torturescr/cursor_horny.png tools/png2bestpal/res/color_tbl_basic.txt $(PNGTOBSPAL) +pkg/data/legal32.pal: gfx/menufx/loading/legal-32.png tools/png2bestpal/res/color_tbl_basic.txt $(PNGTOBSPAL) +pkg/data/legal64.pal: gfx/menufx/loading/legal-64.png tools/png2bestpal/res/color_tbl_basic.txt $(PNGTOBSPAL) +pkg/data/legal-720p-wide.pal: gfx/menufx/loading/legal-720p-wide.png tools/png2bestpal/res/color_tbl_basic.txt $(PNGTOBSPAL) +pkg/data/legal-1080p-wide.pal: gfx/menufx/loading/legal-1080p-wide.png tools/png2bestpal/res/color_tbl_basic.txt $(PNGTOBSPAL) +pkg/data/startfx32.pal: gfx/menufx/loading/startupfx-32.png tools/png2bestpal/res/color_tbl_basic.txt $(PNGTOBSPAL) +pkg/data/startfx64.pal: gfx/menufx/loading/startupfx-64.png tools/png2bestpal/res/color_tbl_basic.txt $(PNGTOBSPAL) +pkg/data/loading32.pal: gfx/menufx/loading/loading-32.png tools/png2bestpal/res/color_tbl_basic.txt $(PNGTOBSPAL) +pkg/data/loading64.pal: gfx/menufx/loading/loading-64.png tools/png2bestpal/res/color_tbl_basic.txt $(PNGTOBSPAL) +pkg/data/nocd.pal: gfx/menufx/loading/nocd-32.png tools/png2bestpal/res/color_tbl_basic.txt $(PNGTOBSPAL) + +pkg/ldata/torture.pal pkg/data/legal32.pal pkg/data/legal64.pal pkg/data/legal-720p-wide.pal pkg/data/legal-1080p-wide.pal pkg/data/startfx32.pal pkg/data/startfx64.pal pkg/data/loading32.pal pkg/data/loading64.pal pkg/data/nocd.pal: + -$(ECHO) 'Building palette: $@' + @$(MKDIR) $(@D) + $(PNGTOBSPAL) -o "$@" -m "$(filter %.txt,$^)" $(filter %.png,$^) + -$(ECHO) 'Finished building: $@' + -$(ECHO) ' ' + +pkg/ldata/front.pal: gfx/palettes/front.pal +pkg/data/palette.dat: gfx/palettes/engine.pal + +pkg/ldata/front.pal pkg/data/palette.dat: + -$(ECHO) 'Building palette: $@' + @$(MKDIR) $(@D) + # Simplified, for now + $(CP) "$<" "$@" + -$(ECHO) 'Finished building: $@' + -$(ECHO) ' ' + +# mark palette files precious to make sure they're not auto-removed after dependencies are built +.PRECIOUS: pkg/ldata/torture.pal pkg/ldata/front.pal pkg/data/palette.dat + +pkg/ldata/lndflag_ens.dat: gfx/landviewdattabs/landview_ensign/filelist_lndflag.txt pkg/campgns/keeporig_lnd/rgmap00.pal $(PNGTORAW) +pkg/ldata/netflag_ens.dat: gfx/landviewdattabs/landview_ensign/filelist_netflag.txt pkg/campgns/keeporig_lnd/rgmap00.pal $(PNGTORAW) +pkg/ldata/lndflag_pin.dat: gfx/landviewdattabs/landview_pinpnt/filelist_lndflag.txt pkg/campgns/keeporig_lnd/rgmap00.pal $(PNGTORAW) +pkg/ldata/netflag_pin.dat: gfx/landviewdattabs/landview_pinpnt/filelist_netflag.txt pkg/campgns/keeporig_lnd/rgmap00.pal $(PNGTORAW) +pkg/ldata/maphand.dat: gfx/landviewdattabs/landview_hand/filelist_maphand.txt pkg/campgns/keeporig_lnd/rgmap00.pal $(PNGTORAW) +pkg/ldata/netfont.dat: gfx/menufx/font_net/filelist_netfont.txt pkg/campgns/keeporig_lnd/rgmap00.pal $(PNGTORAW) + +pkg/ldata/fronttor.dat: gfx/menufx/torturescr/filelist_fronttor.txt pkg/ldata/torture.pal $(PNGTORAW) +pkg/ldata/door01.dat: gfx/menufx/torturescr/filelist_tortr_doora.txt pkg/ldata/torture.pal $(PNGTORAW) +pkg/ldata/door02.dat: gfx/menufx/torturescr/filelist_tortr_doorb.txt pkg/ldata/torture.pal $(PNGTORAW) +pkg/ldata/door03.dat: gfx/menufx/torturescr/filelist_tortr_doorc.txt pkg/ldata/torture.pal $(PNGTORAW) +pkg/ldata/door04.dat: gfx/menufx/torturescr/filelist_tortr_doord.txt pkg/ldata/torture.pal $(PNGTORAW) +pkg/ldata/door05.dat: gfx/menufx/torturescr/filelist_tortr_doore.txt pkg/ldata/torture.pal $(PNGTORAW) +pkg/ldata/door06.dat: gfx/menufx/torturescr/filelist_tortr_doorf.txt pkg/ldata/torture.pal $(PNGTORAW) +pkg/ldata/door07.dat: gfx/menufx/torturescr/filelist_tortr_doorg.txt pkg/ldata/torture.pal $(PNGTORAW) +pkg/ldata/door08.dat: gfx/menufx/torturescr/filelist_tortr_doorh.txt pkg/ldata/torture.pal $(PNGTORAW) +pkg/ldata/door09.dat: gfx/menufx/torturescr/filelist_tortr_doori.txt pkg/ldata/torture.pal $(PNGTORAW) +pkg/ldata/torture.raw: gfx/menufx/torturescr/tortr_background.png pkg/ldata/torture.pal $(PNGTORAW) + +pkg/ldata/front.raw: gfx/menufx/frontend-64/front_background-64.png pkg/ldata/front.pal $(PNGTORAW) +pkg/ldata/frontbit.dat: gfx/menufx/frontend-64/filelist_frontbit.txt pkg/ldata/front.pal $(PNGTORAW) +pkg/ldata/frontft1.dat: gfx/menufx/font_front_hdr_red-64/filelist_frontft1.txt pkg/ldata/front.pal $(PNGTORAW) +pkg/ldata/frontft2.dat: gfx/menufx/font_front_std_red-64/filelist_frontft2.txt pkg/ldata/front.pal $(PNGTORAW) +pkg/ldata/frontft3.dat: gfx/menufx/font_front_std_ylw-64/filelist_frontft3.txt pkg/ldata/front.pal $(PNGTORAW) +pkg/ldata/frontft4.dat: gfx/menufx/font_front_std_dkr-64/filelist_frontft4.txt pkg/ldata/front.pal $(PNGTORAW) + +pkg/data/frac00.raw: gfx/enginefx/textures-32/frac00.png gfx/enginefx/textures-32/fract_bw.pal $(PNGTORAW) +pkg/data/frac01.raw: gfx/enginefx/textures-32/frac01.png gfx/enginefx/textures-32/fract_bw.pal $(PNGTORAW) +pkg/data/frac02.raw: gfx/enginefx/textures-32/frac02.png gfx/enginefx/textures-32/fract_bw.pal $(PNGTORAW) +pkg/data/frac03.raw: gfx/enginefx/textures-32/frac03.png gfx/enginefx/textures-32/fract_bw.pal $(PNGTORAW) +pkg/data/frac04.raw: gfx/enginefx/textures-32/frac04.png gfx/enginefx/textures-32/fract_bw.pal $(PNGTORAW) +pkg/data/frac05.raw: gfx/enginefx/textures-32/frac05.png gfx/enginefx/textures-32/fract_bw.pal $(PNGTORAW) +pkg/data/frac06.raw: gfx/enginefx/textures-32/frac06.png gfx/enginefx/textures-32/fract_bw.pal $(PNGTORAW) +pkg/data/frac07.raw: gfx/enginefx/textures-32/frac07.png gfx/enginefx/textures-32/fract_bw.pal $(PNGTORAW) +pkg/data/frac08.raw: gfx/enginefx/textures-32/frac08.png gfx/enginefx/textures-32/fract_bw.pal $(PNGTORAW) + +pkg/data/tmapa000.dat: gfx/enginefx/textures-32/filelist_tmapa000.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapa001.dat: gfx/enginefx/textures-32/filelist_tmapa001.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapa002.dat: gfx/enginefx/textures-32/filelist_tmapa002.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapa003.dat: gfx/enginefx/textures-32/filelist_tmapa003.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapa004.dat: gfx/enginefx/textures-32/filelist_tmapa004.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapa005.dat: gfx/enginefx/textures-32/filelist_tmapa005.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapa006.dat: gfx/enginefx/textures-32/filelist_tmapa006.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapa007.dat: gfx/enginefx/textures-32/filelist_tmapa007.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapa008.dat: gfx/enginefx/textures-32/filelist_tmapa008.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapa009.dat: gfx/enginefx/textures-32/filelist_tmapa009.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapa010.dat: gfx/enginefx/textures-32/filelist_tmapa010.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapa011.dat: gfx/enginefx/textures-32/filelist_tmapa011.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapa012.dat: gfx/enginefx/textures-32/filelist_tmapa012.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapa013.dat: gfx/enginefx/textures-32/filelist_tmapa013.txt pkg/data/palette.dat $(PNGTORAW) + +pkg/data/tmapb000.dat: gfx/enginefx/textures-32/filelist_tmapb000.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapb001.dat: gfx/enginefx/textures-32/filelist_tmapb001.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapb002.dat: gfx/enginefx/textures-32/filelist_tmapb002.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapb003.dat: gfx/enginefx/textures-32/filelist_tmapb003.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapb004.dat: gfx/enginefx/textures-32/filelist_tmapb004.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapb005.dat: gfx/enginefx/textures-32/filelist_tmapb005.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapb006.dat: gfx/enginefx/textures-32/filelist_tmapb006.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapb007.dat: gfx/enginefx/textures-32/filelist_tmapb007.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapb008.dat: gfx/enginefx/textures-32/filelist_tmapb008.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapb009.dat: gfx/enginefx/textures-32/filelist_tmapb009.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapb010.dat: gfx/enginefx/textures-32/filelist_tmapb010.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapb011.dat: gfx/enginefx/textures-32/filelist_tmapb011.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapb012.dat: gfx/enginefx/textures-32/filelist_tmapb012.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/tmapb013.dat: gfx/enginefx/textures-32/filelist_tmapb013.txt pkg/data/palette.dat $(PNGTORAW) + +pkg/data/gmap32.raw: gfx/enginefx/guimap/gmap-32.png pkg/data/palette.dat $(PNGTORAW) +pkg/data/gmap64.raw: gfx/enginefx/guimap/gmap-64.png pkg/data/palette.dat $(PNGTORAW) +pkg/data/gmapbug.dat: gfx/enginefx/parchmentbug/filelist-gbug.txt pkg/data/palette.dat $(PNGTORAW) + +pkg/data/legal32.raw: gfx/menufx/loading/legal-32.png pkg/data/legal32.pal $(PNGTORAW) +pkg/data/legal64.raw: gfx/menufx/loading/legal-64.png pkg/data/legal64.pal $(PNGTORAW) +pkg/data/legal-720p-wide.raw: gfx/menufx/loading/legal-720p-wide.png pkg/data/legal-720p-wide.pal $(PNGTORAW) +pkg/data/legal-1080p-wide.raw: gfx/menufx/loading/legal-1080p-wide.png pkg/data/legal-1080p-wide.pal $(PNGTORAW) +pkg/data/startfx32.raw: gfx/menufx/loading/startupfx-32.png pkg/data/startfx32.pal $(PNGTORAW) +pkg/data/startfx64.raw: gfx/menufx/loading/startupfx-64.png pkg/data/startfx64.pal $(PNGTORAW) +pkg/data/loading32.raw: gfx/menufx/loading/loading-32.png pkg/data/loading32.pal $(PNGTORAW) +pkg/data/loading64.raw: gfx/menufx/loading/loading-64.png pkg/data/loading64.pal $(PNGTORAW) +pkg/data/nocd.raw: gfx/menufx/loading/nocd-32.png pkg/data/nocd.pal $(PNGTORAW) +pkg/data/gui2-64.dat: gfx/menufx/gui2-64/filelist_gui2.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/gui2-32.dat: gfx/menufx/gui2-32/filelist_gui2.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/gui1-64.dat: gfx/menufx/gui1-64/filelist_gui1.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/gui1-32.dat: gfx/menufx/gui1-32/filelist_gui1.txt pkg/data/palette.dat $(PNGTORAW) + +pkg/data/pointer64.dat: gfx/enginefx/pointer-64/filelist_pointer.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/font1-64.dat: gfx/enginefx/font_simp-64/filelist_font1.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/font1-32.dat: gfx/enginefx/font_simp-32/filelist_font1.txt pkg/data/palette.dat $(PNGTORAW) + +pkg/data/font2-32.dat: gfx/menufx/font2-32/filelist_font2.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/font2-64.dat: gfx/menufx/font2-64/filelist_font2.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/creature.jty: gfx/enginefx/sprites-32/animlist.txt pkg/data/palette.dat $(PNGTORAW) + +pkg/data/swipe01.dat: gfx/enginefx/swipes-32/filelist_bhandrl.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/swipe02.dat: gfx/enginefx/swipes-32/filelist_swordrl.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/swipe03.dat: gfx/enginefx/swipes-32/filelist_scythlr.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/swipe04.dat: gfx/enginefx/swipes-32/filelist_sticklr.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/swipe05.dat: gfx/enginefx/swipes-32/filelist_stickrl.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/swipe06.dat: gfx/enginefx/swipes-32/filelist_clawsrl.txt pkg/data/palette.dat $(PNGTORAW) +pkg/data/swipe07.dat: gfx/enginefx/swipes-32/filelist_teeth.txt pkg/data/palette.dat $(PNGTORAW) + +pkg/data/frac%.raw: + -$(ECHO) 'Building RAW texture: $@' + $(PNGTORAW) -o "$@" -p "$(word 2,$^)" -r 255 -f raw -l 100 "$<" + -$(ECHO) 'Finished building: $@' + -$(ECHO) ' ' + +pkg/data/tmap%.dat: + -$(ECHO) 'Building RAW texture: $@' + $(PNGTORAW) -b -o "$@" -p "$(word 2,$^)" -f raw -l 0 "$<" + -$(ECHO) 'Finished building: $@' + -$(ECHO) ' ' + +define BUILD_RAW_IMAGE_CMD + -$(ECHO) 'Building RAW image: $@' + $(PNGTORAW) -o "$@" -p "$(word 2,$^)" -f raw -l 100 "$<" + -$(ECHO) 'Finished building: $@' + -$(ECHO) ' ' +endef + +pkg/ldata/%.raw: + $(BUILD_RAW_IMAGE_CMD) + +pkg/data/%.raw: + $(BUILD_RAW_IMAGE_CMD) + + +define BUILD_TABULATED_SPRITES_CMD + -$(ECHO) 'Building tabulated sprites: $@' + $(MKDIR) "$(@D)" + $(PNGTORAW) -b -o "$@" -p "$(word 2,$^)" -f sspr -l 0 "$<" + -$(ECHO) 'Finished building: $@' + -$(ECHO) ' ' +endef + +pkg/ldata/%.dat: + $(BUILD_TABULATED_SPRITES_CMD) + +pkg/data/%.dat: + $(BUILD_TABULATED_SPRITES_CMD) + + +define BUILD_JONTY_SPRITES_CMD + -$(ECHO) 'Building jonty sprites: $@' + @$(MKDIR) "$(@D)" + $(PNGTORAW) -m -o "$@" -p "$(word 2,$^)" -f jspr -l 0 "$<" + -$(ECHO) 'Finished building: $@' + -$(ECHO) ' ' +endef + +pkg/creatrs/%.jty: + $(BUILD_JONTY_SPRITES_CMD) + +pkg/data/%.jty: + $(BUILD_JONTY_SPRITES_CMD) + + +# ============================================================================ +# MODULAR ASSET ARCHITECTURE: Submodule-based gfx/ directory +# ============================================================================ +# The gfx/ directory is now a git submodule, not an ephemeral clone. +# To initialize: git submodule update --init --recursive +# Original clone rule commented out below: +# +# gfx/%:: | gfx/LICENSE ; +# gfx/LICENSE: +# git clone --depth=1 https://github.com/dkfans/FXGraphics.git gfx + +# Submodule existence check +gfx/%:: | gfx/.git ; + +gfx/.git: + @echo "ERROR: gfx/ submodule not initialized" + @echo "Run: git submodule update --init --recursive" + @exit 1 + +# The package is extracted only if targets does not exits; the "|" causes file dates to be ignored +# Note that ignoring timestamp means it is possible to have outadated files after a new +# package release, if no targets were modified with the update. +$(foreach campaign,$(sort $(CAMPAIGNS)), gfx/$(campaign)_lnd/%.png) \ +gfx/menufx/loading/%.png gfx/palettes/%.pal \ +gfx/menufx/font2-32/%.txt gfx/menufx/font2-64/%.txt gfx/menufx/font_net/%.txt \ +gfx/menufx/font_front_std_dkr-64/%.txt gfx/menufx/font_front_std_red-64/%.txt gfx/menufx/font_front_std_ylw-64/%.txt \ +gfx/menufx/font_front_hdr_dkr-64/%.txt gfx/menufx/font_front_hdr_red-64/%.txt gfx/menufx/font_front_hdr_ylw-64/%.txt \ +gfx/menufx/frontend-64/%.txt gfx/enginefx/pointer-64/%.txt \ +gfx/menufx/gui1-32/%.txt gfx/menufx/gui1-64/%.txt gfx/menufx/gui1-128/%.txt gfx/menufx/gui1-256/%.txt \ +gfx/menufx/gui2-32/%.txt gfx/menufx/gui2-64/%.txt gfx/menufx/gui2-128/%.txt gfx/menufx/gui2-256/%.txt \ +gfx/landviewdattabs/landview_ensign/%.txt gfx/landviewdattabs/landview_hand/%.txt gfx/landviewdattabs/landview_pinpnt/%.txt \ +gfx/enginefx/font_simp-32/%.txt gfx/enginefx/font_simp-64/%.txt \ +gfx/enginefx/sprites-32/%.txt gfx/enginefx/sprites-64/%.txt gfx/enginefx/sprites-128/%.txt \ +gfx/enginefx/swipes-32/%.txt gfx/enginefx/swipes-64/%.txt gfx/enginefx/swipes-128/%.txt \ +gfx/enginefx/textures-32/%.png gfx/enginefx/textures-64/%.png gfx/enginefx/textures-128/%.png \ +gfx/enginefx/textures-32/%.txt gfx/enginefx/textures-64/%.txt gfx/enginefx/textures-128/%.txt \ +gfx/menufx/torturescr/%.png gfx/menufx/torturescr/%.txt gfx/landviewdattabs/guimap/%.txt gfx/enginefx/parchmentbug/%.txt gfx/creatrportrait/%.txt: gfx + +#****************************************************************************** diff --git a/build/make/pkg_lang.mk b/build/make/pkg_lang.mk new file mode 100644 index 0000000000..637f231a4b --- /dev/null +++ b/build/make/pkg_lang.mk @@ -0,0 +1,232 @@ +#****************************************************************************** +# Free implementation of Bullfrog's Dungeon Keeper strategy game. +#****************************************************************************** +# @file tool_peresec.mk +# A script used by GNU Make to recompile the project. +# @par Purpose: +# Defines make rules for tools needed to build KeeperFX. +# Most tools can either by compiled from source or downloaded. +# @par Comment: +# None. +# @author Tomasz Lis +# @date 25 Jan 2009 - 02 Jul 2011 +# @par Copying and copyrights: +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +#****************************************************************************** +LANGUAGE ?= eng + +NGTEXTDATS = \ +pkg/fxdata/gtext_eng.dat \ +pkg/fxdata/gtext_chi.dat \ +pkg/fxdata/gtext_cht.dat \ +pkg/fxdata/gtext_cze.dat \ +pkg/fxdata/gtext_dut.dat \ +pkg/fxdata/gtext_fre.dat \ +pkg/fxdata/gtext_ger.dat \ +pkg/fxdata/gtext_ita.dat \ +pkg/fxdata/gtext_jpn.dat \ +pkg/fxdata/gtext_kor.dat \ +pkg/fxdata/gtext_lat.dat \ +pkg/fxdata/gtext_pol.dat \ +pkg/fxdata/gtext_rus.dat \ +pkg/fxdata/gtext_spa.dat \ +pkg/fxdata/gtext_swe.dat \ +pkg/fxdata/gtext_ukr.dat \ +pkg/fxdata/gtext_por.dat \ + +NCTEXTDATS = \ +pkg/campgns/ami2019/text_eng.dat \ +pkg/campgns/ami2019/text_chi.dat \ +pkg/campgns/ami2019/text_ger.dat \ +pkg/campgns/ami2019/text_spa.dat \ +pkg/campgns/ancntkpr/text_eng.dat \ +pkg/campgns/ancntkpr/text_chi.dat \ +pkg/campgns/ancntkpr/text_fre.dat \ +pkg/campgns/ancntkpr/text_ger.dat \ +pkg/campgns/ancntkpr/text_pol.dat \ +pkg/campgns/ancntkpr/text_por.dat \ +pkg/campgns/ancntkpr/text_spa.dat \ +pkg/campgns/ancntkpr/text_lat.dat \ +pkg/campgns/burdnimp/text_eng.dat \ +pkg/campgns/burdnimp/text_chi.dat \ +pkg/campgns/burdnimp/text_pol.dat \ +pkg/campgns/burdnimp/text_por.dat \ +pkg/campgns/burdnimp/text_spa.dat \ +pkg/campgns/lqizgood/text_eng.dat \ +pkg/campgns/lqizgood/text_chi.dat \ +pkg/campgns/lqizgood/text_fre.dat \ +pkg/campgns/lqizgood/text_pol.dat \ +pkg/campgns/lqizgood/text_por.dat \ +pkg/campgns/lqizgood/text_ukr.dat \ +pkg/campgns/origplus/text_eng.dat \ +pkg/campgns/origplus/text_chi.dat \ +pkg/campgns/origplus/text_cht.dat \ +pkg/campgns/origplus/text_cze.dat \ +pkg/campgns/origplus/text_dut.dat \ +pkg/campgns/origplus/text_fre.dat \ +pkg/campgns/origplus/text_ger.dat \ +pkg/campgns/origplus/text_ita.dat \ +pkg/campgns/origplus/text_jpn.dat \ +pkg/campgns/origplus/text_kor.dat \ +pkg/campgns/origplus/text_lat.dat \ +pkg/campgns/origplus/text_pol.dat \ +pkg/campgns/origplus/text_por.dat \ +pkg/campgns/origplus/text_rus.dat \ +pkg/campgns/origplus/text_spa.dat \ +pkg/campgns/origplus/text_swe.dat \ +pkg/campgns/origplus/text_ukr.dat \ +pkg/campgns/revlord/text_eng.dat \ +pkg/campgns/revlord/text_chi.dat \ +pkg/campgns/revlord/text_ger.dat \ +pkg/campgns/revlord/text_por.dat \ +pkg/campgns/revlord/text_spa.dat \ +pkg/campgns/twinkprs/text_eng.dat \ +pkg/campgns/twinkprs/text_chi.dat \ +pkg/campgns/twinkprs/text_fre.dat \ +pkg/campgns/twinkprs/text_jpn.dat \ +pkg/campgns/twinkprs/text_pol.dat \ +pkg/campgns/twinkprs/text_por.dat \ +pkg/campgns/twinkprs/text_spa.dat \ +pkg/campgns/twinkprs/text_lat.dat \ +pkg/campgns/undedkpr/text_eng.dat \ +pkg/campgns/undedkpr/text_chi.dat \ +pkg/campgns/undedkpr/text_ger.dat \ +pkg/campgns/undedkpr/text_pol.dat \ +pkg/campgns/undedkpr/text_por.dat \ +pkg/campgns/undedkpr/text_spa.dat + +MPTEXTDATS = \ +pkg/levels/classic/text_eng.dat \ +pkg/levels/classic/text_chi.dat \ +pkg/levels/classic/text_fre.dat \ +pkg/levels/classic/text_ger.dat \ +pkg/levels/classic/text_por.dat \ +pkg/levels/classic/text_spa.dat \ +pkg/levels/classic/text_rus.dat \ +pkg/levels/standard/text_eng.dat \ +pkg/levels/standard/text_chi.dat \ +pkg/levels/standard/text_fre.dat \ +pkg/levels/standard/text_ger.dat \ +pkg/levels/standard/text_por.dat \ +pkg/levels/standard/text_spa.dat \ +pkg/levels/lostlvls/text_eng.dat \ +pkg/levels/lostlvls/text_por.dat \ +pkg/levels/lostlvls/text_chi.dat \ +pkg/levels/lostlvls/text_rus.dat + +EU_CHAR_ENCODING = tools/po2ngdat/res/char_encoding_tbl_eu.txt +JP_CHAR_ENCODING = tools/po2ngdat/res/char_encoding_tbl_jp.txt +RU_CHAR_ENCODING = tools/po2ngdat/res/char_encoding_tbl_ru.txt +CH_CHAR_ENCODING = tools/po2ngdat/res/char_encoding_tbl_ch.txt +KR_CHAR_ENCODING = tools/po2ngdat/res/char_encoding_tbl_kr.txt + +.PRECIOUS: $(EU_CHAR_ENCODING) $(JP_CHAR_ENCODING) $(RU_CHAR_ENCODING) $(CH_CHAR_ENCODING) $(KR_CHAR_ENCODING) + +pkg-languages: $(NGTEXTDATS) $(NCTEXTDATS) $(MPTEXTDATS) + +# Creation of Only single language engine language files from PO/POT files (for development) +pkg-lang-single: pkg/fxdata/gtext_$(LANGUAGE).dat + +$(patsubst %/,%,$(sort $(dir $(NCTEXTDATS)))): + $(MKDIR) $@ + +$(patsubst %/,%,$(sort $(dir $(MPTEXTDATS)))): + $(MKDIR) $@ + +# Creation of engine language files from PO/POT files +pkg/fxdata/gtext_jpn.dat: lang/gtext_jpn.po $(POTONGDAT) $(JP_CHAR_ENCODING) | pkg/fxdata + $(POTONGDAT) -o $@ -e $(JP_CHAR_ENCODING) $< >/dev/null + +pkg/fxdata/gtext_rus.dat: lang/gtext_rus.po $(POTONGDAT) $(RU_CHAR_ENCODING) | pkg/fxdata + $(POTONGDAT) -o $@ -e $(RU_CHAR_ENCODING) $< >/dev/null + +pkg/fxdata/gtext_ukr.dat: lang/gtext_ukr.po $(POTONGDAT) $(RU_CHAR_ENCODING) | pkg/fxdata + $(POTONGDAT) -o $@ -e $(RU_CHAR_ENCODING) $< >/dev/null + +pkg/fxdata/gtext_chi.dat: lang/gtext_chi.po $(POTONGDAT) $(CH_CHAR_ENCODING) | pkg/fxdata + $(POTONGDAT) -o $@ -e $(CH_CHAR_ENCODING) $< >/dev/null + +pkg/fxdata/gtext_cht.dat: lang/gtext_cht.po $(POTONGDAT) $(CH_CHAR_ENCODING) | pkg/fxdata + $(POTONGDAT) -o $@ -e $(CH_CHAR_ENCODING) $< >/dev/null + +pkg/fxdata/gtext_kor.dat: lang/gtext_kor.po $(POTONGDAT) $(KR_CHAR_ENCODING) | pkg/fxdata + $(POTONGDAT) -o $@ -e $(KR_CHAR_ENCODING) $< >/dev/null + +pkg/fxdata/gtext_%.dat: lang/gtext_%.po $(POTONGDAT) $(EU_CHAR_ENCODING) | pkg/fxdata + $(POTONGDAT) -o $@ -e $(EU_CHAR_ENCODING) $< >/dev/null + +pkg/fxdata/gtext_%.dat: lang/gtext_%.pot $(POTONGDAT) $(EU_CHAR_ENCODING) | pkg/fxdata + $(POTONGDAT) -o $@ -e $(EU_CHAR_ENCODING) $< >/dev/null + +pkg/%/text_chi.dat : lang/%/text_chi.po $(POTONGDAT) $(CH_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(CH_CHAR_ENCODING) $< >/dev/null + +pkg/%/text_cht.dat : lang/%/text_cht.po $(POTONGDAT) $(CH_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(CH_CHAR_ENCODING) $< >/dev/null + +pkg/%/text_cze.dat: lang/%/text_cze.po $(POTONGDAT) $(EU_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(EU_CHAR_ENCODING) $< >/dev/null + +pkg/%/text_dut.dat: lang/%/text_dut.po $(POTONGDAT) $(EU_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(EU_CHAR_ENCODING) $< >/dev/null + +pkg/%/text_fre.dat: lang/%/text_fre.po $(POTONGDAT) $(EU_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(EU_CHAR_ENCODING) $< >/dev/null + +pkg/%/text_ger.dat: lang/%/text_ger.po $(POTONGDAT) $(EU_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(EU_CHAR_ENCODING) $< >/dev/null + +pkg/%/text_ita.dat: lang/%/text_ita.po $(POTONGDAT) $(EU_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(EU_CHAR_ENCODING) $< >/dev/null + +pkg/%/text_kor.dat: lang/%/text_kor.po $(POTONGDAT) $(KR_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(KR_CHAR_ENCODING) $< >/dev/null + +pkg/%/text_jpn.dat: lang/%/text_jpn.po $(POTONGDAT) $(JP_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(JP_CHAR_ENCODING) $< >/dev/null + +pkg/%/text_lat.dat: lang/%/text_lat.po $(POTONGDAT) $(EU_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(EU_CHAR_ENCODING) $< >/dev/null + +pkg/%/text_pol.dat: lang/%/text_pol.po $(POTONGDAT) $(EU_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(EU_CHAR_ENCODING) $< >/dev/null + +pkg/%/text_por.dat: lang/%/text_por.po $(POTONGDAT) $(EU_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(EU_CHAR_ENCODING) $< >/dev/null + +pkg/%/text_rus.dat: lang/%/text_rus.po $(POTONGDAT) $(RU_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(RU_CHAR_ENCODING) $< >/dev/null + +pkg/%/text_ukr.dat: lang/%/text_ukr.po $(POTONGDAT) $(RU_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(RU_CHAR_ENCODING) $< >/dev/null + +pkg/%/text_spa.dat: lang/%/text_spa.po $(POTONGDAT) $(EU_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(EU_CHAR_ENCODING) $< >/dev/null + +pkg/%/text_swe.dat: lang/%/text_swe.po $(POTONGDAT) $(EU_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(EU_CHAR_ENCODING) $< >/dev/null + +pkg/%/landview_pol.dat: lang/%/landview_pol.po $(POTONGDAT) $(EU_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(EU_CHAR_ENCODING) $< >/dev/null + +pkg/%/landview_dut.dat: lang/%/landview_dut.po $(POTONGDAT) $(EU_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(EU_CHAR_ENCODING) $< >/dev/null + +pkg/%/landview_fre.dat: lang/%/landview_fre.po $(POTONGDAT) $(EU_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(EU_CHAR_ENCODING) $< >/dev/null + +pkg/%/landview_kor.dat: lang/%/landview_kor.po $(POTONGDAT) $(KR_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(KR_CHAR_ENCODING) $< >/dev/null + +pkg/%/landview_rus.dat: lang/%/landview_rus.po $(POTONGDAT) $(RU_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(RU_CHAR_ENCODING) $< >/dev/null + +pkg/%/text_eng.dat: lang/%/text_eng.pot $(POTONGDAT) $(EU_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(EU_CHAR_ENCODING) $< >/dev/null + +pkg/%/landview_eng.dat: lang/%/landview_eng.pot $(POTONGDAT) $(EU_CHAR_ENCODING) | pkg/% + $(POTONGDAT) -o $@ -e $(EU_CHAR_ENCODING) $< >/dev/null diff --git a/build/make/pkg_sfx.mk b/build/make/pkg_sfx.mk new file mode 100644 index 0000000000..f20a45d7d5 --- /dev/null +++ b/build/make/pkg_sfx.mk @@ -0,0 +1,130 @@ +#****************************************************************************** +# Free implementation of Bullfrog's Dungeon Keeper strategy game. +#****************************************************************************** +# @file pkg_sfx.mk +# A script used by GNU Make to recompile the project. +# @par Purpose: +# Defines make rules for tools needed to build KeeperFX. +# Most tools can either by compiled from source or downloaded. +# @par Comment: +# None. +# @author Tomasz Lis +# @date 25 Jan 2009 - 02 Jul 2011 +# @par Copying and copyrights: +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +#****************************************************************************** + +NGSPEECHBANKS = \ +speech_chi \ +speech_cht \ +speech_dut \ +speech_eng \ +speech_fre \ +speech_ger \ +speech_ita \ +speech_jpn \ +speech_kor \ +speech_lat \ +speech_pol \ +speech_rus \ +speech_spa \ +speech_swe + +NGSOUNDDATS = $(patsubst %,pkg/sound/%.dat,$(NGSPEECHBANKS) sound) + +NGSOUNDLISTS = $(patsubst %,sfx/%/filelist.txt,$(NGSPEECHBANKS) sound) + +LANDVIEWSPEECH = \ +$(foreach lng,eng chi,ancntkpr_$(lng)) \ +$(foreach lng,eng chi,burdnimp_$(lng)) \ +$(foreach lng,eng chi dut,dzjr06lv_$(lng)) \ +$(foreach lng,eng chi,jdkmaps8_$(lng)) \ +$(foreach lng,eng chi cht dut fre ger ita jpn kor pol rus spa swe,keeporig_$(lng)) \ +$(foreach lng,eng chi dut,lqizgood_$(lng)) \ +$(foreach lng,eng chi,postanck_$(lng)) \ +$(foreach lng,eng chi,pstunded_$(lng)) \ +$(foreach lng,eng chi,revlord_$(lng)) \ +$(foreach lng,eng dut,twinkprs_$(lng)) \ +$(foreach lng,eng chi,undedkpr_$(lng)) + +LANDVIEWSPEECHDIRS = $(patsubst %,pkg/campgns/%,$(LANDVIEWSPEECH)) + +.PHONY: pkg-sfx convert-sfx + +pkg-sfx: $(NGSOUNDDATS) $(LANDVIEWSPEECHDIRS) + +pkg/sound/sound.dat: sfx/sound/filelist.txt $(WAVTODAT) +pkg/sound/speech_chi.dat: sfx/speech_chi/filelist.txt $(WAVTODAT) +pkg/sound/speech_cht.dat: sfx/speech_cht/filelist.txt $(WAVTODAT) +pkg/sound/speech_dut.dat: sfx/speech_dut/filelist.txt $(WAVTODAT) +pkg/sound/speech_eng.dat: sfx/speech_eng/filelist.txt $(WAVTODAT) +pkg/sound/speech_fre.dat: sfx/speech_fre/filelist.txt $(WAVTODAT) +pkg/sound/speech_ger.dat: sfx/speech_ger/filelist.txt $(WAVTODAT) +pkg/sound/speech_ita.dat: sfx/speech_ita/filelist.txt $(WAVTODAT) +pkg/sound/speech_jpn.dat: sfx/speech_jpn/filelist.txt $(WAVTODAT) +pkg/sound/speech_kor.dat: sfx/speech_kor/filelist.txt $(WAVTODAT) +pkg/sound/speech_lat.dat: sfx/speech_lat/filelist.txt $(WAVTODAT) +pkg/sound/speech_pol.dat: sfx/speech_pol/filelist.txt $(WAVTODAT) +pkg/sound/speech_rus.dat: sfx/speech_rus/filelist.txt $(WAVTODAT) +pkg/sound/speech_spa.dat: sfx/speech_spa/filelist.txt $(WAVTODAT) +pkg/sound/speech_swe.dat: sfx/speech_swe/filelist.txt $(WAVTODAT) + +pkg/sound/%.dat: + -$(ECHO) 'Building sound bank: $@' + @$(MKDIR) "$(@D)" + $(WAVTODAT) -o "$@" "$<" + -$(ECHO) 'Finished building: $@' + -$(ECHO) ' ' + +# Creation of land view speeches for campaigns +define define_campaign_speeches_rule +pkg/campgns/$(1)_$(2): sfx/campgns/$(1)_$(2)/filelist.txt + -$(ECHO) 'Copying campaign SFX: $$@' + @$(MKDIR) "$$@" + tail -n +2 "$$<" | cut -f1 | xargs -d '\n' -I {} $(CP) "$$(/dev/null + $(MV) "$@.dl" "$@" + -$(ECHO) 'Finished downloading: $@' + -$(ECHO) ' ' + +clean-dkillconv: + -$(RM) tools/dkillconv/bin/* + +deep-clean-dkillconv: + -$(RM) tools/dkillconv/pkg/$(DKILLCONV_PACKAGE) + +else ifneq (,$(findstring .zip,$(DKILLCONV_PACKAGE))) + +# If we have zip prebuild, download and extract it +$(DKILLTOLVL): tools/dkillconv/pkg/$(DKILLCONV_PACKAGE) + -$(ECHO) 'Extracting package: $<' + $(MKDIR) "$(@D)" + cd "$(@D)"; \ + unzip -DD -qo "../../../$<" + -$(ECHO) 'Finished extracting: $<' + -$(ECHO) ' ' + +tools/dkillconv/pkg/$(DKILLCONV_PACKAGE): + -$(ECHO) 'Downloading package: $@' + $(MKDIR) "$(@D)" + curl -L -o "$@.dl" "$(DKILLCONV_DOWNLOAD)" + unzip -qt "$@.dl" + $(MV) "$@.dl" "$@" + -$(ECHO) 'Finished downloading: $@' + -$(ECHO) ' ' + +clean-dkillconv: + -$(RM) tools/dkillconv/bin/* + +deep-clean-dkillconv: + -$(RM) tools/dkillconv/pkg/$(DKILLCONV_PACKAGE) + +else + +$(error Cannot find dkillconv tool source nor prebuild. Get package or source manually.) + +endif + +#****************************************************************************** diff --git a/build/make/tool_png2bestpal.mk b/build/make/tool_png2bestpal.mk new file mode 100644 index 0000000000..0d5776ebe0 --- /dev/null +++ b/build/make/tool_png2bestpal.mk @@ -0,0 +1,112 @@ +#****************************************************************************** +# Free implementation of Bullfrog's Dungeon Keeper strategy game. +#****************************************************************************** +# @file tool_png2bestpal.mk +# A script used by GNU Make to recompile the project. +# @par Purpose: +# Defines make rules for tools needed to build KeeperFX. +# Most tools can either by compiled from source or downloaded. +# @par Comment: +# None. +# @author Tomasz Lis +# @date 25 Jan 2009 - 02 Jul 2011 +# @par Copying and copyrights: +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +#****************************************************************************** + +.PHONY: clean-png2bestpal deep-clean-png2bestpal + +tools: $(PNGTOBSPAL) + +clean-tools: clean-png2bestpal + +deep-clean-tools: deep-clean-png2bestpal + +ifneq (,$(wildcard tools/png2bestpal/src/png2bestpal.cpp)) + +# If we have source code of this tool, compile it +$(PNGTOBSPAL): tools/png2bestpal/src/png2bestpal.cpp + $(MAKE) -C tools/png2bestpal + +clean-png2bestpal: + $(MAKE) -C tools/png2bestpal clean + +else ifneq (,$(findstring .tar.gz,$(PNGTOBSPAL_PACKAGE))) + +# If we have tar gzip prebuild, download and extract it +$(PNGTOBSPAL): tools/png2bestpal/pkg/$(PNGTOBSPAL_PACKAGE) + -$(ECHO) 'Extracting package: $<' + $(MKDIR) "$(@D)" + cd "$(@D)"; \ + tar -zxmUf "../../../$<" --exclude="*color_tbl_*.txt" + -$(ECHO) 'Finished extracting: $<' + -$(ECHO) ' ' + +tools/png2bestpal/res/%.txt: tools/png2bestpal/pkg/$(PNGTOBSPAL_PACKAGE) + -$(ECHO) 'Extracting encoding table: $@' + $(MKDIR) "$(@D)" + cd "$(@D)"; \ + tar -zxmUf "../../../$<" --wildcards "*color_tbl_*.txt" + -$(ECHO) 'Finished extracting: $@' + -$(ECHO) ' ' + +tools/png2bestpal/pkg/$(PNGTOBSPAL_PACKAGE): + -$(ECHO) 'Downloading package: $@' + $(MKDIR) "$(@D)" + curl -L -o "$@.dl" "$(PNGTOBSPAL_DOWNLOAD)" + tar -tzf "$@.dl" >/dev/null + $(MV) "$@.dl" "$@" + -$(ECHO) 'Finished downloading: $@' + -$(ECHO) ' ' + +clean-png2bestpal: + -$(RM) tools/png2bestpal/bin/* + +deep-clean-png2bestpal: + -$(RM) tools/png2bestpal/pkg/$(PNGTOBSPAL_PACKAGE) + +else ifneq (,$(findstring .zip,$(PNGTOBSPAL_PACKAGE))) + +# If we have zip prebuild, download and extract it +$(PNGTOBSPAL): tools/png2bestpal/pkg/$(PNGTOBSPAL_PACKAGE) + -$(ECHO) 'Extracting package: $<' + $(MKDIR) "$(@D)" + cd "$(@D)"; \ + unzip -DD -qo "../../../$<" -x "color_tbl_*.txt" + -$(ECHO) 'Finished extracting: $<' + -$(ECHO) ' ' + +tools/png2bestpal/res/%.txt: tools/png2bestpal/pkg/$(PNGTOBSPAL_PACKAGE) + -$(ECHO) 'Extracting encoding table: $@' + $(MKDIR) "$(@D)" + cd "$(@D)"; \ + unzip -DD -qo "../../../$<" "color_tbl_*.txt" + -$(ECHO) 'Finished extracting: $@' + -$(ECHO) ' ' + +tools/png2bestpal/pkg/$(PNGTOBSPAL_PACKAGE): + -$(ECHO) 'Downloading package: $@' + $(MKDIR) "$(@D)" + curl -L -o "$@.dl" "$(PNGTOBSPAL_DOWNLOAD)" + unzip -qt "$@.dl" + $(MV) "$@.dl" "$@" + -$(ECHO) 'Finished downloading: $@' + -$(ECHO) ' ' + +clean-png2bestpal: + -$(RM) tools/png2bestpal/bin/* + +deep-clean-png2bestpal: + -$(RM) tools/png2bestpal/pkg/$(PNGTOBSPAL_PACKAGE) + +else + +$(error Cannot find png2bestpal tool source nor prebuild. Get package or source manually.) + +endif + +#****************************************************************************** diff --git a/build/make/tool_png2ico.mk b/build/make/tool_png2ico.mk new file mode 100644 index 0000000000..9d9c484b77 --- /dev/null +++ b/build/make/tool_png2ico.mk @@ -0,0 +1,96 @@ +#****************************************************************************** +# Free implementation of Bullfrog's Dungeon Keeper strategy game. +#****************************************************************************** +# @file tool_png2ico.mk +# A script used by GNU Make to recompile the project. +# @par Purpose: +# Defines make rules for tools needed to build KeeperFX. +# Most tools can either by compiled from source or downloaded. +# @par Comment: +# None. +# @author Tomasz Lis +# @date 25 Jan 2009 - 02 Jul 2011 +# @par Copying and copyrights: +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +#****************************************************************************** + +.PHONY: clean-png2ico deep-clean-png2ico + +tools: $(PNGTOICO) + +clean-tools: clean-png2ico + +deep-clean-tools: deep-clean-png2ico + +ifneq (,$(wildcard tools/png2ico/png2ico.cpp)) + +# If we have source code of this tool, compile it +$(PNGTOICO): tools/png2ico/png2ico.cpp + $(MAKE) -C tools/png2ico + +clean-png2ico: + $(MAKE) -C tools/png2ico clean + +else ifneq (,$(findstring .tar.gz,$(PNGTOICO_PACKAGE))) + +# If we have tar gzip prebuild, download and extract it +$(PNGTOICO): tools/png2ico/$(PNGTOICO_PACKAGE) + -$(ECHO) 'Extracting package: $<' + $(MKDIR) "$(@D)" + cd "$(@D)"; \ + tar -zxmf "../../$<" + -$(ECHO) 'Finished extracting: $<' + -$(ECHO) ' ' + +tools/png2ico/$(PNGTOICO_PACKAGE): + -$(ECHO) 'Downloading package: $@' + $(MKDIR) "$(@D)" + curl -L -o "$@.dl" "$(PNGTOICO_DOWNLOAD)" + tar -tzf "$@.dl" >/dev/null + $(MV) "$@.dl" "$@" + -$(ECHO) 'Finished downloading: $@' + -$(ECHO) ' ' + +clean-png2ico: + -$(RM) $(PNGTOICO) tools/png2ico/README tools/png2ico/VERSION tools/png2ico/LICENSE tools/png2ico/doc/png2ico.txt + +deep-clean-png2ico: + -$(RM) tools/png2ico/$(PNGTOICO_PACKAGE) + +else ifneq (,$(findstring .zip,$(PNGTOICO_PACKAGE))) + +# If we have zip prebuild, download and extract it +$(PNGTOICO): tools/png2ico/$(PNGTOICO_PACKAGE) + -$(ECHO) 'Extracting package: $<' + $(MKDIR) "$(@D)" + cd "$(@D)"; \ + unzip -DD -qo "../../$<" + -$(ECHO) 'Finished extracting: $<' + -$(ECHO) ' ' + +tools/png2ico/$(PNGTOICO_PACKAGE): + -$(ECHO) 'Downloading package: $@' + $(MKDIR) "$(@D)" + curl -L -o "$@.dl" "$(PNGTOICO_DOWNLOAD)" + unzip -qt "$@.dl" + $(MV) "$@.dl" "$@" + -$(ECHO) 'Finished downloading: $@' + -$(ECHO) ' ' + +clean-png2ico: + -$(RM) $(PNGTOICO) tools/png2ico/README tools/png2ico/VERSION tools/png2ico/LICENSE tools/png2ico/doc/png2ico.txt + +deep-clean-png2ico: + -$(RM) tools/png2ico/$(PNGTOICO_PACKAGE) + +else + +$(error Cannot find png2ico tool source nor prebuild. Get package or source manually.) + +endif + +#****************************************************************************** diff --git a/build/make/tool_pngpal2raw.mk b/build/make/tool_pngpal2raw.mk new file mode 100644 index 0000000000..1ad9a07e29 --- /dev/null +++ b/build/make/tool_pngpal2raw.mk @@ -0,0 +1,96 @@ +#****************************************************************************** +# Free implementation of Bullfrog's Dungeon Keeper strategy game. +#****************************************************************************** +# @file tool_pngpal2raw.mk +# A script used by GNU Make to recompile the project. +# @par Purpose: +# Defines make rules for tools needed to build KeeperFX. +# Most tools can either by compiled from source or downloaded. +# @par Comment: +# None. +# @author Tomasz Lis +# @date 25 Jan 2009 - 02 Jul 2011 +# @par Copying and copyrights: +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +#****************************************************************************** + +.PHONY: clean-pngpal2raw deep-clean-pngpal2raw + +tools: $(PNGTORAW) + +clean-tools: clean-pngpal2raw + +deep-clean-tools: deep-clean-pngpal2raw + +ifneq (,$(wildcard tools/pngpal2raw/src/pngpal2raw.cpp)) + +# If we have source code of this tool, compile it +$(PNGTORAW): tools/pngpal2raw/src/pngpal2raw.cpp + $(MAKE) -C tools/pngpal2raw + +clean-pngpal2raw: + $(MAKE) -C tools/pngpal2raw clean + +else ifneq (,$(findstring .tar.gz,$(PNGTORAW_PACKAGE))) + +# If we have tar gzip prebuild, download and extract it +$(PNGTORAW): tools/pngpal2raw/pkg/$(PNGTORAW_PACKAGE) + -$(ECHO) 'Extracting package: $<' + $(MKDIR) "$(@D)" + cd "$(@D)"; \ + tar -zxmUf "../../../$<" + -$(ECHO) 'Finished extracting: $<' + -$(ECHO) ' ' + +tools/pngpal2raw/pkg/$(PNGTORAW_PACKAGE): + -$(ECHO) 'Downloading package: $@' + $(MKDIR) "$(@D)" + curl -L -o "$@.dl" "$(PNGTORAW_DOWNLOAD)" + tar -tzf "$@.dl" >/dev/null + $(MV) "$@.dl" "$@" + -$(ECHO) 'Finished downloading: $@' + -$(ECHO) ' ' + +clean-pngpal2raw: + -$(RM) tools/pngpal2raw/bin/* + +deep-clean-pngpal2raw: + -$(RM) tools/pngpal2raw/pkg/$(PNGTORAW_PACKAGE) + +else ifneq (,$(findstring .zip,$(PNGTORAW_PACKAGE))) + +# If we have zip prebuild, download and extract it +$(PNGTORAW): tools/pngpal2raw/pkg/$(PNGTORAW_PACKAGE) + -$(ECHO) 'Extracting package: $<' + $(MKDIR) "$(@D)" + cd "$(@D)"; \ + unzip -DD -qo "../../../$<" + -$(ECHO) 'Finished extracting: $<' + -$(ECHO) ' ' + +tools/pngpal2raw/pkg/$(PNGTORAW_PACKAGE): + -$(ECHO) 'Downloading package: $@' + $(MKDIR) "$(@D)" + curl -L -o "$@.dl" "$(PNGTORAW_DOWNLOAD)" + unzip -qt "$@.dl" + $(MV) "$@.dl" "$@" + -$(ECHO) 'Finished downloading: $@' + -$(ECHO) ' ' + +clean-pngpal2raw: + -$(RM) tools/pngpal2raw/bin/* + +deep-clean-pngpal2raw: + -$(RM) tools/pngpal2raw/pkg/$(PNGTORAW_PACKAGE) + +else + +$(error Cannot find pngpal2raw tool source nor prebuild. Get package or source manually.) + +endif + +#****************************************************************************** diff --git a/build/make/tool_po2ngdat.mk b/build/make/tool_po2ngdat.mk new file mode 100644 index 0000000000..fba890752a --- /dev/null +++ b/build/make/tool_po2ngdat.mk @@ -0,0 +1,110 @@ +#****************************************************************************** +# Free implementation of Bullfrog's Dungeon Keeper strategy game. +#****************************************************************************** +# @file tool_po2ngdat.mk +# A script used by GNU Make to recompile the project. +# @par Purpose: +# Defines make rules for tools needed to build KeeperFX. +# Most tools can either by compiled from source or downloaded. +# @par Comment: +# None. +# @author Tomasz Lis +# @date 25 Jan 2009 - 02 Jul 2011 +# @par Copying and copyrights: +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +#****************************************************************************** + +.PHONY: clean-po2ngdat deep-clean-po2ngdat + +tools: $(POTONGDAT) + +clean-tools: clean-po2ngdat + +deep-clean-tools: deep-clean-po2ngdat + +ifneq (,$(wildcard tools/po2ngdat/src/po2ngdat.cpp)) + +# If we have source code of this tool, compile it +$(POTONGDAT): tools/po2ngdat/src/po2ngdat.cpp + $(MAKE) -C tools/po2ngdat + +clean-po2ngdat: + $(MAKE) -C tools/po2ngdat clean + +else ifneq (,$(findstring .tar.gz,$(POTONGDAT_PACKAGE))) + +# If we have tar gzip prebuild, download and extract it +$(POTONGDAT): tools/po2ngdat/pkg/$(POTONGDAT_PACKAGE) + -$(ECHO) 'Extracting package: $<' + $(MKDIR) "$(@D)" + cd "$(@D)"; \ + tar -zxmUf "../../../$<" --exclude="*char_encoding_*.txt" + -$(ECHO) 'Finished extracting: $<' + -$(ECHO) ' ' + +tools/po2ngdat/res: + $(MKDIR) $@ + +tools/po2ngdat/res/char_encoding_tbl_%.txt: tools/po2ngdat/pkg/$(POTONGDAT_PACKAGE) | tools/po2ngdat/res + tar xzmf $< -C $(@D) ./$(@F) + +tools/po2ngdat/pkg/$(POTONGDAT_PACKAGE): + -$(ECHO) 'Downloading package: $@' + $(MKDIR) "$(@D)" + curl -L -o "$@.dl" "$(POTONGDAT_DOWNLOAD)" + tar -tzf "$@.dl" >/dev/null + $(MV) "$@.dl" "$@" + -$(ECHO) 'Finished downloading: $@' + -$(ECHO) ' ' + +clean-po2ngdat: + -$(RM) tools/po2ngdat/bin/* + +deep-clean-po2ngdat: + -$(RM) tools/po2ngdat/pkg/$(POTONGDAT_PACKAGE) + +else ifneq (,$(findstring .zip,$(POTONGDAT_PACKAGE))) + +# If we have zip prebuild, download and extract it +$(POTONGDAT): tools/po2ngdat/pkg/$(POTONGDAT_PACKAGE) + -$(ECHO) 'Extracting package: $<' + $(MKDIR) "$(@D)" + cd "$(@D)"; \ + unzip -DD -qo "../../../$<" -x "char_encoding_*.txt" + -$(ECHO) 'Finished extracting: $<' + -$(ECHO) ' ' + +tools/po2ngdat/res/%.txt: tools/po2ngdat/pkg/$(POTONGDAT_PACKAGE) + -$(ECHO) 'Extracting encoding table: $@' + $(MKDIR) "$(@D)" + cd "$(@D)"; \ + unzip -DD -qo "../../../$<" "char_encoding_*.txt" + -$(ECHO) 'Finished extracting: $@' + -$(ECHO) ' ' + +tools/po2ngdat/pkg/$(POTONGDAT_PACKAGE): + -$(ECHO) 'Downloading package: $@' + $(MKDIR) "$(@D)" + curl -L -o "$@.dl" "$(POTONGDAT_DOWNLOAD)" + unzip -qt "$@.dl" + $(MV) "$@.dl" "$@" + -$(ECHO) 'Finished downloading: $@' + -$(ECHO) ' ' + +clean-po2ngdat: + -$(RM) tools/po2ngdat/bin/* + +deep-clean-po2ngdat: + -$(RM) tools/po2ngdat/pkg/$(POTONGDAT_PACKAGE) + +else + +$(error Cannot find po2ngdat tool source nor prebuild. Get package or source manually.) + +endif + +#****************************************************************************** diff --git a/build/make/tool_rnctools.mk b/build/make/tool_rnctools.mk new file mode 100644 index 0000000000..2e3ef8bc8c --- /dev/null +++ b/build/make/tool_rnctools.mk @@ -0,0 +1,96 @@ +#****************************************************************************** +# Free implementation of Bullfrog's Dungeon Keeper strategy game. +#****************************************************************************** +# @file tool_rnctools.mk +# A script used by GNU Make to recompile the project. +# @par Purpose: +# Defines make rules for tools needed to build KeeperFX. +# Most tools can either by compiled from source or downloaded. +# @par Comment: +# None. +# @author Tomasz Lis +# @date 25 Jan 2009 - 02 Jul 2011 +# @par Copying and copyrights: +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +#****************************************************************************** + +.PHONY: clean-rnctools deep-clean-rnctools + +tools: $(RNC) $(DERNC) + +clean-tools: clean-rnctools + +deep-clean-tools: deep-clean-rnctools + +ifneq (,$(wildcard tools/rnctools/src/dernc.c)) + +# If we have source code of this tool, compile it +$(RNC) $(DERNC): tools/rnctools/src/rnc.c tools/rnctools/src/dernc.c + $(MAKE) -C tools/rnctools + +clean-rnctools: + $(MAKE) -C tools/rnctools clean + +else ifneq (,$(findstring .tar.gz,$(RNCTOOLS_PACKAGE))) + +# If we have tar gzip prebuild, download and extract it +$(RNC) $(DERNC): tools/rnctools/pkg/$(RNCTOOLS_PACKAGE) + -$(ECHO) 'Extracting package: $<' + $(MKDIR) "$(@D)" + cd "$(@D)"; \ + tar -zxmUf "../../../$<" + -$(ECHO) 'Finished extracting: $<' + -$(ECHO) ' ' + +tools/rnctools/pkg/$(RNCTOOLS_PACKAGE): + -$(ECHO) 'Downloading package: $@' + $(MKDIR) "$(@D)" + curl -L -o "$@.dl" "$(RNCTOOLS_DOWNLOAD)" + tar -tzf "$@.dl" >/dev/null + $(MV) "$@.dl" "$@" + -$(ECHO) 'Finished downloading: $@' + -$(ECHO) ' ' + +clean-rnctools: + -$(RM) tools/rnctools/bin/* + +deep-clean-rnctools: + -$(RM) tools/rnctools/pkg/$(RNCTOOLS_PACKAGE) + +else ifneq (,$(findstring .zip,$(RNCTOOLS_PACKAGE))) + +# If we have zip prebuild, download and extract it +$(RNC) $(DERNC): tools/rnctools/pkg/$(RNCTOOLS_PACKAGE) + -$(ECHO) 'Extracting package: $<' + $(MKDIR) "$(@D)" + cd "$(@D)"; \ + unzip -DD -qo "../../../$<" + -$(ECHO) 'Finished extracting: $<' + -$(ECHO) ' ' + +tools/rnctools/pkg/$(RNCTOOLS_PACKAGE): + -$(ECHO) 'Downloading package: $@' + $(MKDIR) "$(@D)" + curl -L -o "$@.dl" "$(RNCTOOLS_DOWNLOAD)" + unzip -qt "$@.dl" + $(MV) "$@.dl" "$@" + -$(ECHO) 'Finished downloading: $@' + -$(ECHO) ' ' + +clean-rnctools: + -$(RM) tools/rnctools/bin/* + +deep-clean-rnctools: + -$(RM) tools/rnctools/pkg/$(RNCTOOLS_PACKAGE) + +else + +$(error Cannot find rnctools tool source nor prebuild. Get package or source manually.) + +endif + +#****************************************************************************** diff --git a/build/make/tool_sndbanker.mk b/build/make/tool_sndbanker.mk new file mode 100644 index 0000000000..ef9dbbbd0d --- /dev/null +++ b/build/make/tool_sndbanker.mk @@ -0,0 +1,96 @@ +#****************************************************************************** +# Free implementation of Bullfrog's Dungeon Keeper strategy game. +#****************************************************************************** +# @file tool_sndbanker.mk +# A script used by GNU Make to recompile the project. +# @par Purpose: +# Defines make rules for tools needed to build KeeperFX. +# Most tools can either by compiled from source or downloaded. +# @par Comment: +# None. +# @author Tomasz Lis +# @date 25 Jan 2009 - 02 Jul 2011 +# @par Copying and copyrights: +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +#****************************************************************************** + +.PHONY: clean-sndbanker deep-clean-sndbanker + +tools: $(WAVTODAT) + +clean-tools: clean-sndbanker + +deep-clean-tools: deep-clean-sndbanker + +ifneq (,$(wildcard tools/sndbanker/src/sndbanker.cpp)) + +# If we have source code of this tool, compile it +$(WAVTODAT): tools/sndbanker/src/sndbanker.cpp + $(MAKE) -C tools/sndbanker + +clean-sndbanker: + $(MAKE) -C tools/sndbanker clean + +else ifneq (,$(findstring .tar.gz,$(SNDBANKER_PACKAGE))) + +# If we have tar gzip prebuild, download and extract it +$(WAVTODAT): tools/sndbanker/pkg/$(SNDBANKER_PACKAGE) + -$(ECHO) 'Extracting package: $<' + $(MKDIR) "$(@D)" + cd "$(@D)"; \ + tar -zxmUf "../../../$<" + -$(ECHO) 'Finished extracting: $<' + -$(ECHO) ' ' + +tools/sndbanker/pkg/$(SNDBANKER_PACKAGE): + -$(ECHO) 'Downloading package: $@' + $(MKDIR) "$(@D)" + curl -L -o "$@.dl" "$(SNDBANKER_DOWNLOAD)" + tar -tzf "$@.dl" >/dev/null + $(MV) "$@.dl" "$@" + -$(ECHO) 'Finished downloading: $@' + -$(ECHO) ' ' + +clean-sndbanker: + -$(RM) tools/sndbanker/bin/* + +deep-clean-sndbanker: + -$(RM) tools/sndbanker/pkg/$(SNDBANKER_PACKAGE) + +else ifneq (,$(findstring .zip,$(SNDBANKER_PACKAGE))) + +# If we have zip prebuild, download and extract it +$(WAVTODAT): tools/sndbanker/pkg/$(SNDBANKER_PACKAGE) + -$(ECHO) 'Extracting package: $<' + $(MKDIR) "$(@D)" + cd "$(@D)"; \ + unzip -DD -qo "../../../$<" + -$(ECHO) 'Finished extracting: $<' + -$(ECHO) ' ' + +tools/sndbanker/pkg/$(SNDBANKER_PACKAGE): + -$(ECHO) 'Downloading package: $@' + $(MKDIR) "$(@D)" + curl -L -o "$@.dl" "$(SNDBANKER_DOWNLOAD)" + unzip -qt "$@.dl" + $(MV) "$@.dl" "$@" + -$(ECHO) 'Finished downloading: $@' + -$(ECHO) ' ' + +clean-sndbanker: + -$(RM) tools/sndbanker/bin/* + +deep-clean-sndbanker: + -$(RM) tools/sndbanker/pkg/$(SNDBANKER_PACKAGE) + +else + +$(error Cannot find sndbanker tool source nor prebuild. Get package or source manually.) + +endif + +#****************************************************************************** diff --git a/build/make/version.mk b/build/make/version.mk new file mode 100644 index 0000000000..0d53c3fa8b --- /dev/null +++ b/build/make/version.mk @@ -0,0 +1,6 @@ +VER_MAJOR=1 +VER_MINOR=3 +VER_RELEASE=1 +VER_BUILD=0 + +PACKAGE_SUFFIX= \ No newline at end of file diff --git a/build/ver_defs.h.in b/build/ver_defs.h.in new file mode 100644 index 0000000000..f2b30fdcc6 --- /dev/null +++ b/build/ver_defs.h.in @@ -0,0 +1,8 @@ +#define VER_MAJOR ${VER_MAJOR} +#define VER_MINOR ${VER_MINOR} +#define VER_RELEASE ${VER_RELEASE} +#define VER_BUILD ${VER_BUILD} +#define VER_STRING "${VER_STRING}" +#define PACKAGE_SUFFIX "${PACKAGE_SUFFIX}" +#define GIT_REVISION "${GIT_REVISION}" + diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 4f6f3d7fc9..d3a8d6ceed 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -1,127 +1,291 @@ cmake_minimum_required(VERSION 3.20) +function(kfx_resolve_dep_archive archive_name archive_url) + set(archive_dst "${CMAKE_SOURCE_DIR}/deps/${archive_name}") -if( NOT EXISTS ${CMAKE_SOURCE_DIR}/deps/enet ) - file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/enet) - if( NOT EXISTS ${CMAKE_SOURCE_DIR}/deps/enet-mingw32.tar.gz ) - file(DOWNLOAD https://github.com/dkfans/kfx-deps/releases/download/initial/enet-mingw32.tar.gz ${CMAKE_SOURCE_DIR}/deps/enet-mingw32.tar.gz SHOW_PROGRESS) + if(NOT EXISTS "${archive_dst}" AND DEFINED ENV{KFX_DEPS_CACHE} AND NOT "$ENV{KFX_DEPS_CACHE}" STREQUAL "") + set(archive_cache_src "$ENV{KFX_DEPS_CACHE}/${archive_name}") + if(EXISTS "${archive_cache_src}") + message(STATUS "Using cached dependency archive: ${archive_name}") + execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${archive_cache_src}" "${archive_dst}") + endif() endif() - execute_process(COMMAND ${CMAKE_COMMAND} -E tar xzf ${CMAKE_SOURCE_DIR}/deps/enet-mingw32.tar.gz WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/enet) + if(NOT EXISTS "${archive_dst}") + file(DOWNLOAD "${archive_url}" "${archive_dst}" SHOW_PROGRESS) + endif() + + file(SIZE "${archive_dst}" archive_size) + if(archive_size EQUAL 0) + message(FATAL_ERROR "Dependency archive ${archive_name} is empty. URL: ${archive_url}") + endif() +endfunction() + + +if( NOT EXISTS ${CMAKE_SOURCE_DIR}/deps/enet6/lib/libenet6.a ) + # Skip tarball extraction if enet is found via vcpkg (MSVC builds) + if(NOT enet_FOUND) + file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/enet6) + kfx_resolve_dep_archive("enet6-mingw32.tar.gz" "https://github.com/dkfans/kfx-deps/releases/download/20260310/enet6-mingw32.tar.gz") + + execute_process(COMMAND ${CMAKE_COMMAND} -E tar xzf ${CMAKE_SOURCE_DIR}/deps/enet6-mingw32.tar.gz WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/enet6) + endif() endif() -if( NOT EXISTS ${CMAKE_SOURCE_DIR}/deps/zlib ) +if( NOT EXISTS ${CMAKE_SOURCE_DIR}/deps/zlib/libz.a ) file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/zlib) - if( NOT EXISTS ${CMAKE_SOURCE_DIR}/deps/zlib-mingw32.tar.gz ) - file(DOWNLOAD https://github.com/dkfans/kfx-deps/releases/download/initial/zlib-mingw32.tar.gz ${CMAKE_SOURCE_DIR}/deps/zlib-mingw32.tar.gz SHOW_PROGRESS) - endif() + kfx_resolve_dep_archive("zlib-mingw32.tar.gz" "https://github.com/dkfans/kfx-deps/releases/download/initial/zlib-mingw32.tar.gz") execute_process(COMMAND ${CMAKE_COMMAND} -E tar xzf ${CMAKE_SOURCE_DIR}/deps/zlib-mingw32.tar.gz WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/zlib) endif() -if( NOT EXISTS ${CMAKE_SOURCE_DIR}/deps/spng ) +if( NOT EXISTS ${CMAKE_SOURCE_DIR}/deps/spng/libspng.a ) file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/spng) - if( NOT EXISTS ${CMAKE_SOURCE_DIR}/deps/spng-mingw32.tar.gz ) - file(DOWNLOAD https://github.com/dkfans/kfx-deps/releases/download/initial/spng-mingw32.tar.gz ${CMAKE_SOURCE_DIR}/deps/spng-mingw32.tar.gz SHOW_PROGRESS) - endif() + kfx_resolve_dep_archive("spng-mingw32.tar.gz" "https://github.com/dkfans/kfx-deps/releases/download/initial/spng-mingw32.tar.gz") execute_process(COMMAND ${CMAKE_COMMAND} -E tar xzf ${CMAKE_SOURCE_DIR}/deps/spng-mingw32.tar.gz WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/spng) endif() -if( NOT EXISTS ${CMAKE_SOURCE_DIR}/deps/astronomy ) +if( NOT EXISTS ${CMAKE_SOURCE_DIR}/deps/astronomy/libastronomy.a ) file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/astronomy) - if( NOT EXISTS ${CMAKE_SOURCE_DIR}/deps/astronomy-mingw32.tar.gz ) - file(DOWNLOAD https://github.com/dkfans/kfx-deps/releases/download/initial/astronomy-mingw32.tar.gz ${CMAKE_SOURCE_DIR}/deps/astronomy-mingw32.tar.gz SHOW_PROGRESS) - endif() + kfx_resolve_dep_archive("astronomy-mingw32.tar.gz" "https://github.com/dkfans/kfx-deps/releases/download/initial/astronomy-mingw32.tar.gz") execute_process(COMMAND ${CMAKE_COMMAND} -E tar xzf ${CMAKE_SOURCE_DIR}/deps/astronomy-mingw32.tar.gz WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/astronomy) endif() -if( NOT EXISTS ${CMAKE_SOURCE_DIR}/deps/centijson ) - file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/centijson) - if( NOT EXISTS ${CMAKE_SOURCE_DIR}/deps/centijson-mingw32.tar.gz ) - file(DOWNLOAD https://github.com/dkfans/kfx-deps/releases/download/initial/centijson-mingw32.tar.gz ${CMAKE_SOURCE_DIR}/deps/centijson-mingw32.tar.gz SHOW_PROGRESS) +if( NOT EXISTS ${CMAKE_SOURCE_DIR}/deps/centijson/libjson.a ) + # Skip tarball extraction if centijson is found via vcpkg (MSVC builds) + if(NOT centijson_FOUND) + file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/centijson) + kfx_resolve_dep_archive("centijson-mingw32.tar.gz" "https://github.com/dkfans/kfx-deps/releases/download/initial/centijson-mingw32.tar.gz") + + execute_process(COMMAND ${CMAKE_COMMAND} -E tar xzf ${CMAKE_SOURCE_DIR}/deps/centijson-mingw32.tar.gz WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/centijson) + endif() +endif() + +if(NOT EXISTS ${CMAKE_SOURCE_DIR}/deps/ffmpeg/libavcodec/libavcodec.a) + # Skip tarball extraction if FFmpeg is found via vcpkg (MSVC builds) + if(NOT FFmpeg_FOUND) + file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/ffmpeg) + kfx_resolve_dep_archive("ffmpeg-mingw32.tar.gz" "https://github.com/dkfans/kfx-deps/releases/download/initial/ffmpeg-mingw32.tar.gz") + + execute_process(COMMAND ${CMAKE_COMMAND} -E tar xzf ${CMAKE_SOURCE_DIR}/deps/ffmpeg-mingw32.tar.gz WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/ffmpeg) endif() +endif() + +if(NOT EXISTS ${CMAKE_SOURCE_DIR}/deps/luajit/lib/libluajit.a) + file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/luajit) + kfx_resolve_dep_archive("luajit-mingw32.tar.gz" "https://github.com/dkfans/kfx-deps/releases/download/20250418/luajit-mingw32.tar.gz") - execute_process(COMMAND ${CMAKE_COMMAND} -E tar xzf ${CMAKE_SOURCE_DIR}/deps/centijson-mingw32.tar.gz WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/centijson) + execute_process(COMMAND ${CMAKE_COMMAND} -E tar xzf ${CMAKE_SOURCE_DIR}/deps/luajit-mingw32.tar.gz WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/luajit) endif() -if(NOT EXISTS ${CMAKE_SOURCE_DIR}/deps/ffmpeg) - file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/ffmpeg) - if(NOT EXISTS ${CMAKE_SOURCE_DIR}/deps/ffmpeg-mingw32.tar.gz) - file(DOWNLOAD https://github.com/dkfans/kfx-deps/releases/download/initial/ffmpeg-mingw32.tar.gz ${CMAKE_SOURCE_DIR}/deps/ffmpeg-mingw32.tar.gz SHOW_PROGRESS) +if(NOT EXISTS ${CMAKE_SOURCE_DIR}/deps/openal/libOpenAL32.a) + # Skip tarball extraction if OpenAL is found via vcpkg (MSVC builds) + if(NOT OpenAL_FOUND AND NOT OPENAL_FOUND) + file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/openal) + kfx_resolve_dep_archive("openal-mingw32.tar.gz" "https://github.com/dkfans/kfx-deps/releases/download/20260310/openal-mingw32.tar.gz") + + execute_process(COMMAND ${CMAKE_COMMAND} -E tar xzf ${CMAKE_SOURCE_DIR}/deps/openal-mingw32.tar.gz WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/openal) endif() +endif() + +if(NOT EXISTS ${CMAKE_SOURCE_DIR}/deps/miniupnpc/libminiupnpc.a) + file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/miniupnpc) + kfx_resolve_dep_archive("miniupnpc-mingw32.tar.gz" "https://github.com/dkfans/kfx-deps/releases/download/20260102/miniupnpc-mingw32.tar.gz") - execute_process(COMMAND ${CMAKE_COMMAND} -E tar xzf ${CMAKE_SOURCE_DIR}/deps/ffmpeg-mingw32.tar.gz WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/ffmpeg) + execute_process(COMMAND ${CMAKE_COMMAND} -E tar xzf ${CMAKE_SOURCE_DIR}/deps/miniupnpc-mingw32.tar.gz WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/miniupnpc) endif() -## enet -add_library(enet_static STATIC IMPORTED) -set_target_properties(enet_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/enet/libenet.a) -set_target_properties(enet_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/enet/include) -target_link_libraries(enet_static INTERFACE ws2_32 winmm) -target_link_libraries(keeperfx PUBLIC enet_static) -target_link_libraries(keeperfx_hvlog PUBLIC enet_static) +if(NOT EXISTS ${CMAKE_SOURCE_DIR}/deps/libnatpmp/libnatpmp.a) + file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/libnatpmp) + kfx_resolve_dep_archive("libnatpmp-mingw32.tar.gz" "https://github.com/dkfans/kfx-deps/releases/download/20260102/libnatpmp-mingw32.tar.gz") + + execute_process(COMMAND ${CMAKE_COMMAND} -E tar xzf ${CMAKE_SOURCE_DIR}/deps/libnatpmp-mingw32.tar.gz WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/deps/libnatpmp) +endif() + +## enet6 +if(MSVC) + find_package(enet6 CONFIG REQUIRED) + target_link_libraries(keeperfx PUBLIC enet6::enet6) + target_link_libraries(keeperfx_hvlog PUBLIC enet6::enet6) +else() + add_library(enet_static STATIC IMPORTED) + set_target_properties(enet_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/enet6/lib/libenet6.a) + set_target_properties(enet_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/enet6/include) + target_link_libraries(enet_static INTERFACE ws2_32 winmm) + target_link_libraries(keeperfx PUBLIC enet_static) + target_link_libraries(keeperfx_hvlog PUBLIC enet_static) +endif() ## spng -add_library(spng_static STATIC IMPORTED) -set_target_properties(spng_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/spng/libspng.a) -set_target_properties(spng_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/spng/include) -target_link_libraries(keeperfx PUBLIC spng_static) -target_link_libraries(keeperfx_hvlog PUBLIC spng_static) +if(MSVC) + find_package(SPNG CONFIG REQUIRED) + target_link_libraries(keeperfx PUBLIC $,spng::spng,spng::spng_static>) + target_link_libraries(keeperfx_hvlog PUBLIC $,spng::spng,spng::spng_static>) +else() + add_library(spng_static STATIC IMPORTED) + set_target_properties(spng_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/spng/libspng.a) + set_target_properties(spng_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/spng/include) + target_link_libraries(keeperfx PUBLIC spng_static) + target_link_libraries(keeperfx_hvlog PUBLIC spng_static) +endif() ## centijson -add_library(centijson_static STATIC IMPORTED) -set_target_properties(centijson_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/centijson/libjson.a) -set_target_properties(centijson_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/centijson/include) -target_link_libraries(keeperfx PUBLIC centijson_static) -target_link_libraries(keeperfx_hvlog PUBLIC centijson_static) +if(MSVC) + find_package(centijson CONFIG REQUIRED) + target_link_libraries(keeperfx PUBLIC centijson::centijson) + target_link_libraries(keeperfx_hvlog PUBLIC centijson::centijson) +else() + add_library(centijson_static STATIC IMPORTED) + set_target_properties(centijson_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/centijson/libjson.a) + set_target_properties(centijson_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/centijson/include) + target_link_libraries(keeperfx PUBLIC centijson_static) + target_link_libraries(keeperfx_hvlog PUBLIC centijson_static) +endif() ## astronomy. -add_library(astronomy_static STATIC IMPORTED) -set_target_properties(astronomy_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/astronomy/libastronomy.a) -set_target_properties(astronomy_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/astronomy/include) -target_link_libraries(keeperfx PUBLIC astronomy_static) -target_link_libraries(keeperfx_hvlog PUBLIC astronomy_static) +if(MSVC) + find_package(astronomy CONFIG REQUIRED) + target_link_libraries(keeperfx PUBLIC astronomy::astronomy) + target_link_libraries(keeperfx_hvlog PUBLIC astronomy::astronomy) +else() + add_library(astronomy_static STATIC IMPORTED) + set_target_properties(astronomy_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/astronomy/libastronomy.a) + set_target_properties(astronomy_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/astronomy/include) + target_link_libraries(keeperfx PUBLIC astronomy_static) + target_link_libraries(keeperfx_hvlog PUBLIC astronomy_static) +endif() ## zlib -add_library(zlib_static STATIC IMPORTED) -set_target_properties(zlib_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/zlib/libz.a) -set_target_properties(zlib_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/zlib/include) -target_link_libraries(keeperfx PUBLIC zlib_static) -target_link_libraries(keeperfx_hvlog PUBLIC zlib_static) +if(MSVC) + find_package(ZLIB REQUIRED) + target_link_libraries(keeperfx PUBLIC ZLIB::ZLIB) + target_link_libraries(keeperfx_hvlog PUBLIC ZLIB::ZLIB) +else() + add_library(zlib_static STATIC IMPORTED) + set_target_properties(zlib_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/zlib/libz.a) + set_target_properties(zlib_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/zlib/include) + target_link_libraries(keeperfx PUBLIC zlib_static) + target_link_libraries(keeperfx_hvlog PUBLIC zlib_static) +endif() # Add minizip -add_library(minizip_static STATIC IMPORTED) -set_target_properties(minizip_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/zlib/libminizip.a) -set_target_properties(minizip_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/zlib/include) -target_link_libraries(minizip_static INTERFACE zlib_static) -target_link_libraries(keeperfx PUBLIC minizip_static) -target_link_libraries(keeperfx_hvlog PUBLIC minizip_static) +if(MSVC) + find_package(unofficial-minizip CONFIG REQUIRED) + target_link_libraries(keeperfx PUBLIC unofficial::minizip::minizip) + target_link_libraries(keeperfx_hvlog PUBLIC unofficial::minizip::minizip) +else() + add_library(minizip_static STATIC IMPORTED) + set_target_properties(minizip_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/zlib/libminizip.a) + set_target_properties(minizip_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/zlib/include) + target_link_libraries(minizip_static INTERFACE zlib_static) + target_link_libraries(keeperfx PUBLIC minizip_static) + target_link_libraries(keeperfx_hvlog PUBLIC minizip_static) +endif() ## centitoml. add_library(centitoml OBJECT "centitoml/toml_api.c") -target_link_libraries(centitoml PUBLIC centijson_static) +if(MSVC) + target_link_libraries(centitoml PUBLIC centijson::centijson) +else() + target_link_libraries(centitoml PUBLIC centijson_static) +endif() target_include_directories(centitoml INTERFACE "centitoml") target_link_libraries(keeperfx PUBLIC centitoml) target_link_libraries(keeperfx_hvlog PUBLIC centitoml) ## ffmpeg -add_library(libavcodec_static STATIC IMPORTED) -set_target_properties(libavcodec_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/ffmpeg/libavcodec/libavcodec.a) -set_target_properties(libavcodec_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/ffmpeg) +if(MSVC) + find_package(FFMPEG COMPONENTS AVCODEC AVFORMAT AVUTIL SWRESAMPLE REQUIRED) + target_include_directories(keeperfx PUBLIC ${FFMPEG_INCLUDE_DIRS}) + target_include_directories(keeperfx_hvlog PUBLIC ${FFMPEG_INCLUDE_DIRS}) + target_link_directories(keeperfx PUBLIC ${FFMPEG_LIBRARY_DIRS}) + target_link_directories(keeperfx_hvlog PUBLIC ${FFMPEG_LIBRARY_DIRS}) + target_link_libraries(keeperfx PUBLIC ${FFMPEG_LIBRARIES} bcrypt) + target_link_libraries(keeperfx_hvlog PUBLIC ${FFMPEG_LIBRARIES} bcrypt) +else() + add_library(libavcodec_static STATIC IMPORTED) + set_target_properties(libavcodec_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/ffmpeg/libavcodec/libavcodec.a) + set_target_properties(libavcodec_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/ffmpeg) -add_library(libavformat_static STATIC IMPORTED) -set_target_properties(libavformat_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/ffmpeg/libavformat/libavformat.a) -set_target_properties(libavformat_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/ffmpeg) + add_library(libavformat_static STATIC IMPORTED) + set_target_properties(libavformat_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/ffmpeg/libavformat/libavformat.a) + set_target_properties(libavformat_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/ffmpeg) -add_library(libavutil_static STATIC IMPORTED) -set_target_properties(libavutil_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/ffmpeg/libavutil/libavutil.a) -set_target_properties(libavutil_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/ffmpeg) + add_library(libavutil_static STATIC IMPORTED) + set_target_properties(libavutil_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/ffmpeg/libavutil/libavutil.a) + set_target_properties(libavutil_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/ffmpeg) -add_library(libswresample_static STATIC IMPORTED) -set_target_properties(libswresample_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/ffmpeg/libswresample/libswresample.a) -set_target_properties(libswresample_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/ffmpeg) + add_library(libswresample_static STATIC IMPORTED) + set_target_properties(libswresample_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/ffmpeg/libswresample/libswresample.a) + set_target_properties(libswresample_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/ffmpeg) + + target_link_libraries(keeperfx PUBLIC libavformat_static libavcodec_static libswresample_static libavutil_static bcrypt) + target_link_libraries(keeperfx_hvlog PUBLIC libavformat_static libavcodec_static libswresample_static libavutil_static bcrypt) +endif() + +## luajit +if(MSVC) + find_library(LUAJIT_LIB NAMES lua51 REQUIRED) + find_path(LUAJIT_INCLUDE NAMES lua.h PATH_SUFFIXES luajit REQUIRED) + target_link_libraries(keeperfx PUBLIC ${LUAJIT_LIB}) + target_link_libraries(keeperfx_hvlog PUBLIC ${LUAJIT_LIB}) + target_include_directories(keeperfx PUBLIC ${LUAJIT_INCLUDE}) + target_include_directories(keeperfx_hvlog PUBLIC ${LUAJIT_INCLUDE}) +else() + add_library(luajit_static STATIC IMPORTED) + set_target_properties(luajit_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/luajit/lib/libluajit.a) + set_target_properties(luajit_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/luajit/include) + target_link_libraries(keeperfx PUBLIC luajit_static) + target_link_libraries(keeperfx_hvlog PUBLIC luajit_static) +endif() + +## openal +if(MSVC) + find_package(OpenAL CONFIG REQUIRED) + target_link_libraries(keeperfx PUBLIC OpenAL::OpenAL) + target_link_libraries(keeperfx_hvlog PUBLIC OpenAL::OpenAL) +else() + add_library(openal_static STATIC IMPORTED) + set_target_properties(openal_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/openal/libOpenAL32.a) + set_target_properties(openal_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/openal/include) + set_target_properties(openal_static PROPERTIES INTERFACE_COMPILE_DEFINITIONS "AL_LIBTYPE_STATIC=1") + target_link_libraries(openal_static INTERFACE avrt) + target_link_libraries(keeperfx PUBLIC openal_static) + target_link_libraries(keeperfx_hvlog PUBLIC openal_static) +endif() + +## miniupnpc +if(MSVC) + find_package(miniupnpc CONFIG REQUIRED) + target_link_libraries(keeperfx PUBLIC miniupnpc::miniupnpc) + target_link_libraries(keeperfx_hvlog PUBLIC miniupnpc::miniupnpc) +else() + add_library(miniupnpc_static STATIC IMPORTED) + set_target_properties(miniupnpc_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/miniupnpc/libminiupnpc.a) + set_target_properties(miniupnpc_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/miniupnpc/include) + target_link_libraries(keeperfx PUBLIC miniupnpc_static) + target_link_libraries(keeperfx_hvlog PUBLIC miniupnpc_static) +endif() + +## libnatpmp +if(MSVC) + find_package(libnatpmp CONFIG REQUIRED) + target_link_libraries(keeperfx PUBLIC libnatpmp::libnatpmp) + target_link_libraries(keeperfx_hvlog PUBLIC libnatpmp::libnatpmp) +else() + add_library(natpmp_static STATIC IMPORTED) + set_target_properties(natpmp_static PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/libnatpmp/libnatpmp.a) + set_target_properties(natpmp_static PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/libnatpmp/include) + target_link_libraries(natpmp_static INTERFACE iphlpapi) + target_link_libraries(keeperfx PUBLIC natpmp_static) + target_link_libraries(keeperfx_hvlog PUBLIC natpmp_static) +endif() -target_link_libraries(keeperfx PUBLIC bcrypt libavcodec_static libavformat_static libavutil_static libswresample_static) -target_link_libraries(keeperfx_hvlog PUBLIC bcrypt libavcodec_static libavformat_static libavutil_static libswresample_static) +## curl +if(MSVC) + find_package(CURL CONFIG REQUIRED) + target_link_libraries(keeperfx PUBLIC CURL::libcurl) + target_link_libraries(keeperfx_hvlog PUBLIC CURL::libcurl) +endif() \ No newline at end of file diff --git a/external/vcpkg b/external/vcpkg new file mode 160000 index 0000000000..4b77da7fed --- /dev/null +++ b/external/vcpkg @@ -0,0 +1 @@ +Subproject commit 4b77da7fed37817f124936239197833469f1b9a8 diff --git a/src/bflib_basics.h b/src/bflib_basics.h index f61ac2060d..9296f98513 100644 --- a/src/bflib_basics.h +++ b/src/bflib_basics.h @@ -24,6 +24,8 @@ #include #include +#include "compiler_compat.h" + #ifdef __cplusplus extern "C" { #endif @@ -129,43 +131,43 @@ extern char consoleLogArray[MAX_CONSOLE_LOG_COUNT][MAX_TEXT_LENGTH]; extern size_t consoleLogArraySize; // High level functions - DK specific -short warning_dialog(const char *codefile,const int ecode,const char *message) __attribute__ ((nonnull(1, 3))); -short error_dialog(const char *codefile,const int ecode,const char *message) __attribute__ ((nonnull(1, 3))); -short error_dialog_fatal(const char *codefile,const int ecode,const char *message) __attribute__ ((nonnull(1, 3))); -int str_append(char * buffer, int size, const char * str) __attribute__ ((nonnull(1, 3))); -int str_appendf(char * buffer, int size, const char * format, ...) __attribute__ ((format(printf, 3, 4), nonnull(1, 3))); +short warning_dialog(const char *codefile,const int ecode,const char *message) KFX_NONNULL(1, 3); +short error_dialog(const char *codefile,const int ecode,const char *message) KFX_NONNULL(1, 3); +short error_dialog_fatal(const char *codefile,const int ecode,const char *message) KFX_NONNULL(1, 3); +int str_append(char * buffer, int size, const char * str) KFX_NONNULL(1, 3); +int str_appendf(char * buffer, int size, const char * format, ...) KFX_PRINTF_FORMAT(3, 4) KFX_NONNULL(1, 3); /******************************************************************************/ -int LbErrorLog(const char *format, ...) __attribute__ ((format(printf, 1, 2), nonnull(1))); -int LbWarnLog(const char *format, ...) __attribute__ ((format(printf, 1, 2), nonnull(1))); -int LbSyncLog(const char *format, ...) __attribute__ ((format(printf, 1, 2), nonnull(1))); -int LbNetLog(const char *format, ...) __attribute__ ((format(printf, 1, 2), nonnull(1))); -int LbJustLog(const char *format, ...) __attribute__ ((format(printf, 1, 2), nonnull(1))); -int LbNaviLog(const char *format, ...) __attribute__ ((format(printf, 1, 2), nonnull(1))); +int LbErrorLog(const char *format, ...) KFX_PRINTF_FORMAT(1, 2) KFX_NONNULL(1); +int LbWarnLog(const char *format, ...) KFX_PRINTF_FORMAT(1, 2) KFX_NONNULL(1); +int LbSyncLog(const char *format, ...) KFX_PRINTF_FORMAT(1, 2) KFX_NONNULL(1); +int LbNetLog(const char *format, ...) KFX_PRINTF_FORMAT(1, 2) KFX_NONNULL(1); +int LbJustLog(const char *format, ...) KFX_PRINTF_FORMAT(1, 2) KFX_NONNULL(1); +int LbNaviLog(const char *format, ...) KFX_PRINTF_FORMAT(1, 2) KFX_NONNULL(1); #ifdef FUNCTESTING -int LbFTestLog(const char *format, ...) __attribute__ ((format(printf, 1, 2), nonnull(1))); +int LbFTestLog(const char *format, ...) KFX_PRINTF_FORMAT(1, 2) KFX_NONNULL(1); #endif -int LbScriptLog(unsigned long line,const char *format, ...) __attribute__ ((format(printf, 2, 3), nonnull(2))); -int LbConfigLog(unsigned long line,const char *format, ...) __attribute__ ((format(printf, 2, 3), nonnull(2))); +int LbScriptLog(unsigned long line,const char *format, ...) KFX_PRINTF_FORMAT(2, 3) KFX_NONNULL(2); +int LbConfigLog(unsigned long line,const char *format, ...) KFX_PRINTF_FORMAT(2, 3) KFX_NONNULL(2); int LbErrorLogSetup(const char *directory, const char *filename, TbBool flag); int LbErrorLogClose(void); -int LbLogClose(struct TbLog *log) __attribute__ ((nonnull(1))); -int LbLogSetup(struct TbLog *log, const char *filename, ulong flags) __attribute__ ((nonnull(1, 2))); -int LbLogSetPrefix(struct TbLog *log, const char *prefix) __attribute__ ((nonnull(1, 2))); -int LbLogSetPrefixFmt(struct TbLog *log, const char *format, ...) __attribute__ ((format(printf, 2, 3), nonnull(1, 2))); +int LbLogClose(struct TbLog *log) KFX_NONNULL(1); +int LbLogSetup(struct TbLog *log, const char *filename, ulong flags) KFX_NONNULL(1, 2); +int LbLogSetPrefix(struct TbLog *log, const char *prefix) KFX_NONNULL(1, 2); +int LbLogSetPrefixFmt(struct TbLog *log, const char *format, ...) KFX_PRINTF_FORMAT(2, 3) KFX_NONNULL(1, 2); /******************************************************************************/ typedef void (*TbNetworkCallbackFunc)(struct TbNetworkCallbackData *, void *); /******************************************************************************/ -unsigned long llong (unsigned char *p) __attribute__ ((nonnull(1))); -unsigned long lword (unsigned char *p) __attribute__ ((nonnull(1))); +unsigned long llong (unsigned char *p) KFX_NONNULL(1); +unsigned long lword (unsigned char *p) KFX_NONNULL(1); long saturate_set_signed(long long val,unsigned short nbits); unsigned long saturate_set_unsigned(unsigned long long val,unsigned short nbits); -void make_lowercase(char *) __attribute__ ((nonnull(1))); -void make_uppercase(char *) __attribute__ ((nonnull(1))); -int natoi(const char * str, int len) __attribute__ ((nonnull(1))); // like atoi but stops after len bytes +void make_lowercase(char *) KFX_NONNULL(1); +void make_uppercase(char *) KFX_NONNULL(1); +int natoi(const char * str, int len) KFX_NONNULL(1); // like atoi but stops after len bytes /** * Converts an index number to a flag - by creating a bitmask where only the nth bit is set to 1. diff --git a/src/bflib_cpu.c b/src/bflib_cpu.c index 5c7c865809..a6b1ab3f83 100644 --- a/src/bflib_cpu.c +++ b/src/bflib_cpu.c @@ -17,37 +17,50 @@ * (at your option) any later version. */ /******************************************************************************/ + #include "pre_inc.h" #include "bflib_cpu.h" #include "bflib_basics.h" #include "post_inc.h" +#ifdef _MSC_VER +#include +#endif + #ifdef __cplusplus extern "C" { #endif /******************************************************************************/ -/** Issue a single request to CPUID. - * Fits 'intel features', for instance note that even if only "eax" and "edx" - * are of interest, other registers will be modified by the operation, - * so we need to tell the compiler about it. - */ +#ifdef _MSC_VER +/** Issue a single request to CPUID (MSVC). */ +static inline void cpuid(int code, uint32_t *a, uint32_t *d) { + int info[4]; + __cpuid(info, code); + *a = (uint32_t)info[0]; + *d = (uint32_t)info[3]; +} + +/** Issue a complete request, storing general registers output in an array (MSVC). */ +static inline void cpuid_string(int code, void *destination) { + int info[4]; + __cpuid(info, code); + memcpy(destination, info, 16); +} +#else +/** Issue a single request to CPUID. */ static inline void cpuid(int code, uint32_t *a, uint32_t *d) { - #if defined(__i386__) || defined(__x86_64__) asm volatile("cpuid":"=a"(*a),"=d"(*d):"0"(code):"ecx","ebx"); - #endif } -/** Issue a complete request, storing general registers output in an array. - */ +/** Issue a complete request, storing general registers output in an array. */ static inline void cpuid_string(int code, void * destination) { - #if defined(__i386__) || defined(__x86_64__) - uint32_t * where = (uint32_t *) destination; - asm volatile("cpuid":"=a"(*where),"=b"(*(where+1)), - "=c"(*(where+2)),"=d"(*(where+3)):"0"(code)); - #endif + uint32_t * where = (uint32_t *) destination; + asm volatile("cpuid":"=a"(*where),"=b"(*(where+1)), + "=c"(*(where+2)),"=d"(*(where+3)):"0"(code)); } +#endif /******************************************************************************/ void cpu_detect(struct CPU_INFO *cpu) @@ -58,7 +71,6 @@ void cpu_detect(struct CPU_INFO *cpu) cpu->timeStampCounter = 0; cpu->feature_intl = 0; cpu->feature_edx = 0; - #if defined(__i386__) || defined(__x86_64__) { uint32_t where[4]; cpuid_string(CPUID_GETVENDORSTRING, where); @@ -83,7 +95,6 @@ void cpu_detect(struct CPU_INFO *cpu) cpuid_string(CPUID_INTELBRANDSTRINGEND, &cpu->brand[32]); } } - #endif } unsigned char cpu_get_type(struct CPU_INFO *cpu) diff --git a/src/bflib_crash.c b/src/bflib_crash.c index 00545f3dae..1766063bd6 100644 --- a/src/bflib_crash.c +++ b/src/bflib_crash.c @@ -33,7 +33,6 @@ #define WIN32_LEAN_AND_MEAN #include #include -#include #include #include #endif diff --git a/src/bflib_fileio.c b/src/bflib_fileio.c index 03f3bd9771..6947916188 100644 --- a/src/bflib_fileio.c +++ b/src/bflib_fileio.c @@ -30,6 +30,9 @@ #include #include #include +#if defined(_WIN32) +#include +#endif #if !defined(_WIN32) #include #include @@ -145,7 +148,7 @@ int create_directory_for_file(const char * fname) memcpy(tmp, fname, separator - fname); tmp[separator - fname] = 0; #if defined(_WIN32) - if (mkdir(tmp) != 0) { + if (_mkdir(tmp) != 0) { #else if (mkdir(tmp, 0755) != 0) { #endif diff --git a/src/bflib_fmvids.cpp b/src/bflib_fmvids.cpp index cc58370486..b963d72021 100644 --- a/src/bflib_fmvids.cpp +++ b/src/bflib_fmvids.cpp @@ -13,7 +13,9 @@ extern "C" { #include #include #include + #ifdef __GNUC__ #pragma GCC diagnostic warning "-Wdeprecated-declarations" + #endif } #include diff --git a/src/bflib_math.c b/src/bflib_math.c index 2aff3d1bca..f606b278cc 100644 --- a/src/bflib_math.c +++ b/src/bflib_math.c @@ -675,7 +675,7 @@ static long bitScanReverse(long s) { unsigned long source = (unsigned long)s; #if defined(_MSC_VER) - DWORD i; + unsigned long i; uint8_t success = _BitScanReverse(&i, source); return success != 0 ? i : -1; #elif defined(__GNUC__) diff --git a/src/cdrom.cpp b/src/cdrom.cpp index 5664f67b1d..292d34018a 100644 --- a/src/cdrom.cpp +++ b/src/cdrom.cpp @@ -1,3 +1,11 @@ +#ifdef _MSC_VER +// MSVC: include windows.h before project headers to guarantee correct OLE/MSG +// type ordering. Other project headers may pull in windows.h with WIN32_LEAN_AND_MEAN +// which excludes winuser.h/ole types; going first prevents that race. +#include +#include +#endif + #include "pre_inc.h" #include "bflib_sndlib.h" #include "game_legacy.h" diff --git a/src/compiler_compat.h b/src/compiler_compat.h new file mode 100644 index 0000000000..e9dc6fbb5c --- /dev/null +++ b/src/compiler_compat.h @@ -0,0 +1,223 @@ +/** + * ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + * compiler_compat.h — GCC to MSVC attribute compatibility + * ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + * + * Maps GCC-specific function attributes (__attribute__) to MSVC/Clang equivalents + * or provides no-op fallbacks. Allows single-source compatibility across compilers. + * + * Include this header at the top of any .h/.hpp file using __attribute__. + */ + +#ifndef COMPILER_COMPAT_H +#define COMPILER_COMPAT_H + +// ━━━ Compiler Detection ━━━ +#if defined(_MSC_VER) + // MSVC (cl.exe) + #define KFX_COMPILER_MSVC 1 + // MSVC does not support __attribute__ at all — define it away so existing + // code using raw __attribute__((nonnull)), __attribute__((format)) etc. compiles. + #ifndef __attribute__ + #define __attribute__(x) + #endif + // __builtin_offsetof is a GCC extension; map it to standard offsetof(). + // offsetof() is a compile-time constant on MSVC (unlike address arithmetic). + #include + #ifndef __builtin_offsetof + #define __builtin_offsetof(type, member) offsetof(type, member) + #endif +#elif defined(__GNUC__) + // GCC or Clang (defines __GNUC__ for compatibility) + #define KFX_COMPILER_GCC 1 +#else + #define KFX_COMPILER_UNKNOWN 1 +#endif + +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// GCC Attribute Wrappers +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +/** + * KFX_NONNULL(indices...) + * Marks specific parameters as never NULL. GCC warns at compile-time if NULL is passed. + * MSVC doesn't have direct equivalent, but can use _Pragma disable for SAL warnings. + * + * Usage: + * int str_len(const char *str) KFX_NONNULL(1); + * int str_compare(const char *a, const char *b) KFX_NONNULL(1, 2); + */ +#if defined(KFX_COMPILER_GCC) + #define KFX_NONNULL(...) __attribute__((nonnull(__VA_ARGS__))) +#elif defined(KFX_COMPILER_MSVC) + // MSVC: suppress /analyze warnings about potential NULL parameters if desired + // Most code doesn't use /analyze, so nonnull is a no-op here + #define KFX_NONNULL(...) +#else + #define KFX_NONNULL(...) +#endif + +/** + * KFX_PRINTF_FORMAT(fmt_idx, va_idx) + * Validates printf-style format string at index fmt_idx, with varargs starting at va_idx. + * Enables -Wformat warnings in GCC/Clang; MSVC has no direct equivalent. + * + * Usage: + * int my_printf(const char *fmt, ...) KFX_PRINTF_FORMAT(1, 2); + * int my_snprintf(char *buf, int size, const char *fmt, ...) KFX_PRINTF_FORMAT(3, 4); + */ +#if defined(KFX_COMPILER_GCC) + #define KFX_PRINTF_FORMAT(fmt_idx, va_idx) __attribute__((format(printf, fmt_idx, va_idx))) +#elif defined(KFX_COMPILER_MSVC) + // MSVC: no direct equivalent. SAL annotations (e.g., _Printf_format_string_) exist + // but require Windows SDK headers and are less portable. Skip for now. + #define KFX_PRINTF_FORMAT(fmt_idx, va_idx) +#else + #define KFX_PRINTF_FORMAT(fmt_idx, va_idx) +#endif + +/** + * KFX_UNUSED + * Marks a variable/parameter as intentionally unused. Suppresses -Wunused warnings. + * C++17 standardizes this as [[maybe_unused]]; we provide backward compat. + * + * Usage: + * void handler(int event KFX_UNUSED) { } + * KFX_UNUSED int debug_val = some_expensive_computation(); + */ +#if __cplusplus >= 201703L || __STDC_VERSION__ >= 202303L + // C++17 or C23+: use standard attribute + #define KFX_UNUSED [[maybe_unused]] +#elif defined(KFX_COMPILER_GCC) + #define KFX_UNUSED __attribute__((unused)) +#elif defined(KFX_COMPILER_MSVC) + // MSVC: __pragma to suppress C4100 (unreferenced formal parameter) + // Or just leave blank; MSVC warnings for unused params are less noisy than GCC. + #define KFX_UNUSED +#else + #define KFX_UNUSED +#endif + +/** + * KFX_DEPRECATED + * Marks a function/variable as deprecated. Emits warning if used. + * Useful for gradual API migration. + * + * Usage: + * KFX_DEPRECATED int old_api() { return 42; } + */ +#if defined(KFX_COMPILER_GCC) + #define KFX_DEPRECATED __attribute__((deprecated)) +#elif defined(KFX_COMPILER_MSVC) + #define KFX_DEPRECATED __declspec(deprecated) +#else + #define KFX_DEPRECATED +#endif + +/** + * KFX_LIKELY / KFX_UNLIKELY + * Branch prediction hints for performance-critical paths. + * GCC/Clang: __builtin_expect. MSVC: __assume or no-op (optimizer is smart enough). + * + * Usage: + * if (KFX_LIKELY(x > 0)) { } + * if (KFX_UNLIKELY(err)) { } + */ +#if defined(KFX_COMPILER_GCC) + #define KFX_LIKELY(x) __builtin_expect(!!(x), 1) + #define KFX_UNLIKELY(x) __builtin_expect(!!(x), 0) +#else + // MSVC/others: no-op; modern optimizers don't need hints + #define KFX_LIKELY(x) (x) + #define KFX_UNLIKELY(x) (x) +#endif + +/** + * KFX_INLINE / KFX_FORCE_INLINE + * Inlining hints. GCC/Clang: inline/always_inline. MSVC: inline/__forceinline. + * + * Usage: + * KFX_INLINE int min(int a, int b) { return a < b ? a : b; } + * KFX_FORCE_INLINE int fast_path() { } + */ +#if defined(KFX_COMPILER_MSVC) + #define KFX_INLINE inline + #define KFX_FORCE_INLINE __forceinline +#elif defined(KFX_COMPILER_GCC) + #define KFX_INLINE inline + #define KFX_FORCE_INLINE inline __attribute__((always_inline)) +#else + #define KFX_INLINE inline + #define KFX_FORCE_INLINE inline +#endif + +/** + * KFX_NORETURN + * Marks a function that never returns (e.g., exit, abort, infinite loop). + * Helps optimizer and static analysis tools. + * + * Usage: + * KFX_NORETURN void fatal_error(const char *msg); + */ +#if __cplusplus >= 201103L || __STDC_VERSION__ >= 201112L + // C++11 or C11+: use standard _Noreturn (deprecated in C23) or [[noreturn]] + #if __cplusplus >= 201703L + #define KFX_NORETURN [[noreturn]] + #else + #define KFX_NORETURN _Noreturn + #endif +#elif defined(KFX_COMPILER_GCC) + #define KFX_NORETURN __attribute__((noreturn)) +#elif defined(KFX_COMPILER_MSVC) + #define KFX_NORETURN __declspec(noreturn) +#else + #define KFX_NORETURN +#endif + +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +// Common Attribute Combinations +// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +/** + * KFX_PRINTF + * Combines KFX_NONNULL + KFX_PRINTF_FORMAT for printf-like functions. + * Parameters are 1-indexed (1-based indexing as per GCC convention). + */ +#define KFX_PRINTF(fmt_idx, va_idx) KFX_NONNULL(fmt_idx) KFX_PRINTF_FORMAT(fmt_idx, va_idx) + +/** + * KFX_PURE + * Function has no side effects and returns same value for same inputs. + * Allows compiler to optimize aggressive caching. + * + * Usage: + * KFX_PURE int absolute_value(int x); + */ +#if defined(KFX_COMPILER_GCC) + #define KFX_PURE __attribute__((pure)) +#elif defined(KFX_COMPILER_MSVC) + // MSVC: no direct equivalent, but intrinsic functions behave this way + #define KFX_PURE +#else + #define KFX_PURE +#endif + +// ══════════════════════════════════════════════════════════════════════════════ +// POSIX Function Compatibility for MSVC +// ══════════════════════════════════════════════════════════════════════════════ +#ifdef KFX_COMPILER_MSVC + #include // _getcwd, _mkdir + #include // _access + + // MSVC uses underscore-prefixed versions of POSIX functions + #define access _access + #define getcwd _getcwd + #define mkdir(path, mode) _mkdir(path) // MSVC mkdir takes 1 arg + + // File access mode constants + #ifndef F_OK + #define F_OK 0 // Test for file existence + #endif +#endif + +#endif // COMPILER_COMPAT_H diff --git a/src/config.c b/src/config.c index 467dcc9f6d..6fc20e8e60 100644 --- a/src/config.c +++ b/src/config.c @@ -469,8 +469,9 @@ int64_t value_default(const struct NamedField* named_field, const char* value_te int64_t value_name(const struct NamedField* named_field, const char* value_text, const struct NamedFieldSet* named_fields_set, int idx, const char* src_str, unsigned char flags) { size_t offset = named_fields_set->struct_size * idx; - strncpy((char*)named_field->field + offset, value_text, COMMAND_WORD_LEN - 1); - ((char*)named_field->field + offset)[COMMAND_WORD_LEN - 1] = '\0'; + char* base = (char*)named_fields_set->get_struct_base() + (ptrdiff_t)named_field->field; + strncpy(base + offset, value_text, COMMAND_WORD_LEN - 1); + (base + offset)[COMMAND_WORD_LEN - 1] = '\0'; return 0; } @@ -666,7 +667,7 @@ int64_t parse_named_field_value(const struct NamedField* named_field, const char int64_t get_named_field_value(const struct NamedField* named_field, const struct NamedFieldSet* named_fields_set, int idx) { - void* field = (char*)named_field->field + named_fields_set->struct_size * idx; + void* field = (char*)named_fields_set->get_struct_base() + (ptrdiff_t)named_field->field + named_fields_set->struct_size * idx; switch (named_field->type) { case dt_uchar: @@ -713,7 +714,7 @@ void assign_null(const struct NamedField* named_field, int64_t value, const stru void assign_default(const struct NamedField* named_field, int64_t value, const struct NamedFieldSet* named_fields_set, int idx, const char* src_str, unsigned char flags) { - void* field = (char*)named_field->field + named_fields_set->struct_size * idx; + void* field = (char*)named_fields_set->get_struct_base() + (ptrdiff_t)named_field->field + named_fields_set->struct_size * idx; switch (named_field->type) { case dt_uchar: @@ -980,7 +981,7 @@ TbBool parse_named_field_block(const char *buf, long len, const char *config_tex void set_defaults(const struct NamedFieldSet* named_fields_set, const char *config_textname) { - memset((void *)named_fields_set->struct_base, 0, named_fields_set->struct_size * named_fields_set->max_count); + memset((void *)named_fields_set->get_struct_base(), 0, named_fields_set->struct_size * named_fields_set->max_count); const struct NamedField* name_NamedField = NULL; @@ -1005,7 +1006,7 @@ void set_defaults(const struct NamedFieldSet* named_fields_set, const char *conf { for (int i = 0; i < named_fields_set->max_count; i++) { - named_fields_set->names[i].name = (char*)name_NamedField->field + i * named_fields_set->struct_size; + named_fields_set->names[i].name = (char*)named_fields_set->get_struct_base() + (ptrdiff_t)name_NamedField->field + i * named_fields_set->struct_size; named_fields_set->names[i].num = i; } named_fields_set->names[named_fields_set->max_count - 1].name = NULL; // must be null for get_id @@ -1037,8 +1038,8 @@ TbBool parse_named_field_blocks(char *buf, long len, const char *config_textname const int i = natoi(&blockname[basename_len], blocknamelen - basename_len); if (i < 0 || i >= named_fields_set->max_count) { continue; - } else if (i >= *named_fields_set->count_field) { - *named_fields_set->count_field = i + 1; + } else if (i >= *named_fields_set->get_count()) { + *named_fields_set->get_count() = i + 1; } char blockname_null[COMMAND_WORD_LEN]; strncpy(blockname_null, blockname, blocknamelen); diff --git a/src/config.h b/src/config.h index 1d3c09d328..f0ab85bdae 100644 --- a/src/config.h +++ b/src/config.h @@ -175,8 +175,27 @@ enum dataTypes char: dt_char, \ default: dt_default))) -#define field(field)\ - &field, var_type(field) +// field_t: portable, works on all C99+ compilers including MSVC. +// Takes the struct type name explicitly — produces a compile-time constant offset. +// Use for simple (non-array-subscript) member paths. +#include +#define field_t(type_name, member_path) \ + (void*)(ptrdiff_t)offsetof(type_name, member_path), \ + var_type(((type_name*)0)->member_path) + +// field_a: like field_t but for array-element member paths array[idx]. +// offsetof(T, arr) + idx*sizeof(element) is compile-time constant on all compilers, +// whereas offsetof(T, arr[n]) is a GCC extension rejected by MSVC. +#define field_a(type_name, array_member, idx) \ + (void*)(ptrdiff_t)(offsetof(type_name, array_member) + (idx) * sizeof(((type_name*)0)->array_member[0])), \ + var_type(((type_name*)0)->array_member[idx]) + +// field: GCC/Clang-only convenience alias that infers the type from an expression +// using the typeof extension. Do not use in new code — prefer field_t()/field_a(). +#ifndef _MSC_VER +#define field(elem0_expr, member_path) \ + field_t(typeof(elem0_expr), member_path) +#endif /******************************************************************************/ struct CommandWord { @@ -209,13 +228,13 @@ struct NamedField { }; struct NamedFieldSet { - int32_t *const count_field; + int32_t* (*get_count)(void); const char* block_basename; const struct NamedField* named_fields; struct NamedCommand* names; const int max_count; const size_t struct_size; - const void* struct_base; + void* (*get_struct_base)(void); }; #define NAMFIELDWRNLOG(format, ...) LbWarnLog("%s(line %lu): " format "\n", src_str , text_line_number, ##__VA_ARGS__) @@ -246,6 +265,11 @@ char *prepare_file_fmtpath_mod(const char *mod_dir, short fgroup, const char *fm char *prepare_file_path_buf(char *dst, int dst_size, short fgroup, const char *fname); char *prepare_file_path(short fgroup, const char *fname); char *prepare_file_fmtpath(short fgroup, const char *fmt_str, ...); +/* New API - self-documenting game vs. mod distinction */ +char *get_game_file_path(short fgroup, const char *fname); +char *get_mod_file_path(const char *mod_dir, short fgroup, const char *fname); +char *get_game_file_path_fmt(short fgroup, const char *fmt_str, ...); +char *get_mod_file_path_fmt(const char *mod_dir, short fgroup, const char *fmt_str, ...); unsigned char *load_data_file_to_buffer(int32_t *ldsize, short fgroup, const char *fmt_str, ...); /******************************************************************************/ TbBool load_config(const struct ConfigFileData* file_data, unsigned short flags); diff --git a/src/config_compp.c b/src/config_compp.c index 77501f5115..bb429a9f01 100644 --- a/src/config_compp.c +++ b/src/config_compp.c @@ -16,6 +16,7 @@ * (at your option) any later version. */ /******************************************************************************/ + #include "pre_inc.h" #include "config_compp.h" #include "globals.h" @@ -67,16 +68,26 @@ static int computer_type_add_event(struct ComputerType *cpt, unsigned char event /******************************************************************************/ static const struct NamedField compp_common_named_fields[] = { - {"ComputerAssists", 0, field(comp_player_conf.computer_assist_types[0]), 0, 0,COMPUTER_MODELS_COUNT, NULL, value_default, assign_default}, - {"ComputerAssists", 1, field(comp_player_conf.computer_assist_types[1]), 0, 0,COMPUTER_MODELS_COUNT, NULL, value_default, assign_default}, - {"ComputerAssists", 2, field(comp_player_conf.computer_assist_types[2]), 0, 0,COMPUTER_MODELS_COUNT, NULL, value_default, assign_default}, - {"ComputerAssists", 3, field(comp_player_conf.computer_assist_types[3]), 0, 0,COMPUTER_MODELS_COUNT, NULL, value_default, assign_default}, - {"SkirmishFirst", 0, field(comp_player_conf.skirmish_first), 0, 0,COMPUTER_MODELS_COUNT, NULL, value_default, assign_default}, - {"SkirmishLast", 0, field(comp_player_conf.skirmish_last), 0, 0,COMPUTER_MODELS_COUNT, NULL, value_default, assign_default}, - {"DefaultComputerAssist", 0, field(comp_player_conf.player_assist_default), 0, 0,COMPUTER_MODELS_COUNT, NULL, value_default, assign_default}, + {"ComputerAssists", 0, field_a(struct ComputerPlayerConfig, computer_assist_types, 0), 0, 0,COMPUTER_MODELS_COUNT, NULL, value_default, assign_default}, + {"ComputerAssists", 1, field_a(struct ComputerPlayerConfig, computer_assist_types, 1), 0, 0,COMPUTER_MODELS_COUNT, NULL, value_default, assign_default}, + {"ComputerAssists", 2, field_a(struct ComputerPlayerConfig, computer_assist_types, 2), 0, 0,COMPUTER_MODELS_COUNT, NULL, value_default, assign_default}, + {"ComputerAssists", 3, field_a(struct ComputerPlayerConfig, computer_assist_types, 3), 0, 0,COMPUTER_MODELS_COUNT, NULL, value_default, assign_default}, + {"SkirmishFirst", 0, field_t(struct ComputerPlayerConfig, skirmish_first), 0, 0,COMPUTER_MODELS_COUNT, NULL, value_default, assign_default}, + {"SkirmishLast", 0, field_t(struct ComputerPlayerConfig, skirmish_last), 0, 0,COMPUTER_MODELS_COUNT, NULL, value_default, assign_default}, + {"DefaultComputerAssist", 0, field_t(struct ComputerPlayerConfig, player_assist_default), 0, 0,COMPUTER_MODELS_COUNT, NULL, value_default, assign_default}, {NULL}, }; +static void* get_compp_common_base(void) { return &comp_player_conf; } +static int32_t* get_processes_count(void) { return &comp_player_conf.processes_count; } +static void* get_processes_base(void) { return comp_player_conf.process_types; } +static int32_t* get_checks_count(void) { return &comp_player_conf.checks_count; } +static void* get_checks_base(void) { return comp_player_conf.check_types; } +static int32_t* get_events_count(void) { return &comp_player_conf.events_count; } +static void* get_events_base(void) { return comp_player_conf.event_types; } +static int32_t* get_computers_count(void) { return &comp_player_conf.computers_count; } +static void* get_computers_base(void) { return comp_player_conf.computer_types; } + const struct NamedFieldSet compp_common_named_fields_set = { NULL, "common", @@ -84,124 +95,124 @@ const struct NamedFieldSet compp_common_named_fields_set = { NULL, 0, 0, - NULL, + get_compp_common_base, }; static const struct NamedField compp_process_named_fields[] = { //name //pos //field //default //min //max //NamedCommand - {"NAME", -1, field(comp_player_conf.process_types[0].name), 0, INT32_MIN,UINT32_MAX, NULL, value_name, assign_null}, - {"MNEMONIC", 0, field(comp_player_conf.process_types[0].mnemonic), 0, INT32_MIN,UINT32_MAX, NULL, value_name, assign_null}, - {"VALUES", 0, field(comp_player_conf.process_types[0].priority ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"VALUES", 1, field(comp_player_conf.process_types[0].process_configuration_value_2 ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"VALUES", 2, field(comp_player_conf.process_types[0].process_configuration_value_3 ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"VALUES", 3, field(comp_player_conf.process_types[0].process_configuration_value_4 ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"VALUES", 4, field(comp_player_conf.process_types[0].process_configuration_value_5 ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"FUNCTIONS", 0, field(comp_player_conf.process_types[0].func_check ), 0, INT32_MIN,UINT32_MAX, computer_process_func_type, value_default, assign_default}, - {"FUNCTIONS", 1, field(comp_player_conf.process_types[0].func_setup ), 0, INT32_MIN,UINT32_MAX, computer_process_func_type, value_default, assign_default}, - {"FUNCTIONS", 2, field(comp_player_conf.process_types[0].func_task ), 0, INT32_MIN,UINT32_MAX, computer_process_func_type, value_default, assign_default}, - {"FUNCTIONS", 3, field(comp_player_conf.process_types[0].func_complete), 0, INT32_MIN,UINT32_MAX, computer_process_func_type, value_default, assign_default}, - {"FUNCTIONS", 4, field(comp_player_conf.process_types[0].func_pause ), 0, INT32_MIN,UINT32_MAX, computer_process_func_type, value_default, assign_default}, - {"PARAMS", 0, field(comp_player_conf.process_types[0].process_parameter_1 ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"PARAMS", 1, field(comp_player_conf.process_types[0].process_parameter_2 ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"PARAMS", 2, field(comp_player_conf.process_types[0].process_parameter_3 ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"PARAMS", 3, field(comp_player_conf.process_types[0].last_run_turn), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"PARAMS", 4, field(comp_player_conf.process_types[0].process_parameter_5 ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"PARAMS", 5, field(comp_player_conf.process_types[0].flags ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"NAME", -1, field_t(struct ComputerProcess, name), 0, INT32_MIN,UINT32_MAX, NULL, value_name, assign_null}, + {"MNEMONIC", 0, field_t(struct ComputerProcess, mnemonic), 0, INT32_MIN,UINT32_MAX, NULL, value_name, assign_null}, + {"VALUES", 0, field_t(struct ComputerProcess, priority), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"VALUES", 1, field_t(struct ComputerProcess, process_configuration_value_2), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"VALUES", 2, field_t(struct ComputerProcess, process_configuration_value_3), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"VALUES", 3, field_t(struct ComputerProcess, process_configuration_value_4), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"VALUES", 4, field_t(struct ComputerProcess, process_configuration_value_5), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"FUNCTIONS", 0, field_t(struct ComputerProcess, func_check), 0, INT32_MIN,UINT32_MAX, computer_process_func_type, value_default, assign_default}, + {"FUNCTIONS", 1, field_t(struct ComputerProcess, func_setup), 0, INT32_MIN,UINT32_MAX, computer_process_func_type, value_default, assign_default}, + {"FUNCTIONS", 2, field_t(struct ComputerProcess, func_task), 0, INT32_MIN,UINT32_MAX, computer_process_func_type, value_default, assign_default}, + {"FUNCTIONS", 3, field_t(struct ComputerProcess, func_complete), 0, INT32_MIN,UINT32_MAX, computer_process_func_type, value_default, assign_default}, + {"FUNCTIONS", 4, field_t(struct ComputerProcess, func_pause), 0, INT32_MIN,UINT32_MAX, computer_process_func_type, value_default, assign_default}, + {"PARAMS", 0, field_t(struct ComputerProcess, process_parameter_1), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"PARAMS", 1, field_t(struct ComputerProcess, process_parameter_2), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"PARAMS", 2, field_t(struct ComputerProcess, process_parameter_3), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"PARAMS", 3, field_t(struct ComputerProcess, last_run_turn), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"PARAMS", 4, field_t(struct ComputerProcess, process_parameter_5), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"PARAMS", 5, field_t(struct ComputerProcess, flags), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, {NULL}, }; const struct NamedFieldSet compp_process_named_fields_set = { - &comp_player_conf.processes_count, + get_processes_count, "process", compp_process_named_fields, NULL, COMPUTER_PROCESS_TYPES_COUNT, sizeof(comp_player_conf.process_types[0]), - comp_player_conf.process_types, + get_processes_base, }; static const struct NamedField compp_check_named_fields[] = { //name //pos //field //default //min //max //NamedCommand - {"NAME", -1, field(comp_player_conf.check_types[0].name ), 0, INT32_MIN,UINT32_MAX, NULL, value_name, assign_null}, - {"MNEMONIC", 0, field(comp_player_conf.check_types[0].mnemonic ), 0, INT32_MIN,UINT32_MAX, NULL, value_name, assign_null}, - {"VALUES", 0, field(comp_player_conf.check_types[0].flags ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"VALUES", 1, field(comp_player_conf.check_types[0].turns_interval), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"FUNCTIONS", 0, field(comp_player_conf.check_types[0].func ), 0, INT32_MIN,UINT32_MAX, computer_check_func_type, value_default, assign_default}, - {"PARAMS", 0, field(comp_player_conf.check_types[0].primary_parameter ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"PARAMS", 1, field(comp_player_conf.check_types[0].secondary_parameter ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"PARAMS", 2, field(comp_player_conf.check_types[0].tertiary_parameter ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"PARAMS", 3, field(comp_player_conf.check_types[0].last_run_turn ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"NAME", -1, field_t(struct ComputerCheck, name), 0, INT32_MIN,UINT32_MAX, NULL, value_name, assign_null}, + {"MNEMONIC", 0, field_t(struct ComputerCheck, mnemonic), 0, INT32_MIN,UINT32_MAX, NULL, value_name, assign_null}, + {"VALUES", 0, field_t(struct ComputerCheck, flags), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"VALUES", 1, field_t(struct ComputerCheck, turns_interval), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"FUNCTIONS", 0, field_t(struct ComputerCheck, func), 0, INT32_MIN,UINT32_MAX, computer_check_func_type, value_default, assign_default}, + {"PARAMS", 0, field_t(struct ComputerCheck, primary_parameter), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"PARAMS", 1, field_t(struct ComputerCheck, secondary_parameter), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"PARAMS", 2, field_t(struct ComputerCheck, tertiary_parameter), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"PARAMS", 3, field_t(struct ComputerCheck, last_run_turn), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, {NULL}, }; const struct NamedFieldSet compp_check_named_fields_set = { - &comp_player_conf.checks_count, + get_checks_count, "check", compp_check_named_fields, NULL, COMPUTER_CHECKS_TYPES_COUNT, sizeof(comp_player_conf.check_types[0]), - comp_player_conf.check_types, + get_checks_base, }; static const struct NamedField compp_event_named_fields[] = { //name //pos //field //default //min //max //NamedCommand - {"NAME", -1, field(comp_player_conf.event_types[0].name ), 0, INT32_MIN,UINT32_MAX, NULL, value_name, assign_null}, - {"MNEMONIC", 0, field(comp_player_conf.event_types[0].mnemonic ), 0, INT32_MIN,UINT32_MAX, NULL, value_name, assign_null}, - {"VALUES", 0, field(comp_player_conf.event_types[0].cetype ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"VALUES", 1, field(comp_player_conf.event_types[0].mevent_kind ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"VALUES", 2, field(comp_player_conf.event_types[0].test_interval ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"FUNCTIONS", 0, field(comp_player_conf.event_types[0].func_event ), 0, INT32_MIN,UINT32_MAX, computer_event_func_type, value_default, assign_default}, - {"FUNCTIONS", 0, field(comp_player_conf.event_types[0].func_test ), 0, INT32_MIN,UINT32_MAX, computer_event_test_func_type, value_default, assign_default}, - {"PROCESS", 0, field(comp_player_conf.event_types[0].process ), 0, INT32_MIN,UINT32_MAX, NULL, value_process_mnemonic, assign_default}, - {"PARAMS", 0, field(comp_player_conf.event_types[0].primary_parameter ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"PARAMS", 1, field(comp_player_conf.event_types[0].secondary_parameter ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"PARAMS", 2, field(comp_player_conf.event_types[0].tertiary_parameter ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"PARAMS", 3, field(comp_player_conf.event_types[0].last_test_gameturn ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"NAME", -1, field_t(struct ComputerEvent, name), 0, INT32_MIN,UINT32_MAX, NULL, value_name, assign_null}, + {"MNEMONIC", 0, field_t(struct ComputerEvent, mnemonic), 0, INT32_MIN,UINT32_MAX, NULL, value_name, assign_null}, + {"VALUES", 0, field_t(struct ComputerEvent, cetype), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"VALUES", 1, field_t(struct ComputerEvent, mevent_kind), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"VALUES", 2, field_t(struct ComputerEvent, test_interval), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"FUNCTIONS", 0, field_t(struct ComputerEvent, func_event), 0, INT32_MIN,UINT32_MAX, computer_event_func_type, value_default, assign_default}, + {"FUNCTIONS", 0, field_t(struct ComputerEvent, func_test), 0, INT32_MIN,UINT32_MAX, computer_event_test_func_type, value_default, assign_default}, + {"PROCESS", 0, field_t(struct ComputerEvent, process), 0, INT32_MIN,UINT32_MAX, NULL, value_process_mnemonic, assign_default}, + {"PARAMS", 0, field_t(struct ComputerEvent, primary_parameter), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"PARAMS", 1, field_t(struct ComputerEvent, secondary_parameter), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"PARAMS", 2, field_t(struct ComputerEvent, tertiary_parameter), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"PARAMS", 3, field_t(struct ComputerEvent, last_test_gameturn), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, {NULL}, }; const struct NamedFieldSet compp_event_named_fields_set = { - &comp_player_conf.events_count, + get_events_count, "event", compp_event_named_fields, NULL, COMPUTER_EVENTS_TYPES_COUNT, sizeof(comp_player_conf.event_types[0]), - comp_player_conf.event_types, + get_events_base, }; static const struct NamedField compp_computer_named_fields[] = { //name //pos //field //default //min //max //NamedCommand - {"NAME", -1, field(comp_player_conf.computer_types[0].name), 0, INT32_MIN,UINT32_MAX, NULL, value_name, assign_null}, - {"TOOLTIPTEXTID", 0, field(comp_player_conf.computer_types[0].tooltip_stridx),GUIStr_Empty, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"ASSISTANTICON", 0, field(comp_player_conf.computer_types[0].sprite_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_icon, assign_icon}, - {"VALUES", 0, field(comp_player_conf.computer_types[0].dig_stack_size ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"VALUES", 1, field(comp_player_conf.computer_types[0].processes_time ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"VALUES", 2, field(comp_player_conf.computer_types[0].click_rate), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"VALUES", 3, field(comp_player_conf.computer_types[0].max_room_build_tasks), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"VALUES", 4, field(comp_player_conf.computer_types[0].turn_begin ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"VALUES", 5, field(comp_player_conf.computer_types[0].sim_before_dig ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"VALUES", 5, field(comp_player_conf.computer_types[0].drop_delay ), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"PROCESSES", -1, field(comp_player_conf.computer_types[0].processes ), 0, INT32_MIN,UINT32_MAX, NULL, value_processes, assign_null}, - {"CHECKS", -1, field(comp_player_conf.computer_types[0].checks ), 0, INT32_MIN,UINT32_MAX, NULL, value_checks, assign_null}, - {"EVENTS", -1, field(comp_player_conf.computer_types[0].events ), 0, INT32_MIN,UINT32_MAX, NULL, value_events, assign_null}, + {"NAME", -1, field_t(struct ComputerType, name), 0, INT32_MIN,UINT32_MAX, NULL, value_name, assign_null}, + {"TOOLTIPTEXTID", 0, field_t(struct ComputerType, tooltip_stridx),GUIStr_Empty, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"ASSISTANTICON", 0, field_t(struct ComputerType, sprite_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_icon, assign_icon}, + {"VALUES", 0, field_t(struct ComputerType, dig_stack_size), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"VALUES", 1, field_t(struct ComputerType, processes_time), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"VALUES", 2, field_t(struct ComputerType, click_rate), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"VALUES", 3, field_t(struct ComputerType, max_room_build_tasks), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"VALUES", 4, field_t(struct ComputerType, turn_begin), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"VALUES", 5, field_t(struct ComputerType, sim_before_dig), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"VALUES", 5, field_t(struct ComputerType, drop_delay), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"PROCESSES", -1, field_t(struct ComputerType, processes), 0, INT32_MIN,UINT32_MAX, NULL, value_processes, assign_null}, + {"CHECKS", -1, field_t(struct ComputerType, checks), 0, INT32_MIN,UINT32_MAX, NULL, value_checks, assign_null}, + {"EVENTS", -1, field_t(struct ComputerType, events), 0, INT32_MIN,UINT32_MAX, NULL, value_events, assign_null}, {NULL}, }; const struct NamedFieldSet compp_computer_named_fields_set = { - &comp_player_conf.computers_count, + get_computers_count, "computer", compp_computer_named_fields, NULL, COMPUTER_MODELS_COUNT, sizeof(comp_player_conf.computer_types[0]), - comp_player_conf.computer_types, + get_computers_base, }; /******************************************************************************/ diff --git a/src/config_compp.h b/src/config_compp.h index ac2fef9c8b..f9660697ba 100644 --- a/src/config_compp.h +++ b/src/config_compp.h @@ -132,10 +132,10 @@ extern const struct ConfigFileData keeper_keepcomp_file_data; /******************************************************************************/ struct ComputerType *get_computer_type_template(long cpt_idx); /******************************************************************************/ +extern struct ComputerPlayerConfig comp_player_conf; +/******************************************************************************/ #ifdef __cplusplus } #endif -extern struct ComputerPlayerConfig comp_player_conf; - #endif diff --git a/src/config_crtrstates.c b/src/config_crtrstates.c index f6a4770c47..a2d1af3b9b 100644 --- a/src/config_crtrstates.c +++ b/src/config_crtrstates.c @@ -16,6 +16,7 @@ * (at your option) any later version. */ /******************************************************************************/ + #include "pre_inc.h" #include "config_crtrstates.h" #include "globals.h" @@ -115,33 +116,40 @@ int64_t value_overrides(const struct NamedField* named_field, const char* value_ return 0; } +#pragma push_macro("game") +#undef game const struct NamedField crstates_states_named_fields[] = { - {"NAME", 0, field(game.conf.crtr_conf.states[0].name), 0, 0, 0, creatrstate_desc, value_name, assign_null}, - {"PROCESSFUNCTION", 0, field(game.conf.crtr_conf.states[0].process_state), 0, 0, 0, process_func_commands, value_function, assign_default}, - {"CLEANUPFUNCTION", 0, field(game.conf.crtr_conf.states[0].cleanup_state), 0, 0, 0, cleanup_func_commands, value_function, assign_default}, - {"MOVEFROMSLABFUNCTION", 0, field(game.conf.crtr_conf.states[0].move_from_slab), 0, 0, 0, move_from_slab_func_commands, value_function, assign_default}, - {"MOVECHECKFUNCTION", 0, field(game.conf.crtr_conf.states[0].move_check), 0, 0, 0, move_check_func_commands, value_function, assign_default}, + {"NAME", 0, field_t(struct CreatureStateConfig, name), 0, 0, 0, creatrstate_desc, value_name, assign_null}, + {"PROCESSFUNCTION", 0, field_t(struct CreatureStateConfig, process_state), 0, 0, 0, process_func_commands, value_function, assign_default}, + {"CLEANUPFUNCTION", 0, field_t(struct CreatureStateConfig, cleanup_state), 0, 0, 0, cleanup_func_commands, value_function, assign_default}, + {"MOVEFROMSLABFUNCTION", 0, field_t(struct CreatureStateConfig, move_from_slab), 0, 0, 0, move_from_slab_func_commands, value_function, assign_default}, + {"MOVECHECKFUNCTION", 0, field_t(struct CreatureStateConfig, move_check), 0, 0, 0, move_check_func_commands, value_function, assign_default}, {"OVERRIDES", -1, NULL,0, 0, 0, 0, NULL, value_overrides, assign_null}, - {"STATETYPE", 0, field(game.conf.crtr_conf.states[0].state_type), 0, 0, 0, creature_state_types_commands, value_default, assign_default}, - {"CAPTIVE", 0, field(game.conf.crtr_conf.states[0].captive), 0, 0, 1, NULL, value_default, assign_default}, - {"TRANSITION", 0, field(game.conf.crtr_conf.states[0].transition), 0, 0, 1, NULL, value_default, assign_default}, - {"FOLLOWBEHAVIOR", 0, field(game.conf.crtr_conf.states[0].follow_behavior), 0, 0, 0, follow_behavior_commands, value_default, assign_default}, - {"BLOCKSALLSTATECHANGES", 0, field(game.conf.crtr_conf.states[0].blocks_all_state_changes), 0, 0, 1, NULL, value_default, assign_default}, - {"SPRITEIDX", 0, field(game.conf.crtr_conf.states[0].sprite_idx), 0, 0, 0, NULL, value_icon, assign_icon}, - {"DISPLAYTHOUGHTBUBBLE", 0, field(game.conf.crtr_conf.states[0].display_thought_bubble), 0, 0, 1, NULL, value_default, assign_default}, - {"SNEAKY", 0, field(game.conf.crtr_conf.states[0].sneaky), 0, 0, 1, NULL, value_default, assign_default}, - {"REACTTOCTA", 0, field(game.conf.crtr_conf.states[0].react_to_cta), 0, 0, 1, NULL, value_default, assign_default}, + {"STATETYPE", 0, field_t(struct CreatureStateConfig, state_type), 0, 0, 0, creature_state_types_commands, value_default, assign_default}, + {"CAPTIVE", 0, field_t(struct CreatureStateConfig, captive), 0, 0, 1, NULL, value_default, assign_default}, + {"TRANSITION", 0, field_t(struct CreatureStateConfig, transition), 0, 0, 1, NULL, value_default, assign_default}, + {"FOLLOWBEHAVIOR", 0, field_t(struct CreatureStateConfig, follow_behavior), 0, 0, 0, follow_behavior_commands, value_default, assign_default}, + {"BLOCKSALLSTATECHANGES", 0, field_t(struct CreatureStateConfig, blocks_all_state_changes), 0, 0, 1, NULL, value_default, assign_default}, + {"SPRITEIDX", 0, field_t(struct CreatureStateConfig, sprite_idx), 0, 0, 0, NULL, value_icon, assign_icon}, + {"DISPLAYTHOUGHTBUBBLE", 0, field_t(struct CreatureStateConfig, display_thought_bubble), 0, 0, 1, NULL, value_default, assign_default}, + {"SNEAKY", 0, field_t(struct CreatureStateConfig, sneaky), 0, 0, 1, NULL, value_default, assign_default}, + {"REACTTOCTA", 0, field_t(struct CreatureStateConfig, react_to_cta), 0, 0, 1, NULL, value_default, assign_default}, {NULL}, }; +#pragma pop_macro("game") + +static int32_t* get_crstates_count(void) { return &game.conf.crtr_conf.states_count; } +static void* get_crstates_base(void) { return game.conf.crtr_conf.states; } + const struct NamedFieldSet crstates_states_named_fields_set = { - &game.conf.crtr_conf.states_count, + get_crstates_count, "state", crstates_states_named_fields, creatrstate_desc, CREATURE_STATES_MAX, sizeof(game.conf.crtr_conf.states[0]), - game.conf.crtr_conf.states, + get_crstates_base, }; static TbBool load_creaturestates_config_file(const char *fname, unsigned short flags); diff --git a/src/config_cubes.c b/src/config_cubes.c index 7801a3a589..593334d827 100644 --- a/src/config_cubes.c +++ b/src/config_cubes.c @@ -16,6 +16,7 @@ * (at your option) any later version. */ /******************************************************************************/ + #include "pre_inc.h" #include "bflib_basics.h" #include "bflib_fileio.h" @@ -51,29 +52,36 @@ static const struct NamedCommand cubes_properties_flags[] = { {NULL, 0}, }; +#pragma push_macro("game") +#undef game static const struct NamedField cubes_named_fields[] = { //name //pos //field //default //min //max //NamedCommand - {"Name", 0, field(game.conf.cube_conf.cube_cfgstats[0].code_name), 0, 0, 0, cube_desc, value_name, assign_null}, - {"Textures", 0, field(game.conf.cube_conf.cube_cfgstats[0].texture_id[0]), 0, 0, USHRT_MAX, NULL, value_default, assign_default}, - {"Textures", 1, field(game.conf.cube_conf.cube_cfgstats[0].texture_id[1]), 0, 0, USHRT_MAX, NULL, value_default, assign_default}, - {"Textures", 2, field(game.conf.cube_conf.cube_cfgstats[0].texture_id[2]), 0, 0, USHRT_MAX, NULL, value_default, assign_default}, - {"Textures", 3, field(game.conf.cube_conf.cube_cfgstats[0].texture_id[3]), 0, 0, USHRT_MAX, NULL, value_default, assign_default}, - {"Textures", 4, field(game.conf.cube_conf.cube_cfgstats[0].texture_id[4]), 0, 0, USHRT_MAX, NULL, value_default, assign_default}, - {"Textures", 5, field(game.conf.cube_conf.cube_cfgstats[0].texture_id[5]), 0, 0, USHRT_MAX, NULL, value_default, assign_default}, - {"OwnershipGroup", 0, field(game.conf.cube_conf.cube_cfgstats[0].ownershipGroup), 0, 0, CUBE_OWNERSHIP_GROUPS, NULL, value_default, assign_default}, - {"Owner", 0, field(game.conf.cube_conf.cube_cfgstats[0].owner), 0, 0, PLAYERS_COUNT, cmpgn_human_player_options,value_default, assign_owner}, - {"Properties", -1, field(game.conf.cube_conf.cube_cfgstats[0].properties_flags), 0, 0, UCHAR_MAX, cubes_properties_flags, value_flagsfield,assign_default}, + {"Name", 0, field_t(struct CubeConfigStats, code_name), 0, 0, 0, cube_desc, value_name, assign_null}, + {"Textures", 0, field_a(struct CubeConfigStats, texture_id, 0), 0, 0, USHRT_MAX, NULL, value_default, assign_default}, + {"Textures", 1, field_a(struct CubeConfigStats, texture_id, 1), 0, 0, USHRT_MAX, NULL, value_default, assign_default}, + {"Textures", 2, field_a(struct CubeConfigStats, texture_id, 2), 0, 0, USHRT_MAX, NULL, value_default, assign_default}, + {"Textures", 3, field_a(struct CubeConfigStats, texture_id, 3), 0, 0, USHRT_MAX, NULL, value_default, assign_default}, + {"Textures", 4, field_a(struct CubeConfigStats, texture_id, 4), 0, 0, USHRT_MAX, NULL, value_default, assign_default}, + {"Textures", 5, field_a(struct CubeConfigStats, texture_id, 5), 0, 0, USHRT_MAX, NULL, value_default, assign_default}, + {"OwnershipGroup", 0, field_t(struct CubeConfigStats, ownershipGroup), 0, 0, CUBE_OWNERSHIP_GROUPS, NULL, value_default, assign_default}, + {"Owner", 0, field_t(struct CubeConfigStats, owner), 0, 0, PLAYERS_COUNT, cmpgn_human_player_options,value_default, assign_owner}, + {"Properties", -1, field_t(struct CubeConfigStats, properties_flags), 0, 0, UCHAR_MAX, cubes_properties_flags, value_flagsfield,assign_default}, {NULL}, }; +#pragma pop_macro("game") + +static int32_t* get_cubes_count(void) { return &game.conf.cube_conf.cube_types_count; } +static void* get_cubes_base(void) { return game.conf.cube_conf.cube_cfgstats; } + const struct NamedFieldSet cubes_named_fields_set = { - &game.conf.cube_conf.cube_types_count, + get_cubes_count, "cube", cubes_named_fields, cube_desc, CUBE_ITEMS_MAX, sizeof(game.conf.cube_conf.cube_cfgstats[0]), - game.conf.cube_conf.cube_cfgstats, + get_cubes_base, }; diff --git a/src/config_effects.c b/src/config_effects.c index 859b523bd1..f38774af1d 100644 --- a/src/config_effects.c +++ b/src/config_effects.c @@ -16,6 +16,7 @@ * (at your option) any later version. */ /******************************************************************************/ + #include "pre_inc.h" #include "config_effects.h" #include "globals.h" @@ -47,34 +48,41 @@ const struct ConfigFileData keeper_effects_file_data = { }; +#pragma push_macro("game") +#undef game const struct NamedField effects_effectgenerator_named_fields[] = { - {"NAME", 0, field(game.conf.effects_conf.effectgen_cfgstats[0].code_name), 0, INT32_MIN, UINT32_MAX, effectgen_desc, value_name, assign_null}, - {"GENERATIONDELAYMIN", 0, field(game.conf.effects_conf.effectgen_cfgstats[0].generation_delay_min), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"GENERATIONDELAYMAX", 0, field(game.conf.effects_conf.effectgen_cfgstats[0].generation_delay_max), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"GENERATIONAMOUNT", 0, field(game.conf.effects_conf.effectgen_cfgstats[0].generation_amount), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"EFFECTMODEL", 0, field(game.conf.effects_conf.effectgen_cfgstats[0].effect_model), 0, INT32_MIN, UINT32_MAX, NULL, value_effOrEffEl,assign_default}, - {"IGNORETERRAIN", 0, field(game.conf.effects_conf.effectgen_cfgstats[0].ignore_terrain), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"SPAWNHEIGHT", 0, field(game.conf.effects_conf.effectgen_cfgstats[0].spawn_height), 1, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"ACCELERATIONMIN", 0, field(game.conf.effects_conf.effectgen_cfgstats[0].acc_x_min), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"ACCELERATIONMIN", 1, field(game.conf.effects_conf.effectgen_cfgstats[0].acc_y_min), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"ACCELERATIONMIN", 2, field(game.conf.effects_conf.effectgen_cfgstats[0].acc_z_min), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"ACCELERATIONMAX", 0, field(game.conf.effects_conf.effectgen_cfgstats[0].acc_x_max), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"ACCELERATIONMAX", 1, field(game.conf.effects_conf.effectgen_cfgstats[0].acc_y_max), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"ACCELERATIONMAX", 2, field(game.conf.effects_conf.effectgen_cfgstats[0].acc_z_max), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"SOUND", 0, field(game.conf.effects_conf.effectgen_cfgstats[0].sound_sample_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"SOUND", 1, field(game.conf.effects_conf.effectgen_cfgstats[0].sound_sample_rng), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"NAME", 0, field_t(struct EffectGeneratorConfigStats, code_name), 0, INT32_MIN, UINT32_MAX, effectgen_desc, value_name, assign_null}, + {"GENERATIONDELAYMIN", 0, field_t(struct EffectGeneratorConfigStats, generation_delay_min), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"GENERATIONDELAYMAX", 0, field_t(struct EffectGeneratorConfigStats, generation_delay_max), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"GENERATIONAMOUNT", 0, field_t(struct EffectGeneratorConfigStats, generation_amount), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"EFFECTMODEL", 0, field_t(struct EffectGeneratorConfigStats, effect_model), 0, INT32_MIN, UINT32_MAX, NULL, value_effOrEffEl,assign_default}, + {"IGNORETERRAIN", 0, field_t(struct EffectGeneratorConfigStats, ignore_terrain), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"SPAWNHEIGHT", 0, field_t(struct EffectGeneratorConfigStats, spawn_height), 1, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"ACCELERATIONMIN", 0, field_t(struct EffectGeneratorConfigStats, acc_x_min), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"ACCELERATIONMIN", 1, field_t(struct EffectGeneratorConfigStats, acc_y_min), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"ACCELERATIONMIN", 2, field_t(struct EffectGeneratorConfigStats, acc_z_min), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"ACCELERATIONMAX", 0, field_t(struct EffectGeneratorConfigStats, acc_x_max), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"ACCELERATIONMAX", 1, field_t(struct EffectGeneratorConfigStats, acc_y_max), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"ACCELERATIONMAX", 2, field_t(struct EffectGeneratorConfigStats, acc_z_max), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"SOUND", 0, field_t(struct EffectGeneratorConfigStats, sound_sample_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"SOUND", 1, field_t(struct EffectGeneratorConfigStats, sound_sample_rng), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, {NULL}, }; +#pragma pop_macro("game") + +static int32_t* get_effectgen_count(void) { return &game.conf.effects_conf.effectgen_cfgstats_count; } +static void* get_effectgen_base(void) { return game.conf.effects_conf.effectgen_cfgstats; } + const struct NamedFieldSet effects_effectgenerator_named_fields_set = { - &game.conf.effects_conf.effectgen_cfgstats_count, + get_effectgen_count, "effectGenerator", effects_effectgenerator_named_fields, effectgen_desc, EFFECTSGEN_TYPES_MAX, sizeof(game.conf.effects_conf.effectgen_cfgstats[0]), - game.conf.effects_conf.effectgen_cfgstats, + get_effectgen_base, }; int32_t const imp_spangle_effects[] = { @@ -128,7 +136,7 @@ static void load_effects(VALUE *value, unsigned short flags) CONDITIONAL_ASSIGN_SPELL(section,"SpellEffect",effcst->spell_effect); } } - + // Set sentinel NULL entry to mark the end of valid entries if (max_effect_id >= 0) { diff --git a/src/config_lenses.c b/src/config_lenses.c index c99e2a2c23..71d2b8a63c 100644 --- a/src/config_lenses.c +++ b/src/config_lenses.c @@ -16,6 +16,7 @@ * (at your option) any later version. */ /******************************************************************************/ + #include "pre_inc.h" #include "config_lenses.h" #include "globals.h" @@ -54,31 +55,34 @@ static int64_t value_overlay(const struct NamedField* named_field, const char* v const struct NamedField lenses_data_named_fields[] = { //name //pos //field //default //min //max //NamedCommand - {"NAME", 0, field(lenses_conf.lenses[0].code_name), 0, 0, 0, lenses_desc, value_name, assign_null}, - {"MIST", 0, field(lenses_conf.lenses[0].mist_file), 0, 0, 0, NULL, value_mist, assign_null}, - {"MIST", 1, field(lenses_conf.lenses[0].mist_lightness), 0, 0, 63, NULL, value_default, assign_default}, - {"MIST", 2, field(lenses_conf.lenses[0].mist_ghost), 0, 0, 255, NULL, value_default, assign_default}, - {"MIST", 3, field(lenses_conf.lenses[0].mist_pos_x_step), 2, 0, 255, NULL, value_default, assign_default}, - {"MIST", 4, field(lenses_conf.lenses[0].mist_pos_y_step), 1, 0, 255, NULL, value_default, assign_default}, - {"MIST", 5, field(lenses_conf.lenses[0].mist_sec_x_step), 253, 0, 255, NULL, value_default, assign_default}, - {"MIST", 6, field(lenses_conf.lenses[0].mist_sec_y_step), 3, 0, 255, NULL, value_default, assign_default}, - {"DISPLACEMENT", 0, field(lenses_conf.lenses[0].displace_kind), 0, 0, 255, NULL, value_default, assign_default}, - {"DISPLACEMENT", 1, field(lenses_conf.lenses[0].displace_magnitude), 0, 0, 511, NULL, value_default, assign_default}, - {"DISPLACEMENT", 2, field(lenses_conf.lenses[0].displace_period), 1, 0, 511, NULL, value_displace, assign_default}, - {"PALETTE", 0, field(lenses_conf.lenses[0].palette), 0, 0, 0, NULL, value_pallete, assign_null}, - {"OVERLAY", 0, field(lenses_conf.lenses[0].overlay_file), 0, 0, 0, NULL, value_overlay, assign_null}, - {"OVERLAY", 1, field(lenses_conf.lenses[0].overlay_alpha), 128, 0, 255, NULL, value_default, assign_default}, + {"NAME", 0, field_t(struct LensConfig, code_name), 0, 0, 0, lenses_desc, value_name, assign_null}, + {"MIST", 0, field_t(struct LensConfig, mist_file), 0, 0, 0, NULL, value_mist, assign_null}, + {"MIST", 1, field_t(struct LensConfig, mist_lightness), 0, 0, 63, NULL, value_default, assign_default}, + {"MIST", 2, field_t(struct LensConfig, mist_ghost), 0, 0, 255, NULL, value_default, assign_default}, + {"MIST", 3, field_t(struct LensConfig, mist_pos_x_step), 2, 0, 255, NULL, value_default, assign_default}, + {"MIST", 4, field_t(struct LensConfig, mist_pos_y_step), 1, 0, 255, NULL, value_default, assign_default}, + {"MIST", 5, field_t(struct LensConfig, mist_sec_x_step), 253, 0, 255, NULL, value_default, assign_default}, + {"MIST", 6, field_t(struct LensConfig, mist_sec_y_step), 3, 0, 255, NULL, value_default, assign_default}, + {"DISPLACEMENT", 0, field_t(struct LensConfig, displace_kind), 0, 0, 255, NULL, value_default, assign_default}, + {"DISPLACEMENT", 1, field_t(struct LensConfig, displace_magnitude), 0, 0, 511, NULL, value_default, assign_default}, + {"DISPLACEMENT", 2, field_t(struct LensConfig, displace_period), 1, 0, 511, NULL, value_displace, assign_default}, + {"PALETTE", 0, field_t(struct LensConfig, palette), 0, 0, 0, NULL, value_pallete, assign_null}, + {"OVERLAY", 0, field_t(struct LensConfig, overlay_file), 0, 0, 0, NULL, value_overlay, assign_null}, + {"OVERLAY", 1, field_t(struct LensConfig, overlay_alpha), 128, 0, 255, NULL, value_default, assign_default}, {NULL}, }; +static int32_t* get_lenses_count(void) { return &lenses_conf.lenses_count; } +static void* get_lenses_base(void) { return lenses_conf.lenses; } + const struct NamedFieldSet lenses_data_named_fields_set = { - &lenses_conf.lenses_count, + get_lenses_count, "lens", lenses_data_named_fields, lenses_desc, LENS_ITEMS_MAX, sizeof(lenses_conf.lenses[0]), - lenses_conf.lenses, + get_lenses_base, }; /******************************************************************************/ @@ -92,12 +96,20 @@ struct LensConfig *get_lens_config(long lens_idx) static int64_t value_mist(const struct NamedField* named_field, const char* value_text, const struct NamedFieldSet* named_fields_set, int idx, const char* src_str, unsigned char flags) { + if (idx < 0 || idx >= named_fields_set->max_count) { + ERRORMSG("Config index %d out of bounds [0,%d) for mist in lens.cfg", idx, named_fields_set->max_count); + return 0; + } lenses_conf.lenses[idx].flags |= LCF_HasMist; return value_name(named_field, value_text, named_fields_set, idx, src_str, flags); } static int64_t value_displace(const struct NamedField* named_field, const char* value_text, const struct NamedFieldSet* named_fields_set, int idx, const char* src_str, unsigned char flags) { + if (idx < 0 || idx >= named_fields_set->max_count) { + ERRORMSG("Config index %d out of bounds [0,%d) for displace in lens.cfg", idx, named_fields_set->max_count); + return 0; + } lenses_conf.lenses[idx].flags |= LCF_HasDisplace; return value_default(named_field, value_text, named_fields_set, idx, src_str, flags); } @@ -105,9 +117,13 @@ static int64_t value_displace(const struct NamedField* named_field, const char* static int64_t value_pallete(const struct NamedField* named_field, const char* value_text, const struct NamedFieldSet* named_fields_set, int idx, const char* src_str, unsigned char flags) { + if (idx < 0 || idx >= named_fields_set->max_count) { + ERRORMSG("Config index %d out of bounds [0,%d) for palette in lens.cfg", idx, named_fields_set->max_count); + return 0; + } lenses_conf.lenses[idx].flags |= LCF_HasPalette; char* fname = prepare_file_path(FGrp_StdData, value_text); - if (LbFileLoadAt(fname, (char*)(named_field->field) + named_fields_set->struct_size * idx) != PALETTE_SIZE) + if (LbFileLoadAt(fname, (char*)named_fields_set->get_struct_base() + named_fields_set->struct_size * idx + (ptrdiff_t)named_field->field) != PALETTE_SIZE) { CONFWRNLOG("Couldn't load \"%s\" file for \"%s\" parameter in [%s%d] block of lens.cfg file.", value_text, named_field->name, named_fields_set->block_basename, idx); @@ -117,6 +133,10 @@ static int64_t value_pallete(const struct NamedField* named_field, const char* v static int64_t value_overlay(const struct NamedField* named_field, const char* value_text, const struct NamedFieldSet* named_fields_set, int idx, const char* src_str, unsigned char flags) { + if (idx < 0 || idx >= named_fields_set->max_count) { + ERRORMSG("Config index %d out of bounds [0,%d) for overlay in lens.cfg", idx, named_fields_set->max_count); + return 0; + } SYNCDBG (9, "value_overlay called: argnum=%d, value='%s', lens=%d", named_field->argnum, value_text, idx); if (value_text == NULL || value_text[0] == '\0') { diff --git a/src/config_magic.c b/src/config_magic.c index 8afbca2d54..fa36664419 100644 --- a/src/config_magic.c +++ b/src/config_magic.c @@ -16,6 +16,7 @@ * (at your option) any later version. */ /******************************************************************************/ + #include "pre_inc.h" #include "config_magic.h" #include "globals.h" @@ -365,60 +366,67 @@ static void assign_strength_before_last(const struct NamedField* named_field, in assign_default(named_field,value,named_fields_set,idx,src_str,flags); } +#pragma push_macro("game") +#undef game static const struct NamedField magic_powers_named_fields[] = { //name //pos //field //default //min //max //NamedCommand - {"NAME", 0, field(game.conf.magic_conf.power_cfgstats[0].code_name), 0, INT32_MIN,UINT32_MAX, power_desc, value_name, assign_null}, - {"POWER", 0, field(game.conf.magic_conf.power_cfgstats[0].strength[0]), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"POWER", 1, field(game.conf.magic_conf.power_cfgstats[0].strength[1]), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"POWER", 2, field(game.conf.magic_conf.power_cfgstats[0].strength[2]), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"POWER", 3, field(game.conf.magic_conf.power_cfgstats[0].strength[3]), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"POWER", 4, field(game.conf.magic_conf.power_cfgstats[0].strength[4]), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"POWER", 5, field(game.conf.magic_conf.power_cfgstats[0].strength[5]), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"POWER", 6, field(game.conf.magic_conf.power_cfgstats[0].strength[6]), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"POWER", 7, field(game.conf.magic_conf.power_cfgstats[0].strength[7]), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"POWER", 8, field(game.conf.magic_conf.power_cfgstats[0].strength[8]), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_strength_before_last}, - {"POWER", 8, field(game.conf.magic_conf.power_cfgstats[0].strength[9]), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"COST", 0, field(game.conf.magic_conf.power_cfgstats[0].cost[0]), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"COST", 1, field(game.conf.magic_conf.power_cfgstats[0].cost[1]), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"COST", 2, field(game.conf.magic_conf.power_cfgstats[0].cost[2]), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"COST", 3, field(game.conf.magic_conf.power_cfgstats[0].cost[3]), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"COST", 4, field(game.conf.magic_conf.power_cfgstats[0].cost[4]), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"COST", 5, field(game.conf.magic_conf.power_cfgstats[0].cost[5]), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"COST", 6, field(game.conf.magic_conf.power_cfgstats[0].cost[6]), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"COST", 7, field(game.conf.magic_conf.power_cfgstats[0].cost[7]), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"COST", 7, field(game.conf.magic_conf.power_cfgstats[0].cost[8]), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"DURATION", 0, field(game.conf.magic_conf.power_cfgstats[0].duration), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"CASTABILITY", -1, field(game.conf.magic_conf.power_cfgstats[0].can_cast_flags), 0, 0,UINT64_MAX, (struct NamedCommand*)powermodel_castability_commands, value_longflagsfield, assign_default}, - {"ARTIFACT", 0, field(game.conf.magic_conf.power_cfgstats[0].artifact_model), 0, INT32_MIN,UINT32_MAX, object_desc, value_default, assign_artifact}, - {"NAMETEXTID", 0, field(game.conf.magic_conf.power_cfgstats[0].name_stridx), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"TOOLTIPTEXTID", 0, field(game.conf.magic_conf.power_cfgstats[0].tooltip_stridx), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"SYMBOLSPRITES", 0, field(game.conf.magic_conf.power_cfgstats[0].bigsym_sprite_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_icon, assign_icon}, - {"SYMBOLSPRITES", 1, field(game.conf.magic_conf.power_cfgstats[0].medsym_sprite_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_icon, assign_icon}, - {"POINTERSPRITES", 0, field(game.conf.magic_conf.power_cfgstats[0].pointer_sprite_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_icon, assign_icon}, - {"PANELTABINDEX", 0, field(game.conf.magic_conf.power_cfgstats[0].panel_tab_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"SOUNDSAMPLES", 0, field(game.conf.magic_conf.power_cfgstats[0].select_sample_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"PROPERTIES", 0, field(game.conf.magic_conf.power_cfgstats[0].config_flags), 0, INT32_MIN,UINT32_MAX, powermodel_properties_commands, value_flagsfield,assign_default}, - {"CASTEXPANDFUNC", 0, field(game.conf.magic_conf.power_cfgstats[0].overcharge_check_idx), 0, INT32_MIN,UINT32_MAX, powermodel_expand_check_func_type, value_default, assign_default}, - {"PLAYERSTATE", 0, field(game.conf.magic_conf.power_cfgstats[0].work_state), 0, INT32_MIN,UINT32_MAX, player_state_commands, value_default, assign_default}, - {"PARENTPOWER", 0, field(game.conf.magic_conf.power_cfgstats[0].parent_power), 0, INT32_MIN,UINT32_MAX, power_desc, value_default, assign_default}, - {"SOUNDPLAYED", 0, field(game.conf.magic_conf.power_cfgstats[0].select_sound_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"COOLDOWN", 0, field(game.conf.magic_conf.power_cfgstats[0].cast_cooldown), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"SPELL", 0, field(game.conf.magic_conf.power_cfgstats[0].spell_idx), 0, INT32_MIN,UINT32_MAX, spell_desc, value_default, assign_default}, - {"EFFECT", 0, field(game.conf.magic_conf.power_cfgstats[0].effect_id), 0, INT32_MIN,UINT32_MAX, NULL, value_effOrEffEl,assign_default}, - {"USEFUNCTION", 0, field(game.conf.magic_conf.power_cfgstats[0].magic_use_func_idx), 0, INT32_MIN,UINT32_MAX, magic_use_func_commands, value_function, assign_default}, - {"CREATURETYPE", 0, field(game.conf.magic_conf.power_cfgstats[0].creature_model), 0, INT32_MIN,UINT32_MAX, creature_desc, value_default, assign_default}, - {"COSTFORMULA", 0, field(game.conf.magic_conf.power_cfgstats[0].cost_formula), 0, INT32_MIN,UINT32_MAX, magic_cost_formula_commands, value_default, assign_default}, + {"NAME", 0, field_t(struct PowerConfigStats, code_name), 0, INT32_MIN,UINT32_MAX, power_desc, value_name, assign_null}, + {"POWER", 0, field_a(struct PowerConfigStats, strength, 0), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"POWER", 1, field_a(struct PowerConfigStats, strength, 1), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"POWER", 2, field_a(struct PowerConfigStats, strength, 2), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"POWER", 3, field_a(struct PowerConfigStats, strength, 3), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"POWER", 4, field_a(struct PowerConfigStats, strength, 4), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"POWER", 5, field_a(struct PowerConfigStats, strength, 5), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"POWER", 6, field_a(struct PowerConfigStats, strength, 6), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"POWER", 7, field_a(struct PowerConfigStats, strength, 7), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"POWER", 8, field_a(struct PowerConfigStats, strength, 8), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_strength_before_last}, + {"POWER", 8, field_a(struct PowerConfigStats, strength, 9), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"COST", 0, field_a(struct PowerConfigStats, cost, 0), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"COST", 1, field_a(struct PowerConfigStats, cost, 1), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"COST", 2, field_a(struct PowerConfigStats, cost, 2), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"COST", 3, field_a(struct PowerConfigStats, cost, 3), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"COST", 4, field_a(struct PowerConfigStats, cost, 4), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"COST", 5, field_a(struct PowerConfigStats, cost, 5), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"COST", 6, field_a(struct PowerConfigStats, cost, 6), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"COST", 7, field_a(struct PowerConfigStats, cost, 7), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"COST", 7, field_a(struct PowerConfigStats, cost, 8), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"DURATION", 0, field_t(struct PowerConfigStats, duration), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"CASTABILITY", -1, field_t(struct PowerConfigStats, can_cast_flags), 0, 0,UINT64_MAX, (struct NamedCommand*)powermodel_castability_commands, value_longflagsfield, assign_default}, + {"ARTIFACT", 0, field_t(struct PowerConfigStats, artifact_model), 0, INT32_MIN,UINT32_MAX, object_desc, value_default, assign_artifact}, + {"NAMETEXTID", 0, field_t(struct PowerConfigStats, name_stridx), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"TOOLTIPTEXTID", 0, field_t(struct PowerConfigStats, tooltip_stridx), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"SYMBOLSPRITES", 0, field_t(struct PowerConfigStats, bigsym_sprite_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_icon, assign_icon}, + {"SYMBOLSPRITES", 1, field_t(struct PowerConfigStats, medsym_sprite_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_icon, assign_icon}, + {"POINTERSPRITES", 0, field_t(struct PowerConfigStats, pointer_sprite_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_icon, assign_icon}, + {"PANELTABINDEX", 0, field_t(struct PowerConfigStats, panel_tab_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"SOUNDSAMPLES", 0, field_t(struct PowerConfigStats, select_sample_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"PROPERTIES", 0, field_t(struct PowerConfigStats, config_flags), 0, INT32_MIN,UINT32_MAX, powermodel_properties_commands, value_flagsfield,assign_default}, + {"CASTEXPANDFUNC", 0, field_t(struct PowerConfigStats, overcharge_check_idx), 0, INT32_MIN,UINT32_MAX, powermodel_expand_check_func_type, value_default, assign_default}, + {"PLAYERSTATE", 0, field_t(struct PowerConfigStats, work_state), 0, INT32_MIN,UINT32_MAX, player_state_commands, value_default, assign_default}, + {"PARENTPOWER", 0, field_t(struct PowerConfigStats, parent_power), 0, INT32_MIN,UINT32_MAX, power_desc, value_default, assign_default}, + {"SOUNDPLAYED", 0, field_t(struct PowerConfigStats, select_sound_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"COOLDOWN", 0, field_t(struct PowerConfigStats, cast_cooldown), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"SPELL", 0, field_t(struct PowerConfigStats, spell_idx), 0, INT32_MIN,UINT32_MAX, spell_desc, value_default, assign_default}, + {"EFFECT", 0, field_t(struct PowerConfigStats, effect_id), 0, INT32_MIN,UINT32_MAX, NULL, value_effOrEffEl,assign_default}, + {"USEFUNCTION", 0, field_t(struct PowerConfigStats, magic_use_func_idx), 0, INT32_MIN,UINT32_MAX, magic_use_func_commands, value_function, assign_default}, + {"CREATURETYPE", 0, field_t(struct PowerConfigStats, creature_model), 0, INT32_MIN,UINT32_MAX, creature_desc, value_default, assign_default}, + {"COSTFORMULA", 0, field_t(struct PowerConfigStats, cost_formula), 0, INT32_MIN,UINT32_MAX, magic_cost_formula_commands, value_default, assign_default}, {NULL}, }; +#pragma pop_macro("game") + +static int32_t* get_powers_count(void) { return &game.conf.magic_conf.power_types_count; } +static void* get_powers_base(void) { return game.conf.magic_conf.power_cfgstats; } + const struct NamedFieldSet magic_powers_named_fields_set = { - &game.conf.magic_conf.power_types_count, + get_powers_count, "power", magic_powers_named_fields, power_desc, MAGIC_ITEMS_MAX, sizeof(game.conf.magic_conf.power_cfgstats[0]), - game.conf.magic_conf.power_cfgstats, + get_powers_base, }; #ifdef __cplusplus diff --git a/src/config_objects.c b/src/config_objects.c index ffdaee4eb8..d1a5c589a5 100644 --- a/src/config_objects.c +++ b/src/config_objects.c @@ -16,6 +16,7 @@ * (at your option) any later version. */ /******************************************************************************/ + #include "pre_inc.h" #include "config_objects.h" #include "globals.h" @@ -78,70 +79,77 @@ const struct NamedCommand objects_genres_desc[] = { {NULL, 0}, }; +#pragma push_macro("game") +#undef game static const struct NamedField objects_named_fields[] = { //name //pos //field //default //min //max //NamedCommand - {"NAME", 0, field(game.conf.object_conf.object_cfgstats[0].code_name), 0, INT32_MIN,UINT32_MAX, object_desc, value_name, assign_null}, - {"GENRE", 0, field(game.conf.object_conf.object_cfgstats[0].genre), 0, INT32_MIN,UINT32_MAX, objects_genres_desc, value_default, assign_default}, - {"RELATEDCREATURE", 0, field(game.conf.object_conf.object_cfgstats[0].related_creatr_model), 0, INT32_MIN,UINT32_MAX, creature_desc, value_default, assign_default}, - {"PROPERTIES", -1, field(game.conf.object_conf.object_cfgstats[0].model_flags), 0, INT32_MIN,UINT32_MAX, objects_properties_commands, value_flagsfield,assign_default}, - {"ANIMATIONID", 0, field(game.conf.object_conf.object_cfgstats[0].sprite_anim_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_animid, assign_animid}, - {"HANDANIMATIONID", 0, field(game.conf.object_conf.object_cfgstats[0].sprite_anim_idx_in_hand), 0, INT32_MIN,UINT32_MAX, NULL, value_animid, assign_animid}, - {"ANIMATIONSPEED", 0, field(game.conf.object_conf.object_cfgstats[0].anim_speed), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"SIZE_XY", 0, field(game.conf.object_conf.object_cfgstats[0].size_xy), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"SIZE_YZ", 0, field(game.conf.object_conf.object_cfgstats[0].size_z), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"SIZE_Z", 0, field(game.conf.object_conf.object_cfgstats[0].size_z), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"MAXIMUMSIZE", 0, field(game.conf.object_conf.object_cfgstats[0].sprite_size_max), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"DESTROYONLIQUID", 0, field(game.conf.object_conf.object_cfgstats[0].destroy_on_liquid), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"DESTROYONLAVA", 0, field(game.conf.object_conf.object_cfgstats[0].destroy_on_lava), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"LAVADESTROYEFFECT", 0, field(game.conf.object_conf.object_cfgstats[0].lava_burn_effect), TngEff_HarmlessGas2, INT32_MIN,UINT32_MAX, NULL, value_effOrEffEl,assign_default}, - {"WATERDESTROYEFFECT", 0, field(game.conf.object_conf.object_cfgstats[0].water_splash_effect),TngEff_Drip3, INT32_MIN,UINT32_MAX, NULL, value_effOrEffEl,assign_default}, - {"HEALTH", 0, field(game.conf.object_conf.object_cfgstats[0].health), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"FALLACCELERATION", 0, field(game.conf.object_conf.object_cfgstats[0].fall_acceleration), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"LIGHTUNAFFECTED", 0, field(game.conf.object_conf.object_cfgstats[0].light_unaffected), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"LIGHTINTENSITY", 0, field(game.conf.object_conf.object_cfgstats[0].ilght.intensity), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"LIGHTRADIUS", 0, field(game.conf.object_conf.object_cfgstats[0].ilght.radius), 0, INT32_MIN,UINT32_MAX, NULL, value_stltocoord,assign_default}, - {"LIGHTISDYNAMIC", 0, field(game.conf.object_conf.object_cfgstats[0].ilght.is_dynamic), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"MAPICON", 0, field(game.conf.object_conf.object_cfgstats[0].map_icon), 0, INT32_MIN,UINT32_MAX, NULL, value_icon, assign_icon}, - {"HANDICON", 0, field(game.conf.object_conf.object_cfgstats[0].hand_icon), 0, INT32_MIN,UINT32_MAX, NULL, value_icon, assign_icon}, - {"PICKUPOFFSET", 0, field(game.conf.object_conf.object_cfgstats[0].object_picked_up_offset.delta_x), 0,SHRT_MIN,SHRT_MAX, NULL, value_default, assign_default}, - {"PICKUPOFFSET", 1, field(game.conf.object_conf.object_cfgstats[0].object_picked_up_offset.delta_y), 0,SHRT_MIN,SHRT_MAX, NULL, value_default, assign_default}, - {"TOOLTIPTEXTID", 0, field(game.conf.object_conf.object_cfgstats[0].tooltip_stridx), GUIStr_Empty, SHRT_MIN, SHRT_MAX, NULL, value_default, assign_default}, - {"TOOLTIPTEXTID", 1, field(game.conf.object_conf.object_cfgstats[0].tooltip_optional), 0, 0, 1, NULL, value_default, assign_default}, - {"AMBIENCESOUND", 0, field(game.conf.object_conf.object_cfgstats[0].fp_smpl_idx), 0, 0,UINT32_MAX, NULL, value_default, assign_default}, - {"UPDATEFUNCTION", 0, field(game.conf.object_conf.object_cfgstats[0].updatefn_idx), 0, INT32_MIN,UINT32_MAX, object_update_functions_desc,value_function, assign_default}, - {"DRAWCLASS", 0, field(game.conf.object_conf.object_cfgstats[0].draw_class), ODC_Default, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"PERSISTENCE", 0, field(game.conf.object_conf.object_cfgstats[0].persistence), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"IMMOBILE", 0, field(game.conf.object_conf.object_cfgstats[0].immobile), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"INITIALSTATE", 0, field(game.conf.object_conf.object_cfgstats[0].initial_state), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"RANDOMSTARTFRAME", 0, field(game.conf.object_conf.object_cfgstats[0].random_start_frame), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"TRANSPARENCYFLAGS", 0, field(game.conf.object_conf.object_cfgstats[0].transparency_flags), 0, INT32_MIN,UINT32_MAX, NULL, value_transpflg, assign_default}, - {"EFFECTBEAM", 0, field(game.conf.object_conf.object_cfgstats[0].effect.beam), 0, INT32_MIN,UINT32_MAX, NULL, value_effOrEffEl,assign_default}, - {"EFFECTPARTICLE", 0, field(game.conf.object_conf.object_cfgstats[0].effect.particle), 0, INT32_MIN,UINT32_MAX, NULL, value_effOrEffEl,assign_default}, - {"EFFECTEXPLOSION1", 0, field(game.conf.object_conf.object_cfgstats[0].effect.explosion1), 0, INT32_MIN,UINT32_MAX, NULL, value_effOrEffEl,assign_default}, - {"EFFECTEXPLOSION2", 0, field(game.conf.object_conf.object_cfgstats[0].effect.explosion2), 0, INT32_MIN,UINT32_MAX, NULL, value_effOrEffEl,assign_default}, - {"EFFECTSPACING", 0, field(game.conf.object_conf.object_cfgstats[0].effect.spacing), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"EFFECTSOUND", 0, field(game.conf.object_conf.object_cfgstats[0].effect.sound_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"EFFECTSOUND", 1, field(game.conf.object_conf.object_cfgstats[0].effect.sound_range), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"FLAMEANIMATIONID", 0, field(game.conf.object_conf.object_cfgstats[0].flame.animation_id), 0, INT32_MIN,UINT32_MAX, NULL, value_animid, assign_animid}, - {"FLAMEANIMATIONSPEED", 0, field(game.conf.object_conf.object_cfgstats[0].flame.anim_speed), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"FLAMEANIMATIONSIZE", 0, field(game.conf.object_conf.object_cfgstats[0].flame.sprite_size), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"FLAMEANIMATIONOFFSET", 0, field(game.conf.object_conf.object_cfgstats[0].flame.fp_add_x), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"FLAMEANIMATIONOFFSET", 1, field(game.conf.object_conf.object_cfgstats[0].flame.fp_add_y), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"FLAMEANIMATIONOFFSET", 2, field(game.conf.object_conf.object_cfgstats[0].flame.td_add_x), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"FLAMEANIMATIONOFFSET", 3, field(game.conf.object_conf.object_cfgstats[0].flame.td_add_y), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"FLAMETRANSPARENCYFLAGS", 0, field(game.conf.object_conf.object_cfgstats[0].flame.transparency_flags), 0, INT32_MIN,UINT32_MAX, NULL, value_transpflg, assign_default}, - {"LIGHTFLAGS", 0, field(game.conf.object_conf.object_cfgstats[0].ilght.flags), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"NAME", 0, field_t(struct ObjectConfigStats, code_name), 0, INT32_MIN,UINT32_MAX, object_desc, value_name, assign_null}, + {"GENRE", 0, field_t(struct ObjectConfigStats, genre), 0, INT32_MIN,UINT32_MAX, objects_genres_desc, value_default, assign_default}, + {"RELATEDCREATURE", 0, field_t(struct ObjectConfigStats, related_creatr_model), 0, INT32_MIN,UINT32_MAX, creature_desc, value_default, assign_default}, + {"PROPERTIES", -1, field_t(struct ObjectConfigStats, model_flags), 0, INT32_MIN,UINT32_MAX, objects_properties_commands, value_flagsfield,assign_default}, + {"ANIMATIONID", 0, field_t(struct ObjectConfigStats, sprite_anim_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_animid, assign_animid}, + {"HANDANIMATIONID", 0, field_t(struct ObjectConfigStats, sprite_anim_idx_in_hand), 0, INT32_MIN,UINT32_MAX, NULL, value_animid, assign_animid}, + {"ANIMATIONSPEED", 0, field_t(struct ObjectConfigStats, anim_speed), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"SIZE_XY", 0, field_t(struct ObjectConfigStats, size_xy), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"SIZE_YZ", 0, field_t(struct ObjectConfigStats, size_z), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"SIZE_Z", 0, field_t(struct ObjectConfigStats, size_z), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"MAXIMUMSIZE", 0, field_t(struct ObjectConfigStats, sprite_size_max), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"DESTROYONLIQUID", 0, field_t(struct ObjectConfigStats, destroy_on_liquid), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"DESTROYONLAVA", 0, field_t(struct ObjectConfigStats, destroy_on_lava), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"LAVADESTROYEFFECT", 0, field_t(struct ObjectConfigStats, lava_burn_effect), TngEff_HarmlessGas2, INT32_MIN,UINT32_MAX, NULL, value_effOrEffEl,assign_default}, + {"WATERDESTROYEFFECT", 0, field_t(struct ObjectConfigStats, water_splash_effect),TngEff_Drip3, INT32_MIN,UINT32_MAX, NULL, value_effOrEffEl,assign_default}, + {"HEALTH", 0, field_t(struct ObjectConfigStats, health), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"FALLACCELERATION", 0, field_t(struct ObjectConfigStats, fall_acceleration), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"LIGHTUNAFFECTED", 0, field_t(struct ObjectConfigStats, light_unaffected), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"LIGHTINTENSITY", 0, field_t(struct ObjectConfigStats, ilght.intensity), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"LIGHTRADIUS", 0, field_t(struct ObjectConfigStats, ilght.radius), 0, INT32_MIN,UINT32_MAX, NULL, value_stltocoord,assign_default}, + {"LIGHTISDYNAMIC", 0, field_t(struct ObjectConfigStats, ilght.is_dynamic), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"MAPICON", 0, field_t(struct ObjectConfigStats, map_icon), 0, INT32_MIN,UINT32_MAX, NULL, value_icon, assign_icon}, + {"HANDICON", 0, field_t(struct ObjectConfigStats, hand_icon), 0, INT32_MIN,UINT32_MAX, NULL, value_icon, assign_icon}, + {"PICKUPOFFSET", 0, field_t(struct ObjectConfigStats, object_picked_up_offset.delta_x), 0,SHRT_MIN,SHRT_MAX, NULL, value_default, assign_default}, + {"PICKUPOFFSET", 1, field_t(struct ObjectConfigStats, object_picked_up_offset.delta_y), 0,SHRT_MIN,SHRT_MAX, NULL, value_default, assign_default}, + {"TOOLTIPTEXTID", 0, field_t(struct ObjectConfigStats, tooltip_stridx), GUIStr_Empty, SHRT_MIN, SHRT_MAX, NULL, value_default, assign_default}, + {"TOOLTIPTEXTID", 1, field_t(struct ObjectConfigStats, tooltip_optional), 0, 0, 1, NULL, value_default, assign_default}, + {"AMBIENCESOUND", 0, field_t(struct ObjectConfigStats, fp_smpl_idx), 0, 0,UINT32_MAX, NULL, value_default, assign_default}, + {"UPDATEFUNCTION", 0, field_t(struct ObjectConfigStats, updatefn_idx), 0, INT32_MIN,UINT32_MAX, object_update_functions_desc,value_function, assign_default}, + {"DRAWCLASS", 0, field_t(struct ObjectConfigStats, draw_class), ODC_Default, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"PERSISTENCE", 0, field_t(struct ObjectConfigStats, persistence), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"IMMOBILE", 0, field_t(struct ObjectConfigStats, immobile), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"INITIALSTATE", 0, field_t(struct ObjectConfigStats, initial_state), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"RANDOMSTARTFRAME", 0, field_t(struct ObjectConfigStats, random_start_frame), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"TRANSPARENCYFLAGS", 0, field_t(struct ObjectConfigStats, transparency_flags), 0, INT32_MIN,UINT32_MAX, NULL, value_transpflg, assign_default}, + {"EFFECTBEAM", 0, field_t(struct ObjectConfigStats, effect.beam), 0, INT32_MIN,UINT32_MAX, NULL, value_effOrEffEl,assign_default}, + {"EFFECTPARTICLE", 0, field_t(struct ObjectConfigStats, effect.particle), 0, INT32_MIN,UINT32_MAX, NULL, value_effOrEffEl,assign_default}, + {"EFFECTEXPLOSION1", 0, field_t(struct ObjectConfigStats, effect.explosion1), 0, INT32_MIN,UINT32_MAX, NULL, value_effOrEffEl,assign_default}, + {"EFFECTEXPLOSION2", 0, field_t(struct ObjectConfigStats, effect.explosion2), 0, INT32_MIN,UINT32_MAX, NULL, value_effOrEffEl,assign_default}, + {"EFFECTSPACING", 0, field_t(struct ObjectConfigStats, effect.spacing), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"EFFECTSOUND", 0, field_t(struct ObjectConfigStats, effect.sound_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"EFFECTSOUND", 1, field_t(struct ObjectConfigStats, effect.sound_range), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"FLAMEANIMATIONID", 0, field_t(struct ObjectConfigStats, flame.animation_id), 0, INT32_MIN,UINT32_MAX, NULL, value_animid, assign_animid}, + {"FLAMEANIMATIONSPEED", 0, field_t(struct ObjectConfigStats, flame.anim_speed), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"FLAMEANIMATIONSIZE", 0, field_t(struct ObjectConfigStats, flame.sprite_size), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"FLAMEANIMATIONOFFSET", 0, field_t(struct ObjectConfigStats, flame.fp_add_x), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"FLAMEANIMATIONOFFSET", 1, field_t(struct ObjectConfigStats, flame.fp_add_y), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"FLAMEANIMATIONOFFSET", 2, field_t(struct ObjectConfigStats, flame.td_add_x), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"FLAMEANIMATIONOFFSET", 3, field_t(struct ObjectConfigStats, flame.td_add_y), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"FLAMETRANSPARENCYFLAGS", 0, field_t(struct ObjectConfigStats, flame.transparency_flags), 0, INT32_MIN,UINT32_MAX, NULL, value_transpflg, assign_default}, + {"LIGHTFLAGS", 0, field_t(struct ObjectConfigStats, ilght.flags), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, {NULL}, }; +#pragma pop_macro("game") + +static int32_t* get_objects_count(void) { return &game.conf.object_conf.object_types_count; } +static void* get_objects_base(void) { return game.conf.object_conf.object_cfgstats; } + const struct NamedFieldSet objects_named_fields_set = { - &game.conf.object_conf.object_types_count, + get_objects_count, "object", objects_named_fields, object_desc, OBJECT_TYPES_MAX, sizeof(game.conf.object_conf.object_cfgstats[0]), - game.conf.object_conf.object_cfgstats, + get_objects_base, }; /******************************************************************************/ diff --git a/src/config_rules.c b/src/config_rules.c index 157e75e7cb..7594ee14a3 100644 --- a/src/config_rules.c +++ b/src/config_rules.c @@ -16,6 +16,7 @@ * (at your option) any later version. */ /******************************************************************************/ + #include "pre_inc.h" #include "config_rules.h" #include "globals.h" @@ -75,139 +76,149 @@ const struct NamedCommand rules_game_classicbugs_commands[] = { {NULL, 0}, }; +#pragma push_macro("game") +#undef game static const struct NamedField rules_game_named_fields[] = { //name //param //field //default //min //max //namedCommand //valueFunc - {"POTOFGOLDHOLDS", 0, field(game.conf.rules[0].game.pot_of_gold_holds ), 1000, INT32_MIN, INT32_MAX,NULL, value_default, assign_default}, - {"CHESTGOLDHOLD", 0, field(game.conf.rules[0].game.chest_gold_hold ), 1000, INT32_MIN, INT32_MAX,NULL, value_default, assign_default}, - {"GOLDPILEVALUE", 0, field(game.conf.rules[0].game.gold_pile_value ), 500, INT32_MIN, INT32_MAX,NULL, value_default, assign_default}, - {"GOLDPILEMAXIMUM", 0, field(game.conf.rules[0].game.gold_pile_maximum ), 5000, INT32_MIN, INT32_MAX,NULL, value_default, assign_default}, - {"GOLDPERHOARD", 0, field(game.conf.rules[0].game.gold_per_hoard ), 2000, INT32_MIN, INT32_MAX,NULL, value_default, assign_default}, - {"FOODLIFEOUTOFHATCHERY", 0, field(game.conf.rules[0].game.food_life_out_of_hatchery ), 100, 0, USHRT_MAX,NULL, value_default, assign_default}, - {"BOULDERREDUCEHEALTHSLAP", 0, field(game.conf.rules[0].game.boulder_reduce_health_slap), 10, INT32_MIN, INT32_MAX,NULL, value_default, assign_default}, - {"BOULDERREDUCEHEALTHWALL", 0, field(game.conf.rules[0].game.boulder_reduce_health_wall), 10, INT32_MIN, INT32_MAX,NULL, value_default, assign_default}, - {"BOULDERREDUCEHEALTHROOM", 0, field(game.conf.rules[0].game.boulder_reduce_health_room), 10, INT32_MIN, INT32_MAX,NULL, value_default, assign_default}, - {"PAYDAYGAP", 0, field(game.conf.rules[0].game.pay_day_gap ), 5000, INT32_MIN, INT32_MAX,NULL, value_default, assign_default}, - {"PAYDAYSPEED", 0, field(game.conf.rules[0].game.pay_day_speed ), 100, 0, UINT32_MAX,NULL, value_default, assign_default}, - {"DUNGEONHEARTHEALTIME", 0, field(game.conf.rules[0].game.dungeon_heart_heal_time ), 10, 0, UINT32_MAX,NULL, value_default, assign_default}, - {"DUNGEONHEARTHEALHEALTH", 0, field(game.conf.rules[0].game.dungeon_heart_heal_health ), 1, INT32_MIN, INT32_MAX,NULL, value_default, assign_default}, - {"HERODOORWAITTIME", 0, field(game.conf.rules[0].game.hero_door_wait_time ), 100, 0, UINT32_MAX,NULL, value_default, assign_default}, - {"ROOMSELLGOLDBACKPERCENT", 0, field(game.conf.rules[0].game.room_sale_percent ), 50, 0, INT32_MAX,NULL, value_default, assign_default}, - {"DOORSELLVALUEPERCENT", 0, field(game.conf.rules[0].game.door_sale_percent ), 100, 0, INT32_MAX,NULL, value_default, assign_default}, - {"TRAPSELLVALUEPERCENT", 0, field(game.conf.rules[0].game.trap_sale_percent ), 100, 0, INT32_MAX,NULL, value_default, assign_default}, - {"BAGGOLDHOLD", 0, field(game.conf.rules[0].game.bag_gold_hold ), 200, INT32_MIN, INT32_MAX,NULL, value_default, assign_default}, - {"ALLIESSHAREVISION", 0, field(game.conf.rules[0].game.allies_share_vision ), 0, 0, 1,NULL, value_default, assign_AlliesShareVision_script}, - {"ALLIESSHAREDROP", 0, field(game.conf.rules[0].game.allies_share_drop ), 0, 0, 1,NULL, value_default, assign_default}, - {"ALLIESSHARECTA", 0, field(game.conf.rules[0].game.allies_share_cta ), 0, 0, 1,NULL, value_default, assign_default}, - {"DISPLAYPORTALLIMIT", 0, field(game.conf.rules[0].game.display_portal_limit ), 0, 0, 1,NULL, value_default, assign_default}, - {"MAXTHINGSINHAND", 0, field(game.conf.rules[0].game.max_things_in_hand ), 8, 0, MAX_THINGS_IN_HAND,NULL, value_default, assign_default}, - {"TORTUREPAYDAY", 0, field(game.conf.rules[0].game.torture_payday ), 50, 0, USHRT_MAX,NULL, value_default, assign_default}, - {"TORTURETRAININGCOST", 0, field(game.conf.rules[0].game.torture_training_cost ), 100, SHRT_MIN, SHRT_MAX,NULL, value_default, assign_default}, - {"TORTURESCAVENGINGCOST", 0, field(game.conf.rules[0].game.torture_scavenging_cost ), 100, SHRT_MIN, SHRT_MAX,NULL, value_default, assign_default}, - {"EASTEREGGSPEECHCHANCE", 0, field(game.conf.rules[0].game.easter_egg_speech_chance ), 2000, 0, INT32_MAX,NULL, value_default, assign_default}, - {"EASTEREGGSPEECHINTERVAL", 0, field(game.conf.rules[0].game.easter_egg_speech_interval), 20000, 0, INT32_MAX,NULL, value_default, assign_default}, - {"GLOBALAMBIENTLIGHT", 0, field(game.conf.rules[0].game.global_ambient_light ), 10, 0, INT32_MAX,NULL, value_default, assign_default}, - {"THINGMINIMUMILLUMINATION", 0, field(game.conf.rules[0].game.thing_minimum_illumination), 32, 0, INT32_MAX,NULL, value_default, assign_default}, - {"LIGHTENABLED", 0, field(game.conf.rules[0].game.light_enabled ), 1, 0, 1,NULL, value_default, assign_default}, - {"MAPCREATURELIMIT", 0, field(game.conf.rules[0].game.creatures_count ), 255, 0, CREATURES_COUNT-2,NULL, value_default, assign_MapCreatureLimit_script}, - {"PRESERVECLASSICBUGS", -1, field(game.conf.rules[0].game.classic_bugs_flags ),ClscBug_None,ClscBug_None, ClscBug_ListEnd,rules_game_classicbugs_commands,value_flagsfield, assign_default}, + {"POTOFGOLDHOLDS", 0, field_t(struct RulesConfig, game.pot_of_gold_holds), 1000, INT32_MIN, INT32_MAX,NULL, value_default, assign_default}, + {"CHESTGOLDHOLD", 0, field_t(struct RulesConfig, game.chest_gold_hold), 1000, INT32_MIN, INT32_MAX,NULL, value_default, assign_default}, + {"GOLDPILEVALUE", 0, field_t(struct RulesConfig, game.gold_pile_value), 500, INT32_MIN, INT32_MAX,NULL, value_default, assign_default}, + {"GOLDPILEMAXIMUM", 0, field_t(struct RulesConfig, game.gold_pile_maximum), 5000, INT32_MIN, INT32_MAX,NULL, value_default, assign_default}, + {"GOLDPERHOARD", 0, field_t(struct RulesConfig, game.gold_per_hoard), 2000, INT32_MIN, INT32_MAX,NULL, value_default, assign_default}, + {"FOODLIFEOUTOFHATCHERY", 0, field_t(struct RulesConfig, game.food_life_out_of_hatchery), 100, 0, USHRT_MAX,NULL, value_default, assign_default}, + {"BOULDERREDUCEHEALTHSLAP", 0, field_t(struct RulesConfig, game.boulder_reduce_health_slap), 10, INT32_MIN, INT32_MAX,NULL, value_default, assign_default}, + {"BOULDERREDUCEHEALTHWALL", 0, field_t(struct RulesConfig, game.boulder_reduce_health_wall), 10, INT32_MIN, INT32_MAX,NULL, value_default, assign_default}, + {"BOULDERREDUCEHEALTHROOM", 0, field_t(struct RulesConfig, game.boulder_reduce_health_room), 10, INT32_MIN, INT32_MAX,NULL, value_default, assign_default}, + {"PAYDAYGAP", 0, field_t(struct RulesConfig, game.pay_day_gap), 5000, INT32_MIN, INT32_MAX,NULL, value_default, assign_default}, + {"PAYDAYSPEED", 0, field_t(struct RulesConfig, game.pay_day_speed), 100, 0, UINT32_MAX,NULL, value_default, assign_default}, + {"DUNGEONHEARTHEALTIME", 0, field_t(struct RulesConfig, game.dungeon_heart_heal_time), 10, 0, UINT32_MAX,NULL, value_default, assign_default}, + {"DUNGEONHEARTHEALHEALTH", 0, field_t(struct RulesConfig, game.dungeon_heart_heal_health), 1, INT32_MIN, INT32_MAX,NULL, value_default, assign_default}, + {"HERODOORWAITTIME", 0, field_t(struct RulesConfig, game.hero_door_wait_time), 100, 0, UINT32_MAX,NULL, value_default, assign_default}, + {"ROOMSELLGOLDBACKPERCENT", 0, field_t(struct RulesConfig, game.room_sale_percent), 50, 0, INT32_MAX,NULL, value_default, assign_default}, + {"DOORSELLVALUEPERCENT", 0, field_t(struct RulesConfig, game.door_sale_percent), 100, 0, INT32_MAX,NULL, value_default, assign_default}, + {"TRAPSELLVALUEPERCENT", 0, field_t(struct RulesConfig, game.trap_sale_percent), 100, 0, INT32_MAX,NULL, value_default, assign_default}, + {"BAGGOLDHOLD", 0, field_t(struct RulesConfig, game.bag_gold_hold), 200, INT32_MIN, INT32_MAX,NULL, value_default, assign_default}, + {"ALLIESSHAREVISION", 0, field_t(struct RulesConfig, game.allies_share_vision), 0, 0, 1,NULL, value_default, assign_AlliesShareVision_script}, + {"ALLIESSHAREDROP", 0, field_t(struct RulesConfig, game.allies_share_drop), 0, 0, 1,NULL, value_default, assign_default}, + {"ALLIESSHARECTA", 0, field_t(struct RulesConfig, game.allies_share_cta), 0, 0, 1,NULL, value_default, assign_default}, + {"DISPLAYPORTALLIMIT", 0, field_t(struct RulesConfig, game.display_portal_limit), 0, 0, 1,NULL, value_default, assign_default}, + {"MAXTHINGSINHAND", 0, field_t(struct RulesConfig, game.max_things_in_hand), 8, 0, MAX_THINGS_IN_HAND,NULL, value_default, assign_default}, + {"TORTUREPAYDAY", 0, field_t(struct RulesConfig, game.torture_payday), 50, 0, USHRT_MAX,NULL, value_default, assign_default}, + {"TORTURETRAININGCOST", 0, field_t(struct RulesConfig, game.torture_training_cost), 100, SHRT_MIN, SHRT_MAX,NULL, value_default, assign_default}, + {"TORTURESCAVENGINGCOST", 0, field_t(struct RulesConfig, game.torture_scavenging_cost), 100, SHRT_MIN, SHRT_MAX,NULL, value_default, assign_default}, + {"EASTEREGGSPEECHCHANCE", 0, field_t(struct RulesConfig, game.easter_egg_speech_chance), 2000, 0, INT32_MAX,NULL, value_default, assign_default}, + {"EASTEREGGSPEECHINTERVAL", 0, field_t(struct RulesConfig, game.easter_egg_speech_interval), 20000, 0, INT32_MAX,NULL, value_default, assign_default}, + {"GLOBALAMBIENTLIGHT", 0, field_t(struct RulesConfig, game.global_ambient_light), 10, 0, INT32_MAX,NULL, value_default, assign_default}, + {"THINGMINIMUMILLUMINATION", 0, field_t(struct RulesConfig, game.thing_minimum_illumination), 32, 0, INT32_MAX,NULL, value_default, assign_default}, + {"LIGHTENABLED", 0, field_t(struct RulesConfig, game.light_enabled), 1, 0, 1,NULL, value_default, assign_default}, + {"MAPCREATURELIMIT", 0, field_t(struct RulesConfig, game.creatures_count), 255, 0, CREATURES_COUNT-2,NULL, value_default, assign_MapCreatureLimit_script}, + {"PRESERVECLASSICBUGS", -1, field_t(struct RulesConfig, game.classic_bugs_flags),ClscBug_None,ClscBug_None, ClscBug_ListEnd,rules_game_classicbugs_commands,value_flagsfield, assign_default}, {NULL}, }; static const struct NamedField rules_computer_named_fields[] = { //name //param //field //default //min //max - {"DISEASEHPTEMPLEPERCENTAGE", 0, field(game.conf.rules[0].computer.disease_to_temple_pct),500, 0, USHRT_MAX,NULL,value_default,assign_default}, + {"DISEASEHPTEMPLEPERCENTAGE", 0, field_t(struct RulesConfig, computer.disease_to_temple_pct),500, 0, USHRT_MAX,NULL,value_default,assign_default}, {NULL}, }; static const struct NamedField rules_creatures_named_fields[] = { //name //param //field //default //min //max //namedCommand //valueFunc - {"RECOVERYFREQUENCY", 0, field(game.conf.rules[0].creature.recovery_frequency ) , 10, 0, UCHAR_MAX,NULL,value_default, assign_default}, - {"BODYREMAINSFOR", 0, field(game.conf.rules[0].creature.body_remains_for ) ,1000, 0, USHRT_MAX,NULL,value_default, assign_default}, - {"FLEEZONERADIUS", 0, field(game.conf.rules[0].creature.flee_zone_radius ) ,2048, 0, UINT32_MAX,NULL,value_default, assign_default}, - {"GAMETURNSINFLEE", 0, field(game.conf.rules[0].creature.game_turns_in_flee ) , 200, 0, INT32_MAX,NULL,value_default, assign_default}, - {"GAMETURNSUNCONSCIOUS", 0, field(game.conf.rules[0].creature.game_turns_unconscious) ,2000, 0, USHRT_MAX,NULL,value_default, assign_default}, - {"CRITICALHEALTHPERCENTAGE", 0, field(game.conf.rules[0].creature.critical_health_permil) , 125, 0, 100,NULL,value_x10 , assign_default}, - {"STUNEVILENEMYCHANCE", 0, field(game.conf.rules[0].creature.stun_enemy_chance_evil) , 100, 0, 100,NULL,value_default, assign_default}, - {"STUNGOODENEMYCHANCE", 0, field(game.conf.rules[0].creature.stun_enemy_chance_good) , 100, 0, 100,NULL,value_default, assign_default}, - {"STUNWITHOUTPRISONCHANCE", 0, field(game.conf.rules[0].creature.stun_without_prison_chance), 0, 0, 100,NULL,value_default, assign_default}, + {"RECOVERYFREQUENCY", 0, field_t(struct RulesConfig, creature.recovery_frequency) , 10, 0, UCHAR_MAX,NULL,value_default, assign_default}, + {"BODYREMAINSFOR", 0, field_t(struct RulesConfig, creature.body_remains_for) ,1000, 0, USHRT_MAX,NULL,value_default, assign_default}, + {"FLEEZONERADIUS", 0, field_t(struct RulesConfig, creature.flee_zone_radius) ,2048, 0, UINT32_MAX,NULL,value_default, assign_default}, + {"GAMETURNSINFLEE", 0, field_t(struct RulesConfig, creature.game_turns_in_flee) , 200, 0, INT32_MAX,NULL,value_default, assign_default}, + {"GAMETURNSUNCONSCIOUS", 0, field_t(struct RulesConfig, creature.game_turns_unconscious) ,2000, 0, USHRT_MAX,NULL,value_default, assign_default}, + {"CRITICALHEALTHPERCENTAGE", 0, field_t(struct RulesConfig, creature.critical_health_permil) , 125, 0, 100,NULL,value_x10 , assign_default}, + {"STUNEVILENEMYCHANCE", 0, field_t(struct RulesConfig, creature.stun_enemy_chance_evil) , 100, 0, 100,NULL,value_default, assign_default}, + {"STUNGOODENEMYCHANCE", 0, field_t(struct RulesConfig, creature.stun_enemy_chance_good) , 100, 0, 100,NULL,value_default, assign_default}, + {"STUNWITHOUTPRISONCHANCE", 0, field_t(struct RulesConfig, creature.stun_without_prison_chance), 0, 0, 100,NULL,value_default, assign_default}, {NULL}, }; static const struct NamedField rules_magic_named_fields[] = { //name //param //field //default //min //max //namedCommand //valueFunc - {"HOLDAUDIENCETIME", 0, field(game.conf.rules[0].magic.hold_audience_time ), 500, 0, INT32_MAX,NULL,value_default, assign_default}, - {"ARMAGEDDONTELEPORTYOURTIMEGAP", 0, field(game.conf.rules[0].magic.armageddon_teleport_your_time_gap ), 10, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, - {"ARMAGEDDONTELEPORTENEMYTIMEGAP", 0, field(game.conf.rules[0].magic.armageddon_teleport_enemy_time_gap), 10, 0, INT32_MAX,NULL,value_default, assign_default}, - {"ARMAGEDDONTELEPORTNEUTRALS", 0, field(game.conf.rules[0].magic.armageddon_teleport_neutrals ), 0, 0, 1,NULL,value_default, assign_default}, - {"ARMAGEDDONCOUNTDOWN", 0, field(game.conf.rules[0].magic.armageddon_count_down ), 500, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, - {"ARMAGEDDONDURATION", 0, field(game.conf.rules[0].magic.armageddon_duration ),4000, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, - {"DISEASETRANSFERPERCENTAGE", 0, field(game.conf.rules[0].magic.disease_transfer_percentage ), 15, 0, CHAR_MAX,NULL,value_default, assign_default}, - {"DISEASELOSEPERCENTAGEHEALTH", 0, field(game.conf.rules[0].magic.disease_lose_percentage_health ), 8, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, - {"DISEASELOSEHEALTHTIME", 0, field(game.conf.rules[0].magic.disease_lose_health_time ), 200, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, - {"MINDISTANCEFORTELEPORT", 0, field(game.conf.rules[0].magic.min_distance_for_teleport ), 20, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, - {"COLLAPSEDUNGEONDAMAGE", 0, field(game.conf.rules[0].magic.collapse_dungeon_damage ), 10, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, - {"TURNSPERCOLLAPSEDUNGEONDAMAGE", 0, field(game.conf.rules[0].magic.turns_per_collapse_dngn_dmg ), 4, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, - {"FRIENDLYFIGHTAREARANGEPERCENT", 0, field(game.conf.rules[0].magic.friendly_fight_area_range_percent ), 0, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, - {"FRIENDLYFIGHTAREADAMAGEPERCENT", 0, field(game.conf.rules[0].magic.friendly_fight_area_damage_percent), 0, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, - {"WEIGHTCALCULATEPUSH", 0, field(game.conf.rules[0].magic.weight_calculate_push ), 0, 0, SHRT_MAX,NULL,value_default, assign_default}, - {"ALLOWINSTANTCHARGEUP", 0, field(game.conf.rules[0].magic.allow_instant_charge_up ), 0, 0, 1,NULL,value_default, assign_default}, + {"HOLDAUDIENCETIME", 0, field_t(struct RulesConfig, magic.hold_audience_time), 500, 0, INT32_MAX,NULL,value_default, assign_default}, + {"ARMAGEDDONTELEPORTYOURTIMEGAP", 0, field_t(struct RulesConfig, magic.armageddon_teleport_your_time_gap), 10, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, + {"ARMAGEDDONTELEPORTENEMYTIMEGAP", 0, field_t(struct RulesConfig, magic.armageddon_teleport_enemy_time_gap), 10, 0, INT32_MAX,NULL,value_default, assign_default}, + {"ARMAGEDDONTELEPORTNEUTRALS", 0, field_t(struct RulesConfig, magic.armageddon_teleport_neutrals), 0, 0, 1,NULL,value_default, assign_default}, + {"ARMAGEDDONCOUNTDOWN", 0, field_t(struct RulesConfig, magic.armageddon_count_down), 500, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, + {"ARMAGEDDONDURATION", 0, field_t(struct RulesConfig, magic.armageddon_duration),4000, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, + {"DISEASETRANSFERPERCENTAGE", 0, field_t(struct RulesConfig, magic.disease_transfer_percentage), 15, 0, CHAR_MAX,NULL,value_default, assign_default}, + {"DISEASELOSEPERCENTAGEHEALTH", 0, field_t(struct RulesConfig, magic.disease_lose_percentage_health), 8, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, + {"DISEASELOSEHEALTHTIME", 0, field_t(struct RulesConfig, magic.disease_lose_health_time), 200, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, + {"MINDISTANCEFORTELEPORT", 0, field_t(struct RulesConfig, magic.min_distance_for_teleport), 20, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, + {"COLLAPSEDUNGEONDAMAGE", 0, field_t(struct RulesConfig, magic.collapse_dungeon_damage), 10, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, + {"TURNSPERCOLLAPSEDUNGEONDAMAGE", 0, field_t(struct RulesConfig, magic.turns_per_collapse_dngn_dmg), 4, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, + {"FRIENDLYFIGHTAREARANGEPERCENT", 0, field_t(struct RulesConfig, magic.friendly_fight_area_range_percent), 0, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, + {"FRIENDLYFIGHTAREADAMAGEPERCENT", 0, field_t(struct RulesConfig, magic.friendly_fight_area_damage_percent), 0, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, + {"WEIGHTCALCULATEPUSH", 0, field_t(struct RulesConfig, magic.weight_calculate_push), 0, 0, SHRT_MAX,NULL,value_default, assign_default}, + {"ALLOWINSTANTCHARGEUP", 0, field_t(struct RulesConfig, magic.allow_instant_charge_up), 0, 0, 1,NULL,value_default, assign_default}, {NULL}, }; static const struct NamedField rules_rooms_named_fields[] = { //name //param //field //default //min //max //namedCommand //valueFunc - {"SCAVENGECOSTFREQUENCY", 0, field(game.conf.rules[0].rooms.scavenge_cost_frequency ), 64, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, - {"TEMPLESCAVENGEPROTECTIONTIME", 0, field(game.conf.rules[0].rooms.temple_scavenge_protection_turns),1000, 0, UINT32_MAX,NULL,value_default, assign_default}, - {"TRAINCOSTFREQUENCY", 0, field(game.conf.rules[0].rooms.train_cost_frequency ), 64, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, - {"TORTURECONVERTCHANCE", 0, field(game.conf.rules[0].rooms.torture_convert_chance ), 33, 0, 100,NULL,value_default, assign_default}, - {"TIMESPENTINPRISONWITHOUTBREAK", 0, field(game.conf.rules[0].rooms.time_in_prison_without_break ),2400, 0, UINT32_MAX,NULL,value_default, assign_default}, - {"GHOSTCONVERTCHANCE", 0, field(game.conf.rules[0].rooms.ghost_convert_chance ), 10, 0, 100,NULL,value_default, assign_default}, - {"DEFAULTGENERATESPEED", 0, field(game.conf.rules[0].rooms.default_generate_speed ), 350, 0, USHRT_MAX,NULL,value_default, assign_default}, - {"DEFAULTMAXCREATURESGENERATEENTRANCE", 0, field(game.conf.rules[0].rooms.default_max_crtrs_gen_entrance ), 200, 0, UINT32_MAX,NULL,value_default, assign_default}, - {"FOODGENERATIONSPEED", 0, field(game.conf.rules[0].rooms.food_generation_speed ),2000, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, - {"PRISONSKELETONCHANCE", 0, field(game.conf.rules[0].rooms.prison_skeleton_chance ), 100, 0, 100,NULL,value_default, assign_default}, - {"BODIESFORVAMPIRE", 0, field(game.conf.rules[0].rooms.bodies_for_vampire ), 6, 0, UCHAR_MAX,NULL,value_default, assign_default}, - {"GRAVEYARDCONVERTTIME", 0, field(game.conf.rules[0].rooms.graveyard_convert_time ), 300, 0, USHRT_MAX,NULL,value_default, assign_default}, - {"SCAVENGEGOODALLOWED", 0, field(game.conf.rules[0].rooms.scavenge_good_allowed ), 1, 0, 1,NULL,value_default, assign_default}, - {"SCAVENGENEUTRALALLOWED", 0, field(game.conf.rules[0].rooms.scavenge_neutral_allowed ), 1, 0, 1,NULL,value_default, assign_default}, - {"TIMEBETWEENPRISONBREAK", 0, field(game.conf.rules[0].rooms.time_between_prison_break ), 64, 0, UINT32_MAX,NULL,value_default, assign_default}, - {"PRISONBREAKCHANCE", 0, field(game.conf.rules[0].rooms.prison_break_chance ), 50, 0, UINT32_MAX,NULL,value_default, assign_default}, - {"TORTUREDEATHCHANCE", 0, field(game.conf.rules[0].rooms.torture_death_chance ), 0, 0, 100,NULL,value_default, assign_default}, - {"BARRACKMAXPARTYSIZE", 0, field(game.conf.rules[0].rooms.barrack_max_party_size ), 10, 0, GROUP_MEMBERS_COUNT,NULL,value_default, assign_default}, - {"TRAININGROOMMAXLEVEL", 0, field(game.conf.rules[0].rooms.training_room_max_level ), 0, 0,CREATURE_MAX_LEVEL+1,NULL,value_default, assign_default}, - {"TRAINEFFICIENCY", 0, field(game.conf.rules[0].rooms.train_efficiency ), 256, 0, USHRT_MAX,NULL,value_default, assign_default}, - {"WORKEFFICIENCY", 0, field(game.conf.rules[0].rooms.work_efficiency ), 256, 0, USHRT_MAX,NULL,value_default, assign_default}, - {"RESEARCHEFFICIENCY", 0, field(game.conf.rules[0].rooms.research_efficiency ), 256, 0, USHRT_MAX,NULL,value_default, assign_default}, - {"SCAVENGEEFFICIENCY", 0, field(game.conf.rules[0].rooms.scavenge_efficiency ), 256, 0, USHRT_MAX,NULL,value_default, assign_default}, + {"SCAVENGECOSTFREQUENCY", 0, field_t(struct RulesConfig, rooms.scavenge_cost_frequency), 64, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, + {"TEMPLESCAVENGEPROTECTIONTIME", 0, field_t(struct RulesConfig, rooms.temple_scavenge_protection_turns),1000, 0, UINT32_MAX,NULL,value_default, assign_default}, + {"TRAINCOSTFREQUENCY", 0, field_t(struct RulesConfig, rooms.train_cost_frequency), 64, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, + {"TORTURECONVERTCHANCE", 0, field_t(struct RulesConfig, rooms.torture_convert_chance), 33, 0, 100,NULL,value_default, assign_default}, + {"TIMESPENTINPRISONWITHOUTBREAK", 0, field_t(struct RulesConfig, rooms.time_in_prison_without_break),2400, 0, UINT32_MAX,NULL,value_default, assign_default}, + {"GHOSTCONVERTCHANCE", 0, field_t(struct RulesConfig, rooms.ghost_convert_chance), 10, 0, 100,NULL,value_default, assign_default}, + {"DEFAULTGENERATESPEED", 0, field_t(struct RulesConfig, rooms.default_generate_speed), 350, 0, USHRT_MAX,NULL,value_default, assign_default}, + {"DEFAULTMAXCREATURESGENERATEENTRANCE", 0, field_t(struct RulesConfig, rooms.default_max_crtrs_gen_entrance), 200, 0, UINT32_MAX,NULL,value_default, assign_default}, + {"FOODGENERATIONSPEED", 0, field_t(struct RulesConfig, rooms.food_generation_speed),2000, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, + {"PRISONSKELETONCHANCE", 0, field_t(struct RulesConfig, rooms.prison_skeleton_chance), 100, 0, 100,NULL,value_default, assign_default}, + {"BODIESFORVAMPIRE", 0, field_t(struct RulesConfig, rooms.bodies_for_vampire), 6, 0, UCHAR_MAX,NULL,value_default, assign_default}, + {"GRAVEYARDCONVERTTIME", 0, field_t(struct RulesConfig, rooms.graveyard_convert_time), 300, 0, USHRT_MAX,NULL,value_default, assign_default}, + {"SCAVENGEGOODALLOWED", 0, field_t(struct RulesConfig, rooms.scavenge_good_allowed), 1, 0, 1,NULL,value_default, assign_default}, + {"SCAVENGENEUTRALALLOWED", 0, field_t(struct RulesConfig, rooms.scavenge_neutral_allowed), 1, 0, 1,NULL,value_default, assign_default}, + {"TIMEBETWEENPRISONBREAK", 0, field_t(struct RulesConfig, rooms.time_between_prison_break), 64, 0, UINT32_MAX,NULL,value_default, assign_default}, + {"PRISONBREAKCHANCE", 0, field_t(struct RulesConfig, rooms.prison_break_chance), 50, 0, UINT32_MAX,NULL,value_default, assign_default}, + {"TORTUREDEATHCHANCE", 0, field_t(struct RulesConfig, rooms.torture_death_chance), 0, 0, 100,NULL,value_default, assign_default}, + {"BARRACKMAXPARTYSIZE", 0, field_t(struct RulesConfig, rooms.barrack_max_party_size), 10, 0, GROUP_MEMBERS_COUNT,NULL,value_default, assign_default}, + {"TRAININGROOMMAXLEVEL", 0, field_t(struct RulesConfig, rooms.training_room_max_level), 0, 0,CREATURE_MAX_LEVEL+1,NULL,value_default, assign_default}, + {"TRAINEFFICIENCY", 0, field_t(struct RulesConfig, rooms.train_efficiency), 256, 0, USHRT_MAX,NULL,value_default, assign_default}, + {"WORKEFFICIENCY", 0, field_t(struct RulesConfig, rooms.work_efficiency), 256, 0, USHRT_MAX,NULL,value_default, assign_default}, + {"RESEARCHEFFICIENCY", 0, field_t(struct RulesConfig, rooms.research_efficiency), 256, 0, USHRT_MAX,NULL,value_default, assign_default}, + {"SCAVENGEEFFICIENCY", 0, field_t(struct RulesConfig, rooms.scavenge_efficiency), 256, 0, USHRT_MAX,NULL,value_default, assign_default}, {NULL}, }; static const struct NamedField rules_workers_named_fields[] = { //name //param //field //default //min //max //namedCommand //valueFunc - {"HITSPERSLAB", 0, field(game.conf.rules[0].workers.hits_per_slab ), 2, 0, UCHAR_MAX,NULL,value_default, assign_default}, - {"DEFAULTIMPDIGDAMAGE", 0, field(game.conf.rules[0].workers.default_imp_dig_damage ), 1, 0, UINT32_MAX,NULL,value_default, assign_default}, - {"DEFAULTIMPDIGOWNDAMAGE", 0, field(game.conf.rules[0].workers.default_imp_dig_own_damage ), 2, 0, UINT32_MAX,NULL,value_default, assign_default}, - {"IMPWORKEXPERIENCE", 0, field(game.conf.rules[0].workers.digger_work_experience ), 0, 0, INT32_MAX,NULL,value_default, assign_default}, - {"DRAGUNCONSCIOUSTOLAIR", 0, field(game.conf.rules[0].workers.drag_to_lair ), 0, 0, 2,NULL,value_default, assign_default}, + {"HITSPERSLAB", 0, field_t(struct RulesConfig, workers.hits_per_slab), 2, 0, UCHAR_MAX,NULL,value_default, assign_default}, + {"DEFAULTIMPDIGDAMAGE", 0, field_t(struct RulesConfig, workers.default_imp_dig_damage), 1, 0, UINT32_MAX,NULL,value_default, assign_default}, + {"DEFAULTIMPDIGOWNDAMAGE", 0, field_t(struct RulesConfig, workers.default_imp_dig_own_damage), 2, 0, UINT32_MAX,NULL,value_default, assign_default}, + {"IMPWORKEXPERIENCE", 0, field_t(struct RulesConfig, workers.digger_work_experience), 0, 0, INT32_MAX,NULL,value_default, assign_default}, + {"DRAGUNCONSCIOUSTOLAIR", 0, field_t(struct RulesConfig, workers.drag_to_lair), 0, 0, 2,NULL,value_default, assign_default}, {NULL}, }; static const struct NamedField rules_health_named_fields[] = { //name //param //field //default //min //max //namedCommand //valueFunc - {"HUNGERHEALTHLOSS", 0, field(game.conf.rules[0].health.hunger_health_loss ), 1, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, - {"GAMETURNSPERHUNGERHEALTHLOSS", 0, field(game.conf.rules[0].health.turns_per_hunger_health_loss ),100, 0, USHRT_MAX,NULL,value_default, assign_default}, - {"FOODHEALTHGAIN", 0, field(game.conf.rules[0].health.food_health_gain ), 10, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, - {"TORTUREHEALTHLOSS", 0, field(game.conf.rules[0].health.torture_health_loss ), 5, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, - {"GAMETURNSPERTORTUREHEALTHLOSS", 0, field(game.conf.rules[0].health.turns_per_torture_health_loss),100, 0, USHRT_MAX,NULL,value_default, assign_default}, + {"HUNGERHEALTHLOSS", 0, field_t(struct RulesConfig, health.hunger_health_loss), 1, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, + {"GAMETURNSPERHUNGERHEALTHLOSS", 0, field_t(struct RulesConfig, health.turns_per_hunger_health_loss),100, 0, USHRT_MAX,NULL,value_default, assign_default}, + {"FOODHEALTHGAIN", 0, field_t(struct RulesConfig, health.food_health_gain), 10, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, + {"TORTUREHEALTHLOSS", 0, field_t(struct RulesConfig, health.torture_health_loss), 5, INT32_MIN, INT32_MAX,NULL,value_default, assign_default}, + {"GAMETURNSPERTORTUREHEALTHLOSS", 0, field_t(struct RulesConfig, health.turns_per_torture_health_loss),100, 0, USHRT_MAX,NULL,value_default, assign_default}, {NULL}, }; static const struct NamedField rules_script_only_named_fields[] = { //name //field //min //max -{"PayDayProgress",0,field(game.pay_day_progress[0]),0,0,INT32_MAX,NULL,value_default,assign_default}, +{"PayDayProgress",0,(void*)(ptrdiff_t)(offsetof(struct Game, pay_day_progress) - offsetof(struct Game, conf.rules)), + var_type(((struct Game*)0)->pay_day_progress[0]),0,0,INT32_MAX,NULL,value_default,assign_default}, {NULL}, }; +#pragma pop_macro("game") +// IntelliSense does not reliably restore object-like macros via pop_macro; suppress the false E0020. +#ifdef __INTELLISENSE__ +#endif + +static void* get_rules_base(void) { return game.conf.rules; } + const struct NamedField* ruleblocks[] = {rules_game_named_fields,rules_rooms_named_fields,rules_magic_named_fields, rules_creatures_named_fields,rules_computer_named_fields,rules_workers_named_fields,rules_health_named_fields,rules_script_only_named_fields}; @@ -220,7 +231,7 @@ const struct NamedFieldSet rules_named_fields_set = { NULL, PLAYERS_COUNT, sizeof(game.conf.rules[0]), - &game.conf.rules, + get_rules_base, }; @@ -267,7 +278,10 @@ static void assign_MapCreatureLimit_script(const struct NamedField* named_field, assign_default(named_field,value,named_fields_set,idx,src_str,flags); if (flag_is_set(flags,ccf_DuringLevel)) { +#pragma push_macro("game") +#undef game short count = setup_excess_creatures_to_leave_or_die(game.conf.rules[idx].game.creatures_count); +#pragma pop_macro("game") if (count > 0) { SCRPTLOG("Map creature limit reduced, causing %d creatures to leave or die",count); diff --git a/src/config_terrain.c b/src/config_terrain.c index 755ac0d9ab..07c5a2ca37 100644 --- a/src/config_terrain.c +++ b/src/config_terrain.c @@ -16,6 +16,7 @@ * (at your option) any later version. */ /******************************************************************************/ + #include "pre_inc.h" #include "config_terrain.h" #include "globals.h" @@ -102,73 +103,87 @@ const struct NamedCommand terrain_room_total_capacity_func_type[] = { {NULL, 0}, }; +#pragma push_macro("game") +#undef game static const struct NamedField terrain_slab_named_fields[] = { //name //field //default //min //max //NamedCommand - {"NAME", 0, field(game.conf.slab_conf.slab_cfgstats[0].code_name), 0, INT32_MIN,UINT32_MAX, slab_desc, value_name, assign_null}, - {"TOOLTIPTEXTID", 0, field(game.conf.slab_conf.slab_cfgstats[0].tooltip_stridx), GUIStr_Empty, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"BLOCKFLAGSHEIGHT", 0, field(game.conf.slab_conf.slab_cfgstats[0].block_flags_height), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"BLOCKHEALTHINDEX", 0, field(game.conf.slab_conf.slab_cfgstats[0].block_health_index), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"BLOCKFLAGS", -1, field(game.conf.slab_conf.slab_cfgstats[0].block_flags), 0, INT32_MIN,UINT32_MAX, terrain_flags, value_flagsfield, assign_default}, - {"NOBLOCKFLAGS", -1, field(game.conf.slab_conf.slab_cfgstats[0].noblck_flags), 0, INT32_MIN,UINT32_MAX, terrain_flags, value_flagsfield, assign_default}, - {"FILLSTYLE", 0, field(game.conf.slab_conf.slab_cfgstats[0].fill_style), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"CATEGORY", 0, field(game.conf.slab_conf.slab_cfgstats[0].category), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"SLBID", 0, field(game.conf.slab_conf.slab_cfgstats[0].slb_id), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"WIBBLE", 0, field(game.conf.slab_conf.slab_cfgstats[0].wibble), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"ISSAFELAND", 0, field(game.conf.slab_conf.slab_cfgstats[0].is_safe_land), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"ISDIGGABLE", 0, field(game.conf.slab_conf.slab_cfgstats[0].is_diggable), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"WLBTYPE", 0, field(game.conf.slab_conf.slab_cfgstats[0].wlb_type), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"ANIMATED", 0, field(game.conf.slab_conf.slab_cfgstats[0].animated), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"ISOWNABLE", 0, field(game.conf.slab_conf.slab_cfgstats[0].is_ownable), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"INDESTRUCTIBLE", 0, field(game.conf.slab_conf.slab_cfgstats[0].indestructible), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"GOLDHELD", 0, field(game.conf.slab_conf.slab_cfgstats[0].gold_held), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"NAME", 0, field_t(struct SlabConfigStats, code_name), 0, INT32_MIN,UINT32_MAX, slab_desc, value_name, assign_null}, + {"TOOLTIPTEXTID", 0, field_t(struct SlabConfigStats, tooltip_stridx), GUIStr_Empty, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"BLOCKFLAGSHEIGHT", 0, field_t(struct SlabConfigStats, block_flags_height), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"BLOCKHEALTHINDEX", 0, field_t(struct SlabConfigStats, block_health_index), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"BLOCKFLAGS", -1, field_t(struct SlabConfigStats, block_flags), 0, INT32_MIN,UINT32_MAX, terrain_flags, value_flagsfield, assign_default}, + {"NOBLOCKFLAGS", -1, field_t(struct SlabConfigStats, noblck_flags), 0, INT32_MIN,UINT32_MAX, terrain_flags, value_flagsfield, assign_default}, + {"FILLSTYLE", 0, field_t(struct SlabConfigStats, fill_style), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"CATEGORY", 0, field_t(struct SlabConfigStats, category), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"SLBID", 0, field_t(struct SlabConfigStats, slb_id), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"WIBBLE", 0, field_t(struct SlabConfigStats, wibble), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"ISSAFELAND", 0, field_t(struct SlabConfigStats, is_safe_land), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"ISDIGGABLE", 0, field_t(struct SlabConfigStats, is_diggable), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"WLBTYPE", 0, field_t(struct SlabConfigStats, wlb_type), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"ANIMATED", 0, field_t(struct SlabConfigStats, animated), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"ISOWNABLE", 0, field_t(struct SlabConfigStats, is_ownable), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"INDESTRUCTIBLE", 0, field_t(struct SlabConfigStats, indestructible), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"GOLDHELD", 0, field_t(struct SlabConfigStats, gold_held), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, {NULL}, }; +#pragma pop_macro("game") + +static int32_t* get_slab_count(void) { return &game.conf.slab_conf.slab_types_count; } +static void* get_slab_base(void) { return game.conf.slab_conf.slab_cfgstats; } + const struct NamedFieldSet terrain_slab_named_fields_set = { - &game.conf.slab_conf.slab_types_count, + get_slab_count, "slab", terrain_slab_named_fields, slab_desc, TERRAIN_ITEMS_MAX, sizeof(game.conf.slab_conf.slab_cfgstats[0]), - game.conf.slab_conf.slab_cfgstats, + get_slab_base, }; +#pragma push_macro("game") +#undef game static const struct NamedField terrain_room_named_fields[] = { //name //pos //field //default //min //max //NamedCommand - {"NAME", 0, field(game.conf.slab_conf.room_cfgstats[0].code_name), 0, INT32_MIN,UINT32_MAX, room_desc, value_name, assign_null}, - {"COST", 0, field(game.conf.slab_conf.room_cfgstats[0].cost), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"HEALTH", 0, field(game.conf.slab_conf.room_cfgstats[0].health), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"PROPERTIES", -1, field(game.conf.slab_conf.room_cfgstats[0].flags), 0, INT32_MIN,RoCFlg_ListEnd, terrain_room_properties_commands, value_flagsfield,assign_default}, - {"SLABASSIGN", 0, field(game.conf.slab_conf.room_cfgstats[0].assigned_slab), 0, INT32_MIN,UINT32_MAX, slab_desc, value_default, assign_default}, - {"CREATURECREATION", 0, field(game.conf.slab_conf.room_cfgstats[0].creature_creation_model), 0, INT32_MIN,UINT32_MAX, creature_desc, value_default, assign_default}, - {"MESSAGES", 0, field(game.conf.slab_conf.room_cfgstats[0].msg_needed), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"MESSAGES", 1, field(game.conf.slab_conf.room_cfgstats[0].msg_too_small), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"MESSAGES", 2, field(game.conf.slab_conf.room_cfgstats[0].msg_no_route), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"NAMETEXTID", 0, field(game.conf.slab_conf.room_cfgstats[0].name_stridx), GUIStr_Empty, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"TOOLTIPTEXTID", 0, field(game.conf.slab_conf.room_cfgstats[0].tooltip_stridx), GUIStr_Empty, INT32_MIN,UINT32_MAX, NULL, value_default, assign_update_room_tab}, - {"SYMBOLSPRITES", 0, field(game.conf.slab_conf.room_cfgstats[0].bigsym_sprite_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_icon, assign_icon}, - {"SYMBOLSPRITES", 1, field(game.conf.slab_conf.room_cfgstats[0].medsym_sprite_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_icon, assign_icon_update_room_tab}, - {"POINTERSPRITES", 0, field(game.conf.slab_conf.room_cfgstats[0].pointer_sprite_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_icon, assign_icon_update_room_tab}, - {"PANELTABINDEX", 0, field(game.conf.slab_conf.room_cfgstats[0].panel_tab_idx), 0, 0, 32, NULL, value_default, assign_update_room_tab}, - {"TOTALCAPACITY", 0, field(game.conf.slab_conf.room_cfgstats[0].update_total_capacity_idx), 0, INT32_MIN,UINT32_MAX, terrain_room_total_capacity_func_type,value_default, assign_reinitialise_rooms}, - {"USEDCAPACITY", 0, field(game.conf.slab_conf.room_cfgstats[0].update_storage_in_room_idx), 0, INT32_MIN,UINT32_MAX, terrain_room_used_capacity_func_type, value_default, assign_default}, - {"USEDCAPACITY", 1, field(game.conf.slab_conf.room_cfgstats[0].update_workers_in_room_idx), 0, INT32_MIN,UINT32_MAX, terrain_room_used_capacity_func_type, value_default, assign_reinitialise_rooms}, - {"SLABSYNERGY", 0, field(game.conf.slab_conf.room_cfgstats[0].synergy_slab), 0, INT32_MIN,UINT32_MAX, slab_desc, value_synergy, assign_recalculate_effeciency}, - {"AMBIENTSNDSAMPLE", 0, field(game.conf.slab_conf.room_cfgstats[0].ambient_snd_smp_id), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, - {"ROLES", -1, field(game.conf.slab_conf.room_cfgstats[0].roles), 0, INT32_MIN,UINT32_MAX, room_roles_desc, value_flagsfield,assign_default}, - {"STORAGEHEIGHT", 0, field(game.conf.slab_conf.room_cfgstats[0].storage_height), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"NAME", 0, field_t(struct RoomConfigStats, code_name), 0, INT32_MIN,UINT32_MAX, room_desc, value_name, assign_null}, + {"COST", 0, field_t(struct RoomConfigStats, cost), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"HEALTH", 0, field_t(struct RoomConfigStats, health), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"PROPERTIES", -1, field_t(struct RoomConfigStats, flags), 0, INT32_MIN,RoCFlg_ListEnd, terrain_room_properties_commands, value_flagsfield,assign_default}, + {"SLABASSIGN", 0, field_t(struct RoomConfigStats, assigned_slab), 0, INT32_MIN,UINT32_MAX, slab_desc, value_default, assign_default}, + {"CREATURECREATION", 0, field_t(struct RoomConfigStats, creature_creation_model), 0, INT32_MIN,UINT32_MAX, creature_desc, value_default, assign_default}, + {"MESSAGES", 0, field_t(struct RoomConfigStats, msg_needed), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"MESSAGES", 1, field_t(struct RoomConfigStats, msg_too_small), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"MESSAGES", 2, field_t(struct RoomConfigStats, msg_no_route), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"NAMETEXTID", 0, field_t(struct RoomConfigStats, name_stridx), GUIStr_Empty, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"TOOLTIPTEXTID", 0, field_t(struct RoomConfigStats, tooltip_stridx), GUIStr_Empty, INT32_MIN,UINT32_MAX, NULL, value_default, assign_update_room_tab}, + {"SYMBOLSPRITES", 0, field_t(struct RoomConfigStats, bigsym_sprite_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_icon, assign_icon}, + {"SYMBOLSPRITES", 1, field_t(struct RoomConfigStats, medsym_sprite_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_icon, assign_icon_update_room_tab}, + {"POINTERSPRITES", 0, field_t(struct RoomConfigStats, pointer_sprite_idx), 0, INT32_MIN,UINT32_MAX, NULL, value_icon, assign_icon_update_room_tab}, + {"PANELTABINDEX", 0, field_t(struct RoomConfigStats, panel_tab_idx), 0, 0, 32, NULL, value_default, assign_update_room_tab}, + {"TOTALCAPACITY", 0, field_t(struct RoomConfigStats, update_total_capacity_idx), 0, INT32_MIN,UINT32_MAX, terrain_room_total_capacity_func_type,value_default, assign_reinitialise_rooms}, + {"USEDCAPACITY", 0, field_t(struct RoomConfigStats, update_storage_in_room_idx), 0, INT32_MIN,UINT32_MAX, terrain_room_used_capacity_func_type, value_default, assign_default}, + {"USEDCAPACITY", 1, field_t(struct RoomConfigStats, update_workers_in_room_idx), 0, INT32_MIN,UINT32_MAX, terrain_room_used_capacity_func_type, value_default, assign_reinitialise_rooms}, + {"SLABSYNERGY", 0, field_t(struct RoomConfigStats, synergy_slab), 0, INT32_MIN,UINT32_MAX, slab_desc, value_synergy, assign_recalculate_effeciency}, + {"AMBIENTSNDSAMPLE", 0, field_t(struct RoomConfigStats, ambient_snd_smp_id), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, + {"ROLES", -1, field_t(struct RoomConfigStats, roles), 0, INT32_MIN,UINT32_MAX, room_roles_desc, value_flagsfield,assign_default}, + {"STORAGEHEIGHT", 0, field_t(struct RoomConfigStats, storage_height), 0, INT32_MIN,UINT32_MAX, NULL, value_default, assign_default}, {NULL}, }; +#pragma pop_macro("game") + +static int32_t* get_room_count(void) { return &game.conf.slab_conf.room_types_count; } +static void* get_room_base(void) { return game.conf.slab_conf.room_cfgstats; } + const struct NamedFieldSet terrain_room_named_fields_set = { - &game.conf.slab_conf.room_types_count, + get_room_count, "room", terrain_room_named_fields, room_desc, TERRAIN_ITEMS_MAX, sizeof(game.conf.slab_conf.room_cfgstats[0]), - game.conf.slab_conf.room_cfgstats, + get_room_base, }; static void assign_update_room_tab(const struct NamedField* named_field, int64_t value, const struct NamedFieldSet* named_fields_set, int idx, const char* src_str, unsigned char flags) diff --git a/src/config_trapdoor.c b/src/config_trapdoor.c index 70c34cee2b..91b785b3e9 100644 --- a/src/config_trapdoor.c +++ b/src/config_trapdoor.c @@ -16,6 +16,7 @@ * (at your option) any later version. */ /******************************************************************************/ + #include "pre_inc.h" #include "config_trapdoor.h" #include "globals.h" @@ -252,121 +253,135 @@ static void assign_refresh_trap_anim_anim_id(const struct NamedField* named_fiel } } +#pragma push_macro("game") +#undef game const struct NamedField trapdoor_door_named_fields[] = { //name //pos //field //default //min //max //NamedCommand - {"NAME", 0, field(game.conf.trapdoor_conf.door_cfgstats[0].code_name), 0, INT32_MIN, UINT32_MAX, door_desc, value_name, assign_null}, - {"NAMETEXTID", 0, field(game.conf.trapdoor_conf.door_cfgstats[0].name_stridx), GUIStr_Empty, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"TOOLTIPTEXTID", 0, field(game.conf.trapdoor_conf.door_cfgstats[0].tooltip_stridx),GUIStr_Empty, INT32_MIN, UINT32_MAX, NULL, value_default, assign_tooltip_idx_door}, - {"SYMBOLSPRITES", 0, field(game.conf.trapdoor_conf.door_cfgstats[0].bigsym_sprite_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_icon, assign_icon}, - {"SYMBOLSPRITES", 1, field(game.conf.trapdoor_conf.door_cfgstats[0].medsym_sprite_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_icon, assign_icon_update_trap_tab}, - {"POINTERSPRITES", 0, field(game.conf.trapdoor_conf.door_cfgstats[0].pointer_sprite_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_icon, assign_icon_update_trap_tab}, - {"PANELTABINDEX", 0, field(game.conf.trapdoor_conf.door_cfgstats[0].panel_tab_idx), 0, 0, 32, NULL, value_default, assign_panel_tab_idx_door}, + {"NAME", 0, field_t(struct DoorConfigStats, code_name), 0, INT32_MIN, UINT32_MAX, door_desc, value_name, assign_null}, + {"NAMETEXTID", 0, field_t(struct DoorConfigStats, name_stridx), GUIStr_Empty, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"TOOLTIPTEXTID", 0, field_t(struct DoorConfigStats, tooltip_stridx),GUIStr_Empty, INT32_MIN, UINT32_MAX, NULL, value_default, assign_tooltip_idx_door}, + {"SYMBOLSPRITES", 0, field_t(struct DoorConfigStats, bigsym_sprite_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_icon, assign_icon}, + {"SYMBOLSPRITES", 1, field_t(struct DoorConfigStats, medsym_sprite_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_icon, assign_icon_update_trap_tab}, + {"POINTERSPRITES", 0, field_t(struct DoorConfigStats, pointer_sprite_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_icon, assign_icon_update_trap_tab}, + {"PANELTABINDEX", 0, field_t(struct DoorConfigStats, panel_tab_idx), 0, 0, 32, NULL, value_default, assign_panel_tab_idx_door}, {"CRATE", 0, NULL,0, 0, INT32_MIN, UINT32_MAX, object_desc, value_default, assign_crate_door}, - {"MANUFACTURELEVEL", 0, field(game.conf.trapdoor_conf.door_cfgstats[0].manufct_level), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"MANUFACTUREREQUIRED", 0, field(game.conf.trapdoor_conf.door_cfgstats[0].manufct_required), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"HEALTH", 0, field(game.conf.trapdoor_conf.door_cfgstats[0].health), 1, INT32_MIN, UINT32_MAX, NULL, value_default, assign_update_door_stats}, - {"SLABKIND", 0, field(game.conf.trapdoor_conf.door_cfgstats[0].slbkind[1]), 0, 0, TERRAIN_ITEMS_MAX, slab_desc, value_default, assign_default}, - {"SLABKIND", 0, field(game.conf.trapdoor_conf.door_cfgstats[0].slbkind[0]), 0, 0, TERRAIN_ITEMS_MAX, slab_desc, value_default, assign_update_door_stats}, - {"OPENSPEED", 0, field(game.conf.trapdoor_conf.door_cfgstats[0].open_speed), 256, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"PROPERTIES", -1, field(game.conf.trapdoor_conf.door_cfgstats[0].model_flags), 0, INT32_MIN, UINT32_MAX, door_properties_commands, value_flagsfield, assign_default}, - {"SELLINGVALUE", 0, field(game.conf.trapdoor_conf.door_cfgstats[0].selling_value), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"UNSELLABLE", 0, field(game.conf.trapdoor_conf.door_cfgstats[0].unsellable), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"PLACESOUND", 0, field(game.conf.trapdoor_conf.door_cfgstats[0].place_sound_idx), 117, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"UPDATEFUNCTION", 0, field(game.conf.trapdoor_conf.door_cfgstats[0].updatefn_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_function, assign_default}, + {"MANUFACTURELEVEL", 0, field_t(struct DoorConfigStats, manufct_level), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"MANUFACTUREREQUIRED", 0, field_t(struct DoorConfigStats, manufct_required), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"HEALTH", 0, field_t(struct DoorConfigStats, health), 1, INT32_MIN, UINT32_MAX, NULL, value_default, assign_update_door_stats}, + {"SLABKIND", 0, field_a(struct DoorConfigStats, slbkind, 1), 0, 0, TERRAIN_ITEMS_MAX, slab_desc, value_default, assign_default}, + {"SLABKIND", 0, field_a(struct DoorConfigStats, slbkind, 0), 0, 0, TERRAIN_ITEMS_MAX, slab_desc, value_default, assign_update_door_stats}, + {"OPENSPEED", 0, field_t(struct DoorConfigStats, open_speed), 256, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"PROPERTIES", -1, field_t(struct DoorConfigStats, model_flags), 0, INT32_MIN, UINT32_MAX, door_properties_commands, value_flagsfield, assign_default}, + {"SELLINGVALUE", 0, field_t(struct DoorConfigStats, selling_value), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"UNSELLABLE", 0, field_t(struct DoorConfigStats, unsellable), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"PLACESOUND", 0, field_t(struct DoorConfigStats, place_sound_idx), 117, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"UPDATEFUNCTION", 0, field_t(struct DoorConfigStats, updatefn_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_function, assign_default}, {NULL}, }; +#pragma pop_macro("game") + +static int32_t* get_door_count(void) { return &game.conf.trapdoor_conf.door_types_count; } +static void* get_door_base(void) { return game.conf.trapdoor_conf.door_cfgstats; } + const struct NamedFieldSet trapdoor_door_named_fields_set = { - &game.conf.trapdoor_conf.door_types_count, + get_door_count, "door", trapdoor_door_named_fields, door_desc, TRAPDOOR_TYPES_MAX, sizeof(game.conf.trapdoor_conf.door_cfgstats[0]), - game.conf.trapdoor_conf.door_cfgstats, + get_door_base, }; +#pragma push_macro("game") +#undef game const struct NamedField trapdoor_trap_named_fields[] = { //name //pos //field //default //min //max //NamedCommand - {"NAME", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].code_name), 0, INT32_MIN, UINT32_MAX, door_desc, value_name, assign_null}, - {"MANUFACTURELEVEL", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].manufct_level), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"MANUFACTUREREQUIRED", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].manufct_required), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"SHOTS", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].shots), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"TIMEBETWEENSHOTS", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].shots_delay), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"SELLINGVALUE", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].selling_value), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"NAMETEXTID", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].name_stridx), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"TOOLTIPTEXTID", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].tooltip_stridx), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_tooltip_idx_trap}, - {"CRATE", 0, NULL,0, 0, INT32_MIN, UINT32_MAX, object_desc, value_default, assign_crate_trap}, - {"SYMBOLSPRITES", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].bigsym_sprite_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_icon, assign_icon}, - {"SYMBOLSPRITES", 1, field(game.conf.trapdoor_conf.trap_cfgstats[0].medsym_sprite_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_icon, assign_icon_update_trap_tab}, - {"POINTERSPRITES", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].pointer_sprite_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_icon, assign_icon_update_trap_tab}, - {"PANELTABINDEX", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].panel_tab_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_panel_tab_idx_trap}, - {"TRIGGERTYPE", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].trigger_type), 0, INT32_MIN, UINT32_MAX, trap_trigger_type_commands,value_default, assign_default}, - {"ACTIVATIONTYPE", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].activation_type), 0, INT32_MIN, UINT32_MAX, trap_activation_type_commands,value_default, assign_default}, - {"ACTIVATIONLUAFUNC", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].activation_lua_func_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_function, assign_default}, - {"EFFECTTYPE", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].created_itm_model), 0, INT32_MIN, UINT32_MAX, NULL, value_activationeffect, assign_default}, - {"ACTIVATIONLEVEL", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].activation_level), 0, 0, 9, NULL, value_min1, assign_default}, - {"ANIMATIONID", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].sprite_anim_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_animid, assign_refresh_trap_anim_anim_id}, - {"MODEL", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].sprite_anim_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_animid, assign_refresh_trap_anim_anim_id}, // Backward compatibility. - {"RECHARGEANIMATIONID", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].recharge_sprite_anim_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_animid, assign_refresh_trap_anim_anim_id}, - {"ATTACKANIMATIONID", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].attack_sprite_anim_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_animid, assign_animid}, - {"MODELSIZE", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].sprite_size_max), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_refresh_trap_anim}, - {"ANIMATIONSPEED", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].anim_speed), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_multiple_refresh_trap_anim}, - {"ATTACKANIMATIONSPEED", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].attack_anim_speed), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_refresh_trap_anim}, - {"RECHARGEANIMATIONSPEED", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].recharge_anim_speed), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_refresh_trap_anim}, - {"UNANIMATED", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].unanimated), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_refresh_trap_anim}, - {"HIDDEN", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].hidden), true, 0, 1, NULL, value_default, assign_default}, - {"SLAPPABLE", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].slappable), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"TRIGGERALARM", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].notify), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"HEALTH", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].health), 1, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"UNSHADED", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].unshaded), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"RANDOMSTARTFRAME", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].random_start_frame), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"THINGSIZE", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].size_xy), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"THINGSIZE", 1, field(game.conf.trapdoor_conf.trap_cfgstats[0].size_z), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"HITTYPE", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].hit_type), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"LIGHTRADIUS", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].light_radius), 0, INT32_MIN, UINT32_MAX, NULL, value_stltocoord, assign_default}, - {"LIGHTINTENSITY", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].light_intensity), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"LIGHTFLAGS", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].light_flag), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"TRANSPARENCYFLAGS", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].transparency_flag), 0, INT32_MIN, UINT32_MAX, NULL, value_transpflg, assign_default}, - {"SHOTVECTOR", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].shotvector.x), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"SHOTVECTOR", 1, field(game.conf.trapdoor_conf.trap_cfgstats[0].shotvector.y), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"SHOTVECTOR", 2, field(game.conf.trapdoor_conf.trap_cfgstats[0].shotvector.z), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"DESTRUCTIBLE", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].destructible), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"UNSTABLE", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].unstable), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"UNSELLABLE", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].unsellable), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"PLACEONBRIDGE", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].place_on_bridge), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"SHOTORIGIN", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].shot_shift_x), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"SHOTORIGIN", 1, field(game.conf.trapdoor_conf.trap_cfgstats[0].shot_shift_y), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"SHOTORIGIN", 2, field(game.conf.trapdoor_conf.trap_cfgstats[0].shot_shift_z), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"PLACESOUND", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].place_sound_idx), 117, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"TRIGGERSOUND", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].trigger_sound_idx), 176, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"DESTROYEDEFFECT", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].destroyed_effect), -TngEffElm_Blast2, INT32_MIN, UINT32_MAX, NULL, value_effOrEffEl, assign_default}, - {"INITIALDELAY", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].initial_delay), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"PLACEONSUBTILE", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].place_on_subtile), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"FLAMEANIMATIONID", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].flame.animation_id), 0, INT32_MIN, UINT32_MAX, NULL, value_animid, assign_refresh_trap_anim_anim_id}, - {"FLAMEANIMATIONSPEED", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].flame.anim_speed), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"FLAMEANIMATIONSIZE", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].flame.sprite_size), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"FLAMEANIMATIONOFFSET", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].flame.fp_add_x), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"FLAMEANIMATIONOFFSET", 1, field(game.conf.trapdoor_conf.trap_cfgstats[0].flame.fp_add_y), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"FLAMEANIMATIONOFFSET", 2, field(game.conf.trapdoor_conf.trap_cfgstats[0].flame.td_add_x), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"FLAMEANIMATIONOFFSET", 3, field(game.conf.trapdoor_conf.trap_cfgstats[0].flame.td_add_y), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"FLAMETRANSPARENCYFLAGS", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].flame.transparency_flags), 0, INT32_MIN, UINT32_MAX, NULL, value_transpflg, assign_default}, - {"DETECTINVISIBLE", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].detect_invisible), true, 0, 1, NULL, value_default, assign_default}, - {"INSTANTPLACEMENT", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].instant_placement), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"REMOVEONCEDEPLETED", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].remove_once_depleted), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"FLAGNUMBER", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].flag_number), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, - {"UPDATEFUNCTION", 0, field(game.conf.trapdoor_conf.trap_cfgstats[0].updatefn_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_function,assign_default}, + {"NAME", 0, field_t(struct TrapConfigStats, code_name), 0, INT32_MIN, UINT32_MAX, door_desc, value_name, assign_null}, + {"MANUFACTURELEVEL", 0, field_t(struct TrapConfigStats, manufct_level), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"MANUFACTUREREQUIRED", 0, field_t(struct TrapConfigStats, manufct_required), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"SHOTS", 0, field_t(struct TrapConfigStats, shots), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"TIMEBETWEENSHOTS", 0, field_t(struct TrapConfigStats, shots_delay), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"SELLINGVALUE", 0, field_t(struct TrapConfigStats, selling_value), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"NAMETEXTID", 0, field_t(struct TrapConfigStats, name_stridx), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"TOOLTIPTEXTID", 0, field_t(struct TrapConfigStats, tooltip_stridx), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_tooltip_idx_trap}, + {"CRATE", 0, NULL,0, 0, INT32_MIN, UINT32_MAX, object_desc, value_default, assign_crate_trap}, + {"SYMBOLSPRITES", 0, field_t(struct TrapConfigStats, bigsym_sprite_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_icon, assign_icon}, + {"SYMBOLSPRITES", 1, field_t(struct TrapConfigStats, medsym_sprite_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_icon, assign_icon_update_trap_tab}, + {"POINTERSPRITES", 0, field_t(struct TrapConfigStats, pointer_sprite_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_icon, assign_icon_update_trap_tab}, + {"PANELTABINDEX", 0, field_t(struct TrapConfigStats, panel_tab_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_panel_tab_idx_trap}, + {"TRIGGERTYPE", 0, field_t(struct TrapConfigStats, trigger_type), 0, INT32_MIN, UINT32_MAX, trap_trigger_type_commands,value_default, assign_default}, + {"ACTIVATIONTYPE", 0, field_t(struct TrapConfigStats, activation_type), 0, INT32_MIN, UINT32_MAX, trap_activation_type_commands,value_default, assign_default}, + {"ACTIVATIONLUAFUNC", 0, field_t(struct TrapConfigStats, activation_lua_func_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_function, assign_default}, + {"EFFECTTYPE", 0, field_t(struct TrapConfigStats, created_itm_model), 0, INT32_MIN, UINT32_MAX, NULL, value_activationeffect, assign_default}, + {"ACTIVATIONLEVEL", 0, field_t(struct TrapConfigStats, activation_level), 0, 0, 9, NULL, value_min1, assign_default}, + {"ANIMATIONID", 0, field_t(struct TrapConfigStats, sprite_anim_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_animid, assign_refresh_trap_anim_anim_id}, + {"MODEL", 0, field_t(struct TrapConfigStats, sprite_anim_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_animid, assign_refresh_trap_anim_anim_id}, // Backward compatibility. + {"RECHARGEANIMATIONID", 0, field_t(struct TrapConfigStats, recharge_sprite_anim_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_animid, assign_refresh_trap_anim_anim_id}, + {"ATTACKANIMATIONID", 0, field_t(struct TrapConfigStats, attack_sprite_anim_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_animid, assign_animid}, + {"MODELSIZE", 0, field_t(struct TrapConfigStats, sprite_size_max), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_refresh_trap_anim}, + {"ANIMATIONSPEED", 0, field_t(struct TrapConfigStats, anim_speed), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_multiple_refresh_trap_anim}, + {"ATTACKANIMATIONSPEED", 0, field_t(struct TrapConfigStats, attack_anim_speed), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_refresh_trap_anim}, + {"RECHARGEANIMATIONSPEED", 0, field_t(struct TrapConfigStats, recharge_anim_speed), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_refresh_trap_anim}, + {"UNANIMATED", 0, field_t(struct TrapConfigStats, unanimated), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_refresh_trap_anim}, + {"HIDDEN", 0, field_t(struct TrapConfigStats, hidden), true, 0, 1, NULL, value_default, assign_default}, + {"SLAPPABLE", 0, field_t(struct TrapConfigStats, slappable), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"TRIGGERALARM", 0, field_t(struct TrapConfigStats, notify), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"HEALTH", 0, field_t(struct TrapConfigStats, health), 1, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"UNSHADED", 0, field_t(struct TrapConfigStats, unshaded), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"RANDOMSTARTFRAME", 0, field_t(struct TrapConfigStats, random_start_frame), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"THINGSIZE", 0, field_t(struct TrapConfigStats, size_xy), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"THINGSIZE", 1, field_t(struct TrapConfigStats, size_z), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"HITTYPE", 0, field_t(struct TrapConfigStats, hit_type), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"LIGHTRADIUS", 0, field_t(struct TrapConfigStats, light_radius), 0, INT32_MIN, UINT32_MAX, NULL, value_stltocoord, assign_default}, + {"LIGHTINTENSITY", 0, field_t(struct TrapConfigStats, light_intensity), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"LIGHTFLAGS", 0, field_t(struct TrapConfigStats, light_flag), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"TRANSPARENCYFLAGS", 0, field_t(struct TrapConfigStats, transparency_flag), 0, INT32_MIN, UINT32_MAX, NULL, value_transpflg, assign_default}, + {"SHOTVECTOR", 0, field_t(struct TrapConfigStats, shotvector.x), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"SHOTVECTOR", 1, field_t(struct TrapConfigStats, shotvector.y), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"SHOTVECTOR", 2, field_t(struct TrapConfigStats, shotvector.z), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"DESTRUCTIBLE", 0, field_t(struct TrapConfigStats, destructible), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"UNSTABLE", 0, field_t(struct TrapConfigStats, unstable), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"UNSELLABLE", 0, field_t(struct TrapConfigStats, unsellable), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"PLACEONBRIDGE", 0, field_t(struct TrapConfigStats, place_on_bridge), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"SHOTORIGIN", 0, field_t(struct TrapConfigStats, shot_shift_x), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"SHOTORIGIN", 1, field_t(struct TrapConfigStats, shot_shift_y), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"SHOTORIGIN", 2, field_t(struct TrapConfigStats, shot_shift_z), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"PLACESOUND", 0, field_t(struct TrapConfigStats, place_sound_idx), 117, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"TRIGGERSOUND", 0, field_t(struct TrapConfigStats, trigger_sound_idx), 176, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"DESTROYEDEFFECT", 0, field_t(struct TrapConfigStats, destroyed_effect), -TngEffElm_Blast2, INT32_MIN, UINT32_MAX, NULL, value_effOrEffEl, assign_default}, + {"INITIALDELAY", 0, field_t(struct TrapConfigStats, initial_delay), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"PLACEONSUBTILE", 0, field_t(struct TrapConfigStats, place_on_subtile), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"FLAMEANIMATIONID", 0, field_t(struct TrapConfigStats, flame.animation_id), 0, INT32_MIN, UINT32_MAX, NULL, value_animid, assign_refresh_trap_anim_anim_id}, + {"FLAMEANIMATIONSPEED", 0, field_t(struct TrapConfigStats, flame.anim_speed), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"FLAMEANIMATIONSIZE", 0, field_t(struct TrapConfigStats, flame.sprite_size), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"FLAMEANIMATIONOFFSET", 0, field_t(struct TrapConfigStats, flame.fp_add_x), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"FLAMEANIMATIONOFFSET", 1, field_t(struct TrapConfigStats, flame.fp_add_y), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"FLAMEANIMATIONOFFSET", 2, field_t(struct TrapConfigStats, flame.td_add_x), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"FLAMEANIMATIONOFFSET", 3, field_t(struct TrapConfigStats, flame.td_add_y), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"FLAMETRANSPARENCYFLAGS", 0, field_t(struct TrapConfigStats, flame.transparency_flags), 0, INT32_MIN, UINT32_MAX, NULL, value_transpflg, assign_default}, + {"DETECTINVISIBLE", 0, field_t(struct TrapConfigStats, detect_invisible), true, 0, 1, NULL, value_default, assign_default}, + {"INSTANTPLACEMENT", 0, field_t(struct TrapConfigStats, instant_placement), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"REMOVEONCEDEPLETED", 0, field_t(struct TrapConfigStats, remove_once_depleted), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"FLAGNUMBER", 0, field_t(struct TrapConfigStats, flag_number), 0, INT32_MIN, UINT32_MAX, NULL, value_default, assign_default}, + {"UPDATEFUNCTION", 0, field_t(struct TrapConfigStats, updatefn_idx), 0, INT32_MIN, UINT32_MAX, NULL, value_function,assign_default}, {NULL}, }; +#pragma pop_macro("game") + +static int32_t* get_trap_count(void) { return &game.conf.trapdoor_conf.trap_types_count; } +static void* get_trap_base(void) { return game.conf.trapdoor_conf.trap_cfgstats; } + const struct NamedFieldSet trapdoor_trap_named_fields_set = { - &game.conf.trapdoor_conf.trap_types_count, + get_trap_count, "trap", trapdoor_trap_named_fields, trap_desc, TRAPDOOR_TYPES_MAX, sizeof(game.conf.trapdoor_conf.trap_cfgstats[0]), - game.conf.trapdoor_conf.trap_cfgstats, + get_trap_base, }; /******************************************************************************/ diff --git a/src/console_cmd.c b/src/console_cmd.c index 87f348baad..507e4ca36c 100644 --- a/src/console_cmd.c +++ b/src/console_cmd.c @@ -76,7 +76,7 @@ extern "C" { #endif -#if defined(__MINGW32__) +#if defined(__MINGW32__) || defined(_MSC_VER) // Copied from stack overflow because MingW doesn't provide it. char *strsep(char ** stringp, const char * delim) { diff --git a/src/custom_sprites.c b/src/custom_sprites.c index 5c10ae9d87..911ca49103 100644 --- a/src/custom_sprites.c +++ b/src/custom_sprites.c @@ -840,8 +840,10 @@ static int read_png_icon(unzFile zip, const char *path, const char *subpath, int return 1; } +#ifdef __clang__ #pragma clang diagnostic push #pragma ide diagnostic ignored "bugprone-branch-clone" +#endif static int read_png_data(unzFile zip, const char *path, struct SpriteContext *context, const char *subpath, int is_fp, VALUE *def, VALUE *itm) { @@ -977,7 +979,9 @@ static int read_png_data(unzFile zip, const char *path, struct SpriteContext *co spng_ctx_free(ctx); return 1; } +#ifdef __clang__ #pragma clang diagnostic pop +#endif static void convert_row(unsigned char *dst_buf, uint32_t *src_buf, int len) { diff --git a/src/lua_api_things.c b/src/lua_api_things.c index 9395468792..4bd05c7c86 100644 --- a/src/lua_api_things.c +++ b/src/lua_api_things.c @@ -38,7 +38,8 @@ static int thing_set_field(lua_State *L); static int thing_get_field(lua_State *L); -static const struct luaL_Reg thing_methods[]; +// Forward reference: defined after thing_get_field. Pointer allows use before definition. +static const struct luaL_Reg *thing_methods_ptr = NULL; @@ -405,7 +406,7 @@ static int thing_set_field(lua_State *L) { static int thing_get_field(lua_State *L) { const char* key = luaL_checkstring(L, 2); - if (try_get_c_method(L, key, thing_methods)) + if (try_get_c_method(L, key, thing_methods_ptr)) { return 1; } @@ -608,7 +609,7 @@ static int thing_eq(lua_State *L) { } -static const struct luaL_Reg thing_methods[] = { +static const struct luaL_Reg thing_methods_arr[] = { {"make_thing_zombie" ,make_thing_zombie }, {"walk_to" ,lua_creature_walk_to }, {"kill" ,lua_kill_creature }, @@ -636,6 +637,9 @@ static const struct luaL_Reg thing_meta[] = { }; void Thing_register(lua_State *L) { + // Initialise forward-reference pointer now that the array is defined + thing_methods_ptr = thing_methods_arr; + // Create and register the metatable as "Thing" luaL_newmetatable(L, "Thing"); @@ -644,7 +648,7 @@ void Thing_register(lua_State *L) { // Create the method table for Lua-accessible methods lua_newtable(L); - luaL_setfuncs(L, thing_methods, 0); // your C methods + luaL_setfuncs(L, thing_methods_arr, 0); // your C methods // Save method table into metatable under __methods lua_setfield(L, -2, "__methods"); diff --git a/src/main.cpp b/src/main.cpp index bc1144eb78..60fd04a34d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -145,8 +145,11 @@ short do_draw; short default_loc_player = 0; struct StartupParameters start_params; -char autostart_multiplayer_campaign[80] = ""; -int autostart_multiplayer_level = 0; +// Defined with C linkage so .c translation units can reference them without name mangling +extern "C" { + char autostart_multiplayer_campaign[80] = ""; + int autostart_multiplayer_level = 0; +} int32_t turns_per_second; int32_t turns_per_second_draw_current = 0; diff --git a/src/net_matchmaking.c b/src/net_matchmaking.c index 270dae4231..589b4da0bf 100644 --- a/src/net_matchmaking.c +++ b/src/net_matchmaking.c @@ -313,7 +313,7 @@ static void load_published_public_ips(int udp_ipv4_port, int udp_ipv6_port, Punc copy_public_ip(1, published_addresses->ipv6, sizeof(published_addresses->ipv6)); } -static int matchmaking_connect_thread(void *) +static int matchmaking_connect_thread(void *userdata) { if (matchmaking_connect() == 0) matchmaking_request_list(); diff --git a/src/net_portforward.cpp b/src/net_portforward.cpp index 34dc1b5ec4..d262fd6526 100644 --- a/src/net_portforward.cpp +++ b/src/net_portforward.cpp @@ -16,6 +16,14 @@ * (at your option) any later version. */ /******************************************************************************/ +#ifdef _MSC_VER +// Include winsock2 and windows before project headers to prevent include-order +// conflicts that leave LPMSG/OLE types undefined (WIN32_LEAN_AND_MEAN race). +#include +#include +#endif + + #include "pre_inc.h" #include "net_portforward.h" #include "bflib_basics.h" diff --git a/src/spritesheet.cpp b/src/spritesheet.cpp index f6a50d140b..ed1c69001a 100644 --- a/src/spritesheet.cpp +++ b/src/spritesheet.cpp @@ -68,12 +68,12 @@ bool load_data_file(TbSpriteSheet & sheet, offset_list & offsets, const char * f if (LbFileLoadAt(fname, buffer.data()) != data_size) return false; // populate sprite data for (size_t i = 0; i < num_sprites; ++i) { - const auto first = buffer.begin() + offsets[i].first; - const auto last = buffer.begin() + offsets[i + 1].first; + const auto offset = offsets[i].first; + const auto size = offsets[i + 1].first - offset; const auto sprite_idx = offsets[i].second; auto & sprite = sheet.sprites[sprite_idx]; auto & data = sheet.data[sprite_idx]; - data = std::move(std::vector(first, last)); + data = std::vector(buffer.data() + offset, buffer.data() + offset + size); sprite.Data = data.data(); } return true; @@ -151,3 +151,11 @@ extern "C" long num_sprites(const TbSpriteSheet * sheet) } return sheet->sprites.size(); } + +extern "C" void trim_spritesheet(TbSpriteSheet *sheet, long count) +{ + if (!sheet || count < 0) return; + if ((size_t)count >= sheet->sprites.size()) return; + sheet->sprites.resize((size_t)count); + sheet->data.resize((size_t)count); +} diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 4e894a27c6..d4bea9e4f3 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,33 +1,134 @@ cmake_minimum_required(VERSION 3.20) +# Docker-first: tools are pre-installed at /usr/local/bin in KFX build images. +# find_program sets these cache variables; download fallback only runs if not found. +find_program(PNGTOICO_PATH png2ico) +find_program(PNGTORAW_PATH pngpal2raw) +find_program(PNGTOBSPAL_PATH png2bestpal) +find_program(POTONGDAT_PATH po2ngdat) +find_program(SNDBANKER_PATH sndbanker) +find_program(RNC_PATH rnc) +find_program(DERNC_PATH dernc) + +if( NOT PNGTOICO_PATH OR NOT PNGTORAW_PATH OR NOT PNGTOBSPAL_PATH OR + NOT POTONGDAT_PATH OR NOT SNDBANKER_PATH OR NOT RNC_PATH OR NOT DERNC_PATH ) + +# Determine platform-specific download URLs if( ${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Windows" ) set( PNGTOICO_DOWNLOAD https://github.com/dkfans/png2ico/releases/download/2024-10-28/png2ico-win-2024-10-28.zip ) - set( ZIP_FILE_NAME png2ico-win-2024-10-28.zip ) - set( EXE_FILE_NAME png2ico.exe) + set( PNGTOICO_FILE png2ico-win-2024-10-28.zip ) + set( PNGTOICO_EXE png2ico.exe) + + set( PNGTORAW_DOWNLOAD https://github.com/dkfans/pngpal2raw/releases/download/v1.0.2/pngpal2raw-1_0_2_35-devel-win.zip ) + set( PNGTORAW_FILE pngpal2raw-1_0_2_35-devel-win.zip ) + set( PNGTORAW_EXE pngpal2raw.exe ) + + set( PNGTOBSPAL_DOWNLOAD https://github.com/dkfans/png2bestpal/releases/download/v1.0.3/png2bestpal-1_0_3_21-devel-win.zip ) + set( PNGTOBSPAL_FILE png2bestpal-1_0_3_21-devel-win.zip ) + set( PNGTOBSPAL_EXE png2bestpal.exe ) + + set( POTONGDAT_DOWNLOAD https://github.com/dkfans/po2ngdat/releases/download/v1.0.2.31-c/po2ngdat-1_0_2_31-devel-win.zip ) + set( POTONGDAT_FILE po2ngdat-1_0_2_31-devel-win.zip ) + set( POTONGDAT_EXE po2ngdat.exe ) + + set( SNDBANKER_DOWNLOAD https://github.com/dkfans/sndbanker/releases/download/v1.0.1/sndbanker-1_0_1_13-devel-win.zip ) + set( SNDBANKER_FILE sndbanker-1_0_1_13-devel-win.zip ) + set( SNDBANKER_EXE sndbanker.exe ) + + set( RNCTOOLS_DOWNLOAD https://github.com/dkfans/rnctools/releases/download/v1.0.2/rnctools-1_0_2_5-devel-win.zip ) + set( RNCTOOLS_FILE rnctools-1_0_2_5-devel-win.zip ) + set( RNC_EXE rnc.exe ) + set( DERNC_EXE dernc.exe ) + elseif( ${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Linux" ) set( PNGTOICO_DOWNLOAD https://github.com/dkfans/png2ico/releases/download/2024-10-28/png2ico-lin-2024-10-28.tar.gz ) - set( ZIP_FILE_NAME png2ico-lin-2024-10-28.tar.gz ) - set( EXE_FILE_NAME png2ico) + set( PNGTOICO_FILE png2ico-lin-2024-10-28.tar.gz ) + set( PNGTOICO_EXE png2ico) + + set( PNGTORAW_DOWNLOAD https://github.com/dkfans/pngpal2raw/releases/download/v1.0.2/pngpal2raw-1_0_2_35-devel-lin.tar.gz ) + set( PNGTORAW_FILE pngpal2raw-1_0_2_35-devel-lin.tar.gz ) + set( PNGTORAW_EXE pngpal2raw ) + + set( PNGTOBSPAL_DOWNLOAD https://github.com/dkfans/png2bestpal/releases/download/v1.0.3/png2bestpal-1_0_3_21-devel-lin.tar.gz ) + set( PNGTOBSPAL_FILE png2bestpal-1_0_3_21-devel-lin.tar.gz ) + set( PNGTOBSPAL_EXE png2bestpal ) + + set( POTONGDAT_DOWNLOAD https://github.com/dkfans/po2ngdat/releases/download/v1.0.2.31-c/po2ngdat-1_0_2_31-devel-lin.tar.gz ) + set( POTONGDAT_FILE po2ngdat-1_0_2_31-devel-lin.tar.gz ) + set( POTONGDAT_EXE po2ngdat ) + + set( SNDBANKER_DOWNLOAD https://github.com/dkfans/sndbanker/releases/download/v1.0.1/sndbanker-1_0_1_13-devel-lin.tar.gz ) + set( SNDBANKER_FILE sndbanker-1_0_1_13-devel-lin.tar.gz ) + set( SNDBANKER_EXE sndbanker ) + + set( RNCTOOLS_DOWNLOAD https://github.com/dkfans/rnctools/releases/download/v1.0.2/rnctools-1_0_2_5-devel-lin.tar.gz ) + set( RNCTOOLS_FILE rnctools-1_0_2_5-devel-lin.tar.gz ) + set( RNC_EXE rnc ) + set( DERNC_EXE dernc ) endif() -set(DESTINATION_DIR ${CMAKE_SOURCE_DIR}/tools/png2ico/${CMAKE_HOST_SYSTEM_NAME}) + # Helper: download and extract a tool into tools//bin/ + macro(download_tool TOOL_NAME TOOL_DOWNLOAD TOOL_FILE TOOL_DIR TOOL_EXE) + if( NOT EXISTS ${CMAKE_SOURCE_DIR}/tools/${TOOL_DIR}/bin/${TOOL_EXE} ) + file( MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/tools/${TOOL_DIR} ) + file( MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/tools/${TOOL_DIR}/bin ) + if( NOT EXISTS ${CMAKE_SOURCE_DIR}/tools/${TOOL_DIR}/${TOOL_FILE} ) + message(STATUS "Downloading ${TOOL_NAME}...") + file( DOWNLOAD ${TOOL_DOWNLOAD} ${CMAKE_SOURCE_DIR}/tools/${TOOL_DIR}/${TOOL_FILE} SHOW_PROGRESS ) + endif() + message(STATUS "Extracting ${TOOL_NAME}...") + execute_process( COMMAND ${CMAKE_COMMAND} -E tar xzf ${CMAKE_SOURCE_DIR}/tools/${TOOL_DIR}/${TOOL_FILE} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tools/${TOOL_DIR}/bin ) + endif() + endmacro() -if( NOT EXISTS ${DESTINATION_DIR} ) - file( MAKE_DIRECTORY ${DESTINATION_DIR} ) - if( NOT EXISTS ${DESTINATION_DIR}/ZIP_FILE_NAME ) - file( DOWNLOAD ${PNGTOICO_DOWNLOAD} ${DESTINATION_DIR}/${ZIP_FILE_NAME} SHOW_PROGRESS ) - endif() + if( NOT PNGTOICO_PATH ) + download_tool("png2ico" "${PNGTOICO_DOWNLOAD}" "${PNGTOICO_FILE}" "png2ico" "${PNGTOICO_EXE}") + set( PNGTOICO_PATH ${CMAKE_SOURCE_DIR}/tools/png2ico/bin/${PNGTOICO_EXE} ) + endif() + if( NOT PNGTORAW_PATH ) + download_tool("pngpal2raw" "${PNGTORAW_DOWNLOAD}" "${PNGTORAW_FILE}" "pngpal2raw" "${PNGTORAW_EXE}") + set( PNGTORAW_PATH ${CMAKE_SOURCE_DIR}/tools/pngpal2raw/bin/${PNGTORAW_EXE} ) + endif() + if( NOT PNGTOBSPAL_PATH ) + download_tool("png2bestpal" "${PNGTOBSPAL_DOWNLOAD}" "${PNGTOBSPAL_FILE}" "png2bestpal" "${PNGTOBSPAL_EXE}") + set( PNGTOBSPAL_PATH ${CMAKE_SOURCE_DIR}/tools/png2bestpal/bin/${PNGTOBSPAL_EXE} ) + endif() + if( NOT POTONGDAT_PATH ) + download_tool("po2ngdat" "${POTONGDAT_DOWNLOAD}" "${POTONGDAT_FILE}" "po2ngdat" "${POTONGDAT_EXE}") + set( POTONGDAT_PATH ${CMAKE_SOURCE_DIR}/tools/po2ngdat/bin/${POTONGDAT_EXE} ) + endif() + if( NOT SNDBANKER_PATH ) + download_tool("sndbanker" "${SNDBANKER_DOWNLOAD}" "${SNDBANKER_FILE}" "sndbanker" "${SNDBANKER_EXE}") + set( SNDBANKER_PATH ${CMAKE_SOURCE_DIR}/tools/sndbanker/bin/${SNDBANKER_EXE} ) + endif() + if( NOT RNC_PATH ) + download_tool("rnctools (rnc)" "${RNCTOOLS_DOWNLOAD}" "${RNCTOOLS_FILE}" "rnctools" "${RNC_EXE}") + set( RNC_PATH ${CMAKE_SOURCE_DIR}/tools/rnctools/bin/${RNC_EXE} ) + endif() + if( NOT DERNC_PATH ) + download_tool("rnctools (dernc)" "${RNCTOOLS_DOWNLOAD}" "${RNCTOOLS_FILE}" "rnctools" "${DERNC_EXE}") + set( DERNC_PATH ${CMAKE_SOURCE_DIR}/tools/rnctools/bin/${DERNC_EXE} ) + endif() - execute_process( COMMAND ${CMAKE_COMMAND} -E tar xzf ${DESTINATION_DIR}/${ZIP_FILE_NAME} WORKING_DIRECTORY ${DESTINATION_DIR} ) -endif() +endif() # NOT all tools found on PATH + +# Propagate resolved paths to parent scope +set(PNGTOICO_PATH ${PNGTOICO_PATH} PARENT_SCOPE) +set(PNGTORAW_PATH ${PNGTORAW_PATH} PARENT_SCOPE) +set(PNGTOBSPAL_PATH ${PNGTOBSPAL_PATH} PARENT_SCOPE) +set(POTONGDAT_PATH ${POTONGDAT_PATH} PARENT_SCOPE) +set(SNDBANKER_PATH ${SNDBANKER_PATH} PARENT_SCOPE) +set(RNC_PATH ${RNC_PATH} PARENT_SCOPE) +set(DERNC_PATH ${DERNC_PATH} PARENT_SCOPE) +# Generate keeperfx icon from PNGs set( PNG_FILE_PREFIX "keeperfx_icon") add_custom_command( OUTPUT ${CMAKE_SOURCE_DIR}/res/keeperfx_icon.ico - COMMAND ${DESTINATION_DIR}/${EXE_FILE_NAME} keeperfx_icon.ico ${PNG_FILE_PREFIX}512-24bpp.png ${PNG_FILE_PREFIX}256-24bpp.png ${PNG_FILE_PREFIX}128-24bpp.png + COMMAND ${PNGTOICO_PATH} keeperfx_icon.ico ${PNG_FILE_PREFIX}512-24bpp.png ${PNG_FILE_PREFIX}256-24bpp.png ${PNG_FILE_PREFIX}128-24bpp.png --colors 256 ${PNG_FILE_PREFIX}128-08bpp.png ${PNG_FILE_PREFIX}064-08bpp.png ${PNG_FILE_PREFIX}048-08bpp.png - --colors 16 ${PNG_FILE_PREFIX}032-08bpp.png ${PNG_FILE_PREFIX}016-08bpp.png + --colors 16 ${PNG_FILE_PREFIX}032-08bpp.png ${PNG_FILE_PREFIX}016-08bpp.png WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/res VERBATIM ) diff --git a/vcpkg-configuration.json b/vcpkg-configuration.json index 93db3b45c8..10d0196e72 100644 --- a/vcpkg-configuration.json +++ b/vcpkg-configuration.json @@ -1,7 +1,7 @@ { "default-registry": { "kind": "git", - "baseline": "9558037875497b9db8cf38fcd7db68ec661bffe7", + "baseline": "4b77da7fed37817f124936239197833469f1b9a8", "repository": "https://github.com/microsoft/vcpkg" }, "registries": [ @@ -9,6 +9,12 @@ "kind": "artifact", "location": "https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip", "name": "microsoft" + }, + { + "kind": "git", + "repository": "https://github.com/cerwym/keeperfx-vcpkg-registry", + "baseline": "dcb6b8df162cf6925237292ab5471d4cc7b4987d", + "packages": ["astronomy", "centijson", "enet6", "libnatpmp"] } ] } diff --git a/vcpkg.json b/vcpkg.json index 4e939a8186..56010e2ad1 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -3,6 +3,21 @@ "sdl2", "sdl2-image", "sdl2-mixer", - "sdl2-net" + "sdl2-net", + { + "name": "ffmpeg", + "features": ["avcodec", "avformat", "swresample"] + }, + "openal-soft", + "enet6", + "astronomy", + "centijson", + "libnatpmp", + "libspng", + "zlib", + "minizip", + "luajit", + "miniupnpc", + "curl" ] }