mirror of https://github.com/OpenRCT2/OpenRCT2.git
Merge with upstream
This commit is contained in:
commit
8a39d9d026
|
@ -2,6 +2,12 @@
|
|||
|
||||
sdl
|
||||
|
||||
# Compiled dll
|
||||
openrct2.dll
|
||||
|
||||
# Build artifacts
|
||||
.cache
|
||||
|
||||
#################
|
||||
## Eclipse
|
||||
#################
|
||||
|
|
38
.travis.yml
38
.travis.yml
|
@ -1,33 +1,17 @@
|
|||
language: c
|
||||
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -y --force-yes binutils-mingw-w64-i686 gcc-mingw-w64-i686 g++-mingw-w64-i686
|
||||
|
||||
# fetch precompiled SDL2 + headers for MinGW and push it into the expected directory
|
||||
- export SDL2_PV=2.0.3
|
||||
- wget http://libsdl.org/release/SDL2-devel-${SDL2_PV}-mingw.tar.gz
|
||||
- tar -xzvf SDL2-devel-${SDL2_PV}-mingw.tar.gz
|
||||
|
||||
# but first fix SDL2 bug
|
||||
- wget "https://github.com/anyc/anyc-overlay/raw/master/media-libs/libsdl2-mingw/files/libsdl2-mingw-2.0.3-fix-platform-detection-for-mingw.patch"
|
||||
- pushd SDL2-${SDL2_PV}/i686-w64-mingw32/include/SDL2/ && patch -p2 < ../../../../libsdl2-mingw-2.0.3-fix-platform-detection-for-mingw.patch && popd
|
||||
|
||||
- sudo mkdir -p /usr/local/cross-tools/
|
||||
- sudo mv SDL2-${SDL2_PV}/i686-w64-mingw32 /usr/local/cross-tools/
|
||||
|
||||
# build a wrapper that looks for the sdl2.pc file in the new directory
|
||||
- echo -e "#! /bin/sh\\nexport PKG_CONFIG_LIBDIR=/usr/local/cross-tools/i686-w64-mingw32/lib/pkgconfig\\npkg-config \$@" > i686-w64-mingw32-pkg-config
|
||||
- chmod +x i686-w64-mingw32-pkg-config
|
||||
- sudo mv i686-w64-mingw32-pkg-config /usr/local/bin/
|
||||
- bash install.sh
|
||||
|
||||
script:
|
||||
- mkdir build
|
||||
- pushd build
|
||||
- cmake -DCMAKE_TOOLCHAIN_FILE=../CMakeLists_mingw.txt -DCMAKE_BUILD_TYPE=Debug ..
|
||||
- make
|
||||
#- make VERBOSE=1
|
||||
- popd
|
||||
- bash build.sh
|
||||
|
||||
#notifications:
|
||||
#irc: "irc.freenode.net#openrct2"
|
||||
notifications:
|
||||
irc: "irc.freenode.net#openrct2-dev"
|
||||
on_failure: always
|
||||
on_success: change
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- cache
|
||||
apt: true
|
||||
|
|
|
@ -1,16 +1,25 @@
|
|||
SET(CMAKE_SYSTEM_NAME Windows)
|
||||
|
||||
SET(COMPILER_PREFIX i686-w64-mingw32)
|
||||
SET(CMAKE_C_COMPILER ${COMPILER_PREFIX}-gcc)
|
||||
SET(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}-c++)
|
||||
SET(CMAKE_RC_COMPILER ${COMPILER_PREFIX}-windres)
|
||||
SET(CMAKE_PKGCONFIG_EXECUTABLE ${COMPILER_PREFIX}-pkg-config)
|
||||
SET(PKG_CONFIG_EXECUTABLE ${COMPILER_PREFIX}-pkg-config)
|
||||
if (APPLE)
|
||||
SET(COMPILER_PREFIX i586-mingw32)
|
||||
SET(CMAKE_C_COMPILER ${COMPILER_PREFIX}-gcc)
|
||||
SET(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}-c++)
|
||||
SET(CMAKE_RC_COMPILER ${COMPILER_PREFIX}-windres)
|
||||
SET(CMAKE_PKGCONFIG_EXECUTABLE i686-w64-mingw32-pkg-config)
|
||||
SET(PKG_CONFIG_EXECUTABLE i686-w64-mingw32-pkg-config)
|
||||
else()
|
||||
SET(COMPILER_PREFIX i686-w64-mingw32)
|
||||
SET(CMAKE_C_COMPILER ${COMPILER_PREFIX}-gcc)
|
||||
SET(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}-c++)
|
||||
SET(CMAKE_RC_COMPILER ${COMPILER_PREFIX}-windres)
|
||||
SET(CMAKE_PKGCONFIG_EXECUTABLE ${COMPILER_PREFIX}-pkg-config)
|
||||
SET(PKG_CONFIG_EXECUTABLE ${COMPILER_PREFIX}-pkg-config)
|
||||
endif (APPLE)
|
||||
|
||||
# potential flags to make code more similar to MSVC:
|
||||
# -fshort-wchar -fshort-enums -mms-bitfields -fpack-struct=1
|
||||
# -fshort-wchar -fshort-enums -mms-bitfields
|
||||
#
|
||||
set(CMAKE_C_FLAGS "-masm=intel -std=gnu99" CACHE STRING "" FORCE)
|
||||
set(CMAKE_C_FLAGS "-masm=intel -std=gnu99 -fpack-struct=2" CACHE STRING "" FORCE)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "-static-libgcc" CACHE STRING "" FORCE)
|
||||
|
||||
include_directories("/usr/include/wine/windows/")
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [[ ! -d build ]]; then
|
||||
mkdir -p build
|
||||
fi
|
||||
|
||||
pushd build
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=../CMakeLists_mingw.txt -DCMAKE_BUILD_TYPE=Debug ..
|
||||
make
|
||||
popd
|
||||
|
||||
if [[ -t 1 ]]; then
|
||||
echo -e "\nDone! Run OpenRCT2 by typing:\n\n\033[95mwine openrct2.exe\n\033[0m"
|
||||
else
|
||||
echo -e "\nDone! Run OpenRCT2 by typing:\n\nwine openrct2.exe\n"
|
||||
fi
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ev
|
||||
|
||||
sudo rm -rf /usr/local/cross-tools/i686-w64-mingw32
|
||||
#rm -rf .cache
|
||||
rm -rf .cache/*.patch
|
||||
rm -rf .cache/SDL2-2.0.3
|
||||
rm -rf .cache/i686-w64-mingw32-pkg-config
|
||||
rm -rf build
|
|
@ -0,0 +1,78 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
SDL2_PV=2.0.3
|
||||
|
||||
cachedir=.cache
|
||||
mkdir -p $cachedir
|
||||
|
||||
echo `uname`
|
||||
|
||||
if [[ `uname` == "Darwin" ]]; then
|
||||
echo "Installation of OpenRCT2 assumes you have homebrew and use it to install packages."
|
||||
# Very possible I'm missing some dependencies here.
|
||||
brew install cmake wine
|
||||
|
||||
if [[ ! -d /usr/include/wine ]]; then
|
||||
# This will almost certainly break as brew changes. Better ideas
|
||||
# welcome.
|
||||
sudo ln -s /usr/local/Cellar/wine/1.6.2/include/wine /usr/include
|
||||
fi
|
||||
|
||||
mingw_dmg=gcc-4.8.0-qt-4.8.4-for-mingw32.dmg
|
||||
mingw_path=/usr/local/gcc-4.8.0-qt-4.8.4-for-mingw32/win32-gcc/bin
|
||||
if [[ ! -f $cachedir/$mingw_dmg ]]; then
|
||||
wget http://crossgcc.rts-software.org/download/gcc-4.8.0-qt-4.8.4-win32/$mingw_dmg --output-document $cachedir/$mingw_dmg
|
||||
fi
|
||||
|
||||
if [[ ! -d $mingw_path ]]; then
|
||||
echo "Open the DMG file and install its contents"
|
||||
open $cachedir/$mingw_dmg
|
||||
fi
|
||||
|
||||
echo "You will need to add $mingw_path to your \$PATH"
|
||||
elif [[ `uname` == "Linux" ]]; then
|
||||
sudo apt-get install -y --force-yes binutils-mingw-w64-i686 gcc-mingw-w64-i686 g++-mingw-w64-i686
|
||||
fi
|
||||
|
||||
if [[ ! -f $cachedir/SDL2-devel-${SDL2_PV}-mingw.tar.gz ]]; then
|
||||
wget http://libsdl.org/release/SDL2-devel-${SDL2_PV}-mingw.tar.gz --output-document $cachedir/SDL2-devel-${SDL2_PV}-mingw.tar.gz;
|
||||
fi
|
||||
if [[ ! -d $cachedir/SDL2-${SDL2_PV} ]]; then
|
||||
pushd $cachedir
|
||||
tar -xzf SDL2-devel-${SDL2_PV}-mingw.tar.gz
|
||||
popd
|
||||
fi
|
||||
|
||||
# Apply platform patch
|
||||
mingw_patch=libsdl2-mingw-2.0.3-fix-platform-detection-for-mingw.patch
|
||||
if [[ ! -f $cachedir/$mingw_patch ]]; then
|
||||
wget "https://github.com/anyc/anyc-overlay/raw/master/media-libs/libsdl2-mingw/files/$mingw_patch" --output-document $cachedir/$mingw_patch;
|
||||
|
||||
# XXX not sure how to make this idempotent.
|
||||
pushd $cachedir/SDL2-${SDL2_PV}/i686-w64-mingw32/include/SDL2/
|
||||
echo "Applying patch."
|
||||
patch -p2 < ../../../../$mingw_patch
|
||||
popd
|
||||
fi
|
||||
|
||||
if [[ ! -d /usr/local/cross-tools ]]; then
|
||||
sudo mkdir -p /usr/local/cross-tools
|
||||
fi
|
||||
if [[ ! -d /usr/local/cross-tools/i686-w64-mingw32 ]]; then
|
||||
sudo cp -r $cachedir/SDL2-${SDL2_PV}/i686-w64-mingw32 /usr/local/cross-tools/
|
||||
fi
|
||||
|
||||
if [[ ! -f $cachedir/i686-w64-mingw32-pkg-config ]]; then
|
||||
# If this fails to work because of newlines, be sure you are running this
|
||||
# script with Bash, and not sh. We should really move this to a separate
|
||||
# file.
|
||||
echo -e "#! /bin/sh\nexport PKG_CONFIG_LIBDIR=/usr/local/cross-tools/i686-w64-mingw32/lib/pkgconfig\npkg-config \$@" > $cachedir/i686-w64-mingw32-pkg-config;
|
||||
fi
|
||||
|
||||
chmod +x $cachedir/i686-w64-mingw32-pkg-config
|
||||
sudo cp $cachedir/i686-w64-mingw32-pkg-config /usr/local/bin/
|
||||
|
||||
ls -al /usr/local/bin | grep pkg-config
|
||||
cat /usr/local/bin/i686-w64-mingw32-pkg-config
|
|
@ -671,4 +671,4 @@ into proprietary programs. If your program is a subroutine library, you
|
|||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<ItemGroup>
|
||||
<ClInclude Include="..\src\addresses.h" />
|
||||
<ClInclude Include="..\src\audio.h" />
|
||||
<ClInclude Include="..\src\award.h" />
|
||||
<ClInclude Include="..\src\climate.h" />
|
||||
<ClInclude Include="..\src\config.h" />
|
||||
<ClInclude Include="..\src\date.h" />
|
||||
|
@ -26,6 +27,7 @@
|
|||
<ClInclude Include="..\src\gfx.h" />
|
||||
<ClInclude Include="..\src\intro.h" />
|
||||
<ClInclude Include="..\src\map.h" />
|
||||
<ClInclude Include="..\src\marketing.h" />
|
||||
<ClInclude Include="..\src\news_item.h" />
|
||||
<ClInclude Include="..\src\object.h" />
|
||||
<ClInclude Include="..\src\osinterface.h" />
|
||||
|
@ -38,7 +40,6 @@
|
|||
<ClInclude Include="..\src\sawyercoding.h" />
|
||||
<ClInclude Include="..\src\scenario.h" />
|
||||
<ClInclude Include="..\src\screenshot.h" />
|
||||
<ClInclude Include="..\src\settings.h" />
|
||||
<ClInclude Include="..\src\sprite.h" />
|
||||
<ClInclude Include="..\src\sprites.h" />
|
||||
<ClInclude Include="..\src\string_ids.h" />
|
||||
|
@ -46,6 +47,7 @@
|
|||
<ClInclude Include="..\src\track.h" />
|
||||
<ClInclude Include="..\src\tutorial.h" />
|
||||
<ClInclude Include="..\src\util.h" />
|
||||
<ClInclude Include="..\src\vehicle.h" />
|
||||
<ClInclude Include="..\src\viewport.h" />
|
||||
<ClInclude Include="..\src\widget.h" />
|
||||
<ClInclude Include="..\src\window.h" />
|
||||
|
@ -57,6 +59,7 @@
|
|||
<ItemGroup>
|
||||
<ClCompile Include="..\lodepng\lodepng.c" />
|
||||
<ClCompile Include="..\src\audio.c" />
|
||||
<ClCompile Include="..\src\award.c" />
|
||||
<ClCompile Include="..\src\climate.c" />
|
||||
<ClCompile Include="..\src\config.c" />
|
||||
<ClCompile Include="..\src\date.c" />
|
||||
|
@ -66,6 +69,7 @@
|
|||
<ClCompile Include="..\src\gfx.c" />
|
||||
<ClCompile Include="..\src\intro.c" />
|
||||
<ClCompile Include="..\src\map.c" />
|
||||
<ClCompile Include="..\src\marketing.c" />
|
||||
<ClCompile Include="..\src\news_item.c" />
|
||||
<ClCompile Include="..\src\object.c" />
|
||||
<ClCompile Include="..\src\object_list.c" />
|
||||
|
@ -80,11 +84,13 @@
|
|||
<ClCompile Include="..\src\scenario.c" />
|
||||
<ClCompile Include="..\src\scenario_list.c" />
|
||||
<ClCompile Include="..\src\screenshot.c" />
|
||||
<ClCompile Include="..\src\sprite.c" />
|
||||
<ClCompile Include="..\src\string_ids.c" />
|
||||
<ClCompile Include="..\src\title.c" />
|
||||
<ClCompile Include="..\src\track.c" />
|
||||
<ClCompile Include="..\src\tutorial.c" />
|
||||
<ClCompile Include="..\src\util.c" />
|
||||
<ClCompile Include="..\src\vehicle.c" />
|
||||
<ClCompile Include="..\src\viewport.c" />
|
||||
<ClCompile Include="..\src\widget.c" />
|
||||
<ClCompile Include="..\src\window.c" />
|
||||
|
@ -199,4 +205,4 @@
|
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
|
@ -126,10 +126,16 @@
|
|||
<ClInclude Include="..\src\screenshot.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\settings.h">
|
||||
<ClInclude Include="..\src\finance.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\finance.h">
|
||||
<ClInclude Include="..\src\vehicle.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\marketing.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\award.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
|
@ -314,10 +320,22 @@
|
|||
<ClCompile Include="..\src\object_list.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\vehicle.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\sprite.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\marketing.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\award.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\openrct2.exe">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
|
@ -84,6 +84,8 @@
|
|||
#define RCT2_ADDRESS_DIRTY_BLOCK_COLUMNS 0x009ABDE8
|
||||
#define RCT2_ADDRESS_DIRTY_BLOCK_ROWS 0x009ABDEC
|
||||
|
||||
#define RCT2_ADDRESS_LIGHTNING_ACTIVE 0x009AC068
|
||||
|
||||
#define RCT2_ADDRESS_RUN_INTRO_TICK_PART 0x009AC319
|
||||
|
||||
#define RCT2_ADDRESS_INSTALLED_OBJECT_LIST 0x009ADAE8
|
||||
|
@ -111,6 +113,10 @@
|
|||
#define RCT2_ADDRESS_CURRENT_TOOL 0x009DE545
|
||||
#define RCT2_ADDRESS_TOOL_WIDGETINDEX 0x009DE546
|
||||
|
||||
#define RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE 0x009DE550
|
||||
#define RCT2_ADDRESS_PICKEDUP_PEEP_X 0x009DE554
|
||||
#define RCT2_ADDRESS_PICKEDUP_PEEP_Y 0x009DE556
|
||||
|
||||
#define RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS 0x009DE55C
|
||||
#define RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER 0x009DE55E
|
||||
#define RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX 0x009DE560
|
||||
|
@ -176,11 +182,11 @@
|
|||
#define RCT2_ADDRESS_PARK_FLAGS 0x013573E4
|
||||
#define RCT2_ADDRESS_PARK_ENTRANCE_FEE 0x013573E8
|
||||
#define RCT2_ADDRESS_GUESTS_IN_PARK 0x01357844
|
||||
#define RCT2_ADDRESS_GUESTS_HEADING_FOR_PARK 0x01357846
|
||||
#define RCT2_ADDRESS_MONTHLY_RIDE_INCOME 0x01357894
|
||||
#define RCT2_ADDRESS_CURRENT_PARK_RATING 0x01357CB0
|
||||
#define RCT2_ADDRESS_PARK_RATING_HISTORY 0x01357CB2
|
||||
#define RCT2_ADDRESS_GUESTS_IN_PARK_HISTORY 0x01357CD2
|
||||
#define RCT2_ADDRESS_GUEST_GENERATION_PROBABILITY 0x013580EC
|
||||
#define RCT2_ADDRESS_OBJECTIVE_TYPE 0x013580F8
|
||||
#define RCT2_ADDRESS_OBJECTIVE_YEAR 0x013580F9
|
||||
#define RCT2_ADDRESS_OBJECTIVE_CURRENCY 0x013580FC
|
||||
|
@ -218,6 +224,8 @@
|
|||
#define RCT2_ADDRESS_MAP_SIZE 0x01358834
|
||||
#define RCT2_ADDRESS_PARK_SIZE 0x013580EA
|
||||
|
||||
#define RCT2_TOTAL_RIDE_VALUE 0x013580EE
|
||||
|
||||
#define RCT2_ADDRESS_SCENARIO_NAME 0x0135920A
|
||||
#define RCT2_ADDRESS_SCENARIO_DETAILS 0x0135924A
|
||||
|
||||
|
@ -249,6 +257,7 @@
|
|||
#define RCT2_ADDRESS_NEWS_ITEM_LIST 0x013CA754
|
||||
|
||||
#define RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE 0x013CE950
|
||||
#define RCT2_ADDRESS_CURRENT_FONT_FLAGS 0x013CE9A2
|
||||
|
||||
#define RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS 0x013CE9A4
|
||||
#define RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT 0x0141E9AC
|
||||
|
@ -257,6 +266,10 @@
|
|||
#define RCT2_ADDRESS_GAME_COMMAND_ERROR_STRING_ID 0x0141E9AE
|
||||
#define RCT2_ADDRESS_CURRENT_ROTATION 0x0141E9E0
|
||||
|
||||
#define RCT2_ADDRESS_FONT_CHAR_WIDTH 0x0141E9E8
|
||||
|
||||
#define RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER 0x0141ED68
|
||||
|
||||
#define RCT2_ADDRESS_WATER_RAISE_COST 0x0141F738
|
||||
#define RCT2_ADDRESS_WATER_LOWER_COST 0x0141F73C
|
||||
|
||||
|
@ -357,6 +370,47 @@ static void RCT2_CALLPROC_X(int address, int _eax, int _ebx, int _ecx, int _edx,
|
|||
#endif
|
||||
}
|
||||
|
||||
static void RCT2_CALLPROC_X_EBPSAFE(int address, int _eax, int _ebx, int _ecx, int _edx, int _esi, int _edi, int _ebp)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
__asm {
|
||||
push ebp
|
||||
push address
|
||||
mov eax, _eax
|
||||
mov ebx, _ebx
|
||||
mov ecx, _ecx
|
||||
mov edx, _edx
|
||||
mov esi, _esi
|
||||
mov edi, _edi
|
||||
mov ebp, _ebp
|
||||
call[esp]
|
||||
add esp, 4
|
||||
pop ebp
|
||||
}
|
||||
#else
|
||||
__asm__ ( "\
|
||||
\n\
|
||||
push ebx \n\
|
||||
push ebp \n\
|
||||
push %[address] \n\
|
||||
mov eax, %[_eax] \n\
|
||||
mov ebx, %[_ebx] \n\
|
||||
mov ecx, %[_ecx] \n\
|
||||
mov edx, %[_edx] \n\
|
||||
mov esi, %[_esi] \n\
|
||||
mov edi, %[_edi] \n\
|
||||
mov ebp, %[_ebp] \n\
|
||||
call [esp] \n\
|
||||
add esp, 4 \n\
|
||||
pop ebp \n\
|
||||
pop ebx \n\
|
||||
" : [address] "+m" (address), [_eax] "+m" (_eax), [_ebx] "+m" (_ebx), [_ecx] "+m" (_ecx), [_edx] "+m" (_edx), [_esi] "+m" (_esi), [_edi] "+m" (_edi), [_ebp] "+m" (_ebp)
|
||||
:
|
||||
: "eax","ecx","edx","esi","edi"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void RCT2_CALLFUNC_X(int address, int *_eax, int *_ebx, int *_ecx, int *_edx, int *_esi, int *_edi, int *_ebp)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
|
|
66
src/audio.h
66
src/audio.h
|
@ -64,9 +64,69 @@ void pause_sounds();
|
|||
void unpause_sounds();
|
||||
|
||||
typedef enum {
|
||||
RCT2_SOUND_SCREAM = 11,
|
||||
RCT2_SOUND_CHAINLIFT = 56,
|
||||
RCT2_SOUND_TRACKFRICTION = 57,
|
||||
SOUND_LIFT_1 = 0,
|
||||
SOUND_TRACK_FRICTION_1 = 1,
|
||||
SOUND_LIFT_2 = 2,
|
||||
SOUND_SCREAM_1 = 3,
|
||||
SOUND_CLICK_1 = 4,
|
||||
SOUND_CLICK_2 = 5,
|
||||
SOUND_PLACE_ITEM = 6,
|
||||
SOUND_SCREAM_2 = 7,
|
||||
SOUND_SCREAM_3 = 8,
|
||||
SOUND_SCREAM_4 = 9,
|
||||
SOUND_SCREAM_5 = 10,
|
||||
SOUND_SCREAM_6 = 11,
|
||||
SOUND_LIFT_3 = 12,
|
||||
SOUND_PURCHASE = 13,
|
||||
SOUND_CRASH = 14,
|
||||
SOUND_LAYING_OUT_WATER = 15,
|
||||
SOUND_WATER_1 = 16,
|
||||
SOUND_WATER_2 = 17,
|
||||
SOUND_TRAIN_WHISTLE = 18,
|
||||
SOUND_TRAIN_CHUGGING = 19,
|
||||
SOUND_WATER_SPLASH = 20,
|
||||
SOUND_HAMMERING = 21,
|
||||
SOUND_RIDE_LAUNCH_1 = 22,
|
||||
SOUND_RIDE_LAUNCH_2 = 23,
|
||||
SOUND_COUGH_1 = 24,
|
||||
SOUND_COUGH_2 = 25,
|
||||
SOUND_COUGH_3 = 26,
|
||||
SOUND_COUGH_4 = 27,
|
||||
SOUND_RAIN_1 = 28,
|
||||
SOUND_THUNDER_1 = 29,
|
||||
SOUND_THUNDER_2 = 30,
|
||||
SOUND_RAIN_2 = 31,
|
||||
SOUND_RAIN_3 = 32,
|
||||
SOUND_BALLOON_POP = 33,
|
||||
SOUND_MECHANIC_FIX = 34,
|
||||
SOUND_SCREAM_7 = 35,
|
||||
SOUND_TOILET_FLUSH = 36,
|
||||
SOUND_CLICK_3 = 37,
|
||||
SOUND_QUACK = 38,
|
||||
SOUND_NEWS_ITEM = 39,
|
||||
SOUND_WINDOW_OPEN = 40,
|
||||
SOUND_LAUGH_1 = 41,
|
||||
SOUND_LAUGH_2 = 42,
|
||||
SOUND_LAUGH_3 = 43,
|
||||
SOUND_APPLAUSE = 44,
|
||||
SOUND_HAUNTED_HOUSE_SCARE = 45,
|
||||
SOUND_HAUNTED_HOUSE_SCREAM_1 = 46,
|
||||
SOUND_HAUNTED_HOUSE_SCREAM_2 = 47,
|
||||
SOUND_48 = 48,
|
||||
SOUND_49 = 49,
|
||||
SOUND_ERROR = 50,
|
||||
SOUND_51 = 51,
|
||||
SOUND_LIFT_4 = 52,
|
||||
SOUND_LIFT_5 = 53,
|
||||
SOUND_TRACK_FRICTION_2 = 54,
|
||||
SOUND_LIFT_6 = 55,
|
||||
SOUND_LIFT_7 = 56,
|
||||
SOUND_TRACK_FRICTION_3 = 57,
|
||||
SOUND_SCREAM_8 = 58,
|
||||
SOUND_TRAM = 59,
|
||||
SOUND_DOOR_OPEN = 60,
|
||||
SOUND_DOOR_CLOSE = 61,
|
||||
SOUND_62 = 62
|
||||
} RCT2_SOUND;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,625 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (c) 2014 Ted John
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* This file is part of OpenRCT2.
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "addresses.h"
|
||||
#include "award.h"
|
||||
#include "news_item.h"
|
||||
#include "peep.h"
|
||||
#include "ride.h"
|
||||
#include "scenario.h"
|
||||
#include "sprite.h"
|
||||
#include "window.h"
|
||||
|
||||
#define NEGATIVE 0
|
||||
#define POSITIVE 1
|
||||
|
||||
int _awardPositiveMap[] = {
|
||||
NEGATIVE, // PARK_AWARD_MOST_UNTIDY
|
||||
POSITIVE, // PARK_AWARD_MOST_TIDY
|
||||
POSITIVE, // PARK_AWARD_BEST_ROLLERCOASTERS
|
||||
POSITIVE, // PARK_AWARD_BEST_VALUE
|
||||
POSITIVE, // PARK_AWARD_MOST_BEAUTIFUL
|
||||
NEGATIVE, // PARK_AWARD_WORST_VALUE
|
||||
POSITIVE, // PARK_AWARD_SAFEST
|
||||
POSITIVE, // PARK_AWARD_BEST_STAFF
|
||||
POSITIVE, // PARK_AWARD_BEST_FOOD
|
||||
NEGATIVE, // PARK_AWARD_WORST_FOOD
|
||||
POSITIVE, // PARK_AWARD_BEST_RESTROOMS
|
||||
NEGATIVE, // PARK_AWARD_MOST_DISAPPOINTING
|
||||
POSITIVE, // PARK_AWARD_BEST_WATER_RIDES
|
||||
POSITIVE, // PARK_AWARD_BEST_CUSTOM_DESIGNED_RIDES
|
||||
POSITIVE, // PARK_AWARD_MOST_DAZZLING_RIDE_COLOURS
|
||||
NEGATIVE, // PARK_AWARD_MOST_CONFUSING_LAYOUT
|
||||
POSITIVE, // PARK_AWARD_BEST_GENTLE_RIDES
|
||||
};
|
||||
|
||||
int award_is_positive(int type)
|
||||
{
|
||||
return _awardPositiveMap[type];
|
||||
}
|
||||
|
||||
#pragma region Award checks
|
||||
|
||||
/** More than 1/16 of the total guests must be thinking untidy thoughts. */
|
||||
static int award_is_deserved_most_untidy(int awardType, int activeAwardTypes)
|
||||
{
|
||||
uint16 spriteIndex;
|
||||
rct_peep *peep;
|
||||
int negativeCount;
|
||||
|
||||
if (activeAwardTypes & (1 << PARK_AWARD_MOST_BEAUTIFUL))
|
||||
return 0;
|
||||
if (activeAwardTypes & (1 << PARK_AWARD_BEST_STAFF))
|
||||
return 0;
|
||||
if (activeAwardTypes & (1 << PARK_AWARD_MOST_TIDY))
|
||||
return 0;
|
||||
|
||||
negativeCount = 0;
|
||||
FOR_ALL_GUESTS(spriteIndex, peep) {
|
||||
if (peep->var_2A != 0)
|
||||
continue;
|
||||
|
||||
if (peep->thoughts[0].var_2 > 5)
|
||||
continue;
|
||||
|
||||
if (peep->thoughts[0].type == PEEP_THOUGHT_TYPE_BAD_LITTER ||
|
||||
peep->thoughts[0].type == PEEP_THOUGHT_TYPE_PATH_DISGUSTING ||
|
||||
peep->thoughts[0].type == PEEP_THOUGHT_TYPE_VANDALISM
|
||||
) {
|
||||
negativeCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return (negativeCount > RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16) / 16);
|
||||
}
|
||||
|
||||
/** More than 1/64 of the total guests must be thinking tidy thoughts and less than 6 guests thinking untidy thoughts. */
|
||||
static int award_is_deserved_most_tidy(int awardType, int activeAwardTypes)
|
||||
{
|
||||
uint16 spriteIndex;
|
||||
rct_peep *peep;
|
||||
int positiveCount;
|
||||
int negativeCount;
|
||||
|
||||
if (activeAwardTypes & (1 << PARK_AWARD_MOST_UNTIDY))
|
||||
return 0;
|
||||
if (activeAwardTypes & (1 << PARK_AWARD_MOST_DISAPPOINTING))
|
||||
return 0;
|
||||
|
||||
positiveCount = 0;
|
||||
negativeCount = 0;
|
||||
FOR_ALL_GUESTS(spriteIndex, peep) {
|
||||
if (peep->var_2A != 0)
|
||||
continue;
|
||||
|
||||
if (peep->thoughts[0].var_2 > 5)
|
||||
continue;
|
||||
|
||||
if (peep->thoughts[0].type == PEEP_THOUGHT_VERY_CLEAN)
|
||||
positiveCount++;
|
||||
|
||||
if (peep->thoughts[0].type == PEEP_THOUGHT_TYPE_BAD_LITTER ||
|
||||
peep->thoughts[0].type == PEEP_THOUGHT_TYPE_PATH_DISGUSTING ||
|
||||
peep->thoughts[0].type == PEEP_THOUGHT_TYPE_VANDALISM
|
||||
) {
|
||||
negativeCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return (negativeCount <= 5 && positiveCount > RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16) / 64);
|
||||
}
|
||||
|
||||
/** At least 6 open roller coasters. */
|
||||
static int award_is_deserved_best_rollercoasters(int awardType, int activeAwardTypes)
|
||||
{
|
||||
int i, rollerCoasters;
|
||||
rct_ride *ride;
|
||||
char *object;
|
||||
|
||||
rollerCoasters = 0;
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
object = RCT2_ADDRESS(0x009ACFA4, char*)[ride->subtype];
|
||||
if (RCT2_GLOBAL(object + 0x1BE, uint8) != RIDE_GROUP_ROLLERCOASTER && RCT2_GLOBAL(object + 0x1BF, uint8) != RIDE_GROUP_ROLLERCOASTER)
|
||||
continue;
|
||||
|
||||
if (ride->status != RIDE_STATUS_OPEN || (ride->lifecycle_flags & 0x400))
|
||||
continue;
|
||||
|
||||
rollerCoasters++;
|
||||
}
|
||||
|
||||
return (rollerCoasters >= 6);
|
||||
}
|
||||
|
||||
/** Entrance fee is 0.10 less than half of the total ride value. */
|
||||
static int award_is_deserved_best_value(int awardType, int activeAwardTypes)
|
||||
{
|
||||
if (activeAwardTypes & (1 << PARK_AWARD_WORST_VALUE))
|
||||
return 0;
|
||||
if (activeAwardTypes & (1 << PARK_AWARD_MOST_DISAPPOINTING))
|
||||
return 0;
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & (PARK_FLAGS_11 | PARK_FLAGS_PARK_FREE_ENTRY))
|
||||
return 0;
|
||||
if (RCT2_GLOBAL(RCT2_TOTAL_RIDE_VALUE, money16) < MONEY(10, 00))
|
||||
return 0;
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16) + MONEY(0, 10) >= RCT2_GLOBAL(RCT2_TOTAL_RIDE_VALUE, money16) / 2)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** More than 1/128 of the total guests must be thinking scenic thoughts and less than 16 untidy thoughts. */
|
||||
static int award_is_deserved_most_beautiful(int awardType, int activeAwardTypes)
|
||||
{
|
||||
uint16 spriteIndex;
|
||||
rct_peep *peep;
|
||||
int positiveCount;
|
||||
int negativeCount;
|
||||
|
||||
if (activeAwardTypes & (1 << PARK_AWARD_MOST_UNTIDY))
|
||||
return 0;
|
||||
if (activeAwardTypes & (1 << PARK_AWARD_MOST_DISAPPOINTING))
|
||||
return 0;
|
||||
|
||||
positiveCount = 0;
|
||||
negativeCount = 0;
|
||||
FOR_ALL_GUESTS(spriteIndex, peep) {
|
||||
if (peep->var_2A != 0)
|
||||
continue;
|
||||
|
||||
if (peep->thoughts[0].var_2 > 5)
|
||||
continue;
|
||||
|
||||
if (peep->thoughts[0].type == PEEP_THOUGHT_TYPE_SCENERY)
|
||||
positiveCount++;
|
||||
|
||||
if (peep->thoughts[0].type == PEEP_THOUGHT_TYPE_BAD_LITTER ||
|
||||
peep->thoughts[0].type == PEEP_THOUGHT_TYPE_PATH_DISGUSTING ||
|
||||
peep->thoughts[0].type == PEEP_THOUGHT_TYPE_VANDALISM
|
||||
) {
|
||||
negativeCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return (negativeCount <= 15 && positiveCount > RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16) / 128);
|
||||
}
|
||||
|
||||
/** Entrance fee is more than total ride value. */
|
||||
static int award_is_deserved_worse_value(int awardType, int activeAwardTypes)
|
||||
{
|
||||
if (activeAwardTypes & (1 << PARK_AWARD_BEST_VALUE))
|
||||
return 0;
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_11)
|
||||
return 0;
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16) == MONEY(0, 00))
|
||||
return 0;
|
||||
if (RCT2_GLOBAL(RCT2_TOTAL_RIDE_VALUE, money16) >= RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** No more than 2 people who think the vandalism is bad and no crashes. */
|
||||
static int award_is_deserved_safest(int awardType, int activeAwardTypes)
|
||||
{
|
||||
int i, peepsWhoDislikeVandalism;
|
||||
uint16 spriteIndex;
|
||||
rct_peep *peep;
|
||||
rct_ride *ride;
|
||||
|
||||
peepsWhoDislikeVandalism = 0;
|
||||
FOR_ALL_GUESTS(spriteIndex, peep) {
|
||||
if (peep->var_2A != 0)
|
||||
continue;
|
||||
if (peep->thoughts[0].var_2 <= 5 && peep->thoughts[0].type == PEEP_THOUGHT_TYPE_VANDALISM)
|
||||
peepsWhoDislikeVandalism++;
|
||||
}
|
||||
|
||||
if (peepsWhoDislikeVandalism > 2)
|
||||
return 0;
|
||||
|
||||
// Check for rides that have crashed maybe?
|
||||
FOR_ALL_RIDES(i, ride)
|
||||
if (ride->var_1AE != 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** All staff types, at least 20 staff, one staff per 32 peeps. */
|
||||
static int award_is_deserved_best_staff(int awardType, int activeAwardTypes)
|
||||
{
|
||||
uint16 spriteIndex;
|
||||
rct_peep *peep;
|
||||
int peepCount, staffCount;
|
||||
int staffTypeFlags;
|
||||
|
||||
if (activeAwardTypes & (1 << PARK_AWARD_MOST_UNTIDY))
|
||||
return 0;
|
||||
|
||||
peepCount = 0;
|
||||
staffCount = 0;
|
||||
staffTypeFlags = 0;
|
||||
FOR_ALL_PEEPS(spriteIndex, peep) {
|
||||
if (peep->type == PEEP_TYPE_STAFF) {
|
||||
staffCount++;
|
||||
staffTypeFlags |= (1 << peep->staff_type);
|
||||
} else {
|
||||
peepCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return ((staffTypeFlags & 0xF) && staffCount >= 20 && staffCount >= peepCount / 32);
|
||||
|
||||
}
|
||||
|
||||
/** At least 7 shops, 4 unique, one shop per 128 guests and no more than 12 hungry guests. */
|
||||
static int award_is_deserved_best_food(int awardType, int activeAwardTypes)
|
||||
{
|
||||
int i, hungryPeeps, shops, uniqueShops;
|
||||
uint64 shopTypes;
|
||||
rct_ride *ride;
|
||||
char *object;
|
||||
uint16 spriteIndex;
|
||||
rct_peep *peep;
|
||||
|
||||
if (activeAwardTypes & (1 << PARK_AWARD_WORST_FOOD))
|
||||
return 0;
|
||||
|
||||
shops = 0;
|
||||
uniqueShops = 0;
|
||||
shopTypes = 0;
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
if (ride->status != RIDE_STATUS_OPEN)
|
||||
continue;
|
||||
if (!(RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x800000))
|
||||
continue;
|
||||
|
||||
shops++;
|
||||
object = RCT2_ADDRESS(0x009ACFA4, char*)[ride->subtype];
|
||||
if (!(shopTypes & (1ULL << RCT2_GLOBAL(object + 0x1C0, uint8)))) {
|
||||
shopTypes |= (1ULL << RCT2_GLOBAL(object + 0x1C0, uint8));
|
||||
uniqueShops++;
|
||||
}
|
||||
}
|
||||
|
||||
if (shops < 7 || uniqueShops < 4 || shops < RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16) / 128)
|
||||
return 0;
|
||||
|
||||
// Count hungry peeps
|
||||
hungryPeeps = 0;
|
||||
FOR_ALL_GUESTS(spriteIndex, peep) {
|
||||
if (peep->var_2A != 0)
|
||||
continue;
|
||||
|
||||
if (peep->thoughts[0].var_2 <= 5 && peep->thoughts[0].type == PEEP_THOUGHT_TYPE_HUNGRY)
|
||||
hungryPeeps++;
|
||||
}
|
||||
|
||||
return (hungryPeeps <= 12);
|
||||
}
|
||||
|
||||
/** No more than 2 unique shops, less than one shop per 256 guests and more than 15 hungry guests. */
|
||||
static int award_is_deserved_worst_food(int awardType, int activeAwardTypes)
|
||||
{
|
||||
int i, hungryPeeps, shops, uniqueShops;
|
||||
uint64 shopTypes;
|
||||
rct_ride *ride;
|
||||
char *object;
|
||||
uint16 spriteIndex;
|
||||
rct_peep *peep;
|
||||
|
||||
if (activeAwardTypes & (1 << PARK_AWARD_BEST_FOOD))
|
||||
return 0;
|
||||
|
||||
shops = 0;
|
||||
uniqueShops = 0;
|
||||
shopTypes = 0;
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
if (ride->status != RIDE_STATUS_OPEN)
|
||||
continue;
|
||||
if (!(RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x800000))
|
||||
continue;
|
||||
|
||||
shops++;
|
||||
object = RCT2_ADDRESS(0x009ACFA4, char*)[ride->subtype];
|
||||
if (!(shopTypes & (1ULL << RCT2_GLOBAL(object + 0x1C0, uint8)))) {
|
||||
shopTypes |= (1ULL << RCT2_GLOBAL(object + 0x1C0, uint8));
|
||||
uniqueShops++;
|
||||
}
|
||||
}
|
||||
|
||||
if (uniqueShops > 2 || shops > RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16) / 256)
|
||||
return 0;
|
||||
|
||||
// Count hungry peeps
|
||||
hungryPeeps = 0;
|
||||
FOR_ALL_GUESTS(spriteIndex, peep) {
|
||||
if (peep->var_2A != 0)
|
||||
continue;
|
||||
|
||||
if (peep->thoughts[0].var_2 <= 5 && peep->thoughts[0].type == PEEP_THOUGHT_TYPE_HUNGRY)
|
||||
hungryPeeps++;
|
||||
}
|
||||
|
||||
return (hungryPeeps > 15);
|
||||
}
|
||||
|
||||
/** At least 4 restrooms, 1 restroom per 128 guests and no more than 16 guests who think they need the restroom. */
|
||||
static int award_is_deserved_best_restrooms(int awardType, int activeAwardTypes)
|
||||
{
|
||||
unsigned int i, numRestrooms, guestsWhoNeedRestroom;
|
||||
rct_ride *ride;
|
||||
uint16 spriteIndex;
|
||||
rct_peep *peep;
|
||||
|
||||
// Count open restrooms
|
||||
numRestrooms = 0;
|
||||
FOR_ALL_RIDES(i, ride)
|
||||
if (ride->type == RIDE_TYPE_BATHROOM && ride->status == RIDE_STATUS_OPEN)
|
||||
numRestrooms++;
|
||||
|
||||
// At least 4 open restrooms
|
||||
if (numRestrooms < 4)
|
||||
return 0;
|
||||
|
||||
// At least one open restroom for every 128 guests
|
||||
if (numRestrooms < RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16) / 128U)
|
||||
return 0;
|
||||
|
||||
// Count number of guests who are thinking they need the restroom
|
||||
guestsWhoNeedRestroom = 0;
|
||||
FOR_ALL_GUESTS(spriteIndex, peep) {
|
||||
if (peep->var_2A != 0)
|
||||
continue;
|
||||
|
||||
if (peep->thoughts[0].var_2 <= 5 && peep->thoughts[0].type == PEEP_THOUGHT_TYPE_BATHROOM)
|
||||
guestsWhoNeedRestroom++;
|
||||
}
|
||||
|
||||
return (guestsWhoNeedRestroom <= 16);
|
||||
}
|
||||
|
||||
/** More than half of the rides have satisfication <= 6 and park rating <= 650. */
|
||||
static int award_is_deserved_most_disappointing(int awardType, int activeAwardTypes)
|
||||
{
|
||||
unsigned int i, countedRides, disappointingRides;
|
||||
rct_ride *ride;
|
||||
|
||||
if (activeAwardTypes & (1 << PARK_AWARD_BEST_VALUE))
|
||||
return 0;
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_RATING, uint16) > 650)
|
||||
return 0;
|
||||
|
||||
// Count the number of disappointing rides
|
||||
countedRides = 0;
|
||||
disappointingRides = 0;
|
||||
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
if (ride->excitement == 0xFFFF || ride->var_158 == 0xFF)
|
||||
continue;
|
||||
|
||||
countedRides++;
|
||||
|
||||
// Satification maybe?
|
||||
if (ride->var_158 <= 6)
|
||||
disappointingRides++;
|
||||
}
|
||||
|
||||
// Half of the rides are disappointing
|
||||
return (disappointingRides >= countedRides / 2);
|
||||
}
|
||||
|
||||
/** At least 6 open water rides. */
|
||||
static int award_is_deserved_best_water_rides(int awardType, int activeAwardTypes)
|
||||
{
|
||||
int i, waterRides;
|
||||
rct_ride *ride;
|
||||
char *object;
|
||||
|
||||
waterRides = 0;
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
object = RCT2_ADDRESS(0x009ACFA4, char*)[ride->subtype];
|
||||
if (RCT2_GLOBAL(object + 0x1BE, uint8) != RIDE_GROUP_WATER && RCT2_GLOBAL(object + 0x1BF, uint8) != RIDE_GROUP_WATER)
|
||||
continue;
|
||||
|
||||
if (ride->status != RIDE_STATUS_OPEN || (ride->lifecycle_flags & 0x400))
|
||||
continue;
|
||||
|
||||
waterRides++;
|
||||
}
|
||||
|
||||
return (waterRides >= 6);
|
||||
}
|
||||
|
||||
/** At least 6 custom designed rides. */
|
||||
static int award_is_deserved_best_custom_designed_rides(int awardType, int activeAwardTypes)
|
||||
{
|
||||
int i, customDesignedRides;
|
||||
rct_ride *ride;
|
||||
|
||||
if (activeAwardTypes & (1 << PARK_AWARD_MOST_DISAPPOINTING))
|
||||
return 0;
|
||||
|
||||
customDesignedRides = 0;
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
if (!(RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x10000000))
|
||||
continue;
|
||||
if (ride->lifecycle_flags & 0x40000)
|
||||
continue;
|
||||
if (ride->excitement < RIDE_RATING(5, 50))
|
||||
continue;
|
||||
if (ride->status != RIDE_STATUS_OPEN || (ride->lifecycle_flags & 0x400))
|
||||
continue;
|
||||
|
||||
customDesignedRides++;
|
||||
}
|
||||
|
||||
return (customDesignedRides >= 6);
|
||||
}
|
||||
|
||||
/** At least 5 colourful rides and more than half of the rides are colourful. */
|
||||
static int award_is_deserved_most_dazzling_ride_colours(int awardType, int activeAwardTypes)
|
||||
{
|
||||
int i, countedRides, colourfulRides;
|
||||
rct_ride *ride;
|
||||
|
||||
if (activeAwardTypes & (1 << PARK_AWARD_MOST_DISAPPOINTING))
|
||||
return 0;
|
||||
|
||||
countedRides = 0;
|
||||
colourfulRides = 0;
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
if (!(RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x10000000))
|
||||
continue;
|
||||
|
||||
countedRides++;
|
||||
if (ride->var_1BC == 5 || ride->var_1BC == 14 || ride->var_1BC == 20 || ride->var_1BC == 30)
|
||||
colourfulRides++;
|
||||
}
|
||||
|
||||
return (colourfulRides >= 5 && colourfulRides >= countedRides - colourfulRides);
|
||||
}
|
||||
|
||||
/** At least 10 peeps and more than 1/64 of total guests are lost or can't find something. */
|
||||
static int award_is_deserved_most_confusing_layout(int awardType, int activeAwardTypes)
|
||||
{
|
||||
unsigned int peepsCounted, peepsLost;
|
||||
uint16 spriteIndex;
|
||||
rct_peep *peep;
|
||||
|
||||
peepsCounted = 0;
|
||||
peepsLost = 0;
|
||||
FOR_ALL_GUESTS(spriteIndex, peep) {
|
||||
if (peep->var_2A != 0)
|
||||
continue;
|
||||
|
||||
peepsCounted++;
|
||||
if (peep->thoughts[0].var_2 <= 5 && peep->thoughts[0].type == PEEP_THOUGHT_TYPE_LOST || peep->thoughts[0].type == PEEP_THOUGHT_TYPE_CANT_FIND)
|
||||
peepsLost++;
|
||||
}
|
||||
|
||||
return (peepsLost >= 10 && peepsLost >= peepsCounted / 64);
|
||||
}
|
||||
|
||||
/** At least 10 open gentle rides. */
|
||||
static int award_is_deserved_best_gentle_rides(int awardType, int activeAwardTypes)
|
||||
{
|
||||
int i, gentleRides;
|
||||
rct_ride *ride;
|
||||
char *object;
|
||||
|
||||
gentleRides = 0;
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
object = RCT2_ADDRESS(0x009ACFA4, char*)[ride->subtype];
|
||||
if (RCT2_GLOBAL(object + 0x1BE, uint8) != RIDE_GROUP_GENTLE && RCT2_GLOBAL(object + 0x1BF, uint8) != RIDE_GROUP_GENTLE)
|
||||
continue;
|
||||
|
||||
if (ride->status != RIDE_STATUS_OPEN || (ride->lifecycle_flags & 0x400))
|
||||
continue;
|
||||
|
||||
gentleRides++;
|
||||
}
|
||||
|
||||
return (gentleRides >= 10);
|
||||
}
|
||||
|
||||
typedef int (*award_deserved_check)(int, int);
|
||||
|
||||
award_deserved_check _awardChecks[] = {
|
||||
award_is_deserved_most_untidy,
|
||||
award_is_deserved_most_tidy,
|
||||
award_is_deserved_best_rollercoasters,
|
||||
award_is_deserved_best_value,
|
||||
award_is_deserved_most_beautiful,
|
||||
award_is_deserved_worse_value,
|
||||
award_is_deserved_safest,
|
||||
award_is_deserved_best_staff,
|
||||
award_is_deserved_best_food,
|
||||
award_is_deserved_worst_food,
|
||||
award_is_deserved_best_restrooms,
|
||||
award_is_deserved_most_disappointing,
|
||||
award_is_deserved_best_water_rides,
|
||||
award_is_deserved_best_custom_designed_rides,
|
||||
award_is_deserved_most_dazzling_ride_colours,
|
||||
award_is_deserved_most_confusing_layout,
|
||||
award_is_deserved_best_gentle_rides
|
||||
};
|
||||
|
||||
static int award_is_deserved(int awardType, int activeAwardTypes)
|
||||
{
|
||||
return _awardChecks[awardType](awardType, activeAwardTypes);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
void award_reset()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MAX_AWARDS; i++)
|
||||
RCT2_ADDRESS(RCT2_ADDRESS_AWARD_LIST, rct_award)[i].time = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0066A86C
|
||||
*/
|
||||
void award_update_all()
|
||||
{
|
||||
int i, activeAwardTypes, freeAwardEntryIndex;
|
||||
rct_award *awards;
|
||||
|
||||
awards = RCT2_ADDRESS(RCT2_ADDRESS_AWARD_LIST, rct_award);
|
||||
|
||||
// Only add new awards if park is open
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_PARK_OPEN) {
|
||||
// Set active award types as flags
|
||||
activeAwardTypes = 0;
|
||||
freeAwardEntryIndex = -1;
|
||||
for (i = 0; i < MAX_AWARDS; i++) {
|
||||
if (awards[i].time != 0)
|
||||
activeAwardTypes |= (1 << awards[i].type);
|
||||
else if (freeAwardEntryIndex == -1)
|
||||
freeAwardEntryIndex = i;
|
||||
}
|
||||
|
||||
// Check if there was a free award entry
|
||||
if (freeAwardEntryIndex != -1) {
|
||||
// Get a random award type not already active
|
||||
int awardType;
|
||||
do {
|
||||
awardType = (((scenario_rand() & 0xFF) * 17) >> 8) & 0xFF;
|
||||
} while (activeAwardTypes & (1 << awardType));
|
||||
|
||||
// Check if award is deserved
|
||||
if (award_is_deserved(awardType, activeAwardTypes)) {
|
||||
// Add award
|
||||
awards[freeAwardEntryIndex].type = awardType;
|
||||
awards[freeAwardEntryIndex].time = 5;
|
||||
news_item_add_to_queue(NEWS_ITEM_AWARD, STR_NEWS_ITEM_AWARD_MOST_UNTIDY + awardType, 0);
|
||||
window_invalidate_by_id(WC_PARK_INFORMATION, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Decrease award times
|
||||
for (i = 0; i < MAX_AWARDS; i++)
|
||||
if (awards[i].time != 0)
|
||||
if (--awards[i].time == 0)
|
||||
window_invalidate_by_id(WC_PARK_INFORMATION, 0);
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (c) 2014 Ted John
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* This file is part of OpenRCT2.
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _AWARD_H_
|
||||
#define _AWARD_H_
|
||||
|
||||
#include "rct2.h"
|
||||
|
||||
typedef struct {
|
||||
uint16 time;
|
||||
uint16 type;
|
||||
} rct_award;
|
||||
|
||||
enum {
|
||||
PARK_AWARD_MOST_UNTIDY,
|
||||
PARK_AWARD_MOST_TIDY,
|
||||
PARK_AWARD_BEST_ROLLERCOASTERS,
|
||||
PARK_AWARD_BEST_VALUE,
|
||||
PARK_AWARD_MOST_BEAUTIFUL,
|
||||
PARK_AWARD_WORST_VALUE,
|
||||
PARK_AWARD_SAFEST,
|
||||
PARK_AWARD_BEST_STAFF,
|
||||
PARK_AWARD_BEST_FOOD,
|
||||
PARK_AWARD_WORST_FOOD,
|
||||
PARK_AWARD_BEST_RESTROOMS,
|
||||
PARK_AWARD_MOST_DISAPPOINTING,
|
||||
PARK_AWARD_BEST_WATER_RIDES,
|
||||
PARK_AWARD_BEST_CUSTOM_DESIGNED_RIDES,
|
||||
PARK_AWARD_MOST_DAZZLING_RIDE_COLOURS,
|
||||
PARK_AWARD_MOST_CONFUSING_LAYOUT,
|
||||
PARK_AWARD_BEST_GENTLE_RIDES,
|
||||
PARK_AWARD_COUNT
|
||||
};
|
||||
|
||||
#define MAX_AWARDS 4
|
||||
|
||||
int award_is_positive(int type);
|
||||
void award_reset();
|
||||
void award_update_all();
|
||||
|
||||
#endif
|
149
src/climate.c
149
src/climate.c
|
@ -19,10 +19,19 @@
|
|||
*****************************************************************************/
|
||||
|
||||
#include "addresses.h"
|
||||
#include "audio.h"
|
||||
#include "climate.h"
|
||||
#include "date.h"
|
||||
#include "gfx.h"
|
||||
#include "rct2.h"
|
||||
#include "scenario.h"
|
||||
|
||||
enum {
|
||||
THUNDER_STATUS_NULL = 0,
|
||||
THUNDER_STATUS_PLAYING = 1,
|
||||
|
||||
MAX_THUNDER_INSTANCES = 2
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
sint8 base_temperature;
|
||||
|
@ -32,6 +41,8 @@ typedef struct {
|
|||
|
||||
int gClimateNextWeather;
|
||||
|
||||
static int _climateCurrentWeatherEffect;
|
||||
|
||||
static int _climateNextTemperature;
|
||||
static int _climateNextWeatherEffect;
|
||||
static int _climateNextWeatherGloom;
|
||||
|
@ -39,8 +50,24 @@ static int _climateNextRainLevel;
|
|||
|
||||
static const rct_weather_transition* climate_transitions[4];
|
||||
|
||||
// Sound data
|
||||
static int _rainVolume = 1;
|
||||
static rct_sound _rainSoundInstance;
|
||||
static unsigned int _lightningTimer, _thunderTimer;
|
||||
static rct_sound _thunderSoundInstance[MAX_THUNDER_INSTANCES];
|
||||
static int _thunderStatus[MAX_THUNDER_INSTANCES] = { THUNDER_STATUS_NULL, THUNDER_STATUS_NULL };
|
||||
static unsigned int _thunderSoundId;
|
||||
static int _thunderVolume;
|
||||
static int _thunderStereoEcho = 0;
|
||||
|
||||
static void climate_determine_future_weather();
|
||||
|
||||
static void climate_update_rain_sound();
|
||||
static void climate_update_thunder_sound();
|
||||
static void climate_update_lightning();
|
||||
static void climate_update_thunder();
|
||||
static int climate_play_thunder(int instanceIndex, int soundId, int volume, int pan);
|
||||
|
||||
int climate_celsius_to_fahrenheit(int celsius)
|
||||
{
|
||||
return (celsius * 29) / 16 + 32;
|
||||
|
@ -88,7 +115,7 @@ void climate_update()
|
|||
|
||||
if (temperature == target_temperature) {
|
||||
if (cur_gloom == next_gloom) {
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_WEATHER_EFFECT, sint8) = _climateNextWeatherEffect;
|
||||
_climateCurrentWeatherEffect = _climateNextWeatherEffect;
|
||||
|
||||
if (cur_rain == next_rain) {
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_WEATHER, sint8) = gClimateNextWeather;
|
||||
|
@ -152,7 +179,127 @@ static void climate_determine_future_weather()
|
|||
RCT2_GLOBAL(RCT2_ADDRESS_CLIMATE_UPDATE_TIMER, sint16) = 1920;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006BCB91
|
||||
*/
|
||||
void climate_update_sound()
|
||||
{
|
||||
if (RCT2_GLOBAL(0x009AF280, uint32) == 0xFFFFFFFF)
|
||||
return;
|
||||
if (RCT2_GLOBAL(0x009AF59C, uint8) != 0)
|
||||
return;
|
||||
if (!(RCT2_GLOBAL(0x009AF59D, uint8) & 1))
|
||||
return;
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 1)
|
||||
return;
|
||||
|
||||
climate_update_rain_sound();
|
||||
climate_update_thunder_sound();
|
||||
}
|
||||
|
||||
static void climate_update_rain_sound()
|
||||
{
|
||||
if (_climateCurrentWeatherEffect == 1 || _climateCurrentWeatherEffect == 2) {
|
||||
if (_rainVolume == 1) {
|
||||
// Start playing the rain sound
|
||||
if (sound_prepare(SOUND_RAIN_1, &_rainSoundInstance, 1, RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_SOUND_SW_BUFFER, uint32)))
|
||||
sound_play(&_rainSoundInstance, 1, -4000, 0, 0);
|
||||
_rainVolume = -4000;
|
||||
} else {
|
||||
// Increase rain sound
|
||||
_rainVolume = min(-1400, _rainVolume + 80);
|
||||
RCT2_CALLPROC_2(0x00404F0D, rct_sound*, int, &_rainSoundInstance, _rainVolume);
|
||||
}
|
||||
} else if (_rainVolume != 1) {
|
||||
// Decrease rain sound
|
||||
_rainVolume -= 80;
|
||||
if (_rainVolume > -4000) {
|
||||
RCT2_CALLPROC_2(0x00404F0D, rct_sound*, int, &_rainSoundInstance, _rainVolume);
|
||||
} else {
|
||||
sound_stop(&_rainSoundInstance);
|
||||
_rainVolume = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void climate_update_thunder_sound()
|
||||
{
|
||||
if (_thunderStereoEcho) {
|
||||
// Play thunder on right side
|
||||
_thunderStereoEcho = 0;
|
||||
climate_play_thunder(1, _thunderSoundId, _thunderVolume, 10000);
|
||||
} else if (_thunderTimer != 0) {
|
||||
climate_update_lightning();
|
||||
climate_update_thunder();
|
||||
} else if (_climateCurrentWeatherEffect == 2) {
|
||||
// Create new thunder and lightning
|
||||
unsigned int randomNumber = scenario_rand();
|
||||
if ((randomNumber & 0xFFFF) <= 0x1B4) {
|
||||
randomNumber >>= 16;
|
||||
_thunderTimer = 43 + (randomNumber % 64);
|
||||
_lightningTimer = randomNumber % 32;
|
||||
}
|
||||
}
|
||||
|
||||
// Stop thunder sounds if they have finished
|
||||
for (int i = 0; i < MAX_THUNDER_INSTANCES; i++) {
|
||||
if (_thunderStatus[i] == THUNDER_STATUS_NULL)
|
||||
continue;
|
||||
|
||||
if (!RCT2_CALLFUNC_1(0x00404E53, int, rct_sound*, &_thunderSoundInstance[i])) {
|
||||
sound_stop(&_thunderSoundInstance[i]);
|
||||
_thunderStatus[i] = THUNDER_STATUS_NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void climate_update_lightning()
|
||||
{
|
||||
if (_lightningTimer == 0)
|
||||
return;
|
||||
|
||||
_lightningTimer--;
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_LIGHTNING_ACTIVE, uint16) == 0)
|
||||
if ((scenario_rand() & 0xFFFF) <= 0x2000)
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_LIGHTNING_ACTIVE, uint16) = 1;
|
||||
}
|
||||
|
||||
static void climate_update_thunder()
|
||||
{
|
||||
_thunderTimer--;
|
||||
if (_thunderTimer != 0)
|
||||
return;
|
||||
|
||||
unsigned int randomNumber = scenario_rand();
|
||||
if (randomNumber & 0x10000) {
|
||||
if (_thunderStatus[0] == THUNDER_STATUS_NULL && _thunderStatus[1] == THUNDER_STATUS_NULL) {
|
||||
// Play thunder on left side
|
||||
_thunderSoundId = (randomNumber & 0x20000) ? SOUND_THUNDER_1 : SOUND_THUNDER_2;
|
||||
_thunderVolume = (-((int)((randomNumber >> 18) & 0xFF))) << 3;
|
||||
climate_play_thunder(0, _thunderSoundId, _thunderVolume, -10000);
|
||||
|
||||
// Let thunder play on right side
|
||||
_thunderStereoEcho = 1;
|
||||
}
|
||||
} else {
|
||||
_thunderSoundId = (randomNumber & 0x20000) ? SOUND_THUNDER_1 : SOUND_THUNDER_2;
|
||||
int pan = (((randomNumber >> 18) & 0xFF) - 128) * 16;
|
||||
climate_play_thunder(0, _thunderSoundId, 0, pan);
|
||||
}
|
||||
}
|
||||
|
||||
static int climate_play_thunder(int instanceIndex, int soundId, int volume, int pan)
|
||||
{
|
||||
if (sound_prepare(soundId, &_thunderSoundInstance[instanceIndex], 1, RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_SOUND_SW_BUFFER, uint32))) {
|
||||
sound_play(&_thunderSoundInstance[instanceIndex], 0, volume, pan, 0);
|
||||
|
||||
_thunderStatus[instanceIndex] = THUNDER_STATUS_PLAYING;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#pragma region Climate / Weather data tables
|
||||
|
||||
|
|
|
@ -44,5 +44,6 @@ extern const rct_weather climate_weather_data[6];
|
|||
int climate_celsius_to_fahrenheit(int celsius);
|
||||
void climate_reset(int climate);
|
||||
void climate_update();
|
||||
void climate_update_sound();
|
||||
|
||||
#endif
|
||||
|
|
318
src/config.c
318
src/config.c
|
@ -19,14 +19,12 @@
|
|||
*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <shlobj.h>
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#include <SDL_keycode.h>
|
||||
#include <ctype.h>
|
||||
#include "addresses.h"
|
||||
#include "config.h"
|
||||
#include "rct2.h"
|
||||
#include <tchar.h>
|
||||
|
||||
|
||||
#include "osinterface.h"
|
||||
|
||||
|
@ -78,15 +76,19 @@ static const uint16 _defaultShortcutKeys[SHORTCUT_COUNT] = {
|
|||
|
||||
general_configuration_t gGeneral_config;
|
||||
general_configuration_t gGeneral_config_default = {
|
||||
1,
|
||||
1,
|
||||
SCREENSHOT_FORMAT_PNG,
|
||||
"",
|
||||
MEASUREMENT_FORMAT_IMPERIAL,
|
||||
TEMPERATURE_FORMAT_F,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0, // play_intro
|
||||
1, // confirmation_prompt
|
||||
SCREENSHOT_FORMAT_PNG, // screenshot_format
|
||||
"", // game_path
|
||||
MEASUREMENT_FORMAT_IMPERIAL, // measurement_format
|
||||
TEMPERATURE_FORMAT_F, // temperature_format
|
||||
CURRENCY_POUNDS, // currency_format
|
||||
0, // construction_marker_colour
|
||||
1, // edge_scrolling
|
||||
0, // always_show_gridlines
|
||||
1, // landscape_smoothing
|
||||
0, // show_height_as_units
|
||||
1, // save_plugin_data
|
||||
};
|
||||
sound_configuration_t gSound_config;
|
||||
|
||||
|
@ -102,6 +104,10 @@ static void config_create_default(char *path);
|
|||
static int config_parse_currency(char* currency);
|
||||
static void config_error(char *msg);
|
||||
|
||||
void config_save_ini(char *path);
|
||||
void config_write_ini_general(FILE *fp);
|
||||
void config_write_ini_sound(FILE *fp);
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006E3604
|
||||
|
@ -117,20 +123,20 @@ void config_reset_shortcut_keys()
|
|||
*/
|
||||
void config_load()
|
||||
{
|
||||
HANDLE hFile;
|
||||
DWORD bytesRead;
|
||||
FILE *fp=NULL;
|
||||
|
||||
char* path = get_file_path(PATH_ID_GAMECFG);
|
||||
hFile = CreateFile(get_file_path(PATH_ID_GAMECFG), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
||||
FILE_FLAG_RANDOM_ACCESS | FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile != INVALID_HANDLE_VALUE) {
|
||||
|
||||
fp = fopen(path, "rb");
|
||||
|
||||
if (fp != NULL) {
|
||||
// Read and check magic number
|
||||
ReadFile(hFile, RCT2_ADDRESS(0x013CE928, void), 4, &bytesRead, NULL);
|
||||
fread(RCT2_ADDRESS(0x013CE928, void), 1, 4, fp);
|
||||
|
||||
if (RCT2_GLOBAL(0x013CE928, int) == MagicNumber) {
|
||||
// Read options
|
||||
ReadFile(hFile, (void*)0x009AAC5C, 2155, &bytesRead, NULL);
|
||||
CloseHandle(hFile);
|
||||
|
||||
fread((void*)0x009AAC5C, 1, 2155, fp);
|
||||
fclose(fp);
|
||||
|
||||
//general configuration
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_EDGE_SCROLLING, sint8) = gGeneral_config.edge_scrolling;
|
||||
|
@ -138,6 +144,37 @@ void config_load()
|
|||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, sint8) = gGeneral_config.measurement_format;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_TEMPERATURE, sint8) = gGeneral_config.temperature_format;
|
||||
|
||||
// always show gridlines
|
||||
if (gGeneral_config.always_show_gridlines){
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) |= CONFIG_FLAG_ALWAYS_SHOW_GRIDLINES;
|
||||
}
|
||||
else {
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) &= !CONFIG_FLAG_ALWAYS_SHOW_GRIDLINES;
|
||||
}
|
||||
|
||||
// landscape smoothing
|
||||
if (!gGeneral_config.landscape_smoothing){
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) |= CONFIG_FLAG_DISABLE_SMOOTH_LANDSCAPE;
|
||||
}
|
||||
else {
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) &= !CONFIG_FLAG_DISABLE_SMOOTH_LANDSCAPE;
|
||||
}
|
||||
|
||||
// show height as units
|
||||
if (gGeneral_config.show_height_as_units){
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) |= CONFIG_FLAG_SHOW_HEIGHT_AS_UNITS;
|
||||
}
|
||||
else {
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) &= !CONFIG_FLAG_SHOW_HEIGHT_AS_UNITS;
|
||||
}
|
||||
|
||||
// save plugin data
|
||||
if (gGeneral_config.save_plugin_data){
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) |= CONFIG_FLAG_SAVE_PLUGIN_DATA;
|
||||
}
|
||||
else {
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) &= !CONFIG_FLAG_SAVE_PLUGIN_DATA;
|
||||
}
|
||||
|
||||
//sound configuration
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_SOUND_QUALITY, sint8) = gSound_config.sound_quality;
|
||||
|
@ -191,23 +228,152 @@ void config_load()
|
|||
RCT2_GLOBAL(0x009AA00D, sint8) = 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save configuration to the data/config.cfg file
|
||||
* rct2: 0x00675487
|
||||
*/
|
||||
void config_save()
|
||||
{
|
||||
HANDLE hFile;
|
||||
DWORD bytesWritten;
|
||||
FILE *fp=NULL;
|
||||
char *configIniPath = osinterface_get_orct2_homefolder();;
|
||||
|
||||
hFile = CreateFile(get_file_path(PATH_ID_GAMECFG), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile != INVALID_HANDLE_VALUE) {
|
||||
WriteFile(hFile, &MagicNumber, 4, &bytesWritten, NULL);
|
||||
WriteFile(hFile, (LPCVOID)0x009AAC5C, 2155, &bytesWritten, NULL);
|
||||
CloseHandle(hFile);
|
||||
fp = fopen(get_file_path(PATH_ID_GAMECFG), "wb");
|
||||
if (fp != NULL){
|
||||
fwrite(&MagicNumber, 4, 1, fp);
|
||||
fwrite((void*)0x009AAC5C, 2155, 1, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
sprintf(configIniPath, "%s%c%s", configIniPath, osinterface_get_path_separator(), "config.ini");
|
||||
config_save_ini(configIniPath);
|
||||
}
|
||||
|
||||
void config_save_ini(char *path)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
|
||||
|
||||
fp = fopen(path, "wt+");
|
||||
|
||||
config_write_ini_general(fp);
|
||||
config_write_ini_sound(fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void config_write_ini_sound(FILE *fp)
|
||||
{
|
||||
fprintf(fp, "[sound]\n");
|
||||
if (gSound_config.sound_quality == SOUND_QUALITY_LOW) {
|
||||
fprintf(fp, "sound_quality = low\n");
|
||||
}
|
||||
else if (gSound_config.sound_quality == SOUND_QUALITY_MEDIUM) {
|
||||
fprintf(fp, "sound_quality = medium\n");
|
||||
}
|
||||
else{
|
||||
fprintf(fp, "sound_quality = high\n");
|
||||
}
|
||||
|
||||
if (gSound_config.forced_software_buffering){
|
||||
fprintf(fp, "forced_software_buffering = true\n");
|
||||
}
|
||||
else {
|
||||
fprintf(fp, "forced_software_buffering = false\n");
|
||||
}
|
||||
}
|
||||
|
||||
void config_write_ini_general(FILE *fp)
|
||||
{
|
||||
int currencyIterator = 0;
|
||||
|
||||
fprintf(fp, "[general]\n");
|
||||
fprintf(fp, "game_path = %s\n", gGeneral_config.game_path);
|
||||
|
||||
switch (gGeneral_config.screenshot_format)
|
||||
{
|
||||
case SCREENSHOT_FORMAT_BMP:
|
||||
fprintf(fp, "screenshot_format = BMP\n");
|
||||
break;
|
||||
case SCREENSHOT_FORMAT_PNG:
|
||||
fprintf(fp, "screenshot_format = PNG\n");
|
||||
break;
|
||||
default:
|
||||
config_error("error saving config.ini: wrong screenshot_format");
|
||||
break;
|
||||
}
|
||||
|
||||
if (gGeneral_config.play_intro){
|
||||
fprintf(fp, "play_intro = true\n");
|
||||
}
|
||||
else {
|
||||
fprintf(fp, "play_intro = false\n");
|
||||
}
|
||||
|
||||
if (gGeneral_config.confirmation_prompt){
|
||||
fprintf(fp, "confirmation_prompt = true\n");
|
||||
}
|
||||
else {
|
||||
fprintf(fp, "confirmation_prompt = false\n");
|
||||
}
|
||||
|
||||
if (gGeneral_config.edge_scrolling){
|
||||
fprintf(fp, "edge_scrolling = true\n");
|
||||
}
|
||||
else {
|
||||
fprintf(fp, "edge_scrolling = false\n");
|
||||
}
|
||||
|
||||
for (currencyIterator = 0; currencyIterator < countof(_currencyLookupTable); currencyIterator++) {
|
||||
if (_currencyLookupTable[currencyIterator].value == gGeneral_config.currency_format) {
|
||||
gGeneral_config.currency_format = _currencyLookupTable[currencyIterator].value;
|
||||
fprintf(fp, "currency = %s\n", _currencyLookupTable[currencyIterator].key);
|
||||
break; // There are more than one valid item for Pound, Euro and Dollar ...
|
||||
}
|
||||
}
|
||||
|
||||
if (gGeneral_config.measurement_format == MEASUREMENT_FORMAT_IMPERIAL) {
|
||||
fprintf(fp, "measurement_format = imperial\n");
|
||||
}
|
||||
else {
|
||||
fprintf(fp, "measurement_format = metric\n");
|
||||
}
|
||||
|
||||
if (gGeneral_config.temperature_format == TEMPERATURE_FORMAT_F) {
|
||||
fprintf(fp, "temperature_format = fahrenheit\n");
|
||||
}
|
||||
else {
|
||||
fprintf(fp, "temperature_format = celsius\n");
|
||||
}
|
||||
|
||||
if (gGeneral_config.always_show_gridlines){
|
||||
fprintf(fp, "always_show_gridlines = true\n");
|
||||
}
|
||||
else {
|
||||
fprintf(fp, "always_show_gridlines = false\n");
|
||||
}
|
||||
|
||||
if (gGeneral_config.landscape_smoothing){
|
||||
fprintf(fp, "landscape_smoothing = true\n");
|
||||
}
|
||||
else {
|
||||
fprintf(fp, "landscape_smoothing = false\n");
|
||||
}
|
||||
|
||||
if (gGeneral_config.show_height_as_units){
|
||||
fprintf(fp, "show_height_as_units = true\n");
|
||||
}
|
||||
else {
|
||||
fprintf(fp, "show_height_as_units = false\n");
|
||||
}
|
||||
|
||||
if (gGeneral_config.save_plugin_data){
|
||||
fprintf(fp, "save_plugin_data = true\n");
|
||||
}
|
||||
else {
|
||||
fprintf(fp, "save_plugin_data = false\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initilise the settings.
|
||||
|
@ -216,20 +382,19 @@ void config_save()
|
|||
*/
|
||||
void config_init()
|
||||
{
|
||||
TCHAR path[MAX_PATH];
|
||||
char *path = osinterface_get_orct2_homefolder();
|
||||
FILE* fp;
|
||||
|
||||
memcpy(&gGeneral_config, &gGeneral_config_default, sizeof(general_configuration_t));
|
||||
|
||||
if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, 0, path))) { // find home folder
|
||||
strcat(path, "\\OpenRCT2");
|
||||
DWORD dwAttrib = GetFileAttributes(path);
|
||||
if (dwAttrib == INVALID_FILE_ATTRIBUTES || !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) { // folder does not exist
|
||||
if (!CreateDirectory(path, NULL)) {
|
||||
config_error("Could not create config file (do you have write access to your documents folder?)");
|
||||
}
|
||||
if (strcmp(path, "") != 0){
|
||||
if (!osinterface_ensure_directory_exists(path)) {
|
||||
config_error("Could not create config file (do you have write access to your documents folder?)");
|
||||
return;
|
||||
}
|
||||
strcat(path, "\\config.ini");
|
||||
|
||||
sprintf(path, "%s%c%s", path, osinterface_get_path_separator(), "config.ini");
|
||||
|
||||
fp = fopen(path, "r");
|
||||
if (!fp) {
|
||||
config_create_default(path);
|
||||
|
@ -242,6 +407,8 @@ void config_init()
|
|||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
free(path);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -253,7 +420,7 @@ void config_init()
|
|||
static int config_find_rct2_path(char *resultPath)
|
||||
{
|
||||
int i;
|
||||
DWORD dwAttrib;
|
||||
|
||||
const char *searchLocations[] = {
|
||||
"C:\\Program Files\\Infogrames\\RollerCoaster Tycoon 2",
|
||||
"C:\\Program Files (x86)\\Infogrames\\RollerCoaster Tycoon 2",
|
||||
|
@ -265,8 +432,7 @@ static int config_find_rct2_path(char *resultPath)
|
|||
};
|
||||
|
||||
for (i = 0; i < countof(searchLocations); i++) {
|
||||
dwAttrib = GetFileAttributes(searchLocations[i]);
|
||||
if (dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
if ( osinterface_directory_exists(searchLocations[i]) ) {
|
||||
strcpy(resultPath, searchLocations[i]);
|
||||
return 1;
|
||||
}
|
||||
|
@ -282,8 +448,7 @@ static int config_find_rct2_path(char *resultPath)
|
|||
*/
|
||||
static void config_create_default(char *path)
|
||||
{
|
||||
FILE* fp;
|
||||
|
||||
gGeneral_config = gGeneral_config_default;
|
||||
|
||||
if (!config_find_rct2_path(gGeneral_config.game_path)) {
|
||||
osinterface_show_messagebox("Unable to find RCT2 installation directory. Please select the directory where you installed RCT2!");
|
||||
|
@ -291,20 +456,7 @@ static void config_create_default(char *path)
|
|||
strcpy(gGeneral_config.game_path, res);
|
||||
}
|
||||
|
||||
fp = fopen(path, "w");
|
||||
fprintf(fp, "[general]\n");
|
||||
fprintf(fp, "game_path = %s\n", gGeneral_config.game_path);
|
||||
fprintf(fp, "screenshot_format = PNG\n");
|
||||
fprintf(fp, "play_intro = false\n");
|
||||
fprintf(fp, "confirmation_prompt = true\n");
|
||||
fprintf(fp, "edge_scrolling = true\n");
|
||||
fprintf(fp, "currency = GBP\n");
|
||||
fprintf(fp, "measurement_format = imperial\n");
|
||||
fprintf(fp, "temperature_format = fahrenheit\n");
|
||||
fprintf(fp, "[sound]\n");
|
||||
fprintf(fp, "sound_quality = high\n");
|
||||
fprintf(fp, "forced_software_buffering = false\n");
|
||||
fclose(fp);
|
||||
config_save_ini(path);
|
||||
}
|
||||
|
||||
|
||||
|
@ -419,7 +571,38 @@ static void config_general(char *setting, char *value){
|
|||
else if (strcmp(setting, "currency") == 0){
|
||||
config_parse_currency(value);
|
||||
}
|
||||
|
||||
else if (strcmp(setting, "always_show_gridlines") == 0){
|
||||
if (strcmp(value, "true") == 0){
|
||||
gGeneral_config.always_show_gridlines = 1;
|
||||
}
|
||||
else {
|
||||
gGeneral_config.always_show_gridlines = 0;
|
||||
}
|
||||
}
|
||||
else if (strcmp(setting, "landscape_smoothing") == 0){
|
||||
if (strcmp(value, "true") == 0){
|
||||
gGeneral_config.landscape_smoothing = 1;
|
||||
}
|
||||
else {
|
||||
gGeneral_config.landscape_smoothing = 0;
|
||||
}
|
||||
}
|
||||
else if (strcmp(setting, "show_height_as_units") == 0){
|
||||
if (strcmp(value, "true") == 0){
|
||||
gGeneral_config.show_height_as_units = 1;
|
||||
}
|
||||
else {
|
||||
gGeneral_config.show_height_as_units = 0;
|
||||
}
|
||||
}
|
||||
else if (strcmp(setting, "save_plugin_data") == 0){
|
||||
if (strcmp(value, "true") == 0){
|
||||
gGeneral_config.save_plugin_data = 1;
|
||||
}
|
||||
else {
|
||||
gGeneral_config.save_plugin_data = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -592,25 +775,6 @@ static int config_parse_section(FILE *fp, char *setting, char *value){
|
|||
return 1;
|
||||
}
|
||||
|
||||
static const struct { char *key; int value; } _currencyLookupTable[] = {
|
||||
{ "GBP", CURRENCY_POUNDS },
|
||||
{ "USD", CURRENCY_DOLLARS },
|
||||
{ "FRF", CURRENCY_FRANC },
|
||||
{ "DEM", CURRENCY_DEUTSCHMARK },
|
||||
{ "YEN", CURRENCY_YEN },
|
||||
{ "ESP", CURRENCY_PESETA },
|
||||
{ "ITL", CURRENCY_LIRA },
|
||||
{ "NLG", CURRENCY_GUILDERS },
|
||||
{ "NOK", CURRENCY_KRONA },
|
||||
{ "SEK", CURRENCY_KRONA },
|
||||
{ "DEK", CURRENCY_KRONA },
|
||||
{ "EUR", CURRENCY_EUROS },
|
||||
|
||||
{ "£", CURRENCY_POUNDS },
|
||||
{ "$", CURRENCY_DOLLARS },
|
||||
{ "€", CURRENCY_EUROS }
|
||||
};
|
||||
|
||||
static int config_parse_currency(char *currency)
|
||||
{
|
||||
int i;
|
||||
|
|
26
src/config.h
26
src/config.h
|
@ -21,8 +21,8 @@
|
|||
#ifndef _CONFIG_H_
|
||||
#define _CONFIG_H_
|
||||
|
||||
#include <windows.h>
|
||||
#include "rct2.h"
|
||||
#include <windows.h> // for MAX_PATH
|
||||
|
||||
enum {
|
||||
CONFIG_FLAG_ALWAYS_SHOW_GRIDLINES = (1 << 0),
|
||||
|
@ -136,9 +136,31 @@ typedef struct general_configuration {
|
|||
sint8 currency_format;
|
||||
sint8 construction_marker_colour;
|
||||
sint8 edge_scrolling;
|
||||
|
||||
sint8 always_show_gridlines;
|
||||
sint8 landscape_smoothing;
|
||||
sint8 show_height_as_units;
|
||||
sint8 save_plugin_data;
|
||||
} general_configuration_t;
|
||||
|
||||
static const struct { char *key; int value; } _currencyLookupTable[] = {
|
||||
{ "GBP", CURRENCY_POUNDS },
|
||||
{ "USD", CURRENCY_DOLLARS },
|
||||
{ "FRF", CURRENCY_FRANC },
|
||||
{ "DEM", CURRENCY_DEUTSCHMARK },
|
||||
{ "YEN", CURRENCY_YEN },
|
||||
{ "ESP", CURRENCY_PESETA },
|
||||
{ "ITL", CURRENCY_LIRA },
|
||||
{ "NLG", CURRENCY_GUILDERS },
|
||||
{ "NOK", CURRENCY_KRONA },
|
||||
{ "SEK", CURRENCY_KRONA },
|
||||
{ "DEK", CURRENCY_KRONA },
|
||||
{ "EUR", CURRENCY_EUROS },
|
||||
|
||||
{ "Ł", CURRENCY_POUNDS },
|
||||
{ "$", CURRENCY_DOLLARS },
|
||||
{ "€", CURRENCY_EUROS }
|
||||
};
|
||||
|
||||
//typedef struct hotkey_configuration{
|
||||
|
||||
//};
|
||||
|
|
|
@ -71,16 +71,13 @@ void finance_payment(money32 amount, rct_expenditure_type type)
|
|||
void finance_pay_wages()
|
||||
{
|
||||
rct_peep* peep;
|
||||
uint16 sprite_idx;
|
||||
uint16 spriteIndex;
|
||||
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & 0x800)
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_11)
|
||||
return;
|
||||
|
||||
for (sprite_idx = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16); sprite_idx != SPRITE_INDEX_NULL; sprite_idx = peep->next) {
|
||||
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[sprite_idx].peep);
|
||||
if (peep->type == PEEP_TYPE_STAFF)
|
||||
finance_payment(wage_table[peep->staff_type] / 4, RCT_EXPENDITURE_TYPE_WAGES);
|
||||
}
|
||||
FOR_ALL_STAFF(spriteIndex, peep)
|
||||
finance_payment(wage_table[peep->staff_type] / 4, RCT_EXPENDITURE_TYPE_WAGES);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -120,12 +117,10 @@ void finance_pay_interest()
|
|||
*/
|
||||
void finance_pay_ride_upkeep()
|
||||
{
|
||||
int i;
|
||||
rct_ride* ride;
|
||||
for (int i = 0; i < MAX_RIDES; i++) {
|
||||
ride = &(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[i]);
|
||||
if (ride->type == RIDE_TYPE_NULL)
|
||||
continue;
|
||||
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_EVER_BEEN_OPENED)) {
|
||||
ride->build_date = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16);
|
||||
ride->var_196 = 25855; // durability?
|
||||
|
@ -142,6 +137,15 @@ void finance_pay_ride_upkeep()
|
|||
}
|
||||
}
|
||||
|
||||
void finance_reset_history()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 128; i++) {
|
||||
RCT2_ADDRESS(RCT2_ADDRESS_BALANCE_HISTORY, money32)[i] = MONEY32_UNDEFINED;
|
||||
RCT2_ADDRESS(RCT2_ADDRESS_WEEKLY_PROFIT_HISTORY, money32)[i] = MONEY32_UNDEFINED;
|
||||
RCT2_ADDRESS(RCT2_ADDRESS_PARK_VALUE_HISTORY, money32)[i] = MONEY32_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -38,6 +38,7 @@ void finance_pay_wages();
|
|||
void finance_pay_research();
|
||||
void finance_pay_interest();
|
||||
void finance_pay_ride_upkeep();
|
||||
void finance_reset_history();
|
||||
void finance_init();
|
||||
void sub_69E869();
|
||||
|
||||
|
|
142
src/game.c
142
src/game.c
|
@ -35,6 +35,7 @@
|
|||
#include "string_ids.h"
|
||||
#include "title.h"
|
||||
#include "tutorial.h"
|
||||
#include "vehicle.h"
|
||||
#include "viewport.h"
|
||||
#include "widget.h"
|
||||
#include "window.h"
|
||||
|
@ -58,10 +59,47 @@ void game_create_windows()
|
|||
RCT2_CALLPROC_EBPSAFE(0x0066B905);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006838BD
|
||||
*/
|
||||
void update_water_animation()
|
||||
{
|
||||
RCT2_CALLPROC_EBPSAFE(0x006838BD);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x00684218
|
||||
*/
|
||||
void update_rain_animation()
|
||||
{
|
||||
if (RCT2_GLOBAL(0x009ABDF2, uint8) == 0)
|
||||
return;
|
||||
|
||||
// Draw picked-up peep
|
||||
if (RCT2_GLOBAL(0x009DE550, uint32) != 0xFFFFFFFF) {
|
||||
gfx_draw_sprite(
|
||||
(rct_drawpixelinfo*)RCT2_ADDRESS_SCREEN_DPI,
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, uint32),
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_X, sint16),
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_Y, sint16)
|
||||
);
|
||||
}
|
||||
|
||||
// Get rain draw function and draw rain
|
||||
uint32 eax = RCT2_ADDRESS(0x009AC058, uint32)[RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_RAIN_LEVEL, uint8)];
|
||||
if (eax != 0xFFFFFFFF && !(RCT2_GLOBAL(0x009DEA6F, uint8) & 1))
|
||||
RCT2_CALLPROC_X(0x00684266, eax, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void game_update()
|
||||
{
|
||||
int eax, tmp;
|
||||
|
||||
// Handles picked-up peep and rain redraw
|
||||
RCT2_CALLPROC_EBPSAFE(0x006843DC);
|
||||
|
||||
// 0x006E3AEC // screen_game_process_mouse_input();
|
||||
// RCT2_CALLPROC_EBPSAFE(0x006E3AEC); // screen_game_process_keyboard_input();
|
||||
screenshot_check();
|
||||
|
@ -123,8 +161,8 @@ void game_update()
|
|||
RCT2_GLOBAL(0x0141F568, uint8) = RCT2_GLOBAL(0x0013CA740, uint8);
|
||||
game_handle_input();
|
||||
|
||||
RCT2_CALLPROC_EBPSAFE(0x006838BD);
|
||||
RCT2_CALLPROC_EBPSAFE(0x00684218);
|
||||
update_water_animation();
|
||||
update_rain_animation();
|
||||
|
||||
if (RCT2_GLOBAL(0x009AAC73, uint8) != 255) {
|
||||
RCT2_GLOBAL(0x009AAC73, uint8)++;
|
||||
|
@ -149,7 +187,7 @@ void game_logic_update()
|
|||
RCT2_CALLPROC_EBPSAFE(0x006646E1);
|
||||
RCT2_CALLPROC_EBPSAFE(0x006A876D);
|
||||
peep_update_all();
|
||||
RCT2_CALLPROC_EBPSAFE(0x006D4204); // update vehicles
|
||||
vehicle_update_all();
|
||||
RCT2_CALLPROC_EBPSAFE(0x00672AA4); // update text effects
|
||||
RCT2_CALLPROC_EBPSAFE(0x006ABE4C); // update rides
|
||||
park_update();
|
||||
|
@ -159,7 +197,7 @@ void game_logic_update()
|
|||
RCT2_CALLPROC_EBPSAFE(0x0068AFAD);
|
||||
RCT2_CALLPROC_EBPSAFE(0x006BBC6B); // vehicle and scream sounds
|
||||
peep_update_crowd_noise();
|
||||
RCT2_CALLPROC_EBPSAFE(0x006BCB91); // weather sound effects
|
||||
climate_update_sound();
|
||||
news_item_update_current();
|
||||
RCT2_CALLPROC_EBPSAFE(0x0067009A); // scenario editor opening of windows for a phase
|
||||
|
||||
|
@ -524,17 +562,11 @@ static void input_mouseover(int x, int y, rct_window *w, int widgetIndex)
|
|||
|
||||
input_mouseover_widget_check(windowClass, windowNumber, widgetIndex);
|
||||
|
||||
if (w != NULL && widgetIndex != -1 && widget->type == WWT_SCROLL) {
|
||||
int eax, ebx, ecx, edx, esi, edi, ebp;
|
||||
eax = x;
|
||||
ebx = y;
|
||||
esi = (int)w;
|
||||
edi = (int)widget;
|
||||
RCT2_CALLFUNC_X(0x006E9F92, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); // widget_scoll_get_part
|
||||
eax &= 0xFFFF;
|
||||
ebx &= 0xFFFF;
|
||||
ecx &= 0xFFFF;
|
||||
edx &= 0xFFFF;
|
||||
if (w != NULL && widgetIndex != -1 && widget->type == WWT_SCROLL)
|
||||
{
|
||||
int eax, ebx, ecx, edx;
|
||||
widget_scroll_get_part(w, widget, x, y, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
if (ecx < 0)
|
||||
goto showTooltip;
|
||||
if (ecx == 0) {
|
||||
|
@ -616,6 +648,37 @@ static void input_mouseover_widget_flatbutton_invalidate()
|
|||
widget_invalidate(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber), RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, rct_windownumber));
|
||||
}
|
||||
|
||||
static void RCT2_CALLPROC_WE_MOUSE_DOWN(int address, int widgetIndex, rct_window*w, rct_widget* widget )
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
__asm {
|
||||
push address
|
||||
push widget
|
||||
push w
|
||||
push widgetIndex
|
||||
mov edi, widget
|
||||
mov edx, widgetIndex
|
||||
mov esi, w
|
||||
call[esp + 12]
|
||||
add esp, 16
|
||||
}
|
||||
#else
|
||||
__asm__("\
|
||||
push %[address]\n\
|
||||
mov edi, %[widget] \n\
|
||||
mov eax, %[w] \n\
|
||||
mov edx, %[widgetIndex] \n\
|
||||
push edi \n\
|
||||
push eax \n\
|
||||
push edx \n\
|
||||
mov esi, %[w] \n\
|
||||
call [esp+12] \n\
|
||||
add esp, 16 \n\
|
||||
" :[address] "+m" (address), [w] "+m" (w), [widget] "+m" (widget), [widgetIndex] "+m" (widgetIndex): : "eax", "esi", "edx", "edi"
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006E95F9
|
||||
|
@ -695,16 +758,8 @@ static void input_leftmousedown(int x, int y, rct_window *w, int widgetIndex)
|
|||
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16) = x;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16) = y;
|
||||
|
||||
int eax, ebx, ecx, edx, esi, edi, ebp;
|
||||
eax = x;
|
||||
ebx = y;
|
||||
esi = (int)w;
|
||||
edi = (int)widget;
|
||||
RCT2_CALLFUNC_X(0x006E9F92, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); // widget_scoll_get_part
|
||||
eax &= 0xFFFF;
|
||||
ebx &= 0xFFFF;
|
||||
ecx &= 0xFFFF;
|
||||
edx &= 0xFFFF;
|
||||
int eax, ebx, ecx, edx;
|
||||
widget_scroll_get_part(w, widget, x, y, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
RCT2_GLOBAL(0x009DE548, uint16) = ecx;
|
||||
RCT2_GLOBAL(0x009DE54C, uint32) = edx;
|
||||
|
@ -754,7 +809,7 @@ static void input_leftmousedown(int x, int y, rct_window *w, int widgetIndex)
|
|||
if (widget_is_disabled(w, widgetIndex))
|
||||
break;
|
||||
|
||||
sound_play_panned(4, w->x + (widget->left + widget->right) / 2);
|
||||
sound_play_panned(SOUND_CLICK_1, w->x + (widget->left + widget->right) / 2);
|
||||
|
||||
// Set new cursor down widget
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass) = windowClass;
|
||||
|
@ -765,7 +820,7 @@ static void input_leftmousedown(int x, int y, rct_window *w, int widgetIndex)
|
|||
RCT2_GLOBAL(0x009DE528, uint16) = 1;
|
||||
|
||||
widget_invalidate(windowClass, windowNumber, widgetIndex);
|
||||
RCT2_CALLPROC_X(w->event_handlers[WE_MOUSE_DOWN], 0, 0, 0, widgetIndex, (int)w, (int)widget, 0);
|
||||
RCT2_CALLPROC_WE_MOUSE_DOWN(w->event_handlers[WE_MOUSE_DOWN], widgetIndex, w, widget);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1021,7 +1076,7 @@ void handle_shortcut_command(int shortcutIndex)
|
|||
case SHORTCUT_SHOW_FINANCIAL_INFORMATION:
|
||||
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0C))
|
||||
if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & 0x800))
|
||||
RCT2_CALLPROC_EBPSAFE(0x0069DDF1);
|
||||
window_finances_open();
|
||||
break;
|
||||
case SHORTCUT_SHOW_RESEARCH_INFORMATION:
|
||||
if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E)) {
|
||||
|
@ -1029,7 +1084,7 @@ void handle_shortcut_command(int shortcutIndex)
|
|||
RCT2_CALLPROC_EBPSAFE(0x006B3CFF);
|
||||
window = window_find_by_id(WC_CONSTRUCT_RIDE, 0);
|
||||
if (window != NULL)
|
||||
window_event_helper(window, 10, WE_MOUSE_DOWN);
|
||||
RCT2_CALLPROC_WE_MOUSE_DOWN(window->event_handlers[WE_MOUSE_DOWN], 10, window, NULL);
|
||||
}
|
||||
break;
|
||||
case SHORTCUT_SHOW_RIDES_LIST:
|
||||
|
@ -1596,6 +1651,35 @@ static void load_game()
|
|||
}
|
||||
}
|
||||
|
||||
char save_game()
|
||||
{
|
||||
int eax, ebx, ecx, edx, esi, edi, ebp;
|
||||
RCT2_CALLFUNC_X(0x006750E9, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
|
||||
if (eax == 0) {
|
||||
// user pressed "cancel"
|
||||
gfx_invalidate_screen();
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *src = (char*)0x0141EF67;
|
||||
do {
|
||||
src++;
|
||||
} while (*src != '.' && *src != '\0');
|
||||
strcpy(src, ".SV6");
|
||||
strcpy((char*) RCT2_ADDRESS_SAVED_GAMES_PATH_2, (char*) 0x0141EF68);
|
||||
|
||||
eax = 0;
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & 8)
|
||||
eax |= 1;
|
||||
RCT2_CALLPROC_X(0x006754F5, eax, 0, 0, 0, 0, 0, 0);
|
||||
// check success?
|
||||
|
||||
game_do_command(0, 1047, 0, -1, 0, 0, 0);
|
||||
gfx_invalidate_screen();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006E3879
|
||||
|
|
|
@ -29,5 +29,6 @@ int game_do_command(int eax, int ebx, int ecx, int edx, int esi, int edi, int eb
|
|||
|
||||
void game_load_or_quit_no_save_prompt();
|
||||
int game_load_save();
|
||||
char save_game();
|
||||
|
||||
#endif
|
||||
|
|
17
src/gfx.h
17
src/gfx.h
|
@ -31,7 +31,7 @@ typedef struct {
|
|||
short width; // 0x08
|
||||
short height; // 0x0A
|
||||
short pitch; // 0x0C note: this is actually (pitch - width)
|
||||
char pad_0E; // 0x0E
|
||||
uint8 zoom_level; // 0x0E
|
||||
char var_0F; // 0x0F
|
||||
} rct_drawpixelinfo;
|
||||
|
||||
|
@ -46,10 +46,23 @@ typedef struct {
|
|||
sint16 unused; // 0x0E
|
||||
} rct_g1_element;
|
||||
|
||||
enum{
|
||||
G1_FLAG_BMP = (1 << 0), //No invisible sections
|
||||
G1_FLAG_RLE_COMPRESSION = (1<<2),
|
||||
};
|
||||
|
||||
enum{
|
||||
IMAGE_TYPE_NO_BACKGROUND = 0,
|
||||
IMAGE_TYPE_USE_PALETTE= (1 << 1),
|
||||
IMAGE_TYPE_MIX_BACKGROUND = (1<<2),
|
||||
IMAGE_TYPE_UNKNOWN = (1<<3)
|
||||
};
|
||||
|
||||
extern int gLastDrawStringX;
|
||||
extern int gLastDrawStringY;
|
||||
|
||||
int gfx_load_g1();
|
||||
void gfx_load_character_widths();
|
||||
|
||||
void gfx_clear(rct_drawpixelinfo *dpi, int colour);
|
||||
void gfx_draw_pixel(rct_drawpixelinfo *dpi, int x, int y, int colour);
|
||||
|
@ -66,7 +79,7 @@ void gfx_draw_string_centred_clipped(rct_drawpixelinfo *dpi, int format, void *a
|
|||
void gfx_draw_string_right(rct_drawpixelinfo *dpi, int format, void *args, int colour, int x, int y);
|
||||
void gfx_draw_string_centred(rct_drawpixelinfo *dpi, int format, int x, int y, int colour, void *args);
|
||||
int gfx_draw_string_centred_wrapped(rct_drawpixelinfo *dpi, void *args, int x, int y, int width, int format, int colour);
|
||||
int gfx_draw_string_left_wrapped(rct_drawpixelinfo *dpi, void *format, int x, int y, int width, int colour, int unknown);
|
||||
int gfx_draw_string_left_wrapped(rct_drawpixelinfo *dpi, void *args, int x, int y, int width, int format, int colour);
|
||||
|
||||
int gfx_get_string_width(char *buffer);
|
||||
int clip_text(char *buffer, int width);
|
||||
|
|
|
@ -82,7 +82,7 @@ void intro_update()
|
|||
_sound_playing_flag = 0;
|
||||
if (RCT2_GLOBAL(0x009AF280, sint32) != -1) {
|
||||
// Prepare and play the sound
|
||||
if (sound_prepare(RCT2_SOUND_CHAINLIFT, &_prepared_sound, 0, 1))
|
||||
if (sound_prepare(SOUND_LIFT_7, &_prepared_sound, 0, 1))
|
||||
if (sound_play(&_prepared_sound, 1, 0, 0, 0))
|
||||
_sound_playing_flag = 1;
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ void intro_update()
|
|||
// Play the track friction sound
|
||||
if (RCT2_GLOBAL(0x009AF280, sint32) != -1) {
|
||||
// Prepare and play the sound
|
||||
if (sound_prepare(RCT2_SOUND_TRACKFRICTION, &_prepared_sound, 1, 1))
|
||||
if (sound_prepare(SOUND_TRACK_FRICTION_3, &_prepared_sound, 1, 1))
|
||||
if (sound_play(&_prepared_sound, 1, -800, 0, 0x3A98))
|
||||
_sound_playing_flag = 1;
|
||||
}
|
||||
|
@ -189,7 +189,7 @@ void intro_update()
|
|||
|
||||
// Play long peep scream sound
|
||||
if (RCT2_GLOBAL(0x009AF280, sint32) != -1)
|
||||
if (sound_prepare(RCT2_SOUND_SCREAM, &_prepared_sound, 0, 1))
|
||||
if (sound_prepare(SOUND_SCREAM_1, &_prepared_sound, 0, 1))
|
||||
if (sound_play(&_prepared_sound, 0, 0, 0, 0))
|
||||
_sound_playing_flag = 1;
|
||||
|
||||
|
|
38
src/map.c
38
src/map.c
|
@ -328,4 +328,40 @@ void sub_68B089()
|
|||
} while (mapElement->base_height == 255);
|
||||
mapElement++;
|
||||
RCT2_GLOBAL(0x0140E9A4, rct_map_element*) = mapElement;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the tile at coordinate at height counts as connected.
|
||||
* @return 1 if connected, 0 otherwise
|
||||
*/
|
||||
int map_coord_is_connected(uint16 tile_idx, uint8 height, uint8 face_direction)
|
||||
{
|
||||
rct_map_element* tile = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx];
|
||||
|
||||
do {
|
||||
rct_map_element_path_properties props = tile->properties.path;
|
||||
uint8 path_type = props.type >> 2, path_dir = props.type & 3;
|
||||
uint8 element_type = tile->type & MAP_ELEMENT_TYPE_MASK;
|
||||
|
||||
if (element_type != PATH_ROAD)
|
||||
continue;
|
||||
|
||||
if (path_type & 1) {
|
||||
if (path_dir == face_direction) {
|
||||
if (height == tile->base_height + 2)
|
||||
return 1;
|
||||
}
|
||||
else if ((path_dir ^ 2) == face_direction && height == tile->base_height) {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (height == tile->base_height)
|
||||
return 1;
|
||||
}
|
||||
|
||||
} while (!(tile->flags & MAP_ELEMENT_FLAG_LAST_TILE) && tile++);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -195,5 +195,7 @@ void map_init();
|
|||
void map_update_tile_pointers();
|
||||
int map_element_height(int x, int y);
|
||||
void sub_68B089();
|
||||
int map_coord_is_connected(uint16 coordinate, uint8 height, uint8 face_direction);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (c) 2014 Ted John
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* This file is part of OpenRCT2.
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "addresses.h"
|
||||
#include "marketing.h"
|
||||
#include "news_item.h"
|
||||
#include "rct2.h"
|
||||
#include "ride.h"
|
||||
#include "string_ids.h"
|
||||
#include "window.h"
|
||||
|
||||
const int advertisingCampaignGuestGenerationProbabilities[] = { 400, 300, 200, 200, 250, 200 };
|
||||
|
||||
int marketing_get_campaign_guest_generation_probability(int campaign)
|
||||
{
|
||||
int probability = advertisingCampaignGuestGenerationProbabilities[campaign];
|
||||
rct_ride *ride;
|
||||
|
||||
// Lower probability of guest generation if price was already low
|
||||
switch (campaign) {
|
||||
case ADVERTISING_CAMPAIGN_PARK_ENTRY_FREE:
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16) < 4)
|
||||
probability /= 8;
|
||||
break;
|
||||
case ADVERTISING_CAMPAIGN_PARK_ENTRY_HALF_PRICE:
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16) < 6)
|
||||
probability /= 8;
|
||||
break;
|
||||
case ADVERTISING_CAMPAIGN_RIDE_FREE:
|
||||
ride = &(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[RCT2_ADDRESS(0x01358116, uint8)[campaign]]);
|
||||
if (ride->price < 3)
|
||||
probability /= 8;
|
||||
break;
|
||||
}
|
||||
|
||||
return probability;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update status of marketing campaigns and send produce a news item when they have finished.
|
||||
* rct2: 0x0069E0C1
|
||||
**/
|
||||
void marketing_update()
|
||||
{
|
||||
for (int campaign = 0; campaign < ADVERTISING_CAMPAIGN_COUNT; campaign++) {
|
||||
uint8 campaign_weeks_left = RCT2_ADDRESS(0x01358102, uint8)[campaign];
|
||||
if (campaign_weeks_left == 0)
|
||||
continue;
|
||||
|
||||
window_invalidate_by_id(WC_FINANCES, 0);
|
||||
|
||||
// High bit marks the campaign as inactive, on first check the campaign is set actice
|
||||
// this makes campaigns run a full x weeks even when started in the middle of a week
|
||||
RCT2_ADDRESS(0x01358102, uint8)[campaign] &= ~(1 << 7);
|
||||
if (campaign_weeks_left & (1 << 7))
|
||||
continue;
|
||||
|
||||
RCT2_ADDRESS(0x01358102, uint8)[campaign]--;
|
||||
if (campaign_weeks_left - 1 != 0)
|
||||
continue;
|
||||
|
||||
int campaign_item = RCT2_ADDRESS(0x01358116, uint8)[campaign];
|
||||
|
||||
// This sets the string parameters for the marketing types that have an argument.
|
||||
if (campaign == ADVERTISING_CAMPAIGN_RIDE_FREE || campaign == ADVERTISING_CAMPAIGN_RIDE) {
|
||||
RCT2_GLOBAL(0x013CE952, uint16) = RCT2_GLOBAL(0x01362942 + 304 * campaign_item, uint16);
|
||||
RCT2_GLOBAL(0x013CE954, uint32) = RCT2_GLOBAL(0x01362944 + 152 * campaign_item, uint32);
|
||||
} else if (campaign == ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE) {
|
||||
campaign_item += 2016;
|
||||
if (campaign_item >= 2048)
|
||||
campaign_item += 96;
|
||||
RCT2_GLOBAL(0x013CE952, uint16) = campaign_item;
|
||||
}
|
||||
|
||||
news_item_add_to_queue(NEWS_ITEM_MONEY, STR_MARKETING_FINISHED_BASE + campaign, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void marketing_set_guest_campaign(rct_peep *peep, int campaign)
|
||||
{
|
||||
switch (campaign) {
|
||||
case ADVERTISING_CAMPAIGN_PARK_ENTRY_FREE:
|
||||
peep->item_standard_flags |= PEEP_ITEM_VOUCHER;
|
||||
peep->var_F0 = 0;
|
||||
break;
|
||||
case ADVERTISING_CAMPAIGN_RIDE_FREE:
|
||||
peep->item_standard_flags |= PEEP_ITEM_VOUCHER;
|
||||
peep->var_F0 = 1;
|
||||
peep->var_F1 = RCT2_ADDRESS(0x01358116, uint8)[campaign];
|
||||
peep->var_C5 = RCT2_ADDRESS(0x01358116, uint8)[campaign];
|
||||
peep->var_C6 = 240;
|
||||
break;
|
||||
case ADVERTISING_CAMPAIGN_PARK_ENTRY_HALF_PRICE:
|
||||
peep->item_standard_flags |= PEEP_ITEM_VOUCHER;
|
||||
peep->var_F0 = 2;
|
||||
break;
|
||||
case ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE:
|
||||
peep->item_standard_flags |= PEEP_ITEM_VOUCHER;
|
||||
peep->var_F0 = 3;
|
||||
peep->var_F1 = RCT2_ADDRESS(0x01358116, uint8)[campaign];
|
||||
break;
|
||||
case ADVERTISING_CAMPAIGN_PARK:
|
||||
break;
|
||||
case ADVERTISING_CAMPAIGN_RIDE:
|
||||
peep->var_C5 = RCT2_ADDRESS(0x01358116, uint8)[campaign];
|
||||
peep->var_C6 = 240;
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (c) 2014 Ted John
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* This file is part of OpenRCT2.
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _MARKETING_H_
|
||||
#define _MARKETING_H_
|
||||
|
||||
#include "peep.h"
|
||||
|
||||
enum {
|
||||
ADVERTISING_CAMPAIGN_PARK_ENTRY_FREE,
|
||||
ADVERTISING_CAMPAIGN_RIDE_FREE,
|
||||
ADVERTISING_CAMPAIGN_PARK_ENTRY_HALF_PRICE,
|
||||
ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE,
|
||||
ADVERTISING_CAMPAIGN_PARK,
|
||||
ADVERTISING_CAMPAIGN_RIDE,
|
||||
ADVERTISING_CAMPAIGN_COUNT
|
||||
};
|
||||
|
||||
int marketing_get_campaign_guest_generation_probability(int campaign);
|
||||
void marketing_update();
|
||||
void marketing_set_guest_campaign(rct_peep *peep, int campaign);
|
||||
|
||||
#endif
|
|
@ -97,7 +97,7 @@ void news_item_update_current()
|
|||
newsItems[0].ticks++;
|
||||
if (newsItems[0].ticks == 1 && !(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 1)) {
|
||||
// Play sound
|
||||
sound_play_panned(39, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16) / 2);
|
||||
sound_play_panned(SOUND_NEWS_ITEM, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, sint16) / 2);
|
||||
}
|
||||
|
||||
// Removal of current news item
|
||||
|
@ -178,7 +178,7 @@ void news_item_get_subject_location(int type, int subject, int *x, int *y, int *
|
|||
int i;
|
||||
rct_ride *ride;
|
||||
rct_peep *peep;
|
||||
rct_car *car;
|
||||
rct_vehicle *vehicle;
|
||||
|
||||
switch (type) {
|
||||
case NEWS_ITEM_RIDE:
|
||||
|
@ -192,7 +192,7 @@ void news_item_get_subject_location(int type, int subject, int *x, int *y, int *
|
|||
*z = map_element_height(*x, *y);
|
||||
break;
|
||||
case NEWS_ITEM_PEEP_ON_RIDE:
|
||||
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[subject]).peep;
|
||||
peep = GET_PEEP(subject);
|
||||
*x = peep->x;
|
||||
*y = peep->y;
|
||||
*z = peep->z;
|
||||
|
@ -212,16 +212,16 @@ void news_item_get_subject_location(int type, int subject, int *x, int *y, int *
|
|||
}
|
||||
|
||||
// Find the first car of the train peep is on
|
||||
car = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[ride->train_car_map[peep->current_train]]).car;
|
||||
vehicle = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[ride->train_car_map[peep->current_train]]).vehicle;
|
||||
// Find the actual car peep is on
|
||||
for (i = 0; i < peep->current_car; i++)
|
||||
car = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[car->next_car]).car;
|
||||
*x = car->x;
|
||||
*y = car->y;
|
||||
*z = car->z;
|
||||
vehicle = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[vehicle->next_vehicle_on_train]).vehicle;
|
||||
*x = vehicle->x;
|
||||
*y = vehicle->y;
|
||||
*z = vehicle->z;
|
||||
break;
|
||||
case NEWS_ITEM_PEEP:
|
||||
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[subject]).peep;
|
||||
peep = GET_PEEP(subject);
|
||||
*x = peep->x;
|
||||
*y = peep->y;
|
||||
*z = peep->z;
|
||||
|
@ -295,12 +295,11 @@ void news_item_open_subject(int type, int subject) {
|
|||
break;
|
||||
case NEWS_ITEM_PEEP_ON_RIDE:
|
||||
case NEWS_ITEM_PEEP:
|
||||
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[subject]).peep;
|
||||
peep = GET_PEEP(subject);
|
||||
RCT2_CALLPROC_X(0x006989E9, 0, 0, 0, (int)peep, 0, 0, 0);
|
||||
break;
|
||||
case NEWS_ITEM_MONEY:
|
||||
// Open finances window
|
||||
RCT2_CALLPROC_EBPSAFE(0x0069DDF1);
|
||||
window_finances_open();
|
||||
break;
|
||||
case NEWS_ITEM_RESEARCH:
|
||||
|
||||
|
|
190
src/object.c
190
src/object.c
|
@ -18,8 +18,11 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <memory.h>
|
||||
#include <stdio.h>
|
||||
#include "addresses.h"
|
||||
#include "object.h"
|
||||
#include "sawyercoding.h"
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -47,19 +50,188 @@ void object_unload(int groupIndex, rct_object_entry_extended *entry)
|
|||
RCT2_CALLPROC_X(0x006A9CAF, 0, groupIndex, 0, 0, 0, 0, (int)entry);
|
||||
}
|
||||
|
||||
static int object_entry_compare(rct_object_entry *a, rct_object_entry *b)
|
||||
{
|
||||
if (a->flags & 0xF0) {
|
||||
if ((a->flags & 0x0F) != (b->flags & 0x0F))
|
||||
return 0;
|
||||
if (*((uint32*)a->name) != *((uint32*)b->name))
|
||||
return 0;
|
||||
if (*((uint32*)(&a->name[4])) != *((uint32*)(&b->name[4])))
|
||||
return 0;
|
||||
} else {
|
||||
if (a->flags != b->flags)
|
||||
return 0;
|
||||
if (*((uint32*)a->name) != *((uint32*)b->name))
|
||||
return 0;
|
||||
if (*((uint32*)(&a->name[4])) != *((uint32*)(&b->name[4])))
|
||||
return 0;
|
||||
if (a->checksum != b->checksum)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int object_calculate_checksum(rct_object_entry *entry, char *data, int dataLength)
|
||||
{
|
||||
int i;
|
||||
char *eee = (char*)entry;
|
||||
int checksum = 0xF369A75B;
|
||||
char *ccc = (char*)&checksum;
|
||||
|
||||
*ccc ^= eee[0];
|
||||
checksum = rol32(checksum, 11);
|
||||
for (i = 4; i < 12; i++) {
|
||||
*ccc ^= eee[i];
|
||||
checksum = rol32(checksum, 11);
|
||||
}
|
||||
for (i = 0; i < dataLength; i++) {
|
||||
*ccc ^= data[i];
|
||||
checksum = rol32(checksum, 11);
|
||||
}
|
||||
|
||||
return checksum;
|
||||
}
|
||||
|
||||
int object_paint(int type, int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp)
|
||||
{
|
||||
RCT2_CALLPROC_X(RCT2_ADDRESS(0x0098D9D4, uint32)[type], eax, ebx, ecx, edx, esi, edi, ebp);
|
||||
#ifdef _MSC_VER
|
||||
__asm jb success
|
||||
#else
|
||||
__asm__ goto ( "jb %l0" : : : : success );
|
||||
#endif
|
||||
return 0;
|
||||
success:
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006A9428
|
||||
*/
|
||||
int sub_6A9428(rct_object_entry* entry)
|
||||
int object_get_scenario_text(rct_object_entry *entry)
|
||||
{
|
||||
RCT2_CALLPROC_X(0x006A9428, 0, 0, 0, 0, 0, 0, (int)entry);
|
||||
#ifdef _MSC_VER
|
||||
__asm jb fail
|
||||
#else
|
||||
__asm__ goto ( "jb %l0" : : : : fail );
|
||||
#endif
|
||||
return 1;
|
||||
fail:
|
||||
// RCT2_CALLPROC_X(0x006A9428, 0, 0, 0, 0, 0, 0, (int)entry); return;
|
||||
|
||||
int i;
|
||||
rct_object_entry *installedObject = RCT2_GLOBAL(0x009ADAE8, rct_object_entry*);
|
||||
for (i = 0; i < RCT2_GLOBAL(0x00F42B6C, sint32); i++) {
|
||||
if (object_entry_compare(installedObject, entry)) {
|
||||
char path[260];
|
||||
char *objectPath = (char*)installedObject + 16;
|
||||
subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), objectPath);
|
||||
|
||||
rct_object_entry openedEntry;
|
||||
FILE *file = fopen(path, "rb");
|
||||
if (file != NULL) {
|
||||
fread(&openedEntry, sizeof(rct_object_entry), 1, file);
|
||||
if (object_entry_compare(&openedEntry, entry)) {
|
||||
|
||||
// Get chunk size
|
||||
char *pos = (char*)installedObject + 16;
|
||||
do {
|
||||
pos++;
|
||||
} while (*(pos - 1) != 0);
|
||||
|
||||
// Read chunk
|
||||
int chunkSize = *((uint32*)pos);
|
||||
char *chunk;
|
||||
if (chunkSize == 0xFFFFFFFF) {
|
||||
chunk = malloc(0x600000);
|
||||
chunkSize = sawyercoding_read_chunk(file, chunk);
|
||||
chunk = realloc(chunk, chunkSize);
|
||||
} else {
|
||||
chunk = malloc(chunkSize);
|
||||
sawyercoding_read_chunk(file, chunk);
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
// Calculate and check checksum
|
||||
if (object_calculate_checksum(&openedEntry, chunk, chunkSize) != openedEntry.checksum) {
|
||||
RCT2_GLOBAL(0x00F42BD9, uint8) = 2;
|
||||
free(chunk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (object_paint(openedEntry.flags & 0x0F, 2, 0, 0, 0, (int)chunk, 0, 0)) {
|
||||
RCT2_GLOBAL(0x00F42BD9, uint8) = 3;
|
||||
free(chunk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int yyy = RCT2_GLOBAL(0x009ADAF0, uint32);
|
||||
RCT2_GLOBAL(0x009ADAF0, uint32) = 0x726E;
|
||||
RCT2_GLOBAL(0x009ADAF8, uint32) = (int)chunk;
|
||||
*((rct_object_entry*)0x00F42BC8) = openedEntry;
|
||||
|
||||
RCT2_GLOBAL(0x009ADAFC, uint8) = 255;
|
||||
RCT2_GLOBAL(0x009ADAFD, uint8) = 1;
|
||||
object_paint(openedEntry.flags & 0x0F, 0, 0, 0, 0, (int)chunk, 0, 0);
|
||||
RCT2_GLOBAL(0x009ADAFC, uint8) = 0;
|
||||
RCT2_GLOBAL(0x009ADAFD, uint8) = 0;
|
||||
RCT2_GLOBAL(0x009ADAF0, uint32) = yyy;
|
||||
return 1;
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
installedObject = object_get_next(installedObject);
|
||||
}
|
||||
|
||||
RCT2_GLOBAL(0x00F42BD9, uint8) = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006A982D
|
||||
*/
|
||||
void object_free_scenario_text()
|
||||
{
|
||||
if (RCT2_GLOBAL(0x009ADAF8, void*) != NULL) {
|
||||
free(RCT2_GLOBAL(0x009ADAF8, void*));
|
||||
RCT2_GLOBAL(0x009ADAF8, void*) = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int object_get_length(rct_object_entry *entry)
|
||||
{
|
||||
return (int)object_get_next(entry) - (int)entry;
|
||||
}
|
||||
|
||||
rct_object_entry *object_get_next(rct_object_entry *entry)
|
||||
{
|
||||
char *pos = (char*)entry;
|
||||
|
||||
// Skip
|
||||
pos += 16;
|
||||
|
||||
// Skip filename
|
||||
do {
|
||||
pos++;
|
||||
} while (*(pos - 1) != 0);
|
||||
|
||||
// Skip
|
||||
pos += 4;
|
||||
|
||||
// Skip name
|
||||
do {
|
||||
pos++;
|
||||
} while (*(pos - 1) != 0);
|
||||
|
||||
// Skip
|
||||
pos += 4;
|
||||
|
||||
// Skip
|
||||
pos += *pos++ * 16;
|
||||
|
||||
// Skip theme objects
|
||||
pos += *pos++ * 16;
|
||||
|
||||
// Skip
|
||||
pos += 4;
|
||||
|
||||
return (rct_object_entry*)pos;
|
||||
}
|
|
@ -52,6 +52,9 @@ void object_unload_all();
|
|||
|
||||
int object_load(int groupIndex, rct_object_entry *entry);
|
||||
void object_unload(int groupIndex, rct_object_entry_extended *entry);
|
||||
int sub_6A9428(rct_object_entry* entry);
|
||||
int object_get_scenario_text(rct_object_entry *entry);
|
||||
void object_free_scenario_text();
|
||||
int object_get_length(rct_object_entry *entry);
|
||||
rct_object_entry *object_get_next(rct_object_entry *entry);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -51,15 +51,15 @@ int object_entry_group_counts[] = {
|
|||
struct { void **data; rct_object_entry_extended *entries; } object_entry_groups[] = {
|
||||
(void**)(0x009ACFA4 ), (rct_object_entry_extended*)(0x00F3F03C ), // rides
|
||||
(void**)(0x009ACFA4 + (128 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (128 * 20)), // small scenery
|
||||
(void**)(0x009ACFA4 + (252 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (252 * 20)), // large scenery
|
||||
(void**)(0x009ACFA4 + (128 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (128 * 20)), // walls
|
||||
(void**)(0x009ACFA4 + (128 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (128 * 20)), // banners
|
||||
(void**)(0x009ACFA4 + ( 32 * 4)), (rct_object_entry_extended*)(0x00F3F03C + ( 32 * 20)), // paths
|
||||
(void**)(0x009ACFA4 + ( 16 * 4)), (rct_object_entry_extended*)(0x00F3F03C + ( 16 * 20)), // path bits
|
||||
(void**)(0x009ACFA4 + ( 15 * 4)), (rct_object_entry_extended*)(0x00F3F03C + ( 15 * 20)), // scenery sets
|
||||
(void**)(0x009ACFA4 + ( 19 * 4)), (rct_object_entry_extended*)(0x00F3F03C + ( 19 * 20)), // park entrance
|
||||
(void**)(0x009ACFA4 + ( 1 * 4)), (rct_object_entry_extended*)(0x00F3F03C + ( 1 * 20)), // water
|
||||
(void**)(0x009ACFA4 + ( 1 * 4)), (rct_object_entry_extended*)(0x00F3F03C + ( 1 * 20)) // scenario text
|
||||
(void**)(0x009ACFA4 + (380 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (380 * 20)), // large scenery
|
||||
(void**)(0x009ACFA4 + (508 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (508 * 20)), // walls
|
||||
(void**)(0x009ACFA4 + (636 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (636 * 20)), // banners
|
||||
(void**)(0x009ACFA4 + (668 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (668 * 20)), // paths
|
||||
(void**)(0x009ACFA4 + (684 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (684 * 20)), // path bits
|
||||
(void**)(0x009ACFA4 + (699 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (699 * 20)), // scenery sets
|
||||
(void**)(0x009ACFA4 + (718 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (718 * 20)), // park entrance
|
||||
(void**)(0x009ACFA4 + (719 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (719 * 20)), // water
|
||||
(void**)(0x009ACFA4 + (720 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (720 * 20)) // scenario text
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -69,42 +69,14 @@ struct { void **data; rct_object_entry_extended *entries; } object_entry_groups[
|
|||
static void object_list_examine()
|
||||
{
|
||||
int i;
|
||||
char *object;
|
||||
rct_object_entry *object;
|
||||
|
||||
object = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, char*);
|
||||
object = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*);
|
||||
for (i = 0; i < RCT2_GLOBAL(0x00F42B6C, sint32); i++) {
|
||||
if (*object & 0xF0)
|
||||
if (object->flags & 0xF0)
|
||||
RCT2_GLOBAL(0x00F42BDA, uint8) |= 1;
|
||||
|
||||
// Skip
|
||||
object += 16;
|
||||
|
||||
// Skip filename
|
||||
// printf("%d %s : ", i, object);
|
||||
do {
|
||||
object++;
|
||||
} while (*(object - 1) != 0);
|
||||
|
||||
// Skip
|
||||
object += 4;
|
||||
|
||||
// Skip name
|
||||
// printf("%s\n", object);
|
||||
do {
|
||||
object++;
|
||||
} while (*(object - 1) != 0);
|
||||
|
||||
// Skip
|
||||
object += 4;
|
||||
|
||||
// Skip
|
||||
object += *object++ * 16;
|
||||
|
||||
// Skip theme objects
|
||||
object += *object++ * 16;
|
||||
|
||||
// Skip
|
||||
object += 4;
|
||||
object = object_get_next(object);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ unsigned int gLastKeyPressed;
|
|||
static void osinterface_create_window();
|
||||
static void osinterface_close_window();
|
||||
static void osinterface_resize(int width, int height);
|
||||
static void osinterface_update_palette(char* colours, int start_index, int num_colours);
|
||||
|
||||
|
||||
static SDL_Window *_window;
|
||||
static SDL_Surface *_surface;
|
||||
|
@ -91,6 +91,7 @@ static void osinterface_create_window()
|
|||
exit(-1);
|
||||
}
|
||||
|
||||
SDL_VERSION(&wmInfo.version);
|
||||
// Get the HWND context
|
||||
if (SDL_GetWindowWMInfo(_window, &wmInfo) != SDL_TRUE) {
|
||||
RCT2_ERROR("SDL_GetWindowWMInfo failed %s", SDL_GetError());
|
||||
|
@ -167,7 +168,7 @@ static void osinterface_resize(int width, int height)
|
|||
gfx_invalidate_screen();
|
||||
}
|
||||
|
||||
static void osinterface_update_palette(char* colours, int start_index, int num_colours)
|
||||
void osinterface_update_palette(char* colours, int start_index, int num_colours)
|
||||
{
|
||||
SDL_Color base[256];
|
||||
SDL_Surface *surface;
|
||||
|
@ -394,14 +395,14 @@ char* osinterface_open_directory_browser(char *title) {
|
|||
LPMALLOC lpMalloc;
|
||||
|
||||
// Initialize COM
|
||||
if (CoInitializeEx(0, COINIT_APARTMENTTHREADED) != S_OK) {
|
||||
if (FAILED(CoInitializeEx(0, COINIT_APARTMENTTHREADED))) {
|
||||
MessageBox(NULL, _T("Error opening browse window"), _T("ERROR"), MB_OK);
|
||||
CoUninitialize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get a pointer to the shell memory allocator
|
||||
if (SHGetMalloc(&lpMalloc) != S_OK) {
|
||||
if (FAILED(SHGetMalloc(&lpMalloc))) {
|
||||
MessageBox(NULL, _T("Error opening browse window"), _T("ERROR"), MB_OK);
|
||||
CoUninitialize();
|
||||
return 0;
|
||||
|
@ -428,3 +429,52 @@ char* osinterface_open_directory_browser(char *title) {
|
|||
CoUninitialize();
|
||||
return outPath;
|
||||
}
|
||||
|
||||
char* osinterface_get_orct2_homefolder()
|
||||
{
|
||||
char *path=NULL;
|
||||
path = malloc(sizeof(char) * MAX_PATH);
|
||||
if (path == NULL){
|
||||
osinterface_show_messagebox("Error allocating memory!");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
path[0] = '\0';
|
||||
|
||||
if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, 0, path)))
|
||||
strcat(path, "\\OpenRCT2");
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
char *osinterface_get_orct2_homesubfolder(const char *subFolder)
|
||||
{
|
||||
char *path = osinterface_get_orct2_homefolder();
|
||||
strcat(path, "\\");
|
||||
strcat(path, subFolder);
|
||||
return path;
|
||||
}
|
||||
|
||||
int osinterface_file_exists(const char *path)
|
||||
{
|
||||
return !(GetFileAttributes(path) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
int osinterface_directory_exists(const char *path)
|
||||
{
|
||||
DWORD dwAttrib = GetFileAttributes(path);
|
||||
return dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY);
|
||||
}
|
||||
|
||||
int osinterface_ensure_directory_exists(const char *path)
|
||||
{
|
||||
if (osinterface_directory_exists(path))
|
||||
return 1;
|
||||
|
||||
return CreateDirectory(path, NULL);
|
||||
}
|
||||
|
||||
char osinterface_get_path_separator()
|
||||
{
|
||||
return '\\';
|
||||
}
|
||||
|
|
|
@ -45,9 +45,18 @@ void osinterface_init();
|
|||
void osinterface_process_messages();
|
||||
void osinterface_draw();
|
||||
void osinterface_free();
|
||||
void osinterface_update_palette(char* colours, int start_index, int num_colours);
|
||||
|
||||
int osinterface_open_common_file_dialog(int type, char *title, char *filename, char *filterPattern, char *filterName);
|
||||
void osinterface_show_messagebox(char* message);
|
||||
char* osinterface_open_directory_browser(char *title);
|
||||
|
||||
char* osinterface_get_orct2_homefolder();
|
||||
char *osinterface_get_orct2_homesubfolder(const char *subFolder);
|
||||
int osinterface_file_exists(const char *path);
|
||||
int osinterface_directory_exists(const char *path);
|
||||
int osinterface_ensure_directory_exists(const char *path);
|
||||
|
||||
char osinterface_get_path_separator();
|
||||
|
||||
#endif
|
||||
|
|
254
src/park.c
254
src/park.c
|
@ -20,8 +20,11 @@
|
|||
|
||||
#include <windows.h>
|
||||
#include "addresses.h"
|
||||
#include "award.h"
|
||||
#include "finance.h"
|
||||
#include "map.h"
|
||||
#include "marketing.h"
|
||||
#include "news_item.h"
|
||||
#include "park.h"
|
||||
#include "peep.h"
|
||||
#include "ride.h"
|
||||
|
@ -30,7 +33,18 @@
|
|||
#include "string_ids.h"
|
||||
#include "window.h"
|
||||
|
||||
const int advertisingCampaignGuestGenerationProbabilities[] = { 400, 300, 200, 200, 250, 200 };
|
||||
/**
|
||||
* In a difficult guest generation scenario, no guests will be generated if over this value.
|
||||
*/
|
||||
int _suggestedGuestMaximum;
|
||||
|
||||
/**
|
||||
* Probability out of 65535, of gaining a new guest per game tick.
|
||||
* new guests per second = 40 * (probability / 65535)
|
||||
* With a full park rating, non-overpriced entrance fee, less guests than the suggested maximum and four positive awards,
|
||||
* approximately 1 guest per second can be generated (+60 guests in one minute).
|
||||
*/
|
||||
int _guestGenerationProbability;
|
||||
|
||||
int park_is_open()
|
||||
{
|
||||
|
@ -55,8 +69,8 @@ void park_init()
|
|||
RCT2_GLOBAL(0x01357846, uint16) = 0;
|
||||
RCT2_GLOBAL(0x013573FE, uint16) = 0;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_RATING, uint16) = 0;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_GUEST_GENERATION_PROBABILITY, uint16) = 0;
|
||||
RCT2_GLOBAL(0x013580EE, uint16) = 0;
|
||||
_guestGenerationProbability = 0;
|
||||
RCT2_GLOBAL(RCT2_TOTAL_RIDE_VALUE, uint16) = 0;
|
||||
RCT2_GLOBAL(0x01357CF4, sint32) = -1;
|
||||
|
||||
for (i = 0; i < 20; i++)
|
||||
|
@ -90,7 +104,9 @@ void park_init()
|
|||
RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCTION_RIGHTS_COST, uint16) = MONEY(40,00);
|
||||
RCT2_GLOBAL(0x01358774, uint16) = 0;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) = PARK_FLAGS_11 | PARK_FLAGS_SHOW_REAL_GUEST_NAMES;
|
||||
park_reset_awards_and_history();
|
||||
park_reset_history();
|
||||
finance_reset_history();
|
||||
award_reset();
|
||||
|
||||
rct_s6_info *info = (rct_s6_info*)0x0141F570;
|
||||
info->name[0] = '\0';
|
||||
|
@ -101,26 +117,13 @@ void park_init()
|
|||
*
|
||||
* rct2: 0x0066729F
|
||||
*/
|
||||
void park_reset_awards_and_history()
|
||||
void park_reset_history()
|
||||
{
|
||||
int i;
|
||||
|
||||
// Reset park rating and guests in park history
|
||||
for (i = 0; i < 32; i++) {
|
||||
RCT2_ADDRESS(RCT2_ADDRESS_PARK_RATING_HISTORY, uint8)[i] = 255;
|
||||
RCT2_ADDRESS(RCT2_ADDRESS_GUESTS_IN_PARK_HISTORY, uint8)[i] = 255;
|
||||
}
|
||||
|
||||
// Reset finance history
|
||||
for (i = 0; i < 128; i++) {
|
||||
RCT2_ADDRESS(RCT2_ADDRESS_BALANCE_HISTORY, money32)[i] = MONEY32_UNDEFINED;
|
||||
RCT2_ADDRESS(RCT2_ADDRESS_WEEKLY_PROFIT_HISTORY, money32)[i] = MONEY32_UNDEFINED;
|
||||
RCT2_ADDRESS(RCT2_ADDRESS_PARK_VALUE_HISTORY, money32)[i] = MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
// Reset awards
|
||||
for (i = 0; i < 4; i++)
|
||||
RCT2_ADDRESS(RCT2_ADDRESS_AWARD_LIST, rct_award)[i].time = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -168,7 +171,7 @@ int calculate_park_rating()
|
|||
// Guests
|
||||
{
|
||||
rct_peep* peep;
|
||||
uint16 sprite_idx;
|
||||
uint16 spriteIndex;
|
||||
int num_happy_peeps;
|
||||
short _bp;
|
||||
|
||||
|
@ -178,10 +181,7 @@ int calculate_park_rating()
|
|||
// Guests, happiness, ?
|
||||
num_happy_peeps = 0;
|
||||
_bp = 0;
|
||||
for (sprite_idx = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16); sprite_idx != SPRITE_INDEX_NULL; sprite_idx = peep->next) {
|
||||
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[sprite_idx].peep);
|
||||
if (peep->type != PEEP_TYPE_GUEST)
|
||||
continue;
|
||||
FOR_ALL_GUESTS(spriteIndex, peep) {
|
||||
if (peep->var_2A != 0)
|
||||
continue;
|
||||
if (peep->happiness > 128)
|
||||
|
@ -214,11 +214,7 @@ int calculate_park_rating()
|
|||
//
|
||||
_ax = 0;
|
||||
num_rides = 0;
|
||||
for (i = 0; i < 255; i++) {
|
||||
ride = &(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[i]);
|
||||
|
||||
if (ride->type == RIDE_TYPE_NULL)
|
||||
continue;
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
_ax += 100 - ride->var_199;
|
||||
|
||||
if (ride->excitement != -1){
|
||||
|
@ -350,14 +346,113 @@ void reset_park_entrances()
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Calculates the probability of a new guest. Also sets total ride value and suggested guest maximum.
|
||||
* Total ride value should probably be set else where, as its not just used for guest generation.
|
||||
* Suggested guest maximum should probably be an output result, not a global.
|
||||
* @returns A probability out of 65535
|
||||
* rct2: 0x0066730A
|
||||
*/
|
||||
static int park_calculate_guest_generation_probability()
|
||||
{
|
||||
int eax, ebx, ecx, edx, esi, edi, ebp;
|
||||
RCT2_CALLFUNC_X(0x0066730A, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
|
||||
return eax & 0xFFFF;
|
||||
unsigned int probability;
|
||||
int i, suggestedMaxGuests, totalRideValue;
|
||||
rct_ride *ride;
|
||||
|
||||
// Calculate suggested guest maximum (based on ride type) and total ride value
|
||||
suggestedMaxGuests = 0;
|
||||
totalRideValue = 0;
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
if (ride->status != RIDE_STATUS_OPEN)
|
||||
continue;
|
||||
if (ride->lifecycle_flags & 0x80)
|
||||
continue;
|
||||
if (ride->lifecycle_flags & 0x400)
|
||||
continue;
|
||||
|
||||
// Add guest score for ride type
|
||||
suggestedMaxGuests += RCT2_GLOBAL(0x0097D21E + (ride->type * 8), uint8);
|
||||
|
||||
// Add ride value
|
||||
if (ride->reliability != RIDE_RELIABILITY_UNDEFINED) {
|
||||
int rideValue = ride->reliability - ride->price;
|
||||
if (rideValue > 0)
|
||||
totalRideValue += rideValue * 2;
|
||||
}
|
||||
}
|
||||
|
||||
// If difficult guest generation, extra guests are available for good rides
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_DIFFICULT_GUEST_GENERATION) {
|
||||
suggestedMaxGuests = min(suggestedMaxGuests, 1000);
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
if (ride->lifecycle_flags & 0x80)
|
||||
continue;
|
||||
if (ride->lifecycle_flags & 0x400)
|
||||
continue;
|
||||
|
||||
if (!(RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x10000000))
|
||||
continue;
|
||||
if (!(RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x200))
|
||||
continue;
|
||||
if (!(ride->lifecycle_flags & 0x02))
|
||||
continue;
|
||||
if (ride->var_0E4 < 0x2580000)
|
||||
continue;
|
||||
if (ride->excitement < RIDE_RATING(6,00))
|
||||
continue;
|
||||
|
||||
// Bonus guests for good ride
|
||||
suggestedMaxGuests += RCT2_GLOBAL(0x0097D21E + (ride->type * 8), uint8) * 2;
|
||||
}
|
||||
}
|
||||
|
||||
suggestedMaxGuests = min(suggestedMaxGuests, 65535);
|
||||
RCT2_GLOBAL(RCT2_TOTAL_RIDE_VALUE, uint16) = totalRideValue;
|
||||
_suggestedGuestMaximum = suggestedMaxGuests;
|
||||
|
||||
// Begin with 50 + park rating
|
||||
probability = 50 + clamp(0, RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_RATING, uint16) - 200, 650);
|
||||
|
||||
// The more guests, the lower the chance of a new one
|
||||
int numGuests = RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16) + RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_HEADING_FOR_PARK, uint16);
|
||||
if (numGuests > suggestedMaxGuests) {
|
||||
probability /= 4;
|
||||
|
||||
// Even lower for difficult guest generation
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_DIFFICULT_GUEST_GENERATION)
|
||||
probability /= 4;
|
||||
}
|
||||
|
||||
// Reduces chance for any more than 7000 guests
|
||||
if (numGuests > 7000)
|
||||
probability /= 4;
|
||||
|
||||
// Check if money is enabled
|
||||
if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_11)) {
|
||||
// Penalty for overpriced entrance fee relative to total ride value
|
||||
money16 entranceFee = RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16);
|
||||
if (entranceFee > totalRideValue) {
|
||||
probability /= 4;
|
||||
|
||||
// Extra penalty for very overpriced entrance fee
|
||||
if (entranceFee / 2 > totalRideValue)
|
||||
probability /= 4;
|
||||
}
|
||||
}
|
||||
|
||||
// Reward or penalties for park awards
|
||||
for (i = 0; i < MAX_AWARDS; i++) {
|
||||
rct_award *award = &RCT2_ADDRESS(RCT2_ADDRESS_AWARD_LIST, rct_award)[i];
|
||||
if (award->time == 0)
|
||||
continue;
|
||||
|
||||
// +/- 0.25% of the probability
|
||||
if (award_is_positive(award->type))
|
||||
probability += probability / 4;
|
||||
else
|
||||
probability -= probability / 4;
|
||||
}
|
||||
|
||||
return probability;
|
||||
}
|
||||
|
||||
static void get_random_peep_spawn(rct2_peep_spawn *spawn)
|
||||
|
@ -370,17 +465,6 @@ static void get_random_peep_spawn(rct2_peep_spawn *spawn)
|
|||
*spawn = peepSpawns[1];
|
||||
}
|
||||
|
||||
static int park_should_generate_new_guest()
|
||||
{
|
||||
if ((scenario_rand() & 0xFFFF) < RCT2_GLOBAL(0x013580EC, uint16)) {
|
||||
int difficultGeneration = (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_DIFFICULT_GUEST_GENERATION) != 0;
|
||||
if (!difficultGeneration || RCT2_GLOBAL(0x0135883C, uint16) + 150 < RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static rct_peep *park_generate_new_guest()
|
||||
{
|
||||
rct_peep *peep;
|
||||
|
@ -388,9 +472,8 @@ static rct_peep *park_generate_new_guest()
|
|||
get_random_peep_spawn(&spawn);
|
||||
|
||||
if (spawn.x != 0xFFFF) {
|
||||
spawn.z *= 16;
|
||||
spawn.direction ^= 2;
|
||||
peep = peep_generate(spawn.x, spawn.y, spawn.z);
|
||||
peep = peep_generate(spawn.x, spawn.y, spawn.z * 16);
|
||||
if (peep != NULL) {
|
||||
peep->var_1E = spawn.direction << 3;
|
||||
|
||||
|
@ -412,75 +495,26 @@ static rct_peep *park_generate_new_guest()
|
|||
static rct_peep *park_generate_new_guest_due_to_campaign(int campaign)
|
||||
{
|
||||
rct_peep *peep = park_generate_new_guest();
|
||||
if (peep != NULL) {
|
||||
switch (campaign) {
|
||||
case ADVERTISING_CAMPAIGN_PARK_ENTRY_FREE:
|
||||
peep->item_standard_flags |= PEEP_ITEM_VOUCHER;
|
||||
peep->var_F0 = 0;
|
||||
break;
|
||||
case ADVERTISING_CAMPAIGN_RIDE_FREE:
|
||||
peep->item_standard_flags |= PEEP_ITEM_VOUCHER;
|
||||
peep->var_F0 = 1;
|
||||
peep->var_F1 = RCT2_ADDRESS(0x01358116, uint8)[campaign];
|
||||
peep->var_C5 = RCT2_ADDRESS(0x01358116, uint8)[campaign];
|
||||
peep->var_C6 = 240;
|
||||
break;
|
||||
case ADVERTISING_CAMPAIGN_PARK_ENTRY_HALF_PRICE:
|
||||
peep->item_standard_flags |= PEEP_ITEM_VOUCHER;
|
||||
peep->var_F0 = 2;
|
||||
break;
|
||||
case ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE:
|
||||
peep->item_standard_flags |= PEEP_ITEM_VOUCHER;
|
||||
peep->var_F0 = 3;
|
||||
peep->var_F1 = RCT2_ADDRESS(0x01358116, uint8)[campaign];
|
||||
break;
|
||||
case ADVERTISING_CAMPAIGN_PARK:
|
||||
break;
|
||||
case ADVERTISING_CAMPAIGN_RIDE:
|
||||
peep->var_C5 = RCT2_ADDRESS(0x01358116, uint8)[campaign];
|
||||
peep->var_C6 = 240;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int park_get_campaign_guest_generation_probability(int campaign)
|
||||
{
|
||||
int probability = advertisingCampaignGuestGenerationProbabilities[campaign];
|
||||
rct_ride *ride;
|
||||
|
||||
// Lower probability of guest generation if price was already low
|
||||
switch (campaign) {
|
||||
case ADVERTISING_CAMPAIGN_PARK_ENTRY_FREE:
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16) < 4)
|
||||
probability /= 8;
|
||||
break;
|
||||
case ADVERTISING_CAMPAIGN_PARK_ENTRY_HALF_PRICE:
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, money16) < 6)
|
||||
probability /= 8;
|
||||
break;
|
||||
case ADVERTISING_CAMPAIGN_RIDE_FREE:
|
||||
ride = &(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[RCT2_ADDRESS(0x01358116, uint8)[campaign]]);
|
||||
if (ride->price < 3)
|
||||
probability /= 8;
|
||||
break;
|
||||
}
|
||||
|
||||
return probability;
|
||||
if (peep != NULL)
|
||||
marketing_set_guest_campaign(peep, campaign);
|
||||
return peep;
|
||||
}
|
||||
|
||||
static void park_generate_new_guests()
|
||||
{
|
||||
// Check and generate a new guest
|
||||
if (park_should_generate_new_guest())
|
||||
park_generate_new_guest();
|
||||
// Generate a new guest for some probability
|
||||
if ((scenario_rand() & 0xFFFF) < _guestGenerationProbability) {
|
||||
int difficultGeneration = (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_DIFFICULT_GUEST_GENERATION) != 0;
|
||||
if (!difficultGeneration || _suggestedGuestMaximum + 150 >= RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16))
|
||||
park_generate_new_guest();
|
||||
}
|
||||
|
||||
// Extra guests generated by advertising campaigns
|
||||
int campaign;
|
||||
for (campaign = 0; campaign < ADVERTISING_CAMPAIGN_COUNT; campaign++) {
|
||||
if (RCT2_ADDRESS(0x01358102, uint8)[campaign] != 0) {
|
||||
// Random chance of guest generation
|
||||
if ((scenario_rand() & 0xFFFF) < park_get_campaign_guest_generation_probability(campaign))
|
||||
if ((scenario_rand() & 0xFFFF) < marketing_get_campaign_guest_generation_probability(campaign))
|
||||
park_generate_new_guest_due_to_campaign(campaign);
|
||||
}
|
||||
}
|
||||
|
@ -501,7 +535,7 @@ void park_update()
|
|||
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_VALUE, money32) = calculate_park_value();
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_COMPANY_VALUE, money32) = calculate_company_value();
|
||||
window_invalidate_by_id(WC_FINANCES, 0);
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_GUEST_GENERATION_PROBABILITY, uint16) = park_calculate_guest_generation_probability();
|
||||
_guestGenerationProbability = park_calculate_guest_generation_probability();
|
||||
RCT2_GLOBAL(0x009A9804, uint16) |= 0x10;
|
||||
window_invalidate_by_id(WC_PARK_INFORMATION, 0);
|
||||
}
|
||||
|
@ -510,6 +544,7 @@ void park_update()
|
|||
park_generate_new_guests();
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
static uint8 calculate_guest_initial_happiness(uint8 percentage) {
|
||||
if (percentage < 15) {
|
||||
// There is a minimum of 15% happiness
|
||||
|
@ -532,4 +567,13 @@ static uint8 calculate_guest_initial_happiness(uint8 percentage) {
|
|||
}
|
||||
}
|
||||
return 40; // This is the lowest possible value
|
||||
=======
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0066A231
|
||||
*/
|
||||
void park_update_histories()
|
||||
{
|
||||
RCT2_CALLPROC_EBPSAFE(0x0066A231);
|
||||
>>>>>>> upstream/master
|
||||
}
|
38
src/park.h
38
src/park.h
|
@ -26,41 +26,6 @@
|
|||
#define DECRYPT_MONEY(money) rol32((money) ^ 0xF4EC9621, 13)
|
||||
#define ENCRYPT_MONEY(money) (ror32((money), 13) ^ 0xF4EC9621)
|
||||
|
||||
typedef struct {
|
||||
uint16 time;
|
||||
uint16 type;
|
||||
} rct_award;
|
||||
|
||||
enum {
|
||||
PARK_AWARD_MOST_UNTIDY,
|
||||
PARK_AWARD_MOST_TIDY,
|
||||
PARK_AWARD_BEST_ROLLERCOASTERS,
|
||||
PARK_AWARD_BEST_VALUE,
|
||||
PARK_AWARD_MOST_BEAUTIFUL,
|
||||
PARK_AWARD_WORST_VALUE,
|
||||
PARK_AWARD_SAFEST,
|
||||
PARK_AWARD_BEST_STAFF,
|
||||
PARK_AWARD_BEST_FOOD,
|
||||
PARK_AWARD_WORST_FOOD,
|
||||
PARK_AWARD_BEST_RESTROOMS,
|
||||
PARK_AWARD_MOST_DISAPPOINTING,
|
||||
PARK_AWARD_BEST_WATER_RIDES,
|
||||
PARK_AWARD_BEST_CUSTOM_DESIGNED_RIDES,
|
||||
PARK_AWARD_MOST_DAZZLING_RIDE_COLOURS,
|
||||
PARK_AWARD_MOST_CONFUSING_LAYOUT,
|
||||
PARK_AWARD_BEST_GENTLE_RIDES,
|
||||
};
|
||||
|
||||
enum {
|
||||
ADVERTISING_CAMPAIGN_PARK_ENTRY_FREE,
|
||||
ADVERTISING_CAMPAIGN_RIDE_FREE,
|
||||
ADVERTISING_CAMPAIGN_PARK_ENTRY_HALF_PRICE,
|
||||
ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE,
|
||||
ADVERTISING_CAMPAIGN_PARK,
|
||||
ADVERTISING_CAMPAIGN_RIDE,
|
||||
ADVERTISING_CAMPAIGN_COUNT
|
||||
};
|
||||
|
||||
enum {
|
||||
PARK_FLAGS_PARK_OPEN = (1 << 0),
|
||||
PARK_FLAGS_FORBID_LANDSCAPE_CHANGES = (1 << 2),
|
||||
|
@ -80,7 +45,7 @@ enum {
|
|||
|
||||
int park_is_open();
|
||||
void park_init();
|
||||
void park_reset_awards_and_history();
|
||||
void park_reset_history();
|
||||
int park_calculate_size();
|
||||
|
||||
int calculate_park_rating();
|
||||
|
@ -89,6 +54,7 @@ money32 calculate_company_value();
|
|||
void reset_park_entrances();
|
||||
|
||||
void park_update();
|
||||
void park_update_histories();
|
||||
|
||||
uint8 calculate_guest_initial_happiness();
|
||||
|
||||
|
|
161
src/peep.c
161
src/peep.c
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include <windows.h>
|
||||
#include "addresses.h"
|
||||
#include "audio.h"
|
||||
#include "news_item.h"
|
||||
#include "peep.h"
|
||||
#include "rct2.h"
|
||||
|
@ -27,20 +28,16 @@
|
|||
#include "sprite.h"
|
||||
#include "window.h"
|
||||
|
||||
static void peep_update(rct_peep *peep);
|
||||
|
||||
int peep_get_staff_count()
|
||||
{
|
||||
uint16 sprite_index;
|
||||
uint16 spriteIndex;
|
||||
rct_peep *peep;
|
||||
int count = 0;
|
||||
|
||||
sprite_index = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16);
|
||||
while (sprite_index != SPRITE_INDEX_NULL) {
|
||||
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[sprite_index].peep);
|
||||
sprite_index = peep->next;
|
||||
|
||||
if (peep->type == PEEP_TYPE_STAFF)
|
||||
count++;
|
||||
}
|
||||
FOR_ALL_STAFF(spriteIndex, peep)
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -52,30 +49,107 @@ int peep_get_staff_count()
|
|||
void peep_update_all()
|
||||
{
|
||||
int i;
|
||||
uint16 sprite_index;
|
||||
uint16 spriteIndex;
|
||||
rct_peep* peep;
|
||||
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0E)
|
||||
return;
|
||||
|
||||
sprite_index = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16);
|
||||
spriteIndex = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16);
|
||||
i = 0;
|
||||
while (sprite_index != 0xFFFF) {
|
||||
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[sprite_index].peep);
|
||||
sprite_index = peep->next;
|
||||
while (spriteIndex != SPRITE_INDEX_NULL) {
|
||||
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[spriteIndex].peep);
|
||||
spriteIndex = peep->next;
|
||||
|
||||
if ((i & 0x7F) != (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 0x7F)) {
|
||||
RCT2_CALLPROC_X(0x0068FC1E, 0, 0, 0, 0, (int)peep, 0, 0);
|
||||
peep_update(peep);
|
||||
} else {
|
||||
RCT2_CALLPROC_X(0x0068F41A, 0, 0, 0, i, (int)peep, 0, 0);
|
||||
if (peep->var_08 == 4)
|
||||
RCT2_CALLPROC_X(0x0068FC1E, 0, 0, 0, 0, (int)peep, 0, 0);
|
||||
peep_update(peep);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0068FC1E
|
||||
*/
|
||||
static void peep_update(rct_peep *peep)
|
||||
{
|
||||
// RCT2_CALLPROC_X(0x0068FC1E, 0, 0, 0, 0, (int)peep, 0, 0); return;
|
||||
|
||||
int i, j;
|
||||
|
||||
if (peep->type == PEEP_TYPE_GUEST) {
|
||||
if (peep->var_AD != 255)
|
||||
if (++peep->var_AE < 720)
|
||||
peep->var_AD = 255;
|
||||
|
||||
// Update thoughts
|
||||
i = 0;
|
||||
int ebp = 0;
|
||||
int edi = -1;
|
||||
for (i = 0; i < PEEP_MAX_THOUGHTS; i++) {
|
||||
if (peep->thoughts[i].type == PEEP_THOUGHT_TYPE_NONE)
|
||||
break;
|
||||
|
||||
if (peep->thoughts[i].var_2 == 1) {
|
||||
ebp++;
|
||||
if (++peep->thoughts[i].var_3 >= 220) {
|
||||
peep->thoughts[i].var_3 = 0;
|
||||
peep->thoughts[i].var_2++;
|
||||
ebp--;
|
||||
}
|
||||
} else if (peep->thoughts[i].var_2 >= 0) {
|
||||
if (++peep->thoughts[i].var_3 > 255) {
|
||||
if (++peep->thoughts[i].var_3 >= 28) {
|
||||
peep->var_45 |= 1;
|
||||
|
||||
// Clear top thought, push others up
|
||||
for (j = i; j < PEEP_MAX_THOUGHTS - 1; j++)
|
||||
peep->thoughts[j].type = peep->thoughts[j + 1].type;
|
||||
peep->thoughts[PEEP_MAX_THOUGHTS - 1].type = PEEP_THOUGHT_TYPE_NONE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
edi = i;
|
||||
}
|
||||
}
|
||||
if (ebp == 0 && edi != -1) {
|
||||
peep->thoughts[edi].var_2 = 1;
|
||||
peep->var_45 |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Walking speed logic
|
||||
unsigned int stepsToTake = peep->energy;
|
||||
if (stepsToTake < 95 && peep->state == PEEP_STATE_QUEUING)
|
||||
stepsToTake = 95;
|
||||
if ((peep->flags & PEEP_FLAGS_SLOW_WALK) && peep->state != PEEP_STATE_QUEUING)
|
||||
stepsToTake /= 2;
|
||||
if (peep->var_71 == 255 && (RCT2_GLOBAL((int)peep + 0x29, uint8) & 4)) {
|
||||
stepsToTake /= 2;
|
||||
if (peep->state == PEEP_STATE_QUEUING)
|
||||
stepsToTake += stepsToTake / 2;
|
||||
}
|
||||
|
||||
unsigned int carryCheck = peep->var_73 + stepsToTake;
|
||||
peep->var_73 = carryCheck;
|
||||
if (carryCheck <= 255) {
|
||||
// loc_68FD3A
|
||||
RCT2_CALLPROC_X(0x0068FD3A, 0, 0, 0, 0, (int)peep, 0, 0);
|
||||
} else {
|
||||
// loc_68FD2F
|
||||
RCT2_CALLPROC_X(0x0068FD2F, 0, 0, 0, 0, (int)peep, 0, 0);
|
||||
switch (peep->state) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -85,7 +159,7 @@ void peep_problem_warnings_update()
|
|||
{
|
||||
rct_peep* peep;
|
||||
rct_ride* ride;
|
||||
uint16 sprite_idx;
|
||||
uint16 spriteIndex;
|
||||
uint16 guests_in_park = RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16);
|
||||
int hunger_counter = 0, lost_counter = 0, noexit_counter = 0, thirst_counter = 0,
|
||||
litter_counter = 0, disgust_counter = 0, bathroom_counter = 0 ,vandalism_counter = 0;
|
||||
|
@ -93,11 +167,8 @@ void peep_problem_warnings_update()
|
|||
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_RIDE_COUNT, sint16) = ride_get_count(); // refactor this to somewhere else
|
||||
|
||||
|
||||
for (sprite_idx = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16); sprite_idx != SPRITE_INDEX_NULL; sprite_idx = peep->next) {
|
||||
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[sprite_idx].peep);
|
||||
|
||||
if (peep->type != PEEP_TYPE_GUEST || peep->var_2A != 0 || peep->thoughts[0].pad_3 > 5)
|
||||
FOR_ALL_GUESTS(spriteIndex, peep) {
|
||||
if (peep->var_2A != 0 || peep->thoughts[0].var_2 > 5)
|
||||
continue;
|
||||
|
||||
switch (peep->thoughts[0].type) {
|
||||
|
@ -212,7 +283,7 @@ void peep_problem_warnings_update()
|
|||
void peep_update_crowd_noise()
|
||||
{
|
||||
rct_viewport *viewport;
|
||||
uint16 sprite_index;
|
||||
uint16 spriteIndex;
|
||||
rct_peep *peep;
|
||||
int visiblePeeps;
|
||||
|
||||
|
@ -234,15 +305,10 @@ void peep_update_crowd_noise()
|
|||
|
||||
// Count the number of peeps visible
|
||||
visiblePeeps = 0;
|
||||
sprite_index = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16);
|
||||
while (sprite_index != SPRITE_INDEX_NULL) {
|
||||
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[sprite_index].peep);
|
||||
sprite_index = peep->next;
|
||||
|
||||
FOR_ALL_GUESTS(spriteIndex, peep) {
|
||||
if (peep->var_16 == 0x8000)
|
||||
continue;
|
||||
if (peep->type != PEEP_TYPE_GUEST)
|
||||
continue;
|
||||
if (viewport->view_x > peep->var_1A)
|
||||
continue;
|
||||
if (viewport->view_x + viewport->view_width < peep->var_16)
|
||||
|
@ -293,6 +359,43 @@ void peep_update_crowd_noise()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0069BE9B
|
||||
*/
|
||||
void peep_applause()
|
||||
{
|
||||
uint16 spriteIndex;
|
||||
rct_peep* peep;
|
||||
|
||||
FOR_ALL_GUESTS(spriteIndex, peep) {
|
||||
if (peep->var_2A != 0)
|
||||
continue;
|
||||
|
||||
// Release balloon
|
||||
if (peep->item_standard_flags & PEEP_ITEM_BALLOON) {
|
||||
peep->item_standard_flags &= ~PEEP_ITEM_BALLOON;
|
||||
if (peep->x != 0x8000) {
|
||||
create_balloon(peep->x, peep->y, peep->z + 9, peep->balloon_colour);
|
||||
peep->var_45 |= 8;
|
||||
RCT2_CALLPROC_X(0x0069B8CC, 0, 0, 0, 0, (int)peep, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Clap
|
||||
if ((peep->state == PEEP_STATE_WALKING || peep->state == PEEP_STATE_QUEUING) && peep->var_71 >= 254) {
|
||||
peep->var_71 = 26;
|
||||
peep->var_72 = 0;
|
||||
peep->var_70 = 0;
|
||||
RCT2_CALLPROC_X(0x00693B58, 0, 0, 0, 0, (int)peep, 0, 0);
|
||||
RCT2_CALLPROC_X(0x006EC473, 0, 0, 0, 0, (int)peep, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Play applause noise
|
||||
sound_play_panned(SOUND_APPLAUSE, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) / 2);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0069A05D
|
||||
|
|
37
src/peep.h
37
src/peep.h
|
@ -307,8 +307,8 @@ enum PEEP_ITEM {
|
|||
typedef struct {
|
||||
uint8 type;
|
||||
uint8 item;
|
||||
uint8 pad_3;
|
||||
uint8 pad_4;
|
||||
uint8 var_2;
|
||||
uint8 var_3;
|
||||
} rct_peep_thought;
|
||||
|
||||
typedef struct {
|
||||
|
@ -359,7 +359,7 @@ typedef struct {
|
|||
uint8 pad_41[0x2];
|
||||
uint8 intensity; // 0x43
|
||||
uint8 nausea_tolerance; // 0x44
|
||||
uint8 pad_45;
|
||||
uint8 var_45;
|
||||
money16 paid_on_drink; // 0x46
|
||||
uint8 pad_48[0x10];
|
||||
uint32 item_extra_flags; // 0x58
|
||||
|
@ -372,8 +372,14 @@ typedef struct {
|
|||
uint8 current_train; // 0x6A
|
||||
uint8 current_car; // 0x6B
|
||||
uint8 current_seat; // 0x6C
|
||||
uint8 pad_6D[0x09];
|
||||
uint8 pad_6D[3];
|
||||
uint8 var_70;
|
||||
uint8 var_71;
|
||||
uint8 var_72;
|
||||
uint8 var_73;
|
||||
uint16 pad_74;
|
||||
uint8 var_76;
|
||||
uint8 pad_77;
|
||||
uint8 var_78;
|
||||
uint8 pad_79[0x03];
|
||||
uint8 rides_been_on[32]; // 0x7C
|
||||
|
@ -382,7 +388,8 @@ typedef struct {
|
|||
money32 cash_spent; // 0xA4
|
||||
uint8 pad_A8;
|
||||
sint32 time_in_park; // 0xA9
|
||||
uint8 pad_AD[0x3];
|
||||
uint8 var_AD;
|
||||
uint16 var_AE;
|
||||
rct_peep_thought thoughts[PEEP_MAX_THOUGHTS]; // 0xB0
|
||||
uint8 pad_C4;
|
||||
uint8 var_C5;
|
||||
|
@ -412,10 +419,30 @@ typedef struct {
|
|||
uint32 item_standard_flags; // 0xFC
|
||||
} rct_peep;
|
||||
|
||||
/** Helper macro until rides are stored in this module. */
|
||||
#define GET_PEEP(sprite_index) &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[sprite_index].peep)
|
||||
|
||||
/**
|
||||
* Helper macro loop for enumerating through all the non null rides. To avoid needing a end loop counterpart, statements are
|
||||
* applied in tautology if statements.
|
||||
*/
|
||||
#define FOR_ALL_PEEPS(sprite_index, peep) \
|
||||
for (sprite_index = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16); sprite_index != SPRITE_INDEX_NULL; sprite_index = peep->next) \
|
||||
if ((peep = GET_PEEP(sprite_index)) || 1)
|
||||
|
||||
#define FOR_ALL_GUESTS(sprite_index, peep) \
|
||||
FOR_ALL_PEEPS(sprite_index, peep) \
|
||||
if (peep->type == PEEP_TYPE_GUEST)
|
||||
|
||||
#define FOR_ALL_STAFF(sprite_index, peep) \
|
||||
FOR_ALL_PEEPS(sprite_index, peep) \
|
||||
if (peep->type == PEEP_TYPE_STAFF)
|
||||
|
||||
int peep_get_staff_count();
|
||||
void peep_update_all();
|
||||
void peep_problem_warnings_update();
|
||||
void peep_update_crowd_noise();
|
||||
void peep_applause();
|
||||
rct_peep *peep_generate(int x, int y, int z);
|
||||
|
||||
#endif
|
||||
|
|
11
src/rct2.c
11
src/rct2.c
|
@ -157,7 +157,9 @@ void rct2_init()
|
|||
scenario_load_list();
|
||||
track_load_list(253);
|
||||
gfx_load_g1();
|
||||
RCT2_CALLPROC_EBPSAFE(0x006C19AC);
|
||||
//RCT2_CALLPROC_EBPSAFE(0x006C19AC); //Load character widths
|
||||
gfx_load_character_widths();
|
||||
|
||||
osinterface_init();
|
||||
RCT2_CALLPROC_EBPSAFE(0x006BA8E0); // init_audio();
|
||||
viewport_init_all();
|
||||
|
@ -165,10 +167,10 @@ void rct2_init()
|
|||
get_local_time();
|
||||
reset_park_entrances();
|
||||
reset_saved_strings();
|
||||
RCT2_CALLPROC_EBPSAFE(0x0069EB13);
|
||||
RCT2_CALLPROC_EBPSAFE(0x0069EB13); //Sprite list reset/load
|
||||
ride_init_all();
|
||||
window_guest_list_init_vars_a();
|
||||
RCT2_CALLPROC_EBPSAFE(0x006BD3A4);
|
||||
RCT2_CALLPROC_EBPSAFE(0x006BD3A4); //Peep?
|
||||
map_init();
|
||||
park_init();
|
||||
RCT2_CALLPROC_EBPSAFE(0x0066B5C0); // 0x0066B5C0 (part of 0x0066B3E8) screen_game_create_windows()
|
||||
|
@ -189,8 +191,7 @@ void rct2_init()
|
|||
void rct2_init_directories()
|
||||
{
|
||||
// check install directory
|
||||
DWORD dwAttrib = GetFileAttributes(gGeneral_config.game_path);
|
||||
if (dwAttrib == INVALID_FILE_ATTRIBUTES || !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
if ( !osinterface_directory_exists(gGeneral_config.game_path) ) {
|
||||
osinterface_show_messagebox("Invalid RCT2 installation path. Please correct in config.ini.");
|
||||
exit(-1);
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ typedef unsigned long long uint64;
|
|||
#define OPENRCT2_PLATFORM "Windows"
|
||||
#define OPENRCT2_TIMESTAMP __DATE__ " " __TIME__
|
||||
|
||||
// Represent fixed point numbers
|
||||
// Represent fixed point numbers. dp = decimal point
|
||||
typedef sint16 fixed16_1dp;
|
||||
typedef sint16 fixed16_2dp;
|
||||
typedef sint32 fixed32_1dp;
|
||||
|
@ -74,7 +74,8 @@ typedef sint32 fixed32_2dp;
|
|||
typedef fixed16_1dp money16;
|
||||
typedef fixed32_1dp money32;
|
||||
|
||||
// Construct a fixed point number.
|
||||
// Construct a fixed point number. For example, to create the value 3.65 you
|
||||
// would write FIXED_2DP(3,65)
|
||||
#define FIXED_XDP(x, whole, fraction) ((whole) * (10 * x) + (fraction))
|
||||
#define FIXED_1DP(whole, fraction) FIXED_XDP(1, whole, fraction)
|
||||
#define FIXED_2DP(whole, fraction) FIXED_XDP(2, whole, fraction)
|
||||
|
|
186
src/ride.c
186
src/ride.c
|
@ -20,14 +20,14 @@
|
|||
|
||||
#include <windows.h>
|
||||
#include "addresses.h"
|
||||
#include "map.h"
|
||||
#include "news_item.h"
|
||||
#include "sprite.h"
|
||||
#include "ride.h"
|
||||
#include "sprite.h"
|
||||
#include "peep.h"
|
||||
#include "window.h"
|
||||
|
||||
#define GET_RIDE(x) (&(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[x]))
|
||||
#define GET_RIDE_MEASUREMENT(x) (&(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_MEASUREMENTS, rct_ride_measurement)[x]))
|
||||
|
||||
#pragma region Ride classification table
|
||||
|
||||
const uint8 gRideClassifications[255] = {
|
||||
|
@ -104,11 +104,8 @@ int ride_get_count()
|
|||
rct_ride *ride;
|
||||
int i, count = 0;
|
||||
|
||||
for (i = 0; i < MAX_RIDES; i++) {
|
||||
ride = GET_RIDE(i);
|
||||
if (ride->type != RIDE_TYPE_NULL)
|
||||
count++;
|
||||
}
|
||||
FOR_ALL_RIDES(i, ride)
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -162,13 +159,10 @@ void ride_init_all()
|
|||
void reset_all_ride_build_dates() {
|
||||
int i;
|
||||
rct_ride *ride;
|
||||
for (i = 0; i < MAX_RIDES; i++) {
|
||||
ride = GET_RIDE(i);
|
||||
if (ride->type != RIDE_TYPE_NULL) {
|
||||
//mov ax, current_month_year
|
||||
//sub [esi + 180h], ax
|
||||
ride->build_date -= RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16);
|
||||
}
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
//mov ax, current_month_year
|
||||
//sub [esi + 180h], ax
|
||||
ride->build_date -= RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,17 +171,15 @@ void reset_all_ride_build_dates() {
|
|||
*/
|
||||
void ride_update_favourited_stat()
|
||||
{
|
||||
int i;
|
||||
rct_ride *ride;
|
||||
uint16 spriteIndex;
|
||||
rct_peep* peep;
|
||||
|
||||
for (int i = 0; i < MAX_RIDES; i++) {
|
||||
ride = GET_RIDE(i);
|
||||
if (ride->type != RIDE_TYPE_NULL)
|
||||
ride->guests_favourite = 0;
|
||||
FOR_ALL_RIDES(i, ride)
|
||||
ride->guests_favourite = 0;
|
||||
|
||||
}
|
||||
for (int sprite_idx = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16); sprite_idx != SPRITE_INDEX_NULL; sprite_idx = peep->next) {
|
||||
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[sprite_idx].peep);
|
||||
FOR_ALL_PEEPS(spriteIndex, peep) {
|
||||
if (peep->var_08 != 4)
|
||||
return;
|
||||
if (peep->favourite_ride != 0xff) {
|
||||
|
@ -198,6 +190,156 @@ void ride_update_favourited_stat()
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
window_invalidate_by_id(WC_RIDE_LIST, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* rct2: 0x006B7C59
|
||||
* @return 1 if the coordinate is reachable or has no entrance, 0 otherwise
|
||||
*/
|
||||
int ride_entrance_exit_is_reachable(uint16 coordinate, rct_ride* ride, int index) {
|
||||
int x = ((coordinate >> 8) & 0xFF) << 5, // cx
|
||||
y = (coordinate & 0xFF) << 5; // ax
|
||||
uint8 station_height = ride->station_heights[index];
|
||||
int tile_idx = ((x << 8) | y) >> 5;
|
||||
rct_map_element* tile = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx];
|
||||
|
||||
while(1) {
|
||||
uint8 element_type = tile->type & MAP_ELEMENT_TYPE_MASK;
|
||||
if (element_type == MAP_ELEMENT_TYPE_ENTRANCE && station_height == tile->base_height) {
|
||||
break;
|
||||
} else if (tile->flags & MAP_ELEMENT_FLAG_LAST_TILE) {
|
||||
return 1;
|
||||
}
|
||||
tile++;
|
||||
}
|
||||
|
||||
uint8 face_direction = tile->type & 3;
|
||||
y -= RCT2_ADDRESS(0x00993CCC, sint16)[face_direction * 2];
|
||||
x -= RCT2_ADDRESS(0x00993CCE, sint16)[face_direction * 2];
|
||||
tile_idx = ((x << 8) | y) >> 5;
|
||||
|
||||
return map_coord_is_connected(tile_idx, station_height, face_direction);
|
||||
}
|
||||
|
||||
|
||||
void ride_entrance_exit_connected(rct_ride* ride, int ride_idx)
|
||||
{
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
uint16 station_start = ride->station_starts[i],
|
||||
entrance = ride->entrances[i],
|
||||
exit = ride->exits[i];
|
||||
|
||||
if (station_start == -1 )
|
||||
continue;
|
||||
if (entrance != -1 && !ride_entrance_exit_is_reachable(entrance, ride, i)) {
|
||||
// name of ride is parameter of the format string
|
||||
RCT2_GLOBAL(0x013CE952, uint16) = ride->var_04A;
|
||||
RCT2_GLOBAL(0x013CE954, uint32) = ride->var_04C;
|
||||
news_item_add_to_queue(1, STR_ENTRANCE_NOT_CONNECTED, ride_idx);
|
||||
ride->connected_message_throttle = 3;
|
||||
}
|
||||
|
||||
if (exit != -1 && !ride_entrance_exit_is_reachable(exit, ride, i)) {
|
||||
// name of ride is parameter of the format string
|
||||
RCT2_GLOBAL(0x013CE952, uint16) = ride->var_04A;
|
||||
RCT2_GLOBAL(0x013CE954, uint32) = ride->var_04C;
|
||||
news_item_add_to_queue(1, STR_EXIT_NOT_CONNECTED, ride_idx);
|
||||
ride->connected_message_throttle = 3;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ride_shop_connected(rct_ride* ride, int ride_idx)
|
||||
{
|
||||
uint16 coordinate = ride->station_starts[0];
|
||||
if (coordinate == 0xFFFF)
|
||||
return;
|
||||
|
||||
int x = ((coordinate >> 8) & 0xFF) << 5, // cx
|
||||
y = (coordinate & 0xFF) << 5; // ax
|
||||
uint16 entrance_directions = 0;
|
||||
int tile_idx = ((x << 8) | y) >> 5, count = 0;
|
||||
rct_map_element* tile = RCT2_ADDRESS(RCT2_ADDRESS_TILE_MAP_ELEMENT_POINTERS, rct_map_element*)[tile_idx];
|
||||
|
||||
|
||||
while (1) {
|
||||
uint8 element_type = tile->type & MAP_ELEMENT_TYPE_MASK;
|
||||
if(element_type == MAP_ELEMENT_TYPE_TRACK && tile->properties.track.ride_index == ride_idx)
|
||||
break;
|
||||
|
||||
if(tile->flags & MAP_ELEMENT_FLAG_LAST_TILE)
|
||||
return;
|
||||
tile++;
|
||||
}
|
||||
|
||||
uint8 track_type = tile->properties.track.type;
|
||||
ride = GET_RIDE(tile->properties.track.ride_index);
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x80000) {
|
||||
entrance_directions = RCT2_ADDRESS(0x0099CA64, uint8)[track_type * 16];
|
||||
} else {
|
||||
entrance_directions = RCT2_ADDRESS(0x0099BA64, uint8)[track_type * 16];
|
||||
}
|
||||
|
||||
|
||||
uint8 tile_direction = tile->type & MAP_ELEMENT_DIRECTION_MASK;
|
||||
entrance_directions <<= tile_direction;
|
||||
entrance_directions = ((entrance_directions >> 12) | entrance_directions) & 0xF;
|
||||
|
||||
// now each bit in entrance_directions stands for an entrance direction to check
|
||||
if (entrance_directions == 0)
|
||||
return;
|
||||
|
||||
for (int count = 0; entrance_directions != 0; ++count) {
|
||||
if (!(entrance_directions & 1)) {
|
||||
entrance_directions >>= 1;
|
||||
continue;
|
||||
}
|
||||
entrance_directions >>= 1;
|
||||
|
||||
uint8 face_direction = count ^ 2; // flip direction north<->south, east<->west
|
||||
y -= RCT2_ADDRESS(0x00993CCC, sint16)[face_direction * 2];
|
||||
x -= RCT2_ADDRESS(0x00993CCE, sint16)[face_direction * 2];
|
||||
tile_idx = ((x << 8) | y) >> 5;
|
||||
|
||||
if (map_coord_is_connected(tile_idx, tile->base_height, face_direction))
|
||||
return;
|
||||
}
|
||||
|
||||
// name of ride is parameter of the format string
|
||||
RCT2_GLOBAL(0x013CE952, uint16) = ride->var_04A;
|
||||
RCT2_GLOBAL(0x013CE954, uint32) = ride->var_04C;
|
||||
news_item_add_to_queue(1, STR_ENTRANCE_NOT_CONNECTED, ride_idx);
|
||||
|
||||
ride->connected_message_throttle = 3;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* rct2: 0x006B7A5E
|
||||
**/
|
||||
void ride_check_all_reachable()
|
||||
{
|
||||
rct_ride *ride;
|
||||
int i;
|
||||
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
if (ride->connected_message_throttle != 0)
|
||||
ride->connected_message_throttle--;
|
||||
if (ride->status != RIDE_STATUS_OPEN || ride->connected_message_throttle != 0)
|
||||
continue;
|
||||
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + ride->type * 8, uint32) & 0x20000)
|
||||
ride_shop_connected(ride, i);
|
||||
else
|
||||
ride_entrance_exit_connected(ride, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
54
src/ride.h
54
src/ride.h
|
@ -23,6 +23,19 @@
|
|||
|
||||
#include "rct2.h"
|
||||
|
||||
typedef fixed16_2dp ride_rating;
|
||||
|
||||
// Convenience function for writing ride ratings. The result is a 16 bit signed
|
||||
// integer. To create the ride rating 3.65 type RIDE_RATING(3,65)
|
||||
#define RIDE_RATING(whole, fraction) FIXED_2DP(whole, fraction)
|
||||
|
||||
// Used for return values, for functions that modify all three.
|
||||
typedef struct {
|
||||
ride_rating excitement;
|
||||
ride_rating intensity;
|
||||
ride_rating nausea;
|
||||
} rating_tuple;
|
||||
|
||||
/**
|
||||
* Ride structure.
|
||||
* size: 0x0260
|
||||
|
@ -43,7 +56,8 @@ typedef struct {
|
|||
uint32 var_04C;
|
||||
uint16 overall_view; // 0x050
|
||||
uint16 station_starts[4]; // 0x052
|
||||
uint8 pad_05A[0x10];
|
||||
uint8 station_heights[4]; // 0x05A
|
||||
uint8 pad_05E[0xC];
|
||||
uint16 entrances[4]; // 0x06A
|
||||
uint16 exits[4]; // 0x072
|
||||
uint8 pad_07A[0x0C];
|
||||
|
@ -55,7 +69,7 @@ typedef struct {
|
|||
uint8 var_0C8;
|
||||
uint8 var_0C9;
|
||||
|
||||
uint8 pad_0CA[0x1B];
|
||||
uint8 pad_0CA[0x1A];
|
||||
|
||||
sint32 var_0E4;
|
||||
sint32 var_0E8;
|
||||
|
@ -65,7 +79,7 @@ typedef struct {
|
|||
uint8 var_114;
|
||||
// Track length? Number of track segments?
|
||||
uint8 var_115;
|
||||
uint8 pad_116[0x0F];
|
||||
uint8 pad_116[0x0E];
|
||||
sint16 var_124;
|
||||
sint16 var_126;
|
||||
sint16 var_128;
|
||||
|
@ -96,13 +110,17 @@ typedef struct {
|
|||
// used in computing excitement, nausea, etc
|
||||
uint8 var_198;
|
||||
uint8 var_199;
|
||||
uint8 pad_19A[0x1A];
|
||||
money32 profit; // 0x1B4
|
||||
uint8 pad_19A[0x14];
|
||||
uint8 var_1AE;
|
||||
uint8 connected_message_throttle;
|
||||
uint32 pad_1B0;
|
||||
sint32 profit; // 0x1B4
|
||||
uint8 queue_time[4]; // 0x1B8
|
||||
uint8 pad_1BC[0x11];
|
||||
uint8 var_1BC;
|
||||
uint8 pad_1BD[0x10];
|
||||
uint8 var_1CD;
|
||||
uint16 guests_favourite; // 0x1CE
|
||||
uint32 lifecycle_flags;
|
||||
uint32 lifecycle_flags; // 0x1D0
|
||||
uint8 pad_1D4[0x20];
|
||||
// Example value for wild mouse ride is d5 (before it's been constructed)
|
||||
// I tried searching the IDA file for "1F4" but couldn't find places where
|
||||
|
@ -295,8 +313,29 @@ enum {
|
|||
RIDE_COLOUR_SCHEME_DIFFERENT_PER_CAR
|
||||
};
|
||||
|
||||
enum {
|
||||
RIDE_GROUP_TRANSPORT,
|
||||
RIDE_GROUP_GENTLE,
|
||||
RIDE_GROUP_ROLLERCOASTER,
|
||||
RIDE_GROUP_THRILL,
|
||||
RIDE_GROUP_WATER,
|
||||
RIDE_GROUP_SHOP
|
||||
};
|
||||
|
||||
#define MAX_RIDES 255
|
||||
#define MAX_RIDE_MEASUREMENTS 8
|
||||
#define RIDE_RELIABILITY_UNDEFINED 0xFFFF
|
||||
|
||||
/** Helper macros until rides are stored in this module. */
|
||||
#define GET_RIDE(x) (&(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[x]))
|
||||
#define GET_RIDE_MEASUREMENT(x) (&(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_MEASUREMENTS, rct_ride_measurement)[x]))
|
||||
|
||||
/**
|
||||
* Helper macro loop for enumerating through all the non null rides.
|
||||
*/
|
||||
#define FOR_ALL_RIDES(i, ride) \
|
||||
for (i = 0; i < MAX_RIDES; i++) \
|
||||
if ((ride = GET_RIDE(i))->type != RIDE_TYPE_NULL)
|
||||
|
||||
extern const uint8 gRideClassifications[255];
|
||||
|
||||
|
@ -306,5 +345,6 @@ int ride_get_max_queue_time(rct_ride *ride);
|
|||
void ride_init_all();
|
||||
void reset_all_ride_build_dates();
|
||||
void ride_update_favourited_stat();
|
||||
void ride_check_all_reachable();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -22,17 +22,7 @@
|
|||
#define _RIDE_RATINGS_H_
|
||||
|
||||
#include "rct2.h"
|
||||
|
||||
typedef fixed16_2dp ride_rating;
|
||||
|
||||
#define RIDE_RATING(whole, fraction) FIXED_2DP(whole, fraction)
|
||||
|
||||
// Used for return values, for functions that modify all three.
|
||||
typedef struct {
|
||||
ride_rating excitement;
|
||||
ride_rating intensity;
|
||||
ride_rating nausea;
|
||||
} rating_tuple;
|
||||
#include "ride.h"
|
||||
|
||||
void crooked_house_excitement(rct_ride *ride);
|
||||
void sub_655FD6(rct_ride *ride);
|
||||
|
|
|
@ -21,10 +21,12 @@
|
|||
#include <windows.h>
|
||||
#include <string.h>
|
||||
#include "addresses.h"
|
||||
#include "award.h"
|
||||
#include "date.h"
|
||||
#include "finance.h"
|
||||
#include "game.h"
|
||||
#include "map.h"
|
||||
#include "marketing.h"
|
||||
#include "news_item.h"
|
||||
#include "object.h"
|
||||
#include "park.h"
|
||||
|
@ -58,14 +60,12 @@ int scenario_load_basic(const char *path)
|
|||
|
||||
// Checks for a scenario string object (possibly for localisation)
|
||||
if ((s6Info->entry.flags & 0xFF) != 255) {
|
||||
if (sub_6A9428(&s6Info->entry)) {
|
||||
if (object_get_scenario_text(&s6Info->entry)) {
|
||||
int ebp = RCT2_GLOBAL(0x009ADAF8, uint32);
|
||||
format_string(s6Info->name, RCT2_GLOBAL(ebp, sint16), NULL);
|
||||
format_string(s6Info->details, RCT2_GLOBAL(ebp + 4, sint16), NULL);
|
||||
RCT2_GLOBAL(0x009AA00C, uint8) = RCT2_GLOBAL(ebp + 6, uint8);
|
||||
|
||||
// Disposes the scenario string object (0x009ADAF8)
|
||||
RCT2_CALLPROC_EBPSAFE(0x006A982D);
|
||||
object_free_scenario_text();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
@ -279,7 +279,9 @@ void scenario_load_and_play(const rct_scenario_basic *scenario)
|
|||
RCT2_GLOBAL(RCT2_ADDRESS_INCOME_FROM_ADMISSIONS, uint32) = 0;
|
||||
RCT2_GLOBAL(0x013587D8, uint16) = 63;
|
||||
sub_69E869(); // (loan related, called above already)
|
||||
park_reset_awards_and_history();
|
||||
park_reset_history();
|
||||
finance_reset_history();
|
||||
award_reset();
|
||||
reset_all_ride_build_dates();
|
||||
date_reset();
|
||||
RCT2_CALLPROC_EBPSAFE(0x00674576);
|
||||
|
@ -336,7 +338,7 @@ void scenario_success()
|
|||
uint32 current_val = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_COMPANY_VALUE, uint32);
|
||||
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_COMPLETED_COMPANY_VALUE, uint32) = current_val;
|
||||
RCT2_CALLPROC_EBPSAFE(0x0069BE9B); // celebration
|
||||
peep_applause();
|
||||
|
||||
for (i = 0; i < gScenarioListCount; i++) {
|
||||
char *cur_scenario_name = RCT2_ADDRESS(0x135936C, char);
|
||||
|
@ -365,20 +367,15 @@ void scenario_success()
|
|||
**/
|
||||
void scenario_objective5_check()
|
||||
{
|
||||
int rcs = 0;
|
||||
int i, rcs = 0;
|
||||
uint8 type_already_counted[256];
|
||||
rct_ride* ride;
|
||||
|
||||
memset(type_already_counted, 0, 256);
|
||||
|
||||
for (int i = 0; i < MAX_RIDES; i++) {
|
||||
uint8 subtype_id;
|
||||
uint32 subtype_p;
|
||||
ride = &(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[i]);
|
||||
if (ride->type == RIDE_TYPE_NULL)
|
||||
continue;
|
||||
subtype_id = (uint8)ride->subtype;
|
||||
subtype_p = RCT2_GLOBAL(0x009ACFA4 + subtype_id * 4, uint32);
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
uint8 subtype_id = ride->subtype;
|
||||
uint32 subtype_p = RCT2_GLOBAL(0x009ACFA4 + subtype_id * 4, uint32);
|
||||
|
||||
if ((RCT2_GLOBAL(subtype_p + 0x1BE, sint8) == 2 ||
|
||||
RCT2_GLOBAL(subtype_p + 0x1BF, sint8) == 2) &&
|
||||
|
@ -400,21 +397,16 @@ void scenario_objective5_check()
|
|||
**/
|
||||
void scenario_objective8_check()
|
||||
{
|
||||
int rcs = 0;
|
||||
int i, rcs = 0;
|
||||
uint8 type_already_counted[256];
|
||||
rct_ride* ride;
|
||||
sint16 objective_length = RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_NUM_GUESTS, uint16);
|
||||
|
||||
memset(type_already_counted, 0, 256);
|
||||
|
||||
for (int i = 0; i < MAX_RIDES; i++) {
|
||||
uint8 subtype_id;
|
||||
uint32 subtype_p;
|
||||
ride = &(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[i]);
|
||||
if (ride->type == RIDE_TYPE_NULL)
|
||||
continue;
|
||||
subtype_id = (uint8)ride->subtype;
|
||||
subtype_p = RCT2_GLOBAL(0x009ACFA4 + subtype_id * 4, uint32);
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
uint8 subtype_id = ride->subtype;
|
||||
uint32 subtype_p = RCT2_GLOBAL(0x009ACFA4 + subtype_id * 4, uint32);
|
||||
|
||||
if ((RCT2_GLOBAL(subtype_p + 0x1BE, sint8) == 2 ||
|
||||
RCT2_GLOBAL(subtype_p + 0x1BF, sint8) == 2) &&
|
||||
|
@ -545,9 +537,9 @@ void scenario_objectives_check()
|
|||
void scenario_entrance_fee_too_high_check()
|
||||
{
|
||||
uint16 x, y;
|
||||
uint16 magic = RCT2_GLOBAL(0x013580EE, uint16),
|
||||
park_entrance_fee = RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, uint16);
|
||||
int max_fee = magic + (magic / 2);
|
||||
uint16 totalRideValue = RCT2_GLOBAL(RCT2_TOTAL_RIDE_VALUE, uint16);
|
||||
uint16 park_entrance_fee = RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, uint16);
|
||||
int max_fee = totalRideValue + (totalRideValue / 2);
|
||||
uint32 game_flags = RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32), packed_xy;
|
||||
|
||||
if ((game_flags & PARK_FLAGS_PARK_OPEN) && park_entrance_fee > max_fee) {
|
||||
|
@ -561,49 +553,6 @@ void scenario_entrance_fee_too_high_check()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Update status of marketing campaigns and send a message when they are done.
|
||||
* rct2: 0x0069E0C1
|
||||
**/
|
||||
void scenario_marketing_update()
|
||||
{
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
uint8 campaign_weeks_left = RCT2_ADDRESS(0x01358102, uint8)[i];
|
||||
int campaign_item = 0;
|
||||
|
||||
if (!campaign_weeks_left)
|
||||
continue;
|
||||
window_invalidate_by_id(WC_FINANCES, 0);
|
||||
|
||||
// high bit marks the campaign as inactive, on first check the campaign is set actice
|
||||
// this makes campaigns run a full x weeks even when started in the middle of a week
|
||||
RCT2_ADDRESS(0x01358102, uint8)[i] &= ~(1 << 7);
|
||||
if (campaign_weeks_left & (1 << 7))
|
||||
continue;
|
||||
|
||||
RCT2_ADDRESS(0x01358102, uint8)[i]--;
|
||||
if (campaign_weeks_left - 1 != 0)
|
||||
continue;
|
||||
|
||||
campaign_item = RCT2_ADDRESS(0x01358116, uint8)[i];
|
||||
|
||||
// this sets the string parameters for the marketing types that have an argument.
|
||||
if (i == 1 || i == 5) { // free RIDES oh yea
|
||||
RCT2_GLOBAL(0x013CE952, uint16) = RCT2_GLOBAL(0x01362942 + 304 * campaign_item, uint16);;
|
||||
RCT2_GLOBAL(0x013CE954, uint32) = RCT2_GLOBAL(0x01362944 + 152 * campaign_item, uint32);
|
||||
} else if (i == 3) { // free food/merch
|
||||
campaign_item += 2016;
|
||||
if (campaign_item >= 2048)
|
||||
campaign_item += 96;
|
||||
RCT2_GLOBAL(0x013CE952, uint16) = campaign_item;
|
||||
}
|
||||
|
||||
news_item_add_to_queue(NEWS_ITEM_MONEY, STR_MARKETING_FINISHED_BASE + i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Scenario and finance related update iteration.
|
||||
* rct2: 0x006C44B1
|
||||
|
@ -630,6 +579,8 @@ void scenario_update()
|
|||
objective_type == 6 || objective_type == 5) {
|
||||
scenario_objectives_check();
|
||||
}
|
||||
|
||||
window_invalidate_by_id(WC_BOTTOM_TOOLBAR, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -639,9 +590,9 @@ void scenario_update()
|
|||
finance_pay_wages();
|
||||
finance_pay_research();
|
||||
finance_pay_interest();
|
||||
scenario_marketing_update();
|
||||
marketing_update();
|
||||
peep_problem_warnings_update();
|
||||
RCT2_CALLPROC_EBPSAFE(0x006B7A5E); // check ride reachability
|
||||
ride_check_all_reachable();
|
||||
ride_update_favourited_stat();
|
||||
|
||||
if (month <= 1 && RCT2_GLOBAL(0x009ADAE0, sint32) != -1 && RCT2_GLOBAL(0x009ADAE0 + 14, uint16) & 1) {
|
||||
|
@ -660,7 +611,7 @@ void scenario_update()
|
|||
break;
|
||||
}
|
||||
}
|
||||
RCT2_CALLPROC_EBPSAFE(0x0066A231); // update histories (finance, ratings, etc)
|
||||
park_update_histories();
|
||||
park_calculate_size();
|
||||
}
|
||||
|
||||
|
@ -678,7 +629,7 @@ void scenario_update()
|
|||
RCT2_CALLPROC_EBPSAFE(0x0069DEAD);
|
||||
scenario_objectives_check();
|
||||
scenario_entrance_fee_too_high_check();
|
||||
RCT2_CALLPROC_EBPSAFE(0x0066A86C); // award checks
|
||||
award_update_all();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
277
src/scenario.h
277
src/scenario.h
|
@ -83,6 +83,283 @@ typedef struct {
|
|||
char completed_by[64]; // 0x0270
|
||||
} rct_scenario_basic;
|
||||
|
||||
/* This will be useful for backwards compatibility
|
||||
typedef struct {
|
||||
// SC6[0]
|
||||
rct_s6_header header;
|
||||
|
||||
// SC6[1]
|
||||
rct_s6_info info;
|
||||
|
||||
// SC6[2]
|
||||
// packed objects
|
||||
|
||||
// SC6[3]
|
||||
rct_object_entry objects[721];
|
||||
|
||||
// SC6[4]
|
||||
uint16 elapsed_months;
|
||||
uint16 current_day;
|
||||
uint32 dword_F663AC;
|
||||
uint32 scenario_srand_0;
|
||||
uint32 scenario_srand_1;
|
||||
|
||||
// SC6[5]
|
||||
rct_map_element map_elements[0x30000];
|
||||
|
||||
// SC6[6]
|
||||
uint32 dword_010E63B8;
|
||||
rct_sprite sprites[10000];
|
||||
uint16 sprites_next_index;
|
||||
uint16 sprites_start_vehicle;
|
||||
uint16 sprites_start_peep;
|
||||
uint16 sprites_start_textfx;
|
||||
uint16 sprites_start_litter;
|
||||
uint8 pad_013573C6[2];
|
||||
uint16 word_013573C8;
|
||||
uint8 pad_013573CA[4];
|
||||
uint16 word_013573CE;
|
||||
uint16 word_013573D0;
|
||||
uint8 pad_013573D2[2];
|
||||
uint16 word_013573D4;
|
||||
uint8 pad_013573D6[4];
|
||||
uint32 dword_013573D8;
|
||||
uint32 dword_013573DC;
|
||||
money32 current_loan;
|
||||
uint32 park_flags;
|
||||
money16 park_entrance_fee;
|
||||
uint16 word_013573EA;
|
||||
uint16 word_013573EC;
|
||||
uint8 pad_013573EE[16];
|
||||
uint8 byte_013573F0;
|
||||
uint8 pad_013573F1[2];
|
||||
rct2_peep_spawn peep_spawns[2];
|
||||
uint8 guest_count_change_modifier;
|
||||
uint8 byte_013573FF;
|
||||
uint8 pad_01357400[4];
|
||||
uint32 dword_01357404;
|
||||
uint32 dword_01357408;
|
||||
uint32 dword_0135740C;
|
||||
uint32 dword_01357410[5];
|
||||
uint32 dword_01357424[8];
|
||||
uint32 dword_01357444[128];
|
||||
uint32 dword_01357644[128];
|
||||
|
||||
// SC6[7]
|
||||
uint16 guests_in_park;
|
||||
uint16 guests_heading_for_park;
|
||||
|
||||
// Ignored in scenario
|
||||
money32 expenditure_table[14];
|
||||
uint32 dword_01357880[5];
|
||||
uint32 dword_01357894;
|
||||
uint32 dword_01357898;
|
||||
uint32 dword_0135789C;
|
||||
uint32 dword_013578A0;
|
||||
uint32 dword_013578A4[201];
|
||||
|
||||
// SC6[8]
|
||||
uint16 last_guests_in_park;
|
||||
uint8 pad_01357BCA[3];
|
||||
uint8 handyman_colour;
|
||||
uint8 mechanic_colour;
|
||||
uint8 security_colour;
|
||||
|
||||
// Ignored in scenario
|
||||
uint32 dword_01357BD0[56];
|
||||
|
||||
// SC6[9]
|
||||
uint16 park_rating;
|
||||
|
||||
// Ignored in scenario
|
||||
uint8 park_rating_history[32];
|
||||
uint8 guests_in_park_history[32];
|
||||
|
||||
// SC6[10]
|
||||
uint16 word_01357CF2;
|
||||
uint32 word_01357CF4;
|
||||
uint8 byte_01357CF8[1000];
|
||||
uint32 dword_013580E0[32];
|
||||
uint16 word_013580E4[16];
|
||||
uint8 byte_013580E6;
|
||||
uint8 byte_013580E7;
|
||||
uint8 byte_013580E8;
|
||||
uint8 byte_013580E9;
|
||||
uint16 park_size;
|
||||
uint16 guest_generation_probability;
|
||||
uint16 total_ride_value;
|
||||
uint32 dword_013580F0;
|
||||
uint16 dword_013580F4;
|
||||
uint8 dword_013580F6;
|
||||
uint8 dword_013580F7;
|
||||
uint8 objective_type;
|
||||
uint8 objective_year;
|
||||
uint8 pad_013580FA[4];
|
||||
money32 objective_currency;
|
||||
uint16 objective_guests;
|
||||
uint8 campaign_weeks_left[20];
|
||||
uint8 campaign_ride_index[22];
|
||||
|
||||
// Ignored in scenario
|
||||
money32 balance_history[128];
|
||||
|
||||
// SC6[11]
|
||||
uint32 dword_0135832C;
|
||||
uint32 current_profit;
|
||||
uint32 dword_01358334;
|
||||
uint16 word_01358338;
|
||||
uint8 pad_0135833A[2];
|
||||
|
||||
// Ignored in scenario
|
||||
uint8 pad_0135833C[2];
|
||||
money32 park_value;
|
||||
money32 park_value_history[128];
|
||||
|
||||
// SC6[12]
|
||||
money32 completed_company_value;
|
||||
uint32 total_admissions;
|
||||
money32 income_from_admissions;
|
||||
money32 company_value;
|
||||
uint8 byte_01358750[16];
|
||||
rct_award awards[4];
|
||||
uint16 word_01358770;
|
||||
uint16 word_01358772;
|
||||
uint16 word_01358774;
|
||||
uint8 pad_01358776[4];
|
||||
uint32 dword_01358778[17];
|
||||
uint32 dword_013587BC;
|
||||
uint32 dword_013587C0;
|
||||
uint32 dword_013587C4;
|
||||
uint16 dword_013587C8;
|
||||
uint8 pad_013587CA[16];
|
||||
uint32 dword_013587D0;
|
||||
uint8 pad_013587D4[8];
|
||||
uint16 word_013587D8[16];
|
||||
money32 cash;
|
||||
uint8 pad_013587FC[50];
|
||||
uint16 word_0135882E;
|
||||
uint16 word_01358830;
|
||||
uint16 word_01358832;
|
||||
uint16 map_size;
|
||||
uint16 word_01358836;
|
||||
uint32 word_01358838;
|
||||
uint16 suggested_max_guests;
|
||||
uint16 word_0135883E;
|
||||
uint8 word_01358840;
|
||||
uint8 word_01358841;
|
||||
uint8 pad_01358842[4];
|
||||
uint32 dword_01358844;
|
||||
uint8 pad_01358848;
|
||||
uint32 dword_01358849;
|
||||
uint8 pad_0135884D[2];
|
||||
uint8 dword_0135884E[622];
|
||||
uint8 pad_01359206[2];
|
||||
uint16 word_01359208;
|
||||
char scenario_name[64];
|
||||
char scenario_description[255];
|
||||
uint8 byte_01359349;
|
||||
uint8 byte_0135934A;
|
||||
uint8 pad_0135934B[3];
|
||||
uint32 dword_0135934C;
|
||||
uint16 park_entrance_x[4];
|
||||
uint16 park_entrance_y[4];
|
||||
uint16 park_entrance_z[4];
|
||||
uint8 byte_01359368;
|
||||
uint8 pad_01359369[3];
|
||||
uint8 byte_0135936C[256];
|
||||
uint8 byte_0135946C[3256];
|
||||
uint8 byte_0135A124;
|
||||
uint8 byte_0135A125;
|
||||
uint16 word_0135A126;
|
||||
uint8 byte_0135A128;
|
||||
uint8 byte_0135A129;
|
||||
uint8 byte_0135A12A;
|
||||
uint8 byte_0135A12B[793];
|
||||
uint8 byte_0135A444[1200];
|
||||
char custom_strings[0x8000];
|
||||
uint32 game_ticks_1;
|
||||
rct_ride rides[255];
|
||||
uint16 word_01388698;
|
||||
uint16 saved_view_x;
|
||||
uint16 saved_view_y;
|
||||
uint16 saved_view_zoom_and_rotation;
|
||||
uint8 byte_013886A0[6000];
|
||||
uint8 byte_01389E10[6000];
|
||||
uint16 word_0138B580;
|
||||
uint8 pad_0138B580[2];
|
||||
uint16 word_0138B584;
|
||||
uint16 word_0138B586;
|
||||
uint16 word_0138B588;
|
||||
uint16 word_0138B58A;
|
||||
uint16 word_0138B58C;
|
||||
uint16 word_0138B58E;
|
||||
uint8 byte_0138B590;
|
||||
uint8 byte_0138B591;
|
||||
uint8 byte_0138B592;
|
||||
uint8 byte_0138B593;
|
||||
uint16 word_0138B594;
|
||||
uint16 word_0138B596;
|
||||
uint16 word_0138B598;
|
||||
uint16 word_0138B59A;
|
||||
uint16 word_0138B59C;
|
||||
uint16 word_0138B59E;
|
||||
uint16 word_0138B5A0;
|
||||
uint16 word_0138B5A2;
|
||||
uint16 word_0138B5A4;
|
||||
uint16 word_0138B5A6;
|
||||
uint16 word_0138B5A8;
|
||||
uint16 word_0138B5AA;
|
||||
uint16 word_0138B5AC;
|
||||
uint16 word_0138B5AE;
|
||||
uint16 word_0138B5B0;
|
||||
uint16 word_0138B5B2;
|
||||
uint16 word_0138B5B4;
|
||||
uint16 word_0138B5B6;
|
||||
uint16 word_0138B5B8;
|
||||
uint16 word_0138B5BA;
|
||||
uint16 word_0138B5BC;
|
||||
uint16 word_0138B5BE;
|
||||
uint16 word_0138B5C0;
|
||||
uint16 word_0138B5C2;
|
||||
uint16 word_0138B5C4;
|
||||
uint16 word_0138B5C6;
|
||||
uint16 word_0138B5C8;
|
||||
uint16 word_0138B5CA;
|
||||
uint16 word_0138B5CC;
|
||||
uint16 word_0138B5CE[31];
|
||||
uint8 ride_measurements[0x25860];
|
||||
uint32 dword_13B0E6C;
|
||||
uint16 word_13B0E70;
|
||||
uint32 dword_13B0E72[0x6600];
|
||||
uint8 byte_13CA672[116];
|
||||
uint8 byte_13CA6E6[84];
|
||||
uint8 byte_13CA73A[4];
|
||||
uint8 unk_13CA73E;
|
||||
uint8 pad_13CA73E;
|
||||
uint8 byte_13CA740;
|
||||
uint8 byte_13CA741;
|
||||
uint8 byte_13CA7424[4];
|
||||
uint8 climate;
|
||||
uint8 pad_013CA747;
|
||||
uint16 climate_update_timer;
|
||||
uint8 current_weather;
|
||||
uint8 next_weather;
|
||||
uint8 temperature;
|
||||
uint8 next_temperature;
|
||||
uint8 current_weather_effect;
|
||||
uint8 next_weather_effect;
|
||||
uint8 current_weather_gloom;
|
||||
uint8 next_weather_gloom;
|
||||
uint8 current_rain_level;
|
||||
uint8 next_rain_level;
|
||||
rct_news_item news_items[61];
|
||||
uint8 byte_13CE730[64];
|
||||
uint32 dword_13CE770;
|
||||
uint16 word_13CE774;
|
||||
uint16 word_13CE776[217];
|
||||
} rct_s6_data;
|
||||
*/
|
||||
|
||||
enum {
|
||||
SCENARIO_FLAGS_VISIBLE = (1 << 0),
|
||||
SCENARIO_FLAGS_COMPLETED = (1 << 1),
|
||||
|
|
|
@ -17,10 +17,11 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
#pragma pack(1)
|
||||
|
||||
#include <lodepng.h>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include "osinterface.h"
|
||||
#include "addresses.h"
|
||||
#include "config.h"
|
||||
#include "gfx.h"
|
||||
|
@ -29,6 +30,8 @@
|
|||
#include "string_ids.h"
|
||||
#include "window_error.h"
|
||||
|
||||
#include <windows.h> // For MAX_PATH
|
||||
|
||||
|
||||
static int screenshot_dump_bmp();
|
||||
static int screenshot_dump_png();
|
||||
|
@ -59,17 +62,27 @@ void screenshot_check()
|
|||
|
||||
static int screenshot_get_next_path(char *path, char *extension)
|
||||
{
|
||||
char *screenshotPath = osinterface_get_orct2_homesubfolder("screenshot");
|
||||
if (!osinterface_ensure_directory_exists(screenshotPath)) {
|
||||
free(screenshotPath);
|
||||
|
||||
fprintf(stderr, "Unable to save screenshots in OpenRCT2 screenshot directory.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 1; i < 1000; i++) {
|
||||
RCT2_GLOBAL(0x013CE952, uint16) = i;
|
||||
|
||||
// Glue together path and filename
|
||||
sprintf(path, "%sSCR%d%s", RCT2_ADDRESS(RCT2_ADDRESS_APP_PATH_SLASH, char), i, extension);
|
||||
sprintf(path, "%s%cSCR%d%s", screenshotPath, osinterface_get_path_separator(), i, extension);
|
||||
|
||||
if (GetFileAttributes(path) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND)
|
||||
if (!osinterface_file_exists(path)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
free(screenshotPath);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -119,22 +132,23 @@ int screenshot_dump_bmp()
|
|||
|
||||
int i, y, index, width, height, stride;
|
||||
char *buffer, path[MAX_PATH], *row;
|
||||
HANDLE hFile;
|
||||
DWORD bytesWritten;
|
||||
FILE *fp;
|
||||
unsigned int bytesWritten;
|
||||
|
||||
// Get a free screenshot path
|
||||
if ((index = screenshot_get_next_path(path, ".bmp")) == -1)
|
||||
return -1;
|
||||
|
||||
// Open file for writing
|
||||
hFile = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
// Open binary file for writing
|
||||
if ((fp = fopen(path, "wb")) == NULL){
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Allocate buffer
|
||||
buffer = malloc(0xFFFF);
|
||||
if (buffer == NULL) {
|
||||
CloseHandle(hFile);
|
||||
//CloseHandle(hFile);
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -149,9 +163,9 @@ int screenshot_dump_bmp()
|
|||
header.bfSize = height * stride + 1038;
|
||||
header.bfOffBits = 1038;
|
||||
|
||||
WriteFile(hFile, &header, sizeof(header), &bytesWritten, NULL);
|
||||
if (bytesWritten != sizeof(header)) {
|
||||
CloseHandle(hFile);
|
||||
bytesWritten = fwrite(&header, sizeof(BitmapFileHeader), 1, fp);
|
||||
if (bytesWritten != 1) {
|
||||
fclose(fp);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
|
@ -166,9 +180,9 @@ int screenshot_dump_bmp()
|
|||
info.biYPelsPerMeter = 2520;
|
||||
info.biClrUsed = 246;
|
||||
|
||||
WriteFile(hFile, &info, sizeof(info), &bytesWritten, NULL);
|
||||
if (bytesWritten != sizeof(info)) {
|
||||
CloseHandle(hFile);
|
||||
bytesWritten=fwrite(&info, sizeof(BitmapInfoHeader), 1, fp);
|
||||
if (bytesWritten != 1) {
|
||||
fclose(fp);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
|
@ -180,9 +194,9 @@ int screenshot_dump_bmp()
|
|||
buffer[i * 4 + 2] = RCT2_ADDRESS(0x01424680, uint8)[i * 4 + 2];
|
||||
}
|
||||
|
||||
WriteFile(hFile, buffer, 246 * 4, &bytesWritten, NULL);
|
||||
if (bytesWritten != 246 * 4) {
|
||||
CloseHandle(hFile);
|
||||
bytesWritten = fwrite(buffer, sizeof(char), 246*4, fp);
|
||||
if (bytesWritten != 246*4){
|
||||
fclose(fp);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
|
@ -194,14 +208,14 @@ int screenshot_dump_bmp()
|
|||
memset(buffer, 0, stride);
|
||||
memcpy(buffer, row, dpi->width);
|
||||
|
||||
WriteFile(hFile, buffer, stride, &bytesWritten, NULL);
|
||||
if (bytesWritten != stride) {
|
||||
CloseHandle(hFile);
|
||||
bytesWritten=fwrite(buffer, sizeof(char), stride, fp);
|
||||
if (bytesWritten != stride){
|
||||
fclose(fp);
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(hFile);
|
||||
fclose(fp);
|
||||
free(buffer);
|
||||
|
||||
return index;
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (c) 2014 Ted John
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* This file is part of OpenRCT2.
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "addresses.h"
|
||||
#include "sprite.h"
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006736C7
|
||||
*/
|
||||
void create_balloon(int x, int y, int z, int colour)
|
||||
{
|
||||
RCT2_CALLPROC_X(0x006736C7, x, colour << 8, y, z, 0, 0, 0);
|
||||
}
|
15
src/sprite.h
15
src/sprite.h
|
@ -27,6 +27,7 @@
|
|||
#define SPRITE_LOCATION_NULL 0x8000
|
||||
|
||||
#include "peep.h"
|
||||
#include "vehicle.h"
|
||||
|
||||
typedef struct {
|
||||
uint8 sprite_identifier; // 0x00
|
||||
|
@ -46,16 +47,6 @@ typedef struct {
|
|||
uint32 var_24;
|
||||
} rct_litter;
|
||||
|
||||
typedef struct {
|
||||
uint8 sprite_idetifier; // 0x00
|
||||
uint8 pad_01[0x0D];
|
||||
sint16 x; // 0x0E
|
||||
sint16 y; // 0x10
|
||||
sint16 z; // 0x12
|
||||
uint8 pad_14[0x2a];
|
||||
uint16 next_car; // 0x3E
|
||||
} rct_car;
|
||||
|
||||
/**
|
||||
* Sprite structure.
|
||||
* size: 0x0100
|
||||
|
@ -65,7 +56,9 @@ typedef union {
|
|||
rct_unk_sprite unknown;
|
||||
rct_peep peep;
|
||||
rct_litter litter;
|
||||
rct_car car;
|
||||
rct_vehicle vehicle;
|
||||
} rct_sprite;
|
||||
|
||||
void create_balloon(int x, int y, int z, int colour);
|
||||
|
||||
#endif
|
||||
|
|
233
src/string_ids.c
233
src/string_ids.c
|
@ -1085,12 +1085,16 @@ void format_integer(char **dest, int value)
|
|||
|
||||
*dest = dst;
|
||||
|
||||
// Right to left
|
||||
while (value > 0) {
|
||||
digit = value % 10;
|
||||
value /= 10;
|
||||
if (value == 0) {
|
||||
*dst++ = '0';
|
||||
} else {
|
||||
// Right to left
|
||||
while (value > 0) {
|
||||
digit = value % 10;
|
||||
value /= 10;
|
||||
|
||||
*dst++ = '0' + digit;
|
||||
*dst++ = '0' + digit;
|
||||
}
|
||||
}
|
||||
finish = dst;
|
||||
|
||||
|
@ -1121,20 +1125,191 @@ void format_comma_separated_integer(char **dest, int value)
|
|||
|
||||
*dest = dst;
|
||||
|
||||
// Groups of three digits, right to left
|
||||
groupIndex = 0;
|
||||
while (value > 0) {
|
||||
// Append group seperator
|
||||
if (groupIndex == 3) {
|
||||
groupIndex = 0;
|
||||
*dst++ = ',';
|
||||
if (value == 0) {
|
||||
*dst++ = '0';
|
||||
} else {
|
||||
// Groups of three digits, right to left
|
||||
groupIndex = 0;
|
||||
while (value > 0) {
|
||||
// Append group seperator
|
||||
if (groupIndex == 3) {
|
||||
groupIndex = 0;
|
||||
*dst++ = ',';
|
||||
}
|
||||
|
||||
digit = value % 10;
|
||||
value /= 10;
|
||||
|
||||
*dst++ = '0' + digit;
|
||||
groupIndex++;
|
||||
}
|
||||
}
|
||||
finish = dst;
|
||||
|
||||
digit = value % 10;
|
||||
value /= 10;
|
||||
// Reverse string
|
||||
dst--;
|
||||
while (*dest < dst) {
|
||||
tmp = **dest;
|
||||
**dest = *dst;
|
||||
*dst = tmp;
|
||||
(*dest)++;
|
||||
dst--;
|
||||
}
|
||||
*dest = finish;
|
||||
}
|
||||
|
||||
*dst++ = '0' + digit;
|
||||
groupIndex++;
|
||||
void format_comma_separated_fixed_2dp(char **dest, int value)
|
||||
{
|
||||
int digit, groupIndex;
|
||||
char *dst = *dest;
|
||||
char *finish;
|
||||
char tmp;
|
||||
|
||||
// Negative sign
|
||||
if (value < 0) {
|
||||
*dst++ = '-';
|
||||
value = -value;
|
||||
}
|
||||
|
||||
*dest = dst;
|
||||
|
||||
// Two decimal places
|
||||
digit = value % 10;
|
||||
value /= 10;
|
||||
*dst++ = '0' + digit;
|
||||
digit = value % 10;
|
||||
value /= 10;
|
||||
*dst++ = '0' + digit;
|
||||
*dst++ = '.';
|
||||
|
||||
if (value == 0) {
|
||||
*dst++ = '0';
|
||||
} else {
|
||||
// Groups of three digits, right to left
|
||||
groupIndex = 0;
|
||||
while (value > 0) {
|
||||
// Append group seperator
|
||||
if (groupIndex == 3) {
|
||||
groupIndex = 0;
|
||||
*dst++ = ',';
|
||||
}
|
||||
|
||||
digit = value % 10;
|
||||
value /= 10;
|
||||
|
||||
*dst++ = '0' + digit;
|
||||
groupIndex++;
|
||||
}
|
||||
}
|
||||
finish = dst;
|
||||
|
||||
// Reverse string
|
||||
dst--;
|
||||
while (*dest < dst) {
|
||||
tmp = **dest;
|
||||
**dest = *dst;
|
||||
*dst = tmp;
|
||||
(*dest)++;
|
||||
dst--;
|
||||
}
|
||||
*dest = finish;
|
||||
}
|
||||
|
||||
void format_currency(char **dest, int value)
|
||||
{
|
||||
int digit, groupIndex;
|
||||
char *dst = *dest;
|
||||
char *finish;
|
||||
char tmp;
|
||||
|
||||
// Negative sign
|
||||
if (value < 0) {
|
||||
*dst++ = '-';
|
||||
value = -value;
|
||||
}
|
||||
|
||||
// Currency symbol
|
||||
*dst++ = '£';
|
||||
|
||||
*dest = dst;
|
||||
|
||||
value /= 10;
|
||||
if (value == 0) {
|
||||
*dst++ = '0';
|
||||
} else {
|
||||
// Groups of three digits, right to left
|
||||
groupIndex = 0;
|
||||
while (value > 0) {
|
||||
// Append group seperator
|
||||
if (groupIndex == 3) {
|
||||
groupIndex = 0;
|
||||
*dst++ = ',';
|
||||
}
|
||||
|
||||
digit = value % 10;
|
||||
value /= 10;
|
||||
|
||||
*dst++ = '0' + digit;
|
||||
groupIndex++;
|
||||
}
|
||||
}
|
||||
finish = dst;
|
||||
|
||||
// Reverse string
|
||||
dst--;
|
||||
while (*dest < dst) {
|
||||
tmp = **dest;
|
||||
**dest = *dst;
|
||||
*dst = tmp;
|
||||
(*dest)++;
|
||||
dst--;
|
||||
}
|
||||
*dest = finish;
|
||||
}
|
||||
|
||||
void format_currency_2dp(char **dest, int value)
|
||||
{
|
||||
int digit, groupIndex;
|
||||
char *dst = *dest;
|
||||
char *finish;
|
||||
char tmp;
|
||||
|
||||
// Negative sign
|
||||
if (value < 0) {
|
||||
*dst++ = '-';
|
||||
value = -value;
|
||||
}
|
||||
|
||||
// Currency symbol
|
||||
*dst++ = '£';
|
||||
|
||||
*dest = dst;
|
||||
|
||||
// Two decimal places
|
||||
*dst++ = '0';
|
||||
digit = value % 10;
|
||||
value /= 10;
|
||||
*dst++ = '0' + digit;
|
||||
*dst++ = '.';
|
||||
|
||||
if (value == 0) {
|
||||
*dst++ = '0';
|
||||
} else {
|
||||
// Groups of three digits, right to left
|
||||
groupIndex = 0;
|
||||
while (value > 0) {
|
||||
// Append group seperator
|
||||
if (groupIndex == 3) {
|
||||
groupIndex = 0;
|
||||
*dst++ = ',';
|
||||
}
|
||||
|
||||
digit = value % 10;
|
||||
value /= 10;
|
||||
|
||||
*dst++ = '0' + digit;
|
||||
groupIndex++;
|
||||
}
|
||||
}
|
||||
finish = dst;
|
||||
|
||||
|
@ -1174,8 +1349,7 @@ void format_string_code(unsigned char format_code, char **dest, char **args)
|
|||
value = *((sint32*)*args);
|
||||
*args += 4;
|
||||
|
||||
// TODO
|
||||
printf("TODO: FORMAT_COMMA2DP32\n");
|
||||
format_comma_separated_fixed_2dp(dest, value);
|
||||
break;
|
||||
case FORMAT_COMMA16:
|
||||
// Pop argument
|
||||
|
@ -1196,16 +1370,14 @@ void format_string_code(unsigned char format_code, char **dest, char **args)
|
|||
value = *((sint32*)*args);
|
||||
*args += 4;
|
||||
|
||||
// TODO
|
||||
printf("TODO: FORMAT_CURRENCY2DP\n");
|
||||
format_currency_2dp(dest, value);
|
||||
break;
|
||||
case FORMAT_CURRENCY:
|
||||
// Pop argument
|
||||
value = *((sint32*)*args);
|
||||
*args += 4;
|
||||
|
||||
// TODO
|
||||
printf("TODO: FORMAT_CURRENCY\n");
|
||||
format_currency(dest, value);
|
||||
break;
|
||||
case FORMAT_STRINGID:
|
||||
case FORMAT_STRINGID2:
|
||||
|
@ -1214,6 +1386,7 @@ void format_string_code(unsigned char format_code, char **dest, char **args)
|
|||
*args += 2;
|
||||
|
||||
format_string_part(dest, value, args);
|
||||
(*dest)--;
|
||||
break;
|
||||
case FORMAT_STRING:
|
||||
// Pop argument
|
||||
|
@ -1228,11 +1401,13 @@ void format_string_code(unsigned char format_code, char **dest, char **args)
|
|||
value = *((uint16*)*args);
|
||||
*args += 2;
|
||||
|
||||
uint16 dateArgs[] = { date_get_year(value), date_get_month(value) };
|
||||
uint16 dateArgs[] = { date_get_month(value), date_get_year(value) + 1 };
|
||||
uint16 *dateArgs2 = dateArgs;
|
||||
char formatString[] = "?, Year ?";
|
||||
formatString[0] = FORMAT_MONTH;
|
||||
formatString[8] = FORMAT_COMMA16;
|
||||
format_string_part_from_raw(dest, formatString, (char**)&dateArgs);
|
||||
format_string_part_from_raw(dest, formatString, (char**)&dateArgs2);
|
||||
(*dest)--;
|
||||
break;
|
||||
case FORMAT_MONTH:
|
||||
// Pop argument
|
||||
|
@ -1338,10 +1513,12 @@ void format_string_part_from_raw(char **dest, const char *src, char **args)
|
|||
*(*dest)++ = code;
|
||||
*(*dest)++ = *src++;
|
||||
*(*dest)++ = *src++;
|
||||
*(*dest)++ = *src++;
|
||||
*(*dest)++ = *src++;
|
||||
} else {
|
||||
*(*dest)++ = code;
|
||||
*(*dest)++ = *src++;
|
||||
*(*dest)++ = *src++;
|
||||
*(*dest)++ = *src++;
|
||||
*(*dest)++ = *src++;
|
||||
}
|
||||
} else if (code <= 'z') {
|
||||
*(*dest)++ = code;
|
||||
|
@ -1364,6 +1541,7 @@ void format_string_part(char **dest, rct_string_id format, char **args)
|
|||
// args += (format & 0xC00) >> 9;
|
||||
format &= ~0xC00;
|
||||
strcpy(*dest, RCT2_ADDRESS(0x135A8F4 + (format * 32), char));
|
||||
*dest = strchr(*dest, 0) + 1;
|
||||
} else if (format < 0xE000) {
|
||||
// Real name
|
||||
format -= -0xA000;
|
||||
|
@ -1371,6 +1549,7 @@ void format_string_part(char **dest, rct_string_id format, char **args)
|
|||
real_names[format % countof(real_names)],
|
||||
real_name_initials[(format >> 10) % countof(real_name_initials)]
|
||||
);
|
||||
*dest = strchr(*dest, 0) + 1;
|
||||
} else {
|
||||
// ?
|
||||
RCT2_CALLPROC_EBPSAFE(RCT2_ADDRESS(0x0095AFB8, uint32)[format]);
|
||||
|
@ -1498,4 +1677,4 @@ void reset_saved_strings() {
|
|||
for (int i = 0; i < 1024; i++) {
|
||||
RCT2_ADDRESS(0x135A8F4, uint8)[i * 32] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -341,6 +341,13 @@ enum {
|
|||
|
||||
STR_SHOW_SUBJECT_TIP = 1937,
|
||||
|
||||
STR_FINANCIAL_SUMMARY = 1949,
|
||||
STR_FINANCIAL_GRAPH = 1950,
|
||||
STR_PARK_VALUE_GRAPH = 1951,
|
||||
STR_PROFIT_GRAPH = 1952,
|
||||
STR_MARKETING = 1953,
|
||||
STR_RESEARCH_FUNDING = 1954,
|
||||
|
||||
STR_CELSIUS_VALUE = 2216,
|
||||
STR_FAHRENHEIT_VALUE = 2217,
|
||||
|
||||
|
@ -365,6 +372,19 @@ enum {
|
|||
STR_MONTH_NOVEMBER = STR_MONTH_JANUARY + 10,
|
||||
STR_MONTH_DECEMBER = STR_MONTH_JANUARY + 11,
|
||||
|
||||
STR_RESEARCH_TRANSPORT_RIDES = 2253,
|
||||
STR_RESEARCH_GENTLE_RIDES = 2254,
|
||||
STR_RESEARCH_ROLLER_COASTERS = 2255,
|
||||
STR_RESEARCH_THRILL_RIDES = 2256,
|
||||
STR_RESEARCH_WATER_RIDES = 2257,
|
||||
STR_RESEARCH_SHOPS_AND_STALLS = 2258,
|
||||
STR_RESEARCH_SCENERY_AND_THEMING = 2259,
|
||||
|
||||
STR_RESEARCH_FUNDING_ = 2264,
|
||||
STR_RESEARCH_PRIORITIES = 2266,
|
||||
|
||||
STR_FINANCES_RESEARCH = 2275,
|
||||
|
||||
STR_SELECT_SCENARIO = 2291,
|
||||
|
||||
STR_CHANGE_BASE_LAND_TIP = 2294,
|
||||
|
@ -439,6 +459,10 @@ enum {
|
|||
STR_OBJECTIVE_REPLAY_LOAN_AND_PARK_VALUE = STR_OBJECTIVE_NONE + 10,
|
||||
STR_OBJECTIVE_MONTHLY_FOOD_INCOME = STR_OBJECTIVE_NONE + 11,
|
||||
|
||||
STR_MARKETING_CAMPAIGNS_IN_OPERATION = 2409,
|
||||
STR_MARKETING_CAMPAIGNS_AVAILABLE = 2411,
|
||||
STR_START_THIS_MARKETING_CAMPAIGN = 2412,
|
||||
|
||||
STR_MARKETING_FINISHED_BASE = 2446,
|
||||
STR_MARKETING_FINISHED_FREE_ENTRY = 2446,
|
||||
STR_MARKETING_FINISHED_FREE_RIDES = 2447,
|
||||
|
@ -447,6 +471,12 @@ enum {
|
|||
STR_MARKETING_FINISHED_PARK_ADS = 2450,
|
||||
STR_MARKETING_FINISHED_RIDE_ADS = 2451,
|
||||
|
||||
STR_FINANCES_SHOW_SUMMARY_TAB_TIP = 2457,
|
||||
STR_FINANCES_SHOW_CASH_TAB_TIP = 2458,
|
||||
STR_FINANCES_SHOW_PARK_VALUE_TAB_TIP = 2459,
|
||||
STR_FINANCES_SHOW_WEEKLY_PROFIT_TAB_TIP = 2460,
|
||||
STR_FINANCES_SHOW_MARKETING_TAB_TIP = 2461,
|
||||
|
||||
STR_PARK_ENTRANCE_TAB_TIP = 2462,
|
||||
STR_PARK_RATING_TAB_TIP = 2463,
|
||||
STR_PARK_GUESTS_TAB_TIP = 2464,
|
||||
|
@ -455,6 +485,15 @@ enum {
|
|||
STR_PARK_OBJECTIVE_TAB_TIP = 2467,
|
||||
STR_PARK_AWARDS_TAB_TIP = 2468,
|
||||
|
||||
STR_SELECT_LEVEL_OF_RESEARCH_AND_DEVELOPMENT = 2469,
|
||||
STR_RESEARCH_NEW_TRANSPORT_RIDES = 2470,
|
||||
STR_RESEARCH_NEW_GENTLE_RIDES = 2471,
|
||||
STR_RESEARCH_NEW_ROLLER_COASTERS = 2472,
|
||||
STR_RESEARCH_NEW_THRILL_RIDES = 2473,
|
||||
STR_RESEARCH_NEW_WATER_RIDES = 2474,
|
||||
STR_RESEARCH_NEW_SHOPS_AND_STALLS = 2475,
|
||||
STR_RESEARCH_NEW_SCENERY_AND_THEMING = 2476,
|
||||
|
||||
STR_PROFIT_PER_WEEK_AND_PARK_VALUE_TIP = 2482,
|
||||
|
||||
STR_CONTROLS = 2485,
|
||||
|
@ -508,8 +547,29 @@ enum {
|
|||
STR_MOST_CONFUSING_LAYOUT = STR_AWARD_MOST_UNTIDY + 15,
|
||||
STR_BEST_GENTLE_RIDES = STR_AWARD_MOST_UNTIDY + 16,
|
||||
|
||||
STR_NEWS_ITEM_AWARD_MOST_UNTIDY = 2831,
|
||||
STR_NEWS_ITEM_MOST_TIDY = STR_NEWS_ITEM_AWARD_MOST_UNTIDY + 1,
|
||||
STR_NEWS_ITEM_BEST_ROLLERCOASTERS = STR_AWARD_MOST_UNTIDY + 2,
|
||||
STR_NEWS_ITEM_BEST_VALUE = STR_NEWS_ITEM_AWARD_MOST_UNTIDY + 3,
|
||||
STR_NEWS_ITEM_MOST_BEAUTIFUL = STR_NEWS_ITEM_AWARD_MOST_UNTIDY + 4,
|
||||
STR_NEWS_ITEM_WORST_VALUE = STR_NEWS_ITEM_AWARD_MOST_UNTIDY + 5,
|
||||
STR_NEWS_ITEM_SAFEST = STR_NEWS_ITEM_AWARD_MOST_UNTIDY + 6,
|
||||
STR_NEWS_ITEM_BEST_STAFF = STR_NEWS_ITEM_AWARD_MOST_UNTIDY + 7,
|
||||
STR_NEWS_ITEM_BEST_FOOD = STR_NEWS_ITEM_AWARD_MOST_UNTIDY + 8,
|
||||
STR_NEWS_ITEM_WORST_FOOD = STR_NEWS_ITEM_AWARD_MOST_UNTIDY + 9,
|
||||
STR_NEWS_ITEM_BEST_RESTROOMS = STR_NEWS_ITEM_AWARD_MOST_UNTIDY + 10,
|
||||
STR_NEWS_ITEM_MOST_DISAPPOINTING = STR_NEWS_ITEM_AWARD_MOST_UNTIDY + 11,
|
||||
STR_NEWS_ITEM_BEST_WATER_RIDES = STR_NEWS_ITEM_AWARD_MOST_UNTIDY + 12,
|
||||
STR_NEWS_ITEM_BEST_CUSTOM_DESIGNED_RIDES = STR_NEWS_ITEM_AWARD_MOST_UNTIDY + 13,
|
||||
STR_NEWS_ITEM_MOST_DAZZLING_RIDE_COLOURS = STR_NEWS_ITEM_AWARD_MOST_UNTIDY + 14,
|
||||
STR_NEWS_ITEM_MOST_CONFUSING_LAYOUT = STR_NEWS_ITEM_AWARD_MOST_UNTIDY + 15,
|
||||
STR_NEWS_ITEM_BEST_GENTLE_RIDES = STR_NEWS_ITEM_AWARD_MOST_UNTIDY + 16,
|
||||
|
||||
STR_NO_RECENT_AWARDS = 2848,
|
||||
|
||||
STR_ENTRANCE_NOT_CONNECTED = 2854,
|
||||
STR_EXIT_NOT_CONNECTED = 2855,
|
||||
|
||||
STR_TUTORIAL = 2856,
|
||||
STR_PRESS_KEY_OR_MOUSE_BUTTON_FOR_CONTROL = 2857,
|
||||
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (c) 2014 Ted John
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* This file is part of OpenRCT2.
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "addresses.h"
|
||||
#include "sprite.h"
|
||||
#include "vehicle.h"
|
||||
|
||||
static void vehicle_update(rct_vehicle *vehicle);
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006D4204
|
||||
*/
|
||||
void vehicle_update_all()
|
||||
{
|
||||
uint16 sprite_index;
|
||||
rct_vehicle *vehicle;
|
||||
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2)
|
||||
return;
|
||||
|
||||
if ((RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 4) && RCT2_GLOBAL(0x0141F570, uint8) != 6)
|
||||
return;
|
||||
|
||||
|
||||
sprite_index = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_VEHICLE, uint16);
|
||||
while (sprite_index != SPRITE_INDEX_NULL) {
|
||||
vehicle = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[sprite_index].vehicle);
|
||||
sprite_index = vehicle->next;
|
||||
|
||||
vehicle_update(vehicle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006D77F2
|
||||
*/
|
||||
static void vehicle_update(rct_vehicle *vehicle)
|
||||
{
|
||||
RCT2_CALLPROC_X(0x006D77F2, 0, 0, 0, 0, (int)vehicle, 0, 0);
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (c) 2014 Ted John
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* This file is part of OpenRCT2.
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _VEHICLE_H_
|
||||
#define _VEHICLE_H_
|
||||
|
||||
#include "rct2.h"
|
||||
|
||||
typedef struct {
|
||||
uint8 sprite_identifier; // 0x00
|
||||
uint8 pad_01[0x03];
|
||||
uint16 next; // 0x04
|
||||
uint8 pad_06[0x08];
|
||||
sint16 x; // 0x0E
|
||||
sint16 y; // 0x10
|
||||
sint16 z; // 0x12
|
||||
uint8 pad_14[0x2A];
|
||||
uint16 next_vehicle_on_train; // 0x3E
|
||||
} rct_vehicle;
|
||||
|
||||
void vehicle_update_all();
|
||||
|
||||
#endif
|
119
src/widget.c
119
src/widget.c
|
@ -156,6 +156,8 @@ void widget_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex)
|
|||
widget_scroll_draw(dpi, w, widgetIndex);
|
||||
break;
|
||||
case WWT_CHECKBOX:
|
||||
widget_checkbox_draw(dpi, w, widgetIndex);
|
||||
break;
|
||||
case WWT_24:
|
||||
widget_checkbox_draw(dpi, w, widgetIndex);
|
||||
break;
|
||||
|
@ -715,7 +717,7 @@ static void widget_closebox_draw(rct_drawpixelinfo *dpi, rct_window *w, int widg
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* rct2: 0x006EBAD9
|
||||
*/
|
||||
static void widget_checkbox_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex)
|
||||
|
@ -736,14 +738,12 @@ static void widget_checkbox_draw(rct_drawpixelinfo *dpi, rct_window *w, int widg
|
|||
colour = w->colours[widget->colour];
|
||||
|
||||
// checkbox
|
||||
if (widget->type != WWT_24) {
|
||||
gfx_fill_rect_inset(dpi, l, t, l + 9, b - 1, colour, 0x60);
|
||||
gfx_fill_rect_inset(dpi, l, t, l + 9, b - 1, colour, 0x60);
|
||||
|
||||
// fill it when checkbox is pressed
|
||||
if (widget_is_pressed(w, widgetIndex)) {
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 224;
|
||||
gfx_draw_string(dpi, (char*)0x009DED72, colour & 0x7F, l, t);
|
||||
}
|
||||
// fill it when checkbox is pressed
|
||||
if (widget_is_pressed(w, widgetIndex)) {
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 224;
|
||||
gfx_draw_string(dpi, (char*)0x009DED72, colour & 0x7F, l, t);
|
||||
}
|
||||
|
||||
// draw the text
|
||||
|
@ -996,3 +996,106 @@ int widget_is_active_tool(rct_window *w, int widgetIndex)
|
|||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void widget_scroll_get_part(rct_window *w, rct_widget* widget, int x, int y, int *output_x, int *output_y, int *output_scroll_area, int *output_dx)
|
||||
{
|
||||
rct_widget* iterator = w->widgets;
|
||||
int scroll_id = 0;
|
||||
while (++iterator != widget)
|
||||
{
|
||||
if (iterator->type == WWT_SCROLL)
|
||||
{
|
||||
scroll_id++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((w->scrolls[scroll_id].flags & 0x01) && y >= (w->y + widget->bottom - 11))
|
||||
{
|
||||
//horizon scrollbar
|
||||
int rightOffset = 0;
|
||||
int iteratorLeft = widget->left + w->x;
|
||||
int iteratorRight = widget->right + w->x;
|
||||
if (w->scrolls[scroll_id].flags & 0x01)
|
||||
{
|
||||
rightOffset = 11;
|
||||
}
|
||||
if (x <= (iteratorLeft += 10))
|
||||
{
|
||||
*output_scroll_area = SCROLL_PART_HSCROLLBAR_LEFT;
|
||||
}
|
||||
else if (x >= (iteratorRight -= rightOffset))
|
||||
{
|
||||
*output_scroll_area = SCROLL_PART_NONE;
|
||||
}
|
||||
else if (x >= (iteratorRight -= 10))
|
||||
{
|
||||
*output_scroll_area = SCROLL_PART_HSCROLLBAR_RIGHT;
|
||||
}
|
||||
else if (x < (widget->left + w->x + w->scrolls[scroll_id].h_thumb_left))
|
||||
{
|
||||
*output_scroll_area = SCROLL_PART_HSCROLLBAR_LEFT_TROUGH;
|
||||
}
|
||||
else if (x >(widget->left + w->x + w->scrolls[scroll_id].h_thumb_right))
|
||||
{
|
||||
*output_scroll_area = SCROLL_PART_HSCROLLBAR_RIGHT_TROUGH;
|
||||
}
|
||||
else
|
||||
{
|
||||
*output_scroll_area = SCROLL_PART_HSCROLLBAR_THUMB;
|
||||
}
|
||||
}
|
||||
else if ((w->scrolls[scroll_id].flags & 10) || (x >= w->x + widget->right - 11))
|
||||
{
|
||||
//vertical scrollbar
|
||||
int bottomOffset = 0;
|
||||
int iteratorTop = widget->top + w->y;
|
||||
int iteratorBottom = widget->bottom + w->y;
|
||||
if (w->scrolls[scroll_id].flags & 0x01)
|
||||
{
|
||||
bottomOffset = 11;
|
||||
}
|
||||
if (y <= (iteratorTop += 10))
|
||||
{
|
||||
*output_scroll_area = SCROLL_PART_VSCROLLBAR_TOP;
|
||||
}
|
||||
else if (y >= (iteratorBottom -= bottomOffset))
|
||||
{
|
||||
*output_scroll_area = SCROLL_PART_NONE;
|
||||
}
|
||||
else if (y >= (iteratorBottom -= 10))
|
||||
{
|
||||
*output_scroll_area = SCROLL_PART_VSCROLLBAR_BOTTOM;
|
||||
}
|
||||
else if (y < (widget->top + w->y + w->scrolls[scroll_id].v_thumb_top))
|
||||
{
|
||||
*output_scroll_area = SCROLL_PART_VSCROLLBAR_TOP_TROUGH;
|
||||
}
|
||||
else if (y > (widget->top + w->y + w->scrolls[scroll_id].v_thumb_bottom))
|
||||
{
|
||||
*output_scroll_area = SCROLL_PART_VSCROLLBAR_BOTTOM_TROUGH;
|
||||
}
|
||||
else
|
||||
{
|
||||
*output_scroll_area = SCROLL_PART_VSCROLLBAR_THUMB;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//view
|
||||
*output_scroll_area = SCROLL_PART_VIEW;
|
||||
*output_x = x - widget->left;
|
||||
*output_y = y - widget->top;
|
||||
*output_x -= w->x;
|
||||
*output_y -= w->y;
|
||||
if (--*output_x < 0 || --*output_y < 0)
|
||||
{
|
||||
*output_scroll_area = SCROLL_PART_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*output_x += w->scrolls[scroll_id].h_left;
|
||||
*output_y += w->scrolls[scroll_id].v_top;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,5 +62,5 @@ int widget_is_disabled(rct_window *w, int widgetIndex);
|
|||
int widget_is_pressed(rct_window *w, int widgetIndex);
|
||||
int widget_is_highlighted(rct_window *w, int widgetIndex);
|
||||
int widget_is_active_tool(rct_window *w, int widgetIndex);
|
||||
|
||||
void widget_scroll_get_part(rct_window *w, rct_widget* widget, int x, int y, int *output_x, int *output_y, int *output_cx, int *output_dx);
|
||||
#endif
|
||||
|
|
|
@ -376,7 +376,7 @@ rct_window *window_create(int x, int y, int width, int height, uint32 *event_han
|
|||
|
||||
// Play sound
|
||||
if (!(flags & (WF_STICK_TO_BACK | WF_STICK_TO_FRONT)))
|
||||
sound_play_panned(40, x + (width / 2));
|
||||
sound_play_panned(SOUND_WINDOW_OPEN, x + (width / 2));
|
||||
|
||||
w->number = 0;
|
||||
w->x = x;
|
||||
|
|
|
@ -81,7 +81,7 @@ typedef struct {
|
|||
* size: 0x12
|
||||
*/
|
||||
typedef struct {
|
||||
uint16 flags; // 0x00
|
||||
uint16 flags; // 0x00 (0x10 == vertical scrollbar, 0x01 == horizontal scrollbar)
|
||||
sint16 h_left; // 0x02
|
||||
sint16 h_right; // 0x04
|
||||
sint16 h_thumb_left; // 0x06
|
||||
|
@ -126,7 +126,7 @@ typedef struct rct_window {
|
|||
sint16 var_484; // viewport target y
|
||||
sint16 var_486; // viewport target z
|
||||
sint16 var_488; // viewport rotation << 8
|
||||
sint16 page; // 0x49A
|
||||
sint16 page; // 0x48A
|
||||
sint16 var_48C;
|
||||
sint16 var_48E;
|
||||
sint16 var_490;
|
||||
|
@ -286,7 +286,7 @@ enum {
|
|||
} WINDOW_CLASS;
|
||||
|
||||
enum PROMPT_MODE {
|
||||
PM_SAVE_BEFORE_LOAD,
|
||||
PM_SAVE_BEFORE_LOAD = 0,
|
||||
PM_SAVE_BEFORE_QUIT,
|
||||
PM_SAVE_BEFORE_QUIT2,
|
||||
PM_QUIT
|
||||
|
@ -359,6 +359,7 @@ void window_park_entrance_open();
|
|||
void window_park_guests_open();
|
||||
void window_park_objective_open();
|
||||
void window_park_rating_open();
|
||||
void window_finances_open();
|
||||
void window_ride_list_open();
|
||||
void window_banner_open();
|
||||
void window_cheats_open();
|
||||
|
|
|
@ -55,7 +55,7 @@ rct_widget window_banner_widgets[] = {
|
|||
|
||||
static void window_banner_emptysub() { }
|
||||
static void window_banner_mouseup();
|
||||
static void window_banner_mousedown();
|
||||
static void window_banner_mousedown(int widgetIndex, rct_window*w, rct_widget* widget);
|
||||
static void window_banner_dropdown();
|
||||
static void window_banner_textinput();
|
||||
static void window_banner_invalidate();
|
||||
|
@ -182,14 +182,14 @@ static void window_banner_mouseup()
|
|||
}
|
||||
}
|
||||
|
||||
static void window_banner_mousedown()
|
||||
static void window_banner_mousedown(int widgetIndex, rct_window*w, rct_widget* widget)
|
||||
{
|
||||
short widgetIndex;
|
||||
//short widgetIndex;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov widgetIndex, dx
|
||||
//__asm mov widgetIndex, dx
|
||||
#else
|
||||
__asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) );
|
||||
// __asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) );
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ static rct_widget window_cheats_money_widgets[] = {
|
|||
{ WWT_IMGBTN, 1, 0, WW - 1, 43, WH - 1, 0x0FFFFFFFF, 65535}, // tab content panel
|
||||
{ WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, 2462}, // tab 1
|
||||
{ WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, 2462}, // tab 2
|
||||
{ WWT_CLOSEBOX, 1, 4, 74, 47, 63, STR_VERY_HIGH, STR_VERY_HIGH}, // high money
|
||||
{ WWT_CLOSEBOX, 1, 4, 74, 67, 83, STR_VERY_HIGH, STR_VERY_HIGH}, // high money
|
||||
{ WIDGETS_END },
|
||||
};
|
||||
|
||||
|
@ -69,7 +69,7 @@ static rct_widget window_cheats_guests_widgets[] = {
|
|||
{ WWT_IMGBTN, 1, 0, WW - 1, 43, WH - 1, 0x0FFFFFFFF, 65535 }, // tab content panel
|
||||
{ WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, 2462 }, // tab 1
|
||||
{ WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, 2462 }, // tab 2
|
||||
{ WWT_CLOSEBOX, 1, 4, 74, 47, 63, STR_EXTREME, STR_EXTREME}, // happy guests
|
||||
{ WWT_CLOSEBOX, 1, 4, 74, 77, 93, STR_EXTREME, STR_EXTREME}, // happy guests
|
||||
{ WIDGETS_END },
|
||||
};
|
||||
|
||||
|
@ -239,7 +239,7 @@ static void window_cheats_guests_mouseup()
|
|||
#endif
|
||||
|
||||
rct_peep* peep;
|
||||
uint16 sprite_idx;
|
||||
uint16 spriteIndex;
|
||||
|
||||
switch (widgetIndex) {
|
||||
case WIDX_CLOSE:
|
||||
|
@ -250,14 +250,9 @@ static void window_cheats_guests_mouseup()
|
|||
window_cheats_set_page(w, widgetIndex - WIDX_TAB_1);
|
||||
break;
|
||||
case WIDX_HAPPY_GUESTS:
|
||||
for (sprite_idx = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16); sprite_idx != SPRITE_INDEX_NULL; sprite_idx = peep->next) {
|
||||
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[sprite_idx].peep);
|
||||
if (peep->type != PEEP_TYPE_GUEST)
|
||||
continue;
|
||||
if (peep->var_2A != 0)
|
||||
continue;
|
||||
peep->happiness = 255;
|
||||
}
|
||||
FOR_ALL_GUESTS(spriteIndex, peep)
|
||||
if (peep->var_2A == 0)
|
||||
peep->happiness = 255;
|
||||
window_invalidate_by_id(0x40 | WC_BOTTOM_TOOLBAR, 0);
|
||||
break;
|
||||
}
|
||||
|
@ -322,6 +317,26 @@ static void window_cheats_paint()
|
|||
|
||||
window_draw_widgets(w, dpi);
|
||||
window_cheats_draw_tab_images(dpi, w);
|
||||
|
||||
if (w->page == WINDOW_CHEATS_PAGE_MONEY){
|
||||
char buffer[256];
|
||||
// Format text (name and version)
|
||||
sprintf(buffer, "%c%c%s", FORMAT_MEDIUMFONT, FORMAT_BLACK, "Increases your money by 1,000.");
|
||||
// Draw shadow
|
||||
gfx_draw_string(dpi, buffer, 0, w->x + 4, w->y + 50);
|
||||
}
|
||||
else if (w->page == WINDOW_CHEATS_PAGE_GUESTS){
|
||||
char buffer[256];
|
||||
// Format text (name and version)
|
||||
sprintf(buffer, "%c%c%s", FORMAT_MEDIUMFONT, FORMAT_BLACK, "Increases every peeps happiness ");
|
||||
// Draw shadow
|
||||
gfx_draw_string(dpi, buffer, 0, w->x + 4, w->y + 50);
|
||||
// Format text (name and version)
|
||||
sprintf(buffer, "%c%c%s", FORMAT_MEDIUMFONT, FORMAT_BLACK, "to max.");
|
||||
// Draw shadow
|
||||
gfx_draw_string(dpi, buffer, 0, w->x + 4, w->y + 60);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void window_cheats_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w)
|
||||
|
@ -333,7 +348,7 @@ static void window_cheats_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w)
|
|||
sprite_idx = 5261;
|
||||
if (w->page == WINDOW_CHEATS_PAGE_MONEY)
|
||||
sprite_idx += (w->var_48E / 2) % 8;
|
||||
gfx_draw_sprite(dpi, sprite_idx, w->x + w->widgets[WIDX_TAB_1].left, w->y + w->widgets[WIDX_TAB_1].top);
|
||||
gfx_draw_sprite(dpi, sprite_idx, w->x + w->widgets[WIDX_TAB_1].left, w->y + w->widgets[WIDX_TAB_1].top);
|
||||
}
|
||||
|
||||
// Guests tab
|
||||
|
|
|
@ -18,16 +18,409 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "addresses.h"
|
||||
#include "game.h"
|
||||
#include "string_ids.h"
|
||||
#include "widget.h"
|
||||
#include "window.h"
|
||||
|
||||
enum {
|
||||
WINDOW_FINANCES_TAB_SUMMARY,
|
||||
WINDOW_FINANCES_TAB_FINANCIAL_GRAPH,
|
||||
WINDOW_FINANCES_TAB_VALUE_GRAPH,
|
||||
WINDOW_FINANCES_TAB_PROFIT_GRAPH,
|
||||
WINDOW_FINANCES_TAB_MARKETING,
|
||||
WINDOW_FINANCES_TAB_RESEARCH
|
||||
} WINDOW_FINANCIAL_TAB;
|
||||
WINDOW_FINANCES_PAGE_SUMMARY,
|
||||
WINDOW_FINANCES_PAGE_FINANCIAL_GRAPH,
|
||||
WINDOW_FINANCES_PAGE_VALUE_GRAPH,
|
||||
WINDOW_FINANCES_PAGE_PROFIT_GRAPH,
|
||||
WINDOW_FINANCES_PAGE_MARKETING,
|
||||
WINDOW_FINANCES_PAGE_RESEARCH,
|
||||
WINDOW_FINANCES_PAGE_COUNT
|
||||
};
|
||||
|
||||
enum {
|
||||
WIDX_BACKGROUND,
|
||||
WIDX_TITLE,
|
||||
WIDX_CLOSE,
|
||||
WIDX_PAGE_BACKGROUND,
|
||||
WIDX_TAB_1,
|
||||
WIDX_TAB_2,
|
||||
WIDX_TAB_3,
|
||||
WIDX_TAB_4,
|
||||
WIDX_TAB_5,
|
||||
WIDX_TAB_6,
|
||||
|
||||
WIDX_LOAN = 10,
|
||||
WIDX_LOAN_INCREASE,
|
||||
WIDX_LOAN_DECREASE,
|
||||
|
||||
WIDX_CAMPAIGN_1 = 12,
|
||||
WIDX_CAMPAIGN_2,
|
||||
WIDX_CAMPAIGN_3,
|
||||
WIDX_CAMPAIGN_4,
|
||||
WIDX_CAMPAIGN_5,
|
||||
WIDX_CAMPAIGN_6,
|
||||
|
||||
WIDX_RESEARCH_FUNDING = 11,
|
||||
WIDX_RESEARCH_FUNDING_DROPDOWN_BUTTON,
|
||||
WIDX_TRANSPORT_RIDES = 14,
|
||||
WIDX_GENTLE_RIDES,
|
||||
WIDX_ROLLER_COASTERS,
|
||||
WIDX_THRILL_RIDES,
|
||||
WIDX_WATER_RIDES,
|
||||
WIDX_SHOPS_AND_STALLS,
|
||||
WIDX_SCENERY_AND_THEMING,
|
||||
};
|
||||
|
||||
#pragma region Widgets
|
||||
|
||||
static rct_widget window_finances_summary_widgets[] = {
|
||||
{ WWT_FRAME, 0, 0, 529, 0, 256, 0xFFFFFFFF, STR_NONE },
|
||||
{ WWT_CAPTION, 0, 1, 528, 1, 14, STR_FINANCIAL_SUMMARY, STR_WINDOW_TITLE_TIP },
|
||||
{ WWT_CLOSEBOX, 0, 517, 527, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP },
|
||||
{ WWT_RESIZE, 1, 0, 529, 43, 256, 0xFFFFFFFF, STR_NONE },
|
||||
{ WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, STR_FINANCES_SHOW_SUMMARY_TAB_TIP },
|
||||
{ WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, STR_FINANCES_SHOW_CASH_TAB_TIP },
|
||||
{ WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, STR_FINANCES_SHOW_PARK_VALUE_TAB_TIP },
|
||||
{ WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, STR_FINANCES_SHOW_WEEKLY_PROFIT_TAB_TIP },
|
||||
{ WWT_TAB, 1, 127, 157, 17, 43, 0x2000144E, STR_FINANCES_SHOW_MARKETING_TAB_TIP },
|
||||
{ WWT_TAB, 1, 158, 188, 17, 43, 0x2000144E, STR_FINANCES_RESEARCH },
|
||||
{ WWT_SPINNER, 1, 64, 153, 229, 240, 1917, STR_NONE },
|
||||
{ WWT_DROPDOWN_BUTTON, 1, 142, 152, 230, 234, STR_NUMERIC_UP, STR_NONE },
|
||||
{ WWT_DROPDOWN_BUTTON, 1, 142, 152, 235, 239, STR_NUMERIC_DOWN, STR_NONE },
|
||||
{ WIDGETS_END },
|
||||
};
|
||||
|
||||
static rct_widget window_finances_cash_widgets[] = {
|
||||
{ WWT_FRAME, 0, 0, 529, 0, 256, 0xFFFFFFFF, STR_NONE },
|
||||
{ WWT_CAPTION, 0, 1, 528, 1, 14, STR_FINANCIAL_GRAPH, STR_WINDOW_TITLE_TIP },
|
||||
{ WWT_CLOSEBOX, 0, 517, 527, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP },
|
||||
{ WWT_RESIZE, 1, 0, 529, 43, 256, 0xFFFFFFFF, STR_NONE },
|
||||
{ WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, STR_FINANCES_SHOW_SUMMARY_TAB_TIP },
|
||||
{ WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, STR_FINANCES_SHOW_CASH_TAB_TIP },
|
||||
{ WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, STR_FINANCES_SHOW_PARK_VALUE_TAB_TIP },
|
||||
{ WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, STR_FINANCES_SHOW_WEEKLY_PROFIT_TAB_TIP },
|
||||
{ WWT_TAB, 1, 127, 157, 17, 43, 0x2000144E, STR_FINANCES_SHOW_MARKETING_TAB_TIP },
|
||||
{ WWT_TAB, 1, 158, 188, 17, 43, 0x2000144E, STR_FINANCES_RESEARCH },
|
||||
{ WIDGETS_END },
|
||||
};
|
||||
|
||||
static rct_widget window_finances_park_value_widgets[] = {
|
||||
{ WWT_FRAME, 0, 0, 529, 0, 256, 0xFFFFFFFF, STR_NONE },
|
||||
{ WWT_CAPTION, 0, 1, 528, 1, 14, STR_PARK_VALUE_GRAPH, STR_WINDOW_TITLE_TIP },
|
||||
{ WWT_CLOSEBOX, 0, 517, 527, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP },
|
||||
{ WWT_RESIZE, 1, 0, 529, 43, 256, 0xFFFFFFFF, STR_NONE },
|
||||
{ WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, STR_FINANCES_SHOW_SUMMARY_TAB_TIP },
|
||||
{ WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, STR_FINANCES_SHOW_CASH_TAB_TIP },
|
||||
{ WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, STR_FINANCES_SHOW_PARK_VALUE_TAB_TIP },
|
||||
{ WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, STR_FINANCES_SHOW_WEEKLY_PROFIT_TAB_TIP },
|
||||
{ WWT_TAB, 1, 127, 157, 17, 43, 0x2000144E, STR_FINANCES_SHOW_MARKETING_TAB_TIP },
|
||||
{ WWT_TAB, 1, 158, 188, 17, 43, 0x2000144E, STR_FINANCES_RESEARCH },
|
||||
{ WIDGETS_END },
|
||||
};
|
||||
|
||||
static rct_widget window_finances_profit_widgets[] = {
|
||||
{ WWT_FRAME, 0, 0, 529, 0, 256, 0xFFFFFFFF, STR_NONE },
|
||||
{ WWT_CAPTION, 0, 1, 528, 1, 14, STR_PROFIT_GRAPH, STR_WINDOW_TITLE_TIP },
|
||||
{ WWT_CLOSEBOX, 0, 517, 527, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP },
|
||||
{ WWT_RESIZE, 1, 0, 529, 43, 256, 0xFFFFFFFF, STR_NONE },
|
||||
{ WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, STR_FINANCES_SHOW_SUMMARY_TAB_TIP },
|
||||
{ WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, STR_FINANCES_SHOW_CASH_TAB_TIP },
|
||||
{ WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, STR_FINANCES_SHOW_PARK_VALUE_TAB_TIP },
|
||||
{ WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, STR_FINANCES_SHOW_WEEKLY_PROFIT_TAB_TIP },
|
||||
{ WWT_TAB, 1, 127, 157, 17, 43, 0x2000144E, STR_FINANCES_SHOW_MARKETING_TAB_TIP },
|
||||
{ WWT_TAB, 1, 158, 188, 17, 43, 0x2000144E, STR_FINANCES_RESEARCH },
|
||||
{ WIDGETS_END },
|
||||
};
|
||||
|
||||
static rct_widget window_finances_marketing_widgets[] = {
|
||||
{ WWT_FRAME, 0, 0, 529, 0, 256, 0xFFFFFFFF, STR_NONE },
|
||||
{ WWT_CAPTION, 0, 1, 528, 1, 14, STR_MARKETING, STR_WINDOW_TITLE_TIP },
|
||||
{ WWT_CLOSEBOX, 0, 517, 527, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP },
|
||||
{ WWT_RESIZE, 1, 0, 529, 43, 256, 0xFFFFFFFF, STR_NONE },
|
||||
{ WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, STR_FINANCES_SHOW_SUMMARY_TAB_TIP },
|
||||
{ WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, STR_FINANCES_SHOW_CASH_TAB_TIP },
|
||||
{ WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, STR_FINANCES_SHOW_PARK_VALUE_TAB_TIP },
|
||||
{ WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, STR_FINANCES_SHOW_WEEKLY_PROFIT_TAB_TIP },
|
||||
{ WWT_TAB, 1, 127, 157, 17, 43, 0x2000144E, STR_FINANCES_SHOW_MARKETING_TAB_TIP },
|
||||
{ WWT_TAB, 1, 158, 188, 17, 43, 0x2000144E, STR_FINANCES_RESEARCH },
|
||||
{ WWT_GROUPBOX, 2, 3, 526, 47, 91, STR_MARKETING_CAMPAIGNS_IN_OPERATION, STR_NONE },
|
||||
{ WWT_GROUPBOX, 2, 3, 526, 47, 252, STR_MARKETING_CAMPAIGNS_AVAILABLE, STR_NONE },
|
||||
{ WWT_IMGBTN, 1, 8, 521, 0, 11, 0xFFFFFFFF, STR_START_THIS_MARKETING_CAMPAIGN },
|
||||
{ WWT_IMGBTN, 1, 8, 521, 0, 11, 0xFFFFFFFF, STR_START_THIS_MARKETING_CAMPAIGN },
|
||||
{ WWT_IMGBTN, 1, 8, 521, 0, 11, 0xFFFFFFFF, STR_START_THIS_MARKETING_CAMPAIGN },
|
||||
{ WWT_IMGBTN, 1, 8, 521, 0, 11, 0xFFFFFFFF, STR_START_THIS_MARKETING_CAMPAIGN },
|
||||
{ WWT_IMGBTN, 1, 8, 521, 0, 11, 0xFFFFFFFF, STR_START_THIS_MARKETING_CAMPAIGN },
|
||||
{ WWT_IMGBTN, 1, 8, 521, 0, 11, 0xFFFFFFFF, STR_START_THIS_MARKETING_CAMPAIGN },
|
||||
{ WIDGETS_END },
|
||||
};
|
||||
|
||||
static rct_widget window_finances_research_widgets[] = {
|
||||
{ WWT_FRAME, 0, 0, 529, 0, 256, 0xFFFFFFFF, STR_NONE },
|
||||
{ WWT_CAPTION, 0, 1, 528, 1, 14, STR_RESEARCH_FUNDING, STR_WINDOW_TITLE_TIP },
|
||||
{ WWT_CLOSEBOX, 0, 517, 527, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP },
|
||||
{ WWT_RESIZE, 1, 0, 529, 43, 256, 0xFFFFFFFF, STR_NONE },
|
||||
{ WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, STR_FINANCES_SHOW_SUMMARY_TAB_TIP },
|
||||
{ WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, STR_FINANCES_SHOW_CASH_TAB_TIP },
|
||||
{ WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, STR_FINANCES_SHOW_PARK_VALUE_TAB_TIP },
|
||||
{ WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, STR_FINANCES_SHOW_WEEKLY_PROFIT_TAB_TIP },
|
||||
{ WWT_TAB, 1, 127, 157, 17, 43, 0x2000144E, STR_FINANCES_SHOW_MARKETING_TAB_TIP },
|
||||
{ WWT_TAB, 1, 158, 188, 17, 43, 0x2000144E, STR_FINANCES_RESEARCH },
|
||||
{ WWT_GROUPBOX, 2, 3, 316, 47, 91, STR_RESEARCH_FUNDING_, STR_NONE },
|
||||
{ WWT_DROPDOWN, 2, 8, 167, 59, 70, 0xFFFFFFFF, STR_SELECT_LEVEL_OF_RESEARCH_AND_DEVELOPMENT },
|
||||
{ WWT_DROPDOWN_BUTTON, 2, 156, 166, 60, 69, 876, STR_SELECT_LEVEL_OF_RESEARCH_AND_DEVELOPMENT },
|
||||
{ WWT_GROUPBOX, 2, 3, 316, 96, 202, STR_RESEARCH_PRIORITIES, STR_NONE },
|
||||
{ WWT_CHECKBOX, 2, 8, 311, 108, 119, STR_RESEARCH_TRANSPORT_RIDES, STR_RESEARCH_NEW_TRANSPORT_RIDES },
|
||||
{ WWT_CHECKBOX, 2, 8, 311, 121, 132, STR_RESEARCH_GENTLE_RIDES, STR_RESEARCH_NEW_GENTLE_RIDES },
|
||||
{ WWT_CHECKBOX, 2, 8, 311, 134, 145, STR_RESEARCH_ROLLER_COASTERS, STR_RESEARCH_NEW_ROLLER_COASTERS },
|
||||
{ WWT_CHECKBOX, 2, 8, 311, 147, 158, STR_RESEARCH_THRILL_RIDES, STR_RESEARCH_NEW_THRILL_RIDES },
|
||||
{ WWT_CHECKBOX, 2, 8, 311, 160, 171, STR_RESEARCH_WATER_RIDES, STR_RESEARCH_NEW_WATER_RIDES },
|
||||
{ WWT_CHECKBOX, 2, 8, 311, 173, 184, STR_RESEARCH_SHOPS_AND_STALLS, STR_RESEARCH_NEW_SHOPS_AND_STALLS },
|
||||
{ WWT_CHECKBOX, 2, 8, 311, 186, 197, STR_RESEARCH_SCENERY_AND_THEMING, STR_RESEARCH_NEW_SCENERY_AND_THEMING },
|
||||
{ WIDGETS_END },
|
||||
};
|
||||
|
||||
static rct_widget *window_finances_page_widgets[] = {
|
||||
window_finances_summary_widgets,
|
||||
window_finances_cash_widgets,
|
||||
window_finances_park_value_widgets,
|
||||
window_finances_profit_widgets,
|
||||
window_finances_marketing_widgets,
|
||||
window_finances_research_widgets
|
||||
};
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Events
|
||||
|
||||
static void* window_finances_page_events[] = {
|
||||
(void*)0x00988EB8,
|
||||
(void*)0x00988F28,
|
||||
(void*)0x00988F98,
|
||||
(void*)0x00989008,
|
||||
(void*)0x00989078,
|
||||
(void*)0x009890E8
|
||||
};
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Enabled widgets
|
||||
|
||||
static uint32 window_finances_page_enabled_widgets[] = {
|
||||
(1 << WIDX_CLOSE) |
|
||||
(1 << WIDX_TAB_1) |
|
||||
(1 << WIDX_TAB_2) |
|
||||
(1 << WIDX_TAB_3) |
|
||||
(1 << WIDX_TAB_4) |
|
||||
(1 << WIDX_TAB_5) |
|
||||
(1 << WIDX_TAB_6) |
|
||||
(1 << WIDX_LOAN_INCREASE) |
|
||||
(1 << WIDX_LOAN_DECREASE),
|
||||
|
||||
(1 << WIDX_CLOSE) |
|
||||
(1 << WIDX_TAB_1) |
|
||||
(1 << WIDX_TAB_2) |
|
||||
(1 << WIDX_TAB_3) |
|
||||
(1 << WIDX_TAB_4) |
|
||||
(1 << WIDX_TAB_5) |
|
||||
(1 << WIDX_TAB_6),
|
||||
|
||||
(1 << WIDX_CLOSE) |
|
||||
(1 << WIDX_TAB_1) |
|
||||
(1 << WIDX_TAB_2) |
|
||||
(1 << WIDX_TAB_3) |
|
||||
(1 << WIDX_TAB_4) |
|
||||
(1 << WIDX_TAB_5) |
|
||||
(1 << WIDX_TAB_6),
|
||||
|
||||
(1 << WIDX_CLOSE) |
|
||||
(1 << WIDX_TAB_1) |
|
||||
(1 << WIDX_TAB_2) |
|
||||
(1 << WIDX_TAB_3) |
|
||||
(1 << WIDX_TAB_4) |
|
||||
(1 << WIDX_TAB_5) |
|
||||
(1 << WIDX_TAB_6),
|
||||
|
||||
(1 << WIDX_CLOSE) |
|
||||
(1 << WIDX_TAB_1) |
|
||||
(1 << WIDX_TAB_2) |
|
||||
(1 << WIDX_TAB_3) |
|
||||
(1 << WIDX_TAB_4) |
|
||||
(1 << WIDX_TAB_5) |
|
||||
(1 << WIDX_TAB_6) |
|
||||
(1 << WIDX_CAMPAIGN_1) |
|
||||
(1 << WIDX_CAMPAIGN_2) |
|
||||
(1 << WIDX_CAMPAIGN_3) |
|
||||
(1 << WIDX_CAMPAIGN_4) |
|
||||
(1 << WIDX_CAMPAIGN_5) |
|
||||
(1 << WIDX_CAMPAIGN_6),
|
||||
|
||||
(1 << WIDX_CLOSE) |
|
||||
(1 << WIDX_TAB_1) |
|
||||
(1 << WIDX_TAB_2) |
|
||||
(1 << WIDX_TAB_3) |
|
||||
(1 << WIDX_TAB_4) |
|
||||
(1 << WIDX_TAB_5) |
|
||||
(1 << WIDX_TAB_6) |
|
||||
|
||||
(1 << WIDX_RESEARCH_FUNDING) |
|
||||
(1 << WIDX_RESEARCH_FUNDING_DROPDOWN_BUTTON) |
|
||||
(1 << WIDX_TRANSPORT_RIDES) |
|
||||
(1 << WIDX_GENTLE_RIDES) |
|
||||
(1 << WIDX_ROLLER_COASTERS) |
|
||||
(1 << WIDX_THRILL_RIDES) |
|
||||
(1 << WIDX_WATER_RIDES) |
|
||||
(1 << WIDX_SHOPS_AND_STALLS) |
|
||||
(1 << WIDX_SCENERY_AND_THEMING)
|
||||
};
|
||||
|
||||
#pragma endregion
|
||||
|
||||
const int window_finances_tab_animation_loops[] = { 16, 32, 32, 32, 38, 16 };
|
||||
|
||||
static void window_finances_set_page(rct_window *w, int page);
|
||||
static void window_finances_set_pressed_tab(rct_window *w);
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0069DDF1
|
||||
*/
|
||||
void window_finances_open()
|
||||
{
|
||||
rct_window *w;
|
||||
|
||||
w = window_bring_to_front_by_id(WC_FINANCES, 0);
|
||||
if (w == NULL) {
|
||||
w = window_create_auto_pos(530, 257, window_finances_page_events[0], WC_FINANCES, WF_10);
|
||||
w->widgets = window_finances_page_widgets[0];
|
||||
w->enabled_widgets = 0x1BF4;
|
||||
w->number = 0;
|
||||
w->page = 0;
|
||||
w->var_48E = 0;
|
||||
w->disabled_widgets = 0;
|
||||
w->colours[0] = 1;
|
||||
w->colours[1] = 19;
|
||||
w->colours[2] = 19;
|
||||
RCT2_CALLPROC_EBPSAFE(0x00684BAE);
|
||||
}
|
||||
|
||||
w->page = 0;
|
||||
window_invalidate(w);
|
||||
w->width = 530;
|
||||
w->height = 257;
|
||||
window_invalidate(w);
|
||||
|
||||
w->widgets = window_finances_page_widgets[0];
|
||||
w->enabled_widgets = window_finances_page_enabled_widgets[0];
|
||||
w->var_020 = RCT2_GLOBAL(0x00988E3C, uint32);
|
||||
w->event_handlers = window_finances_page_events[0];
|
||||
w->pressed_widgets = 0;
|
||||
w->disabled_widgets = 0;
|
||||
window_init_scroll_widgets(w);
|
||||
}
|
||||
|
||||
#pragma region Summary page
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0069CA99
|
||||
*/
|
||||
static void window_finances_summary_mouseup()
|
||||
{
|
||||
short widgetIndex;
|
||||
rct_window *w;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov widgetIndex, dx
|
||||
#else
|
||||
__asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) );
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov w, esi
|
||||
#else
|
||||
__asm__ ( "mov %[w], esi " : [w] "+m" (w) );
|
||||
#endif
|
||||
|
||||
if (widgetIndex == WIDX_CLOSE)
|
||||
window_close(w);
|
||||
else if (widgetIndex >= WIDX_TAB_1 && widgetIndex <= WIDX_TAB_6)
|
||||
window_finances_set_page(w, widgetIndex - WIDX_TAB_1);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0069CBA6
|
||||
*/
|
||||
static void window_finances_summary_update(rct_window *w)
|
||||
{
|
||||
// Tab animation
|
||||
if (++w->var_48E >= window_finances_tab_animation_loops[w->page])
|
||||
w->var_48E = 0;
|
||||
widget_invalidate(w->classification, w->number, WIDX_TAB_1);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0069C732
|
||||
*/
|
||||
static void window_finances_summary_invalidate()
|
||||
{
|
||||
rct_window *w;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov w, esi
|
||||
#else
|
||||
__asm__ ( "mov %[w], esi " : [w] "+m" (w) );
|
||||
#endif
|
||||
|
||||
if (w->widgets != window_finances_page_widgets[0]) {
|
||||
w->widgets = window_finances_page_widgets[0];
|
||||
window_init_scroll_widgets(w);
|
||||
}
|
||||
|
||||
window_finances_set_pressed_tab(w);
|
||||
RCT2_GLOBAL(0x013CE952 + 6, money32) = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_LOAN, money32);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Common
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0069CAC5
|
||||
*/
|
||||
static void window_finances_set_page(rct_window *w, int page)
|
||||
{
|
||||
w->page = page;
|
||||
w->var_48E = 0;
|
||||
if (w->viewport != NULL) {
|
||||
w->viewport->width = 0;
|
||||
w->viewport = NULL;
|
||||
}
|
||||
|
||||
w->enabled_widgets = window_finances_page_enabled_widgets[page];
|
||||
w->var_020 = RCT2_ADDRESS(0x00988E3C, uint32)[page];
|
||||
w->widgets = window_finances_page_widgets[page];
|
||||
w->disabled_widgets = 0;
|
||||
|
||||
window_invalidate(w);
|
||||
if (w->page == WINDOW_FINANCES_PAGE_RESEARCH) {
|
||||
w->width = 320;
|
||||
w->height = 207;
|
||||
} else {
|
||||
w->width = 530;
|
||||
w->height = 257;
|
||||
}
|
||||
RCT2_CALLPROC_X(w->event_handlers[WE_RESIZE], 0, 0, 0, 0, (int)w, 0, 0);
|
||||
RCT2_CALLPROC_X(w->event_handlers[WE_INVALIDATE], 0, 0, 0, 0, (int)w, 0, 0);
|
||||
|
||||
window_init_scroll_widgets(w);
|
||||
window_invalidate(w);
|
||||
}
|
||||
|
||||
static void window_finances_set_pressed_tab(rct_window *w)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < WINDOW_FINANCES_PAGE_COUNT; i++)
|
||||
w->pressed_widgets &= ~(1 << (WIDX_TAB_1 + i));
|
||||
w->pressed_widgets |= 1LL << (WIDX_TAB_1 + w->page);
|
||||
}
|
||||
|
||||
#pragma endregion
|
|
@ -111,7 +111,7 @@ static rct_widget window_footpath_widgets[] = {
|
|||
static void window_footpath_emptysub() { }
|
||||
static void window_footpath_close();
|
||||
static void window_footpath_mouseup();
|
||||
static void window_footpath_mousedown();
|
||||
static void window_footpath_mousedown(int widgetIndex, rct_window*w, rct_widget* widget);
|
||||
static void window_footpath_dropdown();
|
||||
static void window_footpath_update(rct_window *w);
|
||||
static void window_footpath_toolupdate();
|
||||
|
@ -307,31 +307,8 @@ static void window_footpath_mouseup()
|
|||
*
|
||||
* rct2: 0x006A7EC5
|
||||
*/
|
||||
static void window_footpath_mousedown()
|
||||
static void window_footpath_mousedown(int widgetIndex, rct_window*w, rct_widget* widget)
|
||||
{
|
||||
short widgetIndex;
|
||||
rct_window *w;
|
||||
rct_widget *widget;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov widgetIndex, dx
|
||||
#else
|
||||
__asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) );
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov w, esi
|
||||
#else
|
||||
__asm__ ( "mov %[w], esi " : [w] "+m" (w) );
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov widget, edi
|
||||
#else
|
||||
__asm__ ( "mov %[widget], edi " : [widget] "+m" (widget) );
|
||||
#endif
|
||||
|
||||
|
||||
switch (widgetIndex) {
|
||||
case WIDX_FOOTPATH_TYPE:
|
||||
window_footpath_show_footpath_types_dialog(w, widget, 0);
|
||||
|
@ -894,7 +871,7 @@ static void window_footpath_place_path_at_point(int x, int y)
|
|||
// bp = 0x009DEA62
|
||||
// dx = 0x009DEA60
|
||||
// cx = 0x009DEA5E
|
||||
sound_play_panned(6, 0x8001);
|
||||
sound_play_panned(SOUND_PLACE_ITEM, 0x8001);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -172,7 +172,7 @@ static void window_game_bottom_toolbar_mouseup()
|
|||
case WIDX_LEFT_OUTSET:
|
||||
case WIDX_MONEY:
|
||||
if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & 0x800))
|
||||
RCT2_CALLPROC_EBPSAFE(0x0069DDF1);
|
||||
window_finances_open();
|
||||
break;
|
||||
case WIDX_GUESTS:
|
||||
window_park_guests_open();
|
||||
|
@ -498,10 +498,20 @@ static void window_game_bottom_toolbar_draw_right_panel(rct_drawpixelinfo *dpi,
|
|||
y = window_game_bottom_toolbar_widgets[WIDX_RIGHT_OUTSET].top + w->y + 2;
|
||||
|
||||
// Date
|
||||
RCT2_GLOBAL(0x013CE952, short) = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, sint16);
|
||||
char *freeStr = (char*)0x009BC677;
|
||||
freeStr[0] = FORMAT_STRINGID;
|
||||
freeStr[1] = ' ';
|
||||
freeStr[2] = FORMAT_MONTHYEAR;
|
||||
freeStr[3] = 0;
|
||||
|
||||
int month = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, sint16) & 7;
|
||||
int day = ((RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_TICKS, uint16) * days_in_month[month]) >> 16) & 0xFF;
|
||||
|
||||
RCT2_GLOBAL(0x013CE952, short) = STR_DATE_DAY_1 + day;
|
||||
RCT2_GLOBAL(0x013CE954, short) = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, sint16);
|
||||
gfx_draw_string_centred(
|
||||
dpi,
|
||||
1845,
|
||||
3165,
|
||||
x,
|
||||
y,
|
||||
(RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass) == 2 && RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, sint32) == WIDX_DATE ? 2 : w->colours[0] & 0x7F),
|
||||
|
|
|
@ -78,7 +78,7 @@ static rct_widget window_game_top_toolbar_widgets[] = {
|
|||
|
||||
static void window_game_top_toolbar_emptysub() { }
|
||||
static void window_game_top_toolbar_mouseup();
|
||||
static void window_game_top_toolbar_mousedown();
|
||||
static void window_game_top_toolbar_mousedown(int widgetIndex, rct_window*w, rct_widget* widget);
|
||||
static void window_game_top_toolbar_dropdown();
|
||||
static void window_game_top_toolbar_invalidate();
|
||||
static void window_game_top_toolbar_paint();
|
||||
|
@ -166,6 +166,11 @@ static void window_game_top_toolbar_mouseup()
|
|||
game_do_command(0, 1, 0, 0, 2, 0, 0);
|
||||
break;
|
||||
case WIDX_FASTFORWARD:
|
||||
// This is an excellent place to add in debugging statements and
|
||||
// print routines, that will be triggered when you press the
|
||||
// button in the game. Use "git update-index --skip-worktree
|
||||
// src/window_game_top_toolbar" to avoid committing these changes to
|
||||
// version control.
|
||||
window_cheats_open();
|
||||
break;
|
||||
|
||||
|
@ -254,32 +259,10 @@ static void window_game_top_toolbar_mouseup()
|
|||
*
|
||||
* rct2: 0x0066CA3B
|
||||
*/
|
||||
static void window_game_top_toolbar_mousedown()
|
||||
static void window_game_top_toolbar_mousedown(int widgetIndex, rct_window*w, rct_widget* widget)
|
||||
{
|
||||
short widgetIndex;
|
||||
rct_window *w;
|
||||
rct_widget *widget;
|
||||
rct_viewport *mainViewport;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov widgetIndex, dx
|
||||
#else
|
||||
__asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) );
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov w, esi
|
||||
#else
|
||||
__asm__ ( "mov %[w], esi " : [w] "+m" (w) );
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov widget, edi
|
||||
#else
|
||||
__asm__ ( "mov %[widget], edi " : [widget] "+m" (widget) );
|
||||
#endif
|
||||
|
||||
|
||||
if (widgetIndex == WIDX_FILE_MENU) {
|
||||
gDropdownItemsFormat[0] = 882;
|
||||
gDropdownItemsFormat[1] = 883;
|
||||
|
@ -384,30 +367,7 @@ static void window_game_top_toolbar_dropdown()
|
|||
break;
|
||||
case 1: // save game
|
||||
tool_cancel();
|
||||
{
|
||||
int eax, ebx, ecx, edx, esi, edi, ebp;
|
||||
RCT2_CALLFUNC_X(0x006750E9, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
|
||||
if (eax == 0) {
|
||||
gfx_invalidate_screen();
|
||||
break;
|
||||
}
|
||||
|
||||
char *src = (char*)0x0141EF67;
|
||||
do {
|
||||
src++;
|
||||
} while (*src != '.' && *src != '\0');
|
||||
strcpy(src, ".SV6");
|
||||
strcpy((char*) RCT2_ADDRESS_SAVED_GAMES_PATH_2, (char*) 0x0141EF68);
|
||||
|
||||
eax = 0;
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & 8)
|
||||
eax |= 1;
|
||||
RCT2_CALLPROC_X(0x006754F5, eax, 0, 0, 0, 0, 0, 0);
|
||||
// check success?
|
||||
|
||||
game_do_command(0, 1047, 0, -1, 0, 0, 0);
|
||||
gfx_invalidate_screen();
|
||||
}
|
||||
save_game();
|
||||
break;
|
||||
case 3: // about
|
||||
window_about_open();
|
||||
|
|
|
@ -73,7 +73,7 @@ static rct_widget window_guest_list_widgets[] = {
|
|||
static void window_guest_list_emptysub() { }
|
||||
static void window_guest_list_mouseup();
|
||||
static void window_guest_list_resize();
|
||||
static void window_guest_list_mousedown();
|
||||
static void window_guest_list_mousedown(int widgetIndex, rct_window*w, rct_widget* widget);
|
||||
static void window_guest_list_dropdown();
|
||||
static void window_guest_list_update(rct_window *w);
|
||||
static void window_guest_list_scrollgetsize();
|
||||
|
@ -241,32 +241,9 @@ static void window_guest_list_resize()
|
|||
*
|
||||
* rct2: 0x00699AC4
|
||||
*/
|
||||
static void window_guest_list_mousedown()
|
||||
static void window_guest_list_mousedown(int widgetIndex, rct_window*w, rct_widget* widget)
|
||||
{
|
||||
int i;
|
||||
short widgetIndex;
|
||||
rct_window *w;
|
||||
rct_widget *widget;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov widgetIndex, dx
|
||||
#else
|
||||
__asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) );
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov w, esi
|
||||
#else
|
||||
__asm__ ( "mov %[w], esi " : [w] "+m" (w) );
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov widget, edi
|
||||
#else
|
||||
__asm__ ( "mov %[widget], edi " : [widget] "+m" (widget) );
|
||||
#endif
|
||||
|
||||
|
||||
switch (widgetIndex) {
|
||||
case WIDX_TAB_1:
|
||||
case WIDX_TAB_2:
|
||||
|
@ -388,7 +365,7 @@ static void window_guest_list_update(rct_window *w)
|
|||
*/
|
||||
static void window_guest_list_scrollgetsize()
|
||||
{
|
||||
int i, y, numGuests, spriteIdx;
|
||||
int i, y, numGuests, spriteIndex;
|
||||
rct_window *w;
|
||||
rct_peep *peep;
|
||||
|
||||
|
@ -404,13 +381,7 @@ static void window_guest_list_scrollgetsize()
|
|||
// Count the number of guests
|
||||
numGuests = 0;
|
||||
|
||||
spriteIdx = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16);
|
||||
while (spriteIdx != SPRITE_INDEX_NULL) {
|
||||
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[spriteIdx].peep);
|
||||
spriteIdx = peep->next;
|
||||
|
||||
if (peep->type != PEEP_TYPE_GUEST)
|
||||
continue;
|
||||
FOR_ALL_GUESTS(spriteIndex, peep) {
|
||||
if (peep->var_2A != 0)
|
||||
continue;
|
||||
if (_window_guest_list_selected_filter != -1)
|
||||
|
@ -470,7 +441,7 @@ static void window_guest_list_scrollgetsize()
|
|||
*/
|
||||
static void window_guest_list_scrollmousedown()
|
||||
{
|
||||
int i, spriteIdx;
|
||||
int i, spriteIndex;
|
||||
short y;
|
||||
rct_window *w;
|
||||
rct_peep *peep;
|
||||
|
@ -492,13 +463,7 @@ static void window_guest_list_scrollmousedown()
|
|||
case PAGE_INDIVIDUAL:
|
||||
i = y / 10;
|
||||
i += _window_guest_list_selected_page * 3173;
|
||||
spriteIdx = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16);
|
||||
while (spriteIdx != SPRITE_INDEX_NULL) {
|
||||
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[spriteIdx].peep);
|
||||
spriteIdx = peep->next;
|
||||
|
||||
if (peep->type != PEEP_TYPE_GUEST)
|
||||
continue;
|
||||
FOR_ALL_GUESTS(spriteIndex, peep) {
|
||||
if (peep->var_2A != 0)
|
||||
continue;
|
||||
if (_window_guest_list_selected_filter != -1)
|
||||
|
@ -683,7 +648,7 @@ static void window_guest_list_paint()
|
|||
static void window_guest_list_scrollpaint()
|
||||
{
|
||||
int eax, ebx, ecx, edx, esi, edi, ebp;
|
||||
int spriteIdx, format, numGuests, i, j, y;
|
||||
int spriteIndex, format, numGuests, i, j, y;
|
||||
rct_window *w;
|
||||
rct_drawpixelinfo *dpi;
|
||||
rct_peep *peep;
|
||||
|
@ -711,13 +676,7 @@ static void window_guest_list_scrollpaint()
|
|||
y = _window_guest_list_selected_page * -0x7BF2;
|
||||
|
||||
// For each guest
|
||||
spriteIdx = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16);
|
||||
while (spriteIdx != SPRITE_INDEX_NULL) {
|
||||
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[spriteIdx].peep);
|
||||
spriteIdx = peep->next;
|
||||
|
||||
if (peep->type != PEEP_TYPE_GUEST)
|
||||
continue;
|
||||
FOR_ALL_GUESTS(spriteIndex, peep) {
|
||||
peep->var_0C &= ~0x200;
|
||||
if (peep->var_2A != 0)
|
||||
continue;
|
||||
|
@ -772,9 +731,9 @@ static void window_guest_list_scrollpaint()
|
|||
thought = &peep->thoughts[j];
|
||||
if (thought->type == PEEP_THOUGHT_TYPE_NONE)
|
||||
break;
|
||||
if (thought->pad_3 == 0)
|
||||
if (thought->var_2 == 0)
|
||||
continue;
|
||||
if (thought->pad_3 > 5)
|
||||
if (thought->var_2 > 5)
|
||||
break;
|
||||
|
||||
ebx = thought->type;
|
||||
|
@ -878,7 +837,7 @@ static int sub_69B7EA(rct_peep *peep, int *outEAX)
|
|||
*outEAX = eax;
|
||||
return ebx & 0xFFFF;
|
||||
case VIEW_THOUGHTS:
|
||||
if (peep->thoughts[0].pad_3 <= 5) {
|
||||
if (peep->thoughts[0].var_2 <= 5) {
|
||||
eax = peep->thoughts[0].item;
|
||||
ebx = peep->thoughts[0].type;
|
||||
if (peep->thoughts[0].type != PEEP_THOUGHT_TYPE_NONE) {
|
||||
|
@ -907,7 +866,7 @@ static int sub_69B7EA(rct_peep *peep, int *outEAX)
|
|||
*/
|
||||
static void window_guest_list_find_groups()
|
||||
{
|
||||
int spriteIdx, spriteIdx2, groupIndex, faceIndex;
|
||||
int spriteIndex, spriteIndex2, groupIndex, faceIndex;
|
||||
rct_peep *peep, *peep2;
|
||||
|
||||
int eax = RCT2_GLOBAL(0x00F663AC, uint32) & 0xFFFFFF00;
|
||||
|
@ -921,24 +880,13 @@ static void window_guest_list_find_groups()
|
|||
_window_guest_list_num_groups = 0;
|
||||
|
||||
// Set all guests to unassigned
|
||||
spriteIdx = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16);
|
||||
while (spriteIdx != SPRITE_INDEX_NULL) {
|
||||
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[spriteIdx].peep);
|
||||
spriteIdx = peep->next;
|
||||
|
||||
if (peep->type != PEEP_TYPE_GUEST || peep->var_2A != 0)
|
||||
continue;
|
||||
|
||||
peep->var_0C |= (1 << 8);
|
||||
}
|
||||
FOR_ALL_GUESTS(spriteIndex, peep)
|
||||
if (peep->var_2A == 0)
|
||||
peep->var_0C |= (1 << 8);
|
||||
|
||||
// For each guest / group
|
||||
spriteIdx = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16);
|
||||
while (spriteIdx != SPRITE_INDEX_NULL) {
|
||||
peep = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[spriteIdx].peep);
|
||||
spriteIdx = peep->next;
|
||||
|
||||
if (peep->type != PEEP_TYPE_GUEST || peep->var_2A != 0 || !(peep->var_0C & (1 << 8)))
|
||||
FOR_ALL_GUESTS(spriteIndex, peep) {
|
||||
if (peep->var_2A != 0 || !(peep->var_0C & (1 << 8)))
|
||||
continue;
|
||||
|
||||
// New group, cap at 240 though
|
||||
|
@ -961,12 +909,8 @@ static void window_guest_list_find_groups()
|
|||
_window_guest_list_groups_guest_faces[faceIndex++] = get_guest_face_sprite_small(peep) - 5486;
|
||||
|
||||
// Find more peeps that belong to same group
|
||||
spriteIdx2 = peep->next;
|
||||
while (spriteIdx2 != SPRITE_INDEX_NULL) {
|
||||
peep2 = &(RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite)[spriteIdx2].peep);
|
||||
spriteIdx2 = peep2->next;
|
||||
|
||||
if (peep2->type != PEEP_TYPE_GUEST || peep2->var_2A != 0 || !(peep2->var_0C & (1 << 8)))
|
||||
FOR_ALL_GUESTS(spriteIndex2, peep2) {
|
||||
if (peep2->var_2A != 0 || !(peep2->var_0C & (1 << 8)))
|
||||
continue;
|
||||
|
||||
// Get and check if in same group
|
||||
|
|
|
@ -52,7 +52,7 @@ static rct_widget window_land_widgets[] = {
|
|||
static void window_land_emptysub() { }
|
||||
static void window_land_close();
|
||||
static void window_land_mouseup();
|
||||
static void window_land_mousedown();
|
||||
static void window_land_mousedown(int widgetIndex, rct_window*w, rct_widget* widget);
|
||||
static void window_land_dropdown();
|
||||
static void window_land_update(rct_window *w);
|
||||
static void window_land_invalidate();
|
||||
|
@ -217,31 +217,9 @@ static void window_land_mouseup()
|
|||
*
|
||||
* rct2: 0x0066407B
|
||||
*/
|
||||
static void window_land_mousedown()
|
||||
static void window_land_mousedown(int widgetIndex, rct_window*w, rct_widget* widget)
|
||||
{
|
||||
int i;
|
||||
short widgetIndex;
|
||||
rct_window *w;
|
||||
rct_widget *widget;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov widgetIndex, dx
|
||||
#else
|
||||
__asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) );
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov w, esi
|
||||
#else
|
||||
__asm__ ( "mov %[w], esi " : [w] "+m" (w) );
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov widget, edi
|
||||
#else
|
||||
__asm__ ( "mov %[widget], edi " : [widget] "+m" (widget) );
|
||||
#endif
|
||||
|
||||
|
||||
switch (widgetIndex) {
|
||||
case WIDX_FLOOR:
|
||||
|
|
|
@ -77,7 +77,7 @@ static rct_widget window_map_widgets[] = {
|
|||
static void window_map_emptysub() { }
|
||||
static void window_map_close();
|
||||
static void window_map_mouseup();
|
||||
static void window_map_mousedown();
|
||||
static void window_map_mousedown(int widgetIndex, rct_window*w, rct_widget* widget);
|
||||
static void window_map_update(rct_window *w);
|
||||
static void window_map_scrollgetsize();
|
||||
static void window_map_scrollmousedown();
|
||||
|
@ -228,7 +228,7 @@ static void window_map_mouseup()
|
|||
*
|
||||
* rct2: 0x0068D040
|
||||
*/
|
||||
static void window_map_mousedown()
|
||||
static void window_map_mousedown(int widgetIndex, rct_window*w, rct_widget* widget)
|
||||
{
|
||||
RCT2_CALLPROC_EBPSAFE(0x0068D040);
|
||||
}
|
||||
|
|
|
@ -161,7 +161,7 @@ static void window_news_update(rct_window *w)
|
|||
return;
|
||||
|
||||
window_invalidate(w);
|
||||
sound_play_panned(5, w->x + (w->width / 2));
|
||||
sound_play_panned(SOUND_CLICK_2, w->x + (w->width / 2));
|
||||
|
||||
newsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item);
|
||||
j = w->var_480;
|
||||
|
@ -282,7 +282,7 @@ static void window_news_scrollmousedown()
|
|||
w->var_482 = buttonIndex;
|
||||
w->var_484 = 4;
|
||||
window_invalidate(w);
|
||||
sound_play_panned(4, w->x + (w->width / 2));
|
||||
sound_play_panned(SOUND_CLICK_1, w->x + (w->width / 2));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include "window.h"
|
||||
#include "window_dropdown.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum WINDOW_OPTIONS_WIDGET_IDX {
|
||||
WIDX_BACKGROUND,
|
||||
WIDX_TITLE,
|
||||
|
@ -103,7 +105,7 @@ static rct_widget window_options_widgets[] = {
|
|||
|
||||
static void window_options_emptysub() { }
|
||||
static void window_options_mouseup();
|
||||
static void window_options_mousedown();
|
||||
static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget* widget);
|
||||
static void window_options_dropdown();
|
||||
static void window_options_update(rct_window *w);
|
||||
static void window_options_paint();
|
||||
|
@ -221,6 +223,7 @@ static void window_options_mouseup()
|
|||
break;
|
||||
case WIDX_SCREEN_EDGE_SCROLLING:
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_EDGE_SCROLLING, uint8) ^= 1;
|
||||
gGeneral_config.edge_scrolling ^= 1;
|
||||
config_save();
|
||||
window_invalidate(w);
|
||||
break;
|
||||
|
@ -246,11 +249,15 @@ static void window_options_mouseup()
|
|||
break;
|
||||
case WIDX_TILE_SMOOTHING_CHECKBOX:
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) ^= CONFIG_FLAG_DISABLE_SMOOTH_LANDSCAPE;
|
||||
gGeneral_config.landscape_smoothing = !(RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8)
|
||||
& CONFIG_FLAG_DISABLE_SMOOTH_LANDSCAPE);
|
||||
config_save();
|
||||
gfx_invalidate_screen();
|
||||
break;
|
||||
case WIDX_GRIDLINES_CHECKBOX:
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) ^= CONFIG_FLAG_ALWAYS_SHOW_GRIDLINES;
|
||||
gGeneral_config.always_show_gridlines = RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8)
|
||||
& CONFIG_FLAG_ALWAYS_SHOW_GRIDLINES;
|
||||
config_save();
|
||||
gfx_invalidate_screen();
|
||||
|
||||
|
@ -263,12 +270,15 @@ static void window_options_mouseup()
|
|||
break;
|
||||
case WIDX_SAVE_PLUGIN_DATA_CHECKBOX:
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) ^= CONFIG_FLAG_SAVE_PLUGIN_DATA;
|
||||
gGeneral_config.save_plugin_data = !(RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8)
|
||||
& CONFIG_FLAG_SAVE_PLUGIN_DATA);
|
||||
config_save();
|
||||
window_invalidate(w);
|
||||
break;
|
||||
case WIDX_SOUND_SW_BUFFER_CHECKBOX:
|
||||
pause_sounds();
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_SOUND_SW_BUFFER, uint8) ^= 1;
|
||||
gSound_config.forced_software_buffering ^= 1;
|
||||
config_save();
|
||||
unpause_sounds();
|
||||
window_invalidate(w);
|
||||
|
@ -280,25 +290,9 @@ static void window_options_mouseup()
|
|||
*
|
||||
* rct2: 0x006BB01B
|
||||
*/
|
||||
static void window_options_mousedown()
|
||||
static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget* widget)
|
||||
{
|
||||
int num_items, i;
|
||||
short widgetIndex;
|
||||
rct_window *w;
|
||||
rct_widget *widget;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov widgetIndex, dx
|
||||
#else
|
||||
__asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) );
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov w, esi
|
||||
#else
|
||||
__asm__ ( "mov %[w], esi " : [w] "+m" (w) );
|
||||
#endif
|
||||
|
||||
|
||||
widget = &w->widgets[widgetIndex - 1];
|
||||
|
||||
|
@ -309,7 +303,7 @@ static void window_options_mousedown()
|
|||
// populate the list with the sound devices
|
||||
for (i = 0; i < gAudioDeviceCount; i++) {
|
||||
gDropdownItemsFormat[i] = 1142;
|
||||
gDropdownItemsArgs[i] = 1170 | ((uint64)gAudioDevices[i].name << 16);
|
||||
gDropdownItemsArgs[i] = 1170 | ((uint64)(intptr_t)gAudioDevices[i].name << 16);
|
||||
}
|
||||
gDropdownItemsChecked |= (1 << RCT2_GLOBAL(0x9AF280, uint32));
|
||||
break;
|
||||
|
@ -443,9 +437,12 @@ static void window_options_dropdown()
|
|||
case WIDX_HEIGHT_LABELS_DROPDOWN:
|
||||
// reset flag and set it to 1 if height as units is selected
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) &= ~CONFIG_FLAG_SHOW_HEIGHT_AS_UNITS;
|
||||
gGeneral_config.show_height_as_units = 0;
|
||||
|
||||
if (dropdownIndex == 0)
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) |= CONFIG_FLAG_SHOW_HEIGHT_AS_UNITS;
|
||||
if (dropdownIndex == 0) {
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) |= CONFIG_FLAG_SHOW_HEIGHT_AS_UNITS;
|
||||
gGeneral_config.show_height_as_units = 1;
|
||||
}
|
||||
|
||||
window_options_update_height_markers();
|
||||
break;
|
||||
|
@ -461,17 +458,20 @@ static void window_options_dropdown()
|
|||
// TODO: no clue what this does (and if it's correct)
|
||||
RCT2_GLOBAL(0x009AAC75, uint8) = RCT2_GLOBAL(0x009AF601 + dropdownIndex, uint8);
|
||||
RCT2_GLOBAL(0x009AAC76, uint8) = RCT2_GLOBAL(0x009AF604 + dropdownIndex, uint8);
|
||||
|
||||
gSound_config.sound_quality = (sint8)dropdownIndex;
|
||||
config_save();
|
||||
window_invalidate(w);
|
||||
break;
|
||||
case WIDX_CURRENCY_DROPDOWN:
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_CURRENCY, uint8) = dropdownIndex | 0xC0;
|
||||
gGeneral_config.currency_format = (sint8)dropdownIndex;
|
||||
config_save();
|
||||
gfx_invalidate_screen();
|
||||
break;
|
||||
case WIDX_DISTANCE_DROPDOWN:
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, uint8) = (uint8)dropdownIndex;
|
||||
gGeneral_config.measurement_format = (sint8)dropdownIndex;
|
||||
config_save();
|
||||
window_options_update_height_markers();
|
||||
break;
|
||||
case WIDX_RESOLUTION_DROPDOWN:
|
||||
|
@ -486,6 +486,7 @@ static void window_options_dropdown()
|
|||
case WIDX_TEMPERATURE_DROPDOWN:
|
||||
if (dropdownIndex != RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_TEMPERATURE, uint8)) {
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_TEMPERATURE, uint8) = (uint8)dropdownIndex;
|
||||
gGeneral_config.temperature_format = (sint8)dropdownIndex;
|
||||
config_save();
|
||||
gfx_invalidate_screen();
|
||||
}
|
||||
|
@ -676,4 +677,4 @@ static void window_options_update_height_markers()
|
|||
|
||||
config_save();
|
||||
gfx_invalidate_screen();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include <string.h>
|
||||
#include "addresses.h"
|
||||
#include "award.h"
|
||||
#include "config.h"
|
||||
#include "date.h"
|
||||
#include "game.h"
|
||||
|
@ -217,7 +218,7 @@ static void window_park_emptysub() { }
|
|||
static void window_park_entrance_close();
|
||||
static void window_park_entrance_mouseup();
|
||||
static void window_park_entrance_resize();
|
||||
static void window_park_entrance_mousedown();
|
||||
static void window_park_entrance_mousedown(int widgetIndex, rct_window*w, rct_widget* widget);
|
||||
static void window_park_entrance_dropdown();
|
||||
static void window_park_entrance_update(rct_window *w);
|
||||
static void window_park_entrance_toolupdate();
|
||||
|
@ -242,7 +243,7 @@ static void window_park_guests_paint();
|
|||
|
||||
static void window_park_price_mouseup();
|
||||
static void window_park_price_resize();
|
||||
static void window_park_price_mousedown();
|
||||
static void window_park_price_mousedown(int widgetIndex, rct_window*w, rct_widget* widget);
|
||||
static void window_park_price_update(rct_window *w);
|
||||
static void window_park_price_invalidate();
|
||||
static void window_park_price_paint();
|
||||
|
@ -730,31 +731,8 @@ static void window_park_entrance_resize()
|
|||
*
|
||||
* rct2: 0x006681BF
|
||||
*/
|
||||
static void window_park_entrance_mousedown()
|
||||
static void window_park_entrance_mousedown(int widgetIndex, rct_window*w, rct_widget* widget)
|
||||
{
|
||||
short widgetIndex;
|
||||
rct_window *w;
|
||||
rct_widget *widget;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov widgetIndex, dx
|
||||
#else
|
||||
__asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) );
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov w, esi
|
||||
#else
|
||||
__asm__ ( "mov %[w], esi " : [w] "+m" (w) );
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov widget, edi
|
||||
#else
|
||||
__asm__ ( "mov %[widget], edi " : [widget] "+m" (widget) );
|
||||
#endif
|
||||
|
||||
|
||||
if (widgetIndex == WIDX_OPEN_OR_CLOSE) {
|
||||
gDropdownItemsFormat[0] = 1142;
|
||||
gDropdownItemsFormat[1] = 1142;
|
||||
|
@ -1616,24 +1594,9 @@ static void window_park_price_resize()
|
|||
*
|
||||
* rct2: 0x0066902C
|
||||
*/
|
||||
static void window_park_price_mousedown()
|
||||
static void window_park_price_mousedown(int widgetIndex, rct_window*w, rct_widget* widget)
|
||||
{
|
||||
int newFee;
|
||||
short widgetIndex;
|
||||
rct_window *w;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov widgetIndex, dx
|
||||
#else
|
||||
__asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) );
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov w, esi
|
||||
#else
|
||||
__asm__ ( "mov %[w], esi " : [w] "+m" (w) );
|
||||
#endif
|
||||
|
||||
|
||||
switch (widgetIndex) {
|
||||
case WIDX_CLOSE:
|
||||
|
@ -2258,13 +2221,13 @@ static void window_park_awards_paint()
|
|||
y = w->y + window_park_awards_widgets[WIDX_PAGE_BACKGROUND].top + 4;
|
||||
|
||||
count = 0;
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (i = 0; i < MAX_AWARDS; i++) {
|
||||
award = &RCT2_ADDRESS(RCT2_ADDRESS_AWARD_LIST, rct_award)[i];
|
||||
if (award->time == 0)
|
||||
continue;
|
||||
|
||||
gfx_draw_sprite(dpi, SPR_AWARD_MOST_UNTIDY + award->type, x, y);
|
||||
gfx_draw_string_left_wrapped(dpi, (void*)STR_AWARD_MOST_UNTIDY, x + 34, y + 6, 180, 0, 0);
|
||||
gfx_draw_string_left_wrapped(dpi, NULL, x + 34, y + 6, 180, STR_AWARD_MOST_UNTIDY + award->type, 0);
|
||||
|
||||
y += 32;
|
||||
count++;
|
||||
|
|
|
@ -68,7 +68,7 @@ static rct_widget window_ride_list_widgets[] = {
|
|||
static void window_ride_list_emptysub() { }
|
||||
static void window_ride_list_mouseup();
|
||||
static void window_ride_list_resize();
|
||||
static void window_ride_list_mousedown();
|
||||
static void window_ride_list_mousedown(int widgetIndex, rct_window*w, rct_widget* widget);
|
||||
static void window_ride_list_dropdown();
|
||||
static void window_ride_list_update(rct_window *w);
|
||||
static void window_ride_list_scrollgetsize();
|
||||
|
@ -248,31 +248,9 @@ static void window_ride_list_resize()
|
|||
*
|
||||
* rct2: 0x006B3532
|
||||
*/
|
||||
static void window_ride_list_mousedown()
|
||||
static void window_ride_list_mousedown(int widgetIndex, rct_window*w, rct_widget* widget)
|
||||
{
|
||||
int numItems, i;
|
||||
short widgetIndex;
|
||||
rct_window *w;
|
||||
rct_widget *widget;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov widgetIndex, dx
|
||||
#else
|
||||
__asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) );
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov w, esi
|
||||
#else
|
||||
__asm__ ( "mov %[w], esi " : [w] "+m" (w) );
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov widget, edi
|
||||
#else
|
||||
__asm__ ( "mov %[widget], edi " : [widget] "+m" (widget) );
|
||||
#endif
|
||||
|
||||
|
||||
if (widgetIndex == WIDX_OPEN_CLOSE_ALL) {
|
||||
gDropdownItemsFormat[0] = STR_CLOSE_ALL;
|
||||
|
@ -695,10 +673,7 @@ static void window_ride_list_refresh_list(rct_window *w)
|
|||
rct_ride *ride, *otherRide;
|
||||
|
||||
countA = countB = 0;
|
||||
for (i = 0; i < MAX_RIDES; i++) {
|
||||
ride = &(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[i]);
|
||||
if (ride->type == RIDE_TYPE_NULL)
|
||||
continue;
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
if (w->page != gRideClassifications[ride->type])
|
||||
continue;
|
||||
|
||||
|
@ -717,10 +692,7 @@ static void window_ride_list_refresh_list(rct_window *w)
|
|||
|
||||
w->var_476 = countA;
|
||||
j = 0;
|
||||
for (i = 0; i < MAX_RIDES; i++) {
|
||||
ride = &(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[i]);
|
||||
if (ride->type == RIDE_TYPE_NULL)
|
||||
continue;
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
if (w->page != gRideClassifications[ride->type])
|
||||
continue;
|
||||
|
||||
|
@ -844,10 +816,7 @@ static void window_ride_list_close_all(rct_window *w)
|
|||
int i;
|
||||
rct_ride *ride;
|
||||
|
||||
for (i = 0; i < MAX_RIDES; i++) {
|
||||
ride = &RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[i];
|
||||
if (ride->type == RIDE_TYPE_NULL)
|
||||
continue;
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
if (w->page != gRideClassifications[ride->type])
|
||||
continue;
|
||||
if (ride->status == RIDE_STATUS_CLOSED)
|
||||
|
@ -864,10 +833,7 @@ static void window_ride_list_open_all(rct_window *w)
|
|||
int i;
|
||||
rct_ride *ride;
|
||||
|
||||
for (i = 0; i < MAX_RIDES; i++) {
|
||||
ride = &RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride)[i];
|
||||
if (ride->type == RIDE_TYPE_NULL)
|
||||
continue;
|
||||
FOR_ALL_RIDES(i, ride) {
|
||||
if (w->page != gRideClassifications[ride->type])
|
||||
continue;
|
||||
if (ride->status == RIDE_STATUS_OPEN)
|
||||
|
|
|
@ -117,6 +117,12 @@ void window_save_prompt_open()
|
|||
|
||||
prompt_mode = RCT2_GLOBAL(RCT2_ADDRESS_SAVE_PROMPT_MODE, uint16);
|
||||
|
||||
// do not show save prompt if we're in the title demo and click on load game
|
||||
if (prompt_mode != PM_QUIT && RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TITLE_DEMO) {
|
||||
game_load_or_quit_no_save_prompt();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if window is already open
|
||||
window = window_bring_to_front_by_id(WC_SAVE_PROMPT, 0);
|
||||
if (window == NULL) {
|
||||
|
@ -146,14 +152,13 @@ void window_save_prompt_open()
|
|||
y,
|
||||
(uint32*)window_save_prompt_events,
|
||||
WC_SAVE_PROMPT,
|
||||
0
|
||||
WF_TRANSPARENT | WF_STICK_TO_FRONT
|
||||
);
|
||||
|
||||
window->widgets = widgets;
|
||||
window->enabled_widgets = enabled_widgets;
|
||||
window_init_scroll_widgets(window);
|
||||
window->colours[0] = 154;
|
||||
window->flags |= WF_TRANSPARENT;
|
||||
|
||||
// Pause the game
|
||||
RCT2_GLOBAL(0x009DEA6E, uint8) |= 2;
|
||||
|
@ -170,6 +175,12 @@ void window_save_prompt_open()
|
|||
window_save_prompt_widgets[WIDX_LABEL].image = prompt_mode + STR_SAVE_BEFORE_LOADING;
|
||||
|
||||
if (!gGeneral_config.confirmation_prompt) {
|
||||
/* game_load_or_quit_no_save_prompt() will exec requested task and close this window
|
||||
* immediately again.
|
||||
* TODO restructure these functions when we're sure game_load_or_quit_no_save_prompt()
|
||||
* and game_load_or_quit() are not called by the original binary anymore.
|
||||
*/
|
||||
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 0x0D) {
|
||||
game_load_or_quit_no_save_prompt();
|
||||
return;
|
||||
|
@ -246,11 +257,12 @@ static void window_save_prompt_mouseup()
|
|||
} else {
|
||||
switch (widgetIndex) {
|
||||
case WIDX_SAVE:
|
||||
// TODO to avoid data loss, treat SAVE as CANCEL
|
||||
RCT2_ERROR("TODO");
|
||||
window_close(w);
|
||||
window_save_prompt_close();
|
||||
return;
|
||||
if (!save_game()) {
|
||||
// user pressed cancel
|
||||
window_close(w);
|
||||
window_save_prompt_close();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case WIDX_DONT_SAVE:
|
||||
break;
|
||||
|
|
|
@ -45,7 +45,7 @@ static rct_widget window_title_menu_widgets[] = {
|
|||
|
||||
static void window_title_menu_emptysub() { }
|
||||
static void window_title_menu_mouseup();
|
||||
static void window_title_menu_mousedown();
|
||||
static void window_title_menu_mousedown(int widgetIndex, rct_window*w, rct_widget* widget);
|
||||
static void window_title_menu_dropdown();
|
||||
static void window_title_menu_unknown17();
|
||||
static void window_title_menu_paint();
|
||||
|
@ -122,31 +122,8 @@ static void window_title_menu_mouseup()
|
|||
}
|
||||
}
|
||||
|
||||
static void window_title_menu_mousedown()
|
||||
static void window_title_menu_mousedown(int widgetIndex, rct_window*w, rct_widget* widget)
|
||||
{
|
||||
short widgetIndex;
|
||||
rct_window *w;
|
||||
rct_widget *widget;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov widgetIndex, dx
|
||||
#else
|
||||
__asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) );
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov w, esi
|
||||
#else
|
||||
__asm__ ( "mov %[w], esi " : [w] "+m" (w) );
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov widget, edi
|
||||
#else
|
||||
__asm__ ( "mov %[widget], edi " : [widget] "+m" (widget) );
|
||||
#endif
|
||||
|
||||
|
||||
if (widgetIndex == WIDX_SHOW_TUTORIAL) {
|
||||
gDropdownItemsFormat[0] = STR_TUTORIAL_BEGINNERS;
|
||||
gDropdownItemsFormat[1] = STR_TUTORIAL_CUSTOM_RIDES;
|
||||
|
|
|
@ -59,7 +59,7 @@ static void window_scenarioselect_init_tabs();
|
|||
|
||||
static void window_scenarioselect_emptysub() { }
|
||||
static void window_scenarioselect_mouseup();
|
||||
static void window_scenarioselect_mousedown();
|
||||
static void window_scenarioselect_mousedown(int widgetIndex, rct_window*w, rct_widget* widget);
|
||||
static void window_scenarioselect_scrollgetsize();
|
||||
static void window_scenarioselect_scrollmousedown();
|
||||
static void window_scenarioselect_scrollmouseover();
|
||||
|
@ -190,24 +190,8 @@ static void window_scenarioselect_mouseup()
|
|||
window_close(w);
|
||||
}
|
||||
|
||||
static void window_scenarioselect_mousedown()
|
||||
static void window_scenarioselect_mousedown(int widgetIndex, rct_window*w, rct_widget* widget)
|
||||
{
|
||||
short widgetIndex;
|
||||
rct_window *w;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov widgetIndex, dx
|
||||
#else
|
||||
__asm__ ( "mov %[widgetIndex], dx " : [widgetIndex] "+m" (widgetIndex) );
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__asm mov w, esi
|
||||
#else
|
||||
__asm__ ( "mov %[w], esi " : [w] "+m" (w) );
|
||||
#endif
|
||||
|
||||
|
||||
if (widgetIndex >= WIDX_TAB1 && widgetIndex <= WIDX_TAB5) {
|
||||
w->selected_tab = widgetIndex - 4;
|
||||
w->var_494 = 0;
|
||||
|
@ -292,7 +276,7 @@ static void window_scenarioselect_scrollmousedown()
|
|||
if (y >= 0)
|
||||
continue;
|
||||
|
||||
sound_play_panned(4, w->width / 2 + w->x);
|
||||
sound_play_panned(SOUND_CLICK_1, w->width / 2 + w->x);
|
||||
scenario_load_and_play(scenario);
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue