8 Commits

Author SHA1 Message Date
ae5df7212a Release build squashed
Some checks failed
/ release (Debug, map[deps:macos-universal flag:arm64 name:macos scons-script:./.github/workflows/scripts/mac/scons-build.sh suffix:-silicon version:14]) (push) Has been cancelled
/ release (Debug, map[deps:macos-universal flag:x86_64 name:macos scons-script:./.github/workflows/scripts/mac/scons-build.sh suffix:-intel version:13]) (push) Has been cancelled
/ release (Debug, map[name:windows scons-script:./.github/workflows/scripts/win/scons-build.bat suffix: version:2019]) (push) Has been cancelled
/ release (Release, map[deps:macos-universal flag:arm64 name:macos scons-script:./.github/workflows/scripts/mac/scons-build.sh suffix:-silicon version:14]) (push) Has been cancelled
/ release (Release, map[deps:macos-universal flag:x86_64 name:macos scons-script:./.github/workflows/scripts/mac/scons-build.sh suffix:-intel version:13]) (push) Has been cancelled
/ release (Release, map[name:windows scons-script:./.github/workflows/scripts/win/scons-build.bat suffix: version:2019]) (push) Has been cancelled
2025-05-24 14:37:45 -05:00
e7bf5847d0 add conveyor belts flag to game. fix #747 2025-05-24 14:30:34 -05:00
e846540ebd remove out-of-range node in VoDT outdoors (fix #741) 2025-05-23 14:28:41 -05:00
4ed73bf72d Update src/dialogxml/dialogs/dialog.cpp
Co-authored-by: Celtic Minstrel <CelticMinstrel@users.noreply.github.com>
2025-05-23 14:02:50 -05:00
1084f26a88 Count preferences dialog when detecting max UI scale to fit (Fix #740) 2025-05-23 09:11:27 -05:00
b7c1089508 Fix save file dialog with first party. (#740) 2025-05-23 08:55:14 -05:00
1734e7b055 Fix Load screen with no parties in save folder (#740) 2025-05-23 08:48:31 -05:00
42cffb6704 fix itch build when itch client apps folder doesn't exist 2025-05-21 15:21:58 -05:00
16 changed files with 471 additions and 33 deletions

73
.github/workflows/mac-universal.yml vendored Normal file
View File

@@ -0,0 +1,73 @@
name: Mac universal build
on:
push:
branches:
- universal
release:
types: [published]
jobs:
build:
runs-on: macos-14
env:
CONFIGURATION: ${{ matrix.configuration }}
BUTLER_API_KEY: ${{ secrets.BUTLER_API_KEY }}
PROD_MACOS_CERTIFICATE: '${{ secrets.PROD_MACOS_CERTIFICATE }}'
PROD_MACOS_CERTIFICATE_PWD: '${{ secrets.PROD_MACOS_CERTIFICATE_PWD }}'
PROD_MACOS_CERTIFICATE_NAME: '${{ secrets.PROD_MACOS_CERTIFICATE_NAME }}'
PROD_MACOS_CI_KEYCHAIN_PWD: '${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}'
PROD_MACOS_NOTARIZATION_APPLE_ID: '${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }}'
PROD_MACOS_NOTARIZATION_TEAM_ID: '${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}'
PROD_MACOS_NOTARIZATION_PWD: '${{ secrets.PROD_MACOS_NOTARIZATION_PWD }}'
BUILD_OS: macos
strategy:
fail-fast: false
matrix:
configuration:
- Release
- Debug
steps:
- uses: actions/checkout@v4
# Download macos-intel
- uses: robinraju/release-downloader@v1
id: download
with:
latest: true
fileName: 'cboe-macos-intel-${{ matrix.configuration }}.tar'
extract: true
out-file-path: 'cboe-macos-intel-${{ matrix.configuration }}'
# Download macos-silicon
- uses: robinraju/release-downloader@v1
with:
latest: true
fileName: 'cboe-macos-silicon-${{ matrix.configuration }}.tar'
extract: true
out-file-path: 'cboe-macos-silicon-${{ matrix.configuration }}'
- run: .github/workflows/scripts/mac/make-universal.sh
# Skipping this for now because of issue nqnstudios#13
- name: Codesign and notarize
run: 'SIGN="no" NOTARIZE="no" .github/workflows/scripts/mac/sign-apps.sh'
- name: 'Tar files'
run: 'tar -cvf cboe-macos-universal-${{matrix.configuration}}.tar "build/Blades of Exile"'
# Upload everything as artifact
- uses: actions/upload-artifact@v4
with:
name: mac-universal-dependencies-${{matrix.configuration}}
path: cboe-macos-universal-${{matrix.configuration}}.tar
# upload a release
- name: Github release
uses: softprops/action-gh-release@v2
with:
files: cboe-macos-universal-${{ matrix.configuration }}.tar
tag_name: ${{ steps.download.outputs.tag_name }}
- name: 'Itch.io release'
run: './.github/workflows/scripts/butler_push.sh'
shell: bash
if: ${{ matrix.configuration == 'Release' }}

131
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,131 @@
on:
push:
branches:
- 'itch-edition'
tags:
- "v*.*.*"
pull_request:
branches:
- itch-edition
jobs:
release:
env:
ARCH: ${{ matrix.os.flag }}
MACOSX_DEPLOYMENT_TARGET: 10.15
BUTLER_API_KEY: ${{ secrets.BUTLER_API_KEY }}
PROD_MACOS_CERTIFICATE: '${{ secrets.PROD_MACOS_CERTIFICATE }}'
PROD_MACOS_CERTIFICATE_PWD: '${{ secrets.PROD_MACOS_CERTIFICATE_PWD }}'
PROD_MACOS_CERTIFICATE_NAME: '${{ secrets.PROD_MACOS_CERTIFICATE_NAME }}'
PROD_MACOS_CI_KEYCHAIN_PWD: '${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}'
PROD_MACOS_NOTARIZATION_APPLE_ID: '${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }}'
PROD_MACOS_NOTARIZATION_TEAM_ID: '${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}'
PROD_MACOS_NOTARIZATION_PWD: '${{ secrets.PROD_MACOS_NOTARIZATION_PWD }}'
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
DEBUG_FLAG: ${{ matrix.configuration == 'Debug' && 'true' || 'false' }}
BUILD_OS: ${{ matrix.os.name }}
strategy:
fail-fast: false
matrix:
os:
- name: macos
suffix: '-intel'
flag: x86_64
deps: macos-universal
version: 13
scons-script: './.github/workflows/scripts/mac/scons-build.sh'
- name: macos
flag: arm64
suffix: '-silicon'
deps: macos-universal
version: 14
scons-script: './.github/workflows/scripts/mac/scons-build.sh'
# - name: ubuntu
# suffix: ''
# version: 22.04
# scons-script: scons
- name: windows
suffix: ''
version: 2019
scons-script: './.github/workflows/scripts/win/scons-build.bat'
configuration:
- Release
- Debug
runs-on: '${{ matrix.os.name }}-${{ matrix.os.version }}'
steps:
- name: Export GitHub Actions cache environment variables
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: checkout
uses: actions/checkout@v4
with:
submodules: true
- name: Download dependency build
uses: robinraju/release-downloader@v1
with:
repository: NQNStudios/cboe-dependencies
latest: true
fileName: 'dependencies-${{ matrix.os.deps || matrix.os.name }}-${{ matrix.configuration }}.tar'
extract: true
out-file-path: 'deps'
- name: Windows build dependencies
run: 'vcpkg install libxml2 && pip install scons'
if: ${{ matrix.os.name == 'windows' }}
- name: Mac build dependencies
run: brew install scons
if: ${{ matrix.os.name == 'macos' }}
- name: Linux build dependencies
run: sudo apt-get update && sudo apt-get install scons libxml2-utils libgl-dev libopenal-dev
if: ${{ matrix.os.name == 'ubuntu' }}
- name: Install TGUI
run: 'sudo ./.github/workflows/scripts/linux/install-tgui.sh'
if: ${{ matrix.os.name == 'ubuntu' }}
- name: Build
run: '${{ matrix.os.scons-script }} test=false debug=$DEBUG_FLAG'
shell: bash
- name: Download fix-rpaths.py script
run: git clone https://gist.github.com/NQNStudios/7145bcf6621891f5176c8caa165d6b93
if: ${{ matrix.os.name == 'macos' }}
- name: Fix rpaths game
run: 'python 7145bcf6621891f5176c8caa165d6b93/fix-rpaths.py "build/Blades of Exile/Blades of Exile.app"'
if: ${{ matrix.os.name == 'macos' }}
- name: Fix rpaths scenario editor
run: 'python 7145bcf6621891f5176c8caa165d6b93/fix-rpaths.py "build/Blades of Exile/BoE Scenario Editor.app"'
if: ${{ matrix.os.name == 'macos' }}
- name: Fix rpaths character editor
run: 'python 7145bcf6621891f5176c8caa165d6b93/fix-rpaths.py "build/Blades of Exile/BoE Character Editor.app"'
if: ${{ matrix.os.name == 'macos' }}
- run: cp .itch.toml "build/Blades of Exile/"
shell: bash
- name: 'Tar unsigned files'
run: 'tar -cvf cboe-${{ matrix.os.name }}${{ matrix.os.suffix }}-${{ matrix.configuration }}-unsigned.tar "Blades of Exile"'
working-directory: '${{ github.workspace }}/build'
- name: upload pre-signing artifact
uses: actions/upload-artifact@v4
with:
name: cboe-${{ matrix.os.name }}${{ matrix.os.suffix }}-${{ matrix.configuration }}-unsigned
path: '${{ github.workspace }}/build/cboe-${{ matrix.os.name }}${{ matrix.os.suffix }}-${{ matrix.configuration }}-unsigned.tar'
# Skipping this for now because of issue nqnstudios#13
- name: Codesign and notarize
run: 'SIGN="no" NOTARIZE="no" ./.github/workflows/scripts/mac/sign-apps.sh'
if: ${{ matrix.os.name == 'macos' }}
- name: 'Tar files'
run: 'tar -cvf cboe-${{ matrix.os.name }}${{ matrix.os.suffix }}-${{ matrix.configuration }}.tar "Blades of Exile"'
working-directory: '${{ github.workspace }}/build'
- name: 'Upload Artifact'
uses: actions/upload-artifact@v4
with:
name: cboe-${{ matrix.os.name }}${{ matrix.os.suffix }}-${{ matrix.configuration }}
path: '${{ github.workspace }}/build/cboe-${{ matrix.os.name }}${{ matrix.os.suffix }}-${{ matrix.configuration }}.tar'
- name: Github release
uses: softprops/action-gh-release@v2
with:
files: '${{ github.workspace }}/build/cboe-${{ matrix.os.name }}${{ matrix.os.suffix }}-${{ matrix.configuration }}.tar'
if: ${{ startsWith(github.ref, 'refs/tags/') }}
- name: 'Itch.io release'
run: './.github/workflows/scripts/butler_push.sh'
shell: bash
if: ${{ startsWith(github.ref, 'refs/tags/') && matrix.configuration == 'Release' && matrix.os.name != 'macos' }}

28
.github/workflows/scripts/butler_push.sh vendored Executable file
View File

@@ -0,0 +1,28 @@
#! /bin/bash
butler_channel=""
butler_exe=""
release_dir=""
if [ "$BUILD_OS" = "ubuntu" ]; then
butler_channel=linux-amd64
butler_exe=butler
release_dir="linux"
elif [ "$BUILD_OS" = "windows" ]; then
butler_channel=windows-amd64
butler_exe=butler.exe
release_dir="windows"
elif [ "$BUILD_OS" = "macos" ]; then
butler_channel=darwin-amd64
butler_exe=butler
release_dir="macos"
fi
# -L follows redirects
# -O specifies output name
curl -L -o butler.zip https://broth.itch.ovh/butler/${butler_channel}/LATEST/archive/default
unzip butler.zip
# GNU unzip tends to not set the executable bit even though it's set in the .zip
chmod +x ${butler_exe}
# just a sanity check run (and also helpful in case you're sharing CI logs)
./${butler_exe} -V
./${butler_exe} push "build/Blades of Exile/" nqn/blades-of-exile:${release_dir}

View File

@@ -3,7 +3,7 @@
git clone --depth 1 -b 0.9 https://github.com/texus/TGUI.git
cd TGUI
export CLICOLOR_FORCE=1
cmake -D TGUI_CXX_STANDARD=14 .
SFML_DIR=../deps/lib/cmake/SFML cmake -D TGUI_CXX_STANDARD=14 -D SFML_DIR=../deps/lib/cmake/SFML .
make
cmake --install .
cd .. # Probably not needed but...

View File

@@ -0,0 +1,27 @@
#! /bin/bash
if [ -z "$CONFIGURATION" ]; then
CONFIGURATION=Release
fi
INTEL=cboe-macos-intel-$CONFIGURATION
SILICON=cboe-macos-silicon-$CONFIGURATION
combine() {
mkdir -p "build/Blades of Exile/$1.app/Contents/MacOS"
lipo -create "$SILICON/Blades of Exile/$1.app/Contents/MacOS/$1" "$INTEL/Blades of Exile/$1.app/Contents/MacOS/$1" -output "build/Blades of Exile/$1.app/Contents/MacOS/$1"
cp -r "$SILICON/Blades of Exile/$1.app/Contents/Frameworks" "build/Blades of Exile/$1.app/Contents/"
cp -r "$SILICON/Blades of Exile/$1.app/Contents/Resources" "build/Blades of Exile/$1.app/Contents/"
cp "$SILICON/Blades of Exile/$1.app/Contents/Info.plist" "build/Blades of Exile/$1.app/Contents/"
cp "$SILICON/Blades of Exile/$1.app/Contents/PkgInfo" "build/Blades of Exile/$1.app/Contents/"
}
combine "Blades of Exile"
combine "BoE Scenario Editor"
combine "BoE Character Editor"
cp -r "$SILICON/Blades of Exile/Blades of Exile Base" "build/Blades of Exile/"
cp -r "$SILICON/Blades of Exile/Blades of Exile Scenarios" "build/Blades of Exile/"
cp -r "$SILICON/Blades of Exile/data" "build/Blades of Exile/"
cp -r "$SILICON/Blades of Exile/docs" "build/Blades of Exile/"
cp "$SILICON/Blades of Exile/.itch.toml" "build/Blades of Exile/"

View File

@@ -4,4 +4,4 @@ export CC="$(brew --prefix llvm)/bin/clang"
export CXX="$(brew --prefix llvm)/bin/clang++"
export SDKROOT="$(xcrun --show-sdk-path)"
scons CXXFLAGS="-I/usr/local/opt/zlib/include" LINKFLAGS="-L/usr/local/opt/zlib/lib" $@
scons CXXFLAGS="-I/usr/local/opt/zlib/include -arch $ARCH" LINKFLAGS="-L/usr/local/opt/zlib/lib" $@

79
.github/workflows/scripts/mac/sign-apps.sh vendored Executable file
View File

@@ -0,0 +1,79 @@
#! /bin/bash
# CODE-SIGNING STEP
# Original Source: https://federicoterzi.com/blog/automatic-code-signing-and-notarization-for-macos-apps-using-github-actions/
# Modified by NQNStudios
# Turn our base64-encoded certificate back to a regular .p12 file
echo $PROD_MACOS_CERTIFICATE | base64 --decode > certificate.p12
# We need to create a new keychain, otherwise using the certificate will prompt
# with a UI dialog asking for the certificate password, which we can't
# use in a headless CI environment
security create-keychain -p "$PROD_MACOS_CI_KEYCHAIN_PWD" build.keychain
security default-keychain -s build.keychain
security unlock-keychain -p "$PROD_MACOS_CI_KEYCHAIN_PWD" build.keychain
security import certificate.p12 -k build.keychain -P "$PROD_MACOS_CERTIFICATE_PWD" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$PROD_MACOS_CI_KEYCHAIN_PWD" build.keychain
sign() {
if [ "$SIGN" = "no" ];
then
return
fi
APP_PATH="build/Blades of Exile/$1.app"
# We finally codesign our app bundle, specifying the Hardened runtime option
/usr/bin/codesign --force -s "$PROD_MACOS_CERTIFICATE_NAME" --options runtime "$APP_PATH"/Contents/Frameworks/*.dylib -v
(cd "$APP_PATH" && frameworks=Contents/Frameworks/*.framework/Versions/A/* && \
for framework in $frameworks; do
if [ -f "$framework" ]; then
/usr/bin/codesign --force -s "$PROD_MACOS_CERTIFICATE_NAME" --options runtime "$framework" -v
fi
done)
/usr/bin/codesign --force -s "$PROD_MACOS_CERTIFICATE_NAME" --options runtime "$APP_PATH"/Contents/Frameworks/*.framework/Versions/A/Resources/Info.plist -v
/usr/bin/codesign --force -s "$PROD_MACOS_CERTIFICATE_NAME" --options runtime "$APP_PATH/Contents/Info.plist" -v
/usr/bin/codesign --force -s "$PROD_MACOS_CERTIFICATE_NAME" --options runtime "$APP_PATH" -v
# NOTARIZATION STEP
if [ "$NOTARIZE" = "no" ];
then
return
fi
# (same source)
# Store the notarization credentials so that we can prevent a UI password dialog
# from blocking the CI
echo "Create keychain profile"
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$PROD_MACOS_NOTARIZATION_APPLE_ID" --team-id "$PROD_MACOS_NOTARIZATION_TEAM_ID" --password "$PROD_MACOS_NOTARIZATION_PWD"
# We can't notarize an app bundle directly, but we need to compress it as an archive.
# Therefore, we create a zip file containing our app bundle, so that we can send it to the
# notarization service
echo "Creating temp notarization archive"
ditto -c -k --keepParent "$APP_PATH" "notarization.zip"
# Here we send the notarization request to the Apple's Notarization service, waiting for the result.
# This typically takes a few seconds inside a CI environment, but it might take more depending on the App
# characteristics. Visit the Notarization docs for more information and strategies on how to optimize it if
# you're curious
echo "Notarize app"
xcrun notarytool submit "notarization.zip" --keychain-profile "notarytool-profile" --wait
# Finally, we need to "attach the staple" to our executable, which will allow our app to be
# validated by macOS even when an internet connection is not available.
echo "Attach staple"
xcrun stapler staple "$APP_PATH" || exit 1
}
sign "Blades of Exile"
sign "BoE Scenario Editor"
sign "BoE Character Editor"

9
.itch.toml Normal file
View File

@@ -0,0 +1,9 @@
[[actions]]
name = "Play"
path = "Blades of Exile.exe"
platform = "windows"
[[actions]]
name = "Play"
path = "Blades of Exile.app"
platform = "osx"

View File

@@ -232,13 +232,15 @@ elif platform == "win32":
vcpkg_other_libs = list(filter(path.exists, vcpkg_other_libs))
vcpkg_other_bins = [path.join(d.get_abspath(), 'bin') for d in vcpkg_other_packages]
vcpkg_other_bins = list(filter(path.exists, vcpkg_other_bins))
include_paths=[path.join(vcpkg_installed, 'include')] + vcpkg_other_includes
project_includes = []
for (root, dirs, files) in os.walk('src'):
project_includes.append(path.join(os.getcwd(), root))
include_paths=project_includes
env.Append(
LINKFLAGS=['/SUBSYSTEM:WINDOWS','/ENTRY:mainCRTStartup',f'/MACHINE:X{arch_short}'],
LINKFLAGS=['/SUBSYSTEM:WINDOWS','/ENTRY:mainCRTStartup',f'/MACHINE:X{arch_short}', '/VERBOSE', '/NODEFAULTLIB:libboost_filesystem-vc142-mt-x64-1_85.lib'],
CXXFLAGS=['/EHsc','/MD','/FIglobal.hpp'],
CPPPATH=include_paths,
LIBPATH=[path.join(vcpkg_installed, 'lib')] + vcpkg_other_libs + vcpkg_other_bins,
LIBPATH=[],
LIBS=Split("""
kernel32
user32
@@ -259,7 +261,10 @@ elif platform == "win32":
def build_app_package(env, source, build_dir, info):
env.Install(build_dir, source)
elif platform == "posix":
env.Append(CXXFLAGS=["-std=c++14","-include","global.hpp"])
env.Append(
CXXFLAGS=["-std=c++14","-include","global.hpp"],
#LINKFLAGS=["-rpath-link", "deps/lib/", "-rpath", "./"]
)
def build_app_package(env, source, build_dir, info):
env.Install(build_dir, source)
@@ -415,6 +420,7 @@ if not env.GetOption('clean'):
if platform == 'posix':
def check_tgui(conf, second_attempt=False):
if conf.CheckLib('libtgui', language='C++'):
bundled_libs.append('tgui')
return conf
else:
if second_attempt:
@@ -496,7 +502,31 @@ Export("data_dir")
SConscript(["rsrc/SConscript", "doc/SConscript"])
# Bundle required frameworks and libraries
def handle_bundled_libs(extension, prefix=''):
target_dirs = ["#build/Blades of Exile", "#build/test"]
for lib in bundled_libs:
for lpath in env['LIBPATH']:
def check_path(src_file):
_dir = os.path.dirname(src_file)
print(f'checking {_dir} for {prefix}{lib}')
try:
print(os.listdir(_dir))
except:
pass
if path.exists(src_file) and src_file != "/usr/lib/x86_64-linux-gnu/libz.so":
for targ in target_dirs:
for so in os.listdir(_dir):
if os.path.basename(src_file) in so:
print(f'found {path.join(_dir, so)}')
env.Install(targ, path.join(_dir, so))
return True
return False
if check_path(path.join(lpath, prefix + lib + extension)):
break
elif check_path(path.join(lpath.replace('lib', 'bin'), prefix + lib + extension)):
break
elif check_path(path.join(lpath, 'x86_64-linux-gnu', prefix + lib + extension)):
break
if platform == "darwin":
app_targets = []
if 'game' in targets:
@@ -535,20 +565,7 @@ elif platform == "win32":
brotlidec
brotlicommon
""")
target_dirs = ["#build/Blades of Exile", "#build/test"]
for lib in bundled_libs:
for lpath in env['LIBPATH']:
src_file = path.join(lpath, lib + ".dll")
if path.exists(src_file):
for targ in target_dirs:
env.Install(targ, src_file)
break
elif 'lib' in lpath:
src_file = path.join(lpath.replace('lib', 'bin'), lib + ".dll")
if path.exists(src_file):
for targ in target_dirs:
env.Install(targ, src_file)
break
handle_bundled_libs(".dll")
# Extra: Microsoft redistributable libraries installer
if 'msvc' in env["TOOLS"]:
if path.exists("deps/VCRedistInstall.exe"):
@@ -556,11 +573,41 @@ elif platform == "win32":
else:
print("WARNING: Cannot find installer for the MSVC redistributable libraries for your version of Visual Studio.")
print("Please download it from Microsoft's website and place it at:")
print(" deps/VCRedistInstall.exe")
print(" deps/VCRedistInstall.exe")
# Create it so its lack doesn't cause makensis to break
# (Because the installer is an optional component.)
os.makedirs("build/Blades of Exile", exist_ok=True)
open("build/Blades of Exile/VCRedistInstall.exe", 'w').close()
elif platform == "posix":
targets = [
"Blades of Exile",
"BoE Character Editor",
"BoE Scenario Editor",
]
def patchelf():
to_patch = targets + [so for so in os.listdir("build/Blades of Exile") if '.so' in so]
for targ in to_patch:
subprocess.call(['patchelf', '--set-rpath', '.', targ], cwd='build/Blades of Exile')
atexit.register(patchelf)
bundled_libs += Split("""
GL
X11
stdc++
Xrandr
Xcursor
udev
openal
vorbisenc
vorbisfile
vorbis
ogg
FLAC
freetype
GLdispatch
GLX
xcb
""")
handle_bundled_libs(".so", "lib")
if env["package"]:
if platform == "darwin":

View File

@@ -9,10 +9,17 @@
Spiderweb Software, created in 1997 and later released as
Free Open-Source Software.
</text>
<text name='spidweb' relative='pos-in pos' rel-anchor='prev' top='3' left='16' colour='link' underline='true'>
http://www.spidweb.com/blades/opensource.html
<text relative='pos-in pos' rel-anchor='prev' top='2' left='0' width='413'>
You're playing an Itch Edition release of OpenBoE. The Itch Edition
was funded by many generous supporters through IndieGoGo, and is
currently funded by donations on Patreon. Click below to follow the project
and see the rewards for becoming a supporter!
</text>
<text relative='neg pos' rel-anchor='prev' top='3' left='16' width='413'>
<text name='patreon' relative='pos-in pos' rel-anchor='prev' top='0' left='16' width='230' colour='link' underline='true'>
http://patreon.com/blades_itch_edition
</text>
<pict type='item' num='17' relative='pos neg' rel-anchor='prev' top='15' left='2'/>
<text relative='neg pos' anchor='patreon' top='3' left='16' width='413'>
Three exciting original scenarios await you, filled
with many hours of puzzles, fighting and adventure!
In addition to these, hundreds more written by

View File

@@ -39,7 +39,7 @@
2,111,2,2,2,3,2,58,51,59,61,54,31,32,22,22,22,35,25,49,39,4,3,3,43,42,42,47,36,49,38,38,39,2,87,2,44,30,26,36,36,30,23,23,22,22,22,22
4,2,3,111,3,111,3,2,2,57,50,61,54,30,35,240@5,32,26,49,39,3,2,2,2,44,36,37,37,37,40,2,3,2,3,2,4,44,30,34,27,36,31,32,23,23,22,22,22
4,3,2,3,2,3,111,3,2,58,59,50,53,31,25,36,31,25,40,3,4,2,3,2,45,46,36,36,37,48,41,2,2,2,2,2,44,30,22,26,36,36,30,23,23,22,22,22
2,2,4,111,2,2,111,3,2:22,2,57,50,53,45,38,38,38,38,39,2,3,4,3,2,2,45*1,38,38,46,36,40,3,2,2,2,2,44,31,32,34,27,36,30,23,23,23,22,22
2,2,4,111,2,2,111,3,2,2,57,50,53,45,38,38,38,38,39,2,3,4,3,2,2,45*1,38,38,46,36,40,3,2,2,2,2,44,31,32,34,27,36,30,23,23,23,22,22
2,2,3,2,2,2,2,111,111,2,57,50,53,3,111,2,4,113,2,2,4,2,4,2,87,2,2,3,45,46,48,41,2,2,3,2,45,46,31,32,26,36,30,23,23,23,22,22
111,3,3,2,111,111,2,111,2,2,57,50,53,2&9:1,111,112,4,2,2,2,3,2,3,43,41,2,2,2,87,44,37,40,2,2,2,4,3,45,46,30:17,26:17,36,30,22,23,23,22,22
3,2,110,110:20,110,4,111,111,111,3,57,50,53,3,112,3,3,2,111,112,2,2,2,44,40,2,2,2,2,45,38,39,2,2,2,2,3,2,44,30,34,28,33,22,23,22,22,22

View File

@@ -445,6 +445,12 @@ void cDialog::recalcRect(){
winRect.right *= get_ui_scale();
winRect.bottom *= get_ui_scale();
// Uncomment if you need to measure any dialogs.
/*
LOG_VALUE(fname);
LOG_VALUE(winRect.right);
LOG_VALUE(winRect.bottom);
//*/
}
bool cDialog::initCalled = false;

View File

@@ -68,8 +68,8 @@ static std::string get_file_error() {
// Debug builds run from working directory "build/Blades of Exile"
// should helpfully let you enter replay test scenarios.
// Support for multiple scenario directories will also help with how I plan
// to handle scenario packaging/distribution for my fork's release.
// The Itch Edition finds scenarios in the Itch client's install path,
// so scenarios can be distributed as Itch games.
// - Nat
std::vector<fs::path> all_scen_dirs() {
std::vector<fs::path> scen_dirs = { scenDir };
@@ -86,6 +86,29 @@ std::vector<fs::path> all_scen_dirs() {
}
#endif
// Itch Edition: Search Itch client apps.
// But not recursively, because the player could have tons of games installed
// and that would search ALL of the installed files.
// In fact, try to disqualify folders ASAP by only allowing .boes, .txt,
// and Itch meta files
// (designers might want to ship a README.txt)
fs::path itch_apps_path = scenDir/".."/".."/"itch"/"apps";
if(fs::is_directory(itch_apps_path)){
for(fs::directory_iterator app_iter(itch_apps_path); app_iter != fs::directory_iterator(); app_iter++){
fs::path app = *app_iter;
for(fs::directory_iterator file_iter(app); file_iter != fs::directory_iterator(); file_iter++){
fs::path file = *file_iter;
if(file.extension() == ".boes"){
scen_dirs.push_back(*app_iter);
break;
}else if(file.extension() == ".itch"){
}else if(file.extension() != ".txt"){
break;
}
}
}
}
return scen_dirs;
}
@@ -99,6 +122,9 @@ fs::path locate_scenario(std::string scen_name, bool allow_unpacked) {
fs::path scenPath;
for(fs::path scenDir : all_scen_dirs()){
// Some possible directories, like the Itch client installation folder, might not exist
if(!fs::is_directory(scenDir)) continue;
for(fs::recursive_directory_iterator iter(scenDir); iter != fs::recursive_directory_iterator(); iter++) {
fs::file_status stat = iter->status();
std::string fname = iter->path().filename().string().c_str();

View File

@@ -1889,7 +1889,7 @@ class cFilePicker {
save_files.resize(save_file_mtimes.size());
cStack& stk = get_stack();
int num_pages = ceil((float)save_file_mtimes.size() / parties_per_page);
int num_pages = max(1, ceil((float)save_file_mtimes.size() / parties_per_page));
stk.setPageCount(num_pages);
// HACK: For some reason which should be fixed, the buttons and labels on subsequent pages
// aren't getting text on the static buttons and labels
@@ -2098,7 +2098,7 @@ class cFilePicker {
if(party_idx < parties_needed)
populate_slot(slot_idx, save_file_mtimes[party_idx].first, save_file_mtimes[party_idx].second, save_files[party_idx]);
else
empty_slot(party_idx - start_idx);
empty_slot(slot_idx);
}
++pages_populated;

View File

@@ -102,6 +102,7 @@ std::string help_text_rsrc = "help";
std::map<std::string,std::vector<std::string>> feature_flags = {
// Legacy scenario flags
{"resurrection-balm", {"required"}}, // This means it CAN be supported, if the scenario has the flag.
{"conveyor-belts", {"V2"}}, // Diagonal conveyor belts and big monster physics
// Legacy behavior of the T debug action (used by some replays)
// does not change the party's outdoors location
{"debug-enter-town", {"move-outdoors"}},
@@ -1079,6 +1080,7 @@ void init_boe(int argc, char* argv[]) {
init_tiling();
init_snd_tool();
// see fallback_scale() in winutil.cpp for where the default UI scale is calculated based on screen size
adjust_window_mode();
init_ui();
// If we don't do this now it'll flash white to start with

View File

@@ -3,8 +3,11 @@
#include <boost/filesystem/operations.hpp>
#include "keymods.hpp"
// Measured on 5/23/25. For now, must be re-measured at 1x UI scale whenever preferences change (unless making the window smaller, maybe).
short prefs_height = 529;
// The default scale should be the largest that the user's screen can fit all three
// BoE application windows (because they should probably default to match each other).
// BoE application windows and core dialogs of the main game (because they should probably default to match each other).
double fallback_scale() {
static double scale = 0;
// Suppress the float comparison warning.
@@ -17,7 +20,7 @@ double fallback_scale() {
sf::VideoMode desktop = sf::VideoMode::getDesktopMode();
short max_width = max(boe_width, max(pc_width, scen_width));
short max_height = max(boe_height, max(pc_height, scen_height)) + getMenubarHeight();
short max_height = max(prefs_height, max(boe_height, max(pc_height, scen_height))) + getMenubarHeight();
std::vector<double> scale_options = {1.0, 1.5, 2.0, 3.0, 4.0};
for(auto it = scale_options.rbegin(); it != scale_options.rend(); ++it){