mirror of
https://github.com/fallout2-ce/fallout2-ce.git
synced 2026-07-27 16:47:11 -07:00
Compare commits
79
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07939225c6 | ||
|
|
b10526330c | ||
|
|
4c1cad7122 | ||
|
|
b76ff8257e | ||
|
|
6edbd70d60 | ||
|
|
15917dccb3 | ||
|
|
33aae49066 | ||
|
|
bfd41bb40c | ||
|
|
0ccaef5ef0 | ||
|
|
26d7b632fc | ||
|
|
c6818f0849 | ||
|
|
84cac43da1 | ||
|
|
261b54c603 | ||
|
|
46b89abbd8 | ||
|
|
1ee64988bc | ||
|
|
c78ba885d7 | ||
|
|
6835d10590 | ||
|
|
20ad8d8778 | ||
|
|
8c98a15ef6 | ||
|
|
6782a21185 | ||
|
|
d12dbca951 | ||
|
|
823858f275 | ||
|
|
b93591f5d7 | ||
|
|
a91e40e3cc | ||
|
|
7da7d75f30 | ||
|
|
72b4680ff5 | ||
|
|
99a762b649 | ||
|
|
1afe925cbf | ||
|
|
95c07dba9f | ||
|
|
0fc042ef84 | ||
|
|
29df63dd99 | ||
|
|
6f2693edf7 | ||
|
|
e51004a3d1 | ||
|
|
9aa2ae4bbc | ||
|
|
968534314d | ||
|
|
a38f3436f8 | ||
|
|
15c22ccdfc | ||
|
|
f263075abf | ||
|
|
c95f91c2ff | ||
|
|
db86e53af2 | ||
|
|
349af8fbb8 | ||
|
|
9423a2c289 | ||
|
|
dc4753cde9 | ||
|
|
cd3adf1621 | ||
|
|
d42c8456dd | ||
|
|
c574812f1d | ||
|
|
8afe4b3061 | ||
|
|
c423d475c5 | ||
|
|
06d7f09728 | ||
|
|
81164465cf | ||
|
|
0a7834f81b | ||
|
|
f76e310f10 | ||
|
|
303e7573ca | ||
|
|
16ae69fa5a | ||
|
|
6d2d9d6ef3 | ||
|
|
7ae0452e1a | ||
|
|
f63c113d77 | ||
|
|
f8ad77061b | ||
|
|
471ebbf417 | ||
|
|
924e12b94c | ||
|
|
706785d60e | ||
|
|
1175efd379 | ||
|
|
ab2a09610d | ||
|
|
cef24823f4 | ||
|
|
63d79e4bfd | ||
|
|
e42d8021c1 | ||
|
|
8254c758fe | ||
|
|
8b2ead8a2b | ||
|
|
4f89bb7d77 | ||
|
|
0d8741e082 | ||
|
|
bc7ab1ecb2 | ||
|
|
6ce6bea309 | ||
|
|
a0a6091bd0 | ||
|
|
f2b2127709 | ||
|
|
ec6647968b | ||
|
|
f97ceff645 | ||
|
|
4247d7ac3f | ||
|
|
6027c7cf2e | ||
|
|
bd3358709f |
+174
-6
@@ -25,6 +25,9 @@ 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)
|
||||
@@ -35,15 +38,15 @@ endif()
|
||||
# Git Info
|
||||
include("cmake/gitver.cmake")
|
||||
|
||||
target_sources(${EXECUTABLE_NAME} PUBLIC
|
||||
# Shared engine sources — used by both game and mapper targets.
|
||||
# Excludes main.cc/main.h (game-only entry logic).
|
||||
set(FALLOUT_ENGINE_SOURCES
|
||||
"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"
|
||||
@@ -151,13 +154,13 @@ target_sources(${EXECUTABLE_NAME} PUBLIC
|
||||
"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"
|
||||
@@ -180,6 +183,8 @@ target_sources(${EXECUTABLE_NAME} PUBLIC
|
||||
"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"
|
||||
@@ -263,7 +268,7 @@ target_sources(${EXECUTABLE_NAME} PUBLIC
|
||||
"src/xfile.h"
|
||||
)
|
||||
|
||||
target_sources(${EXECUTABLE_NAME} PUBLIC
|
||||
set(FALLOUT_PLATFORM_SOURCES
|
||||
"src/audio_engine.cc"
|
||||
"src/audio_engine.h"
|
||||
"src/delay.cc"
|
||||
@@ -297,6 +302,8 @@ target_sources(${EXECUTABLE_NAME} PUBLIC
|
||||
"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"
|
||||
@@ -309,8 +316,43 @@ target_sources(${EXECUTABLE_NAME} PUBLIC
|
||||
"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"
|
||||
@@ -330,14 +372,33 @@ 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"
|
||||
@@ -454,6 +515,7 @@ 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"))
|
||||
@@ -480,6 +542,13 @@ 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})
|
||||
@@ -503,6 +572,14 @@ 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/*")
|
||||
@@ -527,6 +604,97 @@ 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_edge_setup.cc"
|
||||
"src/mapper/map_edge_setup.h"
|
||||
"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_utils.cc"
|
||||
"src/mapper/mp_utils.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")
|
||||
|
||||
@@ -139,6 +139,77 @@
|
||||
"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": [
|
||||
@@ -197,6 +268,26 @@
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+13
-5
@@ -76,7 +76,7 @@ For example:
|
||||
|
||||
## `ce-frm2png` CLI Tool
|
||||
|
||||
There is also a small FRM conversion tool in this repo for exporting Fallout `.frm` art to `.png`.
|
||||
There is also a small FRM conversion tool in this repo for converting Fallout art between `.frm` and `.png`.
|
||||
|
||||
From the repo root, build it with your normal CMake workflow, targeting `ce-frm2png`:
|
||||
|
||||
@@ -89,18 +89,26 @@ Basic usage:
|
||||
1. `./<BUILD_DIR>/ce-frm2png <input.frm> [output.png]`
|
||||
2. `./<BUILD_DIR>/ce-frm2png <input.frm> [output.png] --palette <path-to-color.pal>`
|
||||
3. `./<BUILD_DIR>/ce-frm2png <input.frm> [output.png] --frame <index> --direction <index>`
|
||||
4. `./<BUILD_DIR>/ce-frm2png - [output.png|-] --palette <path-to-color.pal>`
|
||||
4. `./<BUILD_DIR>/ce-frm2png <input.png> [output.frm] --palette <path-to-color.pal>`
|
||||
5. `./<BUILD_DIR>/ce-frm2png <input.png> [output.frm] --fps 10 --action-frame 0 --x-offset 0 --y-offset 0`
|
||||
6. `./<BUILD_DIR>/ce-frm2png <input.png> <output.png> --palette <path-to-color.pal>`
|
||||
7. `./<BUILD_DIR>/ce-frm2png - [output.png|-] --from-frm --palette <path-to-color.pal>`
|
||||
8. `./<BUILD_DIR>/ce-frm2png - [output.frm|-] --from-png --palette <path-to-color.pal>`
|
||||
|
||||
`-` can be used to take input from stdin (e.g. from `ce-dat-tool cat` or write to stdout).
|
||||
`-` can be used to take input from stdin (e.g. from `ce-dat-tool cat`) or write to stdout. When reading from stdin, pass `--from-frm` or `--from-png`. Output defaults to PNG for FRM input and FRM for PNG input when output is omitted or `-`; use `--to-png` for PNG output to stdout from PNG input.
|
||||
|
||||
If `--palette` isn't specified, it will pick up `color.pal` in the .frm's directory or cwd.
|
||||
Output file extensions are validated against the selected conversion. For example, PNG-to-FRM output must use `.frm`, and PNG output must use `.png`.
|
||||
|
||||
If `--palette` isn't specified, it will pick up `color.pal` in the input file's directory or cwd.
|
||||
|
||||
Notes:
|
||||
|
||||
- The tool expects a raw `color.pal` file. It does not read palettes directly from `master.dat`, so extract `color.pal` first if needed.
|
||||
- A typical extraction flow is: `ce-dat-tool master.dat extract --lower . 'color.pal'`
|
||||
- By default palette index `0` becomes transparent in the output PNG. Pass `--opaque` to keep it opaque.
|
||||
- The current implementation writes RGBA PNGs. It does not preserve the original Fallout palette indices as a palette-indexed PNG.
|
||||
- PNG output is always palette-indexed and preserves Fallout palette indices when possible.
|
||||
- For `png -> frm`, transparent pixels (alpha below 128) map to palette index `0` by default. Pass `--opaque` to quantize every pixel instead.
|
||||
- The current `png -> frm` implementation writes a single-frame FRM and points all six direction slots at the same frame payload.
|
||||
|
||||
## Updating SDL
|
||||
|
||||
|
||||
@@ -143,6 +143,7 @@ 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
|
||||
@@ -150,6 +151,9 @@ 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
|
||||
* Item/Corpse/Container/Critter highlighting (configure using [mods/sfall-mods.ini](https://github.com/sfall-team/sfall/blob/master/artifacts/config_files/sfall-mods.ini))
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -159,6 +163,14 @@ Integrating Sfall goodies is the top priority. Quality of life updates are OK to
|
||||
|
||||
For current sfall compatibility status and the remaining work needed to close gaps, see [SFALL_COMPATIBILITY.md](SFALL_COMPATIBILITY.md).
|
||||
|
||||
## For modders
|
||||
|
||||
* Robust (though not 100%) Sfall opcode and hook support
|
||||
* .ogg/.wav support for map music
|
||||
* .png support for static assets (must be 8bit indexed)
|
||||
* .zip support for .dat archives
|
||||
* Working BIS mapper
|
||||
|
||||
## License
|
||||
|
||||
The source code is this repository is available under the [Sustainable Use License](LICENSE.md).
|
||||
|
||||
+33
-19
@@ -4,6 +4,18 @@ 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.
|
||||
@@ -43,7 +55,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 | eax_available<br>set_eax_environment<br>play_sfall_sound<br>stop_sfall_sound | not implemented | *eax* opcodes will not be implemented |
|
||||
| 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. |
|
||||
| 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 | âś… | - |
|
||||
@@ -55,26 +67,28 @@ 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 | âś… except set_iface_tag_text, add_iface_tag | CE only handles built-in interface tags here; custom tag creation/text is not supported yet. |
|
||||
| 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. |
|
||||
| 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 | âś… except save_array, load_array | - |
|
||||
| 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 | âś… | - |
|
||||
| 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 | - |
|
||||
| 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 | âś… except block_combat, force_aimed_shots, disable_aimed_shots, get_last_target, get_last_attacker, set_spray_settings | - |
|
||||
| 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<br>create_message_window | implemented: only message_box, get_text_width, show_window, create_message_window | - |
|
||||
| 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<br>create_message_window | âś… except interface_print, draw_image, draw_image_scaled, interface_overlay | - |
|
||||
| Interface / Outline | outlined_object<br>get_outline<br>set_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: critter_inven_obj2, item_weight | - |
|
||||
| Interface / Inventory | display_stats<br>inventory_redraw<br>critter_inven_obj2<br>get_current_inven_size<br>item_weight | âś… except get_current_inven_size | - |
|
||||
| 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, obj_is_openable, get_proto_data, set_proto_data | - |
|
||||
| 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 | âś… | `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 | - |
|
||||
| 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/<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 | - |
|
||||
| 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 | - |
|
||||
| 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. |
|
||||
| Hero Appearange | set_dm/df_model<br>hero_select_win | not implemented | - |
|
||||
| Events | add_g_timer_event<br>remove_timer_event<br>create_spatial<br>spatial_radius | not implemented | - |
|
||||
| Other | get_year<br>active_hand<br>toggle_active_hand<br>get/set_viewport_x/y<br>get_light_level<br>message_str_game<br>sneak_success<br>unwield_slot<br>add_extra_msg_file<br>get_metarule_table<br>metarule_exist<br> | âś… except get/set_viewport_x/y, sneak_success | `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
|
||||
|
||||
@@ -92,17 +106,17 @@ See [`https://sfall-team.github.io/sfall/`](https://sfall-team.github.io/sfall/)
|
||||
| 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` | đźš« | - |
|
||||
| ItemDamage | `HOOK_ITEMDAMAGE` | âś… | - |
|
||||
| MoveCost | `HOOK_MOVECOST` | âś… | - |
|
||||
| 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` | đźš« | Et tu |
|
||||
| UseSkill | `HOOK_USESKILL` | âś… | - |
|
||||
| Steal | `HOOK_STEAL` | âś… | - |
|
||||
| WithinPerception | `HOOK_WITHINPERCEPTION` | âś… | - |
|
||||
| InventoryMove | `HOOK_INVENTORYMOVE` | âś… | - |
|
||||
| InvenWield | `HOOK_INVENWIELD` | đźš« | - |
|
||||
| AdjustFID | `HOOK_ADJUSTFID` | đźš« | - |
|
||||
| InvenWield | `HOOK_INVENWIELD` | âś… | - |
|
||||
| AdjustFID | `HOOK_ADJUSTFID` | âś… | Second hook arg currently matches the first because CE has no internal FID modifiers like Hero Appearance. |
|
||||
| CombatTurn | `HOOK_COMBATTURN` | âś… | - |
|
||||
| StdProcedure | `HOOK_STDPROCEDURE` | âś… | - |
|
||||
| StdProcedureEnd | `HOOK_STDPROCEDURE_END` | âś… | - |
|
||||
@@ -113,16 +127,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` | đźš« | Et tu |
|
||||
| UseSkillOn | `HOOK_USESKILLON` | âś… | - |
|
||||
| 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 |
|
||||
| Encounter | `HOOK_ENCOUNTER` | âś… | - |
|
||||
| AdjustPoison | `HOOK_ADJUSTPOISON` | đźš« | (maybe) |
|
||||
| AdjustRads | `HOOK_ADJUSTRADS` | đźš« | (maybe) |
|
||||
| RollCheck | `HOOK_ROLLCHECK` | đźš« | - |
|
||||
| BestWeapon | `HOOK_BESTWEAPON` | đźš« | - |
|
||||
| CanUseWeapon | `HOOK_CANUSEWEAPON` | đźš« | - |
|
||||
| CanUseWeapon | `HOOK_CANUSEWEAPON` | âś… | - |
|
||||
| BuildSfxWeapon | `HOOK_BUILDSFXWEAPON` | đźš« | - |
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# 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")
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
Binary file not shown.
+24
-2
@@ -22,6 +22,10 @@ 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
|
||||
@@ -94,6 +98,8 @@ 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)
|
||||
@@ -104,6 +110,8 @@ 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
|
||||
@@ -111,12 +119,26 @@ numbers_in_dialogue=0
|
||||
;Set to 2 to also skip the splash screen
|
||||
skip_opening_movies=0
|
||||
splash_screen_size=1
|
||||
;Set to 1 to scale movies to fit the screen while preserving aspect ratio.
|
||||
;Set to 0 to keep movies at their native size, centered on screen.
|
||||
movie_aspect_fit=1
|
||||
;Maximum number of columns shown in the main inventory and loot/steal windows (valid range: 1..2)
|
||||
;2-column Loot/steal window requires minimum screen width of 673px
|
||||
inventory_columns=2
|
||||
|
||||
;Set to 0 to keep the main menu art and controls at native size.
|
||||
;Set to 1 to scale only the main menu background image to fit the screen while maintaining aspect ratio.
|
||||
;Set to 2 to also scale the main menu button panel, red buttons, and button labels with the menu art.
|
||||
main_menu_scale_mode=1
|
||||
|
||||
|
||||
[qol]
|
||||
; Automatically open doors that are unlocked and has no script attached.
|
||||
auto_open_doors=0
|
||||
; Overrides distance at which walk animation is used when using an object.
|
||||
use_walk_distance=5
|
||||
; Overrides distance at which walk animation is used when using an object. 0 disables walking
|
||||
; This is the number of empty tiles between the player and the target
|
||||
use_walk_distance=3
|
||||
; 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
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
|
||||
|
||||
#define ARRAY_MAX_STRING (255)
|
||||
#define ARRAY_MAX_STRING (1024)
|
||||
#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+30; i+=10) begin
|
||||
s += "Verbosity.";
|
||||
for (i := 0; i < ARRAY_MAX_STRING+1; i+=100) begin
|
||||
s += "Verbosity.Verbosity.Verbosity.Verbosity.Verbosity.Verbosity.Verbosity.Verbosity.Verbosity.Verbosity.";
|
||||
end
|
||||
arr[0] := s;
|
||||
call assertEquals("array max string", strlen(arr[0]), ARRAY_MAX_STRING-1);
|
||||
@@ -141,8 +141,6 @@ 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};
|
||||
@@ -163,7 +161,6 @@ 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"]];
|
||||
|
||||
@@ -60,12 +60,14 @@ procedure start begin
|
||||
|
||||
display_msg("Testing combat/inventory/object helpers...");
|
||||
|
||||
call assertEquals("metarule attack_is_aimed", metarule_exist("attack_is_aimed"), 1);
|
||||
call assertEquals("metarule get_combat_free_move", metarule_exist("get_combat_free_move"), 1);
|
||||
call assertEquals("metarule set_combat_free_move", metarule_exist("set_combat_free_move"), 1);
|
||||
call assertEquals("metarule item_weight", metarule_exist("item_weight"), 1);
|
||||
call assertEquals("metarule obj_is_openable", metarule_exist("obj_is_openable"), 1);
|
||||
call assertEquals("opcode get_critter_current_ap", opcode_exists(OP_GET_CRITTER_CURRENT_AP), 1);
|
||||
call assertEquals("opcode set_critter_current_ap", opcode_exists(OP_SET_CRITTER_CURRENT_AP), 1);
|
||||
call assertEquals("attack_is_aimed defaults to false", attack_is_aimed, 0);
|
||||
|
||||
testItem := create_object_sid(TEST_ITEM_PID, 0, 0, -1);
|
||||
call assertEquals("item_weight matches proto weight for test item", item_weight(testItem), obj_weight(testItem));
|
||||
|
||||
@@ -1,5 +1,63 @@
|
||||
#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...");
|
||||
@@ -29,5 +87,47 @@ 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
|
||||
|
||||
@@ -65,6 +65,12 @@ procedure ini_test_suite begin
|
||||
call assertEquals("TC7 get_ini_sections size", len_array(result_array), 3);
|
||||
call assertTrue("TC7 get_ini_sections", scan_array(result_array, "TestMisc") >= 0);
|
||||
|
||||
// get_ini_config
|
||||
result_array := get_ini_config_db("config\\config_from_db.cfg");
|
||||
call assertEquals("TC8 get_ini_config_db size", len_array(result_array), 2);
|
||||
call assertTrue("TC8 get_ini_config ValidSection", result_array.ValidSection != 0);
|
||||
call assertEquals("TC8 get_ini_config_db ValidValue", result_array.ValidSection.ValidKey, "ValidValue");
|
||||
|
||||
call report_test_results("ini");
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
#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
|
||||
@@ -0,0 +1,136 @@
|
||||
#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
|
||||
@@ -0,0 +1,43 @@
|
||||
#include "sfall.h"
|
||||
#include "dik.h"
|
||||
#include "define_lite.h"
|
||||
#include "define_extra.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
procedure run_unwield_slot_test(variable slot, variable slotName) begin
|
||||
variable equippedItem := critter_inven_obj2(dude_obj, slot);
|
||||
|
||||
if (equippedItem == 0) then begin
|
||||
display_msg("unwield_slot " + slotName + ": slot is empty");
|
||||
return;
|
||||
end
|
||||
|
||||
unwield_slot(dude_obj, slot);
|
||||
|
||||
call assertTrue("unwield_slot clears " + slotName + " slot", critter_inven_obj2(dude_obj, slot) == 0);
|
||||
call report_test_results("unwield_slot");
|
||||
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_J) then begin
|
||||
call run_unwield_slot_test(INVEN_TYPE_WORN, "armor");
|
||||
end else if (key == DIK_K) then begin
|
||||
call run_unwield_slot_test(INVEN_TYPE_RIGHT_HAND, "right");
|
||||
end else if (key == DIK_L) then begin
|
||||
call run_unwield_slot_test(INVEN_TYPE_LEFT_HAND, "left");
|
||||
end
|
||||
end
|
||||
|
||||
procedure start begin
|
||||
if (not game_loaded) then return;
|
||||
|
||||
call assertEquals("unwield_slot metarule exists", metarule_exist("unwield_slot"), 1);
|
||||
call assertEquals("critter_inven_obj2 metarule exists", metarule_exist("critter_inven_obj2"), 1);
|
||||
display_msg("unwield_slot manual test ready: open inventory or barter, then press J armor, K right, L left");
|
||||
register_hook_proc(HOOK_KEYPRESS, keypress_handler);
|
||||
end
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user