Compare commits

..
185 changed files with 5793 additions and 18991 deletions
+6 -170
View File
@@ -25,9 +25,6 @@ if(MSVC)
endif()
option(FALLOUT_VENDORED "Use vendored third-party libraries" ON)
option(FALLOUT_AUDIO_OGG "Enable OGG decoding with stb_vorbis when available" ON)
set(FALLOUT_STB_VORBIS_DIR "" CACHE PATH "Directory containing stb_vorbis.c")
if(ANDROID)
add_library(${EXECUTABLE_NAME} SHARED)
@@ -38,15 +35,15 @@ endif()
# Git Info
include("cmake/gitver.cmake")
# Shared engine sources — used by both game and mapper targets.
# Excludes main.cc/main.h (game-only entry logic).
set(FALLOUT_ENGINE_SOURCES
target_sources(${EXECUTABLE_NAME} PUBLIC
"src/actions.cc"
"src/actions.h"
"src/animation.cc"
"src/animation.h"
"src/art.cc"
"src/art.h"
"src/audio_file.cc"
"src/audio_file.h"
"src/audio.cc"
"src/audio.h"
"src/automap.cc"
@@ -154,13 +151,13 @@ set(FALLOUT_ENGINE_SOURCES
"src/lips.h"
"src/loadsave.cc"
"src/loadsave.h"
"src/main.cc"
"src/main.h"
"src/mainmenu.cc"
"src/mainmenu.h"
"src/map_defs.h"
"src/map.cc"
"src/map.h"
"src/map_edge.cc"
"src/map_edge.h"
"src/memory_defs.h"
"src/memory_manager.cc"
"src/memory_manager.h"
@@ -183,8 +180,6 @@ set(FALLOUT_ENGINE_SOURCES
"src/obj_types.h"
"src/object.cc"
"src/object.h"
"src/ogg_decoder.cc"
"src/ogg_decoder.h"
"src/opcode_context.cc"
"src/opcode_context.h"
"src/options.cc"
@@ -268,7 +263,7 @@ set(FALLOUT_ENGINE_SOURCES
"src/xfile.h"
)
set(FALLOUT_PLATFORM_SOURCES
target_sources(${EXECUTABLE_NAME} PUBLIC
"src/audio_engine.cc"
"src/audio_engine.h"
"src/delay.cc"
@@ -302,8 +297,6 @@ set(FALLOUT_PLATFORM_SOURCES
"src/sfall_opcodes.cc"
"src/sfall_opcodes.h"
"src/sfall_script_hooks.cc"
"src/script_sound.cc"
"src/script_sound.h"
"src/sfall_arrays.cc"
"src/sfall_arrays.h"
"src/sfall_animation.cc"
@@ -316,43 +309,8 @@ set(FALLOUT_PLATFORM_SOURCES
"third_party/lodepng/lodepng.cpp"
)
target_sources(${EXECUTABLE_NAME} PUBLIC
${FALLOUT_ENGINE_SOURCES}
"src/main.cc"
"src/main.h"
)
target_sources(${EXECUTABLE_NAME} PUBLIC ${FALLOUT_PLATFORM_SOURCES})
target_include_directories(${EXECUTABLE_NAME} PUBLIC "third_party/lodepng")
set(FALLOUT_HAVE_STB_VORBIS OFF)
if(FALLOUT_AUDIO_OGG)
if(EXISTS "${CMAKE_SOURCE_DIR}/third_party/stb_vorbis/stb_vorbis.c")
set(_fallout_stb_vorbis_dir "${CMAKE_SOURCE_DIR}/third_party/stb_vorbis")
else()
set(_fallout_stb_vorbis_dir "${FALLOUT_STB_VORBIS_DIR}")
if(NOT _fallout_stb_vorbis_dir)
find_path(_fallout_stb_vorbis_dir
NAMES "stb_vorbis.c"
DOC "Directory containing stb_vorbis.c")
endif()
endif()
if(_fallout_stb_vorbis_dir AND EXISTS "${_fallout_stb_vorbis_dir}/stb_vorbis.c")
set(FALLOUT_HAVE_STB_VORBIS ON)
target_include_directories(${EXECUTABLE_NAME} PRIVATE "${_fallout_stb_vorbis_dir}")
else()
message(STATUS "OGG support disabled: stb_vorbis.c not found")
endif()
endif()
if(FALLOUT_HAVE_STB_VORBIS)
target_compile_definitions(${EXECUTABLE_NAME} PRIVATE HAVE_STB_VORBIS=1)
else()
target_compile_definitions(${EXECUTABLE_NAME} PRIVATE HAVE_STB_VORBIS=0)
endif()
if(IOS)
target_sources(${EXECUTABLE_NAME} PUBLIC
"src/platform/ios/paths.h"
@@ -372,33 +330,14 @@ if(WIN32)
)
endif()
if(MINGW)
target_compile_definitions(${EXECUTABLE_NAME} PUBLIC
_USE_MATH_DEFINES
)
endif()
if(WIN32)
target_link_libraries(${EXECUTABLE_NAME}
winmm
)
endif()
if(MSVC)
target_link_libraries(${EXECUTABLE_NAME}
debug libcpmtd
optimized libcpmt
)
endif()
if(MINGW)
target_link_options(${EXECUTABLE_NAME} PRIVATE
-static
-static-libgcc
-static-libstdc++
)
endif()
if(WIN32)
target_sources(${EXECUTABLE_NAME} PUBLIC
"os/windows/fallout2-ce.ico"
@@ -515,7 +454,6 @@ target_link_libraries(${EXECUTABLE_NAME} ${ZLIB_LIBRARIES})
target_include_directories(${EXECUTABLE_NAME} PRIVATE ${ZLIB_INCLUDE_DIRS})
target_link_libraries(${EXECUTABLE_NAME} ${SDL2_LIBRARIES})
target_link_libraries(${EXECUTABLE_NAME} ${SDL2_MAIN_LIBRARIES})
target_include_directories(${EXECUTABLE_NAME} PRIVATE ${SDL2_INCLUDE_DIRS})
if((NOT ANDROID) AND (NOT IOS) AND (NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten"))
@@ -542,13 +480,6 @@ if((NOT ANDROID) AND (NOT IOS) AND (NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten"))
if(WIN32)
target_link_libraries(ce-dat-tool winmm)
endif()
if(MINGW)
target_link_options(ce-dat-tool PRIVATE
-static
-static-libgcc
-static-libstdc++
)
endif()
target_include_directories(ce-dat-tool PRIVATE "src")
target_include_directories(ce-dat-tool PRIVATE ${ZLIB_INCLUDE_DIRS})
target_include_directories(ce-dat-tool PRIVATE ${SDL2_INCLUDE_DIRS})
@@ -572,14 +503,6 @@ if((NOT ANDROID) AND (NOT IOS) AND (NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten"))
target_include_directories(ce-frm2png PRIVATE ${ZLIB_INCLUDE_DIRS})
target_link_libraries(ce-frm2png ${SDL2_LIBRARIES})
target_link_libraries(ce-frm2png ${ZLIB_LIBRARIES})
if(MINGW)
target_link_options(ce-frm2png PRIVATE
-static
-static-libgcc
-static-libstdc++
)
endif()
if(APPLE)
file(GLOB_RECURSE CE_DAT_INPUTS CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/files/ce.dat/*")
@@ -604,93 +527,6 @@ if((NOT ANDROID) AND (NOT IOS) AND (NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten"))
endif()
endif()
if((NOT ANDROID) AND (NOT IOS) AND (NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten"))
if(WIN32)
add_executable(mapper-ce WIN32)
else()
add_executable(mapper-ce)
endif()
target_sources(mapper-ce PUBLIC
${FALLOUT_ENGINE_SOURCES}
${FALLOUT_PLATFORM_SOURCES}
"src/mapper/map_func.cc"
"src/mapper/map_func.h"
"src/mapper/mapper.cc"
"src/mapper/mapper.h"
"src/mapper/mp_instance.cc"
"src/mapper/mp_instance.h"
"src/mapper/mp_proto.cc"
"src/mapper/mp_proto.h"
"src/mapper/mp_scrpt.cc"
"src/mapper/mp_scrpt.h"
"src/mapper/mp_targt.cc"
"src/mapper/mp_targt.h"
"src/mapper/mp_text.cc"
"src/mapper/mp_text.h"
)
target_compile_definitions(mapper-ce PUBLIC FALLOUT_MAPPER)
if(WIN32)
target_compile_definitions(mapper-ce PUBLIC
_CRT_SECURE_NO_WARNINGS
_CRT_NONSTDC_NO_WARNINGS
NOMINMAX
WIN32_LEAN_AND_MEAN
_STATIC_CPPLIB
)
if(MINGW)
target_compile_definitions(mapper-ce PUBLIC
_USE_MATH_DEFINES
)
target_link_options(mapper-ce PRIVATE
-static
-static-libgcc
-static-libstdc++
)
endif()
target_link_libraries(mapper-ce
winmm
)
if(MSVC)
target_link_libraries(mapper-ce
debug libcpmtd
optimized libcpmt
)
endif()
target_sources(mapper-ce PUBLIC
"os/windows/fallout2-ce.rc"
)
endif()
if(APPLE)
target_link_libraries(mapper-ce "-framework CoreFoundation")
set_target_properties(mapper-ce PROPERTIES
XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO"
XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO"
)
endif()
target_include_directories(mapper-ce PUBLIC "third_party/lodepng")
target_include_directories(mapper-ce PRIVATE "src")
target_include_directories(mapper-ce PRIVATE ${ZLIB_INCLUDE_DIRS})
target_include_directories(mapper-ce PRIVATE ${SDL2_INCLUDE_DIRS})
target_link_libraries(mapper-ce
fpattern::fpattern
fpattern_windows::fpattern_windows
${ZLIB_LIBRARIES}
${SDL2_LIBRARIES}
${SDL2_MAIN_LIBRARIES}
)
endif()
if(APPLE)
if(IOS)
install(TARGETS ${EXECUTABLE_NAME} DESTINATION "Payload")
-91
View File
@@ -139,77 +139,6 @@
"cacheVariables": {
"CMAKE_SYSTEM_NAME": "iOS"
}
},
{
"name": "Mingw-base",
"hidden": true,
"description": "Base preset for all MinGW builds.",
"inherits":[
"base"
],
"generator": "Ninja",
"toolchainFile": "${sourceDir}/cmake/toolchain/mingw.cmake",
"cacheVariables": {
"CMAKE_SYSTEM_NAME": "Windows"
}
},
{
"name": "Mingw-x86-base",
"hidden": true,
"description": "Base preset for all MinGW x86 builds.",
"inherits": [
"Mingw-base"
],
"cacheVariables": {
"CMAKE_C_FLAGS": "-m32",
"CMAKE_CXX_FLAGS": "-m32",
"CMAKE_SYSTEM_PROCESSOR": "i686"
}
},
{
"name": "Mingw-x86-debug",
"displayName": "MinGW x86 Debug",
"description": "Cross-compile a Debug Windows x86 build with MinGW-w64 and Ninja.",
"inherits": [
"Mingw-x86-base"
],
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "Mingw-x86-release",
"displayName": "MinGW x86 Release",
"description": "Cross-compile a RelWithDebInfo Windows x86 build with MinGW-w64 and Ninja.",
"inherits": [
"Mingw-x86-debug"
],
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
}
},
{
"name": "Mingw-x64-debug",
"displayName": "MinGW x64 Debug",
"description": "Cross-compile a Debug Windows x64 build with MinGW-w64 and Ninja.",
"inherits": [
"Mingw-base"
],
"cacheVariables": {
"CMAKE_SYSTEM_PROCESSOR": "x86_64",
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "Mingw-x64-release",
"displayName": "MinGW x64 Release",
"description": "Cross-compile a RelWithDebInfo Windows x64 build with MinGW-w64 and Ninja.",
"inherits": [
"Mingw-x64-debug"
],
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
}
}
],
"buildPresets": [
@@ -268,26 +197,6 @@
"name": "ios-release",
"configurePreset": "ios",
"configuration": "RelWithDebInfo"
},
{
"name": "Mingw-x86-Debug",
"displayName": "MinGW x86 Debug",
"configurePreset": "Mingw-x86-debug"
},
{
"name": "Mingw-x86-Release",
"displayName": "MinGW x86 Release",
"configurePreset": "Mingw-x86-release"
},
{
"name": "Mingw-x64-Debug",
"displayName": "MinGW x64 Debug",
"configurePreset": "Mingw-x64-debug"
},
{
"name": "Mingw-x64-Release",
"displayName": "MinGW x64 Release",
"configurePreset": "Mingw-x64-release"
}
]
}
+3 -6
View File
@@ -105,13 +105,13 @@ docker run --rm -v $(pwd):/src emscripten/emsdk:3.1.74 sh -c 'git config --globa
## Configuration
The main configuration file is `fallout2.cfg`. There are several important settings you might need to adjust for your installation. Depending on your Fallout distribution main game assets `master.dat`, `critter.dat`, `patch000.dat`, and `data` folder might be either all lowercased, or all uppercased. You can either update `master_dat`, `critter_dat`, `master_patches` and `critter_patches` settings to match your file names, or rename files to match entries in your `fallout2.cfg`.
The main configuration file is `fallout2-ce.cfg`. There are several important settings you might need to adjust for your installation. Depending on your Fallout distribution main game assets `master.dat`, `critter.dat`, `patch000.dat`, and `data` folder might be either all lowercased, or all uppercased. You can either update `master_dat`, `critter_dat`, `master_patches` and `critter_patches` settings to match your file names, or rename files to match entries in your `fallout2-ce.cfg`.
The `sound` folder (with `music` folder inside) might be located either in `data` folder, or be in the Fallout folder. Update `music_path1` setting to match your hierarchy, usually it's `data/sound/music/` or `sound/music/`. Make sure it matches your path exactly (so it might be `SOUND/MUSIC/` if you've installed Fallout from CD). Music files themselves (with `ACM` extension) should be all uppercased, regardless of `sound` and `music` folders.
Additional settings for screen resolution, UI customization, and map options are now integrated into the main `fallout2.cfg` file (previously part of `f2_res.ini` from Mash's HRP). When Fallout 2 CE starts, if it detects an existing `f2_res.ini` file, it automatically migrates these settings into `fallout2.cfg`. After migration, `fallout2.cfg` becomes the single source of truth for this configuration.
Additional settings for screen resolution, UI customization, and map options are now integrated into the main `fallout2-ce.cfg` file (previously part of `f2_res.ini` from Mash's HRP). When Fallout 2 CE starts, if it detects an existing `f2_res.ini` file, it automatically migrates these settings into main config. After that, `fallout2-ce.cfg` becomes the single source of truth for this configuration.
Here are some important settings in `fallout2.cfg` under the `[screen]` and `[ui]` sections. See [the example config](https://github.com/fallout2-ce/fallout2-ce/tree/refs/heads/main/files/fallout2.cfg) for a full list of settings.
Here are some important settings in `fallout2-ce.cfg` under the `[screen]` and `[ui]` sections. See [the example config](https://github.com/fallout2-ce/fallout2-ce/tree/refs/heads/main/files/ce.cfg) for a full list of settings.
```ini
[screen]
@@ -143,7 +143,6 @@ In time this stuff will receive in-game interface, right now you have to do it m
* Expanded 2-column inventory
* Expanded 4-row barter screen
* Expanded AP bar
* Party members can loot and barter in place of PC
* 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
@@ -151,8 +150,6 @@ In time this stuff will receive in-game interface, right now you have to do it m
* When bartering, caps default to the right amount to balance the trade (if possible)
* Music continues playing between maps
* Auto open doors
* 44.1 kHz stereo sound/music supported, in .ogg and .wav format as well as legacy .acm
* Last used save slot is remembered
## Contributing
+13 -25
View File
@@ -4,25 +4,13 @@ This document tracks Fallout 2 CE compatibility with sfall. This is for modders
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.
## HRP EDG Scroll-Blocker Support
CE supports the `.edg` file format from the HRP (High Resolution Patch), which defines per-map scroll boundaries and square-level render clipping.
**How it works in CE:**
- On map load, `maps/<mapname>.edg` is read if present. Missing file = silent fallback to the scroll-blocker object system.
- The `.edg` file defines per-elevation rectangle boundary zones. Multiple chained zones per elevation are supported.
- When loaded, these zones are used for both scroll blocking and visible area clipping (black bars), replacing both vanilla scroll blocking and CE hi-res stencil system.
- v2 EDG files also contain a `SquareRect` that defines "Angled edges", or square-grid stencil. This is also supported.
## Settings (ddraw.ini → fallout2.cfg / game.cfg)
Settings previously read from `ddraw.ini` have been moved into standard CE config files.
Most settings that control game behavior (premade characters, extra message files, combat tweaks, worldmap, etc.) have been moved into [`<DAT>/config/game.cfg`](files/ce.dat/config/game.cfg), which is a content-mod config file intended to be overridden by mods. See that file for the full list with descriptions.
The following settings were moved into [`fallout2.cfg`](files/fallout2.cfg) instead:
The following settings were moved into [`fallout2-ce.cfg`](files/ce.cfg) instead:
| ddraw.ini section | ddraw.ini key | fallout2.cfg section | fallout2.cfg key |
| --- | --- | --- | --- |
@@ -55,7 +43,7 @@ See [`https://sfall-team.github.io/sfall/`](https://sfall-team.github.io/sfall/)
| 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 | play_sfall_sound<br>stop_sfall_sound | âś… | `play_sfall_sound` currently supports `.acm`, `.wav`, `.ogg` formats, and can load from `.dat` archives. `.mp3` is not yet supported. |
| 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 | âś… | - |
@@ -67,10 +55,10 @@ See [`https://sfall-team.github.io/sfall/`](https://sfall-team.github.io/sfall/)
| 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 | âś… | - |
| 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 | âś… | `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 | âś… | Legacy `BoxBarCount`, `BoxBarColors` ddraw.ini settings not supported. |
| Interface / Tags | show_iface_tag<br>hide_iface_tag<br>is_iface_tag_active<br>set_iface_tag_text<br>add_iface_tag | âś… 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 | âś… except get_sfall_global_float | Current CE storage is int-backed; `set_sfall_global` stores integer values |
| 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 | âś… | 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 | âś… | - |
| 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 | âś… except available_global_script_types | - |
| 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: get_attack_type, get/set_bodypart_hit_modifier, combat_data, get/set_critter_current_ap, get/set_combat_free_move | - |
@@ -82,9 +70,9 @@ See [`https://sfall-team.github.io/sfall/`](https://sfall-team.github.io/sfall/)
| Interface / Cursor | get/set_cursor_mode | âś… | - |
| Locks | lock_is_jammed<br>unjam_lock<br>set_unjam_locks_time | not implemented | - |
| INI settings | 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 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>get/set_script<br>obj_is_carrying_obj<br>loot_obj<br>dialog_obj<br>obj_under_cursor<br>get/set_object_data<br>get/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/set/remove_script, obj_is_carrying_obj, loot_obj, dialog_obj, obj_under_cursor, get_object_data, get_flags, set_flags, set_unique_id, obj_is_openable, get_proto_data, set_proto_data | - |
| Objects and scripts | set_self<br>set_dude_obj<br>real_dude_obj<br>remove_script<br>get/set_script<br>obj_is_carrying_obj<br>loot_obj<br>dialog_obj<br>obj_under_cursor<br>get/set_object_data<br>get/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/set/remove_script, obj_is_carrying_obj, loot_obj, dialog_obj, obj_under_cursor, get_object_data, get_flags, set_flags, obj_is_openable, get_proto_data, set_proto_data | - |
| Other / Game management | set_movie_path<br>stop/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, signal_close_game | - |
| Gameplay tweaks | 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>set_hp_per_level_mod<br>gdialog_get_barter_mod<br>get/set_unspent_ap_bonus<br>get/set_unspent_ap_perk_bonus<br>set_base_pickpocket_mod<br>set_critter_pickpocket_mod<br>get/set_inven_ap_cost<br>set_drugs_data<br>get_kill_counter<br>mod_kill_counter<br>set_pipboy_available | implemented: gdialog_get_barter_mod, get/set_unspent_ap{_perk}_bonus, get/set_inven_ap_cost | - |
| Gameplay tweaks | 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>set_hp_per_level_mod<br>gdialog_get_barter_mod<br>get/set_unspent_ap_bonus<br>get/<br>set_base_pickpocket_mod<br>set_critter_pickpocket_mod<br>get/set_inven_ap_cost<br>set_drugs_data<br>get_kill_counter<br>mod_kill_counter<br>set_pipboy_available | implemented: gdialog_get_barter_mod | - |
| NPCs | inc_npc_level<br>get_npc_level<br>npc_engine_level_up | not implemented | - |
| Other | get_year<br>set_dm/df_model<br>active_hand<br>toggle_active_hand<br>get/set_viewport_x/y<br>hero_select_win<br>get_light_level<br>message_str_game<br>sneak_success<br>create_spatial<br>unwield_slot<br>add_g_timer_event<br>add_extra_msg_file<br>get_metarule_table<br>metarule_exist<br>remove_timer_event<br>spatial_radius | implemented: get_year, active_hand, toggle_active_hand, get_light_level, 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. |
@@ -109,12 +97,12 @@ See [`https://sfall-team.github.io/sfall/`](https://sfall-team.github.io/sfall/)
| AmmoCost | `HOOK_AMMOCOST` | âś… | Requires `check_weapon_ammo_cost=1` if you want pre-attack ammo validation to respect per-shot/per-round overrides. |
| KeyPress | `HOOK_KEYPRESS` | âś… | Third hook arg is currently `0`; CE doesn't use VK codes. |
| MouseClick | `HOOK_MOUSECLICK` | âś… | - |
| UseSkill | `HOOK_USESKILL` | âś… | - |
| Steal | `HOOK_STEAL` | âś… | - |
| UseSkill | `HOOK_USESKILL` | đźš« | - |
| Steal | `HOOK_STEAL` | đźš« | Et tu |
| WithinPerception | `HOOK_WITHINPERCEPTION` | âś… | - |
| InventoryMove | `HOOK_INVENTORYMOVE` | âś… | - |
| InvenWield | `HOOK_INVENWIELD` | âś… | - |
| AdjustFID | `HOOK_ADJUSTFID` | âś… | Second hook arg currently matches the first because CE has no internal FID modifiers like Hero Appearance. |
| InvenWield | `HOOK_INVENWIELD` | đźš« | - |
| AdjustFID | `HOOK_ADJUSTFID` | đźš« | - |
| CombatTurn | `HOOK_COMBATTURN` | âś… | - |
| StdProcedure | `HOOK_STDPROCEDURE` | âś… | - |
| StdProcedureEnd | `HOOK_STDPROCEDURE_END` | âś… | - |
@@ -125,16 +113,16 @@ See [`https://sfall-team.github.io/sfall/`](https://sfall-team.github.io/sfall/)
| UseAnimObj | `HOOK_USEANIMOBJ` | đźš« | Et tu; (maybe) |
| ExplosiveTimer | `HOOK_EXPLOSIVETIMER` | âś… | - |
| DescriptionObj | `HOOK_DESCRIPTIONOBJ` | đźš« | Et tu |
| UseSkillOn | `HOOK_USESKILLON` | âś… | - |
| 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` | âś… | - |
| Encounter | `HOOK_ENCOUNTER` | đźš« | Et tu |
| AdjustPoison | `HOOK_ADJUSTPOISON` | đźš« | (maybe) |
| AdjustRads | `HOOK_ADJUSTRADS` | đźš« | (maybe) |
| RollCheck | `HOOK_ROLLCHECK` | đźš« | - |
| BestWeapon | `HOOK_BESTWEAPON` | đźš« | - |
| CanUseWeapon | `HOOK_CANUSEWEAPON` | âś… | - |
| CanUseWeapon | `HOOK_CANUSEWEAPON` | đźš« | - |
| BuildSfxWeapon | `HOOK_BUILDSFXWEAPON` | đźš« | - |
-18
View File
@@ -1,18 +0,0 @@
# specify the cross compiler
set(CMAKE_C_COMPILER ${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32-gcc)
set(CMAKE_CXX_COMPILER ${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32-g++)
set(CMAKE_RC_COMPILER ${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32-windres)
# where is the target environment
set(CMAKE_FIND_ROOT_PATH /usr/${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32)
# search for programs in the build host directories
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
# CMake determines how to examine dependencies based on the *host* system, leading to
# a `file unknown error` unless the target platform is explicitly specified.
set(CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM "windows+pe")
-12
View File
@@ -22,10 +22,6 @@ save_text_maps=0
show_pid_numbers=0
sort_script_list=0
use_art_not_protos=0
; Allows to load a certain map right away after loading the mapper.
map=denbus2
; Allows to disable grid item picker and use a simpler list-based picker.
use_grid_item_picker=1
[preferences]
brightness=1.000000
@@ -98,8 +94,6 @@ auto_quick_save=3
display_bonus_damage=1
;Set to 1 to get notification of karma changes in the notification window
display_karma_changes=0
;Set to 1 to use the hi-res dialog border/background at resolutions above 640x480. Requires art\intrface\HR_ALLTLK.FRM (for example from f2_res.dat)
dialog_border=1
;Set to one to hide areas outside map bounds when using higher than 640x480 resolution, and to zero to disable
enable_high_resolution_stencil=1
;Set to 1 to extend the action points bar to show up to 16 AP instead of 10 (requires iface_apbar_e.frm)
@@ -110,8 +104,6 @@ iface_bar_mode=0
iface_bar_side_art=2
iface_bar_sides_ori=0
iface_bar_width=800
;Whether to load EDG files (HRP format) when loading maps. If loaded, they override default edge clipping and scroll blocking behavior.
edg_support=1
ignore_map_edges=0
;Set to 1 to display numbered dialogue options
numbers_in_dialogue=0
@@ -128,7 +120,3 @@ inventory_columns=2
auto_open_doors=0
; Overrides distance at which walk animation is used when using an object.
use_walk_distance=5
; Allow opening party member inventory from the long-press world menu.
party_trade_from_menu=1
; Allow switching to companions' inventories in loot screens (and barter, in the future)
party_loot_and_barter=1
Binary file not shown.
+6 -3
View File
@@ -4,7 +4,7 @@
#define ARRAY_MAX_STRING (1024)
#define ARRAY_MAX_STRING (255)
#define ARRAY_MAX_SIZE (100000)
procedure array_test_suite begin
@@ -82,8 +82,8 @@ procedure array_test_suite begin
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+1; i+=100) begin
s += "Verbosity.Verbosity.Verbosity.Verbosity.Verbosity.Verbosity.Verbosity.Verbosity.Verbosity.Verbosity.";
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);
@@ -141,6 +141,8 @@ procedure array_test_suite begin
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};
@@ -161,6 +163,7 @@ procedure array_test_suite begin
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("Testing nested expressions...");
arr := [["one", "two"]];
-100
View File
@@ -1,63 +1,5 @@
#include "test_utils.h"
#include "sfall.h"
#include "dik.h"
variable manual_extra_tag := 0;
variable manual_tag5_color := 2;
procedure print_custom_tag_state(variable tag, variable label) begin
display_msg(label + ": " + is_iface_tag_active(tag));
end
procedure toggle_custom_tag(variable tag, variable label) begin
if (is_iface_tag_active(tag)) then begin
hide_iface_tag(tag);
display_msg(label + " hidden");
end else begin
show_iface_tag(tag);
display_msg(label + " shown");
end
call print_custom_tag_state(tag, label);
end
procedure apply_tag5_color begin
set_iface_tag_text(5, "TAG FIVE", manual_tag5_color);
display_msg(string_format1("custom tag 5 color -> %d", manual_tag5_color));
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_B) then begin
call toggle_custom_tag(5, "custom tag 5");
end else if (key == DIK_C) then begin
manual_tag5_color := manual_tag5_color + 1;
if (manual_tag5_color > 7) then begin
manual_tag5_color := 0;
end
call apply_tag5_color;
end else if (key == DIK_N) then begin
call toggle_custom_tag(6, "custom tag 6");
end else if (key == DIK_M) then begin
if (manual_extra_tag == 0) then begin
display_msg("manual extra tag is not initialized");
return;
end
call toggle_custom_tag(manual_extra_tag, "manual extra tag");
end else if (key == DIK_V) then begin
call print_custom_tag_state(5, "custom tag 5");
call print_custom_tag_state(6, "custom tag 6");
if (manual_extra_tag != 0) then begin
call print_custom_tag_state(manual_extra_tag, "manual extra tag");
end
end
end
procedure start begin
display_msg("Testing iface_tag functions...");
@@ -87,47 +29,5 @@ procedure start begin
// RADIATED
call assertFalse("hide_iface_tag(RADIATED)", is_iface_tag_active(2));
// Default custom box from BoxBarCount.
call apply_tag5_color;
call assertFalse("custom tag 5 starts inactive", is_iface_tag_active(5));
show_iface_tag(5);
call assertTrue("show_iface_tag(custom 5)", is_iface_tag_active(5));
show_iface_tag(5);
call assertTrue("show_iface_tag(custom 5 again)", is_iface_tag_active(5));
hide_iface_tag(5);
call assertFalse("hide_iface_tag(custom 5)", is_iface_tag_active(5));
hide_iface_tag(5);
call assertFalse("hide_iface_tag(custom 5 again)", is_iface_tag_active(5));
set_iface_tag_text(6, "TAG SIX", 6);
call assertFalse("custom tag 6 starts inactive", is_iface_tag_active(6));
show_iface_tag(6);
call assertTrue("show_iface_tag(custom 6)", is_iface_tag_active(6));
show_iface_tag(5);
call assertTrue("custom tag 5 still active", is_iface_tag_active(5));
call assertTrue("custom tag 6 still active", is_iface_tag_active(6));
hide_iface_tag(5);
call assertFalse("hide_iface_tag(custom 5 with 6 active)", is_iface_tag_active(5));
call assertTrue("custom tag 6 remains active", is_iface_tag_active(6));
hide_iface_tag(6);
call assertFalse("hide_iface_tag(custom 6)", is_iface_tag_active(6));
// Dynamically added custom box.
variable extra_tag := add_iface_tag;
call assertTrue("add_iface_tag lower bound", extra_tag >= 10);
call assertTrue("add_iface_tag upper bound", extra_tag <= 126);
manual_extra_tag := extra_tag;
set_iface_tag_text(extra_tag, "EXTRA TAG", 3);
call assertFalse("added custom tag starts inactive", is_iface_tag_active(extra_tag));
show_iface_tag(extra_tag);
call assertTrue("show_iface_tag(added custom)", is_iface_tag_active(extra_tag));
hide_iface_tag(extra_tag);
call assertFalse("hide_iface_tag(added custom)", is_iface_tag_active(extra_tag));
variable next_tag := add_iface_tag;
call assertEquals("add_iface_tag increments", next_tag, extra_tag + 1);
call report_test_results("iface_tag");
display_msg("iface_tag manual test ready: B toggle tag 5, C cycle tag 5 color, N toggle tag 6, M toggle extra tag, V print states");
register_hook_proc(HOOK_KEYPRESS, keypress_handler);
end
-78
View File
@@ -1,78 +0,0 @@
#include "sfall.h"
#include "dik.h"
variable loop_sound_id := 0;
variable quiet_loop_sound_id := 0;
variable music_sound_id := 0;
procedure stop_if_active(variable sound_id, variable label) begin
if (sound_id != 0) then begin
stop_sfall_sound(sound_id);
display_msg(label + " stopped");
end else begin
display_msg(label + " is not active");
end
end
procedure keypress_handler begin
variable pressed := get_sfall_arg_at(0);
variable key := get_sfall_arg_at(1);
variable ignored;
if (not pressed) then return;
if (key == DIK_K) then begin
display_msg("play_sfall_sound mode 0 one-shot: sound\\sfx\\pistol.ACM");
ignored := play_sfall_sound("sound\\sfx\\pistol.ACM", 0);
end else if (key == DIK_N) then begin
if (loop_sound_id != 0) then begin
display_msg(string_format1("loop already active id=%d", loop_sound_id));
return;
end
loop_sound_id := play_sfall_sound("sound\\music\\20CAR.ACM", 1);
display_msg(string_format1("mode 1 loop id=%d", loop_sound_id));
end else if (key == DIK_M) then begin
call stop_if_active(loop_sound_id, "mode 1 loop");
loop_sound_id := 0;
end else if (key == DIK_C) then begin
if (quiet_loop_sound_id != 0) then begin
display_msg(string_format1("quiet loop already active id=%d", quiet_loop_sound_id));
return;
end
quiet_loop_sound_id := play_sfall_sound("sound\\music\\20CAR.ACM", 0x30000001);
display_msg(string_format1("quiet mode 1 loop id=%d", quiet_loop_sound_id));
end else if (key == DIK_X) then begin
call stop_if_active(quiet_loop_sound_id, "quiet mode 1 loop");
quiet_loop_sound_id := 0;
end else if (key == DIK_G) then begin
if (music_sound_id != 0) then begin
display_msg(string_format1("mode 2 music replacement already active id=%d", music_sound_id));
return;
end
music_sound_id := play_sfall_sound("sound\\music\\20CAR.ACM", 2);
display_msg(string_format1("mode 2 music replacement id=%d", music_sound_id));
end else if (key == DIK_H) then begin
call stop_if_active(music_sound_id, "mode 2 music replacement");
music_sound_id := 0;
end else if (key == DIK_V) then begin
display_msg("play_sfall_sound mode 3 speech-volume one-shot: sound\\sfx\\pistol.ACM");
ignored := play_sfall_sound("sound\\sfx\\pistol.ACM", 3);
end else if (key == DIK_B) then begin
display_msg("play_sfall_sound mode 0 one-shot wav: smw_1-up.wav"); // needs a wav file in the game dir
ignored := play_sfall_sound("smw_1-up.wav", 0);
end
end
procedure start begin
if (not game_loaded) then return;
display_msg("sfall_sound manual test ready");
display_msg("One-shots use master.dat SFX and loose-file wav; loops/replacement use music");
display_msg("K one-shot ACM mode0, B one-shot WAV mode0, N start loop mode1, M stop loop");
display_msg("C start quiet loop mode1, X stop quiet loop");
display_msg("G start mode2 music replacement, H stop mode2 replacement, V mode3 one-shot");
register_hook_proc(HOOK_KEYPRESS, keypress_handler);
end
-136
View File
@@ -1,136 +0,0 @@
#include "define_lite.h"
#include "sfall.h"
#include "dik.h"
#include "define_extra.h"
#include "lib.inven.h"
#include "test_utils.h"
#define TEST_ITEM_PID 40
#define PARTY_UNIQUE_ID_LOWER_BOUND 18000
#define UNIQUE_ID_LOWER_BOUND 0x10000000
procedure find_random_inventory_item_for_unique_id begin
variable items;
variable length;
variable start;
variable scan;
variable index;
variable item;
variable item_id;
items := inven_as_array(dude_obj);
length := len_array(items);
if (length <= 0) then return 0;
start := random(0, length - 1);
scan := 0;
while (scan < length) do begin
index := start + scan;
if (index >= length) then index -= length;
item := items[index];
item_id := get_object_data(item, OBJ_DATA_ID);
if (item_id < PARTY_UNIQUE_ID_LOWER_BOUND) then begin
return item;
end
scan += 1;
end
return items[start];
end
procedure assign_unique_id_to_random_inventory_item begin
variable item;
variable old_id;
variable new_id;
item := find_random_inventory_item_for_unique_id;
if (item == 0) then begin
display_msg("unique_id manual test: inventory is empty");
return;
end
old_id := get_object_data(item, OBJ_DATA_ID);
new_id := set_unique_id(item);
if (new_id == old_id) then begin
display_msg(string_format3("unique_id manual U: %s pid=%d id unchanged=%d", obj_name(item), obj_pid(item), new_id));
end else begin
display_msg(string_format4("unique_id manual U: %s pid=%d %d->%d", obj_name(item), obj_pid(item), old_id, new_id));
end
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_U) then begin
call assign_unique_id_to_random_inventory_item();
end
end
procedure start begin
variable item_a;
variable item_b;
variable item_c;
variable baseline_total;
variable unique_id_a;
variable unique_id_a_again;
variable unique_id_c;
variable engine_id_a;
variable regular_count;
variable total;
if (not game_loaded) then return;
display_msg("Testing set_unique_id...");
call assertEquals("metarule exists", metarule_exist("set_unique_id"), 1);
baseline_total := obj_is_carrying_obj_pid(dude_obj, TEST_ITEM_PID);
item_a := create_object_sid(TEST_ITEM_PID, 0, 0, -1);
item_b := create_object_sid(TEST_ITEM_PID, 0, 0, -1);
item_c := create_object_sid(TEST_ITEM_PID, 0, 0, -1);
unique_id_a := set_unique_id(item_a);
call assertTrue("unique id lower bound", unique_id_a >= UNIQUE_ID_LOWER_BOUND);
call assertEquals("unique id stored on object", get_object_data(item_a, OBJ_DATA_ID), unique_id_a);
unique_id_a_again := set_unique_id(item_a);
call assertEquals("existing unique id reused", unique_id_a_again, unique_id_a);
add_obj_to_inven(dude_obj, item_a);
add_obj_to_inven(dude_obj, item_b);
call assertEquals("unique item stays separate", obj_is_carrying_obj(dude_obj, item_a), 1);
regular_count := obj_is_carrying_obj(dude_obj, item_b);
call assertTrue("regular item still exists after unique item add", regular_count >= 1);
total := obj_is_carrying_obj_pid(dude_obj, TEST_ITEM_PID);
call assertEquals("unique and regular items add two total items", total, baseline_total + 2);
unique_id_c := set_unique_id(item_c);
call assertNotEquals("second unique item gets new id", unique_id_c, unique_id_a);
add_obj_to_inven(dude_obj, item_c);
call assertEquals("second unique item stays separate", obj_is_carrying_obj(dude_obj, item_c), 1);
total := obj_is_carrying_obj_pid(dude_obj, TEST_ITEM_PID);
call assertEquals("pid total counts all three added items", total, baseline_total + 3);
engine_id_a := unset_unique_id(item_a);
call assertTrue("unset returns engine id", engine_id_a < UNIQUE_ID_LOWER_BOUND);
call assertNotEquals("unset replaces unique id", engine_id_a, unique_id_a);
call assertEquals("engine id stored on object", get_object_data(item_a, OBJ_DATA_ID), engine_id_a);
call assertEquals("remove unique item a", rm_mult_objs_from_inven(dude_obj, item_a, 1), 1);
call assertEquals("remove regular item b", rm_mult_objs_from_inven(dude_obj, item_b, 1), 1);
call assertEquals("remove unique item c", rm_mult_objs_from_inven(dude_obj, item_c, 1), 1);
destroy_object(item_a);
destroy_object(item_b);
destroy_object(item_c);
call report_test_results("unique_id");
display_msg("unique_id manual test ready: press U to assign/print a unique id for a random inventory item");
register_hook_proc(HOOK_KEYPRESS, keypress_handler);
end
-93
View File
@@ -1,93 +0,0 @@
#include "sfall.h"
#include "dik.h"
#include "../test_utils.h"
#define AREA_ARROYO (0)
#define AREA_RND_CITY (28)
#define MAP_RND_CITY1 (68)
variable mode := 0;
variable pending_event := -1;
variable expected_map := -1;
variable arroyo_known_before := 0;
variable car_town_before := 0;
procedure mode_name(variable value) begin
if (value == 0) then return "observe";
if (value == 1) then return "reroute_worldmap_enter";
if (value == 2) then return "cancel_encounters";
return "unknown";
end
procedure log_mode begin
display_msg(string_format2("encounter mode=%d (%s)", mode, mode_name(mode)));
end
procedure begin_pending_assertions(variable event_type) begin
pending_event := event_type;
expected_map := MAP_RND_CITY1;
arroyo_known_before := town_known(AREA_ARROYO);
car_town_before := car_current_town;
end
procedure encounter_handler begin
variable
event_type := get_sfall_arg_at(0),
map_id := get_sfall_arg_at(1),
is_special := get_sfall_arg_at(2),
table_num := get_sfall_arg_at(3),
entry_num := get_sfall_arg_at(4);
display_msg(string_format5("encounter event=%d map=%d special=%d table=%d entry=%d", event_type, map_id, is_special, table_num, entry_num));
if (mode == 1 and event_type == 1) then begin
call begin_pending_assertions(event_type);
display_msg(string_format1("encounter rerouting worldmap entry to map %d", expected_map));
set_sfall_return(expected_map);
end else if (mode == 2 and event_type == 0) then begin
display_msg("canceling encounter");
set_sfall_return(-1);
end
end
procedure keypress_handler begin
variable
pressed := get_sfall_arg_at(0),
key := get_sfall_arg_at(1);
if (not pressed) then return;
if (key != DIK_X) then return;
mode := mode + 1;
if (mode > 2) then mode := 0;
call log_mode;
end
procedure start begin
if (not game_loaded) then return;
display_msg("encounter manual test ready:");
display_msg("press X to cycle mode: observe, reroute worldmap enter, cancel encounters");
display_msg("mode 1: enter any location from the world map");
display_msg("mode 2: cancel encounters");
call log_mode;
register_hook_proc(HOOK_KEYPRESS, keypress_handler);
register_hook_proc(HOOK_ENCOUNTER, encounter_handler);
end
procedure map_enter_p_proc begin
if (expected_map == -1) then return;
call assertEquals("encounter reroute loaded expected map", cur_map_index, expected_map);
call assertEquals("encounter reroute load area matches rerouted map", map_get_load_area, AREA_RND_CITY);
call assertEquals("encounter reroute does not mutate Arroyo known state", town_known(AREA_ARROYO), arroyo_known_before);
call assertEquals("encounter reroute preserves car town", car_current_town, car_town_before);
if (pending_event == 1) then
call report_test_results("hook_encounter_worldmap_enter");
pending_event := -1;
expected_map := -1;
end
-153
View File
@@ -1,153 +0,0 @@
#include "sfall.h"
#include "dik.h"
#include "define_lite.h"
#include "../test_utils.h"
variable seen_adjustfid := 0;
variable seen_invenwield := 0;
variable seen_invenwield_remove := 0;
variable seen_canuseweapon_player := 0;
variable seen_canuseweapon_ai := 0;
variable temp_container := 0;
variable invenwield_override_enabled := false;
variable canuseweapon_override := -1;
procedure invenwield_mode_name begin
if (invenwield_override_enabled) then return "suppress";
return "engine";
end
procedure canuseweapon_mode_name(variable value) begin
if (value == -1) then return "engine";
if (value == 1) then return "on";
if (value == 0) then return "off";
return "unknown";
end
procedure cycle_canuseweapon_override begin
if (canuseweapon_override == -1) then canuseweapon_override := 1;
else if (canuseweapon_override == 1) then canuseweapon_override := 0;
else canuseweapon_override := -1;
display_msg(string_format1("hook_item_compat canuseweapon mode=%s", canuseweapon_mode_name(canuseweapon_override)));
end
procedure adjustfid_handler begin
variable args := get_sfall_args;
call assertEquals("adjustfid arg count", len_array(args), 2);
call assertEquals("adjustfid arg0 type", typeof(args[0]), VALTYPE_INT);
call assertEquals("adjustfid arg1 type", typeof(args[1]), VALTYPE_INT);
seen_adjustfid := seen_adjustfid + 1;
display_msg(string_format2("adjustfid vanilla=%d modified=%d", args[0], args[1]));
end
procedure invenwield_handler begin
variable
args := get_sfall_args,
item := args[1],
slot := args[2],
is_wield := args[3],
is_remove := args[4];
call assertEquals("invenwield arg count", len_array(args), 5);
call assertTrue("invenwield slot range", slot >= 0 and slot <= 2);
call assertTrue("invenwield is_wield flag", is_wield == 0 or is_wield == 1);
call assertTrue("invenwield is_remove flag", is_remove == 0 or is_remove == 1);
seen_invenwield := seen_invenwield + 1;
if (is_remove) then begin
seen_invenwield_remove := seen_invenwield_remove + 1;
end
display_msg(string_format4("invenwield item=%s slot=%d wield=%d remove=%d", obj_name(item), slot, is_wield, is_remove));
if (invenwield_override_enabled) then begin
set_sfall_return(0);
end
end
procedure canuseweapon_handler begin
variable
args := get_sfall_args,
hit_mode := args[2],
result := args[3],
weapon := args[1];
call assertEquals("canuseweapon arg count", len_array(args), 4);
call assertTrue("canuseweapon result flag", result == 0 or result == 1);
if (hit_mode == -1) then begin
seen_canuseweapon_player := seen_canuseweapon_player + 1;
end else begin
seen_canuseweapon_ai := seen_canuseweapon_ai + 1;
end
display_msg(string_format3("canuseweapon item=%s hitmode=%d result=%d", obj_name(weapon), hit_mode, result));
if (canuseweapon_override != -1) then begin
set_sfall_return(canuseweapon_override);
end
end
procedure keypress_handler begin
variable
pressed := get_sfall_arg_at(0),
key := get_sfall_arg_at(1);
if (not pressed) then return;
if (key == DIK_Z) then begin
display_msg("hook_item_compat: unwield armor");
unwield_slot(dude_obj, INVEN_TYPE_WORN);
end else if (key == DIK_X) then begin
display_msg("hook_item_compat: unwield right hand");
unwield_slot(dude_obj, INVEN_TYPE_RIGHT_HAND);
end else if (key == DIK_C) then begin
display_msg("hook_item_compat: unwield left hand");
unwield_slot(dude_obj, INVEN_TYPE_LEFT_HAND);
end else if (key == DIK_V) then begin
display_msg("hook_item_compat: toggle active hand");
toggle_active_hand;
end else if (key == DIK_N) then begin
display_msg("hook_item_compat: move inventory to temp container");
if (temp_container == 0) then begin
temp_container := create_object_sid(467, 0, 0, -1);
end
move_obj_inven_to_obj(dude_obj, temp_container);
end else if (key == DIK_M) then begin
invenwield_override_enabled := not invenwield_override_enabled;
display_msg(string_format1("hook_item_compat invenwield mode=%s", invenwield_mode_name));
end else if (key == DIK_G) then begin
call cycle_canuseweapon_override;
end else if (key == DIK_B) then begin
display_msg(string_format7("hook_item_compat summary inven_mode=%s canuse_mode=%s adjust=%d inven=%d remove=%d player=%d ai=%d",
invenwield_mode_name,
canuseweapon_mode_name(canuseweapon_override),
seen_adjustfid,
seen_invenwield,
seen_invenwield_remove,
seen_canuseweapon_player,
seen_canuseweapon_ai));
call assertTrue("adjustfid observed", seen_adjustfid > 0);
call assertTrue("invenwield observed", seen_invenwield > 0);
call assertTrue("player canuseweapon observed", seen_canuseweapon_player > 0);
call report_test_results("hook_item_compat");
end
end
procedure start begin
if (not game_loaded) then return;
display_msg("hook_item_compat ready:");
display_msg("open inventory/barter to trigger adjustfid");
display_msg("press Z armor, X right, C left, V swap hand");
display_msg("press N disposable-save inventory move, M invenwield mode");
display_msg("press G canuseweapon mode (engine/on/off), B report");
register_hook_proc(HOOK_KEYPRESS, keypress_handler);
register_hook_proc(HOOK_INVENWIELD, invenwield_handler);
register_hook_proc(HOOK_ADJUSTFID, adjustfid_handler);
register_hook_proc(HOOK_CANUSEWEAPON, canuseweapon_handler);
end
-83
View File
@@ -1,83 +0,0 @@
#include "sfall.h"
#include "dik.h"
#include "lib.arrays.h"
variable steal_mode := 0;
procedure steal_mode_name(variable mode) begin
if (mode == 1) then return "force_success";
if (mode == 2) then return "caught_fail";
if (mode == 3) then return "silent_fail";
if (mode == 4) then return "xp_override";
return "vanilla";
end
procedure steal_handler begin
variable
args := get_sfall_args,
thief := args[0],
target := args[1],
item := args[2],
is_planting := args[3],
quantity := args[4],
thief_name := "<null>",
target_name := "<null>",
item_name := "<null>";
if (thief) then thief_name := obj_name(thief);
if (target) then target_name := obj_name(target);
if (item) then item_name := obj_name(item);
display_msg(string_format6("steal mode=%s thief=%s target=%s item=%s planting=%d qty=%d",
steal_mode_name(steal_mode),
thief_name,
target_name,
item_name,
is_planting,
quantity));
display_msg(string_format1("steal args=%s", debug_array_str(args)));
if (thief != dude_obj) then return;
if (steal_mode == 1) then begin
display_msg("steal forcing success");
display_msg(sprintf(mstr_skill(571 + is_planting * 2), item_name));
set_sfall_return(1);
end else if (steal_mode == 2) then begin
display_msg("steal forcing caught failure");
display_msg(sprintf(mstr_skill(570 + is_planting * 2), item_name));
set_sfall_return(0);
end else if (steal_mode == 3) then begin
display_msg("steal forcing silent failure");
set_sfall_return(2);
end else if (steal_mode == 4) then begin
display_msg("steal forcing success with xp override 77");
display_msg(sprintf(mstr_skill(571 + is_planting * 2), item_name));
set_sfall_return(1);
set_sfall_return(77);
end
end
procedure keypress_handler begin
variable
pressed := get_sfall_arg_at(0),
key := get_sfall_arg_at(1);
if (not pressed) then return;
if (key != DIK_X) then return;
steal_mode += 1;
if (steal_mode > 4) then steal_mode := 0;
display_msg(string_format1("steal mode -> %s", steal_mode_name(steal_mode)));
end
procedure start begin
if (not game_loaded) then return;
display_msg("steal manual test ready: press X to cycle vanilla / force_success / caught_fail / silent_fail / xp_override");
display_msg("open a steal screen and move an item in either direction; mode 4 should award 77 XP for a successful action");
register_hook_proc(HOOK_KEYPRESS, keypress_handler);
register_hook_proc(HOOK_STEAL, steal_handler);
end
-145
View File
@@ -1,145 +0,0 @@
#include "sfall.h"
#include "dik.h"
#include "lib.arrays.h"
#include "../test_utils.h"
variable useskill_mode := 0;
variable useskillon_calls := 0;
variable useskill_calls := 0;
variable last_useskillon_skill := -1;
variable last_useskill_skill := -1;
procedure skill_name(variable skill) begin
if (skill == SKILL_FIRST_AID) then return "first_aid";
if (skill == SKILL_DOCTOR) then return "doctor";
if (skill == SKILL_LOCKPICK) then return "lockpick";
if (skill == SKILL_STEAL) then return "steal";
if (skill == SKILL_TRAPS) then return "traps";
if (skill == SKILL_SCIENCE) then return "science";
if (skill == SKILL_REPAIR) then return "repair";
if (skill == SKILL_SNEAK) then return "sneak";
return string_format1("skill_%d", skill);
end
procedure obj_name_safe(variable obj) begin
if (obj == 0) then return "<null>";
return obj_name(obj);
end
procedure useskill_mode_name(variable mode) begin
if (mode == 1) then return "useskillon_cancel";
if (mode == 2) then return "useskillon_user_override";
if (mode == 3) then return "useskillon_allow_combat";
if (mode == 4) then return "useskill_override";
if (mode == 5) then return "useskill_cancel_steal";
return "vanilla";
end
procedure print_mode begin
display_msg(string_format1("useskill mode -> %s", useskill_mode_name(useskill_mode)));
end
procedure useskillon_handler begin
variable
args := get_sfall_args,
user := args[0],
target := args[1],
skill := args[2];
useskillon_calls++;
last_useskillon_skill := skill;
display_msg(string_format("useskillon mode=%s user=%s target=%s skill=%s",
useskill_mode_name(useskill_mode),
obj_name_safe(user),
obj_name_safe(target),
skill_name(skill)));
display_msg(string_format1("useskillon args=%s", debug_array_str(args)));
call assertEquals("useskillon arg count", len_array(args), 3);
call assertTrue("useskillon user is set", user != 0);
call assertTrue("useskillon target is set", target != 0);
if (useskill_mode == 1) then begin
display_msg("useskillon cancelling skill action");
set_sfall_return(-1);
end else if (useskill_mode == 2) then begin
if (skill == SKILL_STEAL) then begin
display_msg("useskillon returning dude_obj for Steal; engine should ignore this return value");
end else begin
display_msg("useskillon returning dude_obj as user override");
end
set_sfall_return(dude_obj);
end else if (useskill_mode == 3) then begin
display_msg("useskillon allowing combat use");
set_sfall_return(0);
set_sfall_return(1);
end
end
procedure useskill_handler begin
variable
args := get_sfall_args,
user := args[0],
target := args[1],
skill := args[2],
skill_bonus := args[3];
useskill_calls++;
last_useskill_skill := skill;
display_msg(string_format("useskill mode=%s user=%s target=%s skill=%s bonus=%d",
useskill_mode_name(useskill_mode),
obj_name_safe(user),
obj_name_safe(target),
skill_name(skill),
skill_bonus));
display_msg(string_format1("useskill args=%s", debug_array_str(args)));
call assertEquals("useskill arg count", len_array(args), 4);
call assertTrue("useskill user is set", user != 0);
call assertTrue("useskill target is set", target != 0);
if (useskill_mode == 4) then begin
display_msg("useskill overriding hard-coded handler with result 1");
set_sfall_return(1);
end else if (useskill_mode == 5) then begin
if (skill == SKILL_STEAL) then begin
display_msg("useskill canceling steal by overriding hard-coded handler with result 0");
set_sfall_return(0);
end
end
end
procedure keypress_handler begin
variable
pressed := get_sfall_arg_at(0),
key := get_sfall_arg_at(1);
if (not pressed) then return;
if (key == DIK_U) then begin
useskill_mode += 1;
if (useskill_mode > 5) then useskill_mode := 0;
call print_mode;
end else if (key == DIK_Y) then begin
display_msg(string_format("useskill stats: on=%d skill=%s, handler=%d skill=%s",
useskillon_calls,
skill_name(last_useskillon_skill),
useskill_calls,
skill_name(last_useskill_skill)));
call report_test_results("hook_useskill");
end
end
procedure start begin
if (not game_loaded) then return;
display_msg("useskill manual test ready");
display_msg("press U to cycle modes: vanilla / useskillon_cancel / useskillon_user_override / useskillon_allow_combat / useskill_override / useskill_cancel_steal");
display_msg("use a Skilldex skill or a medical kit on a valid target; press Y to report assertions");
register_hook_proc(HOOK_KEYPRESS, keypress_handler);
register_hook_proc(HOOK_USESKILLON, useskillon_handler);
register_hook_proc(HOOK_USESKILL, useskill_handler);
end
+27 -30
View File
@@ -46,13 +46,13 @@ typedef enum ScienceRepairTargetType {
SCIENCE_REPAIR_TARGET_TYPE_ANYONE,
} ScienceRepairTargetType;
// 0x5106D0 action_in_explode
// 0x5106D0
static bool _action_in_explode = false;
// 0x5106D4 rotation
// 0x5106D4
int rotation;
// 0x5106E0 death_2
// 0x5106E0
static const int gNormalDeathAnimations[DAMAGE_TYPE_COUNT] = {
ANIM_DANCING_AUTOFIRE,
ANIM_SLICED_IN_HALF,
@@ -63,7 +63,7 @@ static const int gNormalDeathAnimations[DAMAGE_TYPE_COUNT] = {
ANIM_BIG_HOLE,
};
// 0x5106FC death_3
// 0x5106FC
static const int gMaximumBloodDeathAnimations[DAMAGE_TYPE_COUNT] = {
ANIM_CHUNKS_OF_FLESH,
ANIM_SLICED_IN_HALF,
@@ -519,7 +519,7 @@ int _show_death(Object* obj, int anim)
// Animates damage to extras in a given attack (secondary targets).
//
// 0x410FEC show_damage_extras
// 0x410FEC _show_damage_extras
int showDamageToExtras(Attack* attack)
{
for (int index = 0; index < attack->extrasLength; index++) {
@@ -1262,18 +1262,20 @@ int actionPickUp(Object* critter, Object* item)
return reg_anim_end();
}
// This is primarily used to loot critters, namely corpses. I don't believe it can
// be called with a living creature, but am not 100% certain.
// TODO: Looks like the name is a little misleading, container can only be a
// critter, which is enforced by this function as well as at the call sites.
// Used to loot corpses, so probably should be something like actionLootCorpse.
// Check if it can be called with a living critter.
//
// 0x4123E8 was _action_loot_container
int actionLootCritter(Object* critter, Object* target)
// 0x4123E8
int _action_loot_container(Object* critter, Object* container)
{
if (FID_TYPE(target->fid) != OBJ_TYPE_CRITTER) {
if (FID_TYPE(container->fid) != OBJ_TYPE_CRITTER) {
return -1;
}
// SFALL: Fix for trying to loot corpses with the "NoSteal" flag.
if (critterFlagCheck(target->pid, CRITTER_NO_STEAL)) {
if (critterFlagCheck(container->pid, CRITTER_NO_STEAL)) {
return -1;
}
@@ -1286,20 +1288,20 @@ int actionLootCritter(Object* critter, Object* target)
if (isInCombat()) {
reg_anim_begin(ANIMATION_REQUEST_RESERVED);
animationRegisterMoveToObject(critter, target, critter->data.critter.combat.ap, 0);
animationRegisterMoveToObject(critter, container, critter->data.critter.combat.ap, 0);
} else {
reg_anim_begin(critter == gDude ? ANIMATION_REQUEST_RESERVED : ANIMATION_REQUEST_UNRESERVED);
if (objectWithinWalkDistance(critter, target)) {
animationRegisterMoveToObject(critter, target, -1, 0);
if (objectWithinWalkDistance(critter, container)) {
animationRegisterMoveToObject(critter, container, -1, 0);
} else {
animationRegisterRunToObject(critter, target, -1, 0);
animationRegisterRunToObject(critter, container, -1, 0);
}
}
animationRegisterCallbackForced(critter, target, (AnimationCallback*)_is_next_to, -1);
animationRegisterCallback(critter, target, (AnimationCallback*)checkSceneryUseActionPointCost, -1);
animationRegisterCallback(critter, target, (AnimationCallback*)scriptsRequestLooting, -1);
animationRegisterCallbackForced(critter, container, (AnimationCallback*)_is_next_to, -1);
animationRegisterCallback(critter, container, (AnimationCallback*)checkSceneryUseActionPointCost, -1);
animationRegisterCallback(critter, container, (AnimationCallback*)scriptsRequestLooting, -1);
return reg_anim_end();
}
@@ -1336,15 +1338,10 @@ static int _action_use_skill_in_combat_error(Object* critter)
// 0x41255C
int actionUseSkill(Object* user, Object* target, int skill)
{
UseSkillOnHookResult hookResult = scriptHooks_UseSkillOn(&user, target, skill);
if (!hookResult.shouldContinue) {
return -1;
}
switch (skill) {
case SKILL_FIRST_AID:
case SKILL_DOCTOR:
if (isInCombat() && !hookResult.allowInCombat) {
if (isInCombat()) {
// NOTE: Uninline.
return _action_use_skill_in_combat_error(user);
}
@@ -1354,7 +1351,7 @@ int actionUseSkill(Object* user, Object* target, int skill)
}
break;
case SKILL_LOCKPICK:
if (isInCombat() && !hookResult.allowInCombat) {
if (isInCombat()) {
// NOTE: Uninline.
return _action_use_skill_in_combat_error(user);
}
@@ -1365,7 +1362,7 @@ int actionUseSkill(Object* user, Object* target, int skill)
break;
case SKILL_STEAL:
if (isInCombat() && !hookResult.allowInCombat) {
if (isInCombat()) {
// NOTE: Uninline.
return _action_use_skill_in_combat_error(user);
}
@@ -1380,7 +1377,7 @@ int actionUseSkill(Object* user, Object* target, int skill)
break;
case SKILL_TRAPS:
if (isInCombat() && !hookResult.allowInCombat) {
if (isInCombat()) {
// NOTE: Uninline.
return _action_use_skill_in_combat_error(user);
}
@@ -1392,7 +1389,7 @@ int actionUseSkill(Object* user, Object* target, int skill)
break;
case SKILL_SCIENCE:
case SKILL_REPAIR:
if (isInCombat() && !hookResult.allowInCombat) {
if (isInCombat()) {
// NOTE: Uninline.
return _action_use_skill_in_combat_error(user);
}
@@ -1433,9 +1430,9 @@ int actionUseSkill(Object* user, Object* target, int skill)
// Performer is either dude, or party member who's best at the specified
// skill in entire party, and this skill is his/her own best.
Object* performer = hookResult.userOverridden ? user : gDude;
Object* performer = gDude;
if (user == gDude && !hookResult.userOverridden) {
if (user == gDude) {
Object* partyMember = partyMemberGetBestInSkill(skill);
if (partyMember == gDude) {
+1 -1
View File
@@ -12,7 +12,7 @@ int _action_attack(Attack* attack);
int _action_use_an_item_on_object(Object* user, Object* targetObj, Object* item);
int _action_use_an_object(Object* user, Object* targetObj);
int actionPickUp(Object* critter, Object* item);
int actionLootCritter(Object* critter, Object* target);
int _action_loot_container(Object* critter, Object* container);
int _action_skill_use(int skill);
int actionUseSkill(Object* user, Object* target, int skill);
bool _is_hit_from_front(const Object* attacker, const Object* defender);
+11 -11
View File
@@ -309,39 +309,39 @@ static unsigned int animationComputeTicksPerFrame(Object* object, int fid);
static void reportOverloaded(Object* critter);
// 0x510718 curr_sad
// 0x510718
static int gAnimationCurrentSad = 0;
// 0x51071C curr_anim_set
// 0x51071C
static int gAnimationSequenceCurrentIndex = -1;
// 0x510720 anim_in_init
// 0x510720
static bool gAnimationInInit = false;
// 0x510724 anim_in_anim_stop
// 0x510724
static bool gAnimationInStop = false;
// 0x510728 anim_in_bk
// 0x510728
static bool _anim_in_bk = false;
// 0x530014 sad
// 0x530014
static AnimationSad gAnimationSads[ANIMATION_SAD_LIST_CAPACITY];
#define PATH_NODE_CAPACITY 10000
// 0x542FD4 dad
// 0x542FD4
static PathNode gClosedPathNodeList[PATH_NODE_CAPACITY];
// 0x54CC14 anim_set
// 0x54CC14
static AnimationSequence gAnimationSequences[32];
// 0x561814 seen_tile
// 0x561814
static unsigned char gPathfinderProcessedTiles[5000];
// 0x562B9C child_path
// 0x562B9C
static PathNode gOpenPathNodeList[PATH_NODE_CAPACITY];
// 0x56C7DC curr_anim_counter
// 0x56C7DC
static int gAnimationDescriptionCurrentIndex;
// anim_init
+17 -59
View File
@@ -44,19 +44,19 @@ static int artReadHeader(Art* art, File* stream);
static int artGetDataSize(const Art* art);
static int paddingForSize(int size);
// 0x5002D8 str2
// 0x5002D8
static char gDefaultJumpsuitMaleFileName[] = "hmjmps";
// 0x05002E0 aHfjmps
// 0x05002E0
static char gDefaultJumpsuitFemaleFileName[] = "hfjmps";
// 0x5002E8 aHmwarr
// 0x5002E8
static char gDefaultTribalMaleFileName[] = "hmwarr";
// 0x5002F0 aHfprim
// 0x5002F0
static char gDefaultTribalFemaleFileName[] = "hfprim";
// 0x510738 art
// 0x510738
static ArtListDescription gArtListDescriptions[OBJ_TYPE_COUNT] = {
{ 0, "items", nullptr, nullptr, 0 },
{ 0, "critters", nullptr, nullptr, 0 },
@@ -74,18 +74,18 @@ static ArtListDescription gArtListDescriptions[OBJ_TYPE_COUNT] = {
// This flag denotes that localized arts should be looked up first. Used
// together with [gArtLanguage].
//
// 0x510898 darn_foreigners
// 0x510898
static bool gArtLanguageInitialized = false;
// 0x51089C head1
// 0x51089C
static const char* _head1 = "gggnnnbbbgnb";
// 0x5108A0 head2
// 0x5108A0
static const char* _head2 = "vfngfbnfvppp";
// Current native look base fid.
//
// 0x5108A4 art_vault_guy_num
// 0x5108A4
int _art_vault_guy_num = 0;
// Base fids for unarmored dude.
@@ -99,37 +99,37 @@ int _art_vault_guy_num = 0;
// been accessed differently in 0x49F984, which clearly uses look type as an
// index, not gender.
//
// 0x5108A8 art_vault_person_nums
// 0x5108A8
int _art_vault_person_nums[DUDE_NATIVE_LOOK_COUNT][GENDER_COUNT];
// Index of "grid001.frm" in tiles.lst.
//
// 0x5108B8 art_mapper_blank_tile
// 0x5108B8
static int _art_mapper_blank_tile = 1;
// Non-english language name.
//
// This value is used as a directory name to display localized arts.
//
// 0x56C970 darn_foreign_sub_path
// 0x56C970
static char gArtLanguage[32];
// 0x56C990 art_cache
// 0x56C990
Cache gArtCache;
// 0x56C9E4 art_name
// 0x56C9E4
static char _art_name[COMPAT_MAX_PATH];
// head_info
// 0x56CAE8 head_info
// 0x56CAE8
static HeadDescription* gHeadDescriptions;
// anon_alias
// 0x56CAEC anon_alias
// 0x56CAEC
static int* _anon_alias;
// artCritterFidShouldRunData
// 0x56CAF0 artCritterFidShouldRunData
// 0x56CAF0
static int* gArtCritterFidShoudRunData;
static std::unordered_map<std::string, std::shared_ptr<NamedCacheEntry>> gNamedArtCache;
@@ -355,14 +355,6 @@ int artIsObjectTypeHidden(int objectType)
return objectType >= OBJ_TYPE_ITEM && objectType < OBJ_TYPE_COUNT ? gArtListDescriptions[objectType].flags & 1 : 0;
}
// 0x409DF0
void artToggleObjectTypeHidden(int objectType)
{
if (objectType >= 0 && objectType < OBJ_TYPE_COUNT) {
gArtListDescriptions[objectType].flags ^= 1;
}
}
// 0x418F7C
int artGetFidgetCount(int headFid)
{
@@ -452,40 +444,6 @@ int art_list_str(int fid, char* name)
return -1;
}
int artListIndex(int objectType, const char* name)
{
if (objectType < 0 || objectType >= OBJ_TYPE_COUNT) return -1;
if (gArtListDescriptions[objectType].fileNames == nullptr) return -1;
char upperName[13] = { 0 };
strncpy(upperName, name, 12);
upperName[12] = '\0';
compat_strupr(upperName);
int length = gArtListDescriptions[objectType].fileNamesLength;
const char* fileNames = gArtListDescriptions[objectType].fileNames;
for (int index = 0; index < length; index++) {
const char* entry = fileNames + index * 13;
char upperEntry[13];
strncpy(upperEntry, entry, 12);
upperEntry[12] = '\0';
compat_strupr(upperEntry);
char* p = upperEntry;
while (*p && ((*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == '_'))
p++;
*p = '\0';
if (strcmp(upperEntry, upperName) == 0) {
return index;
}
}
return -1;
}
// 0x419160
Art* artLock(int fid, CacheEntry** handlePtr)
{
-2
View File
@@ -122,7 +122,6 @@ void artReset();
void artExit();
char* artGetObjectTypeName(int objectType);
int artIsObjectTypeHidden(int objectType);
void artToggleObjectTypeHidden(int objectType);
int artGetFidgetCount(int headFid);
void artRender(int fid, unsigned char* dest, int width, int height, int pitch);
int art_list_str(int fid, char* name);
@@ -151,7 +150,6 @@ int _art_alias_num(int index);
int artCritterFidShouldRun(int fid);
int artAliasFid(int fid);
int buildFid(int objectType, int frmId, int animType, int weaponCode, int rotation);
int artListIndex(int objectType, const char* name);
Art* artLoad(const char* path);
int artRead(const char* path, unsigned char* data);
int artWrite(const char* path, unsigned char* data);

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