Compare commits

..
Author SHA1 Message Date
cambragol 3822e25201 Update inventory.cc
Added a comment regarding the button flaw on Inventory, Use On and Loot screens.

Also noted that scaling and flipping the main menu button is a temp solution/stop-gap measure.
2025-05-25 02:21:55 +09:00
Mike Klaas 2ba6cbee3a Merge branch 'Splash-and-Help-stretching' into Inventory-Buttons-Fix 2025-05-21 09:02:35 -07:00
cambragol cb90129ebd Merge branch 'main' into Inventory-Buttons-Fix 2025-05-21 09:16:34 +09:00
cambragol 13d5fd2e83 Update inventory.cc
flipped buttons to match top right light source
2025-05-21 08:39:17 +09:00
cambragol 7c3cbbac05 Update inventory.cc 2025-05-19 21:52:43 +09:00
cambragol a5a317ab40 Update inventory.cc 2025-05-19 21:42:52 +09:00
cambragol 372483a5ca Update game.cc
synchronize some settings
2025-05-18 17:00:52 +09:00
cambragol d46549dd11 Update game.cc 2025-05-18 16:43:26 +09:00
cambragol c6970e35de Update draw.h 2025-05-18 16:40:13 +09:00
cambragol 68e7d3e903 Update draw.cc 2025-05-18 16:39:23 +09:00
114 changed files with 1266 additions and 14365 deletions
-42
View File
@@ -1,42 +0,0 @@
name: Auto Format with Clang
on:
pull_request:
types: [opened, synchronize]
push:
branches: [main]
jobs:
format:
runs-on: ubuntu-latest
if: github.actor != 'github-actions[bot]' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref || github.ref_name }}
token: ${{ secrets.PAT_FOR_ACTIONS }}
- name: Run clang-format via Docker
run: |
docker run --rm \
-v ${{ github.workspace }}:/app --workdir /app \
--user $(id -u):$(id -g) silkeh/clang:18 \
bash -c 'find src -type f \( -name "*.cc" -o -name "*.h" \) -print0 | xargs -0 clang-format -i'
# https://github.com/actions/checkout?tab=readme-ov-file#push-a-commit-to-a-pr-using-the-built-in-token
- name: Check and commit changes if needed
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
if ! git diff --quiet; then
git diff
git commit -am "chore: auto-format with clang-format"
git push
else
echo "No formatting changes"
fi
+6 -22
View File
@@ -14,16 +14,6 @@ jobs:
runs-on: ubuntu-latest
permissions: write-all
steps:
- name: start deployment
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
uses: bobheadxi/deployments@v1
id: deployment
with:
ref: ${{ github.event.pull_request.head.sha }}
step: start
debug: true
env: preview-${{ github.event.pull_request.number }}
- name: Clone
uses: actions/checkout@v4
@@ -99,17 +89,11 @@ jobs:
folder: fallout2-ce-ems/dist
target-folder: ${{ steps.set-path.outputs.DEST_DIR }}
clean: false
single-commit: true
- name: Update deployment status
- name: Comment preview URL on PR
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
uses: bobheadxi/deployments@v1
with:
step: finish
status: success
debug: true
env: ${{ steps.deployment.outputs.env }}
deployment_id: ${{ steps.deployment.outputs.deployment_id }}
ref: ${{ github.event.pull_request.head.sha }}
env_url: https://${{ github.repository_owner }}.github.io/fallout2-ce/PR-${{ github.event.pull_request.number }}/
run: |
gh pr comment ${{ github.event.pull_request.number }} \
--body "🚀 WebAssembly PR Preview for ${{github.event.pull_request.head.sha || github.sha }} is available at: https://${{ github.repository_owner }}.github.io/fallout2-ce/PR-${{ github.event.pull_request.number }}/"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+8 -57
View File
@@ -14,27 +14,6 @@ defaults:
shell: bash
jobs:
mark_deployment_as_started:
name: Mark deployment as started
runs-on: ubuntu-latest
permissions:
deployments: write
contents: read
outputs:
deployment_id: ${{ steps.start.outputs.deployment_id }}
env: ${{ steps.start.outputs.env }}
steps:
- name: start deployment
id: start
uses: bobheadxi/deployments@v1
with:
ref: ${{ github.event.pull_request.head.sha }}
step: start
debug: true
env: artifacts-${{ github.event.pull_request.number }}
static-analysis:
name: Static analysis
@@ -108,7 +87,7 @@ jobs:
uses: actions/cache@v4
with:
path: os/android/app/.cxx
key: android-cmake-v101
key: android-cmake-v2
- name: Setup signing config
if: env.KEYSTORE_FILE_BASE64 != '' && env.KEYSTORE_PROPERTIES_FILE_BASE64 != ''
@@ -149,7 +128,7 @@ jobs:
uses: actions/cache@v4
with:
path: out
key: ios-cmake-v101
key: ios-cmake-v5
- name: Configure
run: |
@@ -204,7 +183,7 @@ jobs:
uses: actions/cache@v4
with:
path: out
key: linux-${{ matrix.arch }}-cmake-v101
key: linux-${{ matrix.arch }}-cmake-v3
- name: Configure
run: |
@@ -309,7 +288,7 @@ jobs:
uses: actions/cache@v4
with:
path: out
key: macos-cmake-v101
key: macos-cmake-v6
- name: Configure
run: |
@@ -334,7 +313,7 @@ jobs:
windows:
name: Windows (${{ matrix.arch }})
runs-on: windows-2025
runs-on: windows-2019
strategy:
fail-fast: false
@@ -349,28 +328,19 @@ jobs:
- name: Clone
uses: actions/checkout@v4
- name: Install Visual Studio 2019 Build Tools with v141_xp
shell: cmd
run: |
choco install visualstudio2019buildtools -y --package-parameters="'--add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Component.VC.v141.x86.x64 --add Microsoft.VisualStudio.Component.VC.v141.xp --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.Windows10SDK.10240 --add Microsoft.VisualStudio.ComponentGroup.NativeDesktop.WinXP --add Microsoft.VisualStudio.Component.WinXP'"
- name: Cache cmake build
uses: actions/cache@v4
with:
path: out
key: windows-${{ matrix.arch }}-cmake-v101
key: windows-${{ matrix.arch }}-cmake-v2
- name: Configure
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\Common7\Tools\VsDevCmd.bat" ^
&& cmake --preset windows-${{ matrix.arch }}
cmake --preset windows-${{ matrix.arch }}
- name: Build
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\Common7\Tools\VsDevCmd.bat" ^
&& cmake --build --preset windows-${{ matrix.arch }}-release
cmake --build --preset windows-${{ matrix.arch }}-release
- name: Change executable file name
run: |
@@ -383,25 +353,6 @@ jobs:
path: out/build/windows-${{ matrix.arch }}/RelWithDebInfo/fallout2-ce-${{ matrix.arch }}.exe
retention-days: 7
mark_deployment_as_completed:
name: Mark deployment as completed
runs-on: ubuntu-latest
permissions:
deployments: write
contents: read
needs: [mark_deployment_as_started, android, ios, linux, linux-armhf, linux-arm64, macos, windows]
steps:
- name: Update deployment status
uses: bobheadxi/deployments@v1
with:
step: finish
status: success
debug: true
ref: ${{ github.event.pull_request.head.sha }}
env: ${{ needs.mark_deployment_as_started.outputs.env }}
deployment_id: ${{ needs.mark_deployment_as_started.outputs.deployment_id }}
env_url: "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
release:
name: Release Continuous build
+2 -24
View File
@@ -12,7 +12,6 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: write
deployments: write
steps:
- name: Checkout gh-pages branch
uses: actions/checkout@v4
@@ -30,26 +29,5 @@ jobs:
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
echo "Current branch: $CURRENT_BRANCH"
if [ "$CURRENT_BRANCH" != "gh-pages" ]; then
echo "❌ Refusing to force-push to non-gh-pages branch: $CURRENT_BRANCH"
exit 1
fi
if git diff --cached --quiet; then
echo "No changes to commit"
else
git commit --amend -m "đźš® Remove preview for closed PR #${{ github.event.pull_request.number }}"
git push --force
fi
- name: mark environment as deactivated
uses: bobheadxi/deployments@v1
with:
step: deactivate-env
env: preview-${{ github.event.pull_request.number }}
desc: Environment was pruned
debug: true
git commit -am "đźš® Remove preview for closed PR #${{ github.event.pull_request.number }}"
git push
+10 -12
View File
@@ -243,7 +243,7 @@ jobs:
windows:
name: Windows (${{ matrix.arch }})
runs-on: windows-2025
runs-on: windows-2019
strategy:
fail-fast: false
@@ -258,11 +258,6 @@ jobs:
- name: Clone
uses: actions/checkout@v4
- name: Install Visual Studio 2019 Build Tools with v141_xp
shell: cmd
run: |
choco install visualstudio2019buildtools -y --package-parameters="'--add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Component.VC.v141.x86.x64 --add Microsoft.VisualStudio.Component.VC.v141.xp --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.Windows10SDK.10240 --add Microsoft.VisualStudio.ComponentGroup.NativeDesktop.WinXP --add Microsoft.VisualStudio.Component.WinXP'"
- name: Cache cmake build
uses: actions/cache@v4
with:
@@ -270,16 +265,19 @@ jobs:
key: windows-${{ matrix.arch }}-cmake-v1
- name: Configure
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\Common7\Tools\VsDevCmd.bat" ^
&& cmake -B build -G "Visual Studio 16 2019" -A ${{ matrix.generator-platform }}
cmake \
-B build \
-G "Visual Studio 16 2019" \
-A ${{ matrix.generator-platform }} \
# EOL
- name: Build
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\Common7\Tools\VsDevCmd.bat" ^
&& cmake --build build --config RelWithDebInfo
cmake \
--build build \
--config RelWithDebInfo \
# EOL
- name: Upload
run: |
-6
View File
@@ -288,16 +288,10 @@ target_sources(${EXECUTABLE_NAME} PUBLIC
"src/sfall_opcodes.h"
"src/sfall_arrays.cc"
"src/sfall_arrays.h"
"src/sfall_callbacks.cc"
"src/sfall_callbacks.h"
"src/touch.cc"
"src/touch.h"
"src/scan_unimplemented.cc"
"third_party/lodepng/lodepng.cpp"
)
target_include_directories(${EXECUTABLE_NAME} PUBLIC "third_party/lodepng")
if(IOS)
target_sources(${EXECUTABLE_NAME} PUBLIC
"src/platform/ios/paths.h"
+2 -13
View File
@@ -44,7 +44,7 @@ $ sudo apt install libsdl2-2.0-0
- Alternatively you can use Fallout 2 from Macplay/The Omni Group as a base - you need to extract game assets from the original bundle. Mount CD/DMG, right click `Fallout 2` -> `Show Package Contents`, navigate to `Contents/Resources`. Copy `GameData` folder somewhere, for example `/Applications/Fallout2`.
- Or if you're a Terminal user and have Homebrew installed you can extract the needed files from the GoG installer. **Note**: You must use "Offline backup game installer", not the main game installer.
- Or if you're a Terminal user and have Homebrew installed you can extract the needed files from the GoG installer:
```console
$ brew install innoextract
@@ -125,7 +125,7 @@ IFACE_BAR_SIDES_ORI=0
;This will increase the width of the interface bar expanding the area used to display text.
;if IFACE_BAR_WIDTH=640 - Interface bar will remain at it's original width.
;if IFACE_BAR_WIDTH=800 - Interface bar will use 800pix wide asset from f2_res.dat.
;IFACE_BAR_WIDTH=640
IFACE_BAR_WIDTH=640
```
Recommendations:
@@ -141,17 +141,6 @@ The third configuration file is `ddraw.ini` (part of Sfall). There are dozens of
For a sample ddraw.ini configuration file, containing all currently working settings use this link: [ddraw.ini](https://raw.githubusercontent.com/fallout2-ce/fallout2-ce/refs/heads/main/files/ddraw.ini)
## Quality of life benefits over vanilla Fallout
* High resolution support
* Increased pathfinding nodes 5x for more accurate pathfinding
* Ctrl-click to quickly move items when bartering, looting, or stealing
* _a_ to select "all" when selecting item quantity
* _a_ to `Take All` when looting
* When bartering, caps default to the right amount to balance the trade (if possible)
* Music continues playing between maps (requires config)
* Auto open doors (requires config)
## Contributing
Integrating Sfall goodies is the top priority. Quality of life updates are OK too. Please no large scale refactorings at this time as we need to reconcile changes from Reference Edition, which will make this process slow and error-prone. In any case open up an issue with your suggestion or to notify other people that something is being worked on.
+1 -2
View File
@@ -4,8 +4,7 @@
[Main]
;Set to one to hide areas outside map bounds when using higher than 640x480 resolution, and to zero to disable
;EnableHighResolutionStencil=1
;HiResMode=1
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[Misc]
-7
View File
@@ -1,7 +0,0 @@
#!/bin/bash
docker run --rm \
-v $(pwd):/app --workdir /app \
--user $(id -u):$(id -g) silkeh/clang:18 \
bash -c 'find src -type f -name \*.cc -o -name \*.h | xargs clang-format -i'
-1
View File
@@ -1 +0,0 @@
*.int
-51
View File
@@ -1,51 +0,0 @@
# Testing sFall scripting features
## Basic info
This folder contains scripts which can be used for sFall opcodes.
## Building
Get latest `compile.exe` from [modders pack](https://sourceforge.net/projects/sfall/files/Modders%20pack/) or from [repository](https://github.com/sfall-team/sslc) and run it this way:
```sh
compile.exe -q -p -l -O2 -d -s -n -I<sfall_headers_id> <script_name.ssl>
```
(sfall headers can be found in modderspack)
### Build script using sFall Script Editor
- Get "Fallout sFall Script Editor v4.1.7.RC1", for example from https://nuclear-grot.ucoz.net/forum/12-20-1
- Run script editor, add "sfall_headers" into "Location folder of headers files" in the options
- Open any script here and compile it
- This shoud create compiled script <file.int>
### Build script using VSCode extension
- Install [VSCode Extension](https://marketplace.visualstudio.com/items?itemName=BGforge.bgforge-mls)
## Run test script
1. Move compiled `.int` file into game folder as `data/scripts/gl_<script_name>.int`
2. Change `ddraw.ini` and add this section:
```ini
[Scripts]
GlobalScriptPaths=data/scripts/gl*.int
```
(or add new path using comma as separator)
Note that on non-Windows it have to be `/` as folder separator
3. Run game, check that game displays message about tests
-181
View File
@@ -1,181 +0,0 @@
#include "lib.arrays.h"
#include "test_utils.h"
// #include "define_lite.h"
#define ARRAY_MAX_STRING (255)
#define ARRAY_MAX_SIZE (100000)
procedure array_test_suite begin
variable arr, i, arr2, map, k, v, s;
test_suite_errors := 0;
display_msg("Testing arrays_equal functions...");
call assertEquals("array_equals 1", arrays_equal([9, 7, 2, 1], [9, 7, 2, 1]), true);
call assertEquals("array_equals 2", arrays_equal([9, 7, 0, 1], [9, 7, 2, 1]), false);
call assertEquals("array_equals 3", arrays_equal([1, 1, 1, 1], [1, 1, 1]), false);
call assertEquals("array_equals 4", arrays_equal([], []), true);
call assertEquals("array_equals 5", arrays_equal({}, []), false);
call assertEquals("array_equals 6", arrays_equal({1: 1.0, 2: 2.0}, {1: 1.000, 2: 2.000}), true);
call assertEquals("array_equals 7", arrays_equal({"name": "John", "dept": 15.20}, {"name": "John"}), false);
display_msg("Testing utility functions...");
call assertEquals("strlen", strlen("testing"), 7);
call assertEquals("substr 1", substr("testing", 4, 2), "in");
call assertEquals("substr 2", substr("testing", 1, -1), "estin");
call assertEquals("substr 3", substr("testing", -5, 5), "sting");
call assertEquals("typeof 1", typeof(1), VALTYPE_INT);
call assertEquals("typeof 2", typeof(1.0), VALTYPE_FLOAT);
call assertEquals("typeof 3", typeof("1.0"), VALTYPE_STR);
// Basic array functionality
display_msg("Testing basic arrays functionality...");
arr := create_array(5,0);
call assertEquals("array size", len_array(arr), 5);
arr[0]:=100;
call assertEquals("get array", get_array(arr, 0), 100);
arr[1]:=5.555;
call assertEquals("get array float", get_array(arr, 1), 5.555);
arr[2]:="hello";
call assertEquals("get array str", get_array(arr, 2), "hello");
call assertEquals("get array invalid index", get_array(arr, -1), 0);
call assertEquals("get array invalid index", get_array(arr, 6), 0);
resize_array(arr, 77);
call assertEquals("list resize", len_array(arr), 77);
resize_array(arr, ARRAY_MAX_SIZE + 100);
call assertEquals("resize max", len_array(arr), ARRAY_MAX_SIZE);
free_array(arr);
call assertEquals("not exists check", len_array(arr), -1);
arr := create_array(ARRAY_MAX_SIZE + 100, 0);
call assertEquals("create max", len_array(arr), ARRAY_MAX_SIZE);
free_array(arr);
arr := [6, 1, 10, "one", 10, "two", 5, "three"];
arr[0] := "wtf";
//display_msg(debug_array_str(arr));
call assertEquals("scan list", scan_array(arr, 10), 2);
call assertEquals("scan list 2", scan_array(arr, "two"), 5);
call assertEquals("array_key", array_key(arr, 5), 5);
call assertEquals("array_key out of range", array_key(arr, 9), 0);
call assertEquals("is list", array_key(arr, -1), 0);
call assertEquals("get array as substr", get_array("NiCe", 1), "i");
arr := [78, 12, 99, 1, -5];
sort_array(arr);
call assertEquals("sort ASC", arrays_equal(arr, [-5, 1, 12, 78, 99]), true);
arr := ["Albert", "John", "Mike", "David"];
sort_array_reverse(arr);
call assertEquals("sort DESC", arrays_equal(arr, ["Mike", "John", "David", "Albert"]), true);
reverse_array(arr);
call assertEquals("reverse list", arrays_equal(arr, ["Albert", "David", "John", "Mike"]), true);
shuffle_array(arr);
call assertEquals("shuffle list 1", arrays_equal(arr, ["Albert", "David", "John", "Mike"]), false);
call assertEquals("shuffle list 2", len_array(arr), 4);
if (test_suite_verbose) then display_array(arr);
// some additional stuff
call assertEquals("string_split", get_array(string_split("this+is+good", "+"), 2), "good");
call assertEquals("string_split 2", len_array(string_split("advice", "")), 6);
s := "";
for (i := 0; i < ARRAY_MAX_STRING+30; i+=10) begin
s += "Verbosity.";
end
arr[0] := s;
call assertEquals("array max string", strlen(arr[0]), ARRAY_MAX_STRING-1);
// ASSOC ARRAYS TEST
display_msg("Testing associative arrays...");
arr := create_array(-1,0);
call assertEquals("is map", array_key(arr, -1), 1);
call assertEquals("exists check", len_array(arr), 0);
arr["123"] := 100;
call assertEquals("set/get str=>int", arr["123"], 100);
arr["123"] := 50;
call assertEquals("overwrite 1", arr["123"], 50);
call assertEquals("overwrite 2", len_array(arr), 1);
arr[-1] := "wtf";
call assertEquals("set/get int=>str", arr[-1], "wtf");
arr[3.14] := 0.00001;
call assertEquals("set/get float=>float", arr[3.14], 0.00001);
arr["fourth"] := "elem";
call assertEquals("map size", len_array(arr), 4);
arr[-1] := 0;
call assertEquals("unset key: length", len_array(arr), 3);
call assertEquals("unset key: hashmap", arr[3.14], 0.00001);
call assertEquals("key not exist", arr[777], 0);
free_array(arr);
call assertEquals("not exists check", len_array(arr), -1);
arr := {6:5, 1.001:0.5, 10:"A", 5:0, "wtf":1.1, 10:0.0001, "some":"What"}; // 7 here
// 10:"A" will be overwritten by 10:0.0001
call assertEquals("assoc array expr", len_array(arr), 6); // 6 actual
call assertEquals("scan map 1", scan_array(arr, 1.1), "wtf");
call assertEquals("scan map 2", scan_array(arr, 5), 6);
call assertEquals("scan map 3", scan_array(arr, "What"), "some");
call assertEquals("array_key 1", array_key(arr, 0), 6);
call assertEquals("array_key 2", array_key(arr, 4), "wtf");
call assertEquals("array_key 3", array_key(arr, 1), 1.001);
resize_array(arr, 2);
call assertEquals("map resize 1", len_array(arr), 2);
call assertEquals("map resize 2", arrays_equal(arr, {6:5, 1.001:0.5}), true);
resize_array(arr, 0);
call assertEquals("map clear", len_array(arr), 0);
display_msg("Testing foreach...");
s := "ar";
arr := [6, 10, 0.5, "wtf"];
foreach v in arr begin
s += v;
end
call assertEquals("foreach 1", s, "ar6100.50000wtf");
s := "ar2=";
arr := {"name": "John", "hp": 25, 0: 5.5};
foreach k: v in arr begin
s += k+":"+v+";";
end
call assertEquals("foreach 2", s, "ar2=name:John;hp:25;0:5.50000;");
/*
display_msg("Testing save/load...");
arr := [2,1];
arr2 := {1:2};
save_array("myarray", arr);
call assertEquals("load 1", load_array("myarray"), arr);
save_array("myarray", arr2);
call assertEquals("load 2", load_array("myarray"), arr2);
free_array(arr2);
call assertEquals("not exists check", len_array(arr2), -1);
call assertEquals("load fail", load_array("myarray"), 0);
save_array(0.1, arr);
call assertEquals("save as float", load_array(0.1), arr);
arr2 := list_saved_arrays; // list of array names
//display_msg(debug_array_str(arr2));
call assertNotEquals("saved arrays 1", scan_array(arr2, 0.1), -1);
call assertEquals("saved arrays 2", scan_array(arr2, "myarray"), -1);
save_array(0, arr);
call assertEquals("unsave array 1", load_array(0.1), 0);
call assertEquals("unsave array 2", len_array(arr), 2);
call assertEquals("saved arrays 3", len_array(list_saved_arrays), len_array(arr2) - 1);
*/
display_msg("All tests finished with "+test_suite_errors+" errors.");
call report_test_results("arrays");
end
procedure start begin
display_msg("Starting tests");
call array_test_suite();
end
-33
View File
@@ -1,33 +0,0 @@
#include "test_utils.h"
#include "sfall.h"
procedure start begin
display_msg("Testing iface_tag functions...");
// assumes no iface tags active in the save game
// SNEAK
show_iface_tag(0);
call assertTrue("show_iface_tag(SNEAK)", is_iface_tag_active(0));
hide_iface_tag(0);
call assertFalse("hide_iface_tag(SNEAK)", is_iface_tag_active(0));
// LEVEL
show_iface_tag(3);
call assertTrue("show_iface_tag(LEVEL)", is_iface_tag_active(3));
hide_iface_tag(3);
call assertFalse("hide_iface_tag(LEVEL)", is_iface_tag_active(3));
// ADDICTED
show_iface_tag(4);
call assertTrue("show_iface_tag(ADDICTED)", is_iface_tag_active(4));
hide_iface_tag(4);
call assertFalse("hide_iface_tag(ADDICTED)", is_iface_tag_active(4));
// POISONED
call assertFalse("hide_iface_tag(POISONED)", is_iface_tag_active(1));
// RADIATED
call assertFalse("hide_iface_tag(RADIATED)", is_iface_tag_active(2));
call report_test_results("iface_tag");
end
-69
View File
@@ -1,69 +0,0 @@
#include "lib.arrays.h" // For arrays_equal, len_array, etc.
#include "test_utils.h" // For assertEquals, VALTYPE_STR, report_test_results
// To test: copy test.ini into the game folder before running
procedure ini_test_suite begin
variable result_array, expected_array, key_type, value_type, count, key_val_pair;
display_msg("--- Testing ini functions");
// Test Case 1: Valid file, valid section
result_array := get_ini_section("test.ini", "ValidSection");
expected_array := {"Key1": "Value1", "Key2": "2"};
call assertEquals("TC1 Size", len_array(result_array), 2);
call assertEquals("TC1 Content", arrays_equal(result_array, expected_array), true);
count := 0;
foreach key_val_pair in result_array begin
count += 1;
call assertEquals("TC1 Key Type " + count, typeof(key_val_pair[0]), VALTYPE_STR);
call assertEquals("TC1 Value Type " + count, typeof(key_val_pair[1]), VALTYPE_STR);
end
// basic fetchers
call assertEquals("TC2 Specific Key1 Value", result_array["Key1"], "Value1");
call assertEquals("TC2 get_ini_setting string", get_ini_setting("test.ini|ValidSection|Key1"), 0);
call assertEquals("TC2 get_ini_string string", get_ini_string("test.ini|ValidSection|Key1"), "Value1");
call assertEquals("TC2 get_ini_setting int", get_ini_setting("test.ini|ValidSection|Key2"), 2);
call assertEquals("TC2 get_ini_string int", get_ini_string("test.ini|ValidSection|Key2"), "2");
// INI file not found
result_array := get_ini_section("nonexistent.ini", "AnySection");
call assertEquals("TC3 Size", len_array(result_array), 0);
call assertEquals("TC3 Is Map", array_key(result_array, -1), 1); // Should still be an associative array
call assertEquals("TC3 get_ini_setting", get_ini_setting("notexist.ini|ValidSection|Key2"), 0);
call assertEquals("TC3 get_ini_string", get_ini_string("notexist.ini|ValidSection|Key2"), "");
// Valid file, section not found
result_array := get_ini_section("test.ini", "NonExistentSection");
call assertEquals("TC4 Size", len_array(result_array), 0);
call assertEquals("TC4 Is Map", array_key(result_array, -1), 1);
call assertEquals("TC4 get_ini_setting", get_ini_setting("test.ini|NonExistentSection|Key2"), 0);
call assertEquals("TC4 get_ini_string", get_ini_string("test.ini|NonExistentSection|Key2"), "");
// Valid file, empty section
result_array := get_ini_section("test.ini", "EmptySection");
call assertEquals("TC5 Size", len_array(result_array), 0);
call assertEquals("TC5 Is Map", array_key(result_array, -1), 1);
call assertEquals("TC5 get_ini_setting", get_ini_setting("test.ini|EmptySection|Key2"), 0);
call assertEquals("TC5 get_ini_string", get_ini_string("test.ini|EmptySection|Key2"), "");
// set ini setting
set_ini_setting("test_set.ini|ValidSection|Key3", "OldValue");
call assertEquals("TC6 set_ini_setting 1", get_ini_string("test_set.ini|ValidSection|Key3"), "OldValue");
set_ini_setting("test_set.ini|ValidSection|Key3", "NewValue");
call assertEquals("TC6 set_ini_setting 2", get_ini_string("test_set.ini|ValidSection|Key3"), "NewValue");
set_ini_setting("test_set.ini|ValidSection|Key3", 2);
call assertEquals("TC6 set_ini_setting int", get_ini_setting("test_set.ini|ValidSection|Key3"), 2);
// get_init_sections
result_array := get_ini_sections("test.ini");
call assertEquals("TC7 get_ini_sections size", len_array(result_array), 3);
call assertTrue("TC7 get_ini_sections", scan_array(result_array, "TestMisc") >= 0);
call report_test_results("ini");
end
procedure start begin
call ini_test_suite();
end
-71
View File
@@ -1,71 +0,0 @@
#include "test_utils.h"
#include "sfall.h"
procedure start begin
display_msg("Testing math functions...");
call assertFloat("sin(0)", sin(0), 0.0);
call assertFloat("sin(PI/2)", sin(1.5708), 1.0);
call assertFloat("sin(PI)", sin(3.1416), 0.0);
call assertFloat("sin(-PI/2)", sin(-1.5708), -1.0);
call assertFloat("cos(0)", cos(0), 1.0);
call assertFloat("cos(PI/2)", cos(1.5708), 0.0);
call assertFloat("cos(PI)", cos(3.1416), -1.0);
call assertFloat("cos(-PI)", cos(-3.1416), -1.0);
call assertFloat("tan(0)", tan(0), 0.0);
call assertFloat("tan(PI/4)", tan(0.7854), 1.0);
call assertFloat("tan(-PI/4)", tan(-0.7854), -1.0);
call assertFloat("arctan(0, 1)", arctan(0, 1), 0.0);
call assertFloat("arctan(1, 1)", arctan(1, 1), 0.7854);
call assertFloat("arctan(-1, 1)", arctan(-1, 1), -0.7854);
call assertFloat("arctan(1, 0)", arctan(1, 0), 1.5708);
call assertFloat("log(1)", log(1), 0.0);
call assertFloat("log(e)", log(2.7183), 1.0);
call assertFloat("log(10)", log(10), 2.3026);
call assertFloat("exponent(0)", exponent(0), 1.0);
call assertFloat("exponent(1)", exponent(1), 2.7183);
call assertFloat("exponent(2)", exponent(2), 7.3891);
call assertFloat("exponent(-1)", exponent(-1), 0.3679);
call assertEquals("ceil(2.1)", ceil(2.1), 3);
call assertEquals("ceil(2.0)", ceil(2.0), 2);
call assertEquals("ceil(-2.1)", ceil(-2.1), -2);
call assertEquals("ceil(-2.9)", ceil(-2.9), -2);
call assertEquals("floor2(2.1)", floor2(2.1), 2);
call assertEquals("floor2(2.9)", floor2(2.9), 2);
call assertEquals("floor2(-2.1)", floor2(-2.1), -3);
call assertEquals("floor2(-2.9)", floor2(-2.9), -3);
call assertEquals("2^3", 2^3, 8);
call assertEquals("4^2", 4^2, 16);
call assertEquals("3^0", 3^0, 1);
call assertFloat("2^-1", 2^-1, 0); // note: int truncation
call assertFloat("2^-1", 2^-1.0, 0.5);
call assertFloat("4^0.5", 4^0.5, 2.0);
call assertFloat("8^(1/3)", 8^(1.0/3.0), 2.0);
call assertFloat("2.5^2", 2.5^2, 6.25);
call assertEquals("round(2.3)", round(2.3), 2);
call assertEquals("round(2.5)", round(2.5), 3);
call assertEquals("round(2.7)", round(2.7), 3);
call assertEquals("round(-2.3)", round(-2.3), -2);
call assertEquals("round(-2.5)", round(-2.5), -3);
call assertEquals("round(-2.7)", round(-2.7), -3);
call assertEquals("round(0.0)", round(0.0), 0);
call assertEquals("round(1.0)", round(1.0), 1);
call assertEquals("round(<int>)", round(1), 1);
call assertFloat("sin(arctan(1, 1))", sin(arctan(1, 1)), 0.7071);
call assertFloat("cos(arctan(1, 1))", cos(arctan(1, 1)), 0.7071);
call assertFloat("log(ceil(2.7))", log(ceil(2.7)), 1.0986);
call assertFloat("exponent(log(5))", exponent(log(5)), 5.0);
call report_test_results("math");
end
-14
View File
@@ -1,14 +0,0 @@
#include "sfall.h"
// this is the basic message_box function used by RPU and Et Tu
#define message_box_warning(text) message_box4(text, 0x01, 134, 145)
procedure start begin
// I don't see a practice way to auto test message_box, so this is just a way to do manual testing
variable ret = message_box1("Basic Dialog\nwith multiple lines\nand such.");
display_msg("chose: " + ret);
message_box2("Basic Dialog\nwith default flags.", -1); // -1 means use default flags
message_box2("Basic Dialog\nsmall.", 0x02);
message_box_warning("Missing config values\n(just testing).");
end
-30
View File
@@ -1,30 +0,0 @@
#include "test_utils.h"
#include "sfall.h"
procedure start begin
display_msg("Testing metarule_exist functions...");
call assertEquals("string_format", metarule_exist("string_format"), 1);
call assertEquals("metarule_exist", metarule_exist("metarule_exist"), 1);
// This will fail on sFall
call assertEquals("opcode_exists", metarule_exist("opcode_exists"), 1);
if metarule_exist("opcode_exists") then begin // And example if how to use it
#define opcode_exists(opcode) sfall_func1("opcode_exists", opcode)
#define OP_GET_UPTIME 0x81B3
#define OP_NOOP 0x8000
#define OP_WRITE_INT 0x81D1
call assertEquals("opcode_exists OP_GET_UPTIME", opcode_exists(OP_GET_UPTIME), 1);
call assertEquals("opcode_exists OP_NOOP", opcode_exists(OP_NOOP), 1);
// Probably will never be implemented on fallout2-ce
call assertEquals("opcode_exists OP_WRITE_INT", opcode_exists(OP_WRITE_INT), 0);
call assertEquals("opcode_exists 0xFFFF", opcode_exists(0xFFFF), 0);
end else begin
display_msg("Opcode exists metarule is not available, skipping tests.");
end
call report_test_results("metarule_exist");
end
-15
View File
@@ -1,15 +0,0 @@
#include "test_utils.h"
#include "sfall.h"
procedure start begin
// TODO: move this to a more suitable place, once we have more functions implemented
// These are in the "Other" category in the sfall documentation
display_msg("Testing misc functions...");
variable hand := active_hand;
toggle_active_hand;
call assertEquals("active_hand toggled", active_hand, 1 - hand);
toggle_active_hand;
call assertEquals("active_hand toggled", active_hand, hand);
call report_test_results("misc");
end
-82
View File
@@ -1,82 +0,0 @@
#include "test_utils.h"
#include "sfall.h"
#define REPEAT_64 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
#define REPEAT_512 REPEAT_64 REPEAT_64 REPEAT_64 REPEAT_64 REPEAT_64 REPEAT_64 REPEAT_64 REPEAT_64
#define REPEAT_1024 REPEAT_512 REPEAT_512
procedure start begin
display_msg("Testing sprintf...");
call assertEquals("sprintf hello world", sprintf("Hello %s", "World"), "Hello World");
call assertEquals("sprintf empty string", sprintf("", 123), "");
call assertEquals("sprintf number string", sprintf("%d", 123), "123");
call assertEquals("sprintf number inside string", sprintf("Hello %d !", 123), "Hello 123 !");
call assertEquals("sprintf ascii code", sprintf("Hello %c !", 123), "Hello { !");
call assertEquals("sprintf float string", sprintf("Hello %f !", 3.4), "Hello 3.400000 !");
call assertEquals("sprintf float string", sprintf("Hello %d !", 10/4), "Hello 2 !");
call assertEquals("sprintf two strings", sprintf("Hello %s %s", "World"), "Hello World World");
call assertEquals("Long string", sprintf(REPEAT_1024"x", 1), "Error");
call assertEquals("Not so long", sprintf(REPEAT_1024, 1), REPEAT_1024);
call assertEquals("string_format1 hello world", string_format1("Hello %s!", "World"), "Hello World!");
call assertEquals("string_format1 auto hello world", string_format("Hello %s!", "World"), "Hello World!");
call assertEquals("string_format2 hello world", string_format2("Hello %s%s!", "Wo","rld"), "Hello World!");
call assertEquals("string_format2 auto hello world", string_format("Hello %s%s!", "Wo","rld"), "Hello World!");
call assertEquals("string_format3 hello world", string_format3("Hell%s %s%s!", "o", "Wo","rld"), "Hello World!");
call assertEquals("string_format3 auto hello world", string_format("Hell%s %s%s!", "o", "Wo","rld"), "Hello World!");
call assertEquals("string_format4 hello world", string_format4("Hel%s%s %s%s!", "l", "o", "Wo","rld"), "Hello World!");
call assertEquals("string_format4 auto hello world", string_format("Hel%s%s %s%s!", "l", "o", "Wo","rld"), "Hello World!");
call assertEquals("string_format5 hello world", string_format5("He%s%s%s %s%s!", "l", "l", "o", "Wo","rld"), "Hello World!");
call assertEquals("string_format5 auto hello world", string_format("He%s%s%s %s%s!", "l", "l", "o", "Wo","rld"), "Hello World!");
call assertEquals("string_format6 hello world", string_format6("H%s%s%s%s %s%s!", "e", "l", "l", "o", "Wo","rld"), "Hello World!");
call assertEquals("string_format6 auto hello world", string_format("H%s%s%s%s %s%s!", "e", "l", "l", "o", "Wo","rld"), "Hello World!");
call assertEquals("string_format7 hello world", string_format7("%s%s%s%s%s %s%s!", "H", "e", "l", "l", "o", "Wo","rld"), "Hello World!");
call assertEquals("string_format7 auto hello world", string_format("%s%s%s%s%s %s%s!", "H", "e", "l", "l", "o", "Wo","rld"), "Hello World!");
call assertEquals("formatted string length 1024", strlen(sprintf(REPEAT_1024, 1)), 1024);
call assertEquals("formatted string length 5119", strlen(
string_format7(
"%s%s%s%s%s%s%s",
REPEAT_1024,
REPEAT_1024,
REPEAT_1024,
REPEAT_1024,
REPEAT_1024,
REPEAT_1024,
REPEAT_1024)), 5119);
call assertEquals("string_tolower", string_tolower("miXeD CaSe"), "mixed case");
call assertEquals("string_toupper", string_toupper("miXeD CaSe"), "MIXED CASE");
call assertEquals("string_find ok", string_find("Hello World", "World"), 6);
call assertEquals("string_find missing", string_find("Hello World", "Zebra"), -1);
call assertEquals("string_find_from", string_find_from("Hello World", "o", 6), 7);
call assertEquals("string_compare ok", string_compare("Hello World", "HeLlO WoRld"), 1);
call assertEquals("string_compare neq", string_compare("Hello World", "HeLlO WoRld!"), 0);
call assertEquals("string_compare_locale", string_compare_locale("Hello World", "HeLlO WoRld", 866), 1); // TODO: would be nice to compare cyrillic
call assertEquals("charcode", charcode("A"), 65);
call assertEquals("charcode empty", charcode(""), 0);
call report_test_results("sprintf");
end
-162
View File
@@ -1,162 +0,0 @@
#include "define_lite.h"
#include "sfall.h"
#include "test_utils.h"
#include "command_lite.h"
procedure test_stat_pc(variable stat_id) begin
display_msg("Stat " + stat_id + " = " +
get_pc_base_stat(stat_id) + " + " +
get_pc_extra_stat(stat_id));
call assertNotEquals("Not interesting stat, base stat is zero", get_pc_base_stat(stat_id), 0);
variable old_base_stat := get_pc_base_stat(stat_id);
variable old_extra_stat := get_pc_extra_stat(stat_id);
set_pc_base_stat(stat_id, old_base_stat + 2);
set_pc_extra_stat(stat_id, old_extra_stat + 4);
// display_msg("Stat after update " + stat_id + " = " +
// get_pc_base_stat(stat_id) + " + " +
// get_pc_extra_stat(stat_id));
if (stat_id > STAT_lu) then begin
call assertNotEquals("Base stat was updated while it shouldn't",
get_pc_base_stat(stat_id), old_base_stat + 2);
end else begin
call assertEquals("Base stat updated",
get_pc_base_stat(stat_id), old_base_stat + 2);
end
set_pc_base_stat(stat_id, old_base_stat);
set_pc_extra_stat(stat_id, old_extra_stat);
// display_msg("Stat after reset " + stat_id + " = " +
// get_pc_base_stat(stat_id) + " + " +
// get_pc_extra_stat(stat_id));
call assertEquals("Base stat reset",
get_pc_base_stat(stat_id), old_base_stat);
call assertEquals("Extra stat reset",
get_pc_extra_stat(stat_id), old_extra_stat);
end
procedure test_stat_critter(variable critter, variable stat_id) begin
display_msg("Stat " + stat_id + " = " +
get_critter_base_stat(critter, stat_id) + " + " +
get_critter_extra_stat(critter, stat_id));
call assertNotEquals("Not interesting stat, base stat is zero",
get_critter_base_stat(critter, stat_id), 0);
variable old_base_stat := get_critter_base_stat(critter, stat_id);
variable old_extra_stat := get_critter_extra_stat(critter, stat_id);
set_critter_base_stat(critter, stat_id, old_base_stat + 2);
set_critter_extra_stat(critter, stat_id, old_extra_stat + 4);
// display_msg("Stat after update " + stat_id + " = " +
// get_critter_base_stat(critter, stat_id) + " + " +
// get_critter_extra_stat(critter, stat_id));
if (stat_id > STAT_lu) then begin
call assertNotEquals("Base stat was updated while it shouldn't",
get_critter_base_stat(critter, stat_id), old_base_stat + 2);
end else begin
call assertEquals("Base stat updated",
get_critter_base_stat(critter, stat_id), old_base_stat + 2);
end
set_critter_base_stat(critter, stat_id, old_base_stat);
set_critter_extra_stat(critter, stat_id, old_extra_stat);
// display_msg("Stat after reset " + stat_id + " = " +
// get_critter_base_stat(critter, stat_id) + " + " +
// get_critter_extra_stat(critter, stat_id));
call assertEquals("Base stat reset",
get_critter_base_stat(critter, stat_id), old_base_stat);
call assertEquals("Extra stat reset",
get_critter_extra_stat(critter, stat_id), old_extra_stat);
end
procedure test_derived_base_stat_critter(variable critter) begin
display_msg("Testing derived stats on " + obj_name(critter));
variable old_agility;
old_agility := get_critter_base_stat(critter, STAT_ag);
call assertNotEquals("Initial agility is 10", old_agility, 10);
call assertNotEquals("Action points is 10 while agility is not 10", get_critter_base_stat(critter, STAT_max_move_points), 10);
set_critter_base_stat(critter, STAT_ag, 10);
call assertEquals("Action points updated to 10",
get_critter_base_stat(critter, STAT_max_move_points), 10);
set_critter_base_stat(critter, STAT_ag, old_agility);
call assertNotEquals("Action points updated from 10",
get_critter_base_stat(critter, STAT_max_move_points), 10);
end
procedure start begin
display_msg("Testing stats...");
test_suite_errors := 0;
call test_stat_pc(STAT_max_hit_points);
call test_stat_pc(STAT_lu);
variable critter;
variable closest_critter := dude_obj;
foreach critter in list_as_array(LIST_CRITTERS) begin
if (is_critter_dead(critter)) then begin
continue;
end
if tile_distance(dude_tile, tile_num(critter)) == 0 then begin
continue;
end
if (tile_distance(dude_tile, tile_num(critter)) <
tile_distance(dude_tile, tile_num(closest_critter))) or
(closest_critter == dude_obj)
then begin
closest_critter := critter;
end
end
// display_msg("Closest " + obj_name(closest_critter) + " distance: " +
// tile_distance(dude_tile, tile_num(closest_critter)));
call test_stat_critter(dude_obj, STAT_max_hit_points);
call test_stat_critter(dude_obj, STAT_lu);
if closest_critter != dude_obj then begin
display_msg("Testing stats for " + obj_name(closest_critter));
call test_stat_critter(closest_critter, STAT_max_hit_points);
call test_stat_critter(closest_critter, STAT_lu);
end else begin
display_msg("FAIL: No other critters found to test stats");
test_suite_errors++;
end
if
get_critter_base_stat(dude_obj, STAT_lu) ==
get_critter_base_stat(closest_critter, STAT_lu)
and
get_critter_extra_stat(dude_obj, STAT_max_hit_points) ==
get_critter_extra_stat(closest_critter, STAT_max_hit_points) then begin
display_msg("FAIL: Very sus eq values for dude and closest critter");
test_suite_errors++;
end
call test_derived_base_stat_critter(dude_obj);
call test_derived_base_stat_critter(closest_critter);
call report_test_results("stats");
// set_pc_base_stat(STAT_lu, 10);
// set_pc_extra_stat(STAT_max_hit_points, 500);
end

Some files were not shown because too many files have changed in this diff Show More