Compare commits

..
Author SHA1 Message Date
cambragol f3403c07f7 Merge branch 'main' into stretching-for-800x500-widescreen-mode 2025-06-22 20:33:24 +09:00
cambragol 8c44106688 Merge branch 'main' into stretching-for-800x500-widescreen-mode 2025-06-21 12:02:50 +09:00
cambragol 5248e138f6 removed Scale_2x
Removed scale_2x function, as it no longer worked nor was needed.
Fixed backing up of gPreseverAspect in guserAspectPreference - used to restore users aspect preference, when returning from the main game screen - that window overrides users aspect preferences.
2025-06-16 14:34:32 +09:00
cambragol 0076894414 First pass on widescreen mode
Adds stretching for full and aspect ratio, set from f2_res (for now)
Allows different content to be stretched/displayed uniformly (to mix 640 and 800 content smoothly)
Adds resizeContent which lets renderPresent know how big(wide) the content being stretched is. A bool also reads/restores users aspect ratio setting (because main game area forces aspect ratio)
Adds small tweak to endgame.cc that smooths the transition after slideshow to the credits movie (just keeps the screen black)
2025-06-15 17:50:06 +09:00
179 changed files with 4291 additions and 16679 deletions
+6 -47
View File
@@ -14,16 +14,6 @@ jobs:
runs-on: ubuntu-latest
permissions: write-all
steps:
- name: start deployment
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
uses: bobheadxi/deployments@v1
id: deployment
with:
ref: ${{ github.event.pull_request.head.sha }}
step: start
debug: true
env: preview-${{ github.event.pull_request.number }}
- name: Clone
uses: actions/checkout@v4
@@ -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: |
@@ -105,37 +91,10 @@ jobs:
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 }}
+8 -8
View File
@@ -87,7 +87,7 @@ jobs:
uses: actions/cache@v4
with:
path: os/android/app/.cxx
key: android-cmake-v101
key: android-cmake-v100
- 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-v100
- 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-v100
- name: Configure
run: |
@@ -288,7 +288,7 @@ jobs:
uses: actions/cache@v4
with:
path: out
key: macos-cmake-v101
key: macos-cmake-v100
- name: Configure
run: |
@@ -328,16 +328,16 @@ jobs:
- name: Clone
uses: actions/checkout@v4
- name: Install Visual Studio 2022 Build Tools with v141_xp
- name: Install Visual Studio 2019 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'"
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-v102
key: windows-${{ matrix.arch }}-cmake-v100
- name: Configure
shell: cmd
@@ -432,4 +432,4 @@ jobs:
tag_name: continious
draft: false
prerelease: true
name: Fallout2-CE Continuous Build
name: Fallout2-CE Continuous Build
+1 -10
View File
@@ -12,7 +12,6 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: write
deployments: write
steps:
- name: Checkout gh-pages branch
uses: actions/checkout@v4
@@ -44,12 +43,4 @@ jobs:
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
fi
+1 -10
View File
@@ -286,21 +286,13 @@ 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 +313,7 @@ endif()
if(WIN32)
target_link_libraries(${EXECUTABLE_NAME}
winmm
debug libcpmtd
optimized libcpmt
libcpmt
)
endif()
+2 -2
View File
@@ -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>"
+1 -12
View File
@@ -44,7 +44,7 @@ $ sudo apt install libsdl2-2.0-0
- Alternatively you can use Fallout 2 from Macplay/The Omni Group as a base - you need to extract game assets from the original bundle. Mount CD/DMG, right click `Fallout 2` -> `Show Package Contents`, navigate to `Contents/Resources`. Copy `GameData` folder somewhere, for example `/Applications/Fallout2`.
- Or if you're a Terminal user and have Homebrew installed you can extract the needed files from the GoG installer. **Note**: You must use "Offline backup game installer", not the main game installer.
- Or if you're a Terminal user and have Homebrew installed you can extract the needed files from the GoG installer:
```console
$ brew install innoextract
@@ -126,17 +126,6 @@ IFACE_BAR_SIDES_ORI=0
;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
```
Recommendations:
-104
View File
@@ -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
View File
@@ -1,2 +1 @@
*.int
sfall
-56
View File
@@ -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
-33
View File
@@ -1,33 +0,0 @@
#include "test_utils.h"
#include "sfall.h"
procedure start begin
display_msg("Testing iface_tag functions...");
// assumes no iface tags active in the save game
// SNEAK
show_iface_tag(0);
call assertTrue("show_iface_tag(SNEAK)", is_iface_tag_active(0));
hide_iface_tag(0);
call assertFalse("hide_iface_tag(SNEAK)", is_iface_tag_active(0));
// LEVEL
show_iface_tag(3);
call assertTrue("show_iface_tag(LEVEL)", is_iface_tag_active(3));
hide_iface_tag(3);
call assertFalse("hide_iface_tag(LEVEL)", is_iface_tag_active(3));
// ADDICTED
show_iface_tag(4);
call assertTrue("show_iface_tag(ADDICTED)", is_iface_tag_active(4));
hide_iface_tag(4);
call assertFalse("hide_iface_tag(ADDICTED)", is_iface_tag_active(4));
// POISONED
call assertFalse("hide_iface_tag(POISONED)", is_iface_tag_active(1));
// RADIATED
call assertFalse("hide_iface_tag(RADIATED)", is_iface_tag_active(2));
call report_test_results("iface_tag");
end
+6 -10
View File
@@ -9,10 +9,9 @@ procedure ini_test_suite begin
// 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"], "");
expected_array := {"Key1": "Value1", "Key2": "2"};
call assertEquals("TC1 Size", len_array(result_array), 2);
call assertEquals("TC1 Content", arrays_equal(result_array, expected_array), true);
count := 0;
foreach key_val_pair in result_array begin
count += 1;
@@ -26,22 +25,19 @@ procedure ini_test_suite begin
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_setting", get_ini_setting("notexist.ini|ValidSection|Key2"), 0);
call assertEquals("TC3 get_ini_string", get_ini_string("notexist.ini|ValidSection|Key2"), "");
// Valid file, section not found
result_array := get_ini_section("test.ini", "NonExistentSection");
call assertEquals("TC4 Size", len_array(result_array), 0);
call assertEquals("TC4 Is Map", array_key(result_array, -1), 1);
call assertEquals("TC4 get_ini_setting", get_ini_setting("test.ini|NonExistentSection|Key2"), -1);
call assertEquals("TC4 get_ini_setting", get_ini_setting("test.ini|NonExistentSection|Key2"), 0);
call assertEquals("TC4 get_ini_string", get_ini_string("test.ini|NonExistentSection|Key2"), "");
@@ -49,7 +45,7 @@ procedure ini_test_suite begin
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_setting", get_ini_setting("test.ini|EmptySection|Key2"), 0);
call assertEquals("TC5 get_ini_string", get_ini_string("test.ini|EmptySection|Key2"), "");
// set ini setting
-14
View File
@@ -1,14 +0,0 @@
#include "sfall.h"
// this is the basic message_box function used by RPU and Et Tu
#define message_box_warning(text) message_box4(text, 0x01, 134, 145)
procedure start begin
// I don't see a practice way to auto test message_box, so this is just a way to do manual testing
variable ret = message_box1("Basic Dialog\nwith multiple lines\nand such.");
display_msg("chose: " + ret);
message_box2("Basic Dialog\nwith default flags.", -1); // -1 means use default flags
message_box2("Basic Dialog\nsmall.", 0x02);
message_box_warning("Missing config values\n(just testing).");
end
-30
View File
@@ -1,30 +0,0 @@
#include "test_utils.h"
#include "sfall.h"
procedure start begin
display_msg("Testing metarule_exist functions...");
call assertEquals("string_format", metarule_exist("string_format"), 1);
call assertEquals("metarule_exist", metarule_exist("metarule_exist"), 1);
// This will fail on sFall
call assertEquals("opcode_exists", metarule_exist("opcode_exists"), 1);
if metarule_exist("opcode_exists") then begin // And example if how to use it
#define opcode_exists(opcode) sfall_func1("opcode_exists", opcode)
#define OP_GET_UPTIME 0x81B3
#define OP_NOOP 0x8000
#define OP_WRITE_INT 0x81D1
call assertEquals("opcode_exists OP_GET_UPTIME", opcode_exists(OP_GET_UPTIME), 1);
call assertEquals("opcode_exists OP_NOOP", opcode_exists(OP_NOOP), 1);
// Probably will never be implemented on fallout2-ce
call assertEquals("opcode_exists OP_WRITE_INT", opcode_exists(OP_WRITE_INT), 0);
call assertEquals("opcode_exists 0xFFFF", opcode_exists(0xFFFF), 0);
end else begin
display_msg("Opcode exists metarule is not available, skipping tests.");
end
call report_test_results("metarule_exist");
end
@@ -1,234 +0,0 @@
#include "sfall.h"
#include "dik.h"
#include "command_lite.h"
#include "define_extra.h"
#include "test_utils.h"
#define REG_ANIM_BEGIN 1
#define REG_ANIM_END 3
#define ANIMATION_REQUEST_UNRESERVED 1
#define TEST_ITEM_PID 40
#define TEST_FID_SOURCE_PID 76
#define TEST_LIGHT_VALUE 0x12340002
#define TEST_TAKE_OUT_FRAME WPN_ANIM_PISTOL
#define TEST_STAND_ANIM 0
#define TEST_WALK_ANIM 1
#define reg_anim_begin() reg_anim_func(REG_ANIM_BEGIN, ANIMATION_REQUEST_UNRESERVED)
#define reg_anim_end() reg_anim_func(REG_ANIM_END, 0)
variable hook_registered := false;
variable pending_test := 0;
variable pending_frames := 0;
variable test_move_critter_obj := 0;
variable test_takeout_critter_obj := 0;
variable test_light_obj := 0;
variable test_fid_obj := 0;
variable test_fid_source_obj := 0;
variable test_hide_obj := 0;
variable test_destroy_obj := 0;
variable expected_turn_tile := 0;
variable expected_move_tile := 0;
variable initial_rotation := 0;
variable initial_tile := 0;
variable initial_fid := 0;
variable expected_fid := 0;
variable initial_hide_visibility := 0;
variable initial_destroy_visibility := 0;
variable test_objects_ready := false;
variable pending_timeout_frames := 0;
variable noncombat_test_completed := false;
// Manual checks:
// X:
// - No registered animation should run in combat.
// - The temp critters should not move or draw a weapon.
// V:
// - `reg_anim_combat_check(0)` should allow the registered animations in combat.
// N:
// - Outside combat, the full opcode surface should run and be checked.
procedure setup_test_objects begin
variable elev := elevation(dude_obj);
test_move_critter_obj := create_object_sid(obj_pid(dude_obj), tile_num_in_direction(dude_tile, dude_cur_rot, 3), elev, -1);
test_takeout_critter_obj := create_object_sid(obj_pid(dude_obj), tile_num_in_direction(dude_tile, (dude_cur_rot + 1) % 6, 3), elev, -1);
test_light_obj := create_object_sid(TEST_ITEM_PID, tile_num_in_direction(dude_tile, (dude_cur_rot + 2) % 6, 4), elev, -1);
test_fid_obj := create_object_sid(TEST_ITEM_PID, tile_num_in_direction(dude_tile, (dude_cur_rot + 3) % 6, 4), elev, -1);
test_fid_source_obj := create_object_sid(TEST_FID_SOURCE_PID, tile_num_in_direction(dude_tile, (dude_cur_rot + 4) % 6, 4), elev, -1);
test_hide_obj := create_object_sid(TEST_ITEM_PID, tile_num_in_direction(dude_tile, (dude_cur_rot + 5) % 6, 4), elev, -1);
test_destroy_obj := create_object_sid(TEST_ITEM_PID, tile_num_in_direction(dude_tile, dude_cur_rot, 5), elev, -1);
initial_rotation := obj_get_rot(test_move_critter_obj);
initial_tile := tile_num(test_move_critter_obj);
expected_turn_tile := tile_num_in_direction(initial_tile, (initial_rotation + 3) % 6, 1);
expected_move_tile := tile_num_in_direction(initial_tile, initial_rotation, 1);
initial_fid := get_object_data(test_fid_obj, OBJ_DATA_FID);
expected_fid := get_object_data(test_fid_source_obj, OBJ_DATA_FID);
initial_hide_visibility := obj_is_visible_flag(test_hide_obj);
initial_destroy_visibility := obj_is_visible_flag(test_destroy_obj);
pending_frames := 0;
test_objects_ready := true;
end
procedure ensure_test_objects begin
if (test_objects_ready) then return;
call setup_test_objects();
end
procedure queue_full_sequence begin
reg_anim_begin();
reg_anim_turn_towards(test_move_critter_obj, expected_turn_tile, -1);
reg_anim_take_out(test_takeout_critter_obj, TEST_TAKE_OUT_FRAME, -1);
reg_anim_light(test_light_obj, TEST_LIGHT_VALUE, -1);
reg_anim_change_fid(test_fid_obj, expected_fid, -1);
reg_anim_animate_and_hide(test_hide_obj, TEST_STAND_ANIM, -1);
reg_anim_destroy(test_destroy_obj);
reg_anim_animate_and_move(test_move_critter_obj, expected_move_tile, TEST_WALK_ANIM, -1);
reg_anim_end();
end
procedure start_blocked_test begin
pending_test := 1;
pending_timeout_frames := 30;
call ensure_test_objects();
call queue_full_sequence();
display_msg("Started blocked-case test.");
end
procedure start_enabled_test begin
pending_test := 2;
pending_timeout_frames := 120;
call ensure_test_objects();
reg_anim_combat_check(0);
call queue_full_sequence();
display_msg("Started enabled-case test.");
end
procedure start_noncombat_test begin
pending_test := 3;
pending_timeout_frames := 120;
call ensure_test_objects();
call queue_full_sequence();
display_msg("Started non-combat opcode test.");
end
procedure keypress_handler begin
variable
pressed := get_sfall_arg_at(0),
key := get_sfall_arg_at(1);
if (not pressed) then return;
if (pending_test != 0) then begin
if (key == DIK_X or key == DIK_V or key == DIK_N) then
display_msg("A reg_anim_combat_check test is already running.");
return;
end
if (combat_data and key == DIK_X) then begin
display_msg("X: combat should block all reg_anim calls in this sequence.");
call start_blocked_test();
end else if (combat_data and key == DIK_V) then begin
display_msg("V: reg_anim_combat_check(0) should allow the registered animations in combat.");
call start_enabled_test();
end else if ((not combat_data) and key == DIK_N) then begin
if (noncombat_test_completed) then begin
display_msg("N already ran once. Reload the map or game before running it again.");
return;
end
display_msg("N: outside combat, the full reg_anim opcode sequence should run.");
call start_noncombat_test();
end else if (key == DIK_X or key == DIK_V) then begin
display_msg("Enter combat before running X or V.");
end else if (key == DIK_N) then begin
display_msg("Leave combat before running N.");
end
end
procedure report_blocked_results begin
variable errors_before := test_suite_errors;
call assertEquals("turn_towards blocked", obj_get_rot(test_move_critter_obj), initial_rotation);
call assertEquals("animate_and_move blocked", tile_num(test_move_critter_obj), initial_tile);
call assertEquals("change_fid blocked", get_object_data(test_fid_obj, OBJ_DATA_FID), initial_fid);
call assertEquals("animate_and_hide blocked", obj_is_visible_flag(test_hide_obj), initial_hide_visibility);
call assertEquals("destroy blocked", obj_is_visible_flag(test_destroy_obj), initial_destroy_visibility);
if (test_suite_errors == errors_before) then
display_msg("PASS blocked automatic checks");
else
display_msg("FAIL blocked automatic checks");
call report_test_results("reg_anim_combat_check_blocked");
end
procedure report_enabled_results begin
variable errors_before := test_suite_errors;
call assertNotEquals("turn_towards runs in combat when enabled", obj_get_rot(test_move_critter_obj), initial_rotation);
call assertEquals("animate_and_move runs in combat when enabled", tile_num(test_move_critter_obj), expected_move_tile);
call assertEquals("change_fid runs in combat when enabled", get_object_data(test_fid_obj, OBJ_DATA_FID), expected_fid);
if (test_suite_errors == errors_before) then
display_msg("PASS enabled automatic checks");
else
display_msg("FAIL enabled automatic checks");
call report_test_results("reg_anim_combat_check_enabled");
end
procedure report_noncombat_results begin
variable errors_before := test_suite_errors;
noncombat_test_completed := true;
call assertNotEquals("turn_towards outside combat", obj_get_rot(test_move_critter_obj), initial_rotation);
call assertEquals("animate_and_move outside combat", tile_num(test_move_critter_obj), expected_move_tile);
call assertEquals("change_fid outside combat", get_object_data(test_fid_obj, OBJ_DATA_FID), expected_fid);
call assertEquals("animate_and_hide outside combat", obj_is_visible_flag(test_hide_obj), 0);
if (test_suite_errors == errors_before) then
display_msg("PASS non-combat automatic checks");
else
display_msg("FAIL non-combat automatic checks");
call report_test_results("reg_anim_full_noncombat");
display_msg("Manual check: outside combat, the other clone should play take out, light should visibly apply if supported by the object type, and destroy_obj should be gone.");
end
procedure poll_pending_test begin
if (pending_test == 0) then return;
pending_frames += 1;
if (pending_frames < pending_timeout_frames) then return;
variable current_test := pending_test;
pending_test := 0;
pending_frames := 0;
pending_timeout_frames := 0;
if (current_test == 1) then begin
call report_blocked_results();
end else if (current_test == 2) then begin
call report_enabled_results();
end else if (current_test == 3) then begin
call report_noncombat_results();
end
end
procedure start begin
set_global_script_repeat(1);
if (not hook_registered and game_loaded) then begin
hook_registered := true;
call ensure_test_objects();
register_hook_proc(HOOK_KEYPRESS, keypress_handler);
display_msg("reg_anim_combat_check test loaded. Enter combat for X/V, or stay out of combat for N (one-shot).");
end
call poll_pending_test();
end
-78
View File
@@ -1,78 +0,0 @@
#include "sfall.h"
#include "test_utils.h"
variable blocker_obj := 0;
procedure cleanup begin
if (blocker_obj) then begin
destroy_object(blocker_obj);
blocker_obj := 0;
end
end
procedure start begin
variable elev := elevation(dude_obj);
variable dude_tile := tile_num(dude_obj);
variable dir;
variable step_tile := -1;
variable step_dir := -1;
variable block_tile := -1;
variable path;
variable objs;
variable ground_fid;
variable roof_fid;
display_msg("Testing tile/path functions...");
call cleanup();
for (dir := 0; dir < 6; dir += 1) begin
variable candidate := tile_num_in_direction(dude_tile, dir, 1);
if (candidate != dude_tile and obj_blocking_tile(candidate, elev, BLOCKING_TYPE_BLOCK) == 0) then begin
if (step_tile == -1) then begin
step_tile := candidate;
step_dir := dir;
end
if (block_tile == -1 and candidate != step_tile) then begin
block_tile := candidate;
end
end
end
call assertNotEquals("found reachable neighboring tile", step_tile, -1);
if (step_tile != -1) then begin
path := path_find_to(dude_obj, step_tile, BLOCKING_TYPE_BLOCK);
call assertEquals("one-step path length", len_array(path), 1);
if (len_array(path) == 1) then
call assertEquals("one-step path direction", get_array(path, 0), step_dir);
end
if (block_tile != -1) then begin
blocker_obj := create_object_sid(obj_pid(dude_obj), block_tile, elev, -1);
call assertNotEquals("spawned blocking critter", blocker_obj, 0);
if (blocker_obj) then begin
path := path_find_to(dude_obj, tile_num(blocker_obj), BLOCKING_TYPE_BLOCK);
call assertEquals("occupied destination returns empty path", len_array(path), 0);
end
end else begin
display_msg("Skipping occupied-destination path check: no free adjacent tile for blocker.");
end
objs := tile_get_objs(dude_tile, elev);
call assertTrue("tile_get_objs contains dude", scan_array(objs, dude_obj) != -1);
ground_fid := get_tile_ground_fid(dude_tile, elev);
roof_fid := get_tile_roof_fid(dude_tile, elev);
call assertTrue("ground fid is non-negative", ground_fid >= 0);
call assertTrue("roof fid is non-negative", roof_fid >= 0);
call assertEquals("ground helper matches ext", ground_fid, get_tile_fid_ext(dude_tile, elev, 0));
call assertEquals("roof helper matches ext", roof_fid, get_tile_fid_ext(dude_tile, elev, 1));
call assertTrue("tile_light returns non-negative intensity", tile_light(elev, dude_tile) >= 0);
call assertEquals("tile_by_position metarule exists", metarule_exist("tile_by_position"), 1);
call assertEquals("tile_by_position matches tile_under_cursor", tile_by_position(get_mouse_x, get_mouse_y), tile_under_cursor);
tile_refresh_display;
call cleanup();
call report_test_results("tile_path");
end
-166
View File
@@ -1,166 +0,0 @@
#include "../sfall/sfall.h"
#include "../sfall/dik.h"
#include "../sfall/define_lite.h"
#include "../test_utils.h"
#include "../sfall/lib.arrays.h"
variable last_game_mode;
variable gamemodechange_assertions_enabled := false;
variable gamemodechange_reported := false;
procedure test_with_args(variable arg1) begin
display_msg("test_w_arg" + arg1);
end
procedure test_wo_args begin
display_msg("test_wo_args");
end
procedure tohit_handler begin
variable
attacker := get_sfall_arg_at(1),
target := get_sfall_arg_at(2),
chanceRaw := get_sfall_arg_at(7);
display_msg(string_format("tohit %s -> %s (%d)", obj_name(attacker), obj_name(target), chanceRaw));
if (attacker == dude_obj) then
set_sfall_return(100);
else if (target == dude_obj) then
set_sfall_return(0);
end
procedure useobj_handler begin
variable
user := get_sfall_arg,
item := get_sfall_arg;
display_msg(string_format("useobj %s (%s)", obj_name(user), obj_name(item)));
set_sfall_return(2);
end
procedure useobjon_handler begin
variable args := get_sfall_args,
target := args[0],
user := args[1],
item := args[2];
display_msg(string_format("useobjon %s (%s) -> %s [len: %d]", obj_name(user), obj_name(item), obj_name(target), len_array(args)));
set_sfall_return(0);
end
procedure keypress_handler begin
variable
pressed := get_sfall_arg_at(0),
key := get_sfall_arg_at(1);
display_msg(string_format("keypress %d dx: %d", pressed, key));
if (not pressed) then return;
if (key == DIK_F2) then begin
display_msg(string_format("tile %d, elev %d, map %d", tile_under_cursor, elevation(dude_obj), cur_map_index));
end if (key == DIK_F3) then begin
if (key_pressed(DIK_LCONTROL)) then begin
variable cr := obj_under_cursor(true, false);
if (cr) then
critter_dmg(cr, 1000, DMG_BYPASS_ARMOR);
end else
move_to(dude_obj, tile_under_cursor, elevation(dude_obj));
end
end
procedure gamemodechange_handler begin
variable
event_type := get_sfall_arg_at(0),
previous_mode := get_sfall_arg_at(1),
current_mode := get_game_mode;
display_msg(string_format("gamemodechange event=%d prev=%d cur=%d", event_type, previous_mode, current_mode));
if (not gamemodechange_assertions_enabled) then begin
last_game_mode := current_mode;
return;
end
call assertTrue("gamemodechange event_type is 0 or 1", event_type == 0 or event_type == 1);
call assertEquals("gamemodechange previous mode", previous_mode, last_game_mode);
if (event_type == 0) then
call assertNotEquals("gamemodechange mode changed", current_mode, previous_mode);
else if (not gamemodechange_reported) then begin
gamemodechange_reported := true;
call report_test_results("hook_gamemodechange");
end
last_game_mode := current_mode;
end
procedure combatdamage_handler begin
variable args := get_sfall_args;
display_msg(sprintf("combatdamage %s", debug_array_str(args)));
set_sfall_return(10); // target dmg
set_sfall_return(5);
set_sfall_return(0);
set_sfall_return(DAM_HIT); // attacker flag
set_sfall_return(10); // knockback
end
procedure barterprice_handler begin
variable
args := get_sfall_args,
value := args[2],
caps := args[4],
offerValue := args[7],
offerTable := args[6],
offerCaps := item_caps_total(offerTable);
display_msg(sprintf("barterprice %s", debug_array_str(args)));
set_sfall_return((value - caps) * 2 + caps);
set_sfall_return((offerValue - offerCaps) / 2 + offerCaps);
end
#define ANIM_fall_back (20)
#define ANIM_fall_front (21)
#define ANIM_fire_dance (33)
procedure deathanim_handler begin
variable
args := get_sfall_args;
display_msg(sprintf("deathanim %s", debug_array_str(args)));
set_sfall_return(ANIM_fire_dance);
end
procedure start begin
//call test_with_args(777);
display_msg("start hook test");
if (not game_loaded) then return;
add_obj_to_inven(dude_obj, create_object_sid(40, 0, 0, -1));
add_obj_to_inven(dude_obj, create_object_sid(76, 0, 0, -1));
add_obj_to_inven(dude_obj, create_object_sid(85, 0, 0, -1));
last_game_mode := get_game_mode;
gamemodechange_assertions_enabled := true;
register_hook_proc(HOOK_KEYPRESS, keypress_handler);
register_hook_proc(HOOK_TOHIT, tohit_handler);
register_hook_proc(HOOK_USEOBJ, useobj_handler);
register_hook_proc(HOOK_USEOBJON, useobjon_handler);
register_hook_proc(HOOK_GAMEMODECHANGE, gamemodechange_handler);
register_hook_proc(HOOK_COMBATDAMAGE, combatdamage_handler);
register_hook_proc(HOOK_BARTERPRICE, barterprice_handler);
register_hook_proc(HOOK_DEATHANIM2, deathanim_handler);
end
procedure map_enter_p_proc begin
display_msg("Map Enter hook test");
end
-1
View File
@@ -1,7 +1,6 @@
[ValidSection]
Key1=Value1
Key2=2
EmptyValue=
[SectionWithSpaces]
LeadingSpaceKey = LeadingSpaceValue
-1
View File
@@ -1 +0,0 @@
{100}{}{auto extra msg}
-11
View File
@@ -18,17 +18,6 @@ procedure assertTrue(variable desc, variable a) begin
end
end
procedure assertFalse(variable desc, variable a) begin
test_suite_assertions++;
if (a) then begin
display_msg("Assertion failed \""+desc+"\": is not false");
test_suite_errors ++;
end else if (test_suite_verbose) then begin
display_msg("Assert \""+desc+"\" ok");
end
end
procedure assertEquals(variable desc, variable a, variable b) begin
test_suite_assertions++;

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