Merge branch 'develop' into vehicle-update

This commit is contained in:
Michał Janiszewski 2016-01-05 09:59:53 +01:00
commit 133096cd64
110 changed files with 6270 additions and 2051 deletions

View File

@ -16,16 +16,20 @@ cache:
apt: true
env:
- OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DDISABLE_HTTP_TWITCH=ON -DCMAKE_C_COMPILER=gcc-4.8 -DCMAKE_CXX_COMPILER=g++-4.8"
- OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DDISABLE_HTTP_TWITCH=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++"
- OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=OFF -DDISABLE_HTTP_TWITCH=ON -DCMAKE_C_COMPILER=gcc-4.8 -DCMAKE_CXX_COMPILER=g++-4.8"
- OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=OFF -DDISABLE_HTTP_TWITCH=OFF -DCMAKE_C_COMPILER=gcc-4.8 -DCMAKE_CXX_COMPILER=g++-4.8"
- OPENRCT2_CMAKE_OPTS="-DCMAKE_C_COMPILER=gcc-4.8 -DCMAKE_CXX_COMPILER=g++-4.8"
- OPENRCT2_CMAKE_OPTS="-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++"
- OPENRCT2_CMAKE_OPTS="-DCMAKE_TOOLCHAIN_FILE=../CMakeLists_mingw.txt" TARGET=windows
- OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DCMAKE_TOOLCHAIN_FILE=../CMakeLists_mingw.txt" TARGET=windows
- OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DDISABLE_HTTP_TWITCH=ON -DCMAKE_TOOLCHAIN_FILE=../CMakeLists_mingw.txt" TARGET=windows
- OPENRCT2_CMAKE_OPTS="-DDISABLE_HTTP_TWITCH=ON -DCMAKE_TOOLCHAIN_FILE=../CMakeLists_mingw.txt" TARGET=windows
- TARGET=docker32
- OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DDISABLE_HTTP_TWITCH=ON" TARGET=docker32
# Following entries used to be included in testing, but they only proved useful while changing things in CMake setup.
# They are meant to be used when there are changes to CMakeLists.txt
# - OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DDISABLE_HTTP_TWITCH=ON -DCMAKE_C_COMPILER=gcc-4.8 -DCMAKE_CXX_COMPILER=g++-4.8"
# - OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DDISABLE_HTTP_TWITCH=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++"
# - OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=OFF -DDISABLE_HTTP_TWITCH=ON -DCMAKE_C_COMPILER=gcc-4.8 -DCMAKE_CXX_COMPILER=g++-4.8"
# - OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=OFF -DDISABLE_HTTP_TWITCH=OFF -DCMAKE_C_COMPILER=gcc-4.8 -DCMAKE_CXX_COMPILER=g++-4.8"
# - OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DCMAKE_TOOLCHAIN_FILE=../CMakeLists_mingw.txt" TARGET=windows
# - OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DDISABLE_HTTP_TWITCH=ON -DCMAKE_TOOLCHAIN_FILE=../CMakeLists_mingw.txt" TARGET=windows
# - OPENRCT2_CMAKE_OPTS="-DDISABLE_HTTP_TWITCH=ON -DCMAKE_TOOLCHAIN_FILE=../CMakeLists_mingw.txt" TARGET=windows
sudo: required
dist: trusty

View File

@ -125,8 +125,8 @@ if (APPLE)
endif (APPLE)
# force 32bit build for now and set necessary flags to compile code as is
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -std=gnu99 -fno-omit-frame-pointer -fno-pie")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32 -std=gnu++11 -fno-omit-frame-pointer -fno-pie")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -std=gnu99 -fno-omit-frame-pointer -fno-pie -fstrict-aliasing -Werror=strict-aliasing")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32 -std=gnu++11 -fno-omit-frame-pointer -fno-pie -fstrict-aliasing -Werror=strict-aliasing")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}")

View File

@ -13,6 +13,7 @@
D41B74731C2125E50080A7B9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D41B74721C2125E50080A7B9 /* Assets.xcassets */; };
D435325F1C3472E500BA219B /* libpng.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D435325E1C3472E500BA219B /* libpng.dylib */; };
D43532601C34730200BA219B /* libpng.dylib in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D435325E1C3472E500BA219B /* libpng.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
D46105CE1C38828D00DB1EE3 /* scenario_sources.c in Sources */ = {isa = PBXBuildFile; fileRef = D46105CD1C38828D00DB1EE3 /* scenario_sources.c */; };
D4ABAB061C2F812B0080CAD9 /* news_options.c in Sources */ = {isa = PBXBuildFile; fileRef = D4ABAB051C2F812B0080CAD9 /* news_options.c */; };
D4D4DF141C34697B0048BE43 /* image_io.c in Sources */ = {isa = PBXBuildFile; fileRef = D4D4DF121C34697B0048BE43 /* image_io.c */; };
D4EC47DF1C26342F0024B507 /* addresses.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC46D61C26342F0024B507 /* addresses.c */; };
@ -90,7 +91,6 @@
D4EC48281C26342F0024B507 /* scenario_list.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC476D1C26342F0024B507 /* scenario_list.c */; };
D4EC48291C26342F0024B507 /* scenario.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC476E1C26342F0024B507 /* scenario.c */; };
D4EC482A1C26342F0024B507 /* title.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47711C26342F0024B507 /* title.c */; };
D4EC482B1C26342F0024B507 /* tutorial.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47731C26342F0024B507 /* tutorial.c */; };
D4EC482C1C26342F0024B507 /* sawyercoding.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47761C26342F0024B507 /* sawyercoding.c */; };
D4EC482D1C26342F0024B507 /* util.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47781C26342F0024B507 /* util.c */; };
D4EC482E1C26342F0024B507 /* about.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC477B1C26342F0024B507 /* about.c */; };
@ -219,6 +219,7 @@
D41B741C1C210A7A0080A7B9 /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = usr/lib/libiconv.tbd; sourceTree = SDKROOT; };
D41B74721C2125E50080A7B9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = distribution/osx/Assets.xcassets; sourceTree = SOURCE_ROOT; };
D435325E1C3472E500BA219B /* libpng.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libpng.dylib; sourceTree = "<group>"; };
D46105CD1C38828D00DB1EE3 /* scenario_sources.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = scenario_sources.c; path = src/scenario_sources.c; sourceTree = "<group>"; };
D4895D321C23EFDD000CD788 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = distribution/osx/Info.plist; sourceTree = SOURCE_ROOT; };
D497D0781C20FD52002BF46A /* OpenRCT2.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OpenRCT2.app; sourceTree = BUILT_PRODUCTS_DIR; };
D4ABAB051C2F812B0080CAD9 /* news_options.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = news_options.c; sourceTree = "<group>"; };
@ -370,8 +371,6 @@
D4EC47701C26342F0024B507 /* sprites.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sprites.h; path = src/sprites.h; sourceTree = "<group>"; };
D4EC47711C26342F0024B507 /* title.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = title.c; path = src/title.c; sourceTree = "<group>"; };
D4EC47721C26342F0024B507 /* title.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = title.h; path = src/title.h; sourceTree = "<group>"; };
D4EC47731C26342F0024B507 /* tutorial.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tutorial.c; path = src/tutorial.c; sourceTree = "<group>"; };
D4EC47741C26342F0024B507 /* tutorial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tutorial.h; path = src/tutorial.h; sourceTree = "<group>"; };
D4EC47761C26342F0024B507 /* sawyercoding.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sawyercoding.c; sourceTree = "<group>"; };
D4EC47771C26342F0024B507 /* sawyercoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sawyercoding.h; sourceTree = "<group>"; };
D4EC47781C26342F0024B507 /* util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = util.c; sourceTree = "<group>"; };
@ -626,13 +625,12 @@
D4EC47591C26342F0024B507 /* rct2.c */,
D4EC475A1C26342F0024B507 /* rct2.h */,
D4EC476D1C26342F0024B507 /* scenario_list.c */,
D46105CD1C38828D00DB1EE3 /* scenario_sources.c */,
D4EC476E1C26342F0024B507 /* scenario.c */,
D4EC476F1C26342F0024B507 /* scenario.h */,
D4EC47701C26342F0024B507 /* sprites.h */,
D4EC47711C26342F0024B507 /* title.c */,
D4EC47721C26342F0024B507 /* title.h */,
D4EC47731C26342F0024B507 /* tutorial.c */,
D4EC47741C26342F0024B507 /* tutorial.h */,
D4163F671C2A044D00B83136 /* version.h */,
);
name = Sources;
@ -1312,7 +1310,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "cachedir=\".cache\"\nliburl=\"https://openrct2.website/files/orctlibs-osx.zip\"\n# keep in sync with version in build.sh\nsha256sum=\"02ebc8e7fd8b9b02b7144721784c5d96202a17398bc8652da163c8c85b66a7db\"\n\n[[ ! -e \"${SRCROOT}/libversion\" || $(head -n 1 \"${SRCROOT}/libversion\") != $sha256sum ]]\noutdated=$?\n\nif [[ $outdated -eq 0 ]] || [[ ! -f \"${SRCROOT}/$cachedir/orctlibs.zip\" ]]; then\n if [[ ! -d \"${SRCROOT}/$cachedir\" ]]; then mkdir \"${SRCROOT}/$cachedir\"; fi\n if [[ -f \"${SRCROOT}/$cachedir/orctlibs.zip\" ]]; then rm \"${SRCROOT}/$cachedir/orctlibs.zip\"; fi\n curl -L -o \"${SRCROOT}/$cachedir/orctlibs.zip\" \"$liburl\"\n if [[ -d \"${SRCROOT}/$cachedir/orctlibs\" ]]; then rm -rf \"${SRCROOT}/$cachedir/orctlibs\"; fi\n mkdir \"${SRCROOT}/$cachedir/orctlibs\"\n unzip -uaq -d \"${SRCROOT}/$cachedir/orctlibs\" \"${SRCROOT}/$cachedir/orctlibs.zip\"\nfi\n\nif [[ $outdated -eq 0 ]] || [[ ! -d \"${SRCROOT}/lib\" ]]; then\n if [[ -d \"${SRCROOT}/lib\" ]]; then rm -r \"${SRCROOT}/lib\"; fi\n cp -Rf \"${SRCROOT}/$cachedir/orctlibs/local\" \"${SRCROOT}/lib\"\nfi\nif [[ $outdated -eq 0 ]] || [[ ! -d \"${SRCROOT}/libxc\" ]]; then\n if [[ -d \"${SRCROOT}/libxc\" ]]; then rm -r \"${SRCROOT}/libxc\"; fi\n cp -Rf \"${SRCROOT}/$cachedir/orctlibs/glob\" \"${SRCROOT}/libxc\"\nfi\n\nif [[ $outdated -eq 0 ]]; then\n newsha=$(shasum -a 256 \"${SRCROOT}/$cachedir/orctlibs.zip\" | cut -f1 -d\" \")\n echo $newsha > \"${SRCROOT}/libversion\"\n [[ \"$newsha\" == \"$sha256sum\" ]]\nfi";
shellScript = "cachedir=\".cache\"\nliburl=\"https://openrct2.website/files/orctlibs-osx.zip\"\n# keep in sync with version in build.sh\nsha256sum=\"6562ce9e1f37f125e3345bfd8b961777800436bf607b30dc7c964e0e6991ad2c\"\n\n[[ ! -e \"${SRCROOT}/libversion\" || $(head -n 1 \"${SRCROOT}/libversion\") != $sha256sum ]]\noutdated=$?\n\nif [[ $outdated -eq 0 ]] || [[ ! -f \"${SRCROOT}/$cachedir/orctlibs.zip\" ]]; then\n if [[ ! -d \"${SRCROOT}/$cachedir\" ]]; then mkdir \"${SRCROOT}/$cachedir\"; fi\n if [[ -f \"${SRCROOT}/$cachedir/orctlibs.zip\" ]]; then rm \"${SRCROOT}/$cachedir/orctlibs.zip\"; fi\n curl -L -o \"${SRCROOT}/$cachedir/orctlibs.zip\" \"$liburl\"\n if [[ -d \"${SRCROOT}/$cachedir/orctlibs\" ]]; then rm -rf \"${SRCROOT}/$cachedir/orctlibs\"; fi\n mkdir \"${SRCROOT}/$cachedir/orctlibs\"\n unzip -uaq -d \"${SRCROOT}/$cachedir/orctlibs\" \"${SRCROOT}/$cachedir/orctlibs.zip\"\nfi\n\nif [[ $outdated -eq 0 ]] || [[ ! -d \"${SRCROOT}/lib\" ]]; then\n if [[ -d \"${SRCROOT}/lib\" ]]; then rm -r \"${SRCROOT}/lib\"; fi\n cp -Rf \"${SRCROOT}/$cachedir/orctlibs/local\" \"${SRCROOT}/lib\"\nfi\nif [[ $outdated -eq 0 ]] || [[ ! -d \"${SRCROOT}/libxc\" ]]; then\n if [[ -d \"${SRCROOT}/libxc\" ]]; then rm -r \"${SRCROOT}/libxc\"; fi\n cp -Rf \"${SRCROOT}/$cachedir/orctlibs/glob\" \"${SRCROOT}/libxc\"\nfi\n\nif [[ $outdated -eq 0 ]]; then\n newsha=$(shasum -a 256 \"${SRCROOT}/$cachedir/orctlibs.zip\" | cut -f1 -d\" \")\n echo $newsha > \"${SRCROOT}/libversion\"\n [[ \"$newsha\" == \"$sha256sum\" ]]\nfi";
};
/* End PBXShellScriptBuildPhase section */
@ -1382,7 +1380,6 @@
D4EC48231C26342F0024B507 /* station.c in Sources */,
D4EC484D1C26342F0024B507 /* new_ride.c in Sources */,
D4EC484A1C26342F0024B507 /* music_credits.c in Sources */,
D4EC482B1C26342F0024B507 /* tutorial.c in Sources */,
D4EC48241C26342F0024B507 /* track.c in Sources */,
D4EC47DF1C26342F0024B507 /* addresses.c in Sources */,
D4EC484B1C26342F0024B507 /* network_status.c in Sources */,
@ -1450,6 +1447,7 @@
D4EC482D1C26342F0024B507 /* util.c in Sources */,
D4EC47EA1C26342F0024B507 /* line.c in Sources */,
D4EC48271C26342F0024B507 /* vehicle.c in Sources */,
D46105CE1C38828D00DB1EE3 /* scenario_sources.c in Sources */,
D4EC48281C26342F0024B507 /* scenario_list.c in Sources */,
D4EC48581C26342F0024B507 /* scenery.c in Sources */,
D4EC48061C26342F0024B507 /* LanguagePack.cpp in Sources */,

View File

@ -1,4 +1,5 @@
version: 0.0.4.{build}
os: Previous Visual Studio 2015
build_script:
- ps: >-
.\setenv.ps1

View File

@ -3946,6 +3946,32 @@ STR_5603 :遊客已離開遊樂設施
STR_5604 :遊客已購買物品
STR_5605 :遊客已使用設施
STR_5606 :遊客已死亡
STR_5607 :{SMALLFONT}{BLACK}強制移除選中的地圖元素.
STR_5608 :BH
STR_5609 :CH
STR_5610 :{SMALLFONT}{BLACK}移除選中的地圖元素. 使用時請注意. 因為強制移除地圖元素並不會對遊戲中的現金做成影響.
STR_5611 :G
STR_5612 :{SMALLFONT}{BLACK}Ghost flag
STR_5613 :B
STR_5614 :{SMALLFONT}{BLACK}Broken flag
STR_5615 :L
STR_5616 :{SMALLFONT}{BLACK}Last element for tile flag
STR_5617 :{SMALLFONT}{BLACK}將選中的元素移到上面.
STR_5618 :{SMALLFONT}{BLACK}將選中的元素移到下面.
STR_5619 :夢幻遊樂園
STR_5620 :夢幻遊樂園: 資料片1
STR_5621 :夢幻遊樂園: 資料片2
STR_5622 :模擬樂園2
STR_5623 :瘋狂世界
STR_5624 :時空歷險
STR_5625 :{OPENQUOTES}真實的{ENDQUOTES}樂園
STR_5626 :其他樂園
STR_5627 :樂園列表的排序方式:
STR_5628 :出處的遊戲
STR_5629 :困難程度
STR_5630 :允許劇情解鎖
STR_5631 :額外下載的官方樂園
STR_5632 :建設你的..
#####################

View File

@ -3677,8 +3677,8 @@ STR_5335 :Ride entrance
STR_5336 :Ride exit
STR_5337 :Park entrance
STR_5338 :Element type
STR_5339 :Base height
STR_5340 :Clearance height
STR_5339 :{SMALLFONT}{BLACK}Base height
STR_5340 :{SMALLFONT}{BLACK}Clearance height
STR_5341 :Flags
STR_5342 :Choose a map tile
STR_5343 :Automatically place staff
@ -3945,6 +3945,474 @@ STR_5603 :Guest has left ride
STR_5604 :Guest has bought item
STR_5605 :Guest has used facility
STR_5606 :Guest has died
STR_5607 :{SMALLFONT}{BLACK}Forcefully remove selected map element.
STR_5608 :BH
STR_5609 :CH
STR_5610 :{SMALLFONT}{BLACK}Remove the currently selected map element. This will forcefully remove it, so no cash will be used/gained. Use with caution.
STR_5611 :G
STR_5612 :{SMALLFONT}{BLACK}Ghost flag
STR_5613 :B
STR_5614 :{SMALLFONT}{BLACK}Broken flag
STR_5615 :L
STR_5616 :{SMALLFONT}{BLACK}Last element for tile flag
STR_5617 :{SMALLFONT}{BLACK}Move selected element up.
STR_5618 :{SMALLFONT}{BLACK}Move selected element down.
STR_5619 :RollerCoaster Tycoon
STR_5620 :Added Attractions
STR_5621 :Loopy Landscapes
STR_5622 :RollerCoaster Tycoon 2
STR_5623 :Wacky Worlds
STR_5624 :Time Twister
STR_5625 :{OPENQUOTES}Real{ENDQUOTES} Parks
STR_5626 :Other Parks
STR_5627 :Group scenario list by:
STR_5628 :Source game
STR_5629 :Difficulty level
STR_5630 :Enable unlocking of scenarios
STR_5631 :Original DLC Parks
STR_5632 :Build your own...
#############
# Scenarios #
################
# RCT Original #
################
<Forest Frontiers>
STR_SCNR :Forest Frontiers
STR_PARK :Forest Frontiers
STR_DTLS :Deep in the forest, build a thriving theme park in a large cleared area
<Dynamite Dunes>
STR_SCNR :Dynamite Dunes
STR_PARK :Dynamite Dunes
STR_DTLS :Built in the middle of the desert, this theme park contains just one roller coaster but has space for expansion
<Leafy Lake>
STR_SCNR :Leafy Lake
STR_PARK :Leafy Lake
STR_DTLS :Starting from scratch, build a theme park around a large lake
<Diamond Heights>
STR_SCNR :Diamond Heights
STR_PARK :Diamond Heights
STR_DTLS :Diamond Heights is already a successful theme park with great rides - develop it to double its value
<Evergreen Gardens>
STR_SCNR :Evergreen Gardens
STR_PARK :Evergreen Gardens
STR_DTLS :Convert the beautiful Evergreen Gardens into a thriving theme park
<Bumbly Beach>
STR_SCNR :Bumbly Beach
STR_PARK :Bumbly Beach
STR_DTLS :Develop Bumbly Beach's small amusement park into a thriving theme park
<Trinity Islands>
STR_SCNR :Trinity Islands
STR_PARK :Trinity Islands
STR_DTLS :Several islands form the basis for this new park
<Katie's Dreamland>
STR_SCNR :Katie's Dreamland
STR_PARK :Katie's Dreamland
STR_DTLS :A small theme park with a few rides and room for expansion - Your aim is to double the park value
<Pokey Park>
STR_SCNR :Pokey Park
STR_PARK :Pokey Park
STR_DTLS :A small, cramped amusement park which requires major expansion
<White Water Park>
STR_SCNR :White Water Park
STR_PARK :White Water Park
STR_DTLS :A park with some excellent water-based rides requires expansion
<Millennium Mines>
STR_SCNR :Millennium Mines
STR_PARK :Millennium Mines
STR_DTLS :Convert a large abandoned mine from a tourist attraction into a theme park
<Karts & Coasters>
STR_SCNR :Karts & Coasters
STR_PARK :Karts & Coasters
STR_DTLS :A large park hidden in the forest, with only go-kart tracks and wooden roller coasters
<Mel's World>
STR_SCNR :Mel's World
STR_PARK :Mel's World
STR_DTLS :This theme park has some well-designed modern rides, but plenty of space for expansion
<Mystic Mountain>
STR_SCNR :Mystic Mountain
STR_PARK :Mystic Mountain
STR_DTLS :In the hilly forests of Mystic Mountain, build a theme park from scratch
<Pacific Pyramids>
STR_SCNR :Pacific Pyramids
STR_PARK :Pacific Pyramids
STR_DTLS :Convert the Egyptian Ruins tourist attraction into a thriving theme park
<Crumbly Woods>
STR_SCNR :Crumbly Woods
STR_PARK :Crumbly Woods
STR_DTLS :A large park with well-designed but rather old rides - Replace the old rides or add new rides to make the park more popular
<Paradise Pier>
STR_SCNR :Paradise Pier
STR_PARK :Paradise Pier
STR_DTLS :Convert this sleepy town's pier into a thriving attraction
<Lightning Peaks>
STR_SCNR :Lightning Peaks
STR_PARK :Lightning Peaks
STR_DTLS :The beautiful mountains of Lightning Peaks are popular with walkers and sightseers - Use the available land to attract a new thrill-seeking clientele
<Ivory Towers>
STR_SCNR :Ivory Towers
STR_PARK :Ivory Towers
STR_DTLS :A well-established park, which has a few problems
<Rainbow Valley>
STR_SCNR :Rainbow Valley
STR_PARK :Rainbow Valley
STR_DTLS :Rainbow Valley's local authority won't allow any landscape changes or large tree removal, but you must develop the area into a large theme park
<Thunder Rock>
STR_SCNR :Thunder Rock
STR_PARK :Thunder Rock
STR_DTLS :Thunder Rock stands in the middle of a desert and attracts many tourists - Use the available space to build rides to attract more people
<Mega Park>
STR_SCNR :Mega Park
STR_PARK :Mega Park
STR_DTLS :Just for fun!
## Added Attractions
<Whispering Cliffs>
STR_SCNR :Whispering Cliffs
STR_PARK :Whispering Cliffs
STR_DTLS :Develop the seaside cliffs into a thriving amusement park
<Three Monkeys Park>
STR_SCNR :Three Monkeys Park
STR_PARK :Three Monkeys Park
STR_DTLS :Central to this large developing park is a giant triple-track racing/duelling steel coaster
<Canary Mines>
STR_SCNR :Canary Mines
STR_PARK :Canary Mines
STR_DTLS :This abandoned mine already has the makings of a tourist attraction with its minature railway and a pair of vertical drop roller coasters
<Barony Bridge>
STR_SCNR :Barony Bridge
STR_PARK :Barony Bridge
STR_DTLS :An old redundant bridge is yours to develop into an amusement park
<Funtopia>
STR_SCNR :Funtopia
STR_PARK :Funtopia
STR_DTLS :Covering land both sides of a highway, this park has several rides already operating
<Haunted Harbor>
STR_SCNR :Haunted Harbor
STR_PARK :Haunted Harbor
STR_DTLS :The local authority has agreed to sell nearby land cheaply to this small seaside park, on the condition that certain rides are preserved
<Fun Fortress>
STR_SCNR :Fun Fortress
STR_PARK :Fun Fortress
STR_DTLS :This castle is all yours to turn into a theme park
<Future World>
STR_SCNR :Future World
STR_PARK :Future World
STR_DTLS :This futuristic park has plenty of space for new rides on its alien landscape
<Gentle Glen>
STR_SCNR :Gentle Glen
STR_PARK :Gentle Glen
STR_DTLS :The local population prefer gentle and relaxing rides, so it is your job to expand this park to suit their tastes
<Jolly Jungle>
STR_SCNR :Jolly Jungle
STR_PARK :Jolly Jungle
STR_DTLS :Deep in the jungle lies a large area of land ready to be turned into a theme park
<Hydro Hills>
STR_SCNR :Hydro Hills
STR_PARK :Hydro Hills
STR_DTLS :A series of stepped lakes form the basis for this new park
<Sprightly Park>
STR_SCNR :Sprightly Park
STR_PARK :Sprightly Park
STR_DTLS :This elderly park has many historical rides but is badly in debt
<Magic Quarters>
STR_SCNR :Magic Quarters
STR_PARK :Magic Quarters
STR_DTLS :A large area of land has been cleared and partially themed ready for you to develop into a landscaped theme park
<Fruit Farm>
STR_SCNR :Fruit Farm
STR_PARK :Fruit Farm
STR_DTLS :A thriving fruit farm has built a railroad to boost its income, your job is to develop it into a full-blown amusement park
<Butterfly Dam>
STR_SCNR :Butterfly Dam
STR_PARK :Butterfly Dam
STR_DTLS :The area around a dam is available for you to develop into an amusement park
<Coaster Canyon>
STR_SCNR :Coaster Canyon
STR_PARK :Coaster Canyon
STR_DTLS :A vast canyon is yours to turn into a theme park
<Thunderstorm Park>
STR_SCNR :Thunderstorm Park
STR_PARK :Thunderstorm Park
STR_DTLS :The weather is so wet here that a giant pyramid has been built to allow some rides to be built under cover
<Harmonic Hills>
STR_SCNR :Harmonic Hills
STR_PARK :Harmonic Hills
STR_DTLS :The local authority won't allow you to build above tree height in this park
<Roman Village>
STR_SCNR :Roman Village
STR_PARK :Roman Village
STR_DTLS :Develop this Roman-themed park by adding rides and roller coasters
<Swamp Cove>
STR_SCNR :Swamp Cove
STR_PARK :Swamp Cove
STR_DTLS :Built partly on a series of small islands, this park already has a pair of large roller coasters as its centerpiece
<Adrenaline Heights>
STR_SCNR :Adrenaline Heights
STR_PARK :Adrenaline Heights
STR_DTLS :Build a park to appeal to the high-intensity thrill-seeking local people
<Utopia Park>
STR_SCNR :Utopia Park
STR_PARK :Utopia Park
STR_DTLS :An oasis in the middle of the desert provides an unusual opportunity to build an amusement park
<Rotting Heights>
STR_SCNR :Rotting Heights
STR_PARK :Rotting Heights
STR_DTLS :Overgrown and dilapidated, can you resurrect this once-great amusement park?
<Fiasco Forest>
STR_SCNR :Fiasco Forest
STR_PARK :Fiasco Forest
STR_DTLS :Full of badly designed and dangerous rides, you have a very limited budget and time to fix the problems and turn the park around
<Pickle Park>
STR_SCNR :Pickle Park
STR_PARK :Pickle Park
STR_DTLS :The local authority will not allow any kind of advertising or promotion, so this park must succeed by reputation only
<Giggle Downs>
STR_SCNR :Giggle Downs
STR_PARK :Giggle Downs
STR_DTLS :A four lane steeplechase ride is the centerpiece of this expanding park
<Mineral Park>
STR_SCNR :Mineral Park
STR_PARK :Mineral Park
STR_DTLS :Turn this abandoned stone quarry into a place to attract thrill-seeking tourists
<Coaster Crazy>
STR_SCNR :Coaster Crazy
STR_PARK :Coaster Crazy
STR_DTLS :You have limited funds but unlimited time to turn this mountainside area into a vast roller coaster park
<Urban Park>
STR_SCNR :Urban Park
STR_PARK :Urban Park
STR_DTLS :A tiny park has done a deal with the nearby town to allow expansion through the town itself
<Geoffrey Gardens>
STR_SCNR :Geoffrey Gardens
STR_PARK :Geoffrey Gardens
STR_DTLS :A large garden park needs turning into a thriving theme park
## Loopy Landscapes
<Iceberg Islands>
STR_SCNR :Iceberg Islands
STR_PARK :Iceberg Islands
STR_DTLS :A collection of icebergs make a cold setting for this ambitious theme park
<Volcania>
STR_SCNR :Volcania
STR_PARK :Volcania
STR_DTLS :A dormant volcano is the setting of this coaster-building challenge
<Arid Heights>
STR_SCNR :Arid Heights
STR_PARK :Arid Heights
STR_DTLS :Free of any financial limits, your challenge is to develop this desert park while keeping the guests happy
<Razor Rocks>
STR_SCNR :Razor Rocks
STR_PARK :Razor Rocks
STR_DTLS :Your task is to build a massive coaster-filled park in amongst Razor Rocks
<Crater Lake>
STR_SCNR :Crater Lake
STR_PARK :Crater Lake
STR_DTLS :A large lake in an ancient crater is the setting for this park
<Vertigo Views>
STR_SCNR :Vertigo Views
STR_PARK :Vertigo Views
STR_DTLS :This large park already has an excellent hyper-coaster, but your task is to massively increase its profit
<Paradise Pier 2>
STR_SCNR :Paradise Pier 2
STR_PARK :Paradise Pier 2
STR_DTLS :Paradise Pier has expanded its network of walkways over the sea, and your task is to expand the park to use the extra space
<Dragon's Cove>
STR_SCNR :Dragon's Cove
STR_PARK :Dragon's Cove
STR_DTLS :This sea-side cove is the setting for this coaster-building challenge
<Good Knight Park>
STR_SCNR :Good Knight Park
STR_PARK :Good Knight Park
STR_DTLS :A castle with a pair of roller coasters needs developing into a larger theme park
<Wacky Warren>
STR_SCNR :Wacky Warren
STR_PARK :Wacky Warren
STR_DTLS :A park which has much of its footpaths and coasters underground
<Grand Glacier>
STR_SCNR :Grand Glacier
STR_PARK :Grand Glacier
STR_DTLS :A glacier-filled valley is yours to develop into a theme park
<Crazy Craters>
STR_SCNR :Crazy Craters
STR_PARK :Crazy Craters
STR_DTLS :In a far-off world where money is not needed, you must build an entertainment centre to keep the people happy
<Dusty Desert>
STR_SCNR :Dusty Desert
STR_PARK :Dusty Desert
STR_DTLS :Five coasters require completion in this desert park
<Woodworm Park>
STR_SCNR :Woodworm Park
STR_PARK :Woodworm Park
STR_DTLS :This historical park is only allowed to build older-styled rides
<Icarus Park>
STR_SCNR :Icarus Park
STR_PARK :Icarus Park
STR_DTLS :Develop this alien park to maximize its profit
<Sunny Swamps>
STR_SCNR :Sunny Swamps
STR_PARK :Sunny Swamps
STR_DTLS :This well-themed amusement park already has several rides, but has plenty of space for expansion
<Frightmare Hills>
STR_SCNR :Frightmare Hills
STR_PARK :Frightmare Hills
STR_DTLS :A scary park with a giant centrepiece coaster
<Thunder Rocks>
STR_SCNR :Thunder Rocks
STR_PARK :Thunder Rocks
STR_DTLS :Two large hunks of rock stick out of the sand, upon which the beginnings of a theme park are constructed
<Octagon Park>
STR_SCNR :Octagon Park
STR_PARK :Octagon Park
STR_DTLS :In this large park you must design and build ten large coasters
<Pleasure Island>
STR_SCNR :Pleasure Island
STR_PARK :Pleasure Island
STR_DTLS :A long thin island makes a challenging setting to build a selection of coasters
<Icicle Worlds>
STR_SCNR :Icicle Worlds
STR_PARK :Icicle Worlds
STR_DTLS :An icy landscape needs turning into a thriving theme park
<Southern Sands>
STR_SCNR :Southern Sands
STR_PARK :Southern Sands
STR_DTLS :A desert park with some cleverly designed coasters is yours to expand
<Tiny Towers>
STR_SCNR :Tiny Towers
STR_PARK :Tiny Towers
STR_DTLS :In this tiny park you must finish building the five existing coasters
<Nevermore Park>
STR_SCNR :Nevermore Park
STR_PARK :Nevermore Park
STR_DTLS :A large park with a novel transporation system around its edge
<Pacifica>
STR_SCNR :Pacifica
STR_PARK :Pacifica
STR_DTLS :This large island is all yours to develop as an amusement park
<Urban Jungle>
STR_SCNR :Urban Jungle
STR_PARK :Urban Jungle
STR_DTLS :A giant abandoned skyscraper is a unique opportunity for a theme park developer
<Terror Town>
STR_SCNR :Terror Town
STR_PARK :Terror Town
STR_DTLS :This urban area is all yours to develop into as an amusement park
<Megaworld Park>
STR_SCNR :Megaworld Park
STR_PARK :Megaworld Park
STR_DTLS :A giant park already packed full of rides needs improving
<Venus Ponds>
STR_SCNR :Venus Ponds
STR_PARK :Venus Ponds
STR_DTLS :On a far-away planet this area of land needs turning into a theme park
<Micro Park>
STR_SCNR :Micro Park
STR_PARK :Micro Park
STR_DTLS :Try to create the world's smallest profitable park
## Real Parks from RCT1
# None of them had details
<Alton Towers>
STR_SCNR :Alton Towers
STR_PARK :Alton Towers
STR_DTLS :
<Heide-Park>
STR_SCNR :Heide-Park
STR_PARK :Heide-Park
STR_DTLS :
<Blackpool Pleasure Beach>
STR_SCNR :Blackpool Pleasure Beach
STR_PARK :Blackpool Pleasure Beach
STR_DTLS :
## Misc parks from RCT1
# Had no details
<Fort Anachronism>
STR_SCNR :Fort Anachronism
STR_PARK :Fort Anachronism
STR_DTLS :
#####################
# Rides/attractions #

View File

@ -3646,8 +3646,8 @@ STR_5302 :Clear loan
STR_5303 :Allow building in pause mode
STR_5304 :Title Sequence:
STR_5305 :RollerCoaster Tycoon 1
STR_5306 :RollerCoaster Tycoon 1 (AA)
STR_5307 :RollerCoaster Tycoon 1 (AA + LL)
STR_5306 :RollerCoaster Tycoon 1 (CF)
STR_5307 :RollerCoaster Tycoon 1 (CF + LL)
STR_5308 :RollerCoaster Tycoon 2
STR_5309 :OpenRCT2
STR_5310 :Random
@ -3679,8 +3679,8 @@ STR_5335 :Ride entrance
STR_5336 :Ride exit
STR_5337 :Park entrance
STR_5338 :Element type
STR_5339 :Base height
STR_5340 :Clearance height
STR_5339 :{SMALLFONT}{BLACK}Base height
STR_5340 :{SMALLFONT}{BLACK}Clearance height
STR_5341 :Flags
STR_5342 :Choose a map tile
STR_5343 :Automatically place staff
@ -3926,6 +3926,494 @@ STR_5582 :Trap mouse cursor in window
STR_5583 :{COMMA1DP16}ms{POWERNEGATIVEONE}
STR_5584 :SI
STR_5585 :{SMALLFONT}{BLACK}Unlocks ride operation limits, allowing for things like {VELOCITY} lift hills
STR_5586 :Automatically open shops and stalls
STR_5587 :{SMALLFONT}{BLACK}When enabled, shops and stalls will be automatically opened after building them
STR_5588 :{SMALLFONT}{BLACK}Play with other players
STR_5589 :Notification Settings
STR_5590 :Park awards
STR_5591 :Marketing campaign has finished
STR_5592 :Park warnings
STR_5593 :Park rating warnings
STR_5594 :Ride has broken down
STR_5595 :Ride has crashed
STR_5596 :Ride warnings
STR_5597 :Ride / scenery researched
STR_5598 :Guest warnings
STR_5599 :Guest is lost
STR_5600 :Guest has left the park
STR_5601 :Guest is queuing for ride
STR_5602 :Guest is on ride
STR_5603 :Guest has left ride
STR_5604 :Guest has bought item
STR_5605 :Guest has used facility
STR_5606 :Guest has died
STR_5607 :{SMALLFONT}{BLACK}Forcefully remove selected map element.
STR_5608 :BH
STR_5609 :CH
STR_5610 :{SMALLFONT}{BLACK}Remove the currently selected map element. This will forcefully remove it, so no cash will be used/gained. Use with caution.
STR_5611 :G
STR_5612 :{SMALLFONT}{BLACK}Ghost flag
STR_5613 :B
STR_5614 :{SMALLFONT}{BLACK}Broken flag
STR_5615 :L
STR_5616 :{SMALLFONT}{BLACK}Last element for tile flag
STR_5617 :{SMALLFONT}{BLACK}Move selected element up.
STR_5618 :{SMALLFONT}{BLACK}Move selected element down.
STR_5619 :RollerCoaster Tycoon
STR_5620 :Corkscrew Follies
STR_5621 :Loopy Landscapes
STR_5622 :RollerCoaster Tycoon 2
STR_5623 :Wacky Worlds
STR_5624 :Time Twister
STR_5625 :{OPENQUOTES}Real{ENDQUOTES} Parks
STR_5626 :Other Parks
STR_5627 :Group scenario list by:
STR_5628 :Source game
STR_5629 :Difficulty level
STR_5630 :Enable unlocking of scenarios
STR_5631 :Original DLC Parks
STR_5632 :Build your own...
#############
# Scenarios #
#############
## RCT Original
<Forest Frontiers>
STR_SCNR :Forest Frontiers
STR_PARK :Forest Frontiers
STR_DTLS :Deep in the forest, build a thriving theme park in a large cleared area
<Dynamite Dunes>
STR_SCNR :Dynamite Dunes
STR_PARK :Dynamite Dunes
STR_DTLS :Built in the middle of the desert, this theme park contains just one roller coaster but has space for expansion
<Leafy Lake>
STR_SCNR :Leafy Lake
STR_PARK :Leafy Lake
STR_DTLS :Starting from scratch, build a theme park around a large lake
<Diamond Heights>
STR_SCNR :Diamond Heights
STR_PARK :Diamond Heights
STR_DTLS :Diamond Heights is already a successful theme park with great rides - develop it to double its value
<Evergreen Gardens>
STR_SCNR :Evergreen Gardens
STR_PARK :Evergreen Gardens
STR_DTLS :Convert the beautiful Evergreen Gardens into a thriving theme park
<Bumbly Beach>
STR_SCNR :Bumbly Beach
STR_PARK :Bumbly Beach
STR_DTLS :Develop Bumbly Beach's small amusement park into a thriving theme park
<Trinity Islands>
STR_SCNR :Trinity Islands
STR_PARK :Trinity Islands
STR_DTLS :Several islands form the basis for this new park
<Katie's Dreamland>
STR_SCNR :Katie's World
STR_PARK :Katie's World
STR_DTLS :A small theme park with a few rides and room for expansion - Your aim is to double the park value
<Pokey Park>
STR_SCNR :Dinky Park
STR_PARK :Dinky Park
STR_DTLS :A small, cramped amusement park which requires major expansion
<White Water Park>
STR_SCNR :Aqua Park
STR_PARK :Aqua Park
STR_DTLS :A park with some excellent water-based rides requires expansion
<Millennium Mines>
STR_SCNR :Millennium Mines
STR_PARK :Millennium Mines
STR_DTLS :Convert a large abandoned mine from a tourist attraction into a theme park
<Karts & Coasters>
STR_SCNR :Karts & Coasters
STR_PARK :Karts & Coasters
STR_DTLS :A large park hidden in the forest, with only go-kart tracks and wooden roller coasters
<Mel's World>
STR_SCNR :Mel's World
STR_PARK :Mel's World
STR_DTLS :This theme park has some well-designed modern rides, but plenty of space for expansion
<Mystic Mountain>
STR_SCNR :Mothball Mountain
STR_PARK :Mothball Mountain
STR_DTLS :In the hilly forests of Mothball Mountain, build a theme park from scratch
<Pacific Pyramids>
STR_SCNR :Pacific Pyramids
STR_PARK :Pacific Pyramids
STR_DTLS :Convert the Egyptian Ruins tourist attraction into a thriving theme park
<Crumbly Woods>
STR_SCNR :Crumbly Woods
STR_PARK :Crumbly Woods
STR_DTLS :A large park with well-designed but rather old rides - Replace the old rides or add new rides to make the park more popular
<Paradise Pier>
STR_SCNR :Big Pier
STR_PARK :Big Pier
STR_DTLS :Convert this sleepy town's pier into a thriving attraction
<Lightning Peaks>
STR_SCNR :Lightning Peaks
STR_PARK :Lightning Peaks
STR_DTLS :The beautiful mountains of Lightning Peaks are popular with walkers and sightseers - Use the available land to attract a new thrill-seeking clientele
<Ivory Towers>
STR_SCNR :Ivory Towers
STR_PARK :Ivory Towers
STR_DTLS :A well-established park, which has a few problems
<Rainbow Valley>
STR_SCNR :Rainbow Valley
STR_PARK :Rainbow Valley
STR_DTLS :Rainbow Valley's local authority won't allow any landscape changes or large tree removal, but you must develop the area into a large theme park
<Thunder Rock>
STR_SCNR :Thunder Rock
STR_PARK :Thunder Rock
STR_DTLS :Thunder Rock stands in the middle of a desert and attracts many tourists - Use the available space to build rides to attract more people
<Mega Park>
STR_SCNR :Mega Park
STR_PARK :Mega Park
STR_DTLS :Just for fun!
## Corkscrew Follies
<Whispering Cliffs>
STR_SCNR :Whispering Cliffs
STR_PARK :Whispering Cliffs
STR_DTLS :Develop the seaside cliffs into a thriving amusement park
<Three Monkeys Park>
STR_SCNR :Three Monkeys Park
STR_PARK :Three Monkeys Park
STR_DTLS :Central to this large developing park is a giant triple-track racing/duelling steel coaster
<Canary Mines>
STR_SCNR :Canary Mines
STR_PARK :Canary Mines
STR_DTLS :This abandoned mine already has the makings of a tourist attraction with its minature railway and a pair of vertical drop roller coasters
<Barony Bridge>
STR_SCNR :Barony Bridge
STR_PARK :Barony Bridge
STR_DTLS :An old redundant bridge is yours to develop into an amusement park
<Funtopia>
STR_SCNR :Funtopia
STR_PARK :Funtopia
STR_DTLS :Covering land both sides of a highway, this park has several rides already operating
<Haunted Harbor>
STR_SCNR :Haunted Harbor
STR_PARK :Haunted Harbor
STR_DTLS :The local authority has agreed to sell nearby land cheaply to this small seaside park, on the condition that certain rides are preserved
<Fun Fortress>
STR_SCNR :Fun Fortress
STR_PARK :Fun Fortress
STR_DTLS :This castle is all yours to turn into a theme park
<Future World>
STR_SCNR :Future World
STR_PARK :Future World
STR_DTLS :This futuristic park has plenty of space for new rides on its alien landscape
<Gentle Glen>
STR_SCNR :Gentle Glen
STR_PARK :Gentle Glen
STR_DTLS :The local population prefer gentle and relaxing rides, so it is your job to expand this park to suit their tastes
<Jolly Jungle>
STR_SCNR :Jolly Jungle
STR_PARK :Jolly Jungle
STR_DTLS :Deep in the jungle lies a large area of land ready to be turned into a theme park
<Hydro Hills>
STR_SCNR :Hydro Hills
STR_PARK :Hydro Hills
STR_DTLS :A series of stepped lakes form the basis for this new park
<Sprightly Park>
STR_SCNR :Sprightly Park
STR_PARK :Sprightly Park
STR_DTLS :This elderly park has many historical rides but is badly in debt
<Magic Quarters>
STR_SCNR :Magic Quarters
STR_PARK :Magic Quarters
STR_DTLS :A large area of land has been cleared and partially themed ready for you to develop into a landscaped theme park
<Fruit Farm>
STR_SCNR :Fruit Farm
STR_PARK :Fruit Farm
STR_DTLS :A thriving fruit farm has built a railroad to boost its income, your job is to develop it into a full-blown amusement park
<Butterfly Dam>
STR_SCNR :Butterfly Dam
STR_PARK :Butterfly Dam
STR_DTLS :The area around a dam is available for you to develop into an amusement park
<Coaster Canyon>
STR_SCNR :Coaster Canyon
STR_PARK :Coaster Canyon
STR_DTLS :A vast canyon is yours to turn into a theme park
<Thunderstorm Park>
STR_SCNR :Thunderstorm Park
STR_PARK :Thunderstorm Park
STR_DTLS :The weather is so wet here that a giant pyramid has been built to allow some rides to be built under cover
<Harmonic Hills>
STR_SCNR :Harmonic Hills
STR_PARK :Harmonic Hills
STR_DTLS :The local authority won't allow you to build above tree height in this park
<Roman Village>
STR_SCNR :Roman Village
STR_PARK :Roman Village
STR_DTLS :Develop this Roman-themed park by adding rides and roller coasters
<Swamp Cove>
STR_SCNR :Swamp Cove
STR_PARK :Swamp Cove
STR_DTLS :Built partly on a series of small islands, this park already has a pair of large roller coasters as its centerpiece
<Adrenaline Heights>
STR_SCNR :Adrenaline Heights
STR_PARK :Adrenaline Heights
STR_DTLS :Build a park to appeal to the high-intensity thrill-seeking local people
<Utopia Park>
STR_SCNR :Utopia Park
STR_PARK :Utopia Park
STR_DTLS :An oasis in the middle of the desert provides an unusual opportunity to build an amusement park
<Rotting Heights>
STR_SCNR :Rotting Heights
STR_PARK :Rotting Heights
STR_DTLS :Overgrown and dilapidated, can you resurrect this once-great amusement park?
<Fiasco Forest>
STR_SCNR :Fiasco Forest
STR_PARK :Fiasco Forest
STR_DTLS :Full of badly designed and dangerous rides, you have a very limited budget and time to fix the problems and turn the park around
<Pickle Park>
STR_SCNR :Pickle Park
STR_PARK :Pickle Park
STR_DTLS :The local authority will not allow any kind of advertising or promotion, so this park must succeed by reputation only
<Giggle Downs>
STR_SCNR :Giggle Downs
STR_PARK :Giggle Downs
STR_DTLS :A four lane steeplechase ride is the centerpiece of this expanding park
<Mineral Park>
STR_SCNR :Mineral Park
STR_PARK :Mineral Park
STR_DTLS :Turn this abandoned stone quarry into a place to attract thrill-seeking tourists
<Coaster Crazy>
STR_SCNR :Coaster Crazy
STR_PARK :Coaster Crazy
STR_DTLS :You have limited funds but unlimited time to turn this mountainside area into a vast roller coaster park
<Urban Park>
STR_SCNR :Urban Park
STR_PARK :Urban Park
STR_DTLS :A tiny park has done a deal with the nearby town to allow expansion through the town itself
<Geoffrey Gardens>
STR_SCNR :Geoffrey Gardens
STR_PARK :Geoffrey Gardens
STR_DTLS :A large garden park needs turning into a thriving theme park
## Loopy Landscapes
<Iceberg Islands>
STR_SCNR :Iceberg Islands
STR_PARK :Iceberg Islands
STR_DTLS :A collection of icebergs make a cold setting for this ambitious theme park
<Volcania>
STR_SCNR :Volcania
STR_PARK :Volcania
STR_DTLS :A dormant volcano is the setting of this coaster-building challenge
<Arid Heights>
STR_SCNR :Arid Heights
STR_PARK :Arid Heights
STR_DTLS :Free of any financial limits, your challenge is to develop this desert park while keeping the guests happy
<Razor Rocks>
STR_SCNR :Razor Rocks
STR_PARK :Razor Rocks
STR_DTLS :Your task is to build a massive coaster-filled park in amongst Razor Rocks
<Crater Lake>
STR_SCNR :Crater Lake
STR_PARK :Crater Lake
STR_DTLS :A large lake in an ancient crater is the setting for this park
<Vertigo Views>
STR_SCNR :Vertigo Views
STR_PARK :Vertigo Views
STR_DTLS :This large park already has an excellent hyper-coaster, but your task is to massively increase its profit
<Paradise Pier 2>
STR_SCNR :Big Pier 2
STR_PARK :Big Pier 2
STR_DTLS :Big Pier has expanded its network of walkways over the sea, and your task is to expand the park to use the extra space
<Dragon's Cove>
STR_SCNR :Dragon's Cove
STR_PARK :Dragon's Cove
STR_DTLS :This sea-side cove is the setting for this coaster-building challenge
<Good Knight Park>
STR_SCNR :Good Knight Park
STR_PARK :Good Knight Park
STR_DTLS :A castle with a pair of roller coasters needs developing into a larger theme park
<Wacky Warren>
STR_SCNR :Wacky Warren
STR_PARK :Wacky Warren
STR_DTLS :A park which has much of its footpaths and coasters underground
<Grand Glacier>
STR_SCNR :Grand Glacier
STR_PARK :Grand Glacier
STR_DTLS :A glacier-filled valley is yours to develop into a theme park
<Crazy Craters>
STR_SCNR :Crazy Craters
STR_PARK :Crazy Craters
STR_DTLS :In a far-off world where money is not needed, you must build an entertainment centre to keep the people happy
<Dusty Desert>
STR_SCNR :Dusty Desert
STR_PARK :Dusty Desert
STR_DTLS :Five coasters require completion in this desert park
<Woodworm Park>
STR_SCNR :Woodworm Park
STR_PARK :Woodworm Park
STR_DTLS :This historical park is only allowed to build older-styled rides
<Icarus Park>
STR_SCNR :Icarus Park
STR_PARK :Icarus Park
STR_DTLS :Develop this alien park to maximize its profit
<Sunny Swamps>
STR_SCNR :Sunny Swamps
STR_PARK :Sunny Swamps
STR_DTLS :This well-themed amusement park already has several rides, but has plenty of space for expansion
<Frightmare Hills>
STR_SCNR :Frightmare Hills
STR_PARK :Frightmare Hills
STR_DTLS :A scary park with a giant centrepiece coaster
<Thunder Rocks>
STR_SCNR :Thunder Rocks
STR_PARK :Thunder Rocks
STR_DTLS :Two large hunks of rock stick out of the sand, upon which the beginnings of a theme park are constructed
<Octagon Park>
STR_SCNR :Octagon Park
STR_PARK :Octagon Park
STR_DTLS :In this large park you must design and build ten large coasters
<Pleasure Island>
STR_SCNR :Pleasure Island
STR_PARK :Pleasure Island
STR_DTLS :A long thin island makes a challenging setting to build a selection of coasters
<Icicle Worlds>
STR_SCNR :Icicle Worlds
STR_PARK :Icicle Worlds
STR_DTLS :An icy landscape needs turning into a thriving theme park
<Southern Sands>
STR_SCNR :Southern Sands
STR_PARK :Southern Sands
STR_DTLS :A desert park with some cleverly designed coasters is yours to expand
<Tiny Towers>
STR_SCNR :Tiny Towers
STR_PARK :Tiny Towers
STR_DTLS :In this tiny park you must finish building the five existing coasters
<Nevermore Park>
STR_SCNR :Nevermore Park
STR_PARK :Nevermore Park
STR_DTLS :A large park with a novel transporation system around its edge
<Pacifica>
STR_SCNR :Pacifica
STR_PARK :Pacifica
STR_DTLS :This large island is all yours to develop as an amusement park
<Urban Jungle>
STR_SCNR :Urban Jungle
STR_PARK :Urban Jungle
STR_DTLS :A giant abandoned skyscraper is a unique opportunity for a theme park developer
<Terror Town>
STR_SCNR :Terror Town
STR_PARK :Terror Town
STR_DTLS :This urban area is all yours to develop into as an amusement park
<Megaworld Park>
STR_SCNR :Megaworld Park
STR_PARK :Megaworld Park
STR_DTLS :A giant park already packed full of rides needs improving
<Venus Ponds>
STR_SCNR :Venus Ponds
STR_PARK :Venus Ponds
STR_DTLS :On a far-away planet this area of land needs turning into a theme park
<Micro Park>
STR_SCNR :Micro Park
STR_PARK :Micro Park
STR_DTLS :Try to create the world's smallest profitable park
## Real Parks from RCT1
# None of them had details
<Alton Towers>
STR_SCNR :Alton Towers
STR_PARK :Alton Towers
STR_DTLS :
<Heide-Park>
STR_SCNR :Heide-Park
STR_PARK :Heide-Park
STR_DTLS :
<Blackpool Pleasure Beach>
STR_SCNR :Blackpool Pleasure Beach
STR_PARK :Blackpool Pleasure Beach
STR_DTLS :
## Misc parks from RCT1
# Had no details
<Fort Anachronism>
STR_SCNR :Fort Anachronism
STR_PARK :Fort Anachronism
STR_DTLS :
#########
# Rides #

View File

@ -3278,9 +3278,9 @@ STR_3269 :Landschaftsänderungen verbieten
STR_3270 :{SMALLFONT}{BLACK}Jegliche Änderungen an der{NEWLINE}Landschaft verbieten
STR_3271 :Hohe Bauten verbieten
STR_3272 :{SMALLFONT}{BLACK}Jegliche hohe Bauten verbieten
STR_3273 :Höhere Schwierigkeitsstufe für Parkbewertung
STR_3273 :Höhere Schwierigkeitsgrad für Parkbewertung
STR_3274 :{SMALLFONT}{BLACK}Machen Sie die Parkbewertung schwieriger
STR_3275 :Höhere Schwierigkeitsstufe für Besuchergewinnung
STR_3275 :Höhere Schwierigkeitsgrad für Besuchergewinnung
STR_3276 :{SMALLFONT}{BLACK}Machen Sie das Anlocken von{NEWLINE}Besuchern schwieriger
STR_3277 :{WINDOW_COLOUR_2}Kosten für Landkauf:
STR_3278 :{WINDOW_COLOUR_2}Kosten für Erwerb v. Baurechten:
@ -3672,8 +3672,8 @@ STR_5335 :Attraktionseingang
STR_5336 :Attraktionsausgang
STR_5337 :Parkeingang
STR_5338 :Elementtyp
STR_5339 :Basishöhe
STR_5340 :Lichte Höhe
STR_5339 :{SMALLFONT}{BLACK}Basishöhe
STR_5340 :{SMALLFONT}{BLACK}Lichte Höhe
STR_5341 :Kennzeichen
STR_5342 :Eine Kachel auf der Karte auswählen
STR_5343 :Personal automatisch platzieren
@ -3898,7 +3898,7 @@ STR_5561 :Sprache konnte nicht geladen werden
STR_5562 :WARNUNG!
STR_5563 :Diese Funktion ist derzeit instabil und mit erhöhter Vorsicht zu verwenden.
STR_5564 :Fehlerhaftes Element einf.
STR_5565 :{SMALLFONT}{BLACK}Fügt ein fehlerhaftes Kartenelement auf der Kachel ein, dadurch werden alle Elemente darüber versteckt.
STR_5565 :{SMALLFONT}{BLACK}Fügt ein fehlerhaftes Kartenelement auf{NEWLINE}der Kachel ein, dadurch werden alle Elemente darüber versteckt.
STR_5566 :Passwort:
STR_5567 :Veröffentlichen
STR_5568 :Passwort benötigt
@ -3919,6 +3919,495 @@ STR_5582 :Mauszeiger im Fenster fangen
STR_5583 :{COMMA1DP16}ms{POWERNEGATIVEONE}
STR_5584 :SI
STR_5585 :{SMALLFONT}{BLACK}Hebt Beschränkungen von Attraktionen auf, um Dinge wie {VELOCITY} schnelle Lifthügel zu erlauben
STR_5586 :Läden und Stände automatisch öffnen
STR_5587 :{SMALLFONT}{BLACK}Wenn aktiviert, werden Läden und Stände nach dem Bauen automatisch geöffnet
STR_5588 :{SMALLFONT}{BLACK}Mit anderen Spielern spielen
STR_5589 :Benachrichtigungseinstellungen
STR_5590 :Parkauszeichnungen
STR_5591 :Marketingkampage wurde beendet
STR_5592 :Parkwarnungen
STR_5593 :Parkbewertungswarnungen
STR_5594 :Attraktion ist ausgefallen
STR_5595 :Attraktion ist verunglückt
STR_5596 :Attraktionswarnungen
STR_5597 :Attraktion / Szenerie erforscht
STR_5598 :Besucherwarnungen
STR_5599 :Besucher hat sich verirrt
STR_5600 :Besucher hat den Park verlassen
STR_5601 :Besucher steht für eine Attraktion schlange
STR_5602 :Besucher ist auf einer Attraktion
STR_5603 :Besucher hat eine Attraktion verlassen
STR_5604 :Besucher hat einen Gegenstand gekauft
STR_5605 :Besucher hat eine Einrichtung benutzt
STR_5606 :Besucher ist gestorben
STR_5607 :{SMALLFONT}{BLACK}Erzwingt das Löschen des{NEWLINE}ausgewählten Elements
STR_5608 :BH
STR_5609 :LH
STR_5610 :{SMALLFONT}{BLACK}Entfernt das ausgewählte Kartenelement. Das Löschen wird erzwungen und dadurch kein Geld verwendet/gutgeschrieben. Mit Vorsicht zu verwenden.
STR_5611 :G
STR_5612 :{SMALLFONT}{BLACK}Flag für Ghost-Element
STR_5613 :D
STR_5614 :{SMALLFONT}{BLACK}Flag für defektes Element
STR_5615 :L
STR_5616 :{SMALLFONT}{BLACK}Flag für letztes Element der Kachel
STR_5617 :{SMALLFONT}{BLACK}Ausgewähltes Element nach oben bewegen
STR_5618 :{SMALLFONT}{BLACK}Ausgewähltes Element nach unten bewegen
STR_5619 :RollerCoaster Tycoon
STR_5620 :Added Attractions
STR_5621 :Loopy Landscapes
STR_5622 :RollerCoaster Tycoon 2
STR_5623 :Wacky Worlds
STR_5624 :Time Twister
STR_5625 :{OPENQUOTES}Reale{ENDQUOTES} Parks
STR_5626 :Sonstige Parks
STR_5627 :Szenarioliste ordnen nach:
STR_5628 :Spielherkunft
STR_5629 :Schwierigkeitsgrad
STR_5630 :Freispielen der Szenarios aktivieren
STR_5631 :Originale DLC Parks
STR_5632 :Bauen Sie Ihren eigenen...
#############
# Scenarios #
################
# RCT Original #
################
<Forest Frontiers>
STR_SCNR :Forest Frontiers
STR_PARK :Forest Frontiers
STR_DTLS :Bauen Sie tief im Wald auf einem großen freigelegten Gelände einen erfolgreichen Freizeitpark.
<Dynamite Dunes>
STR_SCNR :Dynamite Dunes
STR_PARK :Dynamite Dunes
STR_DTLS :Dieser Freizeitpark inmitten der Wüste besitzt nur eine Achterbahn, hat aber genug Platz für Erweiterungen.
<Leafy Lake>
STR_SCNR :Leafy Lake
STR_PARK :Leafy Lake
STR_DTLS :Fangen Sie bei Null an und bauen Sie einen Freizeitpark um einen großen See herum.
<Diamond Heights>
STR_SCNR :Diamond Heights
STR_PARK :Diamond Heights
STR_DTLS :Diamond Heights ist bereits ein erfolgreicher Freizeitpark mit tollen Attraktionen. Entwickeln Sie ihn weiter und verdoppeln Sie seinen Verkehrswert.
<Evergreen Gardens>
STR_SCNR :Evergreen Gardens
STR_PARK :Evergreen Gardens
STR_DTLS :Wandeln Sie die schönen Evergreen Gardens in einen gut besuchten Freizeitpark um.
<Bumbly Beach>
STR_SCNR :Bumbly Beach
STR_PARK :Bumbly Beach
STR_DTLS :Machen Sie aus dem kleinen Vergnügungspark Bumbly Beach einen florierenden Freizeitpark.
<Trinity Islands>
STR_SCNR :Trinity Islands
STR_PARK :Trinity Islands
STR_DTLS :Mehrere Inseln bilden den Ausgangspunkt für diesen neuen Park.
<Katie's Dreamland>
STR_SCNR :Katie's Dreamland
STR_PARK :Katie's Dreamland
STR_DTLS :Ein kleiner Freizeitpark mit wenigen Attraktionen, aber genug Gelände zur Erweiterung. Ihr Ziel ist es, den Verkehrswert des Parks zu verdoppeln.
<Pokey Park>
STR_SCNR :Pokey Park
STR_PARK :Pokey Park
STR_DTLS :Ein kleiner, eng zusammengedrängter Vergnügungspark, bei dem eine Erweiterung in großem Ausmaß erforderlich ist.
<White Water Park>
STR_SCNR :White Water Park
STR_PARK :White Water Park
STR_DTLS :Dieser Park mit verschiedenen hervorragenden Wasser-Attraktionen hat einen Ausbau nötig.
<Millennium Mines>
STR_SCNR :Millennium Mines
STR_PARK :Millennium Mines
STR_DTLS :Machen Sie einen Freizeitpark aus dieser weitläufigen, verlassenen Mine, die zur Zeit nur von Touristen besichtigt wird.
<Karts & Coasters>
STR_SCNR :Karts & Coasters
STR_PARK :Karts & Coasters
STR_DTLS :Ein großer Park, versteckt im Wald gelegen, der nur Gokartbahnen und Holzachterbahnen aufzuweisen hat.
<Mel's World>
STR_SCNR :Mel's World
STR_PARK :Mel's World
STR_DTLS :Dieser Freizeitpark verfügt über ein paar ausgezeichnete moderne Attraktionen und jede Menge Platz für Erweiterungen.
<Mystic Mountain>
STR_SCNR :Mystic Mountain
STR_PARK :Mystic Mountain
STR_DTLS :Bauen Sie in den bergigen Wäldern der Mystic Mountains einen neuen Freizeitpark.
<Pacific Pyramids>
STR_SCNR :Pacific Pyramids
STR_PARK :Pacific Pyramids
STR_DTLS :Verwandeln Sie die Touristenattraktion mit ägyptischen Ruinen in einen erfolgreichen Freizeitpark.
<Crumbly Woods>
STR_SCNR :Crumbly Woods
STR_PARK :Crumbly Woods
STR_DTLS :Ein großer Park mit guten, aber ziemlich alten Attraktionen. Ersetzen Sie die alten Attraktionen oder fügen Sie neue hinzu, damit der Park mehr Leute anzieht.
<Paradise Pier>
STR_SCNR :Paradise Pier
STR_PARK :Paradise Pier
STR_DTLS :Verwandeln Sie die Anlegestelle dieser verschlafenen Stadt in einen wohlbekannten und gutgehenden Anziehungspunkt.
<Lightning Peaks>
STR_SCNR :Lightning Peaks
STR_PARK :Lightning Peaks
STR_DTLS :Die herrlichen Berge von Lightning Peaks sind beliebt bei Wanderern und Leuten, die gern interessante Orte besichtigen. Nutzen Sie das zur Verfügung stehende Gelände, um jene Besucher anzulocken, die auf der Suche nach einem aufregenden Kick sind.
<Ivory Towers>
STR_SCNR :Ivory Towers
STR_PARK :Ivory Towers
STR_DTLS :Ein gut geführter Park, der jedoch ein paar Probleme hat.
<Rainbow Valley>
STR_SCNR :Rainbow Valley
STR_PARK :Rainbow Valley
STR_DTLS :Die örtlichen Behörden von Rainbow Valley werden landschaftliche Veränderungen oder größere Baumrodungen nicht erlauben, aber Sie sollen in dem Gebiet einen großen Freizeitpark entstehen lassen.
<Thunder Rock>
STR_SCNR :Thunder Rock
STR_PARK :Thunder Rock
STR_DTLS :Thunder Rock befindet sich mitten in einer Wüste und zieht viele Touristen an. Bauen Sie auf dem verfügbaren Platz Attraktionen, die noch mehr Leute herlocken.
<Mega Park>
STR_SCNR :Mega Park
STR_PARK :Mega Park
STR_DTLS :Nur zum Spaß!
## Added Attractions
<Whispering Cliffs>
STR_SCNR :Whispering Cliffs
STR_PARK :Whispering Cliffs
STR_DTLS :Lassen Sie in diesen Klippen am Meer einen florierenden Vergnügungspark entstehen.
<Three Monkeys Park>
STR_SCNR :Three Monkeys Park
STR_PARK :Three Monkeys Park
STR_DTLS :Mitten in diesem großen, aufstrebenden Park steht eine riesige Dreispur-Achterbahn, in der die Fahrt wie ein Kopf-an-Kopf-Rennen abläuft.
<Canary Mines>
STR_SCNR :Canary Mines
STR_PARK :Canary Mines
STR_DTLS :Dieses verlassene Bergwerk bietet mit der Miniatureisenbahn und den Sturzachterbahnen bereits gute Voraussetzungen, eine Touristenattraktion zu werden.
<Barony Bridge>
STR_SCNR :Barony Bridge
STR_PARK :Barony Bridge
STR_DTLS :Wandeln Sie eine alte, nicht mehr benutzte Brücke in einen attraktiven Park um.
<Funtopia>
STR_SCNR :Funtopia
STR_PARK :Funtopia
STR_DTLS :In diesem Park zu beiden Seiten einer Autobahn sind bereits verschiedene Attraktionen in Betrieb.
<Haunted Harbor>
STR_SCNR :Haunted Harbor
STR_PARK :Haunted Harbor
STR_DTLS :Die örtlichen Behörden haben zugestimmt, dem kleinen Park an der Küste umliegendes Gelände günstig zu verkaufen, unter der Bedingung, dass bestimmte Attraktionen erhalten werden.
<Fun Fortress>
STR_SCNR :Fun Fortress
STR_PARK :Fun Fortress
STR_DTLS :Sie können Ihrer Fantasie freien Lauf lassen, damit ein Themenpark aus diesem Schloss entsteht.
<Future World>
STR_SCNR :Future World
STR_PARK :Future World
STR_DTLS :Dieser futuristische Park bietet auf seinem fremdartigen Gelände viel Platz für neue Attraktionen.
<Gentle Glen>
STR_SCNR :Gentle Glen
STR_PARK :Gentle Glen
STR_DTLS :Die Bevölkerung in der Umgebung bevorzugt gemäßigte Attraktionen, auf denen man sich erholen kann. Ihre Aufgabe ist es, diesen Ansprüchen gerecht zu werden.
<Jolly Jungle>
STR_SCNR :Jolly Jungle
STR_PARK :Jolly Jungle
STR_DTLS :Ein riesiges Gelände tief im Dschungel wartet darauf, von Ihnen in einen Themenpark umgewandelt zu werden.
<Hydro Hills>
STR_SCNR :Hydro Hills
STR_PARK :Hydro Hills
STR_DTLS :Eine Reihe terrassenförmig angeordneter Seen sind der Ausgangsort für den neuen Park.
<Sprightly Park>
STR_SCNR :Sprightly Park
STR_PARK :Sprightly Park
STR_DTLS :Dieser ältere Park besitzt viele historisch interessante Attraktionen, ist aber hoch verschuldet.
<Magic Quarters>
STR_SCNR :Magic Quarters
STR_PARK :Magic Quarters
STR_DTLS :Ein großes Gelände wurde freigeräumt und teilweise thematisch gestaltet. Sie sollen daraus einen interessante Themenlandschaft machen.
<Fruit Farm>
STR_SCNR :Fruit Farm
STR_PARK :Fruit Farm
STR_DTLS :Eine gutgehende Obstplantage hat eine Miniatureisenbahn bauen lassen, um die Einnahmen zu steigern. Entwickeln Sie jetzt daraus einen Vergnügungspark mit allem Drum und Dran.
<Butterfly Dam>
STR_SCNR :Butterfly Dam
STR_PARK :Butterfly Dam
STR_DTLS :Das Gebiet rings um einen Damm steht Ihnen zur Verfügung, damit daraus ein Vergnügungspark entsteht.
<Coaster Canyon>
STR_SCNR :Coaster Canyon
STR_PARK :Coaster Canyon
STR_DTLS :Ein weitläufiger Canyon steht Ihnen zur Verfügung, um in einen Themenpark verwandelt zu werden.
<Thunderstorm Park>
STR_SCNR :Thunderstorm Park
STR_PARK :Thunderstorm Park
STR_DTLS :Das Wetter in dieser Gegend ist so feucht, dass bereits eine riesengroße Pyramide gebaut wurde, damit wenigstens einige Attraktionen überdacht sind.
<Harmonic Hills>
STR_SCNR :Harmonic Hills
STR_PARK :Harmonic Hills
STR_DTLS :Die Baubehörde dieser Gegend erlaubt in diesem Park keine Konstruktionen über Baumhöhe.
<Roman Village>
STR_SCNR :Roman Village
STR_PARK :Roman Village
STR_DTLS :Entwickeln Sie diesen römisch gestalteten Park weiter, indem Sie Achterbahnen und andere Attraktionen hinzufügen.
<Swamp Cove>
STR_SCNR :Swamp Cove
STR_PARK :Swamp Cove
STR_DTLS :Dieser Park, der sich über eine Reihe kleiner Inseln erstreckt, besitzt ein Paar einer großen Achterbahn als Hauptattraktion.
<Adrenaline Heights>
STR_SCNR :Adrenaline Heights
STR_PARK :Adrenaline Heights
STR_DTLS :Bauen Sie einen Park für die Menschen dieser Gegend, die hohe Intensität und Nervenkitzel bevorzugen.
<Utopia Park>
STR_SCNR :Utopia Park
STR_PARK :Utopia Park
STR_DTLS :Eine Oase inmitten der Wüste ist sicher eine ungewöhnliche Herausforderung für Planer eines Vergnügungsparks.
<Rotting Heights>
STR_SCNR :Rotting Heights
STR_PARK :Rotting Heights
STR_DTLS :Überwuchert und verfallen. Können Sie diesen einst großartigen Vergnügungspark wieder zum Leben erwecken?
<Fiasco Forest>
STR_SCNR :Fiasco Forest
STR_PARK :Fiasco Forest
STR_DTLS :Hier gibt es fast nur gefährliche und schlecht geplante Attraktionen. Sie haben nur sehr begrenzte finanzielle Mittel und wenig Zeit, die Probleme zu beheben und den Park umzukrempeln.
<Pickle Park>
STR_SCNR :Pickle Park
STR_PARK :Pickle Park
STR_DTLS :Die strengen örtlichen Ämter erlauben keinerlei Werbung oder Propaganda. Dieser Park kann also nur durch seinen Ruf zum Erfolg gelangen.
<Giggle Downs>
STR_SCNR :Giggle Downs
STR_PARK :Giggle Downs
STR_DTLS :Eine vierspurige Bahn mit Renncharakter ist das Herzstück dieses aufstrebenden Parks.
<Mineral Park>
STR_SCNR :Mineral Park
STR_PARK :Mineral Park
STR_DTLS :Verwandeln Sie diesen verlassenen Steinbruch in einen Ort, der Touristen anzieht, die den besonderen Kick suchen.
<Coaster Crazy>
STR_SCNR :Coaster Crazy
STR_PARK :Coaster Crazy
STR_DTLS :Sie haben nur begrenzt Geld, aber jede Menge Zeit, aus diesem Berggelände einen riesigen Achterbahn-Park zu machen.
<Urban Park>
STR_SCNR :Urban Park
STR_PARK :Urban Park
STR_DTLS :Ein winzig kleiner Park hat mit der nahe gelegenen Stadt vereinbart, dass er sich durch die Stadt hindurch ausbreiten darf.
<Geoffrey Gardens>
STR_SCNR :Geoffrey Gardens
STR_PARK :Geoffrey Gardens
STR_DTLS :Eine große gepflegte Parkanlage soll in einen erfolgreichen Themenpark umgestaltet werden.
## Loopy Landscapes
<Iceberg Islands>
STR_SCNR :Iceberg Islands
STR_PARK :Iceberg Islands
STR_DTLS :Eine Anzahl Eisberge bilden die kalte Umgebung dieses anspruchsvollen Parkprojekts.
<Volcania>
STR_SCNR :Volcania
STR_PARK :Volcania
STR_DTLS :Ein untätiger Vulkan fordert geradezu heraus, an ihm eine Achterbahnanlage zu bauen.
<Arid Heights>
STR_SCNR :Arid Heights
STR_PARK :Arid Heights
STR_DTLS :Ohne jegliche finanzielle Einschränkungen sollen Sie diesen Wüstenpark ausbauen und dabei die Besucher bei Laune halten.
<Razor Rocks>
STR_SCNR :Razor Rocks
STR_PARK :Razor Rocks
STR_DTLS :Ihre Aufgabe ist es, zwischen den zerklüfteten Felsen einen Park mit dicht gedrängten Achterbahnen zu bauen.
<Crater Lake>
STR_SCNR :Crater Lake
STR_PARK :Crater Lake
STR_DTLS :Ein großer See in einem alten Krater ist Ausgangspunkt für diesen Park.
<Vertigo Views>
STR_SCNR :Vertigo Views
STR_PARK :Vertigo Views
STR_DTLS :Dieser große Park besitzt bereits eine ausgezeichnete Hyper-Achterbahn, aber Ihre Aufgabe ist es, die Erträge beträchtlich zu steigern.
<Paradise Pier 2>
STR_SCNR :Paradise Pier 2
STR_PARK :Paradise Pier 2
STR_DTLS :Paradise Pier hat sein Netz von Spazierwegen über dem Meer erweitert. Sie sollen den Park erweitern, indem Sie den neu gewonnenen Platz nutzen.
<Dragon's Cove>
STR_SCNR :Dragon's Cove
STR_PARK :Dragon's Cove
STR_DTLS :Eine Meeresbucht ist der Rahmen für dieses anspruchsvolle Achterbahn-Bauvorhaben.
<Good Knight Park>
STR_SCNR :Good Knight Park
STR_PARK :Good Knight Park
STR_DTLS :Ein Schloss mit ein paar Achterbahnen soll zu einem großen Vergnügungspark entwickelt werden.
<Wacky Warren>
STR_SCNR :Wacky Warren
STR_PARK :Wacky Warren
STR_DTLS :Ein Park, dessen Gehwege und Achterbahnen größtenteils unterirdisch angelegt sind.
<Grand Glacier>
STR_SCNR :Grand Glacier
STR_PARK :Grand Glacier
STR_DTLS :Es steht Ihnen ein Gletschertal zur Verfügung, das in einen Vergnügungspark zu verwandeln ist.
<Crazy Craters>
STR_SCNR :Crazy Craters
STR_PARK :Crazy Craters
STR_DTLS :In einer weit entfernten Welt, wo man Geld nicht braucht, sollen Sie ein Unterhaltungszentrum bauen, damit die Leute glücklich und zufrieden bleiben.
<Dusty Desert>
STR_SCNR :Dusty Desert
STR_PARK :Dusty Desert
STR_DTLS :Fünf Achterbahnen müssen in diesem Wüstenpark fertiggestellt werden.
<Woodworm Park>
STR_SCNR :Woodworm Park
STR_PARK :Woodworm Park
STR_DTLS :In diesem historischen Park dürfen nur Attraktionen im altmodischen Stil gebaut werden.
<Icarus Park>
STR_SCNR :Icarus Park
STR_PARK :Icarus Park
STR_DTLS :Verbessern Sie diesen außerirdischen Park, damit höchste Erträge erzielt werden.
<Sunny Swamps>
STR_SCNR :Sunny Swamps
STR_PARK :Sunny Swamps
STR_DTLS :In diesem nach Themen angelegten Park gibt es zwar verschiedene Attraktionen, aber noch viel Platz für Erweiterungen.
<Frightmare Hills>
STR_SCNR :Frightmare Hills
STR_PARK :Frightmare Hills
STR_DTLS :Ein Gruselpark mit einer Riesenachterbahn als Herzstück.
<Thunder Rocks>
STR_SCNR :Thunder Rocks
STR_PARK :Thunder Rocks
STR_DTLS :Zwei enorme Gesteinsbrocken ragen aus dem Wüstensand, auf denen mit den ersten Bauten für einen Vergnügungspark bereits begonnen wurde.
<Octagon Park>
STR_SCNR :Octagon Park
STR_PARK :Octagon Park
STR_DTLS :In diesem weitläufigen Park sollen Sie zehn große Achterbahnen entwerfen und konstruieren.
<Pleasure Island>
STR_SCNR :Pleasure Island
STR_PARK :Pleasure Island
STR_DTLS :Diese lange, schmale Insel ist Anreiz genug, eine Auswahl an Achterbahnen zu errichten.
<Icicle Worlds>
STR_SCNR :Icicle Worlds
STR_PARK :Icicle Worlds
STR_DTLS :Eine Eislandschaft soll in einen florierenden Vergnügungspark verwandelt werden.
<Southern Sands>
STR_SCNR :Southern Sands
STR_PARK :Southern Sands
STR_DTLS :Ein Park in der Wüste mit ein paar durchdachten Achterbahnen steht Ihnen zur Verfügung und soll erweitert werden.
<Tiny Towers>
STR_SCNR :Tiny Towers
STR_PARK :Tiny Towers
STR_DTLS :In diesem winzigen Park sollten Sie die fünf angefangenen Achterbahnen fertigstellen.
<Nevermore Park>
STR_SCNR :Nevermore Park
STR_PARK :Nevermore Park
STR_DTLS :Ein großer Park mit einem neuartigen Transportsystem, das durch die Randbereiche führt.
<Pacifica>
STR_SCNR :Pacifica
STR_PARK :Pacifica
STR_DTLS :Diese große Insel steht zu Ihrer Verfügung, machen Sie einen Vergnügungspark daraus.
<Urban Jungle>
STR_SCNR :Urban Jungle
STR_PARK :Urban Jungle
STR_DTLS :Ein gigantischer, verlassener Wolkenkratzer ist eine einmalige Gelegenheit für einen Vergnügungsparkbetreiber.
<Terror Town>
STR_SCNR :Terror Town
STR_PARK :Terror Town
STR_DTLS :Aus diesem Stadtgebiet können Sie einen Vergnügungspark zaubern.
<Megaworld Park>
STR_SCNR :Megaworld Park
STR_PARK :Megaworld Park
STR_DTLS :Ein ausgedehnter Park, der bereits mit Attraktionen vollgepackt ist, bedarf der Verbesserung.
<Venus Ponds>
STR_SCNR :Venus Ponds
STR_PARK :Venus Ponds
STR_DTLS :Auf einem weit entfernten Planeten soll dieses Stück Land in einen Vergnügungspark umgewandelt werden.
<Micro Park>
STR_SCNR :Micro Park
STR_PARK :Micro Park
STR_DTLS :Versuchen Sie, den kleinsten Park der Welt anzulegen und dabei möglichst viel Gewinn zu erzielen.
## Real Parks from RCT1
# None of them had details
<Alton Towers>
STR_SCNR :Alton Towers
STR_PARK :Alton Towers
STR_DTLS :
<Heide-Park>
STR_SCNR :Heide-Park
STR_PARK :Heide-Park
STR_DTLS :
<Blackpool Pleasure Beach>
STR_SCNR :Blackpool Pleasure Beach
STR_PARK :Blackpool Pleasure Beach
STR_DTLS :
## Misc parks from RCT1
# Had no details
<Fort Anachronism>
STR_SCNR :Fort Anachronism
STR_PARK :Fort Anachronism
STR_DTLS :
#######################
# Bahnen/Attraktionen #

View File

@ -604,172 +604,172 @@ STR_0599 :A compact roller coaster with individual cars and smooth twisting d
STR_0600 :Powered mine trains career along a smooth and twisted track layout
STR_0601 :
STR_0602 :Roller coaster trains are accelerated out of the station by linear induction motors to speed through twisting inversions
STR_0603 :Guest {INT32}
STR_0604 :Guest {INT32}
STR_0605 :Guest {INT32}
STR_0606 :Guest {INT32}
STR_0607 :Guest {INT32}
STR_0608 :Guest {INT32}
STR_0609 :Guest {INT32}
STR_0610 :Guest {INT32}
STR_0611 :Guest {INT32}
STR_0612 :Guest {INT32}
STR_0613 :Guest {INT32}
STR_0614 :Guest {INT32}
STR_0615 :Guest {INT32}
STR_0616 :Guest {INT32}
STR_0617 :Guest {INT32}
STR_0618 :Guest {INT32}
STR_0619 :Guest {INT32}
STR_0620 :Guest {INT32}
STR_0621 :Guest {INT32}
STR_0622 :Guest {INT32}
STR_0623 :Guest {INT32}
STR_0624 :Guest {INT32}
STR_0625 :Guest {INT32}
STR_0626 :Guest {INT32}
STR_0627 :Guest {INT32}
STR_0628 :Guest {INT32}
STR_0629 :Guest {INT32}
STR_0630 :Guest {INT32}
STR_0631 :Guest {INT32}
STR_0632 :Guest {INT32}
STR_0633 :Guest {INT32}
STR_0634 :Guest {INT32}
STR_0635 :Guest {INT32}
STR_0636 :Guest {INT32}
STR_0637 :Guest {INT32}
STR_0638 :Guest {INT32}
STR_0639 :Guest {INT32}
STR_0640 :Guest {INT32}
STR_0641 :Guest {INT32}
STR_0642 :Guest {INT32}
STR_0643 :Guest {INT32}
STR_0644 :Guest {INT32}
STR_0645 :Guest {INT32}
STR_0646 :Guest {INT32}
STR_0647 :Guest {INT32}
STR_0648 :Guest {INT32}
STR_0649 :Guest {INT32}
STR_0650 :Guest {INT32}
STR_0651 :Guest {INT32}
STR_0652 :Guest {INT32}
STR_0653 :Guest {INT32}
STR_0654 :Guest {INT32}
STR_0655 :Guest {INT32}
STR_0656 :Guest {INT32}
STR_0657 :Guest {INT32}
STR_0658 :Guest {INT32}
STR_0659 :Guest {INT32}
STR_0660 :Guest {INT32}
STR_0661 :Guest {INT32}
STR_0662 :Guest {INT32}
STR_0663 :Guest {INT32}
STR_0664 :Guest {INT32}
STR_0665 :Guest {INT32}
STR_0666 :Guest {INT32}
STR_0667 :Guest {INT32}
STR_0668 :Guest {INT32}
STR_0669 :Guest {INT32}
STR_0670 :Guest {INT32}
STR_0671 :Guest {INT32}
STR_0672 :Guest {INT32}
STR_0673 :Guest {INT32}
STR_0674 :Guest {INT32}
STR_0675 :Guest {INT32}
STR_0676 :Guest {INT32}
STR_0677 :Guest {INT32}
STR_0678 :Guest {INT32}
STR_0679 :Guest {INT32}
STR_0680 :Guest {INT32}
STR_0681 :Guest {INT32}
STR_0682 :Guest {INT32}
STR_0683 :Guest {INT32}
STR_0684 :Guest {INT32}
STR_0685 :Guest {INT32}
STR_0686 :Guest {INT32}
STR_0687 :Guest {INT32}
STR_0688 :Guest {INT32}
STR_0689 :Guest {INT32}
STR_0690 :Guest {INT32}
STR_0691 :Guest {INT32}
STR_0692 :Guest {INT32}
STR_0693 :Guest {INT32}
STR_0694 :Guest {INT32}
STR_0695 :Guest {INT32}
STR_0696 :Guest {INT32}
STR_0697 :Guest {INT32}
STR_0698 :Guest {INT32}
STR_0699 :Guest {INT32}
STR_0700 :Guest {INT32}
STR_0701 :Guest {INT32}
STR_0702 :Guest {INT32}
STR_0703 :Guest {INT32}
STR_0704 :Guest {INT32}
STR_0705 :Guest {INT32}
STR_0706 :Guest {INT32}
STR_0707 :Guest {INT32}
STR_0708 :Guest {INT32}
STR_0709 :Guest {INT32}
STR_0710 :Guest {INT32}
STR_0711 :Guest {INT32}
STR_0712 :Guest {INT32}
STR_0713 :Guest {INT32}
STR_0714 :Guest {INT32}
STR_0715 :Guest {INT32}
STR_0716 :Guest {INT32}
STR_0717 :Guest {INT32}
STR_0718 :Guest {INT32}
STR_0719 :Guest {INT32}
STR_0720 :Guest {INT32}
STR_0721 :Guest {INT32}
STR_0722 :Guest {INT32}
STR_0723 :Guest {INT32}
STR_0724 :Guest {INT32}
STR_0725 :Guest {INT32}
STR_0726 :Guest {INT32}
STR_0727 :Guest {INT32}
STR_0728 :Guest {INT32}
STR_0729 :Guest {INT32}
STR_0730 :Guest {INT32}
STR_0731 :Guest {INT32}
STR_0732 :Guest {INT32}
STR_0733 :Guest {INT32}
STR_0734 :Guest {INT32}
STR_0735 :Guest {INT32}
STR_0736 :Guest {INT32}
STR_0737 :Guest {INT32}
STR_0738 :Guest {INT32}
STR_0739 :Guest {INT32}
STR_0740 :Guest {INT32}
STR_0741 :Guest {INT32}
STR_0742 :Guest {INT32}
STR_0743 :Guest {INT32}
STR_0744 :Guest {INT32}
STR_0745 :Guest {INT32}
STR_0746 :Guest {INT32}
STR_0747 :Guest {INT32}
STR_0748 :Guest {INT32}
STR_0749 :Guest {INT32}
STR_0750 :Guest {INT32}
STR_0751 :Guest {INT32}
STR_0752 :Guest {INT32}
STR_0753 :Guest {INT32}
STR_0754 :Guest {INT32}
STR_0755 :Guest {INT32}
STR_0756 :Guest {INT32}
STR_0757 :Guest {INT32}
STR_0758 :Guest {INT32}
STR_0759 :Guest {INT32}
STR_0760 :Guest {INT32}
STR_0761 :Guest {INT32}
STR_0762 :Guest {INT32}
STR_0763 :Guest {INT32}
STR_0764 :Guest {INT32}
STR_0765 :Guest {INT32}
STR_0766 :Guest {INT32}
STR_0767 :Guest {INT32}
STR_0768 :Handyman {INT32}
STR_0603 :来客{INT32}
STR_0604 :来客{INT32}
STR_0605 :来客{INT32}
STR_0606 :来客{INT32}
STR_0607 :来客{INT32}
STR_0608 :来客{INT32}
STR_0609 :来客{INT32}
STR_0610 :来客{INT32}
STR_0611 :来客{INT32}
STR_0612 :来客{INT32}
STR_0613 :来客{INT32}
STR_0614 :来客{INT32}
STR_0615 :来客{INT32}
STR_0616 :来客{INT32}
STR_0617 :来客{INT32}
STR_0618 :来客{INT32}
STR_0619 :来客{INT32}
STR_0620 :来客{INT32}
STR_0621 :来客{INT32}
STR_0622 :来客{INT32}
STR_0623 :来客{INT32}
STR_0624 :来客{INT32}
STR_0625 :来客{INT32}
STR_0626 :来客{INT32}
STR_0627 :来客{INT32}
STR_0628 :来客{INT32}
STR_0629 :来客{INT32}
STR_0630 :来客{INT32}
STR_0631 :来客{INT32}
STR_0632 :来客{INT32}
STR_0633 :来客{INT32}
STR_0634 :来客{INT32}
STR_0635 :来客{INT32}
STR_0636 :来客{INT32}
STR_0637 :来客{INT32}
STR_0638 :来客{INT32}
STR_0639 :来客{INT32}
STR_0640 :来客{INT32}
STR_0641 :来客{INT32}
STR_0642 :来客{INT32}
STR_0643 :来客{INT32}
STR_0644 :来客{INT32}
STR_0645 :来客{INT32}
STR_0646 :来客{INT32}
STR_0647 :来客{INT32}
STR_0648 :来客{INT32}
STR_0649 :来客{INT32}
STR_0650 :来客{INT32}
STR_0651 :来客{INT32}
STR_0652 :来客{INT32}
STR_0653 :来客{INT32}
STR_0654 :来客{INT32}
STR_0655 :来客{INT32}
STR_0656 :来客{INT32}
STR_0657 :来客{INT32}
STR_0658 :来客{INT32}
STR_0659 :来客{INT32}
STR_0660 :来客{INT32}
STR_0661 :来客{INT32}
STR_0662 :来客{INT32}
STR_0663 :来客{INT32}
STR_0664 :来客{INT32}
STR_0665 :来客{INT32}
STR_0666 :来客{INT32}
STR_0667 :来客{INT32}
STR_0668 :来客{INT32}
STR_0669 :来客{INT32}
STR_0670 :来客{INT32}
STR_0671 :来客{INT32}
STR_0672 :来客{INT32}
STR_0673 :来客{INT32}
STR_0674 :来客{INT32}
STR_0675 :来客{INT32}
STR_0676 :来客{INT32}
STR_0677 :来客{INT32}
STR_0678 :来客{INT32}
STR_0679 :来客{INT32}
STR_0680 :来客{INT32}
STR_0681 :来客{INT32}
STR_0682 :来客{INT32}
STR_0683 :来客{INT32}
STR_0684 :来客{INT32}
STR_0685 :来客{INT32}
STR_0686 :来客{INT32}
STR_0687 :来客{INT32}
STR_0688 :来客{INT32}
STR_0689 :来客{INT32}
STR_0690 :来客{INT32}
STR_0691 :来客{INT32}
STR_0692 :来客{INT32}
STR_0693 :来客{INT32}
STR_0694 :来客{INT32}
STR_0695 :来客{INT32}
STR_0696 :来客{INT32}
STR_0697 :来客{INT32}
STR_0698 :来客{INT32}
STR_0699 :来客{INT32}
STR_0700 :来客{INT32}
STR_0701 :来客{INT32}
STR_0702 :来客{INT32}
STR_0703 :来客{INT32}
STR_0704 :来客{INT32}
STR_0705 :来客{INT32}
STR_0706 :来客{INT32}
STR_0707 :来客{INT32}
STR_0708 :来客{INT32}
STR_0709 :来客{INT32}
STR_0710 :来客{INT32}
STR_0711 :来客{INT32}
STR_0712 :来客{INT32}
STR_0713 :来客{INT32}
STR_0714 :来客{INT32}
STR_0715 :来客{INT32}
STR_0716 :来客{INT32}
STR_0717 :来客{INT32}
STR_0718 :来客{INT32}
STR_0719 :来客{INT32}
STR_0720 :来客{INT32}
STR_0721 :来客{INT32}
STR_0722 :来客{INT32}
STR_0723 :来客{INT32}
STR_0724 :来客{INT32}
STR_0725 :来客{INT32}
STR_0726 :来客{INT32}
STR_0727 :来客{INT32}
STR_0728 :来客{INT32}
STR_0729 :来客{INT32}
STR_0730 :来客{INT32}
STR_0731 :来客{INT32}
STR_0732 :来客{INT32}
STR_0733 :来客{INT32}
STR_0734 :来客{INT32}
STR_0735 :来客{INT32}
STR_0736 :来客{INT32}
STR_0737 :来客{INT32}
STR_0738 :来客{INT32}
STR_0739 :来客{INT32}
STR_0740 :来客{INT32}
STR_0741 :来客{INT32}
STR_0742 :来客{INT32}
STR_0743 :来客{INT32}
STR_0744 :来客{INT32}
STR_0745 :来客{INT32}
STR_0746 :来客{INT32}
STR_0747 :来客{INT32}
STR_0748 :来客{INT32}
STR_0749 :来客{INT32}
STR_0750 :来客{INT32}
STR_0751 :来客{INT32}
STR_0752 :来客{INT32}
STR_0753 :来客{INT32}
STR_0754 :来客{INT32}
STR_0755 :来客{INT32}
STR_0756 :来客{INT32}
STR_0757 :来客{INT32}
STR_0758 :来客{INT32}
STR_0759 :来客{INT32}
STR_0760 :来客{INT32}
STR_0761 :来客{INT32}
STR_0762 :来客{INT32}
STR_0763 :来客{INT32}
STR_0764 :来客{INT32}
STR_0765 :来客{INT32}
STR_0766 :来客{INT32}
STR_0767 :来客{INT32}
STR_0768 :便利屋 {INT32}
STR_0769 :Mechanic {INT32}
STR_0770 :Security Guard {INT32}
STR_0771 :Entertainer {INT32}
@ -779,7 +779,7 @@ STR_0774 :Unnamed park{POP16}{POP16}
STR_0775 :Unnamed park{POP16}{POP16}
STR_0776 :Unnamed park{POP16}{POP16}
STR_0777 :Unnamed park{POP16}{POP16}
STR_0778 :Sign
STR_0778 :バナー
STR_0779 :1日
STR_0780 :2日
STR_0781 :3日
@ -829,12 +829,12 @@ STR_0824 :{BLACK}{CROSS}
STR_0825 :Chosen name in use already
STR_0826 :Too many names defined
STR_0827 :Not enough cash - requires {CURRENCY2DP}
STR_0828 :{SMALLFONT}{BLACK}Close window
STR_0829 :{SMALLFONT}{BLACK}Window title - Drag this to move window
STR_0830 :{SMALLFONT}{BLACK}Zoom view in
STR_0831 :{SMALLFONT}{BLACK}Zoom view out
STR_0832 :{SMALLFONT}{BLACK}Rotate view 90{DEGREE} clockwise
STR_0833 :{SMALLFONT}{BLACK}Pause game
STR_0828 :{SMALLFONT}{BLACK}ウィンドウを閉める
STR_0829 :{SMALLFONT}{BLACK}ウィンドウのタイトル - これをドラッグさせる
STR_0830 :{SMALLFONT}{BLACK}ズームアウト
STR_0831 :{SMALLFONT}{BLACK}ズームイン
STR_0832 :{SMALLFONT}{BLACK}時計回90{DEGREE}りに移動させる
STR_0833 :{SMALLFONT}{BLACK}ゲームをポーズする
STR_0834 :{SMALLFONT}{BLACK}Disk and game options
STR_0835 :Game initialisation failed
STR_0836 :Unable to start game in a minimised state
@ -884,16 +884,16 @@ STR_0878 :高すぎる!
STR_0879 :Can't lower land here...
STR_0880 :Can't raise land here...
STR_0881 :Object in the way
STR_0882 :Load Game
STR_0883 :Save Game
STR_0884 :Load Landscape
STR_0885 :Save Landscape
STR_0886 :Quit Game
STR_0887 :Quit Scenario Editor
STR_0888 :Quit Roller Coaster Designer
STR_0889 :Quit Track Designs Manager
STR_0882 :ゲームを再更新する
STR_0883 :ゲームをセーブする
STR_0884 :景色を再更新する
STR_0885 :景色をセーブする
STR_0886 :ゲームを閉じる
STR_0887 :Scenario Editorを閉じる
STR_0888 :Roller Coaster Designerを閉じる
STR_0889 :Track Designs Managerを閉じる
STR_0890 :SCR{COMMA16}.BMP
STR_0891 :Screenshot
STR_0891 :スクリーンショット
STR_0892 :Screenshot saved to disk as '{STRINGID}'
STR_0893 :Screenshot failed !
STR_0894 :Landscape data area full !
@ -952,9 +952,9 @@ STR_0946 :Cancel
STR_0947 :Save this before loading ?
STR_0948 :Save this before quitting ?
STR_0949 :Save this before quitting ?
STR_0950 :Load Game
STR_0951 :Quit Game
STR_0952 :Quit Game
STR_0950 :ゲームを再更新する
STR_0951 :ゲームを閉じる
STR_0952 :ゲームを閉じる
STR_0953 :Load Landscape
STR_0954 :
STR_0955 :{SMALLFONT}{BLACK}Select seat rotation angle for this track section
@ -974,7 +974,7 @@ STR_0968 :+360{DEGREE}
STR_0969 :+405{DEGREE}
STR_0970 :+450{DEGREE}
STR_0971 :+495{DEGREE}
STR_0972 :Cancel
STR_0972 :キャンセル
STR_0973 :OK
STR_0974 :Rides
STR_0975 :Shops and Stalls
@ -1112,11 +1112,11 @@ STR_1106 :Crashing!
STR_1107 :Crashed!
STR_1108 :Travelling at {VELOCITY}
STR_1109 :Swinging
STR_1110 :Rotating
STR_1111 :Rotating
STR_1110 :回転させる
STR_1111 :回転させる
STR_1112 :Operating
STR_1113 :Showing film
STR_1114 :Rotating
STR_1114 :回転させる
STR_1115 :Operating
STR_1116 :Operating
STR_1117 :Doing circus show
@ -1170,7 +1170,7 @@ STR_1164 :{STRINGID}{NEWLINE}(Right-Click to Remove)
STR_1165 :{STRINGID} - {STRINGID} {COMMA16}
STR_1166 :Can't lower water level here...
STR_1167 :Can't raise water level here...
STR_1168 :Options
STR_1168 :設定
STR_1169 :(None)
STR_1170 :{STRING}
STR_1171 :{RED}Closed - -
@ -1465,7 +1465,7 @@ STR_1459 :Track style
STR_1460 :{SMALLFONT}{BLACK}'U' shaped open track
STR_1461 :{SMALLFONT}{BLACK}'O' shaped enclosed track
STR_1462 :Too steep for lift hill
STR_1463 :Guests
STR_1463 :来客
STR_1464 :Helix up (small)
STR_1465 :Helix up (large)
STR_1466 :Helix down (small)
@ -1695,14 +1695,14 @@ STR_1689 :Block brakes
STR_1690 :{WINDOW_COLOUR_2}{STRINGID}{NEWLINE}{BLACK}{STRINGID}
STR_1691 :{WINDOW_COLOUR_2} Cost: {BLACK}{CURRENCY}
STR_1692 :{WINDOW_COLOUR_2} Cost: {BLACK}from {CURRENCY}
STR_1693 :{SMALLFONT}{BLACK}Guests
STR_1693 :{SMALLFONT}{BLACK}来客
STR_1694 :{SMALLFONT}{BLACK}Staff
STR_1695 :{SMALLFONT}{BLACK}Income and costs
STR_1696 :{SMALLFONT}{BLACK}Customer information
STR_1697 :Cannot place these on queue line area
STR_1698 :Can only place these on queue area
STR_1699 :Too many people in game
STR_1700 :Hire new Handyman
STR_1700 :便利屋を雇います
STR_1701 :Hire new Mechanic
STR_1702 :Hire new Security Guard
STR_1703 :Hire new Entertainer
@ -1756,8 +1756,8 @@ STR_1750 :{DURATION}
STR_1751 :Can't change time limit for ride...
STR_1752 :{SMALLFONT}{BLACK}Show list of individual guests in park
STR_1753 :{SMALLFONT}{BLACK}Show summarised list of guests in park
STR_1754 :{BLACK}{COMMA16} guests
STR_1755 :{BLACK}{COMMA16} guest
STR_1754 :{BLACK}{COMMA16} 来客
STR_1755 :{BLACK}{COMMA16} 来客
STR_1756 :{WINDOW_COLOUR_2}Admission price:
STR_1757 :{WINDOW_COLOUR_2}Reliability: {MOVE_X}{255}{BLACK}{COMMA16}%
STR_1758 :{SMALLFONT}{BLACK}Build mode
@ -1848,9 +1848,9 @@ STR_1842 :Favourite of: {COMMA16} guest
STR_1843 :Favourite of: {COMMA16} guests
STR_1844 :{SMALLFONT}{BLACK}Select information type to show in ride/attraction list
STR_1845 :{MONTHYEAR}
STR_1846 :{COMMA16} guests
STR_1847 :{INLINE_SPRITE}{11}{20}{00}{00}{COMMA16} guests
STR_1848 :{INLINE_SPRITE}{10}{20}{00}{00}{COMMA16} guests
STR_1846 :{COMMA16}人の来客
STR_1847 :{INLINE_SPRITE}{11}{20}{00}{00}{COMMA16}人の来客
STR_1848 :{INLINE_SPRITE}{10}{20}{00}{00}{COMMA16}人の来客
STR_1849 :{WINDOW_COLOUR_2}Play music
STR_1850 :{SMALLFONT}{BLACK}Select whether music should be played for this ride
STR_1851 :{WINDOW_COLOUR_2}Running cost: {BLACK}{CURRENCY2DP} per hour
@ -1861,11 +1861,11 @@ STR_1855 :{WINDOW_COLOUR_2}Built: {BLACK}{COMMA16} Years Ago
STR_1856 :{WINDOW_COLOUR_2}Profit per item sold: {BLACK}{CURRENCY2DP}
STR_1857 :{WINDOW_COLOUR_2}Loss per item sold: {BLACK}{CURRENCY2DP}
STR_1858 :{WINDOW_COLOUR_2}Cost: {BLACK}{CURRENCY2DP} per month
STR_1859 :Handymen
STR_1859 :便利屋
STR_1860 :Mechanics
STR_1861 :Security Guards
STR_1862 :Entertainers
STR_1863 :Handyman
STR_1863 :便利屋
STR_1864 :Mechanic
STR_1865 :Security Guard
STR_1866 :Entertainer
@ -1880,15 +1880,15 @@ STR_1874 :{WINDOW_COLOUR_2}Profit: {BLACK}{CURRENCY2DP} per hour
STR_1875 :{BLACK} {SPRITE}{BLACK} {STRINGID}
STR_1876 :{WINDOW_COLOUR_2}{INLINE_SPRITE}{251}{19}{00}{00}Inspect Rides
STR_1877 :{WINDOW_COLOUR_2}{INLINE_SPRITE}{252}{19}{00}{00}Fix Rides
STR_1878 :{WINDOW_COLOUR_2}Inspection:
STR_1879 :Every 10 minutes
STR_1880 :Every 20 minutes
STR_1881 :Every 30 minutes
STR_1882 :Every 45 minutes
STR_1883 :Every hour
STR_1884 :Every 2 hours
STR_1885 :Never
STR_1886 :Inspecting {STRINGID}
STR_1878 :{WINDOW_COLOUR_2}改めるの:
STR_1879 :毎10分
STR_1880 :毎20分
STR_1881 :毎30分
STR_1882 :毎45分
STR_1883 :毎1時間
STR_1884 :毎2時間
STR_1885 :改めない
STR_1886 :{STRINGID}を改めります
STR_1887 :{WINDOW_COLOUR_2}Time since last inspection: {BLACK}{COMMA16} minutes
STR_1888 :{WINDOW_COLOUR_2}Time since last inspection: {BLACK}more than 4 hours
STR_1889 :{WINDOW_COLOUR_2}Down-Time: {MOVE_X}{255}{BLACK}{COMMA16}%
@ -2025,24 +2025,24 @@ STR_2017 :Cuddly Toys
STR_2018 :Park Maps
STR_2019 :On-Ride Photos
STR_2020 :Umbrellas
STR_2021 :Drinks
STR_2022 :Burgers
STR_2023 :Chips
STR_2024 :Ice Creams
STR_2025 :Candyfloss
STR_2026 :Empty Cans
STR_2027 :Rubbish
STR_2021 :ドリンク
STR_2022 :バーガー
STR_2023 :フライ
STR_2024 :ソフトクリーム
STR_2025 :綿菓子
STR_2026 :空き缶
STR_2027 :ごみ
STR_2028 :Empty Burger Boxes
STR_2029 :Pizzas
STR_2029 :ピザ
STR_2030 :Vouchers
STR_2031 :Popcorn
STR_2032 :Hot Dogs
STR_2031 :ポップコーン
STR_2032 :ホットドッグ
STR_2033 :Tentacles
STR_2034 :Hats
STR_2034 :帽子
STR_2035 :Toffee Apples
STR_2036 :T-Shirts
STR_2037 :Doughnuts
STR_2038 :Coffees
STR_2036 :ティーシャツ
STR_2037 :ドーナツ
STR_2038 :コーヒー
STR_2039 :Empty Cups
STR_2040 :Fried Chicken
STR_2041 :Lemonade
@ -2331,13 +2331,13 @@ STR_2323 :{WINDOW_COLOUR_2}Park size: {BLACK}{COMMA32}m{SQUARED}
STR_2324 :{WINDOW_COLOUR_2}Park size: {BLACK}{COMMA32}sq.ft.
STR_2325 :{SMALLFONT}{BLACK}Buy land to extend park
STR_2326 :{SMALLFONT}{BLACK}Buy construction rights to allow construction above or below land outside the park
STR_2327 :Options
STR_2328 :{WINDOW_COLOUR_2}Currency:
STR_2329 :{WINDOW_COLOUR_2}Distance and Speed:
STR_2330 :{WINDOW_COLOUR_2}Temperature:
STR_2331 :{WINDOW_COLOUR_2}Height Labels:
STR_2332 :Units
STR_2333 :Sound
STR_2327 :設定
STR_2328 :{WINDOW_COLOUR_2}通貨:
STR_2329 :{WINDOW_COLOUR_2}距離と速力:
STR_2330 :{WINDOW_COLOUR_2}温度:
STR_2331 :{WINDOW_COLOUR_2}高さのマーカー:
STR_2332 :単位
STR_2333 :効果音
STR_2334 :パウンド ({POUND})
STR_2335 :ドル ($)
STR_2336 :フラン (F)
@ -2345,7 +2345,7 @@ STR_2337 :ドイツマルク (DM)
STR_2338 :円 ({YEN})
STR_2339 :ペセタ (Pts)
STR_2340 :リラ (L)
STR_2341 :Guilders (fl.)
STR_2341 :フローリン (fl.)
STR_2342 :クローナ (kr)
STR_2343 :ユーロ ({EURO})
STR_2344 :Imperial
@ -2440,7 +2440,7 @@ STR_2432 :{BLACK}Vouchers for half-price entry to {STRINGID}
STR_2433 :{BLACK}Vouchers for free {STRINGID}
STR_2434 :{BLACK}Advertising campaign for {STRINGID}
STR_2435 :{BLACK}Advertising campaign for {STRINGID}
STR_2436 :1 week
STR_2436 :1週間
STR_2437 :<not used anymore>
STR_2438 :<not used anymore>
STR_2439 :<not used anymore>
@ -2727,26 +2727,26 @@ STR_2718 :Up
STR_2719 :New file
STR_2720 :{UINT16}秒
STR_2721 :{UINT16}秒
STR_2722 :{UINT16}分:{UINT16}sec
STR_2723 :{UINT16}分:{UINT16}secs
STR_2724 :{UINT16}分:{UINT16}sec
STR_2725 :{UINT16}分:{UINT16}secs
STR_2722 :{UINT16}分{UINT16}秒
STR_2723 :{UINT16}分{UINT16}秒
STR_2724 :{UINT16}分{UINT16}秒
STR_2725 :{UINT16}分{UINT16}秒
STR_2726 :{UINT16}分
STR_2727 :{UINT16}分
STR_2728 :{UINT16}時間:{UINT16}min
STR_2729 :{UINT16}時間:{UINT16}mins
STR_2730 :{UINT16}時間:{UINT16}min
STR_2731 :{UINT16}時間:{UINT16}mins
STR_2728 :{UINT16}時{UINT16}分
STR_2729 :{UINT16}時{UINT16}分
STR_2730 :{UINT16}時{UINT16}分
STR_2731 :{UINT16}時{UINT16}分
STR_2732 :{COMMA16}ft
STR_2733 :{COMMA16}m
STR_2734 :{COMMA16}mph
STR_2735 :{COMMA16}km/h
STR_2736 :{MONTH}, 第{COMMA16}年
STR_2737 :{STRINGID} {MONTH}, 第{COMMA16}年
STR_2736 :{MONTH}{COMMA16}年
STR_2737 :{STRINGID} {MONTH}{COMMA16}年
STR_2738 :Title screen music:
STR_2739 :None
STR_2740 :ローラーコースター タイクーン 1
STR_2741 :ローラーコースター タイクーン 2
STR_2740 :RollerCoaster Tycoon 1
STR_2741 :RollerCoaster Tycoon 2
STR_2742 :css50.dat not found
STR_2743 :Copy data\css17.dat from your RCT1 installation to data\css50.dat in your RCT2 installation.
STR_2744 :[
@ -2782,7 +2782,7 @@ STR_2772 :Faster Gamespeed
STR_2773 :Windowed
STR_2774 :Fullscreen
STR_2775 :Fullscreen (desktop)
STR_2776 :Language:
STR_2776 :言語:
STR_2777 :{MOVE_X}{SMALLFONT}{STRING}
STR_2778 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRING}
STR_2779 :Viewport #{COMMA16}
@ -2998,7 +2998,7 @@ STR_2987 :{SMALLFONT}{BLACK}Set this banner as a 'no-entry' sign for guests
STR_2988 :{SMALLFONT}{BLACK}Demolish this banner
STR_2989 :{SMALLFONT}{BLACK}Select main colour
STR_2990 :{SMALLFONT}{BLACK}Select text colour
STR_2991 :Sign
STR_2991 :バナー
STR_2992 :Sign text
STR_2993 :Enter new text for this sign:
STR_2994 :{SMALLFONT}{BLACK}Change text on sign
@ -3138,7 +3138,7 @@ STR_3127 :{WINDOW_COLOUR_2}Nausea Factor: {BLACK}+{COMMA16}%
STR_3128 :Save Track Design
STR_3129 :Save Track Design with Scenery
STR_3130 :Save
STR_3131 :Cancel
STR_3131 :キャンセル
STR_3132 :{BLACK}Click items of scenery to select them to be saved with track design...
STR_3133 :Unable to build this on a slope
STR_3134 :{RED}(Design includes scenery which is unavailable)
@ -3449,11 +3449,11 @@ STR_3436 :{SMALLFONT}{BLACK}While waiting for our first riders, we could cust
STR_3437 :{SMALLFONT}{BLACK}Clear large areas of scenery from landscape
STR_3438 :Unable to remove all scenery from here...
STR_3439 :Clear Scenery
STR_3440 :Page 1
STR_3441 :Page 2
STR_3442 :Page 3
STR_3443 :Page 4
STR_3444 :Page 5
STR_3440 :1ページ目
STR_3441 :2ページ目
STR_3442 :3ページ目
STR_3443 :4ページ目
STR_3444 :5ページ目
STR_3445 :Set Patrol Area
STR_3446 :Cancel Patrol Area
@ -3498,10 +3498,10 @@ STR_5156 :{SMALLFONT}{BLACK}Allows testing of most ride types even when the t
STR_5157 :Unlock all prices
STR_5158 :Quit to menu
STR_5159 :Exit OpenRCT2
STR_5160 :{POP16}{MONTH} {PUSH16}{PUSH16}{STRINGID}, Year {POP16}{COMMA16}
STR_5160 :{POP16}{MONTH} {PUSH16}{PUSH16}{STRINGID} {POP16}{COMMA16}
STR_5161 :Date Format:
STR_5162 :Day/Month/Year
STR_5163 :Month/Day/Year
STR_5162 :日月年
STR_5163 :月日年
STR_5164 :Twitch Channel name
STR_5165 :Name peeps after followers
STR_5166 :{SMALLFONT}{BLACK}Will name peeps after channel's Twitch followers
@ -3634,8 +3634,8 @@ STR_5292 :{SMALLFONT}{BLACK}Force a breakdown
STR_5293 :{SMALLFONT}{BLACK}Close ride/attraction
STR_5294 :{SMALLFONT}{BLACK}Test ride/attraction
STR_5295 :{SMALLFONT}{BLACK}Open ride/attraction
STR_5296 :{SMALLFONT}{BLACK}Close park
STR_5297 :{SMALLFONT}{BLACK}Open park
STR_5296 :{SMALLFONT}{BLACK}遊園地を閉める
STR_5297 :{SMALLFONT}{BLACK}遊園地を開ける
STR_5298 :{RED}{STRINGID}
STR_5299 :{LIGHTPINK}{STRINGID}
STR_5300 :{SMALLFONT}{BLACK}Quick fire staff
@ -3643,10 +3643,10 @@ STR_5301 :{MEDIUMFONT}{BLACK}Clear your loan
STR_5302 :Clear loan
STR_5303 :Allow building in pause mode
STR_5304 :Title Sequence:
STR_5305 :ローラーコースター タイクーン 1
STR_5306 :ローラーコースター タイクーン 1 (AA)
STR_5307 :ローラーコースター タイクーン 1 (AA + 遊園地再生計画)
STR_5308 :ローラーコースター タイクーン 2
STR_5305 :RollerCoaster Tycoon 1
STR_5306 :RollerCoaster Tycoon 1 (AA)
STR_5307 :RollerCoaster Tycoon 1 (AA + LL)
STR_5308 :RollerCoaster Tycoon 2
STR_5309 :OpenRCT2
STR_5310 :ランダム
STR_5311 :{SMALLFONT}{BLACK}デバグツール
@ -3819,7 +3819,7 @@ STR_5477 :Map rendering
STR_5478 :Controls
STR_5479 :Toolbar
STR_5480 :Show toolbar buttons for:
STR_5481 :Themes
STR_5481 :スタイル
STR_5482 :{WINDOW_COLOUR_2}Time since last inspection: {BLACK}1 minute
STR_5483 :{BLACK}({COMMA16} weeks remaining)
STR_5484 :{BLACK}({COMMA16} week remaining)
@ -3850,7 +3850,7 @@ STR_5508 :Allow loading files with incorrect checksums
STR_5509 :{SMALLFONT}{BLACK}Allows loading scenarios and saves that have an incorrect checksum, like the scenarios from the demo or damaged saves.
STR_5510 :Default sound device
STR_5511 :(UNKNOWN)
STR_5512 :Save Game As
STR_5512 :名前を保存
STR_5513 :(Quick) save game
STR_5514 :Disable vandalism
STR_5515 :{SMALLFONT}{BLACK}Stops guests from vandalising your park when they're angry
@ -3888,9 +3888,9 @@ STR_5546 :{SMALLFONT}{BLACK}Bright pink
STR_5547 :{SMALLFONT}{BLACK}Light pink
STR_5548 :Show all operating modes
STR_5549 :年月日
STR_5550 :{POP16}{POP16}{COMMA16}年, {PUSH16}{PUSH16}{MONTH} {PUSH16}{PUSH16}{STRINGID}
STR_5551 :Year/Day/Month
STR_5552 :{POP16}{POP16}{COMMA16}年, {PUSH16}{PUSH16}{PUSH16}{STRINGID} {MONTH}
STR_5550 :{POP16}{POP16}{COMMA16}年 {PUSH16}{PUSH16}{MONTH} {PUSH16}{PUSH16}{STRINGID}
STR_5551 :年日月
STR_5552 :{POP16}{POP16}{COMMA16}年 {PUSH16}{PUSH16}{PUSH16}{STRINGID} {MONTH}
STR_5553 :Pause game when Steam overlay is open
STR_5554 :{SMALLFONT}{BLACK}Enable mountain tool
STR_5555 :Show vehicles from other track types

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,98 @@
# RollerCoaster Tycoon 1 Title Sequence
##############################
# RollerCoaster Tycoon 1 #
##############################
# SC_DIAMOND_HEIGHTS
LOADRCT1 3
ROTATE 2
LOCATION 47, 99
WAIT 15
ROTATE 2
LOCATION 90, 48
WAIT 15
ROTATE 1
LOCATION 86, 43
WAIT 15
ROTATE 3
LOCATION 57, 50
WAIT 15
ROTATE 2
LOCATION 86, 64
WAIT 15
# SC_KATIES_DREAMLAND
LOADRCT1 7
LOCATION 48, 44
WAIT 15
LOCATION 64, 41
WAIT 15
# SC_POKEY_PARK,
LOADRCT1 8
ROTATE 2
LOCATION 56, 64
WAIT 15
# SC_WHITE_WATER_PARK
LOADRCT1 9
ROTATE 3
LOCATION 96, 88
WAIT 15
LOCATION 84, 95
WAIT 15
# SC_MILLENNIUM_MINES
LOADRCT1 10
ROTATE 1
ROTATE 1
LOCATION 64, 37
WAIT 15
# SC_KARTS_COASTERS
LOADRCT1 11
LOCATION 84, 56
WAIT 15
LOCATION 34, 36
WAIT 15
LOCATION 33, 65
WAIT 15
# SC_MELS_WORLD
LOADRCT1 12
ROTATE 3
LOCATION 50, 50
WAIT 15
LOCATION 35, 39
WAIT 15
ROTATE 3
LOCATION 62, 39
WAIT 15
# SC_CRUMBLY_WOODS
LOADRCT1 15
ROTATE 3
LOCATION 57, 94
WAIT 15
LOCATION 44, 84
WAIT 15
ROTATE 1
LOCATION 76, 59
WAIT 15
LOCATION 76, 48
WAIT 15
# SC_LIGHTNING_PEAKS
LOADRCT1 17
LOCATION 80, 49
WAIT 15
LOCATION 60, 62
WAIT 15
# SC_IVORY_TOWERS
LOADRCT1 18
ROTATE 3
LOCATION 50, 77
WAIT 15
RESTART

View File

@ -0,0 +1,187 @@
# RollerCoaster Tycoon 1 Title Sequence
##############################
# Added Attractions #
##############################
# SC_HAUNTED_HARBOR
LOADRCT1 45
LOCATION 62, 53
WAIT 11
ROTATE 3
LOCATION 78, 45
WAIT 16
# SC_CANARY_MINES
LOADRCT1 42
LOCATION 52, 28
WAIT 15
# SC_GENTLE_GLEN
LOADRCT1 48
LOCATION 68, 45
WAIT 11
# SC_FUNTOPIA
LOADRCT1 44
LOCATION 69, 93
WAIT 17
# SC_SPRIGHTLY_PARK
LOADRCT1 51
ROTATE 3
LOCATION 97, 72
WAIT 12
ROTATE 2
LOCATION 74, 71
WAIT 12
ROTATE 2
LOCATION 67, 90
WAIT 12
# SC_GIGGLE_DOWNS
LOADRCT1 65
LOCATION 94, 64
WAIT 10
# SC_SWAMP_COVE
LOADRCT1 59
LOCATION 96, 22
WAIT 10
ROTATE 3
LOCATION 90, 29
WAIT 10
# SC_FRUIT_FARM
LOADRCT1 53
LOCATION 47, 52
WAIT 12
# SC_FUTURE_WORLD
LOADRCT1 47
LOCATION 67, 59
WAIT 19
# SC_THREE_MONKEYS_PARK
LOADRCT1 41
ROTATE 2
LOCATION 72, 61
WAIT 8
ROTATE 2
LOCATION 68, 70
WAIT 8
LOCATION 58, 56
WAIT 8
ROTATE 1
LOCATION 44, 70
WAIT 8
ROTATE 3
LOCATION 43, 90
WAIT 10
# SC_ROMAN_VILLAGE
LOADRCT1 58
LOCATION 49, 46
WAIT 15
# SC_ADRENALINE_HEIGHTS
LOADRCT1 60
ROTATE 3
LOCATION 38, 57
WAIT 15
##############################
# RollerCoaster Tycoon 1 #
##############################
# SC_DIAMOND_HEIGHTS
LOADRCT1 3
ROTATE 2
LOCATION 47, 99
WAIT 15
ROTATE 2
LOCATION 90, 48
WAIT 15
ROTATE 1
LOCATION 86, 43
WAIT 15
ROTATE 3
LOCATION 57, 50
WAIT 15
ROTATE 2
LOCATION 86, 64
WAIT 15
# SC_KATIES_DREAMLAND
LOADRCT1 7
LOCATION 48, 44
WAIT 15
LOCATION 64, 41
WAIT 15
# SC_POKEY_PARK,
LOADRCT1 8
ROTATE 2
LOCATION 56, 64
WAIT 15
# SC_WHITE_WATER_PARK
LOADRCT1 9
ROTATE 3
LOCATION 96, 88
WAIT 15
LOCATION 84, 95
WAIT 15
# SC_MILLENNIUM_MINES
LOADRCT1 10
ROTATE 1
ROTATE 1
LOCATION 64, 37
WAIT 15
# SC_KARTS_COASTERS
LOADRCT1 11
LOCATION 84, 56
WAIT 15
LOCATION 34, 36
WAIT 15
LOCATION 33, 65
WAIT 15
# SC_MELS_WORLD
LOADRCT1 12
ROTATE 3
LOCATION 50, 50
WAIT 15
LOCATION 35, 39
WAIT 15
ROTATE 3
LOCATION 62, 39
WAIT 15
# SC_CRUMBLY_WOODS
LOADRCT1 15
ROTATE 3
LOCATION 57, 94
WAIT 15
LOCATION 44, 84
WAIT 15
ROTATE 1
LOCATION 76, 59
WAIT 15
LOCATION 76, 48
WAIT 15
# SC_LIGHTNING_PEAKS
LOADRCT1 17
LOCATION 80, 49
WAIT 15
LOCATION 60, 62
WAIT 15
# SC_IVORY_TOWERS
LOADRCT1 18
ROTATE 3
LOCATION 50, 77
WAIT 15
RESTART

View File

@ -0,0 +1,233 @@
# RollerCoaster Tycoon 1 Title Sequence
##############################
# Added Attractions (part 1) #
##############################
# SC_HAUNTED_HARBOR
LOADRCT1 45
LOCATION 62, 53
WAIT 11
ROTATE 3
LOCATION 78, 45
WAIT 16
# SC_CANARY_MINES
LOADRCT1 42
LOCATION 52, 28
WAIT 15
# SC_GENTLE_GLEN
LOADRCT1 48
LOCATION 68, 45
WAIT 11
# SC_FUNTOPIA
LOADRCT1 44
LOCATION 69, 93
WAIT 17
##############################
# Loopy Landscapes #
##############################
# SC_FRIGHTMARE_HILLS
LOADRCT1 86
LOCATION 46, 47
WAIT 5
# SC_GOOD_KNIGHT_PARK
LOADRCT1 30
ROTATE 2
LOCATION 60, 62
WAIT 5
# SC_ICEBERG_ISLANDS
LOADRCT1 22
ROTATE 3
LOCATION 36, 52
WAIT 4
# SC_SOUTHERN_SANDS
LOADRCT1 91
ROTATE 2
LOCATION 51, 47
WAIT 4
# SC_SUNNY_SWAMPS
LOADRCT1 85
ROTATE 3
LOCATION 77, 82
WAIT 4
# SC_VERTIGO_VIEWS
LOADRCT1 27
LOCATION 22, 56
WAIT 3
# SC_WACKY_WARREN
LOADRCT1 31
ROTATE 3
LOCATION 72, 80
WAIT 4
##############################
# Added Attractions (part 2) #
##############################
# SC_SPRIGHTLY_PARK
LOADRCT1 51
ROTATE 3
LOCATION 97, 72
WAIT 12
ROTATE 2
LOCATION 74, 71
WAIT 12
ROTATE 2
LOCATION 67, 90
WAIT 12
# SC_GIGGLE_DOWNS
LOADRCT1 65
LOCATION 94, 64
WAIT 10
# SC_SWAMP_COVE
LOADRCT1 59
LOCATION 96, 22
WAIT 10
ROTATE 3
LOCATION 90, 29
WAIT 10
# SC_FRUIT_FARM
LOADRCT1 53
LOCATION 47, 52
WAIT 12
# SC_FUTURE_WORLD
LOADRCT1 47
LOCATION 67, 59
WAIT 19
# SC_THREE_MONKEYS_PARK
LOADRCT1 41
ROTATE 2
LOCATION 72, 61
WAIT 8
ROTATE 2
LOCATION 68, 70
WAIT 8
LOCATION 58, 56
WAIT 8
ROTATE 1
LOCATION 44, 70
WAIT 8
ROTATE 3
LOCATION 43, 90
WAIT 10
# SC_ROMAN_VILLAGE
LOADRCT1 58
LOCATION 49, 46
WAIT 15
# SC_ADRENALINE_HEIGHTS
LOADRCT1 60
ROTATE 3
LOCATION 38, 57
WAIT 15
##############################
# RollerCoaster Tycoon 1 #
##############################
# SC_DIAMOND_HEIGHTS
LOADRCT1 3
ROTATE 2
LOCATION 47, 99
WAIT 15
ROTATE 2
LOCATION 90, 48
WAIT 15
ROTATE 1
LOCATION 86, 43
WAIT 15
ROTATE 3
LOCATION 57, 50
WAIT 15
ROTATE 2
LOCATION 86, 64
WAIT 15
# SC_KATIES_DREAMLAND
LOADRCT1 7
LOCATION 48, 44
WAIT 15
LOCATION 64, 41
WAIT 15
# SC_POKEY_PARK,
LOADRCT1 8
ROTATE 2
LOCATION 56, 64
WAIT 15
# SC_WHITE_WATER_PARK
LOADRCT1 9
ROTATE 3
LOCATION 96, 88
WAIT 15
LOCATION 84, 95
WAIT 15
# SC_MILLENNIUM_MINES
LOADRCT1 10
ROTATE 1
ROTATE 1
LOCATION 64, 37
WAIT 15
# SC_KARTS_COASTERS
LOADRCT1 11
LOCATION 84, 56
WAIT 15
LOCATION 34, 36
WAIT 15
LOCATION 33, 65
WAIT 15
# SC_MELS_WORLD
LOADRCT1 12
ROTATE 3
LOCATION 50, 50
WAIT 15
LOCATION 35, 39
WAIT 15
ROTATE 3
LOCATION 62, 39
WAIT 15
# SC_CRUMBLY_WOODS
LOADRCT1 15
ROTATE 3
LOCATION 57, 94
WAIT 15
LOCATION 44, 84
WAIT 15
ROTATE 1
LOCATION 76, 59
WAIT 15
LOCATION 76, 48
WAIT 15
# SC_LIGHTNING_PEAKS
LOADRCT1 17
LOCATION 80, 49
WAIT 15
LOCATION 60, 62
WAIT 15
# SC_IVORY_TOWERS
LOADRCT1 18
ROTATE 3
LOCATION 50, 77
WAIT 15
RESTART

View File

@ -5,6 +5,8 @@
- Feature: Add SI units as a new measurement system for distance / speed.
- Feature: Update alternative font selection mechanism for all platforms.
- Feature: Allow enabling / disabling of different notifications.
- Feature: Improved tile inspector.
- Feature: Integrate RCT1 style scenario select with optional unlock progression.
- Fix: [#2126] Ferris Wheels set to "backward rotation" stop working (original bug)
- Fix: [#2449] Turning off Day/Night Circle while it is night doesn't reset back to day

View File

@ -120,7 +120,6 @@
<ClCompile Include="test\ride\ride_ratings_test.c" />
<ClCompile Include="test\tests.c" />
<ClCompile Include="src\title.c" />
<ClCompile Include="src\tutorial.c" />
<ClCompile Include="src\util\sawyercoding.c" />
<ClCompile Include="src\util\util.c" />
<ClCompile Include="src\windows\about.c" />
@ -266,13 +265,13 @@
<ClInclude Include="src\ride\track_paint.h" />
<ClInclude Include="src\ride\vehicle.h" />
<ClInclude Include="src\scenario.h" />
<ClCompile Include="src\scenario_sources.c" />
<ClInclude Include="src\sprites.h" />
<ClInclude Include="src\version.h" />
<ClInclude Include="test\management\finance_test.h" />
<ClInclude Include="test\ride\ride_ratings_test.h" />
<ClInclude Include="test\tests.h" />
<ClInclude Include="src\title.h" />
<ClInclude Include="src\tutorial.h" />
<ClInclude Include="src\util\sawyercoding.h" />
<ClInclude Include="src\util\util.h" />
<ClInclude Include="src\windows\dropdown.h" />

View File

@ -270,9 +270,6 @@
<ClCompile Include="src\title.c">
<Filter>Source</Filter>
</ClCompile>
<ClCompile Include="src\tutorial.c">
<Filter>Source</Filter>
</ClCompile>
<ClCompile Include="src\localisation\date.c">
<Filter>Source\Localisation</Filter>
</ClCompile>
@ -564,6 +561,9 @@
<ClCompile Include="src\image_io.c">
<Filter>Source</Filter>
</ClCompile>
<ClCompile Include="src\scenario_sources.c">
<Filter>Source</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\management\award.h">
@ -692,9 +692,6 @@
<ClInclude Include="src\title.h">
<Filter>Source</Filter>
</ClInclude>
<ClInclude Include="src\tutorial.h">
<Filter>Source</Filter>
</ClInclude>
<ClInclude Include="src\localisation\date.h">
<Filter>Source\Localisation</Filter>
</ClInclude>

View File

@ -15,7 +15,7 @@ fi
# keep in sync with version in install.sh
if [[ $(uname -s) == "Darwin" ]]; then
# keep in sync with version in Xcode project
sha256sum=02ebc8e7fd8b9b02b7144721784c5d96202a17398bc8652da163c8c85b66a7db
sha256sum=6562ce9e1f37f125e3345bfd8b961777800436bf607b30dc7c964e0e6991ad2c
else
sha256sum=31c5e19d9f794bd5f0e75f20c2b4c3c4664d736b0a4d50c8cde14a9a9007b62d
fi

View File

@ -63,6 +63,7 @@
// are implemented in C. Sometimes memory locations are still used even if
// they aren't directly referenced, for example when a game is saved and
// loaded, large chunks of data is read and written to.
#define RCT2_ADDRESS_SPRITE_ENTRIES 0x00982708
#define RCT2_ADDRESS_EASTEREGG_NAMES 0x00988C20
@ -191,7 +192,7 @@
#define RCT2_ADDRESS_TICKS_SINCE_DRAG_START 0x009DE540
#define RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE 0x009DE550
#define RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE 0x009DE550
#define RCT2_ADDRESS_PICKEDUP_PEEP_X 0x009DE554
#define RCT2_ADDRESS_PICKEDUP_PEEP_Y 0x009DE556

View File

@ -203,6 +203,10 @@ config_property_definition _generalDefinitions[] = {
{ offsetof(general_configuration, show_fps), "show_fps", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL },
{ offsetof(general_configuration, trap_cursor), "trap_cursor", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL },
{ offsetof(general_configuration, auto_open_shops), "auto_open_shops", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL },
{ offsetof(general_configuration, scenario_select_mode), "scenario_select_mode", CONFIG_VALUE_TYPE_UINT8, SCENARIO_SELECT_MODE_ORIGIN, NULL },
{ offsetof(general_configuration, scenario_unlocking_enabled), "scenario_unlocking_enabled", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL },
{ offsetof(general_configuration, scenario_hide_mega_park), "scenario_hide_mega_park", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL },
};
config_property_definition _interfaceDefinitions[] = {
@ -1404,11 +1408,23 @@ void title_sequences_set_default()
platform_get_openrct_data_path(dataPath);
// Load OpenRCT2 title sequence
// RCT1 title sequence
sprintf(path, "%s%c%s%c%s%c", dataPath, sep, "title", sep, "rct1", sep);
title_sequence_open(path, language_get_string(5305));
// RCT1 (AA) title sequence
sprintf(path, "%s%c%s%c%s%c", dataPath, sep, "title", sep, "rct1aa", sep);
title_sequence_open(path, language_get_string(5306));
// RCT1 (AA + LL) title sequence
sprintf(path, "%s%c%s%c%s%c", dataPath, sep, "title", sep, "rct1aall", sep);
title_sequence_open(path, language_get_string(5307));
// RCT2 title sequence
sprintf(path, "%s%c%s%c%s%c", dataPath, sep, "title", sep, "rct2", sep);
title_sequence_open(path, language_get_string(5308));
// Load OpenRCT2 title sequence
// OpenRCT2 title sequence
sprintf(path, "%s%c%s%c%s%c", dataPath, sep, "title", sep, "openrct2", sep);
title_sequence_open(path, language_get_string(5309));
}
@ -1429,12 +1445,21 @@ void title_sequences_load_presets()
platform_enumerate_directories_end(dirEnumHandle);
// Check which title sequence is the current one
if (_stricmp(gConfigInterface.current_title_sequence_preset, "*RCT2") == 0) {
if (_stricmp(gConfigInterface.current_title_sequence_preset, "*RCT1") == 0) {
gCurrentTitleSequence = 0;
}
else if (_stricmp(gConfigInterface.current_title_sequence_preset, "*OPENRCT2") == 0) {
else if (_stricmp(gConfigInterface.current_title_sequence_preset, "*RCT1AA") == 0) {
gCurrentTitleSequence = 1;
}
else if (_stricmp(gConfigInterface.current_title_sequence_preset, "*RCT1AALL") == 0) {
gCurrentTitleSequence = 2;
}
else if (_stricmp(gConfigInterface.current_title_sequence_preset, "*RCT2") == 0) {
gCurrentTitleSequence = 3;
}
else if (_stricmp(gConfigInterface.current_title_sequence_preset, "*OPENRCT2") == 0) {
gCurrentTitleSequence = 4;
}
else {
for (i = TITLE_SEQUENCE_DEFAULT_PRESETS; i < gConfigTitleSequences.num_presets; i++) {
if (_stricmp(gConfigInterface.current_title_sequence_preset, gConfigTitleSequences.presets[i].name) == 0) {
@ -1564,6 +1589,9 @@ static void title_sequence_open(const char *path, const char *customName)
command.command = TITLE_SCRIPT_END;
} else if (_stricmp(token, "LOADMM") == 0) {
command.command = TITLE_SCRIPT_LOADMM;
} else if (_stricmp(token, "LOADRCT1") == 0) {
command.command = TITLE_SCRIPT_LOADRCT1;
command.saveIndex = atoi(part1) & 0xFF;
}
}
if (command.command != 0xFF) {

View File

@ -128,6 +128,11 @@ enum {
SORT_DATE_DESCENDING,
};
enum {
SCENARIO_SELECT_MODE_DIFFICULTY,
SCENARIO_SELECT_MODE_ORIGIN,
};
typedef struct {
uint8 play_intro;
uint8 confirmation_prompt;
@ -172,6 +177,9 @@ typedef struct {
uint8 show_fps;
uint8 trap_cursor;
uint8 auto_open_shops;
uint8 scenario_select_mode;
uint8 scenario_unlocking_enabled;
uint8 scenario_hide_mega_park;
} general_configuration;
typedef struct {

View File

@ -485,7 +485,7 @@ void redraw_rain()
void gfx_invalidate_pickedup_peep()
{
if (RCT2_GLOBAL(0x009ABDF2, uint32) != 0) {
int sprite = RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, sint32);
int sprite = RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, sint32);
if (sprite != -1) {
sprite = sprite & 0x7FFFF;
@ -506,10 +506,10 @@ void gfx_draw_pickedup_peep()
return;
// Draw picked-up peep
if (RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, uint32) != 0xFFFFFFFF) {
if (RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, 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_IMAGE, uint32),
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_X, sint16),
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_Y, sint16), 0
);

View File

@ -149,6 +149,7 @@ int string_get_height_raw(char *buffer);
void gfx_draw_string_centred_wrapped_partial(rct_drawpixelinfo *dpi, int x, int y, int width, int colour, rct_string_id format, void *args, int ticks);
void gfx_draw_string_with_y_offsets(rct_drawpixelinfo *dpi, const utf8 *text, int colour, int x, int y, const sint8 *yOffsets, bool forceSpriteFont);
int gfx_clip_string(char* buffer, int width);
void shorten_path(utf8 *buffer, size_t bufferSize, const utf8 *path, int availableWidth);
bool ttf_initialise();
void ttf_dispose();

View File

@ -21,9 +21,10 @@
#include "../addresses.h"
#include "../interface/colour.h"
#include "../localisation/localisation.h"
#include "../sprites.h"
#include "../world/map.h"
#include "../platform/platform.h"
#include "../sprites.h"
#include "../util/util.h"
#include "../world/map.h"
#include "drawing.h"
static int ttf_get_string_width(const utf8 *text);
@ -1355,3 +1356,40 @@ void gfx_draw_string_with_y_offsets(rct_drawpixelinfo *dpi, const utf8 *text, in
gLastDrawStringX = info.x;
gLastDrawStringY = info.y;
}
void shorten_path(utf8 *buffer, size_t bufferSize, const utf8 *path, int availableWidth)
{
int length = strlen(path);
// Return full string if it fits
if (gfx_get_string_width((char*)path) <= availableWidth) {
safe_strncpy(buffer, path, bufferSize);
return;
}
// Count path separators
int path_separators = 0;
for (int x = 0; x < length; x++) {
if (path[x] == platform_get_path_separator()) {
path_separators++;
}
}
// TODO: Replace with unicode ellipsis when supported
safe_strncpy(buffer, "...", bufferSize);
// Abreviate beginning with xth separator
int begin = -1;
for (int x = 0; x < path_separators; x++){
do {
begin++;
} while (path[begin] != platform_get_path_separator());
safe_strncpy(buffer + 3, path + begin, bufferSize - 3);
if (gfx_get_string_width(buffer) <= availableWidth) {
return;
}
}
safe_strncpy(buffer, path, bufferSize);
}

View File

@ -138,7 +138,7 @@ void editor_convert_save_to_scenario_callback(int result)
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_SCENARIO_EDITOR;
s6Info->editor_step = EDITOR_STEP_OBJECTIVE_SELECTION;
s6Info->category = SCENARIO_CATEGORY_BUILDYOUROWN;
s6Info->category = SCENARIO_CATEGORY_OTHER;
viewport_init_all();
news_item_init_queue();
window_editor_main_open();
@ -328,7 +328,7 @@ static int editor_read_s6(const char *path)
s6Info->editor_step = EDITOR_STEP_LANDSCAPE_EDITOR;
} else {
s6Info->editor_step = EDITOR_STEP_LANDSCAPE_EDITOR;
s6Info->category = SCENARIO_CATEGORY_BUILDYOUROWN;
s6Info->category = SCENARIO_CATEGORY_OTHER;
format_string(s6Info->details, STR_NO_DETAILS_YET, NULL);
}

View File

@ -46,7 +46,6 @@
#include "ride/track.h"
#include "scenario.h"
#include "title.h"
#include "tutorial.h"
#include "util/sawyercoding.h"
#include "util/util.h"
#include "windows/error.h"
@ -57,6 +56,9 @@
#include "world/scenery.h"
#include "world/sprite.h"
#include "world/water.h"
#include <time.h>
#define NUMBER_OF_AUTOSAVES_TO_KEEP 9
int gGameSpeed = 1;
float gDayNightCycle = 0;
@ -288,11 +290,11 @@ void game_update()
RCT2_GLOBAL(0x009E2D74, uint32) = 0;
break;
} else {
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == INPUT_STATE_RESET ||
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == INPUT_STATE_NORMAL
if (gInputState == INPUT_STATE_RESET ||
gInputState == INPUT_STATE_NORMAL
) {
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_VIEWPORT_SCROLLING) {
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~INPUT_FLAG_VIEWPORT_SCROLLING;
if (gInputFlags & INPUT_FLAG_VIEWPORT_SCROLLING) {
gInputFlags &= ~INPUT_FLAG_VIEWPORT_SCROLLING;
break;
}
} else {
@ -310,7 +312,7 @@ void game_update()
RCT2_GLOBAL(0x009A8C28, uint8) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~INPUT_FLAG_VIEWPORT_SCROLLING;
gInputFlags &= ~INPUT_FLAG_VIEWPORT_SCROLLING;
// the flickering frequency is reduced by 4, compared to the original
// it was done due to inability to reproduce original frequency
@ -770,10 +772,10 @@ int game_load_sv6(SDL_RWops* rw)
if (!load_success){
set_load_objects_fail_reason();
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_5){
if (gInputFlags & INPUT_FLAG_5){
//call 0x0040705E Sets cursor position and something else. Calls maybe wind func 8 probably pointless
RCT2_GLOBAL(0x14241BC, uint32) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~INPUT_FLAG_5;
gInputFlags &= ~INPUT_FLAG_5;
}
return 0;//This never gets called
@ -864,10 +866,10 @@ int game_load_network(SDL_RWops* rw)
if (!load_success){
set_load_objects_fail_reason();
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_5){
if (gInputFlags & INPUT_FLAG_5){
//call 0x0040705E Sets cursor position and something else. Calls maybe wind func 8 probably pointless
RCT2_GLOBAL(0x14241BC, uint32) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~INPUT_FLAG_5;
gInputFlags &= ~INPUT_FLAG_5;
}
return 0;//This never gets called
@ -1059,16 +1061,99 @@ void save_game_as()
window_loadsave_open(LOADSAVETYPE_SAVE | LOADSAVETYPE_GAME, (char*)path_get_filename(gScenarioSavePath));
}
int compare_autosave_file_paths (const void * a, const void * b ) {
return strcmp(*(char **)a, *(char **)b);
}
void limit_autosave_count(const size_t numberOfFilesToKeep)
{
int fileEnumHandle = 0;
size_t autosavesCount = 0;
size_t numAutosavesToDelete = 0;
file_info fileInfo;
utf8 filter[MAX_PATH];
utf8 **autosaveFiles = NULL;
size_t i=0;
platform_get_user_directory(filter, "save");
strncat(filter, "autosave_*.sv6", sizeof(filter) - strnlen(filter, MAX_PATH) - 1);
// At first, count how many autosaves there are
fileEnumHandle = platform_enumerate_files_begin(filter);
while (platform_enumerate_files_next(fileEnumHandle, &fileInfo)) {
autosavesCount++;
}
platform_enumerate_files_end(fileEnumHandle);
// If there are fewer autosaves than the number of files to keep we don't need to delete anything
if(autosavesCount <= numberOfFilesToKeep) {
return;
}
autosaveFiles = (utf8**) malloc(sizeof(utf8*) * autosavesCount);
fileEnumHandle = platform_enumerate_files_begin(filter);
for(i = 0; i < autosavesCount; i++) {
autosaveFiles[i] = (utf8*)malloc(sizeof(utf8) * MAX_PATH);
memset(autosaveFiles[i], 0, sizeof(utf8) * MAX_PATH);
if(platform_enumerate_files_next(fileEnumHandle, &fileInfo)) {
platform_get_user_directory(autosaveFiles[i], "save");
strcat(autosaveFiles[i], fileInfo.path);
}
}
platform_enumerate_files_end(fileEnumHandle);
qsort (autosaveFiles, autosavesCount, sizeof (char*), compare_autosave_file_paths);
// calculate how many saves we need to delete.
numAutosavesToDelete = autosavesCount - numberOfFilesToKeep;
i=0;
while (numAutosavesToDelete > 0) {
platform_file_delete(autosaveFiles[i]);
i++;
numAutosavesToDelete--;
}
for(i = 0; i < autosavesCount; i++) {
free(autosaveFiles[i]);
}
free(autosaveFiles);
}
void game_autosave()
{
utf8 path[MAX_PATH];
utf8 backupPath[MAX_PATH];
utf8 timeString[21]="";
time_t rawtime;
struct tm * timeinfo;
time ( &rawtime );
timeinfo = localtime ( &rawtime );
limit_autosave_count(NUMBER_OF_AUTOSAVES_TO_KEEP);
snprintf(timeString, 20, "%d-%02d-%02d_%02d-%02d-%02d", 1900+timeinfo->tm_year, 1+timeinfo->tm_mon, timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
platform_get_user_directory(path, "save");
safe_strncpy(backupPath, path, MAX_PATH);
strcat(path, "autosave.sv6");
strcat(path, "autosave_");
strcat(path, timeString);
strcat(path, ".sv6");
strcat(backupPath, "autosave.sv6.bak");
if (platform_file_exists(path)) {
@ -1129,8 +1214,8 @@ void game_load_or_quit_no_save_prompt()
} else if (RCT2_GLOBAL(RCT2_ADDRESS_SAVE_PROMPT_MODE, uint16) == 1) {
game_do_command(0, 1, 0, 1, GAME_COMMAND_LOAD_OR_QUIT, 0, 0);
tool_cancel();
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_5) {
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~INPUT_FLAG_5;
if (gInputFlags & INPUT_FLAG_5) {
gInputFlags &= ~INPUT_FLAG_5;
}
gGameSpeed = 1;
title_load();

View File

@ -30,6 +30,14 @@ void* g_hooktableaddress = 0;
int g_hooktableoffset = 0;
int g_maxhooks = 1000;
// This macro writes a little-endian 4-byte long value into *data
// It is used to avoid type punning.
#define write_address_strictalias(data, addr) \
*(data + 0) = ((addr) & 0x000000ff) >> 0; \
*(data + 1) = ((addr) & 0x0000ff00) >> 8; \
*(data + 2) = ((addr) & 0x00ff0000) >> 16; \
*(data + 3) = ((addr) & 0xff000000) >> 24;
void hookfunc(int address, int newaddress, int stacksize, int registerargs[], int registersreturned, int eaxDestinationRegister)
{
int i = 0;
@ -118,7 +126,9 @@ void hookfunc(int address, int newaddress, int stacksize, int registerargs[], in
}
data[i++] = 0xE8; // call
*((int *)&data[i]) = (newaddress - address - i - 4); i += 4;
write_address_strictalias(&data[i], newaddress - address - i - 4);
i += 4;
// returnlocation:
@ -220,7 +230,10 @@ void addhook(int address, int newaddress, int stacksize, int registerargs[], int
char data[9];
int i = 0;
data[i++] = 0xE9; // jmp
*((int *)&data[i]) = hookaddress - address - i - 4; i += 4;
write_address_strictalias(&data[i], hookaddress - address - i - 4);
i += 4;
data[i++] = 0xC3; // retn
#ifdef _WIN32
WriteProcessMemory(GetCurrentProcess(), (LPVOID)address, data, i, 0);

View File

@ -35,7 +35,6 @@
#include "platform/platform.h"
#include "ride/ride_data.h"
#include "scenario.h"
#include "tutorial.h"
#include "windows/tooltip.h"
#include "windows/dropdown.h"
#include "world/banner.h"
@ -44,11 +43,21 @@
#include "world/scenery.h"
#include "openrct2.h"
static int _dragX, _dragY;
static rct_windowclass _dragWindowClass;
static rct_windownumber _dragWindowNumber;
static int _dragWidgetIndex, _dragScrollIndex;
static int _originalWindowWidth, _originalWindowHeight;
static sint32 _dragX;
static sint32 _dragY;
static widget_ref _dragWidget;
static uint8 _dragScrollIndex;
static sint32 _originalWindowWidth;
static sint32 _originalWindowHeight;
uint8 gInputState;
uint8 gInputFlags;
uint16 gTooltipNotShownTicks;
uint16 gTooltipTimeout;
widget_ref gTooltipWidget;
sint32 gTooltipCursorX;
sint32 gTooltipCursorY;
typedef struct {
uint32 x, y;
@ -92,7 +101,6 @@ static void input_scroll_part_update_vthumb(rct_window *w, int widgetIndex, int
static void input_scroll_part_update_vtop(rct_window *w, int widgetIndex, int scroll_id);
static void input_scroll_part_update_vbottom(rct_window *w, int widgetIndex, int scroll_id);
static void input_update_tooltip(rct_window *w, int widgetIndex, int x, int y);
static void update_cursor_position();
#pragma region Mouse input
@ -115,7 +123,6 @@ void game_handle_input()
window_event_unknown_07_call(w);
sub_6EA73F();
update_cursor_position();
for (;;) {
game_get_next_input(&x, &y, &state);
@ -125,7 +132,7 @@ void game_handle_input()
game_handle_input_mouse(x, y, state & 0xFF);
}
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_5) {
if (gInputFlags & INPUT_FLAG_5) {
game_handle_input_mouse(x, y, state);
}
else if (x != 0x80000000) {
@ -159,8 +166,6 @@ static void game_get_next_input(int *x, int *y, int *state)
*x = eax->x;
*y = eax->y;
*state = eax->state;
// NOTE this function lacks tutorial logic
}
/**
@ -184,12 +189,12 @@ static rct_mouse_data* get_mouse_input()
* rct2: 0x006E957F
*/
static void input_scroll_drag_begin(int x, int y, rct_window* w, rct_widget* widget, int widgetIndex) {
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_SCROLL_RIGHT;
gInputState = INPUT_STATE_SCROLL_RIGHT;
_dragX = x;
_dragY = y;
_dragWindowClass = w->classification;
_dragWindowNumber = w->number;
_dragWidgetIndex = widgetIndex;
_dragWidget.window_classification = w->classification;
_dragWidget.window_number = w->number;
_dragWidget.widget_index = widgetIndex;
RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_DRAG_START, sint16) = 0;
_dragScrollIndex = window_get_scroll_data_index(w, widgetIndex);
@ -200,8 +205,9 @@ static void input_scroll_drag_begin(int x, int y, rct_window* w, rct_widget* wid
* Based on (heavily changed)
* rct2: 0x006E9E0E, 0x006E9ED0
*/
static void input_scroll_drag_continue(int x, int y, rct_window* w) {
uint8 widgetIndex = _dragWidgetIndex;
static void input_scroll_drag_continue(int x, int y, rct_window* w)
{
uint8 widgetIndex = _dragWidget.widget_index;
uint8 scrollIndex = _dragScrollIndex;
rct_widget* widget = &w->widgets[widgetIndex];
@ -238,13 +244,13 @@ static void input_scroll_drag_continue(int x, int y, rct_window* w) {
*/
static void input_scroll_right(int x, int y, int state) {
rct_window* w = window_find_by_number(
_dragWindowClass,
_dragWindowNumber
);
_dragWidget.window_classification,
_dragWidget.window_number
);
if (w == NULL) {
platform_show_cursor();
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
gInputState = INPUT_STATE_RESET;
return;
}
@ -258,7 +264,7 @@ static void input_scroll_right(int x, int y, int state) {
input_scroll_drag_continue(x, y, w);
break;
case 4:
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
gInputState = INPUT_STATE_RESET;
platform_show_cursor();
break;
}
@ -279,7 +285,7 @@ static void game_handle_input_mouse(int x, int y, int state)
widgetIndex = w == NULL ? -1 : window_find_widget_from_point(w, x, y);
widget = widgetIndex == -1 ? 0 : &w->widgets[widgetIndex];
switch (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8)) {
switch (gInputState) {
case INPUT_STATE_RESET:
window_tooltip_reset(x, y);
// fall-through
@ -315,9 +321,9 @@ static void game_handle_input_mouse(int x, int y, int state)
input_state_widget_pressed(x, y, state, widgetIndex, w, widget);
break;
case INPUT_STATE_POSITIONING_WINDOW:
w = window_find_by_number(_dragWindowClass, _dragWindowNumber);
w = window_find_by_number(_dragWidget.window_classification, _dragWidget.window_number);
if (w == NULL) {
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
gInputState = INPUT_STATE_RESET;
}
else {
input_window_position_continue(w, _dragX, _dragY, x, y);
@ -346,19 +352,19 @@ static void game_handle_input_mouse(int x, int y, int state)
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber)
);
if (!w){
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 0;
gInputState = INPUT_STATE_RESET;
break;
}
if (state == 0){
if (!w->viewport){
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 0;
gInputState = INPUT_STATE_RESET;
break;
}
if (w->classification != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass) ||
w->number != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) ||
!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)) break;
!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE)) break;
w = window_find_by_number(
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass),
@ -371,9 +377,9 @@ static void game_handle_input_mouse(int x, int y, int state)
}
else if (state == 2){
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 0;
gInputState = INPUT_STATE_RESET;
if (RCT2_GLOBAL(0x9DE52E, rct_windownumber) != w->number)break;
if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)){
if ((gInputFlags & INPUT_FLAG_TOOL_ACTIVE)){
w = window_find_by_number(
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass),
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber)
@ -383,7 +389,7 @@ static void game_handle_input_mouse(int x, int y, int state)
window_event_tool_up_call(w, RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16), x, y);
}
else{
if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_4))
if ((gInputFlags & INPUT_FLAG_4))
break;
viewport_interaction_left_click(x, y);
@ -397,9 +403,9 @@ static void game_handle_input_mouse(int x, int y, int state)
input_scroll_end();
break;
case INPUT_STATE_RESIZING:
w = window_find_by_number(_dragWindowClass, _dragWindowNumber);
w = window_find_by_number(_dragWidget.window_classification, _dragWidget.window_number);
if (w == NULL) {
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
gInputState = INPUT_STATE_RESET;
}
else {
if (state == 2)
@ -419,12 +425,12 @@ static void game_handle_input_mouse(int x, int y, int state)
void input_window_position_begin(rct_window *w, int widgetIndex, int x, int y)
{
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_POSITIONING_WINDOW;
gInputState = INPUT_STATE_POSITIONING_WINDOW;
_dragX = x - w->x;
_dragY = y - w->y;
_dragWindowClass = w->classification;
_dragWindowNumber = w->number;
_dragWidgetIndex = widgetIndex;
_dragWidget.window_classification = w->classification;
_dragWidget.window_number = w->number;
_dragWidget.widget_index = widgetIndex;
}
static void input_window_position_continue(rct_window *w, int wdx, int wdy, int x, int y)
@ -437,22 +443,20 @@ static void input_window_position_continue(rct_window *w, int wdx, int wdy, int
static void input_window_position_end(rct_window *w, int x, int y)
{
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_NORMAL;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint8) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) = _dragWindowClass;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) = _dragWindowNumber;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = _dragWidgetIndex;
gInputState = INPUT_STATE_NORMAL;
gTooltipTimeout = 0;
gTooltipWidget = _dragWidget;
window_event_moved_call(w, x, y);
}
static void input_window_resize_begin(rct_window *w, int widgetIndex, int x, int y)
{
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESIZING;
gInputState = INPUT_STATE_RESIZING;
_dragX = x;
_dragY = y;
_dragWindowClass = w->classification;
_dragWindowNumber = w->number;
_dragWidgetIndex = widgetIndex;
_dragWidget.window_classification = w->classification;
_dragWidget.window_number = w->number;
_dragWidget.widget_index = widgetIndex;
_originalWindowWidth = w->width;
_originalWindowHeight = w->height;
}
@ -477,11 +481,9 @@ static void input_window_resize_continue(rct_window *w, int x, int y)
static void input_window_resize_end()
{
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_NORMAL;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint8) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) = _dragWindowClass;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) = _dragWindowNumber;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = _dragWidgetIndex;
gInputState = INPUT_STATE_NORMAL;
gTooltipTimeout = 0;
gTooltipWidget = _dragWidget;
}
#pragma endregion
@ -491,14 +493,14 @@ static void input_window_resize_end()
static void input_viewport_drag_begin(rct_window *w, int x, int y)
{
w->flags &= ~WF_SCROLLING_TO_LOCATION;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_VIEWPORT_RIGHT;
_dragWindowClass = w->classification;
_dragWindowNumber = w->number;
gInputState = INPUT_STATE_VIEWPORT_RIGHT;
_dragWidget.window_classification = w->classification;
_dragWidget.window_number = w->number;
RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_DRAG_START, sint16) = 0;
platform_get_cursor_position(&_dragX, &_dragY);
platform_hide_cursor();
// RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_5;
// gInputFlags |= INPUT_FLAG_5;
}
static void input_viewport_drag_continue()
@ -511,14 +513,14 @@ static void input_viewport_drag_continue()
dx = newDragX - _dragX;
dy = newDragY - _dragY;
w = window_find_by_number(_dragWindowClass, _dragWindowNumber);
w = window_find_by_number(_dragWidget.window_classification, _dragWidget.window_number);
assert(w != NULL);
viewport = w->viewport;
RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_DRAG_START, sint16) += RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_LAST_UPDATE, sint16);
if (viewport == NULL) {
platform_show_cursor();
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
gInputState = INPUT_STATE_RESET;
} else if (dx != 0 || dy != 0) {
if (!(w->flags & WF_NO_SCROLLING)) {
// User dragged a scrollable viewport
@ -544,7 +546,7 @@ static void input_viewport_drag_continue()
static void input_viewport_drag_end()
{
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
gInputState = INPUT_STATE_RESET;
platform_show_cursor();
}
@ -558,12 +560,12 @@ static void input_scroll_begin(rct_window *w, int widgetIndex, int x, int y)
widget = &w->widgets[widgetIndex];
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_SCROLL_LEFT;
gInputState = INPUT_STATE_SCROLL_LEFT;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16) = widgetIndex;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass) = w->classification;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber) = w->number;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16) = x;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16) = y;
gTooltipCursorX = x;
gTooltipCursorY = y;
int eax, ebx, scroll_area, scroll_id;
scroll_id = 0; // safety
@ -647,9 +649,7 @@ static void input_scroll_continue(rct_window *w, int widgetIndex, int state, int
widget_scroll_get_part(w, widget, x, y, &x2, &y2, &scroll_part, &scroll_id);
if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16) == SCROLL_PART_HSCROLLBAR_THUMB){
int temp_x = x;
x -= RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16);
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16) = temp_x;
gTooltipCursorX = x - gTooltipCursorX;
input_scroll_part_update_hthumb(w, widgetIndex, x, scroll_id);
return;
}
@ -702,7 +702,7 @@ static void input_scroll_continue(rct_window *w, int widgetIndex, int state, int
static void input_scroll_end()
{
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET;
gInputState = INPUT_STATE_RESET;
invalidate_scroll();
}
@ -904,9 +904,9 @@ static void input_widget_over(int x, int y, rct_window *w, int widgetIndex)
input_update_tooltip(w, widgetIndex, x, y);
}
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, sint16) = x;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, sint16) = y;
gTooltipTimeout = 0;
gTooltipCursorX = x;
gTooltipCursorY = y;
}
/**
@ -1004,19 +1004,19 @@ static void input_widget_left(int x, int y, rct_window *w, int widgetIndex)
input_window_resize_begin(w, widgetIndex, x, y);
break;
case WWT_VIEWPORT:
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_VIEWPORT_LEFT;
gInputState = INPUT_STATE_VIEWPORT_LEFT;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_X, uint16) = x;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, uint16) = y;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass) = windowClass;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) = windowNumber;
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) {
if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) {
w = window_find_by_number(
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass),
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber)
);
if (w != NULL) {
window_event_tool_down_call(w, RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16), x, y);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_4;
gInputFlags |= INPUT_FLAG_4;
}
}
break;
@ -1034,8 +1034,8 @@ static void input_widget_left(int x, int y, rct_window *w, int widgetIndex)
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass) = windowClass;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber) = windowNumber;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint16) = widgetIndex;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_WIDGET_PRESSED;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_WIDGET_PRESSED;
gInputFlags |= INPUT_FLAG_WIDGET_PRESSED;
gInputState = INPUT_STATE_WIDGET_PRESSED;
RCT2_GLOBAL(0x009DE528, uint16) = 1;
widget_invalidate_by_number(windowClass, windowNumber, widgetIndex);
@ -1071,7 +1071,7 @@ void process_mouse_over(int x, int y)
switch (window->widgets[widgetId].type){
case WWT_VIEWPORT:
if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, int) & INPUT_FLAG_TOOL_ACTIVE) == 0) {
if (!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE)) {
if (viewport_interaction_left_over(x, y)) {
sub_6ED990(CURSOR_HAND_POINT);
return;
@ -1153,7 +1153,7 @@ void process_mouse_over(int x, int y)
*/
void process_mouse_tool(int x, int y)
{
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)
if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE)
{
rct_window* w = window_find_by_number(
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass),
@ -1185,7 +1185,7 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi
rct_window *cursor_w = window_find_by_number(cursor_w_class, cursor_w_number);
if (cursor_w == NULL) {
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 0;
gInputState = INPUT_STATE_RESET;
return;
}
@ -1207,14 +1207,14 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi
window_event_mouse_down_call(w, widgetIndex);
}
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_WIDGET_PRESSED) return;
if (gInputFlags & INPUT_FLAG_WIDGET_PRESSED) return;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_WIDGET_PRESSED;
gInputFlags |= INPUT_FLAG_WIDGET_PRESSED;
widget_invalidate_by_number(cursor_w_class, cursor_w_number, widgetIndex);
return;
case 3:
case 2:
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == 5) {
if (gInputState == INPUT_STATE_DROPDOWN_ACTIVE) {
if (w) {
int dropdown_index = 0;
@ -1236,9 +1236,9 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi
if (cursor_w_class != w->classification || cursor_w_number != w->number || widgetIndex != cursor_widgetIndex)
goto dropdown_cleanup;
dropdown_index = -1;
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_DROPDOWN_STAY_OPEN){
if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_DROPDOWN_MOUSE_UP)){
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_DROPDOWN_MOUSE_UP;
if (gInputFlags & INPUT_FLAG_DROPDOWN_STAY_OPEN){
if (!(gInputFlags & INPUT_FLAG_DROPDOWN_MOUSE_UP)){
gInputFlags |= INPUT_FLAG_DROPDOWN_MOUSE_UP;
return;
}
}
@ -1246,16 +1246,16 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi
window_close_by_class(WC_DROPDOWN);
cursor_w = window_find_by_number(cursor_w_class, cursor_w_number);
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_WIDGET_PRESSED) {
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= 0xFFFE;
if (gInputFlags & INPUT_FLAG_WIDGET_PRESSED) {
gInputFlags &= ~INPUT_FLAG_WIDGET_PRESSED;
widget_invalidate_by_number(cursor_w_class, cursor_w_number, cursor_widgetIndex);
}
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 1;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = cursor_widgetIndex;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) = cursor_w_class;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) = cursor_w_number;
gInputState = INPUT_STATE_NORMAL;
gTooltipTimeout = 0;
gTooltipWidget.widget_index = cursor_widgetIndex;
gTooltipWidget.window_classification = cursor_w_class;
gTooltipWidget.window_number = cursor_w_number;
window_event_dropdown_call(cursor_w, cursor_widgetIndex, dropdown_index);
}
dropdown_cleanup:
@ -1263,9 +1263,9 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi
}
if (state == 3) return;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 1;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = cursor_widgetIndex;
gInputState = INPUT_STATE_NORMAL;
gTooltipTimeout = 0;
gTooltipWidget.widget_index = cursor_widgetIndex;
if (!w)
break;
@ -1288,10 +1288,10 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi
}
RCT2_GLOBAL(0x9DE528, uint16) = 0;
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) != 5){
if (gInputState != INPUT_STATE_DROPDOWN_ACTIVE){
// Hold down widget and drag outside of area??
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_WIDGET_PRESSED){
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= 0xFFFE;
if (gInputFlags & INPUT_FLAG_WIDGET_PRESSED){
gInputFlags &= ~INPUT_FLAG_WIDGET_PRESSED;
widget_invalidate_by_number(cursor_w_class, cursor_w_number, cursor_widgetIndex);
}
return;
@ -1328,36 +1328,34 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi
static void input_update_tooltip(rct_window *w, int widgetIndex, int x, int y)
{
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) == 255) {
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, uint16) < 500 ||
(RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, sint16) == x &&
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, sint16) == y)
) {
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_LAST_UPDATE, uint16);
if (gTooltipWidget.window_classification == 255) {
if (gTooltipNotShownTicks < 500 || (gTooltipCursorX == x && gTooltipCursorY == y)) {
gTooltipTimeout = RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_LAST_UPDATE, uint16);
int bp = 2000;
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, uint16) >= 1)
bp = 0;
if (bp > RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16)) {
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, sint16)++;
int time = 2000;
if (gTooltipNotShownTicks >= 1) {
time = 0;
}
if (time > gTooltipTimeout) {
gTooltipNotShownTicks++;
return;
}
window_tooltip_open(w, widgetIndex, x, y);
}
}
else {
if (((w != NULL) &&
(RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) != w->classification ||
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) != w->number)) ||
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) != widgetIndex
) {
} else {
if ((
(w != NULL) &&
(gTooltipWidget.window_classification != w->classification || gTooltipWidget.window_number != w->number)
) ||
gTooltipWidget.widget_index != widgetIndex
) {
window_tooltip_close();
}
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) += RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_LAST_UPDATE, uint16);
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) < 8000)
return;
window_close_by_class(WC_TOOLTIP);
gTooltipTimeout += RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_LAST_UPDATE, uint16);
if (gTooltipTimeout >= 8000) {
window_close_by_class(WC_TOOLTIP);
}
}
}
@ -1432,11 +1430,10 @@ void game_handle_keyboard_input()
if (!gConsoleOpen) {
// Handle mouse scrolling
if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 0)
if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_EDGE_SCROLLING, uint8) != 0)
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == 1)
if (!(RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 3))
game_handle_edge_scroll();
if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_EDGE_SCROLLING, uint8) != 0)
if (gInputState == INPUT_STATE_NORMAL)
if (!(RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 3))
game_handle_edge_scroll();
// Handle modifier keys and key scrolling
RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) = 0;
@ -1447,8 +1444,7 @@ void game_handle_keyboard_input()
RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) |= 2;
if (gKeysState[SDL_SCANCODE_LALT] || gKeysState[SDL_SCANCODE_RALT])
RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) |= 4;
if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 0)
game_handle_key_scroll();
game_handle_key_scroll();
}
}
@ -1478,8 +1474,6 @@ void game_handle_keyboard_input()
w = window_find_by_class(WC_CHANGE_KEYBOARD_SHORTCUT);
if (w != NULL) {
keyboard_shortcut_set(key);
} else if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 1) {
tutorial_stop();
} else {
w = window_find_by_class(WC_TEXTINPUT);
if (w != NULL) {
@ -1489,10 +1483,6 @@ void game_handle_keyboard_input()
}
}
}
if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) != 0) {
game_handle_keyboard_input_for_tutorial();
}
}
/**
@ -1519,7 +1509,7 @@ int get_next_key()
* rct2: 0x006ED990
*/
void sub_6ED990(char cursor_id){
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == INPUT_STATE_RESIZING)
if (gInputState == INPUT_STATE_RESIZING)
{
cursor_id = CURSOR_DIAGONAL_ARROWS; //resize icon
}
@ -1613,11 +1603,11 @@ void game_handle_edge_scroll()
// Scroll viewport
if (scrollX != 0) {
mainWindow->saved_view_x += scrollX * (12 << mainWindow->viewport->zoom);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_VIEWPORT_SCROLLING;
gInputFlags |= INPUT_FLAG_VIEWPORT_SCROLLING;
}
if (scrollY != 0) {
mainWindow->saved_view_y += scrollY * (12 << mainWindow->viewport->zoom);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_VIEWPORT_SCROLLING;
gInputFlags |= INPUT_FLAG_VIEWPORT_SCROLLING;
}
}
@ -1682,30 +1672,10 @@ void game_handle_key_scroll()
// Scroll viewport
if (scrollX != 0) {
mainWindow->saved_view_x += scrollX * (12 << mainWindow->viewport->zoom);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_VIEWPORT_SCROLLING;
gInputFlags |= INPUT_FLAG_VIEWPORT_SCROLLING;
}
if (scrollY != 0) {
mainWindow->saved_view_y += scrollY * (12 << mainWindow->viewport->zoom);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_VIEWPORT_SCROLLING;
}
}
/**
*
* rct2: 0x006E8346
*/
static void update_cursor_position()
{
switch (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8)) {
case 0:
// RCT2_GLOBAL(0x0142004C, sint32) = RCT2_GLOBAL(0x0142406C, sint32);
// RCT2_GLOBAL(0x01420050, sint32) = RCT2_GLOBAL(0x01424070, sint32);
break;
case 1:
// read tutorial cursor position
break;
case 2:
// write tutorial cursor position
break;
gInputFlags |= INPUT_FLAG_VIEWPORT_SCROLLING;
}
}

View File

@ -23,6 +23,19 @@
#include "interface/window.h"
enum {
INPUT_STATE_RESET,
INPUT_STATE_NORMAL,
INPUT_STATE_WIDGET_PRESSED,
INPUT_STATE_POSITIONING_WINDOW,
INPUT_STATE_VIEWPORT_RIGHT,
INPUT_STATE_DROPDOWN_ACTIVE,
INPUT_STATE_VIEWPORT_LEFT,
INPUT_STATE_SCROLL_LEFT,
INPUT_STATE_RESIZING,
INPUT_STATE_SCROLL_RIGHT
};
enum {
INPUT_FLAG_WIDGET_PRESSED = (1 << 0),
@ -47,10 +60,24 @@ enum {
INPUT_FLAG_VIEWPORT_SCROLLING = (1 << 7)
};
typedef struct {
rct_windowclass window_classification;
rct_windownumber window_number;
uint8 widget_index;
} widget_ref;
extern uint8 gInputState;
extern uint8 gInputFlags;
extern uint16 gTooltipNotShownTicks;
extern uint16 gTooltipTimeout;
extern widget_ref gTooltipWidget;
extern sint32 gTooltipCursorX;
extern sint32 gTooltipCursorY;
void title_handle_keyboard_input();
void game_handle_input();
void game_handle_keyboard_input();
void game_handle_keyboard_input_for_tutorial();
void store_mouse_input(int state);

View File

@ -136,7 +136,7 @@ static void shortcut_cancel_construction_mode()
window = window_find_by_class(WC_ERROR);
if (window != NULL)
window_close(window);
else if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)
else if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE)
tool_cancel();
}
@ -472,12 +472,14 @@ static void shortcut_screenshot()
static void shortcut_reduce_game_speed()
{
game_reduce_game_speed();
if (network_get_mode() == NETWORK_MODE_NONE)
game_reduce_game_speed();
}
static void shortcut_increase_game_speed()
{
game_increase_game_speed();
if (network_get_mode() == NETWORK_MODE_NONE)
game_increase_game_speed();
}
static void shortcut_open_cheat_window()

View File

@ -63,9 +63,18 @@ void title_sequence_change_preset(int preset)
if (preset >= 0 && preset < gConfigTitleSequences.num_presets) {
switch (preset) {
case 0:
gConfigInterface.current_title_sequence_preset = "*RCT2";
gConfigInterface.current_title_sequence_preset = "*RCT1";
break;
case 1:
gConfigInterface.current_title_sequence_preset = "*RCT1AA";
break;
case 2:
gConfigInterface.current_title_sequence_preset = "*RCT1AALL";
break;
case 3:
gConfigInterface.current_title_sequence_preset = "*RCT2";
break;
case 4:
gConfigInterface.current_title_sequence_preset = "*OPENRCT2";
break;
default:

View File

@ -22,6 +22,7 @@
#include "../config.h"
#include "../drawing/drawing.h"
#include "../drawing/supports.h"
#include "../input.h"
#include "../localisation/localisation.h"
#include "../ride/ride_data.h"
#include "../ride/track_data.h"
@ -101,11 +102,11 @@ void viewport_init_all()
RCT2_GLOBAL(RCT2_ADDRESS_ACTIVE_VIEWPORT_PTR_ARRAY, rct_viewport*) = NULL;
// ?
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, sint8) = INPUT_STATE_RESET;
gInputFlags = 0;
gInputState = INPUT_STATE_RESET;
RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass) = -1;
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, sint32) = -1;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, sint16) = -1;
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, sint32) = -1;
gTooltipNotShownTicks = -1;
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, sint16) = 0;
RCT2_GLOBAL(0x009DEA50, sint16) = -1;
textinput_cancel();

View File

@ -272,7 +272,7 @@ int viewport_interaction_get_item_right(int x, int y, viewport_interaction_info
return info->type;
}
if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & (INPUT_FLAG_6 | INPUT_FLAG_TOOL_ACTIVE)) != (INPUT_FLAG_6 | INPUT_FLAG_TOOL_ACTIVE))
if ((gInputFlags & INPUT_FLAG_6) && (gInputFlags & INPUT_FLAG_TOOL_ACTIVE))
if (window_find_by_class(WC_RIDE_CONSTRUCTION) == NULL && window_find_by_class(WC_FOOTPATH) == NULL)
return info->type = VIEWPORT_INTERACTION_ITEM_NONE;
@ -291,7 +291,7 @@ int viewport_interaction_get_item_right(int x, int y, viewport_interaction_info
return info->type;
case VIEWPORT_INTERACTION_ITEM_FOOTPATH_ITEM:
sceneryEntry = g_pathBitSceneryEntries[(mapElement->properties.path.additions & 0x0F) - 1];
sceneryEntry = g_pathBitSceneryEntries[footpath_element_get_path_scenery_index(mapElement)];
RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 0, uint16) = 1164;
if (mapElement->flags & 0x20) {
RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 2, uint16) = 3124;

View File

@ -978,7 +978,7 @@ int widget_is_disabled(rct_window *w, int widgetIndex)
int widget_is_pressed(rct_window *w, int widgetIndex)
{
int inputState = RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8);
int inputState = gInputState;
if (w->pressed_widgets & (1LL << widgetIndex))
return 1;
@ -987,7 +987,7 @@ int widget_is_pressed(rct_window *w, int widgetIndex)
return 0;
if (RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber) != w->number)
return 0;
if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_WIDGET_PRESSED))
if (!(gInputFlags & INPUT_FLAG_WIDGET_PRESSED))
return 0;
if (RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, sint32) == widgetIndex)
return 1;
@ -1008,7 +1008,7 @@ int widget_is_highlighted(rct_window *w, int widgetIndex)
int widget_is_active_tool(rct_window *w, int widgetIndex)
{
if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE))
if (!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE))
return 0;
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != w->classification)
return 0;

View File

@ -41,7 +41,7 @@
rct_window* g_window_list = RCT2_ADDRESS(RCT2_ADDRESS_WINDOW_LIST, rct_window);
uint8 TextInputDescriptionArgs[8];
uint16 TextInputDescriptionArgs[4];
widget_identifier gCurrentTextBox = { { 255, 0 }, 0 };
char gTextBoxInput[512] = { 0 };
int gMaxTextBoxInputLength = 0;
@ -150,7 +150,7 @@ void window_dispatch_update_all()
rct_window *w;
RCT2_GLOBAL(0x01423604, sint32)++;
//RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, sint16)++;
// gTooltipNotShownTicks++;
for (w = RCT2_LAST_WINDOW; w >= g_window_list; w--)
window_event_update_call(w);
}
@ -306,7 +306,7 @@ static void window_all_wheel_input()
return;
// Check window cursor is over
if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_5)) {
if (!(gInputFlags & INPUT_FLAG_5)) {
w = window_find_from_point(gCursorState.x, gCursorState.y);
if (w != NULL) {
// Check if main window
@ -1727,7 +1727,7 @@ void window_set_resize(rct_window *w, int minWidth, int minHeight, int maxWidth,
*/
int tool_set(rct_window *w, int widgetIndex, int tool)
{
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) {
if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) {
if (
w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) &&
w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) &&
@ -1740,8 +1740,8 @@ int tool_set(rct_window *w, int widgetIndex, int tool)
}
}
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_TOOL_ACTIVE;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~INPUT_FLAG_6;
gInputFlags |= INPUT_FLAG_TOOL_ACTIVE;
gInputFlags &= ~INPUT_FLAG_6;
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TOOL, uint8) = tool;
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) = w->classification;
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) = w->number;
@ -1757,8 +1757,8 @@ void tool_cancel()
{
rct_window *w;
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) {
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~INPUT_FLAG_TOOL_ACTIVE;
if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) {
gInputFlags &= ~INPUT_FLAG_TOOL_ACTIVE;
map_invalidate_selection_rect();
map_invalidate_map_selection_tiles();

View File

@ -27,11 +27,13 @@
#include "../ride/ride.h"
#include "../ride/vehicle.h"
#include "../world/park.h"
#include "../management/research.h"
#include "../scenario.h"
#include "colour.h"
struct rct_window;
union rct_window_event;
extern uint8 TextInputDescriptionArgs[8];
extern uint16 TextInputDescriptionArgs[4];
extern char gTextBoxInput[512];
extern int gMaxTextBoxInputLength;
extern int gTextBoxFrameNo;
@ -260,11 +262,23 @@ typedef struct rct_window {
error_variables error;
};
sint16 page; // 0x48A
sint16 var_48C;
union {
sint16 picked_peep_old_x; // 0x48C staff/guest window: peep x gets set to 0x8000 on pickup, this is the old value
sint16 var_48C;
};
uint16 frame_no; // 0x48E updated every tic for motion in windows sprites
uint16 list_information_type; // 0x490 0 for none, Used as current position of marquee in window_peep
sint16 var_492;
uint32 highlighted_item; // 0x494
union {
sint16 picked_peep_frame; // 0x492 Animation frame of picked peep in staff window and guest window
sint16 var_492;
};
union { // 0x494
uint32 highlighted_item;
uint16 ride_colour;
rct_research_item* research_item;
rct_object_entry* object_entry;
scenario_index_entry* highlighted_scenario;
};
uint8 var_498[0x14];
sint16 selected_tab; // 0x4AC
sint16 var_4AE;
@ -372,19 +386,6 @@ enum {
SCROLL_PART_VSCROLLBAR_THUMB = 10,
};
enum {
INPUT_STATE_RESET = 0,
INPUT_STATE_NORMAL = 1,
INPUT_STATE_WIDGET_PRESSED = 2,
INPUT_STATE_POSITIONING_WINDOW = 3,
INPUT_STATE_VIEWPORT_RIGHT = 4,
INPUT_STATE_DROPDOWN_ACTIVE = 5,
INPUT_STATE_VIEWPORT_LEFT = 6,
INPUT_STATE_SCROLL_LEFT = 7,
INPUT_STATE_RESIZING = 8,
INPUT_STATE_SCROLL_RIGHT = 9
};
enum {
WC_MAIN_WINDOW = 0,
WC_TOP_TOOLBAR = 1,

View File

@ -47,6 +47,13 @@ enum {
RCT2_LANGUAGE_ID_END = 255
};
static TTFFontSetDescriptor TTFFontMSGothic = {{
{ "msgothic_02.ttf", "MS PGothic", 9, 1, 0, 15, nullptr },
{ "msgothic_02.ttf", "MS PGothic", 12, 1, 0, 17, nullptr },
{ "msgothic_02.ttf", "MS PGothic", 12, 1, 0, 17, nullptr },
{ "msgothic_02.ttf", "MS PGothic", 13, 1, 0, 20, nullptr },
}};
static TTFFontSetDescriptor TTFFontMingLiu = {{
{ "msjh.ttc", "JhengHei", 9, -1, -3, 6, nullptr },
{ "mingliu.ttc", "MingLiU", 11, 1, 1, 12, nullptr },
@ -94,6 +101,7 @@ const language_descriptor LanguagesDescriptors[LANGUAGE_COUNT] = {
{ "ko", "Korean", "Korean", "korean", &TTFFontGulim, RCT2_LANGUAGE_ID_KOREAN }, // LANGUAGE_KOREAN
{ "ru-RU", "Russian", "Russian", "russian", &TTFFontArial, RCT2_LANGUAGE_ID_ENGLISH_UK }, // LANGUAGE_RUSSIAN
{ "cz-CZ", "Czech", "Czech", "czech", &TTFFontArial, RCT2_LANGUAGE_ID_ENGLISH_UK }, // LANGUAGE_CZECH
{ "jp-JP", "Japanese", "Japanese", "japanese", &TTFFontMSGothic, RCT2_LANGUAGE_ID_ENGLISH_UK }, // LANGUAGE_JAPANESE
};
int gCurrentLanguage = LANGUAGE_UNDEFINED;

View File

@ -43,6 +43,7 @@ enum {
LANGUAGE_KOREAN,
LANGUAGE_RUSSIAN,
LANGUAGE_CZECH,
LANGUAGE_JAPANESE,
LANGUAGE_COUNT
};

View File

@ -1527,8 +1527,6 @@ enum {
STR_ENTRANCE_NOT_CONNECTED = 2854,
STR_EXIT_NOT_CONNECTED = 2855,
STR_TUTORIAL = 2856,
STR_PRESS_KEY_OR_MOUSE_BUTTON_FOR_CONTROL = 2857,
STR_CANT_START_MARKETING_CAMPAIGN = 2858,
STR_INFOGRAMES_INTERACTIVE_CREDITS = 2860,
@ -1878,10 +1876,6 @@ enum {
STR_INSTALL_NEW_TRACK_DESIGN = 3376,
STR_INSTALL_NEW_TRACK_DESIGN_TIP = 3377,
STR_TUTORIAL_BEGINNERS = 3385,
STR_TUTORIAL_CUSTOM_RIDES = 3386,
STR_TUTORIAL_ROLLER_COASTER = 3387,
STR_SAVE_TRACK_SCENERY_UNABLE_TO_SELECT_ADDITIONAL_ITEM_OF_SCENERY = 3389,
STR_SAVE_TRACK_SCENERY_TOO_MANY_ITEMS_SELECTED = 3390,
@ -2004,9 +1998,17 @@ enum {
STR_TILE_INSPECTOR_ENTRANCE_START = 5335,
STR_TILE_INSPECTOR_ELEMENT_TYPE = 5338,
STR_TILE_INSPECTOR_BASE_HEIGHT = 5339,
STR_TILE_INSPECTOR_CLEARANGE_HEIGHT = 5340,
STR_TILE_INSPECTOR_BASE_HEIGHT_SHORT = 5608,
STR_TILE_INSPECTOR_CLEARANCE_HEIGHT = 5340,
STR_TILE_INSPECTOR_CLEARANGE_HEIGHT_SHORT = 5609,
STR_TILE_INSPECTOR_FLAGS = 5341,
STR_TILE_INSPECTOR_CHOOSE_MSG = 5342,
STR_TILE_INSPECTOR_FLAG_GHOST_SHORT = 5611,
STR_TILE_INSPECTOR_FLAG_GHOST = 5612,
STR_TILE_INSPECTOR_FLAG_BROKEN_SHORT = 5613,
STR_TILE_INSPECTOR_FLAG_BROKEN = 5614,
STR_TILE_INSPECTOR_FLAG_LAST_SHORT = 5615,
STR_TILE_INSPECTOR_FLAG_LAST = 5616,
STR_AUTO_STAFF_PLACEMENT = 5343,
@ -2232,6 +2234,23 @@ enum {
STR_NOTIFICATION_GUEST_USED_FACILITY = 5605,
STR_NOTIFICATION_GUEST_DIED = 5606,
STR_SCENARIO_CATEGORY_RCT1 = 5619,
STR_SCENARIO_CATEGORY_RCT1_AA = 5620,
STR_SCENARIO_CATEGORY_RCT1_LL = 5621,
STR_SCENARIO_CATEGORY_RCT2 = 5622,
STR_SCENARIO_CATEGORY_RCT2_WW = 5623,
STR_SCENARIO_CATEGORY_RCT2_TT = 5624,
STR_SCENARIO_CATEGORY_REAL_PARKS = 5625,
STR_SCENARIO_CATEGORY_OTHER_PARKS = 5626,
STR_OPTIONS_SCENARIO_GROUPING = 5627,
STR_OPTIONS_SCENARIO_ORIGIN = 5628,
STR_OPTIONS_SCENARIO_DIFFICULTY = 5629,
STR_OPTIONS_SCENARIO_UNLOCKING = 5630,
STR_DLC_PARKS = 5631,
STR_BUILD_YOUR_OWN_PARKS = 5632,
// Have to include resource strings (from scenarios and objects) for the time being now that language is partially working
STR_COUNT = 32768
};

View File

@ -155,6 +155,13 @@ void game_command_start_campaign(int* eax, int* ebx, int* ecx, int* edx, int* es
int rideOrItem = (*edx >> 8) & 0xFF;
int numWeeks = (*ebx >> 8) & 0xFF;
if (type < 0 || type >= countof(AdvertisingCampaignPricePerWeek))
{
log_warning("Invalid game command, type = %d", type);
*ebx = MONEY32_UNDEFINED;
return;
}
RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_MARKETING * 4;
if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_FORBID_MARKETING_CAMPAIGN) {
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 3048;

View File

@ -379,7 +379,7 @@ void news_item_open_subject(int type, int subject)
if (window != NULL) {
window_invalidate(window);
if (!tool_set(window, 9, 0)) {
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
gInputFlags |= INPUT_FLAG_6;
window_scenery_open();
}
}

View File

@ -358,17 +358,15 @@ int object_entry_compare(const rct_object_entry *a, const 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])))
int match = memcmp(a->name, b->name, 8);
if (match)
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])))
int match = memcmp(a->name, b->name, 8);
if (match)
return 0;
if (a->checksum != b->checksum)
return 0;

View File

@ -203,7 +203,7 @@ bool openrct2_initialise()
gOpenRCT2ShowChangelog = true;
if (gConfigGeneral.last_run_version != NULL && (strcmp(gConfigGeneral.last_run_version, OPENRCT2_VERSION) == 0))
gOpenRCT2ShowChangelog = false;
gConfigGeneral.last_run_version = OPENRCT2_VERSION;
gConfigGeneral.last_run_version = strndup(OPENRCT2_VERSION, strlen(OPENRCT2_VERSION));
config_save_default();
// TODO add configuration option to allow multiple instances

View File

@ -200,11 +200,11 @@ static uint8 peep_assess_surroundings(sint16 center_x, sint16 center_y, sint16 c
switch (map_element_get_type(mapElement)){
case MAP_ELEMENT_TYPE_PATH:
if ((mapElement->properties.path.additions & 0xF) == 0)
if (!footpath_element_has_path_scenery(mapElement))
break;
scenery = g_pathBitSceneryEntries[(mapElement->properties.path.additions & 0x0F) - 1];
if (mapElement->properties.path.additions & (1 << 7))
scenery = g_pathBitSceneryEntries[footpath_element_get_path_scenery_index(mapElement)];
if (footpath_element_path_scenery_is_ghost(mapElement))
break;
if (scenery->path_bit.var_06 &
@ -620,9 +620,10 @@ static void sub_68F41A(rct_peep *peep, int index)
if (mapElement->base_height != peep->next_z)
continue;
uint8 additions = mapElement->properties.path.additions & 0xF;
if (additions != 0 && mapElement->properties.path.additions & (1 << 7)){
rct_scenery_entry *sceneryEntry = g_pathBitSceneryEntries[additions - 1];
// Check if the footpath has ghost path scenery on it
if (footpath_element_has_path_scenery(mapElement) && footpath_element_path_scenery_is_ghost(mapElement)){
uint8 pathSceneryIndex = footpath_element_get_path_scenery_index(mapElement);
rct_scenery_entry *sceneryEntry = g_pathBitSceneryEntries[pathSceneryIndex];
if (sceneryEntry->path_bit.var_06 & (1 << 8)){
found = 1;
}
@ -803,10 +804,17 @@ static void sub_68F41A(rct_peep *peep, int index)
}
}
/* some sort of check to see if peep is connected to the ground?? */
int sub_68F3AE(rct_peep* peep){
/*
* rct2: 0x68F3AE
* Set peep state to falling if path below has gone missing, return 1 if current path is valid, 0 if peep starts falling
*/
int checkForPath(rct_peep *peep){
peep->var_C4++;
if ((peep->var_C4 & 0xF) != (peep->sprite_index & 0xF))return 1;
if ((peep->var_C4 & 0xF) != (peep->sprite_index & 0xF)){
// This condition makes the check happen less often so the peeps hover for a short,
// random time when a path below them has been deleted
return 1;
}
rct_map_element* map_element = map_get_first_element_at(peep->next_x / 32, peep->next_y / 32);
@ -819,10 +827,14 @@ int sub_68F3AE(rct_peep* peep){
do {
if (map_element_get_type(map_element) == map_type){
if (z == map_element->base_height)return 1;
if (z == map_element->base_height) {
// Found a suitable path
return 1;
}
}
} while (!map_element_is_last_for_tile(map_element++));
// Found no suitable path
peep_decrement_num_riders(peep);
peep->state = PEEP_STATE_FALLING;
peep_window_state_update(peep);
@ -830,31 +842,31 @@ int sub_68F3AE(rct_peep* peep){
}
void sub_693B58(rct_peep* peep){
int ebx;
if (peep->action >= 0xFE){
ebx = RCT2_ADDRESS(0x981D8C, uint8)[peep->var_6D];
uint8 action_sprite_type;
if (peep->action >= PEEP_ACTION_NONE_1){ // PEEP_ACTION_NONE_1 or PEEP_ACTION_NONE_2
action_sprite_type = RCT2_ADDRESS(0x981D8C, uint8)[peep->special_sprite];
}
else{
ebx = RCT2_ADDRESS(0x981D8F, uint8)[peep->action];
action_sprite_type = RCT2_ADDRESS(0x981D8F, uint8)[peep->action];
}
if (ebx == peep->action_sprite_type)return;
if (action_sprite_type == peep->action_sprite_type)return;
invalidate_sprite_2((rct_sprite*)peep);
peep->action_sprite_type = ebx;
peep->action_sprite_type = action_sprite_type;
uint8* edx = RCT2_ADDRESS(0x98270C, uint8*)[peep->sprite_type * 2];
peep->sprite_width = edx[ebx * 4];
peep->sprite_height_negative = edx[ebx * 4 + 1];
peep->sprite_height_positive = edx[ebx * 4 + 2];
rct_sprite_bounds* spriteBounds = g_sprite_entries[peep->sprite_type].sprite_bounds;
peep->sprite_width = spriteBounds[action_sprite_type].sprite_width;
peep->sprite_height_negative = spriteBounds[action_sprite_type].sprite_height_negative;
peep->sprite_height_positive = spriteBounds[action_sprite_type].sprite_height_positive;
// This is pointless as nothing will have changed.
invalidate_sprite_2((rct_sprite*)peep);
}
/* 0x00693BE5 */
void sub_693BE5(rct_peep* peep, uint8 al){
if (al == peep->var_6D)return;
if (al == peep->special_sprite)return;
peep->var_6D = al;
peep->special_sprite = al;
// If NONE_1 or NONE_2
if (peep->action >= PEEP_ACTION_NONE_1){
@ -998,8 +1010,8 @@ int peep_update_action(sint16* x, sint16* y, sint16* xy_distance, rct_peep* peep
*x = peep->x + RCT2_ADDRESS(0x981D7C, uint16)[direction / 4];
*y = peep->y + RCT2_ADDRESS(0x981D7E, uint16)[direction / 4];
peep->no_action_frame_no++;
uint32* edi = RCT2_ADDRESS(0x982708, uint32*)[peep->sprite_type * 2];
uint8* _edi = (uint8*)(edi[peep->action_sprite_type * 2 + 1]);
rct_sprite_image * edi = g_sprite_entries[peep->sprite_type].sprite_image;
uint8* _edi = (edi[peep->action_sprite_type]).unkn_04;
if (peep->no_action_frame_no >= *_edi){
peep->no_action_frame_no = 0;
}
@ -1007,8 +1019,8 @@ int peep_update_action(sint16* x, sint16* y, sint16* xy_distance, rct_peep* peep
return 1;
}
uint32* edi = RCT2_ADDRESS(0x982708, uint32*)[peep->sprite_type * 2];
uint8* _edi = (uint8*)(edi[peep->action_sprite_type * 2 + 1]);
rct_sprite_image * edi = g_sprite_entries[peep->sprite_type].sprite_image;
uint8* _edi = (edi[peep->action_sprite_type]).unkn_04;
peep->action_frame++;
int ebx = _edi[peep->action_frame + 1];
@ -1090,12 +1102,12 @@ void set_sprite_type(rct_peep* peep, uint8 type){
if (peep->state == PEEP_STATE_SITTING){
peep->action = PEEP_ACTION_NONE_1;
peep->var_6F = 7;
peep->next_action_sprite_type = 7;
sub_693BAB(peep);
}
if (peep->state == PEEP_STATE_WATCHING){
peep->action = PEEP_ACTION_NONE_1;
peep->var_6F = 2;
peep->next_action_sprite_type = 2;
sub_693BAB(peep);
}
}
@ -1458,7 +1470,7 @@ void peep_try_get_up_from_sitting(rct_peep* peep){
*/
void peep_update_sitting(rct_peep* peep){
if (peep->sub_state == 0){
if (!sub_68F3AE(peep))return;
if (!checkForPath(peep))return;
//691541
sub_693C9E(peep);
@ -1475,7 +1487,7 @@ void peep_update_sitting(rct_peep* peep){
peep->sprite_direction = ((peep->var_37 + 2) & 3) * 8;
invalidate_sprite_2((rct_sprite*)peep);
peep->action = 254;
peep->var_6F = 7;
peep->next_action_sprite_type = 7;
sub_693BAB(peep);
peep->sub_state++;
@ -3414,7 +3426,7 @@ static void peep_update_fixing(int steps, rct_peep* peep){
* rct2: 0x69185D
*/
static void peep_update_queuing(rct_peep* peep){
if (!sub_68F3AE(peep)){
if (!checkForPath(peep)){
remove_peep_from_queue(peep);
return;
}
@ -3465,7 +3477,7 @@ static void peep_update_queuing(rct_peep* peep){
}
}
else{
if (!(peep->time_in_queue & 0x3F) && peep->action == 0xFE && peep->var_6F == 2){
if (!(peep->time_in_queue & 0x3F) && peep->action == 0xFE && peep->next_action_sprite_type == 2){
switch (peep->sprite_type){
case 0xF:
case 0x10:
@ -3518,7 +3530,7 @@ static void peep_update_queuing(rct_peep* peep){
*/
static void peep_update_mowing(rct_peep* peep){
peep->var_E2 = 0;
if (!sub_68F3AE(peep))return;
if (!checkForPath(peep))return;
invalidate_sprite_2((rct_sprite*)peep);
while (1){
@ -3566,7 +3578,7 @@ static void peep_update_mowing(rct_peep* peep){
static void peep_update_watering(rct_peep* peep){
peep->var_E2 = 0;
if (peep->sub_state == 0){
if (!sub_68F3AE(peep))return;
if (!checkForPath(peep))return;
sub_693C9E(peep);
if (!(RCT2_GLOBAL(0xF1EE18, uint16) & 1))return;
@ -3622,7 +3634,7 @@ static void peep_update_emptying_bin(rct_peep* peep){
peep->var_E2 = 0;
if (peep->sub_state == 0){
if (!sub_68F3AE(peep))return;
if (!checkForPath(peep))return;
sub_693C9E(peep);
if (!(RCT2_GLOBAL(0xF1EE18, uint16) & 1))return;
@ -3661,16 +3673,16 @@ static void peep_update_emptying_bin(rct_peep* peep){
}
}
if ((map_element->properties.path.additions & 0x0F) == 0) {
if (!footpath_element_has_path_scenery(map_element)) {
peep_state_reset(peep);
return;
}
rct_scenery_entry* scenery_entry = g_pathBitSceneryEntries[(map_element->properties.path.additions & 0xF) - 1];
rct_scenery_entry* scenery_entry = g_pathBitSceneryEntries[footpath_element_get_path_scenery_index(map_element)];
if (
!(scenery_entry->path_bit.var_06 & 1)
|| map_element->flags & (1 << 5)
|| map_element->properties.path.additions & (1 << 7)
|| footpath_element_path_scenery_is_ghost(map_element)
) {
peep_state_reset(peep);
return;
@ -3691,7 +3703,7 @@ static void peep_update_emptying_bin(rct_peep* peep){
*/
static void peep_update_sweeping(rct_peep* peep){
peep->var_E2 = 0;
if (!sub_68F3AE(peep))return;
if (!checkForPath(peep))return;
invalidate_sprite_2((rct_sprite*)peep);
@ -3726,7 +3738,7 @@ static void peep_update_sweeping(rct_peep* peep){
* rct2: 0x6902A2
*/
static void peep_update_1(rct_peep* peep){
if (!sub_68F3AE(peep))return;
if (!checkForPath(peep))return;
peep_decrement_num_riders(peep);
@ -3795,7 +3807,7 @@ static void peep_update_leaving_park(rct_peep* peep){
*/
static void peep_update_watching(rct_peep* peep){
if (peep->sub_state == 0){
if (!sub_68F3AE(peep))return;
if (!checkForPath(peep))return;
sub_693C9E(peep);
if (!(RCT2_GLOBAL(0xF1EE18, uint16) & 1))return;
@ -3807,7 +3819,7 @@ static void peep_update_watching(rct_peep* peep){
invalidate_sprite_2((rct_sprite*)peep);
peep->action = 0xFE;
peep->var_6F = 2;
peep->next_action_sprite_type = 2;
sub_693BAB(peep);
@ -3925,16 +3937,14 @@ static int peep_update_walking_find_bench(rct_peep* peep){
}
}
uint8 additions = map_element->properties.path.additions & 0xF;
if (!additions) return 0;
rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[additions - 1];
if (!footpath_element_has_path_scenery(map_element)) return 0;
rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[footpath_element_get_path_scenery_index(map_element)];
if (!(sceneryEntry->path_bit.var_06 & 0x2))return 0;
if (map_element->flags & MAP_ELEMENT_FLAG_BROKEN)return 0;
if (map_element->properties.path.additions & 0x80)return 0;
if (footpath_element_path_scenery_is_ghost(map_element)) return 0;
int edges = (map_element->properties.path.edges & 0xF) ^ 0xF;
if (edges == 0) return 0;
@ -4002,16 +4012,14 @@ static int peep_update_walking_find_bin(rct_peep* peep){
}
}
uint8 additions = map_element->properties.path.additions & 0xF;
if (!additions) return 0;
rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[additions - 1];
if (!footpath_element_has_path_scenery(map_element)) return 0;
rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[footpath_element_get_path_scenery_index(map_element)];
if (!(sceneryEntry->path_bit.var_06 & 0x1))return 0;
if (map_element->flags & MAP_ELEMENT_FLAG_BROKEN)return 0;
if (map_element->properties.path.additions & 0x80)return 0;
if (footpath_element_path_scenery_is_ghost(map_element)) return 0;
int edges = (map_element->properties.path.edges & 0xF) ^ 0xF;
if (edges == 0) return 0;
@ -4085,16 +4093,14 @@ static void peep_update_walking_break_scenery(rct_peep* peep){
}
}
uint8 additions = map_element->properties.path.additions & 0xF;
if (!additions) return;
rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[additions - 1];
if (!footpath_element_has_path_scenery(map_element)) return;
rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[footpath_element_get_path_scenery_index(map_element)];
if (!(sceneryEntry->path_bit.var_06 & 0x4))return;
if (map_element->flags & MAP_ELEMENT_FLAG_BROKEN)return;
if (map_element->properties.path.additions & 0x80)return;
if (footpath_element_path_scenery_is_ghost(map_element))return;
int edges = map_element->properties.path.edges & 0xF;
if (edges == 0xF) return;
@ -4132,7 +4138,7 @@ static void peep_update_walking_break_scenery(rct_peep* peep){
*/
static void peep_update_buying(rct_peep* peep)
{
if (!sub_68F3AE(peep))return;
if (!checkForPath(peep))return;
rct_ride* ride = GET_RIDE(peep->current_ride);
if (ride->type == RIDE_TYPE_NULL || ride->status != RIDE_STATUS_OPEN){
@ -4225,7 +4231,7 @@ static void peep_update_buying(rct_peep* peep)
*/
static void peep_update_using_bin(rct_peep* peep){
if (peep->sub_state == 0){
if (!sub_68F3AE(peep))return;
if (!checkForPath(peep))return;
sub_693C9E(peep);
if (!(RCT2_GLOBAL(0xF1EE18, uint16) & 1))return;
@ -4255,13 +4261,12 @@ static void peep_update_using_bin(rct_peep* peep){
}
}
uint8 additions = map_element->properties.path.additions & 0x0F;
if (!additions){
if (!footpath_element_has_path_scenery(map_element)){
peep_state_reset(peep);
return;
}
rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[additions - 1];
rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[footpath_element_get_path_scenery_index(map_element)];
if (!(sceneryEntry->path_bit.var_06 & 1)){
peep_state_reset(peep);
return;
@ -4272,7 +4277,7 @@ static void peep_update_using_bin(rct_peep* peep){
return;
}
if (map_element->properties.path.additions & 0x80){
if (footpath_element_path_scenery_is_ghost(map_element)){
peep_state_reset(peep);
return;
}
@ -4400,7 +4405,7 @@ static void peep_update_heading_to_inspect(rct_peep* peep){
return;
}
if (!sub_68F3AE(peep))return;
if (!checkForPath(peep))return;
sub_693C9E(peep);
@ -4513,7 +4518,7 @@ static void peep_update_answering(rct_peep* peep){
return;
}
if (!sub_68F3AE(peep))return;
if (!checkForPath(peep))return;
sub_693C9E(peep);
@ -4656,11 +4661,8 @@ static int peep_update_patrolling_find_bin(rct_peep* peep){
return 0;
}
uint8 additions = map_element->properties.path.additions & 0xF;
if (additions == 0)return 0;
rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[additions - 1];
if (!footpath_element_has_path_scenery(map_element)) return 0;
rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[footpath_element_get_path_scenery_index(map_element)];
if (!(sceneryEntry->path_bit.var_06 & 1))
return 0;
@ -4668,7 +4670,7 @@ static int peep_update_patrolling_find_bin(rct_peep* peep){
if (map_element->flags & MAP_ELEMENT_FLAG_BROKEN)
return 0;
if (map_element->properties.path.additions & 0x80)
if (footpath_element_path_scenery_is_ghost(map_element))
return 0;
uint8 bin_positions = map_element->properties.path.edges & 0xF;
@ -4768,7 +4770,7 @@ static int peep_update_patrolling_find_sweeping(rct_peep* peep){
*/
static void peep_update_patrolling(rct_peep* peep){
if (!sub_68F3AE(peep))return;
if (!checkForPath(peep))return;
sub_693C9E(peep);
if (!(RCT2_GLOBAL(0xF1EE18, uint16) & 1))return;
@ -4808,7 +4810,7 @@ static void peep_update_patrolling(rct_peep* peep){
* rct2: 0x0069030A
*/
static void peep_update_walking(rct_peep* peep){
if (!sub_68F3AE(peep))return;
if (!checkForPath(peep))return;
if (peep->flags & PEEP_FLAGS_WAVING){
if (peep->action >= PEEP_ACTION_NONE_1){
@ -4958,13 +4960,11 @@ static void peep_update_walking(rct_peep* peep){
}
}
uint8 additions = map_element->properties.path.additions & 0xF;
int ebp = 15;
if (additions){
if (!(map_element->properties.path.additions & 0x80)){
rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[additions - 1];
if (footpath_element_has_path_scenery(map_element)) {
if (!footpath_element_path_scenery_is_ghost(map_element)) {
rct_scenery_entry* sceneryEntry = g_pathBitSceneryEntries[footpath_element_get_path_scenery_index(map_element)];
if (!(sceneryEntry->path_bit.var_06 & 0x2)) ebp = 9;
}
@ -5484,7 +5484,7 @@ rct_peep *peep_generate(int x, int y, int z)
peep->outside_of_park = 1;
peep->state = PEEP_STATE_FALLING;
peep->action = PEEP_ACTION_NONE_2;
peep->var_6D = 0;
peep->special_sprite = 0;
peep->action_sprite_image_offset = 0;
peep->no_action_frame_no = 0;
peep->action_sprite_type = 0;
@ -5492,10 +5492,10 @@ rct_peep *peep_generate(int x, int y, int z)
peep->favourite_ride = 0xFF;
peep->favourite_ride_rating = 0;
uint8* edx = RCT2_ADDRESS(0x98270C, uint8*)[peep->sprite_type * 2];
peep->sprite_width = edx[peep->action_sprite_type * 4];
peep->sprite_height_negative = edx[peep->action_sprite_type * 4 + 1];
peep->sprite_height_positive = edx[peep->action_sprite_type * 4 + 2];
rct_sprite_bounds* spriteBounds = g_sprite_entries[peep->sprite_type].sprite_bounds;
peep->sprite_width = spriteBounds[peep->action_sprite_type].sprite_width;
peep->sprite_height_negative = spriteBounds[peep->action_sprite_type].sprite_height_negative;
peep->sprite_height_positive = spriteBounds[peep->action_sprite_type].sprite_height_positive;
peep->sprite_direction = 0;
@ -6160,14 +6160,15 @@ void peep_set_map_tooltip(rct_peep *peep)
void sub_693BAB(rct_peep* peep) {
uint8 bl = peep->var_6F;
if (bl != peep->action_sprite_type) {
// TBD: Add nextActionSpriteType as function parameter and make peep->next_action_sprite_type obsolete?
uint8 nextActionSpriteType = peep->next_action_sprite_type;
if (nextActionSpriteType != peep->action_sprite_type) {
invalidate_sprite_2((rct_sprite*)peep);
peep->action_sprite_type = bl;
uint8* edx = RCT2_ADDRESS(0x98270C, uint8*)[peep->sprite_type * 2];
peep->sprite_width = edx[bl * 4];
peep->sprite_height_negative = edx[bl * 4 + 1];
peep->sprite_height_positive = edx[bl * 4 + 2];
peep->action_sprite_type = nextActionSpriteType;
rct_sprite_bounds* spriteBounds = g_sprite_entries[peep->sprite_type].sprite_bounds;
peep->sprite_width = spriteBounds[nextActionSpriteType].sprite_width;
peep->sprite_height_negative = spriteBounds[nextActionSpriteType].sprite_height_negative;
peep->sprite_height_positive = spriteBounds[nextActionSpriteType].sprite_height_positive;
invalidate_sprite_2((rct_sprite*)peep);
}
}
@ -6235,7 +6236,7 @@ static int peep_update_queue_position(rct_peep* peep){
return 1;
peep->action = PEEP_ACTION_NONE_1;
peep->var_6F = 2;
peep->next_action_sprite_type = 2;
if (RCT2_GLOBAL(0x00F1AEF1, uint8) != 0xFE)
invalidate_sprite_2((rct_sprite*)peep);
return 1;
@ -6629,7 +6630,7 @@ static int peep_interact_with_path(rct_peep* peep, sint16 x, sint16 y, rct_map_e
// 0x00F1AEE2
bool vandalism_present = false;
if ((map_element->properties.path.additions & 0xF) != 0 &&
if (footpath_element_has_path_scenery(map_element) &&
(map_element->flags & MAP_ELEMENT_FLAG_BROKEN) &&
(map_element->properties.path.edges & 0xF) != 0xF){
vandalism_present = 1;

View File

@ -372,6 +372,12 @@ enum {
PEEP_RIDE_DECISION_THINKING = 1 << 2
};
// Flags used by peep->list_flags
enum {
PEEP_LIST_FLAGS_VISIBLE = 1 << 8, // Peep is eligible to show in summarized guest list window (is inside park?)
PEEP_LIST_FLAGS_FLASHING = 1 << 9, // Peep belongs to highlighted group (flashes red on map)
};
typedef struct {
uint8 type; //0
uint8 item; //1
@ -389,7 +395,7 @@ typedef struct {
// Height from center of sprite to bottom
uint8 sprite_height_negative; // 0x09
uint16 sprite_index; // 0x0A
uint16 var_0C;
uint16 list_flags; // 0x0C Used for highlighting peeps on map with staff list or guest list open
sint16 x; // 0x0E
sint16 y; // 0x10
sint16 z; // 0x12
@ -458,9 +464,11 @@ typedef struct {
uint8 standing_flags; //0x6C
};
};
uint8 var_6D; // 0x6D
// Normally 0, 1 for carrying sliding board on spiral slide ride, 2 for carrying lawn mower
uint8 special_sprite; // 0x6D
uint8 action_sprite_type; // 0x6E
uint8 var_6F;
// Seems to be used like a local variable, as it's always set before calling sub_693BAB, which reads this again
uint8 next_action_sprite_type; // 0x6F
uint8 action_sprite_image_offset; // 0x70
uint8 action; // 0x71
uint8 action_frame; // 0x72
@ -488,7 +496,7 @@ typedef struct {
uint8 previous_ride; // 0xAD
uint16 previous_ride_time_out; // 0xAE
rct_peep_thought thoughts[PEEP_MAX_THOUGHTS]; // 0xB0
uint8 var_C4; // 0xC4
uint8 var_C4; // 0xC4 has something to do with peep falling, see peep.checkForPath
union {
uint8 staff_id; // 0xC5
uint8 guest_heading_to_ride_id; // 0xC5

View File

@ -109,7 +109,8 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx,
int newStaffId = i;
int _eax, _ebx, _ecx = _cx, _edx;
int _eax, _ebx, _ecx = _cx;
rct_sprite_bounds *spriteBounds;
_ebx = _bl;
rct_peep* newPeep = &(create_sprite(_bl)->peep);
@ -129,7 +130,7 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx,
newPeep->sprite_identifier = 1;
newPeep->window_invalidate_flags = 0;
newPeep->action = PEEP_ACTION_NONE_2;
newPeep->var_6D = 0;
newPeep->special_sprite = 0;
newPeep->action_sprite_image_offset = 0;
newPeep->no_action_frame_no = 0;
newPeep->action_sprite_type = 0;
@ -181,10 +182,10 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx,
newPeep->name_string_idx = staff_type + 0x300;
newPeep->sprite_type = _eax;
_edx = RCT2_ADDRESS(0x0098270C, uint32)[_eax * 2];
newPeep->sprite_width = *((uint8*)_edx);
newPeep->sprite_height_negative = *((uint8*)(_edx + 1));
newPeep->sprite_height_positive = *((uint8*)(_edx + 2));
spriteBounds = g_sprite_entries[_eax].sprite_bounds;
newPeep->sprite_width = spriteBounds->sprite_width;
newPeep->sprite_height_negative = spriteBounds->sprite_height_negative;
newPeep->sprite_height_positive = spriteBounds->sprite_height_positive;
if ((gConfigGeneral.auto_staff_placement != 0) != ((SDL_GetModState() & KMOD_SHIFT) != 0)) {
newPeep->state = PEEP_STATE_FALLING;
@ -292,7 +293,13 @@ void game_command_set_staff_order(int *eax, int *ebx, int *ecx, int *edx, int *e
RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_WAGES * 4;
uint8 order_id = *ebx >> 8;
uint16 sprite_id = *edx;
if(*ebx & GAME_COMMAND_FLAG_APPLY){
if (sprite_id >= MAX_SPRITES)
{
log_warning("Invalid game command, sprite_id = %u", sprite_id);
*ebx = MONEY32_UNDEFINED;
return;
}
if (*ebx & GAME_COMMAND_FLAG_APPLY) {
rct_peep *peep = &g_sprite_list[sprite_id].peep;
if(order_id & 0x80){ // change costume
uint8 sprite_type = order_id & ~0x80;
@ -365,7 +372,19 @@ void game_command_fire_staff_member(int *eax, int *ebx, int *ecx, int *edx, int
if(*ebx & GAME_COMMAND_FLAG_APPLY){
window_close_by_class(WC_FIRE_PROMPT);
uint16 sprite_id = *edx;
if (sprite_id >= MAX_SPRITES)
{
log_warning("Invalid game command, sprite_id = %u", sprite_id);
*ebx = MONEY32_UNDEFINED;
return;
}
rct_peep *peep = &g_sprite_list[sprite_id].peep;
if (peep->sprite_identifier != SPRITE_IDENTIFIER_PEEP || peep->type != PEEP_TYPE_STAFF)
{
log_warning("Invalid game command, peep->sprite_identifier = %u, peep->type = %u", peep->sprite_identifier, peep->type);
*ebx = MONEY32_UNDEFINED;
return;
}
remove_peep_from_ride(peep);
peep_sprite_remove(peep);
}

View File

@ -166,6 +166,8 @@ bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer);
bool platform_check_steam_overlay_attached();
datetime64 platform_get_datetime_now_utc();
// BSD and OS X has MAP_ANON instead of MAP_ANONYMOUS
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON

View File

@ -36,6 +36,7 @@
#include <dirent.h>
#include <fnmatch.h>
#include <locale.h>
#include <sys/time.h>
#include <time.h>
// The name of the mutex used to prevent multiple instances of the game from running
@ -499,8 +500,8 @@ bool platform_file_move(const utf8 *srcPath, const utf8 *dstPath)
bool platform_file_delete(const utf8 *path)
{
STUB();
return 0;
int ret = unlink(path);
return ret == 0;
}
wchar_t *regular_to_wchar(const char* src)
@ -753,4 +754,20 @@ uint8 platform_get_locale_temperature_format(){
return TEMPERATURE_FORMAT_C;
}
datetime64 platform_get_datetime_now_utc()
{
const datetime64 epochAsTicks = 621355968000000000;
struct timeval tv;
gettimeofday(&tv, NULL);
uint64 utcEpoch = tv.tv_sec;
// Epoch starts from: 1970-01-01T00:00:00Z
// Convert to ticks from 0001-01-01T00:00:00Z
uint64 utcEpochTicks = (uint64)tv.tv_sec * 10000000ULL + tv.tv_usec * 10;
datetime64 utcNow = epochAsTicks + utcEpochTicks;
return utcNow;
}
#endif

View File

@ -242,7 +242,11 @@ void platform_draw()
if (pitch == (width * 2) + padding) {
uint16 *dst = pixels;
for (int y = height; y > 0; y--) {
for (int x = width; x > 0; x--) { *dst++ = *(uint16 *)(&gPaletteHWMapped[*src++]); }
for (int x = width; x > 0; x--) {
const uint8 lower = *(uint8 *)(&gPaletteHWMapped[*src++]);
const uint8 upper = *(uint8 *)(&gPaletteHWMapped[*src++]);
*dst++ = (lower << 8) | upper;
}
dst = (uint16*)(((uint8 *)dst) + padding);
}
}

View File

@ -262,6 +262,48 @@ int platform_enumerate_files_begin(const utf8 *pattern)
return INVALID_HANDLE;
}
/**
* Due to FindFirstFile / FindNextFile searching for DOS names as well, *.doc also matches *.docx which isn't what the pattern
* specified. This will verify if a filename does indeed match the pattern we asked for.
* @remarks Based on algorithm (http://xoomer.virgilio.it/acantato/dev/wildcard/wildmatch.html)
*/
static bool match_wildcard(const wchar_t *fileName, const wchar_t *pattern)
{
while (*fileName != '\0') {
switch (*pattern) {
case '?':
if (*fileName == '.') {
return false;
}
break;
case '*':
do {
pattern++;
} while (*pattern == '*');
if (*pattern == '\0') {
return false;
}
while (*fileName != '\0') {
if (match_wildcard(fileName++, pattern)) {
return true;
}
}
return false;
default:
if (toupper(*fileName) != toupper(*pattern)) {
return false;
}
break;
}
pattern++;
fileName++;
}
while (*pattern == '*') {
++fileName;
}
return *pattern == '\0';
}
bool platform_enumerate_files_next(int handle, file_info *outFileInfo)
{
bool result;
@ -270,18 +312,28 @@ bool platform_enumerate_files_next(int handle, file_info *outFileInfo)
enumFileInfo = &_enumerateFileInfoList[handle];
if (enumFileInfo->handle == NULL) {
findFileHandle = FindFirstFileW(enumFileInfo->pattern, &enumFileInfo->data);
if (findFileHandle != INVALID_HANDLE_VALUE) {
enumFileInfo->handle = findFileHandle;
result = true;
} else {
result = false;
}
// Get pattern (just filename part)
const wchar_t *patternWithoutDirectory = wcsrchr(enumFileInfo->pattern, '\\');
if (patternWithoutDirectory == NULL) {
patternWithoutDirectory = enumFileInfo->pattern;
} else {
result = FindNextFileW(enumFileInfo->handle, &enumFileInfo->data);
patternWithoutDirectory++;
}
do {
if (enumFileInfo->handle == NULL) {
findFileHandle = FindFirstFileW(enumFileInfo->pattern, &enumFileInfo->data);
if (findFileHandle != INVALID_HANDLE_VALUE) {
enumFileInfo->handle = findFileHandle;
result = true;
} else {
result = false;
}
} else {
result = FindNextFileW(enumFileInfo->handle, &enumFileInfo->data);
}
} while (result && !match_wildcard(enumFileInfo->data.cFileName, patternWithoutDirectory));
if (result) {
outFileInfo->path = enumFileInfo->outFilename = widechar_to_utf8(enumFileInfo->data.cFileName);
outFileInfo->size = ((uint64)enumFileInfo->data.nFileSizeHigh << 32ULL) | (uint64)enumFileInfo->data.nFileSizeLow;
@ -935,4 +987,17 @@ bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer)
#endif
}
datetime64 platform_get_datetime_now_utc()
{
// Get file time
FILETIME fileTime;
GetSystemTimeAsFileTime(&fileTime);
uint64 fileTime64 = ((uint64)fileTime.dwHighDateTime << 32ULL) | ((uint64)fileTime.dwLowDateTime);
// File time starts from: 1601-01-01T00:00:00Z
// Convert to start from: 0001-01-01T00:00:00Z
datetime64 utcNow = fileTime64 - 504911232000000000ULL;
return utcNow;
}
#endif

View File

@ -776,23 +776,22 @@ static void rct1_fix_paths()
mapElement->type &= 0xFC;
mapElement->flags &= ~0x60;
mapElement->properties.path.type &= 0x0F;
mapElement->properties.path.additions &= 0x7F;
footpath_scenery_set_is_ghost(mapElement, false);
if (pathType & 0x80) {
mapElement->type |= 1;
}
mapElement->properties.path.type |= pathType << 4;
// Additions
additions = mapElement->properties.path.additions & 0x0F;
additions = RCT1PathAdditionConversionTable[additions];
if (additions & 0x80) {
additions &= ~0x80;
additions = RCT1PathAdditionConversionTable[footpath_element_get_path_scenery(mapElement)];
if (footpath_element_path_scenery_is_ghost(mapElement)) {
footpath_scenery_set_is_ghost(mapElement, false);
mapElement->flags |= MAP_ELEMENT_FLAG_BROKEN;
} else {
mapElement->flags &= ~MAP_ELEMENT_FLAG_BROKEN;
}
mapElement->properties.path.additions &= 0xF0;
mapElement->properties.path.additions |= additions;
footpath_element_set_path_scenery(mapElement, additions);
break;
case MAP_ELEMENT_TYPE_ENTRANCE:
if (mapElement->properties.entrance.type == ENTRANCE_TYPE_PARK_ENTRANCE) {

View File

@ -438,9 +438,6 @@ void rct2_update_2()
if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0)
RCT2_GLOBAL(RCT2_ADDRESS_PALETTE_EFFECT_FRAME_NO, sint32) += tick2;
if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) != 0)
RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_LAST_UPDATE, sint16) = 31;
// TODO: screenshot countdown process
network_update();

View File

@ -115,6 +115,11 @@ typedef utf16* utf16string;
#define OPENRCT2_MASTER_SERVER_URL "https://servers.openrct2.website"
// Time (represented as number of 100-nanosecond intervals since 0001-01-01T00:00:00Z)
typedef uint64 datetime64;
#define DATETIME64_MIN ((datetime64)0)
// Represent fixed point numbers. dp = decimal point
typedef uint8 fixed8_1dp;
typedef uint8 fixed8_2dp;

View File

@ -1592,7 +1592,7 @@ static int ride_modify_entrance_or_exit(rct_map_element *mapElement, int x, int
sub_6C9627();
if (
_rideConstructionState != RIDE_CONSTRUCTION_STATE_ENTRANCE_EXIT ||
!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) ||
!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE) ||
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != WC_RIDE_CONSTRUCTION
) {
// Replace entrance / exit
@ -1600,7 +1600,7 @@ static int ride_modify_entrance_or_exit(rct_map_element *mapElement, int x, int
RCT2_GLOBAL(0x00F44191, uint8) = entranceType;
RCT2_GLOBAL(0x00F44192, uint8) = rideIndex;
RCT2_GLOBAL(0x00F44193, uint8) = bl;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
gInputFlags |= INPUT_FLAG_6;
if (_rideConstructionState != RIDE_CONSTRUCTION_STATE_ENTRANCE_EXIT) {
RCT2_GLOBAL(0x00F440CC, uint8) = _rideConstructionState;
_rideConstructionState = RIDE_CONSTRUCTION_STATE_ENTRANCE_EXIT;
@ -1755,7 +1755,7 @@ int sub_6CC3FB(int rideIndex)
w = ride_create_or_find_construction_window(rideIndex);
tool_set(w, 23, 12);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
gInputFlags |= INPUT_FLAG_6;
ride = GET_RIDE(_currentRideIndex);
@ -2467,7 +2467,7 @@ rct_peep *find_closest_mechanic(int x, int y, int forInspection)
uint16 spriteIndex;
rct_peep *peep, *closestMechanic = NULL;
closestDistance = -1;
closestDistance = UINT_MAX;
FOR_ALL_STAFF(spriteIndex, peep) {
if (peep->staff_type != STAFF_TYPE_MECHANIC)
continue;
@ -2494,15 +2494,15 @@ rct_peep *find_closest_mechanic(int x, int y, int forInspection)
if (peep->x == (sint16)0x8000)
continue;
// Should probably be euclidean or manhattan distance, this seems a bit naive
distance = max(abs(peep->x - x), abs(peep->y - y));
// manhattan distance
distance = abs(peep->x - x) + abs(peep->y - y);
if (distance < closestDistance) {
closestDistance = distance;
closestMechanic = peep;
}
}
return closestDistance == -1 ? NULL : closestMechanic;
return closestMechanic;
}
rct_peep *ride_get_assigned_mechanic(rct_ride *ride)
@ -2920,7 +2920,15 @@ static bool ride_does_vehicle_colour_exist(uint8 ride_sub_type, vehicle_colour *
static int ride_get_unused_preset_vehicle_colour(uint8 ride_type, uint8 ride_sub_type)
{
if (ride_sub_type >= 128)
{
return 0;
}
rct_ride_type *rideEntry = GET_RIDE_ENTRY(ride_sub_type);
if (rideEntry == (rct_ride_type *)0xFFFFFFFF)
{
return 0;
}
vehicle_colour_preset_list *presetList = rideEntry->vehicle_preset_list;
if (presetList->count == 255)
return 255;
@ -3594,6 +3602,12 @@ void game_command_set_ride_setting(int *eax, int *ebx, int *ecx, int *edx, int *
uint8 ride_id = *edx & 0xFF;
rct_ride* ride = GET_RIDE(ride_id);
if (ride->type == RIDE_TYPE_NULL)
{
log_warning("Invalid game command.");
*ebx = MONEY32_UNDEFINED;
return;
}
uint8 flags = *ebx & 0xFF;
uint8 new_value = (*ebx >> 8) & 0xFF;
@ -4612,6 +4626,11 @@ int ride_is_valid_for_test(int rideIndex, int goingToBeOpen, int isApplying)
rct_xy_element trackElement, problematicTrackElement;
ride = GET_RIDE(rideIndex);
if (ride->type == RIDE_TYPE_NULL)
{
log_warning("Invalid ride type for ride %u", rideIndex);
return 0;
}
window_close_by_number(WC_RIDE_CONSTRUCTION, rideIndex);
@ -4870,6 +4889,12 @@ void game_command_set_ride_status(int *eax, int *ebx, int *ecx, int *edx, int *e
RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS * 4;
ride = GET_RIDE(rideIndex);
if (ride->type == RIDE_TYPE_NULL)
{
log_warning("Invalid game command for ride %u", rideIndex);
*ebx = MONEY32_UNDEFINED;
return;
}
RCT2_GLOBAL(0x00F43484, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32);
switch (targetStatus) {
@ -4950,6 +4975,7 @@ void game_command_set_ride_name(int *eax, int *ebx, int *ecx, int *edx, int *esi
if (nameChunkOffset < 0)
nameChunkOffset = 2;
nameChunkOffset *= 12;
nameChunkOffset = min(nameChunkOffset, countof(newName) - 12);
RCT2_GLOBAL(newName + nameChunkOffset + 0, uint32) = *edx;
RCT2_GLOBAL(newName + nameChunkOffset + 4, uint32) = *ebp;
RCT2_GLOBAL(newName + nameChunkOffset + 8, uint32) = *edi;
@ -5168,6 +5194,10 @@ static int ride_get_random_colour_preset_index(uint8 ride_type)
{
const track_colour_preset_list *colourPresets;
const track_colour *colours;
if (ride_type >= 128)
{
return 0;
}
colourPresets = RCT2_ADDRESS(0x0097D934, track_colour_preset_list*)[ride_type];
@ -5271,6 +5301,11 @@ money32 ride_create(int type, int subType, int flags, int *outRideIndex, int *ou
foundRideEntry:
rideEntryIndex = subType;
rideIndex = ride_get_empty_slot();
if (subType >= 128)
{
log_warning("Invalid request for ride type %u", subType);
return MONEY32_UNDEFINED;
}
if (rideIndex == -1) {
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_TOO_MANY_RIDES;
return MONEY32_UNDEFINED;
@ -5293,6 +5328,11 @@ foundRideEntry:
ride = GET_RIDE(rideIndex);
rideEntry = GET_RIDE_ENTRY(rideEntryIndex);
if (rideEntry == (rct_ride_type *)0xFFFFFFFF)
{
log_warning("Invalid request for ride %u", rideIndex);
return MONEY32_UNDEFINED;
}
ride->type = type;
ride->subtype = rideEntryIndex;
ride_set_colour_preset(ride, *outRideColour & 0xFF);
@ -5602,7 +5642,13 @@ void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi
RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16) = 0;
rct_ride *ride = &g_ride_list[ride_id];
rct_ride *ride = GET_RIDE(ride_id);
if (ride->type == RIDE_TYPE_NULL)
{
log_warning("Invalid game command for ride %u", ride_id);
*ebx = MONEY32_UNDEFINED;
return;
}
int x = 0, y = 0, z = 0;
if(ride->overall_view != (uint16)-1){
x = ((ride->overall_view & 0xFF) * 32) + 16;
@ -5730,25 +5776,61 @@ void game_command_set_ride_appearance(int *eax, int *ebx, int *ecx, int *edx, in
uint8 type = *ebx >> 8;
uint8 value = *edx >> 8;
int index = *edi;
rct_ride *ride = &g_ride_list[ride_id];
if (index < 0) {
log_warning("Invalid game command, index %d out of bounds", index);
*ebx = MONEY32_UNDEFINED;
return;
}
rct_ride *ride = GET_RIDE(ride_id);
if (ride->type == RIDE_TYPE_NULL) {
log_warning("Invalid game command, ride_id = %u", ride_id);
*ebx = MONEY32_UNDEFINED;
return;
}
*ebx = 0;
switch(type){
case 0:
if (index >= countof(ride->track_colour_main)) {
log_warning("Invalid game command, index %d out of bounds", index);
*ebx = MONEY32_UNDEFINED;
break;
}
ride->track_colour_main[index] = value;
gfx_invalidate_screen();
break;
case 1:
if (index >= countof(ride->track_colour_additional)) {
log_warning("Invalid game command, index %d out of bounds", index);
*ebx = MONEY32_UNDEFINED;
break;
}
ride->track_colour_additional[index] = value;
gfx_invalidate_screen();
break;
case 2:
if (index >= countof(ride->vehicle_colours)) {
log_warning("Invalid game command, index %d out of bounds", index);
*ebx = MONEY32_UNDEFINED;
break;
}
*((uint8*)(&ride->vehicle_colours[index])) = value;
ride_update_vehicle_colours(ride_id);
break;
case 3:
if (index >= countof(ride->vehicle_colours)) {
log_warning("Invalid game command, index %d out of bounds", index);
*ebx = MONEY32_UNDEFINED;
break;
}
*((uint8*)(&ride->vehicle_colours[index]) + 1) = value;
ride_update_vehicle_colours(ride_id);
break;
case 4:
if (index >= countof(ride->track_colour_supports)) {
log_warning("Invalid game command, index %d out of bounds", index);
*ebx = MONEY32_UNDEFINED;
break;
}
ride->track_colour_supports[index] = value;
gfx_invalidate_screen();
break;
@ -5767,13 +5849,17 @@ void game_command_set_ride_appearance(int *eax, int *ebx, int *ecx, int *edx, in
gfx_invalidate_screen();
break;
case 7:
if (index >= countof(ride->vehicle_colours_extended)) {
log_warning("Invalid game command, index %d out of bounds", index);
*ebx = MONEY32_UNDEFINED;
break;
}
ride->vehicle_colours_extended[index] = value;
ride_update_vehicle_colours(ride_id);
break;
}
window_invalidate_by_number(WC_RIDE, ride_id);
}
*ebx = 0;
}
/**
@ -5786,21 +5872,28 @@ void game_command_set_ride_price(int *eax, int *ebx, int *ecx, int *edx, int *es
uint8 ride_number;
money16 price;
rct_ride *ride;
rct_ride_type *ride_type;
rct_ride_type *rideEntry;
bool secondary_price;
flags = *ebx;
ride_number = (*edx & 0xFF);
ride = GET_RIDE(ride_number);
ride_type = gRideTypeList[ride->subtype];
rideEntry = GET_RIDE_ENTRY(ride->subtype);
price = *edi;
secondary_price = (*edx >> 8);
if (rideEntry == (rct_ride_type *)0xFFFFFFFF)
{
log_warning("Invalid game command for ride %u", ride_number);
*ebx = MONEY32_UNDEFINED;
return;
}
//eax
//ebx flags
//ecx ecx
//edx ride_number
//ebp ride_type
//ebp rideEntry
*ebx = 0; // for cost check - changing ride price does not cost anything
@ -5809,7 +5902,7 @@ void game_command_set_ride_price(int *eax, int *ebx, int *ecx, int *edx, int *es
if (!secondary_price) {
shop_item = 0x1F;
if (ride->type != RIDE_TYPE_TOILETS) {
shop_item = ride_type->shop_item;
shop_item = rideEntry->shop_item;
if (shop_item == 0xFF) {
ride->price = price;
window_invalidate_by_class(WC_RIDE);
@ -5824,7 +5917,7 @@ void game_command_set_ride_price(int *eax, int *ebx, int *ecx, int *edx, int *es
}
}
else {
shop_item = ride_type->shop_item_secondary;
shop_item = rideEntry->shop_item_secondary;
if (shop_item == 0xFF) {
shop_item = RCT2_GLOBAL(0x0097D7CB + (ride->type * 4), uint8);
if ((ride->lifecycle_flags & RIDE_LIFECYCLE_ON_RIDE_PHOTO) == 0) {
@ -5841,12 +5934,12 @@ void game_command_set_ride_price(int *eax, int *ebx, int *ecx, int *edx, int *es
}
}
ride = GET_RIDE(0);
ride_type = gRideTypeList[ride->subtype];
rideEntry = GET_RIDE_ENTRY(ride->subtype);
uint8 count = 0;
while (count < 0xFF) {
if (ride->type != 0xFF) {
if (ride->type != RIDE_TYPE_TOILETS || shop_item != 0x1F) {
if (ride_type->shop_item == shop_item) {
if (rideEntry->shop_item == shop_item) {
ride->price = price;
window_invalidate_by_number(WC_RIDE, count);
}
@ -5856,8 +5949,8 @@ void game_command_set_ride_price(int *eax, int *ebx, int *ecx, int *edx, int *es
window_invalidate_by_number(WC_RIDE, count);
}
// If the shop item is the same or an on-ride photo
if (ride_type->shop_item_secondary == shop_item ||
(ride_type->shop_item_secondary == 0xFF &&
if (rideEntry->shop_item_secondary == shop_item ||
(rideEntry->shop_item_secondary == 0xFF &&
(shop_item == 0x3 || shop_item == 0x20 || shop_item == 0x21 || shop_item == 0x22))) {
ride->price_secondary = price;
@ -5866,7 +5959,7 @@ void game_command_set_ride_price(int *eax, int *ebx, int *ecx, int *edx, int *es
}
count++;
ride++;
ride_type = gRideTypeList[ride->subtype];
rideEntry = GET_RIDE_ENTRY(ride->subtype);
}
}
}
@ -6884,6 +6977,12 @@ void game_command_set_ride_vehicles(int *eax, int *ebx, int *ecx, int *edx, int
value = (*edx >> 8) & 0xFF;
ride = GET_RIDE(rideIndex);
if (ride->type == RIDE_TYPE_NULL)
{
log_warning("Invalid game command for ride %u", rideIndex);
*ebx = MONEY32_UNDEFINED;
return;
}
RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS * 4;
@ -7225,6 +7324,11 @@ void game_command_place_ride_entrance_or_exit(int *eax, int *ebx, int *ecx, int
money32 remove_ride_entrance_or_exit(sint16 x, sint16 y, uint8 rideIndex, uint8 station_num, uint8 flags){
rct_ride* ride = GET_RIDE(rideIndex);
if (ride->type == RIDE_TYPE_NULL)
{
log_warning("Invalide ride id %u for entrance/exit removal", rideIndex);
return MONEY32_UNDEFINED;
}
if (!(flags & GAME_COMMAND_FLAG_GHOST)){
if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode){
@ -7245,6 +7349,11 @@ money32 remove_ride_entrance_or_exit(sint16 x, sint16 y, uint8 rideIndex, uint8
uint8 found = 0;
rct_map_element* mapElement = map_get_first_element_at(x / 32, y / 32);
if (mapElement == NULL)
{
log_warning("Invalid coordinates for entrance/exit removal x = %d, y = %d", x, y);
return MONEY32_UNDEFINED;
}
do{
if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_ENTRANCE)
continue;

View File

@ -3099,7 +3099,7 @@ int save_track_design(uint8 rideIndex){
return 1;
}
path_set_extension(path, "TD6");
path_append_extension(path, "TD6");
save_track_to_file(RCT2_ADDRESS(0x009D8178, rct_track_td6), path);
@ -3292,6 +3292,14 @@ void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int
rideIndex = _edi & 0xFF;
}
rct_ride* ride = GET_RIDE(rideIndex);
if (ride->type == RIDE_TYPE_NULL)
{
log_warning("Invalid game command for track placement, ride id = %d", rideIndex);
*ebx = MONEY32_UNDEFINED;
return;
}
money32 cost = 0;
if (!(flags & GAME_COMMAND_FLAG_APPLY)){
RCT2_GLOBAL(0x00F44150, uint8) = 0;
@ -3348,7 +3356,6 @@ void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int
if (num_circuits == 0) num_circuits = 1;
game_do_command(0, GAME_COMMAND_FLAG_APPLY | (num_circuits << 8), 0, rideIndex | (9 << 8), GAME_COMMAND_SET_RIDE_SETTING, 0, 0);
rct_ride* ride = GET_RIDE(rideIndex);
ride->lifecycle_flags |= RIDE_LIFECYCLE_NOT_CUSTOM_DESIGN;
@ -4494,6 +4501,11 @@ money32 track_remove(uint8 type, uint8 sequence, sint16 originX, sint16 originY,
uint8 found = 0;
rct_map_element* mapElement = map_get_first_element_at(originX / 32, originY / 32);
if (mapElement == NULL)
{
log_warning("Invalid coordinates for track removal. x = %d, y = %d", originX, originY);
return MONEY32_UNDEFINED;
}
do{
if (mapElement->base_height * 8 != originZ)
continue;
@ -4781,6 +4793,12 @@ void game_command_set_brakes_speed(int *eax, int *ebx, int *ecx, int *edx, int *
}
mapElement = map_get_first_element_at(x >> 5, y >> 5);
if (mapElement == NULL)
{
log_warning("Invalid game command for setting brakes speed. x = %d, y = %d", x, y);
*ebx = MONEY32_UNDEFINED;
return;
}
do {
if (mapElement->base_height * 8 != z)
continue;

View File

@ -45,6 +45,17 @@
#include "world/sprite.h"
#include "world/water.h"
const rct_string_id ScenarioCategoryStringIds[SCENARIO_CATEGORY_COUNT] = {
STR_BEGINNER_PARKS,
STR_CHALLENGING_PARKS,
STR_EXPERT_PARKS,
STR_REAL_PARKS,
STR_OTHER_PARKS,
STR_DLC_PARKS,
STR_BUILD_YOUR_OWN_PARKS,
};
static char _scenarioPath[MAX_PATH];
static const char *_scenarioFileName = "";
@ -58,13 +69,11 @@ static void scenario_objective_check();
* Loads only the basic information from a scenario.
* rct2: 0x006761D6
*/
int scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *info)
bool scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *info)
{
SDL_RWops* rw;
log_verbose("loading scenario details, %s", path);
rw = SDL_RWFromFile(path, "rb");
SDL_RWops* rw = SDL_RWFromFile(path, "rb");
if (rw != NULL) {
// Read first chunk
sawyercoding_read_chunk(rw, (uint8*)header);
@ -72,49 +81,16 @@ int scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *in
// Read second chunk
sawyercoding_read_chunk(rw, (uint8*)info);
SDL_RWclose(rw);
RCT2_GLOBAL(0x009AA00C, uint8) = 0;
// Get filename
utf8 filename[MAX_PATH];
const char *temp_filename = path_get_filename(path);
int len = strnlen(temp_filename, MAX_PATH);
safe_strncpy(filename, temp_filename, MAX_PATH);
if (len == MAX_PATH)
{
filename[MAX_PATH - 1] = '\0';
log_warning("truncated string %s", filename);
}
path_remove_extension(filename);
rct_string_id localisedStringIds[3];
if (language_get_localised_scenario_strings(filename, localisedStringIds)) {
if (localisedStringIds[0] != (rct_string_id)STR_NONE) {
safe_strncpy(info->name, language_get_string(localisedStringIds[0]), 64);
}
if (localisedStringIds[2] != (rct_string_id)STR_NONE) {
safe_strncpy(info->details, language_get_string(localisedStringIds[2]), 256);
}
} else {
// Checks for a scenario string object (possibly for localisation)
if ((info->entry.flags & 0xFF) != 255) {
if (object_get_scenario_text(&info->entry)) {
rct_stex_entry* stex_entry = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TEXT_TEMP_CHUNK, rct_stex_entry*);
format_string(info->name, stex_entry->scenario_name, NULL);
format_string(info->details, stex_entry->details, NULL);
RCT2_GLOBAL(0x009AA00C, uint8) = stex_entry->var_06;
object_free_scenario_text();
}
}
}
return 1;
return true;
} else {
log_error("invalid scenario, %s", path);
SDL_RWclose(rw);
return false;
}
SDL_RWclose(rw);
}
log_error("invalid scenario, %s", path);
// RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, sint8) = -1;
// RCT2_GLOBAL(RCT2_ADDRESS_ERROR_STRING_ID, sint16) = 3011;
return 0;
log_error("unable to open scenario, %s", path);
return false;
}
/**
@ -219,19 +195,6 @@ int scenario_load(const char *path)
return 0;
}
/**
*
* rct2: 0x00678282
* scenario (ebx)
*/
int scenario_load_and_play(const rct_scenario_basic *scenario)
{
char path[MAX_PATH];
substitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char), scenario->path);
return scenario_load_and_play_from_path(path);
}
int scenario_load_and_play_from_path(const char *path)
{
window_close_construction_windows();
@ -316,13 +279,12 @@ void scenario_begin()
safe_strncpy((char*)RCT2_ADDRESS_SCENARIO_NAME, s6Info->name, 64);
{
// Get filename
utf8 filename[MAX_PATH];
safe_strncpy(filename, _scenarioFileName, sizeof(filename));
path_remove_extension(filename);
utf8 normalisedName[64];
safe_strncpy(normalisedName, s6Info->name, sizeof(normalisedName));
scenario_normalise_name(normalisedName);
rct_string_id localisedStringIds[3];
if (language_get_localised_scenario_strings(filename, localisedStringIds)) {
if (language_get_localised_scenario_strings(normalisedName, localisedStringIds)) {
if (localisedStringIds[0] != (rct_string_id)STR_NONE) {
safe_strncpy((char*)RCT2_ADDRESS_SCENARIO_NAME, language_get_string(localisedStringIds[0]), 32);
}
@ -437,29 +399,29 @@ void scenario_failure()
*/
void scenario_success()
{
int i;
rct_scenario_basic* scenario;
uint32 current_val = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_COMPANY_VALUE, uint32);
const money32 companyValue = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_COMPANY_VALUE, money32);
RCT2_GLOBAL(RCT2_ADDRESS_COMPLETED_COMPANY_VALUE, uint32) = current_val;
RCT2_GLOBAL(RCT2_ADDRESS_COMPLETED_COMPANY_VALUE, uint32) = companyValue;
peep_applause();
for (i = 0; i < gScenarioListCount; i++) {
scenario = &gScenarioList[i];
if (strequals(scenario->path, _scenarioFileName, 256, true)) {
// Check if record company value has been broken
if ((scenario->flags & SCENARIO_FLAGS_COMPLETED) && scenario->company_value >= current_val)
break;
scenario_index_entry *scenario = scenario_list_find_by_filename(_scenarioFileName);
if (scenario != NULL) {
// Check if record company value has been broken
if (scenario->highscore == NULL || scenario->highscore->company_value < companyValue) {
if (scenario->highscore == NULL) {
scenario->highscore = scenario_highscore_insert();
} else {
scenario_highscore_free(scenario->highscore);
}
scenario->highscore->fileName = _strdup(path_get_filename(scenario->path));
scenario->highscore->name = NULL;
scenario->highscore->company_value = companyValue;
scenario->highscore->timestamp = platform_get_datetime_now_utc();
// Allow name entry
RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) |= PARK_FLAGS_SCENARIO_COMPLETE_NAME_INPUT;
scenario->company_value = current_val;
scenario->flags |= SCENARIO_FLAGS_COMPLETED;
scenario->completed_by[0] = 0;
RCT2_GLOBAL(0x013587C0, uint32) = current_val;
RCT2_GLOBAL(0x013587C0, money32) = companyValue;
scenario_scores_save();
break;
}
}
scenario_end();
@ -471,21 +433,13 @@ void scenario_success()
*/
void scenario_success_submit_name(const char *name)
{
int i;
rct_scenario_basic* scenario;
uint32 scenarioWinCompanyValue;
for (i = 0; i < gScenarioListCount; i++) {
scenario = &gScenarioList[i];
if (strequals(scenario->path, _scenarioFileName, 256, true)) {
scenarioWinCompanyValue = RCT2_GLOBAL(0x013587C0, uint32);
if (scenario->company_value == scenarioWinCompanyValue) {
safe_strncpy(scenario->completed_by, name, 64);
safe_strncpy((char*)0x013587D8, name, 32);
scenario_scores_save();
}
break;
scenario_index_entry *scenario = scenario_list_find_by_filename(_scenarioFileName);
if (scenario != NULL) {
money32 scenarioWinCompanyValue = RCT2_GLOBAL(0x013587C0, money32);
if (scenario->highscore->company_value == scenarioWinCompanyValue) {
scenario->highscore->name = _strdup(name);
safe_strncpy((char*)0x013587D8, name, 32);
scenario_scores_save();
}
}

View File

@ -72,6 +72,17 @@ typedef struct {
uint32 scenario_count; // 0x0C
} rct_scenario_scores_header;
typedef enum {
SCENARIO_SOURCE_RCT1,
SCENARIO_SOURCE_RCT1_AA,
SCENARIO_SOURCE_RCT1_LL,
SCENARIO_SOURCE_RCT2,
SCENARIO_SOURCE_RCT2_WW,
SCENARIO_SOURCE_RCT2_TT,
SCENARIO_SOURCE_REAL,
SCENARIO_SOURCE_OTHER
} scenario_source;
/**
* Scenario basic structure, mainly for scenario select
* size: 0x02B0
@ -89,6 +100,8 @@ typedef struct {
sint32 flags; // 0x0268
uint32 company_value; // 0x026C
char completed_by[64]; // 0x0270
// uint8 source_game; // new in OpenRCT2
// sint16 source_index; // new in OpenRCT2
} rct_scenario_basic;
typedef struct {
@ -385,11 +398,18 @@ enum {
#define S6_MAGIC_NUMBER 0x00031144
enum {
// RCT2 categories (keep order)
SCENARIO_CATEGORY_BEGINNER,
SCENARIO_CATEGORY_CHALLENGING,
SCENARIO_CATEGORY_EXPERT,
SCENARIO_CATEGORY_REAL,
SCENARIO_CATEGORY_BUILDYOUROWN
SCENARIO_CATEGORY_OTHER,
// OpenRCT2 categories
SCENARIO_CATEGORY_DLC,
SCENARIO_CATEGORY_BUILD_YOUR_OWN,
SCENARIO_CATEGORY_COUNT
};
enum {
@ -407,20 +427,61 @@ enum {
OBJECTIVE_MONTHLY_FOOD_INCOME
};
typedef struct {
utf8 *fileName;
utf8 *name;
money32 company_value;
datetime64 timestamp;
} scenario_highscore_entry;
typedef struct {
utf8 path[MAX_PATH];
uint64 timestamp;
// Category / sequence
uint8 category;
uint8 source_game;
sint16 source_index;
uint16 sc_id;
// Objective
uint8 objective_type;
uint8 objective_arg_1;
sint32 objective_arg_2;
sint16 objective_arg_3;
scenario_highscore_entry *highscore;
utf8 name[64];
utf8 details[256];
} scenario_index_entry;
typedef struct {
const utf8 *title;
uint8 id;
uint8 source;
sint32 index;
uint8 category;
} source_desc;
extern const rct_string_id ScenarioCategoryStringIds[SCENARIO_CATEGORY_COUNT];
// Scenario list
extern int gScenarioListCount;
extern int gScenarioListCapacity;
extern rct_scenario_basic *gScenarioList;
extern scenario_index_entry *gScenarioList;
extern char gScenarioSavePath[MAX_PATH];
extern int gFirstTimeSave;
int scenario_scores_save();
bool scenario_scores_save();
void scenario_load_list();
rct_scenario_basic *get_scenario_by_filename(const char *filename);
int scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *info);
void scenario_list_dispose();
scenario_index_entry *scenario_list_find_by_filename(const utf8 *filename);
scenario_index_entry *scenario_list_find_by_path(const utf8 *path);
scenario_highscore_entry *scenario_highscore_insert();
void scenario_highscore_free(scenario_highscore_entry *highscore);
bool scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *info);
int scenario_load(const char *path);
int scenario_load_and_play(const rct_scenario_basic *scenario);
int scenario_load_and_play_from_path(const char *path);
void scenario_begin();
void scenario_update();
@ -436,4 +497,114 @@ void scenario_success();
void scenario_success_submit_name(const char *name);
void scenario_autosave_check();
bool scenario_get_source_desc(const utf8 *name, source_desc *outDesc);
bool scenario_get_source_desc_by_id(uint8 id, source_desc *outDesc);
void scenario_normalise_name(utf8 *name);
// RCT1 scenario index map
enum {
SC_UNIDENTIFIED = 255,
// RCT
SC_FOREST_FRONTIERS = 0,
SC_DYNAMITE_DUNES,
SC_LEAFY_LAKES,
SC_DIAMOND_HEIGHTS,
SC_EVERGREEN_GARDENS,
SC_BUMBLY_BEACH,
SC_TRINITY_ISLANDS,
SC_KATIES_DREAMLAND,
SC_POKEY_PARK,
SC_WHITE_WATER_PARK,
SC_MILLENNIUM_MINES,
SC_KARTS_COASTERS,
SC_MELS_WORLD,
SC_MYSTIC_MOUNTAIN,
SC_PACIFIC_PYRAMIDS,
SC_CRUMBLY_WOODS,
SC_PARADISE_PIER,
SC_LIGHTNING_PEAKS,
SC_IVORY_TOWERS,
SC_RAINBOW_VALLEY,
SC_THUNDER_ROCK,
SC_MEGA_PARK,
// Loopy Landscapes
SC_ICEBERG_ISLANDS,
SC_VOLCANIA,
SC_ARID_HEIGHTS,
SC_RAZOR_ROCKS,
SC_CRATER_LAKE,
SC_VERTIGO_VIEWS,
SC_PARADISE_PIER_2,
SC_DRAGONS_COVE,
SC_GOOD_KNIGHT_PARK,
SC_WACKY_WARREN,
// Special
ALTON_TOWERS,
FORT_ANACHRONISM,
// Added Attractions
SC_WHISPERING_CLIFFS = 40,
SC_THREE_MONKEYS_PARK,
SC_CANARY_MINES,
SC_BARONY_BRIDGE,
SC_FUNTOPIA,
SC_HAUNTED_HARBOR,
SC_FUN_FORTRESS,
SC_FUTURE_WORLD,
SC_GENTLE_GLEN,
SC_JOLLY_JUNGLE,
SC_HYDRO_HILLS,
SC_SPRIGHTLY_PARK,
SC_MAGIC_QUARTERS,
SC_FRUIT_FARM,
SC_BUTTERFLY_DAM,
SC_COASTER_CANYON,
SC_THUNDERSTORM_PARK,
SC_HARMONIC_HILLS,
SC_ROMAN_VILLAGE,
SC_SWAMP_COVE,
SC_ADRENALINE_HEIGHTS,
SC_UTOPIA,
SC_ROTTING_HEIGHTS,
SC_FIASCO_FOREST,
SC_PICKLE_PARK,
SC_GIGGLE_DOWNS,
SC_MINERAL_PARK,
SC_COASTER_CRAZY,
SC_URBAN_PARK,
SC_GEOFFREY_GARDENS,
// Special
SC_HEIDE_PARK,
SC_PCPLAYER,
SC_PCGW,
SC_GAMEPLAY,
SC_BLACKPOOL_PLEASURE_BEACH,
// Loopy Landscapes
SC_GRAND_GLACIER = 80,
SC_CRAZY_CRATERS,
SC_DUSTY_DESERT,
SC_WOODWORM_PARK,
SC_ICARUS_PARK,
SC_SUNNY_SWAMPS,
SC_FRIGHTMARE_HILLS,
SC_THUNDER_ROCKS,
SC_OCTAGON_PARK,
SC_PLEASURE_ISLAND,
SC_ICICLE_WORLDS,
SC_SOUTHERN_SANDS,
SC_TINY_TOWERS,
SC_NEVERMORE_PARK,
SC_PACIFICA,
SC_URBAN_JUNGLE,
SC_TERROR_TOWN,
SC_MEGAWORLD_PARK,
SC_VENUS_PONDS,
SC_MICRO_PARK,
};
#endif

View File

@ -19,228 +19,535 @@
*****************************************************************************/
#include "addresses.h"
#include "config.h"
#include "localisation/localisation.h"
#include "platform/platform.h"
#include "util/util.h"
#include "scenario.h"
#include "util/util.h"
// Scenario list
int gScenarioListCount = 0;
int gScenarioListCapacity = 0;
rct_scenario_basic *gScenarioList = NULL;
scenario_index_entry *gScenarioList = NULL;
static void scenario_list_add(const char *path);
int gScenarioHighscoreListCount = 0;
int gScenarioHighscoreListCapacity = 0;
scenario_highscore_entry *gScenarioHighscoreList = NULL;
static void scenario_list_include(const utf8 *directory);
static void scenario_list_add(const utf8 *path, uint64 timestamp);
static void scenario_list_sort();
static int scenario_list_sort_compare(const void *a, const void *b);
static int scenario_scores_load();
static int scenario_list_sort_by_category(const void *a, const void *b);
static int scenario_list_sort_by_index(const void *a, const void *b);
static void scenario_translate(scenario_index_entry *scenarioEntry, const rct_object_entry *stexObjectEntry);
rct_scenario_basic *get_scenario_by_filename(const char *filename)
{
int i;
for (i = 0; i < gScenarioListCount; i++)
if (strcmp(gScenarioList[i].path, filename) == 0)
return &gScenarioList[i];
return NULL;
}
static bool scenario_scores_load();
static void scenario_scores_legacy_get_path(utf8 *outPath);
static bool scenario_scores_legacy_load(const utf8 *path);
static void scenario_highscore_remove(scenario_highscore_entry *higscore);
static void scenario_highscore_list_dispose();
static utf8 *io_read_string(SDL_RWops *file);
static void io_write_string(SDL_RWops *file, utf8 *source);
/**
*
* rct2: 0x006775A8
* Searches and grabs the metadata for all the scenarios.
*/
void scenario_load_list()
{
int i, enumFileHandle;
file_info enumFileInfo;
utf8 directory[MAX_PATH];
// Load scores
// Clear scenario list
gScenarioListCount = 0;
// Get scenario directory from RCT2
safe_strncpy(directory, gConfigGeneral.game_path, sizeof(directory));
safe_strcat_path(directory, "Scenarios", sizeof(directory));
scenario_list_include(directory);
// Get scenario directory from user directory
platform_get_user_directory(directory, "scenario");
scenario_list_include(directory);
scenario_list_sort();
scenario_scores_load();
// Set all scenarios to be invisible
for (i = 0; i < gScenarioListCount; i++)
gScenarioList[i].flags &= ~SCENARIO_FLAGS_VISIBLE;
// Enumerate through each scenario in the directory
enumFileHandle = platform_enumerate_files_begin(RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char));
if (enumFileHandle != INVALID_HANDLE) {
while (platform_enumerate_files_next(enumFileHandle, &enumFileInfo)) {
scenario_list_add(enumFileInfo.path);
}
platform_enumerate_files_end(enumFileHandle);
}
// Sort alphabetically
scenario_list_sort();
// Save the scores
scenario_scores_save();
utf8 scoresPath[MAX_PATH];
scenario_scores_legacy_get_path(scoresPath);
scenario_scores_legacy_load(scoresPath);
scenario_scores_legacy_load(get_file_path(PATH_ID_SCORES));
}
static void scenario_list_add(const char *path)
static void scenario_list_include(const utf8 *directory)
{
char scenarioPath[MAX_PATH];
rct_scenario_basic *scenario;
int handle;
file_info fileInfo;
// Scenarios in this directory
utf8 pattern[MAX_PATH];
safe_strncpy(pattern, directory, sizeof(pattern));
safe_strcat_path(pattern, "*.sc6", sizeof(pattern));
handle = platform_enumerate_files_begin(pattern);
while (platform_enumerate_files_next(handle, &fileInfo)) {
utf8 path[MAX_PATH];
safe_strncpy(path, directory, sizeof(pattern));
safe_strcat_path(path, fileInfo.path, sizeof(pattern));
scenario_list_add(path, fileInfo.last_modified);
}
platform_enumerate_files_end(handle);
// Include sub-directories
utf8 subDirectory[MAX_PATH];
handle = platform_enumerate_directories_begin(directory);
while (platform_enumerate_directories_next(handle, subDirectory)) {
utf8 path[MAX_PATH];
safe_strncpy(path, directory, sizeof(pattern));
safe_strcat_path(path, subDirectory, sizeof(pattern));
scenario_list_include(path);
}
platform_enumerate_directories_end(handle);
}
static void scenario_list_add(const utf8 *path, uint64 timestamp)
{
// Load the basic scenario information
rct_s6_header s6Header;
rct_s6_info s6Info;
// Get absolute path
substitute_path(scenarioPath, RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char), path);
// Load the basic scenario information
if (!scenario_load_basic(scenarioPath, &s6Header, &s6Info))
if (!scenario_load_basic(path, &s6Header, &s6Info)) {
return;
}
// Ignore scenarios where first header byte is not 255
if (s6Info.editor_step != 255)
return;
scenario_index_entry *newEntry = NULL;
// Check if scenario already exists in list, likely if in scores
scenario = get_scenario_by_filename(path);
if (scenario != NULL) {
// Update the scenario information
scenario->flags |= SCENARIO_FLAGS_VISIBLE;
scenario->category = s6Info.category;
scenario->objective_type = s6Info.objective_type;
scenario->objective_arg_1 = s6Info.objective_arg_1;
scenario->objective_arg_2 = s6Info.objective_arg_2;
scenario->objective_arg_3 = s6Info.objective_arg_3;
safe_strncpy(scenario->name, s6Info.name, 64);
safe_strncpy(scenario->details, s6Info.details, 256);
} else {
// Check if the scenario list buffer has room for another scenario
if (gScenarioListCount >= gScenarioListCapacity) {
// Allocate more room
gScenarioListCapacity += 16;
gScenarioList = realloc(gScenarioList, gScenarioListCapacity * sizeof(rct_scenario_basic));
const utf8 *filename = path_get_filename(path);
scenario_index_entry *existingEntry = scenario_list_find_by_filename(filename);
if (existingEntry != NULL) {
bool bail = false;
const utf8 *conflictPath;
if (existingEntry->timestamp > timestamp) {
// Existing entry is more recent
conflictPath = existingEntry->path;
// Overwrite existing entry with this one
newEntry = existingEntry;
} else {
// This entry is more recent
conflictPath = path;
bail = true;
}
printf("Scenario conflict: '%s' ignored because it is newer.\n", conflictPath);
if (bail) {
return;
}
}
// Increment the number of scenarios
scenario = &gScenarioList[gScenarioListCount];
if (newEntry == NULL) {
// Increase list size
if (gScenarioListCount == gScenarioListCapacity) {
gScenarioListCapacity = max(8, gScenarioListCapacity * 2);
gScenarioList = (scenario_index_entry*)realloc(gScenarioList, gScenarioListCapacity * sizeof(scenario_index_entry));
}
newEntry = &gScenarioList[gScenarioListCount];
gScenarioListCount++;
}
// Add this new scenario to the list
safe_strncpy(scenario->path, path, 256);
scenario->flags = SCENARIO_FLAGS_VISIBLE;
if (RCT2_GLOBAL(0x009AA00C, uint8) & 1)
scenario->flags |= SCENARIO_FLAGS_SIXFLAGS;
scenario->category = s6Info.category;
scenario->objective_type = s6Info.objective_type;
scenario->objective_arg_1 = s6Info.objective_arg_1;
scenario->objective_arg_2 = s6Info.objective_arg_2;
scenario->objective_arg_3 = s6Info.objective_arg_3;
safe_strncpy(scenario->name, s6Info.name, 64);
safe_strncpy(scenario->details, s6Info.details, 256);
// Set new entry
safe_strncpy(newEntry->path, path, sizeof(newEntry->path));
newEntry->timestamp = timestamp;
newEntry->category = s6Info.category;
newEntry->objective_type = s6Info.objective_type;
newEntry->objective_arg_1 = s6Info.objective_arg_1;
newEntry->objective_arg_2 = s6Info.objective_arg_2;
newEntry->objective_arg_3 = s6Info.objective_arg_3;
newEntry->highscore = NULL;
safe_strncpy(newEntry->name, s6Info.name, sizeof(newEntry->name));
safe_strncpy(newEntry->details, s6Info.details, sizeof(newEntry->details));
// Normalise the name to make the scenario as recognisable as possible.
scenario_normalise_name(newEntry->name);
// Look up and store information regarding the origins of this scenario.
source_desc desc;
if (scenario_get_source_desc(newEntry->name, &desc)) {
newEntry->sc_id = desc.id;
newEntry->source_index = desc.index;
newEntry->source_game = desc.source;
newEntry->category = desc.category;
} else {
newEntry->sc_id = SC_UNIDENTIFIED;
newEntry->source_index = -1;
if (newEntry->category == SCENARIO_CATEGORY_REAL) {
newEntry->source_game = SCENARIO_SOURCE_REAL;
} else {
newEntry->source_game = SCENARIO_SOURCE_OTHER;
}
}
scenario_translate(newEntry, &s6Info.entry);
}
static void scenario_translate(scenario_index_entry *scenarioEntry, const rct_object_entry *stexObjectEntry)
{
rct_string_id localisedStringIds[3];
if (language_get_localised_scenario_strings(scenarioEntry->name, localisedStringIds)) {
if (localisedStringIds[0] != (rct_string_id)STR_NONE) {
safe_strncpy(scenarioEntry->name, language_get_string(localisedStringIds[0]), 64);
}
if (localisedStringIds[2] != (rct_string_id)STR_NONE) {
safe_strncpy(scenarioEntry->details, language_get_string(localisedStringIds[2]), 256);
}
} else {
// Checks for a scenario string object (possibly for localisation)
if ((stexObjectEntry->flags & 0xFF) != 255) {
if (object_get_scenario_text((rct_object_entry*)stexObjectEntry)) {
rct_stex_entry* stex_entry = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TEXT_TEMP_CHUNK, rct_stex_entry*);
format_string(scenarioEntry->name, stex_entry->scenario_name, NULL);
format_string(scenarioEntry->details, stex_entry->details, NULL);
object_free_scenario_text();
}
}
}
}
/**
* Sort the list of scenarios. This used to be an insertion sort which took
* place as each scenario loaded. It has now been changed to a quicksort which
* takes place after all the scenarios have been loaded in.
* rct2: 0x00677C3B
*/
static void scenario_list_sort()
void scenario_list_dispose()
{
qsort(gScenarioList, gScenarioListCount, sizeof(rct_scenario_basic), scenario_list_sort_compare);
gScenarioListCapacity = 0;
gScenarioListCount = 0;
SafeFree(gScenarioList);
}
/**
* Basic scenario information compare function for sorting.
* rct2: 0x00677C08
*/
static int scenario_list_sort_compare(const void *a, const void *b)
static void scenario_list_sort()
{
return strcmp(((rct_scenario_basic*)a)->name, ((rct_scenario_basic*)b)->name);
int(*compareFunc)(void const*, void const*);
compareFunc = gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN ?
scenario_list_sort_by_index :
scenario_list_sort_by_category;
qsort(gScenarioList, gScenarioListCount, sizeof(scenario_index_entry), compareFunc);
}
static int scenario_list_category_compare(int categoryA, int categoryB)
{
if (categoryA == categoryB) return 0;
if (categoryA == SCENARIO_CATEGORY_DLC) return -1;
if (categoryB == SCENARIO_CATEGORY_DLC) return 1;
if (categoryA == SCENARIO_CATEGORY_BUILD_YOUR_OWN) return -1;
if (categoryB == SCENARIO_CATEGORY_BUILD_YOUR_OWN) return 1;
return sgn(categoryA - categoryB);
}
static int scenario_list_sort_by_category(const void *a, const void *b)
{
const scenario_index_entry *entryA = (const scenario_index_entry*)a;
const scenario_index_entry *entryB = (const scenario_index_entry*)b;
// Order by category
if (entryA->category != entryB->category) {
return scenario_list_category_compare(entryA->category, entryB->category);
}
// Then by source game / name
switch (entryA->category) {
default:
if (entryA->source_game != entryB->source_game) {
return entryA->source_game - entryB->source_game;
}
return strcmp(entryA->name, entryB->name);
case SCENARIO_CATEGORY_REAL:
case SCENARIO_CATEGORY_OTHER:
return strcmp(entryA->name, entryB->name);
}
}
static int scenario_list_sort_by_index(const void *a, const void *b)
{
const scenario_index_entry *entryA = (const scenario_index_entry*)a;
const scenario_index_entry *entryB = (const scenario_index_entry*)b;
// Order by source game
if (entryA->source_game != entryB->source_game) {
return entryA->source_game - entryB->source_game;
}
// Then by index / category / name
uint8 sourceGame = entryA->source_game;
switch (sourceGame) {
default:
if (entryA->source_index == -1 && entryB->source_index == -1) {
if (entryA->category == entryB->category) {
return scenario_list_sort_by_category(a, b);
} else {
return scenario_list_category_compare(entryA->category, entryB->category);
}
} else if (entryA->source_index == -1) {
return 1;
} else if (entryB->source_index == -1) {
return -1;
} else {
return entryA->source_index - entryB->source_index;
}
case SCENARIO_SOURCE_REAL:
return scenario_list_sort_by_category(a, b);
}
}
scenario_index_entry *scenario_list_find_by_filename(const utf8 *filename)
{
for (int i = 0; i < gScenarioListCount; i++) {
const utf8 *scenarioFilename = path_get_filename(gScenarioList[i].path);
if (_strcmpi(filename, scenarioFilename) == 0) {
return &gScenarioList[i];
}
}
return NULL;
}
scenario_index_entry *scenario_list_find_by_path(const utf8 *path)
{
for (int i = 0; i < gScenarioListCount; i++) {
if (_strcmpi(path, gScenarioList[i].path) == 0) {
return &gScenarioList[i];
}
}
return NULL;
}
/**
* Gets the path for the scenario scores path.
*/
static void scenario_scores_get_path(utf8 *outPath)
{
platform_get_user_directory(outPath, NULL);
strcat(outPath, "highscores.dat");
}
/**
* Gets the path for the scenario scores path.
*/
static void scenario_scores_legacy_get_path(utf8 *outPath)
{
platform_get_user_directory(outPath, NULL);
strcat(outPath, "scores.dat");
}
/**
*
* rct2: 0x006775A8
* Loads the original scores.dat file and replaces any highscores that
* are better for matching scenarios.
*/
static int scenario_scores_load()
static bool scenario_scores_legacy_load(const utf8 *path)
{
SDL_RWops *file;
char scoresPath[MAX_PATH];
scenario_scores_get_path(scoresPath);
// Free scenario list if already allocated
if (gScenarioList != NULL) {
free(gScenarioList);
gScenarioList = NULL;
}
// Try and load the scores file
// First check user folder and then fallback to install directory
file = SDL_RWFromFile(scoresPath, "rb");
SDL_RWops *file = SDL_RWFromFile(path, "rb");
if (file == NULL) {
file = SDL_RWFromFile(get_file_path(PATH_ID_SCORES), "rb");
if (file == NULL) {
log_error("Unable to load scenario scores.");
return 0;
}
return false;
}
// Load header
rct_scenario_scores_header header;
if (SDL_RWread(file, &header, 16, 1) != 1) {
SDL_RWclose(file);
log_error("Invalid header in scenario scores file.");
return 0;
}
gScenarioListCount = header.scenario_count;
// Load scenario information with scores
int scenarioListBufferSize = gScenarioListCount * sizeof(rct_scenario_basic);
gScenarioListCapacity = gScenarioListCount;
gScenarioList = malloc(scenarioListBufferSize);
if (SDL_RWread(file, gScenarioList, scenarioListBufferSize, 1) == 1) {
SDL_RWclose(file);
return 1;
log_error("Invalid header in legacy scenario scores file.");
return false;
}
// Unable to load scores, free scenario list
// Read scenarios
bool highscoresDirty = false;
for (uint32 i = 0; i < header.scenario_count; i++) {
// Read legacy entry
rct_scenario_basic scBasic;
if (SDL_RWread(file, &scBasic, sizeof(rct_scenario_basic), 1) != 1) {
break;
}
// Ignore non-completed scenarios
if (!(scBasic.flags & SCENARIO_FLAGS_COMPLETED)) {
continue;
}
// Find matching scenario entry
scenario_index_entry *scenarioIndexEntry = scenario_list_find_by_filename(scBasic.path);
if (scenarioIndexEntry != NULL) {
// Check if legacy highscore is better
scenario_highscore_entry *highscore = scenarioIndexEntry->highscore;
if (highscore == NULL) {
highscore = scenario_highscore_insert();
scenarioIndexEntry->highscore = highscore;
} else if (highscore->company_value < (money32)scBasic.company_value) {
scenario_highscore_free(highscore);
// Re-use highscore entry
} else {
highscore = NULL;
}
// Set new highscore
if (highscore != NULL) {
highscore->fileName = _strdup(scBasic.path);
highscore->name = _strdup(scBasic.completed_by);
highscore->company_value = (money32)scBasic.company_value;
highscore->timestamp = DATETIME64_MIN;
highscoresDirty = true;
}
// Exit loop
break;
}
}
SDL_RWclose(file);
gScenarioListCount = 0;
gScenarioListCapacity = 0;
free(gScenarioList);
gScenarioList = NULL;
return 0;
if (highscoresDirty) {
scenario_scores_save();
}
return true;
}
static bool scenario_scores_load()
{
utf8 scoresPath[MAX_PATH];
scenario_scores_get_path(scoresPath);
// Load scores file
SDL_RWops *file = SDL_RWFromFile(scoresPath, "rb");
if (file == NULL) {
return false;
}
// Check file version
uint32 fileVersion;
SDL_RWread(file, &fileVersion, sizeof(fileVersion), 1);
if (fileVersion != 1) {
log_error("Invalid or incompatible highscores file.");
return false;
}
// Read and allocate the highscore list
scenario_highscore_list_dispose();
SDL_RWread(file, &gScenarioHighscoreListCount, sizeof(gScenarioHighscoreListCount), 1);
gScenarioHighscoreListCapacity = gScenarioHighscoreListCount;
gScenarioHighscoreList = malloc(gScenarioHighscoreListCapacity * sizeof(scenario_highscore_entry));
// Read highscores
for (int i = 0; i < gScenarioHighscoreListCount; i++) {
scenario_highscore_entry *highscore = &gScenarioHighscoreList[i];
highscore->fileName = io_read_string(file);
highscore->name = io_read_string(file);
SDL_RWread(file, &highscore->company_value, sizeof(highscore->company_value), 1);
SDL_RWread(file, &highscore->timestamp, sizeof(highscore->timestamp), 1);
// Attach highscore to correct scenario entry
scenario_index_entry *scenarioIndexEntry = scenario_list_find_by_filename(highscore->fileName);
if (scenarioIndexEntry != NULL) {
scenarioIndexEntry->highscore = highscore;
}
}
SDL_RWclose(file);
return true;
}
/**
*
* rct2: 0x00677B50
*/
int scenario_scores_save()
bool scenario_scores_save()
{
SDL_RWops *file;
utf8 scoresPath[MAX_PATH];
scenario_scores_get_path(scoresPath);
file = SDL_RWFromFile(scoresPath, "wb");
SDL_RWops *file = SDL_RWFromFile(scoresPath, "wb");
if (file == NULL) {
log_error("Unable to save scenario scores.");
return 0;
return false;
}
rct_scenario_scores_header header;
header.scenario_count = gScenarioListCount;
SDL_RWwrite(file, &header, sizeof(header), 1);
if (gScenarioListCount > 0)
SDL_RWwrite(file, gScenarioList, gScenarioListCount * sizeof(rct_scenario_basic), 1);
const uint32 fileVersion = 1;
SDL_RWwrite(file, &fileVersion, sizeof(fileVersion), 1);
SDL_RWwrite(file, &gScenarioHighscoreListCount, sizeof(gScenarioHighscoreListCount), 1);
for (int i = 0; i < gScenarioHighscoreListCount; i++) {
scenario_highscore_entry *highscore = &gScenarioHighscoreList[i];
io_write_string(file, highscore->fileName);
io_write_string(file, highscore->name);
SDL_RWwrite(file, &highscore->company_value, sizeof(highscore->company_value), 1);
SDL_RWwrite(file, &highscore->timestamp, sizeof(highscore->timestamp), 1);
}
SDL_RWclose(file);
return 1;
return true;
}
scenario_highscore_entry *scenario_highscore_insert()
{
if (gScenarioHighscoreListCount >= gScenarioHighscoreListCapacity) {
gScenarioHighscoreListCapacity = max(8, gScenarioHighscoreListCapacity * 2);
gScenarioHighscoreList = realloc(gScenarioHighscoreList, gScenarioHighscoreListCapacity * sizeof(scenario_highscore_entry));
}
return &gScenarioHighscoreList[gScenarioHighscoreListCount++];
}
static void scenario_highscore_remove(scenario_highscore_entry *highscore)
{
for (int i = 0; i < gScenarioHighscoreListCount; i++) {
if (&gScenarioHighscoreList[i] == highscore) {
size_t moveSize = (gScenarioHighscoreListCount - i - 1) * sizeof(scenario_highscore_entry);
if (moveSize > 0) {
memmove(&gScenarioHighscoreList[i], &gScenarioHighscoreList[i + 1], moveSize);
}
return;
}
}
}
void scenario_highscore_free(scenario_highscore_entry *highscore)
{
SafeFree(highscore->fileName);
SafeFree(highscore->name);
}
static void scenario_highscore_list_dispose()
{
for (int i = 0; i < gScenarioHighscoreListCount; i++) {
scenario_highscore_free(&gScenarioHighscoreList[i]);
}
gScenarioHighscoreListCapacity = 0;
gScenarioHighscoreListCount = 0;
SafeFree(gScenarioHighscoreList);
}
static utf8 *io_read_string(SDL_RWops *file)
{
size_t bufferCount = 0;
size_t bufferCapacity = 0;
utf8 *buffer = NULL;
utf8 ch;
do {
SDL_RWread(file, &ch, sizeof(ch), 1);
if (ch == '\0' && buffer == NULL) {
break;
}
if (bufferCount >= bufferCapacity) {
bufferCapacity = max(32, bufferCapacity * 2);
buffer = realloc(buffer, bufferCapacity * sizeof(uint8));
}
buffer[bufferCount] = ch;
bufferCount++;
} while (ch != '\0');
if (bufferCount < bufferCapacity) {
buffer = realloc(buffer, bufferCount);
}
return buffer;
}
static void io_write_string(SDL_RWops *file, utf8 *source)
{
if (source == NULL) {
utf8 empty = 0;
SDL_RWwrite(file, &empty, sizeof(utf8), 1);
} else {
SDL_RWwrite(file, source, strlen(source) + 1, 1);
}
}

306
src/scenario_sources.c Normal file
View File

@ -0,0 +1,306 @@
#include "scenario.h"
#include "util/util.h"
typedef struct {
const utf8 *original;
const utf8 *alternative;
} scenario_alias;
const scenario_alias ScenarioAliases[] = {
// UK - US differences:
{ "Katie's Dreamland", "Katie's World" },
{ "Pokey Park", "Dinky Park" },
{ "White Water Park", "Aqua Park" },
{ "Mystic Mountain", "Mothball Mountain" },
{ "Paradise Pier", "Big Pier" },
{ "Paradise Pier 2", "Big Pier 2" },
{ "Mythological - Cradle of Civilisation", "Mythological - Cradle of Civilization" },
// RCT1 pack by RCTScenarioLover has a mistake:
{ "Geoffrey Gardens", "Geoffery Gardens" },
};
typedef struct {
const uint8 id;
const utf8 *title;
const uint8 category;
} scenario_title_desc;
// RCT
const scenario_title_desc ScenarioTitlesRCT1[] = {
{ SC_FOREST_FRONTIERS, "Forest Frontiers", SCENARIO_CATEGORY_BEGINNER },
{ SC_DYNAMITE_DUNES, "Dynamite Dunes", SCENARIO_CATEGORY_BEGINNER },
{ SC_LEAFY_LAKES, "Leafy Lake", SCENARIO_CATEGORY_BEGINNER },
{ SC_DIAMOND_HEIGHTS, "Diamond Heights", SCENARIO_CATEGORY_BEGINNER },
{ SC_EVERGREEN_GARDENS, "Evergreen Gardens", SCENARIO_CATEGORY_BEGINNER },
{ SC_BUMBLY_BEACH, "Bumbly Beach", SCENARIO_CATEGORY_BEGINNER },
{ SC_TRINITY_ISLANDS, "Trinity Islands", SCENARIO_CATEGORY_CHALLENGING },
{ SC_KATIES_DREAMLAND, "Katie's Dreamland", SCENARIO_CATEGORY_CHALLENGING },
{ SC_POKEY_PARK, "Pokey Park", SCENARIO_CATEGORY_CHALLENGING },
{ SC_WHITE_WATER_PARK, "White Water Park", SCENARIO_CATEGORY_CHALLENGING },
{ SC_MILLENNIUM_MINES, "Millennium Mines", SCENARIO_CATEGORY_CHALLENGING },
{ SC_KARTS_COASTERS, "Karts & Coasters", SCENARIO_CATEGORY_CHALLENGING },
{ SC_MELS_WORLD, "Mel's World", SCENARIO_CATEGORY_CHALLENGING },
{ SC_MYSTIC_MOUNTAIN, "Mystic Mountain", SCENARIO_CATEGORY_CHALLENGING },
{ SC_PACIFIC_PYRAMIDS, "Pacific Pyramids", SCENARIO_CATEGORY_CHALLENGING },
{ SC_CRUMBLY_WOODS, "Crumbly Woods", SCENARIO_CATEGORY_CHALLENGING },
{ SC_PARADISE_PIER, "Paradise Pier", SCENARIO_CATEGORY_CHALLENGING },
{ SC_LIGHTNING_PEAKS, "Lightning Peaks", SCENARIO_CATEGORY_EXPERT },
{ SC_IVORY_TOWERS, "Ivory Towers", SCENARIO_CATEGORY_EXPERT },
{ SC_RAINBOW_VALLEY, "Rainbow Valley", SCENARIO_CATEGORY_EXPERT },
{ SC_THUNDER_ROCK, "Thunder Rock", SCENARIO_CATEGORY_EXPERT },
{ SC_MEGA_PARK, "Mega Park", SCENARIO_CATEGORY_OTHER },
};
// RCT: Added Attractions
const scenario_title_desc ScenarioTitlesRCT1AA[] = {
{ SC_WHISPERING_CLIFFS, "Whispering Cliffs", SCENARIO_CATEGORY_BEGINNER },
{ SC_THREE_MONKEYS_PARK, "Three Monkeys Park", SCENARIO_CATEGORY_BEGINNER },
{ SC_CANARY_MINES, "Canary Mines", SCENARIO_CATEGORY_BEGINNER },
{ SC_BARONY_BRIDGE, "Barony Bridge", SCENARIO_CATEGORY_BEGINNER },
{ SC_FUNTOPIA, "Funtopia", SCENARIO_CATEGORY_BEGINNER },
{ SC_HAUNTED_HARBOR, "Haunted Harbor", SCENARIO_CATEGORY_BEGINNER },
{ SC_FUN_FORTRESS, "Fun Fortress", SCENARIO_CATEGORY_BEGINNER },
{ SC_FUTURE_WORLD, "Future World", SCENARIO_CATEGORY_BEGINNER },
{ SC_GENTLE_GLEN, "Gentle Glen", SCENARIO_CATEGORY_BEGINNER },
{ SC_JOLLY_JUNGLE, "Jolly Jungle", SCENARIO_CATEGORY_CHALLENGING },
{ SC_HYDRO_HILLS, "Hydro Hills", SCENARIO_CATEGORY_CHALLENGING },
{ SC_SPRIGHTLY_PARK, "Sprightly Park", SCENARIO_CATEGORY_CHALLENGING },
{ SC_MAGIC_QUARTERS, "Magic Quarters", SCENARIO_CATEGORY_CHALLENGING },
{ SC_FRUIT_FARM, "Fruit Farm", SCENARIO_CATEGORY_CHALLENGING },
{ SC_BUTTERFLY_DAM, "Butterfly Dam", SCENARIO_CATEGORY_CHALLENGING },
{ SC_COASTER_CANYON, "Coaster Canyon", SCENARIO_CATEGORY_CHALLENGING },
{ SC_THUNDERSTORM_PARK, "Thunderstorm Park", SCENARIO_CATEGORY_CHALLENGING },
{ SC_HARMONIC_HILLS, "Harmonic Hills", SCENARIO_CATEGORY_CHALLENGING },
{ SC_ROMAN_VILLAGE, "Roman Village", SCENARIO_CATEGORY_CHALLENGING },
{ SC_SWAMP_COVE, "Swamp Cove", SCENARIO_CATEGORY_CHALLENGING },
{ SC_ADRENALINE_HEIGHTS, "Adrenaline Heights", SCENARIO_CATEGORY_CHALLENGING },
{ SC_UTOPIA, "Utopia", SCENARIO_CATEGORY_CHALLENGING },
{ SC_ROTTING_HEIGHTS, "Rotting Heights", SCENARIO_CATEGORY_EXPERT },
{ SC_FIASCO_FOREST, "Fiasco Forest", SCENARIO_CATEGORY_EXPERT },
{ SC_PICKLE_PARK, "Pickle Park", SCENARIO_CATEGORY_EXPERT },
{ SC_GIGGLE_DOWNS, "Giggle Downs", SCENARIO_CATEGORY_EXPERT },
{ SC_MINERAL_PARK, "Mineral Park", SCENARIO_CATEGORY_EXPERT },
{ SC_COASTER_CRAZY, "Coaster Crazy", SCENARIO_CATEGORY_EXPERT },
{ SC_URBAN_PARK, "Urban Park", SCENARIO_CATEGORY_EXPERT },
{ SC_GEOFFREY_GARDENS, "Geoffrey Gardens", SCENARIO_CATEGORY_EXPERT },
};
// RCT: Loopy Landscapes
const scenario_title_desc ScenarioTitlesRCT1LL[] = {
{ SC_ICEBERG_ISLANDS, "Iceberg Islands", SCENARIO_CATEGORY_BEGINNER },
{ SC_VOLCANIA, "Volcania", SCENARIO_CATEGORY_BEGINNER },
{ SC_ARID_HEIGHTS, "Arid Heights", SCENARIO_CATEGORY_BEGINNER },
{ SC_RAZOR_ROCKS, "Razor Rocks", SCENARIO_CATEGORY_BEGINNER },
{ SC_CRATER_LAKE, "Crater Lake", SCENARIO_CATEGORY_BEGINNER },
{ SC_VERTIGO_VIEWS, "Vertigo Views", SCENARIO_CATEGORY_BEGINNER },
{ SC_PARADISE_PIER_2, "Paradise Pier 2", SCENARIO_CATEGORY_CHALLENGING },
{ SC_DRAGONS_COVE, "Dragon's Cove", SCENARIO_CATEGORY_CHALLENGING },
{ SC_GOOD_KNIGHT_PARK, "Good Knight Park", SCENARIO_CATEGORY_CHALLENGING },
{ SC_WACKY_WARREN, "Wacky Warren", SCENARIO_CATEGORY_CHALLENGING },
{ SC_GRAND_GLACIER, "Grand Glacier", SCENARIO_CATEGORY_CHALLENGING },
{ SC_CRAZY_CRATERS, "Crazy Craters", SCENARIO_CATEGORY_CHALLENGING },
{ SC_DUSTY_DESERT, "Dusty Desert", SCENARIO_CATEGORY_CHALLENGING },
{ SC_WOODWORM_PARK, "Woodworm Park", SCENARIO_CATEGORY_CHALLENGING },
{ SC_ICARUS_PARK, "Icarus Park", SCENARIO_CATEGORY_CHALLENGING },
{ SC_SUNNY_SWAMPS, "Sunny Swamps", SCENARIO_CATEGORY_CHALLENGING },
{ SC_FRIGHTMARE_HILLS, "Frightmare Hills", SCENARIO_CATEGORY_CHALLENGING },
{ SC_THUNDER_ROCKS, "Thunder Rocks", SCENARIO_CATEGORY_CHALLENGING },
{ SC_OCTAGON_PARK, "Octagon Park", SCENARIO_CATEGORY_CHALLENGING },
{ SC_PLEASURE_ISLAND, "Pleasure Island", SCENARIO_CATEGORY_CHALLENGING },
{ SC_ICICLE_WORLDS, "Icicle Worlds", SCENARIO_CATEGORY_CHALLENGING },
{ SC_SOUTHERN_SANDS, "Southern Sands", SCENARIO_CATEGORY_CHALLENGING },
{ SC_TINY_TOWERS, "Tiny Towers", SCENARIO_CATEGORY_CHALLENGING },
{ SC_NEVERMORE_PARK, "Nevermore Park", SCENARIO_CATEGORY_CHALLENGING },
{ SC_PACIFICA, "Pacifica", SCENARIO_CATEGORY_CHALLENGING },
{ SC_URBAN_JUNGLE, "Urban Jungle", SCENARIO_CATEGORY_EXPERT },
{ SC_TERROR_TOWN, "Terror Town", SCENARIO_CATEGORY_EXPERT },
{ SC_MEGAWORLD_PARK, "Megaworld Park", SCENARIO_CATEGORY_EXPERT },
{ SC_VENUS_PONDS, "Venus Ponds", SCENARIO_CATEGORY_EXPERT },
{ SC_MICRO_PARK, "Micro Park", SCENARIO_CATEGORY_EXPERT },
};
// RCT2
const scenario_title_desc ScenarioTitlesRCT2[] = {
{ SC_UNIDENTIFIED, "Crazy Castle", SCENARIO_CATEGORY_BEGINNER },
{ SC_UNIDENTIFIED, "Electric Fields", SCENARIO_CATEGORY_BEGINNER },
{ SC_UNIDENTIFIED, "Factory Capers", SCENARIO_CATEGORY_BEGINNER },
{ SC_UNIDENTIFIED, "Amity Airfield", SCENARIO_CATEGORY_CHALLENGING },
{ SC_UNIDENTIFIED, "Botany Breakers", SCENARIO_CATEGORY_CHALLENGING },
{ SC_UNIDENTIFIED, "Bumbly Bazaar", SCENARIO_CATEGORY_CHALLENGING },
{ SC_UNIDENTIFIED, "Dusty Greens", SCENARIO_CATEGORY_CHALLENGING },
{ SC_UNIDENTIFIED, "Fungus Woods", SCENARIO_CATEGORY_CHALLENGING },
{ SC_UNIDENTIFIED, "Gravity Gardens", SCENARIO_CATEGORY_CHALLENGING },
{ SC_UNIDENTIFIED, "Infernal Views", SCENARIO_CATEGORY_CHALLENGING },
{ SC_UNIDENTIFIED, "Alpine Adventures", SCENARIO_CATEGORY_EXPERT },
{ SC_UNIDENTIFIED, "Extreme Heights", SCENARIO_CATEGORY_EXPERT },
{ SC_UNIDENTIFIED, "Ghost Town", SCENARIO_CATEGORY_EXPERT },
{ SC_UNIDENTIFIED, "Lucky Lake", SCENARIO_CATEGORY_EXPERT },
{ SC_UNIDENTIFIED, "Rainbow Summit", SCENARIO_CATEGORY_EXPERT },
};
// RCT2: Wacky Worlds
const scenario_title_desc ScenarioTitlesRCT2WW[] = {
{ SC_UNIDENTIFIED, "Africa - Victoria Falls", SCENARIO_CATEGORY_BEGINNER },
{ SC_UNIDENTIFIED, "Asia - Great Wall of China Tourism Enhancement", SCENARIO_CATEGORY_BEGINNER },
{ SC_UNIDENTIFIED, "North America - Grand Canyon", SCENARIO_CATEGORY_BEGINNER },
{ SC_UNIDENTIFIED, "South America - Rio Carnival", SCENARIO_CATEGORY_BEGINNER },
{ SC_UNIDENTIFIED, "Africa - African Diamond Mine", SCENARIO_CATEGORY_CHALLENGING },
{ SC_UNIDENTIFIED, "Asia - Maharaja Palace", SCENARIO_CATEGORY_CHALLENGING },
{ SC_UNIDENTIFIED, "Australasia - Ayers Rock", SCENARIO_CATEGORY_CHALLENGING },
{ SC_UNIDENTIFIED, "Europe - European Cultural Festival", SCENARIO_CATEGORY_CHALLENGING },
{ SC_UNIDENTIFIED, "North America - Rollercoaster Heaven", SCENARIO_CATEGORY_CHALLENGING },
{ SC_UNIDENTIFIED, "South America - Inca Lost City", SCENARIO_CATEGORY_CHALLENGING },
{ SC_UNIDENTIFIED, "Africa - Oasis", SCENARIO_CATEGORY_EXPERT },
{ SC_UNIDENTIFIED, "Antarctic - Ecological Salvage", SCENARIO_CATEGORY_EXPERT },
{ SC_UNIDENTIFIED, "Asia - Japanese Coastal Reclaim", SCENARIO_CATEGORY_EXPERT },
{ SC_UNIDENTIFIED, "Australasia - Fun at the Beach", SCENARIO_CATEGORY_EXPERT },
{ SC_UNIDENTIFIED, "Europe - Renovation", SCENARIO_CATEGORY_EXPERT },
{ SC_UNIDENTIFIED, "N. America - Extreme Hawaiian Island", SCENARIO_CATEGORY_EXPERT },
{ SC_UNIDENTIFIED, "South America - Rain Forest Plateau", SCENARIO_CATEGORY_EXPERT },
};
// RCT2: Time Twister
const scenario_title_desc ScenarioTitlesRCT2TT[] = {
{ SC_UNIDENTIFIED, "Dark Age - Robin Hood", SCENARIO_CATEGORY_BEGINNER },
{ SC_UNIDENTIFIED, "Prehistoric - After the Asteroid", SCENARIO_CATEGORY_BEGINNER },
{ SC_UNIDENTIFIED, "Roaring Twenties - Prison Island", SCENARIO_CATEGORY_BEGINNER },
{ SC_UNIDENTIFIED, "Rock 'n' Roll - Flower Power", SCENARIO_CATEGORY_BEGINNER },
{ SC_UNIDENTIFIED, "Dark Age - Castle", SCENARIO_CATEGORY_CHALLENGING },
{ SC_UNIDENTIFIED, "Future - First Encounters", SCENARIO_CATEGORY_CHALLENGING },
{ SC_UNIDENTIFIED, "Mythological - Animatronic Film Set", SCENARIO_CATEGORY_CHALLENGING },
{ SC_UNIDENTIFIED, "Prehistoric - Jurassic Safari", SCENARIO_CATEGORY_CHALLENGING },
{ SC_UNIDENTIFIED, "Roaring Twenties - Schneider Cup", SCENARIO_CATEGORY_CHALLENGING },
{ SC_UNIDENTIFIED, "Future - Future World", SCENARIO_CATEGORY_EXPERT },
{ SC_UNIDENTIFIED, "Mythological - Cradle of Civilisation", SCENARIO_CATEGORY_EXPERT },
{ SC_UNIDENTIFIED, "Prehistoric - Stone Age", SCENARIO_CATEGORY_EXPERT },
{ SC_UNIDENTIFIED, "Roaring Twenties - Skyscrapers", SCENARIO_CATEGORY_EXPERT },
{ SC_UNIDENTIFIED, "Rock 'n' Roll - Rock 'n' Roll", SCENARIO_CATEGORY_EXPERT },
};
// Real parks
const scenario_title_desc ScenarioTitlesRealParks[] = {
{ SC_UNIDENTIFIED, "Alton Towers", SCENARIO_CATEGORY_REAL },
{ SC_UNIDENTIFIED, "Heide-Park", SCENARIO_CATEGORY_REAL },
{ SC_UNIDENTIFIED, "Blackpool Pleasure Beach", SCENARIO_CATEGORY_REAL },
{ SC_UNIDENTIFIED, "Six Flags Belgium", SCENARIO_CATEGORY_REAL },
{ SC_UNIDENTIFIED, "Six Flags Great Adventure", SCENARIO_CATEGORY_REAL },
{ SC_UNIDENTIFIED, "Six Flags Holland", SCENARIO_CATEGORY_REAL },
{ SC_UNIDENTIFIED, "Six Flags Magic Mountain", SCENARIO_CATEGORY_REAL },
{ SC_UNIDENTIFIED, "Six Flags over Texas", SCENARIO_CATEGORY_REAL },
};
// Other parks
const scenario_title_desc ScenarioTitlesOtherParks[] = {
{ SC_UNIDENTIFIED, "Fort Anachronism", SCENARIO_CATEGORY_DLC },
{ SC_UNIDENTIFIED, "PC Player", SCENARIO_CATEGORY_DLC },
{ SC_UNIDENTIFIED, "PC Gaming World", SCENARIO_CATEGORY_DLC },
{ SC_UNIDENTIFIED, "gameplay", SCENARIO_CATEGORY_DLC },
{ SC_UNIDENTIFIED, "Panda World", SCENARIO_CATEGORY_DLC },
{ SC_UNIDENTIFIED, "Competition Land 1", SCENARIO_CATEGORY_DLC },
{ SC_UNIDENTIFIED, "Competition Land 2", SCENARIO_CATEGORY_DLC },
{ SC_UNIDENTIFIED, "Build your own Six Flags Belgium", SCENARIO_CATEGORY_BUILD_YOUR_OWN },
{ SC_UNIDENTIFIED, "Build your own Six Flags Great Adventure", SCENARIO_CATEGORY_BUILD_YOUR_OWN },
{ SC_UNIDENTIFIED, "Build your own Six Flags Holland", SCENARIO_CATEGORY_BUILD_YOUR_OWN },
{ SC_UNIDENTIFIED, "Build your own Six Flags Magic Mountain", SCENARIO_CATEGORY_BUILD_YOUR_OWN },
{ SC_UNIDENTIFIED, "Build your own Six Flags Park", SCENARIO_CATEGORY_BUILD_YOUR_OWN },
{ SC_UNIDENTIFIED, "Build your own Six Flags over Texas", SCENARIO_CATEGORY_BUILD_YOUR_OWN },
};
#define DEFINE_SCENARIO_TITLE_DESC_GROUP(x) { countof(x), x }
const struct {
int count;
const scenario_title_desc * const titles;
} ScenarioTitlesBySource[] = {
DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesRCT1),
DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesRCT1AA),
DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesRCT1LL),
DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesRCT2),
DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesRCT2WW),
DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesRCT2TT),
DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesRealParks),
DEFINE_SCENARIO_TITLE_DESC_GROUP(ScenarioTitlesOtherParks),
};
bool scenario_get_source_desc(const utf8 *name, source_desc *outDesc)
{
assert(outDesc != NULL);
sint32 currentIndex = 0;
for (int i = 0; i < countof(ScenarioTitlesBySource); i++) {
for (int j = 0; j < ScenarioTitlesBySource[i].count; j++) {
const scenario_title_desc *desc = &ScenarioTitlesBySource[i].titles[j];
if (_strcmpi(name, desc->title) == 0) {
outDesc->title = desc->title;
outDesc->id = desc->id;
outDesc->source = i;
outDesc->index = currentIndex;
outDesc->category = desc->category;
return true;
}
currentIndex++;
}
}
outDesc->title = NULL;
outDesc->id = SC_UNIDENTIFIED;
outDesc->source = SCENARIO_SOURCE_OTHER;
outDesc->index = -1;
outDesc->category = SCENARIO_CATEGORY_OTHER;
return false;
}
bool scenario_get_source_desc_by_id(uint8 id, source_desc *outDesc)
{
assert(outDesc != NULL);
sint32 currentIndex = 0;
for (int i = 0; i < countof(ScenarioTitlesBySource); i++) {
for (int j = 0; j < ScenarioTitlesBySource[i].count; j++) {
const scenario_title_desc *desc = &ScenarioTitlesBySource[i].titles[j];
if (id == desc->id) {
outDesc->title = desc->title;
outDesc->id = desc->id;
outDesc->source = i;
outDesc->index = currentIndex;
outDesc->category = desc->category;
return true;
}
currentIndex++;
}
}
outDesc->title = NULL;
outDesc->id = SC_UNIDENTIFIED;
outDesc->source = SCENARIO_SOURCE_OTHER;
outDesc->index = -1;
outDesc->category = SCENARIO_CATEGORY_OTHER;
return false;
}
void scenario_normalise_name(utf8 *name)
{
size_t nameLength = strlen(name);
// Strip "RCT(1|2)?" prefix off scenario names.
if (nameLength >= 3 && (name[0] == 'R' && name[1] == 'C' && name[2] == 'T')) {
if (nameLength >= 4 && (name[3] == '1' || name[3] == '2')) {
log_verbose("Stripping RCT/1/2 from name: %s", name);
safe_strncpy(name, name + 4, 64);
} else {
safe_strncpy(name, name + 3, 64);
}
}
// Trim (for the sake of the above and WW / TT scenarios
safe_strtrimleft(name, name, 64);
// American scenario titles should be converted to British name
// Don't worry, names will be translated using language packs later
for (int i = 0; i < countof(ScenarioAliases); i++) {
if (strcmp(ScenarioAliases[i].alternative, name) == 0) {
log_verbose("Found alias: %s; will treat as: %s", name, ScenarioAliases[i].original);
safe_strncpy(name, ScenarioAliases[i].original, 64);
}
}
}

View File

@ -64,6 +64,7 @@ rct_xy16 _titleScriptCurrentCentralPosition = { -1, -1 };
#define ZOOM(d) TITLE_SCRIPT_ZOOM, d
#define RESTART() TITLE_SCRIPT_RESTART
#define LOAD(i) TITLE_SCRIPT_LOAD, i
#define LOADRCT1(i) TITLE_SCRIPT_LOADRCT1, i
static const uint8 _magicMountainScript[] = {
LOADMM(),
@ -298,10 +299,7 @@ static void title_do_next_script_opcode()
uint8 script_opcode, script_operand;
rct_window* w;
gTitleScriptCommand++;
if (gTitleScriptCommand <= 1 || *(_currentScript - 1) != TITLE_SCRIPT_END)
script_opcode = *_currentScript++;
else
script_opcode = *_currentScript;
script_opcode = *_currentScript++;
if (gTitleScriptSkipTo != -1) {
if (gTitleScriptSkipTo == gTitleScriptCommand) {
gTitleScriptSkipTo = -1;
@ -422,6 +420,38 @@ static void title_do_next_script_opcode()
}
}
break;
case TITLE_SCRIPT_LOADRCT1:
script_operand = (*_currentScript++);
source_desc sourceDesc;
if (!scenario_get_source_desc_by_id(script_operand, &sourceDesc) || sourceDesc.index == -1) {
log_fatal("Invalid scenario id.");
exit(-1);
}
const utf8 *path = NULL;
for (int i = 0; i < gScenarioListCount; i++) {
if (gScenarioList[i].source_index == sourceDesc.index) {
path = gScenarioList[i].path;
break;
}
}
if (path == NULL || !title_load_park(path)) {
script_opcode = *_currentScript;
while (script_opcode != TITLE_SCRIPT_LOADRCT1 && script_opcode != TITLE_SCRIPT_RESTART && script_opcode != TITLE_SCRIPT_END) {
title_skip_opcode();
script_opcode = *_currentScript;
}
if (script_opcode == TITLE_SCRIPT_RESTART) {
title_sequence_change_preset(4);
title_refresh_sequence();
config_save_default();
return;
}
}
gTitleScriptSave = 0xFF;
break;
}
window_invalidate_by_class(WC_TITLE_EDITOR);
}
@ -508,7 +538,7 @@ void title_update()
audio_start_title_music();
}
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~0x80;
gInputFlags &= ~INPUT_FLAG_VIEWPORT_SCROLLING;
window_map_tooltip_update_visibility();
window_dispatch_update_all();
@ -688,6 +718,9 @@ bool title_refresh_sequence()
hasInvalidSave = true;
hasLoad = true;
}
else if (title->commands[i].command == TITLE_SCRIPT_LOADRCT1) {
hasLoad = true;
}
else if (title->commands[i].command == TITLE_SCRIPT_LOADMM) {
hasLoad = true;
}
@ -711,6 +744,9 @@ bool title_refresh_sequence()
for (int i = 0; i < title->num_commands; i++) {
*scriptPtr++ = title->commands[i].command;
switch (title->commands[i].command) {
case TITLE_SCRIPT_LOADRCT1:
*scriptPtr++ = title->commands[i].saveIndex;
break;
case TITLE_SCRIPT_LOAD:
src = title->saves[title->commands[i].saveIndex];
do {

View File

@ -34,7 +34,8 @@ enum {
TITLE_SCRIPT_END,
TITLE_SCRIPT_SPEED,
TITLE_SCRIPT_LOOP,
TITLE_SCRIPT_ENDLOOP
TITLE_SCRIPT_ENDLOOP,
TITLE_SCRIPT_LOADRCT1,
};
extern sint32 gTitleScriptCommand;

View File

@ -1,132 +0,0 @@
/*****************************************************************************
* 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 "interface/window.h"
#include "localisation/localisation.h"
#include "tutorial.h"
#include "windows/error.h"
#include "windows/tooltip.h"
static void sub_6EA2AA(rct_window *w, int widgetIndex, int x, int y, int edi);
/**
*
* rct2: 0x0066ECC1
*/
void tutorial_start(int type)
{
strcpy((char*)0x009BC677, "Tutorial not implemented.");
window_error_open(3165, STR_NONE);
}
/**
*
* rct2: 0x0066EE25
*/
void tutorial_stop()
{
// RCT2_CALLPROC_EBPSAFE(0x0066EE25);
}
void game_handle_keyboard_input_for_tutorial()
{
#ifdef ENABLE_TUTORIAL
rct_window *w;
if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 1) {
int eax, ebx, ecx, edx, esi, edi, ebp;
RCT2_CALLFUNC_X(0x0066EEB4, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
eax &= 0xFF;
RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) = eax;
if (RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 4) {
window_tooltip_close();
if ((w = window_get_main()) != NULL) {
RCT2_CALLPROC_X(0x006EA2AA, 0, 0, 0, 0, (int)w, RCT2_GLOBAL(0x009DEA72, uint16), 0);
RCT2_GLOBAL(0x009DEA72, uint16)++;
}
}
} else {
if (!(RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 4)) {
window_tooltip_close();
if ((w = window_get_main()) != NULL) {
sub_6EA2AA(w, 0, 0, 0, RCT2_GLOBAL(0x009DEA72, uint16));
RCT2_GLOBAL(0x009DEA72, uint16)++;
}
}
// Write tutorial input
RCT2_CALLPROC_X(0x0066EEE1, RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8), 0, 0, 0, 0, 0, 0);
}
#endif
}
static void sub_6EA2AA(rct_window *w, int widgetIndex, int x, int y, int edi)
{
#ifdef ENABLE_TUTORIAL
RCT2_CALLPROC_X(0x006EA2AA, 0, 0, 0, 0, (int)w, RCT2_GLOBAL(0x009DEA72, uint16), 0);
return;
rct_window *tooltipWindow;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) = w->classification;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) = w->number;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = widgetIndex;
rct_string_id stringId = window_event_tooltip_call(w, widgetIndex);
if (stringId == (rct_string_id)STR_NONE)
return;
tooltipWindow = window_find_by_class(WC_TOOLTIP);
if (tooltipWindow == NULL)
return;
char *buffer = (char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER;
RCT2_GLOBAL(0x0142006C, uint32) = edi;
format_string(buffer, edi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS);
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 224;
int width = gfx_get_string_width_new_lined(buffer);
width = min(width, 196);
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 224;
int numLines, fontHeight;
gfx_wrap_string(buffer, width + 1, &numLines, &fontHeight);
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TEXT_HEIGHT, uint16) = numLines;
tooltipWindow->widgets[0].right = width + 3;
tooltipWindow->widgets[0].bottom = ((numLines + 1) * 10) + 4;
char *tooltipBuffer = (char*)RCT2_ADDRESS_TOOLTIP_TEXT_BUFFER;
memcpy(tooltipBuffer, buffer, 512);
window_tooltip_open(w, widgetIndex, x, y);
#endif
}
/**
*
* rct2: 0x0066EE54
*/
void sub_66EE54()
{
// RCT2_CALLPROC_EBPSAFE(0x0066EE54);
}

View File

@ -1,28 +0,0 @@
/*****************************************************************************
* 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 _TUTORIAL_H_
#define _TUTORIAL_H_
void tutorial_start(int type);
void tutorial_stop();
void sub_66EE54();
#endif

View File

@ -67,7 +67,6 @@ const char *path_get_filename(const utf8 *path)
// Checks if the path is valid (e.g. not just a file name)
if (filename == NULL)
{
log_warning("Invalid path given: %s", path);
// Return the input string to keep things working
return path;
}
@ -78,6 +77,8 @@ const char *path_get_filename(const utf8 *path)
return filename;
}
// Returns the extension (dot inclusive) from the given path, or the end of the
// string when no extension was found.
const char *path_get_extension(const utf8 *path)
{
// Get the filename from the path
@ -94,6 +95,15 @@ const char *path_get_extension(const utf8 *path)
}
void path_set_extension(utf8 *path, const utf8 *newExtension)
{
// Remove existing extension (check first if there is one)
if (path_get_extension(path) < strrchr(path, '\0'))
path_remove_extension(path);
// Append new extension
path_append_extension(path, newExtension);
}
void path_append_extension(utf8 *path, const utf8 *newExtension)
{
// Append a dot to the filename if the new extension doesn't start with it
char *endOfString = strrchr(path, '\0');
@ -101,15 +111,17 @@ void path_set_extension(utf8 *path, const utf8 *newExtension)
*endOfString++ = '.';
// Append the extension to the path
// No existing extensions should be removed ("ride.TD6" -> "ride.TD6.TD6")
safe_strncpy(endOfString, newExtension, MAX_PATH - (endOfString - path) - 1);
}
void path_remove_extension(utf8 *path)
{
// Find last dot in filename, and replace it with a null-terminator
char *lastDot = strrchr(path, '.');
if (*lastDot) *lastDot = '\0';
char *lastDot = strrchr(path_get_filename(path), '.');
if (lastDot != NULL)
*lastDot = '\0';
else
log_warning("No extension found. (path = %s)", path);
}
bool readentirefile(const utf8 *path, void **outBuffer, int *outLength)
@ -210,6 +222,70 @@ char *safe_strncpy(char * destination, const char * source, size_t size)
return result;
}
char *safe_strcat(char *destination, const char *source, size_t size)
{
assert(destination != NULL);
assert(source != NULL);
if (size == 0) {
return destination;
}
char *result = destination;
size_t i;
for (i = 0; i < size; i++) {
if (*destination == '\0') {
break;
} else {
destination++;
}
}
bool terminated = false;
for (; i < size; i++) {
if (*source != '\0') {
*destination++ = *source++;
} else {
*destination = *source;
terminated = true;
break;
}
}
if (!terminated) {
result[size - 1] = '\0';
log_warning("Truncating string \"%s\" to %d bytes.", result, size);
}
return result;
}
char *safe_strcat_path(char *destination, const char *source, size_t size)
{
const char pathSeparator = platform_get_path_separator();
size_t length = strlen(destination);
if (length >= size - 1) {
return destination;
}
if (destination[length - 1] != pathSeparator) {
destination[length] = pathSeparator;
destination[length + 1] = '\0';
}
return safe_strcat(destination, source, size);
}
char *safe_strtrimleft(char *destination, const char *source, size_t size)
{
while (*source == ' ' && *source != '\0') {
source++;
}
return safe_strncpy(destination, source, size);
}
bool utf8_is_bom(const char *str)
{
return str[0] == (char)0xEF && str[1] == (char)0xBB && str[2] == (char)0xBF;

View File

@ -33,6 +33,7 @@ bool filename_valid_characters(const utf8 *filename);
const char *path_get_filename(const utf8 *path);
const char *path_get_extension(const utf8 *path);
void path_set_extension(utf8 *path, const utf8 *newExtension);
void path_append_extension(utf8 *path, const utf8 *newExtension);
void path_remove_extension(utf8 *path);
bool readentirefile(const utf8 *path, void **outBuffer, int *outLength);
@ -41,6 +42,9 @@ int bitcount(int source);
bool strequals(const char *a, const char *b, int length, bool caseInsensitive);
int strcicmp(char const *a, char const *b);
char *safe_strncpy(char * destination, const char * source, size_t num);
char *safe_strcat(char *destination, const char *source, size_t size);
char *safe_strcat_path(char *destination, const char *source, size_t size);
char *safe_strtrimleft(char *destination, const char *source, size_t size);
bool utf8_is_bom(const char *str);
bool str_is_null_or_empty(const char *str);

View File

@ -483,7 +483,7 @@ static void cheat_fix_vandalism()
if (map_element_get_type(it.element) != MAP_ELEMENT_TYPE_PATH)
continue;
if ((it.element->properties.path.additions & 0x0F) == 0)
if (!footpath_element_has_path_scenery(it.element))
continue;
it.element->flags &= ~MAP_ELEMENT_FLAG_BROKEN;
@ -511,10 +511,10 @@ static void cheat_remove_litter()
if (map_element_get_type(it.element) != MAP_ELEMENT_TYPE_PATH)
continue;
if ((it.element->properties.path.additions & 0x0F) == 0)
if (!footpath_element_has_path_scenery(it.element))
continue;
sceneryEntry = g_pathBitSceneryEntries[(it.element->properties.path.additions & 0xF) - 1];
sceneryEntry = g_pathBitSceneryEntries[footpath_element_get_path_scenery_index(it.element)];
if(sceneryEntry->path_bit.var_06 & (1 << 0))
it.element->properties.path.addition_status = 0xFF;

View File

@ -194,8 +194,8 @@ static void window_clear_scenery_textinput(rct_window *w, int widgetIndex, char
static void window_clear_scenery_inputsize(rct_window *w)
{
((uint16*)TextInputDescriptionArgs)[0] = MINIMUM_TOOL_SIZE;
((uint16*)TextInputDescriptionArgs)[1] = MAXIMUM_TOOL_SIZE;
TextInputDescriptionArgs[0] = MINIMUM_TOOL_SIZE;
TextInputDescriptionArgs[1] = MAXIMUM_TOOL_SIZE;
window_text_input_open(w, WIDX_PREVIEW, 5128, 5129, STR_NONE, STR_NONE, 3);
}
@ -259,7 +259,7 @@ static void window_clear_scenery_paint(rct_window *w, rct_drawpixelinfo *dpi)
*/
static int window_clear_scenery_should_close()
{
if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE))
if (!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE))
return 1;
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != WC_TOP_TOOLBAR)
return 1;

View File

@ -160,9 +160,9 @@ void window_dropdown_show_text_custom_width(int x, int y, int extray, uint8 colo
memcpy((void*)0x009DEBA4, gDropdownItemsFormat, 40 * 2);
memcpy((void*)0x009DEBF4, gDropdownItemsArgs, 40 * 8);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~(INPUT_FLAG_DROPDOWN_STAY_OPEN | INPUT_FLAG_DROPDOWN_MOUSE_UP);
gInputFlags &= ~(INPUT_FLAG_DROPDOWN_STAY_OPEN | INPUT_FLAG_DROPDOWN_MOUSE_UP);
if (flags & DROPDOWN_FLAG_STAY_OPEN)
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_DROPDOWN_STAY_OPEN;
gInputFlags |= INPUT_FLAG_DROPDOWN_STAY_OPEN;
window_dropdown_close();
_dropdown_num_columns = 1;
@ -204,7 +204,7 @@ void window_dropdown_show_text_custom_width(int x, int y, int extray, uint8 colo
gDropdownItemsDisabled = 0;
gDropdownItemsChecked = 0;
gDropdownIsColour = false;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, sint8) = INPUT_STATE_DROPDOWN_ACTIVE;
gInputState = INPUT_STATE_DROPDOWN_ACTIVE;
}
/**
@ -230,9 +230,9 @@ void window_dropdown_show_image(int x, int y, int extray, uint8 colour, uint8 fl
memcpy((void*)0x009DEBA4, gDropdownItemsFormat, 40 * 2);
memcpy((void*)0x009DEBF4, gDropdownItemsArgs, 40 * 8);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~(INPUT_FLAG_DROPDOWN_STAY_OPEN | INPUT_FLAG_DROPDOWN_MOUSE_UP);
gInputFlags &= ~(INPUT_FLAG_DROPDOWN_STAY_OPEN | INPUT_FLAG_DROPDOWN_MOUSE_UP);
if (flags & DROPDOWN_FLAG_STAY_OPEN)
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_DROPDOWN_STAY_OPEN;
gInputFlags |= INPUT_FLAG_DROPDOWN_STAY_OPEN;
// Close existing dropdown
window_dropdown_close();
@ -274,7 +274,7 @@ void window_dropdown_show_image(int x, int y, int extray, uint8 colour, uint8 fl
gDropdownHighlightedIndex = -1;
gDropdownItemsDisabled = 0;
gDropdownItemsChecked = 0;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, sint8) = INPUT_STATE_DROPDOWN_ACTIVE;
gInputState = INPUT_STATE_DROPDOWN_ACTIVE;
// Copy the following properties until all use of it is decompiled
gDropdownHighlightedIndex = gDropdownHighlightedIndex;
@ -324,7 +324,7 @@ static void window_dropdown_paint(rct_window *w, rct_drawpixelinfo *dpi)
item = gDropdownItemsFormat[i];
if (item == (uint16)-1 || item == (uint16)-2) {
// Image item
image = *((uint32*)&gDropdownItemsArgs[i]);
image = (uint32)gDropdownItemsArgs[i];
if (item == (uint16)-2 && gDropdownHighlightedIndex == i)
image++;

View File

@ -375,7 +375,7 @@ void window_editor_bottom_toolbar_jump_forward_to_save_scenario()
s6Info->editor_step = 255;
// Ensure path has .SC6 extension
path_set_extension(path, ".SC6");
path_append_extension(path, ".SC6");
// Save the scenario
parkFlagsBackup = RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32);

View File

@ -155,8 +155,6 @@ static rct_window_event_list window_editor_inventions_list_drag_events = {
rct_research_item *_editorInventionsListDraggedItem;
#define WindowHighlightedItem(w) *((rct_research_item**)&(w->highlighted_item))
static void window_editor_inventions_list_drag_open(rct_research_item *researchItem);
static void move_research_item(rct_research_item *beforeItem);
@ -437,7 +435,7 @@ static void move_research_item(rct_research_item *beforeItem)
w = window_find_by_class(WC_EDITOR_INVENTION_LIST);
if (w != NULL) {
WindowHighlightedItem(w) = NULL;
w->research_item = NULL;
window_invalidate(w);
}
}
@ -549,7 +547,7 @@ void window_editor_inventions_list_open()
window_init_scroll_widgets(w);
w->var_4AE = 0;
w->selected_tab = 0;
WindowHighlightedItem(w) = NULL;
w->research_item = NULL;
_editorInventionsListDraggedItem = NULL;
}
@ -668,8 +666,8 @@ static void window_editor_inventions_list_scrollmouseover(rct_window *w, int scr
rct_research_item *researchItem;
researchItem = window_editor_inventions_list_get_item_from_scroll_y(scrollIndex, y);
if (researchItem != WindowHighlightedItem(w)) {
WindowHighlightedItem(w) = researchItem;
if (researchItem != w->research_item) {
w->research_item = researchItem;
window_invalidate(w);
}
}
@ -770,7 +768,7 @@ static void window_editor_inventions_list_paint(rct_window *w, rct_drawpixelinfo
researchItem = _editorInventionsListDraggedItem;
if (researchItem == NULL)
researchItem = WindowHighlightedItem(w);
researchItem = w->research_item;
// If the research item is null or a list separator.
if (researchItem == NULL || researchItem->entryIndex < 0)
return;
@ -842,7 +840,7 @@ static void window_editor_inventions_list_scrollpaint(rct_window *w, rct_drawpix
continue;
colour = 142;
if (WindowHighlightedItem(w) == researchItem) {
if (w->research_item == researchItem) {
if (_editorInventionsListDraggedItem == NULL) {
// Highlight
top = itemY;
@ -912,8 +910,8 @@ static void window_editor_inventions_list_drag_open(rct_research_item *researchI
window_editor_inventions_list_drag_widgets[0].right = stringWidth;
w = window_create(
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16) - (stringWidth / 2),
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16) - 7,
gTooltipCursorX - (stringWidth / 2),
gTooltipCursorY - 7,
stringWidth,
14,
&window_editor_inventions_list_drag_events,
@ -922,9 +920,7 @@ static void window_editor_inventions_list_drag_open(rct_research_item *researchI
);
w->widgets = window_editor_inventions_list_drag_widgets;
w->colours[1] = 2;
input_window_position_begin(
w, 0, RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16), RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16)
);
input_window_position_begin(w, 0, gTooltipCursorX, gTooltipCursorY);
}
/**
@ -939,8 +935,8 @@ static void window_editor_inventions_list_drag_cursor(rct_window *w, int widgetI
inventionListWindow = window_find_by_class(WC_EDITOR_INVENTION_LIST);
if (inventionListWindow != NULL) {
researchItem = get_research_item_at(x, y);
if (researchItem != WindowHighlightedItem(inventionListWindow)) {
WindowHighlightedItem(inventionListWindow) = researchItem;
if (researchItem != inventionListWindow->research_item) {
inventionListWindow = (rct_window *)researchItem;
window_invalidate(inventionListWindow);
}
}

View File

@ -36,6 +36,7 @@
#include "dropdown.h"
#include "error.h"
#include "../util/util.h"
#include "../world/footpath.h"
enum {
@ -419,7 +420,7 @@ void window_editor_object_selection_open()
window->var_4AE = 0;
window->selected_tab = 0;
window->selected_list_item = -1;
window->highlighted_item = 0xFFFFFFFF;
window->object_entry = (rct_object_entry *) 0xFFFFFFFF;
window->min_width = 600;
window->min_height = 400;
window->max_width = 1200;
@ -577,7 +578,6 @@ static void setup_in_use_selection_flags(){
map_element_iterator_begin(&iter);
do {
uint16 type;
uint8 path_additions;
rct_banner* banner;
switch (map_element_get_type(iter.element)) {
@ -591,10 +591,9 @@ static void setup_in_use_selection_flags(){
assert(type < object_entry_group_counts[OBJECT_TYPE_PATHS]);
RCT2_ADDRESS(0x0098DA38, uint8*)[OBJECT_TYPE_PATHS][type] |= (1 << 0);
path_additions = iter.element->properties.path.additions & 0xF;
if (path_additions){
path_additions--;
RCT2_ADDRESS(0x0098DA38, uint8*)[OBJECT_TYPE_PATH_BITS][path_additions] |= (1 << 0);
if (footpath_element_has_path_scenery(iter.element)) {
uint8 path_additions = footpath_element_get_path_scenery_index(iter.element);
RCT2_ADDRESS(0x0098DA38, uint8*)[OBJECT_TYPE_PATH_BITS][path_additions] |= 1;
}
break;
case MAP_ELEMENT_TYPE_SCENERY:
@ -836,7 +835,7 @@ static void window_editor_object_selection_mouseup(rct_window *w, int widgetInde
visible_list_refresh(w);
w->selected_list_item = -1;
w->highlighted_item = 0xFFFFFFFF;
w->object_entry = (rct_object_entry *) 0xFFFFFFFF;
w->scrolls[0].v_top = 0;
object_free_scenario_text();
window_invalidate(w);
@ -856,7 +855,7 @@ static void window_editor_object_selection_mouseup(rct_window *w, int widgetInde
visible_list_refresh(w);
w->selected_list_item = -1;
w->highlighted_item = 0xFFFFFFFF;
w->object_entry = (rct_object_entry *) 0xFFFFFFFF;
w->scrolls[0].v_top = 0;
object_free_scenario_text();
window_invalidate(w);
@ -1051,7 +1050,7 @@ static void window_editor_object_selection_scroll_mouseover(rct_window *w, int s
return;
w->selected_list_item = selectedObject;
w->highlighted_item = (uint32)installedEntry;
w->object_entry = installedEntry;
object_free_scenario_text();
if (selectedObject != -1)
object_get_scenario_text(installedEntry);
@ -1342,7 +1341,7 @@ static void window_editor_object_selection_paint(rct_window *w, rct_drawpixelinf
if (w->selected_list_item == -1 || stex_entry == NULL)
return;
highlightedEntry = (rct_object_entry*)w->highlighted_item;
highlightedEntry = w->object_entry;
type = highlightedEntry->flags & 0x0F;
// Draw preview
@ -1458,7 +1457,7 @@ static void window_editor_object_selection_scrollpaint(rct_window *w, rct_drawpi
// Highlight background
colour = 142;
if (listItem->entry == (rct_object_entry*)w->highlighted_item && !(*listItem->flags & OBJECT_SELECTION_FLAG_6)) {
if (listItem->entry == w->object_entry && !(*listItem->flags & OBJECT_SELECTION_FLAG_6)) {
gfx_fill_rect(dpi, 0, y, w->width, y + 11, 0x2000031);
colour = 14;
}
@ -1515,7 +1514,7 @@ static void window_editor_object_set_page(rct_window *w, int page)
w->selected_tab = page;
w->selected_list_item = -1;
w->highlighted_item = 0xFFFFFFFF;
w->object_entry = (rct_object_entry *)0xFFFFFFFF;
w->scrolls[0].v_top = 0;
object_free_scenario_text();

View File

@ -534,9 +534,9 @@ static void window_editor_objective_options_show_category_dropdown(rct_window *w
dropdownWidget = &w->widgets[WIDX_CATEGORY];
for (i = 0; i < 5; i++) {
for (i = SCENARIO_CATEGORY_BEGINNER; i <= SCENARIO_CATEGORY_OTHER; i++) {
gDropdownItemsFormat[i] = 1142;
gDropdownItemsArgs[i] = STR_BEGINNER_PARKS + i;
gDropdownItemsArgs[i] = ScenarioCategoryStringIds[i];
}
window_dropdown_show_text_custom_width(
w->x + dropdownWidget->left,
@ -1036,7 +1036,7 @@ static void window_editor_objective_options_main_paint(rct_window *w, rct_drawpi
// Scenario category value
x = w->x + w->widgets[WIDX_CATEGORY].left + 1;
y = w->y + w->widgets[WIDX_CATEGORY].top;
stringId = STR_BEGINNER_PARKS + s6Info->category;
stringId = ScenarioCategoryStringIds[s6Info->category];
gfx_draw_string_left(dpi, 1193, &stringId, 0, x, y);
}

View File

@ -217,7 +217,7 @@ void window_footpath_open()
tool_cancel();
RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) = PATH_CONSTRUCTION_MODE_LAND;
tool_set(window, WIDX_CONSTRUCT_ON_LAND, 17);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
gInputFlags |= INPUT_FLAG_6;
RCT2_GLOBAL(RCT2_ADDRESS_PATH_ERROR_OCCURED, uint8) = 0;
window_footpath_set_enabled_and_pressed_widgets();
}
@ -263,7 +263,7 @@ static void window_footpath_mouseup(rct_window *w, int widgetIndex)
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~2;
RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) = PATH_CONSTRUCTION_MODE_LAND;
tool_set(w, WIDX_CONSTRUCT_ON_LAND, 17);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
gInputFlags |= INPUT_FLAG_6;
RCT2_GLOBAL(RCT2_ADDRESS_PATH_ERROR_OCCURED, uint8) = 0;
window_footpath_set_enabled_and_pressed_widgets();
break;
@ -278,7 +278,7 @@ static void window_footpath_mouseup(rct_window *w, int widgetIndex)
RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~2;
RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) = PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL_TOOL;
tool_set(w, WIDX_CONSTRUCT_BRIDGE_OR_TUNNEL, 12);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
gInputFlags |= INPUT_FLAG_6;
RCT2_GLOBAL(RCT2_ADDRESS_PATH_ERROR_OCCURED, uint8) = 0;
window_footpath_set_enabled_and_pressed_widgets();
break;
@ -479,14 +479,14 @@ static void window_footpath_update(rct_window *w)
// Check tool
if (RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) == PATH_CONSTRUCTION_MODE_LAND) {
if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE))
if (!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE))
window_close(w);
else if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != WC_FOOTPATH)
window_close(w);
else if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) != WIDX_CONSTRUCT_ON_LAND)
window_close(w);
} else if (RCT2_GLOBAL(RCT2_ADDRESS_PATH_CONSTRUCTION_MODE, uint8) == PATH_CONSTRUCTION_MODE_BRIDGE_OR_TUNNEL_TOOL) {
if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE))
if (!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE))
window_close(w);
else if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != WC_FOOTPATH)
window_close(w);

View File

@ -20,10 +20,12 @@
#include "../addresses.h"
#include "../config.h"
#include "../localisation/date.h"
#include "../localisation/localisation.h"
#include "../input.h"
#include "../interface/themes.h"
#include "../interface/widget.h"
#include "../interface/window.h"
#include "../localisation/date.h"
#include "../localisation/localisation.h"
#include "../management/news_item.h"
#include "../peep/peep.h"
#include "../peep/staff.h"
@ -31,7 +33,6 @@
#include "../world/climate.h"
#include "../world/park.h"
#include "../world/sprite.h"
#include "../interface/themes.h"
enum WINDOW_GAME_BOTTOM_TOOLBAR_WIDGET_IDX {
WIDX_LEFT_OUTSET,
@ -85,7 +86,6 @@ static void window_game_bottom_toolbar_draw_left_panel(rct_drawpixelinfo *dpi, r
static void window_game_bottom_toolbar_draw_park_rating(rct_drawpixelinfo *dpi, rct_window *w, int colour, int x, int y, uint8 factor);
static void window_game_bottom_toolbar_draw_right_panel(rct_drawpixelinfo *dpi, rct_window *w);
static void window_game_bottom_toolbar_draw_news_item(rct_drawpixelinfo *dpi, rct_window *w);
static void window_game_bottom_toolbar_draw_tutorial_text(rct_drawpixelinfo *dpi, rct_window *w);
/**
*
@ -358,8 +358,6 @@ static void window_game_bottom_toolbar_paint(rct_window *w, rct_drawpixelinfo *d
if (!news_item_is_queue_empty())
window_game_bottom_toolbar_draw_news_item(dpi, w);
else if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8))
window_game_bottom_toolbar_draw_tutorial_text(dpi, w);
}
static void window_game_bottom_toolbar_draw_left_panel(rct_drawpixelinfo *dpi, rct_window *w)
@ -551,7 +549,7 @@ static void window_game_bottom_toolbar_draw_news_item(rct_drawpixelinfo *dpi, rc
}
}
uint32 image_id_base = *RCT2_ADDRESS(0x00982708, uint32*)[peep->sprite_type * 2];
uint32 image_id_base = g_sprite_entries[peep->sprite_type].sprite_image->base_image;
image_id_base += w->frame_no & 0xFFFFFFFC;
image_id_base++;
@ -599,16 +597,6 @@ static void window_game_bottom_toolbar_draw_news_item(rct_drawpixelinfo *dpi, rc
}
}
static void window_game_bottom_toolbar_draw_tutorial_text(rct_drawpixelinfo *dpi, rct_window *w)
{
int x, y;
x = (window_game_bottom_toolbar_widgets[WIDX_MIDDLE_OUTSET].left + window_game_bottom_toolbar_widgets[WIDX_MIDDLE_OUTSET].right) / 2 + w->x;
y = window_game_bottom_toolbar_widgets[WIDX_MIDDLE_OUTSET].top + w->y + 2;
gfx_draw_string_centred(dpi, STR_TUTORIAL, x, y, 32, 0);
gfx_draw_string_centred(dpi, STR_PRESS_KEY_OR_MOUSE_BUTTON_FOR_CONTROL, x, y + 10, 32, 0);
}
/**
*
* rct2: 0x0066C6D8
@ -633,7 +621,7 @@ static void window_game_bottom_toolbar_cursor(rct_window *w, int widgetIndex, in
case WIDX_GUESTS:
case WIDX_PARK_RATING:
case WIDX_DATE:
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = 2000;
gTooltipTimeout = 2000;
break;
}
}

View File

@ -503,7 +503,7 @@ void window_guest_open(rct_peep* peep){
window->viewport_focus_coordinates.y = 0;
window->frame_no = 0;
window->list_information_type = 0;
window->var_492 = 0;
window->picked_peep_frame = 0;
window->highlighted_item = 0;
window_guest_disable_widgets(window);
window->min_width = 192;
@ -560,7 +560,7 @@ void window_guest_disable_widgets(rct_window* w){
*/
void window_guest_overview_close(rct_window *w)
{
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE){
if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE){
if (w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS,rct_windowclass) &&
w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER,rct_windownumber))
tool_cancel();
@ -625,7 +625,7 @@ void window_guest_overview_mouse_up(rct_window *w, int widgetIndex)
return;
}
w->var_48C = peep->x;
w->picked_peep_old_x = peep->x;
remove_peep_from_ride(peep);
invalidate_sprite_2((rct_sprite*)peep);
@ -653,7 +653,7 @@ void window_guest_overview_mouse_up(rct_window *w, int widgetIndex)
* rct2: 0x696AA0
*/
void window_guest_set_page(rct_window* w, int page){
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)
if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE)
{
if(w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) &&
w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass))
@ -830,7 +830,7 @@ void window_guest_overview_tab_paint(rct_window* w, rct_drawpixelinfo* dpi){
if (peep->type == PEEP_TYPE_STAFF && peep->staff_type == STAFF_TYPE_ENTERTAINER)
y++;
int ebx = *(RCT2_ADDRESS(0x982708, uint32*)[peep->sprite_type * 2]) + 1;
int ebx = g_sprite_entries[peep->sprite_type].sprite_image->base_image + 1;
int eax = 0;
@ -1182,7 +1182,7 @@ void window_guest_overview_tool_update(rct_window* w, int widgetIndex, int x, in
map_invalidate_selection_rect();
}
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, sint32) = -1;
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, sint32) = -1;
int interactionType;
get_map_coordinates_from_pos(x, y, VIEWPORT_INTERACTION_MASK_NONE, NULL, NULL, &interactionType, NULL, NULL);
@ -1193,19 +1193,21 @@ void window_guest_overview_tool_update(rct_window* w, int widgetIndex, int x, in
y += 16;
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_X, uint16) = x;
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_Y, uint16) = y;
w->var_492++;
if (w->var_492 >= 48)w->var_492 = 0;
w->picked_peep_frame++;
if (w->picked_peep_frame >= 48) {
w->picked_peep_frame = 0;
}
rct_peep* peep;
peep = GET_PEEP(w->number);
int ebx = (RCT2_ADDRESS(0x982708, uint32*)[peep->sprite_type * 2])[22];
ebx += w->var_492 >> 2;
uint32 imageId = g_sprite_entries[peep->sprite_type].sprite_image[11].base_image;
imageId += w->picked_peep_frame >> 2;
int ebp = peep->tshirt_colour << 19;
int ecx = peep->trousers_colour << 24;
ebx |= ebp | ecx | 0xA0000000;
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, uint32) = ebx;
imageId |= ebp | ecx | 0xA0000000;
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, uint32) = imageId;
}
/**
@ -1254,7 +1256,7 @@ void window_guest_overview_tool_down(rct_window* w, int widgetIndex, int x, int
peep->state = 0;
peep_window_state_update(peep);
peep->action = 0xFF;
peep->var_6D = 0;
peep->special_sprite = 0;
peep->action_sprite_image_offset = 0;
peep->action_sprite_type = 0xFF;
peep->var_C4 = 0;
@ -1279,7 +1281,7 @@ void window_guest_overview_tool_abort(rct_window *w, int widgetIndex)
if (peep->state != PEEP_STATE_PICKED)
return;
sprite_move( w->var_48C, peep->y, peep->z + 8, (rct_sprite*)peep);
sprite_move(w->picked_peep_old_x, peep->y, peep->z + 8, (rct_sprite*)peep);
invalidate_sprite_2((rct_sprite*)peep);
if (peep->x != (sint16)0x8000){
@ -1287,13 +1289,13 @@ void window_guest_overview_tool_abort(rct_window *w, int widgetIndex)
peep->state = 0;
peep_window_state_update(peep);
peep->action = 0xFF;
peep->var_6D = 0;
peep->special_sprite = 0;
peep->action_sprite_image_offset = 0;
peep->action_sprite_type = 0;
peep->var_C4 = 0;
}
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, sint32) = -1;
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, sint32) = -1;
}
/**

View File

@ -590,7 +590,7 @@ static void window_guest_list_paint(rct_window *w, rct_drawpixelinfo *dpi)
window_draw_widgets(w, dpi);
// Tab 1 image
i = (_window_guest_list_selected_tab == 0 ? w->list_information_type & 0x0FFFFFFFC : 0);
i += RCT2_ADDRESS(RCT2_GLOBAL(0x00982708, int), int)[0] + 1;
i += g_sprite_entries[0].sprite_image->base_image + 1;
i |= 0xA1600000;
gfx_draw_sprite(
dpi,
@ -655,14 +655,14 @@ static void window_guest_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi,
// For each guest
FOR_ALL_GUESTS(spriteIndex, peep) {
peep->var_0C &= ~0x200;
peep->list_flags &= ~(PEEP_LIST_FLAGS_FLASHING);
if (peep->outside_of_park != 0)
continue;
if (_window_guest_list_selected_filter != -1) {
if (window_guest_list_is_peep_in_filter(peep))
continue;
RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_MAP_FLASHING_FLAGS, uint16) |= (1 << 0);
peep->var_0C |= 0x200;
peep->list_flags |= PEEP_LIST_FLAGS_FLASHING;
}
if (_window_guest_list_tracking_only && !(peep->flags & PEEP_FLAGS_TRACKING))
continue;
@ -841,11 +841,11 @@ static void window_guest_list_find_groups()
// Set all guests to unassigned
FOR_ALL_GUESTS(spriteIndex, peep)
if (peep->outside_of_park == 0)
peep->var_0C |= (1 << 8);
peep->list_flags |= PEEP_LIST_FLAGS_VISIBLE;
// For each guest / group
FOR_ALL_GUESTS(spriteIndex, peep) {
if (peep->outside_of_park != 0 || !(peep->var_0C & (1 << 8)))
if (peep->outside_of_park != 0 || !(peep->list_flags & PEEP_LIST_FLAGS_VISIBLE))
continue;
// New group, cap at 240 though
@ -856,7 +856,7 @@ static void window_guest_list_find_groups()
int ax = peep->sprite_index;
_window_guest_list_num_groups++;
_window_guest_list_groups_num_guests[groupIndex] = 1;
peep->var_0C &= ~(1 << 8);
peep->list_flags &= ~(PEEP_LIST_FLAGS_VISIBLE);
get_arguments_from_peep( peep, &_window_guest_list_groups_argument_1[groupIndex], &_window_guest_list_groups_argument_2[groupIndex]);
RCT2_GLOBAL(0x00F1EDF6, uint32) = _window_guest_list_groups_argument_1[groupIndex];
@ -868,7 +868,7 @@ static void window_guest_list_find_groups()
// Find more peeps that belong to same group
FOR_ALL_GUESTS(spriteIndex2, peep2) {
if (peep2->outside_of_park != 0 || !(peep2->var_0C & (1 << 8)))
if (peep2->outside_of_park != 0 || !(peep2->list_flags & PEEP_LIST_FLAGS_VISIBLE))
continue;
uint32 argument1, argument2;
@ -879,7 +879,7 @@ static void window_guest_list_find_groups()
// Assign guest
_window_guest_list_groups_num_guests[groupIndex]++;
peep2->var_0C &= ~(1 << 8);
peep2->list_flags &= ~(PEEP_LIST_FLAGS_VISIBLE);
// Add face sprite, cap at 56 though
if (_window_guest_list_groups_num_guests[groupIndex] >= 56)

View File

@ -272,7 +272,7 @@ static void window_land_dropdown(rct_window *w, int widgetIndex, int dropdownInd
type = (dropdownIndex == -1) ?
_selectedFloorTexture :
*((uint32*)&gDropdownItemsArgs[dropdownIndex]) - SPR_FLOOR_TEXTURE_GRASS;
(uint32)gDropdownItemsArgs[dropdownIndex] - SPR_FLOOR_TEXTURE_GRASS;
if (RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_SURFACE, uint8) == type) {
RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_SURFACE, uint8) = 255;
@ -288,7 +288,7 @@ static void window_land_dropdown(rct_window *w, int widgetIndex, int dropdownInd
type = (dropdownIndex == -1) ?
_selectedWallTexture :
*((uint32*)&gDropdownItemsArgs[dropdownIndex]) - SPR_WALL_TEXTURE_ROCK;
(uint32)gDropdownItemsArgs[dropdownIndex] - SPR_WALL_TEXTURE_ROCK;
if (RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_EDGE, uint8) == type) {
RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_EDGE, uint8) = 255;
@ -321,8 +321,8 @@ static void window_land_textinput(rct_window *w, int widgetIndex, char *text)
static void window_land_inputsize(rct_window *w)
{
((uint16*)TextInputDescriptionArgs)[0] = MINIMUM_TOOL_SIZE;
((uint16*)TextInputDescriptionArgs)[1] = MAXIMUM_TOOL_SIZE;
TextInputDescriptionArgs[0] = MINIMUM_TOOL_SIZE;
TextInputDescriptionArgs[1] = MAXIMUM_TOOL_SIZE;
window_text_input_open(w, WIDX_PREVIEW, 5128, 5129, STR_NONE, STR_NONE, 3);
}

View File

@ -188,8 +188,8 @@ static void window_land_rights_textinput(rct_window *w, int widgetIndex, char *t
static void window_land_rights_inputsize(rct_window *w)
{
((uint16*)TextInputDescriptionArgs)[0] = MINIMUM_TOOL_SIZE;
((uint16*)TextInputDescriptionArgs)[1] = MAXIMUM_TOOL_SIZE;
TextInputDescriptionArgs[0] = MINIMUM_TOOL_SIZE;
TextInputDescriptionArgs[1] = MAXIMUM_TOOL_SIZE;
window_text_input_open(w, WIDX_PREVIEW, 5128, 5129, STR_NONE, STR_NONE, 3);
}
@ -237,7 +237,7 @@ static void window_land_rights_paint(rct_window *w, rct_drawpixelinfo *dpi)
static int window_land_rights_should_close()
{
if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE))
if (!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE))
return 1;
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != WC_PARK_INFORMATION)
return 1;

View File

@ -144,8 +144,6 @@ static void window_loadsave_sort_list(int index, int endIndex);
static int has_extension(char *path, char *extension);
static void shorten_path(char* path, char* buffer, int available_width);
static rct_window *window_overwrite_prompt_open(const char *name, const char *path);
rct_window *window_loadsave_open(int type, char *defaultName)
@ -160,7 +158,6 @@ rct_window *window_loadsave_open(int type, char *defaultName)
if (!str_is_null_or_empty(defaultName)) {
safe_strncpy(_defaultName, defaultName, sizeof(_defaultName));
path_remove_extension(_defaultName);
}
w = window_bring_to_front_by_class(WC_LOADSAVE);
@ -221,21 +218,12 @@ rct_window *window_loadsave_open(int type, char *defaultName)
window_loadsave_populate_list(w, includeNewItem, path, ".sc6");
break;
case LOADSAVETYPE_SCENARIO:
/*
Uncomment when user scenarios are separated
platform_get_user_directory(path, "scenario");
if (!platform_ensure_directory_exists(path)) {
log_error("Unable to create scenarios directory.");
window_close(w);
return NULL;
log_error("Unable to create scenarios directory.");
window_close(w);
return NULL;
}
*/
safe_strncpy(path, RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char), MAX_PATH);
ch = strchr(path, '*');
if (ch != NULL)
*ch = 0;
window_loadsave_populate_list(w, includeNewItem, path, ".sc6");
break;
@ -306,12 +294,13 @@ static void window_loadsave_mouseup(rct_window *w, int widgetIndex)
}
case WIDX_BROWSE:
safe_strncpy(path, _directory, MAX_PATH);
if (_type & LOADSAVETYPE_SAVE)
strcat(path, (char*)RCT2_ADDRESS_SCENARIO_NAME);
if (_type & LOADSAVETYPE_SAVE) {
strcat(path, _defaultName);
}
memset(filter, '\0', MAX_PATH);
safe_strncpy(filter, "*", MAX_PATH);
strncat(filter, _extension, MAX_PATH);
strncat(filter, _extension, MAX_PATH - strnlen(filter, MAX_PATH) - 1);
switch (_type) {
case (LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME) :
@ -336,7 +325,7 @@ static void window_loadsave_mouseup(rct_window *w, int widgetIndex)
if (result) {
if (!has_extension(path, _extension)) {
strncat(path, _extension, MAX_PATH);
strncat(path, _extension, sizeof(path) - strnlen(path, sizeof(path)) - 1);
}
window_loadsave_select(w, path);
}
@ -480,8 +469,9 @@ static void window_loadsave_paint(rct_window *w, rct_drawpixelinfo *dpi)
{
window_draw_widgets(w, dpi);
if (_shortenedDirectory[0] == '\0')
shorten_path(_directory, _shortenedDirectory, w->width - 8);
if (_shortenedDirectory[0] == '\0') {
shorten_path(_shortenedDirectory, sizeof(_shortenedDirectory), _directory, w->width - 8);
}
utf8 buffer[256];
@ -510,41 +500,6 @@ static void window_loadsave_paint(rct_window *w, rct_drawpixelinfo *dpi)
gfx_draw_string_centred_clipped(dpi, STR_DATE, &id, 1, w->x + 4 + (w->width - 8) * 3 / 4, w->y + 50, (w->width - 8) / 2);
}
static void shorten_path(char* path, char* buffer, int available_width){
int length = strlen(path);
// Return full string if it fits
if (gfx_get_string_width(path) <= available_width){
strcpy(buffer, path);
return;
}
// Count path separators
int path_separators = 0;
for (int x = 0; x < length; x++)
if (path[x] == platform_get_path_separator())
path_separators++;
// TODO: Replace with unicode ellipsis when supported
strcpy(buffer, "...");
// Abreviate beginning with xth separator
int begin = -1;
for (int x = 0; x < path_separators; x++){
do {
begin++;
} while (path[begin] != platform_get_path_separator());
strcpy(buffer + 3, path + begin);
if (gfx_get_string_width(buffer) <= available_width)
return;
}
strcpy(buffer, path);
return;
}
static void window_loadsave_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex)
{
int i, y;
@ -684,7 +639,7 @@ static void window_loadsave_populate_list(rct_window *w, int includeNewItem, con
listItem = &_listItems[_listItemsCount];
memset(listItem->path, '\0', MAX_PATH);
safe_strncpy(listItem->path, directory, MAX_PATH);
strncat(listItem->path, subDir, MAX_PATH);
strncat(listItem->path, subDir, MAX_PATH - strnlen(listItem->path, MAX_PATH) - 1);
safe_strncpy(listItem->name, subDir, sizeof(listItem->name));
listItem->type = TYPE_DIRECTORY;
_listItemsCount++;
@ -700,7 +655,7 @@ static void window_loadsave_populate_list(rct_window *w, int includeNewItem, con
listItem = &_listItems[_listItemsCount];
safe_strncpy(listItem->path, directory, sizeof(listItem->path));
strncat(listItem->path, fileInfo.path, sizeof(listItem->path));
strncat(listItem->path, fileInfo.path, sizeof(listItem->path) - strnlen(listItem->path, MAX_PATH) - 1);
listItem->type = TYPE_FILE;
listItem->date_modified = platform_file_get_modified_time(listItem->path);

View File

@ -241,7 +241,7 @@ void window_map_open()
static void window_map_close(rct_window *w)
{
free(RCT2_GLOBAL(RCT2_ADDRESS_MAP_IMAGE_DATA, uint32*));
if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) &&
if ((gInputFlags & INPUT_FLAG_TOOL_ACTIVE) &&
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8) == w->classification &&
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, uint16) == w->number) {
tool_cancel();
@ -319,7 +319,7 @@ static void window_map_mouseup(rct_window *w, int widgetIndex)
break;
RCT2_GLOBAL(0x9E32D2, sint8) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
gInputFlags |= INPUT_FLAG_6;
show_gridlines();
show_land_rights();
@ -740,7 +740,7 @@ static void window_map_invalidate(rct_window *w)
if ((RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) || gCheatsSandboxMode) {
// scenario editor: build park entrance selected, show rotate button
if (
(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) &&
(gInputFlags & INPUT_FLAG_TOOL_ACTIVE) &&
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == WC_MAP &&
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == WIDX_BUILD_PARK_ENTRANCE
) {
@ -752,7 +752,7 @@ static void window_map_invalidate(rct_window *w)
// If any tool is active
if (
(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) &&
(gInputFlags & INPUT_FLAG_TOOL_ACTIVE) &&
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8) == WC_MAP
) {
// if not in set land rights mode: show the default scenario editor buttons
@ -935,15 +935,15 @@ static void window_map_show_default_scenario_editor_buttons(rct_window *w) {
static void window_map_inputsize_land(rct_window *w)
{
((uint16*)TextInputDescriptionArgs)[0] = MINIMUM_TOOL_SIZE;
((uint16*)TextInputDescriptionArgs)[1] = MAXIMUM_TOOL_SIZE;
TextInputDescriptionArgs[0] = MINIMUM_TOOL_SIZE;
TextInputDescriptionArgs[1] = MAXIMUM_TOOL_SIZE;
window_text_input_open(w, WIDX_LAND_TOOL, 5128, 5129, STR_NONE, STR_NONE, 3);
}
static void window_map_inputsize_map(rct_window *w)
{
((uint16*)TextInputDescriptionArgs)[0] = MINIMUM_MAP_SIZE_PRACTICAL;
((uint16*)TextInputDescriptionArgs)[1] = MAXIMUM_MAP_SIZE_PRACTICAL;
TextInputDescriptionArgs[0] = MINIMUM_MAP_SIZE_PRACTICAL;
TextInputDescriptionArgs[1] = MAXIMUM_MAP_SIZE_PRACTICAL;
window_text_input_open(w, WIDX_MAP_SIZE_SPINNER, 5130, 5131, STR_NONE, STR_NONE, 4);
}
@ -1028,7 +1028,7 @@ static void window_map_paint_peep_overlay(rct_drawpixelinfo *dpi)
color = 0x14;
if ((peep->var_0C & 0x200) != 0) {
if ((peep->list_flags & PEEP_LIST_FLAGS_FLASHING) != 0) {
if (peep->type == PEEP_TYPE_STAFF) {
if ((RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_MAP_FLASHING_FLAGS, uint16) & (1 << 3)) != 0) {
color = 0x8A;

View File

@ -81,7 +81,7 @@ void window_map_tooltip_update_visibility()
cursorX = RCT2_GLOBAL(0x0142406C, sint32);
cursorY = RCT2_GLOBAL(0x01424070, sint32);
inputFlags = RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32);
inputFlags = gInputFlags;
// Check for cursor movement
_cursorHoldDuration++;

View File

@ -488,19 +488,19 @@ static void window_mapgen_base_mouseup(rct_window *w, int widgetIndex)
gfx_invalidate_screen();
break;
case WIDX_MAP_SIZE:
((uint16*)TextInputDescriptionArgs)[0] = MINIMUM_MAP_SIZE_PRACTICAL;
((uint16*)TextInputDescriptionArgs)[1] = MAXIMUM_MAP_SIZE_PRACTICAL;
TextInputDescriptionArgs[0] = MINIMUM_MAP_SIZE_PRACTICAL;
TextInputDescriptionArgs[1] = MAXIMUM_MAP_SIZE_PRACTICAL;
// Practical map size is 2 lower than the technical map size
window_text_input_open(w, WIDX_MAP_SIZE, 5130, 5131, 5182, _mapSize - 2, 4);
break;
case WIDX_BASE_HEIGHT:
((uint16*)TextInputDescriptionArgs)[0] = (BASESIZE_MIN - 12) / 2;
((uint16*)TextInputDescriptionArgs)[1] = (BASESIZE_MAX - 12) / 2;
TextInputDescriptionArgs[0] = (BASESIZE_MIN - 12) / 2;
TextInputDescriptionArgs[1] = (BASESIZE_MAX - 12) / 2;
window_text_input_open(w, WIDX_BASE_HEIGHT, 5183, 5184, 5182, (_baseHeight - 12) / 2, 3);
break;
case WIDX_WATER_LEVEL:
((uint16*)TextInputDescriptionArgs)[0] = (WATERLEVEL_MIN - 12) / 2;
((uint16*)TextInputDescriptionArgs)[1] = (WATERLEVEL_MAX - 12) / 2;
TextInputDescriptionArgs[0] = (WATERLEVEL_MIN - 12) / 2;
TextInputDescriptionArgs[1] = (WATERLEVEL_MAX - 12) / 2;
window_text_input_open(w, WIDX_WATER_LEVEL, 5185, 5186, 5182, (_waterLevel - 12) / 2, 3);
break;
}
@ -583,7 +583,7 @@ static void window_mapgen_base_dropdown(rct_window *w, int widgetIndex, int drop
type = (dropdownIndex == -1) ?
_floorTexture :
*((uint32*)&gDropdownItemsArgs[dropdownIndex]) - SPR_FLOOR_TEXTURE_GRASS;
(uint32)gDropdownItemsArgs[dropdownIndex] - SPR_FLOOR_TEXTURE_GRASS;
if (RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_SURFACE, uint8) == type) {
RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_SURFACE, uint8) = 255;
@ -599,7 +599,7 @@ static void window_mapgen_base_dropdown(rct_window *w, int widgetIndex, int drop
type = (dropdownIndex == -1) ?
_wallTexture :
*((uint32*)&gDropdownItemsArgs[dropdownIndex]) - SPR_WALL_TEXTURE_ROCK;
(uint32)gDropdownItemsArgs[dropdownIndex] - SPR_WALL_TEXTURE_ROCK;
if (RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_EDGE, uint8) == type) {
RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_EDGE, uint8) = 255;
@ -790,8 +790,8 @@ static void window_mapgen_simplex_mouseup(rct_window *w, int widgetIndex)
window_mapgen_set_page(w, widgetIndex - WIDX_TAB_1);
break;
case WIDX_SIMPLEX_MAP_SIZE:
((uint16*)TextInputDescriptionArgs)[0] = MINIMUM_MAP_SIZE_PRACTICAL;
((uint16*)TextInputDescriptionArgs)[1] = MAXIMUM_MAP_SIZE_PRACTICAL;
TextInputDescriptionArgs[0] = MINIMUM_MAP_SIZE_PRACTICAL;
TextInputDescriptionArgs[1] = MAXIMUM_MAP_SIZE_PRACTICAL;
// Practical map size is 2 lower than the technical map size
window_text_input_open(w, WIDX_SIMPLEX_MAP_SIZE, 5130, 5131, 5182, _mapSize - 2, 4);
break;
@ -916,7 +916,7 @@ static void window_mapgen_simplex_dropdown(rct_window *w, int widgetIndex, int d
type = (dropdownIndex == -1) ?
_floorTexture :
*((uint32*)&gDropdownItemsArgs[dropdownIndex]) - SPR_FLOOR_TEXTURE_GRASS;
(uint32)gDropdownItemsArgs[dropdownIndex] - SPR_FLOOR_TEXTURE_GRASS;
if (RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_SURFACE, uint8) == type) {
RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_SURFACE, uint8) = 255;
@ -933,7 +933,7 @@ static void window_mapgen_simplex_dropdown(rct_window *w, int widgetIndex, int d
type = (dropdownIndex == -1) ?
_wallTexture :
*((uint32*)&gDropdownItemsArgs[dropdownIndex]) - SPR_WALL_TEXTURE_ROCK;
(uint32)gDropdownItemsArgs[dropdownIndex] - SPR_WALL_TEXTURE_ROCK;
if (RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_EDGE, uint8) == type) {
RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_TERRAIN_EDGE, uint8) = 255;

View File

@ -194,7 +194,7 @@ static void window_maze_construction_entrance_mouseup(rct_window *w, int widgetI
RCT2_GLOBAL(0x00F44191, uint8) = widgetIndex == WIDX_MAZE_ENTRANCE ? 0 : 1;
RCT2_GLOBAL(0x00F44192, uint8) = (uint8)w->number;
RCT2_GLOBAL(0x00F44193, uint8) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
gInputFlags |= INPUT_FLAG_6;
sub_6C9627();
@ -311,7 +311,7 @@ static void window_maze_construction_update(rct_window *w)
case RIDE_CONSTRUCTION_STATE_BACK:
case RIDE_CONSTRUCTION_STATE_SELECTED:
if (
(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) &&
(gInputFlags & INPUT_FLAG_TOOL_ACTIVE) &&
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == WC_RIDE_CONSTRUCTION
) {
tool_cancel();

View File

@ -344,7 +344,7 @@ static void window_news_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int s
}
}
uint32 image_id = *RCT2_ADDRESS(0x00982708, uint32*)[sprite_type * 2];
uint32 image_id = g_sprite_entries[sprite_type].sprite_image->base_image;
image_id += 0xA0000001;
image_id |= (peep->tshirt_colour << 19) | (peep->trousers_colour << 24);

View File

@ -135,6 +135,9 @@ enum WINDOW_OPTIONS_WIDGET_IDX {
WIDX_TOOLBAR_SHOW_CHEATS,
WIDX_TOOLBAR_SHOW_NEWS,
WIDX_SELECT_BY_TRACK_TYPE,
WIDX_SCENARIO_GROUPING,
WIDX_SCENARIO_GROUPING_DROPDOWN,
WIDX_SCENARIO_UNLOCKING,
// Misc
WIDX_REAL_NAME_CHECKBOX = WIDX_PAGE_START,
@ -162,7 +165,7 @@ enum WINDOW_OPTIONS_WIDGET_IDX {
};
#define WW 310
#define WH 280
#define WH 302
#define MAIN_OPTIONS_WIDGETS \
{ WWT_FRAME, 0, 0, WW-1, 0, WH-1, STR_NONE, STR_NONE }, \
@ -253,6 +256,9 @@ static rct_widget window_options_controls_and_interface_widgets[] = {
{ WWT_CHECKBOX, 2, 155, 299, 229, 240, STR_SHOW_RECENT_MESSAGES_ON_TOOLBAR, STR_NONE }, // Recent messages
{ WWT_CHECKBOX, 2, 10, 299, 254, 265, STR_SELECT_BY_TRACK_TYPE, STR_SELECT_BY_TRACK_TYPE_TIP }, // Select by track type
{ WWT_DROPDOWN, 2, 155, 299, 269, 280, STR_NONE, STR_NONE }, // Scenario select mode
{ WWT_DROPDOWN_BUTTON, 2, 288, 298, 270, 279, STR_DROPDOWN_GLYPH, STR_NONE },
{ WWT_CHECKBOX, 2, 18, 299, 284, 295, STR_OPTIONS_SCENARIO_UNLOCKING, STR_NONE }, // Unlocking of scenarios
{ WIDGETS_END },
};
@ -418,7 +424,10 @@ static uint32 window_options_page_enabled_widgets[] = {
(1 << WIDX_THEMES) |
(1 << WIDX_THEMES_DROPDOWN) |
(1 << WIDX_THEMES_BUTTON) |
(1 << WIDX_SELECT_BY_TRACK_TYPE),
(1 << WIDX_SELECT_BY_TRACK_TYPE) |
(1 << WIDX_SCENARIO_GROUPING) |
(1 << WIDX_SCENARIO_GROUPING_DROPDOWN) |
(1 << WIDX_SCENARIO_UNLOCKING),
MAIN_OPTIONS_ENABLED_WIDGETS |
(1 << WIDX_REAL_NAME_CHECKBOX) |
@ -642,6 +651,11 @@ static void window_options_mouseup(rct_window *w, int widgetIndex)
window_invalidate_by_class(WC_RIDE);
window_invalidate_by_class(WC_CONSTRUCT_RIDE);
break;
case WIDX_SCENARIO_UNLOCKING:
gConfigGeneral.scenario_unlocking_enabled ^= 1;
config_save_default();
window_close_by_class(WC_SCENARIO_SELECT);
break;
}
break;
@ -650,8 +664,7 @@ static void window_options_mouseup(rct_window *w, int widgetIndex)
case WIDX_DEBUGGING_TOOLS:
gConfigGeneral.debugging_tools ^= 1;
config_save_default();
window_invalidate(w);
window_invalidate_by_class(WC_TOP_TOOLBAR);
gfx_invalidate_screen();
break;
case WIDX_TEST_UNFINISHED_TRACKS:
gConfigGeneral.test_unfinished_tracks ^= 1;
@ -940,6 +953,27 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget*
dropdown_set_checked(gCurrentTheme, true);
}
break;
case WIDX_SCENARIO_GROUPING_DROPDOWN:
num_items = 2;
gDropdownItemsFormat[0] = 1142;
gDropdownItemsArgs[0] = STR_OPTIONS_SCENARIO_DIFFICULTY;
gDropdownItemsFormat[1] = 1142;
gDropdownItemsArgs[1] = STR_OPTIONS_SCENARIO_ORIGIN;
window_dropdown_show_text_custom_width(
w->x + widget->left,
w->y + widget->top,
widget->bottom - widget->top + 1,
w->colours[1],
DROPDOWN_FLAG_STAY_OPEN,
num_items,
widget->right - widget->left - 3
);
dropdown_set_checked(gConfigGeneral.scenario_select_mode, true);
break;
}
break;
@ -962,15 +996,14 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget*
gDropdownItemsArgs[i] = (uint32)&gConfigTitleSequences.presets[i].name;
}
window_dropdown_show_text_custom_width(
window_dropdown_show_text(
w->x + widget->left,
w->y + widget->top,
widget->bottom - widget->top + 1,
w->colours[1],
DROPDOWN_FLAG_STAY_OPEN,
num_items,
widget->right - widget->left - 3
);
num_items
);
dropdown_set_checked(gCurrentPreviewTitleSequence, true);
break;
@ -1139,6 +1172,14 @@ static void window_options_dropdown(rct_window *w, int widgetIndex, int dropdown
}
config_save_default();
break;
case WIDX_SCENARIO_GROUPING_DROPDOWN:
if (dropdownIndex != gConfigGeneral.scenario_select_mode) {
gConfigGeneral.scenario_select_mode = dropdownIndex;
config_save_default();
window_invalidate(w);
window_close_by_class(WC_SCENARIO_SELECT);
}
break;
}
break;
@ -1320,6 +1361,13 @@ static void window_options_invalidate(rct_window *w)
widget_set_checkbox_value(w, WIDX_TOOLBAR_SHOW_CHEATS, gConfigInterface.toolbar_show_cheats);
widget_set_checkbox_value(w, WIDX_TOOLBAR_SHOW_NEWS, gConfigInterface.toolbar_show_news);
widget_set_checkbox_value(w, WIDX_SELECT_BY_TRACK_TYPE, gConfigInterface.select_by_track_type);
widget_set_checkbox_value(w, WIDX_SCENARIO_UNLOCKING, gConfigGeneral.scenario_unlocking_enabled);
if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN) {
w->disabled_widgets &= ~(1ULL << WIDX_SCENARIO_UNLOCKING);
} else {
w->disabled_widgets |= (1ULL << WIDX_SCENARIO_UNLOCKING);
}
window_options_controls_and_interface_widgets[WIDX_THEMES].type = WWT_DROPDOWN;
window_options_controls_and_interface_widgets[WIDX_THEMES_DROPDOWN].type = WWT_DROPDOWN_BUTTON;
@ -1332,6 +1380,8 @@ static void window_options_invalidate(rct_window *w)
window_options_controls_and_interface_widgets[WIDX_TOOLBAR_SHOW_CHEATS].type = WWT_CHECKBOX;
window_options_controls_and_interface_widgets[WIDX_TOOLBAR_SHOW_NEWS].type = WWT_CHECKBOX;
window_options_controls_and_interface_widgets[WIDX_SELECT_BY_TRACK_TYPE].type = WWT_CHECKBOX;
window_options_controls_and_interface_widgets[WIDX_SCENARIO_GROUPING].type = WWT_DROPDOWN;
window_options_controls_and_interface_widgets[WIDX_SCENARIO_UNLOCKING].type = WWT_CHECKBOX;
break;
case WINDOW_OPTIONS_PAGE_MISC:
@ -1386,6 +1436,15 @@ static void window_options_invalidate(rct_window *w)
window_options_twitch_widgets[WIDX_NEWS_CHECKBOX].type = WWT_CHECKBOX;
break;
}
// Automatically adjust window height to fit widgets
int y = 0;
for (widget = &w->widgets[WIDX_PAGE_START]; widget->type != WWT_LAST; widget++) {
y = max(y, widget->bottom);
}
w->height = y + 6;
w->widgets[WIDX_BACKGROUND].bottom = w->height - 1;
w->widgets[WIDX_PAGE_BACKGROUND].bottom = w->height - 1;
}
static void window_options_update(rct_window *w)
@ -1481,7 +1540,19 @@ static void window_options_paint(rct_window *w, rct_drawpixelinfo *dpi)
w->x + window_options_controls_and_interface_widgets[WIDX_THEMES].left + 1,
w->y + window_options_controls_and_interface_widgets[WIDX_THEMES].top,
window_options_controls_and_interface_widgets[WIDX_THEMES_DROPDOWN].left - window_options_controls_and_interface_widgets[WIDX_THEMES].left - 4
);
);
gfx_draw_string_left(dpi, STR_OPTIONS_SCENARIO_GROUPING, NULL, w->colours[1], w->x + 10, w->y + window_options_controls_and_interface_widgets[WIDX_SCENARIO_GROUPING].top + 1);
gfx_draw_string_left_clipped(
dpi,
gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_DIFFICULTY ?
STR_OPTIONS_SCENARIO_DIFFICULTY :
STR_OPTIONS_SCENARIO_ORIGIN,
NULL,
w->colours[1],
w->x + window_options_controls_and_interface_widgets[WIDX_SCENARIO_GROUPING].left + 1,
w->y + window_options_controls_and_interface_widgets[WIDX_SCENARIO_GROUPING].top,
window_options_controls_and_interface_widgets[WIDX_SCENARIO_GROUPING_DROPDOWN].left - window_options_controls_and_interface_widgets[WIDX_SCENARIO_GROUPING].left - 4
);
break;
case WINDOW_OPTIONS_PAGE_MISC:
gfx_draw_string_left(dpi, 2700, w, w->colours[1], w->x + 10, w->y + window_options_misc_widgets[WIDX_AUTOSAVE].top + 1);

View File

@ -612,7 +612,7 @@ void window_park_entrance_open()
*/
static void window_park_entrance_close(rct_window *w)
{
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)
if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE)
if (w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) && w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber))
tool_cancel();
}
@ -1124,14 +1124,14 @@ static void window_park_init_viewport(rct_window *w)
void toggle_land_rights_window(rct_window *parkWindow, int widgetIndex)
{
if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8) == WC_PARK_INFORMATION &&
if ((gInputFlags & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8) == WC_PARK_INFORMATION &&
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == WIDX_BUY_LAND_RIGHTS) {
tool_cancel();
}
else {
show_gridlines();
tool_set(parkWindow, widgetIndex, 2);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
gInputFlags |= INPUT_FLAG_6;
RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = 1;
window_land_rights_open();
}
@ -1156,7 +1156,7 @@ void window_park_rating_open()
window->viewport_focus_coordinates.y = -1;
}
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)
if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE)
if (window->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) && window->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber))
tool_cancel();
@ -1272,7 +1272,7 @@ void window_park_guests_open()
window->viewport_focus_coordinates.y = -1;
}
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)
if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE)
if (window->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) && window->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber))
tool_cancel();
@ -1630,7 +1630,7 @@ void window_park_objective_open()
window->viewport_focus_coordinates.y = -1;
}
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)
if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE)
if (window->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) && window->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber))
tool_cancel();
@ -1795,7 +1795,7 @@ void window_park_awards_open()
window->viewport_focus_coordinates.y = -1;
}
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)
if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE)
if (window->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) && window->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber))
tool_cancel();
@ -1907,7 +1907,7 @@ static void window_park_set_page(rct_window *w, int page)
{
int listen;
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)
if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE)
if (w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) && w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber))
tool_cancel();
@ -1982,7 +1982,7 @@ static void window_park_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w)
sprite_idx += (w->frame_no / 8) % 8;
gfx_draw_sprite(dpi, sprite_idx, w->x + w->widgets[WIDX_TAB_3].left, w->y + w->widgets[WIDX_TAB_3].top, 0);
sprite_idx = *RCT2_GLOBAL(0x00982708, sint32*) + 1;
sprite_idx = g_sprite_entries[0].sprite_image->base_image + 1;
if (w->page == WINDOW_PARK_PAGE_GUESTS)
sprite_idx += w->var_492 & 0xFFFFFFFC;

View File

@ -1086,7 +1086,7 @@ static void window_ride_draw_tab_customer(rct_drawpixelinfo *dpi, rct_window *w)
if (w->page == WINDOW_RIDE_PAGE_CUSTOMER)
spriteIndex = w->var_492 & ~3;
spriteIndex += RCT2_GLOBAL(RCT2_GLOBAL(0x00982708, uint32), uint32);
spriteIndex += g_sprite_entries[0].sprite_image->base_image;
spriteIndex += 1;
spriteIndex |= 0xA9E00000;
@ -1183,7 +1183,7 @@ rct_window *window_ride_open(int rideIndex)
w->frame_no = 0;
w->list_information_type = 0;
w->var_492 = 0;
w->highlighted_item = 0;
w->ride_colour = 0;
window_ride_disable_tabs(w);
w->min_width = 316;
w->min_height = 180;
@ -1219,7 +1219,7 @@ rct_window *window_ride_main_open(int rideIndex)
w->ride.var_482 = -1;
}
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) {
if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) {
if (w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) &&
w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber)
) {
@ -1266,7 +1266,7 @@ rct_window *window_ride_open_station(int rideIndex, int stationIndex)
}
if (
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE &&
gInputFlags & INPUT_FLAG_TOOL_ACTIVE &&
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == w->classification &&
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) == w->number
) {
@ -1345,7 +1345,7 @@ rct_window *window_ride_open_vehicle(rct_vehicle *vehicle)
window_invalidate(w);
if (
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE &&
gInputFlags & INPUT_FLAG_TOOL_ACTIVE &&
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == w->classification &&
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) == w->number
) {
@ -1410,7 +1410,7 @@ static void window_ride_set_page(rct_window *w, int page)
{
int listen;
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)
if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE)
if (w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) && w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber))
tool_cancel();
@ -3727,7 +3727,7 @@ static void window_ride_set_track_colour_scheme(rct_window *w, int x, int y)
uint8 newColourScheme;
int interactionType, z, direction;
newColourScheme = (uint8)(*((uint16*)&w->highlighted_item));
newColourScheme = (uint8)w->ride_colour;
rct_xy16 mapCoord = { 0 };
get_map_coordinates_from_pos(x, y, VIEWPORT_INTERACTION_MASK_RIDE, &mapCoord.x, &mapCoord.y, &interactionType, &mapElement, NULL);
@ -3752,7 +3752,7 @@ static void window_ride_set_track_colour_scheme(rct_window *w, int x, int y)
*/
static void window_ride_colour_close(rct_window *w)
{
if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE))
if (!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE))
return;
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != w->classification)
@ -3817,7 +3817,7 @@ static void window_ride_colour_mousedown(int widgetIndex, rct_window *w, rct_wid
ride = GET_RIDE(w->number);
rideEntry = ride_get_entry(ride);
colourSchemeIndex = *((uint16*)&w->highlighted_item);
colourSchemeIndex = w->ride_colour;
dropdownWidget = widget - 1;
switch (widgetIndex) {
@ -3957,20 +3957,20 @@ static void window_ride_colour_dropdown(rct_window *w, int widgetIndex, int drop
switch (widgetIndex) {
case WIDX_TRACK_COLOUR_SCHEME_DROPDOWN:
*((uint16*)&w->highlighted_item) = dropdownIndex;
w->ride_colour = (uint16)dropdownIndex;
window_invalidate(w);
break;
case WIDX_TRACK_MAIN_COLOUR:
game_do_command(0, (0 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, *((uint16*)&w->highlighted_item), 0);
game_do_command(0, (0 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->ride_colour, 0);
break;
case WIDX_TRACK_ADDITIONAL_COLOUR:
game_do_command(0, (1 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, *((uint16*)&w->highlighted_item), 0);
game_do_command(0, (1 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->ride_colour, 0);
break;
case WIDX_TRACK_SUPPORT_COLOUR:
game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, *((uint16*)&w->highlighted_item), 0);
game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->ride_colour, 0);
break;
case WIDX_MAZE_STYLE_DROPDOWN:
game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, *((uint16*)&w->highlighted_item), 0);
game_do_command(0, (4 << 8) | 1, 0, (dropdownIndex << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, w->ride_colour, 0);
break;
case WIDX_ENTRANCE_STYLE_DROPDOWN:
game_do_command(0, (6 << 8) | 1, 0, (window_ride_entrance_style_list[dropdownIndex] << 8) | w->number, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0);
@ -4057,7 +4057,7 @@ static void window_ride_colour_invalidate(rct_window *w)
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->name_arguments;
// Track colours
int colourScheme = *((uint16*)&w->highlighted_item);
int colourScheme = w->ride_colour;
trackColour = ride_get_track_colour(ride, colourScheme);
// Maze style
@ -4226,7 +4226,7 @@ static void window_ride_colour_paint(rct_window *w, rct_drawpixelinfo *dpi)
if (widget->type != WWT_EMPTY)
gfx_fill_rect(dpi, w->x + widget->left + 1, w->y + widget->top + 1, w->x + widget->right - 1, w->y + widget->bottom - 1, 12);
trackColour = ride_get_track_colour(ride, *((uint16*)&w->highlighted_item));
trackColour = ride_get_track_colour(ride, w->ride_colour);
//
if (rideEntry->shop_item == 0xFF) {

View File

@ -1873,7 +1873,7 @@ static void window_ride_construction_entrance_click(rct_window *w)
RCT2_GLOBAL(0x00F44191, uint8) = 0;
RCT2_GLOBAL(0x00F44192, uint8) = w->number & 0xFF;
RCT2_GLOBAL(0x00F44193, uint8) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
gInputFlags |= INPUT_FLAG_6;
sub_6C9627();
if (_rideConstructionState != RIDE_CONSTRUCTION_STATE_ENTRANCE_EXIT) {
RCT2_GLOBAL(0x00F440CC, uint8) = _rideConstructionState;
@ -1897,7 +1897,7 @@ static void window_ride_construction_exit_click(rct_window *w)
RCT2_GLOBAL(0x00F44191, uint8) = 1;
RCT2_GLOBAL(0x00F44192, uint8) = w->number & 0xFF;
RCT2_GLOBAL(0x00F44193, uint8) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
gInputFlags |= INPUT_FLAG_6;
sub_6C9627();
if (_rideConstructionState != RIDE_CONSTRUCTION_STATE_ENTRANCE_EXIT) {
RCT2_GLOBAL(0x00F440CC, uint8) = _rideConstructionState;
@ -1941,7 +1941,7 @@ static void window_ride_construction_update(rct_window *w)
case RIDE_CONSTRUCTION_STATE_BACK:
case RIDE_CONSTRUCTION_STATE_SELECTED:
if (
(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) &&
(gInputFlags & INPUT_FLAG_TOOL_ACTIVE) &&
RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == WC_RIDE_CONSTRUCTION
) {
tool_cancel();
@ -3569,7 +3569,7 @@ void ride_construction_tooldown_construct(int screenX, int screenY)
w = window_find_by_class(WC_RIDE_CONSTRUCTION);
if (w != NULL){
tool_set(w, 23, 12);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= (1 << 6);
gInputFlags |= INPUT_FLAG_6;
RCT2_GLOBAL(0x00F44159, uint8) = 0;
RCT2_GLOBAL(0x00F4415C, uint8) = 0;
}

View File

@ -286,7 +286,7 @@ static void window_ride_list_dropdown(rct_window *w, int widgetIndex, int dropdo
if (dropdownIndex == -1)
return;
_window_ride_list_information_type = *((uint32*)&gDropdownItemsArgs[dropdownIndex]) - STR_STATUS;
_window_ride_list_information_type = (uint32)gDropdownItemsArgs[dropdownIndex] - STR_STATUS;
window_invalidate(w);
}
}

View File

@ -28,7 +28,6 @@
#include "../interface/window.h"
#include "../openrct2.h"
#include "../sprites.h"
#include "../tutorial.h"
enum WINDOW_SAVE_PROMPT_WIDGET_IDX {
WIDX_BACKGROUND,
@ -134,19 +133,6 @@ void window_save_prompt_open()
* and game_load_or_quit() are not called by the original binary anymore.
*/
if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) != 0) {
if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) != 1) {
sub_66EE54();
game_load_or_quit_no_save_prompt();
return;
}
else {
tutorial_stop();
game_load_or_quit_no_save_prompt();
return;
}
}
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_AGE, uint16) < 3840) {
game_load_or_quit_no_save_prompt();
return;
@ -249,18 +235,6 @@ static void window_save_prompt_mouseup(rct_window *w, int widgetIndex)
return;
}
}
if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) != 0) {
if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) != 1) {
sub_66EE54();
game_load_or_quit_no_save_prompt();
return;
} else {
tutorial_stop();
game_load_or_quit_no_save_prompt();
return;
}
}
}
static void window_save_prompt_invalidate(rct_window *w)

View File

@ -490,7 +490,7 @@ bool window_scenery_is_scenery_tool_active() {
int toolWindowClassification = RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass);
int toolWidgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16);
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)
if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE)
if (toolWindowClassification == WC_TOP_TOOLBAR && toolWidgetIndex == 9) // 9 is WIDX_SCENERY
return true;
@ -693,7 +693,7 @@ static void window_scenery_update(rct_window *w)
if (widgetIndex >= WIDX_SCENERY_TAB_CONTENT_PANEL) {
w->scenery.hover_counter++;
if (w->scenery.hover_counter < 8) {
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, sint8) != INPUT_STATE_SCROLL_LEFT) {
if (gInputState != INPUT_STATE_SCROLL_LEFT) {
w->min_width = WINDOW_SCENERY_WIDTH;
w->max_width = WINDOW_SCENERY_WIDTH;
w->min_height = WINDOW_SCENERY_HEIGHT;
@ -713,7 +713,7 @@ static void window_scenery_update(rct_window *w)
}
} else {
w->scenery.hover_counter = 0;
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, sint8) != INPUT_STATE_SCROLL_LEFT) {
if (gInputState != INPUT_STATE_SCROLL_LEFT) {
w->min_width = WINDOW_SCENERY_WIDTH;
w->max_width = WINDOW_SCENERY_WIDTH;
w->min_height = WINDOW_SCENERY_HEIGHT;

View File

@ -369,7 +369,7 @@ void window_staff_disable_widgets(rct_window* w)
*/
void window_staff_overview_close(rct_window *w)
{
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE){
if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE){
if (w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) &&
w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber))
tool_cancel();
@ -382,7 +382,7 @@ void window_staff_overview_close(rct_window *w)
*/
void window_staff_set_page(rct_window* w, int page)
{
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)
if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE)
{
if(w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) &&
w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass))
@ -449,7 +449,7 @@ void window_staff_overview_mouseup(rct_window *w, int widgetIndex)
return;
}
w->var_48C = peep->x;
w->picked_peep_old_x = peep->x;
remove_peep_from_ride(peep);
invalidate_sprite_2((rct_sprite*)peep);
@ -987,7 +987,7 @@ void window_staff_overview_tab_paint(rct_window* w, rct_drawpixelinfo* dpi)
if (peep->type == PEEP_TYPE_STAFF && peep->staff_type == STAFF_TYPE_ENTERTAINER)
y++;
int ebx = *(RCT2_ADDRESS(0x982708, uint32*)[peep->sprite_type * 2]) + 1;
int ebx = g_sprite_entries[peep->sprite_type].sprite_image->base_image + 1;
int eax = 0;
@ -1096,7 +1096,7 @@ void window_staff_overview_tool_update(rct_window* w, int widgetIndex, int x, in
if (widgetIndex != WIDX_PICKUP)
return;
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, sint32) = -1;
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, sint32) = -1;
int interactionType;
get_map_coordinates_from_pos(x, y, VIEWPORT_INTERACTION_MASK_NONE, NULL, NULL, &interactionType, NULL, NULL);
@ -1107,16 +1107,19 @@ void window_staff_overview_tool_update(rct_window* w, int widgetIndex, int x, in
y += 16;
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_X, uint16) = x;
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_Y, uint16) = y;
w->var_492++;
if (w->var_492 >= 48)w->var_492 = 0;
w->picked_peep_frame++;
if (w->picked_peep_frame >= 48) {
w->picked_peep_frame = 0;
}
rct_peep* peep;
peep = GET_PEEP(w->number);
int sprite_idx = (RCT2_ADDRESS(0x982708, uint32*)[peep->sprite_type * 2])[22];
sprite_idx += w->var_492 >> 2;
sprite_idx |= (peep->tshirt_colour << 19) | (peep->trousers_colour << 24) | 0xA0000000;
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, uint32) = sprite_idx;
uint32 imageId = g_sprite_entries[peep->sprite_type].sprite_image[11].base_image;
imageId += w->picked_peep_frame >> 2;
imageId |= (peep->tshirt_colour << 19) | (peep->trousers_colour << 24) | 0xA0000000;
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, uint32) = imageId;
}
/**
@ -1163,7 +1166,7 @@ void window_staff_overview_tool_down(rct_window* w, int widgetIndex, int x, int
peep->state = PEEP_STATE_FALLING;
peep_window_state_update(peep);
peep->action = 0xFF;
peep->var_6D = 0;
peep->special_sprite = 0;
peep->action_sprite_image_offset = 0;
peep->action_sprite_type = 0;
peep->var_C4 = 0;
@ -1191,7 +1194,7 @@ void window_staff_overview_tool_abort(rct_window *w, int widgetIndex)
rct_peep* peep = GET_PEEP(w->number);
if (peep->state != PEEP_STATE_PICKED) return;
sprite_move(w->var_48C, peep->y, peep->z + 8, (rct_sprite*)peep);
sprite_move(w->picked_peep_old_x, peep->y, peep->z + 8, (rct_sprite*)peep);
invalidate_sprite_2((rct_sprite*)peep);
if (peep->x != (sint16)0x8000){
@ -1199,13 +1202,13 @@ void window_staff_overview_tool_abort(rct_window *w, int widgetIndex)
peep->state = PEEP_STATE_FALLING;
peep_window_state_update(peep);
peep->action = 0xFF;
peep->var_6D = 0;
peep->special_sprite = 0;
peep->action_sprite_image_offset = 0;
peep->action_sprite_type = 0;
peep->var_C4 = 0;
}
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, sint32) = -1;
RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, sint32) = -1;
}
else if (widgetIndex == WIDX_PATROL){
hide_gridlines();

View File

@ -181,7 +181,7 @@ void window_staff_list_open()
void window_staff_list_cancel_tools(rct_window *w) {
int toolWindowClassification = RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass);
int toolWindowNumber = RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber);
if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE)
if (gInputFlags & INPUT_FLAG_TOOL_ACTIVE)
if (w->classification == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) && w->number == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber))
tool_cancel();
}
@ -310,10 +310,10 @@ void window_staff_list_update(rct_window *w)
RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_MAP_FLASHING_FLAGS, uint16) |= (1 << 2);
FOR_ALL_PEEPS(spriteIndex, peep) {
if (peep->type == PEEP_TYPE_STAFF) {
peep->var_0C &= ~0x200;
peep->list_flags &= ~(PEEP_LIST_FLAGS_FLASHING);
if (peep->staff_type == RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_STAFF_LIST_SELECTED_TAB, uint8)) {
peep->var_0C |= 0x200;
peep->list_flags |= PEEP_LIST_FLAGS_FLASHING;
}
}
}

View File

@ -26,31 +26,76 @@
#include "../world/scenery.h"
#include "../world/map.h"
#include "../world/footpath.h"
#include "../sprites.h"
enum WINDOW_TILE_INSPECTOR_WIDGET_IDX {
WIDX_BACKGROUND,
WIDX_TITLE,
WIDX_CLOSE,
WIDX_LIST,
WIDX_CORRUPT,
WIDX_CONTENT_PANEL,
WIDX_SCROLL
WIDX_REMOVE,
WIDX_MOVE_DOWN,
WIDX_MOVE_UP,
WIDX_COLUMN_TYPE,
WIDX_COLUMN_BASEHEIGHT,
WIDX_COLUMN_CLEARANCEHEIGHT,
WIDX_COLUMN_GHOSTFLAG,
WIDX_COLUMN_BROKENFLAG,
WIDX_COLUMN_LASTFLAG,
};
#define WW 500
#define WH 400
#define WW 400
#define WH 200
#define MIN_WW WW
#define MAX_WW WW
#define MIN_WH 150
#define MAX_WH 800
#define BW (WW - 5) // Button's right side
#define BX (BW - 23) // Button's left side
#define BY 17 // Button's Top
#define BH (BY + 23) // Button's Bottom
#define BS 24
#define SCROLL_BOTTOM_OFFSET 15
#define LIST_ITEM_HEIGHT 11
// Column offsets
#define COL_X_TYPE 3 // Type
#define COL_X_BH (COL_X_TYPE + 300) // Base height
#define COL_X_CH (COL_X_BH + 20) // Clearance height
#define COL_X_GF (COL_X_CH + 20) // Ghost flag
#define COL_X_BF (COL_X_GF + 12) // Broken flag
#define COL_X_LF (COL_X_BF + 12) // Last for tile flag
rct_widget window_tile_inspector_widgets[] = {
{ WWT_FRAME, 0, 0, WW - 1, 0, WH - 1, 0x0FFFFFFFF, STR_NONE }, // panel / background
{ WWT_CAPTION, 0, 1, WW - 2, 1, 14, STR_TILE_INSPECTOR_TITLE, STR_WINDOW_TITLE_TIP }, // title bar
{ WWT_CLOSEBOX, 0, WW - 13, WW - 3, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button
{ WWT_CLOSEBOX, 1, WW - 150, WW - 3, 18, 39, STR_INSERT_CORRUPT, STR_INSERT_CORRUPT_TIP },
{ WWT_RESIZE, 1, 0, WW - 1, 43, WH - 1, 0x0FFFFFFFF, STR_NONE }, // content panel
{ WWT_SCROLL, 1, 3, WW - 3, 65, WH - 30, 2, STR_NONE }, // scroll area
{ WWT_FRAME, 0, 0, WW - 1, 0, WH - 1, 0x0FFFFFFFF, STR_NONE }, // panel / background
{ WWT_CAPTION, 0, 1, WW - 2, 1, 14, STR_TILE_INSPECTOR_TITLE, STR_WINDOW_TITLE_TIP }, // title bar
{ WWT_CLOSEBOX, 0, WW - 13, WW - 3, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button
// Map element list
{ WWT_SCROLL, 1, 3, WW - 4, 57, WH - SCROLL_BOTTOM_OFFSET, 2, STR_NONE }, // scroll area
// Buttons
{ WWT_FLATBTN, 1, BX, BW, BY, BH, SPR_MAP, STR_INSERT_CORRUPT_TIP }, // Insert corrupt button
{ WWT_FLATBTN, 1, BX - BS * 1, BW - BS * 1, BY, BH, SPR_DEMOLISH, 5607 }, // Remove button
{ WWT_CLOSEBOX, 1, BX - BS * 2, BW - BS * 2, BY, BY + 11, 5375, 5617 }, // Move down
{ WWT_CLOSEBOX, 1, BX - BS * 2, BW - BS * 2, BH - 11, BH, 5376, 5618 }, // Move up
// Column headers
{ WWT_13, 1, COL_X_TYPE, COL_X_BH - 1, 42, 42 + 13, STR_NONE, STR_NONE }, // Type
{ WWT_13, 1, COL_X_BH, COL_X_CH - 1, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_BASE_HEIGHT }, // Base height
{ WWT_13, 1, COL_X_CH, COL_X_GF - 1, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_CLEARANCE_HEIGHT }, // Clearance height
{ WWT_13, 1, COL_X_GF, COL_X_BF - 1, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_FLAG_GHOST }, // Ghost flag
{ WWT_13, 1, COL_X_BF, COL_X_LF - 1, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_FLAG_BROKEN }, // Broken flag
{ WWT_13, 1, COL_X_LF, WW - 3, 42, 42 + 13, STR_NONE, STR_TILE_INSPECTOR_FLAG_LAST }, // Last of tile flag
{ WIDGETS_END },
};
static sint16 window_tile_inspector_highlighted_index = -1;
static int window_tile_inspector_tile_x;
static int window_tile_inspector_tile_y;
static int window_tile_inspector_item_count;
@ -58,15 +103,19 @@ static int window_tile_inspector_item_count;
static void window_tile_inspector_close(rct_window *w);
static void window_tile_inspector_mouseup(rct_window *w, int widgetIndex);
static void window_tile_inspector_resize(rct_window *w);
static void window_title_editor_update(rct_window *w);
static void window_tile_inspector_tool_update(rct_window* w, int widgetIndex, int x, int y);
static void window_tile_inspector_tool_down(rct_window* w, int widgetIndex, int x, int y);
static void window_tile_inspector_tool_abort(rct_window *w, int widgetIndex);
static void window_tile_inspector_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height);
static void window_tile_inspector_scrollmousedown(rct_window *w, int scrollIndex, int x, int y);
static void window_tile_inspector_scrollmouseover(rct_window *w, int scrollIndex, int x, int y);
static void window_tile_inspector_invalidate(rct_window *w);
static void window_tile_inspector_paint(rct_window *w, rct_drawpixelinfo *dpi);
static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex);
static void window_tile_inspector_auto_set_buttons(rct_window *w);
static rct_window_event_list window_tile_inspector_events = {
window_tile_inspector_close,
window_tile_inspector_mouseup,
@ -74,7 +123,7 @@ static rct_window_event_list window_tile_inspector_events = {
NULL,
NULL,
NULL,
NULL,
window_title_editor_update,
NULL,
NULL,
window_tile_inspector_tool_update,
@ -84,7 +133,7 @@ static rct_window_event_list window_tile_inspector_events = {
window_tile_inspector_tool_abort,
NULL,
window_tile_inspector_scrollgetsize,
NULL,
window_tile_inspector_scrollmousedown,
NULL,
window_tile_inspector_scrollmouseover,
NULL,
@ -118,16 +167,17 @@ void window_tile_inspector_open()
);
window->widgets = window_tile_inspector_widgets;
window->enabled_widgets = (1 << WIDX_CLOSE);
window->disabled_widgets = (1 << WIDX_CORRUPT);
window->disabled_widgets = (1 << WIDX_CORRUPT) | (1 << WIDX_MOVE_UP) | (1 << WIDX_MOVE_DOWN) | (1 << WIDX_REMOVE);
window_init_scroll_widgets(window);
window->colours[0] = 7;
window->colours[1] = 7;
window->colours[2] = 7;
window->min_width = WW;
window->min_width = MIN_WW;
window->min_height = MIN_WH;
window->max_width = WW;
window->max_width = MAX_WW;
window->max_height = MAX_WH;
window->selected_list_item = -1;
window_tile_inspector_tile_x = -1;
window_tile_inspector_tile_y = -1;
@ -151,6 +201,50 @@ void corrupt_element(int x, int y) {
mapElement->type = (8 << 2);
}
void remove_element(int index)
{
assert(index < window_tile_inspector_item_count);
rct_map_element *mapElement = map_get_first_element_at(window_tile_inspector_tile_x, window_tile_inspector_tile_y);
mapElement += index;
map_element_remove(mapElement);
window_tile_inspector_item_count--;
}
// Swap element with its parent
void swap_elements(sint16 first, sint16 second)
{
rct_map_element *mapElement;
rct_map_element *firstElement = NULL;
rct_map_element *secondElement = NULL;
mapElement = map_get_first_element_at(window_tile_inspector_tile_x, window_tile_inspector_tile_y);
// swap_elements shouldn't be called when there is only one element on the tile
assert(!map_element_is_last_for_tile(mapElement));
// Search for the elements
sint16 i = 0;
do {
if (i == first) firstElement = mapElement;
if (i == second) secondElement = mapElement;
i++;
// Check if both elements have been found
if (firstElement != NULL && secondElement != NULL)
break;
} while (!map_element_is_last_for_tile(mapElement++));
// Swap their memory
rct_map_element temp = *firstElement;
*firstElement = *secondElement;
*secondElement = temp;
// Swap the 'last map element for tile' flag if either one of them was last
if (map_element_is_last_for_tile(firstElement) || map_element_is_last_for_tile(secondElement)) {
firstElement->flags ^= MAP_ELEMENT_FLAG_LAST_TILE;
secondElement->flags ^= MAP_ELEMENT_FLAG_LAST_TILE;
}
}
static void window_tile_inspector_mouseup(rct_window *w, int widgetIndex)
{
switch (widgetIndex) {
@ -159,9 +253,28 @@ static void window_tile_inspector_mouseup(rct_window *w, int widgetIndex)
break;
case WIDX_CORRUPT:
corrupt_element(window_tile_inspector_tile_x, window_tile_inspector_tile_y);
window_tile_inspector_item_count++;
w->scrolls[0].v_top = 0;
window_invalidate(w);
w->selected_list_item = window_tile_inspector_item_count++;
window_tile_inspector_auto_set_buttons(w);
widget_invalidate(w, WIDX_LIST);
break;
case WIDX_REMOVE:
remove_element(w->selected_list_item);
w->selected_list_item = -1;
window_tile_inspector_auto_set_buttons(w);
widget_invalidate(w, WIDX_LIST);
break;
case WIDX_MOVE_DOWN:
swap_elements(w->selected_list_item, w->selected_list_item + 1);
w->selected_list_item++;
window_tile_inspector_auto_set_buttons(w);
widget_invalidate(w, WIDX_LIST);
break;
case WIDX_MOVE_UP:
swap_elements(w->selected_list_item - 1, w->selected_list_item);
w->selected_list_item--;
window_tile_inspector_auto_set_buttons(w);
widget_invalidate(w, WIDX_LIST);
break;
}
}
@ -180,6 +293,16 @@ static void window_tile_inspector_resize(rct_window *w)
}
}
static void window_title_editor_update(rct_window *w)
{
// Check if the mouse is hovering over the list
if (!widget_is_highlighted(w, WIDX_LIST))
{
window_tile_inspector_highlighted_index = -1;
widget_invalidate(w, WIDX_LIST);
}
}
static void window_tile_inspector_tool_update(rct_window* w, int widgetIndex, int x, int y)
{
int direction;
@ -229,8 +352,13 @@ static void window_tile_inspector_tool_down(rct_window* w, int widgetIndex, int
window_tile_inspector_item_count = numItems;
// Enable 'insert corrupt element' button
w->enabled_widgets |= (1 << WIDX_CORRUPT);
w->disabled_widgets &= ~(1ULL << WIDX_CORRUPT);
// undo selection and buttons affecting it
w->selected_list_item = -1;
w->disabled_widgets |= (1ULL << WIDX_MOVE_UP) | (1ULL << WIDX_MOVE_DOWN) | (1ULL << WIDX_REMOVE);
w->enabled_widgets &= ~((1ULL << WIDX_MOVE_UP) | (1ULL << WIDX_MOVE_DOWN) | (1ULL << WIDX_REMOVE));
w->scrolls[0].v_top = 0;
window_invalidate(w);
@ -244,12 +372,63 @@ static void window_tile_inspector_tool_abort(rct_window *w, int widgetIndex)
static void window_tile_inspector_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height)
{
*width = WW - 30;
*height = window_tile_inspector_item_count * 11;
*height = window_tile_inspector_item_count * LIST_ITEM_HEIGHT;
}
static void window_tile_inspector_auto_set_buttons(rct_window *w)
{
// Remove button
if (w->selected_list_item == -1) { // Check if anything is selected
w->disabled_widgets |= (1ULL << WIDX_REMOVE);
w->enabled_widgets &= ~(1ULL << WIDX_REMOVE);
} else { // Nothing is selected
w->disabled_widgets &= ~(1ULL << WIDX_REMOVE);
w->enabled_widgets |= (1ULL << WIDX_REMOVE);
}
widget_invalidate(w, WIDX_REMOVE);
// Move Up button
if (w->selected_list_item <= 0) { // Top element in list, or -1
w->disabled_widgets |= (1ULL << WIDX_MOVE_UP);
w->enabled_widgets &= ~(1ULL << WIDX_MOVE_UP);
} else { // Not the top element in the list
w->enabled_widgets |= (1ULL << WIDX_MOVE_UP);
w->disabled_widgets &= ~(1ULL << WIDX_MOVE_UP);
}
widget_invalidate(w, WIDX_MOVE_UP);
// Move Down button
if (w->selected_list_item == window_tile_inspector_item_count - 1 || w->selected_list_item == -1) { // Bottom element in list, or -1
w->disabled_widgets |= (1ULL << WIDX_MOVE_DOWN);
w->enabled_widgets &= ~(1ULL << WIDX_MOVE_DOWN);
} else { // Not the bottom element in the list
w->enabled_widgets |= (1ULL << WIDX_MOVE_DOWN);
w->disabled_widgets &= ~(1ULL << WIDX_MOVE_DOWN);
}
widget_invalidate(w, WIDX_MOVE_DOWN);
}
static void window_tile_inspector_scrollmousedown(rct_window *w, int scrollIndex, int x, int y)
{
// Because the list items are displayed in reverse order, subtract the number from the amount of elements
sint16 index = window_tile_inspector_item_count - (y - 1) / LIST_ITEM_HEIGHT - 1;
if (index < 0 || index >= window_tile_inspector_item_count)
return;
w->selected_list_item = index;
// Enable/disable buttons
window_tile_inspector_auto_set_buttons(w);
}
static void window_tile_inspector_scrollmouseover(rct_window *w, int scrollIndex, int x, int y)
{
window_invalidate(w);
sint16 index = window_tile_inspector_item_count - (y - 1) / LIST_ITEM_HEIGHT - 1;
if (index < 0 || index >= window_tile_inspector_item_count)
window_tile_inspector_highlighted_index = -1;
else
window_tile_inspector_highlighted_index = index;
widget_invalidate(w, WIDX_LIST);
}
static void window_tile_inspector_invalidate(rct_window *w)
@ -258,28 +437,53 @@ static void window_tile_inspector_invalidate(rct_window *w)
window_tile_inspector_widgets[WIDX_BACKGROUND].bottom = w->height - 1;
window_tile_inspector_widgets[WIDX_CLOSE].left = w->width - 13;
window_tile_inspector_widgets[WIDX_CLOSE].right = w->width - 3;
window_tile_inspector_widgets[WIDX_CONTENT_PANEL].right = w->width - 1;
window_tile_inspector_widgets[WIDX_CONTENT_PANEL].bottom = w->height - 1;
window_tile_inspector_widgets[WIDX_SCROLL].bottom = w->height - 30;
window_tile_inspector_widgets[WIDX_TITLE].right = w->width - 2;
window_tile_inspector_widgets[WIDX_LIST].right = w->width - 4;
window_tile_inspector_widgets[WIDX_LIST].bottom = w->height - SCROLL_BOTTOM_OFFSET;
window_tile_inspector_widgets[WIDX_COLUMN_LASTFLAG].right = w->width - 3;
}
static void window_tile_inspector_paint(rct_window *w, rct_drawpixelinfo *dpi)
{
int x, y;
char buffer[256];
window_draw_widgets(w, dpi);
x = w->x + 20;
y = w->y + 25;
char buffer[256];
int x = w->x /*+ w->widgets[WIDX_LIST].left*/ + 3;
int y = w->y + w->height - 13;
if (window_tile_inspector_tile_x == -1) {
// Set medium font size
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = FONT_SPRITE_BASE_MEDIUM;
// No tile selected
// Draw column headers
rct_widget *widget;
if ((widget= &w->widgets[WIDX_COLUMN_TYPE])->type != WWT_EMPTY) {
gfx_draw_string_left_clipped(dpi, STR_TILE_INSPECTOR_ELEMENT_TYPE, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, w->colours[1], w->x + widget->left + 1, w->y + widget->top + 1, widget->right - widget->left);
}
if ((widget = &w->widgets[WIDX_COLUMN_BASEHEIGHT])->type != WWT_EMPTY)
{
gfx_draw_string_left_clipped(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT_SHORT, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, w->colours[1], w->x + widget->left + 1, w->y + widget->top + 1, widget->right - widget->left);
}
if ((widget = &w->widgets[WIDX_COLUMN_CLEARANCEHEIGHT])->type != WWT_EMPTY)
{
gfx_draw_string_left_clipped(dpi, STR_TILE_INSPECTOR_CLEARANGE_HEIGHT_SHORT, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, w->colours[1], w->x + widget->left + 1, w->y + widget->top + 1, widget->right - widget->left);
}
if ((widget = &w->widgets[WIDX_COLUMN_GHOSTFLAG])->type != WWT_EMPTY)
{
gfx_draw_string_left_clipped(dpi, STR_TILE_INSPECTOR_FLAG_GHOST_SHORT, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, w->colours[1], w->x + widget->left + 1, w->y + widget->top + 1, widget->right - widget->left);
}
if ((widget = &w->widgets[WIDX_COLUMN_BROKENFLAG])->type != WWT_EMPTY)
{
gfx_draw_string_left_clipped(dpi, STR_TILE_INSPECTOR_FLAG_BROKEN_SHORT, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, w->colours[1], w->x + widget->left + 1, w->y + widget->top + 1, widget->right - widget->left);
}
if ((widget = &w->widgets[WIDX_COLUMN_LASTFLAG])->type != WWT_EMPTY)
{
gfx_draw_string_left_clipped(dpi, STR_TILE_INSPECTOR_FLAG_LAST_SHORT, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, w->colours[1], w->x + widget->left + 1, w->y + widget->top + 1, widget->right - widget->left);
}
// Draw coordinates
if (window_tile_inspector_tile_x == -1) { // No tile selected
gfx_draw_string_left(dpi, STR_TILE_INSPECTOR_CHOOSE_MSG, NULL, 12, x, y);
} else {
sprintf(
buffer,
"X: %d, Y: %d",
@ -288,21 +492,14 @@ static void window_tile_inspector_paint(rct_window *w, rct_drawpixelinfo *dpi)
);
gfx_draw_string(dpi, buffer, 12, x, y);
}
y += 25;
draw_string_left_underline(dpi, STR_TILE_INSPECTOR_ELEMENT_TYPE, NULL, 12, x, y);
draw_string_left_underline(dpi, STR_TILE_INSPECTOR_BASE_HEIGHT, NULL, 12, x + 200, y);
draw_string_left_underline(dpi, STR_TILE_INSPECTOR_CLEARANGE_HEIGHT, NULL, 12, x + 280, y);
draw_string_left_underline(dpi, STR_TILE_INSPECTOR_FLAGS, NULL, 12, x + 390, y);
}
static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex)
{
int x = 15, y = 11 * (window_tile_inspector_item_count - 1), i = 0;
int x = 3;
int y = LIST_ITEM_HEIGHT * (window_tile_inspector_item_count - 1);
int i = 0;
char buffer[256];
if (window_tile_inspector_tile_x == -1)
@ -310,15 +507,21 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo *
rct_map_element *element = map_get_first_element_at(window_tile_inspector_tile_x, window_tile_inspector_tile_y);
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = FONT_SPRITE_BASE_MEDIUM;
do {
int type = map_element_get_type(element);
char *type_name;
int base_height = element->base_height;
int clearance_height = element->clearance_height;
if ((i & 1) != 0)
gfx_fill_rect(dpi, x - 15, y, x + WW - 20, y + 11, ColourMapA[w->colours[1]].lighter | 0x1000000);
// Fill colour for current list element
const int list_width = w->widgets[WIDX_LIST].right - w->widgets[WIDX_LIST].left;
if (i == w->selected_list_item) // Currently selected element
gfx_fill_rect(dpi, 0, y, list_width, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].darker | 0x1000000);
else if (i == window_tile_inspector_highlighted_index) // Hovering
gfx_fill_rect(dpi, 0, y, list_width, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].mid_dark | 0x1000000);
else if ((i & 1) != 0) // odd / even check
gfx_fill_rect(dpi, 0, y, list_width, y + LIST_ITEM_HEIGHT - 1, ColourMapA[w->colours[1]].lighter | 0x1000000);
switch (type) {
case MAP_ELEMENT_TYPE_SURFACE:
@ -332,28 +535,35 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo *
break;
case MAP_ELEMENT_TYPE_PATH:
{
// TODO: use these
uint8 pathType, pathDirection;
pathType = element->properties.path.type >> 2;
pathDirection = element->properties.path.type & 3;
const uint8 pathType = footpath_element_get_type(element);
const uint8 pathHasScenery = footpath_element_has_path_scenery(element);
const uint8 pathAdditionType = footpath_element_get_path_scenery_index(element);
if (footpath_element_is_queue(element)) {
sprintf(
buffer,
"Queue for (%d)",
element->properties.path.ride_index
buffer, "Queue (%s)%s%s for (%d)",
language_get_string(g_pathSceneryEntries[pathType]->name), // Path name
pathHasScenery ? " with " : "", // Adds " with " when there is something on the path
pathHasScenery ? language_get_string(g_pathBitSceneryEntries[pathAdditionType]->name) : "", // Path addition name
element->properties.path.ride_index // Ride index for queue
);
} else {
sprintf(
buffer,
"Path (%s)",
"" // TODO: queue? has bins? has benches? e.t.c.
buffer, "Path (%s)%s%s",
language_get_string(g_pathSceneryEntries[pathType]->name), // Path name
pathHasScenery ? " with " : "", // Adds " with " when there is something on the path
pathHasScenery ? language_get_string(g_pathBitSceneryEntries[pathAdditionType]->name) : "" // Path addition name
);
}
}
type_name = buffer;
break;
case MAP_ELEMENT_TYPE_TRACK:
type_name = "Track"; // TODO: show type?
sprintf(
buffer,
"Track (%s)",
language_get_string(2 + GET_RIDE(element->properties.track.ride_index)->type)
);
type_name = buffer;
break;
case MAP_ELEMENT_TYPE_SCENERY:
sprintf(
@ -397,24 +607,19 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo *
type_name = buffer;
}
gfx_draw_string(dpi, type_name, 12, x, y);
gfx_draw_string_left(dpi, 5182, &base_height, 12, x + 200, y);
gfx_draw_string_left(dpi, 5182, &clearance_height, 12, x + 280, y);
// Undo relative scroll offset, but keep the 3 pixel padding
x = -w->widgets[WIDX_LIST].left;
const bool ghost = (element->flags & MAP_ELEMENT_FLAG_GHOST) != 0;
const bool broken = (element->flags & MAP_ELEMENT_FLAG_BROKEN) != 0;
const bool last = (element->flags & MAP_ELEMENT_FLAG_LAST_TILE) != 0;
gfx_draw_string(dpi, type_name, 12, x + COL_X_TYPE + 3, y); // 3px padding
gfx_draw_string_left(dpi, 5182, &base_height, 12, x + COL_X_BH, y);
gfx_draw_string_left(dpi, 5182, &clearance_height, 12, x + COL_X_CH, y);
if (ghost) gfx_draw_string(dpi, (char*)CheckBoxMarkString, w->colours[1], x + COL_X_GF, y);
if (broken) gfx_draw_string(dpi, (char*)CheckBoxMarkString, w->colours[1], x + COL_X_BF, y);
if (last) gfx_draw_string(dpi, (char*)CheckBoxMarkString, w->colours[1], x + COL_X_LF, y);
uint8 flags = element->flags;
char j;
buffer[8] = '\0';
for (j = 7; j >= 0; j--, flags >>= 1) {
buffer[j] = flags & 1 ? '1' : '0';
}
gfx_draw_string(dpi, buffer, 12, x + 390, y);
y -= 11;
y -= LIST_ITEM_HEIGHT;
i++;
} while (!map_element_is_last_for_tile(element++));
}

View File

@ -22,13 +22,13 @@
#include "../config.h"
#include "../editor.h"
#include "../game.h"
#include "../input.h"
#include "../interface/themes.h"
#include "../interface/widget.h"
#include "../interface/window.h"
#include "../localisation/localisation.h"
#include "../sprites.h"
#include "../tutorial.h"
#include "dropdown.h"
#include "../interface/themes.h"
enum {
WIDX_START_NEW_GAME,
@ -148,19 +148,7 @@ static void window_title_menu_mouseup(rct_window *w, int widgetIndex)
static void window_title_menu_mousedown(int widgetIndex, rct_window*w, rct_widget* widget)
{
if (widgetIndex == WIDX_SHOW_TUTORIAL) {
gDropdownItemsFormat[0] = STR_TUTORIAL_BEGINNERS;
gDropdownItemsFormat[1] = STR_TUTORIAL_CUSTOM_RIDES;
gDropdownItemsFormat[2] = STR_TUTORIAL_ROLLER_COASTER;
window_dropdown_show_text(
w->x + widget->left,
w->y + widget->top,
widget->bottom - widget->top + 1,
w->colours[0] | 0x80,
DROPDOWN_FLAG_STAY_OPEN,
3
);
} else if (widgetIndex == WIDX_GAME_TOOLS) {
if (widgetIndex == WIDX_GAME_TOOLS) {
gDropdownItemsFormat[0] = STR_SCENARIO_EDITOR;
gDropdownItemsFormat[1] = STR_CONVERT_SAVED_GAME_TO_SCENARIO;
gDropdownItemsFormat[2] = STR_ROLLER_COASTER_DESIGNER;
@ -178,9 +166,7 @@ static void window_title_menu_mousedown(int widgetIndex, rct_window*w, rct_widge
static void window_title_menu_dropdown(rct_window *w, int widgetIndex, int dropdownIndex)
{
if (widgetIndex == WIDX_SHOW_TUTORIAL) {
tutorial_start(dropdownIndex);
} else if (widgetIndex == WIDX_GAME_TOOLS) {
if (widgetIndex == WIDX_GAME_TOOLS) {
switch (dropdownIndex) {
case 0:
editor_load();
@ -200,7 +186,7 @@ static void window_title_menu_dropdown(rct_window *w, int widgetIndex, int dropd
static void window_title_menu_cursor(rct_window *w, int widgetIndex, int x, int y, int *cursorId)
{
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, sint16) = 2000;
gTooltipTimeout = 2000;
}
static void window_title_menu_paint(rct_window *w, rct_drawpixelinfo *dpi)

View File

@ -30,6 +30,29 @@
#include "../interface/themes.h"
#include "../util/util.h"
#define INITIAL_NUM_UNLOCKED_SCENARIOS 5
enum {
LIST_ITEM_TYPE_HEADING,
LIST_ITEM_TYPE_SCENARIO,
LIST_ITEM_TYPE_END,
};
typedef struct {
uint8 type;
union {
struct {
rct_string_id string_id;
} heading;
struct {
scenario_index_entry *scenario;
bool is_locked;
} scenario;
};
} sc_list_item;
static sc_list_item *_listItems = NULL;
enum {
WIDX_BACKGROUND,
WIDX_TITLEBAR,
@ -40,25 +63,32 @@ enum {
WIDX_TAB3,
WIDX_TAB4,
WIDX_TAB5,
WIDX_TAB6,
WIDX_TAB7,
WIDX_TAB8,
WIDX_SCENARIOLIST
};
static rct_widget window_scenarioselect_widgets[] = {
{ WWT_FRAME, 0, 0, 609, 0, 333, -1, STR_NONE }, // panel / background
{ WWT_CAPTION, 0, 1, 608, 1, 14, STR_SELECT_SCENARIO, STR_WINDOW_TITLE_TIP }, // title bar
{ WWT_CLOSEBOX, 0, 597, 607, 2, 13, 824, STR_CLOSE_WINDOW_TIP }, // close x button
{ WWT_IMGBTN, 1, 0, 609, 50, 333, -1, STR_NONE }, // tab content panel
{ WWT_FRAME, 0, 0, 733, 0, 333, -1, STR_NONE }, // panel / background
{ WWT_CAPTION, 0, 1, 732, 1, 14, STR_SELECT_SCENARIO, STR_WINDOW_TITLE_TIP }, // title bar
{ WWT_CLOSEBOX, 0, 721, 731, 2, 13, 824, STR_CLOSE_WINDOW_TIP }, // close x button
{ WWT_IMGBTN, 1, 0, 733, 50, 333, -1, STR_NONE }, // tab content panel
{ WWT_TAB, 1, 3, 93, 17, 50, 0x200015BC, STR_NONE }, // tab 1
{ WWT_TAB, 1, 94, 184, 17, 50, 0x200015BC, STR_NONE }, // tab 2
{ WWT_TAB, 1, 185, 275, 17, 50, 0x200015BC, STR_NONE }, // tab 3
{ WWT_TAB, 1, 276, 366, 17, 50, 0x200015BC, STR_NONE }, // tab 4
{ WWT_TAB, 1, 367, 457, 17, 50, 0x200015BC, STR_NONE }, // tab 5
{ WWT_SCROLL, 1, 3, 433, 54, 329, 2, STR_NONE }, // level list
{ WWT_TAB, 1, 458, 593, 17, 50, 0x200015BC, STR_NONE }, // tab 6
{ WWT_TAB, 1, 594, 684, 17, 50, 0x200015BC, STR_NONE }, // tab 7
{ WWT_TAB, 1, 685, 775, 17, 50, 0x200015BC, STR_NONE }, // tab 8
{ WWT_SCROLL, 1, 3, 555, 54, 329, 2, STR_NONE }, // level list
{ WIDGETS_END },
};
static void window_scenarioselect_init_tabs();
static void window_scenarioselect_init_tabs(rct_window *w);
static void window_scenarioselect_close(rct_window *w);
static void window_scenarioselect_mouseup(rct_window *w, int widgetIndex);
static void window_scenarioselect_mousedown(int widgetIndex, rct_window*w, rct_widget* widget);
static void window_scenarioselect_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height);
@ -69,7 +99,7 @@ static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi);
static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex);
static rct_window_event_list window_scenarioselect_events = {
NULL,
window_scenarioselect_close,
window_scenarioselect_mouseup,
NULL,
window_scenarioselect_mousedown,
@ -99,6 +129,11 @@ static rct_window_event_list window_scenarioselect_events = {
window_scenarioselect_scrollpaint
};
static void draw_category_heading(rct_window *w, rct_drawpixelinfo *dpi, int left, int right, int y, rct_string_id stringId);
static void initialise_list_items(rct_window *w);
static bool is_scenario_visible(rct_window *w, scenario_index_entry *scenario);
static bool is_locking_enabled(rct_window *w);
/**
*
* rct2: 0x006781B5
@ -106,6 +141,8 @@ static rct_window_event_list window_scenarioselect_events = {
void window_scenarioselect_open()
{
rct_window* window;
int windowWidth;
int windowHeight = 334;
if (window_bring_to_front_by_class(WC_SCENARIO_SELECT) != NULL)
return;
@ -113,48 +150,62 @@ void window_scenarioselect_open()
// Load scenario list
scenario_load_list();
// Shrink the window if we're showing scenarios by difficulty level.
if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_DIFFICULTY) {
windowWidth = 610;
} else {
windowWidth = 733;
}
window = window_create_centred(
610,
334,
windowWidth,
windowHeight,
&window_scenarioselect_events,
WC_SCENARIO_SELECT,
WF_10
);
window->widgets = window_scenarioselect_widgets;
window->enabled_widgets = (1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2)
| (1 << WIDX_TAB3) | (1 << WIDX_TAB4) | (1 << WIDX_TAB5);
| (1 << WIDX_TAB3) | (1 << WIDX_TAB4) | (1 << WIDX_TAB5)
| (1 << WIDX_TAB6) | (1 << WIDX_TAB7) | (1 << WIDX_TAB8);
window_scenarioselect_init_tabs(window);
initialise_list_items(window);
window_init_scroll_widgets(window);
window->viewport_focus_coordinates.var_480 = -1;
window->highlighted_item = 0;
window_scenarioselect_init_tabs();
window->selected_tab = 0;
window->highlighted_scenario = NULL;
}
/**
*
* rct2: 0x00677C8A
*/
static void window_scenarioselect_init_tabs()
static void window_scenarioselect_init_tabs(rct_window *w)
{
int i, x, show_pages;
rct_widget* widget;
rct_scenario_basic* scenario;
int showPages = 0;
for (int i = 0; i < gScenarioListCount; i++) {
scenario_index_entry *scenario = &gScenarioList[i];
if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN) {
showPages |= 1 << scenario->source_game;
} else {
int category = scenario->category;
if (category > SCENARIO_CATEGORY_OTHER) {
category = SCENARIO_CATEGORY_OTHER;
}
showPages |= 1 << category;
}
}
show_pages = 0;
for (i = 0; i < gScenarioListCount; i++) {
scenario = &gScenarioList[i];
if (scenario->flags & SCENARIO_FLAGS_VISIBLE)
show_pages |= 1 << scenario->category;
int firstPage = bitscanforward(showPages);
if (firstPage != -1) {
w->selected_tab = firstPage;
}
x = 3;
for (i = 0; i < 5; i++) {
widget = &window_scenarioselect_widgets[i + 4];
if (!(show_pages & (1 << i))) {
int x = 3;
for (int i = 0; i < 8; i++) {
rct_widget* widget = &w->widgets[i + 4];
if (!(showPages & (1 << i))) {
widget->type = WWT_EMPTY;
continue;
}
@ -166,17 +217,24 @@ static void window_scenarioselect_init_tabs()
}
}
static void window_scenarioselect_close(rct_window *w)
{
SafeFree(_listItems);
}
static void window_scenarioselect_mouseup(rct_window *w, int widgetIndex)
{
if (widgetIndex == WIDX_CLOSE)
if (widgetIndex == WIDX_CLOSE) {
window_close(w);
}
}
static void window_scenarioselect_mousedown(int widgetIndex, rct_window*w, rct_widget* widget)
{
if (widgetIndex >= WIDX_TAB1 && widgetIndex <= WIDX_TAB5) {
if (widgetIndex >= WIDX_TAB1 && widgetIndex <= WIDX_TAB8) {
w->selected_tab = widgetIndex - 4;
w->highlighted_item = 0;
w->highlighted_scenario = NULL;
initialise_list_items(w);
window_invalidate(w);
window_event_resize_call(w);
window_event_invalidate_call(w);
@ -187,17 +245,18 @@ static void window_scenarioselect_mousedown(int widgetIndex, rct_window*w, rct_w
static void window_scenarioselect_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height)
{
int i;
rct_scenario_basic *scenario;
*height = 0;
for (i = 0; i < gScenarioListCount; i++) {
scenario = &gScenarioList[i];
if (scenario->category != w->selected_tab)
continue;
if (scenario->flags & SCENARIO_FLAGS_VISIBLE)
*height += 24;
int y = 0;
for (sc_list_item *listItem = _listItems; listItem->type != LIST_ITEM_TYPE_END; listItem++) {
switch (listItem->type) {
case LIST_ITEM_TYPE_HEADING:
y += 18;
break;
case LIST_ITEM_TYPE_SCENARIO:
y += 24;
break;
}
}
*height = y;
}
/**
@ -206,23 +265,22 @@ static void window_scenarioselect_scrollgetsize(rct_window *w, int scrollIndex,
*/
static void window_scenarioselect_scrollmousedown(rct_window *w, int scrollIndex, int x, int y)
{
int i;
rct_scenario_basic *scenario;
for (i = 0; i < gScenarioListCount; i++) {
scenario = &gScenarioList[i];
if (scenario->category != w->selected_tab)
continue;
if (!(scenario->flags & SCENARIO_FLAGS_VISIBLE))
continue;
y -= 24;
if (y >= 0)
continue;
audio_play_sound_panned(SOUND_CLICK_1, w->width / 2 + w->x, 0, 0, 0);
scenario_load_and_play(scenario);
break;
for (sc_list_item *listItem = _listItems; listItem->type != LIST_ITEM_TYPE_END; listItem++) {
switch (listItem->type) {
case LIST_ITEM_TYPE_HEADING:
y -= 18;
break;
case LIST_ITEM_TYPE_SCENARIO:
y -= 24;
if (y < 0 && !listItem->scenario.is_locked) {
audio_play_sound_panned(SOUND_CLICK_1, w->width / 2 + w->x, 0, 0, 0);
scenario_load_and_play_from_path(listItem->scenario.scenario->path);
}
break;
}
if (y < 0) {
break;
}
}
}
@ -232,26 +290,26 @@ static void window_scenarioselect_scrollmousedown(rct_window *w, int scrollIndex
*/
static void window_scenarioselect_scrollmouseover(rct_window *w, int scrollIndex, int x, int y)
{
int i;
rct_scenario_basic *scenario, *selected;
selected = NULL;
for (i = 0; i < gScenarioListCount; i++) {
scenario = &gScenarioList[i];
if (scenario->category != w->selected_tab)
continue;
if (!(scenario->flags & SCENARIO_FLAGS_VISIBLE))
continue;
y -= 24;
if (y >= 0)
continue;
selected = scenario;
break;
scenario_index_entry *selected = NULL;
for (sc_list_item *listItem = _listItems; listItem->type != LIST_ITEM_TYPE_END; listItem++) {
switch (listItem->type) {
case LIST_ITEM_TYPE_HEADING:
y -= 18;
break;
case LIST_ITEM_TYPE_SCENARIO:
y -= 24;
if (y < 0 && !listItem->scenario.is_locked) {
selected = listItem->scenario.scenario;
}
break;
}
if (y < 0) {
break;
}
}
if (w->highlighted_item != (uint32)selected) {
w->highlighted_item = (uint32)selected;
if (w->highlighted_scenario != selected) {
w->highlighted_scenario = selected;
window_invalidate(w);
}
}
@ -261,113 +319,341 @@ static void window_scenarioselect_invalidate(rct_window *w)
colour_scheme_update(w);
w->pressed_widgets &= ~( (1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2)
| (1 << WIDX_TAB3) | (1 << WIDX_TAB4) | (1 << WIDX_TAB5) );
| (1 << WIDX_TAB3) | (1 << WIDX_TAB4) | (1 << WIDX_TAB5)
| (1 << WIDX_TAB6) | (1 << WIDX_TAB7) | (1 << WIDX_TAB8) );
w->pressed_widgets |= 1LL << (w->selected_tab + 4);
int windowWidth = w->width;
window_scenarioselect_widgets[WIDX_BACKGROUND].right = windowWidth - 1;
window_scenarioselect_widgets[WIDX_TITLEBAR].right = windowWidth - 2;
window_scenarioselect_widgets[WIDX_CLOSE].left = windowWidth - 13;
window_scenarioselect_widgets[WIDX_CLOSE].right = windowWidth - 3;
window_scenarioselect_widgets[WIDX_TABCONTENT].right = windowWidth - 1;
window_scenarioselect_widgets[WIDX_SCENARIOLIST].right = windowWidth - 179;
int windowHeight = w->height;
window_scenarioselect_widgets[WIDX_BACKGROUND].bottom = windowHeight - 1;
window_scenarioselect_widgets[WIDX_TABCONTENT].bottom = windowHeight - 1;
const int bottomMargin = gConfigGeneral.debugging_tools ? 17 : 5;
window_scenarioselect_widgets[WIDX_SCENARIOLIST].bottom = windowHeight - bottomMargin;
}
static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi)
{
int i, x, y, format;
rct_widget *widget;
rct_scenario_basic *scenario;
scenario_index_entry *scenario;
window_draw_widgets(w, dpi);
format = (theme_get_preset()->features.rct1_scenario_font) ? 5138 : 1193;
// Text for each tab
for (i = 0; i < 5; i++) {
for (i = 0; i < 8; i++) {
widget = &window_scenarioselect_widgets[WIDX_TAB1 + i];
if (widget->type == WWT_EMPTY)
continue;
x = (widget->left + widget->right) / 2 + w->x;
y = (widget->top + widget->bottom) / 2 + w->y - 3;
RCT2_GLOBAL(0x013CE952 + 0, short) = STR_BEGINNER_PARKS + i;
gfx_draw_string_centred_wrapped(dpi, (void*)0x013CE952, x, y, 87, format, 10);
if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN) {
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = STR_SCENARIO_CATEGORY_RCT1 + i;
} else { // old-style
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = ScenarioCategoryStringIds[i];
}
gfx_draw_string_centred_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, 87, format, 10);
}
// Return if no scenario highlighted
scenario = (rct_scenario_basic*)w->highlighted_item;
if (scenario == NULL)
scenario = w->highlighted_scenario;
if (scenario == NULL) {
return;
}
// Scenario path
if (gConfigGeneral.debugging_tools) {
utf8 path[MAX_PATH];
shorten_path(path, sizeof(path), scenario->path, w->width - 6);
const utf8 *pathPtr = path;
gfx_draw_string_left(dpi, 1170, (void*)&pathPtr, w->colours[1], w->x + 3, w->y + w->height - 3 - 11);
}
// Scenario name
x = w->x + window_scenarioselect_widgets[WIDX_SCENARIOLIST].right + 4;
y = w->y + window_scenarioselect_widgets[WIDX_TABCONTENT].top + 5;
safe_strncpy((char*)0x009BC677, scenario->name, 64);
RCT2_GLOBAL(0x013CE952 + 0, short) = 3165;
gfx_draw_string_centred_clipped(dpi, 1193, (void*)0x013CE952, 0, x + 85, y, 170);
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = 3165; // empty string
gfx_draw_string_centred_clipped(dpi, 1193, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x + 85, y, 170);
y += 15;
// Scenario details
safe_strncpy((char*)0x009BC677, scenario->details, 256);
RCT2_GLOBAL(0x013CE952 + 0, short) = 3165;
y += gfx_draw_string_left_wrapped(dpi, (void*)0x013CE952, x, y, 170, 1191, 0) + 5;
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = 3165; // empty string
y += gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, 170, 1191, 0) + 5;
// Scenario objective
RCT2_GLOBAL(0x013CE952 + 0, short) = scenario->objective_type + STR_OBJECTIVE_NONE;
RCT2_GLOBAL(0x013CE952 + 2, short) = scenario->objective_arg_3;
RCT2_GLOBAL(0x013CE952 + 4, short) = date_get_total_months(MONTH_OCTOBER, scenario->objective_arg_1);
RCT2_GLOBAL(0x013CE952 + 6, int) = scenario->objective_arg_2;
y += gfx_draw_string_left_wrapped(dpi, (void*)0x013CE952, x, y, 170, STR_OBJECTIVE, 0) + 5;
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = scenario->objective_type + STR_OBJECTIVE_NONE;
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, short) = scenario->objective_arg_3;
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, short) = date_get_total_months(MONTH_OCTOBER, scenario->objective_arg_1);
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, int) = scenario->objective_arg_2;
y += gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, 170, STR_OBJECTIVE, 0) + 5;
// Scenario score
if (scenario->flags & SCENARIO_FLAGS_COMPLETED) {
safe_strncpy((char*)0x009BC677, scenario->completed_by, 64);
RCT2_GLOBAL(0x013CE952 + 0, short) = 3165;
RCT2_GLOBAL(0x013CE952 + 2, int) = scenario->company_value;
y += gfx_draw_string_left_wrapped(dpi, (void*)0x013CE952, x, y, 170, STR_COMPLETED_BY_WITH_COMPANY_VALUE, 0);
if (scenario->highscore != NULL) {
const utf8 *completedByName = "???";
if (!str_is_null_or_empty(scenario->highscore->name)) {
completedByName = scenario->highscore->name;
}
safe_strncpy((char*)0x009BC677, completedByName, 64);
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, short) = 3165; // empty string
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, int) = scenario->highscore->company_value;
y += gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, 170, STR_COMPLETED_BY_WITH_COMPANY_VALUE, 0);
}
}
static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex)
{
int i, y, colour, highlighted, highlighted_format, unhighlighted_format;
rct_scenario_basic *scenario;
colour = ColourMapA[w->colours[1]].mid_light;
int colour = ColourMapA[w->colours[1]].mid_light;
colour = (colour << 24) | (colour << 16) | (colour << 8) | colour;
gfx_clear(dpi, colour);
highlighted_format = (theme_get_preset()->features.rct1_scenario_font) ? 5139 : 1193;
unhighlighted_format = (theme_get_preset()->features.rct1_scenario_font) ? 5139 : 1191;
int highlighted_format = (theme_get_preset()->features.rct1_scenario_font) ? 5139 : 1193;
int unhighlighted_format = (theme_get_preset()->features.rct1_scenario_font) ? 5139 : 1191;
y = 0;
for (i = 0; i < gScenarioListCount; i++) {
scenario = &gScenarioList[i];
if (scenario->category != w->selected_tab)
bool wide = gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN;
rct_widget *listWidget = &w->widgets[WIDX_SCENARIOLIST];
int listWidth = listWidget->right - listWidget->left - 12;
int y = 0;
for (sc_list_item *listItem = _listItems; listItem->type != LIST_ITEM_TYPE_END; listItem++) {
if (y > dpi->y + dpi->height) {
continue;
if (!(scenario->flags & SCENARIO_FLAGS_VISIBLE))
continue;
if (y > dpi->y + dpi->height)
continue;
highlighted = w->highlighted_item == (int)scenario;
// Draw hover highlight
if (highlighted)
gfx_fill_rect(dpi, 0, y, w->width, y + 23, 0x02000031);
// Draw scenario name
safe_strncpy((char*)0x009BC677, scenario->name, 64);
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = 3165;
gfx_draw_string_centred(dpi, highlighted ? highlighted_format : unhighlighted_format, 210, y + 1, 0, (void*)0x013CE952);
// Check if scenario is completed
if (scenario->flags & SCENARIO_FLAGS_COMPLETED) {
// Draw completion tick
gfx_draw_sprite(dpi, 0x5A9F, 395, y + 1, 0);
// Draw completion score
safe_strncpy((char*)0x009BC677, scenario->completed_by, 64);
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = 2793;
RCT2_GLOBAL(0x013CE954, short) = 3165;
gfx_draw_string_centred(dpi, highlighted ? 1193 : 1191, 210, y + 11, 0, (void*)0x013CE952);
}
y += 24;
switch (listItem->type) {
case LIST_ITEM_TYPE_HEADING:;
const int horizontalRuleMargin = 4;
draw_category_heading(w, dpi, horizontalRuleMargin, listWidth - horizontalRuleMargin, y + 2, listItem->heading.string_id);
y += 18;
break;
case LIST_ITEM_TYPE_SCENARIO:;
// Draw hover highlight
scenario_index_entry *scenario = listItem->scenario.scenario;
bool isHighlighted = w->highlighted_scenario == scenario;
if (isHighlighted) {
gfx_fill_rect(dpi, 0, y, w->width, y + 23, 0x02000031);
}
bool isCompleted = scenario->highscore != NULL;
bool isDisabled = listItem->scenario.is_locked;
// Draw scenario name
rct_string_id placeholderStringId = 3165;
safe_strncpy((char*)language_get_string(placeholderStringId), scenario->name, 64);
int format = isDisabled ? 865 : (isHighlighted ? highlighted_format : unhighlighted_format);
colour = isDisabled ? w->colours[1] | 0x40 : COLOUR_BLACK;
gfx_draw_string_centred(dpi, format, wide ? 270 : 210, y + 1, colour, &placeholderStringId);
// Check if scenario is completed
if (isCompleted) {
// Draw completion tick
gfx_draw_sprite(dpi, 0x5A9F, wide ? 500 : 395, y + 1, 0);
// Draw completion score
const utf8 *completedByName = "???";
if (!str_is_null_or_empty(scenario->highscore->name)) {
completedByName = scenario->highscore->name;
}
safe_strncpy((char*)language_get_string(placeholderStringId), completedByName, 64);
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, rct_string_id) = 2793;
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, rct_string_id) = placeholderStringId;
gfx_draw_string_centred(dpi, format, wide ? 270 : 210, y + 11, 0, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS);
}
y += 24;
break;
}
}
}
static void draw_category_heading(rct_window *w, rct_drawpixelinfo *dpi, int left, int right, int y, rct_string_id stringId)
{
uint8 baseColour = w->colours[1];
uint8 lightColour = ColourMapA[baseColour].lighter;
uint8 darkColour = ColourMapA[baseColour].mid_dark;
// Draw string
int centreX = (left + right) / 2;
gfx_draw_string_centred(dpi, stringId, centreX, y, baseColour, NULL);
// Get string dimensions
utf8 *buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, utf8);
format_string(buffer, stringId, NULL);
int categoryStringHalfWidth = (gfx_get_string_width(buffer) / 2) + 4;
int strLeft = centreX - categoryStringHalfWidth;
int strRight = centreX + categoryStringHalfWidth;
// Draw light horizontal rule
int lineY = y + 4;
gfx_draw_line(dpi, left, lineY, strLeft, lineY, lightColour);
gfx_draw_line(dpi, strRight, lineY, right, lineY, lightColour);
// Draw dark horizontal rule
lineY++;
gfx_draw_line(dpi, left, lineY, strLeft, lineY, darkColour);
gfx_draw_line(dpi, strRight, lineY, right, lineY, darkColour);
}
static void initialise_list_items(rct_window *w)
{
SafeFree(_listItems);
int capacity = gScenarioListCount + 16;
int length = 0;
_listItems = malloc(capacity * sizeof(sc_list_item));
// Mega park unlock
const uint32 rct1RequiredCompletedScenarios = (1 << SC_MEGA_PARK) - 1;
uint32 rct1CompletedScenarios = 0;
int megaParkListItemIndex = -1;
int numUnlocks = INITIAL_NUM_UNLOCKED_SCENARIOS;
uint8 currentHeading = UINT8_MAX;
for (int i = 0; i < gScenarioListCount; i++) {
scenario_index_entry *scenario = &gScenarioList[i];
if (!is_scenario_visible(w, scenario)) {
continue;
}
sc_list_item *listItem;
// Category heading
rct_string_id headingStringId = STR_NONE;
if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN) {
if (w->selected_tab != SCENARIO_SOURCE_REAL && currentHeading != scenario->category) {
currentHeading = scenario->category;
headingStringId = ScenarioCategoryStringIds[currentHeading];
}
} else {
if (w->selected_tab <= SCENARIO_CATEGORY_EXPERT) {
if (currentHeading != scenario->source_game) {
currentHeading = scenario->source_game;
headingStringId = STR_SCENARIO_CATEGORY_RCT1 + currentHeading;
}
} else if (w->selected_tab == SCENARIO_CATEGORY_OTHER) {
int category = scenario->category;
if (category <= SCENARIO_CATEGORY_REAL) {
category = SCENARIO_CATEGORY_OTHER;
}
if (currentHeading != category) {
currentHeading = category;
headingStringId = ScenarioCategoryStringIds[category];
}
}
}
if (headingStringId != (rct_string_id)STR_NONE) {
// Ensure list capacity
if (length == capacity) {
capacity += 32;
_listItems = realloc(_listItems, capacity * sizeof(sc_list_item));
}
listItem = &_listItems[length++];
listItem->type = LIST_ITEM_TYPE_HEADING;
listItem->heading.string_id = headingStringId;
}
// Ensure list capacity
if (length == capacity) {
capacity += 32;
_listItems = realloc(_listItems, capacity * sizeof(sc_list_item));
}
listItem = &_listItems[length++];
// Scenario
listItem->type = LIST_ITEM_TYPE_SCENARIO;
listItem->scenario.scenario = scenario;
if (is_locking_enabled(w)) {
listItem->scenario.is_locked = numUnlocks <= 0;
if (scenario->highscore == NULL) {
numUnlocks--;
} else {
// Mark RCT1 scenario as completed
if (scenario->sc_id < SC_MEGA_PARK) {
rct1CompletedScenarios |= 1 << scenario->sc_id;
}
}
// If scenario is Mega Park, keep a reference to it
if (scenario->sc_id == SC_MEGA_PARK) {
megaParkListItemIndex = length - 1;
}
} else {
listItem->scenario.is_locked = false;
}
}
length++;
_listItems = realloc(_listItems, length * sizeof(sc_list_item));
_listItems[length - 1].type = LIST_ITEM_TYPE_END;
// Mega park handling
if (megaParkListItemIndex != -1) {
bool megaParkLocked = (rct1CompletedScenarios & rct1RequiredCompletedScenarios) != rct1RequiredCompletedScenarios;
_listItems[megaParkListItemIndex].scenario.is_locked = megaParkLocked;
if (megaParkLocked && gConfigGeneral.scenario_hide_mega_park) {
// Remove mega park
int remainingItems = length - megaParkListItemIndex - 1;
memmove(&_listItems[megaParkListItemIndex], &_listItems[megaParkListItemIndex + 1], remainingItems);
// Remove empty headings
int i = 0;
for (sc_list_item *listItem = _listItems; listItem->type != LIST_ITEM_TYPE_END; listItem++) {
if (listItem->type == LIST_ITEM_TYPE_HEADING && (listItem + 1)->type != LIST_ITEM_TYPE_SCENARIO) {
remainingItems = length - i - 1;
memmove(&_listItems[i], &_listItems[i + 1], remainingItems);
listItem--;
} else {
i++;
}
}
}
}
}
static bool is_scenario_visible(rct_window *w, scenario_index_entry *scenario)
{
if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN) {
if (scenario->source_game != w->selected_tab) {
return false;
}
} else {
int category = scenario->category;
if (category > SCENARIO_CATEGORY_OTHER) {
category = SCENARIO_CATEGORY_OTHER;
}
if (category != w->selected_tab) {
return false;
}
}
return true;
}
static bool is_locking_enabled(rct_window *w)
{
if (gConfigGeneral.scenario_select_mode != SCENARIO_SELECT_MODE_ORIGIN) {
return false;
}
if (!gConfigGeneral.scenario_unlocking_enabled) {
return false;
}
if (w->selected_tab >= 6) {
return false;
}
return true;
}

View File

@ -21,6 +21,7 @@
#include "../addresses.h"
#include "../drawing/drawing.h"
#include "../localisation/localisation.h"
#include "../input.h"
#include "../interface/widget.h"
#include "../interface/window.h"
@ -70,12 +71,12 @@ static rct_window_event_list window_tooltip_events = {
void window_tooltip_reset(int x, int y)
{
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_X, uint16) = x;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16) = y;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, uint8) = 255;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 1;
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~(1 << 4);
gTooltipCursorX = x;
gTooltipCursorY = y;
gTooltipTimeout = 0;
gTooltipWidget.window_classification = 255;
gInputState = INPUT_STATE_NORMAL;
gInputFlags &= ~INPUT_FLAG_4;
}
uint8* gTooltip_text_buffer = RCT2_ADDRESS(RCT2_ADDRESS_TOOLTIP_TEXT_BUFFER, uint8);
@ -134,7 +135,7 @@ void window_tooltip_show(rct_string_id id, int x, int y)
);
w->widgets = window_tooltip_widgets;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, uint16) = 0;
gTooltipNotShownTicks = 0;
}
/**
@ -153,9 +154,9 @@ void window_tooltip_open(rct_window *widgetWindow, int widgetIndex, int x, int y
if (widget->tooltip == 0xFFFF)
return;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) = widgetWindow->classification;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_NUMBER, rct_windownumber) = widgetWindow->number;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WIDGET_INDEX, uint16) = widgetIndex;
gTooltipWidget.window_classification = widgetWindow->classification;
gTooltipWidget.window_number = widgetWindow->number;
gTooltipWidget.widget_index = widgetIndex;
if (window_event_tooltip_call(widgetWindow, widgetIndex) == (rct_string_id)STR_NONE)
return;
@ -170,8 +171,8 @@ void window_tooltip_open(rct_window *widgetWindow, int widgetIndex, int x, int y
void window_tooltip_close()
{
window_close_by_class(WC_TOOLTIP);
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TIMEOUT, uint16) = 0;
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_WINDOW_CLASS, rct_windowclass) = 255;
gTooltipTimeout = 0;
gTooltipWidget.window_classification = 255;
RCT2_GLOBAL(0x0142006C, sint32) = -1;
RCT2_GLOBAL(0x009DE51E, uint8) = 0;
}
@ -192,7 +193,7 @@ static void window_tooltip_onclose(rct_window *w)
static void window_tooltip_update(rct_window *w)
{
if (RCT2_GLOBAL(0x009DE51E, uint8) == 0)
RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_NOT_SHOWN_TICKS, uint16) = 0;
gTooltipNotShownTicks = 0;
}
/**

View File

@ -310,7 +310,7 @@ static void window_top_toolbar_mouseup(rct_window *w, int widgetIndex)
break;
case WIDX_SCENERY:
if (!tool_set(w, WIDX_SCENERY, 0)) {
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
gInputFlags |= INPUT_FLAG_6;
window_scenery_open();
}
break;
@ -3117,12 +3117,12 @@ void toggle_footpath_window()
*/
void toggle_land_window(rct_window *topToolbar, int widgetIndex)
{
if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == 1 && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == 7) {
if ((gInputFlags & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == WC_TOP_TOOLBAR && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == 7) {
tool_cancel();
} else {
show_gridlines();
tool_set(topToolbar, widgetIndex, 18);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
gInputFlags |= INPUT_FLAG_6;
RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = 1;
window_land_open();
}
@ -3134,12 +3134,12 @@ void toggle_land_window(rct_window *topToolbar, int widgetIndex)
*/
void toggle_clear_scenery_window(rct_window *topToolbar, int widgetIndex)
{
if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == 1 && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == 16) {
if ((gInputFlags & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == WC_TOP_TOOLBAR && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == 16) {
tool_cancel();
} else {
show_gridlines();
tool_set(topToolbar, widgetIndex, 12);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
gInputFlags |= INPUT_FLAG_6;
RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = 2;
window_clear_scenery_open();
}
@ -3151,12 +3151,12 @@ void toggle_clear_scenery_window(rct_window *topToolbar, int widgetIndex)
*/
void toggle_water_window(rct_window *topToolbar, int widgetIndex)
{
if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == 1 && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == 8) {
if ((gInputFlags & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == WC_TOP_TOOLBAR && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) == 8) {
tool_cancel();
} else {
show_gridlines();
tool_set(topToolbar, widgetIndex, 19);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
gInputFlags |= INPUT_FLAG_6;
RCT2_GLOBAL(RCT2_ADDRESS_LAND_TOOL_SIZE, sint16) = 1;
window_water_open();
}
@ -3168,7 +3168,7 @@ void toggle_water_window(rct_window *topToolbar, int widgetIndex)
*/
bool land_tool_is_active()
{
if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE))
if (!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE))
return false;
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != WC_TOP_TOOLBAR)
return false;

View File

@ -389,7 +389,7 @@ void window_track_place_open()
w->enabled_widgets = 4 | 8 | 0x10 | 0x20;
window_init_scroll_widgets(w);
tool_set(w, 6, 12);
RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6;
gInputFlags |= INPUT_FLAG_6;
window_push_others_right(w);
show_gridlines();
_window_track_place_last_cost = MONEY32_UNDEFINED;
@ -449,7 +449,7 @@ static void window_track_place_mouseup(rct_window *w, int widgetIndex)
*/
static void window_track_place_update(rct_window *w)
{
if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE))
if (!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE))
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != WC_TRACK_DESIGN_PLACE)
window_close(w);
}

View File

@ -181,8 +181,8 @@ static void window_water_textinput(rct_window *w, int widgetIndex, char *text)
static void window_water_inputsize(rct_window *w)
{
((uint16*)TextInputDescriptionArgs)[0] = MINIMUM_TOOL_SIZE;
((uint16*)TextInputDescriptionArgs)[1] = MAXIMUM_TOOL_SIZE;
TextInputDescriptionArgs[0] = MINIMUM_TOOL_SIZE;
TextInputDescriptionArgs[1] = MAXIMUM_TOOL_SIZE;
window_text_input_open(w, WIDX_PREVIEW, 5128, 5129, STR_NONE, STR_NONE, 3);
}
@ -256,7 +256,7 @@ static void window_water_paint(rct_window *w, rct_drawpixelinfo *dpi)
*/
static int window_water_should_close()
{
if (!(RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & INPUT_FLAG_TOOL_ACTIVE))
if (!(gInputFlags & INPUT_FLAG_TOOL_ACTIVE))
return 1;
if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != WC_TOP_TOOLBAR)
return 1;

View File

@ -210,7 +210,7 @@ static money32 footpath_element_update(int x, int y, rct_map_element *mapElement
} else if (pathItemType != 0) {
if (
!(flags & GAME_COMMAND_FLAG_GHOST) &&
(mapElement->properties.path.additions & 0x0F) == pathItemType &&
footpath_element_get_path_scenery(mapElement) == pathItemType &&
!(mapElement->flags & MAP_ELEMENT_FLAG_BROKEN)
) {
if (flags & GAME_COMMAND_FLAG_4)
@ -249,14 +249,17 @@ static money32 footpath_element_update(int x, int y, rct_map_element *mapElement
if (flags & GAME_COMMAND_FLAG_4)
return MONEY32_UNDEFINED;
// Should place a ghost?
if (flags & GAME_COMMAND_FLAG_GHOST) {
if (mapElement->properties.path.additions & 0x0F) {
// Check if there is something on the path already
if (footpath_element_has_path_scenery(mapElement)) {
RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_NONE;
return MONEY32_UNDEFINED;
}
// There is nothing yet - check if we should place a ghost
if (flags & GAME_COMMAND_FLAG_APPLY)
mapElement->properties.path.additions |= 0x80;
footpath_scenery_set_is_ghost(mapElement, true);
}
if (!(flags & GAME_COMMAND_FLAG_APPLY))
@ -264,12 +267,12 @@ static money32 footpath_element_update(int x, int y, rct_map_element *mapElement
if (
(pathItemType != 0 && !(flags & GAME_COMMAND_FLAG_GHOST)) ||
(pathItemType == 0 && (mapElement->properties.path.additions & 0x80))
(pathItemType == 0 && footpath_element_path_scenery_is_ghost(mapElement))
) {
mapElement->properties.path.additions &= ~0x80;
footpath_scenery_set_is_ghost(mapElement, false);
}
mapElement->properties.path.additions = (mapElement->properties.path.additions & 0xF0) | pathItemType;
footpath_element_set_path_scenery(mapElement, pathItemType);
mapElement->flags &= ~MAP_ELEMENT_FLAG_BROKEN;
if (pathItemType != 0) {
rct_scenery_entry* scenery_entry = g_pathBitSceneryEntries[pathItemType - 1];
@ -292,7 +295,7 @@ static money32 footpath_element_update(int x, int y, rct_map_element *mapElement
mapElement->properties.path.type = (mapElement->properties.path.type & 0x0F) | (type << 4);
mapElement->type = (mapElement->type & 0xFE) | (type >> 7);
mapElement->properties.path.additions = (mapElement->properties.path.additions & 0xF0) | pathItemType;
footpath_element_set_path_scenery(mapElement, pathItemType);
mapElement->flags &= ~MAP_ELEMENT_FLAG_BROKEN;
loc_6A6620(flags, x, y, mapElement);
@ -1579,7 +1582,7 @@ bool footpath_element_is_sloped(rct_map_element *mapElement)
return mapElement->properties.path.type & 4;
}
int footpath_element_get_slope_direction(rct_map_element *mapElement)
uint8 footpath_element_get_slope_direction(rct_map_element *mapElement)
{
return mapElement->properties.path.type & 3;
}
@ -1594,6 +1597,45 @@ bool footpath_element_is_wide(rct_map_element *mapElement)
return mapElement->type & 2;
}
bool footpath_element_has_path_scenery(rct_map_element *mapElement)
{
return (mapElement->properties.path.additions & 0xF) > 0;
}
uint8 footpath_element_get_path_scenery(rct_map_element *mapElement)
{
return mapElement->properties.path.additions & 0xF;
}
void footpath_element_set_path_scenery(rct_map_element *mapElement, uint8 pathSceneryType)
{
mapElement->properties.path.additions = (mapElement->properties.path.additions & 0xF0) | pathSceneryType;
}
uint8 footpath_element_get_path_scenery_index(rct_map_element *mapElement)
{
return footpath_element_get_path_scenery(mapElement) - 1;
}
bool footpath_element_path_scenery_is_ghost(rct_map_element *mapElement)
{
return (mapElement->properties.path.additions & 0x80) == 0x80;
}
void footpath_scenery_set_is_ghost(rct_map_element *mapElement, bool isGhost)
{
// Remove ghost flag
mapElement->properties.path.additions &= ~0x80;
// Set flag if it should be a ghost
if (isGhost)
mapElement->properties.path.additions |= 0x80;
}
uint8 footpath_element_get_type(rct_map_element *mapElement)
{
return mapElement->properties.path.type >> 4;
}
/**
*
* rct2: 0x006A8B12

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