mirror of
https://github.com/fallout2-ce/fallout2-ce.git
synced 2026-07-27 16:47:11 -07:00
Compare commits
106
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a59d88f9f5 | ||
|
|
7767aabdce | ||
|
|
9cb2b83db1 | ||
|
|
75ca12e07c | ||
|
|
f85e8ba67b | ||
|
|
07876ddaf9 | ||
|
|
7288f8eeb7 | ||
|
|
1a46d0f59f | ||
|
|
7c2dfa9af1 | ||
|
|
d681e7be69 | ||
|
|
8294e15d3c | ||
|
|
4278d1a1d0 | ||
|
|
b2675ad1ac | ||
|
|
5dafa019c9 | ||
|
|
8888fc46d6 | ||
|
|
001bdbee5c | ||
|
|
40471e5a0b | ||
|
|
ad776876a1 | ||
|
|
224f1088f2 | ||
|
|
05b692f403 | ||
|
|
190906bb5f | ||
|
|
41dd2ccd81 | ||
|
|
04e93cabd7 | ||
|
|
a31af0671d | ||
|
|
72df28f53a | ||
|
|
7e3bd36f86 | ||
|
|
94ce0fbe11 | ||
|
|
a368f27ad4 | ||
|
|
d8d411e847 | ||
|
|
5eef9af7a9 | ||
|
|
0419efad8f | ||
|
|
21f432afbb | ||
|
|
aed05c0daf | ||
|
|
8a8b54d4b7 | ||
|
|
8ee543ec16 | ||
|
|
161bb82f30 | ||
|
|
22bd1ffbba | ||
|
|
f46f1c78d4 | ||
|
|
3d0e206825 | ||
|
|
47a9891e0e | ||
|
|
f1e5cde84f | ||
|
|
015909fdef | ||
|
|
1e91b401f1 | ||
|
|
29a0be50f4 | ||
|
|
9e3ce4cd8d | ||
|
|
592882b7b8 | ||
|
|
cbd7b45736 | ||
|
|
220fb8e190 | ||
|
|
5a29fc1815 | ||
|
|
a083779fb2 | ||
|
|
95d254cd45 | ||
|
|
0d8f4cc711 | ||
|
|
aabc971dd5 | ||
|
|
b069e3b941 | ||
|
|
823f72492f | ||
|
|
e5f3734e08 | ||
|
|
e37522d388 | ||
|
|
07a361f63a | ||
|
|
515bec4c82 | ||
|
|
42bfdc7343 | ||
|
|
0fd5e59575 | ||
|
|
0d0578f111 | ||
|
|
dacda99b98 | ||
|
|
dfb0463b02 | ||
|
|
1903e04c6e | ||
|
|
abec3681b0 | ||
|
|
5a9f8fb46c | ||
|
|
3659c834ae | ||
|
|
196553ec46 | ||
|
|
57f1229a51 | ||
|
|
413c843ff5 | ||
|
|
995102d515 | ||
|
|
dd867446ea | ||
|
|
4f91e38cc0 | ||
|
|
016c83bc48 | ||
|
|
d8dc05597b | ||
|
|
7d9e1612c6 | ||
|
|
848bd97e42 | ||
|
|
5c5512277d | ||
|
|
016f853c0a | ||
|
|
9edbf0dd72 | ||
|
|
36af4b2ea8 | ||
|
|
145cf6bbcc | ||
|
|
5b39307f61 | ||
|
|
547cabc42d | ||
|
|
d2a3d61dcb | ||
|
|
2d1966f0af | ||
|
|
a406c5f019 | ||
|
|
9ca540f05e | ||
|
|
4678e19edd | ||
|
|
485d2253f4 | ||
|
|
72309fc9dc | ||
|
|
fda6fd0646 | ||
|
|
2126e23161 | ||
|
|
0fa90a1a00 | ||
|
|
9bfc3e83cd | ||
|
|
2f974aefed | ||
|
|
b27093b7ac | ||
|
|
6f240acf0a | ||
|
|
5dbcfd997c | ||
|
|
a3d37e11c1 | ||
|
|
0e18e77901 | ||
|
|
9d2db5b36a | ||
|
|
b88230426d | ||
|
|
bbf52f6b2d | ||
|
|
89a9d1ae12 |
@@ -0,0 +1,42 @@
|
||||
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
|
||||
|
||||
|
||||
@@ -89,6 +89,7 @@ jobs:
|
||||
folder: fallout2-ce-ems/dist
|
||||
target-folder: ${{ steps.set-path.outputs.DEST_DIR }}
|
||||
clean: false
|
||||
single-commit: true
|
||||
|
||||
- name: Comment preview URL on PR
|
||||
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
|
||||
|
||||
@@ -313,7 +313,7 @@ jobs:
|
||||
windows:
|
||||
name: Windows (${{ matrix.arch }})
|
||||
|
||||
runs-on: windows-2019
|
||||
runs-on: windows-2025
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -328,19 +328,28 @@ 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-v2
|
||||
key: windows-${{ matrix.arch }}-cmake-v3
|
||||
|
||||
- name: Configure
|
||||
shell: cmd
|
||||
run: |
|
||||
cmake --preset windows-${{ matrix.arch }}
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\Common7\Tools\VsDevCmd.bat" ^
|
||||
&& cmake --preset windows-${{ matrix.arch }}
|
||||
|
||||
- name: Build
|
||||
shell: cmd
|
||||
run: |
|
||||
cmake --build --preset windows-${{ matrix.arch }}-release
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\Common7\Tools\VsDevCmd.bat" ^
|
||||
&& cmake --build --preset windows-${{ matrix.arch }}-release
|
||||
|
||||
- name: Change executable file name
|
||||
run: |
|
||||
|
||||
@@ -29,5 +29,18 @@ jobs:
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git commit -am "đźš® Remove preview for closed PR #${{ github.event.pull_request.number }}"
|
||||
git push
|
||||
|
||||
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
|
||||
@@ -243,7 +243,7 @@ jobs:
|
||||
windows:
|
||||
name: Windows (${{ matrix.arch }})
|
||||
|
||||
runs-on: windows-2019
|
||||
runs-on: windows-2025
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -258,6 +258,11 @@ 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:
|
||||
@@ -265,19 +270,16 @@ jobs:
|
||||
key: windows-${{ matrix.arch }}-cmake-v1
|
||||
|
||||
- name: Configure
|
||||
shell: cmd
|
||||
run: |
|
||||
cmake \
|
||||
-B build \
|
||||
-G "Visual Studio 16 2019" \
|
||||
-A ${{ matrix.generator-platform }} \
|
||||
# EOL
|
||||
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 }}
|
||||
|
||||
- name: Build
|
||||
shell: cmd
|
||||
run: |
|
||||
cmake \
|
||||
--build build \
|
||||
--config RelWithDebInfo \
|
||||
# EOL
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\Common7\Tools\VsDevCmd.bat" ^
|
||||
&& cmake --build build --config RelWithDebInfo
|
||||
|
||||
- name: Upload
|
||||
run: |
|
||||
|
||||
@@ -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,6 +141,17 @@ 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.
|
||||
|
||||
+2
-1
@@ -4,7 +4,8 @@
|
||||
[Main]
|
||||
|
||||
;Set to one to hide areas outside map bounds when using higher than 640x480 resolution, and to zero to disable
|
||||
;HiResMode=1
|
||||
;EnableHighResolutionStencil=1
|
||||
|
||||
|
||||
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
[Misc]
|
||||
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
#!/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'
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
*.int
|
||||
@@ -0,0 +1,51 @@
|
||||
# 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
|
||||
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
#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
|
||||
@@ -0,0 +1,189 @@
|
||||
#include "constants.h"
|
||||
#include "headers/define_extra.h" // For sfall functions if not in constants
|
||||
|
||||
procedure start;
|
||||
procedure description_proc; // For visual checks during game
|
||||
|
||||
variable new_tag1_id = -1;
|
||||
variable new_tag2_id = -1;
|
||||
variable max_tags_test_id = -1;
|
||||
|
||||
procedure start begin
|
||||
// Test Predefined Tags
|
||||
debug_msg("Testing Predefined Interface Tags...");
|
||||
|
||||
// SNEAK (0)
|
||||
debug_msg("Activating SNEAK (0)...");
|
||||
show_iface_tag(0);
|
||||
if (is_iface_tag_active(0)) then
|
||||
debug_msg("SNEAK is active. (Visual check needed)");
|
||||
else
|
||||
debug_msg("ERROR: SNEAK failed to activate or is_iface_tag_active(0) failed.");
|
||||
hide_iface_tag(0);
|
||||
if (not is_iface_tag_active(0)) then
|
||||
debug_msg("SNEAK is inactive.");
|
||||
else
|
||||
debug_msg("ERROR: SNEAK failed to deactivate or is_iface_tag_active(0) failed after hide.");
|
||||
|
||||
// POISONED (1) - Test requires making the player poisoned by other means to truly verify show/hide effect on game state
|
||||
// For now, just test is_iface_tag_active if it reflects direct calls or underlying state.
|
||||
// The opcodes show_iface_tag/hide_iface_tag are not meant to directly poison/cure the player for tags 1 and 2.
|
||||
// They are for custom tags or the specific PC flags (0,3,4). is_iface_tag_active *should* work for 1 and 2.
|
||||
debug_msg("Checking POISONED (1) (depends on game state): " + is_iface_tag_active(1));
|
||||
// Similar for RADIATED (2)
|
||||
debug_msg("Checking RADIATED (2) (depends on game state): " + is_iface_tag_active(2));
|
||||
|
||||
|
||||
// LEVEL (3)
|
||||
debug_msg("Activating LEVEL (3)...");
|
||||
show_iface_tag(3);
|
||||
if (is_iface_tag_active(3)) then
|
||||
debug_msg("LEVEL is active. (Visual check needed)");
|
||||
else
|
||||
debug_msg("ERROR: LEVEL failed to activate or is_iface_tag_active(3) failed.");
|
||||
hide_iface_tag(3);
|
||||
if (not is_iface_tag_active(3)) then
|
||||
debug_msg("LEVEL is inactive.");
|
||||
else
|
||||
debug_msg("ERROR: LEVEL failed to deactivate or is_iface_tag_active(3) failed after hide.");
|
||||
|
||||
// ADDICT (4)
|
||||
debug_msg("Activating ADDICT (4)...");
|
||||
show_iface_tag(4);
|
||||
if (is_iface_tag_active(4)) then
|
||||
debug_msg("ADDICT is active. (Visual check needed)");
|
||||
else
|
||||
debug_msg("ERROR: ADDICT failed to activate or is_iface_tag_active(4) failed.");
|
||||
hide_iface_tag(4);
|
||||
if (not is_iface_tag_active(4)) then
|
||||
debug_msg("ADDICT is inactive.");
|
||||
else
|
||||
debug_msg("ERROR: ADDICT failed to deactivate or is_iface_tag_active(4) failed after hide.");
|
||||
|
||||
debug_msg("Predefined tag tests complete.");
|
||||
debug_msg("---");
|
||||
|
||||
// Test Custom Tags
|
||||
debug_msg("Testing Custom Interface Tags...");
|
||||
|
||||
// Add first custom tag
|
||||
new_tag1_id = add_iface_tag;
|
||||
if (new_tag1_id != -1) then
|
||||
debug_msg("Added custom tag 1 with ID: " + new_tag1_id + " (expected 5 if first)");
|
||||
else
|
||||
debug_msg("ERROR: Failed to add custom tag 1.");
|
||||
return; // Stop if first add fails
|
||||
|
||||
// Show it
|
||||
show_iface_tag(new_tag1_id);
|
||||
if (is_iface_tag_active(new_tag1_id)) then
|
||||
debug_msg("Custom tag 1 is active. (Visual check: should show 'NEW' in green)");
|
||||
else
|
||||
debug_msg("ERROR: Custom tag 1 failed to activate or is_iface_tag_active failed.");
|
||||
|
||||
// Set its text and color
|
||||
set_iface_tag_text(new_tag1_id, "HELLO TAG1", 2); // Color 2 (White from issue description's reference)
|
||||
debug_msg("Set text for custom tag 1 to 'HELLO TAG1' (color white). (Visual check needed)");
|
||||
// Verify text length truncation (19 chars)
|
||||
set_iface_tag_text(new_tag1_id, "ThisIsAVeryLongTextStringIndeed", 3); // Color 3 (Yellow)
|
||||
debug_msg("Set text for custom tag 1 to 'ThisIsAVeryLongTextStringIndeed' (color yellow) - should be truncated. (Visual check needed)");
|
||||
|
||||
|
||||
// Add second custom tag
|
||||
new_tag2_id = add_iface_tag;
|
||||
if (new_tag2_id != -1) then
|
||||
debug_msg("Added custom tag 2 with ID: " + new_tag2_id + " (expected 6 if second)");
|
||||
else
|
||||
debug_msg("ERROR: Failed to add custom tag 2.");
|
||||
// Continue to test tag1 hide
|
||||
|
||||
if (new_tag2_id != -1) then
|
||||
show_iface_tag(new_tag2_id);
|
||||
set_iface_tag_text(new_tag2_id, "AWESOME", 6); // Color 6 (GoodColor/Green)
|
||||
debug_msg("Custom tag 2 ('AWESOME', green) should be active. (Visual check needed)");
|
||||
end
|
||||
|
||||
// Hide first custom tag
|
||||
hide_iface_tag(new_tag1_id);
|
||||
if (not is_iface_tag_active(new_tag1_id)) then
|
||||
debug_msg("Custom tag 1 is now inactive.");
|
||||
else
|
||||
debug_msg("ERROR: Custom tag 1 failed to deactivate.");
|
||||
|
||||
if (new_tag2_id != -1 and is_iface_tag_active(new_tag2_id)) then
|
||||
debug_msg("Custom tag 2 should still be active. (Visual check needed)");
|
||||
else if (new_tag2_id != -1) then
|
||||
debug_msg("ERROR: Custom tag 2 became inactive or failed check.");
|
||||
end
|
||||
|
||||
// Test max tags
|
||||
debug_msg("Attempting to add maximum custom tags (up to 126)...");
|
||||
variable i;
|
||||
variable current_tags = 2; // Assuming new_tag1_id and new_tag2_id were successful (IDs 5 and 6)
|
||||
if (new_tag1_id == -1) then current_tags = 0;
|
||||
if (new_tag1_id != -1 and new_tag2_id == -1) then current_tags = 1;
|
||||
|
||||
|
||||
for (i = current_tags; i < 126; i++) begin
|
||||
max_tags_test_id = add_iface_tag;
|
||||
if (max_tags_test_id == -1) then begin
|
||||
debug_msg("ERROR: Failed to add tag at iteration " + i + ". Max tags might be less than 126 or error in add_iface_tag.");
|
||||
break;
|
||||
end
|
||||
// Minimal show/set_text to ensure they are processed
|
||||
show_iface_tag(max_tags_test_id);
|
||||
set_iface_tag_text(max_tags_test_id, "Tag " + max_tags_test_id, 0); // Default color
|
||||
end
|
||||
if (i == 126) then
|
||||
debug_msg("Successfully added up to 126 custom tags (IDs 5 through 130). Last ID: " + max_tags_test_id);
|
||||
else
|
||||
debug_msg("Stopped adding tags at count " + i + ". Last successful ID: " + max_tags_test_id);
|
||||
end
|
||||
|
||||
// Test adding one more tag (should fail if 126 was the limit)
|
||||
max_tags_test_id = add_iface_tag;
|
||||
if (max_tags_test_id == -1) then
|
||||
debug_msg("Correctly failed to add tag beyond limit (127th attempt).");
|
||||
else
|
||||
debug_msg("ERROR: Added tag beyond 126 limit! ID: " + max_tags_test_id);
|
||||
end
|
||||
|
||||
// Test invalid IDs
|
||||
debug_msg("Testing invalid tag IDs...");
|
||||
show_iface_tag(-1); // Invalid
|
||||
show_iface_tag(1000); // Likely invalid (beyond max added)
|
||||
hide_iface_tag(-2);
|
||||
hide_iface_tag(1001);
|
||||
debug_msg("is_iface_tag_active(-3): " + is_iface_tag_active(-3));
|
||||
debug_msg("is_iface_tag_active(1002): " + is_iface_tag_active(1002));
|
||||
set_iface_tag_text(-4, "INVALID", 0);
|
||||
set_iface_tag_text(1003, "INVALID", 0);
|
||||
debug_msg("Invalid ID tests complete (check console for debug prints from C++).");
|
||||
|
||||
debug_msg("---");
|
||||
debug_msg("Interface Tag testing complete. Check console and game screen.");
|
||||
debug_msg("Will keep some tags active for 10 seconds for visual check then clear...");
|
||||
|
||||
// Keep some tags visible for a moment if run in game
|
||||
// This part is for easier visual checking if you load a game with this script.
|
||||
// For automated testing, the debug_msg output is key.
|
||||
if (game_loaded) then begin
|
||||
if (new_tag1_id != -1) then hide_iface_tag(new_tag1_id); // ensure it's hidden from previous test
|
||||
if (new_tag2_id != -1) then show_iface_tag(new_tag2_id); // ensure tag2 is visible
|
||||
set_iface_tag_text(new_tag2_id, "Testing Done!", 4); // Peanut butter color
|
||||
game_time_advance(game_ticks(10)); // Wait 10 seconds
|
||||
if (new_tag2_id != -1) then hide_iface_tag(new_tag2_id);
|
||||
debug_msg("Visual check period ended.");
|
||||
end
|
||||
end
|
||||
|
||||
// This can be used with `debug_map_scripts` or similar to run on map enter
|
||||
// procedure map_enter_p_proc begin call start; end
|
||||
// procedure map_update_p_proc begin call start; end // If you want it to run repeatedly (not recommended for this test script)
|
||||
|
||||
// For `description_proc` usage with `debug(F5)`:
|
||||
// Create a global script that calls `start` from `description_proc`
|
||||
// Example:
|
||||
// procedure description_proc begin
|
||||
// if (game_loaded) then call start;
|
||||
// end
|
||||
@@ -0,0 +1,71 @@
|
||||
#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
|
||||
@@ -0,0 +1,15 @@
|
||||
#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
|
||||
@@ -0,0 +1,82 @@
|
||||
#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
|
||||
@@ -0,0 +1,162 @@
|
||||
#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
|
||||
@@ -0,0 +1,112 @@
|
||||
#ifndef TEST_UTILS_H
|
||||
#define TEST_UTILS_H
|
||||
|
||||
#include "define_lite.h"
|
||||
|
||||
variable test_suite_errors := 0;
|
||||
variable test_suite_verbose := false;
|
||||
variable test_suite_assertions := 0;
|
||||
|
||||
procedure assertEquals(variable desc, variable a, variable b) begin
|
||||
test_suite_assertions++;
|
||||
|
||||
if (a != b or typeof(a) != typeof(b)) then begin
|
||||
display_msg("FAIL \""+desc+"\": "+a+" != "+b);
|
||||
test_suite_errors ++;
|
||||
end else if (test_suite_verbose) then begin
|
||||
display_msg("ok \""+desc+"\"");
|
||||
end
|
||||
end
|
||||
|
||||
procedure assertNotEquals(variable desc, variable a, variable b) begin
|
||||
test_suite_assertions++;
|
||||
|
||||
if (a == b) then begin
|
||||
display_msg("FAIL \""+desc+"\": "+a+" == "+b);
|
||||
test_suite_errors ++;
|
||||
end else if (test_suite_verbose) then begin
|
||||
display_msg("ok \""+desc+"\"");
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
procedure assertFloat(variable desc, variable a, variable b, variable tolerance = 0.001) begin
|
||||
test_suite_assertions++;
|
||||
|
||||
variable diff := abs(a - b);
|
||||
if (diff > tolerance) then begin
|
||||
display_msg("FAIL \""+desc+"\": "+a+" != "+b+" (diff: "+diff+")");
|
||||
test_suite_errors ++;
|
||||
end else if (test_suite_verbose) then begin
|
||||
display_msg("ok \""+desc+"\"");
|
||||
end
|
||||
end
|
||||
|
||||
procedure report_test_results(variable desc) begin
|
||||
|
||||
display_msg("DONE " + desc + " " +
|
||||
(test_suite_assertions-test_suite_errors) + "/" + test_suite_assertions + "");
|
||||
display_msg("================");
|
||||
|
||||
|
||||
#define GL_VAR_TESTING_INFO_ARRAY_ID "TestArra"
|
||||
#define TEST_ARR_IDENTIFIER_KEY "__testing_info_array__"
|
||||
variable arr_id = get_sfall_global_int(GL_VAR_TESTING_INFO_ARRAY_ID);
|
||||
if arr_id != 0 then begin
|
||||
// Let's check that it is actually our testing array
|
||||
if array_key(arr_id, -1) == 0 then begin
|
||||
// It is not even associative array, so it is not our testing array
|
||||
arr_id = 0;
|
||||
end else begin
|
||||
if arr_id[TEST_ARR_IDENTIFIER_KEY] != 1 then begin
|
||||
// It is associative array, but it is not our testing array
|
||||
arr_id = 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
if arr_id == 0 then begin
|
||||
arr_id = create_array(-1, 0);
|
||||
arr_id[TEST_ARR_IDENTIFIER_KEY] = 1;
|
||||
set_sfall_global(GL_VAR_TESTING_INFO_ARRAY_ID, arr_id);
|
||||
end
|
||||
|
||||
|
||||
#define TEST_SUITES "Test suites"
|
||||
#define TEST_ASSERTIONS_TOTAL "Tests assertings total"
|
||||
#define TEST_ASSERTIONS_FAILED "Tests assertings failed"
|
||||
|
||||
if arr_id[TEST_SUITES] == 0 then begin
|
||||
arr_id[TEST_SUITES] = create_array(-1, 0);
|
||||
end
|
||||
|
||||
//set_sfall_global("test_suite_errors", test_suite_errors);
|
||||
|
||||
arr_id[TEST_ASSERTIONS_TOTAL] += test_suite_assertions;
|
||||
arr_id[TEST_ASSERTIONS_FAILED] += test_suite_errors;
|
||||
arr_id[TEST_SUITES][desc] += 1;
|
||||
|
||||
variable total_suites_names = "";
|
||||
variable total_suites_count = 0;
|
||||
|
||||
variable key, item;
|
||||
foreach (key: item in arr_id[TEST_SUITES]) begin
|
||||
total_suites_count += item;
|
||||
if (total_suites_names != "") then begin
|
||||
total_suites_names += ", ";
|
||||
end
|
||||
total_suites_names += key;
|
||||
end
|
||||
|
||||
|
||||
variable assertions_stats_str = (arr_id[TEST_ASSERTIONS_TOTAL]-arr_id[TEST_ASSERTIONS_FAILED]) +
|
||||
"/" + arr_id[TEST_ASSERTIONS_TOTAL];
|
||||
if (arr_id[TEST_ASSERTIONS_FAILED] == 0) then begin
|
||||
float_msg(dude_obj, "Tested " + total_suites_count + " cases: " + total_suites_names + ". " +
|
||||
assertions_stats_str + " assertions passed!", FLOAT_MSG_GREEN);
|
||||
end else begin
|
||||
float_msg(dude_obj, "Tested " + total_suites_count + " cases: " + total_suites_names + ". " +
|
||||
assertions_stats_str + " assertions passed", FLOAT_MSG_RED);
|
||||
end
|
||||
end
|
||||
|
||||
#endif
|
||||
@@ -3046,6 +3046,10 @@ void _dude_fidget()
|
||||
return;
|
||||
}
|
||||
|
||||
if (GameMode::getCurrentGameMode() == GameMode::kWorldmap) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isInCombat()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1769,7 +1769,7 @@ static int characterEditorWindowInit()
|
||||
|
||||
btn = buttonCreate(
|
||||
gCharacterEditorWindow,
|
||||
343,
|
||||
344, // one pixel right shift to align with background
|
||||
454,
|
||||
_editorFrmImages[EDITOR_GRAPHIC_LITTLE_RED_BUTTON_UP].getWidth(),
|
||||
_editorFrmImages[EDITOR_GRAPHIC_LITTLE_RED_BUTTON_UP].getHeight(),
|
||||
@@ -1787,7 +1787,7 @@ static int characterEditorWindowInit()
|
||||
|
||||
btn = buttonCreate(
|
||||
gCharacterEditorWindow,
|
||||
552,
|
||||
553, // one pixel right shift to align with background
|
||||
454,
|
||||
_editorFrmImages[EDITOR_GRAPHIC_LITTLE_RED_BUTTON_UP].getWidth(),
|
||||
_editorFrmImages[EDITOR_GRAPHIC_LITTLE_RED_BUTTON_UP].getHeight(),
|
||||
@@ -1805,7 +1805,7 @@ static int characterEditorWindowInit()
|
||||
|
||||
btn = buttonCreate(
|
||||
gCharacterEditorWindow,
|
||||
455,
|
||||
456, // one pixel right shift to align with background
|
||||
454,
|
||||
_editorFrmImages[23].getWidth(),
|
||||
_editorFrmImages[23].getHeight(),
|
||||
|
||||
+2
-2
@@ -123,7 +123,7 @@ MessageList gMiscMessageList;
|
||||
static void** gGameGlobalPointers = nullptr;
|
||||
|
||||
// 0x442580
|
||||
int gameInitWithOptions(const char* windowTitle, bool isMapper, int font, int a4, int argc, char** argv)
|
||||
int gameInitWithOptions(const char* windowTitle, bool isMapper, int font, int flags, int argc, char** argv)
|
||||
{
|
||||
char path[COMPAT_MAX_PATH];
|
||||
|
||||
@@ -150,7 +150,7 @@ int gameInitWithOptions(const char* windowTitle, bool isMapper, int font, int a4
|
||||
messageListRepositoryInit();
|
||||
|
||||
programWindowSetTitle(windowTitle);
|
||||
_initWindow(1, a4);
|
||||
_initWindow(1, flags);
|
||||
paletteInit();
|
||||
|
||||
const char* language = settings.system.language.c_str();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user