Merge branch 'main' into mingw-fixes
This commit is contained in:
commit
39efadcb6b
|
@ -1,6 +1,7 @@
|
|||
# Force LF
|
||||
*.c text eol=lf
|
||||
*.cc text eol=lf
|
||||
*.cmake text eol=lf
|
||||
*.h text eol=lf
|
||||
*.md text eol=lf
|
||||
*.json text eol=lf
|
||||
|
|
|
@ -4,15 +4,17 @@ on:
|
|||
push:
|
||||
paths:
|
||||
- '.github/workflows/Build.yml'
|
||||
- 'src/**.c'
|
||||
- 'src/**.cc'
|
||||
- 'src/**.h'
|
||||
- '**/CMakeLists.txt'
|
||||
- '**/*.cmake'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/Build.yml'
|
||||
- 'src/**.c'
|
||||
- 'src/**.cc'
|
||||
- 'src/**.h'
|
||||
- '**/CMakeLists.txt'
|
||||
- '**/*.cmake'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
|
@ -20,23 +22,195 @@ defaults:
|
|||
|
||||
jobs:
|
||||
|
||||
Build:
|
||||
runs-on: windows-latest
|
||||
StaticAnalysis:
|
||||
name: Static analysis
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
:
|
||||
echo ::group::apt update
|
||||
sudo apt update 2>&1
|
||||
echo ::endgroup::
|
||||
sudo apt install cppcheck
|
||||
|
||||
- name: Clone
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: cppcheck
|
||||
run: cppcheck --std=c++17 src/
|
||||
|
||||
Build:
|
||||
name: ${{ matrix.cfg.name }} x${{ matrix.cfg.arch }}
|
||||
runs-on: ${{ matrix.cfg.os }}
|
||||
needs: [StaticAnalysis]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
cfg:
|
||||
#
|
||||
# name .......... overrides job name in GitHub UI
|
||||
# os ............ defines system image; passed to job.<id>.runs-on
|
||||
# cc ............ defines C compiler; passed to CMake configuration step (as `CC` environment variable)
|
||||
# cxx ........... defines C++ compiler; passed to CMake configuration step (as `CXX` environment variable)
|
||||
# ver ........... defines optional suffix to package name when installing compiler with apt, and whenever compiler version is important for build process
|
||||
# cc: gcc, cxx: g++, ver: null --becomes--> sudo apt install gcc g++
|
||||
# cc: gcc, cxx: g++, ver: 10 --becomes--> sudo apt install gcc-10 g++-10
|
||||
# arch .......... defines if building 32bit or 64bit application; used in multiple places to prepare build environment
|
||||
# also used as job name suffix (" x32" or " x64")
|
||||
# generator ..... passed to CMake configuration step (as `-G` switch)
|
||||
# can-fail ...... defines if job status should be set to success even if compilation fails
|
||||
# applies *only* to compilation step; errors in any other steps (installation, preparing build directory, etc.) still mark job as failed
|
||||
# artifact ...... path to compiled application; use "NO" if given job run should not generate any artifacts (case sensitive)
|
||||
# artifact-os ... defines artifact name suffix
|
||||
#
|
||||
- { name: Linux GCC, os: ubuntu-20.04, cc: gcc, cxx: g++, ver: null, arch: 32, generator: "Unix Makefiles", can-fail: false, artifact: Build/fallout2-ce, artifact-os: linux }
|
||||
# { name: Linux GCC, os: ubuntu-22.04, cc: gcc, cxx: g++, ver: null, arch: 64, generator: "Unix Makefiles", can-fail: true, artifact: Build/fallout2-ce, artifact-os: linux }
|
||||
- { name: Linux GCC 10, os: ubuntu-22.04, cc: gcc, cxx: g++, ver: 10, arch: 32, generator: "Unix Makefiles", can-fail: false, artifact: NO, artifact-os: linux }
|
||||
# { name: Linux GCC 10, os: ubuntu-22.04, cc: gcc, cxx: g++, ver: 10, arch: 64, generator: "Unix Makefiles", can-fail: true, artifact: NO, artifact-os: linux }
|
||||
# { name: MacOS 11 CLang, os: macOS-11, cc: clang, cxx: clang++, ver: null, arch: 64, generator: "Unix Makefiles", can-fail: true, artifact: NO, artifact-os: mac }
|
||||
# { name: MacOS 12 CLang, os: macOS-12, cc: clang, cxx: clang++, ver: null, arch: 64, generator: "Unix Makefiles", can-fail: true, artifact: NO, artifact-os: mac }
|
||||
- { name: Windows VS2019, os: windows-2019, cc: cl, cxx: cl, ver: null, arch: 32, generator: "Visual Studio 16 2019", can-fail: false, artifact: NO, artifact-os: windows }
|
||||
# { name: Windows VS2019, os: windows-2019, cc: cl, cxx: cl, ver: null, arch: 64, generator: "Visual Studio 16 2019", can-fail: true, artifact: NO, artifact-os: windows }
|
||||
- { name: Windows VS2022, os: windows-2022, cc: cl, cxx, cl, ver: null, arch: 32, generator: "Visual Studio 17 2022", can-fail: false, artifact: Build/Release/fallout2-ce.exe, artifact-os: windows }
|
||||
# { name: Windows VS2022, os: windows-2022, cc: cl, cxx, cl, ver: null, arch: 64, generator: "Visual Studio 17 2022", can-fail: true, artifact: Build/Release/fallout2-ce.exe, artifact-os: windows }
|
||||
|
||||
steps:
|
||||
- name: Configure
|
||||
run: |
|
||||
: Here be dragons :
|
||||
#set -x
|
||||
arch=${{ matrix.cfg.arch }}
|
||||
ver="${{ matrix.cfg.ver }}"
|
||||
cc="${{ matrix.cfg.cc }}"
|
||||
cxx="${{ matrix.cfg.cxx }}"
|
||||
|
||||
# Variables exported for other steps:
|
||||
#
|
||||
# GHA_PM .................. packages manager executable (might include `sudo`); if not exported, `Install` step is skipped
|
||||
# GHA_PM_COMPILER ......... compiler package(s), including version (if set in matrix)
|
||||
# GHA_PM_COMPILER_EXTRA ... extra compiler packages
|
||||
# GHA_PM_LIBS ............. required libraries packages
|
||||
# GHA_CC .................. C compiler executable, including version (if set in matrix)
|
||||
# GHA_CXX ................. C++ compiler executable, including version (if set in matrix)
|
||||
# GHA_PLATFORM ............ CMake -A ... switch, for configure step
|
||||
# GHA_TOOLCHAIN ........... CMake -DCMAKE_TOOLCHAIN_FILE=... switch, for configure step
|
||||
|
||||
# Compiler executables names
|
||||
[[ "$ver" != "" ]] && verCMAKE="-$ver"
|
||||
echo GHA_CC="$cc$verCMAKE" >> $GITHUB_ENV
|
||||
echo GHA_CXX="$cxx$verCMAKE" >> $GITHUB_ENV
|
||||
|
||||
if [[ $arch -ne 32 ]] && [[ $arch -ne 64 ]]; then
|
||||
echo "[ERROR] matrix.cfg.arch must be set to 32 or 64"
|
||||
exit 1
|
||||
elif [[ "$ver" != "" ]] && ! [[ "$ver" =~ [0-9]+ ]]; then
|
||||
echo "[ERROR] matrix.cfg.ver must be null or number"
|
||||
exit 1
|
||||
elif [[ $RUNNER_OS == "Linux" ]]; then
|
||||
[[ "$ver" != "" ]] && verPM="-$ver"
|
||||
|
||||
echo GHA_PM="sudo apt" >> $GITHUB_ENV
|
||||
apt="amd64"
|
||||
|
||||
if [[ "$cc" == "clang" ]] && [[ "$cxx" == "clang++" ]]; then
|
||||
echo GHA_PM_COMPILER="$cc$verPM" >> $GITHUB_ENV
|
||||
else
|
||||
echo GHA_PM_COMPILER="$cc$verPM $cxx$verPM" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
# Handle building 32bit executable on 64bit host
|
||||
if [[ $arch -eq 32 ]]; then
|
||||
apt="i386"
|
||||
sudo dpkg --add-architecture $apt
|
||||
|
||||
# Extra packages
|
||||
echo GHA_PM_COMPILER_EXTRA="gcc${verPM}-multilib g++${verPM}-multilib" >> $GITHUB_ENV
|
||||
|
||||
# Toolchain file; without proper 32@64 toolchain setup CMake can't find OpenGL libraries
|
||||
echo GHA_TOOLCHAIN="-DCMAKE_TOOLCHAIN_FILE=cmake/toolchain/Linux32.cmake" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
echo GHA_PM_LIBS="libsdl2-dev:$apt zlib1g-dev:$apt" >> $GITHUB_ENV
|
||||
elif [[ $RUNNER_OS == "macOS" ]]; then
|
||||
[[ "$ver" != "" ]] && verPM="@$ver"
|
||||
echo GHA_PM="brew" >> $GITHUB_ENV
|
||||
|
||||
if [[ "$cc" == "gcc" ]] && [[ "$cxx" == "g++" ]]; then
|
||||
echo GHA_PM_COMPILER="$cc$verPM" >> $GITHUB_ENV
|
||||
elif [[ "$cc" == "clang" ]] && [[ "$cxx" == "clang++" ]]; then
|
||||
echo GHA_PM_COMPILER="llvm$verPM" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
echo GHA_PM_LIBS="sdl2" >> $GITHUB_ENV
|
||||
elif [[ $RUNNER_OS == "Windows" ]]; then
|
||||
# VisualStudio; '-A' switch is used to compile 32bit targets on 64bit hosts
|
||||
if [[ "${{ matrix.cfg.generator }}" =~ ^Visual ]]; then
|
||||
if [[ $arch -eq 32 ]]; then
|
||||
echo GHA_PLATFORM="-A Win32" >> $GITHUB_ENV
|
||||
else
|
||||
echo GHA_PLATFORM="-A x64" >> $GITHUB_ENV
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
- name: Install
|
||||
if: env.GHA_PM != ''
|
||||
run: |
|
||||
:
|
||||
#set -x
|
||||
|
||||
echo ::group::Update package manager
|
||||
$GHA_PM update 2>&1
|
||||
echo ::endgroup::
|
||||
|
||||
if [[ ${{ matrix.cfg.arch }} -eq 32 ]] && ([[ "$ImageOS" == "ubuntu20" ]] || [[ "${{ matrix.cfg.os }}" == "ubuntu-20.04" ]]); then
|
||||
echo ::group::Fix Ubuntu 20
|
||||
$GHA_PM install --allow-downgrades libpcre2-8-0=10.34-7
|
||||
echo ::endgroup::
|
||||
fi
|
||||
|
||||
if [[ "$GHA_PM_COMPILER" != "" ]] || [[ "$GHA_PM_COMPILER_EXTRA" ]]; then
|
||||
echo ::group::Compiler
|
||||
$GHA_PM install $GHA_PM_COMPILER $GHA_PM_COMPILER_EXTRA
|
||||
echo ::endgroup::
|
||||
fi
|
||||
|
||||
if [[ "$GHA_PM_LIBS" != "" ]]; then
|
||||
echo ::group::Libraries
|
||||
$GHA_PM install $GHA_PM_LIBS
|
||||
echo :endgroup::
|
||||
fi
|
||||
|
||||
- name: Clone
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Using ${{ env.NAME }} here (instead of usual $NAME) to make full command line clearly displayed, without need to check step environment first
|
||||
- name: Prepare
|
||||
run: cmake -B Build -A Win32
|
||||
run: cmake -B Build -G "${{ matrix.cfg.generator }}" ${{ env.GHA_PLATFORM }} ${{ env.GHA_TOOLCHAIN }} 2>&1
|
||||
env:
|
||||
CC: ${{ env.GHA_CC }}
|
||||
CXX: ${{ env.GHA_CXX }}
|
||||
|
||||
- name: Release build
|
||||
run: cmake --build Build --config Release
|
||||
- name: Build
|
||||
run: cmake --build Build --config Release && echo BUILD_OK=1 >> $GITHUB_ENV
|
||||
continue-on-error: ${{ matrix.cfg.can-fail }}
|
||||
|
||||
- name: Artifact
|
||||
- name: Artifact prepare
|
||||
if: matrix.cfg.artifact != 'NO' && env.BUILD_OK == 1
|
||||
run: |
|
||||
:
|
||||
echo BUILD_OK=0 >> $GITHUB_ENV
|
||||
dir="${{ matrix.cfg.artifact-os }}/x${{ matrix.cfg.arch }}"
|
||||
mkdir -p "$dir"
|
||||
cp "${{ matrix.cfg.artifact }}" "$dir"
|
||||
echo BUILD_OK=1 >> $GITHUB_ENV
|
||||
|
||||
- name: Artifact upload
|
||||
if: matrix.cfg.artifact != 'NO' && env.BUILD_OK == 1
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: fallout2-ce
|
||||
path: |
|
||||
Build/*/fallout2-ce.exe
|
||||
name: fallout2-ce-${{ matrix.cfg.artifact-os }}
|
||||
path: "${{ matrix.cfg.artifact-os }}/x${{ matrix.cfg.arch }}"
|
||||
retention-days: 7
|
||||
|
|
|
@ -247,6 +247,11 @@ if(WIN32)
|
|||
_CRT_SECURE_NO_WARNINGS
|
||||
_CRT_NONSTDC_NO_WARNINGS
|
||||
)
|
||||
else()
|
||||
target_compile_definitions(${EXECUTABLE_NAME} PRIVATE
|
||||
$<$<CONFIG:Debug>:_DEBUG>
|
||||
$<$<CONFIG:RelWithDebInfo>:_DEBUG>
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
|
@ -259,7 +264,7 @@ add_subdirectory("third_party/fpattern")
|
|||
target_link_libraries(${EXECUTABLE_NAME} ${FPATTERN_LIBRARY})
|
||||
target_include_directories(${EXECUTABLE_NAME} PRIVATE ${FPATTERN_INCLUDE_DIR})
|
||||
|
||||
if(NOT APPLE)
|
||||
if(NOT APPLE AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
add_subdirectory("third_party/zlib")
|
||||
add_subdirectory("third_party/sdl2")
|
||||
else()
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
set( CMAKE_SYSTEM_NAME "Linux" )
|
||||
set( CMAKE_SYSTEM_PROCESSOR "i386" )
|
||||
set( CMAKE_C_FLAGS "-m32" )
|
||||
set( CMAKE_CXX_FLAGS "-m32" )
|
|
@ -40,8 +40,8 @@ int _action_in_explode = 0;
|
|||
const int gNormalDeathAnimations[DAMAGE_TYPE_COUNT] = {
|
||||
ANIM_DANCING_AUTOFIRE,
|
||||
ANIM_SLICED_IN_HALF,
|
||||
ANIM_CHUNKS_OF_FLESH,
|
||||
ANIM_CHUNKS_OF_FLESH,
|
||||
ANIM_CHARRED_BODY,
|
||||
ANIM_CHARRED_BODY,
|
||||
ANIM_ELECTRIFY,
|
||||
ANIM_FALL_BACK,
|
||||
ANIM_BIG_HOLE,
|
||||
|
@ -1454,7 +1454,7 @@ int _pick_fall(Object* obj, int anim)
|
|||
}
|
||||
}
|
||||
} else if (anim == ANIM_FALL_BACK) {
|
||||
rotation = (obj->rotation + 3) % 6u;
|
||||
rotation = (obj->rotation + 3) % ROTATION_COUNT;
|
||||
for (i = 1; i < 3; i++) {
|
||||
tile_num = tileGetTileInDirection(obj->tile, rotation, i);
|
||||
if (_obj_blocking_at(obj, tile_num, obj->elevation) != NULL) {
|
||||
|
@ -1725,7 +1725,7 @@ int _compute_explosion_damage(int min, int max, Object* a3, int* a4)
|
|||
}
|
||||
|
||||
if (a4 != NULL) {
|
||||
if ((a3->flags & OBJECT_FLAG_0x800) == 0) {
|
||||
if ((a3->flags & OBJECT_MULTIHEX) == 0) {
|
||||
*a4 = v7 / 10;
|
||||
}
|
||||
}
|
||||
|
@ -1892,7 +1892,7 @@ int _compute_dmg_damage(int min, int max, Object* obj, int* a4, int damageType)
|
|||
}
|
||||
|
||||
if (a4 != NULL) {
|
||||
if ((obj->flags & OBJECT_FLAG_0x800) == 0 && damageType != DAMAGE_TYPE_ELECTRICAL) {
|
||||
if ((obj->flags & OBJECT_MULTIHEX) == 0 && damageType != DAMAGE_TYPE_ELECTRICAL) {
|
||||
*a4 = v10 / 10;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1682,7 +1682,7 @@ int _make_straight_path_func(Object* a1, int from, int to, STRUCT_530014_28* a4,
|
|||
if (a5 != NULL) {
|
||||
Object* v11 = a7(a1, from, a1->elevation);
|
||||
if (v11 != NULL) {
|
||||
if (v11 != *a5 && (a6 != 32 || (v11->flags & OBJECT_FLAG_0x80000000) == 0)) {
|
||||
if (v11 != *a5 && (a6 != 32 || (v11->flags & OBJECT_SHOOT_THRU) == 0)) {
|
||||
*a5 = v11;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1726,7 +1726,7 @@ int _make_straight_path_func(Object* a1, int from, int to, STRUCT_530014_28* a4,
|
|||
int tileY = fromY;
|
||||
|
||||
int pathNodeIndex = 0;
|
||||
int v50 = from;
|
||||
int prevTile = from;
|
||||
int v22 = 0;
|
||||
int tile;
|
||||
|
||||
|
@ -1770,17 +1770,17 @@ int _make_straight_path_func(Object* a1, int from, int to, STRUCT_530014_28* a4,
|
|||
tileY += stepY;
|
||||
middle += v48;
|
||||
|
||||
if (tile != v50) {
|
||||
if (tile != prevTile) {
|
||||
if (a5 != NULL) {
|
||||
Object* obj = a7(a1, tile, a1->elevation);
|
||||
if (obj != NULL) {
|
||||
if (obj != *a5 && (a6 != 32 || (obj->flags & OBJECT_FLAG_0x80000000) == 0)) {
|
||||
if (obj != *a5 && (a6 != 32 || (obj->flags & OBJECT_SHOOT_THRU) == 0)) {
|
||||
*a5 = obj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
v50 = tile;
|
||||
prevTile = tile;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1823,16 +1823,17 @@ int _make_straight_path_func(Object* a1, int from, int to, STRUCT_530014_28* a4,
|
|||
tileX += stepX;
|
||||
middle += v47;
|
||||
|
||||
if (tile != v50) {
|
||||
if (tile != prevTile) {
|
||||
if (a5 != NULL) {
|
||||
Object* obj = a7(a1, tile, a1->elevation);
|
||||
if (obj != NULL) {
|
||||
if (obj != *a5 && (a6 != 32 || (obj->flags & OBJECT_FLAG_0x80000000) == 0)) {
|
||||
if (obj != *a5 && (a6 != 32 || (obj->flags & OBJECT_SHOOT_THRU) == 0)) {
|
||||
*a5 = obj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
prevTile = tile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1863,38 +1864,35 @@ int _make_straight_path_func(Object* a1, int from, int to, STRUCT_530014_28* a4,
|
|||
}
|
||||
|
||||
// 0x4167F8
|
||||
int animateMoveObjectToObject(Object* a1, Object* a2, int a3, int anim, int animationSequenceIndex)
|
||||
int animateMoveObjectToObject(Object* from, Object* to, int a3, int anim, int animationSequenceIndex)
|
||||
{
|
||||
int v10;
|
||||
int v13;
|
||||
STRUCT_530014* ptr;
|
||||
bool hidden = (to->flags & OBJECT_HIDDEN);
|
||||
to->flags |= OBJECT_HIDDEN;
|
||||
|
||||
int hidden = (a2->flags & OBJECT_HIDDEN);
|
||||
a2->flags |= OBJECT_HIDDEN;
|
||||
int moveSadIndex = _anim_move(from, to->tile, to->elevation, -1, anim, 0, animationSequenceIndex);
|
||||
|
||||
v10 = _anim_move(a1, a2->tile, a2->elevation, -1, anim, 0, animationSequenceIndex);
|
||||
|
||||
if (hidden == 0) {
|
||||
a2->flags &= ~OBJECT_HIDDEN;
|
||||
if (!hidden) {
|
||||
to->flags &= ~OBJECT_HIDDEN;
|
||||
}
|
||||
|
||||
if (v10 == -1) {
|
||||
if (moveSadIndex == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ptr = &(_sad[v10]);
|
||||
v13 = (((a1->flags & OBJECT_FLAG_0x800) != 0) + 1); // TODO: What the hell is this?
|
||||
ptr->field_1C -= v13;
|
||||
STRUCT_530014* ptr = &(_sad[moveSadIndex]);
|
||||
// NOTE: Original code is somewhat different. Due to some kind of
|
||||
// optimization this value is either 1 or 2, which is later used in
|
||||
// subsequent calculations and rotations array lookup.
|
||||
bool isMultihex = (from->flags & OBJECT_MULTIHEX);
|
||||
ptr->field_1C -= (isMultihex ? 2 : 1);
|
||||
if (ptr->field_1C <= 0) {
|
||||
ptr->field_20 = -1000;
|
||||
_anim_set_continue(animationSequenceIndex, 0);
|
||||
}
|
||||
|
||||
if (v13) {
|
||||
ptr->field_24 = tileGetTileInDirection(a2->tile, ptr->field_24 + v13 + ptr->field_1C + 3, 1);
|
||||
}
|
||||
ptr->field_24 = tileGetTileInDirection(to->tile, ptr->rotations[isMultihex ? ptr->field_1C + 1 : ptr->field_1C], 1);
|
||||
|
||||
if (v13 == 2) {
|
||||
if (isMultihex) {
|
||||
ptr->field_24 = tileGetTileInDirection(ptr->field_24, ptr->rotations[ptr->field_1C], 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -257,15 +257,15 @@ int _idist(int a1, int a2, int a3, int a4);
|
|||
int _tile_idistance(int tile1, int tile2);
|
||||
int _make_straight_path(Object* a1, int from, int to, STRUCT_530014_28* pathNodes, Object** a5, int a6);
|
||||
int _make_straight_path_func(Object* a1, int from, int to, STRUCT_530014_28* a4, Object** a5, int a6, Object* (*a7)(Object*, int, int));
|
||||
int animateMoveObjectToObject(Object* a1, Object* a2, int a3, int a4, int a5);
|
||||
int animateMoveObjectToTile(Object* obj, int tile_num, int elev, int a4, int a5, int a6);
|
||||
int _anim_move(Object* obj, int tile, int elev, int a3, int a4, int a5, int animationSequenceIndex);
|
||||
int _anim_move_straight_to_tile(Object* obj, int a2, int a3, int fid, int a5, int a6);
|
||||
int _anim_move_on_stairs(Object* obj, int a2, int a3, int fid, int a5);
|
||||
int _check_for_falling(Object* obj, int a2, int a3);
|
||||
int animateMoveObjectToObject(Object* from, Object* to, int a3, int anim, int animationSequenceIndex);
|
||||
int animateMoveObjectToTile(Object* obj, int tile_num, int elev, int a4, int anim, int animationSequenceIndex);
|
||||
int _anim_move(Object* obj, int tile, int elev, int a3, int anim, int a5, int animationSequenceIndex);
|
||||
int _anim_move_straight_to_tile(Object* obj, int tile, int elevation, int anim, int animationSequenceIndex, int flags);
|
||||
int _anim_move_on_stairs(Object* obj, int tile, int elevation, int anim, int animationSequenceIndex);
|
||||
int _check_for_falling(Object* obj, int anim, int a3);
|
||||
void _object_move(int index);
|
||||
void _object_straight_move(int a1);
|
||||
int _anim_animate(Object* obj, int a2, int a3, int a4);
|
||||
void _object_straight_move(int index);
|
||||
int _anim_animate(Object* obj, int anim, int animationSequenceIndex, int flags);
|
||||
void _object_animate();
|
||||
void _object_anim_compact();
|
||||
int _check_move(int* a1);
|
||||
|
@ -274,8 +274,8 @@ int _dude_run(int a1);
|
|||
void _dude_fidget();
|
||||
void _dude_stand(Object* obj, int rotation, int fid);
|
||||
void _dude_standup(Object* a1);
|
||||
int actionRotate(Object* obj, int a2, int a3);
|
||||
int _anim_change_fid(Object* obj, int a2, int fid);
|
||||
int actionRotate(Object* obj, int delta, int animationSequenceIndex);
|
||||
int _anim_change_fid(Object* obj, int animationSequenceIndex, int fid);
|
||||
void _anim_stop();
|
||||
int _check_gravity(int tile, int elevation);
|
||||
unsigned int _compute_tpf(Object* object, int fid);
|
||||
|
|
46
src/art.cc
46
src/art.cc
|
@ -7,11 +7,24 @@
|
|||
#include "memory.h"
|
||||
#include "object.h"
|
||||
#include "proto.h"
|
||||
#include "sfall_config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// 0x5002D8
|
||||
char gDefaultJumpsuitMaleFileName[] = "hmjmps";
|
||||
|
||||
// 0x05002E0
|
||||
char gDefaultJumpsuitFemaleFileName[] = "hfjmps";
|
||||
|
||||
// 0x5002E8
|
||||
char gDefaultTribalMaleFileName[] = "hmwarr";
|
||||
|
||||
// 0x5002F0
|
||||
char gDefaultTribalFemaleFileName[] = "hfprim";
|
||||
|
||||
// 0x510738
|
||||
ArtListDescription gArtListDescriptions[OBJ_TYPE_COUNT] = {
|
||||
{ 0, "items", 0, 0, 0 },
|
||||
|
@ -153,18 +166,43 @@ int artInit()
|
|||
return -1;
|
||||
}
|
||||
|
||||
// SFALL: Modify player model settings.
|
||||
char* jumpsuitMaleFileName = NULL;
|
||||
configGetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_DUDE_NATIVE_LOOK_JUMPSUIT_MALE_KEY, &jumpsuitMaleFileName);
|
||||
if (jumpsuitMaleFileName == NULL || jumpsuitMaleFileName[0] == '\0') {
|
||||
jumpsuitMaleFileName = gDefaultJumpsuitMaleFileName;
|
||||
}
|
||||
|
||||
char* jumpsuitFemaleFileName = NULL;
|
||||
configGetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_DUDE_NATIVE_LOOK_JUMPSUIT_FEMALE_KEY, &jumpsuitFemaleFileName);
|
||||
if (jumpsuitFemaleFileName == NULL || jumpsuitFemaleFileName[0] == '\0') {
|
||||
jumpsuitFemaleFileName = gDefaultJumpsuitFemaleFileName;
|
||||
}
|
||||
|
||||
char* tribalMaleFileName = NULL;
|
||||
configGetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_DUDE_NATIVE_LOOK_TRIBAL_MALE_KEY, &tribalMaleFileName);
|
||||
if (tribalMaleFileName == NULL || tribalMaleFileName[0] == '\0') {
|
||||
tribalMaleFileName = gDefaultTribalMaleFileName;
|
||||
}
|
||||
|
||||
char *tribalFemaleFileName = NULL;
|
||||
configGetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_DUDE_NATIVE_LOOK_TRIBAL_FEMALE_KEY, &tribalFemaleFileName);
|
||||
if (tribalFemaleFileName == NULL || tribalFemaleFileName[0] == '\0') {
|
||||
tribalFemaleFileName = gDefaultTribalFemaleFileName;
|
||||
}
|
||||
|
||||
ptr = gArtListDescriptions[1].fileNames;
|
||||
for (i = 0; i < gArtListDescriptions[1].fileNamesLength; i++) {
|
||||
if (compat_stricmp(ptr, "hmjmps") == 0) {
|
||||
if (compat_stricmp(ptr, jumpsuitMaleFileName) == 0) {
|
||||
_art_vault_person_nums[DUDE_NATIVE_LOOK_JUMPSUIT][GENDER_MALE] = i;
|
||||
} else if (compat_stricmp(ptr, "hfjmps") == 0) {
|
||||
} else if (compat_stricmp(ptr, jumpsuitFemaleFileName) == 0) {
|
||||
_art_vault_person_nums[DUDE_NATIVE_LOOK_JUMPSUIT][GENDER_FEMALE] = i;
|
||||
}
|
||||
|
||||
if (compat_stricmp(ptr, "hmwarr") == 0) {
|
||||
if (compat_stricmp(ptr, tribalMaleFileName) == 0) {
|
||||
_art_vault_person_nums[DUDE_NATIVE_LOOK_TRIBAL][GENDER_MALE] = i;
|
||||
_art_vault_guy_num = i;
|
||||
} else if (compat_stricmp(ptr, "hfprim") == 0) {
|
||||
} else if (compat_stricmp(ptr, tribalFemaleFileName) == 0) {
|
||||
_art_vault_person_nums[DUDE_NATIVE_LOOK_TRIBAL][GENDER_FEMALE] = i;
|
||||
}
|
||||
|
||||
|
|
|
@ -124,6 +124,11 @@ typedef enum DudeNativeLook {
|
|||
DUDE_NATIVE_LOOK_COUNT,
|
||||
} DudeNativeLook;
|
||||
|
||||
extern char gDefaultJumpsuitMaleFileName[];
|
||||
extern char gDefaultJumpsuitFemaleFileName[];
|
||||
extern char gDefaultTribalMaleFileName[];
|
||||
extern char gDefaultTribalFemaleFileName[];
|
||||
|
||||
extern ArtListDescription gArtListDescriptions[OBJ_TYPE_COUNT];
|
||||
extern bool gArtLanguageInitialized;
|
||||
extern const char* _head1;
|
||||
|
|
|
@ -458,7 +458,7 @@ void automapRenderInMapWindow(int window, int elevation, unsigned char* backgrou
|
|||
&& (object->data.critter.combat.results & DAM_DEAD) == 0) {
|
||||
objectColor = _colorTable[31744];
|
||||
} else {
|
||||
if ((object->flags & OBJECT_FLAG_0x40000000) == 0) {
|
||||
if ((object->flags & OBJECT_SEEN) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1011,7 +1011,7 @@ void _decode_map_data(int elevation)
|
|||
|
||||
Object* object = objectFindFirstAtElevation(elevation);
|
||||
while (object != NULL) {
|
||||
if (object->tile != -1 && (object->flags & OBJECT_FLAG_0x40000000) != 0) {
|
||||
if (object->tile != -1 && (object->flags & OBJECT_SEEN) != 0) {
|
||||
int contentType;
|
||||
|
||||
int objectType = (object->fid & 0xF000000) >> 24;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "sound.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h> // qsort
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -126,10 +126,12 @@ typedef struct TownReputationEntry {
|
|||
int city;
|
||||
} TownReputationEntry;
|
||||
|
||||
typedef struct STRUCT_56FCB0 {
|
||||
int field_0;
|
||||
char* field_4;
|
||||
} STRUCT_56FCB0;
|
||||
typedef struct PerkDialogOption {
|
||||
// Depending on the current mode this value is the id of either
|
||||
// perk, trait (handling Mutate perk), or skill (handling Tag perk).
|
||||
int value;
|
||||
char* name;
|
||||
} PerkDialogOption;
|
||||
|
||||
// TODO: Field order is probably wrong.
|
||||
typedef struct KillInfo {
|
||||
|
@ -138,11 +140,11 @@ typedef struct KillInfo {
|
|||
int kills;
|
||||
} KillInfo;
|
||||
|
||||
extern int _grph_id[50];
|
||||
extern const unsigned char _copyflag[EDITOR_GRAPHIC_COUNT];
|
||||
extern const int word_431D3A[EDITOR_DERIVED_STAT_COUNT];
|
||||
extern const int _StatYpos[7];
|
||||
extern const int word_431D6C[EDITOR_DERIVED_STAT_COUNT];
|
||||
extern int gCharacterEditorFrmIds[50];
|
||||
extern const unsigned char gCharacterEditorFrmShouldCopy[EDITOR_GRAPHIC_COUNT];
|
||||
extern const int gCharacterEditorDerivedStatFrmIds[EDITOR_DERIVED_STAT_COUNT];
|
||||
extern const int gCharacterEditorPrimaryStatY[7];
|
||||
extern const int gCharacterEditorDerivedStatsMap[EDITOR_DERIVED_STAT_COUNT];
|
||||
extern char byte_431D93[64];
|
||||
extern const int dword_431DD4[7];
|
||||
|
||||
|
@ -151,10 +153,10 @@ extern const double dbl_501713;
|
|||
extern const double dbl_5018F0;
|
||||
extern const double dbl_5019BE;
|
||||
|
||||
extern bool _bk_enable_0;
|
||||
extern int _skill_cursor;
|
||||
extern int _slider_y;
|
||||
extern int characterEditorRemainingCharacterPoints;
|
||||
extern bool gCharacterEditorIsoWasEnabled;
|
||||
extern int gCharacterEditorCurrentSkill;
|
||||
extern int gCharacterEditorSkillValueAdjustmentSliderY;
|
||||
extern int gCharacterEditorRemainingCharacterPoints;
|
||||
extern KarmaEntry* gKarmaEntries;
|
||||
extern int gKarmaEntriesLength;
|
||||
extern GenericReputationEntry* gGenericReputationEntries;
|
||||
|
@ -162,148 +164,148 @@ extern int gGenericReputationEntriesLength;
|
|||
extern const TownReputationEntry gTownReputationEntries[TOWN_REPUTATION_COUNT];
|
||||
extern const int gAddictionReputationVars[ADDICTION_REPUTATION_COUNT];
|
||||
extern const int gAddictionReputationFrmIds[ADDICTION_REPUTATION_COUNT];
|
||||
extern int _folder_up_button;
|
||||
extern int _folder_down_button;
|
||||
extern int gCharacterEditorFolderViewScrollUpBtn;
|
||||
extern int gCharacterEditorFolderViewScrollDownBtn;
|
||||
|
||||
extern char _folder_card_string[256];
|
||||
extern int _skillsav[SKILL_COUNT];
|
||||
extern MessageList editorMessageList;
|
||||
extern STRUCT_56FCB0 _name_sort_list[DIALOG_PICKER_NUM_OPTIONS];
|
||||
extern int _trait_bids[TRAIT_COUNT];
|
||||
extern MessageListItem editorMessageListItem;
|
||||
extern char _old_str1[48];
|
||||
extern char _old_str2[48];
|
||||
extern int _tag_bids[SKILL_COUNT];
|
||||
extern char _name_save[32];
|
||||
extern Size _GInfo[EDITOR_GRAPHIC_COUNT];
|
||||
extern CacheEntry* _grph_key[EDITOR_GRAPHIC_COUNT];
|
||||
extern unsigned char* _grphcpy[EDITOR_GRAPHIC_COUNT];
|
||||
extern unsigned char* _grphbmp[EDITOR_GRAPHIC_COUNT];
|
||||
extern int _folder_max_lines;
|
||||
extern int _folder_line;
|
||||
extern int _folder_card_fid;
|
||||
extern int _folder_top_line;
|
||||
extern char* _folder_card_title;
|
||||
extern char* _folder_card_title2;
|
||||
extern int _folder_yoffset;
|
||||
extern int _folder_karma_top_line;
|
||||
extern int _folder_highlight_line;
|
||||
extern char* _folder_card_desc;
|
||||
extern int _folder_ypos;
|
||||
extern int _folder_kills_top_line;
|
||||
extern int _folder_perk_top_line;
|
||||
extern unsigned char* gEditorPerkBackgroundBuffer;
|
||||
extern int gEditorPerkWindow;
|
||||
extern int _SliderPlusID;
|
||||
extern int _SliderNegID;
|
||||
extern int _stat_bids_minus[7];
|
||||
extern unsigned char* characterEditorWindowBuf;
|
||||
extern int characterEditorWindowHandle;
|
||||
extern int _stat_bids_plus[7];
|
||||
extern unsigned char* gEditorPerkWindowBuffer;
|
||||
extern CritterProtoData _dude_data;
|
||||
extern unsigned char* characterEditorWindowBackgroundBuf;
|
||||
extern int _cline;
|
||||
extern int _oldsline;
|
||||
extern int _upsent_points_back;
|
||||
extern int _last_level;
|
||||
extern int characterEditorWindowOldFont;
|
||||
extern int _kills_count;
|
||||
extern CacheEntry* _bck_key;
|
||||
extern int _hp_back;
|
||||
extern int _mouse_ypos;
|
||||
extern int _mouse_xpos;
|
||||
extern char gCharacterEditorFolderCardString[256];
|
||||
extern int gCharacterEditorSkillsBackup[SKILL_COUNT];
|
||||
extern MessageList gCharacterEditorMessageList;
|
||||
extern PerkDialogOption gPerkDialogOptionList[DIALOG_PICKER_NUM_OPTIONS];
|
||||
extern int gCharacterEditorOptionalTraitBtns[TRAIT_COUNT];
|
||||
extern MessageListItem gCharacterEditorMessageListItem;
|
||||
extern char gCharacterEditorCardTitle[48];
|
||||
extern char gPerkDialogCardTitle[48];
|
||||
extern int gCharacterEditorTagSkillBtns[SKILL_COUNT];
|
||||
extern char gCharacterEditorNameBackup[32];
|
||||
extern Size gCharacterEditorFrmSize[EDITOR_GRAPHIC_COUNT];
|
||||
extern CacheEntry* gCharacterEditorFrmHandle[EDITOR_GRAPHIC_COUNT];
|
||||
extern unsigned char* gCharacterEditorFrmCopy[EDITOR_GRAPHIC_COUNT];
|
||||
extern unsigned char* gCharacterEditorFrmData[EDITOR_GRAPHIC_COUNT];
|
||||
extern int gCharacterEditorFolderViewMaxLines;
|
||||
extern int gCharacterEditorFolderViewCurrentLine;
|
||||
extern int gCharacterEditorFolderCardFrmId;
|
||||
extern int gCharacterEditorFolderViewTopLine;
|
||||
extern char* gCharacterEditorFolderCardTitle;
|
||||
extern char* gCharacterEditorFolderCardSubtitle;
|
||||
extern int gCharacterEditorFolderViewOffsetY;
|
||||
extern int gCharacterEditorKarmaFolderTopLine;
|
||||
extern int gCharacterEditorFolderViewHighlightedLine;
|
||||
extern char* gCharacterEditorFolderCardDescription;
|
||||
extern int gCharacterEditorFolderViewNextY;
|
||||
extern int gCharacterEditorKillsFolderTopLine;
|
||||
extern int gCharacterEditorPerkFolderTopLine;
|
||||
extern unsigned char* gPerkDialogBackgroundBuffer;
|
||||
extern int gPerkDialogWindow;
|
||||
extern int gCharacterEditorSliderPlusBtn;
|
||||
extern int gCharacterEditorSliderMinusBtn;
|
||||
extern int gCharacterEditorPrimaryStatMinusBtns[7];
|
||||
extern unsigned char* gCharacterEditorWindowBuffer;
|
||||
extern int gCharacterEditorWindow;
|
||||
extern int gCharacterEditorPrimaryStatPlusBtns[7];
|
||||
extern unsigned char* gPerkDialogWindowBuffer;
|
||||
extern CritterProtoData gCharacterEditorDudeDataBackup;
|
||||
extern unsigned char* gCharacterEditorWindowBackgroundBuffer;
|
||||
extern int gPerkDialogCurrentLine;
|
||||
extern int gPerkDialogPreviousCurrentLine;
|
||||
extern int gCharacterEditorUnspentSkillPointsBackup;
|
||||
extern int gCharacterEditorLastLevel;
|
||||
extern int gCharacterEditorOldFont;
|
||||
extern int gCharacterEditorKillsCount;
|
||||
extern CacheEntry* gCharacterEditorWindowBackgroundHandle;
|
||||
extern int gCharacterEditorHitPointsBackup;
|
||||
extern int gCharacterEditorMouseY;
|
||||
extern int gCharacterEditorMouseX;
|
||||
extern int characterEditorSelectedItem;
|
||||
extern int characterEditorWindowSelectedFolder;
|
||||
extern int _frstc_draw1;
|
||||
extern int _crow;
|
||||
extern int _frstc_draw2;
|
||||
extern int _perk_back[PERK_COUNT];
|
||||
extern bool gCharacterEditorCardDrawn;
|
||||
extern int gPerkDialogTopLine;
|
||||
extern bool gPerkDialogCardDrawn;
|
||||
extern int gCharacterEditorPerksBackup[PERK_COUNT];
|
||||
extern unsigned int _repFtime;
|
||||
extern unsigned int _frame_time;
|
||||
extern int _old_tags;
|
||||
extern int _last_level_back;
|
||||
extern int gCharacterEditorOldTaggedSkillCount;
|
||||
extern int gCharacterEditorLastLevelBackup;
|
||||
extern bool gCharacterEditorIsCreationMode;
|
||||
extern int _tag_skill_back[NUM_TAGGED_SKILLS];
|
||||
extern int _card_old_fid2;
|
||||
extern int _card_old_fid1;
|
||||
extern int _trait_back[3];
|
||||
extern int _trait_count;
|
||||
extern int _optrt_count;
|
||||
extern int _temp_trait[3];
|
||||
extern int _tagskill_count;
|
||||
extern int _temp_tag_skill[NUM_TAGGED_SKILLS];
|
||||
extern char _free_perk_back;
|
||||
extern unsigned char _free_perk;
|
||||
extern unsigned char _first_skill_list;
|
||||
extern int gCharacterEditorTaggedSkillsBackup[NUM_TAGGED_SKILLS];
|
||||
extern int gPerkDialogCardFrmId;
|
||||
extern int gCharacterEditorCardFrmId;
|
||||
extern int gCharacterEditorOptionalTraitsBackup[3];
|
||||
extern int gCharacterEditorTempTraitCount;
|
||||
extern int gPerkDialogOptionCount;
|
||||
extern int gCharacterEditorTempTraits[3];
|
||||
extern int gCharacterEditorTaggedSkillCount;
|
||||
extern int gCharacterEditorTempTaggedSkills[NUM_TAGGED_SKILLS];
|
||||
extern char gCharacterEditorHasFreePerkBackup;
|
||||
extern unsigned char gCharacterEditorHasFreePerk;
|
||||
extern unsigned char gCharacterEditorIsSkillsFirstDraw;
|
||||
|
||||
int _editor_design(bool isCreationMode);
|
||||
int characterEditorShow(bool isCreationMode);
|
||||
int characterEditorWindowInit();
|
||||
void characterEditorWindowFree();
|
||||
void _CharEditInit();
|
||||
void characterEditorInit();
|
||||
int _get_input_str(int win, int cancelKeyCode, char* text, int maxLength, int x, int y, int textColor, int backgroundColor, int flags);
|
||||
bool _isdoschar(int ch);
|
||||
char* _strmfe(char* dest, const char* name, const char* ext);
|
||||
void editorRenderFolders();
|
||||
void editorRenderPerks();
|
||||
int _kills_list_comp(const KillInfo* a, const KillInfo* b);
|
||||
int editorRenderKills();
|
||||
void characterEditorRenderBigNumber(int x, int y, int flags, int value, int previousValue, int windowHandle);
|
||||
void editorRenderPcStats();
|
||||
void editorRenderPrimaryStat(int stat, bool animate, int previousValue);
|
||||
void editorRenderGender();
|
||||
void editorRenderAge();
|
||||
void editorRenderName();
|
||||
void editorRenderSecondaryStats();
|
||||
void editorRenderSkills(int a1);
|
||||
void editorRenderDetails();
|
||||
void characterEditorDrawFolders();
|
||||
void characterEditorDrawPerksFolder();
|
||||
int characterEditorKillsCompare(const void* a1, const void* a2);
|
||||
int characterEditorDrawKillsFolder();
|
||||
void characterEditorDrawBigNumber(int x, int y, int flags, int value, int previousValue, int windowHandle);
|
||||
void characterEditorDrawPcStats();
|
||||
void characterEditorDrawPrimaryStat(int stat, bool animate, int previousValue);
|
||||
void characterEditorDrawGender();
|
||||
void characterEditorDrawAge();
|
||||
void characterEditorDrawName();
|
||||
void characterEditorDrawDerivedStats();
|
||||
void characterEditorDrawSkills(int a1);
|
||||
void characterEditorDrawCard();
|
||||
int characterEditorEditName();
|
||||
void _PrintName(unsigned char* buf, int a2);
|
||||
int characterEditorRunEditAgeDialog();
|
||||
void _PrintName(unsigned char* buf, int pitch);
|
||||
int characterEditorEditAge();
|
||||
void characterEditorEditGender();
|
||||
void characterEditorHandleIncDecPrimaryStat(int eventCode);
|
||||
int _OptionWindow();
|
||||
void characterEditorAdjustPrimaryStat(int eventCode);
|
||||
int characterEditorShowOptions();
|
||||
bool characterFileExists(const char* fname);
|
||||
int characterPrintToFile(const char* fileName);
|
||||
char* _AddSpaces(char* string, int length);
|
||||
char* _AddDots(char* string, int length);
|
||||
void _ResetScreen();
|
||||
void _RegInfoAreas();
|
||||
void _SavePlayer();
|
||||
void _RestorePlayer();
|
||||
void characterEditorResetScreen();
|
||||
void characterEditorRegisterInfoAreas();
|
||||
void characterEditorSavePlayer();
|
||||
void characterEditorRestorePlayer();
|
||||
char* _itostndn(int value, char* dest);
|
||||
int _DrawCard(int graphicId, const char* name, const char* attributes, char* description);
|
||||
void _FldrButton();
|
||||
void _InfoButton(int eventCode);
|
||||
void editorAdjustSkill(int a1);
|
||||
int characterEditorDrawCardWithOptions(int graphicId, const char* name, const char* attributes, char* description);
|
||||
void characterEditorHandleFolderButtonPressed();
|
||||
void characterEditorHandleInfoButtonPressed(int eventCode);
|
||||
void characterEditorHandleAdjustSkillButtonPressed(int a1);
|
||||
void characterEditorToggleTaggedSkill(int skill);
|
||||
void characterEditorWindowRenderTraits();
|
||||
void characterEditorDrawOptionalTraits();
|
||||
void characterEditorToggleOptionalTrait(int trait);
|
||||
void editorRenderKarma();
|
||||
int _editor_save(File* stream);
|
||||
int _editor_load(File* stream);
|
||||
void _editor_reset();
|
||||
int _UpdateLevel();
|
||||
void _RedrwDPrks();
|
||||
int editorSelectPerk();
|
||||
int _InputPDLoop(int count, void (*refreshProc)());
|
||||
int _ListDPerks();
|
||||
void _RedrwDMPrk();
|
||||
bool editorHandleMutate();
|
||||
void _RedrwDMTagSkl();
|
||||
bool editorHandleTag();
|
||||
void _ListNewTagSkills();
|
||||
int _ListMyTraits(int a1);
|
||||
int _name_sort_comp(const void* a1, const void* a2);
|
||||
int _DrawCard2(int frmId, const char* name, const char* rank, char* description);
|
||||
void characterEditorDrawKarmaFolder();
|
||||
int characterEditorSave(File* stream);
|
||||
int characterEditorLoad(File* stream);
|
||||
void characterEditorReset();
|
||||
int characterEditorUpdateLevel();
|
||||
void perkDialogRefreshPerks();
|
||||
int perkDialogShow();
|
||||
int perkDialogHandleInput(int count, void (*refreshProc)());
|
||||
int perkDialogDrawPerks();
|
||||
void perkDialogRefreshTraits();
|
||||
bool perkDialogHandleMutatePerk();
|
||||
void perkDialogRefreshSkills();
|
||||
bool perkDialogHandleTagPerk();
|
||||
void perkDialogDrawSkills();
|
||||
int perkDialogDrawTraits(int a1);
|
||||
int perkDialogOptionCompare(const void* a1, const void* a2);
|
||||
int perkDialogDrawCard(int frmId, const char* name, const char* rank, char* description);
|
||||
void _pop_perks();
|
||||
int _is_supper_bonus();
|
||||
int _folder_init();
|
||||
void _folder_scroll(int direction);
|
||||
void _folder_clear();
|
||||
int _folder_print_seperator(const char* string);
|
||||
bool _folder_print_line(const char* string);
|
||||
bool editorDrawKillsEntry(const char* name, int kills);
|
||||
int characterEditorFolderViewInit();
|
||||
void characterEditorFolderViewScroll(int direction);
|
||||
void characterEditorFolderViewClear();
|
||||
int characterEditorFolderViewDrawHeading(const char* string);
|
||||
bool characterEditorFolderViewDrawString(const char* string);
|
||||
bool characterEditorFolderViewDrawKillsEntry(const char* name, int kills);
|
||||
int karmaInit();
|
||||
void karmaFree();
|
||||
int karmaEntryCompare(const void* a1, const void* a2);
|
||||
|
@ -311,4 +313,8 @@ int genericReputationInit();
|
|||
void genericReputationFree();
|
||||
int genericReputationCompare(const void* a1, const void* a2);
|
||||
|
||||
void customKarmaFolderInit();
|
||||
void customKarmaFolderFree();
|
||||
int customKarmaFolderGetFrmId();
|
||||
|
||||
#endif /* CHARACTER_EDITOR_H */
|
||||
|
|
|
@ -179,7 +179,7 @@ int characterSelectorOpen()
|
|||
case KEY_UPPERCASE_C:
|
||||
case KEY_LOWERCASE_C:
|
||||
_ResetPlayer();
|
||||
if (_editor_design(1) == 0) {
|
||||
if (characterEditorShow(1) == 0) {
|
||||
rc = 2;
|
||||
done = true;
|
||||
}
|
||||
|
@ -187,7 +187,7 @@ int characterSelectorOpen()
|
|||
break;
|
||||
case KEY_UPPERCASE_M:
|
||||
case KEY_LOWERCASE_M:
|
||||
if (!_editor_design(1)) {
|
||||
if (!characterEditorShow(1)) {
|
||||
rc = 2;
|
||||
done = true;
|
||||
}
|
||||
|
|
|
@ -354,7 +354,7 @@ void _setMixTableColor(int a1)
|
|||
}
|
||||
|
||||
// 0x4C78E4
|
||||
bool colorPaletteLoad(char* path)
|
||||
bool colorPaletteLoad(const char* path)
|
||||
{
|
||||
if (gColorFileNameMangler != NULL) {
|
||||
path = gColorFileNameMangler(path);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef char*(ColorFileNameManger)(char*);
|
||||
typedef const char*(ColorFileNameManger)(const char*);
|
||||
typedef void(ColorTransitionCallback)();
|
||||
|
||||
typedef int(ColorPaletteFileOpenProc)(const char* path, int mode);
|
||||
|
@ -54,7 +54,7 @@ void _setSystemPaletteEntries(unsigned char* a1, int a2, int a3);
|
|||
void _setIntensityTableColor(int a1);
|
||||
void _setIntensityTables();
|
||||
void _setMixTableColor(int a1);
|
||||
bool colorPaletteLoad(char* path);
|
||||
bool colorPaletteLoad(const char* path);
|
||||
char* _colorError();
|
||||
void _buildBlendTable(unsigned char* ptr, unsigned char ch);
|
||||
void _rebuildColorBlendTables();
|
||||
|
|
|
@ -2542,7 +2542,7 @@ void _combat_update_critter_outline_for_los(Object* critter, bool a2)
|
|||
} else {
|
||||
int v7 = objectGetDistanceBetween(gDude, critter);
|
||||
int v8 = critterGetStat(gDude, STAT_PERCEPTION) * 5;
|
||||
if ((critter->flags & OBJECT_FLAG_0x20000) != 0) {
|
||||
if ((critter->flags & OBJECT_TRANS_GLASS) != 0) {
|
||||
v8 /= 2;
|
||||
}
|
||||
|
||||
|
@ -3382,7 +3382,7 @@ bool _check_ranged_miss(Attack* attack)
|
|||
while (curr != to) {
|
||||
_make_straight_path_func(attack->attacker, curr, to, NULL, &critter, 32, _obj_shoot_blocking_at);
|
||||
if (critter != NULL) {
|
||||
if ((critter->flags & OBJECT_FLAG_0x80000000) == 0) {
|
||||
if ((critter->flags & OBJECT_SHOOT_THRU) == 0) {
|
||||
if ((critter->fid & 0xF000000) >> 24 != OBJ_TYPE_CRITTER) {
|
||||
roll = ROLL_SUCCESS;
|
||||
break;
|
||||
|
@ -3412,7 +3412,7 @@ bool _check_ranged_miss(Attack* attack)
|
|||
|
||||
attack->defenderHitLocation = HIT_LOCATION_TORSO;
|
||||
|
||||
if (roll < ROLL_SUCCESS || critter == NULL || (critter->flags & OBJECT_FLAG_0x80000000) == 0) {
|
||||
if (roll < ROLL_SUCCESS || critter == NULL || (critter->flags & OBJECT_SHOOT_THRU) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -3747,7 +3747,7 @@ int attackCompute(Attack* attack)
|
|||
v25 = _obj_blocking_at(NULL, attack->tile, attack->defender->elevation);
|
||||
}
|
||||
|
||||
if (v25 != NULL && (v25->flags & OBJECT_FLAG_0x80000000) == 0) {
|
||||
if (v25 != NULL && (v25->flags & OBJECT_SHOOT_THRU) == 0) {
|
||||
attack->attackerFlags |= DAM_HIT;
|
||||
attack->defender = v25;
|
||||
attackComputeDamage(attack, 1, 2);
|
||||
|
@ -3834,7 +3834,7 @@ void _compute_explosion_on_extras(Attack* attack, int a2, int a3, int a4)
|
|||
if (v11 != NULL
|
||||
&& (v11->fid & 0xF000000) >> 24 == OBJ_TYPE_CRITTER
|
||||
&& (v11->data.critter.combat.results & DAM_DEAD) == 0
|
||||
&& (v11->flags & OBJECT_FLAG_0x80000000) == 0
|
||||
&& (v11->flags & OBJECT_SHOOT_THRU) == 0
|
||||
&& !_combat_is_shot_blocked(v11, v11->tile, tile, NULL, NULL)) {
|
||||
if (v11 == attack->attacker) {
|
||||
attack->attackerFlags &= ~DAM_HIT;
|
||||
|
@ -4224,7 +4224,7 @@ int attackDetermineToHit(Object* attacker, int tile, Object* defender, int hitLo
|
|||
accuracy += _hit_location_penalty[hitLocation] / 2;
|
||||
}
|
||||
|
||||
if (defender != NULL && (defender->flags & OBJECT_FLAG_0x800) != 0) {
|
||||
if (defender != NULL && (defender->flags & OBJECT_MULTIHEX) != 0) {
|
||||
accuracy += 15;
|
||||
}
|
||||
|
||||
|
@ -4406,7 +4406,7 @@ void attackComputeDamage(Attack* attack, int ammoQuantity, int a3)
|
|||
}
|
||||
|
||||
if (knockbackDistancePtr != NULL
|
||||
&& (critter->flags & OBJECT_FLAG_0x800) == 0
|
||||
&& (critter->flags & OBJECT_MULTIHEX) == 0
|
||||
&& (damageType == DAMAGE_TYPE_EXPLOSION || attack->weapon == NULL || weaponGetAttackTypeForHitMode(attack->weapon, attack->hitMode) == ATTACK_TYPE_MELEE)
|
||||
&& (critter->pid >> 24) == OBJ_TYPE_CRITTER
|
||||
&& _critter_flag_check(critter->pid, 0x4000) == 0) {
|
||||
|
@ -5686,7 +5686,7 @@ bool _combat_is_shot_blocked(Object* a1, int from, int to, Object* a4, int* a5)
|
|||
if ((obstacle->data.critter.combat.results & (DAM_DEAD | DAM_KNOCKED_DOWN | DAM_KNOCKED_OUT)) == 0) {
|
||||
*a5 += 1;
|
||||
|
||||
if ((obstacle->flags & OBJECT_FLAG_0x800) != 0) {
|
||||
if ((obstacle->flags & OBJECT_MULTIHEX) != 0) {
|
||||
*a5 += 1;
|
||||
}
|
||||
}
|
||||
|
@ -5694,7 +5694,7 @@ bool _combat_is_shot_blocked(Object* a1, int from, int to, Object* a4, int* a5)
|
|||
}
|
||||
}
|
||||
|
||||
if ((obstacle->flags & OBJECT_FLAG_0x800) != 0) {
|
||||
if ((obstacle->flags & OBJECT_MULTIHEX) != 0) {
|
||||
int rotation = tileGetRotationTo(current, to);
|
||||
current = tileGetTileInDirection(current, rotation, 1);
|
||||
} else {
|
||||
|
|
|
@ -2143,13 +2143,13 @@ int _ai_move_steps_closer(Object* a1, Object* a2, int actionPoints, int a4)
|
|||
}
|
||||
|
||||
if (actionPoints >= critterGetStat(a1, STAT_MAXIMUM_ACTION_POINTS) / 2 && artCritterFidShouldRun(a1->fid)) {
|
||||
if ((a2->flags & OBJECT_FLAG_0x800) != 0) {
|
||||
if ((a2->flags & OBJECT_MULTIHEX) != 0) {
|
||||
reg_anim_obj_run_to_obj(a1, a2, actionPoints, 0);
|
||||
} else {
|
||||
reg_anim_obj_run_to_tile(a1, tile, a1->elevation, actionPoints, 0);
|
||||
}
|
||||
} else {
|
||||
if ((a2->flags & OBJECT_FLAG_0x800) != 0) {
|
||||
if ((a2->flags & OBJECT_MULTIHEX) != 0) {
|
||||
reg_anim_obj_move_to_obj(a1, a2, actionPoints, 0);
|
||||
} else {
|
||||
reg_anim_obj_move_to_tile(a1, tile, a1->elevation, actionPoints, 0);
|
||||
|
@ -3198,7 +3198,7 @@ bool objectCanHearObject(Object* a1, Object* a2)
|
|||
int sneak = skillGetValue(a2, SKILL_SNEAK);
|
||||
if (_can_see(a1, a2)) {
|
||||
int v8 = perception * 5;
|
||||
if ((a2->flags & OBJECT_FLAG_0x20000) != 0) {
|
||||
if ((a2->flags & OBJECT_TRANS_GLASS) != 0) {
|
||||
v8 /= 2;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include "platform_compat.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -178,8 +180,8 @@ bool configSetString(Config* config, const char* sectionKey, const char* key, co
|
|||
return true;
|
||||
}
|
||||
|
||||
// 0x42C05C
|
||||
bool configGetInt(Config* config, const char* sectionKey, const char* key, int* valuePtr)
|
||||
// 0x42C05C customized: atoi() replaced with strtol()
|
||||
bool configGetInt(Config* config, const char* sectionKey, const char* key, int* valuePtr, unsigned char base /* = 0 */ )
|
||||
{
|
||||
if (valuePtr == NULL) {
|
||||
return false;
|
||||
|
@ -190,7 +192,13 @@ bool configGetInt(Config* config, const char* sectionKey, const char* key, int*
|
|||
return false;
|
||||
}
|
||||
|
||||
*valuePtr = atoi(stringValue);
|
||||
char* end;
|
||||
errno = 0;
|
||||
long l = strtol(stringValue, &end, base); // see https://stackoverflow.com/a/6154614
|
||||
if (((errno == ERANGE && 1 == LONG_MAX) || l > INT_MAX) || ((errno == ERANGE && l == LONG_MIN) || l < INT_MIN) || (*stringValue == '\0' || *end != '\0'))
|
||||
return false;
|
||||
|
||||
*valuePtr = l;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ void configFree(Config* config);
|
|||
bool configParseCommandLineArguments(Config* config, int argc, char** argv);
|
||||
bool configGetString(Config* config, const char* sectionKey, const char* key, char** valuePtr);
|
||||
bool configSetString(Config* config, const char* sectionKey, const char* key, const char* value);
|
||||
bool configGetInt(Config* config, const char* sectionKey, const char* key, int* valuePtr);
|
||||
bool configGetInt(Config* config, const char* sectionKey, const char* key, int* valuePtr, unsigned char base = 0);
|
||||
bool configGetIntList(Config* config, const char* section, const char* key, int* arr, int count);
|
||||
bool configSetInt(Config* config, const char* sectionKey, const char* key, int value);
|
||||
bool configRead(Config* config, const char* filePath, bool isDb);
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <SDL.h>
|
||||
#if _WIN32
|
||||
#include <SDL_syswm.h>
|
||||
#endif
|
||||
|
||||
// NOT USED.
|
||||
void (*_idle_func)() = NULL;
|
||||
|
@ -4276,9 +4278,11 @@ void _kb_init_lock_status()
|
|||
gModifierKeysState |= MODIFIER_KEY_STATE_NUM_LOCK;
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 18)
|
||||
if ((SDL_GetModState() & KMOD_SCROLL) != 0) {
|
||||
gModifierKeysState |= MODIFIER_KEY_STATE_SCROLL_LOCK;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Get pointer to pending key event from the queue but do not consume it.
|
||||
|
|
|
@ -976,7 +976,7 @@ int gcdLoad(const char* path)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (fileReadInt32(stream, &characterEditorRemainingCharacterPoints) == -1) {
|
||||
if (fileReadInt32(stream, &gCharacterEditorRemainingCharacterPoints) == -1) {
|
||||
fileClose(stream);
|
||||
return -1;
|
||||
}
|
||||
|
@ -1048,7 +1048,7 @@ int gcdSave(const char* path)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (fileWriteInt32(stream, characterEditorRemainingCharacterPoints) == -1) {
|
||||
if (fileWriteInt32(stream, gCharacterEditorRemainingCharacterPoints) == -1) {
|
||||
fileClose(stream);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -650,7 +650,12 @@ int fileNameListInit(const char* pattern, char*** fileNameListPtr, int a3, int a
|
|||
}
|
||||
|
||||
if (!v2) {
|
||||
sprintf(xlist->fileNames[index], "%s%s", fileName, extension);
|
||||
// NOTE: Quick and dirty fix to buffer overflow. See RE to
|
||||
// understand the problem.
|
||||
char path[COMPAT_MAX_PATH];
|
||||
sprintf(path, "%s%s", fileName, extension);
|
||||
free(xlist->fileNames[length]);
|
||||
xlist->fileNames[length] = strdup(path);
|
||||
length++;
|
||||
}
|
||||
}
|
||||
|
|
855
src/dbox.cc
855
src/dbox.cc
|
@ -1,6 +1,7 @@
|
|||
#include "dbox.h"
|
||||
|
||||
#include "art.h"
|
||||
#include "character_editor.h"
|
||||
#include "color.h"
|
||||
#include "core.h"
|
||||
#include "debug.h"
|
||||
|
@ -18,6 +19,45 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#define FILE_DIALOG_LINE_COUNT 12
|
||||
|
||||
#define FILE_DIALOG_DOUBLE_CLICK_DELAY 32
|
||||
|
||||
#define LOAD_FILE_DIALOG_DONE_BUTTON_X 58
|
||||
#define LOAD_FILE_DIALOG_DONE_BUTTON_Y 187
|
||||
|
||||
#define LOAD_FILE_DIALOG_DONE_LABEL_X 79
|
||||
#define LOAD_FILE_DIALOG_DONE_LABEL_Y 187
|
||||
|
||||
#define LOAD_FILE_DIALOG_CANCEL_BUTTON_X 163
|
||||
#define LOAD_FILE_DIALOG_CANCEL_BUTTON_Y 187
|
||||
|
||||
#define LOAD_FILE_DIALOG_CANCEL_LABEL_X 182
|
||||
#define LOAD_FILE_DIALOG_CANCEL_LABEL_Y 187
|
||||
|
||||
#define SAVE_FILE_DIALOG_DONE_BUTTON_X 58
|
||||
#define SAVE_FILE_DIALOG_DONE_BUTTON_Y 214
|
||||
|
||||
#define SAVE_FILE_DIALOG_DONE_LABEL_X 79
|
||||
#define SAVE_FILE_DIALOG_DONE_LABEL_Y 213
|
||||
|
||||
#define SAVE_FILE_DIALOG_CANCEL_BUTTON_X 163
|
||||
#define SAVE_FILE_DIALOG_CANCEL_BUTTON_Y 214
|
||||
|
||||
#define SAVE_FILE_DIALOG_CANCEL_LABEL_X 182
|
||||
#define SAVE_FILE_DIALOG_CANCEL_LABEL_Y 213
|
||||
|
||||
#define FILE_DIALOG_TITLE_X 49
|
||||
#define FILE_DIALOG_TITLE_Y 16
|
||||
|
||||
#define FILE_DIALOG_SCROLL_BUTTON_X 36
|
||||
#define FILE_DIALOG_SCROLL_BUTTON_Y 44
|
||||
|
||||
#define FILE_DIALOG_FILE_LIST_X 55
|
||||
#define FILE_DIALOG_FILE_LIST_Y 49
|
||||
#define FILE_DIALOG_FILE_LIST_WIDTH 190
|
||||
#define FILE_DIALOG_FILE_LIST_HEIGHT 124
|
||||
|
||||
// 0x5108C8
|
||||
const int gDialogBoxBackgroundFrmIds[DIALOG_TYPE_COUNT] = {
|
||||
218, // MEDIALOG.FRM - Medium generic dialog box
|
||||
|
@ -55,7 +95,7 @@ const int _dblines[DIALOG_TYPE_COUNT] = {
|
|||
};
|
||||
|
||||
// 0x510900
|
||||
int _flgids[7] = {
|
||||
int gLoadFileDialogFrmIds[FILE_DIALOG_FRM_COUNT] = {
|
||||
224, // loadbox.frm - character editor
|
||||
8, // lilredup.frm - little red button up
|
||||
9, // lilreddn.frm - little red button down
|
||||
|
@ -66,7 +106,7 @@ int _flgids[7] = {
|
|||
};
|
||||
|
||||
// 0x51091C
|
||||
int _flgids2[7] = {
|
||||
int gSaveFileDialogFrmIds[FILE_DIALOG_FRM_COUNT] = {
|
||||
225, // savebox.frm - character editor
|
||||
8, // lilredup.frm - little red button up
|
||||
9, // lilreddn.frm - little red button down
|
||||
|
@ -451,17 +491,32 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i
|
|||
return rc;
|
||||
}
|
||||
|
||||
// 0x41EA78
|
||||
int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLength, int x, int y, int flags)
|
||||
// 0x41DE90
|
||||
int showLoadFileDialog(char *title, char** fileList, char* dest, int fileListLength, int x, int y, int flags)
|
||||
{
|
||||
int oldFont = fontGetCurrent();
|
||||
|
||||
unsigned char* frmBuffers[7];
|
||||
CacheEntry* frmHandles[7];
|
||||
Size frmSizes[7];
|
||||
bool isScrollable = false;
|
||||
if (fileListLength > FILE_DIALOG_LINE_COUNT) {
|
||||
isScrollable = true;
|
||||
}
|
||||
|
||||
for (int index = 0; index < 7; index++) {
|
||||
int fid = buildFid(6, _flgids2[index], 0, 0, 0);
|
||||
int selectedFileIndex = 0;
|
||||
int pageOffset = 0;
|
||||
int maxPageOffset = fileListLength - (FILE_DIALOG_LINE_COUNT + 1);
|
||||
if (maxPageOffset < 0) {
|
||||
maxPageOffset = fileListLength - 1;
|
||||
if (maxPageOffset < 0) {
|
||||
maxPageOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char* frmBuffers[FILE_DIALOG_FRM_COUNT];
|
||||
CacheEntry* frmHandles[FILE_DIALOG_FRM_COUNT];
|
||||
Size frmSizes[FILE_DIALOG_FRM_COUNT];
|
||||
|
||||
for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
|
||||
int fid = buildFid(6, gLoadFileDialogFrmIds[index], 0, 0, 0);
|
||||
frmBuffers[index] = artLockFrameDataReturningSize(fid, &(frmHandles[index]), &(frmSizes[index].width), &(frmSizes[index].height));
|
||||
if (frmBuffers[index] == NULL) {
|
||||
while (--index >= 0) {
|
||||
|
@ -471,16 +526,23 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
|
|||
}
|
||||
}
|
||||
|
||||
int win = windowCreate(x, y, frmSizes[0].width, frmSizes[0].height, 256, WINDOW_FLAG_0x10 | WINDOW_FLAG_0x04);
|
||||
|
||||
int backgroundWidth = frmSizes[FILE_DIALOG_FRM_BACKGROUND].width;
|
||||
int backgroundHeight = frmSizes[FILE_DIALOG_FRM_BACKGROUND].height;
|
||||
|
||||
// Maintain original position in original resolution, otherwise center it.
|
||||
if (screenGetWidth() != 640) x = (screenGetWidth() - backgroundWidth) / 2;
|
||||
if (screenGetHeight() != 480) y = (screenGetHeight() - backgroundHeight) / 2;
|
||||
int win = windowCreate(x, y, backgroundWidth, backgroundHeight, 256, WINDOW_FLAG_0x10 | WINDOW_FLAG_0x04);
|
||||
if (win == -1) {
|
||||
for (int index = 0; index < 7; index++) {
|
||||
for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
|
||||
artUnlock(frmHandles[index]);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned char* windowBuffer = windowGetBuffer(win);
|
||||
memcpy(windowBuffer, frmBuffers[0], frmSizes[0].width * frmSizes[0].height);
|
||||
memcpy(windowBuffer, frmBuffers[FILE_DIALOG_FRM_BACKGROUND], backgroundWidth * backgroundHeight);
|
||||
|
||||
MessageList messageList;
|
||||
MessageListItem messageListItem;
|
||||
|
@ -488,7 +550,7 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
|
|||
if (!messageListInit(&messageList)) {
|
||||
windowDestroy(win);
|
||||
|
||||
for (int index = 0; index < 7; index++) {
|
||||
for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
|
||||
artUnlock(frmHandles[index]);
|
||||
}
|
||||
|
||||
|
@ -501,7 +563,7 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
|
|||
if (!messageListLoad(&messageList, path)) {
|
||||
windowDestroy(win);
|
||||
|
||||
for (int index = 0; index < 7; index++) {
|
||||
for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
|
||||
artUnlock(frmHandles[index]);
|
||||
}
|
||||
|
||||
|
@ -512,23 +574,23 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
|
|||
|
||||
// DONE
|
||||
const char* done = getmsg(&messageList, &messageListItem, 100);
|
||||
fontDrawText(windowBuffer + frmSizes[0].width * 213 + 79, done, frmSizes[0].width, frmSizes[0].width, _colorTable[18979]);
|
||||
fontDrawText(windowBuffer + LOAD_FILE_DIALOG_DONE_LABEL_Y * backgroundWidth + LOAD_FILE_DIALOG_DONE_LABEL_X, done, backgroundWidth, backgroundWidth, _colorTable[18979]);
|
||||
|
||||
// CANCEL
|
||||
const char* cancel = getmsg(&messageList, &messageListItem, 103);
|
||||
fontDrawText(windowBuffer + frmSizes[0].width * 213 + 182, cancel, frmSizes[0].width, frmSizes[0].width, _colorTable[18979]);
|
||||
fontDrawText(windowBuffer + LOAD_FILE_DIALOG_CANCEL_LABEL_Y * backgroundWidth + LOAD_FILE_DIALOG_CANCEL_LABEL_X, cancel, backgroundWidth, backgroundWidth, _colorTable[18979]);
|
||||
|
||||
int doneBtn = buttonCreate(win,
|
||||
58,
|
||||
214,
|
||||
frmSizes[2].width,
|
||||
frmSizes[2].height,
|
||||
LOAD_FILE_DIALOG_DONE_BUTTON_X,
|
||||
LOAD_FILE_DIALOG_DONE_BUTTON_Y,
|
||||
frmSizes[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].width,
|
||||
frmSizes[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].height,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
500,
|
||||
frmBuffers[1],
|
||||
frmBuffers[2],
|
||||
frmBuffers[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_NORMAL],
|
||||
frmBuffers[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED],
|
||||
NULL,
|
||||
BUTTON_FLAG_TRANSPARENT);
|
||||
if (doneBtn != -1) {
|
||||
|
@ -536,16 +598,16 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
|
|||
}
|
||||
|
||||
int cancelBtn = buttonCreate(win,
|
||||
163,
|
||||
214,
|
||||
frmSizes[2].width,
|
||||
frmSizes[2].height,
|
||||
LOAD_FILE_DIALOG_CANCEL_BUTTON_X,
|
||||
LOAD_FILE_DIALOG_CANCEL_BUTTON_Y,
|
||||
frmSizes[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].width,
|
||||
frmSizes[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].height,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
501,
|
||||
frmBuffers[1],
|
||||
frmBuffers[2],
|
||||
frmBuffers[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_NORMAL],
|
||||
frmBuffers[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED],
|
||||
NULL,
|
||||
BUTTON_FLAG_TRANSPARENT);
|
||||
if (cancelBtn != -1) {
|
||||
|
@ -553,16 +615,16 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
|
|||
}
|
||||
|
||||
int scrollUpBtn = buttonCreate(win,
|
||||
36,
|
||||
44,
|
||||
frmSizes[6].width,
|
||||
frmSizes[6].height,
|
||||
FILE_DIALOG_SCROLL_BUTTON_X,
|
||||
FILE_DIALOG_SCROLL_BUTTON_Y,
|
||||
frmSizes[FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED].width,
|
||||
frmSizes[FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED].height,
|
||||
-1,
|
||||
505,
|
||||
506,
|
||||
505,
|
||||
frmBuffers[5],
|
||||
frmBuffers[6],
|
||||
frmBuffers[FILE_DIALOG_FRM_SCROLL_UP_ARROW_NORMAL],
|
||||
frmBuffers[FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED],
|
||||
NULL,
|
||||
BUTTON_FLAG_TRANSPARENT);
|
||||
if (scrollUpBtn != -1) {
|
||||
|
@ -570,16 +632,16 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
|
|||
}
|
||||
|
||||
int scrollDownButton = buttonCreate(win,
|
||||
36,
|
||||
44 + frmSizes[6].height,
|
||||
frmSizes[4].width,
|
||||
frmSizes[4].height,
|
||||
FILE_DIALOG_SCROLL_BUTTON_X,
|
||||
FILE_DIALOG_SCROLL_BUTTON_Y + frmSizes[FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED].height,
|
||||
frmSizes[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_PRESSED].width,
|
||||
frmSizes[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_PRESSED].height,
|
||||
-1,
|
||||
503,
|
||||
504,
|
||||
503,
|
||||
frmBuffers[3],
|
||||
frmBuffers[4],
|
||||
frmBuffers[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_NORMAL],
|
||||
frmBuffers[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_PRESSED],
|
||||
NULL,
|
||||
BUTTON_FLAG_TRANSPARENT);
|
||||
if (scrollUpBtn != -1) {
|
||||
|
@ -588,10 +650,10 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
|
|||
|
||||
buttonCreate(
|
||||
win,
|
||||
55,
|
||||
49,
|
||||
190,
|
||||
124,
|
||||
FILE_DIALOG_FILE_LIST_X,
|
||||
FILE_DIALOG_FILE_LIST_Y,
|
||||
FILE_DIALOG_FILE_LIST_WIDTH,
|
||||
FILE_DIALOG_FILE_LIST_HEIGHT,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
|
@ -601,25 +663,714 @@ int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLen
|
|||
NULL,
|
||||
0);
|
||||
|
||||
if (a1 != NULL) {
|
||||
fontDrawText(windowBuffer + frmSizes[0].width * 16 + 49, a1, frmSizes[0].width, frmSizes[0].width, _colorTable[18979]);
|
||||
if (title != NULL) {
|
||||
fontDrawText(windowBuffer + backgroundWidth * FILE_DIALOG_TITLE_Y + FILE_DIALOG_TITLE_X, title, backgroundWidth, backgroundWidth, _colorTable[18979]);
|
||||
}
|
||||
|
||||
fontSetCurrent(101);
|
||||
|
||||
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
|
||||
windowRefresh(win);
|
||||
|
||||
int doubleClickSelectedFileIndex = -2;
|
||||
int doubleClickTimer = FILE_DIALOG_DOUBLE_CLICK_DELAY;
|
||||
|
||||
int rc = -1;
|
||||
while (rc == -1) {
|
||||
unsigned int tick = _get_time();
|
||||
int keyCode = _get_input();
|
||||
int scrollDirection = FILE_DIALOG_SCROLL_DIRECTION_NONE;
|
||||
int scrollCounter = 0;
|
||||
bool isScrolling = false;
|
||||
|
||||
if (keyCode == 500) {
|
||||
if (fileListLength != 0) {
|
||||
strncpy(dest, fileList[selectedFileIndex + pageOffset], 16);
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = 1;
|
||||
}
|
||||
} else if (keyCode == 501 || keyCode == KEY_ESCAPE) {
|
||||
rc = 1;
|
||||
} else if (keyCode == 502 && fileListLength != 0) {
|
||||
int mouseX;
|
||||
int mouseY;
|
||||
mouseGetPosition(&mouseX, &mouseY);
|
||||
|
||||
int selectedLine = (mouseY - y - FILE_DIALOG_FILE_LIST_Y) / fontGetLineHeight();
|
||||
if (selectedLine - 1 < 0) {
|
||||
selectedLine = 0;
|
||||
}
|
||||
|
||||
if (isScrollable || selectedLine < fileListLength) {
|
||||
if (selectedLine >= FILE_DIALOG_LINE_COUNT) {
|
||||
selectedLine = FILE_DIALOG_LINE_COUNT - 1;
|
||||
}
|
||||
} else {
|
||||
selectedLine = fileListLength - 1;
|
||||
}
|
||||
|
||||
selectedFileIndex = selectedLine;
|
||||
if (selectedFileIndex == doubleClickSelectedFileIndex) {
|
||||
soundPlayFile("ib1p1xx1");
|
||||
strncpy(dest, fileList[selectedFileIndex + pageOffset], 16);
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
doubleClickSelectedFileIndex = selectedFileIndex;
|
||||
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
|
||||
} else if (keyCode == 506) {
|
||||
scrollDirection = FILE_DIALOG_SCROLL_DIRECTION_UP;
|
||||
} else if (keyCode == 504) {
|
||||
scrollDirection = FILE_DIALOG_SCROLL_DIRECTION_DOWN;
|
||||
} else {
|
||||
switch (keyCode) {
|
||||
case KEY_ARROW_UP:
|
||||
pageOffset--;
|
||||
if (pageOffset < 0) {
|
||||
selectedFileIndex--;
|
||||
if (selectedFileIndex < 0) {
|
||||
selectedFileIndex = 0;
|
||||
}
|
||||
pageOffset = 0;
|
||||
}
|
||||
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
|
||||
doubleClickSelectedFileIndex = -2;
|
||||
break;
|
||||
case KEY_ARROW_DOWN:
|
||||
if (isScrollable) {
|
||||
pageOffset++;
|
||||
// FIXME: Should be >= maxPageOffset (as in save dialog).
|
||||
// Otherwise out of bounds index is considered selected.
|
||||
if (pageOffset > maxPageOffset) {
|
||||
selectedFileIndex++;
|
||||
// FIXME: Should be >= FILE_DIALOG_LINE_COUNT (as in
|
||||
// save dialog). Otherwise out of bounds index is
|
||||
// considered selected.
|
||||
if (selectedFileIndex > FILE_DIALOG_LINE_COUNT) {
|
||||
selectedFileIndex = FILE_DIALOG_LINE_COUNT - 1;
|
||||
}
|
||||
pageOffset = maxPageOffset;
|
||||
}
|
||||
} else {
|
||||
selectedFileIndex++;
|
||||
if (selectedFileIndex > maxPageOffset) {
|
||||
selectedFileIndex = maxPageOffset;
|
||||
}
|
||||
}
|
||||
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
|
||||
doubleClickSelectedFileIndex = -2;
|
||||
break;
|
||||
case KEY_HOME:
|
||||
selectedFileIndex = 0;
|
||||
pageOffset = 0;
|
||||
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
|
||||
doubleClickSelectedFileIndex = -2;
|
||||
break;
|
||||
case KEY_END:
|
||||
if (isScrollable) {
|
||||
selectedFileIndex = FILE_DIALOG_LINE_COUNT - 1;
|
||||
pageOffset = maxPageOffset;
|
||||
} else {
|
||||
selectedFileIndex = maxPageOffset;
|
||||
pageOffset = 0;
|
||||
}
|
||||
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
|
||||
doubleClickSelectedFileIndex = -2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (scrollDirection != FILE_DIALOG_SCROLL_DIRECTION_NONE) {
|
||||
unsigned int scrollDelay = 4;
|
||||
doubleClickSelectedFileIndex = -2;
|
||||
while (1) {
|
||||
unsigned int scrollTick = _get_time();
|
||||
scrollCounter += 1;
|
||||
if ((!isScrolling && scrollCounter == 1) || (isScrolling && scrollCounter > 14.4)) {
|
||||
isScrolling = true;
|
||||
|
||||
if (scrollCounter > 14.4) {
|
||||
scrollDelay += 1;
|
||||
if (scrollDelay > 24) {
|
||||
scrollDelay = 24;
|
||||
}
|
||||
}
|
||||
|
||||
if (scrollDirection == FILE_DIALOG_SCROLL_DIRECTION_UP) {
|
||||
pageOffset--;
|
||||
if (pageOffset < 0) {
|
||||
selectedFileIndex--;
|
||||
if (selectedFileIndex < 0) {
|
||||
selectedFileIndex = 0;
|
||||
}
|
||||
pageOffset = 0;
|
||||
}
|
||||
} else {
|
||||
if (isScrollable) {
|
||||
pageOffset++;
|
||||
if (pageOffset > maxPageOffset) {
|
||||
selectedFileIndex++;
|
||||
if (selectedFileIndex >= FILE_DIALOG_LINE_COUNT) {
|
||||
selectedFileIndex = FILE_DIALOG_LINE_COUNT - 1;
|
||||
}
|
||||
pageOffset = maxPageOffset;
|
||||
}
|
||||
} else {
|
||||
selectedFileIndex++;
|
||||
if (selectedFileIndex > maxPageOffset) {
|
||||
selectedFileIndex = maxPageOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
|
||||
windowRefresh(win);
|
||||
}
|
||||
|
||||
unsigned int delay = (scrollCounter > 14.4) ? 1000 / scrollDelay : 1000 / 24;
|
||||
while (getTicksSince(scrollTick) < delay) {
|
||||
}
|
||||
|
||||
if (_game_user_wants_to_quit != 0) {
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
int keyCode = _get_input();
|
||||
if (keyCode == 505 || keyCode == 503) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
windowRefresh(win);
|
||||
|
||||
doubleClickTimer--;
|
||||
if (doubleClickTimer == 0) {
|
||||
doubleClickTimer = FILE_DIALOG_DOUBLE_CLICK_DELAY;
|
||||
doubleClickSelectedFileIndex = -2;
|
||||
}
|
||||
|
||||
while (getTicksSince(tick) < (1000 / 24)) {
|
||||
}
|
||||
}
|
||||
|
||||
if (_game_user_wants_to_quit) {
|
||||
rc = 1;
|
||||
}
|
||||
}
|
||||
|
||||
windowDestroy(win);
|
||||
|
||||
for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
|
||||
artUnlock(frmHandles[index]);
|
||||
}
|
||||
|
||||
messageListFree(&messageList);
|
||||
fontSetCurrent(oldFont);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
// 0x41EA78
|
||||
int showSaveFileDialog(char* title, char** fileList, char* dest, int fileListLength, int x, int y, int flags)
|
||||
{
|
||||
int oldFont = fontGetCurrent();
|
||||
|
||||
bool isScrollable = false;
|
||||
if (fileListLength > FILE_DIALOG_LINE_COUNT) {
|
||||
isScrollable = true;
|
||||
}
|
||||
|
||||
int selectedFileIndex = 0;
|
||||
int pageOffset = 0;
|
||||
int maxPageOffset = fileListLength - (FILE_DIALOG_LINE_COUNT + 1);
|
||||
if (maxPageOffset < 0) {
|
||||
maxPageOffset = fileListLength - 1;
|
||||
if (maxPageOffset < 0) {
|
||||
maxPageOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char* frmBuffers[FILE_DIALOG_FRM_COUNT];
|
||||
CacheEntry* frmHandles[FILE_DIALOG_FRM_COUNT];
|
||||
Size frmSizes[FILE_DIALOG_FRM_COUNT];
|
||||
|
||||
for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
|
||||
int fid = buildFid(6, gSaveFileDialogFrmIds[index], 0, 0, 0);
|
||||
frmBuffers[index] = artLockFrameDataReturningSize(fid, &(frmHandles[index]), &(frmSizes[index].width), &(frmSizes[index].height));
|
||||
if (frmBuffers[index] == NULL) {
|
||||
while (--index >= 0) {
|
||||
artUnlock(frmHandles[index]);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int backgroundWidth = frmSizes[FILE_DIALOG_FRM_BACKGROUND].width;
|
||||
int backgroundHeight = frmSizes[FILE_DIALOG_FRM_BACKGROUND].height;
|
||||
|
||||
// Maintain original position in original resolution, otherwise center it.
|
||||
if (screenGetWidth() != 640) x = (screenGetWidth() - backgroundWidth) / 2;
|
||||
if (screenGetHeight() != 480) y = (screenGetHeight() - backgroundHeight) / 2;
|
||||
int win = windowCreate(x, y, backgroundWidth, backgroundHeight, 256, WINDOW_FLAG_0x10 | WINDOW_FLAG_0x04);
|
||||
if (win == -1) {
|
||||
for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
|
||||
artUnlock(frmHandles[index]);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned char* windowBuffer = windowGetBuffer(win);
|
||||
memcpy(windowBuffer, frmBuffers[FILE_DIALOG_FRM_BACKGROUND], backgroundWidth * backgroundHeight);
|
||||
|
||||
MessageList messageList;
|
||||
MessageListItem messageListItem;
|
||||
|
||||
if (!messageListInit(&messageList)) {
|
||||
windowDestroy(win);
|
||||
|
||||
for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
|
||||
artUnlock(frmHandles[index]);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
char path[COMPAT_MAX_PATH];
|
||||
sprintf(path, "%s%s", asc_5186C8, "DBOX.MSG");
|
||||
|
||||
if (!messageListLoad(&messageList, path)) {
|
||||
windowDestroy(win);
|
||||
|
||||
for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
|
||||
artUnlock(frmHandles[index]);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
fontSetCurrent(103);
|
||||
|
||||
// DONE
|
||||
const char* done = getmsg(&messageList, &messageListItem, 100);
|
||||
fontDrawText(windowBuffer + backgroundWidth * SAVE_FILE_DIALOG_DONE_LABEL_Y + SAVE_FILE_DIALOG_DONE_LABEL_X, done, backgroundWidth, backgroundWidth, _colorTable[18979]);
|
||||
|
||||
// CANCEL
|
||||
const char* cancel = getmsg(&messageList, &messageListItem, 103);
|
||||
fontDrawText(windowBuffer + backgroundWidth * SAVE_FILE_DIALOG_CANCEL_LABEL_Y + SAVE_FILE_DIALOG_CANCEL_LABEL_X, cancel, backgroundWidth, backgroundWidth, _colorTable[18979]);
|
||||
|
||||
int doneBtn = buttonCreate(win,
|
||||
SAVE_FILE_DIALOG_DONE_BUTTON_X,
|
||||
SAVE_FILE_DIALOG_DONE_BUTTON_Y,
|
||||
frmSizes[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].width,
|
||||
frmSizes[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].height,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
500,
|
||||
frmBuffers[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_NORMAL],
|
||||
frmBuffers[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED],
|
||||
NULL,
|
||||
BUTTON_FLAG_TRANSPARENT);
|
||||
if (doneBtn != -1) {
|
||||
buttonSetCallbacks(doneBtn, _gsound_red_butt_press, _gsound_red_butt_release);
|
||||
}
|
||||
|
||||
int cancelBtn = buttonCreate(win,
|
||||
SAVE_FILE_DIALOG_CANCEL_BUTTON_X,
|
||||
SAVE_FILE_DIALOG_CANCEL_BUTTON_Y,
|
||||
frmSizes[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].width,
|
||||
frmSizes[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED].height,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
501,
|
||||
frmBuffers[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_NORMAL],
|
||||
frmBuffers[FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED],
|
||||
NULL,
|
||||
BUTTON_FLAG_TRANSPARENT);
|
||||
if (cancelBtn != -1) {
|
||||
buttonSetCallbacks(cancelBtn, _gsound_red_butt_press, _gsound_red_butt_release);
|
||||
}
|
||||
|
||||
int scrollUpBtn = buttonCreate(win,
|
||||
FILE_DIALOG_SCROLL_BUTTON_X,
|
||||
FILE_DIALOG_SCROLL_BUTTON_Y,
|
||||
frmSizes[FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED].width,
|
||||
frmSizes[FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED].height,
|
||||
-1,
|
||||
505,
|
||||
506,
|
||||
505,
|
||||
frmBuffers[FILE_DIALOG_FRM_SCROLL_UP_ARROW_NORMAL],
|
||||
frmBuffers[FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED],
|
||||
NULL,
|
||||
BUTTON_FLAG_TRANSPARENT);
|
||||
if (scrollUpBtn != -1) {
|
||||
buttonSetCallbacks(cancelBtn, _gsound_red_butt_press, _gsound_red_butt_release);
|
||||
}
|
||||
|
||||
int scrollDownButton = buttonCreate(win,
|
||||
FILE_DIALOG_SCROLL_BUTTON_X,
|
||||
FILE_DIALOG_SCROLL_BUTTON_Y + frmSizes[FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED].height,
|
||||
frmSizes[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_PRESSED].width,
|
||||
frmSizes[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_PRESSED].height,
|
||||
-1,
|
||||
503,
|
||||
504,
|
||||
503,
|
||||
frmBuffers[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_NORMAL],
|
||||
frmBuffers[FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_PRESSED],
|
||||
NULL,
|
||||
BUTTON_FLAG_TRANSPARENT);
|
||||
if (scrollUpBtn != -1) {
|
||||
buttonSetCallbacks(cancelBtn, _gsound_red_butt_press, _gsound_red_butt_release);
|
||||
}
|
||||
|
||||
buttonCreate(
|
||||
win,
|
||||
FILE_DIALOG_FILE_LIST_X,
|
||||
FILE_DIALOG_FILE_LIST_Y,
|
||||
FILE_DIALOG_FILE_LIST_WIDTH,
|
||||
FILE_DIALOG_FILE_LIST_HEIGHT,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
502,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0);
|
||||
|
||||
if (title != NULL) {
|
||||
fontDrawText(windowBuffer + backgroundWidth * FILE_DIALOG_TITLE_Y + FILE_DIALOG_TITLE_X, title, backgroundWidth, backgroundWidth, _colorTable[18979]);
|
||||
}
|
||||
|
||||
fontSetCurrent(101);
|
||||
|
||||
int cursorHeight = fontGetLineHeight();
|
||||
int cursorWidth = fontGetStringWidth("_") - 4;
|
||||
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
|
||||
|
||||
int fileNameLength = 0;
|
||||
char* pch = dest;
|
||||
while (*pch != '\0' && *pch != '.') {
|
||||
fileNameLength++;
|
||||
if (fileNameLength >= 12) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
dest[fileNameLength] = '\0';
|
||||
|
||||
char fileNameCopy[32];
|
||||
strncpy(fileNameCopy, dest, 32);
|
||||
|
||||
int fileNameCopyLength = strlen(fileNameCopy);
|
||||
fileNameCopy[fileNameCopyLength + 1] = '\0';
|
||||
fileNameCopy[fileNameCopyLength] = ' ';
|
||||
|
||||
unsigned char* fileNameBufferPtr = windowBuffer + backgroundWidth * 190 + 57;
|
||||
|
||||
bufferFill(fileNameBufferPtr, fontGetStringWidth(fileNameCopy), cursorHeight, backgroundWidth, 100);
|
||||
fontDrawText(fileNameBufferPtr, fileNameCopy, backgroundWidth, backgroundWidth, _colorTable[992]);
|
||||
|
||||
windowRefresh(win);
|
||||
|
||||
int blinkingCounter = 3;
|
||||
bool blink = false;
|
||||
|
||||
int doubleClickSelectedFileIndex = -2;
|
||||
int doubleClickTimer = FILE_DIALOG_DOUBLE_CLICK_DELAY;
|
||||
|
||||
int rc = -1;
|
||||
while (rc == -1) {
|
||||
unsigned int tick = _get_time();
|
||||
int keyCode = _get_input();
|
||||
int scrollDirection = FILE_DIALOG_SCROLL_DIRECTION_NONE;
|
||||
int scrollCounter = 0;
|
||||
bool isScrolling = false;
|
||||
|
||||
if (keyCode == 500) {
|
||||
rc = 0;
|
||||
} else if (keyCode == KEY_RETURN) {
|
||||
soundPlayFile("ib1p1xx1");
|
||||
rc = 0;
|
||||
} else if (keyCode == 501 || keyCode == KEY_ESCAPE) {
|
||||
rc = 1;
|
||||
} else if ((keyCode == KEY_DELETE || keyCode == KEY_BACKSPACE) && fileNameCopyLength > 0) {
|
||||
bufferFill(fileNameBufferPtr, fontGetStringWidth(fileNameCopy), cursorHeight, backgroundWidth, 100);
|
||||
fileNameCopy[fileNameCopyLength - 1] = ' ';
|
||||
fileNameCopy[fileNameCopyLength] = '\0';
|
||||
fontDrawText(fileNameBufferPtr, fileNameCopy, backgroundWidth, backgroundWidth, _colorTable[992]);
|
||||
fileNameCopyLength--;
|
||||
windowRefresh(win);
|
||||
} else if (keyCode < KEY_FIRST_INPUT_CHARACTER || keyCode > KEY_LAST_INPUT_CHARACTER || fileNameCopyLength >= 8) {
|
||||
if (keyCode == 502 && fileListLength != 0) {
|
||||
int mouseX;
|
||||
int mouseY;
|
||||
mouseGetPosition(&mouseX, &mouseY);
|
||||
|
||||
int selectedLine = (mouseY - y - FILE_DIALOG_FILE_LIST_Y) / fontGetLineHeight();
|
||||
if (selectedLine - 1 < 0) {
|
||||
selectedLine = 0;
|
||||
}
|
||||
|
||||
if (isScrollable || selectedLine < fileListLength) {
|
||||
if (selectedLine >= FILE_DIALOG_LINE_COUNT) {
|
||||
selectedLine = FILE_DIALOG_LINE_COUNT - 1;
|
||||
}
|
||||
} else {
|
||||
selectedLine = fileListLength - 1;
|
||||
}
|
||||
|
||||
selectedFileIndex = selectedLine;
|
||||
if (selectedFileIndex == doubleClickSelectedFileIndex) {
|
||||
soundPlayFile("ib1p1xx1");
|
||||
strncpy(dest, fileList[selectedFileIndex + pageOffset], 16);
|
||||
|
||||
int index;
|
||||
for (index = 0; index < 12; index++) {
|
||||
if (dest[index] == '.' || dest[index] == '\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dest[index] = '\0';
|
||||
rc = 2;
|
||||
} else {
|
||||
doubleClickSelectedFileIndex = selectedFileIndex;
|
||||
bufferFill(fileNameBufferPtr, fontGetStringWidth(fileNameCopy), cursorHeight, backgroundWidth, 100);
|
||||
strncpy(fileNameCopy, fileList[selectedFileIndex + pageOffset], 16);
|
||||
|
||||
int index;
|
||||
for (index = 0; index < 12; index++) {
|
||||
if (fileNameCopy[index] == '.' || fileNameCopy[index] == '\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fileNameCopy[index] = '\0';
|
||||
fileNameCopyLength = strlen(fileNameCopy);
|
||||
fileNameCopy[fileNameCopyLength] = ' ';
|
||||
fileNameCopy[fileNameCopyLength + 1] = '\0';
|
||||
|
||||
fontDrawText(fileNameBufferPtr, fileNameCopy, backgroundWidth, backgroundWidth, _colorTable[992]);
|
||||
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
|
||||
}
|
||||
} else if (keyCode == 506) {
|
||||
scrollDirection = FILE_DIALOG_SCROLL_DIRECTION_UP;
|
||||
} else if (keyCode == 504) {
|
||||
scrollDirection = FILE_DIALOG_SCROLL_DIRECTION_DOWN;
|
||||
} else {
|
||||
switch (keyCode) {
|
||||
case KEY_ARROW_UP:
|
||||
pageOffset--;
|
||||
if (pageOffset < 0) {
|
||||
selectedFileIndex--;
|
||||
if (selectedFileIndex < 0) {
|
||||
selectedFileIndex = 0;
|
||||
}
|
||||
pageOffset = 0;
|
||||
}
|
||||
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
|
||||
doubleClickSelectedFileIndex = -2;
|
||||
break;
|
||||
case KEY_ARROW_DOWN:
|
||||
if (isScrollable) {
|
||||
pageOffset++;
|
||||
if (pageOffset >= maxPageOffset) {
|
||||
selectedFileIndex++;
|
||||
if (selectedFileIndex >= FILE_DIALOG_LINE_COUNT) {
|
||||
selectedFileIndex = FILE_DIALOG_LINE_COUNT - 1;
|
||||
}
|
||||
pageOffset = maxPageOffset;
|
||||
}
|
||||
} else {
|
||||
selectedFileIndex++;
|
||||
if (selectedFileIndex > maxPageOffset) {
|
||||
selectedFileIndex = maxPageOffset;
|
||||
}
|
||||
}
|
||||
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
|
||||
doubleClickSelectedFileIndex = -2;
|
||||
break;
|
||||
case KEY_HOME:
|
||||
selectedFileIndex = 0;
|
||||
pageOffset = 0;
|
||||
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
|
||||
doubleClickSelectedFileIndex = -2;
|
||||
break;
|
||||
case KEY_END:
|
||||
if (isScrollable) {
|
||||
selectedFileIndex = 11;
|
||||
pageOffset = maxPageOffset;
|
||||
} else {
|
||||
selectedFileIndex = maxPageOffset;
|
||||
pageOffset = 0;
|
||||
}
|
||||
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
|
||||
doubleClickSelectedFileIndex = -2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (_isdoschar(keyCode)) {
|
||||
bufferFill(fileNameBufferPtr, fontGetStringWidth(fileNameCopy), cursorHeight, backgroundWidth, 100);
|
||||
|
||||
fileNameCopy[fileNameCopyLength] = keyCode & 0xFF;
|
||||
fileNameCopy[fileNameCopyLength + 1] = ' ';
|
||||
fileNameCopy[fileNameCopyLength + 2] = '\0';
|
||||
fontDrawText(fileNameBufferPtr, fileNameCopy, backgroundWidth, backgroundWidth, _colorTable[992]);
|
||||
fileNameCopyLength++;
|
||||
|
||||
windowRefresh(win);
|
||||
}
|
||||
|
||||
if (scrollDirection != FILE_DIALOG_SCROLL_DIRECTION_NONE) {
|
||||
unsigned int scrollDelay = 4;
|
||||
doubleClickSelectedFileIndex = -2;
|
||||
while (1) {
|
||||
unsigned int scrollTick = _get_time();
|
||||
scrollCounter += 1;
|
||||
if ((!isScrolling && scrollCounter == 1) || (isScrolling && scrollCounter > 14.4)) {
|
||||
isScrolling = true;
|
||||
|
||||
if (scrollCounter > 14.4) {
|
||||
scrollDelay += 1;
|
||||
if (scrollDelay > 24) {
|
||||
scrollDelay = 24;
|
||||
}
|
||||
}
|
||||
|
||||
if (scrollDirection == FILE_DIALOG_SCROLL_DIRECTION_UP) {
|
||||
pageOffset--;
|
||||
if (pageOffset < 0) {
|
||||
selectedFileIndex--;
|
||||
if (selectedFileIndex < 0) {
|
||||
selectedFileIndex = 0;
|
||||
}
|
||||
pageOffset = 0;
|
||||
}
|
||||
} else {
|
||||
if (isScrollable) {
|
||||
pageOffset++;
|
||||
if (pageOffset > maxPageOffset) {
|
||||
selectedFileIndex++;
|
||||
if (selectedFileIndex >= FILE_DIALOG_LINE_COUNT) {
|
||||
selectedFileIndex = FILE_DIALOG_LINE_COUNT - 1;
|
||||
}
|
||||
pageOffset = maxPageOffset;
|
||||
}
|
||||
} else {
|
||||
selectedFileIndex++;
|
||||
if (selectedFileIndex > maxPageOffset) {
|
||||
selectedFileIndex = maxPageOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileDialogRenderFileList(windowBuffer, fileList, pageOffset, fileListLength, selectedFileIndex, backgroundWidth);
|
||||
windowRefresh(win);
|
||||
}
|
||||
|
||||
// NOTE: Original code is slightly different. For unknown reason
|
||||
// entire blinking stuff is placed into two different branches,
|
||||
// which only differs by amount of delay. Probably result of
|
||||
// using large blinking macro as there are no traces of inlined
|
||||
// function.
|
||||
blinkingCounter -= 1;
|
||||
if (blinkingCounter == 0) {
|
||||
blinkingCounter = 3;
|
||||
|
||||
int color = blink ? 100 : _colorTable[992];
|
||||
blink = !blink;
|
||||
|
||||
bufferFill(fileNameBufferPtr + fontGetStringWidth(fileNameCopy) - cursorWidth, cursorWidth, cursorHeight - 2, backgroundWidth, color);
|
||||
}
|
||||
|
||||
// FIXME: Missing windowRefresh makes blinking useless.
|
||||
|
||||
unsigned int delay = (scrollCounter > 14.4) ? 1000 / scrollDelay : 1000 / 24;
|
||||
while (getTicksSince(scrollTick) < delay) {
|
||||
}
|
||||
|
||||
if (_game_user_wants_to_quit != 0) {
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
int key = _get_input();
|
||||
if (key == 505 || key == 503) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
blinkingCounter -= 1;
|
||||
if (blinkingCounter == 0) {
|
||||
blinkingCounter = 3;
|
||||
|
||||
int color = blink ? 100 : _colorTable[992];
|
||||
blink = !blink;
|
||||
|
||||
bufferFill(fileNameBufferPtr + fontGetStringWidth(fileNameCopy) - cursorWidth, cursorWidth, cursorHeight - 2, backgroundWidth, color);
|
||||
}
|
||||
|
||||
windowRefresh(win);
|
||||
|
||||
doubleClickTimer--;
|
||||
if (doubleClickTimer == 0) {
|
||||
doubleClickTimer = FILE_DIALOG_DOUBLE_CLICK_DELAY;
|
||||
doubleClickSelectedFileIndex = -2;
|
||||
}
|
||||
|
||||
while (getTicksSince(tick) < (1000 / 24)) {
|
||||
}
|
||||
}
|
||||
|
||||
if (_game_user_wants_to_quit != 0) {
|
||||
rc = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
if (fileNameCopyLength != 0) {
|
||||
fileNameCopy[fileNameCopyLength] = '\0';
|
||||
strcpy(dest, fileNameCopy);
|
||||
} else {
|
||||
rc = 1;
|
||||
}
|
||||
} else {
|
||||
if (rc == 2) {
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
windowDestroy(win);
|
||||
|
||||
for (int index = 0; index < FILE_DIALOG_FRM_COUNT; index++) {
|
||||
artUnlock(frmHandles[index]);
|
||||
}
|
||||
|
||||
messageListFree(&messageList);
|
||||
fontSetCurrent(oldFont);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
// 0x41FBDC
|
||||
void _PrntFlist(unsigned char* buffer, char** fileList, int pageOffset, int fileListLength, int selectedIndex, int pitch)
|
||||
void fileDialogRenderFileList(unsigned char* buffer, char** fileList, int pageOffset, int fileListLength, int selectedIndex, int pitch)
|
||||
{
|
||||
int lineHeight = fontGetLineHeight();
|
||||
int y = 49;
|
||||
bufferFill(buffer + y * pitch + 55, 190, 124, pitch, 100);
|
||||
int y = FILE_DIALOG_FILE_LIST_Y;
|
||||
bufferFill(buffer + y * pitch + FILE_DIALOG_FILE_LIST_X, FILE_DIALOG_FILE_LIST_WIDTH, FILE_DIALOG_FILE_LIST_HEIGHT, pitch, 100);
|
||||
if (fileListLength != 0) {
|
||||
if (fileListLength - pageOffset > 12) {
|
||||
fileListLength = 12;
|
||||
if (fileListLength - pageOffset > FILE_DIALOG_LINE_COUNT) {
|
||||
fileListLength = FILE_DIALOG_LINE_COUNT;
|
||||
}
|
||||
|
||||
for (int index = 0; index < fileListLength; index++) {
|
||||
int color = index == selectedIndex ? _colorTable[32747] : _colorTable[992];
|
||||
fontDrawText(buffer + y * index + 55, fileList[index], pitch, pitch, color);
|
||||
fontDrawText(buffer + pitch * y + FILE_DIALOG_FILE_LIST_X, fileList[pageOffset + index], pitch, pitch, color);
|
||||
y += lineHeight;
|
||||
}
|
||||
}
|
||||
|
|
26
src/dbox.h
26
src/dbox.h
|
@ -16,17 +16,35 @@ typedef enum DialogType {
|
|||
DIALOG_TYPE_COUNT,
|
||||
} DialogType;
|
||||
|
||||
typedef enum FileDialogFrm {
|
||||
FILE_DIALOG_FRM_BACKGROUND,
|
||||
FILE_DIALOG_FRM_LITTLE_RED_BUTTON_NORMAL,
|
||||
FILE_DIALOG_FRM_LITTLE_RED_BUTTON_PRESSED,
|
||||
FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_NORMAL,
|
||||
FILE_DIALOG_FRM_SCROLL_DOWN_ARROW_PRESSED,
|
||||
FILE_DIALOG_FRM_SCROLL_UP_ARROW_NORMAL,
|
||||
FILE_DIALOG_FRM_SCROLL_UP_ARROW_PRESSED,
|
||||
FILE_DIALOG_FRM_COUNT,
|
||||
} FileDialogFrm;
|
||||
|
||||
typedef enum FileDialogScrollDirection {
|
||||
FILE_DIALOG_SCROLL_DIRECTION_NONE,
|
||||
FILE_DIALOG_SCROLL_DIRECTION_UP,
|
||||
FILE_DIALOG_SCROLL_DIRECTION_DOWN,
|
||||
} FileDialogScrollDirection;
|
||||
|
||||
extern const int gDialogBoxBackgroundFrmIds[DIALOG_TYPE_COUNT];
|
||||
extern const int _ytable[DIALOG_TYPE_COUNT];
|
||||
extern const int _xtable[DIALOG_TYPE_COUNT];
|
||||
extern const int _doneY[DIALOG_TYPE_COUNT];
|
||||
extern const int _doneX[DIALOG_TYPE_COUNT];
|
||||
extern const int _dblines[DIALOG_TYPE_COUNT];
|
||||
extern int _flgids[7];
|
||||
extern int _flgids2[7];
|
||||
extern int gLoadFileDialogFrmIds[FILE_DIALOG_FRM_COUNT];
|
||||
extern int gSaveFileDialogFrmIds[FILE_DIALOG_FRM_COUNT];
|
||||
|
||||
int showDialogBox(const char* title, const char** body, int bodyLength, int x, int y, int titleColor, const char* a8, int bodyColor, int flags);
|
||||
int _save_file_dialog(char* a1, char** fileList, char* fileName, int fileListLength, int x, int y, int flags);
|
||||
void _PrntFlist(unsigned char* buffer, char** fileList, int pageOffset, int fileListLength, int selectedIndex, int pitch);
|
||||
int showLoadFileDialog(char* title, char** fileList, char* dest, int fileListLength, int x, int y, int flags);
|
||||
int showSaveFileDialog(char* title, char** fileList, char* dest, int fileListLength, int x, int y, int flags);
|
||||
void fileDialogRenderFileList(unsigned char* buffer, char** fileList, int pageOffset, int fileListLength, int selectedIndex, int pitch);
|
||||
|
||||
#endif /* DBOX_H */
|
||||
|
|
|
@ -142,7 +142,7 @@ int debugPrint(const char* format, ...)
|
|||
#ifdef _WIN32
|
||||
OutputDebugStringA(string);
|
||||
#else
|
||||
printf(string);
|
||||
printf("%s", string);
|
||||
#endif
|
||||
#endif
|
||||
rc = -1;
|
||||
|
|
|
@ -493,7 +493,12 @@ int endgameEndingSlideshowWindowInit()
|
|||
|
||||
int windowEndgameEndingX = (screenGetWidth() - ENDGAME_ENDING_WINDOW_WIDTH) / 2;
|
||||
int windowEndgameEndingY = (screenGetHeight() - ENDGAME_ENDING_WINDOW_HEIGHT) / 2;
|
||||
gEndgameEndingSlideshowWindow = windowCreate(windowEndgameEndingX, windowEndgameEndingY, ENDGAME_ENDING_WINDOW_WIDTH, ENDGAME_ENDING_WINDOW_HEIGHT, _colorTable[0], 4);
|
||||
gEndgameEndingSlideshowWindow = windowCreate(windowEndgameEndingX,
|
||||
windowEndgameEndingY,
|
||||
ENDGAME_ENDING_WINDOW_WIDTH,
|
||||
ENDGAME_ENDING_WINDOW_HEIGHT,
|
||||
_colorTable[0],
|
||||
WINDOW_FLAG_0x04);
|
||||
if (gEndgameEndingSlideshowWindow == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
|
30
src/game.cc
30
src/game.cc
|
@ -155,7 +155,11 @@ int gameInitWithOptions(const char* windowTitle, bool isMapper, int font, int a4
|
|||
}
|
||||
}
|
||||
|
||||
if (!gIsMapper) {
|
||||
// SFALL: Allow to skip splash screen
|
||||
int skipOpeningMovies = 0;
|
||||
configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_SKIP_OPENING_MOVIES_KEY, &skipOpeningMovies);
|
||||
|
||||
if (!gIsMapper && skipOpeningMovies < 2) {
|
||||
showSplash();
|
||||
}
|
||||
|
||||
|
@ -263,7 +267,7 @@ int gameInitWithOptions(const char* windowTitle, bool isMapper, int font, int a4
|
|||
|
||||
debugPrint(">wmWorldMap_init\t");
|
||||
|
||||
_CharEditInit();
|
||||
characterEditorInit();
|
||||
debugPrint(">CharEditInit\t");
|
||||
|
||||
pipboyInit();
|
||||
|
@ -363,7 +367,7 @@ void gameReset()
|
|||
scriptsReset();
|
||||
worldmapReset();
|
||||
partyMembersReset();
|
||||
_CharEditInit();
|
||||
characterEditorInit();
|
||||
pipboyReset();
|
||||
_ResetLoadSave();
|
||||
gameDialogReset();
|
||||
|
@ -512,7 +516,7 @@ int gameHandleKey(int eventCode, bool isInCombatMode)
|
|||
if (interfaceBarEnabled()) {
|
||||
soundPlayFile("ib1p1xx1");
|
||||
bool isoWasEnabled = isoDisable();
|
||||
_editor_design(false);
|
||||
characterEditorShow(false);
|
||||
if (isoWasEnabled) {
|
||||
isoEnable();
|
||||
}
|
||||
|
@ -887,6 +891,24 @@ int gameSetGlobalVar(int var, int value)
|
|||
return -1;
|
||||
}
|
||||
|
||||
// SFALL: Display karma changes.
|
||||
if (var == GVAR_PLAYER_REPUTATION) {
|
||||
bool shouldDisplayKarmaChanges = false;
|
||||
configGetBool(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_DISPLAY_KARMA_CHANGES_KEY, &shouldDisplayKarmaChanges);
|
||||
if (shouldDisplayKarmaChanges) {
|
||||
int diff = value - gGameGlobalVars[var];
|
||||
if (diff != 0) {
|
||||
char formattedMessage[80];
|
||||
if (diff > 0) {
|
||||
sprintf(formattedMessage, "You gained %d karma.", diff);
|
||||
} else {
|
||||
sprintf(formattedMessage, "You lost %d karma.", -diff);
|
||||
}
|
||||
displayMonitorAddMessage(formattedMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gGameGlobalVars[var] = value;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -571,7 +571,7 @@ void gameDialogEnter(Object* a1, int a2)
|
|||
return;
|
||||
}
|
||||
|
||||
if ((a1->pid >> 24) != OBJ_TYPE_ITEM && (a1->pid >> 24) != OBJ_TYPE_CRITTER) {
|
||||
if ((a1->pid >> 24) != OBJ_TYPE_ITEM && (a1->sid >> 24) != SCRIPT_TYPE_SPATIAL) {
|
||||
MessageListItem messageListItem;
|
||||
|
||||
int rc = _action_can_talk_to(gDude, a1);
|
||||
|
@ -1142,7 +1142,12 @@ int gameDialogReviewWindowInit(int* win)
|
|||
|
||||
int reviewWindowX = (screenGetWidth() - GAME_DIALOG_REVIEW_WINDOW_WIDTH) / 2;
|
||||
int reviewWindowY = (screenGetHeight() - GAME_DIALOG_REVIEW_WINDOW_HEIGHT) / 2;
|
||||
*win = windowCreate(reviewWindowX, reviewWindowY, GAME_DIALOG_REVIEW_WINDOW_WIDTH, GAME_DIALOG_REVIEW_WINDOW_HEIGHT, 256, WINDOW_FLAG_0x10 | WINDOW_FLAG_0x04);
|
||||
*win = windowCreate(reviewWindowX,
|
||||
reviewWindowY,
|
||||
GAME_DIALOG_REVIEW_WINDOW_WIDTH,
|
||||
GAME_DIALOG_REVIEW_WINDOW_HEIGHT,
|
||||
256,
|
||||
WINDOW_FLAG_0x10 | WINDOW_FLAG_0x04);
|
||||
if (*win == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -1548,7 +1553,12 @@ int _gdProcessInit()
|
|||
|
||||
int replyWindowX = (screenGetWidth() - GAME_DIALOG_WINDOW_WIDTH) / 2 + GAME_DIALOG_REPLY_WINDOW_X;
|
||||
int replyWindowY = (screenGetHeight() - GAME_DIALOG_WINDOW_HEIGHT) / 2 + GAME_DIALOG_REPLY_WINDOW_Y;
|
||||
gGameDialogReplyWindow = windowCreate(replyWindowX, replyWindowY, GAME_DIALOG_REPLY_WINDOW_WIDTH, GAME_DIALOG_REPLY_WINDOW_HEIGHT, 256, WINDOW_FLAG_0x04);
|
||||
gGameDialogReplyWindow = windowCreate(replyWindowX,
|
||||
replyWindowY,
|
||||
GAME_DIALOG_REPLY_WINDOW_WIDTH,
|
||||
GAME_DIALOG_REPLY_WINDOW_HEIGHT,
|
||||
256,
|
||||
WINDOW_FLAG_0x04);
|
||||
if (gGameDialogReplyWindow == -1) {
|
||||
goto err;
|
||||
}
|
||||
|
@ -2174,7 +2184,12 @@ int _gdCreateHeadWindow()
|
|||
|
||||
int backgroundWindowX = (screenGetWidth() - GAME_DIALOG_WINDOW_WIDTH) / 2;
|
||||
int backgroundWindowY = (screenGetHeight() - GAME_DIALOG_WINDOW_HEIGHT) / 2;
|
||||
gGameDialogBackgroundWindow = windowCreate(backgroundWindowX, backgroundWindowY, windowWidth, GAME_DIALOG_WINDOW_HEIGHT, 256, WINDOW_FLAG_0x02);
|
||||
gGameDialogBackgroundWindow = windowCreate(backgroundWindowX,
|
||||
backgroundWindowY,
|
||||
windowWidth,
|
||||
GAME_DIALOG_WINDOW_HEIGHT,
|
||||
256,
|
||||
WINDOW_FLAG_0x02);
|
||||
gameDialogWindowRenderBackground();
|
||||
|
||||
unsigned char* buf = windowGetBuffer(gGameDialogBackgroundWindow);
|
||||
|
@ -2594,6 +2609,9 @@ void gameDialogTicker()
|
|||
|
||||
if (_gd_optionsWin != -1) {
|
||||
windowUnhide(_gd_optionsWin);
|
||||
// SFALL: Fix for the player's money not being displayed in the
|
||||
// dialog window after leaving the barter/combat control interface.
|
||||
gameDialogRenderCaps();
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -2980,7 +2998,12 @@ int _gdialog_barter_create_win()
|
|||
|
||||
int barterWindowX = (screenGetWidth() - GAME_DIALOG_WINDOW_WIDTH) / 2;
|
||||
int barterWindowY = (screenGetHeight() - GAME_DIALOG_WINDOW_HEIGHT) / 2 + GAME_DIALOG_WINDOW_HEIGHT - _dialogue_subwin_len;
|
||||
gGameDialogWindow = windowCreate(barterWindowX, barterWindowY, GAME_DIALOG_WINDOW_WIDTH, _dialogue_subwin_len, 256, WINDOW_FLAG_0x02);
|
||||
gGameDialogWindow = windowCreate(barterWindowX,
|
||||
barterWindowY,
|
||||
GAME_DIALOG_WINDOW_WIDTH,
|
||||
_dialogue_subwin_len,
|
||||
256,
|
||||
WINDOW_FLAG_0x02);
|
||||
if (gGameDialogWindow == -1) {
|
||||
artUnlock(backgroundHandle);
|
||||
return -1;
|
||||
|
@ -3133,7 +3156,12 @@ int partyMemberControlWindowInit()
|
|||
_dialogue_subwin_len = artGetHeight(backgroundFrm, 0, 0);
|
||||
int controlWindowX = (screenGetWidth() - GAME_DIALOG_WINDOW_WIDTH) / 2;
|
||||
int controlWindowY = (screenGetHeight() - GAME_DIALOG_WINDOW_HEIGHT) / 2 + GAME_DIALOG_WINDOW_HEIGHT - _dialogue_subwin_len;
|
||||
gGameDialogWindow = windowCreate(controlWindowX, controlWindowY, GAME_DIALOG_WINDOW_WIDTH, _dialogue_subwin_len, 256, WINDOW_FLAG_0x02);
|
||||
gGameDialogWindow = windowCreate(controlWindowX,
|
||||
controlWindowY,
|
||||
GAME_DIALOG_WINDOW_WIDTH,
|
||||
_dialogue_subwin_len,
|
||||
256,
|
||||
WINDOW_FLAG_0x02);
|
||||
if (gGameDialogWindow == -1) {
|
||||
partyMemberControlWindowFree();
|
||||
return -1;
|
||||
|
@ -3567,7 +3595,12 @@ int partyMemberCustomizationWindowInit()
|
|||
|
||||
int customizationWindowX = (screenGetWidth() - GAME_DIALOG_WINDOW_WIDTH) / 2;
|
||||
int customizationWindowY = (screenGetHeight() - GAME_DIALOG_WINDOW_HEIGHT) / 2 + GAME_DIALOG_WINDOW_HEIGHT - _dialogue_subwin_len;
|
||||
gGameDialogWindow = windowCreate(customizationWindowX, customizationWindowY, GAME_DIALOG_WINDOW_WIDTH, _dialogue_subwin_len, 256, WINDOW_FLAG_0x02);
|
||||
gGameDialogWindow = windowCreate(customizationWindowX,
|
||||
customizationWindowY,
|
||||
GAME_DIALOG_WINDOW_WIDTH,
|
||||
_dialogue_subwin_len,
|
||||
256,
|
||||
WINDOW_FLAG_0x02);
|
||||
if (gGameDialogWindow == -1) {
|
||||
partyMemberCustomizationWindowFree();
|
||||
return -1;
|
||||
|
@ -4102,7 +4135,7 @@ int _gdialog_window_create()
|
|||
|
||||
int dialogSubwindowX = (screenGetWidth() - GAME_DIALOG_WINDOW_WIDTH) / 2;
|
||||
int dialogSubwindowY = (screenGetHeight() - GAME_DIALOG_WINDOW_HEIGHT) / 2 + GAME_DIALOG_WINDOW_HEIGHT - _dialogue_subwin_len;
|
||||
gGameDialogWindow = windowCreate(dialogSubwindowX, dialogSubwindowY, screenWidth, _dialogue_subwin_len, 256, 2);
|
||||
gGameDialogWindow = windowCreate(dialogSubwindowX, dialogSubwindowY, screenWidth, _dialogue_subwin_len, 256, WINDOW_FLAG_0x02);
|
||||
if (gGameDialogWindow != -1) {
|
||||
|
||||
unsigned char* v10 = windowGetBuffer(gGameDialogWindow);
|
||||
|
@ -4369,11 +4402,19 @@ void gameDialogRenderTalkingHead(Art* headFrm, int frame)
|
|||
}
|
||||
|
||||
unsigned char* src = windowGetBuffer(gIsoWindow);
|
||||
|
||||
// Usually rendering functions use `screenGetWidth`/`screenGetHeight` to
|
||||
// determine rendering position. However in this case `windowGetHeight`
|
||||
// is a must because isometric window's height can either include
|
||||
// interface bar or not. Offset is updated accordingly (332 -> 232, the
|
||||
// missing 100 is interface bar height, which is already accounted for
|
||||
// when we're using `windowGetHeight`). `windowGetWidth` is used for
|
||||
// consistency.
|
||||
blitBufferToBuffer(
|
||||
src + ((GAME_DIALOG_WINDOW_WIDTH - 332) / 2) * (GAME_DIALOG_WINDOW_WIDTH) + (GAME_DIALOG_WINDOW_WIDTH - 388) / 2,
|
||||
src + ((windowGetHeight(gIsoWindow) - 232) / 2) * windowGetWidth(gIsoWindow) + (windowGetWidth(gIsoWindow) - 388) / 2,
|
||||
388,
|
||||
200,
|
||||
screenGetWidth(),
|
||||
windowGetWidth(gIsoWindow),
|
||||
gGameDialogDisplayBuffer,
|
||||
GAME_DIALOG_WINDOW_WIDTH);
|
||||
}
|
||||
|
|
|
@ -1927,16 +1927,16 @@ int gameMouseObjectsInit()
|
|||
return -1;
|
||||
}
|
||||
|
||||
gGameMouseBouncingCursor->flags |= OBJECT_FLAG_0x20000000;
|
||||
gGameMouseBouncingCursor->flags |= OBJECT_LIGHT_THRU;
|
||||
gGameMouseBouncingCursor->flags |= OBJECT_TEMPORARY;
|
||||
gGameMouseBouncingCursor->flags |= OBJECT_FLAG_0x400;
|
||||
gGameMouseBouncingCursor->flags |= OBJECT_FLAG_0x80000000;
|
||||
gGameMouseBouncingCursor->flags |= OBJECT_SHOOT_THRU;
|
||||
gGameMouseBouncingCursor->flags |= OBJECT_NO_BLOCK;
|
||||
|
||||
gGameMouseHexCursor->flags |= OBJECT_FLAG_0x400;
|
||||
gGameMouseHexCursor->flags |= OBJECT_TEMPORARY;
|
||||
gGameMouseHexCursor->flags |= OBJECT_FLAG_0x20000000;
|
||||
gGameMouseHexCursor->flags |= OBJECT_FLAG_0x80000000;
|
||||
gGameMouseHexCursor->flags |= OBJECT_LIGHT_THRU;
|
||||
gGameMouseHexCursor->flags |= OBJECT_SHOOT_THRU;
|
||||
gGameMouseHexCursor->flags |= OBJECT_NO_BLOCK;
|
||||
|
||||
_obj_toggle_flat(gGameMouseHexCursor, NULL);
|
||||
|
|
|
@ -46,7 +46,7 @@ const char* gMovieFileNames[MOVIE_COUNT] = {
|
|||
};
|
||||
|
||||
// 0x518DE4
|
||||
char* gMoviePaletteFilePaths[MOVIE_COUNT] = {
|
||||
const char* gMoviePaletteFilePaths[MOVIE_COUNT] = {
|
||||
NULL,
|
||||
"art\\cuts\\introsub.pal",
|
||||
"art\\cuts\\eldersub.pal",
|
||||
|
@ -209,7 +209,7 @@ int gameMoviePlay(int movie, int flags)
|
|||
int oldTextColor;
|
||||
int oldFont;
|
||||
if (subtitlesEnabled) {
|
||||
char* subtitlesPaletteFilePath;
|
||||
const char* subtitlesPaletteFilePath;
|
||||
if (gMoviePaletteFilePaths[movie] != NULL) {
|
||||
subtitlesPaletteFilePath = gMoviePaletteFilePaths[movie];
|
||||
} else {
|
||||
|
|
|
@ -35,7 +35,7 @@ typedef enum GameMovie {
|
|||
extern const float flt_50352A;
|
||||
|
||||
extern const char* gMovieFileNames[MOVIE_COUNT];
|
||||
extern char* gMoviePaletteFilePaths[MOVIE_COUNT];
|
||||
extern const char* gMoviePaletteFilePaths[MOVIE_COUNT];
|
||||
extern bool gGameMovieIsPlaying;
|
||||
extern bool gGameMovieFaded;
|
||||
|
||||
|
|
|
@ -41,6 +41,14 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#define INVENTORY_WINDOW_X 80
|
||||
#define INVENTORY_WINDOW_Y 0
|
||||
|
||||
#define INVENTORY_TRADE_WINDOW_X 80
|
||||
#define INVENTORY_TRADE_WINDOW_Y 290
|
||||
#define INVENTORY_TRADE_WINDOW_WIDTH 480
|
||||
#define INVENTORY_TRADE_WINDOW_HEIGHT 180
|
||||
|
||||
#define INVENTORY_LARGE_SLOT_WIDTH 90
|
||||
#define INVENTORY_LARGE_SLOT_HEIGHT 61
|
||||
|
||||
|
@ -550,10 +558,10 @@ bool _setup_inventory(int inventoryWindowType)
|
|||
// Maintain original position in original resolution, otherwise center it.
|
||||
int inventoryWindowX = screenGetWidth() != 640
|
||||
? (screenGetWidth() - windowDescription->width) / 2
|
||||
: 80;
|
||||
: INVENTORY_WINDOW_X;
|
||||
int inventoryWindowY = screenGetHeight() != 480
|
||||
? (screenGetHeight() - windowDescription->height) / 2
|
||||
: 0;
|
||||
: INVENTORY_WINDOW_Y;
|
||||
gInventoryWindow = windowCreate(inventoryWindowX,
|
||||
inventoryWindowY,
|
||||
windowDescription->width,
|
||||
|
@ -582,15 +590,15 @@ bool _setup_inventory(int inventoryWindowType)
|
|||
gInventorySlotsCount = 3;
|
||||
|
||||
// Trade inventory window is a part of game dialog, which is 640x480.
|
||||
int tradeWindowX = (screenGetWidth() - 640) / 2 + 80;
|
||||
int tradeWindowY = (screenGetHeight() - 480) / 2 + 290;
|
||||
gInventoryWindow = windowCreate(tradeWindowX, tradeWindowY, 480, 180, 257, 0);
|
||||
gInventoryWindowMaxX = tradeWindowX + 480;
|
||||
gInventoryWindowMaxY = tradeWindowY + 180;
|
||||
int tradeWindowX = (screenGetWidth() - 640) / 2 + INVENTORY_TRADE_WINDOW_X;
|
||||
int tradeWindowY = (screenGetHeight() - 480) / 2 + INVENTORY_TRADE_WINDOW_Y;
|
||||
gInventoryWindow = windowCreate(tradeWindowX, tradeWindowY, INVENTORY_TRADE_WINDOW_WIDTH, INVENTORY_TRADE_WINDOW_HEIGHT, 257, 0);
|
||||
gInventoryWindowMaxX = tradeWindowX + INVENTORY_TRADE_WINDOW_WIDTH;
|
||||
gInventoryWindowMaxY = tradeWindowY + INVENTORY_TRADE_WINDOW_HEIGHT;
|
||||
|
||||
unsigned char* dest = windowGetBuffer(gInventoryWindow);
|
||||
unsigned char* src = windowGetBuffer(_barter_back_win);
|
||||
blitBufferToBuffer(src + 80, 480, 180, 640, dest, 480);
|
||||
blitBufferToBuffer(src + INVENTORY_TRADE_WINDOW_X, INVENTORY_TRADE_WINDOW_WIDTH, INVENTORY_TRADE_WINDOW_HEIGHT, 640, dest, INVENTORY_TRADE_WINDOW_WIDTH);
|
||||
|
||||
gInventoryPrintItemDescriptionHandler = gameDialogRenderSupplementaryMessage;
|
||||
}
|
||||
|
@ -606,7 +614,7 @@ bool _setup_inventory(int inventoryWindowType)
|
|||
}
|
||||
|
||||
int eventCode = 2005;
|
||||
int y = INVENTORY_SLOT_HEIGHT * 5 + INVENTORY_SLOT_HEIGHT;
|
||||
int y = INVENTORY_SLOT_HEIGHT * 5 + INVENTORY_LOOT_LEFT_SCROLLER_Y;
|
||||
|
||||
// Create invisible buttons representing container's inventory item
|
||||
// slots. For unknown reason it loops backwards and it's size is
|
||||
|
@ -2987,7 +2995,7 @@ void inventoryWindowOpenContextMenu(int keyCode, int inventoryWindowType)
|
|||
|
||||
int x;
|
||||
int y;
|
||||
mouseGetPositionInWindow(gInventoryWindow, &x, &y);
|
||||
mouseGetPosition(&x, &y);
|
||||
|
||||
int actionMenuItemsLength;
|
||||
const int* actionMenuItems;
|
||||
|
@ -3035,9 +3043,15 @@ void inventoryWindowOpenContextMenu(int keyCode, int inventoryWindowType)
|
|||
}
|
||||
|
||||
const InventoryWindowDescription* windowDescription = &(gInventoryWindowDescriptions[inventoryWindowType]);
|
||||
|
||||
Rect windowRect;
|
||||
windowGetRect(gInventoryWindow, &windowRect);
|
||||
int inventoryWindowX = windowRect.left;
|
||||
int inventoryWindowY = windowRect.top;
|
||||
|
||||
gameMouseRenderActionMenuItems(x, y, actionMenuItems, actionMenuItemsLength,
|
||||
windowDescription->width + windowDescription->x,
|
||||
windowDescription->height + windowDescription->y);
|
||||
windowDescription->width + inventoryWindowX,
|
||||
windowDescription->height + inventoryWindowY);
|
||||
|
||||
InventoryCursorData* cursorData = &(gInventoryCursorData[INVENTORY_WINDOW_CURSOR_MENU]);
|
||||
|
||||
|
@ -3046,8 +3060,8 @@ void inventoryWindowOpenContextMenu(int keyCode, int inventoryWindowType)
|
|||
artGetRotationOffsets(cursorData->frm, 0, &offsetX, &offsetY);
|
||||
|
||||
Rect rect;
|
||||
rect.left = x - windowDescription->x - cursorData->width / 2 + offsetX;
|
||||
rect.top = y - windowDescription->y - cursorData->height + 1 + offsetY;
|
||||
rect.left = x - inventoryWindowX - cursorData->width / 2 + offsetX;
|
||||
rect.top = y - inventoryWindowY - cursorData->height + 1 + offsetY;
|
||||
rect.right = rect.left + cursorData->width - 1;
|
||||
rect.bottom = rect.top + cursorData->height - 1;
|
||||
|
||||
|
@ -3082,7 +3096,7 @@ void inventoryWindowOpenContextMenu(int keyCode, int inventoryWindowType)
|
|||
|
||||
int x;
|
||||
int y;
|
||||
mouseGetPositionInWindow(gInventoryWindow, &x, &y);
|
||||
mouseGetPosition(&x, &y);
|
||||
if (y - previousMouseY > 10 || previousMouseY - y > 10) {
|
||||
if (y >= previousMouseY || menuItemIndex <= 0) {
|
||||
if (previousMouseY < y && menuItemIndex < actionMenuItemsLength - 1) {
|
||||
|
@ -4476,6 +4490,7 @@ void _container_enter(int keyCode, int inventoryWindowType)
|
|||
_stack[_curr_stack] = item;
|
||||
_stack_offset[_curr_stack] = 0;
|
||||
|
||||
_inven_dude = _stack[_curr_stack];
|
||||
_pud = &(item->data.inventory);
|
||||
|
||||
_adjust_fid();
|
||||
|
|
16
src/item.cc
16
src/item.cc
|
@ -576,11 +576,11 @@ bool _item_identical(Object* a1, Object* a2)
|
|||
return false;
|
||||
}
|
||||
|
||||
if ((a1->flags & (OBJECT_EQUIPPED | OBJECT_FLAG_0x2000)) != 0) {
|
||||
if ((a1->flags & (OBJECT_EQUIPPED | OBJECT_USED)) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((a2->flags & (OBJECT_EQUIPPED | OBJECT_FLAG_0x2000)) != 0) {
|
||||
if ((a2->flags & (OBJECT_EQUIPPED | OBJECT_USED)) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -989,14 +989,14 @@ int _item_queued(Object* obj)
|
|||
return false;
|
||||
}
|
||||
|
||||
if ((obj->flags & OBJECT_FLAG_0x2000) != 0) {
|
||||
if ((obj->flags & OBJECT_USED) != 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Inventory* inventory = &(obj->data.inventory);
|
||||
for (int index = 0; index < inventory->length; index++) {
|
||||
InventoryItem* inventoryItem = &(inventory->items[index]);
|
||||
if ((inventoryItem->item->flags & OBJECT_FLAG_0x2000) != 0) {
|
||||
if ((inventoryItem->item->flags & OBJECT_USED) != 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2402,11 +2402,11 @@ int _item_m_turn_off_from_queue(Object* obj, void* data)
|
|||
// 0x479960
|
||||
int stealthBoyTurnOn(Object* object)
|
||||
{
|
||||
if ((object->flags & OBJECT_FLAG_0x20000) != 0) {
|
||||
if ((object->flags & OBJECT_TRANS_GLASS) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
object->flags |= OBJECT_FLAG_0x20000;
|
||||
object->flags |= OBJECT_TRANS_GLASS;
|
||||
|
||||
Rect rect;
|
||||
objectGetRect(object, &rect);
|
||||
|
@ -2428,11 +2428,11 @@ int stealthBoyTurnOff(Object* critter, Object* item)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if ((critter->flags & OBJECT_FLAG_0x20000) == 0) {
|
||||
if ((critter->flags & OBJECT_TRANS_GLASS) == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
critter->flags &= ~OBJECT_FLAG_0x20000;
|
||||
critter->flags &= ~OBJECT_TRANS_GLASS;
|
||||
|
||||
Rect rect;
|
||||
objectGetRect(critter, &rect);
|
||||
|
|
68
src/lips.cc
68
src/lips.cc
|
@ -177,44 +177,46 @@ int lipsStart()
|
|||
}
|
||||
|
||||
// 0x47AD98
|
||||
int lipsReadV1(LipsData* a1, File* stream)
|
||||
int lipsReadV1(LipsData* lipsData, File* stream)
|
||||
{
|
||||
int field_C;
|
||||
int sound;
|
||||
int field_14;
|
||||
int field_18;
|
||||
int field_30;
|
||||
int phonemes;
|
||||
int markers;
|
||||
|
||||
if (fileReadInt32(stream, &(a1->version)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(a1->field_4)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(a1->flags)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(field_C)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(a1->field_10)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(lipsData->version)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(lipsData->field_4)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(lipsData->flags)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(sound)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(lipsData->field_10)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(field_14)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(field_18)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(a1->field_1C)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(a1->field_20)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(a1->field_24)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(a1->field_28)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(a1->field_2C)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(field_30)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(a1->field_34)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(a1->field_38)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(a1->field_3C)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(a1->field_40)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(a1->field_44)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(a1->field_48)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(a1->field_4C)) == -1) return -1;
|
||||
if (fileReadFixedLengthString(stream, a1->field_50, 8) == -1) return -1;
|
||||
if (fileReadFixedLengthString(stream, a1->field_58, 4) == -1) return -1;
|
||||
if (fileReadFixedLengthString(stream, a1->field_5C, 4) == -1) return -1;
|
||||
if (fileReadFixedLengthString(stream, a1->field_60, 4) == -1) return -1;
|
||||
if (fileReadFixedLengthString(stream, a1->field_64, 260) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(phonemes)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(lipsData->field_1C)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(lipsData->field_20)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(lipsData->field_24)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(lipsData->field_28)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(lipsData->field_2C)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(markers)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(lipsData->field_34)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(lipsData->field_38)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(lipsData->field_3C)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(lipsData->field_40)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(lipsData->field_44)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(lipsData->field_48)) == -1) return -1;
|
||||
if (fileReadInt32(stream, &(lipsData->field_4C)) == -1) return -1;
|
||||
if (fileReadFixedLengthString(stream, lipsData->field_50, 8) == -1) return -1;
|
||||
if (fileReadFixedLengthString(stream, lipsData->field_58, 4) == -1) return -1;
|
||||
if (fileReadFixedLengthString(stream, lipsData->field_5C, 4) == -1) return -1;
|
||||
if (fileReadFixedLengthString(stream, lipsData->field_60, 4) == -1) return -1;
|
||||
if (fileReadFixedLengthString(stream, lipsData->field_64, 260) == -1) return -1;
|
||||
|
||||
// TODO: What for?
|
||||
a1->sound = (Sound*)field_C;
|
||||
a1->field_14 = (void*)field_14;
|
||||
a1->phonemes = (unsigned char*)field_18;
|
||||
a1->markers = (SpeechMarker*)field_30;
|
||||
// NOTE: Original code is different. For unknown reason it assigns values
|
||||
// from file (integers) and treat them as pointers, which is obviously wrong
|
||||
// is in this case.
|
||||
lipsData->sound = NULL;
|
||||
lipsData->field_14 = NULL;
|
||||
lipsData->phonemes = NULL;
|
||||
lipsData->markers = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ SaveGameHandler* _master_save_list[LOAD_SAVE_HANDLER_COUNT] = {
|
|||
traitsSave,
|
||||
automapSave,
|
||||
preferencesSave,
|
||||
_editor_save,
|
||||
characterEditorSave,
|
||||
worldmapSave,
|
||||
pipboySave,
|
||||
gameMoviesSave,
|
||||
|
@ -142,7 +142,7 @@ LoadGameHandler* _master_load_list[LOAD_SAVE_HANDLER_COUNT] = {
|
|||
traitsLoad,
|
||||
automapLoad,
|
||||
preferencesLoad,
|
||||
_editor_load,
|
||||
characterEditorLoad,
|
||||
worldmapLoad,
|
||||
pipboyLoad,
|
||||
gameMoviesLoad,
|
||||
|
@ -626,9 +626,10 @@ int _QuickSnapShot()
|
|||
}
|
||||
|
||||
// For preview take 640x380 area in the center of isometric window.
|
||||
unsigned char* isoWindowBuffer = windowGetBuffer(gIsoWindow)
|
||||
+ (screenGetWidth() - ORIGINAL_ISO_WINDOW_WIDTH) / 2 * (screenGetHeight() - ORIGINAL_ISO_WINDOW_HEIGHT) / 2
|
||||
+ (screenGetWidth() - ORIGINAL_ISO_WINDOW_WIDTH) / 2;
|
||||
Window* window = windowGetWindow(gIsoWindow);
|
||||
unsigned char* isoWindowBuffer = window->buffer
|
||||
+ window->width * (window->height - ORIGINAL_ISO_WINDOW_HEIGHT) / 2
|
||||
+ (window->width - ORIGINAL_ISO_WINDOW_WIDTH) / 2;
|
||||
blitBufferToBufferStretch(isoWindowBuffer,
|
||||
ORIGINAL_ISO_WINDOW_WIDTH,
|
||||
ORIGINAL_ISO_WINDOW_HEIGHT,
|
||||
|
@ -1107,9 +1108,10 @@ int lsgWindowInit(int windowType)
|
|||
}
|
||||
|
||||
// For preview take 640x380 area in the center of isometric window.
|
||||
unsigned char* isoWindowBuffer = windowGetBuffer(gIsoWindow)
|
||||
+ (screenGetWidth() - ORIGINAL_ISO_WINDOW_WIDTH) / 2 * (screenGetHeight() - ORIGINAL_ISO_WINDOW_HEIGHT) / 2
|
||||
+ (screenGetWidth() - ORIGINAL_ISO_WINDOW_WIDTH) / 2;
|
||||
Window* window = windowGetWindow(gIsoWindow);
|
||||
unsigned char* isoWindowBuffer = window->buffer
|
||||
+ window->width * (window->height - ORIGINAL_ISO_WINDOW_HEIGHT) / 2
|
||||
+ (window->width - ORIGINAL_ISO_WINDOW_WIDTH) / 2;
|
||||
blitBufferToBufferStretch(isoWindowBuffer,
|
||||
ORIGINAL_ISO_WINDOW_WIDTH,
|
||||
ORIGINAL_ISO_WINDOW_HEIGHT,
|
||||
|
|
42
src/main.cc
42
src/main.cc
|
@ -132,9 +132,14 @@ int falloutMain(int argc, char** argv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
gameMoviePlay(MOVIE_IPLOGO, GAME_MOVIE_FADE_IN);
|
||||
gameMoviePlay(MOVIE_INTRO, 0);
|
||||
gameMoviePlay(MOVIE_CREDITS, 0);
|
||||
// SFALL: Allow to skip intro movies
|
||||
int skipOpeningMovies;
|
||||
configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_SKIP_OPENING_MOVIES_KEY, &skipOpeningMovies);
|
||||
if(skipOpeningMovies < 1) {
|
||||
gameMoviePlay(MOVIE_IPLOGO, GAME_MOVIE_FADE_IN);
|
||||
gameMoviePlay(MOVIE_INTRO, 0);
|
||||
gameMoviePlay(MOVIE_CREDITS, 0);
|
||||
}
|
||||
|
||||
FpsLimiter fpsLimiter;
|
||||
|
||||
|
@ -194,7 +199,7 @@ int falloutMain(int argc, char** argv)
|
|||
mainMenuWindowHide(true);
|
||||
mainMenuWindowFree();
|
||||
_game_user_wants_to_quit = 0;
|
||||
gDude->flags &= ~OBJECT_FLAG_0x08;
|
||||
gDude->flags &= ~OBJECT_FLAT;
|
||||
_main_show_death_scene = 0;
|
||||
objectShow(gDude, NULL);
|
||||
mouseHideCursor();
|
||||
|
@ -296,7 +301,7 @@ int _main_load_new(char* mapFileName)
|
|||
{
|
||||
_game_user_wants_to_quit = 0;
|
||||
_main_show_death_scene = 0;
|
||||
gDude->flags &= ~OBJECT_FLAG_0x08;
|
||||
gDude->flags &= ~OBJECT_FLAT;
|
||||
objectShow(gDude, NULL);
|
||||
mouseHideCursor();
|
||||
|
||||
|
@ -639,17 +644,31 @@ int mainMenuWindowInit()
|
|||
int oldFont = fontGetCurrent();
|
||||
fontSetCurrent(100);
|
||||
|
||||
// SFALL: Allow to change font color/flags of copyright/version text
|
||||
// It's the last byte ('3C' by default) that picks the colour used. The first byte supplies additional flags for this option
|
||||
// 0x010000 - change the color for version string only
|
||||
// 0x020000 - underline text (only for the version string)
|
||||
// 0x040000 - monospace font (only for the version string)
|
||||
int fontSettings = _colorTable[21091], fontSettingsSFall = 0;
|
||||
configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_MAIN_MENU_FONT_COLOR_KEY, &fontSettingsSFall);
|
||||
if (fontSettingsSFall && !(fontSettingsSFall & 0x010000))
|
||||
fontSettings = fontSettingsSFall & 0xFF;
|
||||
|
||||
// Copyright.
|
||||
msg.num = 20;
|
||||
if (messageListGetItem(&gMiscMessageList, &msg)) {
|
||||
windowDrawText(gMainMenuWindow, msg.text, 0, 15, 460, _colorTable[21091] | 0x6000000);
|
||||
windowDrawText(gMainMenuWindow, msg.text, 0, 15, 460, fontSettings | 0x06000000);
|
||||
}
|
||||
|
||||
// SFALL: Make sure font settings are applied when using 0x010000 flag
|
||||
if (fontSettingsSFall)
|
||||
fontSettings = fontSettingsSFall;
|
||||
|
||||
// Version.
|
||||
char version[VERSION_MAX];
|
||||
versionGetVersion(version);
|
||||
len = fontGetStringWidth(version);
|
||||
windowDrawText(gMainMenuWindow, version, 0, 615 - len, 460, _colorTable[21091] | 0x6000000);
|
||||
windowDrawText(gMainMenuWindow, version, 0, 615 - len, 460, fontSettings | 0x06000000);
|
||||
|
||||
// menuup.frm
|
||||
fid = buildFid(6, 299, 0, 0, 0);
|
||||
|
@ -683,11 +702,18 @@ int mainMenuWindowInit()
|
|||
|
||||
fontSetCurrent(104);
|
||||
|
||||
// SFALL: Allow to change font color of buttons
|
||||
fontSettings = _colorTable[21091];
|
||||
fontSettingsSFall = 0;
|
||||
configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_MAIN_MENU_BIG_FONT_COLOR_KEY, &fontSettingsSFall);
|
||||
if (fontSettingsSFall)
|
||||
fontSettings = fontSettingsSFall & 0xFF;
|
||||
|
||||
for (int index = 0; index < MAIN_MENU_BUTTON_COUNT; index++) {
|
||||
msg.num = 9 + index;
|
||||
if (messageListGetItem(&gMiscMessageList, &msg)) {
|
||||
len = fontGetStringWidth(msg.text);
|
||||
fontDrawText(gMainMenuWindowBuffer + 640 * (42 * index - index + 20) + 126 - (len / 2), msg.text, 640 - (126 - (len / 2)) - 1, 640, _colorTable[21091]);
|
||||
fontDrawText(gMainMenuWindowBuffer + 640 * (42 * index - index + 20) + 126 - (len / 2), msg.text, 640 - (126 - (len / 2)) - 1, 640, fontSettings);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -903,7 +903,7 @@ int mapLoad(File* stream)
|
|||
Object* object;
|
||||
int fid = buildFid(5, 12, 0, 0, 0);
|
||||
objectCreateWithFidPid(&object, fid, -1);
|
||||
object->flags |= (OBJECT_FLAG_0x20000000 | OBJECT_TEMPORARY | OBJECT_HIDDEN);
|
||||
object->flags |= (OBJECT_LIGHT_THRU | OBJECT_TEMPORARY | OBJECT_HIDDEN);
|
||||
objectSetLocation(object, 1, 0, NULL);
|
||||
object->sid = gMapSid;
|
||||
scriptSetFixedParam(gMapSid, (gMapHeader.flags & 1) == 0);
|
||||
|
|
|
@ -22,10 +22,10 @@ int gMemoryBlocksCurrentCount = 0;
|
|||
int gMemoryBlockMaximumCount = 0;
|
||||
|
||||
// 0x51DEE4
|
||||
int gMemoryBlocksCurrentSize = 0;
|
||||
size_t gMemoryBlocksCurrentSize = 0;
|
||||
|
||||
// 0x51DEE8
|
||||
int gMemoryBlocksMaximumSize = 0;
|
||||
size_t gMemoryBlocksMaximumSize = 0;
|
||||
|
||||
// 0x4C5A80
|
||||
char* internal_strdup(const char* string)
|
||||
|
|
|
@ -29,8 +29,8 @@ extern ReallocProc* gReallocProc;
|
|||
extern FreeProc* gFreeProc;
|
||||
extern int gMemoryBlocksCurrentCount;
|
||||
extern int gMemoryBlockMaximumCount;
|
||||
extern int gMemoryBlocksCurrentSize;
|
||||
extern int gMemoryBlocksMaximumSize;
|
||||
extern size_t gMemoryBlocksCurrentSize;
|
||||
extern size_t gMemoryBlocksMaximumSize;
|
||||
|
||||
char* internal_strdup(const char* string);
|
||||
void* internal_malloc(size_t size);
|
||||
|
|
18
src/mmx.cc
18
src/mmx.cc
|
@ -9,23 +9,7 @@
|
|||
// 0x4E08A0
|
||||
bool mmxIsSupported()
|
||||
{
|
||||
int v1;
|
||||
|
||||
// TODO: There are other ways to determine MMX using FLAGS register.
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
__asm
|
||||
{
|
||||
mov eax, 1
|
||||
cpuid
|
||||
and edx, 0x800000
|
||||
mov v1, edx
|
||||
}
|
||||
#else
|
||||
v1 = 0;
|
||||
#endif
|
||||
|
||||
return v1 != 0;
|
||||
return SDL_HasMMX() == SDL_TRUE;
|
||||
}
|
||||
|
||||
// 0x4E0DB0
|
||||
|
|
|
@ -39,31 +39,31 @@ typedef enum OutlineType {
|
|||
typedef enum ObjectFlags {
|
||||
OBJECT_HIDDEN = 0x01,
|
||||
OBJECT_TEMPORARY = 0x04,
|
||||
OBJECT_FLAG_0x08 = 0x08,
|
||||
OBJECT_FLAT = 0x08,
|
||||
OBJECT_NO_BLOCK = 0x10,
|
||||
OBJECT_LIGHTING = 0x20,
|
||||
OBJECT_FLAG_0x400 = 0x400,
|
||||
OBJECT_FLAG_0x800 = 0x800,
|
||||
OBJECT_FLAG_0x1000 = 0x1000,
|
||||
OBJECT_FLAG_0x2000 = 0x2000,
|
||||
OBJECT_FLAG_0x4000 = 0x4000,
|
||||
OBJECT_FLAG_0x8000 = 0x8000,
|
||||
OBJECT_FLAG_0x10000 = 0x10000,
|
||||
OBJECT_FLAG_0x20000 = 0x20000,
|
||||
OBJECT_FLAG_0x40000 = 0x40000,
|
||||
OBJECT_FLAG_0x80000 = 0x80000,
|
||||
OBJECT_FLAG_0x400 = 0x400, // ???
|
||||
OBJECT_MULTIHEX = 0x800,
|
||||
OBJECT_NO_HIGHLIGHT = 0x1000,
|
||||
OBJECT_USED = 0x2000, // set if there was/is any event for the object
|
||||
OBJECT_TRANS_RED = 0x4000,
|
||||
OBJECT_TRANS_NONE = 0x8000,
|
||||
OBJECT_TRANS_WALL = 0x10000,
|
||||
OBJECT_TRANS_GLASS = 0x20000,
|
||||
OBJECT_TRANS_STEAM = 0x40000,
|
||||
OBJECT_TRANS_ENERGY = 0x80000,
|
||||
OBJECT_IN_LEFT_HAND = 0x1000000,
|
||||
OBJECT_IN_RIGHT_HAND = 0x2000000,
|
||||
OBJECT_WORN = 0x4000000,
|
||||
OBJECT_FLAG_0x10000000 = 0x10000000,
|
||||
OBJECT_FLAG_0x20000000 = 0x20000000,
|
||||
OBJECT_FLAG_0x40000000 = 0x40000000,
|
||||
OBJECT_FLAG_0x80000000 = 0x80000000,
|
||||
OBJECT_WALL_TRANS_END = 0x10000000,
|
||||
OBJECT_LIGHT_THRU = 0x20000000,
|
||||
OBJECT_SEEN = 0x40000000,
|
||||
OBJECT_SHOOT_THRU = 0x80000000,
|
||||
|
||||
OBJECT_IN_ANY_HAND = OBJECT_IN_LEFT_HAND | OBJECT_IN_RIGHT_HAND,
|
||||
OBJECT_EQUIPPED = OBJECT_IN_ANY_HAND | OBJECT_WORN,
|
||||
OBJECT_FLAG_0xFC000 = OBJECT_FLAG_0x80000 | OBJECT_FLAG_0x40000 | OBJECT_FLAG_0x20000 | OBJECT_FLAG_0x10000 | OBJECT_FLAG_0x8000 | OBJECT_FLAG_0x4000,
|
||||
OBJECT_OPEN_DOOR = OBJECT_FLAG_0x80000000 | OBJECT_FLAG_0x20000000 | OBJECT_NO_BLOCK,
|
||||
OBJECT_FLAG_0xFC000 = OBJECT_TRANS_ENERGY | OBJECT_TRANS_STEAM | OBJECT_TRANS_GLASS | OBJECT_TRANS_WALL | OBJECT_TRANS_NONE | OBJECT_TRANS_RED,
|
||||
OBJECT_OPEN_DOOR = OBJECT_SHOOT_THRU | OBJECT_LIGHT_THRU | OBJECT_NO_BLOCK,
|
||||
} ObjectFlags;
|
||||
|
||||
#define OUTLINE_TYPE_MASK 0xFFFFFF
|
||||
|
|
281
src/object.cc
281
src/object.cc
|
@ -30,13 +30,13 @@
|
|||
bool gObjectsInitialized = false;
|
||||
|
||||
// 0x5195FC
|
||||
int _updateHexWidth = 0;
|
||||
int gObjectsUpdateAreaHexWidth = 0;
|
||||
|
||||
// 0x519600
|
||||
int _updateHexHeight = 0;
|
||||
int gObjectsUpdateAreaHexHeight = 0;
|
||||
|
||||
// 0x519604
|
||||
int _updateHexArea = 0;
|
||||
int gObjectsUpdateAreaHexSize = 0;
|
||||
|
||||
// 0x519608
|
||||
int* _orderTable[2] = {
|
||||
|
@ -204,16 +204,7 @@ Rect gObjectsWindowRect;
|
|||
Object* _outlinedObjects[100];
|
||||
|
||||
// 0x639D90
|
||||
int _updateAreaPixelBounds;
|
||||
|
||||
// 0x639D94
|
||||
int dword_639D94;
|
||||
|
||||
// 0x639D98
|
||||
int dword_639D98;
|
||||
|
||||
// 0x639D9C
|
||||
int dword_639D9C;
|
||||
Rect gObjectsUpdateAreaPixelBounds;
|
||||
|
||||
// Contains objects that are bounded to tiles.
|
||||
//
|
||||
|
@ -264,14 +255,14 @@ int objectsInit(unsigned char* buf, int width, int height, int pitch)
|
|||
int eggFid;
|
||||
|
||||
memset(_obj_seen, 0, 5001);
|
||||
dword_639D98 = width + 320;
|
||||
_updateAreaPixelBounds = -320;
|
||||
dword_639D9C = height + 240;
|
||||
dword_639D94 = -240;
|
||||
gObjectsUpdateAreaPixelBounds.right = width + 320;
|
||||
gObjectsUpdateAreaPixelBounds.left = -320;
|
||||
gObjectsUpdateAreaPixelBounds.bottom = height + 240;
|
||||
gObjectsUpdateAreaPixelBounds.top = -240;
|
||||
|
||||
_updateHexWidth = (dword_639D98 + 320 + 1) / 32 + 1;
|
||||
_updateHexHeight = (dword_639D9C + 240 + 1) / 12 + 1;
|
||||
_updateHexArea = _updateHexWidth * _updateHexHeight;
|
||||
gObjectsUpdateAreaHexWidth = (gObjectsUpdateAreaPixelBounds.right + 320 + 1) / 32 + 1;
|
||||
gObjectsUpdateAreaHexHeight = (gObjectsUpdateAreaPixelBounds.bottom + 240 + 1) / 12 + 1;
|
||||
gObjectsUpdateAreaHexSize = gObjectsUpdateAreaHexWidth * gObjectsUpdateAreaHexHeight;
|
||||
|
||||
memset(gObjectListHeadByTile, 0, sizeof(gObjectListHeadByTile));
|
||||
|
||||
|
@ -298,7 +289,7 @@ int objectsInit(unsigned char* buf, int width, int height, int pitch)
|
|||
_obj_light_table_init();
|
||||
_obj_blend_table_init();
|
||||
|
||||
_centerToUpperLeft = tileFromScreenXY(_updateAreaPixelBounds, dword_639D94, 0) - gCenterTile;
|
||||
_centerToUpperLeft = tileFromScreenXY(gObjectsUpdateAreaPixelBounds.left, gObjectsUpdateAreaPixelBounds.top, 0) - gCenterTile;
|
||||
gObjectsWindowWidth = width;
|
||||
gObjectsWindowHeight = height;
|
||||
gObjectsWindowBuffer = buf;
|
||||
|
@ -317,7 +308,7 @@ int objectsInit(unsigned char* buf, int width, int height, int pitch)
|
|||
gDude->flags |= OBJECT_FLAG_0x400;
|
||||
gDude->flags |= OBJECT_TEMPORARY;
|
||||
gDude->flags |= OBJECT_HIDDEN;
|
||||
gDude->flags |= OBJECT_FLAG_0x20000000;
|
||||
gDude->flags |= OBJECT_LIGHT_THRU;
|
||||
objectSetLight(gDude, 4, 0x10000, NULL);
|
||||
|
||||
if (partyMemberAdd(gDude) == -1) {
|
||||
|
@ -330,7 +321,7 @@ int objectsInit(unsigned char* buf, int width, int height, int pitch)
|
|||
gEgg->flags |= OBJECT_FLAG_0x400;
|
||||
gEgg->flags |= OBJECT_TEMPORARY;
|
||||
gEgg->flags |= OBJECT_HIDDEN;
|
||||
gEgg->flags |= OBJECT_FLAG_0x20000000;
|
||||
gEgg->flags |= OBJECT_LIGHT_THRU;
|
||||
|
||||
gObjectsInitialized = true;
|
||||
|
||||
|
@ -767,35 +758,59 @@ void _obj_render_pre_roof(Rect* rect, int elevation)
|
|||
return;
|
||||
}
|
||||
|
||||
int lightLevel = lightGetLightLevel();
|
||||
int v5 = updatedRect.left - 320;
|
||||
int v4 = updatedRect.top - 240;
|
||||
int v17 = updatedRect.right + 320;
|
||||
int v18 = updatedRect.bottom + 240;
|
||||
int v19 = tileFromScreenXY(v5, v4, elevation);
|
||||
int v20 = (v17 - v5 + 1) / 32;
|
||||
int v23 = (v18 - v4 + 1) / 12;
|
||||
int ambientLight = lightGetLightLevel();
|
||||
int minX = updatedRect.left - 320;
|
||||
int minY = updatedRect.top - 240;
|
||||
int maxX = updatedRect.right + 320;
|
||||
int maxY = updatedRect.bottom + 240;
|
||||
int topLeftTile = tileFromScreenXY(minX, minY, elevation);
|
||||
int updateAreaHexWidth = (maxX - minX + 1) / 32;
|
||||
int updateAreaHexHeight = (maxY - minY + 1) / 12;
|
||||
|
||||
int odd = gCenterTile & 1;
|
||||
int* v7 = _orderTable[odd];
|
||||
int* v8 = _offsetTable[odd];
|
||||
// On some maps (which were designed too close to edges) HRP brings a new
|
||||
// problem - extended update rect (+/- 320/240 stuff above) may end up
|
||||
// outside of the map edge. In this case `topLeftTile` will be -1 which
|
||||
// affect all subsequent calculations. In order to fix that attempt to
|
||||
// find closest valid tile.
|
||||
while (!hexGridTileIsValid(topLeftTile)) {
|
||||
minX += 32;
|
||||
minY += 12;
|
||||
topLeftTile = tileFromScreenXY(minX, minY, elevation);
|
||||
}
|
||||
|
||||
// Do the same for the for bottom-right part of the extended update rect.
|
||||
int bottomRightTile = tileFromScreenXY(maxX, maxY, elevation);
|
||||
while (!hexGridTileIsValid(bottomRightTile)) {
|
||||
maxX -= 32;
|
||||
maxY -= 12;
|
||||
bottomRightTile = tileFromScreenXY(maxX, maxY, elevation);
|
||||
}
|
||||
|
||||
updateAreaHexWidth = (maxX - minX + 1) / 32;
|
||||
updateAreaHexHeight = (maxY - minY + 1) / 12;
|
||||
|
||||
int parity = gCenterTile & 1;
|
||||
int* orders = _orderTable[parity];
|
||||
int* offsets = _offsetTable[parity];
|
||||
|
||||
_outlineCount = 0;
|
||||
|
||||
int v34 = 0;
|
||||
for (int i = 0; i < _updateHexArea; i++) {
|
||||
int v9 = *v7++;
|
||||
if (v23 > _offsetDivTable[v9] && v20 > _offsetModTable[v9]) {
|
||||
int v2;
|
||||
int renderCount = 0;
|
||||
for (int i = 0; i < gObjectsUpdateAreaHexSize; i++) {
|
||||
int offsetIndex = *orders++;
|
||||
if (updateAreaHexHeight > _offsetDivTable[offsetIndex] && updateAreaHexWidth > _offsetModTable[offsetIndex]) {
|
||||
int light;
|
||||
|
||||
ObjectListNode* objectListNode = gObjectListHeadByTile[v19 + v8[v9]];
|
||||
ObjectListNode* objectListNode = hexGridTileIsValid(topLeftTile + offsets[offsetIndex])
|
||||
? gObjectListHeadByTile[topLeftTile + offsets[offsetIndex]]
|
||||
: NULL;
|
||||
if (objectListNode != NULL) {
|
||||
// NOTE: calls _light_get_tile two times, probably result of min/max macro
|
||||
int q = _light_get_tile(elevation, objectListNode->obj->tile);
|
||||
if (q >= lightLevel) {
|
||||
v2 = q;
|
||||
int tileLight = _light_get_tile(elevation, objectListNode->obj->tile);
|
||||
if (tileLight >= ambientLight) {
|
||||
light = tileLight;
|
||||
} else {
|
||||
v2 = lightLevel;
|
||||
light = ambientLight;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -805,12 +820,12 @@ void _obj_render_pre_roof(Rect* rect, int elevation)
|
|||
}
|
||||
|
||||
if (elevation == objectListNode->obj->elevation) {
|
||||
if ((objectListNode->obj->flags & OBJECT_FLAG_0x08) == 0) {
|
||||
if ((objectListNode->obj->flags & OBJECT_FLAT) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((objectListNode->obj->flags & OBJECT_HIDDEN) == 0) {
|
||||
_obj_render_object(objectListNode->obj, &updatedRect, v2);
|
||||
_obj_render_object(objectListNode->obj, &updatedRect, light);
|
||||
|
||||
if ((objectListNode->obj->outline & OUTLINE_TYPE_MASK) != 0) {
|
||||
if ((objectListNode->obj->outline & OUTLINE_DISABLED) == 0 && _outlineCount < 100) {
|
||||
|
@ -824,20 +839,22 @@ void _obj_render_pre_roof(Rect* rect, int elevation)
|
|||
}
|
||||
|
||||
if (objectListNode != NULL) {
|
||||
_renderTable[v34++] = objectListNode;
|
||||
_renderTable[renderCount++] = objectListNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < v34; i++) {
|
||||
int v2;
|
||||
for (int i = 0; i < renderCount; i++) {
|
||||
int light;
|
||||
|
||||
ObjectListNode* objectListNode = _renderTable[i];
|
||||
if (objectListNode != NULL) {
|
||||
v2 = lightLevel;
|
||||
int w = _light_get_tile(elevation, objectListNode->obj->tile);
|
||||
if (w > v2) {
|
||||
v2 = w;
|
||||
// NOTE: calls _light_get_tile two times, probably result of min/max macro
|
||||
int tileLight = _light_get_tile(elevation, objectListNode->obj->tile);
|
||||
if (tileLight >= ambientLight) {
|
||||
light = tileLight;
|
||||
} else {
|
||||
light = ambientLight;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -849,7 +866,7 @@ void _obj_render_pre_roof(Rect* rect, int elevation)
|
|||
|
||||
if (elevation == objectListNode->obj->elevation) {
|
||||
if ((objectListNode->obj->flags & OBJECT_HIDDEN) == 0) {
|
||||
_obj_render_object(object, &updatedRect, v2);
|
||||
_obj_render_object(object, &updatedRect, light);
|
||||
|
||||
if ((objectListNode->obj->outline & OUTLINE_TYPE_MASK) != 0) {
|
||||
if ((objectListNode->obj->outline & OUTLINE_DISABLED) == 0 && _outlineCount < 100) {
|
||||
|
@ -943,39 +960,39 @@ int objectCreateWithFidPid(Object** objectPtr, int fid, int pid)
|
|||
}
|
||||
|
||||
if ((proto->flags & 0x800) != 0) {
|
||||
objectListNode->obj->flags |= OBJECT_FLAG_0x800;
|
||||
objectListNode->obj->flags |= OBJECT_MULTIHEX;
|
||||
}
|
||||
|
||||
if ((proto->flags & 0x8000) != 0) {
|
||||
objectListNode->obj->flags |= OBJECT_FLAG_0x8000;
|
||||
objectListNode->obj->flags |= OBJECT_TRANS_NONE;
|
||||
} else {
|
||||
if ((proto->flags & 0x10000) != 0) {
|
||||
objectListNode->obj->flags |= OBJECT_FLAG_0x10000;
|
||||
objectListNode->obj->flags |= OBJECT_TRANS_WALL;
|
||||
} else if ((proto->flags & 0x20000) != 0) {
|
||||
objectListNode->obj->flags |= OBJECT_FLAG_0x20000;
|
||||
objectListNode->obj->flags |= OBJECT_TRANS_GLASS;
|
||||
} else if ((proto->flags & 0x40000) != 0) {
|
||||
objectListNode->obj->flags |= OBJECT_FLAG_0x40000;
|
||||
objectListNode->obj->flags |= OBJECT_TRANS_STEAM;
|
||||
} else if ((proto->flags & 0x80000) != 0) {
|
||||
objectListNode->obj->flags |= OBJECT_FLAG_0x80000;
|
||||
objectListNode->obj->flags |= OBJECT_TRANS_ENERGY;
|
||||
} else if ((proto->flags & 0x4000) != 0) {
|
||||
objectListNode->obj->flags |= OBJECT_FLAG_0x4000;
|
||||
objectListNode->obj->flags |= OBJECT_TRANS_RED;
|
||||
}
|
||||
}
|
||||
|
||||
if ((proto->flags & 0x20000000) != 0) {
|
||||
objectListNode->obj->flags |= OBJECT_FLAG_0x20000000;
|
||||
objectListNode->obj->flags |= OBJECT_LIGHT_THRU;
|
||||
}
|
||||
|
||||
if ((proto->flags & 0x80000000) != 0) {
|
||||
objectListNode->obj->flags |= OBJECT_FLAG_0x80000000;
|
||||
objectListNode->obj->flags |= OBJECT_SHOOT_THRU;
|
||||
}
|
||||
|
||||
if ((proto->flags & 0x10000000) != 0) {
|
||||
objectListNode->obj->flags |= OBJECT_FLAG_0x10000000;
|
||||
objectListNode->obj->flags |= OBJECT_WALL_TRANS_END;
|
||||
}
|
||||
|
||||
if ((proto->flags & 0x1000) != 0) {
|
||||
objectListNode->obj->flags |= OBJECT_FLAG_0x1000;
|
||||
objectListNode->obj->flags |= OBJECT_NO_HIGHLIGHT;
|
||||
}
|
||||
|
||||
_obj_new_sid(objectListNode->obj, &(objectListNode->obj->sid));
|
||||
|
@ -1041,7 +1058,7 @@ int _obj_copy(Object** a1, Object* a2)
|
|||
return -1;
|
||||
}
|
||||
|
||||
objectListNode->obj->flags &= ~OBJECT_FLAG_0x2000;
|
||||
objectListNode->obj->flags &= ~OBJECT_USED;
|
||||
|
||||
Inventory* newInventory = &(objectListNode->obj->data.inventory);
|
||||
newInventory->length = 0;
|
||||
|
@ -1948,7 +1965,7 @@ int _obj_toggle_flat(Object* object, Rect* rect)
|
|||
}
|
||||
}
|
||||
|
||||
object->flags ^= OBJECT_FLAG_0x08;
|
||||
object->flags ^= OBJECT_FLAT;
|
||||
|
||||
_obj_insert(node);
|
||||
objectGetRect(object, &v1);
|
||||
|
@ -1965,7 +1982,7 @@ int _obj_toggle_flat(Object* object, Rect* rect)
|
|||
}
|
||||
}
|
||||
|
||||
object->flags ^= OBJECT_FLAG_0x08;
|
||||
object->flags ^= OBJECT_FLAT;
|
||||
|
||||
_obj_insert(node);
|
||||
}
|
||||
|
@ -2419,7 +2436,7 @@ Object* _obj_blocking_at(Object* a1, int tile, int elev)
|
|||
objectListNode = gObjectListHeadByTile[neighboor];
|
||||
while (objectListNode != NULL) {
|
||||
v7 = objectListNode->obj;
|
||||
if ((v7->flags & OBJECT_FLAG_0x800) != 0) {
|
||||
if ((v7->flags & OBJECT_MULTIHEX) != 0) {
|
||||
if (v7->elevation == elev) {
|
||||
if ((v7->flags & OBJECT_HIDDEN) == 0 && (v7->flags & OBJECT_NO_BLOCK) == 0 && v7 != a1) {
|
||||
type = (v7->fid & 0xF000000) >> 24;
|
||||
|
@ -2451,7 +2468,7 @@ Object* _obj_shoot_blocking_at(Object* obj, int tile, int elev)
|
|||
Object* candidate = objectListItem->obj;
|
||||
if (candidate->elevation == elev) {
|
||||
unsigned int flags = candidate->flags;
|
||||
if ((flags & OBJECT_HIDDEN) == 0 && ((flags & OBJECT_NO_BLOCK) == 0 || (flags & OBJECT_FLAG_0x80000000) == 0) && candidate != obj) {
|
||||
if ((flags & OBJECT_HIDDEN) == 0 && ((flags & OBJECT_NO_BLOCK) == 0 || (flags & OBJECT_SHOOT_THRU) == 0) && candidate != obj) {
|
||||
int type = (candidate->fid & 0xF000000) >> 24;
|
||||
// SFALL: Fix to prevent corpses from blocking line of fire.
|
||||
if ((type == OBJ_TYPE_CRITTER && !critterIsDead(candidate))
|
||||
|
@ -2474,7 +2491,7 @@ Object* _obj_shoot_blocking_at(Object* obj, int tile, int elev)
|
|||
while (objectListItem != NULL) {
|
||||
Object* candidate = objectListItem->obj;
|
||||
unsigned int flags = candidate->flags;
|
||||
if ((flags & OBJECT_FLAG_0x800) != 0) {
|
||||
if ((flags & OBJECT_MULTIHEX) != 0) {
|
||||
if (candidate->elevation == elev) {
|
||||
if ((flags & OBJECT_HIDDEN) == 0 && (flags & OBJECT_NO_BLOCK) == 0 && candidate != obj) {
|
||||
int type = (candidate->fid & 0xF000000) >> 24;
|
||||
|
@ -2533,7 +2550,7 @@ Object* _obj_ai_blocking_at(Object* a1, int tile, int elevation)
|
|||
objectListNode = gObjectListHeadByTile[candidate];
|
||||
while (objectListNode != NULL) {
|
||||
Object* object = objectListNode->obj;
|
||||
if ((object->flags & OBJECT_FLAG_0x800) != 0) {
|
||||
if ((object->flags & OBJECT_MULTIHEX) != 0) {
|
||||
if (object->elevation == elevation) {
|
||||
if ((object->flags & OBJECT_HIDDEN) == 0
|
||||
&& (object->flags & OBJECT_NO_BLOCK) == 0
|
||||
|
@ -2590,7 +2607,7 @@ Object* _obj_sight_blocking_at(Object* a1, int tile, int elevation)
|
|||
Object* object = objectListNode->obj;
|
||||
if (object->elevation == elevation
|
||||
&& (object->flags & OBJECT_HIDDEN) == 0
|
||||
&& (object->flags & OBJECT_FLAG_0x20000000) == 0
|
||||
&& (object->flags & OBJECT_LIGHT_THRU) == 0
|
||||
&& object != a1) {
|
||||
int objectType = (object->fid & 0xF000000) >> 24;
|
||||
if (objectType == OBJ_TYPE_SCENERY || objectType == OBJ_TYPE_WALL) {
|
||||
|
@ -2612,11 +2629,11 @@ int objectGetDistanceBetween(Object* object1, Object* object2)
|
|||
|
||||
int distance = tileDistanceBetween(object1->tile, object2->tile);
|
||||
|
||||
if ((object1->flags & OBJECT_FLAG_0x800) != 0) {
|
||||
if ((object1->flags & OBJECT_MULTIHEX) != 0) {
|
||||
distance -= 1;
|
||||
}
|
||||
|
||||
if ((object2->flags & OBJECT_FLAG_0x800) != 0) {
|
||||
if ((object2->flags & OBJECT_MULTIHEX) != 0) {
|
||||
distance -= 1;
|
||||
}
|
||||
|
||||
|
@ -2636,11 +2653,11 @@ int objectGetDistanceBetweenTiles(Object* object1, int tile1, Object* object2, i
|
|||
|
||||
int distance = tileDistanceBetween(tile1, tile2);
|
||||
|
||||
if ((object1->flags & OBJECT_FLAG_0x800) != 0) {
|
||||
if ((object1->flags & OBJECT_MULTIHEX) != 0) {
|
||||
distance -= 1;
|
||||
}
|
||||
|
||||
if ((object2->flags & OBJECT_FLAG_0x800) != 0) {
|
||||
if ((object2->flags & OBJECT_MULTIHEX) != 0) {
|
||||
distance -= 1;
|
||||
}
|
||||
|
||||
|
@ -2869,7 +2886,7 @@ int objectSetOutline(Object* obj, int outlineType, Rect* rect)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if ((obj->flags & OBJECT_FLAG_0x1000) != 0) {
|
||||
if ((obj->flags & OBJECT_NO_HIGHLIGHT) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -2951,7 +2968,7 @@ int _obj_intersects_with(Object* object, int x, int y)
|
|||
flags |= 0x01;
|
||||
|
||||
if ((object->flags & OBJECT_FLAG_0xFC000) != 0) {
|
||||
if ((object->flags & OBJECT_FLAG_0x8000) == 0) {
|
||||
if ((object->flags & OBJECT_TRANS_NONE) == 0) {
|
||||
flags &= ~0x03;
|
||||
flags |= 0x02;
|
||||
}
|
||||
|
@ -2999,14 +3016,14 @@ int _obj_create_intersect_list(int x, int y, int elevation, int objectType, Obje
|
|||
int v5 = tileFromScreenXY(x - 320, y - 240, elevation);
|
||||
*entriesPtr = NULL;
|
||||
|
||||
if (_updateHexArea <= 0) {
|
||||
if (gObjectsUpdateAreaHexSize <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
|
||||
int parity = gCenterTile & 1;
|
||||
for (int index = 0; index < _updateHexArea; index++) {
|
||||
for (int index = 0; index < gObjectsUpdateAreaHexSize; index++) {
|
||||
int v7 = _orderTable[parity][index];
|
||||
if (_offsetDivTable[v7] < 30 && _offsetModTable[v7] < 20) {
|
||||
ObjectListNode* objectListNode = gObjectListHeadByTile[_offsetTable[parity][v7] + v5];
|
||||
|
@ -3100,7 +3117,7 @@ void _obj_process_seen()
|
|||
if (v5 < 40000) {
|
||||
for (obj_entry = gObjectListHeadByTile[v5]; obj_entry != NULL; obj_entry = obj_entry->next) {
|
||||
if (obj_entry->obj->elevation == gDude->elevation) {
|
||||
obj_entry->obj->flags |= OBJECT_FLAG_0x40000000;
|
||||
obj_entry->obj->flags |= OBJECT_SEEN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3238,46 +3255,46 @@ int _obj_offset_table_init()
|
|||
return -1;
|
||||
}
|
||||
|
||||
_offsetTable[0] = (int*)internal_malloc(sizeof(int) * _updateHexArea);
|
||||
_offsetTable[0] = (int*)internal_malloc(sizeof(int) * gObjectsUpdateAreaHexSize);
|
||||
if (_offsetTable[0] == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
_offsetTable[1] = (int*)internal_malloc(sizeof(int) * _updateHexArea);
|
||||
_offsetTable[1] = (int*)internal_malloc(sizeof(int) * gObjectsUpdateAreaHexSize);
|
||||
if (_offsetTable[1] == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
int tile = tileFromScreenXY(_updateAreaPixelBounds, dword_639D94, 0);
|
||||
if (tile != -1) {
|
||||
int* v5 = _offsetTable[gCenterTile & 1];
|
||||
int v20;
|
||||
int v19;
|
||||
tileToScreenXY(tile, &v20, &v19, 0);
|
||||
for (int parity = 0; parity < 2; parity++) {
|
||||
int originTile = tileFromScreenXY(gObjectsUpdateAreaPixelBounds.left, gObjectsUpdateAreaPixelBounds.top, 0);
|
||||
if (originTile != -1) {
|
||||
int* offsets = _offsetTable[gCenterTile & 1];
|
||||
int originTileX;
|
||||
int originTileY;
|
||||
tileToScreenXY(originTile, &originTileX, &originTileY, 0);
|
||||
|
||||
int v23 = 16;
|
||||
v20 += 16;
|
||||
v19 += 8;
|
||||
if (v20 > _updateAreaPixelBounds) {
|
||||
v23 = -v23;
|
||||
int parityShift = 16;
|
||||
originTileX += 16;
|
||||
originTileY += 8;
|
||||
if (originTileX > gObjectsUpdateAreaPixelBounds.left) {
|
||||
parityShift = -parityShift;
|
||||
}
|
||||
|
||||
int v6 = v20;
|
||||
for (int j = 0; j < _updateHexHeight; j++) {
|
||||
for (int m = 0; m < _updateHexWidth; m++) {
|
||||
int t = tileFromScreenXY(v6, v19, 0);
|
||||
if (t == -1) {
|
||||
int tileX = originTileX;
|
||||
for (int y = 0; y < gObjectsUpdateAreaHexHeight; y++) {
|
||||
for (int x = 0; x < gObjectsUpdateAreaHexWidth; x++) {
|
||||
int tile = tileFromScreenXY(tileX, originTileY, 0);
|
||||
if (tile == -1) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
v6 += 32;
|
||||
*v5++ = t - tile;
|
||||
tileX += 32;
|
||||
*offsets++ = tile - originTile;
|
||||
}
|
||||
|
||||
v6 = v23 + v20;
|
||||
v19 += 12;
|
||||
v23 = -v23;
|
||||
tileX = parityShift + originTileX;
|
||||
originTileY += 12;
|
||||
parityShift = -parityShift;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3286,22 +3303,22 @@ int _obj_offset_table_init()
|
|||
}
|
||||
}
|
||||
|
||||
_offsetDivTable = (int*)internal_malloc(sizeof(int) * _updateHexArea);
|
||||
_offsetDivTable = (int*)internal_malloc(sizeof(int) * gObjectsUpdateAreaHexSize);
|
||||
if (_offsetDivTable == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < _updateHexArea; i++) {
|
||||
_offsetDivTable[i] = i / _updateHexWidth;
|
||||
for (i = 0; i < gObjectsUpdateAreaHexSize; i++) {
|
||||
_offsetDivTable[i] = i / gObjectsUpdateAreaHexWidth;
|
||||
}
|
||||
|
||||
_offsetModTable = (int*)internal_malloc(sizeof(int) * _updateHexArea);
|
||||
_offsetModTable = (int*)internal_malloc(sizeof(int) * gObjectsUpdateAreaHexSize);
|
||||
if (_offsetModTable == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i < _updateHexArea; i++) {
|
||||
_offsetModTable[i] = i % _updateHexWidth;
|
||||
for (i = 0; i < gObjectsUpdateAreaHexSize; i++) {
|
||||
_offsetModTable[i] = i % gObjectsUpdateAreaHexWidth;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -3343,23 +3360,23 @@ int _obj_order_table_init()
|
|||
return -1;
|
||||
}
|
||||
|
||||
_orderTable[0] = (int*)internal_malloc(sizeof(int) * _updateHexArea);
|
||||
_orderTable[0] = (int*)internal_malloc(sizeof(int) * gObjectsUpdateAreaHexSize);
|
||||
if (_orderTable[0] == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
_orderTable[1] = (int*)internal_malloc(sizeof(int) * _updateHexArea);
|
||||
_orderTable[1] = (int*)internal_malloc(sizeof(int) * gObjectsUpdateAreaHexSize);
|
||||
if (_orderTable[1] == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (int index = 0; index < _updateHexArea; index++) {
|
||||
for (int index = 0; index < gObjectsUpdateAreaHexSize; index++) {
|
||||
_orderTable[0][index] = index;
|
||||
_orderTable[1][index] = index;
|
||||
}
|
||||
|
||||
qsort(_orderTable[0], _updateHexArea, sizeof(int), _obj_order_comp_func_even);
|
||||
qsort(_orderTable[1], _updateHexArea, sizeof(int), _obj_order_comp_func_odd);
|
||||
qsort(_orderTable[0], gObjectsUpdateAreaHexSize, sizeof(int), _obj_order_comp_func_even);
|
||||
qsort(_orderTable[1], gObjectsUpdateAreaHexSize, sizeof(int), _obj_order_comp_func_odd);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -3410,12 +3427,12 @@ int _obj_render_table_init()
|
|||
return -1;
|
||||
}
|
||||
|
||||
_renderTable = (ObjectListNode**)internal_malloc(sizeof(*_renderTable) * _updateHexArea);
|
||||
_renderTable = (ObjectListNode**)internal_malloc(sizeof(*_renderTable) * gObjectsUpdateAreaHexSize);
|
||||
if (_renderTable == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int index = 0; index < _updateHexArea; index++) {
|
||||
for (int index = 0; index < gObjectsUpdateAreaHexSize; index++) {
|
||||
_renderTable[index] = NULL;
|
||||
}
|
||||
|
||||
|
@ -3438,11 +3455,11 @@ void _obj_light_table_init()
|
|||
{
|
||||
for (int s = 0; s < 2; s++) {
|
||||
int v4 = gCenterTile + s;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
for (int i = 0; i < ROTATION_COUNT; i++) {
|
||||
int v15 = 8;
|
||||
int* p = _light_offsets[v4 & 1][i];
|
||||
for (int j = 0; j < 8; j++) {
|
||||
int tile = tileGetTileInDirection(v4, (i + 1) % 6, j);
|
||||
int tile = tileGetTileInDirection(v4, (i + 1) % ROTATION_COUNT, j);
|
||||
|
||||
for (int m = 0; m < v15; m++) {
|
||||
*p++ = tileGetTileInDirection(tile, i, m + 1) - v4;
|
||||
|
@ -3856,11 +3873,11 @@ void _obj_insert(ObjectListNode* objectListNode)
|
|||
}
|
||||
|
||||
if (obj->elevation == objectListNode->obj->elevation) {
|
||||
if ((obj->flags & OBJECT_FLAG_0x08) == 0 && (objectListNode->obj->flags & OBJECT_FLAG_0x08) != 0) {
|
||||
if ((obj->flags & OBJECT_FLAT) == 0 && (objectListNode->obj->flags & OBJECT_FLAT) != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((obj->flags & OBJECT_FLAG_0x08) == (objectListNode->obj->flags & OBJECT_FLAG_0x08)) {
|
||||
if ((obj->flags & OBJECT_FLAT) == (objectListNode->obj->flags & OBJECT_FLAT)) {
|
||||
bool v11 = false;
|
||||
CacheEntry* a2;
|
||||
Art* v12 = artLock(obj->fid, &a2);
|
||||
|
@ -4553,10 +4570,10 @@ int _obj_adjust_light(Object* obj, int a2, Rect* rect)
|
|||
objectGetRect(objectListNode->obj, &v29);
|
||||
rectUnion(&objectRect, &v29, &objectRect);
|
||||
|
||||
v14 = (objectListNode->obj->flags & OBJECT_FLAG_0x20000000) == 0;
|
||||
v14 = (objectListNode->obj->flags & OBJECT_LIGHT_THRU) == 0;
|
||||
|
||||
if ((objectListNode->obj->fid & 0xF000000) >> 24 == OBJ_TYPE_WALL) {
|
||||
if ((objectListNode->obj->flags & OBJECT_FLAG_0x08) == 0) {
|
||||
if ((objectListNode->obj->flags & OBJECT_FLAT) == 0) {
|
||||
Proto* proto;
|
||||
protoGetProto(objectListNode->obj->pid, &proto);
|
||||
if ((proto->wall.extendedFlags & 0x8000000) != 0 || (proto->wall.extendedFlags & 0x40000000) != 0) {
|
||||
|
@ -4964,7 +4981,7 @@ void _obj_render_object(Object* object, Rect* rect, int light)
|
|||
v17 = tileIsInFrontOf(object->tile, gDude->tile);
|
||||
if (!v17
|
||||
|| !tileIsToRightOf(object->tile, gDude->tile)
|
||||
|| (object->flags & OBJECT_FLAG_0x10000000) == 0) {
|
||||
|| (object->flags & OBJECT_WALL_TRANS_END) == 0) {
|
||||
// nothing
|
||||
} else {
|
||||
v17 = false;
|
||||
|
@ -4980,7 +4997,7 @@ void _obj_render_object(Object* object, Rect* rect, int light)
|
|||
v17 = tileIsToRightOf(gDude->tile, object->tile);
|
||||
if (v17
|
||||
&& tileIsInFrontOf(gDude->tile, object->tile)
|
||||
&& (object->flags & OBJECT_FLAG_0x10000000) != 0) {
|
||||
&& (object->flags & OBJECT_WALL_TRANS_END) != 0) {
|
||||
v17 = 0;
|
||||
}
|
||||
}
|
||||
|
@ -5071,19 +5088,19 @@ void _obj_render_object(Object* object, Rect* rect, int light)
|
|||
}
|
||||
|
||||
switch (object->flags & OBJECT_FLAG_0xFC000) {
|
||||
case OBJECT_FLAG_0x4000:
|
||||
case OBJECT_TRANS_RED:
|
||||
_dark_translucent_trans_buf_to_buf(src, objectWidth, objectHeight, frameWidth, gObjectsWindowBuffer, objectRect.left, objectRect.top, gObjectsWindowPitch, light, _redBlendTable, _commonGrayTable);
|
||||
break;
|
||||
case OBJECT_FLAG_0x10000:
|
||||
case OBJECT_TRANS_WALL:
|
||||
_dark_translucent_trans_buf_to_buf(src, objectWidth, objectHeight, frameWidth, gObjectsWindowBuffer, objectRect.left, objectRect.top, gObjectsWindowPitch, 0x10000, _wallBlendTable, _commonGrayTable);
|
||||
break;
|
||||
case OBJECT_FLAG_0x20000:
|
||||
case OBJECT_TRANS_GLASS:
|
||||
_dark_translucent_trans_buf_to_buf(src, objectWidth, objectHeight, frameWidth, gObjectsWindowBuffer, objectRect.left, objectRect.top, gObjectsWindowPitch, light, _glassBlendTable, _glassGrayTable);
|
||||
break;
|
||||
case OBJECT_FLAG_0x40000:
|
||||
case OBJECT_TRANS_STEAM:
|
||||
_dark_translucent_trans_buf_to_buf(src, objectWidth, objectHeight, frameWidth, gObjectsWindowBuffer, objectRect.left, objectRect.top, gObjectsWindowPitch, light, _steamBlendTable, _commonGrayTable);
|
||||
break;
|
||||
case OBJECT_FLAG_0x80000:
|
||||
case OBJECT_TRANS_ENERGY:
|
||||
_dark_translucent_trans_buf_to_buf(src, objectWidth, objectHeight, frameWidth, gObjectsWindowBuffer, objectRect.left, objectRect.top, gObjectsWindowPitch, light, _energyBlendTable, _commonGrayTable);
|
||||
break;
|
||||
default:
|
||||
|
|
11
src/object.h
11
src/object.h
|
@ -13,9 +13,9 @@ typedef struct ObjectWithFlags {
|
|||
} ObjectWithFlags;
|
||||
|
||||
extern bool gObjectsInitialized;
|
||||
extern int _updateHexWidth;
|
||||
extern int _updateHexHeight;
|
||||
extern int _updateHexArea;
|
||||
extern int gObjectsUpdateAreaHexWidth;
|
||||
extern int gObjectsUpdateAreaHexHeight;
|
||||
extern int gObjectsUpdateAreaHexSize;
|
||||
extern int* _orderTable[2];
|
||||
extern int* _offsetTable[2];
|
||||
extern int* _offsetModTable;
|
||||
|
@ -49,10 +49,7 @@ extern int _light_blocked[6][36];
|
|||
extern int _light_offsets[2][6][36];
|
||||
extern Rect gObjectsWindowRect;
|
||||
extern Object* _outlinedObjects[100];
|
||||
extern int _updateAreaPixelBounds;
|
||||
extern int dword_639D94;
|
||||
extern int dword_639D98;
|
||||
extern int dword_639D9C;
|
||||
extern Rect gObjectsUpdateAreaPixelBounds;
|
||||
extern ObjectListNode* gObjectListHeadByTile[HEX_GRID_SIZE];
|
||||
extern unsigned char _glassGrayTable[256];
|
||||
extern unsigned char _commonGrayTable[256];
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#ifdef _WIN32
|
||||
#include <timeapi.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#include <chrono>
|
||||
#endif
|
||||
|
||||
int compat_stricmp(const char* string1, const char* string2)
|
||||
|
@ -145,8 +145,8 @@ unsigned int compat_timeGetTime()
|
|||
#ifdef _WIN32
|
||||
return timeGetTime();
|
||||
#else
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return tv.tv_usec / 1000;
|
||||
static auto start = std::chrono::steady_clock::now();
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
return static_cast<unsigned int>(std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count());
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -777,7 +777,7 @@ int _proto_dude_init(const char* path)
|
|||
_proto_dude_update_gender();
|
||||
_inven_reset_dude();
|
||||
|
||||
if ((gDude->flags & OBJECT_FLAG_0x08) != 0) {
|
||||
if ((gDude->flags & OBJECT_FLAT) != 0) {
|
||||
_obj_toggle_flat(gDude, NULL);
|
||||
}
|
||||
|
||||
|
@ -1854,7 +1854,7 @@ int _ResetPlayer()
|
|||
pcStatsReset();
|
||||
protoCritterDataResetStats(&(proto->critter.data));
|
||||
critterReset();
|
||||
_editor_reset();
|
||||
characterEditorReset();
|
||||
protoCritterDataResetSkills(&(proto->critter.data));
|
||||
skillsReset();
|
||||
perksReset();
|
||||
|
|
|
@ -796,7 +796,7 @@ int _obj_use_flare(Object* critter_obj, Object* flare)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if ((flare->flags & OBJECT_FLAG_0x2000) != 0) {
|
||||
if ((flare->flags & OBJECT_USED) != 0) {
|
||||
if (critter_obj == gDude) {
|
||||
// The flare is already lit.
|
||||
messageListItem.num = 588;
|
||||
|
@ -854,7 +854,7 @@ int _obj_use_explosive(Object* explosive)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if ((explosive->flags & OBJECT_FLAG_0x2000) != 0) {
|
||||
if ((explosive->flags & OBJECT_USED) != 0) {
|
||||
// The timer is already ticking.
|
||||
messageListItem.num = 590;
|
||||
if (messageListGetItem(&gProtoMessageList, &messageListItem)) {
|
||||
|
@ -2198,7 +2198,7 @@ int _objPMAttemptPlacement(Object* obj, int tile, int elevation)
|
|||
for (int v4 = 1; v4 <= 100; v4++) {
|
||||
// TODO: Check.
|
||||
v7++;
|
||||
v9 = tileGetTileInDirection(v9, v7 % 6, 1);
|
||||
v9 = tileGetTileInDirection(v9, v7 % ROTATION_COUNT, 1);
|
||||
if (_wmEvalTileNumForPlacement(v9) != 0) {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -232,7 +232,7 @@ int queueAddEvent(int delay, Object* obj, void* data, int eventType)
|
|||
newQueueListNode->data = data;
|
||||
|
||||
if (obj != NULL) {
|
||||
obj->flags |= OBJECT_FLAG_0x2000;
|
||||
obj->flags |= OBJECT_USED;
|
||||
}
|
||||
|
||||
QueueListNode** v3 = &gQueueListHead;
|
||||
|
|
|
@ -1723,7 +1723,8 @@ int scriptWrite(Script* scr, File* stream)
|
|||
|
||||
if (fileWriteInt32(stream, scr->flags) == -1) return -1;
|
||||
if (fileWriteInt32(stream, scr->field_14) == -1) return -1;
|
||||
if (fileWriteInt32(stream, (int)scr->program) == -1) return -1; // FIXME: writing pointer to file
|
||||
// NOTE: Original code writes `scr->program` pointer which is meaningless.
|
||||
if (fileWriteInt32(stream, 0) == -1) return -1;
|
||||
if (fileWriteInt32(stream, scr->field_1C) == -1) return -1;
|
||||
if (fileWriteInt32(stream, scr->localVarsOffset) == -1) return -1;
|
||||
if (fileWriteInt32(stream, scr->localVarsCount) == -1) return -1;
|
||||
|
@ -1753,8 +1754,8 @@ int scriptListExtentWrite(ScriptListExtent* a1, File* stream)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (fileWriteInt32(stream, (int)a1->next) != 0) {
|
||||
// FIXME: writing pointer to file
|
||||
// NOTE: Original code writes `a1->next` pointer which is meaningless.
|
||||
if (fileWriteInt32(stream, 0) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1778,18 +1779,16 @@ int scriptSaveAll(File* stream)
|
|||
for (int index = 0; index < scriptExtent->length; index++) {
|
||||
Script* script = &(scriptExtent->scripts[index]);
|
||||
|
||||
lastScriptExtent = scriptList->tail;
|
||||
if ((script->flags & SCRIPT_FLAG_0x08) != 0) {
|
||||
scriptCount--;
|
||||
|
||||
lastScriptExtent = scriptList->tail;
|
||||
int backwardsIndex = lastScriptExtent->length - 1;
|
||||
while (lastScriptExtent != scriptExtent || backwardsIndex > index) {
|
||||
if (lastScriptExtent == scriptExtent) {
|
||||
if (backwardsIndex >= index) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lastScriptExtent == scriptExtent && backwardsIndex <= index) {
|
||||
break;
|
||||
}
|
||||
|
||||
while (lastScriptExtent != scriptExtent || backwardsIndex > index) {
|
||||
Script* backwardsScript = &(lastScriptExtent->scripts[backwardsIndex]);
|
||||
if ((backwardsScript->flags & SCRIPT_FLAG_0x08) == 0) {
|
||||
break;
|
||||
|
@ -2427,7 +2426,7 @@ bool scriptsExecSpatialProc(Object* object, int tile, int elevation)
|
|||
return false;
|
||||
}
|
||||
|
||||
if ((object->flags & OBJECT_HIDDEN) != 0 || (object->flags & OBJECT_FLAG_0x08) != 0) {
|
||||
if ((object->flags & OBJECT_HIDDEN) != 0 || (object->flags & OBJECT_FLAT) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2685,7 +2684,7 @@ int scriptGetLocalVar(int sid, int variable, int* value)
|
|||
}
|
||||
|
||||
Script* script;
|
||||
if (scriptGetScript(sid, &script) == 1) {
|
||||
if (scriptGetScript(sid, &script) == -1) {
|
||||
*value = -1;
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,15 @@ bool sfallConfigInit(int argc, char** argv)
|
|||
}
|
||||
|
||||
// Initialize defaults.
|
||||
configSetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_DUDE_NATIVE_LOOK_JUMPSUIT_MALE_KEY, "");
|
||||
configSetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_DUDE_NATIVE_LOOK_JUMPSUIT_FEMALE_KEY, "");
|
||||
configSetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_DUDE_NATIVE_LOOK_TRIBAL_MALE_KEY, "");
|
||||
configSetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_DUDE_NATIVE_LOOK_TRIBAL_FEMALE_KEY, "");
|
||||
configSetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_MAIN_MENU_BIG_FONT_COLOR_KEY, 0);
|
||||
configSetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_MAIN_MENU_FONT_COLOR_KEY, 0);
|
||||
configSetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_SKIP_OPENING_MOVIES_KEY, 0);
|
||||
configSetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_STARTING_MAP_KEY, "");
|
||||
configSetBool(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_DISPLAY_KARMA_CHANGES_KEY, false);
|
||||
|
||||
char path[COMPAT_MAX_PATH];
|
||||
char* executable = argv[0];
|
||||
|
|
|
@ -7,7 +7,17 @@
|
|||
|
||||
#define SFALL_CONFIG_MISC_KEY "Misc"
|
||||
|
||||
#define SFALL_CONFIG_DUDE_NATIVE_LOOK_JUMPSUIT_MALE_KEY "MaleDefaultModel"
|
||||
#define SFALL_CONFIG_DUDE_NATIVE_LOOK_JUMPSUIT_FEMALE_KEY "FemaleDefaultModel"
|
||||
#define SFALL_CONFIG_DUDE_NATIVE_LOOK_TRIBAL_MALE_KEY "MaleStartModel"
|
||||
#define SFALL_CONFIG_DUDE_NATIVE_LOOK_TRIBAL_FEMALE_KEY "FemaleStartModel"
|
||||
#define SFALL_CONFIG_MAIN_MENU_BIG_FONT_COLOR_KEY "MainMenuBigFontColour"
|
||||
#define SFALL_CONFIG_MAIN_MENU_FONT_COLOR_KEY "MainMenuFontColour"
|
||||
#define SFALL_CONFIG_SKIP_OPENING_MOVIES_KEY "SkipOpeningMovies"
|
||||
#define SFALL_CONFIG_STARTING_MAP_KEY "StartingMap"
|
||||
#define SFALL_CONFIG_KARMA_FRMS_KEY "KarmaFRMs"
|
||||
#define SFALL_CONFIG_KARMA_POINTS_KEY "KarmaPoints"
|
||||
#define SFALL_CONFIG_DISPLAY_KARMA_CHANGES_KEY "DisplayKarmaChanges"
|
||||
|
||||
extern bool gSfallConfigInitialized;
|
||||
extern Config gSfallConfig;
|
||||
|
|
|
@ -323,6 +323,7 @@ int critterGetStat(Object* critter, int stat)
|
|||
}
|
||||
break;
|
||||
case STAT_DAMAGE_RESISTANCE:
|
||||
case STAT_DAMAGE_RESISTANCE_EXPLOSION:
|
||||
if (perkGetRank(critter, PERK_DERMAL_IMPACT_ARMOR)) {
|
||||
value += 5;
|
||||
} else if (perkGetRank(critter, PERK_DERMAL_IMPACT_ASSAULT_ENHANCEMENT)) {
|
||||
|
|
|
@ -125,9 +125,18 @@ int textFontLoad(int font)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (fileRead(textFontDescriptor, sizeof(TextFontDescriptor), 1, stream) != 1) {
|
||||
goto out;
|
||||
}
|
||||
// NOTE: Original code reads entire descriptor in one go. This does not work
|
||||
// in x64 because of the two pointers.
|
||||
|
||||
if (fileRead(&(textFontDescriptor->glyphCount), 4, 1, stream) != 1) goto out;
|
||||
if (fileRead(&(textFontDescriptor->lineHeight), 4, 1, stream) != 1) goto out;
|
||||
if (fileRead(&(textFontDescriptor->letterSpacing), 4, 1, stream) != 1) goto out;
|
||||
|
||||
int glyphsPtr;
|
||||
if (fileRead(&glyphsPtr, 4, 1, stream) != 1) goto out;
|
||||
|
||||
int dataPtr;
|
||||
if (fileRead(&dataPtr, 4, 1, stream) != 1) goto out;
|
||||
|
||||
textFontDescriptor->glyphs = (TextFontGlyph*)internal_malloc(textFontDescriptor->glyphCount * sizeof(TextFontGlyph));
|
||||
if (textFontDescriptor->glyphs == NULL) {
|
||||
|
|
14
src/tile.cc
14
src/tile.cc
|
@ -387,9 +387,23 @@ int tileInit(TileData** a1, int squareGridWidth, int squareGridHeight, int hexGr
|
|||
bufferDrawLine(_tile_grid_blocked, 32, v25, v20, v22, v20, _colorTable[31744]);
|
||||
}
|
||||
|
||||
// In order to calculate scroll borders correctly we need to pretend we're
|
||||
// at original resolution. Since border is calculated only once at start,
|
||||
// there is not need to change it all the time.
|
||||
gTileWindowWidth = ORIGINAL_ISO_WINDOW_WIDTH;
|
||||
gTileWindowHeight = ORIGINAL_ISO_WINDOW_HEIGHT;
|
||||
|
||||
tileSetCenter(hexGridWidth * (hexGridHeight / 2) + hexGridWidth / 2, 2);
|
||||
tileSetBorder(windowWidth, windowHeight, hexGridWidth, hexGridHeight);
|
||||
|
||||
// Restore actual window size and set center one more time to calculate
|
||||
// correct screen offsets, which are required for subsequent object update
|
||||
// area calculations.
|
||||
gTileWindowWidth = windowWidth;
|
||||
gTileWindowHeight = windowHeight;
|
||||
|
||||
tileSetCenter(hexGridWidth * (hexGridHeight / 2) + hexGridWidth / 2, 2);
|
||||
|
||||
char* executable;
|
||||
configGetString(&gGameConfig, GAME_CONFIG_SYSTEM_KEY, GAME_CONFIG_EXECUTABLE_KEY, &executable);
|
||||
if (compat_stricmp(executable, "mapper") == 0) {
|
||||
|
|
|
@ -265,6 +265,8 @@ void windowManagerExit(void)
|
|||
textFontsExit();
|
||||
_colorsClose();
|
||||
|
||||
SDL_DestroyWindow(gSdlWindow);
|
||||
|
||||
gWindowSystemInitialized = false;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
|
|
@ -617,7 +617,7 @@ bool xlistEnumerate(const char* pattern, XListEnumerationHandler* handler, XList
|
|||
}
|
||||
} while (fileFindNext(&directoryFileFindData));
|
||||
}
|
||||
return findFindClose(&directoryFileFindData);
|
||||
findFindClose(&directoryFileFindData);
|
||||
}
|
||||
xbase = xbase->next;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue