mirror of
https://github.com/fallout2-ce/fallout2-ce.git
synced 2026-07-27 16:47:11 -07:00
Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3822e25201 | ||
|
|
2ba6cbee3a | ||
|
|
cb90129ebd | ||
|
|
13d5fd2e83 | ||
|
|
7c3cbbac05 | ||
|
|
a5a317ab40 | ||
|
|
372483a5ca | ||
|
|
d46549dd11 | ||
|
|
c6970e35de | ||
|
|
68e7d3e903 |
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -86,10 +76,6 @@ jobs:
|
||||
SITE_BASE: ${{ steps.set-path.outputs.SITE_BASE }}
|
||||
F2_GAME_VERSION: Game=${{github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Place hash file
|
||||
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository)
|
||||
run: echo "$GITHUB_SHA" > fallout2-ce-ems/dist/site_hash.txt
|
||||
|
||||
- name: Install rsync (required for the next step)
|
||||
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository)
|
||||
run: |
|
||||
@@ -103,39 +89,11 @@ jobs:
|
||||
folder: fallout2-ce-ems/dist
|
||||
target-folder: ${{ steps.set-path.outputs.DEST_DIR }}
|
||||
clean: false
|
||||
single-commit: true
|
||||
|
||||
|
||||
|
||||
- name: Check that site is deployed
|
||||
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository)
|
||||
run: |
|
||||
URL="$SITE_ORIGIN""$SITE_BASE""site_hash.txt"
|
||||
echo "Expecting $GITHUB_SHA from $URL"
|
||||
for i in `seq 1 80`; do
|
||||
got="$(curl -fsSL --max-time 10 "$URL" | tr -d '\r\n' || true)"
|
||||
if [ "$got" = "$GITHUB_SHA" ]; then
|
||||
echo "âś… Match on attempt $i: ${got}"
|
||||
exit 0
|
||||
fi
|
||||
echo "Received $got, waiting"
|
||||
sleep 5
|
||||
done
|
||||
exit 1
|
||||
|
||||
env:
|
||||
SITE_ORIGIN: https://${{ github.repository_owner }}.github.io
|
||||
SITE_BASE: ${{ steps.set-path.outputs.SITE_BASE }}
|
||||
|
||||
- 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 }}
|
||||
|
||||
@@ -87,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 != ''
|
||||
@@ -128,7 +128,7 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: out
|
||||
key: ios-cmake-v101
|
||||
key: ios-cmake-v5
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
@@ -183,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: |
|
||||
@@ -288,7 +288,7 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: out
|
||||
key: macos-cmake-v101
|
||||
key: macos-cmake-v6
|
||||
|
||||
- name: Configure
|
||||
run: |
|
||||
@@ -313,7 +313,7 @@ jobs:
|
||||
windows:
|
||||
name: Windows (${{ matrix.arch }})
|
||||
|
||||
runs-on: windows-2025
|
||||
runs-on: windows-2019
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -328,28 +328,19 @@ jobs:
|
||||
- name: Clone
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Visual Studio 2022 Build Tools with v141_xp
|
||||
shell: cmd
|
||||
run: |
|
||||
choco install visualstudio2022buildtools -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-v102
|
||||
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: |
|
||||
@@ -432,4 +423,4 @@ jobs:
|
||||
tag_name: continious
|
||||
draft: false
|
||||
prerelease: true
|
||||
name: Fallout2-CE Continuous Build
|
||||
name: Fallout2-CE Continuous Build
|
||||
@@ -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
|
||||
|
||||
@@ -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: |
|
||||
|
||||
+1
-11
@@ -286,21 +286,12 @@ target_sources(${EXECUTABLE_NAME} PUBLIC
|
||||
"src/sfall_metarules.h"
|
||||
"src/sfall_opcodes.cc"
|
||||
"src/sfall_opcodes.h"
|
||||
"src/sfall_script_hooks.cc"
|
||||
"src/sfall_arrays.cc"
|
||||
"src/sfall_arrays.h"
|
||||
"src/sfall_animation.cc"
|
||||
"src/sfall_animation.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"
|
||||
@@ -321,8 +312,7 @@ endif()
|
||||
if(WIN32)
|
||||
target_link_libraries(${EXECUTABLE_NAME}
|
||||
winmm
|
||||
debug libcpmtd
|
||||
optimized libcpmt
|
||||
libcpmt
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
+2
-2
@@ -28,7 +28,7 @@
|
||||
"inherits": [
|
||||
"windows-base"
|
||||
],
|
||||
"generator": "Visual Studio 17 2022",
|
||||
"generator": "Visual Studio 16 2019",
|
||||
"architecture": "Win32",
|
||||
"cacheVariables": {
|
||||
"CMAKE_GENERATOR_TOOLSET": "v141_xp",
|
||||
@@ -42,7 +42,7 @@
|
||||
"inherits": [
|
||||
"windows-base"
|
||||
],
|
||||
"generator": "Visual Studio 17 2022",
|
||||
"generator": "Visual Studio 16 2019",
|
||||
"architecture": "x64",
|
||||
"cacheVariables": {
|
||||
"CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreaded$<$<CONFIG:Debug>:Debug>"
|
||||
|
||||
@@ -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,18 +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
|
||||
|
||||
[STATIC_SCREENS]
|
||||
;if SPLASH_SCRN_SIZE=0 - Splash screen shows at original size if it fits, otherwise scales down while preserving aspect ratio.
|
||||
;if SPLASH_SCRN_SIZE=1 - Splash screen scales to fit the screen while preserving aspect ratio.
|
||||
;if SPLASH_SCRN_SIZE=2 - Splash screen stretches to fill the entire screen.
|
||||
SPLASH_SCRN_SIZE=0
|
||||
|
||||
[MAPS]
|
||||
;if IGNORE_MAP_EDGES=0 - Hi-Res map scroll edges are enabled.
|
||||
;if IGNORE_MAP_EDGES=1 - Hi-Res map scroll edges are ignored.
|
||||
IGNORE_MAP_EDGES=0
|
||||
IFACE_BAR_WIDTH=640
|
||||
```
|
||||
|
||||
Recommendations:
|
||||
@@ -152,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,104 +0,0 @@
|
||||
# Sfall Compatibility
|
||||
|
||||
This document tracks Fallout 2 CE compatibility with sfall. This is for modders who need to know which Sfall features work in CE.
|
||||
|
||||
For now, this covers opcodes/metarules, and hooks. In the future, it will include other ways of modifying the engine (like ini files), and other Sfall-specific behaviour.
|
||||
|
||||
## Opcodes / Metarules
|
||||
|
||||
See [`https://sfall-team.github.io/sfall/`](https://sfall-team.github.io/sfall/) for documentation on specific functions.
|
||||
|
||||
| Group | Opcodes In Group | Compatibility | Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| Direct memory access| read_byte,short,int,string<br>write_byte,short,int,string<br>call_offset_vX | đźš« | Not possible. Open an issue if you need functionality not covered by other opcodes. |
|
||||
| Stats | get/set_pc_base_stat<br>get/set_pc_extra_stat<br>get/set_critter_base_stat<br>get/set_critter_extra_stat | âś… | CE uses engine stat helpers here instead of sfall's direct proto-field behavior, so derived-stat update behavior can differ. |
|
||||
| Stats / Alter min/max | get/set_stat_min/max<br>set_pc_stat_min/max<br>set_npc_stat_min/max | not implemented | - |
|
||||
| Skills | get/set_critter_skill_points<br>get/set_available_skill_points<br>set_skill_max<br>set_critter_skill_mod<br>set_base_skill_mod<br>mod_skill_points_per_level | not implemented | - |
|
||||
| Graphics | graphics_funcs_available<br>force_graphics_refresh<br>get_screen_width<br>get_screen_height<br>set_palette | implemented: only get_screen_width, get_screen_height | - |
|
||||
| Shaders | load_shader<br>free_shader<br>activate_shader<br>deactivate_shader<br>set/get_shader_* | đźš« | likely will not implement direct compatibility
|
||||
| Perks and traits | set_perk_image<br>set_perk_*<br>set_pyromaniac_mod<br>apply_heaveho_fix<br>set_swiftlearner_mod<br>set_fake_perk<br>set_fake_trait<br>set_selectable_perk<br>set_perkbox_title<br>hide_real_perks<br>show_real_perks<br>perk_add_mode<br>clear_selectable_perks<br>has_fake_perk<br>has_fake_trait<br>add_trait<br>remove_trait<br>seq_perk_freq | not implemented | - |
|
||||
| Virtual file system | fs_create<br>fs_copy<br>fs_find<br>fs_read/write_*<br>fs_delete<br>fs_size<br>fs_pos<br>fs_seek<br>fs_resize | đźš« | Open an issue if you have a use case for these |
|
||||
| Combat / Knockback | set_weapon_knockback<br>set_target_knockback<br>set_attacker_knockback<br>remove_weapon_knockback<br>remove_target_knockback<br>remove_attacker_knockback | not implemented | - |
|
||||
| Maps and encounters | in_world_map<br>force_encounter<br>force_encounter_with_flags<br>set_map_time_multi<br>get/set_map_enter_position<br>exec_map_update_scripts<br>get/set_terrain_name<br>set_town_title<br>get/set_can_rest_on_map<br>set_rest_heal_time<br>set_rest_mode<br>set_worldmap_heal_time | implemented: in_world_map, force_encounter, force_encounter_with_flags, set_map_time_multi | - |
|
||||
| Maps and encounters / Worldmap | get_world_map_x/y_pos<br>set_world_map_pos | âś… | - |
|
||||
| Audio | eax_available<br>set_eax_environment<br>play_sfall_sound<br>stop_sfall_sound | not implemented | *eax* opcodes will not be implemented |
|
||||
| Combat / Weapons and ammo | get/set_weapon_ammo_pid<br>get/set_weapon_ammo_count | âś… | - |
|
||||
| Sfall / Version | sfall_ver_major<br>sfall_ver_minor<br>sfall_ver_build | âś… | CE currently reports `4.3.4` |
|
||||
| Utility / Math | log, exponent, round, sqrt, abs, sin, cos, tan, arctan, ceil, ^, floor2, div | âś… | - |
|
||||
| Keyboard and mouse | key_pressed<br>tap_key<br>get_mouse_x/y<br>get_mouse_buttons | âś… | - |
|
||||
| Lists | list_begin<br>list_next<br>list_end<br>list_as_array<br>party_member_list | âś… | - |
|
||||
| Explosions | metarule2_explosions<br>set_attack_explosion_pattern<br>set_attack_explosion_art<br>set_attack_explosion_radius<br>set_attack_is_explosion_fire<br>set_explosion_radius<br>set_dynamite_damage<br>set_plastic_damage<br>get_explosion_damage<br>set_explosion_max_targets<br>item_make_explosive | âś… except item_make_explosive | - |
|
||||
| Animations | reg_anim_combat_check<br>reg_anim_destroy<br>reg_anim_animate_and_hide<br>reg_anim_light<br>reg_anim_change_fid<br>reg_anim_take_out<br>reg_anim_turn_towards<br>reg_anim_callback<br>reg_anim_animate_and_move | âś… except reg_anim_callback | - |
|
||||
| Art and appearance | art_exists<br>refresh_pc_art<br>art_cache_clear<br>set_hero_race<br>set_hero_style | implemented: art_exists, refresh_pc_art, art_cache_clear | - |
|
||||
| Tiles and paths | get_tile_fid<br>tile_under_cursor<br>tile_light<br>tile_get_objs<br>tile_refresh_display<br>obj_blocking_tile<br>tile_by_position<br>get_tile_ground_fid<br>get_tile_roof_fid<br>obj_blocking_line<br>path_find_to<br>objects_in_radius | âś… except objects_in_radius | - |
|
||||
| Utility | sprintf<br>typeof<br>atoi<br>atof | âś… | - |
|
||||
| Utility / Strings | string_split<br>substr<br>strlen<br>charcode<br>get_string_pointer<br>string_find<br>string_find_from<br>string_format<br>string_format_array<br>string_replace<br>string_to_case<br>string_compare | âś… except get_string_pointer | `get_string_pointer` is deprecated and intentionally omitted. |
|
||||
| Interface / Tags | show_iface_tag<br>hide_iface_tag<br>is_iface_tag_active<br>set_iface_tag_text<br>add_iface_tag | implemented: all except set_iface_tag_text, add_iface_tag | CE only handles built-in interface tags here; custom tag creation/text is not supported yet. |
|
||||
| Global variables | set_sfall_global<br>get_sfall_global_int<br>get_sfall_global_float | implemented: all except get_sfall_global_float | Current CE storage is int-backed; `set_sfall_global` stores integer values and there is no float getter yet. |
|
||||
| Hooks / Hook functions | init_hook<br>get_sfall_arg<br>get_sfall_args<br>get_sfall_arg_at<br>set_sfall_return<br>set_sfall_arg<br>register_hook<br>register_hook_proc<br>register_hook_proc_spec | âś… except init_hook | See below for implemented hooks. `init_hook` is deprecated and will not be implemented. register_hook_proc and register_hook_proc_spec both add hooks to the *end* of the hook list, instead of beginning and end, respectively. |
|
||||
| Arrays / Array functions | create_array<br>temp_array<br>fix_array<br>get/set_array<br>resize_array<br>free_array<br>scan_array<br>len_array<br>save/load_array<br>array_key<br>arrayexpr | âś… except save_array, load_array | - |
|
||||
| Perks and traits / NPC perks | set_fake_perk_npc<br>set_fake_trait_npc<br>set_selectable_perk_npc<br>has_fake_perk_npc<br>has_fake_trait_npc | not implemented | - |
|
||||
| Global scripts / Global script functions | set_global_script_repeat<br>set_global_script_type<br>available_global_script_types | implemented: all except available_global_script_types | `GlobalScriptPaths` masks now match archive-backed scripts regardless of `/` vs `\` separators, matching Windows-style `.dat` contents on non-Windows hosts. |
|
||||
| Combat | attack_is_aimed<br>block_combat<br>force_aimed_shots<br>disable_aimed_shots<br>get_attack_type<br>get/set_bodypart_hit_modifier<br>combat_data<br>get/set/reset_critical_table<br>get_last_target<br>get_last_attacker<br>set_critter_burst_disable<br>get/set_critter_current_ap<br>set_spray_settings<br>get/set_combat_free_move | implemented: only get_attack_type, get_bodypart_hit_modifier, combat_data, set_bodypart_hit_modifier | - |
|
||||
| Car | set_car_current_town<br>car_gas_amount<br>set_car_intface_art | implemented: all except set_car_intface_art | - |
|
||||
| Interface / Windows and images | art_frame_data<br>interface_art_draw<br>interface_print<br>draw_image<br>draw_image_scaled<br>get_window_under_mouse<br>create_win<br>get_window_attribute<br>message_box<br>set_window_flag<br>win_fill_color<br>interface_overlay<br>dialog_message<br>get_text_width<br>hide_window<br>show_window | implemented: only message_box, get_text_width, show_window | - |
|
||||
| Interface / Outline | outlined_object<br>get_outline<br>set_outline | implemented: all except get_outline | - |
|
||||
| Interface / Main interface | intface_is_hidden<br>intface_redraw<br>intface_hide<br>intface_show<br>set_quest_failure_value | implemented: only intface_redraw | `intface_redraw` only supports the zero-argument form; the optional-argument path is explicitly unimplemented. |
|
||||
| Interface / Inventory | display_stats<br>inventory_redraw<br>critter_inven_obj2<br>get_current_inven_size<br>item_weight | implemented: only critter_inven_obj2 | - |
|
||||
| Interface / Cursor | get/set_cursor_mode | âś… | - |
|
||||
| Locks | lock_is_jammed<br>unjam_lock<br>set_unjam_locks_time | not implemented | - |
|
||||
| INI settings | modified_ini<br>get_ini_setting<br>get_ini_string<br>get_ini_section<br>get_ini_sections<br>get_ini_config<br>get_ini_config_db<br>set_ini_setting | âś… except modified_ini, get_ini_config, get_ini_config_db | `modified_ini` is intentionally omitted as deprecated. |
|
||||
| Objects and scripts | set_self<br>set_dude_obj<br>real_dude_obj<br>remove_script<br>set_script<br>get_script<br>obj_is_carrying_obj<br>loot_obj<br>dialog_obj<br>obj_under_cursor<br>get_object_data<br>set_object_data<br>get_flags<br>set_flags<br>set_unique_id<br>set_scr_name<br>obj_is_openable<br>get/set_proto_data<br>get_object_ai_data | implemented: set_self, get_script, loot_obj, dialog_obj, obj_under_cursor, get_object_data, get_flags, set_flags, get_proto_data, set_proto_data | - |
|
||||
| Other / Game management | set_movie_path<br>stop_game<br>resume_game<br>mark_movie_played<br>game_loaded<br>get_game_mode<br>get_uptime<br>signal_close_game | implemented: game_loaded, get_game_mode, get_uptime | - |
|
||||
| Other | input_funcs_available<br>get_year<br>set_dm_model<br>set_df_model<br>set_pipboy_available<br>get_kill_counter<br>mod_kill_counter<br>active_hand<br>toggle_active_hand<br>set_pickpocket_max<br>set_hit_chance_max<br>set_xp_mod<br>set_critter_hit_chance_mod<br>set_base_hit_chance_mod<br>inc_npc_level<br>get_npc_level<br>get/set_viewport_x/y<br>set_hp_per_level_mod<br>get/set_unspent_ap_bonus<br>get/set_unspent_ap_perk_bonus<br>hero_select_win<br>create_message_window<br>get_light_level<br>gdialog_get_barter_mod<br>set_inven_ap_cost<br>set_base_pickpocket_mod<br>set_critter_pickpocket_mod<br>message_str_game<br>sneak_success<br>create_spatial<br>unwield_slot<br>get_inven_ap_cost<br>add_g_timer_event<br>add_extra_msg_file<br>get_metarule_table<br>metarule_exist<br>npc_engine_level_up<br>remove_timer_event<br>set_drugs_data<br>spatial_radius | implemented: get_year, active_hand, toggle_active_hand, create_message_window, message_str_game, add_extra_msg_file, metarule_exist | `input_funcs_available`, `nb_create_char` are deprecated in sfall and intentionally absent in CE. `add_extra_msg_file` does not support the explicit `fileNumber` form in CE. |
|
||||
|
||||
## Hooks
|
||||
|
||||
| Hook | ID | Compatibility | Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| ToHit | `HOOK_TOHIT` | âś… | - |
|
||||
| AfterHitRoll | `HOOK_AFTERHITROLL` | đźš« | Et tu |
|
||||
| CalcAPCost | `HOOK_CALCAPCOST` | đźš« | - |
|
||||
| DeathAnim1 | `HOOK_DEATHANIM1` | đźš« | Use DEATHANIM2 instead |
|
||||
| DeathAnim2 | `HOOK_DEATHANIM2` | âś… | - |
|
||||
| CombatDamage | `HOOK_COMBATDAMAGE` | âś… | CE passes the raw `Attack*` as the final mixed argument, matching sfall's shape. |
|
||||
| OnDeath | `HOOK_ONDEATH` | đźš« | - |
|
||||
| FindTarget | `HOOK_FINDTARGET` | đźš« | (maybe) |
|
||||
| UseObjOn | `HOOK_USEOBJON` | âś… | - |
|
||||
| UseObj | `HOOK_USEOBJ` | âś… | CE notes an sfall-matching inconsistency around return code `2` behavior between interface contexts. |
|
||||
| RemoveInvenObj | `HOOK_REMOVEINVENOBJ` | đźš« | - |
|
||||
| BarterPrice | `HOOK_BARTERPRICE` | âś… | - |
|
||||
| MoveCost | `HOOK_MOVECOST` | đźš« | - |
|
||||
| ItemDamage | `HOOK_ITEMDAMAGE` | đźš« | - |
|
||||
| AmmoCost | `HOOK_AMMOCOST` | đźš« | Et tu |
|
||||
| KeyPress | `HOOK_KEYPRESS` | âś… | Third hook arg is currently `0`; CE notes that sfall used VK codes there. |
|
||||
| MouseClick | `HOOK_MOUSECLICK` | đźš« | - |
|
||||
| UseSkill | `HOOK_USESKILL` | đźš« | - |
|
||||
| Steal | `HOOK_STEAL` | đźš« | Et tu |
|
||||
| WithinPerception | `HOOK_WITHINPERCEPTION` | đźš« | Et tu |
|
||||
| InventoryMove | `HOOK_INVENTORYMOVE` | đźš« | Et tu |
|
||||
| InvenWield | `HOOK_INVENWIELD` | đźš« | - |
|
||||
| AdjustFID | `HOOK_ADJUSTFID` | đźš« | - |
|
||||
| CombatTurn | `HOOK_COMBATTURN` | đźš« | - |
|
||||
| StdProcedure | `HOOK_STDPROCEDURE` | đźš« | Et tu |
|
||||
| StdProcedureEnd | `HOOK_STDPROCEDURE_END` | đźš« | - |
|
||||
| CarTravel | `HOOK_CARTRAVEL` | đźš« | - |
|
||||
| SetGlobalVar | `HOOK_SETGLOBALVAR` | đźš« | - |
|
||||
| RestTimer | `HOOK_RESTTIMER` | đźš« | Et tu |
|
||||
| GameModeChange | `HOOK_GAMEMODECHANGE` | âś… | - |
|
||||
| UseAnimObj | `HOOK_USEANIMOBJ` | đźš« | Et tu; (maybe) |
|
||||
| ExplosiveTimer | `HOOK_EXPLOSIVETIMER` | đźš« | - |
|
||||
| DescriptionObj | `HOOK_DESCRIPTIONOBJ` | đźš« | Et tu |
|
||||
| UseSkillOn | `HOOK_USESKILLON` | đźš« | Et tu |
|
||||
| OnExplosion | `HOOK_ONEXPLOSION` | đźš« | (maybe) |
|
||||
| SubCombatDamage | `HOOK_SUBCOMBATDAMAGE` | đźš« | (maybe) |
|
||||
| SetLighting | `HOOK_SETLIGHTING` | đźš« | Et tu; (maybe) |
|
||||
| Sneak | `HOOK_SNEAK` | đźš« | - |
|
||||
| TargetObject | `HOOK_TARGETOBJECT` | đźš« | (maybe) |
|
||||
| Encounter | `HOOK_ENCOUNTER` | đźš« | Et tu |
|
||||
| AdjustPoison | `HOOK_ADJUSTPOISON` | đźš« | (maybe) |
|
||||
| AdjustRads | `HOOK_ADJUSTRADS` | đźš« | (maybe) |
|
||||
| RollCheck | `HOOK_ROLLCHECK` | đźš« | - |
|
||||
| BestWeapon | `HOOK_BESTWEAPON` | đźš« | - |
|
||||
| CanUseWeapon | `HOOK_CANUSEWEAPON` | đźš« | - |
|
||||
| BuildSfxWeapon | `HOOK_BUILDSFXWEAPON` | đźš« | - |
|
||||
+1
-2
@@ -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]
|
||||
|
||||
@@ -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,2 +0,0 @@
|
||||
*.int
|
||||
sfall
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
#include "sfall.h"
|
||||
#include "dik.h"
|
||||
#include "define_lite.h"
|
||||
#include "define_extra.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
variable refresh_pc_art_test_done := false;
|
||||
|
||||
procedure run_refresh_pc_art_test begin
|
||||
variable old_gender := get_critter_stat(dude_obj, STAT_gender);
|
||||
variable new_gender := 1 - old_gender;
|
||||
variable dude_pid := obj_pid(dude_obj);
|
||||
variable old_proto_fid := get_proto_data(dude_pid, PROTO_FID);
|
||||
|
||||
set_pc_base_stat(STAT_gender, new_gender);
|
||||
call assertEquals("gender changes immediately", get_critter_stat(dude_obj, STAT_gender), new_gender);
|
||||
call assertEquals("proto fid unchanged before refresh", get_proto_data(dude_pid, PROTO_FID), old_proto_fid);
|
||||
|
||||
refresh_pc_art;
|
||||
|
||||
variable refreshed_proto_fid := get_proto_data(dude_pid, PROTO_FID);
|
||||
call assertNotEquals("refresh_pc_art updates dude proto fid", refreshed_proto_fid, old_proto_fid);
|
||||
|
||||
if (not critter_inven_obj(dude_obj, INVEN_TYPE_WORN)) then begin
|
||||
call assertEquals("refresh_pc_art updates unarmored dude art", obj_art_fid(dude_obj) bwand 0xFFF, refreshed_proto_fid bwand 0xFFF);
|
||||
end
|
||||
|
||||
set_pc_base_stat(STAT_gender, old_gender);
|
||||
refresh_pc_art;
|
||||
call assertEquals("refresh_pc_art restores original proto fid", get_proto_data(dude_pid, PROTO_FID), old_proto_fid);
|
||||
|
||||
refresh_pc_art_test_done := true;
|
||||
call report_test_results("hook_refresh_pc_art");
|
||||
end
|
||||
|
||||
procedure keypress_handler begin
|
||||
variable pressed := get_sfall_arg_at(0);
|
||||
variable key := get_sfall_arg_at(1);
|
||||
|
||||
if (not pressed) then return;
|
||||
if (key != DIK_X) then return;
|
||||
|
||||
if (refresh_pc_art_test_done) then begin
|
||||
display_msg("refresh_pc_art test already ran");
|
||||
return;
|
||||
end
|
||||
|
||||
call run_refresh_pc_art_test;
|
||||
end
|
||||
|
||||
procedure start begin
|
||||
if (not game_loaded) then return;
|
||||
|
||||
display_msg("refresh_pc_art test ready: press X");
|
||||
register_hook_proc(HOOK_KEYPRESS, keypress_handler);
|
||||
end
|
||||
@@ -1,26 +0,0 @@
|
||||
#include "test_utils.h"
|
||||
#include "sfall.h"
|
||||
|
||||
// to test, copy test_extra_msg_file.msg into <game folder>/text/English/game/
|
||||
|
||||
procedure start begin
|
||||
variable auto_id;
|
||||
variable duplicate_auto_id;
|
||||
|
||||
display_msg("Testing add_extra_msg_file...");
|
||||
|
||||
call assertEquals("metarule exists", metarule_exist("add_extra_msg_file"), 1);
|
||||
|
||||
auto_id := add_extra_msg_file("test_extra_msg_file.msg");
|
||||
call assertNotEquals("auto id is not load error", auto_id, -2);
|
||||
call assertTrue("auto id lower bound", auto_id >= 0x3000);
|
||||
call assertTrue("auto id upper bound", auto_id <= 0x3FFF);
|
||||
call assertEquals("auto message", message_str_game(auto_id, 100), "auto extra msg");
|
||||
|
||||
duplicate_auto_id := add_extra_msg_file("TEST_EXTRA_MSG_FILE.MSG");
|
||||
call assertEquals("duplicate file returns existing id", duplicate_auto_id, auto_id);
|
||||
|
||||
call assertEquals("missing file", add_extra_msg_file("missing_extra_msg_file.msg"), -2);
|
||||
|
||||
call report_test_results("add_extra_msg_file");
|
||||
end
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,73 +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");
|
||||
call assertEquals("TC1 Size", len_array(result_array), 3);
|
||||
call assertEquals("TC1 Key1", result_array["Key1"], "Value1");
|
||||
call assertEquals("TC1 Key2", result_array["Key2"], "2");
|
||||
call assertEquals("TC1 EmptyValue", result_array["EmptyValue"], "");
|
||||
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");
|
||||
call assertEquals("TC2 get_ini_setting empty int", get_ini_setting("test.ini|ValidSection|EmptyValue"), 0);
|
||||
call assertEquals("TC2 get_ini_string empty string", get_ini_string("test.ini|ValidSection|EmptyValue"), "");
|
||||
|
||||
// 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 missing file", get_ini_setting("notexist.ini|ValidSection|Key2"), -1);
|
||||
call assertEquals("TC3 get_ini_setting missing key", get_ini_setting("test.ini|ValidSection|MissingKey"), -1);
|
||||
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"), -1);
|
||||
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"), -1);
|
||||
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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user